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.
- package/dist/config/flags.d.ts +3 -0
- package/dist/config/flags.d.ts.map +1 -1
- package/dist/config/flags.js +1 -0
- package/dist/config/flags.js.map +1 -1
- package/dist/config/proxy.d.ts +1 -0
- package/dist/config/proxy.d.ts.map +1 -1
- package/dist/config/proxy.js +9 -1
- package/dist/config/proxy.js.map +1 -1
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +249 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts +5 -0
- package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.js +7 -0
- package/dist/mcp/agent-variants/WorktreeOrchestrator.js.map +1 -1
- package/dist/mcp/server.d.ts +19 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +67 -102
- package/dist/mcp/server.js.map +1 -1
- package/dist/prototype-host.d.ts +2 -0
- package/dist/prototype-host.d.ts.map +1 -0
- package/dist/prototype-host.js +56 -0
- package/dist/prototype-host.js.map +1 -0
- package/dist/proxy-middleware/preview-bridge.d.ts +24 -0
- package/dist/proxy-middleware/preview-bridge.d.ts.map +1 -0
- package/dist/proxy-middleware/preview-bridge.js +358 -0
- package/dist/proxy-middleware/preview-bridge.js.map +1 -0
- package/dist/proxy-middleware/proxy-config.d.ts +5 -1
- package/dist/proxy-middleware/proxy-config.d.ts.map +1 -1
- package/dist/proxy-middleware/proxy-config.js +62 -18
- package/dist/proxy-middleware/proxy-config.js.map +1 -1
- package/dist/routes/agentVariants.d.ts +2 -1
- package/dist/routes/agentVariants.d.ts.map +1 -1
- package/dist/routes/agentVariants.js +104 -1
- package/dist/routes/agentVariants.js.map +1 -1
- package/dist/routes/mcp.d.ts +3 -1
- package/dist/routes/mcp.d.ts.map +1 -1
- package/dist/routes/mcp.js +33 -3
- package/dist/routes/mcp.js.map +1 -1
- package/dist/routes/prototypeHost.d.ts +13 -0
- package/dist/routes/prototypeHost.d.ts.map +1 -0
- package/dist/routes/prototypeHost.js +207 -0
- package/dist/routes/prototypeHost.js.map +1 -0
- package/dist/routes/static.d.ts +6 -1
- package/dist/routes/static.d.ts.map +1 -1
- package/dist/routes/static.js +15 -3
- package/dist/routes/static.js.map +1 -1
- package/dist/server.d.ts +48 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +228 -33
- package/dist/server.js.map +1 -1
- package/dist/services/AgentSessionService.d.ts +87 -0
- package/dist/services/AgentSessionService.d.ts.map +1 -0
- package/dist/services/AgentSessionService.js +275 -0
- package/dist/services/AgentSessionService.js.map +1 -0
- package/dist/services/BundleStore.d.ts +36 -0
- package/dist/services/BundleStore.d.ts.map +1 -0
- package/dist/services/BundleStore.js +102 -0
- package/dist/services/BundleStore.js.map +1 -0
- package/dist/services/ConfigManager.d.ts +7 -0
- package/dist/services/ConfigManager.d.ts.map +1 -1
- package/dist/services/ConfigManager.js +13 -0
- package/dist/services/ConfigManager.js.map +1 -1
- package/dist/services/HostedDemoAuthSessionService.d.ts +6 -0
- package/dist/services/HostedDemoAuthSessionService.d.ts.map +1 -1
- package/dist/services/HostedDemoAuthSessionService.js +13 -0
- package/dist/services/HostedDemoAuthSessionService.js.map +1 -1
- package/dist/services/InlineVariantGenerationService.d.ts +50 -0
- package/dist/services/InlineVariantGenerationService.d.ts.map +1 -0
- package/dist/services/InlineVariantGenerationService.js +394 -0
- package/dist/services/InlineVariantGenerationService.js.map +1 -0
- package/dist/services/PrototypeBuildService.d.ts +38 -0
- package/dist/services/PrototypeBuildService.d.ts.map +1 -0
- package/dist/services/PrototypeBuildService.js +165 -0
- package/dist/services/PrototypeBuildService.js.map +1 -0
- package/dist/services/PrototypeDeployService.d.ts +34 -0
- package/dist/services/PrototypeDeployService.d.ts.map +1 -0
- package/dist/services/PrototypeDeployService.js +115 -0
- package/dist/services/PrototypeDeployService.js.map +1 -0
- package/dist/services/SessionBridgeService.d.ts +3 -3
- package/dist/services/SessionBridgeService.d.ts.map +1 -1
- package/dist/services/SessionBridgeService.js +15 -3
- package/dist/services/SessionBridgeService.js.map +1 -1
- package/dist/services/SupabaseAuthService.d.ts +25 -0
- package/dist/services/SupabaseAuthService.d.ts.map +1 -0
- package/dist/services/SupabaseAuthService.js +56 -0
- package/dist/services/SupabaseAuthService.js.map +1 -0
- package/dist/services/TerminalAgentRunner.d.ts +65 -0
- package/dist/services/TerminalAgentRunner.d.ts.map +1 -0
- package/dist/services/TerminalAgentRunner.js +511 -0
- package/dist/services/TerminalAgentRunner.js.map +1 -0
- package/dist/services/VariantHistoryService.d.ts +23 -0
- package/dist/services/VariantHistoryService.d.ts.map +1 -1
- package/dist/services/VariantHistoryService.js +22 -0
- package/dist/services/VariantHistoryService.js.map +1 -1
- package/dist/services/WorktreeManager.d.ts +5 -4
- package/dist/services/WorktreeManager.d.ts.map +1 -1
- package/dist/services/WorktreeManager.js +22 -12
- package/dist/services/WorktreeManager.js.map +1 -1
- package/dist/services/accessTokenRefresh.d.ts +8 -0
- package/dist/services/accessTokenRefresh.d.ts.map +1 -1
- package/dist/services/accessTokenRefresh.js +30 -1
- package/dist/services/accessTokenRefresh.js.map +1 -1
- package/dist/services/createAgentVariantsOrchestrator.d.ts +16 -0
- package/dist/services/createAgentVariantsOrchestrator.d.ts.map +1 -0
- package/dist/services/createAgentVariantsOrchestrator.js +42 -0
- package/dist/services/createAgentVariantsOrchestrator.js.map +1 -0
- package/dist/types/change-request-types.d.ts +12 -0
- package/dist/types/change-request-types.d.ts.map +1 -1
- package/dist/utils/elementFileHintSignals.d.ts +8 -0
- package/dist/utils/elementFileHintSignals.d.ts.map +1 -0
- package/dist/utils/elementFileHintSignals.js +40 -0
- package/dist/utils/elementFileHintSignals.js.map +1 -0
- package/dist/utils/formatElementTargetingContext.d.ts +34 -0
- package/dist/utils/formatElementTargetingContext.d.ts.map +1 -0
- package/dist/utils/formatElementTargetingContext.js +88 -0
- package/dist/utils/formatElementTargetingContext.js.map +1 -0
- package/dist/utils/queueAccess.d.ts +11 -0
- package/dist/utils/queueAccess.d.ts.map +1 -0
- package/dist/utils/queueAccess.js +15 -0
- package/dist/utils/queueAccess.js.map +1 -0
- package/package.json +3 -2
- package/src/ui/dist/assets/main-CJ9ZAQrU.css +1 -0
- package/src/ui/dist/assets/main-D-FdZGgx.js +640 -0
- package/src/ui/dist/index.html +2 -2
- package/src/ui/dist/assets/main-BZEruoyc.css +0 -1
- package/src/ui/dist/assets/main-ChnGmvJG.js +0 -382
package/dist/routes/static.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/routes/static.js
CHANGED
|
@@ -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
|
|
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
|
|
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;
|
|
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
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"
|
|
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
|
-
|
|
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((
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
|
|
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' ||
|
|
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 &&
|
|
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) ??
|
|
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
|
|
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
|
|
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
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
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
|
});
|