@cluesmith/codev 1.1.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 (245) hide show
  1. package/bin/af.js +8 -0
  2. package/bin/codev.js +4 -0
  3. package/bin/consult.js +7 -0
  4. package/dist/agent-farm/cli.d.ts +11 -0
  5. package/dist/agent-farm/cli.d.ts.map +1 -0
  6. package/dist/agent-farm/cli.js +359 -0
  7. package/dist/agent-farm/cli.js.map +1 -0
  8. package/dist/agent-farm/commands/cleanup.d.ts +12 -0
  9. package/dist/agent-farm/commands/cleanup.d.ts.map +1 -0
  10. package/dist/agent-farm/commands/cleanup.js +154 -0
  11. package/dist/agent-farm/commands/cleanup.js.map +1 -0
  12. package/dist/agent-farm/commands/db.d.ts +38 -0
  13. package/dist/agent-farm/commands/db.d.ts.map +1 -0
  14. package/dist/agent-farm/commands/db.js +133 -0
  15. package/dist/agent-farm/commands/db.js.map +1 -0
  16. package/dist/agent-farm/commands/index.d.ts +11 -0
  17. package/dist/agent-farm/commands/index.d.ts.map +1 -0
  18. package/dist/agent-farm/commands/index.js +11 -0
  19. package/dist/agent-farm/commands/index.js.map +1 -0
  20. package/dist/agent-farm/commands/open.d.ts +15 -0
  21. package/dist/agent-farm/commands/open.d.ts.map +1 -0
  22. package/dist/agent-farm/commands/open.js +118 -0
  23. package/dist/agent-farm/commands/open.js.map +1 -0
  24. package/dist/agent-farm/commands/rename.d.ts +13 -0
  25. package/dist/agent-farm/commands/rename.d.ts.map +1 -0
  26. package/dist/agent-farm/commands/rename.js +33 -0
  27. package/dist/agent-farm/commands/rename.js.map +1 -0
  28. package/dist/agent-farm/commands/send.d.ts +9 -0
  29. package/dist/agent-farm/commands/send.d.ts.map +1 -0
  30. package/dist/agent-farm/commands/send.js +282 -0
  31. package/dist/agent-farm/commands/send.js.map +1 -0
  32. package/dist/agent-farm/commands/spawn.d.ts +15 -0
  33. package/dist/agent-farm/commands/spawn.d.ts.map +1 -0
  34. package/dist/agent-farm/commands/spawn.js +575 -0
  35. package/dist/agent-farm/commands/spawn.js.map +1 -0
  36. package/dist/agent-farm/commands/start.d.ts +9 -0
  37. package/dist/agent-farm/commands/start.d.ts.map +1 -0
  38. package/dist/agent-farm/commands/start.js +175 -0
  39. package/dist/agent-farm/commands/start.js.map +1 -0
  40. package/dist/agent-farm/commands/status.d.ts +8 -0
  41. package/dist/agent-farm/commands/status.d.ts.map +1 -0
  42. package/dist/agent-farm/commands/status.js +123 -0
  43. package/dist/agent-farm/commands/status.js.map +1 -0
  44. package/dist/agent-farm/commands/stop.d.ts +8 -0
  45. package/dist/agent-farm/commands/stop.d.ts.map +1 -0
  46. package/dist/agent-farm/commands/stop.js +76 -0
  47. package/dist/agent-farm/commands/stop.js.map +1 -0
  48. package/dist/agent-farm/commands/tower.d.ts +19 -0
  49. package/dist/agent-farm/commands/tower.d.ts.map +1 -0
  50. package/dist/agent-farm/commands/tower.js +125 -0
  51. package/dist/agent-farm/commands/tower.js.map +1 -0
  52. package/dist/agent-farm/commands/tutorial.d.ts +10 -0
  53. package/dist/agent-farm/commands/tutorial.d.ts.map +1 -0
  54. package/dist/agent-farm/commands/tutorial.js +49 -0
  55. package/dist/agent-farm/commands/tutorial.js.map +1 -0
  56. package/dist/agent-farm/commands/util.d.ts +15 -0
  57. package/dist/agent-farm/commands/util.d.ts.map +1 -0
  58. package/dist/agent-farm/commands/util.js +108 -0
  59. package/dist/agent-farm/commands/util.js.map +1 -0
  60. package/dist/agent-farm/db/errors.d.ts +17 -0
  61. package/dist/agent-farm/db/errors.d.ts.map +1 -0
  62. package/dist/agent-farm/db/errors.js +46 -0
  63. package/dist/agent-farm/db/errors.js.map +1 -0
  64. package/dist/agent-farm/db/index.d.ts +41 -0
  65. package/dist/agent-farm/db/index.d.ts.map +1 -0
  66. package/dist/agent-farm/db/index.js +168 -0
  67. package/dist/agent-farm/db/index.js.map +1 -0
  68. package/dist/agent-farm/db/migrate.d.ts +15 -0
  69. package/dist/agent-farm/db/migrate.d.ts.map +1 -0
  70. package/dist/agent-farm/db/migrate.js +137 -0
  71. package/dist/agent-farm/db/migrate.js.map +1 -0
  72. package/dist/agent-farm/db/schema.d.ts +16 -0
  73. package/dist/agent-farm/db/schema.d.ts.map +1 -0
  74. package/dist/agent-farm/db/schema.js +103 -0
  75. package/dist/agent-farm/db/schema.js.map +1 -0
  76. package/dist/agent-farm/db/types.d.ts +87 -0
  77. package/dist/agent-farm/db/types.d.ts.map +1 -0
  78. package/dist/agent-farm/db/types.js +65 -0
  79. package/dist/agent-farm/db/types.js.map +1 -0
  80. package/dist/agent-farm/index.d.ts +7 -0
  81. package/dist/agent-farm/index.d.ts.map +1 -0
  82. package/dist/agent-farm/index.js +373 -0
  83. package/dist/agent-farm/index.js.map +1 -0
  84. package/dist/agent-farm/servers/annotate-server.d.ts +9 -0
  85. package/dist/agent-farm/servers/annotate-server.d.ts.map +1 -0
  86. package/dist/agent-farm/servers/annotate-server.js +136 -0
  87. package/dist/agent-farm/servers/annotate-server.js.map +1 -0
  88. package/dist/agent-farm/servers/dashboard-server.d.ts +9 -0
  89. package/dist/agent-farm/servers/dashboard-server.d.ts.map +1 -0
  90. package/dist/agent-farm/servers/dashboard-server.js +939 -0
  91. package/dist/agent-farm/servers/dashboard-server.js.map +1 -0
  92. package/dist/agent-farm/servers/tower-server.d.ts +9 -0
  93. package/dist/agent-farm/servers/tower-server.d.ts.map +1 -0
  94. package/dist/agent-farm/servers/tower-server.js +463 -0
  95. package/dist/agent-farm/servers/tower-server.js.map +1 -0
  96. package/dist/agent-farm/state.d.ts +93 -0
  97. package/dist/agent-farm/state.d.ts.map +1 -0
  98. package/dist/agent-farm/state.js +253 -0
  99. package/dist/agent-farm/state.js.map +1 -0
  100. package/dist/agent-farm/tutorial/index.d.ts +8 -0
  101. package/dist/agent-farm/tutorial/index.d.ts.map +1 -0
  102. package/dist/agent-farm/tutorial/index.js +8 -0
  103. package/dist/agent-farm/tutorial/index.js.map +1 -0
  104. package/dist/agent-farm/tutorial/prompts.d.ts +57 -0
  105. package/dist/agent-farm/tutorial/prompts.d.ts.map +1 -0
  106. package/dist/agent-farm/tutorial/prompts.js +147 -0
  107. package/dist/agent-farm/tutorial/prompts.js.map +1 -0
  108. package/dist/agent-farm/tutorial/runner.d.ts +52 -0
  109. package/dist/agent-farm/tutorial/runner.d.ts.map +1 -0
  110. package/dist/agent-farm/tutorial/runner.js +204 -0
  111. package/dist/agent-farm/tutorial/runner.js.map +1 -0
  112. package/dist/agent-farm/tutorial/state.d.ts +26 -0
  113. package/dist/agent-farm/tutorial/state.d.ts.map +1 -0
  114. package/dist/agent-farm/tutorial/state.js +89 -0
  115. package/dist/agent-farm/tutorial/state.js.map +1 -0
  116. package/dist/agent-farm/tutorial/steps/first-spec.d.ts +7 -0
  117. package/dist/agent-farm/tutorial/steps/first-spec.d.ts.map +1 -0
  118. package/dist/agent-farm/tutorial/steps/first-spec.js +136 -0
  119. package/dist/agent-farm/tutorial/steps/first-spec.js.map +1 -0
  120. package/dist/agent-farm/tutorial/steps/implementation.d.ts +7 -0
  121. package/dist/agent-farm/tutorial/steps/implementation.d.ts.map +1 -0
  122. package/dist/agent-farm/tutorial/steps/implementation.js +76 -0
  123. package/dist/agent-farm/tutorial/steps/implementation.js.map +1 -0
  124. package/dist/agent-farm/tutorial/steps/index.d.ts +10 -0
  125. package/dist/agent-farm/tutorial/steps/index.d.ts.map +1 -0
  126. package/dist/agent-farm/tutorial/steps/index.js +10 -0
  127. package/dist/agent-farm/tutorial/steps/index.js.map +1 -0
  128. package/dist/agent-farm/tutorial/steps/planning.d.ts +7 -0
  129. package/dist/agent-farm/tutorial/steps/planning.d.ts.map +1 -0
  130. package/dist/agent-farm/tutorial/steps/planning.js +143 -0
  131. package/dist/agent-farm/tutorial/steps/planning.js.map +1 -0
  132. package/dist/agent-farm/tutorial/steps/review.d.ts +7 -0
  133. package/dist/agent-farm/tutorial/steps/review.d.ts.map +1 -0
  134. package/dist/agent-farm/tutorial/steps/review.js +78 -0
  135. package/dist/agent-farm/tutorial/steps/review.js.map +1 -0
  136. package/dist/agent-farm/tutorial/steps/setup.d.ts +7 -0
  137. package/dist/agent-farm/tutorial/steps/setup.d.ts.map +1 -0
  138. package/dist/agent-farm/tutorial/steps/setup.js +126 -0
  139. package/dist/agent-farm/tutorial/steps/setup.js.map +1 -0
  140. package/dist/agent-farm/tutorial/steps/welcome.d.ts +7 -0
  141. package/dist/agent-farm/tutorial/steps/welcome.d.ts.map +1 -0
  142. package/dist/agent-farm/tutorial/steps/welcome.js +50 -0
  143. package/dist/agent-farm/tutorial/steps/welcome.js.map +1 -0
  144. package/dist/agent-farm/types.d.ts +131 -0
  145. package/dist/agent-farm/types.d.ts.map +1 -0
  146. package/dist/agent-farm/types.js +5 -0
  147. package/dist/agent-farm/types.js.map +1 -0
  148. package/dist/agent-farm/utils/config.d.ts +27 -0
  149. package/dist/agent-farm/utils/config.d.ts.map +1 -0
  150. package/dist/agent-farm/utils/config.js +242 -0
  151. package/dist/agent-farm/utils/config.js.map +1 -0
  152. package/dist/agent-farm/utils/deps.d.ts +51 -0
  153. package/dist/agent-farm/utils/deps.d.ts.map +1 -0
  154. package/dist/agent-farm/utils/deps.js +194 -0
  155. package/dist/agent-farm/utils/deps.js.map +1 -0
  156. package/dist/agent-farm/utils/index.d.ts +6 -0
  157. package/dist/agent-farm/utils/index.d.ts.map +1 -0
  158. package/dist/agent-farm/utils/index.js +6 -0
  159. package/dist/agent-farm/utils/index.js.map +1 -0
  160. package/dist/agent-farm/utils/logger.d.ts +31 -0
  161. package/dist/agent-farm/utils/logger.d.ts.map +1 -0
  162. package/dist/agent-farm/utils/logger.js +58 -0
  163. package/dist/agent-farm/utils/logger.js.map +1 -0
  164. package/dist/agent-farm/utils/orphan-handler.d.ts +27 -0
  165. package/dist/agent-farm/utils/orphan-handler.d.ts.map +1 -0
  166. package/dist/agent-farm/utils/orphan-handler.js +127 -0
  167. package/dist/agent-farm/utils/orphan-handler.js.map +1 -0
  168. package/dist/agent-farm/utils/port-registry.d.ts +58 -0
  169. package/dist/agent-farm/utils/port-registry.d.ts.map +1 -0
  170. package/dist/agent-farm/utils/port-registry.js +149 -0
  171. package/dist/agent-farm/utils/port-registry.js.map +1 -0
  172. package/dist/agent-farm/utils/shell.d.ts +45 -0
  173. package/dist/agent-farm/utils/shell.d.ts.map +1 -0
  174. package/dist/agent-farm/utils/shell.js +120 -0
  175. package/dist/agent-farm/utils/shell.js.map +1 -0
  176. package/dist/cli.d.ts +10 -0
  177. package/dist/cli.d.ts.map +1 -0
  178. package/dist/cli.js +160 -0
  179. package/dist/cli.js.map +1 -0
  180. package/dist/commands/adopt.d.ts +12 -0
  181. package/dist/commands/adopt.d.ts.map +1 -0
  182. package/dist/commands/adopt.js +178 -0
  183. package/dist/commands/adopt.js.map +1 -0
  184. package/dist/commands/consult/index.d.ts +17 -0
  185. package/dist/commands/consult/index.d.ts.map +1 -0
  186. package/dist/commands/consult/index.js +405 -0
  187. package/dist/commands/consult/index.js.map +1 -0
  188. package/dist/commands/doctor.d.ts +10 -0
  189. package/dist/commands/doctor.d.ts.map +1 -0
  190. package/dist/commands/doctor.js +346 -0
  191. package/dist/commands/doctor.js.map +1 -0
  192. package/dist/commands/init.d.ts +12 -0
  193. package/dist/commands/init.d.ts.map +1 -0
  194. package/dist/commands/init.js +167 -0
  195. package/dist/commands/init.js.map +1 -0
  196. package/dist/commands/tower.d.ts +16 -0
  197. package/dist/commands/tower.d.ts.map +1 -0
  198. package/dist/commands/tower.js +21 -0
  199. package/dist/commands/tower.js.map +1 -0
  200. package/dist/commands/update.d.ts +13 -0
  201. package/dist/commands/update.d.ts.map +1 -0
  202. package/dist/commands/update.js +137 -0
  203. package/dist/commands/update.js.map +1 -0
  204. package/dist/lib/templates.d.ts +57 -0
  205. package/dist/lib/templates.d.ts.map +1 -0
  206. package/dist/lib/templates.js +205 -0
  207. package/dist/lib/templates.js.map +1 -0
  208. package/package.json +55 -0
  209. package/templates/AGENTS.md +49 -0
  210. package/templates/CLAUDE.md +47 -0
  211. package/templates/DEPENDENCIES.md +344 -0
  212. package/templates/agents/architecture-documenter.md +189 -0
  213. package/templates/agents/codev-updater.md +276 -0
  214. package/templates/agents/spider-protocol-updater.md +118 -0
  215. package/templates/annotate.html +903 -0
  216. package/templates/bin/agent-farm +18 -0
  217. package/templates/bin/annotate-server.js +140 -0
  218. package/templates/bin/codev-doctor +335 -0
  219. package/templates/builders.md +30 -0
  220. package/templates/config.json +7 -0
  221. package/templates/dashboard-split.html +1679 -0
  222. package/templates/dashboard.html +149 -0
  223. package/templates/plans/.gitkeep +0 -0
  224. package/templates/protocols/experiment/protocol.md +229 -0
  225. package/templates/protocols/experiment/templates/notes.md +97 -0
  226. package/templates/protocols/maintain/protocol.md +235 -0
  227. package/templates/protocols/spider/protocol.md +639 -0
  228. package/templates/protocols/spider/templates/plan.md +169 -0
  229. package/templates/protocols/spider/templates/review.md +207 -0
  230. package/templates/protocols/spider/templates/spec.md +140 -0
  231. package/templates/protocols/spider-solo/protocol.md +619 -0
  232. package/templates/protocols/spider-solo/templates/plan.md +169 -0
  233. package/templates/protocols/spider-solo/templates/review.md +207 -0
  234. package/templates/protocols/spider-solo/templates/spec.md +140 -0
  235. package/templates/protocols/tick/protocol.md +250 -0
  236. package/templates/protocols/tick/templates/plan.md +67 -0
  237. package/templates/protocols/tick/templates/review.md +90 -0
  238. package/templates/protocols/tick/templates/spec.md +61 -0
  239. package/templates/reviews/.gitkeep +0 -0
  240. package/templates/roles/architect.md +230 -0
  241. package/templates/roles/builder.md +175 -0
  242. package/templates/roles/consultant.md +27 -0
  243. package/templates/specs/.gitkeep +0 -0
  244. package/templates/templates/projectlist.md +129 -0
  245. package/templates/tower.html +1032 -0
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Util command - spawns a utility terminal
3
+ *
4
+ * When the dashboard is running, this creates a tab in the dashboard.
5
+ * When the dashboard is not running, it spawns the terminal directly.
6
+ */
7
+ interface UtilOptions {
8
+ name?: string;
9
+ }
10
+ /**
11
+ * Spawn a utility terminal
12
+ */
13
+ export declare function util(options?: UtilOptions): Promise<void>;
14
+ export {};
15
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/commands/util.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,UAAU,WAAW;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAuCD;;GAEG;AACH,wBAAsB,IAAI,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkEnE"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Util command - spawns a utility terminal
3
+ *
4
+ * When the dashboard is running, this creates a tab in the dashboard.
5
+ * When the dashboard is not running, it spawns the terminal directly.
6
+ */
7
+ import { getConfig, getResolvedCommands } from '../utils/index.js';
8
+ import { logger, fatal } from '../utils/logger.js';
9
+ import { spawnDetached, commandExists, findAvailablePort, openBrowser } from '../utils/shell.js';
10
+ import { loadState, addUtil } from '../state.js';
11
+ /**
12
+ * Try to create a shell tab via the dashboard API
13
+ * Returns true if successful, false if dashboard not available
14
+ */
15
+ async function tryDashboardApi(name) {
16
+ const state = loadState();
17
+ // Dashboard runs on architectPort + 1
18
+ if (!state.architect) {
19
+ return false;
20
+ }
21
+ const config = getConfig();
22
+ const dashboardPort = config.architectPort + 1;
23
+ try {
24
+ const response = await fetch(`http://localhost:${dashboardPort}/api/tabs/shell`, {
25
+ method: 'POST',
26
+ headers: { 'Content-Type': 'application/json' },
27
+ body: JSON.stringify({ name }),
28
+ });
29
+ if (response.ok) {
30
+ const result = await response.json();
31
+ logger.success(`Shell opened in dashboard tab`);
32
+ logger.kv('Name', result.name);
33
+ return true;
34
+ }
35
+ // Dashboard returned an error, fall through to direct spawn
36
+ return false;
37
+ }
38
+ catch {
39
+ // Dashboard not available
40
+ return false;
41
+ }
42
+ }
43
+ /**
44
+ * Spawn a utility terminal
45
+ */
46
+ export async function util(options = {}) {
47
+ const config = getConfig();
48
+ // Try to use dashboard API first (if dashboard is running)
49
+ const dashboardOpened = await tryDashboardApi(options.name);
50
+ if (dashboardOpened) {
51
+ return;
52
+ }
53
+ // Fall back to direct spawn
54
+ // Check for ttyd
55
+ if (!(await commandExists('ttyd'))) {
56
+ fatal('ttyd not found. Install with: brew install ttyd');
57
+ }
58
+ // Generate ID and name
59
+ const id = generateUtilId();
60
+ const name = options.name || `util-${id}`;
61
+ // Find available port
62
+ const port = await findAvailablePort(config.utilPortRange[0]);
63
+ // Get shell command from config (hierarchy: CLI > config.json > default)
64
+ const commands = getResolvedCommands();
65
+ const shell = commands.shell;
66
+ logger.header(`Spawning Utility Terminal`);
67
+ logger.kv('ID', id);
68
+ logger.kv('Name', name);
69
+ logger.kv('Port', port);
70
+ // Start ttyd
71
+ const ttydArgs = [
72
+ '-W',
73
+ '-p', String(port),
74
+ '-t', `titleFixed=${name}`,
75
+ '-t', 'fontSize=14',
76
+ '-t', 'rightClickSelectsWord=true', // Enable word selection on right-click for better UX
77
+ shell,
78
+ ];
79
+ const ttydProcess = spawnDetached('ttyd', ttydArgs, {
80
+ cwd: config.projectRoot,
81
+ });
82
+ if (!ttydProcess.pid) {
83
+ fatal('Failed to start ttyd process for utility terminal');
84
+ }
85
+ // Create util record
86
+ const utilTerminal = {
87
+ id,
88
+ name,
89
+ port,
90
+ pid: ttydProcess.pid,
91
+ };
92
+ addUtil(utilTerminal);
93
+ logger.blank();
94
+ logger.success(`Utility terminal spawned!`);
95
+ logger.kv('Terminal', `http://localhost:${port}`);
96
+ // Open in browser if not using dashboard
97
+ const url = `http://localhost:${port}`;
98
+ await openBrowser(url);
99
+ }
100
+ /**
101
+ * Generate a unique utility ID
102
+ */
103
+ function generateUtilId() {
104
+ const timestamp = Date.now().toString(36);
105
+ const random = Math.random().toString(36).substring(2, 4);
106
+ return `U${timestamp.slice(-3)}${random}`.toUpperCase();
107
+ }
108
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/agent-farm/commands/util.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Database Error Handling Utilities
3
+ *
4
+ * Provides retry logic for SQLITE_BUSY errors and clear error messages
5
+ */
6
+ /**
7
+ * Execute a function with retry logic for SQLITE_BUSY errors
8
+ *
9
+ * The busy_timeout pragma handles most cases, but this provides an additional
10
+ * layer of retry logic for extreme contention scenarios.
11
+ */
12
+ export declare function withRetry<T>(fn: () => T, maxRetries?: number): T;
13
+ /**
14
+ * Check if better-sqlite3 is available and provide helpful error messages
15
+ */
16
+ export declare function checkDatabaseAvailability(): void;
17
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/db/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,UAAU,SAAI,GAAG,CAAC,CAc3D;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAahD"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Database Error Handling Utilities
3
+ *
4
+ * Provides retry logic for SQLITE_BUSY errors and clear error messages
5
+ */
6
+ /**
7
+ * Execute a function with retry logic for SQLITE_BUSY errors
8
+ *
9
+ * The busy_timeout pragma handles most cases, but this provides an additional
10
+ * layer of retry logic for extreme contention scenarios.
11
+ */
12
+ export function withRetry(fn, maxRetries = 3) {
13
+ for (let i = 0; i < maxRetries; i++) {
14
+ try {
15
+ return fn();
16
+ }
17
+ catch (err) {
18
+ const sqliteErr = err;
19
+ if (sqliteErr.code === 'SQLITE_BUSY' && i < maxRetries - 1) {
20
+ console.warn(`[warn] Database busy, retrying (${i + 1}/${maxRetries})...`);
21
+ continue;
22
+ }
23
+ throw err;
24
+ }
25
+ }
26
+ throw new Error('Unreachable');
27
+ }
28
+ /**
29
+ * Check if better-sqlite3 is available and provide helpful error messages
30
+ */
31
+ export function checkDatabaseAvailability() {
32
+ try {
33
+ require('better-sqlite3');
34
+ }
35
+ catch (err) {
36
+ const loadErr = err;
37
+ console.error('[error] better-sqlite3 failed to load. Native compilation may have failed.');
38
+ console.error('[error] Error:', loadErr.message);
39
+ console.error('[error] Try the following:');
40
+ console.error('[error] 1. npm rebuild better-sqlite3');
41
+ console.error('[error] 2. npm install better-sqlite3 --build-from-source');
42
+ console.error('[error] 3. Ensure build tools are installed (Xcode on macOS, build-essential on Linux)');
43
+ process.exit(1);
44
+ }
45
+ }
46
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/agent-farm/db/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAI,EAAW,EAAE,UAAU,GAAG,CAAC;IACtD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,IAAI,CAAC;YACH,OAAO,EAAE,EAAE,CAAC;QACd,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,SAAS,GAAG,GAAkB,CAAC;YACrC,IAAI,SAAS,CAAC,IAAI,KAAK,aAAa,IAAI,CAAC,GAAG,UAAU,GAAG,CAAC,EAAE,CAAC;gBAC3D,OAAO,CAAC,IAAI,CAAC,mCAAmC,CAAC,GAAG,CAAC,IAAI,UAAU,MAAM,CAAC,CAAC;gBAC3E,SAAS;YACX,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB;IACvC,IAAI,CAAC;QACH,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,GAAY,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,4EAA4E,CAAC,CAAC;QAC5F,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QACjD,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC5C,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;QACzD,OAAO,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;QAC7E,OAAO,CAAC,KAAK,CAAC,0FAA0F,CAAC,CAAC;QAC1G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * SQLite Database Module
3
+ *
4
+ * Provides singleton database access for both local state and global registry.
5
+ * Uses better-sqlite3 for synchronous operations with proper concurrency handling.
6
+ */
7
+ import Database from 'better-sqlite3';
8
+ /**
9
+ * Get the local database instance (state.db)
10
+ * Creates and initializes the database if it doesn't exist
11
+ */
12
+ export declare function getDb(): Database.Database;
13
+ /**
14
+ * Get the global database instance (global.db)
15
+ * Creates and initializes the database if it doesn't exist
16
+ */
17
+ export declare function getGlobalDb(): Database.Database;
18
+ /**
19
+ * Close the local database connection
20
+ */
21
+ export declare function closeDb(): void;
22
+ /**
23
+ * Close the global database connection
24
+ */
25
+ export declare function closeGlobalDb(): void;
26
+ /**
27
+ * Close all database connections
28
+ */
29
+ export declare function closeAllDbs(): void;
30
+ /**
31
+ * Get the path to the local database
32
+ */
33
+ export declare function getDbPath(): string;
34
+ /**
35
+ * Get the path to the global database
36
+ */
37
+ export declare function getGlobalDbPath(): string;
38
+ export { LOCAL_SCHEMA, GLOBAL_SCHEMA } from './schema.js';
39
+ export { withRetry } from './errors.js';
40
+ export type { DbArchitect, DbBuilder, DbUtil, DbAnnotation, DbPortAllocation, } from './types.js';
41
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/db/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAyCtC;;;GAGG;AACH,wBAAgB,KAAK,IAAI,QAAQ,CAAC,QAAQ,CAKzC;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,QAAQ,CAAC,QAAQ,CAK/C;AAED;;GAEG;AACH,wBAAgB,OAAO,IAAI,IAAI,CAK9B;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAKpC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAGlC;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAGlC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAuFD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EACV,WAAW,EACX,SAAS,EACT,MAAM,EACN,YAAY,EACZ,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * SQLite Database Module
3
+ *
4
+ * Provides singleton database access for both local state and global registry.
5
+ * Uses better-sqlite3 for synchronous operations with proper concurrency handling.
6
+ */
7
+ import Database from 'better-sqlite3';
8
+ import { existsSync, mkdirSync, copyFileSync, unlinkSync } from 'node:fs';
9
+ import { homedir } from 'node:os';
10
+ import { resolve } from 'node:path';
11
+ import { LOCAL_SCHEMA, GLOBAL_SCHEMA } from './schema.js';
12
+ import { migrateLocalFromJson, migrateGlobalFromJson } from './migrate.js';
13
+ import { getConfig } from '../utils/index.js';
14
+ // Singleton instances
15
+ let _localDb = null;
16
+ let _globalDb = null;
17
+ /**
18
+ * Ensure a directory exists
19
+ */
20
+ function ensureDir(dir) {
21
+ if (!existsSync(dir)) {
22
+ mkdirSync(dir, { recursive: true });
23
+ }
24
+ }
25
+ /**
26
+ * Configure database pragmas for optimal concurrency and durability
27
+ */
28
+ function configurePragmas(db) {
29
+ // Enable WAL mode for better concurrency (readers don't block writers)
30
+ const journalMode = db.pragma('journal_mode = WAL', { simple: true });
31
+ if (journalMode !== 'wal') {
32
+ console.warn('[warn] WAL mode unavailable, using DELETE mode (concurrency limited)');
33
+ }
34
+ // NORMAL synchronous mode balances safety and performance
35
+ db.pragma('synchronous = NORMAL');
36
+ // 5 second timeout when waiting for locks
37
+ db.pragma('busy_timeout = 5000');
38
+ // Enable foreign key constraints
39
+ db.pragma('foreign_keys = ON');
40
+ }
41
+ /**
42
+ * Get the local database instance (state.db)
43
+ * Creates and initializes the database if it doesn't exist
44
+ */
45
+ export function getDb() {
46
+ if (!_localDb) {
47
+ _localDb = ensureLocalDatabase();
48
+ }
49
+ return _localDb;
50
+ }
51
+ /**
52
+ * Get the global database instance (global.db)
53
+ * Creates and initializes the database if it doesn't exist
54
+ */
55
+ export function getGlobalDb() {
56
+ if (!_globalDb) {
57
+ _globalDb = ensureGlobalDatabase();
58
+ }
59
+ return _globalDb;
60
+ }
61
+ /**
62
+ * Close the local database connection
63
+ */
64
+ export function closeDb() {
65
+ if (_localDb) {
66
+ _localDb.close();
67
+ _localDb = null;
68
+ }
69
+ }
70
+ /**
71
+ * Close the global database connection
72
+ */
73
+ export function closeGlobalDb() {
74
+ if (_globalDb) {
75
+ _globalDb.close();
76
+ _globalDb = null;
77
+ }
78
+ }
79
+ /**
80
+ * Close all database connections
81
+ */
82
+ export function closeAllDbs() {
83
+ closeDb();
84
+ closeGlobalDb();
85
+ }
86
+ /**
87
+ * Get the path to the local database
88
+ */
89
+ export function getDbPath() {
90
+ const config = getConfig();
91
+ return resolve(config.stateDir, 'state.db');
92
+ }
93
+ /**
94
+ * Get the path to the global database
95
+ */
96
+ export function getGlobalDbPath() {
97
+ return resolve(homedir(), '.agent-farm', 'global.db');
98
+ }
99
+ /**
100
+ * Initialize the local database (state.db)
101
+ */
102
+ function ensureLocalDatabase() {
103
+ const config = getConfig();
104
+ const dbPath = resolve(config.stateDir, 'state.db');
105
+ const jsonPath = resolve(config.stateDir, 'state.json');
106
+ // Ensure directory exists
107
+ ensureDir(config.stateDir);
108
+ // Create/open database
109
+ const db = new Database(dbPath);
110
+ configurePragmas(db);
111
+ // Run schema (creates tables if they don't exist)
112
+ db.exec(LOCAL_SCHEMA);
113
+ // Check if migration is needed
114
+ const migrated = db.prepare('SELECT version FROM _migrations WHERE version = 1').get();
115
+ if (!migrated && existsSync(jsonPath)) {
116
+ // Migrate from JSON
117
+ migrateLocalFromJson(db, jsonPath);
118
+ // Record migration
119
+ db.prepare('INSERT INTO _migrations (version) VALUES (1)').run();
120
+ // Backup original JSON and remove it
121
+ copyFileSync(jsonPath, jsonPath + '.bak');
122
+ unlinkSync(jsonPath);
123
+ console.log('[info] Migrated state.json to state.db (backup at state.json.bak)');
124
+ }
125
+ else if (!migrated) {
126
+ // Fresh install, just mark migration as done
127
+ db.prepare('INSERT OR IGNORE INTO _migrations (version) VALUES (1)').run();
128
+ console.log('[info] Created new state.db at', dbPath);
129
+ }
130
+ return db;
131
+ }
132
+ /**
133
+ * Initialize the global database (global.db)
134
+ */
135
+ function ensureGlobalDatabase() {
136
+ const globalDir = resolve(homedir(), '.agent-farm');
137
+ const dbPath = resolve(globalDir, 'global.db');
138
+ const jsonPath = resolve(globalDir, 'ports.json');
139
+ // Ensure directory exists
140
+ ensureDir(globalDir);
141
+ // Create/open database
142
+ const db = new Database(dbPath);
143
+ configurePragmas(db);
144
+ // Run schema (creates tables if they don't exist)
145
+ db.exec(GLOBAL_SCHEMA);
146
+ // Check if migration is needed
147
+ const migrated = db.prepare('SELECT version FROM _migrations WHERE version = 1').get();
148
+ if (!migrated && existsSync(jsonPath)) {
149
+ // Migrate from JSON
150
+ migrateGlobalFromJson(db, jsonPath);
151
+ // Record migration
152
+ db.prepare('INSERT INTO _migrations (version) VALUES (1)').run();
153
+ // Backup original JSON and remove it
154
+ copyFileSync(jsonPath, jsonPath + '.bak');
155
+ unlinkSync(jsonPath);
156
+ console.log('[info] Migrated ports.json to global.db (backup at ports.json.bak)');
157
+ }
158
+ else if (!migrated) {
159
+ // Fresh install, just mark migration as done
160
+ db.prepare('INSERT OR IGNORE INTO _migrations (version) VALUES (1)').run();
161
+ console.log('[info] Created new global.db at', dbPath);
162
+ }
163
+ return db;
164
+ }
165
+ // Re-export types and utilities
166
+ export { LOCAL_SCHEMA, GLOBAL_SCHEMA } from './schema.js';
167
+ export { withRetry } from './errors.js';
168
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/agent-farm/db/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Migration Functions
3
+ *
4
+ * Handles migration from JSON files to SQLite databases
5
+ */
6
+ import type Database from 'better-sqlite3';
7
+ /**
8
+ * Migrate local state from JSON to SQLite
9
+ */
10
+ export declare function migrateLocalFromJson(db: Database.Database, jsonPath: string): void;
11
+ /**
12
+ * Migrate global port registry from JSON to SQLite
13
+ */
14
+ export declare function migrateGlobalFromJson(db: Database.Database, jsonPath: string): void;
15
+ //# sourceMappingURL=migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/db/migrate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAkB3C;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAoFlF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CA4CnF"}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Migration Functions
3
+ *
4
+ * Handles migration from JSON files to SQLite databases
5
+ */
6
+ import { readFileSync } from 'node:fs';
7
+ /**
8
+ * Migrate local state from JSON to SQLite
9
+ */
10
+ export function migrateLocalFromJson(db, jsonPath) {
11
+ const jsonContent = readFileSync(jsonPath, 'utf-8');
12
+ const state = JSON.parse(jsonContent);
13
+ // Wrap in transaction for atomicity
14
+ const migrate = db.transaction(() => {
15
+ // Migrate architect
16
+ if (state.architect) {
17
+ db.prepare(`
18
+ INSERT INTO architect (id, pid, port, cmd, started_at, tmux_session)
19
+ VALUES (1, @pid, @port, @cmd, @startedAt, @tmuxSession)
20
+ `).run({
21
+ pid: state.architect.pid,
22
+ port: state.architect.port,
23
+ cmd: state.architect.cmd,
24
+ startedAt: state.architect.startedAt,
25
+ tmuxSession: state.architect.tmuxSession ?? null,
26
+ });
27
+ }
28
+ // Migrate builders
29
+ for (const builder of state.builders || []) {
30
+ db.prepare(`
31
+ INSERT INTO builders (
32
+ id, name, port, pid, status, phase, worktree, branch,
33
+ tmux_session, type, task_text, protocol_name
34
+ )
35
+ VALUES (
36
+ @id, @name, @port, @pid, @status, @phase, @worktree, @branch,
37
+ @tmuxSession, @type, @taskText, @protocolName
38
+ )
39
+ `).run({
40
+ id: builder.id,
41
+ name: builder.name,
42
+ port: builder.port,
43
+ pid: builder.pid,
44
+ status: builder.status,
45
+ phase: builder.phase,
46
+ worktree: builder.worktree,
47
+ branch: builder.branch,
48
+ tmuxSession: builder.tmuxSession ?? null,
49
+ type: builder.type,
50
+ taskText: builder.taskText ?? null,
51
+ protocolName: builder.protocolName ?? null,
52
+ });
53
+ }
54
+ // Migrate utils
55
+ for (const util of state.utils || []) {
56
+ db.prepare(`
57
+ INSERT INTO utils (id, name, port, pid, tmux_session)
58
+ VALUES (@id, @name, @port, @pid, @tmuxSession)
59
+ `).run({
60
+ id: util.id,
61
+ name: util.name,
62
+ port: util.port,
63
+ pid: util.pid,
64
+ tmuxSession: util.tmuxSession ?? null,
65
+ });
66
+ }
67
+ // Migrate annotations
68
+ for (const annotation of state.annotations || []) {
69
+ db.prepare(`
70
+ INSERT INTO annotations (id, file, port, pid, parent_type, parent_id)
71
+ VALUES (@id, @file, @port, @pid, @parentType, @parentId)
72
+ `).run({
73
+ id: annotation.id,
74
+ file: annotation.file,
75
+ port: annotation.port,
76
+ pid: annotation.pid,
77
+ parentType: annotation.parent.type,
78
+ parentId: annotation.parent.id ?? null,
79
+ });
80
+ }
81
+ });
82
+ try {
83
+ migrate();
84
+ }
85
+ catch (err) {
86
+ console.error('[error] Migration failed. JSON file preserved.');
87
+ console.error('[error] Manual recovery: delete state.db and restart');
88
+ throw err;
89
+ }
90
+ }
91
+ /**
92
+ * Migrate global port registry from JSON to SQLite
93
+ */
94
+ export function migrateGlobalFromJson(db, jsonPath) {
95
+ const jsonContent = readFileSync(jsonPath, 'utf-8');
96
+ const data = JSON.parse(jsonContent);
97
+ // Handle both formats: versioned ({ version, entries }) and legacy (direct entries)
98
+ let entries;
99
+ if (data.version && data.entries) {
100
+ // New versioned format
101
+ entries = data.entries;
102
+ }
103
+ else {
104
+ // Legacy format - the object itself is the entries
105
+ // Filter out any non-entry fields
106
+ entries = {};
107
+ for (const [key, value] of Object.entries(data)) {
108
+ if (typeof value === 'object' && value !== null && 'basePort' in value) {
109
+ entries[key] = value;
110
+ }
111
+ }
112
+ }
113
+ // Wrap in transaction for atomicity
114
+ const migrate = db.transaction(() => {
115
+ for (const [projectPath, entry] of Object.entries(entries)) {
116
+ db.prepare(`
117
+ INSERT INTO port_allocations (project_path, base_port, pid, registered_at, last_used_at)
118
+ VALUES (@projectPath, @basePort, @pid, @registeredAt, @lastUsedAt)
119
+ `).run({
120
+ projectPath,
121
+ basePort: entry.basePort,
122
+ pid: entry.pid ?? null,
123
+ registeredAt: entry.registered,
124
+ lastUsedAt: entry.lastUsed ?? entry.registered,
125
+ });
126
+ }
127
+ });
128
+ try {
129
+ migrate();
130
+ }
131
+ catch (err) {
132
+ console.error('[error] Port registry migration failed. JSON file preserved.');
133
+ console.error('[error] Manual recovery: delete global.db and restart');
134
+ throw err;
135
+ }
136
+ }
137
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../../src/agent-farm/db/migrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * SQLite Schema Definitions
3
+ *
4
+ * Defines the schema for both local state (state.db) and global registry (global.db)
5
+ */
6
+ /**
7
+ * Local state schema (state.db)
8
+ * Stores dashboard state: architect, builders, utils, annotations
9
+ */
10
+ export declare const LOCAL_SCHEMA = "\n-- Schema versioning\nCREATE TABLE IF NOT EXISTS _migrations (\n version INTEGER PRIMARY KEY,\n applied_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Architect session (singleton)\nCREATE TABLE IF NOT EXISTS architect (\n id INTEGER PRIMARY KEY CHECK (id = 1),\n pid INTEGER NOT NULL,\n port INTEGER NOT NULL,\n cmd TEXT NOT NULL,\n started_at TEXT NOT NULL DEFAULT (datetime('now')),\n tmux_session TEXT\n);\n\n-- Builder sessions\nCREATE TABLE IF NOT EXISTS builders (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n port INTEGER NOT NULL UNIQUE,\n pid INTEGER NOT NULL,\n status TEXT NOT NULL DEFAULT 'spawning'\n CHECK(status IN ('spawning', 'implementing', 'blocked', 'pr-ready', 'complete')),\n phase TEXT NOT NULL DEFAULT '',\n worktree TEXT NOT NULL,\n branch TEXT NOT NULL,\n tmux_session TEXT,\n type TEXT NOT NULL DEFAULT 'spec'\n CHECK(type IN ('spec', 'task', 'protocol', 'shell', 'worktree')),\n task_text TEXT,\n protocol_name TEXT,\n started_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Indexes for common queries\nCREATE INDEX IF NOT EXISTS idx_builders_status ON builders(status);\nCREATE INDEX IF NOT EXISTS idx_builders_port ON builders(port);\n\n-- Utility terminals\nCREATE TABLE IF NOT EXISTS utils (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n port INTEGER NOT NULL UNIQUE,\n pid INTEGER NOT NULL,\n tmux_session TEXT,\n started_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Annotations (file viewers)\nCREATE TABLE IF NOT EXISTS annotations (\n id TEXT PRIMARY KEY,\n file TEXT NOT NULL,\n port INTEGER NOT NULL UNIQUE,\n pid INTEGER NOT NULL,\n parent_type TEXT NOT NULL CHECK(parent_type IN ('architect', 'builder', 'util')),\n parent_id TEXT,\n started_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Trigger to update updated_at on builders\nCREATE TRIGGER IF NOT EXISTS builders_updated_at\n AFTER UPDATE ON builders\n FOR EACH ROW\n BEGIN\n UPDATE builders SET updated_at = datetime('now') WHERE id = NEW.id;\n END;\n";
11
+ /**
12
+ * Global registry schema (global.db)
13
+ * Stores port allocations across all projects
14
+ */
15
+ export declare const GLOBAL_SCHEMA = "\n-- Schema versioning\nCREATE TABLE IF NOT EXISTS _migrations (\n version INTEGER PRIMARY KEY,\n applied_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Port allocations\nCREATE TABLE IF NOT EXISTS port_allocations (\n project_path TEXT PRIMARY KEY,\n base_port INTEGER NOT NULL UNIQUE\n CHECK(base_port >= 4200 AND base_port % 100 = 0),\n pid INTEGER,\n registered_at TEXT NOT NULL DEFAULT (datetime('now')),\n last_used_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_port_allocations_base_port ON port_allocations(base_port);\n";
16
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/db/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,eAAO,MAAM,YAAY,siEAqExB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,wkBAkBzB,CAAC"}