fix(core): use relative paths in instruction load description
This commit is contained in:
parent
d972aa9d83
commit
6380919fda
2 changed files with 18 additions and 5 deletions
|
|
@ -1,9 +1,11 @@
|
||||||
export * as SessionInstructions from "./instructions"
|
export * as SessionInstructions from "./instructions"
|
||||||
|
|
||||||
|
import { relative } from "path"
|
||||||
import { Context, DateTime, Effect, Layer, Option, Ref, Schema } from "effect"
|
import { Context, DateTime, Effect, Layer, Option, Ref, Schema } from "effect"
|
||||||
import { makeLocationNode } from "../effect/app-node"
|
import { makeLocationNode } from "../effect/app-node"
|
||||||
import { EventV2 } from "../event"
|
import { EventV2 } from "../event"
|
||||||
import { FSUtil } from "../fs-util"
|
import { FSUtil } from "../fs-util"
|
||||||
|
import { Location } from "../location"
|
||||||
import { SessionEvent } from "./event"
|
import { SessionEvent } from "./event"
|
||||||
import { MessageDecodeError } from "./error"
|
import { MessageDecodeError } from "./error"
|
||||||
import { SessionMessage } from "./message"
|
import { SessionMessage } from "./message"
|
||||||
|
|
@ -29,6 +31,10 @@ const layer = Layer.effect(
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
const fs = yield* FSUtil.Service
|
const fs = yield* FSUtil.Service
|
||||||
const store = yield* SessionStore.Service
|
const store = yield* SessionStore.Service
|
||||||
|
const location = yield* Location.Service
|
||||||
|
// Resolved once for the Location layer; the synthetic text and dedup ledger keep
|
||||||
|
// absolute paths, but the human-facing description shows paths relative to this root.
|
||||||
|
const root = FSUtil.resolve(location.directory)
|
||||||
// Same-turn parallel reads settle concurrently, so an in-memory claim guards each
|
// Same-turn parallel reads settle concurrently, so an in-memory claim guards each
|
||||||
// Session/path pair before any filesystem work. The durable history check below covers
|
// Session/path pair before any filesystem work. The durable history check below covers
|
||||||
// paths injected in earlier turns after this Location layer was reopened.
|
// paths injected in earlier turns after this Location layer was reopened.
|
||||||
|
|
@ -70,7 +76,7 @@ const layer = Layer.effect(
|
||||||
messageID: SessionMessage.ID.create(),
|
messageID: SessionMessage.ID.create(),
|
||||||
timestamp: yield* DateTime.now,
|
timestamp: yield* DateTime.now,
|
||||||
text: readable.map((file) => `Instructions from: ${file.path}\n${file.content}`).join("\n\n"),
|
text: readable.map((file) => `Instructions from: ${file.path}\n${file.content}`).join("\n\n"),
|
||||||
description: `Loaded ${readable.map((file) => file.path).join(", ")}`,
|
description: `Loaded ${readable.map((file) => describePath(root, file.path)).join(", ")}`,
|
||||||
metadata: { instruction: { paths: readable.map((file) => file.path) } },
|
metadata: { instruction: { paths: readable.map((file) => file.path) } },
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
@ -94,8 +100,15 @@ function previouslyInjected(store: SessionStore.Interface, sessionID: SessionSch
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Paths are normally discovered under the Location root, so the description shows them
|
||||||
|
// relative to it. A directly-loaded path outside the root falls back to its absolute form
|
||||||
|
// rather than emitting `../..` chains.
|
||||||
|
function describePath(root: string, path: string) {
|
||||||
|
return FSUtil.contains(root, path) ? relative(root, path) : path
|
||||||
|
}
|
||||||
|
|
||||||
export const node = makeLocationNode({
|
export const node = makeLocationNode({
|
||||||
name: "session-instructions",
|
name: "session-instructions",
|
||||||
layer,
|
layer,
|
||||||
deps: [EventV2.node, FSUtil.node, SessionStore.node],
|
deps: [EventV2.node, FSUtil.node, Location.node, SessionStore.node],
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,7 @@ describe("SessionInstructions", () => {
|
||||||
expect(firstInjected[0]!.text).toBe(
|
expect(firstInjected[0]!.text).toBe(
|
||||||
`Instructions from: ${deepPath}\ndeep-instructions\n\nInstructions from: ${subPath}\nsub-instructions`,
|
`Instructions from: ${deepPath}\ndeep-instructions\n\nInstructions from: ${subPath}\nsub-instructions`,
|
||||||
)
|
)
|
||||||
expect(firstInjected[0]!.description).toBe(`Loaded ${deepPath}, ${subPath}`)
|
expect(firstInjected[0]!.description).toBe(`Loaded ${path.relative(dir, deepPath)}, ${path.relative(dir, subPath)}`)
|
||||||
// The synthetic's metadata carries the durable dedup ledger.
|
// The synthetic's metadata carries the durable dedup ledger.
|
||||||
expect(firstInjected[0]!.metadata).toEqual({ instruction: { paths: [deepPath, subPath] } })
|
expect(firstInjected[0]!.metadata).toEqual({ instruction: { paths: [deepPath, subPath] } })
|
||||||
expect(firstInjected[0]!.text).not.toContain("root-instructions")
|
expect(firstInjected[0]!.text).not.toContain("root-instructions")
|
||||||
|
|
@ -168,7 +168,7 @@ describe("SessionInstructions", () => {
|
||||||
const secondInjected = yield* synthetics(sessionID)
|
const secondInjected = yield* synthetics(sessionID)
|
||||||
expect(secondInjected).toHaveLength(2)
|
expect(secondInjected).toHaveLength(2)
|
||||||
expect(secondInjected[1]!.text).toBe(`Instructions from: ${otherPath}\nother-instructions`)
|
expect(secondInjected[1]!.text).toBe(`Instructions from: ${otherPath}\nother-instructions`)
|
||||||
expect(secondInjected[1]!.description).toBe(`Loaded ${otherPath}`)
|
expect(secondInjected[1]!.description).toBe(`Loaded ${path.relative(dir, otherPath)}`)
|
||||||
expect(secondInjected[1]!.metadata).toEqual({ instruction: { paths: [otherPath] } })
|
expect(secondInjected[1]!.metadata).toEqual({ instruction: { paths: [otherPath] } })
|
||||||
expect(secondInjected.some((message) => message.text.includes("root-instructions"))).toBe(false)
|
expect(secondInjected.some((message) => message.text.includes("root-instructions"))).toBe(false)
|
||||||
}),
|
}),
|
||||||
|
|
@ -218,7 +218,7 @@ describe("SessionInstructions", () => {
|
||||||
const injected = yield* synthetics(sessionID)
|
const injected = yield* synthetics(sessionID)
|
||||||
expect(injected).toHaveLength(1)
|
expect(injected).toHaveLength(1)
|
||||||
expect(injected[0]!.text).toBe(`Instructions from: ${subPath}\nsub-instructions`)
|
expect(injected[0]!.text).toBe(`Instructions from: ${subPath}\nsub-instructions`)
|
||||||
expect(injected[0]!.description).toBe(`Loaded ${subPath}`)
|
expect(injected[0]!.description).toBe(`Loaded ${path.relative(dir, subPath)}`)
|
||||||
expect(injected[0]!.metadata).toEqual({ instruction: { paths: [subPath] } })
|
expect(injected[0]!.metadata).toEqual({ instruction: { paths: [subPath] } })
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue