@yycholla/pi-dynamic-workflows 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +325 -0
- package/assets/readme/hero.png +0 -0
- package/assets/readme/hero.svg +70 -0
- package/assets/readme/package-cover.png +0 -0
- package/assets/readme/package-cover.svg +66 -0
- package/assets/readme/workflow.png +0 -0
- package/assets/readme/workflow.svg +77 -0
- package/dist/accept-workflow-guidance.d.ts +14 -0
- package/dist/accept-workflow-guidance.js +53 -0
- package/dist/adversarial-review.d.ts +30 -0
- package/dist/adversarial-review.js +107 -0
- package/dist/agent-history.d.ts +20 -0
- package/dist/agent-history.js +122 -0
- package/dist/agent-registry.d.ts +83 -0
- package/dist/agent-registry.js +190 -0
- package/dist/agent.d.ts +364 -0
- package/dist/agent.js +714 -0
- package/dist/builtin-commands.d.ts +19 -0
- package/dist/builtin-commands.js +251 -0
- package/dist/builtin-workflows.d.ts +45 -0
- package/dist/builtin-workflows.js +121 -0
- package/dist/code-review.d.ts +26 -0
- package/dist/code-review.js +181 -0
- package/dist/config.d.ts +37 -0
- package/dist/config.js +44 -0
- package/dist/deep-research.d.ts +30 -0
- package/dist/deep-research.js +124 -0
- package/dist/display.d.ts +134 -0
- package/dist/display.js +248 -0
- package/dist/effort-command.d.ts +28 -0
- package/dist/effort-command.js +68 -0
- package/dist/enums.d.ts +69 -0
- package/dist/enums.js +78 -0
- package/dist/errors.d.ts +113 -0
- package/dist/errors.js +140 -0
- package/dist/extension-reload.d.ts +37 -0
- package/dist/extension-reload.js +78 -0
- package/dist/fs-persistence.d.ts +63 -0
- package/dist/fs-persistence.js +102 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.js +35 -0
- package/dist/logger.d.ts +21 -0
- package/dist/logger.js +66 -0
- package/dist/model-routing.d.ts +30 -0
- package/dist/model-routing.js +50 -0
- package/dist/model-spec.d.ts +29 -0
- package/dist/model-spec.js +252 -0
- package/dist/model-tier-config.d.ts +133 -0
- package/dist/model-tier-config.js +249 -0
- package/dist/run-persistence.d.ts +180 -0
- package/dist/run-persistence.js +294 -0
- package/dist/saved-commands.d.ts +28 -0
- package/dist/saved-commands.js +100 -0
- package/dist/shared-store.d.ts +98 -0
- package/dist/shared-store.js +212 -0
- package/dist/structured-output.d.ts +19 -0
- package/dist/structured-output.js +30 -0
- package/dist/task-panel.d.ts +61 -0
- package/dist/task-panel.js +422 -0
- package/dist/usage-limit-scheduler.d.ts +145 -0
- package/dist/usage-limit-scheduler.js +368 -0
- package/dist/web-tools.d.ts +20 -0
- package/dist/web-tools.js +120 -0
- package/dist/workflow-authoring-coverage.d.ts +70 -0
- package/dist/workflow-authoring-coverage.js +421 -0
- package/dist/workflow-authoring-reference.d.ts +20 -0
- package/dist/workflow-authoring-reference.js +156 -0
- package/dist/workflow-capability-contract.d.ts +131 -0
- package/dist/workflow-capability-contract.js +604 -0
- package/dist/workflow-commands.d.ts +18 -0
- package/dist/workflow-commands.js +260 -0
- package/dist/workflow-comprehension.d.ts +133 -0
- package/dist/workflow-comprehension.js +1321 -0
- package/dist/workflow-context-measurement.d.ts +72 -0
- package/dist/workflow-context-measurement.js +213 -0
- package/dist/workflow-control-tool.d.ts +30 -0
- package/dist/workflow-control-tool.js +176 -0
- package/dist/workflow-delivery-choice.d.ts +20 -0
- package/dist/workflow-delivery-choice.js +48 -0
- package/dist/workflow-editor.d.ts +93 -0
- package/dist/workflow-editor.js +363 -0
- package/dist/workflow-manager.d.ts +492 -0
- package/dist/workflow-manager.js +1124 -0
- package/dist/workflow-paths.d.ts +22 -0
- package/dist/workflow-paths.js +46 -0
- package/dist/workflow-release-gate.d.ts +39 -0
- package/dist/workflow-release-gate.js +309 -0
- package/dist/workflow-saved.d.ts +38 -0
- package/dist/workflow-saved.js +126 -0
- package/dist/workflow-settings.d.ts +70 -0
- package/dist/workflow-settings.js +131 -0
- package/dist/workflow-tool.d.ts +71 -0
- package/dist/workflow-tool.js +367 -0
- package/dist/workflow-ui.d.ts +182 -0
- package/dist/workflow-ui.js +1587 -0
- package/dist/workflow.d.ts +333 -0
- package/dist/workflow.js +1151 -0
- package/dist/workflows-models-command.d.ts +31 -0
- package/dist/workflows-models-command.js +156 -0
- package/dist/worktree.d.ts +25 -0
- package/dist/worktree.js +61 -0
- package/extensions/workflow.ts +151 -0
- package/package.json +104 -0
- package/skills/workflow-authoring/SKILL.md +30 -0
- package/skills/workflow-authoring/examples/adversarial-verification.js +63 -0
- package/skills/workflow-authoring/examples/bounded-semantic-retry.js +56 -0
- package/skills/workflow-authoring/examples/classify-and-act.js +67 -0
- package/skills/workflow-authoring/examples/fan-out-and-synthesize.js +47 -0
- package/skills/workflow-authoring/examples/generate-and-filter.js +68 -0
- package/skills/workflow-authoring/examples/loop-until-done.js +68 -0
- package/skills/workflow-authoring/examples/phased-budgets.js +75 -0
- package/skills/workflow-authoring/examples/saved-nested-workflows.js +44 -0
- package/skills/workflow-authoring/examples/structured-output.js +37 -0
- package/skills/workflow-authoring/examples/tournament.js +81 -0
- package/skills/workflow-authoring/examples/validated-gate.js +63 -0
- package/skills/workflow-authoring/references/capabilities.md +41 -0
- package/skills/workflow-authoring/references/capability-details.md +357 -0
- package/skills/workflow-authoring/references/common-helpers.md +4 -0
- package/skills/workflow-authoring/references/debugging.md +27 -0
- package/skills/workflow-authoring/references/focused-recipes.md +11 -0
- package/skills/workflow-authoring/references/helpers.md +9 -0
- package/skills/workflow-authoring/references/lifecycle.md +33 -0
- package/skills/workflow-authoring/references/pattern-selection.md +15 -0
- package/skills/workflow-authoring/references/quality-helpers.md +8 -0
- package/skills/workflow-authoring/references/registry-ownership.md +15 -0
- package/skills/workflow-authoring/references/retry-helper.md +5 -0
- package/skills/workflow-authoring/references/review.md +43 -0
- package/skills/workflow-authoring/references/runtime.md +27 -0
- package/skills/workflow-authoring/references/specialized-helpers.md +19 -0
- package/skills/workflow-authoring/references/versions.md +13 -0
- package/skills/workflow-patterns/SKILL.md +51 -0
- package/src/accept-workflow-guidance.ts +71 -0
- package/src/adversarial-review.ts +120 -0
- package/src/agent-history.ts +157 -0
- package/src/agent-registry.ts +221 -0
- package/src/agent.ts +929 -0
- package/src/builtin-commands.ts +286 -0
- package/src/builtin-workflows.ts +155 -0
- package/src/code-review.ts +183 -0
- package/src/config.ts +55 -0
- package/src/deep-research.ts +135 -0
- package/src/display.ts +367 -0
- package/src/effort-command.ts +87 -0
- package/src/enums.ts +77 -0
- package/src/errors.ts +199 -0
- package/src/extension-reload.ts +100 -0
- package/src/fs-persistence.ts +124 -0
- package/src/index.ts +176 -0
- package/src/logger.ts +88 -0
- package/src/model-routing.ts +73 -0
- package/src/model-spec.ts +309 -0
- package/src/model-tier-config.ts +296 -0
- package/src/run-persistence.ts +484 -0
- package/src/saved-commands.ts +115 -0
- package/src/shared-store.ts +228 -0
- package/src/structured-output.ts +47 -0
- package/src/task-panel.ts +490 -0
- package/src/usage-limit-scheduler.ts +432 -0
- package/src/web-tools.ts +124 -0
- package/src/workflow-authoring-coverage.ts +486 -0
- package/src/workflow-authoring-reference.ts +186 -0
- package/src/workflow-capability-contract.ts +806 -0
- package/src/workflow-commands.ts +287 -0
- package/src/workflow-comprehension.ts +1673 -0
- package/src/workflow-context-measurement.ts +262 -0
- package/src/workflow-control-tool.ts +238 -0
- package/src/workflow-delivery-choice.ts +69 -0
- package/src/workflow-editor.ts +444 -0
- package/src/workflow-manager.ts +1405 -0
- package/src/workflow-paths.ts +63 -0
- package/src/workflow-release-gate.ts +529 -0
- package/src/workflow-saved.ts +180 -0
- package/src/workflow-settings.ts +194 -0
- package/src/workflow-tool.ts +464 -0
- package/src/workflow-ui.ts +1789 -0
- package/src/workflow.ts +1615 -0
- package/src/workflows-models-command.ts +211 -0
- package/src/worktree.ts +76 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory key-value store scoped to a single workflow run.
|
|
3
|
+
*
|
|
4
|
+
* One `SharedStore` instance is created at run start and disposed when the run
|
|
5
|
+
* ends. Two MCP-compatible tool definitions (`store_put` / `store_get`) are
|
|
6
|
+
* injected into every agent's tool list so parallel agents can share
|
|
7
|
+
* intermediate state without coordinating through the script itself.
|
|
8
|
+
*
|
|
9
|
+
* Journal integration: callers capture `store.commitDelta(deltaKey)` alongside
|
|
10
|
+
* each agent result in the journal. On resume, `store.applyDelta(delta)` rebuilds
|
|
11
|
+
* the store state additively in callSeq order, so parallel-agent writes are
|
|
12
|
+
* replayed correctly without the last-complete-wins ordering bug that a
|
|
13
|
+
* whole-Map restore() would cause.
|
|
14
|
+
*
|
|
15
|
+
* `deltaKey` must be unique across every run that shares this store instance,
|
|
16
|
+
* not just within one run's callSeq. A nested `workflow()` call restarts its own
|
|
17
|
+
* callSeq at 0 while inheriting the parent's store (so parent and nested-run
|
|
18
|
+
* agents can share state), so a bare callIndex would collide between a parent
|
|
19
|
+
* agent and a concurrently-running nested-run agent that both got index 0 —
|
|
20
|
+
* whichever commits its delta last would clobber the other's entry in
|
|
21
|
+
* `agentDeltas`. Callers compose `deltaKey` as `${runId}:${callIndex}`, and
|
|
22
|
+
* since every run (including each nested run) gets its own distinct `runId`,
|
|
23
|
+
* the composite key is unique across the whole store's lifetime.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { defineTool, type ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
27
|
+
import { Type } from "typebox";
|
|
28
|
+
|
|
29
|
+
export class SharedStore {
|
|
30
|
+
private readonly map = new Map<string, unknown>();
|
|
31
|
+
// Per-agent write deltas for delta-journaling; keyed by a run-unique
|
|
32
|
+
// `${runId}:${callIndex}` string (see class doc) so nested workflow() runs
|
|
33
|
+
// sharing this store can't collide on a bare callIndex.
|
|
34
|
+
private readonly agentDeltas = new Map<string, Record<string, unknown>>();
|
|
35
|
+
// Pre-write shadow values for the CURRENT delta-key's in-progress writes,
|
|
36
|
+
// so a failed retry attempt's mutations can be rolled back (see
|
|
37
|
+
// `discardDelta`) instead of leaking into the live store or a later
|
|
38
|
+
// successful attempt's recorded delta. Populated lazily by `trackPut` (only
|
|
39
|
+
// the first write to a given key within the current delta window is
|
|
40
|
+
// shadowed — later writes to the same key within the same attempt are
|
|
41
|
+
// already covered by that first shadow) and cleared whenever the delta is
|
|
42
|
+
// finalized, either way, via `commitDelta`/`discardDelta`.
|
|
43
|
+
private readonly priorValues = new Map<string, Map<string, { existed: boolean; value: unknown }>>();
|
|
44
|
+
|
|
45
|
+
/** Store a value under `key`. Overwrites any existing value. */
|
|
46
|
+
put(key: string, value: unknown): void {
|
|
47
|
+
this.map.set(key, value);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Store a value and record the write in the per-agent delta for `deltaKey`
|
|
52
|
+
* (a run-unique `${runId}:${callIndex}` string — see class doc). Used by
|
|
53
|
+
* per-agent tools created via `createAgentStoreTools` so that each agent's
|
|
54
|
+
* writes can be journaled and replayed independently.
|
|
55
|
+
*/
|
|
56
|
+
trackPut(key: string, value: unknown, deltaKey: string): void {
|
|
57
|
+
let priors = this.priorValues.get(deltaKey);
|
|
58
|
+
if (!priors) {
|
|
59
|
+
priors = new Map();
|
|
60
|
+
this.priorValues.set(deltaKey, priors);
|
|
61
|
+
}
|
|
62
|
+
// Only shadow the value from BEFORE this delta window started writing to
|
|
63
|
+
// this key — a second write to the same key within the same attempt must
|
|
64
|
+
// not overwrite the shadow with its own (already-in-window) value.
|
|
65
|
+
if (!priors.has(key)) {
|
|
66
|
+
priors.set(
|
|
67
|
+
key,
|
|
68
|
+
this.map.has(key) ? { existed: true, value: this.map.get(key) } : { existed: false, value: undefined },
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
this.map.set(key, value);
|
|
72
|
+
let delta = this.agentDeltas.get(deltaKey);
|
|
73
|
+
if (!delta) {
|
|
74
|
+
delta = {};
|
|
75
|
+
this.agentDeltas.set(deltaKey, delta);
|
|
76
|
+
}
|
|
77
|
+
delta[key] = value;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Retrieve the value for `key`, or `undefined` when absent. */
|
|
81
|
+
get(key: string): unknown {
|
|
82
|
+
return this.map.get(key);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Whether `key` is present in the store. */
|
|
86
|
+
has(key: string): boolean {
|
|
87
|
+
return this.map.has(key);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Return a deep-copied plain-object snapshot of all entries. */
|
|
91
|
+
snapshot(): Record<string, unknown> {
|
|
92
|
+
return structuredClone(Object.fromEntries(this.map));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Extract and clear the write delta accumulated for `deltaKey`.
|
|
97
|
+
* Called after an agent completes to get the set of keys it wrote.
|
|
98
|
+
*/
|
|
99
|
+
commitDelta(deltaKey: string): Record<string, unknown> {
|
|
100
|
+
const delta = this.agentDeltas.get(deltaKey) ?? {};
|
|
101
|
+
this.agentDeltas.delete(deltaKey);
|
|
102
|
+
this.priorValues.delete(deltaKey);
|
|
103
|
+
return delta;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Undo the writes recorded for `deltaKey` and discard its bookkeeping,
|
|
108
|
+
* without touching any other key. Used when a retry attempt fails: that
|
|
109
|
+
* attempt's writes must not remain visible in the live store (e.g. to a
|
|
110
|
+
* concurrently-running sibling agent's store_get, or to script code reading
|
|
111
|
+
* `store.get` directly) and must not merge into the delta eventually
|
|
112
|
+
* recorded when a later attempt of the SAME call succeeds — otherwise a
|
|
113
|
+
* failed attempt's mutations would silently survive into the run's live
|
|
114
|
+
* state while being absent from the journaled delta that resume replay
|
|
115
|
+
* reconstructs from, leaving live execution and replay permanently
|
|
116
|
+
* inconsistent. Each key touched during this delta window is restored to
|
|
117
|
+
* whatever it held immediately before the window started (or deleted, if
|
|
118
|
+
* it did not exist yet) — never to some other attempt's or caller's value.
|
|
119
|
+
*
|
|
120
|
+
* Per-key guard: a key is only rolled back if the store STILL holds this
|
|
121
|
+
* attempt's own last write to it (checked with `Object.is` against the
|
|
122
|
+
* value recorded in `delta`). If a concurrently-running sibling (a
|
|
123
|
+
* different `deltaKey`, e.g. another agent in the same parallel() batch)
|
|
124
|
+
* legitimately overwrote the same key AFTER this attempt wrote it but
|
|
125
|
+
* BEFORE it failed, that sibling's write is left untouched — rolling back
|
|
126
|
+
* unconditionally would silently erase a live, unrelated write that this
|
|
127
|
+
* attempt never made and has no business undoing.
|
|
128
|
+
*
|
|
129
|
+
* A no-op if `deltaKey` never wrote anything (nothing to roll back).
|
|
130
|
+
*/
|
|
131
|
+
discardDelta(deltaKey: string): void {
|
|
132
|
+
const delta = this.agentDeltas.get(deltaKey);
|
|
133
|
+
if (!delta) return;
|
|
134
|
+
const priors = this.priorValues.get(deltaKey);
|
|
135
|
+
for (const key of Object.keys(delta)) {
|
|
136
|
+
// Someone else already overwrote this key since our last write to it —
|
|
137
|
+
// leave their write in place instead of clobbering it with our rollback.
|
|
138
|
+
if (!Object.is(this.map.get(key), delta[key])) continue;
|
|
139
|
+
const prior = priors?.get(key);
|
|
140
|
+
if (prior?.existed) this.map.set(key, prior.value);
|
|
141
|
+
else this.map.delete(key);
|
|
142
|
+
}
|
|
143
|
+
this.agentDeltas.delete(deltaKey);
|
|
144
|
+
this.priorValues.delete(deltaKey);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Apply a write delta additively — sets each key without clearing others.
|
|
149
|
+
* Used during resume replay so parallel-agent deltas applied in callSeq
|
|
150
|
+
* order accumulate correctly regardless of original completion order.
|
|
151
|
+
*/
|
|
152
|
+
applyDelta(delta: Record<string, unknown>): void {
|
|
153
|
+
for (const [k, v] of Object.entries(delta)) {
|
|
154
|
+
this.map.set(k, v);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Replace all entries with a snapshot (for full resets).
|
|
160
|
+
* Prefer `applyDelta` for resume replay — see journal integration above.
|
|
161
|
+
*/
|
|
162
|
+
restore(snap: Record<string, unknown>): void {
|
|
163
|
+
this.map.clear();
|
|
164
|
+
for (const [k, v] of Object.entries(snap)) {
|
|
165
|
+
this.map.set(k, v);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** Clear all entries (called when the run ends). */
|
|
170
|
+
dispose(): void {
|
|
171
|
+
this.map.clear();
|
|
172
|
+
this.agentDeltas.clear();
|
|
173
|
+
this.priorValues.clear();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Create per-agent store tools that attribute writes to `deltaKey`, a
|
|
179
|
+
* run-unique `${runId}:${callIndex}` string (see the `SharedStore` class doc
|
|
180
|
+
* for why the bare callIndex alone is not enough once a nested `workflow()`
|
|
181
|
+
* call shares this store).
|
|
182
|
+
* Used internally by `runWorkflow` so each agent's puts are tracked in the
|
|
183
|
+
* store's delta journal and can be replayed additively on resume.
|
|
184
|
+
*/
|
|
185
|
+
export function createAgentStoreTools(store: SharedStore, deltaKey: string): ToolDefinition[] {
|
|
186
|
+
const storePut = defineTool({
|
|
187
|
+
name: "store_put",
|
|
188
|
+
label: "Store Put",
|
|
189
|
+
description:
|
|
190
|
+
"Write a value to the shared run store. Any other agent in this workflow run can read it with store_get. Overwrites any existing value for the key. Note: when two parallel agents write the same key, the last write wins — no merge is performed.",
|
|
191
|
+
promptSnippet: "Write a value to the shared store",
|
|
192
|
+
parameters: Type.Object({
|
|
193
|
+
key: Type.String({ description: "The key to store the value under." }),
|
|
194
|
+
value: Type.Any({ description: "The value to store (any JSON-serializable value)." }),
|
|
195
|
+
}),
|
|
196
|
+
async execute(_id: string, params: { key: string; value: unknown }) {
|
|
197
|
+
store.trackPut(params.key, params.value, deltaKey);
|
|
198
|
+
return {
|
|
199
|
+
content: [{ type: "text", text: `Stored value under key "${params.key}".` }],
|
|
200
|
+
details: { key: params.key },
|
|
201
|
+
};
|
|
202
|
+
},
|
|
203
|
+
}) as unknown as ToolDefinition;
|
|
204
|
+
|
|
205
|
+
const storeGet = defineTool({
|
|
206
|
+
name: "store_get",
|
|
207
|
+
label: "Store Get",
|
|
208
|
+
description:
|
|
209
|
+
"Read a value from the shared run store previously written by store_put. Returns the stored value, or null when the key does not exist.",
|
|
210
|
+
promptSnippet: "Read a value from the shared store",
|
|
211
|
+
parameters: Type.Object({
|
|
212
|
+
key: Type.String({ description: "The key to read." }),
|
|
213
|
+
}),
|
|
214
|
+
async execute(_id: string, params: { key: string }) {
|
|
215
|
+
const found = store.has(params.key);
|
|
216
|
+
const value = store.get(params.key);
|
|
217
|
+
const text = found
|
|
218
|
+
? `Value for key "${params.key}": ${JSON.stringify(value)}`
|
|
219
|
+
: `Key "${params.key}" not found in store.`;
|
|
220
|
+
return {
|
|
221
|
+
content: [{ type: "text", text }],
|
|
222
|
+
details: { key: params.key, value: found ? value : null, found },
|
|
223
|
+
};
|
|
224
|
+
},
|
|
225
|
+
}) as unknown as ToolDefinition;
|
|
226
|
+
|
|
227
|
+
return [storePut, storeGet];
|
|
228
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { Static, TSchema } from "typebox";
|
|
3
|
+
|
|
4
|
+
export interface StructuredOutputCapture<T = unknown> {
|
|
5
|
+
value: T | undefined;
|
|
6
|
+
called: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface StructuredOutputToolOptions<TSchemaDef extends TSchema> {
|
|
10
|
+
schema: TSchemaDef;
|
|
11
|
+
capture: StructuredOutputCapture<Static<TSchemaDef>>;
|
|
12
|
+
name?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Create a terminating tool that captures validated params as the subagent result.
|
|
17
|
+
*
|
|
18
|
+
* Pi validates `params` against `schema` before execute() is called. Returning
|
|
19
|
+
* `terminate: true` lets the subagent finish on this tool call without paying for
|
|
20
|
+
* an extra assistant follow-up turn.
|
|
21
|
+
*/
|
|
22
|
+
export function createStructuredOutputTool<TSchemaDef extends TSchema>({
|
|
23
|
+
schema,
|
|
24
|
+
capture,
|
|
25
|
+
name = "structured_output",
|
|
26
|
+
}: StructuredOutputToolOptions<TSchemaDef>): ReturnType<typeof defineTool<TSchemaDef, Static<TSchemaDef>>> {
|
|
27
|
+
return defineTool({
|
|
28
|
+
name,
|
|
29
|
+
label: "Structured Output",
|
|
30
|
+
description: "Return the final machine-readable result for this subagent task.",
|
|
31
|
+
promptSnippet: "Return final machine-readable output",
|
|
32
|
+
promptGuidelines: [
|
|
33
|
+
`${name} is the final answer channel for this task; call ${name} exactly once when done.`,
|
|
34
|
+
`Do not write a prose final answer after calling ${name}.`,
|
|
35
|
+
],
|
|
36
|
+
parameters: schema,
|
|
37
|
+
async execute(_toolCallId, params) {
|
|
38
|
+
capture.value = params;
|
|
39
|
+
capture.called = true;
|
|
40
|
+
return {
|
|
41
|
+
content: [{ type: "text", text: "Structured output received." }],
|
|
42
|
+
details: params,
|
|
43
|
+
terminate: true,
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|