rivet-design 0.10.7 → 0.10.9

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 (170) hide show
  1. package/dist/index.d.ts +54 -3
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +302 -129
  4. package/dist/index.js.map +1 -1
  5. package/dist/mcp/agent-variants/SessionStore.d.ts +23 -1
  6. package/dist/mcp/agent-variants/SessionStore.d.ts.map +1 -1
  7. package/dist/mcp/agent-variants/SessionStore.js +42 -0
  8. package/dist/mcp/agent-variants/SessionStore.js.map +1 -1
  9. package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts +99 -2
  10. package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts.map +1 -1
  11. package/dist/mcp/agent-variants/WorktreeOrchestrator.js +734 -74
  12. package/dist/mcp/agent-variants/WorktreeOrchestrator.js.map +1 -1
  13. package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.d.ts +8 -2
  14. package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.d.ts.map +1 -1
  15. package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js +24 -5
  16. package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js.map +1 -1
  17. package/dist/mcp/agent-variants/contracts.d.ts +1175 -233
  18. package/dist/mcp/agent-variants/contracts.d.ts.map +1 -1
  19. package/dist/mcp/agent-variants/contracts.js +12 -4
  20. package/dist/mcp/agent-variants/contracts.js.map +1 -1
  21. package/dist/mcp/agent-variants/designCritique.d.ts +163 -0
  22. package/dist/mcp/agent-variants/designCritique.d.ts.map +1 -0
  23. package/dist/mcp/agent-variants/designCritique.js +710 -0
  24. package/dist/mcp/agent-variants/designCritique.js.map +1 -0
  25. package/dist/mcp/agent-variants/diffQa.d.ts +7 -0
  26. package/dist/mcp/agent-variants/diffQa.d.ts.map +1 -0
  27. package/dist/mcp/agent-variants/diffQa.js +67 -0
  28. package/dist/mcp/agent-variants/diffQa.js.map +1 -0
  29. package/dist/mcp/agent-variants/index.d.ts +2 -2
  30. package/dist/mcp/agent-variants/index.d.ts.map +1 -1
  31. package/dist/mcp/agent-variants/index.js +2 -1
  32. package/dist/mcp/agent-variants/index.js.map +1 -1
  33. package/dist/mcp/agent-variants/pinterestSourceContext.d.ts.map +1 -1
  34. package/dist/mcp/agent-variants/pinterestSourceContext.js +11 -1
  35. package/dist/mcp/agent-variants/pinterestSourceContext.js.map +1 -1
  36. package/dist/mcp/agent-variants/previewQa.d.ts.map +1 -1
  37. package/dist/mcp/agent-variants/previewQa.js +7 -0
  38. package/dist/mcp/agent-variants/previewQa.js.map +1 -1
  39. package/dist/mcp/agent-variants/tools.d.ts.map +1 -1
  40. package/dist/mcp/agent-variants/tools.js +15 -5
  41. package/dist/mcp/agent-variants/tools.js.map +1 -1
  42. package/dist/mcp/auth/httpOAuthProvider.d.ts +103 -0
  43. package/dist/mcp/auth/httpOAuthProvider.d.ts.map +1 -0
  44. package/dist/mcp/auth/httpOAuthProvider.js +454 -0
  45. package/dist/mcp/auth/httpOAuthProvider.js.map +1 -0
  46. package/dist/mcp/auth/tools.d.ts +2 -0
  47. package/dist/mcp/auth/tools.d.ts.map +1 -1
  48. package/dist/mcp/auth/tools.js +12 -5
  49. package/dist/mcp/auth/tools.js.map +1 -1
  50. package/dist/mcp/httpServer.d.ts +36 -0
  51. package/dist/mcp/httpServer.d.ts.map +1 -0
  52. package/dist/mcp/httpServer.js +307 -0
  53. package/dist/mcp/httpServer.js.map +1 -0
  54. package/dist/mcp/server.d.ts +17 -0
  55. package/dist/mcp/server.d.ts.map +1 -1
  56. package/dist/mcp/server.js +50 -29
  57. package/dist/mcp/server.js.map +1 -1
  58. package/dist/proxy-middleware/proxy-config.d.ts.map +1 -1
  59. package/dist/proxy-middleware/proxy-config.js +5 -2
  60. package/dist/proxy-middleware/proxy-config.js.map +1 -1
  61. package/dist/routes/agentVariants.d.ts +2 -1
  62. package/dist/routes/agentVariants.d.ts.map +1 -1
  63. package/dist/routes/agentVariants.js +268 -19
  64. package/dist/routes/agentVariants.js.map +1 -1
  65. package/dist/routes/design.d.ts.map +1 -1
  66. package/dist/routes/design.js +0 -122
  67. package/dist/routes/design.js.map +1 -1
  68. package/dist/routes/mcp.d.ts.map +1 -1
  69. package/dist/routes/mcp.js +2 -1
  70. package/dist/routes/mcp.js.map +1 -1
  71. package/dist/server.d.ts +15 -0
  72. package/dist/server.d.ts.map +1 -1
  73. package/dist/server.js +24 -11
  74. package/dist/server.js.map +1 -1
  75. package/dist/services/AgentSessionService.d.ts +5 -1
  76. package/dist/services/AgentSessionService.d.ts.map +1 -1
  77. package/dist/services/AgentSessionService.js +11 -4
  78. package/dist/services/AgentSessionService.js.map +1 -1
  79. package/dist/services/AuthService.d.ts +1 -0
  80. package/dist/services/AuthService.d.ts.map +1 -1
  81. package/dist/services/AuthService.js +11 -1
  82. package/dist/services/AuthService.js.map +1 -1
  83. package/dist/services/ConfigManager.d.ts +5 -0
  84. package/dist/services/ConfigManager.d.ts.map +1 -1
  85. package/dist/services/ConfigManager.js +25 -3
  86. package/dist/services/ConfigManager.js.map +1 -1
  87. package/dist/services/DevServerRuntimeService.d.ts +119 -0
  88. package/dist/services/DevServerRuntimeService.d.ts.map +1 -0
  89. package/dist/services/DevServerRuntimeService.js +657 -0
  90. package/dist/services/DevServerRuntimeService.js.map +1 -0
  91. package/dist/services/GatewayClient.d.ts +25 -0
  92. package/dist/services/GatewayClient.d.ts.map +1 -1
  93. package/dist/services/GatewayClient.js +70 -11
  94. package/dist/services/GatewayClient.js.map +1 -1
  95. package/dist/services/InlineVariantGenerationService.d.ts +2 -3
  96. package/dist/services/InlineVariantGenerationService.d.ts.map +1 -1
  97. package/dist/services/InlineVariantGenerationService.js +7 -5
  98. package/dist/services/InlineVariantGenerationService.js.map +1 -1
  99. package/dist/services/IntegrationsClient.d.ts +20 -0
  100. package/dist/services/IntegrationsClient.d.ts.map +1 -1
  101. package/dist/services/IntegrationsClient.js +82 -24
  102. package/dist/services/IntegrationsClient.js.map +1 -1
  103. package/dist/services/RequestAuthContext.d.ts +7 -1
  104. package/dist/services/RequestAuthContext.d.ts.map +1 -1
  105. package/dist/services/RequestAuthContext.js +15 -2
  106. package/dist/services/RequestAuthContext.js.map +1 -1
  107. package/dist/services/SessionBridgeService.d.ts +1 -0
  108. package/dist/services/SessionBridgeService.d.ts.map +1 -1
  109. package/dist/services/SessionBridgeService.js +16 -1
  110. package/dist/services/SessionBridgeService.js.map +1 -1
  111. package/dist/services/TelemetryService.d.ts +2 -0
  112. package/dist/services/TelemetryService.d.ts.map +1 -1
  113. package/dist/services/TelemetryService.js +2 -0
  114. package/dist/services/TelemetryService.js.map +1 -1
  115. package/dist/services/VariantHistoryService.d.ts +8 -0
  116. package/dist/services/VariantHistoryService.d.ts.map +1 -1
  117. package/dist/services/VariantHistoryService.js +23 -0
  118. package/dist/services/VariantHistoryService.js.map +1 -1
  119. package/dist/services/VariantRunService.d.ts +56 -0
  120. package/dist/services/VariantRunService.d.ts.map +1 -0
  121. package/dist/services/VariantRunService.js +56 -0
  122. package/dist/services/VariantRunService.js.map +1 -0
  123. package/dist/services/VariantsRuntime.d.ts +22 -0
  124. package/dist/services/VariantsRuntime.d.ts.map +1 -0
  125. package/dist/services/VariantsRuntime.js +32 -0
  126. package/dist/services/VariantsRuntime.js.map +1 -0
  127. package/dist/services/VisualVariantAgentRunner.d.ts +20 -0
  128. package/dist/services/VisualVariantAgentRunner.d.ts.map +1 -0
  129. package/dist/services/VisualVariantAgentRunner.js +66 -0
  130. package/dist/services/VisualVariantAgentRunner.js.map +1 -0
  131. package/dist/services/WorktreeManager.d.ts +34 -0
  132. package/dist/services/WorktreeManager.d.ts.map +1 -1
  133. package/dist/services/WorktreeManager.js +172 -23
  134. package/dist/services/WorktreeManager.js.map +1 -1
  135. package/dist/services/createAgentVariantsOrchestrator.d.ts.map +1 -1
  136. package/dist/services/createAgentVariantsOrchestrator.js +9 -0
  137. package/dist/services/createAgentVariantsOrchestrator.js.map +1 -1
  138. package/dist/utils/devServerCommand.d.ts +11 -4
  139. package/dist/utils/devServerCommand.d.ts.map +1 -1
  140. package/dist/utils/devServerCommand.js +17 -8
  141. package/dist/utils/devServerCommand.js.map +1 -1
  142. package/dist/utils/devServerError.d.ts +34 -0
  143. package/dist/utils/devServerError.d.ts.map +1 -0
  144. package/dist/utils/devServerError.js +39 -0
  145. package/dist/utils/devServerError.js.map +1 -0
  146. package/dist/utils/elementRefToContext.d.ts +4 -0
  147. package/dist/utils/elementRefToContext.d.ts.map +1 -0
  148. package/dist/utils/elementRefToContext.js +63 -0
  149. package/dist/utils/elementRefToContext.js.map +1 -0
  150. package/dist/utils/skills/shared-variants-protocol.d.ts.map +1 -1
  151. package/dist/utils/skills/shared-variants-protocol.js +5 -2
  152. package/dist/utils/skills/shared-variants-protocol.js.map +1 -1
  153. package/dist/utils/variantSessionStart.d.ts +3 -0
  154. package/dist/utils/variantSessionStart.d.ts.map +1 -0
  155. package/dist/utils/variantSessionStart.js +7 -0
  156. package/dist/utils/variantSessionStart.js.map +1 -0
  157. package/package.json +3 -1
  158. package/src/ui/dist/assets/main-Cwwhwfjq.js +645 -0
  159. package/src/ui/dist/assets/main-Do6whVIm.css +1 -0
  160. package/src/ui/dist/index.html +2 -2
  161. package/dist/services/CommentVariationService.d.ts +0 -34
  162. package/dist/services/CommentVariationService.d.ts.map +0 -1
  163. package/dist/services/CommentVariationService.js +0 -136
  164. package/dist/services/CommentVariationService.js.map +0 -1
  165. package/dist/services/VariantCodeGeneratorService.d.ts +0 -39
  166. package/dist/services/VariantCodeGeneratorService.d.ts.map +0 -1
  167. package/dist/services/VariantCodeGeneratorService.js +0 -109
  168. package/dist/services/VariantCodeGeneratorService.js.map +0 -1
  169. package/src/ui/dist/assets/main-DUIrSkV3.css +0 -1
  170. package/src/ui/dist/assets/main-DYpxGvCu.js +0 -646
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VariantRunService = void 0;
4
+ const InlineVariantGenerationService_1 = require("./InlineVariantGenerationService");
5
+ /**
6
+ * Product-facing entry point for variant runs.
7
+ *
8
+ * Keeps callers independent from the lower-level variants state machine so
9
+ * desktop UI, MCP requests, and future hosted workers can start/refine/commit
10
+ * variants through the same lifecycle.
11
+ */
12
+ class VariantRunService {
13
+ orchestrator;
14
+ elementVariantService;
15
+ constructor(options) {
16
+ this.orchestrator = options.orchestrator;
17
+ this.elementVariantService = new InlineVariantGenerationService_1.InlineVariantGenerationService({
18
+ bridge: options.bridge,
19
+ orchestrator: options.orchestrator,
20
+ runner: options.runner,
21
+ createSessionId: options.createSessionId,
22
+ leaseHeartbeatMs: options.leaseHeartbeatMs,
23
+ });
24
+ }
25
+ /**
26
+ * @effect Starts variants for a selected/commented element using the shared
27
+ * variants lifecycle.
28
+ */
29
+ async startElementVariants(request) {
30
+ return this.elementVariantService.processVariantRequest(request);
31
+ }
32
+ /**
33
+ * @effect Starts a refinement work item for an existing static preview variant.
34
+ */
35
+ refineVariant(args) {
36
+ return this.orchestrator.refineVariant(args);
37
+ }
38
+ /**
39
+ * @effect Commits the chosen variant through the shared orchestrator path.
40
+ */
41
+ commitVariant(args) {
42
+ return this.orchestrator.commitVariant(args);
43
+ }
44
+ /**
45
+ * @effect Cancels a variants session and lets the orchestrator clean up.
46
+ */
47
+ cancelVariants(args) {
48
+ return this.orchestrator.cancel(args);
49
+ }
50
+ /** Returns the active variants snapshot for UI and orchestration callers. */
51
+ getSnapshot() {
52
+ return this.orchestrator.buildActiveSnapshot();
53
+ }
54
+ }
55
+ exports.VariantRunService = VariantRunService;
56
+ //# sourceMappingURL=VariantRunService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VariantRunService.js","sourceRoot":"","sources":["../../src/services/VariantRunService.ts"],"names":[],"mappings":";;;AAOA,qFAG0C;AAW1C;;;;;;GAMG;AACH,MAAa,iBAAiB;IACX,YAAY,CAA4B;IACxC,qBAAqB,CAAiC;IAEvE,YAAY,OAAiC;QAC3C,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACzC,IAAI,CAAC,qBAAqB,GAAG,IAAI,+DAA8B,CAAC;YAC9D,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,eAAe,EAAE,OAAO,CAAC,eAAe;YACxC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;SAC3C,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,oBAAoB,CACxB,OAAsB;QAEtB,OAAO,IAAI,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACnE,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,IAKb;QACC,OAAO,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,IAIb;QACC,OAAO,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,IAGd;QACC,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IAED,6EAA6E;IAC7E,WAAW;QACT,OAAO,IAAI,CAAC,YAAY,CAAC,mBAAmB,EAAE,CAAC;IACjD,CAAC;CACF;AA9DD,8CA8DC"}
@@ -0,0 +1,22 @@
1
+ import type { AgentVariantsOrchestrator } from '../mcp/agent-variants';
2
+ import { SessionBridgeService } from './SessionBridgeService';
3
+ import type { TelemetryService } from './TelemetryService';
4
+ import { VariantRunService } from './VariantRunService';
5
+ import type { InlineVariantAgentRunner } from './InlineVariantGenerationService';
6
+ export type VariantsRuntime = {
7
+ bridge: SessionBridgeService;
8
+ orchestrator: AgentVariantsOrchestrator;
9
+ runService: VariantRunService;
10
+ };
11
+ export type CreateVariantsRuntimeOptions = {
12
+ projectPath: string;
13
+ telemetry?: TelemetryService;
14
+ runner: InlineVariantAgentRunner;
15
+ devServerContext?: Parameters<SessionBridgeService['setDevServerContext']>[0];
16
+ devServerHealth?: Parameters<SessionBridgeService['updateDevServerHealth']>[0];
17
+ };
18
+ /**
19
+ * Creates the shared runtime used to start, preview, refine, and commit variant sessions.
20
+ */
21
+ export declare const createVariantsRuntime: (options: CreateVariantsRuntimeOptions) => VariantsRuntime;
22
+ //# sourceMappingURL=VariantsRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VariantsRuntime.d.ts","sourceRoot":"","sources":["../../src/services/VariantsRuntime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAEvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAEjF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,oBAAoB,CAAC;IAC7B,YAAY,EAAE,yBAAyB,CAAC;IACxC,UAAU,EAAE,iBAAiB,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,MAAM,EAAE,wBAAwB,CAAC;IACjC,gBAAgB,CAAC,EAAE,UAAU,CAAC,oBAAoB,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,eAAe,CAAC,EAAE,UAAU,CAC1B,oBAAoB,CAAC,uBAAuB,CAAC,CAC9C,CAAC,CAAC,CAAC,CAAC;CACN,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAChC,SAAS,4BAA4B,KACpC,eAsBF,CAAC"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createVariantsRuntime = void 0;
4
+ const createAgentVariantsOrchestrator_1 = require("./createAgentVariantsOrchestrator");
5
+ const SessionBridgeService_1 = require("./SessionBridgeService");
6
+ const VariantRunService_1 = require("./VariantRunService");
7
+ /**
8
+ * Creates the shared runtime used to start, preview, refine, and commit variant sessions.
9
+ */
10
+ const createVariantsRuntime = (options) => {
11
+ const bridge = new SessionBridgeService_1.SessionBridgeService();
12
+ bridge.startSession(options.projectPath);
13
+ if (options.devServerContext) {
14
+ bridge.setDevServerContext(options.devServerContext);
15
+ }
16
+ if (options.devServerHealth) {
17
+ bridge.updateDevServerHealth(options.devServerHealth);
18
+ }
19
+ const orchestrator = (0, createAgentVariantsOrchestrator_1.createAgentVariantsOrchestrator)({
20
+ bridge,
21
+ telemetry: options.telemetry,
22
+ projectPathFallback: options.projectPath,
23
+ });
24
+ const runService = new VariantRunService_1.VariantRunService({
25
+ bridge,
26
+ orchestrator,
27
+ runner: options.runner,
28
+ });
29
+ return { bridge, orchestrator, runService };
30
+ };
31
+ exports.createVariantsRuntime = createVariantsRuntime;
32
+ //# sourceMappingURL=VariantsRuntime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VariantsRuntime.js","sourceRoot":"","sources":["../../src/services/VariantsRuntime.ts"],"names":[],"mappings":";;;AACA,uFAAoF;AACpF,iEAA8D;AAE9D,2DAAwD;AAmBxD;;GAEG;AACI,MAAM,qBAAqB,GAAG,CACnC,OAAqC,EACpB,EAAE;IACnB,MAAM,MAAM,GAAG,IAAI,2CAAoB,EAAE,CAAC;IAC1C,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACzC,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC7B,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;QAC5B,MAAM,CAAC,qBAAqB,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,YAAY,GAAG,IAAA,iEAA+B,EAAC;QACnD,MAAM;QACN,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,mBAAmB,EAAE,OAAO,CAAC,WAAW;KACzC,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,IAAI,qCAAiB,CAAC;QACvC,MAAM;QACN,YAAY;QACZ,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AAC9C,CAAC,CAAC;AAxBW,QAAA,qBAAqB,yBAwBhC"}
@@ -0,0 +1,20 @@
1
+ import type { ChangeRequest } from '../types/change-request-types';
2
+ import type { InlineVariantAgentRunner } from './InlineVariantGenerationService';
3
+ import type { TerminalAgentRunResult } from './TerminalAgentRunner';
4
+ /**
5
+ * Runs variant work items through the visual editor's direct agent modification path.
6
+ */
7
+ export declare class VisualVariantAgentRunner implements InlineVariantAgentRunner {
8
+ getDisplayName(): string;
9
+ /**
10
+ * @effect Executes a single variant request in the provided worktree and streams feedback to the variants lifecycle.
11
+ */
12
+ runChangeRequest(params: {
13
+ request: ChangeRequest;
14
+ cwd: string;
15
+ sessionId: string;
16
+ resumeSession?: boolean;
17
+ onFeedback: (message: string) => void;
18
+ }): Promise<TerminalAgentRunResult>;
19
+ }
20
+ //# sourceMappingURL=VisualVariantAgentRunner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VisualVariantAgentRunner.d.ts","sourceRoot":"","sources":["../../src/services/VisualVariantAgentRunner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,aAAa,EAGd,MAAM,+BAA+B,CAAC;AAIvC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AACjF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAyCpE;;GAEG;AACH,qBAAa,wBAAyB,YAAW,wBAAwB;IACvE,cAAc,IAAI,MAAM;IAIxB;;OAEG;IACG,gBAAgB,CAAC,MAAM,EAAE;QAC7B,OAAO,EAAE,aAAa,CAAC;QACvB,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;KACvC,GAAG,OAAO,CAAC,sBAAsB,CAAC;CAsCpC"}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VisualVariantAgentRunner = void 0;
4
+ const elementRefToContext_1 = require("../utils/elementRefToContext");
5
+ const agent_1 = require("./agent");
6
+ const commentChanges = (request) => request.changes.filter((change) => change.kind === 'comment');
7
+ const buildInstruction = (request) => {
8
+ const comments = commentChanges(request);
9
+ if (comments.length === 0) {
10
+ return 'Apply the requested variant changes.';
11
+ }
12
+ if (comments.length === 1) {
13
+ return comments[0].instruction;
14
+ }
15
+ return comments
16
+ .map((comment, index) => `Comment ${index + 1}: ${comment.instruction}`)
17
+ .join('\n\n');
18
+ };
19
+ const buildElements = (request) => {
20
+ const elements = commentChanges(request).flatMap((comment) => (comment.elements?.length ? comment.elements : [comment.element]).map(elementRefToContext_1.elementRefToContext));
21
+ if (elements.length > 0) {
22
+ return elements;
23
+ }
24
+ return request.changes
25
+ .filter((change) => 'element' in change)
26
+ .map((change) => (0, elementRefToContext_1.elementRefToContext)(change.element));
27
+ };
28
+ /**
29
+ * Runs variant work items through the visual editor's direct agent modification path.
30
+ */
31
+ class VisualVariantAgentRunner {
32
+ getDisplayName() {
33
+ return 'Rivet agent';
34
+ }
35
+ /**
36
+ * @effect Executes a single variant request in the provided worktree and streams feedback to the variants lifecycle.
37
+ */
38
+ async runChangeRequest(params) {
39
+ const service = new agent_1.AgentModService(params.cwd);
40
+ const result = await service.executeAgenticModification(buildInstruction(params.request), buildElements(params.request), (event) => {
41
+ if (event.type === 'error' && event.error) {
42
+ params.onFeedback(event.error);
43
+ return;
44
+ }
45
+ if (event.type === 'step' && event.step?.type === 'reasoning') {
46
+ const data = event.step.data;
47
+ if (typeof data.text === 'string' && data.text.trim()) {
48
+ params.onFeedback(data.text.trim());
49
+ }
50
+ }
51
+ }, undefined, undefined, params.resumeSession ? params.sessionId : undefined, undefined, {
52
+ traceId: params.request.traceId ?? params.sessionId,
53
+ agentRunId: params.request.agentRunId ?? params.sessionId,
54
+ posthogSessionId: params.request.telemetryContext?.browserSessionId ?? undefined,
55
+ });
56
+ if (!result.success) {
57
+ return {
58
+ success: false,
59
+ error: result.changes || 'Variant generation failed',
60
+ };
61
+ }
62
+ return { success: true };
63
+ }
64
+ }
65
+ exports.VisualVariantAgentRunner = VisualVariantAgentRunner;
66
+ //# sourceMappingURL=VisualVariantAgentRunner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VisualVariantAgentRunner.js","sourceRoot":"","sources":["../../src/services/VisualVariantAgentRunner.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,15 @@ export declare const FRESH_WORKTREES_DIRNAME = ".rivet-variants";
6
6
  export declare const INSTANCE_PREFIX: string;
7
7
  export declare class WorktreeManager {
8
8
  private readonly resolveProjectPath;
9
+ /**
10
+ * Ports handed out by `findFreePortFrom` to a dev server that hasn't bound
11
+ * them yet. Until a port is actually listening, a bind/connect probe still
12
+ * sees it as free, so without this set two concurrent variant starts would
13
+ * both walk away with the same "free" port and collide. Released (see
14
+ * `releasePort`) once the dev server has bound the port — at which point the
15
+ * listener check sees it taken — or has failed to start.
16
+ */
17
+ private readonly reservedPorts;
9
18
  /**
10
19
  * Accepts either a static path, null, or a lazy getter. The getter form
11
20
  * lets long-lived callers (e.g. the agent-variants orchestrator) defer the
@@ -96,6 +105,31 @@ export declare class WorktreeManager {
96
105
  applyDiffToProject(diff: string, projectPath: string): Promise<void>;
97
106
  /** Bind port 0 to get an OS-assigned free port */
98
107
  getFreePort(): Promise<number>;
108
+ /**
109
+ * Find a free port by scanning upward from `startPort` (the framework's
110
+ * default, e.g. 3000 for Next, 5173 for Vite). Returns the first port that is
111
+ * both bindable and not already reserved by a concurrent variant start, so a
112
+ * preview comes up on a sensible, predictable port near the project's normal
113
+ * one — and naturally steps past a port the user's own dev server already
114
+ * holds — instead of a random high port. Falls back to an OS-assigned port if
115
+ * the scan window is exhausted.
116
+ *
117
+ * Port availability is delegated to {@link findAvailablePort}, which (unlike a
118
+ * plain bind check) also rejects a port with an active listener on 127.0.0.1
119
+ * or ::1 — the ports that actually carry `localhost` preview traffic.
120
+ *
121
+ * The returned port is reserved synchronously; the caller MUST `releasePort`
122
+ * it once the dev server has bound it or failed to start (the orchestrator
123
+ * does this in a `finally`). Reserving here is what stops two concurrent
124
+ * starts — neither of which has bound its port yet — from both picking it.
125
+ */
126
+ findFreePortFrom(startPort: number, scanWindow?: number): Promise<number>;
127
+ /**
128
+ * Release a port previously handed out by {@link findFreePortFrom}. Call once
129
+ * the dev server has bound it (the listener check now sees it taken, so the
130
+ * reservation is redundant) or has failed to start (the port is free again).
131
+ */
132
+ releasePort(port: number): void;
99
133
  /** Validate a diff via `git apply --check` without modifying files */
100
134
  validateDiff(diff: string, reverse: boolean): Promise<void>;
101
135
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"WorktreeManager.d.ts","sourceRoot":"","sources":["../../src/services/WorktreeManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WorktreeManager.d.ts","sourceRoot":"","sources":["../../src/services/WorktreeManager.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,18 @@ const logger_1 = require("../utils/logger");
14
14
  const designCatalog_1 = require("./templates/designCatalog");
15
15
  const viteReactTs_1 = require("./templates/viteReactTs");
16
16
  const sourceContext_1 = require("../mcp/agent-variants/sourceContext");
17
+ const devServerError_1 = require("../utils/devServerError");
18
+ const portUtils_1 = require("../utils/portUtils");
17
19
  const log = (0, logger_1.createLogger)('WorktreeManager');
20
+ // How long to wait for a freshly-spawned dev server to answer on its port
21
+ // before giving up. Generous because cold Vite/Next boots (esp. first compile)
22
+ // can take 10s+. The probe now fails fast on early process exit, so this
23
+ // ceiling only governs the "spawned but slow / never serves our port" case.
24
+ const DEV_SERVER_READY_TIMEOUT_MS = 30_000;
25
+ // Keep a rolling tail of the dev server's output so a failed start is
26
+ // diagnosable (which port it tried, EADDRINUSE, missing script) without
27
+ // retaining unbounded logs.
28
+ const DEV_SERVER_OUTPUT_TAIL_LIMIT = 4_000;
18
29
  // Abort any git child process that goes silent (no stdout/stderr) for this
19
30
  // long. Provisioning worktrees for a large project (e.g. React Native, whose
20
31
  // working tree carries native build dirs) used to hang indefinitely because
@@ -43,6 +54,15 @@ const FRESH_ROOTS_REGISTRY_PATH = path_1.default.join(os_1.default.homedir(), '.
43
54
  const FRESH_SESSION_ERROR = 'Fresh-project sessions have no source project — this operation requires an existing project path.';
44
55
  class WorktreeManager {
45
56
  resolveProjectPath;
57
+ /**
58
+ * Ports handed out by `findFreePortFrom` to a dev server that hasn't bound
59
+ * them yet. Until a port is actually listening, a bind/connect probe still
60
+ * sees it as free, so without this set two concurrent variant starts would
61
+ * both walk away with the same "free" port and collide. Released (see
62
+ * `releasePort`) once the dev server has bound the port — at which point the
63
+ * listener check sees it taken — or has failed to start.
64
+ */
65
+ reservedPorts = new Set();
46
66
  /**
47
67
  * Accepts either a static path, null, or a lazy getter. The getter form
48
68
  * lets long-lived callers (e.g. the agent-variants orchestrator) defer the
@@ -184,8 +204,7 @@ class WorktreeManager {
184
204
  symlinkNodeModulesIfAvailable(sourceRoot, destRoot) {
185
205
  const nodeModulesSource = path_1.default.join(sourceRoot, 'node_modules');
186
206
  const nodeModulesDest = path_1.default.join(destRoot, 'node_modules');
187
- if (fs_1.default.existsSync(nodeModulesSource) &&
188
- !fs_1.default.existsSync(nodeModulesDest)) {
207
+ if (fs_1.default.existsSync(nodeModulesSource) && !fs_1.default.existsSync(nodeModulesDest)) {
189
208
  fs_1.default.mkdirSync(destRoot, { recursive: true });
190
209
  fs_1.default.symlinkSync(nodeModulesSource, nodeModulesDest);
191
210
  }
@@ -193,9 +212,14 @@ class WorktreeManager {
193
212
  /** Apply a patch string via stdin to the given cwd using git apply */
194
213
  applyPatchViaStdin(patch, cwd) {
195
214
  return new Promise((resolve, reject) => {
196
- const cp = (0, child_process_1.spawn)('git', ['apply', '--whitespace=nowarn', '-'], { cwd, stdio: ['pipe', 'pipe', 'pipe'] });
215
+ const cp = (0, child_process_1.spawn)('git', ['apply', '--whitespace=nowarn', '-'], {
216
+ cwd,
217
+ stdio: ['pipe', 'pipe', 'pipe'],
218
+ });
197
219
  let stderr = '';
198
- cp.stderr.on('data', (d) => { stderr += d.toString(); });
220
+ cp.stderr.on('data', (d) => {
221
+ stderr += d.toString();
222
+ });
199
223
  cp.on('close', (code) => {
200
224
  if (code !== 0)
201
225
  reject(new Error(`git apply failed: ${stderr}`));
@@ -314,7 +338,9 @@ class WorktreeManager {
314
338
  stdio: ['pipe', 'pipe', 'pipe'],
315
339
  });
316
340
  let stderr = '';
317
- cp.stderr.on('data', (d) => { stderr += d.toString(); });
341
+ cp.stderr.on('data', (d) => {
342
+ stderr += d.toString();
343
+ });
318
344
  cp.on('close', (code) => {
319
345
  if (code !== 0)
320
346
  reject(new Error(`git apply failed: ${stderr}`));
@@ -347,6 +373,62 @@ class WorktreeManager {
347
373
  server.on('error', reject);
348
374
  });
349
375
  }
376
+ /**
377
+ * Find a free port by scanning upward from `startPort` (the framework's
378
+ * default, e.g. 3000 for Next, 5173 for Vite). Returns the first port that is
379
+ * both bindable and not already reserved by a concurrent variant start, so a
380
+ * preview comes up on a sensible, predictable port near the project's normal
381
+ * one — and naturally steps past a port the user's own dev server already
382
+ * holds — instead of a random high port. Falls back to an OS-assigned port if
383
+ * the scan window is exhausted.
384
+ *
385
+ * Port availability is delegated to {@link findAvailablePort}, which (unlike a
386
+ * plain bind check) also rejects a port with an active listener on 127.0.0.1
387
+ * or ::1 — the ports that actually carry `localhost` preview traffic.
388
+ *
389
+ * The returned port is reserved synchronously; the caller MUST `releasePort`
390
+ * it once the dev server has bound it or failed to start (the orchestrator
391
+ * does this in a `finally`). Reserving here is what stops two concurrent
392
+ * starts — neither of which has bound its port yet — from both picking it.
393
+ */
394
+ async findFreePortFrom(startPort, scanWindow = 64) {
395
+ const base = Number.isInteger(startPort) && startPort > 0 && startPort <= 65535
396
+ ? startPort
397
+ : 3000;
398
+ const limit = Math.min(65535, base + scanWindow - 1);
399
+ let from = base;
400
+ while (from <= limit) {
401
+ let candidate;
402
+ try {
403
+ candidate = await (0, portUtils_1.findAvailablePort)(from);
404
+ }
405
+ catch {
406
+ break; // no bindable port between `from` and 65535
407
+ }
408
+ if (candidate > limit)
409
+ break; // first free port is outside the scan window
410
+ // Check-and-claim with no `await` in between, so two concurrent callers
411
+ // can't both observe the same port as unreserved before claiming it.
412
+ if (!this.reservedPorts.has(candidate)) {
413
+ this.reservedPorts.add(candidate);
414
+ return candidate;
415
+ }
416
+ from = candidate + 1; // reserved by a sibling start — step past it
417
+ }
418
+ // Scan window exhausted (or every free port in it is reserved by a sibling
419
+ // that hasn't bound yet) — fall back to an OS-assigned ephemeral port.
420
+ const fallback = await this.getFreePort();
421
+ this.reservedPorts.add(fallback);
422
+ return fallback;
423
+ }
424
+ /**
425
+ * Release a port previously handed out by {@link findFreePortFrom}. Call once
426
+ * the dev server has bound it (the listener check now sees it taken, so the
427
+ * reservation is redundant) or has failed to start (the port is free again).
428
+ */
429
+ releasePort(port) {
430
+ this.reservedPorts.delete(port);
431
+ }
350
432
  /** Validate a diff via `git apply --check` without modifying files */
351
433
  validateDiff(diff, reverse) {
352
434
  if (!diff.trim())
@@ -361,7 +443,9 @@ class WorktreeManager {
361
443
  stdio: ['pipe', 'pipe', 'pipe'],
362
444
  });
363
445
  let stderr = '';
364
- cp.stderr.on('data', (d) => { stderr += d.toString(); });
446
+ cp.stderr.on('data', (d) => {
447
+ stderr += d.toString();
448
+ });
365
449
  cp.on('close', (code) => {
366
450
  if (code !== 0)
367
451
  reject(new Error(`Diff validation failed: ${stderr.trim()}`));
@@ -383,50 +467,113 @@ class WorktreeManager {
383
467
  stdio: 'pipe',
384
468
  detached: false,
385
469
  });
386
- proc.on('error', (err) => log.warn(`Dev server error (port ${port}):`, err));
387
- // Drain stdout/stderr. With `stdio: 'pipe'` and no consumer, the OS pipe
388
- // buffer (~64KB) fills within seconds of Vite's HMR/request logging and
389
- // the child blocks on write, freezing the dev server even though it
390
- // passed the readiness probe.
391
- proc.stdout?.on('data', (data) => {
392
- log.debug(`[variant-dev:${port}] ${data.toString().trim()}`);
393
- });
394
- proc.stderr?.on('data', (data) => {
470
+ // Capture a rolling tail of the child's output so a failed start is
471
+ // diagnosable (EADDRINUSE, missing dev script, build crash) instead of a
472
+ // blind timeout. Draining the pipes is also required: with `stdio: 'pipe'`
473
+ // and no consumer, the OS pipe buffer (~64KB) fills within seconds of
474
+ // Vite's HMR/request logging and the child blocks on write, freezing the
475
+ // dev server even though it passed the readiness probe.
476
+ let outputTail = '';
477
+ const drain = (data) => {
478
+ outputTail = (outputTail + data.toString()).slice(-DEV_SERVER_OUTPUT_TAIL_LIMIT);
395
479
  log.debug(`[variant-dev:${port}] ${data.toString().trim()}`);
396
- });
397
- const deadline = Date.now() + 30_000;
480
+ };
481
+ proc.stdout?.on('data', drain);
482
+ proc.stderr?.on('data', drain);
483
+ // Track early termination so the probe can fail fast: a dev server that
484
+ // exits (or never spawns) before answering on `port` is never coming up —
485
+ // commonly because the project's dev script ignored the injected port and
486
+ // tried to bind its own default, which was already taken (EADDRINUSE).
487
+ const term = {};
488
+ const onExit = (code, signal) => {
489
+ term.exited = { code, signal };
490
+ };
491
+ const onError = (err) => {
492
+ term.spawnError = err;
493
+ log.warn(`Dev server error (port ${port}):`, err);
494
+ };
495
+ proc.once('exit', onExit);
496
+ proc.once('error', onError);
497
+ const detach = () => {
498
+ proc.off('exit', onExit);
499
+ proc.off('error', onError);
500
+ };
501
+ const fail = (reason) => {
502
+ detach();
503
+ const portInUse = (0, devServerError_1.isPortInUseOutput)(outputTail);
504
+ const detail = outputTail.trim();
505
+ let message;
506
+ if (reason === 'spawn_error') {
507
+ message = `Dev server failed to spawn on port ${port}: ${term.spawnError?.message ?? 'unknown error'}`;
508
+ }
509
+ else if (reason === 'exited') {
510
+ message = `Dev server exited before becoming ready on port ${port} (code=${term.exited?.code ?? 'null'}, signal=${term.exited?.signal ?? 'null'}${portInUse ? ', port already in use' : ''})`;
511
+ }
512
+ else {
513
+ message = `Dev server on port ${port} did not become ready within ${DEV_SERVER_READY_TIMEOUT_MS / 1000}s`;
514
+ }
515
+ throw new devServerError_1.DevServerStartError({
516
+ message: detail ? `${message}\n${detail}` : message,
517
+ reason,
518
+ portInUse,
519
+ detail,
520
+ exitCode: term.exited?.code ?? null,
521
+ signal: term.exited?.signal ?? null,
522
+ });
523
+ };
524
+ const deadline = Date.now() + DEV_SERVER_READY_TIMEOUT_MS;
398
525
  while (Date.now() < deadline) {
526
+ if (term.spawnError)
527
+ fail('spawn_error');
528
+ if (term.exited)
529
+ fail('exited');
399
530
  try {
400
531
  const res = await fetch(`http://localhost:${port}`, {
401
532
  signal: AbortSignal.timeout(1_000),
402
533
  });
403
- if (res.status !== 502)
534
+ if (res.status !== 502) {
535
+ detach();
404
536
  return proc;
537
+ }
405
538
  }
406
539
  catch {
407
540
  // not up yet
408
541
  }
409
542
  await new Promise((r) => setTimeout(r, 500));
410
543
  }
544
+ // Deadline hit. If the child died during the final wait, report that
545
+ // (actionable) rather than a generic timeout.
546
+ if (term.spawnError)
547
+ fail('spawn_error');
548
+ if (term.exited)
549
+ fail('exited');
411
550
  try {
412
551
  proc.kill('SIGTERM');
413
552
  }
414
- catch { /* ignore */ }
415
- throw new Error(`Dev server on port ${port} did not become ready within 30s`);
553
+ catch {
554
+ /* ignore */
555
+ }
556
+ return fail('timeout');
416
557
  }
417
558
  /** Stop a dev server with SIGTERM + SIGKILL fallback */
418
559
  async stopDevServer(proc, timeoutMs = 5_000) {
419
560
  if (proc.killed || proc.exitCode !== null || proc.pid == null)
420
561
  return;
421
562
  const exited = new Promise((resolve) => {
422
- const done = () => { proc.off('exit', done); proc.off('error', done); resolve(); };
563
+ const done = () => {
564
+ proc.off('exit', done);
565
+ proc.off('error', done);
566
+ resolve();
567
+ };
423
568
  proc.once('exit', done);
424
569
  proc.once('error', done);
425
570
  });
426
571
  try {
427
572
  proc.kill('SIGTERM');
428
573
  }
429
- catch { /* ignore */ }
574
+ catch {
575
+ /* ignore */
576
+ }
430
577
  const timedOut = await Promise.race([
431
578
  exited.then(() => false),
432
579
  new Promise((r) => setTimeout(() => r(true), timeoutMs)),
@@ -436,7 +583,9 @@ class WorktreeManager {
436
583
  try {
437
584
  proc.kill('SIGKILL');
438
585
  }
439
- catch { /* ignore */ }
586
+ catch {
587
+ /* ignore */
588
+ }
440
589
  await exited;
441
590
  }
442
591
  /** Remove all worktrees for a session.