@llblab/pi-actors 0.25.0 → 0.26.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/BACKLOG.md +4 -8
- package/CHANGELOG.md +7 -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/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/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
package/BACKLOG.md
CHANGED
|
@@ -180,7 +180,7 @@ The backlog is intentionally pruned to the 20% of work most likely to deliver 80
|
|
|
180
180
|
### M-09 Actor Worker v2
|
|
181
181
|
|
|
182
182
|
- Priority: High.
|
|
183
|
-
- Status:
|
|
183
|
+
- Status: Done.
|
|
184
184
|
- Goal: Promote `actor-worker` from a minimal demo into the canonical standard-worker reference pattern.
|
|
185
185
|
- Why now: Mailbox-loop semantics are now stable enough to show artifact production, compact status, and stale-claim recovery without adding a scheduler or broker.
|
|
186
186
|
- Direction:
|
|
@@ -196,7 +196,7 @@ The backlog is intentionally pruned to the 20% of work most likely to deliver 80
|
|
|
196
196
|
### M-10 Dist Package Contract Hardening
|
|
197
197
|
|
|
198
198
|
- Priority: Medium.
|
|
199
|
-
- Status:
|
|
199
|
+
- Status: Done.
|
|
200
200
|
- Goal: Make the dist-first package contract difficult to regress after the 0.24 packaging shift.
|
|
201
201
|
- Why now: `dist/` is now the default JS-only runtime surface and carries mirrored scripts, recipes, fixtures, and skills.
|
|
202
202
|
- Direction:
|
|
@@ -211,7 +211,7 @@ The backlog is intentionally pruned to the 20% of work most likely to deliver 80
|
|
|
211
211
|
### M-11 Actor Termination Semantics
|
|
212
212
|
|
|
213
213
|
- Priority: Medium.
|
|
214
|
-
- Status:
|
|
214
|
+
- Status: Done.
|
|
215
215
|
- Goal: Make `control.kill` the canonical parent-to-actor termination action while keeping `control.stop` and `control.cancel` as actor-domain messages whose meaning depends on the actor protocol.
|
|
216
216
|
- Why now: Mailbox workers need a clearer lifecycle boundary before v2 patterns harden. Treating `stop`, `cancel`, and `kill` as equivalent stop messages blurs actor termination with domain-specific task or playback control.
|
|
217
217
|
- Remaining direction:
|
|
@@ -240,9 +240,5 @@ These are valid ideas but not current focus. Reintroduce only with concrete evid
|
|
|
240
240
|
## Suggested Milestone Order
|
|
241
241
|
|
|
242
242
|
```text
|
|
243
|
-
|
|
244
|
-
M-09
|
|
245
|
-
|
|
246
|
-
0.26 — Package contract hardening and lifecycle semantics:
|
|
247
|
-
M-10, M-11
|
|
243
|
+
Next milestone: choose from deferred items only after concrete actor workflow evidence appears.
|
|
248
244
|
```
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.26.0: Actor Worker v2 and Package Contract Hardening
|
|
6
|
+
|
|
7
|
+
- `[Actor Worker]` Promoted the packaged `actor-worker` into a v2 reference pattern with compact `worker-status.json`, optional per-task result artifacts under `worker-artifacts/`, stale-claim surfacing through status, and artifact metadata on `task.result` room messages.
|
|
8
|
+
- `[Recipes]` Audited packaged async recipe mailbox contracts so `control.stop` and `control.cancel` remain declared only for actor-domain handlers such as locker/coordinator/music control, while generic async recipes expose `control.kill` for runtime termination.
|
|
9
|
+
- `[Packaging]` Hardened dist package regressions with mirrored asset checks for `dist/scripts`, `dist/recipes`, `dist/fixtures`, and `dist/skills`, plus negative checks for stale dist files and source-only runtime imports in built script shims.
|
|
10
|
+
- `[Skills]` Updated the actors skill recipe navigator to document the v2 worker pattern and its `control.kill` termination contract.
|
|
11
|
+
|
|
5
12
|
## 0.25.0: Recipe Doctor Remediation UX
|
|
6
13
|
|
|
7
14
|
- `[Recipe Doctor]` Added prioritized advisory remediations to recipe doctor output, including a compact top action, structured verbose remediation entries, blocked lower-priority candidates for invalid/disabled overrides, and ordered coverage for invalid, disabled, shadowed, and risky shell-boundary recipes.
|
package/README.md
CHANGED
|
@@ -89,7 +89,7 @@ cat > ~/.pi/agent/recipes/docs_review.json <<'JSON'
|
|
|
89
89
|
"async": true,
|
|
90
90
|
"args": ["scope:path", "model:string"],
|
|
91
91
|
"mailbox": {
|
|
92
|
-
"accepts": ["control.
|
|
92
|
+
"accepts": ["control.kill", "control.continue"],
|
|
93
93
|
"emits": ["review.completed", "run.failed"]
|
|
94
94
|
},
|
|
95
95
|
"template": "pi -p --model {model} --no-tools \"Review {scope} for unclear actor-runtime onboarding. Return concise findings.\""
|
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
* Zones: worker demo, mailbox loop recipe runtime
|
|
4
4
|
*/
|
|
5
5
|
interface ActorWorkerArgs {
|
|
6
|
+
artifact_dir?: string;
|
|
6
7
|
branch?: string;
|
|
7
8
|
poll_ms?: string | number;
|
|
8
9
|
run?: string;
|
|
10
|
+
stale_claim_ms?: string | number;
|
|
9
11
|
state_dir?: string;
|
|
12
|
+
write_artifacts?: string | boolean;
|
|
10
13
|
}
|
|
11
14
|
export declare function parseActorWorkerArgs(argv: string[]): ActorWorkerArgs;
|
|
12
15
|
export declare function runActorWorker(argv?: string[]): Promise<void>;
|
package/dist/lib/actor-worker.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Canonical mailbox-backed actor worker entrypoint logic.
|
|
3
3
|
* Zones: worker demo, mailbox loop recipe runtime
|
|
4
4
|
*/
|
|
5
|
-
import { appendFileSync } from "node:fs";
|
|
5
|
+
import { appendFileSync, mkdirSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { join } from "node:path";
|
|
7
|
-
import { appendRoomMessage, ensureRoomMember } from "./actor-rooms.js";
|
|
7
|
+
import { appendRoomMessage, ensureRoomMember, readBranchInboxMessages } from "./actor-rooms.js";
|
|
8
8
|
import { handleMailboxLoopOnce, isMailboxLoopStopMessage } from "./mailbox-loop.js";
|
|
9
9
|
export function parseActorWorkerArgs(argv) {
|
|
10
10
|
const args = {};
|
|
@@ -29,21 +29,54 @@ function sleep(ms) {
|
|
|
29
29
|
function text(value) {
|
|
30
30
|
return typeof value === "string" ? value : JSON.stringify(value);
|
|
31
31
|
}
|
|
32
|
+
function enabled(value) {
|
|
33
|
+
return value !== false && value !== "false" && value !== "0";
|
|
34
|
+
}
|
|
35
|
+
function safeName(value) {
|
|
36
|
+
return String(value ?? "unknown").replaceAll(/[^A-Za-z0-9_.-]+/g, "_");
|
|
37
|
+
}
|
|
32
38
|
export async function runActorWorker(argv = process.argv.slice(2)) {
|
|
33
39
|
const args = parseActorWorkerArgs(argv);
|
|
34
40
|
const stateDir = String(args.state_dir ?? "");
|
|
35
41
|
const run = String(args.run ?? "");
|
|
36
42
|
const branch = String(args.branch ?? "worker");
|
|
37
43
|
const pollMs = Math.max(50, Number(args.poll_ms ?? 1000));
|
|
44
|
+
const staleClaimMs = Math.max(0, Number(args.stale_claim_ms ?? 0));
|
|
45
|
+
const artifactDir = String(args.artifact_dir ?? join(stateDir, "worker-artifacts"));
|
|
46
|
+
const writeArtifacts = enabled(args.write_artifacts ?? true);
|
|
38
47
|
if (!stateDir || !run) {
|
|
39
48
|
throw new Error("usage: actor-worker.mjs --state-dir <dir> --run <id> [--branch worker] [--poll-ms 1000]");
|
|
40
49
|
}
|
|
41
50
|
const branchAddress = `branch:${run}/${branch}`;
|
|
42
51
|
const roomAddress = `room:${run}`;
|
|
43
52
|
const journalPath = join(stateDir, "worker-events.jsonl");
|
|
53
|
+
const statusPath = join(stateDir, "worker-status.json");
|
|
54
|
+
if (writeArtifacts)
|
|
55
|
+
mkdirSync(artifactDir, { recursive: true });
|
|
44
56
|
function journal(event, data = {}) {
|
|
45
57
|
appendFileSync(journalPath, `${JSON.stringify({ event, ts: new Date().toISOString(), ...data })}\n`);
|
|
46
58
|
}
|
|
59
|
+
function staleClaims() {
|
|
60
|
+
if (staleClaimMs <= 0)
|
|
61
|
+
return 0;
|
|
62
|
+
const cutoff = Date.now() - staleClaimMs;
|
|
63
|
+
return readBranchInboxMessages(stateDir, run, branchAddress).filter((record) => {
|
|
64
|
+
if (record.status !== "claimed" || !record.claimed_at)
|
|
65
|
+
return false;
|
|
66
|
+
const claimedAt = Date.parse(record.claimed_at);
|
|
67
|
+
return Number.isFinite(claimedAt) && claimedAt < cutoff;
|
|
68
|
+
}).length;
|
|
69
|
+
}
|
|
70
|
+
function status(state, data = {}) {
|
|
71
|
+
writeFileSync(statusPath, `${JSON.stringify({ artifact_dir: artifactDir, branch, run, stale_claims: staleClaims(), state, ts: new Date().toISOString(), ...data }, null, 2)}\n`);
|
|
72
|
+
}
|
|
73
|
+
function writeResultArtifact(id, result) {
|
|
74
|
+
if (!writeArtifacts)
|
|
75
|
+
return undefined;
|
|
76
|
+
const path = join(artifactDir, `${safeName(id)}.txt`);
|
|
77
|
+
writeFileSync(path, `${result}\n`);
|
|
78
|
+
return path;
|
|
79
|
+
}
|
|
47
80
|
function room(type, summary, body = {}) {
|
|
48
81
|
appendRoomMessage(stateDir, "main", {
|
|
49
82
|
body,
|
|
@@ -55,7 +88,9 @@ export async function runActorWorker(argv = process.argv.slice(2)) {
|
|
|
55
88
|
}
|
|
56
89
|
ensureRoomMember(stateDir, run, "main", branchAddress, { display: branch, role: "worker", status: "present" }, `${branch} joined as mailbox worker`);
|
|
57
90
|
room("awaiting_assignment", `${branch} awaiting assignment`, { branch });
|
|
58
|
-
journal("worker.started", { branch, run });
|
|
91
|
+
journal("worker.started", { artifact_dir: artifactDir, branch, run, stale_claim_ms: staleClaimMs });
|
|
92
|
+
status("awaiting_assignment", { handled: 0, stale_claim_ms: staleClaimMs });
|
|
93
|
+
let handled = 0;
|
|
59
94
|
let stopping = false;
|
|
60
95
|
while (!stopping) {
|
|
61
96
|
const result = await handleMailboxLoopOnce({ address: branchAddress, kind: "branch", run, stateDir }, (message) => {
|
|
@@ -63,6 +98,7 @@ export async function runActorWorker(argv = process.argv.slice(2)) {
|
|
|
63
98
|
stopping = true;
|
|
64
99
|
room("actor.leave", `${branch} stopping`, { branch, reason: message.type });
|
|
65
100
|
journal("worker.stopping", { id: message.id, type: message.type });
|
|
101
|
+
status("stopping", { handled, reason: message.type });
|
|
66
102
|
return;
|
|
67
103
|
}
|
|
68
104
|
room("task.claim", `${branch} claimed ${message.type}`, {
|
|
@@ -70,17 +106,29 @@ export async function runActorWorker(argv = process.argv.slice(2)) {
|
|
|
70
106
|
id: message.id,
|
|
71
107
|
type: message.type,
|
|
72
108
|
});
|
|
109
|
+
const result = text(message.body);
|
|
110
|
+
const artifact = writeResultArtifact(message.id, result);
|
|
111
|
+
handled += 1;
|
|
73
112
|
room("task.result", `${branch} handled ${message.type}`, {
|
|
113
|
+
artifact,
|
|
74
114
|
branch,
|
|
75
115
|
id: message.id,
|
|
76
|
-
result
|
|
116
|
+
result,
|
|
77
117
|
type: message.type,
|
|
78
118
|
});
|
|
79
119
|
room("awaiting_assignment", `${branch} awaiting assignment`, { branch });
|
|
80
|
-
journal("task.handled", { id: message.id, type: message.type });
|
|
120
|
+
journal("task.handled", { artifact, id: message.id, type: message.type });
|
|
121
|
+
status("awaiting_assignment", {
|
|
122
|
+
handled,
|
|
123
|
+
last_artifact: artifact,
|
|
124
|
+
last_id: message.id,
|
|
125
|
+
last_type: message.type,
|
|
126
|
+
stale_claim_ms: staleClaimMs,
|
|
127
|
+
});
|
|
81
128
|
}, { owner: branchAddress });
|
|
82
129
|
if (!result.handled)
|
|
83
130
|
await sleep(pollMs);
|
|
84
131
|
}
|
|
85
|
-
journal("worker.done", { branch, run });
|
|
132
|
+
journal("worker.done", { branch, handled, run });
|
|
133
|
+
status("done", { handled });
|
|
86
134
|
}
|
|
@@ -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
|
}
|
|
@@ -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.0
|
|
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