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
package/src/commands/tunnel.ts
CHANGED
|
@@ -4,12 +4,20 @@ import { resolve } from "node:path";
|
|
|
4
4
|
import type { Command } from "commander";
|
|
5
5
|
import type { EmitContext, HarneryProgramContext } from "../commander.ts";
|
|
6
6
|
|
|
7
|
+
import { resolveCoordRoot } from "../core/agents/coord-client.ts";
|
|
7
8
|
import { resolveBinName } from "../core/config.ts";
|
|
9
|
+
import {
|
|
10
|
+
tryRegisterServer,
|
|
11
|
+
tunnelServerId,
|
|
12
|
+
tunnelServerInput,
|
|
13
|
+
unregisterServer,
|
|
14
|
+
} from "../core/servers/index.ts";
|
|
8
15
|
import {
|
|
9
16
|
processLogDestination,
|
|
10
17
|
runRotatingProcessSync,
|
|
11
18
|
spawnRotatingProcess,
|
|
12
19
|
} from "../core/storage/process-log.ts";
|
|
20
|
+
import { ALLOW_PATHS_ENV, normalizeAllowPaths } from "../lib/tunnel/path-scope.ts";
|
|
13
21
|
import {
|
|
14
22
|
clearState,
|
|
15
23
|
DEFAULT_INSTANCE,
|
|
@@ -35,6 +43,8 @@ import {
|
|
|
35
43
|
* upstream. Cloudflare quick tunnels add an IP allowlist at the gate via the
|
|
36
44
|
* Cloudflare-set `CF-Connecting-IP` header; Tailscale Serve/Funnel exposes the
|
|
37
45
|
* same gate through tailscaled, with Tailscale owning the access boundary.
|
|
46
|
+
* Every provider also passes through a path scope: `up` requires at least one
|
|
47
|
+
* `--allow-path <prefix>`, and the gate refuses any request outside it.
|
|
38
48
|
*
|
|
39
49
|
* State + config persisted under `.cache/tunnel/`. cloudflared auto-installs
|
|
40
50
|
* to ~/.local/bin/ on first run (Linux only; macOS users `brew install`);
|
|
@@ -55,6 +65,7 @@ interface UpOpts {
|
|
|
55
65
|
visibility?: string;
|
|
56
66
|
path?: string;
|
|
57
67
|
httpsPort?: string;
|
|
68
|
+
allowPath?: string[];
|
|
58
69
|
}
|
|
59
70
|
|
|
60
71
|
interface DownOpts {
|
|
@@ -165,6 +176,46 @@ function resolveHttpsPort(raw: string | undefined): number {
|
|
|
165
176
|
return port;
|
|
166
177
|
}
|
|
167
178
|
|
|
179
|
+
/**
|
|
180
|
+
* The path scope for `up`. At least one prefix is required: a tunnel forwards
|
|
181
|
+
* to a whole local app, and publishing all of it has to be a stated choice
|
|
182
|
+
* (`--allow-path /`), never the result of leaving a flag off.
|
|
183
|
+
*/
|
|
184
|
+
function resolveAllowPaths(raw: string[] | undefined): string[] {
|
|
185
|
+
let paths: string[];
|
|
186
|
+
try {
|
|
187
|
+
paths = normalizeAllowPaths(raw ?? []);
|
|
188
|
+
} catch (error) {
|
|
189
|
+
emit.error({
|
|
190
|
+
code: "tunnel_path_scope_invalid",
|
|
191
|
+
message: error instanceof Error ? error.message : String(error),
|
|
192
|
+
});
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
if (paths.length === 0) {
|
|
196
|
+
emit.error({
|
|
197
|
+
code: "tunnel_path_scope_empty",
|
|
198
|
+
message:
|
|
199
|
+
"No path scope; refusing to start. Name what the tunnel shares with --allow-path <prefix> " +
|
|
200
|
+
"(repeatable), or pass --allow-path / to publish the whole upstream.",
|
|
201
|
+
});
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
return paths;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function samePaths(a: readonly string[], b: readonly string[]): boolean {
|
|
208
|
+
return a.length === b.length && [...a].sort().join("\n") === [...b].sort().join("\n");
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function formatPaths(paths: readonly string[]): string {
|
|
212
|
+
return paths.length === 0 ? "(none: every path refused)" : paths.join(", ");
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function collectPath(value: string, previous: string[]): string[] {
|
|
216
|
+
return [...previous, value];
|
|
217
|
+
}
|
|
218
|
+
|
|
168
219
|
function gateScriptPath(): string {
|
|
169
220
|
return resolve(import.meta.dirname, "..", "lib", "tunnel", "gate.ts");
|
|
170
221
|
}
|
|
@@ -444,6 +495,7 @@ interface GateSpawnOpts {
|
|
|
444
495
|
vhost: string;
|
|
445
496
|
provider: TunnelProvider;
|
|
446
497
|
allowedIps: string[];
|
|
498
|
+
allowPaths: string[];
|
|
447
499
|
gateLogPath: string;
|
|
448
500
|
}
|
|
449
501
|
|
|
@@ -470,6 +522,7 @@ function spawnGate(o: GateSpawnOpts): ChildProcess {
|
|
|
470
522
|
HARNERY_TUNNEL_TARGET: o.target,
|
|
471
523
|
HARNERY_TUNNEL_VHOST: o.vhost,
|
|
472
524
|
HARNERY_TUNNEL_PORT: String(o.gatePort),
|
|
525
|
+
[ALLOW_PATHS_ENV]: o.allowPaths.join(","),
|
|
473
526
|
},
|
|
474
527
|
});
|
|
475
528
|
gateProc.unref();
|
|
@@ -498,6 +551,7 @@ async function up(opts: UpOpts): Promise<void> {
|
|
|
498
551
|
provider === "tailscale" ? resolveTailscalePath(opts.path, name) : undefined;
|
|
499
552
|
const tailscaleHttpsPort =
|
|
500
553
|
provider === "tailscale" ? resolveHttpsPort(opts.httpsPort) : undefined;
|
|
554
|
+
const allowPaths = resolveAllowPaths(opts.allowPath);
|
|
501
555
|
|
|
502
556
|
const existing = readState(name);
|
|
503
557
|
if (existing && tunnelIsAlive(existing)) {
|
|
@@ -508,9 +562,19 @@ async function up(opts: UpOpts): Promise<void> {
|
|
|
508
562
|
});
|
|
509
563
|
process.exit(1);
|
|
510
564
|
}
|
|
565
|
+
if (!samePaths(existing.allow_paths, allowPaths)) {
|
|
566
|
+
emit.error({
|
|
567
|
+
code: "tunnel_instance_in_use",
|
|
568
|
+
message:
|
|
569
|
+
`Tunnel [${name}] is already up sharing ${formatPaths(existing.allow_paths)}. ` +
|
|
570
|
+
`Stop it before starting it with ${formatPaths(allowPaths)}.`,
|
|
571
|
+
});
|
|
572
|
+
process.exit(1);
|
|
573
|
+
}
|
|
511
574
|
emit.text(`Already up [${name}]: ${existing.url}\n`);
|
|
512
575
|
emit.text(` Provider: ${existing.provider}\n`);
|
|
513
576
|
emit.text(` Forwarding: ${existing.target} (Host: ${existing.vhost})\n`);
|
|
577
|
+
emit.text(` Paths: ${formatPaths(existing.allow_paths)}\n`);
|
|
514
578
|
return;
|
|
515
579
|
}
|
|
516
580
|
if (existing) downOne(name, new Set());
|
|
@@ -552,6 +616,7 @@ async function up(opts: UpOpts): Promise<void> {
|
|
|
552
616
|
vhost,
|
|
553
617
|
provider,
|
|
554
618
|
allowedIps: cfg.allowed_ips,
|
|
619
|
+
allowPaths,
|
|
555
620
|
gateLogPath,
|
|
556
621
|
});
|
|
557
622
|
|
|
@@ -630,11 +695,13 @@ async function up(opts: UpOpts): Promise<void> {
|
|
|
630
695
|
target,
|
|
631
696
|
vhost,
|
|
632
697
|
gate_port: gatePort,
|
|
698
|
+
allow_paths: allowPaths,
|
|
633
699
|
tailscale_mode: tailscaleMode,
|
|
634
700
|
tailscale_path: tailscalePath,
|
|
635
701
|
tailscale_https_port: tailscaleHttpsPort,
|
|
636
702
|
};
|
|
637
703
|
writeState(state);
|
|
704
|
+
recordTunnelServer(state);
|
|
638
705
|
|
|
639
706
|
const stopHint =
|
|
640
707
|
name === DEFAULT_INSTANCE ? "harn tunnel down" : `harn tunnel down --name ${name}`;
|
|
@@ -642,6 +709,7 @@ async function up(opts: UpOpts): Promise<void> {
|
|
|
642
709
|
emit.text(` Provider: ${provider}${tailscaleMode ? ` (${tailscaleMode})` : ""}\n`);
|
|
643
710
|
emit.text(` URL: ${url}\n\n`);
|
|
644
711
|
emit.text(` Forwarding: ${target} (Host: ${vhost})\n`);
|
|
712
|
+
emit.text(` Paths: ${formatPaths(allowPaths)}\n`);
|
|
645
713
|
emit.text(` Gate port: ${gatePort}\n`);
|
|
646
714
|
if (provider === "cloudflare") {
|
|
647
715
|
emit.text(` Allowed IPs: ${cfg.allowed_ips.join(", ")}\n\n`);
|
|
@@ -662,6 +730,16 @@ async function up(opts: UpOpts): Promise<void> {
|
|
|
662
730
|
emit.text(" Status: harn tunnel status\n");
|
|
663
731
|
}
|
|
664
732
|
|
|
733
|
+
/** The server registry lists tunnels beside every other local server. */
|
|
734
|
+
function registryRoot(): string {
|
|
735
|
+
return resolveCoordRoot() ?? process.cwd();
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
function recordTunnelServer(state: TunnelState): void {
|
|
739
|
+
const coordRoot = registryRoot();
|
|
740
|
+
tryRegisterServer(tunnelServerInput(state, coordRoot), { coordRoot });
|
|
741
|
+
}
|
|
742
|
+
|
|
665
743
|
/** Tear down a single instance by name. Returns the number of processes killed. */
|
|
666
744
|
function downOne(name: string, killed: Set<number>): number {
|
|
667
745
|
const before = killed.size;
|
|
@@ -684,6 +762,7 @@ function downOne(name: string, killed: Set<number>): number {
|
|
|
684
762
|
// lost; they'd otherwise squat on the port and break the next `up`.
|
|
685
763
|
sweepStrays(state?.gate_port ?? DEFAULT_GATE_PORT, killed);
|
|
686
764
|
clearState(name);
|
|
765
|
+
unregisterServer(tunnelServerId(name), { coordRoot: registryRoot() });
|
|
687
766
|
return killed.size - before;
|
|
688
767
|
}
|
|
689
768
|
|
|
@@ -771,6 +850,15 @@ export async function reloadOne(state: TunnelState): Promise<{ ok: boolean; mess
|
|
|
771
850
|
if (!bunAvailable()) {
|
|
772
851
|
return { ok: false, message: `[${name}] bun is not on PATH, so the gate can't be respawned.` };
|
|
773
852
|
}
|
|
853
|
+
if (state.allow_paths.length === 0) {
|
|
854
|
+
return {
|
|
855
|
+
ok: false,
|
|
856
|
+
message:
|
|
857
|
+
`[${name}] has no recorded path scope, so a reloaded gate would refuse every request. ` +
|
|
858
|
+
`Restart it with \`${bin} tunnel down --name ${name}\` and ` +
|
|
859
|
+
`\`${bin} tunnel up --name ${name} --allow-path <prefix>\`.`,
|
|
860
|
+
};
|
|
861
|
+
}
|
|
774
862
|
|
|
775
863
|
// Kill ONLY the gate. sweepStrays() is deliberately avoided here: it also
|
|
776
864
|
// matches `--url http://localhost:<port>`, which is the provider process we
|
|
@@ -803,6 +891,7 @@ export async function reloadOne(state: TunnelState): Promise<{ ok: boolean; mess
|
|
|
803
891
|
vhost: state.vhost,
|
|
804
892
|
provider: state.provider,
|
|
805
893
|
allowedIps: cfg.allowed_ips,
|
|
894
|
+
allowPaths: state.allow_paths,
|
|
806
895
|
gateLogPath: tunnelLogDestinations(name, state.provider).gate,
|
|
807
896
|
});
|
|
808
897
|
|
|
@@ -822,6 +911,7 @@ export async function reloadOne(state: TunnelState): Promise<{ ok: boolean; mess
|
|
|
822
911
|
}
|
|
823
912
|
|
|
824
913
|
writeState({ ...state, gate_pid: pid });
|
|
914
|
+
recordTunnelServer({ ...state, gate_pid: pid });
|
|
825
915
|
const allowNote =
|
|
826
916
|
state.provider === "cloudflare" ? ` Allowlist: ${cfg.allowed_ips.length} IP(s).` : "";
|
|
827
917
|
return { ok: true, message: `[${name}] gate reloaded, URL unchanged: ${state.url}.${allowNote}` };
|
|
@@ -898,6 +988,7 @@ function statusDetail(state: TunnelState): void {
|
|
|
898
988
|
);
|
|
899
989
|
emit.text(` URL: ${state.url}\n`);
|
|
900
990
|
emit.text(` Forwarding: ${state.target} (Host: ${state.vhost})\n`);
|
|
991
|
+
emit.text(` Paths: ${formatPaths(state.allow_paths)}\n`);
|
|
901
992
|
emit.text(` Gate port: ${state.gate_port}\n`);
|
|
902
993
|
if (state.provider === "cloudflare") {
|
|
903
994
|
emit.text(` Allowed IPs: ${cfg.allowed_ips.join(", ")}\n`);
|
|
@@ -941,6 +1032,7 @@ function status(opts: StatusOpts): void {
|
|
|
941
1032
|
state: instanceState(s),
|
|
942
1033
|
url: s.url,
|
|
943
1034
|
fwd: `${s.target} (${s.vhost})`,
|
|
1035
|
+
paths: formatPaths(s.allow_paths),
|
|
944
1036
|
port: String(s.gate_port),
|
|
945
1037
|
up: fmtUptime(s.started_at),
|
|
946
1038
|
}));
|
|
@@ -950,15 +1042,16 @@ function status(opts: StatusOpts): void {
|
|
|
950
1042
|
state: 5,
|
|
951
1043
|
url: Math.max(3, ...rows.map((r) => r.url.length)),
|
|
952
1044
|
fwd: Math.max(10, ...rows.map((r) => r.fwd.length)),
|
|
1045
|
+
paths: Math.max(5, ...rows.map((r) => r.paths.length)),
|
|
953
1046
|
port: 4,
|
|
954
1047
|
};
|
|
955
1048
|
const pad = (s: string, n: number) => s.padEnd(n);
|
|
956
1049
|
emit.text(
|
|
957
|
-
`${pad("NAME", w.name)} ${pad("PROVIDER", w.provider)} ${pad("STATE", w.state)} ${pad("URL", w.url)} ${pad("FORWARDING", w.fwd)} ${pad("PORT", w.port)} UPTIME\n`,
|
|
1050
|
+
`${pad("NAME", w.name)} ${pad("PROVIDER", w.provider)} ${pad("STATE", w.state)} ${pad("URL", w.url)} ${pad("FORWARDING", w.fwd)} ${pad("PATHS", w.paths)} ${pad("PORT", w.port)} UPTIME\n`,
|
|
958
1051
|
);
|
|
959
1052
|
for (const r of rows) {
|
|
960
1053
|
emit.text(
|
|
961
|
-
`${pad(r.name, w.name)} ${pad(r.provider, w.provider)} ${pad(r.state, w.state)} ${pad(r.url, w.url)} ${pad(r.fwd, w.fwd)} ${pad(r.port, w.port)} ${r.up}\n`,
|
|
1054
|
+
`${pad(r.name, w.name)} ${pad(r.provider, w.provider)} ${pad(r.state, w.state)} ${pad(r.url, w.url)} ${pad(r.fwd, w.fwd)} ${pad(r.paths, w.paths)} ${pad(r.port, w.port)} ${r.up}\n`,
|
|
962
1055
|
);
|
|
963
1056
|
}
|
|
964
1057
|
}
|
|
@@ -1071,6 +1164,13 @@ export function registerTunnelCommand(
|
|
|
1071
1164
|
"Tailscale only: URL path mount (default: / for default, /<name> for named instances)",
|
|
1072
1165
|
)
|
|
1073
1166
|
.option("--https-port <port>", "Tailscale only: HTTPS listen port (default: 443)", "443")
|
|
1167
|
+
.option(
|
|
1168
|
+
"--allow-path <prefix>",
|
|
1169
|
+
"URL path prefix the tunnel shares (repeatable, required). Every other path is refused; " +
|
|
1170
|
+
"pass / to publish the whole upstream.",
|
|
1171
|
+
collectPath,
|
|
1172
|
+
[],
|
|
1173
|
+
)
|
|
1074
1174
|
.action(up);
|
|
1075
1175
|
|
|
1076
1176
|
cmd
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import type { Command } from "commander";
|
|
3
|
+
import type { EmitContext } from "../commander.ts";
|
|
4
|
+
import { commandPaceGate } from "../lib/pace/index.ts";
|
|
5
|
+
import {
|
|
6
|
+
parseWebViewTypeStep,
|
|
7
|
+
parseWebViewViewport,
|
|
8
|
+
runWebView,
|
|
9
|
+
type WebViewBackend,
|
|
10
|
+
WebViewUnavailableError,
|
|
11
|
+
} from "../lib/webview/index.ts";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* `harn webview`: a lightweight headless page probe through Bun.WebView.
|
|
15
|
+
*
|
|
16
|
+
* Experimental and Bun-only (Bun 1.4+). It always launches a fresh browser with
|
|
17
|
+
* ephemeral storage unless `--profile` is given, and never attaches to a
|
|
18
|
+
* running user browser. Use `browse` for headed login, the shared cookie jar,
|
|
19
|
+
* HAR capture, full-page screenshots, and page QA; use `browse-ai` for
|
|
20
|
+
* accessibility-tree element references. On Node the command fails with a
|
|
21
|
+
* clear message, matching how `tunnel` handles its Bun-only worker.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
interface WebviewOpts {
|
|
25
|
+
userAgent?: string;
|
|
26
|
+
backend: string;
|
|
27
|
+
viewport: string;
|
|
28
|
+
profile?: string;
|
|
29
|
+
chromePath?: string;
|
|
30
|
+
browserArg: string[];
|
|
31
|
+
timeout: string;
|
|
32
|
+
waitFor?: string;
|
|
33
|
+
type: string[];
|
|
34
|
+
click: string[];
|
|
35
|
+
press: string[];
|
|
36
|
+
evaluate?: string;
|
|
37
|
+
settle: string;
|
|
38
|
+
screenshot?: string;
|
|
39
|
+
html?: boolean;
|
|
40
|
+
json?: boolean;
|
|
41
|
+
pace?: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function registerWebviewCommand(program: Command, emit: EmitContext, binName: string): void {
|
|
45
|
+
program
|
|
46
|
+
.command("webview <url>")
|
|
47
|
+
.description(
|
|
48
|
+
"Lightweight headless page probe through Bun.WebView (experimental, Bun 1.4+). " +
|
|
49
|
+
`Fresh ephemeral browser per call; use ${binName} browse for login, cookies, HAR, and QA.`,
|
|
50
|
+
)
|
|
51
|
+
.option("--backend <engine>", "Browser engine: auto | chrome | webkit", "auto")
|
|
52
|
+
.option(
|
|
53
|
+
"--user-agent <ua>",
|
|
54
|
+
"Chrome user agent: shared store by default; auto refreshes, native disables",
|
|
55
|
+
)
|
|
56
|
+
.option("--viewport <WxH>", "Viewport in CSS pixels", "1280x800")
|
|
57
|
+
.option(
|
|
58
|
+
"--profile <dir>",
|
|
59
|
+
"Persist cookies and local storage in this directory (default is ephemeral)",
|
|
60
|
+
)
|
|
61
|
+
.option("--chrome-path <path>", "Chrome-family executable; implies the Chrome backend")
|
|
62
|
+
.option("--browser-arg <flag>", "Extra Chrome launch flag (repeatable)", collect, [])
|
|
63
|
+
.option("--timeout <ms>", "Navigation and selector timeout in milliseconds", "30000")
|
|
64
|
+
.option("--wait-for <css>", "Wait for a CSS selector after navigation")
|
|
65
|
+
.option(
|
|
66
|
+
"--type <css=>text>",
|
|
67
|
+
"Focus a selector and insert text (repeatable; runs before clicks)",
|
|
68
|
+
collect,
|
|
69
|
+
[],
|
|
70
|
+
)
|
|
71
|
+
.option("--click <css>", "Scroll to and click a CSS selector (repeatable)", collect, [])
|
|
72
|
+
.option(
|
|
73
|
+
"--press <key>",
|
|
74
|
+
"Press a key in the currently focused element (repeatable)",
|
|
75
|
+
collect,
|
|
76
|
+
[],
|
|
77
|
+
)
|
|
78
|
+
.option("--evaluate <expression>", "Evaluate a JavaScript expression after actions")
|
|
79
|
+
.option("--settle <ms>", "Extra delay after actions before capture", "0")
|
|
80
|
+
.option(
|
|
81
|
+
"--screenshot <path>",
|
|
82
|
+
"Save a viewport PNG (Bun.WebView does not provide full-page capture)",
|
|
83
|
+
)
|
|
84
|
+
.option("--html", "Print the final document HTML instead of body text")
|
|
85
|
+
.option("--json", "Print the full result envelope")
|
|
86
|
+
.option(
|
|
87
|
+
"--no-pace",
|
|
88
|
+
"Skip the human-pace gap (3 to 9 s) between page loads of the same site for this run. " +
|
|
89
|
+
"HARNERY_PACE=off disables it machine-wide; local and private hosts never wait.",
|
|
90
|
+
)
|
|
91
|
+
.action(async (url: string, opts: WebviewOpts) => {
|
|
92
|
+
try {
|
|
93
|
+
await runWebview(url, opts, emit);
|
|
94
|
+
} catch (err: unknown) {
|
|
95
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
96
|
+
emit.error({
|
|
97
|
+
code: err instanceof WebViewUnavailableError ? err.code : "webview_error",
|
|
98
|
+
message,
|
|
99
|
+
});
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function runWebview(url: string, opts: WebviewOpts, emit: EmitContext): Promise<void> {
|
|
106
|
+
if (!isBackend(opts.backend)) {
|
|
107
|
+
throw new Error(`Invalid backend "${opts.backend}". Expected auto, chrome, or webkit.`);
|
|
108
|
+
}
|
|
109
|
+
const backend = opts.backend === "auto" && opts.chromePath ? "chrome" : opts.backend;
|
|
110
|
+
const result = await runWebView(url, {
|
|
111
|
+
backend,
|
|
112
|
+
viewport: parseWebViewViewport(opts.viewport),
|
|
113
|
+
profileDir: opts.profile ? resolve(opts.profile) : undefined,
|
|
114
|
+
chromePath: opts.chromePath ? resolve(opts.chromePath) : undefined,
|
|
115
|
+
browserArgs: opts.browserArg,
|
|
116
|
+
timeoutMs: parseNonNegativeInteger(opts.timeout, "--timeout", false),
|
|
117
|
+
waitFor: opts.waitFor,
|
|
118
|
+
typeSteps: opts.type.map(parseWebViewTypeStep),
|
|
119
|
+
clicks: opts.click,
|
|
120
|
+
presses: opts.press,
|
|
121
|
+
evaluate: opts.evaluate,
|
|
122
|
+
settleMs: parseNonNegativeInteger(opts.settle, "--settle", true),
|
|
123
|
+
screenshotPath: opts.screenshot ? resolve(opts.screenshot) : undefined,
|
|
124
|
+
captureHtml: opts.html === true,
|
|
125
|
+
pace: commandPaceGate(opts.pace !== false, (message) => emit.log(message, "info")),
|
|
126
|
+
userAgent: opts.userAgent,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
if (opts.json) {
|
|
130
|
+
emit.data(result);
|
|
131
|
+
} else if (opts.html) {
|
|
132
|
+
emit.text(result.html?.endsWith("\n") ? result.html : `${result.html ?? ""}\n`);
|
|
133
|
+
} else if (opts.evaluate !== undefined) {
|
|
134
|
+
const value =
|
|
135
|
+
typeof result.evaluation === "string"
|
|
136
|
+
? result.evaluation
|
|
137
|
+
: JSON.stringify(result.evaluation, null, 2);
|
|
138
|
+
emit.text(`${value ?? "undefined"}\n`);
|
|
139
|
+
} else {
|
|
140
|
+
emit.text(result.text.endsWith("\n") ? result.text : `${result.text}\n`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function collect(value: string, previous: string[]): string[] {
|
|
145
|
+
return [...previous, value];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function isBackend(value: string): value is WebViewBackend {
|
|
149
|
+
return value === "auto" || value === "chrome" || value === "webkit";
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function parseNonNegativeInteger(value: string, flag: string, allowZero: boolean): number {
|
|
153
|
+
if (!/^\d+$/.test(value)) throw new Error(`${flag} expects an integer, got "${value}".`);
|
|
154
|
+
const parsed = Number.parseInt(value, 10);
|
|
155
|
+
if ((!allowZero && parsed < 1) || (allowZero && parsed < 0)) {
|
|
156
|
+
throw new Error(`${flag} must be ${allowZero ? "zero or greater" : "greater than zero"}.`);
|
|
157
|
+
}
|
|
158
|
+
return parsed;
|
|
159
|
+
}
|
package/src/core/adapter.ts
CHANGED
|
@@ -1,5 +1,106 @@
|
|
|
1
1
|
/** First-party harness adapters supported by Harnery's canonical V3 ledger. */
|
|
2
|
-
export type Adapter = "claude-code" | "cursor" | "codex";
|
|
2
|
+
export type Adapter = "claude-code" | "cursor" | "codex" | "opencode";
|
|
3
3
|
|
|
4
4
|
/** Canonical producer classes used by V3 provenance. */
|
|
5
5
|
export type EventSource = "agent-hooks" | "agent-coord" | "user" | "system";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Runtime census of the workflow adapters. Adding a member to `Adapter`
|
|
9
|
+
* without listing it here is a compile error (see `adaptersComplete`), so a
|
|
10
|
+
* new adapter can never slip past the shared normalizer.
|
|
11
|
+
*/
|
|
12
|
+
export const ADAPTERS = [
|
|
13
|
+
"claude-code",
|
|
14
|
+
"cursor",
|
|
15
|
+
"codex",
|
|
16
|
+
"opencode",
|
|
17
|
+
] as const satisfies readonly Adapter[];
|
|
18
|
+
|
|
19
|
+
type MissingAdapter = Exclude<Adapter, (typeof ADAPTERS)[number]>;
|
|
20
|
+
const adaptersComplete: [MissingAdapter] extends [never] ? true : never = true;
|
|
21
|
+
void adaptersComplete;
|
|
22
|
+
|
|
23
|
+
/** Every adapter falls back to this identity when a platform value carries no usable evidence. */
|
|
24
|
+
export const DEFAULT_ADAPTER: Adapter = "claude-code";
|
|
25
|
+
|
|
26
|
+
/** Why a platform value could not be normalized to a known adapter. */
|
|
27
|
+
export type AdapterFallbackReason = "missing" | "unknown";
|
|
28
|
+
|
|
29
|
+
export interface AdapterFallback {
|
|
30
|
+
/** The raw value that was normalized. */
|
|
31
|
+
value: unknown;
|
|
32
|
+
/** `missing` for null, undefined, or an empty string; `unknown` for anything else. */
|
|
33
|
+
reason: AdapterFallbackReason;
|
|
34
|
+
/** The adapter that was substituted. */
|
|
35
|
+
fallback: string;
|
|
36
|
+
/** Caller-supplied label naming the code path, for the diagnostic line. */
|
|
37
|
+
context?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface AdapterFallbackOptions {
|
|
41
|
+
/** Names the caller in the diagnostic line, e.g. `"claim-conflict"`. */
|
|
42
|
+
context?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Receives every fallback. The default writes one stderr line per unknown
|
|
45
|
+
* value; a missing value is a pre-heartbeat state rather than a
|
|
46
|
+
* misattribution, so it is passed here but not printed.
|
|
47
|
+
*/
|
|
48
|
+
onFallback?: (fallback: AdapterFallback) => void;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Generic membership normalizer shared by every adapter census. Returns the
|
|
53
|
+
* matching id or `null`; it never substitutes a default.
|
|
54
|
+
*/
|
|
55
|
+
export function normalizeAdapterId<T extends string>(
|
|
56
|
+
value: unknown,
|
|
57
|
+
census: readonly T[],
|
|
58
|
+
): T | null {
|
|
59
|
+
if (typeof value !== "string") return null;
|
|
60
|
+
return (census as readonly string[]).includes(value) ? (value as T) : null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Normalize with an explicit, reported fallback. Every caller that must end up
|
|
65
|
+
* with *some* adapter routes through here so the substitution is visible.
|
|
66
|
+
*/
|
|
67
|
+
export function resolveAdapterId<T extends string>(
|
|
68
|
+
value: unknown,
|
|
69
|
+
census: readonly T[],
|
|
70
|
+
fallback: T,
|
|
71
|
+
options: AdapterFallbackOptions = {},
|
|
72
|
+
): T {
|
|
73
|
+
const normalized = normalizeAdapterId(value, census);
|
|
74
|
+
if (normalized !== null) return normalized;
|
|
75
|
+
const reason: AdapterFallbackReason =
|
|
76
|
+
value === undefined || value === null || value === "" ? "missing" : "unknown";
|
|
77
|
+
(options.onFallback ?? reportAdapterFallback)({
|
|
78
|
+
value,
|
|
79
|
+
reason,
|
|
80
|
+
fallback,
|
|
81
|
+
context: options.context,
|
|
82
|
+
});
|
|
83
|
+
return fallback;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Default fallback sink: one stderr line for an unrecognized platform value. */
|
|
87
|
+
export function reportAdapterFallback(fallback: AdapterFallback): void {
|
|
88
|
+
if (fallback.reason !== "unknown") return;
|
|
89
|
+
const where = fallback.context ? ` (${fallback.context})` : "";
|
|
90
|
+
process.stderr.write(
|
|
91
|
+
`harnery: unknown adapter platform ${JSON.stringify(fallback.value)}${where}; treating it as ${fallback.fallback}\n`,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Strict workflow-adapter normalizer: a known id or `null`. */
|
|
96
|
+
export function normalizeAdapter(value: unknown): Adapter | null {
|
|
97
|
+
return normalizeAdapterId(value, ADAPTERS);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Heartbeat `platform` (or any adapter-shaped string) to a workflow adapter,
|
|
102
|
+
* substituting `DEFAULT_ADAPTER` and reporting the substitution.
|
|
103
|
+
*/
|
|
104
|
+
export function adapterFromPlatform(value: unknown, options?: AdapterFallbackOptions): Adapter {
|
|
105
|
+
return resolveAdapterId(value, ADAPTERS, DEFAULT_ADAPTER, options);
|
|
106
|
+
}
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
} from "node:fs";
|
|
23
23
|
import { resolve } from "node:path";
|
|
24
24
|
import { monorepoRoot } from "../agents/coord-client.ts";
|
|
25
|
+
import { stateDirMode, stateFileMode } from "../storage/modes.ts";
|
|
25
26
|
import { stableDigest } from "../workflow/durable-record.ts";
|
|
26
27
|
import type { AdapterId, AdapterProfile, CapabilitySupport } from "./types.ts";
|
|
27
28
|
|
|
@@ -107,12 +108,12 @@ export function writeAttestation(
|
|
|
107
108
|
opts: AttestationStoreOptions = {},
|
|
108
109
|
): string {
|
|
109
110
|
const path = attestationPath(record.adapter, opts);
|
|
110
|
-
mkdirSync(attestationsDir(opts), { recursive: true, mode:
|
|
111
|
+
mkdirSync(attestationsDir(opts), { recursive: true, mode: stateDirMode() });
|
|
111
112
|
const temporary = `${path}.tmp-${process.pid}`;
|
|
112
113
|
try {
|
|
113
114
|
writeFileSync(temporary, `${JSON.stringify(record, null, 2)}\n`, {
|
|
114
115
|
encoding: "utf8",
|
|
115
|
-
mode:
|
|
116
|
+
mode: stateFileMode(),
|
|
116
117
|
});
|
|
117
118
|
renameSync(temporary, path);
|
|
118
119
|
} catch (error) {
|
|
@@ -45,6 +45,18 @@ export const BUILTIN_ADAPTER_PROFILES = {
|
|
|
45
45
|
modelFamily: "claude",
|
|
46
46
|
effortValues: ["low", "medium", "high", "xhigh", "max"],
|
|
47
47
|
verified: { date: "2026-08-18", version: "2.1.233 (Claude Code)" },
|
|
48
|
+
// Checked against 2.1.283 (ADR 0192). Claude Code has no sandbox mode flag;
|
|
49
|
+
// its permission mode and its optional Bash sandbox are separate, so full
|
|
50
|
+
// access needs both: bypass permissions, and a settings layer that turns
|
|
51
|
+
// the Bash sandbox off in case a user or project settings file enabled it.
|
|
52
|
+
fullAccess: {
|
|
53
|
+
argv: [
|
|
54
|
+
"--permission-mode",
|
|
55
|
+
"bypassPermissions",
|
|
56
|
+
"--settings",
|
|
57
|
+
'{"sandbox":{"enabled":false}}',
|
|
58
|
+
],
|
|
59
|
+
},
|
|
48
60
|
capabilities: capabilities({
|
|
49
61
|
effortSelection: supported("Mapped to `--effort <level>`."),
|
|
50
62
|
maxTurns: supported("Mapped to `--max-turns <n>`."),
|
|
@@ -78,6 +90,9 @@ export const BUILTIN_ADAPTER_PROFILES = {
|
|
|
78
90
|
modes: { "read-only": "read-only", "workspace-write": "workspace-write" },
|
|
79
91
|
writableRoots: true,
|
|
80
92
|
},
|
|
93
|
+
// Checked against codex-cli 0.155.1 (ADR 0192): `--sandbox` accepts
|
|
94
|
+
// danger-full-access, and `codex exec` never prompts for approval.
|
|
95
|
+
fullAccess: { argv: ["--sandbox", "danger-full-access"] },
|
|
81
96
|
capabilities: capabilities({
|
|
82
97
|
effortSelection: supported('Mapped to `-c model_reasoning_effort="<level>"`.'),
|
|
83
98
|
filesystemPolicyProjection: supported(
|
|
@@ -106,7 +121,11 @@ export const BUILTIN_ADAPTER_PROFILES = {
|
|
|
106
121
|
authModel: "own-auth",
|
|
107
122
|
modelFamily: "multi",
|
|
108
123
|
effortValues: [],
|
|
109
|
-
verified: { date: "2026-
|
|
124
|
+
verified: { date: "2026-09-20", version: "2026.09.18-9a7762b" },
|
|
125
|
+
// Checked against 2026.09.26-dd393fe (ADR 0192): `--sandbox disabled`
|
|
126
|
+
// overrides the configured sandbox. Cursor carries effort inside the model
|
|
127
|
+
// id, so a full-access floor for it names exact model ids.
|
|
128
|
+
fullAccess: { argv: ["--sandbox", "disabled"] },
|
|
110
129
|
capabilities: capabilities({
|
|
111
130
|
effortSelection: unsupported(
|
|
112
131
|
"Cursor embeds effort in some parameterized model ids; Harnery does not rewrite model ids.",
|
|
@@ -114,6 +133,10 @@ export const BUILTIN_ADAPTER_PROFILES = {
|
|
|
114
133
|
maxTurns: unsupported("cursor-agent exposes no turn-ceiling flag."),
|
|
115
134
|
sessionId: supported("Read from the JSON result envelope."),
|
|
116
135
|
cost: unsupported("The JSON result envelope carries no cost."),
|
|
136
|
+
// Still unknown on 2026-09-20 against cursor-agent 2026.09.18: the live
|
|
137
|
+
// `cursor_composer_context_percent` reader serves IDE hook sessions from
|
|
138
|
+
// the composer `state.vscdb`, and headless `cursor-agent` children (this
|
|
139
|
+
// workflow adapter) leave no composer row and no usage in the JSON result.
|
|
117
140
|
contextTelemetry: unknown("No stable Cursor context-usage payload has been certified."),
|
|
118
141
|
preCompactionSignal: supported("Cursor preCompact is wired to a durable checkpoint."),
|
|
119
142
|
postCompactionSignal: unsupported(
|
|
@@ -121,6 +144,45 @@ export const BUILTIN_ADAPTER_PROFILES = {
|
|
|
121
144
|
),
|
|
122
145
|
}),
|
|
123
146
|
},
|
|
147
|
+
opencode: {
|
|
148
|
+
id: "opencode",
|
|
149
|
+
displayName: "OpenCode",
|
|
150
|
+
binary: "opencode",
|
|
151
|
+
installHint: "curl -fsSL https://opencode.ai/install | bash",
|
|
152
|
+
loginHint: "opencode auth login",
|
|
153
|
+
apiKeyEnv: "OPENCODE_API_KEY",
|
|
154
|
+
integrationMode: "cli-subprocess",
|
|
155
|
+
authModel: "own-auth",
|
|
156
|
+
modelFamily: "multi",
|
|
157
|
+
// Model reasoning is selected through the `provider/model#variant` id;
|
|
158
|
+
// OpenCode exposes no separate effort dial for Harnery to map. It also has
|
|
159
|
+
// no vendor sandbox to remove, so it declares no full-access rendering and
|
|
160
|
+
// a worker on it is never granted one (ADR 0192).
|
|
161
|
+
effortValues: [],
|
|
162
|
+
verified: { date: "2026-09-20", version: "opencode v2.0.11" },
|
|
163
|
+
capabilities: capabilities({
|
|
164
|
+
effortSelection: unsupported(
|
|
165
|
+
"OpenCode selects reasoning through the model id variant; there is no separate effort flag.",
|
|
166
|
+
),
|
|
167
|
+
maxTurns: unsupported("`opencode run` exposes no turn-ceiling flag."),
|
|
168
|
+
sessionId: supported("Read from the `sessionID` on every `--format json` NDJSON line."),
|
|
169
|
+
cost: unsupported(
|
|
170
|
+
"`opencode run --format json` streams parts without a final cost; cost lives in `session export`.",
|
|
171
|
+
),
|
|
172
|
+
// Tool evidence is delivered on the event axis by the Harnery OpenCode
|
|
173
|
+
// plugin, not by the final-result workflow spawn, which retains no tool
|
|
174
|
+
// events (as with Codex and Cursor).
|
|
175
|
+
contextTelemetry: unknown(
|
|
176
|
+
"OpenCode stores context in SQLite; no context-window bridge is certified yet.",
|
|
177
|
+
),
|
|
178
|
+
preCompactionSignal: supported(
|
|
179
|
+
'OpenCode session.hook("compaction") is bridged to a durable checkpoint.',
|
|
180
|
+
),
|
|
181
|
+
postCompactionSignal: unsupported(
|
|
182
|
+
"No post-compact hook is wired; OpenCode post-compaction recovery is not yet certified.",
|
|
183
|
+
),
|
|
184
|
+
}),
|
|
185
|
+
},
|
|
124
186
|
} as const satisfies Record<string, AdapterProfile>;
|
|
125
187
|
|
|
126
188
|
export type BuiltinAdapterId = keyof typeof BUILTIN_ADAPTER_PROFILES;
|