diff --git a/packages/triage-manager/src/actions/judge.ts b/packages/triage-manager/src/actions/judge.ts index 9e463f22b..9d2519df2 100644 --- a/packages/triage-manager/src/actions/judge.ts +++ b/packages/triage-manager/src/actions/judge.ts @@ -100,7 +100,7 @@ export async function deployJudge(input: unknown, ctx: EffectContext, _signal: A return { reviewer: { kind: "judge", head, runId: judgeRun, deployedBy: runId, deadline }, mail: { tenantId, to: judgeRun, content, readyBy: deadline } }; } -const MailedInput = type({ deployJudge: { output: { reviewer: Reviewer } }, mailJudge: { output: "string" } }); +const MailedInput = type({ deployJudge: { output: { reviewer: Reviewer } }, mailJudge: { output: { reply: "string" } } }); /** * The judge becomes a reviewer to wait for once its mail went. A mail that failed by its deadline leaves the pass to @@ -109,7 +109,7 @@ const MailedInput = type({ deployJudge: { output: { reviewer: Reviewer } }, mail export async function judgeMailed(input: unknown): Promise<{ reviewer?: Reviewer; post: boolean }> { const parsed = MailedInput(input); if (parsed instanceof type.errors) throw new Error(`judgeMailed: ${parsed.summary}`); - const mailed = Mailed(parsed.mailJudge.output); + const mailed = Mailed(parsed.mailJudge.output.reply); if (mailed instanceof type.errors) throw new Error(`judgeMailed: ${mailed.summary}`); return mailed.mailed ? { reviewer: parsed.deployJudge.output.reviewer, post: false } : { post: true }; } diff --git a/packages/triage-manager/src/actions/review.ts b/packages/triage-manager/src/actions/review.ts index d001a420e..d62837dfb 100644 --- a/packages/triage-manager/src/actions/review.ts +++ b/packages/triage-manager/src/actions/review.ts @@ -56,7 +56,7 @@ export async function deployReview(input: unknown, ctx: EffectContext, _signal: return { reviewer: { kind: "code-review", head, runId: reviewRun, deployedBy: runId, deadline }, mail: { tenantId, to: reviewRun, content, readyBy: deadline } }; } -const MailedInput = type({ deployReview: { output: { reviewer: Reviewer } }, mailReview: { output: "string" } }); +const MailedInput = type({ deployReview: { output: { reviewer: Reviewer } }, mailReview: { output: { reply: "string" } } }); /** * The review becomes a reviewer to wait for once its mail went. A mail that failed by its deadline leaves the pass to @@ -65,7 +65,7 @@ const MailedInput = type({ deployReview: { output: { reviewer: Reviewer } }, mai export async function reviewMailed(input: unknown): Promise<{ reviewer?: Reviewer; post: boolean }> { const parsed = MailedInput(input); if (parsed instanceof type.errors) throw new Error(`reviewMailed: ${parsed.summary}`); - const mailed = Mailed(parsed.mailReview.output); + const mailed = Mailed(parsed.mailReview.output.reply); if (mailed instanceof type.errors) throw new Error(`reviewMailed: ${mailed.summary}`); return mailed.mailed ? { reviewer: parsed.deployReview.output.reviewer, post: false } : { post: true }; } diff --git a/packages/triage-manager/src/triage-manager.test.ts b/packages/triage-manager/src/triage-manager.test.ts index 1e66d7f5f..85cdec06a 100644 --- a/packages/triage-manager/src/triage-manager.test.ts +++ b/packages/triage-manager/src/triage-manager.test.ts @@ -118,7 +118,10 @@ function actionCredentials(bindings: Bindings, host: Fetch, hub: (url: URL, init const loopFns = (ref: string) => (loops as Record)[ref]!; -/** Runs one mail's body; the mail agent's director runs its one tool, so the mail it would send is recorded and answered `mailed`. */ +/** + * Runs one mail's body; the mail agent's director runs its one tool, so the mail it would send is recorded and answered + * `mailed` in the `{ reply, turn }` a live agent step outputs. + */ async function runMail(definition: WorkflowDefinition, mail: unknown, host: Fetch, hub: ReturnType["hub"], mailed: unknown[] = [], delivers = true) { const body = (definition.steps.events as OnTriggerPrimitive).body; if (!("inline" in body)) throw new Error("the body is not inline"); @@ -128,7 +131,8 @@ async function runMail(definition: WorkflowDefinition, mail: unknown, host: Fetc invokeStep: async function mailAgent({ agent, input }) { if (!agent.id.startsWith("triage-mail")) throw new Error(`no agent but the mail agent runs, not ${agent.id}`); mailed.push(input); - return { output: JSON.stringify({ mailed: delivers }) }; + const reply = JSON.stringify({ mailed: delivers }); + return { output: { reply, turn: { role: "assistant", content: [{ type: "text", text: reply }] } } }; }, actionResolver: (ref) => (actions as Record)[ref]!, actionCredentials: actionCredentials((definition.credentialBindings ?? []) as Bindings, host, hub),