@noodleseed/assistant 1.22.0 → 1.24.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.
- package/README.md +43 -8
- package/dist/app-view-element-DDtXu08a.d.ts +40 -0
- package/dist/app-view-element-DSPtyEul.d.cts +40 -0
- package/dist/app-view.cjs +18666 -0
- package/dist/app-view.cjs.map +1 -0
- package/dist/app-view.d.cts +9 -0
- package/dist/app-view.d.ts +9 -0
- package/dist/app-view.js +15 -0
- package/dist/app-view.js.map +1 -0
- package/dist/{appearance-Cc-eqSbp.d.cts → appearance-0nS2LFjb.d.cts} +1 -0
- package/dist/{appearance-Cc-eqSbp.d.ts → appearance-0nS2LFjb.d.ts} +1 -0
- package/dist/chunk-5NBHHNI3.js +180 -0
- package/dist/chunk-5NBHHNI3.js.map +1 -0
- package/dist/{chunk-6TT3R555.js → chunk-6PVDV7SO.js} +823 -4062
- package/dist/chunk-6PVDV7SO.js.map +1 -0
- package/dist/{chunk-ZPZHPXIQ.js → chunk-IBDP6PXQ.js} +9 -3882
- package/dist/chunk-IBDP6PXQ.js.map +1 -0
- package/dist/chunk-P223CYPO.js +3880 -0
- package/dist/chunk-P223CYPO.js.map +1 -0
- package/dist/chunk-XKTUXFGX.js +3323 -0
- package/dist/chunk-XKTUXFGX.js.map +1 -0
- package/dist/{client-BZ7xPwfW.d.cts → client-By4gqB1k.d.cts} +2 -2
- package/dist/{client-BkJlpN5N.d.ts → client-Cf38TgwN.d.ts} +2 -2
- package/dist/client.d.cts +2 -2
- package/dist/client.d.ts +2 -2
- package/dist/client.js +2 -1
- package/dist/embed.global.js +87 -73
- package/dist/index.cjs +110 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/react/client.d.cts +2 -2
- package/dist/react/client.d.ts +2 -2
- package/dist/react/client.js +2 -1
- package/dist/react/client.js.map +1 -1
- package/dist/react.cjs +298 -69
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +8 -9
- package/dist/react.d.ts +8 -9
- package/dist/react.js +31 -41
- package/dist/react.js.map +1 -1
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/package.json +16 -2
- package/dist/chunk-6TT3R555.js.map +0 -1
- package/dist/chunk-ZPZHPXIQ.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
3
|
-
import './appearance-
|
|
1
|
+
import { a as AssistantViewAvailableDetail, g as AssistantClientEvent, c as AssistantContext, f as AssistantModelContextUpdate, b as AssistantPageContext, h as AssistantInteractionResponse } from './client-By4gqB1k.cjs';
|
|
2
|
+
export { e as AssistantErrorDetail, i as AssistantEvent, j as AssistantViewAvailableEvent } from './client-By4gqB1k.cjs';
|
|
3
|
+
import './appearance-0nS2LFjb.cjs';
|
|
4
4
|
import 'ai';
|
|
5
5
|
|
|
6
6
|
interface AssistantSurfaceAppearance {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
3
|
-
import './appearance-
|
|
1
|
+
import { a as AssistantViewAvailableDetail, g as AssistantClientEvent, c as AssistantContext, f as AssistantModelContextUpdate, b as AssistantPageContext, h as AssistantInteractionResponse } from './client-Cf38TgwN.js';
|
|
2
|
+
export { e as AssistantErrorDetail, i as AssistantEvent, j as AssistantViewAvailableEvent } from './client-Cf38TgwN.js';
|
|
3
|
+
import './appearance-0nS2LFjb.js';
|
|
4
4
|
import 'ai';
|
|
5
5
|
|
|
6
6
|
interface AssistantSurfaceAppearance {
|
package/dist/index.js
CHANGED
|
@@ -2,8 +2,10 @@ import {
|
|
|
2
2
|
ASSISTANT_TAG_NAME,
|
|
3
3
|
NoodleAssistantElement,
|
|
4
4
|
registerNoodleAssistant
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-6PVDV7SO.js";
|
|
6
|
+
import "./chunk-XKTUXFGX.js";
|
|
7
|
+
import "./chunk-IBDP6PXQ.js";
|
|
8
|
+
import "./chunk-P223CYPO.js";
|
|
7
9
|
import "./chunk-3YYTUJPJ.js";
|
|
8
10
|
import "./chunk-5FUTL2UF.js";
|
|
9
11
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export {\n ASSISTANT_TAG_NAME,\n NoodleAssistantElement,\n registerNoodleAssistant,\n} from './element.js';\nexport type { AssistantViewAvailableDetail, AssistantViewAvailableEvent } from './events.js';\nexport type {\n AssistantAppearance,\n AssistantAppearanceTheme,\n AssistantAppearanceWarning,\n AssistantSurfaceAppearance,\n} from './host-appearance.js';\nexport type { AssistantErrorDetail, AssistantEvent } from './transport.js';\n\nimport { registerNoodleAssistant } from './element.js';\n\nregisterNoodleAssistant();\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export {\n ASSISTANT_TAG_NAME,\n NoodleAssistantElement,\n registerNoodleAssistant,\n} from './element.js';\nexport type { AssistantViewAvailableDetail, AssistantViewAvailableEvent } from './events.js';\nexport type {\n AssistantAppearance,\n AssistantAppearanceTheme,\n AssistantAppearanceWarning,\n AssistantSurfaceAppearance,\n} from './host-appearance.js';\nexport type { AssistantErrorDetail, AssistantEvent } from './transport.js';\n\nimport { registerNoodleAssistant } from './element.js';\n\nregisterNoodleAssistant();\n"],"mappings":";;;;;;;;;;;;AAgBA,wBAAwB;","names":[]}
|
package/dist/react/client.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import '../appearance-
|
|
1
|
+
import { b as AssistantPageContext, c as AssistantContext, C as CreateAssistantClientOptions, d as AssistantChatState, A as AssistantClient } from '../client-By4gqB1k.cjs';
|
|
2
|
+
import '../appearance-0nS2LFjb.cjs';
|
|
3
3
|
import 'ai';
|
|
4
4
|
|
|
5
5
|
type UseNoodleAssistantOptions<TPageContext extends AssistantPageContext = AssistantContext> = CreateAssistantClientOptions<TPageContext> & {
|
package/dist/react/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import '../appearance-
|
|
1
|
+
import { b as AssistantPageContext, c as AssistantContext, C as CreateAssistantClientOptions, d as AssistantChatState, A as AssistantClient } from '../client-Cf38TgwN.js';
|
|
2
|
+
import '../appearance-0nS2LFjb.js';
|
|
3
3
|
import 'ai';
|
|
4
4
|
|
|
5
5
|
type UseNoodleAssistantOptions<TPageContext extends AssistantPageContext = AssistantContext> = CreateAssistantClientOptions<TPageContext> & {
|
package/dist/react/client.js
CHANGED
package/dist/react/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react-client.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useLayoutEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n type AssistantChatState,\n type AssistantClient,\n type AssistantContext,\n type AssistantModelContextUpdate,\n type AssistantPageContext,\n type CreateAssistantClientOptions,\n createAssistantClient,\n} from './client.js';\n\nexport type UseNoodleAssistantOptions<\n TPageContext extends AssistantPageContext = AssistantContext,\n> = CreateAssistantClientOptions<TPageContext> & {\n /**\n * Browser-local identity for the authenticated principal/tenant.\n * Changing it discards the previous in-memory session and transcript; it is never sent to Noodle.\n */\n readonly principalKey: string;\n};\n\nexport type UseNoodleAssistantResult<TPageContext extends AssistantPageContext = AssistantContext> =\n AssistantChatState & {\n /** Canonical controller for turns, interactions, context, Apps requests, and aborts. */\n readonly client: AssistantClient<TPageContext>;\n };\n\ninterface AssistantReactStore {\n readonly getSnapshot: () => AssistantChatState;\n readonly subscribe: (listener: () => void) => () => void;\n}\n\nconst useCommittedLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect;\n\n/**\n * Subscribe a customer-owned React renderer to the DOM-free assistant client.\n *\n * The hook owns only client lifetime and React state projection. Session exchange, transport,\n * retries, interaction continuations, and transcript construction remain client responsibilities.\n */\nexport function useNoodleAssistant<TPageContext extends AssistantPageContext = AssistantContext>(\n options: UseNoodleAssistantOptions<TPageContext>,\n): UseNoodleAssistantResult<TPageContext> {\n const optionsRef = useRef(options);\n const { fetch: injectedFetch, principalKey, sessionEndpoint, embedId, serviceUrl } = options;\n\n const client = useMemo(() => {\n if (!principalKey.trim()) throw new Error('principalKey is required');\n // The two mounts are spelled out rather than spread from one object: the exclusive union is what\n // stops a caller passing both, and a spread would collapse it back into an ambiguous shape.\n const behavior = {\n ...(injectedFetch ? { fetch: injectedFetch } : {}),\n clientContext: () => readProvider(optionsRef.current.clientContext),\n pageContext: () => readProvider(optionsRef.current.pageContext),\n };\n return embedId !== undefined\n ? createAssistantClient<TPageContext>({\n embedId,\n ...(serviceUrl !== undefined ? { serviceUrl } : {}),\n ...behavior,\n })\n : createAssistantClient<TPageContext>({\n sessionEndpoint: sessionEndpoint ?? '',\n ...behavior,\n });\n }, [injectedFetch, principalKey, sessionEndpoint, embedId, serviceUrl]);\n const store = useMemo(() => createAssistantReactStore(client), [client]);\n const state = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n const synchronized = useRef<\n | {\n readonly client: AssistantClient<TPageContext>;\n readonly context: AssistantContext | undefined;\n readonly modelContext: AssistantModelContextUpdate | undefined;\n }\n | undefined\n >(undefined);\n\n useCommittedLayoutEffect(() => {\n optionsRef.current = options;\n const previous = synchronized.current;\n if (previous?.client === client) {\n if (previous.context !== options.context) {\n client.updateContext(options.context ?? {});\n }\n if (previous.modelContext !== options.modelContext) {\n client.updateModelContext(options.modelContext ?? {});\n }\n } else {\n if (options.context !== undefined) client.updateContext(options.context);\n if (options.modelContext !== undefined) client.updateModelContext(options.modelContext);\n }\n synchronized.current = {\n client,\n context: options.context,\n modelContext: options.modelContext,\n };\n }, [client, options]);\n\n useCommittedLayoutEffect(\n () => () => {\n client.abort();\n client.resetSession();\n },\n [client],\n );\n\n return useMemo(() => ({ client, ...state }), [client, state]);\n}\n\nfunction createAssistantReactStore<TPageContext extends AssistantPageContext>(\n client: AssistantClient<TPageContext>,\n): AssistantReactStore {\n let snapshot = client.getChatState();\n return {\n getSnapshot: () => snapshot,\n subscribe(listener) {\n let subscribing = true;\n const unsubscribe = client.subscribeChat((next) => {\n snapshot = next;\n if (!subscribing) listener();\n });\n subscribing = false;\n return unsubscribe;\n },\n };\n}\n\nfunction readProvider<T>(value: T | (() => T | undefined) | undefined): T | undefined {\n return typeof value === 'function' ? (value as () => T | undefined)() : value;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/react-client.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useLayoutEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n type AssistantChatState,\n type AssistantClient,\n type AssistantContext,\n type AssistantModelContextUpdate,\n type AssistantPageContext,\n type CreateAssistantClientOptions,\n createAssistantClient,\n} from './client.js';\n\nexport type UseNoodleAssistantOptions<\n TPageContext extends AssistantPageContext = AssistantContext,\n> = CreateAssistantClientOptions<TPageContext> & {\n /**\n * Browser-local identity for the authenticated principal/tenant.\n * Changing it discards the previous in-memory session and transcript; it is never sent to Noodle.\n */\n readonly principalKey: string;\n};\n\nexport type UseNoodleAssistantResult<TPageContext extends AssistantPageContext = AssistantContext> =\n AssistantChatState & {\n /** Canonical controller for turns, interactions, context, Apps requests, and aborts. */\n readonly client: AssistantClient<TPageContext>;\n };\n\ninterface AssistantReactStore {\n readonly getSnapshot: () => AssistantChatState;\n readonly subscribe: (listener: () => void) => () => void;\n}\n\nconst useCommittedLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect;\n\n/**\n * Subscribe a customer-owned React renderer to the DOM-free assistant client.\n *\n * The hook owns only client lifetime and React state projection. Session exchange, transport,\n * retries, interaction continuations, and transcript construction remain client responsibilities.\n */\nexport function useNoodleAssistant<TPageContext extends AssistantPageContext = AssistantContext>(\n options: UseNoodleAssistantOptions<TPageContext>,\n): UseNoodleAssistantResult<TPageContext> {\n const optionsRef = useRef(options);\n const { fetch: injectedFetch, principalKey, sessionEndpoint, embedId, serviceUrl } = options;\n\n const client = useMemo(() => {\n if (!principalKey.trim()) throw new Error('principalKey is required');\n // The two mounts are spelled out rather than spread from one object: the exclusive union is what\n // stops a caller passing both, and a spread would collapse it back into an ambiguous shape.\n const behavior = {\n ...(injectedFetch ? { fetch: injectedFetch } : {}),\n clientContext: () => readProvider(optionsRef.current.clientContext),\n pageContext: () => readProvider(optionsRef.current.pageContext),\n };\n return embedId !== undefined\n ? createAssistantClient<TPageContext>({\n embedId,\n ...(serviceUrl !== undefined ? { serviceUrl } : {}),\n ...behavior,\n })\n : createAssistantClient<TPageContext>({\n sessionEndpoint: sessionEndpoint ?? '',\n ...behavior,\n });\n }, [injectedFetch, principalKey, sessionEndpoint, embedId, serviceUrl]);\n const store = useMemo(() => createAssistantReactStore(client), [client]);\n const state = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n const synchronized = useRef<\n | {\n readonly client: AssistantClient<TPageContext>;\n readonly context: AssistantContext | undefined;\n readonly modelContext: AssistantModelContextUpdate | undefined;\n }\n | undefined\n >(undefined);\n\n useCommittedLayoutEffect(() => {\n optionsRef.current = options;\n const previous = synchronized.current;\n if (previous?.client === client) {\n if (previous.context !== options.context) {\n client.updateContext(options.context ?? {});\n }\n if (previous.modelContext !== options.modelContext) {\n client.updateModelContext(options.modelContext ?? {});\n }\n } else {\n if (options.context !== undefined) client.updateContext(options.context);\n if (options.modelContext !== undefined) client.updateModelContext(options.modelContext);\n }\n synchronized.current = {\n client,\n context: options.context,\n modelContext: options.modelContext,\n };\n }, [client, options]);\n\n useCommittedLayoutEffect(\n () => () => {\n client.abort();\n client.resetSession();\n },\n [client],\n );\n\n return useMemo(() => ({ client, ...state }), [client, state]);\n}\n\nfunction createAssistantReactStore<TPageContext extends AssistantPageContext>(\n client: AssistantClient<TPageContext>,\n): AssistantReactStore {\n let snapshot = client.getChatState();\n return {\n getSnapshot: () => snapshot,\n subscribe(listener) {\n let subscribing = true;\n const unsubscribe = client.subscribeChat((next) => {\n snapshot = next;\n if (!subscribing) listener();\n });\n subscribing = false;\n return unsubscribe;\n },\n };\n}\n\nfunction readProvider<T>(value: T | (() => T | undefined) | undefined): T | undefined {\n return typeof value === 'function' ? (value as () => T | undefined)() : value;\n}\n"],"mappings":";;;;;;;;;AAEA,SAAS,WAAW,iBAAiB,SAAS,QAAQ,4BAA4B;AAgClF,IAAM,2BAA2B,OAAO,WAAW,cAAc,YAAY;AAQtE,SAAS,mBACd,SACwC;AACxC,QAAM,aAAa,OAAO,OAAO;AACjC,QAAM,EAAE,OAAO,eAAe,cAAc,iBAAiB,SAAS,WAAW,IAAI;AAErF,QAAM,SAAS,QAAQ,MAAM;AAC3B,QAAI,CAAC,aAAa,KAAK,EAAG,OAAM,IAAI,MAAM,0BAA0B;AAGpE,UAAM,WAAW;AAAA,MACf,GAAI,gBAAgB,EAAE,OAAO,cAAc,IAAI,CAAC;AAAA,MAChD,eAAe,MAAM,aAAa,WAAW,QAAQ,aAAa;AAAA,MAClE,aAAa,MAAM,aAAa,WAAW,QAAQ,WAAW;AAAA,IAChE;AACA,WAAO,YAAY,SACf,sBAAoC;AAAA,MAClC;AAAA,MACA,GAAI,eAAe,SAAY,EAAE,WAAW,IAAI,CAAC;AAAA,MACjD,GAAG;AAAA,IACL,CAAC,IACD,sBAAoC;AAAA,MAClC,iBAAiB,mBAAmB;AAAA,MACpC,GAAG;AAAA,IACL,CAAC;AAAA,EACP,GAAG,CAAC,eAAe,cAAc,iBAAiB,SAAS,UAAU,CAAC;AACtE,QAAM,QAAQ,QAAQ,MAAM,0BAA0B,MAAM,GAAG,CAAC,MAAM,CAAC;AACvE,QAAM,QAAQ,qBAAqB,MAAM,WAAW,MAAM,aAAa,MAAM,WAAW;AACxF,QAAM,eAAe,OAOnB,MAAS;AAEX,2BAAyB,MAAM;AAC7B,eAAW,UAAU;AACrB,UAAM,WAAW,aAAa;AAC9B,QAAI,UAAU,WAAW,QAAQ;AAC/B,UAAI,SAAS,YAAY,QAAQ,SAAS;AACxC,eAAO,cAAc,QAAQ,WAAW,CAAC,CAAC;AAAA,MAC5C;AACA,UAAI,SAAS,iBAAiB,QAAQ,cAAc;AAClD,eAAO,mBAAmB,QAAQ,gBAAgB,CAAC,CAAC;AAAA,MACtD;AAAA,IACF,OAAO;AACL,UAAI,QAAQ,YAAY,OAAW,QAAO,cAAc,QAAQ,OAAO;AACvE,UAAI,QAAQ,iBAAiB,OAAW,QAAO,mBAAmB,QAAQ,YAAY;AAAA,IACxF;AACA,iBAAa,UAAU;AAAA,MACrB;AAAA,MACA,SAAS,QAAQ;AAAA,MACjB,cAAc,QAAQ;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,QAAQ,OAAO,CAAC;AAEpB;AAAA,IACE,MAAM,MAAM;AACV,aAAO,MAAM;AACb,aAAO,aAAa;AAAA,IACtB;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,SAAO,QAAQ,OAAO,EAAE,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,KAAK,CAAC;AAC9D;AAEA,SAAS,0BACP,QACqB;AACrB,MAAI,WAAW,OAAO,aAAa;AACnC,SAAO;AAAA,IACL,aAAa,MAAM;AAAA,IACnB,UAAU,UAAU;AAClB,UAAI,cAAc;AAClB,YAAM,cAAc,OAAO,cAAc,CAAC,SAAS;AACjD,mBAAW;AACX,YAAI,CAAC,YAAa,UAAS;AAAA,MAC7B,CAAC;AACD,oBAAc;AACd,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,SAAS,aAAgB,OAA6D;AACpF,SAAO,OAAO,UAAU,aAAc,MAA8B,IAAI;AAC1E;","names":[]}
|
package/dist/react.cjs
CHANGED
|
@@ -22112,11 +22112,11 @@ function isAllowedAppLink(value, allowedDomains, baseUrl) {
|
|
|
22112
22112
|
return void 0;
|
|
22113
22113
|
}
|
|
22114
22114
|
}
|
|
22115
|
-
function createAssistantAppHostContext(theme) {
|
|
22115
|
+
function createAssistantAppHostContext(theme, allowFullscreen = false, displayMode = "inline") {
|
|
22116
22116
|
return {
|
|
22117
22117
|
theme,
|
|
22118
|
-
displayMode: "inline",
|
|
22119
|
-
availableDisplayModes: ["inline", "fullscreen"],
|
|
22118
|
+
displayMode: allowFullscreen && displayMode === "fullscreen" ? "fullscreen" : "inline",
|
|
22119
|
+
availableDisplayModes: allowFullscreen ? ["inline", "fullscreen"] : ["inline"],
|
|
22120
22120
|
platform: "web"
|
|
22121
22121
|
};
|
|
22122
22122
|
}
|
|
@@ -22142,6 +22142,13 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
22142
22142
|
title.textContent = detail.title;
|
|
22143
22143
|
card.append(title);
|
|
22144
22144
|
}
|
|
22145
|
+
const exitFullscreen = document.createElement("button");
|
|
22146
|
+
exitFullscreen.className = "noodle-app-fullscreen-exit";
|
|
22147
|
+
exitFullscreen.type = "button";
|
|
22148
|
+
exitFullscreen.setAttribute("aria-label", "Exit fullscreen");
|
|
22149
|
+
exitFullscreen.title = "Exit fullscreen";
|
|
22150
|
+
exitFullscreen.hidden = true;
|
|
22151
|
+
card.append(exitFullscreen);
|
|
22145
22152
|
const frame = document.createElement("iframe");
|
|
22146
22153
|
frame.className = "noodle-app-frame";
|
|
22147
22154
|
frame.title = detail.title ?? detail.tool;
|
|
@@ -22155,8 +22162,31 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
22155
22162
|
let mountedTransport;
|
|
22156
22163
|
let destroyed = false;
|
|
22157
22164
|
let initialized = false;
|
|
22158
|
-
let
|
|
22165
|
+
let currentTheme = actions.theme;
|
|
22166
|
+
let displayMode = "inline";
|
|
22167
|
+
let hostContext = createAssistantAppHostContext(
|
|
22168
|
+
currentTheme,
|
|
22169
|
+
options.allowFullscreen === true,
|
|
22170
|
+
displayMode
|
|
22171
|
+
);
|
|
22159
22172
|
let destroyPromise;
|
|
22173
|
+
const applyDisplayMode = (requestedMode) => {
|
|
22174
|
+
displayMode = requestedMode === "fullscreen" && options.allowFullscreen === true ? "fullscreen" : "inline";
|
|
22175
|
+
card.toggleAttribute("data-fullscreen", displayMode === "fullscreen");
|
|
22176
|
+
exitFullscreen.hidden = displayMode !== "fullscreen";
|
|
22177
|
+
hostContext = createAssistantAppHostContext(
|
|
22178
|
+
currentTheme,
|
|
22179
|
+
options.allowFullscreen === true,
|
|
22180
|
+
displayMode
|
|
22181
|
+
);
|
|
22182
|
+
if (initialized) mountedBridge?.setHostContext(hostContext);
|
|
22183
|
+
return displayMode;
|
|
22184
|
+
};
|
|
22185
|
+
exitFullscreen.addEventListener("click", () => {
|
|
22186
|
+
if (destroyed) return;
|
|
22187
|
+
applyDisplayMode("inline");
|
|
22188
|
+
frame.focus();
|
|
22189
|
+
});
|
|
22160
22190
|
const renderTimer = setTimeout(() => {
|
|
22161
22191
|
if (initialized || !frame.isConnected) return;
|
|
22162
22192
|
const note = document.createElement("div");
|
|
@@ -22214,6 +22244,11 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
22214
22244
|
actions.updateModelContext(update);
|
|
22215
22245
|
return {};
|
|
22216
22246
|
};
|
|
22247
|
+
bridge.onrequestteardown = () => {
|
|
22248
|
+
if (destroyed) return;
|
|
22249
|
+
options.onTeardownRequest?.();
|
|
22250
|
+
void destroy();
|
|
22251
|
+
};
|
|
22217
22252
|
bridge.onopenlink = async ({ url: url2 }) => {
|
|
22218
22253
|
if (destroyed) return { isError: true };
|
|
22219
22254
|
const current = options.getDetail?.() ?? detail;
|
|
@@ -22227,10 +22262,8 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
22227
22262
|
return {};
|
|
22228
22263
|
};
|
|
22229
22264
|
bridge.onrequestdisplaymode = async ({ mode }) => {
|
|
22230
|
-
|
|
22231
|
-
|
|
22232
|
-
card.toggleAttribute("data-fullscreen", accepted === "fullscreen");
|
|
22233
|
-
return { mode: accepted };
|
|
22265
|
+
if (destroyed) return { mode: displayMode };
|
|
22266
|
+
return { mode: applyDisplayMode(mode) };
|
|
22234
22267
|
};
|
|
22235
22268
|
bridge.oncalltool = async (params) => {
|
|
22236
22269
|
if (destroyed) {
|
|
@@ -22275,7 +22308,12 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
22275
22308
|
);
|
|
22276
22309
|
const updateTheme = (theme) => {
|
|
22277
22310
|
if (destroyed) return;
|
|
22278
|
-
|
|
22311
|
+
currentTheme = theme;
|
|
22312
|
+
hostContext = createAssistantAppHostContext(
|
|
22313
|
+
currentTheme,
|
|
22314
|
+
options.allowFullscreen === true,
|
|
22315
|
+
displayMode
|
|
22316
|
+
);
|
|
22279
22317
|
if (initialized) mountedBridge?.setHostContext(hostContext);
|
|
22280
22318
|
};
|
|
22281
22319
|
const destroy = () => {
|
|
@@ -22413,6 +22451,7 @@ var DEFAULT_APPEARANCE = {
|
|
|
22413
22451
|
copy: "Copy",
|
|
22414
22452
|
newMessages: "New messages",
|
|
22415
22453
|
reconnect: "Reconnect",
|
|
22454
|
+
newConversation: "New conversation",
|
|
22416
22455
|
retry: "Try again",
|
|
22417
22456
|
unavailable: "The assistant is temporarily unavailable.",
|
|
22418
22457
|
sessionExpired: "Your assistant session expired. Reopen it to continue.",
|
|
@@ -28122,6 +28161,27 @@ function appInteractionStopped(action) {
|
|
|
28122
28161
|
};
|
|
28123
28162
|
}
|
|
28124
28163
|
|
|
28164
|
+
// src/conversation-recovery.ts
|
|
28165
|
+
function appendConversationRecovery(input) {
|
|
28166
|
+
if (!input.messages) return;
|
|
28167
|
+
input.messages.querySelector(".conversation-error")?.remove();
|
|
28168
|
+
const error51 = document.createElement("section");
|
|
28169
|
+
error51.className = "conversation-error";
|
|
28170
|
+
error51.setAttribute("role", input.action ? "alert" : "status");
|
|
28171
|
+
const text3 = document.createElement("p");
|
|
28172
|
+
text3.textContent = input.message;
|
|
28173
|
+
error51.append(text3);
|
|
28174
|
+
if (input.action) {
|
|
28175
|
+
const button2 = document.createElement("button");
|
|
28176
|
+
button2.type = "button";
|
|
28177
|
+
button2.textContent = input.action.label;
|
|
28178
|
+
button2.addEventListener("click", input.action.run);
|
|
28179
|
+
error51.append(button2);
|
|
28180
|
+
}
|
|
28181
|
+
input.messages.append(error51);
|
|
28182
|
+
input.revealLatest();
|
|
28183
|
+
}
|
|
28184
|
+
|
|
28125
28185
|
// src/input-request-card.ts
|
|
28126
28186
|
function createInputRequestCard(options) {
|
|
28127
28187
|
const card = document.createElement("section");
|
|
@@ -31727,6 +31787,29 @@ var AssistantElementScrollController = class {
|
|
|
31727
31787
|
}
|
|
31728
31788
|
};
|
|
31729
31789
|
|
|
31790
|
+
// src/app-view-styles.ts
|
|
31791
|
+
var ASSISTANT_APP_VIEW_CSS = `
|
|
31792
|
+
.noodle-app-card { position: relative; display: grid; gap: 8px; width: 100%; margin: 4px 0 16px; overflow: hidden; color: var(--ns-assistant-app-text, inherit); border: 1px solid var(--ns-assistant-app-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider, var(--ns-app-view-border, #d1d5db)))); border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius, 12px)); background: var(--ns-assistant-app, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated, var(--ns-app-view-surface, #fff)))); }
|
|
31793
|
+
.noodle-app-title { padding: 10px 12px 0; font-size: .86em; font-weight: 650; }
|
|
31794
|
+
.noodle-app-fullscreen-exit { position: absolute; top: max(12px, env(safe-area-inset-top)); right: max(12px, env(safe-area-inset-right)); z-index: 1; display: grid; place-items: center; width: 44px; height: 44px; padding: 0; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text, var(--ns-app-view-muted, #6b7280))); border: 1px solid var(--ns-assistant-secondary-button-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider, var(--ns-app-view-border, #d1d5db)))); border-radius: 999px; background: var(--ns-assistant-secondary-button, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated, var(--ns-app-view-surface, #fff)))); box-shadow: 0 6px 20px rgba(0,0,0,.14); cursor: pointer; font: inherit; transition: color .15s ease, background .15s ease, transform .15s ease; }
|
|
31795
|
+
.noodle-app-fullscreen-exit[hidden] { display: none; }
|
|
31796
|
+
.noodle-app-fullscreen-exit::before { content: ''; width: 18px; height: 18px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 6 12 12M18 6 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 6 12 12M18 6 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; }
|
|
31797
|
+
.noodle-app-fullscreen-exit:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text, inherit)); background: var(--ns-assistant-hover, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated, var(--ns-app-view-surface, #fff)))); }
|
|
31798
|
+
.noodle-app-fullscreen-exit:focus-visible { outline: 3px solid var(--ns-assistant-focus, var(--ns-assistant-default-focus, #2563eb)); outline-offset: 2px; }
|
|
31799
|
+
.noodle-app-fullscreen-exit:active { transform: scale(.96); }
|
|
31800
|
+
.noodle-app-frame { display: block; width: 100%; min-height: 120px; border: 0; background: transparent; }
|
|
31801
|
+
.noodle-app-fallback { padding: 14px 16px; font-size: 13px; color: var(--ns-assistant-muted, var(--ns-assistant-default-muted, var(--ns-app-view-muted, #6b7280))); }
|
|
31802
|
+
.noodle-app-card[data-fullscreen] { position: fixed; inset: 0; z-index: 2; margin: 0; border-radius: 0; background: var(--ns-assistant-panel, var(--ns-assistant-default-panel, var(--ns-app-view-surface, #fff))); }
|
|
31803
|
+
.noodle-app-card[data-fullscreen] .noodle-app-frame { height: 100% !important; }
|
|
31804
|
+
`;
|
|
31805
|
+
var ASSISTANT_APP_VIEW_STYLES = `<style>
|
|
31806
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
31807
|
+
:host { --ns-app-view-surface: #fff; --ns-app-view-border: #d1d5db; --ns-app-view-muted: #6b7280; display: block; min-width: 0; color: #111827; color-scheme: light; font: inherit; }
|
|
31808
|
+
:host([data-theme="dark"]) { --ns-app-view-surface: #17191f; --ns-app-view-border: #343741; --ns-app-view-muted: #a7adb8; color: #f3f4f6; color-scheme: dark; }
|
|
31809
|
+
:host([hidden]) { display: none; }
|
|
31810
|
+
${ASSISTANT_APP_VIEW_CSS}
|
|
31811
|
+
</style>`;
|
|
31812
|
+
|
|
31730
31813
|
// src/element-styles.ts
|
|
31731
31814
|
var ASSISTANT_ELEMENT_STYLES = `<style>
|
|
31732
31815
|
*, *::before, *::after { box-sizing: border-box; }
|
|
@@ -31829,12 +31912,7 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
|
|
|
31829
31912
|
.input-request input[type="checkbox"] { width: auto; min-height: auto; justify-self: start; accent-color: var(--ns-assistant-accent, var(--ns-assistant-default-accent)); }
|
|
31830
31913
|
.input-request input:focus-visible, .input-request select:focus-visible { border-color: var(--ns-assistant-focus, var(--ns-assistant-default-focus)); box-shadow: 0 0 0 2px var(--ns-assistant-focus, var(--ns-assistant-default-focus)); }
|
|
31831
31914
|
.input-request .proposal-actions { margin-top: 2px; }
|
|
31832
|
-
|
|
31833
|
-
.noodle-app-title { padding: 10px 12px 0; font-size: .86em; font-weight: 650; }
|
|
31834
|
-
.noodle-app-frame { display: block; width: 100%; min-height: 120px; border: 0; background: transparent; }
|
|
31835
|
-
.noodle-app-fallback { padding: 14px 16px; font-size: 13px; color: var(--ns-assistant-muted, var(--ns-assistant-default-muted, #6b7280)); }
|
|
31836
|
-
.noodle-app-card[data-fullscreen] { position: fixed; inset: 0; z-index: 2; margin: 0; border-radius: 0; background: var(--ns-assistant-panel, var(--ns-assistant-default-panel)); }
|
|
31837
|
-
.noodle-app-card[data-fullscreen] .noodle-app-frame { height: 100% !important; }
|
|
31915
|
+
${ASSISTANT_APP_VIEW_CSS}
|
|
31838
31916
|
form { display: flex; flex: 0 0 auto; gap: 8px; align-items: center; min-height: 56px; margin: 8px 16px 16px; padding: 6px 6px 6px 16px; color: var(--ns-assistant-composer-text, inherit); border: 1px solid var(--ns-assistant-composer-border, color-mix(in srgb, var(--ns-assistant-divider, var(--ns-assistant-default-divider)) 86%, transparent)); border-radius: var(--ns-assistant-input-radius, var(--ns-assistant-default-input-radius)); background: var(--ns-assistant-composer, color-mix(in srgb, var(--ns-assistant-input, var(--ns-assistant-default-input)) 92%, transparent)); box-shadow: 0 1px 2px rgba(0,0,0,.04), 0 8px 24px rgba(0,0,0,.035); transition: border-color .15s ease, box-shadow .15s ease; }
|
|
31839
31917
|
form:focus-within { box-shadow: inset 0 0 0 1px var(--ns-assistant-focus, var(--ns-assistant-default-focus)), 0 0 0 2px var(--ns-assistant-focus, var(--ns-assistant-default-focus)); }
|
|
31840
31918
|
textarea { flex: 1; min-height: 24px; max-height: 120px; resize: none; padding: 0; color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: transparent; border: 0; border-radius: 0; outline: 0; box-shadow: none; appearance: none; -webkit-appearance: none; font: inherit; font-size: 16px; line-height: 24px; }
|
|
@@ -32790,33 +32868,28 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
32790
32868
|
this.#setSessionState("error");
|
|
32791
32869
|
}
|
|
32792
32870
|
const detail = error51 instanceof AssistantClientError ? error51.detail : { code: fallbackCode, retryable: false };
|
|
32793
|
-
|
|
32794
|
-
|
|
32871
|
+
const startNewConversation = detail.serviceCode === "session_turn_budget_exhausted";
|
|
32872
|
+
const reconnect = detail.retryable !== false || detail.serviceCode === void 0;
|
|
32873
|
+
const recoveryAction = startNewConversation ? {
|
|
32874
|
+
label: this.#appearance.labels.newConversation,
|
|
32875
|
+
run: () => this.#startNewConversation()
|
|
32876
|
+
} : reconnect ? { label: this.#appearance.labels.reconnect, run: () => this.reconnect() } : void 0;
|
|
32877
|
+
appendConversationRecovery({
|
|
32878
|
+
messages: this.#messages,
|
|
32879
|
+
message: detail.code === "session_expired" ? this.#appearance.labels.sessionExpired : this.#appearance.labels.unavailable,
|
|
32795
32880
|
// A spent or switched-off daily budget offers no retry. Reconnecting cannot succeed, and every
|
|
32796
32881
|
// open tab trying is exactly the load the cap was set to refuse — so the button goes, not just
|
|
32797
32882
|
// the alarming words. A spent *session* keeps it: reconnect mints a fresh one, which is the fix.
|
|
32798
|
-
|
|
32799
|
-
|
|
32883
|
+
...recoveryAction === void 0 ? {} : { action: recoveryAction },
|
|
32884
|
+
revealLatest: () => this.#revealLatest()
|
|
32885
|
+
});
|
|
32800
32886
|
this.#dispatchError(detail);
|
|
32801
32887
|
}
|
|
32802
|
-
#
|
|
32803
|
-
|
|
32804
|
-
this.#
|
|
32805
|
-
|
|
32806
|
-
|
|
32807
|
-
error51.setAttribute("role", offerRetry ? "alert" : "status");
|
|
32808
|
-
const text3 = document.createElement("p");
|
|
32809
|
-
text3.textContent = message;
|
|
32810
|
-
error51.append(text3);
|
|
32811
|
-
if (offerRetry) {
|
|
32812
|
-
const retry = document.createElement("button");
|
|
32813
|
-
retry.type = "button";
|
|
32814
|
-
retry.textContent = this.#appearance.labels.reconnect;
|
|
32815
|
-
retry.addEventListener("click", () => this.reconnect());
|
|
32816
|
-
error51.append(retry);
|
|
32817
|
-
}
|
|
32818
|
-
this.#messages.append(error51);
|
|
32819
|
-
this.#revealLatest();
|
|
32888
|
+
#startNewConversation() {
|
|
32889
|
+
this.resetSession();
|
|
32890
|
+
this.#setSessionState("loading");
|
|
32891
|
+
this.#primeSession();
|
|
32892
|
+
this.dispatchEvent(new CustomEvent("assistant-new-conversation"));
|
|
32820
32893
|
}
|
|
32821
32894
|
#resolvedMode() {
|
|
32822
32895
|
const configured = this.getAttribute("theme") ?? this.#appearance.theme.defaultMode;
|
|
@@ -32994,52 +33067,208 @@ function registerNoodleAssistant() {
|
|
|
32994
33067
|
|
|
32995
33068
|
// src/react-app-view.ts
|
|
32996
33069
|
var import_react = require("react");
|
|
32997
|
-
|
|
32998
|
-
|
|
32999
|
-
|
|
33000
|
-
|
|
33001
|
-
|
|
33002
|
-
|
|
33003
|
-
|
|
33004
|
-
|
|
33005
|
-
|
|
33006
|
-
|
|
33007
|
-
|
|
33008
|
-
|
|
33009
|
-
|
|
33010
|
-
|
|
33011
|
-
|
|
33012
|
-
|
|
33013
|
-
|
|
33014
|
-
|
|
33015
|
-
|
|
33070
|
+
|
|
33071
|
+
// src/app-view-element.ts
|
|
33072
|
+
var APP_VIEW_TAG_NAME = "noodle-app-view";
|
|
33073
|
+
var HTMLElementBase2 = globalThis.HTMLElement ?? class {
|
|
33074
|
+
};
|
|
33075
|
+
function viewIdentity(view) {
|
|
33076
|
+
return `${view.id}\0${view.resourceUri}`;
|
|
33077
|
+
}
|
|
33078
|
+
var NoodleAppViewElement = class extends HTMLElementBase2 {
|
|
33079
|
+
static observedAttributes = ["allow-fullscreen", "theme"];
|
|
33080
|
+
#allowFullscreen = false;
|
|
33081
|
+
#client;
|
|
33082
|
+
#view;
|
|
33083
|
+
#theme = "light";
|
|
33084
|
+
#container;
|
|
33085
|
+
#mounted;
|
|
33086
|
+
#mountedClient;
|
|
33087
|
+
#mountedAllowFullscreen = false;
|
|
33088
|
+
#mountedIdentity;
|
|
33089
|
+
#requestedTeardown;
|
|
33090
|
+
get client() {
|
|
33091
|
+
return this.#client;
|
|
33092
|
+
}
|
|
33093
|
+
/** Allow the hosted App to request fullscreen. Disabled by default. */
|
|
33094
|
+
get allowFullscreen() {
|
|
33095
|
+
return this.#allowFullscreen;
|
|
33096
|
+
}
|
|
33097
|
+
set allowFullscreen(value) {
|
|
33098
|
+
const next = value === true;
|
|
33099
|
+
if (next === this.#allowFullscreen) return;
|
|
33100
|
+
this.#allowFullscreen = next;
|
|
33101
|
+
this.toggleAttribute("allow-fullscreen", next);
|
|
33102
|
+
this.#reconcile();
|
|
33103
|
+
}
|
|
33104
|
+
set client(value) {
|
|
33105
|
+
if (value === this.#client) return;
|
|
33106
|
+
this.#client = value;
|
|
33107
|
+
this.#reconcile();
|
|
33108
|
+
}
|
|
33109
|
+
get view() {
|
|
33110
|
+
return this.#view;
|
|
33111
|
+
}
|
|
33112
|
+
set view(value) {
|
|
33113
|
+
this.#view = value;
|
|
33114
|
+
this.#reconcile();
|
|
33115
|
+
}
|
|
33116
|
+
get theme() {
|
|
33117
|
+
return this.#theme;
|
|
33118
|
+
}
|
|
33119
|
+
set theme(value) {
|
|
33120
|
+
const next = value === "dark" ? "dark" : "light";
|
|
33121
|
+
const changed = next !== this.#theme;
|
|
33122
|
+
this.#theme = next;
|
|
33123
|
+
if (this.getAttribute("data-theme") !== next) this.setAttribute("data-theme", next);
|
|
33124
|
+
if (changed && this.#mounted) updateAssistantAppTheme(this.#mounted, next);
|
|
33125
|
+
}
|
|
33126
|
+
connectedCallback() {
|
|
33127
|
+
this.#ensureContainer();
|
|
33128
|
+
this.#upgradeProperty("allowFullscreen");
|
|
33129
|
+
this.#upgradeProperty("client");
|
|
33130
|
+
this.#upgradeProperty("theme");
|
|
33131
|
+
this.#upgradeProperty("view");
|
|
33132
|
+
this.#reconcile();
|
|
33133
|
+
}
|
|
33134
|
+
disconnectedCallback() {
|
|
33135
|
+
this.#requestedTeardown = void 0;
|
|
33136
|
+
this.#releaseMount();
|
|
33137
|
+
}
|
|
33138
|
+
attributeChangedCallback(name21, _previous, value) {
|
|
33139
|
+
if (name21 === "allow-fullscreen") this.allowFullscreen = value !== null;
|
|
33140
|
+
if (name21 === "theme") this.theme = value === "dark" ? "dark" : "light";
|
|
33141
|
+
}
|
|
33142
|
+
#ensureContainer() {
|
|
33143
|
+
if (this.#container) return this.#container;
|
|
33144
|
+
const root = this.shadowRoot ?? this.attachShadow({ mode: "open" });
|
|
33145
|
+
root.innerHTML = ASSISTANT_APP_VIEW_STYLES;
|
|
33146
|
+
const container = document.createElement("div");
|
|
33147
|
+
container.className = "noodle-app-mount";
|
|
33148
|
+
container.setAttribute("part", "mount");
|
|
33149
|
+
root.append(container);
|
|
33150
|
+
this.#container = container;
|
|
33151
|
+
return container;
|
|
33152
|
+
}
|
|
33153
|
+
#upgradeProperty(name21) {
|
|
33154
|
+
const property = Object.getOwnPropertyDescriptor(this, name21);
|
|
33155
|
+
if (!property) return;
|
|
33156
|
+
Reflect.deleteProperty(this, name21);
|
|
33157
|
+
Reflect.set(this, name21, property.value);
|
|
33158
|
+
}
|
|
33159
|
+
#releaseMount() {
|
|
33160
|
+
const mounted = this.#mounted;
|
|
33161
|
+
this.#mounted = void 0;
|
|
33162
|
+
this.#mountedClient = void 0;
|
|
33163
|
+
this.#mountedAllowFullscreen = false;
|
|
33164
|
+
this.#mountedIdentity = void 0;
|
|
33165
|
+
this.#container?.replaceChildren();
|
|
33166
|
+
if (mounted) void unmountAssistantApp(mounted);
|
|
33167
|
+
}
|
|
33168
|
+
#reconcile() {
|
|
33169
|
+
if (!this.isConnected) return;
|
|
33170
|
+
const client = this.#client;
|
|
33171
|
+
const detail = this.#view;
|
|
33172
|
+
const identity = detail ? viewIdentity(detail) : void 0;
|
|
33173
|
+
if (this.#mounted) {
|
|
33174
|
+
if (client === this.#mountedClient && identity === this.#mountedIdentity && this.#allowFullscreen === this.#mountedAllowFullscreen) {
|
|
33175
|
+
return;
|
|
33176
|
+
}
|
|
33177
|
+
this.#releaseMount();
|
|
33178
|
+
}
|
|
33179
|
+
if (this.#requestedTeardown && (client !== this.#requestedTeardown.client || identity !== this.#requestedTeardown.identity)) {
|
|
33180
|
+
this.#requestedTeardown = void 0;
|
|
33181
|
+
}
|
|
33182
|
+
if (!client || !detail?.html || !identity || this.#requestedTeardown) return;
|
|
33183
|
+
const initialHtml = detail.html;
|
|
33016
33184
|
const sandboxUrl = client.appSandboxUrl?.();
|
|
33017
|
-
|
|
33018
|
-
|
|
33185
|
+
let card;
|
|
33186
|
+
card = mountAssistantApp(
|
|
33187
|
+
detail,
|
|
33019
33188
|
{
|
|
33020
33189
|
client,
|
|
33021
33190
|
sendMessage: (message) => client.sendMessage(message),
|
|
33022
33191
|
updateModelContext: (update) => client.updateModelContext(update),
|
|
33023
|
-
theme:
|
|
33192
|
+
theme: this.#theme
|
|
33024
33193
|
},
|
|
33025
33194
|
{
|
|
33195
|
+
allowFullscreen: this.#allowFullscreen,
|
|
33026
33196
|
...sandboxUrl ? { sandboxUrl } : {},
|
|
33027
|
-
getDetail: () =>
|
|
33028
|
-
|
|
33197
|
+
getDetail: () => {
|
|
33198
|
+
const latest = this.#view;
|
|
33199
|
+
if (this.#client !== client || !latest || viewIdentity(latest) !== identity)
|
|
33200
|
+
return detail;
|
|
33201
|
+
return latest.html ? latest : { ...latest, html: initialHtml };
|
|
33202
|
+
},
|
|
33203
|
+
onRenderFailure: (failure) => {
|
|
33204
|
+
this.dispatchEvent(
|
|
33205
|
+
new CustomEvent("assistant-error", {
|
|
33206
|
+
detail: failure,
|
|
33207
|
+
bubbles: true,
|
|
33208
|
+
composed: true
|
|
33209
|
+
})
|
|
33210
|
+
);
|
|
33211
|
+
},
|
|
33212
|
+
onTeardownRequest: () => {
|
|
33213
|
+
if (this.#mounted !== card) return;
|
|
33214
|
+
this.#mounted = void 0;
|
|
33215
|
+
this.#mountedClient = void 0;
|
|
33216
|
+
this.#mountedIdentity = void 0;
|
|
33217
|
+
this.#requestedTeardown = { client, identity };
|
|
33218
|
+
}
|
|
33029
33219
|
}
|
|
33030
33220
|
);
|
|
33031
33221
|
if (!card) return;
|
|
33032
|
-
mounted
|
|
33033
|
-
|
|
33222
|
+
this.#mounted = card;
|
|
33223
|
+
this.#mountedClient = client;
|
|
33224
|
+
this.#mountedAllowFullscreen = this.#allowFullscreen;
|
|
33225
|
+
this.#mountedIdentity = identity;
|
|
33226
|
+
this.#ensureContainer().replaceChildren(card);
|
|
33227
|
+
}
|
|
33228
|
+
};
|
|
33229
|
+
|
|
33230
|
+
// src/app-view.ts
|
|
33231
|
+
function registerNoodleAppView() {
|
|
33232
|
+
if (!globalThis.customElements?.get(APP_VIEW_TAG_NAME)) {
|
|
33233
|
+
globalThis.customElements?.define(APP_VIEW_TAG_NAME, NoodleAppViewElement);
|
|
33234
|
+
}
|
|
33235
|
+
}
|
|
33236
|
+
registerNoodleAppView();
|
|
33237
|
+
|
|
33238
|
+
// src/react-app-view.ts
|
|
33239
|
+
function NoodleAppView({
|
|
33240
|
+
client,
|
|
33241
|
+
view,
|
|
33242
|
+
theme = "light",
|
|
33243
|
+
allowFullscreen = false,
|
|
33244
|
+
className,
|
|
33245
|
+
onError
|
|
33246
|
+
}) {
|
|
33247
|
+
const elementRef = (0, import_react.useRef)(null);
|
|
33248
|
+
const onErrorRef = (0, import_react.useRef)(onError);
|
|
33249
|
+
onErrorRef.current = onError;
|
|
33250
|
+
(0, import_react.useEffect)(() => {
|
|
33251
|
+
const element = elementRef.current;
|
|
33252
|
+
if (!element) return;
|
|
33253
|
+
const handleError = (event) => {
|
|
33254
|
+
onErrorRef.current?.(event.detail);
|
|
33255
|
+
};
|
|
33256
|
+
element.addEventListener("assistant-error", handleError);
|
|
33257
|
+
registerNoodleAppView();
|
|
33034
33258
|
return () => {
|
|
33035
|
-
|
|
33036
|
-
void unmountAssistantApp(card);
|
|
33259
|
+
element.removeEventListener("assistant-error", handleError);
|
|
33037
33260
|
};
|
|
33038
|
-
}, [
|
|
33261
|
+
}, []);
|
|
33039
33262
|
(0, import_react.useEffect)(() => {
|
|
33040
|
-
|
|
33041
|
-
|
|
33042
|
-
|
|
33263
|
+
const element = elementRef.current;
|
|
33264
|
+
if (!element) return;
|
|
33265
|
+
if (element.client !== client) element.view = void 0;
|
|
33266
|
+
element.allowFullscreen = allowFullscreen;
|
|
33267
|
+
element.client = client;
|
|
33268
|
+
element.theme = theme;
|
|
33269
|
+
element.view = view;
|
|
33270
|
+
}, [allowFullscreen, client, theme, view]);
|
|
33271
|
+
return (0, import_react.createElement)(APP_VIEW_TAG_NAME, { ref: elementRef, class: className });
|
|
33043
33272
|
}
|
|
33044
33273
|
|
|
33045
33274
|
// src/react.ts
|