refactor(core): simplify session runner loop and pending input scopes (#38602)
This commit is contained in:
parent
35d31d8ec1
commit
0f3c30118c
8 changed files with 283 additions and 242 deletions
|
|
@ -195,9 +195,9 @@ describe("SessionV2.create", () => {
|
|||
text: "First",
|
||||
resume: false,
|
||||
})
|
||||
yield* SessionPending.promoteSteers(db, events, parent.id)
|
||||
yield* SessionPending.promote(db, events, parent.id, "steer")
|
||||
yield* session.synthetic({ sessionID: parent.id, text: "parent note", resume: false })
|
||||
yield* SessionPending.promoteSteers(db, events, parent.id)
|
||||
yield* SessionPending.promote(db, events, parent.id, "steer")
|
||||
|
||||
const forked = yield* session.fork({ sessionID: parent.id })
|
||||
const parentContext = yield* session.context(parent.id)
|
||||
|
|
@ -232,13 +232,13 @@ describe("SessionV2.create", () => {
|
|||
text: "Parent changed",
|
||||
resume: false,
|
||||
})
|
||||
yield* SessionPending.promoteSteers(db, events, parent.id)
|
||||
yield* SessionPending.promote(db, events, parent.id, "steer")
|
||||
yield* session.prompt({
|
||||
sessionID: forked.id,
|
||||
text: "Child continues",
|
||||
resume: false,
|
||||
})
|
||||
yield* SessionPending.promoteSteers(db, events, forked.id)
|
||||
yield* SessionPending.promote(db, events, forked.id, "steer")
|
||||
|
||||
expect((yield* session.context(parent.id)).map((message) => message.type)).toEqual(["user", "synthetic", "user"])
|
||||
expect((yield* session.context(forked.id)).map((message) => message.type)).toEqual(["user", "synthetic", "user"])
|
||||
|
|
@ -263,13 +263,13 @@ describe("SessionV2.create", () => {
|
|||
text: "First",
|
||||
resume: false,
|
||||
})
|
||||
yield* SessionPending.promoteSteers(db, events, parent.id)
|
||||
yield* SessionPending.promote(db, events, parent.id, "steer")
|
||||
const second = yield* session.prompt({
|
||||
sessionID: parent.id,
|
||||
text: "Second",
|
||||
resume: false,
|
||||
})
|
||||
yield* SessionPending.promoteSteers(db, events, parent.id)
|
||||
yield* SessionPending.promote(db, events, parent.id, "steer")
|
||||
const assistantMessageID = SessionMessage.ID.create()
|
||||
const model = ModelV2.Ref.make({ id: ModelV2.ID.make("model"), providerID: ProviderV2.ID.make("provider") })
|
||||
yield* events.publish(SessionEvent.Step.Started, {
|
||||
|
|
@ -414,7 +414,7 @@ describe("SessionV2.create", () => {
|
|||
text: "Hello",
|
||||
resume: false,
|
||||
})
|
||||
yield* SessionPending.promoteSteers(db, events, created.id)
|
||||
yield* SessionPending.promote(db, events, created.id, "steer")
|
||||
|
||||
expect(
|
||||
Array.from(yield* logEvents(session, created.id, true).pipe(Stream.take(2), Stream.runCollect)),
|
||||
|
|
@ -440,7 +440,7 @@ describe("SessionV2.create", () => {
|
|||
text: "Replay lifecycle",
|
||||
resume: false,
|
||||
})
|
||||
yield* SessionPending.promoteSteers(sourceDb, sourceEvents, created.id)
|
||||
yield* SessionPending.promote(sourceDb, sourceEvents, created.id, "steer")
|
||||
const serialized = (yield* sourceDb
|
||||
.select()
|
||||
.from(EventTable)
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ describe("SessionV2.prompt", () => {
|
|||
text: "boundary",
|
||||
resume: false,
|
||||
})
|
||||
yield* SessionPending.promoteSteers(db, events, sessionID)
|
||||
yield* SessionPending.promote(db, events, sessionID, "steer")
|
||||
const stale = SessionMessage.ID.make("msg_stale_assistant")
|
||||
yield* db.insert(SessionMessageTable).values(assistantRow(stale, 100)).run().pipe(Effect.orDie)
|
||||
yield* events.publish(SessionEvent.RevertEvent.Staged, {
|
||||
|
|
@ -248,7 +248,7 @@ describe("SessionV2.prompt", () => {
|
|||
text: "boundary",
|
||||
resume: false,
|
||||
})
|
||||
yield* SessionPending.promoteSteers(db, events, sessionID)
|
||||
yield* SessionPending.promote(db, events, sessionID, "steer")
|
||||
yield* events.publish(SessionEvent.RevertEvent.Staged, {
|
||||
sessionID,
|
||||
revert: { messageID: boundary.id, files: [] },
|
||||
|
|
@ -448,7 +448,7 @@ describe("SessionV2.prompt", () => {
|
|||
|
||||
yield* session.prompt({ sessionID, text: "First", resume: false })
|
||||
yield* session.prompt({ sessionID, text: "Second", resume: false })
|
||||
yield* SessionPending.promoteSteers(db, events, sessionID)
|
||||
yield* SessionPending.promote(db, events, sessionID, "steer")
|
||||
const streamed = Array.from(yield* Fiber.join(fiber))
|
||||
|
||||
expect(streamed.map((event): [number | undefined, string] => [event.durable?.seq, event.type])).toEqual([
|
||||
|
|
@ -625,7 +625,7 @@ describe("SessionV2.prompt", () => {
|
|||
})
|
||||
|
||||
yield* Effect.all(
|
||||
[SessionPending.promoteSteers(db, events, sessionID), SessionPending.promoteSteers(db, events, sessionID)],
|
||||
[SessionPending.promote(db, events, sessionID, "steer"), SessionPending.promote(db, events, sessionID, "steer")],
|
||||
{ concurrency: "unbounded" },
|
||||
)
|
||||
|
||||
|
|
@ -855,7 +855,7 @@ describe("SessionV2.prompt", () => {
|
|||
},
|
||||
})
|
||||
|
||||
yield* SessionPending.promoteSteers(db, events, sessionID)
|
||||
yield* SessionPending.promote(db, events, sessionID, "steer")
|
||||
|
||||
expect(yield* session.messages({ sessionID })).toMatchObject([
|
||||
{
|
||||
|
|
@ -880,7 +880,7 @@ describe("SessionV2.prompt", () => {
|
|||
const entries = yield* Effect.all([session.synthetic(input), session.synthetic(input)], {
|
||||
concurrency: "unbounded",
|
||||
})
|
||||
yield* SessionPending.promoteSteers(database.db, events, sessionID)
|
||||
yield* SessionPending.promote(database.db, events, sessionID, "steer")
|
||||
const promotedRetry = yield* session.synthetic(input)
|
||||
const failure = yield* session.synthetic({ ...input, text: "Different completion" }).pipe(Effect.flip)
|
||||
|
||||
|
|
@ -892,7 +892,7 @@ describe("SessionV2.prompt", () => {
|
|||
}),
|
||||
)
|
||||
|
||||
it.effect("keeps synthetic queue input pending until the queue boundary", () =>
|
||||
it.effect("keeps queued input pending until the idle boundary", () =>
|
||||
Effect.gen(function* () {
|
||||
yield* setup
|
||||
const session = yield* SessionV2.Service
|
||||
|
|
@ -907,9 +907,15 @@ describe("SessionV2.prompt", () => {
|
|||
})
|
||||
|
||||
expect(input.delivery).toBe("queue")
|
||||
expect(yield* SessionPending.promoteSteers(db, events, sessionID)).toBe(0)
|
||||
expect(yield* SessionPending.has(db, sessionID, "input")).toBe(true)
|
||||
expect(
|
||||
yield* SessionPending.promote(db, events, sessionID, "steer"),
|
||||
).toBe(0)
|
||||
expect(yield* session.messages({ sessionID })).toEqual([])
|
||||
expect(yield* SessionPending.promoteNextQueued(db, events, sessionID)).toBe(true)
|
||||
expect(
|
||||
yield* SessionPending.promote(db, events, sessionID, "input"),
|
||||
).toBe(1)
|
||||
expect(yield* SessionPending.has(db, sessionID, "input")).toBe(false)
|
||||
expect(yield* session.messages({ sessionID })).toMatchObject([
|
||||
{ id: input.id, type: "synthetic", text: "Queued completion" },
|
||||
])
|
||||
|
|
@ -935,7 +941,7 @@ describe("SessionV2.prompt", () => {
|
|||
resume: false,
|
||||
})
|
||||
|
||||
yield* SessionPending.promoteSteers(db, events, sessionID)
|
||||
yield* SessionPending.promote(db, events, sessionID, "steer")
|
||||
|
||||
expect(
|
||||
(yield* session.messages({ sessionID, order: "asc" })).map((message) =>
|
||||
|
|
@ -978,10 +984,14 @@ describe("SessionV2.pending", () => {
|
|||
{ id: second.id, type: "user", delivery: "steer" },
|
||||
])
|
||||
|
||||
yield* SessionPending.promoteSteers(db, events, sessionID)
|
||||
expect(
|
||||
yield* SessionPending.promote(db, events, sessionID, "input"),
|
||||
).toBe(2)
|
||||
expect(yield* session.pending(sessionID)).toMatchObject([{ id: queued.id, type: "synthetic" }])
|
||||
|
||||
yield* SessionPending.promoteNextQueued(db, events, sessionID)
|
||||
expect(
|
||||
yield* SessionPending.promote(db, events, sessionID, "input"),
|
||||
).toBe(1)
|
||||
expect(yield* session.pending(sessionID)).toEqual([])
|
||||
}),
|
||||
)
|
||||
|
|
@ -993,9 +1003,12 @@ describe("SessionV2.pending", () => {
|
|||
const { db } = yield* Database.Service
|
||||
|
||||
const barrier = yield* session.compact({ sessionID })
|
||||
expect(yield* SessionPending.has(db, sessionID, "any")).toBe(true)
|
||||
expect(yield* SessionPending.has(db, sessionID, "input")).toBe(false)
|
||||
expect(yield* session.pending(sessionID)).toMatchObject([{ id: barrier.id, type: "compaction" }])
|
||||
|
||||
yield* SessionPending.settleCompaction(db, { sessionID })
|
||||
expect(yield* SessionPending.has(db, sessionID, "any")).toBe(false)
|
||||
expect(yield* session.pending(sessionID)).toEqual([])
|
||||
}),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3099,7 +3099,7 @@ describe("SessionRunnerLLM", () => {
|
|||
streamFailure = undefined
|
||||
streamGate = undefined
|
||||
streamStarted = undefined
|
||||
yield* Effect.yieldNow
|
||||
yield* session.wait(sessionID)
|
||||
|
||||
expect(requests).toHaveLength(2)
|
||||
expect(userTexts(requests[1]!)).toEqual(["Start working", "Recover with this"])
|
||||
|
|
@ -3111,7 +3111,7 @@ describe("SessionRunnerLLM", () => {
|
|||
const session = yield* setup
|
||||
const events = yield* EventV2.Service
|
||||
yield* admit(session, "Recover interrupted tool")
|
||||
yield* SessionPending.promoteSteers((yield* Database.Service).db, events, sessionID)
|
||||
yield* SessionPending.promote((yield* Database.Service).db, events, sessionID, "steer")
|
||||
const assistantMessageID = SessionMessage.ID.create()
|
||||
yield* events.publish(SessionEvent.Step.Started, {
|
||||
sessionID,
|
||||
|
|
@ -3168,7 +3168,7 @@ describe("SessionRunnerLLM", () => {
|
|||
const session = yield* setup
|
||||
const events = yield* EventV2.Service
|
||||
yield* admit(session, "Recover interrupted hosted tool")
|
||||
yield* SessionPending.promoteSteers((yield* Database.Service).db, events, sessionID)
|
||||
yield* SessionPending.promote((yield* Database.Service).db, events, sessionID, "steer")
|
||||
const assistantMessageID = SessionMessage.ID.create()
|
||||
yield* events.publish(SessionEvent.Step.Started, {
|
||||
sessionID,
|
||||
|
|
@ -3219,7 +3219,7 @@ describe("SessionRunnerLLM", () => {
|
|||
const session = yield* setup
|
||||
const events = yield* EventV2.Service
|
||||
yield* admit(session, "Recover interrupted tool input")
|
||||
yield* SessionPending.promoteSteers((yield* Database.Service).db, events, sessionID)
|
||||
yield* SessionPending.promote((yield* Database.Service).db, events, sessionID, "steer")
|
||||
const assistantMessageID = SessionMessage.ID.create()
|
||||
yield* events.publish(SessionEvent.Step.Started, {
|
||||
sessionID,
|
||||
|
|
@ -4220,7 +4220,7 @@ describe("SessionRunnerLLM", () => {
|
|||
}),
|
||||
)
|
||||
|
||||
it.effect("retries a physical attempt without consuming the logical agent step", () =>
|
||||
it.effect("retries a model call without consuming the logical agent step", () =>
|
||||
Effect.gen(function* () {
|
||||
const session = yield* setup
|
||||
const agents = yield* AgentV2.Service
|
||||
|
|
|
|||
|
|
@ -406,7 +406,7 @@ describe("SubagentTool", () => {
|
|||
},
|
||||
})
|
||||
const database = yield* Database.Service
|
||||
yield* SessionPending.promoteSteers(database.db, events, parent.id)
|
||||
yield* SessionPending.promote(database.db, events, parent.id, "steer")
|
||||
const synthetic = (yield* sessions.context(parent.id)).filter((message) => message.type === "synthetic")
|
||||
expect(synthetic).toHaveLength(1)
|
||||
expect(synthetic[0]?.text).toContain(`<subagent id="${childID}" state="completed"`)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue