harnery 0.42.0 → 0.44.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/README.md +3 -3
- package/dist/commander.d.ts +16 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +18 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +95 -52
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +38 -11
- package/dist/commands/diagnostics.d.ts.map +1 -1
- package/dist/commands/diagnostics.js +10 -0
- package/dist/commands/doctor.d.ts +12 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +22 -7
- package/dist/commands/governor.js +22 -10
- package/dist/commands/inbox.d.ts +1 -1
- package/dist/commands/inbox.d.ts.map +1 -1
- package/dist/commands/inbox.js +55 -2
- package/dist/commands/rm.d.ts.map +1 -1
- package/dist/commands/rm.js +28 -4
- package/dist/commands/servers.d.ts.map +1 -1
- package/dist/commands/servers.js +16 -1
- package/dist/commands/supervisor.d.ts.map +1 -1
- package/dist/commands/supervisor.js +7 -2
- package/dist/commands/toc.d.ts +14 -0
- package/dist/commands/toc.d.ts.map +1 -1
- package/dist/commands/toc.js +7 -4
- package/dist/commands/tunnel.d.ts +65 -0
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +290 -101
- package/dist/commands/web-fetch.d.ts +3 -2
- package/dist/commands/web-fetch.d.ts.map +1 -1
- package/dist/commands/web-fetch.js +25 -19
- package/dist/commands/web.d.ts +7 -1
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +9 -3
- package/dist/commands/workflow.js +24 -30
- package/dist/core/agents/live-authority-v3.d.ts +1 -0
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +11 -0
- package/dist/core/agents/live-lifecycle-v3.d.ts +4 -2
- package/dist/core/agents/live-lifecycle-v3.d.ts.map +1 -1
- package/dist/core/agents/live-lifecycle-v3.js +28 -7
- package/dist/core/agents/mailbox.d.ts +9 -8
- package/dist/core/agents/mailbox.d.ts.map +1 -1
- package/dist/core/agents/mailbox.js +24 -17
- package/dist/core/agents/render/prompt-context.d.ts +2 -0
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +19 -17
- package/dist/core/agents/render/session-context.d.ts +2 -8
- package/dist/core/agents/render/session-context.d.ts.map +1 -1
- package/dist/core/agents/render/session-context.js +64 -43
- package/dist/core/agents/rules/stop-hook.js +3 -3
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +25 -14
- package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-writer.js +5 -0
- package/dist/core/agents/state/names.d.ts +43 -3
- package/dist/core/agents/state/names.d.ts.map +1 -1
- package/dist/core/agents/state/names.js +87 -3
- package/dist/core/agents/state/pidmap.d.ts.map +1 -1
- package/dist/core/agents/state/pidmap.js +5 -0
- package/dist/core/agents/state/proc-start.d.ts +19 -0
- package/dist/core/agents/state/proc-start.d.ts.map +1 -1
- package/dist/core/agents/state/proc-start.js +41 -0
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +180 -70
- package/dist/core/agents/state/unchanged-file.d.ts +44 -0
- package/dist/core/agents/state/unchanged-file.d.ts.map +1 -0
- package/dist/core/agents/state/unchanged-file.js +390 -0
- package/dist/core/context/index.d.ts +22 -10
- package/dist/core/context/index.d.ts.map +1 -1
- package/dist/core/context/index.js +381 -119
- package/dist/core/context/observation.d.ts +26 -0
- package/dist/core/context/observation.d.ts.map +1 -0
- package/dist/core/context/observation.js +11 -0
- package/dist/core/diagnostics/bundle.d.ts.map +1 -1
- package/dist/core/diagnostics/bundle.js +25 -14
- package/dist/core/diagnostics/path-identity.d.ts +3 -0
- package/dist/core/diagnostics/path-identity.d.ts.map +1 -0
- package/dist/core/diagnostics/path-identity.js +12 -0
- package/dist/core/diagnostics/sanitize.d.ts.map +1 -1
- package/dist/core/diagnostics/sanitize.js +4 -3
- package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
- package/dist/core/events/v3/authority-outbox.js +29 -0
- package/dist/core/events/v3/generation-custody.d.ts +5 -0
- package/dist/core/events/v3/generation-custody.d.ts.map +1 -0
- package/dist/core/events/v3/generation-custody.js +50 -0
- package/dist/core/events/v3/producers/coordination-recorder.d.ts +1 -0
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +7 -0
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +77 -64
- package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -1
- package/dist/core/events/v3/support-storage/pack-reader.js +42 -16
- package/dist/core/governor/planning.d.ts.map +1 -1
- package/dist/core/governor/planning.js +14 -1
- package/dist/core/governor/service-read.d.ts +10 -2
- package/dist/core/governor/service-read.d.ts.map +1 -1
- package/dist/core/governor/service-read.js +105 -22
- package/dist/core/governor/service.d.ts +20 -2
- package/dist/core/governor/service.d.ts.map +1 -1
- package/dist/core/governor/service.js +72 -47
- package/dist/core/hooks/cli.js +120 -23
- package/dist/core/hooks/fork-lineage.d.ts +40 -0
- package/dist/core/hooks/fork-lineage.d.ts.map +1 -0
- package/dist/core/hooks/fork-lineage.js +62 -0
- package/dist/core/hooks/resolve/transcript.d.ts +16 -0
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +84 -0
- package/dist/core/hooks/shell-rm.d.ts +2 -0
- package/dist/core/hooks/shell-rm.d.ts.map +1 -0
- package/dist/core/hooks/shell-rm.js +105 -0
- package/dist/core/hooks/shell-tokens.d.ts +12 -0
- package/dist/core/hooks/shell-tokens.d.ts.map +1 -0
- package/dist/core/hooks/shell-tokens.js +97 -0
- package/dist/core/hooks/shell-waiter.d.ts.map +1 -1
- package/dist/core/hooks/shell-waiter.js +3 -93
- package/dist/core/inbox/contract.d.ts +2 -1
- package/dist/core/inbox/contract.d.ts.map +1 -1
- package/dist/core/inbox/index.d.ts +2 -0
- package/dist/core/inbox/index.d.ts.map +1 -1
- package/dist/core/inbox/index.js +2 -0
- package/dist/core/inbox/peer-messages.d.ts +37 -0
- package/dist/core/inbox/peer-messages.d.ts.map +1 -0
- package/dist/core/inbox/peer-messages.js +72 -0
- package/dist/core/inbox/service.d.ts +8 -1
- package/dist/core/inbox/service.d.ts.map +1 -1
- package/dist/core/inbox/service.js +67 -21
- package/dist/core/inbox/targets.d.ts +22 -0
- package/dist/core/inbox/targets.d.ts.map +1 -0
- package/dist/core/inbox/targets.js +108 -0
- package/dist/core/inbox/watcher.js +7 -3
- package/dist/core/journal/index.d.ts.map +1 -1
- package/dist/core/journal/index.js +17 -2
- package/dist/core/resources/contract.d.ts +3 -0
- package/dist/core/resources/contract.d.ts.map +1 -1
- package/dist/core/resources/service-status.d.ts +14 -1
- package/dist/core/resources/service-status.d.ts.map +1 -1
- package/dist/core/resources/service-status.js +23 -13
- package/dist/core/resources/service.d.ts +9 -1
- package/dist/core/resources/service.d.ts.map +1 -1
- package/dist/core/resources/service.js +47 -27
- package/dist/core/resources/status.d.ts +2 -5
- package/dist/core/resources/status.d.ts.map +1 -1
- package/dist/core/resources/status.js +36 -7
- package/dist/core/semantic/contract.d.ts +5 -5
- package/dist/core/servers/index.d.ts +24 -13
- package/dist/core/servers/index.d.ts.map +1 -1
- package/dist/core/servers/index.js +132 -92
- package/dist/core/servers/tunnels.d.ts +3 -5
- package/dist/core/servers/tunnels.d.ts.map +1 -1
- package/dist/core/servers/tunnels.js +3 -9
- package/dist/core/storage/process-log.d.ts +12 -0
- package/dist/core/storage/process-log.d.ts.map +1 -1
- package/dist/core/storage/process-log.js +10 -2
- package/dist/core/supervisor/contract.d.ts +12 -0
- package/dist/core/supervisor/contract.d.ts.map +1 -1
- package/dist/core/supervisor/explanations.d.ts.map +1 -1
- package/dist/core/supervisor/explanations.js +2 -1
- package/dist/core/supervisor/findings.d.ts.map +1 -1
- package/dist/core/supervisor/findings.js +54 -9
- package/dist/core/supervisor/service.d.ts +9 -1
- package/dist/core/supervisor/service.d.ts.map +1 -1
- package/dist/core/supervisor/service.js +59 -29
- package/dist/core/supervisor/services.d.ts.map +1 -1
- package/dist/core/supervisor/services.js +22 -1
- package/dist/core/supervisor/status.d.ts +17 -2
- package/dist/core/supervisor/status.d.ts.map +1 -1
- package/dist/core/supervisor/status.js +70 -12
- package/dist/core/supervisor/timeline.d.ts.map +1 -1
- package/dist/core/supervisor/timeline.js +2 -1
- package/dist/core/work/state.js +7 -7
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +105 -32
- package/dist/core/workflow/failure-evidence.d.ts +16 -0
- package/dist/core/workflow/failure-evidence.d.ts.map +1 -0
- package/dist/core/workflow/failure-evidence.js +114 -0
- package/dist/core/workflow/index.d.ts +1 -1
- package/dist/core/workflow/index.d.ts.map +1 -1
- package/dist/core/workflow/index.js +1 -1
- package/dist/core/workflow/live-session-v3.d.ts +6 -0
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
- package/dist/core/workflow/live-session-v3.js +126 -5
- package/dist/core/workflow/proof.d.ts +5 -5
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +115 -20
- package/dist/core/workflow/run-state.d.ts +3 -1
- package/dist/core/workflow/run-state.d.ts.map +1 -1
- package/dist/core/workflow/run-state.js +31 -27
- package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
- package/dist/core/workflow/spawn-claude.js +19 -0
- package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
- package/dist/core/workflow/spawn-codex.js +13 -0
- package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
- package/dist/core/workflow/spawn-cursor.js +19 -0
- package/dist/core/workflow/spawn-opencode.d.ts.map +1 -1
- package/dist/core/workflow/spawn-opencode.js +14 -0
- package/dist/core/workflow/types.d.ts +64 -17
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/index.d.ts +0 -1
- package/dist/core/workflow/workspaces/index.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/index.js +0 -1
- package/dist/core/workflow/workspaces/leases.d.ts +3 -1
- package/dist/core/workflow/workspaces/leases.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/leases.js +30 -16
- package/dist/core/workflow/workspaces/local-git.d.ts +6 -2
- package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/local-git.js +270 -6
- package/dist/core/workflow/workspaces/ownership.d.ts +11 -0
- package/dist/core/workflow/workspaces/ownership.d.ts.map +1 -0
- package/dist/core/workflow/workspaces/ownership.js +194 -0
- package/dist/core/workflow/workspaces/reclaim.d.ts +35 -0
- package/dist/core/workflow/workspaces/reclaim.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/reclaim.js +14 -0
- package/dist/core/workflow/workspaces/recovery.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/recovery.js +21 -13
- package/dist/core/workflow/workspaces/state.d.ts +1 -0
- package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/state.js +21 -1
- package/dist/lib/browser/windows-chrome.d.ts +100 -12
- package/dist/lib/browser/windows-chrome.d.ts.map +1 -1
- package/dist/lib/browser/windows-chrome.js +262 -73
- package/dist/lib/docs-links.d.ts.map +1 -1
- package/dist/lib/docs-links.js +45 -2
- package/dist/lib/guarded-remove.d.ts +7 -0
- package/dist/lib/guarded-remove.d.ts.map +1 -1
- package/dist/lib/guarded-remove.js +106 -12
- package/dist/lib/identities/assume.d.ts.map +1 -1
- package/dist/lib/identities/assume.js +4 -0
- package/dist/lib/tunnel/allowlist.d.ts +44 -0
- package/dist/lib/tunnel/allowlist.d.ts.map +1 -0
- package/dist/lib/tunnel/allowlist.js +204 -0
- package/dist/lib/tunnel/current-address.d.ts +41 -0
- package/dist/lib/tunnel/current-address.d.ts.map +1 -0
- package/dist/lib/tunnel/current-address.js +123 -0
- package/dist/lib/tunnel/gate.js +13 -6
- package/dist/lib/tunnel/processes.d.ts +39 -0
- package/dist/lib/tunnel/processes.d.ts.map +1 -0
- package/dist/lib/tunnel/processes.js +121 -0
- package/dist/lib/tunnel/state.d.ts +28 -3
- package/dist/lib/tunnel/state.d.ts.map +1 -1
- package/dist/lib/tunnel/state.js +98 -27
- package/dist/lib/zip/index.d.ts +41 -0
- package/dist/lib/zip/index.d.ts.map +1 -0
- package/dist/lib/zip/index.js +398 -0
- package/package.json +8 -1
- package/src/commander.ts +32 -0
- package/src/commands/agents.ts +151 -74
- package/src/commands/browse.ts +50 -14
- package/src/commands/diagnostics.ts +10 -0
- package/src/commands/doctor.ts +26 -7
- package/src/commands/governor.ts +23 -10
- package/src/commands/inbox.ts +52 -2
- package/src/commands/rm.ts +43 -4
- package/src/commands/servers.ts +16 -4
- package/src/commands/supervisor.ts +7 -2
- package/src/commands/toc.ts +14 -6
- package/src/commands/tunnel.ts +394 -116
- package/src/commands/web-fetch.ts +30 -19
- package/src/commands/web.ts +9 -3
- package/src/commands/workflow.ts +30 -30
- package/src/core/agents/live-authority-v3.ts +17 -0
- package/src/core/agents/live-lifecycle-v3.ts +52 -14
- package/src/core/agents/mailbox.ts +26 -17
- package/src/core/agents/render/prompt-context.ts +35 -20
- package/src/core/agents/render/session-context.ts +92 -48
- package/src/core/agents/rules/stop-hook.ts +3 -3
- package/src/core/agents/state/heartbeat-writer.ts +29 -12
- package/src/core/agents/state/live-coordination-writer.ts +29 -0
- package/src/core/agents/state/names.ts +117 -6
- package/src/core/agents/state/pidmap.ts +13 -0
- package/src/core/agents/state/proc-start.ts +57 -0
- package/src/core/agents/state/stale-sweep.ts +247 -82
- package/src/core/agents/state/unchanged-file.ts +456 -0
- package/src/core/context/index.ts +446 -136
- package/src/core/context/observation.ts +29 -0
- package/src/core/diagnostics/bundle.ts +23 -18
- package/src/core/diagnostics/path-identity.ts +15 -0
- package/src/core/diagnostics/sanitize.ts +4 -3
- package/src/core/events/v3/authority-outbox.ts +56 -0
- package/src/core/events/v3/generation-custody.ts +59 -0
- package/src/core/events/v3/producers/coordination-recorder.ts +15 -0
- package/src/core/events/v3/producers/recorder.ts +94 -68
- package/src/core/events/v3/support-storage/pack-reader.ts +45 -19
- package/src/core/governor/planning.ts +20 -8
- package/src/core/governor/service-read.ts +128 -20
- package/src/core/governor/service.ts +119 -42
- package/src/core/hooks/cli.ts +139 -22
- package/src/core/hooks/fork-lineage.ts +82 -0
- package/src/core/hooks/resolve/transcript.ts +88 -0
- package/src/core/hooks/shell-rm.ts +103 -0
- package/src/core/hooks/shell-tokens.ts +96 -0
- package/src/core/hooks/shell-waiter.ts +4 -91
- package/src/core/inbox/contract.ts +2 -1
- package/src/core/inbox/index.ts +2 -0
- package/src/core/inbox/peer-messages.ts +94 -0
- package/src/core/inbox/service.ts +88 -22
- package/src/core/inbox/targets.ts +148 -0
- package/src/core/inbox/watcher.ts +8 -9
- package/src/core/journal/index.ts +19 -2
- package/src/core/resources/contract.ts +4 -0
- package/src/core/resources/service-status.ts +35 -12
- package/src/core/resources/service.ts +71 -24
- package/src/core/resources/status.ts +57 -8
- package/src/core/servers/index.ts +177 -91
- package/src/core/servers/tunnels.ts +3 -11
- package/src/core/storage/process-log.ts +17 -2
- package/src/core/supervisor/contract.ts +13 -0
- package/src/core/supervisor/explanations.ts +4 -1
- package/src/core/supervisor/findings.ts +68 -10
- package/src/core/supervisor/service.ts +88 -26
- package/src/core/supervisor/services.ts +26 -8
- package/src/core/supervisor/status.ts +89 -12
- package/src/core/supervisor/timeline.ts +2 -1
- package/src/core/work/state.ts +7 -7
- package/src/core/workflow/engine.ts +131 -49
- package/src/core/workflow/failure-evidence.ts +141 -0
- package/src/core/workflow/index.ts +0 -1
- package/src/core/workflow/live-session-v3.ts +146 -5
- package/src/core/workflow/proof.ts +134 -26
- package/src/core/workflow/run-state.ts +31 -29
- package/src/core/workflow/spawn-claude.ts +18 -0
- package/src/core/workflow/spawn-codex.ts +13 -0
- package/src/core/workflow/spawn-cursor.ts +18 -0
- package/src/core/workflow/spawn-opencode.ts +14 -0
- package/src/core/workflow/types.ts +51 -17
- package/src/core/workflow/workspaces/index.ts +0 -1
- package/src/core/workflow/workspaces/leases.ts +48 -17
- package/src/core/workflow/workspaces/local-git.ts +315 -5
- package/src/core/workflow/workspaces/ownership.ts +232 -0
- package/src/core/workflow/workspaces/reclaim.ts +58 -0
- package/src/core/workflow/workspaces/recovery.ts +25 -13
- package/src/core/workflow/workspaces/state.ts +20 -0
- package/src/lib/browser/windows-chrome.ts +346 -86
- package/src/lib/docs-links.ts +49 -2
- package/src/lib/guarded-remove.ts +132 -14
- package/src/lib/identities/assume.ts +4 -0
- package/src/lib/tunnel/allowlist.ts +208 -0
- package/src/lib/tunnel/current-address.ts +158 -0
- package/src/lib/tunnel/gate.ts +16 -8
- package/src/lib/tunnel/processes.ts +149 -0
- package/src/lib/tunnel/state.ts +123 -27
- package/src/lib/zip/index.ts +483 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { resolveName } from "../agents/state/names.js";
|
|
2
|
+
import { coordFreshnessSeconds } from "../config.js";
|
|
3
|
+
import { readCoordinationViewV3, requireAuthoritySafeCoordinationViewV3, } from "../events/v3/coordination-view.js";
|
|
4
|
+
import { liveInstanceIdV3, nativeInstanceIdV3, observeLiveEventLedgerRouteV3, } from "../events/v3/live-route-observer.js";
|
|
5
|
+
/** Resolve one immutable recipient without extending presence or claiming attention. */
|
|
6
|
+
export function resolveMessageTarget(coordRoot, input) {
|
|
7
|
+
const requestedName = normalizeName(input.name);
|
|
8
|
+
const requestedInstance = input.instanceId?.trim();
|
|
9
|
+
if (!requestedName && !requestedInstance) {
|
|
10
|
+
return { ok: false, code: "no_peer", message: "Supply an exact agent name or instance id." };
|
|
11
|
+
}
|
|
12
|
+
const now = input.now?.getTime() ?? Date.now();
|
|
13
|
+
if (!Number.isFinite(now))
|
|
14
|
+
return unsafe("The message addressing clock is invalid.");
|
|
15
|
+
let view;
|
|
16
|
+
try {
|
|
17
|
+
if (observeLiveEventLedgerRouteV3(coordRoot).state === "blocked") {
|
|
18
|
+
return unsafe("The event ledger cannot establish message recipient authority.");
|
|
19
|
+
}
|
|
20
|
+
view = requireAuthoritySafeCoordinationViewV3(readCoordinationViewV3(coordRoot));
|
|
21
|
+
if (!view.source_complete)
|
|
22
|
+
return unsafe("The event ledger read is incomplete.");
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return unsafe("The event ledger cannot establish message recipient authority.");
|
|
26
|
+
}
|
|
27
|
+
// Address historical instances without reopening them. A current generation
|
|
28
|
+
// wins over its own terminal history; otherwise use its last ledger position.
|
|
29
|
+
const byInstance = new Map();
|
|
30
|
+
for (const generation of Object.values(view.terminal_generations)) {
|
|
31
|
+
const prior = byInstance.get(generation.instance_id);
|
|
32
|
+
if (!prior || laterPosition(generation, prior))
|
|
33
|
+
byInstance.set(generation.instance_id, generation);
|
|
34
|
+
}
|
|
35
|
+
for (const generation of Object.values(view.instances))
|
|
36
|
+
byInstance.set(generation.instance_id, generation);
|
|
37
|
+
const freshnessMs = coordFreshnessSeconds(coordRoot) * 1_000;
|
|
38
|
+
const candidates = [...byInstance.values()].flatMap((generation) => {
|
|
39
|
+
const instanceId = nativeInstanceIdV3(generation.instance_id);
|
|
40
|
+
const name = resolveName(coordRoot, instanceId)?.name;
|
|
41
|
+
if (!name)
|
|
42
|
+
return [];
|
|
43
|
+
if (requestedInstance && liveInstanceIdV3(requestedInstance) !== generation.instance_id)
|
|
44
|
+
return [];
|
|
45
|
+
if (requestedName && normalizeName(name) !== requestedName)
|
|
46
|
+
return [];
|
|
47
|
+
const age = now - Date.parse(generation.last_observed_at);
|
|
48
|
+
const diagnostics = view.diagnostics_by_generation[generation.generation_id] ?? [];
|
|
49
|
+
return [
|
|
50
|
+
{
|
|
51
|
+
instanceId,
|
|
52
|
+
name,
|
|
53
|
+
safe: !diagnostics.some((diagnostic) => diagnostic.authority_blocking),
|
|
54
|
+
fresh: generation.phase === "live" && Number.isFinite(age) && age >= 0 && age <= freshnessMs,
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
});
|
|
58
|
+
if (candidates.length === 0) {
|
|
59
|
+
return {
|
|
60
|
+
ok: false,
|
|
61
|
+
code: "no_peer",
|
|
62
|
+
message: "No known agent matches that exact name and instance.",
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (candidates.some((candidate) => !candidate.safe)) {
|
|
66
|
+
return unsafe("A matching agent generation does not have safe coordination authority.");
|
|
67
|
+
}
|
|
68
|
+
const fresh = candidates.filter((candidate) => candidate.fresh);
|
|
69
|
+
const selected = requestedInstance ? candidates : fresh.length > 0 ? fresh : candidates;
|
|
70
|
+
if (selected.length !== 1) {
|
|
71
|
+
return {
|
|
72
|
+
ok: false,
|
|
73
|
+
code: "ambiguous_peer",
|
|
74
|
+
message: "Several agent instances hold that exact name; specify --instance-id.",
|
|
75
|
+
candidates: selected.map(({ instanceId }) => instanceId).sort(),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const target = selected[0];
|
|
79
|
+
if (input.requireLive && !target.fresh) {
|
|
80
|
+
return {
|
|
81
|
+
ok: false,
|
|
82
|
+
code: "not_live",
|
|
83
|
+
message: "That agent is known but outside live presence; omit --require-live to queue its message.",
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
ok: true,
|
|
88
|
+
target: {
|
|
89
|
+
instance_id: target.instanceId,
|
|
90
|
+
name: target.name,
|
|
91
|
+
delivery: target.fresh ? "written-live" : "queued",
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function laterPosition(left, right) {
|
|
96
|
+
return (left.source_position.segment_ordinal > right.source_position.segment_ordinal ||
|
|
97
|
+
(left.source_position.segment_ordinal === right.source_position.segment_ordinal &&
|
|
98
|
+
left.source_position.byte_offset > right.source_position.byte_offset));
|
|
99
|
+
}
|
|
100
|
+
function normalizeName(name) {
|
|
101
|
+
return (name ?? "")
|
|
102
|
+
.trim()
|
|
103
|
+
.replace(/^agent-/i, "")
|
|
104
|
+
.toLowerCase();
|
|
105
|
+
}
|
|
106
|
+
function unsafe(message) {
|
|
107
|
+
return { ok: false, code: "authority_unsafe", message };
|
|
108
|
+
}
|
|
@@ -17,10 +17,14 @@ export async function* watchInbox(service, recipientInstanceId, options) {
|
|
|
17
17
|
}
|
|
18
18
|
function delay(ms, signal) {
|
|
19
19
|
return new Promise((resolve) => {
|
|
20
|
-
const
|
|
21
|
-
signal.addEventListener("abort", () => {
|
|
20
|
+
const finish = () => {
|
|
22
21
|
clearTimeout(timer);
|
|
22
|
+
signal.removeEventListener("abort", finish);
|
|
23
23
|
resolve();
|
|
24
|
-
}
|
|
24
|
+
};
|
|
25
|
+
const timer = setTimeout(finish, ms);
|
|
26
|
+
signal.addEventListener("abort", finish, { once: true });
|
|
27
|
+
if (signal.aborted)
|
|
28
|
+
finish();
|
|
25
29
|
});
|
|
26
30
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/journal/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/journal/index.ts"],"names":[],"mappings":"AA+BA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,kBAAkB,iFAQrB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAC3C,eAAO,MAAM,kBAAkB,QAAY,CAAC;AAC5C,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,6DAA6D;AAC7D,eAAO,MAAM,eAAe,QACyF,CAAC;AAEtH,gFAAgF;AAChF,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AAEzD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,eAAe,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;CACf;AAID,wBAAgB,UAAU,IAAI,MAAM,CAMnC;AAED,wBAAgB,UAAU,IAAI,MAAM,CAInC;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAGtD;AAeD,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,CAAC,GAAE,IAAiB,GAAG,MAAM,CAW1D;AAID,qEAAqE;AACrE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CAwEtE;AAED,+CAA+C;AAC/C,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAkBxD;AAmBD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,SAAoB,GAAG,SAAS,EAAE,CA2DrF;AAID,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,MAAM,GACX,UAAU,CAiEZ;AAID,wGAAwG;AACxG,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQhE;AAED,iEAAiE;AACjE,wBAAgB,aAAa,CAAC,IAAI,SAAyB,GAAG,MAAM,CAkBnE;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAuB9C;AAED,qDAAqD;AACrD,wBAAgB,YAAY,IAAI;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf,EAAE,CAWF;AAID,wBAAgB,mBAAmB,IAAI,MAAM,CAM5C;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAIjE;AAED,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ9D"}
|
|
@@ -3,6 +3,8 @@ import { dirname, resolve } from "node:path";
|
|
|
3
3
|
import { resolveMachineLabel } from "../../lib/machine.js";
|
|
4
4
|
import { assertSafeInstanceId, monorepoRoot, resolveContainedFile, resolveOwner, } from "../agents/index.js";
|
|
5
5
|
import { readLiveCoordinationRow, readLiveCoordinationRows, } from "../agents/state/live-coordination-view.js";
|
|
6
|
+
import { readCoordinationViewV3, requireAuthoritySafeCoordinationViewV3, } from "../events/v3/coordination-view.js";
|
|
7
|
+
import { liveInstanceIdV3, observeLiveEventLedgerRouteV3, } from "../events/v3/live-route-observer.js";
|
|
6
8
|
/**
|
|
7
9
|
* Agent journal: per-agent markdown journal at `.harnery/journal/<instance_id>.md`.
|
|
8
10
|
*
|
|
@@ -340,12 +342,25 @@ export function sweepOrphanJournals() {
|
|
|
340
342
|
const dir = journalDir();
|
|
341
343
|
const root = monorepoRoot();
|
|
342
344
|
const archived = [];
|
|
345
|
+
if (!root)
|
|
346
|
+
return archived;
|
|
347
|
+
let view;
|
|
348
|
+
try {
|
|
349
|
+
if (observeLiveEventLedgerRouteV3(root).state === "blocked")
|
|
350
|
+
return archived;
|
|
351
|
+
view = requireAuthoritySafeCoordinationViewV3(readCoordinationViewV3(root));
|
|
352
|
+
if (!view.source_complete)
|
|
353
|
+
return archived;
|
|
354
|
+
}
|
|
355
|
+
catch {
|
|
356
|
+
// A missing or unsafe read does not prove that an owner has ended.
|
|
357
|
+
return archived;
|
|
358
|
+
}
|
|
343
359
|
for (const f of readdirSync(dir)) {
|
|
344
360
|
if (!f.endsWith(".md"))
|
|
345
361
|
continue;
|
|
346
362
|
const instanceId = f.replace(/\.md$/, "");
|
|
347
|
-
|
|
348
|
-
if (!hb) {
|
|
363
|
+
if (!view.instances[liveInstanceIdV3(instanceId)]) {
|
|
349
364
|
const dest = archiveJournal(instanceId);
|
|
350
365
|
if (dest)
|
|
351
366
|
archived.push(dest);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ProcessGenerationVerdict } from "../agents/state/proc-start.js";
|
|
1
2
|
export declare const RESOURCE_SNAPSHOT_SCHEMA_VERSION = 2;
|
|
2
3
|
export declare const RESOURCE_SERVICE_STATUS_SCHEMA_VERSION = 1;
|
|
3
4
|
export type ResourceSupportState = "supported" | "partial" | "unsupported" | "error";
|
|
@@ -140,6 +141,8 @@ export interface ResourceServiceStatusRecord {
|
|
|
140
141
|
export interface ResourceServiceStatus {
|
|
141
142
|
running: boolean;
|
|
142
143
|
stale: boolean;
|
|
144
|
+
generation: ProcessGenerationVerdict;
|
|
145
|
+
liveness: "running" | "stopped" | "unknown";
|
|
143
146
|
record?: ResourceServiceStatusRecord;
|
|
144
147
|
status_path: string;
|
|
145
148
|
snapshot_path: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/core/resources/contract.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/core/resources/contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
import { type ProcessGenerationVerdict } from "../agents/state/proc-start.js";
|
|
1
2
|
import { type ResourceServiceStatus } from "./contract.js";
|
|
2
|
-
export
|
|
3
|
+
export interface ResourceProcessDependencies {
|
|
4
|
+
readToken?: (pid: number) => string | null;
|
|
5
|
+
probePid?: (pid: number) => unknown;
|
|
6
|
+
}
|
|
7
|
+
export declare function readResourceServiceStatus(coordRoot: string, nowMs?: number, dependencies?: ResourceProcessDependencies): ResourceServiceStatus;
|
|
8
|
+
export declare function resourceProcessLiveness(owner: {
|
|
9
|
+
pid: number;
|
|
10
|
+
host: string;
|
|
11
|
+
start_token?: string;
|
|
12
|
+
}, dependencies?: ResourceProcessDependencies): {
|
|
13
|
+
generation: ProcessGenerationVerdict;
|
|
14
|
+
liveness: ResourceServiceStatus["liveness"];
|
|
15
|
+
};
|
|
3
16
|
//# sourceMappingURL=service-status.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-status.d.ts","sourceRoot":"","sources":["../../../src/core/resources/service-status.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,eAAe,CAAC;AAKvB,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,KAAK,SAAa,
|
|
1
|
+
{"version":3,"file":"service-status.d.ts","sourceRoot":"","sources":["../../../src/core/resources/service-status.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAE9B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,eAAe,CAAC;AAKvB,MAAM,WAAW,2BAA2B;IAC1C,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC3C,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;CACrC;AAED,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,KAAK,SAAa,EAClB,YAAY,GAAE,2BAAgC,GAC7C,qBAAqB,CA2BvB;AAcD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EAC1D,YAAY,GAAE,2BAAgC,GAC7C;IAAE,UAAU,EAAE,wBAAwB,CAAC;IAAC,QAAQ,EAAE,qBAAqB,CAAC,UAAU,CAAC,CAAA;CAAE,CAgBvF"}
|
|
@@ -1,29 +1,31 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
1
2
|
import { hostname } from "node:os";
|
|
2
|
-
import {
|
|
3
|
+
import { verifyProcessGeneration, } from "../agents/state/proc-start.js";
|
|
3
4
|
import { RESOURCE_SERVICE_STATUS_SCHEMA_VERSION, } from "./contract.js";
|
|
4
5
|
import { readResourceServiceRecord, resourcePaths } from "./storage.js";
|
|
5
6
|
const STALE_HEARTBEAT_MS = 15_000;
|
|
6
|
-
export function readResourceServiceStatus(coordRoot, nowMs = Date.now()) {
|
|
7
|
+
export function readResourceServiceStatus(coordRoot, nowMs = Date.now(), dependencies = {}) {
|
|
7
8
|
const paths = resourcePaths(coordRoot);
|
|
8
9
|
const record = readResourceServiceRecord(coordRoot);
|
|
9
10
|
if (!validRecord(record)) {
|
|
10
11
|
return {
|
|
11
12
|
running: false,
|
|
12
13
|
stale: false,
|
|
14
|
+
generation: "unknown",
|
|
15
|
+
liveness: existsSync(paths.service) ? "unknown" : "stopped",
|
|
13
16
|
status_path: paths.service,
|
|
14
17
|
snapshot_path: paths.snapshot,
|
|
15
18
|
};
|
|
16
19
|
}
|
|
17
20
|
const heartbeatAt = Date.parse(record.heartbeat_at);
|
|
18
21
|
const stale = !Number.isFinite(heartbeatAt) || nowMs - heartbeatAt > STALE_HEARTBEAT_MS;
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
!stale &&
|
|
22
|
-
(record.state === "starting" || record.state === "running" || record.state === "stopping") &&
|
|
23
|
-
pidStillMatches(record.pid, record.start_token);
|
|
22
|
+
const owner = resourceProcessLiveness(record, dependencies);
|
|
23
|
+
const liveness = owner.generation === "same" && record.state === "stopped" ? "stopped" : owner.liveness;
|
|
24
24
|
return {
|
|
25
|
-
running,
|
|
25
|
+
running: liveness === "running" && !stale,
|
|
26
26
|
stale,
|
|
27
|
+
generation: owner.generation,
|
|
28
|
+
liveness,
|
|
27
29
|
record,
|
|
28
30
|
status_path: paths.service,
|
|
29
31
|
snapshot_path: paths.snapshot,
|
|
@@ -36,13 +38,21 @@ function validRecord(value) {
|
|
|
36
38
|
typeof value.host === "string" &&
|
|
37
39
|
typeof value.heartbeat_at === "string");
|
|
38
40
|
}
|
|
39
|
-
function
|
|
41
|
+
export function resourceProcessLiveness(owner, dependencies = {}) {
|
|
42
|
+
if (owner.host !== hostname())
|
|
43
|
+
return { generation: "unknown", liveness: "unknown" };
|
|
40
44
|
try {
|
|
41
|
-
process.kill(pid, 0);
|
|
45
|
+
(dependencies.probePid ?? ((pid) => process.kill(pid, 0)))(owner.pid);
|
|
42
46
|
}
|
|
43
47
|
catch (error) {
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
return {
|
|
49
|
+
generation: "unknown",
|
|
50
|
+
liveness: error.code === "ESRCH" ? "stopped" : "unknown",
|
|
51
|
+
};
|
|
46
52
|
}
|
|
47
|
-
|
|
53
|
+
const generation = verifyProcessGeneration(owner.pid, owner.start_token, dependencies.readToken);
|
|
54
|
+
return {
|
|
55
|
+
generation,
|
|
56
|
+
liveness: generation === "same" ? "running" : generation === "different" ? "stopped" : "unknown",
|
|
57
|
+
};
|
|
48
58
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { type ProcessGenerationVerdict } from "../agents/state/proc-start.js";
|
|
1
2
|
import { type ResourceServiceStatus, type ResourceServiceStatusRecord } from "./contract.js";
|
|
2
3
|
import { sampleResources } from "./sampler.js";
|
|
4
|
+
import { type ResourceProcessDependencies } from "./service-status.js";
|
|
3
5
|
export declare const RESOURCE_SERVICE_DEFAULT_INTERVAL_MS = 2000;
|
|
4
6
|
export interface RunResourceServiceInput {
|
|
5
7
|
coordRoot: string;
|
|
@@ -21,6 +23,12 @@ export declare function spawnResourceService(coordRootRaw: string, options?: {
|
|
|
21
23
|
intervalMs?: number;
|
|
22
24
|
}): Promise<ResourceServiceStatus>;
|
|
23
25
|
export declare function ensureResourceServiceRunning(coordRoot: string): Promise<EnsureResourceServiceResult>;
|
|
24
|
-
export
|
|
26
|
+
export interface ResourceServiceStopResult extends ResourceServiceStatus {
|
|
27
|
+
signal_sent: boolean;
|
|
28
|
+
signal_verdict: ProcessGenerationVerdict;
|
|
29
|
+
}
|
|
30
|
+
export declare function requestResourceServiceStop(coordRootRaw: string, dependencies?: ResourceProcessDependencies & {
|
|
31
|
+
kill?: (pid: number, signal: NodeJS.Signals | number) => unknown;
|
|
32
|
+
}): ResourceServiceStopResult;
|
|
25
33
|
export declare function runResourceService(input: RunResourceServiceInput): Promise<ResourceServiceStatusRecord>;
|
|
26
34
|
//# sourceMappingURL=service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/core/resources/service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/core/resources/service.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,KAAK,wBAAwB,EAG9B,MAAM,+BAA+B,CAAC;AAIvC,OAAO,EAGL,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EACjC,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EACL,KAAK,2BAA2B,EAGjC,MAAM,qBAAqB,CAAC;AAG7B,eAAO,MAAM,oCAAoC,OAAQ,CAAC;AAY1D,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,eAAe,CAAC;IAChC,IAAI,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED,MAAM,MAAM,2BAA2B,GACnC;IAAE,KAAK,EAAE,SAAS,GAAG,SAAS,CAAC;IAAC,MAAM,EAAE,qBAAqB,CAAA;CAAE,GAC/D;IAAE,KAAK,EAAE,aAAa,GAAG,aAAa,CAAC;IAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3F,wBAAsB,oBAAoB,CACxC,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACpC,OAAO,CAAC,qBAAqB,CAAC,CAyChC;AAED,wBAAsB,4BAA4B,CAChD,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,2BAA2B,CAAC,CAoBtC;AAED,MAAM,WAAW,yBAA0B,SAAQ,qBAAqB;IACtE,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,wBAAwB,CAAC;CAC1C;AAED,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,MAAM,EACpB,YAAY,GAAE,2BAA2B,GAAG;IAC1C,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,MAAM,KAAK,OAAO,CAAC;CAC7D,GACL,yBAAyB,CAuB3B;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,2BAA2B,CAAC,CA4FtC"}
|
|
@@ -3,12 +3,13 @@ import { randomUUID } from "node:crypto";
|
|
|
3
3
|
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
4
4
|
import { hostname, platform } from "node:os";
|
|
5
5
|
import { resolve } from "node:path";
|
|
6
|
-
import {
|
|
6
|
+
import { processStartToken, signalIfSameGeneration, } from "../agents/state/proc-start.js";
|
|
7
|
+
import { resolveBinName } from "../config.js";
|
|
7
8
|
import { closeProcessLoggers, legacyLogFields, processLogger } from "../storage/logger.js";
|
|
8
9
|
import { stateDirMode, stateFileMode } from "../storage/modes.js";
|
|
9
10
|
import { RESOURCE_SERVICE_STATUS_SCHEMA_VERSION, } from "./contract.js";
|
|
10
11
|
import { sampleResources } from "./sampler.js";
|
|
11
|
-
import { readResourceServiceStatus } from "./service-status.js";
|
|
12
|
+
import { readResourceServiceStatus, resourceProcessLiveness, } from "./service-status.js";
|
|
12
13
|
import { resourcePaths, writePrivateJsonAtomic } from "./storage.js";
|
|
13
14
|
export const RESOURCE_SERVICE_DEFAULT_INTERVAL_MS = 2_000;
|
|
14
15
|
const RESOURCE_SERVICE_MIN_INTERVAL_MS = 500;
|
|
@@ -16,13 +17,15 @@ const RESOURCE_SERVICE_MAX_INTERVAL_MS = 60_000;
|
|
|
16
17
|
export async function spawnResourceService(coordRootRaw, options = {}) {
|
|
17
18
|
const coordRoot = resolve(coordRootRaw);
|
|
18
19
|
const current = readResourceServiceStatus(coordRoot);
|
|
19
|
-
if (current.
|
|
20
|
+
if (current.liveness === "unknown")
|
|
21
|
+
throw unknownResourceOwnerError();
|
|
22
|
+
if (current.liveness === "running") {
|
|
20
23
|
throw new Error(`resource observer is already running under pid ${current.record?.pid}`);
|
|
21
24
|
}
|
|
22
25
|
const intervalMs = normalizeInterval(options.intervalMs);
|
|
23
26
|
const paths = resourcePaths(coordRoot);
|
|
27
|
+
assertResourceLeaseAvailable(paths.lease);
|
|
24
28
|
mkdirSync(paths.root, { recursive: true, mode: stateDirMode() });
|
|
25
|
-
rmSync(paths.stop, { force: true });
|
|
26
29
|
const harnBin = new URL("../../../bin/harn", import.meta.url).pathname;
|
|
27
30
|
if (!existsSync(harnBin))
|
|
28
31
|
throw new Error(`cannot find harn executable at ${harnBin}`);
|
|
@@ -77,27 +80,31 @@ export async function ensureResourceServiceRunning(coordRoot) {
|
|
|
77
80
|
};
|
|
78
81
|
}
|
|
79
82
|
}
|
|
80
|
-
export function requestResourceServiceStop(coordRootRaw) {
|
|
83
|
+
export function requestResourceServiceStop(coordRootRaw, dependencies = {}) {
|
|
81
84
|
const coordRoot = resolve(coordRootRaw);
|
|
82
85
|
const paths = resourcePaths(coordRoot);
|
|
83
|
-
const status = readResourceServiceStatus(coordRoot);
|
|
86
|
+
const status = readResourceServiceStatus(coordRoot, Date.now(), dependencies);
|
|
84
87
|
mkdirSync(paths.root, { recursive: true, mode: stateDirMode() });
|
|
85
88
|
writePrivateJsonAtomic(paths.stop, {
|
|
86
89
|
requested_at: new Date().toISOString(),
|
|
87
90
|
requested_by_pid: process.pid,
|
|
88
91
|
});
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
return readResourceServiceStatus(coordRoot);
|
|
92
|
+
const signal = status.liveness === "running" && status.record?.host === hostname()
|
|
93
|
+
? signalIfSameGeneration(status.record.pid, status.record.start_token, "SIGTERM", dependencies)
|
|
94
|
+
: { sent: false, verdict: status.generation };
|
|
95
|
+
return {
|
|
96
|
+
...readResourceServiceStatus(coordRoot, Date.now(), dependencies),
|
|
97
|
+
signal_sent: signal.sent,
|
|
98
|
+
signal_verdict: signal.verdict,
|
|
99
|
+
};
|
|
98
100
|
}
|
|
99
101
|
export async function runResourceService(input) {
|
|
100
102
|
const coordRoot = resolve(input.coordRoot);
|
|
103
|
+
const current = readResourceServiceStatus(coordRoot);
|
|
104
|
+
if (current.liveness === "unknown")
|
|
105
|
+
throw unknownResourceOwnerError();
|
|
106
|
+
if (current.liveness === "running")
|
|
107
|
+
throw new Error(`resource observer is already running under pid ${current.record?.pid}`);
|
|
101
108
|
const paths = resourcePaths(coordRoot);
|
|
102
109
|
const intervalMs = normalizeInterval(input.intervalMs);
|
|
103
110
|
const now = input.now ?? (() => new Date());
|
|
@@ -212,7 +219,10 @@ function acquireLease(coordRoot, now) {
|
|
|
212
219
|
if (error.code !== "EEXIST")
|
|
213
220
|
throw error;
|
|
214
221
|
const existing = readLease(paths.lease);
|
|
215
|
-
|
|
222
|
+
const liveness = existing ? leaseIsLive(existing) : "unknown";
|
|
223
|
+
if (liveness === "unknown")
|
|
224
|
+
throw unknownResourceOwnerError();
|
|
225
|
+
if (existing && liveness === "running") {
|
|
216
226
|
throw new Error(`resource observer lease is held by pid ${existing.pid}`);
|
|
217
227
|
}
|
|
218
228
|
try {
|
|
@@ -239,7 +249,13 @@ function releaseLease(path, nonce) {
|
|
|
239
249
|
function readLease(path) {
|
|
240
250
|
try {
|
|
241
251
|
const value = JSON.parse(readFileSync(path, "utf8"));
|
|
242
|
-
return value &&
|
|
252
|
+
return value &&
|
|
253
|
+
Number.isSafeInteger(value.pid) &&
|
|
254
|
+
value.pid > 0 &&
|
|
255
|
+
typeof value.host === "string" &&
|
|
256
|
+
value.host.length > 0 &&
|
|
257
|
+
typeof value.nonce === "string" &&
|
|
258
|
+
value.nonce.length > 0
|
|
243
259
|
? value
|
|
244
260
|
: undefined;
|
|
245
261
|
}
|
|
@@ -248,16 +264,20 @@ function readLease(path) {
|
|
|
248
264
|
}
|
|
249
265
|
}
|
|
250
266
|
function leaseIsLive(lease) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
267
|
+
return resourceProcessLiveness(lease).liveness;
|
|
268
|
+
}
|
|
269
|
+
function assertResourceLeaseAvailable(path) {
|
|
270
|
+
if (!existsSync(path))
|
|
271
|
+
return;
|
|
272
|
+
const lease = readLease(path);
|
|
273
|
+
const liveness = lease ? leaseIsLive(lease) : "unknown";
|
|
274
|
+
if (liveness === "unknown")
|
|
275
|
+
throw unknownResourceOwnerError();
|
|
276
|
+
if (liveness === "running")
|
|
277
|
+
throw new Error(`resource observer lease is held by pid ${lease?.pid}`);
|
|
278
|
+
}
|
|
279
|
+
function unknownResourceOwnerError() {
|
|
280
|
+
return new Error(`resource observer process identity is unknown; run ${resolveBinName()} supervisor stop to write the durable stop request before starting again`);
|
|
261
281
|
}
|
|
262
282
|
function log(coordRoot, event, fields, error) {
|
|
263
283
|
try {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type PressureAssessment, type PressureHysteresisState } from "../diagnostics/contract.js";
|
|
2
|
-
import { type SupervisorCapability, type SupervisorPressureRecord } from "../supervisor/contract.js";
|
|
2
|
+
import { type SupervisorCapability, type SupervisorPressureRecord, type SupervisorStatus } from "../supervisor/contract.js";
|
|
3
3
|
import { type ResourceDiskSample, type ResourceHostSample, type ResourceIoSample, type ResourceMachineSample, type ResourceOomSample, type ResourcePressureSample, type ResourceProcessSample, type ResourceSnapshot } from "./contract.js";
|
|
4
4
|
export declare const RESOURCE_STATUS_STALE_MS = 15000;
|
|
5
5
|
export declare const RESOURCE_STATUS_MAX_BYTES: number;
|
|
@@ -15,10 +15,7 @@ export interface ResourceStatus {
|
|
|
15
15
|
platform: NodeJS.Platform | null;
|
|
16
16
|
namespace: ResourceSnapshot["namespace"];
|
|
17
17
|
support: ResourceSnapshot["support"] | null;
|
|
18
|
-
writer:
|
|
19
|
-
running: boolean;
|
|
20
|
-
stale: boolean;
|
|
21
|
-
};
|
|
18
|
+
writer: Pick<SupervisorStatus, "running" | "stale" | "generation" | "liveness" | "running_build" | "installed_build" | "restart_needed" | "build_status">;
|
|
22
19
|
/**
|
|
23
20
|
* The one published pressure assessment, read from the observer's record so
|
|
24
21
|
* this surface, the prompt notice, the dashboard, and a diagnostic bundle all
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/core/resources/status.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC7B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/core/resources/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { closeSync, fstatSync, openSync, readSync, statSync } from "node:fs";
|
|
|
2
2
|
import { unknownPressureAssessment } from "../diagnostics/advice.js";
|
|
3
3
|
import { PRESSURE_ASSESSMENT_SCHEMA_VERSION, PRESSURE_POLICY, } from "../diagnostics/contract.js";
|
|
4
4
|
import { SUPERVISOR_PRESSURE_SCHEMA_VERSION, } from "../supervisor/contract.js";
|
|
5
|
-
import { readSupervisorStatus } from "../supervisor/status.js";
|
|
5
|
+
import { installedSupervisorBuild, readSupervisorStatus } from "../supervisor/status.js";
|
|
6
6
|
import { supervisorPaths } from "../supervisor/storage.js";
|
|
7
7
|
import { RESOURCE_SNAPSHOT_SCHEMA_VERSION, } from "./contract.js";
|
|
8
8
|
import { resourcePaths } from "./storage.js";
|
|
@@ -156,11 +156,13 @@ export function formatResourceSummary(status) {
|
|
|
156
156
|
? "unknown"
|
|
157
157
|
: `${formatBytes(m.memory_available_bytes)} available`;
|
|
158
158
|
const diskText = disk ? `${formatBytes(disk.available_bytes)} available` : "unknown";
|
|
159
|
-
return `${lead} ${status.namespace}/${status.platform}: CPU ${cpu}, RAM ${ram}, disk ${diskText}; ${Math.round((status.sample_age_ms ?? 0) / 1_000)}s old${status.support?.state === "partial" ? "; partial" : ""}${!status.writer.running ? "
|
|
159
|
+
return `${lead} ${status.namespace}/${status.platform}: CPU ${cpu}, RAM ${ram}, disk ${diskText}; ${Math.round((status.sample_age_ms ?? 0) / 1_000)}s old${status.support?.state === "partial" ? "; partial" : ""}${!status.writer.running ? `; writer ${status.writer.liveness === "unknown" ? "unknown" : status.writer.stale ? "stale" : "stopped"}` : ""}.`;
|
|
160
160
|
}
|
|
161
161
|
export function formatResourceStatus(status, bin) {
|
|
162
162
|
const a = status.assessment;
|
|
163
163
|
const lines = [formatResourceSummary(status)];
|
|
164
|
+
const writer = status.writer;
|
|
165
|
+
lines.push(`Writer: ${writer.liveness}; generation ${writer.generation}; running build ${writer.running_build ? `${writer.running_build.version} (${writer.running_build.revision})` : "unknown"}; installed build ${writer.installed_build.version} (${writer.installed_build.revision}); ${writer.build_status}.`);
|
|
164
166
|
lines.push(`Assessment: ${a.state} at ${a.scope} scope; limiting resource ${a.limiting_resource}; trend ${a.trend}; evidence ${a.evidence_state}; recommended action ${a.recommended_action}.`);
|
|
165
167
|
lines.push(`Evidence age: ${a.sample_age_ms === null ? "unknown" : `${Math.round(a.sample_age_ms / 1_000)}s`}; assessment source ${status.assessment_capability.state}${status.assessment_capability.reason_code ? ` (${status.assessment_capability.reason_code})` : ""}.`);
|
|
166
168
|
for (const item of a.reasons)
|
|
@@ -176,7 +178,9 @@ export function formatResourceStatus(status, bin) {
|
|
|
176
178
|
}
|
|
177
179
|
if (a.unattributed_memory_percent !== null)
|
|
178
180
|
lines.push(`Unattributed memory: ${Math.round(a.unattributed_memory_percent)}% of machine memory has no validated owner.`);
|
|
179
|
-
if (status.
|
|
181
|
+
if (status.writer.liveness === "unknown")
|
|
182
|
+
lines.push(`Inspect the writer with ${bin} supervisor status. Run ${bin} supervisor stop to write its durable stop request before starting again.`);
|
|
183
|
+
else if (status.state !== "fresh" || !status.writer.running)
|
|
180
184
|
lines.push(`Start or inspect the writer with ${bin} supervisor start --keep-alive and ${bin} supervisor status.`);
|
|
181
185
|
if (status.host)
|
|
182
186
|
lines.push(`Windows host: ${status.host.state}${status.host.machine ? `; CPU ${status.host.machine.cpu_percent === null ? "warming up" : `${Math.round(status.host.machine.cpu_percent)}%`}, RAM ${status.host.machine.memory_available_bytes === null ? "unknown" : `${formatBytes(status.host.machine.memory_available_bytes)} available`}` : `; ${status.host.reason ?? "unavailable"}`}`);
|
|
@@ -238,7 +242,11 @@ export function readPublishedPressure(coordRoot, nowMs = Date.now(), writer) {
|
|
|
238
242
|
});
|
|
239
243
|
// A record can only be trusted while its writer is alive. Every surface makes
|
|
240
244
|
// the same check here so none of them reports a state the others do not.
|
|
241
|
-
|
|
245
|
+
const observer = writer ?? readWriterState(coordRoot, nowMs);
|
|
246
|
+
if (observer.liveness === "unknown") {
|
|
247
|
+
return gap("error", "pressure_observer_unknown", "Local resource pressure cannot be determined because the resource observer's process identity is unknown.");
|
|
248
|
+
}
|
|
249
|
+
if (!observer.running) {
|
|
242
250
|
return gap("expired", "pressure_observer_not_running", "Local resource pressure cannot be determined because the resource observer is not running.");
|
|
243
251
|
}
|
|
244
252
|
const path = supervisorPaths(coordRoot).pressure;
|
|
@@ -275,20 +283,41 @@ function readWriterState(coordRoot, nowMs) {
|
|
|
275
283
|
// Keep malformed service metadata from making the read expensive. The shared
|
|
276
284
|
// status reader retains ownership of PID/start-token liveness checks.
|
|
277
285
|
if (statSync(supervisorPaths(coordRoot).service).size > 65_536) {
|
|
278
|
-
return
|
|
286
|
+
return unknownWriterState();
|
|
279
287
|
}
|
|
280
288
|
const writer = readSupervisorStatus(coordRoot, nowMs);
|
|
281
289
|
const futureHeartbeat = writer.record && Date.parse(writer.record.heartbeat_at) > nowMs + FUTURE_TOLERANCE_MS;
|
|
282
290
|
return {
|
|
283
291
|
running: writer.running && !futureHeartbeat,
|
|
284
292
|
stale: writer.stale || !!futureHeartbeat,
|
|
293
|
+
generation: writer.generation,
|
|
294
|
+
liveness: writer.liveness,
|
|
295
|
+
running_build: writer.running_build,
|
|
296
|
+
installed_build: writer.installed_build,
|
|
297
|
+
restart_needed: writer.restart_needed,
|
|
298
|
+
build_status: writer.build_status,
|
|
285
299
|
};
|
|
286
300
|
}
|
|
287
|
-
catch {
|
|
301
|
+
catch (error) {
|
|
288
302
|
// A missing writer must not break normal coordination.
|
|
289
|
-
return {
|
|
303
|
+
return {
|
|
304
|
+
...unknownWriterState(),
|
|
305
|
+
liveness: error.code === "ENOENT" ? "stopped" : "unknown",
|
|
306
|
+
};
|
|
290
307
|
}
|
|
291
308
|
}
|
|
309
|
+
function unknownWriterState() {
|
|
310
|
+
return {
|
|
311
|
+
running: false,
|
|
312
|
+
stale: false,
|
|
313
|
+
generation: "unknown",
|
|
314
|
+
liveness: "unknown",
|
|
315
|
+
running_build: null,
|
|
316
|
+
installed_build: installedSupervisorBuild(),
|
|
317
|
+
restart_needed: true,
|
|
318
|
+
build_status: "running build unknown; restart needed",
|
|
319
|
+
};
|
|
320
|
+
}
|
|
292
321
|
function validPressureRecord(v) {
|
|
293
322
|
if (!object(v) ||
|
|
294
323
|
v.schema_version !== SUPERVISOR_PRESSURE_SCHEMA_VERSION ||
|