@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.
- package/README.md +14 -22
- package/bin/myco-run +15 -2
- package/dist/{agent-run-7AYHXIEF.js → agent-run-I4O2K2CK.js} +7 -7
- package/dist/{agent-tasks-UUIFKBD4.js → agent-tasks-UOW5BQIB.js} +7 -7
- package/dist/{chunk-XD3NEN3Q.js → chunk-2V7HR7HB.js} +2 -2
- package/dist/chunk-44PZCAYS.js +107 -0
- package/dist/chunk-44PZCAYS.js.map +1 -0
- package/dist/{chunk-DT42247G.js → chunk-75AZFBFW.js} +3 -3
- package/dist/{chunk-RMJPQZGF.js → chunk-C3EGL5JX.js} +755 -266
- package/dist/chunk-C3EGL5JX.js.map +1 -0
- package/dist/{chunk-7DAH5GLC.js → chunk-CKJAWZQE.js} +5 -1
- package/dist/chunk-CKJAWZQE.js.map +1 -0
- package/dist/{chunk-ML6GTPZU.js → chunk-CML4MCYF.js} +2 -2
- package/dist/{chunk-UTLWSKDV.js → chunk-CURS2TNP.js} +45 -4
- package/dist/chunk-CURS2TNP.js.map +1 -0
- package/dist/{chunk-EBIYONNZ.js → chunk-DPSLJ242.js} +34 -2
- package/dist/chunk-DPSLJ242.js.map +1 -0
- package/dist/{chunk-BZDZORVP.js → chunk-LSP5HYOO.js} +19 -16
- package/dist/chunk-LSP5HYOO.js.map +1 -0
- package/dist/{chunk-NUSTG3BH.js → chunk-N75GMQGA.js} +3 -3
- package/dist/{chunk-F6C4IC6R.js → chunk-NI23QCHB.js} +3 -3
- package/dist/{chunk-C3C5QVLK.js → chunk-O3TRN3RC.js} +2 -2
- package/dist/{chunk-3NCVCGUZ.js → chunk-RAV5YMRU.js} +3 -3
- package/dist/{chunk-25WHTV4N.js → chunk-RIDSOQDR.js} +21 -7
- package/dist/chunk-RIDSOQDR.js.map +1 -0
- package/dist/{chunk-HPZ7YAMA.js → chunk-TCSVDQF5.js} +1130 -195
- package/dist/chunk-TCSVDQF5.js.map +1 -0
- package/dist/{chunk-CTF7TQMJ.js → chunk-TLK46KKD.js} +14 -4
- package/dist/chunk-TLK46KKD.js.map +1 -0
- package/dist/{chunk-IGBHLFV5.js → chunk-TOER6RNC.js} +22 -2
- package/dist/chunk-TOER6RNC.js.map +1 -0
- package/dist/{chunk-ZSJPI5MS.js → chunk-TZAXQKO6.js} +6 -2
- package/dist/chunk-TZAXQKO6.js.map +1 -0
- package/dist/{chunk-RKPTMHED.js → chunk-U3J2DDSR.js} +2 -2
- package/dist/{chunk-SI5BBQAT.js → chunk-W7WENJ6F.js} +2 -2
- package/dist/{chunk-VVGZL2HX.js → chunk-WYOE4IAX.js} +153 -15
- package/dist/{chunk-VVGZL2HX.js.map → chunk-WYOE4IAX.js.map} +1 -1
- package/dist/{chunk-XZWFMMJR.js → chunk-XWOQL4XN.js} +3 -3
- package/dist/{chunk-5ZISXCDC.js → chunk-YZPI2Y3E.js} +39 -5
- package/dist/chunk-YZPI2Y3E.js.map +1 -0
- package/dist/{cli-WJVYP2QT.js → cli-D3TJYJ2U.js} +40 -40
- package/dist/{client-LZ3ZR4HC.js → client-4LLEXLVK.js} +4 -4
- package/dist/{config-ZQIMG3FB.js → config-DA4IUVFL.js} +3 -3
- package/dist/{detect-NJ2OREDP.js → detect-SZ2KDUF4.js} +2 -2
- package/dist/{detect-providers-C64L3QET.js → detect-providers-PSVKXTWE.js} +4 -4
- package/dist/{doctor-XEPBNHM3.js → doctor-KCTXPX5D.js} +12 -12
- package/dist/{executor-NXKJU5KW.js → executor-UYIZC3L5.js} +93 -285
- package/dist/executor-UYIZC3L5.js.map +1 -0
- package/dist/{init-BHVQAQ27.js → init-QFNBKKDC.js} +13 -13
- package/dist/{installer-45ZLP2RP.js → installer-BWJED3ED.js} +2 -2
- package/dist/{llm-KTD6SR55.js → llm-SMA5ZEAW.js} +4 -4
- package/dist/{loader-SHRKUKOS.js → loader-Q3P3R4UP.js} +3 -3
- package/dist/{loader-NEX3UF6U.js → loader-SKKUMT5C.js} +3 -3
- package/dist/{main-YFVBIRRK.js → main-5THODR77.js} +751 -257
- package/dist/main-5THODR77.js.map +1 -0
- package/dist/{open-2U7ZRGA3.js → open-7737CSPN.js} +7 -7
- package/dist/{post-compact-QIBMEWL3.js → post-compact-2TJ5FPZH.js} +7 -7
- package/dist/{post-tool-use-ICGFXDVY.js → post-tool-use-FRTSICC3.js} +6 -6
- package/dist/{post-tool-use-failure-C7TLH3XQ.js → post-tool-use-failure-KYO2NCNB.js} +7 -7
- package/dist/{pre-compact-IF7K4TQK.js → pre-compact-J6GCJEJR.js} +7 -7
- package/dist/{provider-check-LTLQ6BUZ.js → provider-check-AE3L5Z6R.js} +4 -4
- package/dist/{registry-TFQ22Z7N.js → registry-O2NZLO3V.js} +4 -4
- package/dist/{remove-FBGM2QVJ.js → remove-3WZZC7AX.js} +9 -9
- package/dist/{resolution-events-HGKIJOTA.js → resolution-events-XWYLLDRK.js} +4 -4
- package/dist/{restart-TQEECRNW.js → restart-HUHEFOXU.js} +8 -8
- package/dist/{search-NN5FC4Z6.js → search-ZGN3LDXG.js} +8 -8
- package/dist/{server-XMWJ4GF7.js → server-PTXLVVEE.js} +4 -4
- package/dist/{session-GLPAFYPO.js → session-7VV3IQMO.js} +9 -9
- package/dist/{session-end-TI3ILRBC.js → session-end-SMU55UCM.js} +6 -6
- package/dist/{session-start-PJLJDVJJ.js → session-start-NIMWEOIZ.js} +29 -13
- package/dist/session-start-NIMWEOIZ.js.map +1 -0
- package/dist/{setup-llm-AQSWLXCZ.js → setup-llm-7S3VPAPN.js} +8 -8
- package/dist/src/agent/definitions/tasks/extract-only.yaml +1 -1
- package/dist/src/agent/definitions/tasks/full-intelligence.yaml +10 -0
- package/dist/src/agent/definitions/tasks/skill-evolve.yaml +163 -49
- package/dist/src/agent/definitions/tasks/skill-generate.yaml +44 -27
- package/dist/src/agent/definitions/tasks/skill-survey.yaml +132 -138
- package/dist/src/agent/definitions/tasks/supersession-sweep.yaml +1 -1
- package/dist/src/cli.js +1 -1
- package/dist/src/daemon/main.js +1 -1
- package/dist/src/hooks/post-tool-use.js +1 -1
- package/dist/src/hooks/session-end.js +1 -1
- package/dist/src/hooks/session-start.js +1 -1
- package/dist/src/hooks/stop.js +1 -1
- package/dist/src/hooks/user-prompt-submit.js +1 -1
- package/dist/src/mcp/server.js +1 -1
- package/dist/src/symbionts/manifests/codex.yaml +85 -0
- package/dist/src/symbionts/templates/claude-code/hooks.json +12 -12
- package/dist/src/symbionts/templates/claude-code/settings.json +3 -3
- package/dist/src/symbionts/templates/codex/hooks.json +4 -4
- package/dist/src/symbionts/templates/cursor/hooks.json +9 -9
- package/dist/src/symbionts/templates/cursor/settings.json +2 -2
- package/dist/src/symbionts/templates/gemini/hooks.json +6 -6
- package/dist/src/symbionts/templates/gemini/settings.json +2 -2
- package/dist/src/symbionts/templates/myco-run.cjs +44 -0
- package/dist/src/symbionts/templates/opencode/settings.json +2 -2
- package/dist/src/symbionts/templates/vscode-copilot/hooks.json +7 -7
- package/dist/src/symbionts/templates/vscode-copilot/settings.json +2 -2
- package/dist/src/symbionts/templates/windsurf/hooks.json +4 -4
- package/dist/src/symbionts/templates/windsurf/settings.json +2 -2
- package/dist/src/worker/package-lock.json +4338 -0
- package/dist/src/worker/package.json +5 -0
- package/dist/src/worker/src/index.ts +58 -65
- package/dist/src/worker/src/mcp/auth.ts +65 -0
- package/dist/src/worker/src/mcp/server.ts +53 -0
- package/dist/src/worker/src/mcp/tools/context.ts +13 -0
- package/dist/src/worker/src/mcp/tools/get.ts +15 -0
- package/dist/src/worker/src/mcp/tools/graph.ts +35 -0
- package/dist/src/worker/src/mcp/tools/search.ts +32 -0
- package/dist/src/worker/src/mcp/tools/sessions.ts +24 -0
- package/dist/src/worker/src/mcp/tools/skills.ts +16 -0
- package/dist/src/worker/src/mcp/tools/team.ts +9 -0
- package/dist/src/worker/src/schema.ts +5 -1
- package/dist/src/worker/src/search-helpers.ts +70 -0
- package/dist/src/worker/wrangler.toml +9 -0
- package/dist/{stats-BISBIBXZ.js → stats-GEOQ2DFF.js} +9 -9
- package/dist/{stop-47BJ42EO.js → stop-7AKYBJJ2.js} +6 -6
- package/dist/{stop-failure-VU5BTLWX.js → stop-failure-NLE2EURG.js} +7 -7
- package/dist/{subagent-start-SPTKQRHU.js → subagent-start-LBNZF2TG.js} +7 -7
- package/dist/{subagent-stop-UU75BYLC.js → subagent-stop-B2Z5GYAB.js} +7 -7
- package/dist/{task-completed-MVDO7TZF.js → task-completed-PO5TETJ7.js} +7 -7
- package/dist/{team-7X64J4Y6.js → team-DPNP2RN7.js} +97 -14
- package/dist/team-DPNP2RN7.js.map +1 -0
- package/dist/ui/assets/{index-rpmSpJpm.js → index-CiI1fwas.js} +120 -120
- package/dist/ui/index.html +1 -1
- package/dist/{update-DA7VEXOS.js → update-WBWB5URU.js} +18 -9
- package/dist/update-WBWB5URU.js.map +1 -0
- package/dist/{user-prompt-submit-ADZ4NTVO.js → user-prompt-submit-IZJC3NV7.js} +30 -7
- package/dist/user-prompt-submit-IZJC3NV7.js.map +1 -0
- package/dist/{verify-QYSERHF7.js → verify-FNSP62I3.js} +5 -5
- package/dist/{version-A72TAL2J.js → version-QEVU66NT.js} +2 -2
- package/package.json +7 -7
- package/dist/chunk-25WHTV4N.js.map +0 -1
- package/dist/chunk-5ZISXCDC.js.map +0 -1
- package/dist/chunk-7DAH5GLC.js.map +0 -1
- package/dist/chunk-BZDZORVP.js.map +0 -1
- package/dist/chunk-CTF7TQMJ.js.map +0 -1
- package/dist/chunk-EBIYONNZ.js.map +0 -1
- package/dist/chunk-HPZ7YAMA.js.map +0 -1
- package/dist/chunk-IGBHLFV5.js.map +0 -1
- package/dist/chunk-RMJPQZGF.js.map +0 -1
- package/dist/chunk-UTLWSKDV.js.map +0 -1
- package/dist/chunk-ZSJPI5MS.js.map +0 -1
- package/dist/executor-NXKJU5KW.js.map +0 -1
- package/dist/main-YFVBIRRK.js.map +0 -1
- package/dist/session-start-PJLJDVJJ.js.map +0 -1
- package/dist/src/symbionts/templates/hook-guard.cjs +0 -19
- package/dist/team-7X64J4Y6.js.map +0 -1
- package/dist/update-DA7VEXOS.js.map +0 -1
- package/dist/user-prompt-submit-ADZ4NTVO.js.map +0 -1
- /package/dist/{agent-run-7AYHXIEF.js.map → agent-run-I4O2K2CK.js.map} +0 -0
- /package/dist/{agent-tasks-UUIFKBD4.js.map → agent-tasks-UOW5BQIB.js.map} +0 -0
- /package/dist/{chunk-XD3NEN3Q.js.map → chunk-2V7HR7HB.js.map} +0 -0
- /package/dist/{chunk-DT42247G.js.map → chunk-75AZFBFW.js.map} +0 -0
- /package/dist/{chunk-ML6GTPZU.js.map → chunk-CML4MCYF.js.map} +0 -0
- /package/dist/{chunk-NUSTG3BH.js.map → chunk-N75GMQGA.js.map} +0 -0
- /package/dist/{chunk-F6C4IC6R.js.map → chunk-NI23QCHB.js.map} +0 -0
- /package/dist/{chunk-C3C5QVLK.js.map → chunk-O3TRN3RC.js.map} +0 -0
- /package/dist/{chunk-3NCVCGUZ.js.map → chunk-RAV5YMRU.js.map} +0 -0
- /package/dist/{chunk-RKPTMHED.js.map → chunk-U3J2DDSR.js.map} +0 -0
- /package/dist/{chunk-SI5BBQAT.js.map → chunk-W7WENJ6F.js.map} +0 -0
- /package/dist/{chunk-XZWFMMJR.js.map → chunk-XWOQL4XN.js.map} +0 -0
- /package/dist/{cli-WJVYP2QT.js.map → cli-D3TJYJ2U.js.map} +0 -0
- /package/dist/{client-LZ3ZR4HC.js.map → client-4LLEXLVK.js.map} +0 -0
- /package/dist/{config-ZQIMG3FB.js.map → config-DA4IUVFL.js.map} +0 -0
- /package/dist/{detect-NJ2OREDP.js.map → detect-SZ2KDUF4.js.map} +0 -0
- /package/dist/{detect-providers-C64L3QET.js.map → detect-providers-PSVKXTWE.js.map} +0 -0
- /package/dist/{doctor-XEPBNHM3.js.map → doctor-KCTXPX5D.js.map} +0 -0
- /package/dist/{init-BHVQAQ27.js.map → init-QFNBKKDC.js.map} +0 -0
- /package/dist/{installer-45ZLP2RP.js.map → installer-BWJED3ED.js.map} +0 -0
- /package/dist/{llm-KTD6SR55.js.map → llm-SMA5ZEAW.js.map} +0 -0
- /package/dist/{loader-NEX3UF6U.js.map → loader-Q3P3R4UP.js.map} +0 -0
- /package/dist/{loader-SHRKUKOS.js.map → loader-SKKUMT5C.js.map} +0 -0
- /package/dist/{open-2U7ZRGA3.js.map → open-7737CSPN.js.map} +0 -0
- /package/dist/{post-compact-QIBMEWL3.js.map → post-compact-2TJ5FPZH.js.map} +0 -0
- /package/dist/{post-tool-use-ICGFXDVY.js.map → post-tool-use-FRTSICC3.js.map} +0 -0
- /package/dist/{post-tool-use-failure-C7TLH3XQ.js.map → post-tool-use-failure-KYO2NCNB.js.map} +0 -0
- /package/dist/{pre-compact-IF7K4TQK.js.map → pre-compact-J6GCJEJR.js.map} +0 -0
- /package/dist/{provider-check-LTLQ6BUZ.js.map → provider-check-AE3L5Z6R.js.map} +0 -0
- /package/dist/{registry-TFQ22Z7N.js.map → registry-O2NZLO3V.js.map} +0 -0
- /package/dist/{remove-FBGM2QVJ.js.map → remove-3WZZC7AX.js.map} +0 -0
- /package/dist/{resolution-events-HGKIJOTA.js.map → resolution-events-XWYLLDRK.js.map} +0 -0
- /package/dist/{restart-TQEECRNW.js.map → restart-HUHEFOXU.js.map} +0 -0
- /package/dist/{search-NN5FC4Z6.js.map → search-ZGN3LDXG.js.map} +0 -0
- /package/dist/{server-XMWJ4GF7.js.map → server-PTXLVVEE.js.map} +0 -0
- /package/dist/{session-GLPAFYPO.js.map → session-7VV3IQMO.js.map} +0 -0
- /package/dist/{session-end-TI3ILRBC.js.map → session-end-SMU55UCM.js.map} +0 -0
- /package/dist/{setup-llm-AQSWLXCZ.js.map → setup-llm-7S3VPAPN.js.map} +0 -0
- /package/dist/{stats-BISBIBXZ.js.map → stats-GEOQ2DFF.js.map} +0 -0
- /package/dist/{stop-47BJ42EO.js.map → stop-7AKYBJJ2.js.map} +0 -0
- /package/dist/{stop-failure-VU5BTLWX.js.map → stop-failure-NLE2EURG.js.map} +0 -0
- /package/dist/{subagent-start-SPTKQRHU.js.map → subagent-start-LBNZF2TG.js.map} +0 -0
- /package/dist/{subagent-stop-UU75BYLC.js.map → subagent-stop-B2Z5GYAB.js.map} +0 -0
- /package/dist/{task-completed-MVDO7TZF.js.map → task-completed-PO5TETJ7.js.map} +0 -0
- /package/dist/{verify-QYSERHF7.js.map → verify-FNSP62I3.js.map} +0 -0
- /package/dist/{version-A72TAL2J.js.map → version-QEVU66NT.js.map} +0 -0
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
getEmbeddingQueueDepth,
|
|
16
16
|
getUnembedded,
|
|
17
17
|
markEmbedded
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-LSP5HYOO.js";
|
|
19
19
|
import {
|
|
20
20
|
loadSecrets,
|
|
21
21
|
readSecrets,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
import {
|
|
25
25
|
Anthropic,
|
|
26
26
|
createEmbeddingProvider
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-TCSVDQF5.js";
|
|
28
28
|
import {
|
|
29
29
|
buildTaskInstruction,
|
|
30
30
|
closeOpenBatches,
|
|
@@ -72,24 +72,24 @@ import {
|
|
|
72
72
|
setResponseSummary,
|
|
73
73
|
updateCandidate,
|
|
74
74
|
updateNotificationStatus
|
|
75
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-C3EGL5JX.js";
|
|
76
76
|
import {
|
|
77
77
|
fullTextSearch,
|
|
78
78
|
hydrateSearchResults
|
|
79
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-TOER6RNC.js";
|
|
80
80
|
import {
|
|
81
81
|
copyTaskToUser,
|
|
82
82
|
deleteUserTask,
|
|
83
83
|
loadAllTasks,
|
|
84
84
|
validateTaskName,
|
|
85
85
|
writeUserTask
|
|
86
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-RAV5YMRU.js";
|
|
87
87
|
import {
|
|
88
88
|
AgentTaskSchema,
|
|
89
89
|
registerAgent,
|
|
90
90
|
resolveDefinitionsDir,
|
|
91
91
|
taskFromParsed
|
|
92
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-NI23QCHB.js";
|
|
93
93
|
import {
|
|
94
94
|
listTurnsByRun
|
|
95
95
|
} from "./chunk-QLCD77AN.js";
|
|
@@ -106,23 +106,23 @@ import {
|
|
|
106
106
|
listBufferSessionIds
|
|
107
107
|
} from "./chunk-V7XG6V6C.js";
|
|
108
108
|
import "./chunk-IB76KGBY.js";
|
|
109
|
-
import "./chunk-
|
|
109
|
+
import "./chunk-TLK46KKD.js";
|
|
110
110
|
import "./chunk-SAKJMNSR.js";
|
|
111
|
-
import "./chunk-
|
|
111
|
+
import "./chunk-WYOE4IAX.js";
|
|
112
112
|
import {
|
|
113
113
|
checkLocalProvider
|
|
114
|
-
} from "./chunk-
|
|
114
|
+
} from "./chunk-75AZFBFW.js";
|
|
115
115
|
import {
|
|
116
116
|
LmStudioBackend,
|
|
117
117
|
OllamaBackend
|
|
118
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-CML4MCYF.js";
|
|
119
119
|
import {
|
|
120
120
|
countSpores,
|
|
121
121
|
getSpore,
|
|
122
122
|
insertSpore,
|
|
123
123
|
listSpores,
|
|
124
124
|
updateSporeStatus
|
|
125
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-TZAXQKO6.js";
|
|
126
126
|
import {
|
|
127
127
|
closeSession,
|
|
128
128
|
countSessions,
|
|
@@ -133,7 +133,7 @@ import {
|
|
|
133
133
|
listSessions,
|
|
134
134
|
updateSession,
|
|
135
135
|
upsertSession
|
|
136
|
-
} from "./chunk-
|
|
136
|
+
} from "./chunk-RIDSOQDR.js";
|
|
137
137
|
import {
|
|
138
138
|
backfillUnsynced,
|
|
139
139
|
countDeadLettered,
|
|
@@ -149,13 +149,13 @@ import {
|
|
|
149
149
|
pruneOld,
|
|
150
150
|
retryDeadLettered,
|
|
151
151
|
syncRow
|
|
152
|
-
} from "./chunk-
|
|
152
|
+
} from "./chunk-O3TRN3RC.js";
|
|
153
153
|
import {
|
|
154
154
|
EMBEDDING_DIMENSIONS,
|
|
155
155
|
REST_SETTABLE_STATUSES,
|
|
156
156
|
SCHEMA_VERSION,
|
|
157
157
|
createSchema
|
|
158
|
-
} from "./chunk-
|
|
158
|
+
} from "./chunk-CURS2TNP.js";
|
|
159
159
|
import {
|
|
160
160
|
CONFIG_FILENAME,
|
|
161
161
|
MycoConfigSchema,
|
|
@@ -164,7 +164,7 @@ import {
|
|
|
164
164
|
updateBackupConfig,
|
|
165
165
|
updateConfig,
|
|
166
166
|
updateTeamConfig
|
|
167
|
-
} from "./chunk-
|
|
167
|
+
} from "./chunk-2V7HR7HB.js";
|
|
168
168
|
import {
|
|
169
169
|
closeDatabase,
|
|
170
170
|
getDatabase,
|
|
@@ -173,13 +173,13 @@ import {
|
|
|
173
173
|
} from "./chunk-MYX5NCRH.js";
|
|
174
174
|
import {
|
|
175
175
|
resolveCliEntryPath
|
|
176
|
-
} from "./chunk-
|
|
176
|
+
} from "./chunk-XWOQL4XN.js";
|
|
177
177
|
import {
|
|
178
178
|
getPluginVersion
|
|
179
|
-
} from "./chunk-
|
|
179
|
+
} from "./chunk-W7WENJ6F.js";
|
|
180
180
|
import {
|
|
181
181
|
loadManifests
|
|
182
|
-
} from "./chunk-
|
|
182
|
+
} from "./chunk-DPSLJ242.js";
|
|
183
183
|
import {
|
|
184
184
|
findPackageRoot
|
|
185
185
|
} from "./chunk-LPUQPDC2.js";
|
|
@@ -213,6 +213,7 @@ import {
|
|
|
213
213
|
PROMPT_PREVIEW_CHARS,
|
|
214
214
|
PROMPT_VECTOR_OVER_FETCH,
|
|
215
215
|
RELEASE_CHANNELS,
|
|
216
|
+
RESTART_REASON_FILENAME,
|
|
216
217
|
RESTART_RESPONSE_FLUSH_MS,
|
|
217
218
|
SEARCH_RESULTS_DEFAULT_LIMIT,
|
|
218
219
|
SEARCH_SIMILARITY_THRESHOLD,
|
|
@@ -228,12 +229,13 @@ import {
|
|
|
228
229
|
UPDATE_CONFIG_PATH,
|
|
229
230
|
UPDATE_ERROR_PATH,
|
|
230
231
|
UPDATE_SCRIPT_DELAY_SECONDS,
|
|
232
|
+
UPDATE_STAMP_FILENAME,
|
|
231
233
|
USER_AGENT_ID,
|
|
232
234
|
USER_AGENT_NAME,
|
|
233
235
|
USER_TASK_SOURCE,
|
|
234
236
|
epochSeconds,
|
|
235
237
|
estimateTokens
|
|
236
|
-
} from "./chunk-
|
|
238
|
+
} from "./chunk-CKJAWZQE.js";
|
|
237
239
|
import {
|
|
238
240
|
LOG_KINDS,
|
|
239
241
|
kindToComponent
|
|
@@ -370,7 +372,7 @@ var DaemonServer = class {
|
|
|
370
372
|
this.router.add(method, routePath, handler);
|
|
371
373
|
}
|
|
372
374
|
async start(port = 0) {
|
|
373
|
-
return new Promise((
|
|
375
|
+
return new Promise((resolve3, reject) => {
|
|
374
376
|
this.server = http.createServer((req, res) => this.handleRequest(req, res));
|
|
375
377
|
this.server.on("error", reject);
|
|
376
378
|
this.server.listen(port, "127.0.0.1", () => {
|
|
@@ -378,20 +380,20 @@ var DaemonServer = class {
|
|
|
378
380
|
this.port = addr.port;
|
|
379
381
|
this.writeDaemonJson();
|
|
380
382
|
this.logger.info(LOG_KINDS.DAEMON_PORT, "Server started", { port: this.port, dashboard: `http://localhost:${this.port}/` });
|
|
381
|
-
|
|
383
|
+
resolve3();
|
|
382
384
|
});
|
|
383
385
|
});
|
|
384
386
|
}
|
|
385
387
|
async stop() {
|
|
386
|
-
return new Promise((
|
|
388
|
+
return new Promise((resolve3) => {
|
|
387
389
|
this.removeDaemonJson();
|
|
388
390
|
if (this.server) {
|
|
389
391
|
this.server.close(() => {
|
|
390
392
|
this.logger.info(LOG_KINDS.DAEMON_START, "Server stopped");
|
|
391
|
-
|
|
393
|
+
resolve3();
|
|
392
394
|
});
|
|
393
395
|
} else {
|
|
394
|
-
|
|
396
|
+
resolve3();
|
|
395
397
|
}
|
|
396
398
|
});
|
|
397
399
|
}
|
|
@@ -539,14 +541,14 @@ var DaemonServer = class {
|
|
|
539
541
|
}
|
|
540
542
|
};
|
|
541
543
|
function readBody(req) {
|
|
542
|
-
return new Promise((
|
|
544
|
+
return new Promise((resolve3, reject) => {
|
|
543
545
|
let data = "";
|
|
544
546
|
req.on("data", (chunk) => {
|
|
545
547
|
data += chunk;
|
|
546
548
|
});
|
|
547
549
|
req.on("end", () => {
|
|
548
550
|
try {
|
|
549
|
-
|
|
551
|
+
resolve3(data ? JSON.parse(data) : {});
|
|
550
552
|
} catch (e) {
|
|
551
553
|
reject(e);
|
|
552
554
|
}
|
|
@@ -626,11 +628,11 @@ async function resolvePort(configPort, vaultPath) {
|
|
|
626
628
|
return 0;
|
|
627
629
|
}
|
|
628
630
|
function isPortAvailable(port) {
|
|
629
|
-
return new Promise((
|
|
631
|
+
return new Promise((resolve3) => {
|
|
630
632
|
const server = net.createServer();
|
|
631
|
-
server.once("error", () =>
|
|
633
|
+
server.once("error", () => resolve3(false));
|
|
632
634
|
server.once("listening", () => {
|
|
633
|
-
server.close(() =>
|
|
635
|
+
server.close(() => resolve3(true));
|
|
634
636
|
});
|
|
635
637
|
server.listen(port, "127.0.0.1");
|
|
636
638
|
});
|
|
@@ -639,6 +641,53 @@ function isPortAvailable(port) {
|
|
|
639
641
|
// src/symbionts/adapter.ts
|
|
640
642
|
import fs3 from "fs";
|
|
641
643
|
import path3 from "path";
|
|
644
|
+
|
|
645
|
+
// src/symbionts/parsers/standard-jsonl.ts
|
|
646
|
+
var IMAGE_TEXT_REF_PATTERN = /\[Image: source: [^\]]+\]\n*/g;
|
|
647
|
+
var StandardJsonlParser = class {
|
|
648
|
+
constructor(opts) {
|
|
649
|
+
this.opts = opts;
|
|
650
|
+
}
|
|
651
|
+
parseTurns(content) {
|
|
652
|
+
const lines = content.split("\n").filter(Boolean);
|
|
653
|
+
const turns = [];
|
|
654
|
+
let current = null;
|
|
655
|
+
for (const line of lines) {
|
|
656
|
+
let entry;
|
|
657
|
+
try {
|
|
658
|
+
entry = JSON.parse(line);
|
|
659
|
+
} catch {
|
|
660
|
+
continue;
|
|
661
|
+
}
|
|
662
|
+
const role = entry[this.opts.roleField];
|
|
663
|
+
const timestamp = this.opts.extractTimestamp ? entry.timestamp ?? "" : "";
|
|
664
|
+
if (role === "user") {
|
|
665
|
+
if (entry.isMeta === true) continue;
|
|
666
|
+
const msg = entry.message;
|
|
667
|
+
const blocks = Array.isArray(msg?.content) ? msg.content : [];
|
|
668
|
+
const hasText = blocks.some((b) => b.type === "text" && b.text?.trim());
|
|
669
|
+
if (!hasText) continue;
|
|
670
|
+
if (current) turns.push(current);
|
|
671
|
+
const rawPrompt = blocks.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("\n");
|
|
672
|
+
const promptText = (this.opts.stripImageTextRefs ? rawPrompt.replace(IMAGE_TEXT_REF_PATTERN, "") : rawPrompt).trim().slice(0, PROMPT_PREVIEW_CHARS);
|
|
673
|
+
const images = blocks.filter((b) => b.type === "image" && b.source?.type === "base64" && b.source.data).map((b) => ({ data: b.source.data, mediaType: b.source.media_type ?? "image/png" }));
|
|
674
|
+
current = { prompt: promptText, toolCount: 0, timestamp, ...images.length > 0 ? { images } : {} };
|
|
675
|
+
} else if (role === "assistant" && current) {
|
|
676
|
+
const msg = entry.message;
|
|
677
|
+
if (Array.isArray(msg?.content)) {
|
|
678
|
+
const textParts = msg.content.filter((b) => b.type === "text" && b.text).map((b) => b.text);
|
|
679
|
+
const text = textParts.join("\n").trim();
|
|
680
|
+
if (text) current.aiResponse = text;
|
|
681
|
+
current.toolCount += msg.content.filter((b) => b.type === "tool_use").length;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
if (current) turns.push(current);
|
|
686
|
+
return turns;
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
|
|
690
|
+
// src/symbionts/adapter.ts
|
|
642
691
|
function findJsonlInSubdirs(baseDir, sessionId) {
|
|
643
692
|
try {
|
|
644
693
|
for (const entry of fs3.readdirSync(baseDir, { withFileTypes: true })) {
|
|
@@ -683,44 +732,8 @@ var EXT_TO_MIME = {
|
|
|
683
732
|
function mimeTypeForExtension(ext) {
|
|
684
733
|
return EXT_TO_MIME[ext.toLowerCase()] ?? "image/png";
|
|
685
734
|
}
|
|
686
|
-
var IMAGE_TEXT_REF_PATTERN = /\[Image: source: [^\]]+\]\n*/g;
|
|
687
735
|
function parseJsonlTurns(content, opts) {
|
|
688
|
-
|
|
689
|
-
const turns = [];
|
|
690
|
-
let current = null;
|
|
691
|
-
for (const line of lines) {
|
|
692
|
-
let entry;
|
|
693
|
-
try {
|
|
694
|
-
entry = JSON.parse(line);
|
|
695
|
-
} catch {
|
|
696
|
-
continue;
|
|
697
|
-
}
|
|
698
|
-
const role = entry[opts.roleField];
|
|
699
|
-
const timestamp = opts.extractTimestamp ? entry.timestamp ?? "" : "";
|
|
700
|
-
if (role === "user") {
|
|
701
|
-
if (entry.isMeta === true) continue;
|
|
702
|
-
const msg = entry.message;
|
|
703
|
-
const blocks = Array.isArray(msg?.content) ? msg.content : [];
|
|
704
|
-
const hasText = blocks.some((b) => b.type === "text" && b.text?.trim());
|
|
705
|
-
if (!hasText && opts.skipToolResultUsers) continue;
|
|
706
|
-
if (!hasText) continue;
|
|
707
|
-
if (current) turns.push(current);
|
|
708
|
-
const rawPrompt = blocks.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("\n");
|
|
709
|
-
const promptText = (opts.stripImageTextRefs ? rawPrompt.replace(IMAGE_TEXT_REF_PATTERN, "") : rawPrompt).trim().slice(0, PROMPT_PREVIEW_CHARS);
|
|
710
|
-
const images = blocks.filter((b) => b.type === "image" && b.source?.type === "base64" && b.source.data).map((b) => ({ data: b.source.data, mediaType: b.source.media_type ?? "image/png" }));
|
|
711
|
-
current = { prompt: promptText, toolCount: 0, timestamp, ...images.length > 0 ? { images } : {} };
|
|
712
|
-
} else if (role === "assistant" && current) {
|
|
713
|
-
const msg = entry.message;
|
|
714
|
-
if (Array.isArray(msg?.content)) {
|
|
715
|
-
const textParts = msg.content.filter((b) => b.type === "text" && b.text).map((b) => b.text);
|
|
716
|
-
const text = textParts.join("\n").trim();
|
|
717
|
-
if (text) current.aiResponse = text;
|
|
718
|
-
current.toolCount += msg.content.filter((b) => b.type === "tool_use").length;
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
if (current) turns.push(current);
|
|
723
|
-
return turns;
|
|
736
|
+
return new StandardJsonlParser(opts).parseTurns(content);
|
|
724
737
|
}
|
|
725
738
|
|
|
726
739
|
// src/symbionts/claude-code.ts
|
|
@@ -874,10 +887,100 @@ function parseCursorText(content) {
|
|
|
874
887
|
return turns;
|
|
875
888
|
}
|
|
876
889
|
|
|
890
|
+
// src/symbionts/parsers/codex-jsonl.ts
|
|
891
|
+
function parseDataUrl(url) {
|
|
892
|
+
const match = url.match(/^data:([^;]+);base64,(.+)$/);
|
|
893
|
+
if (!match) return null;
|
|
894
|
+
return { mediaType: match[1], data: match[2] };
|
|
895
|
+
}
|
|
896
|
+
var IMAGE_WRAPPER_TAG = /^<\/?image\b[^>]*>$/;
|
|
897
|
+
var CODEX_PROMPT_MARKER = "## My request for Codex:\n";
|
|
898
|
+
function cleanCodexPromptText(text) {
|
|
899
|
+
if (IMAGE_WRAPPER_TAG.test(text.trim())) return "";
|
|
900
|
+
const idx = text.indexOf(CODEX_PROMPT_MARKER);
|
|
901
|
+
if (idx !== -1) return text.slice(idx + CODEX_PROMPT_MARKER.length);
|
|
902
|
+
return text;
|
|
903
|
+
}
|
|
904
|
+
var CodexJsonlParser = class {
|
|
905
|
+
parseTurns(content) {
|
|
906
|
+
const lines = content.split("\n").filter(Boolean);
|
|
907
|
+
const turns = [];
|
|
908
|
+
let current = null;
|
|
909
|
+
for (const line of lines) {
|
|
910
|
+
let entry;
|
|
911
|
+
try {
|
|
912
|
+
entry = JSON.parse(line);
|
|
913
|
+
} catch {
|
|
914
|
+
continue;
|
|
915
|
+
}
|
|
916
|
+
if (entry.type !== "response_item") continue;
|
|
917
|
+
const payload = entry.payload;
|
|
918
|
+
if (!payload) continue;
|
|
919
|
+
const payloadType = payload.type;
|
|
920
|
+
const timestamp = entry.timestamp ?? "";
|
|
921
|
+
if (payloadType === "function_call") {
|
|
922
|
+
if (current) current.toolCount++;
|
|
923
|
+
continue;
|
|
924
|
+
}
|
|
925
|
+
if (payloadType !== "message") continue;
|
|
926
|
+
const role = payload.role;
|
|
927
|
+
const blocks = Array.isArray(payload.content) ? payload.content : [];
|
|
928
|
+
if (role === "user") {
|
|
929
|
+
const textParts = blocks.filter((b) => b.type === "input_text" && b.text?.trim()).map((b) => cleanCodexPromptText(b.text)).filter((t) => t.trim());
|
|
930
|
+
if (textParts.length === 0) continue;
|
|
931
|
+
if (current) turns.push(current);
|
|
932
|
+
const promptText = textParts.join("\n").trim().slice(0, PROMPT_PREVIEW_CHARS);
|
|
933
|
+
const images = [];
|
|
934
|
+
for (const b of blocks) {
|
|
935
|
+
if (b.type === "input_image" && b.image_url) {
|
|
936
|
+
const parsed = parseDataUrl(b.image_url);
|
|
937
|
+
if (parsed) images.push(parsed);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
current = { prompt: promptText, toolCount: 0, timestamp, ...images.length > 0 ? { images } : {} };
|
|
941
|
+
} else if (role === "assistant" && current) {
|
|
942
|
+
const textParts = blocks.filter((b) => b.type === "output_text" && b.text).map((b) => b.text);
|
|
943
|
+
const text = textParts.join("\n").trim();
|
|
944
|
+
if (text) current.aiResponse = text;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
if (current) turns.push(current);
|
|
948
|
+
return turns;
|
|
949
|
+
}
|
|
950
|
+
};
|
|
951
|
+
|
|
877
952
|
// src/symbionts/codex.ts
|
|
953
|
+
import fs5 from "fs";
|
|
878
954
|
import path6 from "path";
|
|
879
955
|
import os3 from "os";
|
|
880
956
|
var TRANSCRIPT_BASE2 = path6.join(os3.homedir(), ".codex");
|
|
957
|
+
var codexParser = new CodexJsonlParser();
|
|
958
|
+
function findCodexTranscript(baseDir, sessionId) {
|
|
959
|
+
const sessionsDir = path6.join(baseDir, "sessions");
|
|
960
|
+
try {
|
|
961
|
+
return scanForSessionFile(sessionsDir, sessionId);
|
|
962
|
+
} catch {
|
|
963
|
+
return null;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
function scanForSessionFile(dir, sessionId) {
|
|
967
|
+
let entries;
|
|
968
|
+
try {
|
|
969
|
+
entries = fs5.readdirSync(dir, { withFileTypes: true });
|
|
970
|
+
} catch {
|
|
971
|
+
return null;
|
|
972
|
+
}
|
|
973
|
+
for (const entry of entries) {
|
|
974
|
+
const fullPath = path6.join(dir, entry.name);
|
|
975
|
+
if (entry.isDirectory()) {
|
|
976
|
+
const found = scanForSessionFile(fullPath, sessionId);
|
|
977
|
+
if (found) return found;
|
|
978
|
+
} else if (entry.isFile() && entry.name.includes(sessionId) && entry.name.endsWith(".jsonl")) {
|
|
979
|
+
return fullPath;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
return null;
|
|
983
|
+
}
|
|
881
984
|
var codexAdapter = {
|
|
882
985
|
name: "codex",
|
|
883
986
|
displayName: "Codex",
|
|
@@ -891,18 +994,12 @@ var codexAdapter = {
|
|
|
891
994
|
toolInput: "tool_input",
|
|
892
995
|
toolOutput: "tool_output"
|
|
893
996
|
},
|
|
894
|
-
findTranscript: (sessionId) =>
|
|
895
|
-
|
|
896
|
-
parseTurns: (content) => parseJsonlTurns(content, {
|
|
897
|
-
roleField: "role",
|
|
898
|
-
extractTimestamp: false,
|
|
899
|
-
skipToolResultUsers: false,
|
|
900
|
-
stripImageTextRefs: false
|
|
901
|
-
})
|
|
997
|
+
findTranscript: (sessionId) => findCodexTranscript(TRANSCRIPT_BASE2, sessionId),
|
|
998
|
+
parseTurns: (content) => codexParser.parseTurns(content)
|
|
902
999
|
};
|
|
903
1000
|
|
|
904
1001
|
// src/symbionts/gemini.ts
|
|
905
|
-
import
|
|
1002
|
+
import fs6 from "fs";
|
|
906
1003
|
import path7 from "path";
|
|
907
1004
|
import os4 from "os";
|
|
908
1005
|
var GEMINI_TMP = path7.join(os4.homedir(), ".gemini", "tmp");
|
|
@@ -922,15 +1019,15 @@ var geminiAdapter = {
|
|
|
922
1019
|
},
|
|
923
1020
|
findTranscript(sessionId) {
|
|
924
1021
|
try {
|
|
925
|
-
for (const project of
|
|
1022
|
+
for (const project of fs6.readdirSync(GEMINI_TMP, { withFileTypes: true })) {
|
|
926
1023
|
if (!project.isDirectory()) continue;
|
|
927
1024
|
const chatsDir = path7.join(GEMINI_TMP, project.name, "chats");
|
|
928
1025
|
try {
|
|
929
|
-
for (const file of
|
|
1026
|
+
for (const file of fs6.readdirSync(chatsDir)) {
|
|
930
1027
|
if (!file.endsWith(".json")) continue;
|
|
931
1028
|
if (file.includes(sessionId.slice(0, 8))) {
|
|
932
1029
|
try {
|
|
933
|
-
const data = JSON.parse(
|
|
1030
|
+
const data = JSON.parse(fs6.readFileSync(path7.join(chatsDir, file), "utf-8"));
|
|
934
1031
|
if (data.sessionId === sessionId) {
|
|
935
1032
|
return path7.join(chatsDir, file);
|
|
936
1033
|
}
|
|
@@ -984,7 +1081,7 @@ function parseGeminiJson(content) {
|
|
|
984
1081
|
}
|
|
985
1082
|
|
|
986
1083
|
// src/symbionts/windsurf.ts
|
|
987
|
-
import
|
|
1084
|
+
import fs7 from "fs";
|
|
988
1085
|
import path8 from "path";
|
|
989
1086
|
import os5 from "os";
|
|
990
1087
|
var TRANSCRIPT_DIR = path8.join(os5.homedir(), ".windsurf", "transcripts");
|
|
@@ -1007,7 +1104,7 @@ var windsurfAdapter = {
|
|
|
1007
1104
|
findTranscript(sessionId) {
|
|
1008
1105
|
const candidate = path8.join(TRANSCRIPT_DIR, `${sessionId}.jsonl`);
|
|
1009
1106
|
try {
|
|
1010
|
-
|
|
1107
|
+
fs7.accessSync(candidate);
|
|
1011
1108
|
return candidate;
|
|
1012
1109
|
} catch {
|
|
1013
1110
|
return null;
|
|
@@ -1142,7 +1239,7 @@ function normalizeResponseParts(response) {
|
|
|
1142
1239
|
}
|
|
1143
1240
|
|
|
1144
1241
|
// src/symbionts/registry.ts
|
|
1145
|
-
import
|
|
1242
|
+
import fs8 from "fs";
|
|
1146
1243
|
var ALL_ADAPTERS = [
|
|
1147
1244
|
claudeCodeAdapter,
|
|
1148
1245
|
cursorAdapter,
|
|
@@ -1165,7 +1262,7 @@ var SymbiontRegistry = class {
|
|
|
1165
1262
|
const filePath = adapter.findTranscript(sessionId);
|
|
1166
1263
|
if (!filePath) continue;
|
|
1167
1264
|
try {
|
|
1168
|
-
const content =
|
|
1265
|
+
const content = fs8.readFileSync(filePath, "utf-8");
|
|
1169
1266
|
const turns = adapter.parseTurns(content);
|
|
1170
1267
|
if (turns.length > 0) {
|
|
1171
1268
|
return { turns, source: adapter.name };
|
|
@@ -1199,7 +1296,7 @@ var SymbiontRegistry = class {
|
|
|
1199
1296
|
*/
|
|
1200
1297
|
parseTurnsFromPath(filePath) {
|
|
1201
1298
|
try {
|
|
1202
|
-
const content =
|
|
1299
|
+
const content = fs8.readFileSync(filePath, "utf-8");
|
|
1203
1300
|
const active = this.detectActiveAgent();
|
|
1204
1301
|
const orderedAdapters = active ? [active, ...this.adapters.filter((a) => a !== active)] : this.adapters;
|
|
1205
1302
|
for (const adapter of orderedAdapters) {
|
|
@@ -1599,12 +1696,34 @@ async function handleRestart(deps, body) {
|
|
|
1599
1696
|
|
|
1600
1697
|
// src/daemon/update-checker.ts
|
|
1601
1698
|
var import_yaml = __toESM(require_dist(), 1);
|
|
1602
|
-
import
|
|
1699
|
+
import fs9 from "fs";
|
|
1603
1700
|
import path9 from "path";
|
|
1701
|
+
import { execFileSync } from "child_process";
|
|
1604
1702
|
import semver from "semver";
|
|
1605
1703
|
var REGISTRY_FETCH_TIMEOUT_MS = 1e4;
|
|
1704
|
+
var devBuildCliEntry = null;
|
|
1705
|
+
function setDevBuildCliEntry(cliEntry) {
|
|
1706
|
+
devBuildCliEntry = cliEntry;
|
|
1707
|
+
}
|
|
1708
|
+
function resolveMycoBinary() {
|
|
1709
|
+
return devBuildCliEntry ?? "myco";
|
|
1710
|
+
}
|
|
1606
1711
|
function isUpdateExempt() {
|
|
1607
|
-
return
|
|
1712
|
+
return devBuildCliEntry !== null;
|
|
1713
|
+
}
|
|
1714
|
+
function detectDevBuild(globalPrefix, cliEntry, realpath) {
|
|
1715
|
+
if (!globalPrefix) return null;
|
|
1716
|
+
if (!cliEntry) return null;
|
|
1717
|
+
try {
|
|
1718
|
+
const resolvedEntry = realpath(cliEntry);
|
|
1719
|
+
const resolvedPrefix = realpath(globalPrefix);
|
|
1720
|
+
if (resolvedEntry.startsWith(resolvedPrefix + path9.sep) || resolvedEntry === resolvedPrefix) {
|
|
1721
|
+
return null;
|
|
1722
|
+
}
|
|
1723
|
+
return cliEntry;
|
|
1724
|
+
} catch {
|
|
1725
|
+
return null;
|
|
1726
|
+
}
|
|
1608
1727
|
}
|
|
1609
1728
|
function defaultUpdateConfig() {
|
|
1610
1729
|
return {
|
|
@@ -1614,7 +1733,7 @@ function defaultUpdateConfig() {
|
|
|
1614
1733
|
}
|
|
1615
1734
|
function readUpdateConfig() {
|
|
1616
1735
|
try {
|
|
1617
|
-
const raw =
|
|
1736
|
+
const raw = fs9.readFileSync(UPDATE_CONFIG_PATH, "utf-8");
|
|
1618
1737
|
const parsed = import_yaml.default.parse(raw);
|
|
1619
1738
|
const channel = RELEASE_CHANNELS.includes(parsed?.channel) ? parsed.channel : DEFAULT_RELEASE_CHANNEL;
|
|
1620
1739
|
const check_interval_hours = typeof parsed?.check_interval_hours === "number" && parsed.check_interval_hours > 0 ? parsed.check_interval_hours : UPDATE_CHECK_INTERVAL_HOURS;
|
|
@@ -1624,12 +1743,12 @@ function readUpdateConfig() {
|
|
|
1624
1743
|
}
|
|
1625
1744
|
}
|
|
1626
1745
|
function writeUpdateConfig(config) {
|
|
1627
|
-
|
|
1628
|
-
|
|
1746
|
+
fs9.mkdirSync(MYCO_GLOBAL_DIR, { recursive: true });
|
|
1747
|
+
fs9.writeFileSync(UPDATE_CONFIG_PATH, import_yaml.default.stringify(config), "utf-8");
|
|
1629
1748
|
}
|
|
1630
1749
|
function readCachedCheck() {
|
|
1631
1750
|
try {
|
|
1632
|
-
const raw =
|
|
1751
|
+
const raw = fs9.readFileSync(UPDATE_CHECK_CACHE_PATH, "utf-8");
|
|
1633
1752
|
return JSON.parse(raw);
|
|
1634
1753
|
} catch {
|
|
1635
1754
|
return null;
|
|
@@ -1637,7 +1756,7 @@ function readCachedCheck() {
|
|
|
1637
1756
|
}
|
|
1638
1757
|
function clearCachedCheck() {
|
|
1639
1758
|
try {
|
|
1640
|
-
|
|
1759
|
+
fs9.unlinkSync(UPDATE_CHECK_CACHE_PATH);
|
|
1641
1760
|
} catch {
|
|
1642
1761
|
}
|
|
1643
1762
|
}
|
|
@@ -1675,6 +1794,25 @@ function buildCheckResult(currentVersion, cache, config, error) {
|
|
|
1675
1794
|
error
|
|
1676
1795
|
};
|
|
1677
1796
|
}
|
|
1797
|
+
function resolveGlobalPrefix() {
|
|
1798
|
+
return execFileSync("npm", ["prefix", "-g"], { encoding: "utf-8", timeout: 5e3 }).trim();
|
|
1799
|
+
}
|
|
1800
|
+
function getInstalledVersion(globalPrefix) {
|
|
1801
|
+
try {
|
|
1802
|
+
const pkgPath = path9.join(
|
|
1803
|
+
globalPrefix,
|
|
1804
|
+
"lib",
|
|
1805
|
+
"node_modules",
|
|
1806
|
+
NPM_PACKAGE_NAME,
|
|
1807
|
+
"package.json"
|
|
1808
|
+
);
|
|
1809
|
+
const raw = fs9.readFileSync(pkgPath, "utf-8");
|
|
1810
|
+
const pkg = JSON.parse(raw);
|
|
1811
|
+
return pkg.version ?? null;
|
|
1812
|
+
} catch {
|
|
1813
|
+
return null;
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1678
1816
|
async function checkForUpdate(currentVersion) {
|
|
1679
1817
|
const config = readUpdateConfig();
|
|
1680
1818
|
const existingCache = readCachedCheck();
|
|
@@ -1717,8 +1855,8 @@ async function checkForUpdate(currentVersion) {
|
|
|
1717
1855
|
channel: config.channel
|
|
1718
1856
|
};
|
|
1719
1857
|
try {
|
|
1720
|
-
|
|
1721
|
-
|
|
1858
|
+
fs9.mkdirSync(path9.dirname(UPDATE_CHECK_CACHE_PATH), { recursive: true });
|
|
1859
|
+
fs9.writeFileSync(UPDATE_CHECK_CACHE_PATH, JSON.stringify(freshCache, null, 2), "utf-8");
|
|
1722
1860
|
} catch {
|
|
1723
1861
|
}
|
|
1724
1862
|
return buildCheckResult(currentVersion, freshCache, config, null);
|
|
@@ -1731,22 +1869,23 @@ function statusFromCache(currentVersion, cache, config) {
|
|
|
1731
1869
|
}
|
|
1732
1870
|
|
|
1733
1871
|
// src/daemon/update-installer.ts
|
|
1734
|
-
import
|
|
1872
|
+
import fs10 from "fs";
|
|
1735
1873
|
import os6 from "os";
|
|
1736
1874
|
import path10 from "path";
|
|
1737
1875
|
import { spawn as spawn2 } from "child_process";
|
|
1738
1876
|
function generateUpdateScript(params) {
|
|
1739
|
-
const { targetVersion, projectRoot, vaultDir } = params;
|
|
1877
|
+
const { targetVersion, projectRoot, vaultDir, mycoBinary } = params;
|
|
1740
1878
|
const packageSpec = `${NPM_PACKAGE_NAME}@${targetVersion}`;
|
|
1741
1879
|
const quotedProjectRoot = JSON.stringify(projectRoot);
|
|
1742
1880
|
const quotedVaultDir = JSON.stringify(vaultDir);
|
|
1881
|
+
const quotedMycoBinary = JSON.stringify(mycoBinary);
|
|
1743
1882
|
const quotedErrorPath = JSON.stringify(UPDATE_ERROR_PATH);
|
|
1744
1883
|
const errorJson = JSON.stringify(
|
|
1745
1884
|
JSON.stringify({ error: `npm install failed for ${packageSpec}` })
|
|
1746
1885
|
);
|
|
1747
1886
|
return `#!/bin/sh
|
|
1748
1887
|
set -e
|
|
1749
|
-
MYCO
|
|
1888
|
+
MYCO=${quotedMycoBinary}
|
|
1750
1889
|
|
|
1751
1890
|
# Wait for daemon to exit cleanly
|
|
1752
1891
|
sleep ${UPDATE_SCRIPT_DELAY_SECONDS}
|
|
@@ -1769,12 +1908,9 @@ fi
|
|
|
1769
1908
|
rm -f "$0"
|
|
1770
1909
|
`;
|
|
1771
1910
|
}
|
|
1772
|
-
function
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
const scriptPath = path10.join(os6.tmpdir(), scriptName);
|
|
1776
|
-
const script = generateUpdateScript(params);
|
|
1777
|
-
fs9.writeFileSync(scriptPath, script, { encoding: "utf-8", mode: 493 });
|
|
1911
|
+
function spawnDetachedScript(namePrefix, content) {
|
|
1912
|
+
const scriptPath = path10.join(os6.tmpdir(), `${namePrefix}-${Date.now()}.sh`);
|
|
1913
|
+
fs10.writeFileSync(scriptPath, content, { encoding: "utf-8", mode: 493 });
|
|
1778
1914
|
const child = spawn2("/bin/sh", [scriptPath], {
|
|
1779
1915
|
detached: true,
|
|
1780
1916
|
stdio: "ignore"
|
|
@@ -1782,17 +1918,94 @@ function spawnUpdateScript(params) {
|
|
|
1782
1918
|
child.unref();
|
|
1783
1919
|
return scriptPath;
|
|
1784
1920
|
}
|
|
1921
|
+
function spawnUpdateScript(params) {
|
|
1922
|
+
fs10.mkdirSync(MYCO_GLOBAL_DIR, { recursive: true });
|
|
1923
|
+
return spawnDetachedScript("myco-update", generateUpdateScript(params));
|
|
1924
|
+
}
|
|
1925
|
+
function generateRestartScript(params) {
|
|
1926
|
+
const { projectRoot, vaultDir, runLocalUpdate, fromVersion, toVersion, mycoBinary } = params;
|
|
1927
|
+
const quotedProjectRoot = JSON.stringify(projectRoot);
|
|
1928
|
+
const quotedVaultDir = JSON.stringify(vaultDir);
|
|
1929
|
+
const quotedMycoBinary = JSON.stringify(mycoBinary);
|
|
1930
|
+
const reasonFile = JSON.stringify(path10.join(vaultDir, RESTART_REASON_FILENAME));
|
|
1931
|
+
const reasonJson = JSON.stringify(JSON.stringify({
|
|
1932
|
+
reason: "version_sync",
|
|
1933
|
+
from_version: fromVersion,
|
|
1934
|
+
to_version: toVersion,
|
|
1935
|
+
local_update_ran: runLocalUpdate
|
|
1936
|
+
}));
|
|
1937
|
+
const updateBlock = runLocalUpdate ? `
|
|
1938
|
+
# Run local project update (hooks, symbionts, gitignore)
|
|
1939
|
+
"$MYCO" update --project ${quotedProjectRoot} || true` : "";
|
|
1940
|
+
return `#!/bin/sh
|
|
1941
|
+
set -e
|
|
1942
|
+
MYCO=${quotedMycoBinary}
|
|
1943
|
+
|
|
1944
|
+
# Wait for daemon to exit cleanly
|
|
1945
|
+
sleep ${UPDATE_SCRIPT_DELAY_SECONDS}
|
|
1946
|
+
${updateBlock}
|
|
1947
|
+
|
|
1948
|
+
# Write restart reason for the new daemon to pick up
|
|
1949
|
+
echo ${reasonJson} > ${reasonFile}
|
|
1950
|
+
|
|
1951
|
+
# Restart daemon
|
|
1952
|
+
"$MYCO" daemon --vault ${quotedVaultDir} &
|
|
1953
|
+
|
|
1954
|
+
# Clean up this script
|
|
1955
|
+
rm -f "$0"
|
|
1956
|
+
`;
|
|
1957
|
+
}
|
|
1958
|
+
function spawnRestartScript(params) {
|
|
1959
|
+
return spawnDetachedScript("myco-restart", generateRestartScript(params));
|
|
1960
|
+
}
|
|
1785
1961
|
|
|
1786
1962
|
// src/daemon/api/update.ts
|
|
1963
|
+
import semver2 from "semver";
|
|
1964
|
+
import fs11 from "fs";
|
|
1965
|
+
import path11 from "path";
|
|
1787
1966
|
var ChannelBodySchema = external_exports.object({
|
|
1788
1967
|
channel: external_exports.enum(RELEASE_CHANNELS)
|
|
1789
1968
|
});
|
|
1790
1969
|
function createUpdateHandlers(deps) {
|
|
1791
|
-
const { vaultDir, projectRoot, currentVersion, scheduleShutdown } = deps;
|
|
1970
|
+
const { vaultDir, projectRoot, currentVersion, scheduleShutdown, globalPrefix } = deps;
|
|
1971
|
+
let restartInitiated = false;
|
|
1972
|
+
function isStampCurrent() {
|
|
1973
|
+
try {
|
|
1974
|
+
const stampPath = path11.join(vaultDir, UPDATE_STAMP_FILENAME);
|
|
1975
|
+
const stamp = fs11.readFileSync(stampPath, "utf-8").trim();
|
|
1976
|
+
return stamp === currentVersion;
|
|
1977
|
+
} catch {
|
|
1978
|
+
return false;
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1792
1981
|
async function handleUpdateStatus(_req) {
|
|
1793
1982
|
if (isUpdateExempt()) {
|
|
1794
1983
|
return { body: { exempt: true, running_version: currentVersion } };
|
|
1795
1984
|
}
|
|
1985
|
+
if (globalPrefix && !restartInitiated) {
|
|
1986
|
+
const installedVersion = getInstalledVersion(globalPrefix);
|
|
1987
|
+
if (installedVersion && semver2.valid(installedVersion) && semver2.valid(currentVersion) && semver2.gt(installedVersion, currentVersion)) {
|
|
1988
|
+
restartInitiated = true;
|
|
1989
|
+
const runLocalUpdate = !isStampCurrent();
|
|
1990
|
+
spawnRestartScript({
|
|
1991
|
+
projectRoot,
|
|
1992
|
+
vaultDir,
|
|
1993
|
+
runLocalUpdate,
|
|
1994
|
+
fromVersion: currentVersion,
|
|
1995
|
+
toVersion: installedVersion,
|
|
1996
|
+
mycoBinary: resolveMycoBinary()
|
|
1997
|
+
});
|
|
1998
|
+
scheduleShutdown();
|
|
1999
|
+
return {
|
|
2000
|
+
body: {
|
|
2001
|
+
restarting: true,
|
|
2002
|
+
reason: "version_sync",
|
|
2003
|
+
running_version: currentVersion,
|
|
2004
|
+
installed_version: installedVersion
|
|
2005
|
+
}
|
|
2006
|
+
};
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
1796
2009
|
const config = readUpdateConfig();
|
|
1797
2010
|
const cache = readCachedCheck();
|
|
1798
2011
|
if (isCacheStale(cache, config.check_interval_hours)) {
|
|
@@ -1836,7 +2049,12 @@ function createUpdateHandlers(deps) {
|
|
|
1836
2049
|
if (!status || !status.update_available) {
|
|
1837
2050
|
return { status: 400, body: { error: "no_update_available" } };
|
|
1838
2051
|
}
|
|
1839
|
-
spawnUpdateScript({
|
|
2052
|
+
spawnUpdateScript({
|
|
2053
|
+
targetVersion: status.latest_version,
|
|
2054
|
+
projectRoot,
|
|
2055
|
+
vaultDir,
|
|
2056
|
+
mycoBinary: resolveMycoBinary()
|
|
2057
|
+
});
|
|
1840
2058
|
scheduleShutdown();
|
|
1841
2059
|
return { body: { status: "applying", version: status.latest_version } };
|
|
1842
2060
|
}
|
|
@@ -1877,8 +2095,8 @@ function createUpdateHandlers(deps) {
|
|
|
1877
2095
|
}
|
|
1878
2096
|
|
|
1879
2097
|
// src/daemon/backup.ts
|
|
1880
|
-
import
|
|
1881
|
-
import
|
|
2098
|
+
import fs12 from "fs";
|
|
2099
|
+
import path12 from "path";
|
|
1882
2100
|
var BACKUP_TABLES = [
|
|
1883
2101
|
"sessions",
|
|
1884
2102
|
"prompt_batches",
|
|
@@ -1893,6 +2111,7 @@ var BACKUP_TABLES = [
|
|
|
1893
2111
|
"team_members"
|
|
1894
2112
|
];
|
|
1895
2113
|
var BACKUP_EXTENSION = ".sql";
|
|
2114
|
+
var BACKUP_FILENAME_PATTERN = /^[A-Za-z0-9_-]+\.sql$/;
|
|
1896
2115
|
var BACKUP_HEADER_TEMPLATE = "-- Myco backup";
|
|
1897
2116
|
function escapeSql(value) {
|
|
1898
2117
|
return value.replace(/'/g, "''");
|
|
@@ -1904,7 +2123,7 @@ function toSqlLiteral(value) {
|
|
|
1904
2123
|
return `'${escapeSql(String(value))}'`;
|
|
1905
2124
|
}
|
|
1906
2125
|
function createBackup(db, backupDir, machineId) {
|
|
1907
|
-
|
|
2126
|
+
fs12.mkdirSync(backupDir, { recursive: true });
|
|
1908
2127
|
const lines = [];
|
|
1909
2128
|
const timestamp = epochSeconds();
|
|
1910
2129
|
lines.push(`${BACKUP_HEADER_TEMPLATE}: machine_id=${machineId}, created_at=${timestamp}`);
|
|
@@ -1922,22 +2141,22 @@ function createBackup(db, backupDir, machineId) {
|
|
|
1922
2141
|
}
|
|
1923
2142
|
lines.push("");
|
|
1924
2143
|
}
|
|
1925
|
-
const filePath =
|
|
1926
|
-
|
|
2144
|
+
const filePath = path12.join(backupDir, `${machineId}${BACKUP_EXTENSION}`);
|
|
2145
|
+
fs12.writeFileSync(filePath, lines.join("\n"), "utf-8");
|
|
1927
2146
|
return filePath;
|
|
1928
2147
|
}
|
|
1929
2148
|
function listBackups(backupDir) {
|
|
1930
2149
|
let entries;
|
|
1931
2150
|
try {
|
|
1932
|
-
entries =
|
|
2151
|
+
entries = fs12.readdirSync(backupDir);
|
|
1933
2152
|
} catch {
|
|
1934
2153
|
return [];
|
|
1935
2154
|
}
|
|
1936
2155
|
const backups = [];
|
|
1937
2156
|
for (const entry of entries) {
|
|
1938
|
-
if (!
|
|
1939
|
-
const filePath =
|
|
1940
|
-
const stat =
|
|
2157
|
+
if (!BACKUP_FILENAME_PATTERN.test(entry)) continue;
|
|
2158
|
+
const filePath = path12.join(backupDir, entry);
|
|
2159
|
+
const stat = fs12.statSync(filePath);
|
|
1941
2160
|
backups.push({
|
|
1942
2161
|
machine_id: entry.slice(0, -BACKUP_EXTENSION.length),
|
|
1943
2162
|
file_name: entry,
|
|
@@ -1949,7 +2168,7 @@ function listBackups(backupDir) {
|
|
|
1949
2168
|
}
|
|
1950
2169
|
var INSERT_REGEX = /^INSERT OR IGNORE INTO (\w+)\s+\(([^)]+)\)\s+VALUES\s+\((.+)\);$/;
|
|
1951
2170
|
function parseBackupFile(backupPath) {
|
|
1952
|
-
const content =
|
|
2171
|
+
const content = fs12.readFileSync(backupPath, "utf-8");
|
|
1953
2172
|
const inserts = [];
|
|
1954
2173
|
for (const line of content.split("\n")) {
|
|
1955
2174
|
const match = INSERT_REGEX.exec(line);
|
|
@@ -2033,7 +2252,7 @@ function restoreBackup(db, backupPath) {
|
|
|
2033
2252
|
}
|
|
2034
2253
|
|
|
2035
2254
|
// src/daemon/api/backup.ts
|
|
2036
|
-
import
|
|
2255
|
+
import path13 from "path";
|
|
2037
2256
|
function createBackupHandlers(deps) {
|
|
2038
2257
|
async function handleCreateBackup(_req) {
|
|
2039
2258
|
const filePath = createBackup(deps.db, deps.backupDir, deps.machineId);
|
|
@@ -2092,7 +2311,7 @@ function createBackupConfigHandlers(deps) {
|
|
|
2092
2311
|
const { vaultDir } = deps;
|
|
2093
2312
|
async function handleGetBackupConfig() {
|
|
2094
2313
|
const cfg = loadConfig(vaultDir);
|
|
2095
|
-
return { body: { dir: cfg.backup.dir ?? null, default_dir:
|
|
2314
|
+
return { body: { dir: cfg.backup.dir ?? null, default_dir: path13.resolve(vaultDir, "backups") } };
|
|
2096
2315
|
}
|
|
2097
2316
|
async function handlePutBackupConfig(req) {
|
|
2098
2317
|
const { dir } = req.body;
|
|
@@ -2103,12 +2322,14 @@ function createBackupConfigHandlers(deps) {
|
|
|
2103
2322
|
}
|
|
2104
2323
|
|
|
2105
2324
|
// src/daemon/team-sync.ts
|
|
2106
|
-
var TeamSyncClient = class {
|
|
2325
|
+
var TeamSyncClient = class _TeamSyncClient {
|
|
2107
2326
|
workerUrl;
|
|
2108
2327
|
apiKey;
|
|
2109
2328
|
machineId;
|
|
2110
2329
|
syncProtocolVersion;
|
|
2111
2330
|
fetchFn;
|
|
2331
|
+
mcpToken = null;
|
|
2332
|
+
mcpTokenHash = null;
|
|
2112
2333
|
constructor(options) {
|
|
2113
2334
|
this.workerUrl = options.workerUrl.replace(/\/+$/, "");
|
|
2114
2335
|
this.apiKey = options.apiKey;
|
|
@@ -2116,6 +2337,14 @@ var TeamSyncClient = class {
|
|
|
2116
2337
|
this.syncProtocolVersion = options.syncProtocolVersion;
|
|
2117
2338
|
this.fetchFn = options.fetch ?? globalThis.fetch;
|
|
2118
2339
|
}
|
|
2340
|
+
// Must match getMcpTokenHash() in src/worker/src/mcp/auth.ts
|
|
2341
|
+
static hashToken(token) {
|
|
2342
|
+
let hash = 0;
|
|
2343
|
+
for (let i = 0; i < token.length; i++) {
|
|
2344
|
+
hash = (hash << 5) - hash + token.charCodeAt(i) | 0;
|
|
2345
|
+
}
|
|
2346
|
+
return Math.abs(hash).toString(16).padStart(8, "0").slice(0, 8);
|
|
2347
|
+
}
|
|
2119
2348
|
/**
|
|
2120
2349
|
* Register this machine with the team worker.
|
|
2121
2350
|
*/
|
|
@@ -2125,7 +2354,12 @@ var TeamSyncClient = class {
|
|
|
2125
2354
|
machine_id: this.machineId,
|
|
2126
2355
|
sync_protocol_version: this.syncProtocolVersion
|
|
2127
2356
|
});
|
|
2128
|
-
|
|
2357
|
+
const response = res;
|
|
2358
|
+
if (response.mcp_token) {
|
|
2359
|
+
this.mcpToken = response.mcp_token;
|
|
2360
|
+
this.mcpTokenHash = _TeamSyncClient.hashToken(response.mcp_token);
|
|
2361
|
+
}
|
|
2362
|
+
return response;
|
|
2129
2363
|
}
|
|
2130
2364
|
/**
|
|
2131
2365
|
* Push a batch of outbox records to the team worker.
|
|
@@ -2191,7 +2425,14 @@ var TeamSyncClient = class {
|
|
|
2191
2425
|
if (!res.ok) {
|
|
2192
2426
|
throw new Error(`Health check failed: ${res.status} ${res.statusText}`);
|
|
2193
2427
|
}
|
|
2194
|
-
|
|
2428
|
+
const data = await res.json();
|
|
2429
|
+
if (data.mcp_token_hash && data.mcp_token_hash !== this.mcpTokenHash) {
|
|
2430
|
+
try {
|
|
2431
|
+
await this.connect({ machine_id: this.machineId });
|
|
2432
|
+
} catch {
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
2435
|
+
return data;
|
|
2195
2436
|
} finally {
|
|
2196
2437
|
clearTimeout(timer);
|
|
2197
2438
|
}
|
|
@@ -2204,6 +2445,22 @@ var TeamSyncClient = class {
|
|
|
2204
2445
|
return res;
|
|
2205
2446
|
}
|
|
2206
2447
|
// ---------------------------------------------------------------------------
|
|
2448
|
+
// MCP token accessors
|
|
2449
|
+
// ---------------------------------------------------------------------------
|
|
2450
|
+
getMcpToken() {
|
|
2451
|
+
return this.mcpToken;
|
|
2452
|
+
}
|
|
2453
|
+
getMcpEndpoint() {
|
|
2454
|
+
if (!this.mcpToken) return null;
|
|
2455
|
+
return `${this.workerUrl}/mcp`;
|
|
2456
|
+
}
|
|
2457
|
+
async rotateMcpToken() {
|
|
2458
|
+
const result = await this.request("POST", "/mcp/rotate");
|
|
2459
|
+
this.mcpToken = result.token;
|
|
2460
|
+
this.mcpTokenHash = _TeamSyncClient.hashToken(result.token);
|
|
2461
|
+
return result.token;
|
|
2462
|
+
}
|
|
2463
|
+
// ---------------------------------------------------------------------------
|
|
2207
2464
|
// Internal
|
|
2208
2465
|
// ---------------------------------------------------------------------------
|
|
2209
2466
|
headers() {
|
|
@@ -2212,15 +2469,15 @@ var TeamSyncClient = class {
|
|
|
2212
2469
|
"Content-Type": "application/json"
|
|
2213
2470
|
};
|
|
2214
2471
|
}
|
|
2215
|
-
async request(method,
|
|
2216
|
-
const res = await this.fetchFn(`${this.workerUrl}${
|
|
2472
|
+
async request(method, path22, body) {
|
|
2473
|
+
const res = await this.fetchFn(`${this.workerUrl}${path22}`, {
|
|
2217
2474
|
method,
|
|
2218
2475
|
headers: this.headers(),
|
|
2219
2476
|
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
2220
2477
|
});
|
|
2221
2478
|
if (!res.ok) {
|
|
2222
2479
|
const text = await res.text().catch(() => "");
|
|
2223
|
-
throw new Error(`Team sync request ${method} ${
|
|
2480
|
+
throw new Error(`Team sync request ${method} ${path22} failed: ${res.status} ${text}`);
|
|
2224
2481
|
}
|
|
2225
2482
|
return res.json();
|
|
2226
2483
|
}
|
|
@@ -2228,7 +2485,7 @@ var TeamSyncClient = class {
|
|
|
2228
2485
|
|
|
2229
2486
|
// src/daemon/api/team-connect.ts
|
|
2230
2487
|
function createTeamHandlers(deps) {
|
|
2231
|
-
const { vaultDir, machineId } = deps;
|
|
2488
|
+
const { vaultDir, machineId, logger } = deps;
|
|
2232
2489
|
async function handleConnect(req) {
|
|
2233
2490
|
const { url, api_key } = req.body;
|
|
2234
2491
|
if (!url || !api_key) {
|
|
@@ -2313,7 +2570,9 @@ function createTeamHandlers(deps) {
|
|
|
2313
2570
|
deployed_worker_version: config.team.deployed_worker_version ?? null,
|
|
2314
2571
|
worker_update_available: config.team.enabled ? config.team.deployed_worker_version !== getPluginVersion() : false,
|
|
2315
2572
|
schema_version: SCHEMA_VERSION,
|
|
2316
|
-
sync_protocol_version: SYNC_PROTOCOL_VERSION
|
|
2573
|
+
sync_protocol_version: SYNC_PROTOCOL_VERSION,
|
|
2574
|
+
mcp_token: client?.getMcpToken() ?? null,
|
|
2575
|
+
mcp_endpoint: client?.getMcpEndpoint() ?? null
|
|
2317
2576
|
}
|
|
2318
2577
|
};
|
|
2319
2578
|
}
|
|
@@ -2326,11 +2585,17 @@ function createTeamHandlers(deps) {
|
|
|
2326
2585
|
return { body: { retried: count } };
|
|
2327
2586
|
}
|
|
2328
2587
|
async function handleUpgradeWorker(_req) {
|
|
2329
|
-
const { upgradeWorker } = await import("./team-
|
|
2588
|
+
const { upgradeWorker } = await import("./team-DPNP2RN7.js");
|
|
2589
|
+
logger.info("team-sync.upgrade.start", "Starting worker upgrade");
|
|
2330
2590
|
const result = upgradeWorker(vaultDir);
|
|
2331
2591
|
if (!result.success) {
|
|
2592
|
+
logger.error("team-sync.upgrade.failed", "Worker upgrade failed", { error: result.error });
|
|
2332
2593
|
return { status: 500, body: { error: result.error } };
|
|
2333
2594
|
}
|
|
2595
|
+
logger.info("team-sync.upgrade.complete", "Worker upgrade complete", {
|
|
2596
|
+
worker_url: result.worker_url,
|
|
2597
|
+
version: result.version
|
|
2598
|
+
});
|
|
2334
2599
|
if (result.worker_url && deps.getTeamClient()) {
|
|
2335
2600
|
const secrets = readSecrets(vaultDir);
|
|
2336
2601
|
const apiKey = secrets[TEAM_API_KEY_SECRET];
|
|
@@ -2345,7 +2610,28 @@ function createTeamHandlers(deps) {
|
|
|
2345
2610
|
}
|
|
2346
2611
|
return { body: result };
|
|
2347
2612
|
}
|
|
2348
|
-
|
|
2613
|
+
async function handleRotateMcpToken(_req) {
|
|
2614
|
+
const client = deps.getTeamClient();
|
|
2615
|
+
if (!client) {
|
|
2616
|
+
return {
|
|
2617
|
+
status: 400,
|
|
2618
|
+
body: { error: "Team sync not connected" }
|
|
2619
|
+
};
|
|
2620
|
+
}
|
|
2621
|
+
try {
|
|
2622
|
+
const token = await client.rotateMcpToken();
|
|
2623
|
+
logger.info("team-sync.mcp-token.rotated", "MCP access token rotated");
|
|
2624
|
+
return { body: { token } };
|
|
2625
|
+
} catch (err) {
|
|
2626
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2627
|
+
logger.error("team-sync.mcp-token.rotate-failed", "MCP token rotation failed", { error: message });
|
|
2628
|
+
return {
|
|
2629
|
+
status: 500,
|
|
2630
|
+
body: { error: message }
|
|
2631
|
+
};
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
return { handleConnect, handleDisconnect, handleStatus, handleBackfill, handleRetryFailed, handleUpgradeWorker, handleRotateMcpToken };
|
|
2349
2635
|
}
|
|
2350
2636
|
|
|
2351
2637
|
// src/daemon/api/session-lifecycle.ts
|
|
@@ -2425,8 +2711,8 @@ function createSessionLifecycleHandlers(deps) {
|
|
|
2425
2711
|
}
|
|
2426
2712
|
|
|
2427
2713
|
// src/daemon/api/skills.ts
|
|
2428
|
-
import
|
|
2429
|
-
import
|
|
2714
|
+
import fs13 from "fs";
|
|
2715
|
+
import path14 from "path";
|
|
2430
2716
|
|
|
2431
2717
|
// src/db/queries/skill-usage.ts
|
|
2432
2718
|
var USAGE_COLUMNS = [
|
|
@@ -2593,15 +2879,15 @@ function createSkillRecordDeleteHandler(deps) {
|
|
|
2593
2879
|
if (result.body?.deleted) {
|
|
2594
2880
|
const record = result.body;
|
|
2595
2881
|
if (record.name) {
|
|
2596
|
-
const projectRoot =
|
|
2597
|
-
const skillDir =
|
|
2882
|
+
const projectRoot = path14.resolve(vaultDir, "..");
|
|
2883
|
+
const skillDir = path14.resolve(projectRoot, ".agents", "skills", record.name);
|
|
2598
2884
|
try {
|
|
2599
|
-
|
|
2885
|
+
fs13.rmSync(skillDir, { recursive: true, force: true });
|
|
2600
2886
|
} catch (err) {
|
|
2601
2887
|
logger.warn(LOG_KINDS.PROCESSOR_BATCH, "Failed to remove skill directory", { name: record.name, error: String(err) });
|
|
2602
2888
|
}
|
|
2603
2889
|
try {
|
|
2604
|
-
const { syncSkillSymlinks } = await import("./installer-
|
|
2890
|
+
const { syncSkillSymlinks } = await import("./installer-BWJED3ED.js");
|
|
2605
2891
|
syncSkillSymlinks(projectRoot, record.name, { remove: true });
|
|
2606
2892
|
} catch (err) {
|
|
2607
2893
|
logger.warn(LOG_KINDS.PROCESSOR_BATCH, "Failed to remove skill symlinks", { name: record.name, error: String(err) });
|
|
@@ -2854,12 +3140,12 @@ async function handleGetModels(req) {
|
|
|
2854
3140
|
|
|
2855
3141
|
// src/daemon/api/stats.ts
|
|
2856
3142
|
import { createHash as createHash2 } from "crypto";
|
|
2857
|
-
import
|
|
2858
|
-
import
|
|
3143
|
+
import fs14 from "fs";
|
|
3144
|
+
import path15 from "path";
|
|
2859
3145
|
function computeConfigHash(vaultDir) {
|
|
2860
3146
|
try {
|
|
2861
|
-
const configPath =
|
|
2862
|
-
const raw =
|
|
3147
|
+
const configPath = path15.join(vaultDir, CONFIG_FILENAME);
|
|
3148
|
+
const raw = fs14.readFileSync(configPath, "utf-8");
|
|
2863
3149
|
return createHash2("md5").update(raw).digest("hex");
|
|
2864
3150
|
} catch {
|
|
2865
3151
|
return "";
|
|
@@ -4212,6 +4498,13 @@ var EmbeddingManager = class {
|
|
|
4212
4498
|
searchVectors(query, options) {
|
|
4213
4499
|
return this.vectorStore.search(query, options);
|
|
4214
4500
|
}
|
|
4501
|
+
/**
|
|
4502
|
+
* Compute pairwise cosine similarity between all vectors in a namespace.
|
|
4503
|
+
* Used by the evolve instruction builder to find semantically overlapping skills.
|
|
4504
|
+
*/
|
|
4505
|
+
pairwiseSimilarity(namespace, threshold) {
|
|
4506
|
+
return this.vectorStore.pairwiseSimilarity(namespace, threshold);
|
|
4507
|
+
}
|
|
4215
4508
|
// -------------------------------------------------------------------------
|
|
4216
4509
|
// Private helpers
|
|
4217
4510
|
// -------------------------------------------------------------------------
|
|
@@ -4482,6 +4775,48 @@ var SqliteVecVectorStore = class {
|
|
|
4482
4775
|
const rows = this.embeddedIdsStmt.all(namespace);
|
|
4483
4776
|
return rows.map((r) => r.record_id);
|
|
4484
4777
|
}
|
|
4778
|
+
/**
|
|
4779
|
+
* Compute pairwise cosine similarity between all vectors in a namespace.
|
|
4780
|
+
* Returns pairs above the threshold, sorted by similarity DESC.
|
|
4781
|
+
*
|
|
4782
|
+
* Uses sqlite-vec's KNN search: for each vector, find the top-K nearest
|
|
4783
|
+
* neighbors within the same namespace. O(n * K) where K is small.
|
|
4784
|
+
*/
|
|
4785
|
+
pairwiseSimilarity(namespace, threshold = 0.5) {
|
|
4786
|
+
this.validateNamespace(namespace);
|
|
4787
|
+
const ns = namespace;
|
|
4788
|
+
const allRows = this.db.prepare(
|
|
4789
|
+
`SELECT record_id, embedding FROM vec_${ns}`
|
|
4790
|
+
).all();
|
|
4791
|
+
if (allRows.length < 2) return [];
|
|
4792
|
+
const pairs = [];
|
|
4793
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4794
|
+
const searchStmt = this.searchStmts.get(ns);
|
|
4795
|
+
for (const row of allRows) {
|
|
4796
|
+
const results = searchStmt.all(
|
|
4797
|
+
row.embedding,
|
|
4798
|
+
// Use the raw embedding as the query vector
|
|
4799
|
+
allRows.length
|
|
4800
|
+
// K = all rows to get exhaustive comparison
|
|
4801
|
+
);
|
|
4802
|
+
for (const match of results) {
|
|
4803
|
+
if (match.record_id === row.record_id) continue;
|
|
4804
|
+
const pairKey = [row.record_id, match.record_id].sort().join("|");
|
|
4805
|
+
if (seen.has(pairKey)) continue;
|
|
4806
|
+
seen.add(pairKey);
|
|
4807
|
+
const similarity = cosineDistanceToSimilarity(match.distance);
|
|
4808
|
+
if (similarity >= threshold) {
|
|
4809
|
+
pairs.push({
|
|
4810
|
+
idA: row.record_id,
|
|
4811
|
+
idB: match.record_id,
|
|
4812
|
+
similarity: Math.round(similarity * 1e3) / 1e3
|
|
4813
|
+
});
|
|
4814
|
+
}
|
|
4815
|
+
}
|
|
4816
|
+
}
|
|
4817
|
+
pairs.sort((a, b) => b.similarity - a.similarity);
|
|
4818
|
+
return pairs;
|
|
4819
|
+
}
|
|
4485
4820
|
// -------------------------------------------------------------------------
|
|
4486
4821
|
// Lifecycle
|
|
4487
4822
|
// -------------------------------------------------------------------------
|
|
@@ -4619,6 +4954,12 @@ function planMetadata(row) {
|
|
|
4619
4954
|
...row.source_path != null ? { source_path: row.source_path } : {}
|
|
4620
4955
|
};
|
|
4621
4956
|
}
|
|
4957
|
+
function skillRecordMetadata(row) {
|
|
4958
|
+
return {
|
|
4959
|
+
...row.status != null ? { status: row.status } : {},
|
|
4960
|
+
...row.name != null ? { name: row.name } : {}
|
|
4961
|
+
};
|
|
4962
|
+
}
|
|
4622
4963
|
function metadataFor(namespace, row) {
|
|
4623
4964
|
switch (namespace) {
|
|
4624
4965
|
case "sessions":
|
|
@@ -4629,6 +4970,8 @@ function metadataFor(namespace, row) {
|
|
|
4629
4970
|
return planMetadata(row);
|
|
4630
4971
|
case "artifacts":
|
|
4631
4972
|
return emptyMetadata();
|
|
4973
|
+
case "skill_records":
|
|
4974
|
+
return skillRecordMetadata(row);
|
|
4632
4975
|
}
|
|
4633
4976
|
}
|
|
4634
4977
|
var SqliteRecordSource = class {
|
|
@@ -4643,6 +4986,9 @@ var SqliteRecordSource = class {
|
|
|
4643
4986
|
if (namespace === "spores") {
|
|
4644
4987
|
return this.getUnembeddedActiveSpores(limit);
|
|
4645
4988
|
}
|
|
4989
|
+
if (namespace === "skill_records") {
|
|
4990
|
+
return this.getUnembeddedActiveSkillRecords(limit);
|
|
4991
|
+
}
|
|
4646
4992
|
const rows = getUnembedded(namespace, limit);
|
|
4647
4993
|
const db = getDatabase();
|
|
4648
4994
|
return rows.map((row) => {
|
|
@@ -4689,6 +5035,12 @@ var SqliteRecordSource = class {
|
|
|
4689
5035
|
).all();
|
|
4690
5036
|
return rows.map((r) => r.id);
|
|
4691
5037
|
}
|
|
5038
|
+
case "skill_records": {
|
|
5039
|
+
const rows = db.prepare(
|
|
5040
|
+
`SELECT id FROM skill_records WHERE status = ?`
|
|
5041
|
+
).all(ACTIVE_STATUS2);
|
|
5042
|
+
return rows.map((r) => r.id);
|
|
5043
|
+
}
|
|
4692
5044
|
}
|
|
4693
5045
|
}
|
|
4694
5046
|
/**
|
|
@@ -4743,7 +5095,7 @@ var SqliteRecordSource = class {
|
|
|
4743
5095
|
assertValidTable(namespace);
|
|
4744
5096
|
const db = getDatabase();
|
|
4745
5097
|
const contentFilter = namespace === "sessions" ? " AND summary IS NOT NULL" : "";
|
|
4746
|
-
const statusFilter = namespace === "spores" ? ` AND status = '${ACTIVE_STATUS2}'` : "";
|
|
5098
|
+
const statusFilter = namespace === "spores" || namespace === "skill_records" ? ` AND status = '${ACTIVE_STATUS2}'` : "";
|
|
4747
5099
|
const row = db.prepare(
|
|
4748
5100
|
`SELECT COUNT(*) AS cnt FROM ${namespace} WHERE embedded = 0${contentFilter}${statusFilter}`
|
|
4749
5101
|
).get();
|
|
@@ -4768,20 +5120,36 @@ var SqliteRecordSource = class {
|
|
|
4768
5120
|
metadata: sporeMetadata(row)
|
|
4769
5121
|
}));
|
|
4770
5122
|
}
|
|
5123
|
+
/** Custom query for skill_records: embedded=0 AND status='active'. */
|
|
5124
|
+
getUnembeddedActiveSkillRecords(limit) {
|
|
5125
|
+
const db = getDatabase();
|
|
5126
|
+
const rows = db.prepare(
|
|
5127
|
+
`SELECT id, description AS text, status, name
|
|
5128
|
+
FROM skill_records
|
|
5129
|
+
WHERE embedded = 0 AND status = ?
|
|
5130
|
+
ORDER BY created_at ASC
|
|
5131
|
+
LIMIT ?`
|
|
5132
|
+
).all(ACTIVE_STATUS2, limit);
|
|
5133
|
+
return rows.map((row) => ({
|
|
5134
|
+
id: String(row.id),
|
|
5135
|
+
text: row.text,
|
|
5136
|
+
metadata: skillRecordMetadata(row)
|
|
5137
|
+
}));
|
|
5138
|
+
}
|
|
4771
5139
|
};
|
|
4772
5140
|
|
|
4773
5141
|
// src/daemon/database/manager.ts
|
|
4774
|
-
import
|
|
5142
|
+
import fs16 from "fs";
|
|
4775
5143
|
|
|
4776
5144
|
// src/db/queries/database.ts
|
|
4777
|
-
import
|
|
5145
|
+
import fs15 from "fs";
|
|
4778
5146
|
function pragmaScalar(name) {
|
|
4779
5147
|
const db = getDatabase();
|
|
4780
5148
|
return db.pragma(name, { simple: true });
|
|
4781
5149
|
}
|
|
4782
5150
|
function safeFileSize(filePath) {
|
|
4783
5151
|
try {
|
|
4784
|
-
return
|
|
5152
|
+
return fs15.statSync(filePath).size;
|
|
4785
5153
|
} catch (err) {
|
|
4786
5154
|
if (err.code === "ENOENT") return 0;
|
|
4787
5155
|
throw err;
|
|
@@ -5053,7 +5421,7 @@ var DatabaseMaintenanceManager = class {
|
|
|
5053
5421
|
}
|
|
5054
5422
|
async vacuum() {
|
|
5055
5423
|
const size_before = this.fileSize();
|
|
5056
|
-
const stats = await
|
|
5424
|
+
const stats = await fs16.promises.statfs(this.vaultDir);
|
|
5057
5425
|
const free_bytes = Number(stats.bavail) * Number(stats.bsize);
|
|
5058
5426
|
const required_bytes = size_before * VACUUM_FREE_SPACE_MULTIPLIER;
|
|
5059
5427
|
if (free_bytes < required_bytes) {
|
|
@@ -5101,7 +5469,7 @@ var DatabaseMaintenanceManager = class {
|
|
|
5101
5469
|
}
|
|
5102
5470
|
fileSize() {
|
|
5103
5471
|
try {
|
|
5104
|
-
return
|
|
5472
|
+
return fs16.statSync(this.dbPath).size;
|
|
5105
5473
|
} catch {
|
|
5106
5474
|
return 0;
|
|
5107
5475
|
}
|
|
@@ -5143,6 +5511,13 @@ function registerBuiltinDomains() {
|
|
|
5143
5511
|
{ id: "mycelium.spore.created", label: "New spore extracted", defaultMode: "summary", defaultLevel: "info" }
|
|
5144
5512
|
]
|
|
5145
5513
|
});
|
|
5514
|
+
register({
|
|
5515
|
+
domain: "daemon",
|
|
5516
|
+
label: "Daemon",
|
|
5517
|
+
types: [
|
|
5518
|
+
{ id: "daemon.version_sync", label: "Version sync restart", defaultMode: "banner", defaultLevel: "info" }
|
|
5519
|
+
]
|
|
5520
|
+
});
|
|
5146
5521
|
}
|
|
5147
5522
|
|
|
5148
5523
|
// src/daemon/api/notifications.ts
|
|
@@ -5487,6 +5862,9 @@ function testAnthropic() {
|
|
|
5487
5862
|
return { ok: true };
|
|
5488
5863
|
}
|
|
5489
5864
|
|
|
5865
|
+
// src/daemon/task-scheduling.ts
|
|
5866
|
+
import { resolve } from "path";
|
|
5867
|
+
|
|
5490
5868
|
// src/daemon/task-scheduler.ts
|
|
5491
5869
|
function resolveSchedule(yamlSchedule, configOverride) {
|
|
5492
5870
|
if (!configOverride?.schedule) return yamlSchedule;
|
|
@@ -5544,8 +5922,12 @@ async function registerScheduledTasks(powerManager, deps) {
|
|
|
5544
5922
|
logger.info(LOG_KINDS.AGENT_RUN, "Scheduled agent tasks disabled globally (agent.scheduled_tasks_enabled: false)");
|
|
5545
5923
|
return;
|
|
5546
5924
|
}
|
|
5547
|
-
const { loadAllTasks: loadAllTasks2 } = await import("./registry-
|
|
5925
|
+
const { loadAllTasks: loadAllTasks2 } = await import("./registry-O2NZLO3V.js");
|
|
5548
5926
|
const allTasks = Array.from(loadAllTasks2(definitionsDir, vaultDir).values());
|
|
5927
|
+
const taskAgentMap = /* @__PURE__ */ new Map();
|
|
5928
|
+
for (const task of allTasks) {
|
|
5929
|
+
taskAgentMap.set(task.name, task.agent);
|
|
5930
|
+
}
|
|
5549
5931
|
const initialLastRuns = {};
|
|
5550
5932
|
try {
|
|
5551
5933
|
const recentRuns = getDatabase().prepare(
|
|
@@ -5566,9 +5948,10 @@ async function registerScheduledTasks(powerManager, deps) {
|
|
|
5566
5948
|
else runningTasks.delete(name);
|
|
5567
5949
|
},
|
|
5568
5950
|
runTask: async (taskName) => {
|
|
5569
|
-
const { runAgent } = await import("./executor-
|
|
5951
|
+
const { runAgent } = await import("./executor-UYIZC3L5.js");
|
|
5570
5952
|
const taskConfig = config.agent.tasks?.[taskName];
|
|
5571
|
-
const
|
|
5953
|
+
const projectRoot = resolve(vaultDir, "..");
|
|
5954
|
+
const built = buildTaskInstruction(taskName, taskConfig?.params, taskAgentMap.get(taskName), projectRoot, embeddingManager);
|
|
5572
5955
|
if (isInstructionRequiredTask(taskName) && !built) {
|
|
5573
5956
|
logger.info(
|
|
5574
5957
|
LOG_KINDS.AGENT_RUN,
|
|
@@ -5735,7 +6118,7 @@ function createMcpProxyHandlers(deps) {
|
|
|
5735
6118
|
name: USER_AGENT_NAME,
|
|
5736
6119
|
created_at: now
|
|
5737
6120
|
});
|
|
5738
|
-
const { insertResolutionEvent } = await import("./resolution-events-
|
|
6121
|
+
const { insertResolutionEvent } = await import("./resolution-events-XWYLLDRK.js");
|
|
5739
6122
|
const resolutionId = `res-${randomBytes(RESOLUTION_ID_RANDOM_BYTES).toString("hex")}`;
|
|
5740
6123
|
insertResolutionEvent({
|
|
5741
6124
|
id: resolutionId,
|
|
@@ -5817,6 +6200,7 @@ function createMcpProxyHandlers(deps) {
|
|
|
5817
6200
|
}
|
|
5818
6201
|
|
|
5819
6202
|
// src/daemon/api/agent-runs.ts
|
|
6203
|
+
import { resolve as resolve2 } from "path";
|
|
5820
6204
|
var AGENT_RUNS_DEFAULT_LIMIT = 50;
|
|
5821
6205
|
var AgentRunBody = external_exports.object({
|
|
5822
6206
|
task: external_exports.string().optional(),
|
|
@@ -5843,9 +6227,11 @@ function createAgentRunHandlers(deps) {
|
|
|
5843
6227
|
let built;
|
|
5844
6228
|
try {
|
|
5845
6229
|
const taskParams = mycoConfig.agent.tasks?.[task]?.params;
|
|
5846
|
-
|
|
6230
|
+
const projectRoot = resolve2(vaultDir, "..");
|
|
6231
|
+
built = buildTaskInstruction(task, taskParams, agentId, projectRoot, embeddingManager);
|
|
5847
6232
|
} catch {
|
|
5848
|
-
|
|
6233
|
+
const projectRoot = resolve2(vaultDir, "..");
|
|
6234
|
+
built = buildTaskInstruction(task, void 0, agentId, projectRoot, embeddingManager);
|
|
5849
6235
|
}
|
|
5850
6236
|
instruction = built?.instruction;
|
|
5851
6237
|
runContext = built?.context;
|
|
@@ -5860,7 +6246,7 @@ function createAgentRunHandlers(deps) {
|
|
|
5860
6246
|
};
|
|
5861
6247
|
}
|
|
5862
6248
|
}
|
|
5863
|
-
const { runAgent } = await import("./executor-
|
|
6249
|
+
const { runAgent } = await import("./executor-UYIZC3L5.js");
|
|
5864
6250
|
const resultPromise = runAgent(vaultDir, {
|
|
5865
6251
|
task,
|
|
5866
6252
|
instruction,
|
|
@@ -5929,8 +6315,8 @@ function createAgentRunHandlers(deps) {
|
|
|
5929
6315
|
}
|
|
5930
6316
|
|
|
5931
6317
|
// src/daemon/api/attachments.ts
|
|
5932
|
-
import
|
|
5933
|
-
import
|
|
6318
|
+
import fs17 from "fs";
|
|
6319
|
+
import path16 from "path";
|
|
5934
6320
|
var ATTACHMENT_MEDIA_TYPES = {
|
|
5935
6321
|
png: "image/png",
|
|
5936
6322
|
jpg: "image/jpeg",
|
|
@@ -5950,14 +6336,14 @@ function createAttachmentHandler(deps) {
|
|
|
5950
6336
|
const contentType2 = att.media_type ?? "application/octet-stream";
|
|
5951
6337
|
return { status: 200, headers: { "Content-Type": contentType2 }, body: att.data };
|
|
5952
6338
|
}
|
|
5953
|
-
const filePath =
|
|
6339
|
+
const filePath = path16.join(vaultDir, "attachments", filename);
|
|
5954
6340
|
let diskData;
|
|
5955
6341
|
try {
|
|
5956
|
-
diskData =
|
|
6342
|
+
diskData = fs17.readFileSync(filePath);
|
|
5957
6343
|
} catch {
|
|
5958
6344
|
return { status: 404, body: { error: "not_found" } };
|
|
5959
6345
|
}
|
|
5960
|
-
const ext =
|
|
6346
|
+
const ext = path16.extname(filename).slice(1).toLowerCase();
|
|
5961
6347
|
const contentType = ATTACHMENT_MEDIA_TYPES[ext] ?? "application/octet-stream";
|
|
5962
6348
|
return { status: 200, headers: { "Content-Type": contentType }, body: diskData };
|
|
5963
6349
|
}
|
|
@@ -5965,19 +6351,19 @@ function createAttachmentHandler(deps) {
|
|
|
5965
6351
|
}
|
|
5966
6352
|
|
|
5967
6353
|
// src/daemon/log-reconcile.ts
|
|
5968
|
-
import
|
|
5969
|
-
import
|
|
6354
|
+
import fs18 from "fs";
|
|
6355
|
+
import path17 from "path";
|
|
5970
6356
|
function reconcileLogBuffer(logDir, sinceTimestamp) {
|
|
5971
6357
|
let replayed = 0;
|
|
5972
6358
|
const files = [];
|
|
5973
6359
|
for (let i = 3; i >= 1; i--) {
|
|
5974
|
-
const rotated =
|
|
5975
|
-
if (
|
|
6360
|
+
const rotated = path17.join(logDir, `daemon.${i}.log`);
|
|
6361
|
+
if (fs18.existsSync(rotated)) files.push(rotated);
|
|
5976
6362
|
}
|
|
5977
|
-
const current =
|
|
5978
|
-
if (
|
|
6363
|
+
const current = path17.join(logDir, "daemon.log");
|
|
6364
|
+
if (fs18.existsSync(current)) files.push(current);
|
|
5979
6365
|
for (const file of files) {
|
|
5980
|
-
const content =
|
|
6366
|
+
const content = fs18.readFileSync(file, "utf-8");
|
|
5981
6367
|
for (const line of content.split("\n")) {
|
|
5982
6368
|
if (!line.trim()) continue;
|
|
5983
6369
|
try {
|
|
@@ -6256,8 +6642,8 @@ function registerPowerJobs(powerManager, deps) {
|
|
|
6256
6642
|
}
|
|
6257
6643
|
|
|
6258
6644
|
// src/daemon/reconciliation.ts
|
|
6259
|
-
import
|
|
6260
|
-
import
|
|
6645
|
+
import fs19 from "fs";
|
|
6646
|
+
import path18 from "path";
|
|
6261
6647
|
|
|
6262
6648
|
// src/daemon/event-handlers.ts
|
|
6263
6649
|
var TOOL_INPUT_STORE_LIMIT = 4e3;
|
|
@@ -6426,10 +6812,10 @@ function createReconciler({ bufferDir, logger }) {
|
|
|
6426
6812
|
function reconcileSession(sessionId) {
|
|
6427
6813
|
if (reconciledSessions.has(sessionId)) return;
|
|
6428
6814
|
reconciledSessions.add(sessionId);
|
|
6429
|
-
const bufferPath =
|
|
6815
|
+
const bufferPath = path18.join(bufferDir, `${sessionId}.jsonl`);
|
|
6430
6816
|
let content;
|
|
6431
6817
|
try {
|
|
6432
|
-
content =
|
|
6818
|
+
content = fs19.readFileSync(bufferPath, "utf-8").trim();
|
|
6433
6819
|
} catch {
|
|
6434
6820
|
return;
|
|
6435
6821
|
}
|
|
@@ -6498,7 +6884,7 @@ function createReconciler({ bufferDir, logger }) {
|
|
|
6498
6884
|
}
|
|
6499
6885
|
|
|
6500
6886
|
// src/daemon/stop-processing.ts
|
|
6501
|
-
import
|
|
6887
|
+
import fs20 from "fs";
|
|
6502
6888
|
|
|
6503
6889
|
// src/daemon/capture-images.ts
|
|
6504
6890
|
var SESSION_SHORT_LEN = 6;
|
|
@@ -6535,6 +6921,78 @@ function captureBatchImages(input) {
|
|
|
6535
6921
|
}
|
|
6536
6922
|
}
|
|
6537
6923
|
|
|
6924
|
+
// src/daemon/plan-capture.ts
|
|
6925
|
+
import { createHash as createHash4 } from "crypto";
|
|
6926
|
+
import os7 from "os";
|
|
6927
|
+
import path19 from "path";
|
|
6928
|
+
function extractTaggedPlans(text, tags) {
|
|
6929
|
+
const results = [];
|
|
6930
|
+
for (const tag of tags) {
|
|
6931
|
+
const regex = new RegExp(`<${tag}>\\n?([\\s\\S]*?)\\n?</${tag}>`, "g");
|
|
6932
|
+
let match;
|
|
6933
|
+
while ((match = regex.exec(text)) !== null) {
|
|
6934
|
+
const content = match[1].trim();
|
|
6935
|
+
if (content) results.push({ tag, content });
|
|
6936
|
+
}
|
|
6937
|
+
}
|
|
6938
|
+
return results;
|
|
6939
|
+
}
|
|
6940
|
+
var TRANSCRIPT_SOURCE_PREFIX = "transcript:";
|
|
6941
|
+
var FILE_WRITE_TOOLS = /* @__PURE__ */ new Set([
|
|
6942
|
+
"Write",
|
|
6943
|
+
"Edit",
|
|
6944
|
+
"Create",
|
|
6945
|
+
"write",
|
|
6946
|
+
"edit",
|
|
6947
|
+
"patch",
|
|
6948
|
+
"create"
|
|
6949
|
+
]);
|
|
6950
|
+
var HEADING_REGEX = /^#\s+(.+)$/m;
|
|
6951
|
+
var PLAN_ID_HASH_LENGTH = 16;
|
|
6952
|
+
function isInPlanDirectory(filePath, watchDirs, projectRoot) {
|
|
6953
|
+
const abs = path19.isAbsolute(filePath) ? filePath : path19.resolve(projectRoot, filePath);
|
|
6954
|
+
return watchDirs.some((dir) => {
|
|
6955
|
+
const expanded = dir.startsWith("~/") ? path19.join(os7.homedir(), dir.slice(2)) : dir;
|
|
6956
|
+
const absDir = path19.isAbsolute(expanded) ? expanded : path19.resolve(projectRoot, expanded);
|
|
6957
|
+
const prefix = absDir.endsWith(path19.sep) ? absDir : absDir + path19.sep;
|
|
6958
|
+
return abs === absDir || abs.startsWith(prefix);
|
|
6959
|
+
});
|
|
6960
|
+
}
|
|
6961
|
+
function isPlanWriteEvent(toolName, toolInput, config) {
|
|
6962
|
+
if (!FILE_WRITE_TOOLS.has(toolName)) return null;
|
|
6963
|
+
const filePath = toolInput?.file_path ?? toolInput?.path ?? toolInput?.filePath;
|
|
6964
|
+
if (typeof filePath !== "string") return null;
|
|
6965
|
+
if (!isInPlanDirectory(filePath, config.watchDirs, config.projectRoot)) return null;
|
|
6966
|
+
if (config.extensions?.length) {
|
|
6967
|
+
const ext = path19.extname(filePath).toLowerCase();
|
|
6968
|
+
if (!config.extensions.includes(ext)) return null;
|
|
6969
|
+
}
|
|
6970
|
+
return filePath;
|
|
6971
|
+
}
|
|
6972
|
+
function parsePlanTitle(content, filename) {
|
|
6973
|
+
const match = HEADING_REGEX.exec(content);
|
|
6974
|
+
if (match) return match[1].trim();
|
|
6975
|
+
return filename ?? null;
|
|
6976
|
+
}
|
|
6977
|
+
function capturePlan(input) {
|
|
6978
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
6979
|
+
const contentHash = createHash4(CONTENT_HASH_ALGORITHM).update(input.content).digest("hex");
|
|
6980
|
+
const id = createHash4("md5").update(input.sourcePath).digest("hex").slice(0, PLAN_ID_HASH_LENGTH);
|
|
6981
|
+
const title = parsePlanTitle(input.content, path19.basename(input.sourcePath));
|
|
6982
|
+
return upsertPlan({
|
|
6983
|
+
id,
|
|
6984
|
+
title,
|
|
6985
|
+
content: input.content,
|
|
6986
|
+
source_path: input.sourcePath,
|
|
6987
|
+
session_id: input.sessionId,
|
|
6988
|
+
prompt_batch_id: input.promptBatchId ?? null,
|
|
6989
|
+
content_hash: contentHash,
|
|
6990
|
+
status: "active",
|
|
6991
|
+
created_at: now,
|
|
6992
|
+
updated_at: now
|
|
6993
|
+
});
|
|
6994
|
+
}
|
|
6995
|
+
|
|
6538
6996
|
// src/daemon/skill-usage.ts
|
|
6539
6997
|
import crypto from "crypto";
|
|
6540
6998
|
var SKILL_USAGE_DETECTION_ENABLED = false;
|
|
@@ -6604,14 +7062,14 @@ function createStopProcessor(deps) {
|
|
|
6604
7062
|
const StopBody = external_exports.object({
|
|
6605
7063
|
session_id: external_exports.string(),
|
|
6606
7064
|
user: external_exports.string().optional(),
|
|
6607
|
-
transcript_path: external_exports.string().
|
|
6608
|
-
last_assistant_message: external_exports.string().
|
|
7065
|
+
transcript_path: external_exports.string().nullish(),
|
|
7066
|
+
last_assistant_message: external_exports.string().nullish()
|
|
6609
7067
|
});
|
|
6610
7068
|
async function triggerTitleSummary(sessionId) {
|
|
6611
7069
|
if (config.agent.summary_batch_interval <= 0) return;
|
|
6612
7070
|
if (config.agent.event_tasks_enabled === false) return;
|
|
6613
7071
|
try {
|
|
6614
|
-
const { runAgent } = await import("./executor-
|
|
7072
|
+
const { runAgent } = await import("./executor-UYIZC3L5.js");
|
|
6615
7073
|
runAgent(vaultDir, {
|
|
6616
7074
|
task: "title-summary",
|
|
6617
7075
|
instruction: `Process session ${sessionId} only`,
|
|
@@ -6701,7 +7159,7 @@ function createStopProcessor(deps) {
|
|
|
6701
7159
|
let transcriptText = null;
|
|
6702
7160
|
if (hookTranscriptPath) {
|
|
6703
7161
|
try {
|
|
6704
|
-
transcriptText =
|
|
7162
|
+
transcriptText = fs20.readFileSync(hookTranscriptPath, "utf-8");
|
|
6705
7163
|
} catch {
|
|
6706
7164
|
}
|
|
6707
7165
|
}
|
|
@@ -6727,6 +7185,33 @@ function createStopProcessor(deps) {
|
|
|
6727
7185
|
logger.warn(LOG_KINDS.PROCESSOR_BATCH, "Failed to populate batch responses", { error: String(err) });
|
|
6728
7186
|
}
|
|
6729
7187
|
}
|
|
7188
|
+
if (deps.planTags.length > 0) {
|
|
7189
|
+
for (const turn of allTurns) {
|
|
7190
|
+
if (!turn.aiResponse) continue;
|
|
7191
|
+
const taggedPlans = extractTaggedPlans(turn.aiResponse, deps.planTags);
|
|
7192
|
+
for (const { tag, content } of taggedPlans) {
|
|
7193
|
+
try {
|
|
7194
|
+
capturePlan({
|
|
7195
|
+
sourcePath: `${TRANSCRIPT_SOURCE_PREFIX}${tag}`,
|
|
7196
|
+
content,
|
|
7197
|
+
sessionId,
|
|
7198
|
+
promptBatchId: latestBatch?.id ?? null
|
|
7199
|
+
});
|
|
7200
|
+
logger.info(LOG_KINDS.CAPTURE_PLAN, "Plan captured from transcript tag", {
|
|
7201
|
+
session_id: sessionId,
|
|
7202
|
+
tag,
|
|
7203
|
+
content_length: content.length
|
|
7204
|
+
});
|
|
7205
|
+
} catch (err) {
|
|
7206
|
+
logger.warn(LOG_KINDS.CAPTURE_PLAN, "Failed to capture plan from transcript tag", {
|
|
7207
|
+
session_id: sessionId,
|
|
7208
|
+
tag,
|
|
7209
|
+
error: err.message
|
|
7210
|
+
});
|
|
7211
|
+
}
|
|
7212
|
+
}
|
|
7213
|
+
}
|
|
7214
|
+
}
|
|
6730
7215
|
if (!hasTitle) {
|
|
6731
7216
|
triggerTitleSummary(sessionId);
|
|
6732
7217
|
}
|
|
@@ -6766,11 +7251,18 @@ function createStopProcessor(deps) {
|
|
|
6766
7251
|
}
|
|
6767
7252
|
const handleStopRoute = async (req) => {
|
|
6768
7253
|
const { session_id: sessionId, user, transcript_path: hookTranscriptPath, last_assistant_message: lastAssistantMessage } = StopBody.parse(req.body);
|
|
6769
|
-
|
|
7254
|
+
const existingSessionMeta = registry.getSession(sessionId);
|
|
7255
|
+
if (!hookTranscriptPath && !existingSessionMeta) {
|
|
7256
|
+
logger.info(LOG_KINDS.HOOKS_STOP, "Stop ignored \u2014 ephemeral sub-invocation", {
|
|
7257
|
+
session_id: sessionId
|
|
7258
|
+
});
|
|
7259
|
+
return { body: { ok: true, ignored: "ephemeral-sub-invocation" } };
|
|
7260
|
+
}
|
|
7261
|
+
if (!existingSessionMeta) {
|
|
6770
7262
|
registry.register(sessionId, { started_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
6771
7263
|
logger.debug(LOG_KINDS.LIFECYCLE_AUTO_REGISTER, "Auto-registered session from stop event", { session_id: sessionId });
|
|
6772
7264
|
}
|
|
6773
|
-
const sessionMeta = registry.getSession(sessionId);
|
|
7265
|
+
const sessionMeta = existingSessionMeta ?? registry.getSession(sessionId);
|
|
6774
7266
|
logger.info(LOG_KINDS.HOOKS_STOP, "Stop received", {
|
|
6775
7267
|
session_id: sessionId,
|
|
6776
7268
|
has_transcript_path: !!hookTranscriptPath,
|
|
@@ -6781,7 +7273,9 @@ function createStopProcessor(deps) {
|
|
|
6781
7273
|
transcript_path: hookTranscriptPath ?? null,
|
|
6782
7274
|
last_message_preview: lastAssistantMessage?.slice(0, LOG_MESSAGE_PREVIEW_CHARS) ?? null
|
|
6783
7275
|
});
|
|
6784
|
-
const
|
|
7276
|
+
const normalizedTranscriptPath = hookTranscriptPath ?? void 0;
|
|
7277
|
+
const normalizedAssistantMessage = lastAssistantMessage ?? void 0;
|
|
7278
|
+
const run = () => processStopEvent(sessionId, user, sessionMeta, normalizedTranscriptPath, normalizedAssistantMessage).catch((err) => {
|
|
6785
7279
|
logger.error(LOG_KINDS.PROCESSOR_SESSION, "Stop processing failed", { session_id: sessionId, error: err.message });
|
|
6786
7280
|
});
|
|
6787
7281
|
const prev = activeStopProcessing ?? Promise.resolve();
|
|
@@ -6801,69 +7295,8 @@ function createStopProcessor(deps) {
|
|
|
6801
7295
|
}
|
|
6802
7296
|
|
|
6803
7297
|
// src/daemon/event-dispatch.ts
|
|
6804
|
-
import
|
|
6805
|
-
import
|
|
6806
|
-
|
|
6807
|
-
// src/daemon/plan-capture.ts
|
|
6808
|
-
import { createHash as createHash4 } from "crypto";
|
|
6809
|
-
import os7 from "os";
|
|
6810
|
-
import path18 from "path";
|
|
6811
|
-
var FILE_WRITE_TOOLS = /* @__PURE__ */ new Set([
|
|
6812
|
-
"Write",
|
|
6813
|
-
"Edit",
|
|
6814
|
-
"Create",
|
|
6815
|
-
"write",
|
|
6816
|
-
"edit",
|
|
6817
|
-
"patch",
|
|
6818
|
-
"create"
|
|
6819
|
-
]);
|
|
6820
|
-
var HEADING_REGEX = /^#\s+(.+)$/m;
|
|
6821
|
-
var PLAN_ID_HASH_LENGTH = 16;
|
|
6822
|
-
function isInPlanDirectory(filePath, watchDirs, projectRoot) {
|
|
6823
|
-
const abs = path18.isAbsolute(filePath) ? filePath : path18.resolve(projectRoot, filePath);
|
|
6824
|
-
return watchDirs.some((dir) => {
|
|
6825
|
-
const expanded = dir.startsWith("~/") ? path18.join(os7.homedir(), dir.slice(2)) : dir;
|
|
6826
|
-
const absDir = path18.isAbsolute(expanded) ? expanded : path18.resolve(projectRoot, expanded);
|
|
6827
|
-
const prefix = absDir.endsWith(path18.sep) ? absDir : absDir + path18.sep;
|
|
6828
|
-
return abs === absDir || abs.startsWith(prefix);
|
|
6829
|
-
});
|
|
6830
|
-
}
|
|
6831
|
-
function isPlanWriteEvent(toolName, toolInput, config) {
|
|
6832
|
-
if (!FILE_WRITE_TOOLS.has(toolName)) return null;
|
|
6833
|
-
const filePath = toolInput?.file_path ?? toolInput?.path ?? toolInput?.filePath;
|
|
6834
|
-
if (typeof filePath !== "string") return null;
|
|
6835
|
-
if (!isInPlanDirectory(filePath, config.watchDirs, config.projectRoot)) return null;
|
|
6836
|
-
if (config.extensions?.length) {
|
|
6837
|
-
const ext = path18.extname(filePath).toLowerCase();
|
|
6838
|
-
if (!config.extensions.includes(ext)) return null;
|
|
6839
|
-
}
|
|
6840
|
-
return filePath;
|
|
6841
|
-
}
|
|
6842
|
-
function parsePlanTitle(content, filename) {
|
|
6843
|
-
const match = HEADING_REGEX.exec(content);
|
|
6844
|
-
if (match) return match[1].trim();
|
|
6845
|
-
return filename ?? null;
|
|
6846
|
-
}
|
|
6847
|
-
function capturePlan(input) {
|
|
6848
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
6849
|
-
const contentHash = createHash4(CONTENT_HASH_ALGORITHM).update(input.content).digest("hex");
|
|
6850
|
-
const id = createHash4("md5").update(input.sourcePath).digest("hex").slice(0, PLAN_ID_HASH_LENGTH);
|
|
6851
|
-
const title = parsePlanTitle(input.content, path18.basename(input.sourcePath));
|
|
6852
|
-
return upsertPlan({
|
|
6853
|
-
id,
|
|
6854
|
-
title,
|
|
6855
|
-
content: input.content,
|
|
6856
|
-
source_path: input.sourcePath,
|
|
6857
|
-
session_id: input.sessionId,
|
|
6858
|
-
prompt_batch_id: input.promptBatchId ?? null,
|
|
6859
|
-
content_hash: contentHash,
|
|
6860
|
-
status: "active",
|
|
6861
|
-
created_at: now,
|
|
6862
|
-
updated_at: now
|
|
6863
|
-
});
|
|
6864
|
-
}
|
|
6865
|
-
|
|
6866
|
-
// src/daemon/event-dispatch.ts
|
|
7298
|
+
import fs21 from "fs";
|
|
7299
|
+
import path20 from "path";
|
|
6867
7300
|
var EventBody = external_exports.object({ type: external_exports.string(), session_id: external_exports.string() }).passthrough();
|
|
6868
7301
|
function createEventDispatcher(deps) {
|
|
6869
7302
|
const {
|
|
@@ -6902,7 +7335,7 @@ function createEventDispatcher(deps) {
|
|
|
6902
7335
|
reconcileSession(event.session_id);
|
|
6903
7336
|
}
|
|
6904
7337
|
if (!sessionBuffers.has(event.session_id)) {
|
|
6905
|
-
const bufferDir =
|
|
7338
|
+
const bufferDir = path20.join(vaultDir, "buffer");
|
|
6906
7339
|
sessionBuffers.set(event.session_id, new EventBuffer(bufferDir, event.session_id));
|
|
6907
7340
|
}
|
|
6908
7341
|
sessionBuffers.get(event.session_id).append(event);
|
|
@@ -6956,10 +7389,10 @@ function createEventDispatcher(deps) {
|
|
|
6956
7389
|
);
|
|
6957
7390
|
if (planFilePath) {
|
|
6958
7391
|
const captureSessionId = event.session_id;
|
|
6959
|
-
|
|
7392
|
+
fs21.promises.readFile(planFilePath, "utf-8").then((planContent) => {
|
|
6960
7393
|
const latestBatch = getLatestBatch(captureSessionId);
|
|
6961
7394
|
capturePlan({
|
|
6962
|
-
sourcePath:
|
|
7395
|
+
sourcePath: path20.relative(projectRoot, planFilePath),
|
|
6963
7396
|
content: planContent,
|
|
6964
7397
|
sessionId: captureSessionId,
|
|
6965
7398
|
promptBatchId: latestBatch?.id ?? null
|
|
@@ -7101,14 +7534,14 @@ function createEventDispatcher(deps) {
|
|
|
7101
7534
|
}
|
|
7102
7535
|
|
|
7103
7536
|
// src/daemon/main.ts
|
|
7104
|
-
import
|
|
7537
|
+
import fs22 from "fs";
|
|
7105
7538
|
import os8 from "os";
|
|
7106
|
-
import
|
|
7539
|
+
import path21 from "path";
|
|
7107
7540
|
function killStaleDaemon(vaultDir, logger) {
|
|
7108
|
-
const daemonJsonPath =
|
|
7541
|
+
const daemonJsonPath = path21.join(vaultDir, "daemon.json");
|
|
7109
7542
|
try {
|
|
7110
|
-
if (!
|
|
7111
|
-
const info = JSON.parse(
|
|
7543
|
+
if (!fs22.existsSync(daemonJsonPath)) return;
|
|
7544
|
+
const info = JSON.parse(fs22.readFileSync(daemonJsonPath, "utf-8"));
|
|
7112
7545
|
if (!info.pid) return;
|
|
7113
7546
|
if (info.pid === process.pid) return;
|
|
7114
7547
|
try {
|
|
@@ -7117,7 +7550,7 @@ function killStaleDaemon(vaultDir, logger) {
|
|
|
7117
7550
|
logger.info(LOG_KINDS.DAEMON_START, "Killed stale daemon", { pid: info.pid });
|
|
7118
7551
|
} catch {
|
|
7119
7552
|
}
|
|
7120
|
-
|
|
7553
|
+
fs22.unlinkSync(daemonJsonPath);
|
|
7121
7554
|
} catch {
|
|
7122
7555
|
}
|
|
7123
7556
|
}
|
|
@@ -7127,18 +7560,19 @@ async function main() {
|
|
|
7127
7560
|
process.stderr.write("Usage: mycod --vault <path>\n");
|
|
7128
7561
|
process.exit(1);
|
|
7129
7562
|
}
|
|
7130
|
-
const vaultDir =
|
|
7563
|
+
const vaultDir = path21.resolve(vaultArg);
|
|
7131
7564
|
loadSecrets(vaultDir);
|
|
7132
7565
|
const config = loadConfig(vaultDir);
|
|
7133
7566
|
const manifests = loadManifests();
|
|
7134
7567
|
const symbiontPlanDirs = manifests.flatMap((m) => m.capture?.planDirs ?? []);
|
|
7568
|
+
const symbiontPlanTags = [...new Set(manifests.flatMap((m) => m.capture?.planTags ?? []))];
|
|
7135
7569
|
const projectRoot = process.cwd();
|
|
7136
7570
|
let planWatchConfig = {
|
|
7137
7571
|
watchDirs: [.../* @__PURE__ */ new Set([...symbiontPlanDirs, ...config.capture.plan_dirs ?? []])],
|
|
7138
7572
|
projectRoot,
|
|
7139
7573
|
extensions: config.capture.artifact_extensions
|
|
7140
7574
|
};
|
|
7141
|
-
const logger = new DaemonLogger(
|
|
7575
|
+
const logger = new DaemonLogger(path21.join(vaultDir, "logs"), {
|
|
7142
7576
|
level: config.daemon.log_level
|
|
7143
7577
|
});
|
|
7144
7578
|
if (config.daemon.log_level === "debug") {
|
|
@@ -7150,12 +7584,68 @@ async function main() {
|
|
|
7150
7584
|
embedding_provider: config.embedding.provider
|
|
7151
7585
|
});
|
|
7152
7586
|
logger.info(LOG_KINDS.CAPTURE_PLAN, "Plan watch directories", { dirs: planWatchConfig.watchDirs });
|
|
7587
|
+
if (symbiontPlanTags.length > 0) {
|
|
7588
|
+
logger.info(LOG_KINDS.CAPTURE_PLAN, "Plan transcript tags", { tags: symbiontPlanTags });
|
|
7589
|
+
}
|
|
7153
7590
|
const machineId = getMachineId(vaultDir);
|
|
7154
7591
|
logger.info(LOG_KINDS.DAEMON_START, "Machine ID resolved", { machine_id: machineId });
|
|
7592
|
+
let globalPrefix = null;
|
|
7593
|
+
try {
|
|
7594
|
+
globalPrefix = resolveGlobalPrefix();
|
|
7595
|
+
logger.debug(LOG_KINDS.DAEMON_START, "npm global prefix resolved", { prefix: globalPrefix });
|
|
7596
|
+
} catch (err) {
|
|
7597
|
+
logger.warn(LOG_KINDS.DAEMON_START, "Failed to resolve npm global prefix", {
|
|
7598
|
+
error: err.message
|
|
7599
|
+
});
|
|
7600
|
+
}
|
|
7601
|
+
const devCliEntry = detectDevBuild(
|
|
7602
|
+
globalPrefix,
|
|
7603
|
+
process.argv[1],
|
|
7604
|
+
fs22.realpathSync
|
|
7605
|
+
);
|
|
7606
|
+
if (devCliEntry) {
|
|
7607
|
+
setDevBuildCliEntry(devCliEntry);
|
|
7608
|
+
globalPrefix = null;
|
|
7609
|
+
logger.info(LOG_KINDS.DAEMON_START, "Dev build detected; update checks exempted", {
|
|
7610
|
+
cli_entry: devCliEntry
|
|
7611
|
+
});
|
|
7612
|
+
}
|
|
7155
7613
|
const db = initDatabase(vaultDbPath(vaultDir));
|
|
7156
7614
|
createSchema(db, machineId);
|
|
7157
7615
|
registerBuiltinDomains();
|
|
7158
7616
|
logger.info(LOG_KINDS.DAEMON_START, "SQLite initialized", { vault: vaultDir });
|
|
7617
|
+
{
|
|
7618
|
+
const reasonPath = path21.join(vaultDir, RESTART_REASON_FILENAME);
|
|
7619
|
+
try {
|
|
7620
|
+
if (fs22.existsSync(reasonPath)) {
|
|
7621
|
+
const raw = JSON.parse(fs22.readFileSync(reasonPath, "utf-8"));
|
|
7622
|
+
fs22.unlinkSync(reasonPath);
|
|
7623
|
+
if (raw.reason === "version_sync" && raw.to_version) {
|
|
7624
|
+
const message = raw.local_update_ran ? "Restarted and updated local project hooks." : "Restarted to pick up the latest version.";
|
|
7625
|
+
notify(vaultDir, {
|
|
7626
|
+
domain: "daemon",
|
|
7627
|
+
type: "daemon.version_sync",
|
|
7628
|
+
title: `Updated to v${raw.to_version}`,
|
|
7629
|
+
message,
|
|
7630
|
+
metadata: {
|
|
7631
|
+
from_version: raw.from_version ?? "unknown",
|
|
7632
|
+
to_version: raw.to_version,
|
|
7633
|
+
local_update_ran: raw.local_update_ran ?? false
|
|
7634
|
+
}
|
|
7635
|
+
});
|
|
7636
|
+
logger.info(LOG_KINDS.DAEMON_START, "Version sync restart detected", {
|
|
7637
|
+
from: raw.from_version,
|
|
7638
|
+
to: raw.to_version,
|
|
7639
|
+
local_update: raw.local_update_ran
|
|
7640
|
+
});
|
|
7641
|
+
}
|
|
7642
|
+
}
|
|
7643
|
+
} catch (err) {
|
|
7644
|
+
logger.warn(LOG_KINDS.DAEMON_START, "Failed to read restart-reason file", {
|
|
7645
|
+
error: err.message
|
|
7646
|
+
});
|
|
7647
|
+
}
|
|
7648
|
+
}
|
|
7159
7649
|
initTeamContext(config.team.enabled, machineId);
|
|
7160
7650
|
logger.setPersistFn((entry) => {
|
|
7161
7651
|
const { timestamp, level, kind, component, message, ...rest } = entry;
|
|
@@ -7171,13 +7661,13 @@ async function main() {
|
|
|
7171
7661
|
});
|
|
7172
7662
|
const lastLogTimestamp = getMaxTimestamp();
|
|
7173
7663
|
if (lastLogTimestamp) {
|
|
7174
|
-
const logDir =
|
|
7664
|
+
const logDir = path21.join(vaultDir, "logs");
|
|
7175
7665
|
const replayedCount = reconcileLogBuffer(logDir, lastLogTimestamp);
|
|
7176
7666
|
if (replayedCount > 0) {
|
|
7177
7667
|
logger.info(LOG_KINDS.DAEMON_RECONCILE, `Replayed ${replayedCount} log entries from buffer`, { replayed: replayedCount });
|
|
7178
7668
|
}
|
|
7179
7669
|
}
|
|
7180
|
-
const vectorsDbPath =
|
|
7670
|
+
const vectorsDbPath = path21.join(vaultDir, "vectors.db");
|
|
7181
7671
|
const vectorStore = new SqliteVecVectorStore(vectorsDbPath);
|
|
7182
7672
|
const llmProvider = createEmbeddingProvider(config.embedding);
|
|
7183
7673
|
const embeddingProvider = new EmbeddingProviderAdapter(llmProvider, config.embedding);
|
|
@@ -7187,7 +7677,7 @@ async function main() {
|
|
|
7187
7677
|
const databaseManager = new DatabaseMaintenanceManager(vaultDbPath(vaultDir), vaultDir, logger);
|
|
7188
7678
|
let definitionsDir;
|
|
7189
7679
|
try {
|
|
7190
|
-
const { registerBuiltInAgentsAndTasks, resolveDefinitionsDir: resolveDefinitionsDir2 } = await import("./loader-
|
|
7680
|
+
const { registerBuiltInAgentsAndTasks, resolveDefinitionsDir: resolveDefinitionsDir2 } = await import("./loader-SKKUMT5C.js");
|
|
7191
7681
|
definitionsDir = resolveDefinitionsDir2();
|
|
7192
7682
|
await registerBuiltInAgentsAndTasks(definitionsDir, vaultDir);
|
|
7193
7683
|
logger.info(LOG_KINDS.AGENT_TASK, "Built-in agents and tasks registered");
|
|
@@ -7213,10 +7703,10 @@ async function main() {
|
|
|
7213
7703
|
}
|
|
7214
7704
|
let uiDir = null;
|
|
7215
7705
|
{
|
|
7216
|
-
const root = findPackageRoot(
|
|
7706
|
+
const root = findPackageRoot(path21.dirname(new URL(import.meta.url).pathname));
|
|
7217
7707
|
if (root) {
|
|
7218
|
-
const candidate =
|
|
7219
|
-
if (
|
|
7708
|
+
const candidate = path21.join(root, "dist", "ui");
|
|
7709
|
+
if (fs22.existsSync(candidate)) uiDir = candidate;
|
|
7220
7710
|
}
|
|
7221
7711
|
}
|
|
7222
7712
|
if (uiDir) {
|
|
@@ -7249,7 +7739,7 @@ async function main() {
|
|
|
7249
7739
|
(p) => createPerProjectAdapter(p, claudeCodeAdapter.parseTurns)
|
|
7250
7740
|
)
|
|
7251
7741
|
});
|
|
7252
|
-
const bufferDir =
|
|
7742
|
+
const bufferDir = path21.join(vaultDir, "buffer");
|
|
7253
7743
|
const sessionBuffers = /* @__PURE__ */ new Map();
|
|
7254
7744
|
const reconciler = createReconciler({ bufferDir, logger });
|
|
7255
7745
|
reconciler.runStartupReconciliation();
|
|
@@ -7260,7 +7750,8 @@ async function main() {
|
|
|
7260
7750
|
embeddingManager,
|
|
7261
7751
|
logger,
|
|
7262
7752
|
config,
|
|
7263
|
-
vaultDir
|
|
7753
|
+
vaultDir,
|
|
7754
|
+
planTags: symbiontPlanTags
|
|
7264
7755
|
});
|
|
7265
7756
|
const sessionLifecycle = createSessionLifecycleHandlers({
|
|
7266
7757
|
registry,
|
|
@@ -7335,11 +7826,12 @@ async function main() {
|
|
|
7335
7826
|
server.registerRoute("POST", "/api/log", createLogIngestionHandler(logger));
|
|
7336
7827
|
server.registerRoute("GET", "/api/models", async (req) => handleGetModels(req));
|
|
7337
7828
|
server.registerRoute("POST", "/api/restart", async (req) => handleRestart({ vaultDir, progressTracker }, req.body));
|
|
7338
|
-
const updateProjectRoot =
|
|
7829
|
+
const updateProjectRoot = path21.dirname(vaultDir);
|
|
7339
7830
|
const updateHandlers = createUpdateHandlers({
|
|
7340
7831
|
vaultDir,
|
|
7341
7832
|
projectRoot: updateProjectRoot,
|
|
7342
7833
|
currentVersion: server.version,
|
|
7834
|
+
globalPrefix,
|
|
7343
7835
|
scheduleShutdown: () => {
|
|
7344
7836
|
setTimeout(() => {
|
|
7345
7837
|
process.kill(process.pid, "SIGTERM");
|
|
@@ -7399,7 +7891,7 @@ async function main() {
|
|
|
7399
7891
|
server.registerRoute("GET", "/api/mcp/sessions", mcpProxy.handleSessions);
|
|
7400
7892
|
server.registerRoute("GET", "/api/mcp/team", mcpProxy.handleTeam);
|
|
7401
7893
|
const rawBackupDir = config.backup.dir;
|
|
7402
|
-
const backupDir = rawBackupDir ?
|
|
7894
|
+
const backupDir = rawBackupDir ? path21.resolve(rawBackupDir.startsWith("~/") ? path21.join(os8.homedir(), rawBackupDir.slice(2)) : rawBackupDir) : path21.resolve(vaultDir, "backups");
|
|
7403
7895
|
const backupHandlers = createBackupHandlers({ db, backupDir, machineId });
|
|
7404
7896
|
server.registerRoute("POST", "/api/backup", backupHandlers.handleCreateBackup);
|
|
7405
7897
|
server.registerRoute("GET", "/api/backups", backupHandlers.handleListBackups);
|
|
@@ -7412,6 +7904,7 @@ async function main() {
|
|
|
7412
7904
|
const teamHandlers = createTeamHandlers({
|
|
7413
7905
|
vaultDir,
|
|
7414
7906
|
machineId,
|
|
7907
|
+
logger,
|
|
7415
7908
|
getTeamClient: teamSync.getTeamClient,
|
|
7416
7909
|
setTeamClient: teamSync.setTeamClient
|
|
7417
7910
|
});
|
|
@@ -7421,6 +7914,7 @@ async function main() {
|
|
|
7421
7914
|
server.registerRoute("POST", "/api/team/backfill", teamHandlers.handleBackfill);
|
|
7422
7915
|
server.registerRoute("POST", "/api/team/retry-failed", teamHandlers.handleRetryFailed);
|
|
7423
7916
|
server.registerRoute("POST", "/api/team/upgrade-worker", teamHandlers.handleUpgradeWorker);
|
|
7917
|
+
server.registerRoute("POST", "/api/team/rotate-mcp-token", teamHandlers.handleRotateMcpToken);
|
|
7424
7918
|
server.registerRoute("GET", "/api/search", createSearchHandler({ embeddingManager, getTeamClient: teamSync.getTeamClient, machineId }));
|
|
7425
7919
|
server.registerRoute("GET", "/api/activity", handleGetFeed);
|
|
7426
7920
|
server.registerRoute("GET", "/api/embedding/status", async () => handleGetEmbeddingStatus(vaultDir));
|
|
@@ -7493,4 +7987,4 @@ export {
|
|
|
7493
7987
|
handleUserPrompt,
|
|
7494
7988
|
main
|
|
7495
7989
|
};
|
|
7496
|
-
//# sourceMappingURL=main-
|
|
7990
|
+
//# sourceMappingURL=main-5THODR77.js.map
|