@pugi/cli 0.1.0-beta.99 → 1.0.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +11 -191
- package/bin/pugi +8 -0
- package/package.json +15 -71
- package/postinstall.mjs +31 -0
- package/CHANGELOG.md +0 -132
- package/THIRD_PARTY_NOTICES.md +0 -40
- package/assets/pugi-mascot.ansi +0 -16
- package/assets/pugi-prozr2-mascot.ansi +0 -9
- package/bin/run.js +0 -34
- package/dist/commands/deploy.js +0 -439
- package/dist/commands/flatten.js +0 -191
- package/dist/commands/jobs-watch.js +0 -201
- package/dist/commands/jobs.js +0 -260
- package/dist/commands/retro.js +0 -210
- package/dist/commands/smoke.js +0 -133
- package/dist/core/agent-progress/cleanup.js +0 -134
- package/dist/core/agent-progress/schema.js +0 -144
- package/dist/core/agent-progress/writer.js +0 -101
- package/dist/core/agents/adaptive-router.js +0 -330
- package/dist/core/agents/loader.js +0 -104
- package/dist/core/agents/query-decomposer.js +0 -297
- package/dist/core/agents/registry.js +0 -69
- package/dist/core/approvals/shortcut-resolver.js +0 -98
- package/dist/core/artifact-chain/dispatcher.js +0 -148
- package/dist/core/artifact-chain/exporter.js +0 -164
- package/dist/core/artifact-chain/state.js +0 -243
- package/dist/core/artifact-chain/steps.js +0 -169
- package/dist/core/ask-user/question.js +0 -92
- package/dist/core/audit/audit-trail.js +0 -275
- package/dist/core/auth/ensure-authenticated.js +0 -129
- package/dist/core/auth/env-provider.js +0 -238
- package/dist/core/auto-open-browser.js +0 -128
- package/dist/core/auto-update/channels.js +0 -122
- package/dist/core/auto-update/checker.js +0 -241
- package/dist/core/auto-update/state.js +0 -235
- package/dist/core/bare-mode/index.js +0 -107
- package/dist/core/bash/redirect.js +0 -281
- package/dist/core/bash-classifier.js +0 -1397
- package/dist/core/checkpoint/resumer.js +0 -149
- package/dist/core/checkpoint/rewinder.js +0 -291
- package/dist/core/checkpoints/shadow-git.js +0 -670
- package/dist/core/citations/parser.js +0 -109
- package/dist/core/classifier/yolo-classifier.js +0 -88
- package/dist/core/clipboard.js +0 -70
- package/dist/core/codegraph/decision-store.js +0 -248
- package/dist/core/codegraph/detect-repo.js +0 -459
- package/dist/core/codegraph/install.js +0 -134
- package/dist/core/codegraph/offer-hook.js +0 -220
- package/dist/core/compact/auto-trigger.js +0 -96
- package/dist/core/compact/buffer-rewriter.js +0 -115
- package/dist/core/compact/summarizer.js +0 -208
- package/dist/core/compact/token-counter.js +0 -108
- package/dist/core/consensus/anvil-fanout.js +0 -276
- package/dist/core/consensus/diff-capture.js +0 -491
- package/dist/core/consensus/rubric.js +0 -233
- package/dist/core/context/builder.js +0 -114
- package/dist/core/context/compaction-events.js +0 -99
- package/dist/core/context/compaction.js +0 -602
- package/dist/core/context/index.js +0 -28
- package/dist/core/context/invariants.js +0 -250
- package/dist/core/context/markdown-loader.js +0 -288
- package/dist/core/context/markdown-traverse.js +0 -255
- package/dist/core/context/pugiignore.js +0 -316
- package/dist/core/context/repo-skeleton.js +0 -533
- package/dist/core/context/tool-eviction.js +0 -55
- package/dist/core/context/watcher.js +0 -342
- package/dist/core/context/working-set.js +0 -165
- package/dist/core/coordinator/agent-tools.js +0 -77
- package/dist/core/coordinator/agent-toolset.js +0 -65
- package/dist/core/coordinator/fsm.js +0 -73
- package/dist/core/coordinator/mode-fsm.js +0 -70
- package/dist/core/cost/rate-card.js +0 -129
- package/dist/core/cost/tracker.js +0 -221
- package/dist/core/credentials.js +0 -355
- package/dist/core/cron/scheduler.js +0 -138
- package/dist/core/denial-tracking/index.js +0 -8
- package/dist/core/denial-tracking/state.js +0 -264
- package/dist/core/diagnostics/probe-runner.js +0 -93
- package/dist/core/diagnostics/probes/api.js +0 -46
- package/dist/core/diagnostics/probes/auth.js +0 -93
- package/dist/core/diagnostics/probes/bare-mode.js +0 -42
- package/dist/core/diagnostics/probes/cli-version.js +0 -127
- package/dist/core/diagnostics/probes/config.js +0 -72
- package/dist/core/diagnostics/probes/denial-tracking.js +0 -57
- package/dist/core/diagnostics/probes/disk.js +0 -81
- package/dist/core/diagnostics/probes/engine-live.js +0 -46
- package/dist/core/diagnostics/probes/git.js +0 -65
- package/dist/core/diagnostics/probes/hooks.js +0 -118
- package/dist/core/diagnostics/probes/mcp.js +0 -75
- package/dist/core/diagnostics/probes/node.js +0 -59
- package/dist/core/diagnostics/probes/pnpm.js +0 -36
- package/dist/core/diagnostics/probes/pugi-md.js +0 -89
- package/dist/core/diagnostics/probes/sandbox.js +0 -72
- package/dist/core/diagnostics/probes/session.js +0 -74
- package/dist/core/diagnostics/probes/status-snapshot.js +0 -488
- package/dist/core/diagnostics/probes/workspace.js +0 -63
- package/dist/core/diagnostics/types.js +0 -70
- package/dist/core/dispatch/cache-cleanup.js +0 -197
- package/dist/core/dispatch/cache-handoff.js +0 -295
- package/dist/core/edits/apply-patch-layer-e.js +0 -189
- package/dist/core/edits/dispatch.js +0 -511
- package/dist/core/edits/format-detector.js +0 -260
- package/dist/core/edits/format-matrix.js +0 -26
- package/dist/core/edits/fuzzy-ladder.js +0 -650
- package/dist/core/edits/index.js +0 -19
- package/dist/core/edits/journal.js +0 -199
- package/dist/core/edits/layer-a-apply.js +0 -217
- package/dist/core/edits/layer-a-fuzzy-apply.js +0 -198
- package/dist/core/edits/layer-b-apply.js +0 -211
- package/dist/core/edits/layer-c-apply.js +0 -160
- package/dist/core/edits/layer-d-ast.js +0 -572
- package/dist/core/edits/marker-parser.js +0 -401
- package/dist/core/edits/security-gate.js +0 -223
- package/dist/core/edits/verify-hook.js +0 -273
- package/dist/core/edits/worktree.js +0 -322
- package/dist/core/engine/adapter-runner.js +0 -8
- package/dist/core/engine/anvil-client.js +0 -344
- package/dist/core/engine/auto-compact.js +0 -179
- package/dist/core/engine/budgets.js +0 -195
- package/dist/core/engine/context-prefix.js +0 -155
- package/dist/core/engine/index.js +0 -12
- package/dist/core/engine/intensity.js +0 -163
- package/dist/core/engine/intent.js +0 -260
- package/dist/core/engine/native-pugi.js +0 -1616
- package/dist/core/engine/noop.js +0 -27
- package/dist/core/engine/prompts.js +0 -236
- package/dist/core/engine/strip-internal-fields.js +0 -124
- package/dist/core/engine/tool-bridge.js +0 -2173
- package/dist/core/engine/verification-patterns.js +0 -195
- package/dist/core/evaluation/golden-dataset.js +0 -293
- package/dist/core/feedback/queue.js +0 -177
- package/dist/core/feedback/submitter.js +0 -145
- package/dist/core/file-cache.js +0 -141
- package/dist/core/flatten/flatten-repo.js +0 -439
- package/dist/core/format/osc8-link.js +0 -28
- package/dist/core/hook-chains.js +0 -392
- package/dist/core/hooks/citation-verify-hook.js +0 -138
- package/dist/core/hooks/citation-verify.js +0 -112
- package/dist/core/hooks/events.js +0 -46
- package/dist/core/hooks/index.js +0 -15
- package/dist/core/hooks/registry.js +0 -216
- package/dist/core/hooks/runner.js +0 -236
- package/dist/core/hooks/v2/event-emitter.js +0 -115
- package/dist/core/hooks/v2/executor.js +0 -282
- package/dist/core/hooks/v2/index.js +0 -25
- package/dist/core/hooks/v2/lifecycle.js +0 -104
- package/dist/core/hooks/v2/loader.js +0 -216
- package/dist/core/hooks/v2/matcher.js +0 -125
- package/dist/core/hooks/v2/trust.js +0 -143
- package/dist/core/hooks/v2/types.js +0 -86
- package/dist/core/hooks/worktree-events.js +0 -158
- package/dist/core/hooks.js +0 -415
- package/dist/core/image/renderer.js +0 -71
- package/dist/core/index-store.js +0 -260
- package/dist/core/init/detector.js +0 -582
- package/dist/core/init/template-renderer.js +0 -242
- package/dist/core/jobs/registry.js +0 -462
- package/dist/core/ledger/results-tsv.js +0 -142
- package/dist/core/log-discipline/stdout-redirect.js +0 -51
- package/dist/core/lsp/cache.js +0 -105
- package/dist/core/lsp/client.js +0 -1229
- package/dist/core/lsp/language-detect.js +0 -66
- package/dist/core/lsp/post-edit-diagnostics.js +0 -171
- package/dist/core/lsp/server-detect.js +0 -173
- package/dist/core/lsp/symbol-cache.js +0 -162
- package/dist/core/lsp/symbol-tools.js +0 -664
- package/dist/core/mcp/client.js +0 -385
- package/dist/core/mcp/http-server.js +0 -553
- package/dist/core/mcp/orchestrator-config.js +0 -192
- package/dist/core/mcp/orchestrator-tools.js +0 -806
- package/dist/core/mcp/permission.js +0 -190
- package/dist/core/mcp/registry.js +0 -193
- package/dist/core/mcp/server-tools.js +0 -219
- package/dist/core/mcp/server.js +0 -397
- package/dist/core/mcp/trust.js +0 -91
- package/dist/core/memory/dual-write.js +0 -416
- package/dist/core/memory/passive-extract.js +0 -130
- package/dist/core/memory/phase1-kinds.js +0 -20
- package/dist/core/memory/secret-scanner.js +0 -304
- package/dist/core/memory-sync/queue.js +0 -170
- package/dist/core/metrics/extract.js +0 -113
- package/dist/core/modes/roo-modes.js +0 -68
- package/dist/core/onboarding/ensure-initialized.js +0 -133
- package/dist/core/onboarding/marker.js +0 -111
- package/dist/core/onboarding/telemetry-state.js +0 -108
- package/dist/core/output-style/presets.js +0 -176
- package/dist/core/output-style/state.js +0 -185
- package/dist/core/path-security.js +0 -345
- package/dist/core/permission.js +0 -369
- package/dist/core/permissions/auto-classifier.js +0 -124
- package/dist/core/permissions/bash-parser.js +0 -371
- package/dist/core/permissions/circuit-breaker.js +0 -83
- package/dist/core/permissions/constrained-edit.js +0 -91
- package/dist/core/permissions/gate.js +0 -278
- package/dist/core/permissions/index.js +0 -20
- package/dist/core/permissions/mode.js +0 -174
- package/dist/core/permissions/network-egress.js +0 -137
- package/dist/core/permissions/state.js +0 -241
- package/dist/core/permissions/tool-class.js +0 -107
- package/dist/core/plan-mode/ui-state.js +0 -51
- package/dist/core/plans/plan-artifact.js +0 -721
- package/dist/core/policy-limits/etag-store.js +0 -122
- package/dist/core/prd-check/parser.js +0 -215
- package/dist/core/prd-check/reporter.js +0 -127
- package/dist/core/prd-check/session-review.js +0 -557
- package/dist/core/prd-check/verifiers.js +0 -223
- package/dist/core/prompt-cache/client-cache.js +0 -99
- package/dist/core/prompts/assembly.js +0 -29
- package/dist/core/prompts/registry.js +0 -364
- package/dist/core/pugi-gitignore.js +0 -52
- package/dist/core/pugi-md/cc-compat-rules.js +0 -735
- package/dist/core/pugi-md/context-injector.js +0 -76
- package/dist/core/pugi-md/walk-up.js +0 -207
- package/dist/core/python/uv-installer.js +0 -270
- package/dist/core/python/uv-resolver.js +0 -83
- package/dist/core/rate-limit/narrator.js +0 -146
- package/dist/core/recipes/cli-types.js +0 -20
- package/dist/core/recipes/loader.js +0 -103
- package/dist/core/recipes/runner.js +0 -345
- package/dist/core/recipes/schema.js +0 -587
- package/dist/core/release-notes/parser.js +0 -241
- package/dist/core/release-notes/state.js +0 -116
- package/dist/core/repl/ask.js +0 -512
- package/dist/core/repl/cancellation.js +0 -98
- package/dist/core/repl/cap-warning.js +0 -91
- package/dist/core/repl/clipboard-read.js +0 -174
- package/dist/core/repl/dispatch-fsm.js +0 -220
- package/dist/core/repl/engine-bridge.js +0 -303
- package/dist/core/repl/history-search.js +0 -175
- package/dist/core/repl/history.js +0 -182
- package/dist/core/repl/kill-ring.js +0 -138
- package/dist/core/repl/model-pricing.js +0 -135
- package/dist/core/repl/privacy-banner.js +0 -71
- package/dist/core/repl/session.js +0 -4962
- package/dist/core/repl/slash-commands.js +0 -747
- package/dist/core/repl/store/index.js +0 -12
- package/dist/core/repl/store/jsonl-log.js +0 -321
- package/dist/core/repl/store/lockfile.js +0 -155
- package/dist/core/repl/store/session-store.js +0 -821
- package/dist/core/repl/store/types.js +0 -44
- package/dist/core/repl/store/uuid-v7.js +0 -68
- package/dist/core/repl/tool-route.js +0 -382
- package/dist/core/repl/workspace-context.js +0 -206
- package/dist/core/repo-map/build.js +0 -125
- package/dist/core/repo-map/cache.js +0 -185
- package/dist/core/repo-map/extractor.js +0 -254
- package/dist/core/repo-map/formatter.js +0 -145
- package/dist/core/repo-map/page-rank.js +0 -105
- package/dist/core/repo-map/scanner.js +0 -211
- package/dist/core/retro/git-collector.js +0 -251
- package/dist/core/retro/health-card.js +0 -25
- package/dist/core/retro/metrics.js +0 -342
- package/dist/core/retro/narrative.js +0 -249
- package/dist/core/retro/plane-collector.js +0 -274
- package/dist/core/retro/pr-issue-link.js +0 -65
- package/dist/core/retro/types.js +0 -16
- package/dist/core/retry-budget/budget.js +0 -284
- package/dist/core/retry-budget/index.js +0 -5
- package/dist/core/retry-budget/retry-cap.js +0 -74
- package/dist/core/routing/lead-worker.js +0 -43
- package/dist/core/routing/pre-flight-estimator.js +0 -108
- package/dist/core/runs/run-tree.js +0 -103
- package/dist/core/sandboxing/adapter.js +0 -29
- package/dist/core/sandboxing/index.js +0 -49
- package/dist/core/sandboxing/none.js +0 -19
- package/dist/core/sandboxing/seatbelt.js +0 -183
- package/dist/core/security/injection-scanner.js +0 -367
- package/dist/core/security/output-filter.js +0 -418
- package/dist/core/session/env-file.js +0 -105
- package/dist/core/session/section-budgets.js +0 -140
- package/dist/core/session.js +0 -377
- package/dist/core/settings.js +0 -400
- package/dist/core/share/formatter.js +0 -271
- package/dist/core/share/redactor.js +0 -221
- package/dist/core/share/uploader.js +0 -267
- package/dist/core/skills/defaults.js +0 -457
- package/dist/core/skills/loader.js +0 -454
- package/dist/core/skills/sources.js +0 -480
- package/dist/core/skills/trust.js +0 -172
- package/dist/core/smoke/headless-driver.js +0 -174
- package/dist/core/smoke/orchestrator.js +0 -194
- package/dist/core/smoke/runner.js +0 -238
- package/dist/core/smoke/scenario-parser.js +0 -316
- package/dist/core/statusline.js +0 -99
- package/dist/core/subagents/dispatcher-real.js +0 -600
- package/dist/core/subagents/dispatcher.js +0 -352
- package/dist/core/subagents/index.js +0 -39
- package/dist/core/subagents/isolation-matrix.js +0 -213
- package/dist/core/subagents/spawn.js +0 -101
- package/dist/core/telemetry/emitter.js +0 -229
- package/dist/core/telemetry/queue.js +0 -251
- package/dist/core/theme/context.js +0 -91
- package/dist/core/theme/presets.js +0 -228
- package/dist/core/theme/state.js +0 -181
- package/dist/core/todos/invariant.js +0 -10
- package/dist/core/todos/state.js +0 -177
- package/dist/core/tool-schema/compressor.js +0 -89
- package/dist/core/transport/version-interceptor.js +0 -166
- package/dist/core/trust.js +0 -109
- package/dist/core/tui/thinking-block.js +0 -64
- package/dist/core/vim/keymap.js +0 -288
- package/dist/core/vim/state.js +0 -92
- package/dist/core/watch-markers/marker-watcher.js +0 -133
- package/dist/core/worktree/include-parser.js +0 -249
- package/dist/core/worktree-manager/cleanup.js +0 -123
- package/dist/core/worktree-manager/manager.js +0 -303
- package/dist/index.js +0 -44
- package/dist/runtime/bootstrap.js +0 -190
- package/dist/runtime/cli.js +0 -8121
- package/dist/runtime/commands/agents.js +0 -385
- package/dist/runtime/commands/budget.js +0 -192
- package/dist/runtime/commands/cancel.js +0 -231
- package/dist/runtime/commands/chain.js +0 -489
- package/dist/runtime/commands/codegraph-status.js +0 -227
- package/dist/runtime/commands/compact.js +0 -297
- package/dist/runtime/commands/config.js +0 -595
- package/dist/runtime/commands/cost.js +0 -199
- package/dist/runtime/commands/delegate.js +0 -312
- package/dist/runtime/commands/dispatch.js +0 -126
- package/dist/runtime/commands/doctor.js +0 -579
- package/dist/runtime/commands/feedback.js +0 -184
- package/dist/runtime/commands/hooks.js +0 -187
- package/dist/runtime/commands/init.js +0 -254
- package/dist/runtime/commands/lsp.js +0 -368
- package/dist/runtime/commands/mcp.js +0 -935
- package/dist/runtime/commands/memory.js +0 -582
- package/dist/runtime/commands/model.js +0 -237
- package/dist/runtime/commands/onboarding.js +0 -275
- package/dist/runtime/commands/patch.js +0 -128
- package/dist/runtime/commands/permissions.js +0 -112
- package/dist/runtime/commands/plan.js +0 -143
- package/dist/runtime/commands/prd-check.js +0 -285
- package/dist/runtime/commands/privacy.js +0 -107
- package/dist/runtime/commands/recipe.js +0 -325
- package/dist/runtime/commands/redo-blob-store.js +0 -92
- package/dist/runtime/commands/redo.js +0 -361
- package/dist/runtime/commands/release-notes.js +0 -229
- package/dist/runtime/commands/repo-map.js +0 -95
- package/dist/runtime/commands/report.js +0 -299
- package/dist/runtime/commands/resume.js +0 -118
- package/dist/runtime/commands/review-consensus.js +0 -414
- package/dist/runtime/commands/rewind.js +0 -333
- package/dist/runtime/commands/roster.js +0 -117
- package/dist/runtime/commands/sessions.js +0 -163
- package/dist/runtime/commands/share.js +0 -316
- package/dist/runtime/commands/skills.js +0 -401
- package/dist/runtime/commands/status.js +0 -186
- package/dist/runtime/commands/stickers.js +0 -82
- package/dist/runtime/commands/style.js +0 -194
- package/dist/runtime/commands/theme.js +0 -196
- package/dist/runtime/commands/undo.js +0 -361
- package/dist/runtime/commands/update.js +0 -289
- package/dist/runtime/commands/vim.js +0 -140
- package/dist/runtime/commands/worktree.js +0 -177
- package/dist/runtime/commands/worktrees.js +0 -155
- package/dist/runtime/deprecation-warning.js +0 -69
- package/dist/runtime/engine-exit-code.js +0 -50
- package/dist/runtime/headless-repl.js +0 -195
- package/dist/runtime/headless.js +0 -548
- package/dist/runtime/load-hooks-or-exit.js +0 -71
- package/dist/runtime/plan-decompose.js +0 -531
- package/dist/runtime/sigint-guard.js +0 -272
- package/dist/runtime/stream-renderer.js +0 -195
- package/dist/runtime/update-check.js +0 -294
- package/dist/runtime/version.js +0 -65
- package/dist/runtime/worktree-bootstrap.js +0 -579
- package/dist/skills/bundled/batch.js +0 -617
- package/dist/skills/bundled/index.js +0 -45
- package/dist/skills/bundled/loop.js +0 -358
- package/dist/skills/bundled/remember.js +0 -383
- package/dist/skills/bundled/simplify.js +0 -289
- package/dist/skills/bundled/skillify.js +0 -373
- package/dist/skills/bundled/stuck.js +0 -558
- package/dist/skills/bundled/verify.js +0 -439
- package/dist/testing/vcr.js +0 -486
- package/dist/tools/agent-tool.js +0 -229
- package/dist/tools/apply-patch.js +0 -556
- package/dist/tools/ask-user-question.js +0 -337
- package/dist/tools/ask-user.js +0 -115
- package/dist/tools/bash.js +0 -1238
- package/dist/tools/brief.js +0 -224
- package/dist/tools/cron.js +0 -433
- package/dist/tools/enter-worktree.js +0 -250
- package/dist/tools/exit-worktree.js +0 -147
- package/dist/tools/file-tools.js +0 -553
- package/dist/tools/http-request.js +0 -336
- package/dist/tools/lsp-tools.js +0 -565
- package/dist/tools/mcp-tool.js +0 -260
- package/dist/tools/multi-edit.js +0 -361
- package/dist/tools/powershell.js +0 -268
- package/dist/tools/registry.js +0 -166
- package/dist/tools/server-tools.js +0 -892
- package/dist/tools/skill-tool.js +0 -96
- package/dist/tools/sleep.js +0 -99
- package/dist/tools/synthetic-output.js +0 -133
- package/dist/tools/tasks.js +0 -208
- package/dist/tools/todo-write.js +0 -184
- package/dist/tools/verify-plan-execution.js +0 -295
- package/dist/tools/web-fetch-injection-scanner.js +0 -207
- package/dist/tools/web-fetch.js +0 -720
- package/dist/tools/web-search.js +0 -458
- package/dist/tui/agent-progress-card.js +0 -111
- package/dist/tui/agent-tree-pane.js +0 -9
- package/dist/tui/agent-tree.js +0 -87
- package/dist/tui/ask-cli.js +0 -52
- package/dist/tui/ask-modal.js +0 -211
- package/dist/tui/ask-user-question-chips.js +0 -315
- package/dist/tui/ask-user-question-prompt.js +0 -203
- package/dist/tui/compact-banner.js +0 -81
- package/dist/tui/conversation-pane.js +0 -164
- package/dist/tui/cost-table.js +0 -111
- package/dist/tui/device-flow.js +0 -142
- package/dist/tui/doctor-table.js +0 -46
- package/dist/tui/feedback-prompt.js +0 -156
- package/dist/tui/input-box.js +0 -732
- package/dist/tui/login-picker.js +0 -69
- package/dist/tui/markdown-render.js +0 -266
- package/dist/tui/multi-file-diff-approval.js +0 -375
- package/dist/tui/onboarding-wizard.js +0 -240
- package/dist/tui/permissions-picker.js +0 -86
- package/dist/tui/render.js +0 -160
- package/dist/tui/repl-render.js +0 -770
- package/dist/tui/repl-splash-art.js +0 -64
- package/dist/tui/repl-splash-mascot.js +0 -154
- package/dist/tui/repl-splash.js +0 -117
- package/dist/tui/repl.js +0 -378
- package/dist/tui/slash-palette.js +0 -106
- package/dist/tui/splash-data.js +0 -61
- package/dist/tui/splash.js +0 -31
- package/dist/tui/status-bar.js +0 -209
- package/dist/tui/status-table.js +0 -7
- package/dist/tui/stickers-art.js +0 -136
- package/dist/tui/style-table.js +0 -28
- package/dist/tui/theme-table.js +0 -29
- package/dist/tui/thinking-spinner.js +0 -123
- package/dist/tui/tool-stream-pane.js +0 -140
- package/dist/tui/update-banner.js +0 -33
- package/dist/tui/vim-input.js +0 -267
- package/dist/tui/welcome-banner.js +0 -107
- package/dist/tui/welcome-data.js +0 -293
- package/dist/tui/workspace-context.js +0 -105
- package/docs/examples/codegraph.mcp.json +0 -10
- package/test/scenarios/codegen-create-file.scenario.txt +0 -13
- package/test/scenarios/compact-force.scenario.txt +0 -12
- package/test/scenarios/identity.scenario.txt +0 -11
- package/test/scenarios/persona-handoff.scenario.txt +0 -12
- package/test/scenarios/walkback.scenario.txt +0 -12
|
@@ -1,401 +0,0 @@
|
|
|
1
|
-
import { createInterface } from 'node:readline/promises';
|
|
2
|
-
import { stdin as input, stdout as output } from 'node:process';
|
|
3
|
-
import { assertValidSlug, globalSkillDir, installSkill, listSkills, parseSkillMarkdown, removeSkill, workspaceSkillDir, } from '../../core/skills/loader.js';
|
|
4
|
-
import { cleanupTmp, fetchSource } from '../../core/skills/sources.js';
|
|
5
|
-
import { hashSkillDir, recordTrust, revokeTrust, verifyTrust, } from '../../core/skills/trust.js';
|
|
6
|
-
import { readdirSync, readFileSync } from 'node:fs';
|
|
7
|
-
import { join } from 'node:path';
|
|
8
|
-
const USAGE = [
|
|
9
|
-
'Usage:',
|
|
10
|
-
' pugi skills list [--global|--workspace] Show installed skills.',
|
|
11
|
-
' pugi skills install <source> [--global|--workspace] [--yes] [--as <name>]',
|
|
12
|
-
' Fetch + trust-prompt + activate a skill.',
|
|
13
|
-
' pugi skills info <name> Show metadata + body preview.',
|
|
14
|
-
' pugi skills remove <name> [--global|--workspace] Delete an installed skill.',
|
|
15
|
-
' pugi skills trust <name> [--global|--workspace] Re-trust the on-disk payload.',
|
|
16
|
-
'',
|
|
17
|
-
'Source forms accepted by `install`:',
|
|
18
|
-
' gh:owner/repo[/subdir][@ref] GitHub tree fetch (default ref: main).',
|
|
19
|
-
' https://github.com/... GitHub tree/blob URL.',
|
|
20
|
-
' anthropic:<slug> Shortcut for gh:anthropics/skills/<slug>@main.',
|
|
21
|
-
' npm:<package>[@version] npm registry tarball.',
|
|
22
|
-
' ./path | /abs/path Local filesystem.',
|
|
23
|
-
' <slug> Catalog lookup (catalog.pugi.dev).',
|
|
24
|
-
].join('\n');
|
|
25
|
-
export async function runSkillsCommand(args, ctx) {
|
|
26
|
-
const sub = args[0];
|
|
27
|
-
if (!sub || sub === '--help' || sub === '-h') {
|
|
28
|
-
ctx.writeOutput({ command: 'skills', usage: USAGE.split('\n') }, USAGE);
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
switch (sub) {
|
|
32
|
-
case 'list':
|
|
33
|
-
return runSkillsList(args.slice(1), ctx);
|
|
34
|
-
case 'install':
|
|
35
|
-
return runSkillsInstall(args.slice(1), ctx);
|
|
36
|
-
case 'info':
|
|
37
|
-
return runSkillsInfo(args.slice(1), ctx);
|
|
38
|
-
case 'remove':
|
|
39
|
-
return runSkillsRemove(args.slice(1), ctx);
|
|
40
|
-
case 'trust':
|
|
41
|
-
return runSkillsTrust(args.slice(1), ctx);
|
|
42
|
-
default:
|
|
43
|
-
throw new Error(`Unknown sub-command "pugi skills ${sub}". Expected list, install, info, remove, or trust.`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
function parseFlags(args) {
|
|
47
|
-
let scope = 'both';
|
|
48
|
-
let yes = false;
|
|
49
|
-
let asName;
|
|
50
|
-
const positional = [];
|
|
51
|
-
for (let i = 0; i < args.length; i++) {
|
|
52
|
-
const arg = args[i];
|
|
53
|
-
if (arg === '--global')
|
|
54
|
-
scope = 'global';
|
|
55
|
-
else if (arg === '--workspace')
|
|
56
|
-
scope = 'workspace';
|
|
57
|
-
else if (arg === '--yes' || arg === '-y')
|
|
58
|
-
yes = true;
|
|
59
|
-
else if (arg === '--as') {
|
|
60
|
-
asName = args[++i];
|
|
61
|
-
}
|
|
62
|
-
else if (arg && !arg.startsWith('--')) {
|
|
63
|
-
positional.push(arg);
|
|
64
|
-
}
|
|
65
|
-
else if (arg) {
|
|
66
|
-
throw new Error(`Unknown flag: ${arg}`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return { scope, yes, asName, positional };
|
|
70
|
-
}
|
|
71
|
-
async function runSkillsList(args, ctx) {
|
|
72
|
-
const flags = parseFlags(args);
|
|
73
|
-
const includeGlobal = flags.scope === 'global' || flags.scope === 'both';
|
|
74
|
-
const includeWorkspace = flags.scope === 'workspace' || flags.scope === 'both';
|
|
75
|
-
const global = includeGlobal ? listSkills('global', ctx.workspaceRoot) : [];
|
|
76
|
-
const workspace = includeWorkspace ? listSkills('workspace', ctx.workspaceRoot) : [];
|
|
77
|
-
const all = [...global, ...workspace];
|
|
78
|
-
const trustStatuses = await Promise.all(all.map(async (skill) => {
|
|
79
|
-
const actual = hashSkillDir(skill.dir);
|
|
80
|
-
const verdict = await verifyTrust('skill', skill.scope, skill.name, actual);
|
|
81
|
-
return { skill, trust: verdict };
|
|
82
|
-
}));
|
|
83
|
-
if (ctx.json) {
|
|
84
|
-
ctx.writeOutput({
|
|
85
|
-
command: 'skills.list',
|
|
86
|
-
skills: trustStatuses.map(({ skill, trust }) => ({
|
|
87
|
-
name: skill.name,
|
|
88
|
-
scope: skill.scope,
|
|
89
|
-
dir: skill.dir,
|
|
90
|
-
description: skill.frontmatter.description,
|
|
91
|
-
version: skill.frontmatter.metadata.version ?? null,
|
|
92
|
-
tools: skill.frontmatter.metadata.tools ?? [],
|
|
93
|
-
trust: trust.status,
|
|
94
|
-
})),
|
|
95
|
-
}, '');
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
if (trustStatuses.length === 0) {
|
|
99
|
-
ctx.writeOutput({ command: 'skills.list', skills: [] }, 'No skills installed. Try `pugi skills install anthropic:python-coding-standards`.');
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
const lines = ['Installed skills:'];
|
|
103
|
-
for (const { skill, trust } of trustStatuses) {
|
|
104
|
-
const version = skill.frontmatter.metadata.version ? ` v${String(skill.frontmatter.metadata.version)}` : '';
|
|
105
|
-
const trustMark = trust.status === 'trusted' ? '[trusted]' : trust.status === 'unsigned' ? '[unsigned]' : '[mismatch]';
|
|
106
|
-
lines.push(` ${skill.name.padEnd(28)} ${skill.scope.padEnd(10)} ${trustMark.padEnd(11)}${version}`);
|
|
107
|
-
lines.push(` ${truncate(skill.frontmatter.description, 80)}`);
|
|
108
|
-
}
|
|
109
|
-
ctx.writeOutput({ command: 'skills.list', skills: trustStatuses }, lines.join('\n'));
|
|
110
|
-
}
|
|
111
|
-
async function runSkillsInstall(args, ctx) {
|
|
112
|
-
const flags = parseFlags(args);
|
|
113
|
-
const source = flags.positional[0];
|
|
114
|
-
if (!source) {
|
|
115
|
-
throw new Error('pugi skills install requires a <source> argument. See `pugi skills --help`.');
|
|
116
|
-
}
|
|
117
|
-
const scope = flags.scope === 'workspace' ? 'workspace' : 'global';
|
|
118
|
-
// 1. Fetch payload to tmp dir.
|
|
119
|
-
let fetched;
|
|
120
|
-
try {
|
|
121
|
-
fetched = await fetchSource(source);
|
|
122
|
-
}
|
|
123
|
-
catch (error) {
|
|
124
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
125
|
-
ctx.writeOutput({ command: 'skills.install', status: 'fetch_failed', source, error: message }, `Skill fetch failed: ${message}`);
|
|
126
|
-
process.exitCode = 1;
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
if (fetched.inferredKind !== 'skill') {
|
|
130
|
-
cleanupTmp(fetched.tmpDir);
|
|
131
|
-
const message = `Source ${source} looks like an agent (single .md), not a skill. Use \`pugi agents install\` instead.`;
|
|
132
|
-
ctx.writeOutput({ command: 'skills.install', status: 'wrong_kind', source }, message);
|
|
133
|
-
process.exitCode = 1;
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
// 2. Parse SKILL.md to surface metadata in the trust prompt.
|
|
137
|
-
const skillMdPath = join(fetched.tmpDir, 'SKILL.md');
|
|
138
|
-
let parsed;
|
|
139
|
-
try {
|
|
140
|
-
parsed = parseSkillMarkdown(readFileSync(skillMdPath, 'utf8'));
|
|
141
|
-
}
|
|
142
|
-
catch (error) {
|
|
143
|
-
cleanupTmp(fetched.tmpDir);
|
|
144
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
145
|
-
ctx.writeOutput({ command: 'skills.install', status: 'parse_failed', source, error: message }, `Skill parse failed: ${message}`);
|
|
146
|
-
process.exitCode = 1;
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
const skillName = flags.asName ?? parsed.frontmatter.name;
|
|
150
|
-
// Fail-fast before any FS or trust-prompt work: a hostile `--as` flag
|
|
151
|
-
// or a hostile frontmatter `name` must never reach path.join.
|
|
152
|
-
try {
|
|
153
|
-
assertValidSlug(skillName, 'skill');
|
|
154
|
-
}
|
|
155
|
-
catch (error) {
|
|
156
|
-
cleanupTmp(fetched.tmpDir);
|
|
157
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
158
|
-
ctx.writeOutput({ command: 'skills.install', status: 'invalid_name', source, name: skillName, error: message }, message);
|
|
159
|
-
process.exitCode = 1;
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
const sha256 = hashSkillDir(fetched.tmpDir);
|
|
163
|
-
const targetDir = scope === 'global' ? globalSkillDir(skillName) : workspaceSkillDir(ctx.workspaceRoot, skillName);
|
|
164
|
-
const summary = {
|
|
165
|
-
name: skillName,
|
|
166
|
-
description: parsed.frontmatter.description,
|
|
167
|
-
version: parsed.frontmatter.metadata.version ?? null,
|
|
168
|
-
tools: parsed.frontmatter.metadata.tools ?? [],
|
|
169
|
-
files: countFiles(fetched.tmpDir),
|
|
170
|
-
source: fetched.sourceUrl,
|
|
171
|
-
targetDir,
|
|
172
|
-
sha256,
|
|
173
|
-
};
|
|
174
|
-
if (!flags.yes) {
|
|
175
|
-
const decision = await promptTrust('skill', summary, parsed.body);
|
|
176
|
-
if (decision === 'no') {
|
|
177
|
-
cleanupTmp(fetched.tmpDir);
|
|
178
|
-
ctx.writeOutput({ command: 'skills.install', status: 'declined', source, name: skillName }, 'Install declined. Nothing changed.');
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
// 3. Install to disk.
|
|
183
|
-
const installedDir = installSkill({
|
|
184
|
-
payloadDir: fetched.tmpDir,
|
|
185
|
-
name: skillName,
|
|
186
|
-
scope,
|
|
187
|
-
workspaceRoot: ctx.workspaceRoot,
|
|
188
|
-
});
|
|
189
|
-
// 4. Record trust.
|
|
190
|
-
await recordTrust({
|
|
191
|
-
kind: 'skill',
|
|
192
|
-
scope,
|
|
193
|
-
name: skillName,
|
|
194
|
-
sha256,
|
|
195
|
-
source: fetched.sourceUrl,
|
|
196
|
-
signedBy: signerIdentity(),
|
|
197
|
-
});
|
|
198
|
-
cleanupTmp(fetched.tmpDir);
|
|
199
|
-
ctx.writeOutput({
|
|
200
|
-
command: 'skills.install',
|
|
201
|
-
status: 'installed',
|
|
202
|
-
name: skillName,
|
|
203
|
-
scope,
|
|
204
|
-
dir: installedDir,
|
|
205
|
-
sha256,
|
|
206
|
-
source: fetched.sourceUrl,
|
|
207
|
-
}, [
|
|
208
|
-
`Installed skill "${skillName}" (${scope}).`,
|
|
209
|
-
` Path: ${installedDir}`,
|
|
210
|
-
` Source: ${fetched.sourceUrl}`,
|
|
211
|
-
` sha256: ${sha256}`,
|
|
212
|
-
].join('\n'));
|
|
213
|
-
}
|
|
214
|
-
async function runSkillsInfo(args, ctx) {
|
|
215
|
-
const flags = parseFlags(args);
|
|
216
|
-
const name = flags.positional[0];
|
|
217
|
-
if (!name) {
|
|
218
|
-
throw new Error('pugi skills info requires a <name> argument.');
|
|
219
|
-
}
|
|
220
|
-
const matches = findSkill(name, flags.scope, ctx.workspaceRoot);
|
|
221
|
-
if (matches.length === 0) {
|
|
222
|
-
ctx.writeOutput({ command: 'skills.info', status: 'not_found', name }, `No skill "${name}" installed. Try \`pugi skills list\`.`);
|
|
223
|
-
process.exitCode = 1;
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
const skill = matches[0];
|
|
227
|
-
if (!skill) {
|
|
228
|
-
ctx.writeOutput({ command: 'skills.info', status: 'not_found', name }, `No skill "${name}" installed.`);
|
|
229
|
-
process.exitCode = 1;
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
const actualSha = hashSkillDir(skill.dir);
|
|
233
|
-
const trust = await verifyTrust('skill', skill.scope, skill.name, actualSha);
|
|
234
|
-
const preview = skill.body.slice(0, 800);
|
|
235
|
-
const lines = [
|
|
236
|
-
`Skill: ${skill.name}`,
|
|
237
|
-
` Scope: ${skill.scope}`,
|
|
238
|
-
` Path: ${skill.dir}`,
|
|
239
|
-
` Description: ${skill.frontmatter.description}`,
|
|
240
|
-
` Version: ${String(skill.frontmatter.metadata.version ?? '(unset)')}`,
|
|
241
|
-
` Tools: ${(skill.frontmatter.metadata.tools ?? []).join(', ') || '(none)'}`,
|
|
242
|
-
` Trust: ${trust.status}`,
|
|
243
|
-
` sha256: ${actualSha}`,
|
|
244
|
-
'',
|
|
245
|
-
'Body preview:',
|
|
246
|
-
preview,
|
|
247
|
-
skill.body.length > 800 ? `... (${skill.body.length - 800} more chars)` : '',
|
|
248
|
-
]
|
|
249
|
-
.filter((line) => line !== '')
|
|
250
|
-
.join('\n');
|
|
251
|
-
ctx.writeOutput({
|
|
252
|
-
command: 'skills.info',
|
|
253
|
-
name: skill.name,
|
|
254
|
-
scope: skill.scope,
|
|
255
|
-
dir: skill.dir,
|
|
256
|
-
frontmatter: skill.frontmatter,
|
|
257
|
-
sha256: actualSha,
|
|
258
|
-
trust,
|
|
259
|
-
bodyPreview: preview,
|
|
260
|
-
bodyLength: skill.body.length,
|
|
261
|
-
}, lines);
|
|
262
|
-
}
|
|
263
|
-
async function runSkillsRemove(args, ctx) {
|
|
264
|
-
const flags = parseFlags(args);
|
|
265
|
-
const name = flags.positional[0];
|
|
266
|
-
if (!name) {
|
|
267
|
-
throw new Error('pugi skills remove requires a <name> argument.');
|
|
268
|
-
}
|
|
269
|
-
const matches = findSkill(name, flags.scope, ctx.workspaceRoot);
|
|
270
|
-
if (matches.length === 0) {
|
|
271
|
-
ctx.writeOutput({ command: 'skills.remove', status: 'not_found', name }, `No skill "${name}" installed.`);
|
|
272
|
-
process.exitCode = 1;
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
for (const skill of matches) {
|
|
276
|
-
removeSkill(skill.name, skill.scope, ctx.workspaceRoot);
|
|
277
|
-
await revokeTrust('skill', skill.scope, skill.name);
|
|
278
|
-
}
|
|
279
|
-
ctx.writeOutput({
|
|
280
|
-
command: 'skills.remove',
|
|
281
|
-
status: 'removed',
|
|
282
|
-
name,
|
|
283
|
-
removed: matches.map((m) => ({ name: m.name, scope: m.scope, dir: m.dir })),
|
|
284
|
-
}, `Removed ${matches.length} skill install(s) named "${name}".`);
|
|
285
|
-
}
|
|
286
|
-
async function runSkillsTrust(args, ctx) {
|
|
287
|
-
const flags = parseFlags(args);
|
|
288
|
-
const name = flags.positional[0];
|
|
289
|
-
if (!name) {
|
|
290
|
-
throw new Error('pugi skills trust requires a <name> argument.');
|
|
291
|
-
}
|
|
292
|
-
const matches = findSkill(name, flags.scope, ctx.workspaceRoot);
|
|
293
|
-
if (matches.length === 0) {
|
|
294
|
-
ctx.writeOutput({ command: 'skills.trust', status: 'not_found', name }, `No skill "${name}" installed.`);
|
|
295
|
-
process.exitCode = 1;
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
const skill = matches[0];
|
|
299
|
-
if (!skill) {
|
|
300
|
-
process.exitCode = 1;
|
|
301
|
-
return;
|
|
302
|
-
}
|
|
303
|
-
const sha256 = hashSkillDir(skill.dir);
|
|
304
|
-
await recordTrust({
|
|
305
|
-
kind: 'skill',
|
|
306
|
-
scope: skill.scope,
|
|
307
|
-
name: skill.name,
|
|
308
|
-
sha256,
|
|
309
|
-
source: skill.dir,
|
|
310
|
-
signedBy: signerIdentity(),
|
|
311
|
-
});
|
|
312
|
-
ctx.writeOutput({ command: 'skills.trust', status: 'trusted', name: skill.name, scope: skill.scope, sha256 }, `Re-trusted skill "${skill.name}" (${skill.scope}). sha256 = ${sha256}.`);
|
|
313
|
-
}
|
|
314
|
-
/* ----------------------------- shared helpers ----------------------------- */
|
|
315
|
-
function findSkill(name, scope, workspaceRoot) {
|
|
316
|
-
const scopes = scope === 'both' ? ['global', 'workspace'] : [scope];
|
|
317
|
-
const out = [];
|
|
318
|
-
for (const s of scopes) {
|
|
319
|
-
const all = listSkills(s, workspaceRoot);
|
|
320
|
-
for (const skill of all) {
|
|
321
|
-
if (skill.name === name)
|
|
322
|
-
out.push(skill);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
return out;
|
|
326
|
-
}
|
|
327
|
-
function countFiles(dir) {
|
|
328
|
-
// Conservative — recurse and count regular files only. Used for the
|
|
329
|
-
// trust prompt summary so the operator sees payload bulk.
|
|
330
|
-
let total = 0;
|
|
331
|
-
const walk = (d) => {
|
|
332
|
-
for (const entry of readdirSync(d, { withFileTypes: true })) {
|
|
333
|
-
const full = join(d, entry.name);
|
|
334
|
-
if (entry.isDirectory())
|
|
335
|
-
walk(full);
|
|
336
|
-
else if (entry.isFile())
|
|
337
|
-
total++;
|
|
338
|
-
}
|
|
339
|
-
};
|
|
340
|
-
walk(dir);
|
|
341
|
-
return total;
|
|
342
|
-
}
|
|
343
|
-
function truncate(text, max) {
|
|
344
|
-
if (text.length <= max)
|
|
345
|
-
return text;
|
|
346
|
-
return `${text.slice(0, max - 1)}…`;
|
|
347
|
-
}
|
|
348
|
-
function signerIdentity() {
|
|
349
|
-
return (process.env.PUGI_TRUSTED_BY?.trim() ||
|
|
350
|
-
process.env.USER?.trim() ||
|
|
351
|
-
process.env.USERNAME?.trim() ||
|
|
352
|
-
'cli');
|
|
353
|
-
}
|
|
354
|
-
/**
|
|
355
|
-
* Interactive trust prompt. Reads from stdin; `info` shows the full
|
|
356
|
-
* body; `y` accepts; everything else declines.
|
|
357
|
-
*
|
|
358
|
-
* Bypassable only via the operator-passed `--yes` flag in the caller
|
|
359
|
-
* (never auto-injected from another code path).
|
|
360
|
-
*/
|
|
361
|
-
async function promptTrust(kind, summary, body) {
|
|
362
|
-
const banner = [
|
|
363
|
-
'',
|
|
364
|
-
`About to install ${kind} "${summary.name}"`,
|
|
365
|
-
` Description: ${summary.description}`,
|
|
366
|
-
` Version: ${summary.version ?? '(unset)'}`,
|
|
367
|
-
` Tools: ${summary.tools.join(', ') || '(none)'}`,
|
|
368
|
-
` Files: ${summary.files}`,
|
|
369
|
-
` Source: ${summary.source}`,
|
|
370
|
-
` Target: ${summary.targetDir}`,
|
|
371
|
-
` sha256: ${summary.sha256}`,
|
|
372
|
-
'',
|
|
373
|
-
'This payload becomes part of the system prompt and may influence agent decisions.',
|
|
374
|
-
'Trust this install? [y/N/info] ',
|
|
375
|
-
].join('\n');
|
|
376
|
-
process.stdout.write(banner);
|
|
377
|
-
if (!input.isTTY) {
|
|
378
|
-
// Non-interactive caller without --yes: refuse rather than block.
|
|
379
|
-
process.stdout.write('\n(non-interactive stdin; declining install)\n');
|
|
380
|
-
return 'no';
|
|
381
|
-
}
|
|
382
|
-
const rl = createInterface({ input, output });
|
|
383
|
-
try {
|
|
384
|
-
while (true) {
|
|
385
|
-
const answer = (await rl.question('')).trim().toLowerCase();
|
|
386
|
-
if (answer === 'y' || answer === 'yes')
|
|
387
|
-
return 'yes';
|
|
388
|
-
if (answer === 'info') {
|
|
389
|
-
process.stdout.write('\n');
|
|
390
|
-
process.stdout.write(body);
|
|
391
|
-
process.stdout.write('\n\nTrust this install? [y/N] ');
|
|
392
|
-
continue;
|
|
393
|
-
}
|
|
394
|
-
return 'no';
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
finally {
|
|
398
|
-
rl.close();
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
//# sourceMappingURL=skills.js.map
|
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `pugi status` — concise session-state probe ().
|
|
3
|
-
*
|
|
4
|
-
* Different from `pugi doctor` (environment health). The status
|
|
5
|
-
* command answers "what is this Pugi session doing right now?" —
|
|
6
|
-
* session id + age, cwd, permission mode, CLI version, token
|
|
7
|
-
* usage, dispatch counts, last command, compact boundaries, auth
|
|
8
|
-
* identity.
|
|
9
|
-
*
|
|
10
|
-
* # Module contract
|
|
11
|
-
*
|
|
12
|
-
* - This file owns the WIRING from CLI flags + ambient process
|
|
13
|
-
* state к the snapshot collector. The data collector itself
|
|
14
|
-
* lives in `core/diagnostics/probes/status-snapshot.ts` and
|
|
15
|
-
* has zero coupling к the CLI dispatch surface.
|
|
16
|
-
*
|
|
17
|
-
* - `runStatusCommand` is the single entry point. Both the
|
|
18
|
-
* top-level `pugi status` handler in `runtime/cli.ts` AND the
|
|
19
|
-
* in-REPL `/status` slash command call it. The function
|
|
20
|
-
* returns the `StatusSnapshot` so the REPL slash handler can
|
|
21
|
-
* mount the Ink renderer without re-collecting fields.
|
|
22
|
-
*
|
|
23
|
-
* - The credential resolver is captured behind a function so the
|
|
24
|
-
* spec can stub it without monkey-patching `core/credentials.ts`.
|
|
25
|
-
*
|
|
26
|
-
* - The permission state module is dynamic-imported with a
|
|
27
|
-
* try/catch so this command lands cleanly before the L6
|
|
28
|
-
* permission-mode work — when the module is absent the field
|
|
29
|
-
* degrades к "unknown" instead of crashing the snapshot.
|
|
30
|
-
*
|
|
31
|
-
* - Exit code is 0 unless the snapshot itself throws. The
|
|
32
|
-
* command is intentionally informational — even a fully
|
|
33
|
-
* "unavailable" snapshot (everything degraded к sentinels)
|
|
34
|
-
* exits 0 so monitoring scripts can rely on a stable contract.
|
|
35
|
-
*/
|
|
36
|
-
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
37
|
-
import { homedir } from 'node:os';
|
|
38
|
-
import { resolveActiveCredential } from '../../core/credentials.js';
|
|
39
|
-
import { PUGI_CLI_VERSION } from '../version.js';
|
|
40
|
-
import { collectStatusSnapshot, } from '../../core/diagnostics/probes/status-snapshot.js';
|
|
41
|
-
/**
|
|
42
|
-
* Default production filesystem stubs. Wraps node:fs so the
|
|
43
|
-
* snapshot collector can stay sync + structurally testable.
|
|
44
|
-
*/
|
|
45
|
-
const DEFAULT_FS = {
|
|
46
|
-
existsSync,
|
|
47
|
-
statSync,
|
|
48
|
-
readdirSync: (p) => readdirSync(p),
|
|
49
|
-
readFileSync: (p, encoding) => readFileSync(p, encoding),
|
|
50
|
-
};
|
|
51
|
-
/**
|
|
52
|
-
* Default credential resolver. Wraps `resolveActiveCredential` so
|
|
53
|
-
* the snapshot only sees the trimmed `ResolvedCredentialSummary`
|
|
54
|
-
* shape and не the full store record.
|
|
55
|
-
*/
|
|
56
|
-
function defaultResolveCredential(env, home) {
|
|
57
|
-
const cred = resolveActiveCredential(env, home);
|
|
58
|
-
if (!cred)
|
|
59
|
-
return null;
|
|
60
|
-
// Tier is не yet recorded в the credentials file — set к null
|
|
61
|
-
// until a future sprint surfaces `tier` on the stored record.
|
|
62
|
-
// The renderer hides the parenthetical when tier is null.
|
|
63
|
-
return {
|
|
64
|
-
apiUrl: cred.apiUrl,
|
|
65
|
-
label: cred.label ?? null,
|
|
66
|
-
tier: null,
|
|
67
|
-
identity: cred.label ?? null,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Default permission-mode loader. Dynamic-imports
|
|
72
|
-
* `core/permissions/state.ts` (L6 in the leak-parity roadmap);
|
|
73
|
-
* returns null when the module is absent OR malformed, which the
|
|
74
|
-
* snapshot field degrades к the "unknown" sentinel.
|
|
75
|
-
*/
|
|
76
|
-
async function defaultResolvePermissionMode() {
|
|
77
|
-
try {
|
|
78
|
-
const mod = (await import('../../core/permissions/state.js').catch(() => null));
|
|
79
|
-
if (!mod || typeof mod.getCurrentPermissionMode !== 'function') {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
const mode = mod.getCurrentPermissionMode();
|
|
83
|
-
return typeof mode === 'string' && mode.length > 0 ? mode : null;
|
|
84
|
-
}
|
|
85
|
-
catch {
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Collect the snapshot + emit the output via the supplied
|
|
91
|
-
* writeOutput sink. Returns the snapshot so REPL callers can
|
|
92
|
-
* route it к the Ink renderer instead of the plain-text fallback.
|
|
93
|
-
*/
|
|
94
|
-
export async function runStatusCommand(ctx) {
|
|
95
|
-
// Resolve the permission mode upfront — the snapshot is sync but
|
|
96
|
-
// the L6 loader is async (dynamic import). We materialise the
|
|
97
|
-
// value here and hand the snapshot a sync getter.
|
|
98
|
-
const permissionMode = ctx.resolvePermissionMode === undefined
|
|
99
|
-
? await defaultResolvePermissionMode()
|
|
100
|
-
: null;
|
|
101
|
-
const deps = {
|
|
102
|
-
cwd: ctx.cwd,
|
|
103
|
-
home: ctx.home,
|
|
104
|
-
cliVersion: PUGI_CLI_VERSION,
|
|
105
|
-
now: ctx.now ?? Date.now,
|
|
106
|
-
liveSessionId: ctx.liveSessionId ?? null,
|
|
107
|
-
sessionStartedAtEpochMs: ctx.sessionStartedAtEpochMs ?? null,
|
|
108
|
-
liveTokensUsed: ctx.liveTokensUsed ?? null,
|
|
109
|
-
lastCommand: ctx.lastCommand ?? null,
|
|
110
|
-
lastCommandAtEpochMs: ctx.lastCommandAtEpochMs ?? null,
|
|
111
|
-
liveApiUrl: ctx.liveApiUrl ?? null,
|
|
112
|
-
workspaceLabel: ctx.workspaceLabel ?? null,
|
|
113
|
-
fs: ctx.fs ?? DEFAULT_FS,
|
|
114
|
-
resolveCredential: ctx.resolveCredential ?? (() => defaultResolveCredential(ctx.env, ctx.home)),
|
|
115
|
-
resolvePermissionMode: ctx.resolvePermissionMode ?? (() => permissionMode),
|
|
116
|
-
};
|
|
117
|
-
let snapshot;
|
|
118
|
-
try {
|
|
119
|
-
snapshot = collectStatusSnapshot(deps);
|
|
120
|
-
}
|
|
121
|
-
catch (error) {
|
|
122
|
-
// Defensive: the snapshot collector is fail-soft per field, but
|
|
123
|
-
// a structural crash (e.g. a hostile env that throws on
|
|
124
|
-
// `process.version` access) must не bring down `pugi status`.
|
|
125
|
-
// We synthesise a minimal envelope and surface the error в the
|
|
126
|
-
// text output so the operator can file a bug.
|
|
127
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
128
|
-
snapshot = {
|
|
129
|
-
command: 'status',
|
|
130
|
-
fields: [
|
|
131
|
-
{
|
|
132
|
-
key: 'session',
|
|
133
|
-
label: 'Session',
|
|
134
|
-
value: 'unknown',
|
|
135
|
-
available: false,
|
|
136
|
-
note: `snapshot collector crashed: ${message}`,
|
|
137
|
-
},
|
|
138
|
-
],
|
|
139
|
-
meta: {
|
|
140
|
-
cliVersion: PUGI_CLI_VERSION,
|
|
141
|
-
nodeVersion: process.version,
|
|
142
|
-
cwd: ctx.cwd,
|
|
143
|
-
capturedAt: new Date((ctx.now ?? Date.now)()).toISOString(),
|
|
144
|
-
},
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
const text = renderStatusTable(snapshot);
|
|
148
|
-
ctx.writeOutput(snapshot, text);
|
|
149
|
-
// Always exit 0 — `pugi status` is informational, never a gate.
|
|
150
|
-
process.exitCode = 0;
|
|
151
|
-
return snapshot;
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Plain-text table renderer. Lays out the snapshot as a two-column
|
|
155
|
-
* (LABEL / VALUE) table with the brand-voice header `Pugi status`.
|
|
156
|
-
* Matches the column-light pattern used by `renderDoctorTable` so
|
|
157
|
-
* narrow terminals stay legible without a layout library.
|
|
158
|
-
*/
|
|
159
|
-
export function renderStatusTable(snapshot) {
|
|
160
|
-
// Row syntax: `${Label}: ${value}` with exactly ONE space after the
|
|
161
|
-
// colon, then the value verbatim. The colon doubles as a visual
|
|
162
|
-
// anchor and the REPL spec assertions match on the single-space
|
|
163
|
-
// form (`Backend: https://api.pugi.io`) — multi-space column
|
|
164
|
-
// padding broke `.includes('Backend: https://...')` substring
|
|
165
|
-
// checks. Operators who want a column layout can run the Ink
|
|
166
|
-
// renderer (`<StatusTable>`); the plain-text fallback stays
|
|
167
|
-
// narrow-terminal friendly without padding columns.
|
|
168
|
-
const lines = [];
|
|
169
|
-
lines.push('Pugi status');
|
|
170
|
-
lines.push('═'.repeat(50));
|
|
171
|
-
for (const field of snapshot.fields) {
|
|
172
|
-
lines.push(`${field.label}: ${field.value}`);
|
|
173
|
-
}
|
|
174
|
-
lines.push('');
|
|
175
|
-
lines.push(`CLI ${snapshot.meta.cliVersion} Node ${snapshot.meta.nodeVersion} cwd ${snapshot.meta.cwd}`);
|
|
176
|
-
return lines.join('\n');
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Default home dir resolver. Centralised so the CLI handler can
|
|
180
|
-
* call `runStatusCommand` without re-importing `os.homedir`
|
|
181
|
-
* everywhere.
|
|
182
|
-
*/
|
|
183
|
-
export function defaultStatusHome() {
|
|
184
|
-
return homedir();
|
|
185
|
-
}
|
|
186
|
-
//# sourceMappingURL=status.js.map
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `pugi stickers` — brand-personality gimmick command ().
|
|
3
|
-
*
|
|
4
|
-
* Parity command with the upstream tool's `/stickers` easter egg. Claude
|
|
5
|
-
* ships physical stickers OR shows ASCII brand art; Pugi's variant
|
|
6
|
-
* focuses на the ASCII branch — picks one of the curated pug-face
|
|
7
|
-
* variants at random and footers it with a rotating brand quote.
|
|
8
|
-
*
|
|
9
|
-
* # Module contract
|
|
10
|
-
*
|
|
11
|
-
* - This file owns the WIRING from CLI flags + ambient state to the
|
|
12
|
-
* art + quote pickers. The corpus + pure renderers live in
|
|
13
|
-
* `tui/stickers-art.tsx` and have zero coupling к the CLI dispatch
|
|
14
|
-
* surface.
|
|
15
|
-
*
|
|
16
|
-
* - `runStickersCommand` is the single entry point. Both the top-
|
|
17
|
-
* level `pugi stickers` handler в `runtime/cli.ts` AND the in-REPL
|
|
18
|
-
* `/stickers` slash command call it. The function returns the
|
|
19
|
-
* resolved `StickersResult` so the slash dispatcher can route the
|
|
20
|
-
* output к the REPL's system pane without re-picking the art.
|
|
21
|
-
*
|
|
22
|
-
* - Exit code is ALWAYS 0. The command is a brand surface — never a
|
|
23
|
-
* gate. Even when the corpus is somehow exhausted (impossible
|
|
24
|
-
* today, the lists are frozen), the handler synthesises a fallback
|
|
25
|
-
* line and exits 0 instead of crashing.
|
|
26
|
-
*
|
|
27
|
-
* - The random source is injected so the spec can pin the chosen
|
|
28
|
-
* art + quote without monkey-patching `Math.random`.
|
|
29
|
-
*/
|
|
30
|
-
import { PUG_QUOTES, PUG_STICKERS, pickArtVariant, pickQuote, renderPugStickersText, } from '../../tui/stickers-art.js';
|
|
31
|
-
/**
|
|
32
|
-
* Pick + render the sticker, hand it к the output sink, exit 0.
|
|
33
|
-
* Returns the picked result so the REPL slash handler can mount the
|
|
34
|
-
* Ink renderer without re-picking.
|
|
35
|
-
*/
|
|
36
|
-
export function runStickersCommand(ctx) {
|
|
37
|
-
const rng = ctx.rng ?? Math.random;
|
|
38
|
-
let art;
|
|
39
|
-
let quote;
|
|
40
|
-
try {
|
|
41
|
-
art = pickArtVariant(rng);
|
|
42
|
-
quote = pickQuote(rng);
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
// Defensive: the pickers are pure + the corpus is frozen, so this
|
|
46
|
-
// path is unreachable in production. If a future refactor swaps
|
|
47
|
-
// the corpus к an empty array we still want к exit 0 with a
|
|
48
|
-
// deterministic fallback so monitoring scripts that probe
|
|
49
|
-
// `pugi stickers` do not flap.
|
|
50
|
-
art = {
|
|
51
|
-
id: 'fallback',
|
|
52
|
-
caption: 'fallback',
|
|
53
|
-
art: '/\\___/\\\n( o o )\n( =^= )',
|
|
54
|
-
};
|
|
55
|
-
quote = 'Pugi: your engineering co-pilot.';
|
|
56
|
-
}
|
|
57
|
-
const text = renderPugStickersText(art, quote);
|
|
58
|
-
const result = {
|
|
59
|
-
command: 'stickers',
|
|
60
|
-
art,
|
|
61
|
-
quote,
|
|
62
|
-
text,
|
|
63
|
-
meta: {
|
|
64
|
-
artVariants: PUG_STICKERS.length,
|
|
65
|
-
quotes: PUG_QUOTES.length,
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
ctx.writeOutput(result, text);
|
|
69
|
-
// Brand surface — never a gate. The caller may have set a different
|
|
70
|
-
// exit code (e.g. dispatch loop reused this handler for an inline
|
|
71
|
-
// brand banner); we explicitly stamp 0 so `pugi stickers && echo ok`
|
|
72
|
-
// stays predictable.
|
|
73
|
-
process.exitCode = 0;
|
|
74
|
-
// Silence the unused-import warning in the rare case `ctx.asciiOnly`
|
|
75
|
-
// is added in a future surface without a switch. Today the flag is
|
|
76
|
-
// honoured by the CLI handler choosing the writeOutput sink — the
|
|
77
|
-
// result.text is the same regardless because the boxed renderer
|
|
78
|
-
// never lands в the plain stdout sink.
|
|
79
|
-
void ctx.asciiOnly;
|
|
80
|
-
return result;
|
|
81
|
-
}
|
|
82
|
-
//# sourceMappingURL=stickers.js.map
|