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,598 @@
1
+ /**
2
+ * BoneCode Context Builder
3
+ *
4
+ * Builds rich codebase context using structural strategies that work
5
+ * without any embedding model:
6
+ * 1. Postgres full-text search (BM25-ranked via ts_rank)
7
+ * 2. Git recency (recently changed files are more relevant)
8
+ * 3. Session history (files read/edited in this session)
9
+ * 4. Import graph expansion (pull in direct dependencies)
10
+ * 5. Instruction file injection (AGENTS.md / CLAUDE.md proximity)
11
+ *
12
+ * OPTIONAL UPGRADE — set EMBEDDING_PROVIDER in .env to enable hybrid search:
13
+ * When EMBEDDING_PROVIDER is set, vector similarity search is added on top
14
+ * of FTS using the bonecode_hybrid_search() stored function (RRF fusion).
15
+ * Without it, pure FTS + structural strategies run — still better than
16
+ * OpenCode's reactive grep approach.
17
+ *
18
+ * To enable embeddings, add to .env:
19
+ * EMBEDDING_PROVIDER=openai # or: ollama, voyage, openai_compatible
20
+ * EMBEDDING_MODEL=text-embedding-3-small
21
+ * EMBEDDING_API_KEY=sk-... # defaults to OPENAI_API_KEY
22
+ * EMBEDDING_BASE_URL= # for local/compatible endpoints
23
+ * EMBEDDING_DIMENSIONS=1536
24
+ */
25
+
26
+ import * as fs from "fs";
27
+ import * as path from "path";
28
+ import { pool } from "../bone/output/session/src/db";
29
+ import { logger } from "../bone/output/session/src/logger";
30
+
31
+ // ─── Types ────────────────────────────────────────────────────────────────────
32
+
33
+ export interface ContextChunk {
34
+ file_path: string;
35
+ content: string;
36
+ start_line: number;
37
+ end_line: number;
38
+ language?: string;
39
+ symbol_name?: string;
40
+ symbol_type?: string;
41
+ relevance_score: number;
42
+ source: "fts" | "vector" | "hybrid" | "import_graph" | "git_recency" | "session_history" | "instruction" | "entrypoint";
43
+ }
44
+
45
+ export interface ContextResult {
46
+ chunks: ContextChunk[];
47
+ instruction_files: string[];
48
+ summary: string;
49
+ }
50
+
51
+ export interface ContextOptions {
52
+ session_id: string;
53
+ project_id: string;
54
+ worktree: string;
55
+ query: string;
56
+ max_chunks?: number;
57
+ max_chars?: number;
58
+ }
59
+
60
+ // ─── Embedding availability check ────────────────────────────────────────────
61
+
62
+ export function embeddingsEnabled(): boolean {
63
+ return !!(process.env.EMBEDDING_PROVIDER && process.env.EMBEDDING_PROVIDER !== "none");
64
+ }
65
+
66
+ // ─── Main entry point ─────────────────────────────────────────────────────────
67
+
68
+ export async function buildContext(opts: ContextOptions): Promise<ContextResult> {
69
+ const {
70
+ session_id, project_id, worktree, query,
71
+ max_chunks = 12,
72
+ max_chars = 12_000,
73
+ } = opts;
74
+
75
+ const chunks: ContextChunk[] = [];
76
+ const seen = new Set<string>(); // deduplicate by file_path:start_line
77
+
78
+ // Run structural strategies in parallel (always active)
79
+ const [ftsChunks, gitChunks, sessionChunks, instructionFiles] = await Promise.all([
80
+ searchFTS(project_id, query, 20).catch(() => []),
81
+ getGitRecentFiles(worktree, query, 10).catch(() => []),
82
+ getSessionHistory(session_id, worktree, 8).catch(() => []),
83
+ findInstructionFiles(worktree, query).catch(() => []),
84
+ ]);
85
+
86
+ // Optional: vector search upgrade when EMBEDDING_PROVIDER is configured
87
+ // Replaces FTS with hybrid search (vector + FTS + RRF) for better recall
88
+ let vectorChunks: ContextChunk[] = [];
89
+ if (embeddingsEnabled() && query.trim()) {
90
+ vectorChunks = await searchVector(project_id, query, 20).catch((e) => {
91
+ logger.error("vector_search_failed", { event: "context", metadata: { error: e.message } });
92
+ return [];
93
+ });
94
+ }
95
+
96
+ // Merge: prefer vector/hybrid results over pure FTS when available
97
+ const primaryChunks = vectorChunks.length > 0 ? vectorChunks : ftsChunks;
98
+ for (const c of primaryChunks) {
99
+ const key = `${c.file_path}:${c.start_line}`;
100
+ if (!seen.has(key)) { seen.add(key); chunks.push(c); }
101
+ }
102
+
103
+ // Add git-recent files not already covered
104
+ for (const c of gitChunks) {
105
+ const key = `${c.file_path}:${c.start_line}`;
106
+ if (!seen.has(key)) { seen.add(key); chunks.push(c); }
107
+ }
108
+
109
+ // Add session history files
110
+ for (const c of sessionChunks) {
111
+ const key = `${c.file_path}:${c.start_line}`;
112
+ if (!seen.has(key)) { seen.add(key); chunks.push(c); }
113
+ }
114
+
115
+ // Expand top results via import graph
116
+ const topFiles = chunks.slice(0, 5).map(c => c.file_path);
117
+ const importChunks = await expandImportGraph(worktree, topFiles, seen, 6).catch(() => []);
118
+ for (const c of importChunks) {
119
+ const key = `${c.file_path}:${c.start_line}`;
120
+ if (!seen.has(key)) { seen.add(key); chunks.push(c); }
121
+ }
122
+
123
+ // Sort by relevance score descending
124
+ chunks.sort((a, b) => b.relevance_score - a.relevance_score);
125
+
126
+ // Trim to budget
127
+ const trimmed = trimToCharBudget(chunks.slice(0, max_chunks), max_chars);
128
+
129
+ const mode = embeddingsEnabled() && vectorChunks.length > 0 ? "hybrid" : "structural";
130
+ const sources = [...new Set(trimmed.map(c => c.source))].join(", ");
131
+ const summary = trimmed.length > 0
132
+ ? `${trimmed.length} chunks [${mode}] from ${[...new Set(trimmed.map(c => path.basename(c.file_path)))].slice(0, 5).join(", ")} (${sources})`
133
+ : "no relevant context found";
134
+
135
+ return { chunks: trimmed, instruction_files: instructionFiles, summary };
136
+ }
137
+
138
+ // ─── Strategy 2: Vector Search (optional — requires EMBEDDING_PROVIDER) ───────
139
+ // Uses the bonecode_hybrid_search() stored function (RRF: vector + FTS).
140
+ // Only called when EMBEDDING_PROVIDER is set in .env.
141
+
142
+ async function searchVector(project_id: string, query: string, limit: number): Promise<ContextChunk[]> {
143
+ if (!query.trim()) return [];
144
+
145
+ // Embed the query using the configured provider
146
+ const { embed_text } = await import("../bone/output/rag/src/extensions");
147
+ const model = process.env.EMBEDDING_MODEL || "text-embedding-nomic-embed-text-v1.5";
148
+ const queryEmbedding = await embed_text(query, model);
149
+ const embStr = "[" + queryEmbedding.join(",") + "]";
150
+
151
+ // Use the stored hybrid search function (RRF fusion of vector + FTS)
152
+ const result = await pool.query(`
153
+ SELECT
154
+ cf.file_path,
155
+ cc.content,
156
+ cc.start_line,
157
+ cc.end_line,
158
+ cc.language,
159
+ cc.symbol_name,
160
+ cc.symbol_type,
161
+ h.rrf_score,
162
+ h.vector_score,
163
+ h.text_score
164
+ FROM bonecode_hybrid_search($1, $2::vector, $3, NULL, NULL, $4) h
165
+ JOIN code_chunks cc ON cc.id = h.chunk_id
166
+ JOIN code_files cf ON cf.id = cc.code_file_id
167
+ JOIN knowledge_bases kb ON kb.id = cc.knowledge_base_id
168
+ WHERE kb.project_id = $5
169
+ ORDER BY h.rrf_score DESC
170
+ `, [
171
+ // knowledge_base_id — find the ready KB for this project
172
+ await getReadyKBId(project_id),
173
+ embStr,
174
+ query,
175
+ limit,
176
+ project_id,
177
+ ]);
178
+
179
+ return result.rows.map((row: any) => ({
180
+ file_path: row.file_path,
181
+ content: row.content,
182
+ start_line: Number(row.start_line),
183
+ end_line: Number(row.end_line),
184
+ language: row.language,
185
+ symbol_name: row.symbol_name,
186
+ symbol_type: row.symbol_type,
187
+ relevance_score: parseFloat(row.rrf_score) * 1000,
188
+ source: "hybrid" as const,
189
+ }));
190
+ }
191
+
192
+ async function getReadyKBId(project_id: string): Promise<string> {
193
+ const result = await pool.query(
194
+ `SELECT id FROM knowledge_bases WHERE project_id = $1 AND state = 'ready' ORDER BY updated_at DESC LIMIT 1`,
195
+ [project_id]
196
+ );
197
+ return result.rows[0]?.id || "";
198
+ }
199
+
200
+ // ─── Strategy 3: Postgres Full-Text Search ────────────────────────────────────
201
+ // Uses the tsvector index already on code_chunks.content.
202
+ // BM25-ranked via ts_rank — no embedding needed.
203
+
204
+ async function searchFTS(project_id: string, query: string, limit: number): Promise<ContextChunk[]> {
205
+ if (!query.trim()) return [];
206
+
207
+ // Extract meaningful terms — strip common words, keep identifiers
208
+ const terms = extractSearchTerms(query);
209
+ if (terms.length === 0) return [];
210
+
211
+ // Sanitize each term: keep only alphanumeric + underscore to prevent tsquery injection.
212
+ // Each term is passed as a separate $N parameter and assembled server-side via plainto_tsquery
213
+ // for the rank, and individual prefix-match queries ORed together for the filter.
214
+ const safeTsQuery = terms
215
+ .map(t => t.replace(/[^a-z0-9_]/g, ""))
216
+ .filter(t => t.length >= 2)
217
+ .map(t => `${t}:*`)
218
+ .join(" | ");
219
+
220
+ if (!safeTsQuery) return [];
221
+
222
+ const result = await pool.query(`
223
+ SELECT
224
+ cf.file_path,
225
+ cc.content,
226
+ cc.start_line,
227
+ cc.end_line,
228
+ cc.language,
229
+ cc.symbol_name,
230
+ cc.symbol_type,
231
+ ts_rank(
232
+ to_tsvector('english', cc.content),
233
+ to_tsquery('english', $2)
234
+ ) AS score
235
+ FROM code_chunks cc
236
+ JOIN code_files cf ON cf.id = cc.code_file_id
237
+ JOIN knowledge_bases kb ON kb.id = cc.knowledge_base_id
238
+ WHERE kb.project_id = $1
239
+ AND to_tsvector('english', cc.content) @@ to_tsquery('english', $2)
240
+ ORDER BY score DESC
241
+ LIMIT $3
242
+ `, [project_id, safeTsQuery, limit]);
243
+
244
+ return result.rows.map((row: any) => ({
245
+ file_path: row.file_path,
246
+ content: row.content,
247
+ start_line: Number(row.start_line),
248
+ end_line: Number(row.end_line),
249
+ language: row.language,
250
+ symbol_name: row.symbol_name,
251
+ symbol_type: row.symbol_type,
252
+ relevance_score: parseFloat(row.score) * 100,
253
+ source: "fts" as const,
254
+ }));
255
+ }
256
+
257
+ // ─── Strategy 2: Git Recency ──────────────────────────────────────────────────
258
+ // Files changed in recent commits are more likely to be relevant.
259
+ // Also filters by query terms appearing in the diff.
260
+
261
+ async function getGitRecentFiles(worktree: string, query: string, limit: number): Promise<ContextChunk[]> {
262
+ if (!fs.existsSync(path.join(worktree, ".git"))) return [];
263
+
264
+ const { execFile } = require("child_process");
265
+ const { promisify } = require("util");
266
+ const exec = promisify(execFile);
267
+
268
+ // Get files changed in last 20 commits
269
+ let changedFiles: string[] = [];
270
+ try {
271
+ const { stdout } = await exec("git", [
272
+ "log", "--name-only", "--pretty=format:", "-20", "--diff-filter=AM"
273
+ ], { cwd: worktree, timeout: 5000 });
274
+ changedFiles = stdout.split("\n")
275
+ .map((f: string) => f.trim())
276
+ .filter((f: string) => f && !f.startsWith("."))
277
+ .filter((f: string, i: number, arr: string[]) => arr.indexOf(f) === i) // deduplicate
278
+ .slice(0, 30);
279
+ } catch {
280
+ return [];
281
+ }
282
+
283
+ const terms = extractSearchTerms(query);
284
+ const chunks: ContextChunk[] = [];
285
+
286
+ for (const relPath of changedFiles.slice(0, limit * 2)) {
287
+ const fullPath = path.join(worktree, relPath);
288
+ if (!fs.existsSync(fullPath)) continue;
289
+
290
+ const ext = path.extname(relPath).toLowerCase();
291
+ const codeExts = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".go", ".rs", ".java", ".cs", ".cpp", ".c"]);
292
+ if (!codeExts.has(ext)) continue;
293
+
294
+ try {
295
+ const content = fs.readFileSync(fullPath, "utf-8");
296
+ const lines = content.split("\n");
297
+
298
+ // Score by how many query terms appear in the file
299
+ const contentLower = content.toLowerCase();
300
+ const termScore = terms.filter(t => contentLower.includes(t.toLowerCase())).length;
301
+ if (termScore === 0 && terms.length > 0) continue;
302
+
303
+ // Extract the most relevant section (around first term match)
304
+ const firstMatch = findFirstTermMatch(lines, terms);
305
+ const startLine = Math.max(0, firstMatch - 10);
306
+ const endLine = Math.min(lines.length - 1, firstMatch + 40);
307
+ const snippet = lines.slice(startLine, endLine + 1).join("\n");
308
+
309
+ chunks.push({
310
+ file_path: fullPath,
311
+ content: snippet,
312
+ start_line: startLine + 1,
313
+ end_line: endLine + 1,
314
+ language: extToLanguage(ext),
315
+ relevance_score: 30 + termScore * 10,
316
+ source: "git_recency",
317
+ });
318
+
319
+ if (chunks.length >= limit) break;
320
+ } catch { continue; }
321
+ }
322
+
323
+ return chunks;
324
+ }
325
+
326
+ // ─── Strategy 3: Session History ─────────────────────────────────────────────
327
+ // Files the agent has already read/edited in this session are highly relevant.
328
+
329
+ async function getSessionHistory(session_id: string, worktree: string, limit: number): Promise<ContextChunk[]> {
330
+ // Look at tool_calls in this session for read_file / edit_file / write_file
331
+ const result = await pool.query(`
332
+ SELECT DISTINCT
333
+ tc.tool_input->>'path' AS file_path,
334
+ tc.tool_name,
335
+ tc.created_at
336
+ FROM tool_calls tc
337
+ WHERE tc.session_id = $1
338
+ AND tc.tool_name IN ('read_file', 'edit_file', 'write_file', 'read', 'edit', 'write')
339
+ AND tc.tool_input->>'path' IS NOT NULL
340
+ AND tc.state = 'done'
341
+ ORDER BY tc.created_at DESC
342
+ LIMIT $2
343
+ `, [session_id, limit * 2]);
344
+
345
+ const chunks: ContextChunk[] = [];
346
+ const seen = new Set<string>();
347
+
348
+ for (const row of result.rows) {
349
+ let filePath = row.file_path as string;
350
+ if (!path.isAbsolute(filePath)) filePath = path.join(worktree, filePath);
351
+ if (seen.has(filePath) || !fs.existsSync(filePath)) continue;
352
+ seen.add(filePath);
353
+
354
+ try {
355
+ const content = fs.readFileSync(filePath, "utf-8");
356
+ const lines = content.split("\n");
357
+ // Take first 60 lines as context (usually the most important part)
358
+ const snippet = lines.slice(0, 60).join("\n");
359
+
360
+ chunks.push({
361
+ file_path: filePath,
362
+ content: snippet,
363
+ start_line: 1,
364
+ end_line: Math.min(60, lines.length),
365
+ language: extToLanguage(path.extname(filePath)),
366
+ relevance_score: 50, // high — agent already touched this file
367
+ source: "session_history",
368
+ });
369
+
370
+ if (chunks.length >= limit) break;
371
+ } catch { continue; }
372
+ }
373
+
374
+ return chunks;
375
+ }
376
+
377
+ // ─── Strategy 4: Import Graph Expansion ──────────────────────────────────────
378
+ // Given a set of relevant files, pull in their direct imports.
379
+ // This ensures the LLM has the types/interfaces/utilities the relevant code depends on.
380
+
381
+ async function expandImportGraph(
382
+ worktree: string,
383
+ seedFiles: string[],
384
+ seen: Set<string>,
385
+ limit: number
386
+ ): Promise<ContextChunk[]> {
387
+ const chunks: ContextChunk[] = [];
388
+ const toExpand = [...seedFiles];
389
+
390
+ for (const filePath of toExpand) {
391
+ if (chunks.length >= limit) break;
392
+ if (!fs.existsSync(filePath)) continue;
393
+
394
+ const imports = extractImports(filePath);
395
+ for (const importPath of imports) {
396
+ if (chunks.length >= limit) break;
397
+
398
+ const resolved = resolveImport(filePath, importPath, worktree);
399
+ if (!resolved || seen.has(`${resolved}:1`)) continue;
400
+
401
+ try {
402
+ const content = fs.readFileSync(resolved, "utf-8");
403
+ const lines = content.split("\n");
404
+ // For imported files, extract just the exports/public API (first 80 lines usually covers it)
405
+ const snippet = lines.slice(0, 80).join("\n");
406
+
407
+ seen.add(`${resolved}:1`);
408
+ chunks.push({
409
+ file_path: resolved,
410
+ content: snippet,
411
+ start_line: 1,
412
+ end_line: Math.min(80, lines.length),
413
+ language: extToLanguage(path.extname(resolved)),
414
+ relevance_score: 20, // lower — indirect dependency
415
+ source: "import_graph",
416
+ });
417
+ } catch { continue; }
418
+ }
419
+ }
420
+
421
+ return chunks;
422
+ }
423
+
424
+ // ─── Strategy 5: Instruction Files ───────────────────────────────────────────
425
+ // Find AGENTS.md, CLAUDE.md, OPENCODE.md near the worktree root.
426
+ // Same approach as OpenCode's instruction.ts.
427
+
428
+ async function findInstructionFiles(worktree: string, _query: string): Promise<string[]> {
429
+ const candidates = ["AGENTS.md", "CLAUDE.md", "OPENCODE.md", ".bonecode/instructions.md", "CONTEXT.md"];
430
+ const found: string[] = [];
431
+
432
+ // Check worktree root and one level down
433
+ const dirsToCheck = [worktree];
434
+ try {
435
+ const entries = fs.readdirSync(worktree, { withFileTypes: true });
436
+ for (const e of entries) {
437
+ if (e.isDirectory() && !e.name.startsWith(".") && e.name !== "node_modules") {
438
+ dirsToCheck.push(path.join(worktree, e.name));
439
+ }
440
+ }
441
+ } catch {}
442
+
443
+ for (const dir of dirsToCheck.slice(0, 5)) {
444
+ for (const name of candidates) {
445
+ const p = path.join(dir, name);
446
+ if (fs.existsSync(p)) {
447
+ found.push(p);
448
+ break; // one per directory
449
+ }
450
+ }
451
+ }
452
+
453
+ return found;
454
+ }
455
+
456
+ // ─── Format for LLM ───────────────────────────────────────────────────────────
457
+
458
+ export function formatContextForPrompt(result: ContextResult, worktree: string): string {
459
+ if (result.chunks.length === 0 && result.instruction_files.length === 0) return "";
460
+
461
+ const parts: string[] = [];
462
+
463
+ // Instruction files first (highest priority)
464
+ for (const instrPath of result.instruction_files) {
465
+ try {
466
+ const content = fs.readFileSync(instrPath, "utf-8").trim();
467
+ if (content) {
468
+ const rel = path.relative(worktree, instrPath);
469
+ parts.push(`<!-- Instructions from ${rel} -->\n${content}`);
470
+ }
471
+ } catch {}
472
+ }
473
+
474
+ // Code chunks
475
+ if (result.chunks.length > 0) {
476
+ parts.push("## Relevant Codebase Context\n");
477
+ for (let i = 0; i < result.chunks.length; i++) {
478
+ const c = result.chunks[i];
479
+ const rel = path.relative(worktree, c.file_path);
480
+ const header = c.symbol_name
481
+ ? `[${i + 1}] ${rel}:${c.start_line}-${c.end_line} (${c.symbol_type}: ${c.symbol_name})`
482
+ : `[${i + 1}] ${rel}:${c.start_line}-${c.end_line}`;
483
+ parts.push(`${header}\n\`\`\`${c.language || ""}\n${c.content.trim()}\n\`\`\``);
484
+ }
485
+ }
486
+
487
+ return parts.join("\n\n");
488
+ }
489
+
490
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
491
+
492
+ function extractSearchTerms(query: string): string[] {
493
+ // Extract meaningful identifiers and terms from the query
494
+ // Remove common English stop words, keep code identifiers
495
+ const stopWords = new Set([
496
+ "the", "a", "an", "is", "are", "was", "were", "be", "been", "being",
497
+ "have", "has", "had", "do", "does", "did", "will", "would", "could",
498
+ "should", "may", "might", "shall", "can", "need", "dare", "ought",
499
+ "used", "to", "of", "in", "for", "on", "with", "at", "by", "from",
500
+ "up", "about", "into", "through", "during", "before", "after",
501
+ "above", "below", "between", "out", "off", "over", "under",
502
+ "again", "further", "then", "once", "here", "there", "when",
503
+ "where", "why", "how", "all", "both", "each", "few", "more",
504
+ "most", "other", "some", "such", "no", "nor", "not", "only",
505
+ "own", "same", "so", "than", "too", "very", "just", "but",
506
+ "and", "or", "if", "as", "it", "its", "this", "that", "these",
507
+ "those", "i", "me", "my", "we", "our", "you", "your", "he", "she",
508
+ "him", "her", "they", "them", "what", "which", "who", "whom",
509
+ "implement", "create", "make", "build", "write", "add", "fix",
510
+ "update", "change", "modify", "use", "using", "get", "set",
511
+ "return", "returns", "function", "method", "class", "file",
512
+ "code", "please", "want", "need", "help", "show", "tell",
513
+ ]);
514
+
515
+ return query
516
+ .toLowerCase()
517
+ .replace(/[^\w\s]/g, " ")
518
+ .split(/\s+/)
519
+ .filter(t => t.length >= 3 && !stopWords.has(t))
520
+ .filter((t, i, arr) => arr.indexOf(t) === i) // deduplicate
521
+ .slice(0, 8); // max 8 terms for FTS query
522
+ }
523
+
524
+ function findFirstTermMatch(lines: string[], terms: string[]): number {
525
+ if (terms.length === 0) return 0;
526
+ for (let i = 0; i < lines.length; i++) {
527
+ const lower = lines[i].toLowerCase();
528
+ if (terms.some(t => lower.includes(t))) return i;
529
+ }
530
+ return 0;
531
+ }
532
+
533
+ function extToLanguage(ext: string): string {
534
+ const map: Record<string, string> = {
535
+ ".ts": "typescript", ".tsx": "typescript",
536
+ ".js": "javascript", ".jsx": "javascript", ".mjs": "javascript",
537
+ ".py": "python", ".go": "go", ".rs": "rust", ".java": "java",
538
+ ".cs": "csharp", ".cpp": "cpp", ".c": "c", ".rb": "ruby",
539
+ ".php": "php", ".swift": "swift", ".kt": "kotlin",
540
+ ".md": "markdown", ".json": "json", ".yaml": "yaml", ".toml": "toml",
541
+ ".sql": "sql", ".sh": "bash",
542
+ };
543
+ return map[ext.toLowerCase()] || "text";
544
+ }
545
+
546
+ function extractImports(filePath: string): string[] {
547
+ const ext = path.extname(filePath).toLowerCase();
548
+ const imports: string[] = [];
549
+
550
+ try {
551
+ const content = fs.readFileSync(filePath, "utf-8");
552
+
553
+ if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
554
+ // ES imports: import ... from "..."
555
+ const esImports = content.matchAll(/^import\s+.*?from\s+['"]([^'"]+)['"]/gm);
556
+ for (const m of esImports) imports.push(m[1]);
557
+ // require(): const x = require("...")
558
+ const requires = content.matchAll(/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g);
559
+ for (const m of requires) imports.push(m[1]);
560
+ } else if (ext === ".py") {
561
+ const pyImports = content.matchAll(/^(?:from\s+(\S+)\s+import|import\s+(\S+))/gm);
562
+ for (const m of pyImports) imports.push((m[1] || m[2]).replace(/\./g, "/"));
563
+ } else if (ext === ".go") {
564
+ const goImports = content.matchAll(/"([^"]+)"/g);
565
+ for (const m of goImports) if (m[1].includes("/")) imports.push(m[1].split("/").slice(-1)[0]);
566
+ }
567
+ } catch {}
568
+
569
+ // Only keep relative imports (not node_modules)
570
+ return imports.filter(i => i.startsWith(".") || i.startsWith("/"));
571
+ }
572
+
573
+ function resolveImport(fromFile: string, importPath: string, worktree: string): string | null {
574
+ const dir = path.dirname(fromFile);
575
+ const base = path.isAbsolute(importPath) ? importPath : path.resolve(dir, importPath);
576
+
577
+ // Try with various extensions
578
+ const exts = ["", ".ts", ".tsx", ".js", ".jsx", "/index.ts", "/index.js"];
579
+ for (const ext of exts) {
580
+ const candidate = base + ext;
581
+ if (fs.existsSync(candidate) && candidate.startsWith(worktree)) {
582
+ return candidate;
583
+ }
584
+ }
585
+ return null;
586
+ }
587
+
588
+ function trimToCharBudget(chunks: ContextChunk[], maxChars: number): ContextChunk[] {
589
+ const result: ContextChunk[] = [];
590
+ let total = 0;
591
+ for (const c of chunks) {
592
+ const size = c.content.length;
593
+ if (total + size > maxChars && result.length > 0) break;
594
+ result.push(c);
595
+ total += size;
596
+ }
597
+ return result;
598
+ }
@@ -0,0 +1,39 @@
1
+ import { sqliteTable, text, integer, primaryKey } from "drizzle-orm/sqlite-core"
2
+
3
+ import { type AccessToken, type AccountID, type OrgID, type RefreshToken } from "./schema"
4
+ import { Timestamps } from "../storage/schema.sql"
5
+
6
+ export const AccountTable = sqliteTable("account", {
7
+ id: text().$type<AccountID>().primaryKey(),
8
+ email: text().notNull(),
9
+ url: text().notNull(),
10
+ access_token: text().$type<AccessToken>().notNull(),
11
+ refresh_token: text().$type<RefreshToken>().notNull(),
12
+ token_expiry: integer(),
13
+ ...Timestamps,
14
+ })
15
+
16
+ export const AccountStateTable = sqliteTable("account_state", {
17
+ id: integer().primaryKey(),
18
+ active_account_id: text()
19
+ .$type<AccountID>()
20
+ .references(() => AccountTable.id, { onDelete: "set null" }),
21
+ active_org_id: text().$type<OrgID>(),
22
+ })
23
+
24
+ // LEGACY
25
+ export const ControlAccountTable = sqliteTable(
26
+ "control_account",
27
+ {
28
+ email: text().notNull(),
29
+ url: text().notNull(),
30
+ access_token: text().$type<AccessToken>().notNull(),
31
+ refresh_token: text().$type<RefreshToken>().notNull(),
32
+ token_expiry: integer(),
33
+ active: integer({ mode: "boolean" })
34
+ .notNull()
35
+ .$default(() => false),
36
+ ...Timestamps,
37
+ },
38
+ (table) => [primaryKey({ columns: [table.email, table.url] })],
39
+ )