zenox 1.0.5 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/constants.d.ts +8 -0
- package/dist/cli/index.js +246 -31
- package/dist/cli/mcp-picker.d.ts +4 -0
- package/dist/cli/mcp.d.ts +1 -0
- package/dist/cli/model-picker.d.ts +4 -4
- package/dist/cli/types.d.ts +20 -0
- package/dist/cli/zenox-config.d.ts +4 -2
- package/package.json +1 -1
package/dist/cli/constants.d.ts
CHANGED
|
@@ -8,3 +8,11 @@ export interface AgentInfo {
|
|
|
8
8
|
}
|
|
9
9
|
export declare const AGENTS: AgentInfo[];
|
|
10
10
|
export declare const DEFAULT_MODELS: Record<AgentName, string>;
|
|
11
|
+
export type McpName = "exa" | "grep_app" | "sequential-thinking";
|
|
12
|
+
export interface McpInfo {
|
|
13
|
+
name: McpName;
|
|
14
|
+
displayName: string;
|
|
15
|
+
description: string;
|
|
16
|
+
recommended: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare const MCP_SERVERS: McpInfo[];
|
package/dist/cli/index.js
CHANGED
|
@@ -2256,6 +2256,9 @@ var {
|
|
|
2256
2256
|
Help
|
|
2257
2257
|
} = import__.default;
|
|
2258
2258
|
|
|
2259
|
+
// node_modules/@clack/prompts/dist/index.mjs
|
|
2260
|
+
import { stripVTControlCharacters as S2 } from "node:util";
|
|
2261
|
+
|
|
2259
2262
|
// node_modules/@clack/core/dist/index.mjs
|
|
2260
2263
|
var import_sisteransi = __toESM(require_src(), 1);
|
|
2261
2264
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
@@ -2880,6 +2883,21 @@ ${import_picocolors2.default.cyan(d2)}
|
|
|
2880
2883
|
}
|
|
2881
2884
|
} }).prompt();
|
|
2882
2885
|
};
|
|
2886
|
+
var Me = (t = "", n = "") => {
|
|
2887
|
+
const r2 = `
|
|
2888
|
+
${t}
|
|
2889
|
+
`.split(`
|
|
2890
|
+
`), i = S2(n).length, s = Math.max(r2.reduce((a, l2) => {
|
|
2891
|
+
const $2 = S2(l2);
|
|
2892
|
+
return $2.length > a ? $2.length : a;
|
|
2893
|
+
}, 0), i) + 2, c = r2.map((a) => `${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(a)}${" ".repeat(s - S2(a).length)}${import_picocolors2.default.gray(o)}`).join(`
|
|
2894
|
+
`);
|
|
2895
|
+
process.stdout.write(`${import_picocolors2.default.gray(o)}
|
|
2896
|
+
${import_picocolors2.default.green(C)} ${import_picocolors2.default.reset(n)} ${import_picocolors2.default.gray(_2.repeat(Math.max(s - i - 1, 1)) + me)}
|
|
2897
|
+
${c}
|
|
2898
|
+
${import_picocolors2.default.gray(de + _2.repeat(s + 2) + pe)}
|
|
2899
|
+
`);
|
|
2900
|
+
};
|
|
2883
2901
|
var xe = (t = "") => {
|
|
2884
2902
|
process.stdout.write(`${import_picocolors2.default.gray(d2)} ${import_picocolors2.default.red(t)}
|
|
2885
2903
|
|
|
@@ -2972,7 +2990,7 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
|
2972
2990
|
};
|
|
2973
2991
|
|
|
2974
2992
|
// src/cli/install.ts
|
|
2975
|
-
var
|
|
2993
|
+
var import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
2976
2994
|
|
|
2977
2995
|
// src/cli/config-manager.ts
|
|
2978
2996
|
import { existsSync } from "node:fs";
|
|
@@ -3106,6 +3124,26 @@ var DEFAULT_MODELS = {
|
|
|
3106
3124
|
oracle: "openai/gpt-5.2",
|
|
3107
3125
|
"ui-planner": "google/gemini-3-pro-high"
|
|
3108
3126
|
};
|
|
3127
|
+
var MCP_SERVERS = [
|
|
3128
|
+
{
|
|
3129
|
+
name: "exa",
|
|
3130
|
+
displayName: "Exa",
|
|
3131
|
+
description: "Web search & code context via Exa AI",
|
|
3132
|
+
recommended: true
|
|
3133
|
+
},
|
|
3134
|
+
{
|
|
3135
|
+
name: "grep_app",
|
|
3136
|
+
displayName: "grep.app",
|
|
3137
|
+
description: "GitHub code search - find real-world examples",
|
|
3138
|
+
recommended: true
|
|
3139
|
+
},
|
|
3140
|
+
{
|
|
3141
|
+
name: "sequential-thinking",
|
|
3142
|
+
displayName: "Sequential Thinking",
|
|
3143
|
+
description: "Structured reasoning for complex problems",
|
|
3144
|
+
recommended: true
|
|
3145
|
+
}
|
|
3146
|
+
];
|
|
3109
3147
|
|
|
3110
3148
|
// src/cli/config-manager.ts
|
|
3111
3149
|
var CONFIG_FILENAMES = ["opencode.json", "opencode.jsonc"];
|
|
@@ -3172,17 +3210,17 @@ function addPluginToJsonc(content) {
|
|
|
3172
3210
|
const afterTrimmed = afterBrace.trimStart();
|
|
3173
3211
|
if (afterTrimmed.startsWith("}")) {
|
|
3174
3212
|
return `${beforeBrace}
|
|
3175
|
-
"
|
|
3213
|
+
"plugin": ["${PACKAGE_NAME}"]
|
|
3176
3214
|
}`;
|
|
3177
3215
|
} else {
|
|
3178
3216
|
return `${beforeBrace}
|
|
3179
|
-
"
|
|
3217
|
+
"plugin": ["${PACKAGE_NAME}"],
|
|
3180
3218
|
${afterBrace.trimStart()}`;
|
|
3181
3219
|
}
|
|
3182
3220
|
}
|
|
3183
3221
|
}
|
|
3184
3222
|
function addPluginToJson(config) {
|
|
3185
|
-
const existingKey = config.plugins ? "plugins" : config.plugin ? "plugin" : "
|
|
3223
|
+
const existingKey = config.plugins ? "plugins" : config.plugin ? "plugin" : "plugin";
|
|
3186
3224
|
const existingPlugins = config.plugins ?? config.plugin ?? [];
|
|
3187
3225
|
const newConfig = {
|
|
3188
3226
|
[existingKey]: [PACKAGE_NAME, ...existingPlugins],
|
|
@@ -3209,7 +3247,7 @@ function getDefaultConfigPath(directory) {
|
|
|
3209
3247
|
}
|
|
3210
3248
|
async function createDefaultConfig(configPath) {
|
|
3211
3249
|
const defaultConfig = {
|
|
3212
|
-
|
|
3250
|
+
plugin: [PACKAGE_NAME]
|
|
3213
3251
|
};
|
|
3214
3252
|
await writeFile(configPath, JSON.stringify(defaultConfig, null, 2) + `
|
|
3215
3253
|
`, "utf-8");
|
|
@@ -3267,28 +3305,77 @@ function getCurrentModels(config) {
|
|
|
3267
3305
|
}
|
|
3268
3306
|
return result;
|
|
3269
3307
|
}
|
|
3308
|
+
function getDisabledMcps(config) {
|
|
3309
|
+
return config?.disabled_mcps ?? [];
|
|
3310
|
+
}
|
|
3311
|
+
async function updateDisabledMcps(disabledMcps) {
|
|
3312
|
+
const existing = await readZenoxConfig() ?? {};
|
|
3313
|
+
if (disabledMcps.length === 0) {
|
|
3314
|
+
const { disabled_mcps: _3, ...rest } = existing;
|
|
3315
|
+
if (Object.keys(rest).length === 0) {
|
|
3316
|
+
return;
|
|
3317
|
+
}
|
|
3318
|
+
await writeZenoxConfig(rest);
|
|
3319
|
+
} else {
|
|
3320
|
+
await writeZenoxConfig({
|
|
3321
|
+
...existing,
|
|
3322
|
+
disabled_mcps: disabledMcps
|
|
3323
|
+
});
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
3270
3326
|
|
|
3271
3327
|
// src/cli/model-picker.ts
|
|
3328
|
+
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
3272
3329
|
var CUSTOM_MODEL_OPTION = "__custom__";
|
|
3330
|
+
function formatModelName(modelId) {
|
|
3331
|
+
return modelId.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
3332
|
+
}
|
|
3273
3333
|
function extractUserModels(config) {
|
|
3274
|
-
const models = new
|
|
3334
|
+
const models = new Map;
|
|
3275
3335
|
const provider = config.provider;
|
|
3276
|
-
if (
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3336
|
+
if (provider) {
|
|
3337
|
+
for (const [providerName, providerConfig] of Object.entries(provider)) {
|
|
3338
|
+
if (!providerConfig || typeof providerConfig !== "object")
|
|
3339
|
+
continue;
|
|
3340
|
+
const providerModels = providerConfig.models;
|
|
3341
|
+
if (!providerModels)
|
|
3342
|
+
continue;
|
|
3343
|
+
for (const [modelId, modelConfig] of Object.entries(providerModels)) {
|
|
3344
|
+
const fullId = `${providerName}/${modelId}`;
|
|
3345
|
+
const cfg = modelConfig;
|
|
3346
|
+
models.set(fullId, {
|
|
3347
|
+
id: fullId,
|
|
3348
|
+
displayName: cfg?.name ?? formatModelName(modelId),
|
|
3349
|
+
provider: providerName
|
|
3350
|
+
});
|
|
3351
|
+
}
|
|
3286
3352
|
}
|
|
3287
3353
|
}
|
|
3288
|
-
|
|
3354
|
+
if (config.model && typeof config.model === "string" && config.model.includes("/")) {
|
|
3355
|
+
const [providerName, modelId] = config.model.split("/");
|
|
3356
|
+
if (!models.has(config.model)) {
|
|
3357
|
+
models.set(config.model, {
|
|
3358
|
+
id: config.model,
|
|
3359
|
+
displayName: formatModelName(modelId),
|
|
3360
|
+
provider: providerName
|
|
3361
|
+
});
|
|
3362
|
+
}
|
|
3363
|
+
}
|
|
3364
|
+
if (config.small_model && typeof config.small_model === "string" && config.small_model.includes("/")) {
|
|
3365
|
+
const [providerName, modelId] = config.small_model.split("/");
|
|
3366
|
+
if (!models.has(config.small_model)) {
|
|
3367
|
+
models.set(config.small_model, {
|
|
3368
|
+
id: config.small_model,
|
|
3369
|
+
displayName: formatModelName(modelId),
|
|
3370
|
+
provider: providerName
|
|
3371
|
+
});
|
|
3372
|
+
}
|
|
3373
|
+
}
|
|
3374
|
+
return Array.from(models.values()).sort((a, b3) => a.id.localeCompare(b3.id));
|
|
3289
3375
|
}
|
|
3290
3376
|
function buildModelOptions(agent, userModels, currentModel) {
|
|
3291
3377
|
const options = [];
|
|
3378
|
+
const userModelIds = userModels.map((m2) => m2.id);
|
|
3292
3379
|
const isDefault = !currentModel || currentModel === agent.defaultModel;
|
|
3293
3380
|
options.push({
|
|
3294
3381
|
value: agent.defaultModel,
|
|
@@ -3296,16 +3383,16 @@ function buildModelOptions(agent, userModels, currentModel) {
|
|
|
3296
3383
|
hint: "Recommended - Default"
|
|
3297
3384
|
});
|
|
3298
3385
|
for (const model of userModels) {
|
|
3299
|
-
if (model === agent.defaultModel)
|
|
3386
|
+
if (model.id === agent.defaultModel)
|
|
3300
3387
|
continue;
|
|
3301
|
-
const isCurrent = currentModel === model;
|
|
3388
|
+
const isCurrent = currentModel === model.id;
|
|
3302
3389
|
options.push({
|
|
3303
|
-
value: model,
|
|
3304
|
-
label: `${model}${isCurrent ? " (Current)" : ""}`,
|
|
3305
|
-
hint:
|
|
3390
|
+
value: model.id,
|
|
3391
|
+
label: `${model.id}${isCurrent ? " (Current)" : ""}`,
|
|
3392
|
+
hint: `${model.displayName} • Your config`
|
|
3306
3393
|
});
|
|
3307
3394
|
}
|
|
3308
|
-
if (currentModel && currentModel !== agent.defaultModel && !
|
|
3395
|
+
if (currentModel && currentModel !== agent.defaultModel && !userModelIds.includes(currentModel)) {
|
|
3309
3396
|
options.push({
|
|
3310
3397
|
value: currentModel,
|
|
3311
3398
|
label: `${currentModel} (Current)`,
|
|
@@ -3320,9 +3407,11 @@ function buildModelOptions(agent, userModels, currentModel) {
|
|
|
3320
3407
|
return options;
|
|
3321
3408
|
}
|
|
3322
3409
|
async function pickModelForAgent(agent, userModels, currentModel) {
|
|
3410
|
+
Me(`${import_picocolors3.default.bold(agent.description)}
|
|
3411
|
+
${import_picocolors3.default.dim(`Default: ${agent.defaultModel}`)}`, agent.displayName);
|
|
3323
3412
|
const options = buildModelOptions(agent, userModels, currentModel);
|
|
3324
3413
|
const selected = await ve({
|
|
3325
|
-
message:
|
|
3414
|
+
message: "Select model:",
|
|
3326
3415
|
options
|
|
3327
3416
|
});
|
|
3328
3417
|
if (pD(selected))
|
|
@@ -3397,6 +3486,63 @@ async function selectAgentsToReconfigure(currentModels) {
|
|
|
3397
3486
|
return selected;
|
|
3398
3487
|
}
|
|
3399
3488
|
|
|
3489
|
+
// src/cli/mcp-picker.ts
|
|
3490
|
+
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
3491
|
+
async function askConfigureMcps() {
|
|
3492
|
+
const result = await ve({
|
|
3493
|
+
message: "Configure MCP servers?",
|
|
3494
|
+
options: [
|
|
3495
|
+
{
|
|
3496
|
+
value: "keep_all",
|
|
3497
|
+
label: "Keep all enabled (Recommended)",
|
|
3498
|
+
hint: "All MCPs are free & enhance capabilities"
|
|
3499
|
+
},
|
|
3500
|
+
{
|
|
3501
|
+
value: "customize",
|
|
3502
|
+
label: "Customize",
|
|
3503
|
+
hint: "Disable specific MCPs"
|
|
3504
|
+
}
|
|
3505
|
+
]
|
|
3506
|
+
});
|
|
3507
|
+
if (pD(result))
|
|
3508
|
+
return null;
|
|
3509
|
+
return result;
|
|
3510
|
+
}
|
|
3511
|
+
async function pickMcpsToEnable(currentDisabled) {
|
|
3512
|
+
Me(`${import_picocolors4.default.dim("All MCPs are free and recommended for best experience.")}
|
|
3513
|
+
${import_picocolors4.default.dim("Unselect only if you have specific conflicts.")}`, "MCP Servers");
|
|
3514
|
+
const allMcpNames = MCP_SERVERS.map((m2) => m2.name);
|
|
3515
|
+
const options = MCP_SERVERS.map((mcp) => {
|
|
3516
|
+
const hint = mcp.recommended ? `${mcp.description} ${import_picocolors4.default.green("• Recommended")}` : mcp.description;
|
|
3517
|
+
return {
|
|
3518
|
+
value: mcp.name,
|
|
3519
|
+
label: mcp.displayName,
|
|
3520
|
+
hint
|
|
3521
|
+
};
|
|
3522
|
+
});
|
|
3523
|
+
const initialValues = allMcpNames.filter((name) => !currentDisabled.includes(name));
|
|
3524
|
+
const selected = await fe({
|
|
3525
|
+
message: "Select MCPs to ENABLE (unselect to disable):",
|
|
3526
|
+
options,
|
|
3527
|
+
initialValues,
|
|
3528
|
+
required: false
|
|
3529
|
+
});
|
|
3530
|
+
if (pD(selected))
|
|
3531
|
+
return null;
|
|
3532
|
+
const enabledMcps = selected;
|
|
3533
|
+
const disabledMcps = allMcpNames.filter((name) => !enabledMcps.includes(name));
|
|
3534
|
+
return disabledMcps;
|
|
3535
|
+
}
|
|
3536
|
+
function showMcpStatus(disabledMcps) {
|
|
3537
|
+
M2.info("MCP Server Status:");
|
|
3538
|
+
for (const mcp of MCP_SERVERS) {
|
|
3539
|
+
const isDisabled = disabledMcps.includes(mcp.name);
|
|
3540
|
+
const status = isDisabled ? import_picocolors4.default.red("✗ Disabled") : import_picocolors4.default.green("✓ Enabled");
|
|
3541
|
+
const rec = mcp.recommended ? import_picocolors4.default.dim(" (Recommended)") : "";
|
|
3542
|
+
M2.message(` ${mcp.displayName}: ${status}${rec}`);
|
|
3543
|
+
}
|
|
3544
|
+
}
|
|
3545
|
+
|
|
3400
3546
|
// src/cli/install.ts
|
|
3401
3547
|
async function runInstall(options = {}) {
|
|
3402
3548
|
const { noTui = false, configPath: customConfigPath } = options;
|
|
@@ -3408,7 +3554,7 @@ async function runInstall(options = {}) {
|
|
|
3408
3554
|
await runInteractive(cwd, customConfigPath);
|
|
3409
3555
|
}
|
|
3410
3556
|
async function runInteractive(cwd, customConfigPath) {
|
|
3411
|
-
Ie(
|
|
3557
|
+
Ie(import_picocolors5.default.cyan(`${PACKAGE_NAME} installer`));
|
|
3412
3558
|
const configFile = customConfigPath ? { path: customConfigPath, format: "json" } : findConfigFile(cwd);
|
|
3413
3559
|
let opencodeConfig = null;
|
|
3414
3560
|
if (!configFile) {
|
|
@@ -3491,7 +3637,33 @@ async function runInteractive(cwd, customConfigPath) {
|
|
|
3491
3637
|
M2.info("Using default models - no zenox.json needed");
|
|
3492
3638
|
}
|
|
3493
3639
|
}
|
|
3494
|
-
|
|
3640
|
+
const mcpChoice = await askConfigureMcps();
|
|
3641
|
+
if (mcpChoice === null) {
|
|
3642
|
+
xe("Installation cancelled");
|
|
3643
|
+
process.exit(0);
|
|
3644
|
+
}
|
|
3645
|
+
if (mcpChoice === "customize") {
|
|
3646
|
+
const zenoxConfig = await readZenoxConfig();
|
|
3647
|
+
const currentDisabled = getDisabledMcps(zenoxConfig);
|
|
3648
|
+
const disabledMcps = await pickMcpsToEnable(currentDisabled);
|
|
3649
|
+
if (disabledMcps === null) {
|
|
3650
|
+
xe("Installation cancelled");
|
|
3651
|
+
process.exit(0);
|
|
3652
|
+
}
|
|
3653
|
+
if (disabledMcps.length > 0) {
|
|
3654
|
+
const spinner = Y2();
|
|
3655
|
+
spinner.start("Saving MCP configuration");
|
|
3656
|
+
try {
|
|
3657
|
+
await updateDisabledMcps(disabledMcps);
|
|
3658
|
+
spinner.stop(`Disabled ${disabledMcps.length} MCP(s)`);
|
|
3659
|
+
} catch (err) {
|
|
3660
|
+
spinner.stop("Failed to save MCP config");
|
|
3661
|
+
M2.error(err instanceof Error ? err.message : "Unknown error");
|
|
3662
|
+
process.exit(1);
|
|
3663
|
+
}
|
|
3664
|
+
}
|
|
3665
|
+
}
|
|
3666
|
+
Se(import_picocolors5.default.green(`${PACKAGE_NAME} installed successfully!`));
|
|
3495
3667
|
}
|
|
3496
3668
|
async function runNonInteractive(cwd, customConfigPath) {
|
|
3497
3669
|
const configFile = customConfigPath ? { path: customConfigPath, format: "json" } : findConfigFile(cwd);
|
|
@@ -3515,9 +3687,9 @@ async function runNonInteractive(cwd, customConfigPath) {
|
|
|
3515
3687
|
}
|
|
3516
3688
|
|
|
3517
3689
|
// src/cli/config.ts
|
|
3518
|
-
var
|
|
3690
|
+
var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
3519
3691
|
async function runConfig() {
|
|
3520
|
-
Ie(
|
|
3692
|
+
Ie(import_picocolors6.default.cyan(`${PACKAGE_NAME} model configurator`));
|
|
3521
3693
|
const cwd = process.cwd();
|
|
3522
3694
|
let userModels = [];
|
|
3523
3695
|
const configFile = findConfigFile(cwd);
|
|
@@ -3533,7 +3705,7 @@ async function runConfig() {
|
|
|
3533
3705
|
for (const agent of AGENTS) {
|
|
3534
3706
|
const model = currentModels[agent.name] ?? agent.defaultModel;
|
|
3535
3707
|
const isCustom = currentModels[agent.name] !== undefined;
|
|
3536
|
-
const suffix = isCustom ?
|
|
3708
|
+
const suffix = isCustom ? import_picocolors6.default.yellow(" (custom)") : import_picocolors6.default.dim(" (default)");
|
|
3537
3709
|
M2.message(` ${agent.displayName}: ${model}${suffix}`);
|
|
3538
3710
|
}
|
|
3539
3711
|
const selectedAgents = await selectAgentsToReconfigure(currentModels);
|
|
@@ -3543,7 +3715,7 @@ async function runConfig() {
|
|
|
3543
3715
|
}
|
|
3544
3716
|
if (selectedAgents.length === 0) {
|
|
3545
3717
|
M2.warn("No agents selected");
|
|
3546
|
-
Se(
|
|
3718
|
+
Se(import_picocolors6.default.yellow("No changes made"));
|
|
3547
3719
|
return;
|
|
3548
3720
|
}
|
|
3549
3721
|
const newModels = {};
|
|
@@ -3586,7 +3758,42 @@ async function runConfig() {
|
|
|
3586
3758
|
} else {
|
|
3587
3759
|
M2.info("All agents using default models - zenox.json not needed");
|
|
3588
3760
|
}
|
|
3589
|
-
Se(
|
|
3761
|
+
Se(import_picocolors6.default.green("Configuration updated!"));
|
|
3762
|
+
}
|
|
3763
|
+
|
|
3764
|
+
// src/cli/mcp.ts
|
|
3765
|
+
var import_picocolors7 = __toESM(require_picocolors(), 1);
|
|
3766
|
+
async function runMcp() {
|
|
3767
|
+
Ie(import_picocolors7.default.cyan(`${PACKAGE_NAME} MCP configurator`));
|
|
3768
|
+
const zenoxConfig = await readZenoxConfig();
|
|
3769
|
+
const currentDisabled = getDisabledMcps(zenoxConfig);
|
|
3770
|
+
showMcpStatus(currentDisabled);
|
|
3771
|
+
const newDisabled = await pickMcpsToEnable(currentDisabled);
|
|
3772
|
+
if (newDisabled === null) {
|
|
3773
|
+
xe("Configuration cancelled");
|
|
3774
|
+
process.exit(0);
|
|
3775
|
+
}
|
|
3776
|
+
const hasChanges = newDisabled.length !== currentDisabled.length || newDisabled.some((m2) => !currentDisabled.includes(m2));
|
|
3777
|
+
if (!hasChanges) {
|
|
3778
|
+
Se(import_picocolors7.default.yellow("No changes made"));
|
|
3779
|
+
return;
|
|
3780
|
+
}
|
|
3781
|
+
const spinner = Y2();
|
|
3782
|
+
spinner.start("Saving MCP configuration");
|
|
3783
|
+
try {
|
|
3784
|
+
await updateDisabledMcps(newDisabled);
|
|
3785
|
+
if (newDisabled.length === 0) {
|
|
3786
|
+
spinner.stop("All MCPs enabled");
|
|
3787
|
+
} else {
|
|
3788
|
+
spinner.stop(`Updated ${getZenoxConfigPath()}`);
|
|
3789
|
+
}
|
|
3790
|
+
} catch (err) {
|
|
3791
|
+
spinner.stop("Failed to save config");
|
|
3792
|
+
M2.error(err instanceof Error ? err.message : "Unknown error");
|
|
3793
|
+
process.exit(1);
|
|
3794
|
+
}
|
|
3795
|
+
showMcpStatus(newDisabled);
|
|
3796
|
+
Se(import_picocolors7.default.green("MCP configuration updated!"));
|
|
3590
3797
|
}
|
|
3591
3798
|
|
|
3592
3799
|
// src/cli/index.ts
|
|
@@ -3611,4 +3818,12 @@ program2.command("config").alias("models").description("Reconfigure sub-agent mo
|
|
|
3611
3818
|
process.exit(1);
|
|
3612
3819
|
}
|
|
3613
3820
|
});
|
|
3821
|
+
program2.command("mcp").description("Configure MCP servers (enable/disable)").action(async () => {
|
|
3822
|
+
try {
|
|
3823
|
+
await runMcp();
|
|
3824
|
+
} catch (err) {
|
|
3825
|
+
console.error(err instanceof Error ? err.message : "Unknown error");
|
|
3826
|
+
process.exit(1);
|
|
3827
|
+
}
|
|
3828
|
+
});
|
|
3614
3829
|
program2.parse();
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type McpName } from "./constants";
|
|
2
|
+
export declare function askConfigureMcps(): Promise<"keep_all" | "customize" | null>;
|
|
3
|
+
export declare function pickMcpsToEnable(currentDisabled: McpName[]): Promise<McpName[] | null>;
|
|
4
|
+
export declare function showMcpStatus(disabledMcps: McpName[]): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runMcp(): Promise<void>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { OpencodeConfig } from "./types";
|
|
1
|
+
import type { OpencodeConfig, UserModelInfo } from "./types";
|
|
2
2
|
import type { AgentName, AgentInfo } from "./constants";
|
|
3
|
-
export declare function extractUserModels(config: OpencodeConfig):
|
|
4
|
-
export declare function pickModelForAgent(agent: AgentInfo, userModels:
|
|
5
|
-
export declare function pickModelsForAllAgents(userModels:
|
|
3
|
+
export declare function extractUserModels(config: OpencodeConfig): UserModelInfo[];
|
|
4
|
+
export declare function pickModelForAgent(agent: AgentInfo, userModels: UserModelInfo[], currentModel?: string): Promise<string | null>;
|
|
5
|
+
export declare function pickModelsForAllAgents(userModels: UserModelInfo[], currentModels: Partial<Record<AgentName, string>>): Promise<Partial<Record<AgentName, string>> | null>;
|
|
6
6
|
export declare function askConfigureModels(): Promise<"defaults" | "customize" | null>;
|
|
7
7
|
export declare function selectAgentsToReconfigure(currentModels: Partial<Record<AgentName, string>>): Promise<AgentName[] | null>;
|
package/dist/cli/types.d.ts
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
|
+
export interface ModelConfig {
|
|
2
|
+
id?: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
options?: Record<string, unknown>;
|
|
5
|
+
variants?: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
export interface ProviderConfig {
|
|
8
|
+
npm?: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
options?: Record<string, unknown>;
|
|
11
|
+
models?: Record<string, ModelConfig>;
|
|
12
|
+
}
|
|
1
13
|
export interface OpencodeConfig {
|
|
2
14
|
plugins?: string[];
|
|
3
15
|
plugin?: string[];
|
|
16
|
+
model?: string;
|
|
17
|
+
small_model?: string;
|
|
18
|
+
provider?: Record<string, ProviderConfig>;
|
|
4
19
|
[key: string]: unknown;
|
|
5
20
|
}
|
|
21
|
+
export interface UserModelInfo {
|
|
22
|
+
id: string;
|
|
23
|
+
displayName: string;
|
|
24
|
+
provider: string;
|
|
25
|
+
}
|
|
6
26
|
export interface InstallOptions {
|
|
7
27
|
noTui?: boolean;
|
|
8
28
|
configPath?: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentName } from "./constants";
|
|
1
|
+
import type { AgentName, McpName } from "./constants";
|
|
2
2
|
export interface ZenoxConfigAgents {
|
|
3
3
|
[key: string]: {
|
|
4
4
|
model: string;
|
|
@@ -7,10 +7,12 @@ export interface ZenoxConfigAgents {
|
|
|
7
7
|
export interface ZenoxConfig {
|
|
8
8
|
agents?: ZenoxConfigAgents;
|
|
9
9
|
disabled_agents?: string[];
|
|
10
|
-
disabled_mcps?:
|
|
10
|
+
disabled_mcps?: McpName[];
|
|
11
11
|
}
|
|
12
12
|
export declare function getZenoxConfigPath(): string;
|
|
13
13
|
export declare function readZenoxConfig(): Promise<ZenoxConfig | null>;
|
|
14
14
|
export declare function writeZenoxConfig(config: ZenoxConfig): Promise<void>;
|
|
15
15
|
export declare function updateAgentModels(models: Partial<Record<AgentName, string>>): Promise<void>;
|
|
16
16
|
export declare function getCurrentModels(config: ZenoxConfig | null): Partial<Record<AgentName, string>>;
|
|
17
|
+
export declare function getDisabledMcps(config: ZenoxConfig | null): McpName[];
|
|
18
|
+
export declare function updateDisabledMcps(disabledMcps: McpName[]): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zenox",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "OpenCode plugin with specialized agents (explorer, librarian, oracle, ui-planner), background tasks for parallel execution, and smart orchestration",
|
|
5
5
|
"author": "Ayush",
|
|
6
6
|
"license": "MIT",
|