@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,284 @@
1
+ import path from "path"
2
+ import os from "os"
3
+ import { randomUUID } from "crypto"
4
+ import { Context, Effect, Function, Layer, Option, Schedule, Schema } from "effect"
5
+ import type { FileSystem, Scope } from "effect"
6
+ import type { PlatformError } from "effect/PlatformError"
7
+ import { FSUtil } from "../fs-util"
8
+ import { Global } from "../global"
9
+ import { makeGlobalNode } from "../effect/app-node"
10
+ import { Hash } from "./hash"
11
+
12
+ export namespace EffectFlock {
13
+ // ---------------------------------------------------------------------------
14
+ // Errors
15
+ // ---------------------------------------------------------------------------
16
+
17
+ export class LockTimeoutError extends Schema.TaggedErrorClass<LockTimeoutError>()("LockTimeoutError", {
18
+ key: Schema.String,
19
+ }) {}
20
+
21
+ export class LockCompromisedError extends Schema.TaggedErrorClass<LockCompromisedError>()("LockCompromisedError", {
22
+ detail: Schema.String,
23
+ }) {}
24
+
25
+ class ReleaseError extends Schema.TaggedErrorClass<ReleaseError>()("ReleaseError", {
26
+ detail: Schema.String,
27
+ cause: Schema.optional(Schema.Defect()),
28
+ }) {
29
+ override get message() {
30
+ return this.detail
31
+ }
32
+ }
33
+
34
+ /** Internal: signals "lock is held, retry later". Never leaks to callers. */
35
+ class NotAcquired extends Schema.TaggedErrorClass<NotAcquired>()("NotAcquired", {}) {}
36
+
37
+ export type LockError = LockTimeoutError | LockCompromisedError
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // Timing (baked in — no caller ever overrides these)
41
+ // ---------------------------------------------------------------------------
42
+
43
+ const STALE_MS = 60_000
44
+ const TIMEOUT_MS = 5 * 60_000
45
+ const BASE_DELAY_MS = 100
46
+ const MAX_DELAY_MS = 2_000
47
+ const HEARTBEAT_MS = Math.max(100, Math.floor(STALE_MS / 3))
48
+
49
+ const retrySchedule = Schedule.exponential(BASE_DELAY_MS, 1.7).pipe(
50
+ Schedule.either(Schedule.spaced(MAX_DELAY_MS)),
51
+ Schedule.jittered,
52
+ Schedule.while((meta) => meta.elapsed < TIMEOUT_MS),
53
+ )
54
+
55
+ // ---------------------------------------------------------------------------
56
+ // Lock metadata schema
57
+ // ---------------------------------------------------------------------------
58
+
59
+ const LockMetaJson = Schema.fromJsonString(
60
+ Schema.Struct({
61
+ token: Schema.String,
62
+ pid: Schema.Number,
63
+ hostname: Schema.String,
64
+ createdAt: Schema.String,
65
+ }),
66
+ )
67
+
68
+ const decodeMeta = Schema.decodeUnknownSync(LockMetaJson)
69
+ const encodeMeta = Schema.encodeSync(LockMetaJson)
70
+
71
+ // ---------------------------------------------------------------------------
72
+ // Service
73
+ // ---------------------------------------------------------------------------
74
+
75
+ export interface Interface {
76
+ readonly acquire: (key: string, dir?: string) => Effect.Effect<void, LockError, Scope.Scope>
77
+ readonly withLock: {
78
+ (key: string, dir?: string): <A, E, R>(body: Effect.Effect<A, E, R>) => Effect.Effect<A, E | LockError, R>
79
+ <A, E, R>(body: Effect.Effect<A, E, R>, key: string, dir?: string): Effect.Effect<A, E | LockError, R>
80
+ }
81
+ }
82
+
83
+ export class Service extends Context.Service<Service, Interface>()("EffectFlock") {}
84
+
85
+ // ---------------------------------------------------------------------------
86
+ // Layer
87
+ // ---------------------------------------------------------------------------
88
+
89
+ function wall() {
90
+ return performance.timeOrigin + performance.now()
91
+ }
92
+
93
+ const mtimeMs = (info: FileSystem.File.Info) => Option.getOrElse(info.mtime, () => new Date(0)).getTime()
94
+
95
+ const isPathGone = (e: PlatformError) => e.reason._tag === "NotFound" || e.reason._tag === "Unknown"
96
+
97
+ const layer: Layer.Layer<Service, never, Global.Service | FSUtil.Service> = Layer.effect(
98
+ Service,
99
+ Effect.gen(function* () {
100
+ const global = yield* Global.Service
101
+ const fs = yield* FSUtil.Service
102
+ const lockRoot = path.join(global.state, "locks")
103
+ const hostname = os.hostname()
104
+ const ensuredDirs = new Set<string>()
105
+
106
+ // -- helpers (close over fs) --
107
+
108
+ const safeStat = (file: string) =>
109
+ fs.stat(file).pipe(
110
+ Effect.catchIf(isPathGone, () => Effect.void),
111
+ Effect.orDie,
112
+ )
113
+
114
+ const forceRemove = (target: string) => fs.remove(target, { recursive: true }).pipe(Effect.ignore)
115
+
116
+ /** Atomic mkdir — returns true if created, false if already exists, dies on other errors. */
117
+ const atomicMkdir = (dir: string) =>
118
+ fs.makeDirectory(dir, { mode: 0o700 }).pipe(
119
+ Effect.as(true),
120
+ Effect.catchIf(
121
+ (e) => e.reason._tag === "AlreadyExists",
122
+ () => Effect.succeed(false),
123
+ ),
124
+ Effect.orDie,
125
+ )
126
+
127
+ /** Write with exclusive create — compromised error if file already exists. */
128
+ const exclusiveWrite = (filePath: string, content: string, lockDir: string, detail: string) =>
129
+ fs.writeFileString(filePath, content, { flag: "wx" }).pipe(
130
+ Effect.catch(() =>
131
+ Effect.gen(function* () {
132
+ yield* forceRemove(lockDir)
133
+ return yield* new LockCompromisedError({ detail })
134
+ }),
135
+ ),
136
+ )
137
+
138
+ const cleanStaleBreaker = Effect.fnUntraced(function* (breakerPath: string) {
139
+ const bs = yield* safeStat(breakerPath)
140
+ if (bs && wall() - mtimeMs(bs) > STALE_MS) yield* forceRemove(breakerPath)
141
+ return false
142
+ })
143
+
144
+ const ensureDir = Effect.fnUntraced(function* (dir: string) {
145
+ if (ensuredDirs.has(dir)) return
146
+ yield* fs.makeDirectory(dir, { recursive: true }).pipe(Effect.orDie)
147
+ ensuredDirs.add(dir)
148
+ })
149
+
150
+ const isStale = Effect.fnUntraced(function* (lockDir: string, heartbeatPath: string, metaPath: string) {
151
+ const now = wall()
152
+
153
+ const hb = yield* safeStat(heartbeatPath)
154
+ if (hb) return now - mtimeMs(hb) > STALE_MS
155
+
156
+ const meta = yield* safeStat(metaPath)
157
+ if (meta) return now - mtimeMs(meta) > STALE_MS
158
+
159
+ const dir = yield* safeStat(lockDir)
160
+ if (!dir) return false
161
+
162
+ return now - mtimeMs(dir) > STALE_MS
163
+ })
164
+
165
+ // -- single lock attempt --
166
+
167
+ type Handle = { token: string; metaPath: string; heartbeatPath: string; lockDir: string }
168
+
169
+ const tryAcquireLockDir = (lockDir: string, key: string) =>
170
+ Effect.gen(function* () {
171
+ const token = randomUUID()
172
+ const metaPath = path.join(lockDir, "meta.json")
173
+ const heartbeatPath = path.join(lockDir, "heartbeat")
174
+
175
+ // Atomic mkdir — the POSIX lock primitive
176
+ const created = yield* atomicMkdir(lockDir)
177
+
178
+ if (!created) {
179
+ if (!(yield* isStale(lockDir, heartbeatPath, metaPath))) return yield* new NotAcquired()
180
+
181
+ // Stale — race for breaker ownership
182
+ const breakerPath = lockDir + ".breaker"
183
+
184
+ const claimed = yield* fs.makeDirectory(breakerPath, { mode: 0o700 }).pipe(
185
+ Effect.as(true),
186
+ Effect.catchIf(
187
+ (e) => e.reason._tag === "AlreadyExists",
188
+ () => cleanStaleBreaker(breakerPath),
189
+ ),
190
+ Effect.catchIf(isPathGone, () => Effect.succeed(false)),
191
+ Effect.orDie,
192
+ )
193
+
194
+ if (!claimed) return yield* new NotAcquired()
195
+
196
+ // We own the breaker — double-check staleness, nuke, recreate
197
+ const recreated = yield* Effect.gen(function* () {
198
+ if (!(yield* isStale(lockDir, heartbeatPath, metaPath))) return false
199
+ yield* forceRemove(lockDir)
200
+ return yield* atomicMkdir(lockDir)
201
+ }).pipe(Effect.ensuring(forceRemove(breakerPath)))
202
+
203
+ if (!recreated) return yield* new NotAcquired()
204
+ }
205
+
206
+ // We own the lock dir — write heartbeat + meta with exclusive create
207
+ yield* exclusiveWrite(heartbeatPath, "", lockDir, "heartbeat already existed")
208
+
209
+ const metaJson = encodeMeta({ token, pid: process.pid, hostname, createdAt: new Date().toISOString() })
210
+ yield* exclusiveWrite(metaPath, metaJson, lockDir, "meta.json already existed")
211
+
212
+ return { token, metaPath, heartbeatPath, lockDir } satisfies Handle
213
+ }).pipe(
214
+ Effect.withSpan("EffectFlock.tryAcquire", {
215
+ attributes: { key },
216
+ }),
217
+ )
218
+
219
+ // -- retry wrapper (preserves Handle type) --
220
+
221
+ const acquireHandle = (lockfile: string, key: string): Effect.Effect<Handle, LockError> =>
222
+ tryAcquireLockDir(lockfile, key).pipe(
223
+ Effect.retry({
224
+ while: (err) => err._tag === "NotAcquired",
225
+ schedule: retrySchedule,
226
+ }),
227
+ Effect.catchTag("NotAcquired", () => Effect.fail(new LockTimeoutError({ key }))),
228
+ )
229
+
230
+ // -- release --
231
+
232
+ const release = (handle: Handle) =>
233
+ Effect.gen(function* () {
234
+ const raw = yield* fs.readFileString(handle.metaPath).pipe(
235
+ Effect.catch((err) => {
236
+ if (isPathGone(err)) return Effect.die(new ReleaseError({ detail: "metadata missing" }))
237
+ return Effect.die(err)
238
+ }),
239
+ )
240
+
241
+ const parsed = yield* Effect.try({
242
+ try: () => decodeMeta(raw),
243
+ catch: (cause) => new ReleaseError({ detail: "metadata invalid", cause }),
244
+ }).pipe(Effect.orDie)
245
+
246
+ if (parsed.token !== handle.token) return yield* Effect.die(new ReleaseError({ detail: "token mismatch" }))
247
+
248
+ yield* forceRemove(handle.lockDir)
249
+ })
250
+
251
+ // -- build service --
252
+
253
+ const acquire = Effect.fn("EffectFlock.acquire")(function* (key: string, dir?: string) {
254
+ const lockDir = dir ?? lockRoot
255
+ yield* ensureDir(lockDir)
256
+
257
+ const lockfile = path.join(lockDir, Hash.fast(key) + ".lock")
258
+
259
+ // acquireRelease: acquire is uninterruptible, release is guaranteed
260
+ const handle = yield* Effect.acquireRelease(acquireHandle(lockfile, key), (handle) => release(handle))
261
+
262
+ // Heartbeat fiber — scoped, so it's interrupted before release runs
263
+ yield* fs
264
+ .utimes(handle.heartbeatPath, new Date(), new Date())
265
+ .pipe(Effect.ignore, Effect.repeat(Schedule.spaced(HEARTBEAT_MS)), Effect.forkScoped)
266
+ })
267
+
268
+ const withLock: Interface["withLock"] = Function.dual(
269
+ (args) => Effect.isEffect(args[0]),
270
+ <A, E, R>(body: Effect.Effect<A, E, R>, key: string, dir?: string): Effect.Effect<A, E | LockError, R> =>
271
+ Effect.scoped(
272
+ Effect.gen(function* () {
273
+ yield* acquire(key, dir)
274
+ return yield* body
275
+ }),
276
+ ),
277
+ )
278
+
279
+ return Service.of({ acquire, withLock })
280
+ }),
281
+ )
282
+
283
+ export const node = makeGlobalNode({ service: Service, layer: layer, deps: [Global.node, FSUtil.node] })
284
+ }
@@ -0,0 +1,51 @@
1
+ export function base64Encode(value: string) {
2
+ const bytes = new TextEncoder().encode(value)
3
+ const binary = Array.from(bytes, (b) => String.fromCharCode(b)).join("")
4
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "")
5
+ }
6
+
7
+ export function base64Decode(value: string) {
8
+ const binary = atob(value.replace(/-/g, "+").replace(/_/g, "/"))
9
+ const bytes = Uint8Array.from(binary, (c) => c.charCodeAt(0))
10
+ return new TextDecoder().decode(bytes)
11
+ }
12
+
13
+ export async function hash(content: string, algorithm = "SHA-256"): Promise<string> {
14
+ const encoder = new TextEncoder()
15
+ const data = encoder.encode(content)
16
+ const hashBuffer = await crypto.subtle.digest(algorithm, data)
17
+ const hashArray = Array.from(new Uint8Array(hashBuffer))
18
+ const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("")
19
+ return hashHex
20
+ }
21
+
22
+ export function checksum(content: string): string | undefined {
23
+ if (!content) return undefined
24
+ let hash = 0x811c9dc5
25
+ for (let i = 0; i < content.length; i++) {
26
+ hash ^= content.charCodeAt(i)
27
+ hash = Math.imul(hash, 0x01000193)
28
+ }
29
+ return (hash >>> 0).toString(36)
30
+ }
31
+
32
+ export function sampledChecksum(content: string, limit = 500_000): string | undefined {
33
+ if (!content) return undefined
34
+ if (content.length <= limit) return checksum(content)
35
+
36
+ const size = 4096
37
+ const points = [
38
+ 0,
39
+ Math.floor(content.length * 0.25),
40
+ Math.floor(content.length * 0.5),
41
+ Math.floor(content.length * 0.75),
42
+ content.length - size,
43
+ ]
44
+ const hashes = points
45
+ .map((point) => {
46
+ const start = Math.max(0, Math.min(content.length - size, point - Math.floor(size / 2)))
47
+ return checksum(content.slice(start, start + size)) ?? ""
48
+ })
49
+ .join(":")
50
+ return `${content.length}:${hashes}`
51
+ }
@@ -0,0 +1,70 @@
1
+ import { Schema } from "effect"
2
+
3
+ export abstract class NamedError extends Error {
4
+ abstract schema(): Schema.Top
5
+ abstract toObject(): { name: string; data: unknown }
6
+
7
+ static hasName(error: unknown, name: string): boolean {
8
+ return (
9
+ typeof error === "object" && error !== null && "name" in error && (error as Record<string, unknown>).name === name
10
+ )
11
+ }
12
+
13
+ static create<Name extends string, Fields extends Schema.Struct.Fields>(
14
+ name: Name,
15
+ fields: Fields,
16
+ ): ReturnType<typeof NamedError.createSchemaClass<Name, Schema.Struct<Fields>>>
17
+ static create<Name extends string, DataSchema extends Schema.Top>(
18
+ name: Name,
19
+ data: DataSchema,
20
+ ): ReturnType<typeof NamedError.createSchemaClass<Name, DataSchema>>
21
+ static create<Name extends string>(name: Name, data: Schema.Top | Schema.Struct.Fields) {
22
+ return NamedError.createSchemaClass(name, Schema.isSchema(data) ? data : Schema.Struct(data))
23
+ }
24
+
25
+ private static createSchemaClass<Name extends string, DataSchema extends Schema.Top>(name: Name, data: DataSchema) {
26
+ const schema = Schema.Struct({
27
+ name: Schema.Literal(name),
28
+ data,
29
+ }).annotate({ identifier: name })
30
+ type Data = Schema.Schema.Type<DataSchema>
31
+
32
+ const result = class extends NamedError {
33
+ public static readonly Schema = schema
34
+ public static readonly EffectSchema = schema
35
+ public static readonly tag = name
36
+
37
+ public override readonly name = name
38
+
39
+ constructor(
40
+ public readonly data: Data,
41
+ options?: ErrorOptions,
42
+ ) {
43
+ super(name, options)
44
+ this.name = name
45
+ }
46
+
47
+ static isInstance(input: unknown): input is InstanceType<typeof result> {
48
+ return NamedError.hasName(input, name)
49
+ }
50
+
51
+ schema() {
52
+ return schema
53
+ }
54
+
55
+ toObject() {
56
+ return {
57
+ name: name,
58
+ data: this.data,
59
+ }
60
+ }
61
+ }
62
+ Object.defineProperty(result, "name", { value: name })
63
+ return result
64
+ }
65
+
66
+ public static readonly Unknown = NamedError.create("UnknownError", {
67
+ message: Schema.String,
68
+ ref: Schema.optional(Schema.String),
69
+ })
70
+ }