@pugi/cli 0.1.0-beta.99 → 1.0.0-alpha.10
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 +1 -1
- package/README.md +11 -191
- package/bin/pugi +8 -0
- package/package.json +15 -71
- package/postinstall.mjs +31 -0
- package/CHANGELOG.md +0 -132
- package/THIRD_PARTY_NOTICES.md +0 -40
- package/assets/pugi-mascot.ansi +0 -16
- package/assets/pugi-prozr2-mascot.ansi +0 -9
- package/bin/run.js +0 -34
- package/dist/commands/deploy.js +0 -439
- package/dist/commands/flatten.js +0 -191
- package/dist/commands/jobs-watch.js +0 -201
- package/dist/commands/jobs.js +0 -260
- package/dist/commands/retro.js +0 -210
- package/dist/commands/smoke.js +0 -133
- package/dist/core/agent-progress/cleanup.js +0 -134
- package/dist/core/agent-progress/schema.js +0 -144
- package/dist/core/agent-progress/writer.js +0 -101
- package/dist/core/agents/adaptive-router.js +0 -330
- package/dist/core/agents/loader.js +0 -104
- package/dist/core/agents/query-decomposer.js +0 -297
- package/dist/core/agents/registry.js +0 -69
- package/dist/core/approvals/shortcut-resolver.js +0 -98
- package/dist/core/artifact-chain/dispatcher.js +0 -148
- package/dist/core/artifact-chain/exporter.js +0 -164
- package/dist/core/artifact-chain/state.js +0 -243
- package/dist/core/artifact-chain/steps.js +0 -169
- package/dist/core/ask-user/question.js +0 -92
- package/dist/core/audit/audit-trail.js +0 -275
- package/dist/core/auth/ensure-authenticated.js +0 -129
- package/dist/core/auth/env-provider.js +0 -238
- package/dist/core/auto-open-browser.js +0 -128
- package/dist/core/auto-update/channels.js +0 -122
- package/dist/core/auto-update/checker.js +0 -241
- package/dist/core/auto-update/state.js +0 -235
- package/dist/core/bare-mode/index.js +0 -107
- package/dist/core/bash/redirect.js +0 -281
- package/dist/core/bash-classifier.js +0 -1397
- package/dist/core/checkpoint/resumer.js +0 -149
- package/dist/core/checkpoint/rewinder.js +0 -291
- package/dist/core/checkpoints/shadow-git.js +0 -670
- package/dist/core/citations/parser.js +0 -109
- package/dist/core/classifier/yolo-classifier.js +0 -88
- package/dist/core/clipboard.js +0 -70
- package/dist/core/codegraph/decision-store.js +0 -248
- package/dist/core/codegraph/detect-repo.js +0 -459
- package/dist/core/codegraph/install.js +0 -134
- package/dist/core/codegraph/offer-hook.js +0 -220
- package/dist/core/compact/auto-trigger.js +0 -96
- package/dist/core/compact/buffer-rewriter.js +0 -115
- package/dist/core/compact/summarizer.js +0 -208
- package/dist/core/compact/token-counter.js +0 -108
- package/dist/core/consensus/anvil-fanout.js +0 -276
- package/dist/core/consensus/diff-capture.js +0 -491
- package/dist/core/consensus/rubric.js +0 -233
- package/dist/core/context/builder.js +0 -114
- package/dist/core/context/compaction-events.js +0 -99
- package/dist/core/context/compaction.js +0 -602
- package/dist/core/context/index.js +0 -28
- package/dist/core/context/invariants.js +0 -250
- package/dist/core/context/markdown-loader.js +0 -288
- package/dist/core/context/markdown-traverse.js +0 -255
- package/dist/core/context/pugiignore.js +0 -316
- package/dist/core/context/repo-skeleton.js +0 -533
- package/dist/core/context/tool-eviction.js +0 -55
- package/dist/core/context/watcher.js +0 -342
- package/dist/core/context/working-set.js +0 -165
- package/dist/core/coordinator/agent-tools.js +0 -77
- package/dist/core/coordinator/agent-toolset.js +0 -65
- package/dist/core/coordinator/fsm.js +0 -73
- package/dist/core/coordinator/mode-fsm.js +0 -70
- package/dist/core/cost/rate-card.js +0 -129
- package/dist/core/cost/tracker.js +0 -221
- package/dist/core/credentials.js +0 -355
- package/dist/core/cron/scheduler.js +0 -138
- package/dist/core/denial-tracking/index.js +0 -8
- package/dist/core/denial-tracking/state.js +0 -264
- package/dist/core/diagnostics/probe-runner.js +0 -93
- package/dist/core/diagnostics/probes/api.js +0 -46
- package/dist/core/diagnostics/probes/auth.js +0 -93
- package/dist/core/diagnostics/probes/bare-mode.js +0 -42
- package/dist/core/diagnostics/probes/cli-version.js +0 -127
- package/dist/core/diagnostics/probes/config.js +0 -72
- package/dist/core/diagnostics/probes/denial-tracking.js +0 -57
- package/dist/core/diagnostics/probes/disk.js +0 -81
- package/dist/core/diagnostics/probes/engine-live.js +0 -46
- package/dist/core/diagnostics/probes/git.js +0 -65
- package/dist/core/diagnostics/probes/hooks.js +0 -118
- package/dist/core/diagnostics/probes/mcp.js +0 -75
- package/dist/core/diagnostics/probes/node.js +0 -59
- package/dist/core/diagnostics/probes/pnpm.js +0 -36
- package/dist/core/diagnostics/probes/pugi-md.js +0 -89
- package/dist/core/diagnostics/probes/sandbox.js +0 -72
- package/dist/core/diagnostics/probes/session.js +0 -74
- package/dist/core/diagnostics/probes/status-snapshot.js +0 -488
- package/dist/core/diagnostics/probes/workspace.js +0 -63
- package/dist/core/diagnostics/types.js +0 -70
- package/dist/core/dispatch/cache-cleanup.js +0 -197
- package/dist/core/dispatch/cache-handoff.js +0 -295
- package/dist/core/edits/apply-patch-layer-e.js +0 -189
- package/dist/core/edits/dispatch.js +0 -511
- package/dist/core/edits/format-detector.js +0 -260
- package/dist/core/edits/format-matrix.js +0 -26
- package/dist/core/edits/fuzzy-ladder.js +0 -650
- package/dist/core/edits/index.js +0 -19
- package/dist/core/edits/journal.js +0 -199
- package/dist/core/edits/layer-a-apply.js +0 -217
- package/dist/core/edits/layer-a-fuzzy-apply.js +0 -198
- package/dist/core/edits/layer-b-apply.js +0 -211
- package/dist/core/edits/layer-c-apply.js +0 -160
- package/dist/core/edits/layer-d-ast.js +0 -572
- package/dist/core/edits/marker-parser.js +0 -401
- package/dist/core/edits/security-gate.js +0 -223
- package/dist/core/edits/verify-hook.js +0 -273
- package/dist/core/edits/worktree.js +0 -322
- package/dist/core/engine/adapter-runner.js +0 -8
- package/dist/core/engine/anvil-client.js +0 -344
- package/dist/core/engine/auto-compact.js +0 -179
- package/dist/core/engine/budgets.js +0 -195
- package/dist/core/engine/context-prefix.js +0 -155
- package/dist/core/engine/index.js +0 -12
- package/dist/core/engine/intensity.js +0 -163
- package/dist/core/engine/intent.js +0 -260
- package/dist/core/engine/native-pugi.js +0 -1616
- package/dist/core/engine/noop.js +0 -27
- package/dist/core/engine/prompts.js +0 -236
- package/dist/core/engine/strip-internal-fields.js +0 -124
- package/dist/core/engine/tool-bridge.js +0 -2173
- package/dist/core/engine/verification-patterns.js +0 -195
- package/dist/core/evaluation/golden-dataset.js +0 -293
- package/dist/core/feedback/queue.js +0 -177
- package/dist/core/feedback/submitter.js +0 -145
- package/dist/core/file-cache.js +0 -141
- package/dist/core/flatten/flatten-repo.js +0 -439
- package/dist/core/format/osc8-link.js +0 -28
- package/dist/core/hook-chains.js +0 -392
- package/dist/core/hooks/citation-verify-hook.js +0 -138
- package/dist/core/hooks/citation-verify.js +0 -112
- package/dist/core/hooks/events.js +0 -46
- package/dist/core/hooks/index.js +0 -15
- package/dist/core/hooks/registry.js +0 -216
- package/dist/core/hooks/runner.js +0 -236
- package/dist/core/hooks/v2/event-emitter.js +0 -115
- package/dist/core/hooks/v2/executor.js +0 -282
- package/dist/core/hooks/v2/index.js +0 -25
- package/dist/core/hooks/v2/lifecycle.js +0 -104
- package/dist/core/hooks/v2/loader.js +0 -216
- package/dist/core/hooks/v2/matcher.js +0 -125
- package/dist/core/hooks/v2/trust.js +0 -143
- package/dist/core/hooks/v2/types.js +0 -86
- package/dist/core/hooks/worktree-events.js +0 -158
- package/dist/core/hooks.js +0 -415
- package/dist/core/image/renderer.js +0 -71
- package/dist/core/index-store.js +0 -260
- package/dist/core/init/detector.js +0 -582
- package/dist/core/init/template-renderer.js +0 -242
- package/dist/core/jobs/registry.js +0 -462
- package/dist/core/ledger/results-tsv.js +0 -142
- package/dist/core/log-discipline/stdout-redirect.js +0 -51
- package/dist/core/lsp/cache.js +0 -105
- package/dist/core/lsp/client.js +0 -1229
- package/dist/core/lsp/language-detect.js +0 -66
- package/dist/core/lsp/post-edit-diagnostics.js +0 -171
- package/dist/core/lsp/server-detect.js +0 -173
- package/dist/core/lsp/symbol-cache.js +0 -162
- package/dist/core/lsp/symbol-tools.js +0 -664
- package/dist/core/mcp/client.js +0 -385
- package/dist/core/mcp/http-server.js +0 -553
- package/dist/core/mcp/orchestrator-config.js +0 -192
- package/dist/core/mcp/orchestrator-tools.js +0 -806
- package/dist/core/mcp/permission.js +0 -190
- package/dist/core/mcp/registry.js +0 -193
- package/dist/core/mcp/server-tools.js +0 -219
- package/dist/core/mcp/server.js +0 -397
- package/dist/core/mcp/trust.js +0 -91
- package/dist/core/memory/dual-write.js +0 -416
- package/dist/core/memory/passive-extract.js +0 -130
- package/dist/core/memory/phase1-kinds.js +0 -20
- package/dist/core/memory/secret-scanner.js +0 -304
- package/dist/core/memory-sync/queue.js +0 -170
- package/dist/core/metrics/extract.js +0 -113
- package/dist/core/modes/roo-modes.js +0 -68
- package/dist/core/onboarding/ensure-initialized.js +0 -133
- package/dist/core/onboarding/marker.js +0 -111
- package/dist/core/onboarding/telemetry-state.js +0 -108
- package/dist/core/output-style/presets.js +0 -176
- package/dist/core/output-style/state.js +0 -185
- package/dist/core/path-security.js +0 -345
- package/dist/core/permission.js +0 -369
- package/dist/core/permissions/auto-classifier.js +0 -124
- package/dist/core/permissions/bash-parser.js +0 -371
- package/dist/core/permissions/circuit-breaker.js +0 -83
- package/dist/core/permissions/constrained-edit.js +0 -91
- package/dist/core/permissions/gate.js +0 -278
- package/dist/core/permissions/index.js +0 -20
- package/dist/core/permissions/mode.js +0 -174
- package/dist/core/permissions/network-egress.js +0 -137
- package/dist/core/permissions/state.js +0 -241
- package/dist/core/permissions/tool-class.js +0 -107
- package/dist/core/plan-mode/ui-state.js +0 -51
- package/dist/core/plans/plan-artifact.js +0 -721
- package/dist/core/policy-limits/etag-store.js +0 -122
- package/dist/core/prd-check/parser.js +0 -215
- package/dist/core/prd-check/reporter.js +0 -127
- package/dist/core/prd-check/session-review.js +0 -557
- package/dist/core/prd-check/verifiers.js +0 -223
- package/dist/core/prompt-cache/client-cache.js +0 -99
- package/dist/core/prompts/assembly.js +0 -29
- package/dist/core/prompts/registry.js +0 -364
- package/dist/core/pugi-gitignore.js +0 -52
- package/dist/core/pugi-md/cc-compat-rules.js +0 -735
- package/dist/core/pugi-md/context-injector.js +0 -76
- package/dist/core/pugi-md/walk-up.js +0 -207
- package/dist/core/python/uv-installer.js +0 -270
- package/dist/core/python/uv-resolver.js +0 -83
- package/dist/core/rate-limit/narrator.js +0 -146
- package/dist/core/recipes/cli-types.js +0 -20
- package/dist/core/recipes/loader.js +0 -103
- package/dist/core/recipes/runner.js +0 -345
- package/dist/core/recipes/schema.js +0 -587
- package/dist/core/release-notes/parser.js +0 -241
- package/dist/core/release-notes/state.js +0 -116
- package/dist/core/repl/ask.js +0 -512
- package/dist/core/repl/cancellation.js +0 -98
- package/dist/core/repl/cap-warning.js +0 -91
- package/dist/core/repl/clipboard-read.js +0 -174
- package/dist/core/repl/dispatch-fsm.js +0 -220
- package/dist/core/repl/engine-bridge.js +0 -303
- package/dist/core/repl/history-search.js +0 -175
- package/dist/core/repl/history.js +0 -182
- package/dist/core/repl/kill-ring.js +0 -138
- package/dist/core/repl/model-pricing.js +0 -135
- package/dist/core/repl/privacy-banner.js +0 -71
- package/dist/core/repl/session.js +0 -4962
- package/dist/core/repl/slash-commands.js +0 -747
- package/dist/core/repl/store/index.js +0 -12
- package/dist/core/repl/store/jsonl-log.js +0 -321
- package/dist/core/repl/store/lockfile.js +0 -155
- package/dist/core/repl/store/session-store.js +0 -821
- package/dist/core/repl/store/types.js +0 -44
- package/dist/core/repl/store/uuid-v7.js +0 -68
- package/dist/core/repl/tool-route.js +0 -382
- package/dist/core/repl/workspace-context.js +0 -206
- package/dist/core/repo-map/build.js +0 -125
- package/dist/core/repo-map/cache.js +0 -185
- package/dist/core/repo-map/extractor.js +0 -254
- package/dist/core/repo-map/formatter.js +0 -145
- package/dist/core/repo-map/page-rank.js +0 -105
- package/dist/core/repo-map/scanner.js +0 -211
- package/dist/core/retro/git-collector.js +0 -251
- package/dist/core/retro/health-card.js +0 -25
- package/dist/core/retro/metrics.js +0 -342
- package/dist/core/retro/narrative.js +0 -249
- package/dist/core/retro/plane-collector.js +0 -274
- package/dist/core/retro/pr-issue-link.js +0 -65
- package/dist/core/retro/types.js +0 -16
- package/dist/core/retry-budget/budget.js +0 -284
- package/dist/core/retry-budget/index.js +0 -5
- package/dist/core/retry-budget/retry-cap.js +0 -74
- package/dist/core/routing/lead-worker.js +0 -43
- package/dist/core/routing/pre-flight-estimator.js +0 -108
- package/dist/core/runs/run-tree.js +0 -103
- package/dist/core/sandboxing/adapter.js +0 -29
- package/dist/core/sandboxing/index.js +0 -49
- package/dist/core/sandboxing/none.js +0 -19
- package/dist/core/sandboxing/seatbelt.js +0 -183
- package/dist/core/security/injection-scanner.js +0 -367
- package/dist/core/security/output-filter.js +0 -418
- package/dist/core/session/env-file.js +0 -105
- package/dist/core/session/section-budgets.js +0 -140
- package/dist/core/session.js +0 -377
- package/dist/core/settings.js +0 -400
- package/dist/core/share/formatter.js +0 -271
- package/dist/core/share/redactor.js +0 -221
- package/dist/core/share/uploader.js +0 -267
- package/dist/core/skills/defaults.js +0 -457
- package/dist/core/skills/loader.js +0 -454
- package/dist/core/skills/sources.js +0 -480
- package/dist/core/skills/trust.js +0 -172
- package/dist/core/smoke/headless-driver.js +0 -174
- package/dist/core/smoke/orchestrator.js +0 -194
- package/dist/core/smoke/runner.js +0 -238
- package/dist/core/smoke/scenario-parser.js +0 -316
- package/dist/core/statusline.js +0 -99
- package/dist/core/subagents/dispatcher-real.js +0 -600
- package/dist/core/subagents/dispatcher.js +0 -352
- package/dist/core/subagents/index.js +0 -39
- package/dist/core/subagents/isolation-matrix.js +0 -213
- package/dist/core/subagents/spawn.js +0 -101
- package/dist/core/telemetry/emitter.js +0 -229
- package/dist/core/telemetry/queue.js +0 -251
- package/dist/core/theme/context.js +0 -91
- package/dist/core/theme/presets.js +0 -228
- package/dist/core/theme/state.js +0 -181
- package/dist/core/todos/invariant.js +0 -10
- package/dist/core/todos/state.js +0 -177
- package/dist/core/tool-schema/compressor.js +0 -89
- package/dist/core/transport/version-interceptor.js +0 -166
- package/dist/core/trust.js +0 -109
- package/dist/core/tui/thinking-block.js +0 -64
- package/dist/core/vim/keymap.js +0 -288
- package/dist/core/vim/state.js +0 -92
- package/dist/core/watch-markers/marker-watcher.js +0 -133
- package/dist/core/worktree/include-parser.js +0 -249
- package/dist/core/worktree-manager/cleanup.js +0 -123
- package/dist/core/worktree-manager/manager.js +0 -303
- package/dist/index.js +0 -44
- package/dist/runtime/bootstrap.js +0 -190
- package/dist/runtime/cli.js +0 -8121
- package/dist/runtime/commands/agents.js +0 -385
- package/dist/runtime/commands/budget.js +0 -192
- package/dist/runtime/commands/cancel.js +0 -231
- package/dist/runtime/commands/chain.js +0 -489
- package/dist/runtime/commands/codegraph-status.js +0 -227
- package/dist/runtime/commands/compact.js +0 -297
- package/dist/runtime/commands/config.js +0 -595
- package/dist/runtime/commands/cost.js +0 -199
- package/dist/runtime/commands/delegate.js +0 -312
- package/dist/runtime/commands/dispatch.js +0 -126
- package/dist/runtime/commands/doctor.js +0 -579
- package/dist/runtime/commands/feedback.js +0 -184
- package/dist/runtime/commands/hooks.js +0 -187
- package/dist/runtime/commands/init.js +0 -254
- package/dist/runtime/commands/lsp.js +0 -368
- package/dist/runtime/commands/mcp.js +0 -935
- package/dist/runtime/commands/memory.js +0 -582
- package/dist/runtime/commands/model.js +0 -237
- package/dist/runtime/commands/onboarding.js +0 -275
- package/dist/runtime/commands/patch.js +0 -128
- package/dist/runtime/commands/permissions.js +0 -112
- package/dist/runtime/commands/plan.js +0 -143
- package/dist/runtime/commands/prd-check.js +0 -285
- package/dist/runtime/commands/privacy.js +0 -107
- package/dist/runtime/commands/recipe.js +0 -325
- package/dist/runtime/commands/redo-blob-store.js +0 -92
- package/dist/runtime/commands/redo.js +0 -361
- package/dist/runtime/commands/release-notes.js +0 -229
- package/dist/runtime/commands/repo-map.js +0 -95
- package/dist/runtime/commands/report.js +0 -299
- package/dist/runtime/commands/resume.js +0 -118
- package/dist/runtime/commands/review-consensus.js +0 -414
- package/dist/runtime/commands/rewind.js +0 -333
- package/dist/runtime/commands/roster.js +0 -117
- package/dist/runtime/commands/sessions.js +0 -163
- package/dist/runtime/commands/share.js +0 -316
- package/dist/runtime/commands/skills.js +0 -401
- package/dist/runtime/commands/status.js +0 -186
- package/dist/runtime/commands/stickers.js +0 -82
- package/dist/runtime/commands/style.js +0 -194
- package/dist/runtime/commands/theme.js +0 -196
- package/dist/runtime/commands/undo.js +0 -361
- package/dist/runtime/commands/update.js +0 -289
- package/dist/runtime/commands/vim.js +0 -140
- package/dist/runtime/commands/worktree.js +0 -177
- package/dist/runtime/commands/worktrees.js +0 -155
- package/dist/runtime/deprecation-warning.js +0 -69
- package/dist/runtime/engine-exit-code.js +0 -50
- package/dist/runtime/headless-repl.js +0 -195
- package/dist/runtime/headless.js +0 -548
- package/dist/runtime/load-hooks-or-exit.js +0 -71
- package/dist/runtime/plan-decompose.js +0 -531
- package/dist/runtime/sigint-guard.js +0 -272
- package/dist/runtime/stream-renderer.js +0 -195
- package/dist/runtime/update-check.js +0 -294
- package/dist/runtime/version.js +0 -65
- package/dist/runtime/worktree-bootstrap.js +0 -579
- package/dist/skills/bundled/batch.js +0 -617
- package/dist/skills/bundled/index.js +0 -45
- package/dist/skills/bundled/loop.js +0 -358
- package/dist/skills/bundled/remember.js +0 -383
- package/dist/skills/bundled/simplify.js +0 -289
- package/dist/skills/bundled/skillify.js +0 -373
- package/dist/skills/bundled/stuck.js +0 -558
- package/dist/skills/bundled/verify.js +0 -439
- package/dist/testing/vcr.js +0 -486
- package/dist/tools/agent-tool.js +0 -229
- package/dist/tools/apply-patch.js +0 -556
- package/dist/tools/ask-user-question.js +0 -337
- package/dist/tools/ask-user.js +0 -115
- package/dist/tools/bash.js +0 -1238
- package/dist/tools/brief.js +0 -224
- package/dist/tools/cron.js +0 -433
- package/dist/tools/enter-worktree.js +0 -250
- package/dist/tools/exit-worktree.js +0 -147
- package/dist/tools/file-tools.js +0 -553
- package/dist/tools/http-request.js +0 -336
- package/dist/tools/lsp-tools.js +0 -565
- package/dist/tools/mcp-tool.js +0 -260
- package/dist/tools/multi-edit.js +0 -361
- package/dist/tools/powershell.js +0 -268
- package/dist/tools/registry.js +0 -166
- package/dist/tools/server-tools.js +0 -892
- package/dist/tools/skill-tool.js +0 -96
- package/dist/tools/sleep.js +0 -99
- package/dist/tools/synthetic-output.js +0 -133
- package/dist/tools/tasks.js +0 -208
- package/dist/tools/todo-write.js +0 -184
- package/dist/tools/verify-plan-execution.js +0 -295
- package/dist/tools/web-fetch-injection-scanner.js +0 -207
- package/dist/tools/web-fetch.js +0 -720
- package/dist/tools/web-search.js +0 -458
- package/dist/tui/agent-progress-card.js +0 -111
- package/dist/tui/agent-tree-pane.js +0 -9
- package/dist/tui/agent-tree.js +0 -87
- package/dist/tui/ask-cli.js +0 -52
- package/dist/tui/ask-modal.js +0 -211
- package/dist/tui/ask-user-question-chips.js +0 -315
- package/dist/tui/ask-user-question-prompt.js +0 -203
- package/dist/tui/compact-banner.js +0 -81
- package/dist/tui/conversation-pane.js +0 -164
- package/dist/tui/cost-table.js +0 -111
- package/dist/tui/device-flow.js +0 -142
- package/dist/tui/doctor-table.js +0 -46
- package/dist/tui/feedback-prompt.js +0 -156
- package/dist/tui/input-box.js +0 -732
- package/dist/tui/login-picker.js +0 -69
- package/dist/tui/markdown-render.js +0 -266
- package/dist/tui/multi-file-diff-approval.js +0 -375
- package/dist/tui/onboarding-wizard.js +0 -240
- package/dist/tui/permissions-picker.js +0 -86
- package/dist/tui/render.js +0 -160
- package/dist/tui/repl-render.js +0 -770
- package/dist/tui/repl-splash-art.js +0 -64
- package/dist/tui/repl-splash-mascot.js +0 -154
- package/dist/tui/repl-splash.js +0 -117
- package/dist/tui/repl.js +0 -378
- package/dist/tui/slash-palette.js +0 -106
- package/dist/tui/splash-data.js +0 -61
- package/dist/tui/splash.js +0 -31
- package/dist/tui/status-bar.js +0 -209
- package/dist/tui/status-table.js +0 -7
- package/dist/tui/stickers-art.js +0 -136
- package/dist/tui/style-table.js +0 -28
- package/dist/tui/theme-table.js +0 -29
- package/dist/tui/thinking-spinner.js +0 -123
- package/dist/tui/tool-stream-pane.js +0 -140
- package/dist/tui/update-banner.js +0 -33
- package/dist/tui/vim-input.js +0 -267
- package/dist/tui/welcome-banner.js +0 -107
- package/dist/tui/welcome-data.js +0 -293
- package/dist/tui/workspace-context.js +0 -105
- package/docs/examples/codegraph.mcp.json +0 -10
- package/test/scenarios/codegen-create-file.scenario.txt +0 -13
- package/test/scenarios/compact-force.scenario.txt +0 -12
- package/test/scenarios/identity.scenario.txt +0 -11
- package/test/scenarios/persona-handoff.scenario.txt +0 -12
- package/test/scenarios/walkback.scenario.txt +0 -12
package/dist/testing/vcr.js
DELETED
|
@@ -1,486 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* VCR — Pugi CLI test helper that records `fetch` interactions to a JSON
|
|
3
|
-
* cassette and replays them deterministically. independent implementation re-implementation
|
|
4
|
-
* of the external `vcr.ts` pattern; Node built-ins only (`node:fs`,
|
|
5
|
-
* `node:crypto`, `node:path`), no new dependencies.
|
|
6
|
-
*
|
|
7
|
-
* # Why this exists
|
|
8
|
-
*
|
|
9
|
-
* Hand-stubbed `globalThis.fetch =` blocks are spread across the CLI
|
|
10
|
-
* test corpus (`anvil-client-e2-contract.spec.ts`, `submit-delegate.spec.ts`,
|
|
11
|
-
* `cost-quota-slash.spec.ts`, `repl-render-transport.spec.ts`). They
|
|
12
|
-
* work but the response bodies are inlined as JSON literals — drifts
|
|
13
|
-
* between the real admin-api wire shape and the test fixture are
|
|
14
|
-
* caught only when production breaks.
|
|
15
|
-
*
|
|
16
|
-
* VCR shifts the source-of-truth: a real run records once to a cassette,
|
|
17
|
-
* subsequent runs replay deterministically. Operators can re-record by
|
|
18
|
-
* deleting the cassette file (auto-mode flips back to record).
|
|
19
|
-
*
|
|
20
|
-
* # Lifecycle
|
|
21
|
-
*
|
|
22
|
-
* const tape = vcr({ path: '...', mode: 'auto' });
|
|
23
|
-
* const restore = tape.install();
|
|
24
|
-
* try {
|
|
25
|
-
* await codeUnderTestThatCallsFetch();
|
|
26
|
-
* await tape.flush(); // no-op in replay mode
|
|
27
|
-
* } finally {
|
|
28
|
-
* restore();
|
|
29
|
-
* }
|
|
30
|
-
*
|
|
31
|
-
* # Matching strategy
|
|
32
|
-
*
|
|
33
|
-
* `method + url + sha256(canonical-body)`. Bodies are normalised when
|
|
34
|
-
* the request advertises `content-type: application/json` so timestamp
|
|
35
|
-
* / uuid wobble inside a JSON envelope does NOT cause a cassette miss.
|
|
36
|
-
*
|
|
37
|
-
* # Security
|
|
38
|
-
*
|
|
39
|
-
* Sensitive headers (`authorization`, `x-pugi-bearer`, `x-api-key`,
|
|
40
|
-
* `cookie`) are redacted at write time so a cassette accidentally
|
|
41
|
-
* committed never leaks a real bearer token. Redaction is one-way —
|
|
42
|
-
* the cassette retains `[REDACTED]` and replay matches on the original
|
|
43
|
-
* scrubbed value (replay does not re-hash the headers; only the body
|
|
44
|
-
* participates in the match key, which keeps record/replay symmetric).
|
|
45
|
-
*
|
|
46
|
-
* # Atomicity
|
|
47
|
-
*
|
|
48
|
-
* Cassette writes go `tmp + rename` so a concurrent reader never sees
|
|
49
|
-
* a half-written JSON document (mirrors the agent-progress writer
|
|
50
|
-
* pattern in `src/core/agent-progress/writer.ts`).
|
|
51
|
-
*/
|
|
52
|
-
import { createHash } from 'node:crypto';
|
|
53
|
-
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from 'node:fs';
|
|
54
|
-
import { dirname } from 'node:path';
|
|
55
|
-
/** Cassette schema version. Bump on breaking changes to the JSON shape. */
|
|
56
|
-
export const VCR_CASSETTE_VERSION = 1;
|
|
57
|
-
/** Headers that are scrubbed to `[REDACTED]` at cassette-write time. */
|
|
58
|
-
export const VCR_SENSITIVE_HEADERS = Object.freeze([
|
|
59
|
-
'authorization',
|
|
60
|
-
'x-pugi-bearer',
|
|
61
|
-
'x-api-key',
|
|
62
|
-
'cookie',
|
|
63
|
-
]);
|
|
64
|
-
/** Placeholder written in place of a sensitive header value. */
|
|
65
|
-
export const VCR_REDACTED = '[REDACTED]';
|
|
66
|
-
/**
|
|
67
|
-
* Error thrown when replay mode looks up a request that is NOT in the
|
|
68
|
-
* cassette. The message lists the cassette's recorded URLs so the
|
|
69
|
-
* operator immediately sees whether the test drifted or the cassette
|
|
70
|
-
* is stale.
|
|
71
|
-
*/
|
|
72
|
-
export class VcrCassetteMiss extends Error {
|
|
73
|
-
request;
|
|
74
|
-
recordedUrls;
|
|
75
|
-
constructor(request, recordedUrls) {
|
|
76
|
-
const recordedList = recordedUrls.length
|
|
77
|
-
? recordedUrls.map((u) => ` - ${u}`).join('\n')
|
|
78
|
-
: ' (empty cassette)';
|
|
79
|
-
super(`VCR cassette miss: ${request.method} ${request.url}\n` +
|
|
80
|
-
`Recorded URLs:\n${recordedList}\n` +
|
|
81
|
-
'Re-record by deleting the cassette and running the test, ' +
|
|
82
|
-
'or check whether the request shape drifted.');
|
|
83
|
-
this.name = 'VcrCassetteMiss';
|
|
84
|
-
this.request = request;
|
|
85
|
-
this.recordedUrls = recordedUrls;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Error thrown when a cassette file on disk advertises a `version`
|
|
90
|
-
* that this VCR build does not understand. Loud failure is the right
|
|
91
|
-
* call — silent best-effort would replay against a shape the test
|
|
92
|
-
* expects to be a different one.
|
|
93
|
-
*/
|
|
94
|
-
export class VcrCassetteVersionMismatch extends Error {
|
|
95
|
-
cassettePath;
|
|
96
|
-
foundVersion;
|
|
97
|
-
expectedVersion;
|
|
98
|
-
constructor(cassettePath, foundVersion) {
|
|
99
|
-
super(`VCR cassette ${cassettePath} advertises version ${foundVersion}; ` +
|
|
100
|
-
`this build expects version ${VCR_CASSETTE_VERSION}. ` +
|
|
101
|
-
'Delete the cassette and re-record, or upgrade the helper.');
|
|
102
|
-
this.name = 'VcrCassetteVersionMismatch';
|
|
103
|
-
this.cassettePath = cassettePath;
|
|
104
|
-
this.foundVersion = foundVersion;
|
|
105
|
-
this.expectedVersion = VCR_CASSETTE_VERSION;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
/* ------------------------------------------------------------------ */
|
|
109
|
-
/* Internal helpers */
|
|
110
|
-
/* ------------------------------------------------------------------ */
|
|
111
|
-
/**
|
|
112
|
-
* Canonicalise a JSON body string so two semantically-equal payloads
|
|
113
|
-
* with different key order hash identically. Non-JSON bodies pass
|
|
114
|
-
* through unchanged.
|
|
115
|
-
*
|
|
116
|
-
* The contract intentionally does NOT walk arrays or recursively
|
|
117
|
-
* normalise nested objects beyond their key order — that is a future
|
|
118
|
-
* refinement if cassettes start to miss on collection re-orderings.
|
|
119
|
-
*/
|
|
120
|
-
function canonicaliseBodyForHash(body, contentType) {
|
|
121
|
-
if (body === undefined || body === '')
|
|
122
|
-
return '';
|
|
123
|
-
const isJson = typeof contentType === 'string' && contentType.toLowerCase().includes('application/json');
|
|
124
|
-
if (!isJson)
|
|
125
|
-
return body;
|
|
126
|
-
try {
|
|
127
|
-
const parsed = JSON.parse(body);
|
|
128
|
-
return canonicalStringify(parsed);
|
|
129
|
-
}
|
|
130
|
-
catch {
|
|
131
|
-
// Body advertised JSON but was not parseable — fall back to the raw
|
|
132
|
-
// string so the test still produces a stable hash and the operator
|
|
133
|
-
// sees the broken body during diagnostics.
|
|
134
|
-
return body;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Stable JSON.stringify with sorted object keys. Arrays preserve order
|
|
139
|
-
* (order is semantically meaningful in the wire shape).
|
|
140
|
-
*/
|
|
141
|
-
function canonicalStringify(value) {
|
|
142
|
-
if (value === null || typeof value !== 'object') {
|
|
143
|
-
return JSON.stringify(value);
|
|
144
|
-
}
|
|
145
|
-
if (Array.isArray(value)) {
|
|
146
|
-
return `[${value.map((v) => canonicalStringify(v)).join(',')}]`;
|
|
147
|
-
}
|
|
148
|
-
const entries = Object.entries(value)
|
|
149
|
-
.filter(([, v]) => v !== undefined)
|
|
150
|
-
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
|
|
151
|
-
const body = entries
|
|
152
|
-
.map(([k, v]) => `${JSON.stringify(k)}:${canonicalStringify(v)}`)
|
|
153
|
-
.join(',');
|
|
154
|
-
return `{${body}}`;
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Normalise a Headers / plain-object header bag into a lowercased
|
|
158
|
-
* record. The cassette stores lowercase keys exclusively so a runtime
|
|
159
|
-
* fetch that sends `Authorization` matches a recorded `authorization`
|
|
160
|
-
* fixture without ambiguity.
|
|
161
|
-
*/
|
|
162
|
-
function normaliseHeaders(input) {
|
|
163
|
-
const out = {};
|
|
164
|
-
if (!input)
|
|
165
|
-
return out;
|
|
166
|
-
if (input instanceof Headers) {
|
|
167
|
-
input.forEach((value, key) => {
|
|
168
|
-
out[key.toLowerCase()] = value;
|
|
169
|
-
});
|
|
170
|
-
return out;
|
|
171
|
-
}
|
|
172
|
-
if (Array.isArray(input)) {
|
|
173
|
-
for (const entry of input) {
|
|
174
|
-
if (Array.isArray(entry) && entry.length === 2) {
|
|
175
|
-
const [k, v] = entry;
|
|
176
|
-
if (typeof k === 'string' && typeof v === 'string') {
|
|
177
|
-
out[k.toLowerCase()] = v;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
return out;
|
|
182
|
-
}
|
|
183
|
-
if (typeof input === 'object') {
|
|
184
|
-
for (const [k, v] of Object.entries(input)) {
|
|
185
|
-
if (typeof v === 'string') {
|
|
186
|
-
out[k.toLowerCase()] = v;
|
|
187
|
-
}
|
|
188
|
-
else if (typeof v === 'number' || typeof v === 'boolean') {
|
|
189
|
-
out[k.toLowerCase()] = String(v);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return out;
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Redact sensitive headers in-place by replacing their values with
|
|
197
|
-
* `[REDACTED]`. The exported list is canonical lowercase; the headers
|
|
198
|
-
* argument is also normalised to lowercase keys before this is called.
|
|
199
|
-
*/
|
|
200
|
-
function redactHeaders(headers) {
|
|
201
|
-
const out = { ...headers };
|
|
202
|
-
for (const key of VCR_SENSITIVE_HEADERS) {
|
|
203
|
-
if (key in out) {
|
|
204
|
-
out[key] = VCR_REDACTED;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return out;
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Resolve `fetch` arguments into the canonical request shape used by
|
|
211
|
-
* the matcher and cassette writer.
|
|
212
|
-
*/
|
|
213
|
-
function buildRequest(input, init) {
|
|
214
|
-
let method = 'GET';
|
|
215
|
-
let url;
|
|
216
|
-
let headers = {};
|
|
217
|
-
let body;
|
|
218
|
-
if (typeof input === 'string') {
|
|
219
|
-
url = input;
|
|
220
|
-
}
|
|
221
|
-
else if (input instanceof URL) {
|
|
222
|
-
url = input.toString();
|
|
223
|
-
}
|
|
224
|
-
else if (typeof input === 'object' && input !== null && 'url' in input) {
|
|
225
|
-
// Request object
|
|
226
|
-
const req = input;
|
|
227
|
-
url = req.url;
|
|
228
|
-
method = req.method;
|
|
229
|
-
headers = normaliseHeaders(req.headers);
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
url = String(input);
|
|
233
|
-
}
|
|
234
|
-
if (init) {
|
|
235
|
-
if (typeof init.method === 'string')
|
|
236
|
-
method = init.method;
|
|
237
|
-
if (init.headers !== undefined) {
|
|
238
|
-
headers = { ...headers, ...normaliseHeaders(init.headers) };
|
|
239
|
-
}
|
|
240
|
-
if (typeof init.body === 'string') {
|
|
241
|
-
body = init.body;
|
|
242
|
-
}
|
|
243
|
-
else if (init.body instanceof URLSearchParams) {
|
|
244
|
-
body = init.body.toString();
|
|
245
|
-
}
|
|
246
|
-
else if (init.body !== undefined && init.body !== null) {
|
|
247
|
-
// ArrayBuffer / Blob / ReadableStream are not supported in VCR
|
|
248
|
-
// record mode — fall back to JSON.stringify so the matcher key
|
|
249
|
-
// is at least stable. The recorded body still surfaces in the
|
|
250
|
-
// cassette so the operator can see what landed.
|
|
251
|
-
try {
|
|
252
|
-
body = JSON.stringify(init.body);
|
|
253
|
-
}
|
|
254
|
-
catch {
|
|
255
|
-
body = String(init.body);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
return {
|
|
260
|
-
method: method.toUpperCase(),
|
|
261
|
-
url,
|
|
262
|
-
headers,
|
|
263
|
-
body,
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
/**
|
|
267
|
-
* Compute the match key for an interaction. The cassette key uses
|
|
268
|
-
* sha256 because collision probability across a test suite is
|
|
269
|
-
* astronomically low, and the hex is short enough to log.
|
|
270
|
-
*/
|
|
271
|
-
function matchKey(request) {
|
|
272
|
-
const contentType = request.headers['content-type'];
|
|
273
|
-
const canonicalBody = canonicaliseBodyForHash(request.body, contentType);
|
|
274
|
-
const hash = createHash('sha256')
|
|
275
|
-
.update(`${request.method}\n${request.url}\n${canonicalBody}`)
|
|
276
|
-
.digest('hex');
|
|
277
|
-
return hash;
|
|
278
|
-
}
|
|
279
|
-
function loadCassette(path) {
|
|
280
|
-
if (!existsSync(path))
|
|
281
|
-
return [];
|
|
282
|
-
const raw = readFileSync(path, 'utf8');
|
|
283
|
-
if (raw.trim() === '')
|
|
284
|
-
return [];
|
|
285
|
-
const parsed = JSON.parse(raw);
|
|
286
|
-
if (typeof parsed !== 'object' ||
|
|
287
|
-
parsed === null ||
|
|
288
|
-
!('version' in parsed) ||
|
|
289
|
-
!('interactions' in parsed)) {
|
|
290
|
-
throw new Error(`VCR cassette ${path} has invalid shape (missing version / interactions)`);
|
|
291
|
-
}
|
|
292
|
-
const cast = parsed;
|
|
293
|
-
if (typeof cast.version !== 'number' || cast.version !== VCR_CASSETTE_VERSION) {
|
|
294
|
-
throw new VcrCassetteVersionMismatch(path, typeof cast.version === 'number' ? cast.version : -1);
|
|
295
|
-
}
|
|
296
|
-
if (!Array.isArray(cast.interactions)) {
|
|
297
|
-
throw new Error(`VCR cassette ${path}: interactions must be an array`);
|
|
298
|
-
}
|
|
299
|
-
return cast.interactions;
|
|
300
|
-
}
|
|
301
|
-
function writeCassetteAtomic(path, interactions) {
|
|
302
|
-
const parent = dirname(path);
|
|
303
|
-
if (!existsSync(parent)) {
|
|
304
|
-
mkdirSync(parent, { recursive: true });
|
|
305
|
-
}
|
|
306
|
-
const file = {
|
|
307
|
-
version: VCR_CASSETTE_VERSION,
|
|
308
|
-
interactions: [...interactions],
|
|
309
|
-
};
|
|
310
|
-
const tmpPath = `${path}.tmp-${process.pid}-${Date.now()}`;
|
|
311
|
-
const body = `${JSON.stringify(file, null, 2)}\n`;
|
|
312
|
-
try {
|
|
313
|
-
writeFileSync(tmpPath, body, 'utf8');
|
|
314
|
-
renameSync(tmpPath, path);
|
|
315
|
-
}
|
|
316
|
-
catch (err) {
|
|
317
|
-
try {
|
|
318
|
-
rmSync(tmpPath, { force: true });
|
|
319
|
-
}
|
|
320
|
-
catch {
|
|
321
|
-
// best-effort
|
|
322
|
-
}
|
|
323
|
-
throw err;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
/* ------------------------------------------------------------------ */
|
|
327
|
-
/* Public factory */
|
|
328
|
-
/* ------------------------------------------------------------------ */
|
|
329
|
-
/** Internal guard — only one VCR can be installed on globalThis at a time. */
|
|
330
|
-
let installed = false;
|
|
331
|
-
export function vcr(cassette) {
|
|
332
|
-
// Snapshot the recorded interactions at construction time so the
|
|
333
|
-
// matcher does not re-read the cassette on every fetch call.
|
|
334
|
-
//
|
|
335
|
-
// In explicit `mode: 'record'` we swallow VcrCassetteVersionMismatch
|
|
336
|
-
// and treat the cassette as empty — the whole point of explicit
|
|
337
|
-
// record mode is to nuke and rewrite, so refusing to construct on a
|
|
338
|
-
// stale on-disk version would brick the re-record workflow.
|
|
339
|
-
// Triple-review Claude P1,.
|
|
340
|
-
let recordedFromDisk;
|
|
341
|
-
try {
|
|
342
|
-
recordedFromDisk = loadCassette(cassette.path);
|
|
343
|
-
}
|
|
344
|
-
catch (err) {
|
|
345
|
-
if (cassette.mode === 'record' && err instanceof VcrCassetteVersionMismatch) {
|
|
346
|
-
recordedFromDisk = [];
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
throw err;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
const newlyRecorded = [];
|
|
353
|
-
const effectiveMode = cassette.mode === 'auto'
|
|
354
|
-
? recordedFromDisk.length > 0 || existsSync(cassette.path)
|
|
355
|
-
? 'replay'
|
|
356
|
-
: 'record'
|
|
357
|
-
: cassette.mode;
|
|
358
|
-
// Precompute the match index for replay mode so lookup is O(1).
|
|
359
|
-
const replayIndex = new Map();
|
|
360
|
-
if (effectiveMode === 'replay') {
|
|
361
|
-
for (const interaction of recordedFromDisk) {
|
|
362
|
-
replayIndex.set(matchKey(interaction.request), interaction);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
let originalFetch;
|
|
366
|
-
function buildResponse(interaction) {
|
|
367
|
-
const headers = new Headers();
|
|
368
|
-
for (const [k, v] of Object.entries(interaction.response.headers)) {
|
|
369
|
-
headers.set(k, v);
|
|
370
|
-
}
|
|
371
|
-
return new Response(interaction.response.body, {
|
|
372
|
-
status: interaction.response.status,
|
|
373
|
-
headers,
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
async function interceptor(input, init) {
|
|
377
|
-
const request = buildRequest(input, init);
|
|
378
|
-
const key = matchKey(request);
|
|
379
|
-
if (effectiveMode === 'replay') {
|
|
380
|
-
const hit = replayIndex.get(key);
|
|
381
|
-
if (!hit) {
|
|
382
|
-
const recordedUrls = recordedFromDisk.map((r) => `${r.request.method} ${r.request.url}`);
|
|
383
|
-
throw new VcrCassetteMiss(request, recordedUrls);
|
|
384
|
-
}
|
|
385
|
-
return buildResponse(hit);
|
|
386
|
-
}
|
|
387
|
-
// Record mode: pass through to the real network, then store.
|
|
388
|
-
if (!originalFetch) {
|
|
389
|
-
// Defensive — should not happen because install() captures it.
|
|
390
|
-
throw new Error('VCR record mode requires a captured original fetch but found none');
|
|
391
|
-
}
|
|
392
|
-
const liveResponse = await originalFetch(input, init);
|
|
393
|
-
// Clone before draining the body so the caller still gets a
|
|
394
|
-
// readable Response with its own untouched stream.
|
|
395
|
-
const cloned = liveResponse.clone();
|
|
396
|
-
const responseBody = await cloned.text();
|
|
397
|
-
const responseHeaders = {};
|
|
398
|
-
liveResponse.headers.forEach((value, key) => {
|
|
399
|
-
responseHeaders[key.toLowerCase()] = value;
|
|
400
|
-
});
|
|
401
|
-
const recordedRequestHeaders = redactHeaders(request.headers);
|
|
402
|
-
const interaction = {
|
|
403
|
-
request: {
|
|
404
|
-
method: request.method,
|
|
405
|
-
url: request.url,
|
|
406
|
-
headers: recordedRequestHeaders,
|
|
407
|
-
body: request.body,
|
|
408
|
-
},
|
|
409
|
-
response: {
|
|
410
|
-
status: liveResponse.status,
|
|
411
|
-
headers: responseHeaders,
|
|
412
|
-
body: responseBody,
|
|
413
|
-
},
|
|
414
|
-
recordedAt: new Date().toISOString(),
|
|
415
|
-
};
|
|
416
|
-
newlyRecorded.push(interaction);
|
|
417
|
-
return liveResponse;
|
|
418
|
-
}
|
|
419
|
-
return {
|
|
420
|
-
install() {
|
|
421
|
-
if (installed) {
|
|
422
|
-
throw new Error('VCR is already installed on globalThis.fetch. ' +
|
|
423
|
-
'Restore the previous tape before installing a new one.');
|
|
424
|
-
}
|
|
425
|
-
originalFetch = globalThis.fetch;
|
|
426
|
-
installed = true;
|
|
427
|
-
globalThis.fetch = interceptor;
|
|
428
|
-
return () => {
|
|
429
|
-
// Idempotent restore — calling twice is safe.
|
|
430
|
-
if (!installed)
|
|
431
|
-
return;
|
|
432
|
-
if (originalFetch) {
|
|
433
|
-
globalThis.fetch = originalFetch;
|
|
434
|
-
}
|
|
435
|
-
installed = false;
|
|
436
|
-
};
|
|
437
|
-
},
|
|
438
|
-
recordedCount() {
|
|
439
|
-
return newlyRecorded.length;
|
|
440
|
-
},
|
|
441
|
-
async flush() {
|
|
442
|
-
if (effectiveMode === 'replay')
|
|
443
|
-
return;
|
|
444
|
-
if (newlyRecorded.length === 0)
|
|
445
|
-
return;
|
|
446
|
-
// Merge any pre-existing on-disk interactions (e.g. auto-mode
|
|
447
|
-
// started fresh but a parallel process raced us) with the newly
|
|
448
|
-
// recorded ones. On-disk wins for duplicate keys so a manual
|
|
449
|
-
// edit to the cassette is not stomped.
|
|
450
|
-
const merged = [];
|
|
451
|
-
const seen = new Set();
|
|
452
|
-
const existing = loadCassette(cassette.path);
|
|
453
|
-
for (const interaction of existing) {
|
|
454
|
-
const k = matchKey(interaction.request);
|
|
455
|
-
seen.add(k);
|
|
456
|
-
merged.push(interaction);
|
|
457
|
-
}
|
|
458
|
-
for (const interaction of newlyRecorded) {
|
|
459
|
-
const k = matchKey(interaction.request);
|
|
460
|
-
if (seen.has(k))
|
|
461
|
-
continue;
|
|
462
|
-
seen.add(k);
|
|
463
|
-
merged.push(interaction);
|
|
464
|
-
}
|
|
465
|
-
writeCassetteAtomic(cassette.path, merged);
|
|
466
|
-
},
|
|
467
|
-
};
|
|
468
|
-
}
|
|
469
|
-
/**
|
|
470
|
-
* Test-only escape hatch: forcibly clear the install latch. Use from
|
|
471
|
-
* an `afterEach` if a test crashed mid-install before its restore
|
|
472
|
-
* handle could run. NEVER call from production code.
|
|
473
|
-
*/
|
|
474
|
-
export function __resetVcrInstallLatchForTests() {
|
|
475
|
-
installed = false;
|
|
476
|
-
}
|
|
477
|
-
/**
|
|
478
|
-
* Build a synthetic cassette file on disk. Useful in tests that want
|
|
479
|
-
* to exercise replay-mode against an inline fixture (cassettes are
|
|
480
|
-
* gitignored so a checked-in fixture is not the right pattern). Writes
|
|
481
|
-
* atomically using the same tmp+rename path as the record-mode flush.
|
|
482
|
-
*/
|
|
483
|
-
export function writeCassetteFixtureForTests(path, interactions) {
|
|
484
|
-
writeCassetteAtomic(path, interactions);
|
|
485
|
-
}
|
|
486
|
-
//# sourceMappingURL=vcr.js.map
|