@goondocks/myco 0.20.2 → 0.21.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 (196) hide show
  1. package/dist/agent-eval-RJSQI5S2.js +355 -0
  2. package/dist/agent-eval-RJSQI5S2.js.map +1 -0
  3. package/dist/{agent-run-X25Q2A6T.js → agent-run-2JSYFOKU.js} +10 -8
  4. package/dist/{agent-run-X25Q2A6T.js.map → agent-run-2JSYFOKU.js.map} +1 -1
  5. package/dist/{agent-tasks-7B6OFERB.js → agent-tasks-APFJIM2T.js} +10 -8
  6. package/dist/{agent-tasks-7B6OFERB.js.map → agent-tasks-APFJIM2T.js.map} +1 -1
  7. package/dist/{chunk-OD4AA7PV.js → chunk-53RPGOEN.js} +56 -8
  8. package/dist/chunk-53RPGOEN.js.map +1 -0
  9. package/dist/chunk-54SXG5HF.js +26 -0
  10. package/dist/chunk-54SXG5HF.js.map +1 -0
  11. package/dist/{chunk-DCSGJ7W4.js → chunk-5ZG4RMUH.js} +2 -2
  12. package/dist/{chunk-FLLBJLHM.js → chunk-6C6QZ4PM.js} +9 -5
  13. package/dist/chunk-6C6QZ4PM.js.map +1 -0
  14. package/dist/chunk-6LB7XELY.js +406 -0
  15. package/dist/chunk-6LB7XELY.js.map +1 -0
  16. package/dist/{chunk-JZGN33AY.js → chunk-75Z7UKDY.js} +4 -4
  17. package/dist/{chunk-XG5RRUYF.js → chunk-BUTL6IFS.js} +2 -2
  18. package/dist/chunk-CESKJD44.js +586 -0
  19. package/dist/chunk-CESKJD44.js.map +1 -0
  20. package/dist/chunk-CISWUP5W.js +101 -0
  21. package/dist/chunk-CISWUP5W.js.map +1 -0
  22. package/dist/chunk-DJ3IHNYO.js +50 -0
  23. package/dist/chunk-DJ3IHNYO.js.map +1 -0
  24. package/dist/chunk-F3OEQYLS.js +847 -0
  25. package/dist/chunk-F3OEQYLS.js.map +1 -0
  26. package/dist/{chunk-6RFZWV4R.js → chunk-FCJ5JV54.js} +1 -1
  27. package/dist/{chunk-6RFZWV4R.js.map → chunk-FCJ5JV54.js.map} +1 -1
  28. package/dist/{chunk-2PDWCDKY.js → chunk-G6QIBNZM.js} +9 -6
  29. package/dist/{chunk-2PDWCDKY.js.map → chunk-G6QIBNZM.js.map} +1 -1
  30. package/dist/{chunk-6X2ERTQV.js → chunk-ILJPRYES.js} +6 -4
  31. package/dist/{chunk-6X2ERTQV.js.map → chunk-ILJPRYES.js.map} +1 -1
  32. package/dist/{chunk-US4LNCAT.js → chunk-IPPMYQ2Y.js} +5 -1
  33. package/dist/chunk-IPPMYQ2Y.js.map +1 -0
  34. package/dist/{chunk-KESLPBKV.js → chunk-JR54LTPP.js} +4 -4
  35. package/dist/{chunk-CCRGY3QW.js → chunk-JZS6GZ6T.js} +16 -94
  36. package/dist/chunk-JZS6GZ6T.js.map +1 -0
  37. package/dist/{chunk-5XIVBO25.js → chunk-LVIY7P35.js} +2 -2
  38. package/dist/chunk-NGH7U6A3.js +13844 -0
  39. package/dist/chunk-NGH7U6A3.js.map +1 -0
  40. package/dist/chunk-OUJSQSKE.js +113 -0
  41. package/dist/chunk-OUJSQSKE.js.map +1 -0
  42. package/dist/{chunk-VVNL26WX.js → chunk-P66DLD6G.js} +22 -10
  43. package/dist/chunk-P66DLD6G.js.map +1 -0
  44. package/dist/{chunk-XATDZX7U.js → chunk-R2JIJBCL.js} +18 -4
  45. package/dist/{chunk-XATDZX7U.js.map → chunk-R2JIJBCL.js.map} +1 -1
  46. package/dist/{chunk-MYOZLMB2.js → chunk-RL5R4CQU.js} +538 -19
  47. package/dist/chunk-RL5R4CQU.js.map +1 -0
  48. package/dist/{chunk-EVDQKYCG.js → chunk-RQSJLWP4.js} +13 -2
  49. package/dist/chunk-RQSJLWP4.js.map +1 -0
  50. package/dist/{chunk-BPRIYNLE.js → chunk-TKAJ3JVF.js} +3 -3
  51. package/dist/{chunk-Q36VMZST.js → chunk-VHNRMM4O.js} +3 -2
  52. package/dist/{chunk-FMRZ26U5.js → chunk-X3IGT5RV.js} +5 -2
  53. package/dist/{chunk-FMRZ26U5.js.map → chunk-X3IGT5RV.js.map} +1 -1
  54. package/dist/{chunk-KHT24OWC.js → chunk-YDUOSRGD.js} +8 -94
  55. package/dist/{chunk-KHT24OWC.js.map → chunk-YDUOSRGD.js.map} +1 -1
  56. package/dist/{cli-GGPWH4UO.js → cli-LNYSTDQM.js} +49 -42
  57. package/dist/cli-LNYSTDQM.js.map +1 -0
  58. package/dist/{client-YXQUTXVZ.js → client-NWE4TCNO.js} +4 -4
  59. package/dist/{config-OMCYHG2S.js → config-VC4ACP42.js} +6 -4
  60. package/dist/{config-OMCYHG2S.js.map → config-VC4ACP42.js.map} +1 -1
  61. package/dist/{detect-providers-5KOPZ7J2.js → detect-providers-ILLQZROY.js} +4 -4
  62. package/dist/{doctor-5JXJ36KA.js → doctor-TI7EZ3RW.js} +48 -15
  63. package/dist/doctor-TI7EZ3RW.js.map +1 -0
  64. package/dist/executor-F2YU7HXJ.js +44 -0
  65. package/dist/{init-LMYOVZAV.js → init-KG3TYVGE.js} +14 -12
  66. package/dist/{init-LMYOVZAV.js.map → init-KG3TYVGE.js.map} +1 -1
  67. package/dist/{installer-FS257JRZ.js → installer-UMH7OJ5A.js} +6 -4
  68. package/dist/{llm-TH4NLIRM.js → llm-AGVEF5XD.js} +5 -4
  69. package/dist/{loader-CQYTFHEW.js → loader-LX7TFRM6.js} +5 -3
  70. package/dist/{loader-NOMBJUPW.js → loader-NAVVZK63.js} +4 -3
  71. package/dist/{main-YTBVRTBI.js → main-5PRQNEEE.js} +2453 -650
  72. package/dist/main-5PRQNEEE.js.map +1 -0
  73. package/dist/{open-HG2DX6RN.js → open-5A27BCSB.js} +10 -8
  74. package/dist/{open-HG2DX6RN.js.map → open-5A27BCSB.js.map} +1 -1
  75. package/dist/{post-compact-JSECI44W.js → post-compact-USAODKPQ.js} +6 -6
  76. package/dist/{post-tool-use-POGPTJBA.js → post-tool-use-GMMSYBII.js} +9 -7
  77. package/dist/post-tool-use-GMMSYBII.js.map +1 -0
  78. package/dist/{post-tool-use-failure-OT7BFWQW.js → post-tool-use-failure-NZVSL2PO.js} +6 -6
  79. package/dist/{pre-compact-OXVODKH4.js → pre-compact-LZ57DLUS.js} +6 -6
  80. package/dist/{provider-check-43LAMSMH.js → provider-check-ZEV5P4KM.js} +4 -4
  81. package/dist/{registry-U4CHXK6R.js → registry-M2Z5QBWH.js} +5 -4
  82. package/dist/{remove-N7ZPELFU.js → remove-T3KE6C5N.js} +10 -8
  83. package/dist/{remove-N7ZPELFU.js.map → remove-T3KE6C5N.js.map} +1 -1
  84. package/dist/{restart-ADG5GBTB.js → restart-YWDEVZUJ.js} +11 -9
  85. package/dist/{restart-ADG5GBTB.js.map → restart-YWDEVZUJ.js.map} +1 -1
  86. package/dist/{search-AHZEUNRR.js → search-GKFDGELR.js} +11 -9
  87. package/dist/{search-AHZEUNRR.js.map → search-GKFDGELR.js.map} +1 -1
  88. package/dist/{server-AGVYZVP5.js → server-AHUR6CWF.js} +368 -269
  89. package/dist/server-AHUR6CWF.js.map +1 -0
  90. package/dist/{session-6IU4AXYP.js → session-2ZEPLWW6.js} +11 -9
  91. package/dist/{session-6IU4AXYP.js.map → session-2ZEPLWW6.js.map} +1 -1
  92. package/dist/{session-end-FT27DWYZ.js → session-end-LWJYQAXX.js} +5 -5
  93. package/dist/session-start-WTA6GCOQ.js +134 -0
  94. package/dist/session-start-WTA6GCOQ.js.map +1 -0
  95. package/dist/{setup-llm-77MP4I2G.js → setup-llm-E7UU5IO7.js} +11 -9
  96. package/dist/{setup-llm-77MP4I2G.js.map → setup-llm-E7UU5IO7.js.map} +1 -1
  97. package/dist/src/agent/definitions/agent.yaml +9 -5
  98. package/dist/src/agent/definitions/tasks/cortex-instructions.yaml +93 -0
  99. package/dist/src/agent/definitions/tasks/cortex-prompt-builder.yaml +67 -0
  100. package/dist/src/agent/definitions/tasks/digest-only.yaml +1 -1
  101. package/dist/src/agent/definitions/tasks/extract-only.yaml +1 -1
  102. package/dist/src/agent/definitions/tasks/review-session.yaml +10 -39
  103. package/dist/src/agent/definitions/tasks/skill-evolve.yaml +4 -4
  104. package/dist/src/agent/definitions/tasks/skill-generate.yaml +1 -1
  105. package/dist/src/agent/definitions/tasks/skill-survey.yaml +2 -6
  106. package/dist/src/agent/definitions/tasks/supersession-sweep.yaml +1 -1
  107. package/dist/src/agent/definitions/tasks/title-summary.yaml +12 -19
  108. package/dist/src/agent/definitions/tasks/{full-intelligence.yaml → vault-evolve.yaml} +17 -82
  109. package/dist/src/agent/definitions/tasks/vault-seed.yaml +370 -0
  110. package/dist/src/agent/prompts/agent.md +12 -38
  111. package/dist/src/cli.js +1 -1
  112. package/dist/src/daemon/main.js +1 -1
  113. package/dist/src/hooks/post-tool-use.js +1 -1
  114. package/dist/src/hooks/session-end.js +1 -1
  115. package/dist/src/hooks/session-start.js +1 -1
  116. package/dist/src/hooks/stop.js +1 -1
  117. package/dist/src/hooks/user-prompt-submit.js +1 -1
  118. package/dist/src/mcp/server.js +1 -1
  119. package/dist/src/symbionts/manifests/claude-code.yaml +4 -0
  120. package/dist/src/symbionts/manifests/pi.yaml +22 -0
  121. package/dist/src/symbionts/templates/pi/package.json +6 -0
  122. package/dist/src/symbionts/templates/pi/plugin.ts +559 -0
  123. package/dist/{stats-NVPWOYTE.js → stats-DFG6S23S.js} +11 -9
  124. package/dist/{stats-NVPWOYTE.js.map → stats-DFG6S23S.js.map} +1 -1
  125. package/dist/{stop-ZPIKVLH4.js → stop-WRBTXEVT.js} +5 -5
  126. package/dist/{stop-failure-2PX67YJC.js → stop-failure-32MGIG2Q.js} +6 -6
  127. package/dist/{subagent-start-UUE6EHQD.js → subagent-start-VFGHQFVL.js} +6 -6
  128. package/dist/{subagent-stop-KQWWWPE6.js → subagent-stop-663FXG3P.js} +6 -6
  129. package/dist/{task-completed-WMHOFQ7B.js → task-completed-ZCQYEFMZ.js} +6 -6
  130. package/dist/{team-LRZ6GTQK.js → team-JTI5CDUO.js} +7 -5
  131. package/dist/{turns-YFNI5CQC.js → turns-HU2CTZAP.js} +2 -2
  132. package/dist/ui/assets/index-DGf1h-Ha.js +842 -0
  133. package/dist/ui/assets/index-_OP4ifzH.css +1 -0
  134. package/dist/ui/index.html +2 -2
  135. package/dist/{update-O6V4RC4W.js → update-3NBQTG32.js} +10 -8
  136. package/dist/{update-O6V4RC4W.js.map → update-3NBQTG32.js.map} +1 -1
  137. package/dist/{user-prompt-submit-N36KUPHI.js → user-prompt-submit-ME2TBKOS.js} +8 -7
  138. package/dist/{user-prompt-submit-N36KUPHI.js.map → user-prompt-submit-ME2TBKOS.js.map} +1 -1
  139. package/dist/{verify-LXPV7NYG.js → verify-R76ZFJSZ.js} +8 -5
  140. package/dist/{verify-LXPV7NYG.js.map → verify-R76ZFJSZ.js.map} +1 -1
  141. package/dist/{version-XMPPJQHR.js → version-GQAFBBPX.js} +2 -2
  142. package/dist/version-GQAFBBPX.js.map +1 -0
  143. package/package.json +3 -1
  144. package/skills/myco/SKILL.md +16 -1
  145. package/skills/myco/references/cli-usage.md +1 -1
  146. package/skills/myco-curate/SKILL.md +1 -1
  147. package/dist/chunk-4YFKBL3F.js +0 -195
  148. package/dist/chunk-4YFKBL3F.js.map +0 -1
  149. package/dist/chunk-CCRGY3QW.js.map +0 -1
  150. package/dist/chunk-EVDQKYCG.js.map +0 -1
  151. package/dist/chunk-FLLBJLHM.js.map +0 -1
  152. package/dist/chunk-MYOZLMB2.js.map +0 -1
  153. package/dist/chunk-OD4AA7PV.js.map +0 -1
  154. package/dist/chunk-US4LNCAT.js.map +0 -1
  155. package/dist/chunk-UYMFCYBF.js +0 -2326
  156. package/dist/chunk-UYMFCYBF.js.map +0 -1
  157. package/dist/chunk-VVNL26WX.js.map +0 -1
  158. package/dist/cli-GGPWH4UO.js.map +0 -1
  159. package/dist/doctor-5JXJ36KA.js.map +0 -1
  160. package/dist/executor-HWW2QNZQ.js +0 -2472
  161. package/dist/executor-HWW2QNZQ.js.map +0 -1
  162. package/dist/main-YTBVRTBI.js.map +0 -1
  163. package/dist/post-tool-use-POGPTJBA.js.map +0 -1
  164. package/dist/server-AGVYZVP5.js.map +0 -1
  165. package/dist/session-start-LAFICHII.js +0 -189
  166. package/dist/session-start-LAFICHII.js.map +0 -1
  167. package/dist/src/agent/definitions/tasks/graph-maintenance.yaml +0 -93
  168. package/dist/ui/assets/index-C2JuNtRB.css +0 -1
  169. package/dist/ui/assets/index-JLVaQKV2.js +0 -832
  170. /package/dist/{chunk-DCSGJ7W4.js.map → chunk-5ZG4RMUH.js.map} +0 -0
  171. /package/dist/{chunk-JZGN33AY.js.map → chunk-75Z7UKDY.js.map} +0 -0
  172. /package/dist/{chunk-XG5RRUYF.js.map → chunk-BUTL6IFS.js.map} +0 -0
  173. /package/dist/{chunk-KESLPBKV.js.map → chunk-JR54LTPP.js.map} +0 -0
  174. /package/dist/{chunk-5XIVBO25.js.map → chunk-LVIY7P35.js.map} +0 -0
  175. /package/dist/{chunk-BPRIYNLE.js.map → chunk-TKAJ3JVF.js.map} +0 -0
  176. /package/dist/{chunk-Q36VMZST.js.map → chunk-VHNRMM4O.js.map} +0 -0
  177. /package/dist/{client-YXQUTXVZ.js.map → client-NWE4TCNO.js.map} +0 -0
  178. /package/dist/{detect-providers-5KOPZ7J2.js.map → detect-providers-ILLQZROY.js.map} +0 -0
  179. /package/dist/{installer-FS257JRZ.js.map → executor-F2YU7HXJ.js.map} +0 -0
  180. /package/dist/{llm-TH4NLIRM.js.map → installer-UMH7OJ5A.js.map} +0 -0
  181. /package/dist/{loader-CQYTFHEW.js.map → llm-AGVEF5XD.js.map} +0 -0
  182. /package/dist/{loader-NOMBJUPW.js.map → loader-LX7TFRM6.js.map} +0 -0
  183. /package/dist/{provider-check-43LAMSMH.js.map → loader-NAVVZK63.js.map} +0 -0
  184. /package/dist/{post-compact-JSECI44W.js.map → post-compact-USAODKPQ.js.map} +0 -0
  185. /package/dist/{post-tool-use-failure-OT7BFWQW.js.map → post-tool-use-failure-NZVSL2PO.js.map} +0 -0
  186. /package/dist/{pre-compact-OXVODKH4.js.map → pre-compact-LZ57DLUS.js.map} +0 -0
  187. /package/dist/{registry-U4CHXK6R.js.map → provider-check-ZEV5P4KM.js.map} +0 -0
  188. /package/dist/{team-LRZ6GTQK.js.map → registry-M2Z5QBWH.js.map} +0 -0
  189. /package/dist/{session-end-FT27DWYZ.js.map → session-end-LWJYQAXX.js.map} +0 -0
  190. /package/dist/{stop-ZPIKVLH4.js.map → stop-WRBTXEVT.js.map} +0 -0
  191. /package/dist/{stop-failure-2PX67YJC.js.map → stop-failure-32MGIG2Q.js.map} +0 -0
  192. /package/dist/{subagent-start-UUE6EHQD.js.map → subagent-start-VFGHQFVL.js.map} +0 -0
  193. /package/dist/{subagent-stop-KQWWWPE6.js.map → subagent-stop-663FXG3P.js.map} +0 -0
  194. /package/dist/{task-completed-WMHOFQ7B.js.map → task-completed-ZCQYEFMZ.js.map} +0 -0
  195. /package/dist/{turns-YFNI5CQC.js.map → team-JTI5CDUO.js.map} +0 -0
  196. /package/dist/{version-XMPPJQHR.js.map → turns-HU2CTZAP.js.map} +0 -0
@@ -1,2326 +0,0 @@
1
- import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
- import {
3
- loadAllTasks
4
- } from "./chunk-6X2ERTQV.js";
5
- import {
6
- getAgent,
7
- getDefaultTask,
8
- getTask,
9
- loadAgentDefinition,
10
- resolveDefinitionsDir,
11
- resolveEffectiveConfig
12
- } from "./chunk-CCRGY3QW.js";
13
- import {
14
- countSpores,
15
- getSpore,
16
- listSporeIdsSince,
17
- listSpores
18
- } from "./chunk-4YFKBL3F.js";
19
- import {
20
- countSessions,
21
- getSession,
22
- getTeamMachineId,
23
- listSessions,
24
- syncRow
25
- } from "./chunk-EVDQKYCG.js";
26
- import {
27
- loadMergedConfig
28
- } from "./chunk-OD4AA7PV.js";
29
- import {
30
- getDatabase
31
- } from "./chunk-MYX5NCRH.js";
32
- import {
33
- DEFAULT_LIST_LIMIT,
34
- DIGEST_TIERS,
35
- EDGE_TYPE_DERIVED_FROM,
36
- EDGE_TYPE_EXTRACTED_FROM,
37
- EDGE_TYPE_FROM_SESSION,
38
- EDGE_TYPE_HAS_BATCH,
39
- GRAPH_EDGE_DEFAULT_CONFIDENCE,
40
- QUERY_DEFAULT_LIST_LIMIT,
41
- epochSeconds
42
- } from "./chunk-FLLBJLHM.js";
43
- import {
44
- require_dist
45
- } from "./chunk-6LQIMRTC.js";
46
- import {
47
- __toESM
48
- } from "./chunk-PZUWP5VK.js";
49
-
50
- // src/notifications/notify.ts
51
- import crypto from "crypto";
52
-
53
- // src/db/queries/notifications.ts
54
- var DEFAULT_LIMIT = 50;
55
- var NOTIFICATION_PRUNE_AGE_SECONDS = 30 * 24 * 60 * 60;
56
- function insertNotification(n) {
57
- const db = getDatabase();
58
- db.prepare(
59
- `INSERT INTO notifications (id, domain, type, level, title, message, mode, status, link, metadata, created_at)
60
- VALUES (?, ?, ?, ?, ?, ?, ?, 'unread', ?, ?, ?)`
61
- ).run(n.id, n.domain, n.type, n.level, n.title, n.message, n.mode, n.link, n.metadata, epochSeconds());
62
- }
63
- function listNotifications(opts = {}) {
64
- const db = getDatabase();
65
- const conditions = [];
66
- const params = [];
67
- if (opts.status) {
68
- conditions.push("status = ?");
69
- params.push(opts.status);
70
- }
71
- if (opts.domain) {
72
- conditions.push("domain = ?");
73
- params.push(opts.domain);
74
- }
75
- if (opts.mode) {
76
- conditions.push("mode = ?");
77
- params.push(opts.mode);
78
- }
79
- const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
80
- const limit = opts.limit ?? DEFAULT_LIMIT;
81
- const offset = opts.offset ?? 0;
82
- return db.prepare(
83
- `SELECT * FROM notifications ${where} ORDER BY created_at DESC LIMIT ? OFFSET ?`
84
- ).all(...params, limit, offset);
85
- }
86
- function countNotifications(status) {
87
- const db = getDatabase();
88
- if (status) {
89
- const row2 = db.prepare("SELECT COUNT(*) as count FROM notifications WHERE status = ?").get(status);
90
- return row2.count;
91
- }
92
- const row = db.prepare("SELECT COUNT(*) as count FROM notifications").get();
93
- return row.count;
94
- }
95
- function getNotification(id) {
96
- const db = getDatabase();
97
- return db.prepare("SELECT * FROM notifications WHERE id = ?").get(id);
98
- }
99
- function updateNotificationStatus(id, status) {
100
- const db = getDatabase();
101
- const result = db.prepare("UPDATE notifications SET status = ? WHERE id = ?").run(status, id);
102
- return result.changes > 0;
103
- }
104
- function dismissAllNotifications(domain) {
105
- const db = getDatabase();
106
- if (domain) {
107
- const result2 = db.prepare("UPDATE notifications SET status = 'dismissed' WHERE domain = ? AND status != 'dismissed'").run(domain);
108
- return result2.changes;
109
- }
110
- const result = db.prepare("UPDATE notifications SET status = 'dismissed' WHERE status != 'dismissed'").run();
111
- return result.changes;
112
- }
113
- function markAllRead(domain) {
114
- const db = getDatabase();
115
- if (domain) {
116
- const result2 = db.prepare("UPDATE notifications SET status = 'read' WHERE domain = ? AND status = 'unread'").run(domain);
117
- return result2.changes;
118
- }
119
- const result = db.prepare("UPDATE notifications SET status = 'read' WHERE status = 'unread'").run();
120
- return result.changes;
121
- }
122
-
123
- // src/notifications/registry.ts
124
- var domains = /* @__PURE__ */ new Map();
125
- function register(descriptor) {
126
- domains.set(descriptor.domain, descriptor);
127
- }
128
- function getAllDomains() {
129
- return [...domains.values()].sort((a, b) => a.domain.localeCompare(b.domain));
130
- }
131
- function getType(typeId) {
132
- for (const descriptor of domains.values()) {
133
- const match = descriptor.types.find((t) => t.id === typeId);
134
- if (match) return { domain: descriptor, type: match };
135
- }
136
- return void 0;
137
- }
138
-
139
- // src/notifications/notify.ts
140
- function notify(vaultDir, payload, config) {
141
- if (!vaultDir) return null;
142
- try {
143
- const cfg = config ?? loadMergedConfig(vaultDir);
144
- if (!cfg.notifications.enabled) return null;
145
- const domainConfig = cfg.notifications.domains[payload.domain];
146
- if (domainConfig && !domainConfig.enabled) return null;
147
- const registeredType = getType(payload.type);
148
- const mode = payload.mode ?? domainConfig?.mode ?? cfg.notifications.default_mode ?? registeredType?.type.defaultMode;
149
- const level = payload.level ?? registeredType?.type.defaultLevel ?? "info";
150
- const id = crypto.randomUUID();
151
- insertNotification({
152
- id,
153
- domain: payload.domain,
154
- type: payload.type,
155
- level,
156
- title: payload.title,
157
- message: payload.message ?? null,
158
- mode,
159
- link: payload.link ?? null,
160
- metadata: payload.metadata ? JSON.stringify(payload.metadata) : null
161
- });
162
- return id;
163
- } catch (err) {
164
- console.warn("[notify] Failed to emit notification:", err instanceof Error ? err.message : err);
165
- return null;
166
- }
167
- }
168
-
169
- // src/utils/error-message.ts
170
- function errorMessage(err) {
171
- if (err instanceof Error) return err.message || err.constructor.name || "Error";
172
- if (typeof err === "string") return err || "Empty string error";
173
- try {
174
- return JSON.stringify(err);
175
- } catch {
176
- return "Unserializable error";
177
- }
178
- }
179
-
180
- // src/db/queries/runs.ts
181
- var DEFAULT_LIST_LIMIT2 = 100;
182
- var DEFAULT_STATUS = "pending";
183
- var STATUS_RUNNING = "running";
184
- var STATUS_COMPLETED = "completed";
185
- var STATUS_FAILED = "failed";
186
- var RUN_COLUMNS = [
187
- "id",
188
- "agent_id",
189
- "task",
190
- "instruction",
191
- "status",
192
- "started_at",
193
- "completed_at",
194
- "tokens_used",
195
- "cost_usd",
196
- "actions_taken",
197
- "error"
198
- ];
199
- var SELECT_COLUMNS = RUN_COLUMNS.join(", ");
200
- function toRunRow(row) {
201
- return {
202
- id: row.id,
203
- agent_id: row.agent_id,
204
- task: row.task ?? null,
205
- instruction: row.instruction ?? null,
206
- status: row.status,
207
- started_at: row.started_at ?? null,
208
- completed_at: row.completed_at ?? null,
209
- tokens_used: row.tokens_used ?? null,
210
- cost_usd: row.cost_usd ?? null,
211
- actions_taken: row.actions_taken ?? null,
212
- error: row.error ?? null
213
- };
214
- }
215
- function insertRun(data) {
216
- const db = getDatabase();
217
- db.prepare(
218
- `INSERT INTO agent_runs (
219
- id, agent_id, task, instruction, status,
220
- started_at, completed_at, tokens_used, cost_usd,
221
- actions_taken, error
222
- ) VALUES (
223
- ?, ?, ?, ?, ?,
224
- ?, ?, ?, ?,
225
- ?, ?
226
- )`
227
- ).run(
228
- data.id,
229
- data.agent_id,
230
- data.task ?? null,
231
- data.instruction ?? null,
232
- data.status ?? DEFAULT_STATUS,
233
- data.started_at ?? null,
234
- data.completed_at ?? null,
235
- data.tokens_used ?? null,
236
- data.cost_usd ?? null,
237
- data.actions_taken ?? null,
238
- data.error ?? null
239
- );
240
- return toRunRow(
241
- db.prepare(`SELECT ${SELECT_COLUMNS} FROM agent_runs WHERE id = ?`).get(data.id)
242
- );
243
- }
244
- function getRun(id) {
245
- const db = getDatabase();
246
- const row = db.prepare(
247
- `SELECT ${SELECT_COLUMNS} FROM agent_runs WHERE id = ?`
248
- ).get(id);
249
- if (!row) return null;
250
- return toRunRow(row);
251
- }
252
- function buildRunsWhere(options) {
253
- const conditions = [];
254
- const params = [];
255
- if (options.agent_id !== void 0) {
256
- conditions.push(`agent_id = ?`);
257
- params.push(options.agent_id);
258
- }
259
- if (options.status !== void 0) {
260
- conditions.push(`status = ?`);
261
- params.push(options.status);
262
- }
263
- if (options.task !== void 0) {
264
- conditions.push(`task = ?`);
265
- params.push(options.task);
266
- }
267
- if (options.search !== void 0 && options.search.length > 0) {
268
- conditions.push(`task LIKE ?`);
269
- params.push(`%${options.search}%`);
270
- }
271
- return {
272
- where: conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "",
273
- params
274
- };
275
- }
276
- function listRuns(options = {}) {
277
- const db = getDatabase();
278
- const { where, params } = buildRunsWhere(options);
279
- const limit = options.limit ?? DEFAULT_LIST_LIMIT2;
280
- const offset = options.offset ?? 0;
281
- const rows = db.prepare(
282
- `SELECT ${SELECT_COLUMNS}
283
- FROM agent_runs
284
- ${where}
285
- ORDER BY started_at DESC NULLS LAST
286
- LIMIT ?
287
- OFFSET ?`
288
- ).all(...params, limit, offset);
289
- return rows.map(toRunRow);
290
- }
291
- function countRuns(options = {}) {
292
- const db = getDatabase();
293
- const { where, params } = buildRunsWhere(options);
294
- const row = db.prepare(
295
- `SELECT COUNT(*) as count FROM agent_runs ${where}`
296
- ).get(...params);
297
- return row.count;
298
- }
299
- function updateRunStatus(id, status, completion) {
300
- const db = getDatabase();
301
- const setClauses = ["status = ?"];
302
- const params = [status];
303
- if (completion?.completed_at !== void 0) {
304
- setClauses.push(`completed_at = ?`);
305
- params.push(completion.completed_at);
306
- }
307
- if (completion?.tokens_used !== void 0) {
308
- setClauses.push(`tokens_used = ?`);
309
- params.push(completion.tokens_used);
310
- }
311
- if (completion?.cost_usd !== void 0) {
312
- setClauses.push(`cost_usd = ?`);
313
- params.push(completion.cost_usd);
314
- }
315
- if (completion?.actions_taken !== void 0) {
316
- setClauses.push(`actions_taken = ?`);
317
- params.push(completion.actions_taken);
318
- }
319
- if (completion?.error !== void 0) {
320
- setClauses.push(`error = ?`);
321
- params.push(completion.error);
322
- }
323
- params.push(id);
324
- const info = db.prepare(
325
- `UPDATE agent_runs
326
- SET ${setClauses.join(", ")}
327
- WHERE id = ?`
328
- ).run(...params);
329
- if (info.changes === 0) return null;
330
- return toRunRow(
331
- db.prepare(`SELECT ${SELECT_COLUMNS} FROM agent_runs WHERE id = ?`).get(id)
332
- );
333
- }
334
- function getRunningRunForTask(agentId, taskName) {
335
- const db = getDatabase();
336
- const row = db.prepare(
337
- `SELECT id FROM agent_runs
338
- WHERE agent_id = ? AND task = ? AND status = ?
339
- LIMIT 1`
340
- ).get(agentId, taskName, STATUS_RUNNING);
341
- return row?.id ?? null;
342
- }
343
- function getLatestRunId(agentId, taskName) {
344
- const db = getDatabase();
345
- if (taskName) {
346
- const row2 = db.prepare(
347
- `SELECT id FROM agent_runs
348
- WHERE agent_id = ? AND task = ?
349
- ORDER BY started_at DESC
350
- LIMIT 1`
351
- ).get(agentId, taskName);
352
- return row2?.id ?? null;
353
- }
354
- const row = db.prepare(
355
- `SELECT id FROM agent_runs
356
- WHERE agent_id = ?
357
- ORDER BY started_at DESC
358
- LIMIT 1`
359
- ).get(agentId);
360
- return row?.id ?? null;
361
- }
362
-
363
- // src/agent/config-resolver.ts
364
- function hasConfiguredProvider(mycoConfig, taskName) {
365
- const taskProvider = taskName ? mycoConfig.agent.tasks?.[taskName]?.provider : void 0;
366
- return !!(taskProvider ?? mycoConfig.agent.provider);
367
- }
368
- function toProviderConfig(p) {
369
- return {
370
- type: p.type,
371
- baseUrl: p.base_url,
372
- model: p.model,
373
- contextLength: p.context_length
374
- };
375
- }
376
- function resolveRunConfig(agentId, requestedTask, vaultDir) {
377
- const definitionsDir = resolveDefinitionsDir();
378
- const definition = loadAgentDefinition(definitionsDir);
379
- const agentRow = getAgent(agentId);
380
- const taskRow = requestedTask ? getTask(requestedTask) : getDefaultTask(agentId);
381
- const allTasks = loadAllTasks(definitionsDir, vaultDir);
382
- const taskName = taskRow?.id ?? requestedTask;
383
- const yamlTask = taskName ? allTasks.get(taskName) : void 0;
384
- const taskOverrides = taskRow ? {
385
- name: taskRow.id,
386
- displayName: taskRow.display_name ?? taskRow.id,
387
- description: taskRow.description ?? "",
388
- agent: taskRow.agent_id,
389
- prompt: taskRow.prompt,
390
- isDefault: taskRow.is_default === 1,
391
- ...taskRow.tool_overrides ? { toolOverrides: JSON.parse(taskRow.tool_overrides) } : {},
392
- // Scalar config from YAML (model, turns, timeout) — DB doesn't store these
393
- ...yamlTask?.model ? { model: yamlTask.model } : {},
394
- ...yamlTask?.maxTurns ? { maxTurns: yamlTask.maxTurns } : {},
395
- ...yamlTask?.timeoutSeconds ? { timeoutSeconds: yamlTask.timeoutSeconds } : {},
396
- // Structural config from YAML
397
- ...yamlTask?.phases ? { phases: yamlTask.phases } : {},
398
- ...yamlTask?.execution ? { execution: yamlTask.execution } : {},
399
- ...yamlTask?.contextQueries ? { contextQueries: yamlTask.contextQueries } : {},
400
- ...yamlTask?.orchestrator ? { orchestrator: yamlTask.orchestrator } : {}
401
- } : void 0;
402
- const config = resolveEffectiveConfig(definition, agentRow, taskOverrides);
403
- let taskProviderOverride;
404
- let phaseProviderOverrides = {};
405
- let taskParams;
406
- try {
407
- const mycoConfig = loadMergedConfig(vaultDir);
408
- const taskConfig = taskName ? mycoConfig.agent.tasks?.[taskName] : void 0;
409
- const globalProvider = mycoConfig.agent.provider;
410
- if (taskConfig?.provider) {
411
- taskProviderOverride = toProviderConfig(taskConfig.provider);
412
- } else if (globalProvider) {
413
- taskProviderOverride = toProviderConfig(globalProvider);
414
- }
415
- if (taskConfig?.phases) {
416
- for (const [phaseName, phaseConfig] of Object.entries(taskConfig.phases)) {
417
- phaseProviderOverrides[phaseName] = {
418
- ...phaseConfig.provider ? { provider: toProviderConfig(phaseConfig.provider) } : {},
419
- ...phaseConfig.maxTurns != null ? { maxTurns: phaseConfig.maxTurns } : {}
420
- };
421
- }
422
- }
423
- const yamlParams = yamlTask?.params;
424
- const configParams = taskConfig?.params;
425
- if (yamlParams || configParams) {
426
- taskParams = { ...yamlParams, ...configParams };
427
- }
428
- } catch {
429
- }
430
- return {
431
- config,
432
- definitionsDir,
433
- taskProviderOverride,
434
- phaseProviderOverrides,
435
- taskName,
436
- taskParams
437
- };
438
- }
439
-
440
- // src/agent/instruction-builders.ts
441
- import { readFileSync } from "fs";
442
- import { resolve } from "path";
443
-
444
- // src/db/queries/skill-candidates.ts
445
- var DEFAULT_CONFIDENCE = 0;
446
- var DEFAULT_STATUS2 = "identified";
447
- var CANDIDATE_COLUMNS = [
448
- "id",
449
- "agent_id",
450
- "machine_id",
451
- "topic",
452
- "rationale",
453
- "confidence",
454
- "status",
455
- "source_ids",
456
- "skill_id",
457
- "supersedes",
458
- "approved_at",
459
- "created_at",
460
- "updated_at",
461
- "synced_at"
462
- ];
463
- var SELECT_COLUMNS2 = CANDIDATE_COLUMNS.join(", ");
464
- function toCandidateRow(row) {
465
- return {
466
- id: row.id,
467
- agent_id: row.agent_id,
468
- machine_id: row.machine_id ?? getTeamMachineId(),
469
- topic: row.topic,
470
- rationale: row.rationale,
471
- confidence: row.confidence,
472
- status: row.status,
473
- source_ids: row.source_ids ?? "[]",
474
- skill_id: row.skill_id ?? null,
475
- supersedes: row.supersedes ?? null,
476
- approved_at: row.approved_at ?? null,
477
- created_at: row.created_at,
478
- updated_at: row.updated_at,
479
- synced_at: row.synced_at ?? null
480
- };
481
- }
482
- function buildWhere(options) {
483
- const conditions = [];
484
- const params = [];
485
- if (options.agent_id !== void 0) {
486
- conditions.push(`agent_id = ?`);
487
- params.push(options.agent_id);
488
- }
489
- if (options.statuses !== void 0 && options.statuses.length > 0) {
490
- const placeholders = options.statuses.map(() => "?").join(", ");
491
- conditions.push(`status IN (${placeholders})`);
492
- params.push(...options.statuses);
493
- } else if (options.status !== void 0) {
494
- conditions.push(`status = ?`);
495
- params.push(options.status);
496
- }
497
- return {
498
- where: conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "",
499
- params
500
- };
501
- }
502
- function insertCandidate(data) {
503
- const db = getDatabase();
504
- db.prepare(
505
- `INSERT INTO skill_candidates (
506
- id, agent_id, machine_id, topic, rationale,
507
- confidence, status, source_ids, skill_id, supersedes, approved_at,
508
- created_at, updated_at
509
- ) VALUES (
510
- ?, ?, ?, ?, ?,
511
- ?, ?, ?, ?, ?, ?,
512
- ?, ?
513
- )`
514
- ).run(
515
- data.id,
516
- data.agent_id,
517
- data.machine_id ?? getTeamMachineId(),
518
- data.topic,
519
- data.rationale,
520
- data.confidence ?? DEFAULT_CONFIDENCE,
521
- data.status ?? DEFAULT_STATUS2,
522
- data.source_ids ?? "[]",
523
- data.skill_id ?? null,
524
- data.supersedes ?? null,
525
- data.approved_at ?? null,
526
- data.created_at,
527
- data.updated_at
528
- );
529
- const raw = db.prepare(`SELECT ${SELECT_COLUMNS2} FROM skill_candidates WHERE id = ?`).get(data.id);
530
- if (!raw) throw new Error(`Failed to insert skill candidate: ${data.id}`);
531
- const row = toCandidateRow(raw);
532
- syncRow("skill_candidates", row);
533
- return row;
534
- }
535
- function getCandidate(id) {
536
- const db = getDatabase();
537
- const row = db.prepare(
538
- `SELECT ${SELECT_COLUMNS2} FROM skill_candidates WHERE id = ?`
539
- ).get(id);
540
- if (!row) return null;
541
- return toCandidateRow(row);
542
- }
543
- function listCandidates(options = {}) {
544
- const db = getDatabase();
545
- const { where, params } = buildWhere(options);
546
- const limit = options.limit ?? DEFAULT_LIST_LIMIT;
547
- const offset = options.offset ?? 0;
548
- const rows = db.prepare(
549
- `SELECT ${SELECT_COLUMNS2}
550
- FROM skill_candidates
551
- ${where}
552
- ORDER BY confidence DESC, created_at DESC
553
- LIMIT ?
554
- OFFSET ?`
555
- ).all(...params, limit, offset);
556
- return rows.map(toCandidateRow);
557
- }
558
- function updateCandidate(id, updates) {
559
- const db = getDatabase();
560
- let autoApprovedAt;
561
- if (updates.status === "approved" && updates.approved_at === void 0) {
562
- const existing = getCandidate(id);
563
- if (existing && existing.approved_at === null) {
564
- autoApprovedAt = updates.updated_at;
565
- }
566
- }
567
- const fieldMap = {
568
- topic: "topic",
569
- rationale: "rationale",
570
- confidence: "confidence",
571
- status: "status",
572
- source_ids: "source_ids",
573
- skill_id: "skill_id",
574
- supersedes: "supersedes",
575
- approved_at: "approved_at",
576
- updated_at: "updated_at"
577
- };
578
- const setClauses = [];
579
- const params = [];
580
- const updateValues = updates;
581
- for (const [key, column] of Object.entries(fieldMap)) {
582
- if (key in updates) {
583
- setClauses.push(`${column} = ?`);
584
- params.push(updateValues[key] ?? null);
585
- } else if (key === "approved_at" && autoApprovedAt !== void 0) {
586
- setClauses.push(`${column} = ?`);
587
- params.push(autoApprovedAt);
588
- }
589
- }
590
- if (setClauses.length === 0) return getCandidate(id);
591
- params.push(id);
592
- db.prepare(
593
- `UPDATE skill_candidates
594
- SET ${setClauses.join(", ")}
595
- WHERE id = ?`
596
- ).run(...params);
597
- const updated = getCandidate(id);
598
- if (updated) syncRow("skill_candidates", updated);
599
- return updated;
600
- }
601
- function listCandidatesWithCount(options = {}) {
602
- const db = getDatabase();
603
- const { where, params } = buildWhere(options);
604
- const limit = options.limit ?? DEFAULT_LIST_LIMIT;
605
- const offset = options.offset ?? 0;
606
- const rows = db.prepare(
607
- `SELECT ${SELECT_COLUMNS2}, COUNT(*) OVER () AS __total
608
- FROM skill_candidates
609
- ${where}
610
- ORDER BY confidence DESC, created_at DESC
611
- LIMIT ?
612
- OFFSET ?`
613
- ).all(...params, limit, offset);
614
- if (rows.length === 0) {
615
- return { items: [], total: countCandidates(options) };
616
- }
617
- const total = Number(rows[0].__total);
618
- const items = rows.map((row) => {
619
- const { __total: _drop, ...rest } = row;
620
- return toCandidateRow(rest);
621
- });
622
- return { items, total };
623
- }
624
- function countCandidates(options = {}) {
625
- const db = getDatabase();
626
- const { where, params } = buildWhere(options);
627
- const row = db.prepare(
628
- `SELECT COUNT(*) as count FROM skill_candidates ${where}`
629
- ).get(...params);
630
- return row.count;
631
- }
632
- function deleteCandidate(id) {
633
- const db = getDatabase();
634
- const info = db.prepare("DELETE FROM skill_candidates WHERE id = ?").run(id);
635
- return info.changes > 0;
636
- }
637
-
638
- // src/db/queries/skill-records.ts
639
- var DEFAULT_STATUS3 = "active";
640
- var DEFAULT_GENERATION = 1;
641
- var RECORD_COLUMNS = [
642
- "id",
643
- "agent_id",
644
- "machine_id",
645
- "name",
646
- "display_name",
647
- "description",
648
- "status",
649
- "generation",
650
- "candidate_id",
651
- "source_ids",
652
- "path",
653
- "usage_count",
654
- "last_used_at",
655
- "created_at",
656
- "updated_at",
657
- "properties",
658
- "synced_at"
659
- ];
660
- var SELECT_COLUMNS3 = RECORD_COLUMNS.join(", ");
661
- function toSkillRecordRow(row) {
662
- return {
663
- id: row.id,
664
- agent_id: row.agent_id,
665
- machine_id: row.machine_id ?? getTeamMachineId(),
666
- name: row.name,
667
- display_name: row.display_name,
668
- description: row.description,
669
- status: row.status,
670
- generation: row.generation,
671
- candidate_id: row.candidate_id ?? null,
672
- source_ids: row.source_ids ?? "[]",
673
- path: row.path,
674
- usage_count: row.usage_count,
675
- last_used_at: row.last_used_at ?? null,
676
- created_at: row.created_at,
677
- updated_at: row.updated_at,
678
- properties: row.properties ?? "{}",
679
- synced_at: row.synced_at ?? null
680
- };
681
- }
682
- function buildWhere2(options) {
683
- const conditions = [];
684
- const params = [];
685
- if (options.agent_id !== void 0) {
686
- conditions.push(`agent_id = ?`);
687
- params.push(options.agent_id);
688
- }
689
- if (options.status !== void 0) {
690
- conditions.push(`status = ?`);
691
- params.push(options.status);
692
- }
693
- return {
694
- where: conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "",
695
- params
696
- };
697
- }
698
- function insertSkillRecord(data) {
699
- const db = getDatabase();
700
- db.prepare(
701
- `INSERT INTO skill_records (
702
- id, agent_id, machine_id, name, display_name,
703
- description, status, generation, candidate_id,
704
- source_ids, path, created_at, updated_at, properties
705
- ) VALUES (
706
- ?, ?, ?, ?, ?,
707
- ?, ?, ?, ?,
708
- ?, ?, ?, ?, ?
709
- )`
710
- ).run(
711
- data.id,
712
- data.agent_id,
713
- data.machine_id ?? getTeamMachineId(),
714
- data.name,
715
- data.display_name,
716
- data.description,
717
- data.status ?? DEFAULT_STATUS3,
718
- data.generation ?? DEFAULT_GENERATION,
719
- data.candidate_id ?? null,
720
- data.source_ids ?? "[]",
721
- data.path,
722
- data.created_at,
723
- data.updated_at,
724
- data.properties ?? "{}"
725
- );
726
- const raw = db.prepare(`SELECT ${SELECT_COLUMNS3} FROM skill_records WHERE id = ?`).get(data.id);
727
- if (!raw) throw new Error(`Failed to insert skill record: ${data.id}`);
728
- const row = toSkillRecordRow(raw);
729
- syncRow("skill_records", row);
730
- return row;
731
- }
732
- function getSkillRecord(id) {
733
- const db = getDatabase();
734
- const row = db.prepare(
735
- `SELECT ${SELECT_COLUMNS3} FROM skill_records WHERE id = ?`
736
- ).get(id);
737
- if (!row) return null;
738
- return toSkillRecordRow(row);
739
- }
740
- function getSkillRecordByName(name) {
741
- const db = getDatabase();
742
- const row = db.prepare(
743
- `SELECT ${SELECT_COLUMNS3} FROM skill_records WHERE name = ?`
744
- ).get(name);
745
- if (!row) return null;
746
- return toSkillRecordRow(row);
747
- }
748
- function listSkillRecords(options = {}) {
749
- const db = getDatabase();
750
- const { where, params } = buildWhere2(options);
751
- const limit = options.limit ?? DEFAULT_LIST_LIMIT;
752
- const offset = options.offset ?? 0;
753
- const rows = db.prepare(
754
- `SELECT ${SELECT_COLUMNS3}
755
- FROM skill_records
756
- ${where}
757
- ORDER BY updated_at DESC
758
- LIMIT ?
759
- OFFSET ?`
760
- ).all(...params, limit, offset);
761
- return rows.map(toSkillRecordRow);
762
- }
763
- function updateSkillRecord(id, updates) {
764
- const db = getDatabase();
765
- const setClauses = [];
766
- const params = [];
767
- const fieldMap = {
768
- display_name: "display_name",
769
- description: "description",
770
- status: "status",
771
- generation: "generation",
772
- source_ids: "source_ids",
773
- path: "path",
774
- usage_count: "usage_count",
775
- last_used_at: "last_used_at",
776
- updated_at: "updated_at",
777
- properties: "properties"
778
- };
779
- for (const [key, column] of Object.entries(fieldMap)) {
780
- if (key in updates) {
781
- setClauses.push(`${column} = ?`);
782
- params.push(updates[key] ?? null);
783
- }
784
- }
785
- if (setClauses.length === 0) return getSkillRecord(id);
786
- params.push(id);
787
- db.prepare(
788
- `UPDATE skill_records
789
- SET ${setClauses.join(", ")}
790
- WHERE id = ?`
791
- ).run(...params);
792
- const updated = getSkillRecord(id);
793
- if (updated) syncRow("skill_records", updated);
794
- return updated;
795
- }
796
- function incrementSkillUsageCount(id, now) {
797
- const db = getDatabase();
798
- db.prepare(
799
- `UPDATE skill_records SET usage_count = usage_count + 1, last_used_at = ?, updated_at = ? WHERE id = ?`
800
- ).run(now, now, id);
801
- }
802
- function listSkillRecordsWithCount(options = {}) {
803
- const items = listSkillRecords(options);
804
- const total = countSkillRecords(options);
805
- return { items, total };
806
- }
807
- function countSkillRecords(options = {}) {
808
- const db = getDatabase();
809
- const { where, params } = buildWhere2(options);
810
- const row = db.prepare(
811
- `SELECT COUNT(*) as count FROM skill_records ${where}`
812
- ).get(...params);
813
- return row.count;
814
- }
815
- function deleteSkillRecordCascade(idOrName) {
816
- const db = getDatabase();
817
- const record = getSkillRecord(idOrName) ?? getSkillRecordByName(idOrName);
818
- if (!record) return null;
819
- db.transaction(() => {
820
- db.prepare("DELETE FROM skill_lineage WHERE skill_id = ?").run(record.id);
821
- db.prepare("DELETE FROM skill_usage WHERE skill_id = ?").run(record.id);
822
- if (record.candidate_id) {
823
- db.prepare(
824
- `UPDATE skill_candidates SET status = 'dismissed', skill_id = NULL, updated_at = ? WHERE id = ?`
825
- ).run(Math.floor(Date.now() / 1e3), record.candidate_id);
826
- }
827
- db.prepare(
828
- `UPDATE skill_candidates SET status = 'dismissed', skill_id = NULL, updated_at = ? WHERE skill_id = ?`
829
- ).run(Math.floor(Date.now() / 1e3), record.id);
830
- db.prepare("DELETE FROM skill_records WHERE id = ?").run(record.id);
831
- })();
832
- return { id: record.id, name: record.name };
833
- }
834
-
835
- // src/db/queries/digest-extracts.ts
836
- var EXTRACT_COLUMNS = [
837
- "id",
838
- "agent_id",
839
- "tier",
840
- "content",
841
- "substrate_hash",
842
- "generated_at",
843
- "machine_id",
844
- "synced_at"
845
- ];
846
- var SELECT_COLUMNS4 = EXTRACT_COLUMNS.join(", ");
847
- function toDigestExtractRow(row) {
848
- return {
849
- id: row.id,
850
- agent_id: row.agent_id,
851
- tier: row.tier,
852
- content: row.content,
853
- substrate_hash: row.substrate_hash ?? null,
854
- generated_at: row.generated_at,
855
- machine_id: row.machine_id ?? "local",
856
- synced_at: row.synced_at ?? null
857
- };
858
- }
859
- function upsertDigestExtract(data) {
860
- const db = getDatabase();
861
- db.prepare(
862
- `INSERT INTO digest_extracts (agent_id, tier, content, generated_at)
863
- VALUES (?, ?, ?, ?)
864
- ON CONFLICT (agent_id, tier) DO UPDATE SET
865
- content = EXCLUDED.content,
866
- generated_at = EXCLUDED.generated_at`
867
- ).run(data.agent_id, data.tier, data.content, data.generated_at);
868
- const row = db.prepare(
869
- `SELECT ${SELECT_COLUMNS4} FROM digest_extracts WHERE agent_id = ? AND tier = ?`
870
- ).get(data.agent_id, data.tier);
871
- return toDigestExtractRow(row);
872
- }
873
- function getDigestExtract(agentId, tier) {
874
- const db = getDatabase();
875
- const row = db.prepare(
876
- `SELECT ${SELECT_COLUMNS4} FROM digest_extracts
877
- WHERE agent_id = ? AND tier = ?`
878
- ).get(agentId, tier);
879
- if (!row) return null;
880
- return toDigestExtractRow(row);
881
- }
882
- function listDigestExtracts(agentId) {
883
- const db = getDatabase();
884
- const tierPlaceholders = DIGEST_TIERS.map(() => "?").join(", ");
885
- const rows = db.prepare(
886
- `SELECT ${SELECT_COLUMNS4}
887
- FROM digest_extracts
888
- WHERE agent_id = ? AND tier IN (${tierPlaceholders})
889
- ORDER BY tier ASC`
890
- ).all(agentId, ...DIGEST_TIERS);
891
- return rows.map(toDigestExtractRow);
892
- }
893
-
894
- // src/db/queries/agent-state.ts
895
- var STATE_COLUMNS = [
896
- "agent_id",
897
- "key",
898
- "value",
899
- "updated_at"
900
- ];
901
- var SELECT_COLUMNS5 = STATE_COLUMNS.join(", ");
902
- function toAgentStateRow(row) {
903
- return {
904
- agent_id: row.agent_id,
905
- key: row.key,
906
- value: row.value,
907
- updated_at: row.updated_at
908
- };
909
- }
910
- function getState(agentId, key) {
911
- const db = getDatabase();
912
- const row = db.prepare(
913
- `SELECT ${SELECT_COLUMNS5} FROM agent_state WHERE agent_id = ? AND key = ?`
914
- ).get(agentId, key);
915
- if (!row) return null;
916
- return toAgentStateRow(row);
917
- }
918
- function setState(agentId, key, value, updatedAt) {
919
- const db = getDatabase();
920
- db.prepare(
921
- `INSERT INTO agent_state (agent_id, key, value, updated_at)
922
- VALUES (?, ?, ?, ?)
923
- ON CONFLICT (agent_id, key) DO UPDATE SET
924
- value = EXCLUDED.value,
925
- updated_at = EXCLUDED.updated_at`
926
- ).run(agentId, key, value, updatedAt);
927
- return toAgentStateRow(
928
- db.prepare(`SELECT ${SELECT_COLUMNS5} FROM agent_state WHERE agent_id = ? AND key = ?`).get(agentId, key)
929
- );
930
- }
931
- function getStatesForAgent(agentId) {
932
- const db = getDatabase();
933
- const rows = db.prepare(
934
- `SELECT ${SELECT_COLUMNS5}
935
- FROM agent_state
936
- WHERE agent_id = ?
937
- ORDER BY key ASC`
938
- ).all(agentId);
939
- return rows.map(toAgentStateRow);
940
- }
941
-
942
- // src/agent/tools/skill-validator.ts
943
- var import_yaml = __toESM(require_dist(), 1);
944
- var MAX_SKILL_LINES = 800;
945
- var MAX_SKILL_DESCRIPTION_CHARS = 1024;
946
- var FRONTMATTER_PATTERN = /^---\n([\s\S]*?)\n---/;
947
- var REQUIRED_FRONTMATTER_FIELDS = ["name", "description", "managed_by", "user-invocable", "allowed-tools"];
948
- var PROTECTED_FRONTMATTER_FIELDS = ["user-invocable", "allowed-tools"];
949
- var ALLOWED_CLAUDE_CODE_TOOLS = /* @__PURE__ */ new Set([
950
- "Read",
951
- "Edit",
952
- "Write",
953
- "MultiEdit",
954
- "Bash",
955
- "Grep",
956
- "Glob",
957
- "NotebookRead",
958
- "NotebookEdit",
959
- "WebFetch",
960
- "WebSearch",
961
- "Task",
962
- "TodoWrite"
963
- ]);
964
- function extractFrontmatterBlock(content) {
965
- return content.match(FRONTMATTER_PATTERN)?.[1];
966
- }
967
- function parseFrontmatter(content) {
968
- const block = extractFrontmatterBlock(content);
969
- if (!block) return null;
970
- const parsed = (0, import_yaml.parse)(block);
971
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
972
- return null;
973
- }
974
- return parsed;
975
- }
976
- function normalizeFrontmatterValue(value) {
977
- if (typeof value === "string") return value;
978
- if (typeof value === "boolean" || typeof value === "number") return String(value);
979
- if (Array.isArray(value)) {
980
- const items = value.map((item) => typeof item === "string" ? item : null).filter((item) => item !== null);
981
- return items.length > 0 ? items.join(", ") : void 0;
982
- }
983
- return void 0;
984
- }
985
- function extractFrontmatterField(content, field) {
986
- try {
987
- const parsed = parseFrontmatter(content);
988
- const normalized = normalizeFrontmatterValue(parsed?.[field]);
989
- if (normalized !== void 0) return normalized;
990
- } catch {
991
- }
992
- const fm = extractFrontmatterBlock(content);
993
- if (!fm) return void 0;
994
- const match = fm.match(new RegExp(`^${field}:\\s*(.+)$`, "m"));
995
- if (match) return match[1].trim();
996
- const blockMatch = fm.match(new RegExp(`^${field}:\\s*$`, "m"));
997
- if (blockMatch) {
998
- const startIdx = fm.indexOf(blockMatch[0]) + blockMatch[0].length;
999
- const remaining = fm.slice(startIdx);
1000
- const items = [];
1001
- for (const line of remaining.split("\n")) {
1002
- const itemMatch = line.match(/^\s+-\s+(.+)$/);
1003
- if (!itemMatch) break;
1004
- items.push(itemMatch[1].trim());
1005
- }
1006
- if (items.length > 0) return items.join(", ");
1007
- }
1008
- return void 0;
1009
- }
1010
- function parseAllowedTools(rawValue) {
1011
- if (!rawValue) return null;
1012
- let stripped = rawValue.trim();
1013
- if (stripped.length === 0) return null;
1014
- if (stripped.startsWith("[") && stripped.endsWith("]")) {
1015
- stripped = stripped.slice(1, -1).trim();
1016
- }
1017
- if (stripped.length === 0) return null;
1018
- const parts = stripped.split(",").map((s) => s.trim().replace(/^['"]|['"]$/g, "")).filter((s) => s.length > 0);
1019
- if (parts.length === 0) return null;
1020
- const sentinels = /* @__PURE__ */ new Set(["None", "none", "null", "Null", "~"]);
1021
- if (parts.some((p) => sentinels.has(p))) return null;
1022
- return parts;
1023
- }
1024
- function stemToken(word) {
1025
- let w = word;
1026
- if (w.length > 5 && w.endsWith("ing")) w = w.slice(0, -3);
1027
- else if (w.length > 5 && w.endsWith("ed")) w = w.slice(0, -2);
1028
- if (w.length > 4 && w.endsWith("s")) w = w.slice(0, -1);
1029
- if (w.length > 4 && w.endsWith("e")) w = w.slice(0, -1);
1030
- return w;
1031
- }
1032
- var STOPWORDS = /* @__PURE__ */ new Set([
1033
- "the",
1034
- "a",
1035
- "an",
1036
- "and",
1037
- "or",
1038
- "but",
1039
- "is",
1040
- "are",
1041
- "was",
1042
- "were",
1043
- "be",
1044
- "been",
1045
- "being",
1046
- "have",
1047
- "has",
1048
- "had",
1049
- "do",
1050
- "does",
1051
- "did",
1052
- "will",
1053
- "would",
1054
- "should",
1055
- "could",
1056
- "may",
1057
- "might",
1058
- "must",
1059
- "can",
1060
- "this",
1061
- "that",
1062
- "these",
1063
- "those",
1064
- "with",
1065
- "from",
1066
- "into",
1067
- "onto",
1068
- "for",
1069
- "when",
1070
- "where",
1071
- "which",
1072
- "what",
1073
- "who",
1074
- "how",
1075
- "why",
1076
- "use",
1077
- "uses",
1078
- "used",
1079
- "using",
1080
- "not",
1081
- "also",
1082
- "than",
1083
- "then",
1084
- "ensure",
1085
- "ensures",
1086
- "make",
1087
- "makes"
1088
- ]);
1089
- function tokenSet(text) {
1090
- return new Set(
1091
- text.toLowerCase().replace(/[^a-z0-9_\s]/g, " ").split(/\s+/).filter((w) => w.length >= 4 && !STOPWORDS.has(w)).map(stemToken)
1092
- );
1093
- }
1094
- function intersectionSize(a, b) {
1095
- let count = 0;
1096
- for (const token of a) {
1097
- if (b.has(token)) count++;
1098
- }
1099
- return count;
1100
- }
1101
- function descriptionSimilarity(a, b) {
1102
- const aTokens = tokenSet(a);
1103
- const bTokens = tokenSet(b);
1104
- if (aTokens.size === 0 || bTokens.size === 0) return 0;
1105
- const intersection = intersectionSize(aTokens, bTokens);
1106
- const union = aTokens.size + bTokens.size - intersection;
1107
- return union === 0 ? 0 : intersection / union;
1108
- }
1109
- function topicOverlapSimilarity(a, b, minTokens = 3) {
1110
- const aTokens = tokenSet(a);
1111
- const bTokens = tokenSet(b);
1112
- if (aTokens.size < minTokens || bTokens.size < minTokens) return 0;
1113
- const intersection = intersectionSize(aTokens, bTokens);
1114
- const smaller = Math.min(aTokens.size, bTokens.size);
1115
- return smaller === 0 ? 0 : intersection / smaller;
1116
- }
1117
- var DESCRIPTION_DUPLICATE_THRESHOLD = 0.4;
1118
- var TOPIC_OVERLAP_THRESHOLD = 0.6;
1119
- function checkFrontmatterPreservation(existing, incoming) {
1120
- const violations = [];
1121
- for (const field of PROTECTED_FRONTMATTER_FIELDS) {
1122
- const oldValue = extractFrontmatterField(existing, field);
1123
- const newValue = extractFrontmatterField(incoming, field);
1124
- if (oldValue === void 0 || newValue === void 0) continue;
1125
- if (field === "allowed-tools") {
1126
- const oldParsed = parseAllowedTools(oldValue);
1127
- const newParsed = parseAllowedTools(newValue);
1128
- if (oldParsed && newParsed) {
1129
- const oldSet = new Set(oldParsed);
1130
- const newSet = new Set(newParsed);
1131
- const changed = oldSet.size !== newSet.size || [...oldSet].some((t) => !newSet.has(t));
1132
- if (changed) {
1133
- violations.push(`${field}: was [${oldParsed.join(", ")}], changed to [${newParsed.join(", ")}]`);
1134
- }
1135
- continue;
1136
- }
1137
- }
1138
- if (oldValue !== newValue) {
1139
- violations.push(`${field}: was "${oldValue}", changed to "${newValue}"`);
1140
- }
1141
- }
1142
- const oldDesc = extractFrontmatterField(existing, "description");
1143
- const newDesc = extractFrontmatterField(incoming, "description");
1144
- if (oldDesc && newDesc && newDesc.length < oldDesc.length * 0.9) {
1145
- violations.push(
1146
- `description shortened from ${oldDesc.length} to ${newDesc.length} chars (${Math.round((1 - newDesc.length / oldDesc.length) * 100)}% reduction). Descriptions are the primary triggering mechanism \u2014 do not shorten them.`
1147
- );
1148
- }
1149
- return violations;
1150
- }
1151
- function validateSkillContent(content, dirName) {
1152
- const issues = [];
1153
- const frontmatter = extractFrontmatterBlock(content);
1154
- if (!frontmatter) {
1155
- issues.push("Missing YAML frontmatter (must start with --- and end with ---)");
1156
- return issues;
1157
- }
1158
- let parsedFrontmatter = null;
1159
- try {
1160
- parsedFrontmatter = parseFrontmatter(content);
1161
- } catch (error) {
1162
- const message = error instanceof Error ? error.message.split("\n")[0] : String(error);
1163
- issues.push(`Invalid YAML frontmatter: ${message}`);
1164
- return issues;
1165
- }
1166
- if (!parsedFrontmatter) {
1167
- issues.push("Invalid YAML frontmatter: top-level frontmatter must be a mapping/object");
1168
- return issues;
1169
- }
1170
- for (const field of REQUIRED_FRONTMATTER_FIELDS) {
1171
- if (!(field in parsedFrontmatter)) {
1172
- issues.push(`Missing required frontmatter field: ${field}`);
1173
- }
1174
- }
1175
- const nameValue = normalizeFrontmatterValue(parsedFrontmatter.name);
1176
- if (nameValue && !nameValue.startsWith("myco:")) {
1177
- issues.push(`Skill name must start with "myco:" prefix. Got: "${nameValue}"`);
1178
- }
1179
- if (nameValue && nameValue !== `myco:${dirName}`) {
1180
- issues.push(`Skill name must match directory name. Expected "myco:${dirName}", got "${nameValue}"`);
1181
- }
1182
- const managedByValue = normalizeFrontmatterValue(parsedFrontmatter.managed_by);
1183
- if (managedByValue && managedByValue !== "myco") {
1184
- issues.push(`managed_by must be "myco". Got: "${managedByValue}"`);
1185
- }
1186
- const descriptionValue = normalizeFrontmatterValue(parsedFrontmatter.description);
1187
- if (descriptionValue && descriptionValue.length > MAX_SKILL_DESCRIPTION_CHARS) {
1188
- issues.push(
1189
- `description exceeds maximum length of ${MAX_SKILL_DESCRIPTION_CHARS} characters (got ${descriptionValue.length})`
1190
- );
1191
- }
1192
- const rawAllowedTools = normalizeFrontmatterValue(parsedFrontmatter["allowed-tools"]);
1193
- if (rawAllowedTools) {
1194
- const rawValue = rawAllowedTools;
1195
- if (rawValue.includes("vault_")) {
1196
- issues.push(
1197
- "allowed-tools contains vault agent tool names (vault_*). Skills run in Claude Code sessions -- use Claude Code tool names instead: Read, Edit, Write, Bash, Grep, Glob"
1198
- );
1199
- } else {
1200
- const parsed = parseAllowedTools(rawValue);
1201
- if (parsed === null) {
1202
- issues.push(
1203
- `allowed-tools value is malformed or empty: "${rawValue}". Provide a comma-separated list of Claude Code tools, e.g. "Read, Edit, Write, Bash, Grep, Glob". Use the narrowest set the skill actually needs.`
1204
- );
1205
- } else {
1206
- const unknown = parsed.filter((t) => !ALLOWED_CLAUDE_CODE_TOOLS.has(t));
1207
- if (unknown.length > 0) {
1208
- issues.push(
1209
- `allowed-tools contains unknown tool name(s): ${unknown.join(", ")}. Valid Claude Code tools: ${[...ALLOWED_CLAUDE_CODE_TOOLS].join(", ")}.`
1210
- );
1211
- }
1212
- }
1213
- }
1214
- }
1215
- const listToolLines = frontmatter.match(/^\s+-\s+vault_\w+/gm);
1216
- if (listToolLines) {
1217
- issues.push(
1218
- "allowed-tools contains vault agent tool names (vault_*). Skills run in Claude Code sessions -- use Claude Code tool names instead: Read, Edit, Write, Bash, Grep, Glob"
1219
- );
1220
- }
1221
- const lineCount = content.split("\n").length;
1222
- if (lineCount > MAX_SKILL_LINES) {
1223
- issues.push(`Skill is ${lineCount} lines (max ${MAX_SKILL_LINES})`);
1224
- }
1225
- return issues;
1226
- }
1227
-
1228
- // src/agent/instruction-builders.ts
1229
- var SKILL_GENERATE_TASK = "skill-generate";
1230
- var SKILL_EVOLVE_TASK = "skill-evolve";
1231
- var SKILL_SURVEY_TASK = "skill-survey";
1232
- var SURVEY_MAX_WISDOM_SPORES = 30;
1233
- var SURVEY_MAX_SESSIONS = 15;
1234
- var SURVEY_MIN_SETTLED_SESSIONS = 2;
1235
- var SURVEY_MIN_SETTLED_ACTIVE_SPORES = 3;
1236
- var SURVEY_WATERMARK_KEY = "skill-survey-watermark";
1237
- function getSkillSurveyEligibility(agentId) {
1238
- const settledSessionCount = countSessions({ includeActive: false });
1239
- if (settledSessionCount < SURVEY_MIN_SETTLED_SESSIONS) {
1240
- return { eligible: false, reason: "insufficient-settled-sessions" };
1241
- }
1242
- const settledSporeCount = countSpores({ includeActive: false, status: "active" });
1243
- if (settledSporeCount < SURVEY_MIN_SETTLED_ACTIVE_SPORES) {
1244
- return { eligible: false, reason: "insufficient-settled-spores" };
1245
- }
1246
- if (!agentId) {
1247
- return { eligible: true, reason: null };
1248
- }
1249
- const watermarkState = getState(agentId, SURVEY_WATERMARK_KEY);
1250
- const watermarkEpoch = watermarkState ? Number(watermarkState.value) : 0;
1251
- if (watermarkEpoch <= 0) {
1252
- return { eligible: true, reason: null };
1253
- }
1254
- const hasNewSettledSessions = countSessions({
1255
- includeActive: false,
1256
- since: watermarkEpoch
1257
- }) > 0;
1258
- if (hasNewSettledSessions) {
1259
- return { eligible: true, reason: null };
1260
- }
1261
- const hasNewSettledSpores = countSpores({
1262
- includeActive: false,
1263
- status: "active",
1264
- since: watermarkEpoch
1265
- }) > 0;
1266
- if (hasNewSettledSpores) {
1267
- return { eligible: true, reason: null };
1268
- }
1269
- return { eligible: false, reason: "no-new-settled-knowledge" };
1270
- }
1271
- function buildSkillGenerateInstruction() {
1272
- const candidates = listCandidates({ status: "approved", limit: 1 });
1273
- if (candidates.length === 0) return void 0;
1274
- const c = candidates[0];
1275
- const parts = [
1276
- `candidate_id: ${c.id}`,
1277
- `topic: ${c.topic}`,
1278
- `confidence: ${c.confidence}`,
1279
- `rationale: ${c.rationale}`,
1280
- "",
1281
- "## Source Material"
1282
- ];
1283
- let sourceIds = [];
1284
- try {
1285
- sourceIds = JSON.parse(c.source_ids || "[]");
1286
- } catch {
1287
- }
1288
- for (const src of sourceIds) {
1289
- if (src.type === "spore") {
1290
- const spore = getSpore(src.id);
1291
- if (spore) {
1292
- parts.push(`
1293
- ### Spore: ${src.id} (${spore.observation_type}, importance ${spore.importance})`);
1294
- parts.push(spore.content);
1295
- if (spore.context) parts.push(`Context: ${spore.context}`);
1296
- if (spore.tags) parts.push(`Tags: ${spore.tags}`);
1297
- }
1298
- } else if (src.type === "session") {
1299
- const session = getSession(src.id);
1300
- if (session) {
1301
- parts.push(`
1302
- ### Session: ${src.id}`);
1303
- if (session.title) parts.push(`Title: ${session.title}`);
1304
- if (session.summary) parts.push(session.summary);
1305
- }
1306
- }
1307
- }
1308
- return {
1309
- instruction: parts.join("\n"),
1310
- context: { candidate_id: c.id }
1311
- };
1312
- }
1313
- function buildSkillSurveyInstruction(agentId) {
1314
- const eligibility = getSkillSurveyEligibility(agentId);
1315
- if (!eligibility.eligible) {
1316
- return void 0;
1317
- }
1318
- const now = epochSeconds();
1319
- const watermarkState = getState(agentId, SURVEY_WATERMARK_KEY);
1320
- const watermarkEpoch = watermarkState ? Number(watermarkState.value) : 0;
1321
- const sinceFilter = watermarkEpoch > 0 ? { since: watermarkEpoch } : {};
1322
- const parts = [
1323
- "## Pre-assembled Vault Context",
1324
- "",
1325
- `Survey watermark: ${watermarkEpoch === 0 ? "first run (full scan)" : new Date(watermarkEpoch * 1e3).toISOString()}`,
1326
- `Eligibility gate: requires ${SURVEY_MIN_SETTLED_SESSIONS}+ settled sessions and ${SURVEY_MIN_SETTLED_ACTIVE_SPORES}+ active spores from settled work.`,
1327
- "",
1328
- "CRITICAL: only propose project-specific procedural domains.",
1329
- "- A valid domain must be anchored to this repository's components, files, commands, or conventions.",
1330
- "- Generic engineering topics that could apply to any Node/TypeScript/React repo are not candidates.",
1331
- "- If a domain fails repo-specificity or cross-session evidence, reject it instead of creating or updating a candidate.",
1332
- ""
1333
- ];
1334
- const digests = listDigestExtracts(agentId);
1335
- if (digests.length > 0) {
1336
- const smallest = digests.reduce((a, b) => a.tier < b.tier ? a : b);
1337
- parts.push("### Digest");
1338
- parts.push(`**Tier ${smallest.tier}** (${smallest.content.length} chars):`);
1339
- parts.push(smallest.content);
1340
- parts.push("");
1341
- }
1342
- const wisdomSpores = listSpores({
1343
- observation_type: "wisdom",
1344
- limit: SURVEY_MAX_WISDOM_SPORES,
1345
- includeActive: false,
1346
- ...sinceFilter
1347
- });
1348
- if (wisdomSpores.length > 0) {
1349
- parts.push(`### Wisdom Spores (${wisdomSpores.length})`);
1350
- for (const s of wisdomSpores) {
1351
- parts.push(`- **${s.id}** (importance ${s.importance}): ${s.content.slice(0, 300)}`);
1352
- }
1353
- parts.push("");
1354
- }
1355
- const decisions = listSpores({
1356
- observation_type: "decision",
1357
- limit: 20,
1358
- includeActive: false,
1359
- ...sinceFilter
1360
- });
1361
- const gotchas = listSpores({
1362
- observation_type: "gotcha",
1363
- limit: 10,
1364
- includeActive: false,
1365
- ...sinceFilter
1366
- });
1367
- if (decisions.length > 0 || gotchas.length > 0) {
1368
- parts.push(`### Decisions (${decisions.length}) & Gotchas (${gotchas.length})`);
1369
- for (const s of [...decisions, ...gotchas]) {
1370
- parts.push(`- **${s.observation_type}** ${s.id}: ${s.content.slice(0, 200)}`);
1371
- }
1372
- parts.push("");
1373
- }
1374
- const sessions = listSessions({
1375
- limit: SURVEY_MAX_SESSIONS,
1376
- includeActive: false,
1377
- ...sinceFilter
1378
- });
1379
- if (sessions.length > 0) {
1380
- parts.push(`### Recent Sessions (${sessions.length})`);
1381
- for (const s of sessions) {
1382
- parts.push(`- **${s.id}**: ${s.title ?? "(untitled)"} \u2014 ${(s.summary ?? "").slice(0, 200)}`);
1383
- }
1384
- parts.push("");
1385
- }
1386
- const activeSkills = listSkillRecords({ status: "active", limit: 100 });
1387
- parts.push(`### Active Skills (${activeSkills.length})`);
1388
- for (const s of activeSkills) {
1389
- parts.push(`- **${s.name}**: ${s.description.slice(0, 150)}`);
1390
- }
1391
- parts.push("");
1392
- setState(agentId, SURVEY_WATERMARK_KEY, String(now), now);
1393
- return { instruction: parts.join("\n") };
1394
- }
1395
- var SKILL_EVOLVE_DEFAULT_ASSESS_INTERVAL_HOURS = 24;
1396
- var SKILL_EVOLVE_DEFAULT_MAX_SKILLS_PER_RUN = 8;
1397
- var MIN_SECTIONS_FOR_STANDALONE = 2;
1398
- function extractHeadings(content) {
1399
- const bodyMatch = content.match(/^---[\s\S]*?---\n([\s\S]*)$/);
1400
- const body = bodyMatch ? bodyMatch[1] : content;
1401
- return body.split("\n").filter((line) => line.startsWith("## ")).map((line) => line.slice(3).trim());
1402
- }
1403
- function headingOverlap(headingsA, headingsB) {
1404
- if (headingsA.length === 0 || headingsB.length === 0) return { score: 0, shared: [] };
1405
- const tokenize = (h) => new Set(
1406
- h.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length >= 4)
1407
- );
1408
- const shared = [];
1409
- for (const a of headingsA) {
1410
- const aTokens = tokenize(a);
1411
- for (const b of headingsB) {
1412
- const bTokens = tokenize(b);
1413
- const intersection = [...aTokens].filter((t) => bTokens.has(t)).length;
1414
- const union = (/* @__PURE__ */ new Set([...aTokens, ...bTokens])).size;
1415
- if (union > 0 && intersection / union >= 0.5) {
1416
- shared.push(`"${a}" ~ "${b}"`);
1417
- }
1418
- }
1419
- }
1420
- const smaller = Math.min(headingsA.length, headingsB.length);
1421
- return { score: smaller > 0 ? shared.length / smaller : 0, shared };
1422
- }
1423
- function buildSkillEvolveInstruction(params, projectRoot, similarityProvider) {
1424
- const assessIntervalHours = Number(params?.assess_interval_hours ?? SKILL_EVOLVE_DEFAULT_ASSESS_INTERVAL_HOURS);
1425
- const maxSkillsPerRun = Number(params?.max_skills_per_run ?? SKILL_EVOLVE_DEFAULT_MAX_SKILLS_PER_RUN);
1426
- const now = epochSeconds();
1427
- const intervalSeconds = assessIntervalHours * 3600;
1428
- const allSkills = listSkillRecords({ status: "active", limit: 100 });
1429
- const needsAssessment = [];
1430
- for (const skill of allSkills) {
1431
- let props = {};
1432
- try {
1433
- props = JSON.parse(skill.properties || "{}");
1434
- } catch {
1435
- props = {};
1436
- }
1437
- const lastAssessedAt = typeof props.last_assessed_at === "number" ? props.last_assessed_at : 0;
1438
- const knowledgeWatermark = typeof props.knowledge_watermark === "number" ? props.knowledge_watermark : 0;
1439
- if (lastAssessedAt > 0 && now - lastAssessedAt < intervalSeconds) continue;
1440
- const newSporeIds = listSporeIdsSince(knowledgeWatermark, 10);
1441
- if (newSporeIds.length === 0) continue;
1442
- needsAssessment.push({
1443
- id: skill.id,
1444
- name: skill.name,
1445
- generation: skill.generation,
1446
- description: skill.description,
1447
- newSporeIds
1448
- });
1449
- if (needsAssessment.length >= maxSkillsPerRun) {
1450
- break;
1451
- }
1452
- }
1453
- if (needsAssessment.length === 0) {
1454
- return "No skills need assessment. All active skills are current or were recently assessed. Report skip via vault_report and finish.";
1455
- }
1456
- const structures = [];
1457
- const skillHeadings = /* @__PURE__ */ new Map();
1458
- for (const skill of allSkills) {
1459
- let content = "";
1460
- if (projectRoot && skill.path) {
1461
- try {
1462
- content = readFileSync(resolve(projectRoot, skill.path), "utf-8");
1463
- } catch {
1464
- }
1465
- }
1466
- const headings = extractHeadings(content);
1467
- skillHeadings.set(skill.name, headings);
1468
- structures.push({
1469
- name: skill.name,
1470
- sectionCount: headings.length,
1471
- headings,
1472
- narrow: headings.length < MIN_SECTIONS_FOR_STANDALONE
1473
- });
1474
- }
1475
- const overlaps = [];
1476
- for (let i = 0; i < allSkills.length; i++) {
1477
- for (let j = i + 1; j < allSkills.length; j++) {
1478
- const a = allSkills[i];
1479
- const b = allSkills[j];
1480
- const descJaccard = descriptionSimilarity(a.description, b.description);
1481
- const aHeadings = skillHeadings.get(a.name) ?? [];
1482
- const bHeadings = skillHeadings.get(b.name) ?? [];
1483
- const ho = headingOverlap(aHeadings, bHeadings);
1484
- const descFlag = descJaccard >= DESCRIPTION_DUPLICATE_THRESHOLD * 0.75;
1485
- const headingFlag = ho.score >= 0.4;
1486
- if (!descFlag && !headingFlag) continue;
1487
- const verdict = descJaccard >= DESCRIPTION_DUPLICATE_THRESHOLD || ho.score >= 0.5 ? "potential-merge" : "potential-narrow";
1488
- overlaps.push({
1489
- skillA: a.name,
1490
- skillB: b.name,
1491
- descriptionJaccard: Math.round(descJaccard * 100) / 100,
1492
- headingOverlap: Math.round(ho.score * 100) / 100,
1493
- sharedHeadings: ho.shared,
1494
- verdict
1495
- });
1496
- }
1497
- }
1498
- const parts = [
1499
- `${needsAssessment.length} skill(s) need assessment.`,
1500
- `assess_interval_hours: ${assessIntervalHours}`,
1501
- `max_skills_per_run: ${maxSkillsPerRun}`
1502
- ];
1503
- for (const skill of needsAssessment) {
1504
- parts.push("");
1505
- parts.push("---");
1506
- parts.push(`## Skill: ${skill.name} (gen ${skill.generation})`);
1507
- parts.push(`id: ${skill.id}`);
1508
- parts.push(`description: ${skill.description}`);
1509
- parts.push(`new_spore_ids: ${JSON.stringify(skill.newSporeIds)}`);
1510
- }
1511
- parts.push("");
1512
- parts.push("## All Active Skills (for inventory analysis)");
1513
- for (const s of structures) {
1514
- const skill = allSkills.find((sk) => sk.name === s.name);
1515
- const narrowTag = s.narrow ? " **[NARROW \u2014 <2 sections]**" : "";
1516
- parts.push(`- **${skill.name}** (gen ${skill.generation}, ${s.sectionCount} sections${narrowTag}): ${skill.description.slice(0, 200)}`);
1517
- if (s.headings.length > 0) {
1518
- parts.push(` Headings: ${s.headings.join(" | ")}`);
1519
- }
1520
- }
1521
- const narrowSkills = structures.filter((s) => s.narrow);
1522
- if (narrowSkills.length > 0) {
1523
- parts.push("");
1524
- parts.push("## Mechanically Narrow Skills (<2 H2 sections)");
1525
- parts.push("These skills have insufficient section breadth for domain-level standalone status.");
1526
- parts.push("Determine which broader skill each should be absorbed into.");
1527
- for (const s of narrowSkills) {
1528
- parts.push(`- **${s.name}**: ${s.sectionCount} section(s). Headings: ${s.headings.length > 0 ? s.headings.join(" | ") : "(none)"}`);
1529
- }
1530
- }
1531
- if (overlaps.length > 0) {
1532
- parts.push("");
1533
- parts.push("## Pre-computed Token Overlap");
1534
- parts.push("Pairs flagged by description token similarity AND/OR heading overlap:");
1535
- for (const o of overlaps) {
1536
- parts.push(`- **${o.skillA}** <-> **${o.skillB}**: desc=${o.descriptionJaccard}, headings=${o.headingOverlap} (${o.verdict})`);
1537
- if (o.sharedHeadings.length > 0) {
1538
- parts.push(` Shared headings: ${o.sharedHeadings.join("; ")}`);
1539
- }
1540
- }
1541
- }
1542
- if (similarityProvider) {
1543
- const idToName = new Map(allSkills.map((s) => [s.id, s.name]));
1544
- try {
1545
- const semanticPairs = similarityProvider.pairwiseSimilarity("skill_records", 0.65);
1546
- if (semanticPairs.length > 0) {
1547
- parts.push("");
1548
- parts.push("## Semantic Similarity (embedding cosine distance)");
1549
- parts.push("Pairs with cosine similarity >= 0.65. This is the STRONGEST overlap signal.");
1550
- parts.push("High similarity (>0.8) means the skills describe nearly identical procedures.");
1551
- for (const p of semanticPairs) {
1552
- const nameA = idToName.get(p.idA) ?? p.idA;
1553
- const nameB = idToName.get(p.idB) ?? p.idB;
1554
- parts.push(`- **${nameA}** <-> **${nameB}**: cosine=${p.similarity}`);
1555
- }
1556
- }
1557
- } catch {
1558
- }
1559
- }
1560
- return parts.join("\n");
1561
- }
1562
- function buildTaskInstruction(taskName, taskParams, agentId, projectRoot, similarityProvider) {
1563
- switch (taskName) {
1564
- case SKILL_GENERATE_TASK:
1565
- return buildSkillGenerateInstruction();
1566
- case SKILL_SURVEY_TASK:
1567
- return agentId ? buildSkillSurveyInstruction(agentId) : void 0;
1568
- case SKILL_EVOLVE_TASK: {
1569
- const instruction = buildSkillEvolveInstruction(taskParams, projectRoot, similarityProvider);
1570
- return instruction ? { instruction } : void 0;
1571
- }
1572
- default:
1573
- return void 0;
1574
- }
1575
- }
1576
- function isInstructionRequiredTask(taskName) {
1577
- return taskName === SKILL_GENERATE_TASK || taskName === SKILL_EVOLVE_TASK || taskName === SKILL_SURVEY_TASK;
1578
- }
1579
-
1580
- // src/db/queries/skill-lineage.ts
1581
- var LINEAGE_COLUMNS = [
1582
- "id",
1583
- "skill_id",
1584
- "generation",
1585
- "action",
1586
- "rationale",
1587
- "source_ids_added",
1588
- "content_snapshot",
1589
- "created_at"
1590
- ];
1591
- var SELECT_COLUMNS6 = LINEAGE_COLUMNS.join(", ");
1592
- function toLineageRow(row) {
1593
- return {
1594
- id: row.id,
1595
- skill_id: row.skill_id,
1596
- generation: row.generation,
1597
- action: row.action,
1598
- rationale: row.rationale,
1599
- source_ids_added: row.source_ids_added ?? "[]",
1600
- content_snapshot: row.content_snapshot,
1601
- created_at: row.created_at
1602
- };
1603
- }
1604
- function insertLineage(data) {
1605
- const db = getDatabase();
1606
- db.prepare(
1607
- `INSERT INTO skill_lineage (
1608
- id, skill_id, generation, action, rationale,
1609
- source_ids_added, content_snapshot, created_at
1610
- ) VALUES (
1611
- ?, ?, ?, ?, ?,
1612
- ?, ?, ?
1613
- )`
1614
- ).run(
1615
- data.id,
1616
- data.skill_id,
1617
- data.generation,
1618
- data.action,
1619
- data.rationale,
1620
- data.source_ids_added ?? "[]",
1621
- data.content_snapshot,
1622
- data.created_at
1623
- );
1624
- return toLineageRow(
1625
- db.prepare(`SELECT ${SELECT_COLUMNS6} FROM skill_lineage WHERE id = ?`).get(data.id)
1626
- );
1627
- }
1628
- function listLineageForSkill(skillId, limit = 50) {
1629
- const db = getDatabase();
1630
- const rows = db.prepare(
1631
- `SELECT ${SELECT_COLUMNS6}
1632
- FROM skill_lineage
1633
- WHERE skill_id = ?
1634
- ORDER BY generation DESC
1635
- LIMIT ?`
1636
- ).all(skillId, limit);
1637
- return rows.map(toLineageRow);
1638
- }
1639
-
1640
- // src/db/queries/batches.ts
1641
- var DEFAULT_UNPROCESSED_LIMIT = 100;
1642
- var BATCHES_DEFAULT_LIMIT = 200;
1643
- var STATUS_COMPLETED2 = "completed";
1644
- var DEFAULT_STATUS4 = "active";
1645
- var DEFAULT_ACTIVITY_COUNT = 0;
1646
- var DEFAULT_PROCESSED = 0;
1647
- var PROCESSED_FLAG = 1;
1648
- var PROMPT_PREFIX_MATCH_CHARS = 60;
1649
- var BATCH_COLUMNS = [
1650
- "id",
1651
- "session_id",
1652
- "prompt_number",
1653
- "user_prompt",
1654
- "response_summary",
1655
- "classification",
1656
- "started_at",
1657
- "ended_at",
1658
- "status",
1659
- "activity_count",
1660
- "processed",
1661
- "content_hash",
1662
- "created_at",
1663
- "machine_id",
1664
- "synced_at"
1665
- ];
1666
- var SELECT_COLUMNS7 = BATCH_COLUMNS.join(", ");
1667
- function toBatchRow(row) {
1668
- return {
1669
- id: row.id,
1670
- session_id: row.session_id,
1671
- prompt_number: row.prompt_number ?? null,
1672
- user_prompt: row.user_prompt ?? null,
1673
- response_summary: row.response_summary ?? null,
1674
- classification: row.classification ?? null,
1675
- started_at: row.started_at ?? null,
1676
- ended_at: row.ended_at ?? null,
1677
- status: row.status,
1678
- activity_count: row.activity_count,
1679
- processed: row.processed,
1680
- content_hash: row.content_hash ?? null,
1681
- created_at: row.created_at,
1682
- machine_id: row.machine_id ?? "local",
1683
- synced_at: row.synced_at ?? null
1684
- };
1685
- }
1686
- function populateBatchResponses(sessionId, responses) {
1687
- const db = getDatabase();
1688
- const batches = db.prepare(
1689
- `SELECT id FROM prompt_batches WHERE session_id = ? ORDER BY id ASC`
1690
- ).all(sessionId);
1691
- for (const { turnIndex, response } of responses) {
1692
- const batchIndex = turnIndex - 1;
1693
- if (batchIndex >= 0 && batchIndex < batches.length) {
1694
- const batchId = batches[batchIndex].id;
1695
- db.prepare(
1696
- `UPDATE prompt_batches SET response_summary = ? WHERE id = ? AND response_summary IS NULL`
1697
- ).run(response, batchId);
1698
- }
1699
- }
1700
- }
1701
- function getUnprocessedBatches(options = {}) {
1702
- const db = getDatabase();
1703
- const conditions = [`processed = ?`];
1704
- const params = [DEFAULT_PROCESSED];
1705
- if (options.after_id !== void 0) {
1706
- conditions.push(`id > ?`);
1707
- params.push(options.after_id);
1708
- }
1709
- if (options.includeActive === false) {
1710
- conditions.push(
1711
- `EXISTS (SELECT 1 FROM sessions s WHERE s.id = prompt_batches.session_id AND s.status != 'active')`
1712
- );
1713
- }
1714
- const limit = options.limit ?? DEFAULT_UNPROCESSED_LIMIT;
1715
- params.push(limit);
1716
- const where = conditions.join(" AND ");
1717
- const rows = db.prepare(
1718
- `SELECT ${SELECT_COLUMNS7}
1719
- FROM prompt_batches
1720
- WHERE ${where}
1721
- ORDER BY id ASC
1722
- LIMIT ?`
1723
- ).all(...params);
1724
- return rows.map(toBatchRow);
1725
- }
1726
- function incrementActivityCount(id) {
1727
- const db = getDatabase();
1728
- const info = db.prepare(
1729
- `UPDATE prompt_batches
1730
- SET activity_count = activity_count + 1
1731
- WHERE id = ?`
1732
- ).run(id);
1733
- if (info.changes === 0) return null;
1734
- return toBatchRow(
1735
- db.prepare(`SELECT ${SELECT_COLUMNS7} FROM prompt_batches WHERE id = ?`).get(id)
1736
- );
1737
- }
1738
- function markBatchProcessed(id) {
1739
- const db = getDatabase();
1740
- const info = db.prepare(
1741
- `UPDATE prompt_batches
1742
- SET processed = ?
1743
- WHERE id = ?`
1744
- ).run(PROCESSED_FLAG, id);
1745
- if (info.changes === 0) return null;
1746
- return toBatchRow(
1747
- db.prepare(`SELECT ${SELECT_COLUMNS7} FROM prompt_batches WHERE id = ?`).get(id)
1748
- );
1749
- }
1750
- function findBatchByPromptPrefix(sessionId, promptPrefix) {
1751
- const db = getDatabase();
1752
- const prefix = promptPrefix.slice(0, PROMPT_PREFIX_MATCH_CHARS);
1753
- const row = db.prepare(
1754
- `SELECT id, prompt_number FROM prompt_batches
1755
- WHERE session_id = ? AND user_prompt LIKE ? || '%'
1756
- LIMIT 1`
1757
- ).get(sessionId, prefix);
1758
- return row ?? null;
1759
- }
1760
- function insertBatchStateless(data) {
1761
- const db = getDatabase();
1762
- const info = db.prepare(
1763
- `INSERT INTO prompt_batches (
1764
- session_id, prompt_number, user_prompt, response_summary,
1765
- classification, started_at, ended_at, status,
1766
- activity_count, processed, content_hash, created_at, machine_id
1767
- ) VALUES (
1768
- ?,
1769
- (SELECT COALESCE(MAX(prompt_number), 0) + 1 FROM prompt_batches WHERE session_id = ?),
1770
- ?, NULL,
1771
- NULL, ?, NULL, ?,
1772
- ?, ?, NULL, ?, ?
1773
- )`
1774
- ).run(
1775
- data.session_id,
1776
- data.session_id,
1777
- data.user_prompt ?? null,
1778
- data.started_at ?? null,
1779
- data.status ?? DEFAULT_STATUS4,
1780
- DEFAULT_ACTIVITY_COUNT,
1781
- DEFAULT_PROCESSED,
1782
- data.created_at,
1783
- data.machine_id ?? getTeamMachineId()
1784
- );
1785
- const batchId = Number(info.lastInsertRowid);
1786
- return toBatchRow(
1787
- db.prepare(`SELECT ${SELECT_COLUMNS7} FROM prompt_batches WHERE id = ?`).get(batchId)
1788
- );
1789
- }
1790
- function closeOpenBatches(sessionId, endedAt) {
1791
- const db = getDatabase();
1792
- const info = db.prepare(
1793
- `UPDATE prompt_batches
1794
- SET status = ?, ended_at = ?
1795
- WHERE session_id = ? AND ended_at IS NULL`
1796
- ).run(STATUS_COMPLETED2, endedAt, sessionId);
1797
- return info.changes;
1798
- }
1799
- function setResponseSummary(batchId, summary) {
1800
- const db = getDatabase();
1801
- db.prepare(
1802
- `UPDATE prompt_batches SET response_summary = ? WHERE id = ? AND response_summary IS NULL`
1803
- ).run(summary, batchId);
1804
- }
1805
- function getLatestBatch(sessionId) {
1806
- const db = getDatabase();
1807
- const row = db.prepare(
1808
- `SELECT ${SELECT_COLUMNS7} FROM prompt_batches
1809
- WHERE session_id = ?
1810
- ORDER BY id DESC LIMIT 1`
1811
- ).get(sessionId);
1812
- if (!row) return null;
1813
- return toBatchRow(row);
1814
- }
1815
- function listBatchesBySession(sessionId, options = {}) {
1816
- const db = getDatabase();
1817
- const limit = options.limit ?? BATCHES_DEFAULT_LIMIT;
1818
- const offset = options.offset ?? 0;
1819
- const rows = db.prepare(
1820
- `SELECT ${SELECT_COLUMNS7}
1821
- FROM prompt_batches
1822
- WHERE session_id = ?
1823
- ORDER BY prompt_number ASC
1824
- LIMIT ?
1825
- OFFSET ?`
1826
- ).all(sessionId, limit, offset);
1827
- return rows.map(toBatchRow);
1828
- }
1829
- function countBatchesBySession(sessionId) {
1830
- const db = getDatabase();
1831
- const row = db.prepare(
1832
- `SELECT COUNT(*) as count FROM prompt_batches WHERE session_id = ?`
1833
- ).get(sessionId);
1834
- return row.count;
1835
- }
1836
-
1837
- // src/db/queries/graph-edges.ts
1838
- import crypto2 from "crypto";
1839
- var DEFAULT_BFS_DEPTH = 2;
1840
- var MAX_BFS_DEPTH = 5;
1841
- var GRAPH_EDGE_COLUMNS = [
1842
- "id",
1843
- "agent_id",
1844
- "source_id",
1845
- "source_type",
1846
- "target_id",
1847
- "target_type",
1848
- "type",
1849
- "session_id",
1850
- "confidence",
1851
- "properties",
1852
- "created_at",
1853
- "machine_id",
1854
- "synced_at"
1855
- ];
1856
- var SELECT_COLUMNS8 = GRAPH_EDGE_COLUMNS.join(", ");
1857
- function toGraphEdgeRow(row) {
1858
- return {
1859
- id: row.id,
1860
- agent_id: row.agent_id,
1861
- source_id: row.source_id,
1862
- source_type: row.source_type,
1863
- target_id: row.target_id,
1864
- target_type: row.target_type,
1865
- type: row.type,
1866
- session_id: row.session_id ?? null,
1867
- confidence: row.confidence,
1868
- properties: row.properties ?? null,
1869
- created_at: row.created_at,
1870
- machine_id: row.machine_id ?? getTeamMachineId(),
1871
- synced_at: row.synced_at ?? null
1872
- };
1873
- }
1874
- function insertGraphEdge(data) {
1875
- const db = getDatabase();
1876
- const id = crypto2.randomUUID();
1877
- db.prepare(
1878
- `INSERT INTO graph_edges (
1879
- id, agent_id, source_id, source_type, target_id, target_type,
1880
- type, session_id, confidence, properties, created_at, machine_id
1881
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
1882
- ).run(
1883
- id,
1884
- data.agent_id,
1885
- data.source_id,
1886
- data.source_type,
1887
- data.target_id,
1888
- data.target_type,
1889
- data.type,
1890
- data.session_id ?? null,
1891
- data.confidence ?? GRAPH_EDGE_DEFAULT_CONFIDENCE,
1892
- data.properties ?? null,
1893
- data.created_at,
1894
- data.machine_id ?? getTeamMachineId()
1895
- );
1896
- const row = toGraphEdgeRow(
1897
- db.prepare(`SELECT ${SELECT_COLUMNS8} FROM graph_edges WHERE id = ?`).get(id)
1898
- );
1899
- syncRow("graph_edges", row);
1900
- return row;
1901
- }
1902
- function listGraphEdges(options = {}) {
1903
- const db = getDatabase();
1904
- const conditions = [];
1905
- const params = [];
1906
- if (options.sourceId !== void 0) {
1907
- conditions.push(`source_id = ?`);
1908
- params.push(options.sourceId);
1909
- }
1910
- if (options.targetId !== void 0) {
1911
- conditions.push(`target_id = ?`);
1912
- params.push(options.targetId);
1913
- }
1914
- if (options.type !== void 0) {
1915
- conditions.push(`type = ?`);
1916
- params.push(options.type);
1917
- }
1918
- if (options.agentId !== void 0) {
1919
- conditions.push(`agent_id = ?`);
1920
- params.push(options.agentId);
1921
- }
1922
- const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
1923
- const limit = options.limit ?? QUERY_DEFAULT_LIST_LIMIT;
1924
- params.push(limit);
1925
- const rows = db.prepare(
1926
- `SELECT ${SELECT_COLUMNS8}
1927
- FROM graph_edges
1928
- ${where}
1929
- ORDER BY created_at DESC
1930
- LIMIT ?`
1931
- ).all(...params);
1932
- return rows.map(toGraphEdgeRow);
1933
- }
1934
- function getGraphForNode(nodeId, nodeType, options) {
1935
- const db = getDatabase();
1936
- const depth = Math.min(Math.max(options?.depth ?? DEFAULT_BFS_DEPTH, 1), MAX_BFS_DEPTH);
1937
- const seenEdgeIds = /* @__PURE__ */ new Set();
1938
- const collectedEdges = [];
1939
- const visited = /* @__PURE__ */ new Set([`${nodeType}:${nodeId}`]);
1940
- let frontier = /* @__PURE__ */ new Set([nodeId]);
1941
- for (let hop = 0; hop < depth; hop++) {
1942
- if (frontier.size === 0) break;
1943
- const frontierArray = Array.from(frontier);
1944
- const placeholders = frontierArray.map(() => `?`).join(", ");
1945
- const rows = db.prepare(
1946
- `SELECT ${SELECT_COLUMNS8}
1947
- FROM graph_edges
1948
- WHERE source_id IN (${placeholders}) OR target_id IN (${placeholders})`
1949
- ).all(...frontierArray, ...frontierArray);
1950
- const nextFrontier = /* @__PURE__ */ new Set();
1951
- for (const row of rows) {
1952
- const edge = toGraphEdgeRow(row);
1953
- if (!seenEdgeIds.has(edge.id)) {
1954
- seenEdgeIds.add(edge.id);
1955
- collectedEdges.push(edge);
1956
- }
1957
- const sourceKey = `${edge.source_type}:${edge.source_id}`;
1958
- const targetKey = `${edge.target_type}:${edge.target_id}`;
1959
- if (!visited.has(sourceKey)) {
1960
- visited.add(sourceKey);
1961
- nextFrontier.add(edge.source_id);
1962
- }
1963
- if (!visited.has(targetKey)) {
1964
- visited.add(targetKey);
1965
- nextFrontier.add(edge.target_id);
1966
- }
1967
- }
1968
- frontier = nextFrontier;
1969
- }
1970
- return { edges: collectedEdges };
1971
- }
1972
-
1973
- // src/db/queries/entities.ts
1974
- var DEFAULT_LIST_LIMIT3 = 100;
1975
- var ENTITY_COLUMNS = [
1976
- "id",
1977
- "agent_id",
1978
- "type",
1979
- "name",
1980
- "properties",
1981
- "first_seen",
1982
- "last_seen",
1983
- "status",
1984
- "machine_id",
1985
- "synced_at"
1986
- ];
1987
- var SELECT_COLUMNS9 = ENTITY_COLUMNS.join(", ");
1988
- function toEntityRow(row) {
1989
- return {
1990
- id: row.id,
1991
- agent_id: row.agent_id,
1992
- type: row.type,
1993
- name: row.name,
1994
- properties: row.properties ?? null,
1995
- first_seen: row.first_seen,
1996
- last_seen: row.last_seen,
1997
- status: row.status ?? "active",
1998
- machine_id: row.machine_id ?? "local",
1999
- synced_at: row.synced_at ?? null
2000
- };
2001
- }
2002
- function insertEntity(data) {
2003
- const db = getDatabase();
2004
- db.prepare(
2005
- `INSERT INTO entities (id, agent_id, type, name, properties, first_seen, last_seen, machine_id)
2006
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
2007
- ON CONFLICT (agent_id, type, name) DO UPDATE SET
2008
- properties = COALESCE(EXCLUDED.properties, entities.properties),
2009
- last_seen = EXCLUDED.last_seen`
2010
- ).run(
2011
- data.id,
2012
- data.agent_id,
2013
- data.type,
2014
- data.name,
2015
- data.properties ?? null,
2016
- data.first_seen,
2017
- data.last_seen,
2018
- data.machine_id ?? getTeamMachineId()
2019
- );
2020
- const row = toEntityRow(
2021
- db.prepare(`SELECT ${SELECT_COLUMNS9} FROM entities WHERE agent_id = ? AND type = ? AND name = ?`).get(
2022
- data.agent_id,
2023
- data.type,
2024
- data.name
2025
- )
2026
- );
2027
- syncRow("entities", row);
2028
- return row;
2029
- }
2030
- function getEntity(id) {
2031
- const db = getDatabase();
2032
- const row = db.prepare(
2033
- `SELECT ${SELECT_COLUMNS9} FROM entities WHERE id = ?`
2034
- ).get(id);
2035
- if (!row) return null;
2036
- return toEntityRow(row);
2037
- }
2038
- function listEntities(options = {}) {
2039
- const db = getDatabase();
2040
- const conditions = [];
2041
- const params = [];
2042
- if (options.agent_id !== void 0) {
2043
- conditions.push(`agent_id = ?`);
2044
- params.push(options.agent_id);
2045
- }
2046
- if (options.type !== void 0) {
2047
- conditions.push(`type = ?`);
2048
- params.push(options.type);
2049
- }
2050
- if (options.name !== void 0) {
2051
- conditions.push(`name = ?`);
2052
- params.push(options.name);
2053
- }
2054
- if (options.status !== void 0) {
2055
- conditions.push(`status = ?`);
2056
- params.push(options.status);
2057
- } else {
2058
- conditions.push(`status = ?`);
2059
- params.push("active");
2060
- }
2061
- if (options.mentioned_in !== void 0 && options.note_type !== void 0) {
2062
- conditions.push(
2063
- `id IN (SELECT entity_id FROM entity_mentions WHERE note_id = ? AND note_type = ?)`
2064
- );
2065
- params.push(options.mentioned_in);
2066
- params.push(options.note_type);
2067
- }
2068
- const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
2069
- const limit = options.limit ?? DEFAULT_LIST_LIMIT3;
2070
- const offset = options.offset ?? 0;
2071
- params.push(limit);
2072
- params.push(offset);
2073
- const rows = db.prepare(
2074
- `SELECT ${SELECT_COLUMNS9}
2075
- FROM entities
2076
- ${where}
2077
- ORDER BY last_seen DESC
2078
- LIMIT ?
2079
- OFFSET ?`
2080
- ).all(...params);
2081
- return rows.map(toEntityRow);
2082
- }
2083
-
2084
- // src/db/queries/lineage.ts
2085
- function createSporeLineage(spore) {
2086
- if (spore.session_id) {
2087
- insertGraphEdge({
2088
- agent_id: spore.agent_id,
2089
- source_id: spore.id,
2090
- source_type: "spore",
2091
- target_id: spore.session_id,
2092
- target_type: "session",
2093
- type: EDGE_TYPE_FROM_SESSION,
2094
- created_at: spore.created_at
2095
- });
2096
- }
2097
- if (spore.prompt_batch_id != null) {
2098
- insertGraphEdge({
2099
- agent_id: spore.agent_id,
2100
- source_id: spore.id,
2101
- source_type: "spore",
2102
- target_id: String(spore.prompt_batch_id),
2103
- target_type: "batch",
2104
- type: EDGE_TYPE_EXTRACTED_FROM,
2105
- created_at: spore.created_at
2106
- });
2107
- }
2108
- if (spore.observation_type === "wisdom" && spore.properties) {
2109
- try {
2110
- const props = JSON.parse(spore.properties);
2111
- if (Array.isArray(props.consolidated_from)) {
2112
- for (const sourceId of props.consolidated_from) {
2113
- insertGraphEdge({
2114
- agent_id: spore.agent_id,
2115
- source_id: spore.id,
2116
- source_type: "spore",
2117
- target_id: sourceId,
2118
- target_type: "spore",
2119
- type: EDGE_TYPE_DERIVED_FROM,
2120
- created_at: spore.created_at
2121
- });
2122
- }
2123
- }
2124
- } catch {
2125
- }
2126
- }
2127
- }
2128
- function createBatchLineage(agentId, sessionId, batchId, createdAt) {
2129
- insertGraphEdge({
2130
- agent_id: agentId,
2131
- source_id: sessionId,
2132
- source_type: "session",
2133
- target_id: String(batchId),
2134
- target_type: "batch",
2135
- type: EDGE_TYPE_HAS_BATCH,
2136
- created_at: createdAt
2137
- });
2138
- }
2139
-
2140
- // src/db/queries/resolution-events.ts
2141
- var EVENT_COLUMNS = [
2142
- "id",
2143
- "agent_id",
2144
- "spore_id",
2145
- "action",
2146
- "new_spore_id",
2147
- "reason",
2148
- "session_id",
2149
- "created_at",
2150
- "machine_id",
2151
- "synced_at"
2152
- ];
2153
- var SELECT_COLUMNS10 = EVENT_COLUMNS.join(", ");
2154
- function toResolutionEventRow(row) {
2155
- return {
2156
- id: row.id,
2157
- agent_id: row.agent_id,
2158
- spore_id: row.spore_id,
2159
- action: row.action,
2160
- new_spore_id: row.new_spore_id ?? null,
2161
- reason: row.reason ?? null,
2162
- session_id: row.session_id ?? null,
2163
- created_at: row.created_at,
2164
- machine_id: row.machine_id ?? "local",
2165
- synced_at: row.synced_at ?? null
2166
- };
2167
- }
2168
- function insertResolutionEvent(data) {
2169
- const db = getDatabase();
2170
- db.prepare(
2171
- `INSERT INTO resolution_events (
2172
- id, agent_id, spore_id, action, new_spore_id, reason, session_id, created_at, machine_id
2173
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
2174
- ).run(
2175
- data.id,
2176
- data.agent_id,
2177
- data.spore_id,
2178
- data.action,
2179
- data.new_spore_id ?? null,
2180
- data.reason ?? null,
2181
- data.session_id ?? null,
2182
- data.created_at,
2183
- data.machine_id ?? getTeamMachineId()
2184
- );
2185
- const row = toResolutionEventRow(
2186
- db.prepare(`SELECT ${SELECT_COLUMNS10} FROM resolution_events WHERE id = ?`).get(data.id)
2187
- );
2188
- syncRow("resolution_events", row);
2189
- return row;
2190
- }
2191
-
2192
- // src/db/queries/reports.ts
2193
- var REPORT_COLUMNS = [
2194
- "id",
2195
- "run_id",
2196
- "agent_id",
2197
- "action",
2198
- "summary",
2199
- "details",
2200
- "created_at"
2201
- ];
2202
- var SELECT_COLUMNS11 = REPORT_COLUMNS.join(", ");
2203
- function toReportRow(row) {
2204
- return {
2205
- id: row.id,
2206
- run_id: row.run_id,
2207
- agent_id: row.agent_id,
2208
- action: row.action,
2209
- summary: row.summary,
2210
- details: row.details ?? null,
2211
- created_at: row.created_at
2212
- };
2213
- }
2214
- function insertReport(data) {
2215
- const db = getDatabase();
2216
- const info = db.prepare(
2217
- `INSERT INTO agent_reports (
2218
- run_id, agent_id, action, summary, details, created_at
2219
- ) VALUES (
2220
- ?, ?, ?, ?, ?, ?
2221
- )`
2222
- ).run(
2223
- data.run_id,
2224
- data.agent_id,
2225
- data.action,
2226
- data.summary,
2227
- data.details ?? null,
2228
- data.created_at
2229
- );
2230
- const reportId = Number(info.lastInsertRowid);
2231
- return toReportRow(
2232
- db.prepare(`SELECT ${SELECT_COLUMNS11} FROM agent_reports WHERE id = ?`).get(reportId)
2233
- );
2234
- }
2235
- function listReports(runId) {
2236
- const db = getDatabase();
2237
- const rows = db.prepare(
2238
- `SELECT ${SELECT_COLUMNS11}
2239
- FROM agent_reports
2240
- WHERE run_id = ?
2241
- ORDER BY created_at ASC`
2242
- ).all(runId);
2243
- return rows.map(toReportRow);
2244
- }
2245
-
2246
- export {
2247
- listNotifications,
2248
- countNotifications,
2249
- getNotification,
2250
- updateNotificationStatus,
2251
- dismissAllNotifications,
2252
- markAllRead,
2253
- register,
2254
- getAllDomains,
2255
- notify,
2256
- insertCandidate,
2257
- getCandidate,
2258
- listCandidates,
2259
- updateCandidate,
2260
- listCandidatesWithCount,
2261
- countCandidates,
2262
- deleteCandidate,
2263
- insertSkillRecord,
2264
- getSkillRecord,
2265
- getSkillRecordByName,
2266
- listSkillRecords,
2267
- updateSkillRecord,
2268
- incrementSkillUsageCount,
2269
- listSkillRecordsWithCount,
2270
- countSkillRecords,
2271
- deleteSkillRecordCascade,
2272
- insertLineage,
2273
- listLineageForSkill,
2274
- populateBatchResponses,
2275
- getUnprocessedBatches,
2276
- incrementActivityCount,
2277
- markBatchProcessed,
2278
- findBatchByPromptPrefix,
2279
- insertBatchStateless,
2280
- closeOpenBatches,
2281
- setResponseSummary,
2282
- getLatestBatch,
2283
- listBatchesBySession,
2284
- countBatchesBySession,
2285
- errorMessage,
2286
- STATUS_RUNNING,
2287
- STATUS_COMPLETED,
2288
- STATUS_FAILED,
2289
- insertRun,
2290
- getRun,
2291
- listRuns,
2292
- countRuns,
2293
- updateRunStatus,
2294
- getRunningRunForTask,
2295
- getLatestRunId,
2296
- setState,
2297
- getStatesForAgent,
2298
- insertGraphEdge,
2299
- listGraphEdges,
2300
- getGraphForNode,
2301
- insertEntity,
2302
- getEntity,
2303
- listEntities,
2304
- createSporeLineage,
2305
- createBatchLineage,
2306
- insertResolutionEvent,
2307
- upsertDigestExtract,
2308
- getDigestExtract,
2309
- listDigestExtracts,
2310
- insertReport,
2311
- listReports,
2312
- descriptionSimilarity,
2313
- topicOverlapSimilarity,
2314
- DESCRIPTION_DUPLICATE_THRESHOLD,
2315
- TOPIC_OVERLAP_THRESHOLD,
2316
- checkFrontmatterPreservation,
2317
- validateSkillContent,
2318
- hasConfiguredProvider,
2319
- resolveRunConfig,
2320
- SKILL_GENERATE_TASK,
2321
- SKILL_SURVEY_TASK,
2322
- getSkillSurveyEligibility,
2323
- buildTaskInstruction,
2324
- isInstructionRequiredTask
2325
- };
2326
- //# sourceMappingURL=chunk-UYMFCYBF.js.map