rivet-design 0.10.0 → 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/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/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/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/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/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/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/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/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 +1 -1
- 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-CIJUZXe8.js +0 -382
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isHtmlDocumentRequest = exports.injectPreviewBridge = exports.shouldInjectPreviewBridge = exports.allowPreviewBridgeNonceInCsp = exports.createPreviewBridgeScript = exports.PREVIEW_BRIDGE_CHANNEL = exports.PREVIEW_BRIDGE_SCRIPT_ID = void 0;
|
|
4
|
+
exports.PREVIEW_BRIDGE_SCRIPT_ID = 'rivet-preview-bridge';
|
|
5
|
+
exports.PREVIEW_BRIDGE_CHANNEL = 'rivet-preview-bridge';
|
|
6
|
+
const MAX_SIBLING_CONTEXT_COUNT = 6;
|
|
7
|
+
const TEXT_SNIPPET_MAX_LENGTH = 80;
|
|
8
|
+
const buildBridgeScript = ({ expectedParentOrigin, } = {}) => `
|
|
9
|
+
(() => {
|
|
10
|
+
const CHANNEL = '${exports.PREVIEW_BRIDGE_CHANNEL}';
|
|
11
|
+
const EXPECTED_PARENT_ORIGIN = ${JSON.stringify(expectedParentOrigin ?? null)} || window.location.origin;
|
|
12
|
+
const RIVET_ID_ATTR = 'data-rivet-id';
|
|
13
|
+
const MAX_SIBLING_CONTEXT_COUNT = ${MAX_SIBLING_CONTEXT_COUNT};
|
|
14
|
+
const TEXT_SNIPPET_MAX_LENGTH = ${TEXT_SNIPPET_MAX_LENGTH};
|
|
15
|
+
if (window.__RIVET_PREVIEW_BRIDGE_ACTIVE__) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
window.__RIVET_PREVIEW_BRIDGE_ACTIVE__ = true;
|
|
19
|
+
|
|
20
|
+
const getClassName = (element) => {
|
|
21
|
+
try {
|
|
22
|
+
const value = element.className;
|
|
23
|
+
if (typeof value === 'string') {
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
if (value && typeof value === 'object' && 'baseVal' in value) {
|
|
27
|
+
return value.baseVal || '';
|
|
28
|
+
}
|
|
29
|
+
} catch {}
|
|
30
|
+
return '';
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const getTextSnippet = (element) => {
|
|
34
|
+
const text = (element.textContent || '').replace(/\\s+/g, ' ').trim();
|
|
35
|
+
return text.slice(0, TEXT_SNIPPET_MAX_LENGTH);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const getXPath = (element) => {
|
|
39
|
+
if (element.id) {
|
|
40
|
+
return '//*[@id="' + element.id + '"]';
|
|
41
|
+
}
|
|
42
|
+
if (element === document.body) {
|
|
43
|
+
return '/html/body';
|
|
44
|
+
}
|
|
45
|
+
let index = 0;
|
|
46
|
+
const siblings = element.parentNode ? element.parentNode.childNodes : [];
|
|
47
|
+
for (let i = 0; i < siblings.length; i += 1) {
|
|
48
|
+
const sibling = siblings[i];
|
|
49
|
+
if (sibling === element) {
|
|
50
|
+
const parent = element.parentNode;
|
|
51
|
+
return parent
|
|
52
|
+
? getXPath(parent) + '/' + element.tagName.toLowerCase() + '[' + (index + 1) + ']'
|
|
53
|
+
: '';
|
|
54
|
+
}
|
|
55
|
+
if (sibling.nodeType === 1 && sibling.tagName === element.tagName) {
|
|
56
|
+
index += 1;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return '';
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const getElementByXPath = (xpath) => {
|
|
63
|
+
try {
|
|
64
|
+
const result = document.evaluate(
|
|
65
|
+
xpath,
|
|
66
|
+
document,
|
|
67
|
+
null,
|
|
68
|
+
XPathResult.FIRST_ORDERED_NODE_TYPE,
|
|
69
|
+
null,
|
|
70
|
+
);
|
|
71
|
+
return result.singleNodeValue || null;
|
|
72
|
+
} catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const ensureRivetId = (element) => {
|
|
78
|
+
const existing = element.getAttribute(RIVET_ID_ATTR);
|
|
79
|
+
if (existing && existing.trim()) {
|
|
80
|
+
return existing.trim();
|
|
81
|
+
}
|
|
82
|
+
const id =
|
|
83
|
+
globalThis.crypto && typeof globalThis.crypto.randomUUID === 'function'
|
|
84
|
+
? globalThis.crypto.randomUUID()
|
|
85
|
+
: 'rivet-' + Math.random().toString(36).slice(2, 11);
|
|
86
|
+
element.setAttribute(RIVET_ID_ATTR, id);
|
|
87
|
+
return id;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const transformStyles = (styles) => {
|
|
91
|
+
const result = {};
|
|
92
|
+
for (let i = 0; i < styles.length; i += 1) {
|
|
93
|
+
const prop = styles[i];
|
|
94
|
+
result[prop] = styles.getPropertyValue(prop);
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const getSiblingElements = (element) => {
|
|
100
|
+
const parent = element.parentElement;
|
|
101
|
+
if (!parent) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
const siblings = Array.from(parent.children);
|
|
105
|
+
const currentIndex = siblings.indexOf(element);
|
|
106
|
+
if (currentIndex === -1) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
const result = siblings
|
|
110
|
+
.map((sibling, index) => ({ sibling, index }))
|
|
111
|
+
.filter(({ sibling }) => sibling !== element)
|
|
112
|
+
.sort((a, b) => Math.abs(a.index - currentIndex) - Math.abs(b.index - currentIndex))
|
|
113
|
+
.slice(0, MAX_SIBLING_CONTEXT_COUNT)
|
|
114
|
+
.map(({ sibling, index }) => ({
|
|
115
|
+
tagName: sibling.tagName.toLowerCase(),
|
|
116
|
+
className: getClassName(sibling),
|
|
117
|
+
id: sibling.id || '',
|
|
118
|
+
textSnippet: getTextSnippet(sibling),
|
|
119
|
+
relativePosition: index < currentIndex ? 'previous' : 'next',
|
|
120
|
+
}));
|
|
121
|
+
return result.length > 0 ? result : undefined;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const getParentSummary = (element) => {
|
|
125
|
+
const parent = element.parentElement;
|
|
126
|
+
if (!parent) {
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
tagName: parent.tagName.toLowerCase(),
|
|
131
|
+
className: getClassName(parent),
|
|
132
|
+
id: parent.id || '',
|
|
133
|
+
textSnippet: getTextSnippet(parent),
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const extractElement = (element) => {
|
|
138
|
+
if (!element) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
const rect = element.getBoundingClientRect();
|
|
142
|
+
const computedStyles = window.getComputedStyle(element);
|
|
143
|
+
const attributes = {};
|
|
144
|
+
for (const attr of Array.from(element.attributes || [])) {
|
|
145
|
+
attributes[attr.name] = attr.value;
|
|
146
|
+
}
|
|
147
|
+
const rivetId = ensureRivetId(element);
|
|
148
|
+
return {
|
|
149
|
+
tagName: element.tagName.toLowerCase(),
|
|
150
|
+
className: getClassName(element),
|
|
151
|
+
id: element.id || '',
|
|
152
|
+
textContent: (element.textContent || '').trim().slice(0, 100),
|
|
153
|
+
innerHTML: (element.innerHTML || '').slice(0, 200),
|
|
154
|
+
attributes,
|
|
155
|
+
computedStyles: transformStyles(computedStyles),
|
|
156
|
+
boundingRect: {
|
|
157
|
+
x: rect.x,
|
|
158
|
+
y: rect.y,
|
|
159
|
+
width: rect.width,
|
|
160
|
+
height: rect.height,
|
|
161
|
+
top: rect.top,
|
|
162
|
+
left: rect.left,
|
|
163
|
+
right: rect.right,
|
|
164
|
+
bottom: rect.bottom,
|
|
165
|
+
},
|
|
166
|
+
xpath: getXPath(element),
|
|
167
|
+
rivetId,
|
|
168
|
+
siblingElements: getSiblingElements(element),
|
|
169
|
+
parentElementSummary: getParentSummary(element),
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const elementFromIdentifier = (identifier) => {
|
|
174
|
+
if (!identifier || typeof identifier !== 'object') {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
const rivetId = typeof identifier.rivetId === 'string' ? identifier.rivetId.trim() : '';
|
|
178
|
+
if (rivetId) {
|
|
179
|
+
try {
|
|
180
|
+
const element = document.querySelector('[' + RIVET_ID_ATTR + '="' + CSS.escape(rivetId) + '"]');
|
|
181
|
+
if (element) {
|
|
182
|
+
return element;
|
|
183
|
+
}
|
|
184
|
+
} catch {}
|
|
185
|
+
}
|
|
186
|
+
const xpath = typeof identifier.xpath === 'string' ? identifier.xpath : '';
|
|
187
|
+
return xpath ? getElementByXPath(xpath) : null;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const elementsInBox = (box) => {
|
|
191
|
+
const candidates = new Set();
|
|
192
|
+
const step = 32;
|
|
193
|
+
const xCount = Math.max(2, Math.min(24, Math.ceil((box.right - box.left) / step) + 1));
|
|
194
|
+
const yCount = Math.max(2, Math.min(24, Math.ceil((box.bottom - box.top) / step) + 1));
|
|
195
|
+
for (let xi = 0; xi < xCount; xi += 1) {
|
|
196
|
+
const x = box.left + ((box.right - box.left) * xi) / (xCount - 1);
|
|
197
|
+
for (let yi = 0; yi < yCount; yi += 1) {
|
|
198
|
+
const y = box.top + ((box.bottom - box.top) * yi) / (yCount - 1);
|
|
199
|
+
const elements =
|
|
200
|
+
typeof document.elementsFromPoint === 'function'
|
|
201
|
+
? document.elementsFromPoint(x, y)
|
|
202
|
+
: [document.elementFromPoint(x, y)].filter(Boolean);
|
|
203
|
+
for (const element of elements) {
|
|
204
|
+
let current = element;
|
|
205
|
+
while (current) {
|
|
206
|
+
candidates.add(current);
|
|
207
|
+
current = current.parentElement;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return Array.from(candidates)
|
|
213
|
+
.filter((element) => {
|
|
214
|
+
const rect = element.getBoundingClientRect();
|
|
215
|
+
return (
|
|
216
|
+
rect.left < box.right &&
|
|
217
|
+
rect.right > box.left &&
|
|
218
|
+
rect.top < box.bottom &&
|
|
219
|
+
rect.bottom > box.top &&
|
|
220
|
+
rect.width > 0 &&
|
|
221
|
+
rect.height > 0
|
|
222
|
+
);
|
|
223
|
+
})
|
|
224
|
+
.map(extractElement)
|
|
225
|
+
.filter(Boolean);
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const send = (source, id, responseNonce, payload) => {
|
|
229
|
+
source.postMessage(
|
|
230
|
+
{
|
|
231
|
+
channel: CHANNEL,
|
|
232
|
+
direction: 'response',
|
|
233
|
+
id,
|
|
234
|
+
responseNonce,
|
|
235
|
+
...payload,
|
|
236
|
+
},
|
|
237
|
+
EXPECTED_PARENT_ORIGIN,
|
|
238
|
+
);
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
window.addEventListener('message', (event) => {
|
|
242
|
+
const message = event.data;
|
|
243
|
+
if (!message || message.channel !== CHANNEL || message.direction !== 'request') {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (event.origin !== EXPECTED_PARENT_ORIGIN) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
event.stopImmediatePropagation();
|
|
250
|
+
const source = event.source;
|
|
251
|
+
if (!source || typeof source.postMessage !== 'function') {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
try {
|
|
255
|
+
let result = null;
|
|
256
|
+
if (message.action === 'elementAtPoint') {
|
|
257
|
+
result = extractElement(document.elementFromPoint(message.payload.x, message.payload.y));
|
|
258
|
+
} else if (message.action === 'elementsInBox') {
|
|
259
|
+
result = elementsInBox(message.payload);
|
|
260
|
+
} else if (message.action === 'resolveElement') {
|
|
261
|
+
result = extractElement(elementFromIdentifier(message.payload));
|
|
262
|
+
} else if (message.action === 'setCursor') {
|
|
263
|
+
const cursor = typeof message.payload.cursor === 'string' ? message.payload.cursor : '';
|
|
264
|
+
document.documentElement.style.cursor = cursor;
|
|
265
|
+
document.body.style.cursor = cursor;
|
|
266
|
+
result = true;
|
|
267
|
+
} else if (message.action === 'scrollBy') {
|
|
268
|
+
window.scrollBy(message.payload.deltaX || 0, message.payload.deltaY || 0);
|
|
269
|
+
result = true;
|
|
270
|
+
} else {
|
|
271
|
+
throw new Error('Unknown action');
|
|
272
|
+
}
|
|
273
|
+
send(source, message.id, message.responseNonce, { ok: true, result });
|
|
274
|
+
} catch (error) {
|
|
275
|
+
send(source, message.id, message.responseNonce, {
|
|
276
|
+
ok: false,
|
|
277
|
+
error: error instanceof Error ? error.message : String(error),
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
})();
|
|
282
|
+
`.trim();
|
|
283
|
+
const createPreviewBridgeScript = (options = {}) => {
|
|
284
|
+
const nonceAttribute = options.scriptNonce
|
|
285
|
+
? ` nonce="${options.scriptNonce}"`
|
|
286
|
+
: '';
|
|
287
|
+
return `<script id="${exports.PREVIEW_BRIDGE_SCRIPT_ID}"${nonceAttribute}>${buildBridgeScript(options)}</script>`;
|
|
288
|
+
};
|
|
289
|
+
exports.createPreviewBridgeScript = createPreviewBridgeScript;
|
|
290
|
+
const SCRIPT_DIRECTIVES = new Set(['script-src', 'script-src-elem']);
|
|
291
|
+
const splitCspDirective = (directive) => directive
|
|
292
|
+
.trim()
|
|
293
|
+
.split(/\s+/)
|
|
294
|
+
.filter((part) => part.length > 0);
|
|
295
|
+
const allowPreviewBridgeNonceInCsp = (csp, { scriptNonce }) => {
|
|
296
|
+
const nonceSource = `'nonce-${scriptNonce}'`;
|
|
297
|
+
const directives = csp
|
|
298
|
+
.split(';')
|
|
299
|
+
.map((directive) => directive.trim())
|
|
300
|
+
.filter((directive) => directive.length > 0);
|
|
301
|
+
let hasScriptDirective = false;
|
|
302
|
+
const nextDirectives = directives.map((directive) => {
|
|
303
|
+
const parts = splitCspDirective(directive);
|
|
304
|
+
const name = parts[0]?.toLowerCase();
|
|
305
|
+
if (!SCRIPT_DIRECTIVES.has(name)) {
|
|
306
|
+
return directive;
|
|
307
|
+
}
|
|
308
|
+
hasScriptDirective = true;
|
|
309
|
+
return parts.includes(nonceSource)
|
|
310
|
+
? directive
|
|
311
|
+
: [...parts, nonceSource].join(' ');
|
|
312
|
+
});
|
|
313
|
+
if (!hasScriptDirective) {
|
|
314
|
+
const defaultDirective = directives.find((directive) => splitCspDirective(directive)[0]?.toLowerCase() === 'default-src');
|
|
315
|
+
const defaultSources = defaultDirective
|
|
316
|
+
? splitCspDirective(defaultDirective).slice(1)
|
|
317
|
+
: [];
|
|
318
|
+
nextDirectives.push(['script-src', ...defaultSources, nonceSource].join(' '));
|
|
319
|
+
}
|
|
320
|
+
return nextDirectives.join('; ');
|
|
321
|
+
};
|
|
322
|
+
exports.allowPreviewBridgeNonceInCsp = allowPreviewBridgeNonceInCsp;
|
|
323
|
+
const firstHeaderValue = (value) => Array.isArray(value) ? (value[0] ?? '') : (value ?? '');
|
|
324
|
+
/** Decides whether a proxied response should receive the isolated-preview bridge. */
|
|
325
|
+
const shouldInjectPreviewBridge = ({ method, accept, contentType, }) => {
|
|
326
|
+
if (method != null && method !== 'GET') {
|
|
327
|
+
return false;
|
|
328
|
+
}
|
|
329
|
+
const normalizedAccept = firstHeaderValue(accept).toLowerCase();
|
|
330
|
+
const normalizedContentType = firstHeaderValue(contentType).toLowerCase();
|
|
331
|
+
return (normalizedAccept.includes('text/html') &&
|
|
332
|
+
normalizedContentType.includes('text/html'));
|
|
333
|
+
};
|
|
334
|
+
exports.shouldInjectPreviewBridge = shouldInjectPreviewBridge;
|
|
335
|
+
/** Adds the isolated-preview bridge to a proxied HTML document. */
|
|
336
|
+
const injectPreviewBridge = (html, options = {}) => {
|
|
337
|
+
if (html.includes(`id="${exports.PREVIEW_BRIDGE_SCRIPT_ID}"`)) {
|
|
338
|
+
return html;
|
|
339
|
+
}
|
|
340
|
+
const script = (0, exports.createPreviewBridgeScript)(options);
|
|
341
|
+
const headMatch = html.match(/<head[^>]*>/i);
|
|
342
|
+
if (headMatch?.index !== undefined) {
|
|
343
|
+
const insertAt = headMatch.index + headMatch[0].length;
|
|
344
|
+
return `${html.slice(0, insertAt)}${script}${html.slice(insertAt)}`;
|
|
345
|
+
}
|
|
346
|
+
if (html.includes('</head>')) {
|
|
347
|
+
return html.replace('</head>', `${script}</head>`);
|
|
348
|
+
}
|
|
349
|
+
if (html.includes('</body>')) {
|
|
350
|
+
return html.replace('</body>', `${script}</body>`);
|
|
351
|
+
}
|
|
352
|
+
return `${script}${html}`;
|
|
353
|
+
};
|
|
354
|
+
exports.injectPreviewBridge = injectPreviewBridge;
|
|
355
|
+
const isHtmlDocumentRequest = (req) => req.method === 'GET' &&
|
|
356
|
+
firstHeaderValue(req.headers.accept).toLowerCase().includes('text/html');
|
|
357
|
+
exports.isHtmlDocumentRequest = isHtmlDocumentRequest;
|
|
358
|
+
//# sourceMappingURL=preview-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-bridge.js","sourceRoot":"","sources":["../../src/proxy-middleware/preview-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from 'http';
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const markPreviewBridgeDocumentUncacheable: (proxyRes: IncomingMessage) => void;
|
|
3
|
+
export declare const createUserDevServerProxy: (userPort: number, userHost?: string, options?: {
|
|
4
|
+
isPreviewBridgeEnabled?: boolean;
|
|
5
|
+
expectedPreviewParentOrigin?: string;
|
|
6
|
+
}) => {
|
|
3
7
|
middleware: import("http-proxy-middleware").RequestHandler<IncomingMessage, ServerResponse<IncomingMessage>, (err?: any) => void>;
|
|
4
8
|
setVariantTarget: (port: number | null) => void;
|
|
5
9
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy-config.d.ts","sourceRoot":"","sources":["../../src/proxy-middleware/proxy-config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"proxy-config.d.ts","sourceRoot":"","sources":["../../src/proxy-middleware/proxy-config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAiB,MAAM,MAAM,CAAC;AAwB3E,eAAO,MAAM,oCAAoC,GAC/C,UAAU,eAAe,KACxB,IAEF,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,UAAU,MAAM,EAChB,WAAU,MAAoB,EAC9B,UAAS;IACP,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACjC;;6BAgC0B,MAAM,GAAG,IAAI;CAkM9C,CAAC"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createUserDevServerProxy = void 0;
|
|
3
|
+
exports.createUserDevServerProxy = exports.markPreviewBridgeDocumentUncacheable = void 0;
|
|
4
4
|
const http_proxy_middleware_1 = require("http-proxy-middleware");
|
|
5
|
+
const crypto_1 = require("crypto");
|
|
5
6
|
const logger_1 = require("../utils/logger");
|
|
7
|
+
const preview_bridge_1 = require("./preview-bridge");
|
|
6
8
|
const log = (0, logger_1.createLogger)('ProxyConfig');
|
|
7
9
|
/**
|
|
8
10
|
* Satisfies http-proxy-middleware's required `target` option; real routing is
|
|
@@ -11,9 +13,14 @@ const log = (0, logger_1.createLogger)('ProxyConfig');
|
|
|
11
13
|
*/
|
|
12
14
|
const PROXY_LIBRARY_PLACEHOLDER_TARGET = 'http://127.0.0.1:9';
|
|
13
15
|
const hasValidUserDevPort = (userPort) => Number.isInteger(userPort) && userPort > 0;
|
|
14
|
-
const
|
|
16
|
+
const markPreviewBridgeDocumentUncacheable = (proxyRes) => {
|
|
17
|
+
proxyRes.headers['cache-control'] = 'no-cache, no-store';
|
|
18
|
+
};
|
|
19
|
+
exports.markPreviewBridgeDocumentUncacheable = markPreviewBridgeDocumentUncacheable;
|
|
20
|
+
const createUserDevServerProxy = (userPort, userHost = 'localhost', options = {}) => {
|
|
15
21
|
let variantTarget = null;
|
|
16
22
|
const hasDefaultUpstream = hasValidUserDevPort(userPort);
|
|
23
|
+
const isPreviewBridgeEnabled = options.isPreviewBridgeEnabled ?? false;
|
|
17
24
|
const defaultTarget = hasDefaultUpstream
|
|
18
25
|
? `http://${userHost}:${userPort}`
|
|
19
26
|
: null;
|
|
@@ -45,25 +52,58 @@ const createUserDevServerProxy = (userPort, userHost = 'localhost') => {
|
|
|
45
52
|
const nextLabel = next ?? defaultTarget ?? '(none)';
|
|
46
53
|
log.info(`setVariantTarget: ${prior} → ${nextLabel}`);
|
|
47
54
|
};
|
|
48
|
-
const
|
|
55
|
+
const prepareProxyResponseHeaders = (proxyRes) => {
|
|
56
|
+
// Allow iframe embedding by removing restrictive security headers
|
|
57
|
+
delete proxyRes.headers['x-frame-options'];
|
|
58
|
+
delete proxyRes.headers['content-security-policy-report-only'];
|
|
59
|
+
// Update Content-Security-Policy to allow iframe embedding
|
|
60
|
+
if (proxyRes.headers['content-security-policy']) {
|
|
61
|
+
const csp = proxyRes.headers['content-security-policy'];
|
|
62
|
+
if (typeof csp === 'string') {
|
|
63
|
+
// Remove frame-ancestors to allow embedding anywhere during development
|
|
64
|
+
proxyRes.headers['content-security-policy'] = csp.replace(/frame-ancestors[^;]*;?/, '');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
const allowBridgeScriptInCsp = (proxyRes, scriptNonce) => {
|
|
69
|
+
const csp = proxyRes.headers['content-security-policy'];
|
|
70
|
+
if (typeof csp === 'string') {
|
|
71
|
+
proxyRes.headers['content-security-policy'] = (0, preview_bridge_1.allowPreviewBridgeNonceInCsp)(csp, { scriptNonce });
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (Array.isArray(csp)) {
|
|
75
|
+
proxyRes.headers['content-security-policy'] = csp.map((value) => (0, preview_bridge_1.allowPreviewBridgeNonceInCsp)(value, { scriptNonce }));
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const createProxyOptions = (isHtmlTransformProxy) => ({
|
|
49
79
|
target: defaultTarget ?? PROXY_LIBRARY_PLACEHOLDER_TARGET,
|
|
50
80
|
router: () => getRouterTargetForLibrary(),
|
|
51
81
|
changeOrigin: true,
|
|
82
|
+
selfHandleResponse: isHtmlTransformProxy,
|
|
52
83
|
// No path rewriting needed when proxying all routes by default
|
|
53
84
|
on: {
|
|
54
|
-
proxyRes:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
85
|
+
proxyRes: isHtmlTransformProxy
|
|
86
|
+
? (0, http_proxy_middleware_1.responseInterceptor)(async (responseBuffer, proxyRes, req, _res) => {
|
|
87
|
+
prepareProxyResponseHeaders(proxyRes);
|
|
88
|
+
const contentType = proxyRes.headers['content-type'];
|
|
89
|
+
if (!(0, preview_bridge_1.shouldInjectPreviewBridge)({
|
|
90
|
+
method: req.method,
|
|
91
|
+
accept: req.headers.accept,
|
|
92
|
+
contentType,
|
|
93
|
+
})) {
|
|
94
|
+
return responseBuffer;
|
|
64
95
|
}
|
|
65
|
-
|
|
66
|
-
|
|
96
|
+
const scriptNonce = (0, crypto_1.randomBytes)(16).toString('base64');
|
|
97
|
+
allowBridgeScriptInCsp(proxyRes, scriptNonce);
|
|
98
|
+
(0, exports.markPreviewBridgeDocumentUncacheable)(proxyRes);
|
|
99
|
+
return (0, preview_bridge_1.injectPreviewBridge)(responseBuffer.toString('utf8'), {
|
|
100
|
+
expectedParentOrigin: options.expectedPreviewParentOrigin,
|
|
101
|
+
scriptNonce,
|
|
102
|
+
});
|
|
103
|
+
})
|
|
104
|
+
: (proxyRes, _req, _res) => {
|
|
105
|
+
prepareProxyResponseHeaders(proxyRes);
|
|
106
|
+
},
|
|
67
107
|
proxyReq: (proxyReq, req, _res) => {
|
|
68
108
|
// Preserve the original host for Next.js Server Actions
|
|
69
109
|
// Next.js checks that x-forwarded-host matches the origin header
|
|
@@ -94,8 +134,9 @@ const createUserDevServerProxy = (userPort, userHost = 'localhost') => {
|
|
|
94
134
|
// Timeout configurations
|
|
95
135
|
proxyTimeout: 30_000, // In MS
|
|
96
136
|
timeout: 30_000, // In MS
|
|
97
|
-
};
|
|
98
|
-
const proxyMiddlewareInstance = (0, http_proxy_middleware_1.createProxyMiddleware)(
|
|
137
|
+
});
|
|
138
|
+
const proxyMiddlewareInstance = (0, http_proxy_middleware_1.createProxyMiddleware)(createProxyOptions(false));
|
|
139
|
+
const htmlTransformProxyMiddlewareInstance = (0, http_proxy_middleware_1.createProxyMiddleware)(createProxyOptions(true));
|
|
99
140
|
const gatedHttp = (req, res, next) => {
|
|
100
141
|
const upstream = getActiveUpstream();
|
|
101
142
|
if (upstream === null) {
|
|
@@ -109,7 +150,10 @@ const createUserDevServerProxy = (userPort, userHost = 'localhost') => {
|
|
|
109
150
|
}
|
|
110
151
|
return;
|
|
111
152
|
}
|
|
112
|
-
|
|
153
|
+
const middleware = isPreviewBridgeEnabled && (0, preview_bridge_1.isHtmlDocumentRequest)(req)
|
|
154
|
+
? htmlTransformProxyMiddlewareInstance
|
|
155
|
+
: proxyMiddlewareInstance;
|
|
156
|
+
void middleware(req, res, next);
|
|
113
157
|
};
|
|
114
158
|
const gated = gatedHttp;
|
|
115
159
|
gated.upgrade = (req, socket, head) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy-config.js","sourceRoot":"","sources":["../../src/proxy-middleware/proxy-config.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"proxy-config.js","sourceRoot":"","sources":["../../src/proxy-middleware/proxy-config.ts"],"names":[],"mappings":"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"}
|
package/dist/routes/mcp.d.ts
CHANGED
|
@@ -11,5 +11,7 @@ import type { AgentVariantsOrchestrator } from '../mcp/agent-variants';
|
|
|
11
11
|
* provided, the intake rejects new variant-request batches while a variants
|
|
12
12
|
* session is already active for the current project.
|
|
13
13
|
*/
|
|
14
|
-
export declare const createMCPRouter: (bridge: SessionBridgeService, telemetry?: TelemetryService, agentVariantsOrchestrator?: AgentVariantsOrchestrator
|
|
14
|
+
export declare const createMCPRouter: (bridge: SessionBridgeService, telemetry?: TelemetryService, agentVariantsOrchestrator?: AgentVariantsOrchestrator, options?: {
|
|
15
|
+
queueAccessToken?: string;
|
|
16
|
+
}) => Router;
|
|
15
17
|
//# sourceMappingURL=mcp.d.ts.map
|
package/dist/routes/mcp.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/routes/mcp.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAOrE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/routes/mcp.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAOrE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AA+RvE;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,GAC1B,QAAQ,oBAAoB,EAC5B,YAAY,gBAAgB,EAC5B,4BAA4B,yBAAyB,EACrD,UAAS;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAO,KAC1C,MA2QF,CAAC"}
|
package/dist/routes/mcp.js
CHANGED
|
@@ -40,8 +40,10 @@ const path = __importStar(require("path"));
|
|
|
40
40
|
const express_1 = require("express");
|
|
41
41
|
const v3_1 = require("zod/v3");
|
|
42
42
|
const index_core_1 = require("../index-core");
|
|
43
|
+
const elementFileHintSignals_1 = require("../utils/elementFileHintSignals");
|
|
43
44
|
const contracts_1 = require("../mcp/agent-variants/contracts");
|
|
44
45
|
const changeBatchClassification_1 = require("../mcp/changeBatchClassification");
|
|
46
|
+
const queueAccess_1 = require("../utils/queueAccess");
|
|
45
47
|
const log = (0, index_core_1.createLogger)('MCPRoutes');
|
|
46
48
|
const MAX_FILE_MATCHES_PER_ELEMENT = 6;
|
|
47
49
|
const elementRefSchema = v3_1.z.object({
|
|
@@ -51,6 +53,22 @@ const elementRefSchema = v3_1.z.object({
|
|
|
51
53
|
id: v3_1.z.string(),
|
|
52
54
|
filePaths: v3_1.z.array(v3_1.z.string()),
|
|
53
55
|
rivetId: v3_1.z.string().optional(),
|
|
56
|
+
textContent: v3_1.z.string().optional(),
|
|
57
|
+
attributes: v3_1.z.record(v3_1.z.string()).optional(),
|
|
58
|
+
componentTree: v3_1.z
|
|
59
|
+
.array(v3_1.z.object({
|
|
60
|
+
name: v3_1.z.string(),
|
|
61
|
+
type: v3_1.z.string().optional(),
|
|
62
|
+
depth: v3_1.z.number().optional(),
|
|
63
|
+
}))
|
|
64
|
+
.optional(),
|
|
65
|
+
parentElementSummary: v3_1.z
|
|
66
|
+
.object({
|
|
67
|
+
tagName: v3_1.z.string(),
|
|
68
|
+
className: v3_1.z.string(),
|
|
69
|
+
textSnippet: v3_1.z.string(),
|
|
70
|
+
})
|
|
71
|
+
.optional(),
|
|
54
72
|
});
|
|
55
73
|
const variantRequestSchema = v3_1.z.object({
|
|
56
74
|
count: v3_1.z
|
|
@@ -134,11 +152,13 @@ async function enrichChangeRequest(request, projectPath) {
|
|
|
134
152
|
const refsToEnrich = [];
|
|
135
153
|
for (const item of request.changes) {
|
|
136
154
|
if ('element' in item && item.element.filePaths.length === 0) {
|
|
137
|
-
|
|
155
|
+
if ((0, elementFileHintSignals_1.shouldSearchElementFileHints)(item.element)) {
|
|
156
|
+
refsToEnrich.push(item.element);
|
|
157
|
+
}
|
|
138
158
|
}
|
|
139
159
|
if ('elements' in item && item.elements) {
|
|
140
160
|
for (const el of item.elements) {
|
|
141
|
-
if (el.filePaths.length === 0) {
|
|
161
|
+
if (el.filePaths.length === 0 && (0, elementFileHintSignals_1.shouldSearchElementFileHints)(el)) {
|
|
142
162
|
refsToEnrich.push(el);
|
|
143
163
|
}
|
|
144
164
|
}
|
|
@@ -258,7 +278,7 @@ function resolveCommentReference(ref, orchestrator, projectPath) {
|
|
|
258
278
|
* provided, the intake rejects new variant-request batches while a variants
|
|
259
279
|
* session is already active for the current project.
|
|
260
280
|
*/
|
|
261
|
-
const createMCPRouter = (bridge, telemetry, agentVariantsOrchestrator) => {
|
|
281
|
+
const createMCPRouter = (bridge, telemetry, agentVariantsOrchestrator, options = {}) => {
|
|
262
282
|
const router = (0, express_1.Router)();
|
|
263
283
|
/**
|
|
264
284
|
* Queue a ChangeRequest from the Rivet UI for retrieval by the MCP client.
|
|
@@ -269,6 +289,16 @@ const createMCPRouter = (bridge, telemetry, agentVariantsOrchestrator) => {
|
|
|
269
289
|
res.status(400).json({ error: 'No active MCP session' });
|
|
270
290
|
return;
|
|
271
291
|
}
|
|
292
|
+
if (!(0, queueAccess_1.isQueueAccessAuthorized)({
|
|
293
|
+
queueAccessToken: options.queueAccessToken,
|
|
294
|
+
getHeader: (name) => req.header(name),
|
|
295
|
+
})) {
|
|
296
|
+
res.status(403).json({
|
|
297
|
+
error: 'Queue access denied',
|
|
298
|
+
reason: 'queue_token_required',
|
|
299
|
+
});
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
272
302
|
const parsed = changeRequestSchema.safeParse(req.body);
|
|
273
303
|
if (!parsed.success) {
|
|
274
304
|
res.status(400).json({
|