mixdog 0.9.2 → 0.9.4
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 +8 -3
- package/scripts/anthropic-maxtokens-test.mjs +119 -0
- package/scripts/bench/lead-review-tasks-r3.json +20 -0
- package/scripts/bench/lead-review-tasks.json +20 -0
- package/scripts/bench/r4-mixed-tasks.json +20 -0
- package/scripts/bench/review-tasks.json +20 -0
- package/scripts/bench/round-codex.json +114 -0
- package/scripts/bench/round-mixdog-lead-r3.json +269 -0
- package/scripts/bench/round-mixdog-lead.json +269 -0
- package/scripts/bench/round-mixdog.json +126 -0
- package/scripts/bench/round-r10-bigsample.json +679 -0
- package/scripts/bench/round-r11-codexalign.json +257 -0
- package/scripts/bench/round-r4-codex.json +114 -0
- package/scripts/bench/round-r4-mixed.json +225 -0
- package/scripts/bench/round-r5-gpt-lead.json +259 -0
- package/scripts/bench/round-r6-codex.json +114 -0
- package/scripts/bench/round-r6-solo.json +257 -0
- package/scripts/bench/round-r7-full.json +254 -0
- package/scripts/bench/round-r8-fulldefault.json +255 -0
- package/scripts/bench-run.mjs +215 -29
- package/scripts/build-tui.mjs +13 -1
- package/scripts/explore-bench.mjs +124 -0
- package/scripts/freevar-smoke.mjs +95 -0
- package/scripts/hook-bus-test.mjs +191 -0
- package/scripts/internal-comms-bench.mjs +1 -0
- package/scripts/internal-comms-smoke.mjs +10 -9
- package/scripts/mouse-probe.mjs +45 -0
- package/scripts/output-style-bench.mjs +13 -6
- package/scripts/output-style-smoke.mjs +4 -4
- package/scripts/path-suffix-test.mjs +57 -0
- package/scripts/provider-toolcall-test.mjs +7 -3
- package/scripts/recall-bench.mjs +207 -0
- package/scripts/recall-usecase-cases.json +18 -0
- package/scripts/recall-usecase-probe.json +6 -0
- package/scripts/session-bench.mjs +152 -6
- package/scripts/tool-smoke.mjs +30 -67
- package/scripts/tui-render-smoke.mjs +90 -0
- package/scripts/webhook-smoke.mjs +208 -0
- package/src/agents/debugger/AGENT.md +5 -2
- package/src/agents/heavy-worker/AGENT.md +21 -11
- package/src/agents/maintainer/AGENT.md +4 -0
- package/src/agents/reviewer/AGENT.md +3 -2
- package/src/agents/worker/AGENT.md +21 -11
- package/src/lib/rules-builder.cjs +4 -0
- package/src/mixdog-session-runtime.mjs +933 -3731
- package/src/output-styles/default.md +34 -9
- package/src/output-styles/{oneline.md → extreme-minimal.md} +5 -4
- package/src/output-styles/minimal.md +4 -1
- package/src/output-styles/simple.md +22 -7
- package/src/repl.mjs +5 -5
- package/src/rules/agent/00-common.md +2 -0
- package/src/rules/agent/30-explorer.md +8 -11
- package/src/rules/lead/lead-brief.md +12 -0
- package/src/rules/lead/lead-tool.md +2 -9
- package/src/rules/shared/01-tool.md +11 -5
- package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +25 -0
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +100 -23
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +6 -15
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +362 -0
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +410 -0
- package/src/runtime/agent/orchestrator/agent-trace.mjs +16 -735
- package/src/runtime/agent/orchestrator/config.mjs +69 -2
- package/src/runtime/agent/orchestrator/context/collect.mjs +51 -0
- package/src/runtime/agent/orchestrator/mcp/client.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +63 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +209 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +489 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +97 -1343
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +607 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +78 -10
- package/src/runtime/agent/orchestrator/providers/api-usage.mjs +1 -13
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +81 -0
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +248 -0
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +303 -0
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +505 -0
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +44 -1014
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +18 -4
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +32 -0
- package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +86 -11
- package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +348 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +54 -20
- package/src/runtime/agent/orchestrator/providers/openai-codex-model.mjs +108 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +19 -12
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +58 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +368 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +760 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +41 -1142
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +732 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +193 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +303 -2119
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +140 -995
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +227 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +67 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +436 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +1105 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +38 -12
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +7 -8
- package/src/runtime/agent/orchestrator/session/compact/budget.mjs +288 -0
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +85 -0
- package/src/runtime/agent/orchestrator/session/compact/engine.mjs +749 -0
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +315 -0
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +643 -0
- package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +326 -0
- package/src/runtime/agent/orchestrator/session/compact.mjs +40 -2282
- package/src/runtime/agent/orchestrator/session/loop/compact-debug.mjs +28 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +274 -0
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +61 -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 +47 -0
- package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +182 -0
- package/src/runtime/agent/orchestrator/session/loop/steering-ladder.mjs +173 -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/termination.mjs +58 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +52 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +239 -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 +409 -1304
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +471 -0
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +230 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +235 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +149 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +155 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +406 -0
- package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +80 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +303 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +210 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +226 -2114
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +189 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +74 -179
- package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +70 -20
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +22 -2
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +33 -42
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +241 -0
- package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +40 -0
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +42 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +11 -4
- package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +29 -0
- package/src/runtime/agent/orchestrator/tools/builtin/search-builders.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +126 -0
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +81 -87
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +161 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +108 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +78 -304
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +11 -6
- 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 +551 -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/keyword-match.mjs +82 -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 +1080 -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-columns.mjs +45 -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 +6 -6
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +36 -4277
- package/src/runtime/agent/orchestrator/tools/graph-binary-fetcher.mjs +6 -3
- package/src/runtime/agent/orchestrator/tools/patch/constants.mjs +9 -0
- package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +171 -0
- package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +471 -0
- package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +436 -0
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +342 -0
- package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +359 -0
- package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +340 -0
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +643 -0
- package/src/runtime/agent/orchestrator/tools/patch.mjs +36 -2959
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +1 -23
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +10 -74
- package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +77 -0
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +2 -4
- package/src/runtime/agent/orchestrator/tools/shell-state.mjs +154 -0
- package/src/runtime/channels/backends/discord-access.mjs +32 -0
- package/src/runtime/channels/backends/discord-attachments.mjs +65 -0
- package/src/runtime/channels/backends/discord-gateway.mjs +233 -0
- package/src/runtime/channels/backends/discord.mjs +12 -292
- package/src/runtime/channels/index.mjs +241 -894
- package/src/runtime/channels/lib/backend-dispatch.mjs +44 -0
- package/src/runtime/channels/lib/boot-profile.mjs +23 -0
- package/src/runtime/channels/lib/crash-log.mjs +106 -0
- package/src/runtime/channels/lib/event-pipeline.mjs +18 -1
- package/src/runtime/channels/lib/event-queue.mjs +63 -4
- package/src/runtime/channels/lib/inbound-routing.mjs +111 -0
- package/src/runtime/channels/lib/index-drop-trace.mjs +72 -0
- package/src/runtime/channels/lib/output-forwarder.mjs +9 -1
- package/src/runtime/channels/lib/owner-heartbeat.mjs +75 -0
- package/src/runtime/channels/lib/parent-bridge.mjs +88 -0
- package/src/runtime/channels/lib/runtime-paths.mjs +14 -4
- package/src/runtime/channels/lib/session-discovery.mjs +56 -4
- package/src/runtime/channels/lib/telegram-format.mjs +19 -22
- package/src/runtime/channels/lib/tool-dispatch.mjs +158 -0
- package/src/runtime/channels/lib/tool-format.mjs +1 -1
- package/src/runtime/channels/lib/transcript-discovery.mjs +4 -4
- package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +6 -3
- package/src/runtime/channels/lib/voice-transcription.mjs +179 -0
- package/src/runtime/channels/lib/webhook/deliveries.mjs +312 -0
- package/src/runtime/channels/lib/webhook/log.mjs +42 -0
- package/src/runtime/channels/lib/webhook/ngrok.mjs +181 -0
- package/src/runtime/channels/lib/webhook/signature.mjs +60 -0
- package/src/runtime/channels/lib/webhook.mjs +36 -570
- package/src/runtime/channels/lib/whisper-language.mjs +42 -0
- package/src/runtime/channels/tool-defs.mjs +11 -130
- package/src/runtime/memory/index.mjs +258 -2050
- package/src/runtime/memory/lib/core-memory-store.mjs +351 -1
- package/src/runtime/memory/lib/cycle-llm-adapters.mjs +58 -0
- package/src/runtime/memory/lib/cycle-scheduler.mjs +497 -0
- package/src/runtime/memory/lib/cycle-signatures.mjs +34 -0
- package/src/runtime/memory/lib/embedding-warmup.mjs +58 -0
- package/src/runtime/memory/lib/http-wire.mjs +57 -0
- package/src/runtime/memory/lib/memory-config-flags.mjs +91 -0
- package/src/runtime/memory/lib/memory-cycle.mjs +1 -1
- package/src/runtime/memory/lib/memory-cycle2-gate.mjs +515 -0
- package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +324 -0
- package/src/runtime/memory/lib/memory-cycle2-shared.mjs +18 -0
- package/src/runtime/memory/lib/memory-cycle2.mjs +72 -837
- package/src/runtime/memory/lib/memory-embed.mjs +149 -0
- package/src/runtime/memory/lib/memory-process-lock.mjs +162 -0
- package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +24 -0
- package/src/runtime/memory/lib/memory-recall-store.mjs +22 -2
- package/src/runtime/memory/lib/memory-retrievers.mjs +8 -0
- package/src/runtime/memory/lib/memory.mjs +20 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +1 -1
- package/src/runtime/memory/lib/promotion-fingerprint.mjs +50 -0
- package/src/runtime/memory/lib/query-handlers.mjs +780 -0
- package/src/runtime/memory/lib/recall-format.mjs +238 -0
- package/src/runtime/memory/lib/runtime-fetcher.mjs +8 -3
- package/src/runtime/memory/lib/transcript-ingest.mjs +425 -0
- package/src/runtime/memory/tool-defs.mjs +6 -14
- package/src/runtime/search/lib/http-fetch.mjs +274 -0
- package/src/runtime/search/lib/ssrf-guard.mjs +333 -0
- package/src/runtime/search/lib/web-tools.mjs +24 -602
- package/src/runtime/shared/abort-controller.mjs +1 -1
- package/src/runtime/shared/atomic-file.mjs +26 -1
- package/src/runtime/shared/background-tasks.mjs +2 -3
- package/src/runtime/shared/buffered-appender.mjs +149 -0
- package/src/runtime/shared/launcher-control.mjs +2 -2
- package/src/runtime/shared/task-notification-envelope.mjs +98 -0
- package/src/runtime/shared/tool-execution-contract.mjs +2 -2
- package/src/runtime/shared/tool-primitives.mjs +308 -0
- package/src/runtime/shared/tool-result-summary.mjs +515 -0
- package/src/runtime/shared/tool-surface.mjs +80 -898
- package/src/runtime/shared/transcript-writer.mjs +52 -2
- package/src/runtime/shared/update-checker.mjs +7 -4
- package/src/session-runtime/config-helpers.mjs +291 -0
- package/src/session-runtime/config-lifecycle.mjs +232 -0
- package/src/session-runtime/cwd-plugins.mjs +226 -0
- package/src/session-runtime/effort.mjs +128 -0
- package/src/session-runtime/fs-utils.mjs +10 -0
- package/src/session-runtime/mcp-glue.mjs +177 -0
- package/src/session-runtime/model-capabilities.mjs +130 -0
- package/src/session-runtime/model-recency.mjs +111 -0
- package/src/session-runtime/native-search.mjs +247 -0
- package/src/session-runtime/output-styles.mjs +126 -0
- package/src/session-runtime/plugin-mcp.mjs +114 -0
- package/src/session-runtime/prewarm.mjs +142 -0
- package/src/session-runtime/provider-models.mjs +278 -0
- package/src/session-runtime/provider-usage.mjs +120 -0
- package/src/session-runtime/quick-model-rows.mjs +170 -0
- package/src/session-runtime/quick-search-models.mjs +46 -0
- package/src/session-runtime/session-hooks.mjs +93 -0
- package/src/session-runtime/session-text.mjs +100 -0
- package/src/session-runtime/settings-api.mjs +319 -0
- package/src/session-runtime/statusline-route.mjs +35 -0
- package/src/session-runtime/tool-catalog.mjs +720 -0
- package/src/session-runtime/tool-defs.mjs +84 -0
- package/src/session-runtime/warmup-schedulers.mjs +201 -0
- package/src/session-runtime/workflow.mjs +358 -0
- package/src/standalone/agent-tool/helpers.mjs +237 -0
- package/src/standalone/agent-tool/notify.mjs +107 -0
- package/src/standalone/agent-tool/provider-init.mjs +143 -0
- package/src/standalone/agent-tool/render.mjs +152 -0
- package/src/standalone/agent-tool/tool-def.mjs +55 -0
- package/src/standalone/agent-tool.mjs +155 -677
- package/src/standalone/channel-worker.mjs +7 -9
- package/src/standalone/explore-tool.mjs +40 -12
- package/src/standalone/hook-bus/config.mjs +207 -0
- package/src/standalone/hook-bus/constants.mjs +90 -0
- package/src/standalone/hook-bus/handlers.mjs +481 -0
- package/src/standalone/hook-bus/payload.mjs +31 -0
- package/src/standalone/hook-bus/rules.mjs +77 -0
- package/src/standalone/hook-bus.mjs +110 -746
- package/src/standalone/memory-runtime-proxy.mjs +7 -0
- package/src/standalone/opencode-go-login.mjs +125 -0
- package/src/standalone/provider-admin.mjs +15 -19
- package/src/standalone/usage-dashboard.mjs +3 -1
- package/src/tui/App.jsx +1163 -7571
- package/src/tui/app/app-format.mjs +206 -0
- package/src/tui/app/channel-pickers.mjs +510 -0
- package/src/tui/app/clipboard.mjs +67 -0
- package/src/tui/app/core-memory-picker.mjs +210 -0
- package/src/tui/app/extension-pickers.mjs +506 -0
- package/src/tui/app/input-parsers.mjs +193 -0
- package/src/tui/app/maintenance-pickers.mjs +324 -0
- package/src/tui/app/model-options.mjs +330 -0
- package/src/tui/app/model-picker.mjs +365 -0
- package/src/tui/app/onboarding-steps.mjs +400 -0
- package/src/tui/app/project-picker.mjs +247 -0
- package/src/tui/app/provider-setup-picker.mjs +580 -0
- package/src/tui/app/resume-picker.mjs +55 -0
- package/src/tui/app/route-pickers.mjs +419 -0
- package/src/tui/app/settings-picker.mjs +490 -0
- package/src/tui/app/slash-commands.mjs +101 -0
- package/src/tui/app/slash-dispatch.mjs +427 -0
- package/src/tui/app/text-layout.mjs +46 -0
- package/src/tui/app/theme-effort-pickers.mjs +154 -0
- package/src/tui/app/transcript-window.mjs +671 -0
- package/src/tui/app/use-mouse-input.mjs +460 -0
- package/src/tui/app/use-prompt-handlers.mjs +310 -0
- package/src/tui/app/use-transcript-scroll.mjs +510 -0
- package/src/tui/app/use-transcript-window.mjs +589 -0
- package/src/tui/components/ConfirmBar.jsx +1 -1
- package/src/tui/components/Picker.jsx +32 -4
- package/src/tui/components/PromptInput.jsx +259 -80
- package/src/tui/components/SlashCommandPalette.jsx +8 -1
- package/src/tui/components/StatusLine.jsx +63 -12
- package/src/tui/components/TextEntryPanel.jsx +11 -0
- package/src/tui/components/ToolExecution.jsx +56 -588
- package/src/tui/components/TranscriptItem.jsx +105 -0
- package/src/tui/components/UsagePanel.jsx +18 -4
- package/src/tui/components/prompt-input/edit-helpers.mjs +72 -0
- package/src/tui/components/prompt-input/voice-indicator.mjs +39 -0
- package/src/tui/components/tool-execution/ResultBody.jsx +56 -0
- package/src/tui/components/tool-execution/surface-detail.mjs +405 -0
- package/src/tui/components/tool-execution/text-format.mjs +161 -0
- package/src/tui/components/tool-output-format.mjs +2 -2
- package/src/tui/display-width.mjs +20 -3
- package/src/tui/dist/index.mjs +18034 -17188
- package/src/tui/engine/agent-envelope.mjs +296 -0
- package/src/tui/engine/agent-job-feed.mjs +133 -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/notification-plan.mjs +76 -0
- package/src/tui/engine/queue-helpers.mjs +161 -0
- package/src/tui/engine/render-timing.mjs +17 -0
- package/src/tui/engine/session-stats.mjs +46 -0
- package/src/tui/engine/tool-approval.mjs +94 -0
- package/src/tui/engine/tool-call-fields.mjs +23 -0
- package/src/tui/engine/tool-card-results.mjs +234 -0
- package/src/tui/engine/tool-result-status.mjs +135 -0
- package/src/tui/engine/tool-result-text.mjs +126 -0
- package/src/tui/engine.mjs +405 -1385
- package/src/tui/figures.mjs +5 -0
- package/src/tui/index.jsx +105 -0
- package/src/tui/input-editing.mjs +60 -10
- package/src/tui/keyboard-protocol.mjs +2 -2
- package/src/tui/lib/voice-recorder.mjs +35 -19
- package/src/tui/markdown/format-token.mjs +11 -9
- package/src/tui/paste-attachments.mjs +38 -0
- package/src/tui/statusline-ansi-bridge.mjs +11 -3
- package/src/tui/theme.mjs +6 -0
- package/src/tui/themes/base.mjs +2 -2
- package/src/tui/themes/kanagawa.mjs +4 -4
- package/src/tui/themes/teal.mjs +4 -5
- package/src/tui/themes/utils.mjs +1 -1
- package/src/ui/statusline-agents.mjs +213 -0
- package/src/ui/statusline-format.mjs +146 -0
- package/src/ui/statusline-segments.mjs +148 -0
- package/src/ui/statusline.mjs +77 -462
- package/src/ui/tool-card.mjs +0 -1
- package/src/vendor/statusline/bin/statusline-route.mjs +15 -2
- package/src/workflows/default/WORKFLOW.md +16 -9
- package/src/workflows/sequential/WORKFLOW.md +16 -11
- package/src/workflows/solo/WORKFLOW.md +5 -1
- package/vendor/ink/build/display-width.js +19 -3
- package/vendor/ink/build/ink.js +103 -6
- package/vendor/ink/build/log-update.js +17 -3
- package/vendor/ink/build/wrap-text.js +125 -0
- package/scripts/_test-folder-dialog.mjs +0 -30
- package/scripts/fix-brief-fn.mjs +0 -35
- package/scripts/fix-format-tool-surface.mjs +0 -24
- package/scripts/fix-tool-exec-visible.mjs +0 -42
- package/scripts/patch-agent-brief.mjs +0 -48
- package/scripts/patch-app.mjs +0 -21
- package/scripts/patch-app2.mjs +0 -18
- package/scripts/patch-dist-brief.mjs +0 -96
- package/scripts/patch-tool-exec.mjs +0 -70
- package/src/examples/schedules/SCHEDULE.example.md +0 -32
- package/src/examples/webhooks/WEBHOOK.example.md +0 -40
- package/src/runtime/agent/orchestrator/session/manager.reactive-persist.test.mjs +0 -107
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +0 -143
- package/src/runtime/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +0 -285
- package/src/runtime/agent/orchestrator/tools/builtin/open-config-tool.mjs +0 -26
- package/src/runtime/shared/channel-notification-routing.test.mjs +0 -45
- package/src/runtime/shared/tool-execution-contract.test.mjs +0 -183
- package/src/standalone/agent-task-status.test.mjs +0 -76
- package/src/tui/components/tool-output-format.test.mjs +0 -399
- package/src/tui/display-width.test.mjs +0 -35
- package/src/tui/engine-runtime-notification.test.mjs +0 -115
- package/src/tui/engine-tool-result-text.test.mjs +0 -75
- package/src/tui/markdown/format-token.test.mjs +0 -354
- package/src/tui/markdown/render-ansi.test.mjs +0 -108
- package/src/tui/markdown/stream-fence.test.mjs +0 -26
- package/src/tui/markdown/streaming-markdown.test.mjs +0 -70
- package/src/tui/prompt-history-store.test.mjs +0 -52
- package/src/tui/statusline-ansi-bridge.test.mjs +0 -159
- package/src/tui/transcript-tool-failures.test.mjs +0 -111
- package/src/ui/markdown.test.mjs +0 -70
- package/src/ui/statusline-context-label.test.mjs +0 -15
- package/src/vendor/statusline/bin/statusline-lib.mjs +0 -186
- package/src/vendor/statusline/bin/statusline-route.test.mjs +0 -80
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
// Native mixdog-graph binary runner — single source of truth for per-file
|
|
2
|
+
// parsing. NO JS parse fallback: absent binary throws. Extracted verbatim
|
|
3
|
+
// from code-graph.mjs, except _graphBinaryPath's local-build relative path,
|
|
4
|
+
// which gains one extra `../` because this module sits one directory deeper
|
|
5
|
+
// (tools/code-graph/ vs tools/). The resolved absolute path is unchanged.
|
|
6
|
+
import { resolve as pathResolve, dirname } from 'node:path';
|
|
7
|
+
import { existsSync } from 'node:fs';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
import { getPluginData } from '../../config.mjs';
|
|
10
|
+
import { ensureGraphBinary, findCachedGraphBinary } from '../graph-binary-fetcher.mjs';
|
|
11
|
+
import { acquire as acquireChildSpawnSlot } from '../../../../shared/child-spawn-gate.mjs';
|
|
12
|
+
import { CODE_GRAPH_BINARY_TIMEOUT_MS, CODE_GRAPH_MAX_FILES } from './constants.mjs';
|
|
13
|
+
|
|
14
|
+
// ── Native graph binary (mixdog-graph) — single source of truth for
|
|
15
|
+
// per-file parsing. There is NO JS parsing fallback: if the binary is
|
|
16
|
+
// absent the build throws so the caller surfaces a clear, fixable error
|
|
17
|
+
// instead of silently degrading to a slow path.
|
|
18
|
+
function _graphBinaryPath() {
|
|
19
|
+
const override = process.env.MIXDOG_GRAPH_BIN;
|
|
20
|
+
if (override && existsSync(override)) return override;
|
|
21
|
+
// fileURLToPath correctly decodes percent-encoded bytes (spaces, non-ASCII)
|
|
22
|
+
// and strips the leading-slash/drive-letter quirk on Windows. Using
|
|
23
|
+
// URL.pathname directly leaves `%20` etc. encoded, breaking paths with
|
|
24
|
+
// spaces or non-ASCII characters.
|
|
25
|
+
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
const binName = process.platform === 'win32' ? 'mixdog-graph.exe' : 'mixdog-graph';
|
|
27
|
+
// Prefer a local cargo build, then a previously fetched/cached prebuilt.
|
|
28
|
+
// This module is one dir deeper than the legacy code-graph.mjs, so the
|
|
29
|
+
// relative walk to repo-root native/ needs six `../` hops
|
|
30
|
+
// (code-graph → tools → orchestrator → agent → runtime → src → root).
|
|
31
|
+
const localBuild = pathResolve(moduleDir, '../../../../../../native/mixdog-graph/target/release', binName);
|
|
32
|
+
if (existsSync(localBuild)) return localBuild;
|
|
33
|
+
try { return findCachedGraphBinary(getPluginData()); } catch { return null; }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function _runGraphBinaryJsonl(absRoot, extraArgs, stdinLines = null) {
|
|
37
|
+
let binPath = _graphBinaryPath();
|
|
38
|
+
if (!binPath) {
|
|
39
|
+
// No local build or cached binary — fetch the prebuilt from the release
|
|
40
|
+
// manifest (sha256-verified). No JS parse fallback: if the platform has
|
|
41
|
+
// no asset or the download fails, the build throws with a fixable error.
|
|
42
|
+
try {
|
|
43
|
+
binPath = await ensureGraphBinary(getPluginData());
|
|
44
|
+
} catch (err) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`[code-graph] mixdog-graph binary unavailable and could not be fetched: ${err?.message || err}. `
|
|
47
|
+
+ 'Build it (cargo build --release in native/mixdog-graph) or check network/release manifest.',
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const { spawn } = await import('node:child_process');
|
|
52
|
+
const timeoutMs = CODE_GRAPH_BINARY_TIMEOUT_MS;
|
|
53
|
+
let retried = false;
|
|
54
|
+
|
|
55
|
+
// Inner spawn + promise — extracted so we can retry once on EAGAIN.
|
|
56
|
+
//
|
|
57
|
+
// child-spawn-gate is NOT acquired here. This function runs inside the
|
|
58
|
+
// code-graph prewarm WORKER THREAD (via _buildCodeGraph), and worker_threads
|
|
59
|
+
// do not share module-level state with the main thread — acquiring here would
|
|
60
|
+
// create a SECOND, independent semaphore that never coordinates with the
|
|
61
|
+
// main-thread rg gate. Instead the gate is held on the MAIN THREAD across the
|
|
62
|
+
// whole graph-build worker's lifetime (see buildCodeGraphAsync). The binary
|
|
63
|
+
// child is spawned exclusively from this worker path, so one main-side slot
|
|
64
|
+
// per worker correctly bounds native graph spawns against rg.
|
|
65
|
+
const _spawnOnce = () => new Promise((resolve, reject) => {
|
|
66
|
+
// When stdinLines is supplied (--files mode), stream one JSON object per
|
|
67
|
+
// line to the child's STDIN — the reused nodes' metadata — so Rust can
|
|
68
|
+
// resolve imports across the WHOLE tree (fresh + reused) while only
|
|
69
|
+
// full-parsing the changed subset passed as argv.
|
|
70
|
+
const wantsStdin = Array.isArray(stdinLines);
|
|
71
|
+
const proc = spawn(binPath, [absRoot, ...extraArgs], {
|
|
72
|
+
stdio: [wantsStdin ? 'pipe' : 'ignore', 'pipe', 'pipe'],
|
|
73
|
+
// windowsHide: native code-graph binary is a console exe; without this each
|
|
74
|
+
// call flashes a console window when spawned under the detached daemon.
|
|
75
|
+
windowsHide: true,
|
|
76
|
+
});
|
|
77
|
+
const chunks = [];
|
|
78
|
+
let stderrText = '';
|
|
79
|
+
const STDERR_CAP = 8 * 1024;
|
|
80
|
+
let settled = false;
|
|
81
|
+
let timedOut = false;
|
|
82
|
+
|
|
83
|
+
// ── timeout + kill helpers (mirrors rg-runner's _killRgProc/_escalateRgKill) ──
|
|
84
|
+
let timeoutTimer = null;
|
|
85
|
+
let killGraceTimer = null;
|
|
86
|
+
let forceSettleTimer = null;
|
|
87
|
+
|
|
88
|
+
const _procGone = () => proc.exitCode != null || proc.signalCode != null;
|
|
89
|
+
|
|
90
|
+
const _escalateKill = () => {
|
|
91
|
+
if (_procGone()) return;
|
|
92
|
+
const pid = proc.pid;
|
|
93
|
+
if (!pid) return;
|
|
94
|
+
try {
|
|
95
|
+
if (process.platform === 'win32') {
|
|
96
|
+
spawn('taskkill', ['/pid', String(pid), '/t', '/f'], {
|
|
97
|
+
windowsHide: true,
|
|
98
|
+
stdio: 'ignore',
|
|
99
|
+
});
|
|
100
|
+
} else {
|
|
101
|
+
try { proc.kill('SIGKILL'); } catch { /* ignore */ }
|
|
102
|
+
}
|
|
103
|
+
} catch { /* ignore */ }
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const _killProc = () => {
|
|
107
|
+
if (_procGone()) return;
|
|
108
|
+
try { proc.kill('SIGTERM'); } catch { /* ignore */ }
|
|
109
|
+
if (killGraceTimer) {
|
|
110
|
+
clearTimeout(killGraceTimer);
|
|
111
|
+
killGraceTimer = null;
|
|
112
|
+
}
|
|
113
|
+
killGraceTimer = setTimeout(() => {
|
|
114
|
+
killGraceTimer = null;
|
|
115
|
+
_escalateKill();
|
|
116
|
+
}, 3000);
|
|
117
|
+
if (killGraceTimer.unref) killGraceTimer.unref();
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const _clearTimers = () => {
|
|
121
|
+
if (timeoutTimer) {
|
|
122
|
+
clearTimeout(timeoutTimer);
|
|
123
|
+
timeoutTimer = null;
|
|
124
|
+
}
|
|
125
|
+
if (killGraceTimer) {
|
|
126
|
+
clearTimeout(killGraceTimer);
|
|
127
|
+
killGraceTimer = null;
|
|
128
|
+
}
|
|
129
|
+
if (forceSettleTimer) {
|
|
130
|
+
clearTimeout(forceSettleTimer);
|
|
131
|
+
forceSettleTimer = null;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Arm timeout — unref so it doesn't keep the process alive. On timeout we
|
|
136
|
+
// start SIGTERM→grace→force-kill but do NOT settle yet: the promise stays
|
|
137
|
+
// pending until the child's 'close' fires (so the build worker — and the
|
|
138
|
+
// main-thread gate slot it holds — is only released once the process is
|
|
139
|
+
// actually gone). A separate force-settle deadline guarantees the promise
|
|
140
|
+
// still resolves if 'close' never arrives. Mirrors rg-runner exactly.
|
|
141
|
+
timeoutTimer = setTimeout(() => {
|
|
142
|
+
timeoutTimer = null;
|
|
143
|
+
timedOut = true;
|
|
144
|
+
_killProc();
|
|
145
|
+
// Hard backstop: if 'close' never fires after the kill escalation,
|
|
146
|
+
// escalate again and settle so we never hang (and never release the
|
|
147
|
+
// gate while the child is provably still alive without a final attempt).
|
|
148
|
+
if (forceSettleTimer) clearTimeout(forceSettleTimer);
|
|
149
|
+
forceSettleTimer = setTimeout(() => {
|
|
150
|
+
forceSettleTimer = null;
|
|
151
|
+
if (settled) return;
|
|
152
|
+
_escalateKill();
|
|
153
|
+
settled = true;
|
|
154
|
+
_clearTimers();
|
|
155
|
+
reject(new Error(`[code-graph] mixdog-graph timed out after ${timeoutMs}ms`));
|
|
156
|
+
}, 5000);
|
|
157
|
+
if (forceSettleTimer.unref) forceSettleTimer.unref();
|
|
158
|
+
}, timeoutMs);
|
|
159
|
+
if (timeoutTimer.unref) timeoutTimer.unref();
|
|
160
|
+
|
|
161
|
+
proc.stdout.on('data', (c) => chunks.push(c));
|
|
162
|
+
proc.stderr.on('data', (c) => {
|
|
163
|
+
if (stderrText.length >= STDERR_CAP) return;
|
|
164
|
+
const piece = c.toString('utf8');
|
|
165
|
+
const room = STDERR_CAP - stderrText.length;
|
|
166
|
+
stderrText += piece.length > room ? piece.slice(0, room) : piece;
|
|
167
|
+
});
|
|
168
|
+
proc.on('error', (err) => {
|
|
169
|
+
if (settled) return;
|
|
170
|
+
settled = true;
|
|
171
|
+
_clearTimers();
|
|
172
|
+
reject(err);
|
|
173
|
+
});
|
|
174
|
+
if (wantsStdin) {
|
|
175
|
+
proc.stdin.on('error', () => { /* child may close stdin early; ignore EPIPE */ });
|
|
176
|
+
proc.stdin.write(stdinLines.length ? `${stdinLines.join('\n')}\n` : '');
|
|
177
|
+
proc.stdin.end();
|
|
178
|
+
}
|
|
179
|
+
proc.on('close', (code) => {
|
|
180
|
+
if (settled) return;
|
|
181
|
+
settled = true;
|
|
182
|
+
_clearTimers();
|
|
183
|
+
if (timedOut) {
|
|
184
|
+
// Our timeout kill won the race: the child is gone now, so the gate
|
|
185
|
+
// slot releases here (not at timeout-fire time). Report as a timeout.
|
|
186
|
+
reject(new Error(`[code-graph] mixdog-graph timed out after ${timeoutMs}ms`));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (code !== 0) {
|
|
190
|
+
reject(new Error(`[code-graph] mixdog-graph exited ${code}: ${stderrText.trim().slice(0, 200)}`));
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const out = [];
|
|
194
|
+
const buf = Buffer.concat(chunks).toString('utf8');
|
|
195
|
+
for (const line of buf.split('\n')) {
|
|
196
|
+
const trimmed = line.trim();
|
|
197
|
+
if (!trimmed) continue;
|
|
198
|
+
try {
|
|
199
|
+
const rec = JSON.parse(trimmed);
|
|
200
|
+
if (rec && typeof rec.rel === 'string') out.push(rec);
|
|
201
|
+
} catch { /* skip malformed line */ }
|
|
202
|
+
}
|
|
203
|
+
resolve(out);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Outer call with one EAGAIN retry (mirrors rg-runner runRg / runRgWindowedLines).
|
|
208
|
+
try {
|
|
209
|
+
return await _spawnOnce();
|
|
210
|
+
} catch (err) {
|
|
211
|
+
if (!retried && (err?.code === 'EAGAIN' || /EAGAIN/i.test(String(err?.message || err?.stderr || '')))) {
|
|
212
|
+
retried = true;
|
|
213
|
+
return _spawnOnce();
|
|
214
|
+
}
|
|
215
|
+
throw err;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
export function _runGraphManifest(absRoot) { return _runGraphBinaryJsonl(absRoot, ['--manifest']); }
|
|
219
|
+
export function _runGraphWalk(absRoot) { return _runGraphBinaryJsonl(absRoot, []); }
|
|
220
|
+
// --files (design A: full-graph resolution) full-parses only `rels` (argv) but
|
|
221
|
+
// resolves imports across the WHOLE tree. The reused nodes' metas are streamed
|
|
222
|
+
// to the child via STDIN as JSONL — one JSON object per line:
|
|
223
|
+
// {rel, lang, rawImports, packageName, namespaceName, goPackageName,
|
|
224
|
+
// topLevelTypes}. Rust builds the index + resolves over ALL nodes (fresh +
|
|
225
|
+
// reused) and emits fresh rels as full records, reused rels as lightweight
|
|
226
|
+
// {rel, resolvedImports, importedBy}.
|
|
227
|
+
export function _runGraphFiles(absRoot, rels, reusedMetas) {
|
|
228
|
+
const lines = Array.isArray(reusedMetas)
|
|
229
|
+
? reusedMetas.map((m) => JSON.stringify({
|
|
230
|
+
rel: m.rel,
|
|
231
|
+
lang: m.lang,
|
|
232
|
+
rawImports: Array.isArray(m.rawImports) ? m.rawImports : [],
|
|
233
|
+
packageName: m.packageName || '',
|
|
234
|
+
namespaceName: m.namespaceName || '',
|
|
235
|
+
goPackageName: m.goPackageName || '',
|
|
236
|
+
topLevelTypes: Array.isArray(m.topLevelTypes) ? m.topLevelTypes : [],
|
|
237
|
+
}))
|
|
238
|
+
: [];
|
|
239
|
+
return _runGraphBinaryJsonl(absRoot, ['--files', ...rels], lines);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Map a Rust FileRecord (rel/lang/fp/tokens/rawImports/resolvedImports/
|
|
243
|
+
// importedBy/...) onto the JS fileInfo shape the graph assembler expects.
|
|
244
|
+
// Import resolution — including Go module paths — now happens entirely in
|
|
245
|
+
// Rust; resolvedImports/importedBy are repo-relative path lists passed
|
|
246
|
+
// straight through.
|
|
247
|
+
export function _fileInfoFromRustRecord(rec, absRoot) {
|
|
248
|
+
const rel = rec.rel;
|
|
249
|
+
const abs = pathResolve(absRoot, rel);
|
|
250
|
+
const lang = rec.lang;
|
|
251
|
+
return {
|
|
252
|
+
abs,
|
|
253
|
+
rel,
|
|
254
|
+
lang,
|
|
255
|
+
fingerprint: typeof rec.fp === 'string' ? rec.fp : '',
|
|
256
|
+
sourceText: null,
|
|
257
|
+
rawImports: Array.isArray(rec.rawImports) ? rec.rawImports : [],
|
|
258
|
+
resolvedImports: Array.isArray(rec.resolvedImports)
|
|
259
|
+
? rec.resolvedImports.filter((v) => typeof v === 'string')
|
|
260
|
+
: [],
|
|
261
|
+
importedBy: Array.isArray(rec.importedBy)
|
|
262
|
+
? rec.importedBy.filter((v) => typeof v === 'string')
|
|
263
|
+
: [],
|
|
264
|
+
packageName: typeof rec.packageName === 'string' ? rec.packageName : '',
|
|
265
|
+
namespaceName: typeof rec.namespaceName === 'string' ? rec.namespaceName : '',
|
|
266
|
+
goPackageName: typeof rec.goPackageName === 'string' ? rec.goPackageName : '',
|
|
267
|
+
topLevelTypes: Array.isArray(rec.topLevelTypes) ? rec.topLevelTypes : [],
|
|
268
|
+
tokenSymbols: Array.isArray(rec.tokens) ? rec.tokens : null,
|
|
269
|
+
symbols: Array.isArray(rec.symbols) ? rec.symbols : [],
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Reuse a node from the previous graph whose fp is unchanged — skips both
|
|
274
|
+
// the Rust call and re-parsing for files that did not change.
|
|
275
|
+
export function _reuseFileInfo(prevNode, previousGraph, absRoot) {
|
|
276
|
+
const rel = prevNode.rel;
|
|
277
|
+
const fp = prevNode.fingerprint || '';
|
|
278
|
+
const cachedText = previousGraph?._sourceTextCache?.get(rel);
|
|
279
|
+
return {
|
|
280
|
+
abs: prevNode.abs || pathResolve(absRoot, rel),
|
|
281
|
+
rel,
|
|
282
|
+
lang: prevNode.lang,
|
|
283
|
+
fingerprint: fp,
|
|
284
|
+
sourceText: cachedText?.fingerprint === fp ? cachedText.text : null,
|
|
285
|
+
rawImports: Array.isArray(prevNode.rawImports) ? prevNode.rawImports : [],
|
|
286
|
+
resolvedImports: Array.isArray(prevNode.resolvedImportsRel) ? prevNode.resolvedImportsRel : [],
|
|
287
|
+
importedBy: Array.isArray(prevNode.importedBy) ? prevNode.importedBy : [],
|
|
288
|
+
packageName: prevNode.packageName || '',
|
|
289
|
+
namespaceName: prevNode.namespaceName || '',
|
|
290
|
+
goPackageName: prevNode.goPackageName || '',
|
|
291
|
+
topLevelTypes: Array.isArray(prevNode.topLevelTypes) ? prevNode.topLevelTypes : [],
|
|
292
|
+
tokenSymbols: Array.isArray(prevNode.tokenSymbols) ? prevNode.tokenSymbols : null,
|
|
293
|
+
symbols: Array.isArray(prevNode.symbols) ? prevNode.symbols : [],
|
|
294
|
+
};
|
|
295
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// Graph (de)serialization, runtime-cache lifecycle, and signature hashing.
|
|
2
|
+
// Extracted verbatim from code-graph.mjs. Graph shape: { cwd, nodes:
|
|
3
|
+
// Map<rel,node>, reverse: Map<rel,Set<rel>>, schemaVersion, builtAt,
|
|
4
|
+
// signature, +runtime caches }. Persisted form omits empty fields.
|
|
5
|
+
import { createHash } from 'node:crypto';
|
|
6
|
+
import { resolve as pathResolve } from 'node:path';
|
|
7
|
+
import { SYMBOL_SCHEMA_VERSION, CODE_GRAPH_MAX_FILES } from './constants.mjs';
|
|
8
|
+
|
|
9
|
+
export function _computeGraphSignature(fileMetas) {
|
|
10
|
+
const hash = createHash('sha1');
|
|
11
|
+
hash.update(`${SYMBOL_SCHEMA_VERSION}\n`);
|
|
12
|
+
// R5-③: include rel/path alongside fp so renames and path-swaps (same
|
|
13
|
+
// bytes moved to a different rel, or two files exchanging paths) flip
|
|
14
|
+
// the signature and invalidate the memory/disk cache checks at the
|
|
15
|
+
// call sites just below in buildCodeGraphAsync. Without rel, an fp-only
|
|
16
|
+
// hash collides across rename pairs and the cache serves stale graph
|
|
17
|
+
// topology where node.rel no longer matches what's on disk.
|
|
18
|
+
for (const meta of fileMetas) hash.update(`${meta.rel || ''}\0${meta.fp}\n`);
|
|
19
|
+
return hash.digest('hex');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function _serializeGraph(graph) {
|
|
23
|
+
// Compact-on-disk: omit empty / falsy fields. Saves ~30-50% on disk
|
|
24
|
+
// for typical mixed-language graphs because most nodes don't carry
|
|
25
|
+
// packageName / namespaceName / topLevelTypes. Smaller
|
|
26
|
+
// payload → faster JSON.parse on cold-process boot. _deserializeGraph
|
|
27
|
+
// tolerates missing fields by defaulting to '' / [].
|
|
28
|
+
return {
|
|
29
|
+
schemaVersion: SYMBOL_SCHEMA_VERSION,
|
|
30
|
+
builtAt: Number(graph?.builtAt || Date.now()),
|
|
31
|
+
signature: String(graph?.signature || ''),
|
|
32
|
+
truncated: Boolean(graph?.truncated),
|
|
33
|
+
maxFiles: CODE_GRAPH_MAX_FILES,
|
|
34
|
+
nodes: [...(graph?.nodes?.values?.() || [])].map((node) => {
|
|
35
|
+
const out = {
|
|
36
|
+
rel: node.rel,
|
|
37
|
+
lang: node.lang,
|
|
38
|
+
};
|
|
39
|
+
if (node.fingerprint) out.fingerprint = node.fingerprint;
|
|
40
|
+
if (Array.isArray(node.rawImports) && node.rawImports.length) out.rawImports = node.rawImports;
|
|
41
|
+
if (Array.isArray(node.resolvedImportsRel) && node.resolvedImportsRel.length) {
|
|
42
|
+
out.resolvedImports = node.resolvedImportsRel;
|
|
43
|
+
}
|
|
44
|
+
if (Array.isArray(node.importedBy) && node.importedBy.length) {
|
|
45
|
+
out.importedBy = node.importedBy;
|
|
46
|
+
}
|
|
47
|
+
if (node.packageName) out.packageName = node.packageName;
|
|
48
|
+
if (node.namespaceName) out.namespaceName = node.namespaceName;
|
|
49
|
+
if (node.goPackageName) out.goPackageName = node.goPackageName;
|
|
50
|
+
if (Array.isArray(node.topLevelTypes) && node.topLevelTypes.length) {
|
|
51
|
+
out.topLevelTypes = node.topLevelTypes;
|
|
52
|
+
}
|
|
53
|
+
if (Array.isArray(node.tokenSymbols) && node.tokenSymbols.length) {
|
|
54
|
+
out.tokenSymbols = node.tokenSymbols;
|
|
55
|
+
}
|
|
56
|
+
if (Array.isArray(node.symbols) && node.symbols.length) {
|
|
57
|
+
out.symbols = node.symbols;
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function _deserializeGraph(cwd, payload) {
|
|
65
|
+
if (!payload || typeof payload !== 'object' || !Array.isArray(payload.nodes)) return null;
|
|
66
|
+
const nodes = new Map();
|
|
67
|
+
const reverse = new Map();
|
|
68
|
+
for (const item of payload.nodes) {
|
|
69
|
+
if (!item || typeof item.rel !== 'string' || typeof item.lang !== 'string') continue;
|
|
70
|
+
// Persisted fields are repo-relative, mirroring the live build. The
|
|
71
|
+
// JS resolution layer is gone — resolvedImports/resolvedImportsRel are
|
|
72
|
+
// restored straight from disk; the reverse index is rederived below from
|
|
73
|
+
// the forward edges of every node.
|
|
74
|
+
const resolvedImportsRel = Array.isArray(item.resolvedImports) ? item.resolvedImports.filter((v) => typeof v === 'string') : [];
|
|
75
|
+
const importedBy = Array.isArray(item.importedBy) ? item.importedBy.filter((v) => typeof v === 'string') : [];
|
|
76
|
+
const node = {
|
|
77
|
+
abs: pathResolve(cwd, item.rel),
|
|
78
|
+
rel: item.rel,
|
|
79
|
+
lang: item.lang,
|
|
80
|
+
fingerprint: item.fingerprint || '',
|
|
81
|
+
rawImports: Array.isArray(item.rawImports) ? item.rawImports : [],
|
|
82
|
+
resolvedImportsRel,
|
|
83
|
+
resolvedImports: resolvedImportsRel.map((rel) => pathResolve(cwd, rel)),
|
|
84
|
+
importedBy,
|
|
85
|
+
packageName: item.packageName || '',
|
|
86
|
+
namespaceName: item.namespaceName || '',
|
|
87
|
+
goPackageName: item.goPackageName || '',
|
|
88
|
+
topLevelTypes: Array.isArray(item.topLevelTypes) ? item.topLevelTypes : [],
|
|
89
|
+
tokenSymbols: Array.isArray(item.tokenSymbols) ? item.tokenSymbols : null,
|
|
90
|
+
symbols: Array.isArray(item.symbols) ? item.symbols : [],
|
|
91
|
+
};
|
|
92
|
+
nodes.set(node.rel, node);
|
|
93
|
+
// reverse is derived from the FORWARD edges of every node, not from the
|
|
94
|
+
// persisted importedBy. On the incremental --files path reused nodes carry
|
|
95
|
+
// a stale importedBy, so a fresh edge A→B (A parsed, B reused) would drop
|
|
96
|
+
// B's reverse entry. Walking resolvedImportsRel keeps reverse self-consistent.
|
|
97
|
+
for (const rel of resolvedImportsRel) {
|
|
98
|
+
if (!reverse.has(rel)) reverse.set(rel, new Set());
|
|
99
|
+
reverse.get(rel).add(node.rel);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const graph = _attachGraphRuntimeCaches({
|
|
103
|
+
cwd,
|
|
104
|
+
nodes,
|
|
105
|
+
reverse,
|
|
106
|
+
// Pre-endLine disk payloads have no schemaVersion → null → dropped by the
|
|
107
|
+
// previousGraph schema guard so their endLine-less nodes never seed reuse.
|
|
108
|
+
schemaVersion: typeof payload.schemaVersion === 'string' ? payload.schemaVersion : null,
|
|
109
|
+
builtAt: Number(payload.builtAt || Date.now()),
|
|
110
|
+
signature: String(payload.signature || ''),
|
|
111
|
+
});
|
|
112
|
+
// Restore the truncation flag persisted from the live build so disk-cache
|
|
113
|
+
// hits keep emitting the WARN line in find_symbol/overview output instead
|
|
114
|
+
// of silently working with a partial graph.
|
|
115
|
+
if (graph && payload.truncated) graph.truncated = true;
|
|
116
|
+
return graph;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function _attachGraphRuntimeCaches(graph) {
|
|
120
|
+
if (!graph || typeof graph !== 'object') return graph;
|
|
121
|
+
if (!graph._referenceSearchCache) graph._referenceSearchCache = new Map();
|
|
122
|
+
if (!graph._maskedLinesCache) graph._maskedLinesCache = new Map();
|
|
123
|
+
if (!graph._sourceLinesCache) graph._sourceLinesCache = new Map();
|
|
124
|
+
if (!graph._sourceTextCache) graph._sourceTextCache = new Map();
|
|
125
|
+
if (!graph._symbolTokenIndex) graph._symbolTokenIndex = new Map();
|
|
126
|
+
if (typeof graph._symbolTokenIndexDirty !== 'boolean') graph._symbolTokenIndexDirty = true;
|
|
127
|
+
return graph;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function _estimateGraphRuntimeCacheBytes(graph) {
|
|
131
|
+
if (!graph) return 0;
|
|
132
|
+
let total = 0;
|
|
133
|
+
for (const entry of graph._sourceTextCache?.values() || []) {
|
|
134
|
+
total += Buffer.byteLength(String(entry?.text || ''), 'utf8');
|
|
135
|
+
}
|
|
136
|
+
for (const lines of graph._maskedLinesCache?.values() || []) {
|
|
137
|
+
if (!Array.isArray(lines)) continue;
|
|
138
|
+
for (const line of lines) total += Buffer.byteLength(String(line || ''), 'utf8');
|
|
139
|
+
}
|
|
140
|
+
for (const lines of graph._sourceLinesCache?.values() || []) {
|
|
141
|
+
if (!Array.isArray(lines)) continue;
|
|
142
|
+
for (const line of lines) total += Buffer.byteLength(String(line || ''), 'utf8');
|
|
143
|
+
}
|
|
144
|
+
for (const memo of graph._referenceSearchCache?.values() || []) {
|
|
145
|
+
total += Buffer.byteLength(String(memo || ''), 'utf8');
|
|
146
|
+
}
|
|
147
|
+
return total;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function _clearGraphRuntimeCaches(graph) {
|
|
151
|
+
if (!graph) return;
|
|
152
|
+
graph._sourceTextCache?.clear();
|
|
153
|
+
graph._maskedLinesCache?.clear();
|
|
154
|
+
graph._sourceLinesCache?.clear();
|
|
155
|
+
graph._referenceSearchCache?.clear();
|
|
156
|
+
graph._symbolTokenIndex?.clear();
|
|
157
|
+
graph._symbolTokenIndexDirty = true;
|
|
158
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Keyword-to-symbol fuzzy matching: tokenization, token-aligned contiguous
|
|
2
|
+
// match, ordered token match, and ranking key. Pure string helpers with no
|
|
3
|
+
// graph/cache state. Extracted from search.mjs.
|
|
4
|
+
|
|
5
|
+
export function _keywordSymbolSortKey(symbolName, keyword) {
|
|
6
|
+
const lowerName = String(symbolName || '').toLowerCase();
|
|
7
|
+
const lowerKey = String(keyword || '').toLowerCase();
|
|
8
|
+
const idx = lowerName.indexOf(lowerKey);
|
|
9
|
+
if (idx < 0) return null;
|
|
10
|
+
const atStart = idx === 0 ? 0 : 1;
|
|
11
|
+
return [lowerName.length, atStart, idx, symbolName];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function _tokenizeKeyword(s) {
|
|
15
|
+
return String(s || '')
|
|
16
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
17
|
+
.split(/[^a-zA-Z0-9]+/)
|
|
18
|
+
.filter(Boolean)
|
|
19
|
+
.map((t) => t.toLowerCase());
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function _tokenStartOffsets(sym) {
|
|
23
|
+
const starts = new Set();
|
|
24
|
+
let prevAlnum = false;
|
|
25
|
+
let prevUpper = false;
|
|
26
|
+
for (let i = 0; i < sym.length; i += 1) {
|
|
27
|
+
const c = sym[i];
|
|
28
|
+
const isAlnum = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
|
|
29
|
+
if (!isAlnum) { prevAlnum = false; prevUpper = false; continue; }
|
|
30
|
+
const isUpper = c >= 'A' && c <= 'Z';
|
|
31
|
+
if (!prevAlnum) starts.add(i);
|
|
32
|
+
else if (isUpper && !prevUpper) starts.add(i);
|
|
33
|
+
prevAlnum = true;
|
|
34
|
+
prevUpper = isUpper;
|
|
35
|
+
}
|
|
36
|
+
return starts;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function _contiguousMatchTokenAligned(sym, lowerKey) {
|
|
40
|
+
const len = lowerKey.length;
|
|
41
|
+
if (!len) return false;
|
|
42
|
+
const symLower = sym.toLowerCase();
|
|
43
|
+
const starts = _tokenStartOffsets(sym);
|
|
44
|
+
let lead = 0;
|
|
45
|
+
while (lead < len) {
|
|
46
|
+
const c = lowerKey[lead];
|
|
47
|
+
const isAlnum = (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9');
|
|
48
|
+
if (isAlnum) break;
|
|
49
|
+
lead += 1;
|
|
50
|
+
}
|
|
51
|
+
let from = 0;
|
|
52
|
+
for (;;) {
|
|
53
|
+
const idx = symLower.indexOf(lowerKey, from);
|
|
54
|
+
if (idx < 0) return false;
|
|
55
|
+
const end = idx + len;
|
|
56
|
+
const effectiveIdx = idx + lead;
|
|
57
|
+
if (starts.has(effectiveIdx)) return true;
|
|
58
|
+
let interiorBoundary = false;
|
|
59
|
+
for (const s of starts) {
|
|
60
|
+
if (s > effectiveIdx && s < end) { interiorBoundary = true; break; }
|
|
61
|
+
}
|
|
62
|
+
if (!interiorBoundary) return true;
|
|
63
|
+
from = idx + 1;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function _orderedTokenMatch(symLower, tokens) {
|
|
68
|
+
let from = 0;
|
|
69
|
+
for (const t of tokens) {
|
|
70
|
+
const i = symLower.indexOf(t, from);
|
|
71
|
+
if (i < 0) return false;
|
|
72
|
+
from = i + t.length;
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function _keywordMatchesSymbolName(name, lowerKey, keyTokens) {
|
|
78
|
+
const sym = String(name || '').trim();
|
|
79
|
+
if (!sym || !lowerKey) return false;
|
|
80
|
+
if (_contiguousMatchTokenAligned(sym, lowerKey)) return true;
|
|
81
|
+
return keyTokens.length >= 2 && _orderedTokenMatch(sym.toLowerCase(), keyTokens);
|
|
82
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// Per-language lexical predicates + JS tokenizer character/keyword sets.
|
|
2
|
+
// Pure functions, no state. Extracted verbatim from code-graph.mjs; shared
|
|
3
|
+
// by the text masker, symbol index, and search/format layers.
|
|
4
|
+
|
|
5
|
+
export function _langUsesDollarInIdentifiers(lang) {
|
|
6
|
+
// `$` is a valid identifier char only in JS/TS/PHP. The 5 new langs are
|
|
7
|
+
// deliberately excluded: kotlin/swift/scala/lua have no `$` in identifiers,
|
|
8
|
+
// and bash's `$` is a variable-expansion sigil (`$var`), not an identifier
|
|
9
|
+
// char — treating it as a word-boundary char would mis-tokenize.
|
|
10
|
+
// Second batch (dart/objc/elixir/zig/r) likewise excluded: none use `$` as
|
|
11
|
+
// an identifier char (objc `$` is invalid; elixir/dart/zig/r have no `$` in
|
|
12
|
+
// names), so they stay out.
|
|
13
|
+
return lang === 'javascript' || lang === 'typescript' || lang === 'php';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function _langAllowsBangQuestionSuffix(lang) {
|
|
17
|
+
// Method names may end in `!`/`?` only in ruby (`save!`/`empty?`) and rust
|
|
18
|
+
// (`!` macros). Kotlin is NOT here: its `!!` is the not-null assertion
|
|
19
|
+
// OPERATOR, not an identifier suffix — including it would fold `foo!!` into
|
|
20
|
+
// the `foo` reference and break matching. swift `?`/`!` are optional/
|
|
21
|
+
// force-unwrap operators (not name chars); scala/bash/lua have no suffix.
|
|
22
|
+
// Second batch: elixir function names may end in `?`/`!` (`valid?`/`save!`)
|
|
23
|
+
// exactly like ruby → included. dart/objc/zig/r have no such suffix.
|
|
24
|
+
return lang === 'ruby' || lang === 'rust' || lang === 'elixir';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function _supportsHashComments(lang) {
|
|
28
|
+
// Hash-comment langs: python/ruby/php plus bash. lua is NOT hash — it uses
|
|
29
|
+
// `--` line + `--[[ ]]` block comments (see _maskNonCodeText). kotlin/
|
|
30
|
+
// swift/scala are slash-comment C-family (see _supportsSlashComments).
|
|
31
|
+
// Second batch: elixir and r are `#`-only line-comment langs → included.
|
|
32
|
+
// (dart/objc/zig are slash-comment, handled by _supportsSlashComments.)
|
|
33
|
+
return lang === 'python' || lang === 'ruby' || lang === 'php'
|
|
34
|
+
|| lang === 'bash' || lang === 'elixir' || lang === 'r';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function _supportsSlashComments(lang) {
|
|
38
|
+
// Slash-comment langs: everything C-family, incl. new kotlin/swift/scala.
|
|
39
|
+
// Excluded: python/ruby/bash (hash) and lua (`--` comments; `//` is lua
|
|
40
|
+
// integer division, so it must not be treated as a comment opener).
|
|
41
|
+
// Second batch: dart/objc/zig are C-family slash-comment (kept by the
|
|
42
|
+
// default). Excluded here: elixir/r (hash-only, see _supportsHashComments).
|
|
43
|
+
return lang !== 'python' && lang !== 'ruby'
|
|
44
|
+
&& lang !== 'bash' && lang !== 'lua'
|
|
45
|
+
&& lang !== 'elixir' && lang !== 'r';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function _supportsSingleQuoteStrings(lang) {
|
|
49
|
+
return lang === 'typescript'
|
|
50
|
+
|| lang === 'javascript'
|
|
51
|
+
|| lang === 'python'
|
|
52
|
+
|| lang === 'ruby'
|
|
53
|
+
|| lang === 'php'
|
|
54
|
+
// New langs with single-quote string literals: swift uses double quotes
|
|
55
|
+
// only (excluded); kotlin uses double/triple-double (excluded); scala
|
|
56
|
+
// single-quotes are Char literals not strings (excluded); bash and lua
|
|
57
|
+
// both support `'...'` single-quoted strings.
|
|
58
|
+
|| lang === 'bash'
|
|
59
|
+
|| lang === 'lua'
|
|
60
|
+
// Second batch. dart: `'...'` is a primary string form → included. r:
|
|
61
|
+
// `'...'` is a string literal equivalent to `"..."` → included. objc:
|
|
62
|
+
// `'x'` is a char literal — INCLUDED here so its contents are masked as a
|
|
63
|
+
// single-quote string. This deliberately DIVERGES from c/cpp, which are
|
|
64
|
+
// NOT in this list: objc's masker benefits from neutralizing char-literal
|
|
65
|
+
// bytes, whereas c/cpp char literals are left unmasked.
|
|
66
|
+
// elixir: EXCLUDED — `'...'` is a charlist, not a string; but charlists
|
|
67
|
+
// are single-line and `\\`-escaped just like a string, so masking them as
|
|
68
|
+
// strings would be safe — they are nonetheless left out to keep elixir
|
|
69
|
+
// string handling limited to `"..."`/`"""` (charlist contents are rare in
|
|
70
|
+
// code-graph anchors and excluding avoids masking a stray apostrophe in a
|
|
71
|
+
// comment-less context). zig: EXCLUDED — `'c'` is a char literal only and
|
|
72
|
+
// zig multiline strings are `\\`-prefixed lines (out of scope), so no
|
|
73
|
+
// single-quote string form applies.
|
|
74
|
+
|| lang === 'dart'
|
|
75
|
+
|| lang === 'r'
|
|
76
|
+
|| lang === 'objc';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function _supportsBacktickStrings(lang) {
|
|
80
|
+
return lang === 'typescript' || lang === 'javascript' || lang === 'go';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function _supportsTripleSingleQuoteStrings(lang) {
|
|
84
|
+
// `'''` triple-single-quote strings: python, and dart (which supports BOTH
|
|
85
|
+
// `'''` and `"""` multiline strings). kotlin/scala/swift have `"""` but NOT
|
|
86
|
+
// `'''`; treating `'''` as a string opener there would mis-mask a
|
|
87
|
+
// single-quote char/string followed by an empty string.
|
|
88
|
+
return lang === 'python' || lang === 'dart';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function _supportsTripleDoubleQuoteStrings(lang) {
|
|
92
|
+
// `"""` triple-double-quote raw/multiline strings: python, kotlin, scala
|
|
93
|
+
// and swift. bash/lua have no triple-quote form (lua long strings use
|
|
94
|
+
// `[[ ]]`).
|
|
95
|
+
// Second batch: elixir `"""` heredoc docstrings → included. dart supports
|
|
96
|
+
// BOTH `'''` and `"""` multiline strings → included here (and in the triple-
|
|
97
|
+
// single predicate). objc/zig/r have no `"""` form.
|
|
98
|
+
return lang === 'python' || lang === 'kotlin'
|
|
99
|
+
|| lang === 'scala' || lang === 'swift' || lang === 'elixir'
|
|
100
|
+
|| lang === 'dart';
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function _isJsLike(lang) {
|
|
104
|
+
return lang === 'javascript' || lang === 'typescript';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function _isWordStartChar(c) {
|
|
108
|
+
return c === '_' || c === '$'
|
|
109
|
+
|| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function _isWordChar(c) {
|
|
113
|
+
return _isWordStartChar(c) || (c >= '0' && c <= '9');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ECMAScript expression-context keywords that can precede a regex literal.
|
|
117
|
+
// After any of these, a `/` opens a RegExp literal; after a value (identifier,
|
|
118
|
+
// number, `)`, `]`), `/` is the division operator. This list is from the
|
|
119
|
+
// language spec — not a heuristic — and resolves the `/`-ambiguity.
|
|
120
|
+
export const REGEX_PRECEDENT_KEYWORDS = new Set([
|
|
121
|
+
'return', 'typeof', 'delete', 'void', 'new', 'throw', 'await', 'yield',
|
|
122
|
+
'in', 'of', 'instanceof', 'case', 'do', 'else', 'if', 'while',
|
|
123
|
+
]);
|
|
124
|
+
|
|
125
|
+
export const REGEX_PRECEDENT_CHARS = new Set([
|
|
126
|
+
'=', '(', ',', ';', ':', '?', '!', '~', '&', '|', '^', '+', '-',
|
|
127
|
+
'*', '%', '<', '>', '{', '[',
|
|
128
|
+
]);
|