@duvoai/cli 1.45.3 → 1.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/duvo.js CHANGED
@@ -9796,15 +9796,7 @@ var adminCaseQueueConsumerSchema = z49.object({
9796
9796
  agentName: z49.string(),
9797
9797
  caseTriggerEnabled: z49.boolean(),
9798
9798
  isHandoverTarget: z49.boolean(),
9799
- problems: z49.array(adminCaseQueueAgentProblemSchema),
9800
- /** Raw concurrency set on the trigger row, null if unset or no trigger exists. */
9801
- triggerConcurrency: z49.number().nullable(),
9802
- /**
9803
- * Effective concurrency for the consumer trigger:
9804
- * `min(triggerConcurrency ?? defaultConcurrency, maxConcurrency)`.
9805
- * Null when this consumer has no trigger.
9806
- */
9807
- effectiveConcurrency: z49.number().nullable()
9799
+ problems: z49.array(adminCaseQueueAgentProblemSchema)
9808
9800
  });
9809
9801
  var adminCaseQueueItemSummarySchema = z49.object({
9810
9802
  id: z49.string(),
@@ -9858,6 +9850,13 @@ var adminCaseQueueDetailResponseSchema = z49.object({
9858
9850
  name: z49.string(),
9859
9851
  description: z49.string().nullable(),
9860
9852
  folderId: z49.string().nullable(),
9853
+ /** The configured per-queue concurrency cap (case_queue.concurrency); null uses the default. */
9854
+ configuredConcurrency: z49.number().nullable(),
9855
+ /**
9856
+ * Effective per-queue concurrency after the default fallback and the
9857
+ * `MAX_CASE_TRIGGER_CONCURRENCY` ceiling. Always a number.
9858
+ */
9859
+ effectiveConcurrency: z49.number(),
9861
9860
  createdAt: z49.string(),
9862
9861
  updatedAt: z49.string()
9863
9862
  }),
@@ -9865,13 +9864,13 @@ var adminCaseQueueDetailResponseSchema = z49.object({
9865
9864
  consumers: z49.array(adminCaseQueueConsumerSchema),
9866
9865
  /**
9867
9866
  * `env.DEFAULT_CASE_TRIGGER_CONCURRENCY` — the per-queue concurrency applied
9868
- * to a trigger that has no concurrency set.
9867
+ * to a queue that has no explicit cap set.
9869
9868
  */
9870
9869
  defaultConcurrency: z49.number(),
9871
9870
  /**
9872
9871
  * `env.MAX_CASE_TRIGGER_CONCURRENCY` — the hard per-queue ceiling for
9873
- * effective trigger concurrency, clamping both a trigger's own concurrency
9874
- * and the fallback default when either exceeds this value.
9872
+ * effective concurrency, clamping both a queue's own cap and the fallback
9873
+ * default when either exceeds this value.
9875
9874
  */
9876
9875
  maxConcurrency: z49.number(),
9877
9876
  items: z49.object({
@@ -9882,20 +9881,19 @@ var adminCaseQueueDetailResponseSchema = z49.object({
9882
9881
  })
9883
9882
  })
9884
9883
  });
9885
- var adminUpdateCaseTriggerConcurrencyRequestSchema = z49.object({
9884
+ var adminUpdateQueueConcurrencyRequestSchema = z49.object({
9886
9885
  concurrency: z49.int().positive().nullable().describe(
9887
- "New per-trigger concurrency cap. A positive integer (up to the platform max) sets an explicit cap; null clears it so the trigger uses the platform default."
9886
+ "New per-queue concurrency cap. A positive integer (up to the platform max) sets an explicit cap; null clears it so the queue uses the platform default."
9888
9887
  )
9889
9888
  });
9890
- var adminUpdateCaseTriggerConcurrencyResponseSchema = z49.object({
9889
+ var adminUpdateQueueConcurrencyResponseSchema = z49.object({
9891
9890
  data: z49.object({
9892
- agentId: z49.string(),
9893
- /** Raw concurrency stored on the trigger row, null when using the default. */
9894
- triggerConcurrency: z49.number().nullable(),
9891
+ queueId: z49.string(),
9892
+ /** The configured concurrency stored on the queue row, null when using the default. */
9893
+ configuredConcurrency: z49.number().nullable(),
9895
9894
  /**
9896
9895
  * Effective concurrency after applying the default fallback and the
9897
- * `MAX_CASE_TRIGGER_CONCURRENCY` ceiling. Always a number because a trigger
9898
- * row exists.
9896
+ * `MAX_CASE_TRIGGER_CONCURRENCY` ceiling.
9899
9897
  */
9900
9898
  effectiveConcurrency: z49.number()
9901
9899
  })
@@ -11542,7 +11540,6 @@ var automationRevisionQueueBindingApiSchema = z64.object({
11542
11540
  "Agent the queue routes to in this revision (null when unrouted)"
11543
11541
  ),
11544
11542
  enabled: z64.boolean().describe("Whether the queue's routing is enabled"),
11545
- concurrency: z64.int().nullable().describe("Per-revision concurrency limit (null for the queue default)"),
11546
11543
  name: z64.string().nullable().describe(
11547
11544
  "Per-revision queue name override (null to keep the queue's own name)"
11548
11545
  ),
@@ -11586,6 +11583,111 @@ var automationRevisionScheduleBindingApiSchema = z64.object({
11586
11583
  day_of_month: z64.int().min(1).max(31).nullable().describe("Day of month for a monthly schedule"),
11587
11584
  task: z64.string().nullable().describe("Prompt passed as the run's initial user message")
11588
11585
  });
11586
+ var automationTriggerSubscriptionApiSchema = z64.object({
11587
+ id: z64.guid().describe("Subscription identifier"),
11588
+ automation_trigger_id: z64.guid().describe("Declaration this subscription fulfills"),
11589
+ user_id: z64.guid().nullable().describe(
11590
+ "Scope owner. Always populated today: a null-scope (team) subscription needs the shared-run runtime, so nothing creates one yet"
11591
+ ),
11592
+ created_by: z64.guid().nullable().describe("Who authored the subscription"),
11593
+ enabled: z64.boolean().describe("Whether this scope participates"),
11594
+ integration_instance_id: z64.guid().nullable().describe("The connection this subscription currently fires with"),
11595
+ pending_integration_instance_id: z64.guid().nullable().describe(
11596
+ "A connection change staged with a draft, applied atomically on that draft's promotion"
11597
+ ),
11598
+ pending_from_revision_id: z64.guid().nullable().describe("Draft revision the staged connection change belongs to")
11599
+ });
11600
+ var automationScheduleSubscriptionApiSchema = z64.object({
11601
+ id: z64.guid().describe("Subscription identifier"),
11602
+ automation_schedule_id: z64.guid().describe("Declaration this subscription fulfills"),
11603
+ user_id: z64.guid().nullable().describe(
11604
+ "Scope owner. Always populated today: a null-scope (team) subscription needs the shared-run runtime, so nothing creates one yet"
11605
+ ),
11606
+ created_by: z64.guid().nullable().describe("Who authored the subscription"),
11607
+ enabled: z64.boolean().describe("Whether this scope participates")
11608
+ });
11609
+ var automationRevisionTriggersResponseApiSchema = z64.object({
11610
+ revision_id: z64.guid().describe("Revision these declarations were read from"),
11611
+ revision_status: automationRevisionStatusApiSchema.describe(
11612
+ "`draft`, `live`, or `historic` \u2014 drives read-only presentation"
11613
+ ),
11614
+ revision_updated_at: z64.string().describe(
11615
+ "ISO 8601 change stamp, and the concurrency token for the paired PUT. Send it back as `If-Match` and a write from stale state is refused with 409. Without it there is no check, and because the PUT replaces the complete set, a stale client silently drops declarations another editor added"
11616
+ ),
11617
+ triggers: z64.array(automationRevisionTriggerBindingApiSchema).describe(
11618
+ "Credential-free trigger declarations and this revision's config"
11619
+ ),
11620
+ subscriptions: z64.array(automationTriggerSubscriptionApiSchema).describe(
11621
+ "How each declaration is fulfilled **right now** \u2014 every scope's, not just the caller's. Returned at any revision status, and always current state: this is not a record of what fulfilled the declaration while a historic revision was live (that is not stored). On a historic revision it answers what a rollback would resume \u2014 note that activation disables the subscriptions of a declaration a newer revision omits and never re-enables them, so a bound-but-disabled row means rolling back will not resume it until each member opts back in"
11622
+ )
11623
+ });
11624
+ var automationRevisionSchedulesResponseApiSchema = z64.object({
11625
+ revision_id: z64.guid().describe("Revision these declarations were read from"),
11626
+ revision_status: automationRevisionStatusApiSchema.describe(
11627
+ "`draft`, `live`, or `historic` \u2014 drives read-only presentation"
11628
+ ),
11629
+ revision_updated_at: z64.string().describe(
11630
+ "ISO 8601 change stamp, and the concurrency token for the paired PUT. Send it back as `If-Match` and a write from stale state is refused with 409. Without it there is no check, and because the PUT replaces the complete set, a stale client silently drops declarations another editor added"
11631
+ ),
11632
+ schedules: z64.array(automationRevisionScheduleBindingApiSchema).describe(
11633
+ "Credential-free schedule declarations and this revision's config"
11634
+ ),
11635
+ subscriptions: z64.array(automationScheduleSubscriptionApiSchema).describe(
11636
+ "Who the schedule runs as **right now** \u2014 every scope's, not just the caller's. Returned at any revision status, and always current state rather than a record of who it ran as while a historic revision was live. Unlike the trigger lane, activation never disables a schedule opt-in when a revision omits the declaration, so these survive a rollback intact"
11637
+ )
11638
+ });
11639
+ var setAutomationRevisionTriggerApiSchema = z64.object({
11640
+ automation_trigger_id: z64.guid().optional().describe("Existing declaration to update; omit to mint a new one"),
11641
+ agent_id: z64.guid().describe("Agent this trigger routes to"),
11642
+ integration_slug: z64.string().min(1).describe("Integration to watch"),
11643
+ trigger_type: z64.string().min(1).describe("Trigger type within the integration"),
11644
+ enabled: z64.boolean().default(true).describe("Whether the trigger is enabled in this revision"),
11645
+ filter_config: z64.record(z64.string(), z64.unknown()).default({}).describe("Per-revision filter configuration"),
11646
+ integration_instance_id: z64.guid().nullable().optional().describe(
11647
+ "Connection to fulfill this declaration with. Applied on promotion for an already-live declaration; set directly for one that is not live. Omit to leave it as it is; pass null to discard a choice staged against this draft"
11648
+ )
11649
+ });
11650
+ var setAutomationRevisionTriggersRequestApiSchema = z64.object({
11651
+ triggers: z64.array(setAutomationRevisionTriggerApiSchema).describe(
11652
+ "The draft's complete desired trigger set; declarations absent here are removed from the draft"
11653
+ )
11654
+ });
11655
+ var setAutomationRevisionScheduleApiSchema = z64.object({
11656
+ automation_schedule_id: z64.guid().optional().describe("Existing declaration to update; omit to mint a new one"),
11657
+ agent_id: z64.guid().describe("Agent this schedule fires"),
11658
+ enabled: z64.boolean().default(true).describe("Whether the schedule is enabled"),
11659
+ cron: z64.string().min(1).nullable().optional().describe("5-field cron expression; mutually exclusive with `frequency`"),
11660
+ frequency: z64.enum(AUTOMATION_SCHEDULE_FREQUENCIES).nullable().optional().describe("Frequency form; mutually exclusive with `cron`"),
11661
+ time: z64.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/).nullable().optional().describe("Local time of day as HH:MM"),
11662
+ timezone: z64.string().default("UTC").describe("IANA timezone the schedule is evaluated in"),
11663
+ day: z64.enum(AUTOMATION_SCHEDULE_DAYS).nullable().optional().describe("Day of week for a weekly schedule"),
11664
+ day_of_month: z64.int().min(1).max(31).nullable().optional().describe("Day of month for a monthly schedule"),
11665
+ task: z64.string().nullable().optional().describe("Prompt passed as the run's initial user message")
11666
+ });
11667
+ var setAutomationRevisionSchedulesRequestApiSchema = z64.object({
11668
+ schedules: z64.array(setAutomationRevisionScheduleApiSchema).describe(
11669
+ "The draft's complete desired schedule set; declarations absent here are removed from the draft"
11670
+ )
11671
+ });
11672
+ var setAutomationTriggerSubscriptionRequestApiSchema = z64.object({
11673
+ enabled: z64.boolean().describe("Whether this scope participates"),
11674
+ integration_instance_id: z64.guid().nullable().optional().describe(
11675
+ "Connection this scope fires with. Required to enable a subscription that has none"
11676
+ )
11677
+ });
11678
+ var setAutomationScheduleSubscriptionRequestApiSchema = z64.object({
11679
+ enabled: z64.boolean().describe("Whether this scope participates")
11680
+ });
11681
+ var automationTriggerSubscriptionResponseApiSchema = z64.object({
11682
+ subscription: automationTriggerSubscriptionApiSchema.describe(
11683
+ "The subscription after the change"
11684
+ )
11685
+ });
11686
+ var automationScheduleSubscriptionResponseApiSchema = z64.object({
11687
+ subscription: automationScheduleSubscriptionApiSchema.describe(
11688
+ "The subscription after the change"
11689
+ )
11690
+ });
11589
11691
  var automationRevisionDetailApiSchema = automationRevisionSummaryApiSchema.extend({
11590
11692
  ai_description: z64.string().nullable().describe(
11591
11693
  "AI-generated short description of what this revision does (null until generated)"
@@ -11665,9 +11767,6 @@ var setAutomationRevisionQueueBodyApiSchema = z64.object({
11665
11767
  enabled: z64.boolean().optional().describe(
11666
11768
  "Whether routing is enabled (omit to keep current; default true when new)"
11667
11769
  ),
11668
- concurrency: z64.int().nonnegative().nullable().optional().describe(
11669
- "Per-revision concurrency limit (null for queue default; omit to keep current)"
11670
- ),
11671
11770
  name: revisionNameFieldSchema.nullable().optional().describe("Per-revision name override (null clears; omit to keep current)"),
11672
11771
  description: revisionDescriptionFieldSchema.nullable().optional().describe(
11673
11772
  "Per-revision description override (null clears; omit to keep current)"
@@ -12592,6 +12691,7 @@ var getTeamInviteLinkResponseSchema = z79.object({
12592
12691
  hasLink: z79.boolean(),
12593
12692
  link: teamInviteLinkSchema.optional()
12594
12693
  });
12694
+ var createTeamInviteLinkResponseSchema = teamInviteLinkSchema;
12595
12695
  var joinLinkInfoResponseSchema = z79.object({
12596
12696
  valid: z79.boolean(),
12597
12697
  teamName: z79.string().optional(),
@@ -13844,6 +13944,7 @@ var bulkInviteResponseSchema = z93.object({
13844
13944
  skipped: z93.number(),
13845
13945
  failed: z93.number()
13846
13946
  });
13947
+ var createTeamInvitationResponseSchema = teamInvitationDetailApiSchema;
13847
13948
  var TEAM_DISCOVERY_MODES = ["request", "auto"];
13848
13949
  var teamDiscoveryModeSchema = z94.enum(TEAM_DISCOVERY_MODES);
13849
13950
  var BrowserRegionSchema = z94.enum([
@@ -16010,7 +16111,8 @@ function normalizeProfile(value) {
16010
16111
  return {
16011
16112
  type: "api-key",
16012
16113
  apiKey: profile.apiKey,
16013
- apiBaseUrl
16114
+ apiBaseUrl,
16115
+ defaultTeamId: typeof profile.defaultTeamId === "string" ? profile.defaultTeamId : void 0
16014
16116
  };
16015
16117
  }
16016
16118
  return null;
@@ -16188,7 +16290,10 @@ async function resolveConfig(options = {}) {
16188
16290
  apiBaseUrl: env.DUVO_API_BASE_URL ?? profile.apiBaseUrl,
16189
16291
  profileName,
16190
16292
  authType: "api-key",
16191
- defaultTeamId: null
16293
+ // Honored for user-scoped keys (team_id NULL server-side), which can
16294
+ // act on every team the owner can reach; a team-scoped key ignores it
16295
+ // because the server pins the key's team.
16296
+ defaultTeamId: profile.defaultTeamId ?? null
16192
16297
  };
16193
16298
  }
16194
16299
  const fresh = await ensureFreshOAuthProfile(config, profileName, profile);
@@ -16333,6 +16438,11 @@ async function resolveTeamIdFromApiKey(config) {
16333
16438
  "API key is not associated with a team. Pass --team <id> or check your key."
16334
16439
  );
16335
16440
  }
16441
+ if (parsed.data.teams.length > 1) {
16442
+ throw new CliError(
16443
+ "This key can act on multiple teams. Pass --team <id>, set DUVO_TEAM_ID, or choose a default with `duvo team use <id>`. Run `duvo teams list` to see them."
16444
+ );
16445
+ }
16336
16446
  return team.id;
16337
16447
  }
16338
16448
  __name(resolveTeamIdFromApiKey, "resolveTeamIdFromApiKey");
@@ -29096,187 +29206,865 @@ function registerIntegrations(program) {
29096
29206
  }
29097
29207
  __name(registerIntegrations, "registerIntegrations");
29098
29208
 
29099
- // src/commands/login.ts
29100
- import { isCancel as isCancel4, log, password, spinner, text as text2 } from "@clack/prompts";
29101
-
29102
- // src/oauth/auth0-config.ts
29103
- var BAKED_DOMAIN = "login.duvo.ai" ? "login.duvo.ai" : "login.dev.duvo.ai";
29104
- var BAKED_CLIENT_ID = "MpK8jktbMHPlrCxmSPeRbkiSNrRTUjeT" ? "MpK8jktbMHPlrCxmSPeRbkiSNrRTUjeT" : "mq4MhUUHRNKrzkqr1MnAJdcvv5MNfuBU";
29105
- var BAKED_AUDIENCE = "https://api.duvo.ai" ? "https://api.duvo.ai" : "https://api.dev.duvo.ai";
29106
- function resolveAuth0Config() {
29107
- return {
29108
- domain: BAKED_DOMAIN,
29109
- clientId: BAKED_CLIENT_ID,
29110
- audience: BAKED_AUDIENCE,
29111
- issuer: `https://${BAKED_DOMAIN}/`
29112
- };
29113
- }
29114
- __name(resolveAuth0Config, "resolveAuth0Config");
29115
-
29116
- // src/oauth/loopback.ts
29117
- import { createServer } from "node:http";
29118
- var LOOPBACK_PORTS = [49152, 49153, 49154, 49155, 49156];
29119
- var HOST = "127.0.0.1";
29120
- async function startLoopbackServer() {
29121
- const result = await tryBindNext([...LOOPBACK_PORTS]);
29122
- if (!result) {
29209
+ // src/commands/invite/team-roles.ts
29210
+ var TEAM_ROLES2 = Object.values(TEAM_ROLE);
29211
+ var DEFAULT_TEAM_ROLE = TEAM_ROLE.MEMBER;
29212
+ function assertTeamRole(role, flag = "--role") {
29213
+ if (!TEAM_ROLES2.includes(role)) {
29123
29214
  throw new CliError(
29124
- `Could not bind to a local port \u2014 tried ${LOOPBACK_PORTS.join(", ")}.`
29215
+ `Invalid ${flag} "${role}"; expected one of: ${TEAM_ROLES2.join(", ")}`
29125
29216
  );
29126
29217
  }
29127
- const redirectUri = `http://${HOST}:${result.port}/callback`;
29128
- return wrapServer(result.server, redirectUri);
29218
+ return role;
29129
29219
  }
29130
- __name(startLoopbackServer, "startLoopbackServer");
29131
- async function tryBindNext(ports) {
29132
- if (ports.length === 0) {
29133
- return null;
29220
+ __name(assertTeamRole, "assertTeamRole");
29221
+
29222
+ // src/commands/invite/bulk.ts
29223
+ var MAX_MEMBERS = 50;
29224
+ function collect3(value, previous = []) {
29225
+ return [...previous, value];
29226
+ }
29227
+ __name(collect3, "collect");
29228
+ function parseMember(value, defaultRole) {
29229
+ const raw = trimRequired(value, "--member");
29230
+ const separator = raw.indexOf("=");
29231
+ if (separator === -1) {
29232
+ return { email: raw, role: defaultRole };
29134
29233
  }
29135
- const [port, ...rest] = ports;
29136
- const server = await tryBind(port);
29137
- if (server) {
29138
- return { server, port };
29234
+ const email = raw.slice(0, separator).trim();
29235
+ const role = raw.slice(separator + 1).trim();
29236
+ if (email.length === 0) {
29237
+ throw new CliError(
29238
+ `Invalid --member "${raw}"; expected <email> or <email>=<role>.`
29239
+ );
29139
29240
  }
29140
- return tryBindNext(rest);
29141
- }
29142
- __name(tryBindNext, "tryBindNext");
29143
- async function tryBind(port) {
29144
- return new Promise((resolve) => {
29145
- const server = createServer();
29146
- const onError = /* @__PURE__ */ __name((err) => {
29147
- if (err.code === "EADDRINUSE" || err.code === "EACCES") {
29148
- resolve(null);
29149
- return;
29150
- }
29151
- server.close();
29152
- resolve(null);
29153
- }, "onError");
29154
- server.once("error", onError);
29155
- server.listen(port, HOST, () => {
29156
- server.removeListener("error", onError);
29157
- const address = server.address();
29158
- if (!address || address.port !== port) {
29159
- server.close();
29160
- resolve(null);
29161
- return;
29162
- }
29163
- resolve(server);
29164
- });
29165
- });
29241
+ return { email, role: assertTeamRole(role, `--member ${email} role`) };
29166
29242
  }
29167
- __name(tryBind, "tryBind");
29168
- function wrapServer(server, redirectUri) {
29169
- let resolved = false;
29170
- let resolver = null;
29171
- let rejecter = null;
29172
- server.on("request", (req, res) => {
29173
- if (!req.url) {
29174
- res.statusCode = 400;
29175
- res.end("Bad Request");
29176
- return;
29243
+ __name(parseMember, "parseMember");
29244
+ function registerInviteBulk(invite) {
29245
+ invite.command("bulk").description("Invite several people to a team and email each invitation").requiredOption(
29246
+ "--member <email[=role]>",
29247
+ "person to invite; repeat for multiple. Append =<role> to override the --role default",
29248
+ collect3,
29249
+ []
29250
+ ).option(
29251
+ "--role <role>",
29252
+ `role for members that don't specify their own (default ${DEFAULT_TEAM_ROLE})`,
29253
+ DEFAULT_TEAM_ROLE
29254
+ ).option(
29255
+ "--team <id>",
29256
+ "team ID (defaults to the team scoped to your credentials)"
29257
+ ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function bulkAction(options) {
29258
+ if (options.member.length === 0) {
29259
+ throw new CliError("Provide at least one --member <email[=role]>.");
29177
29260
  }
29178
- const url = new URL(req.url, redirectUri);
29179
- if (url.pathname !== "/callback") {
29180
- res.statusCode = 404;
29181
- res.end("Not Found");
29182
- return;
29261
+ const defaultRole = assertTeamRole(options.role ?? DEFAULT_TEAM_ROLE);
29262
+ const members = options.member.map(
29263
+ (value) => parseMember(value, defaultRole)
29264
+ );
29265
+ if (members.length > MAX_MEMBERS) {
29266
+ throw new CliError(
29267
+ `Provide at most ${MAX_MEMBERS} --member values (got ${members.length}).`
29268
+ );
29183
29269
  }
29184
- const error = url.searchParams.get("error");
29185
- const code = url.searchParams.get("code");
29186
- const state = url.searchParams.get("state");
29187
- if (error) {
29188
- const description = url.searchParams.get("error_description") ?? error;
29189
- res.statusCode = 400;
29190
- res.setHeader("Content-Type", "text/html; charset=utf-8");
29191
- res.end(renderHtml(`Authorization failed: ${description}`));
29192
- if (!resolved && rejecter) {
29193
- resolved = true;
29194
- rejecter(new CliError(`Authorization denied: ${description}`));
29195
- }
29196
- return;
29270
+ const emails = members.map((member) => member.email.toLowerCase());
29271
+ if (new Set(emails).size !== emails.length) {
29272
+ throw new CliError("--member emails must be unique.");
29197
29273
  }
29198
- if (!code || !state) {
29199
- res.statusCode = 400;
29200
- res.setHeader("Content-Type", "text/html; charset=utf-8");
29201
- res.end(renderHtml("Missing code or state."));
29202
- if (!resolved && rejecter) {
29203
- resolved = true;
29204
- rejecter(new CliError("Callback missing code or state."));
29274
+ const config = await requireAuthenticatedConfig(this);
29275
+ const { apiKey, apiBaseUrl } = config;
29276
+ const teamId = await resolveRequiredTeamId(config, {
29277
+ override: options.team ?? getTeamFlag(this)
29278
+ });
29279
+ const raw = await httpRequest({
29280
+ method: "POST",
29281
+ path: buildTeamPath(teamId, "/invites/bulk"),
29282
+ apiKey,
29283
+ apiBaseUrl,
29284
+ body: { members }
29285
+ });
29286
+ const parsed = bulkInviteResponseSchema.safeParse(raw);
29287
+ if (options.json) {
29288
+ printJson(raw);
29289
+ if (parsed.success && parsed.data.failed > 0) {
29290
+ throw new CliError(
29291
+ `${parsed.data.failed} of ${members.length} invitations could not be emailed and were rolled back.`
29292
+ );
29205
29293
  }
29206
29294
  return;
29207
29295
  }
29208
- res.statusCode = 200;
29209
- res.setHeader("Content-Type", "text/html; charset=utf-8");
29210
- res.end(renderHtml("You are now signed in. You can close this tab."));
29211
- if (!resolved && resolver) {
29212
- resolved = true;
29213
- resolver({ code, state });
29296
+ if (!parsed.success) {
29297
+ throw new CliError(
29298
+ `Unexpected response from the API: ${parsed.error.message}`
29299
+ );
29214
29300
  }
29215
- });
29216
- return {
29217
- redirectUri,
29218
- waitForCallback(timeoutMs) {
29219
- return new Promise((resolve, reject) => {
29220
- resolver = resolve;
29221
- rejecter = reject;
29222
- const timer = setTimeout(() => {
29223
- if (!resolved) {
29224
- resolved = true;
29225
- reject(new CliError("Authorization timed out."));
29226
- }
29227
- }, timeoutMs);
29228
- timer.unref();
29229
- });
29230
- },
29231
- async close() {
29232
- await new Promise((resolve) => server.close(() => resolve()));
29301
+ const { succeeded, skipped, failed } = parsed.data;
29302
+ console.log(green(`Invited ${succeeded} of ${members.length} people.`));
29303
+ console.log();
29304
+ console.log(
29305
+ renderKeyValue([
29306
+ { label: "Invited", value: String(succeeded) },
29307
+ { label: "Skipped", value: String(skipped) },
29308
+ { label: "Failed", value: String(failed) }
29309
+ ])
29310
+ );
29311
+ if (skipped > 0) {
29312
+ console.log();
29313
+ console.log(
29314
+ "Skipped people are already on the team or already hold a pending invitation."
29315
+ );
29233
29316
  }
29234
- };
29235
- }
29236
- __name(wrapServer, "wrapServer");
29237
- var HTML_ESCAPES = {
29238
- "&": "&amp;",
29239
- "<": "&lt;",
29240
- ">": "&gt;"
29241
- };
29242
- function renderHtml(message) {
29243
- const safe = message.replace(/[&<>]/g, (c) => HTML_ESCAPES[c] ?? c);
29244
- return `<!doctype html>
29245
- <html lang="en">
29246
- <head>
29247
- <meta charset="utf-8" />
29248
- <title>Duvo CLI</title>
29249
- <style>
29250
- body { font-family: system-ui, sans-serif; padding: 4rem; text-align: center; }
29251
- .card { display: inline-block; padding: 2rem 3rem; border-radius: 12px; background: #f6f8fa; }
29252
- </style>
29253
- </head>
29254
- <body>
29255
- <div class="card">
29256
- <h2>Duvo CLI</h2>
29257
- <p>${safe}</p>
29258
- </div>
29259
- </body>
29260
- </html>`;
29317
+ if (failed > 0) {
29318
+ console.log();
29319
+ console.log(
29320
+ "Failed invitations could not be emailed and were rolled back \u2014 re-run for those addresses."
29321
+ );
29322
+ throw new CliError(
29323
+ `${failed} of ${members.length} invitations could not be emailed and were rolled back.`
29324
+ );
29325
+ }
29326
+ }, "bulkAction"));
29261
29327
  }
29262
- __name(renderHtml, "renderHtml");
29328
+ __name(registerInviteBulk, "registerInviteBulk");
29263
29329
 
29264
- // src/oauth/open-browser.ts
29265
- import { spawn } from "node:child_process";
29266
- import { platform } from "node:os";
29267
- var BASE_OPTIONS = {
29268
- detached: true,
29269
- stdio: "ignore",
29270
- shell: false
29271
- };
29272
- function spawnPlanFor(url) {
29273
- const os = platform();
29274
- if (os === "darwin") {
29275
- return { command: "open", args: [url], options: BASE_OPTIONS };
29330
+ // src/api/invite-schemas.ts
29331
+ import { z as z127 } from "zod";
29332
+ var updateTeamInviteResponseSchema = z127.object({
29333
+ id: z127.string(),
29334
+ role: z127.string()
29335
+ });
29336
+ var inviteSuccessResponseSchema = z127.object({
29337
+ success: z127.literal(true)
29338
+ });
29339
+
29340
+ // src/commands/invite/send-invitation-email.ts
29341
+ function classifyFailure(error) {
29342
+ if (error instanceof CliHttpError && error.status < 500) {
29343
+ return "failed";
29276
29344
  }
29277
- if (os === "win32") {
29278
- return {
29279
- command: "cmd.exe",
29345
+ return "unconfirmed";
29346
+ }
29347
+ __name(classifyFailure, "classifyFailure");
29348
+ async function trySendInvitationEmail(args) {
29349
+ try {
29350
+ const raw = await httpRequest({
29351
+ method: "POST",
29352
+ path: buildTeamPath(
29353
+ args.teamId,
29354
+ `/invites/${encodeURIComponent(args.inviteId)}/send-email`
29355
+ ),
29356
+ apiKey: args.apiKey,
29357
+ apiBaseUrl: args.apiBaseUrl,
29358
+ body: {}
29359
+ });
29360
+ const parsed = inviteSuccessResponseSchema.safeParse(raw);
29361
+ if (parsed.success) {
29362
+ return { status: "sent", error: null };
29363
+ }
29364
+ return { status: "unconfirmed", error: parsed.error.message };
29365
+ } catch (error) {
29366
+ return {
29367
+ status: classifyFailure(error),
29368
+ error: error instanceof Error ? error.message : String(error)
29369
+ };
29370
+ }
29371
+ }
29372
+ __name(trySendInvitationEmail, "trySendInvitationEmail");
29373
+
29374
+ // src/commands/invite/create.ts
29375
+ var EMAIL_SENT_LABEL = {
29376
+ sent: "yes",
29377
+ failed: "no",
29378
+ unconfirmed: "unconfirmed"
29379
+ };
29380
+ function assertEmailDelivered(emailRequested, outcome) {
29381
+ if (!emailRequested || outcome.status === "sent") {
29382
+ return;
29383
+ }
29384
+ throw new CliError(
29385
+ outcome.status === "failed" ? `The invitation was created but --send-email failed: ${outcome.error}` : `The invitation was created but --send-email could not be confirmed: ${outcome.error}`
29386
+ );
29387
+ }
29388
+ __name(assertEmailDelivered, "assertEmailDelivered");
29389
+ function registerInviteCreate(invite) {
29390
+ invite.command("create").description("Invite one person to a team").requiredOption("--email <email>", "email address of the person to invite").option(
29391
+ "--role <role>",
29392
+ `team role to grant (default ${DEFAULT_TEAM_ROLE}, or ${TEAM_ROLE.CLARITY_MEMBER} with --process)`
29393
+ ).option(
29394
+ "--process <id>",
29395
+ `invite them to this Clarity process instead of the whole team (defaults --role to ${TEAM_ROLE.CLARITY_MEMBER}, the only role a process invitation accepts)`
29396
+ ).option(
29397
+ "--send-email",
29398
+ "also email the invitation to the recipient. Without it the invitation is created but nobody is notified"
29399
+ ).option(
29400
+ "--team <id>",
29401
+ "team ID (defaults to the team scoped to your credentials)"
29402
+ ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function createAction(options) {
29403
+ const email = trimRequired(options.email ?? "", "--email");
29404
+ const processId = options.process === void 0 ? void 0 : trimRequired(options.process, "--process");
29405
+ const defaultRole = processId === void 0 ? DEFAULT_TEAM_ROLE : TEAM_ROLE.CLARITY_MEMBER;
29406
+ const role = assertTeamRole(options.role ?? defaultRole);
29407
+ const config = await requireAuthenticatedConfig(this);
29408
+ const { apiKey, apiBaseUrl } = config;
29409
+ const teamId = await resolveRequiredTeamId(config, {
29410
+ override: options.team ?? getTeamFlag(this)
29411
+ });
29412
+ const body = { email, role };
29413
+ if (processId !== void 0) {
29414
+ body.processId = processId;
29415
+ }
29416
+ const raw = await httpRequest({
29417
+ method: "POST",
29418
+ path: buildTeamPath(teamId, "/invites"),
29419
+ apiKey,
29420
+ apiBaseUrl,
29421
+ body
29422
+ });
29423
+ const parsed = createTeamInvitationResponseSchema.safeParse(raw);
29424
+ if (!parsed.success) {
29425
+ if (options.json) {
29426
+ printJson(raw);
29427
+ return;
29428
+ }
29429
+ throw new CliError(
29430
+ `Unexpected response from the API: ${parsed.error.message}`
29431
+ );
29432
+ }
29433
+ const emailRequested = options.sendEmail === true;
29434
+ const emailOutcome = emailRequested ? await trySendInvitationEmail({
29435
+ apiKey,
29436
+ apiBaseUrl,
29437
+ teamId,
29438
+ inviteId: parsed.data.id
29439
+ }) : { status: "failed", error: null };
29440
+ if (options.json) {
29441
+ printJson(raw);
29442
+ assertEmailDelivered(emailRequested, emailOutcome);
29443
+ return;
29444
+ }
29445
+ console.log(green("Invitation created!"));
29446
+ console.log();
29447
+ console.log(
29448
+ renderKeyValue([
29449
+ { label: "Invitation ID", value: parsed.data.id },
29450
+ { label: "Email", value: parsed.data.email },
29451
+ { label: "Role", value: parsed.data.role },
29452
+ { label: "Team", value: parsed.data.team.name },
29453
+ { label: "Process", value: parsed.data.process?.name ?? "\u2014" },
29454
+ { label: "Status", value: parsed.data.status },
29455
+ { label: "Email sent", value: EMAIL_SENT_LABEL[emailOutcome.status] }
29456
+ ])
29457
+ );
29458
+ if (!emailRequested) {
29459
+ console.log();
29460
+ console.log(
29461
+ `Nobody has been notified yet. Send the email with: duvo invite resend ${parsed.data.id}`
29462
+ );
29463
+ return;
29464
+ }
29465
+ if (emailOutcome.status === "failed") {
29466
+ console.log();
29467
+ console.log(
29468
+ `The invitation exists but the email was rejected, so nobody was notified: ${emailOutcome.error}`
29469
+ );
29470
+ console.log(`Send it with: duvo invite resend ${parsed.data.id}`);
29471
+ }
29472
+ if (emailOutcome.status === "unconfirmed") {
29473
+ console.log();
29474
+ console.log(
29475
+ `The invitation exists but the email could not be confirmed: ${emailOutcome.error}`
29476
+ );
29477
+ console.log(
29478
+ `It may or may not have been delivered. Check with the recipient before running: duvo invite resend ${parsed.data.id}`
29479
+ );
29480
+ }
29481
+ assertEmailDelivered(emailRequested, emailOutcome);
29482
+ }, "createAction"));
29483
+ }
29484
+ __name(registerInviteCreate, "registerInviteCreate");
29485
+
29486
+ // src/commands/invite/delete.ts
29487
+ function registerInviteDelete(invite) {
29488
+ invite.command("delete <id>").alias("revoke").description(
29489
+ "Revoke a pending invitation so its link and email stop working"
29490
+ ).option(
29491
+ "--team <id>",
29492
+ "team ID (defaults to the team scoped to your credentials)"
29493
+ ).option("-y, --yes", "skip the confirmation prompt").option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function deleteAction(id, options) {
29494
+ const inviteId = trimRequired(id, "<id>");
29495
+ const config = await requireAuthenticatedConfig(this);
29496
+ const { apiKey, apiBaseUrl } = config;
29497
+ const teamId = await resolveRequiredTeamId(config, {
29498
+ override: options.team ?? getTeamFlag(this)
29499
+ });
29500
+ await confirmDestructive({
29501
+ message: `Revoke invitation "${inviteId}"?`,
29502
+ skip: options.yes === true
29503
+ });
29504
+ const raw = await httpRequest({
29505
+ method: "DELETE",
29506
+ path: buildTeamPath(teamId, `/invites/${encodeURIComponent(inviteId)}`),
29507
+ apiKey,
29508
+ apiBaseUrl
29509
+ });
29510
+ if (options.json) {
29511
+ printJson(raw);
29512
+ return;
29513
+ }
29514
+ const parsed = inviteSuccessResponseSchema.safeParse(raw);
29515
+ if (!parsed.success) {
29516
+ throw new CliError(
29517
+ `Unexpected response from the API: ${parsed.error.message}`
29518
+ );
29519
+ }
29520
+ console.log(green(`Invitation ${inviteId} revoked.`));
29521
+ }, "deleteAction"));
29522
+ }
29523
+ __name(registerInviteDelete, "registerInviteDelete");
29524
+
29525
+ // src/commands/invite/link.ts
29526
+ var LINK_PATH = "/team-invite-link";
29527
+ function registerGet(link) {
29528
+ link.command("get").description("Show the team's shareable invite link").option(
29529
+ "--team <id>",
29530
+ "team ID (defaults to the team scoped to your credentials)"
29531
+ ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function getAction(options) {
29532
+ const config = await requireAuthenticatedConfig(this);
29533
+ const { apiKey, apiBaseUrl } = config;
29534
+ const teamId = await resolveRequiredTeamId(config, {
29535
+ override: options.team ?? getTeamFlag(this)
29536
+ });
29537
+ const raw = await httpRequest({
29538
+ method: "GET",
29539
+ path: buildTeamPath(teamId, LINK_PATH),
29540
+ apiKey,
29541
+ apiBaseUrl
29542
+ });
29543
+ if (options.json) {
29544
+ printJson(raw);
29545
+ return;
29546
+ }
29547
+ const parsed = getTeamInviteLinkResponseSchema.safeParse(raw);
29548
+ if (!parsed.success) {
29549
+ throw new CliError(
29550
+ `Unexpected response from the API: ${parsed.error.message}`
29551
+ );
29552
+ }
29553
+ const { hasLink, link: inviteLink } = parsed.data;
29554
+ if (!hasLink || !inviteLink) {
29555
+ console.log(
29556
+ "No invite link yet. Create one with: duvo invite link create"
29557
+ );
29558
+ return;
29559
+ }
29560
+ console.log(
29561
+ renderKeyValue([
29562
+ { label: "Link ID", value: inviteLink.id },
29563
+ { label: "URL", value: inviteLink.url ?? "\u2014" },
29564
+ { label: "Created", value: inviteLink.createdAt },
29565
+ {
29566
+ label: "Created by",
29567
+ value: inviteLink.createdBy.name ?? inviteLink.createdBy.email
29568
+ }
29569
+ ])
29570
+ );
29571
+ }, "getAction"));
29572
+ }
29573
+ __name(registerGet, "registerGet");
29574
+ function registerCreate2(link) {
29575
+ link.command("create").description(
29576
+ "Create or regenerate the team's shareable invite link (regenerating invalidates the previous URL)"
29577
+ ).option(
29578
+ "--team <id>",
29579
+ "team ID (defaults to the team scoped to your credentials)"
29580
+ ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function createAction(options) {
29581
+ const config = await requireAuthenticatedConfig(this);
29582
+ const { apiKey, apiBaseUrl } = config;
29583
+ const teamId = await resolveRequiredTeamId(config, {
29584
+ override: options.team ?? getTeamFlag(this)
29585
+ });
29586
+ const raw = await httpRequest({
29587
+ method: "POST",
29588
+ path: buildTeamPath(teamId, LINK_PATH),
29589
+ apiKey,
29590
+ apiBaseUrl,
29591
+ body: {}
29592
+ });
29593
+ if (options.json) {
29594
+ printJson(raw);
29595
+ return;
29596
+ }
29597
+ const parsed = createTeamInviteLinkResponseSchema.safeParse(raw);
29598
+ if (!parsed.success) {
29599
+ throw new CliError(
29600
+ `Unexpected response from the API: ${parsed.error.message}`
29601
+ );
29602
+ }
29603
+ console.log(green("Invite link ready!"));
29604
+ console.log();
29605
+ console.log(
29606
+ renderKeyValue([
29607
+ { label: "Link ID", value: parsed.data.id },
29608
+ { label: "URL", value: parsed.data.url ?? "\u2014" },
29609
+ { label: "Created", value: parsed.data.createdAt }
29610
+ ])
29611
+ );
29612
+ console.log();
29613
+ console.log(
29614
+ "Anyone with this URL can join the team. Any previous link no longer works."
29615
+ );
29616
+ }, "createAction"));
29617
+ }
29618
+ __name(registerCreate2, "registerCreate");
29619
+ function registerDelete2(link) {
29620
+ link.command("delete").description("Delete the team's shareable invite link").option(
29621
+ "--team <id>",
29622
+ "team ID (defaults to the team scoped to your credentials)"
29623
+ ).option("-y, --yes", "skip the confirmation prompt").option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function deleteAction(options) {
29624
+ const config = await requireAuthenticatedConfig(this);
29625
+ const { apiKey, apiBaseUrl } = config;
29626
+ const teamId = await resolveRequiredTeamId(config, {
29627
+ override: options.team ?? getTeamFlag(this)
29628
+ });
29629
+ await confirmDestructive({
29630
+ message: `Delete the invite link for team "${teamId}"?`,
29631
+ skip: options.yes === true
29632
+ });
29633
+ const raw = await httpRequest({
29634
+ method: "DELETE",
29635
+ path: buildTeamPath(teamId, LINK_PATH),
29636
+ apiKey,
29637
+ apiBaseUrl
29638
+ });
29639
+ if (options.json) {
29640
+ printJson(raw);
29641
+ return;
29642
+ }
29643
+ console.log(green("Invite link deleted."));
29644
+ }, "deleteAction"));
29645
+ }
29646
+ __name(registerDelete2, "registerDelete");
29647
+ function registerInviteLink(invite) {
29648
+ const link = invite.command("link").description("Manage the team's shareable invite link");
29649
+ registerGet(link);
29650
+ registerCreate2(link);
29651
+ registerDelete2(link);
29652
+ }
29653
+ __name(registerInviteLink, "registerInviteLink");
29654
+
29655
+ // src/commands/invite/list.ts
29656
+ var TABLE_COLUMNS27 = [
29657
+ { header: "ID", cell: /* @__PURE__ */ __name((row) => row.id, "cell") },
29658
+ { header: "EMAIL", cell: /* @__PURE__ */ __name((row) => row.email, "cell") },
29659
+ { header: "ROLE", cell: /* @__PURE__ */ __name((row) => row.role, "cell") },
29660
+ { header: "STATUS", cell: /* @__PURE__ */ __name((row) => row.status, "cell") },
29661
+ {
29662
+ header: "PROCESS",
29663
+ cell: /* @__PURE__ */ __name((row) => row.process_id ?? "", "cell")
29664
+ },
29665
+ { header: "CREATED", cell: /* @__PURE__ */ __name((row) => row.created_at, "cell") }
29666
+ ];
29667
+ function registerInviteList(invite) {
29668
+ invite.command("list").description("List a team's pending invitations").option(
29669
+ "--process <id>",
29670
+ "list the pending invitations for this Clarity process instead of the team's own"
29671
+ ).option(
29672
+ "--team <id>",
29673
+ "team ID (defaults to the team scoped to your credentials)"
29674
+ ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function listAction(options) {
29675
+ const config = await requireAuthenticatedConfig(this);
29676
+ const { apiKey, apiBaseUrl } = config;
29677
+ const teamId = await resolveRequiredTeamId(config, {
29678
+ override: options.team ?? getTeamFlag(this)
29679
+ });
29680
+ const searchParams = new URLSearchParams();
29681
+ if (options.process !== void 0) {
29682
+ searchParams.append(
29683
+ "processId",
29684
+ trimRequired(options.process, "--process")
29685
+ );
29686
+ }
29687
+ const raw = await httpRequest({
29688
+ method: "GET",
29689
+ path: buildTeamPath(teamId, "/invites"),
29690
+ apiKey,
29691
+ apiBaseUrl,
29692
+ searchParams
29693
+ });
29694
+ if (options.json) {
29695
+ printJson(raw);
29696
+ return;
29697
+ }
29698
+ const parsed = listTeamInvitesResponseSchema.safeParse(raw);
29699
+ if (!parsed.success) {
29700
+ throw new CliError(
29701
+ `Unexpected response from the API: ${parsed.error.message}`
29702
+ );
29703
+ }
29704
+ const { invitations } = parsed.data;
29705
+ if (invitations.length === 0) {
29706
+ console.log("No pending invitations found.");
29707
+ return;
29708
+ }
29709
+ console.log(renderTable(TABLE_COLUMNS27, invitations));
29710
+ console.log(`Showing ${invitations.length}`);
29711
+ }, "listAction"));
29712
+ }
29713
+ __name(registerInviteList, "registerInviteList");
29714
+
29715
+ // src/commands/invite/org-member.ts
29716
+ var ORG_ROLES2 = Object.values(ORG_ROLE);
29717
+ var DEFAULT_ROLE = ORG_ROLE.MEMBER;
29718
+ function registerInviteOrgMember(invite) {
29719
+ invite.command("org-member <org-id>").description(
29720
+ "Invite a person to an organization, optionally onto one of its teams"
29721
+ ).requiredOption("--email <email>", "email address of the person to invite").option(
29722
+ "--role <role>",
29723
+ `organization role to grant: ${ORG_ROLES2.join(", ")} (default ${DEFAULT_ROLE})`,
29724
+ DEFAULT_ROLE
29725
+ ).option("--team-id <id>", "assign the invitee to this team in the org").option(
29726
+ "--send-email",
29727
+ "also email the invitation to the recipient. Without it the invitation is created but nobody is notified"
29728
+ ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function inviteOrgMemberAction(orgId, options) {
29729
+ const email = options.email?.trim();
29730
+ if (email === void 0 || email.length === 0) {
29731
+ throw new CliError("--email must not be empty");
29732
+ }
29733
+ const role = options.role ?? DEFAULT_ROLE;
29734
+ if (!ORG_ROLES2.includes(role)) {
29735
+ throw new CliError(
29736
+ `Invalid --role "${role}"; expected one of: ${ORG_ROLES2.join(", ")}`
29737
+ );
29738
+ }
29739
+ const { apiKey, apiBaseUrl } = await requireAuthenticatedConfig(this);
29740
+ const body = { email, role };
29741
+ if (options.teamId !== void 0) {
29742
+ const teamId = options.teamId.trim();
29743
+ if (teamId.length === 0) {
29744
+ throw new CliError("--team-id must not be empty");
29745
+ }
29746
+ body.teamId = teamId;
29747
+ }
29748
+ if (options.sendEmail === true) {
29749
+ body.sendEmail = true;
29750
+ }
29751
+ const raw = await httpRequest({
29752
+ method: "POST",
29753
+ path: `/v2/organizations/${encodeURIComponent(orgId)}/members`,
29754
+ apiKey,
29755
+ apiBaseUrl,
29756
+ body
29757
+ });
29758
+ const parsed = inviteOrgMemberResponseSchema.safeParse(raw);
29759
+ if (options.json) {
29760
+ printJson(raw);
29761
+ if (options.sendEmail === true && parsed.success && !parsed.data.emailSent) {
29762
+ throw new CliError(
29763
+ `The invitation was created (${parsed.data.invitationId}) but --send-email did not deliver it.`
29764
+ );
29765
+ }
29766
+ return;
29767
+ }
29768
+ if (!parsed.success) {
29769
+ throw new CliError(
29770
+ `Unexpected response from POST /v2/organizations/:orgId/members: ${parsed.error.message}`
29771
+ );
29772
+ }
29773
+ console.log(green("Invitation created!"));
29774
+ console.log();
29775
+ console.log(
29776
+ renderKeyValue([
29777
+ { label: "Invitation ID", value: parsed.data.invitationId },
29778
+ { label: "Email", value: email },
29779
+ { label: "Role", value: role },
29780
+ { label: "Team", value: body.teamId ?? "\u2014" },
29781
+ { label: "Email sent", value: parsed.data.emailSent ? "yes" : "no" }
29782
+ ])
29783
+ );
29784
+ if (options.sendEmail === true && !parsed.data.emailSent) {
29785
+ console.log();
29786
+ throw new CliError(
29787
+ `The invitation was created (${parsed.data.invitationId}) but --send-email did not deliver it. Send it from the organization members page.`
29788
+ );
29789
+ }
29790
+ }, "inviteOrgMemberAction"));
29791
+ }
29792
+ __name(registerInviteOrgMember, "registerInviteOrgMember");
29793
+
29794
+ // src/commands/invite/resend.ts
29795
+ function registerInviteResend(invite) {
29796
+ invite.command("resend <id>").description("Email an invitation to its recipient").option(
29797
+ "--team <id>",
29798
+ "team ID (defaults to the team scoped to your credentials)"
29799
+ ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function resendAction(id, options) {
29800
+ const inviteId = trimRequired(id, "<id>");
29801
+ const config = await requireAuthenticatedConfig(this);
29802
+ const { apiKey, apiBaseUrl } = config;
29803
+ const teamId = await resolveRequiredTeamId(config, {
29804
+ override: options.team ?? getTeamFlag(this)
29805
+ });
29806
+ const raw = await httpRequest({
29807
+ method: "POST",
29808
+ path: buildTeamPath(
29809
+ teamId,
29810
+ `/invites/${encodeURIComponent(inviteId)}/send-email`
29811
+ ),
29812
+ apiKey,
29813
+ apiBaseUrl,
29814
+ body: {}
29815
+ });
29816
+ if (options.json) {
29817
+ printJson(raw);
29818
+ return;
29819
+ }
29820
+ const parsed = inviteSuccessResponseSchema.safeParse(raw);
29821
+ if (!parsed.success) {
29822
+ throw new CliError(
29823
+ `Unexpected response from the API: ${parsed.error.message}`
29824
+ );
29825
+ }
29826
+ console.log(green(`Invitation ${inviteId} emailed.`));
29827
+ }, "resendAction"));
29828
+ }
29829
+ __name(registerInviteResend, "registerInviteResend");
29830
+
29831
+ // src/commands/invite/update.ts
29832
+ function registerInviteUpdate(invite) {
29833
+ invite.command("update <id>").description("Change the role on a pending invitation").requiredOption("--role <role>", "new team role for the invitation").option(
29834
+ "--team <id>",
29835
+ "team ID (defaults to the team scoped to your credentials)"
29836
+ ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function updateAction(id, options) {
29837
+ const inviteId = trimRequired(id, "<id>");
29838
+ const role = assertTeamRole(trimRequired(options.role ?? "", "--role"));
29839
+ const config = await requireAuthenticatedConfig(this);
29840
+ const { apiKey, apiBaseUrl } = config;
29841
+ const teamId = await resolveRequiredTeamId(config, {
29842
+ override: options.team ?? getTeamFlag(this)
29843
+ });
29844
+ const raw = await httpRequest({
29845
+ method: "PATCH",
29846
+ path: buildTeamPath(teamId, `/invites/${encodeURIComponent(inviteId)}`),
29847
+ apiKey,
29848
+ apiBaseUrl,
29849
+ body: { role }
29850
+ });
29851
+ if (options.json) {
29852
+ printJson(raw);
29853
+ return;
29854
+ }
29855
+ const parsed = updateTeamInviteResponseSchema.safeParse(raw);
29856
+ if (!parsed.success) {
29857
+ throw new CliError(
29858
+ `Unexpected response from the API: ${parsed.error.message}`
29859
+ );
29860
+ }
29861
+ console.log(green("Invitation updated!"));
29862
+ console.log();
29863
+ console.log(
29864
+ renderKeyValue([
29865
+ { label: "Invitation ID", value: parsed.data.id },
29866
+ { label: "Role", value: parsed.data.role }
29867
+ ])
29868
+ );
29869
+ }, "updateAction"));
29870
+ }
29871
+ __name(registerInviteUpdate, "registerInviteUpdate");
29872
+
29873
+ // src/commands/invite/index.ts
29874
+ function registerInvite(program) {
29875
+ const invite = program.command("invite").description("Invite people to a team or organization");
29876
+ registerInviteList(invite);
29877
+ registerInviteCreate(invite);
29878
+ registerInviteBulk(invite);
29879
+ registerInviteUpdate(invite);
29880
+ registerInviteResend(invite);
29881
+ registerInviteDelete(invite);
29882
+ registerInviteOrgMember(invite);
29883
+ registerInviteLink(invite);
29884
+ }
29885
+ __name(registerInvite, "registerInvite");
29886
+
29887
+ // src/commands/login.ts
29888
+ import { isCancel as isCancel4, log, password, spinner, text as text2 } from "@clack/prompts";
29889
+
29890
+ // src/oauth/auth0-config.ts
29891
+ var BAKED_DOMAIN = "login.duvo.ai" ? "login.duvo.ai" : "login.dev.duvo.ai";
29892
+ var BAKED_CLIENT_ID = "MpK8jktbMHPlrCxmSPeRbkiSNrRTUjeT" ? "MpK8jktbMHPlrCxmSPeRbkiSNrRTUjeT" : "mq4MhUUHRNKrzkqr1MnAJdcvv5MNfuBU";
29893
+ var BAKED_AUDIENCE = "https://api.duvo.ai" ? "https://api.duvo.ai" : "https://api.dev.duvo.ai";
29894
+ function resolveAuth0Config() {
29895
+ return {
29896
+ domain: BAKED_DOMAIN,
29897
+ clientId: BAKED_CLIENT_ID,
29898
+ audience: BAKED_AUDIENCE,
29899
+ issuer: `https://${BAKED_DOMAIN}/`
29900
+ };
29901
+ }
29902
+ __name(resolveAuth0Config, "resolveAuth0Config");
29903
+
29904
+ // src/oauth/loopback.ts
29905
+ import { createServer } from "node:http";
29906
+ var LOOPBACK_PORTS = [49152, 49153, 49154, 49155, 49156];
29907
+ var HOST = "127.0.0.1";
29908
+ async function startLoopbackServer() {
29909
+ const result = await tryBindNext([...LOOPBACK_PORTS]);
29910
+ if (!result) {
29911
+ throw new CliError(
29912
+ `Could not bind to a local port \u2014 tried ${LOOPBACK_PORTS.join(", ")}.`
29913
+ );
29914
+ }
29915
+ const redirectUri = `http://${HOST}:${result.port}/callback`;
29916
+ return wrapServer(result.server, redirectUri);
29917
+ }
29918
+ __name(startLoopbackServer, "startLoopbackServer");
29919
+ async function tryBindNext(ports) {
29920
+ if (ports.length === 0) {
29921
+ return null;
29922
+ }
29923
+ const [port, ...rest] = ports;
29924
+ const server = await tryBind(port);
29925
+ if (server) {
29926
+ return { server, port };
29927
+ }
29928
+ return tryBindNext(rest);
29929
+ }
29930
+ __name(tryBindNext, "tryBindNext");
29931
+ async function tryBind(port) {
29932
+ return new Promise((resolve) => {
29933
+ const server = createServer();
29934
+ const onError = /* @__PURE__ */ __name((err) => {
29935
+ if (err.code === "EADDRINUSE" || err.code === "EACCES") {
29936
+ resolve(null);
29937
+ return;
29938
+ }
29939
+ server.close();
29940
+ resolve(null);
29941
+ }, "onError");
29942
+ server.once("error", onError);
29943
+ server.listen(port, HOST, () => {
29944
+ server.removeListener("error", onError);
29945
+ const address = server.address();
29946
+ if (!address || address.port !== port) {
29947
+ server.close();
29948
+ resolve(null);
29949
+ return;
29950
+ }
29951
+ resolve(server);
29952
+ });
29953
+ });
29954
+ }
29955
+ __name(tryBind, "tryBind");
29956
+ function wrapServer(server, redirectUri) {
29957
+ let resolved = false;
29958
+ let resolver = null;
29959
+ let rejecter = null;
29960
+ server.on("request", (req, res) => {
29961
+ if (!req.url) {
29962
+ res.statusCode = 400;
29963
+ res.end("Bad Request");
29964
+ return;
29965
+ }
29966
+ const url = new URL(req.url, redirectUri);
29967
+ if (url.pathname !== "/callback") {
29968
+ res.statusCode = 404;
29969
+ res.end("Not Found");
29970
+ return;
29971
+ }
29972
+ const error = url.searchParams.get("error");
29973
+ const code = url.searchParams.get("code");
29974
+ const state = url.searchParams.get("state");
29975
+ if (error) {
29976
+ const description = url.searchParams.get("error_description") ?? error;
29977
+ res.statusCode = 400;
29978
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
29979
+ res.end(renderHtml(`Authorization failed: ${description}`));
29980
+ if (!resolved && rejecter) {
29981
+ resolved = true;
29982
+ rejecter(new CliError(`Authorization denied: ${description}`));
29983
+ }
29984
+ return;
29985
+ }
29986
+ if (!code || !state) {
29987
+ res.statusCode = 400;
29988
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
29989
+ res.end(renderHtml("Missing code or state."));
29990
+ if (!resolved && rejecter) {
29991
+ resolved = true;
29992
+ rejecter(new CliError("Callback missing code or state."));
29993
+ }
29994
+ return;
29995
+ }
29996
+ res.statusCode = 200;
29997
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
29998
+ res.end(renderHtml("You are now signed in. You can close this tab."));
29999
+ if (!resolved && resolver) {
30000
+ resolved = true;
30001
+ resolver({ code, state });
30002
+ }
30003
+ });
30004
+ return {
30005
+ redirectUri,
30006
+ waitForCallback(timeoutMs) {
30007
+ return new Promise((resolve, reject) => {
30008
+ resolver = resolve;
30009
+ rejecter = reject;
30010
+ const timer = setTimeout(() => {
30011
+ if (!resolved) {
30012
+ resolved = true;
30013
+ reject(new CliError("Authorization timed out."));
30014
+ }
30015
+ }, timeoutMs);
30016
+ timer.unref();
30017
+ });
30018
+ },
30019
+ async close() {
30020
+ await new Promise((resolve) => server.close(() => resolve()));
30021
+ }
30022
+ };
30023
+ }
30024
+ __name(wrapServer, "wrapServer");
30025
+ var HTML_ESCAPES = {
30026
+ "&": "&amp;",
30027
+ "<": "&lt;",
30028
+ ">": "&gt;"
30029
+ };
30030
+ function renderHtml(message) {
30031
+ const safe = message.replace(/[&<>]/g, (c) => HTML_ESCAPES[c] ?? c);
30032
+ return `<!doctype html>
30033
+ <html lang="en">
30034
+ <head>
30035
+ <meta charset="utf-8" />
30036
+ <title>Duvo CLI</title>
30037
+ <style>
30038
+ body { font-family: system-ui, sans-serif; padding: 4rem; text-align: center; }
30039
+ .card { display: inline-block; padding: 2rem 3rem; border-radius: 12px; background: #f6f8fa; }
30040
+ </style>
30041
+ </head>
30042
+ <body>
30043
+ <div class="card">
30044
+ <h2>Duvo CLI</h2>
30045
+ <p>${safe}</p>
30046
+ </div>
30047
+ </body>
30048
+ </html>`;
30049
+ }
30050
+ __name(renderHtml, "renderHtml");
30051
+
30052
+ // src/oauth/open-browser.ts
30053
+ import { spawn } from "node:child_process";
30054
+ import { platform } from "node:os";
30055
+ var BASE_OPTIONS = {
30056
+ detached: true,
30057
+ stdio: "ignore",
30058
+ shell: false
30059
+ };
30060
+ function spawnPlanFor(url) {
30061
+ const os = platform();
30062
+ if (os === "darwin") {
30063
+ return { command: "open", args: [url], options: BASE_OPTIONS };
30064
+ }
30065
+ if (os === "win32") {
30066
+ return {
30067
+ command: "cmd.exe",
29280
30068
  args: ["/c", "start", '""', `"${url}"`],
29281
30069
  options: { ...BASE_OPTIONS, windowsVerbatimArguments: true }
29282
30070
  };
@@ -29789,7 +30577,7 @@ __name(parseNotificationTypeOption, "parseNotificationTypeOption");
29789
30577
 
29790
30578
  // src/commands/notifications/feed.ts
29791
30579
  var MIN_LIMIT11 = 1;
29792
- var TABLE_COLUMNS27 = [
30580
+ var TABLE_COLUMNS28 = [
29793
30581
  { header: "KIND", cell: /* @__PURE__ */ __name((row) => row.kind, "cell") },
29794
30582
  {
29795
30583
  header: "ID",
@@ -29876,7 +30664,7 @@ function registerNotificationsFeed(notifications) {
29876
30664
  console.log("No feed items found.");
29877
30665
  return;
29878
30666
  }
29879
- console.log(renderTable(TABLE_COLUMNS27, items));
30667
+ console.log(renderTable(TABLE_COLUMNS28, items));
29880
30668
  console.log(`Showing ${items.length}`);
29881
30669
  if (nextCursor) {
29882
30670
  console.log(
@@ -29983,7 +30771,7 @@ __name(registerNotificationsGet, "registerNotificationsGet");
29983
30771
 
29984
30772
  // src/commands/notifications/list.ts
29985
30773
  var MIN_LIMIT12 = 1;
29986
- var TABLE_COLUMNS28 = [
30774
+ var TABLE_COLUMNS29 = [
29987
30775
  { header: "ID", cell: /* @__PURE__ */ __name((row) => row.id, "cell") },
29988
30776
  { header: "TYPE", cell: /* @__PURE__ */ __name((row) => row.type, "cell") },
29989
30777
  { header: "SEVERITY", cell: /* @__PURE__ */ __name((row) => row.severity, "cell") },
@@ -30117,7 +30905,7 @@ function registerNotificationsList(notifications) {
30117
30905
  console.log("No notifications found.");
30118
30906
  return;
30119
30907
  }
30120
- console.log(renderTable(TABLE_COLUMNS28, notifications2));
30908
+ console.log(renderTable(TABLE_COLUMNS29, notifications2));
30121
30909
  console.log(`Showing ${notifications2.length}`);
30122
30910
  if (nextCursor) {
30123
30911
  console.log(
@@ -30472,7 +31260,7 @@ function parseHeaders(raw) {
30472
31260
  return result;
30473
31261
  }
30474
31262
  __name(parseHeaders, "parseHeaders");
30475
- var TABLE_COLUMNS29 = [
31263
+ var TABLE_COLUMNS30 = [
30476
31264
  { header: "NAME", cell: /* @__PURE__ */ __name((row) => row.name, "cell") },
30477
31265
  { header: "DESCRIPTION", cell: /* @__PURE__ */ __name((row) => row.description, "cell") }
30478
31266
  ];
@@ -30530,7 +31318,7 @@ function registerOauthMcpProbe(mcp) {
30530
31318
  console.log("No tools advertised by this MCP server.");
30531
31319
  return;
30532
31320
  }
30533
- console.log(renderTable(TABLE_COLUMNS29, rows));
31321
+ console.log(renderTable(TABLE_COLUMNS30, rows));
30534
31322
  console.log(`Showing ${rows.length}`);
30535
31323
  }, "probeMcpAction"));
30536
31324
  }
@@ -30621,7 +31409,7 @@ function registerOauth(program) {
30621
31409
  __name(registerOauth, "registerOauth");
30622
31410
 
30623
31411
  // src/commands/plugins/list.ts
30624
- var TABLE_COLUMNS30 = [
31412
+ var TABLE_COLUMNS31 = [
30625
31413
  { header: "NAME", cell: /* @__PURE__ */ __name((row) => row.name, "cell") },
30626
31414
  { header: "TYPE", cell: /* @__PURE__ */ __name((row) => row.type, "cell") },
30627
31415
  {
@@ -30655,7 +31443,7 @@ function registerPluginsList(plugins) {
30655
31443
  console.log("No plugins found.");
30656
31444
  return;
30657
31445
  }
30658
- console.log(renderTable(TABLE_COLUMNS30, parsed.data.plugins));
31446
+ console.log(renderTable(TABLE_COLUMNS31, parsed.data.plugins));
30659
31447
  console.log(`Showing ${parsed.data.plugins.length}`);
30660
31448
  }, "listAction"));
30661
31449
  }
@@ -31115,7 +31903,7 @@ function registerPulseAttachmentUrl(pulse) {
31115
31903
  __name(registerPulseAttachmentUrl, "registerPulseAttachmentUrl");
31116
31904
 
31117
31905
  // src/commands/pulse/connections.ts
31118
- var TABLE_COLUMNS31 = [
31906
+ var TABLE_COLUMNS32 = [
31119
31907
  {
31120
31908
  header: "CONNECTION ID",
31121
31909
  cell: /* @__PURE__ */ __name((row) => row.connection_id, "cell")
@@ -31147,7 +31935,7 @@ function registerList4(connections) {
31147
31935
  console.log("No connections attached.");
31148
31936
  return;
31149
31937
  }
31150
- console.log(renderTable(TABLE_COLUMNS31, parsed.data.connections));
31938
+ console.log(renderTable(TABLE_COLUMNS32, parsed.data.connections));
31151
31939
  }, "listAction"));
31152
31940
  }
31153
31941
  __name(registerList4, "registerList");
@@ -31439,7 +32227,7 @@ __name(registerPulseHtml, "registerPulseHtml");
31439
32227
  var DEFAULT_LIMIT11 = 20;
31440
32228
  var MIN_LIMIT13 = 1;
31441
32229
  var MAX_LIMIT11 = 100;
31442
- var TABLE_COLUMNS32 = [
32230
+ var TABLE_COLUMNS33 = [
31443
32231
  { header: "ID", cell: /* @__PURE__ */ __name((row) => row.id, "cell") },
31444
32232
  {
31445
32233
  header: "TITLE",
@@ -31501,7 +32289,7 @@ function registerPulseList(pulse) {
31501
32289
  console.log("No Pulse dashboards found.");
31502
32290
  return;
31503
32291
  }
31504
- console.log(renderTable(TABLE_COLUMNS32, response.artifacts));
32292
+ console.log(renderTable(TABLE_COLUMNS33, response.artifacts));
31505
32293
  console.log(
31506
32294
  `Showing ${response.artifacts.length} of ${response.total} \xB7 offset ${response.offset}`
31507
32295
  );
@@ -31513,7 +32301,7 @@ __name(registerPulseList, "registerPulseList");
31513
32301
  var DEFAULT_LIMIT12 = 100;
31514
32302
  var MIN_LIMIT14 = 1;
31515
32303
  var MAX_LIMIT12 = 500;
31516
- var TABLE_COLUMNS33 = [
32304
+ var TABLE_COLUMNS34 = [
31517
32305
  { header: "ROLE", cell: /* @__PURE__ */ __name((row) => row.role, "cell") },
31518
32306
  {
31519
32307
  header: "CONTENT",
@@ -31561,7 +32349,7 @@ function registerPulseMessages(pulse) {
31561
32349
  console.log("No messages yet.");
31562
32350
  return;
31563
32351
  }
31564
- console.log(renderTable(TABLE_COLUMNS33, data));
32352
+ console.log(renderTable(TABLE_COLUMNS34, data));
31565
32353
  console.log(`Showing ${data.length} of ${total}`);
31566
32354
  if (hasMore) {
31567
32355
  console.log(
@@ -32114,7 +32902,7 @@ function registerPulse(program) {
32114
32902
  __name(registerPulse, "registerPulse");
32115
32903
 
32116
32904
  // src/commands/queue-labels/index.ts
32117
- var TABLE_COLUMNS34 = [
32905
+ var TABLE_COLUMNS35 = [
32118
32906
  { header: "ID", cell: /* @__PURE__ */ __name((row) => row.id, "cell") },
32119
32907
  { header: "KEY", cell: /* @__PURE__ */ __name((row) => row.key, "cell") },
32120
32908
  { header: "VALUE", cell: /* @__PURE__ */ __name((row) => row.value, "cell") },
@@ -32130,9 +32918,9 @@ var TABLE_COLUMNS34 = [
32130
32918
  function registerQueueLabels(program) {
32131
32919
  const labels = program.command("queue-labels").description("Manage label vocabularies on a queue");
32132
32920
  registerList5(labels);
32133
- registerCreate2(labels);
32921
+ registerCreate3(labels);
32134
32922
  registerUpdate2(labels);
32135
- registerDelete2(labels);
32923
+ registerDelete3(labels);
32136
32924
  }
32137
32925
  __name(registerQueueLabels, "registerQueueLabels");
32138
32926
  function registerList5(labels) {
@@ -32168,12 +32956,12 @@ function registerList5(labels) {
32168
32956
  console.log("No labels defined on this queue.");
32169
32957
  return;
32170
32958
  }
32171
- console.log(renderTable(TABLE_COLUMNS34, parsed.data.labels));
32959
+ console.log(renderTable(TABLE_COLUMNS35, parsed.data.labels));
32172
32960
  console.log(`Showing ${parsed.data.labels.length}`);
32173
32961
  }, "listAction"));
32174
32962
  }
32175
32963
  __name(registerList5, "registerList");
32176
- function registerCreate2(labels) {
32964
+ function registerCreate3(labels) {
32177
32965
  labels.command("create").description("Create a label on a queue without assigning it to a case").requiredOption("--queue <id>", "ID of the queue").option("--key <text>", "label key (omit for tag-only labels)").requiredOption("--value <text>", "label value (required, non-empty)").option("--color-hue <n>", "color hue 0-360 (auto-derived if omitted)").option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function createAction(options) {
32178
32966
  if (options.value.trim().length === 0) {
32179
32967
  throw new CliError("--value must not be empty");
@@ -32217,7 +33005,7 @@ function registerCreate2(labels) {
32217
33005
  );
32218
33006
  }, "createAction"));
32219
33007
  }
32220
- __name(registerCreate2, "registerCreate");
33008
+ __name(registerCreate3, "registerCreate");
32221
33009
  function registerUpdate2(labels) {
32222
33010
  labels.command("update <label-id>").description(
32223
33011
  "Rename a label or change its color (affects every case it's assigned to)"
@@ -32280,7 +33068,7 @@ function registerUpdate2(labels) {
32280
33068
  }, "updateAction"));
32281
33069
  }
32282
33070
  __name(registerUpdate2, "registerUpdate");
32283
- function registerDelete2(labels) {
33071
+ function registerDelete3(labels) {
32284
33072
  labels.command("delete <label-id>").description(
32285
33073
  "Delete a label from a queue (cascade-removes from every case it was assigned to)"
32286
33074
  ).requiredOption("--queue <id>", "ID of the queue the label belongs to").option("-y, --yes", "skip confirmation prompt").option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function deleteAction(labelId, options) {
@@ -32311,7 +33099,7 @@ function registerDelete2(labels) {
32311
33099
  console.log(green("Label deleted!"));
32312
33100
  }, "deleteAction"));
32313
33101
  }
32314
- __name(registerDelete2, "registerDelete");
33102
+ __name(registerDelete3, "registerDelete");
32315
33103
  var LABEL_PAGE_SIZE = 1e3;
32316
33104
  async function fetchCurrentLabelValue(queueId, labelId, apiKey, apiBaseUrl) {
32317
33105
  for (let offset = 0; ; offset += LABEL_PAGE_SIZE) {
@@ -32922,7 +33710,7 @@ __name(registerQueuesLinkAgent, "registerQueuesLinkAgent");
32922
33710
  var DEFAULT_LIMIT13 = 20;
32923
33711
  var MIN_LIMIT15 = 1;
32924
33712
  var MAX_LIMIT13 = 100;
32925
- var TABLE_COLUMNS35 = [
33713
+ var TABLE_COLUMNS36 = [
32926
33714
  { header: "ID", cell: /* @__PURE__ */ __name((row) => row.id, "cell") },
32927
33715
  { header: "NAME", cell: /* @__PURE__ */ __name((row) => row.name, "cell") },
32928
33716
  {
@@ -32970,7 +33758,7 @@ function registerQueuesList(queues) {
32970
33758
  console.log("No queues found.");
32971
33759
  return;
32972
33760
  }
32973
- console.log(renderTable(TABLE_COLUMNS35, response.queues));
33761
+ console.log(renderTable(TABLE_COLUMNS36, response.queues));
32974
33762
  const resolvedOffset = response.offset ?? offset;
32975
33763
  const total = response.total ?? null;
32976
33764
  const summary = total === null ? `Showing ${response.queues.length} \xB7 offset ${resolvedOffset}` : `Showing ${response.queues.length} of ${total} \xB7 offset ${resolvedOffset}`;
@@ -33228,7 +34016,7 @@ function registerRevisionLoginsDetach(revisionLogins) {
33228
34016
  __name(registerRevisionLoginsDetach, "registerRevisionLoginsDetach");
33229
34017
 
33230
34018
  // src/commands/revision-logins/list.ts
33231
- var TABLE_COLUMNS36 = [
34019
+ var TABLE_COLUMNS37 = [
33232
34020
  { header: "ID", cell: /* @__PURE__ */ __name((row) => row.id, "cell") },
33233
34021
  { header: "DOMAIN", cell: /* @__PURE__ */ __name((row) => row.domain, "cell") },
33234
34022
  {
@@ -33264,7 +34052,7 @@ function registerRevisionLoginsList(revisionLogins) {
33264
34052
  console.log("No logins attached to this revision.");
33265
34053
  return;
33266
34054
  }
33267
- console.log(renderTable(TABLE_COLUMNS36, rows));
34055
+ console.log(renderTable(TABLE_COLUMNS37, rows));
33268
34056
  console.log(`Showing ${rows.length}`);
33269
34057
  }, "listAction"));
33270
34058
  }
@@ -33337,7 +34125,7 @@ function registerRevisionSecretsDetach(revisionSecrets) {
33337
34125
  __name(registerRevisionSecretsDetach, "registerRevisionSecretsDetach");
33338
34126
 
33339
34127
  // src/commands/revision-secrets/list.ts
33340
- var TABLE_COLUMNS37 = [
34128
+ var TABLE_COLUMNS38 = [
33341
34129
  { header: "ID", cell: /* @__PURE__ */ __name((row) => row.id, "cell") },
33342
34130
  { header: "NAME", cell: /* @__PURE__ */ __name((row) => row.name, "cell") },
33343
34131
  {
@@ -33375,7 +34163,7 @@ function registerRevisionSecretsList(revisionSecrets) {
33375
34163
  console.log("No secrets attached to this revision.");
33376
34164
  return;
33377
34165
  }
33378
- console.log(renderTable(TABLE_COLUMNS37, rows));
34166
+ console.log(renderTable(TABLE_COLUMNS38, rows));
33379
34167
  console.log(`Showing ${rows.length}`);
33380
34168
  }, "listAction"));
33381
34169
  }
@@ -33391,91 +34179,91 @@ function registerRevisionSecrets(program) {
33391
34179
  __name(registerRevisionSecrets, "registerRevisionSecrets");
33392
34180
 
33393
34181
  // src/api/run-schemas.ts
33394
- import { z as z127 } from "zod";
33395
- var publicRunSchema = z127.object({
33396
- id: z127.string(),
33397
- agent_id: z127.string(),
33398
- build_id: z127.string(),
33399
- status: z127.string(),
33400
- source: z127.string().nullish(),
33401
- sandbox_id: z127.string().nullish(),
33402
- started_at: z127.string().nullish(),
33403
- completed_at: z127.string().nullish(),
33404
- created_at: z127.string(),
33405
- updated_at: z127.string().nullish(),
33406
- human_in_the_loop_enabled: z127.boolean().nullish()
33407
- });
33408
- var startRunResponseSchema = z127.object({
34182
+ import { z as z128 } from "zod";
34183
+ var publicRunSchema = z128.object({
34184
+ id: z128.string(),
34185
+ agent_id: z128.string(),
34186
+ build_id: z128.string(),
34187
+ status: z128.string(),
34188
+ source: z128.string().nullish(),
34189
+ sandbox_id: z128.string().nullish(),
34190
+ started_at: z128.string().nullish(),
34191
+ completed_at: z128.string().nullish(),
34192
+ created_at: z128.string(),
34193
+ updated_at: z128.string().nullish(),
34194
+ human_in_the_loop_enabled: z128.boolean().nullish()
34195
+ });
34196
+ var startRunResponseSchema = z128.object({
33409
34197
  run: publicRunSchema
33410
34198
  });
33411
- var questionOptionSchema = z127.object({
33412
- label: z127.string(),
33413
- description: z127.string().nullish()
33414
- });
33415
- var questionSchema = z127.object({
33416
- question: z127.string(),
33417
- header: z127.string().nullish(),
33418
- options: z127.array(questionOptionSchema).nullish(),
33419
- multi_select: z127.boolean().nullish()
33420
- });
33421
- var pendingHumanRequestSchema = z127.object({
33422
- id: z127.string(),
33423
- title: z127.string(),
33424
- description: z127.string().nullish(),
33425
- created_at: z127.string(),
33426
- type: z127.string(),
33427
- questions: z127.array(questionSchema).nullish()
33428
- });
33429
- var getRunResponseSchema = z127.object({
34199
+ var questionOptionSchema = z128.object({
34200
+ label: z128.string(),
34201
+ description: z128.string().nullish()
34202
+ });
34203
+ var questionSchema = z128.object({
34204
+ question: z128.string(),
34205
+ header: z128.string().nullish(),
34206
+ options: z128.array(questionOptionSchema).nullish(),
34207
+ multi_select: z128.boolean().nullish()
34208
+ });
34209
+ var pendingHumanRequestSchema = z128.object({
34210
+ id: z128.string(),
34211
+ title: z128.string(),
34212
+ description: z128.string().nullish(),
34213
+ created_at: z128.string(),
34214
+ type: z128.string(),
34215
+ questions: z128.array(questionSchema).nullish()
34216
+ });
34217
+ var getRunResponseSchema = z128.object({
33430
34218
  run: publicRunSchema.nullable(),
33431
34219
  pending_human_request: pendingHumanRequestSchema.nullish()
33432
34220
  });
33433
- var stopRunResponseSchema = z127.object({
33434
- success: z127.boolean(),
33435
- message: z127.string().nullish()
33436
- });
33437
- var runMessageSchema = z127.object({
33438
- id: z127.string(),
33439
- type: z127.string(),
33440
- role: z127.string(),
33441
- timestamp: z127.string(),
33442
- text_content: z127.string().nullish(),
33443
- tool_call: z127.object({
33444
- id: z127.string(),
33445
- name: z127.string(),
33446
- arguments: z127.record(z127.string(), z127.unknown()).nullish()
34221
+ var stopRunResponseSchema = z128.object({
34222
+ success: z128.boolean(),
34223
+ message: z128.string().nullish()
34224
+ });
34225
+ var runMessageSchema = z128.object({
34226
+ id: z128.string(),
34227
+ type: z128.string(),
34228
+ role: z128.string(),
34229
+ timestamp: z128.string(),
34230
+ text_content: z128.string().nullish(),
34231
+ tool_call: z128.object({
34232
+ id: z128.string(),
34233
+ name: z128.string(),
34234
+ arguments: z128.record(z128.string(), z128.unknown()).nullish()
33447
34235
  }).nullish(),
33448
- tool_result: z127.object({
33449
- tool_call_id: z127.string(),
33450
- result: z127.unknown().nullish(),
33451
- error: z127.string().nullish()
34236
+ tool_result: z128.object({
34237
+ tool_call_id: z128.string(),
34238
+ result: z128.unknown().nullish(),
34239
+ error: z128.string().nullish()
33452
34240
  }).nullish()
33453
34241
  });
33454
- var listRunMessagesResponseSchema = z127.object({
33455
- messages: z127.array(runMessageSchema),
33456
- total: z127.number().nullish(),
33457
- limit: z127.number().nullish(),
33458
- offset: z127.number().nullish()
34242
+ var listRunMessagesResponseSchema = z128.object({
34243
+ messages: z128.array(runMessageSchema),
34244
+ total: z128.number().nullish(),
34245
+ limit: z128.number().nullish(),
34246
+ offset: z128.number().nullish()
33459
34247
  });
33460
- var postedMessageSchema = z127.object({
33461
- id: z127.string(),
33462
- type: z127.string(),
33463
- role: z127.string(),
33464
- timestamp: z127.string(),
33465
- text_content: z127.string()
34248
+ var postedMessageSchema = z128.object({
34249
+ id: z128.string(),
34250
+ type: z128.string(),
34251
+ role: z128.string(),
34252
+ timestamp: z128.string(),
34253
+ text_content: z128.string()
33466
34254
  });
33467
- var postRunMessageResponseSchema = z127.object({
34255
+ var postRunMessageResponseSchema = z128.object({
33468
34256
  message: postedMessageSchema
33469
34257
  });
33470
- var respondHumanRequestResponseSchema = z127.object({
33471
- human_request: z127.object({
33472
- id: z127.string(),
33473
- run_id: z127.string(),
33474
- title: z127.string(),
33475
- description: z127.string().nullish(),
33476
- response: z127.string().nullish(),
33477
- responded_at: z127.string().nullish(),
33478
- created_at: z127.string()
34258
+ var respondHumanRequestResponseSchema = z128.object({
34259
+ human_request: z128.object({
34260
+ id: z128.string(),
34261
+ run_id: z128.string(),
34262
+ title: z128.string(),
34263
+ description: z128.string().nullish(),
34264
+ response: z128.string().nullish(),
34265
+ responded_at: z128.string().nullish(),
34266
+ created_at: z128.string()
33479
34267
  })
33480
34268
  });
33481
34269
 
@@ -33626,7 +34414,7 @@ var MAX_LIMIT14 = 100;
33626
34414
  var SORT_ORDERS2 = ["asc", "desc"];
33627
34415
  var HAS_ISSUES_VALUES = ["true", "false"];
33628
34416
  var TITLE_PREVIEW_WIDTH = 50;
33629
- var TABLE_COLUMNS38 = [
34417
+ var TABLE_COLUMNS39 = [
33630
34418
  { header: "ID", cell: /* @__PURE__ */ __name((row) => row.id, "cell") },
33631
34419
  { header: "RUN#", cell: /* @__PURE__ */ __name((row) => String(row.run_number), "cell") },
33632
34420
  { header: "STATUS", cell: /* @__PURE__ */ __name((row) => row.status, "cell") },
@@ -33750,7 +34538,7 @@ function registerRunsList(runs) {
33750
34538
  console.log("No runs found.");
33751
34539
  return;
33752
34540
  }
33753
- console.log(renderTable(TABLE_COLUMNS38, response.data));
34541
+ console.log(renderTable(TABLE_COLUMNS39, response.data));
33754
34542
  console.log(
33755
34543
  `Showing ${response.data.length} of ${response.total} \xB7 offset ${offset}`
33756
34544
  );
@@ -33860,7 +34648,7 @@ var DEFAULT_LIMIT15 = 20;
33860
34648
  var MIN_LIMIT17 = 1;
33861
34649
  var MAX_LIMIT15 = 50;
33862
34650
  var TEXT_PREVIEW_WIDTH2 = 60;
33863
- var TABLE_COLUMNS39 = [
34651
+ var TABLE_COLUMNS40 = [
33864
34652
  { header: "ID", cell: /* @__PURE__ */ __name((row) => row.id, "cell") },
33865
34653
  { header: "ROLE", cell: /* @__PURE__ */ __name((row) => row.role, "cell") },
33866
34654
  { header: "TYPE", cell: /* @__PURE__ */ __name((row) => row.type, "cell") },
@@ -33925,7 +34713,7 @@ function registerRunsMessages(runs) {
33925
34713
  console.log("No messages found.");
33926
34714
  return;
33927
34715
  }
33928
- console.log(renderTable(TABLE_COLUMNS39, response.messages));
34716
+ console.log(renderTable(TABLE_COLUMNS40, response.messages));
33929
34717
  const resolvedOffset = response.offset ?? offset;
33930
34718
  const summary = response.total === null || response.total === void 0 ? `Showing ${response.messages.length} \xB7 offset ${resolvedOffset}` : `Showing ${response.messages.length} of ${response.total} \xB7 offset ${resolvedOffset}`;
33931
34719
  console.log(summary);
@@ -34193,28 +34981,28 @@ function registerRuns(program) {
34193
34981
  __name(registerRuns, "registerRuns");
34194
34982
 
34195
34983
  // src/api/sandbox-schemas.ts
34196
- import { z as z128 } from "zod";
34197
- var createSandboxResponseSchema = z128.object({
34198
- sandbox_id: z128.string(),
34199
- expires_at: z128.string()
34984
+ import { z as z129 } from "zod";
34985
+ var createSandboxResponseSchema = z129.object({
34986
+ sandbox_id: z129.string(),
34987
+ expires_at: z129.string()
34200
34988
  });
34201
- var createSandboxUploadUrlResponseSchema = z128.object({
34202
- upload_url: z128.string(),
34203
- path: z128.string(),
34204
- expires_in_seconds: z128.number()
34989
+ var createSandboxUploadUrlResponseSchema = z129.object({
34990
+ upload_url: z129.string(),
34991
+ path: z129.string(),
34992
+ expires_in_seconds: z129.number()
34205
34993
  });
34206
- var sandboxFileSchema = z128.object({
34207
- name: z128.string(),
34208
- path: z128.string(),
34209
- type: z128.enum(["file", "dir"]),
34210
- size_bytes: z128.number()
34994
+ var sandboxFileSchema = z129.object({
34995
+ name: z129.string(),
34996
+ path: z129.string(),
34997
+ type: z129.enum(["file", "dir"]),
34998
+ size_bytes: z129.number()
34211
34999
  });
34212
- var listSandboxFilesResponseSchema = z128.object({
34213
- files: z128.array(sandboxFileSchema)
35000
+ var listSandboxFilesResponseSchema = z129.object({
35001
+ files: z129.array(sandboxFileSchema)
34214
35002
  });
34215
- var uploadSandboxFileResponseSchema = z128.object({
34216
- path: z128.string(),
34217
- size_bytes: z128.number()
35003
+ var uploadSandboxFileResponseSchema = z129.object({
35004
+ path: z129.string(),
35005
+ size_bytes: z129.number()
34218
35006
  });
34219
35007
  var DEFAULT_SANDBOX_FILES_PATH = "/workspace";
34220
35008
 
@@ -34251,7 +35039,7 @@ function registerSandboxesCreate(sandboxes) {
34251
35039
  __name(registerSandboxesCreate, "registerSandboxesCreate");
34252
35040
 
34253
35041
  // src/commands/sandboxes/files.ts
34254
- var TABLE_COLUMNS40 = [
35042
+ var TABLE_COLUMNS41 = [
34255
35043
  { header: "TYPE", cell: /* @__PURE__ */ __name((row) => row.type, "cell") },
34256
35044
  { header: "NAME", cell: /* @__PURE__ */ __name((row) => row.name, "cell") },
34257
35045
  { header: "PATH", cell: /* @__PURE__ */ __name((row) => row.path, "cell") },
@@ -34289,7 +35077,7 @@ function registerSandboxesFiles(sandboxes) {
34289
35077
  console.log("No files found.");
34290
35078
  return;
34291
35079
  }
34292
- console.log(renderTable(TABLE_COLUMNS40, files));
35080
+ console.log(renderTable(TABLE_COLUMNS41, files));
34293
35081
  console.log(`Showing ${files.length}`);
34294
35082
  }, "filesAction"));
34295
35083
  }
@@ -34634,7 +35422,7 @@ function registerSecretsGet(secrets) {
34634
35422
  __name(registerSecretsGet, "registerSecretsGet");
34635
35423
 
34636
35424
  // src/commands/secrets/list.ts
34637
- var TABLE_COLUMNS41 = [
35425
+ var TABLE_COLUMNS42 = [
34638
35426
  { header: "ID", cell: /* @__PURE__ */ __name((row) => row.id, "cell") },
34639
35427
  { header: "NAME", cell: /* @__PURE__ */ __name((row) => row.name, "cell") },
34640
35428
  {
@@ -34678,7 +35466,7 @@ function registerSecretsList(secrets) {
34678
35466
  console.log("No secrets found.");
34679
35467
  return;
34680
35468
  }
34681
- console.log(renderTable(TABLE_COLUMNS41, rows));
35469
+ console.log(renderTable(TABLE_COLUMNS42, rows));
34682
35470
  console.log(`Showing ${rows.length}`);
34683
35471
  }, "listAction"));
34684
35472
  }
@@ -34789,7 +35577,7 @@ function registerSecrets(program) {
34789
35577
  __name(registerSecrets, "registerSecrets");
34790
35578
 
34791
35579
  // src/commands/skills/assignments.ts
34792
- var TABLE_COLUMNS42 = [
35580
+ var TABLE_COLUMNS43 = [
34793
35581
  { header: "ID", cell: /* @__PURE__ */ __name((row) => row.id, "cell") },
34794
35582
  { header: "NAME", cell: /* @__PURE__ */ __name((row) => row.name, "cell") }
34795
35583
  ];
@@ -34817,7 +35605,7 @@ function registerSkillsAssignments(skills) {
34817
35605
  console.log("No agents use this skill.");
34818
35606
  return;
34819
35607
  }
34820
- console.log(renderTable(TABLE_COLUMNS42, assignments));
35608
+ console.log(renderTable(TABLE_COLUMNS43, assignments));
34821
35609
  console.log(`Showing ${assignments.length} of ${total}`);
34822
35610
  }, "assignmentsAction"));
34823
35611
  }
@@ -34825,13 +35613,13 @@ __name(registerSkillsAssignments, "registerSkillsAssignments");
34825
35613
 
34826
35614
  // src/commands/skills/create.ts
34827
35615
  import { readFileSync as readFileSync5 } from "node:fs";
34828
- import { z as z129 } from "zod";
34829
- var createSkillResponseSchema = z129.object({
34830
- skill: z129.object({
34831
- id: z129.string(),
34832
- name: z129.string(),
34833
- description: z129.string(),
34834
- team_id: z129.string()
35616
+ import { z as z130 } from "zod";
35617
+ var createSkillResponseSchema = z130.object({
35618
+ skill: z130.object({
35619
+ id: z130.string(),
35620
+ name: z130.string(),
35621
+ description: z130.string(),
35622
+ team_id: z130.string()
34835
35623
  })
34836
35624
  });
34837
35625
  function registerSkillsCreate(skills) {
@@ -35110,7 +35898,7 @@ function registerSkillsFileUpdate(skills) {
35110
35898
  __name(registerSkillsFileUpdate, "registerSkillsFileUpdate");
35111
35899
 
35112
35900
  // src/commands/skills/files.ts
35113
- var TABLE_COLUMNS43 = [
35901
+ var TABLE_COLUMNS44 = [
35114
35902
  { header: "PATH", cell: /* @__PURE__ */ __name((row) => row.path, "cell") },
35115
35903
  { header: "NAME", cell: /* @__PURE__ */ __name((row) => row.name, "cell") },
35116
35904
  {
@@ -35149,7 +35937,7 @@ function registerSkillsFiles(skills) {
35149
35937
  console.log("No files found.");
35150
35938
  return;
35151
35939
  }
35152
- console.log(renderTable(TABLE_COLUMNS43, parsed.data.files));
35940
+ console.log(renderTable(TABLE_COLUMNS44, parsed.data.files));
35153
35941
  console.log(`Showing ${parsed.data.files.length}`);
35154
35942
  }, "filesAction"));
35155
35943
  }
@@ -35206,13 +35994,13 @@ function readExistingContent(source) {
35206
35994
  __name(readExistingContent, "readExistingContent");
35207
35995
 
35208
35996
  // src/commands/skills/install.ts
35209
- import { z as z130 } from "zod";
35210
- var installSkillResponseSchema = z130.object({
35211
- skill: z130.object({
35212
- id: z130.string(),
35213
- name: z130.string(),
35214
- description: z130.string(),
35215
- team_id: z130.string()
35997
+ import { z as z131 } from "zod";
35998
+ var installSkillResponseSchema = z131.object({
35999
+ skill: z131.object({
36000
+ id: z131.string(),
36001
+ name: z131.string(),
36002
+ description: z131.string(),
36003
+ team_id: z131.string()
35216
36004
  })
35217
36005
  });
35218
36006
  function registerSkillsInstall(skills) {
@@ -35361,48 +36149,48 @@ function registerSkillsList(skills) {
35361
36149
  __name(registerSkillsList, "registerSkillsList");
35362
36150
 
35363
36151
  // src/api/skill-revision-schemas.ts
35364
- import { z as z131 } from "zod";
35365
- var skillRevisionSchema = z131.object({
35366
- id: z131.string(),
35367
- skill_id: z131.string(),
35368
- revision_number: z131.number().nullable(),
35369
- status: z131.enum(["draft", "live", "historic"]),
35370
- revision_name: z131.string().nullable(),
35371
- revision_description: z131.string().nullable(),
35372
- created_by: z131.string().nullable(),
35373
- created_by_name: z131.string().nullable(),
35374
- created_at: z131.string(),
35375
- updated_at: z131.string()
35376
- });
35377
- var listSkillRevisionsResponseSchema = z131.object({
35378
- revisions: z131.array(skillRevisionSchema),
35379
- total: z131.number().nullish(),
35380
- limit: z131.number().nullish(),
35381
- offset: z131.number().nullish()
35382
- });
35383
- var createSkillRevisionResponseSchema = z131.object({
36152
+ import { z as z132 } from "zod";
36153
+ var skillRevisionSchema = z132.object({
36154
+ id: z132.string(),
36155
+ skill_id: z132.string(),
36156
+ revision_number: z132.number().nullable(),
36157
+ status: z132.enum(["draft", "live", "historic"]),
36158
+ revision_name: z132.string().nullable(),
36159
+ revision_description: z132.string().nullable(),
36160
+ created_by: z132.string().nullable(),
36161
+ created_by_name: z132.string().nullable(),
36162
+ created_at: z132.string(),
36163
+ updated_at: z132.string()
36164
+ });
36165
+ var listSkillRevisionsResponseSchema = z132.object({
36166
+ revisions: z132.array(skillRevisionSchema),
36167
+ total: z132.number().nullish(),
36168
+ limit: z132.number().nullish(),
36169
+ offset: z132.number().nullish()
36170
+ });
36171
+ var createSkillRevisionResponseSchema = z132.object({
35384
36172
  revision: skillRevisionSchema,
35385
- created: z131.boolean()
36173
+ created: z132.boolean()
35386
36174
  });
35387
- var skillRevisionResponseSchema = z131.object({
36175
+ var skillRevisionResponseSchema = z132.object({
35388
36176
  revision: skillRevisionSchema
35389
36177
  });
35390
- var deleteSkillRevisionResponseSchema = z131.object({
35391
- success: z131.boolean(),
35392
- message: z131.string()
36178
+ var deleteSkillRevisionResponseSchema = z132.object({
36179
+ success: z132.boolean(),
36180
+ message: z132.string()
35393
36181
  });
35394
- var skillRevisionFileSchema = z131.object({
35395
- name: z131.string(),
35396
- path: z131.string(),
35397
- size: z131.number().optional(),
35398
- contentType: z131.string().optional(),
35399
- updatedAt: z131.string().optional()
36182
+ var skillRevisionFileSchema = z132.object({
36183
+ name: z132.string(),
36184
+ path: z132.string(),
36185
+ size: z132.number().optional(),
36186
+ contentType: z132.string().optional(),
36187
+ updatedAt: z132.string().optional()
35400
36188
  });
35401
- var listSkillRevisionFilesResponseSchema = z131.object({
35402
- files: z131.array(skillRevisionFileSchema),
35403
- limit: z131.number().nullish(),
35404
- has_more: z131.boolean().nullish(),
35405
- next_cursor: z131.string().nullish()
36189
+ var listSkillRevisionFilesResponseSchema = z132.object({
36190
+ files: z132.array(skillRevisionFileSchema),
36191
+ limit: z132.number().nullish(),
36192
+ has_more: z132.boolean().nullish(),
36193
+ next_cursor: z132.string().nullish()
35406
36194
  });
35407
36195
 
35408
36196
  // src/commands/skills/revisions/create.ts
@@ -35565,7 +36353,7 @@ __name(registerSkillsRevisionsFileUpdate, "registerSkillsRevisionsFileUpdate");
35565
36353
  var DEFAULT_LIMIT16 = 100;
35566
36354
  var MIN_LIMIT18 = 1;
35567
36355
  var MAX_LIMIT16 = 1e3;
35568
- var TABLE_COLUMNS44 = [
36356
+ var TABLE_COLUMNS45 = [
35569
36357
  { header: "PATH", cell: /* @__PURE__ */ __name((row) => row.path, "cell") },
35570
36358
  { header: "NAME", cell: /* @__PURE__ */ __name((row) => row.name, "cell") },
35571
36359
  {
@@ -35627,7 +36415,7 @@ function registerSkillsRevisionsFiles(revisions) {
35627
36415
  );
35628
36416
  return;
35629
36417
  }
35630
- console.log(renderTable(TABLE_COLUMNS44, parsed.data.files));
36418
+ console.log(renderTable(TABLE_COLUMNS45, parsed.data.files));
35631
36419
  console.log(
35632
36420
  nextCursor === null ? `Showing ${parsed.data.files.length}` : `Showing ${parsed.data.files.length} \xB7 more files remain \u2014 next page: --cursor ${nextCursor}`
35633
36421
  );
@@ -35639,7 +36427,7 @@ __name(registerSkillsRevisionsFiles, "registerSkillsRevisionsFiles");
35639
36427
  var DEFAULT_LIMIT17 = 20;
35640
36428
  var MIN_LIMIT19 = 1;
35641
36429
  var MAX_LIMIT17 = 100;
35642
- var TABLE_COLUMNS45 = [
36430
+ var TABLE_COLUMNS46 = [
35643
36431
  { header: "ID", cell: /* @__PURE__ */ __name((row) => row.id, "cell") },
35644
36432
  {
35645
36433
  header: "VERSION",
@@ -35688,7 +36476,7 @@ function registerSkillsRevisionsList(revisions) {
35688
36476
  console.log("No revisions found.");
35689
36477
  return;
35690
36478
  }
35691
- console.log(renderTable(TABLE_COLUMNS45, response.revisions));
36479
+ console.log(renderTable(TABLE_COLUMNS46, response.revisions));
35692
36480
  const resolvedOffset = response.offset ?? offset;
35693
36481
  const total = response.total ?? null;
35694
36482
  const summary = total === null ? `Showing ${response.revisions.length} \xB7 offset ${resolvedOffset}` : `Showing ${response.revisions.length} of ${total} \xB7 offset ${resolvedOffset}`;
@@ -35878,13 +36666,13 @@ __name(registerSkillsSystem, "registerSkillsSystem");
35878
36666
  // src/commands/skills/upload.ts
35879
36667
  import { readFile as readFile10, stat as stat3 } from "node:fs/promises";
35880
36668
  import { basename as basename4 } from "node:path";
35881
- import { z as z132 } from "zod";
35882
- var uploadSkillResponseSchema = z132.object({
35883
- skill: z132.object({
35884
- id: z132.string(),
35885
- name: z132.string(),
35886
- description: z132.string(),
35887
- team_id: z132.string()
36669
+ import { z as z133 } from "zod";
36670
+ var uploadSkillResponseSchema = z133.object({
36671
+ skill: z133.object({
36672
+ id: z133.string(),
36673
+ name: z133.string(),
36674
+ description: z133.string(),
36675
+ team_id: z133.string()
35888
36676
  })
35889
36677
  });
35890
36678
  function registerSkillsUpload(skills) {
@@ -36120,17 +36908,17 @@ function registerSuggestionsGet(suggestions) {
36120
36908
  __name(registerSuggestionsGet, "registerSuggestionsGet");
36121
36909
 
36122
36910
  // src/commands/suggestions/list.ts
36123
- import { z as z133 } from "zod";
36911
+ import { z as z134 } from "zod";
36124
36912
  var DEFAULT_LIMIT18 = 100;
36125
36913
  var MIN_LIMIT20 = 1;
36126
36914
  var MAX_LIMIT18 = 250;
36127
- var listEnvelopeSchema = z133.object({
36128
- data: z133.array(z133.unknown()),
36129
- pending_count: z133.number().int().nonnegative()
36915
+ var listEnvelopeSchema = z134.object({
36916
+ data: z134.array(z134.unknown()),
36917
+ pending_count: z134.number().int().nonnegative()
36130
36918
  });
36131
36919
  var STATUS_FILTERS = ["pending", "history"];
36132
36920
  var TITLE_PREVIEW_WIDTH2 = 50;
36133
- var TABLE_COLUMNS46 = [
36921
+ var TABLE_COLUMNS47 = [
36134
36922
  { header: "ID", cell: /* @__PURE__ */ __name((row) => row.id, "cell") },
36135
36923
  { header: "TYPE", cell: /* @__PURE__ */ __name((row) => row.type, "cell") },
36136
36924
  { header: "STATUS", cell: /* @__PURE__ */ __name((row) => row.status, "cell") },
@@ -36208,7 +36996,7 @@ function registerSuggestionsList(suggestions) {
36208
36996
  console.log(`Pending total: ${pendingCount}`);
36209
36997
  return;
36210
36998
  }
36211
- console.log(renderTable(TABLE_COLUMNS46, data));
36999
+ console.log(renderTable(TABLE_COLUMNS47, data));
36212
37000
  console.log(
36213
37001
  `Showing ${data.length} \xB7 offset ${offset} \xB7 pending total ${pendingCount}`
36214
37002
  );
@@ -36335,7 +37123,7 @@ __name(registerTeamGet, "registerTeamGet");
36335
37123
  var DEFAULT_LIMIT19 = 50;
36336
37124
  var MIN_LIMIT21 = 1;
36337
37125
  var MAX_LIMIT19 = 100;
36338
- var TABLE_COLUMNS47 = [
37126
+ var TABLE_COLUMNS48 = [
36339
37127
  { header: "ID", cell: /* @__PURE__ */ __name((row) => row.id, "cell") },
36340
37128
  { header: "NAME", cell: /* @__PURE__ */ __name((row) => row.name ?? "", "cell") },
36341
37129
  { header: "EMAIL", cell: /* @__PURE__ */ __name((row) => row.email, "cell") },
@@ -36386,7 +37174,7 @@ function registerTeamMembers(team) {
36386
37174
  console.log("No members found.");
36387
37175
  return;
36388
37176
  }
36389
- console.log(renderTable(TABLE_COLUMNS47, response.members));
37177
+ console.log(renderTable(TABLE_COLUMNS48, response.members));
36390
37178
  console.log(
36391
37179
  `Showing ${response.members.length} of ${response.total} \xB7 offset ${response.offset}`
36392
37180
  );
@@ -36395,19 +37183,14 @@ function registerTeamMembers(team) {
36395
37183
  __name(registerTeamMembers, "registerTeamMembers");
36396
37184
 
36397
37185
  // src/commands/team/use.ts
36398
- import { z as z134 } from "zod";
37186
+ import { z as z135 } from "zod";
36399
37187
  var TEAM_ID_SHAPE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
36400
- var teamIdSchema = z134.string().regex(TEAM_ID_SHAPE);
37188
+ var teamIdSchema = z135.string().regex(TEAM_ID_SHAPE);
36401
37189
  function registerTeamUse(team) {
36402
37190
  team.command("use <team-id>").description(
36403
- "Set the default team for the active OAuth profile (overridable per-command via --team or DUVO_TEAM_ID)"
37191
+ "Set the default team for the active profile (overridable per-command via --team or DUVO_TEAM_ID)"
36404
37192
  ).action(/* @__PURE__ */ __name(async function useAction(teamId) {
36405
37193
  const auth = await requireAuthenticatedConfig(this);
36406
- if (auth.authType === "api-key") {
36407
- throw new CliError(
36408
- `This is an API-key profile \u2014 the team is baked into the key itself. Create or switch to an OAuth profile to use \`team use\`.`
36409
- );
36410
- }
36411
37194
  const parsedTeamId = teamIdSchema.safeParse(teamId);
36412
37195
  if (!parsedTeamId.success) {
36413
37196
  throw new CliError(
@@ -36420,16 +37203,17 @@ function registerTeamUse(team) {
36420
37203
  auth.apiBaseUrl
36421
37204
  );
36422
37205
  const config = await readConfig();
36423
- const profileFlag = getProfileFlag(this);
36424
- const profileName = profileFlag ?? config.defaultProfile;
37206
+ const profileName = auth.profileName;
36425
37207
  if (!profileName) {
36426
37208
  throw new CliError(
36427
- "No active profile. Run `duvo login` first or pass --profile."
37209
+ "Can't set a default team for an env-supplied credential (DUVO_API_KEY) \u2014 there's no stored profile to persist it to. Set DUVO_TEAM_ID instead, or store the key first with `duvo login --api-key`."
36428
37210
  );
36429
37211
  }
36430
37212
  const profile = config.profiles[profileName];
36431
- if (!profile || profile.type !== "oauth") {
36432
- throw new CliError(`Profile "${profileName}" is not an OAuth profile.`);
37213
+ if (!profile) {
37214
+ throw new CliError(
37215
+ `Profile "${profileName}" does not exist. Run \`duvo profiles list\` to see available profiles.`
37216
+ );
36433
37217
  }
36434
37218
  const updated = {
36435
37219
  ...config,
@@ -36483,10 +37267,10 @@ function registerTeam(program) {
36483
37267
  __name(registerTeam, "registerTeam");
36484
37268
 
36485
37269
  // src/commands/teams/create-org-team.ts
36486
- import { z as z135 } from "zod";
36487
- var createOrgTeamResponseSchema = z135.object({
36488
- id: z135.guid(),
36489
- name: z135.string()
37270
+ import { z as z136 } from "zod";
37271
+ var createOrgTeamResponseSchema = z136.object({
37272
+ id: z136.guid(),
37273
+ name: z136.string()
36490
37274
  });
36491
37275
  function registerTeamsCreateOrgTeam(teams) {
36492
37276
  teams.command("create-org-team <org-id>").description("Create a new team inside an organization you administer").requiredOption("--name <name>", "team name").option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function createOrgTeamAction(orgId, options) {
@@ -36523,87 +37307,15 @@ function registerTeamsCreateOrgTeam(teams) {
36523
37307
  }
36524
37308
  __name(registerTeamsCreateOrgTeam, "registerTeamsCreateOrgTeam");
36525
37309
 
36526
- // src/commands/teams/invite-org-member.ts
36527
- var ORG_ROLES2 = Object.values(ORG_ROLE);
36528
- var DEFAULT_ROLE = ORG_ROLE.MEMBER;
36529
- function registerTeamsInviteOrgMember(teams) {
36530
- teams.command("invite-org-member <org-id>").description(
36531
- "Invite a person to an organization, optionally onto one of its teams"
36532
- ).requiredOption("--email <email>", "email address of the person to invite").option(
36533
- "--role <role>",
36534
- `organization role to grant: ${ORG_ROLES2.join(", ")} (default ${DEFAULT_ROLE})`,
36535
- DEFAULT_ROLE
36536
- ).option("--team-id <id>", "assign the invitee to this team in the org").option(
36537
- "--frontend-url <url>",
36538
- "base URL used to build the invitation email link (email is skipped if omitted)"
36539
- ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function inviteOrgMemberAction(orgId, options) {
36540
- const email = options.email?.trim();
36541
- if (email === void 0 || email.length === 0) {
36542
- throw new CliError("--email must not be empty");
36543
- }
36544
- const role = options.role ?? DEFAULT_ROLE;
36545
- if (!ORG_ROLES2.includes(role)) {
36546
- throw new CliError(
36547
- `Invalid --role "${role}"; expected one of: ${ORG_ROLES2.join(", ")}`
36548
- );
36549
- }
36550
- const { apiKey, apiBaseUrl } = await requireAuthenticatedConfig(this);
36551
- const body = { email, role };
36552
- if (options.teamId !== void 0) {
36553
- const teamId = options.teamId.trim();
36554
- if (teamId.length === 0) {
36555
- throw new CliError("--team-id must not be empty");
36556
- }
36557
- body.teamId = teamId;
36558
- }
36559
- if (options.frontendUrl !== void 0) {
36560
- const frontendUrl = options.frontendUrl.trim();
36561
- if (frontendUrl.length === 0) {
36562
- throw new CliError("--frontend-url must not be empty");
36563
- }
36564
- body.frontendUrl = frontendUrl;
36565
- }
36566
- const raw = await httpRequest({
36567
- method: "POST",
36568
- path: `/v2/organizations/${encodeURIComponent(orgId)}/members`,
36569
- apiKey,
36570
- apiBaseUrl,
36571
- body
36572
- });
36573
- if (options.json) {
36574
- printJson(raw);
36575
- return;
36576
- }
36577
- const parsed = inviteOrgMemberResponseSchema.safeParse(raw);
36578
- if (!parsed.success) {
36579
- throw new CliError(
36580
- `Unexpected response from POST /v2/organizations/:orgId/members: ${parsed.error.message}`
36581
- );
36582
- }
36583
- console.log(green("Invitation created!"));
36584
- console.log();
36585
- console.log(
36586
- renderKeyValue([
36587
- { label: "Invitation ID", value: parsed.data.invitationId },
36588
- { label: "Email", value: email },
36589
- { label: "Role", value: role },
36590
- { label: "Team", value: body.teamId ?? "\u2014" },
36591
- { label: "Email sent", value: parsed.data.emailSent ? "yes" : "no" }
36592
- ])
36593
- );
36594
- }, "inviteOrgMemberAction"));
36595
- }
36596
- __name(registerTeamsInviteOrgMember, "registerTeamsInviteOrgMember");
36597
-
36598
37310
  // src/commands/teams/list.ts
36599
- import { z as z136 } from "zod";
36600
- var teamApiSchema2 = z136.object({
36601
- id: z136.string(),
36602
- name: z136.string(),
36603
- organization_id: z136.string().nullable()
37311
+ import { z as z137 } from "zod";
37312
+ var teamApiSchema2 = z137.object({
37313
+ id: z137.string(),
37314
+ name: z137.string(),
37315
+ organization_id: z137.string().nullable()
36604
37316
  });
36605
- var listMyTeamsResponseSchema3 = z136.object({
36606
- teams: z136.array(teamApiSchema2)
37317
+ var listMyTeamsResponseSchema3 = z137.object({
37318
+ teams: z137.array(teamApiSchema2)
36607
37319
  });
36608
37320
  function registerTeamsList(teams) {
36609
37321
  teams.command("list", { isDefault: true }).description("List every team you can act on").option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function listAction(options) {
@@ -36646,21 +37358,21 @@ function registerTeamsList(teams) {
36646
37358
  __name(registerTeamsList, "registerTeamsList");
36647
37359
 
36648
37360
  // src/commands/teams/org-insights.ts
36649
- import { z as z137 } from "zod";
36650
- var headlineSchema = z137.object({
36651
- total_runs: z137.number(),
36652
- completed_runs: z137.number(),
36653
- failed_runs: z137.number(),
36654
- success_rate: z137.number().nullable(),
36655
- active_agents: z137.number(),
36656
- active_users: z137.number(),
36657
- start_date: z137.string(),
36658
- end_date: z137.string(),
36659
- truncated: z137.boolean(),
36660
- aggregated_teams: z137.number(),
36661
- total_teams: z137.number()
36662
- });
36663
- var orgInsightsHeadlineResponseSchema = z137.object({
37361
+ import { z as z138 } from "zod";
37362
+ var headlineSchema = z138.object({
37363
+ total_runs: z138.number(),
37364
+ completed_runs: z138.number(),
37365
+ failed_runs: z138.number(),
37366
+ success_rate: z138.number().nullable(),
37367
+ active_agents: z138.number(),
37368
+ active_users: z138.number(),
37369
+ start_date: z138.string(),
37370
+ end_date: z138.string(),
37371
+ truncated: z138.boolean(),
37372
+ aggregated_teams: z138.number(),
37373
+ total_teams: z138.number()
37374
+ });
37375
+ var orgInsightsHeadlineResponseSchema = z138.object({
36664
37376
  headline: headlineSchema
36665
37377
  });
36666
37378
  function formatRate(rate) {
@@ -36728,26 +37440,26 @@ function registerTeamsOrgInsights(teams) {
36728
37440
  __name(registerTeamsOrgInsights, "registerTeamsOrgInsights");
36729
37441
 
36730
37442
  // src/commands/teams/org-metrics.ts
36731
- import { z as z138 } from "zod";
36732
- var teamMetricSchema = z138.object({
36733
- team_id: z138.string(),
36734
- team_name: z138.string(),
36735
- is_deleted: z138.boolean(),
36736
- member_count: z138.number(),
36737
- assignment_count: z138.number(),
36738
- scheduled_job_count: z138.number(),
36739
- total_jobs: z138.number(),
36740
- completed_jobs: z138.number(),
36741
- failed_jobs: z138.number(),
36742
- total_runs: z138.number()
36743
- });
36744
- var orgInsightsMetricsResponseSchema = z138.object({
36745
- teams: z138.array(teamMetricSchema),
36746
- start_date: z138.string(),
36747
- end_date: z138.string(),
36748
- truncated: z138.boolean(),
36749
- total_teams: z138.number(),
36750
- org_member_count: z138.number()
37443
+ import { z as z139 } from "zod";
37444
+ var teamMetricSchema = z139.object({
37445
+ team_id: z139.string(),
37446
+ team_name: z139.string(),
37447
+ is_deleted: z139.boolean(),
37448
+ member_count: z139.number(),
37449
+ assignment_count: z139.number(),
37450
+ scheduled_job_count: z139.number(),
37451
+ total_jobs: z139.number(),
37452
+ completed_jobs: z139.number(),
37453
+ failed_jobs: z139.number(),
37454
+ total_runs: z139.number()
37455
+ });
37456
+ var orgInsightsMetricsResponseSchema = z139.object({
37457
+ teams: z139.array(teamMetricSchema),
37458
+ start_date: z139.string(),
37459
+ end_date: z139.string(),
37460
+ truncated: z139.boolean(),
37461
+ total_teams: z139.number(),
37462
+ org_member_count: z139.number()
36751
37463
  });
36752
37464
  function registerTeamsOrgMetrics(teams) {
36753
37465
  teams.command("org-metrics <org-id>").description("Show per-team run metrics across an organization").option("--start-date <date>", "window start (ISO 8601, default 7d ago)").option("--end-date <date>", "window end (ISO 8601, default now)").option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function orgMetricsAction(orgId, options) {
@@ -36810,20 +37522,20 @@ ${total_teams} teams${suffix} \xB7 ${org_member_count} org members`
36810
37522
  __name(registerTeamsOrgMetrics, "registerTeamsOrgMetrics");
36811
37523
 
36812
37524
  // src/commands/teams/org-usage.ts
36813
- import { z as z139 } from "zod";
37525
+ import { z as z140 } from "zod";
36814
37526
  var GRANULARITIES = ["day", "week", "month"];
36815
37527
  var DEFAULT_LOOKBACK_MS = 30 * 24 * 60 * 60 * 1e3;
36816
- var bucketSchema = z139.object({
36817
- period: z139.string(),
36818
- total_runs: z139.number(),
36819
- scheduled_runs: z139.number(),
36820
- on_demand_runs: z139.number()
36821
- });
36822
- var usageChartResponseSchema = z139.object({
36823
- buckets: z139.array(bucketSchema),
36824
- granularity: z139.enum(GRANULARITIES),
36825
- truncated: z139.boolean(),
36826
- total_teams: z139.number()
37528
+ var bucketSchema = z140.object({
37529
+ period: z140.string(),
37530
+ total_runs: z140.number(),
37531
+ scheduled_runs: z140.number(),
37532
+ on_demand_runs: z140.number()
37533
+ });
37534
+ var usageChartResponseSchema = z140.object({
37535
+ buckets: z140.array(bucketSchema),
37536
+ granularity: z140.enum(GRANULARITIES),
37537
+ truncated: z140.boolean(),
37538
+ total_teams: z140.number()
36827
37539
  });
36828
37540
  function registerTeamsOrgUsage(teams) {
36829
37541
  teams.command("org-usage <org-id>").description("Show org-wide run volume over time (scheduled vs on-demand)").option("--start-date <date>", "window start (ISO 8601, default 30d ago)").option("--end-date <date>", "window end (ISO 8601, default now)").option(
@@ -36882,17 +37594,17 @@ function registerTeamsOrgUsage(teams) {
36882
37594
  __name(registerTeamsOrgUsage, "registerTeamsOrgUsage");
36883
37595
 
36884
37596
  // src/commands/teams/org.ts
36885
- import { z as z140 } from "zod";
36886
- var orgTeamSchema = z140.object({
36887
- id: z140.string(),
36888
- name: z140.string(),
36889
- userIsMember: z140.boolean(),
36890
- userRole: z140.string().nullable(),
36891
- memberCount: z140.number()
37597
+ import { z as z141 } from "zod";
37598
+ var orgTeamSchema = z141.object({
37599
+ id: z141.string(),
37600
+ name: z141.string(),
37601
+ userIsMember: z141.boolean(),
37602
+ userRole: z141.string().nullable(),
37603
+ memberCount: z141.number()
36892
37604
  });
36893
- var listOrgTeamsResponseSchema = z140.object({
36894
- teams: z140.array(orgTeamSchema),
36895
- total: z140.number()
37605
+ var listOrgTeamsResponseSchema = z141.object({
37606
+ teams: z141.array(orgTeamSchema),
37607
+ total: z141.number()
36896
37608
  });
36897
37609
  var SORT_BY_VALUES = ["createdAt", "name"];
36898
37610
  function registerTeamsOrg(teams) {
@@ -36953,17 +37665,17 @@ function registerTeamsOrg(teams) {
36953
37665
  __name(registerTeamsOrg, "registerTeamsOrg");
36954
37666
 
36955
37667
  // src/commands/teams/orgs.ts
36956
- import { z as z141 } from "zod";
36957
- var orgMembershipSchema = z141.object({
36958
- organization: z141.object({
36959
- id: z141.string(),
36960
- name: z141.string()
37668
+ import { z as z142 } from "zod";
37669
+ var orgMembershipSchema = z142.object({
37670
+ organization: z142.object({
37671
+ id: z142.string(),
37672
+ name: z142.string()
36961
37673
  }),
36962
- role: z141.string(),
36963
- memberCount: z141.number()
37674
+ role: z142.string(),
37675
+ memberCount: z142.number()
36964
37676
  });
36965
- var listMyOrganizationsResponseSchema = z141.object({
36966
- memberships: z141.array(orgMembershipSchema)
37677
+ var listMyOrganizationsResponseSchema = z142.object({
37678
+ memberships: z142.array(orgMembershipSchema)
36967
37679
  });
36968
37680
  function registerTeamsOrgs(teams) {
36969
37681
  teams.command("orgs").description("List the organizations you belong to and your role in each").option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function orgsAction(options) {
@@ -37010,7 +37722,6 @@ function registerTeams(program) {
37010
37722
  registerTeamsOrg(teams);
37011
37723
  registerTeamsOrgs(teams);
37012
37724
  registerTeamsCreateOrgTeam(teams);
37013
- registerTeamsInviteOrgMember(teams);
37014
37725
  registerTeamsOrgInsights(teams);
37015
37726
  registerTeamsOrgMetrics(teams);
37016
37727
  registerTeamsOrgUsage(teams);
@@ -37141,7 +37852,7 @@ __name(isStandaloneBinary, "isStandaloneBinary");
37141
37852
  import { createRequire } from "node:module";
37142
37853
  function getPackageMeta() {
37143
37854
  if (true) {
37144
- return { name: "@duvoai/cli", version: "1.45.3" };
37855
+ return { name: "@duvoai/cli", version: "1.46.0" };
37145
37856
  }
37146
37857
  const require2 = createRequire(import.meta.url);
37147
37858
  const raw = require2("../../package.json");
@@ -37372,15 +38083,25 @@ __name(updateNpmInstall, "updateNpmInstall");
37372
38083
  function registerWhoami(program) {
37373
38084
  program.command("whoami").description(
37374
38085
  "Print the active profile, the authenticated user's name and email, the team ID that subsequent commands will act on, and the auth type"
37375
- ).action(/* @__PURE__ */ __name(async function whoamiAction() {
38086
+ ).option("--json", "output machine-readable JSON").action(/* @__PURE__ */ __name(async function whoamiAction(options) {
37376
38087
  const resolved = await requireAuthenticatedConfig(this);
38088
+ const user = await fetchUser(resolved);
38089
+ const teamId = await resolveActiveTeamId(resolved, getTeamFlag(this));
38090
+ if (options.json) {
38091
+ printJson({
38092
+ profile: resolved.profileName,
38093
+ user,
38094
+ team: teamId,
38095
+ authType: resolved.authType
38096
+ });
38097
+ return;
38098
+ }
37377
38099
  const profileLabel = resolved.profileName ?? "(env-only, no stored profile)";
37378
38100
  console.log(`Profile ${profileLabel}`);
37379
- const userLine = await fetchUserLine(resolved);
37380
- if (userLine !== null) {
38101
+ if (user !== null) {
38102
+ const userLine = user.name ? `${user.name} <${user.email}>` : user.email;
37381
38103
  console.log(`User ${userLine}`);
37382
38104
  }
37383
- const teamId = await resolveActiveTeamId(resolved, getTeamFlag(this));
37384
38105
  if (teamId !== null) {
37385
38106
  console.log(`Team ${teamId}`);
37386
38107
  }
@@ -37389,7 +38110,7 @@ function registerWhoami(program) {
37389
38110
  }, "whoamiAction"));
37390
38111
  }
37391
38112
  __name(registerWhoami, "registerWhoami");
37392
- async function fetchUserLine(config) {
38113
+ async function fetchUser(config) {
37393
38114
  try {
37394
38115
  const raw = await httpRequest({
37395
38116
  method: "GET",
@@ -37401,13 +38122,13 @@ async function fetchUserLine(config) {
37401
38122
  if (!parsed.success) {
37402
38123
  return null;
37403
38124
  }
37404
- const { name, email } = parsed.data.profile;
37405
- return name ? `${name} <${email}>` : email;
38125
+ const { id, name, email } = parsed.data.profile;
38126
+ return { id, name, email };
37406
38127
  } catch {
37407
38128
  return null;
37408
38129
  }
37409
38130
  }
37410
- __name(fetchUserLine, "fetchUserLine");
38131
+ __name(fetchUser, "fetchUser");
37411
38132
  async function resolveActiveTeamId(config, override) {
37412
38133
  try {
37413
38134
  return await resolveRequiredTeamId(config, { override });
@@ -37555,7 +38276,7 @@ function createProgram() {
37555
38276
  "use a specific profile for this invocation (overrides default profile)"
37556
38277
  ).option(
37557
38278
  "--team <id>",
37558
- "use a specific team for this invocation (overrides DUVO_TEAM_ID and profile default; API-key profiles are pinned to the key's team, so a different value is rejected by the server)"
38279
+ "use a specific team for this invocation (overrides DUVO_TEAM_ID and profile default; team-scoped API keys stay pinned to the key's team)"
37559
38280
  ).addOption(
37560
38281
  new Option2(
37561
38282
  "--no-update-notifier",
@@ -37604,6 +38325,7 @@ ${notice}` : "";
37604
38325
  registerSuggestions(program);
37605
38326
  registerTeam(program);
37606
38327
  registerTeams(program);
38328
+ registerInvite(program);
37607
38329
  registerSecrets(program);
37608
38330
  registerCredentials(program);
37609
38331
  registerRevisionSecrets(program);