@ken-jo/agent-connector 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/README.md +188 -20
  2. package/dist/action-PLZW5BGX.js +54 -0
  3. package/dist/action-PLZW5BGX.js.map +1 -0
  4. package/dist/{amp-YGV66GJT.js → amp-B524U6LO.js} +81 -5
  5. package/dist/amp-B524U6LO.js.map +1 -0
  6. package/dist/{antigravity-7IBYFO6P.js → antigravity-ANDKF3K7.js} +4 -4
  7. package/dist/{antigravity-cli-JEOUP2VN.js → antigravity-cli-LLRPDDOT.js} +4 -4
  8. package/dist/chunk-22Y24V7O.js +21 -0
  9. package/dist/chunk-22Y24V7O.js.map +1 -0
  10. package/dist/chunk-3PFFTFCU.js +190 -0
  11. package/dist/chunk-3PFFTFCU.js.map +1 -0
  12. package/dist/{chunk-SCVBYSF7.js → chunk-6XHB6BE3.js} +1 -1
  13. package/dist/chunk-76FUSVIA.js +43 -0
  14. package/dist/chunk-76FUSVIA.js.map +1 -0
  15. package/dist/{chunk-GSGDG2BV.js → chunk-ADTHT2FN.js} +109 -16
  16. package/dist/chunk-ADTHT2FN.js.map +1 -0
  17. package/dist/{chunk-ZAM4M7LI.js → chunk-BHUCB6LY.js} +135 -296
  18. package/dist/chunk-BHUCB6LY.js.map +1 -0
  19. package/dist/{chunk-MEH7GC7R.js → chunk-BXGFUENQ.js} +20 -3
  20. package/dist/chunk-BXGFUENQ.js.map +1 -0
  21. package/dist/chunk-CIRDOY2V.js +351 -0
  22. package/dist/chunk-CIRDOY2V.js.map +1 -0
  23. package/dist/{chunk-QADSG2JY.js → chunk-G3ER4SY5.js} +1152 -106
  24. package/dist/chunk-G3ER4SY5.js.map +1 -0
  25. package/dist/{chunk-44HUXXC6.js → chunk-G5CQHVQG.js} +232 -5
  26. package/dist/chunk-G5CQHVQG.js.map +1 -0
  27. package/dist/{chunk-PD4VFEBY.js → chunk-IW77FFNX.js} +39 -1
  28. package/dist/chunk-IW77FFNX.js.map +1 -0
  29. package/dist/chunk-J3D5W5T2.js +83 -0
  30. package/dist/chunk-J3D5W5T2.js.map +1 -0
  31. package/dist/{openclaw-UZ5BMCGQ.js → chunk-KGGBNKI4.js} +125 -33
  32. package/dist/chunk-KGGBNKI4.js.map +1 -0
  33. package/dist/{chunk-3JCRUROU.js → chunk-KGJWE6A2.js} +13 -4
  34. package/dist/chunk-KGJWE6A2.js.map +1 -0
  35. package/dist/{chunk-DS3LUFVN.js → chunk-KGXDYGNJ.js} +26 -16
  36. package/dist/chunk-KGXDYGNJ.js.map +1 -0
  37. package/dist/{chunk-KVAAFYRR.js → chunk-KHO5WNTP.js} +2 -18
  38. package/dist/chunk-KHO5WNTP.js.map +1 -0
  39. package/dist/{chunk-KQSNDFBN.js → chunk-LL4OBGRU.js} +3 -3
  40. package/dist/{chunk-WNREHWKL.js → chunk-MAH6QQTO.js} +3 -3
  41. package/dist/{claude-code-4275HQU4.js → claude-code-MLWS7CW6.js} +180 -28
  42. package/dist/claude-code-MLWS7CW6.js.map +1 -0
  43. package/dist/cli/sdk.js +4 -3
  44. package/dist/cli/sdk.js.map +1 -1
  45. package/dist/cli.js +1 -1
  46. package/dist/{codebuff-LE3KBZGM.js → codebuff-SH2S3QAN.js} +102 -5
  47. package/dist/codebuff-SH2S3QAN.js.map +1 -0
  48. package/dist/{codex-4BY2ZJIW.js → codex-BXA4FIF4.js} +3 -3
  49. package/dist/{copilot-cli-IPISKO3V.js → copilot-cli-ROIBTTDT.js} +3 -3
  50. package/dist/{crush-X3E25EQG.js → crush-QLEFLHUC.js} +3 -3
  51. package/dist/{cursor-UH3W622V.js → cursor-ASJPWZ4R.js} +6 -3
  52. package/dist/cursor-ASJPWZ4R.js.map +1 -0
  53. package/dist/{detect-MNDHGLSV.js → detect-ZIIS55LD.js} +4 -3
  54. package/dist/{detect-MNDHGLSV.js.map → detect-ZIIS55LD.js.map} +1 -1
  55. package/dist/{doctor-N5KZDD55.js → doctor-TJUGSQ5C.js} +17 -13
  56. package/dist/doctor-TJUGSQ5C.js.map +1 -0
  57. package/dist/{droid-T5VBRXZF.js → droid-NCSS3B5Y.js} +170 -4
  58. package/dist/droid-NCSS3B5Y.js.map +1 -0
  59. package/dist/{gemini-cli-ZSUK55UA.js → gemini-cli-SLVWLXJW.js} +3 -3
  60. package/dist/{goose-M3RR3CZG.js → goose-PBA7KTE5.js} +100 -5
  61. package/dist/goose-PBA7KTE5.js.map +1 -0
  62. package/dist/{hermes-CUNKIAR5.js → hermes-ONDCECP2.js} +3 -3
  63. package/dist/{hook-7LUOKIXH.js → hook-OU522ABV.js} +12 -9
  64. package/dist/{hook-7LUOKIXH.js.map → hook-OU522ABV.js.map} +1 -1
  65. package/dist/index.d.ts +71 -3
  66. package/dist/index.js +22 -3
  67. package/dist/{install-TQTT4F3I.js → install-UDCBL7HP.js} +12 -10
  68. package/dist/{install-TQTT4F3I.js.map → install-UDCBL7HP.js.map} +1 -1
  69. package/dist/introspect-DuZSPSHB.d.ts +53 -0
  70. package/dist/{jetbrains-copilot-C3HDGGML.js → jetbrains-copilot-YABZ3HFA.js} +3 -3
  71. package/dist/{kilo-PKAJCWPX.js → kilo-F3ZDZKCT.js} +3 -3
  72. package/dist/{kilo-cli-QWUVXG2O.js → kilo-cli-3HWPWBY4.js} +3 -3
  73. package/dist/{kimi-EVD7YKXS.js → kimi-NV72FVAO.js} +3 -3
  74. package/dist/{kiro-UQRY6EIO.js → kiro-C5W6AGDR.js} +3 -3
  75. package/dist/{leaderboard-MUJ7DURM.js → leaderboard-TIBVONVT.js} +3 -3
  76. package/dist/mimo-code-IMM5YM3M.js +754 -0
  77. package/dist/mimo-code-IMM5YM3M.js.map +1 -0
  78. package/dist/{mux-5CI5FP2W.js → mux-DSSH4AFS.js} +3 -3
  79. package/dist/nemoclaw-3EVNKD3I.js +58 -0
  80. package/dist/nemoclaw-3EVNKD3I.js.map +1 -0
  81. package/dist/{omp-AXA7XY22.js → omp-Z6FRNDPN.js} +3 -3
  82. package/dist/openclaw-7G437NT7.js +18 -0
  83. package/dist/openclaw-7G437NT7.js.map +1 -0
  84. package/dist/{opencode-NZBRLJN3.js → opencode-Q6KBSAKW.js} +3 -3
  85. package/dist/{package-SYPA5POO.js → package-RMPN57YZ.js} +7 -6
  86. package/dist/{package-SYPA5POO.js.map → package-RMPN57YZ.js.map} +1 -1
  87. package/dist/{pi-WMTUX6ES.js → pi-LZT6WWAZ.js} +2 -2
  88. package/dist/{qwen-code-MRRIUQ3P.js → qwen-code-WQBKRPWJ.js} +3 -3
  89. package/dist/{roo-code-NI5UU6JB.js → roo-code-GWSNU3OW.js} +137 -4
  90. package/dist/roo-code-GWSNU3OW.js.map +1 -0
  91. package/dist/runtime/index.d.ts +96 -2
  92. package/dist/runtime/index.js +18 -10
  93. package/dist/sdk/index.d.ts +52 -0
  94. package/dist/sdk/index.js +81 -0
  95. package/dist/sdk/index.js.map +1 -0
  96. package/dist/sdk/test.d.ts +74 -0
  97. package/dist/sdk/test.js +291 -0
  98. package/dist/sdk/test.js.map +1 -0
  99. package/dist/{serve-XJOSA7BY.js → serve-D3GO36UT.js} +12 -9
  100. package/dist/{serve-XJOSA7BY.js.map → serve-D3GO36UT.js.map} +1 -1
  101. package/dist/{status-DYSS6BOR.js → status-KOSKCETC.js} +10 -8
  102. package/dist/{status-DYSS6BOR.js.map → status-KOSKCETC.js.map} +1 -1
  103. package/dist/statusline-ZNTCL5YC.js +59 -0
  104. package/dist/statusline-ZNTCL5YC.js.map +1 -0
  105. package/dist/{telemetry-IJ4GP2Q3.js → telemetry-XIKUUGTQ.js} +5 -4
  106. package/dist/{telemetry-IJ4GP2Q3.js.map → telemetry-XIKUUGTQ.js.map} +1 -1
  107. package/dist/{trae-CQC72RHH.js → trae-NWT3TMSZ.js} +99 -5
  108. package/dist/trae-NWT3TMSZ.js.map +1 -0
  109. package/dist/{types-CNigfEuR.d.ts → types-BEKsAium.d.ts} +268 -6
  110. package/dist/{uninstall-3DXIBRCV.js → uninstall-2LBLQVFA.js} +12 -10
  111. package/dist/{uninstall-3DXIBRCV.js.map → uninstall-2LBLQVFA.js.map} +1 -1
  112. package/dist/{upgrade-GJEB3ITY.js → upgrade-ZC2S7VRN.js} +12 -10
  113. package/dist/{upgrade-GJEB3ITY.js.map → upgrade-ZC2S7VRN.js.map} +1 -1
  114. package/dist/{usage-2BJLM3GJ.js → usage-E2A4O2CY.js} +3 -3
  115. package/dist/{usage-event-472X3DOY.js → usage-event-JKMC4QC4.js} +11 -8
  116. package/dist/{usage-event-472X3DOY.js.map → usage-event-JKMC4QC4.js.map} +1 -1
  117. package/dist/{vscode-copilot-4RVRTCKV.js → vscode-copilot-ALV45XF6.js} +3 -3
  118. package/dist/{warp-X6MB67NT.js → warp-H6IX4U3J.js} +3 -3
  119. package/dist/{zed-NTCYW4V2.js → zed-RH34TNSW.js} +3 -3
  120. package/package.json +9 -1
  121. package/dist/amp-YGV66GJT.js.map +0 -1
  122. package/dist/chunk-3JCRUROU.js.map +0 -1
  123. package/dist/chunk-44HUXXC6.js.map +0 -1
  124. package/dist/chunk-DS3LUFVN.js.map +0 -1
  125. package/dist/chunk-GSGDG2BV.js.map +0 -1
  126. package/dist/chunk-KVAAFYRR.js.map +0 -1
  127. package/dist/chunk-MEH7GC7R.js.map +0 -1
  128. package/dist/chunk-NJU275US.js +0 -238
  129. package/dist/chunk-NJU275US.js.map +0 -1
  130. package/dist/chunk-PD4VFEBY.js.map +0 -1
  131. package/dist/chunk-QADSG2JY.js.map +0 -1
  132. package/dist/chunk-ZAM4M7LI.js.map +0 -1
  133. package/dist/claude-code-4275HQU4.js.map +0 -1
  134. package/dist/codebuff-LE3KBZGM.js.map +0 -1
  135. package/dist/cursor-UH3W622V.js.map +0 -1
  136. package/dist/doctor-N5KZDD55.js.map +0 -1
  137. package/dist/droid-T5VBRXZF.js.map +0 -1
  138. package/dist/goose-M3RR3CZG.js.map +0 -1
  139. package/dist/openclaw-UZ5BMCGQ.js.map +0 -1
  140. package/dist/roo-code-NI5UU6JB.js.map +0 -1
  141. package/dist/trae-CQC72RHH.js.map +0 -1
  142. /package/dist/{antigravity-7IBYFO6P.js.map → antigravity-ANDKF3K7.js.map} +0 -0
  143. /package/dist/{antigravity-cli-JEOUP2VN.js.map → antigravity-cli-LLRPDDOT.js.map} +0 -0
  144. /package/dist/{chunk-SCVBYSF7.js.map → chunk-6XHB6BE3.js.map} +0 -0
  145. /package/dist/{chunk-KQSNDFBN.js.map → chunk-LL4OBGRU.js.map} +0 -0
  146. /package/dist/{chunk-WNREHWKL.js.map → chunk-MAH6QQTO.js.map} +0 -0
  147. /package/dist/{codex-4BY2ZJIW.js.map → codex-BXA4FIF4.js.map} +0 -0
  148. /package/dist/{copilot-cli-IPISKO3V.js.map → copilot-cli-ROIBTTDT.js.map} +0 -0
  149. /package/dist/{crush-X3E25EQG.js.map → crush-QLEFLHUC.js.map} +0 -0
  150. /package/dist/{gemini-cli-ZSUK55UA.js.map → gemini-cli-SLVWLXJW.js.map} +0 -0
  151. /package/dist/{hermes-CUNKIAR5.js.map → hermes-ONDCECP2.js.map} +0 -0
  152. /package/dist/{jetbrains-copilot-C3HDGGML.js.map → jetbrains-copilot-YABZ3HFA.js.map} +0 -0
  153. /package/dist/{kilo-PKAJCWPX.js.map → kilo-F3ZDZKCT.js.map} +0 -0
  154. /package/dist/{kilo-cli-QWUVXG2O.js.map → kilo-cli-3HWPWBY4.js.map} +0 -0
  155. /package/dist/{kimi-EVD7YKXS.js.map → kimi-NV72FVAO.js.map} +0 -0
  156. /package/dist/{kiro-UQRY6EIO.js.map → kiro-C5W6AGDR.js.map} +0 -0
  157. /package/dist/{leaderboard-MUJ7DURM.js.map → leaderboard-TIBVONVT.js.map} +0 -0
  158. /package/dist/{mux-5CI5FP2W.js.map → mux-DSSH4AFS.js.map} +0 -0
  159. /package/dist/{omp-AXA7XY22.js.map → omp-Z6FRNDPN.js.map} +0 -0
  160. /package/dist/{opencode-NZBRLJN3.js.map → opencode-Q6KBSAKW.js.map} +0 -0
  161. /package/dist/{pi-WMTUX6ES.js.map → pi-LZT6WWAZ.js.map} +0 -0
  162. /package/dist/{qwen-code-MRRIUQ3P.js.map → qwen-code-WQBKRPWJ.js.map} +0 -0
  163. /package/dist/{usage-2BJLM3GJ.js.map → usage-E2A4O2CY.js.map} +0 -0
  164. /package/dist/{vscode-copilot-4RVRTCKV.js.map → vscode-copilot-ALV45XF6.js.map} +0 -0
  165. /package/dist/{warp-X6MB67NT.js.map → warp-H6IX4U3J.js.map} +0 -0
  166. /package/dist/{zed-NTCYW4V2.js.map → zed-RH34TNSW.js.map} +0 -0
@@ -0,0 +1,754 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ resolveEnvRefsDeep
4
+ } from "./chunk-DBQMX75U.js";
5
+ import {
6
+ BaseAdapter
7
+ } from "./chunk-IW77FFNX.js";
8
+ import "./chunk-7L6ITC4T.js";
9
+ import {
10
+ buildServeWrapperCommand,
11
+ shouldWrapForTelemetry
12
+ } from "./chunk-BXGFUENQ.js";
13
+ import "./chunk-N6HH7K6P.js";
14
+ import "./chunk-TRQKHP7D.js";
15
+
16
+ // src/adapters/mimo-code/index.ts
17
+ import {
18
+ chmodSync,
19
+ existsSync,
20
+ mkdirSync,
21
+ readFileSync,
22
+ rmSync,
23
+ writeFileSync
24
+ } from "fs";
25
+ import { homedir } from "os";
26
+ import { dirname, join } from "path";
27
+ var HOST = "mimo-code";
28
+ var MCP_ROOT_KEY = "mcp";
29
+ var CONFIG_DIR_NAME = "mimocode";
30
+ var CONFIG_FILE_NAME = "mimocode.json";
31
+ var EVENT_TO_MIMOCODE = {
32
+ PreToolUse: "tool.execute.before",
33
+ PostToolUse: "tool.execute.after",
34
+ // No real SessionStart hook (inherited from OpenCode #14808 / #5409). The
35
+ // verified surrogate is experimental.chat.system.transform.
36
+ SessionStart: "experimental.chat.system.transform"
37
+ };
38
+ var MiMoCodeAdapter = class extends BaseAdapter {
39
+ id = HOST;
40
+ name = "MiMoCode";
41
+ paradigm = "ts-plugin";
42
+ capabilities = {
43
+ // Memory surface: AGENTS.md-first managed block (CLAUDE.md fallback, like
44
+ // OpenCode — MiMoCode keeps OpenCode's CLAUDE.md import + AGENTS.md reading).
45
+ supportsMemory: true,
46
+ preToolUse: true,
47
+ postToolUse: true,
48
+ preCompact: false,
49
+ sessionStart: true,
50
+ sessionEnd: false,
51
+ userPromptSubmit: false,
52
+ stop: false,
53
+ notification: false,
54
+ // tool.execute.before mutates output.args → input rewrite supported.
55
+ canModifyArgs: true,
56
+ // tool.execute.after mutates output.output → output rewrite supported.
57
+ canModifyOutput: true,
58
+ // injected via experimental.chat.system.transform at session start.
59
+ canInjectSessionContext: true,
60
+ transports: ["stdio", "sse", "http"],
61
+ // Content surfaces: MiMoCode authors all three natively under <mcDir>
62
+ // (inherited from OpenCode's commands/skills/agent layout).
63
+ supportsCommands: true,
64
+ supportsSkills: true,
65
+ supportsSubagents: true
66
+ };
67
+ // ── Detection ──────────────────────────────────────────────────────────
68
+ detectInstalled(projectDir) {
69
+ const userConfigDir = join(homedir(), ".config", CONFIG_DIR_NAME);
70
+ const userConfig = join(userConfigDir, CONFIG_FILE_NAME);
71
+ const projectConfig = join(projectDir, CONFIG_FILE_NAME);
72
+ const userInstalled = existsSync(userConfigDir) || existsSync(userConfig);
73
+ const projInstalled = existsSync(projectConfig);
74
+ const installed = userInstalled || projInstalled;
75
+ const scope = projInstalled && !userInstalled ? "project" : "user";
76
+ const configPath = scope === "project" ? projectConfig : userConfig;
77
+ return {
78
+ id: this.id,
79
+ name: this.name,
80
+ installed,
81
+ paradigm: this.paradigm,
82
+ capabilities: this.capabilities,
83
+ configPath,
84
+ scope,
85
+ reason: installed ? scope === "project" ? `found project MiMoCode config at ${projectConfig}` : `found MiMoCode config under ${userConfigDir}` : `no MiMoCode config at ${userConfigDir}`,
86
+ confidence: installed ? "high" : "low"
87
+ };
88
+ }
89
+ // ── Memory surface: AGENTS.md / CLAUDE.md-fallback probe (project) ──────
90
+ // Mirrors OpenCode: project AGENTS.md, falling back to CLAUDE.md ONLY when no
91
+ // AGENTS.md exists (creating AGENTS.md beside a relied-on CLAUDE.md would
92
+ // shadow the user's rules). User scope stays on the BaseAdapter default.
93
+ memoryTargets(ctx) {
94
+ if (this.memoryOverride(ctx)?.path || ctx.scope !== "project") {
95
+ return super.memoryTargets(ctx);
96
+ }
97
+ const agentsMd = join(ctx.projectDir, "AGENTS.md");
98
+ if (existsSync(agentsMd)) {
99
+ return [{ path: agentsMd, reason: "AGENTS.md (mimocode's primary project rules file)" }];
100
+ }
101
+ const claudeMd = join(ctx.projectDir, "CLAUDE.md");
102
+ if (existsSync(claudeMd)) {
103
+ return [
104
+ {
105
+ path: claudeMd,
106
+ reason: "CLAUDE.md (mimocode's fallback rules file \u2014 creating AGENTS.md would shadow it)"
107
+ }
108
+ ];
109
+ }
110
+ return [{ path: agentsMd, reason: "AGENTS.md standard (created; no mimocode rules file yet)" }];
111
+ }
112
+ // ── Native paths ───────────────────────────────────────────────────────
113
+ getConfigDir(ctx) {
114
+ return ctx.scope === "project" ? ctx.projectDir : join(homedir(), ".config", CONFIG_DIR_NAME);
115
+ }
116
+ getServerConfigPath(ctx) {
117
+ return join(this.getConfigDir(ctx), CONFIG_FILE_NAME);
118
+ }
119
+ /**
120
+ * For ts-plugin hosts the "hook config path" is the generated plugin FILE.
121
+ * MiMoCode (like OpenCode) auto-loads every file in the plugin dir; writing
122
+ * this file IS the registration.
123
+ */
124
+ getHookConfigPath(ctx) {
125
+ return join(this.pluginDir(ctx), this.pluginFileName(ctx));
126
+ }
127
+ /** Plugin directory MiMoCode auto-loads modules from, per scope. */
128
+ pluginDir(ctx) {
129
+ return ctx.scope === "project" ? join(ctx.projectDir, `.${CONFIG_DIR_NAME}`, "plugin") : join(homedir(), ".config", CONFIG_DIR_NAME, "plugin");
130
+ }
131
+ /** Plugin module file name (one per connector, kebab-case id). */
132
+ pluginFileName(ctx) {
133
+ return `${ctx.connector.id}.js`;
134
+ }
135
+ // ── MCP server install / uninstall ─────────────────────────────────────
136
+ installServer(ctx) {
137
+ const server = this.effectiveServer(ctx);
138
+ const serverPath = this.getServerConfigPath(ctx);
139
+ if (!server) {
140
+ return [
141
+ {
142
+ platform: this.id,
143
+ action: "skip",
144
+ path: serverPath,
145
+ detail: ctx.connector.server ? "server registration disabled for mimo-code" : "connector declares no MCP server"
146
+ }
147
+ ];
148
+ }
149
+ const entry = this.renderServerEntry(ctx, server);
150
+ return [
151
+ this.upsertServerInJson(
152
+ serverPath,
153
+ MCP_ROOT_KEY,
154
+ ctx.connector.id,
155
+ entry,
156
+ ctx.dryRun
157
+ )
158
+ ];
159
+ }
160
+ uninstallServer(ctx) {
161
+ const serverPath = this.getServerConfigPath(ctx);
162
+ return [
163
+ this.removeServerFromJson(
164
+ serverPath,
165
+ MCP_ROOT_KEY,
166
+ ctx.connector.id,
167
+ ctx.dryRun
168
+ )
169
+ ];
170
+ }
171
+ /** Resolve the per-platform server override into an effective ServerDef. */
172
+ effectiveServer(ctx) {
173
+ const override = ctx.connector.platforms[HOST]?.server;
174
+ if (override === false) return void 0;
175
+ const base = ctx.connector.server;
176
+ if (!base) return void 0;
177
+ return override && typeof override === "object" ? { ...base, ...override } : base;
178
+ }
179
+ /**
180
+ * Render a normalized ServerDef into MiMoCode's native "mcp" entry (OpenCode
181
+ * dialect).
182
+ *
183
+ * stdio → { type: "local", command: [exe, ...args], environment }
184
+ * remote → { type: "remote", url }
185
+ *
186
+ * MiMoCode flattens command+args into a single ARRAY. When telemetry wrapping
187
+ * applies, the wrapper's command+args (which already include the real command
188
+ * tail after `--`) become the head of that array. No native interpolation
189
+ * token → resolve every ${env:VAR} reference to a literal at install time.
190
+ */
191
+ renderServerEntry(ctx, server) {
192
+ const transport = server.transport;
193
+ if (transport === "stdio") {
194
+ let command = server.command ?? "";
195
+ let args = [...server.args ?? []];
196
+ if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {
197
+ const wrapped = buildServeWrapperCommand(
198
+ ctx.homeBinPath,
199
+ ctx.connector.id,
200
+ command,
201
+ args,
202
+ ctx.scope,
203
+ this.id
204
+ );
205
+ command = wrapped.command;
206
+ args = wrapped.args;
207
+ }
208
+ const commandArray = resolveEnvRefsDeep([command, ...args]).filter(
209
+ (s) => s !== ""
210
+ );
211
+ const entry2 = {
212
+ type: "local",
213
+ command: commandArray
214
+ };
215
+ const environment = this.renderEnv(server.env);
216
+ if (environment) entry2.environment = environment;
217
+ if (server.enabled === false) entry2.enabled = false;
218
+ return entry2;
219
+ }
220
+ const entry = {
221
+ type: "remote",
222
+ url: resolveEnvRefsDeep(server.url ?? "")
223
+ };
224
+ if (server.enabled === false) entry.enabled = false;
225
+ return entry;
226
+ }
227
+ /** Render env values, resolving every ${env:VAR} reference to a literal. */
228
+ renderEnv(env) {
229
+ if (!env || Object.keys(env).length === 0) return void 0;
230
+ return resolveEnvRefsDeep({ ...env });
231
+ }
232
+ // ── Hook install / uninstall (ts-plugin) ───────────────────────────────
233
+ installHooks(ctx) {
234
+ const pluginPath = this.getHookConfigPath(ctx);
235
+ if (ctx.connector.platforms[HOST]?.hooks === false) {
236
+ return [
237
+ {
238
+ platform: this.id,
239
+ action: "skip",
240
+ path: pluginPath,
241
+ detail: "hooks disabled for mimo-code"
242
+ }
243
+ ];
244
+ }
245
+ if (ctx.connector.hookEvents.length === 0) {
246
+ return [
247
+ {
248
+ platform: this.id,
249
+ action: "skip",
250
+ path: pluginPath,
251
+ detail: "connector declares no hooks"
252
+ }
253
+ ];
254
+ }
255
+ const files = this.synthesizePlugin(ctx);
256
+ const changes = [];
257
+ for (const file of files) {
258
+ const before = existsSync(file.path) ? this.safeRead(file.path) : void 0;
259
+ let action;
260
+ if (before === void 0) action = "create";
261
+ else if (before === file.contents) action = "skip";
262
+ else action = "update";
263
+ if (action !== "skip" && !ctx.dryRun) {
264
+ ensureDir(dirname(file.path));
265
+ writeFileSync(file.path, file.contents, "utf8");
266
+ chmodSync(file.path, file.executable ? 493 : 420);
267
+ }
268
+ changes.push({
269
+ platform: this.id,
270
+ action,
271
+ path: file.path,
272
+ detail: `mimo-code plugin module (${this.hookDetail(ctx)})`
273
+ });
274
+ }
275
+ return changes;
276
+ }
277
+ /**
278
+ * Human-facing summary of which declared events the synthesized module
279
+ * ACTUALLY wires. Only events present in EVENT_TO_MIMOCODE are mapped/wired;
280
+ * any declared event with no mapping is reported separately as "unsupported
281
+ * here" so the detail never overstates coverage.
282
+ */
283
+ hookDetail(ctx) {
284
+ const declared = ctx.connector.hookEvents;
285
+ const mapped = declared.filter((e) => EVENT_TO_MIMOCODE[e] !== void 0);
286
+ const unsupported = declared.filter((e) => EVENT_TO_MIMOCODE[e] === void 0);
287
+ const base = mapped.join(",");
288
+ return unsupported.length > 0 ? `${base}; unsupported here: ${unsupported.join(",")}` : base;
289
+ }
290
+ uninstallHooks(ctx) {
291
+ const pluginPath = this.getHookConfigPath(ctx);
292
+ if (!existsSync(pluginPath)) {
293
+ return [
294
+ {
295
+ platform: this.id,
296
+ action: "skip",
297
+ path: pluginPath,
298
+ detail: "no mimo-code plugin module present"
299
+ }
300
+ ];
301
+ }
302
+ if (!ctx.dryRun) rmSync(pluginPath, { force: true });
303
+ return [
304
+ {
305
+ platform: this.id,
306
+ action: "remove",
307
+ path: pluginPath,
308
+ detail: "mimo-code plugin module"
309
+ }
310
+ ];
311
+ }
312
+ // ── Content surfaces: commands / skills / subagents ──────────────────────
313
+ // CONTENT-ONLY: pure native-file writers under <mcDir>/{commands,skills,
314
+ // agent}. No runtime dispatch, no home-bin pointer, no telemetry wrap. Each
315
+ // method is idempotent (byte-identical → skip) and reversible. Mirrors
316
+ // OpenCode's layout: commands/<name>.md, skills/<name>/SKILL.md, and the
317
+ // SINGULAR agent/<name>.md dir for subagents. For project scope the content
318
+ // root is <projectDir>/.mimocode (NOT the project root where mimocode.json
319
+ // lives).
320
+ contentRootDir(ctx) {
321
+ return ctx.scope === "project" ? join(ctx.projectDir, `.${CONFIG_DIR_NAME}`) : this.getConfigDir(ctx);
322
+ }
323
+ commandsDir(ctx) {
324
+ return join(this.contentRootDir(ctx), "commands");
325
+ }
326
+ skillsDir(ctx) {
327
+ return join(this.contentRootDir(ctx), "skills");
328
+ }
329
+ agentDir(ctx) {
330
+ return join(this.contentRootDir(ctx), "agent");
331
+ }
332
+ /** Native command file path: <mcDir>/commands/<name>.md. */
333
+ commandPath(ctx, name) {
334
+ return join(this.commandsDir(ctx), `${name}.md`);
335
+ }
336
+ /** Native skill dir: <mcDir>/skills/<name>. */
337
+ skillDir(ctx, name) {
338
+ return join(this.skillsDir(ctx), name);
339
+ }
340
+ /** Native subagent file path: <mcDir>/agent/<name>.md (SINGULAR dir). */
341
+ subagentPath(ctx, name) {
342
+ return join(this.agentDir(ctx), `${name}.md`);
343
+ }
344
+ // ── Commands ──────────────────────────────────────────────────────────────
345
+ installCommands(ctx) {
346
+ const { connector } = ctx;
347
+ if (connector.platforms[HOST]?.commands === false) {
348
+ return [{ platform: this.id, action: "skip", detail: "commands disabled for mimo-code" }];
349
+ }
350
+ if (connector.commands.length === 0) {
351
+ return [{ platform: this.id, action: "skip", detail: "connector declares no commands" }];
352
+ }
353
+ return connector.commands.map(
354
+ (cmd) => this.writeContentFile(
355
+ this.commandPath(ctx, cmd.name),
356
+ this.renderCommand(cmd),
357
+ ctx.dryRun
358
+ )
359
+ );
360
+ }
361
+ uninstallCommands(ctx) {
362
+ const { connector } = ctx;
363
+ if (connector.commands.length === 0) {
364
+ return [{ platform: this.id, action: "skip", detail: "connector declares no commands" }];
365
+ }
366
+ return connector.commands.map(
367
+ (cmd) => this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun)
368
+ );
369
+ }
370
+ /** Render a command to md+frontmatter (description, model, subtask). */
371
+ renderCommand(cmd) {
372
+ const frontmatter = {};
373
+ if (cmd.description !== void 0) frontmatter.description = cmd.description;
374
+ if (cmd.model !== void 0) frontmatter.model = cmd.model;
375
+ if (cmd.subtask !== void 0) frontmatter.subtask = cmd.subtask;
376
+ if (cmd.extra) Object.assign(frontmatter, cmd.extra);
377
+ return this.renderFrontmatterMd(frontmatter, cmd.prompt);
378
+ }
379
+ // ── Skills ────────────────────────────────────────────────────────────────
380
+ installSkills(ctx) {
381
+ const { connector } = ctx;
382
+ if (connector.platforms[HOST]?.skills === false) {
383
+ return [{ platform: this.id, action: "skip", detail: "skills disabled for mimo-code" }];
384
+ }
385
+ if (connector.skills.length === 0) {
386
+ return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
387
+ }
388
+ const changes = [];
389
+ for (const skill of connector.skills) {
390
+ const dir = this.skillDir(ctx, skill.name);
391
+ changes.push(
392
+ this.writeContentFile(join(dir, "SKILL.md"), this.renderSkill(skill), ctx.dryRun)
393
+ );
394
+ for (const [rel, contents] of Object.entries(skill.resources ?? {})) {
395
+ const target = this.resolveWithin(dir, rel);
396
+ if (target === null) {
397
+ changes.push({
398
+ platform: this.id,
399
+ action: "warn",
400
+ detail: `skill resource "${rel}" escapes the skill dir; skipped`
401
+ });
402
+ continue;
403
+ }
404
+ changes.push(this.writeContentFile(target, contents, ctx.dryRun));
405
+ }
406
+ }
407
+ return changes;
408
+ }
409
+ uninstallSkills(ctx) {
410
+ const { connector } = ctx;
411
+ if (connector.skills.length === 0) {
412
+ return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
413
+ }
414
+ const changes = [];
415
+ for (const skill of connector.skills) {
416
+ const dir = this.skillDir(ctx, skill.name);
417
+ changes.push(this.removeContentFile(join(dir, "SKILL.md"), ctx.dryRun));
418
+ for (const rel of Object.keys(skill.resources ?? {})) {
419
+ const target = this.resolveWithin(dir, rel);
420
+ if (target === null) continue;
421
+ changes.push(this.removeContentFile(target, ctx.dryRun));
422
+ }
423
+ changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));
424
+ }
425
+ return changes;
426
+ }
427
+ /**
428
+ * Render a skill's SKILL.md (UNIFORM across platforms): frontmatter
429
+ * (name, description + optional model, allowed-tools, disable-model-invocation)
430
+ * + markdown body.
431
+ */
432
+ renderSkill(skill) {
433
+ const frontmatter = {
434
+ name: skill.name,
435
+ description: skill.description
436
+ };
437
+ if (skill.model !== void 0) frontmatter.model = skill.model;
438
+ const allow = skill.tools?.allow;
439
+ if (allow && allow.length > 0) frontmatter["allowed-tools"] = allow.join(", ");
440
+ if (skill.disableModelInvocation !== void 0) {
441
+ frontmatter["disable-model-invocation"] = skill.disableModelInvocation;
442
+ }
443
+ if (skill.extra) Object.assign(frontmatter, skill.extra);
444
+ return this.renderFrontmatterMd(frontmatter, skill.body);
445
+ }
446
+ // ── Subagents ───────────────────────────────────────────────────────────────
447
+ installSubagents(ctx) {
448
+ const { connector } = ctx;
449
+ if (connector.platforms[HOST]?.subagents === false) {
450
+ return [{ platform: this.id, action: "skip", detail: "subagents disabled for mimo-code" }];
451
+ }
452
+ if (connector.subagents.length === 0) {
453
+ return [{ platform: this.id, action: "skip", detail: "connector declares no subagents" }];
454
+ }
455
+ return connector.subagents.map(
456
+ (agent) => this.writeContentFile(
457
+ this.subagentPath(ctx, agent.name),
458
+ this.renderSubagent(agent),
459
+ ctx.dryRun
460
+ )
461
+ );
462
+ }
463
+ uninstallSubagents(ctx) {
464
+ const { connector } = ctx;
465
+ if (connector.subagents.length === 0) {
466
+ return [{ platform: this.id, action: "skip", detail: "connector declares no subagents" }];
467
+ }
468
+ return connector.subagents.map(
469
+ (agent) => this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun)
470
+ );
471
+ }
472
+ /**
473
+ * Render a subagent to md+frontmatter (OpenCode's shape, inherited by
474
+ * MiMoCode): (description, mode:"subagent", model, permission) with the system
475
+ * prompt as the body. `name` comes from the filename. A readonly agent gets a
476
+ * per-tool deny map (edit/bash) so it cannot mutate the workspace.
477
+ */
478
+ renderSubagent(agent) {
479
+ const frontmatter = {
480
+ description: agent.description,
481
+ mode: "subagent"
482
+ };
483
+ if (agent.model !== void 0) frontmatter.model = agent.model;
484
+ if (agent.readonly === true) {
485
+ frontmatter.permission = { edit: "deny", bash: "deny" };
486
+ }
487
+ if (agent.extra) Object.assign(frontmatter, agent.extra);
488
+ return this.renderFrontmatterMd(frontmatter, agent.prompt);
489
+ }
490
+ // ── ts-plugin synthesis ────────────────────────────────────────────────
491
+ /**
492
+ * Build ONE self-contained ESM bridge module for MiMoCode. The module imports
493
+ * nothing from agent-connector; it embeds the home-bin path + connector id and
494
+ * a `bridge()` helper that shells out to the universal hook entrypoint
495
+ * (`<homeBin> hook mimo-code <event> --connector <id>`), feeding the payload on
496
+ * stdin and JSON.parsing the normalized HookResponse from stdout (fail-open).
497
+ */
498
+ synthesizePlugin(ctx) {
499
+ const path = this.getHookConfigPath(ctx);
500
+ const contents = this.buildPluginSource(ctx);
501
+ return [{ path, contents, executable: false }];
502
+ }
503
+ /** Compose the generated plugin source with plain string concatenation. */
504
+ buildPluginSource(ctx) {
505
+ const homeBin = JSON.stringify(ctx.homeBinPath);
506
+ const connectorId = JSON.stringify(ctx.connector.id);
507
+ const events = ctx.connector.hookEvents.filter(
508
+ (e) => EVENT_TO_MIMOCODE[e] !== void 0
509
+ );
510
+ const has = (e) => events.includes(e);
511
+ const header = `/**
512
+ * AUTO-GENERATED by agent-connector \u2014 DO NOT EDIT.
513
+ *
514
+ * Self-contained MiMoCode plugin bridge for connector ${ctx.connector.id}.
515
+ * It imports nothing from agent-connector: every hook invocation shells out to
516
+ * the stable home binary's universal entrypoint and JSON-parses the normalized
517
+ * response. Fail-open: any bridge error degrades to "allow".
518
+ */
519
+ import { execFileSync, execSync } from "node:child_process";
520
+
521
+ const HOME_BIN = ${homeBin};
522
+ const CONNECTOR_ID = ${connectorId};
523
+
524
+ /**
525
+ * Invoke the universal hook entrypoint for one event.
526
+ * @param {string} event canonical event name (PreToolUse|PostToolUse|SessionStart)
527
+ * @param {object} payload MiMoCode-shaped payload posted on stdin
528
+ * @returns {object|null} normalized HookResponse, or null on any failure
529
+ */
530
+ function bridge(event, payload) {
531
+ try {
532
+ // On Windows HOME_BIN is the agent-connector.cmd launcher: Node cannot
533
+ // execFile a batch file, and shell+args is deprecated (DEP0190), so run one
534
+ // quoted command line via a shell. POSIX keeps the direct execFile (no shell).
535
+ const args = ["hook", "mimo-code", event, "--connector", CONNECTOR_ID];
536
+ const opts = { input: JSON.stringify(payload), encoding: "utf8" };
537
+ const stdout =
538
+ process.platform === "win32"
539
+ ? execSync([HOME_BIN, ...args].map((a) => '"' + a + '"').join(" "), opts)
540
+ : execFileSync(HOME_BIN, args, opts);
541
+ const text = (stdout || "").trim();
542
+ if (text === "") return { decision: "allow" };
543
+ return JSON.parse(text);
544
+ } catch {
545
+ // Fail-open \u2014 never wedge a tool call on a bridge error.
546
+ return null;
547
+ }
548
+ }
549
+ `;
550
+ const handlers = [];
551
+ if (has("PreToolUse")) {
552
+ handlers.push(` // PreToolUse \u2192 block (throw) / rewrite args (mutate output.args).
553
+ "tool.execute.before": async (input, output) => {
554
+ const payload = {
555
+ toolName: input.tool ?? "",
556
+ toolInput: (output && output.args) ?? {},
557
+ sessionId: input.sessionID ?? "",
558
+ projectDir: PROJECT_DIR,
559
+ };
560
+ const res = bridge("PreToolUse", payload);
561
+ if (!res) return;
562
+ // MiMoCode has no "ask" gate \u2014 degrade "ask" to a block (safe direction).
563
+ if (res.decision === "deny" || res.decision === "ask") {
564
+ throw new Error(res.reason || "Blocked by ${ctx.connector.id}");
565
+ }
566
+ if (res.updatedInput && output && output.args) {
567
+ Object.assign(output.args, res.updatedInput);
568
+ }
569
+ },`);
570
+ }
571
+ if (has("PostToolUse")) {
572
+ handlers.push(` // PostToolUse \u2192 observe / rewrite tool output (mutate output.output).
573
+ "tool.execute.after": async (input, output) => {
574
+ const payload = {
575
+ toolName: input.tool ?? "",
576
+ toolInput: input.args ?? {},
577
+ toolOutput: output ? output.output : undefined,
578
+ sessionId: input.sessionID ?? "",
579
+ projectDir: PROJECT_DIR,
580
+ };
581
+ const res = bridge("PostToolUse", payload);
582
+ if (!res) return;
583
+ if (typeof res.updatedOutput === "string" && output) {
584
+ output.output = res.updatedOutput;
585
+ }
586
+ },`);
587
+ }
588
+ if (has("SessionStart")) {
589
+ handlers.push(` // SessionStart surrogate \u2192 inject context into the system prompt.
590
+ // MiMoCode has no real SessionStart hook (inherited from OpenCode
591
+ // #14808 / #5409); experimental.chat.system.transform is the injection point.
592
+ "experimental.chat.system.transform": async (input, output) => {
593
+ const payload = {
594
+ sessionId: (input && input.sessionID) ?? "",
595
+ projectDir: PROJECT_DIR,
596
+ };
597
+ const res = bridge("SessionStart", payload);
598
+ if (!res) return;
599
+ if (res.additionalContext && output && Array.isArray(output.system)) {
600
+ // Insert at index 1 (after the header) to preserve the prompt-cache
601
+ // fold (header must remain system[0]).
602
+ output.system.splice(1, 0, res.additionalContext);
603
+ }
604
+ },`);
605
+ }
606
+ const factory = `
607
+ export default async function (ctx) {
608
+ // ctx.directory is the MiMoCode project root; fall back to cwd.
609
+ const PROJECT_DIR =
610
+ (ctx && (ctx.directory || (ctx.worktree && ctx.worktree.path))) ||
611
+ process.cwd();
612
+
613
+ return {
614
+ ${handlers.join("\n")}
615
+ };
616
+ }
617
+ `;
618
+ return header + factory;
619
+ }
620
+ // ── Runtime: parse OUR bridge payload → normalized event ───────────────
621
+ /**
622
+ * `raw` is the payload OUR generated plugin posts (NOT a host-native shape):
623
+ * { toolName, toolInput, toolOutput?, isError?, sessionId, projectDir }
624
+ * so this maps straight through.
625
+ */
626
+ parseEvent(event, raw) {
627
+ const input = raw ?? {};
628
+ const base = {
629
+ hostPlatform: HOST,
630
+ connectorId: "",
631
+ sessionId: typeof input.sessionId === "string" ? input.sessionId : "",
632
+ raw,
633
+ ...typeof input.projectDir === "string" ? { projectDir: input.projectDir } : {}
634
+ };
635
+ switch (event) {
636
+ case "PreToolUse": {
637
+ const ev = {
638
+ ...base,
639
+ toolName: input.toolName ?? "",
640
+ toolInput: input.toolInput ?? {}
641
+ };
642
+ return ev;
643
+ }
644
+ case "PostToolUse": {
645
+ const ev = {
646
+ ...base,
647
+ toolName: input.toolName ?? "",
648
+ toolInput: input.toolInput ?? {},
649
+ ...typeof input.toolOutput === "string" ? { toolOutput: input.toolOutput } : {},
650
+ ...typeof input.isError === "boolean" ? { isError: input.isError } : {}
651
+ };
652
+ return ev;
653
+ }
654
+ case "SessionStart": {
655
+ const ev = { ...base, source: "startup" };
656
+ return ev;
657
+ }
658
+ default:
659
+ return { ...base, source: "startup" };
660
+ }
661
+ }
662
+ // ── Runtime: normalized response → reply the generated bridge parses ───
663
+ /**
664
+ * Our generated bridge consumes this stdout directly, so the reply body is the
665
+ * NORMALIZED HookResponse itself — the bridge JSON.parses it and reads
666
+ * decision / updatedInput / updatedOutput / additionalContext.
667
+ */
668
+ formatReply(_event, response) {
669
+ return {
670
+ exitCode: 0,
671
+ stdout: JSON.stringify(response ?? { decision: "allow" })
672
+ };
673
+ }
674
+ // ── Diagnostics ────────────────────────────────────────────────────────
675
+ getHealthChecks(ctx) {
676
+ const serverPath = this.getServerConfigPath(ctx);
677
+ const pluginPath = this.getHookConfigPath(ctx);
678
+ const connectorId = ctx.connector.id;
679
+ const hasHooks = ctx.connector.hookEvents.length > 0;
680
+ const checks = [
681
+ {
682
+ name: `${this.name}: mimocode.json present`,
683
+ check: () => existsSync(serverPath) ? { status: "OK", detail: serverPath } : { status: "FAIL", detail: `not found: ${serverPath}` }
684
+ },
685
+ {
686
+ name: `${this.name}: mcp.${connectorId} registered`,
687
+ check: () => {
688
+ if (!ctx.connector.server) {
689
+ return { status: "OK", detail: "no MCP server declared" };
690
+ }
691
+ const cfg = this.readJson(
692
+ serverPath
693
+ );
694
+ const bucket = cfg?.[MCP_ROOT_KEY];
695
+ if (!cfg || !bucket) {
696
+ return { status: "FAIL", detail: `no ${MCP_ROOT_KEY} in ${serverPath}` };
697
+ }
698
+ return connectorId in bucket ? { status: "OK", detail: `${MCP_ROOT_KEY}.${connectorId} present` } : {
699
+ status: "FAIL",
700
+ detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${serverPath}`
701
+ };
702
+ }
703
+ },
704
+ {
705
+ name: `${this.name}: plugin module present`,
706
+ check: () => {
707
+ if (!hasHooks) return { status: "OK", detail: "no hooks declared" };
708
+ return existsSync(pluginPath) ? { status: "OK", detail: pluginPath } : { status: "FAIL", detail: `not found: ${pluginPath}` };
709
+ }
710
+ }
711
+ ];
712
+ for (const cmd of ctx.connector.commands) {
713
+ const p = this.commandPath(ctx, cmd.name);
714
+ checks.push({
715
+ name: `${this.name}: command ${cmd.name} present`,
716
+ check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
717
+ });
718
+ }
719
+ for (const skill of ctx.connector.skills) {
720
+ const p = join(this.skillDir(ctx, skill.name), "SKILL.md");
721
+ checks.push({
722
+ name: `${this.name}: skill ${skill.name} present`,
723
+ check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
724
+ });
725
+ }
726
+ for (const agent of ctx.connector.subagents) {
727
+ const p = this.subagentPath(ctx, agent.name);
728
+ checks.push({
729
+ name: `${this.name}: subagent ${agent.name} present`,
730
+ check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
731
+ });
732
+ }
733
+ return checks;
734
+ }
735
+ /** Read a file, returning undefined on any error (idempotency compare). */
736
+ safeRead(path) {
737
+ try {
738
+ return readFileSync(path, "utf8");
739
+ } catch {
740
+ return void 0;
741
+ }
742
+ }
743
+ };
744
+ function ensureDir(dir) {
745
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
746
+ }
747
+ var adapter = new MiMoCodeAdapter();
748
+ var mimo_code_default = adapter;
749
+ export {
750
+ MiMoCodeAdapter,
751
+ adapter,
752
+ mimo_code_default as default
753
+ };
754
+ //# sourceMappingURL=mimo-code-IMM5YM3M.js.map