@agent-native/core 0.78.8 → 0.79.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +25 -0
  3. package/corpus/core/docs/content/actions.md +4 -2
  4. package/corpus/core/docs/content/agent-surfaces.md +9 -0
  5. package/corpus/core/docs/content/extensions.md +10 -0
  6. package/corpus/core/docs/content/generative-ui.md +217 -0
  7. package/corpus/core/docs/content/key-concepts.md +2 -2
  8. package/corpus/core/docs/content/mcp-apps.md +3 -5
  9. package/corpus/core/docs/content/native-chat-ui.md +9 -5
  10. package/corpus/core/docs/content/tracking.md +9 -3
  11. package/corpus/core/package.json +1 -1
  12. package/corpus/core/src/action-ui.ts +1 -0
  13. package/corpus/core/src/client/analytics.ts +195 -12
  14. package/corpus/core/src/client/chat/index.ts +1 -0
  15. package/corpus/core/src/client/chat/tool-call-display.tsx +5 -2
  16. package/corpus/core/src/client/chat/widgets/InlineExtensionWidget.tsx +139 -0
  17. package/corpus/core/src/client/chat/widgets/builtin-tool-renderers.tsx +27 -1
  18. package/corpus/core/src/client/conversation/AgentConversation.tsx +38 -0
  19. package/corpus/core/src/client/conversation/code-agent-transcript.ts +9 -0
  20. package/corpus/core/src/client/conversation/types.ts +4 -0
  21. package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +27 -5
  22. package/corpus/core/src/client/extensions/ExtensionViewer.tsx +26 -5
  23. package/corpus/core/src/client/extensions/InlineExtensionFrame.tsx +654 -0
  24. package/corpus/core/src/client/extensions/iframe-bridge.ts +30 -0
  25. package/corpus/core/src/client/extensions/index.ts +5 -0
  26. package/corpus/core/src/client/index.ts +1 -0
  27. package/corpus/core/src/client/session-replay.ts +89 -14
  28. package/corpus/core/src/code-agents/transcript-normalizer.ts +14 -0
  29. package/corpus/core/src/extensions/actions.ts +218 -1
  30. package/corpus/core/src/extensions/html-shell.ts +70 -3
  31. package/corpus/core/src/extensions/routes.ts +12 -4
  32. package/corpus/core/src/index.browser.ts +1 -0
  33. package/corpus/core/src/index.ts +1 -0
  34. package/corpus/core/src/mcp/build-server.ts +1 -1
  35. package/corpus/core/src/mcp/embed-app.ts +11 -1
  36. package/corpus/core/src/server/agent-chat-plugin.ts +21 -9
  37. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +13 -0
  38. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/references/api.md +2 -0
  39. package/corpus/core/src/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +115 -0
  40. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +198 -59
  41. package/corpus/templates/analytics/AGENTS.md +12 -0
  42. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +1105 -0
  43. package/corpus/templates/analytics/actions/dashboard-panel-order.ts +169 -0
  44. package/corpus/templates/analytics/actions/get-sql-dashboard.ts +89 -6
  45. package/corpus/templates/analytics/actions/mutate-dashboard.ts +333 -0
  46. package/corpus/templates/analytics/actions/reorder-dashboard-panels.ts +214 -0
  47. package/corpus/templates/analytics/actions/send-dashboard-report-now.ts +48 -21
  48. package/corpus/templates/analytics/actions/update-dashboard.ts +193 -100
  49. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +11 -0
  50. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +1 -1
  51. package/corpus/templates/analytics/app/global.css +81 -10
  52. package/corpus/templates/analytics/app/i18n-data.ts +249 -4
  53. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/ChartCard.tsx +3 -3
  54. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +41 -1
  55. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/EmailReportDialog.tsx +1 -1
  56. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +4 -4
  57. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +48 -18
  58. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-layout.ts +32 -0
  59. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +204 -70
  60. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +1101 -227
  61. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +160 -133
  62. package/corpus/templates/analytics/changelog/2026-06-26-agents-can-now-edit-dashboards-through-a-typed-mutation-scri.md +6 -0
  63. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-bar-chart-hovers-stay-subtle-in-dark-mode.md +6 -0
  64. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-chart-moves-are-now-handled-by-panel-id-making-sim.md +6 -0
  65. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-charts-drag-smoothly-with-stable-cards-inactive-ch.md +6 -0
  66. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-charts-show-a-refresh-spinner-while-keeping-existi.md +6 -0
  67. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-edits-stay-stable-while-chart-order-and-deletions-.md +6 -0
  68. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-email-reports-queue-immediate-sends.md +6 -0
  69. package/corpus/templates/analytics/changelog/2026-06-26-explorer-dashboards-now-drag-charts-with-a-stable-preview-an.md +6 -0
  70. package/corpus/templates/analytics/changelog/2026-06-26-session-replay-playback-can-now-be-toggled-by-clicking-the-r.md +6 -0
  71. package/corpus/templates/analytics/changelog/2026-06-26-session-replays-now-open-from-the-full-row-and-play-with-tim.md +6 -0
  72. package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +21 -0
  73. package/corpus/templates/analytics/server/lib/dashboard-report.ts +41 -17
  74. package/corpus/templates/analytics/server/plugins/agent-chat.ts +5 -0
  75. package/dist/action-ui.d.ts +1 -0
  76. package/dist/action-ui.d.ts.map +1 -1
  77. package/dist/action-ui.js +1 -0
  78. package/dist/action-ui.js.map +1 -1
  79. package/dist/client/analytics.d.ts.map +1 -1
  80. package/dist/client/analytics.js +173 -12
  81. package/dist/client/analytics.js.map +1 -1
  82. package/dist/client/chat/index.d.ts +1 -1
  83. package/dist/client/chat/index.d.ts.map +1 -1
  84. package/dist/client/chat/index.js +1 -1
  85. package/dist/client/chat/index.js.map +1 -1
  86. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  87. package/dist/client/chat/tool-call-display.js +3 -1
  88. package/dist/client/chat/tool-call-display.js.map +1 -1
  89. package/dist/client/chat/widgets/InlineExtensionWidget.d.ts +17 -0
  90. package/dist/client/chat/widgets/InlineExtensionWidget.d.ts.map +1 -0
  91. package/dist/client/chat/widgets/InlineExtensionWidget.js +85 -0
  92. package/dist/client/chat/widgets/InlineExtensionWidget.js.map +1 -0
  93. package/dist/client/chat/widgets/builtin-tool-renderers.d.ts.map +1 -1
  94. package/dist/client/chat/widgets/builtin-tool-renderers.js +15 -2
  95. package/dist/client/chat/widgets/builtin-tool-renderers.js.map +1 -1
  96. package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
  97. package/dist/client/conversation/AgentConversation.js +33 -0
  98. package/dist/client/conversation/AgentConversation.js.map +1 -1
  99. package/dist/client/conversation/code-agent-transcript.js +8 -0
  100. package/dist/client/conversation/code-agent-transcript.js.map +1 -1
  101. package/dist/client/conversation/types.d.ts +4 -0
  102. package/dist/client/conversation/types.d.ts.map +1 -1
  103. package/dist/client/conversation/types.js.map +1 -1
  104. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
  105. package/dist/client/extensions/EmbeddedExtension.js +29 -1
  106. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  107. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  108. package/dist/client/extensions/ExtensionViewer.js +28 -1
  109. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  110. package/dist/client/extensions/InlineExtensionFrame.d.ts +25 -0
  111. package/dist/client/extensions/InlineExtensionFrame.d.ts.map +1 -0
  112. package/dist/client/extensions/InlineExtensionFrame.js +488 -0
  113. package/dist/client/extensions/InlineExtensionFrame.js.map +1 -0
  114. package/dist/client/extensions/iframe-bridge.d.ts +2 -0
  115. package/dist/client/extensions/iframe-bridge.d.ts.map +1 -1
  116. package/dist/client/extensions/iframe-bridge.js +23 -0
  117. package/dist/client/extensions/iframe-bridge.js.map +1 -1
  118. package/dist/client/extensions/index.d.ts +1 -0
  119. package/dist/client/extensions/index.d.ts.map +1 -1
  120. package/dist/client/extensions/index.js +1 -0
  121. package/dist/client/extensions/index.js.map +1 -1
  122. package/dist/client/index.d.ts +1 -1
  123. package/dist/client/index.d.ts.map +1 -1
  124. package/dist/client/index.js +1 -1
  125. package/dist/client/index.js.map +1 -1
  126. package/dist/client/session-replay.d.ts +11 -1
  127. package/dist/client/session-replay.d.ts.map +1 -1
  128. package/dist/client/session-replay.js +74 -14
  129. package/dist/client/session-replay.js.map +1 -1
  130. package/dist/code-agents/transcript-normalizer.d.ts +2 -0
  131. package/dist/code-agents/transcript-normalizer.d.ts.map +1 -1
  132. package/dist/code-agents/transcript-normalizer.js +8 -0
  133. package/dist/code-agents/transcript-normalizer.js.map +1 -1
  134. package/dist/collab/awareness.d.ts +2 -2
  135. package/dist/collab/awareness.d.ts.map +1 -1
  136. package/dist/collab/routes.d.ts +2 -2
  137. package/dist/extensions/actions.d.ts.map +1 -1
  138. package/dist/extensions/actions.js +200 -1
  139. package/dist/extensions/actions.js.map +1 -1
  140. package/dist/extensions/html-shell.d.ts.map +1 -1
  141. package/dist/extensions/html-shell.js +70 -3
  142. package/dist/extensions/html-shell.js.map +1 -1
  143. package/dist/extensions/routes.d.ts.map +1 -1
  144. package/dist/extensions/routes.js +11 -4
  145. package/dist/extensions/routes.js.map +1 -1
  146. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  147. package/dist/index.browser.d.ts +1 -1
  148. package/dist/index.browser.d.ts.map +1 -1
  149. package/dist/index.browser.js +1 -1
  150. package/dist/index.browser.js.map +1 -1
  151. package/dist/index.d.ts +1 -1
  152. package/dist/index.d.ts.map +1 -1
  153. package/dist/index.js +1 -1
  154. package/dist/index.js.map +1 -1
  155. package/dist/mcp/build-server.js +1 -1
  156. package/dist/mcp/build-server.js.map +1 -1
  157. package/dist/mcp/embed-app.d.ts.map +1 -1
  158. package/dist/mcp/embed-app.js +11 -1
  159. package/dist/mcp/embed-app.js.map +1 -1
  160. package/dist/observability/routes.d.ts +7 -7
  161. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  162. package/dist/resources/handlers.d.ts +2 -2
  163. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  164. package/dist/server/agent-chat-plugin.js +21 -9
  165. package/dist/server/agent-chat-plugin.js.map +1 -1
  166. package/dist/server/agent-engine-api-key-route.d.ts +2 -2
  167. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +13 -0
  168. package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +2 -0
  169. package/dist/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +115 -0
  170. package/docs/content/actions.md +4 -2
  171. package/docs/content/agent-surfaces.md +9 -0
  172. package/docs/content/extensions.md +10 -0
  173. package/docs/content/generative-ui.md +217 -0
  174. package/docs/content/key-concepts.md +2 -2
  175. package/docs/content/mcp-apps.md +3 -5
  176. package/docs/content/native-chat-ui.md +9 -5
  177. package/docs/content/tracking.md +9 -3
  178. package/package.json +1 -1
  179. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +13 -0
  180. package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +2 -0
  181. package/src/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +115 -0
@@ -0,0 +1,488 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useRef, useState } from "react";
3
+ import { buildExtensionHtml } from "../../extensions/html-shell.js";
4
+ import { getThemeVars } from "../../extensions/theme.js";
5
+ import { sendToAgentChat } from "../agent-chat.js";
6
+ import { agentNativePath } from "../api-path.js";
7
+ import { isAllowedExtensionPath, sanitizeExtensionRequestOptions, checkBridgePolicy, } from "./iframe-bridge.js";
8
+ const THEME_CSS_VARS = [
9
+ "--background",
10
+ "--foreground",
11
+ "--card",
12
+ "--card-foreground",
13
+ "--popover",
14
+ "--popover-foreground",
15
+ "--primary",
16
+ "--primary-foreground",
17
+ "--secondary",
18
+ "--secondary-foreground",
19
+ "--muted",
20
+ "--muted-foreground",
21
+ "--accent",
22
+ "--accent-foreground",
23
+ "--destructive",
24
+ "--destructive-foreground",
25
+ "--border",
26
+ "--input",
27
+ "--ring",
28
+ "--radius",
29
+ "--sidebar-background",
30
+ "--sidebar-foreground",
31
+ "--sidebar-primary",
32
+ "--sidebar-primary-foreground",
33
+ "--sidebar-accent",
34
+ "--sidebar-accent-foreground",
35
+ "--sidebar-border",
36
+ "--sidebar-ring",
37
+ ];
38
+ function getParentThemeVars() {
39
+ if (typeof document === "undefined")
40
+ return {};
41
+ const computed = getComputedStyle(document.documentElement);
42
+ const vars = {};
43
+ for (const name of THEME_CSS_VARS) {
44
+ const val = computed.getPropertyValue(name).trim();
45
+ if (val)
46
+ vars[name] = val;
47
+ }
48
+ return vars;
49
+ }
50
+ function normalizeRole(value) {
51
+ return value === "owner" ||
52
+ value === "admin" ||
53
+ value === "editor" ||
54
+ value === "viewer"
55
+ ? value
56
+ : "viewer";
57
+ }
58
+ function serializeChatValue(value) {
59
+ if (value === undefined || value === null)
60
+ return undefined;
61
+ if (typeof value === "string")
62
+ return value;
63
+ try {
64
+ return JSON.stringify(value);
65
+ }
66
+ catch {
67
+ return String(value);
68
+ }
69
+ }
70
+ function transientDataKey(extensionId, collection, scope) {
71
+ return `agent-native:inline-extension-data:${extensionId}:${scope}:${collection}`;
72
+ }
73
+ function readTransientRows(extensionId, collection, scope) {
74
+ if (typeof localStorage === "undefined")
75
+ return [];
76
+ try {
77
+ const parsed = JSON.parse(localStorage.getItem(transientDataKey(extensionId, collection, scope)) ??
78
+ "[]");
79
+ return Array.isArray(parsed) ? parsed : [];
80
+ }
81
+ catch {
82
+ return [];
83
+ }
84
+ }
85
+ function writeTransientRows(extensionId, collection, scope, rows) {
86
+ if (typeof localStorage === "undefined")
87
+ return;
88
+ localStorage.setItem(transientDataKey(extensionId, collection, scope), JSON.stringify(rows));
89
+ }
90
+ function parseTransientDataPath(extensionId, path) {
91
+ try {
92
+ const url = new URL(path, "http://agent-native.local");
93
+ const parts = url.pathname.split("/");
94
+ if (parts.length < 6 ||
95
+ parts.length > 7 ||
96
+ parts[1] !== "_agent-native" ||
97
+ parts[2] !== "extensions" ||
98
+ parts[3] !== "data" ||
99
+ decodeURIComponent(parts[4]) !== extensionId) {
100
+ return null;
101
+ }
102
+ return {
103
+ collection: decodeURIComponent(parts[5] ?? ""),
104
+ itemId: parts[6] ? decodeURIComponent(parts[6]) : undefined,
105
+ scope: url.searchParams.get("scope") || "user",
106
+ };
107
+ }
108
+ catch {
109
+ return null;
110
+ }
111
+ }
112
+ async function handleTransientExtensionData(extensionId, path, options) {
113
+ const parsed = parseTransientDataPath(extensionId, path);
114
+ if (!parsed?.collection)
115
+ return null;
116
+ const method = String(options.method ?? "GET").toUpperCase();
117
+ if (method === "GET" || method === "HEAD") {
118
+ const rows = readTransientRows(extensionId, parsed.collection, parsed.scope);
119
+ return {
120
+ response: {
121
+ ok: true,
122
+ status: 200,
123
+ statusText: "OK",
124
+ body: rows,
125
+ },
126
+ };
127
+ }
128
+ if (method === "POST") {
129
+ const bodyText = typeof options.body === "string" ? options.body : "{}";
130
+ let body;
131
+ try {
132
+ body = JSON.parse(bodyText);
133
+ }
134
+ catch {
135
+ body = {};
136
+ }
137
+ if (body.data === undefined) {
138
+ return {
139
+ response: {
140
+ ok: false,
141
+ status: 400,
142
+ statusText: "Bad Request",
143
+ body: { error: "data is required" },
144
+ },
145
+ };
146
+ }
147
+ const itemId = typeof body.id === "string" && body.id.trim()
148
+ ? body.id.trim()
149
+ : `item-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
150
+ const requestedScope = body.scope === "org" || parsed.scope === "org" ? "org" : "user";
151
+ const now = new Date().toISOString();
152
+ const rows = readTransientRows(extensionId, parsed.collection, requestedScope);
153
+ const existing = rows.find((row) => row.id === itemId);
154
+ const row = {
155
+ id: itemId,
156
+ extensionId,
157
+ toolId: extensionId,
158
+ collection: parsed.collection,
159
+ data: typeof body.data === "string" ? body.data : JSON.stringify(body.data),
160
+ ownerEmail: "",
161
+ scope: requestedScope,
162
+ orgId: requestedScope === "org" ? "inline" : null,
163
+ createdAt: existing?.createdAt ?? now,
164
+ updatedAt: now,
165
+ };
166
+ writeTransientRows(extensionId, parsed.collection, requestedScope, [
167
+ row,
168
+ ...rows.filter((item) => item.id !== itemId),
169
+ ]);
170
+ return {
171
+ response: {
172
+ ok: true,
173
+ status: 200,
174
+ statusText: "OK",
175
+ body: row,
176
+ },
177
+ };
178
+ }
179
+ if (method === "DELETE" && parsed.itemId) {
180
+ const rows = readTransientRows(extensionId, parsed.collection, parsed.scope);
181
+ writeTransientRows(extensionId, parsed.collection, parsed.scope, rows.filter((row) => row.id !== parsed.itemId));
182
+ return {
183
+ response: {
184
+ ok: true,
185
+ status: 200,
186
+ statusText: "OK",
187
+ body: { ok: true },
188
+ },
189
+ };
190
+ }
191
+ return {
192
+ response: {
193
+ ok: false,
194
+ status: 405,
195
+ statusText: "Method Not Allowed",
196
+ body: { error: "Unsupported transient extensionData request" },
197
+ },
198
+ };
199
+ }
200
+ function buildTransientSrcDoc(extension, isDark) {
201
+ return buildExtensionHtml(extension.content ?? "", getThemeVars(isDark), isDark, extension.id, {
202
+ authorEmail: "",
203
+ viewerEmail: "",
204
+ isAuthor: true,
205
+ role: "owner",
206
+ });
207
+ }
208
+ export function InlineExtensionFrame({ extensionId, extension: providedExtension, slotId = "agent-chat.inline", context, className, initialHeight = 260, }) {
209
+ const providedId = providedExtension?.id ?? extensionId ?? "";
210
+ const iframeRef = useRef(null);
211
+ const [height, setHeight] = useState(initialHeight);
212
+ const [isDark, setIsDark] = useState(() => typeof document === "undefined"
213
+ ? false
214
+ : document.documentElement.classList.contains("dark"));
215
+ const bridgeContextRef = useRef({
216
+ role: providedExtension?.content ? "owner" : "viewer",
217
+ isAuthor: !!providedExtension?.content,
218
+ });
219
+ const bindingLatchedRef = useRef(false);
220
+ const [fetchedExtension, setFetchedExtension] = useState(null);
221
+ const [isLoading, setIsLoading] = useState(false);
222
+ useEffect(() => {
223
+ if (typeof document === "undefined")
224
+ return;
225
+ setIsDark(document.documentElement.classList.contains("dark"));
226
+ const observer = new MutationObserver(() => {
227
+ setIsDark(document.documentElement.classList.contains("dark"));
228
+ });
229
+ observer.observe(document.documentElement, {
230
+ attributes: true,
231
+ attributeFilter: ["class"],
232
+ });
233
+ return () => observer.disconnect();
234
+ }, []);
235
+ useEffect(() => {
236
+ if (!providedId || providedExtension) {
237
+ setFetchedExtension(null);
238
+ setIsLoading(false);
239
+ return;
240
+ }
241
+ let cancelled = false;
242
+ setIsLoading(true);
243
+ fetch(agentNativePath(`/_agent-native/extensions/${providedId}`))
244
+ .then(async (res) => {
245
+ if (!res.ok)
246
+ return null;
247
+ return (await res.json());
248
+ })
249
+ .then((row) => {
250
+ if (!cancelled)
251
+ setFetchedExtension(row);
252
+ })
253
+ .catch(() => {
254
+ if (!cancelled)
255
+ setFetchedExtension(null);
256
+ })
257
+ .finally(() => {
258
+ if (!cancelled)
259
+ setIsLoading(false);
260
+ });
261
+ return () => {
262
+ cancelled = true;
263
+ };
264
+ }, [providedExtension, providedId]);
265
+ const extension = providedExtension ?? fetchedExtension ?? null;
266
+ const resolvedId = extension?.id ?? providedId;
267
+ const isTransient = extension?.mode === "transient" ||
268
+ (!!extension?.content && !extensionId && extension?.mode !== "persisted");
269
+ const initialDarkRef = useRef(isDark);
270
+ const iframeSrc = useMemo(() => {
271
+ if (!resolvedId || isTransient)
272
+ return undefined;
273
+ const v = encodeURIComponent(extension?.updatedAt ?? "");
274
+ return agentNativePath(`/_agent-native/extensions/${resolvedId}/render?slot=${encodeURIComponent(slotId)}&dark=${initialDarkRef.current}&v=${v}`);
275
+ }, [extension?.updatedAt, isTransient, resolvedId, slotId]);
276
+ const srcDoc = useMemo(() => {
277
+ if (!extension || !isTransient)
278
+ return undefined;
279
+ return buildTransientSrcDoc(extension, initialDarkRef.current);
280
+ }, [extension, isTransient]);
281
+ useEffect(() => {
282
+ bridgeContextRef.current = isTransient
283
+ ? { role: "owner", isAuthor: true }
284
+ : { role: "viewer", isAuthor: false };
285
+ bindingLatchedRef.current = false;
286
+ setHeight(initialHeight);
287
+ }, [initialHeight, isTransient, resolvedId, extension?.updatedAt]);
288
+ const sendThemeToIframe = () => {
289
+ const win = iframeRef.current?.contentWindow;
290
+ if (!win)
291
+ return;
292
+ win.postMessage({
293
+ type: "agent-native-theme-update",
294
+ isDark,
295
+ vars: getParentThemeVars(),
296
+ }, "*");
297
+ };
298
+ useEffect(() => {
299
+ sendThemeToIframe();
300
+ }, [isDark, srcDoc, iframeSrc]);
301
+ const contextJson = JSON.stringify(context ?? {});
302
+ const sendContextToIframe = () => {
303
+ const win = iframeRef.current?.contentWindow;
304
+ if (!win)
305
+ return;
306
+ win.postMessage({ type: "agent-native-slot-context", context: context ?? {} }, "*");
307
+ };
308
+ useEffect(() => {
309
+ sendContextToIframe();
310
+ }, [contextJson, srcDoc, iframeSrc]);
311
+ useEffect(() => {
312
+ const handleMessage = async (event) => {
313
+ if (event.source !== iframeRef.current?.contentWindow)
314
+ return;
315
+ const message = event.data;
316
+ if (!message || typeof message !== "object")
317
+ return;
318
+ if (message.type === "agent-native-extension-binding") {
319
+ if (bindingLatchedRef.current)
320
+ return;
321
+ bindingLatchedRef.current = true;
322
+ const binding = message.binding ?? {};
323
+ const role = normalizeRole(binding.role);
324
+ bridgeContextRef.current = {
325
+ role,
326
+ isAuthor: !!binding.isAuthor,
327
+ source: binding.source === "local-files" ? "local-files" : "database",
328
+ permissions: binding && typeof binding.permissions === "object"
329
+ ? binding.permissions
330
+ : undefined,
331
+ };
332
+ return;
333
+ }
334
+ if (message.type === "agent-native-extension-resize") {
335
+ const h = Number(message.height);
336
+ if (Number.isFinite(h) && h > 0) {
337
+ setHeight(Math.ceil(Math.min(Math.max(h, 96), 1000)));
338
+ }
339
+ return;
340
+ }
341
+ if (message.type === "agent-native-extension-keydown") {
342
+ document.dispatchEvent(new KeyboardEvent("keydown", {
343
+ key: message.key,
344
+ code: message.code,
345
+ metaKey: !!message.metaKey,
346
+ ctrlKey: !!message.ctrlKey,
347
+ shiftKey: !!message.shiftKey,
348
+ altKey: !!message.altKey,
349
+ bubbles: true,
350
+ cancelable: true,
351
+ }));
352
+ return;
353
+ }
354
+ if (message.type === "agent-native-send-to-chat") {
355
+ const text = serializeChatValue(message.message);
356
+ if (!text?.trim())
357
+ return;
358
+ sendToAgentChat({
359
+ message: text,
360
+ context: serializeChatValue(message.context),
361
+ submit: message.submit !== false,
362
+ openSidebar: message.openSidebar !== false,
363
+ });
364
+ return;
365
+ }
366
+ if (message.type === "agent-native-ui-output") {
367
+ window.dispatchEvent(new CustomEvent("agentNative.inlineUiOutput", {
368
+ detail: {
369
+ extensionId: resolvedId,
370
+ key: typeof message.key === "string"
371
+ ? message.key
372
+ : undefined,
373
+ value: message.value,
374
+ output: message.output,
375
+ },
376
+ }));
377
+ return;
378
+ }
379
+ if (message.type === "agent-native-extension-error-fix") {
380
+ const errors = Array.isArray(message.errors)
381
+ ? message.errors
382
+ : [];
383
+ sendToAgentChat({
384
+ message: `Fix runtime errors in the inline extension "${extension?.name ?? resolvedId}".\n\nErrors:\n${errors.join("\n")}`,
385
+ context: [
386
+ `The user is viewing an inline generated extension named "${extension?.name ?? resolvedId}".`,
387
+ isTransient
388
+ ? "This is a transient chat-only extension. Re-render it with render-inline-extension instead of update-extension."
389
+ : `This is saved as extension id ${resolvedId}. Use get-extension/update-extension for durable edits.`,
390
+ extension?.content
391
+ ? `\nCurrent inline content:\n\`\`\`html\n${extension.content}\n\`\`\``
392
+ : "",
393
+ ]
394
+ .filter(Boolean)
395
+ .join("\n"),
396
+ submit: true,
397
+ openSidebar: true,
398
+ });
399
+ return;
400
+ }
401
+ if (message.type !== "agent-native-extension-request")
402
+ return;
403
+ const requestId = String(message.requestId ?? "");
404
+ const path = String(message.path ?? "");
405
+ const respond = (payload) => {
406
+ iframeRef.current?.contentWindow?.postMessage({
407
+ type: "agent-native-extension-response",
408
+ requestId,
409
+ ...payload,
410
+ }, "*");
411
+ };
412
+ if (!requestId ||
413
+ !resolvedId ||
414
+ !isAllowedExtensionPath(path, resolvedId)) {
415
+ respond({ error: "Extension request path is not allowed" });
416
+ return;
417
+ }
418
+ try {
419
+ const options = sanitizeExtensionRequestOptions(message.options);
420
+ const policy = checkBridgePolicy(path, options.method ?? "GET", {
421
+ ...bridgeContextRef.current,
422
+ extensionId: resolvedId,
423
+ });
424
+ if (!policy.ok) {
425
+ respond({
426
+ response: {
427
+ ok: false,
428
+ status: 403,
429
+ statusText: "Forbidden",
430
+ body: { error: policy.error },
431
+ },
432
+ });
433
+ return;
434
+ }
435
+ if (isTransient) {
436
+ const localData = await handleTransientExtensionData(resolvedId, path, options);
437
+ if (localData) {
438
+ respond(localData);
439
+ return;
440
+ }
441
+ }
442
+ const finalHeaders = new Headers(options.headers ?? undefined);
443
+ finalHeaders.set("X-Agent-Native-Extension-Bridge", "1");
444
+ finalHeaders.set("X-Agent-Native-Extension-Id", resolvedId);
445
+ finalHeaders.set("X-Agent-Native-Tool-Bridge", "1");
446
+ finalHeaders.set("X-Agent-Native-Tool-Id", resolvedId);
447
+ const res = await fetch(agentNativePath(path), {
448
+ ...options,
449
+ headers: finalHeaders,
450
+ credentials: "same-origin",
451
+ });
452
+ const text = await res.text();
453
+ let body = text;
454
+ if (text) {
455
+ try {
456
+ body = JSON.parse(text);
457
+ }
458
+ catch {
459
+ body = text;
460
+ }
461
+ }
462
+ respond({
463
+ response: {
464
+ ok: res.ok,
465
+ status: res.status,
466
+ statusText: res.statusText,
467
+ body,
468
+ },
469
+ });
470
+ }
471
+ catch (err) {
472
+ respond({ error: err?.message ?? "Extension host request failed" });
473
+ }
474
+ };
475
+ window.addEventListener("message", handleMessage);
476
+ return () => window.removeEventListener("message", handleMessage);
477
+ }, [extension, isTransient, resolvedId]);
478
+ if (!extension) {
479
+ if (!isLoading)
480
+ return null;
481
+ return (_jsx("div", { className: className, style: { height: initialHeight }, "aria-busy": "true" }));
482
+ }
483
+ return (_jsx("div", { className: `relative ${className ?? ""}`, children: _jsx("iframe", { ref: iframeRef, src: iframeSrc, srcDoc: srcDoc, title: extension.name, sandbox: "allow-scripts allow-forms", style: { width: "100%", border: 0, height, display: "block" }, onLoad: () => {
484
+ sendThemeToIframe();
485
+ sendContextToIframe();
486
+ } }, `${resolvedId}-${extension.updatedAt ?? "inline"}-${isTransient ? "transient" : "persisted"}`) }));
487
+ }
488
+ //# sourceMappingURL=InlineExtensionFrame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InlineExtensionFrame.js","sourceRoot":"","sources":["../../../src/client/extensions/InlineExtensionFrame.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { buildExtensionHtml } from \"../../extensions/html-shell.js\";\nimport { getThemeVars } from \"../../extensions/theme.js\";\nimport { sendToAgentChat } from \"../agent-chat.js\";\nimport { agentNativePath } from \"../api-path.js\";\nimport {\n isAllowedExtensionPath,\n sanitizeExtensionRequestOptions,\n checkBridgePolicy,\n type BridgePolicyContext,\n type ExtensionBridgeRole,\n} from \"./iframe-bridge.js\";\n\nconst THEME_CSS_VARS = [\n \"--background\",\n \"--foreground\",\n \"--card\",\n \"--card-foreground\",\n \"--popover\",\n \"--popover-foreground\",\n \"--primary\",\n \"--primary-foreground\",\n \"--secondary\",\n \"--secondary-foreground\",\n \"--muted\",\n \"--muted-foreground\",\n \"--accent\",\n \"--accent-foreground\",\n \"--destructive\",\n \"--destructive-foreground\",\n \"--border\",\n \"--input\",\n \"--ring\",\n \"--radius\",\n \"--sidebar-background\",\n \"--sidebar-foreground\",\n \"--sidebar-primary\",\n \"--sidebar-primary-foreground\",\n \"--sidebar-accent\",\n \"--sidebar-accent-foreground\",\n \"--sidebar-border\",\n \"--sidebar-ring\",\n];\n\ninterface InlineExtensionSource {\n mode?: \"database\" | \"local-files\";\n permissions?: BridgePolicyContext[\"permissions\"];\n}\n\nexport interface InlineExtensionDefinition {\n id: string;\n name: string;\n description?: string;\n content?: string;\n updatedAt?: string;\n mode?: \"transient\" | \"persisted\";\n source?: InlineExtensionSource;\n}\n\nexport interface InlineExtensionFrameProps {\n extensionId?: string;\n extension?: InlineExtensionDefinition;\n slotId?: string;\n context?: Record<string, unknown> | null;\n className?: string;\n initialHeight?: number;\n}\n\nfunction getParentThemeVars(): 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_CSS_VARS) {\n const val = computed.getPropertyValue(name).trim();\n if (val) vars[name] = val;\n }\n return vars;\n}\n\nfunction normalizeRole(value: unknown): ExtensionBridgeRole {\n return value === \"owner\" ||\n value === \"admin\" ||\n value === \"editor\" ||\n value === \"viewer\"\n ? value\n : \"viewer\";\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\nfunction transientDataKey(\n extensionId: string,\n collection: string,\n scope: string,\n): string {\n return `agent-native:inline-extension-data:${extensionId}:${scope}:${collection}`;\n}\n\ninterface TransientDataRow {\n id: string;\n extensionId: string;\n toolId: string;\n collection: string;\n data: string;\n ownerEmail: string;\n scope: string;\n orgId: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nfunction readTransientRows(\n extensionId: string,\n collection: string,\n scope: string,\n): TransientDataRow[] {\n if (typeof localStorage === \"undefined\") return [];\n try {\n const parsed = JSON.parse(\n localStorage.getItem(transientDataKey(extensionId, collection, scope)) ??\n \"[]\",\n );\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\nfunction writeTransientRows(\n extensionId: string,\n collection: string,\n scope: string,\n rows: TransientDataRow[],\n): void {\n if (typeof localStorage === \"undefined\") return;\n localStorage.setItem(\n transientDataKey(extensionId, collection, scope),\n JSON.stringify(rows),\n );\n}\n\nfunction parseTransientDataPath(\n extensionId: string,\n path: string,\n): { collection: string; itemId?: string; scope: string } | null {\n try {\n const url = new URL(path, \"http://agent-native.local\");\n const parts = url.pathname.split(\"/\");\n if (\n parts.length < 6 ||\n parts.length > 7 ||\n parts[1] !== \"_agent-native\" ||\n parts[2] !== \"extensions\" ||\n parts[3] !== \"data\" ||\n decodeURIComponent(parts[4]) !== extensionId\n ) {\n return null;\n }\n return {\n collection: decodeURIComponent(parts[5] ?? \"\"),\n itemId: parts[6] ? decodeURIComponent(parts[6]) : undefined,\n scope: url.searchParams.get(\"scope\") || \"user\",\n };\n } catch {\n return null;\n }\n}\n\nasync function handleTransientExtensionData(\n extensionId: string,\n path: string,\n options: RequestInit,\n): Promise<Record<string, unknown> | null> {\n const parsed = parseTransientDataPath(extensionId, path);\n if (!parsed?.collection) return null;\n\n const method = String(options.method ?? \"GET\").toUpperCase();\n if (method === \"GET\" || method === \"HEAD\") {\n const rows = readTransientRows(\n extensionId,\n parsed.collection,\n parsed.scope,\n );\n return {\n response: {\n ok: true,\n status: 200,\n statusText: \"OK\",\n body: rows,\n },\n };\n }\n\n if (method === \"POST\") {\n const bodyText = typeof options.body === \"string\" ? options.body : \"{}\";\n let body: Record<string, unknown>;\n try {\n body = JSON.parse(bodyText);\n } catch {\n body = {};\n }\n if (body.data === undefined) {\n return {\n response: {\n ok: false,\n status: 400,\n statusText: \"Bad Request\",\n body: { error: \"data is required\" },\n },\n };\n }\n const itemId =\n typeof body.id === \"string\" && body.id.trim()\n ? body.id.trim()\n : `item-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n const requestedScope =\n body.scope === \"org\" || parsed.scope === \"org\" ? \"org\" : \"user\";\n const now = new Date().toISOString();\n const rows = readTransientRows(\n extensionId,\n parsed.collection,\n requestedScope,\n );\n const existing = rows.find((row) => row.id === itemId);\n const row: TransientDataRow = {\n id: itemId,\n extensionId,\n toolId: extensionId,\n collection: parsed.collection,\n data:\n typeof body.data === \"string\" ? body.data : JSON.stringify(body.data),\n ownerEmail: \"\",\n scope: requestedScope,\n orgId: requestedScope === \"org\" ? \"inline\" : null,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n };\n writeTransientRows(extensionId, parsed.collection, requestedScope, [\n row,\n ...rows.filter((item) => item.id !== itemId),\n ]);\n return {\n response: {\n ok: true,\n status: 200,\n statusText: \"OK\",\n body: row,\n },\n };\n }\n\n if (method === \"DELETE\" && parsed.itemId) {\n const rows = readTransientRows(\n extensionId,\n parsed.collection,\n parsed.scope,\n );\n writeTransientRows(\n extensionId,\n parsed.collection,\n parsed.scope,\n rows.filter((row) => row.id !== parsed.itemId),\n );\n return {\n response: {\n ok: true,\n status: 200,\n statusText: \"OK\",\n body: { ok: true },\n },\n };\n }\n\n return {\n response: {\n ok: false,\n status: 405,\n statusText: \"Method Not Allowed\",\n body: { error: \"Unsupported transient extensionData request\" },\n },\n };\n}\n\nfunction buildTransientSrcDoc(\n extension: InlineExtensionDefinition,\n isDark: boolean,\n): string {\n return buildExtensionHtml(\n extension.content ?? \"\",\n getThemeVars(isDark),\n isDark,\n extension.id,\n {\n authorEmail: \"\",\n viewerEmail: \"\",\n isAuthor: true,\n role: \"owner\",\n },\n );\n}\n\nexport function InlineExtensionFrame({\n extensionId,\n extension: providedExtension,\n slotId = \"agent-chat.inline\",\n context,\n className,\n initialHeight = 260,\n}: InlineExtensionFrameProps) {\n const providedId = providedExtension?.id ?? extensionId ?? \"\";\n const iframeRef = useRef<HTMLIFrameElement | null>(null);\n const [height, setHeight] = useState<number>(initialHeight);\n const [isDark, setIsDark] = useState(() =>\n typeof document === \"undefined\"\n ? false\n : document.documentElement.classList.contains(\"dark\"),\n );\n const bridgeContextRef = useRef<BridgePolicyContext>({\n role: providedExtension?.content ? \"owner\" : \"viewer\",\n isAuthor: !!providedExtension?.content,\n });\n const bindingLatchedRef = useRef(false);\n const [fetchedExtension, setFetchedExtension] =\n useState<InlineExtensionDefinition | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n useEffect(() => {\n if (typeof document === \"undefined\") return;\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 useEffect(() => {\n if (!providedId || providedExtension) {\n setFetchedExtension(null);\n setIsLoading(false);\n return;\n }\n let cancelled = false;\n setIsLoading(true);\n fetch(agentNativePath(`/_agent-native/extensions/${providedId}`))\n .then(async (res) => {\n if (!res.ok) return null;\n return (await res.json()) as InlineExtensionDefinition;\n })\n .then((row) => {\n if (!cancelled) setFetchedExtension(row);\n })\n .catch(() => {\n if (!cancelled) setFetchedExtension(null);\n })\n .finally(() => {\n if (!cancelled) setIsLoading(false);\n });\n return () => {\n cancelled = true;\n };\n }, [providedExtension, providedId]);\n\n const extension = providedExtension ?? fetchedExtension ?? null;\n const resolvedId = extension?.id ?? providedId;\n const isTransient =\n extension?.mode === \"transient\" ||\n (!!extension?.content && !extensionId && extension?.mode !== \"persisted\");\n\n const initialDarkRef = useRef(isDark);\n const iframeSrc = useMemo(() => {\n if (!resolvedId || isTransient) return undefined;\n const v = encodeURIComponent(extension?.updatedAt ?? \"\");\n return agentNativePath(\n `/_agent-native/extensions/${resolvedId}/render?slot=${encodeURIComponent(slotId)}&dark=${initialDarkRef.current}&v=${v}`,\n );\n }, [extension?.updatedAt, isTransient, resolvedId, slotId]);\n\n const srcDoc = useMemo(() => {\n if (!extension || !isTransient) return undefined;\n return buildTransientSrcDoc(extension, initialDarkRef.current);\n }, [extension, isTransient]);\n\n useEffect(() => {\n bridgeContextRef.current = isTransient\n ? { role: \"owner\", isAuthor: true }\n : { role: \"viewer\", isAuthor: false };\n bindingLatchedRef.current = false;\n setHeight(initialHeight);\n }, [initialHeight, isTransient, resolvedId, extension?.updatedAt]);\n\n const sendThemeToIframe = () => {\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n win.postMessage(\n {\n type: \"agent-native-theme-update\",\n isDark,\n vars: getParentThemeVars(),\n },\n \"*\",\n );\n };\n\n useEffect(() => {\n sendThemeToIframe();\n }, [isDark, srcDoc, iframeSrc]);\n\n const contextJson = JSON.stringify(context ?? {});\n const sendContextToIframe = () => {\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n win.postMessage(\n { type: \"agent-native-slot-context\", context: context ?? {} },\n \"*\",\n );\n };\n\n useEffect(() => {\n sendContextToIframe();\n }, [contextJson, srcDoc, iframeSrc]);\n\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 if (bindingLatchedRef.current) return;\n bindingLatchedRef.current = true;\n const binding = (message as any).binding ?? {};\n const role = normalizeRole(binding.role);\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 as any).height);\n if (Number.isFinite(h) && h > 0) {\n setHeight(Math.ceil(Math.min(Math.max(h, 96), 1000)));\n }\n return;\n }\n\n if (message.type === \"agent-native-extension-keydown\") {\n document.dispatchEvent(\n new KeyboardEvent(\"keydown\", {\n key: (message as any).key,\n code: (message as any).code,\n metaKey: !!(message as any).metaKey,\n ctrlKey: !!(message as any).ctrlKey,\n shiftKey: !!(message as any).shiftKey,\n altKey: !!(message as any).altKey,\n bubbles: true,\n cancelable: true,\n }),\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-ui-output\") {\n window.dispatchEvent(\n new CustomEvent(\"agentNative.inlineUiOutput\", {\n detail: {\n extensionId: resolvedId,\n key:\n typeof (message as any).key === \"string\"\n ? (message as any).key\n : undefined,\n value: (message as any).value,\n output: (message as any).output,\n },\n }),\n );\n return;\n }\n\n if (message.type === \"agent-native-extension-error-fix\") {\n const errors: string[] = Array.isArray((message as any).errors)\n ? (message as any).errors\n : [];\n sendToAgentChat({\n message: `Fix runtime errors in the inline extension \"${extension?.name ?? resolvedId}\".\\n\\nErrors:\\n${errors.join(\"\\n\")}`,\n context: [\n `The user is viewing an inline generated extension named \"${extension?.name ?? resolvedId}\".`,\n isTransient\n ? \"This is a transient chat-only extension. Re-render it with render-inline-extension instead of update-extension.\"\n : `This is saved as extension id ${resolvedId}. Use get-extension/update-extension for durable edits.`,\n extension?.content\n ? `\\nCurrent inline content:\\n\\`\\`\\`html\\n${extension.content}\\n\\`\\`\\``\n : \"\",\n ]\n .filter(Boolean)\n .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 as any).requestId ?? \"\");\n const path = String((message as any).path ?? \"\");\n const respond = (payload: Record<string, unknown>) => {\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: \"agent-native-extension-response\",\n requestId,\n ...payload,\n },\n \"*\",\n );\n };\n\n if (\n !requestId ||\n !resolvedId ||\n !isAllowedExtensionPath(path, resolvedId)\n ) {\n respond({ error: \"Extension request path is not allowed\" });\n return;\n }\n\n try {\n const options = sanitizeExtensionRequestOptions(\n (message as any).options,\n );\n const policy = checkBridgePolicy(path, options.method ?? \"GET\", {\n ...bridgeContextRef.current,\n extensionId: resolvedId,\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\n if (isTransient) {\n const localData = await handleTransientExtensionData(\n resolvedId,\n path,\n options,\n );\n if (localData) {\n respond(localData);\n return;\n }\n }\n\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\", resolvedId);\n finalHeaders.set(\"X-Agent-Native-Tool-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Tool-Id\", resolvedId);\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 }, [extension, isTransient, resolvedId]);\n\n if (!extension) {\n if (!isLoading) 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 ${className ?? \"\"}`}>\n <iframe\n ref={iframeRef}\n key={`${resolvedId}-${extension.updatedAt ?? \"inline\"}-${isTransient ? \"transient\" : \"persisted\"}`}\n src={iframeSrc}\n srcDoc={srcDoc}\n title={extension.name}\n sandbox=\"allow-scripts allow-forms\"\n style={{ width: \"100%\", border: 0, height, display: \"block\" }}\n onLoad={() => {\n sendThemeToIframe();\n sendContextToIframe();\n }}\n />\n </div>\n );\n}\n"]}
@@ -15,6 +15,8 @@ export declare function isAllowedExtensionPath(path: string, extensionId: string
15
15
  export declare function sanitizeExtensionRequestOptions(value: unknown): RequestInit;
16
16
  export type ExtensionBridgeRole = "owner" | "admin" | "editor" | "viewer";
17
17
  export interface BridgePolicyContext {
18
+ /** Extension id currently owning the iframe. Used for narrow helper-specific exceptions. */
19
+ extensionId?: string;
18
20
  /** Resolved role of the viewer on this extension. */
19
21
  role: ExtensionBridgeRole;
20
22
  /** True when viewer is the extension's owner_email — equivalent to role "owner"
@@ -1 +1 @@
1
- {"version":3,"file":"iframe-bridge.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/iframe-bridge.ts"],"names":[],"mappings":"AAgCA;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAuCT;AAED,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAiC3E;AAuCD,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAI1E,MAAM,WAAW,mBAAmB;IAClC,qDAAqD;IACrD,IAAI,EAAE,mBAAmB,CAAC;IAC1B;gEAC4D;IAC5D,QAAQ,EAAE,OAAO,CAAC;IAClB,2FAA2F;IAC3F,MAAM,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC;IACpC,WAAW,CAAC,EAAE;QACZ,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,GAAG,CAAC,EAAE,OAAO,CAAC;QACd,aAAa,CAAC,EAAE,OAAO,CAAC;KACzB,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,mBAAmB,GACvB,kBAAkB,CAkFpB"}
1
+ {"version":3,"file":"iframe-bridge.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/iframe-bridge.ts"],"names":[],"mappings":"AAgCA;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAuCT;AAED,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAiC3E;AAuCD,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAI1E,MAAM,WAAW,mBAAmB;IAClC,4FAA4F;IAC5F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,IAAI,EAAE,mBAAmB,CAAC;IAC1B;gEAC4D;IAC5D,QAAQ,EAAE,OAAO,CAAC;IAClB,2FAA2F;IAC3F,MAAM,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC;IACpC,WAAW,CAAC,EAAE;QACZ,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,GAAG,CAAC,EAAE,OAAO,CAAC;QACd,aAAa,CAAC,EAAE,OAAO,CAAC;KACzB,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,mBAAmB,GACvB,kBAAkB,CAwFpB"}
@@ -188,6 +188,10 @@ export function checkBridgePolicy(path, method, ctx) {
188
188
  if (path.startsWith("/_agent-native/application-state/")) {
189
189
  if (READ_METHODS.has(upperMethod))
190
190
  return { ok: true };
191
+ if (upperMethod === "PUT" &&
192
+ isInlineUiOutputApplicationStatePath(path, ctx.extensionId)) {
193
+ return { ok: true };
194
+ }
191
195
  return {
192
196
  ok: false,
193
197
  error: deniedMessage("appFetch (mutation)", ctx.role),
@@ -249,10 +253,29 @@ function checkLocalFileBridgePolicy(path, method, ctx) {
249
253
  if (path.startsWith("/_agent-native/application-state/")) {
250
254
  if (READ_METHODS.has(upperMethod))
251
255
  return { ok: true };
256
+ if (upperMethod === "PUT" &&
257
+ isInlineUiOutputApplicationStatePath(path, ctx.extensionId)) {
258
+ return { ok: true };
259
+ }
252
260
  return { ok: false, error: localDeniedMessage("applicationState") };
253
261
  }
254
262
  if (READ_METHODS.has(upperMethod))
255
263
  return { ok: true };
256
264
  return { ok: false, error: localDeniedMessage("appFetch") };
257
265
  }
266
+ function isInlineUiOutputApplicationStatePath(path, extensionId) {
267
+ if (!extensionId)
268
+ return false;
269
+ try {
270
+ const pathname = new URL(path, "http://agent-native.local").pathname;
271
+ const prefix = "/_agent-native/application-state/";
272
+ if (!pathname.startsWith(prefix))
273
+ return false;
274
+ const key = decodeURIComponent(pathname.slice(prefix.length));
275
+ return key === `inline-ui:${extensionId}:output`;
276
+ }
277
+ catch {
278
+ return false;
279
+ }
280
+ }
258
281
  //# sourceMappingURL=iframe-bridge.js.map