Просмотр исходного кода

feat(core): include session ID in instructions

Dax Raad 1 месяц назад
Родитель
Сommit
ce636daf04

+ 40 - 32
packages/core/src/instructions/builtins.ts

@@ -3,10 +3,11 @@ export * as InstructionBuiltIns from "./builtins"
 import { makeLocationNode } from "../effect/app-node"
 import { Context, DateTime, Effect, Layer, Schema } from "effect"
 import { Location } from "../location"
+import { SessionSchema } from "../session/schema"
 import { Instructions } from "./index"
 
 export interface Interface {
-  readonly load: () => Effect.Effect<Instructions.Instructions>
+  readonly load: (sessionID: SessionSchema.ID) => Effect.Effect<Instructions.Instructions>
 }
 
 export class Service extends Context.Service<Service, Interface>()("@opencode/v2/InstructionBuiltIns") {}
@@ -15,38 +16,45 @@ const layer = Layer.effect(
   Service,
   Effect.gen(function* () {
     const location = yield* Location.Service
-    const instructions = Instructions.combine([
-      Instructions.make({
-        key: Instructions.Key.make("core/environment"),
-        codec: Schema.toCodecJson(Schema.String),
-        read: Effect.sync(() =>
-          [
-            "<env>",
-            `  Working directory: ${location.directory}`,
-            `  Workspace root folder: ${location.project.directory}`,
-            `  Is directory a git repo: ${location.vcs?.type === "git" ? "yes" : "no"}`,
-            `  Platform: ${process.platform}`,
-            "</env>",
-          ].join("\n"),
+    return Service.of({
+      load: (sessionID) =>
+        Effect.succeed(
+          Instructions.combine([
+            Instructions.make({
+              key: Instructions.Key.make("core/environment"),
+              codec: Schema.toCodecJson(Schema.String),
+              read: Effect.sync(() =>
+                [
+                  "<env>",
+                  `  Session ID: ${sessionID}`,
+                  `  Working directory: ${location.directory}`,
+                  `  Workspace root folder: ${location.project.directory}`,
+                  `  Is directory a git repo: ${location.vcs?.type === "git" ? "yes" : "no"}`,
+                  `  Platform: ${process.platform}`,
+                  "</env>",
+                ].join("\n"),
+              ),
+              render: {
+                initial: (environment) =>
+                  ["Here is some useful information about the environment you are running in:", environment].join(
+                    "\n",
+                  ),
+                changed: (_previous, environment) =>
+                  ["The environment you are running in is now:", environment].join("\n"),
+              },
+            }),
+            Instructions.make({
+              key: Instructions.Key.make("core/date"),
+              codec: Schema.toCodecJson(Schema.String),
+              read: DateTime.nowAsDate.pipe(Effect.map((date) => date.toDateString())),
+              render: {
+                initial: (date) => `Today's date: ${date}`,
+                changed: (_previous, date) => `Today's date is now: ${date}`,
+              },
+            }),
+          ]),
         ),
-        render: {
-          initial: (environment) =>
-            ["Here is some useful information about the environment you are running in:", environment].join("\n"),
-          changed: (_previous, environment) => ["The environment you are running in is now:", environment].join("\n"),
-        },
-      }),
-      Instructions.make({
-        key: Instructions.Key.make("core/date"),
-        codec: Schema.toCodecJson(Schema.String),
-        read: DateTime.nowAsDate.pipe(Effect.map((date) => date.toDateString())),
-        render: {
-          initial: (date) => `Today's date: ${date}`,
-          changed: (_previous, date) => `Today's date is now: ${date}`,
-        },
-      }),
-    ])
-
-    return Service.of({ load: () => Effect.succeed(instructions) })
+    })
   }),
 )
 

+ 1 - 1
packages/core/src/session/runner/llm.ts

@@ -145,7 +145,7 @@ const layer = Layer.effect(
     const loadInstructions = (agent: AgentV2.Selection, sessionID: SessionSchema.ID) =>
       Effect.all(
         [
-          builtins.load(),
+          builtins.load(sessionID),
           discovery.load(),
           skillGuidance.load(agent),
           referenceGuidance.load(),

+ 8 - 5
packages/core/test/instructions/builtins.test.ts

@@ -7,6 +7,7 @@ import { FSUtil } from "@opencode-ai/core/fs-util"
 import { Global } from "@opencode-ai/core/global"
 import { AbsolutePath } from "@opencode-ai/core/schema"
 import { InstructionBuiltIns } from "@opencode-ai/core/instructions/builtins"
+import { SessionSchema } from "@opencode-ai/core/session/schema"
 import { location } from "../fixture/location"
 import { testEffect } from "../lib/effect"
 import { readInitial, readUpdate } from "../lib/instructions"
@@ -14,6 +15,7 @@ import { readInitial, readUpdate } from "../lib/instructions"
 const directory = AbsolutePath.make(FSUtil.resolve("/repo/packages/core"))
 const projectDirectory = AbsolutePath.make(FSUtil.resolve("/repo"))
 const timestamp = Date.parse("2026-06-03T12:00:00.000Z")
+const sessionID = SessionSchema.ID.make("ses_builtin_test")
 const localDate = (time: number) => new Date(time).toDateString()
 const locationLayer = Layer.succeed(
   Location.Service,
@@ -36,12 +38,13 @@ describe("InstructionBuiltIns", () => {
     Effect.gen(function* () {
       yield* TestClock.setTime(timestamp)
       const context = yield* InstructionBuiltIns.Service
-      const initialized = yield* readInitial(yield* context.load())
+      const initialized = yield* readInitial(yield* context.load(sessionID))
 
       expect(initialized.text).toBe(
         [
           "Here is some useful information about the environment you are running in:",
           "<env>",
+          `  Session ID: ${sessionID}`,
           `  Working directory: ${directory}`,
           `  Workspace root folder: ${projectDirectory}`,
           "  Is directory a git repo: yes",
@@ -58,10 +61,10 @@ describe("InstructionBuiltIns", () => {
     Effect.gen(function* () {
       yield* TestClock.setTime(timestamp)
       const context = yield* InstructionBuiltIns.Service
-      const initialized = yield* readInitial(yield* context.load())
+      const initialized = yield* readInitial(yield* context.load(sessionID))
 
       yield* TestClock.setTime(timestamp + 24 * 60 * 60 * 1000)
-      const refreshed = yield* readUpdate(yield* context.load(), initialized)
+      const refreshed = yield* readUpdate(yield* context.load(sessionID), initialized)
 
       expect(refreshed.text).toBe(`Today's date is now: ${localDate(timestamp + 24 * 60 * 60 * 1000)}`)
     }),
@@ -71,10 +74,10 @@ describe("InstructionBuiltIns", () => {
     Effect.gen(function* () {
       yield* TestClock.setTime(timestamp)
       const context = yield* InstructionBuiltIns.Service
-      const initialized = yield* readInitial(yield* context.load())
+      const initialized = yield* readInitial(yield* context.load(sessionID))
 
       yield* TestClock.setTime(timestamp + 60 * 60 * 1000)
-      expect((yield* readUpdate(yield* context.load(), initialized)).changed).toBe(false)
+      expect((yield* readUpdate(yield* context.load(sessionID), initialized)).changed).toBe(false)
     }),
   )
 })