@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/tui/repl.js
DELETED
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* REPL root component - Sprint .
|
|
4
|
-
*
|
|
5
|
-
* Three-zone layout:
|
|
6
|
-
*
|
|
7
|
-
* header - `Pugi.io · workspace: <name> · v<X> on watch`
|
|
8
|
-
* main - conversation pane (top half) + agent tree (bottom half)
|
|
9
|
-
* footer - input box + status bar + key hints
|
|
10
|
-
*
|
|
11
|
-
* The component subscribes to a ReplSession instance for state. It does
|
|
12
|
-
* NOT own the SSE client or the transport - the session module does.
|
|
13
|
-
* This keeps the component a pure render over a typed state plus three
|
|
14
|
-
* callbacks (submit, exit, overlay request).
|
|
15
|
-
*
|
|
16
|
-
* Overlays (`/help`, `/agents`) are rendered as full-pane modals that
|
|
17
|
-
* eclipse the main area so they read top-to-bottom even on small
|
|
18
|
-
* terminals. Pressing any key dismisses an overlay.
|
|
19
|
-
*/
|
|
20
|
-
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
21
|
-
import { Box, Text, useApp, useInput } from 'ink';
|
|
22
|
-
import { PUGI_TAGLINE, THE_TEN } from '@pugi/personas';
|
|
23
|
-
import { AgentTreePane } from './agent-tree-pane.js';
|
|
24
|
-
import { AskModal, PlanReviewModal } from './ask-modal.js';
|
|
25
|
-
import { ConversationPane } from './conversation-pane.js';
|
|
26
|
-
import { InputBox } from './input-box.js';
|
|
27
|
-
import { ReplSplash } from './repl-splash.js';
|
|
28
|
-
import { StatusBar } from './status-bar.js';
|
|
29
|
-
import { ThinkingSpinner } from './thinking-spinner.js';
|
|
30
|
-
import { ToolStreamPane } from './tool-stream-pane.js';
|
|
31
|
-
import { UpdateBanner } from './update-banner.js';
|
|
32
|
-
import { WelcomeBanner } from './welcome-banner.js';
|
|
33
|
-
import { collectWorkspaceContext } from './workspace-context.js';
|
|
34
|
-
import { useTheme } from '../core/theme/context.js';
|
|
35
|
-
import { slugForCwd } from '../core/repl/history.js';
|
|
36
|
-
import { SLASH_COMMAND_HELP, SLASH_COMMAND_GROUPS } from '../core/repl/slash-commands.js';
|
|
37
|
-
const TICK_INTERVAL_MS = 200;
|
|
38
|
-
const PULSE_INTERVAL_MS = 700;
|
|
39
|
-
// : maximum transcript rows the conversation pane renders at once.
|
|
40
|
-
// Older rows scroll off the top; full history stays in session state.
|
|
41
|
-
const CONVERSATION_WINDOW = 12;
|
|
42
|
-
export function Repl(props) {
|
|
43
|
-
const [state, setState] = useState(props.session.getState());
|
|
44
|
-
const [overlay, setOverlay] = useState('none');
|
|
45
|
-
const [pulsePhase, setPulsePhase] = useState(0);
|
|
46
|
-
const [tickNow, setTickNow] = useState((props.now ?? Date.now)());
|
|
47
|
-
// : operator-driven collapse for the tool stream pane. The CLI
|
|
48
|
-
// host can hide the pane entirely via `--no-tool-stream`; this state
|
|
49
|
-
// is the runtime toggle (Ctrl+T) for operators who want the pane on
|
|
50
|
-
// screen but folded to a single row while they read a long reply.
|
|
51
|
-
const [toolStreamCollapsed, setToolStreamCollapsed] = useState(false);
|
|
52
|
-
// wave 3: boot splash visible until first input, first
|
|
53
|
-
// `agent.spawned` event, or 10s idle. The host gates the initial
|
|
54
|
-
// visibility on `--no-splash` / PUGI_SKIP_SPLASH via `skipSplash`.
|
|
55
|
-
// CEO dogfood: default splash to HIDDEN at boot
|
|
56
|
-
// (parity with the upstream tool's minimal one-line banner). Operator can
|
|
57
|
-
// opt back in via `/splash` slash. The chafa pug pre-print + header
|
|
58
|
-
// line already give the brand cue without the multi-row Plan/Model/
|
|
59
|
-
// Tenant block crowding the top.
|
|
60
|
-
const [splashVisible, setSplashVisible] = useState(false);
|
|
61
|
-
const dismissSplash = useCallback(() => setSplashVisible(false), []);
|
|
62
|
-
// CEO P0 #2 : welcome banner. Visible from boot
|
|
63
|
-
// until the operator submits the first brief OR the session emits
|
|
64
|
-
// its first agent event. The host owns dismissal lifecycle (kept
|
|
65
|
-
// symmetric with the splash) so the welcome card never lingers
|
|
66
|
-
// behind а live transcript.
|
|
67
|
-
const [welcomeVisible, setWelcomeVisible] = useState(Boolean(props.welcomeData));
|
|
68
|
-
// wave 3: workspace context snapshot for the status bar. We
|
|
69
|
-
// read once at mount and freeze; a brand-new PUGI.md or skill is
|
|
70
|
-
// surfaced on the next REPL boot rather than via a watcher.
|
|
71
|
-
const workspaceContext = useMemo(() => props.workspaceContext ?? collectWorkspaceContext(process.cwd()), [props.workspaceContext]);
|
|
72
|
-
// Subscribe to session state updates. The session module fires the
|
|
73
|
-
// callback synchronously inside `patch` so we mirror without a
|
|
74
|
-
// batching layer.
|
|
75
|
-
useEffect(() => {
|
|
76
|
-
const unsubscribe = props.session.subscribe(setState);
|
|
77
|
-
return unsubscribe;
|
|
78
|
-
}, [props.session]);
|
|
79
|
-
// 200ms tick for the status-bar wall-clock + token counter rerender.
|
|
80
|
-
// Cheaper than re-mounting the session subscription and lets the
|
|
81
|
-
// status bar lag the dispatcher events by at most one frame.
|
|
82
|
-
useEffect(() => {
|
|
83
|
-
const interval = setInterval(() => {
|
|
84
|
-
setTickNow((props.now ?? Date.now)());
|
|
85
|
-
}, TICK_INTERVAL_MS);
|
|
86
|
-
return () => clearInterval(interval);
|
|
87
|
-
}, [props.now]);
|
|
88
|
-
// Pulse the on-watch dot every 700ms. Three glyphs cycle, so the
|
|
89
|
-
// operator sees a gentle three-step animation rather than a binary
|
|
90
|
-
// blink. Subtle by design - brand voice forbids flashing.
|
|
91
|
-
useEffect(() => {
|
|
92
|
-
const interval = setInterval(() => {
|
|
93
|
-
setPulsePhase((prev) => (prev + 1) % 3);
|
|
94
|
-
}, PULSE_INTERVAL_MS);
|
|
95
|
-
return () => clearInterval(interval);
|
|
96
|
-
}, []);
|
|
97
|
-
useEffect(() => {
|
|
98
|
-
props.onOverlayChange?.(overlay);
|
|
99
|
-
}, [overlay, props]);
|
|
100
|
-
// wave 3: dismiss the boot splash once the first agent spawns
|
|
101
|
-
// (the operator has clearly engaged the system) or the transcript
|
|
102
|
-
// gains a row. Mirrors the natural attention shift the upstream tool /
|
|
103
|
-
// Codex / Gemini CLI all do on their boot screens.
|
|
104
|
-
useEffect(() => {
|
|
105
|
-
if (!splashVisible)
|
|
106
|
-
return;
|
|
107
|
-
if (state.agents.length > 0 || state.transcript.length > 0) {
|
|
108
|
-
setSplashVisible(false);
|
|
109
|
-
}
|
|
110
|
-
}, [splashVisible, state.agents.length, state.transcript.length]);
|
|
111
|
-
// CEO P0 #2 v2: welcome banner stays until the operator
|
|
112
|
-
// actively engages the loop — first agent spawn. Boot-time auto-init
|
|
113
|
-
// emits system rows into `state.transcript` (skip-trust hints, dirty
|
|
114
|
-
// tree warnings) which used к dismiss the banner within ~2s, hiding
|
|
115
|
-
// the brand mascot before the operator could read it. Drop the
|
|
116
|
-
// `transcript.length` trigger; agent spawn (= real dispatch) remains
|
|
117
|
-
// the sole signal that the operator stopped reading the banner.
|
|
118
|
-
useEffect(() => {
|
|
119
|
-
if (!welcomeVisible)
|
|
120
|
-
return;
|
|
121
|
-
if (state.agents.length > 0) {
|
|
122
|
-
setWelcomeVisible(false);
|
|
123
|
-
}
|
|
124
|
-
}, [welcomeVisible, state.agents.length]);
|
|
125
|
-
const personaNames = useMemo(() => buildPersonaNameMap(), []);
|
|
126
|
-
const { exit } = useApp();
|
|
127
|
-
const handleSubmit = useCallback((line) => {
|
|
128
|
-
// Dismiss the boot splash on first operator input. Idempotent —
|
|
129
|
-
// `setSplashVisible(false)` is a no-op once the state already
|
|
130
|
-
// settled to false (timer fired or `agent.spawned` arrived).
|
|
131
|
-
setSplashVisible(false);
|
|
132
|
-
// CEO P0 #2 : same dismissal for the welcome banner
|
|
133
|
-
// — the operator engaging the input box is the cleanest signal
|
|
134
|
-
// they have finished reading the boot card.
|
|
135
|
-
setWelcomeVisible(false);
|
|
136
|
-
// Run async without awaiting - the session module owns the
|
|
137
|
-
// network call, errors land in the transcript automatically.
|
|
138
|
-
void props.session.handleInput(line).then((verdict) => {
|
|
139
|
-
applyVerdictSideEffects(verdict, {
|
|
140
|
-
showHelp: () => setOverlay('help'),
|
|
141
|
-
showRoster: () => setOverlay('roster'),
|
|
142
|
-
farewell: () => {
|
|
143
|
-
setOverlay('farewell');
|
|
144
|
-
setTimeout(() => {
|
|
145
|
-
props.session.close();
|
|
146
|
-
exit();
|
|
147
|
-
}, 800);
|
|
148
|
-
},
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
}, [props.session, exit]);
|
|
152
|
-
const handleExit = useCallback(() => {
|
|
153
|
-
setOverlay('farewell');
|
|
154
|
-
setTimeout(() => {
|
|
155
|
-
props.session.close();
|
|
156
|
-
exit();
|
|
157
|
-
}, 400);
|
|
158
|
-
}, [props.session, exit]);
|
|
159
|
-
// Any keystroke dismisses an overlay; mounting useInput at the root
|
|
160
|
-
// gives us the dismiss without colliding with the input box (which
|
|
161
|
-
// unmounts while an overlay is active).
|
|
162
|
-
useInput((_input, _key) => {
|
|
163
|
-
if (overlay !== 'none' && overlay !== 'farewell') {
|
|
164
|
-
setOverlay('none');
|
|
165
|
-
}
|
|
166
|
-
}, { isActive: overlay === 'help' || overlay === 'roster' });
|
|
167
|
-
// : Ctrl+T toggles the tool stream pane between expanded and
|
|
168
|
-
// collapsed states. Active only while no overlay is open, so the
|
|
169
|
-
// toggle never fights the help/roster dismiss handler. The input box
|
|
170
|
-
// owns its own raw-input mode, so this listener only fires on the
|
|
171
|
-
// global Ctrl+T binding rather than every printable keystroke.
|
|
172
|
-
useInput((input, key) => {
|
|
173
|
-
if (key.ctrl && input === 't') {
|
|
174
|
-
setToolStreamCollapsed((prev) => !prev);
|
|
175
|
-
}
|
|
176
|
-
}, { isActive: overlay === 'none' && props.hideToolStream !== true });
|
|
177
|
-
// office-hours: a pending ask or plan-review modal pauses input
|
|
178
|
-
// until the operator resolves it. The modal owns its own useInput
|
|
179
|
-
// hook, so the InputBox unmounts while a modal is open to avoid two
|
|
180
|
-
// raw-input listeners competing for the same keystroke. Resolution
|
|
181
|
-
// forwards through ReplSession.resolveAsk / resolvePlanReview.
|
|
182
|
-
const askPending = state.pendingAsk !== null;
|
|
183
|
-
const planPending = state.pendingPlanReview !== null;
|
|
184
|
-
const modalActive = askPending || planPending;
|
|
185
|
-
const handleAskResolve = useCallback((verdict) => {
|
|
186
|
-
void props.session.resolveAsk(verdict);
|
|
187
|
-
}, [props.session]);
|
|
188
|
-
const handlePlanReviewResolve = useCallback((result) => {
|
|
189
|
-
void props.session.resolvePlanReview(result);
|
|
190
|
-
}, [props.session]);
|
|
191
|
-
// : Ctrl+C abort handler. Forwards to ReplSession.cancel() which
|
|
192
|
-
// aborts the in-flight dispatch, closes the SSE stream, and surfaces
|
|
193
|
-
// "Aborted." in the transcript.
|
|
194
|
-
//
|
|
195
|
-
// Return contract (consumed by InputBox):
|
|
196
|
-
// - true - dispatch was cancelled (keep the buffer + DO arm
|
|
197
|
-
// the press-again-to-exit timer; second Ctrl+C in
|
|
198
|
-
// the window exits).
|
|
199
|
-
// - false - idle / nothing to cancel (legacy: clear buffer +
|
|
200
|
-
// arm the exit timer so the operator sees the hint
|
|
201
|
-
// and can confirm exit on the next press).
|
|
202
|
-
// - undefined - bypassed entirely (e.g. a modal owns the input).
|
|
203
|
-
// InputBox MUST NOT arm the exit timer and MUST
|
|
204
|
-
// NOT clear the buffer. P2 fix: previously this
|
|
205
|
-
// returned `false` and the buffer-clear path wiped
|
|
206
|
-
// the operator's mid-typed modal text on the first
|
|
207
|
-
// Ctrl+C, costing a press of work.
|
|
208
|
-
const handleCancel = useCallback(() => {
|
|
209
|
-
if (modalActive)
|
|
210
|
-
return undefined;
|
|
211
|
-
return props.session.cancel();
|
|
212
|
-
}, [props.session, modalActive]);
|
|
213
|
-
// BT 8 (the upstream tool parity): Esc-Esc walkback. Forwards to
|
|
214
|
-
// ReplSession.walkbackLastTurn which trims the trailing operator
|
|
215
|
-
// turn + its persona response from the in-memory transcript. Returns
|
|
216
|
-
// `'walked-back'` so the input box knows the host did the work;
|
|
217
|
-
// `'nothing'` covers both the empty-transcript and dispatch-in-flight
|
|
218
|
-
// refusals (the session module owns the refusal copy in both cases).
|
|
219
|
-
const handleWalkback = useCallback(() => {
|
|
220
|
-
if (modalActive)
|
|
221
|
-
return 'nothing';
|
|
222
|
-
const verdict = props.session.walkbackLastTurn();
|
|
223
|
-
return verdict === 'walked-back' ? 'walked-back' : 'nothing';
|
|
224
|
-
}, [props.session, modalActive]);
|
|
225
|
-
// — Shift+Tab cycles the 6 canonical permission modes (CC
|
|
226
|
-
// parity). Refuses while a modal is active so the operator does not
|
|
227
|
-
// accidentally flip mode mid-prompt; otherwise resolves the current
|
|
228
|
-
// mode through the workspace > global > default merge, advances via
|
|
229
|
-
// `nextPermissionMode`, и persists к .pugi/session.json. Returns the
|
|
230
|
-
// new mode string so the InputBox can flash a one-line toast.
|
|
231
|
-
const handleCyclePermissionMode = useCallback(() => {
|
|
232
|
-
if (modalActive)
|
|
233
|
-
return null;
|
|
234
|
-
try {
|
|
235
|
-
// Lazy-require так this code path doesn't drag the permissions
|
|
236
|
-
// module into the splash + boot stages where it isn't needed.
|
|
237
|
-
// The require is sync but the inner work is pure JSON IO.
|
|
238
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
239
|
-
const perm = require('../core/permissions/index.js');
|
|
240
|
-
const workspaceRoot = process.cwd();
|
|
241
|
-
const current = perm.resolveMode({ workspaceRoot });
|
|
242
|
-
const next = perm.nextPermissionMode(current);
|
|
243
|
-
perm.setCurrentMode(workspaceRoot, next);
|
|
244
|
-
return next;
|
|
245
|
-
}
|
|
246
|
-
catch {
|
|
247
|
-
// Persistence is best-effort — if .pugi/session.json is read-only
|
|
248
|
-
// или ENOENT-on-parent the toast is suppressed so we don't lie
|
|
249
|
-
// about the flip к the operator.
|
|
250
|
-
return null;
|
|
251
|
-
}
|
|
252
|
-
}, [modalActive]);
|
|
253
|
-
// CEO dogfood (parity with the upstream tool): input
|
|
254
|
-
// box pinned to alt-screen BOTTOM, conversation grows above it.
|
|
255
|
-
// Beta.3's height={rows} fix broke keystroke focus - raw echo at
|
|
256
|
-
// viewport bottom. The right pattern is minHeight on the root +
|
|
257
|
-
// flexGrow=1 on the MainArea Box: empty alt-screen lives ABOVE the
|
|
258
|
-
// input, and the input stays the sole focusable surface adjacent
|
|
259
|
-
// to the cursor row, so all keystrokes route through it.
|
|
260
|
-
const altScreenRows = process.stdout.rows ?? 24;
|
|
261
|
-
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, minHeight: altScreenRows, children: [welcomeVisible && props.welcomeData ? (_jsx(WelcomeBanner, { data: props.welcomeData, mascotPrePrinted: props.mascotPrePrinted === true, autoInitStatus: props.autoInitStatus ?? null })) : null, splashVisible ? (_jsx(ReplSplash, { cliVersion: state.cliVersion, workspaceLabel: state.workspaceLabel, plan: props.splashPlan, model: props.splashModel, tenant: props.splashTenant, onDismiss: dismissSplash, mascotPrePrinted: props.mascotPrePrinted === true })) : null, _jsx(Header, { state: state }), _jsx(Box, { flexDirection: "column", marginTop: 1, flexGrow: 1, justifyContent: "flex-end", children: overlay === 'help' ? (_jsx(HelpOverlay, {})) : overlay === 'roster' ? (_jsx(RosterOverlay, {})) : overlay === 'farewell' ? (_jsx(FarewellOverlay, {})) : (_jsx(MainArea, { state: state, personaNames: personaNames, nowEpochMs: tickNow, hideToolStream: props.hideToolStream === true, toolStreamCollapsed: toolStreamCollapsed })) }), state.pendingAsk ? (_jsx(Box, { marginTop: 1, children: _jsx(AskModal, { tag: state.pendingAsk, onResolve: handleAskResolve }) })) : null, state.pendingPlanReview ? (_jsx(Box, { marginTop: 1, children: _jsx(PlanReviewModal, { tag: state.pendingPlanReview, onResolve: handlePlanReviewResolve }) })) : null, _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [overlay === 'farewell' || modalActive ? null : (_jsx(InputBox, { onSubmit: handleSubmit, onExit: handleExit, onCancel: handleCancel, onWalkback: handleWalkback, onCyclePermissionMode: handleCyclePermissionMode, now: props.now,
|
|
262
|
-
// Slug from process.cwd() (full path) so two workspaces with
|
|
263
|
-
// the same basename do not share history. state.workspaceLabel
|
|
264
|
-
// is the basename only. Codex review P2.
|
|
265
|
-
workspaceSlug: slugForCwd(process.cwd()) })), _jsx(ThinkingSpinner, { dispatchState: state.dispatchState, dispatchToolLabel: state.dispatchToolLabel }), _jsx(StatusBar, { connection: state.connection, activeAgentCount: countActive(state), tokensDownstreamTotal: state.tokensDownstreamTotal, briefStartedAtEpochMs: state.briefStartedAtEpochMs, nowEpochMs: tickNow, pulsePhase: pulsePhase, pugiMdCount: workspaceContext.pugiMdCount, mcpServerCount: workspaceContext.mcpServerCount, skillCount: workspaceContext.skillCount, quotaPct: props.quotaPct, dispatchState: state.dispatchState, dispatchToolLabel: state.dispatchToolLabel, lastCompletedOutcome: state.lastCompletedOutcome,
|
|
266
|
-
// cost-meter sprint — surface accumulated session totals
|
|
267
|
-
// + per-turn delta flash on the status bar's top row. The
|
|
268
|
-
// session module owns accumulation; the bar is a pure render.
|
|
269
|
-
sessionTokensIn: state.sessionTokensIn, sessionTokensOut: state.sessionTokensOut, sessionCostUsd: state.sessionCostUsd, sessionStartedAtEpochMs: state.sessionStartedAtEpochMs, lastTurnDelta: state.lastTurnDelta }), props.updateBanner ? _jsx(UpdateBanner, { result: props.updateBanner }) : null] })] }));
|
|
270
|
-
}
|
|
271
|
-
function Header({ state }) {
|
|
272
|
-
// the header `.io` brand accent + connection
|
|
273
|
-
// pill route through `useTheme()` so the operator's `/theme` flip
|
|
274
|
-
// (default / dark / light / colorblind) re-tints the chrome on
|
|
275
|
-
// re-mount. The `useTheme` hook returns the `default` preset's
|
|
276
|
-
// colors when no provider is mounted, preserving the previous
|
|
277
|
-
// `#3da9fc` constants for tests that import `<Repl />` standalone.
|
|
278
|
-
const theme = useTheme();
|
|
279
|
-
return (_jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Pugi" }), _jsx(Text, { bold: true, color: theme.accent, children: ".io" }), _jsx(Text, { dimColor: true, children: ` · workspace: ${state.workspaceLabel} · v${state.cliVersion} · ` }), _jsx(Text, { color: theme.accent, children: state.connection === 'on_watch' ? 'on watch' : state.connection.replace('_', ' ') })] }));
|
|
280
|
-
}
|
|
281
|
-
function MainArea({ state, personaNames, nowEpochMs, hideToolStream, toolStreamCollapsed, }) {
|
|
282
|
-
// : three vertical panes stacked above the input box.
|
|
283
|
-
//
|
|
284
|
-
// 1. Conversation pane (top) - transcript with Markdown render.
|
|
285
|
-
// 2. Tool stream pane (mid) - live Read/Edit/Bash/Grep lines.
|
|
286
|
-
// Hidden when `--no-tool-stream` is
|
|
287
|
-
// set; collapsed via Ctrl+T while
|
|
288
|
-
// the pane is visible.
|
|
289
|
-
// 3. Agent tree pane (bottom) - Cyber-Zoo roster with persona /
|
|
290
|
-
// status / duration / token counts.
|
|
291
|
-
//
|
|
292
|
-
// The window over the transcript is small (last 12 rows) so the
|
|
293
|
-
// bottom of the frame stays anchored to the input box. New agents
|
|
294
|
-
// push the operator line up the screen, mirroring the upstream tool /
|
|
295
|
-
// peer CLI / Gemini CLI rendering.
|
|
296
|
-
const conversationSlice = state.transcript.slice(-CONVERSATION_WINDOW);
|
|
297
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(ConversationPane, { rows: conversationSlice, personaNames: personaNames }), hideToolStream ? null : (_jsx(Box, { marginTop: 1, children: _jsx(ToolStreamPane, { calls: state.toolCalls, collapsed: toolStreamCollapsed }) })), _jsx(Box, { marginTop: 1, children: _jsx(AgentTreePane, { agents: state.agents, nowEpochMs: nowEpochMs }) })] }));
|
|
298
|
-
}
|
|
299
|
-
function HelpOverlay() {
|
|
300
|
-
// Group commands by their `group` field so the operator scans the
|
|
301
|
-
// palette by intent (dispatch → session → tools → settings → meta).
|
|
302
|
-
// The wave-2 expansion grew the surface from 6 to 20 commands;
|
|
303
|
-
// a flat list would force the operator to read 20 rows top-to-bottom
|
|
304
|
-
// every time. Grouping cuts perceived complexity dramatically.
|
|
305
|
-
const grouped = new Map();
|
|
306
|
-
for (const row of SLASH_COMMAND_HELP) {
|
|
307
|
-
const list = grouped.get(row.group);
|
|
308
|
-
if (list) {
|
|
309
|
-
grouped.set(row.group, [...list, row]);
|
|
310
|
-
}
|
|
311
|
-
else {
|
|
312
|
-
grouped.set(row.group, [row]);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Pugi REPL help" }), SLASH_COMMAND_GROUPS.map((group) => {
|
|
316
|
-
const rows = grouped.get(group);
|
|
317
|
-
if (!rows || rows.length === 0)
|
|
318
|
-
return null;
|
|
319
|
-
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { dimColor: true, children: ` -- ${group} --` }), rows.map((row) => (_jsxs(Box, { children: [_jsx(Text, { bold: true, color: "#3da9fc", children: ` /${row.name} ${row.args}`.padEnd(22, ' ') }), _jsx(Text, { dimColor: true, children: row.gloss })] }, row.name)))] }, group));
|
|
320
|
-
}), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: `${PUGI_TAGLINE}` }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: 'Press any key to dismiss.' }) })] }));
|
|
321
|
-
}
|
|
322
|
-
function RosterOverlay() {
|
|
323
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "On-watch roster" }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: THE_TEN.map((persona) => (_jsxs(Box, { children: [_jsx(Text, { bold: true, children: ` ${persona.name.padEnd(10, ' ')}` }), _jsx(Text, { dimColor: true, children: `${persona.role.padEnd(20, ' ')}` }), _jsx(Text, { children: persona.oneLiner })] }, persona.slug))) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: 'Press any key to dismiss.' }) })] }));
|
|
324
|
-
}
|
|
325
|
-
function FarewellOverlay() {
|
|
326
|
-
return (_jsx(Box, { flexDirection: "column", alignItems: "center", paddingY: 2, children: _jsx(Text, { bold: true, color: "#3da9fc", children: PUGI_TAGLINE }) }));
|
|
327
|
-
}
|
|
328
|
-
function applyVerdictSideEffects(verdict, handlers) {
|
|
329
|
-
switch (verdict.kind) {
|
|
330
|
-
case 'help':
|
|
331
|
-
handlers.showHelp();
|
|
332
|
-
return;
|
|
333
|
-
case 'roster':
|
|
334
|
-
handlers.showRoster();
|
|
335
|
-
return;
|
|
336
|
-
case 'quit':
|
|
337
|
-
handlers.farewell();
|
|
338
|
-
return;
|
|
339
|
-
case 'dispatch':
|
|
340
|
-
case 'stop':
|
|
341
|
-
case 'web':
|
|
342
|
-
case 'error':
|
|
343
|
-
case 'noop':
|
|
344
|
-
case 'clear':
|
|
345
|
-
case 'version':
|
|
346
|
-
case 'jobs':
|
|
347
|
-
case 'ask':
|
|
348
|
-
case 'consensus':
|
|
349
|
-
case 'diff':
|
|
350
|
-
case 'cost':
|
|
351
|
-
case 'quota':
|
|
352
|
-
case 'status':
|
|
353
|
-
case 'resume':
|
|
354
|
-
case 'mcp':
|
|
355
|
-
case 'stub':
|
|
356
|
-
// All non-overlay verdicts: the session module already appended
|
|
357
|
-
// any operator-visible system lines (and, for `ask`, set
|
|
358
|
-
// pendingAsk so the modal renders on the next frame). No further
|
|
359
|
-
// UI side effect needed here.
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
function countActive(state) {
|
|
364
|
-
let count = 0;
|
|
365
|
-
for (const agent of state.agents) {
|
|
366
|
-
if (agent.status === 'queued' || agent.status === 'thinking')
|
|
367
|
-
count += 1;
|
|
368
|
-
}
|
|
369
|
-
return count;
|
|
370
|
-
}
|
|
371
|
-
function buildPersonaNameMap() {
|
|
372
|
-
const map = new Map();
|
|
373
|
-
for (const persona of THE_TEN) {
|
|
374
|
-
map.set(persona.slug, persona.name);
|
|
375
|
-
}
|
|
376
|
-
return map;
|
|
377
|
-
}
|
|
378
|
-
//# sourceMappingURL=repl.js.map
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Box, Text } from 'ink';
|
|
3
|
-
import { SLASH_COMMAND_HELP } from '../core/repl/slash-commands.js';
|
|
4
|
-
export const PALETTE_ROW_LIMIT = 8;
|
|
5
|
-
/**
|
|
6
|
-
* Compute the FULL filtered candidate list for a given input buffer.
|
|
7
|
-
* Centralises the "starts-with-slash → filter SLASH_COMMAND_HELP"
|
|
8
|
-
* logic so the input box and the unit test agree on the shape.
|
|
9
|
-
*
|
|
10
|
-
* fix: returns the FULL filtered set, not just the
|
|
11
|
-
* first PALETTE_ROW_LIMIT rows. The palette renderer now windows the
|
|
12
|
-
* visible slice internally based on `focusedIndex`, so the operator
|
|
13
|
-
* can scroll past row 7 via ↑/↓ on a long list (e.g. 20 commands when
|
|
14
|
-
* the buffer is `/`). `totalBeforeLimit` is preserved on the return
|
|
15
|
-
* shape for backward compatibility but always equals `rows.length`.
|
|
16
|
-
*
|
|
17
|
-
* Behaviour:
|
|
18
|
-
* - Empty / non-slash buffer → empty result; palette stays hidden.
|
|
19
|
-
* - `/` alone → all registry rows (the operator wants to browse).
|
|
20
|
-
* - `/he` → rows whose name starts with `he` (case-insensitive).
|
|
21
|
-
*/
|
|
22
|
-
export function filterPalette(buffer) {
|
|
23
|
-
if (!buffer.startsWith('/')) {
|
|
24
|
-
return { rows: [], totalBeforeLimit: 0 };
|
|
25
|
-
}
|
|
26
|
-
// Treat anything past the first whitespace as args - palette only
|
|
27
|
-
// filters on the command name itself.
|
|
28
|
-
const headEnd = buffer.indexOf(' ');
|
|
29
|
-
const head = headEnd === -1 ? buffer.slice(1) : buffer.slice(1, headEnd);
|
|
30
|
-
const prefix = head.toLowerCase();
|
|
31
|
-
// Lowercase row.name too so a registry entry like `Help` still matches
|
|
32
|
-
// an operator typing `/he`. Today every entry is lowercase, but the
|
|
33
|
-
// type contract on SlashCommandHelp.name does not enforce that, and
|
|
34
|
-
// a future addition would silently disappear from the palette
|
|
35
|
-
// without this guard. Codex P2.
|
|
36
|
-
const all = prefix.length === 0
|
|
37
|
-
? SLASH_COMMAND_HELP
|
|
38
|
-
: SLASH_COMMAND_HELP.filter((row) => row.name.toLowerCase().startsWith(prefix));
|
|
39
|
-
// Defensive copy via spread so callers cannot mutate the registry
|
|
40
|
-
// through the returned readonly array (TS-only enforcement, but
|
|
41
|
-
// future refactors might assume the contract).
|
|
42
|
-
const rows = [...all];
|
|
43
|
-
return {
|
|
44
|
-
rows,
|
|
45
|
-
totalBeforeLimit: rows.length,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
export function computePaletteWindow(rows, focusedIndex) {
|
|
49
|
-
const total = rows.length;
|
|
50
|
-
if (total <= PALETTE_ROW_LIMIT) {
|
|
51
|
-
return { visible: rows, startIndex: 0, total };
|
|
52
|
-
}
|
|
53
|
-
// Sliding window: anchor the start so the focused row stays inside the
|
|
54
|
-
// PALETTE_ROW_LIMIT span. Clamp at both ends so we never render fewer
|
|
55
|
-
// than PALETTE_ROW_LIMIT rows when the list is long enough to fill them.
|
|
56
|
-
let start = focusedIndex - Math.floor(PALETTE_ROW_LIMIT / 2);
|
|
57
|
-
if (start < 0)
|
|
58
|
-
start = 0;
|
|
59
|
-
const maxStart = total - PALETTE_ROW_LIMIT;
|
|
60
|
-
if (start > maxStart)
|
|
61
|
-
start = maxStart;
|
|
62
|
-
return {
|
|
63
|
-
visible: rows.slice(start, start + PALETTE_ROW_LIMIT),
|
|
64
|
-
startIndex: start,
|
|
65
|
-
total,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Compute the auto-complete result for the Tab key. Picks the focused
|
|
70
|
-
* row when there is one, falls back to the longest common prefix
|
|
71
|
-
* otherwise (bash-like behaviour). Returns the new buffer the input
|
|
72
|
-
* box should adopt, or `null` when there is nothing to complete.
|
|
73
|
-
*/
|
|
74
|
-
export function completePalette(buffer, rows, focusedIndex) {
|
|
75
|
-
if (rows.length === 0)
|
|
76
|
-
return null;
|
|
77
|
-
const target = rows[focusedIndex] ?? rows[0];
|
|
78
|
-
if (!target)
|
|
79
|
-
return null;
|
|
80
|
-
// Preserve any args the operator has already started typing after a
|
|
81
|
-
// space; only swap the head.
|
|
82
|
-
const headEnd = buffer.indexOf(' ');
|
|
83
|
-
const tail = headEnd === -1 ? '' : buffer.slice(headEnd);
|
|
84
|
-
return `/${target.name}${tail}`;
|
|
85
|
-
}
|
|
86
|
-
export function SlashPalette(props) {
|
|
87
|
-
if (props.rows.length === 0)
|
|
88
|
-
return null;
|
|
89
|
-
// fix: compute the visible window so the operator
|
|
90
|
-
// can scroll past row 7 on long lists. Focus indexes the full rows
|
|
91
|
-
// array; the window slides to keep the focused row visible.
|
|
92
|
-
const window = computePaletteWindow(props.rows, props.focusedIndex);
|
|
93
|
-
const overflow = window.total > PALETTE_ROW_LIMIT;
|
|
94
|
-
// Indicator value: focused row is 1-based for human display
|
|
95
|
-
// ("→ 9/20" reads better than "→ 8/20" when the operator is on
|
|
96
|
-
// the ninth entry).
|
|
97
|
-
const focusedDisplayIndex = Math.min(window.total, Math.max(1, props.focusedIndex + 1));
|
|
98
|
-
return (_jsxs(Box, { flexDirection: "column", marginTop: 0, paddingLeft: 2, children: [window.visible.map((row, visibleIdx) => {
|
|
99
|
-
const absoluteIdx = window.startIndex + visibleIdx;
|
|
100
|
-
const focused = absoluteIdx === props.focusedIndex;
|
|
101
|
-
const glyph = focused ? '▸' : '·';
|
|
102
|
-
const cmd = `/${row.name}${row.args ? ` ${row.args}` : ''}`.padEnd(22, ' ');
|
|
103
|
-
return (_jsxs(Box, { children: [_jsx(Text, { color: focused ? 'cyan' : 'gray', children: `${glyph} ` }), _jsx(Text, { bold: focused, color: focused ? 'cyan' : undefined, dimColor: !focused, children: cmd }), _jsx(Text, { dimColor: true, children: row.gloss })] }, row.name));
|
|
104
|
-
}), overflow ? (_jsx(Box, { children: _jsx(Text, { dimColor: true, children: ` → ${focusedDisplayIndex}/${window.total}` }) })) : null, _jsx(Box, { children: _jsx(Text, { dimColor: true, children: ' ↑/↓ select · Tab complete · Enter run · Esc close' }) })] }));
|
|
105
|
-
}
|
|
106
|
-
//# sourceMappingURL=slash-palette.js.map
|
package/dist/tui/splash-data.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { homedir } from 'node:os';
|
|
2
|
-
import { DEFAULT_API_URL, maskApiKey, normalizeApiUrl, readCredentialsFile, resolveActiveCredential, } from '../core/credentials.js';
|
|
3
|
-
/**
|
|
4
|
-
* Decode the JWT payload for display only — no signature check. The
|
|
5
|
-
* splash never sends the token over the wire so a stale or malformed
|
|
6
|
-
* JWT is still safe to show. Mirrors `decodeJwtPrincipal` in
|
|
7
|
-
* runtime/cli.ts, intentionally duplicated rather than imported to
|
|
8
|
-
* keep the TUI layer independent of the giant CLI module.
|
|
9
|
-
*/
|
|
10
|
-
function decodeJwtPayload(token) {
|
|
11
|
-
try {
|
|
12
|
-
const parts = token.split('.');
|
|
13
|
-
if (parts.length < 2)
|
|
14
|
-
return null;
|
|
15
|
-
const payload = parts[1];
|
|
16
|
-
if (!payload)
|
|
17
|
-
return null;
|
|
18
|
-
const padded = payload
|
|
19
|
-
.replace(/-/g, '+')
|
|
20
|
-
.replace(/_/g, '/')
|
|
21
|
-
.padEnd(payload.length + ((4 - (payload.length % 4)) % 4), '=');
|
|
22
|
-
const json = Buffer.from(padded, 'base64').toString('utf8');
|
|
23
|
-
const obj = JSON.parse(json);
|
|
24
|
-
if (!obj || typeof obj !== 'object')
|
|
25
|
-
return null;
|
|
26
|
-
return {
|
|
27
|
-
sub: typeof obj.sub === 'string' ? obj.sub : undefined,
|
|
28
|
-
email: typeof obj.email === 'string' ? obj.email : undefined,
|
|
29
|
-
customerId: typeof obj.customerId === 'string' ? obj.customerId : undefined,
|
|
30
|
-
plan: typeof obj.plan === 'string' ? obj.plan : undefined,
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
export function collectSplashData(input) {
|
|
38
|
-
const env = input.env ?? process.env;
|
|
39
|
-
const home = input.home ?? homedir();
|
|
40
|
-
const credential = resolveActiveCredential(env, home);
|
|
41
|
-
if (!credential) {
|
|
42
|
-
const file = readCredentialsFile(home);
|
|
43
|
-
const apiUrl = normalizeApiUrl(env.PUGI_API_URL ?? file.activeApiUrl ?? DEFAULT_API_URL);
|
|
44
|
-
return {
|
|
45
|
-
cliVersion: input.cliVersion,
|
|
46
|
-
apiUrl,
|
|
47
|
-
isAuthenticated: false,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
const principal = decodeJwtPayload(credential.apiKey);
|
|
51
|
-
return {
|
|
52
|
-
cliVersion: input.cliVersion,
|
|
53
|
-
apiUrl: credential.apiUrl,
|
|
54
|
-
isAuthenticated: true,
|
|
55
|
-
apiKeyMasked: maskApiKey(credential.apiKey),
|
|
56
|
-
...(principal?.email ? { email: principal.email } : {}),
|
|
57
|
-
...(principal?.customerId ? { tenant: principal.customerId } : {}),
|
|
58
|
-
...(principal?.plan ? { plan: principal.plan } : {}),
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
//# sourceMappingURL=splash-data.js.map
|
package/dist/tui/splash.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Box, Text } from 'ink';
|
|
3
|
-
/**
|
|
4
|
-
* Bare `pugi` (no args) splash. Rendered only on a real TTY by the
|
|
5
|
-
* CLI dispatcher; non-TTY callers see the existing usage dump.
|
|
6
|
-
*
|
|
7
|
-
* Layout intentionally restrained: bold "pugi.io" wordmark, dim
|
|
8
|
-
* version/endpoint metadata, neutral body. No background colors, no
|
|
9
|
-
* emoji decoration, ASCII separators only.
|
|
10
|
-
*/
|
|
11
|
-
export function Splash({ data }) {
|
|
12
|
-
const accountLine = data.isAuthenticated
|
|
13
|
-
? `${data.email ?? data.apiKeyMasked ?? 'authenticated'}${data.tenant ? ` (tenant: ${data.tenant})` : ''}`
|
|
14
|
-
: 'not signed in';
|
|
15
|
-
const primaryHint = data.isAuthenticated
|
|
16
|
-
? {
|
|
17
|
-
cmd: 'pugi code "fix the bug"',
|
|
18
|
-
gloss: 'Run a one-shot coding task',
|
|
19
|
-
}
|
|
20
|
-
: {
|
|
21
|
-
cmd: 'pugi login',
|
|
22
|
-
gloss: 'Connect this terminal to your Pugi account',
|
|
23
|
-
};
|
|
24
|
-
return (_jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [_jsx(Box, { children: _jsx(Text, { bold: true, color: "#3da9fc", children: "pugi.io" }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: `v${data.cliVersion} · ${data.apiUrl}` }) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: "Account: " }), _jsx(Text, { children: accountLine })] }), data.isAuthenticated && data.plan ? (_jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: "Plan: " }), _jsx(Text, { children: data.plan })] })) : null] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "Quick start:" }), _jsx(HintRow, { command: primaryHint.cmd, gloss: primaryHint.gloss }), data.isAuthenticated ? (_jsx(HintRow, { command: 'pugi login', gloss: 'Re-authenticate or switch accounts' })) : (_jsx(HintRow, { command: 'pugi code "fix the bug"', gloss: 'Run a one-shot coding task' })), _jsx(HintRow, { command: 'pugi review --triple', gloss: 'Run the Anvil triple-review gate' }), _jsx(HintRow, { command: 'pugi help', gloss: 'Full command reference' })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Docs: https://pugi.dev \u00B7 Status: https://pugi.io/status" }) })] }));
|
|
25
|
-
}
|
|
26
|
-
function HintRow({ command, gloss }) {
|
|
27
|
-
// Pad command names so the gloss column lines up across rows.
|
|
28
|
-
const padded = command.padEnd(28, ' ');
|
|
29
|
-
return (_jsxs(Text, { children: [_jsx(Text, { children: ` ${padded}` }), _jsx(Text, { dimColor: true, children: gloss })] }));
|
|
30
|
-
}
|
|
31
|
-
//# sourceMappingURL=splash.js.map
|