@goondocks/myco 0.18.0 → 0.19.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 (192) hide show
  1. package/README.md +17 -130
  2. package/dist/{agent-run-2NFYMQXW.js → agent-run-EADUYYAS.js} +6 -6
  3. package/dist/{agent-tasks-MEIYLXGN.js → agent-tasks-GC77JXQB.js} +6 -6
  4. package/dist/{chunk-EO2RQW4S.js → chunk-2CKDAFSX.js} +2 -2
  5. package/dist/{chunk-NZI7WBZI.js → chunk-2DF4OZ2D.js} +22 -2
  6. package/dist/chunk-2DF4OZ2D.js.map +1 -0
  7. package/dist/{chunk-OW433Q4C.js → chunk-2LN2BBKA.js} +45 -4
  8. package/dist/chunk-2LN2BBKA.js.map +1 -0
  9. package/dist/{chunk-U7GJTVSX.js → chunk-2OO3BRFK.js} +21 -7
  10. package/dist/chunk-2OO3BRFK.js.map +1 -0
  11. package/dist/{chunk-RAV5YMRU.js → chunk-3TPD6HEF.js} +4 -4
  12. package/dist/{chunk-JMOUFG6Y.js → chunk-44PZCAYS.js} +47 -5
  13. package/dist/chunk-44PZCAYS.js.map +1 -0
  14. package/dist/{chunk-D7TYRPRM.js → chunk-6LQIMRTC.js} +145 -145
  15. package/dist/chunk-6LQIMRTC.js.map +1 -0
  16. package/dist/{chunk-NI23QCHB.js → chunk-AELJ4PS5.js} +5 -5
  17. package/dist/{chunk-BUIR3JWM.js → chunk-CYBC2HZ3.js} +3 -3
  18. package/dist/chunk-EM63ZFKA.js +166 -0
  19. package/dist/chunk-EM63ZFKA.js.map +1 -0
  20. package/dist/{chunk-O3TRN3RC.js → chunk-INWD6AIQ.js} +2 -2
  21. package/dist/{chunk-CML4MCYF.js → chunk-KSXTNYXO.js} +2 -2
  22. package/dist/{chunk-KWTOCJLB.js → chunk-LLJMDXO2.js} +1176 -241
  23. package/dist/chunk-LLJMDXO2.js.map +1 -0
  24. package/dist/{chunk-2V7HR7HB.js → chunk-MDEUXYJG.js} +4 -4
  25. package/dist/{chunk-PFWIPRF6.js → chunk-MS6FDV45.js} +3 -3
  26. package/dist/{chunk-55QEICRO.js → chunk-N77K772N.js} +3 -3
  27. package/dist/{chunk-E4VLWIJC.js → chunk-ODXLRR4U.js} +1 -1
  28. package/dist/{chunk-DLFDBKEV.js → chunk-OZF5EURR.js} +19 -16
  29. package/dist/chunk-OZF5EURR.js.map +1 -0
  30. package/dist/{chunk-IB76KGBY.js → chunk-POEPHBQK.js} +1 -1
  31. package/dist/{chunk-7OYXB2NM.js → chunk-REN37KYI.js} +6 -2
  32. package/dist/chunk-REN37KYI.js.map +1 -0
  33. package/dist/{chunk-JDI4DPWD.js → chunk-RXROZBSK.js} +637 -150
  34. package/dist/chunk-RXROZBSK.js.map +1 -0
  35. package/dist/{chunk-U3J2DDSR.js → chunk-SCI55NKY.js} +2 -2
  36. package/dist/{chunk-GDY63YAW.js → chunk-U6PF3YII.js} +79 -79
  37. package/dist/chunk-U6PF3YII.js.map +1 -0
  38. package/dist/{chunk-FABWUX5G.js → chunk-UVKQ62II.js} +18 -4
  39. package/dist/chunk-UVKQ62II.js.map +1 -0
  40. package/dist/{chunk-VOCGURV7.js → chunk-UW6DGPSV.js} +3 -3
  41. package/dist/{chunk-CKJAWZQE.js → chunk-W4VHC2ES.js} +11 -3
  42. package/dist/chunk-W4VHC2ES.js.map +1 -0
  43. package/dist/{chunk-75AZFBFW.js → chunk-YPWF322W.js} +3 -3
  44. package/dist/{cli-IIMBALPV.js → cli-X7CFP4YD.js} +39 -39
  45. package/dist/{client-VZCUISHZ.js → client-YA33HUFY.js} +4 -4
  46. package/dist/{config-DA4IUVFL.js → config-RFB2DJC6.js} +6 -6
  47. package/dist/{detect-GEM3NVK6.js → detect-BEOIHGBC.js} +5 -5
  48. package/dist/{detect-providers-PSVKXTWE.js → detect-providers-2OQBU4VX.js} +4 -4
  49. package/dist/{doctor-QYD34X7Q.js → doctor-FAH7N66M.js} +11 -11
  50. package/dist/{executor-NSPRTH4M.js → executor-ICTRRUBY.js} +93 -285
  51. package/dist/executor-ICTRRUBY.js.map +1 -0
  52. package/dist/{init-WYYL44KZ.js → init-PTJEOTJV.js} +15 -15
  53. package/dist/{llm-KEDHK3TQ.js → llm-7D2OGDEK.js} +4 -4
  54. package/dist/{loader-Q3P3R4UP.js → loader-O2JFO2UC.js} +6 -6
  55. package/dist/{loader-SKKUMT5C.js → loader-VPE4RCIF.js} +6 -6
  56. package/dist/{main-6PY3ITQ5.js → main-EIKBLOUL.js} +752 -264
  57. package/dist/main-EIKBLOUL.js.map +1 -0
  58. package/dist/{open-HRFMJDQX.js → open-2JCSOLZS.js} +6 -6
  59. package/dist/{post-compact-HT24YMAN.js → post-compact-2HPPWPBI.js} +10 -10
  60. package/dist/{post-tool-use-DENRI5WB.js → post-tool-use-TWBBBABS.js} +9 -9
  61. package/dist/{post-tool-use-failure-A6SNJX42.js → post-tool-use-failure-LIJYR4KL.js} +10 -10
  62. package/dist/{pre-compact-3Q4BALCL.js → pre-compact-II2CMNTG.js} +10 -10
  63. package/dist/{provider-check-AE3L5Z6R.js → provider-check-KEQNQ6LO.js} +4 -4
  64. package/dist/{registry-O2NZLO3V.js → registry-X5FDGYXT.js} +7 -7
  65. package/dist/{remove-YB5A6HY2.js → remove-L5MVYBOY.js} +11 -11
  66. package/dist/{resolution-events-XWYLLDRK.js → resolution-events-MVIZMONR.js} +4 -4
  67. package/dist/{restart-RGDVHELZ.js → restart-VIT3JBD6.js} +7 -7
  68. package/dist/{search-WOHT3G55.js → search-O6BB5MTO.js} +7 -7
  69. package/dist/{server-6SUNYDV7.js → server-O3UPJVBR.js} +258 -173
  70. package/dist/server-O3UPJVBR.js.map +1 -0
  71. package/dist/{session-W3SKRFRV.js → session-5JV3DQIK.js} +8 -8
  72. package/dist/{session-end-OUTY7AFF.js → session-end-PZ2OXBGG.js} +9 -9
  73. package/dist/{session-start-5MB3LFOA.js → session-start-FDGM56BX.js} +22 -17
  74. package/dist/{session-start-5MB3LFOA.js.map → session-start-FDGM56BX.js.map} +1 -1
  75. package/dist/{setup-llm-ZMYGIQX5.js → setup-llm-MQK557BB.js} +10 -10
  76. package/dist/src/agent/definitions/tasks/extract-only.yaml +1 -1
  77. package/dist/src/agent/definitions/tasks/full-intelligence.yaml +10 -0
  78. package/dist/src/agent/definitions/tasks/skill-evolve.yaml +163 -49
  79. package/dist/src/agent/definitions/tasks/skill-generate.yaml +44 -27
  80. package/dist/src/agent/definitions/tasks/skill-survey.yaml +132 -138
  81. package/dist/src/agent/definitions/tasks/supersession-sweep.yaml +1 -1
  82. package/dist/src/cli.js +1 -1
  83. package/dist/src/daemon/main.js +1 -1
  84. package/dist/src/hooks/post-tool-use.js +1 -1
  85. package/dist/src/hooks/session-end.js +1 -1
  86. package/dist/src/hooks/session-start.js +1 -1
  87. package/dist/src/hooks/stop.js +1 -1
  88. package/dist/src/hooks/user-prompt-submit.js +1 -1
  89. package/dist/src/mcp/server.js +1 -1
  90. package/dist/src/symbionts/manifests/codex.yaml +45 -7
  91. package/dist/{stats-DGI6B3HX.js → stats-2STTARTC.js} +11 -11
  92. package/dist/{stop-YGHODSP7.js → stop-WNKCMCGO.js} +9 -9
  93. package/dist/{stop-failure-7IJTPJ6W.js → stop-failure-6GTOBVTN.js} +10 -10
  94. package/dist/{subagent-start-ZBQ5PJB5.js → subagent-start-VJF5YKVX.js} +10 -10
  95. package/dist/{subagent-stop-N2TDQU2D.js → subagent-stop-UW6HMICY.js} +10 -10
  96. package/dist/{task-completed-BDLMRSBB.js → task-completed-U4Q3XXLX.js} +10 -10
  97. package/dist/{team-2ZFGTSIN.js → team-N6TXS2PF.js} +148 -103
  98. package/dist/team-N6TXS2PF.js.map +1 -0
  99. package/dist/ui/assets/{index-DtT9_nlT.js → index-CHIm98OP.js} +48 -48
  100. package/dist/ui/index.html +1 -1
  101. package/dist/{update-STLAN7LR.js → update-ZYCOWKMD.js} +11 -11
  102. package/dist/{user-prompt-submit-4IBFUYQ3.js → user-prompt-submit-SOYL4OWF.js} +15 -12
  103. package/dist/user-prompt-submit-SOYL4OWF.js.map +1 -0
  104. package/dist/{verify-EJYPO7QA.js → verify-P37PQ4YM.js} +8 -8
  105. package/dist/{version-YPBIKH77.js → version-XAWC277D.js} +2 -2
  106. package/package.json +25 -8
  107. package/CONTRIBUTING.md +0 -132
  108. package/dist/chunk-7OYXB2NM.js.map +0 -1
  109. package/dist/chunk-CKJAWZQE.js.map +0 -1
  110. package/dist/chunk-D7TYRPRM.js.map +0 -1
  111. package/dist/chunk-DLFDBKEV.js.map +0 -1
  112. package/dist/chunk-FABWUX5G.js.map +0 -1
  113. package/dist/chunk-GDY63YAW.js.map +0 -1
  114. package/dist/chunk-JDI4DPWD.js.map +0 -1
  115. package/dist/chunk-JMOUFG6Y.js.map +0 -1
  116. package/dist/chunk-KWTOCJLB.js.map +0 -1
  117. package/dist/chunk-NZI7WBZI.js.map +0 -1
  118. package/dist/chunk-OW433Q4C.js.map +0 -1
  119. package/dist/chunk-RJMXDUMA.js +0 -40
  120. package/dist/chunk-RJMXDUMA.js.map +0 -1
  121. package/dist/chunk-U7GJTVSX.js.map +0 -1
  122. package/dist/executor-NSPRTH4M.js.map +0 -1
  123. package/dist/main-6PY3ITQ5.js.map +0 -1
  124. package/dist/server-6SUNYDV7.js.map +0 -1
  125. package/dist/src/worker/package-lock.json +0 -4338
  126. package/dist/src/worker/package.json +0 -22
  127. package/dist/src/worker/src/auth.ts +0 -31
  128. package/dist/src/worker/src/index.ts +0 -470
  129. package/dist/src/worker/src/mcp/auth.ts +0 -65
  130. package/dist/src/worker/src/mcp/server.ts +0 -53
  131. package/dist/src/worker/src/mcp/tools/context.ts +0 -13
  132. package/dist/src/worker/src/mcp/tools/get.ts +0 -15
  133. package/dist/src/worker/src/mcp/tools/graph.ts +0 -35
  134. package/dist/src/worker/src/mcp/tools/search.ts +0 -32
  135. package/dist/src/worker/src/mcp/tools/sessions.ts +0 -24
  136. package/dist/src/worker/src/mcp/tools/skills.ts +0 -16
  137. package/dist/src/worker/src/mcp/tools/team.ts +0 -9
  138. package/dist/src/worker/src/schema.ts +0 -324
  139. package/dist/src/worker/src/search-helpers.ts +0 -70
  140. package/dist/src/worker/tsconfig.json +0 -16
  141. package/dist/src/worker/wrangler.toml +0 -30
  142. package/dist/team-2ZFGTSIN.js.map +0 -1
  143. package/dist/user-prompt-submit-4IBFUYQ3.js.map +0 -1
  144. /package/dist/{agent-run-2NFYMQXW.js.map → agent-run-EADUYYAS.js.map} +0 -0
  145. /package/dist/{agent-tasks-MEIYLXGN.js.map → agent-tasks-GC77JXQB.js.map} +0 -0
  146. /package/dist/{chunk-EO2RQW4S.js.map → chunk-2CKDAFSX.js.map} +0 -0
  147. /package/dist/{chunk-RAV5YMRU.js.map → chunk-3TPD6HEF.js.map} +0 -0
  148. /package/dist/{chunk-NI23QCHB.js.map → chunk-AELJ4PS5.js.map} +0 -0
  149. /package/dist/{chunk-BUIR3JWM.js.map → chunk-CYBC2HZ3.js.map} +0 -0
  150. /package/dist/{chunk-O3TRN3RC.js.map → chunk-INWD6AIQ.js.map} +0 -0
  151. /package/dist/{chunk-CML4MCYF.js.map → chunk-KSXTNYXO.js.map} +0 -0
  152. /package/dist/{chunk-2V7HR7HB.js.map → chunk-MDEUXYJG.js.map} +0 -0
  153. /package/dist/{chunk-PFWIPRF6.js.map → chunk-MS6FDV45.js.map} +0 -0
  154. /package/dist/{chunk-55QEICRO.js.map → chunk-N77K772N.js.map} +0 -0
  155. /package/dist/{chunk-E4VLWIJC.js.map → chunk-ODXLRR4U.js.map} +0 -0
  156. /package/dist/{chunk-IB76KGBY.js.map → chunk-POEPHBQK.js.map} +0 -0
  157. /package/dist/{chunk-U3J2DDSR.js.map → chunk-SCI55NKY.js.map} +0 -0
  158. /package/dist/{chunk-VOCGURV7.js.map → chunk-UW6DGPSV.js.map} +0 -0
  159. /package/dist/{chunk-75AZFBFW.js.map → chunk-YPWF322W.js.map} +0 -0
  160. /package/dist/{cli-IIMBALPV.js.map → cli-X7CFP4YD.js.map} +0 -0
  161. /package/dist/{client-VZCUISHZ.js.map → client-YA33HUFY.js.map} +0 -0
  162. /package/dist/{config-DA4IUVFL.js.map → config-RFB2DJC6.js.map} +0 -0
  163. /package/dist/{detect-GEM3NVK6.js.map → detect-BEOIHGBC.js.map} +0 -0
  164. /package/dist/{detect-providers-PSVKXTWE.js.map → detect-providers-2OQBU4VX.js.map} +0 -0
  165. /package/dist/{doctor-QYD34X7Q.js.map → doctor-FAH7N66M.js.map} +0 -0
  166. /package/dist/{init-WYYL44KZ.js.map → init-PTJEOTJV.js.map} +0 -0
  167. /package/dist/{llm-KEDHK3TQ.js.map → llm-7D2OGDEK.js.map} +0 -0
  168. /package/dist/{loader-Q3P3R4UP.js.map → loader-O2JFO2UC.js.map} +0 -0
  169. /package/dist/{loader-SKKUMT5C.js.map → loader-VPE4RCIF.js.map} +0 -0
  170. /package/dist/{open-HRFMJDQX.js.map → open-2JCSOLZS.js.map} +0 -0
  171. /package/dist/{post-compact-HT24YMAN.js.map → post-compact-2HPPWPBI.js.map} +0 -0
  172. /package/dist/{post-tool-use-DENRI5WB.js.map → post-tool-use-TWBBBABS.js.map} +0 -0
  173. /package/dist/{post-tool-use-failure-A6SNJX42.js.map → post-tool-use-failure-LIJYR4KL.js.map} +0 -0
  174. /package/dist/{pre-compact-3Q4BALCL.js.map → pre-compact-II2CMNTG.js.map} +0 -0
  175. /package/dist/{provider-check-AE3L5Z6R.js.map → provider-check-KEQNQ6LO.js.map} +0 -0
  176. /package/dist/{registry-O2NZLO3V.js.map → registry-X5FDGYXT.js.map} +0 -0
  177. /package/dist/{remove-YB5A6HY2.js.map → remove-L5MVYBOY.js.map} +0 -0
  178. /package/dist/{resolution-events-XWYLLDRK.js.map → resolution-events-MVIZMONR.js.map} +0 -0
  179. /package/dist/{restart-RGDVHELZ.js.map → restart-VIT3JBD6.js.map} +0 -0
  180. /package/dist/{search-WOHT3G55.js.map → search-O6BB5MTO.js.map} +0 -0
  181. /package/dist/{session-W3SKRFRV.js.map → session-5JV3DQIK.js.map} +0 -0
  182. /package/dist/{session-end-OUTY7AFF.js.map → session-end-PZ2OXBGG.js.map} +0 -0
  183. /package/dist/{setup-llm-ZMYGIQX5.js.map → setup-llm-MQK557BB.js.map} +0 -0
  184. /package/dist/{stats-DGI6B3HX.js.map → stats-2STTARTC.js.map} +0 -0
  185. /package/dist/{stop-YGHODSP7.js.map → stop-WNKCMCGO.js.map} +0 -0
  186. /package/dist/{stop-failure-7IJTPJ6W.js.map → stop-failure-6GTOBVTN.js.map} +0 -0
  187. /package/dist/{subagent-start-ZBQ5PJB5.js.map → subagent-start-VJF5YKVX.js.map} +0 -0
  188. /package/dist/{subagent-stop-N2TDQU2D.js.map → subagent-stop-UW6HMICY.js.map} +0 -0
  189. /package/dist/{task-completed-BDLMRSBB.js.map → task-completed-U4Q3XXLX.js.map} +0 -0
  190. /package/dist/{update-STLAN7LR.js.map → update-ZYCOWKMD.js.map} +0 -0
  191. /package/dist/{verify-EJYPO7QA.js.map → verify-P37PQ4YM.js.map} +0 -0
  192. /package/dist/{version-YPBIKH77.js.map → version-XAWC277D.js.map} +0 -0
@@ -15,16 +15,18 @@ import {
15
15
  getEmbeddingQueueDepth,
16
16
  getUnembedded,
17
17
  markEmbedded
18
- } from "./chunk-DLFDBKEV.js";
18
+ } from "./chunk-OZF5EURR.js";
19
19
  import {
20
20
  loadSecrets,
21
+ readJsonConfig,
21
22
  readSecrets,
23
+ resolveHomeConfigPath,
22
24
  writeSecret
23
- } from "./chunk-RJMXDUMA.js";
25
+ } from "./chunk-EM63ZFKA.js";
24
26
  import {
25
27
  Anthropic,
26
28
  createEmbeddingProvider
27
- } from "./chunk-KWTOCJLB.js";
29
+ } from "./chunk-LLJMDXO2.js";
28
30
  import {
29
31
  buildTaskInstruction,
30
32
  closeOpenBatches,
@@ -72,24 +74,24 @@ import {
72
74
  setResponseSummary,
73
75
  updateCandidate,
74
76
  updateNotificationStatus
75
- } from "./chunk-JDI4DPWD.js";
77
+ } from "./chunk-RXROZBSK.js";
76
78
  import {
77
79
  fullTextSearch,
78
80
  hydrateSearchResults
79
- } from "./chunk-NZI7WBZI.js";
81
+ } from "./chunk-2DF4OZ2D.js";
80
82
  import {
81
83
  copyTaskToUser,
82
84
  deleteUserTask,
83
85
  loadAllTasks,
84
86
  validateTaskName,
85
87
  writeUserTask
86
- } from "./chunk-RAV5YMRU.js";
88
+ } from "./chunk-3TPD6HEF.js";
87
89
  import {
88
90
  AgentTaskSchema,
89
91
  registerAgent,
90
92
  resolveDefinitionsDir,
91
93
  taskFromParsed
92
- } from "./chunk-NI23QCHB.js";
94
+ } from "./chunk-AELJ4PS5.js";
93
95
  import {
94
96
  listTurnsByRun
95
97
  } from "./chunk-QLCD77AN.js";
@@ -105,24 +107,24 @@ import {
105
107
  cleanStaleBuffers,
106
108
  listBufferSessionIds
107
109
  } from "./chunk-V7XG6V6C.js";
108
- import "./chunk-IB76KGBY.js";
109
- import "./chunk-55QEICRO.js";
110
+ import "./chunk-POEPHBQK.js";
111
+ import "./chunk-N77K772N.js";
110
112
  import "./chunk-SAKJMNSR.js";
111
113
  import "./chunk-WYOE4IAX.js";
112
114
  import {
113
115
  checkLocalProvider
114
- } from "./chunk-75AZFBFW.js";
116
+ } from "./chunk-YPWF322W.js";
115
117
  import {
116
118
  LmStudioBackend,
117
119
  OllamaBackend
118
- } from "./chunk-CML4MCYF.js";
120
+ } from "./chunk-KSXTNYXO.js";
119
121
  import {
120
122
  countSpores,
121
123
  getSpore,
122
124
  insertSpore,
123
125
  listSpores,
124
126
  updateSporeStatus
125
- } from "./chunk-7OYXB2NM.js";
127
+ } from "./chunk-REN37KYI.js";
126
128
  import {
127
129
  closeSession,
128
130
  countSessions,
@@ -133,7 +135,7 @@ import {
133
135
  listSessions,
134
136
  updateSession,
135
137
  upsertSession
136
- } from "./chunk-U7GJTVSX.js";
138
+ } from "./chunk-2OO3BRFK.js";
137
139
  import {
138
140
  backfillUnsynced,
139
141
  countDeadLettered,
@@ -149,13 +151,13 @@ import {
149
151
  pruneOld,
150
152
  retryDeadLettered,
151
153
  syncRow
152
- } from "./chunk-O3TRN3RC.js";
154
+ } from "./chunk-INWD6AIQ.js";
153
155
  import {
154
156
  EMBEDDING_DIMENSIONS,
155
157
  REST_SETTABLE_STATUSES,
156
158
  SCHEMA_VERSION,
157
159
  createSchema
158
- } from "./chunk-OW433Q4C.js";
160
+ } from "./chunk-2LN2BBKA.js";
159
161
  import {
160
162
  CONFIG_FILENAME,
161
163
  MycoConfigSchema,
@@ -164,7 +166,7 @@ import {
164
166
  updateBackupConfig,
165
167
  updateConfig,
166
168
  updateTeamConfig
167
- } from "./chunk-2V7HR7HB.js";
169
+ } from "./chunk-MDEUXYJG.js";
168
170
  import {
169
171
  closeDatabase,
170
172
  getDatabase,
@@ -173,13 +175,13 @@ import {
173
175
  } from "./chunk-MYX5NCRH.js";
174
176
  import {
175
177
  resolveCliEntryPath
176
- } from "./chunk-BUIR3JWM.js";
178
+ } from "./chunk-CYBC2HZ3.js";
177
179
  import {
178
180
  getPluginVersion
179
- } from "./chunk-EO2RQW4S.js";
181
+ } from "./chunk-2CKDAFSX.js";
180
182
  import {
181
183
  loadManifests
182
- } from "./chunk-FABWUX5G.js";
184
+ } from "./chunk-UVKQ62II.js";
183
185
  import {
184
186
  findPackageRoot
185
187
  } from "./chunk-LPUQPDC2.js";
@@ -201,7 +203,7 @@ import {
201
203
  MS_PER_SECOND,
202
204
  MYCO_GLOBAL_DIR,
203
205
  NPM_PACKAGE_NAME,
204
- NPM_REGISTRY_URL,
206
+ NPM_REGISTRY_BASE_URL,
205
207
  POWER_ACTIVE_INTERVAL_MS,
206
208
  POWER_DEEP_SLEEP_THRESHOLD_MS,
207
209
  POWER_IDLE_THRESHOLD_MS,
@@ -228,6 +230,7 @@ import {
228
230
  UPDATE_CHECK_INTERVAL_HOURS,
229
231
  UPDATE_CONFIG_PATH,
230
232
  UPDATE_ERROR_PATH,
233
+ UPDATE_PACKAGES,
231
234
  UPDATE_SCRIPT_DELAY_SECONDS,
232
235
  UPDATE_STAMP_FILENAME,
233
236
  USER_AGENT_ID,
@@ -235,18 +238,18 @@ import {
235
238
  USER_TASK_SOURCE,
236
239
  epochSeconds,
237
240
  estimateTokens
238
- } from "./chunk-CKJAWZQE.js";
241
+ } from "./chunk-W4VHC2ES.js";
239
242
  import {
240
243
  LOG_KINDS,
241
244
  kindToComponent
242
245
  } from "./chunk-E7NUADTQ.js";
243
246
  import {
244
247
  require_dist
245
- } from "./chunk-D7TYRPRM.js";
246
- import "./chunk-E4VLWIJC.js";
248
+ } from "./chunk-6LQIMRTC.js";
249
+ import "./chunk-ODXLRR4U.js";
247
250
  import {
248
251
  external_exports
249
- } from "./chunk-GDY63YAW.js";
252
+ } from "./chunk-U6PF3YII.js";
250
253
  import {
251
254
  __toESM
252
255
  } from "./chunk-PZUWP5VK.js";
@@ -372,7 +375,7 @@ var DaemonServer = class {
372
375
  this.router.add(method, routePath, handler);
373
376
  }
374
377
  async start(port = 0) {
375
- return new Promise((resolve, reject) => {
378
+ return new Promise((resolve3, reject) => {
376
379
  this.server = http.createServer((req, res) => this.handleRequest(req, res));
377
380
  this.server.on("error", reject);
378
381
  this.server.listen(port, "127.0.0.1", () => {
@@ -380,20 +383,20 @@ var DaemonServer = class {
380
383
  this.port = addr.port;
381
384
  this.writeDaemonJson();
382
385
  this.logger.info(LOG_KINDS.DAEMON_PORT, "Server started", { port: this.port, dashboard: `http://localhost:${this.port}/` });
383
- resolve();
386
+ resolve3();
384
387
  });
385
388
  });
386
389
  }
387
390
  async stop() {
388
- return new Promise((resolve) => {
391
+ return new Promise((resolve3) => {
389
392
  this.removeDaemonJson();
390
393
  if (this.server) {
391
394
  this.server.close(() => {
392
395
  this.logger.info(LOG_KINDS.DAEMON_START, "Server stopped");
393
- resolve();
396
+ resolve3();
394
397
  });
395
398
  } else {
396
- resolve();
399
+ resolve3();
397
400
  }
398
401
  });
399
402
  }
@@ -541,14 +544,14 @@ var DaemonServer = class {
541
544
  }
542
545
  };
543
546
  function readBody(req) {
544
- return new Promise((resolve, reject) => {
547
+ return new Promise((resolve3, reject) => {
545
548
  let data = "";
546
549
  req.on("data", (chunk) => {
547
550
  data += chunk;
548
551
  });
549
552
  req.on("end", () => {
550
553
  try {
551
- resolve(data ? JSON.parse(data) : {});
554
+ resolve3(data ? JSON.parse(data) : {});
552
555
  } catch (e) {
553
556
  reject(e);
554
557
  }
@@ -628,11 +631,11 @@ async function resolvePort(configPort, vaultPath) {
628
631
  return 0;
629
632
  }
630
633
  function isPortAvailable(port) {
631
- return new Promise((resolve) => {
634
+ return new Promise((resolve3) => {
632
635
  const server = net.createServer();
633
- server.once("error", () => resolve(false));
636
+ server.once("error", () => resolve3(false));
634
637
  server.once("listening", () => {
635
- server.close(() => resolve(true));
638
+ server.close(() => resolve3(true));
636
639
  });
637
640
  server.listen(port, "127.0.0.1");
638
641
  });
@@ -641,6 +644,53 @@ function isPortAvailable(port) {
641
644
  // src/symbionts/adapter.ts
642
645
  import fs3 from "fs";
643
646
  import path3 from "path";
647
+
648
+ // src/symbionts/parsers/standard-jsonl.ts
649
+ var IMAGE_TEXT_REF_PATTERN = /\[Image: source: [^\]]+\]\n*/g;
650
+ var StandardJsonlParser = class {
651
+ constructor(opts) {
652
+ this.opts = opts;
653
+ }
654
+ parseTurns(content) {
655
+ const lines = content.split("\n").filter(Boolean);
656
+ const turns = [];
657
+ let current = null;
658
+ for (const line of lines) {
659
+ let entry;
660
+ try {
661
+ entry = JSON.parse(line);
662
+ } catch {
663
+ continue;
664
+ }
665
+ const role = entry[this.opts.roleField];
666
+ const timestamp = this.opts.extractTimestamp ? entry.timestamp ?? "" : "";
667
+ if (role === "user") {
668
+ if (entry.isMeta === true) continue;
669
+ const msg = entry.message;
670
+ const blocks = Array.isArray(msg?.content) ? msg.content : [];
671
+ const hasText = blocks.some((b) => b.type === "text" && b.text?.trim());
672
+ if (!hasText) continue;
673
+ if (current) turns.push(current);
674
+ const rawPrompt = blocks.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("\n");
675
+ const promptText = (this.opts.stripImageTextRefs ? rawPrompt.replace(IMAGE_TEXT_REF_PATTERN, "") : rawPrompt).trim().slice(0, PROMPT_PREVIEW_CHARS);
676
+ const images = blocks.filter((b) => b.type === "image" && b.source?.type === "base64" && b.source.data).map((b) => ({ data: b.source.data, mediaType: b.source.media_type ?? "image/png" }));
677
+ current = { prompt: promptText, toolCount: 0, timestamp, ...images.length > 0 ? { images } : {} };
678
+ } else if (role === "assistant" && current) {
679
+ const msg = entry.message;
680
+ if (Array.isArray(msg?.content)) {
681
+ const textParts = msg.content.filter((b) => b.type === "text" && b.text).map((b) => b.text);
682
+ const text = textParts.join("\n").trim();
683
+ if (text) current.aiResponse = text;
684
+ current.toolCount += msg.content.filter((b) => b.type === "tool_use").length;
685
+ }
686
+ }
687
+ }
688
+ if (current) turns.push(current);
689
+ return turns;
690
+ }
691
+ };
692
+
693
+ // src/symbionts/adapter.ts
644
694
  function findJsonlInSubdirs(baseDir, sessionId) {
645
695
  try {
646
696
  for (const entry of fs3.readdirSync(baseDir, { withFileTypes: true })) {
@@ -685,44 +735,8 @@ var EXT_TO_MIME = {
685
735
  function mimeTypeForExtension(ext) {
686
736
  return EXT_TO_MIME[ext.toLowerCase()] ?? "image/png";
687
737
  }
688
- var IMAGE_TEXT_REF_PATTERN = /\[Image: source: [^\]]+\]\n*/g;
689
738
  function parseJsonlTurns(content, opts) {
690
- const lines = content.split("\n").filter(Boolean);
691
- const turns = [];
692
- let current = null;
693
- for (const line of lines) {
694
- let entry;
695
- try {
696
- entry = JSON.parse(line);
697
- } catch {
698
- continue;
699
- }
700
- const role = entry[opts.roleField];
701
- const timestamp = opts.extractTimestamp ? entry.timestamp ?? "" : "";
702
- if (role === "user") {
703
- if (entry.isMeta === true) continue;
704
- const msg = entry.message;
705
- const blocks = Array.isArray(msg?.content) ? msg.content : [];
706
- const hasText = blocks.some((b) => b.type === "text" && b.text?.trim());
707
- if (!hasText && opts.skipToolResultUsers) continue;
708
- if (!hasText) continue;
709
- if (current) turns.push(current);
710
- const rawPrompt = blocks.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("\n");
711
- const promptText = (opts.stripImageTextRefs ? rawPrompt.replace(IMAGE_TEXT_REF_PATTERN, "") : rawPrompt).trim().slice(0, PROMPT_PREVIEW_CHARS);
712
- const images = blocks.filter((b) => b.type === "image" && b.source?.type === "base64" && b.source.data).map((b) => ({ data: b.source.data, mediaType: b.source.media_type ?? "image/png" }));
713
- current = { prompt: promptText, toolCount: 0, timestamp, ...images.length > 0 ? { images } : {} };
714
- } else if (role === "assistant" && current) {
715
- const msg = entry.message;
716
- if (Array.isArray(msg?.content)) {
717
- const textParts = msg.content.filter((b) => b.type === "text" && b.text).map((b) => b.text);
718
- const text = textParts.join("\n").trim();
719
- if (text) current.aiResponse = text;
720
- current.toolCount += msg.content.filter((b) => b.type === "tool_use").length;
721
- }
722
- }
723
- }
724
- if (current) turns.push(current);
725
- return turns;
739
+ return new StandardJsonlParser(opts).parseTurns(content);
726
740
  }
727
741
 
728
742
  // src/symbionts/claude-code.ts
@@ -876,10 +890,100 @@ function parseCursorText(content) {
876
890
  return turns;
877
891
  }
878
892
 
893
+ // src/symbionts/parsers/codex-jsonl.ts
894
+ function parseDataUrl(url) {
895
+ const match = url.match(/^data:([^;]+);base64,(.+)$/);
896
+ if (!match) return null;
897
+ return { mediaType: match[1], data: match[2] };
898
+ }
899
+ var IMAGE_WRAPPER_TAG = /^<\/?image\b[^>]*>$/;
900
+ var CODEX_PROMPT_MARKER = "## My request for Codex:\n";
901
+ function cleanCodexPromptText(text) {
902
+ if (IMAGE_WRAPPER_TAG.test(text.trim())) return "";
903
+ const idx = text.indexOf(CODEX_PROMPT_MARKER);
904
+ if (idx !== -1) return text.slice(idx + CODEX_PROMPT_MARKER.length);
905
+ return text;
906
+ }
907
+ var CodexJsonlParser = class {
908
+ parseTurns(content) {
909
+ const lines = content.split("\n").filter(Boolean);
910
+ const turns = [];
911
+ let current = null;
912
+ for (const line of lines) {
913
+ let entry;
914
+ try {
915
+ entry = JSON.parse(line);
916
+ } catch {
917
+ continue;
918
+ }
919
+ if (entry.type !== "response_item") continue;
920
+ const payload = entry.payload;
921
+ if (!payload) continue;
922
+ const payloadType = payload.type;
923
+ const timestamp = entry.timestamp ?? "";
924
+ if (payloadType === "function_call") {
925
+ if (current) current.toolCount++;
926
+ continue;
927
+ }
928
+ if (payloadType !== "message") continue;
929
+ const role = payload.role;
930
+ const blocks = Array.isArray(payload.content) ? payload.content : [];
931
+ if (role === "user") {
932
+ const textParts = blocks.filter((b) => b.type === "input_text" && b.text?.trim()).map((b) => cleanCodexPromptText(b.text)).filter((t) => t.trim());
933
+ if (textParts.length === 0) continue;
934
+ if (current) turns.push(current);
935
+ const promptText = textParts.join("\n").trim().slice(0, PROMPT_PREVIEW_CHARS);
936
+ const images = [];
937
+ for (const b of blocks) {
938
+ if (b.type === "input_image" && b.image_url) {
939
+ const parsed = parseDataUrl(b.image_url);
940
+ if (parsed) images.push(parsed);
941
+ }
942
+ }
943
+ current = { prompt: promptText, toolCount: 0, timestamp, ...images.length > 0 ? { images } : {} };
944
+ } else if (role === "assistant" && current) {
945
+ const textParts = blocks.filter((b) => b.type === "output_text" && b.text).map((b) => b.text);
946
+ const text = textParts.join("\n").trim();
947
+ if (text) current.aiResponse = text;
948
+ }
949
+ }
950
+ if (current) turns.push(current);
951
+ return turns;
952
+ }
953
+ };
954
+
879
955
  // src/symbionts/codex.ts
956
+ import fs5 from "fs";
880
957
  import path6 from "path";
881
958
  import os3 from "os";
882
959
  var TRANSCRIPT_BASE2 = path6.join(os3.homedir(), ".codex");
960
+ var codexParser = new CodexJsonlParser();
961
+ function findCodexTranscript(baseDir, sessionId) {
962
+ const sessionsDir = path6.join(baseDir, "sessions");
963
+ try {
964
+ return scanForSessionFile(sessionsDir, sessionId);
965
+ } catch {
966
+ return null;
967
+ }
968
+ }
969
+ function scanForSessionFile(dir, sessionId) {
970
+ let entries;
971
+ try {
972
+ entries = fs5.readdirSync(dir, { withFileTypes: true });
973
+ } catch {
974
+ return null;
975
+ }
976
+ for (const entry of entries) {
977
+ const fullPath = path6.join(dir, entry.name);
978
+ if (entry.isDirectory()) {
979
+ const found = scanForSessionFile(fullPath, sessionId);
980
+ if (found) return found;
981
+ } else if (entry.isFile() && entry.name.includes(sessionId) && entry.name.endsWith(".jsonl")) {
982
+ return fullPath;
983
+ }
984
+ }
985
+ return null;
986
+ }
883
987
  var codexAdapter = {
884
988
  name: "codex",
885
989
  displayName: "Codex",
@@ -893,18 +997,12 @@ var codexAdapter = {
893
997
  toolInput: "tool_input",
894
998
  toolOutput: "tool_output"
895
999
  },
896
- findTranscript: (sessionId) => findJsonlInSubdirs(TRANSCRIPT_BASE2, sessionId),
897
- // Codex uses 'role' field (like Cursor), not 'type' (like Claude Code)
898
- parseTurns: (content) => parseJsonlTurns(content, {
899
- roleField: "role",
900
- extractTimestamp: false,
901
- skipToolResultUsers: false,
902
- stripImageTextRefs: false
903
- })
1000
+ findTranscript: (sessionId) => findCodexTranscript(TRANSCRIPT_BASE2, sessionId),
1001
+ parseTurns: (content) => codexParser.parseTurns(content)
904
1002
  };
905
1003
 
906
1004
  // src/symbionts/gemini.ts
907
- import fs5 from "fs";
1005
+ import fs6 from "fs";
908
1006
  import path7 from "path";
909
1007
  import os4 from "os";
910
1008
  var GEMINI_TMP = path7.join(os4.homedir(), ".gemini", "tmp");
@@ -924,15 +1022,15 @@ var geminiAdapter = {
924
1022
  },
925
1023
  findTranscript(sessionId) {
926
1024
  try {
927
- for (const project of fs5.readdirSync(GEMINI_TMP, { withFileTypes: true })) {
1025
+ for (const project of fs6.readdirSync(GEMINI_TMP, { withFileTypes: true })) {
928
1026
  if (!project.isDirectory()) continue;
929
1027
  const chatsDir = path7.join(GEMINI_TMP, project.name, "chats");
930
1028
  try {
931
- for (const file of fs5.readdirSync(chatsDir)) {
1029
+ for (const file of fs6.readdirSync(chatsDir)) {
932
1030
  if (!file.endsWith(".json")) continue;
933
1031
  if (file.includes(sessionId.slice(0, 8))) {
934
1032
  try {
935
- const data = JSON.parse(fs5.readFileSync(path7.join(chatsDir, file), "utf-8"));
1033
+ const data = JSON.parse(fs6.readFileSync(path7.join(chatsDir, file), "utf-8"));
936
1034
  if (data.sessionId === sessionId) {
937
1035
  return path7.join(chatsDir, file);
938
1036
  }
@@ -986,7 +1084,7 @@ function parseGeminiJson(content) {
986
1084
  }
987
1085
 
988
1086
  // src/symbionts/windsurf.ts
989
- import fs6 from "fs";
1087
+ import fs7 from "fs";
990
1088
  import path8 from "path";
991
1089
  import os5 from "os";
992
1090
  var TRANSCRIPT_DIR = path8.join(os5.homedir(), ".windsurf", "transcripts");
@@ -1009,7 +1107,7 @@ var windsurfAdapter = {
1009
1107
  findTranscript(sessionId) {
1010
1108
  const candidate = path8.join(TRANSCRIPT_DIR, `${sessionId}.jsonl`);
1011
1109
  try {
1012
- fs6.accessSync(candidate);
1110
+ fs7.accessSync(candidate);
1013
1111
  return candidate;
1014
1112
  } catch {
1015
1113
  return null;
@@ -1144,7 +1242,7 @@ function normalizeResponseParts(response) {
1144
1242
  }
1145
1243
 
1146
1244
  // src/symbionts/registry.ts
1147
- import fs7 from "fs";
1245
+ import fs8 from "fs";
1148
1246
  var ALL_ADAPTERS = [
1149
1247
  claudeCodeAdapter,
1150
1248
  cursorAdapter,
@@ -1167,7 +1265,7 @@ var SymbiontRegistry = class {
1167
1265
  const filePath = adapter.findTranscript(sessionId);
1168
1266
  if (!filePath) continue;
1169
1267
  try {
1170
- const content = fs7.readFileSync(filePath, "utf-8");
1268
+ const content = fs8.readFileSync(filePath, "utf-8");
1171
1269
  const turns = adapter.parseTurns(content);
1172
1270
  if (turns.length > 0) {
1173
1271
  return { turns, source: adapter.name };
@@ -1201,7 +1299,7 @@ var SymbiontRegistry = class {
1201
1299
  */
1202
1300
  parseTurnsFromPath(filePath) {
1203
1301
  try {
1204
- const content = fs7.readFileSync(filePath, "utf-8");
1302
+ const content = fs8.readFileSync(filePath, "utf-8");
1205
1303
  const active = this.detectActiveAgent();
1206
1304
  const orderedAdapters = active ? [active, ...this.adapters.filter((a) => a !== active)] : this.adapters;
1207
1305
  for (const adapter of orderedAdapters) {
@@ -1601,7 +1699,7 @@ async function handleRestart(deps, body) {
1601
1699
 
1602
1700
  // src/daemon/update-checker.ts
1603
1701
  var import_yaml = __toESM(require_dist(), 1);
1604
- import fs8 from "fs";
1702
+ import fs9 from "fs";
1605
1703
  import path9 from "path";
1606
1704
  import { execFileSync } from "child_process";
1607
1705
  import semver from "semver";
@@ -1638,7 +1736,7 @@ function defaultUpdateConfig() {
1638
1736
  }
1639
1737
  function readUpdateConfig() {
1640
1738
  try {
1641
- const raw = fs8.readFileSync(UPDATE_CONFIG_PATH, "utf-8");
1739
+ const raw = fs9.readFileSync(UPDATE_CONFIG_PATH, "utf-8");
1642
1740
  const parsed = import_yaml.default.parse(raw);
1643
1741
  const channel = RELEASE_CHANNELS.includes(parsed?.channel) ? parsed.channel : DEFAULT_RELEASE_CHANNEL;
1644
1742
  const check_interval_hours = typeof parsed?.check_interval_hours === "number" && parsed.check_interval_hours > 0 ? parsed.check_interval_hours : UPDATE_CHECK_INTERVAL_HOURS;
@@ -1648,20 +1746,38 @@ function readUpdateConfig() {
1648
1746
  }
1649
1747
  }
1650
1748
  function writeUpdateConfig(config) {
1651
- fs8.mkdirSync(MYCO_GLOBAL_DIR, { recursive: true });
1652
- fs8.writeFileSync(UPDATE_CONFIG_PATH, import_yaml.default.stringify(config), "utf-8");
1749
+ fs9.mkdirSync(MYCO_GLOBAL_DIR, { recursive: true });
1750
+ fs9.writeFileSync(UPDATE_CONFIG_PATH, import_yaml.default.stringify(config), "utf-8");
1653
1751
  }
1654
1752
  function readCachedCheck() {
1655
1753
  try {
1656
- const raw = fs8.readFileSync(UPDATE_CHECK_CACHE_PATH, "utf-8");
1657
- return JSON.parse(raw);
1754
+ const raw = fs9.readFileSync(UPDATE_CHECK_CACHE_PATH, "utf-8");
1755
+ const parsed = JSON.parse(raw);
1756
+ if (parsed && typeof parsed === "object" && "packages" in parsed && parsed.packages) {
1757
+ return parsed;
1758
+ }
1759
+ const legacy = parsed;
1760
+ if (typeof legacy.checked_at === "string" && typeof legacy.latest_stable === "string") {
1761
+ return {
1762
+ checked_at: legacy.checked_at,
1763
+ channel: RELEASE_CHANNELS.includes(legacy.channel) ? legacy.channel : DEFAULT_RELEASE_CHANNEL,
1764
+ packages: {
1765
+ myco: {
1766
+ package_name: NPM_PACKAGE_NAME,
1767
+ latest_stable: legacy.latest_stable,
1768
+ latest_beta: legacy.latest_beta ?? null
1769
+ }
1770
+ }
1771
+ };
1772
+ }
1773
+ return null;
1658
1774
  } catch {
1659
1775
  return null;
1660
1776
  }
1661
1777
  }
1662
1778
  function clearCachedCheck() {
1663
1779
  try {
1664
- fs8.unlinkSync(UPDATE_CHECK_CACHE_PATH);
1780
+ fs9.unlinkSync(UPDATE_CHECK_CACHE_PATH);
1665
1781
  } catch {
1666
1782
  }
1667
1783
  }
@@ -1672,6 +1788,9 @@ function isCacheStale(cache, intervalHours) {
1672
1788
  const ageMs = Date.now() - checkedAt;
1673
1789
  return ageMs > intervalHours * MS_PER_HOUR;
1674
1790
  }
1791
+ function packageRegistryUrl(packageName) {
1792
+ return `${NPM_REGISTRY_BASE_URL}/${encodeURIComponent(packageName)}`;
1793
+ }
1675
1794
  function resolveTargetVersion(distTags, channel) {
1676
1795
  const stable = distTags.latest;
1677
1796
  const beta = distTags.beta ?? null;
@@ -1681,62 +1800,133 @@ function resolveTargetVersion(distTags, channel) {
1681
1800
  const higher = semver.gt(beta, stable) ? beta : stable;
1682
1801
  return higher;
1683
1802
  }
1684
- function buildCheckResult(currentVersion, cache, config, error) {
1685
- const targetVersion = resolveTargetVersion(
1686
- { latest: cache.latest_stable, beta: cache.latest_beta ?? void 0 },
1687
- cache.channel
1803
+ function resolveTargetVersionFromCache(pkg, channel) {
1804
+ return resolveTargetVersion(
1805
+ { latest: pkg.latest_stable, beta: pkg.latest_beta ?? void 0 },
1806
+ channel
1688
1807
  );
1689
- const update_available = semver.valid(currentVersion) !== null && semver.valid(targetVersion) !== null && semver.gt(targetVersion, currentVersion);
1808
+ }
1809
+ function buildInstalledPackageVersions(globalPrefix, currentVersion) {
1810
+ const installed = {
1811
+ myco: currentVersion,
1812
+ "myco-team": null,
1813
+ "myco-collective": null
1814
+ };
1815
+ if (globalPrefix === null) return installed;
1816
+ for (const pkg of UPDATE_PACKAGES) {
1817
+ const version = getInstalledVersion(globalPrefix, pkg.packageName);
1818
+ if (pkg.id === "myco") {
1819
+ installed.myco = version ?? currentVersion;
1820
+ continue;
1821
+ }
1822
+ installed[pkg.id] = version;
1823
+ }
1824
+ return installed;
1825
+ }
1826
+ function buildPackageResults(currentVersion, cache, channel, globalPrefix) {
1827
+ const installedVersions = buildInstalledPackageVersions(globalPrefix, currentVersion);
1828
+ return UPDATE_PACKAGES.map((pkg) => {
1829
+ const cached = cache.packages[pkg.id];
1830
+ const installedVersion = installedVersions[pkg.id];
1831
+ const latestVersion = cached ? resolveTargetVersionFromCache(cached, channel) : null;
1832
+ const updateAvailable = installedVersion !== null && latestVersion !== null && semver.valid(installedVersion) !== null && semver.valid(latestVersion) !== null && semver.gt(latestVersion, installedVersion);
1833
+ return {
1834
+ id: pkg.id,
1835
+ display_name: pkg.displayName,
1836
+ package_name: pkg.packageName,
1837
+ installed: installedVersion !== null,
1838
+ installed_version: installedVersion,
1839
+ latest_version: latestVersion,
1840
+ latest_stable: cached?.latest_stable ?? null,
1841
+ latest_beta: cached?.latest_beta ?? null,
1842
+ update_available: updateAvailable
1843
+ };
1844
+ });
1845
+ }
1846
+ function buildCheckResult(currentVersion, cache, config, error, globalPrefix) {
1847
+ const packages = buildPackageResults(currentVersion, cache, cache.channel, globalPrefix);
1848
+ const primaryPackage = packages.find((pkg) => pkg.id === "myco");
1849
+ const targetVersion = primaryPackage?.latest_version ?? currentVersion;
1850
+ const latestStable = primaryPackage?.latest_stable ?? currentVersion;
1851
+ const latestBeta = primaryPackage?.latest_beta ?? null;
1852
+ const updateAvailable = packages.some((pkg) => pkg.installed && pkg.update_available);
1690
1853
  return {
1691
- update_available,
1854
+ update_available: updateAvailable,
1692
1855
  running_version: currentVersion,
1693
1856
  latest_version: targetVersion,
1694
- latest_stable: cache.latest_stable,
1695
- latest_beta: cache.latest_beta,
1857
+ latest_stable: latestStable,
1858
+ latest_beta: latestBeta,
1696
1859
  channel: cache.channel,
1697
1860
  check_interval_hours: config.check_interval_hours,
1698
1861
  last_check: cache.checked_at,
1699
- error
1862
+ error,
1863
+ packages
1700
1864
  };
1701
1865
  }
1702
1866
  function resolveGlobalPrefix() {
1703
1867
  return execFileSync("npm", ["prefix", "-g"], { encoding: "utf-8", timeout: 5e3 }).trim();
1704
1868
  }
1705
- function getInstalledVersion(globalPrefix) {
1869
+ function getInstalledVersion(globalPrefix, packageName = NPM_PACKAGE_NAME) {
1706
1870
  try {
1707
1871
  const pkgPath = path9.join(
1708
1872
  globalPrefix,
1709
1873
  "lib",
1710
1874
  "node_modules",
1711
- NPM_PACKAGE_NAME,
1875
+ packageName,
1712
1876
  "package.json"
1713
1877
  );
1714
- const raw = fs8.readFileSync(pkgPath, "utf-8");
1878
+ const raw = fs9.readFileSync(pkgPath, "utf-8");
1715
1879
  const pkg = JSON.parse(raw);
1716
1880
  return pkg.version ?? null;
1717
1881
  } catch {
1718
1882
  return null;
1719
1883
  }
1720
1884
  }
1721
- async function checkForUpdate(currentVersion) {
1885
+ async function checkForUpdate(currentVersion, globalPrefix = null) {
1722
1886
  const config = readUpdateConfig();
1723
1887
  const existingCache = readCachedCheck();
1724
- let distTags;
1725
- let fetchError = null;
1726
- try {
1727
- const response = await fetch(NPM_REGISTRY_URL, {
1728
- signal: AbortSignal.timeout(REGISTRY_FETCH_TIMEOUT_MS)
1729
- });
1730
- if (!response.ok) {
1731
- throw new Error(`Registry responded with ${response.status}`);
1888
+ const freshPackages = {};
1889
+ const fetchErrors = [];
1890
+ const registryChecks = await Promise.allSettled(
1891
+ UPDATE_PACKAGES.map(async (pkg) => {
1892
+ const response = await fetch(packageRegistryUrl(pkg.packageName), {
1893
+ signal: AbortSignal.timeout(REGISTRY_FETCH_TIMEOUT_MS)
1894
+ });
1895
+ if (!response.ok) {
1896
+ throw new Error(`${pkg.packageName}: registry responded with ${response.status}`);
1897
+ }
1898
+ const data = await response.json();
1899
+ return {
1900
+ id: pkg.id,
1901
+ package_name: pkg.packageName,
1902
+ latest_stable: data["dist-tags"].latest,
1903
+ latest_beta: data["dist-tags"].beta ?? null
1904
+ };
1905
+ })
1906
+ );
1907
+ for (const result of registryChecks) {
1908
+ if (result.status === "fulfilled") {
1909
+ freshPackages[result.value.id] = {
1910
+ package_name: result.value.package_name,
1911
+ latest_stable: result.value.latest_stable,
1912
+ latest_beta: result.value.latest_beta
1913
+ };
1914
+ continue;
1732
1915
  }
1733
- const data = await response.json();
1734
- distTags = data["dist-tags"];
1735
- } catch (err) {
1736
- fetchError = err instanceof Error ? err.message : String(err);
1737
- if (existingCache !== null) {
1738
- return buildCheckResult(currentVersion, existingCache, config, fetchError);
1916
+ const message = result.reason instanceof Error ? result.reason.message : String(result.reason);
1917
+ fetchErrors.push(message);
1918
+ }
1919
+ if (existingCache !== null) {
1920
+ for (const pkg of UPDATE_PACKAGES) {
1921
+ if (freshPackages[pkg.id] !== void 0) continue;
1922
+ const cached = existingCache.packages[pkg.id];
1923
+ if (cached) {
1924
+ freshPackages[pkg.id] = cached;
1925
+ }
1739
1926
  }
1927
+ }
1928
+ if (Object.keys(freshPackages).length === 0) {
1929
+ const fetchError = fetchErrors[0] ?? "registry fetch failed";
1740
1930
  return {
1741
1931
  update_available: false,
1742
1932
  running_version: currentVersion,
@@ -1746,47 +1936,49 @@ async function checkForUpdate(currentVersion) {
1746
1936
  channel: config.channel,
1747
1937
  check_interval_hours: config.check_interval_hours,
1748
1938
  last_check: (/* @__PURE__ */ new Date()).toISOString(),
1749
- error: fetchError
1939
+ error: fetchError,
1940
+ packages: buildPackageResults(
1941
+ currentVersion,
1942
+ { checked_at: (/* @__PURE__ */ new Date()).toISOString(), channel: config.channel, packages: {} },
1943
+ config.channel,
1944
+ globalPrefix
1945
+ )
1750
1946
  };
1751
1947
  }
1752
- const latestStable = distTags.latest;
1753
- const latestBeta = distTags.beta ?? null;
1754
- const targetVersion = resolveTargetVersion(distTags, config.channel);
1755
1948
  const freshCache = {
1756
1949
  checked_at: (/* @__PURE__ */ new Date()).toISOString(),
1757
- current_version: currentVersion,
1758
- latest_stable: latestStable,
1759
- latest_beta: latestBeta,
1760
- channel: config.channel
1950
+ channel: config.channel,
1951
+ packages: freshPackages
1761
1952
  };
1762
1953
  try {
1763
- fs8.mkdirSync(path9.dirname(UPDATE_CHECK_CACHE_PATH), { recursive: true });
1764
- fs8.writeFileSync(UPDATE_CHECK_CACHE_PATH, JSON.stringify(freshCache, null, 2), "utf-8");
1954
+ fs9.mkdirSync(path9.dirname(UPDATE_CHECK_CACHE_PATH), { recursive: true });
1955
+ fs9.writeFileSync(UPDATE_CHECK_CACHE_PATH, JSON.stringify(freshCache, null, 2), "utf-8");
1765
1956
  } catch {
1766
1957
  }
1767
- return buildCheckResult(currentVersion, freshCache, config, null);
1958
+ const error = fetchErrors.length > 0 ? fetchErrors.join("; ") : null;
1959
+ return buildCheckResult(currentVersion, freshCache, config, error, globalPrefix);
1768
1960
  }
1769
- function statusFromCache(currentVersion, cache, config) {
1961
+ function statusFromCache(currentVersion, cache, config, globalPrefix = null) {
1770
1962
  const resolvedCache = cache !== void 0 ? cache : readCachedCheck();
1771
1963
  if (resolvedCache === null) return null;
1772
1964
  const resolvedConfig = config !== void 0 ? config : readUpdateConfig();
1773
- return buildCheckResult(currentVersion, resolvedCache, resolvedConfig, null);
1965
+ return buildCheckResult(currentVersion, resolvedCache, resolvedConfig, null, globalPrefix);
1774
1966
  }
1775
1967
 
1776
1968
  // src/daemon/update-installer.ts
1777
- import fs9 from "fs";
1969
+ import fs10 from "fs";
1778
1970
  import os6 from "os";
1779
1971
  import path10 from "path";
1780
1972
  import { spawn as spawn2 } from "child_process";
1781
1973
  function generateUpdateScript(params) {
1782
- const { targetVersion, projectRoot, vaultDir, mycoBinary } = params;
1783
- const packageSpec = `${NPM_PACKAGE_NAME}@${targetVersion}`;
1974
+ const { packageSpecs, projectRoot, vaultDir, mycoBinary } = params;
1975
+ const installArgs = packageSpecs.map((spec) => JSON.stringify(spec)).join(" ");
1784
1976
  const quotedProjectRoot = JSON.stringify(projectRoot);
1785
1977
  const quotedVaultDir = JSON.stringify(vaultDir);
1786
1978
  const quotedMycoBinary = JSON.stringify(mycoBinary);
1787
1979
  const quotedErrorPath = JSON.stringify(UPDATE_ERROR_PATH);
1788
1980
  const errorJson = JSON.stringify(
1789
- JSON.stringify({ error: `npm install failed for ${packageSpec}` })
1981
+ JSON.stringify({ error: `npm install failed for ${packageSpecs.join(", ")}` })
1790
1982
  );
1791
1983
  return `#!/bin/sh
1792
1984
  set -e
@@ -1796,7 +1988,7 @@ MYCO=${quotedMycoBinary}
1796
1988
  sleep ${UPDATE_SCRIPT_DELAY_SECONDS}
1797
1989
 
1798
1990
  # Attempt the update
1799
- if npm install -g ${packageSpec} 2>&1; then
1991
+ if npm install -g ${installArgs} 2>&1; then
1800
1992
  # Sync project files (gitignore, symbiont registration)
1801
1993
  "$MYCO" update --project ${quotedProjectRoot} || true
1802
1994
  # Clear any previous error
@@ -1815,7 +2007,7 @@ rm -f "$0"
1815
2007
  }
1816
2008
  function spawnDetachedScript(namePrefix, content) {
1817
2009
  const scriptPath = path10.join(os6.tmpdir(), `${namePrefix}-${Date.now()}.sh`);
1818
- fs9.writeFileSync(scriptPath, content, { encoding: "utf-8", mode: 493 });
2010
+ fs10.writeFileSync(scriptPath, content, { encoding: "utf-8", mode: 493 });
1819
2011
  const child = spawn2("/bin/sh", [scriptPath], {
1820
2012
  detached: true,
1821
2013
  stdio: "ignore"
@@ -1824,7 +2016,7 @@ function spawnDetachedScript(namePrefix, content) {
1824
2016
  return scriptPath;
1825
2017
  }
1826
2018
  function spawnUpdateScript(params) {
1827
- fs9.mkdirSync(MYCO_GLOBAL_DIR, { recursive: true });
2019
+ fs10.mkdirSync(MYCO_GLOBAL_DIR, { recursive: true });
1828
2020
  return spawnDetachedScript("myco-update", generateUpdateScript(params));
1829
2021
  }
1830
2022
  function generateRestartScript(params) {
@@ -1866,7 +2058,7 @@ function spawnRestartScript(params) {
1866
2058
 
1867
2059
  // src/daemon/api/update.ts
1868
2060
  import semver2 from "semver";
1869
- import fs10 from "fs";
2061
+ import fs11 from "fs";
1870
2062
  import path11 from "path";
1871
2063
  var ChannelBodySchema = external_exports.object({
1872
2064
  channel: external_exports.enum(RELEASE_CHANNELS)
@@ -1877,7 +2069,7 @@ function createUpdateHandlers(deps) {
1877
2069
  function isStampCurrent() {
1878
2070
  try {
1879
2071
  const stampPath = path11.join(vaultDir, UPDATE_STAMP_FILENAME);
1880
- const stamp = fs10.readFileSync(stampPath, "utf-8").trim();
2072
+ const stamp = fs11.readFileSync(stampPath, "utf-8").trim();
1881
2073
  return stamp === currentVersion;
1882
2074
  } catch {
1883
2075
  return false;
@@ -1914,10 +2106,10 @@ function createUpdateHandlers(deps) {
1914
2106
  const config = readUpdateConfig();
1915
2107
  const cache = readCachedCheck();
1916
2108
  if (isCacheStale(cache, config.check_interval_hours)) {
1917
- checkForUpdate(currentVersion).catch(() => {
2109
+ checkForUpdate(currentVersion, globalPrefix).catch(() => {
1918
2110
  });
1919
2111
  }
1920
- const status = statusFromCache(currentVersion, cache, config);
2112
+ const status = statusFromCache(currentVersion, cache, config, globalPrefix);
1921
2113
  if (!status) {
1922
2114
  return {
1923
2115
  body: {
@@ -1943,25 +2135,32 @@ function createUpdateHandlers(deps) {
1943
2135
  body: { error: "update_exempt", message: "Updates disabled in dev mode" }
1944
2136
  };
1945
2137
  }
1946
- const result = await checkForUpdate(currentVersion);
2138
+ const result = await checkForUpdate(currentVersion, globalPrefix);
1947
2139
  return { body: { exempt: false, ...result } };
1948
2140
  }
1949
2141
  async function handleUpdateApply(_req) {
1950
2142
  if (isUpdateExempt()) {
1951
2143
  return { status: 400, body: { error: "update_exempt" } };
1952
2144
  }
1953
- const status = statusFromCache(currentVersion);
1954
- if (!status || !status.update_available) {
2145
+ const status = statusFromCache(currentVersion, void 0, void 0, globalPrefix);
2146
+ const packageSpecs = (status?.packages ?? []).filter((pkg) => pkg.installed && pkg.update_available && pkg.latest_version).map((pkg) => `${pkg.package_name}@${pkg.latest_version}`);
2147
+ if (!status || packageSpecs.length === 0) {
1955
2148
  return { status: 400, body: { error: "no_update_available" } };
1956
2149
  }
1957
2150
  spawnUpdateScript({
1958
- targetVersion: status.latest_version,
2151
+ packageSpecs,
1959
2152
  projectRoot,
1960
2153
  vaultDir,
1961
2154
  mycoBinary: resolveMycoBinary()
1962
2155
  });
1963
2156
  scheduleShutdown();
1964
- return { body: { status: "applying", version: status.latest_version } };
2157
+ return {
2158
+ body: {
2159
+ status: "applying",
2160
+ version: status.latest_version,
2161
+ packages: packageSpecs
2162
+ }
2163
+ };
1965
2164
  }
1966
2165
  async function handleUpdateChannel(req) {
1967
2166
  const parsed = ChannelBodySchema.safeParse(req.body);
@@ -1972,7 +2171,7 @@ function createUpdateHandlers(deps) {
1972
2171
  const config = readUpdateConfig();
1973
2172
  writeUpdateConfig({ ...config, channel });
1974
2173
  clearCachedCheck();
1975
- const channelStatus = statusFromCache(currentVersion);
2174
+ const channelStatus = statusFromCache(currentVersion, void 0, void 0, globalPrefix);
1976
2175
  if (!channelStatus) {
1977
2176
  return {
1978
2177
  body: {
@@ -2000,7 +2199,7 @@ function createUpdateHandlers(deps) {
2000
2199
  }
2001
2200
 
2002
2201
  // src/daemon/backup.ts
2003
- import fs11 from "fs";
2202
+ import fs12 from "fs";
2004
2203
  import path12 from "path";
2005
2204
  var BACKUP_TABLES = [
2006
2205
  "sessions",
@@ -2028,7 +2227,7 @@ function toSqlLiteral(value) {
2028
2227
  return `'${escapeSql(String(value))}'`;
2029
2228
  }
2030
2229
  function createBackup(db, backupDir, machineId) {
2031
- fs11.mkdirSync(backupDir, { recursive: true });
2230
+ fs12.mkdirSync(backupDir, { recursive: true });
2032
2231
  const lines = [];
2033
2232
  const timestamp = epochSeconds();
2034
2233
  lines.push(`${BACKUP_HEADER_TEMPLATE}: machine_id=${machineId}, created_at=${timestamp}`);
@@ -2047,13 +2246,13 @@ function createBackup(db, backupDir, machineId) {
2047
2246
  lines.push("");
2048
2247
  }
2049
2248
  const filePath = path12.join(backupDir, `${machineId}${BACKUP_EXTENSION}`);
2050
- fs11.writeFileSync(filePath, lines.join("\n"), "utf-8");
2249
+ fs12.writeFileSync(filePath, lines.join("\n"), "utf-8");
2051
2250
  return filePath;
2052
2251
  }
2053
2252
  function listBackups(backupDir) {
2054
2253
  let entries;
2055
2254
  try {
2056
- entries = fs11.readdirSync(backupDir);
2255
+ entries = fs12.readdirSync(backupDir);
2057
2256
  } catch {
2058
2257
  return [];
2059
2258
  }
@@ -2061,7 +2260,7 @@ function listBackups(backupDir) {
2061
2260
  for (const entry of entries) {
2062
2261
  if (!BACKUP_FILENAME_PATTERN.test(entry)) continue;
2063
2262
  const filePath = path12.join(backupDir, entry);
2064
- const stat = fs11.statSync(filePath);
2263
+ const stat = fs12.statSync(filePath);
2065
2264
  backups.push({
2066
2265
  machine_id: entry.slice(0, -BACKUP_EXTENSION.length),
2067
2266
  file_name: entry,
@@ -2073,7 +2272,7 @@ function listBackups(backupDir) {
2073
2272
  }
2074
2273
  var INSERT_REGEX = /^INSERT OR IGNORE INTO (\w+)\s+\(([^)]+)\)\s+VALUES\s+\((.+)\);$/;
2075
2274
  function parseBackupFile(backupPath) {
2076
- const content = fs11.readFileSync(backupPath, "utf-8");
2275
+ const content = fs12.readFileSync(backupPath, "utf-8");
2077
2276
  const inserts = [];
2078
2277
  for (const line of content.split("\n")) {
2079
2278
  const match = INSERT_REGEX.exec(line);
@@ -2349,6 +2548,18 @@ var TeamSyncClient = class _TeamSyncClient {
2349
2548
  const res = await this.request("GET", "/config");
2350
2549
  return res;
2351
2550
  }
2551
+ async getCollectiveStatus() {
2552
+ const res = await this.request("GET", "/collective/status");
2553
+ return res;
2554
+ }
2555
+ async getCollectiveSettings() {
2556
+ const res = await this.request("GET", "/collective/settings");
2557
+ return res;
2558
+ }
2559
+ async collectiveQuery(tool, args = {}) {
2560
+ const res = await this.request("POST", "/collective/query", { tool, args });
2561
+ return res;
2562
+ }
2352
2563
  // ---------------------------------------------------------------------------
2353
2564
  // MCP token accessors
2354
2565
  // ---------------------------------------------------------------------------
@@ -2389,6 +2600,12 @@ var TeamSyncClient = class _TeamSyncClient {
2389
2600
  };
2390
2601
 
2391
2602
  // src/daemon/api/team-connect.ts
2603
+ var TEAM_CONFIG_DIR = ".myco-team";
2604
+ var TEAM_CONFIG_FILE = "config.json";
2605
+ function readInstalledTeamPackageVersion() {
2606
+ const config = readJsonConfig(resolveHomeConfigPath(TEAM_CONFIG_DIR, TEAM_CONFIG_FILE));
2607
+ return config?.package_version?.trim() || null;
2608
+ }
2392
2609
  function createTeamHandlers(deps) {
2393
2610
  const { vaultDir, machineId, logger } = deps;
2394
2611
  async function handleConnect(req) {
@@ -2443,6 +2660,7 @@ function createTeamHandlers(deps) {
2443
2660
  const client = deps.getTeamClient();
2444
2661
  const secrets = readSecrets(vaultDir);
2445
2662
  const hasApiKey = Boolean(secrets[TEAM_API_KEY_SECRET]);
2663
+ const installedTeamPackageVersion = readInstalledTeamPackageVersion();
2446
2664
  let healthy = false;
2447
2665
  let healthError;
2448
2666
  if (client && config.team.enabled) {
@@ -2460,6 +2678,14 @@ function createTeamHandlers(deps) {
2460
2678
  deadLetterCount = countDeadLettered();
2461
2679
  } catch {
2462
2680
  }
2681
+ let collectiveStatus = null;
2682
+ if (client && config.team.enabled) {
2683
+ try {
2684
+ collectiveStatus = await client.getCollectiveStatus();
2685
+ } catch {
2686
+ collectiveStatus = null;
2687
+ }
2688
+ }
2463
2689
  return {
2464
2690
  body: {
2465
2691
  enabled: config.team.enabled,
@@ -2472,8 +2698,16 @@ function createTeamHandlers(deps) {
2472
2698
  dead_letter_count: deadLetterCount,
2473
2699
  machine_id: machineId,
2474
2700
  package_version: getPluginVersion(),
2701
+ installed_team_package_version: installedTeamPackageVersion,
2475
2702
  deployed_worker_version: config.team.deployed_worker_version ?? null,
2476
- worker_update_available: config.team.enabled ? config.team.deployed_worker_version !== getPluginVersion() : false,
2703
+ worker_update_available: config.team.enabled && Boolean(installedTeamPackageVersion) && config.team.deployed_worker_version !== installedTeamPackageVersion,
2704
+ collective_connected: collectiveStatus?.connected ?? false,
2705
+ collective_url: collectiveStatus?.collective_url ?? null,
2706
+ collective_project_id: collectiveStatus?.project_id ?? null,
2707
+ collective_last_settings_sync: collectiveStatus?.last_settings_sync ?? null,
2708
+ collective_last_heartbeat: collectiveStatus?.last_heartbeat ?? null,
2709
+ collective_capabilities: collectiveStatus?.capabilities ?? [],
2710
+ collective_settings: collectiveStatus?.settings ?? {},
2477
2711
  schema_version: SCHEMA_VERSION,
2478
2712
  sync_protocol_version: SYNC_PROTOCOL_VERSION,
2479
2713
  mcp_token: client?.getMcpToken() ?? null,
@@ -2490,7 +2724,7 @@ function createTeamHandlers(deps) {
2490
2724
  return { body: { retried: count } };
2491
2725
  }
2492
2726
  async function handleUpgradeWorker(_req) {
2493
- const { upgradeWorker } = await import("./team-2ZFGTSIN.js");
2727
+ const { upgradeWorker } = await import("./team-N6TXS2PF.js");
2494
2728
  logger.info("team-sync.upgrade.start", "Starting worker upgrade");
2495
2729
  const result = upgradeWorker(vaultDir);
2496
2730
  if (!result.success) {
@@ -2539,6 +2773,96 @@ function createTeamHandlers(deps) {
2539
2773
  return { handleConnect, handleDisconnect, handleStatus, handleBackfill, handleRetryFailed, handleUpgradeWorker, handleRotateMcpToken };
2540
2774
  }
2541
2775
 
2776
+ // src/daemon/api/collective.ts
2777
+ function createCollectiveHandlers(deps) {
2778
+ async function requireTeamClient() {
2779
+ const client = deps.getTeamClient();
2780
+ if (!client) {
2781
+ throw new Error("Team sync is not connected");
2782
+ }
2783
+ return client;
2784
+ }
2785
+ async function handleStatus(_req) {
2786
+ try {
2787
+ const client = await requireTeamClient();
2788
+ return { body: await client.getCollectiveStatus() };
2789
+ } catch (error) {
2790
+ return {
2791
+ status: 400,
2792
+ body: { error: error instanceof Error ? error.message : String(error) }
2793
+ };
2794
+ }
2795
+ }
2796
+ async function handleSearch(req) {
2797
+ try {
2798
+ const client = await requireTeamClient();
2799
+ const query = req.query.q;
2800
+ if (!query) {
2801
+ return { status: 400, body: { error: "Missing q parameter" } };
2802
+ }
2803
+ const project = req.query.project;
2804
+ const limit = req.query.limit ? Number(req.query.limit) : void 0;
2805
+ return {
2806
+ body: await client.collectiveQuery("collective_search", { query, project, limit })
2807
+ };
2808
+ } catch (error) {
2809
+ return {
2810
+ status: 400,
2811
+ body: { error: error instanceof Error ? error.message : String(error) }
2812
+ };
2813
+ }
2814
+ }
2815
+ async function handleProjects(_req) {
2816
+ try {
2817
+ const client = await requireTeamClient();
2818
+ return {
2819
+ body: await client.collectiveQuery("collective_projects", {})
2820
+ };
2821
+ } catch (error) {
2822
+ return {
2823
+ status: 400,
2824
+ body: { error: error instanceof Error ? error.message : String(error) }
2825
+ };
2826
+ }
2827
+ }
2828
+ async function handleProject(req) {
2829
+ try {
2830
+ const client = await requireTeamClient();
2831
+ const project = req.query.project;
2832
+ if (!project) {
2833
+ return { status: 400, body: { error: "Missing project parameter" } };
2834
+ }
2835
+ const includeDigest = req.query.include_digest === "true";
2836
+ return {
2837
+ body: await client.collectiveQuery("collective_project", { project, include_digest: includeDigest })
2838
+ };
2839
+ } catch (error) {
2840
+ return {
2841
+ status: 400,
2842
+ body: { error: error instanceof Error ? error.message : String(error) }
2843
+ };
2844
+ }
2845
+ }
2846
+ async function handleSettings(_req) {
2847
+ try {
2848
+ const client = await requireTeamClient();
2849
+ return { body: await client.getCollectiveSettings() };
2850
+ } catch (error) {
2851
+ return {
2852
+ status: 400,
2853
+ body: { error: error instanceof Error ? error.message : String(error) }
2854
+ };
2855
+ }
2856
+ }
2857
+ return {
2858
+ handleStatus,
2859
+ handleSearch,
2860
+ handleProjects,
2861
+ handleProject,
2862
+ handleSettings
2863
+ };
2864
+ }
2865
+
2542
2866
  // src/daemon/api/session-lifecycle.ts
2543
2867
  var RegisterBody = external_exports.object({
2544
2868
  session_id: external_exports.string(),
@@ -2616,7 +2940,7 @@ function createSessionLifecycleHandlers(deps) {
2616
2940
  }
2617
2941
 
2618
2942
  // src/daemon/api/skills.ts
2619
- import fs12 from "fs";
2943
+ import fs13 from "fs";
2620
2944
  import path14 from "path";
2621
2945
 
2622
2946
  // src/db/queries/skill-usage.ts
@@ -2787,7 +3111,7 @@ function createSkillRecordDeleteHandler(deps) {
2787
3111
  const projectRoot = path14.resolve(vaultDir, "..");
2788
3112
  const skillDir = path14.resolve(projectRoot, ".agents", "skills", record.name);
2789
3113
  try {
2790
- fs12.rmSync(skillDir, { recursive: true, force: true });
3114
+ fs13.rmSync(skillDir, { recursive: true, force: true });
2791
3115
  } catch (err) {
2792
3116
  logger.warn(LOG_KINDS.PROCESSOR_BATCH, "Failed to remove skill directory", { name: record.name, error: String(err) });
2793
3117
  }
@@ -3045,12 +3369,12 @@ async function handleGetModels(req) {
3045
3369
 
3046
3370
  // src/daemon/api/stats.ts
3047
3371
  import { createHash as createHash2 } from "crypto";
3048
- import fs13 from "fs";
3372
+ import fs14 from "fs";
3049
3373
  import path15 from "path";
3050
3374
  function computeConfigHash(vaultDir) {
3051
3375
  try {
3052
3376
  const configPath = path15.join(vaultDir, CONFIG_FILENAME);
3053
- const raw = fs13.readFileSync(configPath, "utf-8");
3377
+ const raw = fs14.readFileSync(configPath, "utf-8");
3054
3378
  return createHash2("md5").update(raw).digest("hex");
3055
3379
  } catch {
3056
3380
  return "";
@@ -3730,6 +4054,26 @@ async function handleGetDigest(req) {
3730
4054
  }
3731
4055
 
3732
4056
  // src/daemon/api/search.ts
4057
+ var SEARCH_NAMESPACE_RULES = [
4058
+ { key: "all", value: void 0 },
4059
+ { key: "session", value: "sessions" },
4060
+ { key: "sessions", value: "sessions" },
4061
+ { key: "spore", value: "spores" },
4062
+ { key: "spores", value: "spores" },
4063
+ { key: "plan", value: "plans" },
4064
+ { key: "plans", value: "plans" },
4065
+ { key: "artifact", value: "artifacts" },
4066
+ { key: "artifacts", value: "artifacts" },
4067
+ { key: "skill", value: "skill_records" },
4068
+ { key: "skill_records", value: "skill_records" }
4069
+ ];
4070
+ function normalizeSearchNamespace(value) {
4071
+ if (!value) return void 0;
4072
+ for (const rule of SEARCH_NAMESPACE_RULES) {
4073
+ if (rule.key === value) return rule.value;
4074
+ }
4075
+ return value;
4076
+ }
3733
4077
  function createSearchHandler(deps) {
3734
4078
  return async function handleSearch(req) {
3735
4079
  const query = req.query.q;
@@ -3750,7 +4094,7 @@ function createSearchHandler(deps) {
3750
4094
  }
3751
4095
  return { body: { mode: "semantic", results: [], provider_unavailable: true } };
3752
4096
  }
3753
- const searchNamespace = namespace ?? type;
4097
+ const searchNamespace = normalizeSearchNamespace(namespace ?? type);
3754
4098
  const vectorResults = deps.embeddingManager.searchVectors(queryVector, {
3755
4099
  namespace: searchNamespace,
3756
4100
  limit,
@@ -4403,6 +4747,13 @@ var EmbeddingManager = class {
4403
4747
  searchVectors(query, options) {
4404
4748
  return this.vectorStore.search(query, options);
4405
4749
  }
4750
+ /**
4751
+ * Compute pairwise cosine similarity between all vectors in a namespace.
4752
+ * Used by the evolve instruction builder to find semantically overlapping skills.
4753
+ */
4754
+ pairwiseSimilarity(namespace, threshold) {
4755
+ return this.vectorStore.pairwiseSimilarity(namespace, threshold);
4756
+ }
4406
4757
  // -------------------------------------------------------------------------
4407
4758
  // Private helpers
4408
4759
  // -------------------------------------------------------------------------
@@ -4673,6 +5024,48 @@ var SqliteVecVectorStore = class {
4673
5024
  const rows = this.embeddedIdsStmt.all(namespace);
4674
5025
  return rows.map((r) => r.record_id);
4675
5026
  }
5027
+ /**
5028
+ * Compute pairwise cosine similarity between all vectors in a namespace.
5029
+ * Returns pairs above the threshold, sorted by similarity DESC.
5030
+ *
5031
+ * Uses sqlite-vec's KNN search: for each vector, find the top-K nearest
5032
+ * neighbors within the same namespace. O(n * K) where K is small.
5033
+ */
5034
+ pairwiseSimilarity(namespace, threshold = 0.5) {
5035
+ this.validateNamespace(namespace);
5036
+ const ns = namespace;
5037
+ const allRows = this.db.prepare(
5038
+ `SELECT record_id, embedding FROM vec_${ns}`
5039
+ ).all();
5040
+ if (allRows.length < 2) return [];
5041
+ const pairs = [];
5042
+ const seen = /* @__PURE__ */ new Set();
5043
+ const searchStmt = this.searchStmts.get(ns);
5044
+ for (const row of allRows) {
5045
+ const results = searchStmt.all(
5046
+ row.embedding,
5047
+ // Use the raw embedding as the query vector
5048
+ allRows.length
5049
+ // K = all rows to get exhaustive comparison
5050
+ );
5051
+ for (const match of results) {
5052
+ if (match.record_id === row.record_id) continue;
5053
+ const pairKey = [row.record_id, match.record_id].sort().join("|");
5054
+ if (seen.has(pairKey)) continue;
5055
+ seen.add(pairKey);
5056
+ const similarity = cosineDistanceToSimilarity(match.distance);
5057
+ if (similarity >= threshold) {
5058
+ pairs.push({
5059
+ idA: row.record_id,
5060
+ idB: match.record_id,
5061
+ similarity: Math.round(similarity * 1e3) / 1e3
5062
+ });
5063
+ }
5064
+ }
5065
+ }
5066
+ pairs.sort((a, b) => b.similarity - a.similarity);
5067
+ return pairs;
5068
+ }
4676
5069
  // -------------------------------------------------------------------------
4677
5070
  // Lifecycle
4678
5071
  // -------------------------------------------------------------------------
@@ -4810,6 +5203,12 @@ function planMetadata(row) {
4810
5203
  ...row.source_path != null ? { source_path: row.source_path } : {}
4811
5204
  };
4812
5205
  }
5206
+ function skillRecordMetadata(row) {
5207
+ return {
5208
+ ...row.status != null ? { status: row.status } : {},
5209
+ ...row.name != null ? { name: row.name } : {}
5210
+ };
5211
+ }
4813
5212
  function metadataFor(namespace, row) {
4814
5213
  switch (namespace) {
4815
5214
  case "sessions":
@@ -4820,6 +5219,8 @@ function metadataFor(namespace, row) {
4820
5219
  return planMetadata(row);
4821
5220
  case "artifacts":
4822
5221
  return emptyMetadata();
5222
+ case "skill_records":
5223
+ return skillRecordMetadata(row);
4823
5224
  }
4824
5225
  }
4825
5226
  var SqliteRecordSource = class {
@@ -4834,6 +5235,9 @@ var SqliteRecordSource = class {
4834
5235
  if (namespace === "spores") {
4835
5236
  return this.getUnembeddedActiveSpores(limit);
4836
5237
  }
5238
+ if (namespace === "skill_records") {
5239
+ return this.getUnembeddedActiveSkillRecords(limit);
5240
+ }
4837
5241
  const rows = getUnembedded(namespace, limit);
4838
5242
  const db = getDatabase();
4839
5243
  return rows.map((row) => {
@@ -4880,6 +5284,12 @@ var SqliteRecordSource = class {
4880
5284
  ).all();
4881
5285
  return rows.map((r) => r.id);
4882
5286
  }
5287
+ case "skill_records": {
5288
+ const rows = db.prepare(
5289
+ `SELECT id FROM skill_records WHERE status = ?`
5290
+ ).all(ACTIVE_STATUS2);
5291
+ return rows.map((r) => r.id);
5292
+ }
4883
5293
  }
4884
5294
  }
4885
5295
  /**
@@ -4934,7 +5344,7 @@ var SqliteRecordSource = class {
4934
5344
  assertValidTable(namespace);
4935
5345
  const db = getDatabase();
4936
5346
  const contentFilter = namespace === "sessions" ? " AND summary IS NOT NULL" : "";
4937
- const statusFilter = namespace === "spores" ? ` AND status = '${ACTIVE_STATUS2}'` : "";
5347
+ const statusFilter = namespace === "spores" || namespace === "skill_records" ? ` AND status = '${ACTIVE_STATUS2}'` : "";
4938
5348
  const row = db.prepare(
4939
5349
  `SELECT COUNT(*) AS cnt FROM ${namespace} WHERE embedded = 0${contentFilter}${statusFilter}`
4940
5350
  ).get();
@@ -4959,20 +5369,36 @@ var SqliteRecordSource = class {
4959
5369
  metadata: sporeMetadata(row)
4960
5370
  }));
4961
5371
  }
5372
+ /** Custom query for skill_records: embedded=0 AND status='active'. */
5373
+ getUnembeddedActiveSkillRecords(limit) {
5374
+ const db = getDatabase();
5375
+ const rows = db.prepare(
5376
+ `SELECT id, description AS text, status, name
5377
+ FROM skill_records
5378
+ WHERE embedded = 0 AND status = ?
5379
+ ORDER BY created_at ASC
5380
+ LIMIT ?`
5381
+ ).all(ACTIVE_STATUS2, limit);
5382
+ return rows.map((row) => ({
5383
+ id: String(row.id),
5384
+ text: row.text,
5385
+ metadata: skillRecordMetadata(row)
5386
+ }));
5387
+ }
4962
5388
  };
4963
5389
 
4964
5390
  // src/daemon/database/manager.ts
4965
- import fs15 from "fs";
5391
+ import fs16 from "fs";
4966
5392
 
4967
5393
  // src/db/queries/database.ts
4968
- import fs14 from "fs";
5394
+ import fs15 from "fs";
4969
5395
  function pragmaScalar(name) {
4970
5396
  const db = getDatabase();
4971
5397
  return db.pragma(name, { simple: true });
4972
5398
  }
4973
5399
  function safeFileSize(filePath) {
4974
5400
  try {
4975
- return fs14.statSync(filePath).size;
5401
+ return fs15.statSync(filePath).size;
4976
5402
  } catch (err) {
4977
5403
  if (err.code === "ENOENT") return 0;
4978
5404
  throw err;
@@ -5244,7 +5670,7 @@ var DatabaseMaintenanceManager = class {
5244
5670
  }
5245
5671
  async vacuum() {
5246
5672
  const size_before = this.fileSize();
5247
- const stats = await fs15.promises.statfs(this.vaultDir);
5673
+ const stats = await fs16.promises.statfs(this.vaultDir);
5248
5674
  const free_bytes = Number(stats.bavail) * Number(stats.bsize);
5249
5675
  const required_bytes = size_before * VACUUM_FREE_SPACE_MULTIPLIER;
5250
5676
  if (free_bytes < required_bytes) {
@@ -5292,7 +5718,7 @@ var DatabaseMaintenanceManager = class {
5292
5718
  }
5293
5719
  fileSize() {
5294
5720
  try {
5295
- return fs15.statSync(this.dbPath).size;
5721
+ return fs16.statSync(this.dbPath).size;
5296
5722
  } catch {
5297
5723
  return 0;
5298
5724
  }
@@ -5685,6 +6111,9 @@ function testAnthropic() {
5685
6111
  return { ok: true };
5686
6112
  }
5687
6113
 
6114
+ // src/daemon/task-scheduling.ts
6115
+ import { resolve } from "path";
6116
+
5688
6117
  // src/daemon/task-scheduler.ts
5689
6118
  function resolveSchedule(yamlSchedule, configOverride) {
5690
6119
  if (!configOverride?.schedule) return yamlSchedule;
@@ -5742,8 +6171,12 @@ async function registerScheduledTasks(powerManager, deps) {
5742
6171
  logger.info(LOG_KINDS.AGENT_RUN, "Scheduled agent tasks disabled globally (agent.scheduled_tasks_enabled: false)");
5743
6172
  return;
5744
6173
  }
5745
- const { loadAllTasks: loadAllTasks2 } = await import("./registry-O2NZLO3V.js");
6174
+ const { loadAllTasks: loadAllTasks2 } = await import("./registry-X5FDGYXT.js");
5746
6175
  const allTasks = Array.from(loadAllTasks2(definitionsDir, vaultDir).values());
6176
+ const taskAgentMap = /* @__PURE__ */ new Map();
6177
+ for (const task of allTasks) {
6178
+ taskAgentMap.set(task.name, task.agent);
6179
+ }
5747
6180
  const initialLastRuns = {};
5748
6181
  try {
5749
6182
  const recentRuns = getDatabase().prepare(
@@ -5764,9 +6197,10 @@ async function registerScheduledTasks(powerManager, deps) {
5764
6197
  else runningTasks.delete(name);
5765
6198
  },
5766
6199
  runTask: async (taskName) => {
5767
- const { runAgent } = await import("./executor-NSPRTH4M.js");
6200
+ const { runAgent } = await import("./executor-ICTRRUBY.js");
5768
6201
  const taskConfig = config.agent.tasks?.[taskName];
5769
- const built = buildTaskInstruction(taskName, taskConfig?.params);
6202
+ const projectRoot = resolve(vaultDir, "..");
6203
+ const built = buildTaskInstruction(taskName, taskConfig?.params, taskAgentMap.get(taskName), projectRoot, embeddingManager);
5770
6204
  if (isInstructionRequiredTask(taskName) && !built) {
5771
6205
  logger.info(
5772
6206
  LOG_KINDS.AGENT_RUN,
@@ -5933,7 +6367,7 @@ function createMcpProxyHandlers(deps) {
5933
6367
  name: USER_AGENT_NAME,
5934
6368
  created_at: now
5935
6369
  });
5936
- const { insertResolutionEvent } = await import("./resolution-events-XWYLLDRK.js");
6370
+ const { insertResolutionEvent } = await import("./resolution-events-MVIZMONR.js");
5937
6371
  const resolutionId = `res-${randomBytes(RESOLUTION_ID_RANDOM_BYTES).toString("hex")}`;
5938
6372
  insertResolutionEvent({
5939
6373
  id: resolutionId,
@@ -6015,6 +6449,7 @@ function createMcpProxyHandlers(deps) {
6015
6449
  }
6016
6450
 
6017
6451
  // src/daemon/api/agent-runs.ts
6452
+ import { resolve as resolve2 } from "path";
6018
6453
  var AGENT_RUNS_DEFAULT_LIMIT = 50;
6019
6454
  var AgentRunBody = external_exports.object({
6020
6455
  task: external_exports.string().optional(),
@@ -6041,9 +6476,11 @@ function createAgentRunHandlers(deps) {
6041
6476
  let built;
6042
6477
  try {
6043
6478
  const taskParams = mycoConfig.agent.tasks?.[task]?.params;
6044
- built = buildTaskInstruction(task, taskParams);
6479
+ const projectRoot = resolve2(vaultDir, "..");
6480
+ built = buildTaskInstruction(task, taskParams, agentId, projectRoot, embeddingManager);
6045
6481
  } catch {
6046
- built = buildTaskInstruction(task);
6482
+ const projectRoot = resolve2(vaultDir, "..");
6483
+ built = buildTaskInstruction(task, void 0, agentId, projectRoot, embeddingManager);
6047
6484
  }
6048
6485
  instruction = built?.instruction;
6049
6486
  runContext = built?.context;
@@ -6058,7 +6495,7 @@ function createAgentRunHandlers(deps) {
6058
6495
  };
6059
6496
  }
6060
6497
  }
6061
- const { runAgent } = await import("./executor-NSPRTH4M.js");
6498
+ const { runAgent } = await import("./executor-ICTRRUBY.js");
6062
6499
  const resultPromise = runAgent(vaultDir, {
6063
6500
  task,
6064
6501
  instruction,
@@ -6127,7 +6564,7 @@ function createAgentRunHandlers(deps) {
6127
6564
  }
6128
6565
 
6129
6566
  // src/daemon/api/attachments.ts
6130
- import fs16 from "fs";
6567
+ import fs17 from "fs";
6131
6568
  import path16 from "path";
6132
6569
  var ATTACHMENT_MEDIA_TYPES = {
6133
6570
  png: "image/png",
@@ -6151,7 +6588,7 @@ function createAttachmentHandler(deps) {
6151
6588
  const filePath = path16.join(vaultDir, "attachments", filename);
6152
6589
  let diskData;
6153
6590
  try {
6154
- diskData = fs16.readFileSync(filePath);
6591
+ diskData = fs17.readFileSync(filePath);
6155
6592
  } catch {
6156
6593
  return { status: 404, body: { error: "not_found" } };
6157
6594
  }
@@ -6163,19 +6600,19 @@ function createAttachmentHandler(deps) {
6163
6600
  }
6164
6601
 
6165
6602
  // src/daemon/log-reconcile.ts
6166
- import fs17 from "fs";
6603
+ import fs18 from "fs";
6167
6604
  import path17 from "path";
6168
6605
  function reconcileLogBuffer(logDir, sinceTimestamp) {
6169
6606
  let replayed = 0;
6170
6607
  const files = [];
6171
6608
  for (let i = 3; i >= 1; i--) {
6172
6609
  const rotated = path17.join(logDir, `daemon.${i}.log`);
6173
- if (fs17.existsSync(rotated)) files.push(rotated);
6610
+ if (fs18.existsSync(rotated)) files.push(rotated);
6174
6611
  }
6175
6612
  const current = path17.join(logDir, "daemon.log");
6176
- if (fs17.existsSync(current)) files.push(current);
6613
+ if (fs18.existsSync(current)) files.push(current);
6177
6614
  for (const file of files) {
6178
- const content = fs17.readFileSync(file, "utf-8");
6615
+ const content = fs18.readFileSync(file, "utf-8");
6179
6616
  for (const line of content.split("\n")) {
6180
6617
  if (!line.trim()) continue;
6181
6618
  try {
@@ -6454,7 +6891,7 @@ function registerPowerJobs(powerManager, deps) {
6454
6891
  }
6455
6892
 
6456
6893
  // src/daemon/reconciliation.ts
6457
- import fs18 from "fs";
6894
+ import fs19 from "fs";
6458
6895
  import path18 from "path";
6459
6896
 
6460
6897
  // src/daemon/event-handlers.ts
@@ -6627,7 +7064,7 @@ function createReconciler({ bufferDir, logger }) {
6627
7064
  const bufferPath = path18.join(bufferDir, `${sessionId}.jsonl`);
6628
7065
  let content;
6629
7066
  try {
6630
- content = fs18.readFileSync(bufferPath, "utf-8").trim();
7067
+ content = fs19.readFileSync(bufferPath, "utf-8").trim();
6631
7068
  } catch {
6632
7069
  return;
6633
7070
  }
@@ -6696,7 +7133,7 @@ function createReconciler({ bufferDir, logger }) {
6696
7133
  }
6697
7134
 
6698
7135
  // src/daemon/stop-processing.ts
6699
- import fs19 from "fs";
7136
+ import fs20 from "fs";
6700
7137
 
6701
7138
  // src/daemon/capture-images.ts
6702
7139
  var SESSION_SHORT_LEN = 6;
@@ -6733,6 +7170,78 @@ function captureBatchImages(input) {
6733
7170
  }
6734
7171
  }
6735
7172
 
7173
+ // src/daemon/plan-capture.ts
7174
+ import { createHash as createHash4 } from "crypto";
7175
+ import os7 from "os";
7176
+ import path19 from "path";
7177
+ function extractTaggedPlans(text, tags) {
7178
+ const results = [];
7179
+ for (const tag of tags) {
7180
+ const regex = new RegExp(`<${tag}>\\n?([\\s\\S]*?)\\n?</${tag}>`, "g");
7181
+ let match;
7182
+ while ((match = regex.exec(text)) !== null) {
7183
+ const content = match[1].trim();
7184
+ if (content) results.push({ tag, content });
7185
+ }
7186
+ }
7187
+ return results;
7188
+ }
7189
+ var TRANSCRIPT_SOURCE_PREFIX = "transcript:";
7190
+ var FILE_WRITE_TOOLS = /* @__PURE__ */ new Set([
7191
+ "Write",
7192
+ "Edit",
7193
+ "Create",
7194
+ "write",
7195
+ "edit",
7196
+ "patch",
7197
+ "create"
7198
+ ]);
7199
+ var HEADING_REGEX = /^#\s+(.+)$/m;
7200
+ var PLAN_ID_HASH_LENGTH = 16;
7201
+ function isInPlanDirectory(filePath, watchDirs, projectRoot) {
7202
+ const abs = path19.isAbsolute(filePath) ? filePath : path19.resolve(projectRoot, filePath);
7203
+ return watchDirs.some((dir) => {
7204
+ const expanded = dir.startsWith("~/") ? path19.join(os7.homedir(), dir.slice(2)) : dir;
7205
+ const absDir = path19.isAbsolute(expanded) ? expanded : path19.resolve(projectRoot, expanded);
7206
+ const prefix = absDir.endsWith(path19.sep) ? absDir : absDir + path19.sep;
7207
+ return abs === absDir || abs.startsWith(prefix);
7208
+ });
7209
+ }
7210
+ function isPlanWriteEvent(toolName, toolInput, config) {
7211
+ if (!FILE_WRITE_TOOLS.has(toolName)) return null;
7212
+ const filePath = toolInput?.file_path ?? toolInput?.path ?? toolInput?.filePath;
7213
+ if (typeof filePath !== "string") return null;
7214
+ if (!isInPlanDirectory(filePath, config.watchDirs, config.projectRoot)) return null;
7215
+ if (config.extensions?.length) {
7216
+ const ext = path19.extname(filePath).toLowerCase();
7217
+ if (!config.extensions.includes(ext)) return null;
7218
+ }
7219
+ return filePath;
7220
+ }
7221
+ function parsePlanTitle(content, filename) {
7222
+ const match = HEADING_REGEX.exec(content);
7223
+ if (match) return match[1].trim();
7224
+ return filename ?? null;
7225
+ }
7226
+ function capturePlan(input) {
7227
+ const now = Math.floor(Date.now() / 1e3);
7228
+ const contentHash = createHash4(CONTENT_HASH_ALGORITHM).update(input.content).digest("hex");
7229
+ const id = createHash4("md5").update(input.sourcePath).digest("hex").slice(0, PLAN_ID_HASH_LENGTH);
7230
+ const title = parsePlanTitle(input.content, path19.basename(input.sourcePath));
7231
+ return upsertPlan({
7232
+ id,
7233
+ title,
7234
+ content: input.content,
7235
+ source_path: input.sourcePath,
7236
+ session_id: input.sessionId,
7237
+ prompt_batch_id: input.promptBatchId ?? null,
7238
+ content_hash: contentHash,
7239
+ status: "active",
7240
+ created_at: now,
7241
+ updated_at: now
7242
+ });
7243
+ }
7244
+
6736
7245
  // src/daemon/skill-usage.ts
6737
7246
  import crypto from "crypto";
6738
7247
  var SKILL_USAGE_DETECTION_ENABLED = false;
@@ -6809,7 +7318,7 @@ function createStopProcessor(deps) {
6809
7318
  if (config.agent.summary_batch_interval <= 0) return;
6810
7319
  if (config.agent.event_tasks_enabled === false) return;
6811
7320
  try {
6812
- const { runAgent } = await import("./executor-NSPRTH4M.js");
7321
+ const { runAgent } = await import("./executor-ICTRRUBY.js");
6813
7322
  runAgent(vaultDir, {
6814
7323
  task: "title-summary",
6815
7324
  instruction: `Process session ${sessionId} only`,
@@ -6899,7 +7408,7 @@ function createStopProcessor(deps) {
6899
7408
  let transcriptText = null;
6900
7409
  if (hookTranscriptPath) {
6901
7410
  try {
6902
- transcriptText = fs19.readFileSync(hookTranscriptPath, "utf-8");
7411
+ transcriptText = fs20.readFileSync(hookTranscriptPath, "utf-8");
6903
7412
  } catch {
6904
7413
  }
6905
7414
  }
@@ -6925,6 +7434,33 @@ function createStopProcessor(deps) {
6925
7434
  logger.warn(LOG_KINDS.PROCESSOR_BATCH, "Failed to populate batch responses", { error: String(err) });
6926
7435
  }
6927
7436
  }
7437
+ if (deps.planTags.length > 0) {
7438
+ for (const turn of allTurns) {
7439
+ if (!turn.aiResponse) continue;
7440
+ const taggedPlans = extractTaggedPlans(turn.aiResponse, deps.planTags);
7441
+ for (const { tag, content } of taggedPlans) {
7442
+ try {
7443
+ capturePlan({
7444
+ sourcePath: `${TRANSCRIPT_SOURCE_PREFIX}${tag}`,
7445
+ content,
7446
+ sessionId,
7447
+ promptBatchId: latestBatch?.id ?? null
7448
+ });
7449
+ logger.info(LOG_KINDS.CAPTURE_PLAN, "Plan captured from transcript tag", {
7450
+ session_id: sessionId,
7451
+ tag,
7452
+ content_length: content.length
7453
+ });
7454
+ } catch (err) {
7455
+ logger.warn(LOG_KINDS.CAPTURE_PLAN, "Failed to capture plan from transcript tag", {
7456
+ session_id: sessionId,
7457
+ tag,
7458
+ error: err.message
7459
+ });
7460
+ }
7461
+ }
7462
+ }
7463
+ }
6928
7464
  if (!hasTitle) {
6929
7465
  triggerTitleSummary(sessionId);
6930
7466
  }
@@ -7008,69 +7544,8 @@ function createStopProcessor(deps) {
7008
7544
  }
7009
7545
 
7010
7546
  // src/daemon/event-dispatch.ts
7011
- import fs20 from "fs";
7547
+ import fs21 from "fs";
7012
7548
  import path20 from "path";
7013
-
7014
- // src/daemon/plan-capture.ts
7015
- import { createHash as createHash4 } from "crypto";
7016
- import os7 from "os";
7017
- import path19 from "path";
7018
- var FILE_WRITE_TOOLS = /* @__PURE__ */ new Set([
7019
- "Write",
7020
- "Edit",
7021
- "Create",
7022
- "write",
7023
- "edit",
7024
- "patch",
7025
- "create"
7026
- ]);
7027
- var HEADING_REGEX = /^#\s+(.+)$/m;
7028
- var PLAN_ID_HASH_LENGTH = 16;
7029
- function isInPlanDirectory(filePath, watchDirs, projectRoot) {
7030
- const abs = path19.isAbsolute(filePath) ? filePath : path19.resolve(projectRoot, filePath);
7031
- return watchDirs.some((dir) => {
7032
- const expanded = dir.startsWith("~/") ? path19.join(os7.homedir(), dir.slice(2)) : dir;
7033
- const absDir = path19.isAbsolute(expanded) ? expanded : path19.resolve(projectRoot, expanded);
7034
- const prefix = absDir.endsWith(path19.sep) ? absDir : absDir + path19.sep;
7035
- return abs === absDir || abs.startsWith(prefix);
7036
- });
7037
- }
7038
- function isPlanWriteEvent(toolName, toolInput, config) {
7039
- if (!FILE_WRITE_TOOLS.has(toolName)) return null;
7040
- const filePath = toolInput?.file_path ?? toolInput?.path ?? toolInput?.filePath;
7041
- if (typeof filePath !== "string") return null;
7042
- if (!isInPlanDirectory(filePath, config.watchDirs, config.projectRoot)) return null;
7043
- if (config.extensions?.length) {
7044
- const ext = path19.extname(filePath).toLowerCase();
7045
- if (!config.extensions.includes(ext)) return null;
7046
- }
7047
- return filePath;
7048
- }
7049
- function parsePlanTitle(content, filename) {
7050
- const match = HEADING_REGEX.exec(content);
7051
- if (match) return match[1].trim();
7052
- return filename ?? null;
7053
- }
7054
- function capturePlan(input) {
7055
- const now = Math.floor(Date.now() / 1e3);
7056
- const contentHash = createHash4(CONTENT_HASH_ALGORITHM).update(input.content).digest("hex");
7057
- const id = createHash4("md5").update(input.sourcePath).digest("hex").slice(0, PLAN_ID_HASH_LENGTH);
7058
- const title = parsePlanTitle(input.content, path19.basename(input.sourcePath));
7059
- return upsertPlan({
7060
- id,
7061
- title,
7062
- content: input.content,
7063
- source_path: input.sourcePath,
7064
- session_id: input.sessionId,
7065
- prompt_batch_id: input.promptBatchId ?? null,
7066
- content_hash: contentHash,
7067
- status: "active",
7068
- created_at: now,
7069
- updated_at: now
7070
- });
7071
- }
7072
-
7073
- // src/daemon/event-dispatch.ts
7074
7549
  var EventBody = external_exports.object({ type: external_exports.string(), session_id: external_exports.string() }).passthrough();
7075
7550
  function createEventDispatcher(deps) {
7076
7551
  const {
@@ -7163,7 +7638,7 @@ function createEventDispatcher(deps) {
7163
7638
  );
7164
7639
  if (planFilePath) {
7165
7640
  const captureSessionId = event.session_id;
7166
- fs20.promises.readFile(planFilePath, "utf-8").then((planContent) => {
7641
+ fs21.promises.readFile(planFilePath, "utf-8").then((planContent) => {
7167
7642
  const latestBatch = getLatestBatch(captureSessionId);
7168
7643
  capturePlan({
7169
7644
  sourcePath: path20.relative(projectRoot, planFilePath),
@@ -7308,14 +7783,14 @@ function createEventDispatcher(deps) {
7308
7783
  }
7309
7784
 
7310
7785
  // src/daemon/main.ts
7311
- import fs21 from "fs";
7786
+ import fs22 from "fs";
7312
7787
  import os8 from "os";
7313
7788
  import path21 from "path";
7314
7789
  function killStaleDaemon(vaultDir, logger) {
7315
7790
  const daemonJsonPath = path21.join(vaultDir, "daemon.json");
7316
7791
  try {
7317
- if (!fs21.existsSync(daemonJsonPath)) return;
7318
- const info = JSON.parse(fs21.readFileSync(daemonJsonPath, "utf-8"));
7792
+ if (!fs22.existsSync(daemonJsonPath)) return;
7793
+ const info = JSON.parse(fs22.readFileSync(daemonJsonPath, "utf-8"));
7319
7794
  if (!info.pid) return;
7320
7795
  if (info.pid === process.pid) return;
7321
7796
  try {
@@ -7324,7 +7799,7 @@ function killStaleDaemon(vaultDir, logger) {
7324
7799
  logger.info(LOG_KINDS.DAEMON_START, "Killed stale daemon", { pid: info.pid });
7325
7800
  } catch {
7326
7801
  }
7327
- fs21.unlinkSync(daemonJsonPath);
7802
+ fs22.unlinkSync(daemonJsonPath);
7328
7803
  } catch {
7329
7804
  }
7330
7805
  }
@@ -7339,6 +7814,7 @@ async function main() {
7339
7814
  const config = loadConfig(vaultDir);
7340
7815
  const manifests = loadManifests();
7341
7816
  const symbiontPlanDirs = manifests.flatMap((m) => m.capture?.planDirs ?? []);
7817
+ const symbiontPlanTags = [...new Set(manifests.flatMap((m) => m.capture?.planTags ?? []))];
7342
7818
  const projectRoot = process.cwd();
7343
7819
  let planWatchConfig = {
7344
7820
  watchDirs: [.../* @__PURE__ */ new Set([...symbiontPlanDirs, ...config.capture.plan_dirs ?? []])],
@@ -7357,6 +7833,9 @@ async function main() {
7357
7833
  embedding_provider: config.embedding.provider
7358
7834
  });
7359
7835
  logger.info(LOG_KINDS.CAPTURE_PLAN, "Plan watch directories", { dirs: planWatchConfig.watchDirs });
7836
+ if (symbiontPlanTags.length > 0) {
7837
+ logger.info(LOG_KINDS.CAPTURE_PLAN, "Plan transcript tags", { tags: symbiontPlanTags });
7838
+ }
7360
7839
  const machineId = getMachineId(vaultDir);
7361
7840
  logger.info(LOG_KINDS.DAEMON_START, "Machine ID resolved", { machine_id: machineId });
7362
7841
  let globalPrefix = null;
@@ -7371,7 +7850,7 @@ async function main() {
7371
7850
  const devCliEntry = detectDevBuild(
7372
7851
  globalPrefix,
7373
7852
  process.argv[1],
7374
- fs21.realpathSync
7853
+ fs22.realpathSync
7375
7854
  );
7376
7855
  if (devCliEntry) {
7377
7856
  setDevBuildCliEntry(devCliEntry);
@@ -7387,9 +7866,9 @@ async function main() {
7387
7866
  {
7388
7867
  const reasonPath = path21.join(vaultDir, RESTART_REASON_FILENAME);
7389
7868
  try {
7390
- if (fs21.existsSync(reasonPath)) {
7391
- const raw = JSON.parse(fs21.readFileSync(reasonPath, "utf-8"));
7392
- fs21.unlinkSync(reasonPath);
7869
+ if (fs22.existsSync(reasonPath)) {
7870
+ const raw = JSON.parse(fs22.readFileSync(reasonPath, "utf-8"));
7871
+ fs22.unlinkSync(reasonPath);
7393
7872
  if (raw.reason === "version_sync" && raw.to_version) {
7394
7873
  const message = raw.local_update_ran ? "Restarted and updated local project hooks." : "Restarted to pick up the latest version.";
7395
7874
  notify(vaultDir, {
@@ -7447,7 +7926,7 @@ async function main() {
7447
7926
  const databaseManager = new DatabaseMaintenanceManager(vaultDbPath(vaultDir), vaultDir, logger);
7448
7927
  let definitionsDir;
7449
7928
  try {
7450
- const { registerBuiltInAgentsAndTasks, resolveDefinitionsDir: resolveDefinitionsDir2 } = await import("./loader-SKKUMT5C.js");
7929
+ const { registerBuiltInAgentsAndTasks, resolveDefinitionsDir: resolveDefinitionsDir2 } = await import("./loader-VPE4RCIF.js");
7451
7930
  definitionsDir = resolveDefinitionsDir2();
7452
7931
  await registerBuiltInAgentsAndTasks(definitionsDir, vaultDir);
7453
7932
  logger.info(LOG_KINDS.AGENT_TASK, "Built-in agents and tasks registered");
@@ -7476,7 +7955,7 @@ async function main() {
7476
7955
  const root = findPackageRoot(path21.dirname(new URL(import.meta.url).pathname));
7477
7956
  if (root) {
7478
7957
  const candidate = path21.join(root, "dist", "ui");
7479
- if (fs21.existsSync(candidate)) uiDir = candidate;
7958
+ if (fs22.existsSync(candidate)) uiDir = candidate;
7480
7959
  }
7481
7960
  }
7482
7961
  if (uiDir) {
@@ -7520,7 +7999,8 @@ async function main() {
7520
7999
  embeddingManager,
7521
8000
  logger,
7522
8001
  config,
7523
- vaultDir
8002
+ vaultDir,
8003
+ planTags: symbiontPlanTags
7524
8004
  });
7525
8005
  const sessionLifecycle = createSessionLifecycleHandlers({
7526
8006
  registry,
@@ -7684,6 +8164,14 @@ async function main() {
7684
8164
  server.registerRoute("POST", "/api/team/retry-failed", teamHandlers.handleRetryFailed);
7685
8165
  server.registerRoute("POST", "/api/team/upgrade-worker", teamHandlers.handleUpgradeWorker);
7686
8166
  server.registerRoute("POST", "/api/team/rotate-mcp-token", teamHandlers.handleRotateMcpToken);
8167
+ const collectiveHandlers = createCollectiveHandlers({
8168
+ getTeamClient: teamSync.getTeamClient
8169
+ });
8170
+ server.registerRoute("GET", "/api/collective/status", collectiveHandlers.handleStatus);
8171
+ server.registerRoute("GET", "/api/collective/search", collectiveHandlers.handleSearch);
8172
+ server.registerRoute("GET", "/api/collective/projects", collectiveHandlers.handleProjects);
8173
+ server.registerRoute("GET", "/api/collective/project", collectiveHandlers.handleProject);
8174
+ server.registerRoute("GET", "/api/collective/settings", collectiveHandlers.handleSettings);
7687
8175
  server.registerRoute("GET", "/api/search", createSearchHandler({ embeddingManager, getTeamClient: teamSync.getTeamClient, machineId }));
7688
8176
  server.registerRoute("GET", "/api/activity", handleGetFeed);
7689
8177
  server.registerRoute("GET", "/api/embedding/status", async () => handleGetEmbeddingStatus(vaultDir));
@@ -7756,4 +8244,4 @@ export {
7756
8244
  handleUserPrompt,
7757
8245
  main
7758
8246
  };
7759
- //# sourceMappingURL=main-6PY3ITQ5.js.map
8247
+ //# sourceMappingURL=main-EIKBLOUL.js.map