@bevel-software/platform-core-backend 0.28.1 → 0.30.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 (274) hide show
  1. package/agent-guide/access-control.md +15 -0
  2. package/agent-guide/skills.md +8 -0
  3. package/dist/__tests__/test-repositories.d.ts +3 -0
  4. package/dist/__tests__/test-repositories.d.ts.map +1 -0
  5. package/dist/__tests__/test-repositories.js +18 -0
  6. package/dist/__tests__/test-repositories.js.map +1 -0
  7. package/dist/core/catalog-revision.d.ts.map +1 -1
  8. package/dist/core/catalog-revision.js +4 -2
  9. package/dist/core/catalog-revision.js.map +1 -1
  10. package/dist/core/compose-embed.d.ts +35 -0
  11. package/dist/core/compose-embed.d.ts.map +1 -0
  12. package/dist/core/compose-embed.js +14 -0
  13. package/dist/core/compose-embed.js.map +1 -0
  14. package/dist/core/core-ports.d.ts +10 -0
  15. package/dist/core/core-ports.d.ts.map +1 -1
  16. package/dist/core/core-ports.js.map +1 -1
  17. package/dist/core/create-core-server.d.ts.map +1 -1
  18. package/dist/core/create-core-server.js +8 -2
  19. package/dist/core/create-core-server.js.map +1 -1
  20. package/dist/core/create-core-services.d.ts +4 -1
  21. package/dist/core/create-core-services.d.ts.map +1 -1
  22. package/dist/core/create-core-services.js +57 -18
  23. package/dist/core/create-core-services.js.map +1 -1
  24. package/dist/core/lifecycle.d.ts +19 -6
  25. package/dist/core/lifecycle.d.ts.map +1 -1
  26. package/dist/core/lifecycle.js +17 -6
  27. package/dist/core/lifecycle.js.map +1 -1
  28. package/dist/modules/access/access-control.interface.d.ts +20 -0
  29. package/dist/modules/access/access-control.interface.d.ts.map +1 -1
  30. package/dist/modules/access/access-control.service.d.ts +68 -15
  31. package/dist/modules/access/access-control.service.d.ts.map +1 -1
  32. package/dist/modules/access/access-control.service.js +282 -58
  33. package/dist/modules/access/access-control.service.js.map +1 -1
  34. package/dist/modules/access/access.routes.d.ts.map +1 -1
  35. package/dist/modules/access/access.routes.js +20 -6
  36. package/dist/modules/access/access.routes.js.map +1 -1
  37. package/dist/modules/agent-instructions/shared-file-rules.d.ts +1 -1
  38. package/dist/modules/agent-instructions/shared-file-rules.js +1 -1
  39. package/dist/modules/auth/index.d.ts +15 -0
  40. package/dist/modules/auth/index.d.ts.map +1 -0
  41. package/dist/modules/auth/index.js +20 -0
  42. package/dist/modules/auth/index.js.map +1 -0
  43. package/dist/modules/diff/diff.service.d.ts.map +1 -1
  44. package/dist/modules/diff/diff.service.js +7 -1
  45. package/dist/modules/diff/diff.service.js.map +1 -1
  46. package/dist/modules/embed/embed.interface.d.ts +22 -0
  47. package/dist/modules/embed/embed.interface.d.ts.map +1 -1
  48. package/dist/modules/embed/embed.service.d.ts +28 -14
  49. package/dist/modules/embed/embed.service.d.ts.map +1 -1
  50. package/dist/modules/embed/embed.service.js +38 -17
  51. package/dist/modules/embed/embed.service.js.map +1 -1
  52. package/dist/modules/embed/embed.tools.d.ts.map +1 -1
  53. package/dist/modules/embed/embed.tools.js +10 -2
  54. package/dist/modules/embed/embed.tools.js.map +1 -1
  55. package/dist/modules/kb-fs/git-dir.d.ts +21 -0
  56. package/dist/modules/kb-fs/git-dir.d.ts.map +1 -0
  57. package/dist/modules/kb-fs/git-dir.js +58 -0
  58. package/dist/modules/kb-fs/git-dir.js.map +1 -0
  59. package/dist/modules/kb-fs/index.d.ts +9 -0
  60. package/dist/modules/kb-fs/index.d.ts.map +1 -0
  61. package/dist/modules/kb-fs/index.js +3 -0
  62. package/dist/modules/kb-fs/index.js.map +1 -0
  63. package/dist/modules/kb-fs/ref-files.d.ts +63 -0
  64. package/dist/modules/kb-fs/ref-files.d.ts.map +1 -0
  65. package/dist/modules/kb-fs/ref-files.js +249 -0
  66. package/dist/modules/kb-fs/ref-files.js.map +1 -0
  67. package/dist/modules/plugins/join-request-jobs.service.d.ts.map +1 -1
  68. package/dist/modules/plugins/join-request-jobs.service.js +43 -8
  69. package/dist/modules/plugins/join-request-jobs.service.js.map +1 -1
  70. package/dist/modules/plugins/teams.routes.d.ts +4 -0
  71. package/dist/modules/plugins/teams.routes.d.ts.map +1 -1
  72. package/dist/modules/plugins/teams.routes.js +9 -1
  73. package/dist/modules/plugins/teams.routes.js.map +1 -1
  74. package/dist/modules/skills/skills.contract.d.ts.map +1 -1
  75. package/dist/modules/skills/skills.tools.d.ts +8 -1
  76. package/dist/modules/skills/skills.tools.d.ts.map +1 -1
  77. package/dist/modules/skills/skills.tools.js +115 -11
  78. package/dist/modules/skills/skills.tools.js.map +1 -1
  79. package/dist/modules/tool-auth/internal-token.service.d.ts +1 -1
  80. package/dist/modules/tool-auth/tool-auth.middleware.d.ts +1 -2
  81. package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
  82. package/dist/modules/tool-auth/tool-auth.middleware.js +1 -2
  83. package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
  84. package/dist/modules/tool-helpers/default-branch-write.d.ts +69 -0
  85. package/dist/modules/tool-helpers/default-branch-write.d.ts.map +1 -0
  86. package/dist/modules/tool-helpers/default-branch-write.js +63 -0
  87. package/dist/modules/tool-helpers/default-branch-write.js.map +1 -0
  88. package/dist/modules/tool-helpers/index.d.ts +1 -0
  89. package/dist/modules/tool-helpers/index.d.ts.map +1 -1
  90. package/dist/modules/tool-helpers/index.js +1 -0
  91. package/dist/modules/tool-helpers/index.js.map +1 -1
  92. package/dist/modules/tool-helpers/tool-handler.d.ts +2 -2
  93. package/dist/modules/tool-helpers/tool.contract.d.ts +2 -2
  94. package/dist/modules/workflow/file-lock.service.d.ts +27 -5
  95. package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
  96. package/dist/modules/workflow/file-lock.service.js +70 -18
  97. package/dist/modules/workflow/file-lock.service.js.map +1 -1
  98. package/dist/modules/workflow/git/git.service.d.ts +42 -0
  99. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  100. package/dist/modules/workflow/git/git.service.js +201 -24
  101. package/dist/modules/workflow/git/git.service.js.map +1 -1
  102. package/dist/modules/workflow/index.d.ts +8 -0
  103. package/dist/modules/workflow/index.d.ts.map +1 -0
  104. package/dist/modules/workflow/index.js +8 -0
  105. package/dist/modules/workflow/index.js.map +1 -0
  106. package/dist/modules/workflow/pending-commits.service.d.ts +2 -17
  107. package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -1
  108. package/dist/modules/workflow/pending-commits.service.js +4 -24
  109. package/dist/modules/workflow/pending-commits.service.js.map +1 -1
  110. package/dist/modules/workflow/workflow-hooks.d.ts +1 -1
  111. package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
  112. package/dist/modules/workflow/workflow.routes.js +20 -1
  113. package/dist/modules/workflow/workflow.routes.js.map +1 -1
  114. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  115. package/dist/modules/workflow/workflow.service.js +5 -3
  116. package/dist/modules/workflow/workflow.service.js.map +1 -1
  117. package/dist/modules/workspace/agent-access.gate.d.ts +2 -2
  118. package/dist/modules/workspace/agent-access.gate.js +2 -2
  119. package/dist/modules/workspace/bounded-matcher.d.ts +79 -0
  120. package/dist/modules/workspace/bounded-matcher.d.ts.map +1 -0
  121. package/dist/modules/workspace/bounded-matcher.js +261 -0
  122. package/dist/modules/workspace/bounded-matcher.js.map +1 -0
  123. package/dist/modules/workspace/fetch-instant.d.ts +9 -0
  124. package/dist/modules/workspace/fetch-instant.d.ts.map +1 -0
  125. package/dist/modules/workspace/fetch-instant.js +13 -0
  126. package/dist/modules/workspace/fetch-instant.js.map +1 -0
  127. package/dist/modules/workspace/index.d.ts +17 -0
  128. package/dist/modules/workspace/index.d.ts.map +1 -0
  129. package/dist/modules/workspace/index.js +16 -0
  130. package/dist/modules/workspace/index.js.map +1 -0
  131. package/dist/modules/workspace/kb-repository.contract.d.ts +124 -0
  132. package/dist/modules/workspace/kb-repository.contract.d.ts.map +1 -0
  133. package/dist/modules/workspace/kb-repository.contract.js +19 -0
  134. package/dist/modules/workspace/kb-repository.contract.js.map +1 -0
  135. package/dist/modules/workspace/kb-repository.d.ts +236 -0
  136. package/dist/modules/workspace/kb-repository.d.ts.map +1 -0
  137. package/dist/modules/workspace/kb-repository.js +811 -0
  138. package/dist/modules/workspace/kb-repository.js.map +1 -0
  139. package/dist/modules/workspace/pattern-matcher.contract.d.ts +50 -0
  140. package/dist/modules/workspace/pattern-matcher.contract.d.ts.map +1 -0
  141. package/dist/modules/workspace/pattern-matcher.contract.js +27 -0
  142. package/dist/modules/workspace/pattern-matcher.contract.js.map +1 -0
  143. package/dist/modules/workspace/routine-write-policy.d.ts +0 -7
  144. package/dist/modules/workspace/routine-write-policy.d.ts.map +1 -1
  145. package/dist/modules/workspace/routine-write-policy.js +0 -5
  146. package/dist/modules/workspace/routine-write-policy.js.map +1 -1
  147. package/dist/modules/workspace/set-aside-clone.d.ts +40 -0
  148. package/dist/modules/workspace/set-aside-clone.d.ts.map +1 -1
  149. package/dist/modules/workspace/set-aside-clone.js +139 -0
  150. package/dist/modules/workspace/set-aside-clone.js.map +1 -1
  151. package/dist/modules/workspace/startup/kb-startup-runner.d.ts +99 -0
  152. package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
  153. package/dist/modules/workspace/startup/kb-startup-runner.js +407 -29
  154. package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
  155. package/dist/modules/workspace/workspace.service.d.ts +68 -32
  156. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  157. package/dist/modules/workspace/workspace.service.js +240 -161
  158. package/dist/modules/workspace/workspace.service.js.map +1 -1
  159. package/dist/modules/workspace/workspace.tools.d.ts +13 -4
  160. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  161. package/dist/modules/workspace/workspace.tools.js +268 -356
  162. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  163. package/dist/shared/workspace-id.d.ts +17 -0
  164. package/dist/shared/workspace-id.d.ts.map +1 -1
  165. package/dist/shared/workspace-id.js +24 -0
  166. package/dist/shared/workspace-id.js.map +1 -1
  167. package/dist/test-setup.js +4 -0
  168. package/dist/test-setup.js.map +1 -1
  169. package/mcp-app/page.html +142 -8
  170. package/package.json +3 -3
  171. package/src/__tests__/test-repositories.ts +22 -0
  172. package/src/__tests__/workspace-service.ts +69 -0
  173. package/src/core/__tests__/compose-embed.test.ts +65 -0
  174. package/src/core/__tests__/lifecycle.test.ts +45 -26
  175. package/src/core/catalog-revision.ts +4 -2
  176. package/src/core/compose-embed.ts +50 -0
  177. package/src/core/core-ports.ts +10 -0
  178. package/src/core/create-core-server.ts +8 -2
  179. package/src/core/create-core-services.ts +63 -24
  180. package/src/core/lifecycle.ts +34 -12
  181. package/src/modules/access/__tests__/access-control.atref-cache.test.ts +443 -25
  182. package/src/modules/access/__tests__/access-control.group-read.test.ts +73 -0
  183. package/src/modules/access/__tests__/access.routes.group-grant.test.ts +66 -0
  184. package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +2 -0
  185. package/src/modules/access/access-control.interface.ts +22 -0
  186. package/src/modules/access/access-control.service.ts +302 -58
  187. package/src/modules/access/access.routes.ts +22 -6
  188. package/src/modules/agent-instructions/shared-file-rules.ts +1 -1
  189. package/src/modules/auth/index.ts +29 -0
  190. package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +2 -1
  191. package/src/modules/diff/__tests__/diff.service.test.ts +2 -1
  192. package/src/modules/diff/__tests__/diff.service.worktree.test.ts +76 -0
  193. package/src/modules/diff/diff.service.ts +6 -4
  194. package/src/modules/embed/__tests__/embed.service.test.ts +76 -3
  195. package/src/modules/embed/__tests__/embed.tools.test.ts +29 -0
  196. package/src/modules/embed/embed.interface.ts +24 -0
  197. package/src/modules/embed/embed.service.ts +44 -19
  198. package/src/modules/embed/embed.tools.ts +10 -2
  199. package/src/modules/kb-fs/__tests__/git-dir.test.ts +77 -0
  200. package/src/modules/kb-fs/__tests__/ref-files.test.ts +338 -0
  201. package/src/modules/kb-fs/git-dir.ts +53 -0
  202. package/src/modules/kb-fs/index.ts +8 -0
  203. package/src/modules/kb-fs/ref-files.ts +279 -0
  204. package/src/modules/plugins/__tests__/join-request-jobs.service.test.ts +73 -6
  205. package/src/modules/plugins/__tests__/teams.routes.test.ts +55 -0
  206. package/src/modules/plugins/join-request-jobs.service.ts +45 -8
  207. package/src/modules/plugins/teams.routes.ts +14 -1
  208. package/src/modules/settings/__tests__/setup.routes.layout-phase.test.ts +2 -2
  209. package/src/modules/settings/__tests__/setup.routes.managed-phase.test.ts +2 -2
  210. package/src/modules/skills/__tests__/branch-skills.tools.test.ts +1 -1
  211. package/src/modules/skills/skills.contract.ts +4 -0
  212. package/src/modules/skills/skills.tools.ts +120 -10
  213. package/src/modules/tool-auth/internal-token.service.ts +1 -1
  214. package/src/modules/tool-auth/tool-auth.middleware.ts +1 -2
  215. package/src/modules/tool-helpers/__tests__/branch-declaration.test.ts +2 -2
  216. package/src/modules/tool-helpers/__tests__/can-write.tools.test.ts +581 -0
  217. package/src/modules/tool-helpers/default-branch-write.ts +90 -0
  218. package/src/modules/tool-helpers/index.ts +5 -0
  219. package/src/modules/tool-helpers/tool-handler.ts +2 -2
  220. package/src/modules/tool-helpers/tool.contract.ts +2 -2
  221. package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +42 -3
  222. package/src/modules/workflow/__tests__/fake-file-lock-db.ts +13 -2
  223. package/src/modules/workflow/__tests__/workflow.routes.lock-path.test.ts +168 -1
  224. package/src/modules/workflow/__tests__/workflow.service.delete-branch.test.ts +102 -6
  225. package/src/modules/workflow/file-lock.service.ts +79 -18
  226. package/src/modules/workflow/git/__tests__/git.service.changedPathsMemo.test.ts +175 -0
  227. package/src/modules/workflow/git/__tests__/git.service.readFileAtRef.test.ts +42 -0
  228. package/src/modules/workflow/git/__tests__/git.service.worktrees.test.ts +284 -0
  229. package/src/modules/workflow/git/git.service.ts +207 -22
  230. package/src/modules/workflow/index.ts +7 -0
  231. package/src/modules/workflow/pending-commits.service.ts +4 -23
  232. package/src/modules/workflow/workflow-hooks.ts +1 -1
  233. package/src/modules/workflow/workflow.routes.ts +24 -1
  234. package/src/modules/workflow/workflow.service.ts +3 -2
  235. package/src/modules/workspace/__tests__/agent-downloads.test.ts +2 -2
  236. package/src/modules/workspace/__tests__/bounded-matcher.test.ts +213 -0
  237. package/src/modules/workspace/__tests__/git-internals.security.test.ts +22 -7
  238. package/src/modules/workspace/__tests__/kb-repository.test.ts +481 -0
  239. package/src/modules/workspace/__tests__/rest-tool-arguments.test.ts +14 -0
  240. package/src/modules/workspace/__tests__/routine-write-policy.test.ts +0 -11
  241. package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +2 -2
  242. package/src/modules/workspace/__tests__/workspace.routes.folder-zip-access.test.ts +2 -2
  243. package/src/modules/workspace/__tests__/workspace.routes.folders.test.ts +4 -3
  244. package/src/modules/workspace/__tests__/workspace.service.any-workspace-credentials.test.ts +2 -2
  245. package/src/modules/workspace/__tests__/workspace.service.ensure-remotes-fetched.test.ts +2 -2
  246. package/src/modules/workspace/__tests__/workspace.service.forget-clone-races.test.ts +12 -5
  247. package/src/modules/workspace/__tests__/workspace.service.list-cloned.test.ts +6 -6
  248. package/src/modules/workspace/__tests__/workspace.service.move-never-overwrites.test.ts +2 -1
  249. package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +2 -1
  250. package/src/modules/workspace/__tests__/workspace.service.replaced-repository.test.ts +2 -1
  251. package/src/modules/workspace/__tests__/workspace.service.test.ts +24 -23
  252. package/src/modules/workspace/__tests__/workspace.service.unknown-branch.test.ts +2 -1
  253. package/src/modules/workspace/__tests__/workspace.service.worktrees.test.ts +620 -0
  254. package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +15 -1
  255. package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +71 -5
  256. package/src/modules/workspace/__tests__/workspace.tools.test.ts +174 -309
  257. package/src/modules/workspace/agent-access.gate.ts +2 -2
  258. package/src/modules/workspace/bounded-matcher.ts +328 -0
  259. package/src/modules/workspace/fetch-instant.ts +13 -0
  260. package/src/modules/workspace/index.ts +26 -0
  261. package/src/modules/workspace/kb-repository.contract.ts +124 -0
  262. package/src/modules/workspace/kb-repository.ts +844 -0
  263. package/src/modules/workspace/pattern-matcher.contract.ts +69 -0
  264. package/src/modules/workspace/routine-write-policy.ts +0 -15
  265. package/src/modules/workspace/set-aside-clone.ts +140 -0
  266. package/src/modules/workspace/startup/__tests__/kb-startup-runner.degraded.test.ts +3 -2
  267. package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +12 -10
  268. package/src/modules/workspace/startup/__tests__/kb-startup-runner.worktrees.test.ts +613 -0
  269. package/src/modules/workspace/startup/kb-startup-runner.ts +422 -29
  270. package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +4 -3
  271. package/src/modules/workspace/workspace.service.ts +247 -169
  272. package/src/modules/workspace/workspace.tools.ts +299 -385
  273. package/src/shared/workspace-id.ts +24 -0
  274. package/src/test-setup.ts +5 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded-matcher.d.ts","sourceRoot":"","sources":["../../../src/modules/workspace/bounded-matcher.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EAGpB,MAAM,+BAA+B,CAAC;AAEvC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,2BAA2B;IAC1C,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iGAAiG;IACjG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA4CD,qBAAa,oBAAqB,YAAW,eAAe;IAC1D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;gBAElB,IAAI,GAAE,2BAAgC;IAiBlD,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc;IAgB/C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B;;;;;OAKG;IACH,OAAO,CAAC,QAAQ;YAQF,OAAO;IAcrB,OAAO,CAAC,OAAO;IAQf,OAAO,CAAC,KAAK;CAcd"}
@@ -0,0 +1,261 @@
1
+ import { Worker } from 'node:worker_threads';
2
+ import { ToolError } from '../tool-helpers/tool.contract.js';
3
+ import { PatternTooExpensiveError, SearchBusyError, } from './pattern-matcher.contract.js';
4
+ /**
5
+ * Slack on top of the remaining budget before a batch is given up on: the
6
+ * budget counts only the worker's own matching time, so handing the lines over
7
+ * and the answer back must not be what trips it.
8
+ */
9
+ const TRANSFER_GRACE_MS = 250;
10
+ /** The worker: compiles the pattern it is handed and answers the indices of the lines it matches. */
11
+ const WORKER_SOURCE = `
12
+ const { parentPort } = require('node:worker_threads');
13
+ const { performance } = require('node:perf_hooks');
14
+ let cached = { key: null, re: null };
15
+ parentPort.on('message', ({ source, flags, lines, shared, limit }) => {
16
+ try {
17
+ // One line too long to post, written into shared memory as raw UTF-16 code units.
18
+ if (shared) lines = [Buffer.from(shared).toString('utf16le')];
19
+ const key = flags + '/' + source;
20
+ if (cached.key !== key) cached = { key, re: new RegExp(source, flags) };
21
+ const re = cached.re;
22
+ const started = performance.now();
23
+ const hits = [];
24
+ for (let i = 0; i < lines.length && hits.length < limit; i++) {
25
+ re.lastIndex = 0;
26
+ if (re.test(lines[i])) hits.push(i);
27
+ }
28
+ parentPort.postMessage({ hits, elapsed: performance.now() - started });
29
+ } catch (err) {
30
+ parentPort.postMessage({ error: String(err && err.message ? err.message : err) });
31
+ }
32
+ });
33
+ `;
34
+ export class WorkerPatternMatcher {
35
+ budgetMs;
36
+ poolMax;
37
+ maxWaiting;
38
+ maxPatternLength;
39
+ batchChars;
40
+ batchLines;
41
+ idle = [];
42
+ all = new Set();
43
+ waiting = [];
44
+ closed = false;
45
+ lease;
46
+ constructor(opts = {}) {
47
+ this.budgetMs = option('budgetMs', opts.budgetMs ?? 5_000, 1, MAX_TIMER_MS - TRANSFER_GRACE_MS);
48
+ // A pool of none would leave every search waiting for a worker that never comes.
49
+ this.poolMax = option('poolMax', opts.poolMax ?? 4, 1);
50
+ // No queue at all is allowed: every search past the pool is refused busy.
51
+ this.maxWaiting = option('maxWaiting', opts.maxWaiting ?? 16, 0);
52
+ this.maxPatternLength = option('maxPatternLength', opts.maxPatternLength ?? 1_000, 1);
53
+ this.batchChars = option('batchChars', opts.batchChars ?? 1_000_000, 1);
54
+ this.batchLines = option('batchLines', opts.batchLines ?? 10_000, 1);
55
+ this.lease = {
56
+ acquire: () => this.acquire(),
57
+ release: (w) => this.release(w),
58
+ batchEnd: (lines, from) => this.batchEnd(lines, from),
59
+ batchChars: this.batchChars,
60
+ };
61
+ }
62
+ search(source, flags) {
63
+ if (source.length > this.maxPatternLength) {
64
+ throw new ToolError(`Pattern too long: ${source.length} characters, and a search pattern may have at most ${this.maxPatternLength}.`, 400, { code: 'pattern_too_long' });
65
+ }
66
+ try {
67
+ new RegExp(source, flags);
68
+ }
69
+ catch (err) {
70
+ throw new ToolError(`Invalid regex: ${err.message}`, 400);
71
+ }
72
+ return new BoundedSearch(this.lease, source, flags, this.budgetMs);
73
+ }
74
+ async close() {
75
+ this.closed = true;
76
+ for (const waiter of this.waiting.splice(0))
77
+ waiter.reject(new SearchBusyError());
78
+ const workers = [...this.all];
79
+ this.idle.length = 0;
80
+ await Promise.all(workers.map((w) => w.terminate()));
81
+ }
82
+ /**
83
+ * Where the batch starting at `from` ends: about `batchChars` characters on,
84
+ * at most `batchLines` lines on, and never empty. A batch of one line past
85
+ * `batchChars` is handed over through shared memory instead (see
86
+ * {@link BoundedSearch.matchBatch}).
87
+ */
88
+ batchEnd(lines, from) {
89
+ let to = from;
90
+ let chars = 0;
91
+ const last = Math.min(lines.length, from + this.batchLines);
92
+ while (to < last && (to === from || chars + lines[to].length <= this.batchChars))
93
+ chars += lines[to++].length;
94
+ return to;
95
+ }
96
+ async acquire() {
97
+ if (this.closed)
98
+ throw new SearchBusyError();
99
+ if (this.idle.length === 0 && this.all.size >= this.poolMax && this.waiting.length >= this.maxWaiting) {
100
+ throw new SearchBusyError();
101
+ }
102
+ const w = this.idle.pop() ??
103
+ (this.all.size < this.poolMax
104
+ ? this.spawn()
105
+ : await new Promise((resolve, reject) => this.waiting.push({ resolve, reject })));
106
+ w.ref();
107
+ return w;
108
+ }
109
+ release(w) {
110
+ const next = this.waiting.shift();
111
+ if (next)
112
+ return next.resolve(w);
113
+ // An idle worker must not hold a process's exit open.
114
+ w.unref();
115
+ this.idle.push(w);
116
+ }
117
+ spawn() {
118
+ const w = new Worker(WORKER_SOURCE, { eval: true });
119
+ this.all.add(w);
120
+ // A worker that dies — terminated over budget, or out of memory — leaves the pool.
121
+ w.once('exit', () => {
122
+ this.all.delete(w);
123
+ const at = this.idle.indexOf(w);
124
+ if (at >= 0)
125
+ this.idle.splice(at, 1);
126
+ if (this.closed)
127
+ return;
128
+ const next = this.waiting.shift();
129
+ if (next)
130
+ next.resolve(this.spawn());
131
+ });
132
+ return w;
133
+ }
134
+ }
135
+ /** One search: a caller's pattern, matched off the event loop under one budget. */
136
+ class BoundedSearch {
137
+ pool;
138
+ source;
139
+ flags;
140
+ budgetMs;
141
+ spentMs = 0;
142
+ constructor(pool, source, flags, budgetMs) {
143
+ this.pool = pool;
144
+ this.source = source;
145
+ this.flags = flags;
146
+ this.budgetMs = budgetMs;
147
+ }
148
+ async matchingLines(lines, limit) {
149
+ if (limit <= 0 || lines.length === 0)
150
+ return [];
151
+ if (this.spentMs >= this.budgetMs)
152
+ throw new PatternTooExpensiveError(this.source, this.budgetMs);
153
+ const w = await this.pool.acquire();
154
+ const hits = [];
155
+ try {
156
+ for (let from = 0; from < lines.length && hits.length < limit;) {
157
+ const to = this.pool.batchEnd(lines, from);
158
+ for (const i of await this.matchBatch(w, lines.slice(from, to), limit - hits.length))
159
+ hits.push(from + i);
160
+ from = to;
161
+ }
162
+ }
163
+ catch (err) {
164
+ // Terminating is what stops a regex mid-backtrack; the pool replaces it.
165
+ void w.terminate();
166
+ throw err;
167
+ }
168
+ this.pool.release(w);
169
+ return hits;
170
+ }
171
+ /**
172
+ * One handoff to the worker, charged to this search's budget. No handoff
173
+ * copies more than `batchChars` characters on the request thread at once: a
174
+ * line longer than that goes over in shared memory, not in the message.
175
+ */
176
+ async matchBatch(w, lines, limit) {
177
+ if (this.spentMs >= this.budgetMs)
178
+ throw new PatternTooExpensiveError(this.source, this.budgetMs);
179
+ const oversized = lines.length === 1 && lines[0].length > this.pool.batchChars;
180
+ const payload = oversized ? { shared: await shareLine(w, lines[0], this.pool.batchChars) } : { lines };
181
+ const remaining = this.budgetMs - this.spentMs;
182
+ const reply = await run(w, { source: this.source, flags: this.flags, ...payload, limit }, remaining + TRANSFER_GRACE_MS);
183
+ if (reply === 'timeout') {
184
+ this.spentMs = this.budgetMs;
185
+ throw new PatternTooExpensiveError(this.source, this.budgetMs);
186
+ }
187
+ if ('error' in reply)
188
+ throw new ToolError(`Invalid regex: ${reply.error}`, 400);
189
+ this.spentMs += reply.elapsed;
190
+ if (this.spentMs > this.budgetMs)
191
+ throw new PatternTooExpensiveError(this.source, this.budgetMs);
192
+ return reply.hits;
193
+ }
194
+ }
195
+ /**
196
+ * A line as raw UTF-16 code units in shared memory, which a message hands the
197
+ * worker without copying. It is written `chunkChars` at a time with a turn of
198
+ * the event loop between, so a line of any length never holds the request
199
+ * thread for longer than one chunk. Raw code units keep the line exact, lone
200
+ * surrogates included.
201
+ *
202
+ * The worker it is meant for can be terminated by `close()` during those turns,
203
+ * before {@link run} listens for its exit; a message posted to it then would
204
+ * never be answered. So its exit is watched here too: writing stops and the
205
+ * search is answered busy, as one terminated under `run` is.
206
+ */
207
+ async function shareLine(w, line, chunkChars) {
208
+ let exited = false;
209
+ const onExit = () => {
210
+ exited = true;
211
+ };
212
+ w.once('exit', onExit);
213
+ try {
214
+ const shared = new SharedArrayBuffer(line.length * 2);
215
+ const bytes = Buffer.from(shared);
216
+ for (let at = 0; at < line.length && !exited; at += chunkChars) {
217
+ if (at > 0)
218
+ await new Promise((resolve) => setImmediate(resolve));
219
+ bytes.write(line.slice(at, at + chunkChars), at * 2, 'utf16le');
220
+ }
221
+ if (exited)
222
+ throw new SearchBusyError();
223
+ return shared;
224
+ }
225
+ finally {
226
+ w.off('exit', onExit);
227
+ }
228
+ }
229
+ function run(w, message, timeoutMs) {
230
+ return new Promise((resolve, reject) => {
231
+ const settle = (fn) => {
232
+ clearTimeout(timer);
233
+ w.off('message', onMessage);
234
+ w.off('error', onError);
235
+ w.off('exit', onExit);
236
+ fn();
237
+ };
238
+ const onMessage = (reply) => settle(() => resolve(reply));
239
+ const onError = (err) => settle(() => reject(err));
240
+ // Terminated under the search by `close()`: answered as busy, not left hanging until the timer.
241
+ const onExit = () => settle(() => reject(new SearchBusyError()));
242
+ const timer = setTimeout(() => settle(() => resolve('timeout')), timeoutMs);
243
+ w.on('message', onMessage);
244
+ w.on('error', onError);
245
+ w.on('exit', onExit);
246
+ w.postMessage(message);
247
+ });
248
+ }
249
+ /**
250
+ * The longest delay `setTimeout` honours. A longer one fires after 1 ms, so a
251
+ * budget past this (less the grace added to it) would stop every search at once.
252
+ */
253
+ const MAX_TIMER_MS = 2_147_483_647;
254
+ /** A sizing option as given, refused at construction unless it is an integer from `min` to `max`. */
255
+ function option(name, value, min, max = Number.MAX_SAFE_INTEGER) {
256
+ if (!Number.isInteger(value) || value < min || value > max) {
257
+ throw new RangeError(`WorkerPatternMatcher: ${name} must be an integer from ${min} to ${max}, got ${value}.`);
258
+ }
259
+ return value;
260
+ }
261
+ //# sourceMappingURL=bounded-matcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded-matcher.js","sourceRoot":"","sources":["../../../src/modules/workspace/bounded-matcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAC7D,OAAO,EAGL,wBAAwB,EACxB,eAAe,GAChB,MAAM,+BAA+B,CAAC;AAsDvC;;;;GAIG;AACH,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B,qGAAqG;AACrG,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;CAsBrB,CAAC;AAYF,MAAM,OAAO,oBAAoB;IACd,QAAQ,CAAS;IACjB,OAAO,CAAS;IAChB,UAAU,CAAS;IACnB,gBAAgB,CAAS;IACzB,UAAU,CAAS;IACnB,UAAU,CAAS;IACnB,IAAI,GAAa,EAAE,CAAC;IACpB,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IACxB,OAAO,GAAa,EAAE,CAAC;IAChC,MAAM,GAAG,KAAK,CAAC;IACN,KAAK,CAAQ;IAE9B,YAAY,OAAoC,EAAE;QAChD,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK,EAAE,CAAC,EAAE,YAAY,GAAG,iBAAiB,CAAC,CAAC;QAChG,iFAAiF;QACjF,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACvD,0EAA0E;QAC1E,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,kBAAkB,EAAE,IAAI,CAAC,gBAAgB,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC;QACtF,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC;QACxE,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC;QACrE,IAAI,CAAC,KAAK,GAAG;YACX,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE;YAC7B,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;YACrD,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,MAAc,EAAE,KAAa;QAClC,IAAI,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1C,MAAM,IAAI,SAAS,CACjB,qBAAqB,MAAM,CAAC,MAAM,sDAAsD,IAAI,CAAC,gBAAgB,GAAG,EAChH,GAAG,EACH,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAC7B,CAAC;QACJ,CAAC;QACD,IAAI,CAAC;YACH,IAAI,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,SAAS,CAAC,kBAAmB,GAAa,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YAAE,MAAM,CAAC,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC;QAClF,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QACrB,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IACvD,CAAC;IAED;;;;;OAKG;IACK,QAAQ,CAAC,KAAe,EAAE,IAAY;QAC5C,IAAI,EAAE,GAAG,IAAI,CAAC;QACd,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5D,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI,IAAI,KAAK,GAAG,KAAK,CAAC,EAAE,CAAE,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC;YAAE,KAAK,IAAI,KAAK,CAAC,EAAE,EAAE,CAAE,CAAC,MAAM,CAAC;QAChH,OAAO,EAAE,CAAC;IACZ,CAAC;IAEO,KAAK,CAAC,OAAO;QACnB,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,eAAe,EAAE,CAAC;QAC7C,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACtG,MAAM,IAAI,eAAe,EAAE,CAAC;QAC9B,CAAC;QACD,MAAM,CAAC,GACL,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YACf,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO;gBAC3B,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE;gBACd,CAAC,CAAC,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9F,CAAC,CAAC,GAAG,EAAE,CAAC;QACR,OAAO,CAAC,CAAC;IACX,CAAC;IAEO,OAAO,CAAC,CAAS;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAClC,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACjC,sDAAsD;QACtD,CAAC,CAAC,KAAK,EAAE,CAAC;QACV,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAEO,KAAK;QACX,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChB,mFAAmF;QACnF,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;YAClB,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACnB,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAChC,IAAI,EAAE,IAAI,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;YACrC,IAAI,IAAI,CAAC,MAAM;gBAAE,OAAO;YACxB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAClC,IAAI,IAAI;gBAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,CAAC;IACX,CAAC;CACF;AAED,mFAAmF;AACnF,MAAM,aAAa;IAIE;IACA;IACA;IACA;IANX,OAAO,GAAG,CAAC,CAAC;IAEpB,YACmB,IAAW,EACX,MAAc,EACd,KAAa,EACb,QAAgB;QAHhB,SAAI,GAAJ,IAAI,CAAO;QACX,WAAM,GAAN,MAAM,CAAQ;QACd,UAAK,GAAL,KAAK,CAAQ;QACb,aAAQ,GAAR,QAAQ,CAAQ;IAChC,CAAC;IAEJ,KAAK,CAAC,aAAa,CAAC,KAAe,EAAE,KAAa;QAChD,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAChD,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,wBAAwB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClG,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACpC,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,GAAG,KAAK,GAAI,CAAC;gBAChE,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBAC3C,KAAK,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;oBAAE,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;gBAC1G,IAAI,GAAG,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,yEAAyE;YACzE,KAAK,CAAC,CAAC,SAAS,EAAE,CAAC;YACnB,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,UAAU,CAAC,CAAS,EAAE,KAAe,EAAE,KAAa;QAChE,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,wBAAwB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClG,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;QAChF,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAE,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;QACxG,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;QAC/C,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,EAAE,SAAS,GAAG,iBAAiB,CAAC,CAAC;QACzH,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC7B,MAAM,IAAI,wBAAwB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,OAAO,IAAI,KAAK;YAAE,MAAM,IAAI,SAAS,CAAC,kBAAkB,KAAK,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;QAChF,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC;QAC9B,IAAI,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,wBAAwB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjG,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;CACF;AAED;;;;;;;;;;;GAWG;AACH,KAAK,UAAU,SAAS,CAAC,CAAS,EAAE,IAAY,EAAE,UAAkB;IAClE,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,MAAM,MAAM,GAAG,GAAG,EAAE;QAClB,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC,CAAC;IACF,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACtD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,UAAU,EAAE,CAAC;YAC/D,IAAI,EAAE,GAAG,CAAC;gBAAE,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;YACxE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,GAAG,UAAU,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC;QAClE,CAAC;QACD,IAAI,MAAM;YAAE,MAAM,IAAI,eAAe,EAAE,CAAC;QACxC,OAAO,MAAM,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED,SAAS,GAAG,CAAC,CAAS,EAAE,OAAe,EAAE,SAAiB;IACxD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,CAAC,EAAc,EAAE,EAAE;YAChC,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YAC5B,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACxB,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACtB,EAAE,EAAE,CAAC;QACP,CAAC,CAAC;QACF,MAAM,SAAS,GAAG,CAAC,KAAY,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACjE,MAAM,OAAO,GAAG,CAAC,GAAU,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,gGAAgG;QAChG,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC,CAAC;QACjE,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QAC5E,CAAC,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC3B,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACvB,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrB,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,YAAY,GAAG,aAAa,CAAC;AAEnC,qGAAqG;AACrG,SAAS,MAAM,CAAC,IAAY,EAAE,KAAa,EAAE,GAAW,EAAE,GAAG,GAAG,MAAM,CAAC,gBAAgB;IACrF,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,GAAG,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;QAC3D,MAAM,IAAI,UAAU,CAAC,yBAAyB,IAAI,4BAA4B,GAAG,OAAO,GAAG,SAAS,KAAK,GAAG,CAAC,CAAC;IAChH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * An instant on the one clock that fetch starts and `fetchedSince` instants
3
+ * are read from. Milliseconds, like `Date.now()`, but strictly increasing in
4
+ * call order: two readings never compare equal, so a fetch started in the
5
+ * same millisecond as a listing is still ordered before or after it, and
6
+ * "started after the instant" is a strict comparison that cannot be a tie.
7
+ */
8
+ export declare function fetchInstant(): number;
9
+ //# sourceMappingURL=fetch-instant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-instant.d.ts","sourceRoot":"","sources":["../../../src/modules/workspace/fetch-instant.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAGrC"}
@@ -0,0 +1,13 @@
1
+ let last = 0;
2
+ /**
3
+ * An instant on the one clock that fetch starts and `fetchedSince` instants
4
+ * are read from. Milliseconds, like `Date.now()`, but strictly increasing in
5
+ * call order: two readings never compare equal, so a fetch started in the
6
+ * same millisecond as a listing is still ordered before or after it, and
7
+ * "started after the instant" is a strict comparison that cannot be a tie.
8
+ */
9
+ export function fetchInstant() {
10
+ last = Math.max(Date.now(), last + 0.001);
11
+ return last;
12
+ }
13
+ //# sourceMappingURL=fetch-instant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-instant.js","sourceRoot":"","sources":["../../../src/modules/workspace/fetch-instant.ts"],"names":[],"mappings":"AAAA,IAAI,IAAI,GAAG,CAAC,CAAC;AAEb;;;;;;GAMG;AACH,MAAM,UAAU,YAAY;IAC1B,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * What the workspace module offers the other modules: how a file's bytes are
3
+ * read and told apart — the reader registry `read_file` dispatches on, and
4
+ * the raw content type a file is served with — so a module that serves a
5
+ * file answers exactly as a read of it would. The services are wired by the
6
+ * composition root.
7
+ */
8
+ export { FileReaderRegistry, type FileKind, type FileReader, type ReadResult, } from './file-readers/file-reader.js';
9
+ export { OCTET_STREAM, rawExtensionOf, rawMimeFor } from './file-readers/raw-mime.js';
10
+ /**
11
+ * The knowledge base's one repository, every branch workspace a worktree of
12
+ * it. (Where a checkout's git directory is — its `.git` folder, or the
13
+ * folder its `.git` FILE names — is `kb-fs/git-dir.ts`.)
14
+ */
15
+ export { KbRepository, repositoryDirFor, workingCopyShape, type WorkingCopyShape, } from './kb-repository.js';
16
+ export type { AddWorktreeOptions, FetchOptions, IKbRepository } from './kb-repository.contract.js';
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/workspace/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,kBAAkB,EAClB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,UAAU,GAChB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACtF;;;;GAIG;AACH,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * What the workspace module offers the other modules: how a file's bytes are
3
+ * read and told apart — the reader registry `read_file` dispatches on, and
4
+ * the raw content type a file is served with — so a module that serves a
5
+ * file answers exactly as a read of it would. The services are wired by the
6
+ * composition root.
7
+ */
8
+ export { FileReaderRegistry, } from './file-readers/file-reader.js';
9
+ export { OCTET_STREAM, rawExtensionOf, rawMimeFor } from './file-readers/raw-mime.js';
10
+ /**
11
+ * The knowledge base's one repository, every branch workspace a worktree of
12
+ * it. (Where a checkout's git directory is — its `.git` folder, or the
13
+ * folder its `.git` FILE names — is `kb-fs/git-dir.ts`.)
14
+ */
15
+ export { KbRepository, repositoryDirFor, workingCopyShape, } from './kb-repository.js';
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/workspace/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,kBAAkB,GAInB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACtF;;;;GAIG;AACH,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,GAEjB,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * The knowledge base's one repository, every branch workspace a worktree of
3
+ * it — the contract its consumers (the workspace service, the KB startup
4
+ * phase, the set-aside of a moved repository, the git layer) depend on.
5
+ * `KbRepository` (`kb-repository.ts`) is the implementation, a bare
6
+ * repository driven by the git CLI; the composition root makes ONE and
7
+ * injects it everywhere, so that one fetch serves every workspace and the
8
+ * repository's administration — its creation, the writes to its one config
9
+ * file, its worktree list, a set-aside — is serialized in one place.
10
+ *
11
+ * Nothing else is serialized by the application: git was built for many
12
+ * worktrees of one repository, and protects the refs, `packed-refs` and the
13
+ * object store with its own locks. The worktree list (`worktrees/`) it does
14
+ * not lock, which is why adding, removing and pruning worktrees are
15
+ * administration here. Two worktrees run side by side, as two developers'
16
+ * worktrees of one repository do.
17
+ */
18
+ export interface FetchOptions {
19
+ /** A fetch that SUCCEEDED this recently is fresh enough; nothing runs. */
20
+ maxAgeMs: number;
21
+ /**
22
+ * An instant (`fetchInstant()`): a success counts as fresh only when
23
+ * its fetch started after it, however young it is (a fetch from before a listing may lack
24
+ * what the listing saw). A fetch in flight that started before it is
25
+ * waited for, not joined, and a fresh one runs.
26
+ */
27
+ fetchedSince?: number;
28
+ /** Skip the freshness window (the in-flight join still applies). */
29
+ force?: boolean;
30
+ /**
31
+ * A fetch that FAILED this recently is not retried: the answer is the
32
+ * failure. For pollers, so a host that is down is not asked again on every
33
+ * request. Absent, a failure is retried on the next call.
34
+ */
35
+ failureBackoffMs?: number;
36
+ }
37
+ export interface AddWorktreeOptions {
38
+ /** A converted clone whose branch was never pushed: its local ref is enough. */
39
+ allowLocalOnly?: boolean;
40
+ /** A conversion: a local ref behind the remote stays where it is. */
41
+ keepLocalTip?: boolean;
42
+ /**
43
+ * Reuse the repository's own fetch when it started after this instant
44
+ * (`fetchInstant()`)
45
+ * and knows the branch. An instant, not an age: it is compared inside the
46
+ * reservation, so time spent waiting for it cannot age a fetch out.
47
+ */
48
+ fetchedSince?: number;
49
+ }
50
+ export interface IKbRepository {
51
+ /** The bare repository's folder. */
52
+ readonly dir: string;
53
+ /**
54
+ * Run `fn` as the repository's one administrator for its duration: no
55
+ * creation of the repository, no write to its one config file (git refuses
56
+ * a second writer of it rather than waiting), no change to its worktree
57
+ * list (which git does not lock: a prune beside a `worktree add` can take
58
+ * the entry being made), and no set-aside runs beside it. Git operations
59
+ * in the worktrees are not held back — git's own locks cover them — so a
60
+ * caller that moves the repository's folders holds those off itself (the
61
+ * startup phase runs before anything is served; the workspace service
62
+ * wraps a set-aside in what surrounds one). Never nested: `fn` must not
63
+ * call `exclusive` again, nor a method that does (`ensure`,
64
+ * `refreshCredentials`, `writeConfig`, `addWorktree`, `removeWorktree`,
65
+ * `forgetWorktrees`, `prune`, `setOriginUrl`).
66
+ */
67
+ exclusive<T>(fn: () => Promise<T>): Promise<T>;
68
+ /** Whether the repository is on disk and finished (its first fetch landed). */
69
+ exists(): Promise<boolean>;
70
+ /** Create the repository and fetch it once when it is not there. Throws with git's words, redacted. */
71
+ ensure(): Promise<void>;
72
+ /** Re-stamp the credential helper when the deployment's credential changed. */
73
+ refreshCredentials(): Promise<void>;
74
+ /** Run `git config` writes against the shared configuration, one writer at a time. */
75
+ writeConfig(cwd: string, argLists: readonly string[][]): Promise<void>;
76
+ /**
77
+ * Garbage-collect the repository when git finds it worth it (`gc --auto`
78
+ * with git's default thresholds). Automatic collection is off on the
79
+ * repository — a commit in one worktree would otherwise collect beside
80
+ * every other worktree's work — so the startup phase runs this once, when
81
+ * nothing else does. Never throws.
82
+ */
83
+ maintain(): Promise<void>;
84
+ /** The last time the repository reached the remote and whether it worked; null before any attempt. */
85
+ lastContact(): {
86
+ at: number;
87
+ ok: boolean;
88
+ } | null;
89
+ /** Why the last fetch failed, redacted; null when it did not. */
90
+ lastFetchFailure(): string | null;
91
+ /**
92
+ * `git fetch --prune origin`, once for every workspace: throttled, and
93
+ * joined while in flight. Answers whether the remote-tracking refs are
94
+ * provably fresh. Never throws.
95
+ */
96
+ fetch(opts: FetchOptions): Promise<boolean>;
97
+ /** Forget what this process knows of the repository (it was set aside). */
98
+ forget(): void;
99
+ /** Add the worktree of `branch` at `checkoutDir`, copying no history. */
100
+ addWorktree(branch: string, checkoutDir: string, opts?: AddWorktreeOptions): Promise<void>;
101
+ /** Remove and prune the worktree at `checkoutDir`, with its branch's local ref; nothing else. */
102
+ removeWorktree(checkoutDir: string, branch: string): Promise<void>;
103
+ /** Prune worktrees whose folders were deleted by hand, and drop their branches' local refs. */
104
+ forgetWorktrees(branches: readonly string[]): Promise<void>;
105
+ /** `git worktree prune`. */
106
+ prune(): Promise<void>;
107
+ /** The folders of the repository's worktrees, as git lists them. */
108
+ listWorktrees(): Promise<string[]>;
109
+ /** Import the tip of `branch` from the full clone at `cloneDir` (unpushed commits included); answers the tip. */
110
+ importBranch(cloneDir: string, branch: string): Promise<string>;
111
+ /**
112
+ * Import the full clone's stash entries and its other local refs (not its own
113
+ * branch, not remote-tracking ones) under `refs/kb-converted/<workspaceId>/`,
114
+ * leaving the clone as it was; answers the refs written.
115
+ */
116
+ importLocalRefs(cloneDir: string, branch: string, workspaceId: string): Promise<string[]>;
117
+ /** The address the repository fetches from, or null when it cannot be read. */
118
+ originUrl(): Promise<string | null>;
119
+ /** Re-link a repository and its worktrees that were moved together; answers the worktrees that could not be. */
120
+ relinkMovedCopy(movedRepository: string, movedWorktrees: readonly string[]): Promise<string[]>;
121
+ /** Point the repository at `url`, forgetting the old address's fetch freshness. */
122
+ setOriginUrl(url: string): Promise<void>;
123
+ }
124
+ //# sourceMappingURL=kb-repository.contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kb-repository.contract.d.ts","sourceRoot":"","sources":["../../../src/modules/workspace/kb-repository.contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The knowledge base's one repository, every branch workspace a worktree of
3
+ * it — the contract its consumers (the workspace service, the KB startup
4
+ * phase, the set-aside of a moved repository, the git layer) depend on.
5
+ * `KbRepository` (`kb-repository.ts`) is the implementation, a bare
6
+ * repository driven by the git CLI; the composition root makes ONE and
7
+ * injects it everywhere, so that one fetch serves every workspace and the
8
+ * repository's administration — its creation, the writes to its one config
9
+ * file, its worktree list, a set-aside — is serialized in one place.
10
+ *
11
+ * Nothing else is serialized by the application: git was built for many
12
+ * worktrees of one repository, and protects the refs, `packed-refs` and the
13
+ * object store with its own locks. The worktree list (`worktrees/`) it does
14
+ * not lock, which is why adding, removing and pruning worktrees are
15
+ * administration here. Two worktrees run side by side, as two developers'
16
+ * worktrees of one repository do.
17
+ */
18
+ export {};
19
+ //# sourceMappingURL=kb-repository.contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kb-repository.contract.js","sourceRoot":"","sources":["../../../src/modules/workspace/kb-repository.contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG"}