harnery 0.40.0 → 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/README.md +1 -1
- package/dist/commander.js +4 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +34 -20
- package/dist/commands/artifacts.d.ts.map +1 -1
- package/dist/commands/artifacts.js +113 -12
- package/dist/commands/browse-ai.d.ts.map +1 -1
- package/dist/commands/browse-ai.js +4 -0
- package/dist/commands/browse.d.ts +164 -0
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +388 -45
- package/dist/commands/checkpoint.js +8 -12
- package/dist/commands/claude-desktop.d.ts.map +1 -1
- package/dist/commands/claude-desktop.js +52 -0
- package/dist/commands/deinit.d.ts +1 -1
- package/dist/commands/deinit.d.ts.map +1 -1
- package/dist/commands/deinit.js +8 -4
- package/dist/commands/disk.d.ts +6 -0
- package/dist/commands/disk.d.ts.map +1 -0
- package/dist/commands/disk.js +80 -0
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +2 -0
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +58 -3
- package/dist/commands/fetch.d.ts.map +1 -1
- package/dist/commands/fetch.js +10 -0
- package/dist/commands/files.d.ts +16 -0
- package/dist/commands/files.d.ts.map +1 -1
- package/dist/commands/files.js +54 -2
- package/dist/commands/init.d.ts +21 -5
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +271 -109
- package/dist/commands/instructions.js +5 -4
- package/dist/commands/ledger-v3.d.ts.map +1 -1
- package/dist/commands/ledger-v3.js +2 -1
- package/dist/commands/rm.d.ts +4 -0
- package/dist/commands/rm.d.ts.map +1 -0
- package/dist/commands/rm.js +87 -0
- package/dist/commands/servers.d.ts +7 -0
- package/dist/commands/servers.d.ts.map +1 -0
- package/dist/commands/servers.js +394 -0
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +82 -2
- package/dist/commands/webview.d.ts +4 -0
- package/dist/commands/webview.d.ts.map +1 -0
- package/dist/commands/webview.js +94 -0
- package/dist/core/adapter.d.ts +50 -1
- package/dist/core/adapter.d.ts.map +1 -1
- package/dist/core/adapter.js +59 -1
- package/dist/core/adapters/attestation.d.ts.map +1 -1
- package/dist/core/adapters/attestation.js +3 -2
- package/dist/core/adapters/profiles.d.ts +29 -3
- package/dist/core/adapters/profiles.d.ts.map +1 -1
- package/dist/core/adapters/profiles.js +53 -1
- package/dist/core/adapters/registry.d.ts.map +1 -1
- package/dist/core/adapters/registry.js +33 -0
- package/dist/core/adapters/types.d.ts +9 -0
- package/dist/core/adapters/types.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.d.ts +1 -1
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +2 -7
- package/dist/core/agents/cli.js +25 -16
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +7 -2
- package/dist/core/agents/render/session-context.d.ts.map +1 -1
- package/dist/core/agents/render/session-context.js +2 -0
- package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/claim-conflict.js +3 -9
- package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/commit-conflict.js +2 -8
- package/dist/core/agents/rules/stop-hook.d.ts +2 -0
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +1 -1
- package/dist/core/agents/session-events.d.ts +6 -2
- package/dist/core/agents/session-events.d.ts.map +1 -1
- package/dist/core/agents/session-events.js +105 -26
- package/dist/core/agents/session-finalization-state-v3.d.ts.map +1 -1
- package/dist/core/agents/session-finalization-state-v3.js +2 -1
- package/dist/core/agents/session-finalizer-v3.d.ts.map +1 -1
- package/dist/core/agents/session-finalizer-v3.js +5 -4
- package/dist/core/agents/session-name-display.d.ts +28 -0
- package/dist/core/agents/session-name-display.d.ts.map +1 -1
- package/dist/core/agents/session-name-display.js +43 -0
- package/dist/core/agents/state/heartbeat-reader.d.ts +7 -0
- package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.d.ts +10 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +21 -2
- package/dist/core/agents/state/live-coordination-view.d.ts +20 -0
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +61 -0
- package/dist/core/agents/state/live-coordination-writer.js +3 -0
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +2 -10
- package/dist/core/agents/turn-changes.d.ts +17 -0
- package/dist/core/agents/turn-changes.d.ts.map +1 -0
- package/dist/core/agents/turn-changes.js +76 -0
- package/dist/core/artifacts/delivery-card.d.ts.map +1 -1
- package/dist/core/artifacts/delivery-card.js +11 -3
- package/dist/core/artifacts/index.d.ts +140 -4
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +526 -52
- package/dist/core/config.d.ts +73 -11
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +142 -3
- package/dist/core/context/index.d.ts.map +1 -1
- package/dist/core/context/index.js +2 -1
- package/dist/core/conversations/archive.d.ts.map +1 -1
- package/dist/core/conversations/archive.js +4 -3
- package/dist/core/diagnostics/bundle.d.ts.map +1 -1
- package/dist/core/diagnostics/bundle.js +5 -4
- package/dist/core/events/legacy-storage/canary.d.ts.map +1 -1
- package/dist/core/events/legacy-storage/canary.js +5 -4
- package/dist/core/events/legacy-storage/compression.d.ts.map +1 -1
- package/dist/core/events/legacy-storage/compression.js +2 -1
- package/dist/core/events/v3/adapter-id.d.ts +10 -2
- package/dist/core/events/v3/adapter-id.d.ts.map +1 -1
- package/dist/core/events/v3/adapter-id.js +16 -0
- package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
- package/dist/core/events/v3/authority-outbox.js +2 -1
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
- package/dist/core/events/v3/bootstrap.js +5 -4
- package/dist/core/events/v3/capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/capabilities.js +17 -0
- package/dist/core/events/v3/contract.d.ts +5 -0
- package/dist/core/events/v3/contract.d.ts.map +1 -1
- package/dist/core/events/v3/contract.js +7 -1
- package/dist/core/events/v3/control-witness.d.ts.map +1 -1
- package/dist/core/events/v3/control-witness.js +3 -2
- package/dist/core/events/v3/coordination-transaction-recovery.d.ts.map +1 -1
- package/dist/core/events/v3/coordination-transaction-recovery.js +4 -3
- package/dist/core/events/v3/fingerprint-keys.d.ts.map +1 -1
- package/dist/core/events/v3/fingerprint-keys.js +7 -6
- package/dist/core/events/v3/generated.d.ts +1 -1
- package/dist/core/events/v3/generated.js +1 -1
- package/dist/core/events/v3/live-feed.d.ts.map +1 -1
- package/dist/core/events/v3/live-feed.js +5 -4
- package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/command-recorder.js +8 -7
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +8 -7
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts.map +1 -1
- package/dist/core/events/v3/producers/diagnostic-summaries.js +5 -4
- package/dist/core/events/v3/producers/hook-base.d.ts +1 -0
- package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook-base.js +10 -4
- package/dist/core/events/v3/producers/hook.d.ts +2 -0
- package/dist/core/events/v3/producers/hook.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook.js +16 -1
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +16 -6
- package/dist/core/events/v3/producers/recorder.d.ts +2 -4
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +125 -101
- package/dist/core/events/v3/projection.js +9 -1
- package/dist/core/events/v3/recovery.d.ts.map +1 -1
- package/dist/core/events/v3/recovery.js +4 -3
- package/dist/core/events/v3/support-storage/inventory.d.ts.map +1 -1
- package/dist/core/events/v3/support-storage/inventory.js +2 -1
- package/dist/core/events/v3/support-storage/maintenance.d.ts.map +1 -1
- package/dist/core/events/v3/support-storage/maintenance.js +4 -3
- package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -1
- package/dist/core/events/v3/support-storage/pack-reader.js +4 -3
- package/dist/core/events/v3/support-storage/pack-writer.d.ts.map +1 -1
- package/dist/core/events/v3/support-storage/pack-writer.js +6 -5
- package/dist/core/events/v3/tool-line-changes.d.ts +8 -0
- package/dist/core/events/v3/tool-line-changes.d.ts.map +1 -0
- package/dist/core/events/v3/tool-line-changes.js +135 -0
- package/dist/core/events/v3/writer.d.ts.map +1 -1
- package/dist/core/events/v3/writer.js +8 -7
- package/dist/core/governor/planning.d.ts.map +1 -1
- package/dist/core/governor/planning.js +6 -5
- package/dist/core/governor/service.d.ts.map +1 -1
- package/dist/core/governor/service.js +12 -11
- package/dist/core/governor/state.d.ts.map +1 -1
- package/dist/core/governor/state.js +7 -6
- package/dist/core/guard/evaluator.js +1 -0
- package/dist/core/guard/storage.d.ts.map +1 -1
- package/dist/core/guard/storage.js +3 -2
- package/dist/core/hooks/adapter/behaviors/claude-code.d.ts +4 -0
- package/dist/core/hooks/adapter/behaviors/claude-code.d.ts.map +1 -0
- package/dist/core/hooks/adapter/behaviors/claude-code.js +31 -0
- package/dist/core/hooks/adapter/behaviors/codex.d.ts +15 -0
- package/dist/core/hooks/adapter/behaviors/codex.d.ts.map +1 -0
- package/dist/core/hooks/adapter/behaviors/codex.js +82 -0
- package/dist/core/hooks/adapter/behaviors/cursor.d.ts +7 -0
- package/dist/core/hooks/adapter/behaviors/cursor.d.ts.map +1 -0
- package/dist/core/hooks/adapter/behaviors/cursor.js +35 -0
- package/dist/core/hooks/adapter/behaviors/index.d.ts +11 -0
- package/dist/core/hooks/adapter/behaviors/index.d.ts.map +1 -0
- package/dist/core/hooks/adapter/behaviors/index.js +20 -0
- package/dist/core/hooks/adapter/behaviors/openclaw.d.ts +7 -0
- package/dist/core/hooks/adapter/behaviors/openclaw.d.ts.map +1 -0
- package/dist/core/hooks/adapter/behaviors/openclaw.js +34 -0
- package/dist/core/hooks/adapter/behaviors/opencode.d.ts +7 -0
- package/dist/core/hooks/adapter/behaviors/opencode.d.ts.map +1 -0
- package/dist/core/hooks/adapter/behaviors/opencode.js +34 -0
- package/dist/core/hooks/adapter/behaviors/types.d.ts +89 -0
- package/dist/core/hooks/adapter/behaviors/types.d.ts.map +1 -0
- package/dist/core/hooks/adapter/behaviors/types.js +1 -0
- package/dist/core/hooks/adapter/detect.d.ts +1 -1
- package/dist/core/hooks/adapter/detect.d.ts.map +1 -1
- package/dist/core/hooks/adapter/detect.js +2 -3
- package/dist/core/hooks/adapter/events.d.ts +46 -1
- package/dist/core/hooks/adapter/events.d.ts.map +1 -1
- package/dist/core/hooks/adapter/events.js +36 -0
- package/dist/core/hooks/adapter/opencode-plugin.d.ts +60 -0
- package/dist/core/hooks/adapter/opencode-plugin.d.ts.map +1 -0
- package/dist/core/hooks/adapter/opencode-plugin.js +129 -0
- package/dist/core/hooks/adapter/output.d.ts +7 -0
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +8 -1
- package/dist/core/hooks/adapter/runtime-telemetry.js +3 -1
- package/dist/core/hooks/adapter/wiring.d.ts +52 -8
- package/dist/core/hooks/adapter/wiring.d.ts.map +1 -1
- package/dist/core/hooks/adapter/wiring.js +133 -12
- package/dist/core/hooks/cli.js +676 -531
- package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
- package/dist/core/hooks/effects/image-capture.js +2 -1
- package/dist/core/hooks/prompt-context/contract.d.ts.map +1 -1
- package/dist/core/hooks/prompt-context/contract.js +1 -0
- package/dist/core/hooks/resolve/transcript.d.ts +1 -1
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +35 -4
- package/dist/core/hooks/run-markers.d.ts +37 -0
- package/dist/core/hooks/run-markers.d.ts.map +1 -0
- package/dist/core/hooks/run-markers.js +109 -0
- package/dist/core/hooks/session-name-presence.d.ts +3 -1
- package/dist/core/hooks/session-name-presence.d.ts.map +1 -1
- package/dist/core/hooks/session-name-presence.js +7 -2
- package/dist/core/hooks/shell-waiter.d.ts +2 -0
- package/dist/core/hooks/shell-waiter.d.ts.map +1 -0
- package/dist/core/hooks/shell-waiter.js +173 -0
- package/dist/core/resources/service.d.ts.map +1 -1
- package/dist/core/resources/service.js +5 -4
- package/dist/core/semantic/review.d.ts.map +1 -1
- package/dist/core/semantic/review.js +5 -4
- package/dist/core/semantic/service.d.ts.map +1 -1
- package/dist/core/semantic/service.js +15 -14
- package/dist/core/semantic/storage.d.ts.map +1 -1
- package/dist/core/semantic/storage.js +5 -4
- package/dist/core/servers/index.d.ts +211 -0
- package/dist/core/servers/index.d.ts.map +1 -0
- package/dist/core/servers/index.js +560 -0
- package/dist/core/servers/net.d.ts +58 -0
- package/dist/core/servers/net.d.ts.map +1 -0
- package/dist/core/servers/net.js +270 -0
- package/dist/core/servers/tunnels.d.ts +14 -0
- package/dist/core/servers/tunnels.d.ts.map +1 -0
- package/dist/core/servers/tunnels.js +33 -0
- package/dist/core/storage/atomic-json.d.ts.map +1 -1
- package/dist/core/storage/atomic-json.js +7 -3
- package/dist/core/storage/builtins.js +1 -0
- package/dist/core/storage/durable-history.d.ts.map +1 -1
- package/dist/core/storage/durable-history.js +6 -5
- package/dist/core/storage/maintenance-providers.d.ts.map +1 -1
- package/dist/core/storage/maintenance-providers.js +2 -1
- package/dist/core/storage/maintenance.d.ts.map +1 -1
- package/dist/core/storage/maintenance.js +7 -6
- package/dist/core/storage/metrics.d.ts.map +1 -1
- package/dist/core/storage/metrics.js +5 -1
- package/dist/core/storage/modes.d.ts +17 -0
- package/dist/core/storage/modes.d.ts.map +1 -0
- package/dist/core/storage/modes.js +47 -0
- package/dist/core/storage/process-log.d.ts.map +1 -1
- package/dist/core/storage/process-log.js +3 -2
- package/dist/core/storage/receipts.d.ts.map +1 -1
- package/dist/core/storage/receipts.js +4 -3
- package/dist/core/storage/segments.d.ts.map +1 -1
- package/dist/core/storage/segments.js +7 -6
- package/dist/core/supervisor/hook-health.d.ts +2 -1
- package/dist/core/supervisor/hook-health.d.ts.map +1 -1
- package/dist/core/supervisor/hook-health.js +4 -3
- package/dist/core/supervisor/service.d.ts.map +1 -1
- package/dist/core/supervisor/service.js +7 -6
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +8 -7
- package/dist/core/workflow/adapters.d.ts +7 -0
- package/dist/core/workflow/adapters.d.ts.map +1 -1
- package/dist/core/workflow/adapters.js +9 -0
- package/dist/core/workflow/approvals.d.ts.map +1 -1
- package/dist/core/workflow/approvals.js +6 -5
- package/dist/core/workflow/billing.d.ts.map +1 -1
- package/dist/core/workflow/billing.js +33 -4
- package/dist/core/workflow/durable-record.d.ts.map +1 -1
- package/dist/core/workflow/durable-record.js +4 -3
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +30 -1
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
- package/dist/core/workflow/live-session-v3.js +2 -3
- package/dist/core/workflow/run-state.d.ts.map +1 -1
- package/dist/core/workflow/run-state.js +3 -2
- package/dist/core/workflow/sandbox-projection.d.ts +13 -2
- package/dist/core/workflow/sandbox-projection.d.ts.map +1 -1
- package/dist/core/workflow/sandbox-projection.js +23 -0
- package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
- package/dist/core/workflow/spawn-claude.js +6 -1
- package/dist/core/workflow/spawn-codex.d.ts +2 -0
- package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
- package/dist/core/workflow/spawn-codex.js +20 -1
- package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
- package/dist/core/workflow/spawn-cursor.js +6 -1
- package/dist/core/workflow/spawn-opencode.d.ts +36 -0
- package/dist/core/workflow/spawn-opencode.d.ts.map +1 -0
- package/dist/core/workflow/spawn-opencode.js +135 -0
- package/dist/core/workflow/transcript.d.ts.map +1 -1
- package/dist/core/workflow/transcript.js +3 -2
- package/dist/core/workflow/types.d.ts +47 -2
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/worker-access.d.ts +92 -0
- package/dist/core/workflow/worker-access.d.ts.map +1 -0
- package/dist/core/workflow/worker-access.js +450 -0
- package/dist/core/workflow/workspaces/leases.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/leases.js +5 -4
- package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/local-git.js +3 -2
- package/dist/core/workflow/workspaces/paths.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/paths.js +2 -1
- package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/state.js +10 -9
- package/dist/lazy-commands.js +8 -1
- package/dist/lib/agent-browser/client.d.ts +9 -0
- package/dist/lib/agent-browser/client.d.ts.map +1 -1
- package/dist/lib/agent-browser/client.js +13 -0
- package/dist/lib/browser/batch-steps.d.ts +18 -0
- package/dist/lib/browser/batch-steps.d.ts.map +1 -0
- package/dist/lib/browser/batch-steps.js +82 -0
- package/dist/lib/browser/client.d.ts +35 -1
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +117 -8
- package/dist/lib/browser/collect/collector.d.ts +99 -0
- package/dist/lib/browser/collect/collector.d.ts.map +1 -0
- package/dist/lib/browser/collect/collector.js +202 -0
- package/dist/lib/browser/collect/fields.d.ts +31 -0
- package/dist/lib/browser/collect/fields.d.ts.map +1 -0
- package/dist/lib/browser/collect/fields.js +75 -0
- package/dist/lib/browser/collect/index.d.ts +6 -0
- package/dist/lib/browser/collect/index.d.ts.map +1 -0
- package/dist/lib/browser/collect/index.js +5 -0
- package/dist/lib/browser/collect/page-driver.d.ts +14 -0
- package/dist/lib/browser/collect/page-driver.d.ts.map +1 -0
- package/dist/lib/browser/collect/page-driver.js +306 -0
- package/dist/lib/browser/collect/presets.d.ts +52 -0
- package/dist/lib/browser/collect/presets.d.ts.map +1 -0
- package/dist/lib/browser/collect/presets.js +176 -0
- package/dist/lib/browser/collect/scroll-plan.d.ts +85 -0
- package/dist/lib/browser/collect/scroll-plan.d.ts.map +1 -0
- package/dist/lib/browser/collect/scroll-plan.js +118 -0
- package/dist/lib/browser/identity.d.ts +25 -0
- package/dist/lib/browser/identity.d.ts.map +1 -0
- package/dist/lib/browser/identity.js +66 -0
- package/dist/lib/browser/index.d.ts +3 -2
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +2 -1
- package/dist/lib/browser/launch-args.d.ts +26 -0
- package/dist/lib/browser/launch-args.d.ts.map +1 -1
- package/dist/lib/browser/launch-args.js +41 -1
- package/dist/lib/browser/page-review-judge.d.ts +2 -0
- package/dist/lib/browser/page-review-judge.d.ts.map +1 -1
- package/dist/lib/browser/page-review-judge.js +13 -0
- package/dist/lib/browser/qa-run-contracts.d.ts +10 -0
- package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -1
- package/dist/lib/browser/qa-run.d.ts.map +1 -1
- package/dist/lib/browser/qa-run.js +1 -0
- package/dist/lib/browser/user-agent.d.ts +53 -0
- package/dist/lib/browser/user-agent.d.ts.map +1 -0
- package/dist/lib/browser/user-agent.js +79 -0
- package/dist/lib/browser/windows-chrome.d.ts +59 -0
- package/dist/lib/browser/windows-chrome.d.ts.map +1 -0
- package/dist/lib/browser/windows-chrome.js +179 -0
- package/dist/lib/claude-desktop-share.d.ts +136 -0
- package/dist/lib/claude-desktop-share.d.ts.map +1 -0
- package/dist/lib/claude-desktop-share.js +394 -0
- package/dist/lib/disk-usage.d.ts +50 -0
- package/dist/lib/disk-usage.d.ts.map +1 -0
- package/dist/lib/disk-usage.js +303 -0
- package/dist/lib/docs-lint.d.ts +6 -0
- package/dist/lib/docs-lint.d.ts.map +1 -1
- package/dist/lib/docs-lint.js +8 -3
- package/dist/lib/docs-metadata-managed.d.ts +1 -0
- package/dist/lib/docs-metadata-managed.d.ts.map +1 -1
- package/dist/lib/docs-metadata-managed.js +17 -1
- package/dist/lib/guarded-remove.d.ts +34 -0
- package/dist/lib/guarded-remove.d.ts.map +1 -0
- package/dist/lib/guarded-remove.js +310 -0
- package/dist/lib/identities/assume.d.ts.map +1 -1
- package/dist/lib/identities/assume.js +4 -9
- package/dist/lib/instructions/apply.d.ts.map +1 -1
- package/dist/lib/instructions/apply.js +2 -0
- package/dist/lib/instructions/templates.js +8 -8
- package/dist/lib/pace/index.d.ts +2 -0
- package/dist/lib/pace/index.d.ts.map +1 -0
- package/dist/lib/pace/index.js +1 -0
- package/dist/lib/pace/pace.d.ts +95 -0
- package/dist/lib/pace/pace.d.ts.map +1 -0
- package/dist/lib/pace/pace.js +313 -0
- package/dist/lib/tunnel/error-page.d.ts +1 -1
- package/dist/lib/tunnel/error-page.d.ts.map +1 -1
- package/dist/lib/tunnel/error-page.js +19 -8
- package/dist/lib/tunnel/forward-headers.d.ts +11 -0
- package/dist/lib/tunnel/forward-headers.d.ts.map +1 -0
- package/dist/lib/tunnel/forward-headers.js +17 -0
- package/dist/lib/tunnel/gate.js +34 -10
- package/dist/lib/tunnel/path-scope.d.ts +22 -0
- package/dist/lib/tunnel/path-scope.d.ts.map +1 -0
- package/dist/lib/tunnel/path-scope.js +62 -0
- package/dist/lib/tunnel/state.d.ts +5 -0
- package/dist/lib/tunnel/state.d.ts.map +1 -1
- package/dist/lib/tunnel/state.js +17 -3
- package/dist/lib/webview/index.d.ts +2 -0
- package/dist/lib/webview/index.d.ts.map +1 -0
- package/dist/lib/webview/index.js +1 -0
- package/dist/lib/webview/webview.d.ts +116 -0
- package/dist/lib/webview/webview.d.ts.map +1 -0
- package/dist/lib/webview/webview.js +289 -0
- package/opencode-plugin/package.json +19 -0
- package/opencode-plugin/src/index.ts +791 -0
- package/package.json +16 -4
- package/schemas/config.schema.json +104 -0
- package/schemas/event-v3.schema.json +164 -0
- package/src/commander.ts +26 -0
- package/src/commands/agents.ts +47 -18
- package/src/commands/artifacts.ts +171 -19
- package/src/commands/browse-ai.ts +8 -0
- package/src/commands/browse.ts +570 -48
- package/src/commands/checkpoint.ts +7 -9
- package/src/commands/claude-desktop.ts +61 -0
- package/src/commands/deinit.ts +9 -4
- package/src/commands/disk.ts +114 -0
- package/src/commands/docs.ts +2 -0
- package/src/commands/doctor.ts +63 -3
- package/src/commands/fetch.ts +14 -0
- package/src/commands/files.ts +93 -2
- package/src/commands/init.ts +334 -122
- package/src/commands/instructions.ts +8 -4
- package/src/commands/ledger-v3.ts +2 -1
- package/src/commands/rm.ts +115 -0
- package/src/commands/servers.ts +506 -0
- package/src/commands/tunnel.ts +102 -2
- package/src/commands/webview.ts +159 -0
- package/src/core/adapter.ts +102 -1
- package/src/core/adapters/attestation.ts +3 -2
- package/src/core/adapters/profiles.ts +63 -1
- package/src/core/adapters/registry.ts +37 -0
- package/src/core/adapters/types.ts +10 -0
- package/src/core/agents/canonical-emit.ts +2 -5
- package/src/core/agents/cli.ts +26 -17
- package/src/core/agents/coord-client.ts +9 -3
- package/src/core/agents/render/session-context.ts +1 -0
- package/src/core/agents/rules/claim-conflict.ts +3 -8
- package/src/core/agents/rules/commit-conflict.ts +2 -7
- package/src/core/agents/rules/stop-hook.ts +3 -1
- package/src/core/agents/session-events.ts +120 -26
- package/src/core/agents/session-finalization-state-v3.ts +2 -1
- package/src/core/agents/session-finalizer-v3.ts +5 -4
- package/src/core/agents/session-name-display.ts +48 -0
- package/src/core/agents/state/heartbeat-reader.ts +7 -0
- package/src/core/agents/state/heartbeat-writer.ts +24 -2
- package/src/core/agents/state/live-coordination-view.ts +74 -0
- package/src/core/agents/state/live-coordination-writer.ts +3 -0
- package/src/core/agents/state/stale-sweep.ts +2 -9
- package/src/core/agents/turn-changes.ts +97 -0
- package/src/core/artifacts/delivery-card.ts +12 -3
- package/src/core/artifacts/index.ts +701 -47
- package/src/core/config.ts +206 -4
- package/src/core/context/index.ts +2 -1
- package/src/core/conversations/archive.ts +4 -3
- package/src/core/diagnostics/bundle.ts +5 -3
- package/src/core/events/legacy-storage/canary.ts +5 -4
- package/src/core/events/legacy-storage/compression.ts +2 -1
- package/src/core/events/v3/adapter-id.ts +29 -1
- package/src/core/events/v3/authority-outbox.ts +2 -1
- package/src/core/events/v3/bootstrap.ts +5 -4
- package/src/core/events/v3/capabilities.ts +17 -0
- package/src/core/events/v3/contract.ts +9 -1
- package/src/core/events/v3/control-witness.ts +3 -2
- package/src/core/events/v3/coordination-transaction-recovery.ts +4 -3
- package/src/core/events/v3/fingerprint-keys.ts +7 -6
- package/src/core/events/v3/generated.ts +1 -1
- package/src/core/events/v3/live-feed.ts +5 -4
- package/src/core/events/v3/producers/command-recorder.ts +8 -6
- package/src/core/events/v3/producers/coordination-recorder.ts +8 -7
- package/src/core/events/v3/producers/diagnostic-summaries.ts +5 -4
- package/src/core/events/v3/producers/hook-base.ts +11 -4
- package/src/core/events/v3/producers/hook.ts +19 -1
- package/src/core/events/v3/producers/intake.ts +18 -6
- package/src/core/events/v3/producers/recorder.ts +139 -114
- package/src/core/events/v3/projection.ts +11 -1
- package/src/core/events/v3/recovery.ts +4 -3
- package/src/core/events/v3/support-storage/inventory.ts +2 -1
- package/src/core/events/v3/support-storage/maintenance.ts +8 -3
- package/src/core/events/v3/support-storage/pack-reader.ts +4 -3
- package/src/core/events/v3/support-storage/pack-writer.ts +6 -5
- package/src/core/events/v3/tool-line-changes.ts +139 -0
- package/src/core/events/v3/writer.ts +8 -7
- package/src/core/governor/planning.ts +6 -5
- package/src/core/governor/service.ts +12 -11
- package/src/core/governor/state.ts +7 -6
- package/src/core/guard/evaluator.ts +1 -0
- package/src/core/guard/storage.ts +3 -2
- package/src/core/hooks/adapter/behaviors/claude-code.ts +33 -0
- package/src/core/hooks/adapter/behaviors/codex.ts +96 -0
- package/src/core/hooks/adapter/behaviors/cursor.ts +37 -0
- package/src/core/hooks/adapter/behaviors/index.ts +31 -0
- package/src/core/hooks/adapter/behaviors/openclaw.ts +36 -0
- package/src/core/hooks/adapter/behaviors/opencode.ts +36 -0
- package/src/core/hooks/adapter/behaviors/types.ts +110 -0
- package/src/core/hooks/adapter/detect.ts +2 -3
- package/src/core/hooks/adapter/events.ts +72 -1
- package/src/core/hooks/adapter/opencode-plugin.ts +177 -0
- package/src/core/hooks/adapter/output.ts +8 -1
- package/src/core/hooks/adapter/runtime-telemetry.ts +3 -1
- package/src/core/hooks/adapter/wiring.ts +198 -16
- package/src/core/hooks/cli.ts +776 -539
- package/src/core/hooks/effects/image-capture.ts +2 -1
- package/src/core/hooks/prompt-context/contract.ts +1 -0
- package/src/core/hooks/resolve/transcript.ts +42 -5
- package/src/core/hooks/run-markers.ts +132 -0
- package/src/core/hooks/session-name-presence.ts +10 -3
- package/src/core/hooks/shell-waiter.ts +166 -0
- package/src/core/resources/service.ts +5 -4
- package/src/core/semantic/review.ts +5 -4
- package/src/core/semantic/service.ts +15 -14
- package/src/core/semantic/storage.ts +5 -4
- package/src/core/servers/index.ts +712 -0
- package/src/core/servers/net.ts +283 -0
- package/src/core/servers/tunnels.ts +39 -0
- package/src/core/storage/atomic-json.ts +7 -3
- package/src/core/storage/builtins.ts +1 -0
- package/src/core/storage/durable-history.ts +6 -5
- package/src/core/storage/maintenance-providers.ts +2 -1
- package/src/core/storage/maintenance.ts +7 -6
- package/src/core/storage/metrics.ts +5 -1
- package/src/core/storage/modes.ts +53 -0
- package/src/core/storage/process-log.ts +3 -2
- package/src/core/storage/receipts.ts +4 -3
- package/src/core/storage/segments.ts +7 -6
- package/src/core/supervisor/hook-health.ts +4 -4
- package/src/core/supervisor/service.ts +7 -6
- package/src/core/work/state.ts +8 -7
- package/src/core/workflow/adapters.ts +15 -0
- package/src/core/workflow/approvals.ts +6 -5
- package/src/core/workflow/billing.ts +34 -4
- package/src/core/workflow/durable-record.ts +4 -3
- package/src/core/workflow/engine.ts +38 -1
- package/src/core/workflow/live-session-v3.ts +2 -3
- package/src/core/workflow/run-state.ts +3 -2
- package/src/core/workflow/sandbox-projection.ts +38 -2
- package/src/core/workflow/spawn-claude.ts +5 -1
- package/src/core/workflow/spawn-codex.ts +18 -1
- package/src/core/workflow/spawn-cursor.ts +5 -1
- package/src/core/workflow/spawn-opencode.ts +153 -0
- package/src/core/workflow/transcript.ts +3 -2
- package/src/core/workflow/types.ts +62 -2
- package/src/core/workflow/worker-access.ts +525 -0
- package/src/core/workflow/workspaces/leases.ts +5 -4
- package/src/core/workflow/workspaces/local-git.ts +3 -2
- package/src/core/workflow/workspaces/paths.ts +2 -1
- package/src/core/workflow/workspaces/state.ts +10 -9
- package/src/lazy-commands.ts +11 -1
- package/src/lib/agent-browser/client.ts +18 -0
- package/src/lib/browser/batch-steps.ts +79 -0
- package/src/lib/browser/client.ts +147 -9
- package/src/lib/browser/collect/collector.ts +306 -0
- package/src/lib/browser/collect/fields.ts +87 -0
- package/src/lib/browser/collect/index.ts +47 -0
- package/src/lib/browser/collect/page-driver.ts +327 -0
- package/src/lib/browser/collect/presets.ts +237 -0
- package/src/lib/browser/collect/scroll-plan.ts +179 -0
- package/src/lib/browser/identity.ts +64 -0
- package/src/lib/browser/index.ts +16 -1
- package/src/lib/browser/launch-args.ts +53 -1
- package/src/lib/browser/page-review-judge.ts +16 -0
- package/src/lib/browser/qa-run-contracts.ts +11 -0
- package/src/lib/browser/qa-run.ts +1 -0
- package/src/lib/browser/user-agent.ts +130 -0
- package/src/lib/browser/windows-chrome.ts +227 -0
- package/src/lib/claude-desktop-share.ts +511 -0
- package/src/lib/disk-usage.ts +347 -0
- package/src/lib/docs-lint.ts +8 -3
- package/src/lib/docs-metadata-managed.ts +21 -0
- package/src/lib/guarded-remove.ts +376 -0
- package/src/lib/identities/assume.ts +7 -7
- package/src/lib/instructions/apply.ts +2 -0
- package/src/lib/instructions/templates.ts +8 -8
- package/src/lib/pace/index.ts +14 -0
- package/src/lib/pace/pace.ts +370 -0
- package/src/lib/tunnel/error-page.ts +25 -9
- package/src/lib/tunnel/forward-headers.ts +16 -0
- package/src/lib/tunnel/gate.ts +39 -10
- package/src/lib/tunnel/path-scope.ts +73 -0
- package/src/lib/tunnel/state.ts +20 -3
- package/src/lib/webview/index.ts +13 -0
- package/src/lib/webview/webview.ts +457 -0
|
@@ -13,6 +13,11 @@ import {
|
|
|
13
13
|
cursorSpawner,
|
|
14
14
|
normalizeCursorResult,
|
|
15
15
|
} from "../workflow/spawn-cursor.ts";
|
|
16
|
+
import {
|
|
17
|
+
buildOpenCodeInvocation,
|
|
18
|
+
normalizeOpenCodeResult,
|
|
19
|
+
openCodeSpawner,
|
|
20
|
+
} from "../workflow/spawn-opencode.ts";
|
|
16
21
|
import {
|
|
17
22
|
BUILTIN_ADAPTER_IDS,
|
|
18
23
|
BUILTIN_ADAPTER_PROFILES,
|
|
@@ -85,6 +90,38 @@ const BUILTIN_ADAPTERS: Record<BuiltinAdapterId, Adapter> = {
|
|
|
85
90
|
},
|
|
86
91
|
},
|
|
87
92
|
},
|
|
93
|
+
opencode: {
|
|
94
|
+
profile: BUILTIN_ADAPTER_PROFILES.opencode,
|
|
95
|
+
spawn: openCodeSpawner,
|
|
96
|
+
buildInvocation: buildOpenCodeInvocation,
|
|
97
|
+
normalizeResult: normalizeOpenCodeResult,
|
|
98
|
+
fixture: {
|
|
99
|
+
// `opencode run --format json` streams NDJSON: a step-start line then one
|
|
100
|
+
// or more text parts, each carrying the same sessionID.
|
|
101
|
+
raw: {
|
|
102
|
+
stdout: [
|
|
103
|
+
JSON.stringify({
|
|
104
|
+
type: "step_start",
|
|
105
|
+
sessionID: "opencode-bench-session",
|
|
106
|
+
part: { type: "step-start" },
|
|
107
|
+
}),
|
|
108
|
+
JSON.stringify({
|
|
109
|
+
type: "text",
|
|
110
|
+
sessionID: "opencode-bench-session",
|
|
111
|
+
part: { type: "text", text: "HARNERY_BENCH_OK" },
|
|
112
|
+
}),
|
|
113
|
+
].join("\n"),
|
|
114
|
+
stderr: "",
|
|
115
|
+
exitCode: 0,
|
|
116
|
+
durationMs: 11,
|
|
117
|
+
},
|
|
118
|
+
expected: {
|
|
119
|
+
ok: true,
|
|
120
|
+
text: "HARNERY_BENCH_OK",
|
|
121
|
+
sessionId: "opencode-bench-session",
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
},
|
|
88
125
|
};
|
|
89
126
|
|
|
90
127
|
/** Mutable registry for embedders, initialized empty unless adapters are
|
|
@@ -67,6 +67,16 @@ export interface AdapterProfile {
|
|
|
67
67
|
/** How this adapter projects host filesystem policy into the vendor's own
|
|
68
68
|
* sandbox (ADR 0039). Absent means it cannot project any of it. */
|
|
69
69
|
sandboxProjection?: AdapterSandboxProjection;
|
|
70
|
+
/** Vendor-native arguments that launch a worker with no vendor sandbox
|
|
71
|
+
* (ADR 0192). Absent means the adapter has no distinguishable full-access
|
|
72
|
+
* mode, so a worker on it never qualifies for one. */
|
|
73
|
+
fullAccess?: AdapterFullAccessRendering;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** How an adapter renders an unsandboxed launch (ADR 0192). The spawner emits
|
|
77
|
+
* exactly these arguments, so the declaration and the argv cannot drift. */
|
|
78
|
+
export interface AdapterFullAccessRendering {
|
|
79
|
+
argv: readonly string[];
|
|
70
80
|
}
|
|
71
81
|
|
|
72
82
|
/** Fully planned child invocation. `resultFile` is used by adapters such as
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { spawnSync } from "node:child_process";
|
|
14
|
-
import type
|
|
14
|
+
import { type EventAdapterIdV3, eventAdapterIdV3FromPlatform } from "../events/v3/adapter-id.ts";
|
|
15
15
|
import type { LiveCoordinationObservationV3 } from "../events/v3/live-observation.ts";
|
|
16
16
|
import { coordBinPath } from "./coord-bin.ts";
|
|
17
17
|
import { resolveCoordRoot } from "./coord-client.ts";
|
|
@@ -94,10 +94,7 @@ export function emitEventV3(input: EventV3EmitInput): boolean {
|
|
|
94
94
|
* Normalize the heartbeat's `platform` field to the canonical Adapter type.
|
|
95
95
|
*/
|
|
96
96
|
export function normalizeAdapter(platform: string | undefined): EventAdapterIdV3 {
|
|
97
|
-
|
|
98
|
-
if (platform === "codex") return "codex";
|
|
99
|
-
if (platform === "openclaw") return "openclaw";
|
|
100
|
-
return "claude-code";
|
|
97
|
+
return eventAdapterIdV3FromPlatform(platform, { context: "canonical-emit" });
|
|
101
98
|
}
|
|
102
99
|
|
|
103
100
|
/** Producer joins use the private native session ID, never its V3 fingerprint. */
|
package/src/core/agents/cli.ts
CHANGED
|
@@ -13,6 +13,8 @@ import { appendFile, mkdir } from "node:fs/promises";
|
|
|
13
13
|
import { hostname } from "node:os";
|
|
14
14
|
import { dirname, join, resolve } from "node:path";
|
|
15
15
|
import { coordEnv } from "../../lib/env.ts";
|
|
16
|
+
import { normalizeAdapter, adapterFromPlatform as sharedAdapterFromPlatform } from "../adapter.ts";
|
|
17
|
+
import { resolveBinName } from "../config.ts";
|
|
16
18
|
import { closeProcessLoggers, legacyLogFields, processLogger } from "../storage/logger.ts";
|
|
17
19
|
import { acquireNoClobberLease } from "../workflow/workspaces/leases.ts";
|
|
18
20
|
|
|
@@ -166,12 +168,6 @@ async function handleProject(root: string, rest: string[]): Promise<number> {
|
|
|
166
168
|
return view.authority_safe ? 0 : 1;
|
|
167
169
|
}
|
|
168
170
|
|
|
169
|
-
function adapterFromPlatform(platform: unknown): "claude-code" | "cursor" | "codex" {
|
|
170
|
-
if (platform === "cursor") return "cursor";
|
|
171
|
-
if (platform === "codex") return "codex";
|
|
172
|
-
return "claude-code";
|
|
173
|
-
}
|
|
174
|
-
|
|
175
171
|
const coordinationRetryCell = new Int32Array(new SharedArrayBuffer(4));
|
|
176
172
|
const COORDINATION_RETRY_ATTEMPTS = 240;
|
|
177
173
|
const COORDINATION_RETRY_DELAY_MS = 25;
|
|
@@ -281,7 +277,7 @@ async function handleStateAction(root: string, action: string, rest: string[]):
|
|
|
281
277
|
coordRoot: root,
|
|
282
278
|
owner,
|
|
283
279
|
nativeSessionId: before?.session_id ?? owner,
|
|
284
|
-
adapter:
|
|
280
|
+
adapter: sharedAdapterFromPlatform(before?.platform, { context: "agent-coord" }),
|
|
285
281
|
task,
|
|
286
282
|
});
|
|
287
283
|
break;
|
|
@@ -312,9 +308,22 @@ async function handleStateAction(root: string, action: string, rest: string[]):
|
|
|
312
308
|
hb = writer.setAssignedNameCache(root, owner, name, "session");
|
|
313
309
|
}
|
|
314
310
|
} catch (error) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
)
|
|
311
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
312
|
+
// A missing heartbeat usually means the session's generation ended
|
|
313
|
+
// while its process lived on, so name the reopen command (ADR 0088).
|
|
314
|
+
// A still-live generation whose authority the ledger withholds looks
|
|
315
|
+
// the same here; name its diagnostics instead, since reopen cannot apply.
|
|
316
|
+
const { describeLiveAuthorityBlockV3, liveAuthorityBlockHintV3, liveAuthorityBlockV3 } =
|
|
317
|
+
await import("./state/live-coordination-view.ts");
|
|
318
|
+
const block = detail.includes("heartbeat_missing:")
|
|
319
|
+
? liveAuthorityBlockV3(root, owner)
|
|
320
|
+
: null;
|
|
321
|
+
const hint = block
|
|
322
|
+
? `; ${describeLiveAuthorityBlockV3(block)}; ${liveAuthorityBlockHintV3(resolveBinName(root))}`
|
|
323
|
+
: detail.includes("heartbeat_missing:")
|
|
324
|
+
? `; run \`${resolveBinName(root)} agents lifecycle active\` to open a fresh generation for this continuing session`
|
|
325
|
+
: "";
|
|
326
|
+
process.stderr.write(`agent-coord set-task: V3 authority refused (${detail})${hint}\n`);
|
|
318
327
|
return 1;
|
|
319
328
|
}
|
|
320
329
|
if (!hb) {
|
|
@@ -347,7 +356,7 @@ async function handleStateAction(root: string, action: string, rest: string[]):
|
|
|
347
356
|
coordRoot: root,
|
|
348
357
|
owner,
|
|
349
358
|
nativeSessionId: before?.session_id ?? owner,
|
|
350
|
-
adapter:
|
|
359
|
+
adapter: sharedAdapterFromPlatform(before?.platform, { context: "agent-coord" }),
|
|
351
360
|
operation: "released",
|
|
352
361
|
path,
|
|
353
362
|
access: "write",
|
|
@@ -408,7 +417,7 @@ async function handleStateAction(root: string, action: string, rest: string[]):
|
|
|
408
417
|
coordRoot: root,
|
|
409
418
|
owner,
|
|
410
419
|
nativeSessionId: sessionId ?? owner,
|
|
411
|
-
adapter:
|
|
420
|
+
adapter: sharedAdapterFromPlatform(adapter, { context: "agent-coord" }),
|
|
412
421
|
});
|
|
413
422
|
}
|
|
414
423
|
const { repairLiveCoordinationHeartbeat } = await import(
|
|
@@ -418,7 +427,7 @@ async function handleStateAction(root: string, action: string, rest: string[]):
|
|
|
418
427
|
root,
|
|
419
428
|
owner,
|
|
420
429
|
sessionId ?? owner,
|
|
421
|
-
|
|
430
|
+
sharedAdapterFromPlatform(adapter, { context: "agent-coord" }),
|
|
422
431
|
model,
|
|
423
432
|
);
|
|
424
433
|
} catch (error) {
|
|
@@ -453,7 +462,7 @@ async function handleStateAction(root: string, action: string, rest: string[]):
|
|
|
453
462
|
root,
|
|
454
463
|
owner,
|
|
455
464
|
sessionId ?? owner,
|
|
456
|
-
|
|
465
|
+
sharedAdapterFromPlatform(adapter, { context: "agent-coord" }),
|
|
457
466
|
);
|
|
458
467
|
if (!heartbeat) {
|
|
459
468
|
throw new Error("authoritative coordination cache could not be materialized");
|
|
@@ -471,7 +480,7 @@ async function handleStateAction(root: string, action: string, rest: string[]):
|
|
|
471
480
|
root,
|
|
472
481
|
owner,
|
|
473
482
|
sessionId ?? owner,
|
|
474
|
-
|
|
483
|
+
sharedAdapterFromPlatform(adapter, { context: "agent-coord" }),
|
|
475
484
|
);
|
|
476
485
|
process.stdout.write(
|
|
477
486
|
`${JSON.stringify({
|
|
@@ -875,7 +884,7 @@ async function handleEmitEvent(root: string, rest: string[]): Promise<number> {
|
|
|
875
884
|
const eventType = args.type;
|
|
876
885
|
const instanceId = args.owner;
|
|
877
886
|
const sessionId = args.session;
|
|
878
|
-
const adapter = args.adapter
|
|
887
|
+
const adapter = normalizeAdapter(args.adapter) ?? undefined;
|
|
879
888
|
const dataJson = args["data-stdin"] === "true" ? await readStdin() : "";
|
|
880
889
|
|
|
881
890
|
if (!eventType || !instanceId || !sessionId || !adapter || !dataJson) {
|
|
@@ -1063,7 +1072,7 @@ async function handleGitHook(fallbackRoot: string, rest: string[]): Promise<numb
|
|
|
1063
1072
|
owner,
|
|
1064
1073
|
subject: hit.instance_id,
|
|
1065
1074
|
nativeSessionId: hit.session_id ?? owner,
|
|
1066
|
-
adapter:
|
|
1075
|
+
adapter: sharedAdapterFromPlatform(hit.platform, { context: "agent-coord" }),
|
|
1067
1076
|
operation: "released",
|
|
1068
1077
|
path,
|
|
1069
1078
|
access: "write",
|
|
@@ -527,6 +527,10 @@ const SESSION_ID_ENV_VARS = [
|
|
|
527
527
|
"CURSOR_CONVERSATION_ID",
|
|
528
528
|
"CODEX_SESSION_ID",
|
|
529
529
|
"CODEX_THREAD_ID",
|
|
530
|
+
// OpenCode exports no session id into the tool shell; the Harnery OpenCode
|
|
531
|
+
// plugin stamps this via shell.hook("create.before") so a coord CLI run as a
|
|
532
|
+
// Bash tool recovers its identity.
|
|
533
|
+
"OPENCODE_SESSION_ID",
|
|
530
534
|
] as const;
|
|
531
535
|
|
|
532
536
|
/** Read normalized candidates from the first non-empty adapter session-id env var. */
|
|
@@ -637,10 +641,12 @@ export function resolveSingleActiveOwner(root: string): string | null {
|
|
|
637
641
|
return live.size === 1 ? [...live][0]! : null;
|
|
638
642
|
}
|
|
639
643
|
|
|
640
|
-
function adapterCandidatesFromEnv(): Array<"claude-code" | "codex" | "cursor"> {
|
|
644
|
+
function adapterCandidatesFromEnv(): Array<"claude-code" | "codex" | "cursor" | "opencode"> {
|
|
641
645
|
const value = process.env.HARNERY_AGENT_COORD_PLATFORM?.trim();
|
|
642
|
-
if (value === "claude-code" || value === "codex" || value === "cursor"
|
|
643
|
-
|
|
646
|
+
if (value === "claude-code" || value === "codex" || value === "cursor" || value === "opencode") {
|
|
647
|
+
return [value];
|
|
648
|
+
}
|
|
649
|
+
return ["claude-code", "codex", "cursor", "opencode"];
|
|
644
650
|
}
|
|
645
651
|
|
|
646
652
|
function nativeOwnerForV3Instance(root: string, instanceId: string): string {
|
|
@@ -126,6 +126,7 @@ export function renderSessionContext(opts: RenderOpts): string {
|
|
|
126
126
|
if (d.missing.length > 0)
|
|
127
127
|
bits.push(`missing: ${d.missing.map((m) => m.subcommand).join(", ")}`);
|
|
128
128
|
if (d.orphans.length > 0) bits.push(`orphaned: ${d.orphans.join(", ")}`);
|
|
129
|
+
if (d.stale.length > 0) bits.push(`outdated: ${d.stale.map((m) => m.subcommand).join(", ")}`);
|
|
129
130
|
return ` - ${d.settingsFile} — ${bits.join("; ")}`;
|
|
130
131
|
});
|
|
131
132
|
messages.push(
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
import { spawnSync } from "node:child_process";
|
|
18
18
|
import { existsSync } from "node:fs";
|
|
19
19
|
import { join } from "node:path";
|
|
20
|
+
import { adapterFromPlatform as sharedAdapterFromPlatform } from "../../adapter.ts";
|
|
20
21
|
import { recordLiveClaimChangeV3 } from "../live-authority-v3.ts";
|
|
21
22
|
import { readLiveCoordinationRows } from "../state/live-coordination-view.ts";
|
|
22
23
|
|
|
@@ -248,7 +249,7 @@ function acquireClaimThroughLedger(coordRoot: string, req: ClaimRequest): boolea
|
|
|
248
249
|
coordRoot,
|
|
249
250
|
owner: req.instance_id,
|
|
250
251
|
nativeSessionId: req.session_id ?? owner?.session_id ?? req.instance_id,
|
|
251
|
-
adapter:
|
|
252
|
+
adapter: sharedAdapterFromPlatform(owner?.platform, { context: "claim-conflict" }),
|
|
252
253
|
operation: "acquired",
|
|
253
254
|
path: req.path,
|
|
254
255
|
access: "write",
|
|
@@ -272,7 +273,7 @@ function releaseClaimThroughLedger(
|
|
|
272
273
|
owner: actor.instance_id,
|
|
273
274
|
subject: subjectInstanceId,
|
|
274
275
|
nativeSessionId: actor.session_id ?? owner?.session_id ?? actor.instance_id,
|
|
275
|
-
adapter:
|
|
276
|
+
adapter: sharedAdapterFromPlatform(owner?.platform, { context: "claim-conflict" }),
|
|
276
277
|
operation: "released",
|
|
277
278
|
path: relPath,
|
|
278
279
|
access: "write",
|
|
@@ -283,12 +284,6 @@ function releaseClaimThroughLedger(
|
|
|
283
284
|
}
|
|
284
285
|
}
|
|
285
286
|
|
|
286
|
-
function adapterFromPlatform(platform: unknown): "claude-code" | "cursor" | "codex" {
|
|
287
|
-
if (platform === "cursor") return "cursor";
|
|
288
|
-
if (platform === "codex") return "codex";
|
|
289
|
-
return "claude-code";
|
|
290
|
-
}
|
|
291
|
-
|
|
292
287
|
function authorityUnavailable(path: string, operation: string): VerdictResult {
|
|
293
288
|
return {
|
|
294
289
|
allow: false,
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
import { spawnSync } from "node:child_process";
|
|
24
24
|
import { appendFileSync, existsSync } from "node:fs";
|
|
25
25
|
import { basename, dirname, join } from "node:path";
|
|
26
|
+
import { adapterFromPlatform as sharedAdapterFromPlatform } from "../../adapter.ts";
|
|
26
27
|
import { coordFreshnessSeconds } from "../../config.ts";
|
|
27
28
|
import { resolveOwner } from "../../hooks/resolve/owner.ts";
|
|
28
29
|
import { recordLiveClaimChangeV3 } from "../live-authority-v3.ts";
|
|
@@ -232,7 +233,7 @@ function retainBlockedStagedPaths(
|
|
|
232
233
|
coordRoot,
|
|
233
234
|
owner: instanceId,
|
|
234
235
|
nativeSessionId: self.session_id ?? sessionId,
|
|
235
|
-
adapter:
|
|
236
|
+
adapter: sharedAdapterFromPlatform(self.platform, { context: "commit-conflict" }),
|
|
236
237
|
operation: "acquired",
|
|
237
238
|
path,
|
|
238
239
|
access: "write",
|
|
@@ -244,12 +245,6 @@ function retainBlockedStagedPaths(
|
|
|
244
245
|
}
|
|
245
246
|
}
|
|
246
247
|
|
|
247
|
-
function adapterFromPlatform(platform: unknown): "claude-code" | "cursor" | "codex" {
|
|
248
|
-
if (platform === "cursor") return "cursor";
|
|
249
|
-
if (platform === "codex") return "codex";
|
|
250
|
-
return "claude-code";
|
|
251
|
-
}
|
|
252
|
-
|
|
253
248
|
function findOverlap(
|
|
254
249
|
staged: string,
|
|
255
250
|
files: readonly string[],
|
|
@@ -32,6 +32,8 @@ export interface StopHookRequest {
|
|
|
32
32
|
turn_window?: { start_ms: number; end_ms: number };
|
|
33
33
|
stop_hook_active?: boolean;
|
|
34
34
|
status_box_present_strict?: boolean;
|
|
35
|
+
/** Current observation overrides an older failed terminal during remediation. */
|
|
36
|
+
session_name_observation_unavailable?: boolean;
|
|
35
37
|
bypass?: boolean;
|
|
36
38
|
workflow_child?: boolean;
|
|
37
39
|
}
|
|
@@ -188,7 +190,7 @@ export function evaluateStopHookV3Events(
|
|
|
188
190
|
|
|
189
191
|
// Claude Code can prove session-name presentation from assistant-only text.
|
|
190
192
|
// Cursor cannot expose that text and Codex returned observe-only above.
|
|
191
|
-
if (req.adapter !== "cursor") {
|
|
193
|
+
if (req.adapter !== "cursor" && !req.session_name_observation_unavailable) {
|
|
192
194
|
const naming = turnTerminals
|
|
193
195
|
.map((event) => observedNaming(event.payload.ritual?.session_name))
|
|
194
196
|
.filter((value): value is { required: boolean; present: boolean } => value !== undefined);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* `writeSessionEvent` records command spans in the canonical V3 ledger.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { randomBytes } from "node:crypto";
|
|
7
|
+
import { createHash, type Hash, randomBytes } from "node:crypto";
|
|
8
8
|
import { existsSync, readFileSync } from "node:fs";
|
|
9
9
|
import { resolve } from "node:path";
|
|
10
10
|
// Kept dependency-light: vendored verbatim into a downstream consumer, so no coordEnv import.
|
|
@@ -64,18 +64,52 @@ export function readLastIntent(instanceId?: string): string | null {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
type OutputStream = "stdout" | "stderr" | "combined";
|
|
68
|
+
|
|
69
|
+
interface OutputSummary {
|
|
70
|
+
stream: OutputStream;
|
|
71
|
+
bytes: number;
|
|
72
|
+
lines: number;
|
|
73
|
+
chunks: number;
|
|
74
|
+
hash: Hash;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
interface PendingCommand {
|
|
78
|
+
coordRoot: string;
|
|
79
|
+
fields: Record<string, unknown>;
|
|
80
|
+
streams: Map<OutputStream, OutputSummary>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const pendingCommands = new Map<string, PendingCommand>();
|
|
84
|
+
let exitFlushInstalled = false;
|
|
85
|
+
|
|
86
|
+
function commandKey(fields: Record<string, unknown>): string | undefined {
|
|
87
|
+
return typeof fields.instance_id === "string" && typeof fields.cmd_id === "string"
|
|
88
|
+
? JSON.stringify([fields.instance_id, fields.cmd_id])
|
|
89
|
+
: undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function flushCommandOutput(command: PendingCommand): void {
|
|
93
|
+
for (const summary of command.streams.values()) {
|
|
94
|
+
recordCommandObservation("command.output_observed", command.fields, command.coordRoot, summary);
|
|
95
|
+
}
|
|
96
|
+
command.streams.clear();
|
|
97
|
+
}
|
|
68
98
|
|
|
69
99
|
/** Emit a command/narration event to the canonical stream. Swallows every
|
|
70
100
|
* error and skips when identity can't be resolved: telemetry must never break
|
|
71
101
|
* or slow down a command. */
|
|
72
|
-
function recordCommandObservation(
|
|
102
|
+
function recordCommandObservation(
|
|
103
|
+
type: SessionEventType,
|
|
104
|
+
fields: Record<string, unknown>,
|
|
105
|
+
coordRoot: string,
|
|
106
|
+
summary?: OutputSummary,
|
|
107
|
+
): boolean {
|
|
73
108
|
const instanceId = typeof fields.instance_id === "string" ? fields.instance_id : undefined;
|
|
74
|
-
if (!instanceId) return;
|
|
109
|
+
if (!instanceId) return false;
|
|
75
110
|
try {
|
|
76
|
-
const coordRoot = coordinationRootPath();
|
|
77
111
|
const route = resolveLiveEventLedgerRouteV3(coordRoot);
|
|
78
|
-
if (route.state === "blocked") return;
|
|
112
|
+
if (route.state === "blocked") return false;
|
|
79
113
|
const liveInstanceId = liveInstanceIdV3(instanceId);
|
|
80
114
|
const hook = readHookProducerStateByInstanceV3(coordRoot, liveInstanceId);
|
|
81
115
|
if (!hook) {
|
|
@@ -84,10 +118,10 @@ function recordCommandObservation(type: SessionEventType, fields: Record<string,
|
|
|
84
118
|
instance_id: instanceId,
|
|
85
119
|
reason: "hook_generation_not_found",
|
|
86
120
|
});
|
|
87
|
-
return;
|
|
121
|
+
return false;
|
|
88
122
|
}
|
|
89
|
-
const command = commandSignalAndObservation(type, fields);
|
|
90
|
-
if (!command) return;
|
|
123
|
+
const command = commandSignalAndObservation(type, fields, summary);
|
|
124
|
+
if (!command) return false;
|
|
91
125
|
const result = recordCommandSignalV3({
|
|
92
126
|
coordRoot,
|
|
93
127
|
mode: route.mode,
|
|
@@ -105,7 +139,7 @@ function recordCommandObservation(type: SessionEventType, fields: Record<string,
|
|
|
105
139
|
const expectedLifecycleReopenGap =
|
|
106
140
|
result.reason === "turn_not_started" &&
|
|
107
141
|
hook.session_start_derivation === "approved_lifecycle_reopen";
|
|
108
|
-
if (expectedLifecycleReopenGap) return;
|
|
142
|
+
if (expectedLifecycleReopenGap) return false;
|
|
109
143
|
writeProducerDiagnosticV3(coordRoot, "command_emit_unjoinable", {
|
|
110
144
|
type,
|
|
111
145
|
instance_id: instanceId,
|
|
@@ -120,10 +154,10 @@ function recordCommandObservation(type: SessionEventType, fields: Record<string,
|
|
|
120
154
|
result_state: result.state,
|
|
121
155
|
});
|
|
122
156
|
}
|
|
157
|
+
return result.state === "recorded" || result.state === "already_recorded";
|
|
123
158
|
} catch (error) {
|
|
124
159
|
// Telemetry must never break the command, but the loss is preserved.
|
|
125
160
|
try {
|
|
126
|
-
const coordRoot = coordinationRootPath();
|
|
127
161
|
writeProducerDiagnosticV3(coordRoot, "command_emit_failed", {
|
|
128
162
|
type,
|
|
129
163
|
instance_id: instanceId,
|
|
@@ -132,17 +166,26 @@ function recordCommandObservation(type: SessionEventType, fields: Record<string,
|
|
|
132
166
|
} catch {
|
|
133
167
|
/* diagnostics are best-effort */
|
|
134
168
|
}
|
|
169
|
+
return false;
|
|
135
170
|
}
|
|
136
171
|
}
|
|
137
172
|
|
|
173
|
+
/** Count the non-empty lines in one output chunk; a single event may carry many. */
|
|
174
|
+
export function countOutputLines(text: string): number {
|
|
175
|
+
if (!text) return 0;
|
|
176
|
+
let count = 0;
|
|
177
|
+
for (const line of text.split("\n")) if (line.length > 0) count += 1;
|
|
178
|
+
return count;
|
|
179
|
+
}
|
|
180
|
+
|
|
138
181
|
function commandSignalAndObservation(
|
|
139
182
|
type: SessionEventType,
|
|
140
183
|
fields: Record<string, unknown>,
|
|
184
|
+
summary?: OutputSummary,
|
|
141
185
|
): { signal: CommandSignalV3; observation: CommandObservationV3 } | undefined {
|
|
142
186
|
const commandId = typeof fields.cmd_id === "string" ? fields.cmd_id : undefined;
|
|
143
187
|
if (!commandId) return undefined;
|
|
144
188
|
if (type === "command.started") {
|
|
145
|
-
outputSequence.set(commandId, 0);
|
|
146
189
|
const command = typeof fields.cmd === "string" ? fields.cmd : "";
|
|
147
190
|
const executable = command.trim().split(/\s+/, 1)[0] || "unknown";
|
|
148
191
|
return {
|
|
@@ -161,24 +204,25 @@ function commandSignalAndObservation(
|
|
|
161
204
|
};
|
|
162
205
|
}
|
|
163
206
|
if (type === "command.output_observed") {
|
|
164
|
-
|
|
165
|
-
outputSequence.set(commandId, sequence);
|
|
166
|
-
const line = typeof fields.line === "string" ? fields.line : "";
|
|
167
|
-
const stream =
|
|
168
|
-
fields.stream === "stdout" || fields.stream === "stderr" ? fields.stream : "combined";
|
|
207
|
+
if (!summary) return undefined;
|
|
169
208
|
return {
|
|
170
209
|
signal: "command.output_observed",
|
|
171
210
|
observation: {
|
|
172
211
|
native_command_id: commandId,
|
|
173
|
-
native_observation_id: `${commandId}:output:${
|
|
174
|
-
stream,
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
212
|
+
native_observation_id: `${commandId}:output-summary:${summary.stream}`,
|
|
213
|
+
stream: summary.stream,
|
|
214
|
+
// The normalizer HMACs this bounded descriptor with the generation key.
|
|
215
|
+
// Neither raw output nor its unkeyed digest is written to the ledger.
|
|
216
|
+
output: {
|
|
217
|
+
format: "harnery-output-chunks-v1",
|
|
218
|
+
chunks: summary.chunks,
|
|
219
|
+
sha256: summary.hash.digest("hex"),
|
|
220
|
+
},
|
|
221
|
+
output_bytes: summary.bytes,
|
|
222
|
+
output_lines: summary.lines,
|
|
178
223
|
},
|
|
179
224
|
};
|
|
180
225
|
}
|
|
181
|
-
outputSequence.delete(commandId);
|
|
182
226
|
const exitCode =
|
|
183
227
|
typeof fields.exit === "number" && Number.isSafeInteger(fields.exit) ? fields.exit : undefined;
|
|
184
228
|
return {
|
|
@@ -197,14 +241,64 @@ function commandSignalAndObservation(
|
|
|
197
241
|
}
|
|
198
242
|
|
|
199
243
|
/**
|
|
200
|
-
*
|
|
201
|
-
*
|
|
244
|
+
* Start/completion use the durable V3 recorder. Output only updates bounded
|
|
245
|
+
* per-stream counters and hashes; summaries flush before completion or at
|
|
246
|
+
* process exit. A forced kill can lose unflushed summaries (ADR 0188).
|
|
247
|
+
* Best-effort: telemetry never throws into the caller.
|
|
202
248
|
*/
|
|
203
249
|
export function writeSessionEvent(
|
|
204
250
|
type: SessionEventType,
|
|
205
251
|
fields: Record<string, unknown> = {},
|
|
206
252
|
): void {
|
|
207
|
-
|
|
253
|
+
try {
|
|
254
|
+
const key = commandKey(fields);
|
|
255
|
+
if (!key) return;
|
|
256
|
+
if (type === "command.output_observed") {
|
|
257
|
+
const command = pendingCommands.get(key);
|
|
258
|
+
if (!command) return;
|
|
259
|
+
const stream =
|
|
260
|
+
fields.stream === "stdout" || fields.stream === "stderr" ? fields.stream : "combined";
|
|
261
|
+
let summary = command.streams.get(stream);
|
|
262
|
+
if (!summary) {
|
|
263
|
+
summary = { stream, bytes: 0, lines: 0, chunks: 0, hash: createHash("sha256") };
|
|
264
|
+
command.streams.set(stream, summary);
|
|
265
|
+
}
|
|
266
|
+
const line = typeof fields.line === "string" ? fields.line : "";
|
|
267
|
+
const normalized = line.normalize("NFC");
|
|
268
|
+
// Length framing preserves chunk boundaries, including empty chunks.
|
|
269
|
+
summary.hash.update(`${Buffer.byteLength(normalized, "utf8")}:`).update(normalized);
|
|
270
|
+
summary.bytes += Buffer.byteLength(line, "utf8");
|
|
271
|
+
summary.lines += countOutputLines(line);
|
|
272
|
+
summary.chunks += 1;
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
const command = pendingCommands.get(key);
|
|
276
|
+
const coordRoot = command?.coordRoot ?? coordinationRootPath();
|
|
277
|
+
if (type === "command.completed") {
|
|
278
|
+
pendingCommands.delete(key);
|
|
279
|
+
if (command) flushCommandOutput(command);
|
|
280
|
+
recordCommandObservation(type, fields, coordRoot);
|
|
281
|
+
} else if (recordCommandObservation(type, fields, coordRoot) && !command) {
|
|
282
|
+
pendingCommands.set(key, {
|
|
283
|
+
coordRoot,
|
|
284
|
+
fields: {
|
|
285
|
+
instance_id: fields.instance_id,
|
|
286
|
+
cmd_id: fields.cmd_id,
|
|
287
|
+
bridge: fields.bridge,
|
|
288
|
+
},
|
|
289
|
+
streams: new Map(),
|
|
290
|
+
});
|
|
291
|
+
if (!exitFlushInstalled) {
|
|
292
|
+
exitFlushInstalled = true;
|
|
293
|
+
process.once("exit", () => {
|
|
294
|
+
for (const pending of pendingCommands.values()) flushCommandOutput(pending);
|
|
295
|
+
pendingCommands.clear();
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
} catch {
|
|
300
|
+
// Root resolution and in-memory bookkeeping must not break the command.
|
|
301
|
+
}
|
|
208
302
|
}
|
|
209
303
|
|
|
210
304
|
/** Trim long values to keep individual events small. */
|
|
@@ -2,6 +2,7 @@ import { existsSync, lstatSync, readdirSync, readFileSync } from "node:fs";
|
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
3
|
import type { ApprovedSessionEndReasonV3 } from "../events/v3/producers/recorder.ts";
|
|
4
4
|
import { EVENT_V3_LEDGER_RELATIVE_ROOT } from "../events/v3/reader.ts";
|
|
5
|
+
import { stateModeTooOpen } from "../storage/modes.ts";
|
|
5
6
|
|
|
6
7
|
export const SESSION_FINALIZATION_REQUEST_FORMAT_V3 =
|
|
7
8
|
"harnery-v3-session-finalization-request" as const;
|
|
@@ -72,7 +73,7 @@ export function listSessionFinalizationRequestsV3(
|
|
|
72
73
|
|
|
73
74
|
export function readSessionFinalizationRequestV3(filePath: string): SessionFinalizationRequestV3 {
|
|
74
75
|
const metadata = lstatSync(filePath);
|
|
75
|
-
if (!metadata.isFile() || metadata.isSymbolicLink() || (metadata.mode
|
|
76
|
+
if (!metadata.isFile() || metadata.isSymbolicLink() || stateModeTooOpen(metadata.mode)) {
|
|
76
77
|
throw new Error("V3 session finalization request is unsafe");
|
|
77
78
|
}
|
|
78
79
|
const request = JSON.parse(readFileSync(filePath, "utf8")) as SessionFinalizationRequestV3;
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
import { readLedgerV3 } from "../events/v3/reader.ts";
|
|
33
33
|
import { assertEventV3 } from "../events/v3/validate.ts";
|
|
34
34
|
import { EVENT_V3_LEDGER_RELATIVE_ROOT, writeEventV3 } from "../events/v3/writer.ts";
|
|
35
|
+
import { stateDirMode, stateFileMode } from "../storage/modes.ts";
|
|
35
36
|
import { fsyncParentDirectory } from "../workflow/durable-record.ts";
|
|
36
37
|
import { acquireNoClobberLease } from "../workflow/workspaces/leases.ts";
|
|
37
38
|
import { readCodexArchiveObservationsV3 } from "./codex-archive-v3.ts";
|
|
@@ -901,20 +902,20 @@ function writeRequest(
|
|
|
901
902
|
create = false,
|
|
902
903
|
): void {
|
|
903
904
|
const directory = sessionFinalizationRequestDirectoryV3(coordRoot);
|
|
904
|
-
mkdirSync(directory, { recursive: true, mode:
|
|
905
|
-
chmodSync(directory,
|
|
905
|
+
mkdirSync(directory, { recursive: true, mode: stateDirMode() });
|
|
906
|
+
chmodSync(directory, stateDirMode());
|
|
906
907
|
const path = sessionFinalizationRequestPathV3(coordRoot, request.request_id);
|
|
907
908
|
if (create && existsSync(path)) throw new Error("V3 finalization request already exists");
|
|
908
909
|
const temporary = `${path}.tmp-${process.pid}-${randomUUID()}`;
|
|
909
910
|
let fd: number | undefined;
|
|
910
911
|
try {
|
|
911
|
-
fd = openSync(temporary, "wx",
|
|
912
|
+
fd = openSync(temporary, "wx", stateFileMode());
|
|
912
913
|
writeFileSync(fd, `${JSON.stringify(request)}\n`, "utf8");
|
|
913
914
|
fsyncSync(fd);
|
|
914
915
|
closeSync(fd);
|
|
915
916
|
fd = undefined;
|
|
916
917
|
renameSync(temporary, path);
|
|
917
|
-
chmodSync(path,
|
|
918
|
+
chmodSync(path, stateFileMode());
|
|
918
919
|
fsyncParentDirectory(path);
|
|
919
920
|
} finally {
|
|
920
921
|
if (fd !== undefined) closeSync(fd);
|