@noodleseed/assistant 1.8.0 → 1.9.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-4B3XXGRP.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,11 @@ 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 destroyPromise;
22152
22159
  const renderTimer = setTimeout(() => {
22153
22160
  if (initialized || !frame.isConnected) return;
22154
22161
  const note = document.createElement("div");
@@ -22160,6 +22167,7 @@ function mountAssistantApp(detail, actions, options = {}) {
22160
22167
  frame.addEventListener(
22161
22168
  "load",
22162
22169
  () => {
22170
+ if (destroyed) return;
22163
22171
  const target = frame.contentWindow;
22164
22172
  if (!target) return;
22165
22173
  const bridge = new DX(
@@ -22176,19 +22184,24 @@ function mountAssistantApp(detail, actions, options = {}) {
22176
22184
  hostContext: createAssistantAppHostContext(actions.theme)
22177
22185
  }
22178
22186
  );
22187
+ mountedBridge = bridge;
22179
22188
  bridge.onsandboxready = () => {
22189
+ if (destroyed) return;
22190
+ const current = options.getDetail?.() ?? detail;
22180
22191
  void bridge.sendSandboxResourceReady({
22181
- html: detail.html,
22192
+ html: current.html,
22182
22193
  sandbox: "allow-scripts allow-forms",
22183
- ...detail.resourceMeta ?? {}
22194
+ ...current.resourceMeta ?? {}
22184
22195
  });
22185
22196
  };
22186
22197
  bridge.onsizechange = ({ height }) => {
22198
+ if (destroyed) return;
22187
22199
  if (typeof height === "number" && Number.isFinite(height)) {
22188
22200
  frame.style.height = `${Math.min(1200, Math.max(120, Math.ceil(height)))}px`;
22189
22201
  }
22190
22202
  };
22191
22203
  bridge.onmessage = async ({ content }) => {
22204
+ if (destroyed) return {};
22192
22205
  const text3 = content.flatMap(
22193
22206
  (part) => part.type === "text" && typeof part.text === "string" ? [part.text] : []
22194
22207
  ).join("\n").trim();
@@ -22196,13 +22209,16 @@ function mountAssistantApp(detail, actions, options = {}) {
22196
22209
  return {};
22197
22210
  };
22198
22211
  bridge.onupdatemodelcontext = async (update) => {
22212
+ if (destroyed) return {};
22199
22213
  actions.updateModelContext(update);
22200
22214
  return {};
22201
22215
  };
22202
22216
  bridge.onopenlink = async ({ url: url2 }) => {
22217
+ if (destroyed) return { isError: true };
22218
+ const current = options.getDetail?.() ?? detail;
22203
22219
  const allowed = isAllowedAppLink(
22204
22220
  url2,
22205
- detail.allowedOpenDomains ?? [],
22221
+ current.allowedOpenDomains ?? [],
22206
22222
  globalThis.location?.href ?? "https://invalid.example"
22207
22223
  );
22208
22224
  if (!allowed) return { isError: true };
@@ -22211,30 +22227,74 @@ function mountAssistantApp(detail, actions, options = {}) {
22211
22227
  };
22212
22228
  bridge.onrequestdisplaymode = async ({ mode }) => {
22213
22229
  const accepted = mode === "fullscreen" ? "fullscreen" : "inline";
22230
+ if (destroyed) return { mode: accepted };
22214
22231
  card.toggleAttribute("data-fullscreen", accepted === "fullscreen");
22215
22232
  return { mode: accepted };
22216
22233
  };
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);
22234
+ bridge.oncalltool = async (params) => {
22235
+ if (destroyed) {
22236
+ return {
22237
+ content: [{ type: "text", text: "App view is closing." }],
22238
+ isError: true
22239
+ };
22240
+ }
22241
+ return await actions.client.requestApp("tools/call", params);
22242
+ };
22243
+ bridge.onlistresources = async (params) => {
22244
+ if (destroyed) {
22245
+ return { resources: [] };
22246
+ }
22247
+ return await actions.client.requestApp("resources/list", params ?? {});
22248
+ };
22249
+ bridge.onreadresource = async (params) => {
22250
+ if (destroyed) {
22251
+ return { contents: [] };
22252
+ }
22253
+ return await actions.client.requestApp("resources/read", params);
22254
+ };
22220
22255
  bridge.oninitialized = () => {
22256
+ if (destroyed) return;
22221
22257
  initialized = true;
22222
22258
  clearTimeout(renderTimer);
22223
- void bridge.sendToolInput({ arguments: detail.arguments ?? {} });
22259
+ const current = options.getDetail?.() ?? detail;
22260
+ void bridge.sendToolInput({ arguments: current.arguments ?? {} });
22224
22261
  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 } : {}
22262
+ content: [{ type: "text", text: JSON.stringify(current.result) }],
22263
+ ...typeof current.result === "object" && current.result !== null && !Array.isArray(current.result) ? { structuredContent: current.result } : {}
22227
22264
  });
22228
22265
  };
22229
- void bridge.connect(new E(target, target)).catch(() => {
22230
- clearTimeout(renderTimer);
22231
- card.remove();
22266
+ const transport = new E(target, target);
22267
+ mountedTransport = transport;
22268
+ void bridge.connect(transport).catch(() => {
22269
+ void destroy();
22232
22270
  });
22233
22271
  },
22234
22272
  { once: true }
22235
22273
  );
22274
+ const destroy = () => {
22275
+ if (destroyPromise) return destroyPromise;
22276
+ destroyed = true;
22277
+ clearTimeout(renderTimer);
22278
+ destroyPromise = (async () => {
22279
+ try {
22280
+ if (initialized) {
22281
+ await mountedBridge?.teardownResource({}, { timeout: APP_TEARDOWN_TIMEOUT_MS });
22282
+ }
22283
+ } catch {
22284
+ }
22285
+ await mountedTransport?.close().catch(() => {
22286
+ });
22287
+ card.remove();
22288
+ mountedApps.delete(card);
22289
+ })();
22290
+ return destroyPromise;
22291
+ };
22292
+ mountedApps.set(card, { destroy });
22236
22293
  return card;
22237
22294
  }
22295
+ function unmountAssistantApp(card) {
22296
+ return mountedApps.get(card)?.destroy() ?? Promise.resolve();
22297
+ }
22238
22298
 
22239
22299
  // src/appearance.ts
22240
22300
  var common = {
@@ -32392,13 +32452,57 @@ function registerNoodleAssistant() {
32392
32452
  }
32393
32453
  }
32394
32454
 
32455
+ // src/react-app-view.ts
32456
+ var import_react = require("react");
32457
+ function NoodleAppView({
32458
+ client,
32459
+ view,
32460
+ theme = "light",
32461
+ className,
32462
+ onError
32463
+ }) {
32464
+ const container = (0, import_react.useRef)(null);
32465
+ const current = (0, import_react.useRef)({ view, theme, onError });
32466
+ const viewId = view.id;
32467
+ const resourceUri = view.resourceUri;
32468
+ (0, import_react.useEffect)(() => {
32469
+ current.current = { view, theme, onError };
32470
+ });
32471
+ (0, import_react.useEffect)(() => {
32472
+ const host = container.current;
32473
+ if (!host) return;
32474
+ const initialView = { ...current.current.view, id: viewId, resourceUri };
32475
+ const sandboxUrl = client.appSandboxUrl?.();
32476
+ const card = mountAssistantApp(
32477
+ initialView,
32478
+ {
32479
+ client,
32480
+ sendMessage: (message) => client.sendMessage(message),
32481
+ updateModelContext: (update) => client.updateModelContext(update),
32482
+ theme: current.current.theme
32483
+ },
32484
+ {
32485
+ ...sandboxUrl ? { sandboxUrl } : {},
32486
+ getDetail: () => current.current.view,
32487
+ onRenderFailure: (failure) => current.current.onError?.(failure)
32488
+ }
32489
+ );
32490
+ if (!card) return;
32491
+ host.replaceChildren(card);
32492
+ return () => {
32493
+ void unmountAssistantApp(card);
32494
+ };
32495
+ }, [client, resourceUri, viewId]);
32496
+ return (0, import_react.createElement)("div", { ref: container, className });
32497
+ }
32498
+
32395
32499
  // src/react.ts
32396
- var NoodleAssistantWithRef = (0, import_react.forwardRef)(
32500
+ var NoodleAssistantWithRef = (0, import_react2.forwardRef)(
32397
32501
  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)(() => {
32502
+ const ref = (0, import_react2.useRef)(null);
32503
+ const readyNotified = (0, import_react2.useRef)(false);
32504
+ (0, import_react2.useImperativeHandle)(forwardedRef, () => ref.current, []);
32505
+ (0, import_react2.useEffect)(() => {
32402
32506
  const element = ref.current;
32403
32507
  if (!element) return;
32404
32508
  const ready = () => {
@@ -32443,7 +32547,7 @@ var NoodleAssistantWithRef = (0, import_react.forwardRef)(
32443
32547
  props.pageContext,
32444
32548
  props.sessionEndpoint
32445
32549
  ]);
32446
- return (0, import_react.createElement)("noodle-assistant", {
32550
+ return (0, import_react2.createElement)("noodle-assistant", {
32447
32551
  ref,
32448
32552
  class: props.className,
32449
32553
  "session-endpoint": props.sessionEndpoint,
@@ -32454,6 +32558,7 @@ var NoodleAssistantWithRef = (0, import_react.forwardRef)(
32454
32558
  var NoodleAssistant2 = NoodleAssistantWithRef;
32455
32559
  // Annotate the CommonJS export names for ESM import in node:
32456
32560
  0 && (module.exports = {
32561
+ NoodleAppView,
32457
32562
  NoodleAssistant
32458
32563
  });
32459
32564
  /*! Bundled license information: