@duvoai/cli 1.74.0 → 1.75.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.
Files changed (2) hide show
  1. package/dist/bin/duvo.js +63 -68
  2. package/package.json +1 -1
package/dist/bin/duvo.js CHANGED
@@ -3726,8 +3726,9 @@ var rotateInterviewVoiceTokenResponseSchema = z10.object({
3726
3726
  providerConfig: voiceProviderConfigSchema
3727
3727
  });
3728
3728
  var WEBSOCKET_FALLBACK_MINT_REASON = "websocket-fallback";
3729
+ var TURN_RELAY_FALLBACK_MINT_REASON = "turn-relay-fallback";
3729
3730
  var rotateVoiceTokenQuerySchema = z10.object({
3730
- reason: z10.enum([WEBSOCKET_FALLBACK_MINT_REASON]).optional()
3731
+ reason: z10.enum([WEBSOCKET_FALLBACK_MINT_REASON, TURN_RELAY_FALLBACK_MINT_REASON]).optional()
3731
3732
  });
3732
3733
  var CLARITY_INTERVIEW_STATUSES = [
3733
3734
  "pending",
@@ -4209,7 +4210,7 @@ var clarityTransformationProposalSnapshotKindDetailResponseSchema = z12.object({
4209
4210
  snapshot: clarityTransformationProposalSnapshotKindApiSchema
4210
4211
  });
4211
4212
  var saveClarityProcessSnapshotBodySchema = z12.object({
4212
- steps: z12.array(clarityV1WritablePostprocessStepSchema).min(1).superRefine(refineStepGraph),
4213
+ steps: z12.array(postprocessClarityStepBaseSchema).min(1).superRefine(refineStepGraph),
4213
4214
  baselineSnapshotId: z12.guid(),
4214
4215
  clarityCurrentProcessId: z12.guid().optional(),
4215
4216
  ...swotAnalysisAgentCurrentProcessSchema.shape,
@@ -25317,8 +25318,9 @@ var rotateInterviewVoiceTokenResponseSchema2 = z342.object({
25317
25318
  providerConfig: voiceProviderConfigSchema2
25318
25319
  });
25319
25320
  var WEBSOCKET_FALLBACK_MINT_REASON2 = "websocket-fallback";
25321
+ var TURN_RELAY_FALLBACK_MINT_REASON2 = "turn-relay-fallback";
25320
25322
  var rotateVoiceTokenQuerySchema2 = z342.object({
25321
- reason: z342.enum([WEBSOCKET_FALLBACK_MINT_REASON2]).optional()
25323
+ reason: z342.enum([WEBSOCKET_FALLBACK_MINT_REASON2, TURN_RELAY_FALLBACK_MINT_REASON2]).optional()
25322
25324
  });
25323
25325
  var CLARITY_INTERVIEW_STATUSES2 = [
25324
25326
  "pending",
@@ -25800,7 +25802,7 @@ var clarityTransformationProposalSnapshotKindDetailResponseSchema2 = z362.object
25800
25802
  snapshot: clarityTransformationProposalSnapshotKindApiSchema2
25801
25803
  });
25802
25804
  var saveClarityProcessSnapshotBodySchema2 = z362.object({
25803
- steps: z362.array(clarityV1WritablePostprocessStepSchema2).min(1).superRefine(refineStepGraph2),
25805
+ steps: z362.array(postprocessClarityStepBaseSchema2).min(1).superRefine(refineStepGraph2),
25804
25806
  baselineSnapshotId: z362.guid(),
25805
25807
  clarityCurrentProcessId: z362.guid().optional(),
25806
25808
  ...swotAnalysisAgentCurrentProcessSchema2.shape,
@@ -26384,7 +26386,6 @@ function clarityStepsToEaseDocument(steps) {
26384
26386
  const stepOrder = steps.map((step) => step.id);
26385
26387
  const stepsById = Object.fromEntries(
26386
26388
  steps.map((step) => {
26387
- const serialized = serializeClarityStepForV12(step);
26388
26389
  const {
26389
26390
  id,
26390
26391
  readiness: _readiness,
@@ -26392,7 +26393,7 @@ function clarityStepsToEaseDocument(steps) {
26392
26393
  extraCaptureNeeded: _extraCaptureNeeded,
26393
26394
  linkedAgentId: _linkedAgentId,
26394
26395
  ...baseStep
26395
- } = serialized;
26396
+ } = step;
26396
26397
  return [id, baseStep];
26397
26398
  })
26398
26399
  );
@@ -26492,42 +26493,25 @@ __name(assertEaseDocument, "assertEaseDocument");
26492
26493
  __name3(assertEaseDocument, "assertEaseDocument");
26493
26494
  function materializeEaseDocument(easeDocument) {
26494
26495
  const ease = assertEaseDocument(easeDocument);
26496
+ const steps = postprocessClarityStepBaseSchema2.array().parse(
26497
+ coerceStepsOutput2(
26498
+ ease.stepOrder.map((stepId) => ({
26499
+ id: stepId,
26500
+ ...ease.stepsById[stepId]
26501
+ }))
26502
+ )
26503
+ );
26495
26504
  return {
26496
26505
  ...pickAllowedRoots(ease),
26497
- steps: ease.stepOrder.map(
26498
- (stepId) => legacyClarityStepBaseSchema2.parse(
26499
- coerceStepOutput2({
26500
- id: stepId,
26501
- ...ease.stepsById[stepId]
26502
- })
26503
- )
26504
- )
26506
+ steps
26505
26507
  };
26506
26508
  }
26507
26509
  __name(materializeEaseDocument, "materializeEaseDocument");
26508
26510
  __name3(materializeEaseDocument, "materializeEaseDocument");
26509
- function normalizeEaseOutput(output) {
26510
- return {
26511
- ...pickAllowedRoots(output),
26512
- steps: output.steps.map(
26513
- (step) => postprocessClarityStepBaseSchema2.parse(step)
26514
- )
26515
- };
26516
- }
26517
- __name(normalizeEaseOutput, "normalizeEaseOutput");
26518
- __name3(normalizeEaseOutput, "normalizeEaseOutput");
26519
26511
  function clarityOutputToEaseDocument(output) {
26520
- const stepOrder = output.steps.map((step) => step.id);
26521
- const stepsById = Object.fromEntries(
26522
- output.steps.map((step) => {
26523
- const { id, ...baseStep } = step;
26524
- return [id, baseStep];
26525
- })
26526
- );
26527
26512
  return {
26528
26513
  ...pickAllowedRoots(output),
26529
- stepOrder,
26530
- stepsById
26514
+ ...clarityStepsToEaseDocument(output.steps)
26531
26515
  };
26532
26516
  }
26533
26517
  __name(clarityOutputToEaseDocument, "clarityOutputToEaseDocument");
@@ -31406,9 +31390,10 @@ var toolExecutionPairSchema = z562.object({
31406
31390
  });
31407
31391
  var screenshotsTimelineResponseSchema = z562.object({
31408
31392
  toolExecutions: z562.array(toolExecutionPairSchema),
31409
- // Screenshots stored for the run, which exceeds the frames returned when the
31410
- // timeline is capped. Both fields are optional so a client parsing this
31411
- // schema still reads a response from a backend that predates the cap.
31393
+ // After-frames stored for the run, which can exceed the number returned when
31394
+ // the timeline is capped. The timeline reads only after-frames, not every
31395
+ // stored screenshot. Both fields are optional so a client parsing this schema
31396
+ // still reads a response from a backend that predates the cap.
31412
31397
  totalScreenshotCount: z562.number().int().nonnegative().optional(),
31413
31398
  truncated: z562.boolean().optional()
31414
31399
  });
@@ -36965,22 +36950,27 @@ var FEATURE_FLAG_CATALOGUE = {
36965
36950
  CLARITY_REALTIME_SDP_PROXY: {
36966
36951
  key: "clarity_realtime_sdp_proxy",
36967
36952
  defaultValue: false,
36968
- description: "Superseded by clarity_sdp_proxy_wss_fallback, which enables this and the WebSocket fallback together; still honoured on its own so teams already enabled keep working. 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)."
36953
+ description: "Read only while clarity_wss_first_transport is off (the INC-150 kill-switch path): superseded by clarity_sdp_proxy_wss_fallback, still honoured on its own so teams already enabled keep working. Routes interview WebRTC signaling through the Duvo backend. Retirement staged in #10298 once the kill switch itself retires."
36969
36954
  },
36970
36955
  CLARITY_INTERVIEW_WS_FALLBACK: {
36971
36956
  key: "clarity_interview_ws_fallback",
36972
36957
  defaultValue: false,
36973
- description: "Superseded by clarity_sdp_proxy_wss_fallback, which enables this and the SDP proxy together; still honoured on its own so teams already enabled keep working. Lets a Clarity interview fall back to a WebSocket transport when the WebRTC media path cannot be established, which is how networks that block UDP and raw TCP/443 fail today: signaling succeeds and the interview then dies with 'Connection lost'. The fallback is attempted once, only for that specific failure, and carries the full interview (audio both ways, screen frames, tools, interruption) over the same TLS connection the rest of the app uses. Off-by-default for staged rollout."
36958
+ description: "Read only while clarity_wss_first_transport is off (the INC-150 kill-switch path): superseded by clarity_sdp_proxy_wss_fallback, still honoured on its own. Arms the WebSocket fallback after a WebRTC media-path failure. Retirement staged in #10298 once the kill switch itself retires."
36974
36959
  },
36975
36960
  CLARITY_SDP_PROXY_WSS_FALLBACK: {
36976
36961
  key: "clarity_sdp_proxy_wss_fallback",
36977
- defaultValue: false,
36978
- description: "Enables the full enterprise-network transport ladder in one switch: SDP signaling is routed through the Duvo backend AND the interview may fall back to a WebSocket transport when the WebRTC media path cannot be established. The two halves address consecutive failures on the same restricted network \u2014 signaling blocked by domain filtering, then media blocked by UDP policy \u2014 and a network that needs one usually needs the other, so they roll out together. Supersedes clarity_realtime_sdp_proxy and clarity_interview_ws_fallback, which remain honoured independently so teams already on them keep working; either legacy flag still enables its own half. Off-by-default for staged rollout. Does not cover networks that block the OpenAI domain outright for media as well \u2014 those need the TURN relay."
36962
+ defaultValue: true,
36963
+ description: "Read only while clarity_wss_first_transport is off (the INC-150 kill-switch path): enables the SDP proxy and the WebSocket fallback together for the pre-ladder orchestration; an explicit false is that path's own kill switch and beats the superseded standalone keys. Retirement staged in #10298 once clarity_wss_first_transport itself retires."
36964
+ },
36965
+ CLARITY_WSS_FIRST_TRANSPORT: {
36966
+ key: "clarity_wss_first_transport",
36967
+ defaultValue: true,
36968
+ description: "Kill switch for the Clarity WSS-first transport ladder (default on): the OpenAI WebSocket transport first, relay-only WebRTC through the TURN relay when the socket cannot connect. An explicit false restores the pre-ladder orchestration \u2014 direct WebRTC first with the flag-gated WebSocket fallback \u2014 in minutes, without a revert release; INC-150 is why that path exists. Remove the flag and the legacy path one release after the ladder survives in prod."
36979
36969
  },
36980
36970
  CLARITY_TURN_RELAY_SPIKE: {
36981
36971
  key: "clarity_turn_relay_spike",
36982
36972
  defaultValue: false,
36983
- description: "Test-only spike that forces Clarity OpenAI Realtime WebRTC through an authenticated Duvo coturn relay. Requires isolated TURN environment configuration and fails closed when enabled without it. Never enable as a production rollout flag."
36973
+ description: "Per-team diagnostic that reorders the Clarity transport ladder to relay-first: WebRTC media through the authenticated Duvo coturn relay (turn.prd.duvo.ai) from the FIRST attempt, falling forward to the OpenAI WebSocket transport on a relay media failure. The default ladder is the inverse (socket first, relay on socket failure), so this flag exists for teams whose networks are known to need the relay immediately. Requires CLARITY_TURN_RELAY_URL and CLARITY_TURN_SHARED_SECRET, and fails the interview start when enabled without them. Keep per-team: the relay is a single capacity-limited VM (coturn total-quota caps concurrent sessions), and forcing it moves ALL of a team's media there rather than only socket-failed sessions."
36984
36974
  },
36985
36975
  CLARITY_SIGNAVIO_SWIMLANES_EXPORT: {
36986
36976
  key: "clarity_signavio_swimlanes_export",
@@ -49376,7 +49366,7 @@ var CLARITY_READ_TOOLS = [
49376
49366
  path: "/v2/organizations/:orgId/clarity/hierarchy/tree"
49377
49367
  }
49378
49368
  ],
49379
- description: "Read the raw Clarity process hierarchy tree."
49369
+ description: "Read the raw Clarity process hierarchy tree. Narrow a large organization with --root (one subtree) or --owner-team (one team's processes)."
49380
49370
  },
49381
49371
  {
49382
49372
  name: "getClarityHierarchyPeople",
@@ -49389,7 +49379,7 @@ var CLARITY_READ_TOOLS = [
49389
49379
  path: "/v2/organizations/:orgId/clarity/hierarchy/people"
49390
49380
  }
49391
49381
  ],
49392
- description: "Read the people on every process in the landscape in one request, with role, invite status, and capture counts."
49382
+ description: "Read the people on every process in the landscape in one request, with role, invite status, and capture counts. Narrow it with --root (one subtree), --owner-team (one owning team), and --user or --search (one person); filtering to a person and reading their capture counts answers who still owes a capture. Check `truncated` before treating the rows, or a count derived from them, as the whole answer: a landscape large enough to hit a cap reports a lower bound."
49393
49383
  },
49394
49384
  {
49395
49385
  name: "listClarityLandscapeNodePeople",
@@ -53564,7 +53554,10 @@ function registerClarityLandscape(clarity) {
53564
53554
  }
53565
53555
  renderLandscapeNodes(response.nodes, "No landscape nodes found.");
53566
53556
  }, "getAction"));
53567
- landscape.command("tree").description("Read the raw Clarity process tree").option("--org <org-id>", ORG_FLAG_DESCRIPTION2).option("--root <node-id>", "only read the subtree under this node").option("--json", "output JSON").action(/* @__PURE__ */ __name(async function treeAction(options) {
53557
+ landscape.command("tree").description("Read the raw Clarity process tree").option("--org <org-id>", ORG_FLAG_DESCRIPTION2).option("--root <node-id>", "only read the subtree under this node").option(
53558
+ "--owner-team <team-id>",
53559
+ "only read the process nodes owned by this team"
53560
+ ).option("--json", "output JSON").action(/* @__PURE__ */ __name(async function treeAction(options) {
53568
53561
  const config = await requireAuthenticatedConfig(this);
53569
53562
  const response = await loadTree(this, config, options);
53570
53563
  if (options.json) {
@@ -53575,7 +53568,13 @@ function registerClarityLandscape(clarity) {
53575
53568
  }, "treeAction"));
53576
53569
  landscape.command("people").description(
53577
53570
  "Read the people on every process in the landscape in one request"
53578
- ).option("--org <org-id>", ORG_FLAG_DESCRIPTION2).option("--root <node-id>", "only read the subtree under this node").option("--json", "output JSON").action(/* @__PURE__ */ __name(async function peopleAction(options) {
53571
+ ).option("--org <org-id>", ORG_FLAG_DESCRIPTION2).option("--root <node-id>", "only read the subtree under this node").option(
53572
+ "--owner-team <team-id>",
53573
+ "only read the rosters of processes owned by this team"
53574
+ ).option("--user <user-id>", "only read the rows for this platform user").option(
53575
+ "--search <text>",
53576
+ "only read the rows whose person name or email contains this text"
53577
+ ).option("--json", "output JSON").action(/* @__PURE__ */ __name(async function peopleAction(options) {
53579
53578
  const config = await requireAuthenticatedConfig(this);
53580
53579
  const response = await loadHierarchyPeople(this, config, options);
53581
53580
  if (options.json) {
@@ -53861,7 +53860,7 @@ async function loadLandscape(command, config, options) {
53861
53860
  __name(loadLandscape, "loadLandscape");
53862
53861
  async function loadTree(command, config, options) {
53863
53862
  const path = resolveOrgPath(command, TREE_RESOURCE_PATH);
53864
- const searchParams = buildRootSearchParams(options.root);
53863
+ const searchParams = buildLandscapeFilterSearchParams(options);
53865
53864
  const raw = await httpRequest({
53866
53865
  method: "GET",
53867
53866
  path,
@@ -53874,7 +53873,7 @@ async function loadTree(command, config, options) {
53874
53873
  __name(loadTree, "loadTree");
53875
53874
  async function loadHierarchyPeople(command, config, options) {
53876
53875
  const path = resolveOrgPath(command, PEOPLE_RESOURCE_PATH);
53877
- const searchParams = buildRootSearchParams(options.root);
53876
+ const searchParams = buildLandscapeFilterSearchParams(options);
53878
53877
  const raw = await httpRequest({
53879
53878
  method: "GET",
53880
53879
  path,
@@ -53903,6 +53902,20 @@ function buildRootSearchParams(rootId) {
53903
53902
  return searchParams;
53904
53903
  }
53905
53904
  __name(buildRootSearchParams, "buildRootSearchParams");
53905
+ function buildLandscapeFilterSearchParams(options) {
53906
+ const searchParams = buildRootSearchParams(options.root);
53907
+ for (const [key, value] of [
53908
+ ["ownerTeamId", options.ownerTeam],
53909
+ ["userId", options.user],
53910
+ ["search", options.search]
53911
+ ]) {
53912
+ if (value !== void 0) {
53913
+ searchParams.set(key, value);
53914
+ }
53915
+ }
53916
+ return searchParams;
53917
+ }
53918
+ __name(buildLandscapeFilterSearchParams, "buildLandscapeFilterSearchParams");
53906
53919
  function renderLandscapeNodes(nodes, emptyMessage) {
53907
53920
  if (nodes.length === 0) {
53908
53921
  console.log(emptyMessage);
@@ -55656,25 +55669,17 @@ function registerClaritySaveTransformationProposal(clarity) {
55656
55669
  }
55657
55670
  __name(registerClaritySaveTransformationProposal, "registerClaritySaveTransformationProposal");
55658
55671
  async function saveSnapshot(args) {
55659
- const wireSteps = args.body.steps.map(serializeClarityStepForV1);
55660
- const parsedBody = saveClarityProcessSnapshotBodySchema.safeParse({
55661
- ...args.body,
55662
- steps: wireSteps
55663
- });
55672
+ const parsedBody = saveClarityProcessSnapshotBodySchema.safeParse(args.body);
55664
55673
  if (!parsedBody.success) {
55665
55674
  throw new CliError(`Invalid snapshot edits: ${parsedBody.error.message}`);
55666
55675
  }
55667
55676
  const { apiKey, apiBaseUrl } = await requireAuthenticatedConfig(args.command);
55668
- const { steps: _steps, ...bodyFields } = parsedBody.data;
55669
55677
  const raw = await httpRequest({
55670
55678
  method: "POST",
55671
55679
  path: `/v2/clarity-v2/processes/${encodeURIComponent(args.processId)}/snapshots/${args.kind}/save`,
55672
55680
  apiKey,
55673
55681
  apiBaseUrl,
55674
- body: {
55675
- ...bodyFields,
55676
- steps: wireSteps
55677
- }
55682
+ body: parsedBody.data
55678
55683
  });
55679
55684
  if (args.json) {
55680
55685
  printJson(raw);
@@ -55721,16 +55726,6 @@ async function readSnapshotFile(path) {
55721
55726
  );
55722
55727
  }
55723
55728
  const snapshot = Array.isArray(parsed.data) ? { steps: parsed.data } : parsed.data;
55724
- try {
55725
- for (const step of snapshot.steps) {
55726
- serializeClarityStepForV1(step);
55727
- }
55728
- } catch (error) {
55729
- if (error instanceof ClarityV1RepresentationError) {
55730
- throw new CliError(`Invalid steps file "${path}": ${error.message}`);
55731
- }
55732
- throw error;
55733
- }
55734
55729
  return snapshot;
55735
55730
  }
55736
55731
  __name(readSnapshotFile, "readSnapshotFile");
@@ -68500,7 +68495,7 @@ __name(isStandaloneBinary, "isStandaloneBinary");
68500
68495
  import { createRequire } from "node:module";
68501
68496
  function getPackageMeta() {
68502
68497
  if (true) {
68503
- return { name: "@duvoai/cli", version: "1.74.0" };
68498
+ return { name: "@duvoai/cli", version: "1.75.0" };
68504
68499
  }
68505
68500
  const require2 = createRequire(import.meta.url);
68506
68501
  const raw = require2("../../package.json");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duvoai/cli",
3
- "version": "1.74.0",
3
+ "version": "1.75.0",
4
4
  "description": "Command-line interface for the Duvo public API",
5
5
  "bin": {
6
6
  "duvo": "./dist/bin/duvo.js"