@noodleseed/assistant 1.23.0 → 1.25.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 +4 -9
- package/dist/{app-view-element-7ZQZLYbL.d.ts → app-view-element-9ojWWYov.d.cts} +3 -2
- package/dist/{app-view-element-1i_w6FDf.d.cts → app-view-element-BM4lral-.d.ts} +3 -2
- package/dist/app-view.cjs +213 -41
- package/dist/app-view.cjs.map +1 -1
- package/dist/app-view.d.cts +3 -3
- package/dist/app-view.d.ts +3 -3
- package/dist/app-view.js +2 -2
- package/dist/{appearance-Cc-eqSbp.d.cts → appearance-B6vSg8Ub.d.cts} +5 -0
- package/dist/{appearance-Cc-eqSbp.d.ts → appearance-B6vSg8Ub.d.ts} +5 -0
- package/dist/{chunk-IBDP6PXQ.js → chunk-7BQHW37I.js} +71 -3
- package/dist/chunk-7BQHW37I.js.map +1 -0
- package/dist/{chunk-5NBHHNI3.js → chunk-LNBUYHL7.js} +2 -2
- package/dist/chunk-LNBUYHL7.js.map +1 -0
- package/dist/{chunk-XKTUXFGX.js → chunk-P32MAR4K.js} +214 -42
- package/dist/chunk-P32MAR4K.js.map +1 -0
- package/dist/{chunk-X7UQDIGS.js → chunk-SGMECNNU.js} +94 -43
- package/dist/chunk-SGMECNNU.js.map +1 -0
- package/dist/{client-Bp_VKpMg.d.ts → client-BkogON2A.d.ts} +11 -1
- package/dist/{client-uo57Swlm.d.cts → client-C07ppTU_.d.cts} +11 -1
- package/dist/client.cjs +70 -2
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +2 -2
- package/dist/client.d.ts +2 -2
- package/dist/client.js +1 -1
- package/dist/embed.global.js +149 -114
- package/dist/index.cjs +396 -105
- 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 +3 -3
- package/dist/react/client.cjs +70 -2
- package/dist/react/client.cjs.map +1 -1
- package/dist/react/client.d.cts +2 -2
- package/dist/react/client.d.ts +2 -2
- package/dist/react/client.js +1 -1
- package/dist/react.cjs +396 -105
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +3 -3
- package/dist/react.d.ts +3 -3
- package/dist/react.js +4 -4
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +3 -1
- package/dist/server.d.ts +3 -1
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-5NBHHNI3.js.map +0 -1
- package/dist/chunk-IBDP6PXQ.js.map +0 -1
- package/dist/chunk-X7UQDIGS.js.map +0 -1
- package/dist/chunk-XKTUXFGX.js.map +0 -1
package/dist/react.cjs
CHANGED
|
@@ -15197,7 +15197,7 @@ __export(react_exports, {
|
|
|
15197
15197
|
module.exports = __toCommonJS(react_exports);
|
|
15198
15198
|
var import_react2 = require("react");
|
|
15199
15199
|
|
|
15200
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
|
|
15200
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
|
|
15201
15201
|
init_v4();
|
|
15202
15202
|
var RELATED_TASK_META_KEY = "io.modelcontextprotocol/related-task";
|
|
15203
15203
|
var JSONRPC_VERSION = "2.0";
|
|
@@ -20594,7 +20594,7 @@ var pipelineType = ZodPipeline.create;
|
|
|
20594
20594
|
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/mini/parse.js
|
|
20595
20595
|
init_core2();
|
|
20596
20596
|
|
|
20597
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
|
|
20597
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
|
|
20598
20598
|
function isZ4Schema(s2) {
|
|
20599
20599
|
const schema = s2;
|
|
20600
20600
|
return !!schema._zod;
|
|
@@ -20657,7 +20657,7 @@ function getLiteralValue(schema) {
|
|
|
20657
20657
|
return void 0;
|
|
20658
20658
|
}
|
|
20659
20659
|
|
|
20660
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
|
|
20660
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
|
|
20661
20661
|
function isTerminal(status) {
|
|
20662
20662
|
return status === "completed" || status === "failed" || status === "cancelled";
|
|
20663
20663
|
}
|
|
@@ -20665,7 +20665,7 @@ function isTerminal(status) {
|
|
|
20665
20665
|
// ../../node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@4.4.3/node_modules/zod-to-json-schema/dist/esm/parsers/string.js
|
|
20666
20666
|
var ALPHA_NUMERIC = new Set("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789");
|
|
20667
20667
|
|
|
20668
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
|
|
20668
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
|
|
20669
20669
|
function getMethodLiteral(schema) {
|
|
20670
20670
|
const shape = getObjectShape(schema);
|
|
20671
20671
|
const methodSchema = shape?.method;
|
|
@@ -20686,7 +20686,7 @@ function parseWithCompat(schema, data) {
|
|
|
20686
20686
|
return result.data;
|
|
20687
20687
|
}
|
|
20688
20688
|
|
|
20689
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
|
|
20689
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
|
|
20690
20690
|
var DEFAULT_REQUEST_TIMEOUT_MSEC = 6e4;
|
|
20691
20691
|
var Protocol = class {
|
|
20692
20692
|
constructor(_options) {
|
|
@@ -21798,6 +21798,15 @@ var E = class {
|
|
|
21798
21798
|
sessionId;
|
|
21799
21799
|
setProtocolVersion;
|
|
21800
21800
|
};
|
|
21801
|
+
function AZ(X2) {
|
|
21802
|
+
if (!X2) return "";
|
|
21803
|
+
let Y = [];
|
|
21804
|
+
if (X2.camera) Y.push("camera");
|
|
21805
|
+
if (X2.microphone) Y.push("microphone");
|
|
21806
|
+
if (X2.geolocation) Y.push("geolocation");
|
|
21807
|
+
if (X2.clipboardWrite) Y.push("clipboard-write");
|
|
21808
|
+
return Y.join("; ");
|
|
21809
|
+
}
|
|
21801
21810
|
var KX = [j];
|
|
21802
21811
|
var DX = class extends _ {
|
|
21803
21812
|
_client;
|
|
@@ -22068,34 +22077,131 @@ function GX(X2, Y) {
|
|
|
22068
22077
|
return JSON.stringify(X2) === JSON.stringify(Y);
|
|
22069
22078
|
}
|
|
22070
22079
|
|
|
22080
|
+
// src/app-sandbox-policy.ts
|
|
22081
|
+
var MAX_DOMAINS_PER_DIRECTIVE = 32;
|
|
22082
|
+
function isRecord(value) {
|
|
22083
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22084
|
+
}
|
|
22085
|
+
function isLoopback(hostname3) {
|
|
22086
|
+
return hostname3 === "localhost" || hostname3 === "127.0.0.1" || hostname3 === "[::1]";
|
|
22087
|
+
}
|
|
22088
|
+
function normalizeDomain(value, connect) {
|
|
22089
|
+
if (value.length > 512 || /[;\r\n'"\s]/u.test(value)) return void 0;
|
|
22090
|
+
try {
|
|
22091
|
+
const parsed = new URL(value);
|
|
22092
|
+
const secure = parsed.protocol === "https:" || connect && parsed.protocol === "wss:";
|
|
22093
|
+
const local = isLoopback(parsed.hostname) && (parsed.protocol === "http:" || connect && parsed.protocol === "ws:");
|
|
22094
|
+
if (!secure && !local) return void 0;
|
|
22095
|
+
if (parsed.username || parsed.password || parsed.pathname !== "/" || parsed.search || parsed.hash) {
|
|
22096
|
+
return void 0;
|
|
22097
|
+
}
|
|
22098
|
+
return parsed.origin;
|
|
22099
|
+
} catch {
|
|
22100
|
+
return void 0;
|
|
22101
|
+
}
|
|
22102
|
+
}
|
|
22103
|
+
function normalizeDomains(values, connect) {
|
|
22104
|
+
const normalized = [
|
|
22105
|
+
...new Set(
|
|
22106
|
+
values.slice(0, MAX_DOMAINS_PER_DIRECTIVE).map((value) => typeof value === "string" ? normalizeDomain(value, connect) : void 0).filter((value) => value !== void 0)
|
|
22107
|
+
)
|
|
22108
|
+
];
|
|
22109
|
+
return normalized;
|
|
22110
|
+
}
|
|
22111
|
+
function resolveAssistantAppSandboxPolicy(resourceMeta) {
|
|
22112
|
+
if (!isRecord(resourceMeta)) return {};
|
|
22113
|
+
const rawCsp = resourceMeta.csp;
|
|
22114
|
+
const csp = isRecord(rawCsp) ? {
|
|
22115
|
+
...Array.isArray(rawCsp.connectDomains) ? { connectDomains: normalizeDomains(rawCsp.connectDomains, true) } : {},
|
|
22116
|
+
...Array.isArray(rawCsp.resourceDomains) ? { resourceDomains: normalizeDomains(rawCsp.resourceDomains, false) } : {},
|
|
22117
|
+
...Array.isArray(rawCsp.frameDomains) ? { frameDomains: normalizeDomains(rawCsp.frameDomains, false) } : {},
|
|
22118
|
+
...Array.isArray(rawCsp.baseUriDomains) ? { baseUriDomains: normalizeDomains(rawCsp.baseUriDomains, false) } : {}
|
|
22119
|
+
} : void 0;
|
|
22120
|
+
const rawPermissions = resourceMeta.permissions;
|
|
22121
|
+
const permissions = isRecord(rawPermissions) ? {
|
|
22122
|
+
...isRecord(rawPermissions.camera) ? { camera: {} } : {},
|
|
22123
|
+
...isRecord(rawPermissions.microphone) ? { microphone: {} } : {},
|
|
22124
|
+
...isRecord(rawPermissions.geolocation) ? { geolocation: {} } : {},
|
|
22125
|
+
...isRecord(rawPermissions.clipboardWrite) ? { clipboardWrite: {} } : {}
|
|
22126
|
+
} : void 0;
|
|
22127
|
+
const allowAttribute = AZ(permissions);
|
|
22128
|
+
return {
|
|
22129
|
+
...csp === void 0 ? {} : { csp },
|
|
22130
|
+
...permissions === void 0 ? {} : { permissions },
|
|
22131
|
+
...allowAttribute ? { allowAttribute } : {}
|
|
22132
|
+
};
|
|
22133
|
+
}
|
|
22134
|
+
function assistantAppSandboxUrl(sandboxUrl, policy) {
|
|
22135
|
+
const parsed = new URL(sandboxUrl);
|
|
22136
|
+
if (policy.csp) parsed.searchParams.set("csp", JSON.stringify(policy.csp));
|
|
22137
|
+
const parentOrigin = globalThis.location?.origin;
|
|
22138
|
+
if (parentOrigin && parentOrigin !== "null") {
|
|
22139
|
+
parsed.hash = new URLSearchParams({ parentOrigin }).toString();
|
|
22140
|
+
}
|
|
22141
|
+
return parsed.href;
|
|
22142
|
+
}
|
|
22143
|
+
|
|
22071
22144
|
// src/app-host.ts
|
|
22072
|
-
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>
|
|
22073
|
-
let inner;
|
|
22145
|
+
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><body><script>
|
|
22146
|
+
let inner,loaded=false;
|
|
22147
|
+
if(self===top)throw new Error('The assistant sandbox relay must be embedded');
|
|
22148
|
+
const standardSandbox='allow-scripts allow-same-origin allow-forms';
|
|
22149
|
+
const rawParentOrigin=new URLSearchParams(location.hash.slice(1)).get('parentOrigin');
|
|
22150
|
+
let expectedParentOrigin;
|
|
22151
|
+
try{const parsed=new URL(rawParentOrigin||'');if(parsed.origin===rawParentOrigin&&/^https?:$/.test(parsed.protocol))expectedParentOrigin=parsed.origin}catch{}
|
|
22152
|
+
const parentTarget=expectedParentOrigin||'*';
|
|
22153
|
+
const ownOrigin=self.origin;
|
|
22074
22154
|
const ready={jsonrpc:'2.0',method:'ui/notifications/sandbox-proxy-ready',params:{}};
|
|
22075
22155
|
// Re-announce until the host acknowledges with the resource: when this document is hosted
|
|
22076
22156
|
// cross-origin, the first announcement can arrive before the host's load handler is listening.
|
|
22077
|
-
const announce=setInterval(()=>parent.postMessage(ready,
|
|
22157
|
+
const announce=setInterval(()=>parent.postMessage(ready,parentTarget),120);
|
|
22078
22158
|
setTimeout(()=>clearInterval(announce),15000);
|
|
22079
22159
|
addEventListener('message',(event)=>{
|
|
22080
22160
|
if(event.source===parent){
|
|
22161
|
+
if(expectedParentOrigin&&event.origin!==expectedParentOrigin)return;
|
|
22081
22162
|
const message=event.data;
|
|
22082
22163
|
if(message?.method==='ui/notifications/sandbox-resource-ready'){
|
|
22083
22164
|
clearInterval(announce);
|
|
22084
|
-
if(
|
|
22165
|
+
if(loaded)return;
|
|
22166
|
+
loaded=true;
|
|
22167
|
+
const requestedSandbox=message.params?.sandbox;
|
|
22085
22168
|
inner=document.createElement('iframe');
|
|
22086
|
-
inner.setAttribute('sandbox',
|
|
22169
|
+
inner.setAttribute('sandbox',requestedSandbox===standardSandbox?standardSandbox:'allow-scripts');
|
|
22087
22170
|
inner.setAttribute('referrerpolicy','no-referrer');
|
|
22088
|
-
|
|
22089
|
-
|
|
22171
|
+
const permissions=message.params?.permissions;
|
|
22172
|
+
const allow=[];
|
|
22173
|
+
if(permissions?.camera)allow.push('camera');
|
|
22174
|
+
if(permissions?.microphone)allow.push('microphone');
|
|
22175
|
+
if(permissions?.geolocation)allow.push('geolocation');
|
|
22176
|
+
if(permissions?.clipboardWrite)allow.push('clipboard-write');
|
|
22177
|
+
if(allow.length)inner.setAttribute('allow',allow.join('; '));
|
|
22178
|
+
document.body.append(inner);
|
|
22179
|
+
let html=String(message.params?.html||'');
|
|
22180
|
+
const csp=message.params?.csp;
|
|
22181
|
+
if(csp&&typeof csp==='object'){
|
|
22182
|
+
const list=(value,fallback)=>Array.isArray(value)&&value.length?value.join(' '):fallback;
|
|
22183
|
+
const resources=Array.isArray(csp.resourceDomains)?csp.resourceDomains:[];
|
|
22184
|
+
const suffix=resources.length?' '+resources.join(' '):'';
|
|
22185
|
+
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('; ');
|
|
22186
|
+
const meta='<meta http-equiv="Content-Security-Policy" content="'+policy.replace(/&/g,'&').replace(/"/g,'"')+'">';
|
|
22187
|
+
const doctype=html.match(/^\\s*<!doctype[^>]*>/i);
|
|
22188
|
+
html=doctype?html.slice(0,doctype[0].length)+meta+html.slice(doctype[0].length):meta+html;
|
|
22189
|
+
}
|
|
22190
|
+
try{
|
|
22191
|
+
const doc=inner.contentDocument||inner.contentWindow?.document;
|
|
22192
|
+
if(!doc)throw new Error('document unavailable');
|
|
22193
|
+
doc.open();doc.write(html);doc.close();
|
|
22194
|
+
}catch{inner.srcdoc=html}
|
|
22090
22195
|
return;
|
|
22091
22196
|
}
|
|
22092
22197
|
inner?.contentWindow?.postMessage(message,'*');
|
|
22093
22198
|
} else if(inner && event.source===inner.contentWindow) {
|
|
22094
|
-
|
|
22199
|
+
if(event.origin!==ownOrigin)return;
|
|
22200
|
+
parent.postMessage(event.data,parentTarget);
|
|
22095
22201
|
}
|
|
22096
22202
|
});
|
|
22097
|
-
parent.postMessage(ready,
|
|
22098
|
-
</script>`;
|
|
22203
|
+
parent.postMessage(ready,parentTarget);
|
|
22204
|
+
</script></body>`;
|
|
22099
22205
|
function isAllowedAppLink(value, allowedDomains, baseUrl) {
|
|
22100
22206
|
try {
|
|
22101
22207
|
const parsed = new URL(value, baseUrl);
|
|
@@ -22122,16 +22228,42 @@ function createAssistantAppHostContext(theme, allowFullscreen = false, displayMo
|
|
|
22122
22228
|
}
|
|
22123
22229
|
var APP_RENDER_TIMEOUT_MS = 1e4;
|
|
22124
22230
|
var APP_TEARDOWN_TIMEOUT_MS = 1e3;
|
|
22231
|
+
var STANDARD_SANDBOX = "allow-scripts allow-same-origin allow-forms";
|
|
22125
22232
|
var mountedApps = /* @__PURE__ */ new WeakMap();
|
|
22126
22233
|
function resolveSandboxUrl(value) {
|
|
22127
22234
|
if (!value) return void 0;
|
|
22128
22235
|
try {
|
|
22129
22236
|
const parsed = new URL(value);
|
|
22130
|
-
|
|
22237
|
+
const loopback = parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "[::1]";
|
|
22238
|
+
const permittedProtocol = parsed.protocol === "https:" || parsed.protocol === "http:" && loopback;
|
|
22239
|
+
const embedderOrigin = globalThis.location?.origin;
|
|
22240
|
+
if (!permittedProtocol || embedderOrigin && embedderOrigin !== "null" && parsed.origin === embedderOrigin) {
|
|
22241
|
+
return void 0;
|
|
22242
|
+
}
|
|
22243
|
+
return parsed.href;
|
|
22131
22244
|
} catch {
|
|
22132
22245
|
return void 0;
|
|
22133
22246
|
}
|
|
22134
22247
|
}
|
|
22248
|
+
function copyAppJson(value, depth = 0) {
|
|
22249
|
+
if (depth > 64) throw new Error("App payload nesting exceeds the host limit");
|
|
22250
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return value;
|
|
22251
|
+
if (typeof value === "number") {
|
|
22252
|
+
if (!Number.isFinite(value)) throw new Error("App payload numbers must be finite");
|
|
22253
|
+
return value;
|
|
22254
|
+
}
|
|
22255
|
+
if (Array.isArray(value)) return value.map((entry) => copyAppJson(entry, depth + 1));
|
|
22256
|
+
const copied = {};
|
|
22257
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
22258
|
+
Object.defineProperty(copied, key, {
|
|
22259
|
+
value: copyAppJson(entry, depth + 1),
|
|
22260
|
+
enumerable: true,
|
|
22261
|
+
configurable: true,
|
|
22262
|
+
writable: true
|
|
22263
|
+
});
|
|
22264
|
+
}
|
|
22265
|
+
return copied;
|
|
22266
|
+
}
|
|
22135
22267
|
function mountAssistantApp(detail, actions, options = {}) {
|
|
22136
22268
|
if (!detail.html) return void 0;
|
|
22137
22269
|
const card = document.createElement("section");
|
|
@@ -22152,16 +22284,25 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
22152
22284
|
const frame = document.createElement("iframe");
|
|
22153
22285
|
frame.className = "noodle-app-frame";
|
|
22154
22286
|
frame.title = detail.title ?? detail.tool;
|
|
22155
|
-
|
|
22287
|
+
const policy = resolveAssistantAppSandboxPolicy(detail.resourceMeta);
|
|
22156
22288
|
frame.setAttribute("referrerpolicy", "no-referrer");
|
|
22157
22289
|
const sandboxUrl = resolveSandboxUrl(options.sandboxUrl);
|
|
22158
|
-
|
|
22159
|
-
|
|
22290
|
+
const appliedPolicy = sandboxUrl ? policy : { csp: policy.csp ?? {} };
|
|
22291
|
+
if (sandboxUrl) {
|
|
22292
|
+
frame.setAttribute("sandbox", STANDARD_SANDBOX);
|
|
22293
|
+
if (policy.allowAttribute) frame.setAttribute("allow", policy.allowAttribute);
|
|
22294
|
+
frame.src = assistantAppSandboxUrl(sandboxUrl, policy);
|
|
22295
|
+
} else {
|
|
22296
|
+
frame.setAttribute("sandbox", "allow-scripts");
|
|
22297
|
+
frame.srcdoc = PROXY_DOCUMENT;
|
|
22298
|
+
}
|
|
22160
22299
|
card.append(frame);
|
|
22161
22300
|
let mountedBridge;
|
|
22162
22301
|
let mountedTransport;
|
|
22163
22302
|
let destroyed = false;
|
|
22164
22303
|
let initialized = false;
|
|
22304
|
+
let renderFailed = false;
|
|
22305
|
+
let renderStage = "sandbox_load";
|
|
22165
22306
|
let currentTheme = actions.theme;
|
|
22166
22307
|
let displayMode = "inline";
|
|
22167
22308
|
let hostContext = createAssistantAppHostContext(
|
|
@@ -22170,6 +22311,15 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
22170
22311
|
displayMode
|
|
22171
22312
|
);
|
|
22172
22313
|
let destroyPromise;
|
|
22314
|
+
let transportClosePromise;
|
|
22315
|
+
let renderTimer;
|
|
22316
|
+
const closeTransport = () => {
|
|
22317
|
+
if (transportClosePromise) return transportClosePromise;
|
|
22318
|
+
const closing = mountedTransport?.close().catch(() => {
|
|
22319
|
+
}) ?? Promise.resolve();
|
|
22320
|
+
transportClosePromise = closing;
|
|
22321
|
+
return closing;
|
|
22322
|
+
};
|
|
22173
22323
|
const applyDisplayMode = (requestedMode) => {
|
|
22174
22324
|
displayMode = requestedMode === "fullscreen" && options.allowFullscreen === true ? "fullscreen" : "inline";
|
|
22175
22325
|
card.toggleAttribute("data-fullscreen", displayMode === "fullscreen");
|
|
@@ -22187,18 +22337,26 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
22187
22337
|
applyDisplayMode("inline");
|
|
22188
22338
|
frame.focus();
|
|
22189
22339
|
});
|
|
22190
|
-
const
|
|
22191
|
-
if (initialized || !frame.isConnected)
|
|
22340
|
+
const showRenderFailure = (code) => {
|
|
22341
|
+
if (code === "view_render_timeout" && initialized || destroyed || renderFailed || !frame.isConnected)
|
|
22342
|
+
return;
|
|
22343
|
+
renderFailed = true;
|
|
22344
|
+
clearTimeout(renderTimer);
|
|
22192
22345
|
const note = document.createElement("div");
|
|
22193
22346
|
note.className = "noodle-app-fallback";
|
|
22194
22347
|
note.textContent = "This app view could not be displayed.";
|
|
22195
22348
|
frame.replaceWith(note);
|
|
22196
|
-
options.onRenderFailure?.({ code
|
|
22349
|
+
options.onRenderFailure?.({ code, retryable: false, stage: renderStage });
|
|
22350
|
+
void closeTransport();
|
|
22351
|
+
};
|
|
22352
|
+
renderTimer = setTimeout(() => {
|
|
22353
|
+
showRenderFailure("view_render_timeout");
|
|
22197
22354
|
}, APP_RENDER_TIMEOUT_MS);
|
|
22198
22355
|
frame.addEventListener(
|
|
22199
22356
|
"load",
|
|
22200
22357
|
() => {
|
|
22201
|
-
if (destroyed) return;
|
|
22358
|
+
if (destroyed || renderFailed) return;
|
|
22359
|
+
renderStage = "sandbox_proxy";
|
|
22202
22360
|
const target = frame.contentWindow;
|
|
22203
22361
|
if (!target) return;
|
|
22204
22362
|
const bridge = new DX(
|
|
@@ -22209,7 +22367,11 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
22209
22367
|
serverTools: {},
|
|
22210
22368
|
serverResources: {},
|
|
22211
22369
|
updateModelContext: { text: {}, structuredContent: {} },
|
|
22212
|
-
message: { text: {} }
|
|
22370
|
+
message: { text: {} },
|
|
22371
|
+
sandbox: {
|
|
22372
|
+
...appliedPolicy.csp === void 0 ? {} : { csp: appliedPolicy.csp },
|
|
22373
|
+
...appliedPolicy.permissions === void 0 ? {} : { permissions: appliedPolicy.permissions }
|
|
22374
|
+
}
|
|
22213
22375
|
},
|
|
22214
22376
|
{
|
|
22215
22377
|
hostContext
|
|
@@ -22217,13 +22379,15 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
22217
22379
|
);
|
|
22218
22380
|
mountedBridge = bridge;
|
|
22219
22381
|
bridge.onsandboxready = () => {
|
|
22220
|
-
if (destroyed) return;
|
|
22382
|
+
if (destroyed || renderFailed) return;
|
|
22383
|
+
renderStage = "app_initialize";
|
|
22221
22384
|
const current = options.getDetail?.() ?? detail;
|
|
22222
22385
|
void bridge.sendSandboxResourceReady({
|
|
22223
22386
|
html: current.html,
|
|
22224
|
-
sandbox: "allow-scripts",
|
|
22225
|
-
...
|
|
22226
|
-
|
|
22387
|
+
sandbox: sandboxUrl ? STANDARD_SANDBOX : "allow-scripts",
|
|
22388
|
+
...appliedPolicy.csp === void 0 ? {} : { csp: appliedPolicy.csp },
|
|
22389
|
+
...appliedPolicy.permissions === void 0 ? {} : { permissions: appliedPolicy.permissions }
|
|
22390
|
+
}).catch(() => showRenderFailure("view_bridge_error"));
|
|
22227
22391
|
};
|
|
22228
22392
|
bridge.onsizechange = ({ height }) => {
|
|
22229
22393
|
if (destroyed) return;
|
|
@@ -22287,21 +22451,30 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
22287
22451
|
return await actions.client.requestApp("resources/read", params);
|
|
22288
22452
|
};
|
|
22289
22453
|
bridge.oninitialized = () => {
|
|
22290
|
-
if (destroyed) return;
|
|
22291
|
-
|
|
22292
|
-
|
|
22293
|
-
|
|
22294
|
-
|
|
22295
|
-
|
|
22296
|
-
|
|
22297
|
-
|
|
22298
|
-
|
|
22299
|
-
|
|
22454
|
+
if (destroyed || renderFailed) return;
|
|
22455
|
+
try {
|
|
22456
|
+
const current = options.getDetail?.() ?? detail;
|
|
22457
|
+
const copiedArguments = copyAppJson(current.arguments ?? {});
|
|
22458
|
+
const copiedResult = copyAppJson(current.result);
|
|
22459
|
+
const argumentsRecord = typeof copiedArguments === "object" && copiedArguments !== null && !Array.isArray(copiedArguments) ? copiedArguments : {};
|
|
22460
|
+
initialized = true;
|
|
22461
|
+
clearTimeout(renderTimer);
|
|
22462
|
+
bridge.setHostContext(hostContext);
|
|
22463
|
+
void Promise.all([
|
|
22464
|
+
bridge.sendToolInput({ arguments: argumentsRecord }),
|
|
22465
|
+
bridge.sendToolResult({
|
|
22466
|
+
content: [{ type: "text", text: JSON.stringify(copiedResult) }],
|
|
22467
|
+
...typeof copiedResult === "object" && copiedResult !== null && !Array.isArray(copiedResult) ? { structuredContent: copiedResult } : {}
|
|
22468
|
+
})
|
|
22469
|
+
]).catch(() => showRenderFailure("view_bridge_error"));
|
|
22470
|
+
} catch {
|
|
22471
|
+
showRenderFailure("view_bridge_error");
|
|
22472
|
+
}
|
|
22300
22473
|
};
|
|
22301
22474
|
const transport = new E(target, target);
|
|
22302
22475
|
mountedTransport = transport;
|
|
22303
22476
|
void bridge.connect(transport).catch(() => {
|
|
22304
|
-
|
|
22477
|
+
showRenderFailure("view_bridge_error");
|
|
22305
22478
|
});
|
|
22306
22479
|
},
|
|
22307
22480
|
{ once: true }
|
|
@@ -22327,8 +22500,7 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
22327
22500
|
}
|
|
22328
22501
|
} catch {
|
|
22329
22502
|
}
|
|
22330
|
-
await
|
|
22331
|
-
});
|
|
22503
|
+
await closeTransport();
|
|
22332
22504
|
card.remove();
|
|
22333
22505
|
mountedApps.delete(card);
|
|
22334
22506
|
})();
|
|
@@ -22451,13 +22623,19 @@ var DEFAULT_APPEARANCE = {
|
|
|
22451
22623
|
copy: "Copy",
|
|
22452
22624
|
newMessages: "New messages",
|
|
22453
22625
|
reconnect: "Reconnect",
|
|
22626
|
+
newConversation: "New conversation",
|
|
22454
22627
|
retry: "Try again",
|
|
22455
22628
|
unavailable: "The assistant is temporarily unavailable.",
|
|
22456
22629
|
sessionExpired: "Your assistant session expired. Reopen it to continue.",
|
|
22457
22630
|
sessionIdle: "Assistant session idle",
|
|
22458
22631
|
sessionLoading: "Assistant session loading",
|
|
22459
22632
|
sessionReady: "Assistant session ready",
|
|
22460
|
-
sessionError: "Assistant session unavailable"
|
|
22633
|
+
sessionError: "Assistant session unavailable",
|
|
22634
|
+
signInHeading: "Sign in to continue",
|
|
22635
|
+
signInBody: "",
|
|
22636
|
+
signInAction: "Sign in",
|
|
22637
|
+
// Empty means no sign-up button: authoring the label is the opt-in (ADR 0201, 2026-08-22).
|
|
22638
|
+
signUpAction: ""
|
|
22461
22639
|
},
|
|
22462
22640
|
presentation: {
|
|
22463
22641
|
panel: {
|
|
@@ -27097,6 +27275,9 @@ var AssistantChatStateStore = class {
|
|
|
27097
27275
|
})
|
|
27098
27276
|
);
|
|
27099
27277
|
return;
|
|
27278
|
+
case "auth_requested":
|
|
27279
|
+
this.#writeStandaloneData(() => this.#writeData("sign-in", event.data.id, event.data));
|
|
27280
|
+
return;
|
|
27100
27281
|
case "tool_completed":
|
|
27101
27282
|
this.#writeData("tool-result", event.data.id, event.data);
|
|
27102
27283
|
return;
|
|
@@ -27321,14 +27502,14 @@ function toChatError(error51) {
|
|
|
27321
27502
|
}
|
|
27322
27503
|
function readErrorDetail(error51) {
|
|
27323
27504
|
const detail = Reflect.get(error51, "detail");
|
|
27324
|
-
if (!
|
|
27505
|
+
if (!isRecord2(detail) || typeof detail.code !== "string") return void 0;
|
|
27325
27506
|
return {
|
|
27326
27507
|
code: detail.code,
|
|
27327
27508
|
...typeof detail.status === "number" ? { status: detail.status } : {},
|
|
27328
27509
|
retryable: detail.retryable === true
|
|
27329
27510
|
};
|
|
27330
27511
|
}
|
|
27331
|
-
function
|
|
27512
|
+
function isRecord2(value) {
|
|
27332
27513
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27333
27514
|
}
|
|
27334
27515
|
|
|
@@ -27355,13 +27536,14 @@ var AssistantClientError = class extends Error {
|
|
|
27355
27536
|
}
|
|
27356
27537
|
};
|
|
27357
27538
|
function parseSession(value) {
|
|
27358
|
-
if (!
|
|
27539
|
+
if (!isRecord3(value) || !isRecord3(value.endpoints)) {
|
|
27359
27540
|
throw clientError("session_failed", "Assistant session response is invalid", true);
|
|
27360
27541
|
}
|
|
27361
27542
|
const interactions = value.endpoints.interactions;
|
|
27362
27543
|
const apps = value.endpoints.apps;
|
|
27363
27544
|
const sandbox = value.endpoints.sandbox;
|
|
27364
|
-
|
|
27545
|
+
const transcript = value.endpoints.transcript;
|
|
27546
|
+
if (typeof value.token !== "string" || typeof value.expiresAt !== "string" || typeof value.endpoints.turns !== "string" || typeof value.endpoints.toolConfirmations !== "string" || interactions !== void 0 && typeof interactions !== "string" || apps !== void 0 && typeof apps !== "string" || sandbox !== void 0 && typeof sandbox !== "string" || transcript !== void 0 && typeof transcript !== "string") {
|
|
27365
27547
|
throw clientError("session_failed", "Assistant session response is invalid", true);
|
|
27366
27548
|
}
|
|
27367
27549
|
return {
|
|
@@ -27372,13 +27554,14 @@ function parseSession(value) {
|
|
|
27372
27554
|
toolConfirmations: value.endpoints.toolConfirmations,
|
|
27373
27555
|
...typeof interactions === "string" ? { interactions } : {},
|
|
27374
27556
|
...typeof apps === "string" ? { apps } : {},
|
|
27375
|
-
...typeof sandbox === "string" ? { sandbox } : {}
|
|
27557
|
+
...typeof sandbox === "string" ? { sandbox } : {},
|
|
27558
|
+
...typeof transcript === "string" ? { transcript } : {}
|
|
27376
27559
|
},
|
|
27377
|
-
...
|
|
27378
|
-
...
|
|
27560
|
+
...isRecord3(value.configuration) ? { configuration: value.configuration } : {},
|
|
27561
|
+
...isRecord3(value.resume) && typeof value.resume.tool === "string" ? { resume: { tool: value.resume.tool } } : {}
|
|
27379
27562
|
};
|
|
27380
27563
|
}
|
|
27381
|
-
function
|
|
27564
|
+
function isRecord3(value) {
|
|
27382
27565
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27383
27566
|
}
|
|
27384
27567
|
async function readStableErrorCode(response) {
|
|
@@ -27388,7 +27571,7 @@ async function readStableErrorCode(response) {
|
|
|
27388
27571
|
} catch {
|
|
27389
27572
|
return void 0;
|
|
27390
27573
|
}
|
|
27391
|
-
if (!
|
|
27574
|
+
if (!isRecord3(value) || typeof value.code !== "string") return void 0;
|
|
27392
27575
|
return /^[A-Za-z0-9_.-]{1,64}$/.test(value.code) ? value.code : void 0;
|
|
27393
27576
|
}
|
|
27394
27577
|
function clientError(code, message, retryable, status, options, serviceCode) {
|
|
@@ -27419,12 +27602,12 @@ function toAssistantClientEvent(event) {
|
|
|
27419
27602
|
}
|
|
27420
27603
|
break;
|
|
27421
27604
|
case "tool_proposed":
|
|
27422
|
-
if (hasString(value, "id") && hasString(value, "tool") && hasOptionalString(value.title) && hasOptionalString(value.description) && hasOptionalJson(value.arguments) && (value.reviewSchema === void 0 ||
|
|
27605
|
+
if (hasString(value, "id") && hasString(value, "tool") && hasOptionalString(value.title) && hasOptionalString(value.description) && hasOptionalJson(value.arguments) && (value.reviewSchema === void 0 || isRecord4(value.reviewSchema)) && hasOptionalString(value.expiresAt) && (value.requiresConfirmation === void 0 || value.requiresConfirmation === true) && hasOptionalTurnId(value)) {
|
|
27423
27606
|
return event;
|
|
27424
27607
|
}
|
|
27425
27608
|
break;
|
|
27426
27609
|
case "input_requested":
|
|
27427
|
-
if (hasString(value, "id") && hasString(value, "message") &&
|
|
27610
|
+
if (hasString(value, "id") && hasString(value, "message") && isRecord4(value.requestedSchema) && hasString(value, "expiresAt") && hasOptionalTurnId(value)) {
|
|
27428
27611
|
return event;
|
|
27429
27612
|
}
|
|
27430
27613
|
break;
|
|
@@ -27468,7 +27651,7 @@ function toAssistantClientEvent(event) {
|
|
|
27468
27651
|
return { event: "unrecognized", data: { name: event.event, payload: value } };
|
|
27469
27652
|
}
|
|
27470
27653
|
function isViewAvailableDetail(value) {
|
|
27471
|
-
return hasString(value, "id") && hasString(value, "tool") && typeof value.resourceUri === "string" && value.resourceUri.startsWith("ui://") && hasOptionalString(value.title) && (value.replayed === void 0 || value.replayed === true) && isJsonValue(value.result, 0) && hasOptionalJson(value.arguments) && hasOptionalString(value.html) && (value.resourceMeta === void 0 ||
|
|
27654
|
+
return hasString(value, "id") && hasString(value, "tool") && typeof value.resourceUri === "string" && value.resourceUri.startsWith("ui://") && hasOptionalString(value.title) && (value.replayed === void 0 || value.replayed === true) && isJsonValue(value.result, 0) && hasOptionalJson(value.arguments) && hasOptionalString(value.html) && (value.resourceMeta === void 0 || isRecord4(value.resourceMeta)) && (value.allowedOpenDomains === void 0 || Array.isArray(value.allowedOpenDomains) && value.allowedOpenDomains.every(isHttpsUrl)) && hasOptionalTurnId(value);
|
|
27472
27655
|
}
|
|
27473
27656
|
function isHttpsUrl(value) {
|
|
27474
27657
|
if (typeof value !== "string") return false;
|
|
@@ -27501,11 +27684,11 @@ function isJsonValue(value, depth) {
|
|
|
27501
27684
|
if (Array.isArray(value)) {
|
|
27502
27685
|
return value.length <= 256 && value.every((entry) => isJsonValue(entry, depth + 1));
|
|
27503
27686
|
}
|
|
27504
|
-
if (!
|
|
27687
|
+
if (!isRecord4(value)) return false;
|
|
27505
27688
|
const entries2 = Object.entries(value);
|
|
27506
27689
|
return entries2.length <= 256 && entries2.every(([, entry]) => isJsonValue(entry, depth + 1));
|
|
27507
27690
|
}
|
|
27508
|
-
function
|
|
27691
|
+
function isRecord4(value) {
|
|
27509
27692
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27510
27693
|
}
|
|
27511
27694
|
|
|
@@ -27527,6 +27710,43 @@ function sessionSourceKey(options) {
|
|
|
27527
27710
|
return `${options.embedId ?? ""}|${options.serviceUrl ?? ""}|${options.sessionEndpoint ?? ""}`;
|
|
27528
27711
|
}
|
|
27529
27712
|
|
|
27713
|
+
// src/transcript-replay.ts
|
|
27714
|
+
function parseTranscriptEntries(value) {
|
|
27715
|
+
if (typeof value !== "object" || value === null) return [];
|
|
27716
|
+
const entries2 = value.entries;
|
|
27717
|
+
if (!Array.isArray(entries2)) return [];
|
|
27718
|
+
const parsed = [];
|
|
27719
|
+
for (const entry of entries2) {
|
|
27720
|
+
const { role, text: text3 } = entry ?? {};
|
|
27721
|
+
if (role !== "user" && role !== "assistant" || typeof text3 !== "string") return [];
|
|
27722
|
+
parsed.push({ role, text: text3 });
|
|
27723
|
+
}
|
|
27724
|
+
return parsed;
|
|
27725
|
+
}
|
|
27726
|
+
function transcriptReplayEvents(entries2) {
|
|
27727
|
+
const events = [];
|
|
27728
|
+
let open = false;
|
|
27729
|
+
let awaitingAssistant = false;
|
|
27730
|
+
for (const entry of entries2) {
|
|
27731
|
+
if (entry.role === "user") {
|
|
27732
|
+
if (open) events.push({ event: "message_completed", data: {} });
|
|
27733
|
+
events.push({ event: "message_started", data: { message: entry.text } });
|
|
27734
|
+
open = true;
|
|
27735
|
+
awaitingAssistant = true;
|
|
27736
|
+
continue;
|
|
27737
|
+
}
|
|
27738
|
+
if (!open || !awaitingAssistant) {
|
|
27739
|
+
if (open) events.push({ event: "message_completed", data: {} });
|
|
27740
|
+
events.push({ event: "resume_started", data: { tool: "" } });
|
|
27741
|
+
open = true;
|
|
27742
|
+
}
|
|
27743
|
+
events.push({ event: "content", data: { delta: entry.text } });
|
|
27744
|
+
awaitingAssistant = false;
|
|
27745
|
+
}
|
|
27746
|
+
if (open) events.push({ event: "message_completed", data: {} });
|
|
27747
|
+
return events;
|
|
27748
|
+
}
|
|
27749
|
+
|
|
27530
27750
|
// src/transport.ts
|
|
27531
27751
|
var AssistantTransportError = class extends Error {
|
|
27532
27752
|
code = "invalid_response";
|
|
@@ -27635,15 +27855,15 @@ function parseFrame(frame) {
|
|
|
27635
27855
|
if (event === "done" && !isValidDonePayload(parsed)) {
|
|
27636
27856
|
throw invalidStream("assistant event stream contained an invalid done event");
|
|
27637
27857
|
}
|
|
27638
|
-
return { event, data:
|
|
27858
|
+
return { event, data: isRecord5(parsed) ? parsed : { value: parsed } };
|
|
27639
27859
|
}
|
|
27640
27860
|
function normalizeLineEndings(input) {
|
|
27641
27861
|
return input.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
|
|
27642
27862
|
}
|
|
27643
27863
|
function isValidDonePayload(value) {
|
|
27644
|
-
return
|
|
27864
|
+
return isRecord5(value) && (value.turnId === void 0 || typeof value.turnId === "string" && value.turnId.length > 0);
|
|
27645
27865
|
}
|
|
27646
|
-
function
|
|
27866
|
+
function isRecord5(value) {
|
|
27647
27867
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27648
27868
|
}
|
|
27649
27869
|
function invalidStream(message, cause) {
|
|
@@ -27697,6 +27917,12 @@ var DefaultAssistantClient = class {
|
|
|
27697
27917
|
await this.#singleFlight(async (signal) => {
|
|
27698
27918
|
if (this.#session) return;
|
|
27699
27919
|
const session = await this.#createSession(signal);
|
|
27920
|
+
if (this.#source.kind !== "public" && session.endpoints.transcript) {
|
|
27921
|
+
try {
|
|
27922
|
+
await this.#replayTranscript(session, signal);
|
|
27923
|
+
} catch {
|
|
27924
|
+
}
|
|
27925
|
+
}
|
|
27700
27926
|
if (session.resume) {
|
|
27701
27927
|
try {
|
|
27702
27928
|
await this.#runChatOperation(signal, () => this.#resumeTurn(session, signal));
|
|
@@ -27705,6 +27931,26 @@ var DefaultAssistantClient = class {
|
|
|
27705
27931
|
}
|
|
27706
27932
|
});
|
|
27707
27933
|
}
|
|
27934
|
+
/** Fetch and re-emit the bounded visible transcript through the standard event path. */
|
|
27935
|
+
async #replayTranscript(session, signal) {
|
|
27936
|
+
const endpoint = session.endpoints.transcript;
|
|
27937
|
+
if (!endpoint) return;
|
|
27938
|
+
const response = await this.#request(
|
|
27939
|
+
endpoint,
|
|
27940
|
+
{
|
|
27941
|
+
method: "POST",
|
|
27942
|
+
headers: authorizedHeaders(session.token, "application/json"),
|
|
27943
|
+
body: "{}",
|
|
27944
|
+
signal
|
|
27945
|
+
},
|
|
27946
|
+
"turn_failed"
|
|
27947
|
+
);
|
|
27948
|
+
if (!response.ok) return;
|
|
27949
|
+
for (const event of transcriptReplayEvents(parseTranscriptEntries(await response.json()))) {
|
|
27950
|
+
this.#emit(event);
|
|
27951
|
+
if (event.event === "message_completed") await this.#chat.flush();
|
|
27952
|
+
}
|
|
27953
|
+
}
|
|
27708
27954
|
/** POST the one-shot resume trigger; a 409 means nothing was pending, which renders as silence. */
|
|
27709
27955
|
async #resumeTurn(session, signal) {
|
|
27710
27956
|
const response = await this.#request(
|
|
@@ -28136,10 +28382,10 @@ function authorizedHeaders(token, accept) {
|
|
|
28136
28382
|
};
|
|
28137
28383
|
}
|
|
28138
28384
|
function parseAppInteraction(value) {
|
|
28139
|
-
if (!
|
|
28385
|
+
if (!isRecord3(value) || !isRecord3(value.interaction)) return void 0;
|
|
28140
28386
|
const event = value.interaction.event;
|
|
28141
28387
|
const data = value.interaction.data;
|
|
28142
|
-
if (event !== "tool_proposed" && event !== "input_requested" || !
|
|
28388
|
+
if (event !== "tool_proposed" && event !== "input_requested" || !isRecord3(data)) {
|
|
28143
28389
|
return void 0;
|
|
28144
28390
|
}
|
|
28145
28391
|
const parsed = toAssistantClientEvent({ event, data });
|
|
@@ -28160,6 +28406,27 @@ function appInteractionStopped(action) {
|
|
|
28160
28406
|
};
|
|
28161
28407
|
}
|
|
28162
28408
|
|
|
28409
|
+
// src/conversation-recovery.ts
|
|
28410
|
+
function appendConversationRecovery(input) {
|
|
28411
|
+
if (!input.messages) return;
|
|
28412
|
+
input.messages.querySelector(".conversation-error")?.remove();
|
|
28413
|
+
const error51 = document.createElement("section");
|
|
28414
|
+
error51.className = "conversation-error";
|
|
28415
|
+
error51.setAttribute("role", input.action ? "alert" : "status");
|
|
28416
|
+
const text3 = document.createElement("p");
|
|
28417
|
+
text3.textContent = input.message;
|
|
28418
|
+
error51.append(text3);
|
|
28419
|
+
if (input.action) {
|
|
28420
|
+
const button2 = document.createElement("button");
|
|
28421
|
+
button2.type = "button";
|
|
28422
|
+
button2.textContent = input.action.label;
|
|
28423
|
+
button2.addEventListener("click", input.action.run);
|
|
28424
|
+
error51.append(button2);
|
|
28425
|
+
}
|
|
28426
|
+
input.messages.append(error51);
|
|
28427
|
+
input.revealLatest();
|
|
28428
|
+
}
|
|
28429
|
+
|
|
28163
28430
|
// src/input-request-card.ts
|
|
28164
28431
|
function createInputRequestCard(options) {
|
|
28165
28432
|
const card = document.createElement("section");
|
|
@@ -31250,22 +31517,46 @@ function renderMarkdown(text3) {
|
|
|
31250
31517
|
// src/sign-in-card.ts
|
|
31251
31518
|
function createSignInCard(options) {
|
|
31252
31519
|
const card = document.createElement("div");
|
|
31253
|
-
card.className = "
|
|
31520
|
+
card.className = "tool-proposal sign-in";
|
|
31254
31521
|
card.dataset.tool = options.tool;
|
|
31255
31522
|
card.setAttribute("role", "status");
|
|
31256
|
-
const
|
|
31257
|
-
|
|
31523
|
+
const badge = document.createElement("span");
|
|
31524
|
+
badge.className = "sign-in-badge";
|
|
31525
|
+
badge.setAttribute("aria-hidden", "true");
|
|
31526
|
+
card.append(badge);
|
|
31527
|
+
const heading = document.createElement("h3");
|
|
31258
31528
|
heading.textContent = options.labels.heading;
|
|
31259
31529
|
card.append(heading);
|
|
31260
|
-
|
|
31261
|
-
|
|
31262
|
-
|
|
31263
|
-
|
|
31264
|
-
|
|
31265
|
-
|
|
31266
|
-
|
|
31267
|
-
|
|
31268
|
-
|
|
31530
|
+
if (options.labels.body) {
|
|
31531
|
+
const body = document.createElement("p");
|
|
31532
|
+
body.className = "proposal-description";
|
|
31533
|
+
body.textContent = options.labels.body;
|
|
31534
|
+
card.append(body);
|
|
31535
|
+
}
|
|
31536
|
+
const actions = document.createElement("div");
|
|
31537
|
+
actions.className = "proposal-actions";
|
|
31538
|
+
const buttons = [];
|
|
31539
|
+
const act = (intent) => {
|
|
31540
|
+
for (const button2 of buttons) button2.disabled = true;
|
|
31541
|
+
options.onAction(intent);
|
|
31542
|
+
};
|
|
31543
|
+
const signIn = document.createElement("button");
|
|
31544
|
+
signIn.type = "button";
|
|
31545
|
+
signIn.className = "sign-in-action";
|
|
31546
|
+
signIn.textContent = options.labels.action;
|
|
31547
|
+
signIn.addEventListener("click", () => act("sign-in"));
|
|
31548
|
+
buttons.push(signIn);
|
|
31549
|
+
actions.append(signIn);
|
|
31550
|
+
if (options.labels.signUpAction) {
|
|
31551
|
+
const signUp = document.createElement("button");
|
|
31552
|
+
signUp.type = "button";
|
|
31553
|
+
signUp.className = "sign-up-action";
|
|
31554
|
+
signUp.textContent = options.labels.signUpAction;
|
|
31555
|
+
signUp.addEventListener("click", () => act("sign-up"));
|
|
31556
|
+
buttons.push(signUp);
|
|
31557
|
+
actions.append(signUp);
|
|
31558
|
+
}
|
|
31559
|
+
card.append(actions);
|
|
31269
31560
|
return card;
|
|
31270
31561
|
}
|
|
31271
31562
|
|
|
@@ -31293,7 +31584,7 @@ var AssistantElementEventController = class {
|
|
|
31293
31584
|
if (event.event === "unrecognized") return;
|
|
31294
31585
|
const { event: name21, data } = event;
|
|
31295
31586
|
if (name21 === "session_started") {
|
|
31296
|
-
if (
|
|
31587
|
+
if (isRecord6(data.configuration)) {
|
|
31297
31588
|
this.#host.applyConfiguration(data.configuration);
|
|
31298
31589
|
}
|
|
31299
31590
|
this.#host.element.dispatchEvent(
|
|
@@ -31361,10 +31652,10 @@ var AssistantElementEventController = class {
|
|
|
31361
31652
|
this.#appendToolProposal(
|
|
31362
31653
|
String(data.id ?? ""),
|
|
31363
31654
|
String(data.tool ?? "action"),
|
|
31364
|
-
|
|
31655
|
+
isRecord6(data.arguments) ? data.arguments : void 0,
|
|
31365
31656
|
typeof data.title === "string" ? data.title : void 0,
|
|
31366
31657
|
"description" in data && typeof data.description === "string" ? data.description : void 0,
|
|
31367
|
-
"reviewSchema" in data &&
|
|
31658
|
+
"reviewSchema" in data && isRecord6(data.reviewSchema) ? data.reviewSchema : void 0
|
|
31368
31659
|
);
|
|
31369
31660
|
return;
|
|
31370
31661
|
}
|
|
@@ -31377,7 +31668,7 @@ var AssistantElementEventController = class {
|
|
|
31377
31668
|
);
|
|
31378
31669
|
return;
|
|
31379
31670
|
}
|
|
31380
|
-
if (name21 === "input_requested" &&
|
|
31671
|
+
if (name21 === "input_requested" && isRecord6(data.requestedSchema)) {
|
|
31381
31672
|
this.#appendInputRequest(
|
|
31382
31673
|
String(data.id ?? ""),
|
|
31383
31674
|
String(data.message ?? "More information is required"),
|
|
@@ -31471,17 +31762,20 @@ var AssistantElementEventController = class {
|
|
|
31471
31762
|
const messages = this.#host.messages();
|
|
31472
31763
|
if (!messages) return;
|
|
31473
31764
|
this.#proposalCards.get(id)?.remove();
|
|
31765
|
+
const labels = this.#host.labels();
|
|
31474
31766
|
const card = createSignInCard({
|
|
31475
31767
|
tool,
|
|
31476
31768
|
signInTicket,
|
|
31477
31769
|
expiresAt,
|
|
31478
31770
|
labels: {
|
|
31479
|
-
heading:
|
|
31480
|
-
|
|
31771
|
+
heading: labels.signInHeading,
|
|
31772
|
+
body: labels.signInBody,
|
|
31773
|
+
action: labels.signInAction,
|
|
31774
|
+
signUpAction: labels.signUpAction
|
|
31481
31775
|
},
|
|
31482
|
-
|
|
31776
|
+
onAction: (intent) => this.#host.element.dispatchEvent(
|
|
31483
31777
|
new CustomEvent("assistant-sign-in-requested", {
|
|
31484
|
-
detail: { id, tool, signInTicket, expiresAt },
|
|
31778
|
+
detail: { id, tool, signInTicket, expiresAt, intent },
|
|
31485
31779
|
bubbles: true,
|
|
31486
31780
|
composed: true
|
|
31487
31781
|
})
|
|
@@ -31545,7 +31839,7 @@ var AssistantElementEventController = class {
|
|
|
31545
31839
|
this.#host.revealLatest();
|
|
31546
31840
|
}
|
|
31547
31841
|
};
|
|
31548
|
-
function
|
|
31842
|
+
function isRecord6(value) {
|
|
31549
31843
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
31550
31844
|
}
|
|
31551
31845
|
|
|
@@ -31877,8 +32171,10 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
|
|
|
31877
32171
|
.proposal-details .proposal-arguments { margin-top: 4px; }
|
|
31878
32172
|
.proposal-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: end; }
|
|
31879
32173
|
.tool-proposal button { min-height: 44px; padding: 9px 16px; border: 1px solid var(--ns-assistant-secondary-button-border, transparent); border-radius: var(--ns-assistant-button-radius, var(--ns-assistant-default-button-radius)); color: var(--ns-assistant-secondary-button-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-secondary-button, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated))); cursor: pointer; font-weight: 600; }
|
|
31880
|
-
.tool-proposal .proposal-accept { color: var(--ns-assistant-primary-button-text, var(--ns-assistant-accent-text, var(--ns-assistant-default-accent-text))); background: var(--ns-assistant-primary-button, var(--ns-assistant-accent, var(--ns-assistant-default-accent))); border-color: var(--ns-assistant-primary-button-border, transparent); }
|
|
32174
|
+
.tool-proposal .proposal-accept, .tool-proposal .sign-in-action { color: var(--ns-assistant-primary-button-text, var(--ns-assistant-accent-text, var(--ns-assistant-default-accent-text))); background: var(--ns-assistant-primary-button, var(--ns-assistant-accent, var(--ns-assistant-default-accent))); border-color: var(--ns-assistant-primary-button-border, transparent); }
|
|
31881
32175
|
.tool-proposal button:disabled { opacity: .55; cursor: not-allowed; }
|
|
32176
|
+
.sign-in .sign-in-badge { display: grid; place-items: center; width: 38px; height: 38px; border-radius: 999px; color: var(--ns-assistant-accent, var(--ns-assistant-default-accent)); background: color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 12%, transparent); }
|
|
32177
|
+
.sign-in .sign-in-badge::before { content: ''; width: 19px; height: 19px; 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='M12 12a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Zm0 2.2c-4.3 0-7.8 2.6-7.8 5.8v1h15.6v-1c0-3.2-3.5-5.8-7.8-5.8Z'/%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='M12 12a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Zm0 2.2c-4.3 0-7.8 2.6-7.8 5.8v1h15.6v-1c0-3.2-3.5-5.8-7.8-5.8Z'/%3E%3C/svg%3E") center / contain no-repeat; }
|
|
31882
32178
|
.tool-proposal button { min-height: 45px; }
|
|
31883
32179
|
.tool-result { display: grid; gap: 10px; margin: 8px 0 16px; padding: 16px; border: 1px solid var(--ns-assistant-divider, var(--ns-assistant-default-divider)); border-radius: var(--ns-assistant-card-radius, 14px); background: var(--ns-assistant-assistant-message, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated))); }
|
|
31884
32180
|
.tool-result > strong { color: var(--ns-assistant-success, var(--ns-assistant-default-success)); }
|
|
@@ -32846,33 +33142,28 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
32846
33142
|
this.#setSessionState("error");
|
|
32847
33143
|
}
|
|
32848
33144
|
const detail = error51 instanceof AssistantClientError ? error51.detail : { code: fallbackCode, retryable: false };
|
|
32849
|
-
|
|
32850
|
-
|
|
33145
|
+
const startNewConversation = detail.serviceCode === "session_turn_budget_exhausted";
|
|
33146
|
+
const reconnect = detail.retryable !== false || detail.serviceCode === void 0;
|
|
33147
|
+
const recoveryAction = startNewConversation ? {
|
|
33148
|
+
label: this.#appearance.labels.newConversation,
|
|
33149
|
+
run: () => this.#startNewConversation()
|
|
33150
|
+
} : reconnect ? { label: this.#appearance.labels.reconnect, run: () => this.reconnect() } : void 0;
|
|
33151
|
+
appendConversationRecovery({
|
|
33152
|
+
messages: this.#messages,
|
|
33153
|
+
message: detail.code === "session_expired" ? this.#appearance.labels.sessionExpired : this.#appearance.labels.unavailable,
|
|
32851
33154
|
// A spent or switched-off daily budget offers no retry. Reconnecting cannot succeed, and every
|
|
32852
33155
|
// open tab trying is exactly the load the cap was set to refuse — so the button goes, not just
|
|
32853
33156
|
// the alarming words. A spent *session* keeps it: reconnect mints a fresh one, which is the fix.
|
|
32854
|
-
|
|
32855
|
-
|
|
33157
|
+
...recoveryAction === void 0 ? {} : { action: recoveryAction },
|
|
33158
|
+
revealLatest: () => this.#revealLatest()
|
|
33159
|
+
});
|
|
32856
33160
|
this.#dispatchError(detail);
|
|
32857
33161
|
}
|
|
32858
|
-
#
|
|
32859
|
-
|
|
32860
|
-
this.#
|
|
32861
|
-
|
|
32862
|
-
|
|
32863
|
-
error51.setAttribute("role", offerRetry ? "alert" : "status");
|
|
32864
|
-
const text3 = document.createElement("p");
|
|
32865
|
-
text3.textContent = message;
|
|
32866
|
-
error51.append(text3);
|
|
32867
|
-
if (offerRetry) {
|
|
32868
|
-
const retry = document.createElement("button");
|
|
32869
|
-
retry.type = "button";
|
|
32870
|
-
retry.textContent = this.#appearance.labels.reconnect;
|
|
32871
|
-
retry.addEventListener("click", () => this.reconnect());
|
|
32872
|
-
error51.append(retry);
|
|
32873
|
-
}
|
|
32874
|
-
this.#messages.append(error51);
|
|
32875
|
-
this.#revealLatest();
|
|
33162
|
+
#startNewConversation() {
|
|
33163
|
+
this.resetSession();
|
|
33164
|
+
this.#setSessionState("loading");
|
|
33165
|
+
this.#primeSession();
|
|
33166
|
+
this.dispatchEvent(new CustomEvent("assistant-new-conversation"));
|
|
32876
33167
|
}
|
|
32877
33168
|
#resolvedMode() {
|
|
32878
33169
|
const configured = this.getAttribute("theme") ?? this.#appearance.theme.defaultMode;
|