@narumitw/pi-subagents 1.0.0 → 1.0.2
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/README.md +12 -4
- package/package.json +7 -7
- package/src/automation-registration.ts +137 -0
- package/src/automation-tool.ts +40 -0
- package/src/automation.ts +6 -156
- package/src/cached-module-loader.ts +18 -0
- package/src/config-registration.ts +114 -0
- package/src/config-ui.ts +2 -2
- package/src/consult-registration.ts +132 -0
- package/src/consult-render.ts +1 -1
- package/src/consult-tool.ts +95 -0
- package/src/consult.ts +37 -204
- package/src/create-stateful-transport.ts +106 -18
- package/src/inspect-registration.ts +64 -0
- package/src/inspect-tool.ts +43 -0
- package/src/inspect.ts +7 -69
- package/src/panel-planning.ts +2 -2
- package/src/panel-presets.ts +3 -0
- package/src/params.ts +2 -2
- package/src/pi-args.ts +41 -0
- package/src/render.ts +4 -47
- package/src/runner-outcome.ts +31 -0
- package/src/runner.ts +18 -79
- package/src/settings.ts +4 -1
- package/src/stateful.ts +254 -98
- package/src/subagents.ts +82 -29
- package/src/usage-format.ts +42 -0
- package/src/verified-execution-contract.ts +3 -31
- package/src/verified-execution-schema.ts +32 -0
package/src/subagents.ts
CHANGED
|
@@ -21,11 +21,24 @@ import type {
|
|
|
21
21
|
DelegationCwdPolicy,
|
|
22
22
|
SubagentSettings,
|
|
23
23
|
} from "./agents/types.js";
|
|
24
|
-
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
type AutomationRegistrationDependencies,
|
|
26
|
+
registerSubagentAutomation,
|
|
27
|
+
} from "./automation-registration.js";
|
|
28
|
+
import { cachedModuleLoader, throwIfAborted } from "./cached-module-loader.js";
|
|
29
|
+
import {
|
|
30
|
+
type ConfigRegistrationDependencies,
|
|
31
|
+
registerSubagentConfigCommand,
|
|
32
|
+
registerSubagentConfigLifecycle,
|
|
33
|
+
} from "./config-registration.js";
|
|
34
|
+
import {
|
|
35
|
+
type ConsultRegistrationDependencies,
|
|
36
|
+
registerSubagentConsult,
|
|
37
|
+
} from "./consult-registration.js";
|
|
38
|
+
import {
|
|
39
|
+
type InspectRegistrationDependencies,
|
|
40
|
+
registerSubagentInspect,
|
|
41
|
+
} from "./inspect-registration.js";
|
|
29
42
|
import { MAX_BLOCKING_PARALLEL_CONCURRENCY } from "./limits.js";
|
|
30
43
|
import { SubagentParams } from "./params.js";
|
|
31
44
|
import { renderSubagentCall, renderSubagentResult } from "./render.js";
|
|
@@ -40,17 +53,34 @@ import {
|
|
|
40
53
|
resolveBlockingMaxParallelTasks,
|
|
41
54
|
} from "./settings.js";
|
|
42
55
|
import { registerStatefulSubagents } from "./stateful.js";
|
|
56
|
+
import type { SubagentTransport } from "./transport.js";
|
|
57
|
+
|
|
58
|
+
type BlockingExecutionModule = Pick<typeof import("./execution.js"), "executeSubagent">;
|
|
59
|
+
|
|
60
|
+
export interface SubagentsDependencies {
|
|
61
|
+
loadBlockingExecution?: () => Promise<BlockingExecutionModule>;
|
|
62
|
+
loadStatefulTransport?: () => Promise<SubagentTransport>;
|
|
63
|
+
automation?: AutomationRegistrationDependencies;
|
|
64
|
+
config?: ConfigRegistrationDependencies;
|
|
65
|
+
consult?: ConsultRegistrationDependencies;
|
|
66
|
+
inspect?: InspectRegistrationDependencies;
|
|
67
|
+
}
|
|
43
68
|
|
|
44
|
-
export default function (pi: ExtensionAPI) {
|
|
69
|
+
export default function (pi: ExtensionAPI, dependencies: SubagentsDependencies = {}) {
|
|
70
|
+
const loadBlockingExecution = cachedModuleLoader(
|
|
71
|
+
dependencies.loadBlockingExecution ?? (() => import("./execution.js")),
|
|
72
|
+
);
|
|
45
73
|
const configOwner = registerSubagentConfigLifecycle(pi);
|
|
46
74
|
const settings = readSubagentSettings();
|
|
47
75
|
let currentSettings: SubagentSettings | undefined = settings;
|
|
48
76
|
let currentCatalog = "";
|
|
49
77
|
const blockingEnabled = settings?.blocking?.enabled !== false;
|
|
50
78
|
const refreshBlockingCatalog = blockingEnabled
|
|
51
|
-
? registerBlockingSubagent(pi, () => currentSettings)
|
|
79
|
+
? registerBlockingSubagent(pi, () => currentSettings, loadBlockingExecution)
|
|
52
80
|
: () => undefined;
|
|
53
|
-
if (blockingEnabled)
|
|
81
|
+
if (blockingEnabled) {
|
|
82
|
+
registerSubagentAutomation(pi, { getSettings: () => currentSettings }, dependencies.automation);
|
|
83
|
+
}
|
|
54
84
|
let refreshStatefulCatalog: (catalog: string) => void = () => undefined;
|
|
55
85
|
let refreshConsultCatalog: (catalog: string) => void = () => undefined;
|
|
56
86
|
|
|
@@ -78,6 +108,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
78
108
|
blockingEnabled,
|
|
79
109
|
settings: settings?.stateful,
|
|
80
110
|
getSettings: () => currentSettings,
|
|
111
|
+
loadTransport: dependencies.loadStatefulTransport,
|
|
81
112
|
});
|
|
82
113
|
refreshStatefulCatalog = statefulRuntime.setAgentCatalog;
|
|
83
114
|
const getBlockingEnabled = () => blockingEnabled;
|
|
@@ -88,18 +119,24 @@ export default function (pi: ExtensionAPI) {
|
|
|
88
119
|
currentSettings?.cwdPolicy?.consultation ?? DEFAULT_CONSULTATION_CWD_POLICY;
|
|
89
120
|
const getDelegationCwdPolicy = () =>
|
|
90
121
|
currentSettings?.cwdPolicy?.delegation ?? DEFAULT_DELEGATION_CWD_POLICY;
|
|
91
|
-
registerSubagentInspect(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
122
|
+
registerSubagentInspect(
|
|
123
|
+
pi,
|
|
124
|
+
{
|
|
125
|
+
...statefulRuntime,
|
|
126
|
+
getBlockingEnabled,
|
|
127
|
+
getMaxParallelTasks,
|
|
128
|
+
getConsultResourcePolicy,
|
|
129
|
+
getConsultationCwdPolicy,
|
|
130
|
+
getDelegationCwdPolicy,
|
|
131
|
+
},
|
|
132
|
+
dependencies.inspect,
|
|
133
|
+
);
|
|
99
134
|
if (blockingEnabled) {
|
|
100
|
-
refreshConsultCatalog = registerSubagentConsult(
|
|
101
|
-
|
|
102
|
-
|
|
135
|
+
refreshConsultCatalog = registerSubagentConsult(
|
|
136
|
+
pi,
|
|
137
|
+
{ getSettings: () => currentSettings },
|
|
138
|
+
dependencies.consult,
|
|
139
|
+
);
|
|
103
140
|
}
|
|
104
141
|
registerSubagentConfigCommand(
|
|
105
142
|
pi,
|
|
@@ -155,12 +192,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
155
192
|
},
|
|
156
193
|
},
|
|
157
194
|
configOwner,
|
|
195
|
+
dependencies.config,
|
|
158
196
|
);
|
|
159
197
|
}
|
|
160
198
|
|
|
161
199
|
function registerBlockingSubagent(
|
|
162
200
|
pi: ExtensionAPI,
|
|
163
201
|
getSettings: () => SubagentSettings | undefined,
|
|
202
|
+
loadExecution: () => Promise<BlockingExecutionModule>,
|
|
164
203
|
): (catalog: string) => void {
|
|
165
204
|
let catalog = "";
|
|
166
205
|
const activeControllers = new Set<AbortController>();
|
|
@@ -212,14 +251,28 @@ function registerBlockingSubagent(
|
|
|
212
251
|
const effectiveSignal = signal
|
|
213
252
|
? AbortSignal.any([signal, lifecycleController.signal])
|
|
214
253
|
: lifecycleController.signal;
|
|
215
|
-
const work =
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
254
|
+
const work = (async () => {
|
|
255
|
+
throwIfAborted(effectiveSignal, "Blocking subagent execution was cancelled");
|
|
256
|
+
let executionModule: BlockingExecutionModule;
|
|
257
|
+
try {
|
|
258
|
+
executionModule = await loadExecution();
|
|
259
|
+
} catch (error) {
|
|
260
|
+
throwIfAborted(
|
|
261
|
+
effectiveSignal,
|
|
262
|
+
"Blocking subagent execution was cancelled while loading",
|
|
263
|
+
);
|
|
264
|
+
throw error;
|
|
265
|
+
}
|
|
266
|
+
throwIfAborted(effectiveSignal, "Blocking subagent execution was cancelled while loading");
|
|
267
|
+
return executionModule.executeSubagent(
|
|
268
|
+
toolCallId,
|
|
269
|
+
params,
|
|
270
|
+
effectiveSignal,
|
|
271
|
+
onUpdate,
|
|
272
|
+
ctx,
|
|
273
|
+
getSettings(),
|
|
274
|
+
);
|
|
275
|
+
})();
|
|
223
276
|
activeWork.add(work);
|
|
224
277
|
try {
|
|
225
278
|
return await work;
|
|
@@ -256,8 +309,7 @@ function appendAgentCatalog(baseDescription: string, catalog: string): string {
|
|
|
256
309
|
}
|
|
257
310
|
|
|
258
311
|
export { parsePositiveInteger } from "./execution/runtime-policy.js";
|
|
259
|
-
export {
|
|
260
|
-
export { buildPiArgs } from "./runner.js";
|
|
312
|
+
export { buildPiArgs } from "./pi-args.js";
|
|
261
313
|
export {
|
|
262
314
|
DEFAULT_CONSULT_RESOURCE_POLICY,
|
|
263
315
|
DEFAULT_CONSULTATION_CWD_POLICY,
|
|
@@ -286,3 +338,4 @@ export {
|
|
|
286
338
|
updateDelegationWorkflowSetting,
|
|
287
339
|
updateStatefulLimitSetting,
|
|
288
340
|
} from "./settings.js";
|
|
341
|
+
export { formatTokens, formatUsageStats } from "./usage-format.js";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { SubagentThinkingLevel } from "./agents/types.js";
|
|
2
|
+
import { safeLine } from "./render-common.js";
|
|
3
|
+
|
|
4
|
+
export function formatTokens(count: number): string {
|
|
5
|
+
if (count < 1000) return count.toString();
|
|
6
|
+
if (count < 10000) return `${(count / 1000).toFixed(1)}k`;
|
|
7
|
+
if (count < 1000000) return `${Math.round(count / 1000)}k`;
|
|
8
|
+
return `${(count / 1000000).toFixed(1)}M`;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function formatUsageStats(
|
|
12
|
+
usage: {
|
|
13
|
+
input: number;
|
|
14
|
+
output: number;
|
|
15
|
+
cacheRead: number;
|
|
16
|
+
cacheWrite: number;
|
|
17
|
+
cost: number;
|
|
18
|
+
contextTokens?: number;
|
|
19
|
+
turns?: number;
|
|
20
|
+
},
|
|
21
|
+
model?: string,
|
|
22
|
+
thinkingLevel?: SubagentThinkingLevel,
|
|
23
|
+
actualProvider?: string,
|
|
24
|
+
actualModel?: string,
|
|
25
|
+
): string {
|
|
26
|
+
const parts: string[] = [];
|
|
27
|
+
if (usage.turns) parts.push(`${usage.turns} turn${usage.turns > 1 ? "s" : ""}`);
|
|
28
|
+
if (usage.input) parts.push(`↑${formatTokens(usage.input)}`);
|
|
29
|
+
if (usage.output) parts.push(`↓${formatTokens(usage.output)}`);
|
|
30
|
+
if (usage.cacheRead) parts.push(`R${formatTokens(usage.cacheRead)}`);
|
|
31
|
+
if (usage.cacheWrite) parts.push(`W${formatTokens(usage.cacheWrite)}`);
|
|
32
|
+
if (usage.cost) parts.push(`$${usage.cost.toFixed(4)}`);
|
|
33
|
+
if (usage.contextTokens && usage.contextTokens > 0)
|
|
34
|
+
parts.push(`ctx:${formatTokens(usage.contextTokens)}`);
|
|
35
|
+
const safeProvider = actualProvider ? safeLine(actualProvider, "", 256) : undefined;
|
|
36
|
+
const safeModel = actualModel ? safeLine(actualModel, "", 256) : undefined;
|
|
37
|
+
const actual =
|
|
38
|
+
safeProvider && safeModel ? `${safeProvider}/${safeModel}` : (safeModel ?? safeProvider);
|
|
39
|
+
if (actual ?? model) parts.push(actual ?? safeLine(model, "", 256));
|
|
40
|
+
if (thinkingLevel) parts.push(`requested-thinking:${safeLine(thinkingLevel, "", 128)}`);
|
|
41
|
+
return parts.join(" ");
|
|
42
|
+
}
|
|
@@ -1,41 +1,13 @@
|
|
|
1
|
-
import { StringEnum } from "@earendil-works/pi-ai";
|
|
2
|
-
import { type Static, Type } from "typebox";
|
|
3
1
|
import { normalizeDelegationContract } from "./delegation-contract.js";
|
|
4
2
|
import {
|
|
5
3
|
type VerificationCheckRequest,
|
|
6
4
|
validateVerificationChecks,
|
|
7
5
|
} from "./verification-harness.js";
|
|
6
|
+
import type { VerifiedExecutionContract } from "./verified-execution-schema.js";
|
|
8
7
|
import type { ResolvedWorkflowTask } from "./workflow-planning.js";
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
id: Type.String({
|
|
13
|
-
minLength: 1,
|
|
14
|
-
maxLength: 256,
|
|
15
|
-
pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$",
|
|
16
|
-
}),
|
|
17
|
-
command: StringEnum(["git", "node", "npm", "npx"] as const),
|
|
18
|
-
args: Type.Optional(Type.Array(Type.String({ maxLength: 4096 }), { maxItems: 64 })),
|
|
19
|
-
cwd: Type.Optional(Type.String({ minLength: 1, maxLength: 4096 })),
|
|
20
|
-
timeoutMs: Type.Optional(Type.Integer({ minimum: 1, maximum: 600_000 })),
|
|
21
|
-
},
|
|
22
|
-
{ additionalProperties: false },
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
export const VerifiedExecutionContractSchema = Type.Object(
|
|
26
|
-
{
|
|
27
|
-
verifierAgent: Type.String({ minLength: 1, maxLength: 256 }),
|
|
28
|
-
maxReworkCycles: Type.Optional(Type.Integer({ minimum: 0, maximum: 1, default: 1 })),
|
|
29
|
-
checks: Type.Optional(Type.Array(VerificationCheckSchema, { maxItems: 32 })),
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
additionalProperties: false,
|
|
33
|
-
description:
|
|
34
|
-
"Explicitly gate mutating workflow success on executor-owned deterministic checks, one least-authority independent verifier, exact submitted-state identity, and managed integration acceptance.",
|
|
35
|
-
},
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
export type VerifiedExecutionContract = Static<typeof VerifiedExecutionContractSchema>;
|
|
9
|
+
export type { VerifiedExecutionContract } from "./verified-execution-schema.js";
|
|
10
|
+
export { VerifiedExecutionContractSchema } from "./verified-execution-schema.js";
|
|
39
11
|
|
|
40
12
|
export interface PreparedVerifiedWorkflow {
|
|
41
13
|
tasks: ResolvedWorkflowTask[];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { StringEnum } from "@earendil-works/pi-ai";
|
|
2
|
+
import { type Static, Type } from "typebox";
|
|
3
|
+
|
|
4
|
+
const VerificationCheckSchema = Type.Object(
|
|
5
|
+
{
|
|
6
|
+
id: Type.String({
|
|
7
|
+
minLength: 1,
|
|
8
|
+
maxLength: 256,
|
|
9
|
+
pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$",
|
|
10
|
+
}),
|
|
11
|
+
command: StringEnum(["git", "node", "npm", "npx"] as const),
|
|
12
|
+
args: Type.Optional(Type.Array(Type.String({ maxLength: 4096 }), { maxItems: 64 })),
|
|
13
|
+
cwd: Type.Optional(Type.String({ minLength: 1, maxLength: 4096 })),
|
|
14
|
+
timeoutMs: Type.Optional(Type.Integer({ minimum: 1, maximum: 600_000 })),
|
|
15
|
+
},
|
|
16
|
+
{ additionalProperties: false },
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
export const VerifiedExecutionContractSchema = Type.Object(
|
|
20
|
+
{
|
|
21
|
+
verifierAgent: Type.String({ minLength: 1, maxLength: 256 }),
|
|
22
|
+
maxReworkCycles: Type.Optional(Type.Integer({ minimum: 0, maximum: 1, default: 1 })),
|
|
23
|
+
checks: Type.Optional(Type.Array(VerificationCheckSchema, { maxItems: 32 })),
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
additionalProperties: false,
|
|
27
|
+
description:
|
|
28
|
+
"Explicitly gate mutating workflow success on executor-owned deterministic checks, one least-authority independent verifier, exact submitted-state identity, and managed integration acceptance.",
|
|
29
|
+
},
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
export type VerifiedExecutionContract = Static<typeof VerifiedExecutionContractSchema>;
|