@pugi/cli 0.1.0-beta.99 → 1.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +11 -191
- package/bin/pugi +8 -0
- package/package.json +15 -71
- package/postinstall.mjs +31 -0
- package/CHANGELOG.md +0 -132
- package/THIRD_PARTY_NOTICES.md +0 -40
- package/assets/pugi-mascot.ansi +0 -16
- package/assets/pugi-prozr2-mascot.ansi +0 -9
- package/bin/run.js +0 -34
- package/dist/commands/deploy.js +0 -439
- package/dist/commands/flatten.js +0 -191
- package/dist/commands/jobs-watch.js +0 -201
- package/dist/commands/jobs.js +0 -260
- package/dist/commands/retro.js +0 -210
- package/dist/commands/smoke.js +0 -133
- package/dist/core/agent-progress/cleanup.js +0 -134
- package/dist/core/agent-progress/schema.js +0 -144
- package/dist/core/agent-progress/writer.js +0 -101
- package/dist/core/agents/adaptive-router.js +0 -330
- package/dist/core/agents/loader.js +0 -104
- package/dist/core/agents/query-decomposer.js +0 -297
- package/dist/core/agents/registry.js +0 -69
- package/dist/core/approvals/shortcut-resolver.js +0 -98
- package/dist/core/artifact-chain/dispatcher.js +0 -148
- package/dist/core/artifact-chain/exporter.js +0 -164
- package/dist/core/artifact-chain/state.js +0 -243
- package/dist/core/artifact-chain/steps.js +0 -169
- package/dist/core/ask-user/question.js +0 -92
- package/dist/core/audit/audit-trail.js +0 -275
- package/dist/core/auth/ensure-authenticated.js +0 -129
- package/dist/core/auth/env-provider.js +0 -238
- package/dist/core/auto-open-browser.js +0 -128
- package/dist/core/auto-update/channels.js +0 -122
- package/dist/core/auto-update/checker.js +0 -241
- package/dist/core/auto-update/state.js +0 -235
- package/dist/core/bare-mode/index.js +0 -107
- package/dist/core/bash/redirect.js +0 -281
- package/dist/core/bash-classifier.js +0 -1397
- package/dist/core/checkpoint/resumer.js +0 -149
- package/dist/core/checkpoint/rewinder.js +0 -291
- package/dist/core/checkpoints/shadow-git.js +0 -670
- package/dist/core/citations/parser.js +0 -109
- package/dist/core/classifier/yolo-classifier.js +0 -88
- package/dist/core/clipboard.js +0 -70
- package/dist/core/codegraph/decision-store.js +0 -248
- package/dist/core/codegraph/detect-repo.js +0 -459
- package/dist/core/codegraph/install.js +0 -134
- package/dist/core/codegraph/offer-hook.js +0 -220
- package/dist/core/compact/auto-trigger.js +0 -96
- package/dist/core/compact/buffer-rewriter.js +0 -115
- package/dist/core/compact/summarizer.js +0 -208
- package/dist/core/compact/token-counter.js +0 -108
- package/dist/core/consensus/anvil-fanout.js +0 -276
- package/dist/core/consensus/diff-capture.js +0 -491
- package/dist/core/consensus/rubric.js +0 -233
- package/dist/core/context/builder.js +0 -114
- package/dist/core/context/compaction-events.js +0 -99
- package/dist/core/context/compaction.js +0 -602
- package/dist/core/context/index.js +0 -28
- package/dist/core/context/invariants.js +0 -250
- package/dist/core/context/markdown-loader.js +0 -288
- package/dist/core/context/markdown-traverse.js +0 -255
- package/dist/core/context/pugiignore.js +0 -316
- package/dist/core/context/repo-skeleton.js +0 -533
- package/dist/core/context/tool-eviction.js +0 -55
- package/dist/core/context/watcher.js +0 -342
- package/dist/core/context/working-set.js +0 -165
- package/dist/core/coordinator/agent-tools.js +0 -77
- package/dist/core/coordinator/agent-toolset.js +0 -65
- package/dist/core/coordinator/fsm.js +0 -73
- package/dist/core/coordinator/mode-fsm.js +0 -70
- package/dist/core/cost/rate-card.js +0 -129
- package/dist/core/cost/tracker.js +0 -221
- package/dist/core/credentials.js +0 -355
- package/dist/core/cron/scheduler.js +0 -138
- package/dist/core/denial-tracking/index.js +0 -8
- package/dist/core/denial-tracking/state.js +0 -264
- package/dist/core/diagnostics/probe-runner.js +0 -93
- package/dist/core/diagnostics/probes/api.js +0 -46
- package/dist/core/diagnostics/probes/auth.js +0 -93
- package/dist/core/diagnostics/probes/bare-mode.js +0 -42
- package/dist/core/diagnostics/probes/cli-version.js +0 -127
- package/dist/core/diagnostics/probes/config.js +0 -72
- package/dist/core/diagnostics/probes/denial-tracking.js +0 -57
- package/dist/core/diagnostics/probes/disk.js +0 -81
- package/dist/core/diagnostics/probes/engine-live.js +0 -46
- package/dist/core/diagnostics/probes/git.js +0 -65
- package/dist/core/diagnostics/probes/hooks.js +0 -118
- package/dist/core/diagnostics/probes/mcp.js +0 -75
- package/dist/core/diagnostics/probes/node.js +0 -59
- package/dist/core/diagnostics/probes/pnpm.js +0 -36
- package/dist/core/diagnostics/probes/pugi-md.js +0 -89
- package/dist/core/diagnostics/probes/sandbox.js +0 -72
- package/dist/core/diagnostics/probes/session.js +0 -74
- package/dist/core/diagnostics/probes/status-snapshot.js +0 -488
- package/dist/core/diagnostics/probes/workspace.js +0 -63
- package/dist/core/diagnostics/types.js +0 -70
- package/dist/core/dispatch/cache-cleanup.js +0 -197
- package/dist/core/dispatch/cache-handoff.js +0 -295
- package/dist/core/edits/apply-patch-layer-e.js +0 -189
- package/dist/core/edits/dispatch.js +0 -511
- package/dist/core/edits/format-detector.js +0 -260
- package/dist/core/edits/format-matrix.js +0 -26
- package/dist/core/edits/fuzzy-ladder.js +0 -650
- package/dist/core/edits/index.js +0 -19
- package/dist/core/edits/journal.js +0 -199
- package/dist/core/edits/layer-a-apply.js +0 -217
- package/dist/core/edits/layer-a-fuzzy-apply.js +0 -198
- package/dist/core/edits/layer-b-apply.js +0 -211
- package/dist/core/edits/layer-c-apply.js +0 -160
- package/dist/core/edits/layer-d-ast.js +0 -572
- package/dist/core/edits/marker-parser.js +0 -401
- package/dist/core/edits/security-gate.js +0 -223
- package/dist/core/edits/verify-hook.js +0 -273
- package/dist/core/edits/worktree.js +0 -322
- package/dist/core/engine/adapter-runner.js +0 -8
- package/dist/core/engine/anvil-client.js +0 -344
- package/dist/core/engine/auto-compact.js +0 -179
- package/dist/core/engine/budgets.js +0 -195
- package/dist/core/engine/context-prefix.js +0 -155
- package/dist/core/engine/index.js +0 -12
- package/dist/core/engine/intensity.js +0 -163
- package/dist/core/engine/intent.js +0 -260
- package/dist/core/engine/native-pugi.js +0 -1616
- package/dist/core/engine/noop.js +0 -27
- package/dist/core/engine/prompts.js +0 -236
- package/dist/core/engine/strip-internal-fields.js +0 -124
- package/dist/core/engine/tool-bridge.js +0 -2173
- package/dist/core/engine/verification-patterns.js +0 -195
- package/dist/core/evaluation/golden-dataset.js +0 -293
- package/dist/core/feedback/queue.js +0 -177
- package/dist/core/feedback/submitter.js +0 -145
- package/dist/core/file-cache.js +0 -141
- package/dist/core/flatten/flatten-repo.js +0 -439
- package/dist/core/format/osc8-link.js +0 -28
- package/dist/core/hook-chains.js +0 -392
- package/dist/core/hooks/citation-verify-hook.js +0 -138
- package/dist/core/hooks/citation-verify.js +0 -112
- package/dist/core/hooks/events.js +0 -46
- package/dist/core/hooks/index.js +0 -15
- package/dist/core/hooks/registry.js +0 -216
- package/dist/core/hooks/runner.js +0 -236
- package/dist/core/hooks/v2/event-emitter.js +0 -115
- package/dist/core/hooks/v2/executor.js +0 -282
- package/dist/core/hooks/v2/index.js +0 -25
- package/dist/core/hooks/v2/lifecycle.js +0 -104
- package/dist/core/hooks/v2/loader.js +0 -216
- package/dist/core/hooks/v2/matcher.js +0 -125
- package/dist/core/hooks/v2/trust.js +0 -143
- package/dist/core/hooks/v2/types.js +0 -86
- package/dist/core/hooks/worktree-events.js +0 -158
- package/dist/core/hooks.js +0 -415
- package/dist/core/image/renderer.js +0 -71
- package/dist/core/index-store.js +0 -260
- package/dist/core/init/detector.js +0 -582
- package/dist/core/init/template-renderer.js +0 -242
- package/dist/core/jobs/registry.js +0 -462
- package/dist/core/ledger/results-tsv.js +0 -142
- package/dist/core/log-discipline/stdout-redirect.js +0 -51
- package/dist/core/lsp/cache.js +0 -105
- package/dist/core/lsp/client.js +0 -1229
- package/dist/core/lsp/language-detect.js +0 -66
- package/dist/core/lsp/post-edit-diagnostics.js +0 -171
- package/dist/core/lsp/server-detect.js +0 -173
- package/dist/core/lsp/symbol-cache.js +0 -162
- package/dist/core/lsp/symbol-tools.js +0 -664
- package/dist/core/mcp/client.js +0 -385
- package/dist/core/mcp/http-server.js +0 -553
- package/dist/core/mcp/orchestrator-config.js +0 -192
- package/dist/core/mcp/orchestrator-tools.js +0 -806
- package/dist/core/mcp/permission.js +0 -190
- package/dist/core/mcp/registry.js +0 -193
- package/dist/core/mcp/server-tools.js +0 -219
- package/dist/core/mcp/server.js +0 -397
- package/dist/core/mcp/trust.js +0 -91
- package/dist/core/memory/dual-write.js +0 -416
- package/dist/core/memory/passive-extract.js +0 -130
- package/dist/core/memory/phase1-kinds.js +0 -20
- package/dist/core/memory/secret-scanner.js +0 -304
- package/dist/core/memory-sync/queue.js +0 -170
- package/dist/core/metrics/extract.js +0 -113
- package/dist/core/modes/roo-modes.js +0 -68
- package/dist/core/onboarding/ensure-initialized.js +0 -133
- package/dist/core/onboarding/marker.js +0 -111
- package/dist/core/onboarding/telemetry-state.js +0 -108
- package/dist/core/output-style/presets.js +0 -176
- package/dist/core/output-style/state.js +0 -185
- package/dist/core/path-security.js +0 -345
- package/dist/core/permission.js +0 -369
- package/dist/core/permissions/auto-classifier.js +0 -124
- package/dist/core/permissions/bash-parser.js +0 -371
- package/dist/core/permissions/circuit-breaker.js +0 -83
- package/dist/core/permissions/constrained-edit.js +0 -91
- package/dist/core/permissions/gate.js +0 -278
- package/dist/core/permissions/index.js +0 -20
- package/dist/core/permissions/mode.js +0 -174
- package/dist/core/permissions/network-egress.js +0 -137
- package/dist/core/permissions/state.js +0 -241
- package/dist/core/permissions/tool-class.js +0 -107
- package/dist/core/plan-mode/ui-state.js +0 -51
- package/dist/core/plans/plan-artifact.js +0 -721
- package/dist/core/policy-limits/etag-store.js +0 -122
- package/dist/core/prd-check/parser.js +0 -215
- package/dist/core/prd-check/reporter.js +0 -127
- package/dist/core/prd-check/session-review.js +0 -557
- package/dist/core/prd-check/verifiers.js +0 -223
- package/dist/core/prompt-cache/client-cache.js +0 -99
- package/dist/core/prompts/assembly.js +0 -29
- package/dist/core/prompts/registry.js +0 -364
- package/dist/core/pugi-gitignore.js +0 -52
- package/dist/core/pugi-md/cc-compat-rules.js +0 -735
- package/dist/core/pugi-md/context-injector.js +0 -76
- package/dist/core/pugi-md/walk-up.js +0 -207
- package/dist/core/python/uv-installer.js +0 -270
- package/dist/core/python/uv-resolver.js +0 -83
- package/dist/core/rate-limit/narrator.js +0 -146
- package/dist/core/recipes/cli-types.js +0 -20
- package/dist/core/recipes/loader.js +0 -103
- package/dist/core/recipes/runner.js +0 -345
- package/dist/core/recipes/schema.js +0 -587
- package/dist/core/release-notes/parser.js +0 -241
- package/dist/core/release-notes/state.js +0 -116
- package/dist/core/repl/ask.js +0 -512
- package/dist/core/repl/cancellation.js +0 -98
- package/dist/core/repl/cap-warning.js +0 -91
- package/dist/core/repl/clipboard-read.js +0 -174
- package/dist/core/repl/dispatch-fsm.js +0 -220
- package/dist/core/repl/engine-bridge.js +0 -303
- package/dist/core/repl/history-search.js +0 -175
- package/dist/core/repl/history.js +0 -182
- package/dist/core/repl/kill-ring.js +0 -138
- package/dist/core/repl/model-pricing.js +0 -135
- package/dist/core/repl/privacy-banner.js +0 -71
- package/dist/core/repl/session.js +0 -4962
- package/dist/core/repl/slash-commands.js +0 -747
- package/dist/core/repl/store/index.js +0 -12
- package/dist/core/repl/store/jsonl-log.js +0 -321
- package/dist/core/repl/store/lockfile.js +0 -155
- package/dist/core/repl/store/session-store.js +0 -821
- package/dist/core/repl/store/types.js +0 -44
- package/dist/core/repl/store/uuid-v7.js +0 -68
- package/dist/core/repl/tool-route.js +0 -382
- package/dist/core/repl/workspace-context.js +0 -206
- package/dist/core/repo-map/build.js +0 -125
- package/dist/core/repo-map/cache.js +0 -185
- package/dist/core/repo-map/extractor.js +0 -254
- package/dist/core/repo-map/formatter.js +0 -145
- package/dist/core/repo-map/page-rank.js +0 -105
- package/dist/core/repo-map/scanner.js +0 -211
- package/dist/core/retro/git-collector.js +0 -251
- package/dist/core/retro/health-card.js +0 -25
- package/dist/core/retro/metrics.js +0 -342
- package/dist/core/retro/narrative.js +0 -249
- package/dist/core/retro/plane-collector.js +0 -274
- package/dist/core/retro/pr-issue-link.js +0 -65
- package/dist/core/retro/types.js +0 -16
- package/dist/core/retry-budget/budget.js +0 -284
- package/dist/core/retry-budget/index.js +0 -5
- package/dist/core/retry-budget/retry-cap.js +0 -74
- package/dist/core/routing/lead-worker.js +0 -43
- package/dist/core/routing/pre-flight-estimator.js +0 -108
- package/dist/core/runs/run-tree.js +0 -103
- package/dist/core/sandboxing/adapter.js +0 -29
- package/dist/core/sandboxing/index.js +0 -49
- package/dist/core/sandboxing/none.js +0 -19
- package/dist/core/sandboxing/seatbelt.js +0 -183
- package/dist/core/security/injection-scanner.js +0 -367
- package/dist/core/security/output-filter.js +0 -418
- package/dist/core/session/env-file.js +0 -105
- package/dist/core/session/section-budgets.js +0 -140
- package/dist/core/session.js +0 -377
- package/dist/core/settings.js +0 -400
- package/dist/core/share/formatter.js +0 -271
- package/dist/core/share/redactor.js +0 -221
- package/dist/core/share/uploader.js +0 -267
- package/dist/core/skills/defaults.js +0 -457
- package/dist/core/skills/loader.js +0 -454
- package/dist/core/skills/sources.js +0 -480
- package/dist/core/skills/trust.js +0 -172
- package/dist/core/smoke/headless-driver.js +0 -174
- package/dist/core/smoke/orchestrator.js +0 -194
- package/dist/core/smoke/runner.js +0 -238
- package/dist/core/smoke/scenario-parser.js +0 -316
- package/dist/core/statusline.js +0 -99
- package/dist/core/subagents/dispatcher-real.js +0 -600
- package/dist/core/subagents/dispatcher.js +0 -352
- package/dist/core/subagents/index.js +0 -39
- package/dist/core/subagents/isolation-matrix.js +0 -213
- package/dist/core/subagents/spawn.js +0 -101
- package/dist/core/telemetry/emitter.js +0 -229
- package/dist/core/telemetry/queue.js +0 -251
- package/dist/core/theme/context.js +0 -91
- package/dist/core/theme/presets.js +0 -228
- package/dist/core/theme/state.js +0 -181
- package/dist/core/todos/invariant.js +0 -10
- package/dist/core/todos/state.js +0 -177
- package/dist/core/tool-schema/compressor.js +0 -89
- package/dist/core/transport/version-interceptor.js +0 -166
- package/dist/core/trust.js +0 -109
- package/dist/core/tui/thinking-block.js +0 -64
- package/dist/core/vim/keymap.js +0 -288
- package/dist/core/vim/state.js +0 -92
- package/dist/core/watch-markers/marker-watcher.js +0 -133
- package/dist/core/worktree/include-parser.js +0 -249
- package/dist/core/worktree-manager/cleanup.js +0 -123
- package/dist/core/worktree-manager/manager.js +0 -303
- package/dist/index.js +0 -44
- package/dist/runtime/bootstrap.js +0 -190
- package/dist/runtime/cli.js +0 -8121
- package/dist/runtime/commands/agents.js +0 -385
- package/dist/runtime/commands/budget.js +0 -192
- package/dist/runtime/commands/cancel.js +0 -231
- package/dist/runtime/commands/chain.js +0 -489
- package/dist/runtime/commands/codegraph-status.js +0 -227
- package/dist/runtime/commands/compact.js +0 -297
- package/dist/runtime/commands/config.js +0 -595
- package/dist/runtime/commands/cost.js +0 -199
- package/dist/runtime/commands/delegate.js +0 -312
- package/dist/runtime/commands/dispatch.js +0 -126
- package/dist/runtime/commands/doctor.js +0 -579
- package/dist/runtime/commands/feedback.js +0 -184
- package/dist/runtime/commands/hooks.js +0 -187
- package/dist/runtime/commands/init.js +0 -254
- package/dist/runtime/commands/lsp.js +0 -368
- package/dist/runtime/commands/mcp.js +0 -935
- package/dist/runtime/commands/memory.js +0 -582
- package/dist/runtime/commands/model.js +0 -237
- package/dist/runtime/commands/onboarding.js +0 -275
- package/dist/runtime/commands/patch.js +0 -128
- package/dist/runtime/commands/permissions.js +0 -112
- package/dist/runtime/commands/plan.js +0 -143
- package/dist/runtime/commands/prd-check.js +0 -285
- package/dist/runtime/commands/privacy.js +0 -107
- package/dist/runtime/commands/recipe.js +0 -325
- package/dist/runtime/commands/redo-blob-store.js +0 -92
- package/dist/runtime/commands/redo.js +0 -361
- package/dist/runtime/commands/release-notes.js +0 -229
- package/dist/runtime/commands/repo-map.js +0 -95
- package/dist/runtime/commands/report.js +0 -299
- package/dist/runtime/commands/resume.js +0 -118
- package/dist/runtime/commands/review-consensus.js +0 -414
- package/dist/runtime/commands/rewind.js +0 -333
- package/dist/runtime/commands/roster.js +0 -117
- package/dist/runtime/commands/sessions.js +0 -163
- package/dist/runtime/commands/share.js +0 -316
- package/dist/runtime/commands/skills.js +0 -401
- package/dist/runtime/commands/status.js +0 -186
- package/dist/runtime/commands/stickers.js +0 -82
- package/dist/runtime/commands/style.js +0 -194
- package/dist/runtime/commands/theme.js +0 -196
- package/dist/runtime/commands/undo.js +0 -361
- package/dist/runtime/commands/update.js +0 -289
- package/dist/runtime/commands/vim.js +0 -140
- package/dist/runtime/commands/worktree.js +0 -177
- package/dist/runtime/commands/worktrees.js +0 -155
- package/dist/runtime/deprecation-warning.js +0 -69
- package/dist/runtime/engine-exit-code.js +0 -50
- package/dist/runtime/headless-repl.js +0 -195
- package/dist/runtime/headless.js +0 -548
- package/dist/runtime/load-hooks-or-exit.js +0 -71
- package/dist/runtime/plan-decompose.js +0 -531
- package/dist/runtime/sigint-guard.js +0 -272
- package/dist/runtime/stream-renderer.js +0 -195
- package/dist/runtime/update-check.js +0 -294
- package/dist/runtime/version.js +0 -65
- package/dist/runtime/worktree-bootstrap.js +0 -579
- package/dist/skills/bundled/batch.js +0 -617
- package/dist/skills/bundled/index.js +0 -45
- package/dist/skills/bundled/loop.js +0 -358
- package/dist/skills/bundled/remember.js +0 -383
- package/dist/skills/bundled/simplify.js +0 -289
- package/dist/skills/bundled/skillify.js +0 -373
- package/dist/skills/bundled/stuck.js +0 -558
- package/dist/skills/bundled/verify.js +0 -439
- package/dist/testing/vcr.js +0 -486
- package/dist/tools/agent-tool.js +0 -229
- package/dist/tools/apply-patch.js +0 -556
- package/dist/tools/ask-user-question.js +0 -337
- package/dist/tools/ask-user.js +0 -115
- package/dist/tools/bash.js +0 -1238
- package/dist/tools/brief.js +0 -224
- package/dist/tools/cron.js +0 -433
- package/dist/tools/enter-worktree.js +0 -250
- package/dist/tools/exit-worktree.js +0 -147
- package/dist/tools/file-tools.js +0 -553
- package/dist/tools/http-request.js +0 -336
- package/dist/tools/lsp-tools.js +0 -565
- package/dist/tools/mcp-tool.js +0 -260
- package/dist/tools/multi-edit.js +0 -361
- package/dist/tools/powershell.js +0 -268
- package/dist/tools/registry.js +0 -166
- package/dist/tools/server-tools.js +0 -892
- package/dist/tools/skill-tool.js +0 -96
- package/dist/tools/sleep.js +0 -99
- package/dist/tools/synthetic-output.js +0 -133
- package/dist/tools/tasks.js +0 -208
- package/dist/tools/todo-write.js +0 -184
- package/dist/tools/verify-plan-execution.js +0 -295
- package/dist/tools/web-fetch-injection-scanner.js +0 -207
- package/dist/tools/web-fetch.js +0 -720
- package/dist/tools/web-search.js +0 -458
- package/dist/tui/agent-progress-card.js +0 -111
- package/dist/tui/agent-tree-pane.js +0 -9
- package/dist/tui/agent-tree.js +0 -87
- package/dist/tui/ask-cli.js +0 -52
- package/dist/tui/ask-modal.js +0 -211
- package/dist/tui/ask-user-question-chips.js +0 -315
- package/dist/tui/ask-user-question-prompt.js +0 -203
- package/dist/tui/compact-banner.js +0 -81
- package/dist/tui/conversation-pane.js +0 -164
- package/dist/tui/cost-table.js +0 -111
- package/dist/tui/device-flow.js +0 -142
- package/dist/tui/doctor-table.js +0 -46
- package/dist/tui/feedback-prompt.js +0 -156
- package/dist/tui/input-box.js +0 -732
- package/dist/tui/login-picker.js +0 -69
- package/dist/tui/markdown-render.js +0 -266
- package/dist/tui/multi-file-diff-approval.js +0 -375
- package/dist/tui/onboarding-wizard.js +0 -240
- package/dist/tui/permissions-picker.js +0 -86
- package/dist/tui/render.js +0 -160
- package/dist/tui/repl-render.js +0 -770
- package/dist/tui/repl-splash-art.js +0 -64
- package/dist/tui/repl-splash-mascot.js +0 -154
- package/dist/tui/repl-splash.js +0 -117
- package/dist/tui/repl.js +0 -378
- package/dist/tui/slash-palette.js +0 -106
- package/dist/tui/splash-data.js +0 -61
- package/dist/tui/splash.js +0 -31
- package/dist/tui/status-bar.js +0 -209
- package/dist/tui/status-table.js +0 -7
- package/dist/tui/stickers-art.js +0 -136
- package/dist/tui/style-table.js +0 -28
- package/dist/tui/theme-table.js +0 -29
- package/dist/tui/thinking-spinner.js +0 -123
- package/dist/tui/tool-stream-pane.js +0 -140
- package/dist/tui/update-banner.js +0 -33
- package/dist/tui/vim-input.js +0 -267
- package/dist/tui/welcome-banner.js +0 -107
- package/dist/tui/welcome-data.js +0 -293
- package/dist/tui/workspace-context.js +0 -105
- package/docs/examples/codegraph.mcp.json +0 -10
- package/test/scenarios/codegen-create-file.scenario.txt +0 -13
- package/test/scenarios/compact-force.scenario.txt +0 -12
- package/test/scenarios/identity.scenario.txt +0 -11
- package/test/scenarios/persona-handoff.scenario.txt +0 -12
- package/test/scenarios/walkback.scenario.txt +0 -12
package/dist/core/credentials.js
DELETED
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from 'node:fs';
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
|
-
import { resolve } from 'node:path';
|
|
4
|
-
import { z } from 'zod';
|
|
5
|
-
/**
|
|
6
|
-
* Local credentials store for the Pugi CLI.
|
|
7
|
-
*
|
|
8
|
-
* Stored at `~/.pugi/credentials.json` (mode 0o600). Mirrors the convention
|
|
9
|
-
* peer CLI uses (`~/.codex/auth.json`) and matches gh CLI's per-host
|
|
10
|
-
* token model. The store is intentionally file-based, not OS keychain —
|
|
11
|
-
* adding the native `keytar` dep would force per-platform native builds
|
|
12
|
-
* across npm distribution and complicate the install path. The 0600
|
|
13
|
-
* file mode plus a strictly typed Zod schema is the minimum-viable
|
|
14
|
-
* substitute for the keychain path.
|
|
15
|
-
*
|
|
16
|
-
* Multi-host: each host (apiUrl) has its own record. `pugi login` adds
|
|
17
|
-
* or replaces the record for the active host; `pugi logout` removes it.
|
|
18
|
-
* `loadActiveCredential` returns the record for the active host (the one
|
|
19
|
-
* matching `PUGI_API_URL` or `apiUrl` from `~/.pugi/config.json`).
|
|
20
|
-
*
|
|
21
|
-
* Future device-flow tokens land in the same `tokens` array with a
|
|
22
|
-
* `kind: 'oauth-device'` discriminator and a refresh-on-use rotation.
|
|
23
|
-
*/
|
|
24
|
-
const CREDENTIALS_SCHEMA_VERSION = 1;
|
|
25
|
-
/**
|
|
26
|
-
* How the credential was obtained. Surfaced by `pugi whoami` so the user
|
|
27
|
-
* can confirm at a glance whether a stored record came from an
|
|
28
|
-
* interactive device flow, a paste-in PAT, or an env-var prime in CI.
|
|
29
|
-
*
|
|
30
|
-
* Older credential files written before this discriminator was added do
|
|
31
|
-
* not carry `source` — the field is optional and `pugi whoami` falls
|
|
32
|
-
* back to `unknown` so we never crash on a legacy file.
|
|
33
|
-
*/
|
|
34
|
-
export const pugiTokenSourceSchema = z.enum(['token', 'device-flow', 'env']);
|
|
35
|
-
export const pugiTokenRecordSchema = z.object({
|
|
36
|
-
apiUrl: z.string().url(),
|
|
37
|
-
apiKey: z.string().min(1),
|
|
38
|
-
label: z.string().min(1).optional(),
|
|
39
|
-
createdAt: z.string().datetime(),
|
|
40
|
-
/**
|
|
41
|
-
* When the credential was last refreshed in the store. Today the
|
|
42
|
-
* field is set on `storeApiKey` (create / replace) and on
|
|
43
|
-
* `switchActiveAccount`. Read paths (`pugi whoami`, every API call)
|
|
44
|
-
* intentionally do NOT touch the file to keep disk IO off the hot
|
|
45
|
-
* path — a recency value that lags is acceptable, a 0o600 write per
|
|
46
|
-
* `pugi <anything>` is not.
|
|
47
|
-
*/
|
|
48
|
-
lastUsedAt: z.string().datetime().optional(),
|
|
49
|
-
/**
|
|
50
|
-
* Provenance discriminator — see `pugiTokenSourceSchema`. Optional so
|
|
51
|
-
* legacy records (pre-0048) still parse.
|
|
52
|
-
*/
|
|
53
|
-
source: pugiTokenSourceSchema.optional(),
|
|
54
|
-
});
|
|
55
|
-
export const pugiCredentialsFileSchema = z.object({
|
|
56
|
-
schema: z.literal(CREDENTIALS_SCHEMA_VERSION),
|
|
57
|
-
tokens: z.array(pugiTokenRecordSchema).default([]),
|
|
58
|
-
/**
|
|
59
|
-
* URL of the host the user most recently logged into. `pugi whoami`
|
|
60
|
-
* and `resolveActiveCredential` read this when `PUGI_API_URL` is unset
|
|
61
|
-
* so a self-hosted user who runs `pugi login --api-url https://anvil.acme.corp`
|
|
62
|
-
* doesn't have to also export PUGI_API_URL for follow-up commands.
|
|
63
|
-
* Env still wins when set (CI fast path).
|
|
64
|
-
*/
|
|
65
|
-
activeApiUrl: z.string().url().optional(),
|
|
66
|
-
});
|
|
67
|
-
export const DEFAULT_API_URL = 'https://api.pugi.io';
|
|
68
|
-
export function credentialsPaths(home = homedir()) {
|
|
69
|
-
const pugiDir = resolve(home, '.pugi');
|
|
70
|
-
return {
|
|
71
|
-
homeDir: home,
|
|
72
|
-
pugiDir,
|
|
73
|
-
filePath: resolve(pugiDir, 'credentials.json'),
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
export function readCredentialsFile(home = homedir()) {
|
|
77
|
-
const { filePath } = credentialsPaths(home);
|
|
78
|
-
if (!existsSync(filePath)) {
|
|
79
|
-
return { schema: CREDENTIALS_SCHEMA_VERSION, tokens: [] };
|
|
80
|
-
}
|
|
81
|
-
const text = readFileSync(filePath, 'utf8');
|
|
82
|
-
let raw;
|
|
83
|
-
try {
|
|
84
|
-
raw = JSON.parse(text);
|
|
85
|
-
}
|
|
86
|
-
catch {
|
|
87
|
-
// Corrupt JSON: a partial/empty write or hand-edit. Rename the bad
|
|
88
|
-
// file aside so the next write does not silently produce an empty
|
|
89
|
-
// token list (silent data loss). Returning empty here is acceptable
|
|
90
|
-
// because the corrupt copy is preserved for forensic recovery.
|
|
91
|
-
quarantineCorruptCredentials(filePath, 'json-parse');
|
|
92
|
-
return { schema: CREDENTIALS_SCHEMA_VERSION, tokens: [] };
|
|
93
|
-
}
|
|
94
|
-
const parsed = pugiCredentialsFileSchema.safeParse(raw);
|
|
95
|
-
if (parsed.success)
|
|
96
|
-
return parsed.data;
|
|
97
|
-
quarantineCorruptCredentials(filePath, 'schema-mismatch');
|
|
98
|
-
return { schema: CREDENTIALS_SCHEMA_VERSION, tokens: [] };
|
|
99
|
-
}
|
|
100
|
-
function quarantineCorruptCredentials(filePath, reason) {
|
|
101
|
-
try {
|
|
102
|
-
const backup = `${filePath}.corrupt-${reason}-${Date.now()}`;
|
|
103
|
-
renameSync(filePath, backup);
|
|
104
|
-
if (process.stderr?.write) {
|
|
105
|
-
process.stderr.write(`pugi: warning — corrupt credentials file preserved at ${backup}; starting from empty token list\n`);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
// Best-effort. If we cannot rename (e.g. read-only fs), the next
|
|
110
|
-
// write will overwrite the corrupt file anyway.
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
export function writeCredentialsFile(file, home = homedir()) {
|
|
114
|
-
const paths = credentialsPaths(home);
|
|
115
|
-
if (!existsSync(paths.pugiDir)) {
|
|
116
|
-
mkdirSync(paths.pugiDir, { recursive: true, mode: 0o700 });
|
|
117
|
-
}
|
|
118
|
-
// Defensively tighten existing dir permissions — `mkdirSync(mode)` only
|
|
119
|
-
// applies on creation, not on pre-existing dirs that another tool may
|
|
120
|
-
// have created with 0o755.
|
|
121
|
-
try {
|
|
122
|
-
chmodSync(paths.pugiDir, 0o700);
|
|
123
|
-
}
|
|
124
|
-
catch {
|
|
125
|
-
// Best-effort; FAT/CI filesystems may not support chmod.
|
|
126
|
-
}
|
|
127
|
-
// Validate before persisting so a corrupt object never lands on disk.
|
|
128
|
-
const validated = pugiCredentialsFileSchema.parse(file);
|
|
129
|
-
// Atomic write: tmp + rename. `rename(2)` is atomic on POSIX same-fs,
|
|
130
|
-
// so a concurrent reader either sees the old file or the new one — never
|
|
131
|
-
// a truncated mid-write state that the corrupt-recovery path would
|
|
132
|
-
// quarantine as data loss. Two concurrent writers still race (no advisory
|
|
133
|
-
// lock yet), but neither corrupts the target file.
|
|
134
|
-
const tmp = `${paths.filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
135
|
-
writeFileSync(tmp, `${JSON.stringify(validated, null, 2)}\n`, {
|
|
136
|
-
encoding: 'utf8',
|
|
137
|
-
mode: 0o600,
|
|
138
|
-
});
|
|
139
|
-
try {
|
|
140
|
-
chmodSync(tmp, 0o600);
|
|
141
|
-
}
|
|
142
|
-
catch {
|
|
143
|
-
// Best-effort on filesystems that don't support chmod (FAT, some CIs).
|
|
144
|
-
}
|
|
145
|
-
renameSync(tmp, paths.filePath);
|
|
146
|
-
try {
|
|
147
|
-
chmodSync(paths.filePath, 0o600);
|
|
148
|
-
}
|
|
149
|
-
catch {
|
|
150
|
-
// Best-effort — rename preserves the tmp file's mode on POSIX, this
|
|
151
|
-
// is belt-and-braces.
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Add or replace the credential record for the given apiUrl. Returns the
|
|
156
|
-
* stored record (without the `apiKey` echoed back at the caller — the
|
|
157
|
-
* caller already has it). Idempotent.
|
|
158
|
-
*/
|
|
159
|
-
export function storeApiKey(input) {
|
|
160
|
-
const home = input.home ?? homedir();
|
|
161
|
-
const file = readCredentialsFile(home);
|
|
162
|
-
const apiUrl = normalizeApiUrl(input.apiUrl);
|
|
163
|
-
const now = new Date().toISOString();
|
|
164
|
-
const record = pugiTokenRecordSchema.parse({
|
|
165
|
-
apiUrl,
|
|
166
|
-
apiKey: input.apiKey,
|
|
167
|
-
label: input.label,
|
|
168
|
-
createdAt: now,
|
|
169
|
-
lastUsedAt: now,
|
|
170
|
-
source: input.source,
|
|
171
|
-
});
|
|
172
|
-
const others = file.tokens.filter((token) => normalizeApiUrl(token.apiUrl) !== apiUrl);
|
|
173
|
-
writeCredentialsFile({
|
|
174
|
-
schema: CREDENTIALS_SCHEMA_VERSION,
|
|
175
|
-
tokens: [...others, record],
|
|
176
|
-
// Promote the just-logged-in host to active so subsequent `whoami`
|
|
177
|
-
// and `review --remote` find it without the user re-exporting
|
|
178
|
-
// PUGI_API_URL. Env still wins via resolveActiveCredential.
|
|
179
|
-
activeApiUrl: apiUrl,
|
|
180
|
-
}, home);
|
|
181
|
-
return record;
|
|
182
|
-
}
|
|
183
|
-
export function clearApiKey(apiUrl, home = homedir()) {
|
|
184
|
-
const file = readCredentialsFile(home);
|
|
185
|
-
const target = normalizeApiUrl(apiUrl);
|
|
186
|
-
const before = file.tokens.length;
|
|
187
|
-
const tokens = file.tokens.filter((token) => normalizeApiUrl(token.apiUrl) !== target);
|
|
188
|
-
if (tokens.length === before)
|
|
189
|
-
return false;
|
|
190
|
-
// If the cleared host was the active one, demote `activeApiUrl` to the
|
|
191
|
-
// most recently-stored remaining record (or undefined when the store
|
|
192
|
-
// is now empty) so subsequent `whoami` doesn't point at a vanished host.
|
|
193
|
-
const nextActive = file.activeApiUrl && normalizeApiUrl(file.activeApiUrl) === target
|
|
194
|
-
? tokens.at(-1)?.apiUrl
|
|
195
|
-
: file.activeApiUrl;
|
|
196
|
-
writeCredentialsFile({
|
|
197
|
-
schema: CREDENTIALS_SCHEMA_VERSION,
|
|
198
|
-
tokens,
|
|
199
|
-
...(nextActive ? { activeApiUrl: nextActive } : {}),
|
|
200
|
-
}, home);
|
|
201
|
-
return true;
|
|
202
|
-
}
|
|
203
|
-
export function loadApiKey(apiUrl, home = homedir()) {
|
|
204
|
-
const file = readCredentialsFile(home);
|
|
205
|
-
const target = normalizeApiUrl(apiUrl);
|
|
206
|
-
return file.tokens.find((token) => normalizeApiUrl(token.apiUrl) === target) ?? null;
|
|
207
|
-
}
|
|
208
|
-
export function resolveActiveCredential(env = process.env, home = homedir()) {
|
|
209
|
-
// Resolve the active apiUrl with this precedence:
|
|
210
|
-
// 1. PUGI_API_URL env (lets CI / self-hosted users force a specific endpoint)
|
|
211
|
-
// 2. credentials.json `activeApiUrl` (set by `pugi login` to the host the
|
|
212
|
-
// user most recently authenticated against — covers self-hosted Anvil
|
|
213
|
-
// without re-exporting env between commands)
|
|
214
|
-
// 3. DEFAULT_API_URL (`https://api.pugi.io`)
|
|
215
|
-
const file = readCredentialsFile(home);
|
|
216
|
-
const apiUrl = normalizeApiUrl(env.PUGI_API_URL ?? file.activeApiUrl ?? DEFAULT_API_URL);
|
|
217
|
-
if (env.PUGI_API_KEY) {
|
|
218
|
-
return { apiUrl, apiKey: env.PUGI_API_KEY, source: 'env' };
|
|
219
|
-
}
|
|
220
|
-
const record = file.tokens.find((token) => normalizeApiUrl(token.apiUrl) === apiUrl);
|
|
221
|
-
if (record) {
|
|
222
|
-
return {
|
|
223
|
-
apiUrl: record.apiUrl,
|
|
224
|
-
apiKey: record.apiKey,
|
|
225
|
-
source: 'file',
|
|
226
|
-
fileSource: record.source ?? null,
|
|
227
|
-
...(record.label ? { label: record.label } : {}),
|
|
228
|
-
...(record.createdAt ? { createdAt: record.createdAt } : {}),
|
|
229
|
-
...(record.lastUsedAt ? { lastUsedAt: record.lastUsedAt } : {}),
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
return null;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Re-point the credentials store at a different already-stored host or
|
|
236
|
-
* label. Used by `pugi accounts switch <label>` so subsequent commands
|
|
237
|
-
* authenticate against the chosen account without forcing the user to
|
|
238
|
-
* re-export PUGI_API_URL between commands.
|
|
239
|
-
*
|
|
240
|
-
* Match precedence:
|
|
241
|
-
* 1. exact `label` match (case-insensitive, label is user-chosen so
|
|
242
|
-
* we forgive casing — same convention as `gh auth switch`)
|
|
243
|
-
* 2. exact `apiUrl` match (canonicalised) — lets `pugi accounts
|
|
244
|
-
* switch https://api.acme.com` work without a label.
|
|
245
|
-
*
|
|
246
|
-
* Returns the now-active record, or null when nothing matched.
|
|
247
|
-
*/
|
|
248
|
-
export function switchActiveAccount(selector, home = homedir()) {
|
|
249
|
-
const file = readCredentialsFile(home);
|
|
250
|
-
const normalisedSelector = selector.trim();
|
|
251
|
-
if (!normalisedSelector)
|
|
252
|
-
return null;
|
|
253
|
-
const lower = normalisedSelector.toLowerCase();
|
|
254
|
-
const targetApiUrl = (() => {
|
|
255
|
-
try {
|
|
256
|
-
return normalizeApiUrl(normalisedSelector);
|
|
257
|
-
}
|
|
258
|
-
catch {
|
|
259
|
-
return null;
|
|
260
|
-
}
|
|
261
|
-
})();
|
|
262
|
-
const match = file.tokens.find((token) => {
|
|
263
|
-
if (token.label && token.label.toLowerCase() === lower)
|
|
264
|
-
return true;
|
|
265
|
-
if (targetApiUrl && normalizeApiUrl(token.apiUrl) === targetApiUrl)
|
|
266
|
-
return true;
|
|
267
|
-
return false;
|
|
268
|
-
});
|
|
269
|
-
if (!match)
|
|
270
|
-
return null;
|
|
271
|
-
const apiUrl = normalizeApiUrl(match.apiUrl);
|
|
272
|
-
const now = new Date().toISOString();
|
|
273
|
-
const updated = pugiTokenRecordSchema.parse({
|
|
274
|
-
...match,
|
|
275
|
-
apiUrl,
|
|
276
|
-
lastUsedAt: now,
|
|
277
|
-
});
|
|
278
|
-
const others = file.tokens.filter((token) => normalizeApiUrl(token.apiUrl) !== apiUrl);
|
|
279
|
-
writeCredentialsFile({
|
|
280
|
-
schema: CREDENTIALS_SCHEMA_VERSION,
|
|
281
|
-
tokens: [...others, updated],
|
|
282
|
-
activeApiUrl: apiUrl,
|
|
283
|
-
}, home);
|
|
284
|
-
return updated;
|
|
285
|
-
}
|
|
286
|
-
/**
|
|
287
|
-
* List every stored credential in stable display order — most recently
|
|
288
|
-
* used first, falling back to creation order. Returned records carry
|
|
289
|
-
* the raw `apiKey`; callers must mask before printing.
|
|
290
|
-
*/
|
|
291
|
-
export function listStoredCredentials(home = homedir()) {
|
|
292
|
-
const file = readCredentialsFile(home);
|
|
293
|
-
const activeUrl = file.activeApiUrl ? normalizeApiUrl(file.activeApiUrl) : null;
|
|
294
|
-
return file.tokens
|
|
295
|
-
.map((token) => ({
|
|
296
|
-
...token,
|
|
297
|
-
isActive: activeUrl !== null && normalizeApiUrl(token.apiUrl) === activeUrl,
|
|
298
|
-
}))
|
|
299
|
-
.sort((a, b) => {
|
|
300
|
-
// Active record always pinned to the top — it's the one the user
|
|
301
|
-
// is asking about whenever they run `pugi accounts list`.
|
|
302
|
-
if (a.isActive && !b.isActive)
|
|
303
|
-
return -1;
|
|
304
|
-
if (b.isActive && !a.isActive)
|
|
305
|
-
return 1;
|
|
306
|
-
const aWhen = a.lastUsedAt ?? a.createdAt;
|
|
307
|
-
const bWhen = b.lastUsedAt ?? b.createdAt;
|
|
308
|
-
return bWhen.localeCompare(aWhen);
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* Canonicalize an apiUrl so two equivalent inputs always resolve to the
|
|
313
|
-
* same record:
|
|
314
|
-
* - lowercase scheme + host (URL spec: scheme/host are case-insensitive)
|
|
315
|
-
* - strip trailing slashes
|
|
316
|
-
* - preserve path/query/fragment case (those ARE case-sensitive)
|
|
317
|
-
*
|
|
318
|
-
* Falls back to the trimmed input when the URL is not parseable, so a
|
|
319
|
-
* caller that manages to pass a non-URL string still sees a stable key
|
|
320
|
-
* instead of throwing.
|
|
321
|
-
*/
|
|
322
|
-
export function normalizeApiUrl(input) {
|
|
323
|
-
const trimmed = input.trim();
|
|
324
|
-
try {
|
|
325
|
-
const url = new URL(trimmed);
|
|
326
|
-
const path = url.pathname + url.search + url.hash;
|
|
327
|
-
const stripped = path.replace(/\/+$/, '');
|
|
328
|
-
return `${url.protocol.toLowerCase()}//${url.host.toLowerCase()}${stripped}`;
|
|
329
|
-
}
|
|
330
|
-
catch {
|
|
331
|
-
return trimmed.replace(/\/+$/, '');
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Best-effort masked token for log lines and `pugi whoami` output.
|
|
336
|
-
* Never returns the raw secret. Keeps the first 4 + last 4 characters so
|
|
337
|
-
* the user can correlate against an issued key without exposing it.
|
|
338
|
-
*/
|
|
339
|
-
export function maskApiKey(apiKey) {
|
|
340
|
-
if (apiKey.length <= 12)
|
|
341
|
-
return `${'*'.repeat(apiKey.length)}`;
|
|
342
|
-
return `${apiKey.slice(0, 4)}…${apiKey.slice(-4)}`;
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* Delete the entire credentials file. Used by `pugi logout --all` and
|
|
346
|
-
* by tests that want a clean slate.
|
|
347
|
-
*/
|
|
348
|
-
export function purgeAllCredentials(home = homedir()) {
|
|
349
|
-
const paths = credentialsPaths(home);
|
|
350
|
-
if (!existsSync(paths.filePath))
|
|
351
|
-
return false;
|
|
352
|
-
rmSync(paths.filePath);
|
|
353
|
-
return true;
|
|
354
|
-
}
|
|
355
|
-
//# sourceMappingURL=credentials.js.map
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cron scheduler primitive .
|
|
3
|
-
*
|
|
4
|
-
* Wraps `node-cron` (4.2.1, MIT, ~4M weekly downloads) — the de-facto
|
|
5
|
-
* Node cron scheduler. We do NOT parse cron expressions ourselves;
|
|
6
|
-
* node-cron handles validation, timezone math, и DST edge cases.
|
|
7
|
-
*
|
|
8
|
-
* What this module adds:
|
|
9
|
-
* - Named job registry (schedule/cancel/list by name)
|
|
10
|
-
* - Concurrency guard — a still-running job is skipped, not stacked,
|
|
11
|
-
* when the next tick fires (prevents overlap when an action runs
|
|
12
|
-
* longer than the cron period)
|
|
13
|
-
* - Stats per job: scheduled, lastRunAt, lastDurationMs, failures
|
|
14
|
-
*
|
|
15
|
-
* Pure-ish: state lives в the CronScheduler instance, no globals.
|
|
16
|
-
* Tool surface (ScheduleCronTool / CronList / CronDelete) wires this
|
|
17
|
-
* primitive into the engine в a separate PR.
|
|
18
|
-
*/
|
|
19
|
-
import cron from 'node-cron';
|
|
20
|
-
export class CronScheduler {
|
|
21
|
-
jobs = new Map();
|
|
22
|
-
/**
|
|
23
|
-
* Register a cron job. Replaces any prior job at the same name —
|
|
24
|
-
* the previous one is stopped и destroyed first.
|
|
25
|
-
*
|
|
26
|
-
* Throws `RangeError` when `expression` is invalid per node-cron's
|
|
27
|
-
* parser. The error originates from node-cron and bubbles unchanged.
|
|
28
|
-
*/
|
|
29
|
-
schedule(name, expression, action, options = {}) {
|
|
30
|
-
if (!name)
|
|
31
|
-
throw new TypeError('cron job name must be non-empty');
|
|
32
|
-
if (!cron.validate(expression)) {
|
|
33
|
-
throw new RangeError(`invalid cron expression: ${expression}`);
|
|
34
|
-
}
|
|
35
|
-
const existing = this.jobs.get(name);
|
|
36
|
-
if (existing) {
|
|
37
|
-
existing.task.stop();
|
|
38
|
-
}
|
|
39
|
-
const internal = {
|
|
40
|
-
task: undefined,
|
|
41
|
-
expression,
|
|
42
|
-
scheduledAt: Date.now(),
|
|
43
|
-
lastRunAt: null,
|
|
44
|
-
lastDurationMs: null,
|
|
45
|
-
runs: 0,
|
|
46
|
-
failures: 0,
|
|
47
|
-
running: false,
|
|
48
|
-
};
|
|
49
|
-
const wrapped = async () => {
|
|
50
|
-
// Concurrency guard: if previous invocation still running, skip.
|
|
51
|
-
// Stacking would tie up the event loop с long-running actions.
|
|
52
|
-
if (internal.running)
|
|
53
|
-
return;
|
|
54
|
-
internal.running = true;
|
|
55
|
-
const start = Date.now();
|
|
56
|
-
try {
|
|
57
|
-
await action();
|
|
58
|
-
internal.runs += 1;
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
internal.failures += 1;
|
|
62
|
-
}
|
|
63
|
-
finally {
|
|
64
|
-
internal.lastRunAt = start;
|
|
65
|
-
internal.lastDurationMs = Date.now() - start;
|
|
66
|
-
internal.running = false;
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
const scheduleOptions = {};
|
|
70
|
-
if (options.timezone !== undefined) {
|
|
71
|
-
scheduleOptions.timezone = options.timezone;
|
|
72
|
-
}
|
|
73
|
-
internal.task = cron.schedule(expression, wrapped, scheduleOptions);
|
|
74
|
-
this.jobs.set(name, internal);
|
|
75
|
-
if (options.runOnRegister) {
|
|
76
|
-
// Don't await — register is sync from the caller's perspective
|
|
77
|
-
void wrapped();
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
/** Cancel + drop a job by name. Returns true когда removed, false absent. */
|
|
81
|
-
cancel(name) {
|
|
82
|
-
const job = this.jobs.get(name);
|
|
83
|
-
if (!job)
|
|
84
|
-
return false;
|
|
85
|
-
job.task.stop();
|
|
86
|
-
this.jobs.delete(name);
|
|
87
|
-
return true;
|
|
88
|
-
}
|
|
89
|
-
/** Stop + drop ALL jobs. Safe to call on an empty scheduler. */
|
|
90
|
-
cancelAll() {
|
|
91
|
-
for (const job of this.jobs.values()) {
|
|
92
|
-
job.task.stop();
|
|
93
|
-
}
|
|
94
|
-
this.jobs.clear();
|
|
95
|
-
}
|
|
96
|
-
/** Snapshot of all registered jobs. Sorted by name for stable output. */
|
|
97
|
-
list() {
|
|
98
|
-
const out = [];
|
|
99
|
-
for (const [name, job] of this.jobs) {
|
|
100
|
-
out.push({
|
|
101
|
-
name,
|
|
102
|
-
expression: job.expression,
|
|
103
|
-
scheduledAt: job.scheduledAt,
|
|
104
|
-
lastRunAt: job.lastRunAt,
|
|
105
|
-
lastDurationMs: job.lastDurationMs,
|
|
106
|
-
runs: job.runs,
|
|
107
|
-
failures: job.failures,
|
|
108
|
-
running: job.running,
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
return out.sort((a, b) => a.name.localeCompare(b.name));
|
|
112
|
-
}
|
|
113
|
-
/** Lookup a single job's stats. Returns null when absent. */
|
|
114
|
-
stats(name) {
|
|
115
|
-
const job = this.jobs.get(name);
|
|
116
|
-
if (!job)
|
|
117
|
-
return null;
|
|
118
|
-
return {
|
|
119
|
-
name,
|
|
120
|
-
expression: job.expression,
|
|
121
|
-
scheduledAt: job.scheduledAt,
|
|
122
|
-
lastRunAt: job.lastRunAt,
|
|
123
|
-
lastDurationMs: job.lastDurationMs,
|
|
124
|
-
runs: job.runs,
|
|
125
|
-
failures: job.failures,
|
|
126
|
-
running: job.running,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Standalone helper для callers that only want one-off validation
|
|
132
|
-
* without creating a scheduler. Mirrors node-cron's `validate()` so
|
|
133
|
-
* callers don't need to import node-cron directly.
|
|
134
|
-
*/
|
|
135
|
-
export function isValidCronExpression(expression) {
|
|
136
|
-
return cron.validate(expression);
|
|
137
|
-
}
|
|
138
|
-
//# sourceMappingURL=scheduler.js.map
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Public re-exports for the denial-tracking surface. Engine adapter
|
|
3
|
-
* code imports from here so we can move internals around (e.g. split
|
|
4
|
-
* the diagnostics probe into a sibling file) without churning every
|
|
5
|
-
* call site.
|
|
6
|
-
*/
|
|
7
|
-
export { DenialTrackingState, buildDenialContext, canonicalArgHash, DENIAL_TRACKING_MAX_ENTRIES, DENIAL_REMINDER_THRESHOLD, DENIAL_ARGS_SUMMARY_BYTES, } from './state.js';
|
|
8
|
-
//# sourceMappingURL=index.js.map
|