@llblab/pi-actors 0.12.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.
Files changed (86) hide show
  1. package/AGENTS.md +72 -0
  2. package/BACKLOG.md +38 -0
  3. package/CHANGELOG.md +179 -0
  4. package/README.md +338 -0
  5. package/docs/README.md +21 -0
  6. package/docs/actor-messages.md +149 -0
  7. package/docs/async-runs.md +335 -0
  8. package/docs/command-templates.md +424 -0
  9. package/docs/component-recipes.md +148 -0
  10. package/docs/recipe-library.md +176 -0
  11. package/docs/task-first-recipes.md +233 -0
  12. package/docs/template-recipes.md +285 -0
  13. package/docs/tool-registry.md +142 -0
  14. package/index.ts +198 -0
  15. package/lib/actor-messages.ts +120 -0
  16. package/lib/async-runs.ts +688 -0
  17. package/lib/command-templates.ts +795 -0
  18. package/lib/config.ts +266 -0
  19. package/lib/execution.ts +720 -0
  20. package/lib/file-state.ts +24 -0
  21. package/lib/identity.ts +29 -0
  22. package/lib/observability.ts +525 -0
  23. package/lib/output.ts +123 -0
  24. package/lib/paths.ts +35 -0
  25. package/lib/prompts.ts +75 -0
  26. package/lib/recipe-references.ts +586 -0
  27. package/lib/registry.ts +302 -0
  28. package/lib/runtime.ts +101 -0
  29. package/lib/schema.ts +402 -0
  30. package/lib/temp.ts +44 -0
  31. package/lib/tools.ts +651 -0
  32. package/package.json +52 -0
  33. package/recipes/music-player.json +25 -0
  34. package/recipes/pipeline-architect-coordinator.json +88 -0
  35. package/recipes/pipeline-artifact-report.json +52 -0
  36. package/recipes/pipeline-artifact-write.json +66 -0
  37. package/recipes/pipeline-async-run-ops.json +67 -0
  38. package/recipes/pipeline-checkpoint-continuation.json +57 -0
  39. package/recipes/pipeline-development-tasking.json +73 -0
  40. package/recipes/pipeline-docs-maintenance.json +72 -0
  41. package/recipes/pipeline-media-library.json +51 -0
  42. package/recipes/pipeline-quorum-review.json +72 -0
  43. package/recipes/pipeline-release-readiness.json +83 -0
  44. package/recipes/pipeline-repo-health.json +81 -0
  45. package/recipes/pipeline-research-synthesis.json +87 -0
  46. package/recipes/pipeline-review-readiness.json +49 -0
  47. package/recipes/subagent-artifact.json +26 -0
  48. package/recipes/subagent-checkpoint.json +27 -0
  49. package/recipes/subagent-conflict-report.json +25 -0
  50. package/recipes/subagent-contradiction-map.json +26 -0
  51. package/recipes/subagent-critic.json +28 -0
  52. package/recipes/subagent-evidence-map.json +26 -0
  53. package/recipes/subagent-followup.json +27 -0
  54. package/recipes/subagent-judge.json +26 -0
  55. package/recipes/subagent-merge.json +26 -0
  56. package/recipes/subagent-message.json +29 -0
  57. package/recipes/subagent-normalize.json +24 -0
  58. package/recipes/subagent-plan.json +26 -0
  59. package/recipes/subagent-prompt.json +22 -0
  60. package/recipes/subagent-quorum.json +41 -0
  61. package/recipes/subagent-review-coordinator.json +107 -0
  62. package/recipes/subagent-review.json +30 -0
  63. package/recipes/subagent-task-card.json +28 -0
  64. package/recipes/subagent-tools.json +17 -0
  65. package/recipes/subagent-verify.json +27 -0
  66. package/recipes/subagents-prompts.json +32 -0
  67. package/recipes/utility-actor-message.json +24 -0
  68. package/recipes/utility-artifact-manifest.json +17 -0
  69. package/recipes/utility-artifact-write.json +17 -0
  70. package/recipes/utility-changelog-head.json +12 -0
  71. package/recipes/utility-changelog-section.json +14 -0
  72. package/recipes/utility-git-log.json +12 -0
  73. package/recipes/utility-git-status.json +10 -0
  74. package/recipes/utility-jsonl-tail.json +11 -0
  75. package/recipes/utility-markdown-index.json +15 -0
  76. package/recipes/utility-package-summary.json +12 -0
  77. package/recipes/utility-playlist-build.json +18 -0
  78. package/recipes/utility-playlist-scan.json +12 -0
  79. package/recipes/utility-run-state-files.json +14 -0
  80. package/recipes/utility-run-summary.json +12 -0
  81. package/recipes/utility-validate-recipe.json +14 -0
  82. package/recipes/utility-validation-wrapper.json +14 -0
  83. package/scripts/async-runner.mjs +170 -0
  84. package/scripts/music-player.mjs +637 -0
  85. package/scripts/recipe-utils.mjs +273 -0
  86. package/scripts/validate-recipe.mjs +89 -0
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Actor message protocol helpers.
3
+ * Zones: 0.10 draft communication protocol, addressed messages, mailbox metadata
4
+ * Owns pure validation/normalization for the semantic message envelope; transport routing stays in adapters.
5
+ */
6
+
7
+ export type ActorAddressKind =
8
+ | "branch"
9
+ | "coordinator"
10
+ | "run"
11
+ | "session"
12
+ | "tool";
13
+
14
+ export interface ActorAddress {
15
+ kind: ActorAddressKind;
16
+ value?: string;
17
+ branch?: string;
18
+ }
19
+
20
+ export interface ActorMessage {
21
+ to: string;
22
+ type: string;
23
+ body?: unknown;
24
+ correlation_id?: string;
25
+ from?: string;
26
+ metadata?: Record<string, unknown>;
27
+ reply_to?: string;
28
+ summary?: string;
29
+ }
30
+
31
+ const ADDRESS_PATTERN = /^[A-Za-z0-9_.-]+$/;
32
+ const MESSAGE_TYPE_PATTERN = /^[A-Za-z][A-Za-z0-9_.:-]*$/;
33
+
34
+ function assertToken(value: string, label: string): string {
35
+ const normalized = value.trim();
36
+ if (!normalized) throw new Error(`${label} is required`);
37
+ if (!ADDRESS_PATTERN.test(normalized)) {
38
+ throw new Error(`${label} contains unsupported characters: ${value}`);
39
+ }
40
+ return normalized;
41
+ }
42
+
43
+ export function parseActorAddress(address: string): ActorAddress {
44
+ const value = address.trim();
45
+ if (value === "coordinator") return { kind: "coordinator" };
46
+ const separator = value.indexOf(":");
47
+ if (separator < 0) throw new Error(`Actor address must include kind: ${address}`);
48
+ const kind = value.slice(0, separator) as ActorAddressKind;
49
+ const rest = value.slice(separator + 1);
50
+ switch (kind) {
51
+ case "branch": {
52
+ const [run, branch, ...extra] = rest.split("/");
53
+ if (extra.length > 0) throw new Error(`Branch address has too many parts: ${address}`);
54
+ return {
55
+ kind,
56
+ value: assertToken(run || "", "branch run"),
57
+ branch: assertToken(branch || "", "branch id"),
58
+ };
59
+ }
60
+ case "run":
61
+ case "session":
62
+ case "tool":
63
+ return { kind, value: assertToken(rest, `${kind} address`) };
64
+ default:
65
+ throw new Error(`Unsupported actor address kind: ${kind}`);
66
+ }
67
+ }
68
+
69
+ export function formatActorAddress(address: ActorAddress): string {
70
+ if (address.kind === "coordinator") return "coordinator";
71
+ if (address.kind === "branch") {
72
+ return `branch:${assertToken(address.value || "", "branch run")}/${assertToken(address.branch || "", "branch id")}`;
73
+ }
74
+ return `${address.kind}:${assertToken(address.value || "", `${address.kind} address`)}`;
75
+ }
76
+
77
+ function normalizeOptionalString(value: unknown, label: string): string | undefined {
78
+ if (value === undefined || value === null) return undefined;
79
+ if (typeof value !== "string") throw new Error(`${label} must be a string`);
80
+ const normalized = value.trim();
81
+ return normalized || undefined;
82
+ }
83
+
84
+ function normalizeMetadata(value: unknown): Record<string, unknown> | undefined {
85
+ if (value === undefined || value === null) return undefined;
86
+ if (typeof value !== "object" || Array.isArray(value)) {
87
+ throw new Error("message metadata must be an object");
88
+ }
89
+ return value as Record<string, unknown>;
90
+ }
91
+
92
+ export function normalizeActorMessage(input: unknown): ActorMessage {
93
+ if (!input || typeof input !== "object" || Array.isArray(input)) {
94
+ throw new Error("actor message must be an object");
95
+ }
96
+ const record = input as Record<string, unknown>;
97
+ const to = normalizeOptionalString(record.to, "message.to");
98
+ if (!to) throw new Error("message.to is required");
99
+ const parsedTo = parseActorAddress(to);
100
+ const type = normalizeOptionalString(record.type, "message.type");
101
+ if (!type) throw new Error("message.type is required");
102
+ if (!MESSAGE_TYPE_PATTERN.test(type)) {
103
+ throw new Error(`message.type contains unsupported characters: ${type}`);
104
+ }
105
+ const from = normalizeOptionalString(record.from, "message.from");
106
+ if (from) parseActorAddress(from);
107
+ const normalizedTo = formatActorAddress(parsedTo);
108
+ return {
109
+ to: normalizedTo,
110
+ type,
111
+ ...(record.body !== undefined ? { body: record.body } : {}),
112
+ ...(record.correlation_id !== undefined
113
+ ? { correlation_id: String(record.correlation_id) }
114
+ : {}),
115
+ ...(from ? { from: formatActorAddress(parseActorAddress(from)) } : {}),
116
+ ...(record.metadata !== undefined ? { metadata: normalizeMetadata(record.metadata) } : {}),
117
+ ...(record.reply_to !== undefined ? { reply_to: String(record.reply_to) } : {}),
118
+ ...(record.summary !== undefined ? { summary: String(record.summary) } : {}),
119
+ };
120
+ }