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/dist/commands/browse.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
1
2
|
import { existsSync, mkdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
3
|
import { homedir } from "node:os";
|
|
3
4
|
import { dirname, isAbsolute, resolve } from "node:path";
|
|
5
|
+
import { chromium } from "playwright";
|
|
4
6
|
import { PNG } from "pngjs";
|
|
5
7
|
import { resolveBinName } from "../core/config.js";
|
|
8
|
+
import { splitBatchSteps } from "../lib/browser/batch-steps.js";
|
|
6
9
|
import { CAPTURE_FIDELITY_MISMATCH_THRESHOLD, compareBand, cropNativePng, decideFidelity, pngDimensions, } from "../lib/browser/capture-fidelity.js";
|
|
7
|
-
import {
|
|
10
|
+
import { createPageDriver, createRng, DEFAULT_COLLECT_LIMITS, PACING_LIMITS, parseProbability, parseRange, presetNames, randomSeed, resolveCollectSpec, runCollect, scrollPacingFromEnv, } from "../lib/browser/collect/index.js";
|
|
11
|
+
import { Browser, browserProxyFromEnv, browserProxyGateFromEnv, captureDevOverlay, chromeMajorFromExecutable, DEFAULT_CRITIQUE_RUBRIC, extractObservedIp, installedChromeChannel, installedChromePath, parseAssertSpec, resolveUserAgent, runCritique, tilesFromFullPage, WEBRTC_PROXY_ONLY_ARG, writeNetscapeCookieFile, wslHeadedLaunchArgs, } from "../lib/browser/index.js";
|
|
12
|
+
import { isWSL } from "../lib/browser/launch-args.js";
|
|
8
13
|
import { allocateTileBudget, validatePageReviewAllocation, } from "../lib/browser/page-review-budget.js";
|
|
9
14
|
import { PAGE_REVIEW_CAPTURE_PLAN_SCHEMA, } from "../lib/browser/page-review-contracts.js";
|
|
10
15
|
import { findPackTile, gateHitsFromEnvelope, readPackContext, tileId, writePackContext, writePackExpandedTile, } from "../lib/browser/page-review-pack.js";
|
|
@@ -17,7 +22,9 @@ import { startBrowserSessionServer, } from "../lib/browser/session-control.js";
|
|
|
17
22
|
import { captureThumbnailFingerprint, registerCaptureThumbnail, } from "../lib/browser/thumbnail-association.js";
|
|
18
23
|
import { reviewCandidateRects } from "../lib/browser/tiling.js";
|
|
19
24
|
import { diffAgainstBaseline, saveBaseline, } from "../lib/browser/visual-diff.js";
|
|
20
|
-
import {
|
|
25
|
+
import { harvestDomain, harvestWindowsChromeCookies, stopWindowsChromeProfile, windowsChromePath, windowsLocalAppData, windowsPlainProfile, wslPathToWindows, } from "../lib/browser/windows-chrome.js";
|
|
26
|
+
import { applyExtraCookies, CookieJar, mergeCookies } from "../lib/cookies/index.js";
|
|
27
|
+
import { commandPaceGate } from "../lib/pace/index.js";
|
|
21
28
|
/**
|
|
22
29
|
* `harn browse <url>`: Playwright-backed page navigation with shared
|
|
23
30
|
* cookie jar + persistent profile + diagnostics capture for LLM
|
|
@@ -70,26 +77,66 @@ export function registerBrowseCommand(program, emitParam, context, binName = res
|
|
|
70
77
|
.option("--capture-evaluate <js>", "In trio mode, evaluate JS inside the exact screenshot viewport immediately before capture; result is written as captureEval")
|
|
71
78
|
.option("--batch <steps>", "Run multiple steps in one session, semicolon-separated. Each step is one of: " +
|
|
72
79
|
"`click <selector>`, `fill <selector=>value>`, `press <key>`, `wait <selector|ms>`, `eval <js>`, `reload`. " +
|
|
73
|
-
'Example: `--batch "click button; wait 1500; reload; wait 3000"`. `reload` preserves sessionStorage + cookies, which is how to repro sessionStorage-restored UI state.'
|
|
80
|
+
'Example: `--batch "click button; wait 1500; reload; wait 3000"`. `reload` preserves sessionStorage + cookies, which is how to repro sessionStorage-restored UI state. ' +
|
|
81
|
+
"An `eval` step keeps semicolons inside JS quotes and (), [], {}; `\\;` is always a literal semicolon.")
|
|
82
|
+
.option("--collect [preset]", "Scroll an infinite feed like a reader and collect every item that passes through the DOM, " +
|
|
83
|
+
`de-duplicated, as JSON. Presets: ${presetNames().join(", ")} (default generic). ` +
|
|
84
|
+
"Skips the trio, checks and --evaluate; runs after --wait-for and --batch.")
|
|
85
|
+
.option("--collect-item <css>", "Item selector (overrides the preset's).")
|
|
86
|
+
.option("--collect-key <extractor>", "Dedupe key extractor, <selector>[@attr] inside the item. Default: the preset key, else the " +
|
|
87
|
+
"first permalink-like link, else a hash of the item text.")
|
|
88
|
+
.option("--collect-key-pattern <regex>", "Regex a link must match to count as a permalink key.")
|
|
89
|
+
.option("--collect-field <name=extractor>", "Add or override a field: name=<selector>[@attr]. name[]= collects every match. Empty selector " +
|
|
90
|
+
"or :scope is the item itself; no @attr reads visible text (repeatable).", (value, previous = []) => [...previous, value], [])
|
|
91
|
+
.option("--collect-expand [selector]", "Click 'show more' buttons inside visible items before harvesting (preset selector by default). " +
|
|
92
|
+
"At most 3 per step and 50 per run; links and action buttons are never clicked.")
|
|
93
|
+
.option("--collect-max-items <n>", "Stop after this many unique items.")
|
|
94
|
+
.option("--collect-max-scrolls <n>", "Stop after this many scroll steps (default 60).", "60")
|
|
95
|
+
.option("--collect-max-seconds <n>", "Stop after this much wall time (default 300).", "300")
|
|
96
|
+
.option("--collect-idle <n>", "Stop after this many steps with no new items and no page growth (default 5).", "5")
|
|
97
|
+
.option("--collect-step <min-max>", "Scroll distance per step as a viewport fraction (default 0.6-1.1; env HARNERY_COLLECT_STEP).")
|
|
98
|
+
.option("--collect-pause <min-max>", "Pause after each step in ms (default 1200-3500; env HARNERY_COLLECT_PAUSE_MS).")
|
|
99
|
+
.option("--collect-read-chance <p>", "Chance of a longer reading pause per step (default 0.12).")
|
|
100
|
+
.option("--collect-read-pause <min-max>", "Reading pause in ms (default 4000-9000).")
|
|
101
|
+
.option("--collect-back-chance <p>", "Chance a step starts with a small scroll back up (default 0.08).")
|
|
102
|
+
.option("--collect-seed <n>", "Seed for the scroll schedule; the envelope reports the seed used.")
|
|
103
|
+
.option("--collect-format <format>", "json (envelope, default) or jsonl (one item per line).", "json")
|
|
104
|
+
.option("--collect-out <path>", "Write the collection to this file instead of stdout.")
|
|
74
105
|
.option("--network-har <path>", "Record network traffic to a HAR file (finalized on close)")
|
|
75
|
-
.option("--viewport <preset|WxH>", "Viewport: mobile (390x844), tablet (820x1180), desktop (1280x800), hd (1920x1080), or explicit '1920x1080'
|
|
106
|
+
.option("--viewport <preset|WxH>", "Viewport: mobile (390x844), tablet (820x1180), desktop (1280x800), hd (1920x1080), or explicit '1920x1080'. Default: real window in headed mode, desktop in headless mode")
|
|
76
107
|
.option("--color-scheme <scheme>", "Emulate prefers-color-scheme for the whole session: light | dark. " +
|
|
77
108
|
"Renders theme-aware pages in that scheme without page-specific toggles. " +
|
|
78
109
|
"Absent = browser default (unchanged behavior).")
|
|
79
|
-
.option("--login", "
|
|
110
|
+
.option("--login", "Open the URL in the installed Google Chrome with nothing attached (no DevTools protocol, no " +
|
|
111
|
+
"Playwright) so a person can sign in; under WSL this is the Windows host's Chrome. Sign in, then " +
|
|
112
|
+
"close the window or create the --login-close-file; later browse and browse-session runs reuse " +
|
|
113
|
+
"the cookies. Sites cannot tell this window from the person's own browser.")
|
|
114
|
+
.option("--attached", "With --login: open an automation-controlled Chrome that this process and --control-file can drive. " +
|
|
115
|
+
"Sites can detect it and may lock the account, so use it only for agent-driven headed sessions on " +
|
|
116
|
+
"sites you own. Never use it to sign in to a third-party account.")
|
|
80
117
|
.option("--login-close-file <path>", "With --login, wait for this file instead of terminal Enter, then remove it and close cleanly")
|
|
81
|
-
.option("--control-file <path>", "With --login, publish an owner-only descriptor for repeated browse-session control")
|
|
82
|
-
.option("--headed", "
|
|
118
|
+
.option("--control-file <path>", "With --login --attached, publish an owner-only descriptor for repeated browse-session control")
|
|
119
|
+
.option("--headed", "Automation-controlled headed window for one-off visual checks. Not for signing in; use --login.")
|
|
120
|
+
.option("--browser-channel <name>", "Browser to launch: chrome | chrome-beta | msedge | chromium. Headed launches (--login, --headed) " +
|
|
121
|
+
"default to the installed Google Chrome with the automation signals removed, because the bundled " +
|
|
122
|
+
'"Chrome for Testing" build advertises itself and sign-in flows refuse clicks; chromium forces the ' +
|
|
123
|
+
"bundled build. HARNERY_BROWSER_CHANNEL sets the default machine-wide.")
|
|
124
|
+
.option("--user-agent <ua|auto|native>", "User agent to present. Default: a normal Windows (or macOS on a Mac) Chrome user agent at the launched " +
|
|
125
|
+
"Chrome's major version, stored at ~/.cache/harnery/user-agent.json and reused by every surface; never " +
|
|
126
|
+
"Linux, never HeadlessChrome. A string rewrites the store, auto refreshes it, native uses the browser's own. " +
|
|
127
|
+
"HARNERY_BROWSER_UA overrides for one environment.")
|
|
83
128
|
.option("--browser-arg <flag>", "Extra Chromium launch flag, passed straight to the browser (repeatable). " +
|
|
84
129
|
"e.g. --browser-arg --disable-gpu. Also settable machine-wide via the " +
|
|
85
|
-
"HARNERY_BROWSER_ARGS env var (whitespace-separated). Under WSL,
|
|
86
|
-
"
|
|
87
|
-
"
|
|
130
|
+
"HARNERY_BROWSER_ARGS env var (whitespace-separated). Under WSL, set " +
|
|
131
|
+
"HARNERY_BROWSER_WSL_DISABLE_GPU=1 to add --disable-gpu when a headed window paints blank; " +
|
|
132
|
+
"it is off by default because software WebGL is a bot tell.", (value, prev = []) => [...prev, value], [])
|
|
88
133
|
.option("--proxy-from-env", "Pass HTTP(S)_PROXY to Playwright as an authenticated browser proxy. " +
|
|
89
134
|
"Credentials stay in the child environment, never command arguments. " +
|
|
90
135
|
"When the host also injects the HARNERY_BROWSER_PROXY_* gate variables, " +
|
|
91
136
|
"the expected IP is verified before the requested URL opens.")
|
|
92
137
|
.option("--no-cookies", "Skip cookie-jar attach and persist")
|
|
138
|
+
.option("--no-pace", "Skip the human-pace gap (3 to 9 s) between page loads of the same site for this run. " +
|
|
139
|
+
"HARNERY_PACE=off disables it machine-wide; local and private hosts never wait.")
|
|
93
140
|
.option("--store <path>", `Cookie store path (default ${DEFAULT_STORE})`)
|
|
94
141
|
.option("--profile <dir>", `Persistent Chromium profile dir (default ${DEFAULT_PROFILE})`)
|
|
95
142
|
.option("--export-cookies <path>", "Write live profile cookies as an owner-only Netscape cookies.txt file on close")
|
|
@@ -296,7 +343,8 @@ async function runBrowse(url, opts, context) {
|
|
|
296
343
|
: new CookieJar({ path: opts.store ?? DEFAULT_STORE, source: "harn-browse" });
|
|
297
344
|
if (jar)
|
|
298
345
|
applyExtraCookies(url, jar, context?.extraCookies);
|
|
299
|
-
const
|
|
346
|
+
const loginMode = resolveLoginMode(opts);
|
|
347
|
+
const headed = loginMode === "attached" || opts.headed;
|
|
300
348
|
const viewport = parseViewport(opts.viewport ?? "desktop");
|
|
301
349
|
const deviceScaleFactor = parseDeviceScaleFactor(opts.deviceScaleFactor);
|
|
302
350
|
if (opts.reviewPackAllocation && !opts.reviewPack) {
|
|
@@ -322,30 +370,58 @@ async function runBrowse(url, opts, context) {
|
|
|
322
370
|
}
|
|
323
371
|
const proxy = opts.proxyFromEnv ? browserProxyFromEnv() : undefined;
|
|
324
372
|
const proxyGate = opts.proxyFromEnv ? browserProxyGateFromEnv() : null;
|
|
325
|
-
if (opts.loginCloseFile && !opts.login) {
|
|
326
|
-
throw new Error("--login-close-file requires --login.");
|
|
327
|
-
}
|
|
328
|
-
if (opts.controlFile && !opts.login) {
|
|
329
|
-
throw new Error("--control-file requires --login.");
|
|
330
|
-
}
|
|
331
373
|
const loginCloseFile = opts.loginCloseFile ? resolve(opts.loginCloseFile) : null;
|
|
332
374
|
if (loginCloseFile && existsSync(loginCloseFile)) {
|
|
333
375
|
throw new Error(`Login close signal already exists at ${loginCloseFile}. Remove the stale file before launching.`);
|
|
334
376
|
}
|
|
377
|
+
const collectPlan = opts.collect ? buildCollectPlan(opts) : null;
|
|
378
|
+
const pace = commandPaceGate(opts.pace !== false, (message) => emit.log(message, "info"));
|
|
379
|
+
if (loginMode === "plain") {
|
|
380
|
+
const plainExecutable = installedChromePath();
|
|
381
|
+
const plainUa = resolveUserAgent({
|
|
382
|
+
requested: opts.userAgent,
|
|
383
|
+
env: process.env.HARNERY_BROWSER_UA,
|
|
384
|
+
chromeMajor: plainExecutable ? chromeMajorFromExecutable(plainExecutable) : undefined,
|
|
385
|
+
});
|
|
386
|
+
await pace?.before(url);
|
|
387
|
+
if (useWindowsPlainLogin()) {
|
|
388
|
+
await runWindowsPlainLogin(url, opts.store ?? DEFAULT_STORE, loginCloseFile, emit);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
await runPlainLogin(url, opts.profile ?? DEFAULT_PROFILE, loginCloseFile, plainUa, emit);
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
const channel = resolveBrowserChannel(opts, Boolean(headed));
|
|
395
|
+
const userAgent = resolveUserAgent({
|
|
396
|
+
requested: opts.userAgent,
|
|
397
|
+
env: process.env.HARNERY_BROWSER_UA,
|
|
398
|
+
chromeMajor: launchedChromeMajor(channel),
|
|
399
|
+
});
|
|
335
400
|
const browser = new Browser({
|
|
336
401
|
profileDir: opts.profile ?? DEFAULT_PROFILE,
|
|
337
402
|
headed,
|
|
338
403
|
jar,
|
|
339
|
-
viewport,
|
|
404
|
+
viewport: headed && !opts.viewport ? null : viewport,
|
|
340
405
|
...(deviceScaleFactor !== undefined ? { deviceScaleFactor } : {}),
|
|
341
406
|
...(colorScheme ? { colorScheme } : {}),
|
|
342
407
|
navigationTimeout: Number.parseInt(opts.timeout, 10),
|
|
343
408
|
waitUntil: opts.waitUntil,
|
|
344
409
|
recordHarPath: opts.networkHar ? resolve(opts.networkHar) : undefined,
|
|
345
410
|
extraHeaders: context?.extraHeaders,
|
|
411
|
+
pace,
|
|
346
412
|
launchArgs: resolveLaunchArgs(opts, Boolean(headed), Boolean(proxy)),
|
|
413
|
+
...(channel ? { channel } : {}),
|
|
414
|
+
hideAutomation: Boolean(headed),
|
|
415
|
+
...(userAgent ? { userAgent } : {}),
|
|
347
416
|
proxy,
|
|
348
417
|
});
|
|
418
|
+
if (userAgent)
|
|
419
|
+
emit.log(`Presenting as: ${userAgent}`, "debug");
|
|
420
|
+
if (headed) {
|
|
421
|
+
emit.log(channel && channel !== "chromium"
|
|
422
|
+
? `Headed session uses the installed ${channel} channel with automation signals hidden.`
|
|
423
|
+
: "Headed session uses Playwright's bundled Chromium (no Google Chrome found); automation signals hidden.", "info");
|
|
424
|
+
}
|
|
349
425
|
// Print mode: --snapshot / --html / --json all suppress file writes.
|
|
350
426
|
const printMode = opts.snapshot || opts.html || opts.json;
|
|
351
427
|
let controlServer = null;
|
|
@@ -382,6 +458,10 @@ async function runBrowse(url, opts, context) {
|
|
|
382
458
|
if (opts.batch) {
|
|
383
459
|
batchResult = await runBatch(browser, opts.batch, Number.parseInt(opts.timeout, 10));
|
|
384
460
|
}
|
|
461
|
+
if (collectPlan) {
|
|
462
|
+
await runCollectMode(browser, collectPlan);
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
385
465
|
let evalResult;
|
|
386
466
|
if (opts.evaluate) {
|
|
387
467
|
evalResult = await browser.evaluate(opts.evaluate);
|
|
@@ -772,11 +852,11 @@ async function runBrowse(url, opts, context) {
|
|
|
772
852
|
const lifecycleAbort = new AbortController();
|
|
773
853
|
const closeWaits = [];
|
|
774
854
|
if (loginCloseFile) {
|
|
775
|
-
emit.log(`[--login]
|
|
855
|
+
emit.log(`[--login --attached] Automation-controlled Chrome is open. Drive the visible window now. Create ${loginCloseFile} to close cleanly.`, "info");
|
|
776
856
|
closeWaits.push(waitForLoginCloseFile(loginCloseFile, lifecycleAbort.signal));
|
|
777
857
|
}
|
|
778
858
|
else {
|
|
779
|
-
emit.log("[--login]
|
|
859
|
+
emit.log("[--login --attached] Automation-controlled Chrome is open. Drive the visible window now. Press Enter here to close + persist cookies into the profile.", "info");
|
|
780
860
|
closeWaits.push(waitForTerminalEnter(lifecycleAbort.signal));
|
|
781
861
|
}
|
|
782
862
|
if (controlServer) {
|
|
@@ -912,6 +992,137 @@ async function runBrowse(url, opts, context) {
|
|
|
912
992
|
process.exitCode = receivedSignal === "SIGINT" ? 130 : 143;
|
|
913
993
|
}
|
|
914
994
|
}
|
|
995
|
+
function parsePositiveInt(raw, flag) {
|
|
996
|
+
if (!/^\d+$/.test(raw.trim()) || Number.parseInt(raw, 10) < 1) {
|
|
997
|
+
throw new Error(`${flag} must be a positive integer (got "${raw}").`);
|
|
998
|
+
}
|
|
999
|
+
return Number.parseInt(raw, 10);
|
|
1000
|
+
}
|
|
1001
|
+
function buildCollectPlan(opts) {
|
|
1002
|
+
if (opts.login)
|
|
1003
|
+
throw new Error("--collect cannot run with --login.");
|
|
1004
|
+
if (opts.snapshot || opts.html || opts.json) {
|
|
1005
|
+
throw new Error("--collect prints its own JSON; drop --snapshot, --html and --json.");
|
|
1006
|
+
}
|
|
1007
|
+
const presetName = typeof opts.collect === "string" ? opts.collect : "generic";
|
|
1008
|
+
const spec = resolveCollectSpec(presetName, {
|
|
1009
|
+
item: opts.collectItem,
|
|
1010
|
+
key: opts.collectKey,
|
|
1011
|
+
keyPattern: opts.collectKeyPattern,
|
|
1012
|
+
fields: opts.collectField,
|
|
1013
|
+
expand: opts.collectExpand,
|
|
1014
|
+
});
|
|
1015
|
+
const limits = {
|
|
1016
|
+
...DEFAULT_COLLECT_LIMITS,
|
|
1017
|
+
maxItems: opts.collectMaxItems === undefined
|
|
1018
|
+
? null
|
|
1019
|
+
: parsePositiveInt(opts.collectMaxItems, "--collect-max-items"),
|
|
1020
|
+
maxScrolls: parsePositiveInt(opts.collectMaxScrolls ?? "60", "--collect-max-scrolls"),
|
|
1021
|
+
maxMs: parsePositiveInt(opts.collectMaxSeconds ?? "300", "--collect-max-seconds") * 1_000,
|
|
1022
|
+
idleSteps: parsePositiveInt(opts.collectIdle ?? "5", "--collect-idle"),
|
|
1023
|
+
expandPerStep: spec.expand ? 3 : 0,
|
|
1024
|
+
};
|
|
1025
|
+
const pacing = scrollPacingFromEnv();
|
|
1026
|
+
const msBounds = { min: 0, max: PACING_LIMITS.maxPauseMs };
|
|
1027
|
+
if (opts.collectStep) {
|
|
1028
|
+
pacing.step = parseRange(opts.collectStep, "--collect-step", {
|
|
1029
|
+
min: 0.05,
|
|
1030
|
+
max: PACING_LIMITS.maxStepFraction,
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
if (opts.collectPause)
|
|
1034
|
+
pacing.pauseMs = parseRange(opts.collectPause, "--collect-pause", msBounds);
|
|
1035
|
+
if (opts.collectReadPause) {
|
|
1036
|
+
pacing.readPauseMs = parseRange(opts.collectReadPause, "--collect-read-pause", msBounds);
|
|
1037
|
+
}
|
|
1038
|
+
if (opts.collectReadChance !== undefined) {
|
|
1039
|
+
pacing.readChance = parseProbability(opts.collectReadChance, "--collect-read-chance");
|
|
1040
|
+
}
|
|
1041
|
+
if (opts.collectBackChance !== undefined) {
|
|
1042
|
+
pacing.backChance = parseProbability(opts.collectBackChance, "--collect-back-chance");
|
|
1043
|
+
}
|
|
1044
|
+
let seed = randomSeed();
|
|
1045
|
+
if (opts.collectSeed !== undefined) {
|
|
1046
|
+
if (!/^\d+$/.test(opts.collectSeed.trim())) {
|
|
1047
|
+
throw new Error(`--collect-seed must be a non-negative integer (got "${opts.collectSeed}").`);
|
|
1048
|
+
}
|
|
1049
|
+
seed = Number(BigInt(opts.collectSeed.trim()) % 4294967296n);
|
|
1050
|
+
}
|
|
1051
|
+
const format = opts.collectFormat ?? "json";
|
|
1052
|
+
if (format !== "json" && format !== "jsonl") {
|
|
1053
|
+
throw new Error(`--collect-format must be json or jsonl (got "${format}").`);
|
|
1054
|
+
}
|
|
1055
|
+
return {
|
|
1056
|
+
spec,
|
|
1057
|
+
limits,
|
|
1058
|
+
pacing,
|
|
1059
|
+
seed,
|
|
1060
|
+
format,
|
|
1061
|
+
out: opts.collectOut ? resolve(opts.collectOut) : null,
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
async function runCollectMode(browser, plan) {
|
|
1065
|
+
const page = browser.currentPage;
|
|
1066
|
+
const rng = createRng(plan.seed);
|
|
1067
|
+
let interrupted = false;
|
|
1068
|
+
const onSignal = () => {
|
|
1069
|
+
interrupted = true;
|
|
1070
|
+
};
|
|
1071
|
+
process.on("SIGINT", onSignal);
|
|
1072
|
+
process.on("SIGTERM", onSignal);
|
|
1073
|
+
let result;
|
|
1074
|
+
try {
|
|
1075
|
+
emit.log(`collect: preset ${plan.spec.preset}, item ${plan.spec.item}, seed ${plan.seed}`, "info");
|
|
1076
|
+
const driver = createPageDriver(page, plan.spec, {
|
|
1077
|
+
rng,
|
|
1078
|
+
log: (message) => emit.log(message, "warn"),
|
|
1079
|
+
});
|
|
1080
|
+
result = await runCollect(driver, {
|
|
1081
|
+
limits: plan.limits,
|
|
1082
|
+
pacing: plan.pacing,
|
|
1083
|
+
rng,
|
|
1084
|
+
shouldStop: () => interrupted,
|
|
1085
|
+
onStep: ({ step, items, added }) => emit.log(`collect: step ${step}, ${items} items (+${added})`, "debug"),
|
|
1086
|
+
});
|
|
1087
|
+
}
|
|
1088
|
+
finally {
|
|
1089
|
+
process.removeListener("SIGINT", onSignal);
|
|
1090
|
+
process.removeListener("SIGTERM", onSignal);
|
|
1091
|
+
}
|
|
1092
|
+
const { items, stats } = result;
|
|
1093
|
+
emit.log(`collect: ${items.length} items in ${stats.steps} steps, stopped on ${stats.stopReason}` +
|
|
1094
|
+
(stats.stopDetail ? ` (${stats.stopDetail})` : ""), "info");
|
|
1095
|
+
const envelope = {
|
|
1096
|
+
url: page.url(),
|
|
1097
|
+
preset: plan.spec.preset,
|
|
1098
|
+
itemSelector: plan.spec.item,
|
|
1099
|
+
seed: plan.seed,
|
|
1100
|
+
stopReason: stats.stopReason,
|
|
1101
|
+
stats,
|
|
1102
|
+
items,
|
|
1103
|
+
};
|
|
1104
|
+
if (plan.format === "jsonl") {
|
|
1105
|
+
const body = items.map((item) => JSON.stringify(item)).join("\n");
|
|
1106
|
+
if (plan.out) {
|
|
1107
|
+
mkdirSync(dirname(plan.out), { recursive: true });
|
|
1108
|
+
writeFileSync(plan.out, body ? `${body}\n` : "");
|
|
1109
|
+
emit.file(plan.out, { items: items.length, stopReason: stats.stopReason, stats });
|
|
1110
|
+
}
|
|
1111
|
+
else if (body) {
|
|
1112
|
+
process.stdout.write(`${body}\n`);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
else if (plan.out) {
|
|
1116
|
+
mkdirSync(dirname(plan.out), { recursive: true });
|
|
1117
|
+
writeFileSync(plan.out, `${JSON.stringify(envelope, null, 2)}\n`);
|
|
1118
|
+
emit.file(plan.out, { items: items.length, stopReason: stats.stopReason, stats });
|
|
1119
|
+
}
|
|
1120
|
+
else {
|
|
1121
|
+
emit.data(envelope);
|
|
1122
|
+
}
|
|
1123
|
+
if (interrupted)
|
|
1124
|
+
process.exitCode = 130;
|
|
1125
|
+
}
|
|
915
1126
|
async function runBatch(browser, batch, defaultTimeoutMs) {
|
|
916
1127
|
const result = { clipboardReads: [] };
|
|
917
1128
|
const steps = splitBatchSteps(batch);
|
|
@@ -982,27 +1193,6 @@ async function runBatch(browser, batch, defaultTimeoutMs) {
|
|
|
982
1193
|
}
|
|
983
1194
|
return result;
|
|
984
1195
|
}
|
|
985
|
-
function splitBatchSteps(input) {
|
|
986
|
-
const steps = [];
|
|
987
|
-
let buf = "";
|
|
988
|
-
for (let i = 0; i < input.length; i++) {
|
|
989
|
-
const ch = input[i];
|
|
990
|
-
if (ch === "\\" && input[i + 1] === ";") {
|
|
991
|
-
buf += ";";
|
|
992
|
-
i++;
|
|
993
|
-
continue;
|
|
994
|
-
}
|
|
995
|
-
if (ch === ";") {
|
|
996
|
-
steps.push(buf);
|
|
997
|
-
buf = "";
|
|
998
|
-
continue;
|
|
999
|
-
}
|
|
1000
|
-
buf += ch;
|
|
1001
|
-
}
|
|
1002
|
-
if (buf.trim())
|
|
1003
|
-
steps.push(buf);
|
|
1004
|
-
return steps;
|
|
1005
|
-
}
|
|
1006
1196
|
// ---------------------------------------------------------------------------
|
|
1007
1197
|
// Print mode (--snapshot / --html / --json): stdout, no file writes
|
|
1008
1198
|
// ---------------------------------------------------------------------------
|
|
@@ -2035,15 +2225,50 @@ function summarizeDiagnostics(diag) {
|
|
|
2035
2225
|
}
|
|
2036
2226
|
/**
|
|
2037
2227
|
* Merge Chromium launch flags from three sources, in order, de-duped:
|
|
2038
|
-
* 1. WSLg
|
|
2039
|
-
*
|
|
2040
|
-
*
|
|
2228
|
+
* 1. WSLg `--disable-gpu`, only when HARNERY_BROWSER_WSL_DISABLE_GPU=1. It
|
|
2229
|
+
* was the default for headed launches, but software WebGL (SwiftShader)
|
|
2230
|
+
* is a bot tell that sign-in flows screen for, and current WSLg exposes
|
|
2231
|
+
* the host GPU through D3D12, so the flag is now opt-in for machines
|
|
2232
|
+
* that still paint a blank headed window without it.
|
|
2041
2233
|
* 2. HARNERY_BROWSER_ARGS env (whitespace-separated) — a machine-wide default.
|
|
2042
2234
|
* 3. --browser-arg flags on this invocation (repeatable).
|
|
2043
2235
|
*/
|
|
2236
|
+
const BROWSER_CHANNELS = new Set(["chrome", "chrome-beta", "msedge", "chromium"]);
|
|
2237
|
+
/**
|
|
2238
|
+
* Pick the browser channel: `--browser-channel`, then `HARNERY_BROWSER_CHANNEL`,
|
|
2239
|
+
* then (headed only) the installed Google Chrome when one exists. Headless runs
|
|
2240
|
+
* keep the bundled Chromium unless told otherwise, so QA renders stay stable.
|
|
2241
|
+
*/
|
|
2242
|
+
function resolveBrowserChannel(opts, headed) {
|
|
2243
|
+
const requested = (opts.browserChannel ?? process.env.HARNERY_BROWSER_CHANNEL)?.trim();
|
|
2244
|
+
if (requested) {
|
|
2245
|
+
if (!BROWSER_CHANNELS.has(requested)) {
|
|
2246
|
+
throw new Error(`Unknown --browser-channel "${requested}". Use chrome, chrome-beta, msedge, or chromium.`);
|
|
2247
|
+
}
|
|
2248
|
+
return requested;
|
|
2249
|
+
}
|
|
2250
|
+
return headed ? installedChromeChannel() : undefined;
|
|
2251
|
+
}
|
|
2252
|
+
/**
|
|
2253
|
+
* Major version of the Chrome that will launch: the installed Chrome for the
|
|
2254
|
+
* `chrome` channel, else Playwright's bundled Chromium. Unknown when neither
|
|
2255
|
+
* answers `--version`; the user-agent store then keeps its last value.
|
|
2256
|
+
*/
|
|
2257
|
+
function launchedChromeMajor(channel) {
|
|
2258
|
+
if (channel === "chrome") {
|
|
2259
|
+
const exe = installedChromePath();
|
|
2260
|
+
return exe ? chromeMajorFromExecutable(exe) : undefined;
|
|
2261
|
+
}
|
|
2262
|
+
try {
|
|
2263
|
+
return chromeMajorFromExecutable(chromium.executablePath());
|
|
2264
|
+
}
|
|
2265
|
+
catch {
|
|
2266
|
+
return undefined;
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2044
2269
|
function resolveLaunchArgs(opts, headed, proxyEnabled) {
|
|
2045
2270
|
const args = [];
|
|
2046
|
-
if (headed &&
|
|
2271
|
+
if (headed && process.env.HARNERY_BROWSER_WSL_DISABLE_GPU === "1") {
|
|
2047
2272
|
args.push(...wslHeadedLaunchArgs());
|
|
2048
2273
|
}
|
|
2049
2274
|
const envArgs = process.env.HARNERY_BROWSER_ARGS?.trim();
|
|
@@ -2067,6 +2292,124 @@ async function verifyBrowserProxyGate(browser, gate) {
|
|
|
2067
2292
|
}
|
|
2068
2293
|
emit.log(`browser proxy gate: ${observedIp} · expected IP confirmed`, "info");
|
|
2069
2294
|
}
|
|
2295
|
+
/**
|
|
2296
|
+
* How a `browse` run handles sign-in. `--login` opens the installed Google
|
|
2297
|
+
* Chrome with nothing attached, because sites can detect an
|
|
2298
|
+
* automation-controlled browser and disable the account that signed in with
|
|
2299
|
+
* it. The attached window is reachable only through an explicit `--attached`.
|
|
2300
|
+
*/
|
|
2301
|
+
export function resolveLoginMode(opts) {
|
|
2302
|
+
if (opts.attached && !opts.login)
|
|
2303
|
+
throw new Error("--attached requires --login.");
|
|
2304
|
+
if (opts.loginCloseFile && !opts.login)
|
|
2305
|
+
throw new Error("--login-close-file requires --login.");
|
|
2306
|
+
if (opts.controlFile && !(opts.login && opts.attached)) {
|
|
2307
|
+
throw new Error("--control-file requires --login --attached. A sign-in to a third-party account uses plain " +
|
|
2308
|
+
"--login, which nothing can drive.");
|
|
2309
|
+
}
|
|
2310
|
+
if (!opts.login)
|
|
2311
|
+
return "none";
|
|
2312
|
+
return opts.attached ? "attached" : "plain";
|
|
2313
|
+
}
|
|
2314
|
+
/**
|
|
2315
|
+
* `--login`: spawn the installed Google Chrome directly on the shared
|
|
2316
|
+
* persistent profile, with no DevTools protocol attached. Playwright enables
|
|
2317
|
+
* its runtime hooks in every frame it drives, and sign-in verification vendors
|
|
2318
|
+
* (X's is the reported case) detect that and fail the flow with no explanation.
|
|
2319
|
+
* The person signs in here; cookies land in the same profile that later
|
|
2320
|
+
* `browse` and `browse-session` runs open, so read-only captures inherit the
|
|
2321
|
+
* session without ever repeating the sign-in under automation.
|
|
2322
|
+
*/
|
|
2323
|
+
async function runPlainLogin(url, profileDir, loginCloseFile, userAgent, emit) {
|
|
2324
|
+
const executable = installedChromePath();
|
|
2325
|
+
if (!executable) {
|
|
2326
|
+
throw new Error("--login needs an installed Google Chrome at a standard path; none was found on this machine. " +
|
|
2327
|
+
"Install Google Chrome; do not fall back to --attached for a third-party sign-in.");
|
|
2328
|
+
}
|
|
2329
|
+
mkdirSync(profileDir, { recursive: true });
|
|
2330
|
+
const child = spawn(executable, [
|
|
2331
|
+
`--user-data-dir=${profileDir}`,
|
|
2332
|
+
"--no-first-run",
|
|
2333
|
+
"--no-default-browser-check",
|
|
2334
|
+
...(userAgent ? [`--user-agent=${userAgent}`] : []),
|
|
2335
|
+
url,
|
|
2336
|
+
], { stdio: "ignore" });
|
|
2337
|
+
const exited = new Promise((resolveExit) => {
|
|
2338
|
+
child.once("exit", () => resolveExit());
|
|
2339
|
+
child.once("error", () => resolveExit());
|
|
2340
|
+
});
|
|
2341
|
+
const lifecycleAbort = new AbortController();
|
|
2342
|
+
const waits = [exited];
|
|
2343
|
+
if (loginCloseFile) {
|
|
2344
|
+
emit.log(`[--login] Plain Google Chrome is open with nothing attached. Sign in, then close the window or create ${loginCloseFile}.`, "info");
|
|
2345
|
+
waits.push(waitForLoginCloseFile(loginCloseFile, lifecycleAbort.signal));
|
|
2346
|
+
}
|
|
2347
|
+
else {
|
|
2348
|
+
emit.log("[--login] Plain Google Chrome is open with nothing attached. Sign in, then close the window or press Enter here.", "info");
|
|
2349
|
+
waits.push(waitForTerminalEnter(lifecycleAbort.signal));
|
|
2350
|
+
}
|
|
2351
|
+
await Promise.race(waits);
|
|
2352
|
+
lifecycleAbort.abort();
|
|
2353
|
+
if (child.exitCode === null && child.signalCode === null) {
|
|
2354
|
+
child.kill("SIGTERM");
|
|
2355
|
+
await Promise.race([exited, new Promise((r) => setTimeout(r, 5000))]);
|
|
2356
|
+
}
|
|
2357
|
+
emit.log(`[--login] Chrome closed; cookies persisted in ${profileDir}.`, "info");
|
|
2358
|
+
}
|
|
2359
|
+
/**
|
|
2360
|
+
* Under WSL, `--login` opens the Windows host's Google Chrome when one
|
|
2361
|
+
* is installed. Some sign-in flows reject every browser running inside WSL,
|
|
2362
|
+
* even a plain Linux Chrome, while the Windows desktop Chrome signs in
|
|
2363
|
+
* normally. `HARNERY_BROWSER_WSL_PLAIN=linux` keeps the Linux Chrome.
|
|
2364
|
+
*/
|
|
2365
|
+
function useWindowsPlainLogin() {
|
|
2366
|
+
if (!isWSL())
|
|
2367
|
+
return false;
|
|
2368
|
+
if ((process.env.HARNERY_BROWSER_WSL_PLAIN ?? "").toLowerCase() === "linux")
|
|
2369
|
+
return false;
|
|
2370
|
+
return windowsChromePath() !== undefined;
|
|
2371
|
+
}
|
|
2372
|
+
/**
|
|
2373
|
+
* The WSL form of `--login`: the person signs in through the Windows
|
|
2374
|
+
* Chrome on a dedicated Windows profile with nothing attached. When the window
|
|
2375
|
+
* closes, the profile's cookies for the sign-in site are read and merged into
|
|
2376
|
+
* the shared cookie store, which later `browse` runs attach.
|
|
2377
|
+
*/
|
|
2378
|
+
async function runWindowsPlainLogin(url, storePath, loginCloseFile, emit) {
|
|
2379
|
+
const chromeLinux = windowsChromePath();
|
|
2380
|
+
const localAppData = windowsLocalAppData();
|
|
2381
|
+
if (!chromeLinux || !localAppData) {
|
|
2382
|
+
throw new Error("--login under WSL needs the Windows Google Chrome and %LOCALAPPDATA%; neither was readable.");
|
|
2383
|
+
}
|
|
2384
|
+
const chromeWindows = wslPathToWindows(chromeLinux);
|
|
2385
|
+
const profileWindows = windowsPlainProfile(localAppData);
|
|
2386
|
+
const child = spawn(chromeLinux, [`--user-data-dir=${profileWindows}`, "--no-first-run", "--no-default-browser-check", url], { stdio: "ignore" });
|
|
2387
|
+
const exited = new Promise((resolveExit) => {
|
|
2388
|
+
child.once("exit", () => resolveExit());
|
|
2389
|
+
child.once("error", () => resolveExit());
|
|
2390
|
+
});
|
|
2391
|
+
const lifecycleAbort = new AbortController();
|
|
2392
|
+
const waits = [exited];
|
|
2393
|
+
const how = loginCloseFile ? `create ${loginCloseFile}` : "press Enter here";
|
|
2394
|
+
emit.log(`[--login] Windows Google Chrome is open with nothing attached (profile ${profileWindows}). Sign in, then close the window or ${how}.`, "info");
|
|
2395
|
+
waits.push(loginCloseFile
|
|
2396
|
+
? waitForLoginCloseFile(loginCloseFile, lifecycleAbort.signal)
|
|
2397
|
+
: waitForTerminalEnter(lifecycleAbort.signal));
|
|
2398
|
+
await Promise.race(waits);
|
|
2399
|
+
lifecycleAbort.abort();
|
|
2400
|
+
stopWindowsChromeProfile(profileWindows);
|
|
2401
|
+
await Promise.race([exited, new Promise((r) => setTimeout(r, 5000))]);
|
|
2402
|
+
const domain = harvestDomain(url);
|
|
2403
|
+
const cookies = harvestWindowsChromeCookies({ chromeWindows, profileWindows, domain });
|
|
2404
|
+
if (cookies.length === 0) {
|
|
2405
|
+
emit.log(`[--login] No ${domain} cookies were found in the Windows profile; the sign-in may not have completed.`, "warn");
|
|
2406
|
+
return;
|
|
2407
|
+
}
|
|
2408
|
+
const jar = new CookieJar({ path: storePath, source: "harn-browse" });
|
|
2409
|
+
jar.save(mergeCookies(jar.load(), cookies));
|
|
2410
|
+
const names = [...new Set(cookies.map((cookie) => cookie.name))].sort().join(", ");
|
|
2411
|
+
emit.log(`[--login] Copied ${cookies.length} ${domain} cookies into ${storePath}: ${names}.`, "info");
|
|
2412
|
+
}
|
|
2070
2413
|
async function waitForLoginCloseFile(path, signal) {
|
|
2071
2414
|
while (!existsSync(path) && !signal?.aborted) {
|
|
2072
2415
|
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ADAPTERS, normalizeAdapter } from "../core/adapter.js";
|
|
1
2
|
import { monorepoRoot, resolveOwner } from "../core/agents/index.js";
|
|
2
3
|
import { readLiveCoordinationRow } from "../core/agents/state/live-coordination-view.js";
|
|
3
4
|
import { checkpointContext, readContextState, readLatestCapsule, } from "../core/context/index.js";
|
|
@@ -58,7 +59,7 @@ export function registerCheckpointCommand(program, emit, context) {
|
|
|
58
59
|
.description("Create a durable context-continuity capsule for the current work")
|
|
59
60
|
.option("--session <id>", "Session id (defaults to the current agent heartbeat)")
|
|
60
61
|
.option("--instance <id>", "Agent instance id (defaults to the current owner)")
|
|
61
|
-
.option("--adapter <id>", "
|
|
62
|
+
.option("--adapter <id>", `${ADAPTERS.join(", ")} (inferred from heartbeat)`)
|
|
62
63
|
.option("--reason <reason>", "manual, pressure, pre_compact, or session_end", "manual")
|
|
63
64
|
.option("--note <text>", "Short continuation note for the recovered agent")
|
|
64
65
|
.option("--json", "Structured JSON output")
|
|
@@ -68,7 +69,7 @@ export function registerCheckpointCommand(program, emit, context) {
|
|
|
68
69
|
const reason = parseCheckpointReason(opts.reason);
|
|
69
70
|
const identity = resolveContinuityIdentity(context, opts);
|
|
70
71
|
if (!identity.adapter) {
|
|
71
|
-
throw new Error(
|
|
72
|
+
throw new Error(`could not infer the adapter; pass --adapter ${ADAPTERS.join("|")}`);
|
|
72
73
|
}
|
|
73
74
|
const result = checkpointContext(identity.coordRoot, {
|
|
74
75
|
sessionId: identity.sessionId,
|
|
@@ -135,18 +136,13 @@ function resolveContinuityIdentity(context, opts) {
|
|
|
135
136
|
return { coordRoot, instanceId, sessionId, adapter };
|
|
136
137
|
}
|
|
137
138
|
function adapterFromPlatform(platform) {
|
|
138
|
-
|
|
139
|
-
return "claude-code";
|
|
140
|
-
if (platform === "cursor")
|
|
141
|
-
return "cursor";
|
|
142
|
-
if (platform === "codex")
|
|
143
|
-
return "codex";
|
|
144
|
-
return null;
|
|
139
|
+
return normalizeAdapter(platform);
|
|
145
140
|
}
|
|
146
141
|
function parseAdapter(value) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
142
|
+
const adapter = normalizeAdapter(value);
|
|
143
|
+
if (adapter)
|
|
144
|
+
return adapter;
|
|
145
|
+
throw new Error(`invalid adapter "${value}"; expected one of ${ADAPTERS.join(", ")}`);
|
|
150
146
|
}
|
|
151
147
|
function parseCheckpointReason(value) {
|
|
152
148
|
if (value === "manual" ||
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-desktop.d.ts","sourceRoot":"","sources":["../../src/commands/claude-desktop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"claude-desktop.d.ts","sourceRoot":"","sources":["../../src/commands/claude-desktop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAiB1E;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,WAAW,EACjB,QAAQ,CAAC,EAAE,qBAAqB,GAC/B,IAAI,CAoNN"}
|