@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
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Maximum symbols carried per file. The formatter further truncates к
|
|
3
|
-
* the 2 KB injection budget, but capping per-file here keeps a single
|
|
4
|
-
* giant `index.ts` from monopolising the map.
|
|
5
|
-
*/
|
|
6
|
-
export const MAX_SYMBOLS_PER_FILE = 50;
|
|
7
|
-
/**
|
|
8
|
-
* Extract symbols + summary from a single file. `kind` is dispatched
|
|
9
|
-
* on the lowercased extension. Files with an unrecognised extension
|
|
10
|
-
* return an empty symbol list with `summary: null` — the scanner
|
|
11
|
-
* already filtered by `SUPPORTED_EXTENSIONS` so this branch is mostly
|
|
12
|
-
* defensive (test fixtures sometimes pass `.txt`).
|
|
13
|
-
*/
|
|
14
|
-
export function extractFromFile(file, source) {
|
|
15
|
-
switch (file.ext) {
|
|
16
|
-
case '.ts':
|
|
17
|
-
case '.tsx':
|
|
18
|
-
case '.js':
|
|
19
|
-
case '.jsx':
|
|
20
|
-
case '.mjs':
|
|
21
|
-
case '.cjs':
|
|
22
|
-
return extractFromTsLike(file, source);
|
|
23
|
-
case '.md':
|
|
24
|
-
case '.mdx':
|
|
25
|
-
return extractFromMarkdown(file, source);
|
|
26
|
-
default:
|
|
27
|
-
return {
|
|
28
|
-
relPath: file.relPath,
|
|
29
|
-
ext: file.ext,
|
|
30
|
-
summary: null,
|
|
31
|
-
symbols: [],
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
/* ------------------------- TS / JS extraction ------------------------- */
|
|
36
|
-
/**
|
|
37
|
-
* Identifier pattern. We use the ASCII subset (letters/digits/`$`/`_`)
|
|
38
|
-
* rather than the full unicode ID start/continue range because the
|
|
39
|
-
* unicode tables would inflate the bundle by ~50 KB for zero benefit
|
|
40
|
-
* — Pugi's customers are typing English identifiers. Unicode names
|
|
41
|
-
* in source still PARSE (they just do not surface в the repo-map);
|
|
42
|
-
* the formatter degrades gracefully.
|
|
43
|
-
*/
|
|
44
|
-
const IDENT = '[A-Za-z_$][A-Za-z0-9_$]*';
|
|
45
|
-
/**
|
|
46
|
-
* Top-level declaration shapes:
|
|
47
|
-
*
|
|
48
|
-
* export? (default)? class Foo { ... }
|
|
49
|
-
* export? (default)? function foo() { ... }
|
|
50
|
-
* export? (default)? async function foo() { ... }
|
|
51
|
-
* export? (const|let|var) foo = (args) => { ... }
|
|
52
|
-
* export? (const|let|var) foo = async (args) => { ... }
|
|
53
|
-
* export? (const|let|var) foo = function (args) { ... }
|
|
54
|
-
* export? interface Foo { ... }
|
|
55
|
-
* export? type Foo = ...
|
|
56
|
-
* export? enum Foo { ... }
|
|
57
|
-
*
|
|
58
|
-
* The patterns anchor on start-of-line (`^` with the `m` flag) so they
|
|
59
|
-
* never match nested declarations inside a class body or a closure.
|
|
60
|
-
* That intentionally loses precision for module-level IIFEs (e.g.
|
|
61
|
-
* `;(function init() {})()`), but the L28 budget already drops nested
|
|
62
|
-
* symbols, so the loss is invisible to the operator.
|
|
63
|
-
*/
|
|
64
|
-
const TS_CLASS_RE = new RegExp(`^(export\\s+(?:default\\s+)?(?:abstract\\s+)?)?class\\s+(${IDENT})`, 'gm');
|
|
65
|
-
const TS_FUNCTION_RE = new RegExp(`^(export\\s+(?:default\\s+)?)?(?:async\\s+)?function\\s*\\*?\\s+(${IDENT})`, 'gm');
|
|
66
|
-
/**
|
|
67
|
-
* Arrow / function-expression `const|let|var foo = (...) => ...` shape.
|
|
68
|
-
* The optional type annotation between the identifier and the `=` is
|
|
69
|
-
* non-trivial because TS allows `(...) => ...` IN the annotation
|
|
70
|
-
* itself ("export const x: () => number = () => 1"). We allow `=>`
|
|
71
|
-
* as a unit inside the annotation by matching the char class
|
|
72
|
-
* `(?:=>|[^=\\n])*?` which consumes either an arrow token OR a
|
|
73
|
-
* non-`=` char; the trailing assignment `=` is then the first
|
|
74
|
-
* standalone `=` (`(?!>)`) on the line. The match tail (`=>` arrow,
|
|
75
|
-
* parenthesised arg list, generic, or `function` keyword) anchors
|
|
76
|
-
* the RHS so plain `const x = 1` does not surface as a function.
|
|
77
|
-
*/
|
|
78
|
-
const TS_ARROW_RE = new RegExp(`^(export\\s+)?(?:const|let|var)\\s+(${IDENT})\\b(?:=>|[^=\\n])*?=(?!>)\\s*(?:async\\s*)?(?:\\(|<|function\\b)`, 'gm');
|
|
79
|
-
const TS_INTERFACE_RE = new RegExp(`^(export\\s+)?interface\\s+(${IDENT})`, 'gm');
|
|
80
|
-
const TS_TYPE_RE = new RegExp(`^(export\\s+)?type\\s+(${IDENT})\\s*[=<]`, 'gm');
|
|
81
|
-
const TS_ENUM_RE = new RegExp(`^(export\\s+)?(?:const\\s+)?enum\\s+(${IDENT})`, 'gm');
|
|
82
|
-
/**
|
|
83
|
-
* Lead JSDoc / TSDoc block: `/** ... */` at the start of the file or
|
|
84
|
-
* preceded only by whitespace + import statements. We pick the first
|
|
85
|
-
* non-empty narrative line — the convention across Pugi's own codebase
|
|
86
|
-
* is that the headline sentence sits at the top of the block.
|
|
87
|
-
*/
|
|
88
|
-
const LEAD_DOC_RE = /\/\*\*([\s\S]*?)\*\//;
|
|
89
|
-
function extractFromTsLike(file, source) {
|
|
90
|
-
const symbols = [];
|
|
91
|
-
// We compute line numbers lazily by counting newlines в `source`
|
|
92
|
-
// up к each match's `.index`. Building a single prefix-newline
|
|
93
|
-
// array once is cheaper than calling `source.slice(0, idx).split`
|
|
94
|
-
// per match.
|
|
95
|
-
const lineStarts = computeLineStarts(source);
|
|
96
|
-
const lineFor = (offset) => binarySearchLine(lineStarts, offset);
|
|
97
|
-
const pushMatches = (regex, kind, exportIndex, nameIndex) => {
|
|
98
|
-
regex.lastIndex = 0;
|
|
99
|
-
let match;
|
|
100
|
-
while ((match = regex.exec(source)) !== null) {
|
|
101
|
-
if (symbols.length >= MAX_SYMBOLS_PER_FILE)
|
|
102
|
-
return;
|
|
103
|
-
const name = match[nameIndex];
|
|
104
|
-
if (!name)
|
|
105
|
-
continue;
|
|
106
|
-
const exported = Boolean(match[exportIndex]);
|
|
107
|
-
symbols.push({
|
|
108
|
-
name,
|
|
109
|
-
kind,
|
|
110
|
-
exported,
|
|
111
|
-
line: lineFor(match.index),
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
pushMatches(TS_CLASS_RE, 'class', 1, 2);
|
|
116
|
-
pushMatches(TS_FUNCTION_RE, 'function', 1, 2);
|
|
117
|
-
pushMatches(TS_ARROW_RE, 'const', 1, 2);
|
|
118
|
-
pushMatches(TS_INTERFACE_RE, 'interface', 1, 2);
|
|
119
|
-
pushMatches(TS_TYPE_RE, 'type', 1, 2);
|
|
120
|
-
pushMatches(TS_ENUM_RE, 'enum', 1, 2);
|
|
121
|
-
// Dedupe by `name + kind` — `export const x = function x() {}` would
|
|
122
|
-
// otherwise show up twice (arrow regex + function regex). Keep the
|
|
123
|
-
// earlier one (lowest line) and the exported flag if either match
|
|
124
|
-
// saw it.
|
|
125
|
-
const dedup = new Map();
|
|
126
|
-
for (const sym of symbols) {
|
|
127
|
-
const key = `${sym.kind}::${sym.name}`;
|
|
128
|
-
const prior = dedup.get(key);
|
|
129
|
-
if (!prior) {
|
|
130
|
-
dedup.set(key, sym);
|
|
131
|
-
}
|
|
132
|
-
else if (sym.line < prior.line) {
|
|
133
|
-
dedup.set(key, { ...sym, exported: prior.exported || sym.exported });
|
|
134
|
-
}
|
|
135
|
-
else if (sym.exported && !prior.exported) {
|
|
136
|
-
dedup.set(key, { ...prior, exported: true });
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
const deduped = Array.from(dedup.values()).sort((a, b) => a.line - b.line);
|
|
140
|
-
return {
|
|
141
|
-
relPath: file.relPath,
|
|
142
|
-
ext: file.ext,
|
|
143
|
-
summary: extractLeadDocSummary(source),
|
|
144
|
-
symbols: deduped.slice(0, MAX_SYMBOLS_PER_FILE),
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Extract the first narrative sentence from a leading JSDoc block.
|
|
149
|
-
* Returns null when no block is present in the first 4 KB of the
|
|
150
|
-
* file (cap protects against huge generated headers).
|
|
151
|
-
*/
|
|
152
|
-
export function extractLeadDocSummary(source) {
|
|
153
|
-
const window = source.slice(0, 4096);
|
|
154
|
-
const match = LEAD_DOC_RE.exec(window);
|
|
155
|
-
if (!match)
|
|
156
|
-
return null;
|
|
157
|
-
const body = match[1] ?? '';
|
|
158
|
-
for (const rawLine of body.split('\n')) {
|
|
159
|
-
const line = rawLine.replace(/^\s*\*\s?/u, '').trim();
|
|
160
|
-
if (line.length === 0)
|
|
161
|
-
continue;
|
|
162
|
-
// Skip the `@param` / `@returns` / `@deprecated` block prefixes —
|
|
163
|
-
// the summary is the prose lead, not the tag soup.
|
|
164
|
-
if (line.startsWith('@'))
|
|
165
|
-
continue;
|
|
166
|
-
// Truncate at 120 chars so a 5-line philosophical preamble does
|
|
167
|
-
// not blow the formatter's column budget.
|
|
168
|
-
return line.length > 120 ? line.slice(0, 117) + '...' : line;
|
|
169
|
-
}
|
|
170
|
-
return null;
|
|
171
|
-
}
|
|
172
|
-
/* -------------------------- Markdown extraction -------------------------- */
|
|
173
|
-
const MD_HEADING_RE = /^(#{1,6})\s+(.+?)\s*#*\s*$/gm;
|
|
174
|
-
function extractFromMarkdown(file, source) {
|
|
175
|
-
const symbols = [];
|
|
176
|
-
const lineStarts = computeLineStarts(source);
|
|
177
|
-
MD_HEADING_RE.lastIndex = 0;
|
|
178
|
-
let match;
|
|
179
|
-
while ((match = MD_HEADING_RE.exec(source)) !== null) {
|
|
180
|
-
if (symbols.length >= MAX_SYMBOLS_PER_FILE)
|
|
181
|
-
break;
|
|
182
|
-
const level = match[1]?.length ?? 0;
|
|
183
|
-
// Only H1 + H2 surface — the L28 budget cannot afford H3+ depth
|
|
184
|
-
// and the operator-readable map is meant к answer "what is в
|
|
185
|
-
// this file" not "what is the full TOC".
|
|
186
|
-
if (level > 2)
|
|
187
|
-
continue;
|
|
188
|
-
const name = (match[2] ?? '').trim();
|
|
189
|
-
if (!name)
|
|
190
|
-
continue;
|
|
191
|
-
symbols.push({
|
|
192
|
-
name,
|
|
193
|
-
kind: 'heading',
|
|
194
|
-
exported: true,
|
|
195
|
-
line: binarySearchLine(lineStarts, match.index),
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
return {
|
|
199
|
-
relPath: file.relPath,
|
|
200
|
-
ext: file.ext,
|
|
201
|
-
summary: extractMarkdownSummary(source),
|
|
202
|
-
symbols,
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* First non-heading paragraph in the markdown file. Truncated к 120
|
|
207
|
-
* chars like the JSDoc summary so the formatter stays single-line.
|
|
208
|
-
*/
|
|
209
|
-
export function extractMarkdownSummary(source) {
|
|
210
|
-
const lines = source.split('\n').slice(0, 200);
|
|
211
|
-
let sawHeading = false;
|
|
212
|
-
for (const raw of lines) {
|
|
213
|
-
const line = raw.trim();
|
|
214
|
-
if (line.length === 0)
|
|
215
|
-
continue;
|
|
216
|
-
if (line.startsWith('#')) {
|
|
217
|
-
sawHeading = true;
|
|
218
|
-
continue;
|
|
219
|
-
}
|
|
220
|
-
// Skip front-matter delimiters and HTML/markdown directives.
|
|
221
|
-
if (line === '---' || line.startsWith('<!--'))
|
|
222
|
-
continue;
|
|
223
|
-
if (!sawHeading) {
|
|
224
|
-
// Pre-heading body — usually front-matter content. Skip it; the
|
|
225
|
-
// first POST-heading paragraph is the operator-facing summary.
|
|
226
|
-
continue;
|
|
227
|
-
}
|
|
228
|
-
return line.length > 120 ? line.slice(0, 117) + '...' : line;
|
|
229
|
-
}
|
|
230
|
-
return null;
|
|
231
|
-
}
|
|
232
|
-
/* ----------------------------- helpers ----------------------------- */
|
|
233
|
-
function computeLineStarts(source) {
|
|
234
|
-
const starts = [0];
|
|
235
|
-
for (let i = 0; i < source.length; i += 1) {
|
|
236
|
-
if (source.charCodeAt(i) === 10 /* \n */)
|
|
237
|
-
starts.push(i + 1);
|
|
238
|
-
}
|
|
239
|
-
return starts;
|
|
240
|
-
}
|
|
241
|
-
function binarySearchLine(starts, offset) {
|
|
242
|
-
// Returns 1-based line number.
|
|
243
|
-
let lo = 0;
|
|
244
|
-
let hi = starts.length - 1;
|
|
245
|
-
while (lo < hi) {
|
|
246
|
-
const mid = (lo + hi + 1) >>> 1;
|
|
247
|
-
if (starts[mid] <= offset)
|
|
248
|
-
lo = mid;
|
|
249
|
-
else
|
|
250
|
-
hi = mid - 1;
|
|
251
|
-
}
|
|
252
|
-
return lo + 1;
|
|
253
|
-
}
|
|
254
|
-
//# sourceMappingURL=extractor.js.map
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Default byte cap for the engine system-prompt injection. The L28
|
|
3
|
-
* spec calls for 2000 tokens; conservatively that is ~8 KB of UTF-8
|
|
4
|
-
* (rough Claude tokeniser ratio: ~4 chars per token). We cap at 8 KB
|
|
5
|
-
* so the formatted block stays under the token budget across every
|
|
6
|
-
* supported model family without per-model accounting.
|
|
7
|
-
*/
|
|
8
|
-
export const DEFAULT_FORMAT_BYTES_CAP = 8 * 1024;
|
|
9
|
-
/**
|
|
10
|
-
* Maximum symbols per row. The engine row format is:
|
|
11
|
-
*
|
|
12
|
-
* `- path/to/file.ts — summary line — exports: Foo(class), bar(fn)`
|
|
13
|
-
*
|
|
14
|
-
* Beyond 6 symbols the row grows past the readable column budget and
|
|
15
|
-
* the additional names rarely move the needle for the model — the
|
|
16
|
-
* exports tail is signal-bearing only for the first few entries
|
|
17
|
-
* anyway (`index.ts` re-exports tend к pile up).
|
|
18
|
-
*/
|
|
19
|
-
export const MAX_SYMBOLS_PER_ROW = 6;
|
|
20
|
-
/**
|
|
21
|
-
* Render the repo-map text. The implementation is intentionally split
|
|
22
|
-
* into:
|
|
23
|
-
*
|
|
24
|
-
* - `prioritise(...)` — pure sort + filter, fully testable in
|
|
25
|
-
* isolation, no I/O of any kind.
|
|
26
|
-
* - `renderRow(...)` — one file's row, byte-counted.
|
|
27
|
-
* - main loop — assembles header + rows + footer, respecting cap.
|
|
28
|
-
*
|
|
29
|
-
* The split lets the spec assert each stage in isolation (priority
|
|
30
|
-
* order, single-row shape, truncation arithmetic).
|
|
31
|
-
*/
|
|
32
|
-
export function formatRepoMap(extracts, options = {}) {
|
|
33
|
-
const maxBytes = options.maxBytes ?? DEFAULT_FORMAT_BYTES_CAP;
|
|
34
|
-
const omitHeader = options.omitHeader === true;
|
|
35
|
-
const prioritised = prioritise(extracts);
|
|
36
|
-
const header = omitHeader
|
|
37
|
-
? ''
|
|
38
|
-
: `## Repo map\n\n${prioritised.length} source files indexed.\n\n`;
|
|
39
|
-
const headerBytes = byteLength(header);
|
|
40
|
-
if (headerBytes >= maxBytes) {
|
|
41
|
-
// Cap is smaller than even the header — emit nothing rather than
|
|
42
|
-
// a truncated header that the engine cannot parse.
|
|
43
|
-
return {
|
|
44
|
-
text: '',
|
|
45
|
-
filesIncluded: 0,
|
|
46
|
-
filesTotal: extracts.length,
|
|
47
|
-
bytes: 0,
|
|
48
|
-
truncated: extracts.length > 0,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
const rows = [];
|
|
52
|
-
let bytesUsed = headerBytes;
|
|
53
|
-
let filesIncluded = 0;
|
|
54
|
-
let truncated = false;
|
|
55
|
-
for (let i = 0; i < prioritised.length; i += 1) {
|
|
56
|
-
const row = renderRow(prioritised[i]);
|
|
57
|
-
const rowBytes = byteLength(row);
|
|
58
|
-
// Reserve space for the footer (`\n... N more files\n`). We
|
|
59
|
-
// overestimate at 64 bytes — the exact number depends on the
|
|
60
|
-
// file count digits but 64 covers any realistic case.
|
|
61
|
-
const footerReserve = i + 1 < prioritised.length ? 64 : 0;
|
|
62
|
-
if (bytesUsed + rowBytes + footerReserve > maxBytes) {
|
|
63
|
-
truncated = true;
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
rows.push(row);
|
|
67
|
-
bytesUsed += rowBytes;
|
|
68
|
-
filesIncluded += 1;
|
|
69
|
-
}
|
|
70
|
-
let text = header + rows.join('');
|
|
71
|
-
if (truncated) {
|
|
72
|
-
const omitted = prioritised.length - filesIncluded;
|
|
73
|
-
text += `\n... ${omitted} more file${omitted === 1 ? '' : 's'}\n`;
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
text,
|
|
77
|
-
filesIncluded,
|
|
78
|
-
filesTotal: extracts.length,
|
|
79
|
-
bytes: byteLength(text),
|
|
80
|
-
truncated,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
/* ----------------------------- helpers ----------------------------- */
|
|
84
|
-
/**
|
|
85
|
-
* Sort the extracts by (exported-symbol count desc, path asc). The
|
|
86
|
-
* engine cares about the public surface; a file with 12 exported
|
|
87
|
-
* symbols carries more signal than 50 private helpers.
|
|
88
|
-
*/
|
|
89
|
-
export function prioritise(extracts) {
|
|
90
|
-
return [...extracts].sort((a, b) => {
|
|
91
|
-
const expA = countExports(a);
|
|
92
|
-
const expB = countExports(b);
|
|
93
|
-
if (expA !== expB)
|
|
94
|
-
return expB - expA;
|
|
95
|
-
return a.relPath < b.relPath ? -1 : a.relPath > b.relPath ? 1 : 0;
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
function countExports(extract) {
|
|
99
|
-
let n = 0;
|
|
100
|
-
for (const sym of extract.symbols)
|
|
101
|
-
if (sym.exported)
|
|
102
|
-
n += 1;
|
|
103
|
-
return n;
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Render a single file row. Format:
|
|
107
|
-
*
|
|
108
|
-
* `- path/to/file.ts — summary — exports: Foo(class), bar(fn), Baz(type)`
|
|
109
|
-
*
|
|
110
|
-
* When there are no exported symbols, the `exports:` tail is dropped.
|
|
111
|
-
* When there is no summary, the dash separator is dropped.
|
|
112
|
-
*/
|
|
113
|
-
export function renderRow(extract) {
|
|
114
|
-
const exported = extract.symbols.filter((s) => s.exported);
|
|
115
|
-
const symbolsTail = exported.length > 0
|
|
116
|
-
? ` — exports: ${formatSymbolList(exported.slice(0, MAX_SYMBOLS_PER_ROW))}`
|
|
117
|
-
: '';
|
|
118
|
-
const summaryTail = extract.summary ? ` — ${extract.summary}` : '';
|
|
119
|
-
return `- ${extract.relPath}${summaryTail}${symbolsTail}\n`;
|
|
120
|
-
}
|
|
121
|
-
function formatSymbolList(symbols) {
|
|
122
|
-
return symbols.map((s) => `${s.name}(${shortKind(s.kind)})`).join(', ');
|
|
123
|
-
}
|
|
124
|
-
function shortKind(kind) {
|
|
125
|
-
switch (kind) {
|
|
126
|
-
case 'function':
|
|
127
|
-
return 'fn';
|
|
128
|
-
case 'class':
|
|
129
|
-
return 'class';
|
|
130
|
-
case 'interface':
|
|
131
|
-
return 'iface';
|
|
132
|
-
case 'type':
|
|
133
|
-
return 'type';
|
|
134
|
-
case 'enum':
|
|
135
|
-
return 'enum';
|
|
136
|
-
case 'const':
|
|
137
|
-
return 'const';
|
|
138
|
-
case 'heading':
|
|
139
|
-
return 'h';
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
function byteLength(s) {
|
|
143
|
-
return Buffer.byteLength(s, 'utf8');
|
|
144
|
-
}
|
|
145
|
-
//# sourceMappingURL=formatter.js.map
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PageRank scorer для repo-map (#60 Phase 2).
|
|
3
|
-
*
|
|
4
|
-
* Thin wrapper around `graphology` + `graphology-metrics` PageRank
|
|
5
|
-
* implementation. We do NOT roll our own power-iteration loop —
|
|
6
|
-
* graphology's centrality module is the maintained, well-tested
|
|
7
|
-
* standard в the JS ecosystem (Yomguithereal, MIT, 2k+ stars).
|
|
8
|
-
*
|
|
9
|
-
* What this module adds on top of the library:
|
|
10
|
-
* - Pugi domain types (PageRankNode / PageRankEdge with optional weight)
|
|
11
|
-
* - File-level aggregation (aggregateByFile) — sums symbol scores per file
|
|
12
|
-
* - Output normalization (normalizeScores) к [0, 100] range для prompt
|
|
13
|
-
* table rendering per docs/features/feat-pugi-ranked-repo-map.md §4
|
|
14
|
-
*
|
|
15
|
-
* No I/O, no globals. Safe to call from worker threads.
|
|
16
|
-
*/
|
|
17
|
-
import * as graphologyModule from 'graphology';
|
|
18
|
-
import * as pagerankModule from 'graphology-metrics/centrality/pagerank.js';
|
|
19
|
-
const graphologyAny = graphologyModule;
|
|
20
|
-
const Graph = graphologyAny.default ?? graphologyModule;
|
|
21
|
-
const pagerankAny = pagerankModule;
|
|
22
|
-
const pagerankCentrality = pagerankAny.default ?? pagerankModule;
|
|
23
|
-
const DEFAULT_DAMPING = 0.85;
|
|
24
|
-
const DEFAULT_MAX_ITERATIONS = 100;
|
|
25
|
-
const DEFAULT_TOLERANCE = 1e-6;
|
|
26
|
-
export function pageRank(nodes, edges, options = {}) {
|
|
27
|
-
const damping = options.damping ?? DEFAULT_DAMPING;
|
|
28
|
-
const maxIterations = options.maxIterations ?? DEFAULT_MAX_ITERATIONS;
|
|
29
|
-
const tolerance = options.tolerance ?? DEFAULT_TOLERANCE;
|
|
30
|
-
if (damping < 0 || damping >= 1) {
|
|
31
|
-
throw new RangeError(`damping must be в [0, 1), got ${damping}`);
|
|
32
|
-
}
|
|
33
|
-
if (maxIterations < 1) {
|
|
34
|
-
throw new RangeError(`maxIterations must be >= 1, got ${maxIterations}`);
|
|
35
|
-
}
|
|
36
|
-
if (tolerance <= 0) {
|
|
37
|
-
throw new RangeError(`tolerance must be > 0, got ${tolerance}`);
|
|
38
|
-
}
|
|
39
|
-
const scores = new Map();
|
|
40
|
-
if (nodes.length === 0) {
|
|
41
|
-
return { scores };
|
|
42
|
-
}
|
|
43
|
-
const seen = new Set();
|
|
44
|
-
for (const node of nodes) {
|
|
45
|
-
if (seen.has(node.id)) {
|
|
46
|
-
throw new Error('duplicate node ids — pageRank requires unique node.id');
|
|
47
|
-
}
|
|
48
|
-
seen.add(node.id);
|
|
49
|
-
}
|
|
50
|
-
const graph = new Graph({ type: 'directed', multi: true, allowSelfLoops: true });
|
|
51
|
-
for (const node of nodes) {
|
|
52
|
-
graph.addNode(node.id);
|
|
53
|
-
}
|
|
54
|
-
for (const edge of edges) {
|
|
55
|
-
if (!seen.has(edge.from) || !seen.has(edge.to)) {
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
const weight = edge.weight ?? 1;
|
|
59
|
-
if (weight <= 0)
|
|
60
|
-
continue;
|
|
61
|
-
graph.addEdge(edge.from, edge.to, { weight });
|
|
62
|
-
}
|
|
63
|
-
pagerankCentrality.assign(graph, {
|
|
64
|
-
alpha: damping,
|
|
65
|
-
maxIterations,
|
|
66
|
-
tolerance,
|
|
67
|
-
getEdgeWeight: 'weight',
|
|
68
|
-
nodePageRankAttribute: 'pagerank',
|
|
69
|
-
});
|
|
70
|
-
for (const id of graph.nodes()) {
|
|
71
|
-
const score = graph.getNodeAttribute(id, 'pagerank');
|
|
72
|
-
scores.set(id, typeof score === 'number' ? score : 0);
|
|
73
|
-
}
|
|
74
|
-
return { scores };
|
|
75
|
-
}
|
|
76
|
-
export function aggregateByFile(symbolScores, symbolToFile) {
|
|
77
|
-
const fileScores = new Map();
|
|
78
|
-
for (const [symbolId, score] of symbolScores) {
|
|
79
|
-
const file = symbolToFile.get(symbolId);
|
|
80
|
-
if (file === undefined)
|
|
81
|
-
continue;
|
|
82
|
-
fileScores.set(file, (fileScores.get(file) ?? 0) + score);
|
|
83
|
-
}
|
|
84
|
-
return fileScores;
|
|
85
|
-
}
|
|
86
|
-
export function normalizeScores(scores) {
|
|
87
|
-
const normalized = new Map();
|
|
88
|
-
if (scores.size === 0)
|
|
89
|
-
return normalized;
|
|
90
|
-
let max = 0;
|
|
91
|
-
for (const score of scores.values()) {
|
|
92
|
-
if (score > max)
|
|
93
|
-
max = score;
|
|
94
|
-
}
|
|
95
|
-
if (max === 0) {
|
|
96
|
-
for (const id of scores.keys())
|
|
97
|
-
normalized.set(id, 0);
|
|
98
|
-
return normalized;
|
|
99
|
-
}
|
|
100
|
-
for (const [id, score] of scores) {
|
|
101
|
-
normalized.set(id, (score / max) * 100);
|
|
102
|
-
}
|
|
103
|
-
return normalized;
|
|
104
|
-
}
|
|
105
|
-
//# sourceMappingURL=page-rank.js.map
|