mixdog 0.9.1 → 0.9.3
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/package.json +9 -1
- package/scripts/_bench-cwc.json +20 -0
- package/scripts/agent-loop-policy-test.mjs +37 -0
- package/scripts/agent-parallel-smoke.mjs +54 -10
- package/scripts/anthropic-maxtokens-test.mjs +119 -0
- package/scripts/background-task-meta-smoke.mjs +1 -1
- package/scripts/bench-run.mjs +262 -0
- package/scripts/build-tui.mjs +13 -1
- package/scripts/compact-smoke.mjs +12 -0
- package/scripts/compact-trigger-migration-smoke.mjs +67 -1
- package/scripts/explore-bench.mjs +124 -0
- package/scripts/hook-bus-test.mjs +191 -0
- package/scripts/ingest-pure-conversation-smoke.mjs +148 -0
- package/scripts/internal-comms-bench.mjs +727 -0
- package/scripts/internal-comms-smoke.mjs +75 -0
- package/scripts/lead-workflow-smoke.mjs +4 -4
- package/scripts/live-worker-smoke.mjs +9 -9
- package/scripts/output-style-bench.mjs +285 -0
- package/scripts/output-style-smoke.mjs +13 -10
- package/scripts/patch-replay.mjs +90 -0
- package/scripts/path-suffix-test.mjs +57 -0
- package/scripts/provider-stream-stall-test.mjs +276 -0
- package/scripts/provider-toolcall-test.mjs +599 -1
- package/scripts/recall-bench.mjs +207 -0
- package/scripts/routing-corpus.mjs +281 -0
- package/scripts/session-bench.mjs +1526 -0
- package/scripts/session-diag.mjs +595 -0
- package/scripts/task-bench.mjs +207 -0
- package/scripts/tool-failures.mjs +6 -6
- package/scripts/tool-smoke.mjs +310 -67
- package/scripts/toolcall-args-test.mjs +81 -0
- package/src/agents/debugger/AGENT.md +4 -4
- package/src/agents/heavy-worker/AGENT.md +20 -9
- package/src/agents/reviewer/AGENT.md +4 -4
- package/src/agents/worker/AGENT.md +17 -9
- package/src/app.mjs +10 -6
- package/src/defaults/{hidden-roles.json → agents.json} +7 -7
- package/src/examples/schedules/SCHEDULE.example.md +32 -0
- package/src/examples/webhooks/WEBHOOK.example.md +40 -0
- package/src/headless-role.mjs +14 -14
- package/src/help.mjs +1 -0
- package/src/lib/rules-builder.cjs +32 -54
- package/src/mixdog-session-runtime.mjs +1040 -2036
- package/src/output-styles/default.md +12 -7
- package/src/output-styles/minimal.md +25 -0
- package/src/output-styles/oneline.md +21 -0
- package/src/output-styles/simple.md +10 -9
- package/src/repl.mjs +17 -7
- package/src/rules/agent/00-common.md +7 -5
- package/src/rules/agent/30-explorer.md +8 -12
- package/src/rules/lead/01-general.md +3 -1
- package/src/rules/lead/lead-tool.md +13 -2
- package/src/rules/shared/01-tool.md +23 -12
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +90 -32
- package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +32 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +18 -6
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +23 -20
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +48 -14
- package/src/runtime/agent/orchestrator/agent-trace.mjs +87 -12
- package/src/runtime/agent/orchestrator/config.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +182 -67
- package/src/runtime/agent/orchestrator/{internal-roles.mjs → internal-agents.mjs} +72 -72
- package/src/runtime/agent/orchestrator/internal-tools.mjs +13 -26
- package/src/runtime/agent/orchestrator/mcp/client.mjs +100 -18
- package/src/runtime/agent/orchestrator/providers/anthropic-betas.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +188 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-leaked-toolcall.mjs +444 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +313 -84
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +104 -38
- package/src/runtime/agent/orchestrator/providers/api-usage.mjs +28 -33
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +184 -17
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +8 -1
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +32 -0
- package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +18 -8
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +54 -20
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +227 -31
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +83 -6
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +229 -115
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +213 -33
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +18 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +49 -17
- package/src/runtime/agent/orchestrator/providers/registry.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +22 -17
- package/src/runtime/agent/orchestrator/session/compact.mjs +560 -51
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +250 -3
- package/src/runtime/agent/orchestrator/session/loop/compact-debug.mjs +28 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +262 -0
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +38 -0
- package/src/runtime/agent/orchestrator/session/loop/env.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/loop/hidden-agents.mjs +21 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +49 -0
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +63 -0
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +52 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +218 -0
- package/src/runtime/agent/orchestrator/session/loop/transcript-repair.mjs +101 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +35 -0
- package/src/runtime/agent/orchestrator/session/loop.mjs +513 -1000
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +227 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +235 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +137 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +155 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +303 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +232 -1152
- package/src/runtime/agent/orchestrator/session/store.mjs +4 -4
- package/src/runtime/agent/orchestrator/session/tool-envelope.mjs +61 -0
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +5 -0
- package/src/runtime/agent/orchestrator/stall-policy.mjs +63 -15
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +194 -24
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +143 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +34 -18
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +241 -0
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.test.mjs +162 -0
- package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/list-formatting.mjs +10 -0
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +42 -2
- package/src/runtime/agent/orchestrator/tools/builtin/path-utils.mjs +15 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-args.mjs +9 -44
- package/src/runtime/agent/orchestrator/tools/builtin/read-constants.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +14 -5
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +11 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +10 -17
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +23 -2
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +50 -39
- package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +3 -2
- package/src/runtime/agent/orchestrator/tools/builtin/tool-output-limit.mjs +10 -0
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +70 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +303 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +43 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +382 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +497 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +295 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-model.mjs +158 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/lang-predicates.mjs +128 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/memory-cache.mjs +66 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/project-root.mjs +44 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1192 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/source-access.mjs +81 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/span.mjs +19 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +280 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/text-mask.mjs +347 -0
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +39 -4189
- package/src/runtime/agent/orchestrator/tools/patch.mjs +119 -5
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +1 -2
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +1 -2
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +2 -4
- package/src/runtime/channels/backends/discord.mjs +99 -9
- package/src/runtime/channels/backends/telegram.mjs +501 -0
- package/src/runtime/channels/index.mjs +437 -1439
- package/src/runtime/channels/lib/boot-profile.mjs +23 -0
- package/src/runtime/channels/lib/config.mjs +54 -2
- package/src/runtime/channels/lib/crash-log.mjs +106 -0
- package/src/runtime/channels/lib/format.mjs +4 -2
- package/src/runtime/channels/lib/index-drop-trace.mjs +72 -0
- package/src/runtime/channels/lib/output-forwarder.mjs +88 -67
- package/src/runtime/channels/lib/runtime-paths.mjs +29 -0
- package/src/runtime/channels/lib/scheduler.mjs +1 -1
- package/src/runtime/channels/lib/telegram-format.mjs +280 -0
- package/src/runtime/channels/lib/tool-format.mjs +1 -1
- package/src/runtime/channels/lib/transcript-discovery.mjs +19 -1
- package/src/runtime/channels/lib/webhook.mjs +59 -31
- package/src/runtime/channels/lib/whisper-language.mjs +42 -0
- package/src/runtime/channels/tool-defs.mjs +1 -1
- package/src/runtime/memory/index.mjs +465 -345
- package/src/runtime/memory/lib/agent-ipc.mjs +2 -2
- package/src/runtime/memory/lib/core-memory-store.mjs +352 -2
- package/src/runtime/memory/lib/cycle-signatures.mjs +34 -0
- package/src/runtime/memory/lib/http-wire.mjs +57 -0
- package/src/runtime/memory/lib/memory-cycle1.mjs +1 -1
- package/src/runtime/memory/lib/memory-cycle2.mjs +65 -9
- package/src/runtime/memory/lib/memory-cycle3.mjs +1 -1
- package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +24 -0
- package/src/runtime/memory/lib/memory-retrievers.mjs +8 -0
- package/src/runtime/memory/lib/memory.mjs +121 -4
- package/src/runtime/memory/lib/pg/adapter.mjs +139 -15
- package/src/runtime/memory/lib/promotion-fingerprint.mjs +50 -0
- package/src/runtime/memory/lib/recall-format.mjs +183 -0
- package/src/runtime/memory/lib/session-ingest.mjs +107 -0
- package/src/runtime/memory/lib/trace-store.mjs +69 -22
- package/src/runtime/memory/tool-defs.mjs +10 -7
- package/src/runtime/shared/abort-controller.mjs +1 -1
- package/src/runtime/shared/background-tasks.mjs +2 -3
- package/src/runtime/shared/buffered-appender.mjs +149 -0
- package/src/runtime/shared/channel-notification-routing.mjs +12 -0
- package/src/runtime/shared/channel-notification-routing.test.mjs +45 -0
- package/src/runtime/shared/config.mjs +9 -0
- package/src/runtime/shared/llm/http-agent.mjs +12 -5
- package/src/runtime/shared/schedules-store.mjs +21 -19
- package/src/runtime/shared/task-notification-envelope.mjs +98 -0
- package/src/runtime/shared/task-notification-envelope.test.mjs +107 -0
- package/src/runtime/shared/tool-execution-contract.mjs +2 -2
- package/src/runtime/shared/tool-surface.mjs +98 -13
- package/src/runtime/shared/transcript-writer.mjs +156 -0
- package/src/runtime/shared/update-checker.mjs +214 -0
- package/src/session-runtime/config-helpers.mjs +209 -0
- package/src/session-runtime/effort.mjs +128 -0
- package/src/session-runtime/fs-utils.mjs +10 -0
- package/src/session-runtime/model-capabilities.mjs +130 -0
- package/src/session-runtime/output-styles.mjs +124 -0
- package/src/session-runtime/plugin-mcp.mjs +114 -0
- package/src/session-runtime/session-text.mjs +100 -0
- package/src/session-runtime/statusline-route.mjs +35 -0
- package/src/session-runtime/tool-catalog.mjs +720 -0
- package/src/session-runtime/workflow.mjs +358 -0
- package/src/standalone/agent-tool.mjs +302 -117
- package/src/standalone/channel-admin.mjs +133 -40
- package/src/standalone/channel-worker.mjs +10 -292
- package/src/standalone/explore-tool.mjs +12 -5
- package/src/standalone/hook-bus.mjs +165 -8
- package/src/standalone/memory-runtime-proxy.mjs +3 -1
- package/src/standalone/opencode-go-login.mjs +121 -0
- package/src/standalone/provider-admin.mjs +25 -3
- package/src/standalone/usage-dashboard.mjs +1 -1
- package/src/tui/App.jsx +2883 -778
- package/src/tui/components/ConfirmBar.jsx +47 -0
- package/src/tui/components/ContextPanel.jsx +5 -3
- package/src/tui/components/ItemRightHintOverprint.jsx +54 -0
- package/src/tui/components/Markdown.jsx +22 -98
- package/src/tui/components/Message.jsx +14 -35
- package/src/tui/components/Picker.jsx +87 -12
- package/src/tui/components/PromptInput.jsx +355 -22
- package/src/tui/components/QueuedCommands.jsx +1 -1
- package/src/tui/components/SlashCommandPalette.jsx +8 -5
- package/src/tui/components/Spinner.jsx +7 -7
- package/src/tui/components/StatusLine.jsx +40 -21
- package/src/tui/components/TextEntryPanel.jsx +51 -7
- package/src/tui/components/ToolExecution.jsx +183 -101
- package/src/tui/components/TurnDone.jsx +4 -4
- package/src/tui/components/UsagePanel.jsx +1 -1
- package/src/tui/components/tool-output-format.mjs +161 -23
- package/src/tui/components/tool-output-format.test.mjs +87 -0
- package/src/tui/display-width.mjs +69 -0
- package/src/tui/display-width.test.mjs +35 -0
- package/src/tui/dist/index.mjs +6731 -2333
- package/src/tui/engine/agent-envelope.mjs +296 -0
- package/src/tui/engine/boot-profile.mjs +21 -0
- package/src/tui/engine/labels.mjs +67 -0
- package/src/tui/engine/notice-text.mjs +112 -0
- package/src/tui/engine/queue-helpers.mjs +161 -0
- package/src/tui/engine/session-stats.mjs +46 -0
- package/src/tui/engine/tool-call-fields.mjs +23 -0
- package/src/tui/engine/tool-result-text.mjs +126 -0
- package/src/tui/engine.mjs +569 -948
- package/src/tui/index.jsx +117 -7
- package/src/tui/input-editing.mjs +58 -8
- package/src/tui/input-editing.selection.test.mjs +75 -0
- package/src/tui/keyboard-protocol.mjs +42 -0
- package/src/tui/lib/voice-recorder.mjs +469 -0
- package/src/tui/markdown/format-token.mjs +128 -76
- package/src/tui/markdown/format-token.test.mjs +61 -19
- package/src/tui/markdown/measure-rendered-rows.mjs +85 -0
- package/src/tui/markdown/render-ansi.test.mjs +1 -1
- package/src/tui/markdown/streaming-markdown.mjs +167 -0
- package/src/tui/markdown/streaming-markdown.test.mjs +70 -0
- package/src/tui/markdown/table-layout.mjs +9 -9
- package/src/tui/paste-attachments.mjs +36 -9
- package/src/tui/paste-fix.test.mjs +119 -0
- package/src/tui/prompt-history-store.mjs +129 -0
- package/src/tui/prompt-history-store.test.mjs +52 -0
- package/src/tui/statusline-ansi-bridge.test.mjs +3 -3
- package/src/tui/theme.mjs +41 -657
- package/src/tui/themes/base.mjs +86 -0
- package/src/tui/themes/basic.mjs +85 -0
- package/src/tui/themes/catppuccin.mjs +72 -0
- package/src/tui/themes/dracula.mjs +70 -0
- package/src/tui/themes/everforest.mjs +71 -0
- package/src/tui/themes/gruvbox.mjs +71 -0
- package/src/tui/themes/index.mjs +71 -0
- package/src/tui/themes/indigo.mjs +78 -0
- package/src/tui/themes/kanagawa.mjs +80 -0
- package/src/tui/themes/light.mjs +81 -0
- package/src/tui/themes/nord.mjs +72 -0
- package/src/tui/themes/onedark.mjs +16 -0
- package/src/tui/themes/rosepine.mjs +70 -0
- package/src/tui/themes/teal.mjs +80 -0
- package/src/tui/themes/tokyonight.mjs +79 -0
- package/src/tui/themes/utils.mjs +106 -0
- package/src/tui/themes/warm.mjs +79 -0
- package/src/tui/transcript-tool-failures.mjs +13 -2
- package/src/ui/markdown.mjs +1 -1
- package/src/ui/model-display.mjs +2 -2
- package/src/ui/statusline.mjs +75 -27
- package/src/vendor/statusline/bin/statusline-route.mjs +5 -12
- package/src/vendor/statusline/src/gateway/claude-current.mjs +3 -3
- package/src/vendor/statusline/src/gateway/route-meta.mjs +30 -16
- package/src/workflows/default/WORKFLOW.md +46 -12
- package/src/workflows/sequential/WORKFLOW.md +51 -0
- package/src/workflows/solo/WORKFLOW.md +12 -1
- package/vendor/ink/build/display-width.js +62 -0
- package/vendor/ink/build/ink.js +100 -12
- package/vendor/ink/build/measure-text.js +4 -1
- package/vendor/ink/build/output.js +115 -9
- package/vendor/ink/build/render-node-to-output.js +4 -1
- package/vendor/ink/build/render.js +4 -0
- package/src/output-styles/extreme-simple.md +0 -20
- package/src/rules/lead/04-workflow.md +0 -51
- package/src/workflows/default/workflow.json +0 -13
- package/src/workflows/solo/workflow.json +0 -7
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Per-node source-text accessors with fingerprint-keyed runtime caching:
|
|
2
|
+
// raw text, raw lines, masked lines. Extracted verbatim from code-graph.mjs.
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { toDisplayPath } from '../builtin.mjs';
|
|
5
|
+
import { _maskNonCodeText } from './text-mask.mjs';
|
|
6
|
+
|
|
7
|
+
export function _graphRel(absPath, cwd) {
|
|
8
|
+
return toDisplayPath(absPath, cwd);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function _getSourceTextForNode(graph, node, fallbackText = null) {
|
|
12
|
+
const cached = graph?._sourceTextCache?.get(node.rel);
|
|
13
|
+
if (cached && cached.fingerprint === (node.fingerprint || '')) {
|
|
14
|
+
return cached.text;
|
|
15
|
+
}
|
|
16
|
+
if (typeof fallbackText === 'string') {
|
|
17
|
+
graph?._sourceTextCache?.set(node.rel, {
|
|
18
|
+
fingerprint: node.fingerprint || '',
|
|
19
|
+
text: fallbackText,
|
|
20
|
+
});
|
|
21
|
+
return fallbackText;
|
|
22
|
+
}
|
|
23
|
+
let text = '';
|
|
24
|
+
let readOk = false;
|
|
25
|
+
try { text = readFileSync(node.abs, 'utf8'); readOk = true; } catch { text = ''; readOk = false; }
|
|
26
|
+
if (readOk) {
|
|
27
|
+
graph?._sourceTextCache?.set(node.rel, {
|
|
28
|
+
fingerprint: node.fingerprint || '',
|
|
29
|
+
text,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return text;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function _getSourceLinesForNode(graph, node) {
|
|
36
|
+
const cached = graph?._sourceLinesCache?.get(node.rel);
|
|
37
|
+
if (cached && cached.fingerprint === (node.fingerprint || '')) {
|
|
38
|
+
return cached.lines;
|
|
39
|
+
}
|
|
40
|
+
const text = _getSourceTextForNode(graph, node);
|
|
41
|
+
const lines = text.split(/\r?\n/);
|
|
42
|
+
graph?._sourceLinesCache?.set(node.rel, {
|
|
43
|
+
fingerprint: node.fingerprint || '',
|
|
44
|
+
lines,
|
|
45
|
+
});
|
|
46
|
+
return lines;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function _getMaskedLinesForNode(graph, node) {
|
|
50
|
+
const cached = graph?._maskedLinesCache?.get(node.rel);
|
|
51
|
+
if (cached && cached.fingerprint === (node.fingerprint || '')) {
|
|
52
|
+
return cached.lines;
|
|
53
|
+
}
|
|
54
|
+
const text = _getSourceTextForNode(graph, node);
|
|
55
|
+
const lines = _maskNonCodeText(text, node.lang).split(/\r?\n/);
|
|
56
|
+
graph?._maskedLinesCache?.set(node.rel, {
|
|
57
|
+
fingerprint: node.fingerprint || '',
|
|
58
|
+
lines,
|
|
59
|
+
});
|
|
60
|
+
return lines;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// "file not found in graph" fires AFTER the dispatch-level existsSync check
|
|
64
|
+
// passed — the file EXISTS on disk but is not indexed. Say that explicitly,
|
|
65
|
+
// and offer same-basename indexed paths as a secondary pointer (capped at 3).
|
|
66
|
+
export function _appendSameBasenameHint(message, normFile, graph) {
|
|
67
|
+
const raw = String(normFile || '');
|
|
68
|
+
const base = raw.replace(/\\/g, '/').split('/').pop();
|
|
69
|
+
if (!base || !graph?.nodes) return message;
|
|
70
|
+
const baseLower = base.toLowerCase();
|
|
71
|
+
const matches = [];
|
|
72
|
+
for (const key of graph.nodes.keys()) {
|
|
73
|
+
if (key.split('/').pop().toLowerCase() === baseLower) {
|
|
74
|
+
matches.push(key);
|
|
75
|
+
if (matches.length >= 3) break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const why = ' — the file exists on disk but is not indexed (excluded dir like dist/vendor, unsupported type, or graph file cap); use grep/read on it directly.';
|
|
79
|
+
if (!matches.length) return `${message}${why}`;
|
|
80
|
+
return `${message}${why} If you meant the indexed source, same filename is indexed at: ${matches.map((m) => `"${m}"`).join(', ')}.`;
|
|
81
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Declaration span-end inference from indentation. Recovers the end line of a
|
|
2
|
+
// brace-delimited declaration whose endLine the graph does not record
|
|
3
|
+
// (assignment-style decls). Extracted verbatim from code-graph.mjs.
|
|
4
|
+
|
|
5
|
+
const SYMBOL_SPAN_SCAN_MAX_LINES = 400;
|
|
6
|
+
|
|
7
|
+
export function _inferSpanEndByIndent(allLines, startLine) {
|
|
8
|
+
const decl = allLines[startLine - 1];
|
|
9
|
+
if (typeof decl !== 'string' || !/[{([]\s*$/.test(decl.trimEnd())) return null;
|
|
10
|
+
const declIndent = decl.match(/^[ \t]*/)[0].length;
|
|
11
|
+
const last = Math.min(allLines.length, startLine - 1 + SYMBOL_SPAN_SCAN_MAX_LINES);
|
|
12
|
+
for (let i = startLine; i < last; i++) {
|
|
13
|
+
const line = allLines[i];
|
|
14
|
+
if (!/^[ \t]*[})\]]/.test(line)) continue;
|
|
15
|
+
const indent = line.match(/^[ \t]*/)[0].length;
|
|
16
|
+
if (indent <= declIndent) return i + 1;
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
// Identifier tokenization, cheap regex symbol extraction, lazy per-symbol
|
|
2
|
+
// candidate-node lookup, and explainer anchor lines. Extracted verbatim
|
|
3
|
+
// from code-graph.mjs.
|
|
4
|
+
import {
|
|
5
|
+
_langUsesDollarInIdentifiers,
|
|
6
|
+
_langAllowsBangQuestionSuffix,
|
|
7
|
+
} from './lang-predicates.mjs';
|
|
8
|
+
import { _getSourceTextForNode } from './source-access.mjs';
|
|
9
|
+
import { _graphRel } from './source-access.mjs';
|
|
10
|
+
|
|
11
|
+
// Unicode-aware word-boundary wrapper for an already-regex-escaped
|
|
12
|
+
// symbol. JS `\b` only fires at ASCII [A-Za-z0-9_] transitions, so
|
|
13
|
+
// CJK / Cyrillic / Greek identifiers never matched the legacy shape.
|
|
14
|
+
// `$` is part of the boundary only for JS/TS/PHP; Ruby/Kotlin/Rust
|
|
15
|
+
// `!?` suffixes are kept distinct from the unsuffixed name when searching.
|
|
16
|
+
export function _unicodeBoundaryPattern(escaped, lang = null, symbol = null) {
|
|
17
|
+
const allowDollar = !lang || _langUsesDollarInIdentifiers(lang);
|
|
18
|
+
const before = allowDollar ? '(?<![\\p{ID_Continue}$])' : '(?<![\\p{ID_Continue}])';
|
|
19
|
+
let after = allowDollar ? '(?![\\p{ID_Continue}$])' : '(?![\\p{ID_Continue}])';
|
|
20
|
+
const sym = symbol == null ? '' : String(symbol);
|
|
21
|
+
if (lang && _langAllowsBangQuestionSuffix(lang) && sym && !/[!?]$/.test(sym)) {
|
|
22
|
+
after = allowDollar ? '(?![\\p{ID_Continue}$!?])' : '(?![\\p{ID_Continue}!?])';
|
|
23
|
+
}
|
|
24
|
+
return `${before}${escaped}${after}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function _extractIdentifierTokens(text, lang = null) {
|
|
28
|
+
const out = new Set();
|
|
29
|
+
const allowDollar = !lang || _langUsesDollarInIdentifiers(lang);
|
|
30
|
+
const before = allowDollar ? '(?<![\\p{ID_Continue}$])' : '(?<![\\p{ID_Continue}])';
|
|
31
|
+
const suffix = lang && _langAllowsBangQuestionSuffix(lang) ? '[!?]?' : '';
|
|
32
|
+
const after = allowDollar ? '(?![\\p{ID_Continue}$])' : '(?![\\p{ID_Continue}])';
|
|
33
|
+
const re = new RegExp(`${before}[$@]?[\\p{ID_Start}_][\\p{ID_Continue}]*${suffix}${after}`, 'gu');
|
|
34
|
+
let match = null;
|
|
35
|
+
const src = String(text || '');
|
|
36
|
+
while ((match = re.exec(src))) {
|
|
37
|
+
out.add(match[0]);
|
|
38
|
+
}
|
|
39
|
+
return [...out];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function _getTokenSymbolsForNode(graph, node) {
|
|
43
|
+
if (Array.isArray(node?.tokenSymbols)) return node.tokenSymbols;
|
|
44
|
+
const text = _getSourceTextForNode(graph, node);
|
|
45
|
+
const tokens = _extractIdentifierTokens(text, node.lang);
|
|
46
|
+
node.tokenSymbols = tokens;
|
|
47
|
+
return tokens;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Lazy per-symbol candidate lookup. Caches the result back into
|
|
51
|
+
// `_symbolTokenIndex` so repeat lookups are O(1). Compared to a full
|
|
52
|
+
// _ensureSymbolTokenIndex sweep, the per-symbol scan is O(N) where N is
|
|
53
|
+
// the node count (~7000 on refs/), and each node's check is a cheap
|
|
54
|
+
// Array.includes on its pre-extracted tokenSymbols. Cold-process first
|
|
55
|
+
// lookup drops from ~1-2s to ~50ms.
|
|
56
|
+
export function _lookupCandidateNodes(graph, symbol, language = null) {
|
|
57
|
+
if (!graph?.nodes) return [];
|
|
58
|
+
const cacheKey = `${language || '*'}|${symbol}`;
|
|
59
|
+
if (graph._symbolTokenIndex?.has(cacheKey)) {
|
|
60
|
+
const rels = graph._symbolTokenIndex.get(cacheKey);
|
|
61
|
+
return rels.map((rel) => graph.nodes.get(rel)).filter(Boolean);
|
|
62
|
+
}
|
|
63
|
+
const candidates = [];
|
|
64
|
+
for (const node of graph.nodes.values()) {
|
|
65
|
+
if (language && node.lang !== language) continue;
|
|
66
|
+
const tokens = _getTokenSymbolsForNode(graph, node);
|
|
67
|
+
if (tokens.includes(symbol)) candidates.push(node);
|
|
68
|
+
}
|
|
69
|
+
if (candidates.length > 0) {
|
|
70
|
+
if (graph._symbolTokenIndex) {
|
|
71
|
+
graph._symbolTokenIndex.set(cacheKey, candidates.map((n) => n.rel));
|
|
72
|
+
}
|
|
73
|
+
return candidates;
|
|
74
|
+
}
|
|
75
|
+
// Token-index miss → fall back to language-filtered full graph scan.
|
|
76
|
+
// _extractIdentifierTokens uses ASCII `\b` word-boundary which misses
|
|
77
|
+
// unicode (Korean/CJK), $-prefixed identifiers in some positions, and
|
|
78
|
+
// certain multi-byte language tokens (Rust raw idents, Go method
|
|
79
|
+
// receivers). The downstream search loop's sourceText.includes()
|
|
80
|
+
// still catches these — we just need to give it the full node set.
|
|
81
|
+
// Not cached: caching the fallback would mask token-extractor
|
|
82
|
+
// improvements and would also keep returning the heavy scan after a
|
|
83
|
+
// future graph rebuild populated the token map for the symbol.
|
|
84
|
+
const fallback = [];
|
|
85
|
+
for (const node of graph.nodes.values()) {
|
|
86
|
+
if (language && node.lang !== language) continue;
|
|
87
|
+
fallback.push(node);
|
|
88
|
+
}
|
|
89
|
+
return fallback;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function _extractSymbolsCheap(text, lang) {
|
|
93
|
+
const all = _collectCheapSymbols(text, lang).map((item) => `${item.kind} ${item.name} (L${item.line})`);
|
|
94
|
+
return all.length ? _capGraphList(all).join('\n') : '(no symbols)';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Control-flow keywords that the bare `name(args) {?$` patterns below
|
|
98
|
+
// would otherwise mis-collect as function/method symbols (e.g. an
|
|
99
|
+
// `if (...) {` line). Excluding at the collection stage keeps the
|
|
100
|
+
// invariant out of every downstream label/summarizer.
|
|
101
|
+
const _CHEAP_SYMBOL_CONTROL_FLOW = new Set([
|
|
102
|
+
'if', 'else', 'elif', 'for', 'foreach', 'while', 'do',
|
|
103
|
+
'switch', 'case', 'default', 'when', 'select',
|
|
104
|
+
'try', 'catch', 'finally', 'throw', 'throws',
|
|
105
|
+
'return', 'yield', 'await', 'goto', 'break', 'continue',
|
|
106
|
+
'with', 'using', 'lock', 'synchronized', 'unless',
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
export function _collectCheapSymbols(text, lang) {
|
|
110
|
+
const lines = String(text || '').split(/\r?\n/);
|
|
111
|
+
const out = [];
|
|
112
|
+
const push = (kind, name, idx) => {
|
|
113
|
+
if (!name) return;
|
|
114
|
+
// Skip control-flow keywords so `if(...) {`, `for(...) {`,
|
|
115
|
+
// `while(...) {`, `switch(...) {`, `catch(...) {` no longer leak
|
|
116
|
+
// as function/method symbols through the bare `name(args)` shapes.
|
|
117
|
+
if (_CHEAP_SYMBOL_CONTROL_FLOW.has(name)) return;
|
|
118
|
+
out.push({ kind, name, line: idx + 1 });
|
|
119
|
+
};
|
|
120
|
+
// Slash (`//` `/*`) comments: all C-family langs incl. new kotlin/swift/
|
|
121
|
+
// scala. Excluded: python/ruby (hash), bash (hash), lua (`--`; also `//`
|
|
122
|
+
// is lua integer-division, so slash-stripping would delete code). Second
|
|
123
|
+
// batch: dart/objc/zig are C-family slash-comment (kept by the default);
|
|
124
|
+
// elixir/r are hash-comment (excluded below).
|
|
125
|
+
const supportsSlash = lang !== 'python' && lang !== 'ruby'
|
|
126
|
+
&& lang !== 'bash' && lang !== 'lua'
|
|
127
|
+
&& lang !== 'elixir' && lang !== 'r';
|
|
128
|
+
// Hash (`#`) comments: python/ruby/php and bash. lua uses `--` (handled by
|
|
129
|
+
// _maskNonCodeText, not needed here since lua has no cheap-symbol matcher).
|
|
130
|
+
// Second batch: elixir and r are `#`-only line-comment langs → included.
|
|
131
|
+
const supportsHash = lang === 'python' || lang === 'ruby' || lang === 'php'
|
|
132
|
+
|| lang === 'bash' || lang === 'elixir' || lang === 'r';
|
|
133
|
+
let inBlockComment = false;
|
|
134
|
+
for (let i = 0; i < lines.length; i++) {
|
|
135
|
+
// Per-line comment stripping at the collection stage so header/JSDoc
|
|
136
|
+
// words like "These", "side", "effects" cannot bleed into the
|
|
137
|
+
// overview `symbols:` token list or the cheap summarizer output.
|
|
138
|
+
// An unclosed `/*` keeps the code before it and flips the block flag
|
|
139
|
+
// so code-before-comment lines (and spaced generators like `* gen()`)
|
|
140
|
+
// still reach the per-language matchers below.
|
|
141
|
+
let line = lines[i];
|
|
142
|
+
if (supportsSlash) {
|
|
143
|
+
if (inBlockComment) {
|
|
144
|
+
const endIdx = line.indexOf('*/');
|
|
145
|
+
if (endIdx < 0) continue;
|
|
146
|
+
line = line.slice(endIdx + 2);
|
|
147
|
+
inBlockComment = false;
|
|
148
|
+
}
|
|
149
|
+
while (true) {
|
|
150
|
+
const startIdx = line.indexOf('/*');
|
|
151
|
+
if (startIdx < 0) break;
|
|
152
|
+
const endIdx = line.indexOf('*/', startIdx + 2);
|
|
153
|
+
if (endIdx < 0) {
|
|
154
|
+
line = line.slice(0, startIdx);
|
|
155
|
+
inBlockComment = true;
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
line = line.slice(0, startIdx) + ' ' + line.slice(endIdx + 2);
|
|
159
|
+
}
|
|
160
|
+
const slashIdx = line.indexOf('//');
|
|
161
|
+
if (slashIdx >= 0) line = line.slice(0, slashIdx);
|
|
162
|
+
}
|
|
163
|
+
if (supportsHash) {
|
|
164
|
+
if (/^\s*#/.test(line)) continue;
|
|
165
|
+
}
|
|
166
|
+
if (!line.trim()) continue;
|
|
167
|
+
let m = null;
|
|
168
|
+
if (lang === 'typescript' || lang === 'javascript') {
|
|
169
|
+
if ((m = /\b(class|interface|type|enum)\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(line))) push(m[1], m[2], i);
|
|
170
|
+
else if ((m = /\bfunction\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(/.exec(line))) push('function', m[1], i);
|
|
171
|
+
else if ((m = /\b(?:const|let|var)\s+([A-Za-z_][A-Za-z0-9_]*)\b/.exec(line))) push('binding', m[1], i);
|
|
172
|
+
else if ((m = /^\s*(?:static\s+)?(?:async\s+)?(?:get\s+|set\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*\([^;]*\)\s*\{?$/.exec(line))) push('method', m[1], i);
|
|
173
|
+
} else if (lang === 'python') {
|
|
174
|
+
if ((m = /^\s*class\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(line))) push('class', m[1], i);
|
|
175
|
+
else if ((m = /^\s*def\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(line))) push('function', m[1], i);
|
|
176
|
+
} else if (lang === 'go') {
|
|
177
|
+
if ((m = /^\s*type\s+([A-Za-z_][A-Za-z0-9_]*)\s+struct\b/.exec(line))) push('struct', m[1], i);
|
|
178
|
+
else if ((m = /^\s*func(?:\s*\([^)]*\))?\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(/.exec(line))) push('function', m[1], i);
|
|
179
|
+
} else if (lang === 'rust') {
|
|
180
|
+
if ((m = /^\s*(?:pub\s+)?struct\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(line))) push('struct', m[1], i);
|
|
181
|
+
else if ((m = /^\s*(?:pub\s+)?fn\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(/.exec(line))) push('function', m[1], i);
|
|
182
|
+
} else if (lang === 'kotlin') {
|
|
183
|
+
// Kotlin: `fun name(...)` is the canonical function declaration whether
|
|
184
|
+
// the body is a `{` block or an `= expr` expression body. The shared
|
|
185
|
+
// Java/C#-style `name(...) {` pattern misses expression bodies that
|
|
186
|
+
// end with the expression itself (no trailing `{` or `;`), so caller
|
|
187
|
+
// names disappear for those functions.
|
|
188
|
+
if ((m = /\b(class|interface|enum|object)\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(line))) push(m[1], m[2], i);
|
|
189
|
+
else if ((m = /^\s*(?:public\s+|private\s+|protected\s+|internal\s+)?(?:open\s+|abstract\s+|final\s+)?(?:override\s+)?(?:suspend\s+)?(?:inline\s+)?fun\s+(?:<[^>]+>\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*\(/.exec(line))) push('function', m[1], i);
|
|
190
|
+
else if ((m = /^\s*(?:public\s+|private\s+|protected\s+|internal\s+)?(?:const\s+)?(?:val|var)\s+([A-Za-z_][A-Za-z0-9_]*)\b/.exec(line))) push('binding', m[1], i);
|
|
191
|
+
} else if (lang === 'java' || lang === 'csharp') {
|
|
192
|
+
if ((m = /\b(class|interface|enum|record)\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(line))) push(m[1], m[2], i);
|
|
193
|
+
else if ((m = /\b([A-Za-z_][A-Za-z0-9_]*)\s*\([^;]*\)\s*\{?$/.exec(line))) push('function', m[1], i);
|
|
194
|
+
} else if (lang === 'c' || lang === 'cpp') {
|
|
195
|
+
if ((m = /\b(class|struct|enum)\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(line))) push(m[1], m[2], i);
|
|
196
|
+
else if ((m = /^\s*[A-Za-z_][\w\s:*<>~]*\s+([A-Za-z_][A-Za-z0-9_]*)\s*\([^;]*\)\s*\{?$/.exec(line))) push('function', m[1], i);
|
|
197
|
+
} else if (lang === 'ruby' || lang === 'php') {
|
|
198
|
+
if ((m = /^\s*class\s+([A-Za-z_][A-Za-z0-9_:]*)/.exec(line))) push('class', m[1], i);
|
|
199
|
+
else if ((m = /^\s*def\s+([A-Za-z_][A-Za-z0-9_!?=]*)/.exec(line))) push('function', m[1], i);
|
|
200
|
+
}
|
|
201
|
+
// No cheap-regex matcher for swift/scala/bash/lua or the second batch
|
|
202
|
+
// (dart/objc/elixir/zig/r): the native indexer now emits symbols for these
|
|
203
|
+
// langs, so _collectCheapSymbols runs only as a fallback when native
|
|
204
|
+
// symbols are absent. They are deliberately left without a branch (yield no
|
|
205
|
+
// cheap anchors) rather than guessing with a loose pattern; callers
|
|
206
|
+
// (overview/anchors) fall back to native symbols.
|
|
207
|
+
}
|
|
208
|
+
return out;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Raised from 6 to 50 after HS-A6 surfaced that overview on a ~46KB file
|
|
212
|
+
// returned only the first 6 anchors (all within the first 87 lines, 5%
|
|
213
|
+
// of the file). tail-trim still bounds output payload, so a higher cap
|
|
214
|
+
// surfaces full structure on large files without hurting small ones.
|
|
215
|
+
export function _extractExplainerAnchorLines(node, graph, { limit = 50, maxLineChars = 180 } = {}) {
|
|
216
|
+
const sourceLines = _getSourceTextForNode(graph, node).split(/\r?\n/);
|
|
217
|
+
const symbols = Array.isArray(node.symbols) && node.symbols.length
|
|
218
|
+
? node.symbols
|
|
219
|
+
: _collectCheapSymbols(sourceLines.join('\n'), node.lang);
|
|
220
|
+
const out = [];
|
|
221
|
+
const seen = new Set();
|
|
222
|
+
for (const item of symbols) {
|
|
223
|
+
if (out.length >= limit) break;
|
|
224
|
+
const idx = item.line - 1;
|
|
225
|
+
const line = String(sourceLines[idx] || '').trim();
|
|
226
|
+
if (!line) continue;
|
|
227
|
+
const key = `${item.name}:${item.line}`;
|
|
228
|
+
if (seen.has(key)) continue;
|
|
229
|
+
seen.add(key);
|
|
230
|
+
out.push(`${item.kind} ${item.name} (L${item.line}): ${line.slice(0, maxLineChars)}`);
|
|
231
|
+
}
|
|
232
|
+
return out;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Bound model-facing structural list output (imports/dependents/related,
|
|
236
|
+
// symbols, external callers) so a high fan-in/fan-out or symbol-dense file
|
|
237
|
+
// cannot inject an unbounded result — mirrors the find_imports/find_dependents
|
|
238
|
+
// cap.
|
|
239
|
+
export function _capGraphList(arr, cap = 200) {
|
|
240
|
+
return arr.length > cap
|
|
241
|
+
? [...arr.slice(0, cap), `[truncated — showing first ${cap} of ${arr.length}]`]
|
|
242
|
+
: arr;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export function _buildExplainerFileSummary(node, graph, cwd) {
|
|
246
|
+
const topTypes = Array.isArray(node?.topLevelTypes) ? node.topLevelTypes.slice(0, 8) : [];
|
|
247
|
+
const importsAll = Array.isArray(node?.resolvedImports) ? node.resolvedImports.map((p) => _graphRel(p, cwd)) : [];
|
|
248
|
+
const imports = importsAll.slice(0, 8);
|
|
249
|
+
const tokensAll = _getTokenSymbolsForNode(graph, node);
|
|
250
|
+
// Prefer native tree-sitter symbol names; fall back to the regex token
|
|
251
|
+
// dump only when the native graph path didn't populate node.symbols.
|
|
252
|
+
const hasNativeSymbols = Array.isArray(node?.symbols) && node.symbols.length > 0;
|
|
253
|
+
const symbolsAll = hasNativeSymbols
|
|
254
|
+
? [...new Set(node.symbols.map((s) => s.name))]
|
|
255
|
+
: tokensAll;
|
|
256
|
+
const symbolNames = symbolsAll.slice(0, hasNativeSymbols ? 30 : 20);
|
|
257
|
+
const anchors = _extractExplainerAnchorLines(node, graph);
|
|
258
|
+
const sourceHead = _getSourceTextForNode(graph, node)
|
|
259
|
+
.split(/\r?\n/)
|
|
260
|
+
.slice(0, 6)
|
|
261
|
+
.join('\n')
|
|
262
|
+
.trim()
|
|
263
|
+
.slice(0, 420);
|
|
264
|
+
const parts = [
|
|
265
|
+
`file: ${node.rel}`,
|
|
266
|
+
`language: ${node.lang}`,
|
|
267
|
+
];
|
|
268
|
+
if (topTypes.length) parts.push(`top-level: ${topTypes.join(', ')}`);
|
|
269
|
+
if (symbolNames.length) {
|
|
270
|
+
const more = symbolsAll.length - symbolNames.length;
|
|
271
|
+
parts.push(`symbols: ${symbolNames.join(', ')}${more > 0 ? `, … +${more} more (mode:symbols for full list)` : ''}`);
|
|
272
|
+
}
|
|
273
|
+
if (imports.length) {
|
|
274
|
+
const more = importsAll.length - imports.length;
|
|
275
|
+
parts.push(`imports: ${imports.join(', ')}${more > 0 ? `, … +${more} more (mode:imports for full list)` : ''}`);
|
|
276
|
+
}
|
|
277
|
+
if (anchors.length) parts.push(`anchors:\n${anchors.join('\n')}`);
|
|
278
|
+
if (sourceHead) parts.push(`head:\n${sourceHead}`);
|
|
279
|
+
return parts.join('\n');
|
|
280
|
+
}
|