@goondocks/myco 0.9.0 → 0.10.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 (169) hide show
  1. package/.claude-plugin/marketplace.json +1 -4
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +19 -2
  4. package/dist/{agent-run-EFICNTAU.js → agent-run-CGXF5PPC.js} +7 -7
  5. package/dist/{agent-tasks-RXJ7Z5NG.js → agent-tasks-T7NVI3R7.js} +7 -7
  6. package/dist/{chunk-JMJJEQ3P.js → chunk-5LPERML5.js} +3 -3
  7. package/dist/{chunk-RJ6ZQKG5.js → chunk-5QERXFH7.js} +2 -2
  8. package/dist/{chunk-UBZPD4HN.js → chunk-5SDH75YC.js} +2 -2
  9. package/dist/{chunk-5VZ52A4T.js → chunk-76ZO5RGT.js} +16 -2
  10. package/dist/{chunk-5VZ52A4T.js.map → chunk-76ZO5RGT.js.map} +1 -1
  11. package/dist/{chunk-46PWOKSI.js → chunk-AEJS57ZK.js} +2 -2
  12. package/dist/{chunk-DCXRSSBP.js → chunk-C3AEZ3BZ.js} +3 -3
  13. package/dist/{chunk-4LPQ26CK.js → chunk-CUDM5YJY.js} +25 -8
  14. package/dist/chunk-CUDM5YJY.js.map +1 -0
  15. package/dist/{chunk-YDN4OM33.js → chunk-D6DXYAFK.js} +20 -7
  16. package/dist/chunk-D6DXYAFK.js.map +1 -0
  17. package/dist/chunk-ENWBFX7F.js +50 -0
  18. package/dist/chunk-ENWBFX7F.js.map +1 -0
  19. package/dist/{chunk-OXZSXYAT.js → chunk-FFQES5MC.js} +48 -21
  20. package/dist/chunk-FFQES5MC.js.map +1 -0
  21. package/dist/{chunk-U3IBO3O3.js → chunk-FMIWFRAM.js} +3 -3
  22. package/dist/{chunk-KYLDNM7H.js → chunk-FPMEIN2W.js} +2 -2
  23. package/dist/{chunk-PB6TOLRQ.js → chunk-G2LQBFE3.js} +2 -2
  24. package/dist/{chunk-XNOCTDHF.js → chunk-J4RVYUH4.js} +2 -2
  25. package/dist/{chunk-MHSCMET3.js → chunk-MAZOVVDU.js} +33 -3
  26. package/dist/chunk-MAZOVVDU.js.map +1 -0
  27. package/dist/{chunk-JYOOJCPQ.js → chunk-MKKXCCQ5.js} +5 -5
  28. package/dist/{chunk-QIK2XSDQ.js → chunk-MSXYUXZR.js} +4 -4
  29. package/dist/{chunk-FFAYUQ5N.js → chunk-RJMXDUMA.js} +2 -1
  30. package/dist/{chunk-WGTCA2NU.js → chunk-S6I62FAH.js} +10 -2
  31. package/dist/{chunk-WGTCA2NU.js.map → chunk-S6I62FAH.js.map} +1 -1
  32. package/dist/{chunk-3K5WGSJ4.js → chunk-U7UUJ4FD.js} +23 -8
  33. package/dist/chunk-U7UUJ4FD.js.map +1 -0
  34. package/dist/{chunk-PT5IC642.js → chunk-W6HI4CCS.js} +2 -2
  35. package/dist/{chunk-KB4DGYIY.js → chunk-WXSJKESH.js} +12 -7
  36. package/dist/{chunk-KB4DGYIY.js.map → chunk-WXSJKESH.js.map} +1 -1
  37. package/dist/{chunk-KV4OC4H3.js → chunk-WZZH3YXJ.js} +119 -16
  38. package/dist/chunk-WZZH3YXJ.js.map +1 -0
  39. package/dist/chunk-XLY3REL3.js +165 -0
  40. package/dist/chunk-XLY3REL3.js.map +1 -0
  41. package/dist/{chunk-TRUJLI6K.js → chunk-YZMNEIFI.js} +9 -5
  42. package/dist/chunk-YZMNEIFI.js.map +1 -0
  43. package/dist/{chunk-2T7RPVPP.js → chunk-ZESTWGJT.js} +2 -2
  44. package/dist/{chunk-BUSP3OJB.js → chunk-ZMW6KQX2.js} +3 -3
  45. package/dist/{cli-ODLFRIYS.js → cli-6CPFJGRZ.js} +47 -36
  46. package/dist/cli-6CPFJGRZ.js.map +1 -0
  47. package/dist/client-B27SN5QG.js +15 -0
  48. package/dist/{config-UR5BSGVX.js → config-G3CSGI7P.js} +2 -2
  49. package/dist/{detect-providers-Q42OD4OS.js → detect-providers-AZ6DEQU7.js} +5 -5
  50. package/dist/{doctor-JLKTXDEH.js → doctor-RHHWJTMB.js} +10 -10
  51. package/dist/{executor-ONSDHPGX.js → executor-A5C5KDLP.js} +33 -20
  52. package/dist/executor-A5C5KDLP.js.map +1 -0
  53. package/dist/{init-6GWY345B.js → init-ARJROOWV.js} +15 -15
  54. package/dist/{init-wizard-UONLDYLI.js → init-wizard-XNFOZCEB.js} +8 -8
  55. package/dist/llm-XJFHRFHB.js +17 -0
  56. package/dist/{loader-SH67XD54.js → loader-GKXR5ONU.js} +4 -4
  57. package/dist/{loader-XVXKZZDH.js → loader-PZ7ZRSA4.js} +8 -4
  58. package/dist/{logs-QZVYF6FP.js → logs-LXHPDKUA.js} +3 -3
  59. package/dist/machine-id-RCM7TXPJ.js +13 -0
  60. package/dist/{main-BMCL7CPO.js → main-PVX6R3I6.js} +752 -80
  61. package/dist/main-PVX6R3I6.js.map +1 -0
  62. package/dist/{openai-embeddings-C265WRNK.js → openai-embeddings-ST3B6GW7.js} +5 -5
  63. package/dist/{openrouter-U6VFCRX2.js → openrouter-HJHOO3EO.js} +5 -5
  64. package/dist/{post-compact-OWFSOITU.js → post-compact-LR3DSGT3.js} +7 -7
  65. package/dist/{post-tool-use-DOUM7CGQ.js → post-tool-use-SOFVNFU3.js} +6 -6
  66. package/dist/{post-tool-use-failure-SG3C7PE6.js → post-tool-use-failure-2CZZZASB.js} +7 -7
  67. package/dist/{pre-compact-3J33CHXQ.js → pre-compact-3E3D6565.js} +7 -7
  68. package/dist/{provider-check-3WBPZADE.js → provider-check-SOTDYLJE.js} +5 -5
  69. package/dist/{registry-J4XTWARS.js → registry-WVZG6R2R.js} +5 -5
  70. package/dist/{resolution-events-TFEQPVKS.js → resolution-events-UPHJJLDQ.js} +5 -2
  71. package/dist/{restart-2VM33WOB.js → restart-XIUFVS33.js} +8 -8
  72. package/dist/{search-ZGQR5MDE.js → search-VB6Z2ZXV.js} +8 -8
  73. package/dist/{server-6KMBJCHZ.js → server-AKPBRP6Z.js} +5 -5
  74. package/dist/{session-Z2FXDDG6.js → session-UVZS6CY5.js} +9 -8
  75. package/dist/{session-Z2FXDDG6.js.map → session-UVZS6CY5.js.map} +1 -1
  76. package/dist/{session-end-FLVX32LE.js → session-end-YMQ44U6Z.js} +6 -6
  77. package/dist/{session-start-UCLK7PXE.js → session-start-3754HF3N.js} +11 -10
  78. package/dist/{session-start-UCLK7PXE.js.map → session-start-3754HF3N.js.map} +1 -1
  79. package/dist/{setup-llm-GKMCHURK.js → setup-llm-NWHOPJUV.js} +8 -8
  80. package/dist/src/cli.js +1 -1
  81. package/dist/src/daemon/main.js +1 -1
  82. package/dist/src/hooks/post-tool-use.js +1 -1
  83. package/dist/src/hooks/session-end.js +1 -1
  84. package/dist/src/hooks/session-start.js +1 -1
  85. package/dist/src/hooks/stop.js +1 -1
  86. package/dist/src/hooks/user-prompt-submit.js +1 -1
  87. package/dist/src/mcp/server.js +1 -1
  88. package/dist/{stats-IUJPZSVZ.js → stats-CDQXOTEC.js} +9 -9
  89. package/dist/{stop-XRQLLXST.js → stop-WSFGRPXZ.js} +6 -6
  90. package/dist/{stop-failure-2CAJJKRG.js → stop-failure-4FR7574F.js} +7 -7
  91. package/dist/{subagent-start-MWWQTZMQ.js → subagent-start-7SGBXJYP.js} +7 -7
  92. package/dist/{subagent-stop-PJXYGRXB.js → subagent-stop-MRVTNX3V.js} +7 -7
  93. package/dist/{task-completed-4LFRJVGI.js → task-completed-XXPYPSRV.js} +7 -7
  94. package/dist/team-XMHYCKFF.js +251 -0
  95. package/dist/team-XMHYCKFF.js.map +1 -0
  96. package/dist/ui/assets/index-BGbil7f1.css +1 -0
  97. package/dist/ui/assets/index-CPA_uq_j.js +794 -0
  98. package/dist/ui/index.html +2 -2
  99. package/dist/update-W3UFZU4G.js +79 -0
  100. package/dist/update-W3UFZU4G.js.map +1 -0
  101. package/dist/{user-prompt-submit-KSM3AR6P.js → user-prompt-submit-LSWCYUW3.js} +6 -6
  102. package/dist/{verify-UDAYVX37.js → verify-O7TQ5DDY.js} +9 -9
  103. package/dist/{version-KLBN4HZT.js → version-VWWY7SPQ.js} +2 -2
  104. package/dist/version-VWWY7SPQ.js.map +1 -0
  105. package/package.json +1 -1
  106. package/dist/chunk-3K5WGSJ4.js.map +0 -1
  107. package/dist/chunk-4LPQ26CK.js.map +0 -1
  108. package/dist/chunk-KV4OC4H3.js.map +0 -1
  109. package/dist/chunk-MHSCMET3.js.map +0 -1
  110. package/dist/chunk-OXZSXYAT.js.map +0 -1
  111. package/dist/chunk-TRUJLI6K.js.map +0 -1
  112. package/dist/chunk-YDN4OM33.js.map +0 -1
  113. package/dist/cli-ODLFRIYS.js.map +0 -1
  114. package/dist/client-MXRNQ5FI.js +0 -13
  115. package/dist/executor-ONSDHPGX.js.map +0 -1
  116. package/dist/llm-BV3QNVRD.js +0 -17
  117. package/dist/main-BMCL7CPO.js.map +0 -1
  118. package/dist/ui/assets/index-DZrElonz.js +0 -744
  119. package/dist/ui/assets/index-TkeiYbZB.css +0 -1
  120. /package/dist/{agent-run-EFICNTAU.js.map → agent-run-CGXF5PPC.js.map} +0 -0
  121. /package/dist/{agent-tasks-RXJ7Z5NG.js.map → agent-tasks-T7NVI3R7.js.map} +0 -0
  122. /package/dist/{chunk-JMJJEQ3P.js.map → chunk-5LPERML5.js.map} +0 -0
  123. /package/dist/{chunk-RJ6ZQKG5.js.map → chunk-5QERXFH7.js.map} +0 -0
  124. /package/dist/{chunk-UBZPD4HN.js.map → chunk-5SDH75YC.js.map} +0 -0
  125. /package/dist/{chunk-46PWOKSI.js.map → chunk-AEJS57ZK.js.map} +0 -0
  126. /package/dist/{chunk-DCXRSSBP.js.map → chunk-C3AEZ3BZ.js.map} +0 -0
  127. /package/dist/{chunk-U3IBO3O3.js.map → chunk-FMIWFRAM.js.map} +0 -0
  128. /package/dist/{chunk-KYLDNM7H.js.map → chunk-FPMEIN2W.js.map} +0 -0
  129. /package/dist/{chunk-PB6TOLRQ.js.map → chunk-G2LQBFE3.js.map} +0 -0
  130. /package/dist/{chunk-XNOCTDHF.js.map → chunk-J4RVYUH4.js.map} +0 -0
  131. /package/dist/{chunk-JYOOJCPQ.js.map → chunk-MKKXCCQ5.js.map} +0 -0
  132. /package/dist/{chunk-QIK2XSDQ.js.map → chunk-MSXYUXZR.js.map} +0 -0
  133. /package/dist/{chunk-FFAYUQ5N.js.map → chunk-RJMXDUMA.js.map} +0 -0
  134. /package/dist/{chunk-PT5IC642.js.map → chunk-W6HI4CCS.js.map} +0 -0
  135. /package/dist/{chunk-2T7RPVPP.js.map → chunk-ZESTWGJT.js.map} +0 -0
  136. /package/dist/{chunk-BUSP3OJB.js.map → chunk-ZMW6KQX2.js.map} +0 -0
  137. /package/dist/{client-MXRNQ5FI.js.map → client-B27SN5QG.js.map} +0 -0
  138. /package/dist/{config-UR5BSGVX.js.map → config-G3CSGI7P.js.map} +0 -0
  139. /package/dist/{detect-providers-Q42OD4OS.js.map → detect-providers-AZ6DEQU7.js.map} +0 -0
  140. /package/dist/{doctor-JLKTXDEH.js.map → doctor-RHHWJTMB.js.map} +0 -0
  141. /package/dist/{init-6GWY345B.js.map → init-ARJROOWV.js.map} +0 -0
  142. /package/dist/{init-wizard-UONLDYLI.js.map → init-wizard-XNFOZCEB.js.map} +0 -0
  143. /package/dist/{llm-BV3QNVRD.js.map → llm-XJFHRFHB.js.map} +0 -0
  144. /package/dist/{loader-SH67XD54.js.map → loader-GKXR5ONU.js.map} +0 -0
  145. /package/dist/{loader-XVXKZZDH.js.map → loader-PZ7ZRSA4.js.map} +0 -0
  146. /package/dist/{logs-QZVYF6FP.js.map → logs-LXHPDKUA.js.map} +0 -0
  147. /package/dist/{openai-embeddings-C265WRNK.js.map → machine-id-RCM7TXPJ.js.map} +0 -0
  148. /package/dist/{openrouter-U6VFCRX2.js.map → openai-embeddings-ST3B6GW7.js.map} +0 -0
  149. /package/dist/{provider-check-3WBPZADE.js.map → openrouter-HJHOO3EO.js.map} +0 -0
  150. /package/dist/{post-compact-OWFSOITU.js.map → post-compact-LR3DSGT3.js.map} +0 -0
  151. /package/dist/{post-tool-use-DOUM7CGQ.js.map → post-tool-use-SOFVNFU3.js.map} +0 -0
  152. /package/dist/{post-tool-use-failure-SG3C7PE6.js.map → post-tool-use-failure-2CZZZASB.js.map} +0 -0
  153. /package/dist/{pre-compact-3J33CHXQ.js.map → pre-compact-3E3D6565.js.map} +0 -0
  154. /package/dist/{registry-J4XTWARS.js.map → provider-check-SOTDYLJE.js.map} +0 -0
  155. /package/dist/{resolution-events-TFEQPVKS.js.map → registry-WVZG6R2R.js.map} +0 -0
  156. /package/dist/{version-KLBN4HZT.js.map → resolution-events-UPHJJLDQ.js.map} +0 -0
  157. /package/dist/{restart-2VM33WOB.js.map → restart-XIUFVS33.js.map} +0 -0
  158. /package/dist/{search-ZGQR5MDE.js.map → search-VB6Z2ZXV.js.map} +0 -0
  159. /package/dist/{server-6KMBJCHZ.js.map → server-AKPBRP6Z.js.map} +0 -0
  160. /package/dist/{session-end-FLVX32LE.js.map → session-end-YMQ44U6Z.js.map} +0 -0
  161. /package/dist/{setup-llm-GKMCHURK.js.map → setup-llm-NWHOPJUV.js.map} +0 -0
  162. /package/dist/{stats-IUJPZSVZ.js.map → stats-CDQXOTEC.js.map} +0 -0
  163. /package/dist/{stop-XRQLLXST.js.map → stop-WSFGRPXZ.js.map} +0 -0
  164. /package/dist/{stop-failure-2CAJJKRG.js.map → stop-failure-4FR7574F.js.map} +0 -0
  165. /package/dist/{subagent-start-MWWQTZMQ.js.map → subagent-start-7SGBXJYP.js.map} +0 -0
  166. /package/dist/{subagent-stop-PJXYGRXB.js.map → subagent-stop-MRVTNX3V.js.map} +0 -0
  167. /package/dist/{task-completed-4LFRJVGI.js.map → task-completed-XXPYPSRV.js.map} +0 -0
  168. /package/dist/{user-prompt-submit-KSM3AR6P.js.map → user-prompt-submit-LSWCYUW3.js.map} +0 -0
  169. /package/dist/{verify-UDAYVX37.js.map → verify-O7TQ5DDY.js.map} +0 -0
@@ -2,7 +2,7 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  DaemonLogger,
4
4
  LEVEL_ORDER
5
- } from "./chunk-2T7RPVPP.js";
5
+ } from "./chunk-ZESTWGJT.js";
6
6
  import {
7
7
  EMBEDDABLE_TABLES,
8
8
  EMBEDDABLE_TEXT_COLUMNS,
@@ -12,13 +12,16 @@ import {
12
12
  getEmbeddingQueueDepth,
13
13
  getUnembedded,
14
14
  markEmbedded
15
- } from "./chunk-QIK2XSDQ.js";
15
+ } from "./chunk-MSXYUXZR.js";
16
16
  import {
17
17
  withTaskConfig
18
18
  } from "./chunk-M5XWW7UI.js";
19
+ import {
20
+ getMachineId
21
+ } from "./chunk-ENWBFX7F.js";
19
22
  import {
20
23
  createEmbeddingProvider
21
- } from "./chunk-JYOOJCPQ.js";
24
+ } from "./chunk-MKKXCCQ5.js";
22
25
  import {
23
26
  closeOpenBatches,
24
27
  countRuns,
@@ -41,45 +44,47 @@ import {
41
44
  listTurnsByRun,
42
45
  populateBatchResponses,
43
46
  setResponseSummary
44
- } from "./chunk-OXZSXYAT.js";
47
+ } from "./chunk-FFQES5MC.js";
45
48
  import {
46
49
  fullTextSearch,
47
50
  hydrateSearchResults
48
- } from "./chunk-PT5IC642.js";
51
+ } from "./chunk-W6HI4CCS.js";
49
52
  import {
50
53
  copyTaskToUser,
51
54
  deleteUserTask,
52
55
  loadAllTasks,
53
56
  validateTaskName,
54
57
  writeUserTask
55
- } from "./chunk-BUSP3OJB.js";
58
+ } from "./chunk-ZMW6KQX2.js";
56
59
  import {
57
60
  AgentTaskSchema,
58
61
  registerAgent,
59
62
  resolveDefinitionsDir,
60
63
  taskFromParsed
61
- } from "./chunk-JMJJEQ3P.js";
64
+ } from "./chunk-5LPERML5.js";
62
65
  import {
63
66
  checkLocalProvider
64
- } from "./chunk-DCXRSSBP.js";
67
+ } from "./chunk-C3AEZ3BZ.js";
65
68
  import {
66
69
  EventBuffer,
67
70
  cleanStaleBuffers,
68
71
  listBufferSessionIds
69
72
  } from "./chunk-V7XG6V6C.js";
70
73
  import "./chunk-IB76KGBY.js";
71
- import "./chunk-46PWOKSI.js";
72
- import "./chunk-RJ6ZQKG5.js";
73
- import "./chunk-KYLDNM7H.js";
74
+ import "./chunk-AEJS57ZK.js";
75
+ import "./chunk-5QERXFH7.js";
76
+ import "./chunk-FPMEIN2W.js";
74
77
  import {
75
- loadSecrets
76
- } from "./chunk-FFAYUQ5N.js";
78
+ loadSecrets,
79
+ readSecrets,
80
+ writeSecret
81
+ } from "./chunk-RJMXDUMA.js";
77
82
  import {
78
83
  SymbiontRegistry,
79
84
  claudeCodeAdapter,
80
85
  createPerProjectAdapter,
81
86
  extensionForMimeType
82
- } from "./chunk-KB4DGYIY.js";
87
+ } from "./chunk-WXSJKESH.js";
83
88
  import "./chunk-SAKJMNSR.js";
84
89
  import {
85
90
  loadManifests
@@ -87,14 +92,14 @@ import {
87
92
  import {
88
93
  LmStudioBackend,
89
94
  OllamaBackend
90
- } from "./chunk-UBZPD4HN.js";
95
+ } from "./chunk-5SDH75YC.js";
91
96
  import {
92
97
  countSpores,
93
98
  getSpore,
94
99
  insertSpore,
95
100
  listSpores,
96
101
  updateSporeStatus
97
- } from "./chunk-3K5WGSJ4.js";
102
+ } from "./chunk-U7UUJ4FD.js";
98
103
  import {
99
104
  closeSession,
100
105
  countSessions,
@@ -104,17 +109,29 @@ import {
104
109
  listSessions,
105
110
  updateSession,
106
111
  upsertSession
107
- } from "./chunk-4LPQ26CK.js";
112
+ } from "./chunk-CUDM5YJY.js";
113
+ import {
114
+ backfillUnsynced,
115
+ countPending,
116
+ initTeamContext,
117
+ listPending,
118
+ markSent,
119
+ pruneOld,
120
+ syncRow
121
+ } from "./chunk-XLY3REL3.js";
108
122
  import {
109
123
  EMBEDDING_DIMENSIONS,
124
+ SCHEMA_VERSION,
110
125
  createSchema
111
- } from "./chunk-KV4OC4H3.js";
126
+ } from "./chunk-WZZH3YXJ.js";
112
127
  import {
113
128
  CONFIG_FILENAME,
114
129
  MycoConfigSchema,
115
130
  loadConfig,
116
- updateConfig
117
- } from "./chunk-MHSCMET3.js";
131
+ updateBackupConfig,
132
+ updateConfig,
133
+ updateTeamConfig
134
+ } from "./chunk-MAZOVVDU.js";
118
135
  import {
119
136
  require_dist
120
137
  } from "./chunk-D7TYRPRM.js";
@@ -128,13 +145,16 @@ import {
128
145
  initDatabase,
129
146
  vaultDbPath
130
147
  } from "./chunk-MYX5NCRH.js";
131
- import "./chunk-TRUJLI6K.js";
148
+ import {
149
+ resolveCliEntryPath
150
+ } from "./chunk-YZMNEIFI.js";
132
151
  import {
133
152
  CONTENT_HASH_ALGORITHM,
134
153
  DAEMON_EVICT_POLL_MS,
135
154
  DAEMON_EVICT_TIMEOUT_MS,
136
155
  DEAD_SESSION_MAX_PROMPTS,
137
156
  DEFAULT_AGENT_ID,
157
+ DEFAULT_MACHINE_ID,
138
158
  EMBEDDING_BATCH_SIZE,
139
159
  EXCLUDED_SPORE_STATUSES,
140
160
  FEED_DEFAULT_LIMIT,
@@ -157,19 +177,24 @@ import {
157
177
  SEARCH_SIMILARITY_THRESHOLD,
158
178
  STALE_BUFFER_MAX_AGE_MS,
159
179
  STALE_SESSION_THRESHOLD_MS,
180
+ SYNC_PROTOCOL_VERSION,
181
+ TEAM_API_KEY_SECRET,
182
+ TEAM_HEALTH_TIMEOUT_MS,
183
+ TEAM_SEARCH_TIMEOUT_MS,
184
+ TEAM_SOURCE_PREFIX,
160
185
  USER_AGENT_ID,
161
186
  USER_AGENT_NAME,
162
187
  USER_TASK_SOURCE,
163
188
  epochSeconds,
164
189
  estimateTokens
165
- } from "./chunk-5VZ52A4T.js";
190
+ } from "./chunk-76ZO5RGT.js";
166
191
  import {
167
192
  LOG_KINDS,
168
193
  kindToComponent
169
- } from "./chunk-WGTCA2NU.js";
194
+ } from "./chunk-S6I62FAH.js";
170
195
  import {
171
196
  getPluginVersion
172
- } from "./chunk-PB6TOLRQ.js";
197
+ } from "./chunk-G2LQBFE3.js";
173
198
  import {
174
199
  findPackageRoot
175
200
  } from "./chunk-LPUQPDC2.js";
@@ -633,7 +658,9 @@ var PLAN_COLUMNS = [
633
658
  "processed",
634
659
  "embedded",
635
660
  "created_at",
636
- "updated_at"
661
+ "updated_at",
662
+ "machine_id",
663
+ "synced_at"
637
664
  ];
638
665
  var SELECT_COLUMNS = PLAN_COLUMNS.join(", ");
639
666
  function toPlanRow(row) {
@@ -651,7 +678,9 @@ function toPlanRow(row) {
651
678
  processed: row.processed,
652
679
  embedded: row.embedded ?? 0,
653
680
  created_at: row.created_at,
654
- updated_at: row.updated_at ?? null
681
+ updated_at: row.updated_at ?? null,
682
+ machine_id: row.machine_id ?? DEFAULT_MACHINE_ID,
683
+ synced_at: row.synced_at ?? null
655
684
  };
656
685
  }
657
686
  function upsertPlan(data) {
@@ -660,11 +689,11 @@ function upsertPlan(data) {
660
689
  `INSERT INTO plans (
661
690
  id, status, author, title, content,
662
691
  source_path, tags, session_id, prompt_batch_id, content_hash,
663
- processed, created_at, updated_at
692
+ processed, created_at, updated_at, machine_id
664
693
  ) VALUES (
665
694
  ?, ?, ?, ?, ?,
666
695
  ?, ?, ?, ?, ?,
667
- ?, ?, ?
696
+ ?, ?, ?, ?
668
697
  )
669
698
  ON CONFLICT (id) DO UPDATE SET
670
699
  status = EXCLUDED.status,
@@ -695,11 +724,14 @@ function upsertPlan(data) {
695
724
  data.content_hash ?? null,
696
725
  data.processed ?? DEFAULT_PROCESSED,
697
726
  data.created_at,
698
- data.updated_at ?? null
727
+ data.updated_at ?? null,
728
+ data.machine_id ?? DEFAULT_MACHINE_ID
699
729
  );
700
- return toPlanRow(
730
+ const row = toPlanRow(
701
731
  db.prepare(`SELECT ${SELECT_COLUMNS} FROM plans WHERE id = ?`).get(data.id)
702
732
  );
733
+ syncRow("plans", row);
734
+ return row;
703
735
  }
704
736
  function listPlans(options = {}) {
705
737
  const db = getDatabase();
@@ -787,7 +819,9 @@ function mergeConfigSections(current, incoming) {
787
819
  embedding: { ...current.embedding, ...incoming.embedding },
788
820
  capture: { ...current.capture, ...incoming.capture },
789
821
  agent: { ...current.agent, ...incoming.agent },
790
- context: { ...current.context, ...incoming.context }
822
+ context: { ...current.context, ...incoming.context },
823
+ backup: { ...current.backup, ...incoming.backup },
824
+ team: { ...current.team, ...incoming.team }
791
825
  };
792
826
  }
793
827
  async function handleGetConfig(vaultDir) {
@@ -1025,8 +1059,8 @@ async function handleRestart(deps, body) {
1025
1059
  body: { status: "busy", message: "Active operations in progress. Use force=true to override." }
1026
1060
  };
1027
1061
  }
1028
- const mycoCmd = process.env.MYCO_CMD || "myco";
1029
- const shellCmd = `sleep ${RESTART_CHILD_DELAY_SECONDS} && ${mycoCmd} daemon --vault ${deps.vaultDir}`;
1062
+ const { execPath, cliEntry } = resolveCliEntryPath();
1063
+ const shellCmd = `sleep ${RESTART_CHILD_DELAY_SECONDS} && ${execPath} ${cliEntry} daemon --vault ${deps.vaultDir}`;
1030
1064
  const child = spawn("/bin/sh", ["-c", shellCmd], {
1031
1065
  detached: true,
1032
1066
  stdio: "ignore"
@@ -1038,6 +1072,431 @@ async function handleRestart(deps, body) {
1038
1072
  return { body: { status: "restarting" } };
1039
1073
  }
1040
1074
 
1075
+ // src/daemon/backup.ts
1076
+ import fs3 from "fs";
1077
+ import path4 from "path";
1078
+ var BACKUP_TABLES = [
1079
+ "sessions",
1080
+ "prompt_batches",
1081
+ "spores",
1082
+ "entities",
1083
+ "graph_edges",
1084
+ "entity_mentions",
1085
+ "resolution_events",
1086
+ "plans",
1087
+ "artifacts",
1088
+ "digest_extracts",
1089
+ "team_members"
1090
+ ];
1091
+ var BACKUP_EXTENSION = ".sql";
1092
+ var BACKUP_HEADER_TEMPLATE = "-- Myco backup";
1093
+ function escapeSql(value) {
1094
+ return value.replace(/'/g, "''");
1095
+ }
1096
+ function toSqlLiteral(value) {
1097
+ if (value === null || value === void 0) return "NULL";
1098
+ if (typeof value === "number") return String(value);
1099
+ if (Buffer.isBuffer(value)) return `X'${value.toString("hex")}'`;
1100
+ return `'${escapeSql(String(value))}'`;
1101
+ }
1102
+ function createBackup(db, backupDir, machineId) {
1103
+ fs3.mkdirSync(backupDir, { recursive: true });
1104
+ const lines = [];
1105
+ const timestamp = epochSeconds();
1106
+ lines.push(`${BACKUP_HEADER_TEMPLATE}: machine_id=${machineId}, created_at=${timestamp}`);
1107
+ lines.push(`-- Protocol version: ${SYNC_PROTOCOL_VERSION}`);
1108
+ lines.push("");
1109
+ for (const table of BACKUP_TABLES) {
1110
+ const rows = db.prepare(`SELECT * FROM ${table}`).all();
1111
+ if (rows.length === 0) continue;
1112
+ lines.push(`-- Table: ${table} (${rows.length} rows)`);
1113
+ const columns = Object.keys(rows[0]);
1114
+ const columnList = columns.map((c) => `"${c}"`).join(", ");
1115
+ for (const row of rows) {
1116
+ const values = columns.map((c) => toSqlLiteral(row[c])).join(", ");
1117
+ lines.push(`INSERT OR IGNORE INTO ${table} (${columnList}) VALUES (${values});`);
1118
+ }
1119
+ lines.push("");
1120
+ }
1121
+ const filePath = path4.join(backupDir, `${machineId}${BACKUP_EXTENSION}`);
1122
+ fs3.writeFileSync(filePath, lines.join("\n"), "utf-8");
1123
+ return filePath;
1124
+ }
1125
+ function listBackups(backupDir) {
1126
+ let entries;
1127
+ try {
1128
+ entries = fs3.readdirSync(backupDir);
1129
+ } catch {
1130
+ return [];
1131
+ }
1132
+ const backups = [];
1133
+ for (const entry of entries) {
1134
+ if (!entry.endsWith(BACKUP_EXTENSION)) continue;
1135
+ const filePath = path4.join(backupDir, entry);
1136
+ const stat = fs3.statSync(filePath);
1137
+ backups.push({
1138
+ machine_id: entry.slice(0, -BACKUP_EXTENSION.length),
1139
+ file_name: entry,
1140
+ size_bytes: stat.size,
1141
+ modified_at: stat.mtime.toISOString()
1142
+ });
1143
+ }
1144
+ return backups.sort((a, b) => b.modified_at.localeCompare(a.modified_at));
1145
+ }
1146
+ var INSERT_REGEX = /^INSERT OR IGNORE INTO (\w+)\s+\(([^)]+)\)\s+VALUES\s+\((.+)\);$/;
1147
+ function parseBackupFile(backupPath) {
1148
+ const content = fs3.readFileSync(backupPath, "utf-8");
1149
+ const inserts = [];
1150
+ for (const line of content.split("\n")) {
1151
+ const match = INSERT_REGEX.exec(line);
1152
+ if (!match) continue;
1153
+ inserts.push({
1154
+ table: match[1],
1155
+ columns: match[2].split(",").map((c) => c.trim().replace(/"/g, "")),
1156
+ valueSql: match[3]
1157
+ });
1158
+ }
1159
+ return inserts;
1160
+ }
1161
+ function restorePreview(db, backupPath) {
1162
+ const inserts = parseBackupFile(backupPath);
1163
+ const counts = /* @__PURE__ */ new Map();
1164
+ db.pragma("foreign_keys = OFF");
1165
+ db.exec("SAVEPOINT restore_preview");
1166
+ try {
1167
+ for (const insert of inserts) {
1168
+ if (!counts.has(insert.table)) {
1169
+ counts.set(insert.table, { new: 0, existing: 0 });
1170
+ }
1171
+ const tableCounts = counts.get(insert.table);
1172
+ try {
1173
+ const columnList = insert.columns.map((c) => `"${c}"`).join(", ");
1174
+ const stmt = `INSERT OR IGNORE INTO ${insert.table} (${columnList}) VALUES (${insert.valueSql})`;
1175
+ const result = db.prepare(stmt).run();
1176
+ if (result.changes > 0) {
1177
+ tableCounts.new++;
1178
+ } else {
1179
+ tableCounts.existing++;
1180
+ }
1181
+ } catch {
1182
+ tableCounts.existing++;
1183
+ }
1184
+ }
1185
+ } finally {
1186
+ db.exec("ROLLBACK TO restore_preview");
1187
+ db.exec("RELEASE restore_preview");
1188
+ db.pragma("foreign_keys = ON");
1189
+ }
1190
+ return Array.from(counts.entries()).map(([table, c]) => ({
1191
+ table,
1192
+ new: c.new,
1193
+ existing: c.existing
1194
+ }));
1195
+ }
1196
+ function restoreBackup(db, backupPath) {
1197
+ const inserts = parseBackupFile(backupPath);
1198
+ const counts = /* @__PURE__ */ new Map();
1199
+ db.pragma("foreign_keys = OFF");
1200
+ try {
1201
+ const runRestore = db.transaction(() => {
1202
+ for (const insert of inserts) {
1203
+ if (!counts.has(insert.table)) {
1204
+ counts.set(insert.table, { new: 0, existing: 0 });
1205
+ }
1206
+ const tableCounts = counts.get(insert.table);
1207
+ const columnList = insert.columns.map((c) => `"${c}"`).join(", ");
1208
+ const stmt = `INSERT OR IGNORE INTO ${insert.table} (${columnList}) VALUES (${insert.valueSql})`;
1209
+ const result = db.prepare(stmt).run();
1210
+ if (result.changes > 0) {
1211
+ tableCounts.new++;
1212
+ } else {
1213
+ tableCounts.existing++;
1214
+ }
1215
+ }
1216
+ });
1217
+ runRestore();
1218
+ } finally {
1219
+ db.pragma("foreign_keys = ON");
1220
+ }
1221
+ const tables = Array.from(counts.entries()).map(([table, c]) => ({
1222
+ table,
1223
+ new: c.new,
1224
+ existing: c.existing
1225
+ }));
1226
+ const total_restored = tables.reduce((sum, t) => sum + t.new, 0);
1227
+ const total_skipped = tables.reduce((sum, t) => sum + t.existing, 0);
1228
+ return { tables, total_restored, total_skipped };
1229
+ }
1230
+
1231
+ // src/daemon/api/backup.ts
1232
+ function createBackupHandlers(deps) {
1233
+ async function handleCreateBackup(_req) {
1234
+ const filePath = createBackup(deps.db, deps.backupDir, deps.machineId);
1235
+ const backups = listBackups(deps.backupDir);
1236
+ const created = backups.find((b) => b.machine_id === deps.machineId);
1237
+ return {
1238
+ body: {
1239
+ file_path: filePath,
1240
+ machine_id: deps.machineId,
1241
+ size_bytes: created?.size_bytes ?? 0
1242
+ }
1243
+ };
1244
+ }
1245
+ async function handleListBackups(_req) {
1246
+ const backups = listBackups(deps.backupDir);
1247
+ return { body: { backups } };
1248
+ }
1249
+ async function handleRestorePreview(req) {
1250
+ const { machine_id } = req.body;
1251
+ if (!machine_id) {
1252
+ return { status: 400, body: { error: "missing_machine_id" } };
1253
+ }
1254
+ const backups = listBackups(deps.backupDir);
1255
+ const backup = backups.find((b) => b.machine_id === machine_id);
1256
+ if (!backup) {
1257
+ return { status: 404, body: { error: "backup_not_found" } };
1258
+ }
1259
+ const backupPath = `${deps.backupDir}/${backup.file_name}`;
1260
+ const tables = restorePreview(deps.db, backupPath);
1261
+ const total_new = tables.reduce((sum, t) => sum + t.new, 0);
1262
+ const total_existing = tables.reduce((sum, t) => sum + t.existing, 0);
1263
+ return { body: { machine_id, tables, total_new, total_existing } };
1264
+ }
1265
+ async function handleRestore(req) {
1266
+ const { machine_id } = req.body;
1267
+ if (!machine_id) {
1268
+ return { status: 400, body: { error: "missing_machine_id" } };
1269
+ }
1270
+ const backups = listBackups(deps.backupDir);
1271
+ const backup = backups.find((b) => b.machine_id === machine_id);
1272
+ if (!backup) {
1273
+ return { status: 404, body: { error: "backup_not_found" } };
1274
+ }
1275
+ const backupPath = `${deps.backupDir}/${backup.file_name}`;
1276
+ const result = restoreBackup(deps.db, backupPath);
1277
+ return { body: { machine_id, ...result } };
1278
+ }
1279
+ return {
1280
+ handleCreateBackup,
1281
+ handleListBackups,
1282
+ handleRestorePreview,
1283
+ handleRestore
1284
+ };
1285
+ }
1286
+
1287
+ // src/daemon/team-sync.ts
1288
+ var TeamSyncClient = class {
1289
+ workerUrl;
1290
+ apiKey;
1291
+ machineId;
1292
+ syncProtocolVersion;
1293
+ fetchFn;
1294
+ constructor(options) {
1295
+ this.workerUrl = options.workerUrl.replace(/\/+$/, "");
1296
+ this.apiKey = options.apiKey;
1297
+ this.machineId = options.machineId;
1298
+ this.syncProtocolVersion = options.syncProtocolVersion;
1299
+ this.fetchFn = options.fetch ?? globalThis.fetch;
1300
+ }
1301
+ /**
1302
+ * Register this machine with the team worker.
1303
+ */
1304
+ async connect(info) {
1305
+ const res = await this.request("POST", "/connect", {
1306
+ ...info,
1307
+ machine_id: this.machineId,
1308
+ sync_protocol_version: this.syncProtocolVersion
1309
+ });
1310
+ return res;
1311
+ }
1312
+ /**
1313
+ * Push a batch of outbox records to the team worker.
1314
+ *
1315
+ * @returns the number of records accepted by the worker.
1316
+ */
1317
+ async pushBatch(records) {
1318
+ const res = await this.request("POST", "/sync", {
1319
+ machine_id: this.machineId,
1320
+ sync_protocol_version: this.syncProtocolVersion,
1321
+ records: records.map((r) => {
1322
+ const data = typeof r.payload === "string" ? JSON.parse(r.payload) : r.payload;
1323
+ return {
1324
+ table: r.table_name,
1325
+ id: String(r.row_id),
1326
+ machine_id: r.machine_id,
1327
+ operation: r.operation,
1328
+ data,
1329
+ content_hash: data.content_hash ?? null
1330
+ };
1331
+ })
1332
+ });
1333
+ return res;
1334
+ }
1335
+ /**
1336
+ * Search team knowledge across all connected machines.
1337
+ *
1338
+ * Uses AbortController for timeout enforcement.
1339
+ */
1340
+ async search(query, options = {}) {
1341
+ const timeoutMs = options.timeoutMs ?? TEAM_SEARCH_TIMEOUT_MS;
1342
+ const controller = new AbortController();
1343
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
1344
+ try {
1345
+ const params = new URLSearchParams({ q: query });
1346
+ if (options.limit) params.set("limit", String(options.limit));
1347
+ if (options.tables) params.set("tables", options.tables.join(","));
1348
+ const res = await this.fetchFn(`${this.workerUrl}/search?${params}`, {
1349
+ method: "GET",
1350
+ headers: this.headers(),
1351
+ signal: controller.signal
1352
+ });
1353
+ if (!res.ok) {
1354
+ throw new Error(`Team search failed: ${res.status} ${res.statusText}`);
1355
+ }
1356
+ return await res.json();
1357
+ } finally {
1358
+ clearTimeout(timer);
1359
+ }
1360
+ }
1361
+ /**
1362
+ * Check worker health.
1363
+ */
1364
+ async health() {
1365
+ const controller = new AbortController();
1366
+ const timer = setTimeout(() => controller.abort(), TEAM_HEALTH_TIMEOUT_MS);
1367
+ try {
1368
+ const res = await this.fetchFn(`${this.workerUrl}/health`, {
1369
+ method: "GET",
1370
+ headers: this.headers(),
1371
+ signal: controller.signal
1372
+ });
1373
+ if (!res.ok) {
1374
+ throw new Error(`Health check failed: ${res.status} ${res.statusText}`);
1375
+ }
1376
+ return await res.json();
1377
+ } finally {
1378
+ clearTimeout(timer);
1379
+ }
1380
+ }
1381
+ /**
1382
+ * Get team configuration from the worker.
1383
+ */
1384
+ async getConfig() {
1385
+ const res = await this.request("GET", "/config");
1386
+ return res;
1387
+ }
1388
+ // ---------------------------------------------------------------------------
1389
+ // Internal
1390
+ // ---------------------------------------------------------------------------
1391
+ headers() {
1392
+ return {
1393
+ "Authorization": `Bearer ${this.apiKey}`,
1394
+ "Content-Type": "application/json"
1395
+ };
1396
+ }
1397
+ async request(method, path8, body) {
1398
+ const res = await this.fetchFn(`${this.workerUrl}${path8}`, {
1399
+ method,
1400
+ headers: this.headers(),
1401
+ body: body !== void 0 ? JSON.stringify(body) : void 0
1402
+ });
1403
+ if (!res.ok) {
1404
+ const text = await res.text().catch(() => "");
1405
+ throw new Error(`Team sync request ${method} ${path8} failed: ${res.status} ${text}`);
1406
+ }
1407
+ return res.json();
1408
+ }
1409
+ };
1410
+
1411
+ // src/daemon/api/team-connect.ts
1412
+ function createTeamHandlers(deps) {
1413
+ const { vaultDir, machineId } = deps;
1414
+ async function handleConnect(req) {
1415
+ const { url, api_key } = req.body;
1416
+ if (!url || !api_key) {
1417
+ return {
1418
+ status: 400,
1419
+ body: { error: "missing_fields", message: "Both url and api_key are required" }
1420
+ };
1421
+ }
1422
+ try {
1423
+ new URL(url);
1424
+ } catch {
1425
+ return {
1426
+ status: 400,
1427
+ body: { error: "invalid_url", message: "Invalid worker URL" }
1428
+ };
1429
+ }
1430
+ const client = new TeamSyncClient({
1431
+ workerUrl: url,
1432
+ apiKey: api_key,
1433
+ machineId,
1434
+ syncProtocolVersion: SYNC_PROTOCOL_VERSION
1435
+ });
1436
+ try {
1437
+ await client.health();
1438
+ } catch (err) {
1439
+ return {
1440
+ status: 502,
1441
+ body: {
1442
+ error: "connection_failed",
1443
+ message: `Could not connect to team worker: ${err.message}`
1444
+ }
1445
+ };
1446
+ }
1447
+ updateTeamConfig(vaultDir, {
1448
+ enabled: true,
1449
+ worker_url: url
1450
+ });
1451
+ writeSecret(vaultDir, TEAM_API_KEY_SECRET, api_key);
1452
+ deps.setTeamClient(client);
1453
+ const config = loadConfig(vaultDir);
1454
+ return { body: { connected: true, team: config.team } };
1455
+ }
1456
+ async function handleDisconnect(_req) {
1457
+ updateTeamConfig(vaultDir, { enabled: false });
1458
+ deps.setTeamClient(null);
1459
+ return { body: { connected: false } };
1460
+ }
1461
+ async function handleStatus(_req) {
1462
+ const config = loadConfig(vaultDir);
1463
+ const client = deps.getTeamClient();
1464
+ const secrets = readSecrets(vaultDir);
1465
+ const hasApiKey = Boolean(secrets[TEAM_API_KEY_SECRET]);
1466
+ let healthy = false;
1467
+ let healthError;
1468
+ if (client && config.team.enabled) {
1469
+ try {
1470
+ await client.health();
1471
+ healthy = true;
1472
+ } catch (err) {
1473
+ healthError = err.message;
1474
+ }
1475
+ }
1476
+ let pendingCount = 0;
1477
+ try {
1478
+ pendingCount = countPending();
1479
+ } catch {
1480
+ }
1481
+ return {
1482
+ body: {
1483
+ enabled: config.team.enabled,
1484
+ worker_url: config.team.worker_url ?? null,
1485
+ has_api_key: hasApiKey,
1486
+ api_key: secrets[TEAM_API_KEY_SECRET] ?? null,
1487
+ healthy,
1488
+ health_error: healthError,
1489
+ pending_sync_count: pendingCount,
1490
+ machine_id: machineId,
1491
+ package_version: getPluginVersion(),
1492
+ schema_version: SCHEMA_VERSION,
1493
+ sync_protocol_version: SYNC_PROTOCOL_VERSION
1494
+ }
1495
+ };
1496
+ }
1497
+ return { handleConnect, handleDisconnect, handleStatus };
1498
+ }
1499
+
1041
1500
  // src/daemon/api/progress.ts
1042
1501
  import { randomUUID } from "crypto";
1043
1502
  var MAX_CONCURRENT_OPERATIONS = 10;
@@ -1179,12 +1638,12 @@ async function handleGetModels(req) {
1179
1638
 
1180
1639
  // src/daemon/api/stats.ts
1181
1640
  import { createHash as createHash3 } from "crypto";
1182
- import fs3 from "fs";
1183
- import path4 from "path";
1641
+ import fs4 from "fs";
1642
+ import path5 from "path";
1184
1643
  function computeConfigHash(vaultDir) {
1185
1644
  try {
1186
- const configPath = path4.join(vaultDir, CONFIG_FILENAME);
1187
- const raw = fs3.readFileSync(configPath, "utf-8");
1645
+ const configPath = path5.join(vaultDir, CONFIG_FILENAME);
1646
+ const raw = fs4.readFileSync(configPath, "utf-8");
1188
1647
  return createHash3("md5").update(raw).digest("hex");
1189
1648
  } catch {
1190
1649
  return "";
@@ -1574,6 +2033,86 @@ async function handleGetGraph(req) {
1574
2033
  }
1575
2034
  };
1576
2035
  }
2036
+ var FULL_GRAPH_NODE_LIMIT = 500;
2037
+ async function handleGetFullGraph(_req) {
2038
+ const db = getDatabase();
2039
+ const entityRows = db.prepare(
2040
+ `SELECT id, type, name, properties, status, first_seen as created_at
2041
+ FROM entities WHERE agent_id = ? LIMIT ?`
2042
+ ).all(DEFAULT_AGENT_ID, FULL_GRAPH_NODE_LIMIT);
2043
+ const sporeRows = db.prepare(
2044
+ `SELECT id, observation_type, status, content, properties, created_at
2045
+ FROM spores WHERE agent_id = ? AND status = 'active' LIMIT ?`
2046
+ ).all(DEFAULT_AGENT_ID, FULL_GRAPH_NODE_LIMIT);
2047
+ const sessionRows = db.prepare(
2048
+ `SELECT id, title, summary, status, started_at as created_at
2049
+ FROM sessions ORDER BY created_at DESC LIMIT ?`
2050
+ ).all(FULL_GRAPH_NODE_LIMIT);
2051
+ const allIds = /* @__PURE__ */ new Set();
2052
+ for (const r of [...entityRows, ...sporeRows, ...sessionRows]) {
2053
+ allIds.add(r.id);
2054
+ }
2055
+ const excludedTypes = Array.from(EXCLUDED_GRAPH_EDGE_TYPES).map(() => "?").join(", ");
2056
+ const allIdsList = Array.from(allIds);
2057
+ const idPlaceholders = allIdsList.map(() => "?").join(", ");
2058
+ const edgeRows = db.prepare(
2059
+ `SELECT source_id, source_type, target_id, target_type, type, confidence
2060
+ FROM graph_edges
2061
+ WHERE agent_id = ?
2062
+ AND type NOT IN (${excludedTypes})
2063
+ AND source_id IN (${idPlaceholders})
2064
+ AND target_id IN (${idPlaceholders})`
2065
+ ).all(DEFAULT_AGENT_ID, ...Array.from(EXCLUDED_GRAPH_EDGE_TYPES), ...allIdsList, ...allIdsList);
2066
+ const filteredEdges = edgeRows;
2067
+ const mentionCounts = /* @__PURE__ */ new Map();
2068
+ const entityIdArray = entityRows.map((r) => r.id);
2069
+ if (entityIdArray.length > 0) {
2070
+ const placeholders = entityIdArray.map(() => "?").join(", ");
2071
+ const mentionRows = db.prepare(
2072
+ `SELECT entity_id, COUNT(*) as count FROM entity_mentions
2073
+ WHERE entity_id IN (${placeholders}) GROUP BY entity_id`
2074
+ ).all(...entityIdArray);
2075
+ for (const row of mentionRows) {
2076
+ mentionCounts.set(row.entity_id, Number(row.count));
2077
+ }
2078
+ }
2079
+ const nodes = [
2080
+ ...entityRows.map((n) => ({
2081
+ id: n.id,
2082
+ name: n.name,
2083
+ type: n.type,
2084
+ status: n.status ?? void 0,
2085
+ created_at: n.created_at,
2086
+ properties: n.properties ?? void 0,
2087
+ mention_count: mentionCounts.get(n.id) ?? 0
2088
+ })),
2089
+ ...sporeRows.map((n) => ({
2090
+ id: n.id,
2091
+ name: (n.content ?? "").slice(0, SPORE_NAME_PREVIEW_CHARS),
2092
+ type: "spore",
2093
+ status: n.status ?? void 0,
2094
+ created_at: n.created_at,
2095
+ content: n.content,
2096
+ properties: n.properties ?? void 0,
2097
+ observation_type: n.observation_type
2098
+ })),
2099
+ ...sessionRows.map((n) => ({
2100
+ id: n.id,
2101
+ name: n.title ?? `Session ${n.id.slice(-6)}`,
2102
+ type: "session",
2103
+ status: n.status ?? void 0,
2104
+ created_at: n.created_at,
2105
+ content: n.summary ?? void 0
2106
+ }))
2107
+ ];
2108
+ const edges = filteredEdges.map((e) => ({
2109
+ source_id: e.source_id,
2110
+ target_id: e.target_id,
2111
+ label: e.type,
2112
+ weight: e.confidence
2113
+ }));
2114
+ return { body: { nodes, edges } };
2115
+ }
1577
2116
  async function handleGetDigest(req) {
1578
2117
  const agentId = req.query.agent_id ?? DEFAULT_AGENT_ID;
1579
2118
  const extracts = listDigestExtracts(agentId);
@@ -1590,14 +2129,14 @@ function createSearchHandler(deps) {
1590
2129
  const limit = Number(req.query.limit) || SEARCH_RESULTS_DEFAULT_LIMIT;
1591
2130
  const namespace = req.query.namespace;
1592
2131
  if (mode === "fts") {
1593
- const results2 = fullTextSearch(query, { type, limit });
1594
- return { body: { mode: "fts", results: results2 } };
2132
+ const results = fullTextSearch(query, { type, limit });
2133
+ return { body: { mode: "fts", results } };
1595
2134
  }
1596
2135
  const queryVector = await deps.embeddingManager.embedQuery(query);
1597
2136
  if (queryVector === null) {
1598
2137
  if (mode === "auto") {
1599
- const results2 = fullTextSearch(query, { type, limit });
1600
- return { body: { mode: "fts", results: results2, fallback: true } };
2138
+ const results = fullTextSearch(query, { type, limit });
2139
+ return { body: { mode: "fts", results, fallback: true } };
1601
2140
  }
1602
2141
  return { body: { mode: "semantic", results: [], provider_unavailable: true } };
1603
2142
  }
@@ -1607,8 +2146,25 @@ function createSearchHandler(deps) {
1607
2146
  limit,
1608
2147
  threshold: SEARCH_SIMILARITY_THRESHOLD
1609
2148
  });
1610
- const results = hydrateSearchResults(vectorResults);
1611
- return { body: { mode: "semantic", results } };
2149
+ const localResults = hydrateSearchResults(vectorResults).map((r) => ({
2150
+ ...r,
2151
+ source: "local"
2152
+ }));
2153
+ const teamClient = deps.getTeamClient?.();
2154
+ let teamResults = [];
2155
+ if (teamClient) {
2156
+ try {
2157
+ const teamResponse = await teamClient.search(query, { limit });
2158
+ teamResults = teamResponse.results.map((r) => ({
2159
+ ...r,
2160
+ source: `${TEAM_SOURCE_PREFIX}${r.machine_id}`
2161
+ }));
2162
+ } catch {
2163
+ }
2164
+ }
2165
+ const dedupedTeam = deps.machineId ? teamResults.filter((r) => r.machine_id !== deps.machineId) : teamResults;
2166
+ const merged = [...localResults, ...dedupedTeam].sort((a, b) => (b.score ?? 0) - (a.score ?? 0)).slice(0, limit);
2167
+ return { body: { mode: "semantic", results: merged } };
1612
2168
  };
1613
2169
  }
1614
2170
 
@@ -2903,19 +3459,19 @@ function testCloud() {
2903
3459
  }
2904
3460
 
2905
3461
  // src/daemon/log-reconcile.ts
2906
- import fs4 from "fs";
2907
- import path5 from "path";
3462
+ import fs5 from "fs";
3463
+ import path6 from "path";
2908
3464
  function reconcileLogBuffer(logDir, sinceTimestamp) {
2909
3465
  let replayed = 0;
2910
3466
  const files = [];
2911
3467
  for (let i = 3; i >= 1; i--) {
2912
- const rotated = path5.join(logDir, `daemon.${i}.log`);
2913
- if (fs4.existsSync(rotated)) files.push(rotated);
3468
+ const rotated = path6.join(logDir, `daemon.${i}.log`);
3469
+ if (fs5.existsSync(rotated)) files.push(rotated);
2914
3470
  }
2915
- const current = path5.join(logDir, "daemon.log");
2916
- if (fs4.existsSync(current)) files.push(current);
3471
+ const current = path6.join(logDir, "daemon.log");
3472
+ if (fs5.existsSync(current)) files.push(current);
2917
3473
  for (const file of files) {
2918
- const content = fs4.readFileSync(file, "utf-8");
3474
+ const content = fs5.readFileSync(file, "utf-8");
2919
3475
  for (const line of content.split("\n")) {
2920
3476
  if (!line.trim()) continue;
2921
3477
  try {
@@ -3131,8 +3687,8 @@ async function runSessionMaintenance(deps) {
3131
3687
  }
3132
3688
 
3133
3689
  // src/daemon/main.ts
3134
- import fs5 from "fs";
3135
- import path6 from "path";
3690
+ import fs6 from "fs";
3691
+ import path7 from "path";
3136
3692
  var AGENT_RUNS_DEFAULT_LIMIT = 50;
3137
3693
  var TOOL_INPUT_STORE_LIMIT = 4e3;
3138
3694
  var TOOL_OUTPUT_STORE_LIMIT = 2e3;
@@ -3258,10 +3814,10 @@ function handleCompact(sessionId, phase, trigger, compactSummary) {
3258
3814
  });
3259
3815
  }
3260
3816
  function killStaleDaemon(vaultDir, logger) {
3261
- const daemonJsonPath = path6.join(vaultDir, "daemon.json");
3817
+ const daemonJsonPath = path7.join(vaultDir, "daemon.json");
3262
3818
  try {
3263
- if (!fs5.existsSync(daemonJsonPath)) return;
3264
- const info = JSON.parse(fs5.readFileSync(daemonJsonPath, "utf-8"));
3819
+ if (!fs6.existsSync(daemonJsonPath)) return;
3820
+ const info = JSON.parse(fs6.readFileSync(daemonJsonPath, "utf-8"));
3265
3821
  if (!info.pid) return;
3266
3822
  if (info.pid === process.pid) return;
3267
3823
  try {
@@ -3270,7 +3826,7 @@ function killStaleDaemon(vaultDir, logger) {
3270
3826
  logger.info(LOG_KINDS.DAEMON_START, "Killed stale daemon", { pid: info.pid });
3271
3827
  } catch {
3272
3828
  }
3273
- fs5.unlinkSync(daemonJsonPath);
3829
+ fs6.unlinkSync(daemonJsonPath);
3274
3830
  } catch {
3275
3831
  }
3276
3832
  }
@@ -3280,7 +3836,7 @@ async function main() {
3280
3836
  process.stderr.write("Usage: mycod --vault <path>\n");
3281
3837
  process.exit(1);
3282
3838
  }
3283
- const vaultDir = path6.resolve(vaultArg);
3839
+ const vaultDir = path7.resolve(vaultArg);
3284
3840
  loadSecrets(vaultDir);
3285
3841
  const config = loadConfig(vaultDir);
3286
3842
  const manifests = loadManifests();
@@ -3291,7 +3847,7 @@ async function main() {
3291
3847
  projectRoot,
3292
3848
  extensions: config.capture.artifact_extensions
3293
3849
  };
3294
- const logger = new DaemonLogger(path6.join(vaultDir, "logs"), {
3850
+ const logger = new DaemonLogger(path7.join(vaultDir, "logs"), {
3295
3851
  level: config.daemon.log_level
3296
3852
  });
3297
3853
  killStaleDaemon(vaultDir, logger);
@@ -3300,9 +3856,12 @@ async function main() {
3300
3856
  embedding_provider: config.embedding.provider
3301
3857
  });
3302
3858
  logger.info(LOG_KINDS.CAPTURE_PLAN, "Plan watch directories", { dirs: planWatchConfig.watchDirs });
3859
+ const machineId = getMachineId(vaultDir);
3860
+ logger.info(LOG_KINDS.DAEMON_START, "Machine ID resolved", { machine_id: machineId });
3303
3861
  const db = initDatabase(vaultDbPath(vaultDir));
3304
- createSchema(db);
3862
+ createSchema(db, machineId);
3305
3863
  logger.info(LOG_KINDS.DAEMON_START, "SQLite initialized", { vault: vaultDir });
3864
+ initTeamContext(config.team.enabled, machineId);
3306
3865
  logger.setPersistFn((entry) => {
3307
3866
  const { timestamp, level, kind, component, message, ...rest } = entry;
3308
3867
  insertLogEntry({
@@ -3317,13 +3876,13 @@ async function main() {
3317
3876
  });
3318
3877
  const lastLogTimestamp = getMaxTimestamp();
3319
3878
  if (lastLogTimestamp) {
3320
- const logDir = path6.join(vaultDir, "logs");
3879
+ const logDir = path7.join(vaultDir, "logs");
3321
3880
  const replayedCount = reconcileLogBuffer(logDir, lastLogTimestamp);
3322
3881
  if (replayedCount > 0) {
3323
3882
  logger.info(LOG_KINDS.DAEMON_RECONCILE, `Replayed ${replayedCount} log entries from buffer`, { replayed: replayedCount });
3324
3883
  }
3325
3884
  }
3326
- const vectorsDbPath = path6.join(vaultDir, "vectors.db");
3885
+ const vectorsDbPath = path7.join(vaultDir, "vectors.db");
3327
3886
  const vectorStore = new SqliteVecVectorStore(vectorsDbPath);
3328
3887
  const llmProvider = createEmbeddingProvider(config.embedding);
3329
3888
  const embeddingProvider = new EmbeddingProviderAdapter(llmProvider, config.embedding);
@@ -3331,7 +3890,7 @@ async function main() {
3331
3890
  const embeddingManager = new EmbeddingManager(vectorStore, embeddingProvider, recordSource, logger);
3332
3891
  logger.info(LOG_KINDS.EMBEDDING_EMBED, "EmbeddingManager initialized", { vectors_db: vectorsDbPath });
3333
3892
  try {
3334
- const { registerBuiltInAgentsAndTasks, resolveDefinitionsDir: resolveDefinitionsDir2 } = await import("./loader-SH67XD54.js");
3893
+ const { registerBuiltInAgentsAndTasks, resolveDefinitionsDir: resolveDefinitionsDir2 } = await import("./loader-GKXR5ONU.js");
3335
3894
  const definitionsDir = resolveDefinitionsDir2();
3336
3895
  await registerBuiltInAgentsAndTasks(definitionsDir, vaultDir);
3337
3896
  logger.info(LOG_KINDS.AGENT_TASK, "Built-in agents and tasks registered");
@@ -3357,10 +3916,10 @@ async function main() {
3357
3916
  }
3358
3917
  let uiDir = null;
3359
3918
  {
3360
- const root = findPackageRoot(path6.dirname(new URL(import.meta.url).pathname));
3919
+ const root = findPackageRoot(path7.dirname(new URL(import.meta.url).pathname));
3361
3920
  if (root) {
3362
- const candidate = path6.join(root, "dist", "ui");
3363
- if (fs5.existsSync(candidate)) uiDir = candidate;
3921
+ const candidate = path7.join(root, "dist", "ui");
3922
+ if (fs6.existsSync(candidate)) uiDir = candidate;
3364
3923
  }
3365
3924
  }
3366
3925
  if (uiDir) {
@@ -3397,7 +3956,7 @@ async function main() {
3397
3956
  const running = getRunningRun(DEFAULT_AGENT_ID);
3398
3957
  if (running) return;
3399
3958
  try {
3400
- const { runAgent } = await import("./executor-ONSDHPGX.js");
3959
+ const { runAgent } = await import("./executor-A5C5KDLP.js");
3401
3960
  runAgent(vaultDir, {
3402
3961
  task: "title-summary",
3403
3962
  instruction: `Process session ${sessionId} only`,
@@ -3406,7 +3965,7 @@ async function main() {
3406
3965
  } catch {
3407
3966
  }
3408
3967
  }
3409
- const bufferDir = path6.join(vaultDir, "buffer");
3968
+ const bufferDir = path7.join(vaultDir, "buffer");
3410
3969
  const sessionBuffers = /* @__PURE__ */ new Map();
3411
3970
  const startupCleanedCount = cleanStaleBuffers(bufferDir, STALE_BUFFER_MAX_AGE_MS);
3412
3971
  if (startupCleanedCount > 0) {
@@ -3450,9 +4009,9 @@ async function main() {
3450
4009
  function reconcileSession(sessionId) {
3451
4010
  if (reconciledSessions.has(sessionId)) return;
3452
4011
  reconciledSessions.add(sessionId);
3453
- const bufferPath = path6.join(bufferDir, `${sessionId}.jsonl`);
3454
- if (!fs5.existsSync(bufferPath)) return;
3455
- const content = fs5.readFileSync(bufferPath, "utf-8").trim();
4012
+ const bufferPath = path7.join(bufferDir, `${sessionId}.jsonl`);
4013
+ if (!fs6.existsSync(bufferPath)) return;
4014
+ const content = fs6.readFileSync(bufferPath, "utf-8").trim();
3456
4015
  if (!content) return;
3457
4016
  if (!getSession(sessionId)) {
3458
4017
  logger.debug(LOG_KINDS.LIFECYCLE_RECONCILE, "Skipping reconciliation for deleted session", { session_id: sessionId });
@@ -3606,10 +4165,10 @@ async function main() {
3606
4165
  );
3607
4166
  if (planFilePath) {
3608
4167
  const captureSessionId = event.session_id;
3609
- fs5.promises.readFile(planFilePath, "utf-8").then((planContent) => {
4168
+ fs6.promises.readFile(planFilePath, "utf-8").then((planContent) => {
3610
4169
  const latestBatch = getLatestBatch(captureSessionId);
3611
4170
  capturePlan({
3612
- sourcePath: path6.relative(projectRoot, planFilePath),
4171
+ sourcePath: path7.relative(projectRoot, planFilePath),
3613
4172
  content: planContent,
3614
4173
  sessionId: captureSessionId,
3615
4174
  promptBatchId: latestBatch?.id ?? null
@@ -4024,6 +4583,7 @@ async function main() {
4024
4583
  server.registerRoute("GET", "/api/spores", handleListSpores);
4025
4584
  server.registerRoute("GET", "/api/spores/:id", handleGetSpore);
4026
4585
  server.registerRoute("GET", "/api/entities", handleListEntities);
4586
+ server.registerRoute("GET", "/api/graph", handleGetFullGraph);
4027
4587
  server.registerRoute("GET", "/api/graph/:id", handleGetGraph);
4028
4588
  server.registerRoute("GET", "/api/digest", handleGetDigest);
4029
4589
  const ATTACHMENT_MEDIA_TYPES = {
@@ -4043,14 +4603,14 @@ async function main() {
4043
4603
  const contentType2 = att.media_type ?? "application/octet-stream";
4044
4604
  return { status: 200, headers: { "Content-Type": contentType2 }, body: att.data };
4045
4605
  }
4046
- const filePath = path6.join(vaultDir, "attachments", filename);
4606
+ const filePath = path7.join(vaultDir, "attachments", filename);
4047
4607
  let diskData;
4048
4608
  try {
4049
- diskData = fs5.readFileSync(filePath);
4609
+ diskData = fs6.readFileSync(filePath);
4050
4610
  } catch {
4051
4611
  return { status: 404, body: { error: "not_found" } };
4052
4612
  }
4053
- const ext = path6.extname(filename).slice(1).toLowerCase();
4613
+ const ext = path7.extname(filename).slice(1).toLowerCase();
4054
4614
  const contentType = ATTACHMENT_MEDIA_TYPES[ext] ?? "application/octet-stream";
4055
4615
  return { status: 200, headers: { "Content-Type": contentType }, body: diskData };
4056
4616
  });
@@ -4061,7 +4621,7 @@ async function main() {
4061
4621
  });
4062
4622
  server.registerRoute("POST", "/api/agent/run", async (req) => {
4063
4623
  const { task, instruction, agentId } = AgentRunBody.parse(req.body);
4064
- const { runAgent } = await import("./executor-ONSDHPGX.js");
4624
+ const { runAgent } = await import("./executor-A5C5KDLP.js");
4065
4625
  const resultPromise = runAgent(vaultDir, { task, instruction, agentId, embeddingManager });
4066
4626
  const effectiveAgentId = agentId ?? "myco-agent";
4067
4627
  const latestRun = getRunningRun(effectiveAgentId);
@@ -4242,7 +4802,7 @@ async function main() {
4242
4802
  name: USER_AGENT_NAME,
4243
4803
  created_at: now
4244
4804
  });
4245
- const { insertResolutionEvent } = await import("./resolution-events-TFEQPVKS.js");
4805
+ const { insertResolutionEvent } = await import("./resolution-events-UPHJJLDQ.js");
4246
4806
  const resolutionId = `res-${randomBytes(RESOLUTION_ID_RANDOM_BYTES).toString("hex")}`;
4247
4807
  insertResolutionEvent({
4248
4808
  id: resolutionId,
@@ -4261,7 +4821,69 @@ async function main() {
4261
4821
  }
4262
4822
  };
4263
4823
  });
4264
- server.registerRoute("GET", "/api/search", createSearchHandler({ embeddingManager }));
4824
+ const backupDir = config.backup.dir ? path7.resolve(config.backup.dir) : path7.resolve(vaultDir, "backups");
4825
+ const backupHandlers = createBackupHandlers({ db, backupDir, machineId });
4826
+ server.registerRoute("POST", "/api/backup", backupHandlers.handleCreateBackup);
4827
+ server.registerRoute("GET", "/api/backups", backupHandlers.handleListBackups);
4828
+ server.registerRoute("POST", "/api/restore/preview", backupHandlers.handleRestorePreview);
4829
+ server.registerRoute("POST", "/api/restore", backupHandlers.handleRestore);
4830
+ server.registerRoute("GET", "/api/backup/config", async () => {
4831
+ const cfg = loadConfig(vaultDir);
4832
+ return { body: { dir: cfg.backup.dir ?? null, default_dir: path7.resolve(vaultDir, "backups") } };
4833
+ });
4834
+ server.registerRoute("PUT", "/api/backup/config", async (req) => {
4835
+ const { dir } = req.body;
4836
+ updateBackupConfig(vaultDir, { dir: dir || void 0 });
4837
+ return { body: { dir: dir || null } };
4838
+ });
4839
+ let teamClient = null;
4840
+ if (config.team.enabled && config.team.worker_url) {
4841
+ const secrets = readSecrets(vaultDir);
4842
+ const teamApiKey = secrets["MYCO_TEAM_API_KEY"];
4843
+ if (teamApiKey) {
4844
+ teamClient = new TeamSyncClient({
4845
+ workerUrl: config.team.worker_url,
4846
+ apiKey: teamApiKey,
4847
+ machineId,
4848
+ syncProtocolVersion: SYNC_PROTOCOL_VERSION
4849
+ });
4850
+ logger.info(LOG_KINDS.TEAM_SYNC_START, "Team sync client initialized", { worker_url: config.team.worker_url });
4851
+ teamClient.connect({
4852
+ machine_id: machineId,
4853
+ version: server.version
4854
+ }).then(() => {
4855
+ logger.info(LOG_KINDS.TEAM_SYNC_START, "Node registered with team worker");
4856
+ }).catch((err) => {
4857
+ logger.warn(LOG_KINDS.TEAM_SYNC_ERROR, "Node registration failed (will retry on next flush)", { error: err.message });
4858
+ });
4859
+ setTimeout(() => {
4860
+ try {
4861
+ const backfilled = backfillUnsynced(machineId);
4862
+ if (backfilled > 0) {
4863
+ logger.info(LOG_KINDS.TEAM_SYNC_START, `Backfilled ${backfilled} unsynced records into outbox`);
4864
+ }
4865
+ } catch (err) {
4866
+ logger.error(LOG_KINDS.TEAM_SYNC_ERROR, "Backfill failed", { error: err.message });
4867
+ }
4868
+ }, 0);
4869
+ }
4870
+ }
4871
+ const teamHandlers = createTeamHandlers({
4872
+ vaultDir,
4873
+ machineId,
4874
+ getTeamClient: () => teamClient,
4875
+ setTeamClient: (c) => {
4876
+ teamClient = c;
4877
+ }
4878
+ });
4879
+ server.registerRoute("POST", "/api/team/connect", teamHandlers.handleConnect);
4880
+ server.registerRoute("POST", "/api/team/disconnect", teamHandlers.handleDisconnect);
4881
+ server.registerRoute("GET", "/api/team/status", teamHandlers.handleStatus);
4882
+ server.registerRoute("POST", "/api/team/backfill", async () => {
4883
+ const count = backfillUnsynced(machineId);
4884
+ return { body: { enqueued: count } };
4885
+ });
4886
+ server.registerRoute("GET", "/api/search", createSearchHandler({ embeddingManager, getTeamClient: () => teamClient, machineId }));
4265
4887
  server.registerRoute("GET", "/api/activity", handleGetFeed);
4266
4888
  server.registerRoute("GET", "/api/embedding/status", async () => handleGetEmbeddingStatus(vaultDir));
4267
4889
  server.registerRoute("GET", "/api/embedding/details", async () => handleEmbeddingDetails(embeddingManager));
@@ -4335,7 +4957,7 @@ async function main() {
4335
4957
  lastAgentRun = Date.now();
4336
4958
  try {
4337
4959
  logger.info(LOG_KINDS.AGENT_AUTO_RUN, "Unprocessed batches found, starting agent", { count });
4338
- const { runAgent } = await import("./executor-ONSDHPGX.js");
4960
+ const { runAgent } = await import("./executor-A5C5KDLP.js");
4339
4961
  const runResult = await runAgent(vaultDir, { embeddingManager });
4340
4962
  logger.info(LOG_KINDS.AGENT_RUN, "Agent run completed", { status: runResult.status, runId: runResult.runId });
4341
4963
  } catch (err) {
@@ -4360,6 +4982,56 @@ async function main() {
4360
4982
  }
4361
4983
  }
4362
4984
  });
4985
+ powerManager.register({
4986
+ name: "auto-backup",
4987
+ runIn: ["idle", "sleep"],
4988
+ fn: async () => {
4989
+ try {
4990
+ logger.info(LOG_KINDS.BACKUP_START, "Auto-backup starting");
4991
+ const filePath = createBackup(db, backupDir, machineId);
4992
+ logger.info(LOG_KINDS.BACKUP_COMPLETE, "Auto-backup complete", { file_path: filePath });
4993
+ } catch (err) {
4994
+ logger.error(LOG_KINDS.BACKUP_ERROR, "Auto-backup failed", { error: err.message });
4995
+ }
4996
+ }
4997
+ });
4998
+ if (config.team.enabled) {
4999
+ powerManager.register({
5000
+ name: "team-sync-flush",
5001
+ runIn: ["active", "idle"],
5002
+ fn: async () => {
5003
+ const client = teamClient;
5004
+ if (!client) return;
5005
+ try {
5006
+ const pending = listPending();
5007
+ if (pending.length === 0) return;
5008
+ logger.info(LOG_KINDS.TEAM_SYNC_START, "Flushing outbox", { count: pending.length });
5009
+ const result = await client.pushBatch(pending);
5010
+ if (result.synced > 0 || result.skipped > 0) {
5011
+ const failedIds = new Set(result.errors.map((e) => e.id));
5012
+ const sentIds = pending.filter((r) => !failedIds.has(String(r.row_id))).map((r) => r.id);
5013
+ if (sentIds.length > 0) {
5014
+ markSent(sentIds, epochSeconds());
5015
+ }
5016
+ }
5017
+ if (result.errors.length > 0) {
5018
+ logger.warn(LOG_KINDS.TEAM_SYNC_ERROR, `Sync errors: ${result.errors.length}`, {
5019
+ errors: result.errors.slice(0, 5)
5020
+ });
5021
+ }
5022
+ pruneOld();
5023
+ logger.info(LOG_KINDS.TEAM_SYNC_COMPLETE, "Outbox flush complete", {
5024
+ synced: result.synced,
5025
+ skipped: result.skipped,
5026
+ errors: result.errors.length,
5027
+ total: pending.length
5028
+ });
5029
+ } catch (err) {
5030
+ logger.error(LOG_KINDS.TEAM_SYNC_ERROR, "Outbox flush failed", { error: err.message });
5031
+ }
5032
+ }
5033
+ });
5034
+ }
4363
5035
  powerManager.start();
4364
5036
  const shutdown = async (signal) => {
4365
5037
  logger.info(LOG_KINDS.DAEMON_START, `${signal} received`);
@@ -4390,4 +5062,4 @@ export {
4390
5062
  handleUserPrompt,
4391
5063
  main
4392
5064
  };
4393
- //# sourceMappingURL=main-BMCL7CPO.js.map
5065
+ //# sourceMappingURL=main-PVX6R3I6.js.map