@pugi/cli 0.1.0-beta.98 → 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 -192
- 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/core/settings.js
DELETED
|
@@ -1,400 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
-
import { resolve } from 'node:path';
|
|
3
|
-
import { z } from 'zod';
|
|
4
|
-
const pugiSettingsSchema = z.object({
|
|
5
|
-
schema: z.number().int().positive().default(1),
|
|
6
|
-
workflow: z
|
|
7
|
-
.object({
|
|
8
|
-
brand: z.string().default('pugi'),
|
|
9
|
-
legacyName: z.string().optional(),
|
|
10
|
-
approvals: z.enum(['auto', 'manual']).default('auto'),
|
|
11
|
-
notAutomatic: z.array(z.string()).default([]),
|
|
12
|
-
defaultBaseBranch: z.string().default('dev'),
|
|
13
|
-
branchPrefixes: z.array(z.string()).default(['feature', 'fix', 'refactor', 'chore']),
|
|
14
|
-
aiCoAuthorTrailers: z.boolean().default(false),
|
|
15
|
-
})
|
|
16
|
-
.default({}),
|
|
17
|
-
permissions: z
|
|
18
|
-
.object({
|
|
19
|
-
mode: z.enum(['plan', 'ask', 'acceptEdits', 'auto', 'dontAsk', 'bypassPermissions']).default('auto'),
|
|
20
|
-
allow: z.array(z.string()).default([]),
|
|
21
|
-
deny: z.array(z.string()).default([]),
|
|
22
|
-
notAutomatic: z.array(z.string()).default([]),
|
|
23
|
-
// task — operator-declared read-only paths. Every
|
|
24
|
-
// edit / write tool call whose target matches one of these
|
|
25
|
-
// patterns is denied with source `readonly_paths`, regardless
|
|
26
|
-
// of the active permission mode. Match grammar mirrors
|
|
27
|
-
// allow/deny: exact path OR tail-* glob. Targets are
|
|
28
|
-
// workspace-relative, no leading slash.
|
|
29
|
-
//
|
|
30
|
-
// Why a dedicated field вместо leaning on a generic deny rule
|
|
31
|
-
// like `deny: ["edit:vendor/x"]`?
|
|
32
|
-
// - Explicit intent surfaces в `pugi doctor` and the REPL
|
|
33
|
-
// ("3 paths read-only") без parsing rule strings.
|
|
34
|
-
// - Covers BOTH the `edit` tool AND the `write` tool with
|
|
35
|
-
// one entry; a generic deny needs two rules.
|
|
36
|
-
// - Survives a future migration of the `permissions` schema
|
|
37
|
-
// because the field carries its own contract.
|
|
38
|
-
readonlyPaths: z.array(z.string()).default([]),
|
|
39
|
-
})
|
|
40
|
-
.default({}),
|
|
41
|
-
privacy: z
|
|
42
|
-
.object({
|
|
43
|
-
mode: z.enum(['balanced', 'embeddings-only', 'airgapped']).default('balanced'),
|
|
44
|
-
telemetry: z.enum(['off', 'anonymous', 'community']).default('off'),
|
|
45
|
-
})
|
|
46
|
-
.default({}),
|
|
47
|
-
// beta.13 P1 fix: ui.cyberZoo gates the cyber-zoo splash +
|
|
48
|
-
// ambient art in the REPL. Schema must declare the key explicitly
|
|
49
|
-
// because Zod's strip pass swallows unknown keys, which is how the
|
|
50
|
-
// initial `pugi init` write (which serialises `ui.cyberZoo`) was
|
|
51
|
-
// bypassed by the runtime reader — the value never made it past the
|
|
52
|
-
// schema gate so admin-api always saw the historical 'on' default.
|
|
53
|
-
ui: z
|
|
54
|
-
.object({
|
|
55
|
-
cyberZoo: z.enum(['on', 'off']).default('on'),
|
|
56
|
-
})
|
|
57
|
-
.default({}),
|
|
58
|
-
artifacts: z
|
|
59
|
-
.object({
|
|
60
|
-
defaultPath: z.string().default('.pugi/artifacts'),
|
|
61
|
-
promoteExplicitly: z.boolean().default(true),
|
|
62
|
-
})
|
|
63
|
-
.default({}),
|
|
64
|
-
// `web.fetch.enabled` gates the `pugi web` / `/web` SSRF-guarded
|
|
65
|
-
// fetcher. Default-off matches the spec posture; the schema must
|
|
66
|
-
// declare it explicitly because Zod's strict-pass strips unknown
|
|
67
|
-
// keys and would silently swallow the operator's intent.
|
|
68
|
-
//
|
|
69
|
-
// β1b T4 : added `web.search.enabled` to gate the
|
|
70
|
-
// Brave-Search-backed `web_search` tool. Distinct from `web.fetch`
|
|
71
|
-
// because search queries themselves are an egress event that can
|
|
72
|
-
// leak operator intent — an operator may want fetch without
|
|
73
|
-
// implicitly enabling search-as-egress.
|
|
74
|
-
web: z
|
|
75
|
-
.object({
|
|
76
|
-
fetch: z
|
|
77
|
-
.object({
|
|
78
|
-
enabled: z.boolean().optional(),
|
|
79
|
-
})
|
|
80
|
-
.optional(),
|
|
81
|
-
search: z
|
|
82
|
-
.object({
|
|
83
|
-
enabled: z.boolean().optional(),
|
|
84
|
-
})
|
|
85
|
-
.optional(),
|
|
86
|
-
})
|
|
87
|
-
.optional(),
|
|
88
|
-
// β7 L9 — per-language LSP toggle. When omitted, every supported
|
|
89
|
-
// server is available subject to binary detection on PATH. When
|
|
90
|
-
// present, only languages set to `true` are launched (false silently
|
|
91
|
-
// skips that language even if the binary is installed). Use this in
|
|
92
|
-
// workspaces where a heavyweight server (rust-analyzer indexing a
|
|
93
|
-
// monorepo, pyright on a fresh venv) wastes resources for the
|
|
94
|
-
// current task. The `pugi lsp servers` subcommand surfaces the
|
|
95
|
-
// current toggle state per server.
|
|
96
|
-
//
|
|
97
|
-
// Schema is intentionally permissive (`optional()` on the section AND
|
|
98
|
-
// on every per-language flag) so a partial config keeps the
|
|
99
|
-
// backwards-compatible "every language enabled" default.
|
|
100
|
-
lsp: z
|
|
101
|
-
.object({
|
|
102
|
-
typescript: z.boolean().optional(),
|
|
103
|
-
javascript: z.boolean().optional(),
|
|
104
|
-
python: z.boolean().optional(),
|
|
105
|
-
go: z.boolean().optional(),
|
|
106
|
-
rust: z.boolean().optional(),
|
|
107
|
-
// post-edit auto-diagnostics. When `true`,
|
|
108
|
-
// a successful `edit`/`write`/`multi_edit` triggers a diagnostic
|
|
109
|
-
// pull on the touched file(s) and the result is appended to the
|
|
110
|
-
// tool envelope so the model can self-correct in the same turn.
|
|
111
|
-
// Off by default — the cold-start of `typescript-language-server`
|
|
112
|
-
// is heavy enough that we opt in explicitly until dogfood proves
|
|
113
|
-
// the throughput trade is worth it. Also enabled via env var
|
|
114
|
-
// `PUGI_LSP_POST_EDIT=1` for CI / one-off operator probes.
|
|
115
|
-
postEditDiagnostics: z.boolean().optional(),
|
|
116
|
-
})
|
|
117
|
-
.optional(),
|
|
118
|
-
// β1 Pl9 — per-command budget overrides. Optional. Partial
|
|
119
|
-
// overrides merge against the β1 defaults in
|
|
120
|
-
// `core/engine/budgets.ts::beta1DefaultBudgets`. The schema is
|
|
121
|
-
// intentionally loose at the leaf (positive integers) so a typo lands
|
|
122
|
-
// a deterministic `BudgetConfigError` at `resolveBudget()` instead of
|
|
123
|
-
// a Zod parse error two layers up.
|
|
124
|
-
// task — operator-customizable status line.
|
|
125
|
-
// When `command` is set, Pugi spawns it on each turn boundary with
|
|
126
|
-
// a single JSON document on stdin (see `statusline.ts` for the
|
|
127
|
-
// schema). The command's stdout (first non-empty line, trimmed) is
|
|
128
|
-
// displayed in the Ink Footer. Failures are non-fatal — they emit
|
|
129
|
-
// a structured log line and the footer falls back to the default.
|
|
130
|
-
// Mirrors CC's `statusLine` config so cross-tool muscle memory
|
|
131
|
-
// carries over для operators who lived in CC first.
|
|
132
|
-
statusLine: z
|
|
133
|
-
.object({
|
|
134
|
-
command: z.string().min(1),
|
|
135
|
-
timeoutMs: z.number().int().positive().max(5000).default(500),
|
|
136
|
-
})
|
|
137
|
-
.optional(),
|
|
138
|
-
budgets: z
|
|
139
|
-
.object({
|
|
140
|
-
code: z
|
|
141
|
-
.object({ maxTokens: z.number().int().positive().optional(), maxToolCalls: z.number().int().positive().optional() })
|
|
142
|
-
.optional(),
|
|
143
|
-
fix: z
|
|
144
|
-
.object({ maxTokens: z.number().int().positive().optional(), maxToolCalls: z.number().int().positive().optional() })
|
|
145
|
-
.optional(),
|
|
146
|
-
build: z
|
|
147
|
-
.object({ maxTokens: z.number().int().positive().optional(), maxToolCalls: z.number().int().positive().optional() })
|
|
148
|
-
.optional(),
|
|
149
|
-
plan: z
|
|
150
|
-
.object({ maxTokens: z.number().int().positive().optional(), maxToolCalls: z.number().int().positive().optional() })
|
|
151
|
-
.optional(),
|
|
152
|
-
explain: z
|
|
153
|
-
.object({ maxTokens: z.number().int().positive().optional(), maxToolCalls: z.number().int().positive().optional() })
|
|
154
|
-
.optional(),
|
|
155
|
-
review_triple: z
|
|
156
|
-
.object({ maxTokens: z.number().int().positive().optional(), maxToolCalls: z.number().int().positive().optional() })
|
|
157
|
-
.optional(),
|
|
158
|
-
})
|
|
159
|
-
.optional(),
|
|
160
|
-
// #24 (CEO P1) — hook chains. First-class config
|
|
161
|
-
// for `PostToolUseFailure` + `TaskCompleted` event chains. The shape
|
|
162
|
-
// is intentionally loose (`z.any()` at the leaf) because the
|
|
163
|
-
// canonical reader lives in `core/hook-chains.ts` where the
|
|
164
|
-
// matcher/run/timeoutMs grammar is validated. Declaring the key here
|
|
165
|
-
// keeps Zod's strip-pass from swallowing it before the chain reader
|
|
166
|
-
// sees it. See `hook-chains.ts` for the full schema.
|
|
167
|
-
hooks: z.any().optional(),
|
|
168
|
-
// PUGI-260 — persistent default for the 1M context tier opt-in.
|
|
169
|
-
// `pugi config set context.tier 1m` writes this; per-invocation
|
|
170
|
-
// `--context-tier=...` flags override it. When omitted, the CLI
|
|
171
|
-
// sends no `contextTier` field на the wire (server treats as
|
|
172
|
-
// `standard` routing). The closed enum mirrors the CLI flag и the
|
|
173
|
-
// admin-api DTO; an unrecognised value triggers a Zod parse error
|
|
174
|
-
// at load time rather than a silent fallback.
|
|
175
|
-
context: z
|
|
176
|
-
.object({
|
|
177
|
-
tier: z.enum(['1m', 'standard']).optional(),
|
|
178
|
-
})
|
|
179
|
-
.optional(),
|
|
180
|
-
// PUGI-487 - `pugi --worktree` flag governance.
|
|
181
|
-
//
|
|
182
|
-
// Two knobs control the user-facing --worktree flag introduced for
|
|
183
|
-
// parity with parallel-agent isolation patterns in other coding
|
|
184
|
-
// CLIs:
|
|
185
|
-
//
|
|
186
|
-
// - `baseRef`: which ref the new worktree branches FROM.
|
|
187
|
-
// `'fresh'` (default) resolves origin/<default-branch> so each
|
|
188
|
-
// parallel session starts from a clean trunk.
|
|
189
|
-
// `'head'` carries the operator's current local HEAD (including
|
|
190
|
-
// unpushed work) into the new tree.
|
|
191
|
-
//
|
|
192
|
-
// - `cleanupPeriodDays`: integer days. The daily sweep removes
|
|
193
|
-
// user-facing worktrees older than N days that have no
|
|
194
|
-
// uncommitted, untracked, or unpushed state. Default 7 mirrors
|
|
195
|
-
// a one-work-week window. Set to 0 to disable auto-cleanup.
|
|
196
|
-
//
|
|
197
|
-
// Both knobs are optional - the consumers (`bootstrapWorktree`,
|
|
198
|
-
// `runUserWorktreeCleanup`) carry their own defaults so a missing
|
|
199
|
-
// section produces standard behaviour.
|
|
200
|
-
worktree: z
|
|
201
|
-
.object({
|
|
202
|
-
baseRef: z.enum(['fresh', 'head']).optional(),
|
|
203
|
-
cleanupPeriodDays: z.number().int().min(0).max(365).optional(),
|
|
204
|
-
})
|
|
205
|
-
.optional(),
|
|
206
|
-
// Trust Sprint item 6 — bash sandbox adapter selection.
|
|
207
|
-
//
|
|
208
|
-
// `none` — passthrough (existing behaviour, default).
|
|
209
|
-
// `macOS-seatbelt` — wraps spawn calls in `/usr/bin/sandbox-exec`
|
|
210
|
-
// with a profile that allows reads anywhere,
|
|
211
|
-
// denies writes outside workspace + ~/.pugi,
|
|
212
|
-
// and permits standard network egress so
|
|
213
|
-
// `npm install` / `git fetch` still work.
|
|
214
|
-
// `docker` — Linux fallback (NOT shipped in this PR;
|
|
215
|
-
// accepted in the schema so settings.json
|
|
216
|
-
// does not error when operators forward-look
|
|
217
|
-
// at the keyword. Adapter throws at boot if
|
|
218
|
-
// selected today).
|
|
219
|
-
//
|
|
220
|
-
// The bash classifier denylist + permission FSM remain in force on
|
|
221
|
-
// top of the sandbox. This is defence-in-depth: the sandbox bounds
|
|
222
|
-
// what a tool CAN do; the classifier bounds what a tool TRIES.
|
|
223
|
-
bash: z
|
|
224
|
-
.object({
|
|
225
|
-
sandbox: z.enum(['none', 'macOS-seatbelt', 'docker']).optional(),
|
|
226
|
-
})
|
|
227
|
-
.optional(),
|
|
228
|
-
});
|
|
229
|
-
/**
|
|
230
|
-
* #20 — the upstream tool drop-in compat ingest.
|
|
231
|
-
*
|
|
232
|
-
* Operators migrating from the upstream tool typically keep a `.claude/`
|
|
233
|
-
* directory at workspace root with settings.json, slash commands,
|
|
234
|
-
* and ambient guidance files. We honour the existence of that
|
|
235
|
-
* directory and mirror the subset of keys that map cleanly onto
|
|
236
|
-
* Pugi's own settings surface — Pugi values ALWAYS win on conflict
|
|
237
|
-
* (the operator opted into Pugi as their primary), CC fills gaps.
|
|
238
|
-
*
|
|
239
|
-
* Opt-out: `PUGI_CC_COMPAT_DISABLE=1` short-circuits the merger and
|
|
240
|
-
* loads only `.pugi/settings.json` (or the empty default).
|
|
241
|
-
*
|
|
242
|
-
* Key mirror table:
|
|
243
|
-
* - `permissions.defaultMode` → `permissions.mode`
|
|
244
|
-
* (CC values map: `acceptEdits|plan|bypassPermissions|default` →
|
|
245
|
-
* `acceptEdits|plan|bypassPermissions|ask`).
|
|
246
|
-
* - `permissions.allow` → `permissions.allow` (concatenated, deduped).
|
|
247
|
-
* - `permissions.deny` → `permissions.deny` (concatenated, deduped).
|
|
248
|
-
* - `enabledPlugins` → ignored (CC-only concept; Pugi has its own
|
|
249
|
-
* plugin surface and we do not want to silently activate them).
|
|
250
|
-
* - `hooks` → currently ignored. Pugi's hook system is
|
|
251
|
-
* managed via `apps/pugi-cli/src/core/hooks/`; future work can
|
|
252
|
-
* wire CC hook entries through that bridge.
|
|
253
|
-
*
|
|
254
|
-
* Unknown CC keys are dropped on the floor by Zod's strip semantics
|
|
255
|
-
* just like the existing PUGI settings path — we never warn on
|
|
256
|
-
* unrecognised CC keys, because the CC surface is wider and we want
|
|
257
|
-
* fallthrough to be silent (operator does not need a stream of "we
|
|
258
|
-
* skipped this CC concept" warnings on every CLI invocation).
|
|
259
|
-
*/
|
|
260
|
-
const ccPermissionsSchema = z
|
|
261
|
-
.object({
|
|
262
|
-
defaultMode: z.string().optional(),
|
|
263
|
-
allow: z.array(z.string()).optional(),
|
|
264
|
-
deny: z.array(z.string()).optional(),
|
|
265
|
-
})
|
|
266
|
-
.passthrough()
|
|
267
|
-
.optional();
|
|
268
|
-
const ccSettingsSchema = z
|
|
269
|
-
.object({
|
|
270
|
-
permissions: ccPermissionsSchema,
|
|
271
|
-
enabledPlugins: z.unknown().optional(),
|
|
272
|
-
hooks: z.unknown().optional(),
|
|
273
|
-
})
|
|
274
|
-
.passthrough();
|
|
275
|
-
/**
|
|
276
|
-
* Env var that disables ingest entirely. Useful for CI
|
|
277
|
-
* sandboxes where a stray `.claude/` from a parent checkout could
|
|
278
|
-
* otherwise leak permissions into Pugi.
|
|
279
|
-
*/
|
|
280
|
-
export const CC_COMPAT_DISABLE_ENV = 'PUGI_CC_COMPAT_DISABLE';
|
|
281
|
-
/**
|
|
282
|
-
* Map a CC `permissions.defaultMode` to the closest Pugi permission
|
|
283
|
-
* mode. Unknown / missing values map to `undefined` so the caller
|
|
284
|
-
* keeps Pugi's own default.
|
|
285
|
-
*
|
|
286
|
-
* CC's `default` mode = "ask the user for each tool" which is Pugi's
|
|
287
|
-
* `ask` mode. `acceptEdits` / `plan` / `bypassPermissions` map 1:1.
|
|
288
|
-
*/
|
|
289
|
-
export function mapCcPermissionMode(mode) {
|
|
290
|
-
if (typeof mode !== 'string')
|
|
291
|
-
return undefined;
|
|
292
|
-
switch (mode) {
|
|
293
|
-
case 'acceptEdits':
|
|
294
|
-
return 'acceptEdits';
|
|
295
|
-
case 'plan':
|
|
296
|
-
return 'plan';
|
|
297
|
-
case 'bypassPermissions':
|
|
298
|
-
return 'bypassPermissions';
|
|
299
|
-
case 'default':
|
|
300
|
-
return 'ask';
|
|
301
|
-
default:
|
|
302
|
-
return undefined;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* Merge a parsed CC settings object into a Pugi settings object.
|
|
307
|
-
* Pugi ALWAYS wins on conflict; CC values fill gaps only.
|
|
308
|
-
*/
|
|
309
|
-
export function mergeCcIntoPugi(pugi, cc, opts) {
|
|
310
|
-
const merged = {
|
|
311
|
-
...pugi,
|
|
312
|
-
permissions: { ...pugi.permissions },
|
|
313
|
-
};
|
|
314
|
-
const pugiWroteMode = pugiPermissionKeyPresent(opts.pugiRawJson, 'mode');
|
|
315
|
-
if (!pugiWroteMode) {
|
|
316
|
-
const ccMode = mapCcPermissionMode(cc.permissions?.defaultMode);
|
|
317
|
-
if (ccMode)
|
|
318
|
-
merged.permissions.mode = ccMode;
|
|
319
|
-
}
|
|
320
|
-
if (Array.isArray(cc.permissions?.allow)) {
|
|
321
|
-
merged.permissions.allow = dedupeKeepFirst([
|
|
322
|
-
...pugi.permissions.allow,
|
|
323
|
-
...cc.permissions.allow,
|
|
324
|
-
]);
|
|
325
|
-
}
|
|
326
|
-
if (Array.isArray(cc.permissions?.deny)) {
|
|
327
|
-
merged.permissions.deny = dedupeKeepFirst([
|
|
328
|
-
...pugi.permissions.deny,
|
|
329
|
-
...cc.permissions.deny,
|
|
330
|
-
]);
|
|
331
|
-
}
|
|
332
|
-
// `enabledPlugins` and `hooks` are intentionally NOT mirrored. See
|
|
333
|
-
// the doc-block above for rationale.
|
|
334
|
-
void opts.pugiSettingsExisted;
|
|
335
|
-
return merged;
|
|
336
|
-
}
|
|
337
|
-
function pugiPermissionKeyPresent(raw, key) {
|
|
338
|
-
if (!raw || typeof raw !== 'object')
|
|
339
|
-
return false;
|
|
340
|
-
const permissions = raw.permissions;
|
|
341
|
-
if (!permissions || typeof permissions !== 'object')
|
|
342
|
-
return false;
|
|
343
|
-
return Object.prototype.hasOwnProperty.call(permissions, key);
|
|
344
|
-
}
|
|
345
|
-
function dedupeKeepFirst(items) {
|
|
346
|
-
const seen = new Set();
|
|
347
|
-
const out = [];
|
|
348
|
-
for (const item of items) {
|
|
349
|
-
if (seen.has(item))
|
|
350
|
-
continue;
|
|
351
|
-
seen.add(item);
|
|
352
|
-
out.push(item);
|
|
353
|
-
}
|
|
354
|
-
return out;
|
|
355
|
-
}
|
|
356
|
-
/**
|
|
357
|
-
* Read + parse `.claude/settings.json` at `root`. Returns `undefined`
|
|
358
|
-
* when the file is absent, malformed, or the operator has opted out
|
|
359
|
-
* via `PUGI_CC_COMPAT_DISABLE=1`. Never throws — a broken CC settings
|
|
360
|
-
* file degrades to "no ingest", not a Pugi boot crash.
|
|
361
|
-
*/
|
|
362
|
-
export function loadCcSettings(root, env = process.env) {
|
|
363
|
-
if (env[CC_COMPAT_DISABLE_ENV] === '1')
|
|
364
|
-
return undefined;
|
|
365
|
-
const ccPath = resolve(root, '.claude/settings.json');
|
|
366
|
-
if (!existsSync(ccPath))
|
|
367
|
-
return undefined;
|
|
368
|
-
let parsed;
|
|
369
|
-
try {
|
|
370
|
-
parsed = JSON.parse(readFileSync(ccPath, 'utf8'));
|
|
371
|
-
}
|
|
372
|
-
catch {
|
|
373
|
-
return undefined;
|
|
374
|
-
}
|
|
375
|
-
const result = ccSettingsSchema.safeParse(parsed);
|
|
376
|
-
if (!result.success)
|
|
377
|
-
return undefined;
|
|
378
|
-
return result.data;
|
|
379
|
-
}
|
|
380
|
-
export function loadSettings(root, env = process.env) {
|
|
381
|
-
const settingsPath = resolve(root, '.pugi/settings.json');
|
|
382
|
-
const pugiExists = existsSync(settingsPath);
|
|
383
|
-
let pugiRawJson = undefined;
|
|
384
|
-
let pugi;
|
|
385
|
-
if (pugiExists) {
|
|
386
|
-
pugiRawJson = JSON.parse(readFileSync(settingsPath, 'utf8'));
|
|
387
|
-
pugi = pugiSettingsSchema.parse(pugiRawJson);
|
|
388
|
-
}
|
|
389
|
-
else {
|
|
390
|
-
pugi = pugiSettingsSchema.parse({});
|
|
391
|
-
}
|
|
392
|
-
const cc = loadCcSettings(root, env);
|
|
393
|
-
if (!cc)
|
|
394
|
-
return pugi;
|
|
395
|
-
return mergeCcIntoPugi(pugi, cc, {
|
|
396
|
-
pugiSettingsExisted: pugiExists,
|
|
397
|
-
pugiRawJson,
|
|
398
|
-
});
|
|
399
|
-
}
|
|
400
|
-
//# sourceMappingURL=settings.js.map
|
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Markdown transcript formatter used by `pugi share` ().
|
|
3
|
-
*
|
|
4
|
-
* Walks the session's `.pugi/events.jsonl` audit log and reconstructs a
|
|
5
|
-
* Markdown document the operator (and downstream Gist / pugi.io readers)
|
|
6
|
-
* can read top-to-bottom. The format is intentionally human-first — turn
|
|
7
|
-
* headers, code-block-wrapped tool I/O, and a small front-matter block
|
|
8
|
-
* with session metadata. Machine-readability is a non-goal here; the
|
|
9
|
-
* JSONL log remains the source of truth for tooling.
|
|
10
|
-
*
|
|
11
|
-
* Why we reconstruct from JSONL instead of from the live REPL state:
|
|
12
|
-
*
|
|
13
|
-
* - The CLI top-level `pugi share` command runs from a fresh shell and
|
|
14
|
-
* has no in-memory REPL state to read; only the event log is
|
|
15
|
-
* persisted.
|
|
16
|
-
* - The in-REPL `/share` slash uses the same handler so behaviour is
|
|
17
|
-
* identical regardless of entry point. Operators sharing a session
|
|
18
|
-
* from inside the REPL get the exact same output they would get from
|
|
19
|
-
* a follow-up shell command.
|
|
20
|
-
* - The JSONL log is append-only and survives REPL crashes, so a
|
|
21
|
-
* `--share` after a crash is the most useful debug surface.
|
|
22
|
-
*
|
|
23
|
-
* Event vocabulary the formatter knows about (see
|
|
24
|
-
* `packages/pugi-sdk/src/audit-trace.ts` for the schema):
|
|
25
|
-
*
|
|
26
|
-
* session.created Session boundary; emits front matter.
|
|
27
|
-
* session.command_started One-line "running pugi <cmd>" header.
|
|
28
|
-
* session.command_completed Status line ("success" / "error").
|
|
29
|
-
* tool_call Markdown turn header + inputSummary
|
|
30
|
-
* rendered as a fenced block.
|
|
31
|
-
* tool_result "Result (status):" + outputSummary
|
|
32
|
-
* rendered as a fenced block.
|
|
33
|
-
* file_mutation Inline `path` + operation summary.
|
|
34
|
-
* subagent.* Indented "[subagent <role>] ..." line.
|
|
35
|
-
* hook.* Quiet "[hook <event>] ..." line.
|
|
36
|
-
* compaction.* "[compaction <tier>] ..." line.
|
|
37
|
-
*
|
|
38
|
-
* Unknown event types are surfaced as a single italic line ("[event
|
|
39
|
-
* type=...]") so a future event added to the SDK does not silently
|
|
40
|
-
* vanish from the transcript.
|
|
41
|
-
*
|
|
42
|
-
* Performance: the formatter is O(n) over the events file, runs entirely
|
|
43
|
-
* in memory, and is bounded by the session log size (currently capped at
|
|
44
|
-
* a few MB per session). No streaming I/O is needed for typical sessions
|
|
45
|
-
* — the operator does not run /share against multi-GB logs.
|
|
46
|
-
*/
|
|
47
|
-
/**
|
|
48
|
-
* Format a session's event log as Markdown. Pure — no I/O. The caller
|
|
49
|
-
* reads `.pugi/events.jsonl` and hands the contents in.
|
|
50
|
-
*/
|
|
51
|
-
export function formatTranscript(input) {
|
|
52
|
-
const now = input.now ? input.now() : new Date();
|
|
53
|
-
const events = parseEvents(input.eventsJsonl);
|
|
54
|
-
const filteredSessionId = pickSessionId(input.sessionId, events);
|
|
55
|
-
const sessionEvents = events.filter((e) => typeof e.raw.sessionId !== 'string' || e.raw.sessionId === filteredSessionId);
|
|
56
|
-
const lines = [];
|
|
57
|
-
// Front matter — a fenced block at the top so downstream readers can
|
|
58
|
-
// grok the context before any turn content. Not YAML front matter
|
|
59
|
-
// (`---`) because Gist + pugi.io render Markdown directly; the fenced
|
|
60
|
-
// approach renders predictably without a parser.
|
|
61
|
-
lines.push('# Pugi session transcript');
|
|
62
|
-
lines.push('');
|
|
63
|
-
lines.push('```');
|
|
64
|
-
lines.push(`session_id: ${filteredSessionId}`);
|
|
65
|
-
lines.push(`workspace: ${input.workspaceRoot}`);
|
|
66
|
-
lines.push(`cli_version: ${input.cliVersion}`);
|
|
67
|
-
lines.push(`exported_at: ${now.toISOString()}`);
|
|
68
|
-
lines.push(`event_count: ${sessionEvents.length}`);
|
|
69
|
-
lines.push('```');
|
|
70
|
-
lines.push('');
|
|
71
|
-
if (sessionEvents.length === 0) {
|
|
72
|
-
lines.push('_No events recorded for this session._');
|
|
73
|
-
return {
|
|
74
|
-
markdown: `${lines.join('\n')}\n`,
|
|
75
|
-
turnCount: 0,
|
|
76
|
-
eventCount: 0,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
let turnCount = 0;
|
|
80
|
-
for (const event of sessionEvents) {
|
|
81
|
-
const rendered = renderEvent(event);
|
|
82
|
-
if (rendered === null)
|
|
83
|
-
continue;
|
|
84
|
-
lines.push(...rendered.lines);
|
|
85
|
-
lines.push('');
|
|
86
|
-
if (rendered.isTurn)
|
|
87
|
-
turnCount += 1;
|
|
88
|
-
}
|
|
89
|
-
return {
|
|
90
|
-
markdown: `${lines.join('\n').replace(/\n{3,}/g, '\n\n')}\n`,
|
|
91
|
-
turnCount,
|
|
92
|
-
eventCount: sessionEvents.length,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Parse the JSONL log. Malformed lines are skipped silently — the file
|
|
97
|
-
* is append-only and may have partial-write tail rows. Returning the
|
|
98
|
-
* stable typed shape lets the formatter walk without re-checking every
|
|
99
|
-
* field.
|
|
100
|
-
*/
|
|
101
|
-
function parseEvents(raw) {
|
|
102
|
-
const out = [];
|
|
103
|
-
for (const line of raw.split('\n')) {
|
|
104
|
-
const trimmed = line.trim();
|
|
105
|
-
if (trimmed.length === 0)
|
|
106
|
-
continue;
|
|
107
|
-
try {
|
|
108
|
-
const parsed = JSON.parse(trimmed);
|
|
109
|
-
const type = typeof parsed.type === 'string' ? parsed.type : '';
|
|
110
|
-
const timestamp = typeof parsed.timestamp === 'string' ? parsed.timestamp : '';
|
|
111
|
-
if (type.length === 0)
|
|
112
|
-
continue;
|
|
113
|
-
out.push({ raw: parsed, type, timestamp });
|
|
114
|
-
}
|
|
115
|
-
catch {
|
|
116
|
-
// partial-write or corrupt row; skip without affecting the rest
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return out;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Resolve the effective session id. When the operator passes a non-empty
|
|
123
|
-
* value we honour it. When they pass an empty string / placeholder
|
|
124
|
-
* (`'no-session'`), we fall back to the newest `session.created` event
|
|
125
|
-
* id in the file. Last-resort fallback is the literal placeholder so the
|
|
126
|
-
* transcript still renders something meaningful in the front matter.
|
|
127
|
-
*/
|
|
128
|
-
function pickSessionId(provided, events) {
|
|
129
|
-
if (provided && provided !== 'no-session')
|
|
130
|
-
return provided;
|
|
131
|
-
for (let i = events.length - 1; i >= 0; i -= 1) {
|
|
132
|
-
const e = events[i];
|
|
133
|
-
if (!e)
|
|
134
|
-
continue;
|
|
135
|
-
if (e.type === 'session' && e.raw.name === 'created' && typeof e.raw.sessionId === 'string') {
|
|
136
|
-
return e.raw.sessionId;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return provided || 'unknown-session';
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Format one event as a Markdown block. Returns `null` to suppress the
|
|
143
|
-
* event entirely (e.g. session.created is captured in front matter so we
|
|
144
|
-
* skip it here).
|
|
145
|
-
*/
|
|
146
|
-
function renderEvent(event) {
|
|
147
|
-
const ts = event.timestamp || '';
|
|
148
|
-
switch (event.type) {
|
|
149
|
-
case 'session': {
|
|
150
|
-
const name = String(event.raw.name ?? '');
|
|
151
|
-
if (name === 'created')
|
|
152
|
-
return null; // captured by front matter
|
|
153
|
-
if (name === 'command_started') {
|
|
154
|
-
const command = String(event.raw.command ?? '');
|
|
155
|
-
return {
|
|
156
|
-
lines: [`## ${ts} — command \`${escapeInline(command)}\``],
|
|
157
|
-
isTurn: false,
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
if (name === 'command_completed') {
|
|
161
|
-
const command = String(event.raw.command ?? '');
|
|
162
|
-
const status = String(event.raw.status ?? 'unknown');
|
|
163
|
-
return {
|
|
164
|
-
lines: [`_command \`${escapeInline(command)}\` finished: ${status}_`],
|
|
165
|
-
isTurn: false,
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
return {
|
|
169
|
-
lines: [`_session ${name}_`],
|
|
170
|
-
isTurn: false,
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
case 'tool_call': {
|
|
174
|
-
const tool = String(event.raw.tool ?? 'unknown');
|
|
175
|
-
const summary = String(event.raw.inputSummary ?? '');
|
|
176
|
-
const out = [`### ${ts} — tool \`${escapeInline(tool)}\``];
|
|
177
|
-
if (summary.length > 0) {
|
|
178
|
-
out.push('');
|
|
179
|
-
out.push('Input:');
|
|
180
|
-
out.push(fenced(summary));
|
|
181
|
-
}
|
|
182
|
-
return { lines: out, isTurn: true };
|
|
183
|
-
}
|
|
184
|
-
case 'tool_result': {
|
|
185
|
-
const status = String(event.raw.status ?? 'unknown');
|
|
186
|
-
const summary = String(event.raw.outputSummary ?? '');
|
|
187
|
-
const out = [`Result (${status}):`];
|
|
188
|
-
if (summary.length > 0) {
|
|
189
|
-
out.push(fenced(summary));
|
|
190
|
-
}
|
|
191
|
-
return { lines: out, isTurn: false };
|
|
192
|
-
}
|
|
193
|
-
case 'file_mutation': {
|
|
194
|
-
const path = String(event.raw.path ?? '');
|
|
195
|
-
const op = String(event.raw.operation ?? '');
|
|
196
|
-
return {
|
|
197
|
-
lines: [`- file ${op}: \`${escapeInline(path)}\``],
|
|
198
|
-
isTurn: false,
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
case 'subagent.spawned':
|
|
202
|
-
case 'subagent.tool_call':
|
|
203
|
-
case 'subagent.completed':
|
|
204
|
-
case 'subagent.blocked':
|
|
205
|
-
case 'subagent.failed': {
|
|
206
|
-
const role = String(event.raw.role ?? '');
|
|
207
|
-
const persona = String(event.raw.personaSlug ?? '');
|
|
208
|
-
const detail = String(event.raw.detail ?? event.raw.error ?? event.raw.toolName ?? '');
|
|
209
|
-
const tail = detail.length > 0 ? ` ${detail}` : '';
|
|
210
|
-
return {
|
|
211
|
-
lines: [`_[subagent ${role} / ${persona}] ${event.type}${tail}_`],
|
|
212
|
-
isTurn: false,
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
case 'hook.invoked':
|
|
216
|
-
case 'hook.result':
|
|
217
|
-
case 'hook.skipped': {
|
|
218
|
-
const ev = String(event.raw.event ?? '');
|
|
219
|
-
const reason = String(event.raw.reason ?? event.raw.runSummary ?? event.raw.matchSummary ?? '');
|
|
220
|
-
const tail = reason.length > 0 ? ` ${reason}` : '';
|
|
221
|
-
return {
|
|
222
|
-
lines: [`_[hook ${ev}] ${event.type.replace('hook.', '')}${tail}_`],
|
|
223
|
-
isTurn: false,
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
case 'compaction.started':
|
|
227
|
-
case 'compaction.completed':
|
|
228
|
-
case 'compaction.skipped':
|
|
229
|
-
case 'compaction.invariant_violated': {
|
|
230
|
-
const tier = String(event.raw.tier ?? '');
|
|
231
|
-
return {
|
|
232
|
-
lines: [`_[compaction ${tier}] ${event.type.replace('compaction.', '')}_`],
|
|
233
|
-
isTurn: false,
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
default: {
|
|
237
|
-
return {
|
|
238
|
-
lines: [`_[event type=${event.type}]_`],
|
|
239
|
-
isTurn: false,
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* Wrap a string in a fenced code block. Pick a fence length that does
|
|
246
|
-
* not collide with backtick runs inside the content. Markdown 0.30 allows
|
|
247
|
-
* variable-length fences; we pick the shortest that is longer than the
|
|
248
|
-
* longest run inside the content (min 3, max 7).
|
|
249
|
-
*/
|
|
250
|
-
function fenced(content) {
|
|
251
|
-
const longestRun = (content.match(/`+/g) ?? [])
|
|
252
|
-
.map((s) => s.length)
|
|
253
|
-
.reduce((max, n) => (n > max ? n : max), 0);
|
|
254
|
-
const fenceLen = Math.min(7, Math.max(3, longestRun + 1));
|
|
255
|
-
const fence = '`'.repeat(fenceLen);
|
|
256
|
-
// Trim trailing whitespace inside content so the closing fence sits
|
|
257
|
-
// tight against the body; preserve leading whitespace (matters for code).
|
|
258
|
-
return `${fence}\n${content.replace(/\s+$/u, '')}\n${fence}`;
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* Escape inline-Markdown specials (backtick, pipe) inside a span that we
|
|
262
|
-
* are wrapping in inline code. The closing backtick rule says a `<code>`
|
|
263
|
-
* span can contain backticks as long as the fence length differs — for
|
|
264
|
-
* simplicity we replace bare backticks with a Unicode look-alike when
|
|
265
|
-
* they appear in identifier-like positions (e.g. paths or tool names).
|
|
266
|
-
* Backticks in real content go through `fenced()` instead.
|
|
267
|
-
*/
|
|
268
|
-
function escapeInline(text) {
|
|
269
|
-
return text.replace(/`/g, 'ˋ');
|
|
270
|
-
}
|
|
271
|
-
//# sourceMappingURL=formatter.js.map
|