@mutagent/cli 0.1.220 → 0.1.221
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/bin/cli.js +182 -90
- package/dist/bin/cli.js.map +11 -10
- package/dist/index.js +75 -18
- package/dist/index.js.map +6 -5
- package/package.json +2 -2
package/dist/bin/cli.js
CHANGED
|
@@ -58,6 +58,7 @@ function loadConfig() {
|
|
|
58
58
|
apiKey: process.env.MUTAGENT_API_KEY ?? credentials?.apiKey ?? rcConfig?.apiKey,
|
|
59
59
|
endpoint: process.env.MUTAGENT_ENDPOINT ?? credentials?.endpoint ?? rcConfig?.endpoint,
|
|
60
60
|
defaultWorkspace: credentials?.defaultWorkspace ?? rcConfig?.defaultWorkspace,
|
|
61
|
+
defaultWorkspaceSource: credentials?.defaultWorkspace ? credentials.defaultWorkspaceSource ?? "login-inferred" : rcConfig?.defaultWorkspace ? "login-inferred" : undefined,
|
|
61
62
|
defaultOrganization: credentials?.defaultOrganization ?? rcConfig?.defaultOrganization
|
|
62
63
|
};
|
|
63
64
|
return configSchema.parse(merged);
|
|
@@ -83,11 +84,15 @@ function saveFullCredentials(creds) {
|
|
|
83
84
|
existingCredentials = JSON.parse(readFileSync(CREDENTIALS_FILE, "utf-8"));
|
|
84
85
|
} catch {}
|
|
85
86
|
}
|
|
87
|
+
const existingSource = existingCredentials.defaultWorkspaceSource;
|
|
88
|
+
const workspaceChanged = creds.workspaceId !== undefined && creds.workspaceId !== existingCredentials.defaultWorkspace;
|
|
89
|
+
const source = creds.workspaceId === undefined ? existingSource : workspaceChanged ? "login-inferred" : existingSource ?? "login-inferred";
|
|
86
90
|
const credentials = {
|
|
87
91
|
...existingCredentials,
|
|
88
92
|
apiKey: creds.apiKey,
|
|
89
93
|
endpoint: creds.endpoint ?? existingCredentials.endpoint ?? "https://api.mutagent.io",
|
|
90
94
|
defaultWorkspace: creds.workspaceId ?? existingCredentials.defaultWorkspace,
|
|
95
|
+
defaultWorkspaceSource: source,
|
|
91
96
|
defaultOrganization: creds.organizationId ?? existingCredentials.defaultOrganization,
|
|
92
97
|
expiresAt: creds.expiresAt
|
|
93
98
|
};
|
|
@@ -109,7 +114,7 @@ function hasCredentials() {
|
|
|
109
114
|
function getApiKey() {
|
|
110
115
|
return process.env.MUTAGENT_API_KEY ?? loadConfig().apiKey;
|
|
111
116
|
}
|
|
112
|
-
function setDefaultWorkspace(workspaceId) {
|
|
117
|
+
function setDefaultWorkspace(workspaceId, source = "user") {
|
|
113
118
|
if (!existsSync(CREDENTIALS_DIR)) {
|
|
114
119
|
mkdirSync(CREDENTIALS_DIR, { recursive: true });
|
|
115
120
|
}
|
|
@@ -121,7 +126,8 @@ function setDefaultWorkspace(workspaceId) {
|
|
|
121
126
|
}
|
|
122
127
|
const updated = {
|
|
123
128
|
...existingCredentials,
|
|
124
|
-
defaultWorkspace: workspaceId
|
|
129
|
+
defaultWorkspace: workspaceId,
|
|
130
|
+
defaultWorkspaceSource: source
|
|
125
131
|
};
|
|
126
132
|
writeFileSync(CREDENTIALS_FILE, JSON.stringify(updated, null, 2));
|
|
127
133
|
}
|
|
@@ -149,12 +155,14 @@ var init_config = __esm(() => {
|
|
|
149
155
|
format: z.enum(["table", "json"]).default("table"),
|
|
150
156
|
timeout: z.number().default(30000),
|
|
151
157
|
defaultWorkspace: z.string().optional(),
|
|
158
|
+
defaultWorkspaceSource: z.enum(["user", "login-inferred"]).optional(),
|
|
152
159
|
defaultOrganization: z.string().optional()
|
|
153
160
|
});
|
|
154
161
|
credentialsSchema = z.object({
|
|
155
162
|
apiKey: z.string().optional(),
|
|
156
163
|
endpoint: z.string().optional(),
|
|
157
164
|
defaultWorkspace: z.string().optional(),
|
|
165
|
+
defaultWorkspaceSource: z.enum(["user", "login-inferred"]).optional(),
|
|
158
166
|
defaultOrganization: z.string().optional(),
|
|
159
167
|
expiresAt: z.string().optional()
|
|
160
168
|
}).loose();
|
|
@@ -317,6 +325,25 @@ var init_errors = __esm(() => {
|
|
|
317
325
|
};
|
|
318
326
|
});
|
|
319
327
|
|
|
328
|
+
// src/lib/provider-request.ts
|
|
329
|
+
function buildCreateProviderBody(data) {
|
|
330
|
+
const body = {
|
|
331
|
+
name: data.name,
|
|
332
|
+
provider: data.provider,
|
|
333
|
+
isDefault: data.isDefault ?? false
|
|
334
|
+
};
|
|
335
|
+
if (data.apiKey)
|
|
336
|
+
body.apiKey = data.apiKey;
|
|
337
|
+
if (data.baseUrl)
|
|
338
|
+
body.baseUrl = data.baseUrl;
|
|
339
|
+
if (data.hostedFamily)
|
|
340
|
+
body.hostedFamily = data.hostedFamily;
|
|
341
|
+
if (data.credentialFields && Object.keys(data.credentialFields).length > 0) {
|
|
342
|
+
body.credentialFields = data.credentialFields;
|
|
343
|
+
}
|
|
344
|
+
return body;
|
|
345
|
+
}
|
|
346
|
+
|
|
320
347
|
// src/lib/sdk-client.ts
|
|
321
348
|
var exports_sdk_client = {};
|
|
322
349
|
__export(exports_sdk_client, {
|
|
@@ -335,11 +362,15 @@ class SDKClientWrapper {
|
|
|
335
362
|
endpoint;
|
|
336
363
|
workspaceId;
|
|
337
364
|
organizationId;
|
|
365
|
+
workspaceResolution = "none";
|
|
338
366
|
constructor(opts) {
|
|
339
367
|
this.apiKey = opts.apiKey;
|
|
340
368
|
this.endpoint = opts.serverURL ?? "http://localhost:3003";
|
|
341
369
|
this.workspaceId = opts.workspaceId;
|
|
342
370
|
this.organizationId = opts.organizationId;
|
|
371
|
+
if (opts.workspaceId && opts.workspaceSource === "user") {
|
|
372
|
+
this.workspaceResolution = "configured";
|
|
373
|
+
}
|
|
343
374
|
const httpClient = new HTTPClient;
|
|
344
375
|
httpClient.addHook("beforeRequest", (req) => {
|
|
345
376
|
if (this.workspaceId)
|
|
@@ -583,7 +614,8 @@ class SDKClientWrapper {
|
|
|
583
614
|
return this.organizationId;
|
|
584
615
|
}
|
|
585
616
|
async ensureContext() {
|
|
586
|
-
|
|
617
|
+
const needsWorkspaceClassification = !this.workspaceId || this.workspaceResolution === "none";
|
|
618
|
+
if (this.organizationId && !needsWorkspaceClassification)
|
|
587
619
|
return;
|
|
588
620
|
if (!this.organizationId) {
|
|
589
621
|
let orgs = await fetchOrganizations(this.apiKey, this.endpoint).catch(() => []);
|
|
@@ -595,18 +627,41 @@ class SDKClientWrapper {
|
|
|
595
627
|
this.organizationId = orgs[0].id;
|
|
596
628
|
}
|
|
597
629
|
}
|
|
598
|
-
if (
|
|
630
|
+
if (this.workspaceResolution === "none" && this.organizationId) {
|
|
599
631
|
try {
|
|
600
632
|
const response = await this.sdk.workspaces.listWorkspaces({ includeInactive: false });
|
|
601
633
|
const workspaces = response.workspaces;
|
|
602
|
-
if (workspaces.length
|
|
603
|
-
|
|
604
|
-
|
|
634
|
+
if (workspaces.length === 1 && workspaces[0]) {
|
|
635
|
+
this.workspaceId = String(workspaces[0].id);
|
|
636
|
+
this.workspaceResolution = "sole";
|
|
637
|
+
} else if (workspaces.length > 1) {
|
|
638
|
+
const defaultWs = workspaces.find((ws) => ws.isDefault);
|
|
639
|
+
if (defaultWs) {
|
|
605
640
|
this.workspaceId = String(defaultWs.id);
|
|
641
|
+
this.workspaceResolution = "configured";
|
|
642
|
+
} else {
|
|
643
|
+
const first = workspaces[0] ?? undefined;
|
|
644
|
+
if (first) {
|
|
645
|
+
this.workspaceId = this.workspaceId ?? String(first.id);
|
|
646
|
+
this.workspaceResolution = "ambiguous";
|
|
647
|
+
}
|
|
648
|
+
}
|
|
606
649
|
}
|
|
607
650
|
} catch {}
|
|
608
651
|
}
|
|
609
652
|
}
|
|
653
|
+
getWorkspaceResolution() {
|
|
654
|
+
return this.workspaceResolution;
|
|
655
|
+
}
|
|
656
|
+
requireUnambiguousWorkspace() {
|
|
657
|
+
if (!this.workspaceId || this.workspaceResolution === "none") {
|
|
658
|
+
throw new MutagentError("WORKSPACE_REQUIRED", "No workspace configured.", "Set one with: mutagent config set workspace <workspace-id> (list them with: mutagent workspaces list)");
|
|
659
|
+
}
|
|
660
|
+
if (this.workspaceResolution === "ambiguous") {
|
|
661
|
+
throw new MutagentError("WORKSPACE_AMBIGUOUS", "Several workspaces are available and none is marked default, so the target for this write is ambiguous.", "Choose one explicitly: mutagent config set workspace <workspace-id> (list them with: mutagent workspaces list)");
|
|
662
|
+
}
|
|
663
|
+
return this.workspaceId;
|
|
664
|
+
}
|
|
610
665
|
async testProvider(id) {
|
|
611
666
|
try {
|
|
612
667
|
const response = await this.sdk.providerConfigs.testProvider({
|
|
@@ -618,21 +673,20 @@ class SDKClientWrapper {
|
|
|
618
673
|
}
|
|
619
674
|
}
|
|
620
675
|
async createProvider(data) {
|
|
676
|
+
this.requireUnambiguousWorkspace();
|
|
677
|
+
const body = buildCreateProviderBody(data);
|
|
621
678
|
try {
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
apiKey: data.apiKey,
|
|
626
|
-
scope: data.scope ?? {},
|
|
627
|
-
baseUrl: data.baseUrl,
|
|
628
|
-
isDefault: data.isDefault
|
|
679
|
+
const created = await this.request("/api/providers", {
|
|
680
|
+
method: "POST",
|
|
681
|
+
body: JSON.stringify(body)
|
|
629
682
|
});
|
|
630
|
-
return
|
|
683
|
+
return created;
|
|
631
684
|
} catch (error) {
|
|
632
685
|
this.handleError(error);
|
|
633
686
|
}
|
|
634
687
|
}
|
|
635
688
|
async updateProvider(id, data) {
|
|
689
|
+
const workspaceId = this.requireUnambiguousWorkspace();
|
|
636
690
|
try {
|
|
637
691
|
const response = await this.sdk.providerConfigs.updateProvider({
|
|
638
692
|
id,
|
|
@@ -644,14 +698,16 @@ class SDKClientWrapper {
|
|
|
644
698
|
baseUrl: data.baseUrl
|
|
645
699
|
}
|
|
646
700
|
});
|
|
647
|
-
return response;
|
|
701
|
+
return { ...response, workspaceId };
|
|
648
702
|
} catch (error) {
|
|
649
703
|
this.handleError(error);
|
|
650
704
|
}
|
|
651
705
|
}
|
|
652
706
|
async deleteProvider(id) {
|
|
707
|
+
const workspaceId = this.requireUnambiguousWorkspace();
|
|
653
708
|
try {
|
|
654
709
|
await this.sdk.providerConfigs.deleteProvider({ id });
|
|
710
|
+
return { workspaceId };
|
|
655
711
|
} catch (error) {
|
|
656
712
|
this.handleError(error);
|
|
657
713
|
}
|
|
@@ -668,7 +724,8 @@ async function getSDKClient() {
|
|
|
668
724
|
apiKey,
|
|
669
725
|
serverURL: config.endpoint,
|
|
670
726
|
workspaceId: config.defaultWorkspace,
|
|
671
|
-
organizationId: config.defaultOrganization
|
|
727
|
+
organizationId: config.defaultOrganization,
|
|
728
|
+
workspaceSource: config.defaultWorkspaceSource
|
|
672
729
|
});
|
|
673
730
|
await sdkClient.ensureContext().catch((err) => {
|
|
674
731
|
if (process.env.MUTAGENT_DEBUG) {
|
|
@@ -2192,80 +2249,118 @@ init_sdk_client();
|
|
|
2192
2249
|
import { Command as Command5 } from "commander";
|
|
2193
2250
|
import chalk11 from "chalk";
|
|
2194
2251
|
init_errors();
|
|
2252
|
+
import { Provider as ProviderCatalogId } from "@mutagent/sdk/models";
|
|
2195
2253
|
|
|
2196
2254
|
// src/commands/providers/add.ts
|
|
2197
2255
|
init_sdk_client();
|
|
2198
2256
|
import chalk8 from "chalk";
|
|
2199
2257
|
init_errors();
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2258
|
+
var GATEWAY_HOSTED_FAMILIES = {
|
|
2259
|
+
azure: ["openai", "anthropic"],
|
|
2260
|
+
vertex: ["gemini", "anthropic"],
|
|
2261
|
+
bedrock: ["anthropic"]
|
|
2262
|
+
};
|
|
2263
|
+
var GATEWAY_PROVIDERS = new Set(Object.keys(GATEWAY_HOSTED_FAMILIES));
|
|
2264
|
+
var HOSTED_FAMILIES = [
|
|
2265
|
+
...new Set(Object.values(GATEWAY_HOSTED_FAMILIES).flat())
|
|
2266
|
+
];
|
|
2267
|
+
var SECRET_WIRE_NAME = {
|
|
2268
|
+
vertex: "serviceAccountKey"
|
|
2269
|
+
};
|
|
2270
|
+
function collectCredentialFields(options) {
|
|
2271
|
+
const fields = {};
|
|
2272
|
+
if (options.resourceEndpoint)
|
|
2273
|
+
fields.resourceEndpoint = options.resourceEndpoint;
|
|
2274
|
+
if (options.deploymentName)
|
|
2275
|
+
fields.deploymentName = options.deploymentName;
|
|
2276
|
+
if (options.apiVersion)
|
|
2277
|
+
fields.apiVersion = options.apiVersion;
|
|
2278
|
+
if (options.projectId)
|
|
2279
|
+
fields.projectId = options.projectId;
|
|
2280
|
+
if (options.region)
|
|
2281
|
+
fields.region = options.region;
|
|
2282
|
+
return fields;
|
|
2217
2283
|
}
|
|
2218
2284
|
function registerAddCommand(parent) {
|
|
2219
|
-
parent.command("add").description("Add a new provider configuration").requiredOption("-p, --provider <type>", "Provider type (openai, anthropic,
|
|
2285
|
+
parent.command("add").description("Add a new provider configuration").requiredOption("-p, --provider <type>", "Provider type (openai, anthropic, azure, ...)").requiredOption("-n, --name <name>", "Display name for this provider").option("-k, --api-key <key>", "API key for the provider (every entry except Google Vertex)").option("--service-account-key <json>", "Google Vertex service-account credential JSON").option("--hosted-family <family>", `Hosted model family for gateway providers: ${HOSTED_FAMILIES.join(", ")}`).option("--base-url <url>", "Custom base URL for the provider API").option("--resource-endpoint <url>", "Azure resource endpoint").option("--deployment-name <name>", "Azure deployment name").option("--api-version <version>", "Azure API version (e.g. 2024-08-01-preview)").option("--project-id <id>", "Google Vertex project ID").option("--region <region>", "Region (Vertex location, or AWS Bedrock region)").option("--set-default", "Set as the default provider of its kind").addHelpText("after", `
|
|
2220
2286
|
Examples:
|
|
2221
2287
|
${chalk8.dim("$")} mutagent providers add --provider openai --name "My OpenAI" --api-key $OPENAI_API_KEY
|
|
2222
|
-
${chalk8.dim("$")} mutagent providers add --provider
|
|
2223
|
-
|
|
2224
|
-
${chalk8.dim("$")} mutagent providers add --provider
|
|
2288
|
+
${chalk8.dim("$")} mutagent providers add --provider azure --name "Azure GPT" --api-key $KEY \\
|
|
2289
|
+
--hosted-family openai --resource-endpoint https://my.openai.azure.com --deployment-name gpt-5
|
|
2290
|
+
${chalk8.dim("$")} mutagent providers add --provider bedrock --name "Bedrock Claude" --api-key $KEY \\
|
|
2291
|
+
--hosted-family anthropic --region us-east-1
|
|
2292
|
+
${chalk8.dim("$")} mutagent providers add --provider custom --name "Ollama" --api-key none --base-url https://ollama.internal --json
|
|
2293
|
+
|
|
2294
|
+
Gateway providers (${[...GATEWAY_PROVIDERS].join(", ")}) serve another vendor's models and
|
|
2295
|
+
require --hosted-family. Direct providers must not set it.
|
|
2225
2296
|
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
org Uses your configured organization
|
|
2229
|
-
user Personal provider config
|
|
2297
|
+
Providers are configured for your workspace. Set the target with:
|
|
2298
|
+
${chalk8.dim("$")} mutagent config set workspace <workspace-id>
|
|
2230
2299
|
|
|
2231
2300
|
The API key is encrypted server-side and never returned in plain text.
|
|
2301
|
+
|
|
2302
|
+
AI Agent Directive:
|
|
2303
|
+
Run 'mutagent providers list --json' first to check whether the provider already exists.
|
|
2304
|
+
This command writes a credential — confirm with the user before running it.
|
|
2232
2305
|
`).action(async (options) => {
|
|
2233
2306
|
const isJson = getJsonFlag(parent);
|
|
2234
2307
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
2235
2308
|
try {
|
|
2236
2309
|
const providerType = validateProviderType(options.provider);
|
|
2237
|
-
|
|
2238
|
-
|
|
2310
|
+
const secretWireName = SECRET_WIRE_NAME[providerType] ?? "apiKey";
|
|
2311
|
+
const secret = secretWireName === "apiKey" ? options.apiKey : options.serviceAccountKey;
|
|
2312
|
+
const secretFlag = secretWireName === "apiKey" ? "--api-key" : "--service-account-key";
|
|
2313
|
+
if (!secret || secret.trim() === "") {
|
|
2314
|
+
throw new MutagentError("MISSING_CREDENTIAL", `${providerType} requires a credential and none was provided.`, `Provide it with ${secretFlag}`);
|
|
2315
|
+
}
|
|
2316
|
+
if (secretWireName !== "apiKey" && options.apiKey) {
|
|
2317
|
+
throw new MutagentError("WRONG_CREDENTIAL_FLAG", `'${providerType}' does not take an API key.`, `Use ${secretFlag} instead of --api-key`);
|
|
2239
2318
|
}
|
|
2240
|
-
const
|
|
2241
|
-
|
|
2242
|
-
|
|
2319
|
+
const allowedFamilies = GATEWAY_HOSTED_FAMILIES[providerType];
|
|
2320
|
+
const isGateway = allowedFamilies !== undefined;
|
|
2321
|
+
if (options.hostedFamily) {
|
|
2322
|
+
if (!isGateway) {
|
|
2323
|
+
throw new MutagentError("HOSTED_FAMILY_NOT_APPLICABLE", `'${providerType}' serves its own models, so it has no hosted family.`, `Drop --hosted-family, or pick a gateway provider: ${[...GATEWAY_PROVIDERS].join(", ")}`);
|
|
2324
|
+
}
|
|
2325
|
+
if (!allowedFamilies.includes(options.hostedFamily)) {
|
|
2326
|
+
throw new MutagentError("INVALID_HOSTED_FAMILY", `'${providerType}' does not host '${options.hostedFamily}'.`, `${providerType} hosts: ${allowedFamilies.join(", ")}`);
|
|
2327
|
+
}
|
|
2328
|
+
} else if (isGateway && allowedFamilies.length > 1) {
|
|
2329
|
+
throw new MutagentError("MISSING_HOSTED_FAMILY", `'${providerType}' is a gateway and needs to know which model family it serves.`, `Add --hosted-family <${allowedFamilies.join("|")}>`);
|
|
2243
2330
|
}
|
|
2244
2331
|
const client = await getSDKClient();
|
|
2245
|
-
const
|
|
2332
|
+
const workspaceId = client.requireUnambiguousWorkspace();
|
|
2333
|
+
const credentialFields = collectCredentialFields(options);
|
|
2334
|
+
if (secretWireName !== "apiKey")
|
|
2335
|
+
credentialFields[secretWireName] = secret;
|
|
2246
2336
|
const created = await client.createProvider({
|
|
2247
2337
|
name: options.name,
|
|
2248
2338
|
provider: providerType,
|
|
2249
|
-
apiKey:
|
|
2250
|
-
scope,
|
|
2339
|
+
apiKey: secretWireName === "apiKey" ? secret : undefined,
|
|
2251
2340
|
baseUrl: options.baseUrl,
|
|
2252
|
-
isDefault: options.setDefault
|
|
2341
|
+
isDefault: options.setDefault,
|
|
2342
|
+
hostedFamily: options.hostedFamily,
|
|
2343
|
+
credentialFields
|
|
2253
2344
|
});
|
|
2254
2345
|
if (isJson) {
|
|
2255
|
-
const directive = buildProviderCreatedDirective(created,
|
|
2346
|
+
const directive = buildProviderCreatedDirective(created, workspaceId);
|
|
2256
2347
|
echoDirectiveToStderr(directive);
|
|
2257
2348
|
output.output({
|
|
2258
2349
|
success: true,
|
|
2259
2350
|
...created,
|
|
2351
|
+
workspaceId,
|
|
2260
2352
|
_links: providerLinks(created.id),
|
|
2261
2353
|
_directive: directive
|
|
2262
2354
|
});
|
|
2263
2355
|
} else {
|
|
2264
2356
|
output.success(`Provider created: ${created.name ?? options.name}`);
|
|
2265
|
-
console.log(` ID:
|
|
2266
|
-
console.log(` Type:
|
|
2267
|
-
|
|
2268
|
-
|
|
2357
|
+
console.log(` ID: ${String(created.id)}`);
|
|
2358
|
+
console.log(` Type: ${providerType}`);
|
|
2359
|
+
if (options.hostedFamily) {
|
|
2360
|
+
console.log(` Serves: ${options.hostedFamily}`);
|
|
2361
|
+
}
|
|
2362
|
+
console.log(` Workspace: ${workspaceId}`);
|
|
2363
|
+
console.log(` URL: ${providerLink(created.id)}`);
|
|
2269
2364
|
if (options.setDefault) {
|
|
2270
2365
|
console.log(chalk8.green(" Set as default provider"));
|
|
2271
2366
|
}
|
|
@@ -2277,14 +2372,14 @@ The API key is encrypted server-side and never returned in plain text.
|
|
|
2277
2372
|
}
|
|
2278
2373
|
});
|
|
2279
2374
|
}
|
|
2280
|
-
function buildProviderCreatedDirective(provider,
|
|
2375
|
+
function buildProviderCreatedDirective(provider, workspaceId) {
|
|
2281
2376
|
const title = `Provider Created — ${provider.name ?? "Unknown"}`;
|
|
2282
2377
|
const dashboardUrl = providerLink(provider.id);
|
|
2283
2378
|
const apiUrl = `/api/providers/${String(provider.id)}`;
|
|
2284
2379
|
const rows = [
|
|
2285
2380
|
{ label: "Name", value: provider.name ?? "Unknown" },
|
|
2286
2381
|
{ label: "Provider ID", value: String(provider.id) },
|
|
2287
|
-
{ label: "
|
|
2382
|
+
{ label: "Workspace", value: workspaceId }
|
|
2288
2383
|
];
|
|
2289
2384
|
const links = [
|
|
2290
2385
|
{ label: "Settings", url: dashboardUrl },
|
|
@@ -2298,7 +2393,7 @@ function buildProviderCreatedDirective(provider, scope) {
|
|
|
2298
2393
|
display: "status_card",
|
|
2299
2394
|
template: "provider_created",
|
|
2300
2395
|
title,
|
|
2301
|
-
fields: { providerId: String(provider.id), name: provider.name,
|
|
2396
|
+
fields: { providerId: String(provider.id), name: provider.name, workspaceId },
|
|
2302
2397
|
links: { settings: dashboardUrl, api: apiUrl },
|
|
2303
2398
|
next,
|
|
2304
2399
|
instruction: "MANDATORY: Display this card to the user before proceeding.",
|
|
@@ -2311,7 +2406,7 @@ init_sdk_client();
|
|
|
2311
2406
|
import chalk9 from "chalk";
|
|
2312
2407
|
init_errors();
|
|
2313
2408
|
function registerUpdateCommand(parent) {
|
|
2314
|
-
parent.command("update").description("Update an existing provider configuration").argument("<id>", "Provider ID (from: mutagent providers list)").option("-n, --name <name>", "Updated display name").option("-k, --api-key <key>", "Updated API key (will be re-encrypted)").option("--active <bool>", "Activate or deactivate (true|false)").option("--set-default", "Set as default provider
|
|
2409
|
+
parent.command("update").description("Update an existing provider configuration").argument("<id>", "Provider ID (from: mutagent providers list)").option("-n, --name <name>", "Updated display name").option("-k, --api-key <key>", "Updated API key (will be re-encrypted)").option("--active <bool>", "Activate or deactivate (true|false)").option("--set-default", "Set as the default provider of its kind").option("--base-url <url>", 'Updated base URL (use "" to clear)').addHelpText("after", `
|
|
2315
2410
|
Examples:
|
|
2316
2411
|
${chalk9.dim("$")} mutagent providers update <id> --name "New Name"
|
|
2317
2412
|
${chalk9.dim("$")} mutagent providers update <id> --api-key $NEW_KEY --json
|
|
@@ -2364,8 +2459,11 @@ PATCH semantics — only provided fields are updated.
|
|
|
2364
2459
|
});
|
|
2365
2460
|
} else {
|
|
2366
2461
|
output.success(`Provider updated: ${String(updated.name ?? id)}`);
|
|
2367
|
-
console.log(` ID:
|
|
2368
|
-
|
|
2462
|
+
console.log(` ID: ${String(updated.id ?? id)}`);
|
|
2463
|
+
if (updated.workspaceId) {
|
|
2464
|
+
console.log(` Workspace: ${updated.workspaceId}`);
|
|
2465
|
+
}
|
|
2466
|
+
console.log(` URL: ${providerLink(updated.id ?? id)}`);
|
|
2369
2467
|
if (options.apiKey) {
|
|
2370
2468
|
console.log(chalk9.dim(" API key re-encrypted server-side."));
|
|
2371
2469
|
}
|
|
@@ -2427,8 +2525,9 @@ ${chalk10.dim("Warning: API keys are AES-256-GCM encrypted and irrecoverable aft
|
|
|
2427
2525
|
` + `Use --force to confirm: mutagent providers delete ${id} --force`);
|
|
2428
2526
|
}
|
|
2429
2527
|
const client = await getSDKClient();
|
|
2528
|
+
let deletedFrom;
|
|
2430
2529
|
try {
|
|
2431
|
-
await client.deleteProvider(id);
|
|
2530
|
+
deletedFrom = (await client.deleteProvider(id)).workspaceId;
|
|
2432
2531
|
} catch (error) {
|
|
2433
2532
|
if (error instanceof ApiError && error.statusCode === 404) {
|
|
2434
2533
|
if (isJson) {
|
|
@@ -2458,7 +2557,10 @@ ${chalk10.dim("Warning: API keys are AES-256-GCM encrypted and irrecoverable aft
|
|
|
2458
2557
|
});
|
|
2459
2558
|
} else {
|
|
2460
2559
|
output.success(`Deleted provider: ${id}`);
|
|
2461
|
-
|
|
2560
|
+
if (deletedFrom) {
|
|
2561
|
+
console.log(` Workspace: ${deletedFrom}`);
|
|
2562
|
+
}
|
|
2563
|
+
console.log(` Settings: ${providerSettingsLink()}`);
|
|
2462
2564
|
}
|
|
2463
2565
|
} catch (error) {
|
|
2464
2566
|
handleError(error, isJson);
|
|
@@ -2484,24 +2586,13 @@ function buildProviderDeletedDirective(id) {
|
|
|
2484
2586
|
}
|
|
2485
2587
|
|
|
2486
2588
|
// src/commands/providers/index.ts
|
|
2487
|
-
var VALID_PROVIDER_TYPES =
|
|
2488
|
-
"openai",
|
|
2489
|
-
"anthropic",
|
|
2490
|
-
"google",
|
|
2491
|
-
"azure",
|
|
2492
|
-
"bedrock",
|
|
2493
|
-
"cohere",
|
|
2494
|
-
"mistral",
|
|
2495
|
-
"groq",
|
|
2496
|
-
"together",
|
|
2497
|
-
"replicate",
|
|
2498
|
-
"custom"
|
|
2499
|
-
];
|
|
2589
|
+
var VALID_PROVIDER_TYPES = Object.values(ProviderCatalogId);
|
|
2500
2590
|
function validateProviderType(type) {
|
|
2501
|
-
|
|
2591
|
+
const match = VALID_PROVIDER_TYPES.find((entry) => entry === type);
|
|
2592
|
+
if (!match) {
|
|
2502
2593
|
throw new MutagentError("INVALID_PROVIDER_TYPE", `Invalid provider type: ${type}`, `Valid types: ${VALID_PROVIDER_TYPES.join(", ")}`);
|
|
2503
2594
|
}
|
|
2504
|
-
return
|
|
2595
|
+
return match;
|
|
2505
2596
|
}
|
|
2506
2597
|
function createProvidersCommand() {
|
|
2507
2598
|
const providers = new Command5("providers").description("Manage LLM provider configurations (BYOK)").addHelpText("after", `
|
|
@@ -2514,7 +2605,7 @@ Examples:
|
|
|
2514
2605
|
${chalk11.dim("$")} mutagent providers test <provider-id>
|
|
2515
2606
|
|
|
2516
2607
|
Provider Types:
|
|
2517
|
-
|
|
2608
|
+
${VALID_PROVIDER_TYPES.join(", ")}
|
|
2518
2609
|
|
|
2519
2610
|
Subcommands:
|
|
2520
2611
|
list, get, add, update, delete, test
|
|
@@ -2567,10 +2658,10 @@ Examples:
|
|
|
2567
2658
|
const withLinks = result.data.map((p) => ({
|
|
2568
2659
|
id: p.id,
|
|
2569
2660
|
name: p.name,
|
|
2570
|
-
|
|
2661
|
+
provider: p.provider,
|
|
2571
2662
|
isActive: p.isActive,
|
|
2572
2663
|
updatedAt: p.updatedAt,
|
|
2573
|
-
...options.models ? { models: catalogByKind[p.
|
|
2664
|
+
...options.models ? { models: catalogByKind[p.provider] ?? [] } : {},
|
|
2574
2665
|
_links: providerLinks(p.id)
|
|
2575
2666
|
}));
|
|
2576
2667
|
output.output({ ...result, data: withLinks });
|
|
@@ -2582,11 +2673,11 @@ Examples:
|
|
|
2582
2673
|
const formatted = result.data.map((p) => ({
|
|
2583
2674
|
id: p.id,
|
|
2584
2675
|
name: p.name,
|
|
2585
|
-
|
|
2676
|
+
provider: p.provider,
|
|
2586
2677
|
baseUrl: p.baseUrl ?? "default",
|
|
2587
2678
|
active: p.isActive ? "Yes" : "No",
|
|
2588
2679
|
updated: p.updatedAt ? new Date(p.updatedAt).toLocaleDateString() : "N/A",
|
|
2589
|
-
...options.models ? { models: formatModels(p.
|
|
2680
|
+
...options.models ? { models: formatModels(p.provider) } : {},
|
|
2590
2681
|
url: providerLink(p.id)
|
|
2591
2682
|
}));
|
|
2592
2683
|
output.output(formatted);
|
|
@@ -2612,7 +2703,7 @@ Examples:
|
|
|
2612
2703
|
const formatted = {
|
|
2613
2704
|
id: provider.id,
|
|
2614
2705
|
name: provider.name,
|
|
2615
|
-
|
|
2706
|
+
provider: provider.provider,
|
|
2616
2707
|
baseUrl: provider.baseUrl ?? "default",
|
|
2617
2708
|
isActive: provider.isActive ? "Yes" : "No",
|
|
2618
2709
|
createdBy: provider.createdBy ?? "N/A",
|
|
@@ -2645,12 +2736,13 @@ ${chalk11.dim("Tests connectivity and lists available models for the provider.")
|
|
|
2645
2736
|
output.output({ ...result, _links: providerLinks(id) });
|
|
2646
2737
|
} else {
|
|
2647
2738
|
if (result.success) {
|
|
2648
|
-
|
|
2739
|
+
const latency = typeof result.latencyMs === "number" ? ` (${String(result.latencyMs)}ms)` : "";
|
|
2740
|
+
output.success(`Provider test passed${latency}`);
|
|
2649
2741
|
console.log(chalk11.green(`Message: ${result.message}`));
|
|
2650
|
-
if (result.
|
|
2742
|
+
if (result.models && result.models.length > 0) {
|
|
2651
2743
|
console.log(chalk11.bold(`
|
|
2652
2744
|
Available Models:`));
|
|
2653
|
-
result.
|
|
2745
|
+
result.models.forEach((model) => {
|
|
2654
2746
|
console.log(` - ${model}`);
|
|
2655
2747
|
});
|
|
2656
2748
|
}
|
|
@@ -3464,7 +3556,7 @@ What it does:
|
|
|
3464
3556
|
workspaceValidation = { id: found.id, name: found.name, validated: true, corrected: false };
|
|
3465
3557
|
} else if (workspaces[0]) {
|
|
3466
3558
|
const first = workspaces[0];
|
|
3467
|
-
(deps.setDefaultWorkspace ?? setDefaultWorkspace)(first.id);
|
|
3559
|
+
(deps.setDefaultWorkspace ?? setDefaultWorkspace)(first.id, "login-inferred");
|
|
3468
3560
|
workspace = first.id;
|
|
3469
3561
|
workspaceValidation = { id: first.id, name: first.name, validated: true, corrected: true };
|
|
3470
3562
|
}
|
|
@@ -5044,5 +5136,5 @@ program.addCommand(createInstallCommand());
|
|
|
5044
5136
|
program.addCommand(createFeedbackCommand());
|
|
5045
5137
|
program.parse();
|
|
5046
5138
|
|
|
5047
|
-
//# debugId=
|
|
5139
|
+
//# debugId=EF6771B96785663564756E2164756E21
|
|
5048
5140
|
//# sourceMappingURL=cli.js.map
|