fix(tui): hide initial instruction sync (#36891)

Co-authored-by: Kit Langton <kit.langton@gmail.com>
This commit is contained in:
opencode-agent[bot] 2026-07-14 12:42:09 -04:00 committed by GitHub
commit cd9be63484
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 50 additions and 4 deletions

View file

@ -30,6 +30,8 @@ export const prepare = Effect.fn("InstructionState.prepare")(function* (
SessionEvent.InstructionsUpdated,
{ sessionID, delta: admission.delta },
{
// Initial sync establishes the baseline; unlike later deltas it is not chronological history.
...(!stored ? { metadata: { instructions: { initial: true } } } : {}),
commit: () => insertBlobs(db, admission.blobs),
},
)

View file

@ -943,6 +943,30 @@ describe("SessionRunnerLLM", () => {
}),
)
it.effect("marks the initial instruction sync as baseline metadata", () =>
Effect.gen(function* () {
const session = yield* setup
const events = yield* EventV2.Service
const instructionEvents: EventV2.Payload[] = []
const unsubscribe = yield* events.listen((event) =>
Effect.sync(() => {
if (event.type === "session.instructions.updated") instructionEvents.push(event)
}),
)
yield* admit(session, "First")
yield* session.resume(sessionID)
systemBaseline = "Changed context"
yield* admit(session, "Second")
yield* session.resume(sessionID)
yield* unsubscribe
expect(instructionEvents).toHaveLength(2)
expect(instructionEvents[0]?.metadata).toEqual({ instructions: { initial: true } })
expect(instructionEvents[1]?.metadata).toBeUndefined()
}),
)
it.effect("retries the first request after system context becomes available", () =>
Effect.gen(function* () {
const session = yield* setup

View file

@ -404,6 +404,14 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
})
break
case "session.instructions.updated":
const instructions = event.metadata?.instructions
if (
typeof instructions === "object" &&
instructions !== null &&
"initial" in instructions &&
instructions.initial === true
)
break
message.update(event.data.sessionID, (draft, index) => {
message.append(draft, index, {
id: messageIDFromEvent(event.id),

View file

@ -2385,7 +2385,7 @@ test("renders admitted prompts immediately and tracks them until promoted", asyn
}
})
test("projects live instruction updates with their message ID", async () => {
test("skips initial instruction state and projects later updates with their message ID", async () => {
const events = createEventStream()
const calls = createFetch(undefined, events)
let sync!: ReturnType<typeof useData>
@ -2419,18 +2419,30 @@ test("projects live instruction updates with their message ID", async () => {
created: 0,
type: "session.instructions.updated",
durable: durable("session-1", 0, 2),
metadata: { instructions: { initial: true } },
data: {
sessionID: "session-1",
delta: { "core/date": "0".repeat(64) },
},
})
emitEvent(events, {
id: "evt_instructions_2",
created: 1,
type: "session.instructions.updated",
durable: durable("session-1", 1, 2),
data: {
sessionID: "session-1",
delta: { "core/date": "1".repeat(64) },
},
})
await wait(() => sync.session.message.list("session-1")?.length === 1)
await wait(() => sync.session.message.list("session-1")?.some((message) => message.time.created === 1))
expect(sync.session.message.list("session-1")).toHaveLength(1)
expect(sync.session.message.list("session-1")?.[0]).toMatchObject({
id: SessionMessage.ID.fromEvent(EventV2.ID.make("evt_instructions_1")),
id: SessionMessage.ID.fromEvent(EventV2.ID.make("evt_instructions_2")),
type: "system",
text: "Instructions updated: core/date",
time: { created: 0 },
time: { created: 1 },
})
} finally {
app.renderer.destroy()