@goondocks/myco 0.14.4 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-run-GZ5UVLDV.js → agent-run-DUOJ3KDI.js} +6 -6
- package/dist/{agent-tasks-KKQ2GBBB.js → agent-tasks-LUWBY5JD.js} +6 -6
- package/dist/{chunk-X34OFKYU.js → chunk-23FJUKCN.js} +2 -2
- package/dist/{chunk-KNTJOMWY.js → chunk-3MEOYXOW.js} +2 -2
- package/dist/{chunk-PSYLKCWQ.js → chunk-4BQ5QE76.js} +24 -5
- package/dist/chunk-4BQ5QE76.js.map +1 -0
- package/dist/{chunk-JTYZRPX5.js → chunk-5ZT2Q6P5.js} +1 -1
- package/dist/{chunk-JJXVDCEX.js → chunk-75J2BR4P.js} +486 -488
- package/dist/chunk-75J2BR4P.js.map +1 -0
- package/dist/{chunk-GMTWRMLP.js → chunk-B3SF2CCW.js} +3 -3
- package/dist/{chunk-S6I62FAH.js → chunk-CUADDHHU.js} +4 -2
- package/dist/{chunk-S6I62FAH.js.map → chunk-CUADDHHU.js.map} +1 -1
- package/dist/{chunk-4VF6KQ2Z.js → chunk-DJQOYEK3.js} +87 -84
- package/dist/chunk-DJQOYEK3.js.map +1 -0
- package/dist/{chunk-LD6U3L6O.js → chunk-DK5VEBB5.js} +5 -5
- package/dist/{chunk-STBNNKL5.js → chunk-DKGUCEWU.js} +6 -6
- package/dist/{chunk-OQVKLTQY.js → chunk-EYMKBNRP.js} +2 -2
- package/dist/{chunk-KH64DHOY.js → chunk-GDY63YAW.js} +279 -277
- package/dist/chunk-GDY63YAW.js.map +1 -0
- package/dist/{chunk-ZESTWGJT.js → chunk-GYIA6XLB.js} +2 -2
- package/dist/{chunk-BCKYVLUZ.js → chunk-GZ7MXWYX.js} +3 -3
- package/dist/{chunk-S66YG6QK.js → chunk-LF5Z62X6.js} +46 -7
- package/dist/chunk-LF5Z62X6.js.map +1 -0
- package/dist/{chunk-TFBAV3PV.js → chunk-OMZCVRX6.js} +2 -2
- package/dist/{chunk-UZ5Y6XMP.js → chunk-R3YW7XVF.js} +2 -2
- package/dist/{chunk-PX5KIOKY.js → chunk-SPJGJEFV.js} +10 -2
- package/dist/{chunk-PX5KIOKY.js.map → chunk-SPJGJEFV.js.map} +1 -1
- package/dist/{chunk-QFMBZ72S.js → chunk-SV6UCB2Z.js} +2 -2
- package/dist/{chunk-NVCGF2DS.js → chunk-X4XFJG6I.js} +10 -6
- package/dist/chunk-X4XFJG6I.js.map +1 -0
- package/dist/{chunk-TNCBMGWB.js → chunk-X5IXK5KO.js} +262 -226
- package/dist/chunk-X5IXK5KO.js.map +1 -0
- package/dist/{chunk-TVV6PZOC.js → chunk-Z7TZJ2SP.js} +2 -2
- package/dist/{cli-JLDCZ77U.js → cli-YBD2GPK4.js} +45 -44
- package/dist/cli-YBD2GPK4.js.map +1 -0
- package/dist/{client-LRQMMKLP.js → client-CJ3X252K.js} +4 -4
- package/dist/{config-H657SF6B.js → config-MOWCOJJ4.js} +4 -4
- package/dist/{detect-27DN6UTL.js → detect-GFYKKHLJ.js} +3 -3
- package/dist/{detect-providers-PAVE2X6O.js → detect-providers-EU35RUL3.js} +2 -2
- package/dist/{doctor-IG3CXMI7.js → doctor-JR7NEL7K.js} +38 -19
- package/dist/doctor-JR7NEL7K.js.map +1 -0
- package/dist/{executor-HKNINUWO.js → executor-7XOKS6HS.js} +439 -248
- package/dist/executor-7XOKS6HS.js.map +1 -0
- package/dist/{init-RHQUINC2.js → init-PDLKYWQ4.js} +41 -23
- package/dist/init-PDLKYWQ4.js.map +1 -0
- package/dist/{init-wizard-ZB3JRDLE.js → init-wizard-WH3SXNMB.js} +7 -7
- package/dist/{installer-25TSX4SR.js → installer-BTUNKWOU.js} +2 -2
- package/dist/{llm-T3QVHC3Y.js → llm-DK44LYO6.js} +4 -4
- package/dist/{loader-WQKVWL5D.js → loader-WC4U5NM5.js} +4 -4
- package/dist/{loader-JQLO6K44.js → loader-WGDVRGLM.js} +6 -4
- package/dist/{logs-LXHPDKUA.js → logs-WFBX2I7C.js} +3 -3
- package/dist/{main-MVXPBP5Z.js → main-JB3R3DQE.js} +2346 -1912
- package/dist/main-JB3R3DQE.js.map +1 -0
- package/dist/{open-CVEMRH3Z.js → open-AADZPSLW.js} +6 -6
- package/dist/{openai-embeddings-5T5ZP7LO.js → openai-embeddings-SEIV7AM3.js} +2 -2
- package/dist/{openrouter-RD2COFC7.js → openrouter-ELODIZRP.js} +2 -2
- package/dist/{post-compact-ALQ2UGZ7.js → post-compact-KNQ4DYLM.js} +9 -9
- package/dist/{post-tool-use-SPL7HIYU.js → post-tool-use-OMWHFQLM.js} +10 -10
- package/dist/{post-tool-use-failure-B3CUYBTR.js → post-tool-use-failure-KFP6MB7Z.js} +9 -9
- package/dist/{pre-compact-KPWC4V64.js → pre-compact-2ZYE2HRB.js} +9 -9
- package/dist/{provider-check-QN7OGXZA.js → provider-check-B66E5PWS.js} +2 -2
- package/dist/{registry-2XQMCPA6.js → registry-DHWVHXWY.js} +5 -5
- package/dist/{remove-O2WCN6RC.js → remove-QT7634L5.js} +52 -20
- package/dist/remove-QT7634L5.js.map +1 -0
- package/dist/{resolution-events-5EVUEWHS.js → resolution-events-DBCRVZGU.js} +4 -4
- package/dist/{restart-S52VV3SP.js → restart-YQNQEHOU.js} +7 -7
- package/dist/{search-IOJ5O37S.js → search-C6JTQDWY.js} +6 -6
- package/dist/{server-T4VPK6FU.js → server-QJ3RWZZZ.js} +8 -8
- package/dist/{session-ID6BX72K.js → session-JLVL5TYX.js} +8 -8
- package/dist/{session-end-I7ZABXRI.js → session-end-XFZRRP5H.js} +10 -10
- package/dist/{session-start-VPOUY42U.js → session-start-XGINISXO.js} +15 -15
- package/dist/{setup-llm-G5UG5N3T.js → setup-llm-X2OCM6R7.js} +8 -8
- package/dist/src/agent/definitions/tasks/full-intelligence.yaml +8 -7
- package/dist/src/agent/definitions/tasks/skill-evolve.yaml +71 -144
- package/dist/src/agent/definitions/tasks/skill-generate.yaml +10 -62
- package/dist/src/agent/definitions/tasks/skill-survey.yaml +87 -53
- package/dist/src/agent/prompts/agent.md +1 -0
- 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/worker/src/schema.ts +14 -0
- package/dist/{stats-GRI4MTS2.js → stats-2EAETG2T.js} +9 -9
- package/dist/{stop-UTZ2CXI2.js → stop-WOBDYTSA.js} +10 -10
- package/dist/{stop-failure-CECM5NB7.js → stop-failure-QEC7ZGBQ.js} +9 -9
- package/dist/{subagent-start-SYZGJYUN.js → subagent-start-H6DVRVOE.js} +9 -9
- package/dist/{subagent-stop-7WWW7TGQ.js → subagent-stop-LKENKJ65.js} +9 -9
- package/dist/{task-completed-N7SIY6T6.js → task-completed-ZZ47PRPD.js} +9 -9
- package/dist/{team-SJPDXELY.js → team-J62N7VMG.js} +34 -26
- package/dist/team-J62N7VMG.js.map +1 -0
- package/dist/ui/assets/index-Bx9l8uxa.js +837 -0
- package/dist/ui/assets/{index-BmsHIwjl.css → index-DlEQ8A8Y.css} +1 -1
- package/dist/ui/index.html +2 -2
- package/dist/{update-DZZYQ4NJ.js → update-LX3CJ4TJ.js} +30 -14
- package/dist/update-LX3CJ4TJ.js.map +1 -0
- package/dist/{user-prompt-submit-UUNRRS5P.js → user-prompt-submit-NNMLY3EW.js} +10 -10
- package/dist/{verify-JHIMXTY5.js → verify-AMRQXQ3K.js} +6 -6
- package/dist/{version-VKNCAPZW.js → version-6OJH5HLZ.js} +2 -2
- package/package.json +2 -2
- package/dist/chunk-4VF6KQ2Z.js.map +0 -1
- package/dist/chunk-JJXVDCEX.js.map +0 -1
- package/dist/chunk-KH64DHOY.js.map +0 -1
- package/dist/chunk-NVCGF2DS.js.map +0 -1
- package/dist/chunk-PSYLKCWQ.js.map +0 -1
- package/dist/chunk-S66YG6QK.js.map +0 -1
- package/dist/chunk-TNCBMGWB.js.map +0 -1
- package/dist/cli-JLDCZ77U.js.map +0 -1
- package/dist/doctor-IG3CXMI7.js.map +0 -1
- package/dist/executor-HKNINUWO.js.map +0 -1
- package/dist/init-RHQUINC2.js.map +0 -1
- package/dist/main-MVXPBP5Z.js.map +0 -1
- package/dist/remove-O2WCN6RC.js.map +0 -1
- package/dist/resolve-3FEUV462.js +0 -9
- package/dist/team-SJPDXELY.js.map +0 -1
- package/dist/ui/assets/index-Cn6cQwJy.js +0 -842
- package/dist/update-DZZYQ4NJ.js.map +0 -1
- package/dist/version-VKNCAPZW.js.map +0 -1
- /package/dist/{agent-run-GZ5UVLDV.js.map → agent-run-DUOJ3KDI.js.map} +0 -0
- /package/dist/{agent-tasks-KKQ2GBBB.js.map → agent-tasks-LUWBY5JD.js.map} +0 -0
- /package/dist/{chunk-X34OFKYU.js.map → chunk-23FJUKCN.js.map} +0 -0
- /package/dist/{chunk-KNTJOMWY.js.map → chunk-3MEOYXOW.js.map} +0 -0
- /package/dist/{chunk-JTYZRPX5.js.map → chunk-5ZT2Q6P5.js.map} +0 -0
- /package/dist/{chunk-GMTWRMLP.js.map → chunk-B3SF2CCW.js.map} +0 -0
- /package/dist/{chunk-LD6U3L6O.js.map → chunk-DK5VEBB5.js.map} +0 -0
- /package/dist/{chunk-STBNNKL5.js.map → chunk-DKGUCEWU.js.map} +0 -0
- /package/dist/{chunk-OQVKLTQY.js.map → chunk-EYMKBNRP.js.map} +0 -0
- /package/dist/{chunk-ZESTWGJT.js.map → chunk-GYIA6XLB.js.map} +0 -0
- /package/dist/{chunk-BCKYVLUZ.js.map → chunk-GZ7MXWYX.js.map} +0 -0
- /package/dist/{chunk-TFBAV3PV.js.map → chunk-OMZCVRX6.js.map} +0 -0
- /package/dist/{chunk-UZ5Y6XMP.js.map → chunk-R3YW7XVF.js.map} +0 -0
- /package/dist/{chunk-QFMBZ72S.js.map → chunk-SV6UCB2Z.js.map} +0 -0
- /package/dist/{chunk-TVV6PZOC.js.map → chunk-Z7TZJ2SP.js.map} +0 -0
- /package/dist/{client-LRQMMKLP.js.map → client-CJ3X252K.js.map} +0 -0
- /package/dist/{config-H657SF6B.js.map → config-MOWCOJJ4.js.map} +0 -0
- /package/dist/{detect-27DN6UTL.js.map → detect-GFYKKHLJ.js.map} +0 -0
- /package/dist/{detect-providers-PAVE2X6O.js.map → detect-providers-EU35RUL3.js.map} +0 -0
- /package/dist/{init-wizard-ZB3JRDLE.js.map → init-wizard-WH3SXNMB.js.map} +0 -0
- /package/dist/{installer-25TSX4SR.js.map → installer-BTUNKWOU.js.map} +0 -0
- /package/dist/{llm-T3QVHC3Y.js.map → llm-DK44LYO6.js.map} +0 -0
- /package/dist/{loader-JQLO6K44.js.map → loader-WC4U5NM5.js.map} +0 -0
- /package/dist/{loader-WQKVWL5D.js.map → loader-WGDVRGLM.js.map} +0 -0
- /package/dist/{logs-LXHPDKUA.js.map → logs-WFBX2I7C.js.map} +0 -0
- /package/dist/{open-CVEMRH3Z.js.map → open-AADZPSLW.js.map} +0 -0
- /package/dist/{openai-embeddings-5T5ZP7LO.js.map → openai-embeddings-SEIV7AM3.js.map} +0 -0
- /package/dist/{openrouter-RD2COFC7.js.map → openrouter-ELODIZRP.js.map} +0 -0
- /package/dist/{post-compact-ALQ2UGZ7.js.map → post-compact-KNQ4DYLM.js.map} +0 -0
- /package/dist/{post-tool-use-SPL7HIYU.js.map → post-tool-use-OMWHFQLM.js.map} +0 -0
- /package/dist/{post-tool-use-failure-B3CUYBTR.js.map → post-tool-use-failure-KFP6MB7Z.js.map} +0 -0
- /package/dist/{pre-compact-KPWC4V64.js.map → pre-compact-2ZYE2HRB.js.map} +0 -0
- /package/dist/{provider-check-QN7OGXZA.js.map → provider-check-B66E5PWS.js.map} +0 -0
- /package/dist/{registry-2XQMCPA6.js.map → registry-DHWVHXWY.js.map} +0 -0
- /package/dist/{resolution-events-5EVUEWHS.js.map → resolution-events-DBCRVZGU.js.map} +0 -0
- /package/dist/{restart-S52VV3SP.js.map → restart-YQNQEHOU.js.map} +0 -0
- /package/dist/{search-IOJ5O37S.js.map → search-C6JTQDWY.js.map} +0 -0
- /package/dist/{server-T4VPK6FU.js.map → server-QJ3RWZZZ.js.map} +0 -0
- /package/dist/{session-ID6BX72K.js.map → session-JLVL5TYX.js.map} +0 -0
- /package/dist/{session-end-I7ZABXRI.js.map → session-end-XFZRRP5H.js.map} +0 -0
- /package/dist/{session-start-VPOUY42U.js.map → session-start-XGINISXO.js.map} +0 -0
- /package/dist/{setup-llm-G5UG5N3T.js.map → setup-llm-X2OCM6R7.js.map} +0 -0
- /package/dist/{stats-GRI4MTS2.js.map → stats-2EAETG2T.js.map} +0 -0
- /package/dist/{stop-UTZ2CXI2.js.map → stop-WOBDYTSA.js.map} +0 -0
- /package/dist/{stop-failure-CECM5NB7.js.map → stop-failure-QEC7ZGBQ.js.map} +0 -0
- /package/dist/{subagent-start-SYZGJYUN.js.map → subagent-start-H6DVRVOE.js.map} +0 -0
- /package/dist/{subagent-stop-7WWW7TGQ.js.map → subagent-stop-LKENKJ65.js.map} +0 -0
- /package/dist/{task-completed-N7SIY6T6.js.map → task-completed-ZZ47PRPD.js.map} +0 -0
- /package/dist/{user-prompt-submit-UUNRRS5P.js.map → user-prompt-submit-NNMLY3EW.js.map} +0 -0
- /package/dist/{verify-JHIMXTY5.js.map → verify-AMRQXQ3K.js.map} +0 -0
- /package/dist/{resolve-3FEUV462.js.map → version-6OJH5HLZ.js.map} +0 -0
|
@@ -1,8 +1,143 @@
|
|
|
1
1
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
2
|
|
|
3
3
|
// src/symbionts/installer.ts
|
|
4
|
+
import fs3 from "fs";
|
|
5
|
+
import path3 from "path";
|
|
6
|
+
|
|
7
|
+
// src/symbionts/toml-helpers.ts
|
|
8
|
+
var TOML_SECTION_RE = /^\[([^\]]+)\]/;
|
|
9
|
+
function findTomlSectionEnd(raw, searchStart, serverName) {
|
|
10
|
+
const subsectionPrefix = `mcp_servers.${serverName}.`;
|
|
11
|
+
const rawLines = raw.slice(searchStart).split("\n");
|
|
12
|
+
let offset = searchStart;
|
|
13
|
+
for (const line of rawLines) {
|
|
14
|
+
offset += line.length + 1;
|
|
15
|
+
const m = line.match(TOML_SECTION_RE);
|
|
16
|
+
if (m && !m[1].startsWith(subsectionPrefix) && m[1] !== `mcp_servers.${serverName}`) {
|
|
17
|
+
return offset - line.length - 1;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return raw.length;
|
|
21
|
+
}
|
|
22
|
+
function buildTomlMcpSection(raw, serverName, server) {
|
|
23
|
+
const sectionHeader = `[mcp_servers.${serverName}]`;
|
|
24
|
+
const lines = [sectionHeader];
|
|
25
|
+
for (const [key, val] of Object.entries(server)) {
|
|
26
|
+
if (key === "env" && typeof val === "object" && val !== null) continue;
|
|
27
|
+
if (typeof val === "string") {
|
|
28
|
+
lines.push(`${key} = "${val}"`);
|
|
29
|
+
} else if (Array.isArray(val)) {
|
|
30
|
+
lines.push(`${key} = [${val.map((v) => `"${v}"`).join(", ")}]`);
|
|
31
|
+
} else if (typeof val === "boolean") {
|
|
32
|
+
lines.push(`${key} = ${val}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const env = server.env;
|
|
36
|
+
if (env && Object.keys(env).length > 0) {
|
|
37
|
+
lines.push("");
|
|
38
|
+
lines.push(`[mcp_servers.${serverName}.env]`);
|
|
39
|
+
for (const [key, val] of Object.entries(env)) {
|
|
40
|
+
lines.push(`${key} = "${val}"`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const block = lines.join("\n");
|
|
44
|
+
let updated;
|
|
45
|
+
if (raw.includes(sectionHeader)) {
|
|
46
|
+
const startIdx = raw.indexOf(sectionHeader);
|
|
47
|
+
const endIdx = findTomlSectionEnd(raw, startIdx + sectionHeader.length, serverName);
|
|
48
|
+
const before = raw.slice(0, startIdx).trimEnd();
|
|
49
|
+
const after = raw.slice(endIdx);
|
|
50
|
+
const separator = before ? "\n\n" : "";
|
|
51
|
+
updated = (before + separator + block + after).trimEnd() + "\n";
|
|
52
|
+
} else {
|
|
53
|
+
const separator = raw.trim() ? "\n\n" : "";
|
|
54
|
+
updated = (raw.trimEnd() + separator + block).trimEnd() + "\n";
|
|
55
|
+
}
|
|
56
|
+
return updated;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/symbionts/settings-merge.ts
|
|
60
|
+
function deepMergeSettings(target, source) {
|
|
61
|
+
const result = { ...target };
|
|
62
|
+
for (const [key, sourceVal] of Object.entries(source)) {
|
|
63
|
+
const targetVal = result[key];
|
|
64
|
+
if (Array.isArray(sourceVal) && Array.isArray(targetVal)) {
|
|
65
|
+
result[key] = [.../* @__PURE__ */ new Set([...targetVal, ...sourceVal])];
|
|
66
|
+
} else if (isPlainObject(sourceVal) && isPlainObject(targetVal)) {
|
|
67
|
+
result[key] = deepMergeSettings(
|
|
68
|
+
targetVal,
|
|
69
|
+
sourceVal
|
|
70
|
+
);
|
|
71
|
+
} else {
|
|
72
|
+
result[key] = sourceVal;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
function isPlainObject(val) {
|
|
78
|
+
return typeof val === "object" && val !== null && !Array.isArray(val);
|
|
79
|
+
}
|
|
80
|
+
function deepRemoveSettings(target, template) {
|
|
81
|
+
let changed = false;
|
|
82
|
+
for (const [key, templateVal] of Object.entries(template)) {
|
|
83
|
+
const targetVal = target[key];
|
|
84
|
+
if (targetVal === void 0) continue;
|
|
85
|
+
if (Array.isArray(templateVal) && Array.isArray(targetVal)) {
|
|
86
|
+
const templateSet = new Set(templateVal.map(String));
|
|
87
|
+
const filtered = targetVal.filter((v) => !templateSet.has(String(v)));
|
|
88
|
+
if (filtered.length !== targetVal.length) {
|
|
89
|
+
if (filtered.length > 0) {
|
|
90
|
+
target[key] = filtered;
|
|
91
|
+
} else {
|
|
92
|
+
delete target[key];
|
|
93
|
+
}
|
|
94
|
+
changed = true;
|
|
95
|
+
}
|
|
96
|
+
} else if (isPlainObject(templateVal) && isPlainObject(targetVal)) {
|
|
97
|
+
if (deepRemoveSettings(targetVal, templateVal)) {
|
|
98
|
+
if (Object.keys(targetVal).length === 0) {
|
|
99
|
+
delete target[key];
|
|
100
|
+
}
|
|
101
|
+
changed = true;
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
if (String(targetVal) === String(templateVal)) {
|
|
105
|
+
delete target[key];
|
|
106
|
+
changed = true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return changed;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/symbionts/json-helpers.ts
|
|
4
114
|
import fs from "fs";
|
|
5
115
|
import path from "path";
|
|
116
|
+
function readJsonFile(filePath) {
|
|
117
|
+
try {
|
|
118
|
+
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
119
|
+
} catch {
|
|
120
|
+
return {};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function writeJsonFile(filePath, data) {
|
|
124
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
125
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
126
|
+
}
|
|
127
|
+
function writeOrDeleteJsonFile(filePath, data) {
|
|
128
|
+
if (Object.keys(data).length === 0) {
|
|
129
|
+
try {
|
|
130
|
+
fs.unlinkSync(filePath);
|
|
131
|
+
} catch {
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
writeJsonFile(filePath, data);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// src/symbionts/install-helpers.ts
|
|
139
|
+
import fs2 from "fs";
|
|
140
|
+
import path2 from "path";
|
|
6
141
|
var MYCO_HOOK_COMMAND_PREFIX = "myco-run";
|
|
7
142
|
var MYCO_HOOK_GUARD_PREFIX = "node .agents/myco-hook.cjs";
|
|
8
143
|
function isMycoHookCommand(command) {
|
|
@@ -13,6 +148,35 @@ function isMycoHookGroup(group) {
|
|
|
13
148
|
if (typeof group.command === "string" && isMycoHookCommand(group.command)) return true;
|
|
14
149
|
return false;
|
|
15
150
|
}
|
|
151
|
+
function ensureAgentsMd(projectRoot, packageRoot) {
|
|
152
|
+
const agentsMdPath = path2.join(projectRoot, "AGENTS.md");
|
|
153
|
+
if (fs2.existsSync(agentsMdPath)) return;
|
|
154
|
+
const candidates = [
|
|
155
|
+
path2.join(packageRoot, "src/symbionts/templates/agents-starter.md"),
|
|
156
|
+
path2.join(packageRoot, "dist/src/symbionts/templates/agents-starter.md")
|
|
157
|
+
];
|
|
158
|
+
for (const p of candidates) {
|
|
159
|
+
try {
|
|
160
|
+
const content = fs2.readFileSync(p, "utf-8");
|
|
161
|
+
fs2.writeFileSync(agentsMdPath, content, "utf-8");
|
|
162
|
+
return;
|
|
163
|
+
} catch {
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function ensureSymlink(linkPath, target) {
|
|
168
|
+
try {
|
|
169
|
+
if (fs2.readlinkSync(linkPath) === target) return;
|
|
170
|
+
} catch {
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
fs2.rmSync(linkPath, { recursive: true, force: true });
|
|
174
|
+
} catch {
|
|
175
|
+
}
|
|
176
|
+
fs2.symlinkSync(target, linkPath);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// src/symbionts/installer.ts
|
|
16
180
|
var GITIGNORE_COMMENT = "# Myco managed (machine-specific)";
|
|
17
181
|
var GITIGNORE_SKILLS_COMMENT_LEGACY = "# Myco skill symlinks (machine-specific)";
|
|
18
182
|
var WRANGLER_CACHE_DIR = ".wrangler/";
|
|
@@ -46,13 +210,13 @@ var SymbiontInstaller = class {
|
|
|
46
210
|
if (!reg?.hooksTarget) return false;
|
|
47
211
|
const guardTemplate = this.loadHookGuardTemplate();
|
|
48
212
|
if (!guardTemplate) return false;
|
|
49
|
-
const targetPath =
|
|
213
|
+
const targetPath = path3.join(this.projectRoot, HOOK_GUARD_PROJECT_PATH);
|
|
50
214
|
try {
|
|
51
|
-
if (
|
|
215
|
+
if (fs3.readFileSync(targetPath, "utf-8") === guardTemplate) return false;
|
|
52
216
|
} catch {
|
|
53
217
|
}
|
|
54
|
-
|
|
55
|
-
|
|
218
|
+
fs3.mkdirSync(path3.dirname(targetPath), { recursive: true });
|
|
219
|
+
fs3.writeFileSync(targetPath, guardTemplate, "utf-8");
|
|
56
220
|
return true;
|
|
57
221
|
}
|
|
58
222
|
/**
|
|
@@ -62,9 +226,9 @@ var SymbiontInstaller = class {
|
|
|
62
226
|
uninstallHookGuard() {
|
|
63
227
|
const reg = this.manifest.registration;
|
|
64
228
|
if (!reg?.hooksTarget) return false;
|
|
65
|
-
const targetPath =
|
|
229
|
+
const targetPath = path3.join(this.projectRoot, HOOK_GUARD_PROJECT_PATH);
|
|
66
230
|
try {
|
|
67
|
-
|
|
231
|
+
fs3.unlinkSync(targetPath);
|
|
68
232
|
return true;
|
|
69
233
|
} catch {
|
|
70
234
|
return false;
|
|
@@ -73,12 +237,12 @@ var SymbiontInstaller = class {
|
|
|
73
237
|
/** Load the hook-guard template from package root. */
|
|
74
238
|
loadHookGuardTemplate() {
|
|
75
239
|
const candidates = [
|
|
76
|
-
|
|
77
|
-
|
|
240
|
+
path3.join(this.packageRoot, TEMPLATES_SUBDIR, HOOK_GUARD_TEMPLATE_FILENAME),
|
|
241
|
+
path3.join(this.packageRoot, "dist", TEMPLATES_SUBDIR, HOOK_GUARD_TEMPLATE_FILENAME)
|
|
78
242
|
];
|
|
79
243
|
for (const p of candidates) {
|
|
80
244
|
try {
|
|
81
|
-
return
|
|
245
|
+
return fs3.readFileSync(p, "utf-8");
|
|
82
246
|
} catch {
|
|
83
247
|
}
|
|
84
248
|
}
|
|
@@ -87,13 +251,13 @@ var SymbiontInstaller = class {
|
|
|
87
251
|
/** Load a JSON template file for this symbiont. Returns null if not found. */
|
|
88
252
|
loadTemplate(name) {
|
|
89
253
|
const candidates = [
|
|
90
|
-
|
|
254
|
+
path3.join(this.packageRoot, TEMPLATES_SUBDIR, this.manifest.name, `${name}.json`),
|
|
91
255
|
// tsup preserves the src/ prefix under dist/, so the same subdir works in both layouts
|
|
92
|
-
|
|
256
|
+
path3.join(this.packageRoot, "dist", TEMPLATES_SUBDIR, this.manifest.name, `${name}.json`)
|
|
93
257
|
];
|
|
94
258
|
for (const filePath of candidates) {
|
|
95
259
|
try {
|
|
96
|
-
return JSON.parse(
|
|
260
|
+
return JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
97
261
|
} catch {
|
|
98
262
|
}
|
|
99
263
|
}
|
|
@@ -130,7 +294,7 @@ var SymbiontInstaller = class {
|
|
|
130
294
|
* Single read → apply all transforms in memory → single write.
|
|
131
295
|
*/
|
|
132
296
|
installBatchedJson(reg) {
|
|
133
|
-
const targetPath =
|
|
297
|
+
const targetPath = path3.join(this.projectRoot, reg.hooksTarget ?? reg.mcpTarget ?? reg.settingsTarget);
|
|
134
298
|
let data = readJsonFile(targetPath);
|
|
135
299
|
let hooks = false, mcp = false, settings = false;
|
|
136
300
|
const hooksTemplate = reg.hooksTarget ? this.loadTemplate("hooks") : null;
|
|
@@ -188,7 +352,7 @@ var SymbiontInstaller = class {
|
|
|
188
352
|
* Batched uninstall for agents where hooks, MCP, and settings share one JSON file.
|
|
189
353
|
*/
|
|
190
354
|
uninstallBatchedJson(reg) {
|
|
191
|
-
const targetPath =
|
|
355
|
+
const targetPath = path3.join(this.projectRoot, reg.hooksTarget ?? reg.mcpTarget ?? reg.settingsTarget);
|
|
192
356
|
const data = readJsonFile(targetPath);
|
|
193
357
|
if (Object.keys(data).length === 0) {
|
|
194
358
|
return { hooks: false, mcp: false, skills: this.uninstallSkills(), settings: false, instructions: this.uninstallInstructions() };
|
|
@@ -238,35 +402,35 @@ var SymbiontInstaller = class {
|
|
|
238
402
|
const reg = this.manifest.registration;
|
|
239
403
|
if (!reg?.instructionsFile) return false;
|
|
240
404
|
ensureAgentsMd(this.projectRoot, this.packageRoot);
|
|
241
|
-
const targetPath =
|
|
405
|
+
const targetPath = path3.join(this.projectRoot, reg.instructionsFile);
|
|
242
406
|
let existing = null;
|
|
243
407
|
try {
|
|
244
|
-
existing =
|
|
408
|
+
existing = fs3.readFileSync(targetPath, "utf-8");
|
|
245
409
|
} catch {
|
|
246
410
|
}
|
|
247
411
|
if (existing !== null) {
|
|
248
412
|
if (existing.includes(INSTRUCTIONS_REF_START) || existing.includes(INSTRUCTIONS_STUB_MARKER)) {
|
|
249
413
|
return false;
|
|
250
414
|
}
|
|
251
|
-
|
|
415
|
+
fs3.writeFileSync(targetPath, INSTRUCTIONS_REF_BLOCK + existing, "utf-8");
|
|
252
416
|
return true;
|
|
253
417
|
}
|
|
254
418
|
const templateCandidates = [
|
|
255
|
-
|
|
256
|
-
|
|
419
|
+
path3.join(this.packageRoot, "src/symbionts/templates/instructions-stub.md"),
|
|
420
|
+
path3.join(this.packageRoot, "dist/src/symbionts/templates/instructions-stub.md")
|
|
257
421
|
];
|
|
258
422
|
let stub = null;
|
|
259
423
|
for (const p of templateCandidates) {
|
|
260
424
|
try {
|
|
261
|
-
stub =
|
|
425
|
+
stub = fs3.readFileSync(p, "utf-8");
|
|
262
426
|
break;
|
|
263
427
|
} catch {
|
|
264
428
|
}
|
|
265
429
|
}
|
|
266
430
|
if (!stub) return false;
|
|
267
431
|
stub = stub.replace("{agentDisplayName}", this.manifest.displayName);
|
|
268
|
-
|
|
269
|
-
|
|
432
|
+
fs3.mkdirSync(path3.dirname(targetPath), { recursive: true });
|
|
433
|
+
fs3.writeFileSync(targetPath, stub, "utf-8");
|
|
270
434
|
return true;
|
|
271
435
|
}
|
|
272
436
|
/**
|
|
@@ -277,15 +441,15 @@ var SymbiontInstaller = class {
|
|
|
277
441
|
uninstallInstructions() {
|
|
278
442
|
const reg = this.manifest.registration;
|
|
279
443
|
if (!reg?.instructionsFile) return false;
|
|
280
|
-
const targetPath =
|
|
444
|
+
const targetPath = path3.join(this.projectRoot, reg.instructionsFile);
|
|
281
445
|
let content;
|
|
282
446
|
try {
|
|
283
|
-
content =
|
|
447
|
+
content = fs3.readFileSync(targetPath, "utf-8");
|
|
284
448
|
} catch {
|
|
285
449
|
return false;
|
|
286
450
|
}
|
|
287
451
|
if (content.includes(INSTRUCTIONS_STUB_MARKER)) {
|
|
288
|
-
|
|
452
|
+
fs3.unlinkSync(targetPath);
|
|
289
453
|
return true;
|
|
290
454
|
}
|
|
291
455
|
if (content.includes(INSTRUCTIONS_REF_START)) {
|
|
@@ -294,7 +458,7 @@ var SymbiontInstaller = class {
|
|
|
294
458
|
if (endIdx > startIdx) {
|
|
295
459
|
const afterEnd = endIdx + INSTRUCTIONS_REF_END.length;
|
|
296
460
|
const cleaned = (content.slice(0, startIdx) + content.slice(afterEnd)).replace(/^\n+/, "");
|
|
297
|
-
|
|
461
|
+
fs3.writeFileSync(targetPath, cleaned, "utf-8");
|
|
298
462
|
return true;
|
|
299
463
|
}
|
|
300
464
|
}
|
|
@@ -303,7 +467,7 @@ var SymbiontInstaller = class {
|
|
|
303
467
|
/** List skill directory names from the package root. Returns empty array if not found. */
|
|
304
468
|
listSkillDirs() {
|
|
305
469
|
try {
|
|
306
|
-
return
|
|
470
|
+
return fs3.readdirSync(path3.join(this.packageRoot, SKILLS_SUBDIR), { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
307
471
|
} catch {
|
|
308
472
|
return [];
|
|
309
473
|
}
|
|
@@ -319,13 +483,12 @@ var SymbiontInstaller = class {
|
|
|
319
483
|
const skillNames = this.listSkillDirs();
|
|
320
484
|
const desired = [
|
|
321
485
|
...skillNames.map((name) => `${CANONICAL_SKILLS_DIR}/${name}`),
|
|
322
|
-
...reg.skillsTarget !== CANONICAL_SKILLS_DIR ? skillNames.map((name) => `${reg.skillsTarget}/${name}`) : [],
|
|
323
486
|
WRANGLER_CACHE_DIR
|
|
324
487
|
];
|
|
325
|
-
const gitignorePath =
|
|
488
|
+
const gitignorePath = path3.join(this.projectRoot, ".gitignore");
|
|
326
489
|
let content = "";
|
|
327
490
|
try {
|
|
328
|
-
content =
|
|
491
|
+
content = fs3.readFileSync(gitignorePath, "utf-8");
|
|
329
492
|
} catch {
|
|
330
493
|
}
|
|
331
494
|
const stripped = this.stripMycoGitignoreBlock(content, skillNames);
|
|
@@ -337,7 +500,7 @@ ${desired.join("\n")}
|
|
|
337
500
|
const spacer = stripped.length > 0 && desiredBlock.length > 0 ? "\n" : "";
|
|
338
501
|
const result = stripped + separator + spacer + desiredBlock;
|
|
339
502
|
if (result === content) return;
|
|
340
|
-
|
|
503
|
+
fs3.writeFileSync(gitignorePath, result, "utf-8");
|
|
341
504
|
}
|
|
342
505
|
/**
|
|
343
506
|
* Remove all Myco-owned gitignore entries: the comment header, per-skill
|
|
@@ -372,7 +535,7 @@ ${desired.join("\n")}
|
|
|
372
535
|
if (!reg?.hooksTarget) return false;
|
|
373
536
|
const template = this.loadTemplate("hooks");
|
|
374
537
|
if (!template) return false;
|
|
375
|
-
const targetPath =
|
|
538
|
+
const targetPath = path3.join(this.projectRoot, reg.hooksTarget);
|
|
376
539
|
const settings = readJsonFile(targetPath);
|
|
377
540
|
const existingHooks = settings.hooks ?? {};
|
|
378
541
|
const mergedHooks = {};
|
|
@@ -400,7 +563,7 @@ ${desired.join("\n")}
|
|
|
400
563
|
if (!reg?.mcpTarget) return false;
|
|
401
564
|
const template = this.loadTemplate("mcp");
|
|
402
565
|
if (!template) return false;
|
|
403
|
-
const targetPath =
|
|
566
|
+
const targetPath = path3.join(this.projectRoot, reg.mcpTarget);
|
|
404
567
|
const mcpFormat = reg.mcpFormat ?? "json";
|
|
405
568
|
if (mcpFormat === "toml") {
|
|
406
569
|
return this.installMcpToml(targetPath, template);
|
|
@@ -422,14 +585,14 @@ ${desired.join("\n")}
|
|
|
422
585
|
installMcpToml(targetPath, template) {
|
|
423
586
|
let raw = "";
|
|
424
587
|
try {
|
|
425
|
-
raw =
|
|
588
|
+
raw = fs3.readFileSync(targetPath, "utf-8");
|
|
426
589
|
} catch {
|
|
427
590
|
}
|
|
428
591
|
for (const [name, def] of Object.entries(template)) {
|
|
429
592
|
raw = buildTomlMcpSection(raw, name, def);
|
|
430
593
|
}
|
|
431
|
-
|
|
432
|
-
|
|
594
|
+
fs3.mkdirSync(path3.dirname(targetPath), { recursive: true });
|
|
595
|
+
fs3.writeFileSync(targetPath, raw, "utf-8");
|
|
433
596
|
return true;
|
|
434
597
|
}
|
|
435
598
|
/**
|
|
@@ -442,23 +605,24 @@ ${desired.join("\n")}
|
|
|
442
605
|
if (!reg?.skillsTarget) return false;
|
|
443
606
|
const skillNames = this.listSkillDirs();
|
|
444
607
|
if (skillNames.length === 0) return false;
|
|
445
|
-
const skillsSrc =
|
|
446
|
-
const canonicalDir =
|
|
447
|
-
|
|
608
|
+
const skillsSrc = path3.join(this.packageRoot, SKILLS_SUBDIR);
|
|
609
|
+
const canonicalDir = path3.join(this.projectRoot, CANONICAL_SKILLS_DIR);
|
|
610
|
+
fs3.mkdirSync(canonicalDir, { recursive: true });
|
|
448
611
|
for (const name of skillNames) {
|
|
449
|
-
const canonicalLink =
|
|
450
|
-
const target =
|
|
612
|
+
const canonicalLink = path3.join(canonicalDir, name);
|
|
613
|
+
const target = path3.join(skillsSrc, name);
|
|
451
614
|
ensureSymlink(canonicalLink, target);
|
|
452
615
|
}
|
|
453
|
-
const agentSkillsDir =
|
|
454
|
-
const canonicalRel =
|
|
616
|
+
const agentSkillsDir = path3.join(this.projectRoot, reg.skillsTarget);
|
|
617
|
+
const canonicalRel = path3.relative(agentSkillsDir, canonicalDir);
|
|
455
618
|
if (reg.skillsTarget !== CANONICAL_SKILLS_DIR) {
|
|
456
|
-
|
|
619
|
+
fs3.mkdirSync(agentSkillsDir, { recursive: true });
|
|
457
620
|
for (const name of skillNames) {
|
|
458
|
-
const agentLink =
|
|
459
|
-
const relTarget =
|
|
621
|
+
const agentLink = path3.join(agentSkillsDir, name);
|
|
622
|
+
const relTarget = path3.join(canonicalRel, name);
|
|
460
623
|
ensureSymlink(agentLink, relTarget);
|
|
461
624
|
}
|
|
625
|
+
ensureLocalSkillsGitignore(agentSkillsDir);
|
|
462
626
|
}
|
|
463
627
|
return true;
|
|
464
628
|
}
|
|
@@ -471,7 +635,7 @@ ${desired.join("\n")}
|
|
|
471
635
|
if (!reg?.settingsTarget) return false;
|
|
472
636
|
const template = this.loadTemplate("settings");
|
|
473
637
|
if (!template) return false;
|
|
474
|
-
const targetPath =
|
|
638
|
+
const targetPath = path3.join(this.projectRoot, reg.settingsTarget);
|
|
475
639
|
const existing = readJsonFile(targetPath);
|
|
476
640
|
const merged = deepMergeSettings(existing, template);
|
|
477
641
|
writeJsonFile(targetPath, merged);
|
|
@@ -488,7 +652,7 @@ ${desired.join("\n")}
|
|
|
488
652
|
if (!reg?.settingsTarget) return false;
|
|
489
653
|
const template = this.loadTemplate("settings");
|
|
490
654
|
if (!template) return false;
|
|
491
|
-
const targetPath =
|
|
655
|
+
const targetPath = path3.join(this.projectRoot, reg.settingsTarget);
|
|
492
656
|
const settings = readJsonFile(targetPath);
|
|
493
657
|
if (Object.keys(settings).length === 0) return false;
|
|
494
658
|
const changed = deepRemoveSettings(settings, template);
|
|
@@ -500,7 +664,7 @@ ${desired.join("\n")}
|
|
|
500
664
|
uninstallHooks() {
|
|
501
665
|
const reg = this.manifest.registration;
|
|
502
666
|
if (!reg?.hooksTarget) return false;
|
|
503
|
-
const targetPath =
|
|
667
|
+
const targetPath = path3.join(this.projectRoot, reg.hooksTarget);
|
|
504
668
|
const settings = readJsonFile(targetPath);
|
|
505
669
|
const existingHooks = settings.hooks ?? {};
|
|
506
670
|
if (Object.keys(existingHooks).length === 0) return false;
|
|
@@ -525,7 +689,7 @@ ${desired.join("\n")}
|
|
|
525
689
|
uninstallMcp() {
|
|
526
690
|
const reg = this.manifest.registration;
|
|
527
691
|
if (!reg?.mcpTarget) return false;
|
|
528
|
-
const targetPath =
|
|
692
|
+
const targetPath = path3.join(this.projectRoot, reg.mcpTarget);
|
|
529
693
|
const mcpFormat = reg.mcpFormat ?? "json";
|
|
530
694
|
if (mcpFormat === "toml") {
|
|
531
695
|
return this.uninstallMcpToml(targetPath);
|
|
@@ -548,7 +712,7 @@ ${desired.join("\n")}
|
|
|
548
712
|
uninstallMcpToml(targetPath) {
|
|
549
713
|
let raw = "";
|
|
550
714
|
try {
|
|
551
|
-
raw =
|
|
715
|
+
raw = fs3.readFileSync(targetPath, "utf-8");
|
|
552
716
|
} catch {
|
|
553
717
|
return false;
|
|
554
718
|
}
|
|
@@ -561,11 +725,11 @@ ${desired.join("\n")}
|
|
|
561
725
|
const updated = (before + (before && after ? "\n\n" : "") + after).trimEnd();
|
|
562
726
|
if (!updated.trim()) {
|
|
563
727
|
try {
|
|
564
|
-
|
|
728
|
+
fs3.unlinkSync(targetPath);
|
|
565
729
|
} catch {
|
|
566
730
|
}
|
|
567
731
|
} else {
|
|
568
|
-
|
|
732
|
+
fs3.writeFileSync(targetPath, updated + "\n", "utf-8");
|
|
569
733
|
}
|
|
570
734
|
return true;
|
|
571
735
|
}
|
|
@@ -578,214 +742,69 @@ ${desired.join("\n")}
|
|
|
578
742
|
let removed = false;
|
|
579
743
|
if (reg.skillsTarget !== CANONICAL_SKILLS_DIR) {
|
|
580
744
|
for (const name of skillNames) {
|
|
581
|
-
const link =
|
|
745
|
+
const link = path3.join(this.projectRoot, reg.skillsTarget, name);
|
|
582
746
|
try {
|
|
583
|
-
|
|
747
|
+
fs3.unlinkSync(link);
|
|
584
748
|
removed = true;
|
|
585
749
|
} catch {
|
|
586
750
|
}
|
|
587
751
|
}
|
|
588
752
|
try {
|
|
589
|
-
|
|
753
|
+
fs3.rmdirSync(path3.join(this.projectRoot, reg.skillsTarget));
|
|
590
754
|
} catch {
|
|
591
755
|
}
|
|
592
756
|
}
|
|
593
|
-
const canonicalDir =
|
|
757
|
+
const canonicalDir = path3.join(this.projectRoot, CANONICAL_SKILLS_DIR);
|
|
594
758
|
for (const name of skillNames) {
|
|
595
|
-
const link =
|
|
759
|
+
const link = path3.join(canonicalDir, name);
|
|
596
760
|
try {
|
|
597
|
-
|
|
761
|
+
fs3.unlinkSync(link);
|
|
598
762
|
removed = true;
|
|
599
763
|
} catch {
|
|
600
764
|
}
|
|
601
765
|
}
|
|
602
766
|
try {
|
|
603
|
-
|
|
767
|
+
fs3.rmdirSync(canonicalDir);
|
|
604
768
|
} catch {
|
|
605
769
|
}
|
|
606
770
|
try {
|
|
607
|
-
|
|
771
|
+
fs3.rmdirSync(path3.join(this.projectRoot, ".agents"));
|
|
608
772
|
} catch {
|
|
609
773
|
}
|
|
610
774
|
return removed;
|
|
611
775
|
}
|
|
612
776
|
/** Remove Myco entries from project .gitignore. */
|
|
613
777
|
cleanGitignore() {
|
|
614
|
-
const gitignorePath =
|
|
778
|
+
const gitignorePath = path3.join(this.projectRoot, ".gitignore");
|
|
615
779
|
let content = "";
|
|
616
780
|
try {
|
|
617
|
-
content =
|
|
781
|
+
content = fs3.readFileSync(gitignorePath, "utf-8");
|
|
618
782
|
} catch {
|
|
619
783
|
return;
|
|
620
784
|
}
|
|
621
785
|
const cleaned = this.stripMycoGitignoreBlock(content, this.listSkillDirs()).trim();
|
|
622
786
|
if (cleaned) {
|
|
623
|
-
|
|
787
|
+
fs3.writeFileSync(gitignorePath, cleaned + "\n", "utf-8");
|
|
624
788
|
} else {
|
|
625
789
|
try {
|
|
626
|
-
|
|
790
|
+
fs3.unlinkSync(gitignorePath);
|
|
627
791
|
} catch {
|
|
628
792
|
}
|
|
629
793
|
}
|
|
630
794
|
}
|
|
631
795
|
};
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
const subsectionPrefix = `mcp_servers.${serverName}.`;
|
|
635
|
-
const rawLines = raw.slice(searchStart).split("\n");
|
|
636
|
-
let offset = searchStart;
|
|
637
|
-
for (const line of rawLines) {
|
|
638
|
-
offset += line.length + 1;
|
|
639
|
-
const m = line.match(TOML_SECTION_RE);
|
|
640
|
-
if (m && !m[1].startsWith(subsectionPrefix) && m[1] !== `mcp_servers.${serverName}`) {
|
|
641
|
-
return offset - line.length - 1;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
return raw.length;
|
|
645
|
-
}
|
|
646
|
-
function buildTomlMcpSection(raw, serverName, server) {
|
|
647
|
-
const sectionHeader = `[mcp_servers.${serverName}]`;
|
|
648
|
-
const lines = [sectionHeader];
|
|
649
|
-
for (const [key, val] of Object.entries(server)) {
|
|
650
|
-
if (key === "env" && typeof val === "object" && val !== null) continue;
|
|
651
|
-
if (typeof val === "string") {
|
|
652
|
-
lines.push(`${key} = "${val}"`);
|
|
653
|
-
} else if (Array.isArray(val)) {
|
|
654
|
-
lines.push(`${key} = [${val.map((v) => `"${v}"`).join(", ")}]`);
|
|
655
|
-
} else if (typeof val === "boolean") {
|
|
656
|
-
lines.push(`${key} = ${val}`);
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
const env = server.env;
|
|
660
|
-
if (env && Object.keys(env).length > 0) {
|
|
661
|
-
lines.push("");
|
|
662
|
-
lines.push(`[mcp_servers.${serverName}.env]`);
|
|
663
|
-
for (const [key, val] of Object.entries(env)) {
|
|
664
|
-
lines.push(`${key} = "${val}"`);
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
const block = lines.join("\n");
|
|
668
|
-
let updated;
|
|
669
|
-
if (raw.includes(sectionHeader)) {
|
|
670
|
-
const startIdx = raw.indexOf(sectionHeader);
|
|
671
|
-
const endIdx = findTomlSectionEnd(raw, startIdx + sectionHeader.length, serverName);
|
|
672
|
-
const before = raw.slice(0, startIdx).trimEnd();
|
|
673
|
-
const after = raw.slice(endIdx);
|
|
674
|
-
const separator = before ? "\n\n" : "";
|
|
675
|
-
updated = (before + separator + block + after).trimEnd() + "\n";
|
|
676
|
-
} else {
|
|
677
|
-
const separator = raw.trim() ? "\n\n" : "";
|
|
678
|
-
updated = (raw.trimEnd() + separator + block).trimEnd() + "\n";
|
|
679
|
-
}
|
|
680
|
-
return updated;
|
|
681
|
-
}
|
|
682
|
-
function deepMergeSettings(target, source) {
|
|
683
|
-
const result = { ...target };
|
|
684
|
-
for (const [key, sourceVal] of Object.entries(source)) {
|
|
685
|
-
const targetVal = result[key];
|
|
686
|
-
if (Array.isArray(sourceVal) && Array.isArray(targetVal)) {
|
|
687
|
-
result[key] = [.../* @__PURE__ */ new Set([...targetVal, ...sourceVal])];
|
|
688
|
-
} else if (isPlainObject(sourceVal) && isPlainObject(targetVal)) {
|
|
689
|
-
result[key] = deepMergeSettings(
|
|
690
|
-
targetVal,
|
|
691
|
-
sourceVal
|
|
692
|
-
);
|
|
693
|
-
} else {
|
|
694
|
-
result[key] = sourceVal;
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
return result;
|
|
698
|
-
}
|
|
699
|
-
function isPlainObject(val) {
|
|
700
|
-
return typeof val === "object" && val !== null && !Array.isArray(val);
|
|
701
|
-
}
|
|
702
|
-
function deepRemoveSettings(target, template) {
|
|
703
|
-
let changed = false;
|
|
704
|
-
for (const [key, templateVal] of Object.entries(template)) {
|
|
705
|
-
const targetVal = target[key];
|
|
706
|
-
if (targetVal === void 0) continue;
|
|
707
|
-
if (Array.isArray(templateVal) && Array.isArray(targetVal)) {
|
|
708
|
-
const templateSet = new Set(templateVal.map(String));
|
|
709
|
-
const filtered = targetVal.filter((v) => !templateSet.has(String(v)));
|
|
710
|
-
if (filtered.length !== targetVal.length) {
|
|
711
|
-
if (filtered.length > 0) {
|
|
712
|
-
target[key] = filtered;
|
|
713
|
-
} else {
|
|
714
|
-
delete target[key];
|
|
715
|
-
}
|
|
716
|
-
changed = true;
|
|
717
|
-
}
|
|
718
|
-
} else if (isPlainObject(templateVal) && isPlainObject(targetVal)) {
|
|
719
|
-
if (deepRemoveSettings(targetVal, templateVal)) {
|
|
720
|
-
if (Object.keys(targetVal).length === 0) {
|
|
721
|
-
delete target[key];
|
|
722
|
-
}
|
|
723
|
-
changed = true;
|
|
724
|
-
}
|
|
725
|
-
} else {
|
|
726
|
-
if (String(targetVal) === String(templateVal)) {
|
|
727
|
-
delete target[key];
|
|
728
|
-
changed = true;
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
return changed;
|
|
733
|
-
}
|
|
734
|
-
function readJsonFile(filePath) {
|
|
735
|
-
try {
|
|
736
|
-
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
737
|
-
} catch {
|
|
738
|
-
return {};
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
function writeJsonFile(filePath, data) {
|
|
742
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
743
|
-
fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
744
|
-
}
|
|
745
|
-
function writeOrDeleteJsonFile(filePath, data) {
|
|
746
|
-
if (Object.keys(data).length === 0) {
|
|
747
|
-
try {
|
|
748
|
-
fs.unlinkSync(filePath);
|
|
749
|
-
} catch {
|
|
750
|
-
}
|
|
751
|
-
} else {
|
|
752
|
-
writeJsonFile(filePath, data);
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
function ensureAgentsMd(projectRoot, packageRoot) {
|
|
756
|
-
const agentsMdPath = path.join(projectRoot, "AGENTS.md");
|
|
757
|
-
if (fs.existsSync(agentsMdPath)) return;
|
|
796
|
+
function syncSkillSymlinks(projectRoot, skillName, opts) {
|
|
797
|
+
const selfDir = path3.dirname(new URL(import.meta.url).pathname);
|
|
758
798
|
const candidates = [
|
|
759
|
-
|
|
760
|
-
|
|
799
|
+
path3.join(selfDir, "manifests"),
|
|
800
|
+
path3.join(selfDir, "src", "symbionts", "manifests")
|
|
761
801
|
];
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
const content = fs.readFileSync(p, "utf-8");
|
|
765
|
-
fs.writeFileSync(agentsMdPath, content, "utf-8");
|
|
766
|
-
return;
|
|
767
|
-
} catch {
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
function ensureSymlink(linkPath, target) {
|
|
772
|
-
try {
|
|
773
|
-
if (fs.readlinkSync(linkPath) === target) return;
|
|
774
|
-
} catch {
|
|
775
|
-
}
|
|
776
|
-
try {
|
|
777
|
-
fs.rmSync(linkPath, { recursive: true, force: true });
|
|
778
|
-
} catch {
|
|
779
|
-
}
|
|
780
|
-
fs.symlinkSync(target, linkPath);
|
|
781
|
-
}
|
|
782
|
-
function syncSkillSymlinks(projectRoot, skillName, opts) {
|
|
783
|
-
const manifestDir = path.join(path.dirname(new URL(import.meta.url).pathname), "manifests");
|
|
784
|
-
if (!fs.existsSync(manifestDir)) return;
|
|
802
|
+
const manifestDir = candidates.find((d) => fs3.existsSync(d));
|
|
803
|
+
if (!manifestDir) return;
|
|
785
804
|
const targets = /* @__PURE__ */ new Set();
|
|
786
|
-
for (const file of
|
|
805
|
+
for (const file of fs3.readdirSync(manifestDir).filter((f) => f.endsWith(".yaml"))) {
|
|
787
806
|
try {
|
|
788
|
-
const content =
|
|
807
|
+
const content = fs3.readFileSync(path3.join(manifestDir, file), "utf-8");
|
|
789
808
|
const match = content.match(/skillsTarget:\s*(.+)/);
|
|
790
809
|
if (match) targets.add(match[1].trim());
|
|
791
810
|
} catch {
|
|
@@ -793,29 +812,46 @@ function syncSkillSymlinks(projectRoot, skillName, opts) {
|
|
|
793
812
|
}
|
|
794
813
|
for (const target of targets) {
|
|
795
814
|
if (target === CANONICAL_SKILLS_DIR) continue;
|
|
796
|
-
const agentSkillsDir =
|
|
797
|
-
const linkPath =
|
|
815
|
+
const agentSkillsDir = path3.join(projectRoot, target);
|
|
816
|
+
const linkPath = path3.join(agentSkillsDir, skillName);
|
|
798
817
|
if (opts?.remove) {
|
|
799
818
|
try {
|
|
800
|
-
|
|
819
|
+
fs3.unlinkSync(linkPath);
|
|
801
820
|
} catch {
|
|
802
821
|
}
|
|
803
822
|
try {
|
|
804
|
-
|
|
823
|
+
fs3.rmdirSync(agentSkillsDir);
|
|
805
824
|
} catch {
|
|
806
825
|
}
|
|
807
826
|
} else {
|
|
808
|
-
|
|
809
|
-
const canonicalDir =
|
|
810
|
-
const relTarget =
|
|
827
|
+
fs3.mkdirSync(agentSkillsDir, { recursive: true });
|
|
828
|
+
const canonicalDir = path3.join(projectRoot, CANONICAL_SKILLS_DIR);
|
|
829
|
+
const relTarget = path3.join(path3.relative(agentSkillsDir, canonicalDir), skillName);
|
|
811
830
|
ensureSymlink(linkPath, relTarget);
|
|
831
|
+
ensureLocalSkillsGitignore(agentSkillsDir);
|
|
812
832
|
}
|
|
813
833
|
}
|
|
814
834
|
}
|
|
835
|
+
var LOCAL_SKILLS_GITIGNORE = `# Myco-managed symlinks \u2014 generated skills are symlinked here automatically.
|
|
836
|
+
# The canonical location for all skills is .agents/skills/.
|
|
837
|
+
#
|
|
838
|
+
# To add your own skill to this directory, un-ignore it:
|
|
839
|
+
# !my-skill
|
|
840
|
+
*
|
|
841
|
+
!.gitignore
|
|
842
|
+
`;
|
|
843
|
+
function ensureLocalSkillsGitignore(agentSkillsDir) {
|
|
844
|
+
const gitignorePath = path3.join(agentSkillsDir, ".gitignore");
|
|
845
|
+
try {
|
|
846
|
+
if (fs3.readFileSync(gitignorePath, "utf-8") === LOCAL_SKILLS_GITIGNORE) return;
|
|
847
|
+
} catch {
|
|
848
|
+
}
|
|
849
|
+
fs3.writeFileSync(gitignorePath, LOCAL_SKILLS_GITIGNORE, "utf-8");
|
|
850
|
+
}
|
|
815
851
|
|
|
816
852
|
export {
|
|
817
853
|
MYCO_MCP_SERVER_NAME,
|
|
818
854
|
SymbiontInstaller,
|
|
819
855
|
syncSkillSymlinks
|
|
820
856
|
};
|
|
821
|
-
//# sourceMappingURL=chunk-
|
|
857
|
+
//# sourceMappingURL=chunk-X5IXK5KO.js.map
|