bonecode 1.0.0

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 (605) hide show
  1. package/ARCHITECTURE.md +183 -0
  2. package/README.md +71 -0
  3. package/bin/bonecode +62 -0
  4. package/bone/migrations/rag_vectors.sql +258 -0
  5. package/bone/output/agent/.dockerignore +7 -0
  6. package/bone/output/agent/.env.example +36 -0
  7. package/bone/output/agent/.github/workflows/ci.yaml +58 -0
  8. package/bone/output/agent/AgentDomain.bone.map +350 -0
  9. package/bone/output/agent/AgentDomain.postman_collection.json +958 -0
  10. package/bone/output/agent/Dockerfile +22 -0
  11. package/bone/output/agent/README.md +47 -0
  12. package/bone/output/agent/admin/index.html +740 -0
  13. package/bone/output/agent/docker-compose.yaml +22 -0
  14. package/bone/output/agent/k8s/deployment.yaml +75 -0
  15. package/bone/output/agent/migrations/agent.sql +36 -0
  16. package/bone/output/agent/migrations/agent_instance.sql +36 -0
  17. package/bone/output/agent/migrations/audit_log.sql +18 -0
  18. package/bone/output/agent/migrations/build_step.sql +34 -0
  19. package/bone/output/agent/migrations/event_outbox.sql +31 -0
  20. package/bone/output/agent/migrations/plan.sql +30 -0
  21. package/bone/output/agent/migrations/task.sql +30 -0
  22. package/bone/output/agent/migrations/tool_call.sql +33 -0
  23. package/bone/output/agent/openapi.yaml +1116 -0
  24. package/bone/output/agent/package.json +36 -0
  25. package/bone/output/agent/schema.graphql +233 -0
  26. package/bone/output/agent/sdk/client.ts +231 -0
  27. package/bone/output/agent/src/algorithms.ts +2 -0
  28. package/bone/output/agent/src/audit.ts +44 -0
  29. package/bone/output/agent/src/auth.ts +57 -0
  30. package/bone/output/agent/src/cron.ts +12 -0
  31. package/bone/output/agent/src/db.ts +32 -0
  32. package/bone/output/agent/src/debug.ts +66 -0
  33. package/bone/output/agent/src/events.ts +243 -0
  34. package/bone/output/agent/src/extensions.ts +54 -0
  35. package/bone/output/agent/src/failure_rules.ts +323 -0
  36. package/bone/output/agent/src/flows.ts +168 -0
  37. package/bone/output/agent/src/health.ts +43 -0
  38. package/bone/output/agent/src/index.ts +100 -0
  39. package/bone/output/agent/src/logger.ts +66 -0
  40. package/bone/output/agent/src/metrics.ts +75 -0
  41. package/bone/output/agent/src/migrate.ts +352 -0
  42. package/bone/output/agent/src/migration_diff.ts +108 -0
  43. package/bone/output/agent/src/notify.ts +125 -0
  44. package/bone/output/agent/src/routes/agent_instance.ts +234 -0
  45. package/bone/output/agent/src/routes/build_step.ts +105 -0
  46. package/bone/output/agent/src/routes/plan.ts +91 -0
  47. package/bone/output/agent/src/routes/task.ts +105 -0
  48. package/bone/output/agent/src/routes/tool_call.ts +166 -0
  49. package/bone/output/agent/src/schemas.ts +384 -0
  50. package/bone/output/agent/src/state_machines/agent_instance.ts +24 -0
  51. package/bone/output/agent/src/state_machines/build_step.ts +22 -0
  52. package/bone/output/agent/src/state_machines/plan.ts +22 -0
  53. package/bone/output/agent/src/state_machines/task.ts +22 -0
  54. package/bone/output/agent/src/state_machines/tool_call.ts +22 -0
  55. package/bone/output/agent/src/tests.ts +362 -0
  56. package/bone/output/agent/src/websocket.ts +201 -0
  57. package/bone/output/agent/tsconfig.json +25 -0
  58. package/bone/output/rag/.dockerignore +7 -0
  59. package/bone/output/rag/.env.example +36 -0
  60. package/bone/output/rag/.github/workflows/ci.yaml +58 -0
  61. package/bone/output/rag/Dockerfile +22 -0
  62. package/bone/output/rag/RAGDomain.bone.map +287 -0
  63. package/bone/output/rag/RAGDomain.postman_collection.json +923 -0
  64. package/bone/output/rag/README.md +47 -0
  65. package/bone/output/rag/admin/index.html +818 -0
  66. package/bone/output/rag/docker-compose.yaml +22 -0
  67. package/bone/output/rag/k8s/deployment.yaml +75 -0
  68. package/bone/output/rag/migrations/audit_log.sql +18 -0
  69. package/bone/output/rag/migrations/code_chunk.sql +34 -0
  70. package/bone/output/rag/migrations/code_file.sql +33 -0
  71. package/bone/output/rag/migrations/event_outbox.sql +31 -0
  72. package/bone/output/rag/migrations/indexing_job.sql +33 -0
  73. package/bone/output/rag/migrations/knowledge_base.sql +35 -0
  74. package/bone/output/rag/migrations/memory_entry.sql +34 -0
  75. package/bone/output/rag/openapi.yaml +1097 -0
  76. package/bone/output/rag/package.json +36 -0
  77. package/bone/output/rag/schema.graphql +245 -0
  78. package/bone/output/rag/sdk/client.ts +234 -0
  79. package/bone/output/rag/src/algorithms.ts +2 -0
  80. package/bone/output/rag/src/audit.ts +37 -0
  81. package/bone/output/rag/src/auth.ts +57 -0
  82. package/bone/output/rag/src/cron.ts +12 -0
  83. package/bone/output/rag/src/db.ts +32 -0
  84. package/bone/output/rag/src/debug.ts +66 -0
  85. package/bone/output/rag/src/events.ts +243 -0
  86. package/bone/output/rag/src/extensions.ts +350 -0
  87. package/bone/output/rag/src/failure_rules.ts +315 -0
  88. package/bone/output/rag/src/flows.ts +239 -0
  89. package/bone/output/rag/src/health.ts +43 -0
  90. package/bone/output/rag/src/index.ts +95 -0
  91. package/bone/output/rag/src/logger.ts +66 -0
  92. package/bone/output/rag/src/metrics.ts +75 -0
  93. package/bone/output/rag/src/migrate.ts +364 -0
  94. package/bone/output/rag/src/migration_diff.ts +108 -0
  95. package/bone/output/rag/src/notify.ts +99 -0
  96. package/bone/output/rag/src/routes/code_chunk.ts +75 -0
  97. package/bone/output/rag/src/routes/code_file.ts +101 -0
  98. package/bone/output/rag/src/routes/indexing_job.ts +87 -0
  99. package/bone/output/rag/src/routes/knowledge_base.ts +230 -0
  100. package/bone/output/rag/src/routes/memory_entry.ts +87 -0
  101. package/bone/output/rag/src/schemas.ts +394 -0
  102. package/bone/output/rag/src/state_machines/code_file.ts +23 -0
  103. package/bone/output/rag/src/state_machines/indexing_job.ts +22 -0
  104. package/bone/output/rag/src/state_machines/knowledge_base.ts +23 -0
  105. package/bone/output/rag/src/state_machines/memory_entry.ts +20 -0
  106. package/bone/output/rag/src/tests.ts +340 -0
  107. package/bone/output/rag/tsconfig.json +25 -0
  108. package/bone/output/session/.dockerignore +7 -0
  109. package/bone/output/session/.env.example +36 -0
  110. package/bone/output/session/.github/workflows/ci.yaml +58 -0
  111. package/bone/output/session/Dockerfile +22 -0
  112. package/bone/output/session/README.md +47 -0
  113. package/bone/output/session/SessionDomain.bone.map +350 -0
  114. package/bone/output/session/SessionDomain.postman_collection.json +958 -0
  115. package/bone/output/session/admin/index.html +667 -0
  116. package/bone/output/session/docker-compose.yaml +22 -0
  117. package/bone/output/session/k8s/deployment.yaml +75 -0
  118. package/bone/output/session/migrations/audit_log.sql +18 -0
  119. package/bone/output/session/migrations/event_outbox.sql +31 -0
  120. package/bone/output/session/migrations/message.sql +31 -0
  121. package/bone/output/session/migrations/part.sql +28 -0
  122. package/bone/output/session/migrations/permission.sql +28 -0
  123. package/bone/output/session/migrations/project.sql +28 -0
  124. package/bone/output/session/migrations/session.sql +38 -0
  125. package/bone/output/session/openapi.yaml +1101 -0
  126. package/bone/output/session/package.json +36 -0
  127. package/bone/output/session/schema.graphql +222 -0
  128. package/bone/output/session/sdk/client.ts +225 -0
  129. package/bone/output/session/src/algorithms.ts +2 -0
  130. package/bone/output/session/src/audit.ts +44 -0
  131. package/bone/output/session/src/auth.ts +57 -0
  132. package/bone/output/session/src/cron.ts +12 -0
  133. package/bone/output/session/src/db.ts +32 -0
  134. package/bone/output/session/src/debug.ts +66 -0
  135. package/bone/output/session/src/events.ts +270 -0
  136. package/bone/output/session/src/extensions.ts +215 -0
  137. package/bone/output/session/src/failure_rules.ts +284 -0
  138. package/bone/output/session/src/flows.ts +168 -0
  139. package/bone/output/session/src/health.ts +43 -0
  140. package/bone/output/session/src/index.ts +100 -0
  141. package/bone/output/session/src/logger.ts +66 -0
  142. package/bone/output/session/src/metrics.ts +75 -0
  143. package/bone/output/session/src/migrate.ts +332 -0
  144. package/bone/output/session/src/migration_diff.ts +108 -0
  145. package/bone/output/session/src/notify.ts +112 -0
  146. package/bone/output/session/src/routes/message.ts +93 -0
  147. package/bone/output/session/src/routes/part.ts +79 -0
  148. package/bone/output/session/src/routes/permission.ts +79 -0
  149. package/bone/output/session/src/routes/project.ts +79 -0
  150. package/bone/output/session/src/routes/session.ts +294 -0
  151. package/bone/output/session/src/schemas.ts +357 -0
  152. package/bone/output/session/src/state_machines/session.ts +23 -0
  153. package/bone/output/session/src/tests.ts +326 -0
  154. package/bone/output/session/src/websocket.ts +201 -0
  155. package/bone/output/session/tsconfig.json +25 -0
  156. package/bone/output/workspace/.dockerignore +7 -0
  157. package/bone/output/workspace/.env.example +36 -0
  158. package/bone/output/workspace/.github/workflows/ci.yaml +58 -0
  159. package/bone/output/workspace/Dockerfile +22 -0
  160. package/bone/output/workspace/README.md +45 -0
  161. package/bone/output/workspace/WorkspaceDomain.bone.map +189 -0
  162. package/bone/output/workspace/WorkspaceDomain.postman_collection.json +621 -0
  163. package/bone/output/workspace/admin/index.html +485 -0
  164. package/bone/output/workspace/docker-compose.yaml +22 -0
  165. package/bone/output/workspace/k8s/deployment.yaml +75 -0
  166. package/bone/output/workspace/migrations/audit_log.sql +18 -0
  167. package/bone/output/workspace/migrations/codebase.sql +34 -0
  168. package/bone/output/workspace/migrations/event_outbox.sql +31 -0
  169. package/bone/output/workspace/migrations/snapshot.sql +32 -0
  170. package/bone/output/workspace/migrations/workspace.sql +33 -0
  171. package/bone/output/workspace/openapi.yaml +721 -0
  172. package/bone/output/workspace/package.json +36 -0
  173. package/bone/output/workspace/schema.graphql +153 -0
  174. package/bone/output/workspace/sdk/client.ts +155 -0
  175. package/bone/output/workspace/src/algorithms.ts +2 -0
  176. package/bone/output/workspace/src/audit.ts +37 -0
  177. package/bone/output/workspace/src/auth.ts +57 -0
  178. package/bone/output/workspace/src/cron.ts +12 -0
  179. package/bone/output/workspace/src/db.ts +32 -0
  180. package/bone/output/workspace/src/debug.ts +66 -0
  181. package/bone/output/workspace/src/events.ts +243 -0
  182. package/bone/output/workspace/src/extensions.ts +44 -0
  183. package/bone/output/workspace/src/failure_rules.ts +153 -0
  184. package/bone/output/workspace/src/health.ts +43 -0
  185. package/bone/output/workspace/src/index.ts +89 -0
  186. package/bone/output/workspace/src/logger.ts +66 -0
  187. package/bone/output/workspace/src/metrics.ts +75 -0
  188. package/bone/output/workspace/src/migrate.ts +220 -0
  189. package/bone/output/workspace/src/migration_diff.ts +108 -0
  190. package/bone/output/workspace/src/notify.ts +73 -0
  191. package/bone/output/workspace/src/routes/codebase.ts +87 -0
  192. package/bone/output/workspace/src/routes/snapshot.ts +127 -0
  193. package/bone/output/workspace/src/routes/workspace.ts +190 -0
  194. package/bone/output/workspace/src/schemas.ts +231 -0
  195. package/bone/output/workspace/src/state_machines/codebase.ts +21 -0
  196. package/bone/output/workspace/src/state_machines/snapshot.ts +20 -0
  197. package/bone/output/workspace/src/state_machines/workspace.ts +21 -0
  198. package/bone/output/workspace/src/tests.ts +249 -0
  199. package/bone/output/workspace/tsconfig.json +25 -0
  200. package/compat/opencode_adapter.ts +410 -0
  201. package/package.json +69 -0
  202. package/scripts/check_benchmark_session.js +34 -0
  203. package/scripts/check_finish_event.js +24 -0
  204. package/scripts/check_parts.js +15 -0
  205. package/scripts/compile.js +79 -0
  206. package/scripts/copy_opencode.ps1 +53 -0
  207. package/scripts/create_functions.sql +129 -0
  208. package/scripts/migrate.js +85 -0
  209. package/scripts/migrate_from_opencode.ts +218 -0
  210. package/scripts/test_agent_loop.js +101 -0
  211. package/scripts/test_api.ps1 +116 -0
  212. package/scripts/test_context_builder.js +136 -0
  213. package/scripts/test_context_builder.ts +97 -0
  214. package/scripts/test_rag.js +189 -0
  215. package/scripts/test_stream_events.js +36 -0
  216. package/scripts/test_websocket_and_saga.js +216 -0
  217. package/src/cli.ts +475 -0
  218. package/src/config.ts +162 -0
  219. package/src/context_builder.ts +598 -0
  220. package/src/engine/account/account.sql.ts +39 -0
  221. package/src/engine/account/account.ts +456 -0
  222. package/src/engine/account/repo.ts +166 -0
  223. package/src/engine/account/schema.ts +99 -0
  224. package/src/engine/account/url.ts +8 -0
  225. package/src/engine/acp/README.md +174 -0
  226. package/src/engine/acp/agent.ts +1968 -0
  227. package/src/engine/acp/runtime.ts +22 -0
  228. package/src/engine/acp/session.ts +122 -0
  229. package/src/engine/acp/types.ts +24 -0
  230. package/src/engine/agent/agent.ts +463 -0
  231. package/src/engine/agent/generate.txt +75 -0
  232. package/src/engine/agent/prompt/compaction.txt +9 -0
  233. package/src/engine/agent/prompt/explore.txt +18 -0
  234. package/src/engine/agent/prompt/scout.txt +36 -0
  235. package/src/engine/agent/prompt/summary.txt +11 -0
  236. package/src/engine/agent/prompt/title.txt +44 -0
  237. package/src/engine/agent/subagent-permissions.ts +34 -0
  238. package/src/engine/auth/index.ts +96 -0
  239. package/src/engine/background/background/job.ts +200 -0
  240. package/src/engine/background/job.ts +200 -0
  241. package/src/engine/bus/bus-event.ts +45 -0
  242. package/src/engine/bus/global.ts +22 -0
  243. package/src/engine/bus/index.ts +203 -0
  244. package/src/engine/command/command/index.ts +181 -0
  245. package/src/engine/command/command/template/initialize.txt +66 -0
  246. package/src/engine/command/command/template/review.txt +101 -0
  247. package/src/engine/command/index.ts +181 -0
  248. package/src/engine/command/template/initialize.txt +66 -0
  249. package/src/engine/command/template/review.txt +101 -0
  250. package/src/engine/config/agent.ts +172 -0
  251. package/src/engine/config/attachment.ts +25 -0
  252. package/src/engine/config/command.ts +62 -0
  253. package/src/engine/config/config.ts +833 -0
  254. package/src/engine/config/console-state.ts +14 -0
  255. package/src/engine/config/entry-name.ts +16 -0
  256. package/src/engine/config/error.ts +23 -0
  257. package/src/engine/config/formatter.ts +13 -0
  258. package/src/engine/config/layout.ts +6 -0
  259. package/src/engine/config/lsp.ts +43 -0
  260. package/src/engine/config/managed.ts +71 -0
  261. package/src/engine/config/markdown.ts +96 -0
  262. package/src/engine/config/mcp.ts +56 -0
  263. package/src/engine/config/model-id.ts +5 -0
  264. package/src/engine/config/parse.ts +79 -0
  265. package/src/engine/config/paths.ts +45 -0
  266. package/src/engine/config/permission.ts +58 -0
  267. package/src/engine/config/plugin.ts +84 -0
  268. package/src/engine/config/provider.ts +111 -0
  269. package/src/engine/config/reference.ts +23 -0
  270. package/src/engine/config/server.ts +19 -0
  271. package/src/engine/config/skills.ts +14 -0
  272. package/src/engine/config/variable.ts +90 -0
  273. package/src/engine/control-plane/adapters/index.ts +41 -0
  274. package/src/engine/control-plane/adapters/worktree.ts +96 -0
  275. package/src/engine/control-plane/dev/README.md +19 -0
  276. package/src/engine/control-plane/dev/debug-workspace-plugin.ts +73 -0
  277. package/src/engine/control-plane/schema.ts +14 -0
  278. package/src/engine/control-plane/types.ts +59 -0
  279. package/src/engine/control-plane/util.ts +39 -0
  280. package/src/engine/control-plane/workspace-adapter-runtime.ts +51 -0
  281. package/src/engine/control-plane/workspace-context.ts +26 -0
  282. package/src/engine/control-plane/workspace.sql.ts +20 -0
  283. package/src/engine/control-plane/workspace.ts +1072 -0
  284. package/src/engine/data-migration.ts +161 -0
  285. package/src/engine/effect/app-runtime.ts +143 -0
  286. package/src/engine/effect/bootstrap-runtime.ts +29 -0
  287. package/src/engine/effect/bridge.ts +84 -0
  288. package/src/engine/effect/config-service.ts +67 -0
  289. package/src/engine/effect/instance-ref.ts +11 -0
  290. package/src/engine/effect/instance-registry.ts +12 -0
  291. package/src/engine/effect/instance-state.ts +72 -0
  292. package/src/engine/effect/promise.ts +17 -0
  293. package/src/engine/effect/run-service.ts +47 -0
  294. package/src/engine/effect/runner.ts +217 -0
  295. package/src/engine/effect/runtime-flags.ts +74 -0
  296. package/src/engine/effect/service-use.ts +38 -0
  297. package/src/engine/env/index.ts +37 -0
  298. package/src/engine/event-v2-bridge.ts +89 -0
  299. package/src/engine/file/file/ignore.ts +81 -0
  300. package/src/engine/file/file/index.ts +651 -0
  301. package/src/engine/file/file/protected.ts +59 -0
  302. package/src/engine/file/file/ripgrep.ts +481 -0
  303. package/src/engine/file/file/watcher.ts +167 -0
  304. package/src/engine/file/ignore.ts +81 -0
  305. package/src/engine/file/index.ts +651 -0
  306. package/src/engine/file/protected.ts +59 -0
  307. package/src/engine/file/ripgrep.ts +481 -0
  308. package/src/engine/file/watcher.ts +167 -0
  309. package/src/engine/format/format/formatter.ts +404 -0
  310. package/src/engine/format/format/index.ts +209 -0
  311. package/src/engine/format/formatter.ts +404 -0
  312. package/src/engine/format/index.ts +209 -0
  313. package/src/engine/git/git/index.ts +347 -0
  314. package/src/engine/git/index.ts +347 -0
  315. package/src/engine/id/id.ts +80 -0
  316. package/src/engine/ide/index.ts +70 -0
  317. package/src/engine/image/image/image.ts +176 -0
  318. package/src/engine/image/image.ts +176 -0
  319. package/src/engine/index.ts +251 -0
  320. package/src/engine/installation/index.ts +327 -0
  321. package/src/engine/lsp/client.ts +707 -0
  322. package/src/engine/lsp/diagnostic.ts +29 -0
  323. package/src/engine/lsp/language.ts +121 -0
  324. package/src/engine/lsp/launch.ts +21 -0
  325. package/src/engine/lsp/lsp/client.ts +707 -0
  326. package/src/engine/lsp/lsp/diagnostic.ts +29 -0
  327. package/src/engine/lsp/lsp/language.ts +121 -0
  328. package/src/engine/lsp/lsp/launch.ts +21 -0
  329. package/src/engine/lsp/lsp/lsp.ts +507 -0
  330. package/src/engine/lsp/lsp/server.ts +2064 -0
  331. package/src/engine/lsp/lsp.ts +507 -0
  332. package/src/engine/lsp/server.ts +2064 -0
  333. package/src/engine/mcp/auth.ts +146 -0
  334. package/src/engine/mcp/index.ts +958 -0
  335. package/src/engine/mcp/mcp/auth.ts +146 -0
  336. package/src/engine/mcp/mcp/index.ts +958 -0
  337. package/src/engine/mcp/mcp/oauth-callback.ts +232 -0
  338. package/src/engine/mcp/mcp/oauth-provider.ts +214 -0
  339. package/src/engine/mcp/oauth-callback.ts +232 -0
  340. package/src/engine/mcp/oauth-provider.ts +214 -0
  341. package/src/engine/node.ts +6 -0
  342. package/src/engine/patch/index.ts +689 -0
  343. package/src/engine/patch/patch/index.ts +689 -0
  344. package/src/engine/permission/arity.ts +163 -0
  345. package/src/engine/permission/evaluate.ts +15 -0
  346. package/src/engine/permission/index.ts +306 -0
  347. package/src/engine/permission/permission/arity.ts +163 -0
  348. package/src/engine/permission/permission/evaluate.ts +15 -0
  349. package/src/engine/permission/permission/index.ts +306 -0
  350. package/src/engine/permission/permission/schema.ts +13 -0
  351. package/src/engine/permission/schema.ts +13 -0
  352. package/src/engine/plugin/azure.ts +26 -0
  353. package/src/engine/plugin/cloudflare.ts +76 -0
  354. package/src/engine/plugin/codex.ts +622 -0
  355. package/src/engine/plugin/digitalocean.ts +411 -0
  356. package/src/engine/plugin/github-copilot/copilot.ts +394 -0
  357. package/src/engine/plugin/github-copilot/models.ts +196 -0
  358. package/src/engine/plugin/index.ts +295 -0
  359. package/src/engine/plugin/install.ts +439 -0
  360. package/src/engine/plugin/loader.ts +216 -0
  361. package/src/engine/plugin/meta.ts +188 -0
  362. package/src/engine/plugin/shared.ts +323 -0
  363. package/src/engine/project/bootstrap-service.ts +9 -0
  364. package/src/engine/project/bootstrap.ts +75 -0
  365. package/src/engine/project/instance-context.ts +24 -0
  366. package/src/engine/project/instance-layer.ts +11 -0
  367. package/src/engine/project/instance-runtime.ts +16 -0
  368. package/src/engine/project/instance-store.ts +193 -0
  369. package/src/engine/project/project.sql.ts +17 -0
  370. package/src/engine/project/project.ts +537 -0
  371. package/src/engine/project/schema.ts +13 -0
  372. package/src/engine/project/vcs.ts +405 -0
  373. package/src/engine/provider/auth.ts +225 -0
  374. package/src/engine/provider/error.ts +204 -0
  375. package/src/engine/provider/model-status.ts +8 -0
  376. package/src/engine/provider/provider.ts +1843 -0
  377. package/src/engine/provider/schema.ts +30 -0
  378. package/src/engine/provider/sdk/copilot/AGENTS.md +1 -0
  379. package/src/engine/provider/transform.ts +1376 -0
  380. package/src/engine/pty/index.ts +365 -0
  381. package/src/engine/pty/input.ts +24 -0
  382. package/src/engine/pty/pty/index.ts +365 -0
  383. package/src/engine/pty/pty/input.ts +24 -0
  384. package/src/engine/pty/pty/pty.bun.ts +26 -0
  385. package/src/engine/pty/pty/pty.node.ts +27 -0
  386. package/src/engine/pty/pty/pty.ts +25 -0
  387. package/src/engine/pty/pty/schema.ts +14 -0
  388. package/src/engine/pty/pty/ticket.ts +68 -0
  389. package/src/engine/pty/pty.bun.ts +26 -0
  390. package/src/engine/pty/pty.node.ts +27 -0
  391. package/src/engine/pty/pty.ts +25 -0
  392. package/src/engine/pty/schema.ts +14 -0
  393. package/src/engine/pty/ticket.ts +68 -0
  394. package/src/engine/question/index.ts +213 -0
  395. package/src/engine/question/question/index.ts +213 -0
  396. package/src/engine/question/question/schema.ts +10 -0
  397. package/src/engine/question/schema.ts +10 -0
  398. package/src/engine/reference/reference/reference.ts +241 -0
  399. package/src/engine/reference/reference/repository-cache.ts +147 -0
  400. package/src/engine/reference/reference.ts +241 -0
  401. package/src/engine/reference/repository-cache.ts +147 -0
  402. package/src/engine/session/compaction.ts +651 -0
  403. package/src/engine/session/compaction_logic.ts +120 -0
  404. package/src/engine/session/instruction.ts +238 -0
  405. package/src/engine/session/instruction_loader.ts +54 -0
  406. package/src/engine/session/llm.ts +459 -0
  407. package/src/engine/session/message-error.ts +14 -0
  408. package/src/engine/session/message-v2.ts +1202 -0
  409. package/src/engine/session/message.ts +146 -0
  410. package/src/engine/session/overflow.ts +32 -0
  411. package/src/engine/session/overflow_check.ts +46 -0
  412. package/src/engine/session/processor.ts +823 -0
  413. package/src/engine/session/prompt/anthropic.txt +105 -0
  414. package/src/engine/session/prompt/beast.txt +147 -0
  415. package/src/engine/session/prompt/build-switch.txt +5 -0
  416. package/src/engine/session/prompt/codex.txt +79 -0
  417. package/src/engine/session/prompt/copilot-gpt-5.txt +143 -0
  418. package/src/engine/session/prompt/default.txt +105 -0
  419. package/src/engine/session/prompt/gemini.txt +155 -0
  420. package/src/engine/session/prompt/gpt.txt +107 -0
  421. package/src/engine/session/prompt/kimi.txt +95 -0
  422. package/src/engine/session/prompt/max-steps.txt +16 -0
  423. package/src/engine/session/prompt/plan-reminder-anthropic.txt +67 -0
  424. package/src/engine/session/prompt/plan.txt +26 -0
  425. package/src/engine/session/prompt/trinity.txt +97 -0
  426. package/src/engine/session/prompt.ts +671 -0
  427. package/src/engine/session/provider_transform.ts +187 -0
  428. package/src/engine/session/retry.ts +200 -0
  429. package/src/engine/session/retry_logic.ts +65 -0
  430. package/src/engine/session/revert.ts +162 -0
  431. package/src/engine/session/run-state.ts +153 -0
  432. package/src/engine/session/schema.ts +26 -0
  433. package/src/engine/session/session.sql.ts +137 -0
  434. package/src/engine/session/session.ts +1011 -0
  435. package/src/engine/session/status.ts +94 -0
  436. package/src/engine/session/summary.ts +164 -0
  437. package/src/engine/session/system.ts +84 -0
  438. package/src/engine/session/system_prompt.ts +65 -0
  439. package/src/engine/session/todo.ts +81 -0
  440. package/src/engine/session/tool_registry.ts +162 -0
  441. package/src/engine/share/session.ts +61 -0
  442. package/src/engine/share/share-next.ts +376 -0
  443. package/src/engine/share/share.sql.ts +13 -0
  444. package/src/engine/shell/shell/shell.ts +215 -0
  445. package/src/engine/shell/shell.ts +215 -0
  446. package/src/engine/skill/discovery.ts +116 -0
  447. package/src/engine/skill/index.ts +336 -0
  448. package/src/engine/skill/prompt/customize-opencode.md +377 -0
  449. package/src/engine/skill/skill/discovery.ts +116 -0
  450. package/src/engine/skill/skill/index.ts +336 -0
  451. package/src/engine/skill/skill/prompt/customize-opencode.md +377 -0
  452. package/src/engine/snapshot/index.ts +762 -0
  453. package/src/engine/snapshot/snapshot/index.ts +762 -0
  454. package/src/engine/sync/README.md +179 -0
  455. package/src/engine/sync/event.sql.ts +17 -0
  456. package/src/engine/sync/index.ts +410 -0
  457. package/src/engine/sync/schema.ts +11 -0
  458. package/src/engine/temporary.ts +33 -0
  459. package/src/engine/tool/apply_patch.ts +313 -0
  460. package/src/engine/tool/apply_patch.txt +33 -0
  461. package/src/engine/tool/edit.ts +711 -0
  462. package/src/engine/tool/edit.txt +10 -0
  463. package/src/engine/tool/external-directory.ts +49 -0
  464. package/src/engine/tool/glob.ts +103 -0
  465. package/src/engine/tool/glob.txt +6 -0
  466. package/src/engine/tool/grep.ts +156 -0
  467. package/src/engine/tool/grep.txt +8 -0
  468. package/src/engine/tool/invalid.ts +21 -0
  469. package/src/engine/tool/json-schema.ts +164 -0
  470. package/src/engine/tool/lsp.ts +113 -0
  471. package/src/engine/tool/lsp.txt +24 -0
  472. package/src/engine/tool/mcp-websearch.ts +96 -0
  473. package/src/engine/tool/plan-enter.txt +14 -0
  474. package/src/engine/tool/plan-exit.txt +13 -0
  475. package/src/engine/tool/plan.ts +78 -0
  476. package/src/engine/tool/question.ts +44 -0
  477. package/src/engine/tool/question.txt +10 -0
  478. package/src/engine/tool/read.ts +337 -0
  479. package/src/engine/tool/read.txt +14 -0
  480. package/src/engine/tool/registry.ts +472 -0
  481. package/src/engine/tool/repo_clone.ts +80 -0
  482. package/src/engine/tool/repo_clone.txt +5 -0
  483. package/src/engine/tool/repo_overview.ts +279 -0
  484. package/src/engine/tool/repo_overview.txt +4 -0
  485. package/src/engine/tool/schema.ts +14 -0
  486. package/src/engine/tool/shell/id.ts +19 -0
  487. package/src/engine/tool/shell/prompt.ts +295 -0
  488. package/src/engine/tool/shell/shell.txt +77 -0
  489. package/src/engine/tool/shell.ts +647 -0
  490. package/src/engine/tool/skill.ts +75 -0
  491. package/src/engine/tool/skill.txt +5 -0
  492. package/src/engine/tool/task.ts +337 -0
  493. package/src/engine/tool/task.txt +58 -0
  494. package/src/engine/tool/task_status.ts +179 -0
  495. package/src/engine/tool/task_status.txt +13 -0
  496. package/src/engine/tool/todo.ts +57 -0
  497. package/src/engine/tool/todowrite.txt +167 -0
  498. package/src/engine/tool/tool/apply_patch.ts +313 -0
  499. package/src/engine/tool/tool/apply_patch.txt +33 -0
  500. package/src/engine/tool/tool/edit.ts +711 -0
  501. package/src/engine/tool/tool/edit.txt +10 -0
  502. package/src/engine/tool/tool/external-directory.ts +49 -0
  503. package/src/engine/tool/tool/glob.ts +103 -0
  504. package/src/engine/tool/tool/glob.txt +6 -0
  505. package/src/engine/tool/tool/grep.ts +156 -0
  506. package/src/engine/tool/tool/grep.txt +8 -0
  507. package/src/engine/tool/tool/invalid.ts +21 -0
  508. package/src/engine/tool/tool/json-schema.ts +164 -0
  509. package/src/engine/tool/tool/lsp.ts +113 -0
  510. package/src/engine/tool/tool/lsp.txt +24 -0
  511. package/src/engine/tool/tool/mcp-websearch.ts +96 -0
  512. package/src/engine/tool/tool/plan-enter.txt +14 -0
  513. package/src/engine/tool/tool/plan-exit.txt +13 -0
  514. package/src/engine/tool/tool/plan.ts +78 -0
  515. package/src/engine/tool/tool/question.ts +44 -0
  516. package/src/engine/tool/tool/question.txt +10 -0
  517. package/src/engine/tool/tool/read.ts +337 -0
  518. package/src/engine/tool/tool/read.txt +14 -0
  519. package/src/engine/tool/tool/registry.ts +472 -0
  520. package/src/engine/tool/tool/repo_clone.ts +80 -0
  521. package/src/engine/tool/tool/repo_clone.txt +5 -0
  522. package/src/engine/tool/tool/repo_overview.ts +279 -0
  523. package/src/engine/tool/tool/repo_overview.txt +4 -0
  524. package/src/engine/tool/tool/schema.ts +14 -0
  525. package/src/engine/tool/tool/shell/id.ts +19 -0
  526. package/src/engine/tool/tool/shell/prompt.ts +295 -0
  527. package/src/engine/tool/tool/shell/shell.txt +77 -0
  528. package/src/engine/tool/tool/shell.ts +647 -0
  529. package/src/engine/tool/tool/skill.ts +75 -0
  530. package/src/engine/tool/tool/skill.txt +5 -0
  531. package/src/engine/tool/tool/task.ts +337 -0
  532. package/src/engine/tool/tool/task.txt +58 -0
  533. package/src/engine/tool/tool/task_status.ts +179 -0
  534. package/src/engine/tool/tool/task_status.txt +13 -0
  535. package/src/engine/tool/tool/todo.ts +57 -0
  536. package/src/engine/tool/tool/todowrite.txt +167 -0
  537. package/src/engine/tool/tool/tool.ts +164 -0
  538. package/src/engine/tool/tool/truncate.ts +160 -0
  539. package/src/engine/tool/tool/truncation-dir.ts +4 -0
  540. package/src/engine/tool/tool/webfetch.ts +192 -0
  541. package/src/engine/tool/tool/webfetch.txt +13 -0
  542. package/src/engine/tool/tool/websearch.ts +143 -0
  543. package/src/engine/tool/tool/websearch.txt +14 -0
  544. package/src/engine/tool/tool/write.ts +104 -0
  545. package/src/engine/tool/tool/write.txt +8 -0
  546. package/src/engine/tool/tool.ts +164 -0
  547. package/src/engine/tool/truncate.ts +160 -0
  548. package/src/engine/tool/truncation-dir.ts +4 -0
  549. package/src/engine/tool/webfetch.ts +192 -0
  550. package/src/engine/tool/webfetch.txt +13 -0
  551. package/src/engine/tool/websearch.ts +143 -0
  552. package/src/engine/tool/websearch.txt +14 -0
  553. package/src/engine/tool/write.ts +104 -0
  554. package/src/engine/tool/write.txt +8 -0
  555. package/src/engine/util/archive.ts +17 -0
  556. package/src/engine/util/bom.ts +31 -0
  557. package/src/engine/util/data-url.ts +9 -0
  558. package/src/engine/util/defer.ts +10 -0
  559. package/src/engine/util/effect-http-client.ts +11 -0
  560. package/src/engine/util/error.ts +88 -0
  561. package/src/engine/util/filesystem.ts +252 -0
  562. package/src/engine/util/format.ts +20 -0
  563. package/src/engine/util/iife.ts +3 -0
  564. package/src/engine/util/lazy.ts +20 -0
  565. package/src/engine/util/local-context.ts +25 -0
  566. package/src/engine/util/locale.ts +86 -0
  567. package/src/engine/util/media.ts +26 -0
  568. package/src/engine/util/process.ts +176 -0
  569. package/src/engine/util/queue.ts +32 -0
  570. package/src/engine/util/record.ts +3 -0
  571. package/src/engine/util/repository.ts +158 -0
  572. package/src/engine/util/rpc.ts +66 -0
  573. package/src/engine/util/signal.ts +12 -0
  574. package/src/engine/util/timeout.ts +13 -0
  575. package/src/engine/util/token.ts +7 -0
  576. package/src/engine/util/util/archive.ts +17 -0
  577. package/src/engine/util/util/bom.ts +31 -0
  578. package/src/engine/util/util/data-url.ts +9 -0
  579. package/src/engine/util/util/defer.ts +10 -0
  580. package/src/engine/util/util/effect-http-client.ts +11 -0
  581. package/src/engine/util/util/error.ts +88 -0
  582. package/src/engine/util/util/filesystem.ts +252 -0
  583. package/src/engine/util/util/format.ts +20 -0
  584. package/src/engine/util/util/iife.ts +3 -0
  585. package/src/engine/util/util/lazy.ts +20 -0
  586. package/src/engine/util/util/local-context.ts +25 -0
  587. package/src/engine/util/util/locale.ts +86 -0
  588. package/src/engine/util/util/media.ts +26 -0
  589. package/src/engine/util/util/process.ts +176 -0
  590. package/src/engine/util/util/queue.ts +32 -0
  591. package/src/engine/util/util/record.ts +3 -0
  592. package/src/engine/util/util/repository.ts +158 -0
  593. package/src/engine/util/util/rpc.ts +66 -0
  594. package/src/engine/util/util/signal.ts +12 -0
  595. package/src/engine/util/util/timeout.ts +13 -0
  596. package/src/engine/util/util/token.ts +7 -0
  597. package/src/engine/util/util/which.ts +14 -0
  598. package/src/engine/util/util/wildcard.ts +59 -0
  599. package/src/engine/util/which.ts +14 -0
  600. package/src/engine/util/wildcard.ts +59 -0
  601. package/src/engine/worktree/index.ts +621 -0
  602. package/src/rag_worker.ts +519 -0
  603. package/src/server.ts +201 -0
  604. package/src/tui.ts +637 -0
  605. package/tsconfig.json +24 -0
@@ -0,0 +1,249 @@
1
+ // Generated by BoneScript compiler. DO NOT EDIT.
2
+ // Regression tests derived from capability declarations.
3
+ // Run: npx ts-node src/tests.ts
4
+
5
+ import * as http from "http";
6
+
7
+ const BASE_URL = process.env.TEST_BASE_URL || "http://localhost:3000";
8
+ const AUTH_TOKEN = process.env.TEST_AUTH_TOKEN || "";
9
+
10
+ let passed = 0;
11
+ let failed = 0;
12
+
13
+ async function request(method: string, path: string, body?: any): Promise<{ status: number; data: any }> {
14
+ const url = new URL(path, BASE_URL);
15
+ const res = await fetch(url.toString(), {
16
+ method,
17
+ headers: {
18
+ "Content-Type": "application/json",
19
+ ...(AUTH_TOKEN ? { "Authorization": `Bearer ${AUTH_TOKEN}` } : {}),
20
+ },
21
+ body: body ? JSON.stringify(body) : undefined,
22
+ });
23
+ const data = await res.json().catch(() => ({}));
24
+ return { status: res.status, data };
25
+ }
26
+
27
+ async function test(name: string, fn: () => Promise<void>): Promise<void> {
28
+ try {
29
+ await fn();
30
+ console.log(` ✓ ${name}`);
31
+ passed++;
32
+ } catch (e: any) {
33
+ console.log(` ✗ ${name}: ${e.message}`);
34
+ failed++;
35
+ }
36
+ }
37
+
38
+ function assert(condition: boolean, message: string): void {
39
+ if (!condition) throw new Error(message);
40
+ }
41
+
42
+ (async () => {
43
+ // ─── WorkspaceService Tests ─────────────────────────────────────────────────────
44
+
45
+ console.log("\nWorkspaceService — CRUD");
46
+
47
+ let __workspace_id: string;
48
+
49
+ await test("POST /workspaces — creates entity", async () => {
50
+ const { status, data } = await request("POST", "/workspaces", {"project_id":"00000000-0000-0000-0000-000000000001","root_path":"test_value","git_remote":null,"git_branch":null,"git_commit":null,"is_dirty":true,"file_count":null,"total_size_bytes":null,"config":null});
51
+ assert(status === 201, `Expected 201, got ${status}: ${JSON.stringify(data)}`);
52
+ assert(data.id, "Response must have id");
53
+ __workspace_id = data.id;
54
+ });
55
+
56
+ await test("GET /workspaces/:id — reads entity", async () => {
57
+ const { status, data } = await request("GET", `/workspaces/${__workspace_id}`);
58
+ assert(status === 200, `Expected 200, got ${status}`);
59
+ assert(data.id === __workspace_id, "ID must match");
60
+ });
61
+
62
+ await test("GET /workspaces — lists entities", async () => {
63
+ const { status, data } = await request("GET", "/workspaces");
64
+ assert(status === 200, `Expected 200, got ${status}`);
65
+ assert(Array.isArray(data.items), "Response must have items array");
66
+ assert(typeof data.total === "number", "Response must have total");
67
+ });
68
+
69
+ await test("GET /workspaces — rejects unauthenticated", async () => {
70
+ const res = await fetch(`${BASE_URL}/workspaces`);
71
+ assert(res.status === 401, `Expected 401, got ${res.status}`);
72
+ });
73
+
74
+ await test("POST /workspaces/create-snapshot — capability executes", async () => {
75
+ const { status, data } = await request("POST", "/workspaces/create-snapshot", {
76
+ workspace_id: __workspace_id,
77
+ });
78
+ // Capability may return 200 (success) or 422 (precondition failed) — both are valid
79
+ assert([200, 422].includes(status), `Expected 200 or 422, got ${status}: ${JSON.stringify(data)}`);
80
+ });
81
+
82
+ await test("POST /workspaces/create-snapshot — returns 401 without auth", async () => {
83
+ const res = await fetch(`${BASE_URL}/workspaces/create-snapshot`, { method: "POST" });
84
+ assert(res.status === 401, `Expected 401, got ${res.status}`);
85
+ });
86
+
87
+ await test("POST /workspaces/revert-to-snapshot — capability executes", async () => {
88
+ const { status, data } = await request("POST", "/workspaces/revert-to-snapshot", {
89
+ workspace_id: __workspace_id,
90
+ });
91
+ // Capability may return 200 (success) or 422 (precondition failed) — both are valid
92
+ assert([200, 422].includes(status), `Expected 200 or 422, got ${status}: ${JSON.stringify(data)}`);
93
+ });
94
+
95
+ await test("POST /workspaces/revert-to-snapshot — returns 401 without auth", async () => {
96
+ const res = await fetch(`${BASE_URL}/workspaces/revert-to-snapshot`, { method: "POST" });
97
+ assert(res.status === 401, `Expected 401, got ${res.status}`);
98
+ });
99
+
100
+ await test("POST /workspaces/analyze-codebase — capability executes", async () => {
101
+ const { status, data } = await request("POST", "/workspaces/analyze-codebase", {
102
+ workspace_id: __workspace_id,
103
+ });
104
+ // Capability may return 200 (success) or 422 (precondition failed) — both are valid
105
+ assert([200, 422].includes(status), `Expected 200 or 422, got ${status}: ${JSON.stringify(data)}`);
106
+ });
107
+
108
+ await test("POST /workspaces/analyze-codebase — returns 401 without auth", async () => {
109
+ const res = await fetch(`${BASE_URL}/workspaces/analyze-codebase`, { method: "POST" });
110
+ assert(res.status === 401, `Expected 401, got ${res.status}`);
111
+ });
112
+
113
+ // State machine: Workspace
114
+ await test("PUT /workspaces/:id — rejects invalid state transition", async () => {
115
+ const { status, data } = await request("PUT", `/workspaces/${__workspace_id}`, {
116
+ state: "__invalid_state__",
117
+ });
118
+ assert(status === 422, `Expected 422 for invalid transition, got ${status}`);
119
+ assert(data.error?.code === "INVALID_TRANSITION", "Error code must be INVALID_TRANSITION");
120
+ });
121
+
122
+ await test("DELETE /workspaces/:id — deletes entity", async () => {
123
+ const { status } = await request("DELETE", `/workspaces/${__workspace_id}`);
124
+ assert(status === 204, `Expected 204, got ${status}`);
125
+ });
126
+
127
+ await test("GET /workspaces/:id — returns 404 after delete", async () => {
128
+ const { status } = await request("GET", `/workspaces/${__workspace_id}`);
129
+ assert(status === 404, `Expected 404, got ${status}`);
130
+ });
131
+
132
+ // ─── CodebaseService Tests ─────────────────────────────────────────────────────
133
+
134
+ console.log("\nCodebaseService — CRUD");
135
+
136
+ let __codebase_id: string;
137
+
138
+ await test("POST /codebases — creates entity", async () => {
139
+ const { status, data } = await request("POST", "/codebases", {"workspace_id":"00000000-0000-0000-0000-000000000001","project_id":"00000000-0000-0000-0000-000000000001","primary_language":null,"languages":null,"framework":null,"build_tool":null,"test_framework":null,"entry_points":null,"dependencies":null,"analysis_version":null});
140
+ assert(status === 201, `Expected 201, got ${status}: ${JSON.stringify(data)}`);
141
+ assert(data.id, "Response must have id");
142
+ __codebase_id = data.id;
143
+ });
144
+
145
+ await test("GET /codebases/:id — reads entity", async () => {
146
+ const { status, data } = await request("GET", `/codebases/${__codebase_id}`);
147
+ assert(status === 200, `Expected 200, got ${status}`);
148
+ assert(data.id === __codebase_id, "ID must match");
149
+ });
150
+
151
+ await test("GET /codebases — lists entities", async () => {
152
+ const { status, data } = await request("GET", "/codebases");
153
+ assert(status === 200, `Expected 200, got ${status}`);
154
+ assert(Array.isArray(data.items), "Response must have items array");
155
+ assert(typeof data.total === "number", "Response must have total");
156
+ });
157
+
158
+ await test("GET /codebases — rejects unauthenticated", async () => {
159
+ const res = await fetch(`${BASE_URL}/codebases`);
160
+ assert(res.status === 401, `Expected 401, got ${res.status}`);
161
+ });
162
+
163
+ // State machine: Codebase
164
+ await test("PUT /codebases/:id — rejects invalid state transition", async () => {
165
+ const { status, data } = await request("PUT", `/codebases/${__codebase_id}`, {
166
+ state: "__invalid_state__",
167
+ });
168
+ assert(status === 422, `Expected 422 for invalid transition, got ${status}`);
169
+ assert(data.error?.code === "INVALID_TRANSITION", "Error code must be INVALID_TRANSITION");
170
+ });
171
+
172
+ await test("DELETE /codebases/:id — deletes entity", async () => {
173
+ const { status } = await request("DELETE", `/codebases/${__codebase_id}`);
174
+ assert(status === 204, `Expected 204, got ${status}`);
175
+ });
176
+
177
+ await test("GET /codebases/:id — returns 404 after delete", async () => {
178
+ const { status } = await request("GET", `/codebases/${__codebase_id}`);
179
+ assert(status === 404, `Expected 404, got ${status}`);
180
+ });
181
+
182
+ // ─── SnapshotService Tests ─────────────────────────────────────────────────────
183
+
184
+ console.log("\nSnapshotService — CRUD");
185
+
186
+ let __snapshot_id: string;
187
+
188
+ await test("POST /snapshots — creates entity", async () => {
189
+ const { status, data } = await request("POST", "/snapshots", {"session_id":"00000000-0000-0000-0000-000000000001","project_id":"00000000-0000-0000-0000-000000000001","workspace_id":"00000000-0000-0000-0000-000000000001","git_hash":"test_value","message_id":null,"part_id":null,"diff_summary":null,"files_changed":null});
190
+ assert(status === 201, `Expected 201, got ${status}: ${JSON.stringify(data)}`);
191
+ assert(data.id, "Response must have id");
192
+ __snapshot_id = data.id;
193
+ });
194
+
195
+ await test("GET /snapshots/:id — reads entity", async () => {
196
+ const { status, data } = await request("GET", `/snapshots/${__snapshot_id}`);
197
+ assert(status === 200, `Expected 200, got ${status}`);
198
+ assert(data.id === __snapshot_id, "ID must match");
199
+ });
200
+
201
+ await test("GET /snapshots — lists entities", async () => {
202
+ const { status, data } = await request("GET", "/snapshots");
203
+ assert(status === 200, `Expected 200, got ${status}`);
204
+ assert(Array.isArray(data.items), "Response must have items array");
205
+ assert(typeof data.total === "number", "Response must have total");
206
+ });
207
+
208
+ await test("GET /snapshots — rejects unauthenticated", async () => {
209
+ const res = await fetch(`${BASE_URL}/snapshots`);
210
+ assert(res.status === 401, `Expected 401, got ${res.status}`);
211
+ });
212
+
213
+ await test("POST /snapshots/revert-to-snapshot — capability executes", async () => {
214
+ const { status, data } = await request("POST", "/snapshots/revert-to-snapshot", {
215
+ snapshot_id: __snapshot_id,
216
+ });
217
+ // Capability may return 200 (success) or 422 (precondition failed) — both are valid
218
+ assert([200, 422].includes(status), `Expected 200 or 422, got ${status}: ${JSON.stringify(data)}`);
219
+ });
220
+
221
+ await test("POST /snapshots/revert-to-snapshot — returns 401 without auth", async () => {
222
+ const res = await fetch(`${BASE_URL}/snapshots/revert-to-snapshot`, { method: "POST" });
223
+ assert(res.status === 401, `Expected 401, got ${res.status}`);
224
+ });
225
+
226
+ // State machine: Snapshot
227
+ await test("PUT /snapshots/:id — rejects invalid state transition", async () => {
228
+ const { status, data } = await request("PUT", `/snapshots/${__snapshot_id}`, {
229
+ state: "__invalid_state__",
230
+ });
231
+ assert(status === 422, `Expected 422 for invalid transition, got ${status}`);
232
+ assert(data.error?.code === "INVALID_TRANSITION", "Error code must be INVALID_TRANSITION");
233
+ });
234
+
235
+ await test("DELETE /snapshots/:id — deletes entity", async () => {
236
+ const { status } = await request("DELETE", `/snapshots/${__snapshot_id}`);
237
+ assert(status === 204, `Expected 204, got ${status}`);
238
+ });
239
+
240
+ await test("GET /snapshots/:id — returns 404 after delete", async () => {
241
+ const { status } = await request("GET", `/snapshots/${__snapshot_id}`);
242
+ assert(status === 404, `Expected 404, got ${status}`);
243
+ });
244
+
245
+ console.log(`\n════════════════════════════════════════`);
246
+ console.log(`Results: ${passed} passed, ${failed} failed`);
247
+ console.log("═".repeat(40));
248
+ if (failed > 0) process.exit(1);
249
+ })().catch(e => { console.error(e); process.exit(1); });
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "lib": [
6
+ "ES2020",
7
+ "DOM"
8
+ ],
9
+ "outDir": "./dist",
10
+ "rootDir": "./src",
11
+ "strict": true,
12
+ "esModuleInterop": true,
13
+ "skipLibCheck": true,
14
+ "forceConsistentCasingInFileNames": true,
15
+ "declaration": true,
16
+ "sourceMap": true
17
+ },
18
+ "include": [
19
+ "src/**/*"
20
+ ],
21
+ "exclude": [
22
+ "node_modules",
23
+ "dist"
24
+ ]
25
+ }
@@ -0,0 +1,410 @@
1
+ /**
2
+ * BoneCode Compatibility Adapter
3
+ *
4
+ * Maps the OpenCode v2 HTTP + SSE API to the BoneCode backend.
5
+ * Existing clients (TUI, Desktop, VS Code) connect to this adapter
6
+ * and receive responses in the exact format they expect.
7
+ *
8
+ * OpenCode API surface covered:
9
+ * POST /v2/session → create_session
10
+ * GET /v2/session → list sessions
11
+ * GET /v2/session/:id → get session
12
+ * DELETE /v2/session/:id → delete_session
13
+ * POST /v2/session/:id/prompt → run_agent_turn (streaming SSE)
14
+ * GET /v2/session/:id/message → list messages
15
+ * GET /v2/session/:id/message/:msgId → get message
16
+ * GET /v2/event → SSE event stream (global)
17
+ * GET /v2/provider → list providers
18
+ * GET /v2/model → list models
19
+ * GET /v2/config → get config
20
+ * PUT /v2/config → update config
21
+ * GET /health → health check
22
+ */
23
+
24
+ import { Router, Request, Response } from "express";
25
+ import { pool } from "../bone/output/session/src/db";
26
+ import { eventBus } from "../bone/output/session/src/events";
27
+ import { requireAuth } from "../bone/output/session/src/auth";
28
+ import { v4 as uuid } from "uuid";
29
+
30
+ export const compatRouter = Router();
31
+
32
+ // ─── SSE Helper ───────────────────────────────────────────────────────────────
33
+
34
+ function sendSSE(res: Response, event: string, data: unknown): void {
35
+ res.write(`event: ${event}\n`);
36
+ res.write(`data: ${JSON.stringify(data)}\n\n`);
37
+ }
38
+
39
+ // ─── Session Routes ───────────────────────────────────────────────────────────
40
+
41
+ // POST /v2/session — create a new session
42
+ compatRouter.post("/v2/session", async (req: Request, res: Response) => {
43
+ try {
44
+ const { projectID, title, parentID } = req.body;
45
+
46
+ // Resolve or create project
47
+ let project_id = projectID;
48
+ if (!project_id) {
49
+ const cwd = req.body.directory || process.cwd();
50
+ const projectResult = await pool.query(
51
+ `SELECT id FROM projects WHERE worktree = $1 LIMIT 1`,
52
+ [cwd]
53
+ );
54
+ if (projectResult.rows[0]) {
55
+ project_id = projectResult.rows[0].id;
56
+ } else {
57
+ project_id = uuid();
58
+ await pool.query(
59
+ `INSERT INTO projects (id, root_commit_hash, worktree, vcs, name, sandboxes) VALUES ($1, $2, $3, $4, $5, $6)`,
60
+ [project_id, "unknown", cwd, "git", cwd.split("/").pop() || "project", JSON.stringify([])]
61
+ );
62
+ }
63
+ }
64
+
65
+ const session_id = uuid();
66
+ const slug = `session-${Date.now()}`;
67
+ const sessionTitle = title || "New Session";
68
+
69
+ await pool.query(
70
+ `INSERT INTO sessions (id, slug, project_id, parent_id, directory, title, version, state)
71
+ VALUES ($1, $2, $3, $4, $5, $6, $7, 'created')`,
72
+ [session_id, slug, project_id, parentID || null, req.body.directory || process.cwd(), sessionTitle, "1.0.0"]
73
+ );
74
+
75
+ // Publish event so WebSocket subscribers receive it
76
+ await eventBus.publish("SessionCreated", {
77
+ session_id, project_id, slug, title: sessionTitle,
78
+ created_at: new Date().toISOString(),
79
+ }, "CompatAdapter");
80
+
81
+ const session = await getSessionInfo(session_id);
82
+ res.status(201).json(session);
83
+ } catch (e: any) {
84
+ res.status(400).json({ error: { code: "CREATE_FAILED", message: e.message } });
85
+ }
86
+ });
87
+
88
+ // GET /v2/session — list sessions
89
+ compatRouter.get("/v2/session", async (req: Request, res: Response) => {
90
+ try {
91
+ const { projectID, directory, search } = req.query;
92
+ let sql = `SELECT * FROM sessions WHERE state != 'deleted'`;
93
+ const params: unknown[] = [];
94
+ let idx = 1;
95
+
96
+ if (projectID) { sql += ` AND project_id = $${idx++}`; params.push(projectID); }
97
+ if (directory) { sql += ` AND directory = $${idx++}`; params.push(directory); }
98
+ if (search) { sql += ` AND title ILIKE $${idx++}`; params.push(`%${search}%`); }
99
+
100
+ sql += ` ORDER BY updated_at DESC LIMIT 100`;
101
+
102
+ const result = await pool.query(sql, params);
103
+ res.json(result.rows.map(toOpenCodeSession));
104
+ } catch (e: any) {
105
+ res.status(500).json({ error: { code: "LIST_FAILED", message: e.message } });
106
+ }
107
+ });
108
+
109
+ // GET /v2/session/:id — get session
110
+ compatRouter.get("/v2/session/:id", async (req: Request, res: Response) => {
111
+ try {
112
+ const session = await getSessionInfo(req.params.id);
113
+ if (!session) return res.status(404).json({ error: { code: "NOT_FOUND", message: "Session not found" } });
114
+ res.json(session);
115
+ } catch (e: any) {
116
+ res.status(500).json({ error: { code: "DB_ERROR", message: e.message } });
117
+ }
118
+ });
119
+
120
+ // DELETE /v2/session/:id — delete session
121
+ compatRouter.delete("/v2/session/:id", async (req: Request, res: Response) => {
122
+ try {
123
+ await pool.query(`UPDATE sessions SET state = 'deleted', updated_at = NOW() WHERE id = $1`, [req.params.id]);
124
+ res.status(204).send();
125
+ } catch (e: any) {
126
+ res.status(500).json({ error: { code: "DELETE_FAILED", message: e.message } });
127
+ }
128
+ });
129
+
130
+ // POST /v2/session/:id/prompt — run agent turn (streaming SSE)
131
+ compatRouter.post("/v2/session/:id/prompt", requireAuth, async (req: Request, res: Response) => {
132
+ const session_id = req.params.id;
133
+
134
+ // Set up SSE
135
+ res.setHeader("Content-Type", "text/event-stream");
136
+ res.setHeader("Cache-Control", "no-cache");
137
+ res.setHeader("Connection", "keep-alive");
138
+ res.flushHeaders();
139
+
140
+ try {
141
+ const { content, modelID, providerID } = req.body;
142
+
143
+ // Create user message
144
+ const message_id = uuid();
145
+ await pool.query(
146
+ `INSERT INTO messages (id, session_id, role) VALUES ($1, $2, 'user')`,
147
+ [message_id, session_id]
148
+ );
149
+
150
+ // Create text part for user message
151
+ const part_id = uuid();
152
+ await pool.query(
153
+ `INSERT INTO parts (id, message_id, session_id, part_type, data, order_index) VALUES ($1, $2, $3, 'text', $4, 0)`,
154
+ [part_id, message_id, session_id, JSON.stringify({ text: content })]
155
+ );
156
+
157
+ // Update session state to active
158
+ await pool.query(
159
+ `UPDATE sessions SET state = 'active', updated_at = NOW() WHERE id = $1`,
160
+ [session_id]
161
+ );
162
+
163
+ // Emit session.updated event to SSE subscribers
164
+ sendSSE(res, "session.updated", { type: "session.updated", properties: { id: session_id } });
165
+ sendSSE(res, "message.updated", { type: "message.updated", properties: { id: message_id, sessionID: session_id } });
166
+
167
+ // Subscribe to part updates for this session (live streaming)
168
+ const unsubscribe = subscribeToSessionEvents(session_id, (event) => {
169
+ sendSSE(res, event.type, event.data);
170
+ });
171
+
172
+ // Start the agent turn (async — results come via events)
173
+ startAgentTurn(session_id, message_id, modelID, providerID)
174
+ .then(() => {
175
+ sendSSE(res, "session.updated", { type: "session.updated", properties: { id: session_id } });
176
+ res.end();
177
+ })
178
+ .catch((e) => {
179
+ console.error("[AgentLoop] Error:", e.message, e.stack?.split("\n").slice(0,5).join(" | "));
180
+ sendSSE(res, "error", { type: "error", properties: { message: e.message } });
181
+ res.end();
182
+ })
183
+ .finally(() => {
184
+ unsubscribe();
185
+ });
186
+
187
+ // Handle client disconnect
188
+ req.on("close", () => {
189
+ unsubscribe();
190
+ });
191
+ } catch (e: any) {
192
+ sendSSE(res, "error", { type: "error", properties: { message: e.message } });
193
+ res.end();
194
+ }
195
+ });
196
+
197
+ // GET /v2/session/:id/message — list messages
198
+ compatRouter.get("/v2/session/:id/message", async (req: Request, res: Response) => {
199
+ try {
200
+ const result = await pool.query(
201
+ `SELECT m.*, json_agg(p.* ORDER BY p.order_index) FILTER (WHERE p.id IS NOT NULL) as parts
202
+ FROM messages m
203
+ LEFT JOIN parts p ON p.message_id = m.id
204
+ WHERE m.session_id = $1
205
+ GROUP BY m.id
206
+ ORDER BY m.created_at ASC`,
207
+ [req.params.id]
208
+ );
209
+ res.json(result.rows.map(toOpenCodeMessage));
210
+ } catch (e: any) {
211
+ res.status(500).json({ error: { code: "DB_ERROR", message: e.message } });
212
+ }
213
+ });
214
+
215
+ // ─── Global SSE Event Stream ──────────────────────────────────────────────────
216
+
217
+ // GET /v2/event — global SSE stream for all events
218
+ compatRouter.get("/v2/event", (req: Request, res: Response) => {
219
+ res.setHeader("Content-Type", "text/event-stream");
220
+ res.setHeader("Cache-Control", "no-cache");
221
+ res.setHeader("Connection", "keep-alive");
222
+ res.flushHeaders();
223
+
224
+ // Subscribe to all system events
225
+ const handler = async (event: any) => {
226
+ sendSSE(res, event.type, event);
227
+ };
228
+
229
+ const eventTypes = [
230
+ "SessionCreated", "SessionStateChanged", "MessageAdded", "PartUpdated",
231
+ "AgentStarted", "AgentCompleted", "ToolCallRequested", "ToolCallCompleted",
232
+ "PermissionRequired",
233
+ ];
234
+
235
+ for (const type of eventTypes) {
236
+ eventBus.subscribe(type, handler);
237
+ }
238
+
239
+ req.on("close", () => {
240
+ for (const type of eventTypes) {
241
+ eventBus.unsubscribe(type, handler);
242
+ }
243
+ });
244
+ });
245
+
246
+ // ─── Provider / Model Routes ──────────────────────────────────────────────────
247
+
248
+ // GET /v2/provider — list available providers
249
+ compatRouter.get("/v2/provider", (_req: Request, res: Response) => {
250
+ res.json([
251
+ { id: "anthropic", name: "Anthropic", models: ["claude-opus-4-5", "claude-sonnet-4-5", "claude-haiku-3-5"] },
252
+ { id: "openai", name: "OpenAI", models: ["gpt-4o", "gpt-4o-mini", "o1", "o3-mini"] },
253
+ { id: "google", name: "Google", models: ["gemini-2.0-flash", "gemini-1.5-pro"] },
254
+ { id: "ollama", name: "Ollama (local)", models: [] },
255
+ { id: "openrouter", name: "OpenRouter", models: [] },
256
+ ]);
257
+ });
258
+
259
+ // GET /v2/model — list all models
260
+ compatRouter.get("/v2/model", (_req: Request, res: Response) => {
261
+ res.json({
262
+ models: [
263
+ { id: "claude-opus-4-5", provider: "anthropic", name: "Claude Opus 4.5", contextWindow: 200000 },
264
+ { id: "claude-sonnet-4-5", provider: "anthropic", name: "Claude Sonnet 4.5", contextWindow: 200000 },
265
+ { id: "gpt-4o", provider: "openai", name: "GPT-4o", contextWindow: 128000 },
266
+ { id: "gemini-2.0-flash", provider: "google", name: "Gemini 2.0 Flash", contextWindow: 1000000 },
267
+ ],
268
+ });
269
+ });
270
+
271
+ // ─── Config Routes ────────────────────────────────────────────────────────────
272
+
273
+ compatRouter.get("/v2/config", (_req: Request, res: Response) => {
274
+ res.json({
275
+ version: "1.0.0",
276
+ autoshare: false,
277
+ theme: "dark",
278
+ model: process.env.DEFAULT_MODEL || "claude-sonnet-4-5",
279
+ provider: process.env.DEFAULT_PROVIDER || "anthropic",
280
+ });
281
+ });
282
+
283
+ compatRouter.put("/v2/config", (req: Request, res: Response) => {
284
+ // Config updates are stored in the DB in production
285
+ res.json({ ok: true });
286
+ });
287
+
288
+ // ─── Health ───────────────────────────────────────────────────────────────────
289
+
290
+ compatRouter.get("/health", async (_req: Request, res: Response) => {
291
+ try {
292
+ await pool.query("SELECT 1");
293
+ res.json({ status: "ok", db: "connected" });
294
+ } catch {
295
+ res.status(503).json({ status: "error", db: "disconnected" });
296
+ }
297
+ });
298
+
299
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
300
+
301
+ async function getSessionInfo(session_id: string): Promise<Record<string, unknown> | null> {
302
+ const result = await pool.query(`SELECT * FROM sessions WHERE id = $1`, [session_id]);
303
+ if (!result.rows[0]) return null;
304
+ return toOpenCodeSession(result.rows[0]);
305
+ }
306
+
307
+ function toOpenCodeSession(row: any): Record<string, unknown> {
308
+ return {
309
+ id: row.id,
310
+ slug: row.slug,
311
+ projectID: row.project_id,
312
+ workspaceID: row.workspace_id,
313
+ parentID: row.parent_id,
314
+ directory: row.directory,
315
+ title: row.title,
316
+ version: row.version,
317
+ share: row.share_url ? { url: row.share_url } : undefined,
318
+ summary: row.summary_files ? {
319
+ additions: row.summary_additions,
320
+ deletions: row.summary_deletions,
321
+ files: row.summary_files,
322
+ } : undefined,
323
+ time: {
324
+ created: new Date(row.created_at).getTime(),
325
+ updated: new Date(row.updated_at).getTime(),
326
+ archived: row.state === "archived" ? new Date(row.updated_at).getTime() : undefined,
327
+ },
328
+ };
329
+ }
330
+
331
+ function toOpenCodeMessage(row: any): Record<string, unknown> {
332
+ return {
333
+ id: row.id,
334
+ sessionID: row.session_id,
335
+ role: row.role,
336
+ parts: (row.parts || []).map((p: any) => ({
337
+ id: p.id,
338
+ type: p.part_type,
339
+ ...p.data,
340
+ })),
341
+ time: { created: new Date(row.created_at).getTime() },
342
+ tokens: {
343
+ input: row.tokens_input,
344
+ output: row.tokens_output,
345
+ },
346
+ cost: row.cost_usd,
347
+ model: row.model_id,
348
+ provider: row.provider_id,
349
+ };
350
+ }
351
+
352
+ // ─── Agent Turn Orchestration ─────────────────────────────────────────────────
353
+
354
+ async function startAgentTurn(
355
+ session_id: string,
356
+ message_id: string,
357
+ modelID?: string,
358
+ providerID?: string
359
+ ): Promise<void> {
360
+ // Use the full BoneCode agent loop: multi-turn, compaction, retry, RAG, all OpenCode tools
361
+ const { runAgentLoop } = await import("../src/engine/session/prompt");
362
+
363
+ const result = await runAgentLoop({
364
+ session_id,
365
+ message_id,
366
+ content: "", // content already stored as a message part before this is called
367
+ model_id: modelID || process.env.DEFAULT_MODEL || "qwen3.6-35b-a3b-uncensored-heretic-apex",
368
+ provider_id: providerID || process.env.DEFAULT_PROVIDER || "openai_compatible",
369
+ });
370
+
371
+ if (!result.ok) {
372
+ throw new Error(result.error || "Agent loop failed");
373
+ }
374
+ }
375
+
376
+ // ─── Session Event Subscription ───────────────────────────────────────────────
377
+
378
+ function subscribeToSessionEvents(
379
+ session_id: string,
380
+ callback: (event: { type: string; data: unknown }) => void
381
+ ): () => void {
382
+ const handler = async (event: any) => {
383
+ if (event.payload?.session_id === session_id) {
384
+ callback({ type: mapEventType(event.type), data: event.payload });
385
+ }
386
+ };
387
+
388
+ const types = ["PartUpdated", "MessageAdded", "AgentCompleted", "AgentFailed", "ToolCallRequested"];
389
+ for (const type of types) {
390
+ eventBus.subscribe(type, handler);
391
+ }
392
+
393
+ // Return a real cleanup function that removes all registered handlers
394
+ return () => {
395
+ for (const type of types) {
396
+ eventBus.unsubscribe(type, handler);
397
+ }
398
+ };
399
+ }
400
+
401
+ function mapEventType(boneEventType: string): string {
402
+ const map: Record<string, string> = {
403
+ PartUpdated: "part.updated",
404
+ MessageAdded: "message.updated",
405
+ AgentCompleted: "session.updated",
406
+ AgentFailed: "session.updated",
407
+ ToolCallRequested: "tool.requested",
408
+ };
409
+ return map[boneEventType] || boneEventType.toLowerCase();
410
+ }