@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
package/dist/agent.d.ts
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import { type CreateAgentSessionOptions, ModelRegistry, ModelRuntime, type ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { Static, TSchema } from "typebox";
|
|
3
|
+
import { type AgentHistoryEntry } from "./agent-history.js";
|
|
4
|
+
import { type ModelTierConfig, type RankableModel } from "./model-tier-config.js";
|
|
5
|
+
import { type StructuredOutputCapture } from "./structured-output.js";
|
|
6
|
+
/**
|
|
7
|
+
* Last-resort structured-output recovery: extract a JSON block from prose, coerce
|
|
8
|
+
* it toward the schema, and accept it only if it then validates. Never fabricates
|
|
9
|
+
* — returns undefined unless the parsed value genuinely satisfies the schema.
|
|
10
|
+
*/
|
|
11
|
+
export declare function extractValidated<T>(text: string, schema: TSchema): T | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* The last assistant message's terminal metadata (stopReason/errorMessage). The pi
|
|
14
|
+
* SDK does NOT throw provider usage/quota limits — it records them as an assistant
|
|
15
|
+
* message with stopReason "error" and an errorMessage. This is the only place that
|
|
16
|
+
* metadata is observable to the workflow layer.
|
|
17
|
+
*/
|
|
18
|
+
export declare function lastAssistantError(messages: unknown[]): {
|
|
19
|
+
stopReason?: string;
|
|
20
|
+
errorMessage?: string;
|
|
21
|
+
} | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* If the subagent's turn ended in a provider usage/quota/rate-limit error, throw a
|
|
24
|
+
* PROVIDER_USAGE_LIMIT WorkflowError carrying the real provider message + reset hint.
|
|
25
|
+
* Gated on stopReason === "error" so a successful turn whose text merely mentions
|
|
26
|
+
* "rate limit" is never misclassified. recoverable:false so the run checkpoints
|
|
27
|
+
* (paused) rather than being retried into the same wall or collapsed to a silent null.
|
|
28
|
+
*/
|
|
29
|
+
export declare function throwIfProviderLimit(messages: unknown[], label?: string): void;
|
|
30
|
+
/** Minimal session surface resolveStructuredOutput needs (real session or a test double). */
|
|
31
|
+
export interface StructuredSession {
|
|
32
|
+
prompt(text: string): Promise<void>;
|
|
33
|
+
setActiveToolsByName?(names: string[]): void;
|
|
34
|
+
messages: unknown[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Resolve a schema agent's result. If the tool was called, return the captured
|
|
38
|
+
* value. Otherwise re-prompt up to maxSchemaRetries (tools restricted to
|
|
39
|
+
* structured_output), then try strict schema-validated prose extraction, else
|
|
40
|
+
* throw SCHEMA_NONCOMPLIANCE (non-recoverable — surfaced, never a silent null).
|
|
41
|
+
* Module-level with an injected `lastText` so it is unit-testable.
|
|
42
|
+
*/
|
|
43
|
+
export declare function resolveStructuredOutput<T>(session: StructuredSession, capture: StructuredOutputCapture<T>, schema: TSchema, options: {
|
|
44
|
+
maxSchemaRetries?: number;
|
|
45
|
+
signal?: AbortSignal;
|
|
46
|
+
label?: string;
|
|
47
|
+
}, lastText: (messages: unknown[]) => string): Promise<T>;
|
|
48
|
+
/**
|
|
49
|
+
* Resolve which concrete model spec a subagent should use. Precedence, most
|
|
50
|
+
* specific first:
|
|
51
|
+
* 1. options.model — an explicit per-agent model (also carries agentType /
|
|
52
|
+
* phase model, which the workflow layer folds into options.model).
|
|
53
|
+
* 2. options.tier — resolved via the model-tiers config, falling back to the
|
|
54
|
+
* session's main model when the tier has no configured entry.
|
|
55
|
+
* 3. DEFAULT TIER — when neither is set but the user has a model-tiers config,
|
|
56
|
+
* untagged agents default to the "medium" tier so a configured tier set
|
|
57
|
+
* actually affects the whole workflow (not just agents the script tagged).
|
|
58
|
+
* Fresh-install medium == the session model, so this is a no-op until the
|
|
59
|
+
* user customizes tiers via /workflows-models.
|
|
60
|
+
* Returns undefined when nothing applies, so the session default is used.
|
|
61
|
+
*
|
|
62
|
+
* `loadConfig` is injectable for testing; it defaults to reading from disk.
|
|
63
|
+
*/
|
|
64
|
+
export declare function resolveAgentModelSpec(options: {
|
|
65
|
+
model?: string;
|
|
66
|
+
tier?: string;
|
|
67
|
+
}, mainModel: string | undefined, loadConfig?: () => ModelTierConfig | null, onTierWithoutConfig?: (tier: string) => void): string | undefined;
|
|
68
|
+
export interface WorkflowAgentOptions {
|
|
69
|
+
cwd?: string;
|
|
70
|
+
/** Extra tools available to the subagent in addition to the structured output tool. */
|
|
71
|
+
tools?: ToolDefinition[];
|
|
72
|
+
/**
|
|
73
|
+
* Extra tool NAMES to deny in the subagent session, on top of the always-on
|
|
74
|
+
* defaults ({@link DEFAULT_EXCLUDED_SUBAGENT_TOOLS}). Lets the host exclude
|
|
75
|
+
* other recursive-orchestration tools it registers (e.g. a pi-subagents tool)
|
|
76
|
+
* so a workflow subagent can't fan out through them either (#107).
|
|
77
|
+
*/
|
|
78
|
+
excludeTools?: string[];
|
|
79
|
+
/** Override any createAgentSession option (model, modelRuntime, resourceLoader, etc.). */
|
|
80
|
+
session?: Partial<CreateAgentSessionOptions>;
|
|
81
|
+
/** Extra system guidance prepended to every subagent task. */
|
|
82
|
+
instructions?: string;
|
|
83
|
+
/**
|
|
84
|
+
* The session's main model (`provider/modelId`). Used as a fallback when
|
|
85
|
+
* resolving opts.tier and no model-tiers.json config exists. Without this,
|
|
86
|
+
* a workflow using `{ tier: "small" }` would log a warning and fall through
|
|
87
|
+
* to the session default when no config is saved yet.
|
|
88
|
+
*/
|
|
89
|
+
mainModel?: string;
|
|
90
|
+
/**
|
|
91
|
+
* Shared model registry from the host Pi session. When provided, subagents
|
|
92
|
+
* resolve tier/model specs against the same registry the main session uses,
|
|
93
|
+
* including dynamically-registered providers such as ollama-cloud. Without
|
|
94
|
+
* this, the agent builds an isolated registry from disk and may miss models
|
|
95
|
+
* that are only available via extension registration.
|
|
96
|
+
*/
|
|
97
|
+
modelRegistry?: ModelRegistry;
|
|
98
|
+
/**
|
|
99
|
+
* Persist each subagent transcript as a real pi session file under the
|
|
100
|
+
* standard sessions directory (keyed by the runner's project cwd), instead
|
|
101
|
+
* of the default in-memory session that is discarded when the run ends.
|
|
102
|
+
* Default: false (current behavior).
|
|
103
|
+
*/
|
|
104
|
+
persistAgentSessions?: boolean;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The ModelRuntime behind a registry facade. pi's ModelRegistry does not expose
|
|
108
|
+
* its runtime publicly, so reach into the private field (stable since 0.80.8);
|
|
109
|
+
* subagent sessions need it to share the host session's exact catalog and auth
|
|
110
|
+
* (createAgentSession takes modelRuntime, not a registry, since 0.80.8).
|
|
111
|
+
*
|
|
112
|
+
* Exported so the test suite can pin this pi-internals contract: the cast means
|
|
113
|
+
* neither tsc nor mock-based tests would notice pi renaming the field, and the
|
|
114
|
+
* runtime consequence is silent (subagents fall back to a default runtime and
|
|
115
|
+
* extension-registered providers vanish from routing).
|
|
116
|
+
*/
|
|
117
|
+
export declare function runtimeOf(registry: ModelRegistry): ModelRuntime | undefined;
|
|
118
|
+
/**
|
|
119
|
+
* List the user's currently available models (those with auth configured) with
|
|
120
|
+
* the minimal fields tier ranking needs: canonical spec, output price, and
|
|
121
|
+
* context window. This is the single place the SDK `Model` is projected into
|
|
122
|
+
* the SDK-agnostic `RankableModel`. Best-effort: returns [] if the registry
|
|
123
|
+
* can't be built (or while the disk-backed fallback is still initializing).
|
|
124
|
+
*/
|
|
125
|
+
export declare function listAvailableModels(registry?: ModelRegistry): RankableModel[];
|
|
126
|
+
/**
|
|
127
|
+
* List the user's currently available models as `provider/modelId` specs. Used
|
|
128
|
+
* to tell the workflow author which models it may route agents to. Best-effort:
|
|
129
|
+
* returns [] if the registry can't be built.
|
|
130
|
+
*/
|
|
131
|
+
export declare function listAvailableModelSpecs(registry?: ModelRegistry): string[];
|
|
132
|
+
/** Real token/cost usage for a single subagent run, read from the SDK session. */
|
|
133
|
+
export interface AgentUsage {
|
|
134
|
+
input: number;
|
|
135
|
+
output: number;
|
|
136
|
+
cacheRead: number;
|
|
137
|
+
cacheWrite: number;
|
|
138
|
+
total: number;
|
|
139
|
+
cost: number;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Map session stats to an AgentUsage, or undefined when the provider reported
|
|
143
|
+
* no usage at all (all-zero stats). Returning undefined — instead of a zero
|
|
144
|
+
* breakdown — lets displays fall back to their scalar token count, so setups
|
|
145
|
+
* on non-reporting providers render the same as before the split existed.
|
|
146
|
+
*/
|
|
147
|
+
export declare function usageFromStats(stats: {
|
|
148
|
+
tokens: {
|
|
149
|
+
input: number;
|
|
150
|
+
output: number;
|
|
151
|
+
cacheRead: number;
|
|
152
|
+
cacheWrite: number;
|
|
153
|
+
total: number;
|
|
154
|
+
};
|
|
155
|
+
cost: number;
|
|
156
|
+
}): AgentUsage | undefined;
|
|
157
|
+
export interface AgentRunOptions<TSchemaDef extends TSchema | undefined = undefined> {
|
|
158
|
+
label?: string;
|
|
159
|
+
/**
|
|
160
|
+
* Display name recorded on the persisted session (session_info entry) when
|
|
161
|
+
* `persistAgentSessions` is enabled, so transcripts are identifiable in
|
|
162
|
+
* session pickers (e.g. `workflow:<runId> <label>`). Ignored for in-memory
|
|
163
|
+
* sessions or when an explicit session.sessionManager override is injected.
|
|
164
|
+
*/
|
|
165
|
+
sessionName?: string;
|
|
166
|
+
schema?: TSchemaDef;
|
|
167
|
+
tools?: ToolDefinition[];
|
|
168
|
+
instructions?: string;
|
|
169
|
+
signal?: AbortSignal;
|
|
170
|
+
/**
|
|
171
|
+
* Called once with this subagent's real usage, read from the session right
|
|
172
|
+
* before disposal. Fires on both the success and error paths so partial
|
|
173
|
+
* usage is never lost — but NOT when the provider reported no usage at all
|
|
174
|
+
* (all-zero stats), so consumers keep their scalar fallback.
|
|
175
|
+
*/
|
|
176
|
+
onUsage?: (usage: AgentUsage) => void;
|
|
177
|
+
/**
|
|
178
|
+
* Model spec for this subagent: either `provider/modelId` (unambiguous) or a
|
|
179
|
+
* bare `modelId`. When it can't be resolved, the session default is used and
|
|
180
|
+
* a warning is logged. When omitted, the session default applies.
|
|
181
|
+
*/
|
|
182
|
+
model?: string;
|
|
183
|
+
/**
|
|
184
|
+
* Model tier name (e.g. "small", "medium", "big"). When set (and no explicit
|
|
185
|
+
* `model` is given), the model is resolved from the user's model-tiers.json
|
|
186
|
+
* config before `run()` starts, falling back to the session's main model when
|
|
187
|
+
* the tier has no configured entry. An explicit `model` always takes priority,
|
|
188
|
+
* so workflow scripts can use `{ tier: "small" }` for coarse routing without
|
|
189
|
+
* caring which concrete model backs that tier.
|
|
190
|
+
*/
|
|
191
|
+
tier?: string;
|
|
192
|
+
/** Called with the resolved model id once known (for display/telemetry). */
|
|
193
|
+
onModelResolved?: (modelId: string) => void;
|
|
194
|
+
/** Called when `model`/`tier`/phase resolved to a spec that wasn't found (fell back to session default). */
|
|
195
|
+
onModelFallback?: (requestedSpec: string) => void;
|
|
196
|
+
/** Called with a compact snapshot of this subagent's message/tool history. */
|
|
197
|
+
onHistory?: (history: AgentHistoryEntry[]) => void;
|
|
198
|
+
/** Run this agent in a different working directory (e.g. an isolated worktree). */
|
|
199
|
+
cwd?: string;
|
|
200
|
+
/**
|
|
201
|
+
* Restrict the subagent's coding tools to these names (an agentType
|
|
202
|
+
* definition's `tools` allowlist). Undefined = all coding tools. The
|
|
203
|
+
* structured_output tool is always added after this filter, so a schema
|
|
204
|
+
* still works under a restrictive allowlist.
|
|
205
|
+
*/
|
|
206
|
+
toolNames?: string[];
|
|
207
|
+
/** Remove these coding-tool names after the allowlist (an agentType `disallowedTools` denylist). */
|
|
208
|
+
disallowedToolNames?: string[];
|
|
209
|
+
/**
|
|
210
|
+
* With `schema`: how many extra repair turns to allow if the model finishes
|
|
211
|
+
* without calling structured_output. Each retry re-prompts (tools restricted to
|
|
212
|
+
* structured_output) before falling back to strict prose extraction. Default 2.
|
|
213
|
+
*/
|
|
214
|
+
maxSchemaRetries?: number;
|
|
215
|
+
/**
|
|
216
|
+
* Tools that are always injected AFTER the tool-policy filter (`toolNames` /
|
|
217
|
+
* `disallowedToolNames`), so they are available even under a restrictive
|
|
218
|
+
* allowlist. Used by the workflow runtime to inject shared-store tools into
|
|
219
|
+
* every agent regardless of its agentType definition.
|
|
220
|
+
*/
|
|
221
|
+
systemTools?: ToolDefinition[];
|
|
222
|
+
/**
|
|
223
|
+
* Per-run model registry override. Takes precedence over the constructor's
|
|
224
|
+
* `modelRegistry` (WorkflowAgentOptions.modelRegistry) for both model
|
|
225
|
+
* resolution and the `createAgentSession` call this run makes. Falls back to
|
|
226
|
+
* the constructor's shared registry, then a lazily-built disk registry, when
|
|
227
|
+
* omitted.
|
|
228
|
+
*/
|
|
229
|
+
modelRegistry?: ModelRegistry;
|
|
230
|
+
}
|
|
231
|
+
export type AgentRunResult<TSchemaDef extends TSchema | undefined> = TSchemaDef extends TSchema ? Static<TSchemaDef> : string;
|
|
232
|
+
/**
|
|
233
|
+
* Orchestration tools ALWAYS denied to workflow subagents. The `workflow` and
|
|
234
|
+
* `workflow_control` tools are registered globally by the extension, so — unless
|
|
235
|
+
* excluded — a subagent's session sees them and can start its own independent
|
|
236
|
+
* background workflows. Those nested runs recursively fan out and are NOT bounded
|
|
237
|
+
* by the parent run's maxAgents / concurrency / progress / accounting, and can
|
|
238
|
+
* drain a shared provider quota and pile up paused runs (#107). Callers may deny
|
|
239
|
+
* additional tool names via WorkflowAgentOptions.excludeTools.
|
|
240
|
+
*/
|
|
241
|
+
export declare const DEFAULT_EXCLUDED_SUBAGENT_TOOLS: string[];
|
|
242
|
+
/**
|
|
243
|
+
* The full subagent tool denylist: the always-on defaults plus any names the
|
|
244
|
+
* caller added (via WorkflowAgentOptions.excludeTools) or set on the injected
|
|
245
|
+
* session options. Extracted so the merge — and its order — is unit-testable;
|
|
246
|
+
* a spread-order regression that dropped the defaults would slip past a test
|
|
247
|
+
* that only asserts the constant. The SDK dedupes, so overlap is harmless.
|
|
248
|
+
*/
|
|
249
|
+
export declare function subagentExcludedTools(extra?: string[], sessionExclude?: string[]): string[];
|
|
250
|
+
export declare class WorkflowAgent {
|
|
251
|
+
private readonly cwd;
|
|
252
|
+
private readonly baseTools;
|
|
253
|
+
/** Extra subagent tool-name denylist, merged with the always-on defaults. */
|
|
254
|
+
private readonly excludeTools;
|
|
255
|
+
private readonly sessionOptions;
|
|
256
|
+
private readonly persistAgentSessions;
|
|
257
|
+
private readonly instructions?;
|
|
258
|
+
private readonly mainModel?;
|
|
259
|
+
/** Shared registry from the host session, when provided. */
|
|
260
|
+
private readonly sharedRegistry?;
|
|
261
|
+
/** Lazily built once; shares the SDK's agentDir/auth so resolved models are authed. */
|
|
262
|
+
private registry?;
|
|
263
|
+
/**
|
|
264
|
+
* Memoized model-tiers.json snapshot, boxed so a legitimately-null config
|
|
265
|
+
* (file absent/invalid) is distinguishable from "not loaded yet". See
|
|
266
|
+
* loadTierConfig() below for why this is scoped per-instance.
|
|
267
|
+
*/
|
|
268
|
+
private tierConfigBox?;
|
|
269
|
+
/**
|
|
270
|
+
* Shared resource loader for every subagent of this run, built once. See
|
|
271
|
+
* getSharedResourceLoader — this is the #109 memory mitigation.
|
|
272
|
+
*/
|
|
273
|
+
private sharedResourceLoaderPromise?;
|
|
274
|
+
constructor(options?: WorkflowAgentOptions);
|
|
275
|
+
/**
|
|
276
|
+
* A resource loader shared by every subagent of this run, built once (#109).
|
|
277
|
+
*
|
|
278
|
+
* Without a resourceLoader, createAgentSession() builds a fresh
|
|
279
|
+
* DefaultResourceLoader per subagent and reloads it — re-running EVERY installed
|
|
280
|
+
* extension factory each time (verified: N subagents → N factory runs). Each
|
|
281
|
+
* such factory that arms a load-time timer/listener then roots its subagent
|
|
282
|
+
* session forever, because AgentSession.dispose() emits no session_shutdown to
|
|
283
|
+
* run the cleanup — the dominant #109 leak, and one our own extension
|
|
284
|
+
* (UsageLimitScheduler) can trigger.
|
|
285
|
+
*
|
|
286
|
+
* `noExtensions: true` skips loading host extensions; skills, prompts, and
|
|
287
|
+
* AGENTS.md context still load. The subagent keeps the tools this workflow
|
|
288
|
+
* hands it via `customTools` (coding tools + any toolset like web-research) —
|
|
289
|
+
* those are unaffected. What it loses is HOST EXTENSION-REGISTERED tools (MCP
|
|
290
|
+
* bridges, browser tools, anything a host extension added via ctx.registerTool):
|
|
291
|
+
* pre-change a subagent session inherited those from the full host extension
|
|
292
|
+
* set, now it does not, so an agentType `tools` allowlist naming one matches
|
|
293
|
+
* nothing. This is a deliberate trade-off — it also structurally kills recursive
|
|
294
|
+
* orchestration in subagents (no extension runtime at all), beyond the name-level
|
|
295
|
+
* #107 denylist — and must be release-noted. `createAgentSession` with a shared
|
|
296
|
+
* resourceLoader is a supported embedding pattern. runWorkflow builds one
|
|
297
|
+
* WorkflowAgent per run, so this loader's lifetime is exactly one run: built
|
|
298
|
+
* once, reused by all its subagents, then dropped with the agent.
|
|
299
|
+
*/
|
|
300
|
+
private getSharedResourceLoader;
|
|
301
|
+
/**
|
|
302
|
+
* Resolve the registry for a run: an explicit per-run registry wins, then the
|
|
303
|
+
* constructor's shared registry, then a lazily-built disk registry (shared
|
|
304
|
+
* across calls once built). Async because pi >= 0.80.8 builds registries from
|
|
305
|
+
* an async-created ModelRuntime.
|
|
306
|
+
*/
|
|
307
|
+
private getRegistry;
|
|
308
|
+
/**
|
|
309
|
+
* Read+parse ~/.pi/workflows/model-tiers.json at most once for this
|
|
310
|
+
* instance's lifetime, instead of on every run() call. `resolveAgentModelSpec`
|
|
311
|
+
* previously received `loadModelTierConfig` directly (sync existsSync +
|
|
312
|
+
* readFileSync + JSON.parse from disk), which it calls unconditionally for
|
|
313
|
+
* any agent without an explicit options.model — so a large fan-out did N
|
|
314
|
+
* redundant synchronous disk reads that blocked the event loop and stalled
|
|
315
|
+
* concurrent agents' I/O.
|
|
316
|
+
*
|
|
317
|
+
* `runWorkflow()` constructs a fresh `WorkflowAgent` per run (see
|
|
318
|
+
* `new WorkflowAgent(options)` in workflow.ts, unless a caller injects its
|
|
319
|
+
* own `options.agent` runner — a test-only escape hatch per
|
|
320
|
+
* WorkflowManagerOptions.agent's doc comment), so a WorkflowAgent instance's
|
|
321
|
+
* lifetime is one run in production. Memoizing on `this` therefore has the
|
|
322
|
+
* same scope and lifetime as the agentRegistry snapshot workflow.ts already
|
|
323
|
+
* takes once per run "for determinism" — the config file isn't expected to
|
|
324
|
+
* change mid-run, and two different runs (= two different WorkflowAgent
|
|
325
|
+
* instances) each get their own fresh read of whatever is on disk at the
|
|
326
|
+
* time, so this does not leak stale config across runs or break tests that
|
|
327
|
+
* construct fresh agents with different configs.
|
|
328
|
+
*
|
|
329
|
+
* `loader` is injectable for tests (defaults to the real disk read); it is
|
|
330
|
+
* only ever consulted once, on the first call, regardless of what is passed
|
|
331
|
+
* on later calls.
|
|
332
|
+
*/
|
|
333
|
+
private loadTierConfig;
|
|
334
|
+
/**
|
|
335
|
+
* Session manager for one subagent run. File-backed (persisted under the
|
|
336
|
+
* standard sessions dir, keyed by the runner's project cwd — never a
|
|
337
|
+
* per-call worktree cwd) when persistAgentSessions is on; in-memory otherwise.
|
|
338
|
+
*
|
|
339
|
+
* SessionManager.create() only creates the session directory — the SDK writes
|
|
340
|
+
* the session file lazily (synchronous fs calls, uncaught) on the first
|
|
341
|
+
* assistant message, deep inside session.prompt(). A failure there would
|
|
342
|
+
* otherwise throw mid-run and abort this subagent. Probe writability up front
|
|
343
|
+
* so any create/write failure (permissions, disk full) degrades this single
|
|
344
|
+
* agent to an in-memory session instead — the run continues, just without a
|
|
345
|
+
* persisted transcript.
|
|
346
|
+
*/
|
|
347
|
+
private createSessionManager;
|
|
348
|
+
/** Best-effort write probe: throws if the session directory isn't actually writable. */
|
|
349
|
+
private assertSessionDirWritable;
|
|
350
|
+
run<TSchemaDef extends TSchema | undefined = undefined>(prompt: string, options?: AgentRunOptions<TSchemaDef>): Promise<AgentRunResult<TSchemaDef>>;
|
|
351
|
+
private buildPrompt;
|
|
352
|
+
private lastAssistantText;
|
|
353
|
+
/**
|
|
354
|
+
* The unstructured agent's FINAL answer: assistant text that appears after the
|
|
355
|
+
* last tool result. Text before the final tool result is stale progress (the
|
|
356
|
+
* agent's last real action was a tool call, not answering), so returning it
|
|
357
|
+
* would mask an incomplete run and suppress AGENT_EMPTY_OUTPUT retries (#111).
|
|
358
|
+
*
|
|
359
|
+
* Distinct from lastAssistantText(), which stays deliberately lenient — the
|
|
360
|
+
* schema path's prose-JSON recovery (resolveStructuredOutput) may need to read
|
|
361
|
+
* the structured payload out of any assistant message, not only the terminal one.
|
|
362
|
+
*/
|
|
363
|
+
private finalAssistantText;
|
|
364
|
+
}
|