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.
Files changed (417) hide show
  1. package/package.json +8 -3
  2. package/scripts/anthropic-maxtokens-test.mjs +119 -0
  3. package/scripts/bench/lead-review-tasks-r3.json +20 -0
  4. package/scripts/bench/lead-review-tasks.json +20 -0
  5. package/scripts/bench/r4-mixed-tasks.json +20 -0
  6. package/scripts/bench/review-tasks.json +20 -0
  7. package/scripts/bench/round-codex.json +114 -0
  8. package/scripts/bench/round-mixdog-lead-r3.json +269 -0
  9. package/scripts/bench/round-mixdog-lead.json +269 -0
  10. package/scripts/bench/round-mixdog.json +126 -0
  11. package/scripts/bench/round-r10-bigsample.json +679 -0
  12. package/scripts/bench/round-r11-codexalign.json +257 -0
  13. package/scripts/bench/round-r4-codex.json +114 -0
  14. package/scripts/bench/round-r4-mixed.json +225 -0
  15. package/scripts/bench/round-r5-gpt-lead.json +259 -0
  16. package/scripts/bench/round-r6-codex.json +114 -0
  17. package/scripts/bench/round-r6-solo.json +257 -0
  18. package/scripts/bench/round-r7-full.json +254 -0
  19. package/scripts/bench/round-r8-fulldefault.json +255 -0
  20. package/scripts/bench-run.mjs +215 -29
  21. package/scripts/build-tui.mjs +13 -1
  22. package/scripts/explore-bench.mjs +124 -0
  23. package/scripts/freevar-smoke.mjs +95 -0
  24. package/scripts/hook-bus-test.mjs +191 -0
  25. package/scripts/internal-comms-bench.mjs +1 -0
  26. package/scripts/internal-comms-smoke.mjs +10 -9
  27. package/scripts/mouse-probe.mjs +45 -0
  28. package/scripts/output-style-bench.mjs +13 -6
  29. package/scripts/output-style-smoke.mjs +4 -4
  30. package/scripts/path-suffix-test.mjs +57 -0
  31. package/scripts/provider-toolcall-test.mjs +7 -3
  32. package/scripts/recall-bench.mjs +207 -0
  33. package/scripts/recall-usecase-cases.json +18 -0
  34. package/scripts/recall-usecase-probe.json +6 -0
  35. package/scripts/session-bench.mjs +152 -6
  36. package/scripts/tool-smoke.mjs +30 -67
  37. package/scripts/tui-render-smoke.mjs +90 -0
  38. package/scripts/webhook-smoke.mjs +208 -0
  39. package/src/agents/debugger/AGENT.md +5 -2
  40. package/src/agents/heavy-worker/AGENT.md +21 -11
  41. package/src/agents/maintainer/AGENT.md +4 -0
  42. package/src/agents/reviewer/AGENT.md +3 -2
  43. package/src/agents/worker/AGENT.md +21 -11
  44. package/src/lib/rules-builder.cjs +4 -0
  45. package/src/mixdog-session-runtime.mjs +933 -3731
  46. package/src/output-styles/default.md +34 -9
  47. package/src/output-styles/{oneline.md → extreme-minimal.md} +5 -4
  48. package/src/output-styles/minimal.md +4 -1
  49. package/src/output-styles/simple.md +22 -7
  50. package/src/repl.mjs +5 -5
  51. package/src/rules/agent/00-common.md +2 -0
  52. package/src/rules/agent/30-explorer.md +8 -11
  53. package/src/rules/lead/lead-brief.md +12 -0
  54. package/src/rules/lead/lead-tool.md +2 -9
  55. package/src/rules/shared/01-tool.md +11 -5
  56. package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +25 -0
  57. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +100 -23
  58. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +6 -15
  59. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +362 -0
  60. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +410 -0
  61. package/src/runtime/agent/orchestrator/agent-trace.mjs +16 -735
  62. package/src/runtime/agent/orchestrator/config.mjs +69 -2
  63. package/src/runtime/agent/orchestrator/context/collect.mjs +51 -0
  64. package/src/runtime/agent/orchestrator/mcp/client.mjs +6 -2
  65. package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +63 -21
  66. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +93 -0
  67. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +209 -0
  68. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +489 -0
  69. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +97 -1343
  70. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +607 -0
  71. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +78 -10
  72. package/src/runtime/agent/orchestrator/providers/api-usage.mjs +1 -13
  73. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +81 -0
  74. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +248 -0
  75. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +303 -0
  76. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +505 -0
  77. package/src/runtime/agent/orchestrator/providers/gemini.mjs +44 -1014
  78. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +18 -4
  79. package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +32 -0
  80. package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +86 -11
  81. package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +348 -0
  82. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +54 -20
  83. package/src/runtime/agent/orchestrator/providers/openai-codex-model.mjs +108 -0
  84. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +19 -12
  85. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +58 -0
  86. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +368 -0
  87. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +760 -0
  88. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +41 -1142
  89. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +732 -0
  90. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +193 -0
  91. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +303 -2119
  92. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +140 -995
  93. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +227 -0
  94. package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +67 -0
  95. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +436 -0
  96. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +1105 -0
  97. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +2 -1
  98. package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +38 -12
  99. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +7 -8
  100. package/src/runtime/agent/orchestrator/session/compact/budget.mjs +288 -0
  101. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +85 -0
  102. package/src/runtime/agent/orchestrator/session/compact/engine.mjs +749 -0
  103. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +82 -0
  104. package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +315 -0
  105. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +643 -0
  106. package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +326 -0
  107. package/src/runtime/agent/orchestrator/session/compact.mjs +40 -2282
  108. package/src/runtime/agent/orchestrator/session/loop/compact-debug.mjs +28 -0
  109. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +274 -0
  110. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +61 -0
  111. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +38 -0
  112. package/src/runtime/agent/orchestrator/session/loop/env.mjs +14 -0
  113. package/src/runtime/agent/orchestrator/session/loop/hidden-agents.mjs +21 -0
  114. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +47 -0
  115. package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +182 -0
  116. package/src/runtime/agent/orchestrator/session/loop/steering-ladder.mjs +173 -0
  117. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +63 -0
  118. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +100 -0
  119. package/src/runtime/agent/orchestrator/session/loop/termination.mjs +58 -0
  120. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +52 -0
  121. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +239 -0
  122. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +218 -0
  123. package/src/runtime/agent/orchestrator/session/loop/transcript-repair.mjs +101 -0
  124. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +35 -0
  125. package/src/runtime/agent/orchestrator/session/loop.mjs +409 -1304
  126. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +471 -0
  127. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +230 -0
  128. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +235 -0
  129. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +149 -0
  130. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +155 -0
  131. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +406 -0
  132. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +80 -0
  133. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +303 -0
  134. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +210 -0
  135. package/src/runtime/agent/orchestrator/session/manager.mjs +226 -2114
  136. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +189 -0
  137. package/src/runtime/agent/orchestrator/session/store.mjs +74 -179
  138. package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -3
  139. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +70 -20
  140. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +22 -2
  141. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +33 -42
  142. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +241 -0
  143. package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +1 -1
  144. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +40 -0
  145. package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +42 -2
  146. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +1 -1
  147. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +11 -4
  148. package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +29 -0
  149. package/src/runtime/agent/orchestrator/tools/builtin/search-builders.mjs +8 -0
  150. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +126 -0
  151. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +81 -87
  152. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +161 -0
  153. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +108 -0
  154. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +78 -304
  155. package/src/runtime/agent/orchestrator/tools/builtin.mjs +11 -6
  156. package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +303 -0
  157. package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +43 -0
  158. package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +382 -0
  159. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +551 -0
  160. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +295 -0
  161. package/src/runtime/agent/orchestrator/tools/code-graph/graph-model.mjs +158 -0
  162. package/src/runtime/agent/orchestrator/tools/code-graph/keyword-match.mjs +82 -0
  163. package/src/runtime/agent/orchestrator/tools/code-graph/lang-predicates.mjs +128 -0
  164. package/src/runtime/agent/orchestrator/tools/code-graph/memory-cache.mjs +66 -0
  165. package/src/runtime/agent/orchestrator/tools/code-graph/project-root.mjs +44 -0
  166. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1080 -0
  167. package/src/runtime/agent/orchestrator/tools/code-graph/source-access.mjs +81 -0
  168. package/src/runtime/agent/orchestrator/tools/code-graph/span.mjs +19 -0
  169. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +280 -0
  170. package/src/runtime/agent/orchestrator/tools/code-graph/text-columns.mjs +45 -0
  171. package/src/runtime/agent/orchestrator/tools/code-graph/text-mask.mjs +347 -0
  172. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +6 -6
  173. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +36 -4277
  174. package/src/runtime/agent/orchestrator/tools/graph-binary-fetcher.mjs +6 -3
  175. package/src/runtime/agent/orchestrator/tools/patch/constants.mjs +9 -0
  176. package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +171 -0
  177. package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +471 -0
  178. package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +436 -0
  179. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +342 -0
  180. package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +359 -0
  181. package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +340 -0
  182. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +643 -0
  183. package/src/runtime/agent/orchestrator/tools/patch.mjs +36 -2959
  184. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +1 -23
  185. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +10 -74
  186. package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +77 -0
  187. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +2 -4
  188. package/src/runtime/agent/orchestrator/tools/shell-state.mjs +154 -0
  189. package/src/runtime/channels/backends/discord-access.mjs +32 -0
  190. package/src/runtime/channels/backends/discord-attachments.mjs +65 -0
  191. package/src/runtime/channels/backends/discord-gateway.mjs +233 -0
  192. package/src/runtime/channels/backends/discord.mjs +12 -292
  193. package/src/runtime/channels/index.mjs +241 -894
  194. package/src/runtime/channels/lib/backend-dispatch.mjs +44 -0
  195. package/src/runtime/channels/lib/boot-profile.mjs +23 -0
  196. package/src/runtime/channels/lib/crash-log.mjs +106 -0
  197. package/src/runtime/channels/lib/event-pipeline.mjs +18 -1
  198. package/src/runtime/channels/lib/event-queue.mjs +63 -4
  199. package/src/runtime/channels/lib/inbound-routing.mjs +111 -0
  200. package/src/runtime/channels/lib/index-drop-trace.mjs +72 -0
  201. package/src/runtime/channels/lib/output-forwarder.mjs +9 -1
  202. package/src/runtime/channels/lib/owner-heartbeat.mjs +75 -0
  203. package/src/runtime/channels/lib/parent-bridge.mjs +88 -0
  204. package/src/runtime/channels/lib/runtime-paths.mjs +14 -4
  205. package/src/runtime/channels/lib/session-discovery.mjs +56 -4
  206. package/src/runtime/channels/lib/telegram-format.mjs +19 -22
  207. package/src/runtime/channels/lib/tool-dispatch.mjs +158 -0
  208. package/src/runtime/channels/lib/tool-format.mjs +1 -1
  209. package/src/runtime/channels/lib/transcript-discovery.mjs +4 -4
  210. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +6 -3
  211. package/src/runtime/channels/lib/voice-transcription.mjs +179 -0
  212. package/src/runtime/channels/lib/webhook/deliveries.mjs +312 -0
  213. package/src/runtime/channels/lib/webhook/log.mjs +42 -0
  214. package/src/runtime/channels/lib/webhook/ngrok.mjs +181 -0
  215. package/src/runtime/channels/lib/webhook/signature.mjs +60 -0
  216. package/src/runtime/channels/lib/webhook.mjs +36 -570
  217. package/src/runtime/channels/lib/whisper-language.mjs +42 -0
  218. package/src/runtime/channels/tool-defs.mjs +11 -130
  219. package/src/runtime/memory/index.mjs +258 -2050
  220. package/src/runtime/memory/lib/core-memory-store.mjs +351 -1
  221. package/src/runtime/memory/lib/cycle-llm-adapters.mjs +58 -0
  222. package/src/runtime/memory/lib/cycle-scheduler.mjs +497 -0
  223. package/src/runtime/memory/lib/cycle-signatures.mjs +34 -0
  224. package/src/runtime/memory/lib/embedding-warmup.mjs +58 -0
  225. package/src/runtime/memory/lib/http-wire.mjs +57 -0
  226. package/src/runtime/memory/lib/memory-config-flags.mjs +91 -0
  227. package/src/runtime/memory/lib/memory-cycle.mjs +1 -1
  228. package/src/runtime/memory/lib/memory-cycle2-gate.mjs +515 -0
  229. package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +324 -0
  230. package/src/runtime/memory/lib/memory-cycle2-shared.mjs +18 -0
  231. package/src/runtime/memory/lib/memory-cycle2.mjs +72 -837
  232. package/src/runtime/memory/lib/memory-embed.mjs +149 -0
  233. package/src/runtime/memory/lib/memory-process-lock.mjs +162 -0
  234. package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +24 -0
  235. package/src/runtime/memory/lib/memory-recall-store.mjs +22 -2
  236. package/src/runtime/memory/lib/memory-retrievers.mjs +8 -0
  237. package/src/runtime/memory/lib/memory.mjs +20 -0
  238. package/src/runtime/memory/lib/pg/supervisor.mjs +1 -1
  239. package/src/runtime/memory/lib/promotion-fingerprint.mjs +50 -0
  240. package/src/runtime/memory/lib/query-handlers.mjs +780 -0
  241. package/src/runtime/memory/lib/recall-format.mjs +238 -0
  242. package/src/runtime/memory/lib/runtime-fetcher.mjs +8 -3
  243. package/src/runtime/memory/lib/transcript-ingest.mjs +425 -0
  244. package/src/runtime/memory/tool-defs.mjs +6 -14
  245. package/src/runtime/search/lib/http-fetch.mjs +274 -0
  246. package/src/runtime/search/lib/ssrf-guard.mjs +333 -0
  247. package/src/runtime/search/lib/web-tools.mjs +24 -602
  248. package/src/runtime/shared/abort-controller.mjs +1 -1
  249. package/src/runtime/shared/atomic-file.mjs +26 -1
  250. package/src/runtime/shared/background-tasks.mjs +2 -3
  251. package/src/runtime/shared/buffered-appender.mjs +149 -0
  252. package/src/runtime/shared/launcher-control.mjs +2 -2
  253. package/src/runtime/shared/task-notification-envelope.mjs +98 -0
  254. package/src/runtime/shared/tool-execution-contract.mjs +2 -2
  255. package/src/runtime/shared/tool-primitives.mjs +308 -0
  256. package/src/runtime/shared/tool-result-summary.mjs +515 -0
  257. package/src/runtime/shared/tool-surface.mjs +80 -898
  258. package/src/runtime/shared/transcript-writer.mjs +52 -2
  259. package/src/runtime/shared/update-checker.mjs +7 -4
  260. package/src/session-runtime/config-helpers.mjs +291 -0
  261. package/src/session-runtime/config-lifecycle.mjs +232 -0
  262. package/src/session-runtime/cwd-plugins.mjs +226 -0
  263. package/src/session-runtime/effort.mjs +128 -0
  264. package/src/session-runtime/fs-utils.mjs +10 -0
  265. package/src/session-runtime/mcp-glue.mjs +177 -0
  266. package/src/session-runtime/model-capabilities.mjs +130 -0
  267. package/src/session-runtime/model-recency.mjs +111 -0
  268. package/src/session-runtime/native-search.mjs +247 -0
  269. package/src/session-runtime/output-styles.mjs +126 -0
  270. package/src/session-runtime/plugin-mcp.mjs +114 -0
  271. package/src/session-runtime/prewarm.mjs +142 -0
  272. package/src/session-runtime/provider-models.mjs +278 -0
  273. package/src/session-runtime/provider-usage.mjs +120 -0
  274. package/src/session-runtime/quick-model-rows.mjs +170 -0
  275. package/src/session-runtime/quick-search-models.mjs +46 -0
  276. package/src/session-runtime/session-hooks.mjs +93 -0
  277. package/src/session-runtime/session-text.mjs +100 -0
  278. package/src/session-runtime/settings-api.mjs +319 -0
  279. package/src/session-runtime/statusline-route.mjs +35 -0
  280. package/src/session-runtime/tool-catalog.mjs +720 -0
  281. package/src/session-runtime/tool-defs.mjs +84 -0
  282. package/src/session-runtime/warmup-schedulers.mjs +201 -0
  283. package/src/session-runtime/workflow.mjs +358 -0
  284. package/src/standalone/agent-tool/helpers.mjs +237 -0
  285. package/src/standalone/agent-tool/notify.mjs +107 -0
  286. package/src/standalone/agent-tool/provider-init.mjs +143 -0
  287. package/src/standalone/agent-tool/render.mjs +152 -0
  288. package/src/standalone/agent-tool/tool-def.mjs +55 -0
  289. package/src/standalone/agent-tool.mjs +155 -677
  290. package/src/standalone/channel-worker.mjs +7 -9
  291. package/src/standalone/explore-tool.mjs +40 -12
  292. package/src/standalone/hook-bus/config.mjs +207 -0
  293. package/src/standalone/hook-bus/constants.mjs +90 -0
  294. package/src/standalone/hook-bus/handlers.mjs +481 -0
  295. package/src/standalone/hook-bus/payload.mjs +31 -0
  296. package/src/standalone/hook-bus/rules.mjs +77 -0
  297. package/src/standalone/hook-bus.mjs +110 -746
  298. package/src/standalone/memory-runtime-proxy.mjs +7 -0
  299. package/src/standalone/opencode-go-login.mjs +125 -0
  300. package/src/standalone/provider-admin.mjs +15 -19
  301. package/src/standalone/usage-dashboard.mjs +3 -1
  302. package/src/tui/App.jsx +1163 -7571
  303. package/src/tui/app/app-format.mjs +206 -0
  304. package/src/tui/app/channel-pickers.mjs +510 -0
  305. package/src/tui/app/clipboard.mjs +67 -0
  306. package/src/tui/app/core-memory-picker.mjs +210 -0
  307. package/src/tui/app/extension-pickers.mjs +506 -0
  308. package/src/tui/app/input-parsers.mjs +193 -0
  309. package/src/tui/app/maintenance-pickers.mjs +324 -0
  310. package/src/tui/app/model-options.mjs +330 -0
  311. package/src/tui/app/model-picker.mjs +365 -0
  312. package/src/tui/app/onboarding-steps.mjs +400 -0
  313. package/src/tui/app/project-picker.mjs +247 -0
  314. package/src/tui/app/provider-setup-picker.mjs +580 -0
  315. package/src/tui/app/resume-picker.mjs +55 -0
  316. package/src/tui/app/route-pickers.mjs +419 -0
  317. package/src/tui/app/settings-picker.mjs +490 -0
  318. package/src/tui/app/slash-commands.mjs +101 -0
  319. package/src/tui/app/slash-dispatch.mjs +427 -0
  320. package/src/tui/app/text-layout.mjs +46 -0
  321. package/src/tui/app/theme-effort-pickers.mjs +154 -0
  322. package/src/tui/app/transcript-window.mjs +671 -0
  323. package/src/tui/app/use-mouse-input.mjs +460 -0
  324. package/src/tui/app/use-prompt-handlers.mjs +310 -0
  325. package/src/tui/app/use-transcript-scroll.mjs +510 -0
  326. package/src/tui/app/use-transcript-window.mjs +589 -0
  327. package/src/tui/components/ConfirmBar.jsx +1 -1
  328. package/src/tui/components/Picker.jsx +32 -4
  329. package/src/tui/components/PromptInput.jsx +259 -80
  330. package/src/tui/components/SlashCommandPalette.jsx +8 -1
  331. package/src/tui/components/StatusLine.jsx +63 -12
  332. package/src/tui/components/TextEntryPanel.jsx +11 -0
  333. package/src/tui/components/ToolExecution.jsx +56 -588
  334. package/src/tui/components/TranscriptItem.jsx +105 -0
  335. package/src/tui/components/UsagePanel.jsx +18 -4
  336. package/src/tui/components/prompt-input/edit-helpers.mjs +72 -0
  337. package/src/tui/components/prompt-input/voice-indicator.mjs +39 -0
  338. package/src/tui/components/tool-execution/ResultBody.jsx +56 -0
  339. package/src/tui/components/tool-execution/surface-detail.mjs +405 -0
  340. package/src/tui/components/tool-execution/text-format.mjs +161 -0
  341. package/src/tui/components/tool-output-format.mjs +2 -2
  342. package/src/tui/display-width.mjs +20 -3
  343. package/src/tui/dist/index.mjs +18034 -17188
  344. package/src/tui/engine/agent-envelope.mjs +296 -0
  345. package/src/tui/engine/agent-job-feed.mjs +133 -0
  346. package/src/tui/engine/boot-profile.mjs +21 -0
  347. package/src/tui/engine/labels.mjs +67 -0
  348. package/src/tui/engine/notice-text.mjs +112 -0
  349. package/src/tui/engine/notification-plan.mjs +76 -0
  350. package/src/tui/engine/queue-helpers.mjs +161 -0
  351. package/src/tui/engine/render-timing.mjs +17 -0
  352. package/src/tui/engine/session-stats.mjs +46 -0
  353. package/src/tui/engine/tool-approval.mjs +94 -0
  354. package/src/tui/engine/tool-call-fields.mjs +23 -0
  355. package/src/tui/engine/tool-card-results.mjs +234 -0
  356. package/src/tui/engine/tool-result-status.mjs +135 -0
  357. package/src/tui/engine/tool-result-text.mjs +126 -0
  358. package/src/tui/engine.mjs +405 -1385
  359. package/src/tui/figures.mjs +5 -0
  360. package/src/tui/index.jsx +105 -0
  361. package/src/tui/input-editing.mjs +60 -10
  362. package/src/tui/keyboard-protocol.mjs +2 -2
  363. package/src/tui/lib/voice-recorder.mjs +35 -19
  364. package/src/tui/markdown/format-token.mjs +11 -9
  365. package/src/tui/paste-attachments.mjs +38 -0
  366. package/src/tui/statusline-ansi-bridge.mjs +11 -3
  367. package/src/tui/theme.mjs +6 -0
  368. package/src/tui/themes/base.mjs +2 -2
  369. package/src/tui/themes/kanagawa.mjs +4 -4
  370. package/src/tui/themes/teal.mjs +4 -5
  371. package/src/tui/themes/utils.mjs +1 -1
  372. package/src/ui/statusline-agents.mjs +213 -0
  373. package/src/ui/statusline-format.mjs +146 -0
  374. package/src/ui/statusline-segments.mjs +148 -0
  375. package/src/ui/statusline.mjs +77 -462
  376. package/src/ui/tool-card.mjs +0 -1
  377. package/src/vendor/statusline/bin/statusline-route.mjs +15 -2
  378. package/src/workflows/default/WORKFLOW.md +16 -9
  379. package/src/workflows/sequential/WORKFLOW.md +16 -11
  380. package/src/workflows/solo/WORKFLOW.md +5 -1
  381. package/vendor/ink/build/display-width.js +19 -3
  382. package/vendor/ink/build/ink.js +103 -6
  383. package/vendor/ink/build/log-update.js +17 -3
  384. package/vendor/ink/build/wrap-text.js +125 -0
  385. package/scripts/_test-folder-dialog.mjs +0 -30
  386. package/scripts/fix-brief-fn.mjs +0 -35
  387. package/scripts/fix-format-tool-surface.mjs +0 -24
  388. package/scripts/fix-tool-exec-visible.mjs +0 -42
  389. package/scripts/patch-agent-brief.mjs +0 -48
  390. package/scripts/patch-app.mjs +0 -21
  391. package/scripts/patch-app2.mjs +0 -18
  392. package/scripts/patch-dist-brief.mjs +0 -96
  393. package/scripts/patch-tool-exec.mjs +0 -70
  394. package/src/examples/schedules/SCHEDULE.example.md +0 -32
  395. package/src/examples/webhooks/WEBHOOK.example.md +0 -40
  396. package/src/runtime/agent/orchestrator/session/manager.reactive-persist.test.mjs +0 -107
  397. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +0 -143
  398. package/src/runtime/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +0 -285
  399. package/src/runtime/agent/orchestrator/tools/builtin/open-config-tool.mjs +0 -26
  400. package/src/runtime/shared/channel-notification-routing.test.mjs +0 -45
  401. package/src/runtime/shared/tool-execution-contract.test.mjs +0 -183
  402. package/src/standalone/agent-task-status.test.mjs +0 -76
  403. package/src/tui/components/tool-output-format.test.mjs +0 -399
  404. package/src/tui/display-width.test.mjs +0 -35
  405. package/src/tui/engine-runtime-notification.test.mjs +0 -115
  406. package/src/tui/engine-tool-result-text.test.mjs +0 -75
  407. package/src/tui/markdown/format-token.test.mjs +0 -354
  408. package/src/tui/markdown/render-ansi.test.mjs +0 -108
  409. package/src/tui/markdown/stream-fence.test.mjs +0 -26
  410. package/src/tui/markdown/streaming-markdown.test.mjs +0 -70
  411. package/src/tui/prompt-history-store.test.mjs +0 -52
  412. package/src/tui/statusline-ansi-bridge.test.mjs +0 -159
  413. package/src/tui/transcript-tool-failures.test.mjs +0 -111
  414. package/src/ui/markdown.test.mjs +0 -70
  415. package/src/ui/statusline-context-label.test.mjs +0 -15
  416. package/src/vendor/statusline/bin/statusline-lib.mjs +0 -186
  417. package/src/vendor/statusline/bin/statusline-route.test.mjs +0 -80
@@ -0,0 +1,551 @@
1
+ // Tool dispatch layer: codeGraph (mode router), findSymbolTool,
2
+ // resolveSymbolReadSpan, executeCodeGraphTool (entry with cwd re-rooting +
3
+ // batch fan-out + abort race), isCodeGraphTool. Extracted verbatim from
4
+ // code-graph.mjs.
5
+ import { resolve as pathResolve, isAbsolute, relative as pathRelative } from 'node:path';
6
+ import { readFileSync, existsSync, statSync } from 'node:fs';
7
+ import { normalizeInputPath, toDisplayPath } from '../builtin.mjs';
8
+ import { findFileByBasename } from '../builtin/path-diagnostics.mjs';
9
+ import { markScopedCacheIncomplete } from '../../session/cache/scoped-cache-outcome.mjs';
10
+ import { CODE_GRAPH_TOOL_DEFS } from '../code-graph-tool-defs.mjs';
11
+ import { CODE_GRAPH_MAX_FILES } from './constants.mjs';
12
+ import { _graphRel, _getSourceTextForNode, _appendSameBasenameHint } from './source-access.mjs';
13
+ import { _extractSymbolsCheap, _buildExplainerFileSummary } from './symbol-index.mjs';
14
+ import { _inferSpanEndByIndent } from './span.mjs';
15
+ import {
16
+ _PROJECT_ROOT_SENTINELS,
17
+ _resolveFileProjectRoot,
18
+ _findDirProjectRoot,
19
+ _stripEmptyArgs,
20
+ } from './project-root.mjs';
21
+ import { buildCodeGraphAsync, prewarmCodeGraph, prewarmCodeGraphSymbols } from './build.mjs';
22
+ import {
23
+ _findSymbolHits,
24
+ _findSymbolAcrossGraph,
25
+ _searchSymbolsByKeyword,
26
+ _extractCallees,
27
+ _formatCalleeRow,
28
+ _CALLEES_BRACE_LANGS,
29
+ _formatRelated,
30
+ _formatImpact,
31
+ _resolveReferenceLanguageNode,
32
+ _prewarmReferenceSourceText,
33
+ _cheapReferenceSearch,
34
+ _formatCallerReferences,
35
+ _formatTransitiveCallers,
36
+ _augmentNoHitDiagnostic,
37
+ _pickCalleeDeclHit,
38
+ } from './search.mjs';
39
+
40
+ const CODE_GRAPH_BATCHABLE_MODES = new Set(['symbol', 'find_symbol', 'symbol_search', 'callers', 'callees', 'references']);
41
+ const CODE_GRAPH_FILE_BATCHABLE_MODES = new Set(['imports', 'dependents', 'related', 'impact', 'symbols', 'overview']);
42
+
43
+ function _collectGraphSymbolList(args) {
44
+ const split = (s) => String(s || '').split(/[,\s]+/).map((t) => t.trim()).filter(Boolean);
45
+ return [...new Set([
46
+ ...(Array.isArray(args?.symbols) ? args.symbols.map((s) => String(s || '').trim()).filter(Boolean) : []),
47
+ ...(typeof args?.symbols === 'string' ? split(args.symbols) : []),
48
+ ...(typeof args?.symbol === 'string' ? split(args.symbol) : []),
49
+ ])];
50
+ }
51
+
52
+ const CODE_GRAPH_FILE_BATCH_CAP = 20;
53
+
54
+ function _collectGraphFileList(args) {
55
+ const split = (s) => String(s || '').split(/,+/).map((t) => t.trim()).filter(Boolean);
56
+ const list = [...new Set([
57
+ ...(Array.isArray(args?.files) ? args.files.map((f) => String(f || '').trim()).filter(Boolean) : []),
58
+ ...(typeof args?.files === 'string' ? split(args.files) : []),
59
+ ...(typeof args?.file === 'string' && args.file.trim() ? [args.file.trim()] : []),
60
+ ])];
61
+ if (list.length > CODE_GRAPH_FILE_BATCH_CAP) {
62
+ const capped = list.slice(0, CODE_GRAPH_FILE_BATCH_CAP);
63
+ capped._capped = true;
64
+ return capped;
65
+ }
66
+ return list;
67
+ }
68
+
69
+ async function codeGraph(args, cwd, signal = null, options = {}) {
70
+ let mode = String(args?.mode || '').trim();
71
+ if (!mode) throw new Error('code_graph: "mode" is required');
72
+ if (mode === 'search') mode = 'symbol_search';
73
+
74
+ if (mode === 'prewarm') {
75
+ const _splitMulti = (s) => String(s || '').split(/[,\s]+/).map((t) => t.trim()).filter(Boolean);
76
+ const fromSymbolsArr = Array.isArray(args?.symbols)
77
+ ? args.symbols.map((s) => String(s || '').trim()).filter(Boolean)
78
+ : [];
79
+ const fromSymbolsStr = typeof args?.symbols === 'string' ? _splitMulti(args.symbols) : [];
80
+ const fromSymbolField = typeof args?.symbol === 'string' ? _splitMulti(args.symbol) : [];
81
+ const symbols = [...new Set([...fromSymbolsArr, ...fromSymbolsStr, ...fromSymbolField])];
82
+ if (symbols.length > 0) prewarmCodeGraphSymbols(cwd, symbols);
83
+ else prewarmCodeGraph(cwd);
84
+ return `prewarm scheduled: cwd=${cwd} symbols=${symbols.length}${symbols.length ? ` (${symbols.slice(0, 5).join(',')}${symbols.length > 5 ? `,+${symbols.length - 5}` : ''})` : ''}`;
85
+ }
86
+
87
+ const graph = await buildCodeGraphAsync(cwd, signal);
88
+ if (!graph || graph.nodes.size === 0) {
89
+ throw new Error(`code_graph: cwd '${cwd}' is not an indexed/known project root or contains zero eligible files`);
90
+ }
91
+ if (options?.scopedCacheOutcome && graph.truncated) {
92
+ markScopedCacheIncomplete(options.scopedCacheOutcome);
93
+ }
94
+ const normFile = normalizeInputPath(args?.file);
95
+ const abs = normFile ? (isAbsolute(normFile) ? pathResolve(normFile) : pathResolve(cwd, normFile)) : null;
96
+ let fileIsDirectory = false;
97
+ if (abs) {
98
+ try { fileIsDirectory = statSync(abs).isDirectory(); } catch { fileIsDirectory = false; }
99
+ }
100
+ const rel = abs && !fileIsDirectory ? _graphRel(abs, cwd) : null;
101
+ const scopeRelPrefix = abs && fileIsDirectory
102
+ ? (() => {
103
+ const r = _graphRel(abs, cwd).replace(/\\/g, '/').replace(/\/+$/, '');
104
+ return (!r || r === '.') ? null : `${r}/`;
105
+ })()
106
+ : null;
107
+ const node = rel ? graph.nodes.get(rel) : null;
108
+
109
+ if (mode === 'overview') {
110
+ if (rel && !node) return _appendSameBasenameHint(`Error: code_graph overview: file not found in graph: ${normFile}`, normFile, graph);
111
+ if (node) return _buildExplainerFileSummary(node, graph, cwd);
112
+ const byLang = new Map();
113
+ for (const node of graph.nodes.values()) {
114
+ byLang.set(node.lang, (byLang.get(node.lang) || 0) + 1);
115
+ }
116
+ const lines = [
117
+ `files\t${graph.nodes.size}`,
118
+ `edges\t${Array.from(graph.nodes.values()).reduce((sum, n) => sum + n.resolvedImports.length, 0)}`,
119
+ ];
120
+ for (const [lang, count] of [...byLang.entries()].sort((a, b) => b[1] - a[1])) {
121
+ lines.push(`${lang}\t${count}`);
122
+ }
123
+ if (graph?.truncated) {
124
+ lines.push(`WARN: graph truncated at CODE_GRAPH_MAX_FILES=${CODE_GRAPH_MAX_FILES} — some files under cwd were not indexed`);
125
+ }
126
+ return lines.join('\n');
127
+ }
128
+
129
+ if (mode === 'imports') {
130
+ if (!node) return _appendSameBasenameHint(`Error: code_graph imports: file not found in graph: ${normFile || '(missing file)'}`, normFile, graph);
131
+ const GRAPH_LIST_CAP = 200;
132
+ const resolvedAll = node.resolvedImports.map((p) => _graphRel(p, cwd));
133
+ const rawAll = node.rawImports;
134
+ const resolved = resolvedAll.slice(0, GRAPH_LIST_CAP);
135
+ const raw = rawAll.slice(0, GRAPH_LIST_CAP);
136
+ const parts = [];
137
+ if (resolved.length) parts.push(resolved.join('\n'));
138
+ if (raw.length) parts.push(`# raw\n${raw.join('\n')}`);
139
+ if (resolvedAll.length > resolved.length || rawAll.length > raw.length) {
140
+ parts.push(`[truncated — showing first ${GRAPH_LIST_CAP} of ${resolvedAll.length} resolved / ${rawAll.length} raw imports]`);
141
+ }
142
+ return parts.join('\n\n') || '(no imports)';
143
+ }
144
+
145
+ if (mode === 'dependents') {
146
+ if (!rel) throw new Error('code_graph dependents: "file" is required');
147
+ if (!node) return _appendSameBasenameHint(`Error: code_graph dependents: file not found in graph: ${normFile || '(missing file)'}`, normFile, graph);
148
+ const GRAPH_LIST_CAP = 200;
149
+ const depsAll = [...(graph.reverse.get(rel) || [])].sort();
150
+ if (!depsAll.length) return '(no dependents)';
151
+ const deps = depsAll.slice(0, GRAPH_LIST_CAP);
152
+ const basename = rel.split('/').pop();
153
+ const stem = basename.replace(/\.[^/.]+$/, '');
154
+ const enriched = deps.map((dep) => {
155
+ const depNode = graph.nodes.get(dep);
156
+ if (!depNode) return dep;
157
+ let text;
158
+ try { text = readFileSync(depNode.abs, 'utf8'); } catch { return dep; }
159
+ const linesArr = text.split(/\r?\n/);
160
+ for (let i = 0; i < linesArr.length; i++) {
161
+ const ln = linesArr[i];
162
+ if (!/(?:^|\W)(?:import|require)\b|\bfrom\s*['"]/.test(ln)) continue;
163
+ if (ln.includes(`/${basename}`) || ln.includes(`/${stem}`) || ln.includes(`'${basename}'`) || ln.includes(`"${basename}"`)) {
164
+ return `${dep}:${i + 1}`;
165
+ }
166
+ }
167
+ return dep;
168
+ });
169
+ const out = enriched.join('\n');
170
+ return depsAll.length > deps.length
171
+ ? `${out}\n[truncated — showing first ${GRAPH_LIST_CAP} of ${depsAll.length} dependents]`
172
+ : out;
173
+ }
174
+
175
+ if (mode === 'related') {
176
+ if (!node) return _appendSameBasenameHint(`Error: code_graph related: file not found in graph: ${normFile || '(missing file)'}`, normFile, graph);
177
+ return _formatRelated(node, graph, cwd);
178
+ }
179
+
180
+ if (mode === 'impact') {
181
+ if (!node) return _appendSameBasenameHint(`Error: code_graph impact: file not found in graph: ${normFile || '(missing file)'}`, normFile, graph);
182
+ const targetSymbol = String(args?.symbol || '').trim();
183
+ return _formatImpact(node, graph, cwd, targetSymbol);
184
+ }
185
+
186
+ if (mode === 'callees') {
187
+ const symbol = String(args?.symbol || '').trim();
188
+ if (!symbol) throw new Error('code_graph callees: "symbol" is required.');
189
+ const explicitLanguage = String(args?.language || '').trim() || null;
190
+ if (rel && !node) return _appendSameBasenameHint(`Error: code_graph callees: file not found in graph: ${normFile || '(missing file)'}`, normFile, graph);
191
+ const allHits = _findSymbolHits(graph, symbol, { language: explicitLanguage });
192
+ const hits = rel ? allHits.filter((h) => h.rel === rel) : allHits;
193
+ const declHit = hits.find((h) => h.declarationLike) || hits[0];
194
+ if (!declHit) {
195
+ const scopeNote = rel ? ` file=${rel}` : '';
196
+ return `(no symbol matches in cwd=${cwd}${scopeNote})`;
197
+ }
198
+ if (!_CALLEES_BRACE_LANGS.has(declHit.lang)) {
199
+ return `(callees unsupported for ${declHit.lang})`;
200
+ }
201
+ const rows = _extractCallees(graph, declHit, cwd, {
202
+ cap: 200,
203
+ callerSymbol: symbol,
204
+ language: explicitLanguage,
205
+ });
206
+ if (!rows.length) return `(no callees)`;
207
+ const out = ['# callees'];
208
+ for (const row of rows) out.push(_formatCalleeRow(row));
209
+ return out.join('\n');
210
+ }
211
+
212
+ if (mode === 'symbols') {
213
+ if (!node) return _appendSameBasenameHint(`Error: code_graph symbols: file not found in graph: ${normFile || '(missing file)'}`, normFile, graph);
214
+ let text = '';
215
+ try { text = readFileSync(node.abs, 'utf8'); } catch { return '(no symbols)'; }
216
+ return _extractSymbolsCheap(text, node.lang);
217
+ }
218
+
219
+ if (mode === 'find_symbol') {
220
+ const symbol = String(args?.symbol || '').trim();
221
+ if (!symbol) throw new Error('code_graph find_symbol: "symbol" is required.');
222
+ const language = String(args?.language || '').trim() || null;
223
+ const limit = Math.max(1, Math.min(50, Number(args?.limit || 20)));
224
+ if (rel && !node) return _appendSameBasenameHint(`Error: code_graph find_symbol: file not found in graph: ${normFile || '(missing file)'}`, normFile, graph);
225
+ return _findSymbolAcrossGraph(graph, symbol, cwd, { language, limit, fileRel: rel, body: args?.body !== false });
226
+ }
227
+
228
+ if (mode === 'symbol_search') {
229
+ const language = String(args?.language || '').trim() || null;
230
+ const limit = Math.max(1, Math.min(100, Number(args?.limit || 30)));
231
+ const symbolsList = Array.isArray(args?.symbols)
232
+ ? args.symbols.map((s) => String(s || '').trim()).filter(Boolean)
233
+ : [];
234
+ const keyword = String(args?.symbol || '').trim();
235
+ const keywords = symbolsList.length ? symbolsList : (keyword ? [keyword] : []);
236
+ if (!keywords.length) throw new Error('code_graph symbol_search: "symbol" (or "symbols[]") is required.');
237
+ if (keywords.length === 1) {
238
+ return _searchSymbolsByKeyword(graph, keywords[0], cwd, { language, limit });
239
+ }
240
+ // Batch: merge results across symbols, dedupe identical result blocks.
241
+ const seen = new Set();
242
+ const sections = [];
243
+ for (const kw of keywords) {
244
+ const result = _searchSymbolsByKeyword(graph, kw, cwd, { language, limit });
245
+ if (seen.has(result)) continue;
246
+ seen.add(result);
247
+ sections.push(`# symbol_search: ${kw}\n${result}`);
248
+ }
249
+ return sections.join('\n\n');
250
+ }
251
+
252
+ if (mode === 'references') {
253
+ const symbol = String(args?.symbol || '').trim();
254
+ if (!symbol) throw new Error('code_graph references: "symbol" is required.');
255
+ const explicitLanguage = String(args?.language || '').trim() || null;
256
+ if (explicitLanguage) {
257
+ const langHasFiles = [...graph.nodes.values()].some((n) => n.lang === explicitLanguage);
258
+ if (!langHasFiles) {
259
+ throw new Error(`code_graph references: language '${explicitLanguage}' has no adapter topLevelTypes and is not in supportedRegexLangs for this project`);
260
+ }
261
+ }
262
+ const narrowedByCaller = Boolean(rel || scopeRelPrefix || explicitLanguage);
263
+ const resolved = _resolveReferenceLanguageNode(graph, symbol, rel, cwd, explicitLanguage);
264
+ if (rel && resolved.kind === 'file-not-found') {
265
+ return _appendSameBasenameHint(`Error: code_graph references: file not found in graph: ${normFile || '(missing file)'}`, normFile, graph);
266
+ }
267
+ if (rel && resolved.kind === 'symbol-not-present') {
268
+ return `Error: code_graph references: symbol "${symbol}" not found in ${normFile || rel}`;
269
+ }
270
+ const resolvedNode = resolved.kind === 'ok' ? resolved.node : null;
271
+ const lang = explicitLanguage
272
+ || ((narrowedByCaller && resolvedNode) ? resolvedNode.lang : null);
273
+ const rawLimit = Number(args?.limit);
274
+ const userLimit = Number.isFinite(rawLimit) && rawLimit > 0
275
+ ? Math.min(500, Math.floor(rawLimit))
276
+ : null;
277
+ await _prewarmReferenceSourceText(graph, symbol, lang);
278
+ const refResult = _cheapReferenceSearch(graph, symbol, cwd, { language: lang, limit: userLimit, fileRel: rel, scopeRelPrefix });
279
+ return narrowedByCaller ? refResult : _augmentNoHitDiagnostic(refResult, '(no references)', graph, cwd, symbol);
280
+ }
281
+
282
+ if (mode === 'callers') {
283
+ const symbol = String(args?.symbol || '').trim();
284
+ if (!symbol) throw new Error('code_graph callers: "symbol" is required.');
285
+ const explicitLanguage = String(args?.language || '').trim() || null;
286
+ if (explicitLanguage) {
287
+ const langHasFiles = [...graph.nodes.values()].some((n) => n.lang === explicitLanguage);
288
+ if (!langHasFiles) {
289
+ throw new Error(`code_graph callers: language '${explicitLanguage}' has no adapter topLevelTypes and is not in supportedRegexLangs for this project`);
290
+ }
291
+ }
292
+ const narrowedByCaller = Boolean(rel || scopeRelPrefix || explicitLanguage);
293
+ const resolved = _resolveReferenceLanguageNode(graph, symbol, rel, cwd, explicitLanguage);
294
+ if (rel && resolved.kind === 'file-not-found') {
295
+ return _appendSameBasenameHint(`Error: code_graph callers: file not found in graph: ${normFile || '(missing file)'}`, normFile, graph);
296
+ }
297
+ if (rel && resolved.kind === 'symbol-not-present') {
298
+ return `Error: code_graph callers: symbol "${symbol}" not found in ${normFile || rel}`;
299
+ }
300
+ const resolvedNode = resolved.kind === 'ok' ? resolved.node : null;
301
+ const lang = explicitLanguage
302
+ || ((narrowedByCaller && resolvedNode) ? resolvedNode.lang : null);
303
+ const rawLimit = Number(args?.limit);
304
+ const userLimit = Number.isFinite(rawLimit) && rawLimit > 0
305
+ ? Math.min(500, Math.floor(rawLimit))
306
+ : null;
307
+ await _prewarmReferenceSourceText(graph, symbol, lang);
308
+ const depth = Math.max(1, Math.min(5, Math.floor(Number(args?.depth) || 1)));
309
+ if (depth > 1) {
310
+ return _formatTransitiveCallers(graph, symbol, cwd, { language: lang, depth, page: args?.page });
311
+ }
312
+ const refs = _cheapReferenceSearch(graph, symbol, cwd, { language: lang, limit: userLimit, fileRel: rel, scopeRelPrefix });
313
+ const callerResult = _formatCallerReferences(graph, symbol, refs, userLimit ? { limit: userLimit } : undefined);
314
+ return narrowedByCaller ? callerResult : _augmentNoHitDiagnostic(callerResult, '(no callers)', graph, cwd, symbol);
315
+ }
316
+
317
+ throw new Error(`code_graph: unknown mode "${mode}"`);
318
+ }
319
+
320
+ async function findSymbolTool(args, cwd, signal = null, options = {}) {
321
+ if (args?.mode === 'prewarm') {
322
+ const _splitMulti = (s) => String(s || '').split(/[,\s]+/).map((t) => t.trim()).filter(Boolean);
323
+ const fromSymbolsArr = Array.isArray(args?.symbols)
324
+ ? args.symbols.map((s) => String(s || '').trim()).filter(Boolean)
325
+ : [];
326
+ const fromSymbolsStr = typeof args?.symbols === 'string' ? _splitMulti(args.symbols) : [];
327
+ const fromSymbolField = typeof args?.symbol === 'string' ? _splitMulti(args.symbol) : [];
328
+ const symbols = [...new Set([...fromSymbolsArr, ...fromSymbolsStr, ...fromSymbolField])];
329
+ if (symbols.length > 0) prewarmCodeGraphSymbols(cwd, symbols);
330
+ else prewarmCodeGraph(cwd);
331
+ return `prewarm scheduled: cwd=${cwd} symbols=${symbols.length}${symbols.length ? ` (${symbols.slice(0, 5).join(',')}${symbols.length > 5 ? `,+${symbols.length - 5}` : ''})` : ''}`;
332
+ }
333
+ const graph = await buildCodeGraphAsync(cwd, signal);
334
+ if (!graph) throw new Error(`find_symbol: cwd '${cwd}' is not an indexed/known project root or contains zero eligible files`);
335
+ if (options?.scopedCacheOutcome && graph.truncated) {
336
+ markScopedCacheIncomplete(options.scopedCacheOutcome);
337
+ }
338
+ const symbol = String(args?.symbol || '').trim();
339
+ const language = String(args?.language || '').trim() || null;
340
+ const limit = Math.max(1, Math.min(50, Number(args?.limit || 20)));
341
+ const normFile = normalizeInputPath(args?.file);
342
+ const abs = normFile ? (isAbsolute(normFile) ? pathResolve(normFile) : pathResolve(cwd, normFile)) : null;
343
+ const fileRel = abs ? _graphRel(abs, cwd) : null;
344
+ if (fileRel && !graph.nodes.get(fileRel)) {
345
+ return _appendSameBasenameHint(`Error: find_symbol: file not found in graph: ${normFile}`, normFile, graph);
346
+ }
347
+ if (!symbol) {
348
+ if (fileRel) {
349
+ const node = graph.nodes.get(fileRel);
350
+ let text = '';
351
+ try { text = readFileSync(node.abs, 'utf8'); } catch { return '(no symbols)'; }
352
+ return _extractSymbolsCheap(text, node.lang);
353
+ }
354
+ throw new Error('find_symbol: provide "symbol" (to locate) or "file" (to list its symbols).');
355
+ }
356
+ return _findSymbolAcrossGraph(graph, symbol, cwd, { language, limit, fileRel, body: args?.body !== false });
357
+ }
358
+
359
+ /**
360
+ * Resolve a symbol name to a 1-based [startLine, endLine] declaration span for read().
361
+ * Returns `{ offset, limit, startLine, endLine, rel, note? }` or `{ error }`.
362
+ */
363
+ export async function resolveSymbolReadSpan(cwd, { symbol, path = null, language = null, line = null } = {}) {
364
+ const cleanSymbol = String(symbol || '').trim();
365
+ if (!cleanSymbol) return { error: 'symbol is required' };
366
+ let graph;
367
+ try {
368
+ graph = await buildCodeGraphAsync(cwd);
369
+ } catch (err) {
370
+ return { error: `symbol read: code graph unavailable (${err?.message || err})` };
371
+ }
372
+ if (!graph) return { error: 'symbol read: code graph could not be built for cwd' };
373
+
374
+ const normFile = path ? normalizeInputPath(path) : null;
375
+ const abs = normFile ? (isAbsolute(normFile) ? pathResolve(normFile) : pathResolve(cwd, normFile)) : null;
376
+ const fileRel = abs ? _graphRel(abs, cwd) : null;
377
+ if (fileRel && !graph.nodes.get(fileRel)) {
378
+ return { error: `symbol '${cleanSymbol}' not found — file not indexed: ${path}; use find_symbol` };
379
+ }
380
+
381
+ let hits = _findSymbolHits(graph, cleanSymbol, { language });
382
+ if (fileRel) hits = hits.filter((h) => h.rel === fileRel);
383
+ if (!hits.length) {
384
+ const scope = fileRel ? ` in ${fileRel}` : '';
385
+ return { error: `symbol '${cleanSymbol}' not found${scope}; use find_symbol to locate it` };
386
+ }
387
+
388
+ const disambigLine = Number(line);
389
+ let primary;
390
+ if (Number.isFinite(disambigLine) && disambigLine > 0) {
391
+ const onLine = hits.filter((h) => h.line === disambigLine);
392
+ primary = _pickCalleeDeclHit(onLine.length ? onLine : hits, fileRel);
393
+ } else {
394
+ primary = _pickCalleeDeclHit(hits, fileRel);
395
+ }
396
+ if (!primary) return { error: `symbol '${cleanSymbol}' not found; use find_symbol` };
397
+
398
+ const startLine = Number(primary.line);
399
+ let endLine = Number(primary.endLine);
400
+ let approximate = false;
401
+ if (!Number.isFinite(startLine) || startLine < 1) {
402
+ return { error: `symbol '${cleanSymbol}' has no valid declaration line; use find_symbol` };
403
+ }
404
+ if (!Number.isFinite(endLine) || endLine < startLine) {
405
+ const node = graph.nodes.get(primary.rel);
406
+ const srcText = node ? _getSourceTextForNode(graph, node) : null;
407
+ const inferred = srcText ? _inferSpanEndByIndent(srcText.split('\n'), startLine) : null;
408
+ if (inferred) {
409
+ endLine = inferred;
410
+ } else {
411
+ endLine = startLine + 79;
412
+ approximate = true;
413
+ }
414
+ }
415
+ const declCount = hits.filter((h) => h.declarationLike).length;
416
+ const notes = [];
417
+ if (approximate) notes.push('end line unknown — approximate range from declaration line');
418
+ if (!fileRel && (hits.length > 1 || declCount > 1)) {
419
+ notes.push('other matches exist — pass path= (and line= to disambiguate) to scope');
420
+ } else if (fileRel && declCount > 1) {
421
+ notes.push(
422
+ `${declCount} declarations of '${cleanSymbol}' in this file — reading the first; pass line= to pick another`,
423
+ );
424
+ }
425
+
426
+ return {
427
+ rel: primary.rel,
428
+ startLine,
429
+ endLine,
430
+ offset: startLine - 1,
431
+ limit: endLine - startLine + 1,
432
+ approximate,
433
+ note: notes.length ? notes.join('; ') : undefined,
434
+ };
435
+ }
436
+
437
+ export async function executeCodeGraphTool(name, args, cwd, signal = null, options = {}) {
438
+ if (!cwd) throw new Error('find_symbol/code_graph requires cwd — caller did not provide a working directory');
439
+ const fileArg = (args && typeof args.file === 'string' && args.file.trim()) ? args.file.trim() : '';
440
+ const baseCwd = (args && typeof args.cwd === 'string' && args.cwd.trim()) ? args.cwd.trim() : cwd;
441
+ let effectiveCwd = baseCwd;
442
+ if (fileArg) {
443
+ const abs = isAbsolute(fileArg) ? pathResolve(fileArg) : pathResolve(baseCwd, fileArg);
444
+ if (!existsSync(abs)) {
445
+ const elsewhere = findFileByBasename(pathResolve(baseCwd), abs);
446
+ const hint = elsewhere.length
447
+ ? ` Same filename exists at: ${elsewhere.map((p) => `"${toDisplayPath(p, baseCwd).replace(/\\/g, '/')}"`).join(', ')}. Use that path.`
448
+ : '';
449
+ return `Error: ${name}: file not found: ${fileArg}${hint}`;
450
+ }
451
+ let fileArgIsDirectory = false;
452
+ try { fileArgIsDirectory = statSync(abs).isDirectory(); } catch { fileArgIsDirectory = false; }
453
+ const rel = pathRelative(pathResolve(baseCwd), abs);
454
+ const insideCwd = rel === '' || (!!rel && !rel.startsWith('..') && !isAbsolute(rel));
455
+ if (!insideCwd) {
456
+ const hasExplicitCwd = args && typeof args.cwd === 'string' && args.cwd.trim();
457
+ if (!hasExplicitCwd) {
458
+ const fileRoot = fileArgIsDirectory ? _findDirProjectRoot(abs) : _resolveFileProjectRoot(abs);
459
+ if (!fileRoot) {
460
+ throw new Error(`find_symbol: file '${fileArg}' is outside cwd '${baseCwd}' and has no detectable project root (no package.json/.git ancestor). Provide an explicit cwd.`);
461
+ }
462
+ effectiveCwd = fileRoot;
463
+ }
464
+ }
465
+ }
466
+ if (!fileArg && !(args && typeof args.cwd === 'string' && args.cwd.trim())) {
467
+ const projectRoot = _findDirProjectRoot(effectiveCwd);
468
+ if (!projectRoot) {
469
+ throw new Error(
470
+ `${name}: cwd '${effectiveCwd}' is not inside a project (no `
471
+ + `${_PROJECT_ROOT_SENTINELS.join('/')} at it or any ancestor). Refusing to `
472
+ + `index an arbitrary tree. Run 'cwd set <repo>', or pass an explicit `
473
+ + `'cwd' (repo root) or a 'file' anchor.`);
474
+ }
475
+ effectiveCwd = projectRoot;
476
+ }
477
+ if (signal?.aborted) throw new Error('aborted');
478
+ const _work = (() => {
479
+ switch (name) {
480
+ case 'code_graph': {
481
+ const rawMode = String(args?.mode || '').trim();
482
+ const batchMode = rawMode === 'search' ? 'symbol_search' : rawMode;
483
+ const declModes = new Set(['symbol', 'find_symbol']);
484
+ const dispatchOne = (a) => (declModes.has(rawMode)
485
+ ? findSymbolTool(_stripEmptyArgs(a), effectiveCwd, signal, options)
486
+ : codeGraph(a, effectiveCwd, signal, options));
487
+ if (CODE_GRAPH_BATCHABLE_MODES.has(batchMode)) {
488
+ const symbolList = _collectGraphSymbolList(args);
489
+ if (symbolList.length > 1) {
490
+ return (async () => {
491
+ const sections = [];
492
+ for (const sym of symbolList) {
493
+ let body;
494
+ try { body = await dispatchOne({ ...args, symbol: sym, symbols: undefined }); }
495
+ catch (e) { body = `Error: ${e?.message || String(e)}`; }
496
+ sections.push(`# ${batchMode} ${sym}\n${body}`);
497
+ }
498
+ return sections.join('\n\n');
499
+ })();
500
+ }
501
+ if (symbolList.length === 1 && args?.symbol !== symbolList[0]) {
502
+ return dispatchOne({ ...args, symbol: symbolList[0], symbols: undefined });
503
+ }
504
+ }
505
+ if (CODE_GRAPH_FILE_BATCHABLE_MODES.has(batchMode)) {
506
+ const fileList = _collectGraphFileList(args);
507
+ if (fileList.length > 1) {
508
+ const capped = fileList._capped;
509
+ return (async () => {
510
+ const sections = [];
511
+ for (const f of fileList) {
512
+ let body;
513
+ try { body = await dispatchOne({ ...args, file: f, files: undefined }); }
514
+ catch (e) { body = `Error: ${e?.message || String(e)}`; }
515
+ sections.push(`# ${batchMode} ${f}\n${body}`);
516
+ }
517
+ if (capped) sections.push(`Note: file list capped at ${CODE_GRAPH_FILE_BATCH_CAP} entries.`);
518
+ return sections.join('\n\n');
519
+ })();
520
+ }
521
+ if (fileList.length === 1 && args?.file !== fileList[0]) {
522
+ return dispatchOne({ ...args, file: fileList[0], files: undefined });
523
+ }
524
+ }
525
+ return dispatchOne(args);
526
+ }
527
+ default: throw new Error(`Unknown code-graph tool: ${name}`);
528
+ }
529
+ })();
530
+ if (!signal) return _work;
531
+ let onAbort = null;
532
+ const abortP = new Promise((_, reject) => {
533
+ if (signal.aborted) { reject(new Error('aborted')); return; }
534
+ onAbort = () => reject(new Error('aborted'));
535
+ signal.addEventListener('abort', onAbort, { once: true });
536
+ });
537
+ const cleanup = () => {
538
+ if (onAbort) {
539
+ try { signal.removeEventListener('abort', onAbort); } catch {}
540
+ onAbort = null;
541
+ }
542
+ };
543
+ return Promise.race([_work, abortP]).then(
544
+ (v) => { cleanup(); return v; },
545
+ (e) => { cleanup(); throw e; },
546
+ );
547
+ }
548
+
549
+ export function isCodeGraphTool(name) {
550
+ return CODE_GRAPH_TOOL_DEFS.some((t) => t.name === name);
551
+ }