@jamesaphoenix/tx-core 0.4.1

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 (289) hide show
  1. package/dist/db.d.ts +42 -0
  2. package/dist/db.d.ts.map +1 -0
  3. package/dist/db.js +46 -0
  4. package/dist/db.js.map +1 -0
  5. package/dist/errors.d.ts +231 -0
  6. package/dist/errors.d.ts.map +1 -0
  7. package/dist/errors.js +139 -0
  8. package/dist/errors.js.map +1 -0
  9. package/dist/id.d.ts +6 -0
  10. package/dist/id.d.ts.map +1 -0
  11. package/dist/id.js +21 -0
  12. package/dist/id.js.map +1 -0
  13. package/dist/index.d.ts +25 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +56 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/layer.d.ts +50 -0
  18. package/dist/layer.d.ts.map +1 -0
  19. package/dist/layer.js +155 -0
  20. package/dist/layer.js.map +1 -0
  21. package/dist/mappers/anchor.d.ts +14 -0
  22. package/dist/mappers/anchor.d.ts.map +1 -0
  23. package/dist/mappers/anchor.js +38 -0
  24. package/dist/mappers/anchor.js.map +1 -0
  25. package/dist/mappers/attempt.d.ts +15 -0
  26. package/dist/mappers/attempt.d.ts.map +1 -0
  27. package/dist/mappers/attempt.js +23 -0
  28. package/dist/mappers/attempt.js.map +1 -0
  29. package/dist/mappers/candidate.d.ts +23 -0
  30. package/dist/mappers/candidate.d.ts.map +1 -0
  31. package/dist/mappers/candidate.js +53 -0
  32. package/dist/mappers/candidate.js.map +1 -0
  33. package/dist/mappers/claim.d.ts +30 -0
  34. package/dist/mappers/claim.d.ts.map +1 -0
  35. package/dist/mappers/claim.js +32 -0
  36. package/dist/mappers/claim.js.map +1 -0
  37. package/dist/mappers/deduplication.d.ts +39 -0
  38. package/dist/mappers/deduplication.d.ts.map +1 -0
  39. package/dist/mappers/deduplication.js +53 -0
  40. package/dist/mappers/deduplication.js.map +1 -0
  41. package/dist/mappers/edge.d.ts +10 -0
  42. package/dist/mappers/edge.d.ts.map +1 -0
  43. package/dist/mappers/edge.js +19 -0
  44. package/dist/mappers/edge.js.map +1 -0
  45. package/dist/mappers/file-learning.d.ts +14 -0
  46. package/dist/mappers/file-learning.d.ts.map +1 -0
  47. package/dist/mappers/file-learning.js +75 -0
  48. package/dist/mappers/file-learning.js.map +1 -0
  49. package/dist/mappers/index.d.ts +17 -0
  50. package/dist/mappers/index.d.ts.map +1 -0
  51. package/dist/mappers/index.js +30 -0
  52. package/dist/mappers/index.js.map +1 -0
  53. package/dist/mappers/learning.d.ts +19 -0
  54. package/dist/mappers/learning.d.ts.map +1 -0
  55. package/dist/mappers/learning.js +41 -0
  56. package/dist/mappers/learning.js.map +1 -0
  57. package/dist/mappers/orchestrator-state.d.ts +33 -0
  58. package/dist/mappers/orchestrator-state.d.ts.map +1 -0
  59. package/dist/mappers/orchestrator-state.js +34 -0
  60. package/dist/mappers/orchestrator-state.js.map +1 -0
  61. package/dist/mappers/run.d.ts +32 -0
  62. package/dist/mappers/run.d.ts.map +1 -0
  63. package/dist/mappers/run.js +64 -0
  64. package/dist/mappers/run.js.map +1 -0
  65. package/dist/mappers/task.d.ts +23 -0
  66. package/dist/mappers/task.d.ts.map +1 -0
  67. package/dist/mappers/task.js +54 -0
  68. package/dist/mappers/task.js.map +1 -0
  69. package/dist/mappers/tracked-project.d.ts +15 -0
  70. package/dist/mappers/tracked-project.d.ts.map +1 -0
  71. package/dist/mappers/tracked-project.js +23 -0
  72. package/dist/mappers/tracked-project.js.map +1 -0
  73. package/dist/mappers/worker.d.ts +33 -0
  74. package/dist/mappers/worker.d.ts.map +1 -0
  75. package/dist/mappers/worker.js +35 -0
  76. package/dist/mappers/worker.js.map +1 -0
  77. package/dist/repo/anchor-repo.d.ts +52 -0
  78. package/dist/repo/anchor-repo.d.ts.map +1 -0
  79. package/dist/repo/anchor-repo.js +204 -0
  80. package/dist/repo/anchor-repo.js.map +1 -0
  81. package/dist/repo/attempt-repo.d.ts +25 -0
  82. package/dist/repo/attempt-repo.d.ts.map +1 -0
  83. package/dist/repo/attempt-repo.js +78 -0
  84. package/dist/repo/attempt-repo.js.map +1 -0
  85. package/dist/repo/candidate-repo.d.ts +16 -0
  86. package/dist/repo/candidate-repo.d.ts.map +1 -0
  87. package/dist/repo/candidate-repo.js +143 -0
  88. package/dist/repo/candidate-repo.js.map +1 -0
  89. package/dist/repo/claim-repo.d.ts +17 -0
  90. package/dist/repo/claim-repo.d.ts.map +1 -0
  91. package/dist/repo/claim-repo.js +62 -0
  92. package/dist/repo/claim-repo.js.map +1 -0
  93. package/dist/repo/deduplication-repo.d.ts +37 -0
  94. package/dist/repo/deduplication-repo.d.ts.map +1 -0
  95. package/dist/repo/deduplication-repo.js +133 -0
  96. package/dist/repo/deduplication-repo.js.map +1 -0
  97. package/dist/repo/dep-repo.d.ts +19 -0
  98. package/dist/repo/dep-repo.d.ts.map +1 -0
  99. package/dist/repo/dep-repo.js +104 -0
  100. package/dist/repo/dep-repo.js.map +1 -0
  101. package/dist/repo/edge-repo.d.ts +26 -0
  102. package/dist/repo/edge-repo.d.ts.map +1 -0
  103. package/dist/repo/edge-repo.js +227 -0
  104. package/dist/repo/edge-repo.js.map +1 -0
  105. package/dist/repo/file-learning-repo.d.ts +17 -0
  106. package/dist/repo/file-learning-repo.d.ts.map +1 -0
  107. package/dist/repo/file-learning-repo.js +60 -0
  108. package/dist/repo/file-learning-repo.js.map +1 -0
  109. package/dist/repo/index.d.ts +18 -0
  110. package/dist/repo/index.d.ts.map +1 -0
  111. package/dist/repo/index.js +18 -0
  112. package/dist/repo/index.js.map +1 -0
  113. package/dist/repo/learning-repo.d.ts +31 -0
  114. package/dist/repo/learning-repo.d.ts.map +1 -0
  115. package/dist/repo/learning-repo.js +165 -0
  116. package/dist/repo/learning-repo.js.map +1 -0
  117. package/dist/repo/orchestrator-state-repo.d.ts +27 -0
  118. package/dist/repo/orchestrator-state-repo.d.ts.map +1 -0
  119. package/dist/repo/orchestrator-state-repo.js +96 -0
  120. package/dist/repo/orchestrator-state-repo.js.map +1 -0
  121. package/dist/repo/run-repo.d.ts +31 -0
  122. package/dist/repo/run-repo.d.ts.map +1 -0
  123. package/dist/repo/run-repo.js +132 -0
  124. package/dist/repo/run-repo.js.map +1 -0
  125. package/dist/repo/task-repo.d.ts +21 -0
  126. package/dist/repo/task-repo.d.ts.map +1 -0
  127. package/dist/repo/task-repo.js +169 -0
  128. package/dist/repo/task-repo.js.map +1 -0
  129. package/dist/repo/tracked-project-repo.d.ts +16 -0
  130. package/dist/repo/tracked-project-repo.d.ts.map +1 -0
  131. package/dist/repo/tracked-project-repo.js +54 -0
  132. package/dist/repo/tracked-project-repo.js.map +1 -0
  133. package/dist/repo/worker-repo.d.ts +19 -0
  134. package/dist/repo/worker-repo.d.ts.map +1 -0
  135. package/dist/repo/worker-repo.js +72 -0
  136. package/dist/repo/worker-repo.js.map +1 -0
  137. package/dist/schemas/index.d.ts +8 -0
  138. package/dist/schemas/index.d.ts.map +1 -0
  139. package/dist/schemas/index.js +7 -0
  140. package/dist/schemas/index.js.map +1 -0
  141. package/dist/schemas/sync.d.ts +296 -0
  142. package/dist/schemas/sync.d.ts.map +1 -0
  143. package/dist/schemas/sync.js +146 -0
  144. package/dist/schemas/sync.js.map +1 -0
  145. package/dist/schemas/worker.d.ts +77 -0
  146. package/dist/schemas/worker.d.ts.map +1 -0
  147. package/dist/schemas/worker.js +80 -0
  148. package/dist/schemas/worker.js.map +1 -0
  149. package/dist/services/anchor-service.d.ts +147 -0
  150. package/dist/services/anchor-service.d.ts.map +1 -0
  151. package/dist/services/anchor-service.js +540 -0
  152. package/dist/services/anchor-service.js.map +1 -0
  153. package/dist/services/anchor-verification.d.ts +94 -0
  154. package/dist/services/anchor-verification.d.ts.map +1 -0
  155. package/dist/services/anchor-verification.js +617 -0
  156. package/dist/services/anchor-verification.js.map +1 -0
  157. package/dist/services/ast-grep-service.d.ts +58 -0
  158. package/dist/services/ast-grep-service.d.ts.map +1 -0
  159. package/dist/services/ast-grep-service.js +356 -0
  160. package/dist/services/ast-grep-service.js.map +1 -0
  161. package/dist/services/attempt-service.d.ts +24 -0
  162. package/dist/services/attempt-service.d.ts.map +1 -0
  163. package/dist/services/attempt-service.js +55 -0
  164. package/dist/services/attempt-service.js.map +1 -0
  165. package/dist/services/auto-sync-service.d.ts +56 -0
  166. package/dist/services/auto-sync-service.d.ts.map +1 -0
  167. package/dist/services/auto-sync-service.js +66 -0
  168. package/dist/services/auto-sync-service.js.map +1 -0
  169. package/dist/services/candidate-extractor-service.d.ts +56 -0
  170. package/dist/services/candidate-extractor-service.d.ts.map +1 -0
  171. package/dist/services/candidate-extractor-service.js +365 -0
  172. package/dist/services/candidate-extractor-service.js.map +1 -0
  173. package/dist/services/claim-service.d.ts +52 -0
  174. package/dist/services/claim-service.d.ts.map +1 -0
  175. package/dist/services/claim-service.js +134 -0
  176. package/dist/services/claim-service.js.map +1 -0
  177. package/dist/services/daemon-service.d.ts +214 -0
  178. package/dist/services/daemon-service.d.ts.map +1 -0
  179. package/dist/services/daemon-service.js +522 -0
  180. package/dist/services/daemon-service.js.map +1 -0
  181. package/dist/services/deduplication-service.d.ts +67 -0
  182. package/dist/services/deduplication-service.d.ts.map +1 -0
  183. package/dist/services/deduplication-service.js +145 -0
  184. package/dist/services/deduplication-service.js.map +1 -0
  185. package/dist/services/dep-service.d.ts +14 -0
  186. package/dist/services/dep-service.d.ts.map +1 -0
  187. package/dist/services/dep-service.js +34 -0
  188. package/dist/services/dep-service.js.map +1 -0
  189. package/dist/services/diversifier-service.d.ts +46 -0
  190. package/dist/services/diversifier-service.d.ts.map +1 -0
  191. package/dist/services/diversifier-service.js +197 -0
  192. package/dist/services/diversifier-service.js.map +1 -0
  193. package/dist/services/edge-service.d.ts +78 -0
  194. package/dist/services/edge-service.d.ts.map +1 -0
  195. package/dist/services/edge-service.js +158 -0
  196. package/dist/services/edge-service.js.map +1 -0
  197. package/dist/services/embedding-service.d.ts +138 -0
  198. package/dist/services/embedding-service.d.ts.map +1 -0
  199. package/dist/services/embedding-service.js +318 -0
  200. package/dist/services/embedding-service.js.map +1 -0
  201. package/dist/services/feedback-tracker.d.ts +64 -0
  202. package/dist/services/feedback-tracker.d.ts.map +1 -0
  203. package/dist/services/feedback-tracker.js +110 -0
  204. package/dist/services/feedback-tracker.js.map +1 -0
  205. package/dist/services/file-learning-service.d.ts +17 -0
  206. package/dist/services/file-learning-service.d.ts.map +1 -0
  207. package/dist/services/file-learning-service.js +41 -0
  208. package/dist/services/file-learning-service.js.map +1 -0
  209. package/dist/services/file-watcher-service.d.ts +141 -0
  210. package/dist/services/file-watcher-service.d.ts.map +1 -0
  211. package/dist/services/file-watcher-service.js +278 -0
  212. package/dist/services/file-watcher-service.js.map +1 -0
  213. package/dist/services/graph-expansion.d.ts +155 -0
  214. package/dist/services/graph-expansion.d.ts.map +1 -0
  215. package/dist/services/graph-expansion.js +466 -0
  216. package/dist/services/graph-expansion.js.map +1 -0
  217. package/dist/services/hierarchy-service.d.ts +16 -0
  218. package/dist/services/hierarchy-service.d.ts.map +1 -0
  219. package/dist/services/hierarchy-service.js +66 -0
  220. package/dist/services/hierarchy-service.js.map +1 -0
  221. package/dist/services/index.d.ts +36 -0
  222. package/dist/services/index.d.ts.map +1 -0
  223. package/dist/services/index.js +36 -0
  224. package/dist/services/index.js.map +1 -0
  225. package/dist/services/learning-service.d.ts +39 -0
  226. package/dist/services/learning-service.d.ts.map +1 -0
  227. package/dist/services/learning-service.js +151 -0
  228. package/dist/services/learning-service.js.map +1 -0
  229. package/dist/services/migration-service.d.ts +67 -0
  230. package/dist/services/migration-service.d.ts.map +1 -0
  231. package/dist/services/migration-service.js +144 -0
  232. package/dist/services/migration-service.js.map +1 -0
  233. package/dist/services/orchestrator-service.d.ts +52 -0
  234. package/dist/services/orchestrator-service.d.ts.map +1 -0
  235. package/dist/services/orchestrator-service.js +203 -0
  236. package/dist/services/orchestrator-service.js.map +1 -0
  237. package/dist/services/promotion-service.d.ts +67 -0
  238. package/dist/services/promotion-service.d.ts.map +1 -0
  239. package/dist/services/promotion-service.js +151 -0
  240. package/dist/services/promotion-service.js.map +1 -0
  241. package/dist/services/query-expansion-service.d.ts +55 -0
  242. package/dist/services/query-expansion-service.d.ts.map +1 -0
  243. package/dist/services/query-expansion-service.js +174 -0
  244. package/dist/services/query-expansion-service.js.map +1 -0
  245. package/dist/services/ready-service.d.ts +16 -0
  246. package/dist/services/ready-service.d.ts.map +1 -0
  247. package/dist/services/ready-service.js +70 -0
  248. package/dist/services/ready-service.js.map +1 -0
  249. package/dist/services/reranker-service.d.ts +51 -0
  250. package/dist/services/reranker-service.d.ts.map +1 -0
  251. package/dist/services/reranker-service.js +128 -0
  252. package/dist/services/reranker-service.js.map +1 -0
  253. package/dist/services/retriever-service.d.ts +49 -0
  254. package/dist/services/retriever-service.d.ts.map +1 -0
  255. package/dist/services/retriever-service.js +419 -0
  256. package/dist/services/retriever-service.js.map +1 -0
  257. package/dist/services/score-service.d.ts +43 -0
  258. package/dist/services/score-service.d.ts.map +1 -0
  259. package/dist/services/score-service.js +82 -0
  260. package/dist/services/score-service.js.map +1 -0
  261. package/dist/services/swarm-verification.d.ts +104 -0
  262. package/dist/services/swarm-verification.d.ts.map +1 -0
  263. package/dist/services/swarm-verification.js +400 -0
  264. package/dist/services/swarm-verification.js.map +1 -0
  265. package/dist/services/sync-service.d.ts +115 -0
  266. package/dist/services/sync-service.d.ts.map +1 -0
  267. package/dist/services/sync-service.js +350 -0
  268. package/dist/services/sync-service.js.map +1 -0
  269. package/dist/services/task-service.d.ts +22 -0
  270. package/dist/services/task-service.d.ts.map +1 -0
  271. package/dist/services/task-service.js +221 -0
  272. package/dist/services/task-service.js.map +1 -0
  273. package/dist/services/worker-process.d.ts +41 -0
  274. package/dist/services/worker-process.d.ts.map +1 -0
  275. package/dist/services/worker-process.js +280 -0
  276. package/dist/services/worker-process.js.map +1 -0
  277. package/dist/services/worker-service.d.ts +74 -0
  278. package/dist/services/worker-service.d.ts.map +1 -0
  279. package/dist/services/worker-service.js +148 -0
  280. package/dist/services/worker-service.js.map +1 -0
  281. package/dist/utils/glob.d.ts +15 -0
  282. package/dist/utils/glob.d.ts.map +1 -0
  283. package/dist/utils/glob.js +27 -0
  284. package/dist/utils/glob.js.map +1 -0
  285. package/dist/utils/math.d.ts +6 -0
  286. package/dist/utils/math.d.ts.map +1 -0
  287. package/dist/utils/math.js +21 -0
  288. package/dist/utils/math.js.map +1 -0
  289. package/package.json +72 -0
@@ -0,0 +1,41 @@
1
+ /**
2
+ * WorkerProcess - PRD-018
3
+ *
4
+ * Implements the worker process with heartbeat fiber, lease renewal,
5
+ * Claude subprocess management, and graceful shutdown handling.
6
+ * Uses Effect-TS patterns per DD-002.
7
+ */
8
+ import { Effect } from "effect";
9
+ import { WorkerService } from "./worker-service.js";
10
+ import { ClaimService } from "./claim-service.js";
11
+ import { ReadyService } from "./ready-service.js";
12
+ import { TaskService } from "./task-service.js";
13
+ /**
14
+ * Configuration for the worker process.
15
+ */
16
+ export interface WorkerProcessConfig {
17
+ /** Optional worker name. Defaults to worker-{timestamp} */
18
+ readonly name?: string;
19
+ /** List of agent capabilities (e.g., ['tx-implementer', 'tx-tester']) */
20
+ readonly capabilities: readonly string[];
21
+ /** Heartbeat interval in seconds. Should match orchestrator config. */
22
+ readonly heartbeatIntervalSeconds: number;
23
+ /** How often to renew the lease (in seconds). Should be < lease duration. */
24
+ readonly leaseRenewalIntervalSeconds?: number;
25
+ /** Working directory for Claude subprocess. Defaults to process.cwd() */
26
+ readonly workingDirectory?: string;
27
+ }
28
+ /**
29
+ * Run the worker process.
30
+ *
31
+ * This function:
32
+ * 1. Registers the worker with the orchestrator
33
+ * 2. Starts a background heartbeat fiber
34
+ * 3. Runs a work loop that claims and processes tasks
35
+ * 4. Handles graceful shutdown via SIGTERM/SIGINT
36
+ *
37
+ * @param config Worker process configuration
38
+ * @returns Effect that runs until shutdown is requested
39
+ */
40
+ export declare const runWorkerProcess: (config: WorkerProcessConfig) => Effect.Effect<void, import("../errors.js").TaskNotFoundError | import("../errors.js").ValidationError | import("../errors.js").DatabaseError | import("../errors.js").RegistrationError | import("../errors.js").WorkerNotFoundError, TaskService | ReadyService | WorkerService | ClaimService>;
41
+ //# sourceMappingURL=worker-process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-process.d.ts","sourceRoot":"","sources":["../../src/services/worker-process.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAwB,MAAM,QAAQ,CAAA;AAGrD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAG/C;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,yEAAyE;IACzE,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;IACxC,uEAAuE;IACvE,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAA;IACzC,6EAA6E;IAC7E,QAAQ,CAAC,2BAA2B,CAAC,EAAE,MAAM,CAAA;IAC7C,yEAAyE;IACzE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CACnC;AAmBD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,mBAAmB,qSAwLxD,CAAA"}
@@ -0,0 +1,280 @@
1
+ /**
2
+ * WorkerProcess - PRD-018
3
+ *
4
+ * Implements the worker process with heartbeat fiber, lease renewal,
5
+ * Claude subprocess management, and graceful shutdown handling.
6
+ * Uses Effect-TS patterns per DD-002.
7
+ */
8
+ import { Effect, Duration, Fiber, Ref } from "effect";
9
+ import { spawn } from "child_process";
10
+ import * as os from "os";
11
+ import { WorkerService } from "./worker-service.js";
12
+ import { ClaimService } from "./claim-service.js";
13
+ import { ReadyService } from "./ready-service.js";
14
+ import { TaskService } from "./task-service.js";
15
+ /**
16
+ * Run the worker process.
17
+ *
18
+ * This function:
19
+ * 1. Registers the worker with the orchestrator
20
+ * 2. Starts a background heartbeat fiber
21
+ * 3. Runs a work loop that claims and processes tasks
22
+ * 4. Handles graceful shutdown via SIGTERM/SIGINT
23
+ *
24
+ * @param config Worker process configuration
25
+ * @returns Effect that runs until shutdown is requested
26
+ */
27
+ export const runWorkerProcess = (config) => Effect.gen(function* () {
28
+ const workerService = yield* WorkerService;
29
+ const claimService = yield* ClaimService;
30
+ const readyService = yield* ReadyService;
31
+ const taskService = yield* TaskService;
32
+ // Shutdown state ref (mutable, shared with signal handlers)
33
+ const shutdownState = yield* Ref.make({
34
+ requested: false,
35
+ claudeProcess: null
36
+ });
37
+ // Register with orchestrator
38
+ const worker = yield* workerService.register({
39
+ name: config.name,
40
+ hostname: os.hostname(),
41
+ pid: process.pid,
42
+ capabilities: config.capabilities
43
+ });
44
+ const workerId = worker.id;
45
+ yield* Effect.log(`Worker ${workerId} registered`);
46
+ // Set up signal handlers for graceful shutdown
47
+ const handleSignal = (signal) => {
48
+ console.log(`Worker ${workerId} received ${signal}`);
49
+ // Mark shutdown as requested (sync since signal handlers can't use async)
50
+ Effect.runSync(Ref.update(shutdownState, (state) => ({
51
+ ...state,
52
+ requested: true
53
+ })));
54
+ // Try to terminate Claude subprocess if running
55
+ Effect.runSync(Ref.get(shutdownState).pipe(Effect.map((state) => {
56
+ if (state.claudeProcess && !state.claudeProcess.killed) {
57
+ state.claudeProcess.kill("SIGTERM");
58
+ }
59
+ })));
60
+ };
61
+ process.on("SIGTERM", () => handleSignal("SIGTERM"));
62
+ process.on("SIGINT", () => handleSignal("SIGINT"));
63
+ // Completed tasks counter for metrics (shared with heartbeat loop)
64
+ const tasksCompletedRef = yield* Ref.make(0);
65
+ // Heartbeat fiber - runs continuously in background
66
+ const heartbeatFiber = yield* Effect.fork(runHeartbeatLoop(workerId, config.heartbeatIntervalSeconds, shutdownState, tasksCompletedRef));
67
+ try {
68
+ // Main work loop
69
+ while (true) {
70
+ // Check if shutdown was requested
71
+ const state = yield* Ref.get(shutdownState);
72
+ if (state.requested) {
73
+ yield* Effect.log(`Worker ${workerId} shutting down gracefully`);
74
+ break;
75
+ }
76
+ // Update status to idle
77
+ yield* workerService.updateStatus(workerId, "idle");
78
+ // Check for available work
79
+ const readyTasks = yield* readyService.getReady(1);
80
+ if (readyTasks.length === 0) {
81
+ // No work available, wait and try again
82
+ yield* Effect.sleep(Duration.seconds(5));
83
+ continue;
84
+ }
85
+ const task = readyTasks[0];
86
+ // Try to claim the task
87
+ const claimResult = yield* claimService.claim(task.id, workerId).pipe(Effect.either);
88
+ if (claimResult._tag === "Left") {
89
+ // Someone else claimed it, try again
90
+ yield* Effect.log(`Worker ${workerId} failed to claim task ${task.id}: ${claimResult.left._tag}`);
91
+ continue;
92
+ }
93
+ const _claim = claimResult.right;
94
+ yield* Effect.log(`Worker ${workerId} claimed task ${task.id}`);
95
+ const tasksCompleted = yield* Ref.get(tasksCompletedRef);
96
+ // Update worker status to busy with current task
97
+ yield* workerService.heartbeat({
98
+ workerId,
99
+ timestamp: new Date(),
100
+ status: "busy",
101
+ currentTaskId: task.id,
102
+ metrics: {
103
+ cpuPercent: process.cpuUsage().user / 1000000,
104
+ memoryMb: process.memoryUsage().heapUsed / 1024 / 1024,
105
+ tasksCompleted
106
+ }
107
+ });
108
+ // Select appropriate agent for the task
109
+ const agent = selectAgent(task);
110
+ // Start lease renewal fiber
111
+ const renewalInterval = config.leaseRenewalIntervalSeconds ??
112
+ config.heartbeatIntervalSeconds * 10; // Default: 10x heartbeat interval
113
+ const renewFiber = yield* Effect.fork(runLeaseRenewalLoop(task.id, workerId, renewalInterval, shutdownState));
114
+ try {
115
+ // Run Claude subprocess
116
+ const result = yield* runClaude(agent, task, workerId, config.workingDirectory ?? process.cwd(), shutdownState);
117
+ if (result.success) {
118
+ // Mark task as done
119
+ yield* taskService.update(task.id, { status: "done" });
120
+ yield* Ref.update(tasksCompletedRef, (n) => n + 1);
121
+ yield* Effect.log(`Task ${task.id} completed successfully`);
122
+ }
123
+ else {
124
+ yield* Effect.log(`Task ${task.id} failed: ${result.error ?? "Unknown error"}`);
125
+ }
126
+ // Release the claim
127
+ yield* claimService.release(task.id, workerId).pipe(Effect.catchAll((error) => Effect.log(`Failed to release claim for task ${task.id}: ${error.message}`)));
128
+ }
129
+ finally {
130
+ // Stop renewal fiber
131
+ yield* Fiber.interrupt(renewFiber);
132
+ }
133
+ }
134
+ // Graceful shutdown: mark as stopping
135
+ yield* workerService.updateStatus(workerId, "stopping");
136
+ }
137
+ finally {
138
+ // Cleanup: stop heartbeat fiber and deregister
139
+ yield* Fiber.interrupt(heartbeatFiber);
140
+ // Release any active claims before deregistering
141
+ yield* claimService.releaseByWorker(workerId).pipe(Effect.catchAll((error) => Effect.log(`Failed to release claims for worker ${workerId}: ${error.message}`).pipe(Effect.as(0))));
142
+ yield* workerService.deregister(workerId).pipe(Effect.catchAll((error) => Effect.log(`Failed to deregister worker ${workerId}: ${error.message}`)));
143
+ yield* Effect.log(`Worker ${workerId} shutdown complete`);
144
+ }
145
+ });
146
+ /**
147
+ * Run the heartbeat loop.
148
+ * Sends periodic heartbeats to the orchestrator.
149
+ */
150
+ const runHeartbeatLoop = (workerId, intervalSeconds, shutdownState, tasksCompletedRef) => Effect.gen(function* () {
151
+ const workerService = yield* WorkerService;
152
+ while (true) {
153
+ // Check shutdown before heartbeat
154
+ const state = yield* Ref.get(shutdownState);
155
+ if (state.requested)
156
+ break;
157
+ // Determine current status based on whether Claude is running
158
+ const status = state.claudeProcess ? "busy" : "idle";
159
+ // Read current completed count from shared ref
160
+ const tasksCompleted = yield* Ref.get(tasksCompletedRef);
161
+ yield* workerService
162
+ .heartbeat({
163
+ workerId,
164
+ timestamp: new Date(),
165
+ status,
166
+ currentTaskId: undefined, // The main loop sets this
167
+ metrics: {
168
+ cpuPercent: process.cpuUsage().user / 1000000,
169
+ memoryMb: process.memoryUsage().heapUsed / 1024 / 1024,
170
+ tasksCompleted
171
+ }
172
+ })
173
+ .pipe(Effect.catchAll((error) => Effect.log(`Heartbeat failed for ${workerId}: ${error.message}`)));
174
+ yield* Effect.sleep(Duration.seconds(intervalSeconds));
175
+ }
176
+ });
177
+ /**
178
+ * Run the lease renewal loop.
179
+ * Periodically renews the lease on a claimed task.
180
+ */
181
+ const runLeaseRenewalLoop = (taskId, workerId, intervalSeconds, shutdownState) => Effect.gen(function* () {
182
+ const claimService = yield* ClaimService;
183
+ while (true) {
184
+ // Wait before first renewal
185
+ yield* Effect.sleep(Duration.seconds(intervalSeconds));
186
+ // Check shutdown before renewal
187
+ const state = yield* Ref.get(shutdownState);
188
+ if (state.requested)
189
+ break;
190
+ yield* claimService
191
+ .renew(taskId, workerId)
192
+ .pipe(Effect.tap(() => Effect.log(`Renewed lease on task ${taskId}`)), Effect.catchAll((error) => Effect.log(`Lease renewal failed for task ${taskId}: ${error.message}`)));
193
+ }
194
+ });
195
+ /**
196
+ * Run a Claude subprocess to work on a task.
197
+ */
198
+ const runClaude = (agent, task, workerId, workingDirectory, shutdownState) => Effect.async((resume) => {
199
+ const prompt = buildPrompt(agent, task);
200
+ const proc = spawn("claude", ["--dangerously-skip-permissions", "--print", prompt], {
201
+ cwd: workingDirectory,
202
+ env: { ...process.env, TX_WORKER_ID: workerId },
203
+ stdio: ["pipe", "pipe", "pipe"]
204
+ });
205
+ // Store the process reference for signal handling
206
+ Effect.runSync(Ref.update(shutdownState, (state) => ({
207
+ ...state,
208
+ claudeProcess: proc
209
+ })));
210
+ let stderr = "";
211
+ proc.stderr?.on("data", (data) => {
212
+ stderr += data.toString();
213
+ });
214
+ proc.on("close", (code) => {
215
+ // Clear the process reference
216
+ Effect.runSync(Ref.update(shutdownState, (state) => ({
217
+ ...state,
218
+ claudeProcess: null
219
+ })));
220
+ if (code === 0) {
221
+ resume(Effect.succeed({ success: true, exitCode: code ?? 0 }));
222
+ }
223
+ else {
224
+ resume(Effect.succeed({
225
+ success: false,
226
+ error: stderr || `Exit code ${code}`,
227
+ exitCode: code ?? 1
228
+ }));
229
+ }
230
+ });
231
+ proc.on("error", (err) => {
232
+ // Clear the process reference
233
+ Effect.runSync(Ref.update(shutdownState, (state) => ({
234
+ ...state,
235
+ claudeProcess: null
236
+ })));
237
+ resume(Effect.succeed({
238
+ success: false,
239
+ error: err.message,
240
+ exitCode: 1
241
+ }));
242
+ });
243
+ });
244
+ /**
245
+ * Build the prompt for the Claude subprocess.
246
+ */
247
+ const buildPrompt = (agent, task) => `Read .claude/agents/${agent}.md for your instructions.
248
+
249
+ Your assigned task: ${task.id}
250
+ Task title: ${task.title}
251
+
252
+ Run \`tx show ${task.id}\` to get full details, then follow your agent instructions.
253
+ When done, run \`tx done ${task.id}\` to mark the task complete.
254
+ If you discover new work, create subtasks with \`tx add\`.
255
+ If you hit a blocker, update the task status: \`tx update ${task.id} --status blocked\`.`;
256
+ /**
257
+ * Select the appropriate agent based on task characteristics.
258
+ */
259
+ const selectAgent = (task) => {
260
+ const title = task.title.toLowerCase();
261
+ // Test/integration tasks go to tester
262
+ if (title.includes("test") ||
263
+ title.includes("integration") ||
264
+ title.includes("fixture")) {
265
+ return "tx-tester";
266
+ }
267
+ // Review/audit tasks go to reviewer
268
+ if (title.includes("review") ||
269
+ title.includes("audit") ||
270
+ title.includes("check")) {
271
+ return "tx-reviewer";
272
+ }
273
+ // High-priority tasks without children may need decomposition
274
+ if (task.score >= 800 && task.children.length === 0) {
275
+ return "tx-decomposer";
276
+ }
277
+ // Default to implementer
278
+ return "tx-implementer";
279
+ };
280
+ //# sourceMappingURL=worker-process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-process.js","sourceRoot":"","sources":["../../src/services/worker-process.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * WorkerService - PRD-018
3
+ *
4
+ * Manages worker registration, heartbeats, and lifecycle.
5
+ * Uses Effect-TS patterns per DD-002.
6
+ */
7
+ import { Context, Effect, Layer } from "effect";
8
+ import { WorkerRepository } from "../repo/worker-repo.js";
9
+ import { OrchestratorStateRepository } from "../repo/orchestrator-state-repo.js";
10
+ import { DatabaseError, RegistrationError, WorkerNotFoundError } from "../errors.js";
11
+ import type { Worker, WorkerStatus, Heartbeat } from "../schemas/worker.js";
12
+ /**
13
+ * Input for worker registration.
14
+ */
15
+ export interface WorkerRegistration {
16
+ readonly workerId?: string;
17
+ readonly name?: string;
18
+ readonly hostname?: string;
19
+ readonly pid?: number;
20
+ readonly capabilities?: readonly string[];
21
+ }
22
+ /**
23
+ * Filter options for listing workers.
24
+ */
25
+ export interface WorkerFilter {
26
+ readonly status?: readonly WorkerStatus[];
27
+ readonly noCurrentTask?: boolean;
28
+ }
29
+ /**
30
+ * Configuration for finding dead workers.
31
+ */
32
+ export interface FindDeadConfig {
33
+ readonly missedHeartbeats: number;
34
+ }
35
+ declare const WorkerService_base: Context.TagClass<WorkerService, "WorkerService", {
36
+ /**
37
+ * Register a new worker with the orchestrator.
38
+ * Checks orchestrator state and pool capacity before registration.
39
+ */
40
+ readonly register: (registration: WorkerRegistration) => Effect.Effect<Worker, RegistrationError | DatabaseError>;
41
+ /**
42
+ * Process a heartbeat from a worker.
43
+ * Updates last heartbeat time, status, and optional metrics.
44
+ */
45
+ readonly heartbeat: (heartbeat: Heartbeat) => Effect.Effect<void, WorkerNotFoundError | DatabaseError>;
46
+ /**
47
+ * Deregister a worker.
48
+ * Removes the worker from the registry.
49
+ * Note: Active claims should be released by ClaimService before calling this.
50
+ */
51
+ readonly deregister: (workerId: string) => Effect.Effect<void, WorkerNotFoundError | DatabaseError>;
52
+ /**
53
+ * List workers with optional filtering.
54
+ */
55
+ readonly list: (filter?: WorkerFilter) => Effect.Effect<readonly Worker[], DatabaseError>;
56
+ /**
57
+ * Find workers that have missed heartbeats.
58
+ * Uses the orchestrator's configured heartbeat interval.
59
+ */
60
+ readonly findDead: (config: FindDeadConfig) => Effect.Effect<readonly Worker[], DatabaseError>;
61
+ /**
62
+ * Mark a worker as dead.
63
+ */
64
+ readonly markDead: (workerId: string) => Effect.Effect<void, WorkerNotFoundError | DatabaseError>;
65
+ /**
66
+ * Update a worker's status.
67
+ */
68
+ readonly updateStatus: (workerId: string, status: WorkerStatus) => Effect.Effect<void, WorkerNotFoundError | DatabaseError>;
69
+ }>;
70
+ export declare class WorkerService extends WorkerService_base {
71
+ }
72
+ export declare const WorkerServiceLive: Layer.Layer<WorkerService, never, WorkerRepository | OrchestratorStateRepository>;
73
+ export {};
74
+ //# sourceMappingURL=worker-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-service.d.ts","sourceRoot":"","sources":["../../src/services/worker-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAG/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAA;AAChF,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAE3E;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IACzC,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;CAClC;;IAkBG;;;OAGG;uBACgB,CACjB,YAAY,EAAE,kBAAkB,KAC7B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,aAAa,CAAC;IAE7D;;;OAGG;wBACiB,CAClB,SAAS,EAAE,SAAS,KACjB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,mBAAmB,GAAG,aAAa,CAAC;IAE7D;;;;OAIG;yBACkB,CACnB,QAAQ,EAAE,MAAM,KACb,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,mBAAmB,GAAG,aAAa,CAAC;IAE7D;;OAEG;mBACY,CACb,MAAM,CAAC,EAAE,YAAY,KAClB,MAAM,CAAC,MAAM,CAAC,SAAS,MAAM,EAAE,EAAE,aAAa,CAAC;IAEpD;;;OAGG;uBACgB,CACjB,MAAM,EAAE,cAAc,KACnB,MAAM,CAAC,MAAM,CAAC,SAAS,MAAM,EAAE,EAAE,aAAa,CAAC;IAEpD;;OAEG;uBACgB,CACjB,QAAQ,EAAE,MAAM,KACb,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,mBAAmB,GAAG,aAAa,CAAC;IAE7D;;OAEG;2BACoB,CACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,YAAY,KACjB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,mBAAmB,GAAG,aAAa,CAAC;;AAxDjE,qBAAa,aAAc,SAAQ,kBA0DhC;CAAG;AAEN,eAAO,MAAM,iBAAiB,mFAqK7B,CAAA"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * WorkerService - PRD-018
3
+ *
4
+ * Manages worker registration, heartbeats, and lifecycle.
5
+ * Uses Effect-TS patterns per DD-002.
6
+ */
7
+ import { Context, Effect, Layer } from "effect";
8
+ import { createHash, randomBytes } from "crypto";
9
+ import * as os from "os";
10
+ import { WorkerRepository } from "../repo/worker-repo.js";
11
+ import { OrchestratorStateRepository } from "../repo/orchestrator-state-repo.js";
12
+ import { RegistrationError, WorkerNotFoundError } from "../errors.js";
13
+ /**
14
+ * Generate a unique worker ID.
15
+ */
16
+ const generateWorkerId = () => {
17
+ const random = randomBytes(16).toString("hex");
18
+ const timestamp = Date.now().toString(36);
19
+ const hash = createHash("sha256")
20
+ .update(timestamp + random)
21
+ .digest("hex")
22
+ .substring(0, 8);
23
+ return `worker-${hash}`;
24
+ };
25
+ export class WorkerService extends Context.Tag("WorkerService")() {
26
+ }
27
+ export const WorkerServiceLive = Layer.effect(WorkerService, Effect.gen(function* () {
28
+ const workerRepo = yield* WorkerRepository;
29
+ const orchestratorRepo = yield* OrchestratorStateRepository;
30
+ return {
31
+ register: (registration) => Effect.gen(function* () {
32
+ // Verify orchestrator is running
33
+ const state = yield* orchestratorRepo.get();
34
+ if (state.status !== "running") {
35
+ return yield* Effect.fail(new RegistrationError({
36
+ reason: "Orchestrator is not running"
37
+ }));
38
+ }
39
+ // Count active workers (starting, idle, busy)
40
+ const startingCount = yield* workerRepo.countByStatus("starting");
41
+ const idleCount = yield* workerRepo.countByStatus("idle");
42
+ const busyCount = yield* workerRepo.countByStatus("busy");
43
+ const activeWorkers = startingCount + idleCount + busyCount;
44
+ // Check pool capacity
45
+ if (activeWorkers >= state.workerPoolSize) {
46
+ return yield* Effect.fail(new RegistrationError({
47
+ reason: `Worker pool at capacity (${state.workerPoolSize})`
48
+ }));
49
+ }
50
+ const now = new Date();
51
+ const worker = {
52
+ id: registration.workerId ?? generateWorkerId(),
53
+ name: registration.name ?? `worker-${Date.now()}`,
54
+ hostname: registration.hostname ?? os.hostname(),
55
+ pid: registration.pid ?? process.pid,
56
+ status: "starting",
57
+ registeredAt: now,
58
+ lastHeartbeatAt: now,
59
+ currentTaskId: null,
60
+ capabilities: [...(registration.capabilities ?? ["tx-implementer"])],
61
+ metadata: {}
62
+ };
63
+ yield* workerRepo.insert(worker);
64
+ yield* Effect.log(`Worker ${worker.id} registered`);
65
+ return worker;
66
+ }),
67
+ heartbeat: (heartbeat) => Effect.gen(function* () {
68
+ const worker = yield* workerRepo.findById(heartbeat.workerId);
69
+ if (!worker) {
70
+ return yield* Effect.fail(new WorkerNotFoundError({ workerId: heartbeat.workerId }));
71
+ }
72
+ // Build updated worker
73
+ const updated = {
74
+ ...worker,
75
+ lastHeartbeatAt: heartbeat.timestamp,
76
+ status: heartbeat.status,
77
+ currentTaskId: heartbeat.currentTaskId ?? null,
78
+ metadata: heartbeat.metrics
79
+ ? { ...worker.metadata, lastMetrics: heartbeat.metrics }
80
+ : worker.metadata
81
+ };
82
+ yield* workerRepo.update(updated);
83
+ }),
84
+ deregister: (workerId) => Effect.gen(function* () {
85
+ const worker = yield* workerRepo.findById(workerId);
86
+ if (!worker) {
87
+ return yield* Effect.fail(new WorkerNotFoundError({ workerId }));
88
+ }
89
+ // Note: Active claims should be released by ClaimService before calling this.
90
+ // The ClaimService.releaseByWorker call is handled by the orchestrator/caller.
91
+ const deleted = yield* workerRepo.delete(workerId);
92
+ if (deleted) {
93
+ yield* Effect.log(`Worker ${workerId} deregistered`);
94
+ }
95
+ }),
96
+ list: (filter) => Effect.gen(function* () {
97
+ // Get all workers in a single query
98
+ const allWorkers = yield* workerRepo.findAll();
99
+ if (!filter) {
100
+ return allWorkers;
101
+ }
102
+ let results = [...allWorkers];
103
+ // Filter by status if specified
104
+ if (filter.status && filter.status.length > 0) {
105
+ const statusSet = new Set(filter.status);
106
+ results = results.filter((w) => statusSet.has(w.status));
107
+ }
108
+ // Filter by noCurrentTask if specified
109
+ if (filter.noCurrentTask) {
110
+ results = results.filter((w) => w.currentTaskId === null);
111
+ }
112
+ return results;
113
+ }),
114
+ findDead: (config) => Effect.gen(function* () {
115
+ const state = yield* orchestratorRepo.get();
116
+ const heartbeatTimeoutSeconds = state.heartbeatIntervalSeconds * config.missedHeartbeats;
117
+ const cutoff = new Date(Date.now() - heartbeatTimeoutSeconds * 1000);
118
+ // Get workers with old heartbeats
119
+ const staleWorkers = yield* workerRepo.findByLastHeartbeatBefore(cutoff);
120
+ // Exclude workers that are already dead or stopping
121
+ return staleWorkers.filter((w) => w.status !== "dead" && w.status !== "stopping");
122
+ }),
123
+ markDead: (workerId) => Effect.gen(function* () {
124
+ const worker = yield* workerRepo.findById(workerId);
125
+ if (!worker) {
126
+ return yield* Effect.fail(new WorkerNotFoundError({ workerId }));
127
+ }
128
+ const updated = {
129
+ ...worker,
130
+ status: "dead"
131
+ };
132
+ yield* workerRepo.update(updated);
133
+ yield* Effect.log(`Worker ${workerId} marked as dead`);
134
+ }),
135
+ updateStatus: (workerId, status) => Effect.gen(function* () {
136
+ const worker = yield* workerRepo.findById(workerId);
137
+ if (!worker) {
138
+ return yield* Effect.fail(new WorkerNotFoundError({ workerId }));
139
+ }
140
+ const updated = {
141
+ ...worker,
142
+ status
143
+ };
144
+ yield* workerRepo.update(updated);
145
+ })
146
+ };
147
+ }));
148
+ //# sourceMappingURL=worker-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-service.js","sourceRoot":"","sources":["../../src/services/worker-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Simple glob matching - checks if file path matches pattern.
3
+ * Supports: *, **, ?
4
+ *
5
+ * - `*` matches any characters except /
6
+ * - `**` matches any characters including /
7
+ * - `?` matches a single character
8
+ *
9
+ * @example
10
+ * matchesGlob("src/utils/math.ts", "src/**\/*.ts") // true
11
+ * matchesGlob("src/index.ts", "*.ts") // false (no / in *)
12
+ * matchesGlob("file.ts", "file.??") // true
13
+ */
14
+ export declare const matchesGlob: (filePath: string, pattern: string) => boolean;
15
+ //# sourceMappingURL=glob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../src/utils/glob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,EAAE,SAAS,MAAM,KAAG,OAa/D,CAAA"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Simple glob matching - checks if file path matches pattern.
3
+ * Supports: *, **, ?
4
+ *
5
+ * - `*` matches any characters except /
6
+ * - `**` matches any characters including /
7
+ * - `?` matches a single character
8
+ *
9
+ * @example
10
+ * matchesGlob("src/utils/math.ts", "src/**\/*.ts") // true
11
+ * matchesGlob("src/index.ts", "*.ts") // false (no / in *)
12
+ * matchesGlob("file.ts", "file.??") // true
13
+ */
14
+ export const matchesGlob = (filePath, pattern) => {
15
+ // Simple glob matching without external dependencies
16
+ // Order matters: protect glob patterns, escape dots, then restore patterns
17
+ const regexPattern = pattern
18
+ .replace(/\*\*/g, "<<<GLOBSTAR>>>") // Protect ** (will become .*)
19
+ .replace(/\?/g, "<<<QUESTION>>>") // Protect ? (will become .)
20
+ .replace(/\*/g, "[^/]*") // Replace * with segment matcher
21
+ .replace(/\./g, "\\.") // Escape literal dots (e.g., .ts → \\.ts)
22
+ .replace(/<<<GLOBSTAR>>>/g, ".*") // Restore ** as .* (matches any path)
23
+ .replace(/<<<QUESTION>>>/g, "."); // Restore ? as . (matches single char)
24
+ const regex = new RegExp(`^${regexPattern}$`);
25
+ return regex.test(filePath);
26
+ };
27
+ //# sourceMappingURL=glob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.js","sourceRoot":"","sources":["../../src/utils/glob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAE,OAAe,EAAW,EAAE;IACxE,qDAAqD;IACrD,2EAA2E;IAC3E,MAAM,YAAY,GAAG,OAAO;SACzB,OAAO,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,8BAA8B;SACjE,OAAO,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC,4BAA4B;SAC7D,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,iCAAiC;SACzD,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,0CAA0C;SAChE,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC,sCAAsC;SACvE,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAA,CAAC,uCAAuC;IAE1E,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,YAAY,GAAG,CAAC,CAAA;IAC7C,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;AAC7B,CAAC,CAAA"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Calculate cosine similarity between two vectors.
3
+ * Returns a value between -1 and 1, where 1 means identical direction.
4
+ */
5
+ export declare const cosineSimilarity: (a: Float32Array, b: Float32Array) => number;
6
+ //# sourceMappingURL=math.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../../src/utils/math.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,GAAG,YAAY,EAAE,GAAG,YAAY,KAAG,MAiBnE,CAAA"}