@duvoai/cli 1.26.0 → 1.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/duvo.js CHANGED
@@ -2255,6 +2255,16 @@ var AGENT_RUN_STATUSES = [
2255
2255
  "interrupted"
2256
2256
  // User interrupted
2257
2257
  ];
2258
+ var TERMINAL_AGENT_RUN_STATUSES = [
2259
+ "completed",
2260
+ "failed",
2261
+ "interrupted"
2262
+ ];
2263
+ function isTerminalAgentRunStatus(status) {
2264
+ return TERMINAL_AGENT_RUN_STATUSES.includes(status);
2265
+ }
2266
+ __name(isTerminalAgentRunStatus, "isTerminalAgentRunStatus");
2267
+ __name2(isTerminalAgentRunStatus, "isTerminalAgentRunStatus");
2258
2268
  var agentRunStatusSchema = z10.enum(AGENT_RUN_STATUSES);
2259
2269
  var AGENT_RUN_SOURCES = [
2260
2270
  "app",
@@ -2503,7 +2513,7 @@ var canExecuteConcurrentResultSchema = z11.object({
2503
2513
  var BrowsingProviderSchema = z12.enum(["google", "anthropic"]);
2504
2514
  var PLATFORM_DEFAULT_MODELS = {
2505
2515
  agent: {
2506
- model: "claude-sonnet-5"
2516
+ model: "claude-sonnet-5[1m]"
2507
2517
  },
2508
2518
  browsing: {
2509
2519
  provider: "google",
@@ -2512,6 +2522,7 @@ var PLATFORM_DEFAULT_MODELS = {
2512
2522
  };
2513
2523
  var CLAUDE_MODEL_IDS = [
2514
2524
  "claude-sonnet-5",
2525
+ "claude-sonnet-5[1m]",
2515
2526
  "claude-opus-4-8",
2516
2527
  "claude-opus-4-8[1m]"
2517
2528
  ];
@@ -2555,6 +2566,10 @@ var AVAILABLE_AGENT_MODELS = {
2555
2566
  displayName: "Claude Sonnet 5",
2556
2567
  description: "Fast and capable for everyday tasks"
2557
2568
  },
2569
+ "claude-sonnet-5[1m]": {
2570
+ displayName: "Claude Sonnet 5",
2571
+ description: "Fast and capable for everyday tasks"
2572
+ },
2558
2573
  "claude-opus-4-8": {
2559
2574
  displayName: "Claude Opus 4.8",
2560
2575
  description: "Our most capable model \u2014 best for complex work"
@@ -2572,21 +2587,28 @@ var BrowsingModelIdSchema = z12.enum([
2572
2587
  "claude-sonnet-4-5",
2573
2588
  "claude-opus-4-1"
2574
2589
  ]);
2575
- var LEGACY_DEFAULT_MODEL = "claude-sonnet-5";
2590
+ var LEGACY_DEFAULT_MODEL = "claude-sonnet-5[1m]";
2576
2591
  var LEGACY_MODEL_REMAP = {
2577
- "claude-sonnet-4-6": "claude-sonnet-5",
2578
- "claude-sonnet-4-6[1m]": "claude-sonnet-5",
2592
+ // Bare Sonnet 5 is still schema-valid (stored configs keep parsing) but is
2593
+ // upgraded to the [1m]-suffixed ID at resolve time so the pinned CLI budgets
2594
+ // the real 1M window instead of its 200K unknown-model fallback.
2595
+ "claude-sonnet-5": "claude-sonnet-5[1m]",
2596
+ "claude-sonnet-4-6": "claude-sonnet-5[1m]",
2597
+ "claude-sonnet-4-6[1m]": "claude-sonnet-5[1m]",
2579
2598
  "claude-opus-4-6": "claude-opus-4-8",
2580
2599
  "claude-opus-4-6[1m]": "claude-opus-4-8[1m]",
2581
2600
  "claude-opus-4-7": "claude-opus-4-8",
2582
2601
  "claude-opus-4-7[1m]": "claude-opus-4-8[1m]"
2583
2602
  };
2584
2603
  function mapModelToClaudeModel(model) {
2604
+ const remapped = model != null && model !== "" ? LEGACY_MODEL_REMAP[model] : void 0;
2605
+ if (remapped) {
2606
+ return remapped;
2607
+ }
2585
2608
  if (model && CLAUDE_MODEL_IDS.includes(model)) {
2586
2609
  return model;
2587
2610
  }
2588
- const remapped = model != null && model !== "" ? LEGACY_MODEL_REMAP[model] : void 0;
2589
- return remapped ?? LEGACY_DEFAULT_MODEL;
2611
+ return LEGACY_DEFAULT_MODEL;
2590
2612
  }
2591
2613
  __name(mapModelToClaudeModel, "mapModelToClaudeModel");
2592
2614
  __name2(mapModelToClaudeModel, "mapModelToClaudeModel");
@@ -3186,7 +3208,63 @@ var clarityProcessListItemSchema = z15.object({
3186
3208
  contributors: z15.array(z15.object({ userId: z15.string(), userName: z15.string() })).optional(),
3187
3209
  createdAt: z15.coerce.date(),
3188
3210
  updatedAt: z15.coerce.date(),
3189
- createdByName: z15.string().optional()
3211
+ createdByName: z15.string().optional(),
3212
+ /** Team-scoped lists only; absent on org portfolio rows. */
3213
+ folderId: z15.guid().nullable().optional(),
3214
+ /**
3215
+ * Read-time folder suggestion: set when the process is unfiled and its
3216
+ * landscape leaf sits under a group node a team folder links to.
3217
+ */
3218
+ suggestedFolderId: z15.guid().nullable().optional()
3219
+ });
3220
+ var clarityProcessFolderSchema = z15.object({
3221
+ id: z15.guid(),
3222
+ teamId: z15.guid(),
3223
+ name: z15.string(),
3224
+ /** Linked landscape group node, or null for plain custom folders. */
3225
+ landscapeNodeId: z15.guid().nullable(),
3226
+ /** Once true, landscape group renames no longer propagate to this folder. */
3227
+ nameOverridden: z15.boolean(),
3228
+ sortOrder: z15.number().int(),
3229
+ createdAt: z15.coerce.date(),
3230
+ updatedAt: z15.coerce.date()
3231
+ });
3232
+ var clarityProcessFolderListItemSchema = clarityProcessFolderSchema.extend({
3233
+ processCount: z15.number(),
3234
+ /** Unfiled team processes whose landscape group matches this folder's link. */
3235
+ suggestedCount: z15.number()
3236
+ });
3237
+ var clarityProcessFolderListResponseSchema = z15.object({
3238
+ folders: z15.array(clarityProcessFolderListItemSchema)
3239
+ });
3240
+ var claritySuccessResponseSchema = z15.object({
3241
+ success: z15.boolean()
3242
+ });
3243
+ var clarityProcessFolderResponseSchema = z15.object({
3244
+ folder: clarityProcessFolderSchema
3245
+ });
3246
+ var clarityMoveProcessesToFolderResponseSchema = z15.object({
3247
+ movedCount: z15.number()
3248
+ });
3249
+ var claritySetupFoldersFromLandscapeResponseSchema = z15.object({
3250
+ folders: z15.array(clarityProcessFolderSchema),
3251
+ createdCount: z15.number()
3252
+ });
3253
+ var clarityFileSuggestedProcessesResponseSchema = z15.object({
3254
+ filedCount: z15.number()
3255
+ });
3256
+ var clarityLandscapeGroupSchema = z15.object({
3257
+ id: z15.guid(),
3258
+ name: z15.string(),
3259
+ sortOrder: z15.number().int(),
3260
+ processCount: z15.number()
3261
+ });
3262
+ var clarityLandscapeGroupListResponseSchema = z15.object({
3263
+ groups: z15.array(clarityLandscapeGroupSchema),
3264
+ /** Team processes whose landscape leaf sits under no group node. */
3265
+ unclassifiedCount: z15.number(),
3266
+ /** True when the bounded read could not return every group. */
3267
+ truncated: z15.boolean()
3190
3268
  });
3191
3269
  var CLARITY_PROCESS_LIST_ORDERS = [
3192
3270
  "updated_desc",
@@ -3337,7 +3415,9 @@ var clarityLandscapeCaptureRequestSchema = z15.object({
3337
3415
  });
3338
3416
  }
3339
3417
  });
3340
- var clarityProcessLandscapeNodeSchema = z15.object({
3418
+ var CLARITY_PROCESS_LANDSCAPE_REDACTED_NODE_HINT = "restricted_process";
3419
+ var clarityProcessLandscapeFullNodeSchema = z15.object({
3420
+ access: z15.literal("full"),
3341
3421
  id: z15.guid(),
3342
3422
  parentId: z15.guid().nullable(),
3343
3423
  processId: z15.guid().nullable(),
@@ -3360,7 +3440,27 @@ var clarityProcessLandscapeNodeSchema = z15.object({
3360
3440
  captureSuggestions: z15.array(clarityLandscapeCaptureSuggestionSchema).default([]),
3361
3441
  captureRequests: z15.array(clarityLandscapeCaptureRequestSchema).default([]),
3362
3442
  labels: z15.array(clarityProcessAssignedLabelSchema).default([])
3363
- });
3443
+ }).strict();
3444
+ var clarityProcessLandscapePublicNodeSchema = clarityProcessLandscapeFullNodeSchema.omit({ access: true }).partial({
3445
+ teamAssignmentSuggestions: true,
3446
+ captureSuggestions: true,
3447
+ captureRequests: true
3448
+ });
3449
+ var clarityProcessLandscapeRedactedNodeSchema = z15.object({
3450
+ access: z15.literal("redacted"),
3451
+ hint: z15.literal(CLARITY_PROCESS_LANDSCAPE_REDACTED_NODE_HINT),
3452
+ id: z15.guid(),
3453
+ parentId: z15.guid().nullable(),
3454
+ sortOrder: z15.number(),
3455
+ depth: z15.number()
3456
+ }).strict();
3457
+ var clarityProcessLandscapeNodeSchema = z15.discriminatedUnion(
3458
+ "access",
3459
+ [
3460
+ clarityProcessLandscapeFullNodeSchema,
3461
+ clarityProcessLandscapeRedactedNodeSchema
3462
+ ]
3463
+ );
3364
3464
  var clarityProcessLandscapeUnlinkedProcessSchema = clarityProcessLandscapeSummarySchema.extend({
3365
3465
  teamId: z15.guid(),
3366
3466
  teamName: z15.string().nullable(),
@@ -3372,7 +3472,8 @@ var clarityProcessLandscapeLinkSchema = z15.object({
3372
3472
  targetNodeId: z15.guid(),
3373
3473
  type: z15.enum(["hands_off_to", "shares_step_with", "variant_of"]),
3374
3474
  state: z15.enum(["suggested", "confirmed"]),
3375
- confidence: z15.number().nullable()
3475
+ confidence: z15.number().nullable(),
3476
+ rationale: z15.string().nullable().default(null)
3376
3477
  });
3377
3478
  var clarityProcessLandscapeStatsSchema = z15.object({
3378
3479
  totalNodes: z15.number(),
@@ -3381,14 +3482,25 @@ var clarityProcessLandscapeStatsSchema = z15.object({
3381
3482
  unsortedProcesses: z15.number(),
3382
3483
  latestUpdatedAt: z15.string().nullable()
3383
3484
  });
3485
+ var landscapeGenerationResultSummarySchema = z15.object({
3486
+ changed: z15.boolean(),
3487
+ createdNodeCount: z15.number().int().nonnegative(),
3488
+ reparentedNodeCount: z15.number().int().nonnegative(),
3489
+ attachedProcessCount: z15.number().int().nonnegative(),
3490
+ suggestedRelationshipCount: z15.number().int().nonnegative().default(0),
3491
+ unchangedWriteCount: z15.number().int().nonnegative(),
3492
+ failedWriteCount: z15.number().int().nonnegative()
3493
+ });
3384
3494
  var clarityProcessLandscapeGenerationSchema = z15.object({
3385
- eligibleCaptureCount: z15.number(),
3495
+ eligibleCaptureCount: z15.number().int().nonnegative(),
3496
+ eligibleProcessCount: z15.number().int().nonnegative(),
3386
3497
  status: z15.enum(["idle", "starting", "running", "completed", "failed"])
3387
3498
  });
3388
3499
  var generateClarityProcessLandscapeResponseSchema = z15.object({
3389
3500
  started: z15.literal(true),
3390
3501
  generationId: z15.guid(),
3391
- eligibleCaptureCount: z15.number()
3502
+ eligibleCaptureCount: z15.number().int().nonnegative(),
3503
+ eligibleProcessCount: z15.number().int().nonnegative()
3392
3504
  });
3393
3505
  var clarityProcessLandscapeResponseSchema = z15.object({
3394
3506
  nodes: z15.array(clarityProcessLandscapeNodeSchema),
@@ -3398,6 +3510,9 @@ var clarityProcessLandscapeResponseSchema = z15.object({
3398
3510
  generation: clarityProcessLandscapeGenerationSchema,
3399
3511
  truncated: z15.boolean()
3400
3512
  });
3513
+ var clarityProcessLandscapePublicResponseSchema = clarityProcessLandscapeResponseSchema.extend({
3514
+ nodes: z15.array(clarityProcessLandscapePublicNodeSchema)
3515
+ });
3401
3516
  var clarityProcessPersonSchema = z15.object({
3402
3517
  id: z15.guid(),
3403
3518
  userId: z15.guid().nullable(),
@@ -5011,7 +5126,14 @@ var clarityProcessLandscapeGenerationStatusChangedEventDataSchema = z21.object({
5011
5126
  status: clarityProcessLandscapeGenerationSchema.shape.status.exclude([
5012
5127
  "idle"
5013
5128
  ]),
5014
- error: z21.string().optional()
5129
+ result: landscapeGenerationResultSummarySchema.optional()
5130
+ });
5131
+ var clarityProcessLandscapeChangedEventDataSchema = z21.object({
5132
+ organizationId: z21.guid()
5133
+ });
5134
+ var clarityProcessLandscapeOrganizeStatusChangedEventDataSchema = z21.object({
5135
+ organizationId: z21.guid(),
5136
+ status: z21.enum(["completed", "failed"])
5015
5137
  });
5016
5138
  var clarityProcessLandscapeRoomPayloadSchema = z21.object({
5017
5139
  organizationId: z21.guid()
@@ -6892,7 +7014,6 @@ var integrationResponseSchema = z27.object({
6892
7014
  server_url: z27.string().optional(),
6893
7015
  transport_type: TransportTypeSchema.optional(),
6894
7016
  auth_method: z27.string().nullable().optional(),
6895
- composio_mcp_id: z27.string().nullable().default(null),
6896
7017
  custom_integration_id: z27.string().nullable().optional(),
6897
7018
  icon_url: z27.string().nullable().optional(),
6898
7019
  oauth_provider: z27.string().nullable().optional(),
@@ -6901,7 +7022,7 @@ var integrationResponseSchema = z27.object({
6901
7022
  * to start the OAuth flow via
6902
7023
  * `POST /v1/connections/oauth/native/:provider/start`. Derived
6903
7024
  * server-side from the integration `type`; null when no native provider
6904
- * exists for the type (default-provider, composio, custom MCP).
7025
+ * exists for the type (default-provider, custom MCP).
6905
7026
  */
6906
7027
  oauth_provider_key: z27.string().nullable().optional(),
6907
7028
  oauth_scopes: z27.array(z27.string()).nullable().optional(),
@@ -6990,15 +7111,6 @@ var checkDcrSupportResponseSchema = z27.object({
6990
7111
  var authorizationUrlResponseSchema = z27.object({
6991
7112
  authorization_url: z27.string().describe("OAuth provider authorization URL to open in a browser")
6992
7113
  });
6993
- var startComposioConnectionResponseSchema = z27.object({
6994
- redirect_url: z27.string().nullable().describe(
6995
- "Browser URL the user must visit to complete authorization. Null when the connection was completed synchronously (e.g. for API_KEY auth that did not require a browser flow)."
6996
- ),
6997
- status: z27.string().nullable().describe("Composio connection status, e.g. INITIATED or ACTIVE."),
6998
- connected_account_id: z27.string().describe(
6999
- "Composio connected-account ID, passed to /v1/connections/composio/finalize to complete the flow."
7000
- )
7001
- });
7002
7114
  var createCustomIntegrationRequestSchema = z27.object({
7003
7115
  name: z27.string().min(1, "Name is required"),
7004
7116
  auth_method: z27.enum(["url", "apikey", "headers", "oauth"]),
@@ -7035,7 +7147,6 @@ var updateIntegrationRequestSchema = z27.object({
7035
7147
  plaintext: z27.record(z27.string(), z27.string()).optional(),
7036
7148
  secret: z27.record(z27.string(), z27.string()).optional()
7037
7149
  }).nullable().optional(),
7038
- composio_mcp_id: z27.string().nullable().optional(),
7039
7150
  // Toggle team sharing. `true` makes the instance team-shared
7040
7151
  // (`user_id = NULL`); `false` reverts it to personal owned by the caller.
7041
7152
  // Rejected when the org-level "Connections sharing" setting is OFF and
@@ -7241,6 +7352,14 @@ var artifactVisibilitySchema = z31.enum([
7241
7352
  "teams"
7242
7353
  ]);
7243
7354
  var artifactPublishPermissionSchema = z31.enum(["view", "edit"]);
7355
+ var artifactRefreshFrequencySchema = z31.enum([
7356
+ "every_15_minutes",
7357
+ "every_30_minutes",
7358
+ "hourly",
7359
+ "every_6_hours",
7360
+ "daily",
7361
+ "weekly"
7362
+ ]);
7244
7363
  var artifactSchema = z31.object({
7245
7364
  id: z31.guid(),
7246
7365
  team_id: z31.guid(),
@@ -7263,6 +7382,13 @@ var artifactSchema = z31.object({
7263
7382
  // image. Optional so older/other clients (and fixtures) tolerate its absence;
7264
7383
  // the backend always includes it (string or null).
7265
7384
  thumbnail_url: z31.string().nullable().optional(),
7385
+ // Background auto-refresh cadence, or null when off. Optional so older
7386
+ // clients and fixtures tolerate its absence; the backend always includes it.
7387
+ refresh_frequency: artifactRefreshFrequencySchema.nullable().optional(),
7388
+ // When the last scheduled refresh was dispatched / the next one is due.
7389
+ // Null until a schedule is set (next) or has fired at least once (last).
7390
+ last_refresh_at: z31.string().nullable().optional(),
7391
+ next_refresh_at: z31.string().nullable().optional(),
7266
7392
  created_at: z31.string(),
7267
7393
  updated_at: z31.string()
7268
7394
  });
@@ -7391,8 +7517,12 @@ var answerArtifactQuestionResponseSchema = z31.object({
7391
7517
  ok: z31.literal(true)
7392
7518
  });
7393
7519
  var updateArtifactBodySchema = z31.object({
7394
- title: z31.string().trim().min(1).max(120)
7395
- }).strict();
7520
+ title: z31.string().trim().min(1).max(120).optional(),
7521
+ refresh_frequency: artifactRefreshFrequencySchema.nullable().optional()
7522
+ }).strict().refine(
7523
+ (body) => body.title !== void 0 || body.refresh_frequency !== void 0,
7524
+ { message: "At least one field is required" }
7525
+ );
7396
7526
  var publishArtifactBodySchema = z31.object({
7397
7527
  visibility: z31.enum(["private", "team", "organization"]),
7398
7528
  // The audience permission to apply when publishing. Applies to the Pulse's
@@ -8318,6 +8448,16 @@ var adminOrgAddMemberRequestSchema = z40.object({
8318
8448
  var adminOrgAddMemberResponseSchema = z40.object({
8319
8449
  member: adminOrgMemberSchema
8320
8450
  });
8451
+ var adminOrgInviteMemberRequestSchema = z40.object({
8452
+ email: z40.email(),
8453
+ role: z40.enum(ORG_ROLES.ALL),
8454
+ frontendUrl: z40.url().optional()
8455
+ });
8456
+ var adminOrgInviteMemberResponseSchema = z40.object({
8457
+ success: z40.literal(true),
8458
+ invitationId: z40.guid(),
8459
+ emailSent: z40.boolean()
8460
+ });
8321
8461
  var adminOrgUpdateMemberRoleRequestSchema = z40.object({
8322
8462
  role: z40.enum(ORG_ROLES.ALL)
8323
8463
  });
@@ -8696,6 +8836,7 @@ var agentApiSchema = z42.object({
8696
8836
  team_id: z42.string().nullable(),
8697
8837
  thread_id: z42.string().nullable(),
8698
8838
  folder_id: z42.string().nullable().optional(),
8839
+ automation_id: z42.guid().nullable().optional(),
8699
8840
  created_at: z42.string().nullable(),
8700
8841
  updated_at: z42.string().nullable(),
8701
8842
  created_by: z42.object({
@@ -9063,6 +9204,33 @@ var automationRevisionDetailResponseApiSchema = z50.object({
9063
9204
  var automationRevisionResponseApiSchema = z50.object({
9064
9205
  revision: automationRevisionSummaryApiSchema.describe("The revision summary")
9065
9206
  });
9207
+ var automationFlowAgentApiSchema = z50.object({
9208
+ id: z50.guid().describe("Agent identifier"),
9209
+ name: z50.string().describe("Agent name")
9210
+ });
9211
+ var automationFlowQueueApiSchema = z50.object({
9212
+ id: z50.guid().describe("Queue identifier"),
9213
+ name: z50.string().describe("Queue name (per-revision override or canonical)"),
9214
+ item_count: z50.int().describe("Active (non-deleted) case count in the queue"),
9215
+ producer_agent_ids: z50.array(z50.guid()).describe("Agents that add cases to this queue"),
9216
+ consumer_agent_ids: z50.array(z50.guid()).describe("Agents that process cases from this queue"),
9217
+ routed_consumer_agent_id: z50.guid().nullable().describe(
9218
+ "Consumer the revision routes new cases to (null when unrouted or disabled)"
9219
+ )
9220
+ });
9221
+ var automationFlowHandoverApiSchema = z50.object({
9222
+ source_agent_id: z50.guid().describe("Agent that hands work over"),
9223
+ target_agent_id: z50.guid().describe("Agent that receives the handover")
9224
+ });
9225
+ var automationFlowApiSchema = z50.object({
9226
+ revision_id: z50.guid().describe("Revision this flow was computed for"),
9227
+ agents: z50.array(automationFlowAgentApiSchema).describe("Agent nodes in the flow"),
9228
+ queues: z50.array(automationFlowQueueApiSchema).describe("Queue nodes in the flow"),
9229
+ handovers: z50.array(automationFlowHandoverApiSchema).describe("Agent \u2192 agent handover edges")
9230
+ });
9231
+ var automationFlowResponseApiSchema = z50.object({
9232
+ flow: automationFlowApiSchema.describe("The revision's flow graph")
9233
+ });
9066
9234
  var AUTOMATION_REVISION_NAME_MAX_LENGTH = 200;
9067
9235
  var AUTOMATION_REVISION_DESCRIPTION_MAX_LENGTH = 2e3;
9068
9236
  var revisionNameFieldSchema = z50.string().trim().min(1).max(AUTOMATION_REVISION_NAME_MAX_LENGTH);
@@ -9103,6 +9271,82 @@ var activateAutomationRevisionResponseApiSchema = z50.object({
9103
9271
  ),
9104
9272
  repinned_case_count: z50.int().describe("Number of pending cases re-pinned onto the activated revision")
9105
9273
  });
9274
+ var automationEntrypointRunApiSchema = z50.object({
9275
+ id: z50.guid().describe("Agent run ID of the entrypoint run"),
9276
+ agent_id: z50.guid().describe("Agent that ran"),
9277
+ build_id: z50.guid().describe("Build the run executed"),
9278
+ agent_name: z50.string().nullable().describe("Display name of the agent that ran"),
9279
+ status: agentRunStatusSchema.describe("Run status"),
9280
+ source: z50.string().nullable().describe("How the run was started (schedule, slack, manual, api, \u2026)"),
9281
+ automation_revision_id: z50.guid().nullable().describe("Revision the run was pinned to (null for legacy runs)"),
9282
+ run_count: z50.int().describe(
9283
+ "Total runs in this run's chain, including the entrypoint run itself"
9284
+ ),
9285
+ produced_case_count: z50.int().describe(
9286
+ "Cases produced by runs in this chain. Non-zero means the chain has something to expand even when run_count is 1 (an unclaimed produced case)"
9287
+ ),
9288
+ eval_summaries: evalSummarySchema.nullable().describe("Evaluation summary for the run, when available"),
9289
+ created_at: z50.string().describe("ISO 8601 creation timestamp"),
9290
+ started_at: z50.string().nullable().describe("ISO 8601 start timestamp"),
9291
+ completed_at: z50.string().nullable().describe("ISO 8601 completion timestamp"),
9292
+ updated_at: z50.string().describe("ISO 8601 last-modified timestamp")
9293
+ });
9294
+ var automationEntrypointRunsListApiSchema = z50.object({
9295
+ runs: z50.array(automationEntrypointRunApiSchema).describe("Entrypoint runs, newest first"),
9296
+ total: z50.int().describe("Total entrypoint runs matching the query"),
9297
+ limit: z50.int().describe("Page size used"),
9298
+ offset: z50.int().describe("Offset used")
9299
+ });
9300
+ var automationRunChainNodeApiSchema = z50.object({
9301
+ id: z50.guid().describe("Agent run ID"),
9302
+ agent_id: z50.guid().describe("Agent that ran"),
9303
+ build_id: z50.guid().describe("Build the run executed"),
9304
+ agent_name: z50.string().nullable().describe("Display name of the agent"),
9305
+ automation_revision_id: z50.guid().nullable().describe("Revision the run was pinned to (null for legacy runs)"),
9306
+ parent_agent_run_id: z50.guid().nullable().describe(
9307
+ "Run that directly caused this run (null for the entrypoint run)"
9308
+ ),
9309
+ parent_relationship: z50.string().nullable().describe(
9310
+ "Why this run was created from its parent (produced_case, handover, retry, \u2026)"
9311
+ ),
9312
+ status: agentRunStatusSchema.describe("Run status"),
9313
+ source: z50.string().nullable().describe("How the run was started"),
9314
+ case_queue_item_id: z50.guid().nullable().describe(
9315
+ "Case this run claimed, when it was triggered by claiming one (nests the run under that case in the tree)"
9316
+ ),
9317
+ eval_summaries: evalSummarySchema.nullable().describe("Evaluation summary for the run, when available"),
9318
+ created_at: z50.string().describe("ISO 8601 creation timestamp"),
9319
+ started_at: z50.string().nullable().describe("ISO 8601 start timestamp"),
9320
+ completed_at: z50.string().nullable().describe("ISO 8601 completion timestamp")
9321
+ });
9322
+ var automationRunChainCaseNodeApiSchema = z50.object({
9323
+ id: z50.guid().describe("Case (case_queue_item) ID"),
9324
+ title: z50.string().nullable().describe("Case title"),
9325
+ queue_id: z50.guid().describe("Queue the case belongs to"),
9326
+ queue_name: z50.string().nullable().describe("Display name of the queue the case was added to"),
9327
+ status: z50.enum([
9328
+ "pending",
9329
+ "in_progress",
9330
+ "needs_input",
9331
+ "postponed",
9332
+ "completed",
9333
+ "failed"
9334
+ ]).describe("Derived case display status"),
9335
+ producer_run_id: z50.guid().describe("Run that produced this case \u2014 its parent in the tree"),
9336
+ created_at: z50.string().describe("ISO 8601 creation timestamp")
9337
+ });
9338
+ var automationRunChainResponseApiSchema = z50.object({
9339
+ entrypoint_run_id: z50.guid().describe(
9340
+ "The chain's entrypoint run \u2014 resolved from the requested run, which may be any run in the chain"
9341
+ ),
9342
+ runs: z50.array(automationRunChainNodeApiSchema).describe("All runs in the chain, oldest first"),
9343
+ cases: z50.array(automationRunChainCaseNodeApiSchema).describe(
9344
+ "Cases produced by runs in the chain, each nested under its producer run"
9345
+ ),
9346
+ truncated: z50.boolean().describe(
9347
+ "True when the chain exceeded the server cap and only the first runs are returned, so the rendered tree is incomplete"
9348
+ )
9349
+ });
9106
9350
  var BROWSER_EGRESS_MODES = [
9107
9351
  "provider",
9108
9352
  "direct",
@@ -9695,6 +9939,10 @@ var caseQueueSchema = z60.object({
9695
9939
  // Optional (additive) so existing CaseQueue consumers and fixtures across the
9696
9940
  // FE/CLI don't break; the backend always populates it on real responses.
9697
9941
  automation_id: z60.guid().nullable().optional(),
9942
+ // Optional (additive), populated by the get-queue route. Consumers use it to
9943
+ // confirm a queue belongs to the acting team before building team-scoped
9944
+ // links (e.g. the automation-shell redirect resolver).
9945
+ team_id: z60.string().nullable().optional(),
9698
9946
  created_at: z60.string(),
9699
9947
  /**
9700
9948
  * True when at least one case in this queue has ever had an approval
@@ -9880,7 +10128,7 @@ var FEATURE_FLAG_CATALOGUE = {
9880
10128
  CASE_QUEUE_EVALS: {
9881
10129
  key: "case_queue_evals",
9882
10130
  defaultValue: false,
9883
- description: "Surfaces case-level evaluation rubrics in the FE: the queue's 'Evaluation rubrics' panel + 'why changed' transparency feed, and the per-case eval-outcome pill/panel. Backend generation + evaluation run regardless of this flag; it gates display only. DUVO-6203."
10131
+ description: "Enables automatic case-level evaluations and their supporting rubrics, plus the queue's 'Evaluation rubrics' panel, 'why changed' transparency feed, and per-case evaluation outcome. DUVO-6203."
9884
10132
  },
9885
10133
  AGENTIC_MEMORY_TEAM_WIDE: {
9886
10134
  key: "agentic_memory_team_wide",
@@ -9962,6 +10210,11 @@ var FEATURE_FLAG_CATALOGUE = {
9962
10210
  defaultValue: false,
9963
10211
  description: "Enables the Clarity meeting notetaker (Recall.ai bot). When disabled, the 'Meeting Notetaker' option is hidden in the Add Content menu and the POST /clarity/processes/:id/captures/meeting invite route returns 404; the Recall webhook callback is unaffected. Off-by-default for staged rollout."
9964
10212
  },
10213
+ CLARITY_REALTIME_SDP_PROXY: {
10214
+ key: "clarity_realtime_sdp_proxy",
10215
+ defaultValue: false,
10216
+ description: "Routes the Clarity interview WebRTC signaling (SDP offer/answer exchange) through the Duvo backend instead of the browser calling api.openai.com directly, so interviews can start on corporate networks that domain-block OpenAI. Voice/screen media still flows browser-to-OpenAI over WebRTC. Off-by-default for staged rollout; does not help networks that block UDP (those need a TURN relay)."
10217
+ },
9965
10218
  CLARITY_SIGNAVIO_SWIMLANES_EXPORT: {
9966
10219
  key: "clarity_signavio_swimlanes_export",
9967
10220
  defaultValue: false,
@@ -10047,6 +10300,11 @@ var FEATURE_FLAG_CATALOGUE = {
10047
10300
  defaultValue: false,
10048
10301
  description: "Enables portfolio intelligence analysis in the Clarity sidebar, providing cross-process insights and recommendations."
10049
10302
  },
10303
+ PULSE_SCHEDULED_REFRESH: {
10304
+ key: "pulse_scheduled_refresh",
10305
+ defaultValue: false,
10306
+ description: "Enables Pulse scheduled background auto-refresh: the Auto-refresh menu in the Pulse header, the `refresh_frequency` field on PATCH /artifacts/:id, and dispatching by the scheduled-refresh cron (already-armed schedules pause while off). The manual Refresh data button is unaffected. Off-by-default for staged rollout."
10307
+ },
10050
10308
  SHARED_CONNECTIONS: {
10051
10309
  key: "shared_connections",
10052
10310
  defaultValue: false,
@@ -11378,6 +11636,53 @@ function deriveHostnameFromInput(input) {
11378
11636
  }
11379
11637
  __name(deriveHostnameFromInput, "deriveHostnameFromInput");
11380
11638
  __name2(deriveHostnameFromInput, "deriveHostnameFromInput");
11639
+ function isHostLikeIdentifier(value) {
11640
+ const host = deriveHostnameFromInput(value);
11641
+ if (!host) {
11642
+ return false;
11643
+ }
11644
+ if (/\s/.test(host)) {
11645
+ return false;
11646
+ }
11647
+ return host.includes(".") || host === "localhost";
11648
+ }
11649
+ __name(isHostLikeIdentifier, "isHostLikeIdentifier");
11650
+ __name2(isHostLikeIdentifier, "isHostLikeIdentifier");
11651
+ function normalizeAppName(value) {
11652
+ return value.trim().toLowerCase().replace(/\s+/g, " ");
11653
+ }
11654
+ __name(normalizeAppName, "normalizeAppName");
11655
+ __name2(normalizeAppName, "normalizeAppName");
11656
+ function normalizeCredentialIdentifier(input) {
11657
+ const trimmed = (input || "").trim();
11658
+ if (!trimmed) {
11659
+ return "";
11660
+ }
11661
+ return isHostLikeIdentifier(trimmed) ? deriveDomain(trimmed) : trimmed;
11662
+ }
11663
+ __name(normalizeCredentialIdentifier, "normalizeCredentialIdentifier");
11664
+ __name2(normalizeCredentialIdentifier, "normalizeCredentialIdentifier");
11665
+ function identifiersMatch(a, b) {
11666
+ if (!a || !b) {
11667
+ return false;
11668
+ }
11669
+ const aIsHost = isHostLikeIdentifier(a);
11670
+ const bIsHost = isHostLikeIdentifier(b);
11671
+ if (aIsHost && bIsHost) {
11672
+ const hostA = deriveDomain(a);
11673
+ const hostB = deriveDomain(b);
11674
+ if (!hostA || !hostB) {
11675
+ return false;
11676
+ }
11677
+ return hostA === hostB || hostA.endsWith(`.${hostB}`) || hostB.endsWith(`.${hostA}`);
11678
+ }
11679
+ if (!aIsHost && !bIsHost) {
11680
+ return normalizeAppName(a) === normalizeAppName(b);
11681
+ }
11682
+ return false;
11683
+ }
11684
+ __name(identifiersMatch, "identifiersMatch");
11685
+ __name2(identifiersMatch, "identifiersMatch");
11381
11686
  var AGENT_MENTION_REGEX_SOURCE = `<DUVO:AGENT\\s+id="((?:[^"\\\\]|\\\\.)*)"\\s+name="((?:[^"\\\\]|\\\\.)*)">`;
11382
11687
  function unescapeAttrValue(value) {
11383
11688
  return value.replace(/\\(.)/g, "$1");
@@ -16187,7 +16492,6 @@ var integrationSchema = z89.object({
16187
16492
  server_url: z89.string().optional(),
16188
16493
  transport_type: z89.string().optional(),
16189
16494
  auth_method: z89.string().nullish(),
16190
- composio_mcp_id: z89.string().nullish(),
16191
16495
  custom_integration_id: z89.string().nullish(),
16192
16496
  icon_url: z89.string().nullish(),
16193
16497
  oauth_provider: z89.string().nullish(),
@@ -21308,7 +21612,8 @@ var processSummarySchema = z99.object({
21308
21612
  id: z99.string(),
21309
21613
  name: z99.string()
21310
21614
  }).passthrough();
21311
- var landscapeNodeSchema = z99.object({
21615
+ var landscapeFullNodeSchema = z99.object({
21616
+ access: z99.literal("full").default("full"),
21312
21617
  id: z99.string(),
21313
21618
  parentId: z99.string().nullable(),
21314
21619
  processId: z99.string().nullable(),
@@ -21316,6 +21621,18 @@ var landscapeNodeSchema = z99.object({
21316
21621
  ownerLabel: z99.string().nullable(),
21317
21622
  process: processSummarySchema.nullable()
21318
21623
  }).passthrough();
21624
+ var landscapeRedactedNodeSchema = z99.object({
21625
+ access: z99.literal("redacted"),
21626
+ hint: z99.literal("restricted_process"),
21627
+ id: z99.string(),
21628
+ parentId: z99.string().nullable(),
21629
+ sortOrder: z99.number(),
21630
+ depth: z99.number()
21631
+ }).strict();
21632
+ var landscapeNodeSchema = z99.union([
21633
+ landscapeFullNodeSchema,
21634
+ landscapeRedactedNodeSchema
21635
+ ]);
21319
21636
  var unlinkedProcessSchema = processSummarySchema.extend({
21320
21637
  teamId: z99.string(),
21321
21638
  teamName: z99.string().nullable()
@@ -21368,7 +21685,8 @@ var deleteNodeResponseSchema = z99.object({
21368
21685
  var generateLandscapeResponseSchema = z99.object({
21369
21686
  started: z99.literal(true),
21370
21687
  generationId: z99.string(),
21371
- eligibleCaptureCount: z99.number()
21688
+ eligibleCaptureCount: z99.number(),
21689
+ eligibleProcessCount: z99.number().int().nonnegative()
21372
21690
  }).passthrough();
21373
21691
  var captureSchema = z99.object({
21374
21692
  id: z99.string(),
@@ -21396,10 +21714,14 @@ var LANDSCAPE_COLUMNS = [
21396
21714
  maxWidth: 36
21397
21715
  },
21398
21716
  { header: "TYPE", cell: getLandscapeNodeType },
21399
- { header: "NAME", cell: /* @__PURE__ */ __name((row) => row.name, "cell"), maxWidth: 28 },
21717
+ {
21718
+ header: "NAME",
21719
+ cell: /* @__PURE__ */ __name((row) => row.access === "redacted" ? "Restricted process" : row.name, "cell"),
21720
+ maxWidth: 28
21721
+ },
21400
21722
  {
21401
21723
  header: "PROCESS",
21402
- cell: /* @__PURE__ */ __name((row) => row.process?.name ?? "-", "cell"),
21724
+ cell: /* @__PURE__ */ __name((row) => row.access === "redacted" ? "-" : row.process?.name ?? "-", "cell"),
21403
21725
  maxWidth: 28
21404
21726
  }
21405
21727
  ];
@@ -21543,7 +21865,7 @@ function registerClarityLandscape(clarity) {
21543
21865
  return;
21544
21866
  }
21545
21867
  console.log(
21546
- `Started process landscape generation: ${response.generationId} (${response.eligibleCaptureCount} captures)`
21868
+ `Started process landscape generation: ${response.generationId} (${response.eligibleProcessCount} processes, ${response.eligibleCaptureCount} optional captures)`
21547
21869
  );
21548
21870
  }, "generateAction"));
21549
21871
  landscape.command("captures").description("List Clarity captures eligible for the process landscape").option("--org <org-id>", ORG_FLAG_DESCRIPTION).option("--limit <n>", "page size").option("--include-transcripts", "include full transcripts in JSON output").option("--json", "output JSON").action(/* @__PURE__ */ __name(async function capturesAction(options) {
@@ -21563,7 +21885,7 @@ function registerClarityLandscape(clarity) {
21563
21885
  }
21564
21886
  renderCaptures(response, "No landscape captures found.");
21565
21887
  }, "capturesAction"));
21566
- landscape.command("propose-process").description("Propose a new process node in the Clarity process landscape").requiredOption("--name <name>", "proposed process name").option("--description <text>", "proposed process description").option("--parent <node-id>", "parent area node id").option("--org <org-id>", ORG_FLAG_DESCRIPTION).option("--json", "output JSON").action(/* @__PURE__ */ __name(async function proposeProcessAction(options) {
21888
+ landscape.command("propose-process").description("Create a process node in the Clarity process landscape").requiredOption("--name <name>", "process name").option("--description <text>", "process description").option("--parent <node-id>", "parent area node id").option("--team <team-id>", "owning team id").option("--org <org-id>", ORG_FLAG_DESCRIPTION).option("--json", "output JSON").action(/* @__PURE__ */ __name(async function proposeProcessAction(options) {
21567
21889
  const config = await requireAuthenticatedConfig(this);
21568
21890
  const path = resolveOrgPath(this, PROPOSED_PROCESSES_RESOURCE_PATH);
21569
21891
  const raw = await httpRequest({
@@ -21571,10 +21893,13 @@ function registerClarityLandscape(clarity) {
21571
21893
  path,
21572
21894
  apiKey: config.apiKey,
21573
21895
  apiBaseUrl: config.apiBaseUrl,
21574
- body: buildProposeProcessBody(options)
21896
+ body: buildProposeProcessBody({
21897
+ ...options,
21898
+ team: this.optsWithGlobals().team
21899
+ })
21575
21900
  });
21576
21901
  const node = nodeResponseSchema.parse(raw);
21577
- renderNodeMutationResult("Proposed process", node, options);
21902
+ renderNodeMutationResult("Process created", node, options);
21578
21903
  }, "proposeProcessAction"));
21579
21904
  }
21580
21905
  __name(registerClarityLandscape, "registerClarityLandscape");
@@ -21620,7 +21945,8 @@ function buildProposeProcessBody(options) {
21620
21945
  return {
21621
21946
  name: options.name,
21622
21947
  ...options.description !== void 0 ? { description: options.description } : {},
21623
- ...options.parent !== void 0 ? { parentId: options.parent } : {}
21948
+ ...options.parent !== void 0 ? { parentId: options.parent } : {},
21949
+ ...options.team !== void 0 ? { teamId: options.team } : {}
21624
21950
  };
21625
21951
  }
21626
21952
  __name(buildProposeProcessBody, "buildProposeProcessBody");
@@ -21746,6 +22072,9 @@ function renderNodeMutationResult(label, node, options) {
21746
22072
  }
21747
22073
  __name(renderNodeMutationResult, "renderNodeMutationResult");
21748
22074
  function searchableLandscapeNodeText(node) {
22075
+ if (node.access === "redacted") {
22076
+ return [node.id, node.parentId ?? ""];
22077
+ }
21749
22078
  return [
21750
22079
  node.id,
21751
22080
  node.parentId ?? "",
@@ -21758,6 +22087,9 @@ function searchableLandscapeNodeText(node) {
21758
22087
  }
21759
22088
  __name(searchableLandscapeNodeText, "searchableLandscapeNodeText");
21760
22089
  function getLandscapeNodeType(node) {
22090
+ if (node.access === "redacted") {
22091
+ return PROCESS_NODE_TYPE;
22092
+ }
21761
22093
  return node.processId ? PROCESS_NODE_TYPE : AREA_NODE_TYPE;
21762
22094
  }
21763
22095
  __name(getLandscapeNodeType, "getLandscapeNodeType");
@@ -22383,6 +22715,7 @@ var processLinkSchema = z101.object({
22383
22715
  type: processLinkTypeSchema,
22384
22716
  state: processLinkStateSchema,
22385
22717
  confidence: z101.number().nullable(),
22718
+ rationale: z101.string().nullable().default(null),
22386
22719
  created_at: z101.string(),
22387
22720
  updated_at: z101.string()
22388
22721
  });
@@ -22416,6 +22749,11 @@ var PROCESS_LINK_COLUMNS = [
22416
22749
  {
22417
22750
  header: "CONF",
22418
22751
  cell: /* @__PURE__ */ __name((row) => row.confidence === null ? "-" : row.confidence.toFixed(2), "cell")
22752
+ },
22753
+ {
22754
+ header: "RATIONALE",
22755
+ cell: /* @__PURE__ */ __name((row) => row.rationale ?? "-", "cell"),
22756
+ maxWidth: 60
22419
22757
  }
22420
22758
  ];
22421
22759
  function registerClarityProcessLinks(clarity) {
@@ -22582,6 +22920,9 @@ function renderProcessLinks(response) {
22582
22920
  return;
22583
22921
  }
22584
22922
  console.log(renderTable(PROCESS_LINK_COLUMNS, response.process_links));
22923
+ console.log(
22924
+ "Source and target nodes can belong to different teams in this organization."
22925
+ );
22585
22926
  console.log("");
22586
22927
  console.log(
22587
22928
  `Showing ${response.process_links.length} of ${response.total} \xB7 offset ${response.offset}`
@@ -23824,10 +24165,7 @@ function registerConnectionsUpdate(connections) {
23824
24165
  ...previous ?? [],
23825
24166
  value
23826
24167
  ]
23827
- ).option("--clear-headers", "remove all configured headers").option("--composio-mcp-id <id>", "associate a Composio MCP server ID").option(
23828
- "--clear-composio-mcp-id",
23829
- "remove the Composio MCP server association"
23830
- ).option("--share", "share this connection with the team (manager+ only)").option("--unshare", "revert this connection to personal").option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function updateAction(id, options) {
24168
+ ).option("--clear-headers", "remove all configured headers").option("--share", "share this connection with the team (manager+ only)").option("--unshare", "revert this connection to personal").option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function updateAction(id, options) {
23831
24169
  if (options.share && options.unshare) {
23832
24170
  throw new CliError("Pass either --share or --unshare, not both.");
23833
24171
  }
@@ -23836,11 +24174,6 @@ function registerConnectionsUpdate(connections) {
23836
24174
  "Pass either --clear-headers or --header / --secret-header, not both."
23837
24175
  );
23838
24176
  }
23839
- if (options.composioMcpId !== void 0 && Boolean(options.clearComposioMcpId)) {
23840
- throw new CliError(
23841
- "Pass either --composio-mcp-id or --clear-composio-mcp-id, not both."
23842
- );
23843
- }
23844
24177
  const body = {};
23845
24178
  if (options.name !== void 0) {
23846
24179
  const trimmed = options.name.trim();
@@ -23879,15 +24212,6 @@ function registerConnectionsUpdate(connections) {
23879
24212
  }
23880
24213
  body.headers = headers;
23881
24214
  }
23882
- if (options.composioMcpId !== void 0) {
23883
- const trimmed = options.composioMcpId.trim();
23884
- if (trimmed.length === 0) {
23885
- throw new CliError("--composio-mcp-id must not be empty");
23886
- }
23887
- body.composio_mcp_id = trimmed;
23888
- } else if (options.clearComposioMcpId) {
23889
- body.composio_mcp_id = null;
23890
- }
23891
24215
  if (options.share) {
23892
24216
  body.shared = true;
23893
24217
  } else if (options.unshare) {
@@ -23895,7 +24219,7 @@ function registerConnectionsUpdate(connections) {
23895
24219
  }
23896
24220
  if (Object.keys(body).length === 0) {
23897
24221
  throw new CliError(
23898
- "Provide at least one field to update (--name, --server-url, --auth-method, --header, --secret-header, --clear-headers, --composio-mcp-id, --clear-composio-mcp-id, --share, --unshare)."
24222
+ "Provide at least one field to update (--name, --server-url, --auth-method, --header, --secret-header, --clear-headers, --share, --unshare)."
23899
24223
  );
23900
24224
  }
23901
24225
  const { apiKey, apiBaseUrl } = await requireAuthenticatedConfig(this);
@@ -25562,184 +25886,6 @@ async function revokeOAuthProfile(profile) {
25562
25886
  }
25563
25887
  __name(revokeOAuthProfile, "revokeOAuthProfile");
25564
25888
 
25565
- // src/commands/oauth/composio/connect.ts
25566
- function registerOauthComposioConnect(composio) {
25567
- composio.command("connect").description(
25568
- "Finalize a Composio-backed connection after the start step has produced a connected_account_id."
25569
- ).requiredOption(
25570
- "--app <slug>",
25571
- "Composio app slug (e.g. 'slack', 'googlesheets')"
25572
- ).requiredOption(
25573
- "--name <name>",
25574
- "human-readable name to display for the connection"
25575
- ).requiredOption(
25576
- "--connected-account-id <id>",
25577
- "Composio connected-account ID returned by `duvo oauth composio start`"
25578
- ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function connectComposioAction(options) {
25579
- const config = await requireAuthenticatedConfig(this);
25580
- const { apiKey, apiBaseUrl } = config;
25581
- const teamId = await resolveRequiredTeamId(config, {
25582
- override: getTeamFlag(this)
25583
- });
25584
- if (!options.app || options.app.trim().length === 0) {
25585
- throw new CliError("--app must not be empty");
25586
- }
25587
- if (!options.name || options.name.trim().length === 0) {
25588
- throw new CliError("--name must not be empty");
25589
- }
25590
- if (!options.connectedAccountId || options.connectedAccountId.trim().length === 0) {
25591
- throw new CliError("--connected-account-id must not be empty");
25592
- }
25593
- const body = {
25594
- app: options.app.trim(),
25595
- integration_name: options.name.trim(),
25596
- connected_account_id: options.connectedAccountId.trim()
25597
- };
25598
- const raw = await httpRequest({
25599
- method: "POST",
25600
- path: buildTeamPath(teamId, "/connections/composio/finalize"),
25601
- apiKey,
25602
- apiBaseUrl,
25603
- body
25604
- });
25605
- if (options.json) {
25606
- printJson(raw);
25607
- return;
25608
- }
25609
- const parsed = connectIntegrationResponseSchema.safeParse(raw);
25610
- if (!parsed.success) {
25611
- throw new CliError(
25612
- `Unexpected response from the API: ${parsed.error.message}`
25613
- );
25614
- }
25615
- const { integration_id, mcp_url } = parsed.data;
25616
- console.log(green("Connection created!"));
25617
- console.log();
25618
- console.log(
25619
- renderKeyValue([
25620
- { label: "Integration ID", value: integration_id },
25621
- { label: "MCP URL", value: mcp_url }
25622
- ])
25623
- );
25624
- }, "connectComposioAction"));
25625
- }
25626
- __name(registerOauthComposioConnect, "registerOauthComposioConnect");
25627
-
25628
- // src/commands/oauth/composio/start.ts
25629
- function collectKeyValue(value, previous) {
25630
- return [...previous, value];
25631
- }
25632
- __name(collectKeyValue, "collectKeyValue");
25633
- function parseAuthFields(raw) {
25634
- if (!raw || raw.length === 0) {
25635
- return void 0;
25636
- }
25637
- const result = {};
25638
- for (const entry of raw) {
25639
- const index = entry.indexOf("=");
25640
- if (index <= 0) {
25641
- throw new CliError(
25642
- `--auth-field must be in KEY=VALUE format (got "${entry}")`
25643
- );
25644
- }
25645
- const key = entry.slice(0, index).trim();
25646
- const value = entry.slice(index + 1);
25647
- if (key.length === 0) {
25648
- throw new CliError(`--auth-field key must not be empty (got "${entry}")`);
25649
- }
25650
- result[key] = value;
25651
- }
25652
- return result;
25653
- }
25654
- __name(parseAuthFields, "parseAuthFields");
25655
- function registerOauthComposioStart(composio) {
25656
- composio.command("start").description(
25657
- "Start a Composio-backed OAuth connection. Returns a redirect URL to open in a browser; afterwards run `duvo oauth composio connect` to finalize."
25658
- ).requiredOption(
25659
- "--auth-config <id>",
25660
- "Composio auth-config ID for the toolkit"
25661
- ).requiredOption(
25662
- "--callback-url <url>",
25663
- "where to send the user's browser after they finish the Composio consent screen"
25664
- ).option(
25665
- "--auth-scheme <scheme>",
25666
- "Composio auth scheme (e.g. OAUTH2, API_KEY, BEARER_TOKEN); required when using --auth-field"
25667
- ).option(
25668
- "--auth-field <key=value>",
25669
- "auth field for non-OAuth schemes; repeat for multiple",
25670
- collectKeyValue,
25671
- []
25672
- ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function startComposioAction(options) {
25673
- const config = await requireAuthenticatedConfig(this);
25674
- const { apiKey, apiBaseUrl } = config;
25675
- const teamId = await resolveRequiredTeamId(config, {
25676
- override: getTeamFlag(this)
25677
- });
25678
- if (!options.authConfig || options.authConfig.trim().length === 0) {
25679
- throw new CliError("--auth-config must not be empty");
25680
- }
25681
- if (!options.callbackUrl || options.callbackUrl.trim().length === 0) {
25682
- throw new CliError("--callback-url must not be empty");
25683
- }
25684
- const authFields = parseAuthFields(options.authField);
25685
- const trimmedAuthScheme = options.authScheme?.trim();
25686
- if (authFields && !trimmedAuthScheme) {
25687
- throw new CliError(
25688
- "--auth-scheme is required when --auth-field is provided"
25689
- );
25690
- }
25691
- const body = {
25692
- auth_config_id: options.authConfig.trim(),
25693
- callback_url: options.callbackUrl.trim()
25694
- };
25695
- if (options.authScheme !== void 0) {
25696
- if (trimmedAuthScheme === void 0 || trimmedAuthScheme.length === 0) {
25697
- throw new CliError("--auth-scheme must not be empty");
25698
- }
25699
- body.auth_scheme = trimmedAuthScheme;
25700
- }
25701
- if (authFields) {
25702
- body.auth_fields = authFields;
25703
- }
25704
- const raw = await httpRequest({
25705
- method: "POST",
25706
- path: buildTeamPath(teamId, "/connections/composio/start"),
25707
- apiKey,
25708
- apiBaseUrl,
25709
- body
25710
- });
25711
- if (options.json) {
25712
- printJson(raw);
25713
- return;
25714
- }
25715
- const parsed = startComposioConnectionResponseSchema.safeParse(raw);
25716
- if (!parsed.success) {
25717
- throw new CliError(
25718
- `Unexpected response from the API: ${parsed.error.message}`
25719
- );
25720
- }
25721
- const { redirect_url, status, connected_account_id } = parsed.data;
25722
- console.log(
25723
- renderKeyValue([
25724
- { label: "Connected Account ID", value: connected_account_id },
25725
- { label: "Status", value: status ?? "" },
25726
- { label: "Redirect URL", value: redirect_url ?? "" }
25727
- ])
25728
- );
25729
- }, "startComposioAction"));
25730
- }
25731
- __name(registerOauthComposioStart, "registerOauthComposioStart");
25732
-
25733
- // src/commands/oauth/composio/index.ts
25734
- function registerOauthComposio(oauth) {
25735
- const composio = oauth.command("composio").description(
25736
- "Composio-backed OAuth flows. Run `start` to get a redirect URL, then `connect` to finalize."
25737
- );
25738
- registerOauthComposioStart(composio);
25739
- registerOauthComposioConnect(composio);
25740
- }
25741
- __name(registerOauthComposio, "registerOauthComposio");
25742
-
25743
25889
  // src/commands/oauth/mcp/authorize.ts
25744
25890
  function registerOauthMcpAuthorize(mcp) {
25745
25891
  mcp.command("authorize").description(
@@ -25864,10 +26010,10 @@ function registerOauthMcpCheck(mcp) {
25864
26010
  __name(registerOauthMcpCheck, "registerOauthMcpCheck");
25865
26011
 
25866
26012
  // src/commands/oauth/mcp/probe.ts
25867
- function collectKeyValue2(value, previous) {
26013
+ function collectKeyValue(value, previous) {
25868
26014
  return [...previous, value];
25869
26015
  }
25870
- __name(collectKeyValue2, "collectKeyValue");
26016
+ __name(collectKeyValue, "collectKeyValue");
25871
26017
  function parseHeaders(raw) {
25872
26018
  if (!raw || raw.length === 0) {
25873
26019
  return void 0;
@@ -25900,7 +26046,7 @@ function registerOauthMcpProbe(mcp) {
25900
26046
  ).option(
25901
26047
  "--header <key=value>",
25902
26048
  "optional HTTP header for authentication; repeat for multiple",
25903
- collectKeyValue2,
26049
+ collectKeyValue,
25904
26050
  []
25905
26051
  ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function probeMcpAction(url, options) {
25906
26052
  const trimmedUrl = url.trim();
@@ -26034,7 +26180,6 @@ __name(registerOauthNative, "registerOauthNative");
26034
26180
  function registerOauth(program) {
26035
26181
  const oauth = program.command("oauth").description("Start and probe OAuth flows for Duvo connections");
26036
26182
  registerOauthNative(oauth);
26037
- registerOauthComposio(oauth);
26038
26183
  registerOauthMcp(oauth);
26039
26184
  }
26040
26185
  __name(registerOauth, "registerOauth");
@@ -26757,6 +26902,7 @@ function registerPulseMessages(pulse) {
26757
26902
  __name(registerPulseMessages, "registerPulseMessages");
26758
26903
 
26759
26904
  // src/commands/pulse/move.ts
26905
+ var MOVE_REQUEST_TIMEOUT_MS = 12e4;
26760
26906
  function registerPulseMove(pulse) {
26761
26907
  pulse.command("move <id>").description(
26762
26908
  "Move a Pulse dashboard to another team. Only the latest version moves \u2014 chat, raw events, older versions, and member shares are deleted; you become the owner, visibility resets to private, and the dashboard's API key is rotated. Requires Manager or above on both teams."
@@ -26790,7 +26936,8 @@ function registerPulseMove(pulse) {
26790
26936
  apiKey,
26791
26937
  apiBaseUrl,
26792
26938
  searchParams,
26793
- body: { targetTeamId }
26939
+ body: { targetTeamId },
26940
+ timeoutMs: MOVE_REQUEST_TIMEOUT_MS
26794
26941
  });
26795
26942
  if (options.json) {
26796
26943
  printJson(raw);
@@ -26875,6 +27022,69 @@ function registerPulsePdf(pulse) {
26875
27022
  }
26876
27023
  __name(registerPulsePdf, "registerPulsePdf");
26877
27024
 
27025
+ // src/commands/pulse/refresh-schedule.ts
27026
+ var OFF = "off";
27027
+ var FREQUENCY_CHOICES = [...artifactRefreshFrequencySchema.options, OFF].join(
27028
+ ", "
27029
+ );
27030
+ function parseFrequency2(raw) {
27031
+ if (raw === OFF) {
27032
+ return null;
27033
+ }
27034
+ const parsed = artifactRefreshFrequencySchema.safeParse(raw);
27035
+ if (!parsed.success) {
27036
+ throw new CliError(`--frequency must be one of: ${FREQUENCY_CHOICES}.`);
27037
+ }
27038
+ return parsed.data;
27039
+ }
27040
+ __name(parseFrequency2, "parseFrequency");
27041
+ function registerPulseRefreshSchedule(pulse) {
27042
+ pulse.command("refresh-schedule <id>").description(
27043
+ "Set how often a Pulse dashboard auto-refreshes in the background (creator only)"
27044
+ ).requiredOption(
27045
+ "--frequency <frequency>",
27046
+ `the auto-refresh cadence: ${FREQUENCY_CHOICES}`
27047
+ ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function refreshScheduleAction(id, options) {
27048
+ const pulseId = trimRequired(id, "<id>");
27049
+ const frequency = parseFrequency2(
27050
+ trimRequired(options.frequency ?? "", "--frequency")
27051
+ );
27052
+ const { apiKey, apiBaseUrl } = await requireAuthenticatedConfig(this);
27053
+ const raw = await httpRequest({
27054
+ method: "PATCH",
27055
+ path: `/v2/artifacts/${encodeURIComponent(pulseId)}`,
27056
+ apiKey,
27057
+ apiBaseUrl,
27058
+ body: { refresh_frequency: frequency }
27059
+ });
27060
+ if (options.json) {
27061
+ printJson(raw);
27062
+ return;
27063
+ }
27064
+ const parsed = artifactSchema.safeParse(raw);
27065
+ if (!parsed.success) {
27066
+ throw new CliError(
27067
+ `Unexpected response from the API: ${parsed.error.message}`
27068
+ );
27069
+ }
27070
+ console.log(
27071
+ frequency ? green("Pulse auto-refresh scheduled.") : green("Pulse auto-refresh turned off.")
27072
+ );
27073
+ console.log();
27074
+ console.log(
27075
+ renderKeyValue([
27076
+ { label: "ID", value: parsed.data.id },
27077
+ { label: "Frequency", value: parsed.data.refresh_frequency ?? OFF },
27078
+ {
27079
+ label: "Next refresh",
27080
+ value: parsed.data.next_refresh_at ?? "\u2014"
27081
+ }
27082
+ ])
27083
+ );
27084
+ }, "refreshScheduleAction"));
27085
+ }
27086
+ __name(registerPulseRefreshSchedule, "registerPulseRefreshSchedule");
27087
+
26878
27088
  // src/commands/pulse/refresh.ts
26879
27089
  function registerPulseRefresh(pulse) {
26880
27090
  pulse.command("refresh <id>").description(
@@ -27242,6 +27452,7 @@ function registerPulse(program) {
27242
27452
  registerPulseStop(pulse);
27243
27453
  registerPulseRefresh(pulse);
27244
27454
  registerPulseRename(pulse);
27455
+ registerPulseRefreshSchedule(pulse);
27245
27456
  registerPulseShare(pulse);
27246
27457
  registerPulseDuplicate(pulse);
27247
27458
  registerPulseMove(pulse);
@@ -29544,7 +29755,7 @@ __name(registerSandboxes, "registerSandboxes");
29544
29755
 
29545
29756
  // src/commands/secrets/parse-key-value.ts
29546
29757
  var ENV_VAR_KEY_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
29547
- function collectKeyValue3(flag, raw, previous) {
29758
+ function collectKeyValue2(flag, raw, previous) {
29548
29759
  const equalsIndex = raw.indexOf("=");
29549
29760
  if (equalsIndex <= 0) {
29550
29761
  throw new CliError(`${flag} must be in the form KEY=VALUE (got "${raw}")`);
@@ -29564,7 +29775,7 @@ function collectKeyValue3(flag, raw, previous) {
29564
29775
  accumulator[key] = value;
29565
29776
  return accumulator;
29566
29777
  }
29567
- __name(collectKeyValue3, "collectKeyValue");
29778
+ __name(collectKeyValue2, "collectKeyValue");
29568
29779
  function collectRename(flag, raw, previous) {
29569
29780
  const equalsIndex = raw.indexOf("=");
29570
29781
  if (equalsIndex <= 0) {
@@ -29618,7 +29829,7 @@ function registerSecretsCreate(secrets) {
29618
29829
  ).option("--shared", "create as team-shared (requires manager role)").requiredOption(
29619
29830
  "--value <KEY=VALUE>",
29620
29831
  "env var to store (repeat for multiple)",
29621
- collectKeyValue3.bind(null, "--value"),
29832
+ collectKeyValue2.bind(null, "--value"),
29622
29833
  void 0
29623
29834
  ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function createAction(options) {
29624
29835
  const name = trimRequired(options.name ?? "", "--name");
@@ -29809,7 +30020,7 @@ function registerSecretsUpdate(secrets) {
29809
30020
  ).option("--name <name>", "new name").option("--service-slug <slug>", "set the service slug").option("--clear-service-slug", "remove the service slug").option("--shared", "promote to team-shared (requires manager role)").option("--personal", "demote to personal (requires manager role)").option(
29810
30021
  "--set <KEY=VALUE>",
29811
30022
  "add or overwrite an env var (repeatable)",
29812
- collectKeyValue3.bind(null, "--set"),
30023
+ collectKeyValue2.bind(null, "--set"),
29813
30024
  void 0
29814
30025
  ).option(
29815
30026
  "--remove <KEY>",
@@ -31313,11 +31524,63 @@ function registerTeamsOrg(teams) {
31313
31524
  }
31314
31525
  __name(registerTeamsOrg, "registerTeamsOrg");
31315
31526
 
31527
+ // src/commands/teams/orgs.ts
31528
+ import { z as z118 } from "zod";
31529
+ var orgMembershipSchema = z118.object({
31530
+ organization: z118.object({
31531
+ id: z118.string(),
31532
+ name: z118.string()
31533
+ }),
31534
+ role: z118.string(),
31535
+ memberCount: z118.number()
31536
+ });
31537
+ var listMyOrganizationsResponseSchema = z118.object({
31538
+ memberships: z118.array(orgMembershipSchema)
31539
+ });
31540
+ function registerTeamsOrgs(teams) {
31541
+ 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) {
31542
+ const { apiKey, apiBaseUrl } = await requireAuthenticatedConfig(this);
31543
+ const raw = await httpRequest({
31544
+ method: "GET",
31545
+ path: "/v2/organizations/mine",
31546
+ apiKey,
31547
+ apiBaseUrl
31548
+ });
31549
+ if (options.json) {
31550
+ printJson(raw);
31551
+ return;
31552
+ }
31553
+ const parsed = listMyOrganizationsResponseSchema.safeParse(raw);
31554
+ if (!parsed.success) {
31555
+ throw new CliError(
31556
+ `Unexpected response from GET /v2/organizations/mine: ${parsed.error.message}`
31557
+ );
31558
+ }
31559
+ if (parsed.data.memberships.length === 0) {
31560
+ console.log("You are not a member of any organization.");
31561
+ return;
31562
+ }
31563
+ console.log(
31564
+ renderTable(
31565
+ [
31566
+ { header: "ID", cell: /* @__PURE__ */ __name((m) => m.organization.id, "cell") },
31567
+ { header: "NAME", cell: /* @__PURE__ */ __name((m) => m.organization.name, "cell"), maxWidth: 40 },
31568
+ { header: "ROLE", cell: /* @__PURE__ */ __name((m) => m.role, "cell") },
31569
+ { header: "MEMBERS", cell: /* @__PURE__ */ __name((m) => String(m.memberCount), "cell") }
31570
+ ],
31571
+ parsed.data.memberships
31572
+ )
31573
+ );
31574
+ }, "orgsAction"));
31575
+ }
31576
+ __name(registerTeamsOrgs, "registerTeamsOrgs");
31577
+
31316
31578
  // src/commands/teams/index.ts
31317
31579
  function registerTeams(program) {
31318
31580
  const teams = program.command("teams").description("Inspect the teams your credentials can act on");
31319
31581
  registerTeamsList(teams);
31320
31582
  registerTeamsOrg(teams);
31583
+ registerTeamsOrgs(teams);
31321
31584
  registerTeamsOrgInsights(teams);
31322
31585
  registerTeamsOrgMetrics(teams);
31323
31586
  registerTeamsOrgUsage(teams);
@@ -31377,7 +31640,7 @@ __name(resolveActiveTeamId, "resolveActiveTeamId");
31377
31640
  var version = resolveVersion();
31378
31641
  function resolveVersion() {
31379
31642
  if (true) {
31380
- return "1.26.0";
31643
+ return "1.28.1";
31381
31644
  }
31382
31645
  const packageJsonPath = join3(
31383
31646
  dirname3(fileURLToPath2(import.meta.url)),
@@ -31571,7 +31834,7 @@ function isNewerVersion(candidate, current) {
31571
31834
  __name(isNewerVersion, "isNewerVersion");
31572
31835
  function loadPackageMeta() {
31573
31836
  if (true) {
31574
- return { name: "@duvoai/cli", version: "1.26.0" };
31837
+ return { name: "@duvoai/cli", version: "1.28.1" };
31575
31838
  }
31576
31839
  const require2 = createRequire(import.meta.url);
31577
31840
  const raw = require2("../package.json");