@llblab/pi-actors 0.22.3 → 0.22.4
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/BACKLOG.md +456 -81
- package/CHANGELOG.md +16 -0
- package/dist/index.js +1 -1
- package/dist/lib/actor-rooms.d.ts +8 -2
- package/dist/lib/actor-rooms.js +58 -9
- package/dist/lib/async-runs.js +32 -10
- package/dist/lib/observability.js +28 -10
- package/dist/lib/recipe-discovery.js +121 -16
- package/dist/lib/recipe-references.d.ts +1 -0
- package/dist/lib/recipe-references.js +40 -1
- package/dist/lib/registry.js +5 -1
- package/dist/lib/tools.js +25 -8
- package/index.ts +1 -1
- package/lib/actor-rooms.ts +79 -11
- package/lib/async-runs.ts +124 -88
- package/lib/observability.ts +85 -24
- package/lib/recipe-discovery.ts +186 -41
- package/lib/recipe-references.ts +88 -14
- package/lib/registry.ts +7 -1
- package/lib/tools.ts +42 -15
- package/package.json +1 -1
- package/skills/actors/SKILL.md +1 -1
- package/skills/swarm/SKILL.md +1 -1
package/dist/lib/tools.js
CHANGED
|
@@ -361,6 +361,7 @@ export function createRegisterToolDefinition(deps) {
|
|
|
361
361
|
state_dir: stringSchema(Prompts.REGISTER_TOOL_PARAM_DESCRIPTIONS.state_dir),
|
|
362
362
|
template: unionSchema([
|
|
363
363
|
stringSchema(Prompts.REGISTER_TOOL_PARAM_DESCRIPTIONS.template),
|
|
364
|
+
looseObjectSchema(Prompts.REGISTER_TOOL_PARAM_DESCRIPTIONS.template),
|
|
364
365
|
arraySchema(Prompts.REGISTER_TOOL_PARAM_DESCRIPTIONS.templateArray),
|
|
365
366
|
nullSchema(Prompts.REGISTER_TOOL_PARAM_DESCRIPTIONS.templateNull),
|
|
366
367
|
]),
|
|
@@ -390,6 +391,16 @@ function messageBodyToToolParams(message) {
|
|
|
390
391
|
return {};
|
|
391
392
|
return { input: message.body };
|
|
392
393
|
}
|
|
394
|
+
function formatToolActorFailure(tool, message, params, error) {
|
|
395
|
+
const original = error instanceof Error ? error.message : String(error);
|
|
396
|
+
const paramsPreview = compactPreview(params, 240) ?? "{}";
|
|
397
|
+
return Object.assign(new Error(`tool actor ${tool} failed for message type ${message.type}: ${original}; params=${paramsPreview}`), {
|
|
398
|
+
message_type: message.type,
|
|
399
|
+
original_error: original,
|
|
400
|
+
params_preview: paramsPreview,
|
|
401
|
+
tool,
|
|
402
|
+
});
|
|
403
|
+
}
|
|
393
404
|
function runIdFromActorAddress(address) {
|
|
394
405
|
if (!address)
|
|
395
406
|
return undefined;
|
|
@@ -672,15 +683,16 @@ export function createInspectToolDefinition(deps = {}) {
|
|
|
672
683
|
if (view !== "mailbox")
|
|
673
684
|
throw new Error("inspect branch:<run>/<branch> supports view=mailbox.");
|
|
674
685
|
const status = assertRunAccessibleToContext(runId, ctx);
|
|
675
|
-
const
|
|
686
|
+
const branchInbox = ActorRooms.readBranchInboxDiagnostics(String(status.state_dir ?? ""), runId, target, Number(input.lines || 40));
|
|
687
|
+
const messages = branchInbox.messages;
|
|
676
688
|
return {
|
|
677
689
|
content: [
|
|
678
690
|
{
|
|
679
691
|
type: "text",
|
|
680
|
-
text: maybeJsonText(messages, input.verbose === true, compactBranchInbox(messages.map((message) => ({ ...message })))),
|
|
692
|
+
text: maybeJsonText(input.verbose === true ? branchInbox : messages, input.verbose === true, `${compactBranchInbox(messages.map((message) => ({ ...message })))}${branchInbox.corrupted > 0 ? `\ncorrupted=${branchInbox.corrupted}` : ""}`),
|
|
681
693
|
},
|
|
682
694
|
],
|
|
683
|
-
details: { messages },
|
|
695
|
+
details: { corrupted: branchInbox.corrupted, messages },
|
|
684
696
|
};
|
|
685
697
|
}
|
|
686
698
|
switch (view) {
|
|
@@ -806,9 +818,7 @@ export function createActorMessageToolDefinition(deps = {}) {
|
|
|
806
818
|
const runId = address.value;
|
|
807
819
|
if (message.from)
|
|
808
820
|
assertMessageSenderBelongsToRun(message, runId, `branch:${runId}/<branch>`);
|
|
809
|
-
const status =
|
|
810
|
-
? assertRunExistsForActorMessage(runId)
|
|
811
|
-
: assertRunAccessibleToContext(runId, ctx);
|
|
821
|
+
const status = assertRunAccessibleToContext(runId, ctx);
|
|
812
822
|
const stateDir = String(status.state_dir ?? "");
|
|
813
823
|
if (stateDir && address.branch) {
|
|
814
824
|
const ensureBranchMember = (actorAddress) => {
|
|
@@ -834,7 +844,7 @@ export function createActorMessageToolDefinition(deps = {}) {
|
|
|
834
844
|
else if (address.kind === "room" && address.value && address.room) {
|
|
835
845
|
const runId = address.value;
|
|
836
846
|
assertMessageSenderBelongsToRun(message, runId, `room:${runId}`);
|
|
837
|
-
const status =
|
|
847
|
+
const status = assertRunAccessibleToContext(runId, ctx);
|
|
838
848
|
const stateDir = String(status.state_dir ?? "");
|
|
839
849
|
if (!stateDir)
|
|
840
850
|
throw new Error(`${message.to} has no run state directory.`);
|
|
@@ -853,7 +863,14 @@ export function createActorMessageToolDefinition(deps = {}) {
|
|
|
853
863
|
if (!tool || typeof tool.execute !== "function") {
|
|
854
864
|
throw new Error(`tool actor not found or not executable: ${address.value}`);
|
|
855
865
|
}
|
|
856
|
-
const
|
|
866
|
+
const toolParams = messageBodyToToolParams(message);
|
|
867
|
+
let toolResult;
|
|
868
|
+
try {
|
|
869
|
+
toolResult = await tool.execute(`message:${message.type}`, toolParams, _signal, _onUpdate, ctx);
|
|
870
|
+
}
|
|
871
|
+
catch (error) {
|
|
872
|
+
throw formatToolActorFailure(address.value, message, toolParams, error);
|
|
873
|
+
}
|
|
857
874
|
result = {
|
|
858
875
|
invoked: true,
|
|
859
876
|
sent: true,
|
package/index.ts
CHANGED
|
@@ -174,7 +174,7 @@ export default function toolRegistryExtension(pi: ExtensionAPI) {
|
|
|
174
174
|
observedRuns,
|
|
175
175
|
observedRunEventLines,
|
|
176
176
|
summary,
|
|
177
|
-
transitions.map((transition) => transition.run),
|
|
177
|
+
transitions.map((transition) => transition.stateDir ?? transition.run),
|
|
178
178
|
);
|
|
179
179
|
for (const event of outboxEvents) {
|
|
180
180
|
if (!Observability.shouldNotifyRunOutboxEvent(event)) continue;
|
package/lib/actor-rooms.ts
CHANGED
|
@@ -383,24 +383,86 @@ function updateRosterForMessage(
|
|
|
383
383
|
return roster;
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
-
export
|
|
386
|
+
export interface BranchInboxRecord extends ActorMessage {
|
|
387
|
+
id?: string;
|
|
388
|
+
queued_at?: string;
|
|
389
|
+
status?: string;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
export interface BranchInboxReadResult {
|
|
393
|
+
corrupted: number;
|
|
394
|
+
messages: BranchInboxRecord[];
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function readBranchInboxFile(
|
|
387
398
|
stateDir: string,
|
|
388
399
|
run: string,
|
|
389
400
|
address: string,
|
|
390
401
|
limit = 40,
|
|
391
|
-
):
|
|
402
|
+
): BranchInboxReadResult {
|
|
392
403
|
const branch = branchIdFromAddress(address, run);
|
|
393
404
|
if (!branch) throw new Error(`Expected branch:${run}/<branch>; got ${address}`);
|
|
394
405
|
try {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
406
|
+
const lines = readJsonlTailLines(branchInboxFile(stateDir, branch), limit);
|
|
407
|
+
const messages: BranchInboxRecord[] = [];
|
|
408
|
+
let corrupted = 0;
|
|
409
|
+
for (const line of lines) {
|
|
410
|
+
try {
|
|
411
|
+
messages.push(JSON.parse(line));
|
|
412
|
+
} catch {
|
|
413
|
+
corrupted += 1;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return { corrupted, messages };
|
|
417
|
+
} catch (error) {
|
|
418
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") return { corrupted: 0, messages: [] };
|
|
419
|
+
throw error;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function readAllBranchInboxLines(
|
|
424
|
+
stateDir: string,
|
|
425
|
+
run: string,
|
|
426
|
+
address: string,
|
|
427
|
+
): Array<{ raw: string } | { message: BranchInboxRecord }> {
|
|
428
|
+
const branch = branchIdFromAddress(address, run);
|
|
429
|
+
if (!branch) throw new Error(`Expected branch:${run}/<branch>; got ${address}`);
|
|
430
|
+
try {
|
|
431
|
+
const content = fs.readFileSync(branchInboxFile(stateDir, branch), "utf8");
|
|
432
|
+
return content
|
|
433
|
+
.split("\n")
|
|
434
|
+
.filter((line) => line.length > 0)
|
|
435
|
+
.map((line) => {
|
|
436
|
+
try {
|
|
437
|
+
return { message: JSON.parse(line) as BranchInboxRecord };
|
|
438
|
+
} catch {
|
|
439
|
+
return { raw: line };
|
|
440
|
+
}
|
|
441
|
+
});
|
|
398
442
|
} catch (error) {
|
|
399
443
|
if ((error as NodeJS.ErrnoException).code === "ENOENT") return [];
|
|
400
444
|
throw error;
|
|
401
445
|
}
|
|
402
446
|
}
|
|
403
447
|
|
|
448
|
+
export function readBranchInboxMessages(
|
|
449
|
+
stateDir: string,
|
|
450
|
+
run: string,
|
|
451
|
+
address: string,
|
|
452
|
+
limit = 40,
|
|
453
|
+
): BranchInboxRecord[] {
|
|
454
|
+
return readBranchInboxFile(stateDir, run, address, limit).messages;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export function readBranchInboxDiagnostics(
|
|
458
|
+
stateDir: string,
|
|
459
|
+
run: string,
|
|
460
|
+
address: string,
|
|
461
|
+
limit = 40,
|
|
462
|
+
): BranchInboxReadResult {
|
|
463
|
+
return readBranchInboxFile(stateDir, run, address, limit);
|
|
464
|
+
}
|
|
465
|
+
|
|
404
466
|
export function getBranchInboxTerminalRetainLimit(): number {
|
|
405
467
|
const value = Number(process.env.PI_ACTORS_BRANCH_INBOX_TERMINAL_RETAINED ?? "");
|
|
406
468
|
return Number.isInteger(value) && value >= 0
|
|
@@ -458,17 +520,23 @@ export function updateBranchInboxMessageStatus(
|
|
|
458
520
|
const releaseLock = acquireBranchInboxLock(stateDir, branch);
|
|
459
521
|
try {
|
|
460
522
|
const file = branchInboxFile(stateDir, branch);
|
|
461
|
-
const
|
|
523
|
+
const records = readAllBranchInboxLines(stateDir, run, address);
|
|
462
524
|
let changed = false;
|
|
463
525
|
const timestampKey = `${status}_at`;
|
|
464
|
-
const updated =
|
|
465
|
-
if (message.id !== id) return
|
|
526
|
+
const updated = records.map((record) => {
|
|
527
|
+
if (!("message" in record) || record.message.id !== id) return record;
|
|
466
528
|
changed = true;
|
|
467
|
-
return { ...message, ...metadata, [timestampKey]: new Date().toISOString(), status };
|
|
529
|
+
return { message: { ...record.message, ...metadata, [timestampKey]: new Date().toISOString(), status } };
|
|
468
530
|
});
|
|
469
531
|
if (!changed) return false;
|
|
470
|
-
const
|
|
471
|
-
|
|
532
|
+
const validMessages = updated.flatMap((record) => "message" in record ? [record.message] : []);
|
|
533
|
+
const compactedIds = new Set(compactBranchInboxMessages(validMessages).map((message) => message.id));
|
|
534
|
+
const lines = updated.flatMap((record) => {
|
|
535
|
+
if ("raw" in record) return [record.raw];
|
|
536
|
+
if (record.message.id && !compactedIds.has(record.message.id)) return [];
|
|
537
|
+
return [JSON.stringify(record.message)];
|
|
538
|
+
});
|
|
539
|
+
fs.writeFileSync(file, lines.length ? `${lines.join("\n")}\n` : "");
|
|
472
540
|
notifyActorWake(stateDir, address, "branch.inbox.status", { id, status });
|
|
473
541
|
return true;
|
|
474
542
|
} finally {
|
package/lib/async-runs.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Owns detached run state, observation, log tailing, listing, and cancellation safety
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { randomUUID } from "node:crypto";
|
|
8
7
|
import { spawn, spawnSync } from "node:child_process";
|
|
8
|
+
import { randomUUID } from "node:crypto";
|
|
9
9
|
import {
|
|
10
10
|
closeSync,
|
|
11
11
|
constants,
|
|
@@ -133,7 +133,10 @@ const DEFAULT_RECIPE_ROOT = Paths.getRecipeRoot();
|
|
|
133
133
|
|
|
134
134
|
function packageRoot(): string {
|
|
135
135
|
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
136
|
-
if (
|
|
136
|
+
if (
|
|
137
|
+
basename(moduleDir) === "lib" &&
|
|
138
|
+
basename(dirname(moduleDir)) === "dist"
|
|
139
|
+
) {
|
|
137
140
|
return dirname(dirname(moduleDir));
|
|
138
141
|
}
|
|
139
142
|
return dirname(moduleDir);
|
|
@@ -409,84 +412,88 @@ export function startRun(
|
|
|
409
412
|
try {
|
|
410
413
|
assertNoActiveRunState(stateDir);
|
|
411
414
|
prepareStateDirForStart(stateDir);
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
? {
|
|
462
|
-
: {}),
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
415
|
+
const stdout = join(stateDir, "stdout.log");
|
|
416
|
+
const stderr = join(stateDir, "stderr.log");
|
|
417
|
+
const recipeFile = startParams.file
|
|
418
|
+
? resolveRecipeFile(startParams.file)
|
|
419
|
+
: undefined;
|
|
420
|
+
const recipe = startParams.name || getRunIdFromFile(recipeFile);
|
|
421
|
+
const includeActorRecipeContext =
|
|
422
|
+
startParams.actor_context !== false &&
|
|
423
|
+
startParams.actor_context !== "off";
|
|
424
|
+
const recipeContextRecords =
|
|
425
|
+
recipeFile && includeActorRecipeContext
|
|
426
|
+
? RecipeReferences.buildRecipeContextRecords(recipeFile)
|
|
427
|
+
: undefined;
|
|
428
|
+
if (recipeFile && isMutableUsageRecipeFile(recipeFile)) {
|
|
429
|
+
RecipeUsage.recordRecipeLaunch(recipeFile);
|
|
430
|
+
}
|
|
431
|
+
const outFd = openSync(stdout, "a");
|
|
432
|
+
const errFd = openSync(stderr, "a");
|
|
433
|
+
const argv = asyncRunnerArgv(stateDir);
|
|
434
|
+
const values = {
|
|
435
|
+
...(startParams.values || {}),
|
|
436
|
+
actor_address: `run:${run}`,
|
|
437
|
+
communication_file: join(stateDir, "communication.json"),
|
|
438
|
+
default_room: `room:${run}`,
|
|
439
|
+
run_id: run,
|
|
440
|
+
state_dir: stateDir,
|
|
441
|
+
};
|
|
442
|
+
const outputValues = {
|
|
443
|
+
...(startParams.defaults || {}),
|
|
444
|
+
...values,
|
|
445
|
+
};
|
|
446
|
+
const artifacts = resolveArtifactPaths(startParams.artifacts, outputValues);
|
|
447
|
+
const meta: AsyncRunMeta = {
|
|
448
|
+
argv: [process.execPath, ...argv],
|
|
449
|
+
createdAt: new Date().toISOString(),
|
|
450
|
+
cwd,
|
|
451
|
+
...(startParams.launch_source
|
|
452
|
+
? { launch_source: startParams.launch_source }
|
|
453
|
+
: {}),
|
|
454
|
+
...(startParams.ownerId ? { ownerId: startParams.ownerId } : {}),
|
|
455
|
+
pid: 0,
|
|
456
|
+
...(recipe ? { recipe } : {}),
|
|
457
|
+
...(recipeFile ? { recipe_file: recipeFile } : {}),
|
|
458
|
+
run,
|
|
459
|
+
state_dir: stateDir,
|
|
460
|
+
status: "running",
|
|
461
|
+
...(startParams.tool ? { tool: startParams.tool } : {}),
|
|
462
|
+
template: resolved.template,
|
|
463
|
+
values,
|
|
464
|
+
...(artifacts ? { artifacts } : {}),
|
|
465
|
+
...(startParams.control ? { control: startParams.control } : {}),
|
|
466
|
+
...(startParams.mailbox ? { mailbox: startParams.mailbox } : {}),
|
|
467
|
+
...(recipeContextRecords && recipeContextRecords.length > 0
|
|
468
|
+
? { recipe_context_records: recipeContextRecords }
|
|
469
|
+
: {}),
|
|
470
|
+
...(startParams.retire_when === "children_terminal"
|
|
471
|
+
? { retire_when: "children_terminal" as const }
|
|
472
|
+
: {}),
|
|
473
|
+
};
|
|
474
|
+
writeJsonAtomic(join(stateDir, "run.json"), meta);
|
|
475
|
+
const child = spawn(process.execPath, argv, {
|
|
476
|
+
cwd,
|
|
477
|
+
detached: true,
|
|
478
|
+
stdio: ["ignore", outFd, errFd],
|
|
479
|
+
});
|
|
480
|
+
closeSync(outFd);
|
|
481
|
+
closeSync(errFd);
|
|
482
|
+
meta.pid = child.pid ?? 0;
|
|
483
|
+
writeJsonAtomic(join(stateDir, "run.json"), meta);
|
|
484
|
+
writeJsonAtomic(join(stateDir, "progress.json"), {
|
|
485
|
+
completed: 0,
|
|
486
|
+
failures: [],
|
|
487
|
+
phase: "starting",
|
|
488
|
+
updatedAt: new Date().toISOString(),
|
|
489
|
+
});
|
|
490
|
+
writeFileSync(
|
|
491
|
+
join(stateDir, "events.jsonl"),
|
|
492
|
+
`${JSON.stringify({ event: "run.start", run, pid: meta.pid, ts: new Date().toISOString() })}\n`,
|
|
493
|
+
{ flag: "a" },
|
|
494
|
+
);
|
|
495
|
+
child.unref();
|
|
496
|
+
return meta;
|
|
490
497
|
} finally {
|
|
491
498
|
releaseStartLock();
|
|
492
499
|
}
|
|
@@ -806,7 +813,10 @@ export function claimRunInboxMessage(
|
|
|
806
813
|
...messages[index],
|
|
807
814
|
claimed_at: new Date().toISOString(),
|
|
808
815
|
claimed_by: owner,
|
|
809
|
-
id:
|
|
816
|
+
id:
|
|
817
|
+
typeof messages[index].id === "string"
|
|
818
|
+
? messages[index].id
|
|
819
|
+
: randomUUID(),
|
|
810
820
|
status: "claimed",
|
|
811
821
|
} satisfies RunInboxMessage;
|
|
812
822
|
messages[index] = claimed;
|
|
@@ -928,9 +938,10 @@ function appendRunInboxMessage(stateDir: string, message: string): string {
|
|
|
928
938
|
let record: Record<string, unknown>;
|
|
929
939
|
try {
|
|
930
940
|
const parsed = JSON.parse(message) as unknown;
|
|
931
|
-
record =
|
|
932
|
-
|
|
933
|
-
|
|
941
|
+
record =
|
|
942
|
+
parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
|
943
|
+
? (parsed as Record<string, unknown>)
|
|
944
|
+
: { body: parsed, type: "run.message" };
|
|
934
945
|
} catch {
|
|
935
946
|
record = { body: message, type: "run.message" };
|
|
936
947
|
}
|
|
@@ -1057,7 +1068,13 @@ export async function sendRunMessage(
|
|
|
1057
1068
|
const payload = message.endsWith("\n") ? message : `${message}\n`;
|
|
1058
1069
|
const payloadBytes = Buffer.byteLength(payload);
|
|
1059
1070
|
const inboxId = appendRunInboxMessage(stateDir, message);
|
|
1060
|
-
const wake = notifyRunMessageWake(
|
|
1071
|
+
const wake = notifyRunMessageWake(
|
|
1072
|
+
stateDir,
|
|
1073
|
+
run,
|
|
1074
|
+
payloadBytes,
|
|
1075
|
+
endpoint,
|
|
1076
|
+
inboxId,
|
|
1077
|
+
);
|
|
1061
1078
|
const runtimePlatform = options.platform ?? process.platform;
|
|
1062
1079
|
if (endpoint.type === "mailbox") {
|
|
1063
1080
|
return {
|
|
@@ -1066,6 +1083,7 @@ export async function sendRunMessage(
|
|
|
1066
1083
|
control: "inbox.jsonl",
|
|
1067
1084
|
control_path: endpoint.path,
|
|
1068
1085
|
control_type: endpoint.type,
|
|
1086
|
+
inbox_id: inboxId,
|
|
1069
1087
|
queued: true,
|
|
1070
1088
|
run,
|
|
1071
1089
|
sent: true,
|
|
@@ -1087,6 +1105,7 @@ export async function sendRunMessage(
|
|
|
1087
1105
|
control: "control.fifo",
|
|
1088
1106
|
control_path: endpoint.path,
|
|
1089
1107
|
control_type: endpoint.type,
|
|
1108
|
+
inbox_id: inboxId,
|
|
1090
1109
|
run,
|
|
1091
1110
|
sent: true,
|
|
1092
1111
|
state_dir: stateDir,
|
|
@@ -1104,13 +1123,28 @@ export async function sendRunMessage(
|
|
|
1104
1123
|
control: endpoint.path,
|
|
1105
1124
|
control_path: endpoint.path,
|
|
1106
1125
|
control_type: endpoint.type,
|
|
1126
|
+
inbox_id: inboxId,
|
|
1107
1127
|
run,
|
|
1108
1128
|
sent: true,
|
|
1109
1129
|
state_dir: stateDir,
|
|
1110
1130
|
};
|
|
1111
1131
|
} catch (error) {
|
|
1112
|
-
|
|
1113
|
-
|
|
1132
|
+
const deliveryError =
|
|
1133
|
+
error instanceof Error ? error.message : String(error);
|
|
1134
|
+
throw Object.assign(
|
|
1135
|
+
new Error(
|
|
1136
|
+
`Run control endpoint is not ready: ${endpoint.path}: ${deliveryError}`,
|
|
1137
|
+
),
|
|
1138
|
+
{
|
|
1139
|
+
control_path: endpoint.path,
|
|
1140
|
+
control_type: endpoint.type,
|
|
1141
|
+
delivery_error: deliveryError,
|
|
1142
|
+
inbox_id: inboxId,
|
|
1143
|
+
queued: true,
|
|
1144
|
+
run,
|
|
1145
|
+
sent: false,
|
|
1146
|
+
state_dir: stateDir,
|
|
1147
|
+
},
|
|
1114
1148
|
);
|
|
1115
1149
|
}
|
|
1116
1150
|
}
|
|
@@ -1150,7 +1184,9 @@ function signalOwnedRunProcess(
|
|
|
1150
1184
|
const result = spawnSync(plan.command, plan.args, { encoding: "utf8" });
|
|
1151
1185
|
if (result.status !== 0) {
|
|
1152
1186
|
throw new Error(
|
|
1153
|
-
result.stderr?.trim() ||
|
|
1187
|
+
result.stderr?.trim() ||
|
|
1188
|
+
result.stdout?.trim() ||
|
|
1189
|
+
`${plan.command} failed`,
|
|
1154
1190
|
);
|
|
1155
1191
|
}
|
|
1156
1192
|
return plan;
|