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
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seeded randomness and the human-like scroll schedule for `browse --collect`.
|
|
3
|
+
*
|
|
4
|
+
* Everything here is pure: given a seed and a pacing policy, the plan for each
|
|
5
|
+
* step (wheel notches, pauses, reading pauses, small scroll-backs) is fully
|
|
6
|
+
* reproducible, which is what the unit tests rely on.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** A random source returning floats in [0, 1). */
|
|
10
|
+
export type Rng = () => number;
|
|
11
|
+
|
|
12
|
+
/** mulberry32: a small, fast, well-distributed 32-bit seeded generator. */
|
|
13
|
+
export function createRng(seed: number): Rng {
|
|
14
|
+
let a = seed >>> 0;
|
|
15
|
+
return () => {
|
|
16
|
+
a = (a + 0x6d2b79f5) >>> 0;
|
|
17
|
+
let t = a;
|
|
18
|
+
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
19
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
20
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** A fresh 32-bit seed for runs that did not pass one. */
|
|
25
|
+
export function randomSeed(): number {
|
|
26
|
+
return Math.floor(Math.random() * 0x1_0000_0000) >>> 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface Range {
|
|
30
|
+
min: number;
|
|
31
|
+
max: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function uniform(rng: Rng, range: Range): number {
|
|
35
|
+
return range.min + (range.max - range.min) * rng();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ScrollPacing {
|
|
39
|
+
/** Scroll distance per step, as a fraction of the viewport height. */
|
|
40
|
+
step: Range;
|
|
41
|
+
/** Pause after each step, in ms. */
|
|
42
|
+
pauseMs: Range;
|
|
43
|
+
/** Probability that a step is followed by a longer reading pause instead. */
|
|
44
|
+
readChance: number;
|
|
45
|
+
/** Reading pause, in ms. */
|
|
46
|
+
readPauseMs: Range;
|
|
47
|
+
/** Probability that a step starts with a small scroll back up. */
|
|
48
|
+
backChance: number;
|
|
49
|
+
/** Scroll-back distance, as a fraction of the viewport height. */
|
|
50
|
+
back: Range;
|
|
51
|
+
/** Size of one wheel notch, in px. */
|
|
52
|
+
tickPx: Range;
|
|
53
|
+
/** Gap between wheel notches, in ms. */
|
|
54
|
+
tickGapMs: Range;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const DEFAULT_SCROLL_PACING: ScrollPacing = {
|
|
58
|
+
step: { min: 0.6, max: 1.1 },
|
|
59
|
+
pauseMs: { min: 1_200, max: 3_500 },
|
|
60
|
+
readChance: 0.12,
|
|
61
|
+
readPauseMs: { min: 4_000, max: 9_000 },
|
|
62
|
+
backChance: 0.08,
|
|
63
|
+
back: { min: 0.1, max: 0.3 },
|
|
64
|
+
tickPx: { min: 80, max: 140 },
|
|
65
|
+
tickGapMs: { min: 12, max: 45 },
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/** Upper bounds that keep every pause and step bounded. */
|
|
69
|
+
export const PACING_LIMITS = {
|
|
70
|
+
maxStepFraction: 3,
|
|
71
|
+
maxPauseMs: 120_000,
|
|
72
|
+
} as const;
|
|
73
|
+
|
|
74
|
+
export interface WheelTick {
|
|
75
|
+
/** Positive scrolls down, negative scrolls up. */
|
|
76
|
+
deltaY: number;
|
|
77
|
+
/** Wait after this notch, in ms. */
|
|
78
|
+
gapMs: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface ScrollStepPlan {
|
|
82
|
+
/** Optional scroll-back notches run before the main step (negative deltas). */
|
|
83
|
+
back: WheelTick[];
|
|
84
|
+
/** Pause after the scroll-back, in ms (0 when there is no scroll-back). */
|
|
85
|
+
backPauseMs: number;
|
|
86
|
+
/** Main downward notches. */
|
|
87
|
+
ticks: WheelTick[];
|
|
88
|
+
/** Total downward distance, in px. */
|
|
89
|
+
deltaY: number;
|
|
90
|
+
/** Pause after the main step, in ms. */
|
|
91
|
+
pauseMs: number;
|
|
92
|
+
/** True when the pause is a longer reading pause. */
|
|
93
|
+
reading: boolean;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Split a distance into wheel notches the way a mouse wheel reports them. */
|
|
97
|
+
export function wheelTicks(rng: Rng, pacing: ScrollPacing, distance: number): WheelTick[] {
|
|
98
|
+
const sign = distance < 0 ? -1 : 1;
|
|
99
|
+
let remaining = Math.round(Math.abs(distance));
|
|
100
|
+
const ticks: WheelTick[] = [];
|
|
101
|
+
while (remaining > 0) {
|
|
102
|
+
const size = Math.min(remaining, Math.max(1, Math.round(uniform(rng, pacing.tickPx))));
|
|
103
|
+
remaining -= size;
|
|
104
|
+
ticks.push({ deltaY: sign * size, gapMs: Math.round(uniform(rng, pacing.tickGapMs)) });
|
|
105
|
+
}
|
|
106
|
+
return ticks;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function planScrollStep(
|
|
110
|
+
rng: Rng,
|
|
111
|
+
pacing: ScrollPacing,
|
|
112
|
+
viewportHeight: number,
|
|
113
|
+
): ScrollStepPlan {
|
|
114
|
+
const height = Math.max(1, viewportHeight);
|
|
115
|
+
let back: WheelTick[] = [];
|
|
116
|
+
let backPauseMs = 0;
|
|
117
|
+
if (rng() < pacing.backChance) {
|
|
118
|
+
back = wheelTicks(rng, pacing, -uniform(rng, pacing.back) * height);
|
|
119
|
+
backPauseMs = Math.round(uniform(rng, { min: 400, max: 1_100 }));
|
|
120
|
+
}
|
|
121
|
+
const deltaY = Math.max(1, Math.round(uniform(rng, pacing.step) * height));
|
|
122
|
+
const ticks = wheelTicks(rng, pacing, deltaY);
|
|
123
|
+
const reading = rng() < pacing.readChance;
|
|
124
|
+
const pauseMs = Math.round(uniform(rng, reading ? pacing.readPauseMs : pacing.pauseMs));
|
|
125
|
+
return { back, backPauseMs, ticks, deltaY, pauseMs, reading };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Parse `min-max` (or a single value meaning min = max). Throws a message that
|
|
130
|
+
* names the flag when the value is malformed or out of bounds.
|
|
131
|
+
*/
|
|
132
|
+
export function parseRange(raw: string, flag: string, bounds: { min: number; max: number }): Range {
|
|
133
|
+
const text = raw.trim();
|
|
134
|
+
const m = /^(\d+(?:\.\d+)?)(?:\s*-\s*(\d+(?:\.\d+)?))?$/.exec(text);
|
|
135
|
+
if (!m) throw new Error(`${flag} must be <min>-<max> or a single number (got "${raw}").`);
|
|
136
|
+
const min = Number(m[1]);
|
|
137
|
+
const max = m[2] === undefined ? min : Number(m[2]);
|
|
138
|
+
if (min > max) throw new Error(`${flag}: min (${min}) must not exceed max (${max}).`);
|
|
139
|
+
if (min < bounds.min || max > bounds.max) {
|
|
140
|
+
throw new Error(`${flag} must stay within ${bounds.min}-${bounds.max} (got "${raw}").`);
|
|
141
|
+
}
|
|
142
|
+
return { min, max };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function parseProbability(raw: string, flag: string): number {
|
|
146
|
+
const n = Number(raw);
|
|
147
|
+
if (!Number.isFinite(n) || n < 0 || n > 1) {
|
|
148
|
+
throw new Error(`${flag} must be a number from 0 to 1 (got "${raw}").`);
|
|
149
|
+
}
|
|
150
|
+
return n;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Machine-wide pacing defaults from the environment, in the same style as the
|
|
155
|
+
* page-load pace gate (`HARNERY_PACE_*`):
|
|
156
|
+
*
|
|
157
|
+
* - `HARNERY_COLLECT_PAUSE_MS`: pause after each step, `min-max` in ms.
|
|
158
|
+
* - `HARNERY_COLLECT_STEP`: step size as a viewport fraction, `min-max`.
|
|
159
|
+
*
|
|
160
|
+
* Command flags override these.
|
|
161
|
+
*/
|
|
162
|
+
export function scrollPacingFromEnv(env: NodeJS.ProcessEnv = process.env): ScrollPacing {
|
|
163
|
+
const pacing: ScrollPacing = { ...DEFAULT_SCROLL_PACING };
|
|
164
|
+
const pause = env.HARNERY_COLLECT_PAUSE_MS?.trim();
|
|
165
|
+
if (pause) {
|
|
166
|
+
pacing.pauseMs = parseRange(pause, "HARNERY_COLLECT_PAUSE_MS", {
|
|
167
|
+
min: 0,
|
|
168
|
+
max: PACING_LIMITS.maxPauseMs,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
const step = env.HARNERY_COLLECT_STEP?.trim();
|
|
172
|
+
if (step) {
|
|
173
|
+
pacing.step = parseRange(step, "HARNERY_COLLECT_STEP", {
|
|
174
|
+
min: 0.05,
|
|
175
|
+
max: PACING_LIMITS.maxStepFraction,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return pacing;
|
|
179
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** Keep Chromium's UA, navigator.platform and client hints in one profile. */
|
|
2
|
+
export function browserIdentity(userAgent: string, browserVersion?: string) {
|
|
3
|
+
const chrome = /(?:Chrome|Chromium)\/(\d+)\.([\d.]+)/.exec(userAgent);
|
|
4
|
+
const windows = userAgent.includes("Windows NT");
|
|
5
|
+
const mac = userAgent.includes("Macintosh");
|
|
6
|
+
// A custom non-Chromium or non-desktop UA is an explicit caller choice.
|
|
7
|
+
if (!chrome || (!windows && !mac)) return undefined;
|
|
8
|
+
const major = chrome[1]!;
|
|
9
|
+
const fullVersion = browserVersion?.startsWith(`${major}.`)
|
|
10
|
+
? browserVersion
|
|
11
|
+
: `${major}.${chrome[2]}`;
|
|
12
|
+
const brand = userAgent.includes("Edg/") ? "Microsoft Edge" : "Google Chrome";
|
|
13
|
+
return {
|
|
14
|
+
userAgent,
|
|
15
|
+
platform: windows ? "Win32" : "MacIntel",
|
|
16
|
+
userAgentMetadata: {
|
|
17
|
+
brands: [
|
|
18
|
+
{ brand: "Chromium", version: major },
|
|
19
|
+
{ brand, version: major },
|
|
20
|
+
],
|
|
21
|
+
fullVersionList: [
|
|
22
|
+
{ brand: "Chromium", version: fullVersion },
|
|
23
|
+
{ brand, version: fullVersion },
|
|
24
|
+
],
|
|
25
|
+
platform: windows ? "Windows" : "macOS",
|
|
26
|
+
platformVersion: windows ? "10.0.0" : "10.15.7",
|
|
27
|
+
architecture: "x86",
|
|
28
|
+
bitness: "64",
|
|
29
|
+
model: "",
|
|
30
|
+
mobile: false,
|
|
31
|
+
wow64: false,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Initial popup documents exist before Playwright can attach a page session. */
|
|
37
|
+
export function installDocumentIdentity(identity: NonNullable<ReturnType<typeof browserIdentity>>) {
|
|
38
|
+
const metadata = identity.userAgentMetadata;
|
|
39
|
+
const basics = { brands: metadata.brands, mobile: metadata.mobile, platform: metadata.platform };
|
|
40
|
+
Object.defineProperty(Navigator.prototype, "platform", {
|
|
41
|
+
configurable: true,
|
|
42
|
+
get: () => identity.platform,
|
|
43
|
+
});
|
|
44
|
+
if (!("userAgentData" in navigator)) return;
|
|
45
|
+
const nativeData = (navigator as Navigator & { userAgentData: object }).userAgentData;
|
|
46
|
+
const data = Object.create(Object.getPrototypeOf(nativeData));
|
|
47
|
+
for (const [name, value] of Object.entries(basics)) {
|
|
48
|
+
Object.defineProperty(data, name, { enumerable: true, get: () => value });
|
|
49
|
+
}
|
|
50
|
+
Object.defineProperty(data, "toJSON", { value: () => ({ ...basics }) });
|
|
51
|
+
Object.defineProperty(data, "getHighEntropyValues", {
|
|
52
|
+
value: async (hints: string[]) => {
|
|
53
|
+
const result: Record<string, unknown> = { ...basics };
|
|
54
|
+
for (const hint of hints) {
|
|
55
|
+
if (Object.hasOwn(metadata, hint)) result[hint] = metadata[hint as keyof typeof metadata];
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(Navigator.prototype, "userAgentData", {
|
|
61
|
+
configurable: true,
|
|
62
|
+
get: () => data,
|
|
63
|
+
});
|
|
64
|
+
}
|
package/src/lib/browser/index.ts
CHANGED
|
@@ -76,7 +76,14 @@ export type {
|
|
|
76
76
|
OverlapResult,
|
|
77
77
|
} from "./geometry.js";
|
|
78
78
|
export { buildLayoutLintCheck } from "./geometry.js";
|
|
79
|
-
export {
|
|
79
|
+
export {
|
|
80
|
+
AUTOMATION_DEFAULT_ARGS_TO_DROP,
|
|
81
|
+
automationDisguiseArgs,
|
|
82
|
+
installedChromeChannel,
|
|
83
|
+
installedChromePath,
|
|
84
|
+
isWSL,
|
|
85
|
+
wslHeadedLaunchArgs,
|
|
86
|
+
} from "./launch-args.js";
|
|
80
87
|
export type {
|
|
81
88
|
OverflowElement,
|
|
82
89
|
OverflowResult,
|
|
@@ -178,6 +185,7 @@ export {
|
|
|
178
185
|
type QaRunContext,
|
|
179
186
|
type QaRunCritiqueOutcome,
|
|
180
187
|
type QaRunCritiquePool,
|
|
188
|
+
type QaRunCritiqueTileTiming,
|
|
181
189
|
type QaRunInteraction,
|
|
182
190
|
type QaRunJob,
|
|
183
191
|
type QaRunJobValidation,
|
|
@@ -237,6 +245,13 @@ export {
|
|
|
237
245
|
snappedBandRects,
|
|
238
246
|
type VisualAtom,
|
|
239
247
|
} from "./tiling.js";
|
|
248
|
+
export {
|
|
249
|
+
chromeMajorFromExecutable,
|
|
250
|
+
hostFamily,
|
|
251
|
+
normalUserAgent,
|
|
252
|
+
readStoredUserAgent,
|
|
253
|
+
resolveUserAgent,
|
|
254
|
+
} from "./user-agent.js";
|
|
240
255
|
export type {
|
|
241
256
|
CheckVisibilityOptions,
|
|
242
257
|
VisibilityResult,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Chromium launch-arg helpers for environment-specific workarounds.
|
|
@@ -31,3 +31,55 @@ export function isWSL(): boolean {
|
|
|
31
31
|
export function wslHeadedLaunchArgs(): string[] {
|
|
32
32
|
return isWSL() ? ["--disable-gpu"] : [];
|
|
33
33
|
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Playwright's bundled browser is "Chrome for Testing", launched with
|
|
37
|
+
* `--enable-automation`. Both are visible to the page: the User-Agent brand
|
|
38
|
+
* list carries "Chrome for Testing" and `navigator.webdriver` reads true, so
|
|
39
|
+
* sign-in flows on sites that screen for automation (X, some banks, some
|
|
40
|
+
* Cloudflare-fronted apps) silently refuse clicks in a headed window that a
|
|
41
|
+
* person is driving. Headed sessions therefore launch the operator's real
|
|
42
|
+
* Google Chrome when one is installed and drop the automation signals.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/** Default Chromium args Playwright adds that a headed session must not carry. */
|
|
46
|
+
export const AUTOMATION_DEFAULT_ARGS_TO_DROP: readonly string[] = ["--enable-automation"];
|
|
47
|
+
|
|
48
|
+
/** Launch flags that stop Blink from reporting the automation state to pages. */
|
|
49
|
+
export function automationDisguiseArgs(): string[] {
|
|
50
|
+
return ["--disable-blink-features=AutomationControlled"];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const CHROME_PATHS: Record<string, string[]> = {
|
|
54
|
+
linux: ["/usr/bin/google-chrome", "/usr/bin/google-chrome-stable", "/opt/google/chrome/chrome"],
|
|
55
|
+
darwin: ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"],
|
|
56
|
+
win32: [
|
|
57
|
+
"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
|
|
58
|
+
"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* `"chrome"` when a stable Google Chrome install is present at a well-known
|
|
64
|
+
* path for this platform, else `undefined` (use Playwright's bundled
|
|
65
|
+
* Chromium). Playwright resolves the `chrome` channel to the same install, so
|
|
66
|
+
* the check only has to answer whether asking for it can succeed.
|
|
67
|
+
*/
|
|
68
|
+
export function installedChromeChannel(
|
|
69
|
+
platform: NodeJS.Platform = process.platform,
|
|
70
|
+
exists: (path: string) => boolean = existsSync,
|
|
71
|
+
): "chrome" | undefined {
|
|
72
|
+
return installedChromePath(platform, exists) ? "chrome" : undefined;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Filesystem path of the installed stable Google Chrome for this platform, or
|
|
77
|
+
* `undefined`. Used to spawn Chrome with nothing attached for sign-in flows
|
|
78
|
+
* whose verification vendors detect the DevTools protocol itself.
|
|
79
|
+
*/
|
|
80
|
+
export function installedChromePath(
|
|
81
|
+
platform: NodeJS.Platform = process.platform,
|
|
82
|
+
exists: (path: string) => boolean = existsSync,
|
|
83
|
+
): string | undefined {
|
|
84
|
+
return (CHROME_PATHS[platform] ?? []).find((candidate) => exists(candidate));
|
|
85
|
+
}
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
} from "./page-review-pack.js";
|
|
26
26
|
import type { QaContext } from "./qa-plan.js";
|
|
27
27
|
import type { CritiqueReusePlan } from "./qa-reuse.js";
|
|
28
|
+
import type { QaRunCritiqueTileTiming } from "./qa-run-contracts.js";
|
|
28
29
|
import { loadQaSnapshot, type QaSnapshotStoreOptions } from "./qa-snapshot.js";
|
|
29
30
|
|
|
30
31
|
export interface JudgePageReviewPackOptions {
|
|
@@ -62,6 +63,7 @@ export interface JudgedContext extends PageReviewCritiqueRecord {
|
|
|
62
63
|
export interface JudgePageReviewPackResult {
|
|
63
64
|
contexts: JudgedContext[];
|
|
64
65
|
pool: { concurrency: number; wall_time_ms: number; provider: string };
|
|
66
|
+
tile_timings: QaRunCritiqueTileTiming[];
|
|
65
67
|
tiles_total: number;
|
|
66
68
|
tiles_reviewed: number;
|
|
67
69
|
tiles_reused: number;
|
|
@@ -261,6 +263,7 @@ export async function judgePageReviewPack(
|
|
|
261
263
|
|
|
262
264
|
let meta: Record<string, unknown> | undefined;
|
|
263
265
|
let concurrency = 0;
|
|
266
|
+
const tileTimings: Array<QaRunCritiqueTileTiming | undefined> = new Array(work.length);
|
|
264
267
|
if (provider && work.length > 0) {
|
|
265
268
|
concurrency = Math.max(
|
|
266
269
|
1,
|
|
@@ -277,12 +280,15 @@ export async function judgePageReviewPack(
|
|
|
277
280
|
const entry = perContext[item.contextIndex];
|
|
278
281
|
if (!entry) continue;
|
|
279
282
|
entry.judged.add(item.tile.id);
|
|
283
|
+
const tileStarted = performance.now();
|
|
284
|
+
let tileOutcome: QaRunCritiqueTileTiming["outcome"] = "passed";
|
|
280
285
|
try {
|
|
281
286
|
const found = await provider({ url: item.url, rubric: item.rubric, tile: item.tile });
|
|
282
287
|
for (const finding of found) {
|
|
283
288
|
entry.findings.push({ ...finding, tile: item.tile.index, tile_id: item.tile.id });
|
|
284
289
|
}
|
|
285
290
|
} catch (err: unknown) {
|
|
291
|
+
tileOutcome = "failed";
|
|
286
292
|
entry.findings.push({
|
|
287
293
|
tile: item.tile.index,
|
|
288
294
|
tile_id: item.tile.id,
|
|
@@ -290,6 +296,13 @@ export async function judgePageReviewPack(
|
|
|
290
296
|
category: "provider-error",
|
|
291
297
|
description: `critique provider failed on ${item.tile.label}: ${err instanceof Error ? err.message : String(err)}`,
|
|
292
298
|
});
|
|
299
|
+
} finally {
|
|
300
|
+
tileTimings[i] = {
|
|
301
|
+
context_id: entry.record.id,
|
|
302
|
+
tile_id: item.tile.id,
|
|
303
|
+
duration_ms: Math.max(0, Math.round(performance.now() - tileStarted)),
|
|
304
|
+
outcome: tileOutcome,
|
|
305
|
+
};
|
|
293
306
|
}
|
|
294
307
|
}
|
|
295
308
|
};
|
|
@@ -360,6 +373,9 @@ export async function judgePageReviewPack(
|
|
|
360
373
|
return {
|
|
361
374
|
contexts,
|
|
362
375
|
pool: { concurrency, wall_time_ms: Date.now() - started, provider: label },
|
|
376
|
+
tile_timings: tileTimings.filter(
|
|
377
|
+
(timing): timing is QaRunCritiqueTileTiming => timing !== undefined,
|
|
378
|
+
),
|
|
363
379
|
tiles_total: tilesTotal,
|
|
364
380
|
tiles_reviewed: tilesReviewed,
|
|
365
381
|
tiles_reused: tilesReused,
|
|
@@ -145,6 +145,15 @@ export interface QaRunCritiqueLatency {
|
|
|
145
145
|
p95: number;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
/** Wall time for one tile's complete vision call, including provider retries
|
|
149
|
+
* and failover. Reused and unjudged tiles have no call and no timing entry. */
|
|
150
|
+
export interface QaRunCritiqueTileTiming {
|
|
151
|
+
context_id: string;
|
|
152
|
+
tile_id: string;
|
|
153
|
+
duration_ms: number;
|
|
154
|
+
outcome: "passed" | "failed";
|
|
155
|
+
}
|
|
156
|
+
|
|
148
157
|
/** What share of the page the critique tiles covered, lifted from the browse
|
|
149
158
|
* envelope. `capped` means the tiler dropped bands past its per-context
|
|
150
159
|
* maximum; in signoff mode that is a blocker, in review mode a flag. Across
|
|
@@ -188,6 +197,8 @@ export interface QaRunCritiquePool {
|
|
|
188
197
|
wall_time_ms: number;
|
|
189
198
|
provider: string;
|
|
190
199
|
latency_ms?: Record<string, QaRunCritiqueLatency>;
|
|
200
|
+
/** One entry per attempted tile, in context and tile order. */
|
|
201
|
+
tile_timings?: QaRunCritiqueTileTiming[];
|
|
191
202
|
}
|
|
192
203
|
|
|
193
204
|
/** Where the run's page review pack lives: the on-disk evidence an agent can
|
|
@@ -1397,6 +1397,7 @@ export async function runQaMatrix(options: QaRunMatrixOptions): Promise<QaRunRes
|
|
|
1397
1397
|
wall_time_ms: judged.pool.wall_time_ms,
|
|
1398
1398
|
provider: judged.pool.provider,
|
|
1399
1399
|
...(latency ? { latency_ms: latency } : {}),
|
|
1400
|
+
tile_timings: judged.tile_timings,
|
|
1400
1401
|
};
|
|
1401
1402
|
for (const row of judged.contexts) {
|
|
1402
1403
|
judgedById.set(row.context_id, row);
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, resolve } from "node:path";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Present as a normal browser.
|
|
8
|
+
*
|
|
9
|
+
* A desktop-Linux user agent is itself a block signal: web application
|
|
10
|
+
* firewalls commonly deny "X11; Linux" outright because almost no customer
|
|
11
|
+
* browses from desktop Linux, and headless builds announce "HeadlessChrome".
|
|
12
|
+
* Sunbelt Network's Cloudflare rule was the reported case: the same page
|
|
13
|
+
* answered 200 the moment the browser said Windows. Every Harnery page load
|
|
14
|
+
* therefore uses a user agent for the host the operator actually sits at
|
|
15
|
+
* (Windows under WSL or on Windows, macOS on a Mac), never Linux, with the
|
|
16
|
+
* Chrome major version of the browser that is really running.
|
|
17
|
+
*
|
|
18
|
+
* The resolved string is persisted at `~/.cache/harnery/user-agent.json` so
|
|
19
|
+
* every process reuses the one that works; `HARNERY_BROWSER_UA` overrides it
|
|
20
|
+
* for a run (`native` disables the override), and `--user-agent` on `browse`
|
|
21
|
+
* rewrites the stored value.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export type HostFamily = "windows" | "mac";
|
|
25
|
+
|
|
26
|
+
const STORE_PATH = resolve(homedir(), ".cache", "harnery", "user-agent.json");
|
|
27
|
+
|
|
28
|
+
/** Windows unless the operator is on a Mac. Linux never presents as Linux. */
|
|
29
|
+
export function hostFamily(platform: NodeJS.Platform = process.platform): HostFamily {
|
|
30
|
+
return platform === "darwin" ? "mac" : "windows";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** A current-shape Chrome user agent for the host family and Chrome major. */
|
|
34
|
+
export function normalUserAgent(chromeMajor: number, family: HostFamily): string {
|
|
35
|
+
const os = family === "mac" ? "Macintosh; Intel Mac OS X 10_15_7" : "Windows NT 10.0; Win64; x64";
|
|
36
|
+
return `Mozilla/5.0 (${os}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${chromeMajor}.0.0.0 Safari/537.36`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Major version from `<chrome> --version` output, or `undefined`. */
|
|
40
|
+
export function parseChromeMajor(versionOutput: string): number | undefined {
|
|
41
|
+
const match = /(\d+)\.\d+\.\d+\.\d+/.exec(versionOutput);
|
|
42
|
+
return match ? Number(match[1]) : undefined;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Ask an installed Chrome binary for its major version. */
|
|
46
|
+
export function chromeMajorFromExecutable(executable: string): number | undefined {
|
|
47
|
+
try {
|
|
48
|
+
const res = spawnSync(executable, ["--version"], { encoding: "utf8", timeout: 5000 });
|
|
49
|
+
return parseChromeMajor(`${res.stdout ?? ""}${res.stderr ?? ""}`);
|
|
50
|
+
} catch {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface StoredUserAgent {
|
|
56
|
+
userAgent: string;
|
|
57
|
+
source: "auto" | "manual";
|
|
58
|
+
chromeMajor?: number;
|
|
59
|
+
updatedAt: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function readStoredUserAgent(path: string = STORE_PATH): StoredUserAgent | undefined {
|
|
63
|
+
try {
|
|
64
|
+
if (!existsSync(path)) return undefined;
|
|
65
|
+
const parsed = JSON.parse(readFileSync(path, "utf8")) as Partial<StoredUserAgent>;
|
|
66
|
+
return typeof parsed.userAgent === "string" && parsed.userAgent.length > 0
|
|
67
|
+
? (parsed as StoredUserAgent)
|
|
68
|
+
: undefined;
|
|
69
|
+
} catch {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function writeStoredUserAgent(entry: StoredUserAgent, path: string = STORE_PATH): void {
|
|
75
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
76
|
+
writeFileSync(path, `${JSON.stringify(entry, null, 2)}\n`, { mode: 0o600 });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface ResolveUserAgentInput {
|
|
80
|
+
/** Explicit `--user-agent` value: a string, `"native"`, or `"auto"`. */
|
|
81
|
+
requested?: string;
|
|
82
|
+
/** `HARNERY_BROWSER_UA` from the environment. */
|
|
83
|
+
env?: string;
|
|
84
|
+
/** Major version of the Chrome that will actually launch, when known. */
|
|
85
|
+
chromeMajor?: number;
|
|
86
|
+
platform?: NodeJS.Platform;
|
|
87
|
+
storePath?: string;
|
|
88
|
+
now?: () => string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* The user agent to launch with, or `undefined` for the browser's native
|
|
93
|
+
* string. Precedence: explicit request, then environment, then the stored
|
|
94
|
+
* value (refreshed when the Chrome major moved), then a fresh auto value.
|
|
95
|
+
* An explicit string or `auto` request rewrites the store; `native` does not.
|
|
96
|
+
*/
|
|
97
|
+
export function resolveUserAgent(input: ResolveUserAgentInput = {}): string | undefined {
|
|
98
|
+
const now = input.now ?? (() => new Date().toISOString());
|
|
99
|
+
const family = hostFamily(input.platform);
|
|
100
|
+
const requested = input.requested?.trim();
|
|
101
|
+
if (requested && requested !== "auto") {
|
|
102
|
+
if (requested === "native") return undefined;
|
|
103
|
+
writeStoredUserAgent(
|
|
104
|
+
{ userAgent: requested, source: "manual", updatedAt: now() },
|
|
105
|
+
input.storePath,
|
|
106
|
+
);
|
|
107
|
+
return requested;
|
|
108
|
+
}
|
|
109
|
+
const env = input.env?.trim();
|
|
110
|
+
if (env && requested !== "auto") {
|
|
111
|
+
return env === "native" ? undefined : env;
|
|
112
|
+
}
|
|
113
|
+
const stored = readStoredUserAgent(input.storePath);
|
|
114
|
+
if (
|
|
115
|
+
stored &&
|
|
116
|
+
requested !== "auto" &&
|
|
117
|
+
(stored.source === "manual" ||
|
|
118
|
+
input.chromeMajor === undefined ||
|
|
119
|
+
stored.chromeMajor === input.chromeMajor)
|
|
120
|
+
) {
|
|
121
|
+
return stored.userAgent;
|
|
122
|
+
}
|
|
123
|
+
const major = input.chromeMajor ?? stored?.chromeMajor ?? 149;
|
|
124
|
+
const userAgent = normalUserAgent(major, family);
|
|
125
|
+
writeStoredUserAgent(
|
|
126
|
+
{ userAgent, source: "auto", chromeMajor: major, updatedAt: now() },
|
|
127
|
+
input.storePath,
|
|
128
|
+
);
|
|
129
|
+
return userAgent;
|
|
130
|
+
}
|