rivet-design 0.26.2 → 0.27.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.
Files changed (94) hide show
  1. package/dist/agent-variants/DirectionRefReservations.d.ts +11 -0
  2. package/dist/agent-variants/DirectionRefReservations.js +47 -0
  3. package/dist/agent-variants/PreviewRuntime.js +20 -7
  4. package/dist/agent-variants/SessionStore.d.ts +10 -1
  5. package/dist/agent-variants/SessionStore.js +25 -2
  6. package/dist/agent-variants/WorkItemRequestTimes.d.ts +6 -0
  7. package/dist/agent-variants/WorkItemRequestTimes.js +21 -0
  8. package/dist/agent-variants/WorktreeOrchestrator.d.ts +2 -1
  9. package/dist/agent-variants/WorktreeOrchestrator.js +92 -78
  10. package/dist/agent-variants/contracts.d.ts +120 -116
  11. package/dist/agent-variants/existingStaticEntry.d.ts +34 -0
  12. package/dist/agent-variants/existingStaticEntry.js +136 -0
  13. package/dist/agent-variants/staticPreviewFiles.js +1 -1
  14. package/dist/agent-variants/variant-project-runtime.d.ts +2 -1
  15. package/dist/agent-variants/variantsTelemetry.d.ts +8 -0
  16. package/dist/agent-variants/variantsTelemetry.js +5 -0
  17. package/dist/agent-variants/workItemInput.d.ts +168 -146
  18. package/dist/agent-variants/workItemInput.js +12 -1
  19. package/dist/cli/commands/directionTarget.d.ts +23 -0
  20. package/dist/cli/commands/directionTarget.js +87 -0
  21. package/dist/cli/commands/mcpServe.js +1 -0
  22. package/dist/cli/commands/open.js +28 -4
  23. package/dist/cli/commands/serve.js +2 -0
  24. package/dist/cli/commands/variants.js +36 -43
  25. package/dist/cli/envelope.d.ts +1 -1
  26. package/dist/cli/envelope.js +1 -0
  27. package/dist/cli/handoff.d.ts +1 -0
  28. package/dist/cli/handoff.js +20 -4
  29. package/dist/cli/projectRuntimeUpgrade.d.ts +11 -0
  30. package/dist/cli/projectRuntimeUpgrade.js +43 -11
  31. package/dist/cli/router.js +1 -0
  32. package/dist/cli/telemetry.d.ts +10 -0
  33. package/dist/cli/telemetry.js +37 -1
  34. package/dist/config/pluginMetrics.js +38 -0
  35. package/dist/index.d.ts +19 -0
  36. package/dist/index.js +14 -5
  37. package/dist/mcp/explorationSchema.js +1 -1
  38. package/dist/mcp/getExploration.js +11 -5
  39. package/dist/proxy-middleware/proxy-config.js +7 -0
  40. package/dist/routes/agentVariants.js +4 -0
  41. package/dist/routes/cli.js +10 -1
  42. package/dist/routes/library/middleware.js +11 -5
  43. package/dist/server.js +20 -6
  44. package/dist/services/DependencyPreparationService.js +57 -19
  45. package/dist/services/GuidanceVerifierRunner.js +4 -4
  46. package/dist/services/ProjectLibrary.d.ts +4 -1
  47. package/dist/services/ProjectLibrary.js +14 -9
  48. package/dist/services/ProjectPackageManager.d.ts +5 -0
  49. package/dist/services/ProjectPackageManager.js +33 -11
  50. package/dist/services/ProjectRuntimeService.d.ts +8 -0
  51. package/dist/services/ProjectRuntimeService.js +15 -2
  52. package/dist/services/TelemetryService.d.ts +13 -2
  53. package/dist/services/TelemetryService.js +29 -0
  54. package/dist/services/VariantHistoryService.d.ts +8 -0
  55. package/dist/services/VariantHistoryService.js +40 -0
  56. package/dist/services/WorktreeManager.d.ts +1 -0
  57. package/dist/services/WorktreeManager.js +17 -0
  58. package/dist/services/createAgentVariantsOrchestrator.js +9 -2
  59. package/dist/services/directionRefs.d.ts +21 -0
  60. package/dist/services/directionRefs.js +148 -0
  61. package/dist/services/profiles/DesignProfiles.js +16 -8
  62. package/dist/services/projectDirections.d.ts +22 -0
  63. package/dist/services/projectDirections.js +38 -0
  64. package/dist/types/direction-ref.d.ts +36 -0
  65. package/dist/types/direction-ref.js +3 -0
  66. package/dist/types/guidance-verifier.d.ts +7 -5
  67. package/dist/types/guidance-verifier.js +14 -1
  68. package/dist/types/variant-history.d.ts +3 -1
  69. package/dist/utils/devServerError.d.ts +5 -0
  70. package/dist/utils/devServerError.js +4 -0
  71. package/dist/utils/failureReason.d.ts +16 -0
  72. package/dist/utils/failureReason.js +106 -0
  73. package/dist/utils/hostedLogPrivacy.d.ts +1 -0
  74. package/dist/utils/hostedLogPrivacy.js +10 -4
  75. package/dist/utils/skills/claude-skill.d.ts +1 -1
  76. package/dist/utils/skills/claude-skill.js +1 -1
  77. package/dist/utils/skills/cli-guidance.d.ts +1 -1
  78. package/dist/utils/skills/cli-guidance.js +7 -6
  79. package/dist/utils/skills/cursor-rules.d.ts +1 -1
  80. package/dist/utils/skills/cursor-rules.js +1 -1
  81. package/dist/utils/subprocessEnvironment.d.ts +1 -1
  82. package/dist/utils/subprocessEnvironment.js +0 -1
  83. package/package.json +4 -4
  84. package/src/ui/dist/assets/LibraryEntry-BZ5EdFgA.js +37 -0
  85. package/src/ui/dist/assets/main-MepMmTwb.css +1 -0
  86. package/src/ui/dist/assets/main-RriU35pI.js +497 -0
  87. package/src/ui/dist/index.html +2 -2
  88. package/dist/services/StaticPreviewServer.d.ts +0 -8
  89. package/dist/services/StaticPreviewServer.js +0 -207
  90. package/src/ui/dist/assets/LibraryEntry-92R_T-Xa.js +0 -37
  91. package/src/ui/dist/assets/main-D0UmAaUe.css +0 -1
  92. package/src/ui/dist/assets/main-DgEfJvYu.js +0 -497
  93. package/src/ui/dist/fonts/Goldman-Bold.woff2 +0 -0
  94. package/src/ui/dist/fonts/Goldman-Regular.woff2 +0 -0
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseVariantWorkItemInput = exports.isVariantWorkItem = exports.isVariantWorkItemKind = exports.VARIANT_WORK_ITEM_KINDS = void 0;
3
+ exports.parseVariantWorkItemInput = exports.shownDirectionRef = exports.isVariantWorkItem = exports.isVariantWorkItemKind = exports.VARIANT_WORK_ITEM_KINDS = void 0;
4
4
  const v3_1 = require("zod/v3");
5
5
  const errors_1 = require("./errors");
6
6
  exports.VARIANT_WORK_ITEM_KINDS = [
@@ -21,6 +21,12 @@ const variantWorkItemInputFields = v3_1.z.object({
21
21
  briefLabel: v3_1.z.string().optional(),
22
22
  briefBody: v3_1.z.string().optional(),
23
23
  briefNotes: v3_1.z.string().optional(),
24
+ directionRef: v3_1.z
25
+ .custom((value) => typeof value === 'string')
26
+ .optional(),
27
+ sourceDirectionRef: v3_1.z
28
+ .custom((value) => typeof value === 'string')
29
+ .optional(),
24
30
  visualReferenceUrl: v3_1.z.string().optional(),
25
31
  instruction: v3_1.z.string().optional(),
26
32
  guidance: v3_1.z.array(recordOf()).optional(),
@@ -59,6 +65,11 @@ const variantWorkItemInputSchemas = {
59
65
  briefBody: v3_1.z.string(),
60
66
  }),
61
67
  };
68
+ const shownDirectionRef = (input) => {
69
+ const directionRef = input.directionRef ?? input.sourceDirectionRef;
70
+ return directionRef ? { directionRef } : {};
71
+ };
72
+ exports.shownDirectionRef = shownDirectionRef;
62
73
  const variantWorkItemInputParsers = {
63
74
  static_preview: (input) => variantWorkItemInputSchemas.static_preview.safeParse(input),
64
75
  refine_variant: (input) => variantWorkItemInputSchemas.refine_variant.safeParse(input),
@@ -0,0 +1,23 @@
1
+ import { type CliCommandResult } from '../envelope';
2
+ import type { DirectionRef } from '../../types/direction-ref';
3
+ export type DirectionTarget = {
4
+ projectId?: string;
5
+ sessionId: string;
6
+ variantId: string;
7
+ directionRef?: DirectionRef;
8
+ };
9
+ type DirectionTargetResult = {
10
+ ok: true;
11
+ target: DirectionTarget;
12
+ } | {
13
+ ok: false;
14
+ result: CliCommandResult;
15
+ };
16
+ export declare const resolveDirectionTarget: (args: {
17
+ command: string;
18
+ projectPath: string;
19
+ input: string;
20
+ usage: string;
21
+ }) => Promise<DirectionTargetResult>;
22
+ export {};
23
+ //# sourceMappingURL=directionTarget.d.ts.map
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveDirectionTarget = void 0;
4
+ const envelope_1 = require("../envelope");
5
+ const libraryErrors_1 = require("../../services/libraryErrors");
6
+ const ProjectLibrary_1 = require("../../services/ProjectLibrary");
7
+ const VariantHistoryService_1 = require("../../services/VariantHistoryService");
8
+ const directionRefs_1 = require("../../services/directionRefs");
9
+ const projectDirections_1 = require("../../services/projectDirections");
10
+ const errorMessage_1 = require("../../utils/errorMessage");
11
+ const resolveInProject = async (args) => {
12
+ const library = ProjectLibrary_1.ProjectLibrary.openReadOnly();
13
+ try {
14
+ const owner = library?.registry.findByPath(args.projectPath);
15
+ if (library && owner)
16
+ return {
17
+ projectId: owner.id,
18
+ resolution: await (0, projectDirections_1.resolveProjectDirection)({
19
+ source: { kind: 'library', library, projectId: owner.id },
20
+ address: args.address,
21
+ }),
22
+ };
23
+ const history = new VariantHistoryService_1.VariantHistoryService();
24
+ try {
25
+ return {
26
+ resolution: await (0, projectDirections_1.resolveProjectDirection)({
27
+ source: { kind: 'history', history, projectPath: args.projectPath },
28
+ address: args.address,
29
+ }),
30
+ };
31
+ }
32
+ finally {
33
+ history.metadata.closeAll();
34
+ }
35
+ }
36
+ finally {
37
+ library?.close();
38
+ }
39
+ };
40
+ const resolveDirectionTarget = async (args) => {
41
+ const address = (0, directionRefs_1.parseDirectionAddress)(args.input);
42
+ if (!address)
43
+ return {
44
+ ok: false,
45
+ result: (0, envelope_1.errorResult)(args.command, 'USAGE_ERROR', args.usage),
46
+ };
47
+ if (address.kind === 'ids') {
48
+ const { projectId, sessionId, variantId } = address;
49
+ return {
50
+ ok: true,
51
+ target: { ...(projectId ? { projectId } : {}), sessionId, variantId },
52
+ };
53
+ }
54
+ try {
55
+ const { projectId, resolution } = await resolveInProject({
56
+ projectPath: args.projectPath,
57
+ address,
58
+ });
59
+ if (!resolution.isResolved)
60
+ return {
61
+ ok: false,
62
+ result: (0, envelope_1.errorResult)(args.command, resolution.code, resolution.message, {
63
+ input: args.input.trim(),
64
+ candidates: resolution.candidates,
65
+ }),
66
+ };
67
+ const { directionRef, sessionId, variantId } = resolution.direction;
68
+ return {
69
+ ok: true,
70
+ target: {
71
+ ...(projectId ? { projectId } : {}),
72
+ sessionId,
73
+ variantId,
74
+ directionRef,
75
+ },
76
+ };
77
+ }
78
+ catch (error) {
79
+ const isMissingProject = error instanceof libraryErrors_1.LibraryError && error.code === 'project_not_found';
80
+ return {
81
+ ok: false,
82
+ result: (0, envelope_1.errorResult)(args.command, isMissingProject ? 'WORK_ITEM_NOT_FOUND' : 'OPERATION_FAILED', (0, errorMessage_1.errorMessage)(error)),
83
+ };
84
+ }
85
+ };
86
+ exports.resolveDirectionTarget = resolveDirectionTarget;
87
+ //# sourceMappingURL=directionTarget.js.map
@@ -182,6 +182,7 @@ const buildMcpServer = async (options = {}) => {
182
182
  durationMs: Date.now() - startedAt,
183
183
  designContextKind: (0, telemetry_1.designContextKindForEnvelope)(result.envelope),
184
184
  ...(0, telemetry_1.variantContextMetadataForArgs)(command, rest),
185
+ ...(0, telemetry_1.verificationMetadataForEnvelope)(result.envelope),
185
186
  ...callerFields,
186
187
  source: 'mcp',
187
188
  });
@@ -47,6 +47,7 @@ const flags_1 = require("../flags");
47
47
  const client_1 = require("../client");
48
48
  const serverHandshake_1 = require("../serverHandshake");
49
49
  const serverVersion_1 = require("../serverVersion");
50
+ const telemetry_1 = require("../telemetry");
50
51
  const handoff_1 = require("../handoff");
51
52
  const callerRunnerPaths_1 = require("../callerRunnerPaths");
52
53
  const runnerSelection_1 = require("../runnerSelection");
@@ -149,6 +150,15 @@ const passthroughServeArgs = (context) => {
149
150
  }
150
151
  return args;
151
152
  };
153
+ const USER_PORT_FLAG = '--user-port';
154
+ const withoutUserPort = (args) => args.filter((arg, index) => arg !== USER_PORT_FLAG && args[index - 1] !== USER_PORT_FLAG);
155
+ const previewRecoveryServeArgs = (context, retiredArgs) => {
156
+ const userPort = (0, flags_1.stringFlag)(context.flags, 'user-port');
157
+ return [
158
+ ...withoutUserPort(retiredArgs ?? passthroughServeArgs(context)),
159
+ ...(userPort === undefined ? [] : [USER_PORT_FLAG, userPort]),
160
+ ];
161
+ };
152
162
  const serveEnvFor = (handoff, baseEnv) => ({
153
163
  ...(0, subprocessEnvironment_1.subprocessEnvironment)('rivetRuntime', baseEnv),
154
164
  ...(0, callerRunnerPaths_1.callerRunnerPathsEnvEntry)(baseEnv),
@@ -283,12 +293,26 @@ const ensureProjectRuntime = async (context, io, dependencies = {}) => {
283
293
  }
284
294
  if (replacement.outcome === 'attach') {
285
295
  const readinessError = await verifyRuntimeReadiness(existing, Math.min(serverStartTimeoutMs, APP_HEALTH_TIMEOUT_MS));
286
- if (readinessError)
296
+ if (!readinessError) {
297
+ return finishProjectOpen(await openedData(existing, true), io);
298
+ }
299
+ if ((0, telemetry_1.serverUnavailableReasonForEnvelope)(readinessError.envelope) !==
300
+ 'app_health_failed')
301
+ return readinessError;
302
+ const retirement = await (0, projectRuntimeUpgrade_1.retireUnavailablePreview)({
303
+ attached: existing,
304
+ clientVersion: (0, serverVersion_1.serverVersionInfo)(existing.handshake).cliVersion,
305
+ shutdownTimeoutMs: timeoutFromEnv(env, UPGRADE_SHUTDOWN_TIMEOUT_ENV, DEFAULT_UPGRADE_SHUTDOWN_TIMEOUT_MS),
306
+ });
307
+ if (retirement.outcome === 'kept')
287
308
  return readinessError;
288
- return finishProjectOpen(await openedData(existing, true), io);
309
+ restartArgs = previewRecoveryServeArgs(context, retirement.restartArgs);
310
+ io.writeProgress('The project server is restarting because the app preview is unavailable…');
311
+ }
312
+ else {
313
+ interruptedWork = replacement.interruptedWork;
314
+ restartArgs = replacement.restartArgs;
289
315
  }
290
- interruptedWork = replacement.interruptedWork;
291
- restartArgs = replacement.restartArgs;
292
316
  }
293
317
  io.writeProgress(`Starting Rivet server for ${projectPath}…`);
294
318
  const handle = spawnServer({
@@ -113,6 +113,7 @@ const handleServe = async (args, io) => {
113
113
  stage: 'resolve_dev_server',
114
114
  failureReason: 'operation_failed',
115
115
  durationMs: Date.now() - serverStartStartedAt,
116
+ error,
116
117
  });
117
118
  await telemetry.shutdown();
118
119
  await logForwarder.shutdown();
@@ -299,6 +300,7 @@ const handleServe = async (args, io) => {
299
300
  stage: 'start_editor_server',
300
301
  failureReason: 'operation_failed',
301
302
  durationMs: Date.now() - serverStartStartedAt,
303
+ error,
302
304
  });
303
305
  await telemetry.shutdown();
304
306
  await logForwarder.shutdown();
@@ -50,6 +50,7 @@ const handoff_1 = require("../handoff");
50
50
  const callerModel_1 = require("../callerModel");
51
51
  const shared_1 = require("./shared");
52
52
  const elementSelector_1 = require("./elementSelector");
53
+ const directionTarget_1 = require("./directionTarget");
53
54
  const hostWorkNextAction_1 = require("../hostWorkNextAction");
54
55
  const runLabel_1 = require("../../agent-variants/runLabel");
55
56
  const contracts_1 = require("../../agent-variants/contracts");
@@ -116,44 +117,22 @@ const LIST_FLAG_SPEC = {
116
117
  const GET_FLAG_SPEC = {
117
118
  detail: { takesValue: false },
118
119
  };
119
- const parseVariantTarget = (raw) => {
120
- if (raw === undefined) {
120
+ const START_TARGET_USAGE = 'Usage: --target <directionRef>|<sessionId>:<variantId> (example: --target warm-editorial-green)';
121
+ const GET_USAGE = 'Usage: rivet variants get <directionRef>|last|[<projectId>/]<sessionId>:<variantId> [--detail] [--project <path>]';
122
+ const resolveStartTarget = async (args) => {
123
+ if (args.raw === undefined)
121
124
  return { ok: true };
122
- }
123
- const separatorIndex = raw.indexOf(':');
124
- if (separatorIndex <= 0 || separatorIndex === raw.length - 1) {
125
- return {
126
- ok: false,
127
- message: 'Usage: --target <sessionId>:<variantId> (example: --target abc:def)',
128
- };
129
- }
130
- const sessionId = raw.slice(0, separatorIndex).trim();
131
- const variantId = raw.slice(separatorIndex + 1).trim();
132
- if (!sessionId || !variantId) {
133
- return {
134
- ok: false,
135
- message: 'Usage: --target <sessionId>:<variantId> (example: --target abc:def)',
136
- };
137
- }
125
+ const resolved = await (0, directionTarget_1.resolveDirectionTarget)({
126
+ command: START_COMMAND,
127
+ projectPath: args.projectPath,
128
+ input: args.raw,
129
+ usage: START_TARGET_USAGE,
130
+ });
131
+ if (!resolved.ok)
132
+ return resolved;
133
+ const { sessionId, variantId } = resolved.target;
138
134
  return { ok: true, target: { kind: 'variant', sessionId, variantId } };
139
135
  };
140
- const variantReferenceFromString = (raw) => {
141
- if (!raw)
142
- return null;
143
- const projectSeparator = raw.indexOf('/');
144
- const projectId = projectSeparator === -1 ? undefined : raw.slice(0, projectSeparator);
145
- const direction = projectSeparator === -1 ? raw : raw.slice(projectSeparator + 1);
146
- if (projectSeparator !== -1 && (!projectId || direction.includes('/')))
147
- return null;
148
- const variantSeparator = direction.indexOf(':');
149
- if (variantSeparator <= 0 || variantSeparator === direction.length - 1)
150
- return null;
151
- if (direction.indexOf(':', variantSeparator + 1) !== -1)
152
- return null;
153
- const sessionId = direction.slice(0, variantSeparator).trim();
154
- const variantId = direction.slice(variantSeparator + 1).trim();
155
- return sessionId && variantId ? { projectId, sessionId, variantId } : null;
156
- };
157
136
  const parseJsonFlag = (command, name, raw) => {
158
137
  if (raw === undefined) {
159
138
  return { ok: true };
@@ -437,7 +416,7 @@ const handleVariantsStart = async (args, options) => {
437
416
  }
438
417
  const instruction = (0, flags_1.stringFlag)(context.flags, 'instruction');
439
418
  if (!instruction?.trim()) {
440
- return (0, envelope_1.errorResult)(START_COMMAND, 'USAGE_ERROR', 'Usage: rivet variants start --instruction <text> [--run-label <text>] [--briefs <json>] [--count N] [--fidelity low|medium|high] [--element <selector>] [--files <json>] [--fresh] [--context-images <json>] [--context-assets <json>] [--reference-pages <json>] [--reference-videos <json>] [--target <sessionId>:<variantId>]');
419
+ return (0, envelope_1.errorResult)(START_COMMAND, 'USAGE_ERROR', 'Usage: rivet variants start --instruction <text> [--run-label <text>] [--briefs <json>] [--count N] [--fidelity low|medium|high] [--element <selector>] [--files <json>] [--fresh] [--context-images <json>] [--context-assets <json>] [--reference-pages <json>] [--reference-videos <json>] [--target <directionRef>|<sessionId>:<variantId>]');
441
420
  }
442
421
  if (context.flags.errors.length > 0) {
443
422
  return (0, envelope_1.errorResult)(START_COMMAND, 'USAGE_ERROR', context.flags.errors.join('; '));
@@ -508,10 +487,12 @@ const handleVariantsStart = async (args, options) => {
508
487
  return (0, envelope_1.errorResult)(START_COMMAND, 'USAGE_ERROR', '--count must match --briefs length when both are provided.');
509
488
  }
510
489
  const isFresh = isFreshStart;
511
- const parsedTarget = parseVariantTarget((0, flags_1.stringFlag)(context.flags, 'target'));
512
- if (!parsedTarget.ok) {
513
- return (0, envelope_1.errorResult)(START_COMMAND, 'USAGE_ERROR', parsedTarget.message);
514
- }
490
+ const parsedTarget = await resolveStartTarget({
491
+ projectPath: context.projectPath,
492
+ raw: (0, flags_1.stringFlag)(context.flags, 'target'),
493
+ });
494
+ if (!parsedTarget.ok)
495
+ return parsedTarget.result;
515
496
  if (isFresh && parsedTarget.target) {
516
497
  return (0, envelope_1.errorResult)(START_COMMAND, 'USAGE_ERROR', '--fresh cannot be combined with --target; start fresh generation from the base project.');
517
498
  }
@@ -782,6 +763,7 @@ const handleSavedVariantGet = async (args) => {
782
763
  return (0, envelope_1.errorResult)(GET_COMMAND, 'WORK_ITEM_NOT_FOUND', 'No saved variant exists for this project and reference.');
783
764
  const saved = 'detail' in found ? found.detail : found.summary;
784
765
  const { manifest, variantDir } = saved;
766
+ const directionRef = args.directionRef ?? manifest.directionRef;
785
767
  const kind = manifest.artifact.kind === 'diff' ? 'diff' : 'project-created';
786
768
  const artifactPath = path.join(variantDir, manifest.artifact.kind === 'diff'
787
769
  ? manifest.artifact.diffPath
@@ -789,6 +771,7 @@ const handleSavedVariantGet = async (args) => {
789
771
  const variant = args.isDetailed && 'detail' in found
790
772
  ? {
791
773
  ...manifest,
774
+ directionRef,
792
775
  kind,
793
776
  artifactPath,
794
777
  diff: found.detail.diff,
@@ -796,6 +779,7 @@ const handleSavedVariantGet = async (args) => {
796
779
  designMarkdown: found.detail.designMarkdown,
797
780
  }
798
781
  : {
782
+ directionRef,
799
783
  sessionId: manifest.sessionId,
800
784
  variantId: manifest.variantId,
801
785
  status: manifest.status,
@@ -825,12 +809,21 @@ const handleVariantsGet = async (args) => {
825
809
  if ((0, shared_1.isCommandResult)(context)) {
826
810
  return context;
827
811
  }
828
- const reference = variantReferenceFromString(context.flags.positionals[0]);
829
- if (!reference ||
812
+ const input = context.flags.positionals[0];
813
+ if (input === undefined ||
830
814
  context.flags.positionals.length !== 1 ||
831
815
  context.flags.errors.length > 0) {
832
- return (0, envelope_1.errorResult)(GET_COMMAND, 'USAGE_ERROR', 'Usage: rivet variants get [<projectId>/]<sessionId>:<variantId> [--detail] [--project <path>]');
816
+ return (0, envelope_1.errorResult)(GET_COMMAND, 'USAGE_ERROR', GET_USAGE);
833
817
  }
818
+ const resolved = await (0, directionTarget_1.resolveDirectionTarget)({
819
+ command: GET_COMMAND,
820
+ projectPath: context.projectPath,
821
+ input,
822
+ usage: GET_USAGE,
823
+ });
824
+ if (!resolved.ok)
825
+ return resolved.result;
826
+ const reference = resolved.target;
834
827
  if (reference.projectId)
835
828
  return handleSavedVariantGet({
836
829
  ...reference,
@@ -8,7 +8,7 @@ export declare const CLI_EXIT_CODES: {
8
8
  readonly waitTimeout: 5;
9
9
  };
10
10
  export type CliExitCode = (typeof CLI_EXIT_CODES)[keyof typeof CLI_EXIT_CODES];
11
- export type CliErrorCode = 'OPERATION_FAILED' | 'USAGE_ERROR' | 'AUTH_REQUIRED' | 'SERVER_UNAVAILABLE' | 'WAIT_TIMEOUT' | 'SESSION_NOT_FOUND' | 'WORK_ITEM_NOT_FOUND' | 'MCP_REMOVED';
11
+ export type CliErrorCode = 'OPERATION_FAILED' | 'USAGE_ERROR' | 'AUTH_REQUIRED' | 'SERVER_UNAVAILABLE' | 'WAIT_TIMEOUT' | 'SESSION_NOT_FOUND' | 'WORK_ITEM_NOT_FOUND' | 'DIRECTION_AMBIGUOUS' | 'MCP_REMOVED';
12
12
  export type CliLoginAction = {
13
13
  action: 'login';
14
14
  command: 'rivet login';
@@ -24,6 +24,7 @@ const ERROR_EXIT_CODES = {
24
24
  WAIT_TIMEOUT: exports.CLI_EXIT_CODES.waitTimeout,
25
25
  SESSION_NOT_FOUND: exports.CLI_EXIT_CODES.operationFailed,
26
26
  WORK_ITEM_NOT_FOUND: exports.CLI_EXIT_CODES.operationFailed,
27
+ DIRECTION_AMBIGUOUS: exports.CLI_EXIT_CODES.usageError,
27
28
  MCP_REMOVED: exports.CLI_EXIT_CODES.usageError,
28
29
  };
29
30
  const loginRecovery = (authUrl) => ({
@@ -35,6 +35,7 @@ export type CallerTelemetryFields = {
35
35
  callerAgent?: string;
36
36
  callerModel?: string;
37
37
  callerAgentSource?: 'handoff' | 'env';
38
+ callerRunId?: string;
38
39
  };
39
40
  export declare const callerTelemetryFieldsFromArgs: (args: string[], env?: NodeJS.ProcessEnv) => CallerTelemetryFields;
40
41
  export declare const initiatorFor: (handoff: CallerHandoff | null) => WorkItemInitiator;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.initiatorFor = exports.callerTelemetryFieldsFromArgs = exports.detectCallerAgentFromEnv = exports.callerAgentEvidenceFromEnv = exports.detectCallerAgentsFromEnv = exports.parseHandoff = exports.HANDOFF_ENV_VARS = exports.CALLER_AGENT_ALLOWLIST = void 0;
4
+ const node_crypto_1 = require("node:crypto");
4
5
  exports.CALLER_AGENT_ALLOWLIST = ['claude', 'codex', 'cursor'];
5
6
  exports.HANDOFF_ENV_VARS = {
6
7
  agent: 'RIVET_CALLER_AGENT',
@@ -84,6 +85,11 @@ const callerAgentEvidenceFromEnv = (env = process.env) => ENV_MARKERS_BY_AGENT.m
84
85
  exports.callerAgentEvidenceFromEnv = callerAgentEvidenceFromEnv;
85
86
  const detectCallerAgentFromEnv = (env = process.env) => (0, exports.detectCallerAgentsFromEnv)(env)[0];
86
87
  exports.detectCallerAgentFromEnv = detectCallerAgentFromEnv;
88
+ const CALLER_RUN_ID_HEX_LENGTH = 16;
89
+ const callerRunIdForSession = (session) => (0, node_crypto_1.createHash)('sha256')
90
+ .update(session)
91
+ .digest('hex')
92
+ .slice(0, CALLER_RUN_ID_HEX_LENGTH);
87
93
  const callerTelemetryFieldsFromArgs = (args, env = process.env) => {
88
94
  const valueOf = (flag) => {
89
95
  const index = args.indexOf(flag);
@@ -95,15 +101,25 @@ const callerTelemetryFieldsFromArgs = (args, env = process.env) => {
95
101
  callerSession: valueOf('--caller-session'),
96
102
  handoffJson: valueOf('--handoff'),
97
103
  }, env);
98
- if (parsed.ok && parsed.handoff) {
104
+ const handoff = parsed.ok ? parsed.handoff : null;
105
+ const session = handoff?.session ??
106
+ nonEmpty(env.CODEX_THREAD_ID) ??
107
+ nonEmpty(env.CLAUDE_CODE_SESSION_ID);
108
+ const callerRunId = session ? callerRunIdForSession(session) : undefined;
109
+ const runId = callerRunId ? { callerRunId } : {};
110
+ if (handoff) {
99
111
  return {
100
- callerAgent: parsed.handoff.agent,
101
- callerModel: parsed.handoff.model,
112
+ callerAgent: handoff.agent,
113
+ callerModel: handoff.model,
102
114
  callerAgentSource: 'handoff',
115
+ ...runId,
103
116
  };
104
117
  }
105
118
  const detected = (0, exports.detectCallerAgentFromEnv)(env);
106
- return detected ? { callerAgent: detected, callerAgentSource: 'env' } : {};
119
+ if (detected) {
120
+ return { callerAgent: detected, callerAgentSource: 'env', ...runId };
121
+ }
122
+ return runId;
107
123
  };
108
124
  exports.callerTelemetryFieldsFromArgs = callerTelemetryFieldsFromArgs;
109
125
  const initiatorFor = (handoff) => handoff
@@ -12,6 +12,17 @@ type RuntimeUpgradeOutcome = {
12
12
  restartArgs?: string[];
13
13
  interruptedWork?: RuntimeInterruption;
14
14
  };
15
+ type RuntimeRetirement = {
16
+ outcome: 'retired';
17
+ restartArgs?: string[];
18
+ } | {
19
+ outcome: 'kept';
20
+ };
21
+ export declare const retireUnavailablePreview: ({ attached, clientVersion, shutdownTimeoutMs, }: {
22
+ attached: AttachedServer;
23
+ clientVersion: string;
24
+ shutdownTimeoutMs: number;
25
+ }) => Promise<RuntimeRetirement>;
15
26
  export declare const prepareRuntimeUpgrade: ({ attached, io, shutdownTimeoutMs, }: {
16
27
  attached: AttachedServer;
17
28
  io: CliIO;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.prepareRuntimeUpgrade = void 0;
6
+ exports.prepareRuntimeUpgrade = exports.retireUnavailablePreview = void 0;
7
7
  const zod_1 = require("zod");
8
8
  const fs_1 = __importDefault(require("fs"));
9
9
  const client_1 = require("./client");
@@ -34,6 +34,43 @@ const INTERRUPTIBLE_REASONS = new Set([
34
34
  'active_work',
35
35
  'unknown_execution_state',
36
36
  ]);
37
+ const awaitOwnedRuntimeShutdown = async ({ attached, processIdentity, shutdownTimeoutMs, }) => {
38
+ if (await (0, serverShutdown_1.waitForServerShutdown)(attached, shutdownTimeoutMs))
39
+ return;
40
+ await (0, stopRuntimeProcess_1.stopRuntimeProcess)({
41
+ pid: attached.handshake.pid,
42
+ timeoutMs: shutdownTimeoutMs,
43
+ isOwned: async () => {
44
+ return (processIdentity !== null &&
45
+ (0, stopRuntimeProcess_1.runtimeProcessIdentity)(attached.handshake.pid) === processIdentity);
46
+ },
47
+ });
48
+ };
49
+ const retireUnavailablePreview = async ({ attached, clientVersion, shutdownTimeoutMs, }) => {
50
+ const serverVersion = attached.handshake.rivetVersion;
51
+ if (!serverVersion || (0, serverVersion_1.isNewerVersion)(serverVersion, clientVersion))
52
+ return { outcome: 'kept' };
53
+ try {
54
+ const processIdentity = (0, stopRuntimeProcess_1.runtimeProcessIdentity)(attached.handshake.pid);
55
+ const upgrade = await (0, client_1.requestServer)(attached, '/api/cli/upgrade', {
56
+ method: 'POST',
57
+ body: { clientVersion, requireIdle: true },
58
+ });
59
+ const parsed = upgradeSchema.parse(upgrade.body);
60
+ if (upgrade.status !== 200 || parsed.stopping !== true)
61
+ return { outcome: 'kept' };
62
+ await awaitOwnedRuntimeShutdown({
63
+ attached,
64
+ processIdentity,
65
+ shutdownTimeoutMs,
66
+ });
67
+ return { outcome: 'retired', restartArgs: parsed.restartArgs };
68
+ }
69
+ catch {
70
+ return { outcome: 'kept' };
71
+ }
72
+ };
73
+ exports.retireUnavailablePreview = retireUnavailablePreview;
37
74
  const prepareRuntimeUpgrade = async ({ attached, io, shutdownTimeoutMs, }) => {
38
75
  const info = (0, serverVersion_1.serverVersionInfo)(attached.handshake);
39
76
  if (!info.staleServer)
@@ -92,16 +129,11 @@ const prepareRuntimeUpgrade = async ({ attached, io, shutdownTimeoutMs, }) => {
92
129
  : undefined;
93
130
  if (interruptedWork)
94
131
  io.writeProgress(`${interruptedWork.message} Recovery details: ${interruptedWork.receiptPath}`);
95
- if (!(await (0, serverShutdown_1.waitForServerShutdown)(attached, shutdownTimeoutMs))) {
96
- await (0, stopRuntimeProcess_1.stopRuntimeProcess)({
97
- pid: attached.handshake.pid,
98
- timeoutMs: shutdownTimeoutMs,
99
- isOwned: async () => {
100
- return (processIdentity !== null &&
101
- (0, stopRuntimeProcess_1.runtimeProcessIdentity)(attached.handshake.pid) === processIdentity);
102
- },
103
- });
104
- }
132
+ await awaitOwnedRuntimeShutdown({
133
+ attached,
134
+ processIdentity,
135
+ shutdownTimeoutMs,
136
+ });
105
137
  io.writeProgress(`Upgrading project server to rivet v${info.cliVersion}…`);
106
138
  return {
107
139
  outcome: 'spawn',
@@ -309,6 +309,7 @@ const runCliControlCommand = async (args, io = io_1.processCliIO) => {
309
309
  designContextKind: (0, telemetry_1.designContextKindForEnvelope)(result.envelope),
310
310
  ...(0, telemetry_1.variantContextMetadataForArgs)(command, rest),
311
311
  ...(0, telemetry_1.browserMetadataForEnvelope)(result.envelope),
312
+ ...(0, telemetry_1.verificationMetadataForEnvelope)(result.envelope),
312
313
  ...(0, handoff_1.callerTelemetryFieldsFromArgs)(rest),
313
314
  });
314
315
  telemetry.reportInstallRefActivations();
@@ -1,6 +1,7 @@
1
1
  import type { CliEnvelope } from './envelope';
2
2
  import type { BrowserOpenResult } from './browser';
3
3
  import { type ServerUnavailableReason } from './serverUnavailable';
4
+ import { type GuidanceVerifierErrorReason } from '../types/guidance-verifier';
4
5
  export type { ServerUnavailableReason } from './serverUnavailable';
5
6
  export type DesignContextKind = 'arena' | 'pinterest' | 'reference' | 'unsupported' | 'website';
6
7
  export type VariantContextKind = 'image' | 'variant' | 'video' | 'website';
@@ -14,6 +15,15 @@ export type BrowserMetadata = {
14
15
  browserAction?: BrowserOpenResult['action'];
15
16
  browserReason?: BrowserOpenResult['reason'];
16
17
  };
18
+ declare const COMPLETED_VERIFICATION_STATUSES: readonly ["pass", "fail", "blocked"];
19
+ type CompletedVerificationStatus = (typeof COMPLETED_VERIFICATION_STATUSES)[number];
20
+ export type VerificationOutcome = CompletedVerificationStatus | GuidanceVerifierErrorReason;
21
+ export type VerificationMetadata = {
22
+ verificationOutcome?: VerificationOutcome;
23
+ verificationCheckCount?: number;
24
+ verificationDurationMs?: number;
25
+ };
26
+ export declare const verificationMetadataForEnvelope: (envelope: CliEnvelope) => VerificationMetadata;
17
27
  export declare const browserMetadataForEnvelope: (envelope: CliEnvelope) => BrowserMetadata;
18
28
  export declare const serverUnavailableReasonForEnvelope: (envelope: CliEnvelope) => ServerUnavailableReason | undefined;
19
29
  export declare const designContextKindForEnvelope: (envelope: CliEnvelope) => DesignContextKind | undefined;
@@ -1,10 +1,46 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.variantContextMetadataForArgs = exports.designContextKindForEnvelope = exports.serverUnavailableReasonForEnvelope = exports.browserMetadataForEnvelope = void 0;
3
+ exports.variantContextMetadataForArgs = exports.designContextKindForEnvelope = exports.serverUnavailableReasonForEnvelope = exports.browserMetadataForEnvelope = exports.verificationMetadataForEnvelope = void 0;
4
4
  const serverUnavailable_1 = require("./serverUnavailable");
5
+ const guidance_verifier_1 = require("../types/guidance-verifier");
6
+ const COMPLETED_VERIFICATION_STATUSES = ['pass', 'fail', 'blocked'];
7
+ const isCompletedVerificationStatus = (value) => typeof value === 'string' &&
8
+ COMPLETED_VERIFICATION_STATUSES.includes(value);
9
+ const isGuidanceVerifierErrorReason = (value) => typeof value === 'string' &&
10
+ guidance_verifier_1.GUIDANCE_VERIFIER_ERROR_REASONS.includes(value);
11
+ const isNonNegativeDuration = (value) => typeof value === 'number' && Number.isFinite(value) && value >= 0;
12
+ const verificationOutcomeForReport = (report) => {
13
+ if (report.execution === 'completed' &&
14
+ isCompletedVerificationStatus(report.status)) {
15
+ return report.status;
16
+ }
17
+ if (report.execution === 'error' &&
18
+ isGuidanceVerifierErrorReason(report.reason)) {
19
+ return report.reason;
20
+ }
21
+ return undefined;
22
+ };
5
23
  const recordOf = (value) => value !== null && typeof value === 'object'
6
24
  ? value
7
25
  : {};
26
+ const verificationMetadataForEnvelope = (envelope) => {
27
+ if (envelope.command !== 'context.verify')
28
+ return {};
29
+ const report = recordOf(envelope.ok ? envelope.data : envelope.error.details);
30
+ const verificationOutcome = verificationOutcomeForReport(report);
31
+ const verificationCheckCount = Array.isArray(report.checks)
32
+ ? report.checks.length
33
+ : undefined;
34
+ const verificationDurationMs = isNonNegativeDuration(report.durationMs)
35
+ ? report.durationMs
36
+ : undefined;
37
+ return {
38
+ ...(verificationOutcome !== undefined ? { verificationOutcome } : {}),
39
+ ...(verificationCheckCount !== undefined ? { verificationCheckCount } : {}),
40
+ ...(verificationDurationMs !== undefined ? { verificationDurationMs } : {}),
41
+ };
42
+ };
43
+ exports.verificationMetadataForEnvelope = verificationMetadataForEnvelope;
8
44
  const browserMetadataForEnvelope = (envelope) => {
9
45
  if (envelope.command !== 'open')
10
46
  return {};