@agent-native/core 0.114.11 → 0.114.12
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/corpus/core/CHANGELOG.md +6 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +89 -1
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.js +65 -1
- package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/secrets/routes.d.ts +6 -6
- package/package.json +1 -1
- package/src/client/extensions/EmbeddedExtension.tsx +89 -1
package/corpus/core/CHANGELOG.md
CHANGED
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.114.
|
|
3
|
+
"version": "0.114.12",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -177,6 +177,7 @@ export function EmbeddedExtension({
|
|
|
177
177
|
// originates inside the same sandboxed realm as user code) and must be
|
|
178
178
|
// ignored so a viewer cannot self-escalate to owner.
|
|
179
179
|
const bindingLatchedRef = useRef(false);
|
|
180
|
+
const extensionRef = useRef(null as null | Extension);
|
|
180
181
|
|
|
181
182
|
useEffect(() => {
|
|
182
183
|
setIsDark(document.documentElement.classList.contains("dark"));
|
|
@@ -216,6 +217,7 @@ export function EmbeddedExtension({
|
|
|
216
217
|
retry: shouldRetryExtensionLoad,
|
|
217
218
|
retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 4000),
|
|
218
219
|
});
|
|
220
|
+
extensionRef.current = extension ?? null;
|
|
219
221
|
|
|
220
222
|
// Notify the host once when the extension can't be loaded for this viewer so
|
|
221
223
|
// it can show a fallback instead of a blank panel.
|
|
@@ -338,6 +340,92 @@ export function EmbeddedExtension({
|
|
|
338
340
|
return;
|
|
339
341
|
}
|
|
340
342
|
|
|
343
|
+
if (message.type === "agent-native-extension-error-fix") {
|
|
344
|
+
const name = extensionRef.current?.name ?? extensionId;
|
|
345
|
+
const errors: string[] = Array.isArray((message as any).errors)
|
|
346
|
+
? (message as any).errors
|
|
347
|
+
: [];
|
|
348
|
+
const errorDetails: Array<{ message: string; stack: string }> =
|
|
349
|
+
Array.isArray((message as any).errorDetails)
|
|
350
|
+
? (message as any).errorDetails
|
|
351
|
+
: [];
|
|
352
|
+
const consoleLogs: Array<{ level: string; message: string }> =
|
|
353
|
+
Array.isArray((message as any).consoleLogs)
|
|
354
|
+
? (message as any).consoleLogs
|
|
355
|
+
: [];
|
|
356
|
+
const networkLogs: Array<{
|
|
357
|
+
path: string;
|
|
358
|
+
method: string;
|
|
359
|
+
ok?: boolean;
|
|
360
|
+
status?: number;
|
|
361
|
+
error?: string;
|
|
362
|
+
}> = Array.isArray((message as any).networkLogs)
|
|
363
|
+
? (message as any).networkLogs
|
|
364
|
+
: [];
|
|
365
|
+
|
|
366
|
+
const detailedTrace = errorDetails
|
|
367
|
+
.filter((e) => e && typeof e === "object")
|
|
368
|
+
.map((e) => {
|
|
369
|
+
const msg =
|
|
370
|
+
typeof e.message === "string" ? e.message : String(e.message);
|
|
371
|
+
return typeof e.stack === "string" ? `${msg}\n${e.stack}` : msg;
|
|
372
|
+
})
|
|
373
|
+
.join("\n\n");
|
|
374
|
+
|
|
375
|
+
// Force a fresh read from the server, same as ExtensionViewer's fix
|
|
376
|
+
// flow — the query cache may hold the agent's previous (broken) turn.
|
|
377
|
+
let freshContent: string | undefined;
|
|
378
|
+
try {
|
|
379
|
+
const res = await fetch(
|
|
380
|
+
agentNativePath(`/_agent-native/extensions/${extensionId}`),
|
|
381
|
+
{ cache: "no-store" },
|
|
382
|
+
);
|
|
383
|
+
if (res.ok) {
|
|
384
|
+
const fresh = (await res.json()) as Extension;
|
|
385
|
+
freshContent =
|
|
386
|
+
typeof fresh?.content === "string" ? fresh.content : undefined;
|
|
387
|
+
}
|
|
388
|
+
} catch {
|
|
389
|
+
// Fall through with no snapshot — agent can still re-read via get-extension.
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const contextParts = [
|
|
393
|
+
`The user is viewing a dashboard panel embedding extension "${name}" (id: ${extensionId}, slot: ${slotId}) and there are runtime errors that need fixing.`,
|
|
394
|
+
`\nFull error details:\n${detailedTrace}`,
|
|
395
|
+
];
|
|
396
|
+
|
|
397
|
+
if (consoleLogs.length > 0) {
|
|
398
|
+
const consoleStr = consoleLogs
|
|
399
|
+
.map((l) => `[${l.level}] ${l.message}`)
|
|
400
|
+
.join("\n");
|
|
401
|
+
contextParts.push(`\nRecent console output:\n${consoleStr}`);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (networkLogs.length > 0) {
|
|
405
|
+
const netStr = networkLogs
|
|
406
|
+
.map(
|
|
407
|
+
(l) =>
|
|
408
|
+
`${l.method} ${l.path} → ${l.ok ? l.status : "FAILED: " + (l.error || l.status)}`,
|
|
409
|
+
)
|
|
410
|
+
.join("\n");
|
|
411
|
+
contextParts.push(`\nRecent network requests:\n${netStr}`);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (freshContent) {
|
|
415
|
+
contextParts.push(
|
|
416
|
+
`\nCurrent extension content (just re-read from the database — this is the authoritative source, not anything you may have written in a previous turn):\n\`\`\`html\n${freshContent}\n\`\`\``,
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
sendToAgentChat({
|
|
421
|
+
message: `Fix runtime errors in extension "${name}" (id: ${extensionId}), embedded as a dashboard panel. The content snapshot below was just re-read from the database — treat it as authoritative and ignore any prior version you may have generated in this chat. If in doubt, call get-extension first.\n\nErrors:\n${errors.join("\n")}`,
|
|
422
|
+
context: contextParts.join("\n"),
|
|
423
|
+
submit: true,
|
|
424
|
+
openSidebar: true,
|
|
425
|
+
});
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
|
|
341
429
|
if (message.type !== "agent-native-extension-request") return;
|
|
342
430
|
|
|
343
431
|
const requestId = String(message.requestId ?? "");
|
|
@@ -410,7 +498,7 @@ export function EmbeddedExtension({
|
|
|
410
498
|
|
|
411
499
|
window.addEventListener("message", handleMessage);
|
|
412
500
|
return () => window.removeEventListener("message", handleMessage);
|
|
413
|
-
}, [extensionId]);
|
|
501
|
+
}, [extensionId, slotId]);
|
|
414
502
|
|
|
415
503
|
if (!extension) {
|
|
416
504
|
if (!isLoading && !isFetching) return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmbeddedExtension.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/EmbeddedExtension.tsx"],"names":[],"mappings":"AAwFA;;;;;;;;;;GAUG;AACH,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GAClD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB;2CACuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf;iDAC6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;qEAEiE;IACjE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;4EAGwE;IACxE,aAAa,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,MAAM,EACN,OAAO,EACP,SAAS,EACT,aAAkB,EAClB,OAAO,EACP,aAAa,GACd,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"EmbeddedExtension.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/EmbeddedExtension.tsx"],"names":[],"mappings":"AAwFA;;;;;;;;;;GAUG;AACH,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GAClD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB;2CACuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf;iDAC6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;qEAEiE;IACjE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;4EAGwE;IACxE,aAAa,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,MAAM,EACN,OAAO,EACP,SAAS,EACT,aAAkB,EAClB,OAAO,EACP,aAAa,GACd,EAAE,sBAAsB,sCAsZxB"}
|
|
@@ -102,6 +102,7 @@ export function EmbeddedExtension({ extensionId, slotId, context, className, ini
|
|
|
102
102
|
// originates inside the same sandboxed realm as user code) and must be
|
|
103
103
|
// ignored so a viewer cannot self-escalate to owner.
|
|
104
104
|
const bindingLatchedRef = useRef(false);
|
|
105
|
+
const extensionRef = useRef(null);
|
|
105
106
|
useEffect(() => {
|
|
106
107
|
setIsDark(document.documentElement.classList.contains("dark"));
|
|
107
108
|
const observer = new MutationObserver(() => {
|
|
@@ -131,6 +132,7 @@ export function EmbeddedExtension({ extensionId, slotId, context, className, ini
|
|
|
131
132
|
retry: shouldRetryExtensionLoad,
|
|
132
133
|
retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 4000),
|
|
133
134
|
});
|
|
135
|
+
extensionRef.current = extension ?? null;
|
|
134
136
|
// Notify the host once when the extension can't be loaded for this viewer so
|
|
135
137
|
// it can show a fallback instead of a blank panel.
|
|
136
138
|
const onUnavailableRef = useRef(onUnavailable);
|
|
@@ -238,6 +240,68 @@ export function EmbeddedExtension({ extensionId, slotId, context, className, ini
|
|
|
238
240
|
});
|
|
239
241
|
return;
|
|
240
242
|
}
|
|
243
|
+
if (message.type === "agent-native-extension-error-fix") {
|
|
244
|
+
const name = extensionRef.current?.name ?? extensionId;
|
|
245
|
+
const errors = Array.isArray(message.errors)
|
|
246
|
+
? message.errors
|
|
247
|
+
: [];
|
|
248
|
+
const errorDetails = Array.isArray(message.errorDetails)
|
|
249
|
+
? message.errorDetails
|
|
250
|
+
: [];
|
|
251
|
+
const consoleLogs = Array.isArray(message.consoleLogs)
|
|
252
|
+
? message.consoleLogs
|
|
253
|
+
: [];
|
|
254
|
+
const networkLogs = Array.isArray(message.networkLogs)
|
|
255
|
+
? message.networkLogs
|
|
256
|
+
: [];
|
|
257
|
+
const detailedTrace = errorDetails
|
|
258
|
+
.filter((e) => e && typeof e === "object")
|
|
259
|
+
.map((e) => {
|
|
260
|
+
const msg = typeof e.message === "string" ? e.message : String(e.message);
|
|
261
|
+
return typeof e.stack === "string" ? `${msg}\n${e.stack}` : msg;
|
|
262
|
+
})
|
|
263
|
+
.join("\n\n");
|
|
264
|
+
// Force a fresh read from the server, same as ExtensionViewer's fix
|
|
265
|
+
// flow — the query cache may hold the agent's previous (broken) turn.
|
|
266
|
+
let freshContent;
|
|
267
|
+
try {
|
|
268
|
+
const res = await fetch(agentNativePath(`/_agent-native/extensions/${extensionId}`), { cache: "no-store" });
|
|
269
|
+
if (res.ok) {
|
|
270
|
+
const fresh = (await res.json());
|
|
271
|
+
freshContent =
|
|
272
|
+
typeof fresh?.content === "string" ? fresh.content : undefined;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
// Fall through with no snapshot — agent can still re-read via get-extension.
|
|
277
|
+
}
|
|
278
|
+
const contextParts = [
|
|
279
|
+
`The user is viewing a dashboard panel embedding extension "${name}" (id: ${extensionId}, slot: ${slotId}) and there are runtime errors that need fixing.`,
|
|
280
|
+
`\nFull error details:\n${detailedTrace}`,
|
|
281
|
+
];
|
|
282
|
+
if (consoleLogs.length > 0) {
|
|
283
|
+
const consoleStr = consoleLogs
|
|
284
|
+
.map((l) => `[${l.level}] ${l.message}`)
|
|
285
|
+
.join("\n");
|
|
286
|
+
contextParts.push(`\nRecent console output:\n${consoleStr}`);
|
|
287
|
+
}
|
|
288
|
+
if (networkLogs.length > 0) {
|
|
289
|
+
const netStr = networkLogs
|
|
290
|
+
.map((l) => `${l.method} ${l.path} → ${l.ok ? l.status : "FAILED: " + (l.error || l.status)}`)
|
|
291
|
+
.join("\n");
|
|
292
|
+
contextParts.push(`\nRecent network requests:\n${netStr}`);
|
|
293
|
+
}
|
|
294
|
+
if (freshContent) {
|
|
295
|
+
contextParts.push(`\nCurrent extension content (just re-read from the database — this is the authoritative source, not anything you may have written in a previous turn):\n\`\`\`html\n${freshContent}\n\`\`\``);
|
|
296
|
+
}
|
|
297
|
+
sendToAgentChat({
|
|
298
|
+
message: `Fix runtime errors in extension "${name}" (id: ${extensionId}), embedded as a dashboard panel. The content snapshot below was just re-read from the database — treat it as authoritative and ignore any prior version you may have generated in this chat. If in doubt, call get-extension first.\n\nErrors:\n${errors.join("\n")}`,
|
|
299
|
+
context: contextParts.join("\n"),
|
|
300
|
+
submit: true,
|
|
301
|
+
openSidebar: true,
|
|
302
|
+
});
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
241
305
|
if (message.type !== "agent-native-extension-request")
|
|
242
306
|
return;
|
|
243
307
|
const requestId = String(message.requestId ?? "");
|
|
@@ -306,7 +370,7 @@ export function EmbeddedExtension({ extensionId, slotId, context, className, ini
|
|
|
306
370
|
};
|
|
307
371
|
window.addEventListener("message", handleMessage);
|
|
308
372
|
return () => window.removeEventListener("message", handleMessage);
|
|
309
|
-
}, [extensionId]);
|
|
373
|
+
}, [extensionId, slotId]);
|
|
310
374
|
if (!extension) {
|
|
311
375
|
if (!isLoading && !isFetching)
|
|
312
376
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmbeddedExtension.js","sourceRoot":"","sources":["../../../src/client/extensions/EmbeddedExtension.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n IconDots,\n IconExternalLink,\n IconLayoutSidebarRightCollapse,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { Link } from \"react-router\";\n\nimport { extensionPath } from \"../../extensions/path.js\";\nimport { THEME_VAR_NAMES } from \"../../extensions/theme.js\";\nimport { SESSION_REPLAY_IFRAME_ATTRIBUTE } from \"../../session-replay-iframe-protocol.js\";\nimport { sendToAgentChat } from \"../agent-chat.js\";\nimport { agentNativePath } from \"../api-path.js\";\nimport { useAppearance } from \"../appearance.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\nimport { useT } from \"../i18n.js\";\nimport {\n deleteOrHideExtension,\n invalidateExtensionRemoval,\n} from \"./delete-extension.js\";\nimport {\n extensionLoadError,\n extensionLoadErrorStatus,\n shouldRetryExtensionLoad,\n} from \"./extension-load-error.js\";\nimport {\n isAllowedExtensionPath,\n sanitizeExtensionRequestOptions,\n checkBridgePolicy,\n type BridgePolicyContext,\n type ExtensionBridgeRole,\n} from \"./iframe-bridge.js\";\nimport { normalizeAgentNativeExtensionSandbox } from \"./portable-extension.js\";\n\ninterface Extension {\n id: string;\n name: string;\n description?: string;\n content?: string;\n updatedAt?: string;\n canDelete?: boolean;\n source?: {\n mode?: \"database\" | \"local-files\";\n permissions?: BridgePolicyContext[\"permissions\"];\n };\n}\n\nconst EXTENSION_IFRAME_SANDBOX =\n normalizeAgentNativeExtensionSandbox(undefined);\n\n// Read the host app's *actual* computed theme values for the shared token set\n// (THEME_VAR_NAMES). The iframe ships with a generic baked palette\n// (getThemeVars); syncing the live values keeps embedded extensions visually\n// identical to the surrounding app even when a template overrides the default\n// palette (e.g. analytics uses a neutral-gray dark theme, not near-black).\nfunction readHostThemeVars(): Record<string, string> {\n if (typeof document === \"undefined\") return {};\n const computed = getComputedStyle(document.documentElement);\n const vars: Record<string, string> = {};\n for (const name of THEME_VAR_NAMES) {\n const value = computed.getPropertyValue(name).trim();\n if (value) vars[name] = value;\n }\n return vars;\n}\n\nfunction serializeChatValue(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\n/**\n * Slot contexts (e.g. Design's `DesignExtensionSlotContext`) commonly carry\n * live callback functions alongside plain data — the host component uses\n * those callbacks itself, but `window.postMessage` uses the structured clone\n * algorithm, which throws a `DataCloneError` on any function-valued property\n * (see MDN's postMessage docs). Round-tripping through JSON drops functions\n * (and other non-cloneable values like symbols) the same way\n * `JSON.stringify` already silently omits them, producing a payload that's\n * safe to post. Exported so a test can verify functions never reach the\n * iframe instead of only reading the code.\n */\nexport function sanitizeSlotContextForPostMessage(\n context: Record<string, unknown> | null | undefined,\n): Record<string, unknown> {\n try {\n return JSON.parse(JSON.stringify(context ?? {}));\n } catch {\n // Circular reference or other non-serializable shape — fail safe to an\n // empty context rather than letting postMessage throw and skip every\n // other message this handler sends in the same tick (theme update,\n // ready signal).\n return {};\n }\n}\n\nexport interface EmbeddedExtensionProps {\n extensionId: string;\n /** Slot identifier passed via the iframe URL so the extension runtime knows it's\n * embedded and enables auto-resize. */\n slotId: string;\n /** Object pushed into the extension as `window.slotContext`. Re-posted whenever\n * the host re-renders with a new context. */\n context?: Record<string, unknown> | null;\n /** Optional className applied to the iframe container. */\n className?: string;\n /** Initial iframe height before content reports a real height. */\n initialHeight?: number;\n /** Fires once when the embedded iframe first signals content readiness — its\n * first height report, or iframe load as a fallback. Hosts that gate on\n * content paint (e.g. dashboard report screenshots) use this. */\n onReady?: () => void;\n /** Fires when the extension can't be loaded for this viewer (e.g. 403/404 —\n * the extension isn't shared with them or no longer exists). Hosts can use\n * this to render an explanatory fallback instead of a blank panel. By default\n * the component renders nothing on failure (slot-style silent skip). */\n onUnavailable?: (status?: number) => void;\n}\n\n/**\n * Renders a extension inline as a small auto-sized iframe — for use inside an\n * `<ExtensionSlot>`. Different from `<ExtensionViewer>` (which is full-page with a\n * toolbar): no header, sized to content, receives a `slotContext`.\n */\nexport function EmbeddedExtension({\n extensionId,\n slotId,\n context,\n className,\n initialHeight = 80,\n onReady,\n onUnavailable,\n}: EmbeddedExtensionProps) {\n const iframeRef = useRef<HTMLIFrameElement | null>(null);\n // Latch the readiness signal so onReady fires at most once per iframe\n // instance. Reset when the iframe is recreated (extensionId/updatedAt change).\n const onReadyRef = useRef(onReady);\n onReadyRef.current = onReady;\n const readyFiredRef = useRef(false);\n const fireReady = () => {\n if (readyFiredRef.current) return;\n readyFiredRef.current = true;\n onReadyRef.current?.();\n };\n const [height, setHeight] = useState<number>(initialHeight);\n const [isDark, setIsDark] = useState(\n () =>\n typeof document !== \"undefined\" &&\n document.documentElement.classList.contains(\"dark\"),\n );\n // (audit H4) Mirror ExtensionViewer's role-aware gating; deny-by-default until\n // the iframe's render binding announcement arrives.\n const bridgeContextRef = useRef<BridgePolicyContext>({\n role: \"viewer\",\n isAuthor: false,\n });\n // (audit H4) Latch the render binding once per iframe instance. The shell\n // posts the server-resolved binding BEFORE user content runs; any later\n // agent-native-extension-binding message is attacker-controllable (it\n // originates inside the same sandboxed realm as user code) and must be\n // ignored so a viewer cannot self-escalate to owner.\n const bindingLatchedRef = useRef(false);\n\n useEffect(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n const observer = new MutationObserver(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n });\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\"],\n });\n return () => observer.disconnect();\n }, []);\n\n const {\n data: extension,\n isFetching,\n isLoading,\n isError,\n error,\n } = useQuery<Extension>({\n queryKey: [\"extension\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n );\n if (res.status === 404) {\n throw extensionLoadError(404, \"Extension not found\");\n }\n if (res.status === 403) {\n throw extensionLoadError(403, \"Extension access denied\");\n }\n if (!res.ok) {\n throw extensionLoadError(res.status, \"Failed to fetch extension\");\n }\n return res.json();\n },\n retry: shouldRetryExtensionLoad,\n retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 4000),\n });\n\n // Notify the host once when the extension can't be loaded for this viewer so\n // it can show a fallback instead of a blank panel.\n const onUnavailableRef = useRef(onUnavailable);\n onUnavailableRef.current = onUnavailable;\n const unavailableFiredRef = useRef(false);\n useEffect(() => {\n unavailableFiredRef.current = false;\n }, [extensionId]);\n useEffect(() => {\n if (isError && !isFetching && !unavailableFiredRef.current) {\n unavailableFiredRef.current = true;\n onUnavailableRef.current?.(extensionLoadErrorStatus(error));\n }\n }, [isError, isFetching, error]);\n\n // Initial dark state is baked into the URL on first load only; subsequent\n // theme toggles update the iframe's <html class=\"dark\"> via postMessage so\n // the user's interaction state inside the extension survives the toggle.\n const initialDarkRef = useRef(isDark);\n const iframeSrc = useMemo(() => {\n const v = encodeURIComponent(extension?.updatedAt ?? \"\");\n return agentNativePath(\n `/_agent-native/extensions/${extensionId}/render?slot=${encodeURIComponent(slotId)}&dark=${initialDarkRef.current}&v=${v}`,\n );\n }, [extensionId, slotId, extension?.updatedAt]);\n\n // Reset role + binding latch to deny-by-default whenever the iframe is\n // recreated (its key changes). The new render's first binding announcement\n // re-establishes the role.\n useEffect(() => {\n bridgeContextRef.current = { role: \"viewer\", isAuthor: false };\n bindingLatchedRef.current = false;\n readyFiredRef.current = false;\n }, [extensionId, extension?.updatedAt]);\n\n const appearance = useAppearance();\n\n useEffect(() => {\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n win.postMessage(\n { type: \"agent-native-theme-update\", isDark, vars: readHostThemeVars() },\n \"*\",\n );\n }, [isDark, appearance]);\n\n // Forward slot context whenever it changes. The iframe's own load handler\n // posts the initial value once it's ready; this effect handles updates.\n const contextJson = JSON.stringify(context ?? {});\n useEffect(() => {\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n // Post the JSON-round-tripped context, not the raw `context` object —\n // slot contexts (e.g. Design's DesignExtensionSlotContext) carry live\n // callback functions the host uses internally, and postMessage's\n // structured clone throws a DataCloneError on any function-valued\n // property. See sanitizeSlotContextForPostMessage's docblock.\n win.postMessage(\n {\n type: \"agent-native-slot-context\",\n context: sanitizeSlotContextForPostMessage(context),\n },\n \"*\",\n );\n }, [contextJson]);\n\n // Bridge extension requests + height reports.\n useEffect(() => {\n const handleMessage = async (event: MessageEvent) => {\n if (event.source !== iframeRef.current?.contentWindow) return;\n const message = event.data;\n if (!message || typeof message !== \"object\") return;\n\n if (message.type === \"agent-native-extension-binding\") {\n // Only the FIRST announcement (sent by the shell before user content\n // runs) is trusted. Ignore re-announcements — a malicious extension\n // body could otherwise postMessage a forged owner binding to escalate.\n if (bindingLatchedRef.current) return;\n bindingLatchedRef.current = true;\n const binding = (message as any).binding ?? {};\n const role: ExtensionBridgeRole =\n binding.role === \"owner\" ||\n binding.role === \"admin\" ||\n binding.role === \"editor\" ||\n binding.role === \"viewer\"\n ? binding.role\n : \"viewer\";\n bridgeContextRef.current = {\n role,\n isAuthor: !!binding.isAuthor,\n source: binding.source === \"local-files\" ? \"local-files\" : \"database\",\n permissions:\n binding && typeof binding.permissions === \"object\"\n ? binding.permissions\n : undefined,\n };\n return;\n }\n\n if (message.type === \"agent-native-extension-resize\") {\n const h = Number(message.height);\n if (Number.isFinite(h) && h > 0) {\n setHeight(Math.ceil(h));\n // First laid-out height means the content has painted.\n fireReady();\n }\n return;\n }\n\n if (message.type === \"agent-native-send-to-chat\") {\n const text = serializeChatValue((message as any).message);\n if (!text?.trim()) return;\n sendToAgentChat({\n message: text,\n context: serializeChatValue((message as any).context),\n submit: (message as any).submit !== false,\n openSidebar: (message as any).openSidebar !== false,\n });\n return;\n }\n\n if (message.type !== \"agent-native-extension-request\") return;\n\n const requestId = String(message.requestId ?? \"\");\n const path = String(message.path ?? \"\");\n const respond = (payload: Record<string, unknown>) => {\n iframeRef.current?.contentWindow?.postMessage(\n { type: \"agent-native-extension-response\", requestId, ...payload },\n \"*\",\n );\n };\n\n if (!requestId || !isAllowedExtensionPath(path, extensionId)) {\n respond({ error: \"Extension request path is not allowed\" });\n return;\n }\n\n try {\n const options = sanitizeExtensionRequestOptions(message.options);\n // (audit H4) Role-aware gating: viewer-shared extensions can read but not\n // write. The bridge policy is decided here in the parent before the\n // request leaves; the server enforces a second layer.\n const policy = checkBridgePolicy(path, options.method ?? \"GET\", {\n ...bridgeContextRef.current,\n extensionId,\n });\n if (!policy.ok) {\n respond({\n response: {\n ok: false,\n status: 403,\n statusText: \"Forbidden\",\n body: { error: policy.error },\n },\n });\n return;\n }\n // (audit H5) Same extension-bridge tagging as <ExtensionViewer>. action-routes\n // uses these headers to enforce per-action `toolCallable` opt-in.\n const finalHeaders = new Headers(options.headers ?? undefined);\n finalHeaders.set(\"X-Agent-Native-Extension-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Extension-Id\", extensionId);\n finalHeaders.set(\"X-Agent-Native-Tool-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Tool-Id\", extensionId);\n const res = await fetch(agentNativePath(path), {\n ...options,\n headers: finalHeaders,\n credentials: \"same-origin\",\n });\n const text = await res.text();\n let body: unknown = text;\n if (text) {\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n }\n respond({\n response: {\n ok: res.ok,\n status: res.status,\n statusText: res.statusText,\n body,\n },\n });\n } catch (err: any) {\n respond({ error: err?.message ?? \"Extension host request failed\" });\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [extensionId]);\n\n if (!extension) {\n if (!isLoading && !isFetching) return null;\n return (\n <div\n className={className}\n style={{ height: initialHeight }}\n aria-busy=\"true\"\n />\n );\n }\n\n return (\n <div className={`relative group/embedded-extension ${className ?? \"\"}`}>\n <iframe\n {...{ [SESSION_REPLAY_IFRAME_ATTRIBUTE]: \"\" }}\n ref={iframeRef}\n key={`${extensionId}-${extension.updatedAt ?? \"\"}`}\n src={iframeSrc}\n title={extension.name}\n sandbox={EXTENSION_IFRAME_SANDBOX}\n style={{ width: \"100%\", border: 0, height, display: \"block\" }}\n onLoad={() => {\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: \"agent-native-slot-context\",\n context: sanitizeSlotContextForPostMessage(context),\n },\n \"*\",\n );\n // Re-assert theme once the iframe document is live. The src bakes in\n // the initial dark state, but this covers the race where isDark\n // settled before the iframe's message listener existed.\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: \"agent-native-theme-update\",\n isDark,\n vars: readHostThemeVars(),\n },\n \"*\",\n );\n // Fallback readiness signal in case the extension never reports a\n // height (e.g. fixed-height content that skips auto-resize).\n fireReady();\n }}\n />\n <EmbeddedToolMenu\n extensionId={extensionId}\n slotId={slotId}\n toolName={extension.name}\n canDelete={extension.canDelete}\n />\n </div>\n );\n}\n\nfunction EmbeddedToolMenu({\n extensionId,\n slotId,\n toolName,\n canDelete,\n}: {\n extensionId: string;\n slotId: string;\n toolName: string;\n canDelete?: boolean;\n}) {\n const t = useT();\n const [open, setOpen] = useState(false);\n const [confirmingDelete, setConfirmingDelete] = useState(false);\n const queryClient = useQueryClient();\n\n const closeMenu = () => {\n setOpen(false);\n setConfirmingDelete(false);\n };\n\n const removeFromSlot = async () => {\n closeMenu();\n queryClient.setQueryData<any[]>([\"slot-installs\", slotId], (old) =>\n (old ?? []).filter((i) => i.extensionId !== extensionId),\n );\n try {\n await fetch(\n agentNativePath(\n `/_agent-native/slots/${encodeURIComponent(slotId)}/install/${encodeURIComponent(extensionId)}`,\n ),\n { method: \"DELETE\" },\n );\n } finally {\n queryClient.invalidateQueries({ queryKey: [\"slot-installs\", slotId] });\n }\n };\n\n const deleteExtension = async () => {\n closeMenu();\n try {\n await deleteOrHideExtension({ id: extensionId, canDelete });\n invalidateExtensionRemoval(queryClient, extensionId);\n } catch {\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n }\n };\n\n return (\n <Popover\n open={open}\n onOpenChange={(o) => {\n setOpen(o);\n if (!o) setConfirmingDelete(false);\n }}\n >\n <TooltipProvider delayDuration={200}>\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"absolute top-1 right-1 flex h-6 w-6 items-center justify-center rounded-md bg-background/60 text-muted-foreground/60 opacity-0 hover:bg-accent hover:text-foreground hover:opacity-100 group-hover/embedded-extension:opacity-100 cursor-pointer transition-opacity\"\n aria-label={t(\"extensions.optionsFor\", { name: toolName })}\n >\n <IconDots className=\"h-3.5 w-3.5\" />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>\n {t(\"extensions.optionsFor\", { name: toolName })}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n <PopoverContent align=\"end\" sideOffset={4} className=\"w-56 p-1\">\n {!confirmingDelete ? (\n <div className=\"flex flex-col\">\n <Link\n to={extensionPath(extensionId, toolName)}\n onClick={closeMenu}\n className=\"flex items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] hover:bg-accent cursor-pointer text-left\"\n >\n <IconExternalLink className=\"h-3.5 w-3.5\" />\n <span>{t(\"extensions.openFullView\")}</span>\n </Link>\n <button\n type=\"button\"\n onClick={removeFromSlot}\n className=\"flex items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] hover:bg-accent cursor-pointer text-left\"\n >\n <IconLayoutSidebarRightCollapse className=\"h-3.5 w-3.5\" />\n <span>{t(\"extensions.removeFromWidgetArea\")}</span>\n </button>\n {canDelete !== false && (\n <>\n <div className=\"my-1 h-px bg-border/40\" />\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(true)}\n className=\"flex items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] text-destructive hover:bg-destructive/10 cursor-pointer text-left\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n <span>{t(\"extensions.deleteExtensionEllipsis\")}</span>\n </button>\n </>\n )}\n </div>\n ) : (\n <div className=\"flex flex-col gap-2 p-2\">\n <p className=\"text-[12px]\">\n {t(\"extensions.deleteQuestion\", { name: toolName })}{\" \"}\n {t(\"extensions.deleteEverywhereConfirmation\")}\n </p>\n <div className=\"flex justify-end gap-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(false)}\n className=\"rounded-md px-2 py-1 text-[12px] hover:bg-accent cursor-pointer\"\n >\n {t(\"extensions.cancel\")}\n </button>\n <button\n type=\"button\"\n onClick={deleteExtension}\n className=\"rounded-md bg-destructive px-2 py-1 text-[12px] text-destructive-foreground hover:bg-destructive/90 cursor-pointer\"\n >\n {t(\"extensions.delete\")}\n </button>\n </div>\n </div>\n )}\n </PopoverContent>\n </Popover>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"EmbeddedExtension.js","sourceRoot":"","sources":["../../../src/client/extensions/EmbeddedExtension.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n IconDots,\n IconExternalLink,\n IconLayoutSidebarRightCollapse,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { Link } from \"react-router\";\n\nimport { extensionPath } from \"../../extensions/path.js\";\nimport { THEME_VAR_NAMES } from \"../../extensions/theme.js\";\nimport { SESSION_REPLAY_IFRAME_ATTRIBUTE } from \"../../session-replay-iframe-protocol.js\";\nimport { sendToAgentChat } from \"../agent-chat.js\";\nimport { agentNativePath } from \"../api-path.js\";\nimport { useAppearance } from \"../appearance.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\nimport { useT } from \"../i18n.js\";\nimport {\n deleteOrHideExtension,\n invalidateExtensionRemoval,\n} from \"./delete-extension.js\";\nimport {\n extensionLoadError,\n extensionLoadErrorStatus,\n shouldRetryExtensionLoad,\n} from \"./extension-load-error.js\";\nimport {\n isAllowedExtensionPath,\n sanitizeExtensionRequestOptions,\n checkBridgePolicy,\n type BridgePolicyContext,\n type ExtensionBridgeRole,\n} from \"./iframe-bridge.js\";\nimport { normalizeAgentNativeExtensionSandbox } from \"./portable-extension.js\";\n\ninterface Extension {\n id: string;\n name: string;\n description?: string;\n content?: string;\n updatedAt?: string;\n canDelete?: boolean;\n source?: {\n mode?: \"database\" | \"local-files\";\n permissions?: BridgePolicyContext[\"permissions\"];\n };\n}\n\nconst EXTENSION_IFRAME_SANDBOX =\n normalizeAgentNativeExtensionSandbox(undefined);\n\n// Read the host app's *actual* computed theme values for the shared token set\n// (THEME_VAR_NAMES). The iframe ships with a generic baked palette\n// (getThemeVars); syncing the live values keeps embedded extensions visually\n// identical to the surrounding app even when a template overrides the default\n// palette (e.g. analytics uses a neutral-gray dark theme, not near-black).\nfunction readHostThemeVars(): Record<string, string> {\n if (typeof document === \"undefined\") return {};\n const computed = getComputedStyle(document.documentElement);\n const vars: Record<string, string> = {};\n for (const name of THEME_VAR_NAMES) {\n const value = computed.getPropertyValue(name).trim();\n if (value) vars[name] = value;\n }\n return vars;\n}\n\nfunction serializeChatValue(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\n/**\n * Slot contexts (e.g. Design's `DesignExtensionSlotContext`) commonly carry\n * live callback functions alongside plain data — the host component uses\n * those callbacks itself, but `window.postMessage` uses the structured clone\n * algorithm, which throws a `DataCloneError` on any function-valued property\n * (see MDN's postMessage docs). Round-tripping through JSON drops functions\n * (and other non-cloneable values like symbols) the same way\n * `JSON.stringify` already silently omits them, producing a payload that's\n * safe to post. Exported so a test can verify functions never reach the\n * iframe instead of only reading the code.\n */\nexport function sanitizeSlotContextForPostMessage(\n context: Record<string, unknown> | null | undefined,\n): Record<string, unknown> {\n try {\n return JSON.parse(JSON.stringify(context ?? {}));\n } catch {\n // Circular reference or other non-serializable shape — fail safe to an\n // empty context rather than letting postMessage throw and skip every\n // other message this handler sends in the same tick (theme update,\n // ready signal).\n return {};\n }\n}\n\nexport interface EmbeddedExtensionProps {\n extensionId: string;\n /** Slot identifier passed via the iframe URL so the extension runtime knows it's\n * embedded and enables auto-resize. */\n slotId: string;\n /** Object pushed into the extension as `window.slotContext`. Re-posted whenever\n * the host re-renders with a new context. */\n context?: Record<string, unknown> | null;\n /** Optional className applied to the iframe container. */\n className?: string;\n /** Initial iframe height before content reports a real height. */\n initialHeight?: number;\n /** Fires once when the embedded iframe first signals content readiness — its\n * first height report, or iframe load as a fallback. Hosts that gate on\n * content paint (e.g. dashboard report screenshots) use this. */\n onReady?: () => void;\n /** Fires when the extension can't be loaded for this viewer (e.g. 403/404 —\n * the extension isn't shared with them or no longer exists). Hosts can use\n * this to render an explanatory fallback instead of a blank panel. By default\n * the component renders nothing on failure (slot-style silent skip). */\n onUnavailable?: (status?: number) => void;\n}\n\n/**\n * Renders a extension inline as a small auto-sized iframe — for use inside an\n * `<ExtensionSlot>`. Different from `<ExtensionViewer>` (which is full-page with a\n * toolbar): no header, sized to content, receives a `slotContext`.\n */\nexport function EmbeddedExtension({\n extensionId,\n slotId,\n context,\n className,\n initialHeight = 80,\n onReady,\n onUnavailable,\n}: EmbeddedExtensionProps) {\n const iframeRef = useRef<HTMLIFrameElement | null>(null);\n // Latch the readiness signal so onReady fires at most once per iframe\n // instance. Reset when the iframe is recreated (extensionId/updatedAt change).\n const onReadyRef = useRef(onReady);\n onReadyRef.current = onReady;\n const readyFiredRef = useRef(false);\n const fireReady = () => {\n if (readyFiredRef.current) return;\n readyFiredRef.current = true;\n onReadyRef.current?.();\n };\n const [height, setHeight] = useState<number>(initialHeight);\n const [isDark, setIsDark] = useState(\n () =>\n typeof document !== \"undefined\" &&\n document.documentElement.classList.contains(\"dark\"),\n );\n // (audit H4) Mirror ExtensionViewer's role-aware gating; deny-by-default until\n // the iframe's render binding announcement arrives.\n const bridgeContextRef = useRef<BridgePolicyContext>({\n role: \"viewer\",\n isAuthor: false,\n });\n // (audit H4) Latch the render binding once per iframe instance. The shell\n // posts the server-resolved binding BEFORE user content runs; any later\n // agent-native-extension-binding message is attacker-controllable (it\n // originates inside the same sandboxed realm as user code) and must be\n // ignored so a viewer cannot self-escalate to owner.\n const bindingLatchedRef = useRef(false);\n const extensionRef = useRef(null as null | Extension);\n\n useEffect(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n const observer = new MutationObserver(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n });\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\"],\n });\n return () => observer.disconnect();\n }, []);\n\n const {\n data: extension,\n isFetching,\n isLoading,\n isError,\n error,\n } = useQuery<Extension>({\n queryKey: [\"extension\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n );\n if (res.status === 404) {\n throw extensionLoadError(404, \"Extension not found\");\n }\n if (res.status === 403) {\n throw extensionLoadError(403, \"Extension access denied\");\n }\n if (!res.ok) {\n throw extensionLoadError(res.status, \"Failed to fetch extension\");\n }\n return res.json();\n },\n retry: shouldRetryExtensionLoad,\n retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 4000),\n });\n extensionRef.current = extension ?? null;\n\n // Notify the host once when the extension can't be loaded for this viewer so\n // it can show a fallback instead of a blank panel.\n const onUnavailableRef = useRef(onUnavailable);\n onUnavailableRef.current = onUnavailable;\n const unavailableFiredRef = useRef(false);\n useEffect(() => {\n unavailableFiredRef.current = false;\n }, [extensionId]);\n useEffect(() => {\n if (isError && !isFetching && !unavailableFiredRef.current) {\n unavailableFiredRef.current = true;\n onUnavailableRef.current?.(extensionLoadErrorStatus(error));\n }\n }, [isError, isFetching, error]);\n\n // Initial dark state is baked into the URL on first load only; subsequent\n // theme toggles update the iframe's <html class=\"dark\"> via postMessage so\n // the user's interaction state inside the extension survives the toggle.\n const initialDarkRef = useRef(isDark);\n const iframeSrc = useMemo(() => {\n const v = encodeURIComponent(extension?.updatedAt ?? \"\");\n return agentNativePath(\n `/_agent-native/extensions/${extensionId}/render?slot=${encodeURIComponent(slotId)}&dark=${initialDarkRef.current}&v=${v}`,\n );\n }, [extensionId, slotId, extension?.updatedAt]);\n\n // Reset role + binding latch to deny-by-default whenever the iframe is\n // recreated (its key changes). The new render's first binding announcement\n // re-establishes the role.\n useEffect(() => {\n bridgeContextRef.current = { role: \"viewer\", isAuthor: false };\n bindingLatchedRef.current = false;\n readyFiredRef.current = false;\n }, [extensionId, extension?.updatedAt]);\n\n const appearance = useAppearance();\n\n useEffect(() => {\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n win.postMessage(\n { type: \"agent-native-theme-update\", isDark, vars: readHostThemeVars() },\n \"*\",\n );\n }, [isDark, appearance]);\n\n // Forward slot context whenever it changes. The iframe's own load handler\n // posts the initial value once it's ready; this effect handles updates.\n const contextJson = JSON.stringify(context ?? {});\n useEffect(() => {\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n // Post the JSON-round-tripped context, not the raw `context` object —\n // slot contexts (e.g. Design's DesignExtensionSlotContext) carry live\n // callback functions the host uses internally, and postMessage's\n // structured clone throws a DataCloneError on any function-valued\n // property. See sanitizeSlotContextForPostMessage's docblock.\n win.postMessage(\n {\n type: \"agent-native-slot-context\",\n context: sanitizeSlotContextForPostMessage(context),\n },\n \"*\",\n );\n }, [contextJson]);\n\n // Bridge extension requests + height reports.\n useEffect(() => {\n const handleMessage = async (event: MessageEvent) => {\n if (event.source !== iframeRef.current?.contentWindow) return;\n const message = event.data;\n if (!message || typeof message !== \"object\") return;\n\n if (message.type === \"agent-native-extension-binding\") {\n // Only the FIRST announcement (sent by the shell before user content\n // runs) is trusted. Ignore re-announcements — a malicious extension\n // body could otherwise postMessage a forged owner binding to escalate.\n if (bindingLatchedRef.current) return;\n bindingLatchedRef.current = true;\n const binding = (message as any).binding ?? {};\n const role: ExtensionBridgeRole =\n binding.role === \"owner\" ||\n binding.role === \"admin\" ||\n binding.role === \"editor\" ||\n binding.role === \"viewer\"\n ? binding.role\n : \"viewer\";\n bridgeContextRef.current = {\n role,\n isAuthor: !!binding.isAuthor,\n source: binding.source === \"local-files\" ? \"local-files\" : \"database\",\n permissions:\n binding && typeof binding.permissions === \"object\"\n ? binding.permissions\n : undefined,\n };\n return;\n }\n\n if (message.type === \"agent-native-extension-resize\") {\n const h = Number(message.height);\n if (Number.isFinite(h) && h > 0) {\n setHeight(Math.ceil(h));\n // First laid-out height means the content has painted.\n fireReady();\n }\n return;\n }\n\n if (message.type === \"agent-native-send-to-chat\") {\n const text = serializeChatValue((message as any).message);\n if (!text?.trim()) return;\n sendToAgentChat({\n message: text,\n context: serializeChatValue((message as any).context),\n submit: (message as any).submit !== false,\n openSidebar: (message as any).openSidebar !== false,\n });\n return;\n }\n\n if (message.type === \"agent-native-extension-error-fix\") {\n const name = extensionRef.current?.name ?? extensionId;\n const errors: string[] = Array.isArray((message as any).errors)\n ? (message as any).errors\n : [];\n const errorDetails: Array<{ message: string; stack: string }> =\n Array.isArray((message as any).errorDetails)\n ? (message as any).errorDetails\n : [];\n const consoleLogs: Array<{ level: string; message: string }> =\n Array.isArray((message as any).consoleLogs)\n ? (message as any).consoleLogs\n : [];\n const networkLogs: Array<{\n path: string;\n method: string;\n ok?: boolean;\n status?: number;\n error?: string;\n }> = Array.isArray((message as any).networkLogs)\n ? (message as any).networkLogs\n : [];\n\n const detailedTrace = errorDetails\n .filter((e) => e && typeof e === \"object\")\n .map((e) => {\n const msg =\n typeof e.message === \"string\" ? e.message : String(e.message);\n return typeof e.stack === \"string\" ? `${msg}\\n${e.stack}` : msg;\n })\n .join(\"\\n\\n\");\n\n // Force a fresh read from the server, same as ExtensionViewer's fix\n // flow — the query cache may hold the agent's previous (broken) turn.\n let freshContent: string | undefined;\n try {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n { cache: \"no-store\" },\n );\n if (res.ok) {\n const fresh = (await res.json()) as Extension;\n freshContent =\n typeof fresh?.content === \"string\" ? fresh.content : undefined;\n }\n } catch {\n // Fall through with no snapshot — agent can still re-read via get-extension.\n }\n\n const contextParts = [\n `The user is viewing a dashboard panel embedding extension \"${name}\" (id: ${extensionId}, slot: ${slotId}) and there are runtime errors that need fixing.`,\n `\\nFull error details:\\n${detailedTrace}`,\n ];\n\n if (consoleLogs.length > 0) {\n const consoleStr = consoleLogs\n .map((l) => `[${l.level}] ${l.message}`)\n .join(\"\\n\");\n contextParts.push(`\\nRecent console output:\\n${consoleStr}`);\n }\n\n if (networkLogs.length > 0) {\n const netStr = networkLogs\n .map(\n (l) =>\n `${l.method} ${l.path} → ${l.ok ? l.status : \"FAILED: \" + (l.error || l.status)}`,\n )\n .join(\"\\n\");\n contextParts.push(`\\nRecent network requests:\\n${netStr}`);\n }\n\n if (freshContent) {\n contextParts.push(\n `\\nCurrent extension content (just re-read from the database — this is the authoritative source, not anything you may have written in a previous turn):\\n\\`\\`\\`html\\n${freshContent}\\n\\`\\`\\``,\n );\n }\n\n sendToAgentChat({\n message: `Fix runtime errors in extension \"${name}\" (id: ${extensionId}), embedded as a dashboard panel. The content snapshot below was just re-read from the database — treat it as authoritative and ignore any prior version you may have generated in this chat. If in doubt, call get-extension first.\\n\\nErrors:\\n${errors.join(\"\\n\")}`,\n context: contextParts.join(\"\\n\"),\n submit: true,\n openSidebar: true,\n });\n return;\n }\n\n if (message.type !== \"agent-native-extension-request\") return;\n\n const requestId = String(message.requestId ?? \"\");\n const path = String(message.path ?? \"\");\n const respond = (payload: Record<string, unknown>) => {\n iframeRef.current?.contentWindow?.postMessage(\n { type: \"agent-native-extension-response\", requestId, ...payload },\n \"*\",\n );\n };\n\n if (!requestId || !isAllowedExtensionPath(path, extensionId)) {\n respond({ error: \"Extension request path is not allowed\" });\n return;\n }\n\n try {\n const options = sanitizeExtensionRequestOptions(message.options);\n // (audit H4) Role-aware gating: viewer-shared extensions can read but not\n // write. The bridge policy is decided here in the parent before the\n // request leaves; the server enforces a second layer.\n const policy = checkBridgePolicy(path, options.method ?? \"GET\", {\n ...bridgeContextRef.current,\n extensionId,\n });\n if (!policy.ok) {\n respond({\n response: {\n ok: false,\n status: 403,\n statusText: \"Forbidden\",\n body: { error: policy.error },\n },\n });\n return;\n }\n // (audit H5) Same extension-bridge tagging as <ExtensionViewer>. action-routes\n // uses these headers to enforce per-action `toolCallable` opt-in.\n const finalHeaders = new Headers(options.headers ?? undefined);\n finalHeaders.set(\"X-Agent-Native-Extension-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Extension-Id\", extensionId);\n finalHeaders.set(\"X-Agent-Native-Tool-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Tool-Id\", extensionId);\n const res = await fetch(agentNativePath(path), {\n ...options,\n headers: finalHeaders,\n credentials: \"same-origin\",\n });\n const text = await res.text();\n let body: unknown = text;\n if (text) {\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n }\n respond({\n response: {\n ok: res.ok,\n status: res.status,\n statusText: res.statusText,\n body,\n },\n });\n } catch (err: any) {\n respond({ error: err?.message ?? \"Extension host request failed\" });\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [extensionId, slotId]);\n\n if (!extension) {\n if (!isLoading && !isFetching) return null;\n return (\n <div\n className={className}\n style={{ height: initialHeight }}\n aria-busy=\"true\"\n />\n );\n }\n\n return (\n <div className={`relative group/embedded-extension ${className ?? \"\"}`}>\n <iframe\n {...{ [SESSION_REPLAY_IFRAME_ATTRIBUTE]: \"\" }}\n ref={iframeRef}\n key={`${extensionId}-${extension.updatedAt ?? \"\"}`}\n src={iframeSrc}\n title={extension.name}\n sandbox={EXTENSION_IFRAME_SANDBOX}\n style={{ width: \"100%\", border: 0, height, display: \"block\" }}\n onLoad={() => {\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: \"agent-native-slot-context\",\n context: sanitizeSlotContextForPostMessage(context),\n },\n \"*\",\n );\n // Re-assert theme once the iframe document is live. The src bakes in\n // the initial dark state, but this covers the race where isDark\n // settled before the iframe's message listener existed.\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: \"agent-native-theme-update\",\n isDark,\n vars: readHostThemeVars(),\n },\n \"*\",\n );\n // Fallback readiness signal in case the extension never reports a\n // height (e.g. fixed-height content that skips auto-resize).\n fireReady();\n }}\n />\n <EmbeddedToolMenu\n extensionId={extensionId}\n slotId={slotId}\n toolName={extension.name}\n canDelete={extension.canDelete}\n />\n </div>\n );\n}\n\nfunction EmbeddedToolMenu({\n extensionId,\n slotId,\n toolName,\n canDelete,\n}: {\n extensionId: string;\n slotId: string;\n toolName: string;\n canDelete?: boolean;\n}) {\n const t = useT();\n const [open, setOpen] = useState(false);\n const [confirmingDelete, setConfirmingDelete] = useState(false);\n const queryClient = useQueryClient();\n\n const closeMenu = () => {\n setOpen(false);\n setConfirmingDelete(false);\n };\n\n const removeFromSlot = async () => {\n closeMenu();\n queryClient.setQueryData<any[]>([\"slot-installs\", slotId], (old) =>\n (old ?? []).filter((i) => i.extensionId !== extensionId),\n );\n try {\n await fetch(\n agentNativePath(\n `/_agent-native/slots/${encodeURIComponent(slotId)}/install/${encodeURIComponent(extensionId)}`,\n ),\n { method: \"DELETE\" },\n );\n } finally {\n queryClient.invalidateQueries({ queryKey: [\"slot-installs\", slotId] });\n }\n };\n\n const deleteExtension = async () => {\n closeMenu();\n try {\n await deleteOrHideExtension({ id: extensionId, canDelete });\n invalidateExtensionRemoval(queryClient, extensionId);\n } catch {\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n }\n };\n\n return (\n <Popover\n open={open}\n onOpenChange={(o) => {\n setOpen(o);\n if (!o) setConfirmingDelete(false);\n }}\n >\n <TooltipProvider delayDuration={200}>\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"absolute top-1 right-1 flex h-6 w-6 items-center justify-center rounded-md bg-background/60 text-muted-foreground/60 opacity-0 hover:bg-accent hover:text-foreground hover:opacity-100 group-hover/embedded-extension:opacity-100 cursor-pointer transition-opacity\"\n aria-label={t(\"extensions.optionsFor\", { name: toolName })}\n >\n <IconDots className=\"h-3.5 w-3.5\" />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>\n {t(\"extensions.optionsFor\", { name: toolName })}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n <PopoverContent align=\"end\" sideOffset={4} className=\"w-56 p-1\">\n {!confirmingDelete ? (\n <div className=\"flex flex-col\">\n <Link\n to={extensionPath(extensionId, toolName)}\n onClick={closeMenu}\n className=\"flex items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] hover:bg-accent cursor-pointer text-left\"\n >\n <IconExternalLink className=\"h-3.5 w-3.5\" />\n <span>{t(\"extensions.openFullView\")}</span>\n </Link>\n <button\n type=\"button\"\n onClick={removeFromSlot}\n className=\"flex items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] hover:bg-accent cursor-pointer text-left\"\n >\n <IconLayoutSidebarRightCollapse className=\"h-3.5 w-3.5\" />\n <span>{t(\"extensions.removeFromWidgetArea\")}</span>\n </button>\n {canDelete !== false && (\n <>\n <div className=\"my-1 h-px bg-border/40\" />\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(true)}\n className=\"flex items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] text-destructive hover:bg-destructive/10 cursor-pointer text-left\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n <span>{t(\"extensions.deleteExtensionEllipsis\")}</span>\n </button>\n </>\n )}\n </div>\n ) : (\n <div className=\"flex flex-col gap-2 p-2\">\n <p className=\"text-[12px]\">\n {t(\"extensions.deleteQuestion\", { name: toolName })}{\" \"}\n {t(\"extensions.deleteEverywhereConfirmation\")}\n </p>\n <div className=\"flex justify-end gap-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(false)}\n className=\"rounded-md px-2 py-1 text-[12px] hover:bg-accent cursor-pointer\"\n >\n {t(\"extensions.cancel\")}\n </button>\n <button\n type=\"button\"\n onClick={deleteExtension}\n className=\"rounded-md bg-destructive px-2 py-1 text-[12px] text-destructive-foreground hover:bg-destructive/90 cursor-pointer\"\n >\n {t(\"extensions.delete\")}\n </button>\n </div>\n </div>\n )}\n </PopoverContent>\n </Popover>\n );\n}\n"]}
|
|
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
62
62
|
error: string;
|
|
63
63
|
states?: undefined;
|
|
64
64
|
} | {
|
|
65
|
-
error?: undefined;
|
|
66
65
|
states: {
|
|
67
66
|
clientId: number;
|
|
68
67
|
state: string;
|
|
69
68
|
}[];
|
|
69
|
+
error?: undefined;
|
|
70
70
|
}>>;
|
|
71
71
|
/**
|
|
72
72
|
* GET /_agent-native/collab/:docId/users
|
|
@@ -77,10 +77,10 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
|
|
|
77
77
|
error: string;
|
|
78
78
|
users?: undefined;
|
|
79
79
|
} | {
|
|
80
|
-
error?: undefined;
|
|
81
80
|
users: {
|
|
82
81
|
clientId: number;
|
|
83
82
|
lastSeen: number;
|
|
84
83
|
}[];
|
|
84
|
+
error?: undefined;
|
|
85
85
|
}>>;
|
|
86
86
|
//# sourceMappingURL=awareness.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"awareness.d.ts","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAgB3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAOD,eAAO,MAAM,sBAAsB,EAAG,kBAA2B,CAAC;AAElE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAOD,wBAAgB,mBAAmB,IAAI,YAAY,CAElD;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,cAAc,GAAG,SAAS,GAChC,IAAI,CAON;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,KAAK,CAAC,EAAE,cAAc,GACrB,IAAI,CAgBN;AAoBD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAmB,GAC7B,IAAI,CAON;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE1E;AAiBD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAO1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI,CAOnE;AAkCD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"awareness.d.ts","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAgB3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAOD,eAAO,MAAM,sBAAsB,EAAG,kBAA2B,CAAC;AAElE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAOD,wBAAgB,mBAAmB,IAAI,YAAY,CAElD;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,cAAc,GAAG,SAAS,GAChC,IAAI,CAON;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,KAAK,CAAC,EAAE,cAAc,GACrB,IAAI,CAgBN;AAoBD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAmB,GAC7B,IAAI,CAON;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE1E;AAiBD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAO1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI,CAOnE;AAkCD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;;;;;kBAwDa,MAAM;eAAS,MAAM;;;GAoB1D,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc;;;;;kBAYM,MAAM;kBAAY,MAAM;;;GAMvD,CAAC"}
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
|
|
14
14
|
*/
|
|
15
15
|
export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
ok?: undefined;
|
|
17
16
|
error: string;
|
|
17
|
+
ok?: undefined;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
package/dist/secrets/routes.d.ts
CHANGED
|
@@ -37,17 +37,17 @@ export declare function createWriteSecretHandler(): import("h3").EventHandlerWit
|
|
|
37
37
|
status?: undefined;
|
|
38
38
|
ok?: undefined;
|
|
39
39
|
} | {
|
|
40
|
-
error?: undefined;
|
|
41
40
|
ok: boolean;
|
|
42
41
|
status: string;
|
|
42
|
+
error?: undefined;
|
|
43
43
|
} | {
|
|
44
44
|
error: string;
|
|
45
45
|
removed?: undefined;
|
|
46
46
|
ok?: undefined;
|
|
47
47
|
} | {
|
|
48
|
-
error?: undefined;
|
|
49
48
|
ok: boolean;
|
|
50
49
|
removed: boolean;
|
|
50
|
+
error?: undefined;
|
|
51
51
|
}>>;
|
|
52
52
|
/**
|
|
53
53
|
* POST /_agent-native/secrets/:key/test — re-run the validator against the
|
|
@@ -58,13 +58,13 @@ export declare function createTestSecretHandler(): import("h3").EventHandlerWith
|
|
|
58
58
|
note?: undefined;
|
|
59
59
|
ok?: undefined;
|
|
60
60
|
} | {
|
|
61
|
-
error?: undefined;
|
|
62
61
|
ok: boolean;
|
|
63
62
|
note?: undefined;
|
|
64
|
-
} | {
|
|
65
63
|
error?: undefined;
|
|
64
|
+
} | {
|
|
66
65
|
ok: boolean;
|
|
67
66
|
note: string;
|
|
67
|
+
error?: undefined;
|
|
68
68
|
} | {
|
|
69
69
|
note?: undefined;
|
|
70
70
|
ok: boolean;
|
|
@@ -95,12 +95,12 @@ export interface AdHocSecretPayload {
|
|
|
95
95
|
export declare function createAdHocSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<AdHocSecretPayload[] | {
|
|
96
96
|
error: string;
|
|
97
97
|
} | {
|
|
98
|
-
error?: undefined;
|
|
99
98
|
ok: boolean;
|
|
100
99
|
key: string;
|
|
101
|
-
} | {
|
|
102
100
|
error?: undefined;
|
|
101
|
+
} | {
|
|
103
102
|
ok: boolean;
|
|
104
103
|
removed: boolean;
|
|
104
|
+
error?: undefined;
|
|
105
105
|
}>>;
|
|
106
106
|
//# sourceMappingURL=routes.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.114.
|
|
3
|
+
"version": "0.114.12",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -177,6 +177,7 @@ export function EmbeddedExtension({
|
|
|
177
177
|
// originates inside the same sandboxed realm as user code) and must be
|
|
178
178
|
// ignored so a viewer cannot self-escalate to owner.
|
|
179
179
|
const bindingLatchedRef = useRef(false);
|
|
180
|
+
const extensionRef = useRef(null as null | Extension);
|
|
180
181
|
|
|
181
182
|
useEffect(() => {
|
|
182
183
|
setIsDark(document.documentElement.classList.contains("dark"));
|
|
@@ -216,6 +217,7 @@ export function EmbeddedExtension({
|
|
|
216
217
|
retry: shouldRetryExtensionLoad,
|
|
217
218
|
retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 4000),
|
|
218
219
|
});
|
|
220
|
+
extensionRef.current = extension ?? null;
|
|
219
221
|
|
|
220
222
|
// Notify the host once when the extension can't be loaded for this viewer so
|
|
221
223
|
// it can show a fallback instead of a blank panel.
|
|
@@ -338,6 +340,92 @@ export function EmbeddedExtension({
|
|
|
338
340
|
return;
|
|
339
341
|
}
|
|
340
342
|
|
|
343
|
+
if (message.type === "agent-native-extension-error-fix") {
|
|
344
|
+
const name = extensionRef.current?.name ?? extensionId;
|
|
345
|
+
const errors: string[] = Array.isArray((message as any).errors)
|
|
346
|
+
? (message as any).errors
|
|
347
|
+
: [];
|
|
348
|
+
const errorDetails: Array<{ message: string; stack: string }> =
|
|
349
|
+
Array.isArray((message as any).errorDetails)
|
|
350
|
+
? (message as any).errorDetails
|
|
351
|
+
: [];
|
|
352
|
+
const consoleLogs: Array<{ level: string; message: string }> =
|
|
353
|
+
Array.isArray((message as any).consoleLogs)
|
|
354
|
+
? (message as any).consoleLogs
|
|
355
|
+
: [];
|
|
356
|
+
const networkLogs: Array<{
|
|
357
|
+
path: string;
|
|
358
|
+
method: string;
|
|
359
|
+
ok?: boolean;
|
|
360
|
+
status?: number;
|
|
361
|
+
error?: string;
|
|
362
|
+
}> = Array.isArray((message as any).networkLogs)
|
|
363
|
+
? (message as any).networkLogs
|
|
364
|
+
: [];
|
|
365
|
+
|
|
366
|
+
const detailedTrace = errorDetails
|
|
367
|
+
.filter((e) => e && typeof e === "object")
|
|
368
|
+
.map((e) => {
|
|
369
|
+
const msg =
|
|
370
|
+
typeof e.message === "string" ? e.message : String(e.message);
|
|
371
|
+
return typeof e.stack === "string" ? `${msg}\n${e.stack}` : msg;
|
|
372
|
+
})
|
|
373
|
+
.join("\n\n");
|
|
374
|
+
|
|
375
|
+
// Force a fresh read from the server, same as ExtensionViewer's fix
|
|
376
|
+
// flow — the query cache may hold the agent's previous (broken) turn.
|
|
377
|
+
let freshContent: string | undefined;
|
|
378
|
+
try {
|
|
379
|
+
const res = await fetch(
|
|
380
|
+
agentNativePath(`/_agent-native/extensions/${extensionId}`),
|
|
381
|
+
{ cache: "no-store" },
|
|
382
|
+
);
|
|
383
|
+
if (res.ok) {
|
|
384
|
+
const fresh = (await res.json()) as Extension;
|
|
385
|
+
freshContent =
|
|
386
|
+
typeof fresh?.content === "string" ? fresh.content : undefined;
|
|
387
|
+
}
|
|
388
|
+
} catch {
|
|
389
|
+
// Fall through with no snapshot — agent can still re-read via get-extension.
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const contextParts = [
|
|
393
|
+
`The user is viewing a dashboard panel embedding extension "${name}" (id: ${extensionId}, slot: ${slotId}) and there are runtime errors that need fixing.`,
|
|
394
|
+
`\nFull error details:\n${detailedTrace}`,
|
|
395
|
+
];
|
|
396
|
+
|
|
397
|
+
if (consoleLogs.length > 0) {
|
|
398
|
+
const consoleStr = consoleLogs
|
|
399
|
+
.map((l) => `[${l.level}] ${l.message}`)
|
|
400
|
+
.join("\n");
|
|
401
|
+
contextParts.push(`\nRecent console output:\n${consoleStr}`);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (networkLogs.length > 0) {
|
|
405
|
+
const netStr = networkLogs
|
|
406
|
+
.map(
|
|
407
|
+
(l) =>
|
|
408
|
+
`${l.method} ${l.path} → ${l.ok ? l.status : "FAILED: " + (l.error || l.status)}`,
|
|
409
|
+
)
|
|
410
|
+
.join("\n");
|
|
411
|
+
contextParts.push(`\nRecent network requests:\n${netStr}`);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (freshContent) {
|
|
415
|
+
contextParts.push(
|
|
416
|
+
`\nCurrent extension content (just re-read from the database — this is the authoritative source, not anything you may have written in a previous turn):\n\`\`\`html\n${freshContent}\n\`\`\``,
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
sendToAgentChat({
|
|
421
|
+
message: `Fix runtime errors in extension "${name}" (id: ${extensionId}), embedded as a dashboard panel. The content snapshot below was just re-read from the database — treat it as authoritative and ignore any prior version you may have generated in this chat. If in doubt, call get-extension first.\n\nErrors:\n${errors.join("\n")}`,
|
|
422
|
+
context: contextParts.join("\n"),
|
|
423
|
+
submit: true,
|
|
424
|
+
openSidebar: true,
|
|
425
|
+
});
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
|
|
341
429
|
if (message.type !== "agent-native-extension-request") return;
|
|
342
430
|
|
|
343
431
|
const requestId = String(message.requestId ?? "");
|
|
@@ -410,7 +498,7 @@ export function EmbeddedExtension({
|
|
|
410
498
|
|
|
411
499
|
window.addEventListener("message", handleMessage);
|
|
412
500
|
return () => window.removeEventListener("message", handleMessage);
|
|
413
|
-
}, [extensionId]);
|
|
501
|
+
}, [extensionId, slotId]);
|
|
414
502
|
|
|
415
503
|
if (!extension) {
|
|
416
504
|
if (!isLoading && !isFetching) return null;
|