@llblab/pi-actors 0.41.1 → 0.42.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 +11 -6
- package/BACKLOG.md +2 -62
- package/CHANGELOG.md +15 -0
- package/README.md +22 -4
- package/dist/index.js +25 -121
- package/dist/lib/async-runs.d.ts +25 -5
- package/dist/lib/async-runs.js +136 -47
- package/dist/lib/automatic-review-runtime.d.ts +18 -0
- package/dist/lib/automatic-review-runtime.js +96 -0
- package/dist/lib/draft-consolidation-transaction.d.ts +65 -0
- package/dist/lib/draft-consolidation-transaction.js +610 -0
- package/dist/lib/draft-consolidation.d.ts +35 -0
- package/dist/lib/draft-consolidation.js +126 -0
- package/dist/lib/draft-review.d.ts +56 -0
- package/dist/lib/draft-review.js +254 -0
- package/dist/lib/draft-sleep.d.ts +65 -0
- package/dist/lib/draft-sleep.js +468 -0
- package/dist/lib/file-state.d.ts +8 -1
- package/dist/lib/file-state.js +115 -18
- package/dist/lib/inspector-actions.d.ts +16 -0
- package/dist/lib/inspector-actions.js +57 -0
- package/dist/lib/inspector-command.d.ts +7 -0
- package/dist/lib/inspector-command.js +37 -0
- package/dist/lib/inspector-overlay.d.ts +20 -3
- package/dist/lib/inspector-overlay.js +275 -74
- package/dist/lib/inspector.d.ts +9 -0
- package/dist/lib/inspector.js +48 -0
- package/dist/lib/observability.d.ts +1 -0
- package/dist/lib/observability.js +11 -1
- package/dist/lib/paths.d.ts +7 -0
- package/dist/lib/paths.js +28 -0
- package/dist/lib/recipes-discovery.js +32 -24
- package/dist/lib/recipes-usage.d.ts +18 -6
- package/dist/lib/recipes-usage.js +445 -34
- package/dist/lib/review-control.d.ts +14 -0
- package/dist/lib/review-control.js +111 -0
- package/dist/lib/review-diagnostics.d.ts +11 -0
- package/dist/lib/review-diagnostics.js +148 -0
- package/dist/lib/review-projection.d.ts +14 -0
- package/dist/lib/review-projection.js +170 -0
- package/dist/lib/run-ui-runtime.d.ts +18 -0
- package/dist/lib/run-ui-runtime.js +123 -0
- package/dist/lib/runs-artifacts.d.ts +1 -1
- package/dist/lib/runs-artifacts.js +1 -1
- package/dist/lib/runs-control.d.ts +8 -2
- package/dist/lib/runs-control.js +23 -6
- package/dist/lib/runs-identity.d.ts +1 -1
- package/dist/lib/runs-identity.js +1 -1
- package/dist/lib/runs-index.d.ts +11 -2
- package/dist/lib/runs-index.js +46 -23
- package/dist/lib/runs-mailbox.d.ts +1 -1
- package/dist/lib/runs-mailbox.js +1 -1
- package/dist/lib/runs-messages.d.ts +1 -1
- package/dist/lib/runs-messages.js +1 -1
- package/dist/lib/runs-outbox.d.ts +1 -1
- package/dist/lib/runs-outbox.js +1 -1
- package/dist/lib/runs-ownership.d.ts +1 -1
- package/dist/lib/runs-ownership.js +1 -1
- package/dist/lib/runs-parent-teardown.d.ts +51 -0
- package/dist/lib/runs-parent-teardown.js +172 -0
- package/dist/lib/runs-process.d.ts +1 -1
- package/dist/lib/runs-process.js +1 -1
- package/dist/lib/runs-retention.d.ts +1 -1
- package/dist/lib/runs-retention.js +1 -1
- package/dist/lib/runs-start.d.ts +5 -3
- package/dist/lib/runs-start.js +6 -48
- package/dist/lib/runs-status.d.ts +5 -3
- package/dist/lib/runs-status.js +4 -6
- package/dist/lib/runtime.d.ts +7 -1
- package/dist/lib/runtime.js +32 -18
- package/dist/lib/tool-review-lineage-transaction.d.ts +27 -0
- package/dist/lib/tool-review-lineage-transaction.js +597 -0
- package/dist/lib/tool-review-lineage.d.ts +24 -0
- package/dist/lib/tool-review-lineage.js +98 -0
- package/dist/lib/tool-review-scheduler.d.ts +80 -0
- package/dist/lib/tool-review-scheduler.js +494 -0
- package/dist/lib/tool-review-transaction.d.ts +50 -0
- package/dist/lib/tool-review-transaction.js +362 -0
- package/dist/lib/tool-review.d.ts +56 -0
- package/dist/lib/tool-review.js +197 -0
- package/dist/lib/tools-inspect.js +26 -3
- package/dist/lib/tools-local.js +4 -2
- package/dist/lib/tools-message.d.ts +1 -0
- package/dist/lib/tools-message.js +29 -17
- package/dist/lib/tools-spawn.js +4 -1
- package/dist/lib/tools.d.ts +1 -0
- package/dist/lib/tools.js +1 -0
- package/dist/recipes/draft-review.json +24 -0
- package/dist/recipes/tool-review.json +24 -0
- package/dist/scripts/release-gates.mjs +165 -0
- package/dist/skills/actors/SKILL.md +9 -8
- package/dist/skills/swarm/SKILL.md +1 -1
- package/docs/actor-inspector.md +20 -11
- package/docs/async-runs.md +9 -1
- package/docs/recipe-library.md +7 -3
- package/docs/template-recipes.md +4 -11
- package/docs/tool-registry.md +11 -4
- package/index.ts +27 -142
- package/lib/async-runs.ts +218 -62
- package/lib/automatic-review-runtime.ts +135 -0
- package/lib/draft-consolidation-transaction.ts +821 -0
- package/lib/draft-consolidation.ts +181 -0
- package/lib/draft-review.ts +325 -0
- package/lib/draft-sleep.ts +576 -0
- package/lib/file-state.ts +143 -19
- package/lib/inspector-actions.ts +79 -0
- package/lib/inspector-command.ts +54 -0
- package/lib/inspector-overlay.ts +325 -91
- package/lib/inspector.ts +72 -0
- package/lib/observability.ts +14 -1
- package/lib/paths.ts +43 -0
- package/lib/recipes-discovery.ts +34 -26
- package/lib/recipes-usage.ts +569 -40
- package/lib/review-control.ts +137 -0
- package/lib/review-diagnostics.ts +164 -0
- package/lib/review-projection.ts +200 -0
- package/lib/run-ui-runtime.ts +153 -0
- package/lib/runs-artifacts.ts +1 -1
- package/lib/runs-control.ts +49 -5
- package/lib/runs-identity.ts +1 -1
- package/lib/runs-index.ts +57 -21
- package/lib/runs-mailbox.ts +1 -1
- package/lib/runs-messages.ts +1 -1
- package/lib/runs-outbox.ts +1 -1
- package/lib/runs-ownership.ts +1 -1
- package/lib/runs-parent-teardown.ts +257 -0
- package/lib/runs-process.ts +1 -1
- package/lib/runs-retention.ts +1 -1
- package/lib/runs-start.ts +12 -68
- package/lib/runs-status.ts +12 -8
- package/lib/runtime.ts +34 -17
- package/lib/tool-review-lineage-transaction.ts +881 -0
- package/lib/tool-review-lineage.ts +145 -0
- package/lib/tool-review-scheduler.ts +635 -0
- package/lib/tool-review-transaction.ts +563 -0
- package/lib/tool-review.ts +270 -0
- package/lib/tools-inspect.ts +33 -3
- package/lib/tools-local.ts +8 -2
- package/lib/tools-message.ts +45 -30
- package/lib/tools-spawn.ts +8 -1
- package/lib/tools.ts +5 -0
- package/package.json +3 -2
- package/recipes/draft-review.json +24 -0
- package/recipes/tool-review.json +24 -0
- package/scripts/release-gates.mjs +165 -0
- package/skills/actors/SKILL.md +9 -8
- package/skills/swarm/SKILL.md +1 -1
package/lib/inspector.ts
CHANGED
|
@@ -74,6 +74,7 @@ export interface ActorInspectorPreviewReadOptions {
|
|
|
74
74
|
|
|
75
75
|
export interface ActorInspectorRunItem {
|
|
76
76
|
run: string;
|
|
77
|
+
runInstanceId?: string;
|
|
77
78
|
status: string;
|
|
78
79
|
updatedAt?: string;
|
|
79
80
|
}
|
|
@@ -89,6 +90,10 @@ export function readActorInspectorRuns(
|
|
|
89
90
|
.flatMap((entry) => {
|
|
90
91
|
const stateDir = path.join(stateRoot, entry.name);
|
|
91
92
|
if (!matchesOwner(stateDir, ownerId)) return [];
|
|
93
|
+
const runMeta = readJsonFileResilient<Record<string, unknown>>(
|
|
94
|
+
path.join(stateDir, "run.json"),
|
|
95
|
+
{},
|
|
96
|
+
).value;
|
|
92
97
|
const progress = readJsonFileResilient<Record<string, unknown>>(
|
|
93
98
|
path.join(stateDir, "progress.json"),
|
|
94
99
|
{},
|
|
@@ -99,6 +104,9 @@ export function readActorInspectorRuns(
|
|
|
99
104
|
).value;
|
|
100
105
|
return [{
|
|
101
106
|
run: entry.name,
|
|
107
|
+
...(typeof runMeta.run_instance_id === "string"
|
|
108
|
+
? { runInstanceId: runMeta.run_instance_id }
|
|
109
|
+
: {}),
|
|
102
110
|
status: String(progress.phase ?? (Object.keys(result).length ? "terminal" : "unknown")),
|
|
103
111
|
...(typeof progress.updatedAt === "string"
|
|
104
112
|
? { updatedAt: progress.updatedAt }
|
|
@@ -119,6 +127,70 @@ export function readActorInspectorRuns(
|
|
|
119
127
|
}
|
|
120
128
|
}
|
|
121
129
|
|
|
130
|
+
export interface ActorInspectorRecipeView {
|
|
131
|
+
composition: Array<Record<string, unknown>>;
|
|
132
|
+
definition?: Record<string, unknown>;
|
|
133
|
+
diagnostics: string[];
|
|
134
|
+
identity: Record<string, unknown>;
|
|
135
|
+
launch: Record<string, unknown>;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function readActorInspectorRecipe(
|
|
139
|
+
stateDir: string,
|
|
140
|
+
): ActorInspectorRecipeView {
|
|
141
|
+
const result = readJsonFileResilient<Record<string, unknown>>(
|
|
142
|
+
path.join(stateDir, "run.json"),
|
|
143
|
+
{},
|
|
144
|
+
);
|
|
145
|
+
const meta = result.value;
|
|
146
|
+
const contexts = Array.isArray(meta.recipe_context_records)
|
|
147
|
+
? meta.recipe_context_records
|
|
148
|
+
.filter((entry): entry is Record<string, unknown> =>
|
|
149
|
+
Boolean(entry && typeof entry === "object" && !Array.isArray(entry)),
|
|
150
|
+
)
|
|
151
|
+
: [];
|
|
152
|
+
const primary = contexts.find((entry) => entry.depth === 0) ?? contexts[0];
|
|
153
|
+
const definition = primary?.recipe && typeof primary.recipe === "object" &&
|
|
154
|
+
!Array.isArray(primary.recipe)
|
|
155
|
+
? primary.recipe as Record<string, unknown>
|
|
156
|
+
: undefined;
|
|
157
|
+
const redacted = (value: unknown): unknown =>
|
|
158
|
+
SessionEvidence.redactSessionEvidenceValue(value);
|
|
159
|
+
const redactedRecord = (value: Record<string, unknown>): Record<string, unknown> =>
|
|
160
|
+
redacted(Object.fromEntries(
|
|
161
|
+
Object.entries(value).filter(([, entry]) => entry !== undefined),
|
|
162
|
+
)) as Record<string, unknown>;
|
|
163
|
+
return {
|
|
164
|
+
composition: contexts.map((entry) => redactedRecord({
|
|
165
|
+
...(typeof entry.alias === "string" ? { alias: entry.alias } : {}),
|
|
166
|
+
depth: entry.depth,
|
|
167
|
+
file: entry.file,
|
|
168
|
+
import_path: entry.import_path,
|
|
169
|
+
name: entry.name,
|
|
170
|
+
})),
|
|
171
|
+
...(definition
|
|
172
|
+
? { definition: redactedRecord(definition) }
|
|
173
|
+
: {}),
|
|
174
|
+
diagnostics: result.diagnostics.map((diagnostic) => diagnostic.message),
|
|
175
|
+
identity: redactedRecord({
|
|
176
|
+
run: meta.run,
|
|
177
|
+
recipe: meta.recipe,
|
|
178
|
+
recipe_file: meta.recipe_file,
|
|
179
|
+
launch_source: meta.launch_source,
|
|
180
|
+
}),
|
|
181
|
+
launch: redactedRecord({
|
|
182
|
+
cwd: meta.cwd,
|
|
183
|
+
template: meta.template,
|
|
184
|
+
values: meta.values,
|
|
185
|
+
model_policy: meta.model_policy,
|
|
186
|
+
mailbox: meta.mailbox,
|
|
187
|
+
artifacts: meta.artifacts,
|
|
188
|
+
notification_policy: meta.notification_policy,
|
|
189
|
+
retire_when: meta.retire_when,
|
|
190
|
+
}),
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
122
194
|
export interface ActorInspectorTurnItem extends SessionEvidence.SessionEvidenceTurn {
|
|
123
195
|
commandId: string;
|
|
124
196
|
diagnostics: string[];
|
package/lib/observability.ts
CHANGED
|
@@ -43,6 +43,7 @@ export interface RunObservation {
|
|
|
43
43
|
artifacts?: Record<string, string>;
|
|
44
44
|
launchSource?: AsyncRuns.AsyncRunLaunchSource;
|
|
45
45
|
modelPolicy?: Record<string, unknown>;
|
|
46
|
+
notificationPolicy?: "normal" | "silent";
|
|
46
47
|
recipeFile?: string;
|
|
47
48
|
terminalHandled?: boolean;
|
|
48
49
|
retireWhen?: string;
|
|
@@ -531,6 +532,9 @@ function observeRun(stateDir: string): RunObservation | undefined {
|
|
|
531
532
|
!Array.isArray(status.model_policy)
|
|
532
533
|
? { modelPolicy: status.model_policy as Record<string, unknown> }
|
|
533
534
|
: {}),
|
|
535
|
+
...(status.notification_policy === "silent"
|
|
536
|
+
? { notificationPolicy: "silent" as const }
|
|
537
|
+
: {}),
|
|
534
538
|
...(typeof status.recipe_file === "string"
|
|
535
539
|
? { recipeFile: status.recipe_file }
|
|
536
540
|
: {}),
|
|
@@ -919,7 +923,11 @@ export function detectRunTransitions(
|
|
|
919
923
|
for (const run of summary.runs) {
|
|
920
924
|
const key = runObservationKey(run);
|
|
921
925
|
const old = previous.get(key);
|
|
922
|
-
if (
|
|
926
|
+
if (
|
|
927
|
+
run.notificationPolicy !== "silent" &&
|
|
928
|
+
!run.terminalHandled &&
|
|
929
|
+
TERMINAL.has(run.status)
|
|
930
|
+
) {
|
|
923
931
|
transitions.push({
|
|
924
932
|
from: old ?? "running",
|
|
925
933
|
run: run.run,
|
|
@@ -1037,6 +1045,11 @@ export function detectRunOutboxEvents(
|
|
|
1037
1045
|
const key = run.stateDir ?? run.run;
|
|
1038
1046
|
const records = readOutboxRecords(run);
|
|
1039
1047
|
const previousCount = previousLineCounts.get(key) ?? 0;
|
|
1048
|
+
if (run.notificationPolicy === "silent") {
|
|
1049
|
+
previousLineCounts.set(key, records.length);
|
|
1050
|
+
seenEventIds.set(key, seenEventIds.get(key) ?? new Set<string>());
|
|
1051
|
+
continue;
|
|
1052
|
+
}
|
|
1040
1053
|
const start = Math.min(previousCount, records.length);
|
|
1041
1054
|
const seen = seenEventIds.get(key) ?? new Set<string>();
|
|
1042
1055
|
for (let index = start; index < records.length; index += 1) {
|
package/lib/paths.ts
CHANGED
|
@@ -17,6 +17,13 @@ export function getAgentDir(
|
|
|
17
17
|
: join(homedir(), ".pi", "agent");
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
export function isAutomaticRecipeReviewEnabled(
|
|
21
|
+
env: Record<string, string | undefined> = process.env,
|
|
22
|
+
): boolean {
|
|
23
|
+
const value = env.PI_ACTORS_AUTOMATIC_REVIEW?.trim().toLowerCase();
|
|
24
|
+
return value === undefined || !["0", "false", "off"].includes(value);
|
|
25
|
+
}
|
|
26
|
+
|
|
20
27
|
export interface ExtensionRuntimePaths {
|
|
21
28
|
configPath: string;
|
|
22
29
|
runStateRoot: string;
|
|
@@ -38,6 +45,42 @@ export function getRunStateRoot(agentDir = getAgentDir()): string {
|
|
|
38
45
|
return join(getExtensionTmpDir(agentDir), "runs");
|
|
39
46
|
}
|
|
40
47
|
|
|
48
|
+
export function getDraftSleepRoot(agentDir = getAgentDir()): string {
|
|
49
|
+
return join(getExtensionTmpDir(agentDir), "draft-sleep");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function getDraftSleepStatePath(agentDir = getAgentDir()): string {
|
|
53
|
+
return join(getDraftSleepRoot(agentDir), "state.json");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function getDraftSleepBatchDir(
|
|
57
|
+
batchId: string,
|
|
58
|
+
agentDir = getAgentDir(),
|
|
59
|
+
): string {
|
|
60
|
+
if (!/^[a-f0-9-]{36}$/u.test(batchId)) {
|
|
61
|
+
throw new Error("Invalid draft sleep batch id.");
|
|
62
|
+
}
|
|
63
|
+
return join(getDraftSleepRoot(agentDir), "batches", batchId);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function getToolReviewRoot(agentDir = getAgentDir()): string {
|
|
67
|
+
return join(getExtensionTmpDir(agentDir), "tool-review");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function getToolReviewStatePath(agentDir = getAgentDir()): string {
|
|
71
|
+
return join(getToolReviewRoot(agentDir), "state.json");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function getToolReviewBatchDir(
|
|
75
|
+
reviewId: string,
|
|
76
|
+
agentDir = getAgentDir(),
|
|
77
|
+
): string {
|
|
78
|
+
if (!/^[a-f0-9-]{36}$/u.test(reviewId)) {
|
|
79
|
+
throw new Error("Invalid tool review id.");
|
|
80
|
+
}
|
|
81
|
+
return join(getToolReviewRoot(agentDir), "batches", reviewId);
|
|
82
|
+
}
|
|
83
|
+
|
|
41
84
|
export function getExtensionRuntimePaths(
|
|
42
85
|
agentDir = getAgentDir(),
|
|
43
86
|
): ExtensionRuntimePaths {
|
package/lib/recipes-discovery.ts
CHANGED
|
@@ -703,32 +703,40 @@ function templatePreview(value: unknown): string | undefined {
|
|
|
703
703
|
|
|
704
704
|
export function listDraftRecipes(root: string): Array<Record<string, unknown>> {
|
|
705
705
|
return listRecipeFiles(root).map((path) => {
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
706
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
707
|
+
const id = RecipesReferences.getRecipeIdFromPath(path);
|
|
708
|
+
const bytes = readFileSync(path);
|
|
709
|
+
const fingerprint = createHash("sha256").update(bytes).digest("hex");
|
|
710
|
+
const stat = statSync(path);
|
|
711
|
+
const config = RecipesReferences.readRawRecipeConfig(path);
|
|
712
|
+
const resolved = RecipesReferences.readResolvedRecipeConfig(path);
|
|
713
|
+
const diagnostics = getRecipeConfigDiagnostics(path, resolved);
|
|
714
|
+
const after = readFileSync(path);
|
|
715
|
+
if (createHash("sha256").update(after).digest("hex") !== fingerprint) {
|
|
716
|
+
continue;
|
|
717
|
+
}
|
|
718
|
+
const sourceRun = String(config?.description ?? "").match(
|
|
719
|
+
/spawn run ([^\s]+)/,
|
|
720
|
+
)?.[1];
|
|
721
|
+
const preview = templatePreview(config?.template);
|
|
722
|
+
const riskLabels = getRecipeRiskLabels(resolved);
|
|
723
|
+
return {
|
|
724
|
+
id,
|
|
725
|
+
path,
|
|
726
|
+
sha256: fingerprint,
|
|
727
|
+
size: bytes.byteLength,
|
|
728
|
+
created_at: stat.birthtime.toISOString(),
|
|
729
|
+
modified_at: stat.mtime.toISOString(),
|
|
730
|
+
valid: Boolean(resolved),
|
|
731
|
+
diagnostics,
|
|
732
|
+
...(riskLabels.length ? { risk_labels: riskLabels } : {}),
|
|
733
|
+
...(config?.description ? { description: config.description } : {}),
|
|
734
|
+
...(sourceRun ? { source_run: sourceRun } : {}),
|
|
735
|
+
...(config?.async !== undefined ? { async: config.async } : {}),
|
|
736
|
+
...(preview ? { template_preview: preview } : {}),
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
throw new Error(`Draft changed repeatedly during inventory: ${path}`);
|
|
732
740
|
});
|
|
733
741
|
}
|
|
734
742
|
|