@divergeai/cli 0.1.2 → 0.1.3

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/README.md CHANGED
@@ -5,7 +5,7 @@ model gateway, and call platform tools as yourself.
5
5
 
6
6
  ```bash
7
7
  npm install -g @divergeai/cli
8
- diverge login # opens the browser; choose your organization
8
+ diverge login # browser sign-in; the organization is chosen afterwards in the CLI
9
9
  diverge agents setup claude # Claude Code on the gateway
10
10
  diverge agents run dsh -- --profile web --port 3131 --no-open
11
11
  diverge tools list --organization-id <id>
@@ -16,8 +16,11 @@ Node 22 or later. Linux and macOS are supported; Windows is best-effort.
16
16
  ## Sign in
17
17
 
18
18
  `diverge login` runs the browser sign-in (authorization code with PKCE on a
19
- loopback listener). A login serves exactly one organization: without
20
- `--organization-id` the platform asks you to choose. The login is cached in
19
+ loopback listener). The browser only authenticates you; the organization is
20
+ chosen afterwards in the CLI, never through the browser: `--organization-id
21
+ <id|name>` if given, else the last login's, else your only membership, else a
22
+ menu. The login is bound to that organization on the platform, and `diverge
23
+ org use <id|name>` switches without a browser. The login is cached in
21
24
  `~/.diverge/token.json` (mode 0600), refreshes itself, and `diverge logout`
22
25
  revokes it on the platform before forgetting it.
23
26
 
package/dist/diverge.mjs CHANGED
@@ -7387,7 +7387,7 @@ import path10 from "node:path";
7387
7387
  import { parseArgs } from "node:util";
7388
7388
 
7389
7389
  // src/version.ts
7390
- var VERSION = true ? "0.1.2" : "dev";
7390
+ var VERSION = true ? "0.1.3" : "dev";
7391
7391
  var USER_AGENT = `diverge/${VERSION}`;
7392
7392
 
7393
7393
  // src/http.ts
@@ -7686,15 +7686,25 @@ async function login(options, deps = defaultDeps) {
7686
7686
  await loopback.close();
7687
7687
  }
7688
7688
  }
7689
- async function refreshUserToken(baseUrl, clientId2, token, nowMs = Date.now()) {
7689
+ async function refreshUserToken(baseUrl, clientId2, token, nowMs = Date.now(), organizationId) {
7690
7690
  if (!token.refresh_token) throw new CliError("Cached login expired. Run: diverge login");
7691
7691
  const payload = await postToken(baseUrl, {
7692
7692
  grant_type: "refresh_token",
7693
7693
  refresh_token: token.refresh_token,
7694
- client_id: clientId2
7694
+ client_id: clientId2,
7695
+ ...organizationId ? { organization_id: organizationId } : {}
7695
7696
  });
7696
7697
  return cachedFrom(payload, token.base_url, token.refresh_token, nowMs);
7697
7698
  }
7699
+ async function bindOrganization(source, organizationId, nowMs = Date.now()) {
7700
+ const token = loadUserToken(source.tokenFile);
7701
+ if (!token || token.base_url !== source.baseUrl.replace(/\/+$/, "")) {
7702
+ throw new CliError("No cached login for this deployment. Run: diverge login");
7703
+ }
7704
+ const bound = await refreshUserToken(source.baseUrl, source.clientId, token, nowMs, organizationId);
7705
+ saveUserToken(source.tokenFile, bound);
7706
+ return bound;
7707
+ }
7698
7708
  async function getUserToken(source, freshForSeconds = 30, nowMs = Date.now()) {
7699
7709
  const token = loadUserToken(source.tokenFile);
7700
7710
  if (!token || token.base_url !== source.baseUrl.replace(/\/+$/, "")) {
@@ -8344,6 +8354,38 @@ ${agentsUsage}`);
8344
8354
  // src/commands/login.ts
8345
8355
  import { parseArgs as parseArgs2 } from "node:util";
8346
8356
 
8357
+ // src/auth/organizations.ts
8358
+ function chooseOrganization(input) {
8359
+ const memberships = input.memberships;
8360
+ const flag = input.flag?.trim();
8361
+ if (flag) {
8362
+ const match = memberships.find((organization) => organization.id === flag || organization.name.toLowerCase() === flag.toLowerCase());
8363
+ if (match) return { kind: "chosen", organizationId: match.id, name: match.name, reason: "flag" };
8364
+ if (input.platformActor) return { kind: "chosen", organizationId: flag, reason: "flag" };
8365
+ throw new CliError(`Not one of your organizations: ${flag}. Yours: ${memberships.map((organization) => `${organization.name} (${organization.id})`).join(", ") || "none"}`);
8366
+ }
8367
+ const remembered = input.remembered?.trim();
8368
+ if (remembered) {
8369
+ const match = memberships.find((organization) => organization.id === remembered);
8370
+ if (match) return { kind: "chosen", organizationId: match.id, name: match.name, reason: "remembered" };
8371
+ if (input.platformActor) return { kind: "chosen", organizationId: remembered, reason: "remembered" };
8372
+ }
8373
+ if (memberships.length === 1) return { kind: "chosen", organizationId: memberships[0].id, name: memberships[0].name, reason: "only" };
8374
+ if (memberships.length === 0) return { kind: "none" };
8375
+ return { kind: "ask", options: memberships };
8376
+ }
8377
+ function organizationMenu(options) {
8378
+ return options.map((organization, index) => ` ${index + 1}. ${organization.name} (${organization.id})`);
8379
+ }
8380
+ function pickFromMenu(answer, options) {
8381
+ const trimmed = answer.trim();
8382
+ const index = Number(trimmed);
8383
+ if (Number.isInteger(index) && index >= 1 && index <= options.length) return options[index - 1];
8384
+ const match = options.find((organization) => organization.id === trimmed || organization.name.toLowerCase() === trimmed.toLowerCase());
8385
+ if (!match) throw new CliError(`Not one of the listed organizations: ${trimmed}`);
8386
+ return match;
8387
+ }
8388
+
8347
8389
  // src/auth/userinfo.ts
8348
8390
  async function fetchUserInfo(baseUrl, accessToken) {
8349
8391
  return fetchJson(userinfoEndpoint(baseUrl), { headers: { Authorization: `Bearer ${accessToken}` }, timeoutMs: 15e3 });
@@ -8357,12 +8399,25 @@ async function describeAccount(baseUrl, accessToken, fallbackSub, options = {})
8357
8399
  }
8358
8400
  }
8359
8401
 
8402
+ // src/prompt.ts
8403
+ import readline from "node:readline";
8404
+ function ask(question) {
8405
+ const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
8406
+ return new Promise((resolve) => rl.question(question, (answer) => {
8407
+ rl.close();
8408
+ resolve(answer);
8409
+ }));
8410
+ }
8411
+
8360
8412
  // src/commands/login.ts
8361
8413
  var DEFAULT_SCOPES = "mcp:read mcp:execute inference:execute";
8362
- var loginUsage = `diverge login [--organization-id <id>] [--scopes "<scopes>"] [--as <email>] [--no-browser] [--api-url <url>]
8414
+ var loginUsage = `diverge login [--organization-id <id|name>] [--scopes "<scopes>"] [--as <email>] [--no-browser] [--api-url <url>]
8363
8415
 
8364
- Sign in through the browser. Without --organization-id the platform asks you to
8365
- choose one; a login serves exactly one organization. --api-url is remembered.
8416
+ Sign in through the browser, then choose where to act. The browser only
8417
+ authenticates the person; the organization is chosen here afterwards \u2014 the
8418
+ one named by --organization-id (id or name), else the last login's, else the
8419
+ only membership, else a menu \u2014 and the login is bound to it on the platform.
8420
+ Switch later with: diverge org use <id|name>.
8366
8421
  --as <email> names the account: the platform signs that account in instead of
8367
8422
  reusing whatever session the browser holds, and issues nothing to any other.
8368
8423
  Without --as, the account of the last login is used; switching is explicit.
@@ -8404,29 +8459,90 @@ async function runLogin(args, io) {
8404
8459
  baseUrl: apiUrl,
8405
8460
  clientId: clientId(io.env),
8406
8461
  scopes,
8407
- organizationId: values["organization-id"],
8408
- selectOrganization: !values["organization-id"],
8409
8462
  openBrowser: !values["no-browser"],
8410
8463
  tokenFile: tokenFile(io.env),
8411
8464
  loginHint,
8412
8465
  print: io.stdout
8413
8466
  });
8414
8467
  const claims = tokenClaims(token.access_token);
8415
- const remaining = Math.max(0, Math.round(token.expires_at - Date.now() / 1e3));
8416
- io.stdout(`Logged in to ${apiUrl} for organization ${claims.organizationId ?? "none"}; token cached (${remaining}s to expiry, auto-refreshes).`);
8417
- let account;
8468
+ let info;
8418
8469
  try {
8419
- account = (await fetchUserInfo(apiUrl, token.access_token)).email ?? void 0;
8470
+ info = await fetchUserInfo(apiUrl, token.access_token);
8420
8471
  } catch (error) {
8421
- io.stderr(`Signed in as: ${claims.sub ?? "unknown user"} (email unavailable: ${error instanceof Error ? error.message : String(error)})`);
8472
+ throw new CliError(`Signed in, but the platform could not say who or where (${error instanceof Error ? error.message : String(error)}); run: diverge login`);
8422
8473
  }
8423
- if (account) io.stdout(`Signed in as: ${account}`);
8424
- writeConfig({ ...readConfig(io.env), ...account ? { account } : {}, scopes }, io.env);
8474
+ io.stdout(`Signed in as: ${info.email}`);
8475
+ const bound = await bindChosenOrganization(io, apiUrl, values["organization-id"], config.organization, info);
8476
+ const remaining = Math.max(0, Math.round(bound.token.expires_at - Date.now() / 1e3));
8477
+ io.stdout(`Logged in to ${apiUrl}; token cached (${remaining}s to expiry, auto-refreshes).`);
8478
+ writeConfig({ ...readConfig(io.env), account: info.email, scopes, organization: bound.organizationId }, io.env);
8425
8479
  const granted = new Set(claims.scopes ?? []);
8426
8480
  const missing = scopes.split(" ").filter((scope) => scope && !granted.has(scope));
8427
8481
  if (missing.length) io.stderr(`Not granted at this organization (your roles lack them): ${missing.join(" ")}`);
8428
8482
  return 0;
8429
8483
  }
8484
+ async function bindChosenOrganization(io, apiUrl, flag, remembered, info) {
8485
+ const memberships = info.organizations ?? [];
8486
+ let choice = chooseOrganization({ flag, remembered, memberships, platformActor: info.platformActor });
8487
+ if (choice.kind === "none") {
8488
+ throw new CliError("You are not a member of any organization; ask an administrator to add you, then sign in again.");
8489
+ }
8490
+ if (choice.kind === "ask") {
8491
+ if (!io.interactive) {
8492
+ throw new CliError(`You belong to several organizations; pass --organization-id <id|name>:
8493
+ ${organizationMenu(choice.options).join("\n")}`);
8494
+ }
8495
+ io.stdout("Choose the organization to act in:");
8496
+ for (const line of organizationMenu(choice.options)) io.stdout(line);
8497
+ const picked = pickFromMenu(await ask("Organization (number, id or name): "), choice.options);
8498
+ choice = { kind: "chosen", organizationId: picked.id, name: picked.name, reason: "flag" };
8499
+ }
8500
+ const source = { tokenFile: tokenFile(io.env), baseUrl: apiUrl, clientId: clientId(io.env) };
8501
+ const token = await bindOrganization(source, choice.organizationId);
8502
+ const label = choice.name ? `${choice.name} (${choice.organizationId})` : choice.organizationId;
8503
+ const why = choice.reason === "remembered" ? " (the last login; pass --organization-id to switch)" : choice.reason === "only" ? " (your only organization)" : "";
8504
+ io.stdout(`Organization: ${label}${why}`);
8505
+ return { organizationId: choice.organizationId, token };
8506
+ }
8507
+
8508
+ // src/commands/org.ts
8509
+ import { parseArgs as parseArgs3 } from "node:util";
8510
+ var orgUsage = `diverge org [use <id|name>]
8511
+
8512
+ Without a verb: the organizations you may act in, the bound one marked.
8513
+ use <id|name>: bind the login to that organization on the platform, without a
8514
+ browser; every later command acts there. A platform actor may name an
8515
+ organization they are not a member of.`;
8516
+ async function runOrg(args, io) {
8517
+ const { positionals } = parseArgs3({ args, options: {}, strict: true, allowPositionals: true });
8518
+ const apiUrl = resolveApiUrl(void 0, io.env);
8519
+ const source = { tokenFile: tokenFile(io.env), baseUrl: apiUrl, clientId: clientId(io.env) };
8520
+ const token = await getUserToken(source);
8521
+ const info = await fetchUserInfo(apiUrl, token.access_token);
8522
+ const memberships = info.organizations ?? [];
8523
+ const current = tokenClaims(token.access_token).organizationId ?? void 0;
8524
+ const verb = positionals[0];
8525
+ if (!verb) {
8526
+ if (memberships.length === 0 && !current) {
8527
+ io.stdout("You are not a member of any organization.");
8528
+ return 0;
8529
+ }
8530
+ for (const organization of memberships) io.stdout(`${organization.id === current ? "*" : " "} ${organization.name} (${organization.id})`);
8531
+ if (current && !memberships.some((organization) => organization.id === current)) io.stdout(`* ${current} (not a membership; acting as the platform)`);
8532
+ return 0;
8533
+ }
8534
+ if (verb !== "use") throw new CliError(`Unknown verb: ${verb}
8535
+
8536
+ ${orgUsage}`);
8537
+ const target = positionals[1];
8538
+ if (!target) throw new CliError("org use needs an organization id or name");
8539
+ const choice = chooseOrganization({ flag: target, memberships, platformActor: info.platformActor });
8540
+ if (choice.kind !== "chosen") throw new CliError("org use needs an organization id or name");
8541
+ const bound = await bindOrganization(source, choice.organizationId);
8542
+ writeConfig({ ...readConfig(io.env), organization: choice.organizationId }, io.env);
8543
+ io.stdout(`Organization: ${choice.name ? `${choice.name} (${choice.organizationId})` : choice.organizationId}; scopes ${(tokenClaims(bound.access_token).scopes ?? []).join(" ") || "none"}`);
8544
+ return 0;
8545
+ }
8430
8546
 
8431
8547
  // src/commands/logout.ts
8432
8548
  var logoutUsage = "diverge logout\n\nRevoke the login's session on the platform and forget it locally.";
@@ -8524,8 +8640,10 @@ async function runStatus(_args, io) {
8524
8640
  const remaining = Math.round(token.expires_at - Date.now() / 1e3);
8525
8641
  const mismatch = token.base_url !== apiUrl ? ` (for ${token.base_url}, not the configured deployment)` : "";
8526
8642
  io.stdout(`Login: ${isFresh(token, 0) ? `valid for ${remaining}s` : "expired (auto-refreshes)"}; refresh token ${token.refresh_token ? "present" : "absent"}${mismatch}`);
8527
- io.stdout(`Signed in as: ${await signedInAs(token, io)}`);
8528
- io.stdout(`Organization: ${claims.organizationId ?? "none (sign in again to choose one)"}`);
8643
+ const account = await signedInAs(token, io);
8644
+ io.stdout(`Signed in as: ${account.line}`);
8645
+ const organization = account.organizations?.find((candidate) => candidate.id === claims.organizationId);
8646
+ io.stdout(`Organization: ${claims.organizationId ? `${organization ? `${organization.name} (${claims.organizationId})` : claims.organizationId}` : "none (run: diverge org use <id|name>)"}`);
8529
8647
  io.stdout(`Scopes: ${(claims.scopes ?? []).join(" ") || "none"}`);
8530
8648
  io.stdout(describeToolExecution(io.env));
8531
8649
  return 0;
@@ -8536,9 +8654,14 @@ async function signedInAs(cached, io) {
8536
8654
  try {
8537
8655
  accessToken = (await getUserToken({ tokenFile: tokenFile(io.env), baseUrl: cached.base_url, clientId: clientId(io.env) })).access_token;
8538
8656
  } catch (error) {
8539
- return `${sub ?? "unknown user"} (email unavailable: ${error instanceof Error ? error.message : String(error)})`;
8657
+ return { line: `${sub ?? "unknown user"} (email unavailable: ${error instanceof Error ? error.message : String(error)})` };
8658
+ }
8659
+ try {
8660
+ const info = await fetchUserInfo(cached.base_url, accessToken);
8661
+ return { line: `${info.email} (${info.sub})`, organizations: info.organizations };
8662
+ } catch (error) {
8663
+ return { line: `${sub ?? "unknown user"} (email unavailable: ${error instanceof Error ? error.message : String(error)})` };
8540
8664
  }
8541
- return describeAccount(cached.base_url, accessToken, sub, { withSub: true });
8542
8665
  }
8543
8666
 
8544
8667
  // src/commands/token.ts
@@ -8551,10 +8674,10 @@ async function runToken(_args, io) {
8551
8674
  }
8552
8675
 
8553
8676
  // src/commands/tools.ts
8554
- import { parseArgs as parseArgs3 } from "node:util";
8677
+ import { parseArgs as parseArgs4 } from "node:util";
8555
8678
 
8556
8679
  // src/mcp/bridge.ts
8557
- import readline from "node:readline";
8680
+ import readline2 from "node:readline";
8558
8681
 
8559
8682
  // src/tools/client.ts
8560
8683
  var PENDING_INVOCATION_STATUSES = ["pending", "approved", "executing"];
@@ -8831,7 +8954,7 @@ var BridgeServer = class {
8831
8954
  }
8832
8955
  };
8833
8956
  async function serveBridge(server, input, output) {
8834
- const lines = readline.createInterface({ input, crlfDelay: Infinity });
8957
+ const lines = readline2.createInterface({ input, crlfDelay: Infinity });
8835
8958
  for await (const raw of lines) {
8836
8959
  const line = raw.trim();
8837
8960
  if (!line) continue;
@@ -8998,7 +9121,7 @@ async function runTools(args, io) {
8998
9121
  }
8999
9122
  switch (verb) {
9000
9123
  case "list": {
9001
- const { values } = parseArgs3({ args: rest, options: { ...SCOPE_OPTIONS, filter: { type: "string" }, capability: { type: "string" }, json: { type: "boolean", default: false } }, strict: true });
9124
+ const { values } = parseArgs4({ args: rest, options: { ...SCOPE_OPTIONS, filter: { type: "string" }, capability: { type: "string" }, json: { type: "boolean", default: false } }, strict: true });
9002
9125
  const { client: tools } = await client(values, io);
9003
9126
  let list = await tools.listTools();
9004
9127
  if (values.filter) list = list.filter((tool) => tool.name.includes(values.filter));
@@ -9008,7 +9131,7 @@ async function runTools(args, io) {
9008
9131
  return ExitCode.Ok;
9009
9132
  }
9010
9133
  case "capabilities": {
9011
- const { values } = parseArgs3({ args: rest, options: { ...SCOPE_OPTIONS, json: { type: "boolean", default: false } }, strict: true });
9134
+ const { values } = parseArgs4({ args: rest, options: { ...SCOPE_OPTIONS, json: { type: "boolean", default: false } }, strict: true });
9012
9135
  const { client: tools } = await client(values, io);
9013
9136
  const list = await tools.listTools();
9014
9137
  if (values.json) io.stdout(JSON.stringify(capabilityClusters(list), null, 2));
@@ -9016,7 +9139,7 @@ async function runTools(args, io) {
9016
9139
  return ExitCode.Ok;
9017
9140
  }
9018
9141
  case "describe": {
9019
- const { values, positionals } = parseArgs3({ args: rest, options: { ...SCOPE_OPTIONS, json: { type: "boolean", default: false } }, strict: true, allowPositionals: true });
9142
+ const { values, positionals } = parseArgs4({ args: rest, options: { ...SCOPE_OPTIONS, json: { type: "boolean", default: false } }, strict: true, allowPositionals: true });
9020
9143
  const name = positionals[0];
9021
9144
  if (!name) throw new CliError("describe needs a tool name");
9022
9145
  const { settings, client: tools } = await client(values, io);
@@ -9031,7 +9154,7 @@ async function runTools(args, io) {
9031
9154
  return ExitCode.Ok;
9032
9155
  }
9033
9156
  case "call": {
9034
- const { values, positionals } = parseArgs3({ args: rest, options: { ...SCOPE_OPTIONS, "args-json": { type: "string", default: "{}" }, wait: { type: "boolean", default: false }, timeout: { type: "string", default: "600" } }, strict: true, allowPositionals: true });
9157
+ const { values, positionals } = parseArgs4({ args: rest, options: { ...SCOPE_OPTIONS, "args-json": { type: "string", default: "{}" }, wait: { type: "boolean", default: false }, timeout: { type: "string", default: "600" } }, strict: true, allowPositionals: true });
9035
9158
  const name = positionals[0];
9036
9159
  if (!name) throw new CliError("call needs a tool name");
9037
9160
  let parsedArgs;
@@ -9060,7 +9183,7 @@ async function runTools(args, io) {
9060
9183
  return emit(io, settledOutcome(invocation));
9061
9184
  }
9062
9185
  case "invocation": {
9063
- const { values, positionals } = parseArgs3({ args: rest, options: { ...SCOPE_OPTIONS, wait: { type: "boolean", default: false }, timeout: { type: "string", default: "600" }, json: { type: "boolean", default: false } }, strict: true, allowPositionals: true });
9186
+ const { values, positionals } = parseArgs4({ args: rest, options: { ...SCOPE_OPTIONS, wait: { type: "boolean", default: false }, timeout: { type: "string", default: "600" }, json: { type: "boolean", default: false } }, strict: true, allowPositionals: true });
9064
9187
  const id = positionals[0];
9065
9188
  if (!id) throw new CliError("invocation needs an id");
9066
9189
  const { client: tools } = await client(values, io);
@@ -9078,7 +9201,7 @@ async function runTools(args, io) {
9078
9201
  return emit(io, settledOutcome(invocation));
9079
9202
  }
9080
9203
  case "bridge": {
9081
- const { values } = parseArgs3({ args: rest, options: { ...SCOPE_OPTIONS, tools: { type: "string" } }, strict: true });
9204
+ const { values } = parseArgs4({ args: rest, options: { ...SCOPE_OPTIONS, tools: { type: "string" } }, strict: true });
9082
9205
  const { client: tools } = await client(values, io);
9083
9206
  const allow = (values.tools ?? "").split(",").map((name) => name.trim()).filter(Boolean);
9084
9207
  return serveBridge(new BridgeServer(tools, { tools: allow }), process.stdin, process.stdout);
@@ -9092,7 +9215,7 @@ ${toolsUsage}`);
9092
9215
 
9093
9216
  // src/commands/plugins.ts
9094
9217
  import fs7 from "node:fs";
9095
- import { parseArgs as parseArgs4 } from "node:util";
9218
+ import { parseArgs as parseArgs5 } from "node:util";
9096
9219
  var pluginsUsage = `diverge plugins <validate|publish|list|retire> [--organization-id <id>] ...
9097
9220
 
9098
9221
  validate <manifest.json> (dry run: the platform's full validation, nothing stored)
@@ -9155,7 +9278,7 @@ async function runPlugins(args, io) {
9155
9278
  }
9156
9279
  switch (verb) {
9157
9280
  case "validate": {
9158
- const { values, positionals } = parseArgs4({ args: rest, options: { ...SCOPE_OPTIONS2, json: { type: "boolean", default: false } }, allowPositionals: true, strict: true });
9281
+ const { values, positionals } = parseArgs5({ args: rest, options: { ...SCOPE_OPTIONS2, json: { type: "boolean", default: false } }, allowPositionals: true, strict: true });
9159
9282
  const manifest = readManifest(positionals[0]);
9160
9283
  const tools = await client2(values, io);
9161
9284
  const outcome = await tools.publishPlugin(manifest, { dryRun: true });
@@ -9172,7 +9295,7 @@ async function runPlugins(args, io) {
9172
9295
  return ExitCode.Ok;
9173
9296
  }
9174
9297
  case "publish": {
9175
- const { values, positionals } = parseArgs4({ args: rest, options: { ...SCOPE_OPTIONS2, json: { type: "boolean", default: false } }, allowPositionals: true, strict: true });
9298
+ const { values, positionals } = parseArgs5({ args: rest, options: { ...SCOPE_OPTIONS2, json: { type: "boolean", default: false } }, allowPositionals: true, strict: true });
9176
9299
  const manifest = readManifest(positionals[0]);
9177
9300
  const tools = await client2(values, io);
9178
9301
  const outcome = await tools.publishPlugin(manifest, { dryRun: false });
@@ -9190,7 +9313,7 @@ async function runPlugins(args, io) {
9190
9313
  return ExitCode.Ok;
9191
9314
  }
9192
9315
  case "list": {
9193
- const { values } = parseArgs4({ args: rest, options: { ...SCOPE_OPTIONS2, json: { type: "boolean", default: false } }, strict: true });
9316
+ const { values } = parseArgs5({ args: rest, options: { ...SCOPE_OPTIONS2, json: { type: "boolean", default: false } }, strict: true });
9194
9317
  const tools = await client2(values, io);
9195
9318
  const plugins = await tools.listPlugins();
9196
9319
  if (values.json) io.stdout(JSON.stringify(plugins, null, 2));
@@ -9199,7 +9322,7 @@ async function runPlugins(args, io) {
9199
9322
  return ExitCode.Ok;
9200
9323
  }
9201
9324
  case "retire": {
9202
- const { values, positionals } = parseArgs4({ args: rest, options: SCOPE_OPTIONS2, allowPositionals: true, strict: true });
9325
+ const { values, positionals } = parseArgs5({ args: rest, options: SCOPE_OPTIONS2, allowPositionals: true, strict: true });
9203
9326
  const pluginId = positionals[0];
9204
9327
  if (!pluginId) throw new CliError(`A plugin id is required.
9205
9328
 
@@ -9269,6 +9392,7 @@ var COMMANDS = [
9269
9392
  { name: "login", summary: "Sign in through the browser", usage: loginUsage, run: runLogin },
9270
9393
  { name: "logout", summary: "Revoke the login and forget it", usage: logoutUsage, run: runLogout },
9271
9394
  { name: "status", summary: "Show the deployment and the cached login", usage: statusUsage, run: runStatus },
9395
+ { name: "org", summary: "Show or switch the organization the login acts in", usage: orgUsage, run: runOrg },
9272
9396
  { name: "token", summary: "Print a fresh access token", usage: tokenUsage, run: runToken },
9273
9397
  { name: "agents", summary: "Point a coding agent at the model gateway (setup, run, status)", usage: agentsUsage, run: runAgents },
9274
9398
  { name: "tools", summary: "Discover and execute platform tools; raise and read approvals", usage: toolsUsage, run: runTools },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@divergeai/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Divergent platform CLI: sign in, wire coding agents to the inference gateway, call platform tools",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",