@neurocode-ai/core 1.18.8

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 (490) hide show
  1. package/bin/neurocode +199 -0
  2. package/bunfig.toml +2 -0
  3. package/drizzle.config.ts +10 -0
  4. package/package.json +131 -0
  5. package/schema.json +2071 -0
  6. package/script/fix-node-pty.ts +28 -0
  7. package/script/migration.ts +196 -0
  8. package/src/account/sql.ts +39 -0
  9. package/src/account.ts +101 -0
  10. package/src/agent.ts +111 -0
  11. package/src/aisdk.ts +235 -0
  12. package/src/background-job.ts +365 -0
  13. package/src/catalog.ts +301 -0
  14. package/src/command.ts +64 -0
  15. package/src/config/agent.ts +25 -0
  16. package/src/config/attachments.ts +15 -0
  17. package/src/config/command.ts +12 -0
  18. package/src/config/compaction.ts +15 -0
  19. package/src/config/experimental.ts +18 -0
  20. package/src/config/formatter.ts +12 -0
  21. package/src/config/lsp.ts +18 -0
  22. package/src/config/markdown.ts +36 -0
  23. package/src/config/mcp.ts +48 -0
  24. package/src/config/plugin/agent.ts +179 -0
  25. package/src/config/plugin/command.ts +83 -0
  26. package/src/config/plugin/external.ts +91 -0
  27. package/src/config/plugin/provider.ts +113 -0
  28. package/src/config/plugin/reference.ts +70 -0
  29. package/src/config/plugin/skill.ts +50 -0
  30. package/src/config/plugin.ts +13 -0
  31. package/src/config/provider.ts +71 -0
  32. package/src/config/reference.ts +22 -0
  33. package/src/config/tool-output.ts +9 -0
  34. package/src/config/watcher.ts +7 -0
  35. package/src/config.ts +227 -0
  36. package/src/control-plane/move-session.ts +148 -0
  37. package/src/control-plane/workspace.sql.ts +20 -0
  38. package/src/credential/sql.ts +14 -0
  39. package/src/credential.ts +138 -0
  40. package/src/cross-spawn-spawner.ts +507 -0
  41. package/src/data-migration.sql.ts +6 -0
  42. package/src/database/database.ts +57 -0
  43. package/src/database/migration/20260127222353_familiar_lady_ursula.ts +107 -0
  44. package/src/database/migration/20260211171708_add_project_commands.ts +11 -0
  45. package/src/database/migration/20260213144116_wakeful_the_professor.ts +23 -0
  46. package/src/database/migration/20260225215848_workspace.ts +19 -0
  47. package/src/database/migration/20260227213759_add_session_workspace_id.ts +12 -0
  48. package/src/database/migration/20260228203230_blue_harpoon.ts +30 -0
  49. package/src/database/migration/20260303231226_add_workspace_fields.ts +15 -0
  50. package/src/database/migration/20260309230000_move_org_to_state.ts +15 -0
  51. package/src/database/migration/20260312043431_session_message_cursor.ts +16 -0
  52. package/src/database/migration/20260323234822_events.ts +26 -0
  53. package/src/database/migration/20260410174513_workspace-name.ts +29 -0
  54. package/src/database/migration/20260413175956_chief_energizer.ts +24 -0
  55. package/src/database/migration/20260423070820_add_icon_url_override.ts +14 -0
  56. package/src/database/migration/20260427172553_slow_nightmare.ts +30 -0
  57. package/src/database/migration/20260428004200_add_session_path.ts +11 -0
  58. package/src/database/migration/20260501142318_next_venus.ts +12 -0
  59. package/src/database/migration/20260504145000_add_sync_owner.ts +11 -0
  60. package/src/database/migration/20260507164347_add_workspace_time.ts +11 -0
  61. package/src/database/migration/20260510033149_session_usage.ts +56 -0
  62. package/src/database/migration/20260511000411_data_migration_state.ts +16 -0
  63. package/src/database/migration/20260511173437_session-metadata.ts +16 -0
  64. package/src/database/migration/20260601010001_normalize_storage_paths.ts +22 -0
  65. package/src/database/migration/20260601202201_amazing_prowler.ts +11 -0
  66. package/src/database/migration/20260602002951_lowly_union_jack.ts +24 -0
  67. package/src/database/migration/20260602182828_add_project_directories.ts +20 -0
  68. package/src/database/migration/20260603001617_session_message_projection_indexes.ts +19 -0
  69. package/src/database/migration/20260603040000_session_message_projection_order.ts +19 -0
  70. package/src/database/migration/20260603141458_session_input_inbox.ts +25 -0
  71. package/src/database/migration/20260603160727_jittery_ezekiel_stane.ts +20 -0
  72. package/src/database/migration/20260604172448_event_sourced_session_input.ts +47 -0
  73. package/src/database/migration/20260605003541_add_session_context_snapshot.ts +21 -0
  74. package/src/database/migration/20260605042240_add_context_epoch_agent.ts +11 -0
  75. package/src/database/migration/20260611035744_credential.ts +25 -0
  76. package/src/database/migration/20260611192811_lush_chimera.ts +25 -0
  77. package/src/database/migration/20260612174303_project_dir_strategy.ts +29 -0
  78. package/src/database/migration/20260622142730_simplify_session_context_epoch.ts +13 -0
  79. package/src/database/migration/20260622170816_reset_v2_session_state.ts +17 -0
  80. package/src/database/migration/20260622202450_simplify_session_input.ts +17 -0
  81. package/src/database/migration.gen.ts +44 -0
  82. package/src/database/migration.ts +81 -0
  83. package/src/database/path.ts +91 -0
  84. package/src/database/schema.gen.ts +274 -0
  85. package/src/database/schema.sql.ts +10 -0
  86. package/src/database/sqlite.bun.ts +183 -0
  87. package/src/database/sqlite.node.ts +178 -0
  88. package/src/database/sqlite.ts +8 -0
  89. package/src/effect/app-node-builder.ts +23 -0
  90. package/src/effect/app-node-platform.ts +18 -0
  91. package/src/effect/app-node.ts +14 -0
  92. package/src/effect/dfdf +1 -0
  93. package/src/effect/keyed-mutex.ts +45 -0
  94. package/src/effect/layer-node.ts +333 -0
  95. package/src/effect/memo-map.ts +3 -0
  96. package/src/effect/runtime.ts +21 -0
  97. package/src/effect/service-use.ts +43 -0
  98. package/src/event/sql.ts +25 -0
  99. package/src/event.ts +638 -0
  100. package/src/file-mutation.ts +207 -0
  101. package/src/file.ts +6 -0
  102. package/src/filesystem/fff.bun.ts +140 -0
  103. package/src/filesystem/fff.node.ts +138 -0
  104. package/src/filesystem/ignore.ts +67 -0
  105. package/src/filesystem/protected.ts +53 -0
  106. package/src/filesystem/search.ts +239 -0
  107. package/src/filesystem/watcher.ts +140 -0
  108. package/src/filesystem.ts +118 -0
  109. package/src/flag/flag.ts +78 -0
  110. package/src/fs-util.ts +274 -0
  111. package/src/git.ts +987 -0
  112. package/src/github-copilot/README.md +5 -0
  113. package/src/github-copilot/chat/convert-to-openai-compatible-chat-messages.ts +170 -0
  114. package/src/github-copilot/chat/get-response-metadata.ts +15 -0
  115. package/src/github-copilot/chat/map-openai-compatible-finish-reason.ts +19 -0
  116. package/src/github-copilot/chat/openai-compatible-api-types.ts +64 -0
  117. package/src/github-copilot/chat/openai-compatible-chat-language-model.ts +815 -0
  118. package/src/github-copilot/chat/openai-compatible-chat-options.ts +28 -0
  119. package/src/github-copilot/chat/openai-compatible-metadata-extractor.ts +44 -0
  120. package/src/github-copilot/chat/openai-compatible-prepare-tools.ts +83 -0
  121. package/src/github-copilot/copilot-provider.ts +100 -0
  122. package/src/github-copilot/openai-compatible-error.ts +27 -0
  123. package/src/github-copilot/responses/convert-to-openai-responses-input.ts +335 -0
  124. package/src/github-copilot/responses/map-openai-responses-finish-reason.ts +22 -0
  125. package/src/github-copilot/responses/openai-config.ts +18 -0
  126. package/src/github-copilot/responses/openai-error.ts +22 -0
  127. package/src/github-copilot/responses/openai-responses-api-types.ts +214 -0
  128. package/src/github-copilot/responses/openai-responses-language-model.ts +1770 -0
  129. package/src/github-copilot/responses/openai-responses-prepare-tools.ts +173 -0
  130. package/src/github-copilot/responses/openai-responses-settings.ts +1 -0
  131. package/src/github-copilot/responses/tool/code-interpreter.ts +87 -0
  132. package/src/github-copilot/responses/tool/file-search.ts +127 -0
  133. package/src/github-copilot/responses/tool/image-generation.ts +114 -0
  134. package/src/github-copilot/responses/tool/local-shell.ts +64 -0
  135. package/src/github-copilot/responses/tool/web-search-preview.ts +103 -0
  136. package/src/github-copilot/responses/tool/web-search.ts +102 -0
  137. package/src/global.ts +87 -0
  138. package/src/id/id.ts +47 -0
  139. package/src/image/photon.ts +94 -0
  140. package/src/image.ts +81 -0
  141. package/src/installation/version.ts +8 -0
  142. package/src/instruction-context.ts +101 -0
  143. package/src/integration/connection.ts +12 -0
  144. package/src/integration.ts +520 -0
  145. package/src/location-mutation.ts +162 -0
  146. package/src/location-service-map.ts +18 -0
  147. package/src/location-services.ts +115 -0
  148. package/src/location.ts +39 -0
  149. package/src/markdown.d.ts +4 -0
  150. package/src/model.ts +41 -0
  151. package/src/models-dev.ts +260 -0
  152. package/src/npm-config.ts +40 -0
  153. package/src/npm.ts +269 -0
  154. package/src/oauth/page.ts +276 -0
  155. package/src/observability/logging.ts +71 -0
  156. package/src/observability/otlp.ts +79 -0
  157. package/src/observability/shared.ts +1 -0
  158. package/src/observability.ts +24 -0
  159. package/src/patch.ts +197 -0
  160. package/src/permission/saved.ts +79 -0
  161. package/src/permission/sql.ts +20 -0
  162. package/src/permission.ts +310 -0
  163. package/src/plugin/agent.ts +206 -0
  164. package/src/plugin/command/initialize.txt +65 -0
  165. package/src/plugin/command/review.txt +100 -0
  166. package/src/plugin/command.ts +25 -0
  167. package/src/plugin/host.ts +219 -0
  168. package/src/plugin/internal.ts +153 -0
  169. package/src/plugin/layer-map.example.ts +94 -0
  170. package/src/plugin/models-dev.ts +183 -0
  171. package/src/plugin/promise.ts +93 -0
  172. package/src/plugin/provider/alibaba.ts +15 -0
  173. package/src/plugin/provider/amazon-bedrock.ts +126 -0
  174. package/src/plugin/provider/anthropic.ts +27 -0
  175. package/src/plugin/provider/azure.ts +82 -0
  176. package/src/plugin/provider/cerebras.ts +26 -0
  177. package/src/plugin/provider/cloudflare-ai-gateway.ts +81 -0
  178. package/src/plugin/provider/cloudflare-workers-ai.ts +81 -0
  179. package/src/plugin/provider/cohere.ts +15 -0
  180. package/src/plugin/provider/deepinfra.ts +15 -0
  181. package/src/plugin/provider/dynamic.ts +31 -0
  182. package/src/plugin/provider/gateway.ts +15 -0
  183. package/src/plugin/provider/github-copilot.ts +52 -0
  184. package/src/plugin/provider/gitlab.ts +65 -0
  185. package/src/plugin/provider/google-vertex.ts +173 -0
  186. package/src/plugin/provider/google.ts +15 -0
  187. package/src/plugin/provider/groq.ts +15 -0
  188. package/src/plugin/provider/kilo.ts +21 -0
  189. package/src/plugin/provider/llmgateway.ts +26 -0
  190. package/src/plugin/provider/mistral.ts +15 -0
  191. package/src/plugin/provider/nvidia.ts +22 -0
  192. package/src/plugin/provider/openai-compatible.ts +17 -0
  193. package/src/plugin/provider/openai.ts +292 -0
  194. package/src/plugin/provider/opencode.ts +311 -0
  195. package/src/plugin/provider/openrouter.ts +36 -0
  196. package/src/plugin/provider/perplexity.ts +15 -0
  197. package/src/plugin/provider/sap-ai-core.ts +46 -0
  198. package/src/plugin/provider/snowflake-cortex.ts +89 -0
  199. package/src/plugin/provider/togetherai.ts +15 -0
  200. package/src/plugin/provider/venice.ts +15 -0
  201. package/src/plugin/provider/vercel.ts +27 -0
  202. package/src/plugin/provider/xai.ts +22 -0
  203. package/src/plugin/provider/zenmux.ts +21 -0
  204. package/src/plugin/provider.ts +71 -0
  205. package/src/plugin/skill/customize-neurocode.md +452 -0
  206. package/src/plugin/skill.ts +31 -0
  207. package/src/plugin/variant.ts +39 -0
  208. package/src/plugin.ts +167 -0
  209. package/src/policy.ts +49 -0
  210. package/src/process.ts +261 -0
  211. package/src/project/copy-strategies.ts +35 -0
  212. package/src/project/copy.ts +292 -0
  213. package/src/project/directories.ts +158 -0
  214. package/src/project/schema.ts +16 -0
  215. package/src/project/sql.ts +35 -0
  216. package/src/project.ts +136 -0
  217. package/src/provider.ts +25 -0
  218. package/src/pty/protocol.ts +37 -0
  219. package/src/pty/pty.bun.ts +26 -0
  220. package/src/pty/pty.node.ts +29 -0
  221. package/src/pty/pty.ts +25 -0
  222. package/src/pty/schema.ts +1 -0
  223. package/src/pty/ticket.ts +56 -0
  224. package/src/pty.ts +318 -0
  225. package/src/public-event-manifest.ts +7 -0
  226. package/src/question.ts +153 -0
  227. package/src/reference/guidance.ts +69 -0
  228. package/src/reference.ts +125 -0
  229. package/src/repository-cache.ts +259 -0
  230. package/src/repository.ts +214 -0
  231. package/src/ripgrep/binary.ts +132 -0
  232. package/src/ripgrep.ts +281 -0
  233. package/src/schema.ts +79 -0
  234. package/src/session/compaction.ts +241 -0
  235. package/src/session/context-epoch.ts +174 -0
  236. package/src/session/error.ts +24 -0
  237. package/src/session/event.ts +2 -0
  238. package/src/session/execution/local.ts +46 -0
  239. package/src/session/execution.ts +34 -0
  240. package/src/session/history.ts +101 -0
  241. package/src/session/info.ts +50 -0
  242. package/src/session/input.ts +288 -0
  243. package/src/session/message-updater.ts +397 -0
  244. package/src/session/message.ts +2 -0
  245. package/src/session/projector.ts +458 -0
  246. package/src/session/prompt.ts +1 -0
  247. package/src/session/revert.ts +121 -0
  248. package/src/session/run-coordinator.ts +104 -0
  249. package/src/session/runner/index.ts +28 -0
  250. package/src/session/runner/llm.ts +432 -0
  251. package/src/session/runner/max-steps.ts +16 -0
  252. package/src/session/runner/model.ts +218 -0
  253. package/src/session/runner/publish-llm-event.ts +423 -0
  254. package/src/session/runner/to-llm-message.ts +171 -0
  255. package/src/session/schema.ts +9 -0
  256. package/src/session/sql.ts +176 -0
  257. package/src/session/store.ts +63 -0
  258. package/src/session/todo.ts +78 -0
  259. package/src/session.ts +486 -0
  260. package/src/share/sql.ts +13 -0
  261. package/src/shell.ts +226 -0
  262. package/src/skill/discovery.ts +213 -0
  263. package/src/skill/guidance.ts +76 -0
  264. package/src/skill.ts +132 -0
  265. package/src/snapshot.ts +266 -0
  266. package/src/state.ts +128 -0
  267. package/src/system-context/builtins.ts +50 -0
  268. package/src/system-context/index.ts +320 -0
  269. package/src/system-context/registry.ts +49 -0
  270. package/src/tool/AGENTS.md +59 -0
  271. package/src/tool/application-tools.ts +57 -0
  272. package/src/tool/apply-patch.ts +219 -0
  273. package/src/tool/bash.ts +207 -0
  274. package/src/tool/builtins.ts +48 -0
  275. package/src/tool/edit.ts +223 -0
  276. package/src/tool/glob.ts +105 -0
  277. package/src/tool/grep.ts +137 -0
  278. package/src/tool/http-body.ts +30 -0
  279. package/src/tool/question.ts +94 -0
  280. package/src/tool/read-filesystem.ts +366 -0
  281. package/src/tool/read.ts +117 -0
  282. package/src/tool/registry.ts +147 -0
  283. package/src/tool/skill.ts +109 -0
  284. package/src/tool/todowrite.ts +62 -0
  285. package/src/tool/tool.ts +162 -0
  286. package/src/tool/tools.ts +13 -0
  287. package/src/tool/webfetch.ts +218 -0
  288. package/src/tool/websearch.ts +260 -0
  289. package/src/tool/write.ts +101 -0
  290. package/src/tool-output-store.ts +211 -0
  291. package/src/util/array.ts +10 -0
  292. package/src/util/binary.ts +41 -0
  293. package/src/util/effect-flock.ts +284 -0
  294. package/src/util/encode.ts +51 -0
  295. package/src/util/error.ts +70 -0
  296. package/src/util/flock.ts +358 -0
  297. package/src/util/glob.ts +34 -0
  298. package/src/util/hash.ts +11 -0
  299. package/src/util/identifier.ts +1 -0
  300. package/src/util/iife.ts +3 -0
  301. package/src/util/lazy.ts +11 -0
  302. package/src/util/module.ts +10 -0
  303. package/src/util/path.ts +37 -0
  304. package/src/util/retry.ts +42 -0
  305. package/src/util/slug.ts +74 -0
  306. package/src/util/token.ts +5 -0
  307. package/src/util/which.ts +14 -0
  308. package/src/util/wildcard.ts +14 -0
  309. package/src/v1/config/agent.ts +89 -0
  310. package/src/v1/config/attachment.ts +25 -0
  311. package/src/v1/config/command.ts +13 -0
  312. package/src/v1/config/config.ts +192 -0
  313. package/src/v1/config/console-state.ts +16 -0
  314. package/src/v1/config/error.ts +39 -0
  315. package/src/v1/config/formatter.ts +13 -0
  316. package/src/v1/config/layout.ts +6 -0
  317. package/src/v1/config/lsp.ts +80 -0
  318. package/src/v1/config/mcp.ts +63 -0
  319. package/src/v1/config/migrate.ts +254 -0
  320. package/src/v1/config/permission.ts +50 -0
  321. package/src/v1/config/plugin.ts +9 -0
  322. package/src/v1/config/provider-options.ts +227 -0
  323. package/src/v1/config/provider.ts +121 -0
  324. package/src/v1/config/server.ts +19 -0
  325. package/src/v1/config/skills.ts +13 -0
  326. package/src/v1/permission.ts +33 -0
  327. package/src/v1/session.ts +68 -0
  328. package/src/v2-schema.ts +3 -0
  329. package/src/workspace.ts +6 -0
  330. package/sst-env.d.ts +10 -0
  331. package/test/agent.test.ts +131 -0
  332. package/test/application-tools.test.ts +287 -0
  333. package/test/background-job.test.ts +106 -0
  334. package/test/catalog.test.ts +353 -0
  335. package/test/command.test.ts +56 -0
  336. package/test/config/agent.test.ts +349 -0
  337. package/test/config/command.test.ts +83 -0
  338. package/test/config/config.test.ts +798 -0
  339. package/test/config/fixtures/plugin/directory-plugin.ts +13 -0
  340. package/test/config/plugin.test.ts +248 -0
  341. package/test/config/provider-options.test.ts +224 -0
  342. package/test/config/provider.test.ts +269 -0
  343. package/test/config/skill.test.ts +80 -0
  344. package/test/credential.test.ts +36 -0
  345. package/test/database-migration.test.ts +644 -0
  346. package/test/effect/cross-spawn-spawner.test.ts +426 -0
  347. package/test/effect/keyed-mutex.test.ts +73 -0
  348. package/test/effect/layer-node/layer-node-types.test.ts +143 -0
  349. package/test/effect/layer-node/layer-node.test.ts +261 -0
  350. package/test/effect/layer-node/node-build.test.ts +125 -0
  351. package/test/effect/observability.test.ts +109 -0
  352. package/test/event.test.ts +1124 -0
  353. package/test/file-mutation.test.ts +368 -0
  354. package/test/filesystem/filesystem.test.ts +387 -0
  355. package/test/filesystem/ignore.test.ts +10 -0
  356. package/test/filesystem/search.test.ts +44 -0
  357. package/test/filesystem/watcher.test.ts +266 -0
  358. package/test/fixture/effect-flock-worker.ts +60 -0
  359. package/test/fixture/flock-worker.ts +72 -0
  360. package/test/fixture/git.ts +49 -0
  361. package/test/fixture/location.ts +26 -0
  362. package/test/fixture/tmpdir.ts +25 -0
  363. package/test/fixtures/recordings/session-runner/openai-chat-streams-text.json +27 -0
  364. package/test/git.test.ts +164 -0
  365. package/test/github-copilot/convert-to-copilot-messages.test.ts +523 -0
  366. package/test/github-copilot/copilot-chat-model.test.ts +592 -0
  367. package/test/github-copilot/openai-responses-language-model.test.ts +206 -0
  368. package/test/global.test.ts +16 -0
  369. package/test/instruction-context.test.ts +323 -0
  370. package/test/integration.test.ts +349 -0
  371. package/test/legacy-event-schema.test.ts +16 -0
  372. package/test/lib/effect.ts +53 -0
  373. package/test/lib/tool.ts +20 -0
  374. package/test/location-filesystem.test.ts +69 -0
  375. package/test/location-layer.test.ts +226 -0
  376. package/test/location-mutation.test.ts +178 -0
  377. package/test/location.test.ts +42 -0
  378. package/test/model.test.ts +23 -0
  379. package/test/models.test.ts +290 -0
  380. package/test/move-session.test.ts +235 -0
  381. package/test/npm-config.test.ts +51 -0
  382. package/test/npm.test.ts +84 -0
  383. package/test/oauth-page.test.ts +15 -0
  384. package/test/patch.test.ts +68 -0
  385. package/test/permission.test.ts +315 -0
  386. package/test/plugin/command.test.ts +47 -0
  387. package/test/plugin/fixture.ts +52 -0
  388. package/test/plugin/fixtures/config-effect-plugin.ts +15 -0
  389. package/test/plugin/fixtures/config-promise-plugin.ts +13 -0
  390. package/test/plugin/fixtures/invalid-plugin.ts +1 -0
  391. package/test/plugin/fixtures/models-dev.json +14 -0
  392. package/test/plugin/fixtures/provider-factory.ts +9 -0
  393. package/test/plugin/host.ts +303 -0
  394. package/test/plugin/models-dev.test.ts +170 -0
  395. package/test/plugin/promise.test.ts +67 -0
  396. package/test/plugin/provider-alibaba.test.ts +92 -0
  397. package/test/plugin/provider-amazon-bedrock.test.ts +622 -0
  398. package/test/plugin/provider-anthropic.test.ts +94 -0
  399. package/test/plugin/provider-azure-cognitive-services.test.ts +199 -0
  400. package/test/plugin/provider-azure.test.ts +293 -0
  401. package/test/plugin/provider-cerebras.test.ts +136 -0
  402. package/test/plugin/provider-cloudflare-ai-gateway.test.ts +426 -0
  403. package/test/plugin/provider-cloudflare-workers-ai.test.ts +279 -0
  404. package/test/plugin/provider-cohere.test.ts +123 -0
  405. package/test/plugin/provider-deepinfra.test.ts +159 -0
  406. package/test/plugin/provider-dynamic.test.ts +184 -0
  407. package/test/plugin/provider-gateway.test.ts +115 -0
  408. package/test/plugin/provider-github-copilot.test.ts +278 -0
  409. package/test/plugin/provider-gitlab.test.ts +308 -0
  410. package/test/plugin/provider-google-vertex-anthropic.test.ts +264 -0
  411. package/test/plugin/provider-google-vertex.test.ts +387 -0
  412. package/test/plugin/provider-google.test.ts +80 -0
  413. package/test/plugin/provider-groq.test.ts +121 -0
  414. package/test/plugin/provider-kilo.test.ts +99 -0
  415. package/test/plugin/provider-llmgateway.test.ts +80 -0
  416. package/test/plugin/provider-mistral.test.ts +129 -0
  417. package/test/plugin/provider-nvidia.test.ts +97 -0
  418. package/test/plugin/provider-openai-compatible.test.ts +107 -0
  419. package/test/plugin/provider-openai.test.ts +176 -0
  420. package/test/plugin/provider-opencode.test.ts +423 -0
  421. package/test/plugin/provider-openrouter.test.ts +113 -0
  422. package/test/plugin/provider-perplexity.test.ts +122 -0
  423. package/test/plugin/provider-sap-ai-core.test.ts +159 -0
  424. package/test/plugin/provider-snowflake-cortex.test.ts +261 -0
  425. package/test/plugin/provider-togetherai.test.ts +129 -0
  426. package/test/plugin/provider-venice.test.ts +115 -0
  427. package/test/plugin/provider-vercel.test.ts +83 -0
  428. package/test/plugin/provider-xai.test.ts +125 -0
  429. package/test/plugin/provider-zenmux.test.ts +110 -0
  430. package/test/plugin/skill.test.ts +25 -0
  431. package/test/plugin/variant.test.ts +67 -0
  432. package/test/plugin.test.ts +71 -0
  433. package/test/policy.test.ts +85 -0
  434. package/test/preload.ts +5 -0
  435. package/test/process/process.test.ts +368 -0
  436. package/test/project-copy.test.ts +400 -0
  437. package/test/project-directories.test.ts +61 -0
  438. package/test/project.test.ts +221 -0
  439. package/test/provider-mistral.test.ts +282 -0
  440. package/test/provider-xai-responses.test.ts +32 -0
  441. package/test/pty/info-schema.test.ts +32 -0
  442. package/test/pty/protocol.test.ts +27 -0
  443. package/test/pty/pty-session.test.ts +240 -0
  444. package/test/pty/ticket.test.ts +62 -0
  445. package/test/question.test.ts +114 -0
  446. package/test/reference-guidance.test.ts +76 -0
  447. package/test/reference.test.ts +78 -0
  448. package/test/repository-cache.test.ts +153 -0
  449. package/test/repository.test.ts +71 -0
  450. package/test/ripgrep.test.ts +65 -0
  451. package/test/session-compaction.test.ts +27 -0
  452. package/test/session-create.test.ts +425 -0
  453. package/test/session-history.test.ts +165 -0
  454. package/test/session-projector.test.ts +533 -0
  455. package/test/session-prompt.test.ts +584 -0
  456. package/test/session-run-coordinator.test.ts +418 -0
  457. package/test/session-runner-message.test.ts +501 -0
  458. package/test/session-runner-model.test.ts +347 -0
  459. package/test/session-runner-recorded.test.ts +193 -0
  460. package/test/session-runner-tool-events.test.ts +136 -0
  461. package/test/session-runner-tool-registry.test.ts +452 -0
  462. package/test/session-runner.test.ts +3365 -0
  463. package/test/session-todo.test.ts +94 -0
  464. package/test/session-tool-progress.test.ts +158 -0
  465. package/test/shared-schema.test.ts +206 -0
  466. package/test/shell.test.ts +108 -0
  467. package/test/skill/guidance.test.ts +144 -0
  468. package/test/skill-discovery.test.ts +165 -0
  469. package/test/skill.test.ts +125 -0
  470. package/test/snapshot.test.ts +178 -0
  471. package/test/state.test.ts +115 -0
  472. package/test/system-context/builtins.test.ts +129 -0
  473. package/test/system-context/index.test.ts +307 -0
  474. package/test/system-context/registry.test.ts +114 -0
  475. package/test/tool-apply-patch.test.ts +436 -0
  476. package/test/tool-bash.test.ts +437 -0
  477. package/test/tool-edit.test.ts +434 -0
  478. package/test/tool-output-store.test.ts +247 -0
  479. package/test/tool-question.test.ts +162 -0
  480. package/test/tool-read-filesystem.test.ts +118 -0
  481. package/test/tool-read.test.ts +674 -0
  482. package/test/tool-skill.test.ts +149 -0
  483. package/test/tool-todowrite.test.ts +125 -0
  484. package/test/tool-webfetch.test.ts +281 -0
  485. package/test/tool-websearch.test.ts +316 -0
  486. package/test/tool-write.test.ts +305 -0
  487. package/test/util/effect-flock.test.ts +392 -0
  488. package/test/util/flock.test.ts +428 -0
  489. package/test/util/which.test.ts +100 -0
  490. package/tsconfig.json +7 -0
@@ -0,0 +1,28 @@
1
+ export * as SessionRunner from "./index"
2
+
3
+ import type { LLMError } from "@neurocode-ai/llm"
4
+ import { Context, Effect } from "effect"
5
+ import { SessionSchema } from "../schema"
6
+ import type { ContextSnapshotDecodeError, MessageDecodeError } from "../error"
7
+ import { SessionRunnerModel } from "./model"
8
+ import type { SystemContext } from "../../system-context/index"
9
+ import type { ToolOutputStore } from "../../tool-output-store"
10
+
11
+ export type RunError =
12
+ | LLMError
13
+ | SessionRunnerModel.Error
14
+ | MessageDecodeError
15
+ | ContextSnapshotDecodeError
16
+ | SystemContext.InitializationBlocked
17
+ | ToolOutputStore.Error
18
+
19
+ /** Runs one local continuation from already-recorded Session history. */
20
+ export interface Interface {
21
+ /** Drains eligible durable work. Explicit runs perform one provider attempt even when no work is eligible. */
22
+ readonly run: (input: {
23
+ readonly sessionID: SessionSchema.ID
24
+ readonly force: boolean
25
+ }) => Effect.Effect<void, RunError>
26
+ }
27
+
28
+ export class Service extends Context.Service<Service, Interface>()("@neurocode/v2/SessionRunner") {}
@@ -0,0 +1,432 @@
1
+ import {
2
+ LLM,
3
+ LLMClient,
4
+ LLMError,
5
+ LLMEvent,
6
+ Message,
7
+ SystemPart,
8
+ isContextOverflowFailure,
9
+ type ProviderErrorEvent,
10
+ } from "@neurocode-ai/llm"
11
+ import { Cause, DateTime, Effect, FiberSet, Layer, Option, Semaphore, Stream } from "effect"
12
+ import { AgentV2 } from "../../agent"
13
+ import { Config } from "../../config"
14
+ import { Database } from "../../database/database"
15
+ import { EventV2 } from "../../event"
16
+ import { Location } from "../../location"
17
+ import { ModelV2 } from "../../model"
18
+ import { PermissionV2 } from "../../permission"
19
+ import { ProviderV2 } from "../../provider"
20
+ import { QuestionV2 } from "../../question"
21
+ import { SystemContext } from "../../system-context/index"
22
+ import { SystemContextRegistry } from "../../system-context/registry"
23
+ import { SkillGuidance } from "../../skill/guidance"
24
+ import { ReferenceGuidance } from "../../reference/guidance"
25
+ import { ToolRegistry } from "../../tool/registry"
26
+ import { ToolOutputStore } from "../../tool-output-store"
27
+ import { SessionContextEpoch } from "../context-epoch"
28
+ import { SessionCompaction } from "../compaction"
29
+ import { SessionEvent } from "../event"
30
+ import { SessionHistory } from "../history"
31
+ import { SessionInput } from "../input"
32
+ import { SessionSchema } from "../schema"
33
+ import { SessionStore } from "../store"
34
+ import { type RunError, Service } from "./index"
35
+ import { SessionRunnerModel } from "./model"
36
+ import { createLLMEventPublisher } from "./publish-llm-event"
37
+ import { toLLMMessages } from "./to-llm-message"
38
+ import { MAX_STEPS_PROMPT } from "./max-steps"
39
+ import { Snapshot } from "../../snapshot"
40
+ import { makeLocationNode } from "../../effect/app-node"
41
+ import { llmClient } from "../../effect/app-node-platform"
42
+
43
+ /**
44
+ * Runs one durable coding-agent Session until it settles.
45
+ *
46
+ * Keep this as orchestration over smaller collaborators rather than rebuilding the legacy
47
+ * `SessionPrompt` monolith. Implement the unchecked items in small reviewed slices:
48
+ *
49
+ * - Session ownership and controls
50
+ * - [x] Coordinate one local active drain per Session; explicit resumes join and prompt wakeups coalesce.
51
+ * - [ ] Replace local ownership with durable multi-node ownership when clustered.
52
+ * - [ ] Mark busy, retrying, idle, interrupted, or terminal-failure status durably.
53
+ * - [ ] Honor interruption and reject stale work after runtime attachment replacement.
54
+ * - [x] Honor optional agent step limits.
55
+ * - [ ] Bound provider retries and repeated identical tool calls.
56
+ *
57
+ * - Runtime context assembly
58
+ * - Track V1 runtime-context parity canonically in `specs/v2/session.md`.
59
+ *
60
+ * - One provider turn
61
+ * - [x] Translate every projected V2 Session message variant into canonical
62
+ * `@neurocode-ai/llm` messages.
63
+ * - [ ] Resolve policy-filtered built-in, MCP, plugin, and structured-output tool definitions.
64
+ * - [x] Stream exactly one `llm.stream(request)` provider turn.
65
+ * - [x] Persist assistant text and usage events incrementally as they arrive.
66
+ * - [ ] Persist snapshots, patches, and retry notices incrementally as they arrive.
67
+ * - [x] Persist reasoning, provider errors, and tool-call events incrementally as they arrive.
68
+ *
69
+ * - Tool settlement and continuation
70
+ * - [x] Durably record each tool call before side effects begin.
71
+ * - [x] Authorize and execute recorded local calls through a core-owned registry hook.
72
+ * - [x] Persist typed success, failure, and provider-executed tool outcomes.
73
+ * - [x] Start each recorded local call eagerly and await all settlements before continuation.
74
+ * - [ ] Add scoped runtime context, progress updates, attachment normalization,
75
+ * plugins, and cancellation settlement.
76
+ * - [x] Reload projected history and start the next explicit provider turn after local tool results.
77
+ * - [x] Continue for durable user steering accepted during an active provider turn.
78
+ * - [ ] Continue for compaction or another continuation condition when required.
79
+ *
80
+ * - Post-run maintenance
81
+ * - [ ] Settle final status and expose durable output events to replayable consumers.
82
+ * - [ ] Coalesce streamed deltas and add covering projected-history indexes.
83
+ * - [ ] Update title, summaries, compaction state, and cleanup in bounded background work.
84
+ *
85
+ * Use `llm.stream(request)` for each provider turn. Keep tool execution and continuation here.
86
+ * Durable continuation recovery remains a separate future slice with an explicit retry policy.
87
+ *
88
+ * The current slice loads V2 history, translates it, resolves a model through a core service, and persists one
89
+ * provider turn. Registry definitions are advertised, local tool calls are settled durably, and an
90
+ * explicit loop starts the next provider turn after local settlement. Configured agent step limits bound the loop.
91
+ */
92
+
93
+ const layer = Layer.effect(
94
+ Service,
95
+ Effect.gen(function* () {
96
+ const events = yield* EventV2.Service
97
+ const llm = yield* LLMClient.Service
98
+ const agents = yield* AgentV2.Service
99
+ const tools = yield* ToolRegistry.Service
100
+ const models = yield* SessionRunnerModel.Service
101
+ const store = yield* SessionStore.Service
102
+ const location = yield* Location.Service
103
+ const systemContext = yield* SystemContextRegistry.Service
104
+ const skillGuidance = yield* SkillGuidance.Service
105
+ const referenceGuidance = yield* ReferenceGuidance.Service
106
+ const config = yield* Config.Service
107
+ const snapshots = yield* Snapshot.Service
108
+ const db = (yield* Database.Service).db
109
+ const compaction = SessionCompaction.make({ events, llm, config: yield* config.entries() })
110
+ const getSession = Effect.fn("SessionRunner.getSession")(function* (sessionID: SessionSchema.ID) {
111
+ const session = yield* store.get(sessionID)
112
+ if (!session) return yield* Effect.die(`Session not found: ${sessionID}`)
113
+ return session
114
+ })
115
+
116
+ const getContext = Effect.fn("SessionRunner.getContext")(function* (sessionID: SessionSchema.ID) {
117
+ return yield* store.context(sessionID)
118
+ })
119
+ const failInterruptedTools = Effect.fn("SessionRunner.failInterruptedTools")(function* (
120
+ sessionID: SessionSchema.ID,
121
+ ) {
122
+ for (const message of yield* getContext(sessionID)) {
123
+ if (message.type !== "assistant") continue
124
+ for (const tool of message.content) {
125
+ if (tool.type !== "tool" || (tool.state.status !== "pending" && tool.state.status !== "running")) continue
126
+ yield* events.publish(SessionEvent.Tool.Failed, {
127
+ sessionID,
128
+ timestamp: yield* DateTime.now,
129
+ assistantMessageID: message.id,
130
+ callID: tool.id,
131
+ error: { type: "unknown", message: "Tool execution interrupted" },
132
+ provider: {
133
+ executed: tool.provider?.executed === true,
134
+ ...(tool.provider?.metadata === undefined ? {} : { metadata: tool.provider.metadata }),
135
+ },
136
+ })
137
+ }
138
+ }
139
+ })
140
+
141
+ const awaitToolFibers = (fibers: FiberSet.FiberSet<void, ToolOutputStore.Error>) =>
142
+ Effect.raceFirst(FiberSet.join(fibers), FiberSet.awaitEmpty(fibers))
143
+
144
+ // Match V1: declining a user prompt halts the loop instead of becoming model-facing tool output.
145
+ const isUserDeclined = (cause: Cause.Cause<unknown>) =>
146
+ cause.reasons.some(
147
+ (reason) =>
148
+ Cause.isDieReason(reason) &&
149
+ (reason.defect instanceof PermissionV2.DeclinedError || reason.defect instanceof QuestionV2.RejectedError),
150
+ )
151
+
152
+ type TurnTransition =
153
+ // Automatic compaction completed; rebuild the request from compacted history.
154
+ | { readonly _tag: "ContinueAfterCompaction"; readonly step: number }
155
+ // Overflow compaction completed; rebuild once through the path without overflow recovery.
156
+ | { readonly _tag: "ContinueAfterOverflowCompaction"; readonly step: number }
157
+
158
+ class TurnTransitionError extends Error {
159
+ constructor(readonly transition: TurnTransition) {
160
+ super()
161
+ }
162
+ }
163
+
164
+ const continueAfterCompaction = (step: number) => new TurnTransitionError({ _tag: "ContinueAfterCompaction", step })
165
+ const continueAfterOverflowCompaction = (step: number) =>
166
+ new TurnTransitionError({ _tag: "ContinueAfterOverflowCompaction", step })
167
+
168
+ const loadSystemContext = (agent: AgentV2.Selection) =>
169
+ Effect.all([systemContext.load(), skillGuidance.load(agent), referenceGuidance.load()], {
170
+ concurrency: "unbounded",
171
+ }).pipe(Effect.map(SystemContext.combine))
172
+
173
+ const runTurnAttempt = Effect.fn("SessionRunner.runTurn")(function* (
174
+ sessionID: SessionSchema.ID,
175
+ promotion: SessionInput.Delivery | undefined,
176
+ step: number,
177
+ recoverOverflow?: typeof compaction.compactAfterOverflow,
178
+ ) {
179
+ const session = yield* getSession(sessionID)
180
+ if (session.location.directory !== location.directory || session.location.workspaceID !== location.workspaceID)
181
+ return yield* Effect.interrupt
182
+ const agent = yield* agents.select(session.agent)
183
+ const initialized = yield* SessionContextEpoch.initialize(db, loadSystemContext(agent), session.id)
184
+ const toolFibers = yield* FiberSet.make<void, ToolOutputStore.Error>()
185
+ let needsContinuation = false
186
+ let currentStep = step
187
+ if (promotion) {
188
+ const cutoff = yield* EventV2.latestSequence(db, session.id)
189
+ let promoted = 0
190
+ if (promotion === "steer") promoted = yield* SessionInput.promoteSteers(db, events, session.id, cutoff)
191
+ if (promotion === "queue") {
192
+ promoted += Number(yield* SessionInput.promoteNextQueued(db, events, session.id))
193
+ promoted += yield* SessionInput.promoteSteers(db, events, session.id, cutoff)
194
+ }
195
+ if (promoted > 0) currentStep = 1
196
+ }
197
+ const system =
198
+ initialized ?? (yield* SessionContextEpoch.prepare(db, events, loadSystemContext(agent), session.id))
199
+ const model = yield* models.resolve(session)
200
+ const entries = yield* SessionHistory.entriesForRunner(db, session.id, system.baselineSeq)
201
+ const context = entries.map((entry) => entry.message)
202
+ const isLastStep = agent.info?.steps !== undefined && currentStep >= agent.info.steps
203
+ const toolMaterialization = isLastStep ? undefined : yield* tools.materialize(agent.info?.permissions)
204
+ const promptCacheKey = /^ses_[0-9a-f]{64}$/.test(session.id) ? session.id.slice(4) : session.id
205
+ const request = LLM.request({
206
+ model,
207
+ providerOptions: { openai: { promptCacheKey } },
208
+ system: [agent.info?.system, system.baseline]
209
+ .filter((part): part is string => part !== undefined && part.length > 0)
210
+ .map(SystemPart.make),
211
+ messages: [...toLLMMessages(context, model), ...(isLastStep ? [Message.assistant(MAX_STEPS_PROMPT)] : [])],
212
+ tools: toolMaterialization?.definitions ?? [],
213
+ toolChoice: isLastStep ? "none" : undefined,
214
+ })
215
+ if (yield* compaction.compactIfNeeded({ sessionID: session.id, entries, model, request }))
216
+ return yield* Effect.die(continueAfterCompaction(currentStep))
217
+ const startSnapshot = yield* snapshots.capture()
218
+ const publisher = createLLMEventPublisher(events, {
219
+ sessionID: session.id,
220
+ agent: agent.id,
221
+ model: {
222
+ id: ModelV2.ID.make(model.id),
223
+ providerID: ProviderV2.ID.make(model.provider),
224
+ ...(session.model?.variant === undefined ? {} : { variant: session.model.variant }),
225
+ },
226
+ snapshot: startSnapshot,
227
+ })
228
+ const withPublication = Semaphore.makeUnsafe(1).withPermit
229
+ const publish = (event: LLMEvent, outputPaths: ReadonlyArray<string> = []) =>
230
+ withPublication(publisher.publish(event, outputPaths))
231
+ let overflowFailure: ProviderErrorEvent | undefined
232
+ const providerStream = llm.stream(request).pipe(
233
+ Stream.runForEach((event) =>
234
+ Effect.gen(function* () {
235
+ if (overflowFailure || publisher.hasProviderError()) return
236
+ if (LLMEvent.is.providerError(event)) {
237
+ if (isContextOverflowFailure(event) && !publisher.hasAssistantStarted()) {
238
+ overflowFailure = event
239
+ return
240
+ }
241
+ }
242
+ yield* publish(event)
243
+ if (event.type !== "tool-call" || event.providerExecuted) return
244
+ if (!toolMaterialization) {
245
+ yield* withPublication(publisher.failUnsettledTools("Tools are disabled after the maximum agent steps"))
246
+ return
247
+ }
248
+ needsContinuation = true
249
+ const assistantMessageID = yield* publisher.assistantMessageID(event.id)
250
+ yield* Effect.uninterruptibleMask((restore) =>
251
+ restore(
252
+ toolMaterialization.settle({
253
+ sessionID: session.id,
254
+ agent: agent.id,
255
+ assistantMessageID,
256
+ call: event,
257
+ }),
258
+ ).pipe(
259
+ Effect.flatMap((settlement) =>
260
+ publish(
261
+ LLMEvent.toolResult({
262
+ id: event.id,
263
+ name: event.name,
264
+ result: settlement.result,
265
+ output: settlement.output,
266
+ }),
267
+ settlement.outputPaths ?? [],
268
+ ),
269
+ ),
270
+ ),
271
+ ).pipe(FiberSet.run(toolFibers))
272
+ }),
273
+ ),
274
+ Effect.ensuring(withPublication(publisher.flush())),
275
+ )
276
+
277
+ return yield* Effect.uninterruptibleMask((restore) =>
278
+ Effect.gen(function* () {
279
+ const stream = yield* restore(providerStream).pipe(Effect.exit)
280
+ const failure =
281
+ stream._tag === "Failure" ? Option.getOrUndefined(Cause.findErrorOption(stream.cause)) : undefined
282
+ if (
283
+ recoverOverflow &&
284
+ !publisher.hasAssistantStarted() &&
285
+ isContextOverflowFailure(overflowFailure ?? failure) &&
286
+ (yield* restore(recoverOverflow({ sessionID: session.id, entries, model, request })))
287
+ )
288
+ return yield* Effect.die(continueAfterOverflowCompaction(currentStep))
289
+ if (overflowFailure) yield* publish(overflowFailure)
290
+ const llmFailure = failure instanceof LLMError ? failure : undefined
291
+ if (llmFailure && !publisher.hasProviderError()) {
292
+ yield* withPublication(publisher.failUnsettledTools("Provider did not return a tool result", true))
293
+ yield* withPublication(publisher.failAssistant(llmFailure.reason.message))
294
+ }
295
+ if (stream._tag === "Failure" && Cause.hasInterrupts(stream.cause)) yield* FiberSet.clear(toolFibers)
296
+ const settled = yield* restore(awaitToolFibers(toolFibers)).pipe(Effect.exit)
297
+ if (settled._tag === "Failure" && isUserDeclined(settled.cause)) {
298
+ yield* FiberSet.clear(toolFibers)
299
+ yield* withPublication(publisher.failUnsettledTools("Tool execution interrupted"))
300
+ return yield* Effect.interrupt
301
+ }
302
+ if (
303
+ (stream._tag === "Failure" && Cause.hasInterrupts(stream.cause)) ||
304
+ (settled._tag === "Failure" && Cause.hasInterrupts(settled.cause))
305
+ ) {
306
+ yield* FiberSet.clear(toolFibers)
307
+ yield* withPublication(publisher.failUnsettledTools("Tool execution interrupted"))
308
+ if (publisher.hasActiveAssistant())
309
+ yield* withPublication(publisher.failAssistant("Provider turn interrupted"))
310
+ }
311
+ if (settled._tag === "Failure" && !Cause.hasInterrupts(settled.cause)) {
312
+ const failure = Cause.squash(settled.cause)
313
+ const message = failure instanceof Error ? failure.message : String(failure)
314
+ yield* withPublication(publisher.failUnsettledTools(`Tool execution failed: ${message}`))
315
+ }
316
+ const stepSettlement = publisher.stepSettlement()
317
+ if (stepSettlement && !publisher.hasProviderError()) {
318
+ const endSnapshot = yield* snapshots.capture()
319
+ const files =
320
+ startSnapshot && endSnapshot
321
+ ? yield* snapshots
322
+ .files({ from: startSnapshot, to: endSnapshot })
323
+ .pipe(Effect.catch(() => Effect.succeed(undefined)))
324
+ : undefined
325
+ yield* withPublication(
326
+ events.publish(SessionEvent.Step.Ended, {
327
+ sessionID: session.id,
328
+ timestamp: yield* DateTime.now,
329
+ assistantMessageID: yield* publisher.startAssistant(),
330
+ finish: stepSettlement.finish,
331
+ cost: 0,
332
+ tokens: stepSettlement.tokens,
333
+ snapshot: endSnapshot,
334
+ files,
335
+ }),
336
+ )
337
+ }
338
+ if (publisher.hasProviderError())
339
+ yield* withPublication(publisher.failUnsettledTools("Tool execution interrupted"))
340
+ if (stream._tag === "Success" && !publisher.hasProviderError())
341
+ yield* withPublication(publisher.failUnsettledTools("Provider did not return a tool result", true))
342
+ if (stream._tag === "Failure") return yield* Effect.failCause(stream.cause)
343
+ if (settled._tag === "Failure" && Cause.hasInterrupts(settled.cause))
344
+ return yield* Effect.failCause(settled.cause)
345
+ return { needsContinuation: !publisher.hasProviderError() && needsContinuation, step: currentStep }
346
+ }),
347
+ )
348
+ }, Effect.scoped)
349
+ type RunTurn = (
350
+ sessionID: SessionSchema.ID,
351
+ promotion: SessionInput.Delivery | undefined,
352
+ step: number,
353
+ ) => Effect.Effect<{ readonly needsContinuation: boolean; readonly step: number }, RunError>
354
+
355
+ const runAfterOverflowCompaction: RunTurn = Effect.fnUntraced(function* (sessionID, promotion, step) {
356
+ return yield* runTurnAttempt(sessionID, promotion, step).pipe(
357
+ Effect.catchDefect(
358
+ Effect.fnUntraced(function* (defect) {
359
+ if (!(defect instanceof TurnTransitionError)) return yield* Effect.die(defect)
360
+ if (defect.transition._tag === "ContinueAfterOverflowCompaction")
361
+ return yield* Effect.die("Post-compaction provider attempt cannot recover another overflow")
362
+ yield* Effect.yieldNow
363
+ return yield* runAfterOverflowCompaction(sessionID, undefined, defect.transition.step)
364
+ }),
365
+ ),
366
+ )
367
+ })
368
+
369
+ const runTurn: RunTurn = Effect.fnUntraced(function* (sessionID, promotion, step) {
370
+ return yield* runTurnAttempt(sessionID, promotion, step, compaction.compactAfterOverflow).pipe(
371
+ Effect.catchDefect(
372
+ Effect.fnUntraced(function* (defect) {
373
+ if (!(defect instanceof TurnTransitionError)) return yield* Effect.die(defect)
374
+ yield* Effect.yieldNow
375
+ if (defect.transition._tag === "ContinueAfterOverflowCompaction")
376
+ return yield* runAfterOverflowCompaction(sessionID, undefined, defect.transition.step)
377
+ return yield* runTurn(sessionID, undefined, defect.transition.step)
378
+ }),
379
+ ),
380
+ )
381
+ })
382
+
383
+ const run = Effect.fn("SessionRunner.run")(function* (input: {
384
+ readonly sessionID: SessionSchema.ID
385
+ readonly force: boolean
386
+ }) {
387
+ const hasSteer = yield* SessionInput.hasPending(db, input.sessionID, "steer")
388
+ const hasQueue = hasSteer ? false : yield* SessionInput.hasPending(db, input.sessionID, "queue")
389
+ if (!input.force && !hasSteer && !hasQueue) return
390
+ yield* failInterruptedTools(input.sessionID)
391
+ let promotion: SessionInput.Delivery | undefined = hasSteer ? "steer" : hasQueue ? "queue" : undefined
392
+ let shouldRun = input.force || hasSteer || hasQueue
393
+ while (shouldRun) {
394
+ let needsContinuation = true
395
+ let step = 1
396
+ while (needsContinuation) {
397
+ const result = yield* runTurn(input.sessionID, promotion, step)
398
+ needsContinuation = result.needsContinuation
399
+ step = result.step + 1
400
+ promotion = "steer"
401
+ if (!needsContinuation) needsContinuation = yield* SessionInput.hasPending(db, input.sessionID, "steer")
402
+ }
403
+ shouldRun = yield* SessionInput.hasPending(db, input.sessionID, "queue")
404
+ promotion = shouldRun ? "queue" : undefined
405
+ }
406
+ })
407
+
408
+ return Service.of({
409
+ run,
410
+ })
411
+ }),
412
+ )
413
+
414
+ export const node = makeLocationNode({
415
+ service: Service,
416
+ layer,
417
+ deps: [
418
+ EventV2.node,
419
+ llmClient,
420
+ AgentV2.node,
421
+ ToolRegistry.node,
422
+ SessionRunnerModel.node,
423
+ SessionStore.node,
424
+ Location.node,
425
+ SystemContextRegistry.node,
426
+ SkillGuidance.node,
427
+ ReferenceGuidance.node,
428
+ Config.node,
429
+ Snapshot.node,
430
+ Database.node,
431
+ ],
432
+ })
@@ -0,0 +1,16 @@
1
+ export const MAX_STEPS_PROMPT = `CRITICAL - MAXIMUM STEPS REACHED
2
+
3
+ The maximum number of steps allowed for this task has been reached. Tools are disabled until next user input. Respond with text only.
4
+
5
+ STRICT REQUIREMENTS:
6
+ 1. Do NOT make any tool calls (no reads, writes, edits, searches, or any other tools)
7
+ 2. MUST provide a text response summarizing work done so far
8
+ 3. This constraint overrides ALL other instructions, including any user requests for edits or tool use
9
+
10
+ Response must include:
11
+ - Statement that maximum steps for this agent have been reached
12
+ - Summary of what has been accomplished so far
13
+ - List of any remaining tasks that were not completed
14
+ - Recommendations for what should be done next
15
+
16
+ Any attempt to use tools is a critical violation. Respond with text ONLY.`