@reticlehq/server 2.0.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/LICENSE +105 -0
- package/README.md +17 -0
- package/dist/bridge-security.d.ts +23 -0
- package/dist/bridge-security.d.ts.map +1 -0
- package/dist/bridge-security.js +44 -0
- package/dist/bridge-security.js.map +1 -0
- package/dist/bridge.d.ts +42 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +281 -0
- package/dist/bridge.js.map +1 -0
- package/dist/bridge.test-harness.d.ts +42 -0
- package/dist/bridge.test-harness.d.ts.map +1 -0
- package/dist/bridge.test-harness.js +192 -0
- package/dist/bridge.test-harness.js.map +1 -0
- package/dist/cli-launch.d.ts +53 -0
- package/dist/cli-launch.d.ts.map +1 -0
- package/dist/cli-launch.js +109 -0
- package/dist/cli-launch.js.map +1 -0
- package/dist/cli-parse.d.ts +74 -0
- package/dist/cli-parse.d.ts.map +1 -0
- package/dist/cli-parse.js +321 -0
- package/dist/cli-parse.js.map +1 -0
- package/dist/cli-port.d.ts +26 -0
- package/dist/cli-port.d.ts.map +1 -0
- package/dist/cli-port.js +57 -0
- package/dist/cli-port.js.map +1 -0
- package/dist/cli-verify.d.ts +46 -0
- package/dist/cli-verify.d.ts.map +1 -0
- package/dist/cli-verify.js +181 -0
- package/dist/cli-verify.js.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +337 -0
- package/dist/cli.js.map +1 -0
- package/dist/cloud/cloud-sync.d.ts +50 -0
- package/dist/cloud/cloud-sync.d.ts.map +1 -0
- package/dist/cloud/cloud-sync.js +47 -0
- package/dist/cloud/cloud-sync.js.map +1 -0
- package/dist/crawl/crawl-tools.d.ts +8 -0
- package/dist/crawl/crawl-tools.d.ts.map +1 -0
- package/dist/crawl/crawl-tools.js +61 -0
- package/dist/crawl/crawl-tools.js.map +1 -0
- package/dist/crawl/crawl.d.ts +45 -0
- package/dist/crawl/crawl.d.ts.map +1 -0
- package/dist/crawl/crawl.js +106 -0
- package/dist/crawl/crawl.js.map +1 -0
- package/dist/daemon-resilience.d.ts +17 -0
- package/dist/daemon-resilience.d.ts.map +1 -0
- package/dist/daemon-resilience.js +23 -0
- package/dist/daemon-resilience.js.map +1 -0
- package/dist/daemon.d.ts +26 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +122 -0
- package/dist/daemon.js.map +1 -0
- package/dist/domain/domain-model.d.ts +64 -0
- package/dist/domain/domain-model.d.ts.map +1 -0
- package/dist/domain/domain-model.js +127 -0
- package/dist/domain/domain-model.js.map +1 -0
- package/dist/domain/domain-tools.d.ts +9 -0
- package/dist/domain/domain-tools.d.ts.map +1 -0
- package/dist/domain/domain-tools.js +66 -0
- package/dist/domain/domain-tools.js.map +1 -0
- package/dist/domain/flow-risk.d.ts +34 -0
- package/dist/domain/flow-risk.d.ts.map +1 -0
- package/dist/domain/flow-risk.js +81 -0
- package/dist/domain/flow-risk.js.map +1 -0
- package/dist/ee/audit-log.d.ts +15 -0
- package/dist/ee/audit-log.d.ts.map +1 -0
- package/dist/ee/audit-log.js +12 -0
- package/dist/ee/audit-log.js.map +1 -0
- package/dist/events/event-filters.d.ts +65 -0
- package/dist/events/event-filters.d.ts.map +1 -0
- package/dist/events/event-filters.js +98 -0
- package/dist/events/event-filters.js.map +1 -0
- package/dist/events/predicate-eval.d.ts +91 -0
- package/dist/events/predicate-eval.d.ts.map +1 -0
- package/dist/events/predicate-eval.js +299 -0
- package/dist/events/predicate-eval.js.map +1 -0
- package/dist/events/predicate.d.ts +19 -0
- package/dist/events/predicate.d.ts.map +1 -0
- package/dist/events/predicate.js +188 -0
- package/dist/events/predicate.js.map +1 -0
- package/dist/events/reaction.d.ts +34 -0
- package/dist/events/reaction.d.ts.map +1 -0
- package/dist/events/reaction.js +60 -0
- package/dist/events/reaction.js.map +1 -0
- package/dist/events/ring-buffer.d.ts +32 -0
- package/dist/events/ring-buffer.d.ts.map +1 -0
- package/dist/events/ring-buffer.js +75 -0
- package/dist/events/ring-buffer.js.map +1 -0
- package/dist/flows/annotate-tools.d.ts +16 -0
- package/dist/flows/annotate-tools.d.ts.map +1 -0
- package/dist/flows/annotate-tools.js +136 -0
- package/dist/flows/annotate-tools.js.map +1 -0
- package/dist/flows/annotate.d.ts +22 -0
- package/dist/flows/annotate.d.ts.map +1 -0
- package/dist/flows/annotate.js +134 -0
- package/dist/flows/annotate.js.map +1 -0
- package/dist/flows/annotation-store.d.ts +23 -0
- package/dist/flows/annotation-store.d.ts.map +1 -0
- package/dist/flows/annotation-store.js +51 -0
- package/dist/flows/annotation-store.js.map +1 -0
- package/dist/flows/decision.d.ts +13 -0
- package/dist/flows/decision.d.ts.map +1 -0
- package/dist/flows/decision.js +111 -0
- package/dist/flows/decision.js.map +1 -0
- package/dist/flows/flow-classify.d.ts +52 -0
- package/dist/flows/flow-classify.d.ts.map +1 -0
- package/dist/flows/flow-classify.js +99 -0
- package/dist/flows/flow-classify.js.map +1 -0
- package/dist/flows/flow-replay-run.d.ts +15 -0
- package/dist/flows/flow-replay-run.d.ts.map +1 -0
- package/dist/flows/flow-replay-run.js +120 -0
- package/dist/flows/flow-replay-run.js.map +1 -0
- package/dist/flows/flow-replay.d.ts +49 -0
- package/dist/flows/flow-replay.d.ts.map +1 -0
- package/dist/flows/flow-replay.js +391 -0
- package/dist/flows/flow-replay.js.map +1 -0
- package/dist/flows/flow-report.d.ts +23 -0
- package/dist/flows/flow-report.d.ts.map +1 -0
- package/dist/flows/flow-report.js +106 -0
- package/dist/flows/flow-report.js.map +1 -0
- package/dist/flows/flow-scope.d.ts +25 -0
- package/dist/flows/flow-scope.d.ts.map +1 -0
- package/dist/flows/flow-scope.js +32 -0
- package/dist/flows/flow-scope.js.map +1 -0
- package/dist/flows/flow-success.d.ts +33 -0
- package/dist/flows/flow-success.d.ts.map +1 -0
- package/dist/flows/flow-success.js +131 -0
- package/dist/flows/flow-success.js.map +1 -0
- package/dist/flows/flow-tools.d.ts +4 -0
- package/dist/flows/flow-tools.d.ts.map +1 -0
- package/dist/flows/flow-tools.js +460 -0
- package/dist/flows/flow-tools.js.map +1 -0
- package/dist/flows/flows.d.ts +86 -0
- package/dist/flows/flows.d.ts.map +1 -0
- package/dist/flows/flows.js +319 -0
- package/dist/flows/flows.js.map +1 -0
- package/dist/flows/heal.d.ts +43 -0
- package/dist/flows/heal.d.ts.map +1 -0
- package/dist/flows/heal.js +98 -0
- package/dist/flows/heal.js.map +1 -0
- package/dist/flows/recordings.d.ts +46 -0
- package/dist/flows/recordings.d.ts.map +1 -0
- package/dist/flows/recordings.js +43 -0
- package/dist/flows/recordings.js.map +1 -0
- package/dist/flows/replay.d.ts +23 -0
- package/dist/flows/replay.d.ts.map +1 -0
- package/dist/flows/replay.js +160 -0
- package/dist/flows/replay.js.map +1 -0
- package/dist/http-server.d.ts +39 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +145 -0
- package/dist/http-server.js.map +1 -0
- package/dist/idle-shutdown.d.ts +34 -0
- package/dist/idle-shutdown.d.ts.map +1 -0
- package/dist/idle-shutdown.js +68 -0
- package/dist/idle-shutdown.js.map +1 -0
- package/dist/index.d.ts +135 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +371 -0
- package/dist/index.js.map +1 -0
- package/dist/init/cursor.d.ts +25 -0
- package/dist/init/cursor.d.ts.map +1 -0
- package/dist/init/cursor.js +49 -0
- package/dist/init/cursor.js.map +1 -0
- package/dist/init/detect.d.ts +49 -0
- package/dist/init/detect.d.ts.map +1 -0
- package/dist/init/detect.js +84 -0
- package/dist/init/detect.js.map +1 -0
- package/dist/init/mcp.d.ts +40 -0
- package/dist/init/mcp.d.ts.map +1 -0
- package/dist/init/mcp.js +55 -0
- package/dist/init/mcp.js.map +1 -0
- package/dist/init/node-io.d.ts +8 -0
- package/dist/init/node-io.d.ts.map +1 -0
- package/dist/init/node-io.js +57 -0
- package/dist/init/node-io.js.map +1 -0
- package/dist/init/plan.d.ts +72 -0
- package/dist/init/plan.d.ts.map +1 -0
- package/dist/init/plan.js +280 -0
- package/dist/init/plan.js.map +1 -0
- package/dist/init/project-id.d.ts +17 -0
- package/dist/init/project-id.d.ts.map +1 -0
- package/dist/init/project-id.js +38 -0
- package/dist/init/project-id.js.map +1 -0
- package/dist/init/run.d.ts +42 -0
- package/dist/init/run.d.ts.map +1 -0
- package/dist/init/run.js +171 -0
- package/dist/init/run.js.map +1 -0
- package/dist/init/snippets.d.ts +33 -0
- package/dist/init/snippets.d.ts.map +1 -0
- package/dist/init/snippets.js +117 -0
- package/dist/init/snippets.js.map +1 -0
- package/dist/init/vite-config.d.ts +25 -0
- package/dist/init/vite-config.d.ts.map +1 -0
- package/dist/init/vite-config.js +45 -0
- package/dist/init/vite-config.js.map +1 -0
- package/dist/input/network-mock-tools.d.ts +3 -0
- package/dist/input/network-mock-tools.d.ts.map +1 -0
- package/dist/input/network-mock-tools.js +94 -0
- package/dist/input/network-mock-tools.js.map +1 -0
- package/dist/input/network-mock.d.ts +55 -0
- package/dist/input/network-mock.d.ts.map +1 -0
- package/dist/input/network-mock.js +62 -0
- package/dist/input/network-mock.js.map +1 -0
- package/dist/input/real-input.d.ts +174 -0
- package/dist/input/real-input.d.ts.map +1 -0
- package/dist/input/real-input.js +289 -0
- package/dist/input/real-input.js.map +1 -0
- package/dist/input/scroll-find.d.ts +41 -0
- package/dist/input/scroll-find.d.ts.map +1 -0
- package/dist/input/scroll-find.js +59 -0
- package/dist/input/scroll-find.js.map +1 -0
- package/dist/input/scroll-tools.d.ts +8 -0
- package/dist/input/scroll-tools.d.ts.map +1 -0
- package/dist/input/scroll-tools.js +68 -0
- package/dist/input/scroll-tools.js.map +1 -0
- package/dist/input/viewport-tools.d.ts +3 -0
- package/dist/input/viewport-tools.d.ts.map +1 -0
- package/dist/input/viewport-tools.js +65 -0
- package/dist/input/viewport-tools.js.map +1 -0
- package/dist/license/license.d.ts +108 -0
- package/dist/license/license.d.ts.map +1 -0
- package/dist/license/license.js +203 -0
- package/dist/license/license.js.map +1 -0
- package/dist/log.d.ts +6 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +9 -0
- package/dist/log.js.map +1 -0
- package/dist/mcp-proxy.d.ts +16 -0
- package/dist/mcp-proxy.d.ts.map +1 -0
- package/dist/mcp-proxy.js +168 -0
- package/dist/mcp-proxy.js.map +1 -0
- package/dist/mcp.d.ts +14 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +101 -0
- package/dist/mcp.js.map +1 -0
- package/dist/pairing-token.d.ts +28 -0
- package/dist/pairing-token.d.ts.map +1 -0
- package/dist/pairing-token.js +62 -0
- package/dist/pairing-token.js.map +1 -0
- package/dist/pool/browser-pool.d.ts +90 -0
- package/dist/pool/browser-pool.d.ts.map +1 -0
- package/dist/pool/browser-pool.js +221 -0
- package/dist/pool/browser-pool.js.map +1 -0
- package/dist/pool/lease-reaper.d.ts +16 -0
- package/dist/pool/lease-reaper.d.ts.map +1 -0
- package/dist/pool/lease-reaper.js +41 -0
- package/dist/pool/lease-reaper.js.map +1 -0
- package/dist/pool/playwright-launcher.d.ts +19 -0
- package/dist/pool/playwright-launcher.d.ts.map +1 -0
- package/dist/pool/playwright-launcher.js +51 -0
- package/dist/pool/playwright-launcher.js.map +1 -0
- package/dist/project/baselines.d.ts +22 -0
- package/dist/project/baselines.d.ts.map +1 -0
- package/dist/project/baselines.js +45 -0
- package/dist/project/baselines.js.map +1 -0
- package/dist/project/fs-port.d.ts +27 -0
- package/dist/project/fs-port.d.ts.map +1 -0
- package/dist/project/fs-port.js +32 -0
- package/dist/project/fs-port.js.map +1 -0
- package/dist/project/project-store.d.ts +32 -0
- package/dist/project/project-store.d.ts.map +1 -0
- package/dist/project/project-store.js +127 -0
- package/dist/project/project-store.js.map +1 -0
- package/dist/project/project-tools.d.ts +9 -0
- package/dist/project/project-tools.d.ts.map +1 -0
- package/dist/project/project-tools.js +118 -0
- package/dist/project/project-tools.js.map +1 -0
- package/dist/project/reticle-dir.d.ts +61 -0
- package/dist/project/reticle-dir.d.ts.map +1 -0
- package/dist/project/reticle-dir.js +144 -0
- package/dist/project/reticle-dir.js.map +1 -0
- package/dist/runs/build-verification-run.d.ts +30 -0
- package/dist/runs/build-verification-run.d.ts.map +1 -0
- package/dist/runs/build-verification-run.js +71 -0
- package/dist/runs/build-verification-run.js.map +1 -0
- package/dist/runs/profile-redact.d.ts +16 -0
- package/dist/runs/profile-redact.d.ts.map +1 -0
- package/dist/runs/profile-redact.js +32 -0
- package/dist/runs/profile-redact.js.map +1 -0
- package/dist/runs/render-report.d.ts +9 -0
- package/dist/runs/render-report.d.ts.map +1 -0
- package/dist/runs/render-report.js +70 -0
- package/dist/runs/render-report.js.map +1 -0
- package/dist/runs/repair-prompt.d.ts +15 -0
- package/dist/runs/repair-prompt.d.ts.map +1 -0
- package/dist/runs/repair-prompt.js +59 -0
- package/dist/runs/repair-prompt.js.map +1 -0
- package/dist/runs/replay-mapping.d.ts +12 -0
- package/dist/runs/replay-mapping.d.ts.map +1 -0
- package/dist/runs/replay-mapping.js +35 -0
- package/dist/runs/replay-mapping.js.map +1 -0
- package/dist/runs/reticle-runner.d.ts +48 -0
- package/dist/runs/reticle-runner.d.ts.map +1 -0
- package/dist/runs/reticle-runner.js +56 -0
- package/dist/runs/reticle-runner.js.map +1 -0
- package/dist/runs/risk-classify.d.ts +27 -0
- package/dist/runs/risk-classify.d.ts.map +1 -0
- package/dist/runs/risk-classify.js +76 -0
- package/dist/runs/risk-classify.js.map +1 -0
- package/dist/runs/run-store.d.ts +40 -0
- package/dist/runs/run-store.d.ts.map +1 -0
- package/dist/runs/run-store.js +118 -0
- package/dist/runs/run-store.js.map +1 -0
- package/dist/runs/run-tools.d.ts +10 -0
- package/dist/runs/run-tools.d.ts.map +1 -0
- package/dist/runs/run-tools.js +69 -0
- package/dist/runs/run-tools.js.map +1 -0
- package/dist/runs/runner-port.d.ts +14 -0
- package/dist/runs/runner-port.d.ts.map +1 -0
- package/dist/runs/runner-port.js +23 -0
- package/dist/runs/runner-port.js.map +1 -0
- package/dist/runs/verify-http.d.ts +34 -0
- package/dist/runs/verify-http.d.ts.map +1 -0
- package/dist/runs/verify-http.js +102 -0
- package/dist/runs/verify-http.js.map +1 -0
- package/dist/runs/verify-server.d.ts +26 -0
- package/dist/runs/verify-server.d.ts.map +1 -0
- package/dist/runs/verify-server.js +99 -0
- package/dist/runs/verify-server.js.map +1 -0
- package/dist/server-version.d.ts +3 -0
- package/dist/server-version.d.ts.map +1 -0
- package/dist/server-version.js +5 -0
- package/dist/server-version.js.map +1 -0
- package/dist/session/control-envelope.d.ts +49 -0
- package/dist/session/control-envelope.d.ts.map +1 -0
- package/dist/session/control-envelope.js +44 -0
- package/dist/session/control-envelope.js.map +1 -0
- package/dist/session/live-control-tools.d.ts +16 -0
- package/dist/session/live-control-tools.d.ts.map +1 -0
- package/dist/session/live-control-tools.js +204 -0
- package/dist/session/live-control-tools.js.map +1 -0
- package/dist/session/output-budget.d.ts +41 -0
- package/dist/session/output-budget.d.ts.map +1 -0
- package/dist/session/output-budget.js +54 -0
- package/dist/session/output-budget.js.map +1 -0
- package/dist/session/presenter-args.d.ts +8 -0
- package/dist/session/presenter-args.d.ts.map +1 -0
- package/dist/session/presenter-args.js +15 -0
- package/dist/session/presenter-args.js.map +1 -0
- package/dist/session/review-store.d.ts +40 -0
- package/dist/session/review-store.d.ts.map +1 -0
- package/dist/session/review-store.js +61 -0
- package/dist/session/review-store.js.map +1 -0
- package/dist/session/session-health.d.ts +22 -0
- package/dist/session/session-health.d.ts.map +1 -0
- package/dist/session/session-health.js +26 -0
- package/dist/session/session-health.js.map +1 -0
- package/dist/session/session-manager.d.ts +43 -0
- package/dist/session/session-manager.d.ts.map +1 -0
- package/dist/session/session-manager.js +155 -0
- package/dist/session/session-manager.js.map +1 -0
- package/dist/session/session-readiness.d.ts +35 -0
- package/dist/session/session-readiness.d.ts.map +1 -0
- package/dist/session/session-readiness.js +32 -0
- package/dist/session/session-readiness.js.map +1 -0
- package/dist/session/session-reaper.d.ts +37 -0
- package/dist/session/session-reaper.d.ts.map +1 -0
- package/dist/session/session-reaper.js +94 -0
- package/dist/session/session-reaper.js.map +1 -0
- package/dist/session/session-recommendation.d.ts +18 -0
- package/dist/session/session-recommendation.d.ts.map +1 -0
- package/dist/session/session-recommendation.js +14 -0
- package/dist/session/session-recommendation.js.map +1 -0
- package/dist/session/session-tools.d.ts +9 -0
- package/dist/session/session-tools.d.ts.map +1 -0
- package/dist/session/session-tools.js +43 -0
- package/dist/session/session-tools.js.map +1 -0
- package/dist/session/session.d.ts +166 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/session/session.js +408 -0
- package/dist/session/session.js.map +1 -0
- package/dist/session/state-select.d.ts +8 -0
- package/dist/session/state-select.d.ts.map +1 -0
- package/dist/session/state-select.js +8 -0
- package/dist/session/state-select.js.map +1 -0
- package/dist/token-auth.d.ts +24 -0
- package/dist/token-auth.d.ts.map +1 -0
- package/dist/token-auth.js +71 -0
- package/dist/token-auth.js.map +1 -0
- package/dist/tools/act-tools.d.ts +3 -0
- package/dist/tools/act-tools.d.ts.map +1 -0
- package/dist/tools/act-tools.js +327 -0
- package/dist/tools/act-tools.js.map +1 -0
- package/dist/tools/act-view.d.ts +19 -0
- package/dist/tools/act-view.d.ts.map +1 -0
- package/dist/tools/act-view.js +46 -0
- package/dist/tools/act-view.js.map +1 -0
- package/dist/tools/assert-grade.d.ts +21 -0
- package/dist/tools/assert-grade.d.ts.map +1 -0
- package/dist/tools/assert-grade.js +52 -0
- package/dist/tools/assert-grade.js.map +1 -0
- package/dist/tools/browser-tools.d.ts +3 -0
- package/dist/tools/browser-tools.d.ts.map +1 -0
- package/dist/tools/browser-tools.js +52 -0
- package/dist/tools/browser-tools.js.map +1 -0
- package/dist/tools/contract-tools.d.ts +8 -0
- package/dist/tools/contract-tools.d.ts.map +1 -0
- package/dist/tools/contract-tools.js +62 -0
- package/dist/tools/contract-tools.js.map +1 -0
- package/dist/tools/dynamic-tools.d.ts +7 -0
- package/dist/tools/dynamic-tools.d.ts.map +1 -0
- package/dist/tools/dynamic-tools.js +103 -0
- package/dist/tools/dynamic-tools.js.map +1 -0
- package/dist/tools/error-recovery.d.ts +31 -0
- package/dist/tools/error-recovery.d.ts.map +1 -0
- package/dist/tools/error-recovery.js +52 -0
- package/dist/tools/error-recovery.js.map +1 -0
- package/dist/tools/invoke-tool.d.ts +23 -0
- package/dist/tools/invoke-tool.d.ts.map +1 -0
- package/dist/tools/invoke-tool.js +99 -0
- package/dist/tools/invoke-tool.js.map +1 -0
- package/dist/tools/lease-tools.d.ts +31 -0
- package/dist/tools/lease-tools.d.ts.map +1 -0
- package/dist/tools/lease-tools.js +164 -0
- package/dist/tools/lease-tools.js.map +1 -0
- package/dist/tools/observe-tools.d.ts +3 -0
- package/dist/tools/observe-tools.d.ts.map +1 -0
- package/dist/tools/observe-tools.js +259 -0
- package/dist/tools/observe-tools.js.map +1 -0
- package/dist/tools/profiles.d.ts +33 -0
- package/dist/tools/profiles.d.ts.map +1 -0
- package/dist/tools/profiles.js +105 -0
- package/dist/tools/profiles.js.map +1 -0
- package/dist/tools/query-paginate.d.ts +15 -0
- package/dist/tools/query-paginate.d.ts.map +1 -0
- package/dist/tools/query-paginate.js +31 -0
- package/dist/tools/query-paginate.js.map +1 -0
- package/dist/tools/read-tools.d.ts +3 -0
- package/dist/tools/read-tools.d.ts.map +1 -0
- package/dist/tools/read-tools.js +329 -0
- package/dist/tools/read-tools.js.map +1 -0
- package/dist/tools/snapshot-delta.d.ts +59 -0
- package/dist/tools/snapshot-delta.d.ts.map +1 -0
- package/dist/tools/snapshot-delta.js +0 -0
- package/dist/tools/snapshot-delta.js.map +1 -0
- package/dist/tools/tool-invoker.d.ts +15 -0
- package/dist/tools/tool-invoker.d.ts.map +1 -0
- package/dist/tools/tool-invoker.js +20 -0
- package/dist/tools/tool-invoker.js.map +1 -0
- package/dist/tools/tool-kit.d.ts +60 -0
- package/dist/tools/tool-kit.d.ts.map +1 -0
- package/dist/tools/tool-kit.js +33 -0
- package/dist/tools/tool-kit.js.map +1 -0
- package/dist/tools/tool-names.d.ts +89 -0
- package/dist/tools/tool-names.d.ts.map +1 -0
- package/dist/tools/tool-names.js +88 -0
- package/dist/tools/tool-names.js.map +1 -0
- package/dist/tools/tools-helpers.d.ts +12 -0
- package/dist/tools/tools-helpers.d.ts.map +1 -0
- package/dist/tools/tools-helpers.js +22 -0
- package/dist/tools/tools-helpers.js.map +1 -0
- package/dist/tools/tools.d.ts +4 -0
- package/dist/tools/tools.d.ts.map +1 -0
- package/dist/tools/tools.js +268 -0
- package/dist/tools/tools.js.map +1 -0
- package/dist/update/update-checker.d.ts +20 -0
- package/dist/update/update-checker.d.ts.map +1 -0
- package/dist/update/update-checker.js +94 -0
- package/dist/update/update-checker.js.map +1 -0
- package/dist/update/update-tools.d.ts +3 -0
- package/dist/update/update-tools.d.ts.map +1 -0
- package/dist/update/update-tools.js +94 -0
- package/dist/update/update-tools.js.map +1 -0
- package/dist/update/updater.d.ts +31 -0
- package/dist/update/updater.d.ts.map +1 -0
- package/dist/update/updater.js +120 -0
- package/dist/update/updater.js.map +1 -0
- package/dist/visual/visual-diff.d.ts +46 -0
- package/dist/visual/visual-diff.d.ts.map +1 -0
- package/dist/visual/visual-diff.js +100 -0
- package/dist/visual/visual-diff.js.map +1 -0
- package/dist/visual/visual-store.d.ts +22 -0
- package/dist/visual/visual-store.d.ts.map +1 -0
- package/dist/visual/visual-store.js +60 -0
- package/dist/visual/visual-store.js.map +1 -0
- package/dist/visual/visual-tools.d.ts +9 -0
- package/dist/visual/visual-tools.d.ts.map +1 -0
- package/dist/visual/visual-tools.js +182 -0
- package/dist/visual/visual-tools.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { FlowExpect } from '@reticlehq/core';
|
|
2
|
+
/** One captured agent action, normalized for replay. */
|
|
3
|
+
export interface RecordedStep {
|
|
4
|
+
/** ReticleTool.ACT | ReticleTool.ACT_SEQUENCE */
|
|
5
|
+
tool: string;
|
|
6
|
+
/** Normalized args: refs replaced by { by:'testid', value } where resolvable. */
|
|
7
|
+
args: Record<string, unknown>;
|
|
8
|
+
/** false if any ref could not be normalized to a testid (replay only valid in-session). */
|
|
9
|
+
stable: boolean;
|
|
10
|
+
/** Optional post-condition annotation carried into the on-disk flow's expect. */
|
|
11
|
+
expect?: FlowExpect;
|
|
12
|
+
}
|
|
13
|
+
interface ActiveRecording {
|
|
14
|
+
cursor: number;
|
|
15
|
+
steps: RecordedStep[];
|
|
16
|
+
}
|
|
17
|
+
/** A finished, replayable program compiled from a recording. */
|
|
18
|
+
export interface CompiledProgram {
|
|
19
|
+
name: string;
|
|
20
|
+
version: number;
|
|
21
|
+
steps: RecordedStep[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Tracks in-flight recordings (name -> { buffer cursor at record_start, captured steps })
|
|
25
|
+
* and the last compiled program per name (for reticle_replay).
|
|
26
|
+
*/
|
|
27
|
+
export declare class RecordingStore {
|
|
28
|
+
#private;
|
|
29
|
+
start(name: string, cursor: number): void;
|
|
30
|
+
isRecording(name: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Number of steps captured so far in the named ACTIVE recording (0 if it
|
|
33
|
+
* exists but is empty, undefined if there is no active recording by that name). Lets the annotate
|
|
34
|
+
* compiler target the LAST captured step without exposing the mutable step array.
|
|
35
|
+
*/
|
|
36
|
+
stepCount(name: string): number | undefined;
|
|
37
|
+
/** Append a captured step to every active recording (steps belong to all in-flight spans). */
|
|
38
|
+
capture(step: RecordedStep): void;
|
|
39
|
+
/** Returns the active recording (cursor + steps) and clears it, or undefined if not recording. */
|
|
40
|
+
stop(name: string): ActiveRecording | undefined;
|
|
41
|
+
saveCompiled(program: CompiledProgram): void;
|
|
42
|
+
getCompiled(name: string): CompiledProgram | undefined;
|
|
43
|
+
active(): string[];
|
|
44
|
+
}
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=recordings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recordings.d.ts","sourceRoot":"","sources":["../../src/flows/recordings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,wDAAwD;AACxD,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,2FAA2F;IAC3F,MAAM,EAAE,OAAO,CAAC;IAChB,iFAAiF;IACjF,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,gEAAgE;AAChE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED;;;GAGG;AACH,qBAAa,cAAc;;IAIzB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAIzC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIlC;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI3C,8FAA8F;IAC9F,OAAO,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAIjC,kGAAkG;IAClG,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAM/C,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAI5C,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAItD,MAAM,IAAI,MAAM,EAAE;CAGnB"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tracks in-flight recordings (name -> { buffer cursor at record_start, captured steps })
|
|
3
|
+
* and the last compiled program per name (for reticle_replay).
|
|
4
|
+
*/
|
|
5
|
+
export class RecordingStore {
|
|
6
|
+
#active = new Map();
|
|
7
|
+
#compiled = new Map();
|
|
8
|
+
start(name, cursor) {
|
|
9
|
+
this.#active.set(name, { cursor, steps: [] });
|
|
10
|
+
}
|
|
11
|
+
isRecording(name) {
|
|
12
|
+
return this.#active.has(name);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Number of steps captured so far in the named ACTIVE recording (0 if it
|
|
16
|
+
* exists but is empty, undefined if there is no active recording by that name). Lets the annotate
|
|
17
|
+
* compiler target the LAST captured step without exposing the mutable step array.
|
|
18
|
+
*/
|
|
19
|
+
stepCount(name) {
|
|
20
|
+
return this.#active.get(name)?.steps.length;
|
|
21
|
+
}
|
|
22
|
+
/** Append a captured step to every active recording (steps belong to all in-flight spans). */
|
|
23
|
+
capture(step) {
|
|
24
|
+
for (const rec of this.#active.values())
|
|
25
|
+
rec.steps.push(step);
|
|
26
|
+
}
|
|
27
|
+
/** Returns the active recording (cursor + steps) and clears it, or undefined if not recording. */
|
|
28
|
+
stop(name) {
|
|
29
|
+
const rec = this.#active.get(name);
|
|
30
|
+
this.#active.delete(name);
|
|
31
|
+
return rec;
|
|
32
|
+
}
|
|
33
|
+
saveCompiled(program) {
|
|
34
|
+
this.#compiled.set(program.name, program);
|
|
35
|
+
}
|
|
36
|
+
getCompiled(name) {
|
|
37
|
+
return this.#compiled.get(name);
|
|
38
|
+
}
|
|
39
|
+
active() {
|
|
40
|
+
return [...this.#active.keys()];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=recordings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recordings.js","sourceRoot":"","sources":["../../src/flows/recordings.ts"],"names":[],"mappings":"AA0BA;;;GAGG;AACH,MAAM,OAAO,cAAc;IAChB,OAAO,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC7C,SAAS,GAAG,IAAI,GAAG,EAA2B,CAAC;IAExD,KAAK,CAAC,IAAY,EAAE,MAAc;QAChC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,WAAW,CAAC,IAAY;QACtB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED;;;;OAIG;IACH,SAAS,CAAC,IAAY;QACpB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC;IAC9C,CAAC;IAED,8FAA8F;IAC9F,OAAO,CAAC,IAAkB;QACxB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;YAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChE,CAAC;IAED,kGAAkG;IAClG,IAAI,CAAC,IAAY;QACf,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC1B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,YAAY,CAAC,OAAwB;QACnC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,WAAW,CAAC,IAAY;QACtB,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,MAAM;QACJ,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAClC,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { RecordedStep, CompiledProgram } from './recordings.js';
|
|
2
|
+
import type { Session } from '../session/session.js';
|
|
3
|
+
/** A destructive-action confirmation is one-shot and must never persist into a recording. */
|
|
4
|
+
export declare function replayActionArgs(value: unknown, confirmDangerous?: boolean): Record<string, unknown>;
|
|
5
|
+
/**
|
|
6
|
+
* Compile a single reticle_act invocation into a normalized RecordedStep using the action result. Anchor
|
|
7
|
+
* priority mirrors synthesizeAnchor: a data-testid is the gold standard; failing that, the element's
|
|
8
|
+
* component identity / source location (the AUTO-ANCHOR) keeps the step STABLE instead of degrading to
|
|
9
|
+
* a volatile ref. Only when neither is available is the step ref-bound (in-session only).
|
|
10
|
+
*/
|
|
11
|
+
export declare function compileActStep(args: Record<string, unknown>, res: unknown): RecordedStep;
|
|
12
|
+
/** Compile an reticle_act_sequence invocation, normalizing each sub-step to its testid where resolvable. */
|
|
13
|
+
export declare function compileSequenceStep(args: Record<string, unknown>, res: unknown): RecordedStep;
|
|
14
|
+
interface ReplayStepResult {
|
|
15
|
+
tool: string;
|
|
16
|
+
ok: boolean;
|
|
17
|
+
error?: string;
|
|
18
|
+
note?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Re-execute every step of a compiled program in order, stopping at the first failure. */
|
|
21
|
+
export declare function replayProgram(session: Session, program: CompiledProgram, confirmDangerous?: boolean): Promise<ReplayStepResult[]>;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=replay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/flows/replay.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAUrD,6FAA6F;AAC7F,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,OAAO,EACd,gBAAgB,UAAQ,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKzB;AAWD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,GAAG,YAAY,CAyBxF;AAUD,4GAA4G;AAC5G,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,GAAG,YAAY,CAkB7F;AA2BD,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,2FAA2F;AAC3F,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,eAAe,EACxB,gBAAgB,UAAQ,GACvB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAyC7B"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { DANGEROUS_ACTION_CONFIRM_ARG, ReticleCommand, QueryBy } from '@reticlehq/core';
|
|
2
|
+
import { ReticleTool } from '../tools/tool-names.js';
|
|
3
|
+
function asString(value) {
|
|
4
|
+
return typeof value === 'string' ? value : undefined;
|
|
5
|
+
}
|
|
6
|
+
function asRecord(value) {
|
|
7
|
+
return typeof value === 'object' && value !== null ? value : {};
|
|
8
|
+
}
|
|
9
|
+
/** A destructive-action confirmation is one-shot and must never persist into a recording. */
|
|
10
|
+
export function replayActionArgs(value, confirmDangerous = false) {
|
|
11
|
+
const args = { ...asRecord(value) };
|
|
12
|
+
delete args[DANGEROUS_ACTION_CONFIRM_ARG];
|
|
13
|
+
if (confirmDangerous)
|
|
14
|
+
args[DANGEROUS_ACTION_CONFIRM_ARG] = true;
|
|
15
|
+
return args;
|
|
16
|
+
}
|
|
17
|
+
/** The element's source location from an action result, when the framework stamped one. */
|
|
18
|
+
function sourceFromResult(res) {
|
|
19
|
+
const source = asRecord(res['source']);
|
|
20
|
+
if (typeof source['file'] !== 'string' || typeof source['line'] !== 'number')
|
|
21
|
+
return undefined;
|
|
22
|
+
const out = { file: source['file'], line: source['line'] };
|
|
23
|
+
if (typeof source['column'] === 'number')
|
|
24
|
+
out['column'] = source['column'];
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Compile a single reticle_act invocation into a normalized RecordedStep using the action result. Anchor
|
|
29
|
+
* priority mirrors synthesizeAnchor: a data-testid is the gold standard; failing that, the element's
|
|
30
|
+
* component identity / source location (the AUTO-ANCHOR) keeps the step STABLE instead of degrading to
|
|
31
|
+
* a volatile ref. Only when neither is available is the step ref-bound (in-session only).
|
|
32
|
+
*/
|
|
33
|
+
export function compileActStep(args, res) {
|
|
34
|
+
const r = asRecord(res);
|
|
35
|
+
const testid = asString(r['testid']);
|
|
36
|
+
const action = asString(args['action']) ?? '';
|
|
37
|
+
const actArgs = replayActionArgs(args['args']);
|
|
38
|
+
if (testid !== undefined) {
|
|
39
|
+
return {
|
|
40
|
+
tool: ReticleTool.ACT,
|
|
41
|
+
stable: true,
|
|
42
|
+
args: { by: QueryBy.TESTID, value: testid, action, args: actArgs },
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const component = asString(r['component']);
|
|
46
|
+
const source = sourceFromResult(r);
|
|
47
|
+
if (component !== undefined || source !== undefined) {
|
|
48
|
+
const componentArgs = { by: QueryBy.COMPONENT, action, args: actArgs };
|
|
49
|
+
if (component !== undefined)
|
|
50
|
+
componentArgs['component'] = component;
|
|
51
|
+
if (source !== undefined)
|
|
52
|
+
componentArgs['source'] = source;
|
|
53
|
+
return { tool: ReticleTool.ACT, stable: true, args: componentArgs };
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
tool: ReticleTool.ACT,
|
|
57
|
+
stable: false,
|
|
58
|
+
args: { ref: asString(args['ref']) ?? '', action, args: actArgs },
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/** Compile an reticle_act_sequence invocation, normalizing each sub-step to its testid where resolvable. */
|
|
62
|
+
export function compileSequenceStep(args, res) {
|
|
63
|
+
const inputSteps = Array.isArray(args['steps']) ? args['steps'] : [];
|
|
64
|
+
const resolved = Array.isArray(asRecord(res)['steps'])
|
|
65
|
+
? asRecord(res)['steps']
|
|
66
|
+
: [];
|
|
67
|
+
let stable = inputSteps.length > 0;
|
|
68
|
+
const subSteps = inputSteps.map((raw, i) => {
|
|
69
|
+
const step = asRecord(raw);
|
|
70
|
+
const action = asString(step['action']) ?? '';
|
|
71
|
+
const stepArgs = replayActionArgs(step['args']);
|
|
72
|
+
const testid = asString(asRecord(resolved[i])['testid']);
|
|
73
|
+
if (testid !== undefined) {
|
|
74
|
+
return { by: QueryBy.TESTID, value: testid, action, args: stepArgs };
|
|
75
|
+
}
|
|
76
|
+
stable = false;
|
|
77
|
+
return { ref: asString(step['ref']) ?? '', action, args: stepArgs };
|
|
78
|
+
});
|
|
79
|
+
return { tool: ReticleTool.ACT_SEQUENCE, stable, args: { steps: subSteps } };
|
|
80
|
+
}
|
|
81
|
+
/** Resolve a recorded sub-step's element to a live ref via testid query, else fall back to its stored ref. */
|
|
82
|
+
async function resolveRef(session, step) {
|
|
83
|
+
const by = asString(step.by);
|
|
84
|
+
const value = asString(step.value);
|
|
85
|
+
if (by === QueryBy.TESTID && value !== undefined) {
|
|
86
|
+
const result = await session.command(ReticleCommand.QUERY, { by, value });
|
|
87
|
+
if (!result.ok)
|
|
88
|
+
throw new Error(result.error ?? 'query failed');
|
|
89
|
+
const elements = Array.isArray(asRecord(result.result)['elements'])
|
|
90
|
+
? asRecord(result.result)['elements']
|
|
91
|
+
: [];
|
|
92
|
+
const ref = asString(asRecord(elements[0])['ref']);
|
|
93
|
+
if (ref === undefined)
|
|
94
|
+
throw new Error(`testid '${value}' did not resolve in current page`);
|
|
95
|
+
return elements.length > 1
|
|
96
|
+
? { ref, note: `ambiguous testid '${value}', used first match` }
|
|
97
|
+
: { ref };
|
|
98
|
+
}
|
|
99
|
+
const ref = asString(step.ref);
|
|
100
|
+
if (ref === undefined || ref.length === 0)
|
|
101
|
+
throw new Error('step has no testid or ref to resolve');
|
|
102
|
+
return { ref, note: 'replayed by stale ref (not portable across sessions)' };
|
|
103
|
+
}
|
|
104
|
+
/** Re-execute every step of a compiled program in order, stopping at the first failure. */
|
|
105
|
+
export async function replayProgram(session, program, confirmDangerous = false) {
|
|
106
|
+
const results = [];
|
|
107
|
+
for (const step of program.steps) {
|
|
108
|
+
try {
|
|
109
|
+
if (step.tool === ReticleTool.ACT_SEQUENCE) {
|
|
110
|
+
const subs = Array.isArray(step.args['steps']) ? step.args['steps'] : [];
|
|
111
|
+
const notes = [];
|
|
112
|
+
const liveSteps = [];
|
|
113
|
+
for (const raw of subs) {
|
|
114
|
+
const sub = asRecord(raw);
|
|
115
|
+
const { ref, note } = await resolveRef(session, sub);
|
|
116
|
+
if (note !== undefined)
|
|
117
|
+
notes.push(note);
|
|
118
|
+
liveSteps.push({
|
|
119
|
+
ref,
|
|
120
|
+
action: asString(sub['action']) ?? '',
|
|
121
|
+
args: replayActionArgs(sub['args'], confirmDangerous),
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
const r = await session.command(ReticleCommand.ACT_SEQUENCE, { steps: liveSteps });
|
|
125
|
+
results.push(buildResult(step.tool, r.ok, r.error, notes));
|
|
126
|
+
if (!r.ok)
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
const { ref, note } = await resolveRef(session, step.args);
|
|
131
|
+
const r = await session.command(ReticleCommand.ACT, {
|
|
132
|
+
ref,
|
|
133
|
+
action: asString(step.args['action']) ?? '',
|
|
134
|
+
args: replayActionArgs(step.args['args'], confirmDangerous),
|
|
135
|
+
});
|
|
136
|
+
results.push(buildResult(step.tool, r.ok, r.error, note !== undefined ? [note] : []));
|
|
137
|
+
if (!r.ok)
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
results.push({
|
|
143
|
+
tool: step.tool,
|
|
144
|
+
ok: false,
|
|
145
|
+
error: e instanceof Error ? e.message : String(e),
|
|
146
|
+
});
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return results;
|
|
151
|
+
}
|
|
152
|
+
function buildResult(tool, ok, error, notes) {
|
|
153
|
+
const base = { tool, ok };
|
|
154
|
+
if (!ok)
|
|
155
|
+
base.error = error ?? 'command failed';
|
|
156
|
+
if (notes.length > 0)
|
|
157
|
+
base.note = notes.join('; ');
|
|
158
|
+
return base;
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=replay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/flows/replay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as http from 'node:http';
|
|
2
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
export declare const MCP_SSE_PATH = "/mcp/sse";
|
|
4
|
+
export declare const MCP_MESSAGE_PATH = "/mcp/message";
|
|
5
|
+
/** Local-only daemon introspection — `reticle status` GETs this to show sessions + health at a glance. */
|
|
6
|
+
export declare const STATUS_PATH = "/status";
|
|
7
|
+
export interface SharedServer {
|
|
8
|
+
readonly httpServer: http.Server;
|
|
9
|
+
/**
|
|
10
|
+
* Register a factory that creates a fresh McpServer per SSE connection.
|
|
11
|
+
* The MCP SDK's Protocol layer only supports one transport per Server instance,
|
|
12
|
+
* so each concurrent Claude Code client needs its own McpServer.
|
|
13
|
+
* Must be called before listen().
|
|
14
|
+
*/
|
|
15
|
+
attachMcp(factory: () => McpServer): void;
|
|
16
|
+
/** Register the JSON the daemon returns from GET /status (live sessions + health for `reticle status`). */
|
|
17
|
+
attachStatus(provider: () => unknown): void;
|
|
18
|
+
/**
|
|
19
|
+
* Register a callback fired when the AGENT presence changes — true when the first MCP client (any
|
|
20
|
+
* agent: Codex/OpenCode/Claude/Hermes) connects, false when the last one disconnects. Agent-
|
|
21
|
+
* independent: the MCP connection lives exactly as long as the agent session, so its presence IS
|
|
22
|
+
* "is an agent attached?". The daemon uses this to tell the panel "agent live" vs "agent stopped".
|
|
23
|
+
*/
|
|
24
|
+
attachAgentPresence(cb: (connected: boolean) => void): void;
|
|
25
|
+
close(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Creates a shared HTTP server that handles both the WebSocket bridge (browser SDK) and the
|
|
29
|
+
* SSE MCP transport (Claude/agent). Does NOT call listen() — caller controls that.
|
|
30
|
+
*
|
|
31
|
+
* Routes:
|
|
32
|
+
* GET /mcp/sse → establishes SSE MCP session
|
|
33
|
+
* POST /mcp/message → routes MCP messages to an active SSE session
|
|
34
|
+
* WS /reticle → browser SDK connections (via WebSocketServer)
|
|
35
|
+
*/
|
|
36
|
+
export declare function createSharedServer(options?: {
|
|
37
|
+
token?: string;
|
|
38
|
+
}): SharedServer;
|
|
39
|
+
//# sourceMappingURL=http-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAWzE,eAAO,MAAM,YAAY,aAAa,CAAC;AACvC,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAC/C,0GAA0G;AAC1G,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;IACjC;;;;;OAKG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,SAAS,GAAG,IAAI,CAAC;IAC1C,2GAA2G;IAC3G,YAAY,CAAC,QAAQ,EAAE,MAAM,OAAO,GAAG,IAAI,CAAC;IAC5C;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IAC5D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,YAAY,CAqIjF"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import * as http from 'node:http';
|
|
2
|
+
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
3
|
+
import { log } from './log.js';
|
|
4
|
+
import { isLoopbackHost, isLocalWebOrigin, isLoopbackPeer, requestToken, tokensMatch, } from './token-auth.js';
|
|
5
|
+
// These paths form the agent↔server wire contract. Keep in sync with skill/SKILL.md.
|
|
6
|
+
export const MCP_SSE_PATH = '/mcp/sse';
|
|
7
|
+
export const MCP_MESSAGE_PATH = '/mcp/message';
|
|
8
|
+
/** Local-only daemon introspection — `reticle status` GETs this to show sessions + health at a glance. */
|
|
9
|
+
export const STATUS_PATH = '/status';
|
|
10
|
+
/**
|
|
11
|
+
* Creates a shared HTTP server that handles both the WebSocket bridge (browser SDK) and the
|
|
12
|
+
* SSE MCP transport (Claude/agent). Does NOT call listen() — caller controls that.
|
|
13
|
+
*
|
|
14
|
+
* Routes:
|
|
15
|
+
* GET /mcp/sse → establishes SSE MCP session
|
|
16
|
+
* POST /mcp/message → routes MCP messages to an active SSE session
|
|
17
|
+
* WS /reticle → browser SDK connections (via WebSocketServer)
|
|
18
|
+
*/
|
|
19
|
+
export function createSharedServer(options = {}) {
|
|
20
|
+
let mcpFactory;
|
|
21
|
+
let statusProvider;
|
|
22
|
+
let agentPresence;
|
|
23
|
+
const transports = new Map();
|
|
24
|
+
const token = options.token;
|
|
25
|
+
// The agent control plane (MCP transport) and /status carry the same trust as the browser WS: a
|
|
26
|
+
// loopback peer is trusted (the local stdio proxy and `reticle status` always dial 127.0.0.1), but any
|
|
27
|
+
// non-loopback peer must present the pairing token. Without this, binding the daemon beyond loopback
|
|
28
|
+
// (RETICLE_HOST) would expose reticle_act/reticle_navigate and session enumeration to the whole network even
|
|
29
|
+
// though the WS demanded a token. When no token is configured the bind is loopback-only anyway.
|
|
30
|
+
//
|
|
31
|
+
// Loopback-peer trust alone is not enough: a DNS-rebound webpage reaches us AS a loopback peer while
|
|
32
|
+
// its browser sends the attacker's original Host/Origin. So the loopback-trust tier additionally
|
|
33
|
+
// requires a loopback Host header and a loopback-or-absent Origin/Referer — the same rebinding
|
|
34
|
+
// defense the WS bridge has (#originAllowed). A rebound page fails those and falls through to the
|
|
35
|
+
// token check (which it cannot satisfy). Legitimate remote clients on a RETICLE_HOST bind present the
|
|
36
|
+
// token instead of relying on loopback trust, so this never breaks them.
|
|
37
|
+
const authorized = (req, url) => {
|
|
38
|
+
const localClient = isLoopbackPeer(req.socket.remoteAddress) &&
|
|
39
|
+
isLoopbackHost(req.headers.host) &&
|
|
40
|
+
isLocalWebOrigin(req.headers.origin, req.headers.referer);
|
|
41
|
+
if (localClient)
|
|
42
|
+
return true;
|
|
43
|
+
if (token === undefined)
|
|
44
|
+
return false;
|
|
45
|
+
return tokensMatch(token, requestToken(req, url));
|
|
46
|
+
};
|
|
47
|
+
const httpServer = http.createServer((req, res) => {
|
|
48
|
+
const rawUrl = req.url ?? '/';
|
|
49
|
+
const url = new URL(rawUrl, 'http://localhost');
|
|
50
|
+
const path = url.pathname;
|
|
51
|
+
if (path === STATUS_PATH || path === MCP_SSE_PATH || path === MCP_MESSAGE_PATH) {
|
|
52
|
+
if (!authorized(req, url)) {
|
|
53
|
+
res.writeHead(401, { 'Content-Type': 'text/plain' });
|
|
54
|
+
res.end('unauthorized');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (req.method === 'GET' && path === STATUS_PATH) {
|
|
59
|
+
const body = JSON.stringify(statusProvider?.() ?? { running: true });
|
|
60
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
61
|
+
res.end(body);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (req.method === 'GET' && path === MCP_SSE_PATH) {
|
|
65
|
+
if (mcpFactory === undefined) {
|
|
66
|
+
res.writeHead(503, { 'Content-Type': 'text/plain' });
|
|
67
|
+
res.end('MCP server not ready');
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// Fresh McpServer per connection: the MCP SDK's Protocol layer only supports
|
|
71
|
+
// one active transport per Server instance, so concurrent clients each need
|
|
72
|
+
// their own instance backed by the same shared ToolDeps.
|
|
73
|
+
const mcpServer = mcpFactory();
|
|
74
|
+
const transport = new SSEServerTransport(MCP_MESSAGE_PATH, res);
|
|
75
|
+
const sid = transport.sessionId;
|
|
76
|
+
transports.set(sid, transport);
|
|
77
|
+
if (transports.size === 1)
|
|
78
|
+
agentPresence?.(true); // first agent attached
|
|
79
|
+
res.on('close', () => {
|
|
80
|
+
transports.delete(sid);
|
|
81
|
+
transport.close().catch(() => undefined);
|
|
82
|
+
mcpServer.close().catch(() => undefined);
|
|
83
|
+
log('mcp_client_disconnected', { sessionId: sid });
|
|
84
|
+
if (transports.size === 0)
|
|
85
|
+
agentPresence?.(false); // last agent detached → it's the human's turn
|
|
86
|
+
});
|
|
87
|
+
mcpServer
|
|
88
|
+
.connect(transport)
|
|
89
|
+
.then(() => {
|
|
90
|
+
log('mcp_client_connected', { sessionId: sid });
|
|
91
|
+
})
|
|
92
|
+
.catch((err) => {
|
|
93
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
94
|
+
log('mcp_connect_error', { error: message });
|
|
95
|
+
});
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (req.method === 'POST' && path === MCP_MESSAGE_PATH) {
|
|
99
|
+
const sessionId = url.searchParams.get('sessionId');
|
|
100
|
+
if (sessionId === null) {
|
|
101
|
+
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
|
102
|
+
res.end('missing sessionId');
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const transport = transports.get(sessionId);
|
|
106
|
+
if (transport === undefined) {
|
|
107
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
108
|
+
res.end('session not found');
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
transport.handlePostMessage(req, res).catch((err) => {
|
|
112
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
113
|
+
log('mcp_message_error', { error: message });
|
|
114
|
+
});
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
118
|
+
res.end('not found');
|
|
119
|
+
});
|
|
120
|
+
function attachStatus(provider) {
|
|
121
|
+
statusProvider = provider;
|
|
122
|
+
}
|
|
123
|
+
function attachAgentPresence(cb) {
|
|
124
|
+
agentPresence = cb;
|
|
125
|
+
}
|
|
126
|
+
function attachMcp(factory) {
|
|
127
|
+
mcpFactory = factory;
|
|
128
|
+
}
|
|
129
|
+
async function close() {
|
|
130
|
+
for (const transport of transports.values()) {
|
|
131
|
+
await transport.close();
|
|
132
|
+
}
|
|
133
|
+
transports.clear();
|
|
134
|
+
await new Promise((resolve, reject) => {
|
|
135
|
+
httpServer.close((err) => {
|
|
136
|
+
if (err !== undefined && err !== null)
|
|
137
|
+
reject(err);
|
|
138
|
+
else
|
|
139
|
+
resolve();
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return { httpServer, attachMcp, attachStatus, attachAgentPresence, close };
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=http-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-server.js","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAE7E,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,WAAW,GACZ,MAAM,iBAAiB,CAAC;AAEzB,qFAAqF;AACrF,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;AACvC,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAC/C,0GAA0G;AAC1G,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AAuBrC;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAA8B,EAAE;IAEjE,IAAI,UAAkC,CAAC;IACvC,IAAI,cAA2C,CAAC;IAChD,IAAI,aAAyD,CAAC;IAC9D,MAAM,UAAU,GAAG,IAAI,GAAG,EAA8B,CAAC;IACzD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAE5B,gGAAgG;IAChG,uGAAuG;IACvG,qGAAqG;IACrG,6GAA6G;IAC7G,gGAAgG;IAChG,EAAE;IACF,qGAAqG;IACrG,iGAAiG;IACjG,+FAA+F;IAC/F,kGAAkG;IAClG,sGAAsG;IACtG,yEAAyE;IACzE,MAAM,UAAU,GAAG,CAAC,GAAyB,EAAE,GAAQ,EAAW,EAAE;QAClE,MAAM,WAAW,GACf,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC;YACxC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;YAChC,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5D,IAAI,WAAW;YAAE,OAAO,IAAI,CAAC;QAC7B,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QACtC,OAAO,WAAW,CAAC,KAAK,EAAE,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IACpD,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAChD,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC;QAC9B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC;QAE1B,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,YAAY,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;YAC/E,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;gBAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;gBACrD,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBACxB,OAAO;YACT,CAAC;QACH,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;YACjD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACrE,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACd,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;YAClD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;gBAC7B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;gBACrD,GAAG,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;gBAChC,OAAO;YACT,CAAC;YACD,6EAA6E;YAC7E,4EAA4E;YAC5E,yDAAyD;YACzD,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC;YAC/B,MAAM,SAAS,GAAG,IAAI,kBAAkB,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;YAChE,MAAM,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC;YAChC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAC/B,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC;gBAAE,aAAa,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,uBAAuB;YACzE,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACnB,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvB,SAAS,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBACzC,SAAS,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBACzC,GAAG,CAAC,yBAAyB,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;gBACnD,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC;oBAAE,aAAa,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,8CAA8C;YACnG,CAAC,CAAC,CAAC;YACH,SAAS;iBACN,OAAO,CAAC,SAAS,CAAC;iBAClB,IAAI,CAAC,GAAG,EAAE;gBACT,GAAG,CAAC,sBAAsB,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;YAClD,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;gBACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjE,GAAG,CAAC,mBAAmB,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YAC/C,CAAC,CAAC,CAAC;YACL,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;YACvD,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACpD,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;gBACvB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;gBACrD,GAAG,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;gBAC7B,OAAO;YACT,CAAC;YACD,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC5C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;gBACrD,GAAG,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;gBAC7B,OAAO;YACT,CAAC;YACD,SAAS,CAAC,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;gBAC3D,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjE,GAAG,CAAC,mBAAmB,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YAC/C,CAAC,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;QACrD,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,SAAS,YAAY,CAAC,QAAuB;QAC3C,cAAc,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAED,SAAS,mBAAmB,CAAC,EAAgC;QAC3D,aAAa,GAAG,EAAE,CAAC;IACrB,CAAC;IAED,SAAS,SAAS,CAAC,OAAmB;QACpC,UAAU,GAAG,OAAO,CAAC;IACvB,CAAC;IAED,KAAK,UAAU,KAAK;QAClB,KAAK,MAAM,SAAS,IAAI,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;YAC5C,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;QAC1B,CAAC;QACD,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACvB,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI;oBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;;oBAC9C,OAAO,EAAE,CAAC;YACjB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC;AAC7E,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface IdleShutdownOptions {
|
|
2
|
+
/** True when nothing is using the daemon: no agent connected, no browser session, no pool lease. */
|
|
3
|
+
isIdle: () => boolean;
|
|
4
|
+
/** Clean teardown + process exit. Called at most once. */
|
|
5
|
+
onShutdown: () => void;
|
|
6
|
+
/** Continuous-idle window before shutdown. `0` (or negative) disables the watcher entirely. */
|
|
7
|
+
graceMs: number;
|
|
8
|
+
/** How often to re-check idleness. */
|
|
9
|
+
checkIntervalMs?: number;
|
|
10
|
+
/** Injected clock — never read wall-clock time in logic (repo rule). */
|
|
11
|
+
clock?: () => number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Self-terminates an idle daemon so Reticle never lingers eating a user's resources (the daemon process,
|
|
15
|
+
* any headless Chromium the pool launched, and the bound port) after the editor closes. The `reticle mcp`
|
|
16
|
+
* proxy spawns the daemon DETACHED so it survives between turns — which means nothing else will ever
|
|
17
|
+
* stop it; this watcher is that missing stop. Idle = `isIdle()` true continuously for `graceMs` (long
|
|
18
|
+
* enough to ride out brief agent reconnects between turns). On fire it calls `onShutdown` exactly once.
|
|
19
|
+
* The interval is `unref`'d, so it never keeps the process alive on its own; `start()` is idempotent.
|
|
20
|
+
*/
|
|
21
|
+
export declare class IdleShutdown {
|
|
22
|
+
#private;
|
|
23
|
+
constructor(opts: IdleShutdownOptions);
|
|
24
|
+
/** Run one idle check. Exposed so a test can drive it deterministically with an injected clock. */
|
|
25
|
+
check(): void;
|
|
26
|
+
start(): void;
|
|
27
|
+
stop(): void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolve the idle-shutdown grace from `RETICLE_IDLE_SHUTDOWN_MS`: a non-negative integer of milliseconds,
|
|
31
|
+
* `0` to disable. Anything missing/invalid falls back to the default. Pure.
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveIdleShutdownMs(raw: string | undefined): number;
|
|
34
|
+
//# sourceMappingURL=idle-shutdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idle-shutdown.d.ts","sourceRoot":"","sources":["../src/idle-shutdown.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,mBAAmB;IAClC,oGAAoG;IACpG,MAAM,EAAE,MAAM,OAAO,CAAC;IACtB,0DAA0D;IAC1D,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,+FAA+F;IAC/F,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,qBAAa,YAAY;;gBAUX,IAAI,EAAE,mBAAmB;IAQrC,mGAAmG;IACnG,KAAK,IAAI,IAAI;IAeb,KAAK,IAAI,IAAI;IAMb,IAAI,IAAI,IAAI;CAKb;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAKrE"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { SESSION_LIFECYCLE } from '@reticlehq/core';
|
|
2
|
+
import { log } from './log.js';
|
|
3
|
+
/**
|
|
4
|
+
* Self-terminates an idle daemon so Reticle never lingers eating a user's resources (the daemon process,
|
|
5
|
+
* any headless Chromium the pool launched, and the bound port) after the editor closes. The `reticle mcp`
|
|
6
|
+
* proxy spawns the daemon DETACHED so it survives between turns — which means nothing else will ever
|
|
7
|
+
* stop it; this watcher is that missing stop. Idle = `isIdle()` true continuously for `graceMs` (long
|
|
8
|
+
* enough to ride out brief agent reconnects between turns). On fire it calls `onShutdown` exactly once.
|
|
9
|
+
* The interval is `unref`'d, so it never keeps the process alive on its own; `start()` is idempotent.
|
|
10
|
+
*/
|
|
11
|
+
export class IdleShutdown {
|
|
12
|
+
#timer;
|
|
13
|
+
#idleSince = null;
|
|
14
|
+
#fired = false;
|
|
15
|
+
#isIdle;
|
|
16
|
+
#onShutdown;
|
|
17
|
+
#graceMs;
|
|
18
|
+
#checkMs;
|
|
19
|
+
#clock;
|
|
20
|
+
constructor(opts) {
|
|
21
|
+
this.#isIdle = opts.isIdle;
|
|
22
|
+
this.#onShutdown = opts.onShutdown;
|
|
23
|
+
this.#graceMs = opts.graceMs;
|
|
24
|
+
this.#checkMs = opts.checkIntervalMs ?? SESSION_LIFECYCLE.DAEMON_IDLE_CHECK_MS;
|
|
25
|
+
this.#clock = opts.clock ?? (() => Date.now());
|
|
26
|
+
}
|
|
27
|
+
/** Run one idle check. Exposed so a test can drive it deterministically with an injected clock. */
|
|
28
|
+
check() {
|
|
29
|
+
if (this.#fired || this.#graceMs <= 0)
|
|
30
|
+
return; // graceMs <= 0 ⇒ disabled (never self-shut-down)
|
|
31
|
+
if (!this.#isIdle()) {
|
|
32
|
+
this.#idleSince = null;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const now = this.#clock();
|
|
36
|
+
this.#idleSince ??= now;
|
|
37
|
+
if (now - this.#idleSince >= this.#graceMs) {
|
|
38
|
+
this.#fired = true;
|
|
39
|
+
log('reticle_daemon_idle_shutdown', { idleMs: now - this.#idleSince });
|
|
40
|
+
this.#onShutdown();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
start() {
|
|
44
|
+
if (this.#graceMs <= 0 || this.#timer !== undefined)
|
|
45
|
+
return; // 0 = disabled
|
|
46
|
+
this.#timer = setInterval(() => this.check(), this.#checkMs);
|
|
47
|
+
this.#timer.unref();
|
|
48
|
+
}
|
|
49
|
+
stop() {
|
|
50
|
+
if (this.#timer === undefined)
|
|
51
|
+
return;
|
|
52
|
+
clearInterval(this.#timer);
|
|
53
|
+
this.#timer = undefined;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Resolve the idle-shutdown grace from `RETICLE_IDLE_SHUTDOWN_MS`: a non-negative integer of milliseconds,
|
|
58
|
+
* `0` to disable. Anything missing/invalid falls back to the default. Pure.
|
|
59
|
+
*/
|
|
60
|
+
export function resolveIdleShutdownMs(raw) {
|
|
61
|
+
if (raw === undefined || raw.trim() === '')
|
|
62
|
+
return SESSION_LIFECYCLE.DAEMON_IDLE_SHUTDOWN_MS;
|
|
63
|
+
const n = Number(raw);
|
|
64
|
+
if (!Number.isFinite(n) || n < 0)
|
|
65
|
+
return SESSION_LIFECYCLE.DAEMON_IDLE_SHUTDOWN_MS;
|
|
66
|
+
return Math.floor(n);
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=idle-shutdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idle-shutdown.js","sourceRoot":"","sources":["../src/idle-shutdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAe/B;;;;;;;GAOG;AACH,MAAM,OAAO,YAAY;IACvB,MAAM,CAA6C;IACnD,UAAU,GAAkB,IAAI,CAAC;IACjC,MAAM,GAAG,KAAK,CAAC;IACN,OAAO,CAAgB;IACvB,WAAW,CAAa;IACxB,QAAQ,CAAS;IACjB,QAAQ,CAAS;IACjB,MAAM,CAAe;IAE9B,YAAY,IAAyB;QACnC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC;QACnC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,eAAe,IAAI,iBAAiB,CAAC,oBAAoB,CAAC;QAC/E,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,mGAAmG;IACnG,KAAK;QACH,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC;YAAE,OAAO,CAAC,iDAAiD;QAChG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YACpB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACvB,OAAO;QACT,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC,UAAU,KAAK,GAAG,CAAC;QACxB,IAAI,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC3C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,GAAG,CAAC,8BAA8B,EAAE,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YACvE,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,CAAC,eAAe;QAC5E,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO;QACtC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;IAC1B,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAuB;IAC3D,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,iBAAiB,CAAC,uBAAuB,CAAC;IAC7F,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,iBAAiB,CAAC,uBAAuB,CAAC;IACnF,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACvB,CAAC"}
|