@omnidev-ai/core 0.1.0 → 0.3.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/package.json +3 -2
- package/src/capability/commands.test.ts +6 -10
- package/src/capability/commands.ts +3 -1
- package/src/capability/docs.test.ts +39 -46
- package/src/capability/docs.ts +3 -1
- package/src/capability/loader.test.ts +10 -157
- package/src/capability/loader.ts +8 -69
- package/src/capability/registry.test.ts +9 -27
- package/src/capability/rules.test.ts +25 -35
- package/src/capability/rules.ts +3 -1
- package/src/capability/skills.test.ts +6 -10
- package/src/capability/skills.ts +3 -1
- package/src/capability/sources.test.ts +142 -41
- package/src/capability/sources.ts +377 -345
- package/src/capability/subagents.test.ts +7 -11
- package/src/capability/subagents.ts +3 -1
- package/src/capability/wrapping-integration.test.ts +412 -0
- package/src/config/capabilities.ts +0 -28
- package/src/config/env.test.ts +4 -20
- package/src/config/loader.test.ts +4 -88
- package/src/config/loader.ts +88 -18
- package/src/config/parser.test.ts +0 -25
- package/src/config/profiles.test.ts +5 -42
- package/src/config/provider.test.ts +5 -18
- package/src/index.ts +1 -3
- package/src/mcp-json/manager.test.ts +77 -182
- package/src/mcp-json/manager.ts +22 -34
- package/src/state/active-profile.test.ts +4 -18
- package/src/state/index.ts +1 -0
- package/src/state/manifest.test.ts +25 -162
- package/src/state/manifest.ts +4 -31
- package/src/state/providers.test.ts +125 -0
- package/src/state/providers.ts +69 -0
- package/src/sync.ts +128 -53
- package/src/templates/claude.ts +9 -74
- package/src/test-utils/helpers.test.ts +18 -0
- package/src/test-utils/helpers.ts +98 -1
- package/src/test-utils/index.ts +4 -0
- package/src/types/capability-export.ts +0 -77
- package/src/types/index.ts +66 -22
- package/src/gitignore/manager.test.ts +0 -219
- package/src/gitignore/manager.ts +0 -167
|
@@ -1,48 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { tmpdir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
5
2
|
import type { LoadedCapability } from "../types";
|
|
6
|
-
import {
|
|
3
|
+
import type { ResourceManifest } from "../state/manifest";
|
|
4
|
+
import { setupTestDir } from "@omnidev-ai/core/test-utils";
|
|
5
|
+
import { readMcpJson, syncMcpJson, writeMcpJson } from "./manager";
|
|
7
6
|
|
|
8
7
|
describe("mcp-json manager", () => {
|
|
9
|
-
|
|
10
|
-
let tempDir: string;
|
|
11
|
-
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
originalCwd = process.cwd();
|
|
14
|
-
tempDir = mkdtempSync(join(tmpdir(), "mcp-json-test-"));
|
|
15
|
-
mkdirSync(join(tempDir, ".omni"), { recursive: true });
|
|
16
|
-
process.chdir(tempDir);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
afterEach(() => {
|
|
20
|
-
process.chdir(originalCwd);
|
|
21
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
describe("isOmniDevMcp", () => {
|
|
25
|
-
test("returns true for 'omnidev' server name", () => {
|
|
26
|
-
expect(isOmniDevMcp("omnidev")).toBe(true);
|
|
27
|
-
});
|
|
8
|
+
setupTestDir("mcp-json-test-", { chdir: true, createOmniDir: true });
|
|
28
9
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
test("returns false for non-OmniDev server names", () => {
|
|
36
|
-
expect(isOmniDevMcp("myserver")).toBe(false);
|
|
37
|
-
expect(isOmniDevMcp("playwright")).toBe(false);
|
|
38
|
-
expect(isOmniDevMcp("custom-mcp")).toBe(false);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test("returns false for similar but different names", () => {
|
|
42
|
-
expect(isOmniDevMcp("omnidev-extra")).toBe(false);
|
|
43
|
-
expect(isOmniDevMcp("my-omnidev")).toBe(false);
|
|
44
|
-
expect(isOmniDevMcp("omnisomething")).toBe(false);
|
|
45
|
-
});
|
|
10
|
+
const createEmptyManifest = (): ResourceManifest => ({
|
|
11
|
+
version: 1,
|
|
12
|
+
syncedAt: new Date().toISOString(),
|
|
13
|
+
capabilities: {},
|
|
46
14
|
});
|
|
47
15
|
|
|
48
16
|
describe("readMcpJson", () => {
|
|
@@ -147,68 +115,8 @@ describe("mcp-json manager", () => {
|
|
|
147
115
|
exports: {},
|
|
148
116
|
});
|
|
149
117
|
|
|
150
|
-
describe("
|
|
151
|
-
test("adds
|
|
152
|
-
const capabilities = [createMockCapability("tasks")];
|
|
153
|
-
|
|
154
|
-
await syncMcpJson(capabilities, true, { silent: true });
|
|
155
|
-
|
|
156
|
-
const config = await readMcpJson();
|
|
157
|
-
expect(config.mcpServers).toHaveProperty("omnidev");
|
|
158
|
-
expect(config.mcpServers.omnidev).toEqual({
|
|
159
|
-
command: "bunx",
|
|
160
|
-
args: ["omnidev", "serve"],
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
test("removes omni- prefixed servers when switching to sandbox enabled", async () => {
|
|
165
|
-
// Pre-populate with omni- entries
|
|
166
|
-
await Bun.write(
|
|
167
|
-
".mcp.json",
|
|
168
|
-
JSON.stringify({
|
|
169
|
-
mcpServers: {
|
|
170
|
-
"omni-tasks": { command: "npx", args: ["tasks-mcp"] },
|
|
171
|
-
"omni-context7": { command: "npx", args: ["context7-mcp"] },
|
|
172
|
-
},
|
|
173
|
-
}),
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
const capabilities = [
|
|
177
|
-
createMockCapability("tasks", { command: "npx", args: ["tasks-mcp"] }),
|
|
178
|
-
];
|
|
179
|
-
|
|
180
|
-
await syncMcpJson(capabilities, true, { silent: true });
|
|
181
|
-
|
|
182
|
-
const config = await readMcpJson();
|
|
183
|
-
expect(config.mcpServers).not.toHaveProperty("omni-tasks");
|
|
184
|
-
expect(config.mcpServers).not.toHaveProperty("omni-context7");
|
|
185
|
-
expect(config.mcpServers).toHaveProperty("omnidev");
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
test("preserves user MCPs when sandbox enabled", async () => {
|
|
189
|
-
await Bun.write(
|
|
190
|
-
".mcp.json",
|
|
191
|
-
JSON.stringify({
|
|
192
|
-
mcpServers: {
|
|
193
|
-
myserver: { command: "node", args: ["my-server.js"] },
|
|
194
|
-
playwright: { command: "npx", args: ["@playwright/mcp"] },
|
|
195
|
-
},
|
|
196
|
-
}),
|
|
197
|
-
);
|
|
198
|
-
|
|
199
|
-
const capabilities = [createMockCapability("tasks")];
|
|
200
|
-
|
|
201
|
-
await syncMcpJson(capabilities, true, { silent: true });
|
|
202
|
-
|
|
203
|
-
const config = await readMcpJson();
|
|
204
|
-
expect(config.mcpServers).toHaveProperty("myserver");
|
|
205
|
-
expect(config.mcpServers).toHaveProperty("playwright");
|
|
206
|
-
expect(config.mcpServers).toHaveProperty("omnidev");
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
describe("sandbox disabled mode", () => {
|
|
211
|
-
test("adds omni- prefixed servers for MCP capabilities", async () => {
|
|
118
|
+
describe("MCP wrapping", () => {
|
|
119
|
+
test("adds MCP servers using capability ID", async () => {
|
|
212
120
|
const capabilities = [
|
|
213
121
|
createMockCapability("context7", {
|
|
214
122
|
command: "npx",
|
|
@@ -216,15 +124,14 @@ describe("mcp-json manager", () => {
|
|
|
216
124
|
}),
|
|
217
125
|
];
|
|
218
126
|
|
|
219
|
-
await syncMcpJson(capabilities,
|
|
127
|
+
await syncMcpJson(capabilities, createEmptyManifest(), { silent: true });
|
|
220
128
|
|
|
221
129
|
const config = await readMcpJson();
|
|
222
|
-
expect(config.mcpServers).toHaveProperty("
|
|
223
|
-
expect(config.mcpServers["
|
|
130
|
+
expect(config.mcpServers).toHaveProperty("context7");
|
|
131
|
+
expect(config.mcpServers["context7"]).toEqual({
|
|
224
132
|
command: "npx",
|
|
225
133
|
args: ["-y", "@upstash/context7-mcp"],
|
|
226
134
|
});
|
|
227
|
-
expect(config.mcpServers).not.toHaveProperty("omnidev");
|
|
228
135
|
});
|
|
229
136
|
|
|
230
137
|
test("does not add entries for capabilities without MCP", async () => {
|
|
@@ -233,11 +140,11 @@ describe("mcp-json manager", () => {
|
|
|
233
140
|
createMockCapability("context7", { command: "npx", args: ["context7-mcp"] }),
|
|
234
141
|
];
|
|
235
142
|
|
|
236
|
-
await syncMcpJson(capabilities,
|
|
143
|
+
await syncMcpJson(capabilities, createEmptyManifest(), { silent: true });
|
|
237
144
|
|
|
238
145
|
const config = await readMcpJson();
|
|
239
|
-
expect(config.mcpServers).not.toHaveProperty("
|
|
240
|
-
expect(config.mcpServers).toHaveProperty("
|
|
146
|
+
expect(config.mcpServers).not.toHaveProperty("tasks");
|
|
147
|
+
expect(config.mcpServers).toHaveProperty("context7");
|
|
241
148
|
});
|
|
242
149
|
|
|
243
150
|
test("includes env when present in MCP config", async () => {
|
|
@@ -249,37 +156,49 @@ describe("mcp-json manager", () => {
|
|
|
249
156
|
}),
|
|
250
157
|
];
|
|
251
158
|
|
|
252
|
-
await syncMcpJson(capabilities,
|
|
159
|
+
await syncMcpJson(capabilities, createEmptyManifest(), { silent: true });
|
|
253
160
|
|
|
254
161
|
const config = await readMcpJson();
|
|
255
|
-
expect(config.mcpServers["
|
|
162
|
+
expect(config.mcpServers["my-cap"].env).toEqual({
|
|
256
163
|
API_KEY: "secret",
|
|
257
164
|
DEBUG: "true",
|
|
258
165
|
});
|
|
259
166
|
});
|
|
260
167
|
|
|
261
|
-
test("removes
|
|
168
|
+
test("removes previously managed MCP from manifest", async () => {
|
|
169
|
+
// Setup: pre-populate .mcp.json with an old MCP
|
|
262
170
|
await Bun.write(
|
|
263
171
|
".mcp.json",
|
|
264
172
|
JSON.stringify({
|
|
265
173
|
mcpServers: {
|
|
266
|
-
|
|
174
|
+
oldcap: { command: "npx", args: ["old-mcp"] },
|
|
175
|
+
userserver: { command: "node", args: ["user.js"] },
|
|
267
176
|
},
|
|
268
177
|
}),
|
|
269
178
|
);
|
|
270
179
|
|
|
180
|
+
// Previous manifest tracks oldcap as managed
|
|
181
|
+
const previousManifest: ResourceManifest = {
|
|
182
|
+
version: 1,
|
|
183
|
+
syncedAt: new Date().toISOString(),
|
|
184
|
+
capabilities: {
|
|
185
|
+
oldcap: { skills: [], rules: [], commands: [], subagents: [], mcps: ["oldcap"] },
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
|
|
271
189
|
const capabilities = [
|
|
272
190
|
createMockCapability("context7", { command: "npx", args: ["context7-mcp"] }),
|
|
273
191
|
];
|
|
274
192
|
|
|
275
|
-
await syncMcpJson(capabilities,
|
|
193
|
+
await syncMcpJson(capabilities, previousManifest, { silent: true });
|
|
276
194
|
|
|
277
195
|
const config = await readMcpJson();
|
|
278
|
-
expect(config.mcpServers).not.toHaveProperty("
|
|
279
|
-
expect(config.mcpServers).toHaveProperty("
|
|
196
|
+
expect(config.mcpServers).not.toHaveProperty("oldcap"); // Removed (was managed)
|
|
197
|
+
expect(config.mcpServers).toHaveProperty("userserver"); // Preserved (not managed)
|
|
198
|
+
expect(config.mcpServers).toHaveProperty("context7"); // Added
|
|
280
199
|
});
|
|
281
200
|
|
|
282
|
-
test("preserves user MCPs
|
|
201
|
+
test("preserves user MCPs", async () => {
|
|
283
202
|
await Bun.write(
|
|
284
203
|
".mcp.json",
|
|
285
204
|
JSON.stringify({
|
|
@@ -293,122 +212,98 @@ describe("mcp-json manager", () => {
|
|
|
293
212
|
createMockCapability("context7", { command: "npx", args: ["context7-mcp"] }),
|
|
294
213
|
];
|
|
295
214
|
|
|
296
|
-
await syncMcpJson(capabilities,
|
|
215
|
+
await syncMcpJson(capabilities, createEmptyManifest(), { silent: true });
|
|
297
216
|
|
|
298
217
|
const config = await readMcpJson();
|
|
299
218
|
expect(config.mcpServers).toHaveProperty("myserver");
|
|
300
|
-
expect(config.mcpServers).toHaveProperty("
|
|
219
|
+
expect(config.mcpServers).toHaveProperty("context7");
|
|
301
220
|
});
|
|
302
221
|
|
|
303
|
-
test("
|
|
222
|
+
test("does not add entries when no MCP capabilities", async () => {
|
|
304
223
|
const capabilities = [
|
|
305
224
|
createMockCapability("tasks"), // No MCP
|
|
306
225
|
createMockCapability("ralph"), // No MCP
|
|
307
226
|
];
|
|
308
227
|
|
|
309
|
-
await syncMcpJson(capabilities,
|
|
228
|
+
await syncMcpJson(capabilities, createEmptyManifest(), { silent: true });
|
|
310
229
|
|
|
311
230
|
const config = await readMcpJson();
|
|
312
|
-
|
|
313
|
-
expect(
|
|
314
|
-
});
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
describe("mode switching", () => {
|
|
318
|
-
test("switching from sandbox disabled to enabled cleans up correctly", async () => {
|
|
319
|
-
// Start in sandbox disabled mode
|
|
320
|
-
const capabilities = [
|
|
321
|
-
createMockCapability("context7", { command: "npx", args: ["context7-mcp"] }),
|
|
322
|
-
];
|
|
323
|
-
await syncMcpJson(capabilities, false, { silent: true });
|
|
324
|
-
|
|
325
|
-
let config = await readMcpJson();
|
|
326
|
-
expect(config.mcpServers).toHaveProperty("omni-context7");
|
|
327
|
-
expect(config.mcpServers).not.toHaveProperty("omnidev");
|
|
328
|
-
|
|
329
|
-
// Switch to sandbox enabled
|
|
330
|
-
await syncMcpJson(capabilities, true, { silent: true });
|
|
331
|
-
|
|
332
|
-
config = await readMcpJson();
|
|
333
|
-
expect(config.mcpServers).not.toHaveProperty("omni-context7");
|
|
334
|
-
expect(config.mcpServers).toHaveProperty("omnidev");
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
test("switching from sandbox enabled to disabled cleans up correctly", async () => {
|
|
338
|
-
// Start in sandbox enabled mode
|
|
339
|
-
const capabilities = [
|
|
340
|
-
createMockCapability("context7", { command: "npx", args: ["context7-mcp"] }),
|
|
341
|
-
];
|
|
342
|
-
await syncMcpJson(capabilities, true, { silent: true });
|
|
343
|
-
|
|
344
|
-
let config = await readMcpJson();
|
|
345
|
-
expect(config.mcpServers).toHaveProperty("omnidev");
|
|
346
|
-
expect(config.mcpServers).not.toHaveProperty("omni-context7");
|
|
347
|
-
|
|
348
|
-
// Switch to sandbox disabled
|
|
349
|
-
await syncMcpJson(capabilities, false, { silent: true });
|
|
350
|
-
|
|
351
|
-
config = await readMcpJson();
|
|
352
|
-
expect(config.mcpServers).toHaveProperty("omni-context7");
|
|
353
|
-
expect(config.mcpServers).not.toHaveProperty("omnidev");
|
|
231
|
+
expect(config.mcpServers).not.toHaveProperty("tasks");
|
|
232
|
+
expect(config.mcpServers).not.toHaveProperty("ralph");
|
|
354
233
|
});
|
|
355
234
|
});
|
|
356
235
|
|
|
357
|
-
describe("capability toggle
|
|
236
|
+
describe("capability toggle", () => {
|
|
358
237
|
test("enabling MCP capability adds its entry", async () => {
|
|
359
238
|
// Start with no MCP capabilities
|
|
360
|
-
|
|
239
|
+
let manifest = createEmptyManifest();
|
|
240
|
+
await syncMcpJson([createMockCapability("tasks")], manifest, { silent: true });
|
|
361
241
|
|
|
362
242
|
let config = await readMcpJson();
|
|
363
|
-
expect(Object.keys(config.mcpServers)
|
|
364
|
-
|
|
365
|
-
// Enable MCP capability
|
|
243
|
+
expect(Object.keys(config.mcpServers)).toHaveLength(0);
|
|
244
|
+
|
|
245
|
+
// Enable MCP capability - update manifest to track tasks (no mcps)
|
|
246
|
+
manifest = {
|
|
247
|
+
version: 1,
|
|
248
|
+
syncedAt: new Date().toISOString(),
|
|
249
|
+
capabilities: {
|
|
250
|
+
tasks: { skills: [], rules: [], commands: [], subagents: [], mcps: [] },
|
|
251
|
+
},
|
|
252
|
+
};
|
|
366
253
|
await syncMcpJson(
|
|
367
254
|
[
|
|
368
255
|
createMockCapability("tasks"),
|
|
369
256
|
createMockCapability("context7", { command: "npx", args: ["context7-mcp"] }),
|
|
370
257
|
],
|
|
371
|
-
|
|
258
|
+
manifest,
|
|
372
259
|
{ silent: true },
|
|
373
260
|
);
|
|
374
261
|
|
|
375
262
|
config = await readMcpJson();
|
|
376
|
-
expect(config.mcpServers).toHaveProperty("
|
|
263
|
+
expect(config.mcpServers).toHaveProperty("context7");
|
|
377
264
|
});
|
|
378
265
|
|
|
379
266
|
test("disabling MCP capability removes its entry", async () => {
|
|
380
267
|
// Start with MCP capability
|
|
268
|
+
let manifest = createEmptyManifest();
|
|
381
269
|
await syncMcpJson(
|
|
382
270
|
[createMockCapability("context7", { command: "npx", args: ["context7-mcp"] })],
|
|
383
|
-
|
|
271
|
+
manifest,
|
|
384
272
|
{ silent: true },
|
|
385
273
|
);
|
|
386
274
|
|
|
387
275
|
let config = await readMcpJson();
|
|
388
|
-
expect(config.mcpServers).toHaveProperty("
|
|
389
|
-
|
|
390
|
-
// Disable the capability
|
|
391
|
-
|
|
276
|
+
expect(config.mcpServers).toHaveProperty("context7");
|
|
277
|
+
|
|
278
|
+
// Disable the capability - manifest now tracks context7 with its MCP
|
|
279
|
+
manifest = {
|
|
280
|
+
version: 1,
|
|
281
|
+
syncedAt: new Date().toISOString(),
|
|
282
|
+
capabilities: {
|
|
283
|
+
context7: { skills: [], rules: [], commands: [], subagents: [], mcps: ["context7"] },
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
await syncMcpJson([createMockCapability("tasks")], manifest, { silent: true });
|
|
392
287
|
|
|
393
288
|
config = await readMcpJson();
|
|
394
|
-
expect(config.mcpServers).not.toHaveProperty("
|
|
289
|
+
expect(config.mcpServers).not.toHaveProperty("context7");
|
|
395
290
|
});
|
|
396
291
|
});
|
|
397
292
|
|
|
398
293
|
describe("multiple MCP capabilities", () => {
|
|
399
|
-
test("adds all MCP capabilities
|
|
294
|
+
test("adds all MCP capabilities", async () => {
|
|
400
295
|
const capabilities = [
|
|
401
296
|
createMockCapability("context7", { command: "npx", args: ["context7-mcp"] }),
|
|
402
297
|
createMockCapability("playwright", { command: "npx", args: ["playwright-mcp"] }),
|
|
403
298
|
createMockCapability("tasks"), // No MCP
|
|
404
299
|
];
|
|
405
300
|
|
|
406
|
-
await syncMcpJson(capabilities,
|
|
301
|
+
await syncMcpJson(capabilities, createEmptyManifest(), { silent: true });
|
|
407
302
|
|
|
408
303
|
const config = await readMcpJson();
|
|
409
|
-
expect(config.mcpServers).toHaveProperty("
|
|
410
|
-
expect(config.mcpServers).toHaveProperty("
|
|
411
|
-
expect(config.mcpServers).not.toHaveProperty("
|
|
304
|
+
expect(config.mcpServers).toHaveProperty("context7");
|
|
305
|
+
expect(config.mcpServers).toHaveProperty("playwright");
|
|
306
|
+
expect(config.mcpServers).not.toHaveProperty("tasks");
|
|
412
307
|
});
|
|
413
308
|
});
|
|
414
309
|
});
|
package/src/mcp-json/manager.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import type { LoadedCapability, McpConfig } from "../types";
|
|
3
|
+
import type { ResourceManifest } from "../state/manifest";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* MCP server configuration in .mcp.json
|
|
@@ -19,13 +20,6 @@ export interface McpJsonConfig {
|
|
|
19
20
|
|
|
20
21
|
const MCP_JSON_PATH = ".mcp.json";
|
|
21
22
|
|
|
22
|
-
/**
|
|
23
|
-
* Check if a server name is managed by OmniDev
|
|
24
|
-
*/
|
|
25
|
-
export function isOmniDevMcp(serverName: string): boolean {
|
|
26
|
-
return serverName === "omnidev" || serverName.startsWith("omni-");
|
|
27
|
-
}
|
|
28
|
-
|
|
29
23
|
/**
|
|
30
24
|
* Read .mcp.json or return empty config if doesn't exist
|
|
31
25
|
*/
|
|
@@ -70,49 +64,43 @@ function buildMcpServerConfig(mcp: McpConfig): McpServerConfig {
|
|
|
70
64
|
}
|
|
71
65
|
|
|
72
66
|
/**
|
|
73
|
-
* Sync .mcp.json
|
|
67
|
+
* Sync .mcp.json with enabled capability MCP servers
|
|
74
68
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* - Capability MCPs run as children of OmniDev server
|
|
78
|
-
*
|
|
79
|
-
* When sandboxEnabled = false:
|
|
80
|
-
* - Each capability's MCP is registered as "omni-{capabilityId}"
|
|
81
|
-
* - OmniDev server is NOT registered
|
|
69
|
+
* Each capability with an [mcp] section is registered using its capability ID.
|
|
70
|
+
* Uses the previous manifest to track which MCPs were managed by OmniDev.
|
|
82
71
|
*/
|
|
83
72
|
export async function syncMcpJson(
|
|
84
73
|
capabilities: LoadedCapability[],
|
|
85
|
-
|
|
74
|
+
previousManifest: ResourceManifest,
|
|
86
75
|
options: { silent?: boolean } = {},
|
|
87
76
|
): Promise<void> {
|
|
88
77
|
const mcpJson = await readMcpJson();
|
|
89
78
|
|
|
90
|
-
//
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
79
|
+
// Collect all MCP server names from previous manifest
|
|
80
|
+
const previouslyManagedMcps = new Set<string>();
|
|
81
|
+
for (const resources of Object.values(previousManifest.capabilities)) {
|
|
82
|
+
for (const mcpName of resources.mcps) {
|
|
83
|
+
previouslyManagedMcps.add(mcpName);
|
|
94
84
|
}
|
|
95
85
|
}
|
|
96
86
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
mcpJson.mcpServers[
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
87
|
+
// Remove previously managed MCPs
|
|
88
|
+
for (const serverName of previouslyManagedMcps) {
|
|
89
|
+
delete mcpJson.mcpServers[serverName];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Add MCPs from all enabled capabilities
|
|
93
|
+
let addedCount = 0;
|
|
94
|
+
for (const cap of capabilities) {
|
|
95
|
+
if (cap.config.mcp) {
|
|
96
|
+
mcpJson.mcpServers[cap.id] = buildMcpServerConfig(cap.config.mcp);
|
|
97
|
+
addedCount++;
|
|
109
98
|
}
|
|
110
99
|
}
|
|
111
100
|
|
|
112
101
|
await writeMcpJson(mcpJson);
|
|
113
102
|
|
|
114
103
|
if (!options.silent) {
|
|
115
|
-
|
|
116
|
-
console.log(` - .mcp.json (${count} MCP server(s))`);
|
|
104
|
+
console.log(` - .mcp.json (${addedCount} MCP server(s))`);
|
|
117
105
|
}
|
|
118
106
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { existsSync, mkdirSync
|
|
3
|
-
import {
|
|
4
|
-
import { join } from "node:path";
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
3
|
+
import { setupTestDir } from "@omnidev-ai/core/test-utils";
|
|
5
4
|
import {
|
|
6
5
|
clearActiveProfileState,
|
|
7
6
|
readActiveProfileState,
|
|
@@ -9,20 +8,7 @@ import {
|
|
|
9
8
|
} from "./active-profile";
|
|
10
9
|
|
|
11
10
|
describe("active-profile state", () => {
|
|
12
|
-
|
|
13
|
-
let tempDir: string;
|
|
14
|
-
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
originalCwd = process.cwd();
|
|
17
|
-
tempDir = mkdtempSync(join(tmpdir(), "active-profile-test-"));
|
|
18
|
-
mkdirSync(join(tempDir, ".omni"), { recursive: true });
|
|
19
|
-
process.chdir(tempDir);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
afterEach(() => {
|
|
23
|
-
process.chdir(originalCwd);
|
|
24
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
25
|
-
});
|
|
11
|
+
setupTestDir("active-profile-test-", { chdir: true, createOmniDir: true });
|
|
26
12
|
|
|
27
13
|
describe("readActiveProfileState", () => {
|
|
28
14
|
test("returns null when state file does not exist", async () => {
|
package/src/state/index.ts
CHANGED