@pugi/cli 0.1.0-beta.99 → 1.0.0-alpha.1
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
|
@@ -1,371 +0,0 @@
|
|
|
1
|
-
const WRAPPER_COMMANDS = new Set(['bash', 'sh']);
|
|
2
|
-
const PIPELINE_SEPARATORS = new Set(['&&', '||', '|', ';']);
|
|
3
|
-
export function parseBashCommand(cmd) {
|
|
4
|
-
const rawCommand = cmd;
|
|
5
|
-
const command = stripWrappers(cmd).trim();
|
|
6
|
-
if (command.length === 0) {
|
|
7
|
-
throw new Error('empty bash command');
|
|
8
|
-
}
|
|
9
|
-
const stageSources = splitPipeline(command);
|
|
10
|
-
const envVars = {};
|
|
11
|
-
const redirects = [];
|
|
12
|
-
const pipelineStages = [];
|
|
13
|
-
const tokens = [];
|
|
14
|
-
for (const stageSource of stageSources) {
|
|
15
|
-
const rawTokens = tokenize(stageSource);
|
|
16
|
-
const stage = normalizeStage(rawTokens, envVars, redirects);
|
|
17
|
-
if (stage.length === 0) {
|
|
18
|
-
throw new Error('pipeline stage has no command');
|
|
19
|
-
}
|
|
20
|
-
pipelineStages.push(stage);
|
|
21
|
-
tokens.push(...stage);
|
|
22
|
-
}
|
|
23
|
-
const firstStage = pipelineStages[0];
|
|
24
|
-
if (firstStage === undefined) {
|
|
25
|
-
throw new Error('bash command has no stages');
|
|
26
|
-
}
|
|
27
|
-
const firstCommand = firstStage[0];
|
|
28
|
-
if (firstCommand === undefined || firstCommand.length === 0) {
|
|
29
|
-
throw new Error('bash command has no first command');
|
|
30
|
-
}
|
|
31
|
-
return {
|
|
32
|
-
rawCommand,
|
|
33
|
-
tokens,
|
|
34
|
-
firstCommand,
|
|
35
|
-
pipelineStages,
|
|
36
|
-
envVars,
|
|
37
|
-
redirects,
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
export function isAllowed(cmd, allowlist) {
|
|
41
|
-
let parsed;
|
|
42
|
-
try {
|
|
43
|
-
parsed = parseBashCommand(cmd);
|
|
44
|
-
}
|
|
45
|
-
catch (error) {
|
|
46
|
-
const message = error instanceof Error ? error.message : 'parse failed';
|
|
47
|
-
return { allowed: false, reason: message };
|
|
48
|
-
}
|
|
49
|
-
if (parsed.firstCommand.length === 0) {
|
|
50
|
-
return { allowed: false, reason: 'missing first command' };
|
|
51
|
-
}
|
|
52
|
-
const allowedCommands = new Set(allowlist);
|
|
53
|
-
for (const stage of parsed.pipelineStages) {
|
|
54
|
-
const stageCommand = stage[0];
|
|
55
|
-
if (stageCommand === undefined || stageCommand.length === 0) {
|
|
56
|
-
return {
|
|
57
|
-
allowed: false,
|
|
58
|
-
reason: 'missing command in pipeline stage',
|
|
59
|
-
firstCommand: parsed.firstCommand,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
if (!allowedCommands.has(stageCommand)) {
|
|
63
|
-
return {
|
|
64
|
-
allowed: false,
|
|
65
|
-
reason: `command not allowlisted: ${stageCommand}`,
|
|
66
|
-
firstCommand: parsed.firstCommand,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return { allowed: true, firstCommand: parsed.firstCommand };
|
|
71
|
-
}
|
|
72
|
-
function stripWrappers(cmd) {
|
|
73
|
-
let current = cmd.trim();
|
|
74
|
-
for (let depth = 0; depth < 8; depth += 1) {
|
|
75
|
-
const tokens = tokenize(current);
|
|
76
|
-
const first = tokens[0];
|
|
77
|
-
if (first === undefined) {
|
|
78
|
-
return current;
|
|
79
|
-
}
|
|
80
|
-
if (WRAPPER_COMMANDS.has(first)) {
|
|
81
|
-
const second = tokens[1];
|
|
82
|
-
const third = tokens[2];
|
|
83
|
-
if (second === '-c' && third !== undefined) {
|
|
84
|
-
current = third.trim();
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
if (first === 'eval') {
|
|
89
|
-
const inner = tokens.slice(1).join(' ').trim();
|
|
90
|
-
if (inner.length === 0) {
|
|
91
|
-
throw new Error('eval wrapper has no inner command');
|
|
92
|
-
}
|
|
93
|
-
current = inner;
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
return current;
|
|
97
|
-
}
|
|
98
|
-
throw new Error('too many nested shell wrappers');
|
|
99
|
-
}
|
|
100
|
-
function splitPipeline(command) {
|
|
101
|
-
const stages = [];
|
|
102
|
-
let current = '';
|
|
103
|
-
let quote = 'none';
|
|
104
|
-
let escaped = false;
|
|
105
|
-
for (let i = 0; i < command.length; i += 1) {
|
|
106
|
-
const ch = command[i];
|
|
107
|
-
if (ch === undefined) {
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
110
|
-
if (escaped) {
|
|
111
|
-
current += ch;
|
|
112
|
-
escaped = false;
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
if (quote !== 'single' && ch === '\\') {
|
|
116
|
-
current += ch;
|
|
117
|
-
escaped = true;
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
if (quote === 'none' && ch === "'") {
|
|
121
|
-
current += ch;
|
|
122
|
-
quote = 'single';
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
if (quote === 'single' && ch === "'") {
|
|
126
|
-
current += ch;
|
|
127
|
-
quote = 'none';
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
if (quote === 'none' && ch === '"') {
|
|
131
|
-
current += ch;
|
|
132
|
-
quote = 'double';
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
if (quote === 'double' && ch === '"') {
|
|
136
|
-
current += ch;
|
|
137
|
-
quote = 'none';
|
|
138
|
-
continue;
|
|
139
|
-
}
|
|
140
|
-
if (quote === 'none') {
|
|
141
|
-
const next = command[i + 1];
|
|
142
|
-
const pair = next === undefined ? ch : `${ch}${next}`;
|
|
143
|
-
if (PIPELINE_SEPARATORS.has(pair)) {
|
|
144
|
-
pushStage(stages, current);
|
|
145
|
-
current = '';
|
|
146
|
-
i += 1;
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
if (PIPELINE_SEPARATORS.has(ch)) {
|
|
150
|
-
pushStage(stages, current);
|
|
151
|
-
current = '';
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
current += ch;
|
|
156
|
-
}
|
|
157
|
-
if (escaped) {
|
|
158
|
-
throw new Error('dangling escape in bash command');
|
|
159
|
-
}
|
|
160
|
-
if (quote !== 'none') {
|
|
161
|
-
throw new Error('unterminated quote in bash command');
|
|
162
|
-
}
|
|
163
|
-
pushStage(stages, current);
|
|
164
|
-
return stages;
|
|
165
|
-
}
|
|
166
|
-
function pushStage(stages, stage) {
|
|
167
|
-
const trimmed = stage.trim();
|
|
168
|
-
if (trimmed.length === 0) {
|
|
169
|
-
throw new Error('empty pipeline stage');
|
|
170
|
-
}
|
|
171
|
-
stages.push(trimmed);
|
|
172
|
-
}
|
|
173
|
-
function tokenize(input) {
|
|
174
|
-
const tokens = [];
|
|
175
|
-
let current = '';
|
|
176
|
-
let quote = 'none';
|
|
177
|
-
let escaped = false;
|
|
178
|
-
for (let i = 0; i < input.length; i += 1) {
|
|
179
|
-
const ch = input[i];
|
|
180
|
-
if (ch === undefined) {
|
|
181
|
-
break;
|
|
182
|
-
}
|
|
183
|
-
if (escaped) {
|
|
184
|
-
current += ch;
|
|
185
|
-
escaped = false;
|
|
186
|
-
continue;
|
|
187
|
-
}
|
|
188
|
-
if (quote !== 'single' && ch === '\\') {
|
|
189
|
-
escaped = true;
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
if (quote === 'none' && isWhitespace(ch)) {
|
|
193
|
-
pushToken(tokens, current);
|
|
194
|
-
current = '';
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
if (quote === 'none' && ch === "'") {
|
|
198
|
-
quote = 'single';
|
|
199
|
-
continue;
|
|
200
|
-
}
|
|
201
|
-
if (quote === 'single' && ch === "'") {
|
|
202
|
-
quote = 'none';
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
if (quote === 'none' && ch === '"') {
|
|
206
|
-
quote = 'double';
|
|
207
|
-
continue;
|
|
208
|
-
}
|
|
209
|
-
if (quote === 'double' && ch === '"') {
|
|
210
|
-
quote = 'none';
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
if (quote === 'none' && startsRedirect(input, i)) {
|
|
214
|
-
pushToken(tokens, current);
|
|
215
|
-
current = '';
|
|
216
|
-
const parsed = readRedirect(input, i);
|
|
217
|
-
tokens.push(parsed.token);
|
|
218
|
-
i = parsed.nextIndex - 1;
|
|
219
|
-
continue;
|
|
220
|
-
}
|
|
221
|
-
current += ch;
|
|
222
|
-
}
|
|
223
|
-
if (escaped) {
|
|
224
|
-
throw new Error('dangling escape in bash command');
|
|
225
|
-
}
|
|
226
|
-
if (quote !== 'none') {
|
|
227
|
-
throw new Error('unterminated quote in bash command');
|
|
228
|
-
}
|
|
229
|
-
pushToken(tokens, current);
|
|
230
|
-
return tokens;
|
|
231
|
-
}
|
|
232
|
-
function pushToken(tokens, token) {
|
|
233
|
-
if (token.length > 0) {
|
|
234
|
-
tokens.push(token);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
function startsRedirect(input, index) {
|
|
238
|
-
const ch = input[index];
|
|
239
|
-
if (ch === undefined) {
|
|
240
|
-
return false;
|
|
241
|
-
}
|
|
242
|
-
if (ch === '>' || ch === '<') {
|
|
243
|
-
return true;
|
|
244
|
-
}
|
|
245
|
-
if (!isDigit(ch)) {
|
|
246
|
-
return false;
|
|
247
|
-
}
|
|
248
|
-
let cursor = index;
|
|
249
|
-
while (isDigit(input[cursor] ?? '')) {
|
|
250
|
-
cursor += 1;
|
|
251
|
-
}
|
|
252
|
-
const next = input[cursor];
|
|
253
|
-
return next === '>' || next === '<';
|
|
254
|
-
}
|
|
255
|
-
function readRedirect(input, index) {
|
|
256
|
-
let cursor = index;
|
|
257
|
-
let token = '';
|
|
258
|
-
while (isDigit(input[cursor] ?? '')) {
|
|
259
|
-
const digit = input[cursor];
|
|
260
|
-
if (digit === undefined) {
|
|
261
|
-
break;
|
|
262
|
-
}
|
|
263
|
-
token += digit;
|
|
264
|
-
cursor += 1;
|
|
265
|
-
}
|
|
266
|
-
const first = input[cursor];
|
|
267
|
-
if (first !== '>' && first !== '<') {
|
|
268
|
-
throw new Error('invalid redirect operator');
|
|
269
|
-
}
|
|
270
|
-
token += first;
|
|
271
|
-
cursor += 1;
|
|
272
|
-
const second = input[cursor];
|
|
273
|
-
const third = input[cursor + 1];
|
|
274
|
-
if (first === '>' && second === '>') {
|
|
275
|
-
token += second;
|
|
276
|
-
cursor += 1;
|
|
277
|
-
}
|
|
278
|
-
else if (first === '<' && second === '<' && third === '<') {
|
|
279
|
-
token += `${second}${third}`;
|
|
280
|
-
cursor += 2;
|
|
281
|
-
}
|
|
282
|
-
else if (first === '<' && second === '<') {
|
|
283
|
-
token += second;
|
|
284
|
-
cursor += 1;
|
|
285
|
-
}
|
|
286
|
-
else if ((first === '>' || first === '<') && second === '&') {
|
|
287
|
-
token += second;
|
|
288
|
-
cursor += 1;
|
|
289
|
-
}
|
|
290
|
-
else if (first === '>' && second === '|') {
|
|
291
|
-
token += second;
|
|
292
|
-
cursor += 1;
|
|
293
|
-
}
|
|
294
|
-
else if (first === '<' && second === '>') {
|
|
295
|
-
token += second;
|
|
296
|
-
cursor += 1;
|
|
297
|
-
}
|
|
298
|
-
while (true) {
|
|
299
|
-
const ch = input[cursor];
|
|
300
|
-
if (ch === undefined || isWhitespace(ch) || ch === '"' || ch === "'") {
|
|
301
|
-
break;
|
|
302
|
-
}
|
|
303
|
-
if (ch === '>' || ch === '<') {
|
|
304
|
-
break;
|
|
305
|
-
}
|
|
306
|
-
token += ch;
|
|
307
|
-
cursor += 1;
|
|
308
|
-
}
|
|
309
|
-
return { token, nextIndex: cursor };
|
|
310
|
-
}
|
|
311
|
-
function normalizeStage(rawTokens, envVars, redirects) {
|
|
312
|
-
const withoutEnv = [];
|
|
313
|
-
let commandStarted = false;
|
|
314
|
-
for (const token of rawTokens) {
|
|
315
|
-
if (!commandStarted && isEnvAssignment(token)) {
|
|
316
|
-
const parsed = parseEnvAssignment(token);
|
|
317
|
-
envVars[parsed.name] = parsed.value;
|
|
318
|
-
continue;
|
|
319
|
-
}
|
|
320
|
-
commandStarted = true;
|
|
321
|
-
withoutEnv.push(token);
|
|
322
|
-
}
|
|
323
|
-
const stage = [];
|
|
324
|
-
for (let i = 0; i < withoutEnv.length; i += 1) {
|
|
325
|
-
const token = withoutEnv[i];
|
|
326
|
-
if (token === undefined) {
|
|
327
|
-
continue;
|
|
328
|
-
}
|
|
329
|
-
if (isRedirectToken(token)) {
|
|
330
|
-
if (redirectNeedsOperand(token)) {
|
|
331
|
-
const target = withoutEnv[i + 1];
|
|
332
|
-
if (target === undefined || isRedirectToken(target)) {
|
|
333
|
-
throw new Error('redirect missing target');
|
|
334
|
-
}
|
|
335
|
-
redirects.push(`${token} ${target}`);
|
|
336
|
-
i += 1;
|
|
337
|
-
continue;
|
|
338
|
-
}
|
|
339
|
-
redirects.push(token);
|
|
340
|
-
continue;
|
|
341
|
-
}
|
|
342
|
-
stage.push(token);
|
|
343
|
-
}
|
|
344
|
-
return stage;
|
|
345
|
-
}
|
|
346
|
-
function isEnvAssignment(token) {
|
|
347
|
-
return /^[A-Za-z_][A-Za-z0-9_]*=.*$/u.test(token);
|
|
348
|
-
}
|
|
349
|
-
function parseEnvAssignment(token) {
|
|
350
|
-
const index = token.indexOf('=');
|
|
351
|
-
if (index < 1) {
|
|
352
|
-
throw new Error('invalid environment assignment');
|
|
353
|
-
}
|
|
354
|
-
return {
|
|
355
|
-
name: token.slice(0, index),
|
|
356
|
-
value: token.slice(index + 1),
|
|
357
|
-
};
|
|
358
|
-
}
|
|
359
|
-
function isRedirectToken(token) {
|
|
360
|
-
return /^(?:\d*)?(?:>>?|<|<<|<<<|>\||<>|>&|<&)(?:.+)?$/u.test(token);
|
|
361
|
-
}
|
|
362
|
-
function redirectNeedsOperand(token) {
|
|
363
|
-
return /^(?:\d*)?(?:>>?|<|<<|<<<|>\||<>|>&|<&)$/u.test(token);
|
|
364
|
-
}
|
|
365
|
-
function isWhitespace(ch) {
|
|
366
|
-
return ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r';
|
|
367
|
-
}
|
|
368
|
-
function isDigit(ch) {
|
|
369
|
-
return ch >= '0' && ch <= '9';
|
|
370
|
-
}
|
|
371
|
-
//# sourceMappingURL=bash-parser.js.map
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* bypassPermissions circuit-breaker — .
|
|
3
|
-
*
|
|
4
|
-
* `bypassPermissions` is "skip ALL checks" for trusted scripted runs.
|
|
5
|
-
* Even so, certain commands are catastrophic enough that the gate
|
|
6
|
-
* MUST refuse regardless of mode. This module owns that short list.
|
|
7
|
-
*
|
|
8
|
-
* The breaker is conservative on purpose:
|
|
9
|
-
* - rm -rf against `/`, `~`, or workspace root (`.`)
|
|
10
|
-
* - fork bomb signature (`:(){:|:&};:`)
|
|
11
|
-
* - dd if=/ (raw block-device read or write)
|
|
12
|
-
*
|
|
13
|
-
* False positives are acceptable here — an operator who really wants
|
|
14
|
-
* to nuke their root filesystem can switch to `dontAsk` and re-issue;
|
|
15
|
-
* the breaker is the "are you sure you typed this correctly?" guard,
|
|
16
|
-
* not a hard policy boundary.
|
|
17
|
-
*
|
|
18
|
-
* `evaluateCircuitBreaker` is pure regex matching — no IO, no state.
|
|
19
|
-
* It's called by the gate before any other routing so a bypass-mode
|
|
20
|
-
* session that types `rm -rf /` sees the deny path first.
|
|
21
|
-
*/
|
|
22
|
-
/**
|
|
23
|
-
* Pattern list — kept narrow on purpose. Each entry must match the
|
|
24
|
-
* canonical destructive shape; argv variants without the exact form
|
|
25
|
-
* fall through к the regular `dontAsk` / `bypassPermissions` allow
|
|
26
|
-
* path, which is what the operator opted into.
|
|
27
|
-
*/
|
|
28
|
-
const CIRCUIT_BREAKER_PATTERNS = [
|
|
29
|
-
// rm -rf against absolute root, $HOME, ~, $WORKSPACE_ROOT, or `.`
|
|
30
|
-
// with no further token. The negative lookahead на `[/~.]\S` makes
|
|
31
|
-
// sure `rm -rf /tmp/foo` (specific subtree) doesn't trip — only the
|
|
32
|
-
// catastrophic `rm -rf /` or `rm -rf ~` or `rm -rf .` shapes do.
|
|
33
|
-
{
|
|
34
|
-
pattern: /\brm\s+(-[a-z]*r[a-z]*f|-[a-z]*f[a-z]*r)\s+(\/|~|\$HOME|\$\{HOME\}|\.)\s*$/i,
|
|
35
|
-
reason: 'rm -rf against /, $HOME, ~, or workspace root',
|
|
36
|
-
},
|
|
37
|
-
// Fork bomb signature. Whitespace-tolerant но shape-strict.
|
|
38
|
-
{
|
|
39
|
-
pattern: /:\s*\(\s*\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;?\s*:/,
|
|
40
|
-
reason: 'fork bomb (`:(){ :|:& };:`)',
|
|
41
|
-
},
|
|
42
|
-
// dd to/from raw devices. Either direction is catastrophic enough
|
|
43
|
-
// to warrant the breaker (read of /dev/random into a workspace file
|
|
44
|
-
// can fill the disk, write to /dev/sda destroys the disk).
|
|
45
|
-
{
|
|
46
|
-
pattern: /\bdd\b[^|;&]*\b(if|of)=\/dev\//i,
|
|
47
|
-
reason: 'dd reading/writing /dev/* (catastrophic IO)',
|
|
48
|
-
},
|
|
49
|
-
// mkfs against any disk — single regex covers ext*, xfs, btrfs, vfat.
|
|
50
|
-
{
|
|
51
|
-
pattern: /\bmkfs(\.[a-z0-9]+)?\s+\/dev\//i,
|
|
52
|
-
reason: 'mkfs against /dev/* (filesystem format)',
|
|
53
|
-
},
|
|
54
|
-
];
|
|
55
|
-
/**
|
|
56
|
-
* Test the command against every circuit-breaker pattern. Returns the
|
|
57
|
-
* first match (most-catastrophic-first ordering is encoded в the array
|
|
58
|
-
* order); when no pattern matches, the breaker is `tripped: false` so
|
|
59
|
-
* the caller proceeds to the regular gate decision.
|
|
60
|
-
*
|
|
61
|
-
* Pure function — no IO, no module-scoped state. Safe to call from any
|
|
62
|
-
* surface (gate, doctor command, audit replay).
|
|
63
|
-
*/
|
|
64
|
-
export function evaluateCircuitBreaker(command) {
|
|
65
|
-
const trimmed = command.trim();
|
|
66
|
-
if (trimmed.length === 0)
|
|
67
|
-
return { tripped: false, reason: '' };
|
|
68
|
-
for (const entry of CIRCUIT_BREAKER_PATTERNS) {
|
|
69
|
-
if (entry.pattern.test(trimmed)) {
|
|
70
|
-
return { tripped: true, reason: entry.reason };
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return { tripped: false, reason: '' };
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Diagnostic accessor — exposed для doctor surfaces + spec coverage so
|
|
77
|
-
* the test layer can iterate the full list and assert each entry trips
|
|
78
|
-
* on representative input.
|
|
79
|
-
*/
|
|
80
|
-
export function listCircuitBreakerPatterns() {
|
|
81
|
-
return CIRCUIT_BREAKER_PATTERNS.map((e) => ({ pattern: e.pattern.source, reason: e.reason }));
|
|
82
|
-
}
|
|
83
|
-
//# sourceMappingURL=circuit-breaker.js.map
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import * as path from 'node:path';
|
|
2
|
-
const REGEX_META = new Set(['.', '+', '^', '$', '(', ')', '|', '{', '}', '[', ']', '\\']);
|
|
3
|
-
function globToRegExp(pattern) {
|
|
4
|
-
let re = '';
|
|
5
|
-
let i = 0;
|
|
6
|
-
while (i < pattern.length) {
|
|
7
|
-
const c = pattern[i];
|
|
8
|
-
if (c === '*') {
|
|
9
|
-
if (pattern[i + 1] === '*') {
|
|
10
|
-
re += '.*';
|
|
11
|
-
i += 2;
|
|
12
|
-
if (pattern[i] === '/')
|
|
13
|
-
i += 1;
|
|
14
|
-
}
|
|
15
|
-
else {
|
|
16
|
-
re += '[^/]*';
|
|
17
|
-
i += 1;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
else if (c === '?') {
|
|
21
|
-
re += '[^/]';
|
|
22
|
-
i += 1;
|
|
23
|
-
}
|
|
24
|
-
else if (REGEX_META.has(c)) {
|
|
25
|
-
re += '\\' + c;
|
|
26
|
-
i += 1;
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
re += c;
|
|
30
|
-
i += 1;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return new RegExp('^' + re + '$');
|
|
34
|
-
}
|
|
35
|
-
function toRelPosix(absPath, repoRoot) {
|
|
36
|
-
const normRoot = path.resolve(repoRoot);
|
|
37
|
-
const normPath = path.resolve(absPath);
|
|
38
|
-
const rel = path.relative(normRoot, normPath);
|
|
39
|
-
if (rel === '' || rel.startsWith('..') || path.isAbsolute(rel)) {
|
|
40
|
-
return rel.startsWith('..') || path.isAbsolute(rel) ? null : rel;
|
|
41
|
-
}
|
|
42
|
-
return rel.split(path.sep).join('/');
|
|
43
|
-
}
|
|
44
|
-
export function isPathAllowed(absPath, repoRoot, allowlist) {
|
|
45
|
-
const rel = toRelPosix(absPath, repoRoot);
|
|
46
|
-
if (rel === null)
|
|
47
|
-
return false;
|
|
48
|
-
for (const pattern of allowlist) {
|
|
49
|
-
if (pattern === rel)
|
|
50
|
-
return true;
|
|
51
|
-
if (globToRegExp(pattern).test(rel))
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
const SHELL_OP_SPLIT = /\s*(?:&&|\|\||;|\|)\s*/;
|
|
57
|
-
const ENV_ASSIGN = /^[A-Za-z_][A-Za-z0-9_]*=/;
|
|
58
|
-
export function checkBashCommand(cmd, allowlist) {
|
|
59
|
-
const stages = cmd
|
|
60
|
-
.split(SHELL_OP_SPLIT)
|
|
61
|
-
.map((s) => s.trim())
|
|
62
|
-
.filter((s) => s.length > 0);
|
|
63
|
-
if (stages.length === 0) {
|
|
64
|
-
return { allowed: false, reason: 'empty command' };
|
|
65
|
-
}
|
|
66
|
-
for (const stage of stages) {
|
|
67
|
-
const tokens = stage.split(/\s+/);
|
|
68
|
-
let i = 0;
|
|
69
|
-
while (i < tokens.length && ENV_ASSIGN.test(tokens[i]))
|
|
70
|
-
i += 1;
|
|
71
|
-
const head = tokens[i];
|
|
72
|
-
if (!head) {
|
|
73
|
-
return { allowed: false, reason: `empty stage in command: '${stage}'` };
|
|
74
|
-
}
|
|
75
|
-
if (!allowlist.includes(head)) {
|
|
76
|
-
return { allowed: false, reason: `command '${head}' not in bash_allowlist` };
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return { allowed: true };
|
|
80
|
-
}
|
|
81
|
-
export function verifyTouched(touchedPaths, repoRoot, allowlist) {
|
|
82
|
-
const violations = [];
|
|
83
|
-
for (const p of touchedPaths) {
|
|
84
|
-
const abs = path.isAbsolute(p) ? p : path.resolve(repoRoot, p);
|
|
85
|
-
if (!isPathAllowed(abs, repoRoot, allowlist)) {
|
|
86
|
-
violations.push(p);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return { ok: violations.length === 0, violations };
|
|
90
|
-
}
|
|
91
|
-
//# sourceMappingURL=constrained-edit.js.map
|