@pugi/cli 0.1.0-beta.1 → 0.1.0-beta.100
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/CHANGELOG.md +132 -0
- package/LICENSE +1 -1
- package/README.md +53 -11
- package/THIRD_PARTY_NOTICES.md +40 -0
- package/assets/pugi-mascot.ansi +15 -40
- package/assets/pugi-prozr2-mascot.ansi +9 -0
- package/bin/run.js +33 -1
- package/dist/commands/deploy.js +40 -40
- package/dist/commands/flatten.js +191 -0
- package/dist/commands/jobs-watch.js +201 -0
- package/dist/commands/jobs.js +42 -27
- package/dist/commands/retro.js +210 -0
- package/dist/commands/smoke.js +133 -0
- package/dist/core/agent-progress/cleanup.js +134 -0
- package/dist/core/agent-progress/schema.js +144 -0
- package/dist/core/agent-progress/writer.js +101 -0
- package/dist/core/agents/adaptive-router.js +330 -0
- package/dist/core/agents/query-decomposer.js +297 -0
- package/dist/core/agents/registry.js +3 -3
- package/dist/core/approvals/shortcut-resolver.js +98 -0
- package/dist/core/artifact-chain/dispatcher.js +148 -0
- package/dist/core/artifact-chain/exporter.js +164 -0
- package/dist/core/artifact-chain/state.js +243 -0
- package/dist/core/artifact-chain/steps.js +169 -0
- package/dist/core/ask-user/question.js +92 -0
- package/dist/core/audit/audit-trail.js +275 -0
- package/dist/core/auth/ensure-authenticated.js +129 -0
- package/dist/core/auth/env-provider.js +238 -0
- package/dist/core/auto-open-browser.js +4 -4
- package/dist/core/auto-update/channels.js +122 -0
- package/dist/core/auto-update/checker.js +241 -0
- package/dist/core/auto-update/state.js +235 -0
- package/dist/core/bare-mode/index.js +107 -0
- package/dist/core/bash/redirect.js +281 -0
- package/dist/core/bash-classifier.js +436 -40
- package/dist/core/checkpoint/resumer.js +149 -0
- package/dist/core/checkpoint/rewinder.js +291 -0
- package/dist/core/checkpoints/shadow-git.js +670 -0
- package/dist/core/citations/parser.js +109 -0
- package/dist/core/classifier/yolo-classifier.js +88 -0
- package/dist/core/codegraph/db.js +506 -0
- package/dist/core/codegraph/decision-store.js +248 -0
- package/dist/core/codegraph/detect-repo.js +459 -0
- package/dist/core/codegraph/install.js +134 -0
- package/dist/core/codegraph/offer-hook.js +220 -0
- package/dist/core/codegraph/parser.js +71 -0
- package/dist/core/codegraph/types.js +34 -0
- package/dist/core/compact/auto-trigger.js +96 -0
- package/dist/core/compact/buffer-rewriter.js +115 -0
- package/dist/core/compact/summarizer.js +208 -0
- package/dist/core/compact/token-counter.js +108 -0
- package/dist/core/consensus/anvil-fanout.js +25 -25
- package/dist/core/consensus/diff-capture.js +121 -12
- package/dist/core/consensus/rubric.js +21 -21
- package/dist/core/context/builder.js +6 -6
- package/dist/core/context/compaction-events.js +8 -8
- package/dist/core/context/compaction.js +31 -31
- package/dist/core/context/index.js +15 -8
- package/dist/core/context/invariants.js +51 -51
- package/dist/core/context/markdown-loader.js +28 -10
- package/dist/core/context/markdown-traverse.js +255 -0
- package/dist/core/context/pugiignore.js +41 -41
- package/dist/core/context/repo-skeleton.js +37 -37
- package/dist/core/context/tool-eviction.js +55 -0
- package/dist/core/context/watcher.js +32 -32
- package/dist/core/context/working-set.js +23 -23
- package/dist/core/coordinator/agent-tools.js +77 -0
- package/dist/core/coordinator/agent-toolset.js +65 -0
- package/dist/core/coordinator/fsm.js +73 -0
- package/dist/core/coordinator/mode-fsm.js +70 -0
- package/dist/core/cost/rate-card.js +129 -0
- package/dist/core/cost/tracker.js +221 -0
- package/dist/core/credentials.js +13 -13
- package/dist/core/cron/scheduler.js +138 -0
- package/dist/core/denial-tracking/index.js +8 -0
- package/dist/core/denial-tracking/state.js +264 -0
- package/dist/core/diagnostics/probe-runner.js +93 -0
- package/dist/core/diagnostics/probes/api.js +46 -0
- package/dist/core/diagnostics/probes/auth.js +93 -0
- package/dist/core/diagnostics/probes/bare-mode.js +42 -0
- package/dist/core/diagnostics/probes/cli-version.js +127 -0
- package/dist/core/diagnostics/probes/config.js +72 -0
- package/dist/core/diagnostics/probes/denial-tracking.js +57 -0
- package/dist/core/diagnostics/probes/disk.js +81 -0
- package/dist/core/diagnostics/probes/engine-live.js +46 -0
- package/dist/core/diagnostics/probes/git.js +65 -0
- package/dist/core/diagnostics/probes/hooks.js +118 -0
- package/dist/core/diagnostics/probes/mcp.js +75 -0
- package/dist/core/diagnostics/probes/node.js +59 -0
- package/dist/core/diagnostics/probes/pnpm.js +36 -0
- package/dist/core/diagnostics/probes/pugi-md.js +89 -0
- package/dist/core/diagnostics/probes/sandbox.js +72 -0
- package/dist/core/diagnostics/probes/session.js +74 -0
- package/dist/core/diagnostics/probes/status-snapshot.js +488 -0
- package/dist/core/diagnostics/probes/workspace.js +63 -0
- package/dist/core/diagnostics/types.js +70 -0
- package/dist/core/dispatch/cache-cleanup.js +197 -0
- package/dist/core/dispatch/cache-handoff.js +295 -0
- package/dist/core/edits/apply-patch-layer-e.js +189 -0
- package/dist/core/edits/dispatch.js +333 -7
- package/dist/core/edits/format-detector.js +260 -0
- package/dist/core/edits/format-matrix.js +26 -0
- package/dist/core/edits/fuzzy-ladder.js +650 -0
- package/dist/core/edits/index.js +5 -1
- package/dist/core/edits/journal.js +199 -0
- package/dist/core/edits/layer-a-apply.js +15 -15
- package/dist/core/edits/layer-a-fuzzy-apply.js +198 -0
- package/dist/core/edits/layer-b-apply.js +9 -9
- package/dist/core/edits/layer-c-apply.js +6 -6
- package/dist/core/edits/layer-d-ast.js +557 -14
- package/dist/core/edits/marker-parser.js +12 -12
- package/dist/core/edits/security-gate.js +27 -27
- package/dist/core/edits/verify-hook.js +273 -0
- package/dist/core/edits/worktree.js +322 -0
- package/dist/core/engine/anvil-client.js +214 -26
- package/dist/core/engine/auto-compact.js +247 -0
- package/dist/core/engine/budgets.js +220 -0
- package/dist/core/engine/compact-llm-summarizer.js +124 -0
- package/dist/core/engine/context-prefix.js +155 -0
- package/dist/core/engine/index.js +1 -1
- package/dist/core/engine/intensity.js +163 -0
- package/dist/core/engine/intent.js +260 -0
- package/dist/core/engine/native-pugi.js +1559 -227
- package/dist/core/engine/prompts.js +192 -16
- package/dist/core/engine/strip-internal-fields.js +124 -0
- package/dist/core/engine/tool-bridge.js +1887 -59
- package/dist/core/engine/verification-patterns.js +195 -0
- package/dist/core/evaluation/golden-dataset.js +293 -0
- package/dist/core/feedback/queue.js +177 -0
- package/dist/core/feedback/submitter.js +145 -0
- package/dist/core/file-cache.js +113 -1
- package/dist/core/flatten/flatten-repo.js +439 -0
- package/dist/core/format/osc8-link.js +28 -0
- package/dist/core/hook-chains.js +392 -0
- package/dist/core/hooks/citation-verify-hook.js +138 -0
- package/dist/core/hooks/citation-verify.js +112 -0
- package/dist/core/hooks/events.js +46 -0
- package/dist/core/hooks/index.js +15 -0
- package/dist/core/hooks/registry.js +216 -0
- package/dist/core/hooks/runner.js +236 -0
- package/dist/core/hooks/v2/event-emitter.js +115 -0
- package/dist/core/hooks/v2/executor.js +282 -0
- package/dist/core/hooks/v2/index.js +25 -0
- package/dist/core/hooks/v2/lifecycle.js +104 -0
- package/dist/core/hooks/v2/loader.js +216 -0
- package/dist/core/hooks/v2/matcher.js +125 -0
- package/dist/core/hooks/v2/trust.js +143 -0
- package/dist/core/hooks/v2/types.js +86 -0
- package/dist/core/hooks/worktree-events.js +158 -0
- package/dist/core/image/renderer.js +71 -0
- package/dist/core/init/detector.js +582 -0
- package/dist/core/init/template-renderer.js +242 -0
- package/dist/core/jobs/registry.js +18 -18
- package/dist/core/ledger/results-tsv.js +142 -0
- package/dist/core/log-discipline/stdout-redirect.js +51 -0
- package/dist/core/lsp/cache.js +105 -0
- package/dist/core/lsp/client.js +1229 -0
- package/dist/core/lsp/language-detect.js +66 -0
- package/dist/core/lsp/post-edit-diagnostics.js +171 -0
- package/dist/core/lsp/server-detect.js +173 -0
- package/dist/core/lsp/symbol-cache.js +162 -0
- package/dist/core/lsp/symbol-tools.js +664 -0
- package/dist/core/mcp/client.js +97 -28
- package/dist/core/mcp/http-server.js +553 -0
- package/dist/core/mcp/orchestrator-config.js +192 -0
- package/dist/core/mcp/orchestrator-tools.js +806 -0
- package/dist/core/mcp/permission.js +190 -0
- package/dist/core/mcp/registry.js +39 -17
- package/dist/core/mcp/server-tools.js +219 -0
- package/dist/core/mcp/server.js +397 -0
- package/dist/core/mcp/trust.js +10 -10
- package/dist/core/memory/dual-write.js +416 -0
- package/dist/core/memory/passive-extract.js +130 -0
- package/dist/core/memory/phase1-kinds.js +20 -0
- package/dist/core/memory/secret-scanner.js +304 -0
- package/dist/core/memory-sync/queue.js +170 -0
- package/dist/core/metrics/extract.js +113 -0
- package/dist/core/modes/roo-modes.js +68 -0
- package/dist/core/notes/notes-paths.js +113 -0
- package/dist/core/notes/notes-recorder.js +140 -0
- package/dist/core/notes/notes-writer.js +53 -0
- package/dist/core/notes/renderers.js +0 -0
- package/dist/core/notes/slug.js +105 -0
- package/dist/core/onboarding/ensure-initialized.js +133 -0
- package/dist/core/onboarding/marker.js +111 -0
- package/dist/core/onboarding/telemetry-state.js +108 -0
- package/dist/core/output-style/presets.js +176 -0
- package/dist/core/output-style/state.js +185 -0
- package/dist/core/path-security.js +287 -5
- package/dist/core/permission.js +82 -22
- package/dist/core/permissions/auto-classifier.js +124 -0
- package/dist/core/permissions/bash-parser.js +371 -0
- package/dist/core/permissions/circuit-breaker.js +83 -0
- package/dist/core/permissions/constrained-edit.js +91 -0
- package/dist/core/permissions/gate.js +278 -0
- package/dist/core/permissions/index.js +20 -0
- package/dist/core/permissions/mode.js +174 -0
- package/dist/core/permissions/network-egress.js +137 -0
- package/dist/core/permissions/state.js +241 -0
- package/dist/core/permissions/tool-class.js +107 -0
- package/dist/core/plan-mode/ui-state.js +51 -0
- package/dist/core/plans/plan-artifact.js +721 -0
- package/dist/core/policy-limits/etag-store.js +122 -0
- package/dist/core/prd-check/parser.js +215 -0
- package/dist/core/prd-check/reporter.js +127 -0
- package/dist/core/prd-check/session-review.js +557 -0
- package/dist/core/prd-check/verifiers.js +223 -0
- package/dist/core/prompt-cache/client-cache.js +99 -0
- package/dist/core/prompts/assembly.js +29 -0
- package/dist/core/prompts/registry.js +364 -0
- package/dist/core/pugi-gitignore.js +52 -0
- package/dist/core/pugi-md/cc-compat-rules.js +735 -0
- package/dist/core/pugi-md/context-injector.js +76 -0
- package/dist/core/pugi-md/walk-up.js +207 -0
- package/dist/core/python/uv-installer.js +270 -0
- package/dist/core/python/uv-resolver.js +83 -0
- package/dist/core/rate-limit/narrator.js +146 -0
- package/dist/core/recipes/cli-types.js +20 -0
- package/dist/core/recipes/loader.js +103 -0
- package/dist/core/recipes/runner.js +345 -0
- package/dist/core/recipes/schema.js +587 -0
- package/dist/core/release-notes/parser.js +241 -0
- package/dist/core/release-notes/state.js +116 -0
- package/dist/core/repl/ask.js +37 -37
- package/dist/core/repl/cancellation.js +26 -26
- package/dist/core/repl/cap-warning.js +4 -4
- package/dist/core/repl/clipboard-read.js +11 -11
- package/dist/core/repl/dispatch-fsm.js +12 -12
- package/dist/core/repl/engine-bridge.js +303 -0
- package/dist/core/repl/history-search.js +15 -15
- package/dist/core/repl/history.js +28 -18
- package/dist/core/repl/kill-ring.js +5 -5
- package/dist/core/repl/model-pricing.js +135 -0
- package/dist/core/repl/privacy-banner.js +22 -22
- package/dist/core/repl/session.js +2714 -228
- package/dist/core/repl/slash-commands.js +572 -40
- package/dist/core/repl/store/index.js +1 -1
- package/dist/core/repl/store/jsonl-log.js +22 -22
- package/dist/core/repl/store/lockfile.js +10 -10
- package/dist/core/repl/store/session-store.js +136 -107
- package/dist/core/repl/store/types.js +15 -15
- package/dist/core/repl/store/uuid-v7.js +12 -12
- package/dist/core/repl/tool-route.js +382 -0
- package/dist/core/repl/workspace-context.js +43 -21
- package/dist/core/repo-map/build.js +125 -0
- package/dist/core/repo-map/cache.js +185 -0
- package/dist/core/repo-map/extractor.js +254 -0
- package/dist/core/repo-map/formatter.js +145 -0
- package/dist/core/repo-map/page-rank.js +105 -0
- package/dist/core/repo-map/scanner.js +211 -0
- package/dist/core/retro/git-collector.js +251 -0
- package/dist/core/retro/health-card.js +25 -0
- package/dist/core/retro/metrics.js +342 -0
- package/dist/core/retro/narrative.js +249 -0
- package/dist/core/retro/plane-collector.js +274 -0
- package/dist/core/retro/pr-issue-link.js +65 -0
- package/dist/core/retro/types.js +16 -0
- package/dist/core/retry-budget/budget.js +284 -0
- package/dist/core/retry-budget/index.js +5 -0
- package/dist/core/retry-budget/retry-cap.js +74 -0
- package/dist/core/routing/lead-worker.js +43 -0
- package/dist/core/routing/pre-flight-estimator.js +108 -0
- package/dist/core/runs/run-tree.js +103 -0
- package/dist/core/sandboxing/adapter.js +29 -0
- package/dist/core/sandboxing/index.js +49 -0
- package/dist/core/sandboxing/none.js +19 -0
- package/dist/core/sandboxing/seatbelt.js +183 -0
- package/dist/core/security/injection-scanner.js +367 -0
- package/dist/core/security/output-filter.js +418 -0
- package/dist/core/session/env-file.js +105 -0
- package/dist/core/session/section-budgets.js +140 -0
- package/dist/core/session.js +119 -0
- package/dist/core/settings.js +378 -5
- package/dist/core/share/formatter.js +271 -0
- package/dist/core/share/redactor.js +221 -0
- package/dist/core/share/uploader.js +267 -0
- package/dist/core/skills/defaults.js +457 -0
- package/dist/core/skills/loader.js +22 -22
- package/dist/core/skills/sources.js +27 -27
- package/dist/core/smoke/headless-driver.js +174 -0
- package/dist/core/smoke/orchestrator.js +194 -0
- package/dist/core/smoke/runner.js +238 -0
- package/dist/core/smoke/scenario-parser.js +316 -0
- package/dist/core/statusline.js +99 -0
- package/dist/core/subagents/dispatcher-real.js +600 -0
- package/dist/core/subagents/dispatcher.js +146 -52
- package/dist/core/subagents/index.js +19 -6
- package/dist/core/subagents/isolation-matrix.js +213 -0
- package/dist/core/subagents/spawn.js +19 -4
- package/dist/core/telemetry/emitter.js +229 -0
- package/dist/core/telemetry/queue.js +251 -0
- package/dist/core/theme/context.js +91 -0
- package/dist/core/theme/presets.js +228 -0
- package/dist/core/theme/state.js +181 -0
- package/dist/core/todos/invariant.js +10 -0
- package/dist/core/todos/state.js +177 -0
- package/dist/core/tool-schema/compressor.js +89 -0
- package/dist/core/transport/version-interceptor.js +166 -0
- package/dist/core/trust.js +2 -2
- package/dist/core/tui/thinking-block.js +64 -0
- package/dist/core/vim/keymap.js +288 -0
- package/dist/core/vim/state.js +92 -0
- package/dist/core/watch-markers/marker-watcher.js +133 -0
- package/dist/core/worktree/include-parser.js +249 -0
- package/dist/core/worktree-manager/cleanup.js +123 -0
- package/dist/core/worktree-manager/manager.js +303 -0
- package/dist/index.js +36 -0
- package/dist/runtime/bootstrap.js +190 -0
- package/dist/runtime/cli.js +4536 -477
- package/dist/runtime/commands/agents.js +31 -31
- package/dist/runtime/commands/budget.js +5 -5
- package/dist/runtime/commands/cancel.js +231 -0
- package/dist/runtime/commands/chain.js +489 -0
- package/dist/runtime/commands/codegraph-status.js +227 -0
- package/dist/runtime/commands/compact.js +297 -0
- package/dist/runtime/commands/config.js +74 -40
- package/dist/runtime/commands/cost.js +199 -0
- package/dist/runtime/commands/delegate.js +312 -0
- package/dist/runtime/commands/dispatch.js +126 -0
- package/dist/runtime/commands/doctor.js +579 -0
- package/dist/runtime/commands/feedback.js +184 -0
- package/dist/runtime/commands/hooks.js +187 -0
- package/dist/runtime/commands/index-cmd.js +353 -0
- package/dist/runtime/commands/init.js +254 -0
- package/dist/runtime/commands/lsp.js +368 -0
- package/dist/runtime/commands/mcp.js +935 -0
- package/dist/runtime/commands/memory.js +582 -0
- package/dist/runtime/commands/model.js +237 -0
- package/dist/runtime/commands/onboarding.js +275 -0
- package/dist/runtime/commands/patch.js +128 -0
- package/dist/runtime/commands/permissions.js +112 -0
- package/dist/runtime/commands/plan.js +143 -0
- package/dist/runtime/commands/prd-check.js +285 -0
- package/dist/runtime/commands/privacy.js +17 -17
- package/dist/runtime/commands/recipe.js +325 -0
- package/dist/runtime/commands/redo-blob-store.js +92 -0
- package/dist/runtime/commands/redo.js +361 -0
- package/dist/runtime/commands/release-notes.js +229 -0
- package/dist/runtime/commands/repo-map.js +95 -0
- package/dist/runtime/commands/report.js +299 -0
- package/dist/runtime/commands/resume.js +118 -0
- package/dist/runtime/commands/review-consensus.js +68 -53
- package/dist/runtime/commands/rewind.js +333 -0
- package/dist/runtime/commands/roster.js +117 -0
- package/dist/runtime/commands/servers.js +236 -0
- package/dist/runtime/commands/sessions.js +163 -0
- package/dist/runtime/commands/share.js +316 -0
- package/dist/runtime/commands/skills.js +31 -31
- package/dist/runtime/commands/status.js +186 -0
- package/dist/runtime/commands/stickers.js +82 -0
- package/dist/runtime/commands/style.js +194 -0
- package/dist/runtime/commands/theme.js +196 -0
- package/dist/runtime/commands/undo.js +54 -22
- package/dist/runtime/commands/update.js +289 -0
- package/dist/runtime/commands/vim.js +140 -0
- package/dist/runtime/commands/worktree.js +177 -0
- package/dist/runtime/commands/worktrees.js +155 -0
- package/dist/runtime/deprecation-warning.js +69 -0
- package/dist/runtime/engine-exit-code.js +50 -0
- package/dist/runtime/headless-repl.js +195 -0
- package/dist/runtime/headless.js +548 -0
- package/dist/runtime/load-hooks-or-exit.js +71 -0
- package/dist/runtime/plan-decompose.js +531 -0
- package/dist/runtime/sigint-guard.js +272 -0
- package/dist/runtime/stream-renderer.js +195 -0
- package/dist/runtime/update-check.js +28 -28
- package/dist/runtime/version.js +65 -0
- package/dist/runtime/worktree-bootstrap.js +579 -0
- package/dist/skills/bundled/batch.js +617 -0
- package/dist/skills/bundled/index.js +45 -0
- package/dist/skills/bundled/loop.js +358 -0
- package/dist/skills/bundled/remember.js +383 -0
- package/dist/skills/bundled/simplify.js +289 -0
- package/dist/skills/bundled/skillify.js +373 -0
- package/dist/skills/bundled/stuck.js +558 -0
- package/dist/skills/bundled/verify.js +439 -0
- package/dist/testing/vcr.js +486 -0
- package/dist/tools/agent-tool.js +229 -0
- package/dist/tools/apply-patch.js +556 -0
- package/dist/tools/ask-user-question.js +337 -0
- package/dist/tools/ask-user.js +115 -0
- package/dist/tools/bash.js +624 -46
- package/dist/tools/brief.js +224 -0
- package/dist/tools/cron.js +433 -0
- package/dist/tools/enter-worktree.js +250 -0
- package/dist/tools/exit-worktree.js +147 -0
- package/dist/tools/file-tools.js +161 -44
- package/dist/tools/http-request.js +336 -0
- package/dist/tools/lsp-tools.js +565 -0
- package/dist/tools/mcp-tool.js +260 -0
- package/dist/tools/multi-edit.js +361 -0
- package/dist/tools/powershell.js +268 -0
- package/dist/tools/registry.js +142 -1
- package/dist/tools/server-tools.js +892 -0
- package/dist/tools/skill-tool.js +96 -0
- package/dist/tools/sleep.js +99 -0
- package/dist/tools/synthetic-output.js +133 -0
- package/dist/tools/tasks.js +208 -0
- package/dist/tools/todo-write.js +184 -0
- package/dist/tools/verify-plan-execution.js +295 -0
- package/dist/tools/web-fetch-injection-scanner.js +207 -0
- package/dist/tools/web-fetch.js +195 -10
- package/dist/tools/web-search.js +458 -0
- package/dist/tui/agent-progress-card.js +111 -0
- package/dist/tui/agent-tree.js +22 -1
- package/dist/tui/ask-modal.js +14 -14
- package/dist/tui/ask-user-question-chips.js +315 -0
- package/dist/tui/ask-user-question-prompt.js +203 -0
- package/dist/tui/compact-banner.js +81 -0
- package/dist/tui/conversation-pane.js +85 -11
- package/dist/tui/cost-table.js +111 -0
- package/dist/tui/device-flow.js +2 -2
- package/dist/tui/doctor-table.js +46 -0
- package/dist/tui/feedback-prompt.js +156 -0
- package/dist/tui/input-box.js +247 -32
- package/dist/tui/login-picker.js +3 -3
- package/dist/tui/markdown-render.js +6 -6
- package/dist/tui/multi-file-diff-approval.js +375 -0
- package/dist/tui/onboarding-wizard.js +240 -0
- package/dist/tui/permissions-picker.js +86 -0
- package/dist/tui/render.js +36 -1
- package/dist/tui/repl-render.js +405 -32
- package/dist/tui/repl-splash-art.js +16 -16
- package/dist/tui/repl-splash-mascot.js +48 -24
- package/dist/tui/repl-splash.js +22 -22
- package/dist/tui/repl.js +136 -43
- package/dist/tui/slash-palette.js +6 -6
- package/dist/tui/splash.js +2 -2
- package/dist/tui/status-bar.js +109 -31
- package/dist/tui/status-table.js +7 -0
- package/dist/tui/stickers-art.js +136 -0
- package/dist/tui/style-table.js +28 -0
- package/dist/tui/theme-table.js +29 -0
- package/dist/tui/thinking-spinner.js +123 -0
- package/dist/tui/tool-stream-pane.js +53 -4
- package/dist/tui/update-banner.js +27 -2
- package/dist/tui/vim-input.js +267 -0
- package/dist/tui/welcome-banner.js +107 -0
- package/dist/tui/welcome-data.js +293 -0
- package/dist/tui/workspace-context.js +2 -2
- package/docs/examples/codegraph.mcp.json +10 -0
- package/package.json +25 -7
- package/test/scenarios/codegen-create-file.scenario.txt +13 -0
- package/test/scenarios/compact-force.scenario.txt +12 -0
- package/test/scenarios/identity.scenario.txt +11 -0
- package/test/scenarios/persona-handoff.scenario.txt +12 -0
- package/test/scenarios/walkback.scenario.txt +12 -0
- package/dist/core/engine/compaction-hook.js +0 -154
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `pugi flatten` — CLI surface for the rendergit-port flatten engine.
|
|
3
|
+
*
|
|
4
|
+
* The runner lives here (not in `runtime/cli.ts`) so the dispatch
|
|
5
|
+
* surface stays focused on argv routing. This module owns:
|
|
6
|
+
*
|
|
7
|
+
* - Parsing the command-local flags (`--mode`, `--max-file-size`,
|
|
8
|
+
* `--include`, `--exclude`, `--stdout`, `--open`, `--out`).
|
|
9
|
+
* - Routing to `flattenRepo` with a resolved option bag.
|
|
10
|
+
* - Forwarding the rendered text + summary through the unified
|
|
11
|
+
* `writeOutput` writer so `--json` mode works without a second
|
|
12
|
+
* code path.
|
|
13
|
+
*
|
|
14
|
+
* Ported from karpathy/rendergit (BSD-0). License compatible with
|
|
15
|
+
* Pugi's open-source posture.
|
|
16
|
+
*/
|
|
17
|
+
import { resolve } from 'node:path';
|
|
18
|
+
import { DEFAULT_MAX_FILE_SIZE, flattenRepo, } from '../core/flatten/flatten-repo.js';
|
|
19
|
+
/**
|
|
20
|
+
* Entry point invoked by `runtime/cli.ts::dispatchFlatten`. Returns
|
|
21
|
+
* the desired process exit code so the dispatcher can set
|
|
22
|
+
* `process.exitCode` without a second round-trip.
|
|
23
|
+
*/
|
|
24
|
+
export async function runFlattenCommand(ctx) {
|
|
25
|
+
const parsed = parseArgs(ctx.args);
|
|
26
|
+
if ('error' in parsed) {
|
|
27
|
+
ctx.writeOutput({ ok: false, error: parsed.error }, `pugi flatten: ${parsed.error}`);
|
|
28
|
+
return 2;
|
|
29
|
+
}
|
|
30
|
+
const options = {
|
|
31
|
+
cwd: parsed.cwd,
|
|
32
|
+
mode: parsed.mode,
|
|
33
|
+
stdout: parsed.stdout,
|
|
34
|
+
maxFileSize: parsed.maxFileSize,
|
|
35
|
+
include: parsed.include,
|
|
36
|
+
exclude: parsed.exclude,
|
|
37
|
+
open: parsed.open,
|
|
38
|
+
};
|
|
39
|
+
try {
|
|
40
|
+
const result = await flattenRepo(options);
|
|
41
|
+
if (parsed.stdout) {
|
|
42
|
+
// Always emit the rendered text to stdout. JSON mode wraps it
|
|
43
|
+
// in an envelope so scripted callers can demux the result from
|
|
44
|
+
// the summary line.
|
|
45
|
+
if (ctx.json) {
|
|
46
|
+
ctx.writeOutput({
|
|
47
|
+
ok: true,
|
|
48
|
+
mode: parsed.mode,
|
|
49
|
+
files: result.files.length,
|
|
50
|
+
skipped: result.skipped.length,
|
|
51
|
+
html: result.html,
|
|
52
|
+
}, result.html);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
process.stdout.write(result.html);
|
|
56
|
+
}
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
const summary = `pugi flatten: wrote ${result.files.length} files (${result.skipped.length} skipped) to ${result.path ?? '<unknown>'}`;
|
|
60
|
+
ctx.writeOutput({
|
|
61
|
+
ok: true,
|
|
62
|
+
mode: parsed.mode,
|
|
63
|
+
path: result.path,
|
|
64
|
+
files: result.files.length,
|
|
65
|
+
skipped: result.skipped.length,
|
|
66
|
+
}, summary);
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
71
|
+
ctx.writeOutput({ ok: false, error: msg }, `pugi flatten: ${msg}`);
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function parseArgs(args) {
|
|
76
|
+
let cwd = process.cwd();
|
|
77
|
+
let mode = 'human';
|
|
78
|
+
let stdout = false;
|
|
79
|
+
let open = false;
|
|
80
|
+
let maxFileSize = DEFAULT_MAX_FILE_SIZE;
|
|
81
|
+
const include = [];
|
|
82
|
+
const exclude = [];
|
|
83
|
+
let positionalConsumed = false;
|
|
84
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
85
|
+
const arg = args[i] ?? '';
|
|
86
|
+
if (arg === '--stdout') {
|
|
87
|
+
stdout = true;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (arg === '--open') {
|
|
91
|
+
open = true;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (arg === '--mode') {
|
|
95
|
+
const next = args[i + 1];
|
|
96
|
+
if (!next)
|
|
97
|
+
return { error: '--mode requires a value (human | llm)' };
|
|
98
|
+
const m = parseMode(next);
|
|
99
|
+
if (!m)
|
|
100
|
+
return { error: `--mode: unknown value "${next}" (expected human | llm)` };
|
|
101
|
+
mode = m;
|
|
102
|
+
i += 1;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (arg.startsWith('--mode=')) {
|
|
106
|
+
const m = parseMode(arg.slice('--mode='.length));
|
|
107
|
+
if (!m)
|
|
108
|
+
return { error: `--mode: unknown value "${arg.slice('--mode='.length)}" (expected human | llm)` };
|
|
109
|
+
mode = m;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (arg === '--max-file-size') {
|
|
113
|
+
const next = args[i + 1];
|
|
114
|
+
if (!next)
|
|
115
|
+
return { error: '--max-file-size requires a value (e.g. 200kb)' };
|
|
116
|
+
const n = parseSize(next);
|
|
117
|
+
if (n === undefined)
|
|
118
|
+
return { error: `--max-file-size: cannot parse "${next}"` };
|
|
119
|
+
maxFileSize = n;
|
|
120
|
+
i += 1;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (arg.startsWith('--max-file-size=')) {
|
|
124
|
+
const v = arg.slice('--max-file-size='.length);
|
|
125
|
+
const n = parseSize(v);
|
|
126
|
+
if (n === undefined)
|
|
127
|
+
return { error: `--max-file-size: cannot parse "${v}"` };
|
|
128
|
+
maxFileSize = n;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (arg === '--include') {
|
|
132
|
+
const next = args[i + 1];
|
|
133
|
+
if (!next)
|
|
134
|
+
return { error: '--include requires a pattern' };
|
|
135
|
+
include.push(next);
|
|
136
|
+
i += 1;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (arg.startsWith('--include=')) {
|
|
140
|
+
include.push(arg.slice('--include='.length));
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (arg === '--exclude') {
|
|
144
|
+
const next = args[i + 1];
|
|
145
|
+
if (!next)
|
|
146
|
+
return { error: '--exclude requires a pattern' };
|
|
147
|
+
exclude.push(next);
|
|
148
|
+
i += 1;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (arg.startsWith('--exclude=')) {
|
|
152
|
+
exclude.push(arg.slice('--exclude='.length));
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (arg.startsWith('--')) {
|
|
156
|
+
return { error: `unknown flag "${arg}"` };
|
|
157
|
+
}
|
|
158
|
+
// Positional: workspace path. Only the first non-flag wins; extras
|
|
159
|
+
// are an error so a typo (`pugi flatten . foo`) surfaces.
|
|
160
|
+
if (positionalConsumed) {
|
|
161
|
+
return { error: `unexpected positional argument "${arg}"` };
|
|
162
|
+
}
|
|
163
|
+
cwd = resolve(arg);
|
|
164
|
+
positionalConsumed = true;
|
|
165
|
+
}
|
|
166
|
+
return { cwd, mode, stdout, open, maxFileSize, include, exclude };
|
|
167
|
+
}
|
|
168
|
+
function parseMode(v) {
|
|
169
|
+
if (v === 'human' || v === 'llm')
|
|
170
|
+
return v;
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Parse a size literal: bare number = bytes; `200kb` / `1mb` / `2gb`
|
|
175
|
+
* (case-insensitive, binary units — 1KB = 1024 bytes).
|
|
176
|
+
*/
|
|
177
|
+
export function parseSize(raw) {
|
|
178
|
+
const trimmed = raw.trim().toLowerCase();
|
|
179
|
+
if (trimmed.length === 0)
|
|
180
|
+
return undefined;
|
|
181
|
+
const match = /^(\d+(?:\.\d+)?)\s*(b|kb|mb|gb)?$/.exec(trimmed);
|
|
182
|
+
if (!match)
|
|
183
|
+
return undefined;
|
|
184
|
+
const n = Number(match[1]);
|
|
185
|
+
if (!Number.isFinite(n) || n < 0)
|
|
186
|
+
return undefined;
|
|
187
|
+
const unit = match[2] ?? 'b';
|
|
188
|
+
const multiplier = unit === 'b' ? 1 : unit === 'kb' ? 1024 : unit === 'mb' ? 1024 * 1024 : 1024 * 1024 * 1024;
|
|
189
|
+
return Math.floor(n * multiplier);
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=flatten.js.map
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* `pugi jobs --watch` Ink TUI — live progress .
|
|
4
|
+
*
|
|
5
|
+
* Tails `~/.pugi/agent-progress/*.json` via chokidar and re-renders a
|
|
6
|
+
* grid of <AgentProgressCard> components. Mirrors the the upstream tool
|
|
7
|
+
* `/compact` layout pattern — one card per agent, sorted by status
|
|
8
|
+
* (running → completed → failed) then by lastUpdate descending so the
|
|
9
|
+
* freshest activity floats к the top.
|
|
10
|
+
*
|
|
11
|
+
* Lifecycle:
|
|
12
|
+
* 1. Resolve dir via resolveProgressDir() (env-aware).
|
|
13
|
+
* 2. Initial scan with readdirSync — populate the map.
|
|
14
|
+
* 3. chokidar.watch(dir, { ignoreInitial: true }) for add/change/unlink.
|
|
15
|
+
* 4. setInterval(1000) tick re-renders to keep elapsed labels live
|
|
16
|
+
* WITHOUT re-reading files.
|
|
17
|
+
* 5. SIGINT (Ctrl+C) triggers `app.unmount()` + process.exit(0).
|
|
18
|
+
*
|
|
19
|
+
* Layout: single column under 100 cols, two columns at 100+ cols
|
|
20
|
+
* (Ink's flexbox computes the responsive split automatically — we just
|
|
21
|
+
* set `flexDirection="row" flexWrap="wrap"` and bound each card к 50%
|
|
22
|
+
* width when stdout is wide enough).
|
|
23
|
+
*
|
|
24
|
+
* The TUI is opt-in (operator runs `pugi jobs --watch`); the bare
|
|
25
|
+
* `pugi jobs` continues to print the legacy job-registry table.
|
|
26
|
+
*/
|
|
27
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
28
|
+
import { join } from 'node:path';
|
|
29
|
+
import chokidar from 'chokidar';
|
|
30
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
31
|
+
import { Box, Text, render, useApp, useInput, useStdout } from 'ink';
|
|
32
|
+
import { resolveProgressDir } from '../core/agent-progress/writer.js';
|
|
33
|
+
import { runCleanup } from '../core/agent-progress/cleanup.js';
|
|
34
|
+
import { validateAgentProgress, } from '../core/agent-progress/schema.js';
|
|
35
|
+
import { AgentProgressCard } from '../tui/agent-progress-card.js';
|
|
36
|
+
/** Cleanup pass cadence inside the watcher. Cheap (readdir on a small
|
|
37
|
+
* dir); 60s is the operator-tested sweet spot — fast enough to feel
|
|
38
|
+
* live, slow enough к never burn CPU. */
|
|
39
|
+
const CLEANUP_INTERVAL_MS = 60_000;
|
|
40
|
+
const STATUS_RANK = {
|
|
41
|
+
running: 0,
|
|
42
|
+
completed: 1,
|
|
43
|
+
failed: 2,
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Read + validate one progress file. Returns undefined on any failure
|
|
47
|
+
* — the watcher prefers к skip a malformed entry rather than crash.
|
|
48
|
+
* Exported for the spec.
|
|
49
|
+
*/
|
|
50
|
+
export function readProgressFile(path) {
|
|
51
|
+
if (!existsSync(path))
|
|
52
|
+
return undefined;
|
|
53
|
+
try {
|
|
54
|
+
const body = readFileSync(path, 'utf8');
|
|
55
|
+
const parsed = JSON.parse(body);
|
|
56
|
+
const result = validateAgentProgress(parsed);
|
|
57
|
+
return result.ok ? result.value : undefined;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Sort progress entries for stable, operator-friendly display:
|
|
65
|
+
* 1. Running first.
|
|
66
|
+
* 2. Then by lastUpdate (most recent first).
|
|
67
|
+
* 3. Tiebreak on agentId for snapshot stability.
|
|
68
|
+
*/
|
|
69
|
+
export function sortProgressEntries(entries) {
|
|
70
|
+
return [...entries].sort((a, b) => {
|
|
71
|
+
const rank = STATUS_RANK[a.status] - STATUS_RANK[b.status];
|
|
72
|
+
if (rank !== 0)
|
|
73
|
+
return rank;
|
|
74
|
+
const tsDiff = Date.parse(b.lastUpdate) - Date.parse(a.lastUpdate);
|
|
75
|
+
if (tsDiff !== 0)
|
|
76
|
+
return tsDiff;
|
|
77
|
+
return a.agentId.localeCompare(b.agentId);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
export function JobsWatch(props) {
|
|
81
|
+
const { dir, nowEpochMs, staticMode = false } = props;
|
|
82
|
+
const resolvedDir = useMemo(() => resolveProgressDir(dir), [dir]);
|
|
83
|
+
const [agents, setAgents] = useState(() => initialScan(resolvedDir));
|
|
84
|
+
const [tick, setTick] = useState(0);
|
|
85
|
+
const { exit } = useApp();
|
|
86
|
+
const { stdout } = useStdout();
|
|
87
|
+
const cols = stdout?.columns ?? 80;
|
|
88
|
+
const twoColumns = cols >= 100;
|
|
89
|
+
useInput((_input, key) => {
|
|
90
|
+
if (key.escape || key.ctrl) {
|
|
91
|
+
// Ink's useInput passes ctrl=true for Ctrl+<x>; we exit on Ctrl+C
|
|
92
|
+
// (key.ctrl alone is too broad — actual key char arrives in `input`).
|
|
93
|
+
// Practically, raw mode passes Ctrl+C as SIGINT to the process so
|
|
94
|
+
// this is a belt-and-suspenders catch.
|
|
95
|
+
if (key.escape)
|
|
96
|
+
exit();
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
if (staticMode)
|
|
101
|
+
return;
|
|
102
|
+
let watcher;
|
|
103
|
+
try {
|
|
104
|
+
watcher = chokidar.watch(resolvedDir, {
|
|
105
|
+
ignoreInitial: true,
|
|
106
|
+
depth: 0,
|
|
107
|
+
// The agent writer uses atomic rename — chokidar reports `add`
|
|
108
|
+
// when the final filename appears, never the *.tmp-* intermediate.
|
|
109
|
+
ignored: /\.tmp-/,
|
|
110
|
+
});
|
|
111
|
+
const onChange = (path) => {
|
|
112
|
+
if (!/\.json$/.test(path))
|
|
113
|
+
return;
|
|
114
|
+
const progress = readProgressFile(path);
|
|
115
|
+
if (!progress)
|
|
116
|
+
return;
|
|
117
|
+
setAgents((prev) => ({ ...prev, [progress.agentId]: progress }));
|
|
118
|
+
};
|
|
119
|
+
const onRemove = (path) => {
|
|
120
|
+
const match = /([^/\\]+)\.json$/.exec(path);
|
|
121
|
+
if (!match)
|
|
122
|
+
return;
|
|
123
|
+
const id = match[1];
|
|
124
|
+
if (!id)
|
|
125
|
+
return;
|
|
126
|
+
setAgents((prev) => {
|
|
127
|
+
if (!(id in prev))
|
|
128
|
+
return prev;
|
|
129
|
+
const next = { ...prev };
|
|
130
|
+
delete next[id];
|
|
131
|
+
return next;
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
watcher.on('add', onChange);
|
|
135
|
+
watcher.on('change', onChange);
|
|
136
|
+
watcher.on('unlink', onRemove);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// Watcher failures degrade gracefully — initial scan still rendered.
|
|
140
|
+
}
|
|
141
|
+
const interval = setInterval(() => setTick((t) => t + 1), 1000);
|
|
142
|
+
// Auto-cleanup completed/failed entries older than the TTL. The
|
|
143
|
+
// sweep moves them к `<dir>/archive/` so operators can still
|
|
144
|
+
// forensic; the watcher's chokidar `unlink` handler drops them
|
|
145
|
+
// from the live grid as the rename fires.
|
|
146
|
+
const cleanupInterval = setInterval(() => {
|
|
147
|
+
try {
|
|
148
|
+
runCleanup({ dir: resolvedDir });
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// best-effort housekeeping; never crash the TUI
|
|
152
|
+
}
|
|
153
|
+
}, CLEANUP_INTERVAL_MS);
|
|
154
|
+
return () => {
|
|
155
|
+
clearInterval(interval);
|
|
156
|
+
clearInterval(cleanupInterval);
|
|
157
|
+
if (watcher) {
|
|
158
|
+
void watcher.close();
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}, [resolvedDir, staticMode]);
|
|
162
|
+
const sorted = useMemo(() => sortProgressEntries(Object.values(agents)), [agents]);
|
|
163
|
+
const effectiveNow = nowEpochMs ?? Date.now() + tick * 0; // tick triggers re-render only
|
|
164
|
+
if (sorted.length === 0) {
|
|
165
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Text, { dimColor: true, children: ["No agents broadcasting progress yet. Watching", ' ', _jsx(Text, { bold: true, children: resolvedDir }), " for `<id>.json` files\u2026"] }), _jsx(Text, { dimColor: true, children: "(Press Esc / Ctrl+C \u043A exit.)" })] }));
|
|
166
|
+
}
|
|
167
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, children: "pugi jobs --watch" }), _jsxs(Text, { dimColor: true, children: [' ', "\u00B7 ", sorted.length, " ", sorted.length === 1 ? 'agent' : 'agents', " \u00B7", ' ', resolvedDir] })] }), _jsx(Box, { flexDirection: "row", flexWrap: "wrap", children: sorted.map((progress) => (_jsx(Box, { width: twoColumns ? '50%' : '100%', flexDirection: "column", children: _jsx(AgentProgressCard, { progress: progress, nowEpochMs: effectiveNow }) }, progress.agentId))) }), _jsx(Text, { dimColor: true, children: "(Esc / Ctrl+C \u043A exit.)" })] }));
|
|
168
|
+
}
|
|
169
|
+
function initialScan(dir) {
|
|
170
|
+
const map = {};
|
|
171
|
+
if (!existsSync(dir))
|
|
172
|
+
return map;
|
|
173
|
+
let entries;
|
|
174
|
+
try {
|
|
175
|
+
entries = readdirSync(dir);
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return map;
|
|
179
|
+
}
|
|
180
|
+
for (const name of entries) {
|
|
181
|
+
if (!name.endsWith('.json'))
|
|
182
|
+
continue;
|
|
183
|
+
if (/\.tmp-/.test(name))
|
|
184
|
+
continue;
|
|
185
|
+
const progress = readProgressFile(join(dir, name));
|
|
186
|
+
if (progress)
|
|
187
|
+
map[progress.agentId] = progress;
|
|
188
|
+
}
|
|
189
|
+
return map;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Entry-point for `pugi jobs --watch`. Mounts the Ink app and returns
|
|
193
|
+
* a Promise that resolves when the user exits (Ctrl+C / Esc).
|
|
194
|
+
*/
|
|
195
|
+
export async function runJobsWatch(options = {}) {
|
|
196
|
+
return new Promise((resolve) => {
|
|
197
|
+
const app = render(_jsx(JobsWatch, { dir: options.dir }), { exitOnCtrlC: true });
|
|
198
|
+
void app.waitUntilExit().then(() => resolve(0));
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=jobs-watch.js.map
|
package/dist/commands/jobs.js
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `pugi jobs` command surface — Sprint
|
|
2
|
+
* `pugi jobs` command surface — Sprint .
|
|
3
3
|
*
|
|
4
4
|
* Subcommands:
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* pugi jobs list — table of all tracked jobs (or JSON envelope)
|
|
6
|
+
* pugi jobs status <id> — full record + tail of overflow artifact
|
|
7
|
+
* pugi jobs tail <id> — stream the overflow artifact
|
|
8
|
+
* pugi jobs kill <id> — SIGTERM then SIGKILL after a grace
|
|
9
|
+
* pugi jobs kill --all — kill every running job in this session
|
|
10
10
|
*
|
|
11
11
|
* Power-word voice rules (per Pugi brand guide):
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
* - status names render as "on watch" (running), "shipped" (finished),
|
|
13
|
+
* "stood down" (killed), "blocked" (failed), "lost" (abandoned).
|
|
14
|
+
* - JSON envelopes keep the machine-friendly enum so consumers do
|
|
15
|
+
* not have to map back.
|
|
16
16
|
*/
|
|
17
17
|
import { existsSync, readFileSync } from 'node:fs';
|
|
18
18
|
import { formatDuration, getJobRegistry, relativeAge, } from '../core/jobs/registry.js';
|
|
19
|
+
import { runJobsWatch } from './jobs-watch.js';
|
|
19
20
|
const HUMAN_STATUS = {
|
|
20
21
|
running: 'on watch',
|
|
21
22
|
finished: 'shipped',
|
|
@@ -24,6 +25,19 @@ const HUMAN_STATUS = {
|
|
|
24
25
|
abandoned: 'lost',
|
|
25
26
|
};
|
|
26
27
|
export async function runJobsCommand(args, flags, io, sessionId) {
|
|
28
|
+
// live progress : `pugi jobs --watch` mounts the live
|
|
29
|
+
// agent-progress TUI. The flag may sit anywhere in the arg list
|
|
30
|
+
// (`pugi jobs --watch` or `pugi jobs watch`) — both forms route к
|
|
31
|
+
// the watcher. JSON mode is incompatible (it would never return); we
|
|
32
|
+
// bail with a helpful error instead of silently swallowing the flag.
|
|
33
|
+
const wantsWatch = args.includes('--watch') || args[0] === 'watch';
|
|
34
|
+
if (wantsWatch) {
|
|
35
|
+
if (flags.json) {
|
|
36
|
+
io.writeError('pugi jobs --watch is interactive; --json is not supported.');
|
|
37
|
+
return 2;
|
|
38
|
+
}
|
|
39
|
+
return runJobsWatch();
|
|
40
|
+
}
|
|
27
41
|
const sub = args[0] ?? 'list';
|
|
28
42
|
switch (sub) {
|
|
29
43
|
case 'list':
|
|
@@ -43,11 +57,12 @@ export async function runJobsCommand(args, flags, io, sessionId) {
|
|
|
43
57
|
function usage() {
|
|
44
58
|
return [
|
|
45
59
|
'Usage:',
|
|
46
|
-
'
|
|
47
|
-
'
|
|
48
|
-
'
|
|
49
|
-
'
|
|
50
|
-
'
|
|
60
|
+
' pugi jobs list [--json] Table of background jobs.',
|
|
61
|
+
' pugi jobs status <id> [--json] Full record + tail of artifact.',
|
|
62
|
+
' pugi jobs tail <id> Stream the captured artifact.',
|
|
63
|
+
' pugi jobs kill <id> [--json] SIGTERM, escalate to SIGKILL.',
|
|
64
|
+
' pugi jobs kill --all [--json] Stand down every running job.',
|
|
65
|
+
' pugi jobs --watch Live Ink TUI of agent progress.',
|
|
51
66
|
].join('\n');
|
|
52
67
|
}
|
|
53
68
|
async function runList(flags, io) {
|
|
@@ -91,20 +106,20 @@ async function runStatus(id, flags, io) {
|
|
|
91
106
|
}
|
|
92
107
|
const lines = [
|
|
93
108
|
`Job ${entry.id}`,
|
|
94
|
-
`
|
|
95
|
-
`
|
|
96
|
-
`
|
|
97
|
-
`
|
|
98
|
-
`
|
|
99
|
-
`
|
|
100
|
-
`
|
|
109
|
+
` PID: ${entry.pid}`,
|
|
110
|
+
` Command: ${entry.command}`,
|
|
111
|
+
` Class: ${entry.bashClass}`,
|
|
112
|
+
` Status: ${HUMAN_STATUS[entry.status]} (${entry.status})`,
|
|
113
|
+
` CWD: ${entry.cwd}`,
|
|
114
|
+
` Started: ${entry.startedAt} (${relativeAge(entry.startedAt)} ago)`,
|
|
115
|
+
` Duration: ${formatDuration(entry.startedAt, entry.finishedAt)}`,
|
|
101
116
|
];
|
|
102
117
|
if (entry.finishedAt)
|
|
103
|
-
lines.push(`
|
|
118
|
+
lines.push(` Finished: ${entry.finishedAt}`);
|
|
104
119
|
if (entry.exitCode !== undefined)
|
|
105
|
-
lines.push(`
|
|
120
|
+
lines.push(` Exit code: ${entry.exitCode}`);
|
|
106
121
|
if (entry.outputArtifactRef)
|
|
107
|
-
lines.push(`
|
|
122
|
+
lines.push(` Artifact: ${entry.outputArtifactRef}`);
|
|
108
123
|
if (tail) {
|
|
109
124
|
lines.push('', '--- output tail ---', tail);
|
|
110
125
|
}
|
|
@@ -159,7 +174,7 @@ async function runKill(args, flags, io, sessionId) {
|
|
|
159
174
|
}
|
|
160
175
|
else {
|
|
161
176
|
for (const result of results) {
|
|
162
|
-
io.write(`
|
|
177
|
+
io.write(` ${result.id} ${result.killed ? 'stood down' : 'noop'} (${result.method})\n`);
|
|
163
178
|
}
|
|
164
179
|
}
|
|
165
180
|
return 0;
|
|
@@ -233,7 +248,7 @@ function renderTable(entries) {
|
|
|
233
248
|
return rows
|
|
234
249
|
.map((row) => row
|
|
235
250
|
.map((cell, i) => cell.padEnd(widths[i] ?? cell.length))
|
|
236
|
-
.join('
|
|
251
|
+
.join(' ')
|
|
237
252
|
.trimEnd())
|
|
238
253
|
.join('\n');
|
|
239
254
|
}
|