rivet-design 0.27.0 → 0.28.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 (76) 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.d.ts +4 -0
  4. package/dist/agent-variants/PreviewRuntime.js +5 -3
  5. package/dist/agent-variants/SessionStore.d.ts +10 -1
  6. package/dist/agent-variants/SessionStore.js +25 -2
  7. package/dist/agent-variants/WorkItemRequestTimes.d.ts +6 -0
  8. package/dist/agent-variants/WorkItemRequestTimes.js +21 -0
  9. package/dist/agent-variants/WorktreeOrchestrator.d.ts +2 -1
  10. package/dist/agent-variants/WorktreeOrchestrator.js +92 -78
  11. package/dist/agent-variants/contracts.d.ts +8 -0
  12. package/dist/agent-variants/existingStaticEntry.d.ts +34 -0
  13. package/dist/agent-variants/existingStaticEntry.js +136 -0
  14. package/dist/agent-variants/staticPreviewFiles.js +1 -1
  15. package/dist/agent-variants/variant-project-runtime.d.ts +2 -1
  16. package/dist/agent-variants/variantsTelemetry.d.ts +4 -0
  17. package/dist/agent-variants/variantsTelemetry.js +2 -0
  18. package/dist/agent-variants/workItemInput.d.ts +22 -0
  19. package/dist/agent-variants/workItemInput.js +12 -1
  20. package/dist/cli/commands/directionTarget.d.ts +23 -0
  21. package/dist/cli/commands/directionTarget.js +87 -0
  22. package/dist/cli/commands/open.js +28 -4
  23. package/dist/cli/commands/variants.js +36 -43
  24. package/dist/cli/envelope.d.ts +1 -1
  25. package/dist/cli/envelope.js +1 -0
  26. package/dist/cli/projectRuntimeUpgrade.d.ts +11 -0
  27. package/dist/cli/projectRuntimeUpgrade.js +43 -11
  28. package/dist/config/pluginMetrics.js +2 -0
  29. package/dist/config/posthog.d.ts +2 -0
  30. package/dist/config/posthog.js +5 -0
  31. package/dist/mcp/explorationSchema.js +1 -1
  32. package/dist/mcp/getExploration.js +11 -5
  33. package/dist/proxy-middleware/proxy-config.js +7 -0
  34. package/dist/routes/agentVariants.js +4 -0
  35. package/dist/routes/cli.js +10 -1
  36. package/dist/server.js +12 -6
  37. package/dist/services/DependencyPreparationService.js +44 -6
  38. package/dist/services/FeatureFlagService.js +2 -2
  39. package/dist/services/ProjectLibrary.d.ts +4 -1
  40. package/dist/services/ProjectLibrary.js +14 -9
  41. package/dist/services/ProjectRuntimeService.d.ts +8 -0
  42. package/dist/services/ProjectRuntimeService.js +15 -2
  43. package/dist/services/TelemetryService.d.ts +5 -0
  44. package/dist/services/TelemetryService.js +21 -2
  45. package/dist/services/VariantHistoryService.d.ts +8 -0
  46. package/dist/services/VariantHistoryService.js +40 -0
  47. package/dist/services/WorktreeManager.d.ts +1 -0
  48. package/dist/services/WorktreeManager.js +12 -0
  49. package/dist/services/createAgentVariantsOrchestrator.js +9 -2
  50. package/dist/services/directionRefs.d.ts +21 -0
  51. package/dist/services/directionRefs.js +148 -0
  52. package/dist/services/projectDirections.d.ts +22 -0
  53. package/dist/services/projectDirections.js +38 -0
  54. package/dist/types/direction-ref.d.ts +36 -0
  55. package/dist/types/direction-ref.js +3 -0
  56. package/dist/types/variant-history.d.ts +3 -1
  57. package/dist/utils/failureReason.d.ts +1 -1
  58. package/dist/utils/failureReason.js +3 -0
  59. package/dist/utils/skills/cli-guidance.js +4 -3
  60. package/dist/utils/subprocessEnvironment.d.ts +1 -1
  61. package/dist/utils/subprocessEnvironment.js +0 -1
  62. package/package.json +4 -4
  63. package/src/ui/dist/assets/LibraryEntry-BE8nZneH.js +37 -0
  64. package/src/ui/dist/assets/logo.png +0 -0
  65. package/src/ui/dist/assets/main-1EDrDqgn.js +498 -0
  66. package/src/ui/dist/assets/main-qgqnlUkI.css +1 -0
  67. package/src/ui/dist/assets/rivet-wordmark-orange-CYKVQDmG.svg +7 -0
  68. package/src/ui/dist/index.html +2 -2
  69. package/dist/services/StaticPreviewServer.d.ts +0 -8
  70. package/dist/services/StaticPreviewServer.js +0 -207
  71. package/src/ui/dist/assets/LibraryEntry-RI9Lc7P3.js +0 -37
  72. package/src/ui/dist/assets/main-D0UmAaUe.css +0 -1
  73. package/src/ui/dist/assets/main-DgrLzS5j.js +0 -497
  74. package/src/ui/dist/assets/rivet.svg +0 -3
  75. package/src/ui/dist/fonts/Goldman-Bold.woff2 +0 -0
  76. package/src/ui/dist/fonts/Goldman-Regular.woff2 +0 -0
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod/v3';
2
2
  import type { WorkerSelection } from '../types/change-request-types';
3
+ import type { DirectionRef } from '../types/direction-ref';
3
4
  import type { StaticPreviewTargetElement, VariantWorkItem, WorkItem, WorkItemKind } from './contracts';
4
5
  export declare const VARIANT_WORK_ITEM_KINDS: readonly ["static_preview", "refine_variant", "code_gen"];
5
6
  export type VariantWorkItemKind = (typeof VARIANT_WORK_ITEM_KINDS)[number];
@@ -613,6 +614,8 @@ declare const variantWorkItemInputSchemas: {
613
614
  }>;
614
615
  briefBody: z.ZodOptional<z.ZodString>;
615
616
  briefNotes: z.ZodOptional<z.ZodString>;
617
+ directionRef: z.ZodOptional<z.ZodType<DirectionRef, z.ZodTypeDef, DirectionRef>>;
618
+ sourceDirectionRef: z.ZodOptional<z.ZodType<DirectionRef, z.ZodTypeDef, DirectionRef>>;
616
619
  visualReferenceUrl: z.ZodOptional<z.ZodString>;
617
620
  instruction: z.ZodOptional<z.ZodString>;
618
621
  guidance: z.ZodOptional<z.ZodArray<z.ZodType<{
@@ -1427,6 +1430,8 @@ declare const variantWorkItemInputSchemas: {
1427
1430
  workerSelection?: WorkerSelection | undefined;
1428
1431
  briefBody?: string | undefined;
1429
1432
  briefNotes?: string | undefined;
1433
+ directionRef?: DirectionRef | undefined;
1434
+ sourceDirectionRef?: DirectionRef | undefined;
1430
1435
  visualReferenceUrl?: string | undefined;
1431
1436
  guidance?: {
1432
1437
  id: string;
@@ -1927,6 +1932,8 @@ declare const variantWorkItemInputSchemas: {
1927
1932
  workerSelection?: WorkerSelection | undefined;
1928
1933
  briefBody?: string | undefined;
1929
1934
  briefNotes?: string | undefined;
1935
+ directionRef?: DirectionRef | undefined;
1936
+ sourceDirectionRef?: DirectionRef | undefined;
1930
1937
  visualReferenceUrl?: string | undefined;
1931
1938
  guidance?: {
1932
1939
  id: string;
@@ -2595,6 +2602,8 @@ declare const variantWorkItemInputSchemas: {
2595
2602
  briefLabel: z.ZodOptional<z.ZodString>;
2596
2603
  briefBody: z.ZodOptional<z.ZodString>;
2597
2604
  briefNotes: z.ZodOptional<z.ZodString>;
2605
+ directionRef: z.ZodOptional<z.ZodType<DirectionRef, z.ZodTypeDef, DirectionRef>>;
2606
+ sourceDirectionRef: z.ZodOptional<z.ZodType<DirectionRef, z.ZodTypeDef, DirectionRef>>;
2598
2607
  visualReferenceUrl: z.ZodOptional<z.ZodString>;
2599
2608
  guidance: z.ZodOptional<z.ZodArray<z.ZodType<{
2600
2609
  id: string;
@@ -3407,6 +3416,8 @@ declare const variantWorkItemInputSchemas: {
3407
3416
  briefLabel?: string | undefined;
3408
3417
  briefBody?: string | undefined;
3409
3418
  briefNotes?: string | undefined;
3419
+ directionRef?: DirectionRef | undefined;
3420
+ sourceDirectionRef?: DirectionRef | undefined;
3410
3421
  visualReferenceUrl?: string | undefined;
3411
3422
  guidance?: {
3412
3423
  id: string;
@@ -3907,6 +3918,8 @@ declare const variantWorkItemInputSchemas: {
3907
3918
  briefLabel?: string | undefined;
3908
3919
  briefBody?: string | undefined;
3909
3920
  briefNotes?: string | undefined;
3921
+ directionRef?: DirectionRef | undefined;
3922
+ sourceDirectionRef?: DirectionRef | undefined;
3910
3923
  visualReferenceUrl?: string | undefined;
3911
3924
  guidance?: {
3912
3925
  id: string;
@@ -4572,6 +4585,8 @@ declare const variantWorkItemInputSchemas: {
4572
4585
  assetSourceRoot?: string | undefined;
4573
4586
  }>;
4574
4587
  briefNotes: z.ZodOptional<z.ZodString>;
4588
+ directionRef: z.ZodOptional<z.ZodType<DirectionRef, z.ZodTypeDef, DirectionRef>>;
4589
+ sourceDirectionRef: z.ZodOptional<z.ZodType<DirectionRef, z.ZodTypeDef, DirectionRef>>;
4575
4590
  visualReferenceUrl: z.ZodOptional<z.ZodString>;
4576
4591
  instruction: z.ZodOptional<z.ZodString>;
4577
4592
  guidance: z.ZodOptional<z.ZodArray<z.ZodType<{
@@ -5387,6 +5402,8 @@ declare const variantWorkItemInputSchemas: {
5387
5402
  } | undefined;
5388
5403
  workerSelection?: WorkerSelection | undefined;
5389
5404
  briefNotes?: string | undefined;
5405
+ directionRef?: DirectionRef | undefined;
5406
+ sourceDirectionRef?: DirectionRef | undefined;
5390
5407
  visualReferenceUrl?: string | undefined;
5391
5408
  guidance?: {
5392
5409
  id: string;
@@ -5887,6 +5904,8 @@ declare const variantWorkItemInputSchemas: {
5887
5904
  } | undefined;
5888
5905
  workerSelection?: WorkerSelection | undefined;
5889
5906
  briefNotes?: string | undefined;
5907
+ directionRef?: DirectionRef | undefined;
5908
+ sourceDirectionRef?: DirectionRef | undefined;
5890
5909
  visualReferenceUrl?: string | undefined;
5891
5910
  guidance?: {
5892
5911
  id: string;
@@ -5951,6 +5970,9 @@ export type VariantWorkItemInputByKind = {
5951
5970
  [Kind in VariantWorkItemKind]: z.infer<(typeof variantWorkItemInputSchemas)[Kind]>;
5952
5971
  };
5953
5972
  export type VariantWorkItemInput = VariantWorkItemInputByKind[VariantWorkItemKind];
5973
+ export declare const shownDirectionRef: (input: Pick<VariantWorkItemInput, "directionRef" | "sourceDirectionRef">) => {
5974
+ directionRef?: DirectionRef;
5975
+ };
5954
5976
  export declare const parseVariantWorkItemInput: <Kind extends VariantWorkItemKind>(item: {
5955
5977
  id: string;
5956
5978
  kind: Kind;
@@ -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
@@ -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({
@@ -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) => ({
@@ -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',
@@ -120,6 +120,7 @@ const metricProperties = zod_1.z.object({
120
120
  'WAIT_TIMEOUT',
121
121
  'SESSION_NOT_FOUND',
122
122
  'WORK_ITEM_NOT_FOUND',
123
+ 'DIRECTION_AMBIGUOUS',
123
124
  'MCP_REMOVED',
124
125
  'STATIC_PREVIEW_FAILED',
125
126
  'DEV_SERVER_FAILED',
@@ -164,6 +165,7 @@ const metricProperties = zod_1.z.object({
164
165
  'usage_error',
165
166
  'wait_timeout',
166
167
  'session_not_found',
168
+ 'direction_ambiguous',
167
169
  'mcp_removed',
168
170
  'server_start_timeout',
169
171
  'handshake_missing',
@@ -0,0 +1,2 @@
1
+ export declare const POSTHOG_PUBLIC_API_KEY = "phc_Ntj9tXHbS64XgYxlTfhglRmFivFsfm0AERph4ZlnNH";
2
+ //# sourceMappingURL=posthog.d.ts.map
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POSTHOG_PUBLIC_API_KEY = void 0;
4
+ exports.POSTHOG_PUBLIC_API_KEY = 'phc_Ntj9tXHbS64XgYxlTfhglRmFivFsfm0AERph4ZlnNH';
5
+ //# sourceMappingURL=posthog.js.map
@@ -117,7 +117,7 @@ exports.explorationShape = {
117
117
  baseDirectionId: v3_1.z
118
118
  .string()
119
119
  .optional()
120
- .describe('start: sessionId:variantId — refine an existing variant in place'),
120
+ .describe('start: direction ref (e.g. warm-editorial-green), sessionId:variantId, or projectId/sessionId:variantId — refine an existing variant in place'),
121
121
  project: v3_1.z.string().trim().min(1).describe('Absolute project root path'),
122
122
  };
123
123
  //# sourceMappingURL=explorationSchema.js.map
@@ -17,6 +17,8 @@ const ConfigManager_1 = require("../services/ConfigManager");
17
17
  const ProjectLibrary_1 = require("../services/ProjectLibrary");
18
18
  const VariantHistoryService_1 = require("../services/VariantHistoryService");
19
19
  const historyRoots_1 = require("../services/historyRoots");
20
+ const directionRefs_1 = require("../services/directionRefs");
21
+ const projectDirections_1 = require("../services/projectDirections");
20
22
  const profileAccess_1 = require("./profileAccess");
21
23
  const getExploration = async (input) => {
22
24
  const command = 'rivet_get_exploration';
@@ -68,12 +70,16 @@ const getExploration = async (input) => {
68
70
  ? registered.library.registry.historyRoots(registered.owner.id)
69
71
  : [project, ...(0, historyRoots_1.nestedFreshSessionWorkdirs)(project)];
70
72
  if (!hasLiveServer || input.includeHistory || input.sessionId) {
73
+ const directions = await (0, projectDirections_1.listProjectDirections)(registered
74
+ ? {
75
+ kind: 'library',
76
+ library: registered.library,
77
+ projectId: registered.owner.id,
78
+ }
79
+ : { kind: 'history', history, projectPath: project });
71
80
  const entries = registered
72
- ? await registered.library.listVariants(registered.owner.id)
73
- : (await Promise.all(roots.map(async (projectPath) => (await history.listVariants({ projectPath })).map((entry) => ({
74
- ...entry,
75
- projectPath,
76
- }))))).flat();
81
+ ? directions.filter((entry) => (0, directionRefs_1.isDirectionActive)(entry.manifest.status))
82
+ : directions;
77
83
  data.history = entries.filter((entry) => (!input.sessionId || entry.manifest.sessionId === input.sessionId) &&
78
84
  (!input.variantId || entry.manifest.variantId === input.variantId));
79
85
  if (input.variantId && input.sessionId) {
@@ -13,6 +13,10 @@ const TARGET_ADDRESSED_PREVIEW_PREFIX = '/__rivet/preview';
13
13
  const TARGET_ADDRESSED_PREVIEW_KIND_BASE = 'base';
14
14
  const TARGET_ADDRESSED_PREVIEW_KIND_HISTORY = 'history';
15
15
  const TARGET_ADDRESSED_PREVIEW_KIND_VARIANT = 'variant';
16
+ const CACHE_VALIDATOR_REQUEST_HEADERS = [
17
+ 'if-none-match',
18
+ 'if-modified-since',
19
+ ];
16
20
  const hasValidUserDevPort = (userPort) => Number.isInteger(userPort) && userPort > 0;
17
21
  const resolveTargetAddressedPreview = (args) => {
18
22
  const parsed = new URL(args.rawUrl ?? '/', 'http://rivet.local');
@@ -152,6 +156,9 @@ const createUserDevServerProxy = (userPort, userHost = 'localhost', options = {}
152
156
  requestTargets.set(req, target);
153
157
  if (target.isTargetAddressed) {
154
158
  req.url = target.path;
159
+ for (const header of CACHE_VALIDATOR_REQUEST_HEADERS) {
160
+ delete req.headers[header];
161
+ }
155
162
  }
156
163
  };
157
164
  const getRouterTargetForLibrary = (req) => {