@duvoai/cli 1.8.0 → 1.9.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
@@ -2047,12 +2047,8 @@ var PLATFORM_DEFAULT_MODELS = {
2047
2047
  var CLAUDE_MODEL_IDS = [
2048
2048
  "claude-sonnet-4-6",
2049
2049
  "claude-sonnet-4-6[1m]",
2050
- "claude-opus-4-6",
2051
- "claude-opus-4-6[1m]",
2052
- "claude-opus-4-7",
2053
- "claude-opus-4-7[1m]",
2054
- "claude-fable-5",
2055
- "claude-fable-5[1m]"
2050
+ "claude-opus-4-8",
2051
+ "claude-opus-4-8[1m]"
2056
2052
  ];
2057
2053
  var LEGACY_MODEL_IDS = [
2058
2054
  // Old duvo wrapper aliases
@@ -2075,7 +2071,13 @@ var LEGACY_MODEL_IDS = [
2075
2071
  "claude-sonnet-4-5-20250929",
2076
2072
  "claude-sonnet-4-5-20250929[1m]",
2077
2073
  "claude-opus-4-1-20250805",
2078
- "claude-opus-4-5-20251101"
2074
+ "claude-opus-4-5-20251101",
2075
+ // Retired in favour of Opus 4.8 (migrated via LEGACY_MODEL_REMAP, not the
2076
+ // Sonnet default)
2077
+ "claude-opus-4-6",
2078
+ "claude-opus-4-6[1m]",
2079
+ "claude-opus-4-7",
2080
+ "claude-opus-4-7[1m]"
2079
2081
  ];
2080
2082
  var ClaudeModelIdSchema = z12.enum([
2081
2083
  ...CLAUDE_MODEL_IDS,
@@ -2089,29 +2091,13 @@ var AVAILABLE_AGENT_MODELS = {
2089
2091
  displayName: "Claude Sonnet 4.6",
2090
2092
  description: "Fast and capable for everyday tasks"
2091
2093
  },
2092
- "claude-opus-4-6": {
2093
- displayName: "Claude Opus 4.6",
2094
- description: "Advanced model for complex work"
2095
- },
2096
- "claude-opus-4-6[1m]": {
2097
- displayName: "Claude Opus 4.6",
2098
- description: "Advanced model for complex work"
2099
- },
2100
- "claude-opus-4-7": {
2101
- displayName: "Claude Opus 4.7",
2094
+ "claude-opus-4-8": {
2095
+ displayName: "Claude Opus 4.8",
2102
2096
  description: "Our most capable model \u2014 best for complex work"
2103
2097
  },
2104
- "claude-opus-4-7[1m]": {
2105
- displayName: "Claude Opus 4.7",
2098
+ "claude-opus-4-8[1m]": {
2099
+ displayName: "Claude Opus 4.8",
2106
2100
  description: "Our most capable model \u2014 best for complex work"
2107
- },
2108
- "claude-fable-5": {
2109
- displayName: "Claude Fable 5",
2110
- description: "Our most powerful model for the most demanding work"
2111
- },
2112
- "claude-fable-5[1m]": {
2113
- displayName: "Claude Fable 5",
2114
- description: "Our most powerful model for the most demanding work"
2115
2101
  }
2116
2102
  };
2117
2103
  var BrowsingModelIdSchema = z12.enum([
@@ -2123,19 +2109,21 @@ var BrowsingModelIdSchema = z12.enum([
2123
2109
  "claude-opus-4-1"
2124
2110
  ]);
2125
2111
  var LEGACY_DEFAULT_MODEL = "claude-sonnet-4-6[1m]";
2112
+ var LEGACY_MODEL_REMAP = {
2113
+ "claude-opus-4-6": "claude-opus-4-8",
2114
+ "claude-opus-4-6[1m]": "claude-opus-4-8[1m]",
2115
+ "claude-opus-4-7": "claude-opus-4-8",
2116
+ "claude-opus-4-7[1m]": "claude-opus-4-8[1m]"
2117
+ };
2126
2118
  function mapModelToClaudeModel(model) {
2127
2119
  if (model && CLAUDE_MODEL_IDS.includes(model)) {
2128
2120
  return model;
2129
2121
  }
2130
- return LEGACY_DEFAULT_MODEL;
2122
+ const remapped = model != null && model !== "" ? LEGACY_MODEL_REMAP[model] : void 0;
2123
+ return remapped ?? LEGACY_DEFAULT_MODEL;
2131
2124
  }
2132
2125
  __name(mapModelToClaudeModel, "mapModelToClaudeModel");
2133
2126
  __name2(mapModelToClaudeModel, "mapModelToClaudeModel");
2134
- function isFableModelId(model) {
2135
- return model != null && model.startsWith("claude-fable-5");
2136
- }
2137
- __name(isFableModelId, "isFableModelId");
2138
- __name2(isFableModelId, "isFableModelId");
2139
2127
  function isLegacyModelId(model) {
2140
2128
  return model != null && model !== "" && !CLAUDE_MODEL_IDS.includes(model);
2141
2129
  }
@@ -2946,6 +2934,98 @@ var clarityProcessLandscapeSummarySchema = z13.object({
2946
2934
  contributors: z13.array(clarityProcessContributorSchema),
2947
2935
  updatedAt: z13.coerce.date()
2948
2936
  });
2937
+ var clarityLandscapeAssignedTeamSchema = z13.object({
2938
+ id: z13.guid(),
2939
+ name: z13.string()
2940
+ });
2941
+ var CLARITY_LANDSCAPE_SUGGESTION_STATUSES = [
2942
+ "pending",
2943
+ "accepted",
2944
+ "dismissed"
2945
+ ];
2946
+ var clarityLandscapeSuggestionStatusSchema = z13.enum(
2947
+ CLARITY_LANDSCAPE_SUGGESTION_STATUSES
2948
+ );
2949
+ var clarityLandscapeTeamAssignmentSuggestionSchema = z13.object({
2950
+ id: z13.guid(),
2951
+ suggestedTeamId: z13.guid().nullable(),
2952
+ suggestedTeamName: z13.string(),
2953
+ confidence: z13.number().min(0).max(1),
2954
+ rationale: z13.string(),
2955
+ status: clarityLandscapeSuggestionStatusSchema,
2956
+ createdAt: z13.string()
2957
+ });
2958
+ var clarityLandscapeCaptureSuggestionSchema = z13.object({
2959
+ id: z13.guid(),
2960
+ suggestedUserId: z13.guid().nullable(),
2961
+ suggestedUserName: z13.string().nullable(),
2962
+ suggestedTeamId: z13.guid().nullable(),
2963
+ suggestedTeamName: z13.string().nullable(),
2964
+ gap: z13.string().min(1),
2965
+ suggestedPrompt: z13.string().nullable(),
2966
+ confidence: z13.number().min(0).max(1),
2967
+ rationale: z13.string().min(1),
2968
+ status: clarityLandscapeSuggestionStatusSchema,
2969
+ createdAt: z13.string()
2970
+ }).superRefine((suggestion, ctx) => {
2971
+ const hasSuggestedUser = suggestion.suggestedUserId !== null || suggestion.suggestedUserName !== null;
2972
+ const hasSuggestedTeam = suggestion.suggestedTeamId !== null || suggestion.suggestedTeamName !== null;
2973
+ if (!hasSuggestedUser && !hasSuggestedTeam) {
2974
+ ctx.addIssue({
2975
+ code: "custom",
2976
+ message: "Capture suggestion must include a suggested user or team"
2977
+ });
2978
+ }
2979
+ if (suggestion.suggestedUserId === null !== (suggestion.suggestedUserName === null)) {
2980
+ ctx.addIssue({
2981
+ code: "custom",
2982
+ message: "Suggested user id and name must be provided together",
2983
+ path: ["suggestedUserId"]
2984
+ });
2985
+ }
2986
+ if (suggestion.suggestedTeamId === null !== (suggestion.suggestedTeamName === null)) {
2987
+ ctx.addIssue({
2988
+ code: "custom",
2989
+ message: "Suggested team id and name must be provided together",
2990
+ path: ["suggestedTeamId"]
2991
+ });
2992
+ }
2993
+ });
2994
+ var CLARITY_LANDSCAPE_CAPTURE_REQUEST_STATUSES = [
2995
+ "open",
2996
+ "completed",
2997
+ "cancelled"
2998
+ ];
2999
+ var clarityLandscapeCaptureRequestStatusSchema = z13.enum(
3000
+ CLARITY_LANDSCAPE_CAPTURE_REQUEST_STATUSES
3001
+ );
3002
+ var clarityLandscapeCaptureRequestSchema = z13.object({
3003
+ id: z13.guid(),
3004
+ requestedUserId: z13.guid().nullable(),
3005
+ requestedUserName: z13.string().nullable(),
3006
+ assignedByUserId: z13.guid().nullable().optional(),
3007
+ requestedTeamId: z13.guid().nullable(),
3008
+ requestedTeamName: z13.string().nullable(),
3009
+ gap: z13.string().min(1),
3010
+ prompt: z13.string().nullable(),
3011
+ status: clarityLandscapeCaptureRequestStatusSchema,
3012
+ createdAt: z13.string()
3013
+ }).superRefine((request, ctx) => {
3014
+ if (request.requestedUserId === null !== (request.requestedUserName === null)) {
3015
+ ctx.addIssue({
3016
+ code: "custom",
3017
+ message: "Requested user id and name must be provided together",
3018
+ path: ["requestedUserId"]
3019
+ });
3020
+ }
3021
+ if (request.requestedTeamId === null !== (request.requestedTeamName === null)) {
3022
+ ctx.addIssue({
3023
+ code: "custom",
3024
+ message: "Requested team id and name must be provided together",
3025
+ path: ["requestedTeamId"]
3026
+ });
3027
+ }
3028
+ });
2949
3029
  var clarityProcessLandscapeNodeSchema = z13.object({
2950
3030
  id: z13.guid(),
2951
3031
  parentId: z13.guid().nullable(),
@@ -2962,7 +3042,15 @@ var clarityProcessLandscapeNodeSchema = z13.object({
2962
3042
  source: z13.enum(["ai", "human"]),
2963
3043
  createdAt: z13.string(),
2964
3044
  updatedAt: z13.string(),
2965
- process: clarityProcessLandscapeSummarySchema.nullable()
3045
+ process: clarityProcessLandscapeSummarySchema.nullable(),
3046
+ scope: z13.enum(["team", "organization"]).optional(),
3047
+ teamId: z13.guid().nullable().optional(),
3048
+ teamName: z13.string().nullable().optional(),
3049
+ assignedTeam: clarityLandscapeAssignedTeamSchema.nullable().optional(),
3050
+ assignedTeams: z13.array(z13.object({ teamId: z13.guid(), teamName: z13.string().nullable() })).optional(),
3051
+ teamAssignmentSuggestions: z13.array(clarityLandscapeTeamAssignmentSuggestionSchema).optional(),
3052
+ captureSuggestions: z13.array(clarityLandscapeCaptureSuggestionSchema).optional(),
3053
+ captureRequests: z13.array(clarityLandscapeCaptureRequestSchema).optional()
2966
3054
  });
2967
3055
  var clarityProcessLandscapeLinkSchema = z13.object({
2968
3056
  id: z13.guid(),
@@ -5418,7 +5506,7 @@ var artifactRevisionSchema = z24.object({
5418
5506
  created_at: z24.string()
5419
5507
  });
5420
5508
  var artifactRevisionListResponseSchema = z24.object({
5421
- data: z24.array(artifactRevisionSchema),
5509
+ revisions: z24.array(artifactRevisionSchema),
5422
5510
  total: z24.number(),
5423
5511
  // The live "head" version — what the dashboard currently shows and what the
5424
5512
  // next turn continues from by default. Null while the first turn is in flight.
@@ -5426,7 +5514,7 @@ var artifactRevisionListResponseSchema = z24.object({
5426
5514
  current_version: z24.number().int().positive().nullable()
5427
5515
  });
5428
5516
  var restoreArtifactRevisionResponseSchema = z24.object({
5429
- ok: z24.literal(true),
5517
+ success: z24.literal(true),
5430
5518
  // The version now live (the head was moved here; nothing is copied or lost).
5431
5519
  current_revision_id: z24.guid(),
5432
5520
  current_version: z24.number().int().positive()
@@ -7860,11 +7948,6 @@ var FEATURE_FLAG_CATALOGUE = {
7860
7948
  defaultValue: false,
7861
7949
  description: "Enables the Move Agent to another team flow. Default-off while we monitor multi-table move semantics in prod; flip on for individual teams to grant access."
7862
7950
  },
7863
- FABLE_MODEL: {
7864
- key: "fable_model",
7865
- defaultValue: false,
7866
- description: "Grants a team access to Claude Fable 5 in the agent model selector. Fable is premium-priced (2x Opus per token, ~30% more tokens from its new tokenizer), so it stays off by default and is flipped on per team. The runtime re-checks the flag at dispatch and falls back to the platform default model when a stored config requests Fable for a team whose flag is off."
7867
- },
7868
7951
  TEAM_ONTOLOGY: {
7869
7952
  key: "team_ontology",
7870
7953
  defaultValue: false,
@@ -9384,12 +9467,10 @@ __name2(extractIntegrationTypeFromServerLabel, "extractIntegrationTypeFromServer
9384
9467
  function normalizeToEditableConfig(config) {
9385
9468
  const hasNestedModels = "models" in config && config.models?.agent !== void 0;
9386
9469
  if (hasNestedModels && config.models) {
9387
- const rawModel = config.models.agent.model;
9388
- const isValidCoreModel = !!rawModel && CLAUDE_MODEL_IDS.includes(rawModel);
9389
9470
  return {
9390
9471
  models: {
9391
9472
  agent: {
9392
- model: isValidCoreModel ? rawModel : LEGACY_DEFAULT_MODEL
9473
+ model: mapModelToClaudeModel(config.models.agent.model)
9393
9474
  },
9394
9475
  browsing: {
9395
9476
  provider: config.models.browsing?.provider ?? PLATFORM_DEFAULT_MODELS.browsing.provider,
@@ -12660,7 +12741,7 @@ async function resolveModel(flag) {
12660
12741
  }
12661
12742
  if (!isInteractiveTerminal()) {
12662
12743
  throw new CliError(
12663
- "--model is required in non-interactive shells (e.g. --model claude-opus-4-7)."
12744
+ "--model is required in non-interactive shells (e.g. --model claude-opus-4-8)."
12664
12745
  );
12665
12746
  }
12666
12747
  const answer = await select({
@@ -22201,7 +22282,7 @@ function registerPulseCreate(pulse) {
22201
22282
  const { apiKey, apiBaseUrl } = await requireAuthenticatedConfig(this);
22202
22283
  const raw = await httpRequest({
22203
22284
  method: "POST",
22204
- path: "/v1/artifacts",
22285
+ path: "/v2/artifacts",
22205
22286
  apiKey,
22206
22287
  apiBaseUrl,
22207
22288
  body: { message }
@@ -22237,7 +22318,7 @@ function registerPulseDelete(pulse) {
22237
22318
  });
22238
22319
  const raw = await httpRequest({
22239
22320
  method: "DELETE",
22240
- path: `/v1/artifacts/${encodeURIComponent(pulseId)}`,
22321
+ path: `/v2/artifacts/${encodeURIComponent(pulseId)}`,
22241
22322
  apiKey,
22242
22323
  apiBaseUrl
22243
22324
  });
@@ -22263,7 +22344,7 @@ function registerPulseGet(pulse) {
22263
22344
  const { apiKey, apiBaseUrl } = await requireAuthenticatedConfig(this);
22264
22345
  const raw = await httpRequest({
22265
22346
  method: "GET",
22266
- path: `/v1/artifacts/${encodeURIComponent(pulseId)}`,
22347
+ path: `/v2/artifacts/${encodeURIComponent(pulseId)}`,
22267
22348
  apiKey,
22268
22349
  apiBaseUrl
22269
22350
  });
@@ -22305,12 +22386,16 @@ __name(registerPulseGet, "registerPulseGet");
22305
22386
  function registerPulseHtml(pulse) {
22306
22387
  pulse.command("html <id>").description(
22307
22388
  "Print a Pulse dashboard's rendered HTML document to stdout (pipe to a file or browser)"
22308
- ).action(/* @__PURE__ */ __name(async function htmlAction(id) {
22389
+ ).option(
22390
+ "--version <version-id>",
22391
+ "render a specific historical version instead of the live one (see `duvo pulse versions`)"
22392
+ ).action(/* @__PURE__ */ __name(async function htmlAction(id, options) {
22309
22393
  const pulseId = trimRequired(id, "<id>");
22310
22394
  const { apiKey, apiBaseUrl } = await requireAuthenticatedConfig(this);
22395
+ const path = options.version ? `/v2/artifacts/${encodeURIComponent(pulseId)}/revisions/${encodeURIComponent(options.version)}/render` : `/v2/artifacts/${encodeURIComponent(pulseId)}/render`;
22311
22396
  const raw = await httpRequest({
22312
22397
  method: "GET",
22313
- path: `/v1/artifacts/${encodeURIComponent(pulseId)}/render`,
22398
+ path,
22314
22399
  apiKey,
22315
22400
  apiBaseUrl
22316
22401
  });
@@ -22356,7 +22441,7 @@ function registerPulseList(pulse) {
22356
22441
  searchParams.append("offset", String(offset));
22357
22442
  const raw = await httpRequest({
22358
22443
  method: "GET",
22359
- path: "/v1/artifacts",
22444
+ path: "/v2/artifacts",
22360
22445
  apiKey,
22361
22446
  apiBaseUrl,
22362
22447
  searchParams
@@ -22384,6 +22469,40 @@ function registerPulseList(pulse) {
22384
22469
  }
22385
22470
  __name(registerPulseList, "registerPulseList");
22386
22471
 
22472
+ // src/commands/pulse/restore.ts
22473
+ function registerPulseRestore(pulse) {
22474
+ pulse.command("restore <id> <version-id>").description(
22475
+ "Restore a previous version of a dashboard, making it live again (creator only). Non-destructive \u2014 list versions with `duvo pulse versions`."
22476
+ ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function restoreAction(id, versionId, options) {
22477
+ const pulseId = trimRequired(id, "<id>");
22478
+ const revisionId = trimRequired(versionId, "<version-id>");
22479
+ const { apiKey, apiBaseUrl } = await requireAuthenticatedConfig(this);
22480
+ const raw = await httpRequest({
22481
+ method: "POST",
22482
+ path: `/v2/artifacts/${encodeURIComponent(pulseId)}/revisions/${encodeURIComponent(revisionId)}/restore`,
22483
+ apiKey,
22484
+ apiBaseUrl,
22485
+ body: {}
22486
+ });
22487
+ if (options.json) {
22488
+ printJson(raw);
22489
+ return;
22490
+ }
22491
+ const parsed = restoreArtifactRevisionResponseSchema.safeParse(raw);
22492
+ if (!parsed.success) {
22493
+ throw new CliError(
22494
+ `Unexpected response from the API: ${parsed.error.message}`
22495
+ );
22496
+ }
22497
+ console.log(
22498
+ green(
22499
+ `Restored version ${parsed.data.current_version} as the live dashboard.`
22500
+ )
22501
+ );
22502
+ }, "restoreAction"));
22503
+ }
22504
+ __name(registerPulseRestore, "registerPulseRestore");
22505
+
22387
22506
  // src/commands/pulse/send-message.ts
22388
22507
  function registerPulseSendMessage(pulse) {
22389
22508
  pulse.command("send-message <id>").description(
@@ -22397,7 +22516,7 @@ function registerPulseSendMessage(pulse) {
22397
22516
  const { apiKey, apiBaseUrl } = await requireAuthenticatedConfig(this);
22398
22517
  const raw = await httpRequest({
22399
22518
  method: "POST",
22400
- path: `/v1/artifacts/${encodeURIComponent(pulseId)}/messages`,
22519
+ path: `/v2/artifacts/${encodeURIComponent(pulseId)}/messages`,
22401
22520
  apiKey,
22402
22521
  apiBaseUrl,
22403
22522
  body: { message }
@@ -22421,6 +22540,52 @@ function registerPulseSendMessage(pulse) {
22421
22540
  }
22422
22541
  __name(registerPulseSendMessage, "registerPulseSendMessage");
22423
22542
 
22543
+ // src/commands/pulse/versions.ts
22544
+ function registerPulseVersions(pulse) {
22545
+ pulse.command("versions <id>").description(
22546
+ "List a Pulse dashboard's version history, newest first (the 'time machine'). Restore one with `duvo pulse restore`."
22547
+ ).option("--json", "output raw JSON from the API").action(/* @__PURE__ */ __name(async function versionsAction(id, options) {
22548
+ const pulseId = trimRequired(id, "<id>");
22549
+ const { apiKey, apiBaseUrl } = await requireAuthenticatedConfig(this);
22550
+ const raw = await httpRequest({
22551
+ method: "GET",
22552
+ path: `/v2/artifacts/${encodeURIComponent(pulseId)}/revisions`,
22553
+ apiKey,
22554
+ apiBaseUrl
22555
+ });
22556
+ if (options.json) {
22557
+ printJson(raw);
22558
+ return;
22559
+ }
22560
+ const parsed = artifactRevisionListResponseSchema.safeParse(raw);
22561
+ if (!parsed.success) {
22562
+ throw new CliError(
22563
+ `Unexpected response from the API: ${parsed.error.message}`
22564
+ );
22565
+ }
22566
+ const { revisions, current_revision_id: currentRevisionId } = parsed.data;
22567
+ if (revisions.length === 0) {
22568
+ console.log("No versions yet.");
22569
+ return;
22570
+ }
22571
+ const columns = [
22572
+ {
22573
+ header: "",
22574
+ cell: /* @__PURE__ */ __name((row) => row.id === currentRevisionId ? "\u25B6" : "", "cell")
22575
+ },
22576
+ {
22577
+ header: "VERSION",
22578
+ cell: /* @__PURE__ */ __name((row) => String(row.version), "cell")
22579
+ },
22580
+ { header: "ID", cell: /* @__PURE__ */ __name((row) => row.id, "cell") },
22581
+ { header: "CREATED", cell: /* @__PURE__ */ __name((row) => row.created_at, "cell") }
22582
+ ];
22583
+ console.log(renderTable(columns, revisions));
22584
+ console.log(`\u25B6 marks the current (live) version.`);
22585
+ }, "versionsAction"));
22586
+ }
22587
+ __name(registerPulseVersions, "registerPulseVersions");
22588
+
22424
22589
  // src/commands/pulse/index.ts
22425
22590
  function registerPulse(program) {
22426
22591
  const pulse = program.command("pulse").description("Manage Duvo Pulse dashboards in the public API");
@@ -22430,6 +22595,8 @@ function registerPulse(program) {
22430
22595
  registerPulseHtml(pulse);
22431
22596
  registerPulseSendMessage(pulse);
22432
22597
  registerPulseDelete(pulse);
22598
+ registerPulseVersions(pulse);
22599
+ registerPulseRestore(pulse);
22433
22600
  }
22434
22601
  __name(registerPulse, "registerPulse");
22435
22602
 
@@ -26257,7 +26424,7 @@ __name(resolveActiveTeamId, "resolveActiveTeamId");
26257
26424
  var version = resolveVersion();
26258
26425
  function resolveVersion() {
26259
26426
  if (true) {
26260
- return "1.8.0";
26427
+ return "1.9.1";
26261
26428
  }
26262
26429
  const packageJsonPath = join3(
26263
26430
  dirname3(fileURLToPath2(import.meta.url)),
@@ -26341,7 +26508,7 @@ function checkForUpdate() {
26341
26508
  __name(checkForUpdate, "checkForUpdate");
26342
26509
  function loadPackageMeta() {
26343
26510
  if (true) {
26344
- return { name: "@duvoai/cli", version: "1.8.0" };
26511
+ return { name: "@duvoai/cli", version: "1.9.1" };
26345
26512
  }
26346
26513
  const require2 = createRequire(import.meta.url);
26347
26514
  const raw = require2("../package.json");