@noodleseed/assistant 1.25.0 → 1.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -4
- package/dist/{app-view-element-BM4lral-.d.ts → app-view-element-BNkQab1B.d.ts} +1 -2
- package/dist/{app-view-element-9ojWWYov.d.cts → app-view-element-DhuiNW_x.d.cts} +1 -2
- package/dist/app-view.cjs +36 -208
- package/dist/app-view.cjs.map +1 -1
- package/dist/app-view.d.cts +1 -1
- package/dist/app-view.d.ts +1 -1
- package/dist/app-view.js +2 -2
- package/dist/{chunk-LNBUYHL7.js → chunk-5TYS2Q6S.js} +2 -2
- package/dist/chunk-5TYS2Q6S.js.map +1 -0
- package/dist/{chunk-P32MAR4K.js → chunk-CF2SCDLF.js} +37 -209
- package/dist/chunk-CF2SCDLF.js.map +1 -0
- package/dist/{chunk-SGMECNNU.js → chunk-FJYPE4GC.js} +2 -2
- package/dist/embed.global.js +91 -124
- package/dist/index.cjs +58 -230
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/react.cjs +58 -230
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-LNBUYHL7.js.map +0 -1
- package/dist/chunk-P32MAR4K.js.map +0 -1
- /package/dist/{chunk-SGMECNNU.js.map → chunk-FJYPE4GC.js.map} +0 -0
package/dist/app-view.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as APP_VIEW_TAG_NAME, a as AssistantAppViewErrorDetail, N as NoodleAppViewElement } from './app-view-element-
|
|
1
|
+
export { A as APP_VIEW_TAG_NAME, a as AssistantAppViewErrorDetail, N as NoodleAppViewElement } from './app-view-element-DhuiNW_x.cjs';
|
|
2
2
|
export { A as AssistantClient, a as AssistantViewAvailableDetail } from './client-C07ppTU_.cjs';
|
|
3
3
|
import './appearance-B6vSg8Ub.cjs';
|
|
4
4
|
import 'ai';
|
package/dist/app-view.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as APP_VIEW_TAG_NAME, a as AssistantAppViewErrorDetail, N as NoodleAppViewElement } from './app-view-element-
|
|
1
|
+
export { A as APP_VIEW_TAG_NAME, a as AssistantAppViewErrorDetail, N as NoodleAppViewElement } from './app-view-element-BNkQab1B.js';
|
|
2
2
|
export { A as AssistantClient, a as AssistantViewAvailableDetail } from './client-BkogON2A.js';
|
|
3
3
|
import './appearance-B6vSg8Ub.js';
|
|
4
4
|
import 'ai';
|
package/dist/app-view.js
CHANGED
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
APP_VIEW_TAG_NAME,
|
|
3
3
|
NoodleAppViewElement,
|
|
4
4
|
registerNoodleAppView
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-5TYS2Q6S.js";
|
|
6
|
+
import "./chunk-CF2SCDLF.js";
|
|
7
7
|
import "./chunk-P223CYPO.js";
|
|
8
8
|
import "./chunk-3YYTUJPJ.js";
|
|
9
9
|
import "./chunk-5FUTL2UF.js";
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
mountAssistantApp,
|
|
4
4
|
unmountAssistantApp,
|
|
5
5
|
updateAssistantAppTheme
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-CF2SCDLF.js";
|
|
7
7
|
|
|
8
8
|
// src/app-view-element.ts
|
|
9
9
|
var APP_VIEW_TAG_NAME = "noodle-app-view";
|
|
@@ -177,4 +177,4 @@ export {
|
|
|
177
177
|
NoodleAppViewElement,
|
|
178
178
|
registerNoodleAppView
|
|
179
179
|
};
|
|
180
|
-
//# sourceMappingURL=chunk-
|
|
180
|
+
//# sourceMappingURL=chunk-5TYS2Q6S.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/app-view-element.ts","../src/app-view.ts"],"sourcesContent":["import { mountAssistantApp, unmountAssistantApp, updateAssistantAppTheme } from './app-host.js';\nimport { ASSISTANT_APP_VIEW_STYLES } from './app-view-styles.js';\nimport type { AssistantClient, AssistantViewAvailableDetail } from './client.js';\nimport type { AssistantErrorDetail } from './transport.js';\n\nexport const APP_VIEW_TAG_NAME = 'noodle-app-view';\n\nexport interface AssistantAppViewErrorDetail {\n readonly code: 'view_render_timeout';\n readonly retryable: false;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'noodle-app-view': NoodleAppViewElement;\n }\n\n interface HTMLElementEventMap {\n 'assistant-error': CustomEvent<AssistantErrorDetail>;\n }\n}\n\nconst HTMLElementBase: typeof HTMLElement =\n globalThis.HTMLElement ?? (class {} as unknown as typeof HTMLElement);\n\nfunction viewIdentity(view: AssistantViewAvailableDetail): string {\n return `${view.id}\\u0000${view.resourceUri}`;\n}\n\n/**\n * Framework-neutral host for one service-resolved MCP App view.\n *\n * `client` and `view` are object properties, not serialized attributes. Vue, Angular, and plain DOM\n * renderers can therefore pass the same `data-view` payload without taking a React dependency.\n */\nexport class NoodleAppViewElement extends HTMLElementBase {\n static readonly observedAttributes = ['allow-fullscreen', 'theme'];\n\n #allowFullscreen = false;\n #client: AssistantClient | undefined;\n #view: AssistantViewAvailableDetail | undefined;\n #theme: 'light' | 'dark' = 'light';\n #container: HTMLElement | undefined;\n #mounted: HTMLElement | undefined;\n #mountedClient: AssistantClient | undefined;\n #mountedAllowFullscreen = false;\n #mountedIdentity: string | undefined;\n #requestedTeardown: { readonly client: AssistantClient; readonly identity: string } | undefined;\n\n get client(): AssistantClient | undefined {\n return this.#client;\n }\n\n /** Allow the hosted App to request fullscreen. Disabled by default. */\n get allowFullscreen(): boolean {\n return this.#allowFullscreen;\n }\n\n set allowFullscreen(value: boolean) {\n const next = value === true;\n if (next === this.#allowFullscreen) return;\n this.#allowFullscreen = next;\n this.toggleAttribute('allow-fullscreen', next);\n this.#reconcile();\n }\n\n set client(value: AssistantClient | undefined) {\n if (value === this.#client) return;\n this.#client = value;\n this.#reconcile();\n }\n\n get view(): AssistantViewAvailableDetail | undefined {\n return this.#view;\n }\n\n set view(value: AssistantViewAvailableDetail | undefined) {\n this.#view = value;\n this.#reconcile();\n }\n\n get theme(): 'light' | 'dark' {\n return this.#theme;\n }\n\n set theme(value: 'light' | 'dark') {\n const next = value === 'dark' ? 'dark' : 'light';\n const changed = next !== this.#theme;\n this.#theme = next;\n if (this.getAttribute('data-theme') !== next) this.setAttribute('data-theme', next);\n if (changed && this.#mounted) updateAssistantAppTheme(this.#mounted, next);\n }\n\n connectedCallback(): void {\n this.#ensureContainer();\n this.#upgradeProperty('allowFullscreen');\n this.#upgradeProperty('client');\n this.#upgradeProperty('theme');\n this.#upgradeProperty('view');\n this.#reconcile();\n }\n\n disconnectedCallback(): void {\n this.#requestedTeardown = undefined;\n this.#releaseMount();\n }\n\n attributeChangedCallback(name: string, _previous: string | null, value: string | null): void {\n if (name === 'allow-fullscreen') this.allowFullscreen = value !== null;\n if (name === 'theme') this.theme = value === 'dark' ? 'dark' : 'light';\n }\n\n #ensureContainer(): HTMLElement {\n if (this.#container) return this.#container;\n const root = this.shadowRoot ?? this.attachShadow({ mode: 'open' });\n root.innerHTML = ASSISTANT_APP_VIEW_STYLES;\n const container = document.createElement('div');\n container.className = 'noodle-app-mount';\n container.setAttribute('part', 'mount');\n root.append(container);\n this.#container = container;\n return container;\n }\n\n #upgradeProperty(name: 'allowFullscreen' | 'client' | 'theme' | 'view'): void {\n const property = Object.getOwnPropertyDescriptor(this, name);\n if (!property) return;\n Reflect.deleteProperty(this, name);\n Reflect.set(this, name, property.value);\n }\n\n #releaseMount(): void {\n const mounted = this.#mounted;\n this.#mounted = undefined;\n this.#mountedClient = undefined;\n this.#mountedAllowFullscreen = false;\n this.#mountedIdentity = undefined;\n this.#container?.replaceChildren();\n if (mounted) void unmountAssistantApp(mounted);\n }\n\n #reconcile(): void {\n if (!this.isConnected) return;\n const client = this.#client;\n const detail = this.#view;\n const identity = detail ? viewIdentity(detail) : undefined;\n\n if (this.#mounted) {\n if (\n client === this.#mountedClient &&\n identity === this.#mountedIdentity &&\n this.#allowFullscreen === this.#mountedAllowFullscreen\n ) {\n return;\n }\n this.#releaseMount();\n }\n\n if (\n this.#requestedTeardown &&\n (client !== this.#requestedTeardown.client || identity !== this.#requestedTeardown.identity)\n ) {\n this.#requestedTeardown = undefined;\n }\n if (!client || !detail?.html || !identity || this.#requestedTeardown) return;\n\n const initialHtml = detail.html;\n const sandboxUrl = client.appSandboxUrl?.();\n let card: HTMLElement | undefined;\n card = mountAssistantApp(\n detail,\n {\n client,\n sendMessage: (message) => client.sendMessage(message),\n updateModelContext: (update) => client.updateModelContext(update),\n theme: this.#theme,\n },\n {\n allowFullscreen: this.#allowFullscreen,\n ...(sandboxUrl ? { sandboxUrl } : {}),\n getDetail: () => {\n const latest = this.#view;\n if (this.#client !== client || !latest || viewIdentity(latest) !== identity)\n return detail;\n return latest.html ? latest : { ...latest, html: initialHtml };\n },\n onRenderFailure: (failure) => {\n this.dispatchEvent(\n new CustomEvent<AssistantAppViewErrorDetail>('assistant-error', {\n detail: failure,\n bubbles: true,\n composed: true,\n }),\n );\n },\n onTeardownRequest: () => {\n if (this.#mounted !== card) return;\n this.#mounted = undefined;\n this.#mountedClient = undefined;\n this.#mountedIdentity = undefined;\n this.#requestedTeardown = { client, identity };\n },\n },\n );\n if (!card) return;\n this.#mounted = card;\n this.#mountedClient = client;\n this.#mountedAllowFullscreen = this.#allowFullscreen;\n this.#mountedIdentity = identity;\n this.#ensureContainer().replaceChildren(card);\n }\n}\n","import { APP_VIEW_TAG_NAME, NoodleAppViewElement } from './app-view-element.js';\n\nexport {\n APP_VIEW_TAG_NAME,\n type AssistantAppViewErrorDetail,\n NoodleAppViewElement,\n} from './app-view-element.js';\nexport type { AssistantClient, AssistantViewAvailableDetail } from './client.js';\n\n/** Register the framework-neutral MCP App host. Safe to call more than once or during SSR. */\nexport function registerNoodleAppView(): void {\n if (!globalThis.customElements?.get(APP_VIEW_TAG_NAME)) {\n globalThis.customElements?.define(APP_VIEW_TAG_NAME, NoodleAppViewElement);\n }\n}\n\nregisterNoodleAppView();\n"],"mappings":"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","names":[]}
|
|
@@ -2744,15 +2744,6 @@ var E = class {
|
|
|
2744
2744
|
sessionId;
|
|
2745
2745
|
setProtocolVersion;
|
|
2746
2746
|
};
|
|
2747
|
-
function AZ(X) {
|
|
2748
|
-
if (!X) return "";
|
|
2749
|
-
let Y = [];
|
|
2750
|
-
if (X.camera) Y.push("camera");
|
|
2751
|
-
if (X.microphone) Y.push("microphone");
|
|
2752
|
-
if (X.geolocation) Y.push("geolocation");
|
|
2753
|
-
if (X.clipboardWrite) Y.push("clipboard-write");
|
|
2754
|
-
return Y.join("; ");
|
|
2755
|
-
}
|
|
2756
2747
|
var KX = [j];
|
|
2757
2748
|
var DX = class extends _ {
|
|
2758
2749
|
_client;
|
|
@@ -3023,131 +3014,34 @@ function GX(X, Y) {
|
|
|
3023
3014
|
return JSON.stringify(X) === JSON.stringify(Y);
|
|
3024
3015
|
}
|
|
3025
3016
|
|
|
3026
|
-
// src/app-sandbox-policy.ts
|
|
3027
|
-
var MAX_DOMAINS_PER_DIRECTIVE = 32;
|
|
3028
|
-
function isRecord(value) {
|
|
3029
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3030
|
-
}
|
|
3031
|
-
function isLoopback(hostname) {
|
|
3032
|
-
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]";
|
|
3033
|
-
}
|
|
3034
|
-
function normalizeDomain(value, connect) {
|
|
3035
|
-
if (value.length > 512 || /[;\r\n'"\s]/u.test(value)) return void 0;
|
|
3036
|
-
try {
|
|
3037
|
-
const parsed = new URL(value);
|
|
3038
|
-
const secure = parsed.protocol === "https:" || connect && parsed.protocol === "wss:";
|
|
3039
|
-
const local = isLoopback(parsed.hostname) && (parsed.protocol === "http:" || connect && parsed.protocol === "ws:");
|
|
3040
|
-
if (!secure && !local) return void 0;
|
|
3041
|
-
if (parsed.username || parsed.password || parsed.pathname !== "/" || parsed.search || parsed.hash) {
|
|
3042
|
-
return void 0;
|
|
3043
|
-
}
|
|
3044
|
-
return parsed.origin;
|
|
3045
|
-
} catch {
|
|
3046
|
-
return void 0;
|
|
3047
|
-
}
|
|
3048
|
-
}
|
|
3049
|
-
function normalizeDomains(values, connect) {
|
|
3050
|
-
const normalized = [
|
|
3051
|
-
...new Set(
|
|
3052
|
-
values.slice(0, MAX_DOMAINS_PER_DIRECTIVE).map((value) => typeof value === "string" ? normalizeDomain(value, connect) : void 0).filter((value) => value !== void 0)
|
|
3053
|
-
)
|
|
3054
|
-
];
|
|
3055
|
-
return normalized;
|
|
3056
|
-
}
|
|
3057
|
-
function resolveAssistantAppSandboxPolicy(resourceMeta) {
|
|
3058
|
-
if (!isRecord(resourceMeta)) return {};
|
|
3059
|
-
const rawCsp = resourceMeta.csp;
|
|
3060
|
-
const csp = isRecord(rawCsp) ? {
|
|
3061
|
-
...Array.isArray(rawCsp.connectDomains) ? { connectDomains: normalizeDomains(rawCsp.connectDomains, true) } : {},
|
|
3062
|
-
...Array.isArray(rawCsp.resourceDomains) ? { resourceDomains: normalizeDomains(rawCsp.resourceDomains, false) } : {},
|
|
3063
|
-
...Array.isArray(rawCsp.frameDomains) ? { frameDomains: normalizeDomains(rawCsp.frameDomains, false) } : {},
|
|
3064
|
-
...Array.isArray(rawCsp.baseUriDomains) ? { baseUriDomains: normalizeDomains(rawCsp.baseUriDomains, false) } : {}
|
|
3065
|
-
} : void 0;
|
|
3066
|
-
const rawPermissions = resourceMeta.permissions;
|
|
3067
|
-
const permissions = isRecord(rawPermissions) ? {
|
|
3068
|
-
...isRecord(rawPermissions.camera) ? { camera: {} } : {},
|
|
3069
|
-
...isRecord(rawPermissions.microphone) ? { microphone: {} } : {},
|
|
3070
|
-
...isRecord(rawPermissions.geolocation) ? { geolocation: {} } : {},
|
|
3071
|
-
...isRecord(rawPermissions.clipboardWrite) ? { clipboardWrite: {} } : {}
|
|
3072
|
-
} : void 0;
|
|
3073
|
-
const allowAttribute = AZ(permissions);
|
|
3074
|
-
return {
|
|
3075
|
-
...csp === void 0 ? {} : { csp },
|
|
3076
|
-
...permissions === void 0 ? {} : { permissions },
|
|
3077
|
-
...allowAttribute ? { allowAttribute } : {}
|
|
3078
|
-
};
|
|
3079
|
-
}
|
|
3080
|
-
function assistantAppSandboxUrl(sandboxUrl, policy) {
|
|
3081
|
-
const parsed = new URL(sandboxUrl);
|
|
3082
|
-
if (policy.csp) parsed.searchParams.set("csp", JSON.stringify(policy.csp));
|
|
3083
|
-
const parentOrigin = globalThis.location?.origin;
|
|
3084
|
-
if (parentOrigin && parentOrigin !== "null") {
|
|
3085
|
-
parsed.hash = new URLSearchParams({ parentOrigin }).toString();
|
|
3086
|
-
}
|
|
3087
|
-
return parsed.href;
|
|
3088
|
-
}
|
|
3089
|
-
|
|
3090
3017
|
// src/app-host.ts
|
|
3091
|
-
var PROXY_DOCUMENT = `<!doctype html><meta charset="utf-8"><style>html,body,iframe{border:0;margin:0;width:100%;height:100%;overflow:hidden}body{background:transparent}</style><
|
|
3092
|
-
let inner
|
|
3093
|
-
if(self===top)throw new Error('The assistant sandbox relay must be embedded');
|
|
3094
|
-
const standardSandbox='allow-scripts allow-same-origin allow-forms';
|
|
3095
|
-
const rawParentOrigin=new URLSearchParams(location.hash.slice(1)).get('parentOrigin');
|
|
3096
|
-
let expectedParentOrigin;
|
|
3097
|
-
try{const parsed=new URL(rawParentOrigin||'');if(parsed.origin===rawParentOrigin&&/^https?:$/.test(parsed.protocol))expectedParentOrigin=parsed.origin}catch{}
|
|
3098
|
-
const parentTarget=expectedParentOrigin||'*';
|
|
3099
|
-
const ownOrigin=self.origin;
|
|
3018
|
+
var PROXY_DOCUMENT = `<!doctype html><meta charset="utf-8"><style>html,body,iframe{border:0;margin:0;width:100%;height:100%;overflow:hidden}body{background:transparent}</style><script>
|
|
3019
|
+
let inner;
|
|
3100
3020
|
const ready={jsonrpc:'2.0',method:'ui/notifications/sandbox-proxy-ready',params:{}};
|
|
3101
3021
|
// Re-announce until the host acknowledges with the resource: when this document is hosted
|
|
3102
3022
|
// cross-origin, the first announcement can arrive before the host's load handler is listening.
|
|
3103
|
-
const announce=setInterval(()=>parent.postMessage(ready,
|
|
3023
|
+
const announce=setInterval(()=>parent.postMessage(ready,'*'),120);
|
|
3104
3024
|
setTimeout(()=>clearInterval(announce),15000);
|
|
3105
3025
|
addEventListener('message',(event)=>{
|
|
3106
3026
|
if(event.source===parent){
|
|
3107
|
-
if(expectedParentOrigin&&event.origin!==expectedParentOrigin)return;
|
|
3108
3027
|
const message=event.data;
|
|
3109
3028
|
if(message?.method==='ui/notifications/sandbox-resource-ready'){
|
|
3110
3029
|
clearInterval(announce);
|
|
3111
|
-
if(
|
|
3112
|
-
loaded=true;
|
|
3113
|
-
const requestedSandbox=message.params?.sandbox;
|
|
3030
|
+
if(inner)return;
|
|
3114
3031
|
inner=document.createElement('iframe');
|
|
3115
|
-
inner.setAttribute('sandbox',
|
|
3032
|
+
inner.setAttribute('sandbox',message.params?.sandbox||'allow-scripts');
|
|
3116
3033
|
inner.setAttribute('referrerpolicy','no-referrer');
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
if(permissions?.camera)allow.push('camera');
|
|
3120
|
-
if(permissions?.microphone)allow.push('microphone');
|
|
3121
|
-
if(permissions?.geolocation)allow.push('geolocation');
|
|
3122
|
-
if(permissions?.clipboardWrite)allow.push('clipboard-write');
|
|
3123
|
-
if(allow.length)inner.setAttribute('allow',allow.join('; '));
|
|
3124
|
-
document.body.append(inner);
|
|
3125
|
-
let html=String(message.params?.html||'');
|
|
3126
|
-
const csp=message.params?.csp;
|
|
3127
|
-
if(csp&&typeof csp==='object'){
|
|
3128
|
-
const list=(value,fallback)=>Array.isArray(value)&&value.length?value.join(' '):fallback;
|
|
3129
|
-
const resources=Array.isArray(csp.resourceDomains)?csp.resourceDomains:[];
|
|
3130
|
-
const suffix=resources.length?' '+resources.join(' '):'';
|
|
3131
|
-
const policy=["default-src 'none'","script-src 'unsafe-inline'"+suffix,"style-src 'unsafe-inline'"+suffix,'img-src data: blob:'+suffix,'font-src data: blob:'+suffix,'media-src data: blob:'+suffix,'worker-src blob:'+suffix,'connect-src '+list(csp.connectDomains,"'none'"),'frame-src '+list(csp.frameDomains,"'none'"),"object-src 'none'","form-action 'none'",'base-uri '+list(csp.baseUriDomains,"'none'")].join('; ');
|
|
3132
|
-
const meta='<meta http-equiv="Content-Security-Policy" content="'+policy.replace(/&/g,'&').replace(/"/g,'"')+'">';
|
|
3133
|
-
const doctype=html.match(/^\\s*<!doctype[^>]*>/i);
|
|
3134
|
-
html=doctype?html.slice(0,doctype[0].length)+meta+html.slice(doctype[0].length):meta+html;
|
|
3135
|
-
}
|
|
3136
|
-
try{
|
|
3137
|
-
const doc=inner.contentDocument||inner.contentWindow?.document;
|
|
3138
|
-
if(!doc)throw new Error('document unavailable');
|
|
3139
|
-
doc.open();doc.write(html);doc.close();
|
|
3140
|
-
}catch{inner.srcdoc=html}
|
|
3034
|
+
inner.srcdoc=String(message.params?.html||'');
|
|
3035
|
+
document.body.replaceChildren(inner);
|
|
3141
3036
|
return;
|
|
3142
3037
|
}
|
|
3143
3038
|
inner?.contentWindow?.postMessage(message,'*');
|
|
3144
3039
|
} else if(inner && event.source===inner.contentWindow) {
|
|
3145
|
-
|
|
3146
|
-
parent.postMessage(event.data,parentTarget);
|
|
3040
|
+
parent.postMessage(event.data,'*');
|
|
3147
3041
|
}
|
|
3148
3042
|
});
|
|
3149
|
-
parent.postMessage(ready,
|
|
3150
|
-
</script
|
|
3043
|
+
parent.postMessage(ready,'*');
|
|
3044
|
+
</script>`;
|
|
3151
3045
|
function isAllowedAppLink(value, allowedDomains, baseUrl) {
|
|
3152
3046
|
try {
|
|
3153
3047
|
const parsed = new URL(value, baseUrl);
|
|
@@ -3174,42 +3068,16 @@ function createAssistantAppHostContext(theme, allowFullscreen = false, displayMo
|
|
|
3174
3068
|
}
|
|
3175
3069
|
var APP_RENDER_TIMEOUT_MS = 1e4;
|
|
3176
3070
|
var APP_TEARDOWN_TIMEOUT_MS = 1e3;
|
|
3177
|
-
var STANDARD_SANDBOX = "allow-scripts allow-same-origin allow-forms";
|
|
3178
3071
|
var mountedApps = /* @__PURE__ */ new WeakMap();
|
|
3179
3072
|
function resolveSandboxUrl(value) {
|
|
3180
3073
|
if (!value) return void 0;
|
|
3181
3074
|
try {
|
|
3182
3075
|
const parsed = new URL(value);
|
|
3183
|
-
|
|
3184
|
-
const permittedProtocol = parsed.protocol === "https:" || parsed.protocol === "http:" && loopback;
|
|
3185
|
-
const embedderOrigin = globalThis.location?.origin;
|
|
3186
|
-
if (!permittedProtocol || embedderOrigin && embedderOrigin !== "null" && parsed.origin === embedderOrigin) {
|
|
3187
|
-
return void 0;
|
|
3188
|
-
}
|
|
3189
|
-
return parsed.href;
|
|
3076
|
+
return parsed.protocol === "https:" || parsed.protocol === "http:" ? parsed.href : void 0;
|
|
3190
3077
|
} catch {
|
|
3191
3078
|
return void 0;
|
|
3192
3079
|
}
|
|
3193
3080
|
}
|
|
3194
|
-
function copyAppJson(value, depth = 0) {
|
|
3195
|
-
if (depth > 64) throw new Error("App payload nesting exceeds the host limit");
|
|
3196
|
-
if (value === null || typeof value === "string" || typeof value === "boolean") return value;
|
|
3197
|
-
if (typeof value === "number") {
|
|
3198
|
-
if (!Number.isFinite(value)) throw new Error("App payload numbers must be finite");
|
|
3199
|
-
return value;
|
|
3200
|
-
}
|
|
3201
|
-
if (Array.isArray(value)) return value.map((entry) => copyAppJson(entry, depth + 1));
|
|
3202
|
-
const copied = {};
|
|
3203
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
3204
|
-
Object.defineProperty(copied, key, {
|
|
3205
|
-
value: copyAppJson(entry, depth + 1),
|
|
3206
|
-
enumerable: true,
|
|
3207
|
-
configurable: true,
|
|
3208
|
-
writable: true
|
|
3209
|
-
});
|
|
3210
|
-
}
|
|
3211
|
-
return copied;
|
|
3212
|
-
}
|
|
3213
3081
|
function mountAssistantApp(detail, actions, options = {}) {
|
|
3214
3082
|
if (!detail.html) return void 0;
|
|
3215
3083
|
const card = document.createElement("section");
|
|
@@ -3230,25 +3098,16 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
3230
3098
|
const frame = document.createElement("iframe");
|
|
3231
3099
|
frame.className = "noodle-app-frame";
|
|
3232
3100
|
frame.title = detail.title ?? detail.tool;
|
|
3233
|
-
|
|
3101
|
+
frame.setAttribute("sandbox", "allow-scripts");
|
|
3234
3102
|
frame.setAttribute("referrerpolicy", "no-referrer");
|
|
3235
3103
|
const sandboxUrl = resolveSandboxUrl(options.sandboxUrl);
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
frame.setAttribute("sandbox", STANDARD_SANDBOX);
|
|
3239
|
-
if (policy.allowAttribute) frame.setAttribute("allow", policy.allowAttribute);
|
|
3240
|
-
frame.src = assistantAppSandboxUrl(sandboxUrl, policy);
|
|
3241
|
-
} else {
|
|
3242
|
-
frame.setAttribute("sandbox", "allow-scripts");
|
|
3243
|
-
frame.srcdoc = PROXY_DOCUMENT;
|
|
3244
|
-
}
|
|
3104
|
+
if (sandboxUrl) frame.src = sandboxUrl;
|
|
3105
|
+
else frame.srcdoc = PROXY_DOCUMENT;
|
|
3245
3106
|
card.append(frame);
|
|
3246
3107
|
let mountedBridge;
|
|
3247
3108
|
let mountedTransport;
|
|
3248
3109
|
let destroyed = false;
|
|
3249
3110
|
let initialized = false;
|
|
3250
|
-
let renderFailed = false;
|
|
3251
|
-
let renderStage = "sandbox_load";
|
|
3252
3111
|
let currentTheme = actions.theme;
|
|
3253
3112
|
let displayMode = "inline";
|
|
3254
3113
|
let hostContext = createAssistantAppHostContext(
|
|
@@ -3257,15 +3116,6 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
3257
3116
|
displayMode
|
|
3258
3117
|
);
|
|
3259
3118
|
let destroyPromise;
|
|
3260
|
-
let transportClosePromise;
|
|
3261
|
-
let renderTimer;
|
|
3262
|
-
const closeTransport = () => {
|
|
3263
|
-
if (transportClosePromise) return transportClosePromise;
|
|
3264
|
-
const closing = mountedTransport?.close().catch(() => {
|
|
3265
|
-
}) ?? Promise.resolve();
|
|
3266
|
-
transportClosePromise = closing;
|
|
3267
|
-
return closing;
|
|
3268
|
-
};
|
|
3269
3119
|
const applyDisplayMode = (requestedMode) => {
|
|
3270
3120
|
displayMode = requestedMode === "fullscreen" && options.allowFullscreen === true ? "fullscreen" : "inline";
|
|
3271
3121
|
card.toggleAttribute("data-fullscreen", displayMode === "fullscreen");
|
|
@@ -3283,26 +3133,18 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
3283
3133
|
applyDisplayMode("inline");
|
|
3284
3134
|
frame.focus();
|
|
3285
3135
|
});
|
|
3286
|
-
const
|
|
3287
|
-
if (
|
|
3288
|
-
return;
|
|
3289
|
-
renderFailed = true;
|
|
3290
|
-
clearTimeout(renderTimer);
|
|
3136
|
+
const renderTimer = setTimeout(() => {
|
|
3137
|
+
if (initialized || !frame.isConnected) return;
|
|
3291
3138
|
const note = document.createElement("div");
|
|
3292
3139
|
note.className = "noodle-app-fallback";
|
|
3293
3140
|
note.textContent = "This app view could not be displayed.";
|
|
3294
3141
|
frame.replaceWith(note);
|
|
3295
|
-
options.onRenderFailure?.({ code, retryable: false
|
|
3296
|
-
void closeTransport();
|
|
3297
|
-
};
|
|
3298
|
-
renderTimer = setTimeout(() => {
|
|
3299
|
-
showRenderFailure("view_render_timeout");
|
|
3142
|
+
options.onRenderFailure?.({ code: "view_render_timeout", retryable: false });
|
|
3300
3143
|
}, APP_RENDER_TIMEOUT_MS);
|
|
3301
3144
|
frame.addEventListener(
|
|
3302
3145
|
"load",
|
|
3303
3146
|
() => {
|
|
3304
|
-
if (destroyed
|
|
3305
|
-
renderStage = "sandbox_proxy";
|
|
3147
|
+
if (destroyed) return;
|
|
3306
3148
|
const target = frame.contentWindow;
|
|
3307
3149
|
if (!target) return;
|
|
3308
3150
|
const bridge = new DX(
|
|
@@ -3313,11 +3155,7 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
3313
3155
|
serverTools: {},
|
|
3314
3156
|
serverResources: {},
|
|
3315
3157
|
updateModelContext: { text: {}, structuredContent: {} },
|
|
3316
|
-
message: { text: {} }
|
|
3317
|
-
sandbox: {
|
|
3318
|
-
...appliedPolicy.csp === void 0 ? {} : { csp: appliedPolicy.csp },
|
|
3319
|
-
...appliedPolicy.permissions === void 0 ? {} : { permissions: appliedPolicy.permissions }
|
|
3320
|
-
}
|
|
3158
|
+
message: { text: {} }
|
|
3321
3159
|
},
|
|
3322
3160
|
{
|
|
3323
3161
|
hostContext
|
|
@@ -3325,15 +3163,13 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
3325
3163
|
);
|
|
3326
3164
|
mountedBridge = bridge;
|
|
3327
3165
|
bridge.onsandboxready = () => {
|
|
3328
|
-
if (destroyed
|
|
3329
|
-
renderStage = "app_initialize";
|
|
3166
|
+
if (destroyed) return;
|
|
3330
3167
|
const current = options.getDetail?.() ?? detail;
|
|
3331
3168
|
void bridge.sendSandboxResourceReady({
|
|
3332
3169
|
html: current.html,
|
|
3333
|
-
sandbox:
|
|
3334
|
-
...
|
|
3335
|
-
|
|
3336
|
-
}).catch(() => showRenderFailure("view_bridge_error"));
|
|
3170
|
+
sandbox: "allow-scripts",
|
|
3171
|
+
...current.resourceMeta ?? {}
|
|
3172
|
+
});
|
|
3337
3173
|
};
|
|
3338
3174
|
bridge.onsizechange = ({ height }) => {
|
|
3339
3175
|
if (destroyed) return;
|
|
@@ -3397,30 +3233,21 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
3397
3233
|
return await actions.client.requestApp("resources/read", params);
|
|
3398
3234
|
};
|
|
3399
3235
|
bridge.oninitialized = () => {
|
|
3400
|
-
if (destroyed
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
bridge.sendToolInput({ arguments: argumentsRecord }),
|
|
3411
|
-
bridge.sendToolResult({
|
|
3412
|
-
content: [{ type: "text", text: JSON.stringify(copiedResult) }],
|
|
3413
|
-
...typeof copiedResult === "object" && copiedResult !== null && !Array.isArray(copiedResult) ? { structuredContent: copiedResult } : {}
|
|
3414
|
-
})
|
|
3415
|
-
]).catch(() => showRenderFailure("view_bridge_error"));
|
|
3416
|
-
} catch {
|
|
3417
|
-
showRenderFailure("view_bridge_error");
|
|
3418
|
-
}
|
|
3236
|
+
if (destroyed) return;
|
|
3237
|
+
initialized = true;
|
|
3238
|
+
clearTimeout(renderTimer);
|
|
3239
|
+
bridge.setHostContext(hostContext);
|
|
3240
|
+
const current = options.getDetail?.() ?? detail;
|
|
3241
|
+
void bridge.sendToolInput({ arguments: current.arguments ?? {} });
|
|
3242
|
+
void bridge.sendToolResult({
|
|
3243
|
+
content: [{ type: "text", text: JSON.stringify(current.result) }],
|
|
3244
|
+
...typeof current.result === "object" && current.result !== null && !Array.isArray(current.result) ? { structuredContent: current.result } : {}
|
|
3245
|
+
});
|
|
3419
3246
|
};
|
|
3420
3247
|
const transport = new E(target, target);
|
|
3421
3248
|
mountedTransport = transport;
|
|
3422
3249
|
void bridge.connect(transport).catch(() => {
|
|
3423
|
-
|
|
3250
|
+
void destroy();
|
|
3424
3251
|
});
|
|
3425
3252
|
},
|
|
3426
3253
|
{ once: true }
|
|
@@ -3446,7 +3273,8 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
3446
3273
|
}
|
|
3447
3274
|
} catch {
|
|
3448
3275
|
}
|
|
3449
|
-
await
|
|
3276
|
+
await mountedTransport?.close().catch(() => {
|
|
3277
|
+
});
|
|
3450
3278
|
card.remove();
|
|
3451
3279
|
mountedApps.delete(card);
|
|
3452
3280
|
})();
|
|
@@ -3492,4 +3320,4 @@ export {
|
|
|
3492
3320
|
ASSISTANT_APP_VIEW_CSS,
|
|
3493
3321
|
ASSISTANT_APP_VIEW_STYLES
|
|
3494
3322
|
};
|
|
3495
|
-
//# sourceMappingURL=chunk-
|
|
3323
|
+
//# sourceMappingURL=chunk-CF2SCDLF.js.map
|