@llblab/pi-actors 0.24.5 → 0.24.6
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/CHANGELOG.md +4 -0
- package/dist/lib/async-runs.js +11 -2
- package/dist/skills/actors/SKILL.md +1 -1
- package/dist/skills/swarm/SKILL.md +1 -1
- package/lib/async-runs.ts +17 -2
- package/package.json +1 -1
- package/skills/actors/SKILL.md +1 -1
- package/skills/swarm/SKILL.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.24.6: Async Run Restart Status Hotfix
|
|
6
|
+
|
|
7
|
+
- `[Async Runs]` Treat freshly spawned runner PIDs as running during a short Linux `/proc` identity grace window, preventing restart status checks and immediate run messages from misclassifying a new run as `exited` before its command line is observable.
|
|
8
|
+
|
|
5
9
|
## 0.24.5: Auto-Discovered Skills Hotfix
|
|
6
10
|
|
|
7
11
|
- `[Skills]` Auto-discovered source checkouts now contribute their co-located `skills/` directory through Pi resource discovery, so extension-local actors/swarm skills load even when `pi-actors` is used directly from `~/.pi/agent/extensions` instead of installed as a package.
|
package/dist/lib/async-runs.js
CHANGED
|
@@ -19,6 +19,7 @@ import * as RecipeUsage from "./recipe-usage.js";
|
|
|
19
19
|
import { notifyRuntimeWake } from "./runtime-notifier.js";
|
|
20
20
|
const START_LOCK_MAX_AGE_MS = 5 * 60 * 1000;
|
|
21
21
|
const RUN_INBOX_LOCK_TIMEOUT_MS = 5000;
|
|
22
|
+
const RUNNER_IDENTITY_GRACE_MS = 5000;
|
|
22
23
|
const DEFAULT_STATE_ROOT = Paths.getRunStateRoot();
|
|
23
24
|
const DEFAULT_RECIPE_ROOT = Paths.getRecipeRoot();
|
|
24
25
|
function packageRoot() {
|
|
@@ -215,6 +216,12 @@ function pidMatchesRun(pid, cwd, stateDir) {
|
|
|
215
216
|
return false;
|
|
216
217
|
}
|
|
217
218
|
}
|
|
219
|
+
function isWithinRunnerIdentityGrace(meta) {
|
|
220
|
+
const createdAt = typeof meta.createdAt === "string" ? Date.parse(meta.createdAt) : NaN;
|
|
221
|
+
return (Number.isFinite(createdAt) &&
|
|
222
|
+
Date.now() - createdAt >= 0 &&
|
|
223
|
+
Date.now() - createdAt <= RUNNER_IDENTITY_GRACE_MS);
|
|
224
|
+
}
|
|
218
225
|
function tailFile(path, lines) {
|
|
219
226
|
if (!existsSync(path))
|
|
220
227
|
return "";
|
|
@@ -446,7 +453,8 @@ export function getRunStatus(runOrDir) {
|
|
|
446
453
|
const aliveOwnedRunner = Boolean(pid &&
|
|
447
454
|
isAlive(pid) &&
|
|
448
455
|
(!Array.isArray(meta.argv) ||
|
|
449
|
-
pidMatchesRun(pid, String(meta.cwd ?? ""), stateDir)
|
|
456
|
+
pidMatchesRun(pid, String(meta.cwd ?? ""), stateDir) ||
|
|
457
|
+
isWithinRunnerIdentityGrace(meta)));
|
|
450
458
|
const status = result
|
|
451
459
|
? Number(result.code ?? 0) === 0
|
|
452
460
|
? "done"
|
|
@@ -891,7 +899,8 @@ export async function sendRunMessage(runOrDir, message, options = {}) {
|
|
|
891
899
|
const pid = Number(status.pid || 0);
|
|
892
900
|
if (!pid || !isAlive(pid))
|
|
893
901
|
throw new Error(`Run pid is not alive: ${run}`);
|
|
894
|
-
if (!pidMatchesRun(pid, String(status.cwd), stateDir)
|
|
902
|
+
if (!pidMatchesRun(pid, String(status.cwd), stateDir) &&
|
|
903
|
+
!isWithinRunnerIdentityGrace(status))
|
|
895
904
|
throw new Error(`Run pid owner mismatch: ${run}`);
|
|
896
905
|
const endpoint = getRunControlEndpoint(status, stateDir);
|
|
897
906
|
const payload = message.endsWith("\n") ? message : `${message}\n`;
|
|
@@ -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.24.
|
|
5
|
+
version: 0.24.6
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Actors (pi-actors)
|
package/lib/async-runs.ts
CHANGED
|
@@ -41,6 +41,7 @@ import { notifyRuntimeWake } from "./runtime-notifier.ts";
|
|
|
41
41
|
|
|
42
42
|
const START_LOCK_MAX_AGE_MS = 5 * 60 * 1000;
|
|
43
43
|
const RUN_INBOX_LOCK_TIMEOUT_MS = 5000;
|
|
44
|
+
const RUNNER_IDENTITY_GRACE_MS = 5000;
|
|
44
45
|
|
|
45
46
|
export type AsyncRunLaunchSource = "spawn" | "tool";
|
|
46
47
|
|
|
@@ -377,6 +378,16 @@ function pidMatchesRun(pid: number, cwd: string, stateDir: string): boolean {
|
|
|
377
378
|
}
|
|
378
379
|
}
|
|
379
380
|
|
|
381
|
+
function isWithinRunnerIdentityGrace(meta: Record<string, unknown>): boolean {
|
|
382
|
+
const createdAt =
|
|
383
|
+
typeof meta.createdAt === "string" ? Date.parse(meta.createdAt) : NaN;
|
|
384
|
+
return (
|
|
385
|
+
Number.isFinite(createdAt) &&
|
|
386
|
+
Date.now() - createdAt >= 0 &&
|
|
387
|
+
Date.now() - createdAt <= RUNNER_IDENTITY_GRACE_MS
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
380
391
|
function tailFile(path: string, lines: number): string {
|
|
381
392
|
if (!existsSync(path)) return "";
|
|
382
393
|
const content = readFileSync(path, "utf8").trimEnd();
|
|
@@ -658,7 +669,8 @@ export function getRunStatus(runOrDir: string): Record<string, unknown> {
|
|
|
658
669
|
pid &&
|
|
659
670
|
isAlive(pid) &&
|
|
660
671
|
(!Array.isArray(meta.argv) ||
|
|
661
|
-
pidMatchesRun(pid, String(meta.cwd ?? ""), stateDir)
|
|
672
|
+
pidMatchesRun(pid, String(meta.cwd ?? ""), stateDir) ||
|
|
673
|
+
isWithinRunnerIdentityGrace(meta)),
|
|
662
674
|
);
|
|
663
675
|
const status: AsyncRunStatus = result
|
|
664
676
|
? Number(result.code ?? 0) === 0
|
|
@@ -1240,7 +1252,10 @@ export async function sendRunMessage(
|
|
|
1240
1252
|
throw new Error(`Run is not running: ${run}`);
|
|
1241
1253
|
const pid = Number(status.pid || 0);
|
|
1242
1254
|
if (!pid || !isAlive(pid)) throw new Error(`Run pid is not alive: ${run}`);
|
|
1243
|
-
if (
|
|
1255
|
+
if (
|
|
1256
|
+
!pidMatchesRun(pid, String(status.cwd), stateDir) &&
|
|
1257
|
+
!isWithinRunnerIdentityGrace(status)
|
|
1258
|
+
)
|
|
1244
1259
|
throw new Error(`Run pid owner mismatch: ${run}`);
|
|
1245
1260
|
const endpoint = getRunControlEndpoint(status, stateDir);
|
|
1246
1261
|
const payload = message.endsWith("\n") ? message : `${message}\n`;
|
package/package.json
CHANGED
package/skills/actors/SKILL.md
CHANGED
|
@@ -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.24.
|
|
5
|
+
version: 0.24.6
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Actors (pi-actors)
|
package/skills/swarm/SKILL.md
CHANGED