remove the need for polling from experimental background agents (#29179)

This commit is contained in:
Aiden Cline
2026-05-25 16:09:56 -05:00
committed by GitHub
parent 775321173d
commit dabf2dc013
11 changed files with 63 additions and 431 deletions

View File

@@ -92,7 +92,6 @@ function stubOps(opts?: { onPrompt?: (input: SessionPrompt.PromptInput) => void;
opts?.onPrompt?.(input)
return reply(input, opts?.text ?? "done")
}),
loop: (input) => Effect.succeed(reply({ sessionID: input.sessionID, parts: [] }, opts?.text ?? "done")),
}
}
@@ -237,7 +236,7 @@ describe("tool.task", () => {
expect(kids).toHaveLength(1)
expect(kids[0]?.id).toBe(child.id)
expect(result.metadata.sessionId).toBe(child.id)
expect(result.output).toContain(`task_id: ${child.id}`)
expect(result.output).toContain(`<task id="${child.id}" state="completed">`)
expect(seen?.sessionID).toBe(child.id)
}),
)
@@ -307,7 +306,6 @@ describe("tool.task", () => {
ready.resolve(input)
return cancelled.promise
}).pipe(Effect.as(reply(input, "cancelled"))),
loop: (input) => Effect.succeed(reply({ sessionID: input.sessionID, parts: [] }, "done")),
}
const fiber = yield* def
@@ -371,7 +369,7 @@ describe("tool.task", () => {
expect(kids).toHaveLength(1)
expect(kids[0]?.id).toBe(result.metadata.sessionId)
expect(result.metadata.sessionId).not.toBe("ses_missing")
expect(result.output).toContain(`task_id: ${result.metadata.sessionId}`)
expect(result.output).toContain(`<task id="${result.metadata.sessionId}" state="completed">`)
expect(seen?.sessionID).toBe(result.metadata.sessionId)
}),
)
@@ -511,7 +509,7 @@ describe("tool.task", () => {
const job = yield* jobs.get(result.metadata.sessionId)
expect(result.metadata.background).toBe(true)
expect(result.output).toContain("state: running")
expect(result.output).toContain(`state="running"`)
expect(job?.status).toBe("running")
}),
)
@@ -549,10 +547,9 @@ describe("tool.task", () => {
}),
)
background.instance("background task completion does not wait for the parent resume loop", () =>
background.instance("background task completion does not wait for the parent async prompt", () =>
Effect.gen(function* () {
const jobs = yield* BackgroundJob.Service
const sessions = yield* Session.Service
const { chat, assistant } = yield* seed()
const tool = yield* TaskTool
const def = yield* tool.init()
@@ -573,27 +570,7 @@ describe("tool.task", () => {
promptOps: {
...stubOps({ text: "background done" }),
prompt: (input) =>
input.noReply
? Effect.gen(function* () {
const user = yield* sessions.updateMessage({
id: input.messageID ?? MessageID.ascending(),
role: "user",
sessionID: input.sessionID,
agent: input.agent ?? "build",
model: input.model ?? ref,
time: { created: Date.now() },
})
const parts = input.parts.map((part) => ({
...part,
id: part.id ?? PartID.ascending(),
messageID: user.id,
sessionID: input.sessionID,
}))
yield* Effect.forEach(parts, (part) => sessions.updatePart(part), { discard: true })
return { info: user, parts }
})
: Effect.succeed(reply(input, "background done")),
loop: () => Effect.never,
input.sessionID === chat.id ? Effect.never : Effect.succeed(reply(input, "background done")),
} satisfies TaskPromptOps,
},
messages: [],