@getpipher/armory-fleet 0.10.0 → 0.10.2
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/package.json +1 -1
- package/src/index.ts +9 -5
- package/src/panel/fleet-panel.ts +3 -1
- package/src/runtime/reconcile.ts +17 -0
- package/src/tools/subagent.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getpipher/armory-fleet",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The armory suite's subagent orchestrator for the pi coding agent — a cross-harness, superpowers-native fleet where every agent is armory-native from birth.",
|
|
6
6
|
"license": "MIT",
|
package/src/index.ts
CHANGED
|
@@ -258,7 +258,9 @@ export default async function (pi: ExtensionAPI): Promise<void> {
|
|
|
258
258
|
// SPEC-5b-1: per-session RunLog at .pi/fleet/conversations/ (separate from the
|
|
259
259
|
// SPEC-5a phase journal at .pi/fleet/runs/ — different granularity, no filename collision).
|
|
260
260
|
deps.runLog = new RunLog(join(dir, "conversations"));
|
|
261
|
-
|
|
261
|
+
// v0.10.2: pass the in-memory RunRegistry so reconcile syncs it too — otherwise orphaned
|
|
262
|
+
// (process-gone) runs keep status:"running" in memory and the live widget shows a stale ▶ forever.
|
|
263
|
+
const reconciled = reconcileRuns(deps.runLog, { runRegistry: deps.runRegistry });
|
|
262
264
|
if (reconciled.length > 0) {
|
|
263
265
|
ctx.ui.notify(`reconciled ${reconciled.length} interrupted fleet run${reconciled.length > 1 ? "s" : ""} (marked aborted)`, "info");
|
|
264
266
|
}
|
|
@@ -288,15 +290,17 @@ export default async function (pi: ExtensionAPI): Promise<void> {
|
|
|
288
290
|
}
|
|
289
291
|
// SPEC-5b-2: live widget (above editor). Display-only, independent
|
|
290
292
|
// of the /fleet panel. getTheme is a live getter (EditorTheme gotcha). Disposed on session end.
|
|
293
|
+
const getModelContextWindow = (m: string): number | undefined => {
|
|
294
|
+
const { provider, id } = splitModel(m, deps.parentModel.provider);
|
|
295
|
+
return sharedModelRegistry.find(provider, id)?.contextWindow;
|
|
296
|
+
};
|
|
297
|
+
deps.getModelContextWindow = getModelContextWindow;
|
|
291
298
|
fleetWidget = new FleetWidgetController({
|
|
292
299
|
runRegistry: deps.runRegistry,
|
|
293
300
|
bgRuns,
|
|
294
301
|
ui: ctx.ui as never,
|
|
295
302
|
getTheme: () => ctx.ui.theme,
|
|
296
|
-
getModelContextWindow
|
|
297
|
-
const { provider, id } = splitModel(m, deps.parentModel.provider);
|
|
298
|
-
return sharedModelRegistry.find(provider, id)?.contextWindow;
|
|
299
|
-
},
|
|
303
|
+
getModelContextWindow,
|
|
300
304
|
});
|
|
301
305
|
fleetWidget.start();
|
|
302
306
|
|
package/src/panel/fleet-panel.ts
CHANGED
|
@@ -56,6 +56,8 @@ export interface FleetPanelDeps {
|
|
|
56
56
|
tierStore?: TierStore;
|
|
57
57
|
/** SPEC-6-1: callback to rebuild the tier registry after a write. */
|
|
58
58
|
reloadTiers?: () => void;
|
|
59
|
+
/** SPEC-6-1: model contextWindow resolver for Runs-tab ctx% (Surface C). Optional — ctx% hidden when absent. */
|
|
60
|
+
getModelContextWindow?: (model: string) => number | undefined;
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
export interface FleetPanelOpts {
|
|
@@ -146,7 +148,7 @@ export class FleetPanel extends Container {
|
|
|
146
148
|
: this.view === "lifecycle"
|
|
147
149
|
? [...this.deps.lifecycleRuns.values()].map((l: LifecycleRunRecord) => ({ value: l.runId, label: lifecycleRow(l) }))
|
|
148
150
|
: this.view === "runs"
|
|
149
|
-
? buildRunsIndex(this.deps.runLog?.dir ?? "").map((r: RunMeta) => ({ value: r.runId, label: runsRow(r) }))
|
|
151
|
+
? buildRunsIndex(this.deps.runLog?.dir ?? "").map((r: RunMeta) => ({ value: r.runId, label: runsRow(r, this.deps.getModelContextWindow) }))
|
|
150
152
|
: this.view === "agents"
|
|
151
153
|
? [...this.deps.registry.values()].map((a: AgentDef) => ({ value: a.name, label: agentsRow(a) }))
|
|
152
154
|
: this.view === "scheduled"
|
package/src/runtime/reconcile.ts
CHANGED
|
@@ -2,19 +2,32 @@
|
|
|
2
2
|
// SPEC-5b-1 — on pi boot, mark orphan RunLog runs (run:meta with no run:ended whose process
|
|
3
3
|
// is gone) as aborted so the Runs tab doesn't show stale "running" rows across restarts.
|
|
4
4
|
// Foreground orphans; bg/lifecycle orphans are already handled by scanResumeCandidates (SPEC-5a).
|
|
5
|
+
//
|
|
6
|
+
// v0.10.2 patch: reconcile now ALSO syncs the in-memory RunRegistry (opts.runRegistry). Before this,
|
|
7
|
+
// reconcile only wrote run:ended: aborted to the durable RunLog — the in-memory RunRegistry kept
|
|
8
|
+
// status:"running", so the live above-editor widget (filterActive keeps running|queued|paused)
|
|
9
|
+
// rendered a stale ▶ row that ticked forever for every orphaned (process-gone) run.
|
|
5
10
|
import type { RunLog } from "./run-log.ts";
|
|
11
|
+
import type { RunRegistry } from "../engine/run-registry.ts";
|
|
6
12
|
|
|
7
13
|
export interface ReconcileOpts {
|
|
8
14
|
/** Orphans whose startedAt is older than (now - graceMs) are marked aborted. Default 60000. */
|
|
9
15
|
graceMs?: number;
|
|
10
16
|
/** Test injection. Default Date.now(). */
|
|
11
17
|
now?: number;
|
|
18
|
+
/**
|
|
19
|
+
* v0.10.2: the in-memory RunRegistry to sync alongside the durable log. When set, each orphan
|
|
20
|
+
* reconciled in the log is also transitioned to status:"aborted" in memory so the live widget
|
|
21
|
+
* clears its stale ▶ row. Optional — existing callers that pass only a RunLog are unaffected.
|
|
22
|
+
*/
|
|
23
|
+
runRegistry?: RunRegistry;
|
|
12
24
|
}
|
|
13
25
|
|
|
14
26
|
/** Returns the runIds it marked aborted. Idempotent: a run already ended is skipped. */
|
|
15
27
|
export function reconcileRuns(log: RunLog, opts: ReconcileOpts = {}): string[] {
|
|
16
28
|
const grace = opts.graceMs ?? 60_000;
|
|
17
29
|
const now = opts.now ?? Date.now();
|
|
30
|
+
const reg = opts.runRegistry;
|
|
18
31
|
const aborted: string[] = [];
|
|
19
32
|
for (const meta of log.scanMeta()) {
|
|
20
33
|
if (meta.status !== "running") continue;
|
|
@@ -23,6 +36,10 @@ export function reconcileRuns(log: RunLog, opts: ReconcileOpts = {}): string[] {
|
|
|
23
36
|
type: "run:ended", runId: meta.runId, status: "aborted",
|
|
24
37
|
endedAt: now, resultSummary: "process-gone", tokenTotal: meta.tokenTotal,
|
|
25
38
|
});
|
|
39
|
+
// v0.10.2: sync the in-memory registry so the live widget (which reads runRegistry.list(),
|
|
40
|
+
// not the RunLog) clears the orphan's stale ▶ row. No-op when the run isn't in the registry
|
|
41
|
+
// (e.g. a cross-cwd orphan from another session — out of scope for this patch).
|
|
42
|
+
reg?.update(meta.runId, { status: "aborted", endedAt: now });
|
|
26
43
|
aborted.push(meta.runId);
|
|
27
44
|
}
|
|
28
45
|
return aborted;
|
package/src/tools/subagent.ts
CHANGED
|
@@ -56,6 +56,8 @@ export interface SubagentToolDeps {
|
|
|
56
56
|
tierStore?: import("../tiers/tier-store.ts").TierStore;
|
|
57
57
|
/** SPEC-6-1: rebuild the tier registry after a panel write. */
|
|
58
58
|
reloadTiers?: () => void;
|
|
59
|
+
/** SPEC-6-1: model contextWindow resolver for Runs-tab ctx% (Surface C). Optional — ctx% hidden when absent. */
|
|
60
|
+
getModelContextWindow?: (model: string) => number | undefined;
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
/** Build the pi.registerTool definition. Thin wrapper over spawnSubagent. */
|