mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
feat(durable): nested tool calls, structured output, callers; storage errors end the Session
Nested tool calls: ToolExecutionApi.executeTool() runs another tool as its own pi.tool task owned by the caller, keyed for replay-safe reattachment. Results for programs live in the caller's NestedResultDoc until it settles; pi.live.nestedTools shows each call with the arguments it runs with and a summary. TaskOptions.abandonOnRestart aborts work its creator awaited only in memory before it runs again after a restart. Structured output: structuredOutputSchema and structuredOutput, validated; a tool without a schema gives programs its bounded output (one text as a string, one image as itself, else the list). ToolExecutionResult.content is now output. callers and modelTools decide who may call a tool. Storage errors: any error a Storage method throws fails the Session, which closes itself; later calls and waits reject with SessionFailed, watches end with session_failed, and Session.closed settles. Nothing retries in the Harness. StorageRejected is removed; StorageRequestError marks invalid reads that fail only their call. Listener and onReport errors are contained and reported. Also updates scripts/issues/triage.ts and the vacation experiment for the content -> output rename.
This commit is contained in:
parent
5a10492690
commit
eba8497395
70 changed files with 6137 additions and 671 deletions
|
|
@ -290,7 +290,7 @@ export class Triage {
|
|||
replay: "safe",
|
||||
execute: async (args, api) => {
|
||||
const hits = corpus.search(args.query, issueFor(api.conversationId));
|
||||
return { content: [{ type: "text", text: hits.length ? hits.map(line).join("\n") : "No matches." }] };
|
||||
return { output: [{ type: "text", text: hits.length ? hits.map(line).join("\n") : "No matches." }] };
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -301,9 +301,9 @@ export class Triage {
|
|||
replay: "safe",
|
||||
execute: async (args) => {
|
||||
const issue = corpus.get(args.number);
|
||||
if (!issue) return { content: [{ type: "text", text: `#${args.number} is not in the local corpus.` }] };
|
||||
if (!issue) return { output: [{ type: "text", text: `#${args.number} is not in the local corpus.` }] };
|
||||
const text = `#${issue.number} [${issueStatus(issue)}] ${issue.title}\nLabels: ${issue.labels.join(", ") || "none"}. Created ${issue.createdAt}.\n\n${issue.body.slice(0, 8000)}`;
|
||||
return { content: [{ type: "text", text }] };
|
||||
return { output: [{ type: "text", text }] };
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -329,7 +329,7 @@ export class Triage {
|
|||
replay: "safe",
|
||||
execute: async (args, api, callContext) => {
|
||||
const number = issueFor(api.conversationId);
|
||||
if (number < 0) return { content: [{ type: "text", text: "Unknown conversation." }], isError: true };
|
||||
if (number < 0) return { output: [{ type: "text", text: "Unknown conversation." }], isError: true };
|
||||
const result: TriageResult = {
|
||||
...args,
|
||||
duplicates: args.duplicates.filter((dup) => dup.number !== number).slice(0, 5),
|
||||
|
|
@ -344,7 +344,7 @@ export class Triage {
|
|||
}),
|
||||
callContext,
|
||||
);
|
||||
return { content: [{ type: "text", text: "Recorded." }], control: { terminate: true } };
|
||||
return { output: [{ type: "text", text: "Recorded." }], control: { terminate: true } };
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue