rivet-design 0.9.10 → 0.10.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 (128) hide show
  1. package/dist/config/flags.d.ts +3 -0
  2. package/dist/config/flags.d.ts.map +1 -1
  3. package/dist/config/flags.js +1 -0
  4. package/dist/config/flags.js.map +1 -1
  5. package/dist/config/proxy.d.ts +1 -0
  6. package/dist/config/proxy.d.ts.map +1 -1
  7. package/dist/config/proxy.js +9 -1
  8. package/dist/config/proxy.js.map +1 -1
  9. package/dist/index.d.ts +32 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +249 -3
  12. package/dist/index.js.map +1 -1
  13. package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts +5 -0
  14. package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts.map +1 -1
  15. package/dist/mcp/agent-variants/WorktreeOrchestrator.js +7 -0
  16. package/dist/mcp/agent-variants/WorktreeOrchestrator.js.map +1 -1
  17. package/dist/mcp/server.d.ts +19 -0
  18. package/dist/mcp/server.d.ts.map +1 -1
  19. package/dist/mcp/server.js +67 -102
  20. package/dist/mcp/server.js.map +1 -1
  21. package/dist/prototype-host.d.ts +2 -0
  22. package/dist/prototype-host.d.ts.map +1 -0
  23. package/dist/prototype-host.js +56 -0
  24. package/dist/prototype-host.js.map +1 -0
  25. package/dist/proxy-middleware/preview-bridge.d.ts +24 -0
  26. package/dist/proxy-middleware/preview-bridge.d.ts.map +1 -0
  27. package/dist/proxy-middleware/preview-bridge.js +358 -0
  28. package/dist/proxy-middleware/preview-bridge.js.map +1 -0
  29. package/dist/proxy-middleware/proxy-config.d.ts +5 -1
  30. package/dist/proxy-middleware/proxy-config.d.ts.map +1 -1
  31. package/dist/proxy-middleware/proxy-config.js +62 -18
  32. package/dist/proxy-middleware/proxy-config.js.map +1 -1
  33. package/dist/routes/agentVariants.d.ts +2 -1
  34. package/dist/routes/agentVariants.d.ts.map +1 -1
  35. package/dist/routes/agentVariants.js +104 -1
  36. package/dist/routes/agentVariants.js.map +1 -1
  37. package/dist/routes/mcp.d.ts +3 -1
  38. package/dist/routes/mcp.d.ts.map +1 -1
  39. package/dist/routes/mcp.js +33 -3
  40. package/dist/routes/mcp.js.map +1 -1
  41. package/dist/routes/prototypeHost.d.ts +13 -0
  42. package/dist/routes/prototypeHost.d.ts.map +1 -0
  43. package/dist/routes/prototypeHost.js +207 -0
  44. package/dist/routes/prototypeHost.js.map +1 -0
  45. package/dist/routes/static.d.ts +6 -1
  46. package/dist/routes/static.d.ts.map +1 -1
  47. package/dist/routes/static.js +15 -3
  48. package/dist/routes/static.js.map +1 -1
  49. package/dist/server.d.ts +48 -0
  50. package/dist/server.d.ts.map +1 -1
  51. package/dist/server.js +228 -33
  52. package/dist/server.js.map +1 -1
  53. package/dist/services/AgentSessionService.d.ts +87 -0
  54. package/dist/services/AgentSessionService.d.ts.map +1 -0
  55. package/dist/services/AgentSessionService.js +275 -0
  56. package/dist/services/AgentSessionService.js.map +1 -0
  57. package/dist/services/BundleStore.d.ts +36 -0
  58. package/dist/services/BundleStore.d.ts.map +1 -0
  59. package/dist/services/BundleStore.js +102 -0
  60. package/dist/services/BundleStore.js.map +1 -0
  61. package/dist/services/ConfigManager.d.ts +7 -0
  62. package/dist/services/ConfigManager.d.ts.map +1 -1
  63. package/dist/services/ConfigManager.js +13 -0
  64. package/dist/services/ConfigManager.js.map +1 -1
  65. package/dist/services/HostedDemoAuthSessionService.d.ts +6 -0
  66. package/dist/services/HostedDemoAuthSessionService.d.ts.map +1 -1
  67. package/dist/services/HostedDemoAuthSessionService.js +13 -0
  68. package/dist/services/HostedDemoAuthSessionService.js.map +1 -1
  69. package/dist/services/InlineVariantGenerationService.d.ts +50 -0
  70. package/dist/services/InlineVariantGenerationService.d.ts.map +1 -0
  71. package/dist/services/InlineVariantGenerationService.js +394 -0
  72. package/dist/services/InlineVariantGenerationService.js.map +1 -0
  73. package/dist/services/PrototypeBuildService.d.ts +38 -0
  74. package/dist/services/PrototypeBuildService.d.ts.map +1 -0
  75. package/dist/services/PrototypeBuildService.js +165 -0
  76. package/dist/services/PrototypeBuildService.js.map +1 -0
  77. package/dist/services/PrototypeDeployService.d.ts +34 -0
  78. package/dist/services/PrototypeDeployService.d.ts.map +1 -0
  79. package/dist/services/PrototypeDeployService.js +115 -0
  80. package/dist/services/PrototypeDeployService.js.map +1 -0
  81. package/dist/services/SessionBridgeService.d.ts +3 -3
  82. package/dist/services/SessionBridgeService.d.ts.map +1 -1
  83. package/dist/services/SessionBridgeService.js +15 -3
  84. package/dist/services/SessionBridgeService.js.map +1 -1
  85. package/dist/services/SupabaseAuthService.d.ts +25 -0
  86. package/dist/services/SupabaseAuthService.d.ts.map +1 -0
  87. package/dist/services/SupabaseAuthService.js +56 -0
  88. package/dist/services/SupabaseAuthService.js.map +1 -0
  89. package/dist/services/TerminalAgentRunner.d.ts +65 -0
  90. package/dist/services/TerminalAgentRunner.d.ts.map +1 -0
  91. package/dist/services/TerminalAgentRunner.js +511 -0
  92. package/dist/services/TerminalAgentRunner.js.map +1 -0
  93. package/dist/services/VariantHistoryService.d.ts +23 -0
  94. package/dist/services/VariantHistoryService.d.ts.map +1 -1
  95. package/dist/services/VariantHistoryService.js +22 -0
  96. package/dist/services/VariantHistoryService.js.map +1 -1
  97. package/dist/services/WorktreeManager.d.ts +5 -4
  98. package/dist/services/WorktreeManager.d.ts.map +1 -1
  99. package/dist/services/WorktreeManager.js +22 -12
  100. package/dist/services/WorktreeManager.js.map +1 -1
  101. package/dist/services/accessTokenRefresh.d.ts +8 -0
  102. package/dist/services/accessTokenRefresh.d.ts.map +1 -1
  103. package/dist/services/accessTokenRefresh.js +30 -1
  104. package/dist/services/accessTokenRefresh.js.map +1 -1
  105. package/dist/services/createAgentVariantsOrchestrator.d.ts +16 -0
  106. package/dist/services/createAgentVariantsOrchestrator.d.ts.map +1 -0
  107. package/dist/services/createAgentVariantsOrchestrator.js +42 -0
  108. package/dist/services/createAgentVariantsOrchestrator.js.map +1 -0
  109. package/dist/types/change-request-types.d.ts +12 -0
  110. package/dist/types/change-request-types.d.ts.map +1 -1
  111. package/dist/utils/elementFileHintSignals.d.ts +8 -0
  112. package/dist/utils/elementFileHintSignals.d.ts.map +1 -0
  113. package/dist/utils/elementFileHintSignals.js +40 -0
  114. package/dist/utils/elementFileHintSignals.js.map +1 -0
  115. package/dist/utils/formatElementTargetingContext.d.ts +34 -0
  116. package/dist/utils/formatElementTargetingContext.d.ts.map +1 -0
  117. package/dist/utils/formatElementTargetingContext.js +88 -0
  118. package/dist/utils/formatElementTargetingContext.js.map +1 -0
  119. package/dist/utils/queueAccess.d.ts +11 -0
  120. package/dist/utils/queueAccess.d.ts.map +1 -0
  121. package/dist/utils/queueAccess.js +15 -0
  122. package/dist/utils/queueAccess.js.map +1 -0
  123. package/package.json +3 -2
  124. package/src/ui/dist/assets/main-CJ9ZAQrU.css +1 -0
  125. package/src/ui/dist/assets/main-D-FdZGgx.js +640 -0
  126. package/src/ui/dist/index.html +2 -2
  127. package/src/ui/dist/assets/main-BZEruoyc.css +0 -1
  128. package/src/ui/dist/assets/main-ChnGmvJG.js +0 -382
@@ -1,7 +1,12 @@
1
1
  import { Router } from 'express';
2
2
  import { StaticFileService } from '../services/StaticFileService';
3
+ type StaticRoutesOptions = {
4
+ isPreviewBridgeEnabled?: boolean;
5
+ expectedPreviewParentOrigin?: string;
6
+ };
3
7
  /**
4
8
  * Create routes for serving static files
5
9
  */
6
- export declare const createStaticRoutes: (staticService: StaticFileService, _projectPath: string) => Router;
10
+ export declare const createStaticRoutes: (staticService: StaticFileService, _projectPath: string, options?: StaticRoutesOptions) => Router;
11
+ export {};
7
12
  //# sourceMappingURL=static.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/routes/static.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAqB,MAAM,EAAE,MAAM,SAAS,CAAC;AAG7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAKlE;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC7B,eAAe,iBAAiB,EAChC,cAAc,MAAM,KACnB,MAyCF,CAAC"}
1
+ {"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/routes/static.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAqB,MAAM,EAAE,MAAM,SAAS,CAAC;AAG7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAMlE,KAAK,mBAAmB,GAAG;IACzB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACtC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC7B,eAAe,iBAAiB,EAChC,cAAc,MAAM,EACpB,UAAS,mBAAwB,KAChC,MAuDF,CAAC"}
@@ -41,17 +41,29 @@ const express_1 = __importStar(require("express"));
41
41
  const path_1 = __importDefault(require("path"));
42
42
  const fs_1 = __importDefault(require("fs"));
43
43
  const logger_1 = require("../utils/logger");
44
+ const preview_bridge_1 = require("../proxy-middleware/preview-bridge");
44
45
  const log = (0, logger_1.createLogger)('StaticRoutes');
45
46
  /**
46
47
  * Create routes for serving static files
47
48
  */
48
- const createStaticRoutes = (staticService, _projectPath) => {
49
+ const createStaticRoutes = (staticService, _projectPath, options = {}) => {
49
50
  const router = (0, express_1.Router)();
50
51
  // Serve static files from project directory
51
52
  const basePath = staticService.getBasePath();
52
53
  const entryFileName = staticService.getEntryFileName();
53
54
  log.info(`Serving static files from: ${basePath}`);
54
55
  log.info(`Entry file: ${entryFileName}`);
56
+ const sendEntry = (res, entryPath) => {
57
+ if (options.isPreviewBridgeEnabled) {
58
+ res
59
+ .type('html')
60
+ .send((0, preview_bridge_1.injectPreviewBridge)(fs_1.default.readFileSync(entryPath, 'utf8'), {
61
+ expectedParentOrigin: options.expectedPreviewParentOrigin,
62
+ }));
63
+ return;
64
+ }
65
+ res.sendFile(entryFileName, { root: basePath });
66
+ };
55
67
  // Serve the entry point at /static/ (root of static site)
56
68
  router.get('/static', (_req, res) => {
57
69
  const entryPath = path_1.default.join(basePath, entryFileName);
@@ -63,7 +75,7 @@ const createStaticRoutes = (staticService, _projectPath) => {
63
75
  });
64
76
  return;
65
77
  }
66
- res.sendFile(entryFileName, { root: basePath });
78
+ sendEntry(res, entryPath);
67
79
  });
68
80
  router.get('/static/', (_req, res) => {
69
81
  const entryPath = path_1.default.join(basePath, entryFileName);
@@ -75,7 +87,7 @@ const createStaticRoutes = (staticService, _projectPath) => {
75
87
  });
76
88
  return;
77
89
  }
78
- res.sendFile(entryFileName, { root: basePath });
90
+ sendEntry(res, entryPath);
79
91
  });
80
92
  // Serve all other static files
81
93
  router.use('/static', express_1.default.static(basePath));
@@ -1 +1 @@
1
- {"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/routes/static.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mDAA6D;AAC7D,gDAAwB;AACxB,4CAAoB;AAEpB,4CAA+C;AAE/C,MAAM,GAAG,GAAG,IAAA,qBAAY,EAAC,cAAc,CAAC,CAAC;AAEzC;;GAEG;AACI,MAAM,kBAAkB,GAAG,CAChC,aAAgC,EAChC,YAAoB,EACZ,EAAE;IACV,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;IAExB,4CAA4C;IAC5C,MAAM,QAAQ,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC;IAC7C,MAAM,aAAa,GAAG,aAAa,CAAC,gBAAgB,EAAE,CAAC;IAEvD,GAAG,CAAC,IAAI,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAC;IACnD,GAAG,CAAC,IAAI,CAAC,eAAe,aAAa,EAAE,CAAC,CAAC;IAEzC,0DAA0D;IAC1D,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QACrD,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QACrD,GAAG,CAAC,KAAK,CAAC,wBAAwB,SAAS,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE,wBAAwB;gBAC/B,OAAO,EAAE,SAAS;aACnB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,GAAG,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QACtD,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QACrD,GAAG,CAAC,KAAK,CAAC,wBAAwB,SAAS,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE,wBAAwB;gBAC/B,OAAO,EAAE,SAAS;aACnB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,GAAG,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,+BAA+B;IAC/B,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,iBAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEhD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AA5CW,QAAA,kBAAkB,sBA4C7B"}
1
+ {"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/routes/static.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mDAA6D;AAC7D,gDAAwB;AACxB,4CAAoB;AAEpB,4CAA+C;AAC/C,uEAAyE;AAEzE,MAAM,GAAG,GAAG,IAAA,qBAAY,EAAC,cAAc,CAAC,CAAC;AAOzC;;GAEG;AACI,MAAM,kBAAkB,GAAG,CAChC,aAAgC,EAChC,YAAoB,EACpB,UAA+B,EAAE,EACzB,EAAE;IACV,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;IAExB,4CAA4C;IAC5C,MAAM,QAAQ,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC;IAC7C,MAAM,aAAa,GAAG,aAAa,CAAC,gBAAgB,EAAE,CAAC;IAEvD,GAAG,CAAC,IAAI,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAC;IACnD,GAAG,CAAC,IAAI,CAAC,eAAe,aAAa,EAAE,CAAC,CAAC;IAEzC,MAAM,SAAS,GAAG,CAAC,GAAa,EAAE,SAAiB,EAAE,EAAE;QACrD,IAAI,OAAO,CAAC,sBAAsB,EAAE,CAAC;YACnC,GAAG;iBACA,IAAI,CAAC,MAAM,CAAC;iBACZ,IAAI,CACH,IAAA,oCAAmB,EAAC,YAAE,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE;gBACtD,oBAAoB,EAAE,OAAO,CAAC,2BAA2B;aAC1D,CAAC,CACH,CAAC;YACJ,OAAO;QACT,CAAC;QACD,GAAG,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC;IAEF,0DAA0D;IAC1D,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QACrD,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QACrD,GAAG,CAAC,KAAK,CAAC,wBAAwB,SAAS,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE,wBAAwB;gBAC/B,OAAO,EAAE,SAAS;aACnB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QACtD,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QACrD,GAAG,CAAC,KAAK,CAAC,wBAAwB,SAAS,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE,wBAAwB;gBAC/B,OAAO,EAAE,SAAS;aACnB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,+BAA+B;IAC/B,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,iBAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEhD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AA3DW,QAAA,kBAAkB,sBA2D7B"}
package/dist/server.d.ts CHANGED
@@ -3,7 +3,46 @@ import { TelemetryService } from './services/TelemetryService';
3
3
  import { Framework } from './services/ProjectDetectionService';
4
4
  import { SessionBridgeService } from './services/SessionBridgeService';
5
5
  import type { AgentVariantsOrchestrator } from './mcp/agent-variants';
6
+ export declare const INACTIVE_VARIANTS_EVENT_HEARTBEAT_MS = 30000;
7
+ export declare const RIVET_CORS_ALLOWED_HEADERS: string[];
6
8
  export declare const DIST_UI_PATH: string;
9
+ type RivetUiBootstrap = {
10
+ agentApplyMode: 'embedded' | 'external' | null;
11
+ queueAccessToken: string | null;
12
+ };
13
+ export declare const injectRivetUiBootstrap: (html: string, bootstrap: RivetUiBootstrap) => string;
14
+ type InactiveVariantsEventRequest = {
15
+ on: (event: 'close', listener: () => void) => unknown;
16
+ };
17
+ type InactiveVariantsEventResponse = {
18
+ set: (headers: Record<string, string>) => unknown;
19
+ flushHeaders?: () => unknown;
20
+ write: (chunk: string) => unknown;
21
+ };
22
+ /**
23
+ * Keeps the inactive variants SSE endpoint well-formed for clients that always subscribe.
24
+ */
25
+ export declare const sendInactiveVariantsEventStream: (req: InactiveVariantsEventRequest, res: InactiveVariantsEventResponse) => void;
26
+ /**
27
+ * Returns the host interface Rivet should bind for the current runtime.
28
+ */
29
+ export declare const resolveRivetListenHost: (agentApplyMode?: "embedded" | "external" | null) => string | undefined;
30
+ export declare const resolveEmbeddedAgentUiOrigin: (port: number) => string;
31
+ export declare const resolveEmbeddedAgentPreviewOrigin: (port: number) => string;
32
+ export declare const isEmbeddedAgentUiHost: (hostname: string, agentApplyMode?: "embedded" | "external" | null) => boolean;
33
+ export declare const isRivetUiStaticAssetPath: (requestPath: string) => boolean;
34
+ type RivetCorsOriginCheck = {
35
+ requestOrigin?: string;
36
+ requestHostname: string;
37
+ requestPath: string;
38
+ allowedOrigins: ReadonlySet<string>;
39
+ agentApplyMode?: 'embedded' | 'external' | null;
40
+ };
41
+ /**
42
+ * Allows browser requests from the Rivet UI origin and the opaque sandbox
43
+ * origin used by embedded agent previews when loading preview assets.
44
+ */
45
+ export declare const isRivetCorsOriginAllowed: ({ requestOrigin, requestHostname, requestPath, allowedOrigins, agentApplyMode, }: RivetCorsOriginCheck) => boolean;
7
46
  export type ServerOptions = Omit<CLIOptions, 'help' | 'version' | 'debug'> & {
8
47
  framework: Framework;
9
48
  telemetry?: TelemetryService;
@@ -16,6 +55,14 @@ export type ServerOptions = Omit<CLIOptions, 'help' | 'version' | 'debug'> & {
16
55
  agentVariantsOrchestrator?: AgentVariantsOrchestrator;
17
56
  /** The editor running the MCP session (e.g. 'claude', 'cursor', 'codex'). Shown in the UI button. */
18
57
  mcpEditor?: string;
58
+ /** Whether apply progress is handled inside Rivet or by an external editor. */
59
+ agentApplyMode?: 'embedded' | 'external';
60
+ /** Cancels active embedded terminal-agent work when the UI Stop control is used. */
61
+ agentRunController?: {
62
+ cancelActiveRun: () => {
63
+ stoppedCount: number;
64
+ };
65
+ };
19
66
  /** Skip registering process-level exit/signal handlers. Set true when embedded in another process (e.g. MCP server). */
20
67
  skipProcessHandlers?: boolean;
21
68
  /** Explicit port for the Rivet Express server. Defaults to DEFAULT_PORT (4000). */
@@ -46,4 +93,5 @@ export type ServerHandle = {
46
93
  close: () => Promise<void>;
47
94
  };
48
95
  export declare const startServer: (options: ServerOptions) => Promise<ServerHandle>;
96
+ export {};
49
97
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,UAAU,EAAmC,MAAM,GAAG,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAQ/D,OAAO,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AAO/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAKvE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AA+CtE,eAAO,MAAM,YAAY,QAAkB,CAAC;AAkD5C,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,GAAG;IAC3E,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,UAAU,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,oBAAoB,CAAC;IACrC,mGAAmG;IACnG,yBAAyB,CAAC,EAAE,yBAAyB,CAAC;IACtD,qGAAqG;IACrG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wHAAwH;IACxH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gCAAgC;IAChC,QAAQ,CAAC,EAAE;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,wBAAwB,CAAC,EAAE,OAAO,CAAC;QACnC,oBAAoB,CAAC,EAAE,OAAO,CAAC;QAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,uBAAuB,CAAC,EAAE,MAAM,CAAC;QACjC,6BAA6B,CAAC,EAAE,MAAM,CAAC;KACxC,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,WAAW,GACtB,SAAS,aAAa,KACrB,OAAO,CAAC,YAAY,CA44BtB,CAAC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/dist/server.js CHANGED
@@ -36,10 +36,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.startServer = exports.DIST_UI_PATH = void 0;
39
+ exports.startServer = exports.isRivetCorsOriginAllowed = exports.isRivetUiStaticAssetPath = exports.isEmbeddedAgentUiHost = exports.resolveEmbeddedAgentPreviewOrigin = exports.resolveEmbeddedAgentUiOrigin = exports.resolveRivetListenHost = exports.sendInactiveVariantsEventStream = exports.injectRivetUiBootstrap = exports.DIST_UI_PATH = exports.RIVET_CORS_ALLOWED_HEADERS = exports.INACTIVE_VARIANTS_EVENT_HEARTBEAT_MS = void 0;
40
40
  const Sentry = __importStar(require("@sentry/node"));
41
41
  const express_1 = __importDefault(require("express"));
42
42
  const cors_1 = __importDefault(require("cors"));
43
+ const crypto_1 = require("crypto");
43
44
  const path_1 = __importDefault(require("path"));
44
45
  const fs_1 = __importDefault(require("fs"));
45
46
  const index_core_1 = require("./index-core");
@@ -55,6 +56,7 @@ const proxy_config_1 = require("./proxy-middleware/proxy-config");
55
56
  const StaticFileService_1 = require("./services/StaticFileService");
56
57
  const static_1 = require("./routes/static");
57
58
  const ConfigManager_1 = require("./services/ConfigManager");
59
+ const accessTokenRefresh_1 = require("./services/accessTokenRefresh");
58
60
  const evaluateFlags_1 = require("./config/evaluateFlags");
59
61
  const FeatureFlagService_1 = require("./services/FeatureFlagService");
60
62
  const DesktopVersionPolicyService_1 = require("./services/DesktopVersionPolicyService");
@@ -70,7 +72,19 @@ const HostedDemoAuthSessionStore_1 = require("./services/HostedDemoAuthSessionSt
70
72
  const shouldRecordHostedDemoSessionAction_1 = require("./utils/shouldRecordHostedDemoSessionAction");
71
73
  const hostedDemoSessionAuthRefresh_1 = require("./services/hostedDemoSessionAuthRefresh");
72
74
  const RequestAuthContext_1 = require("./services/RequestAuthContext");
75
+ const queueAccess_1 = require("./utils/queueAccess");
73
76
  const log = (0, index_core_1.createLogger)('RivetServer');
77
+ const QUEUE_ACCESS_TOKEN_BYTES = 32;
78
+ const RIVET_BOOTSTRAP_SCRIPT_ID = 'rivet-bootstrap-config';
79
+ const EMBEDDED_AGENT_LISTEN_HOST = '127.0.0.1';
80
+ const EMBEDDED_AGENT_PREVIEW_HOST = 'localhost';
81
+ const OPAQUE_PREVIEW_ORIGIN = 'null';
82
+ exports.INACTIVE_VARIANTS_EVENT_HEARTBEAT_MS = 30_000;
83
+ exports.RIVET_CORS_ALLOWED_HEADERS = [
84
+ 'Content-Type',
85
+ 'Authorization',
86
+ 'x-rivet-queue-token',
87
+ ];
74
88
  /**
75
89
  * Resolve UI dist path for both development and packaged (desktop app) environments
76
90
  */
@@ -96,6 +110,76 @@ const resolveUiPath = () => {
96
110
  return devPath;
97
111
  };
98
112
  exports.DIST_UI_PATH = resolveUiPath();
113
+ const setNoStoreHeaders = (res) => {
114
+ res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate');
115
+ res.setHeader('Pragma', 'no-cache');
116
+ res.setHeader('Expires', '0');
117
+ };
118
+ const escapeScriptJson = (value) => JSON.stringify(value)
119
+ .replace(/</g, '\\u003c')
120
+ .replace(/\u2028/g, '\\u2028')
121
+ .replace(/\u2029/g, '\\u2029');
122
+ const injectRivetUiBootstrap = (html, bootstrap) => {
123
+ const script = `<script id="${RIVET_BOOTSTRAP_SCRIPT_ID}">window.__RIVET_BOOTSTRAP__=${escapeScriptJson(bootstrap)};</script>`;
124
+ if (html.includes('</head>')) {
125
+ return html.replace('</head>', `${script}</head>`);
126
+ }
127
+ return `${script}${html}`;
128
+ };
129
+ exports.injectRivetUiBootstrap = injectRivetUiBootstrap;
130
+ /**
131
+ * Keeps the inactive variants SSE endpoint well-formed for clients that always subscribe.
132
+ */
133
+ const sendInactiveVariantsEventStream = (req, res) => {
134
+ res.set({
135
+ 'Content-Type': 'text/event-stream',
136
+ 'Cache-Control': 'no-cache, no-transform',
137
+ Connection: 'keep-alive',
138
+ 'X-Accel-Buffering': 'no',
139
+ });
140
+ res.flushHeaders?.();
141
+ res.write('data: {"active":false}\n\n');
142
+ const heartbeat = setInterval(() => {
143
+ res.write(': heartbeat\n\n');
144
+ }, exports.INACTIVE_VARIANTS_EVENT_HEARTBEAT_MS);
145
+ req.on('close', () => {
146
+ clearInterval(heartbeat);
147
+ });
148
+ };
149
+ exports.sendInactiveVariantsEventStream = sendInactiveVariantsEventStream;
150
+ /**
151
+ * Returns the host interface Rivet should bind for the current runtime.
152
+ */
153
+ const resolveRivetListenHost = (agentApplyMode) => agentApplyMode === 'embedded' ? EMBEDDED_AGENT_LISTEN_HOST : undefined;
154
+ exports.resolveRivetListenHost = resolveRivetListenHost;
155
+ const resolveEmbeddedAgentUiOrigin = (port) => `http://${EMBEDDED_AGENT_LISTEN_HOST}:${port}`;
156
+ exports.resolveEmbeddedAgentUiOrigin = resolveEmbeddedAgentUiOrigin;
157
+ const resolveEmbeddedAgentPreviewOrigin = (port) => `http://${EMBEDDED_AGENT_PREVIEW_HOST}:${port}`;
158
+ exports.resolveEmbeddedAgentPreviewOrigin = resolveEmbeddedAgentPreviewOrigin;
159
+ const isEmbeddedAgentUiHost = (hostname, agentApplyMode) => agentApplyMode !== 'embedded' || hostname === EMBEDDED_AGENT_LISTEN_HOST;
160
+ exports.isEmbeddedAgentUiHost = isEmbeddedAgentUiHost;
161
+ const isRivetUiStaticAssetPath = (requestPath) => requestPath === '/rivet/favicon.ico' ||
162
+ requestPath.startsWith('/rivet/assets/') ||
163
+ requestPath.startsWith('/rivet/fonts/');
164
+ exports.isRivetUiStaticAssetPath = isRivetUiStaticAssetPath;
165
+ /**
166
+ * Allows browser requests from the Rivet UI origin and the opaque sandbox
167
+ * origin used by embedded agent previews when loading preview assets.
168
+ */
169
+ const isRivetCorsOriginAllowed = ({ requestOrigin, requestHostname, requestPath, allowedOrigins, agentApplyMode, }) => {
170
+ if (!requestOrigin) {
171
+ return true;
172
+ }
173
+ if (allowedOrigins.has(requestOrigin)) {
174
+ return true;
175
+ }
176
+ return (agentApplyMode === 'embedded' &&
177
+ requestHostname === EMBEDDED_AGENT_PREVIEW_HOST &&
178
+ !requestPath.startsWith('/api/') &&
179
+ !requestPath.startsWith('/rivet') &&
180
+ requestOrigin === OPAQUE_PREVIEW_ORIGIN);
181
+ };
182
+ exports.isRivetCorsOriginAllowed = isRivetCorsOriginAllowed;
99
183
  /**
100
184
  * Path to the dev-mode port marker. Written by the Rivet backend after listen()
101
185
  * succeeds and consumed by `src/ui/vite.config.ts` so that `yarn dev` in the UI
@@ -141,12 +225,16 @@ const removeDevPortFile = () => {
141
225
  }
142
226
  };
143
227
  const startServer = async (options) => {
144
- const { userPort, userHost, telemetry, projectPath, framework, staticEntry, styleFramework, tailwindConfig, sessionBridge, mcpEditor, skipProcessHandlers, } = options;
228
+ const { userPort, userHost, telemetry, projectPath, framework, staticEntry, styleFramework, tailwindConfig, sessionBridge, mcpEditor, agentApplyMode, agentRunController, skipProcessHandlers, } = options;
145
229
  const userPortWithFallback = userPort ?? _1.DEFAULT_USER_PORT;
146
230
  const userHostWithFallback = userHost ?? 'localhost';
147
231
  const isDemoModeEnabled = options.demoMode?.enabled ?? false;
148
232
  const requiresDemoAuth = options.demoMode?.requireSignedInUsers ?? true;
149
233
  const isGitEnabled = options.isGitEnabled ?? !isDemoModeEnabled;
234
+ const queueAccessToken = sessionBridge && agentApplyMode === 'embedded'
235
+ ? (0, crypto_1.randomBytes)(QUEUE_ACCESS_TOKEN_BYTES).toString('base64url')
236
+ : null;
237
+ const rivetUiIndexHtml = fs_1.default.readFileSync(path_1.default.join(exports.DIST_UI_PATH, 'index.html'), 'utf8');
150
238
  if (process.env.SENTRY_DSN) {
151
239
  Sentry.init({
152
240
  dsn: process.env.SENTRY_DSN,
@@ -200,10 +288,9 @@ const startServer = async (options) => {
200
288
  }
201
289
  const listenPort = options.rivetPort ?? _1.DEFAULT_PORT;
202
290
  const app = (0, express_1.default)();
203
- const corsOrigins = new Set([
204
- `http://localhost:${listenPort}`,
205
- `http://127.0.0.1:${listenPort}`,
206
- ]);
291
+ const corsOrigins = new Set(agentApplyMode === 'embedded'
292
+ ? [(0, exports.resolveEmbeddedAgentUiOrigin)(listenPort)]
293
+ : [`http://localhost:${listenPort}`, `http://127.0.0.1:${listenPort}`]);
207
294
  const rawCorsOrigins = process.env.RIVET_CORS_ORIGINS;
208
295
  if (rawCorsOrigins) {
209
296
  rawCorsOrigins
@@ -217,12 +304,22 @@ const startServer = async (options) => {
217
304
  corsOrigins.add('https://demo.rivet.design');
218
305
  }
219
306
  // CORS configuration for local development
220
- app.use((0, cors_1.default)({
221
- origin: [...corsOrigins],
222
- credentials: true,
223
- methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
224
- allowedHeaders: ['Content-Type', 'Authorization'],
225
- }));
307
+ app.use((req, res, next) => {
308
+ (0, cors_1.default)({
309
+ origin: (origin, callback) => {
310
+ callback(null, (0, exports.isRivetCorsOriginAllowed)({
311
+ requestOrigin: origin,
312
+ requestHostname: req.hostname,
313
+ requestPath: req.path,
314
+ allowedOrigins: corsOrigins,
315
+ agentApplyMode,
316
+ }));
317
+ },
318
+ credentials: true,
319
+ methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
320
+ allowedHeaders: exports.RIVET_CORS_ALLOWED_HEADERS,
321
+ })(req, res, next);
322
+ });
226
323
  const jsonBodyParser = express_1.default.json({ limit: '50mb' });
227
324
  app.use((req, res, next) => {
228
325
  if (req.originalUrl.startsWith('/try/')) {
@@ -245,16 +342,12 @@ const startServer = async (options) => {
245
342
  // until the cache TTL expires). Hashed assets under /assets/* are
246
343
  // content-addressed and safe to long-cache.
247
344
  if (filePath.endsWith('.html')) {
248
- res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate');
249
- res.setHeader('Pragma', 'no-cache');
250
- res.setHeader('Expires', '0');
345
+ setNoStoreHeaders(res);
251
346
  }
252
347
  else if (process.env.NODE_ENV !== 'production') {
253
348
  // Dev: defeat caching for everything so HMR-like behavior is reliable
254
349
  // without rebuilds bumping a hash.
255
- res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate');
256
- res.setHeader('Pragma', 'no-cache');
257
- res.setHeader('Expires', '0');
350
+ setNoStoreHeaders(res);
258
351
  }
259
352
  else {
260
353
  // Production hashed assets are content-addressed (`main-<hash>.js`),
@@ -264,24 +357,48 @@ const startServer = async (options) => {
264
357
  }
265
358
  },
266
359
  };
360
+ const sendRivetUiIndex = (req, res) => {
361
+ if (!(0, exports.isEmbeddedAgentUiHost)(req.hostname, agentApplyMode)) {
362
+ res.redirect(302, `${(0, exports.resolveEmbeddedAgentUiOrigin)(listenPort)}${req.originalUrl}`);
363
+ return;
364
+ }
365
+ setNoStoreHeaders(res);
366
+ res
367
+ .type('html')
368
+ .send((0, exports.injectRivetUiBootstrap)(rivetUiIndexHtml, {
369
+ agentApplyMode: agentApplyMode ?? null,
370
+ queueAccessToken,
371
+ }));
372
+ };
267
373
  // Serve hashed UI assets from root so both / and /rivet entrypoints can load them.
268
374
  app.use('/assets', express_1.default.static(path_1.default.join(exports.DIST_UI_PATH, 'assets'), uiStaticOptions));
375
+ app.use('/rivet/assets', express_1.default.static(path_1.default.join(exports.DIST_UI_PATH, 'assets'), uiStaticOptions));
269
376
  // Serve public font files used by auth and hosted demo UI.
270
377
  app.use('/fonts', express_1.default.static(path_1.default.join(exports.DIST_UI_PATH, 'fonts'), uiStaticOptions));
378
+ app.use('/rivet/fonts', express_1.default.static(path_1.default.join(exports.DIST_UI_PATH, 'fonts'), uiStaticOptions));
271
379
  // Serve favicon at root for hosted/static deployments.
272
380
  app.get('/favicon.ico', (_req, res) => {
273
381
  res.sendFile('favicon.ico', { root: exports.DIST_UI_PATH });
274
382
  });
383
+ app.get('/rivet/favicon.ico', (_req, res) => {
384
+ res.sendFile('favicon.ico', { root: exports.DIST_UI_PATH });
385
+ });
275
386
  // Serve Rivet UI at /rivet for non-static modes.
276
387
  if (framework !== 'static') {
277
- app.use('/rivet', express_1.default.static(exports.DIST_UI_PATH, uiStaticOptions));
388
+ app.get(/^\/rivet(?:\/.*)?$/, (req, res, next) => {
389
+ if ((0, exports.isRivetUiStaticAssetPath)(req.path)) {
390
+ next();
391
+ return;
392
+ }
393
+ sendRivetUiIndex(req, res);
394
+ });
278
395
  }
279
396
  log.info(`Serving UI assets from: ${exports.DIST_UI_PATH}`);
280
397
  // Static mode - use root entrypoint for Rivet UI (no dev server to proxy to)
281
398
  if (framework === 'static') {
282
399
  app.get('/', (req, res) => {
283
400
  log.debug(`${framework} mode - serving Rivet at root`);
284
- res.sendFile('index.html', { root: exports.DIST_UI_PATH });
401
+ sendRivetUiIndex(req, res);
285
402
  });
286
403
  }
287
404
  // For web frameworks, root route falls through to catch-all proxy (no special handling needed)
@@ -372,7 +489,9 @@ const startServer = async (options) => {
372
489
  return email.trim().toLowerCase();
373
490
  };
374
491
  const isDemoAuthExemptApiPath = (pathName) => {
375
- if (pathName === '/config' || pathName === '/health' || pathName === '/auth/store') {
492
+ if (pathName === '/config' ||
493
+ pathName === '/health' ||
494
+ pathName === '/auth/store') {
376
495
  return true;
377
496
  }
378
497
  if (pathName === '/demo/session' || pathName.startsWith('/demo/session/')) {
@@ -393,7 +512,8 @@ const startServer = async (options) => {
393
512
  return false;
394
513
  };
395
514
  let demoSessionService = null;
396
- if (isDemoModeEnabled && options.demoMode?.allowSessionProvisioning !== false) {
515
+ if (isDemoModeEnabled &&
516
+ options.demoMode?.allowSessionProvisioning !== false) {
397
517
  const sessionMetadataRedisUrl = options.demoMode?.sessionMetadataRedisUrl ??
398
518
  options.demoMode?.authRedisUrl;
399
519
  const sessionMetadataStore = sessionMetadataRedisUrl
@@ -444,7 +564,8 @@ const startServer = async (options) => {
444
564
  if (!activeDemoSessionId) {
445
565
  return undefined;
446
566
  }
447
- return demoSessionService.getSessionProxyTarget(activeDemoSessionId) ?? undefined;
567
+ return (demoSessionService.getSessionProxyTarget(activeDemoSessionId) ??
568
+ undefined);
448
569
  },
449
570
  });
450
571
  app.use('/api', (req, res, next) => {
@@ -638,7 +759,12 @@ const startServer = async (options) => {
638
759
  app.use('/api', (0, support_1.createSupportRouter)(telemetry));
639
760
  // Static routes (only for static projects)
640
761
  if (staticService) {
641
- app.use((0, static_1.createStaticRoutes)(staticService, projectPath));
762
+ app.use((0, static_1.createStaticRoutes)(staticService, projectPath, {
763
+ isPreviewBridgeEnabled: agentApplyMode === 'embedded',
764
+ expectedPreviewParentOrigin: agentApplyMode === 'embedded'
765
+ ? (0, exports.resolveEmbeddedAgentUiOrigin)(listenPort)
766
+ : undefined,
767
+ }));
642
768
  log.info('Static routes mounted at /static');
643
769
  }
644
770
  // Health check endpoint
@@ -653,6 +779,22 @@ const startServer = async (options) => {
653
779
  },
654
780
  });
655
781
  });
782
+ app.post('/api/agent/stop', (req, res) => {
783
+ if (agentApplyMode !== 'embedded' || !agentRunController) {
784
+ return res.status(404).json({ error: 'No embedded agent run active' });
785
+ }
786
+ if (!(0, queueAccess_1.isQueueAccessAuthorized)({
787
+ queueAccessToken,
788
+ getHeader: (name) => req.header(name),
789
+ })) {
790
+ return res.status(403).json({
791
+ error: 'Queue access denied',
792
+ reason: 'queue_token_required',
793
+ });
794
+ }
795
+ const result = agentRunController.cancelActiveRun();
796
+ return res.json({ success: true, ...result });
797
+ });
656
798
  // Config endpoint
657
799
  app.get('/api/config', async (req, res) => {
658
800
  const configManager = (0, ConfigManager_1.getConfigManager)();
@@ -662,10 +804,21 @@ const startServer = async (options) => {
662
804
  const isAuthenticated = demoAuthSessionService
663
805
  ? isAuthenticatedInDemoMode
664
806
  : configManager.isAuthenticated();
665
- const email = demoAuthSessionService ? demoAuth?.email : configManager.getEmail();
807
+ const email = demoAuthSessionService
808
+ ? demoAuth?.email
809
+ : configManager.getEmail();
666
810
  const userId = demoAuthSessionService
667
811
  ? demoAuth?.userId
668
812
  : configManager.getUserId();
813
+ // Display name lives in the access token's user_metadata (Google OAuth).
814
+ // Decode the demo session's token directly; otherwise let ConfigManager
815
+ // read it off the locally stored token. May be undefined (email-only
816
+ // logins) — the UI falls back to email-derived initials.
817
+ const name = demoAuthSessionService
818
+ ? demoAuth?.token
819
+ ? ((0, accessTokenRefresh_1.getJwtDisplayName)(demoAuth.token) ?? undefined)
820
+ : undefined
821
+ : configManager.getDisplayName();
669
822
  const featureFlagUserKey = (0, featureFlagUserKey_1.getConfigFeatureFlagUserKey)({
670
823
  headers: req.headers,
671
824
  fallbackEmail: email,
@@ -691,9 +844,13 @@ const startServer = async (options) => {
691
844
  agentModeAvailable: isAuthenticated,
692
845
  email,
693
846
  userId,
847
+ name,
694
848
  activeDemoSessionId,
695
849
  isMCPSession: sessionBridge?.isActive() ?? false,
696
850
  mcpEditor: mcpEditor ?? null,
851
+ agentApplyMode: sessionBridge?.isActive()
852
+ ? (agentApplyMode ?? 'external')
853
+ : null,
697
854
  featureFlags,
698
855
  projectPath: livePath,
699
856
  demoMode: isDemoModeEnabled,
@@ -749,15 +906,33 @@ const startServer = async (options) => {
749
906
  deploymentEnv: process.env.NODE_ENV ?? 'development',
750
907
  });
751
908
  }
752
- return res.status(500).json({ error: 'Failed to store auth credentials' });
909
+ return res
910
+ .status(500)
911
+ .json({ error: 'Failed to store auth credentials' });
753
912
  }
754
913
  telemetry?.identifyUser();
755
914
  log.info(`Stored auth for ${email} via browser OAuth`);
756
915
  res.json({ success: true });
757
916
  });
917
+ app.post('/api/auth/logout', (req, res) => {
918
+ try {
919
+ if (demoAuthSessionService) {
920
+ demoAuthSessionService.clearAuthForRequest(req, res);
921
+ }
922
+ else {
923
+ (0, ConfigManager_1.getConfigManager)().clearAuth();
924
+ }
925
+ }
926
+ catch (error) {
927
+ log.warn('Logout failed', error);
928
+ return res.status(500).json({ error: 'Failed to log out' });
929
+ }
930
+ log.info('Cleared auth via logout');
931
+ res.json({ success: true });
932
+ });
758
933
  // MCP bridge routes (only when session bridge is provided)
759
934
  if (sessionBridge) {
760
- app.use('/api/mcp', (0, mcp_1.createMCPRouter)(sessionBridge, options.telemetry, options.agentVariantsOrchestrator));
935
+ app.use('/api/mcp', (0, mcp_1.createMCPRouter)(sessionBridge, options.telemetry, options.agentVariantsOrchestrator, { queueAccessToken: queueAccessToken ?? undefined }));
761
936
  log.info('MCP bridge routes mounted at /api/mcp');
762
937
  }
763
938
  // Agent-driven variants — Express routes back the iframe chip (cycle pills,
@@ -766,12 +941,25 @@ const startServer = async (options) => {
766
941
  app.use('/api', (0, agentVariants_1.createAgentVariantsRouter)(options.agentVariantsOrchestrator, sessionBridge, telemetry));
767
942
  log.info('agent-variants routes mounted at /api/variants');
768
943
  }
944
+ else {
945
+ app.get('/api/variants/active', (_req, res) => {
946
+ res.json({ active: false });
947
+ });
948
+ app.get('/api/variants/events', (req, res) => {
949
+ (0, exports.sendInactiveVariantsEventStream)(req, res);
950
+ });
951
+ }
769
952
  // Proxy all other routes to user's dev server (catch-all)
770
953
  // This must come AFTER all Rivet-specific routes
771
954
  // Skip proxy setup for static apps
772
955
  let userDevProxy = null;
773
956
  if (framework !== 'static') {
774
- userDevProxy = (0, proxy_config_1.createUserDevServerProxy)(userPortWithFallback, userHostWithFallback);
957
+ userDevProxy = (0, proxy_config_1.createUserDevServerProxy)(userPortWithFallback, userHostWithFallback, {
958
+ isPreviewBridgeEnabled: agentApplyMode === 'embedded',
959
+ expectedPreviewParentOrigin: agentApplyMode === 'embedded'
960
+ ? (0, exports.resolveEmbeddedAgentUiOrigin)(listenPort)
961
+ : undefined,
962
+ });
775
963
  // Inject the variant-target setter into the bridge so MCP-driven variant
776
964
  // sessions can swap upstreams without re-creating the proxy.
777
965
  sessionBridge?.registerVariantTargetSetter(userDevProxy.setVariantTarget);
@@ -812,11 +1000,18 @@ const startServer = async (options) => {
812
1000
  // Start server
813
1001
  const activeSockets = new Set();
814
1002
  const httpServer = await new Promise((resolve, reject) => {
815
- const server = app.listen(listenPort, () => {
816
- log.info(`🎨 Rivet server running on http://localhost:${listenPort}`);
817
- writeDevPortFile(listenPort);
818
- resolve(server);
819
- });
1003
+ const listenHost = (0, exports.resolveRivetListenHost)(agentApplyMode);
1004
+ const server = listenHost
1005
+ ? app.listen(listenPort, listenHost, () => {
1006
+ log.info(`🎨 Rivet server running on http://${listenHost}:${listenPort}`);
1007
+ writeDevPortFile(listenPort);
1008
+ resolve(server);
1009
+ })
1010
+ : app.listen(listenPort, () => {
1011
+ log.info(`🎨 Rivet server running on http://localhost:${listenPort}`);
1012
+ writeDevPortFile(listenPort);
1013
+ resolve(server);
1014
+ });
820
1015
  server.on('error', (err) => {
821
1016
  reject(err);
822
1017
  });