@omnidev-ai/cli 0.3.0 → 0.5.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/index.js +1094 -0
- package/package.json +35 -36
- package/src/commands/AGENTS.md +0 -41
- package/src/commands/capability.test.ts +0 -453
- package/src/commands/capability.ts +0 -166
- package/src/commands/doctor.test.ts +0 -196
- package/src/commands/doctor.ts +0 -181
- package/src/commands/init.test.ts +0 -289
- package/src/commands/init.ts +0 -188
- package/src/commands/profile.test.ts +0 -339
- package/src/commands/profile.ts +0 -153
- package/src/commands/provider.test.ts +0 -128
- package/src/commands/provider.ts +0 -139
- package/src/commands/sync.ts +0 -49
- package/src/index.ts +0 -55
- package/src/lib/debug.ts +0 -4
- package/src/lib/dynamic-app.ts +0 -180
- package/src/prompts/provider.ts +0 -17
|
@@ -1,339 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
2
|
-
import { mkdirSync } from "node:fs";
|
|
3
|
-
import { setupTestDir } from "@omnidev-ai/core/test-utils";
|
|
4
|
-
import { runProfileList, runProfileSet } from "./profile";
|
|
5
|
-
|
|
6
|
-
describe("profile commands", () => {
|
|
7
|
-
setupTestDir("profile-test-", { chdir: true });
|
|
8
|
-
let originalExit: typeof process.exit;
|
|
9
|
-
let exitCode: number | undefined;
|
|
10
|
-
let consoleOutput: string[];
|
|
11
|
-
let consoleErrors: string[];
|
|
12
|
-
let originalLog: typeof console.log;
|
|
13
|
-
let originalError: typeof console.error;
|
|
14
|
-
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
// Mock process.exit
|
|
17
|
-
exitCode = undefined;
|
|
18
|
-
originalExit = process.exit;
|
|
19
|
-
process.exit = ((code?: number) => {
|
|
20
|
-
exitCode = code ?? 0;
|
|
21
|
-
throw new Error(`process.exit(${code})`);
|
|
22
|
-
}) as typeof process.exit;
|
|
23
|
-
|
|
24
|
-
// Mock console
|
|
25
|
-
consoleOutput = [];
|
|
26
|
-
consoleErrors = [];
|
|
27
|
-
originalLog = console.log;
|
|
28
|
-
originalError = console.error;
|
|
29
|
-
console.log = (...args: unknown[]) => {
|
|
30
|
-
consoleOutput.push(args.join(" "));
|
|
31
|
-
};
|
|
32
|
-
console.error = (...args: unknown[]) => {
|
|
33
|
-
consoleErrors.push(args.join(" "));
|
|
34
|
-
};
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
afterEach(() => {
|
|
38
|
-
process.exit = originalExit;
|
|
39
|
-
console.log = originalLog;
|
|
40
|
-
console.error = originalError;
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
describe("runProfileList", () => {
|
|
44
|
-
test("should show error when config file does not exist", async () => {
|
|
45
|
-
try {
|
|
46
|
-
await runProfileList();
|
|
47
|
-
} catch {
|
|
48
|
-
// Expected to throw due to process.exit mock
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
expect(exitCode).toBe(1);
|
|
52
|
-
expect(consoleOutput.join("\n")).toContain("No config file found");
|
|
53
|
-
expect(consoleOutput.join("\n")).toContain("Run: omnidev init");
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
test("should show message when no profiles defined", async () => {
|
|
57
|
-
// Create minimal config without profiles
|
|
58
|
-
mkdirSync(".omni", { recursive: true });
|
|
59
|
-
await Bun.write(
|
|
60
|
-
"omni.toml",
|
|
61
|
-
`project = "test-project"
|
|
62
|
-
active_profile = "default"
|
|
63
|
-
`,
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
await runProfileList();
|
|
67
|
-
|
|
68
|
-
expect(exitCode).toBeUndefined();
|
|
69
|
-
expect(consoleOutput.join("\n")).toContain("No profiles defined");
|
|
70
|
-
expect(consoleOutput.join("\n")).toContain("Using default capabilities");
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test("should list all profiles from config", async () => {
|
|
74
|
-
// Create config with profiles
|
|
75
|
-
mkdirSync(".omni", { recursive: true });
|
|
76
|
-
await Bun.write(
|
|
77
|
-
"omni.toml",
|
|
78
|
-
`project = "test-project"
|
|
79
|
-
active_profile = "default"
|
|
80
|
-
|
|
81
|
-
[profiles.default]
|
|
82
|
-
capabilities = []
|
|
83
|
-
|
|
84
|
-
[profiles.planning]
|
|
85
|
-
capabilities = ["tasks", "planner"]
|
|
86
|
-
|
|
87
|
-
[profiles.coding]
|
|
88
|
-
capabilities = []
|
|
89
|
-
`,
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
await runProfileList();
|
|
93
|
-
|
|
94
|
-
expect(exitCode).toBeUndefined();
|
|
95
|
-
const output = consoleOutput.join("\n");
|
|
96
|
-
expect(output).toContain("Available Profiles:");
|
|
97
|
-
expect(output).toContain("default");
|
|
98
|
-
expect(output).toContain("planning");
|
|
99
|
-
expect(output).toContain("coding");
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
test("should show active profile with marker", async () => {
|
|
103
|
-
// Create config with profiles
|
|
104
|
-
mkdirSync(".omni", { recursive: true });
|
|
105
|
-
await Bun.write(
|
|
106
|
-
"omni.toml",
|
|
107
|
-
`project = "test-project"
|
|
108
|
-
active_profile = "planning"
|
|
109
|
-
|
|
110
|
-
[profiles.default]
|
|
111
|
-
capabilities = []
|
|
112
|
-
|
|
113
|
-
[profiles.planning]
|
|
114
|
-
capabilities = ["planner"]
|
|
115
|
-
`,
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
await runProfileList();
|
|
119
|
-
|
|
120
|
-
expect(exitCode).toBeUndefined();
|
|
121
|
-
const output = consoleOutput.join("\n");
|
|
122
|
-
expect(output).toContain("● planning (active)");
|
|
123
|
-
expect(output).toContain("○ default");
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
test("should show profile capabilities", async () => {
|
|
127
|
-
// Create config with profiles
|
|
128
|
-
mkdirSync(".omni", { recursive: true });
|
|
129
|
-
await Bun.write(
|
|
130
|
-
"omni.toml",
|
|
131
|
-
`project = "test-project"
|
|
132
|
-
active_profile = "default"
|
|
133
|
-
|
|
134
|
-
[profiles.default]
|
|
135
|
-
capabilities = []
|
|
136
|
-
|
|
137
|
-
[profiles.planning]
|
|
138
|
-
capabilities = ["planner", "tasks"]
|
|
139
|
-
`,
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
await runProfileList();
|
|
143
|
-
|
|
144
|
-
expect(exitCode).toBeUndefined();
|
|
145
|
-
const output = consoleOutput.join("\n");
|
|
146
|
-
expect(output).toContain("Capabilities: planner, tasks");
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
test("should use default_profile when no active profile", async () => {
|
|
150
|
-
// Create config with active_profile
|
|
151
|
-
mkdirSync(".omni", { recursive: true });
|
|
152
|
-
await Bun.write(
|
|
153
|
-
"omni.toml",
|
|
154
|
-
`project = "test-project"
|
|
155
|
-
active_profile = "planning"
|
|
156
|
-
|
|
157
|
-
[profiles.planning]
|
|
158
|
-
capabilities = ["planner"]
|
|
159
|
-
`,
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
await runProfileList();
|
|
163
|
-
|
|
164
|
-
expect(exitCode).toBeUndefined();
|
|
165
|
-
const output = consoleOutput.join("\n");
|
|
166
|
-
expect(output).toContain("● planning (active)");
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
test("should handle invalid config gracefully", async () => {
|
|
170
|
-
// Create invalid config
|
|
171
|
-
mkdirSync(".omni", { recursive: true });
|
|
172
|
-
await Bun.write("omni.toml", "invalid toml [[[");
|
|
173
|
-
|
|
174
|
-
try {
|
|
175
|
-
await runProfileList();
|
|
176
|
-
} catch {
|
|
177
|
-
// Expected to throw due to process.exit mock
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
expect(exitCode).toBe(1);
|
|
181
|
-
expect(consoleErrors.join("\n")).toContain("Error loading profiles");
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
describe("runProfileSet", () => {
|
|
186
|
-
test("should show error when config file does not exist", async () => {
|
|
187
|
-
try {
|
|
188
|
-
await runProfileSet("planning");
|
|
189
|
-
} catch {
|
|
190
|
-
// Expected to throw due to process.exit mock
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
expect(exitCode).toBe(1);
|
|
194
|
-
expect(consoleOutput.join("\n")).toContain("No config file found");
|
|
195
|
-
expect(consoleOutput.join("\n")).toContain("Run: omnidev init");
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
test("should show error when profile does not exist", async () => {
|
|
199
|
-
// Create config without the requested profile
|
|
200
|
-
mkdirSync(".omni", { recursive: true });
|
|
201
|
-
await Bun.write(
|
|
202
|
-
"omni.toml",
|
|
203
|
-
`project = "test-project"
|
|
204
|
-
|
|
205
|
-
[profiles.default]
|
|
206
|
-
capabilities = []
|
|
207
|
-
`,
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
try {
|
|
211
|
-
await runProfileSet("nonexistent");
|
|
212
|
-
} catch {
|
|
213
|
-
// Expected to throw due to process.exit mock
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
expect(exitCode).toBe(1);
|
|
217
|
-
const output = consoleOutput.join("\n");
|
|
218
|
-
expect(output).toContain('Profile "nonexistent" not found');
|
|
219
|
-
expect(output).toContain("Available profiles:");
|
|
220
|
-
expect(output).toContain("- default");
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
test("should set active profile", async () => {
|
|
224
|
-
// Create config with profiles
|
|
225
|
-
mkdirSync(".omni", { recursive: true });
|
|
226
|
-
await Bun.write(
|
|
227
|
-
"omni.toml",
|
|
228
|
-
`project = "test-project"
|
|
229
|
-
|
|
230
|
-
[profiles.default]
|
|
231
|
-
capabilities = []
|
|
232
|
-
|
|
233
|
-
[profiles.planning]
|
|
234
|
-
capabilities = ["planner"]
|
|
235
|
-
`,
|
|
236
|
-
);
|
|
237
|
-
|
|
238
|
-
await runProfileSet("planning");
|
|
239
|
-
|
|
240
|
-
expect(exitCode).toBeUndefined();
|
|
241
|
-
expect(consoleOutput.join("\n")).toContain("Active profile set to: planning");
|
|
242
|
-
|
|
243
|
-
// Verify active_profile was written to state file (not config.toml)
|
|
244
|
-
const stateContent = await Bun.file(".omni/state/active-profile").text();
|
|
245
|
-
expect(stateContent).toBe("planning");
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
test("should trigger agents sync after setting profile", async () => {
|
|
249
|
-
// Create config with profiles
|
|
250
|
-
mkdirSync(".omni", { recursive: true });
|
|
251
|
-
await Bun.write(
|
|
252
|
-
"omni.toml",
|
|
253
|
-
`project = "test-project"
|
|
254
|
-
active_profile = "default"
|
|
255
|
-
|
|
256
|
-
[profiles.default]
|
|
257
|
-
capabilities = []
|
|
258
|
-
|
|
259
|
-
[profiles.planning]
|
|
260
|
-
capabilities = []
|
|
261
|
-
`,
|
|
262
|
-
);
|
|
263
|
-
|
|
264
|
-
await runProfileSet("planning");
|
|
265
|
-
|
|
266
|
-
expect(exitCode).toBeUndefined();
|
|
267
|
-
const output = consoleOutput.join("\n");
|
|
268
|
-
expect(output).toContain("Syncing agent configuration");
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
test("should show list of available profiles when profile not found", async () => {
|
|
272
|
-
// Create config with multiple profiles
|
|
273
|
-
mkdirSync(".omni", { recursive: true });
|
|
274
|
-
await Bun.write(
|
|
275
|
-
"omni.toml",
|
|
276
|
-
`project = "test-project"
|
|
277
|
-
|
|
278
|
-
[profiles.default]
|
|
279
|
-
capabilities = []
|
|
280
|
-
|
|
281
|
-
[profiles.planning]
|
|
282
|
-
capabilities = []
|
|
283
|
-
|
|
284
|
-
[profiles.coding]
|
|
285
|
-
capabilities = []
|
|
286
|
-
`,
|
|
287
|
-
);
|
|
288
|
-
|
|
289
|
-
try {
|
|
290
|
-
await runProfileSet("nonexistent");
|
|
291
|
-
} catch {
|
|
292
|
-
// Expected to throw due to process.exit mock
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
expect(exitCode).toBe(1);
|
|
296
|
-
const output = consoleOutput.join("\n");
|
|
297
|
-
expect(output).toContain("Available profiles:");
|
|
298
|
-
expect(output).toContain("- default");
|
|
299
|
-
expect(output).toContain("- planning");
|
|
300
|
-
expect(output).toContain("- coding");
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
test("should handle empty profiles config", async () => {
|
|
304
|
-
// Create config without any profiles
|
|
305
|
-
mkdirSync(".omni", { recursive: true });
|
|
306
|
-
await Bun.write(
|
|
307
|
-
"omni.toml",
|
|
308
|
-
`project = "test-project"
|
|
309
|
-
`,
|
|
310
|
-
);
|
|
311
|
-
|
|
312
|
-
try {
|
|
313
|
-
await runProfileSet("default");
|
|
314
|
-
} catch {
|
|
315
|
-
// Expected to throw due to process.exit mock
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
expect(exitCode).toBe(1);
|
|
319
|
-
const output = consoleOutput.join("\n");
|
|
320
|
-
expect(output).toContain('Profile "default" not found');
|
|
321
|
-
expect(output).toContain("(none defined)");
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
test("should handle invalid config gracefully", async () => {
|
|
325
|
-
// Create invalid config
|
|
326
|
-
mkdirSync(".omni", { recursive: true });
|
|
327
|
-
await Bun.write("omni.toml", "invalid toml [[[");
|
|
328
|
-
|
|
329
|
-
try {
|
|
330
|
-
await runProfileSet("planning");
|
|
331
|
-
} catch {
|
|
332
|
-
// Expected to throw due to process.exit mock
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
expect(exitCode).toBe(1);
|
|
336
|
-
expect(consoleErrors.join("\n")).toContain("Error setting profile");
|
|
337
|
-
});
|
|
338
|
-
});
|
|
339
|
-
});
|
package/src/commands/profile.ts
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import { getEnabledAdapters } from "@omnidev-ai/adapters";
|
|
3
|
-
import {
|
|
4
|
-
getActiveProfile,
|
|
5
|
-
loadConfig,
|
|
6
|
-
resolveEnabledCapabilities,
|
|
7
|
-
setActiveProfile,
|
|
8
|
-
syncAgentConfiguration,
|
|
9
|
-
} from "@omnidev-ai/core";
|
|
10
|
-
import { buildCommand, buildRouteMap } from "@stricli/core";
|
|
11
|
-
|
|
12
|
-
const listCommand = buildCommand({
|
|
13
|
-
docs: {
|
|
14
|
-
brief: "List available profiles",
|
|
15
|
-
},
|
|
16
|
-
parameters: {},
|
|
17
|
-
async func() {
|
|
18
|
-
await runProfileList();
|
|
19
|
-
},
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
async function runSetCommand(_flags: Record<string, never>, profileName: string): Promise<void> {
|
|
23
|
-
await runProfileSet(profileName);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const setCommand = buildCommand({
|
|
27
|
-
docs: {
|
|
28
|
-
brief: "Set the active profile",
|
|
29
|
-
},
|
|
30
|
-
parameters: {
|
|
31
|
-
flags: {},
|
|
32
|
-
positional: {
|
|
33
|
-
kind: "tuple" as const,
|
|
34
|
-
parameters: [
|
|
35
|
-
{
|
|
36
|
-
brief: "Profile name",
|
|
37
|
-
parse: String,
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
func: runSetCommand,
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
export const profileRoutes = buildRouteMap({
|
|
46
|
-
routes: {
|
|
47
|
-
list: listCommand,
|
|
48
|
-
set: setCommand,
|
|
49
|
-
},
|
|
50
|
-
docs: {
|
|
51
|
-
brief: "Manage capability profiles",
|
|
52
|
-
},
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
export async function runProfileList(): Promise<void> {
|
|
56
|
-
try {
|
|
57
|
-
// Check if omni.toml exists
|
|
58
|
-
if (!existsSync("omni.toml")) {
|
|
59
|
-
console.log("✗ No config file found");
|
|
60
|
-
console.log(" Run: omnidev init");
|
|
61
|
-
process.exit(1);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Load config
|
|
65
|
-
const config = await loadConfig();
|
|
66
|
-
|
|
67
|
-
// Get active profile
|
|
68
|
-
const activeProfile = (await getActiveProfile()) ?? config.active_profile ?? "default";
|
|
69
|
-
|
|
70
|
-
// Check if profiles exist
|
|
71
|
-
const profiles = config.profiles ?? {};
|
|
72
|
-
const profileNames = Object.keys(profiles);
|
|
73
|
-
|
|
74
|
-
if (profileNames.length === 0) {
|
|
75
|
-
console.log("No profiles defined in omni.toml");
|
|
76
|
-
console.log("");
|
|
77
|
-
console.log("Using default capabilities from omni.toml");
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Display profiles
|
|
82
|
-
console.log("Available Profiles:");
|
|
83
|
-
console.log("");
|
|
84
|
-
|
|
85
|
-
for (const name of profileNames) {
|
|
86
|
-
const isActive = name === activeProfile;
|
|
87
|
-
const icon = isActive ? "●" : "○";
|
|
88
|
-
const profile = profiles[name];
|
|
89
|
-
|
|
90
|
-
if (profile === undefined) {
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
console.log(`${icon} ${name}${isActive ? " (active)" : ""}`);
|
|
95
|
-
|
|
96
|
-
// Show capabilities (including always-enabled)
|
|
97
|
-
const capabilities = resolveEnabledCapabilities(config, name);
|
|
98
|
-
if (capabilities.length > 0) {
|
|
99
|
-
console.log(` Capabilities: ${capabilities.join(", ")}`);
|
|
100
|
-
} else {
|
|
101
|
-
console.log(" Capabilities: none");
|
|
102
|
-
}
|
|
103
|
-
console.log("");
|
|
104
|
-
}
|
|
105
|
-
} catch (error) {
|
|
106
|
-
console.error("✗ Error loading profiles:", error);
|
|
107
|
-
process.exit(1);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export async function runProfileSet(profileName: string): Promise<void> {
|
|
112
|
-
try {
|
|
113
|
-
// Check if omni.toml exists
|
|
114
|
-
if (!existsSync("omni.toml")) {
|
|
115
|
-
console.log("✗ No config file found");
|
|
116
|
-
console.log(" Run: omnidev init");
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Load config
|
|
121
|
-
const config = await loadConfig();
|
|
122
|
-
|
|
123
|
-
// Validate profile exists
|
|
124
|
-
const profiles = config.profiles ?? {};
|
|
125
|
-
if (!(profileName in profiles)) {
|
|
126
|
-
console.log(`✗ Profile "${profileName}" not found in omni.toml`);
|
|
127
|
-
console.log("");
|
|
128
|
-
console.log("Available profiles:");
|
|
129
|
-
const profileNames = Object.keys(profiles);
|
|
130
|
-
if (profileNames.length === 0) {
|
|
131
|
-
console.log(" (none defined)");
|
|
132
|
-
} else {
|
|
133
|
-
for (const name of profileNames) {
|
|
134
|
-
console.log(` - ${name}`);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
process.exit(1);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Set active profile
|
|
141
|
-
await setActiveProfile(profileName);
|
|
142
|
-
|
|
143
|
-
console.log(`✓ Active profile set to: ${profileName}`);
|
|
144
|
-
console.log("");
|
|
145
|
-
|
|
146
|
-
// Auto-sync agent configuration with enabled adapters
|
|
147
|
-
const adapters = await getEnabledAdapters();
|
|
148
|
-
await syncAgentConfiguration({ adapters });
|
|
149
|
-
} catch (error) {
|
|
150
|
-
console.error("✗ Error setting profile:", error);
|
|
151
|
-
process.exit(1);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
2
|
-
import { existsSync, mkdirSync, rmSync } from "node:fs";
|
|
3
|
-
import { captureConsole, tmpdir } from "@omnidev-ai/core/test-utils";
|
|
4
|
-
import { runProviderList, runProviderEnable, runProviderDisable } from "./provider";
|
|
5
|
-
|
|
6
|
-
// Import the functions we need to test
|
|
7
|
-
async function getProviderFunctions() {
|
|
8
|
-
const { readEnabledProviders, writeEnabledProviders } = await import("@omnidev-ai/core");
|
|
9
|
-
return { readEnabledProviders, writeEnabledProviders };
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
describe("provider commands", () => {
|
|
13
|
-
let testDir: string;
|
|
14
|
-
let originalCwd: string;
|
|
15
|
-
|
|
16
|
-
beforeEach(async () => {
|
|
17
|
-
originalCwd = process.cwd();
|
|
18
|
-
testDir = tmpdir("provider-test-");
|
|
19
|
-
process.chdir(testDir);
|
|
20
|
-
|
|
21
|
-
// Create basic OmniDev structure
|
|
22
|
-
mkdirSync(".omni/state", { recursive: true });
|
|
23
|
-
await Bun.write("omni.toml", 'project = "test"\n');
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
afterEach(() => {
|
|
27
|
-
process.chdir(originalCwd);
|
|
28
|
-
if (existsSync(testDir)) {
|
|
29
|
-
rmSync(testDir, { recursive: true, force: true });
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
describe("runProviderList", () => {
|
|
34
|
-
test("lists all providers with status", async () => {
|
|
35
|
-
const { writeEnabledProviders } = await getProviderFunctions();
|
|
36
|
-
await writeEnabledProviders(["claude-code", "cursor"]);
|
|
37
|
-
|
|
38
|
-
const { stdout } = await captureConsole(async () => {
|
|
39
|
-
await runProviderList();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const output = stdout.join("\n");
|
|
43
|
-
expect(output).toContain("Available providers:");
|
|
44
|
-
expect(output).toContain("Claude Code");
|
|
45
|
-
expect(output).toContain("Cursor");
|
|
46
|
-
expect(output).toContain("Codex");
|
|
47
|
-
expect(output).toContain("OpenCode");
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test("shows enabled providers with marker", async () => {
|
|
51
|
-
const { writeEnabledProviders } = await getProviderFunctions();
|
|
52
|
-
await writeEnabledProviders(["claude-code"]);
|
|
53
|
-
|
|
54
|
-
const { stdout } = await captureConsole(async () => {
|
|
55
|
-
await runProviderList();
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
const output = stdout.join("\n");
|
|
59
|
-
// Should have at least one enabled marker
|
|
60
|
-
expect(output).toContain("●");
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test("shows disabled providers with different marker", async () => {
|
|
64
|
-
const { writeEnabledProviders } = await getProviderFunctions();
|
|
65
|
-
await writeEnabledProviders(["claude-code"]);
|
|
66
|
-
|
|
67
|
-
const { stdout } = await captureConsole(async () => {
|
|
68
|
-
await runProviderList();
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
const output = stdout.join("\n");
|
|
72
|
-
// Should have disabled markers for other providers
|
|
73
|
-
expect(output).toContain("○");
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
describe("runProviderEnable", () => {
|
|
78
|
-
test("enables a provider", async () => {
|
|
79
|
-
const { writeEnabledProviders, readEnabledProviders } = await getProviderFunctions();
|
|
80
|
-
await writeEnabledProviders(["claude-code"]);
|
|
81
|
-
|
|
82
|
-
await captureConsole(async () => {
|
|
83
|
-
await runProviderEnable({}, "cursor");
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
const providers = await readEnabledProviders();
|
|
87
|
-
expect(providers).toContain("cursor");
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test("shows success message", async () => {
|
|
91
|
-
const { writeEnabledProviders } = await getProviderFunctions();
|
|
92
|
-
await writeEnabledProviders(["claude-code"]);
|
|
93
|
-
|
|
94
|
-
const { stdout } = await captureConsole(async () => {
|
|
95
|
-
await runProviderEnable({}, "cursor");
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
const output = stdout.join("\n");
|
|
99
|
-
expect(output).toContain("✓ Enabled provider: Cursor");
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
describe("runProviderDisable", () => {
|
|
104
|
-
test("disables a provider", async () => {
|
|
105
|
-
const { writeEnabledProviders, readEnabledProviders } = await getProviderFunctions();
|
|
106
|
-
await writeEnabledProviders(["claude-code", "cursor"]);
|
|
107
|
-
|
|
108
|
-
await captureConsole(async () => {
|
|
109
|
-
await runProviderDisable({}, "cursor");
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
const providers = await readEnabledProviders();
|
|
113
|
-
expect(providers).not.toContain("cursor");
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
test("shows success message", async () => {
|
|
117
|
-
const { writeEnabledProviders } = await getProviderFunctions();
|
|
118
|
-
await writeEnabledProviders(["claude-code", "cursor"]);
|
|
119
|
-
|
|
120
|
-
const { stdout } = await captureConsole(async () => {
|
|
121
|
-
await runProviderDisable({}, "cursor");
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
const output = stdout.join("\n");
|
|
125
|
-
expect(output).toContain("✓ Disabled provider: Cursor");
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
});
|