@llblab/pi-actors 0.25.0 → 0.26.1
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 +4 -8
- package/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/dist/lib/actor-worker.d.ts +3 -0
- package/dist/lib/actor-worker.js +54 -6
- package/dist/lib/coordinator.js +31 -4
- package/dist/recipes/actor-worker.json +10 -6
- package/dist/recipes/lens-swarm.json +0 -2
- package/dist/recipes/pipeline-architect-coordinator.json +0 -2
- package/dist/recipes/pipeline-artifact-bundle.json +0 -2
- package/dist/recipes/pipeline-artifact-report.json +0 -2
- package/dist/recipes/pipeline-artifact-write.json +0 -2
- package/dist/recipes/pipeline-async-run-ops.json +0 -2
- package/dist/recipes/pipeline-checkpoint-continuation.json +0 -2
- package/dist/recipes/pipeline-development-tasking.json +0 -2
- package/dist/recipes/pipeline-docs-maintenance.json +0 -2
- package/dist/recipes/pipeline-media-library.json +0 -2
- package/dist/recipes/pipeline-quorum-review.json +0 -2
- package/dist/recipes/pipeline-release-readiness.json +0 -2
- package/dist/recipes/pipeline-release-summary.json +0 -2
- package/dist/recipes/pipeline-repo-health.json +0 -2
- package/dist/recipes/pipeline-research-synthesis.json +0 -2
- package/dist/recipes/pipeline-review-readiness.json +0 -2
- package/dist/recipes/pipeline-room-swarm.json +0 -2
- package/dist/recipes/subagent-artifact.json +0 -2
- package/dist/recipes/subagent-checkpoint.json +0 -2
- package/dist/recipes/subagent-conflict-report.json +0 -2
- package/dist/recipes/subagent-contradiction-map.json +0 -2
- package/dist/recipes/subagent-critic.json +0 -2
- package/dist/recipes/subagent-evidence-map.json +0 -2
- package/dist/recipes/subagent-followup.json +0 -2
- package/dist/recipes/subagent-judge.json +0 -2
- package/dist/recipes/subagent-merge.json +0 -2
- package/dist/recipes/subagent-message.json +0 -2
- package/dist/recipes/subagent-normalize.json +0 -2
- package/dist/recipes/subagent-plan.json +0 -2
- package/dist/recipes/subagent-prompt.json +0 -2
- package/dist/recipes/subagent-quorum.json +0 -2
- package/dist/recipes/subagent-review-coordinator.json +0 -2
- package/dist/recipes/subagent-review.json +0 -2
- package/dist/recipes/subagent-task-card.json +0 -2
- package/dist/recipes/subagent-tools.json +0 -2
- package/dist/recipes/subagent-verify.json +0 -2
- package/dist/recipes/subagents-prompts.json +0 -2
- package/dist/skills/actors/SKILL.md +2 -2
- package/dist/skills/swarm/SKILL.md +1 -1
- package/docs/actor-messages.md +1 -1
- package/docs/template-recipes.md +2 -2
- package/lib/actor-worker.ts +62 -6
- package/lib/coordinator.ts +33 -4
- package/package.json +1 -1
- package/recipes/actor-worker.json +10 -6
- package/recipes/lens-swarm.json +0 -2
- package/recipes/pipeline-architect-coordinator.json +0 -2
- package/recipes/pipeline-artifact-bundle.json +0 -2
- package/recipes/pipeline-artifact-report.json +0 -2
- package/recipes/pipeline-artifact-write.json +0 -2
- package/recipes/pipeline-async-run-ops.json +0 -2
- package/recipes/pipeline-checkpoint-continuation.json +0 -2
- package/recipes/pipeline-development-tasking.json +0 -2
- package/recipes/pipeline-docs-maintenance.json +0 -2
- package/recipes/pipeline-media-library.json +0 -2
- package/recipes/pipeline-quorum-review.json +0 -2
- package/recipes/pipeline-release-readiness.json +0 -2
- package/recipes/pipeline-release-summary.json +0 -2
- package/recipes/pipeline-repo-health.json +0 -2
- package/recipes/pipeline-research-synthesis.json +0 -2
- package/recipes/pipeline-review-readiness.json +0 -2
- package/recipes/pipeline-room-swarm.json +0 -2
- package/recipes/subagent-artifact.json +0 -2
- package/recipes/subagent-checkpoint.json +0 -2
- package/recipes/subagent-conflict-report.json +0 -2
- package/recipes/subagent-contradiction-map.json +0 -2
- package/recipes/subagent-critic.json +0 -2
- package/recipes/subagent-evidence-map.json +0 -2
- package/recipes/subagent-followup.json +0 -2
- package/recipes/subagent-judge.json +0 -2
- package/recipes/subagent-merge.json +0 -2
- package/recipes/subagent-message.json +0 -2
- package/recipes/subagent-normalize.json +0 -2
- package/recipes/subagent-plan.json +0 -2
- package/recipes/subagent-prompt.json +0 -2
- package/recipes/subagent-quorum.json +0 -2
- package/recipes/subagent-review-coordinator.json +0 -2
- package/recipes/subagent-review.json +0 -2
- package/recipes/subagent-task-card.json +0 -2
- package/recipes/subagent-tools.json +0 -2
- package/recipes/subagent-verify.json +0 -2
- package/recipes/subagents-prompts.json +0 -2
- package/skills/actors/SKILL.md +2 -2
- package/skills/swarm/SKILL.md +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: actors
|
|
3
3
|
description: Highest-density practical guide for pi-actors. Read this skill whenever prompt and tools are not enough for spawn, message, inspect, actor runs, tools, recipes, command templates, async lifecycle, mailboxes, artifacts, and local orchestration mechanics.
|
|
4
4
|
metadata:
|
|
5
|
-
version: 0.
|
|
5
|
+
version: 0.26.1
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Actors (pi-actors)
|
|
@@ -277,7 +277,7 @@ Use packaged recipes by name with `spawn file=<name>` for async actors, or regis
|
|
|
277
277
|
- [`locker`](../../recipes/locker.json): modular queue + acquire/renew/release lease locks + journaled locker messages + platform-adapted control metadata.
|
|
278
278
|
- [`utility-coordinator-lock-snapshot`](../../recipes/utility-coordinator-lock-snapshot.json): one-shot JSON snapshot of a coordinator-locker state directory.
|
|
279
279
|
- [`music-player`](../../recipes/music-player.json): background local/URL/directory/playlist playback actor controlled by messages.
|
|
280
|
-
- [`actor-worker`](../../recipes/actor-worker.json): canonical mailbox-backed branch worker
|
|
280
|
+
- [`actor-worker`](../../recipes/actor-worker.json): canonical mailbox-backed branch worker reference that claims branch inbox work, emits room-visible task lifecycle messages, writes compact `worker-status.json`, optionally writes per-task result artifacts under `worker-artifacts/`, surfaces stale-claim counts when `stale_claim_ms` is set, and terminates on `control.kill`.
|
|
281
281
|
|
|
282
282
|
### Subagent Atoms
|
|
283
283
|
|
package/docs/actor-messages.md
CHANGED
package/docs/template-recipes.md
CHANGED
|
@@ -80,7 +80,7 @@ defaults:
|
|
|
80
80
|
scope: docs
|
|
81
81
|
mailbox:
|
|
82
82
|
accepts:
|
|
83
|
-
- control.
|
|
83
|
+
- control.kill
|
|
84
84
|
---
|
|
85
85
|
|
|
86
86
|
Human notes can explain intent, examples, or review guidance.
|
|
@@ -155,7 +155,7 @@ Use recipe-level `mailbox` to document the semantic messages a recipe actor acce
|
|
|
155
155
|
"control.continue",
|
|
156
156
|
"control.revise",
|
|
157
157
|
"control.approve",
|
|
158
|
-
"control.
|
|
158
|
+
"control.kill"
|
|
159
159
|
],
|
|
160
160
|
"emits": ["checkpoint.needs_scope", "branch.done", "run.done"]
|
|
161
161
|
}
|
package/lib/actor-worker.ts
CHANGED
|
@@ -3,17 +3,20 @@
|
|
|
3
3
|
* Zones: worker demo, mailbox loop recipe runtime
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { appendFileSync } from "node:fs";
|
|
6
|
+
import { appendFileSync, mkdirSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
|
|
9
|
-
import { appendRoomMessage, ensureRoomMember } from "./actor-rooms.ts";
|
|
9
|
+
import { appendRoomMessage, ensureRoomMember, readBranchInboxMessages } from "./actor-rooms.ts";
|
|
10
10
|
import { handleMailboxLoopOnce, isMailboxLoopStopMessage } from "./mailbox-loop.ts";
|
|
11
11
|
|
|
12
12
|
interface ActorWorkerArgs {
|
|
13
|
+
artifact_dir?: string;
|
|
13
14
|
branch?: string;
|
|
14
15
|
poll_ms?: string | number;
|
|
15
16
|
run?: string;
|
|
17
|
+
stale_claim_ms?: string | number;
|
|
16
18
|
state_dir?: string;
|
|
19
|
+
write_artifacts?: string | boolean;
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
export function parseActorWorkerArgs(argv: string[]): ActorWorkerArgs {
|
|
@@ -41,12 +44,23 @@ function text(value: unknown): string {
|
|
|
41
44
|
return typeof value === "string" ? value : JSON.stringify(value);
|
|
42
45
|
}
|
|
43
46
|
|
|
47
|
+
function enabled(value: unknown): boolean {
|
|
48
|
+
return value !== false && value !== "false" && value !== "0";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function safeName(value: unknown): string {
|
|
52
|
+
return String(value ?? "unknown").replaceAll(/[^A-Za-z0-9_.-]+/g, "_");
|
|
53
|
+
}
|
|
54
|
+
|
|
44
55
|
export async function runActorWorker(argv = process.argv.slice(2)): Promise<void> {
|
|
45
56
|
const args = parseActorWorkerArgs(argv);
|
|
46
57
|
const stateDir = String(args.state_dir ?? "");
|
|
47
58
|
const run = String(args.run ?? "");
|
|
48
59
|
const branch = String(args.branch ?? "worker");
|
|
49
60
|
const pollMs = Math.max(50, Number(args.poll_ms ?? 1000));
|
|
61
|
+
const staleClaimMs = Math.max(0, Number(args.stale_claim_ms ?? 0));
|
|
62
|
+
const artifactDir = String(args.artifact_dir ?? join(stateDir, "worker-artifacts"));
|
|
63
|
+
const writeArtifacts = enabled(args.write_artifacts ?? true);
|
|
50
64
|
|
|
51
65
|
if (!stateDir || !run) {
|
|
52
66
|
throw new Error("usage: actor-worker.mjs --state-dir <dir> --run <id> [--branch worker] [--poll-ms 1000]");
|
|
@@ -55,6 +69,8 @@ export async function runActorWorker(argv = process.argv.slice(2)): Promise<void
|
|
|
55
69
|
const branchAddress = `branch:${run}/${branch}`;
|
|
56
70
|
const roomAddress = `room:${run}`;
|
|
57
71
|
const journalPath = join(stateDir, "worker-events.jsonl");
|
|
72
|
+
const statusPath = join(stateDir, "worker-status.json");
|
|
73
|
+
if (writeArtifacts) mkdirSync(artifactDir, { recursive: true });
|
|
58
74
|
|
|
59
75
|
function journal(event: string, data: Record<string, unknown> = {}): void {
|
|
60
76
|
appendFileSync(
|
|
@@ -63,6 +79,30 @@ export async function runActorWorker(argv = process.argv.slice(2)): Promise<void
|
|
|
63
79
|
);
|
|
64
80
|
}
|
|
65
81
|
|
|
82
|
+
function staleClaims(): number {
|
|
83
|
+
if (staleClaimMs <= 0) return 0;
|
|
84
|
+
const cutoff = Date.now() - staleClaimMs;
|
|
85
|
+
return readBranchInboxMessages(stateDir, run, branchAddress).filter((record) => {
|
|
86
|
+
if (record.status !== "claimed" || !record.claimed_at) return false;
|
|
87
|
+
const claimedAt = Date.parse(record.claimed_at);
|
|
88
|
+
return Number.isFinite(claimedAt) && claimedAt < cutoff;
|
|
89
|
+
}).length;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function status(state: string, data: Record<string, unknown> = {}): void {
|
|
93
|
+
writeFileSync(
|
|
94
|
+
statusPath,
|
|
95
|
+
`${JSON.stringify({ artifact_dir: artifactDir, branch, run, stale_claims: staleClaims(), state, ts: new Date().toISOString(), ...data }, null, 2)}\n`,
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function writeResultArtifact(id: unknown, result: string): string | undefined {
|
|
100
|
+
if (!writeArtifacts) return undefined;
|
|
101
|
+
const path = join(artifactDir, `${safeName(id)}.txt`);
|
|
102
|
+
writeFileSync(path, `${result}\n`);
|
|
103
|
+
return path;
|
|
104
|
+
}
|
|
105
|
+
|
|
66
106
|
function room(type: string, summary: string, body: Record<string, unknown> = {}): void {
|
|
67
107
|
appendRoomMessage(stateDir, "main", {
|
|
68
108
|
body,
|
|
@@ -82,7 +122,10 @@ export async function runActorWorker(argv = process.argv.slice(2)): Promise<void
|
|
|
82
122
|
`${branch} joined as mailbox worker`,
|
|
83
123
|
);
|
|
84
124
|
room("awaiting_assignment", `${branch} awaiting assignment`, { branch });
|
|
85
|
-
journal("worker.started", { branch, run });
|
|
125
|
+
journal("worker.started", { artifact_dir: artifactDir, branch, run, stale_claim_ms: staleClaimMs });
|
|
126
|
+
status("awaiting_assignment", { handled: 0, stale_claim_ms: staleClaimMs });
|
|
127
|
+
|
|
128
|
+
let handled = 0;
|
|
86
129
|
|
|
87
130
|
let stopping = false;
|
|
88
131
|
while (!stopping) {
|
|
@@ -93,6 +136,7 @@ export async function runActorWorker(argv = process.argv.slice(2)): Promise<void
|
|
|
93
136
|
stopping = true;
|
|
94
137
|
room("actor.leave", `${branch} stopping`, { branch, reason: message.type });
|
|
95
138
|
journal("worker.stopping", { id: message.id, type: message.type });
|
|
139
|
+
status("stopping", { handled, reason: message.type });
|
|
96
140
|
return;
|
|
97
141
|
}
|
|
98
142
|
room("task.claim", `${branch} claimed ${message.type}`, {
|
|
@@ -100,19 +144,31 @@ export async function runActorWorker(argv = process.argv.slice(2)): Promise<void
|
|
|
100
144
|
id: message.id,
|
|
101
145
|
type: message.type,
|
|
102
146
|
});
|
|
147
|
+
const result = text(message.body);
|
|
148
|
+
const artifact = writeResultArtifact(message.id, result);
|
|
149
|
+
handled += 1;
|
|
103
150
|
room("task.result", `${branch} handled ${message.type}`, {
|
|
151
|
+
artifact,
|
|
104
152
|
branch,
|
|
105
153
|
id: message.id,
|
|
106
|
-
result
|
|
154
|
+
result,
|
|
107
155
|
type: message.type,
|
|
108
156
|
});
|
|
109
157
|
room("awaiting_assignment", `${branch} awaiting assignment`, { branch });
|
|
110
|
-
journal("task.handled", { id: message.id, type: message.type });
|
|
158
|
+
journal("task.handled", { artifact, id: message.id, type: message.type });
|
|
159
|
+
status("awaiting_assignment", {
|
|
160
|
+
handled,
|
|
161
|
+
last_artifact: artifact,
|
|
162
|
+
last_id: message.id,
|
|
163
|
+
last_type: message.type,
|
|
164
|
+
stale_claim_ms: staleClaimMs,
|
|
165
|
+
});
|
|
111
166
|
},
|
|
112
167
|
{ owner: branchAddress },
|
|
113
168
|
);
|
|
114
169
|
if (!result.handled) await sleep(pollMs);
|
|
115
170
|
}
|
|
116
171
|
|
|
117
|
-
journal("worker.done", { branch, run });
|
|
172
|
+
journal("worker.done", { branch, handled, run });
|
|
173
|
+
status("done", { handled });
|
|
118
174
|
}
|
package/lib/coordinator.ts
CHANGED
|
@@ -285,7 +285,7 @@ async function readRoomTranscript(config) {
|
|
|
285
285
|
}
|
|
286
286
|
|
|
287
287
|
async function synthesize(config, locker) {
|
|
288
|
-
if (!config.artifactPath) return;
|
|
288
|
+
if (!config.artifactPath) return { code: 0, empty: false };
|
|
289
289
|
if (locker) {
|
|
290
290
|
await writeLockerMessage(locker, {
|
|
291
291
|
type: "lock.claim",
|
|
@@ -295,11 +295,15 @@ async function synthesize(config, locker) {
|
|
|
295
295
|
const transcript = await readRoomTranscript(config);
|
|
296
296
|
const prompt = `Synthesize this transcript into a concise Markdown artifact. Mission: ${config.mission}. Include: Title, Consensus, Roles, Protocol, Final Artifact Shape, Next Actions, Open Questions. Use only the transcript evidence below.\n\nTRANSCRIPT:\n${transcript.slice(-24000)}`;
|
|
297
297
|
const result = await runPi(prompt, config.model, config.thinking);
|
|
298
|
+
const output = result.stdout.trim();
|
|
299
|
+
const diagnostics = config.stats
|
|
300
|
+
? `\n\n## Diagnostics\n\nparticipant_attempts=${config.stats.participantAttempts}\nparticipant_success=${config.stats.participantSuccess}\nparticipant_failures=${config.stats.participantFailures}\nsynthesis_code=${result.code}\ntranscript_messages=${transcript.trim() ? transcript.split("\n").length : 0}\n`
|
|
301
|
+
: "";
|
|
298
302
|
await writeFile(
|
|
299
303
|
config.artifactPath,
|
|
300
|
-
|
|
304
|
+
output
|
|
301
305
|
? result.stdout
|
|
302
|
-
:
|
|
306
|
+
: `# Synthesis Artifact\n\nNo synthesis output.${diagnostics}\n`,
|
|
303
307
|
"utf8",
|
|
304
308
|
);
|
|
305
309
|
if (locker) {
|
|
@@ -314,6 +318,7 @@ async function synthesize(config, locker) {
|
|
|
314
318
|
});
|
|
315
319
|
}
|
|
316
320
|
process.stdout.write(`artifact=${config.artifactPath}\n`);
|
|
321
|
+
return { code: result.code, empty: !output };
|
|
317
322
|
}
|
|
318
323
|
|
|
319
324
|
async function readInboxLines(inboxPath) {
|
|
@@ -432,11 +437,17 @@ async function participantRound(role, round, config) {
|
|
|
432
437
|
const address = `branch:${config.runId}/${role.name}`;
|
|
433
438
|
const prompt = `You are ${displayName} (${address}), ${role.persona}. Mission: ${config.mission}. Round ${round}/${config.rounds}. First call inspect target=${config.room} view=previews lines=30 and inspect target=${config.room} view=contacts. Then call message once to ${config.room} from ${address} type=chat.message. Body: 2-4 sentences that react to a named participant, propose the next coordination step, and refine the shared artifact. Use contacts for peer names and addresses. End stdout with summary <=160 chars.`;
|
|
434
439
|
const result = await executeParticipantPrompt(role, prompt, config);
|
|
440
|
+
if (config.stats) {
|
|
441
|
+
config.stats.participantAttempts += 1;
|
|
442
|
+
if (result.code === 0) config.stats.participantSuccess += 1;
|
|
443
|
+
else config.stats.participantFailures += 1;
|
|
444
|
+
}
|
|
435
445
|
process.stdout.write(
|
|
436
446
|
`[${role.name} round ${round}] code=${result.code}\n${result.stdout}\n`,
|
|
437
447
|
);
|
|
438
448
|
if (result.stderr.trim())
|
|
439
449
|
process.stderr.write(`[${role.name} round ${round}] ${result.stderr}\n`);
|
|
450
|
+
return result;
|
|
440
451
|
}
|
|
441
452
|
|
|
442
453
|
async function participantJoin(role, config) {
|
|
@@ -635,6 +646,11 @@ const config = {
|
|
|
635
646
|
artifactPath: arg("artifact-path", ""),
|
|
636
647
|
locker: boolArg("locker", false),
|
|
637
648
|
lockerLeaseMs: numberArg("locker-lease-ms", 600000),
|
|
649
|
+
stats: {
|
|
650
|
+
participantAttempts: 0,
|
|
651
|
+
participantSuccess: 0,
|
|
652
|
+
participantFailures: 0,
|
|
653
|
+
},
|
|
638
654
|
};
|
|
639
655
|
|
|
640
656
|
if (!config.model) {
|
|
@@ -650,7 +666,20 @@ try {
|
|
|
650
666
|
const runMode = coordinatorModes[config.mode];
|
|
651
667
|
if (!runMode) throw new Error(`Unknown coordinator mode: ${config.mode}`);
|
|
652
668
|
await runMode(config, locker);
|
|
653
|
-
await synthesize(config, locker);
|
|
669
|
+
const synthesis = await synthesize(config, locker);
|
|
670
|
+
if (config.stats.participantAttempts > 0 && config.stats.participantSuccess === 0) {
|
|
671
|
+
failures.push(
|
|
672
|
+
`All participant rounds failed: attempts=${config.stats.participantAttempts}`,
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
if (synthesis?.empty && config.stats.participantFailures > 0) {
|
|
676
|
+
failures.push(
|
|
677
|
+
`Synthesis output was empty after participant failures: failures=${config.stats.participantFailures}`,
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
if (synthesis && synthesis.code !== 0) {
|
|
681
|
+
failures.push(`Synthesis command failed: code=${synthesis.code}`);
|
|
682
|
+
}
|
|
654
683
|
} catch (globalError) {
|
|
655
684
|
failures.push(`Global coordinator error: ${globalError.message}`);
|
|
656
685
|
} finally {
|
package/package.json
CHANGED
|
@@ -4,18 +4,20 @@
|
|
|
4
4
|
"args": [
|
|
5
5
|
"repo:path",
|
|
6
6
|
"branch:string",
|
|
7
|
-
"poll_ms:int"
|
|
7
|
+
"poll_ms:int",
|
|
8
|
+
"stale_claim_ms:int",
|
|
9
|
+
"write_artifacts:bool"
|
|
8
10
|
],
|
|
9
11
|
"defaults": {
|
|
10
12
|
"repo": "~/.pi/agent/extensions/pi-actors",
|
|
11
13
|
"branch": "worker",
|
|
12
|
-
"poll_ms": "1000"
|
|
14
|
+
"poll_ms": "1000",
|
|
15
|
+
"stale_claim_ms": "0",
|
|
16
|
+
"write_artifacts": "true"
|
|
13
17
|
},
|
|
14
18
|
"mailbox": {
|
|
15
19
|
"accepts": [
|
|
16
20
|
"task.assign",
|
|
17
|
-
"control.stop",
|
|
18
|
-
"control.cancel",
|
|
19
21
|
"control.kill"
|
|
20
22
|
],
|
|
21
23
|
"emits": [
|
|
@@ -29,7 +31,9 @@
|
|
|
29
31
|
]
|
|
30
32
|
},
|
|
31
33
|
"artifacts": {
|
|
32
|
-
"journal": "{state_dir}/worker-events.jsonl"
|
|
34
|
+
"journal": "{state_dir}/worker-events.jsonl",
|
|
35
|
+
"status": "{state_dir}/worker-status.json",
|
|
36
|
+
"results": "{state_dir}/worker-artifacts"
|
|
33
37
|
},
|
|
34
|
-
"template": "{repo}/scripts/actor-worker.mjs --state-dir {state_dir} --run {run_id} --branch {branch} --poll-ms {poll_ms}"
|
|
38
|
+
"template": "{repo}/scripts/actor-worker.mjs --state-dir {state_dir} --run {run_id} --branch {branch} --poll-ms {poll_ms} --stale-claim-ms {stale_claim_ms} --write-artifacts {write_artifacts}"
|
|
35
39
|
}
|
package/recipes/lens-swarm.json
CHANGED