@llblab/pi-actors 0.14.3 → 0.15.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/AGENTS.md +5 -1
- package/BACKLOG.md +18 -32
- package/CHANGELOG.md +20 -0
- package/README.md +24 -20
- package/docs/actor-messages.md +1 -1
- package/docs/async-runs.md +4 -4
- package/docs/command-templates.md +11 -11
- package/docs/recipe-library.md +7 -3
- package/docs/task-first-recipes.md +44 -43
- package/docs/template-recipes.md +7 -2
- package/docs/tool-registry.md +7 -5
- package/lib/actor-messages.ts +20 -7
- package/lib/async-runs.ts +25 -12
- package/lib/command-templates.ts +6 -1
- package/lib/config.ts +2 -2
- package/lib/execution.ts +9 -5
- package/lib/observability.ts +20 -10
- package/lib/prompts.ts +13 -20
- package/lib/tools.ts +196 -64
- package/package.json +17 -9
- package/recipes/coordinator-locker.json +46 -0
- package/recipes/music-player.json +16 -2
- package/recipes/pipeline-architect-coordinator.json +11 -3
- package/recipes/pipeline-artifact-bundle.json +12 -3
- package/recipes/pipeline-artifact-report.json +9 -3
- package/recipes/pipeline-artifact-write.json +9 -3
- package/recipes/pipeline-async-run-ops.json +18 -9
- package/recipes/pipeline-checkpoint-continuation.json +14 -3
- package/recipes/pipeline-development-tasking.json +12 -3
- package/recipes/pipeline-docs-maintenance.json +12 -3
- package/recipes/pipeline-media-library.json +12 -3
- package/recipes/pipeline-quorum-review.json +12 -9
- package/recipes/pipeline-release-readiness.json +27 -9
- package/recipes/pipeline-release-summary.json +89 -0
- package/recipes/pipeline-repo-health.json +12 -3
- package/recipes/pipeline-research-synthesis.json +11 -3
- package/recipes/pipeline-review-readiness.json +12 -6
- package/recipes/subagent-artifact.json +9 -3
- package/recipes/subagent-checkpoint.json +10 -3
- package/recipes/subagent-conflict-report.json +11 -3
- package/recipes/subagent-contradiction-map.json +11 -3
- package/recipes/subagent-critic.json +11 -3
- package/recipes/subagent-evidence-map.json +11 -3
- package/recipes/subagent-followup.json +10 -3
- package/recipes/subagent-judge.json +11 -3
- package/recipes/subagent-merge.json +11 -3
- package/recipes/subagent-message.json +8 -3
- package/recipes/subagent-normalize.json +11 -3
- package/recipes/subagent-plan.json +11 -3
- package/recipes/subagent-prompt.json +10 -3
- package/recipes/subagent-quorum.json +10 -7
- package/recipes/subagent-review-coordinator.json +14 -6
- package/recipes/subagent-review.json +11 -3
- package/recipes/subagent-task-card.json +11 -3
- package/recipes/subagent-tools.json +10 -3
- package/recipes/subagent-verify.json +11 -3
- package/recipes/subagents-prompts.json +10 -3
- package/recipes/utility-coordinator-lock-snapshot.json +14 -0
- package/recipes/utility-run-ops-snapshot.json +3 -3
- package/recipes/utility-skill-summary.json +14 -0
- package/scripts/coordinator-locker.mjs +272 -0
- package/scripts/music-player.mjs +2 -1
- package/scripts/recipe-utils.mjs +239 -81
- package/scripts/validate-recipe.mjs +28 -10
- package/skills/actors/SKILL.md +283 -0
- package/skills/swarm/SKILL.md +451 -0
- package/skills/swarm/references/development-swarm.md +596 -0
package/lib/tools.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* Owns generated runtime tool schemas and the register_tool management tool schema
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { RegisteredTool } from "./config.ts";
|
|
8
7
|
import * as ActorMessages from "./actor-messages.ts";
|
|
9
8
|
import * as AsyncRuns from "./async-runs.ts";
|
|
10
9
|
import * as CommandTemplates from "./command-templates.ts";
|
|
10
|
+
import type { RegisteredTool } from "./config.ts";
|
|
11
11
|
import * as Execution from "./execution.ts";
|
|
12
12
|
import * as Prompts from "./prompts.ts";
|
|
13
13
|
import * as RecipeReferences from "./recipe-references.ts";
|
|
@@ -86,8 +86,7 @@ function sampleValueForArg(
|
|
|
86
86
|
function shouldAddRuntimeToolUsageHint(error: unknown): boolean {
|
|
87
87
|
const message = error instanceof Error ? error.message : String(error);
|
|
88
88
|
return (
|
|
89
|
-
/^Argument \S+ must /.test(message) ||
|
|
90
|
-
/^Missing .* value: /.test(message)
|
|
89
|
+
/^Argument \S+ must /.test(message) || /^Missing .* value: /.test(message)
|
|
91
90
|
);
|
|
92
91
|
}
|
|
93
92
|
|
|
@@ -176,16 +175,15 @@ function compactAsyncRunStatus(value: unknown): string {
|
|
|
176
175
|
return `\n${tokens.join(" ")}`;
|
|
177
176
|
}
|
|
178
177
|
|
|
179
|
-
function
|
|
180
|
-
if (
|
|
181
|
-
return `\n${
|
|
182
|
-
.map((
|
|
178
|
+
function compactRunMessages(messages: AsyncRuns.RunOutboxEvent[]): string {
|
|
179
|
+
if (messages.length === 0) return "\n(no actor messages)";
|
|
180
|
+
return `\n${messages
|
|
181
|
+
.map((message) =>
|
|
183
182
|
[
|
|
184
|
-
`run=${
|
|
185
|
-
`
|
|
186
|
-
`level=${
|
|
187
|
-
`
|
|
188
|
-
`summary=${event.summary.replaceAll(/\s+/g, "_")}`,
|
|
183
|
+
`run=${message.run}`,
|
|
184
|
+
`type=${message.event}`,
|
|
185
|
+
`level=${message.level}`,
|
|
186
|
+
`summary=${message.summary.replaceAll(/\s+/g, "_")}`,
|
|
189
187
|
].join(" "),
|
|
190
188
|
)
|
|
191
189
|
.join("\n")}`;
|
|
@@ -209,10 +207,16 @@ function compactActorFiles(status: Record<string, unknown>): string {
|
|
|
209
207
|
return `\nrun=${run}${artifactText}${files.length ? ` files=${files.join(",")}` : ""}`;
|
|
210
208
|
}
|
|
211
209
|
|
|
212
|
-
function compactSessionRuns(
|
|
210
|
+
function compactSessionRuns(
|
|
211
|
+
session: string,
|
|
212
|
+
runs: Array<Record<string, unknown>>,
|
|
213
|
+
): string {
|
|
213
214
|
if (runs.length === 0) return `\nsession=${session} runs=0`;
|
|
214
215
|
return `\nsession=${session} runs=${runs.length}\n${runs
|
|
215
|
-
.map(
|
|
216
|
+
.map(
|
|
217
|
+
(run) =>
|
|
218
|
+
`run=${String(run.run ?? "")} status=${String(run.status ?? "")}${run.recipe ? ` recipe=${String(run.recipe)}` : ""}`,
|
|
219
|
+
)
|
|
216
220
|
.join("\n")}`;
|
|
217
221
|
}
|
|
218
222
|
|
|
@@ -236,7 +240,7 @@ function compactActorMessageResult(
|
|
|
236
240
|
];
|
|
237
241
|
if (result.bytes !== undefined) tokens.push(`bytes=${String(result.bytes)}`);
|
|
238
242
|
if (result.control) tokens.push(`control=${String(result.control)}`);
|
|
239
|
-
if (result.outbox) tokens.push(`
|
|
243
|
+
if (result.outbox) tokens.push(`messages=${String(result.outbox)}`);
|
|
240
244
|
if (result.tool) tokens.push(`tool=${String(result.tool)}`);
|
|
241
245
|
if (result.stopped === true) tokens.push("stopped=true");
|
|
242
246
|
if (result.signal) tokens.push(`signal=${String(result.signal)}`);
|
|
@@ -309,15 +313,23 @@ function messageBodyToRunLine(message: ActorMessages.ActorMessage): string {
|
|
|
309
313
|
return JSON.stringify(message.body);
|
|
310
314
|
}
|
|
311
315
|
|
|
312
|
-
function messageBodyToToolParams(
|
|
313
|
-
|
|
316
|
+
function messageBodyToToolParams(
|
|
317
|
+
message: ActorMessages.ActorMessage,
|
|
318
|
+
): Record<string, unknown> {
|
|
319
|
+
if (
|
|
320
|
+
message.body &&
|
|
321
|
+
typeof message.body === "object" &&
|
|
322
|
+
!Array.isArray(message.body)
|
|
323
|
+
) {
|
|
314
324
|
return message.body as Record<string, unknown>;
|
|
315
325
|
}
|
|
316
326
|
if (message.body === undefined) return {};
|
|
317
327
|
return { input: message.body };
|
|
318
328
|
}
|
|
319
329
|
|
|
320
|
-
function runIdFromActorAddress(
|
|
330
|
+
function runIdFromActorAddress(
|
|
331
|
+
address: string | undefined,
|
|
332
|
+
): string | undefined {
|
|
321
333
|
if (!address) return undefined;
|
|
322
334
|
const parsed = ActorMessages.parseActorAddress(address);
|
|
323
335
|
if (parsed.kind !== "run" || !parsed.value) {
|
|
@@ -336,10 +348,18 @@ export function createSpawnToolDefinition<
|
|
|
336
348
|
"Create an addressable actor from a recipe file or inline command template. Currently spawns run:<id> actors backed by async runs.",
|
|
337
349
|
parameters: objectSchema(
|
|
338
350
|
{
|
|
339
|
-
artifacts: looseObjectSchema(
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
351
|
+
artifacts: looseObjectSchema(
|
|
352
|
+
"Optional named artifact paths for the spawned actor.",
|
|
353
|
+
),
|
|
354
|
+
as: stringSchema(
|
|
355
|
+
"Optional actor address for the spawned run, e.g. run:<id>.",
|
|
356
|
+
),
|
|
357
|
+
file: stringSchema(
|
|
358
|
+
"Optional template recipe JSON file. Bare names resolve under ~/.pi/agent/recipes.",
|
|
359
|
+
),
|
|
360
|
+
recipe: stringSchema(
|
|
361
|
+
"Alias for file; template recipe JSON file/name to spawn.",
|
|
362
|
+
),
|
|
343
363
|
state_dir: stringSchema("Optional explicit run state directory."),
|
|
344
364
|
template: unionSchema([
|
|
345
365
|
stringSchema("Inline command template string"),
|
|
@@ -348,7 +368,9 @@ export function createSpawnToolDefinition<
|
|
|
348
368
|
"Inline command-template object with flags such as parallel, repeat, retry, failure, and nested template.",
|
|
349
369
|
),
|
|
350
370
|
]),
|
|
351
|
-
values: looseObjectSchema(
|
|
371
|
+
values: looseObjectSchema(
|
|
372
|
+
"Runtime placeholder values passed to the actor.",
|
|
373
|
+
),
|
|
352
374
|
verbose: booleanSchema("Return full JSON instead of compact text."),
|
|
353
375
|
},
|
|
354
376
|
[],
|
|
@@ -366,13 +388,21 @@ export function createSpawnToolDefinition<
|
|
|
366
388
|
);
|
|
367
389
|
const meta = AsyncRuns.startRun(
|
|
368
390
|
{
|
|
369
|
-
file:
|
|
391
|
+
file:
|
|
392
|
+
typeof input.file === "string"
|
|
393
|
+
? input.file
|
|
394
|
+
: typeof input.recipe === "string"
|
|
395
|
+
? input.recipe
|
|
396
|
+
: undefined,
|
|
370
397
|
ownerId: getRunOwnerId(ctx),
|
|
371
398
|
run_id: runId,
|
|
372
|
-
state_dir:
|
|
399
|
+
state_dir:
|
|
400
|
+
typeof input.state_dir === "string" ? input.state_dir : undefined,
|
|
373
401
|
template: input.template as AsyncRuns.AsyncRunStartParams["template"],
|
|
374
402
|
values: asRecord(input.values),
|
|
375
|
-
...(input.artifacts &&
|
|
403
|
+
...(input.artifacts &&
|
|
404
|
+
typeof input.artifacts === "object" &&
|
|
405
|
+
!Array.isArray(input.artifacts)
|
|
376
406
|
? { artifacts: input.artifacts as Record<string, string> }
|
|
377
407
|
: {}),
|
|
378
408
|
},
|
|
@@ -382,7 +412,11 @@ export function createSpawnToolDefinition<
|
|
|
382
412
|
content: [
|
|
383
413
|
{
|
|
384
414
|
type: "text" as const,
|
|
385
|
-
text: maybeJsonText(
|
|
415
|
+
text: maybeJsonText(
|
|
416
|
+
meta,
|
|
417
|
+
input.verbose === true,
|
|
418
|
+
compactAsyncRunStatus(meta),
|
|
419
|
+
),
|
|
386
420
|
},
|
|
387
421
|
],
|
|
388
422
|
details: meta,
|
|
@@ -396,22 +430,31 @@ export interface InspectToolDeps<TContext = unknown> {
|
|
|
396
430
|
}
|
|
397
431
|
|
|
398
432
|
function getContextSessionId(ctx: unknown): string | undefined {
|
|
399
|
-
return (
|
|
433
|
+
return (
|
|
434
|
+
ctx as AsyncRunToolContext | undefined
|
|
435
|
+
)?.sessionManager?.getSessionId?.();
|
|
400
436
|
}
|
|
401
437
|
|
|
402
438
|
function requireContextSessionId(ctx: unknown, actor: string): string {
|
|
403
439
|
const sessionId = getContextSessionId(ctx);
|
|
404
440
|
if (!sessionId) {
|
|
405
|
-
throw new Error(
|
|
441
|
+
throw new Error(
|
|
442
|
+
`${actor} requires a current coordinator session; use session:<id> or session:all for explicit session inventory.`,
|
|
443
|
+
);
|
|
406
444
|
}
|
|
407
445
|
return sessionId;
|
|
408
446
|
}
|
|
409
447
|
|
|
410
|
-
function assertRunAccessibleToContext(
|
|
448
|
+
function assertRunAccessibleToContext(
|
|
449
|
+
runId: string,
|
|
450
|
+
ctx: unknown,
|
|
451
|
+
): Record<string, unknown> {
|
|
411
452
|
const status = AsyncRuns.getRunStatus(runId);
|
|
412
453
|
const sessionId = getContextSessionId(ctx);
|
|
413
454
|
if (sessionId && status.ownerId && status.ownerId !== sessionId) {
|
|
414
|
-
throw new Error(
|
|
455
|
+
throw new Error(
|
|
456
|
+
`run:${runId} is owned by session:${status.ownerId}; current session is ${sessionId}.`,
|
|
457
|
+
);
|
|
415
458
|
}
|
|
416
459
|
return status;
|
|
417
460
|
}
|
|
@@ -427,10 +470,18 @@ export function createInspectToolDefinition<TContext = unknown>(
|
|
|
427
470
|
parameters: objectSchema(
|
|
428
471
|
{
|
|
429
472
|
lines: stringSchema("Line count for tail/messages views. Default 40."),
|
|
430
|
-
status: stringSchema(
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
473
|
+
status: stringSchema(
|
|
474
|
+
"Optional session run filter: all, running, active, terminal, done, failed, cancelled, killed, or exited.",
|
|
475
|
+
),
|
|
476
|
+
target: stringSchema(
|
|
477
|
+
"Actor address to inspect, e.g. run:<id>, coordinator, session:<id>, session:all, or tool:<name>.",
|
|
478
|
+
),
|
|
479
|
+
verbose: booleanSchema(
|
|
480
|
+
"Return full JSON instead of compact text where available.",
|
|
481
|
+
),
|
|
482
|
+
view: stringSchema(
|
|
483
|
+
"Inspection view: status, tail, messages, artifacts, files, or mailbox.",
|
|
484
|
+
),
|
|
434
485
|
},
|
|
435
486
|
["target", "view"],
|
|
436
487
|
),
|
|
@@ -447,17 +498,26 @@ export function createInspectToolDefinition<TContext = unknown>(
|
|
|
447
498
|
const view = String(input.view ?? "");
|
|
448
499
|
if (address.kind === "coordinator") {
|
|
449
500
|
if (view !== "status" && view !== "runs") {
|
|
450
|
-
throw new Error(
|
|
501
|
+
throw new Error(
|
|
502
|
+
"inspect coordinator supports view=status or view=runs.",
|
|
503
|
+
);
|
|
451
504
|
}
|
|
452
505
|
const session = requireContextSessionId(ctx, "inspect coordinator");
|
|
453
|
-
const runs = AsyncRuns.listRuns(
|
|
506
|
+
const runs = AsyncRuns.listRuns(
|
|
507
|
+
undefined,
|
|
508
|
+
typeof input.status === "string" ? input.status : undefined,
|
|
509
|
+
)
|
|
454
510
|
.map((run) => AsyncRuns.getRunStatus(String(run.state_dir)))
|
|
455
511
|
.filter((run) => run.ownerId === session);
|
|
456
512
|
return {
|
|
457
513
|
content: [
|
|
458
514
|
{
|
|
459
515
|
type: "text" as const,
|
|
460
|
-
text: maybeJsonText(
|
|
516
|
+
text: maybeJsonText(
|
|
517
|
+
{ session, runs },
|
|
518
|
+
input.verbose === true,
|
|
519
|
+
compactSessionRuns(session, runs),
|
|
520
|
+
),
|
|
461
521
|
},
|
|
462
522
|
],
|
|
463
523
|
details: { session, runs },
|
|
@@ -465,16 +525,27 @@ export function createInspectToolDefinition<TContext = unknown>(
|
|
|
465
525
|
}
|
|
466
526
|
if (address.kind === "session") {
|
|
467
527
|
if (view !== "status" && view !== "runs") {
|
|
468
|
-
throw new Error(
|
|
528
|
+
throw new Error(
|
|
529
|
+
"inspect session:<id> supports view=status or view=runs.",
|
|
530
|
+
);
|
|
469
531
|
}
|
|
470
|
-
const runs = AsyncRuns.listRuns(
|
|
532
|
+
const runs = AsyncRuns.listRuns(
|
|
533
|
+
undefined,
|
|
534
|
+
typeof input.status === "string" ? input.status : undefined,
|
|
535
|
+
)
|
|
471
536
|
.map((run) => AsyncRuns.getRunStatus(String(run.state_dir)))
|
|
472
|
-
.filter(
|
|
537
|
+
.filter(
|
|
538
|
+
(run) => address.value === "all" || run.ownerId === address.value,
|
|
539
|
+
);
|
|
473
540
|
return {
|
|
474
541
|
content: [
|
|
475
542
|
{
|
|
476
543
|
type: "text" as const,
|
|
477
|
-
text: maybeJsonText(
|
|
544
|
+
text: maybeJsonText(
|
|
545
|
+
{ session: address.value, runs },
|
|
546
|
+
input.verbose === true,
|
|
547
|
+
compactSessionRuns(address.value || "", runs),
|
|
548
|
+
),
|
|
478
549
|
},
|
|
479
550
|
],
|
|
480
551
|
details: { session: address.value, runs },
|
|
@@ -482,7 +553,9 @@ export function createInspectToolDefinition<TContext = unknown>(
|
|
|
482
553
|
}
|
|
483
554
|
if (address.kind === "tool" && address.value) {
|
|
484
555
|
if (view !== "status" && view !== "schema") {
|
|
485
|
-
throw new Error(
|
|
556
|
+
throw new Error(
|
|
557
|
+
"inspect tool:<name> supports view=status or view=schema.",
|
|
558
|
+
);
|
|
486
559
|
}
|
|
487
560
|
const tool = deps.getTool?.(address.value);
|
|
488
561
|
if (!tool) throw new Error(`tool actor not found: ${address.value}`);
|
|
@@ -496,14 +569,21 @@ export function createInspectToolDefinition<TContext = unknown>(
|
|
|
496
569
|
content: [
|
|
497
570
|
{
|
|
498
571
|
type: "text" as const,
|
|
499
|
-
text: maybeJsonText(
|
|
572
|
+
text: maybeJsonText(
|
|
573
|
+
details,
|
|
574
|
+
input.verbose === true || view === "schema",
|
|
575
|
+
compactToolActor(address.value, details),
|
|
576
|
+
),
|
|
500
577
|
},
|
|
501
578
|
],
|
|
502
579
|
details,
|
|
503
580
|
};
|
|
504
581
|
}
|
|
505
582
|
const runId = address.kind === "run" ? address.value : undefined;
|
|
506
|
-
if (!runId)
|
|
583
|
+
if (!runId)
|
|
584
|
+
throw new Error(
|
|
585
|
+
"inspect target must be run:<id>, coordinator, session:<id>, or tool:<name>.",
|
|
586
|
+
);
|
|
507
587
|
switch (view) {
|
|
508
588
|
case "status": {
|
|
509
589
|
const status = assertRunAccessibleToContext(runId, ctx);
|
|
@@ -511,7 +591,11 @@ export function createInspectToolDefinition<TContext = unknown>(
|
|
|
511
591
|
content: [
|
|
512
592
|
{
|
|
513
593
|
type: "text" as const,
|
|
514
|
-
text: maybeJsonText(
|
|
594
|
+
text: maybeJsonText(
|
|
595
|
+
status,
|
|
596
|
+
input.verbose === true,
|
|
597
|
+
compactAsyncRunStatus(status),
|
|
598
|
+
),
|
|
515
599
|
},
|
|
516
600
|
],
|
|
517
601
|
details: status,
|
|
@@ -520,16 +604,26 @@ export function createInspectToolDefinition<TContext = unknown>(
|
|
|
520
604
|
case "tail": {
|
|
521
605
|
assertRunAccessibleToContext(runId, ctx);
|
|
522
606
|
const text = AsyncRuns.tailRun(runId, Number(input.lines || 40));
|
|
523
|
-
return {
|
|
607
|
+
return {
|
|
608
|
+
content: [{ type: "text" as const, text: `\n${text}` }],
|
|
609
|
+
details: {},
|
|
610
|
+
};
|
|
524
611
|
}
|
|
525
612
|
case "messages": {
|
|
526
613
|
assertRunAccessibleToContext(runId, ctx);
|
|
527
|
-
const messages = AsyncRuns.readRunEvents(
|
|
614
|
+
const messages = AsyncRuns.readRunEvents(
|
|
615
|
+
runId,
|
|
616
|
+
Number(input.lines || 40),
|
|
617
|
+
);
|
|
528
618
|
return {
|
|
529
619
|
content: [
|
|
530
620
|
{
|
|
531
621
|
type: "text" as const,
|
|
532
|
-
text: maybeJsonText(
|
|
622
|
+
text: maybeJsonText(
|
|
623
|
+
messages,
|
|
624
|
+
input.verbose === true,
|
|
625
|
+
compactRunMessages(messages),
|
|
626
|
+
),
|
|
533
627
|
},
|
|
534
628
|
],
|
|
535
629
|
details: { messages },
|
|
@@ -542,7 +636,11 @@ export function createInspectToolDefinition<TContext = unknown>(
|
|
|
542
636
|
content: [
|
|
543
637
|
{
|
|
544
638
|
type: "text" as const,
|
|
545
|
-
text: maybeJsonText(
|
|
639
|
+
text: maybeJsonText(
|
|
640
|
+
status,
|
|
641
|
+
input.verbose === true,
|
|
642
|
+
compactActorFiles(status),
|
|
643
|
+
),
|
|
546
644
|
},
|
|
547
645
|
],
|
|
548
646
|
details: status,
|
|
@@ -555,14 +653,20 @@ export function createInspectToolDefinition<TContext = unknown>(
|
|
|
555
653
|
content: [
|
|
556
654
|
{
|
|
557
655
|
type: "text" as const,
|
|
558
|
-
text: maybeJsonText(
|
|
656
|
+
text: maybeJsonText(
|
|
657
|
+
mailbox,
|
|
658
|
+
input.verbose === true,
|
|
659
|
+
`\nrun=${String(status.run ?? runId)} accepts=${Array.isArray(mailbox.accepts) ? mailbox.accepts.join(",") : ""} emits=${Array.isArray(mailbox.emits) ? mailbox.emits.join(",") : ""}`,
|
|
660
|
+
),
|
|
559
661
|
},
|
|
560
662
|
],
|
|
561
663
|
details: { mailbox },
|
|
562
664
|
};
|
|
563
665
|
}
|
|
564
666
|
default:
|
|
565
|
-
throw new Error(
|
|
667
|
+
throw new Error(
|
|
668
|
+
"inspect view must be one of: status, tail, messages, artifacts, files, mailbox.",
|
|
669
|
+
);
|
|
566
670
|
}
|
|
567
671
|
},
|
|
568
672
|
};
|
|
@@ -583,17 +687,29 @@ export function createActorMessageToolDefinition<TContext = unknown>(
|
|
|
583
687
|
parameters: objectSchema(
|
|
584
688
|
{
|
|
585
689
|
body: unionSchema([
|
|
586
|
-
stringSchema(
|
|
690
|
+
stringSchema(
|
|
691
|
+
"Message body. For run:<id>, this is the run-local command line.",
|
|
692
|
+
),
|
|
587
693
|
looseObjectSchema("Structured JSON message body."),
|
|
588
694
|
arraySchema("Structured JSON message body array."),
|
|
589
695
|
]),
|
|
590
|
-
correlation_id: stringSchema(
|
|
591
|
-
|
|
592
|
-
|
|
696
|
+
correlation_id: stringSchema(
|
|
697
|
+
"Optional correlation id for workflow/task linkage.",
|
|
698
|
+
),
|
|
699
|
+
from: stringSchema(
|
|
700
|
+
"Optional sender address, such as coordinator or run:<id>.",
|
|
701
|
+
),
|
|
702
|
+
metadata: looseObjectSchema(
|
|
703
|
+
"Optional structured metadata for routing or domain hints.",
|
|
704
|
+
),
|
|
593
705
|
reply_to: stringSchema("Optional message id this message replies to."),
|
|
594
706
|
summary: stringSchema("Optional short human-facing summary."),
|
|
595
|
-
to: stringSchema(
|
|
596
|
-
|
|
707
|
+
to: stringSchema(
|
|
708
|
+
"Destination actor address, e.g. run:<id>, branch:<run>/<branch>, coordinator, session:<id>, or tool:<name>.",
|
|
709
|
+
),
|
|
710
|
+
type: stringSchema(
|
|
711
|
+
"Semantic message type, e.g. control.approve or checkpoint.needs_scope.",
|
|
712
|
+
),
|
|
597
713
|
verbose: booleanSchema("Return full JSON instead of compact text."),
|
|
598
714
|
},
|
|
599
715
|
["to", "type"],
|
|
@@ -611,7 +727,10 @@ export function createActorMessageToolDefinition<TContext = unknown>(
|
|
|
611
727
|
let result: Record<string, unknown>;
|
|
612
728
|
if (address.kind === "run" && address.value) {
|
|
613
729
|
assertRunAccessibleToContext(address.value, ctx);
|
|
614
|
-
if (
|
|
730
|
+
if (
|
|
731
|
+
message.type === "control.stop" ||
|
|
732
|
+
message.type === "control.cancel"
|
|
733
|
+
) {
|
|
615
734
|
result = AsyncRuns.cancelRun(address.value);
|
|
616
735
|
} else if (message.type === "control.kill") {
|
|
617
736
|
result = AsyncRuns.killRun(address.value);
|
|
@@ -630,7 +749,9 @@ export function createActorMessageToolDefinition<TContext = unknown>(
|
|
|
630
749
|
} else if (address.kind === "tool" && address.value) {
|
|
631
750
|
const tool = deps.getTool?.(address.value);
|
|
632
751
|
if (!tool || typeof tool.execute !== "function") {
|
|
633
|
-
throw new Error(
|
|
752
|
+
throw new Error(
|
|
753
|
+
`tool actor not found or not executable: ${address.value}`,
|
|
754
|
+
);
|
|
634
755
|
}
|
|
635
756
|
const toolResult = await tool.execute(
|
|
636
757
|
`message:${message.type}`,
|
|
@@ -651,15 +772,21 @@ export function createActorMessageToolDefinition<TContext = unknown>(
|
|
|
651
772
|
}
|
|
652
773
|
const sender = ActorMessages.parseActorAddress(message.from);
|
|
653
774
|
if (sender.kind !== "run" || !sender.value) {
|
|
654
|
-
throw new Error(
|
|
775
|
+
throw new Error(
|
|
776
|
+
`message to ${address.kind} currently requires from=run:<id>.`,
|
|
777
|
+
);
|
|
655
778
|
}
|
|
656
779
|
const senderStatus = assertRunAccessibleToContext(sender.value, ctx);
|
|
657
780
|
if (address.kind === "session") {
|
|
658
781
|
if (!senderStatus.ownerId) {
|
|
659
|
-
throw new Error(
|
|
782
|
+
throw new Error(
|
|
783
|
+
`message to session:${address.value} requires sender run owner ${address.value}; got no owner.`,
|
|
784
|
+
);
|
|
660
785
|
}
|
|
661
786
|
if (senderStatus.ownerId !== address.value) {
|
|
662
|
-
throw new Error(
|
|
787
|
+
throw new Error(
|
|
788
|
+
`message to session:${address.value} requires sender run owner ${address.value}; got ${senderStatus.ownerId}.`,
|
|
789
|
+
);
|
|
663
790
|
}
|
|
664
791
|
}
|
|
665
792
|
result = AsyncRuns.appendRunOutboxEvent(sender.value, {
|
|
@@ -807,7 +934,12 @@ export function createRuntimeToolDefinition(
|
|
|
807
934
|
signal,
|
|
808
935
|
);
|
|
809
936
|
} catch (error) {
|
|
810
|
-
throw formatRuntimeToolArgumentError(
|
|
937
|
+
throw formatRuntimeToolArgumentError(
|
|
938
|
+
cfg,
|
|
939
|
+
error,
|
|
940
|
+
required,
|
|
941
|
+
isAsyncRecipe,
|
|
942
|
+
);
|
|
811
943
|
}
|
|
812
944
|
},
|
|
813
945
|
};
|
package/package.json
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llblab/pi-actors",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Actor runtime and orchestrator for agent-managed local processes",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension",
|
|
9
|
+
"actors",
|
|
10
|
+
"orchestration",
|
|
11
|
+
"automation",
|
|
12
|
+
"tools"
|
|
13
|
+
],
|
|
6
14
|
"type": "module",
|
|
7
15
|
"license": "MIT",
|
|
8
16
|
"repository": {
|
|
@@ -13,14 +21,9 @@
|
|
|
13
21
|
"bugs": {
|
|
14
22
|
"url": "https://github.com/llblab/pi-actors/issues"
|
|
15
23
|
},
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
"actors",
|
|
20
|
-
"orchestration",
|
|
21
|
-
"automation",
|
|
22
|
-
"tools"
|
|
23
|
-
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=22.19.0"
|
|
26
|
+
},
|
|
24
27
|
"scripts": {
|
|
25
28
|
"check": "node --experimental-strip-types -e \"await import('./index.ts'); console.log('pi-actors: extension import ok')\"",
|
|
26
29
|
"test": "node --experimental-strip-types --test tests/*.test.ts",
|
|
@@ -32,6 +35,7 @@
|
|
|
32
35
|
"lib",
|
|
33
36
|
"scripts",
|
|
34
37
|
"recipes",
|
|
38
|
+
"skills",
|
|
35
39
|
"README.md",
|
|
36
40
|
"AGENTS.md",
|
|
37
41
|
"BACKLOG.md",
|
|
@@ -41,6 +45,10 @@
|
|
|
41
45
|
"pi": {
|
|
42
46
|
"extensions": [
|
|
43
47
|
"./index.ts"
|
|
48
|
+
],
|
|
49
|
+
"skills": [
|
|
50
|
+
"./skills/actors/SKILL.md",
|
|
51
|
+
"./skills/swarm/SKILL.md"
|
|
44
52
|
]
|
|
45
53
|
},
|
|
46
54
|
"peerDependencies": {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "coordinator-locker",
|
|
3
|
+
"async": true,
|
|
4
|
+
"args": [
|
|
5
|
+
"repo:path",
|
|
6
|
+
"lease_ms:int"
|
|
7
|
+
],
|
|
8
|
+
"defaults": {
|
|
9
|
+
"repo": "~/.pi/agent/extensions/pi-actors",
|
|
10
|
+
"lease_ms": "600000"
|
|
11
|
+
},
|
|
12
|
+
"mailbox": {
|
|
13
|
+
"accepts": [
|
|
14
|
+
"coord.enqueue",
|
|
15
|
+
"coord.claim",
|
|
16
|
+
"coord.complete",
|
|
17
|
+
"coord.fail",
|
|
18
|
+
"lock.acquire",
|
|
19
|
+
"lock.renew",
|
|
20
|
+
"lock.release",
|
|
21
|
+
"control.stop",
|
|
22
|
+
"control.cancel",
|
|
23
|
+
"control.kill"
|
|
24
|
+
],
|
|
25
|
+
"emits": [
|
|
26
|
+
"coord.started",
|
|
27
|
+
"coord.enqueued",
|
|
28
|
+
"coord.assigned",
|
|
29
|
+
"coord.empty",
|
|
30
|
+
"coord.completed",
|
|
31
|
+
"coord.failed",
|
|
32
|
+
"lock.granted",
|
|
33
|
+
"lock.denied",
|
|
34
|
+
"lock.renewed",
|
|
35
|
+
"lock.released",
|
|
36
|
+
"run.done",
|
|
37
|
+
"run.failed"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"artifacts": {
|
|
41
|
+
"queue": "{state_dir}/queue.json",
|
|
42
|
+
"locks": "{state_dir}/locks.json",
|
|
43
|
+
"journal": "{state_dir}/journal.jsonl"
|
|
44
|
+
},
|
|
45
|
+
"template": "{repo}/scripts/coordinator-locker.mjs serve --state-dir {state_dir} --lease-ms {lease_ms}"
|
|
46
|
+
}
|
|
@@ -18,8 +18,22 @@
|
|
|
18
18
|
"player": "auto"
|
|
19
19
|
},
|
|
20
20
|
"mailbox": {
|
|
21
|
-
"accepts": [
|
|
22
|
-
|
|
21
|
+
"accepts": [
|
|
22
|
+
"control.stop",
|
|
23
|
+
"control.cancel",
|
|
24
|
+
"control.kill",
|
|
25
|
+
"player.play",
|
|
26
|
+
"player.pause",
|
|
27
|
+
"player.resume",
|
|
28
|
+
"player.toggle",
|
|
29
|
+
"player.next",
|
|
30
|
+
"player.previous",
|
|
31
|
+
"player.stop",
|
|
32
|
+
"player.status"
|
|
33
|
+
],
|
|
34
|
+
"emits": [
|
|
35
|
+
"player.track"
|
|
36
|
+
]
|
|
23
37
|
},
|
|
24
38
|
"template": "{repo}/scripts/music-player.mjs {command} {source} {loop} {volume} {player} {state_dir}"
|
|
25
39
|
}
|
|
@@ -23,12 +23,20 @@
|
|
|
23
23
|
"failure modes"
|
|
24
24
|
],
|
|
25
25
|
"constraints": "Prefer small composable pieces, explicit contracts, and no broad workflow DSL.",
|
|
26
|
-
"model": "openai-codex/gpt-5.5",
|
|
27
26
|
"tools": ""
|
|
28
27
|
},
|
|
29
28
|
"mailbox": {
|
|
30
|
-
"accepts": [
|
|
31
|
-
|
|
29
|
+
"accepts": [
|
|
30
|
+
"control.stop",
|
|
31
|
+
"control.cancel",
|
|
32
|
+
"control.kill"
|
|
33
|
+
],
|
|
34
|
+
"emits": [
|
|
35
|
+
"pipeline.completed",
|
|
36
|
+
"command.done",
|
|
37
|
+
"run.done",
|
|
38
|
+
"run.failed"
|
|
39
|
+
]
|
|
32
40
|
},
|
|
33
41
|
"template": [
|
|
34
42
|
{
|
|
@@ -32,12 +32,21 @@
|
|
|
32
32
|
"validation_command": "true",
|
|
33
33
|
"validation_scope": ".",
|
|
34
34
|
"validation_timeout_ms": "300000",
|
|
35
|
-
"model": "openai-codex/gpt-5.5",
|
|
36
35
|
"tools": ""
|
|
37
36
|
},
|
|
38
37
|
"mailbox": {
|
|
39
|
-
"accepts": [
|
|
40
|
-
|
|
38
|
+
"accepts": [
|
|
39
|
+
"control.stop",
|
|
40
|
+
"control.cancel",
|
|
41
|
+
"control.kill"
|
|
42
|
+
],
|
|
43
|
+
"emits": [
|
|
44
|
+
"artifact.bundle_ready",
|
|
45
|
+
"artifact.written",
|
|
46
|
+
"artifact.blocked",
|
|
47
|
+
"run.done",
|
|
48
|
+
"run.failed"
|
|
49
|
+
]
|
|
41
50
|
},
|
|
42
51
|
"artifacts": {
|
|
43
52
|
"artifact": "{artifact_path}",
|