@signalridge/pi-workflows 1.4.0 → 1.6.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 +249 -0
- package/README.md +193 -15
- package/package.json +3 -3
- package/skills/workflow-authoring/SKILL.md +23 -7
- package/skills/workflow-authoring/references/capabilities.md +6 -6
- package/skills/workflow-authoring/references/capability-details.md +16 -6
- package/skills/workflow-authoring/references/debugging.md +2 -2
- package/skills/workflow-authoring/references/quality-helpers.md +2 -2
- package/skills/workflow-authoring/references/registry-ownership.md +6 -4
- package/skills/workflow-authoring/references/review.md +6 -2
- package/skills/workflow-authoring/references/runtime.md +3 -3
- package/skills/workflow-authoring/references/specialized-helpers.md +1 -1
- package/skills/workflow-authoring/references/versions.md +1 -1
- package/skills/workflow-patterns/SKILL.md +1 -1
- package/skills/workflow-review/SKILL.md +1 -1
- package/src/builtins.ts +23 -23
- package/src/capabilities.ts +28 -6
- package/src/engine.ts +248 -58
- package/src/index.ts +457 -173
- package/src/journal.ts +278 -253
- package/src/rpc-client.ts +37 -48
- package/src/runtime.ts +429 -54
- package/src/strengths.ts +93 -0
- package/src/ui.ts +29 -4
- package/src/workflow-settings.ts +95 -1
package/src/rpc-client.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import type {
|
|
3
|
+
ManagedRoutingPolicy,
|
|
3
4
|
ManagedSpawnResponse as ProtocolManagedSpawnResponse,
|
|
4
5
|
ManagedTerminalSnapshot as ProtocolManagedTerminalSnapshot,
|
|
5
|
-
WorkflowTier,
|
|
6
6
|
} from "@signalridge/pi-subagents-protocol";
|
|
7
7
|
import {
|
|
8
8
|
PROTOCOL_VERSION,
|
|
9
9
|
parseManagedSpawnResponse,
|
|
10
10
|
parseProtocolPing,
|
|
11
11
|
requiredCapabilitiesMatch,
|
|
12
|
-
workflowTierCapabilityMatch,
|
|
13
12
|
} from "@signalridge/pi-subagents-protocol";
|
|
14
13
|
import type { WorkflowOwner } from "./journal.js";
|
|
15
14
|
|
|
@@ -18,11 +17,8 @@ export interface DispatchTask {
|
|
|
18
17
|
subagent_type: string;
|
|
19
18
|
prompt: string;
|
|
20
19
|
description: string;
|
|
21
|
-
tier
|
|
22
|
-
|
|
23
|
-
model?: string;
|
|
24
|
-
/** Optional thinking suffix/override resolved by pi-subagents. */
|
|
25
|
-
thinking?: "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | "off";
|
|
20
|
+
/** Agent-tier key, from the host's own catalogue. The only model policy here. */
|
|
21
|
+
tier?: string;
|
|
26
22
|
/** Per-call worktree request owned by pi-subagents. */
|
|
27
23
|
isolation?: "worktree";
|
|
28
24
|
/** Forwarded toolset hint (e.g. "web-research") for pi-subagents to augment tools. */
|
|
@@ -105,9 +101,11 @@ function callRpc<T>(
|
|
|
105
101
|
|
|
106
102
|
export const REQUIRED_SUBAGENTS_PROTOCOL = PROTOCOL_VERSION;
|
|
107
103
|
export const PROTOCOL_DIAGNOSTIC =
|
|
108
|
-
|
|
104
|
+
`@signalridge/pi-workflows requires @signalridge/pi-subagents protocol v${PROTOCOL_VERSION} with managedSpawn, lifecycleOwner, ownedStop, childContext, ownedQuiescence, agentTiers, and managedPolicy, plus its Agent-tier routing policy. ` +
|
|
109
105
|
"Install @signalridge/pi-subagents and @signalridge/pi-workflows exactly once; Pi loads both from their configured pi.extensions manifests.";
|
|
110
106
|
|
|
107
|
+
const CAPABILITY_DIAGNOSTIC = `subagents protocol v${PROTOCOL_VERSION} is required, with every capability and an Agent-tier routing policy`;
|
|
108
|
+
|
|
111
109
|
export const CHILD_CONTEXT_QUERY_TIMEOUT_MS = 250;
|
|
112
110
|
|
|
113
111
|
/**
|
|
@@ -169,7 +167,17 @@ export function queryChildSessionContextImmediate(events: WorkflowEventBus): boo
|
|
|
169
167
|
}
|
|
170
168
|
|
|
171
169
|
/** Verify the separately configured pi-subagents package before workflow execution. */
|
|
172
|
-
export
|
|
170
|
+
export interface ManagedProtocolCheck {
|
|
171
|
+
/** The host's Agent-tier catalogue, as of this check. */
|
|
172
|
+
routingPolicy: ManagedRoutingPolicy;
|
|
173
|
+
/** Whole-catalogue identity; used only where a per-tier identity cannot be. */
|
|
174
|
+
routingPolicyFingerprint: string;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export async function checkManagedSpawnProtocol(
|
|
178
|
+
events: WorkflowEventBus,
|
|
179
|
+
signal?: AbortSignal,
|
|
180
|
+
): Promise<ManagedProtocolCheck> {
|
|
173
181
|
const id = requestId();
|
|
174
182
|
const reply = await new Promise<unknown>((resolve, reject) => {
|
|
175
183
|
const replyChannel = `subagents:rpc:ping:reply:${id}`;
|
|
@@ -228,57 +236,40 @@ export async function checkManagedSpawnProtocol(events: WorkflowEventBus, signal
|
|
|
228
236
|
let ping: ReturnType<typeof parseProtocolPing>;
|
|
229
237
|
try {
|
|
230
238
|
ping = parseProtocolPing(reply);
|
|
231
|
-
} catch {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
reply.capabilities.lifecycleOwner !== true ||
|
|
239
|
-
reply.capabilities.ownedStop !== true ||
|
|
240
|
-
reply.capabilities.ownedQuiescence !== true ||
|
|
241
|
-
reply.capabilities.managedPolicy !== true
|
|
242
|
-
) {
|
|
243
|
-
throw new Error(
|
|
244
|
-
`subagents protocol v${REQUIRED_SUBAGENTS_PROTOCOL} with managed spawning, owned stop, owned quiescence, and managed policy capabilities is required`,
|
|
245
|
-
);
|
|
239
|
+
} catch (error: unknown) {
|
|
240
|
+
// Anything shaped like a ping is a peer that is present but not v4-complete,
|
|
241
|
+
// and the actionable answer is the same in every such case: install a
|
|
242
|
+
// matching pair. A reply that is not a ping at all gets its own message,
|
|
243
|
+
// because "upgrade the peer" would be the wrong thing to go do.
|
|
244
|
+
if (!isRecord(reply) || typeof reply.version !== "number") {
|
|
245
|
+
throw new Error("subagents protocol ping did not return a valid version/capability envelope");
|
|
246
246
|
}
|
|
247
|
-
throw new Error(
|
|
247
|
+
throw new Error(`${CAPABILITY_DIAGNOSTIC} (${error instanceof Error ? error.message : String(error)})`);
|
|
248
248
|
}
|
|
249
|
+
// Every v4 capability is required, so one check covers them all. The parser
|
|
250
|
+
// has already rejected a ping without a well-formed routing policy.
|
|
249
251
|
if (ping.version < REQUIRED_SUBAGENTS_PROTOCOL || !requiredCapabilitiesMatch(ping.capabilities)) {
|
|
250
|
-
throw new Error(
|
|
251
|
-
`subagents protocol v${REQUIRED_SUBAGENTS_PROTOCOL} with managed spawning, owned stop, and owned quiescence capability is required`,
|
|
252
|
-
);
|
|
253
|
-
}
|
|
254
|
-
if (!workflowTierCapabilityMatch(ping.capabilities)) {
|
|
255
|
-
throw new Error("subagents workflow tier capability is required before tiered managed spawning");
|
|
256
|
-
}
|
|
257
|
-
if (ping.capabilities.managedPolicy !== true) {
|
|
258
|
-
throw new Error("subagents managed policy capability is required before policy-bearing managed spawning");
|
|
252
|
+
throw new Error(CAPABILITY_DIAGNOSTIC);
|
|
259
253
|
}
|
|
254
|
+
return {
|
|
255
|
+
routingPolicy: ping.routingPolicy.policy,
|
|
256
|
+
routingPolicyFingerprint: ping.routingPolicy.fingerprint,
|
|
257
|
+
};
|
|
260
258
|
}
|
|
261
259
|
|
|
262
260
|
export type ManagedTerminalSnapshot = ProtocolManagedTerminalSnapshot;
|
|
263
261
|
export type ManagedSpawnResponse = ProtocolManagedSpawnResponse;
|
|
264
262
|
|
|
265
263
|
export interface ManagedSpawnClient {
|
|
266
|
-
/**
|
|
267
|
-
/**
|
|
268
|
-
* The fourth argument is the current attempt for protocol-v3 clients. The
|
|
269
|
-
* optional fifth argument is retained only for old in-process test/fixture
|
|
270
|
-
* clients that used the former context, attemptId shape; it is never a
|
|
271
|
-
* runtime context and is not sent over RPC.
|
|
272
|
-
*/
|
|
264
|
+
/** Managed spawn returns a structured response. */
|
|
273
265
|
spawn(
|
|
274
266
|
task: DispatchTask,
|
|
275
267
|
runId: string,
|
|
276
268
|
nodeId: string,
|
|
277
269
|
attemptId?: string,
|
|
278
|
-
legacyAttemptId?: string,
|
|
279
270
|
signal?: AbortSignal,
|
|
280
271
|
): Promise<ManagedSpawnResponse | string>;
|
|
281
|
-
/** Unscoped
|
|
272
|
+
/** Unscoped stop for non-managed callers. */
|
|
282
273
|
stop(agentId: string): Promise<void>;
|
|
283
274
|
/** Owner-scoped v3 stop used by workflow lifecycle operations. */
|
|
284
275
|
stopOwned?(agentId: string, owner: WorkflowOwner): Promise<void>;
|
|
@@ -290,8 +281,8 @@ export interface ManagedSpawnClient {
|
|
|
290
281
|
timeoutMs?: number,
|
|
291
282
|
owners?: WorkflowOwner[],
|
|
292
283
|
): Promise<{ settled: boolean; pending: string[] }>;
|
|
293
|
-
/**
|
|
294
|
-
checkProtocol?: () => Promise<
|
|
284
|
+
/** Fresh capability and routing-policy check; workflow execution remains event-bus-only. */
|
|
285
|
+
checkProtocol?: () => Promise<ManagedProtocolCheck>;
|
|
295
286
|
}
|
|
296
287
|
|
|
297
288
|
/** Event-bus-only client for the additive pi-subagents managed protocol. */
|
|
@@ -320,7 +311,7 @@ export function createManagedSpawnClient(
|
|
|
320
311
|
* error for the same key with a different fingerprint. Same key + same
|
|
321
312
|
* fingerprint still reuses the persisted tombstone (per-call cache).
|
|
322
313
|
*/
|
|
323
|
-
async spawn(task, runId, nodeId, attemptId,
|
|
314
|
+
async spawn(task, runId, nodeId, attemptId, signal) {
|
|
324
315
|
const effectiveAttemptId = attemptId ?? `attempt-1`;
|
|
325
316
|
const spawnKey = `${runId}/${nodeId}/${effectiveAttemptId}`;
|
|
326
317
|
const requestSignal =
|
|
@@ -339,8 +330,6 @@ export function createManagedSpawnClient(
|
|
|
339
330
|
...(task.toolset === undefined ? {} : { toolset: task.toolset }),
|
|
340
331
|
...(task.thread === undefined ? {} : { thread: task.thread }),
|
|
341
332
|
...(task.excludeTools === undefined ? {} : { excludeTools: task.excludeTools }),
|
|
342
|
-
...(task.model === undefined ? {} : { model: task.model }),
|
|
343
|
-
...(task.thinking === undefined ? {} : { thinking: task.thinking }),
|
|
344
333
|
...(task.isolation === undefined ? {} : { isolation: task.isolation }),
|
|
345
334
|
owner: { extension: "pi-workflows", runId, nodeId, attemptId: effectiveAttemptId },
|
|
346
335
|
},
|