@noodleseed/assistant 1.8.0 → 1.10.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/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { g as AssistantViewAvailableDetail, e as AssistantClientEvent, a as AssistantContext, d as AssistantModelContextUpdate, A as AssistantPageContext, h as AssistantInteractionResponse } from './client-BxoNZkWp.cjs';
2
- export { f as AssistantErrorDetail, i as AssistantEvent, j as AssistantViewAvailableEvent } from './client-BxoNZkWp.cjs';
3
- import './appearance-DowzFJjh.cjs';
1
+ import { d as AssistantViewAvailableDetail, f as AssistantClientEvent, a as AssistantContext, e as AssistantModelContextUpdate, A as AssistantPageContext, h as AssistantInteractionResponse } from './client-CsmtpD1z.cjs';
2
+ export { g as AssistantErrorDetail, i as AssistantEvent, j as AssistantViewAvailableEvent } from './client-CsmtpD1z.cjs';
3
+ import './appearance-Cc-eqSbp.cjs';
4
4
  import 'ai';
5
5
 
6
6
  interface AssistantSurfaceAppearance {
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { g as AssistantViewAvailableDetail, e as AssistantClientEvent, a as AssistantContext, d as AssistantModelContextUpdate, A as AssistantPageContext, h as AssistantInteractionResponse } from './client-ERQCAH_0.js';
2
- export { f as AssistantErrorDetail, i as AssistantEvent, j as AssistantViewAvailableEvent } from './client-ERQCAH_0.js';
3
- import './appearance-DowzFJjh.js';
1
+ import { d as AssistantViewAvailableDetail, f as AssistantClientEvent, a as AssistantContext, e as AssistantModelContextUpdate, A as AssistantPageContext, h as AssistantInteractionResponse } from './client-B803xZVn.js';
2
+ export { g as AssistantErrorDetail, i as AssistantEvent, j as AssistantViewAvailableEvent } from './client-B803xZVn.js';
3
+ import './appearance-Cc-eqSbp.js';
4
4
  import 'ai';
5
5
 
6
6
  interface AssistantSurfaceAppearance {
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  ASSISTANT_TAG_NAME,
3
3
  NoodleAssistantElement,
4
4
  registerNoodleAssistant
5
- } from "./chunk-JMBUJSFP.js";
5
+ } from "./chunk-RSNMY27B.js";
6
6
  import "./chunk-RYQBXTLR.js";
7
7
  import "./chunk-3YYTUJPJ.js";
8
8
  import "./chunk-5FUTL2UF.js";
@@ -1,5 +1,5 @@
1
- import { A as AssistantPageContext, a as AssistantContext, C as CreateAssistantClientOptions, b as AssistantChatState, c as AssistantClient } from '../client-BxoNZkWp.cjs';
2
- import '../appearance-DowzFJjh.cjs';
1
+ import { A as AssistantPageContext, a as AssistantContext, C as CreateAssistantClientOptions, b as AssistantChatState, c as AssistantClient } from '../client-CsmtpD1z.cjs';
2
+ import '../appearance-Cc-eqSbp.cjs';
3
3
  import 'ai';
4
4
 
5
5
  interface UseNoodleAssistantOptions<TPageContext extends AssistantPageContext = AssistantContext> extends CreateAssistantClientOptions<TPageContext> {
@@ -1,5 +1,5 @@
1
- import { A as AssistantPageContext, a as AssistantContext, C as CreateAssistantClientOptions, b as AssistantChatState, c as AssistantClient } from '../client-ERQCAH_0.js';
2
- import '../appearance-DowzFJjh.js';
1
+ import { A as AssistantPageContext, a as AssistantContext, C as CreateAssistantClientOptions, b as AssistantChatState, c as AssistantClient } from '../client-B803xZVn.js';
2
+ import '../appearance-Cc-eqSbp.js';
3
3
  import 'ai';
4
4
 
5
5
  interface UseNoodleAssistantOptions<TPageContext extends AssistantPageContext = AssistantContext> extends CreateAssistantClientOptions<TPageContext> {
package/dist/react.cjs CHANGED
@@ -15191,10 +15191,11 @@ var init_v4 = __esm({
15191
15191
  // src/react.ts
15192
15192
  var react_exports = {};
15193
15193
  __export(react_exports, {
15194
+ NoodleAppView: () => NoodleAppView,
15194
15195
  NoodleAssistant: () => NoodleAssistant2
15195
15196
  });
15196
15197
  module.exports = __toCommonJS(react_exports);
15197
- var import_react = require("react");
15198
+ var import_react2 = require("react");
15198
15199
 
15199
15200
  // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
15200
15201
  init_v4();
@@ -22120,6 +22121,8 @@ function createAssistantAppHostContext(theme) {
22120
22121
  };
22121
22122
  }
22122
22123
  var APP_RENDER_TIMEOUT_MS = 1e4;
22124
+ var APP_TEARDOWN_TIMEOUT_MS = 1e3;
22125
+ var mountedApps = /* @__PURE__ */ new WeakMap();
22123
22126
  function resolveSandboxUrl(value) {
22124
22127
  if (!value) return void 0;
22125
22128
  try {
@@ -22148,7 +22151,12 @@ function mountAssistantApp(detail, actions, options = {}) {
22148
22151
  if (sandboxUrl) frame.src = sandboxUrl;
22149
22152
  else frame.srcdoc = PROXY_DOCUMENT;
22150
22153
  card.append(frame);
22154
+ let mountedBridge;
22155
+ let mountedTransport;
22156
+ let destroyed = false;
22151
22157
  let initialized = false;
22158
+ let hostContext = createAssistantAppHostContext(actions.theme);
22159
+ let destroyPromise;
22152
22160
  const renderTimer = setTimeout(() => {
22153
22161
  if (initialized || !frame.isConnected) return;
22154
22162
  const note = document.createElement("div");
@@ -22160,6 +22168,7 @@ function mountAssistantApp(detail, actions, options = {}) {
22160
22168
  frame.addEventListener(
22161
22169
  "load",
22162
22170
  () => {
22171
+ if (destroyed) return;
22163
22172
  const target = frame.contentWindow;
22164
22173
  if (!target) return;
22165
22174
  const bridge = new DX(
@@ -22173,22 +22182,27 @@ function mountAssistantApp(detail, actions, options = {}) {
22173
22182
  message: { text: {} }
22174
22183
  },
22175
22184
  {
22176
- hostContext: createAssistantAppHostContext(actions.theme)
22185
+ hostContext
22177
22186
  }
22178
22187
  );
22188
+ mountedBridge = bridge;
22179
22189
  bridge.onsandboxready = () => {
22190
+ if (destroyed) return;
22191
+ const current = options.getDetail?.() ?? detail;
22180
22192
  void bridge.sendSandboxResourceReady({
22181
- html: detail.html,
22193
+ html: current.html,
22182
22194
  sandbox: "allow-scripts allow-forms",
22183
- ...detail.resourceMeta ?? {}
22195
+ ...current.resourceMeta ?? {}
22184
22196
  });
22185
22197
  };
22186
22198
  bridge.onsizechange = ({ height }) => {
22199
+ if (destroyed) return;
22187
22200
  if (typeof height === "number" && Number.isFinite(height)) {
22188
22201
  frame.style.height = `${Math.min(1200, Math.max(120, Math.ceil(height)))}px`;
22189
22202
  }
22190
22203
  };
22191
22204
  bridge.onmessage = async ({ content }) => {
22205
+ if (destroyed) return {};
22192
22206
  const text3 = content.flatMap(
22193
22207
  (part) => part.type === "text" && typeof part.text === "string" ? [part.text] : []
22194
22208
  ).join("\n").trim();
@@ -22196,13 +22210,16 @@ function mountAssistantApp(detail, actions, options = {}) {
22196
22210
  return {};
22197
22211
  };
22198
22212
  bridge.onupdatemodelcontext = async (update) => {
22213
+ if (destroyed) return {};
22199
22214
  actions.updateModelContext(update);
22200
22215
  return {};
22201
22216
  };
22202
22217
  bridge.onopenlink = async ({ url: url2 }) => {
22218
+ if (destroyed) return { isError: true };
22219
+ const current = options.getDetail?.() ?? detail;
22203
22220
  const allowed = isAllowedAppLink(
22204
22221
  url2,
22205
- detail.allowedOpenDomains ?? [],
22222
+ current.allowedOpenDomains ?? [],
22206
22223
  globalThis.location?.href ?? "https://invalid.example"
22207
22224
  );
22208
22225
  if (!allowed) return { isError: true };
@@ -22211,30 +22228,83 @@ function mountAssistantApp(detail, actions, options = {}) {
22211
22228
  };
22212
22229
  bridge.onrequestdisplaymode = async ({ mode }) => {
22213
22230
  const accepted = mode === "fullscreen" ? "fullscreen" : "inline";
22231
+ if (destroyed) return { mode: accepted };
22214
22232
  card.toggleAttribute("data-fullscreen", accepted === "fullscreen");
22215
22233
  return { mode: accepted };
22216
22234
  };
22217
- bridge.oncalltool = async (params) => await actions.client.requestApp("tools/call", params);
22218
- bridge.onlistresources = async (params) => await actions.client.requestApp("resources/list", params ?? {});
22219
- bridge.onreadresource = async (params) => await actions.client.requestApp("resources/read", params);
22235
+ bridge.oncalltool = async (params) => {
22236
+ if (destroyed) {
22237
+ return {
22238
+ content: [{ type: "text", text: "App view is closing." }],
22239
+ isError: true
22240
+ };
22241
+ }
22242
+ return await actions.client.requestApp("tools/call", params);
22243
+ };
22244
+ bridge.onlistresources = async (params) => {
22245
+ if (destroyed) {
22246
+ return { resources: [] };
22247
+ }
22248
+ return await actions.client.requestApp("resources/list", params ?? {});
22249
+ };
22250
+ bridge.onreadresource = async (params) => {
22251
+ if (destroyed) {
22252
+ return { contents: [] };
22253
+ }
22254
+ return await actions.client.requestApp("resources/read", params);
22255
+ };
22220
22256
  bridge.oninitialized = () => {
22257
+ if (destroyed) return;
22221
22258
  initialized = true;
22222
22259
  clearTimeout(renderTimer);
22223
- void bridge.sendToolInput({ arguments: detail.arguments ?? {} });
22260
+ bridge.setHostContext(hostContext);
22261
+ const current = options.getDetail?.() ?? detail;
22262
+ void bridge.sendToolInput({ arguments: current.arguments ?? {} });
22224
22263
  void bridge.sendToolResult({
22225
- content: [{ type: "text", text: JSON.stringify(detail.result) }],
22226
- ...typeof detail.result === "object" && detail.result !== null && !Array.isArray(detail.result) ? { structuredContent: detail.result } : {}
22264
+ content: [{ type: "text", text: JSON.stringify(current.result) }],
22265
+ ...typeof current.result === "object" && current.result !== null && !Array.isArray(current.result) ? { structuredContent: current.result } : {}
22227
22266
  });
22228
22267
  };
22229
- void bridge.connect(new E(target, target)).catch(() => {
22230
- clearTimeout(renderTimer);
22231
- card.remove();
22268
+ const transport = new E(target, target);
22269
+ mountedTransport = transport;
22270
+ void bridge.connect(transport).catch(() => {
22271
+ void destroy();
22232
22272
  });
22233
22273
  },
22234
22274
  { once: true }
22235
22275
  );
22276
+ const updateTheme = (theme) => {
22277
+ if (destroyed) return;
22278
+ hostContext = createAssistantAppHostContext(theme);
22279
+ if (initialized) mountedBridge?.setHostContext(hostContext);
22280
+ };
22281
+ const destroy = () => {
22282
+ if (destroyPromise) return destroyPromise;
22283
+ destroyed = true;
22284
+ clearTimeout(renderTimer);
22285
+ destroyPromise = (async () => {
22286
+ try {
22287
+ if (initialized) {
22288
+ await mountedBridge?.teardownResource({}, { timeout: APP_TEARDOWN_TIMEOUT_MS });
22289
+ }
22290
+ } catch {
22291
+ }
22292
+ await mountedTransport?.close().catch(() => {
22293
+ });
22294
+ card.remove();
22295
+ mountedApps.delete(card);
22296
+ })();
22297
+ return destroyPromise;
22298
+ };
22299
+ mountedApps.set(card, { destroy, updateTheme });
22236
22300
  return card;
22237
22301
  }
22302
+ function updateAssistantAppTheme(card, theme) {
22303
+ mountedApps.get(card)?.updateTheme(theme);
22304
+ }
22305
+ function unmountAssistantApp(card) {
22306
+ return mountedApps.get(card)?.destroy() ?? Promise.resolve();
22307
+ }
22238
22308
 
22239
22309
  // src/appearance.ts
22240
22310
  var common = {
@@ -31366,7 +31436,7 @@ function contrastWarnings(theme, mode) {
31366
31436
  for (const [role, foreground, background] of pairs) {
31367
31437
  if (!foreground || !background) continue;
31368
31438
  const ratio = contrastRatio2(foreground, background);
31369
- if (ratio >= 4.5) continue;
31439
+ if (ratio === void 0 || ratio >= 4.5) continue;
31370
31440
  warnings.push({
31371
31441
  code: "low_contrast",
31372
31442
  theme: mode,
@@ -31380,13 +31450,16 @@ function contrastWarnings(theme, mode) {
31380
31450
  return warnings;
31381
31451
  }
31382
31452
  function contrastRatio2(first, second) {
31383
- const lighter = Math.max(luminance(first), luminance(second));
31384
- const darker = Math.min(luminance(first), luminance(second));
31453
+ const firstLuminance = luminance(first);
31454
+ const secondLuminance = luminance(second);
31455
+ if (firstLuminance === void 0 || secondLuminance === void 0) return void 0;
31456
+ const lighter = Math.max(firstLuminance, secondLuminance);
31457
+ const darker = Math.min(firstLuminance, secondLuminance);
31385
31458
  return (lighter + 0.05) / (darker + 0.05);
31386
31459
  }
31387
31460
  function luminance(color) {
31388
31461
  const match = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(color);
31389
- if (!match) return 1;
31462
+ if (!match) return void 0;
31390
31463
  const values = match.slice(1).map((value) => {
31391
31464
  const channel = Number.parseInt(value, 16) / 255;
31392
31465
  return channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4;
@@ -32219,6 +32292,9 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32219
32292
  })
32220
32293
  );
32221
32294
  }
32295
+ for (const app of this.shadowRoot?.querySelectorAll(".noodle-app-card") ?? []) {
32296
+ updateAssistantAppTheme(app, mode);
32297
+ }
32222
32298
  }
32223
32299
  #setSessionState(state) {
32224
32300
  this.#sessionState = state;
@@ -32392,13 +32468,63 @@ function registerNoodleAssistant() {
32392
32468
  }
32393
32469
  }
32394
32470
 
32471
+ // src/react-app-view.ts
32472
+ var import_react = require("react");
32473
+ function NoodleAppView({
32474
+ client,
32475
+ view,
32476
+ theme = "light",
32477
+ className,
32478
+ onError
32479
+ }) {
32480
+ const container = (0, import_react.useRef)(null);
32481
+ const mounted = (0, import_react.useRef)(null);
32482
+ const current = (0, import_react.useRef)({ view, theme, onError });
32483
+ const viewId = view.id;
32484
+ const resourceUri = view.resourceUri;
32485
+ (0, import_react.useEffect)(() => {
32486
+ current.current = { view, theme, onError };
32487
+ });
32488
+ (0, import_react.useEffect)(() => {
32489
+ const host = container.current;
32490
+ if (!host) return;
32491
+ const initialView = { ...current.current.view, id: viewId, resourceUri };
32492
+ const sandboxUrl = client.appSandboxUrl?.();
32493
+ const card = mountAssistantApp(
32494
+ initialView,
32495
+ {
32496
+ client,
32497
+ sendMessage: (message) => client.sendMessage(message),
32498
+ updateModelContext: (update) => client.updateModelContext(update),
32499
+ theme: current.current.theme
32500
+ },
32501
+ {
32502
+ ...sandboxUrl ? { sandboxUrl } : {},
32503
+ getDetail: () => current.current.view,
32504
+ onRenderFailure: (failure) => current.current.onError?.(failure)
32505
+ }
32506
+ );
32507
+ if (!card) return;
32508
+ mounted.current = card;
32509
+ host.replaceChildren(card);
32510
+ return () => {
32511
+ if (mounted.current === card) mounted.current = null;
32512
+ void unmountAssistantApp(card);
32513
+ };
32514
+ }, [client, resourceUri, viewId]);
32515
+ (0, import_react.useEffect)(() => {
32516
+ if (mounted.current) updateAssistantAppTheme(mounted.current, theme);
32517
+ }, [theme]);
32518
+ return (0, import_react.createElement)("div", { ref: container, className });
32519
+ }
32520
+
32395
32521
  // src/react.ts
32396
- var NoodleAssistantWithRef = (0, import_react.forwardRef)(
32522
+ var NoodleAssistantWithRef = (0, import_react2.forwardRef)(
32397
32523
  function NoodleAssistant(props, forwardedRef) {
32398
- const ref = (0, import_react.useRef)(null);
32399
- const readyNotified = (0, import_react.useRef)(false);
32400
- (0, import_react.useImperativeHandle)(forwardedRef, () => ref.current, []);
32401
- (0, import_react.useEffect)(() => {
32524
+ const ref = (0, import_react2.useRef)(null);
32525
+ const readyNotified = (0, import_react2.useRef)(false);
32526
+ (0, import_react2.useImperativeHandle)(forwardedRef, () => ref.current, []);
32527
+ (0, import_react2.useEffect)(() => {
32402
32528
  const element = ref.current;
32403
32529
  if (!element) return;
32404
32530
  const ready = () => {
@@ -32443,7 +32569,7 @@ var NoodleAssistantWithRef = (0, import_react.forwardRef)(
32443
32569
  props.pageContext,
32444
32570
  props.sessionEndpoint
32445
32571
  ]);
32446
- return (0, import_react.createElement)("noodle-assistant", {
32572
+ return (0, import_react2.createElement)("noodle-assistant", {
32447
32573
  ref,
32448
32574
  class: props.className,
32449
32575
  "session-endpoint": props.sessionEndpoint,
@@ -32454,6 +32580,7 @@ var NoodleAssistantWithRef = (0, import_react.forwardRef)(
32454
32580
  var NoodleAssistant2 = NoodleAssistantWithRef;
32455
32581
  // Annotate the CommonJS export names for ESM import in node:
32456
32582
  0 && (module.exports = {
32583
+ NoodleAppView,
32457
32584
  NoodleAssistant
32458
32585
  });
32459
32586
  /*! Bundled license information: