@mutagent/cli 0.1.220 → 0.1.222

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 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
- if (this.organizationId && this.workspaceId)
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 (!this.workspaceId && this.organizationId) {
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 > 0) {
603
- const defaultWs = workspaces.find((ws) => ws.isDefault) ?? workspaces[0];
604
- if (defaultWs)
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 response = await this.sdk.providerConfigs.createProvider({
623
- name: data.name,
624
- provider: data.provider,
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 response;
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
- function resolveScope(scopeFlag, client) {
2201
- const scope = scopeFlag ?? "workspace";
2202
- if (scope === "workspace") {
2203
- const wsId = client.getCurrentWorkspaceId();
2204
- if (!wsId) {
2205
- throw new MutagentError("MISSING_WORKSPACE", "No workspace configured. Cannot create workspace-scoped provider.", "Run: mutagent config set defaultWorkspace <workspace-id>");
2206
- }
2207
- return { workspaceId: wsId };
2208
- }
2209
- if (scope === "org") {
2210
- const orgId = client.getCurrentOrgId();
2211
- if (!orgId) {
2212
- throw new MutagentError("MISSING_ORGANIZATION", "No organization configured. Cannot create org-scoped provider.", "Run: mutagent config set defaultOrganization <org-id>");
2213
- }
2214
- return { organizationId: orgId };
2215
- }
2216
- return {};
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, google, ...)").requiredOption("-n, --name <name>", "Display name for this provider").requiredOption("-k, --api-key <key>", "API key for the provider").option("-s, --scope <scope>", "Scope: workspace (default), org, user", "workspace").option("--base-url <url>", "Custom base URL for the provider API").option("--set-default", "Set as default provider for this scope").addHelpText("after", `
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 anthropic --name "Team Claude" --api-key $KEY --scope org
2223
- ${chalk8.dim("$")} mutagent providers add --provider openai --name "Personal" --api-key $KEY --scope user --set-default
2224
- ${chalk8.dim("$")} mutagent providers add --provider custom --name "Ollama" --api-key none --base-url http://localhost:11434 --json
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
- Scope Resolution:
2227
- workspace (default) Uses your configured workspace
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
- if (!options.apiKey || options.apiKey.trim() === "") {
2238
- throw new MutagentError("MISSING_API_KEY", "API key cannot be empty", "Provide a valid API key with --api-key");
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 validScopes = ["workspace", "org", "user"];
2241
- if (options.scope && !validScopes.includes(options.scope)) {
2242
- throw new MutagentError("INVALID_SCOPE", `Invalid scope: ${options.scope}`, `Valid scopes: ${validScopes.join(", ")}`);
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 scope = resolveScope(options.scope, client);
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: options.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, options.scope ?? "workspace");
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: ${String(created.id)}`);
2266
- console.log(` Type: ${providerType}`);
2267
- console.log(` Scope: ${options.scope ?? "workspace"}`);
2268
- console.log(` URL: ${providerLink(created.id)}`);
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, scope) {
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: "Scope", value: scope }
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, scope },
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 for its scope").option("--base-url <url>", 'Updated base URL (use "" to clear)').addHelpText("after", `
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: ${String(updated.id ?? id)}`);
2368
- console.log(` URL: ${providerLink(updated.id ?? id)}`);
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
- console.log(` Settings: ${providerSettingsLink()}`);
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
- if (!VALID_PROVIDER_TYPES.includes(type)) {
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 type;
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
- openai, anthropic, google, azure, bedrock, cohere, mistral, groq, together, replicate, custom
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
- type: p.type,
2661
+ provider: p.provider,
2571
2662
  isActive: p.isActive,
2572
2663
  updatedAt: p.updatedAt,
2573
- ...options.models ? { models: catalogByKind[p.type] ?? [] } : {},
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
- type: p.type,
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.type) } : {},
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
- type: provider.type,
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
- output.success(`Provider test passed (${String(result.responseTimeMs)}ms)`);
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.availableModels && result.availableModels.length > 0) {
2742
+ if (result.models && result.models.length > 0) {
2651
2743
  console.log(chalk11.bold(`
2652
2744
  Available Models:`));
2653
- result.availableModels.forEach((model) => {
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=EC56D6215B8176D364756E2164756E21
5139
+ //# debugId=EF6771B96785663564756E2164756E21
5048
5140
  //# sourceMappingURL=cli.js.map