Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions opencode.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "https://opencode.ai/config.json",
"plugin": [
"opencode-session-start-plugin"
]
}
12 changes: 12 additions & 0 deletions packages/opencode-session-start-plugin/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "opencode-session-start-plugin",
"version": "1.0.0",
"type": "module",
"main": "src/index.ts",
"dependencies": {
"@opencode-ai/plugin": "workspace:*"
},
"devDependencies": {
"typescript": "^5.0.0"
}
}
36 changes: 36 additions & 0 deletions packages/opencode-session-start-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Plugin, tool } from "@opencode-ai/plugin"
import fs from "fs"
import path from "path"

export const SessionStartPlugin: Plugin = async (ctx) => {
return {
tool: {
testSessionStart: tool({
description: "Test the session.start hook - returns status",
args: {},
async execute() {
return "SessionStartPlugin loaded - check console for hook trigger"
},
}),
},
"session.start": async ({ sessionID, directory, projectID }, { context }) => {
console.log("🎯 session.start hook FIRED!")
console.log(" sessionID:", sessionID)
console.log(" directory:", directory)
console.log(" projectID:", projectID)

const testContext = `[TEST] This context was injected by the session.start hook!
Session ID: ${sessionID}
Working Directory: ${directory}
Project ID: ${projectID}
Timestamp: ${new Date().toISOString()}`

context.push(testContext)

console.log("✅ Context injected into system prompt")
console.log(" Context length:", context.join("\n").length, "chars")
},
}
}

export default SessionStartPlugin
21 changes: 20 additions & 1 deletion packages/opencode/src/session/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,26 @@ export namespace SessionPrompt {
await Plugin.trigger("experimental.chat.messages.transform", {}, { messages: msgs })

// Build system prompt, adding structured output instruction if needed
const system = [...(await SystemPrompt.environment(model)), ...(await InstructionPrompt.system())]
// First, check if this is the first message in the session for session.start hook
const existingMessages = await Session.messages({ sessionID })
const isFirstMessage = existingMessages.length <= 1 // Only the message just created

let sessionStartContext: string[] = []
if (isFirstMessage) {
await Plugin.trigger(
"session.start",
{ sessionID, directory: session.directory, projectID: session.projectID },
{ context: [] },
).then((result) => {
sessionStartContext = result.context
})
}

const system = [
...sessionStartContext,
...(await SystemPrompt.environment(model)),
...(await InstructionPrompt.system()),
]
const format = lastUser.format ?? { type: "text" }
if (format.type === "json_schema") {
system.push(STRUCTURED_OUTPUT_SYSTEM_PROMPT)
Expand Down
13 changes: 13 additions & 0 deletions packages/plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,19 @@ export interface Hooks {
[key: string]: ToolDefinition
}
auth?: AuthHook
/**
* Called when a new session starts, before the first message is processed.
* Plugins can inject context into the system prompt using this hook.
* The context strings are appended to the system prompt.
*/
"session.start"?: (
input: {
sessionID: string
directory: string
projectID: string
},
output: { context: string[] },
) => Promise<void>
/**
* Called when a new message is received
*/
Expand Down
46 changes: 46 additions & 0 deletions test-hook.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash
# Test script for session.start hook

echo "=============================================="
echo "Testing session.start Hook"
echo "=============================================="

# Check if bun is available
if ! command -v bun &> /dev/null; then
echo "❌ Bun not found. Please install Bun first:"
echo " curl -fsSL https://bun.sh/install | bash"
exit 1
fi

# Check if we're in the right directory
if [ ! -f "package.json" ]; then
echo "❌ Not in opencode directory"
echo " Run: cd ~/opencode-test"
exit 1
fi

echo "✅ Bun found"
echo "✅ In opencode directory"

# Install dependencies if needed
if [ ! -d "node_modules" ]; then
echo "📦 Installing dependencies..."
bun install
fi

echo ""
echo "=============================================="
echo "To test the session.start hook:"
echo "=============================================="
echo ""
echo "1. Run: bun run dev"
echo "2. OpenCode will start"
echo "3. Start a NEW session (not continue)"
echo "4. You'll see in the logs:"
echo " 🎯 session.start hook FIRED!"
echo " ✅ Context injected into system prompt"
echo ""
echo "Or run with a specific project:"
echo " bun run dev /path/to/your/project"
echo ""
echo "=============================================="
Loading