@cr1ms0n/pi-subagent 0.8.9 → 0.10.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/CHANGELOG.md +24 -0
- package/README.md +130 -569
- package/README.zh-CN.md +132 -0
- package/docs/ARCHITECTURE.md +56 -13
- package/docs/COST-ACCOUNTING.md +116 -66
- package/docs/DEVELOPMENT.md +124 -0
- package/docs/PLAN.md +2 -0
- package/docs/REFERENCE.md +436 -0
- package/docs/RELEASING.md +135 -16
- package/docs/ROADMAP.md +2 -0
- package/docs/SECURITY.md +52 -16
- package/docs/UX.md +158 -141
- package/package.json +10 -2
- package/skills/subagent/SKILL.md +82 -49
- package/src/backends/pi.ts +164 -94
- package/src/child-preflight.ts +166 -0
- package/src/config.ts +254 -252
- package/src/dispatch-preflight.ts +87 -0
- package/src/dispatch-routing.ts +56 -0
- package/src/extension.ts +366 -158
- package/src/format.ts +436 -365
- package/src/jev-router.ts +1032 -0
- package/src/orchestrator.ts +75 -19
- package/src/persistence.ts +643 -335
- package/src/policy.ts +120 -89
- package/src/process-lock.ts +730 -687
- package/src/protocol.ts +320 -290
- package/src/registry.ts +730 -632
- package/src/routing-policy.ts +276 -0
- package/src/routing-types.ts +217 -0
- package/src/runner.ts +1299 -850
- package/src/schema.ts +10 -10
- package/src/startup-check.ts +481 -0
- package/src/types.ts +208 -198
- package/src/usage.ts +316 -274
- package/src/model-policy.ts +0 -169
package/src/types.ts
CHANGED
|
@@ -1,198 +1,208 @@
|
|
|
1
|
-
import type { Message } from "@earendil-works/pi-ai";
|
|
2
|
-
import type { ThinkingLevel } from "./thinking.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export type
|
|
9
|
-
export type
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
1
|
+
import type { Message } from "@earendil-works/pi-ai";
|
|
2
|
+
import type { ThinkingLevel } from "./thinking.js";
|
|
3
|
+
import type { RoutingDecision } from "./routing-types.js";
|
|
4
|
+
|
|
5
|
+
/** Validated selector decision plus mandatory local control-plane tools. */
|
|
6
|
+
export type TaskRouting = RoutingDecision & { readonly mandatoryTools: readonly string[]; readonly outcome: "success" };
|
|
7
|
+
|
|
8
|
+
export type RunMode = "single" | "parallel";
|
|
9
|
+
export type RunState = "queued" | "running" | "completed" | "partial" | "failed" | "cancelled" | "lost" | "timeout";
|
|
10
|
+
/** Distinct timeout phases so agents can retry queue pressure without "fixing" unfinished work. */
|
|
11
|
+
export type TimeoutPhase = "queued" | "starting" | "running" | "cancelling";
|
|
12
|
+
export type TaskProfile = "explore" | "review" | "general";
|
|
13
|
+
export type OutputMode = "inline" | "file-only";
|
|
14
|
+
|
|
15
|
+
/** Durable identity of a spawned child process for orphan reconcile. */
|
|
16
|
+
export interface ChildProcessIdentity {
|
|
17
|
+
pid: number;
|
|
18
|
+
/** Platform-specific process start identity; 0 when unknown. */
|
|
19
|
+
startTime: number;
|
|
20
|
+
pgid?: number;
|
|
21
|
+
hostname?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface UsageStats {
|
|
25
|
+
input: number;
|
|
26
|
+
output: number;
|
|
27
|
+
cacheRead: number;
|
|
28
|
+
cacheWrite: number;
|
|
29
|
+
/** Reasoning is a subset of output when providers report it. */
|
|
30
|
+
reasoning?: number;
|
|
31
|
+
/** Provider-reported total cost. */
|
|
32
|
+
cost: number;
|
|
33
|
+
costInput?: number;
|
|
34
|
+
costOutput?: number;
|
|
35
|
+
costCacheRead?: number;
|
|
36
|
+
costCacheWrite?: number;
|
|
37
|
+
/** Most recent turn's context size; not additive across turns. */
|
|
38
|
+
contextTokens: number;
|
|
39
|
+
turns: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type BackendName = "pi" | "codex" | "claude";
|
|
43
|
+
|
|
44
|
+
export interface TaskSpec {
|
|
45
|
+
/** Agent CLI powering this child. Defaults to "pi". */
|
|
46
|
+
backend?: BackendName;
|
|
47
|
+
task: string;
|
|
48
|
+
/** Short human label shown in UIs and result indexes. */
|
|
49
|
+
label?: string;
|
|
50
|
+
systemPrompt?: string;
|
|
51
|
+
model?: string;
|
|
52
|
+
thinking?: ThinkingLevel;
|
|
53
|
+
tools?: string[];
|
|
54
|
+
profile: TaskProfile;
|
|
55
|
+
canWrite?: boolean;
|
|
56
|
+
cwd?: string;
|
|
57
|
+
timeoutMs: number;
|
|
58
|
+
/** Absolute extension task deadline; absent for legacy explicit-spec SDK callers. */
|
|
59
|
+
deadline?: number;
|
|
60
|
+
/** Present only after mandatory extension routing and local validation. */
|
|
61
|
+
routing?: TaskRouting;
|
|
62
|
+
maxTurns?: number;
|
|
63
|
+
maxCost?: number;
|
|
64
|
+
output?: string;
|
|
65
|
+
outputMode?: OutputMode;
|
|
66
|
+
resume?: string;
|
|
67
|
+
forkResume?: boolean;
|
|
68
|
+
isolation?: "shared" | "worktree";
|
|
69
|
+
allowSharedWrites?: boolean;
|
|
70
|
+
/** Seed worktree with parent checkout WIP (worktree isolation only). */
|
|
71
|
+
includeWip?: boolean;
|
|
72
|
+
/** Opt out of process-tree reaping after a clean exit (e.g. child-started dev servers). */
|
|
73
|
+
keepBackground?: boolean;
|
|
74
|
+
/** Wrap-up grace turns after a max_turns/max_cost breach before SIGTERM. 0 = immediate stop. */
|
|
75
|
+
graceTurns?: number;
|
|
76
|
+
/** Ordered backup models tried on transient provider failures. */
|
|
77
|
+
fallbackModels?: string[];
|
|
78
|
+
/** Extra attempts on transient failures (queue timeout, stall, provider error). */
|
|
79
|
+
maxRetries?: number;
|
|
80
|
+
/** Fork the parent conversation into the child (real branched session). */
|
|
81
|
+
contextFork?: boolean;
|
|
82
|
+
/** Parent session file used for contextFork. */
|
|
83
|
+
parentSessionFile?: string;
|
|
84
|
+
/** What this child may itself spawn; encoded into PI_SUBAGENT_SPAWNS. */
|
|
85
|
+
spawns?: false | "*" | string[];
|
|
86
|
+
/** JSON-Schema subset the child's final fenced json:result block must satisfy. */
|
|
87
|
+
outputSchema?: Record<string, unknown>;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface TaskResult {
|
|
91
|
+
label: string;
|
|
92
|
+
task: string;
|
|
93
|
+
state: RunState;
|
|
94
|
+
exitCode: number | null;
|
|
95
|
+
signal?: NodeJS.Signals;
|
|
96
|
+
messages: Message[];
|
|
97
|
+
stderr: string;
|
|
98
|
+
usage: UsageStats;
|
|
99
|
+
model?: string;
|
|
100
|
+
routing?: TaskRouting;
|
|
101
|
+
thinking?: TaskSpec["thinking"];
|
|
102
|
+
profile?: TaskProfile;
|
|
103
|
+
/** Backend that produced this result (pi | codex | claude). */
|
|
104
|
+
backend?: BackendName;
|
|
105
|
+
canWrite?: boolean;
|
|
106
|
+
stopReason?: string;
|
|
107
|
+
/** Present when stopReason is a timeout-like outcome. */
|
|
108
|
+
timeoutPhase?: TimeoutPhase;
|
|
109
|
+
errorMessage?: string;
|
|
110
|
+
index?: number;
|
|
111
|
+
outputFile?: string;
|
|
112
|
+
outputMode?: OutputMode;
|
|
113
|
+
worktree?: { cwd: string; branch: string; baseCommit: string; changed: boolean; diffSummary?: string };
|
|
114
|
+
sessionId?: string;
|
|
115
|
+
/** Child process identity (persisted for orphan reclaim). */
|
|
116
|
+
process?: ChildProcessIdentity;
|
|
117
|
+
startedAt?: number;
|
|
118
|
+
/** When the semaphore slot was acquired (runtime clock starts here). */
|
|
119
|
+
acquiredAt?: number;
|
|
120
|
+
endedAt?: number;
|
|
121
|
+
liveText?: string;
|
|
122
|
+
/** Incrementally-built compact transcript (assistant text, tool calls, tool results). */
|
|
123
|
+
transcript?: string;
|
|
124
|
+
/** True when a budget-stopped child wrapped up gracefully in its grace turns. */
|
|
125
|
+
wrappedUp?: boolean;
|
|
126
|
+
/** Set while no protocol activity has been seen for the stall window. */
|
|
127
|
+
stalledSince?: number;
|
|
128
|
+
/** Total attempts including retries (present when > 1). */
|
|
129
|
+
attempts?: number;
|
|
130
|
+
/** Models tried across attempts, in order. */
|
|
131
|
+
attemptedModels?: string[];
|
|
132
|
+
/** Parsed structured result when output_schema was requested and validated. */
|
|
133
|
+
structuredOutput?: unknown;
|
|
134
|
+
/** Validation errors when output_schema was requested but the result failed. */
|
|
135
|
+
structuredError?: string;
|
|
136
|
+
protocol: {
|
|
137
|
+
headerSeen: boolean;
|
|
138
|
+
assistantEndSeen: boolean;
|
|
139
|
+
agentEndSeen: boolean;
|
|
140
|
+
agentSettledSeen: boolean;
|
|
141
|
+
validEvents: number;
|
|
142
|
+
parseErrors: number;
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface RunSnapshot {
|
|
147
|
+
schemaVersion: 1;
|
|
148
|
+
id: string;
|
|
149
|
+
sessionKey: string;
|
|
150
|
+
mode: RunMode;
|
|
151
|
+
state: RunState;
|
|
152
|
+
startedAt: number;
|
|
153
|
+
endedAt?: number;
|
|
154
|
+
taskPreviews: string[];
|
|
155
|
+
summary?: string;
|
|
156
|
+
delivered: boolean;
|
|
157
|
+
/** True when a previous owner was killed on reconcile; resume must not auto-reopen. */
|
|
158
|
+
resumeBlocked?: boolean;
|
|
159
|
+
results: Array<{
|
|
160
|
+
label: string;
|
|
161
|
+
task: string;
|
|
162
|
+
state: RunState;
|
|
163
|
+
exitCode: number | null;
|
|
164
|
+
stopReason?: string;
|
|
165
|
+
timeoutPhase?: TimeoutPhase;
|
|
166
|
+
errorMessage?: string;
|
|
167
|
+
usage: UsageStats;
|
|
168
|
+
model?: string;
|
|
169
|
+
routing?: TaskRouting;
|
|
170
|
+
thinking?: TaskSpec["thinking"];
|
|
171
|
+
profile?: TaskProfile;
|
|
172
|
+
canWrite?: boolean;
|
|
173
|
+
outputFile?: string;
|
|
174
|
+
backend?: BackendName;
|
|
175
|
+
outputMode?: OutputMode;
|
|
176
|
+
worktree?: { cwd: string; branch: string; baseCommit: string; changed: boolean; diffSummary?: string };
|
|
177
|
+
sessionId?: string;
|
|
178
|
+
process?: ChildProcessIdentity;
|
|
179
|
+
finalOutput?: string;
|
|
180
|
+
transcript?: string;
|
|
181
|
+
wrappedUp?: boolean;
|
|
182
|
+
stalledSince?: number;
|
|
183
|
+
attempts?: number;
|
|
184
|
+
attemptedModels?: string[];
|
|
185
|
+
structuredOutput?: unknown;
|
|
186
|
+
structuredError?: string;
|
|
187
|
+
}>;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export interface ToolDetails {
|
|
191
|
+
mode: RunMode;
|
|
192
|
+
results: TaskResult[];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export const emptyUsage = (): UsageStats => ({
|
|
196
|
+
input: 0,
|
|
197
|
+
output: 0,
|
|
198
|
+
cacheRead: 0,
|
|
199
|
+
cacheWrite: 0,
|
|
200
|
+
reasoning: 0,
|
|
201
|
+
cost: 0,
|
|
202
|
+
costInput: 0,
|
|
203
|
+
costOutput: 0,
|
|
204
|
+
costCacheRead: 0,
|
|
205
|
+
costCacheWrite: 0,
|
|
206
|
+
contextTokens: 0,
|
|
207
|
+
turns: 0,
|
|
208
|
+
});
|