@goondocks/myco 0.17.2 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/README.md +14 -22
  2. package/bin/myco-run +15 -2
  3. package/dist/{agent-run-7AYHXIEF.js → agent-run-I4O2K2CK.js} +7 -7
  4. package/dist/{agent-tasks-UUIFKBD4.js → agent-tasks-UOW5BQIB.js} +7 -7
  5. package/dist/{chunk-XD3NEN3Q.js → chunk-2V7HR7HB.js} +2 -2
  6. package/dist/chunk-44PZCAYS.js +107 -0
  7. package/dist/chunk-44PZCAYS.js.map +1 -0
  8. package/dist/{chunk-DT42247G.js → chunk-75AZFBFW.js} +3 -3
  9. package/dist/{chunk-RMJPQZGF.js → chunk-C3EGL5JX.js} +755 -266
  10. package/dist/chunk-C3EGL5JX.js.map +1 -0
  11. package/dist/{chunk-7DAH5GLC.js → chunk-CKJAWZQE.js} +5 -1
  12. package/dist/chunk-CKJAWZQE.js.map +1 -0
  13. package/dist/{chunk-ML6GTPZU.js → chunk-CML4MCYF.js} +2 -2
  14. package/dist/{chunk-UTLWSKDV.js → chunk-CURS2TNP.js} +45 -4
  15. package/dist/chunk-CURS2TNP.js.map +1 -0
  16. package/dist/{chunk-EBIYONNZ.js → chunk-DPSLJ242.js} +34 -2
  17. package/dist/chunk-DPSLJ242.js.map +1 -0
  18. package/dist/{chunk-BZDZORVP.js → chunk-LSP5HYOO.js} +19 -16
  19. package/dist/chunk-LSP5HYOO.js.map +1 -0
  20. package/dist/{chunk-NUSTG3BH.js → chunk-N75GMQGA.js} +3 -3
  21. package/dist/{chunk-F6C4IC6R.js → chunk-NI23QCHB.js} +3 -3
  22. package/dist/{chunk-C3C5QVLK.js → chunk-O3TRN3RC.js} +2 -2
  23. package/dist/{chunk-3NCVCGUZ.js → chunk-RAV5YMRU.js} +3 -3
  24. package/dist/{chunk-25WHTV4N.js → chunk-RIDSOQDR.js} +21 -7
  25. package/dist/chunk-RIDSOQDR.js.map +1 -0
  26. package/dist/{chunk-HPZ7YAMA.js → chunk-TCSVDQF5.js} +1130 -195
  27. package/dist/chunk-TCSVDQF5.js.map +1 -0
  28. package/dist/{chunk-CTF7TQMJ.js → chunk-TLK46KKD.js} +14 -4
  29. package/dist/chunk-TLK46KKD.js.map +1 -0
  30. package/dist/{chunk-IGBHLFV5.js → chunk-TOER6RNC.js} +22 -2
  31. package/dist/chunk-TOER6RNC.js.map +1 -0
  32. package/dist/{chunk-ZSJPI5MS.js → chunk-TZAXQKO6.js} +6 -2
  33. package/dist/chunk-TZAXQKO6.js.map +1 -0
  34. package/dist/{chunk-RKPTMHED.js → chunk-U3J2DDSR.js} +2 -2
  35. package/dist/{chunk-SI5BBQAT.js → chunk-W7WENJ6F.js} +2 -2
  36. package/dist/{chunk-VVGZL2HX.js → chunk-WYOE4IAX.js} +153 -15
  37. package/dist/{chunk-VVGZL2HX.js.map → chunk-WYOE4IAX.js.map} +1 -1
  38. package/dist/{chunk-XZWFMMJR.js → chunk-XWOQL4XN.js} +3 -3
  39. package/dist/{chunk-5ZISXCDC.js → chunk-YZPI2Y3E.js} +39 -5
  40. package/dist/chunk-YZPI2Y3E.js.map +1 -0
  41. package/dist/{cli-WJVYP2QT.js → cli-D3TJYJ2U.js} +40 -40
  42. package/dist/{client-LZ3ZR4HC.js → client-4LLEXLVK.js} +4 -4
  43. package/dist/{config-ZQIMG3FB.js → config-DA4IUVFL.js} +3 -3
  44. package/dist/{detect-NJ2OREDP.js → detect-SZ2KDUF4.js} +2 -2
  45. package/dist/{detect-providers-C64L3QET.js → detect-providers-PSVKXTWE.js} +4 -4
  46. package/dist/{doctor-XEPBNHM3.js → doctor-KCTXPX5D.js} +12 -12
  47. package/dist/{executor-NXKJU5KW.js → executor-UYIZC3L5.js} +93 -285
  48. package/dist/executor-UYIZC3L5.js.map +1 -0
  49. package/dist/{init-BHVQAQ27.js → init-QFNBKKDC.js} +13 -13
  50. package/dist/{installer-45ZLP2RP.js → installer-BWJED3ED.js} +2 -2
  51. package/dist/{llm-KTD6SR55.js → llm-SMA5ZEAW.js} +4 -4
  52. package/dist/{loader-SHRKUKOS.js → loader-Q3P3R4UP.js} +3 -3
  53. package/dist/{loader-NEX3UF6U.js → loader-SKKUMT5C.js} +3 -3
  54. package/dist/{main-YFVBIRRK.js → main-5THODR77.js} +751 -257
  55. package/dist/main-5THODR77.js.map +1 -0
  56. package/dist/{open-2U7ZRGA3.js → open-7737CSPN.js} +7 -7
  57. package/dist/{post-compact-QIBMEWL3.js → post-compact-2TJ5FPZH.js} +7 -7
  58. package/dist/{post-tool-use-ICGFXDVY.js → post-tool-use-FRTSICC3.js} +6 -6
  59. package/dist/{post-tool-use-failure-C7TLH3XQ.js → post-tool-use-failure-KYO2NCNB.js} +7 -7
  60. package/dist/{pre-compact-IF7K4TQK.js → pre-compact-J6GCJEJR.js} +7 -7
  61. package/dist/{provider-check-LTLQ6BUZ.js → provider-check-AE3L5Z6R.js} +4 -4
  62. package/dist/{registry-TFQ22Z7N.js → registry-O2NZLO3V.js} +4 -4
  63. package/dist/{remove-FBGM2QVJ.js → remove-3WZZC7AX.js} +9 -9
  64. package/dist/{resolution-events-HGKIJOTA.js → resolution-events-XWYLLDRK.js} +4 -4
  65. package/dist/{restart-TQEECRNW.js → restart-HUHEFOXU.js} +8 -8
  66. package/dist/{search-NN5FC4Z6.js → search-ZGN3LDXG.js} +8 -8
  67. package/dist/{server-XMWJ4GF7.js → server-PTXLVVEE.js} +4 -4
  68. package/dist/{session-GLPAFYPO.js → session-7VV3IQMO.js} +9 -9
  69. package/dist/{session-end-TI3ILRBC.js → session-end-SMU55UCM.js} +6 -6
  70. package/dist/{session-start-PJLJDVJJ.js → session-start-NIMWEOIZ.js} +29 -13
  71. package/dist/session-start-NIMWEOIZ.js.map +1 -0
  72. package/dist/{setup-llm-AQSWLXCZ.js → setup-llm-7S3VPAPN.js} +8 -8
  73. package/dist/src/agent/definitions/tasks/extract-only.yaml +1 -1
  74. package/dist/src/agent/definitions/tasks/full-intelligence.yaml +10 -0
  75. package/dist/src/agent/definitions/tasks/skill-evolve.yaml +163 -49
  76. package/dist/src/agent/definitions/tasks/skill-generate.yaml +44 -27
  77. package/dist/src/agent/definitions/tasks/skill-survey.yaml +132 -138
  78. package/dist/src/agent/definitions/tasks/supersession-sweep.yaml +1 -1
  79. package/dist/src/cli.js +1 -1
  80. package/dist/src/daemon/main.js +1 -1
  81. package/dist/src/hooks/post-tool-use.js +1 -1
  82. package/dist/src/hooks/session-end.js +1 -1
  83. package/dist/src/hooks/session-start.js +1 -1
  84. package/dist/src/hooks/stop.js +1 -1
  85. package/dist/src/hooks/user-prompt-submit.js +1 -1
  86. package/dist/src/mcp/server.js +1 -1
  87. package/dist/src/symbionts/manifests/codex.yaml +85 -0
  88. package/dist/src/symbionts/templates/claude-code/hooks.json +12 -12
  89. package/dist/src/symbionts/templates/claude-code/settings.json +3 -3
  90. package/dist/src/symbionts/templates/codex/hooks.json +4 -4
  91. package/dist/src/symbionts/templates/cursor/hooks.json +9 -9
  92. package/dist/src/symbionts/templates/cursor/settings.json +2 -2
  93. package/dist/src/symbionts/templates/gemini/hooks.json +6 -6
  94. package/dist/src/symbionts/templates/gemini/settings.json +2 -2
  95. package/dist/src/symbionts/templates/myco-run.cjs +44 -0
  96. package/dist/src/symbionts/templates/opencode/settings.json +2 -2
  97. package/dist/src/symbionts/templates/vscode-copilot/hooks.json +7 -7
  98. package/dist/src/symbionts/templates/vscode-copilot/settings.json +2 -2
  99. package/dist/src/symbionts/templates/windsurf/hooks.json +4 -4
  100. package/dist/src/symbionts/templates/windsurf/settings.json +2 -2
  101. package/dist/src/worker/package-lock.json +4338 -0
  102. package/dist/src/worker/package.json +5 -0
  103. package/dist/src/worker/src/index.ts +58 -65
  104. package/dist/src/worker/src/mcp/auth.ts +65 -0
  105. package/dist/src/worker/src/mcp/server.ts +53 -0
  106. package/dist/src/worker/src/mcp/tools/context.ts +13 -0
  107. package/dist/src/worker/src/mcp/tools/get.ts +15 -0
  108. package/dist/src/worker/src/mcp/tools/graph.ts +35 -0
  109. package/dist/src/worker/src/mcp/tools/search.ts +32 -0
  110. package/dist/src/worker/src/mcp/tools/sessions.ts +24 -0
  111. package/dist/src/worker/src/mcp/tools/skills.ts +16 -0
  112. package/dist/src/worker/src/mcp/tools/team.ts +9 -0
  113. package/dist/src/worker/src/schema.ts +5 -1
  114. package/dist/src/worker/src/search-helpers.ts +70 -0
  115. package/dist/src/worker/wrangler.toml +9 -0
  116. package/dist/{stats-BISBIBXZ.js → stats-GEOQ2DFF.js} +9 -9
  117. package/dist/{stop-47BJ42EO.js → stop-7AKYBJJ2.js} +6 -6
  118. package/dist/{stop-failure-VU5BTLWX.js → stop-failure-NLE2EURG.js} +7 -7
  119. package/dist/{subagent-start-SPTKQRHU.js → subagent-start-LBNZF2TG.js} +7 -7
  120. package/dist/{subagent-stop-UU75BYLC.js → subagent-stop-B2Z5GYAB.js} +7 -7
  121. package/dist/{task-completed-MVDO7TZF.js → task-completed-PO5TETJ7.js} +7 -7
  122. package/dist/{team-7X64J4Y6.js → team-DPNP2RN7.js} +97 -14
  123. package/dist/team-DPNP2RN7.js.map +1 -0
  124. package/dist/ui/assets/{index-rpmSpJpm.js → index-CiI1fwas.js} +120 -120
  125. package/dist/ui/index.html +1 -1
  126. package/dist/{update-DA7VEXOS.js → update-WBWB5URU.js} +18 -9
  127. package/dist/update-WBWB5URU.js.map +1 -0
  128. package/dist/{user-prompt-submit-ADZ4NTVO.js → user-prompt-submit-IZJC3NV7.js} +30 -7
  129. package/dist/user-prompt-submit-IZJC3NV7.js.map +1 -0
  130. package/dist/{verify-QYSERHF7.js → verify-FNSP62I3.js} +5 -5
  131. package/dist/{version-A72TAL2J.js → version-QEVU66NT.js} +2 -2
  132. package/package.json +7 -7
  133. package/dist/chunk-25WHTV4N.js.map +0 -1
  134. package/dist/chunk-5ZISXCDC.js.map +0 -1
  135. package/dist/chunk-7DAH5GLC.js.map +0 -1
  136. package/dist/chunk-BZDZORVP.js.map +0 -1
  137. package/dist/chunk-CTF7TQMJ.js.map +0 -1
  138. package/dist/chunk-EBIYONNZ.js.map +0 -1
  139. package/dist/chunk-HPZ7YAMA.js.map +0 -1
  140. package/dist/chunk-IGBHLFV5.js.map +0 -1
  141. package/dist/chunk-RMJPQZGF.js.map +0 -1
  142. package/dist/chunk-UTLWSKDV.js.map +0 -1
  143. package/dist/chunk-ZSJPI5MS.js.map +0 -1
  144. package/dist/executor-NXKJU5KW.js.map +0 -1
  145. package/dist/main-YFVBIRRK.js.map +0 -1
  146. package/dist/session-start-PJLJDVJJ.js.map +0 -1
  147. package/dist/src/symbionts/templates/hook-guard.cjs +0 -19
  148. package/dist/team-7X64J4Y6.js.map +0 -1
  149. package/dist/update-DA7VEXOS.js.map +0 -1
  150. package/dist/user-prompt-submit-ADZ4NTVO.js.map +0 -1
  151. /package/dist/{agent-run-7AYHXIEF.js.map → agent-run-I4O2K2CK.js.map} +0 -0
  152. /package/dist/{agent-tasks-UUIFKBD4.js.map → agent-tasks-UOW5BQIB.js.map} +0 -0
  153. /package/dist/{chunk-XD3NEN3Q.js.map → chunk-2V7HR7HB.js.map} +0 -0
  154. /package/dist/{chunk-DT42247G.js.map → chunk-75AZFBFW.js.map} +0 -0
  155. /package/dist/{chunk-ML6GTPZU.js.map → chunk-CML4MCYF.js.map} +0 -0
  156. /package/dist/{chunk-NUSTG3BH.js.map → chunk-N75GMQGA.js.map} +0 -0
  157. /package/dist/{chunk-F6C4IC6R.js.map → chunk-NI23QCHB.js.map} +0 -0
  158. /package/dist/{chunk-C3C5QVLK.js.map → chunk-O3TRN3RC.js.map} +0 -0
  159. /package/dist/{chunk-3NCVCGUZ.js.map → chunk-RAV5YMRU.js.map} +0 -0
  160. /package/dist/{chunk-RKPTMHED.js.map → chunk-U3J2DDSR.js.map} +0 -0
  161. /package/dist/{chunk-SI5BBQAT.js.map → chunk-W7WENJ6F.js.map} +0 -0
  162. /package/dist/{chunk-XZWFMMJR.js.map → chunk-XWOQL4XN.js.map} +0 -0
  163. /package/dist/{cli-WJVYP2QT.js.map → cli-D3TJYJ2U.js.map} +0 -0
  164. /package/dist/{client-LZ3ZR4HC.js.map → client-4LLEXLVK.js.map} +0 -0
  165. /package/dist/{config-ZQIMG3FB.js.map → config-DA4IUVFL.js.map} +0 -0
  166. /package/dist/{detect-NJ2OREDP.js.map → detect-SZ2KDUF4.js.map} +0 -0
  167. /package/dist/{detect-providers-C64L3QET.js.map → detect-providers-PSVKXTWE.js.map} +0 -0
  168. /package/dist/{doctor-XEPBNHM3.js.map → doctor-KCTXPX5D.js.map} +0 -0
  169. /package/dist/{init-BHVQAQ27.js.map → init-QFNBKKDC.js.map} +0 -0
  170. /package/dist/{installer-45ZLP2RP.js.map → installer-BWJED3ED.js.map} +0 -0
  171. /package/dist/{llm-KTD6SR55.js.map → llm-SMA5ZEAW.js.map} +0 -0
  172. /package/dist/{loader-NEX3UF6U.js.map → loader-Q3P3R4UP.js.map} +0 -0
  173. /package/dist/{loader-SHRKUKOS.js.map → loader-SKKUMT5C.js.map} +0 -0
  174. /package/dist/{open-2U7ZRGA3.js.map → open-7737CSPN.js.map} +0 -0
  175. /package/dist/{post-compact-QIBMEWL3.js.map → post-compact-2TJ5FPZH.js.map} +0 -0
  176. /package/dist/{post-tool-use-ICGFXDVY.js.map → post-tool-use-FRTSICC3.js.map} +0 -0
  177. /package/dist/{post-tool-use-failure-C7TLH3XQ.js.map → post-tool-use-failure-KYO2NCNB.js.map} +0 -0
  178. /package/dist/{pre-compact-IF7K4TQK.js.map → pre-compact-J6GCJEJR.js.map} +0 -0
  179. /package/dist/{provider-check-LTLQ6BUZ.js.map → provider-check-AE3L5Z6R.js.map} +0 -0
  180. /package/dist/{registry-TFQ22Z7N.js.map → registry-O2NZLO3V.js.map} +0 -0
  181. /package/dist/{remove-FBGM2QVJ.js.map → remove-3WZZC7AX.js.map} +0 -0
  182. /package/dist/{resolution-events-HGKIJOTA.js.map → resolution-events-XWYLLDRK.js.map} +0 -0
  183. /package/dist/{restart-TQEECRNW.js.map → restart-HUHEFOXU.js.map} +0 -0
  184. /package/dist/{search-NN5FC4Z6.js.map → search-ZGN3LDXG.js.map} +0 -0
  185. /package/dist/{server-XMWJ4GF7.js.map → server-PTXLVVEE.js.map} +0 -0
  186. /package/dist/{session-GLPAFYPO.js.map → session-7VV3IQMO.js.map} +0 -0
  187. /package/dist/{session-end-TI3ILRBC.js.map → session-end-SMU55UCM.js.map} +0 -0
  188. /package/dist/{setup-llm-AQSWLXCZ.js.map → setup-llm-7S3VPAPN.js.map} +0 -0
  189. /package/dist/{stats-BISBIBXZ.js.map → stats-GEOQ2DFF.js.map} +0 -0
  190. /package/dist/{stop-47BJ42EO.js.map → stop-7AKYBJJ2.js.map} +0 -0
  191. /package/dist/{stop-failure-VU5BTLWX.js.map → stop-failure-NLE2EURG.js.map} +0 -0
  192. /package/dist/{subagent-start-SPTKQRHU.js.map → subagent-start-LBNZF2TG.js.map} +0 -0
  193. /package/dist/{subagent-stop-UU75BYLC.js.map → subagent-stop-B2Z5GYAB.js.map} +0 -0
  194. /package/dist/{task-completed-MVDO7TZF.js.map → task-completed-PO5TETJ7.js.map} +0 -0
  195. /package/dist/{verify-QYSERHF7.js.map → verify-FNSP62I3.js.map} +0 -0
  196. /package/dist/{version-A72TAL2J.js.map → version-QEVU66NT.js.map} +0 -0
@@ -13,5 +13,10 @@
13
13
  "@cloudflare/workers-types": "^4.20250320.0",
14
14
  "typescript": "^5.7.0",
15
15
  "wrangler": "^4.0.0"
16
+ },
17
+ "dependencies": {
18
+ "@modelcontextprotocol/sdk": "^1.29.0",
19
+ "agents": "^0.10.0",
20
+ "zod": "^4.3.6"
16
21
  }
17
22
  }
@@ -8,6 +8,10 @@
8
8
 
9
9
  import { initD1Schema } from './schema';
10
10
  import { validateAuth } from './auth';
11
+ import { createMcpHandler } from 'agents/mcp';
12
+ import { createMcpServerInstance } from './mcp/server';
13
+ import { authenticateMcpRequest, ensureMcpToken, rotateMcpToken, getMcpTokenHash, MCP_TOKEN_KEY } from './mcp/auth';
14
+ import { embedText, hydrateVectorMatches } from './search-helpers';
11
15
 
12
16
  // ---------------------------------------------------------------------------
13
17
  // Types
@@ -19,6 +23,7 @@ export interface Env {
19
23
  AI: Ai;
20
24
  MYCO_TEAM_API_KEY: string;
21
25
  SYNC_PROTOCOL_VERSION: string;
26
+ MYCO_SECRETS: KVNamespace;
22
27
  }
23
28
 
24
29
  /** Tables that support embedding in Vectorize. */
@@ -27,6 +32,7 @@ const EMBEDDABLE_TABLES: Record<string, string> = {
27
32
  sessions: 'summary',
28
33
  plans: 'content',
29
34
  artifacts: 'content',
35
+ skill_records: 'description',
30
36
  };
31
37
 
32
38
  /** All tables the sync endpoint accepts records for. */
@@ -112,13 +118,6 @@ function vectorId(table: string, id: string, machineId: string): string {
112
118
  return `${table}:${id}:${machineId}`;
113
119
  }
114
120
 
115
- /**
116
- * Embed text via Workers AI (bge-m3) and return the vector.
117
- */
118
- async function embedText(ai: Ai, text: string): Promise<number[]> {
119
- const result = await ai.run('@cf/baai/bge-m3', { text: [text] });
120
- return result.data[0];
121
- }
122
121
 
123
122
  /**
124
123
  * Build column names and placeholders for an INSERT OR REPLACE from a data object.
@@ -150,10 +149,15 @@ function buildInsertParts(
150
149
  // ---------------------------------------------------------------------------
151
150
 
152
151
  async function handleHealth(env: Env): Promise<Response> {
153
- const result = await env.MYCO_TEAM_DB.prepare('SELECT COUNT(*) as count FROM nodes').first<{
154
- count: number;
155
- }>();
156
- return jsonResponse({ status: 'ok', nodes: result?.count ?? 0 });
152
+ const [countResult, storedToken] = await Promise.all([
153
+ env.MYCO_TEAM_DB.prepare('SELECT COUNT(*) as count FROM nodes').first<{ count: number }>(),
154
+ env.MYCO_SECRETS.get(MCP_TOKEN_KEY),
155
+ ]);
156
+
157
+ const count = countResult?.count ?? 0;
158
+ const mcpTokenHash = storedToken ? getMcpTokenHash(storedToken) : null;
159
+
160
+ return jsonResponse({ status: 'ok', nodes: count, mcp_token_hash: mcpTokenHash });
157
161
  }
158
162
 
159
163
  async function handleConnect(request: Request, env: Env): Promise<Response> {
@@ -191,10 +195,15 @@ async function handleConnect(request: Request, env: Env): Promise<Response> {
191
195
  config[row.key] = row.value;
192
196
  }
193
197
 
198
+ // MCP token is stored in KV (encrypted at rest), not in team_config
199
+ const mcpToken = await ensureMcpToken(env.MYCO_SECRETS);
200
+
194
201
  return jsonResponse({
195
202
  status: 'connected',
196
203
  sync_protocol_version: parseInt(env.SYNC_PROTOCOL_VERSION, 10),
197
204
  config,
205
+ mcp_token: mcpToken,
206
+ mcp_endpoint: '/mcp',
198
207
  });
199
208
  }
200
209
 
@@ -261,7 +270,11 @@ async function handleSync(request: Request, env: Env): Promise<Response> {
261
270
  if (table === 'spores' && record.data.status === 'superseded') {
262
271
  embeddingTasks.push(() => deleteVector(env, table, id, machine_id));
263
272
  } else {
264
- embeddingTasks.push(() => embedAndUpsert(env, table, id, machine_id, textContent));
273
+ // Include domain-specific metadata for richer search results
274
+ const extra: Record<string, string> = {};
275
+ if (table === 'skill_records' && record.data.name) extra.name = record.data.name as string;
276
+ if (table === 'spores' && record.data.observation_type) extra.observation_type = record.data.observation_type as string;
277
+ embeddingTasks.push(() => embedAndUpsert(env, table, id, machine_id, textContent, extra));
265
278
  }
266
279
  }
267
280
  }
@@ -303,6 +316,7 @@ async function embedAndUpsert(
303
316
  id: string,
304
317
  machineId: string,
305
318
  text: string,
319
+ extra?: Record<string, string>,
306
320
  ): Promise<void> {
307
321
  const vector = await embedText(env.AI, text);
308
322
  const vid = vectorId(table, id, machineId);
@@ -310,7 +324,7 @@ async function embedAndUpsert(
310
324
  {
311
325
  id: vid,
312
326
  values: vector,
313
- metadata: { table, id, machine_id: machineId },
327
+ metadata: { table, id, machine_id: machineId, ...extra },
314
328
  },
315
329
  ]);
316
330
  }
@@ -333,61 +347,16 @@ async function handleSearch(request: Request, env: Env): Promise<Response> {
333
347
 
334
348
  const topK = Math.min(parseInt(url.searchParams.get('top_k') ?? String(DEFAULT_TOP_K), 10), MAX_TOP_K);
335
349
 
336
- // Embed query
337
350
  const queryVector = await embedText(env.AI, query);
351
+ const matches = await env.MYCO_TEAM_VECTORS.query(queryVector, { topK, returnMetadata: 'all' });
338
352
 
339
- // Search Vectorize
340
- const matches = await env.MYCO_TEAM_VECTORS.query(queryVector, {
341
- topK,
342
- returnMetadata: 'all',
343
- });
344
-
345
- // Group matches by table for batch hydration
346
- const byTable = new Map<string, { id: string; machine_id: string; score: number }[]>();
347
- for (const match of matches.matches) {
348
- const meta = match.metadata as { table: string; id: string; machine_id: string } | undefined;
349
- if (!meta) continue;
350
- let group = byTable.get(meta.table);
351
- if (!group) {
352
- group = [];
353
- byTable.set(meta.table, group);
354
- }
355
- group.push({ id: meta.id, machine_id: meta.machine_id, score: match.score });
356
- }
353
+ const validMatches = matches.matches
354
+ .filter((m) => m.metadata)
355
+ .map((m) => ({ metadata: m.metadata as { table: string; id: string; machine_id: string }, score: m.score }));
357
356
 
358
- // Batch-query each table and build results
359
- const results: SearchResult[] = [];
360
- for (const [table, items] of byTable) {
361
- const placeholders = items.map(() => '(?, ?)').join(', ');
362
- const binds = items.flatMap((i) => [i.id, i.machine_id]);
363
- const { results: rows } = await env.MYCO_TEAM_DB.prepare(
364
- `SELECT * FROM ${table} WHERE (id, machine_id) IN (VALUES ${placeholders})`,
365
- ).bind(...binds).all();
366
-
367
- const rowMap = new Map<string, Record<string, unknown>>();
368
- for (const row of rows) {
369
- const r = row as Record<string, unknown>;
370
- rowMap.set(`${r.id}:${r.machine_id}`, r);
371
- }
357
+ const results = await hydrateVectorMatches(env.MYCO_TEAM_DB, validMatches);
372
358
 
373
- for (const item of items) {
374
- const row = rowMap.get(`${item.id}:${item.machine_id}`);
375
- if (row) {
376
- results.push({
377
- table,
378
- id: item.id,
379
- machine_id: item.machine_id,
380
- score: item.score,
381
- data: row,
382
- });
383
- }
384
- }
385
- }
386
-
387
- // Sort by score to preserve ranking after batch hydration
388
- results.sort((a, b) => b.score - a.score);
389
-
390
- return jsonResponse({ results });
359
+ return jsonResponse({ results: results.map((r) => ({ table: r.type, ...r })) });
391
360
  }
392
361
 
393
362
  async function handleGetConfig(env: Env): Promise<Response> {
@@ -429,7 +398,7 @@ async function handlePutConfig(request: Request, env: Env): Promise<Response> {
429
398
  // ---------------------------------------------------------------------------
430
399
 
431
400
  export default {
432
- async fetch(request: Request, env: Env): Promise<Response> {
401
+ async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
433
402
  const url = new URL(request.url);
434
403
  const path = url.pathname;
435
404
  const method = request.method;
@@ -448,6 +417,30 @@ export default {
448
417
  }
449
418
  }
450
419
 
420
+ // MCP routes — separate auth from sync routes
421
+ if (path.startsWith('/mcp')) {
422
+ if (!schemaInitialized) {
423
+ await initD1Schema(env.MYCO_TEAM_DB);
424
+ schemaInitialized = true;
425
+ }
426
+
427
+ // Token rotation — authenticated with team API key
428
+ if (path === '/mcp/rotate' && method === 'POST') {
429
+ const rotateAuthError = validateAuth(request, env);
430
+ if (rotateAuthError) return rotateAuthError;
431
+ const newToken = await rotateMcpToken(env.MYCO_SECRETS);
432
+ return jsonResponse({ token: newToken });
433
+ }
434
+
435
+ // MCP protocol — authenticated with MCP access token
436
+ const mcpAuthError = await authenticateMcpRequest(request, env.MYCO_SECRETS);
437
+ if (mcpAuthError) return mcpAuthError;
438
+
439
+ const server = createMcpServerInstance(env);
440
+ const handler = createMcpHandler(server);
441
+ return handler(request, env, ctx);
442
+ }
443
+
451
444
  // All other routes require auth
452
445
  const authError = validateAuth(request, env);
453
446
  if (authError) return authError;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * MCP access token auth for the Myco cloud MCP server.
3
+ *
4
+ * Tokens are stored in Workers KV (MYCO_SECRETS namespace) under the key 'mcp_access_token'.
5
+ * KV provides AES-256-GCM encryption at rest — the Cloudflare-native approach for
6
+ * runtime-managed secrets. This is separate from the worker's MYCO_TEAM_API_KEY auth
7
+ * used for sync routes.
8
+ */
9
+
10
+ export const MCP_TOKEN_KEY = 'mcp_access_token';
11
+
12
+ export function generateMcpToken(): string {
13
+ return crypto.randomUUID();
14
+ }
15
+
16
+ export function getMcpTokenHash(token: string): string {
17
+ // Non-cryptographic hash for change detection, returns 8 hex chars
18
+ let hash = 0;
19
+ for (let i = 0; i < token.length; i++) {
20
+ hash = ((hash << 5) - hash + token.charCodeAt(i)) | 0;
21
+ }
22
+ return Math.abs(hash).toString(16).padStart(8, '0').slice(0, 8);
23
+ }
24
+
25
+ export async function validateMcpToken(kv: KVNamespace, token: string): Promise<boolean> {
26
+ const stored = await kv.get(MCP_TOKEN_KEY);
27
+ if (!stored) return false;
28
+ return stored === token;
29
+ }
30
+
31
+ export async function ensureMcpToken(kv: KVNamespace): Promise<string> {
32
+ const existing = await kv.get(MCP_TOKEN_KEY);
33
+ if (existing) return existing;
34
+ const token = generateMcpToken();
35
+ await kv.put(MCP_TOKEN_KEY, token);
36
+ return token;
37
+ }
38
+
39
+ export async function rotateMcpToken(kv: KVNamespace): Promise<string> {
40
+ const token = generateMcpToken();
41
+ await kv.put(MCP_TOKEN_KEY, token);
42
+ return token;
43
+ }
44
+
45
+ export async function authenticateMcpRequest(
46
+ request: Request,
47
+ kv: KVNamespace,
48
+ ): Promise<Response | null> {
49
+ const header = request.headers.get('Authorization');
50
+ if (!header) {
51
+ return new Response(JSON.stringify({ error: 'Missing Authorization header' }), {
52
+ status: 401,
53
+ headers: { 'Content-Type': 'application/json' },
54
+ });
55
+ }
56
+ const token = header.startsWith('Bearer ') ? header.slice(7) : '';
57
+ const valid = await validateMcpToken(kv, token);
58
+ if (!valid) {
59
+ return new Response(JSON.stringify({ error: 'Invalid MCP access token' }), {
60
+ status: 401,
61
+ headers: { 'Content-Type': 'application/json' },
62
+ });
63
+ }
64
+ return null;
65
+ }
@@ -0,0 +1,53 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { z } from 'zod';
3
+ import type { Env } from '../index';
4
+ import { handleSearch } from './tools/search';
5
+ import { handleContext } from './tools/context';
6
+ import { handleGet } from './tools/get';
7
+ import { handleSessions } from './tools/sessions';
8
+ import { handleGraph } from './tools/graph';
9
+ import { handleSkills } from './tools/skills';
10
+ import { handleTeam } from './tools/team';
11
+
12
+ export function createMcpServerInstance(env: Env): McpServer {
13
+ const server = new McpServer({ name: 'myco', version: '1.0.0' });
14
+
15
+ server.tool('myco_search', 'Semantic and keyword search across all project knowledge — spores, sessions, plans, artifacts. Returns ranked results with content previews.', {
16
+ query: z.string().describe('The search query'),
17
+ types: z.array(z.string()).optional().describe('Filter to content types: spores, sessions, plans, artifacts'),
18
+ limit: z.number().min(1).max(50).default(10).describe('Maximum results'),
19
+ }, async (args) => handleSearch(args, env));
20
+
21
+ server.tool('myco_context', 'Pre-synthesized project digest. Start here to understand the project. Three tiers: 1500 (executive), 5000 (deep onboarding), 10000 (comprehensive).', {
22
+ tier: z.number().optional().describe('Digest depth: 1500, 5000 (default), or 10000'),
23
+ }, async (args) => handleContext(args, env));
24
+
25
+ server.tool('myco_get', 'Retrieve a specific item by ID and type. Use after search to get full details.', {
26
+ id: z.string().describe('The item ID'),
27
+ type: z.enum(['session', 'spore', 'plan', 'artifact', 'skill']).describe('The item type'),
28
+ }, async (args) => handleGet(args, env));
29
+
30
+ server.tool('myco_sessions', 'List and filter coding sessions. Useful for recent activity, work by branch or agent.', {
31
+ limit: z.number().min(1).max(100).default(20).optional().describe('Maximum sessions'),
32
+ status: z.string().optional().describe('Filter: active, completed'),
33
+ agent: z.string().optional().describe('Filter: claude, codex, cursor, etc.'),
34
+ branch: z.string().optional().describe('Filter by git branch'),
35
+ since: z.string().optional().describe('ISO date — sessions after this date'),
36
+ }, async (args) => handleSessions(args, env));
37
+
38
+ server.tool('myco_graph', 'Traverse the knowledge graph from an entity or note. Returns edges and connected entities.', {
39
+ node_id: z.string().describe('Entity or note ID to traverse from'),
40
+ direction: z.enum(['incoming', 'outgoing', 'both']).default('both').optional().describe('Edge direction'),
41
+ }, async (args) => handleGraph(args, env));
42
+
43
+ server.tool('myco_skills', 'List project skills — reusable patterns extracted from project knowledge.', {
44
+ status: z.string().optional().describe('Filter: active, draft, retired'),
45
+ limit: z.number().min(1).max(100).default(50).optional().describe('Maximum skills'),
46
+ }, async (args) => handleSkills(args, env));
47
+
48
+ // handleTeam takes only env (no args) since it has no parameters
49
+ server.tool('myco_team', 'List team nodes — machines/developers connected to this project with sync status.', {},
50
+ async () => handleTeam(env));
51
+
52
+ return server;
53
+ }
@@ -0,0 +1,13 @@
1
+ import type { Env } from '../../index';
2
+
3
+ export async function handleContext(args: { tier?: number }, env: Pick<Env, 'MYCO_TEAM_DB'>) {
4
+ const tier = args.tier ?? 5000;
5
+ const row = await env.MYCO_TEAM_DB.prepare(
6
+ `SELECT id, tier, content, generated_at FROM digest_extracts WHERE tier = ? ORDER BY generated_at DESC LIMIT 1`,
7
+ ).bind(tier).first<{ id: string; tier: number; content: string; generated_at: number }>();
8
+
9
+ if (!row) {
10
+ return { content: [{ type: 'text' as const, text: JSON.stringify({ content: null, tier, message: `No digest available at tier ${tier}` }) }] };
11
+ }
12
+ return { content: [{ type: 'text' as const, text: JSON.stringify({ content: row.content, tier: row.tier, generated_at: row.generated_at }) }] };
13
+ }
@@ -0,0 +1,15 @@
1
+ import type { Env } from '../../index';
2
+
3
+ const TYPE_TO_TABLE: Record<string, string> = {
4
+ session: 'sessions', spore: 'spores', plan: 'plans', artifact: 'artifacts', skill: 'skill_records',
5
+ };
6
+
7
+ export async function handleGet(args: { id: string; type: string }, env: Pick<Env, 'MYCO_TEAM_DB'>) {
8
+ const table = TYPE_TO_TABLE[args.type];
9
+ if (!table) return { content: [{ type: 'text' as const, text: JSON.stringify({ error: `Unknown type: ${args.type}` }) }] };
10
+
11
+ const row = await env.MYCO_TEAM_DB.prepare(`SELECT * FROM ${table} WHERE id = ? LIMIT 1`).bind(args.id).first<Record<string, unknown>>();
12
+ if (!row) return { content: [{ type: 'text' as const, text: JSON.stringify({ error: `${args.type} '${args.id}' not found` }) }] };
13
+
14
+ return { content: [{ type: 'text' as const, text: JSON.stringify(row) }] };
15
+ }
@@ -0,0 +1,35 @@
1
+ import type { Env } from '../../index';
2
+
3
+ export async function handleGraph(
4
+ args: { node_id: string; direction?: string },
5
+ env: Pick<Env, 'MYCO_TEAM_DB'>,
6
+ ) {
7
+ const { node_id, direction = 'both' } = args;
8
+ let edgeCondition: string;
9
+ const edgeBinds: string[] = [];
10
+
11
+ if (direction === 'outgoing') { edgeCondition = 'source_id = ?'; edgeBinds.push(node_id); }
12
+ else if (direction === 'incoming') { edgeCondition = 'target_id = ?'; edgeBinds.push(node_id); }
13
+ else { edgeCondition = '(source_id = ? OR target_id = ?)'; edgeBinds.push(node_id, node_id); }
14
+
15
+ const { results: edges } = await env.MYCO_TEAM_DB.prepare(
16
+ `SELECT id, source_id, source_type, target_id, target_type, type, confidence, properties FROM graph_edges WHERE ${edgeCondition} LIMIT 100`,
17
+ ).bind(...edgeBinds).all();
18
+
19
+ const entityIds = new Set<string>();
20
+ for (const edge of edges as Array<Record<string, unknown>>) {
21
+ if (edge.source_type === 'entity') entityIds.add(edge.source_id as string);
22
+ if (edge.target_type === 'entity') entityIds.add(edge.target_id as string);
23
+ }
24
+
25
+ let entities: Record<string, unknown>[] = [];
26
+ if (entityIds.size > 0) {
27
+ const placeholders = [...entityIds].map(() => '?').join(', ');
28
+ const { results } = await env.MYCO_TEAM_DB.prepare(
29
+ `SELECT id, type, name, properties, first_seen, last_seen FROM entities WHERE id IN (${placeholders})`,
30
+ ).bind(...entityIds).all();
31
+ entities = results as Record<string, unknown>[];
32
+ }
33
+
34
+ return { content: [{ type: 'text' as const, text: JSON.stringify({ node_id, edges, entities }) }] };
35
+ }
@@ -0,0 +1,32 @@
1
+ import type { Env } from '../../index';
2
+ import { embedText, hydrateVectorMatches } from '../../search-helpers';
3
+
4
+ interface SearchArgs {
5
+ query: string;
6
+ types?: string[];
7
+ limit?: number;
8
+ }
9
+
10
+ export async function handleSearch(args: SearchArgs, env: Pick<Env, 'MYCO_TEAM_DB' | 'MYCO_TEAM_VECTORS' | 'AI'>) {
11
+ const { query, types, limit = 10 } = args;
12
+ const topK = Math.min(Math.max(limit, 1), 50);
13
+
14
+ const queryVector = await embedText(env.AI, query);
15
+ const matches = await env.MYCO_TEAM_VECTORS.query(queryVector, { topK, returnMetadata: 'all' });
16
+
17
+ // Filter by types if specified, then cast metadata
18
+ let filtered = matches.matches.filter((m) => m.metadata);
19
+ if (types && types.length > 0) {
20
+ const typeSet = new Set(types);
21
+ filtered = filtered.filter((m) => typeSet.has((m.metadata as { table: string }).table));
22
+ }
23
+
24
+ const validMatches = filtered.map((m) => ({
25
+ metadata: m.metadata as { table: string; id: string; machine_id: string },
26
+ score: m.score,
27
+ }));
28
+
29
+ const results = await hydrateVectorMatches(env.MYCO_TEAM_DB, validMatches);
30
+
31
+ return { content: [{ type: 'text' as const, text: JSON.stringify({ results: results.slice(0, topK) }) }] };
32
+ }
@@ -0,0 +1,24 @@
1
+ import type { Env } from '../../index';
2
+
3
+ export async function handleSessions(
4
+ args: { limit?: number; status?: string; agent?: string; branch?: string; since?: string },
5
+ env: Pick<Env, 'MYCO_TEAM_DB'>,
6
+ ) {
7
+ const { limit = 20, status, agent, branch, since } = args;
8
+ const conditions: string[] = [];
9
+ const binds: unknown[] = [];
10
+
11
+ if (status) { conditions.push('status = ?'); binds.push(status); }
12
+ if (agent) { conditions.push('agent = ?'); binds.push(agent); }
13
+ if (branch) { conditions.push('branch = ?'); binds.push(branch); }
14
+ if (since) { conditions.push('started_at >= ?'); binds.push(Math.floor(new Date(since).getTime() / 1000)); }
15
+
16
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
17
+ binds.push(Math.min(Math.max(limit, 1), 100));
18
+
19
+ const { results } = await env.MYCO_TEAM_DB.prepare(
20
+ `SELECT id, machine_id, agent, "user", branch, status, title, SUBSTR(summary, 1, 300) as summary, prompt_count, tool_count, started_at, ended_at FROM sessions ${where} ORDER BY started_at DESC LIMIT ?`,
21
+ ).bind(...binds).all();
22
+
23
+ return { content: [{ type: 'text' as const, text: JSON.stringify({ sessions: results }) }] };
24
+ }
@@ -0,0 +1,16 @@
1
+ import type { Env } from '../../index';
2
+
3
+ export async function handleSkills(args: { status?: string; limit?: number }, env: Pick<Env, 'MYCO_TEAM_DB'>) {
4
+ const { status, limit = 50 } = args;
5
+ const conditions: string[] = [];
6
+ const binds: unknown[] = [];
7
+ if (status) { conditions.push('status = ?'); binds.push(status); }
8
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
9
+ binds.push(Math.min(Math.max(limit, 1), 100));
10
+
11
+ const { results } = await env.MYCO_TEAM_DB.prepare(
12
+ `SELECT id, machine_id, name, display_name, description, status, generation, usage_count, last_used_at, created_at, updated_at FROM skill_records ${where} ORDER BY usage_count DESC, created_at DESC LIMIT ?`,
13
+ ).bind(...binds).all();
14
+
15
+ return { content: [{ type: 'text' as const, text: JSON.stringify({ skills: results }) }] };
16
+ }
@@ -0,0 +1,9 @@
1
+ import type { Env } from '../../index';
2
+
3
+ export async function handleTeam(env: Pick<Env, 'MYCO_TEAM_DB'>) {
4
+ const { results } = await env.MYCO_TEAM_DB.prepare(
5
+ `SELECT machine_id, package_version, schema_version, sync_protocol_version, last_seen, registered_at FROM nodes ORDER BY last_seen DESC`,
6
+ ).all();
7
+
8
+ return { content: [{ type: 'text' as const, text: JSON.stringify({ nodes: results }) }] };
9
+ }
@@ -8,7 +8,9 @@
8
8
  * Fully idempotent — safe to call on every request.
9
9
  */
10
10
 
11
- import { CANDIDATE_STATUS } from '@myco/constants/skill-candidate-status.js';
11
+ // Inline constants the worker is deployed independently and cannot
12
+ // import from the main @myco package at runtime.
13
+ const CANDIDATE_STATUS = { APPROVED: 'approved', GENERATED: 'generated' } as const;
12
14
 
13
15
  const SESSIONS_TABLE = `
14
16
  CREATE TABLE IF NOT EXISTS sessions (
@@ -196,6 +198,7 @@ const SKILL_CANDIDATES_TABLE = `
196
198
  status TEXT NOT NULL DEFAULT 'identified',
197
199
  source_ids TEXT NOT NULL DEFAULT '[]',
198
200
  skill_id TEXT,
201
+ supersedes TEXT,
199
202
  approved_at INTEGER,
200
203
  created_at INTEGER NOT NULL,
201
204
  updated_at INTEGER NOT NULL,
@@ -299,6 +302,7 @@ export async function initD1Schema(db: D1Database): Promise<void> {
299
302
  const migrations = [
300
303
  'ALTER TABLE skill_usage ADD COLUMN synced_at INTEGER',
301
304
  'ALTER TABLE skill_candidates ADD COLUMN approved_at INTEGER',
305
+ 'ALTER TABLE skill_candidates ADD COLUMN supersedes TEXT',
302
306
  ];
303
307
  for (const sql of migrations) {
304
308
  try {
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Shared search helpers used by both the REST /search endpoint and MCP myco_search tool.
3
+ */
4
+
5
+ /**
6
+ * Embed text via Workers AI (bge-m3) and return the vector.
7
+ */
8
+ export async function embedText(ai: Ai, text: string): Promise<number[]> {
9
+ const result = await ai.run('@cf/baai/bge-m3', { text: [text] }) as { data: number[][] };
10
+ return result.data[0];
11
+ }
12
+
13
+ export interface HydratedResult {
14
+ id: string;
15
+ machine_id: string;
16
+ type: string;
17
+ score: number;
18
+ data: Record<string, unknown>;
19
+ }
20
+
21
+ interface VectorMatch {
22
+ metadata: { table: string; id: string; machine_id: string };
23
+ score: number;
24
+ }
25
+
26
+ /**
27
+ * Group Vectorize matches by table and batch-hydrate each group from D1.
28
+ * Queries run in parallel across tables.
29
+ */
30
+ export async function hydrateVectorMatches(
31
+ db: D1Database,
32
+ matches: VectorMatch[],
33
+ ): Promise<HydratedResult[]> {
34
+ // Group by table
35
+ const groups = new Map<string, Array<{ id: string; machine_id: string; score: number }>>();
36
+ for (const match of matches) {
37
+ const { table, id, machine_id } = match.metadata;
38
+ const group = groups.get(table) ?? [];
39
+ group.push({ id, machine_id, score: match.score });
40
+ groups.set(table, group);
41
+ }
42
+
43
+ // Hydrate all tables in parallel
44
+ const hydrationPromises = [...groups.entries()].map(async ([table, items]) => {
45
+ const placeholders = items.map(() => '(?, ?)').join(', ');
46
+ const binds = items.flatMap((item) => [item.id, item.machine_id]);
47
+ const { results: rows } = await db.prepare(
48
+ `SELECT * FROM ${table} WHERE (id, machine_id) IN (VALUES ${placeholders})`,
49
+ ).bind(...binds).all();
50
+
51
+ const rowMap = new Map<string, Record<string, unknown>>();
52
+ for (const row of rows as Record<string, unknown>[]) {
53
+ rowMap.set(`${row.id}:${row.machine_id}`, row);
54
+ }
55
+
56
+ const results: HydratedResult[] = [];
57
+ for (const item of items) {
58
+ const row = rowMap.get(`${item.id}:${item.machine_id}`);
59
+ if (row) {
60
+ results.push({ id: item.id, machine_id: item.machine_id, type: table, score: item.score, data: row });
61
+ }
62
+ }
63
+ return results;
64
+ });
65
+
66
+ const resultArrays = await Promise.all(hydrationPromises);
67
+ const results = resultArrays.flat();
68
+ results.sort((a, b) => b.score - a.score);
69
+ return results;
70
+ }
@@ -1,6 +1,10 @@
1
1
  name = "myco-team-sync"
2
2
  main = "src/index.ts"
3
3
  compatibility_date = "2025-03-27"
4
+ # nodejs_compat is required by the agents SDK and @modelcontextprotocol/sdk,
5
+ # which depend on packages that import Node.js built-ins (node:async_hooks,
6
+ # node:diagnostics_channel, node:os, etc.).
7
+ compatibility_flags = [ "nodejs_compat" ]
4
8
 
5
9
  [vars]
6
10
  SYNC_PROTOCOL_VERSION = "1"
@@ -16,6 +20,11 @@ database_id = "<YOUR_D1_DATABASE_ID>"
16
20
  binding = "MYCO_TEAM_VECTORS"
17
21
  index_name = "myco-team-vectors"
18
22
 
23
+ # KV namespace for runtime secrets (MCP tokens, etc.)
24
+ [[kv_namespaces]]
25
+ binding = "MYCO_SECRETS"
26
+ id = "<YOUR_KV_NAMESPACE_ID>"
27
+
19
28
  # Workers AI binding
20
29
  [ai]
21
30
  binding = "AI"
@@ -1,19 +1,19 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  gatherStats
4
- } from "./chunk-BZDZORVP.js";
4
+ } from "./chunk-LSP5HYOO.js";
5
5
  import {
6
6
  initVaultDb
7
- } from "./chunk-CTF7TQMJ.js";
7
+ } from "./chunk-TLK46KKD.js";
8
8
  import "./chunk-SAKJMNSR.js";
9
- import "./chunk-VVGZL2HX.js";
10
- import "./chunk-ML6GTPZU.js";
11
- import "./chunk-XD3NEN3Q.js";
9
+ import "./chunk-WYOE4IAX.js";
10
+ import "./chunk-CML4MCYF.js";
11
+ import "./chunk-2V7HR7HB.js";
12
12
  import "./chunk-MYX5NCRH.js";
13
- import "./chunk-XZWFMMJR.js";
14
- import "./chunk-SI5BBQAT.js";
13
+ import "./chunk-XWOQL4XN.js";
14
+ import "./chunk-W7WENJ6F.js";
15
15
  import "./chunk-LPUQPDC2.js";
16
- import "./chunk-7DAH5GLC.js";
16
+ import "./chunk-CKJAWZQE.js";
17
17
  import "./chunk-E7NUADTQ.js";
18
18
  import "./chunk-D7TYRPRM.js";
19
19
  import "./chunk-E4VLWIJC.js";
@@ -92,4 +92,4 @@ function formatUptime(seconds) {
92
92
  export {
93
93
  run
94
94
  };
95
- //# sourceMappingURL=stats-BISBIBXZ.js.map
95
+ //# sourceMappingURL=stats-GEOQ2DFF.js.map