@opentiny/next-sdk 0.2.6 → 0.2.8

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.
@@ -3083,7 +3083,7 @@ function requireUtils$2() {
3083
3083
  if (hasRequiredUtils$2) return utils$2;
3084
3084
  hasRequiredUtils$2 = 1;
3085
3085
  const isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
3086
- const isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
3086
+ const isIPv42 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
3087
3087
  function stringArrayToHexStripped(input) {
3088
3088
  let acc = "";
3089
3089
  let code2 = 0;
@@ -3306,7 +3306,7 @@ function requireUtils$2() {
3306
3306
  }
3307
3307
  if (component.host !== void 0) {
3308
3308
  let host = unescape(component.host);
3309
- if (!isIPv4(host)) {
3309
+ if (!isIPv42(host)) {
3310
3310
  const ipV6res = normalizeIPv6(host);
3311
3311
  if (ipV6res.isIPV6 === true) {
3312
3312
  host = `[${ipV6res.escapedHost}]`;
@@ -3327,7 +3327,7 @@ function requireUtils$2() {
3327
3327
  recomposeAuthority,
3328
3328
  normalizeComponentEncoding,
3329
3329
  removeDotSegments,
3330
- isIPv4,
3330
+ isIPv4: isIPv42,
3331
3331
  isUUID,
3332
3332
  normalizeIPv6,
3333
3333
  stringArrayToHexStripped
@@ -3548,7 +3548,7 @@ var hasRequiredFastUri;
3548
3548
  function requireFastUri() {
3549
3549
  if (hasRequiredFastUri) return fastUri.exports;
3550
3550
  hasRequiredFastUri = 1;
3551
- const { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = requireUtils$2();
3551
+ const { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4: isIPv42, nonSimpleDomain } = requireUtils$2();
3552
3552
  const { SCHEMES, getSchemeHandler } = requireSchemes();
3553
3553
  function normalize(uri2, options) {
3554
3554
  if (typeof uri2 === "string") {
@@ -3729,7 +3729,7 @@ function requireFastUri() {
3729
3729
  parsed.port = matches[5];
3730
3730
  }
3731
3731
  if (parsed.host) {
3732
- const ipv4result = isIPv4(parsed.host);
3732
+ const ipv4result = isIPv42(parsed.host);
3733
3733
  if (ipv4result === false) {
3734
3734
  const ipv6result = normalizeIPv6(parsed.host);
3735
3735
  parsed.host = ipv6result.host.toLowerCase();
@@ -26982,10 +26982,11 @@ const DEFAULT_REMOTE_URL = "https://chat.opentiny.design";
26982
26982
  const DEFAULT_QR_CODE_URL = "https://ai.opentiny.design/next-remoter";
26983
26983
  const DEFAULT_LOGO_URL = "https://ai.opentiny.design/next-remoter/svgs/logo-next-no-bg-left.svg";
26984
26984
  const getDefaultMenuItems = (options) => {
26985
- return [
26985
+ const hasSession = !!options.sessionId;
26986
+ const baseItems = [
26986
26987
  {
26987
26988
  action: "qr-code",
26988
- show: true,
26989
+ show: hasSession,
26989
26990
  text: "扫码登录",
26990
26991
  desc: "使用手机遥控页面",
26991
26992
  icon: qrCode
@@ -26999,7 +27000,7 @@ const getDefaultMenuItems = (options) => {
26999
27000
  },
27000
27001
  {
27001
27002
  action: "remote-url",
27002
- show: true,
27003
+ show: hasSession,
27003
27004
  text: `遥控器链接`,
27004
27005
  desc: `${options.remoteUrl}`,
27005
27006
  active: true,
@@ -27009,14 +27010,15 @@ const getDefaultMenuItems = (options) => {
27009
27010
  },
27010
27011
  {
27011
27012
  action: "remote-control",
27012
- show: true,
27013
+ show: hasSession,
27013
27014
  text: `识别码`,
27014
- desc: `${options.sessionId.slice(-6)}`,
27015
+ desc: hasSession ? `${options.sessionId.slice(-6)}` : "",
27015
27016
  know: true,
27016
27017
  showCopyIcon: true,
27017
27018
  icon: scan
27018
27019
  }
27019
27020
  ];
27021
+ return baseItems;
27020
27022
  };
27021
27023
  class FloatingBlock {
27022
27024
  constructor(options) {
@@ -27048,9 +27050,6 @@ class FloatingBlock {
27048
27050
  trigger: "hover"
27049
27051
  });
27050
27052
  };
27051
- if (!options.sessionId) {
27052
- throw new Error("sessionId is required");
27053
- }
27054
27053
  this.options = {
27055
27054
  ...options,
27056
27055
  qrCodeUrl: options.qrCodeUrl || DEFAULT_QR_CODE_URL,
@@ -27069,11 +27068,14 @@ class FloatingBlock {
27069
27068
  return this.options.qrCodeUrl?.includes("?") ? "&sessionId=" : "?sessionId=";
27070
27069
  }
27071
27070
  /**
27072
- * 合并菜单项配置
27073
- * @param userMenuItems 用户自定义菜单项配置
27074
- * @returns 合并后的菜单项配置
27071
+ * 合并菜单项配置。
27072
+ * - sessionId:使用默认菜单 + 用户配置(可定制每一项的 show/text/icon 等)
27073
+ * - 无 sessionId:不渲染任何下拉菜单,仅保留点击浮标打开对话框的能力
27075
27074
  */
27076
27075
  mergeMenuItems(userMenuItems) {
27076
+ if (!this.options.sessionId) {
27077
+ return [];
27078
+ }
27077
27079
  if (!userMenuItems) {
27078
27080
  return getDefaultMenuItems(this.options);
27079
27081
  }
@@ -27083,7 +27085,6 @@ class FloatingBlock {
27083
27085
  return {
27084
27086
  ...defaultItem,
27085
27087
  ...userItem,
27086
- // 确保show属性存在,默认为true
27087
27088
  show: userItem.show !== void 0 ? userItem.show : defaultItem.show
27088
27089
  };
27089
27090
  }
@@ -27227,9 +27228,11 @@ class FloatingBlock {
27227
27228
  this.closeDropdown();
27228
27229
  }
27229
27230
  copyRemoteControl() {
27231
+ if (!this.options.sessionId) return;
27230
27232
  this.copyToClipboard(this.options.sessionId.slice(-6));
27231
27233
  }
27232
27234
  copyRemoteURL() {
27235
+ if (!this.options.sessionId) return;
27233
27236
  this.copyToClipboard(this.options.remoteUrl + this.sessionPrefix + this.options.sessionId);
27234
27237
  }
27235
27238
  // 实现复制到剪贴板功能
@@ -27277,8 +27280,9 @@ class FloatingBlock {
27277
27280
  }, 300);
27278
27281
  }, 1500);
27279
27282
  }
27280
- // 创建二维码弹窗
27283
+ // 创建二维码弹窗(无 sessionId 时不展示)
27281
27284
  async showQRCode() {
27285
+ if (!this.options.sessionId) return;
27282
27286
  const qrCode2 = new QrCode((this.options.qrCodeUrl || "") + this.sessionPrefix + this.options.sessionId, {});
27283
27287
  const base642 = await qrCode2.toDataURL();
27284
27288
  const modal = this.createModal(
@@ -27754,6 +27758,19 @@ class FloatingBlock {
27754
27758
  this.dropdownMenu.parentNode.removeChild(this.dropdownMenu);
27755
27759
  }
27756
27760
  }
27761
+ // 隐藏组件
27762
+ hide() {
27763
+ if (this.floatingBlock) {
27764
+ this.floatingBlock.style.display = "none";
27765
+ }
27766
+ this.closeDropdown();
27767
+ }
27768
+ // 显示组件
27769
+ show() {
27770
+ if (this.floatingBlock) {
27771
+ this.floatingBlock.style.display = "flex";
27772
+ }
27773
+ }
27757
27774
  }
27758
27775
  const createRemoter = (options = {}) => {
27759
27776
  return new FloatingBlock(options);
@@ -28049,25 +28066,30 @@ function combineHeaders$1(...headers) {
28049
28066
  }
28050
28067
  function createToolNameMapping({
28051
28068
  tools = [],
28052
- providerToolNames
28069
+ providerToolNames,
28070
+ resolveProviderToolName
28053
28071
  }) {
28072
+ var _a22;
28054
28073
  const customToolNameToProviderToolName = {};
28055
28074
  const providerToolNameToCustomToolName = {};
28056
28075
  for (const tool2 of tools) {
28057
- if (tool2.type === "provider" && tool2.id in providerToolNames) {
28058
- const providerToolName = providerToolNames[tool2.id];
28076
+ if (tool2.type === "provider") {
28077
+ const providerToolName = (_a22 = resolveProviderToolName == null ? void 0 : resolveProviderToolName(tool2)) != null ? _a22 : tool2.id in providerToolNames ? providerToolNames[tool2.id] : void 0;
28078
+ if (providerToolName == null) {
28079
+ continue;
28080
+ }
28059
28081
  customToolNameToProviderToolName[tool2.name] = providerToolName;
28060
28082
  providerToolNameToCustomToolName[providerToolName] = tool2.name;
28061
28083
  }
28062
28084
  }
28063
28085
  return {
28064
28086
  toProviderToolName: (customToolName) => {
28065
- var _a22;
28066
- return (_a22 = customToolNameToProviderToolName[customToolName]) != null ? _a22 : customToolName;
28087
+ var _a32;
28088
+ return (_a32 = customToolNameToProviderToolName[customToolName]) != null ? _a32 : customToolName;
28067
28089
  },
28068
28090
  toCustomToolName: (providerToolName) => {
28069
- var _a22;
28070
- return (_a22 = providerToolNameToCustomToolName[providerToolName]) != null ? _a22 : providerToolName;
28091
+ var _a32;
28092
+ return (_a32 = providerToolNameToCustomToolName[providerToolName]) != null ? _a32 : providerToolName;
28071
28093
  }
28072
28094
  };
28073
28095
  }
@@ -28260,8 +28282,103 @@ async function readResponseWithSizeLimit({
28260
28282
  }
28261
28283
  return result;
28262
28284
  }
28285
+ function validateDownloadUrl(url2) {
28286
+ let parsed;
28287
+ try {
28288
+ parsed = new URL(url2);
28289
+ } catch (e) {
28290
+ throw new DownloadError({
28291
+ url: url2,
28292
+ message: `Invalid URL: ${url2}`
28293
+ });
28294
+ }
28295
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
28296
+ throw new DownloadError({
28297
+ url: url2,
28298
+ message: `URL scheme must be http or https, got ${parsed.protocol}`
28299
+ });
28300
+ }
28301
+ const hostname2 = parsed.hostname;
28302
+ if (!hostname2) {
28303
+ throw new DownloadError({
28304
+ url: url2,
28305
+ message: `URL must have a hostname`
28306
+ });
28307
+ }
28308
+ if (hostname2 === "localhost" || hostname2.endsWith(".local") || hostname2.endsWith(".localhost")) {
28309
+ throw new DownloadError({
28310
+ url: url2,
28311
+ message: `URL with hostname ${hostname2} is not allowed`
28312
+ });
28313
+ }
28314
+ if (hostname2.startsWith("[") && hostname2.endsWith("]")) {
28315
+ const ipv62 = hostname2.slice(1, -1);
28316
+ if (isPrivateIPv6(ipv62)) {
28317
+ throw new DownloadError({
28318
+ url: url2,
28319
+ message: `URL with IPv6 address ${hostname2} is not allowed`
28320
+ });
28321
+ }
28322
+ return;
28323
+ }
28324
+ if (isIPv4(hostname2)) {
28325
+ if (isPrivateIPv4(hostname2)) {
28326
+ throw new DownloadError({
28327
+ url: url2,
28328
+ message: `URL with IP address ${hostname2} is not allowed`
28329
+ });
28330
+ }
28331
+ return;
28332
+ }
28333
+ }
28334
+ function isIPv4(hostname2) {
28335
+ const parts = hostname2.split(".");
28336
+ if (parts.length !== 4) return false;
28337
+ return parts.every((part) => {
28338
+ const num = Number(part);
28339
+ return Number.isInteger(num) && num >= 0 && num <= 255 && String(num) === part;
28340
+ });
28341
+ }
28342
+ function isPrivateIPv4(ip) {
28343
+ const parts = ip.split(".").map(Number);
28344
+ const [a, b] = parts;
28345
+ if (a === 0) return true;
28346
+ if (a === 10) return true;
28347
+ if (a === 127) return true;
28348
+ if (a === 169 && b === 254) return true;
28349
+ if (a === 172 && b >= 16 && b <= 31) return true;
28350
+ if (a === 192 && b === 168) return true;
28351
+ return false;
28352
+ }
28353
+ function isPrivateIPv6(ip) {
28354
+ const normalized = ip.toLowerCase();
28355
+ if (normalized === "::1") return true;
28356
+ if (normalized === "::") return true;
28357
+ if (normalized.startsWith("::ffff:")) {
28358
+ const mappedPart = normalized.slice(7);
28359
+ if (isIPv4(mappedPart)) {
28360
+ return isPrivateIPv4(mappedPart);
28361
+ }
28362
+ const hexParts = mappedPart.split(":");
28363
+ if (hexParts.length === 2) {
28364
+ const high = parseInt(hexParts[0], 16);
28365
+ const low = parseInt(hexParts[1], 16);
28366
+ if (!isNaN(high) && !isNaN(low)) {
28367
+ const a = high >> 8 & 255;
28368
+ const b = high & 255;
28369
+ const c = low >> 8 & 255;
28370
+ const d = low & 255;
28371
+ return isPrivateIPv4(`${a}.${b}.${c}.${d}`);
28372
+ }
28373
+ }
28374
+ }
28375
+ if (normalized.startsWith("fc") || normalized.startsWith("fd")) return true;
28376
+ if (normalized.startsWith("fe80")) return true;
28377
+ return false;
28378
+ }
28263
28379
  async function downloadBlob(url2, options) {
28264
28380
  var _a22, _b22;
28381
+ validateDownloadUrl(url2);
28265
28382
  try {
28266
28383
  const response = await fetch(url2, {
28267
28384
  signal: options == null ? void 0 : options.abortSignal
@@ -28427,7 +28544,7 @@ function withUserAgentSuffix$1(headers, ...userAgentSuffixParts) {
28427
28544
  );
28428
28545
  return Object.fromEntries(normalizedHeaders.entries());
28429
28546
  }
28430
- var VERSION$7 = "4.0.15";
28547
+ var VERSION$7 = "4.0.19";
28431
28548
  var getOriginalFetch = () => globalThis.fetch;
28432
28549
  var getFromApi = async ({
28433
28550
  url: url2,
@@ -28570,8 +28687,8 @@ function mediaTypeToExtension(mediaType) {
28570
28687
  "x-m4a": "m4a"
28571
28688
  }[subtype]) != null ? _a22 : subtype;
28572
28689
  }
28573
- var suspectProtoRx$1 = /"__proto__"\s*:/;
28574
- var suspectConstructorRx$1 = /"constructor"\s*:/;
28690
+ var suspectProtoRx$1 = /"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*:/;
28691
+ var suspectConstructorRx$1 = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
28575
28692
  function _parse$1(text2) {
28576
28693
  const obj = JSON.parse(text2);
28577
28694
  if (obj === null || typeof obj !== "object") {
@@ -28591,7 +28708,7 @@ function filter$1(obj) {
28591
28708
  if (Object.prototype.hasOwnProperty.call(node, "__proto__")) {
28592
28709
  throw new SyntaxError("Object contains forbidden prototype property");
28593
28710
  }
28594
- if (Object.prototype.hasOwnProperty.call(node, "constructor") && Object.prototype.hasOwnProperty.call(node.constructor, "prototype")) {
28711
+ if (Object.prototype.hasOwnProperty.call(node, "constructor") && node.constructor !== null && typeof node.constructor === "object" && Object.prototype.hasOwnProperty.call(node.constructor, "prototype")) {
28595
28712
  throw new SyntaxError("Object contains forbidden prototype property");
28596
28713
  }
28597
28714
  for (const key in node) {
@@ -30078,6 +30195,33 @@ function tool(tool2) {
30078
30195
  function dynamicTool(tool2) {
30079
30196
  return { ...tool2, type: "dynamic" };
30080
30197
  }
30198
+ function createProviderToolFactory({
30199
+ id: id2,
30200
+ inputSchema
30201
+ }) {
30202
+ return ({
30203
+ execute,
30204
+ outputSchema: outputSchema2,
30205
+ needsApproval,
30206
+ toModelOutput,
30207
+ onInputStart,
30208
+ onInputDelta,
30209
+ onInputAvailable,
30210
+ ...args
30211
+ }) => tool({
30212
+ type: "provider",
30213
+ id: id2,
30214
+ args,
30215
+ inputSchema,
30216
+ outputSchema: outputSchema2,
30217
+ execute,
30218
+ needsApproval,
30219
+ toModelOutput,
30220
+ onInputStart,
30221
+ onInputDelta,
30222
+ onInputAvailable
30223
+ });
30224
+ }
30081
30225
  function createProviderToolFactoryWithOutputSchema({
30082
30226
  id: id2,
30083
30227
  inputSchema,
@@ -31548,7 +31692,7 @@ async function getVercelRequestId() {
31548
31692
  var _a92;
31549
31693
  return (_a92 = indexBrowserExports.getContext().headers) == null ? void 0 : _a92["x-vercel-id"];
31550
31694
  }
31551
- var VERSION$6 = "3.0.58";
31695
+ var VERSION$6 = "3.0.66";
31552
31696
  var AI_GATEWAY_PROTOCOL_VERSION = "0.0.1";
31553
31697
  function createGatewayProvider(options = {}) {
31554
31698
  var _a92, _b9;
@@ -32686,6 +32830,8 @@ function asArray(value) {
32686
32830
  }
32687
32831
  async function notify(options) {
32688
32832
  for (const callback of asArray(options.callbacks)) {
32833
+ if (callback == null)
32834
+ continue;
32689
32835
  try {
32690
32836
  await callback(options.event);
32691
32837
  } catch (_ignored) {
@@ -32992,7 +33138,7 @@ function detectMediaType({
32992
33138
  }
32993
33139
  return void 0;
32994
33140
  }
32995
- var VERSION$4 = "6.0.104";
33141
+ var VERSION$4 = "6.0.116";
32996
33142
  var download = async ({
32997
33143
  url: url2,
32998
33144
  maxBytes,
@@ -33000,6 +33146,7 @@ var download = async ({
33000
33146
  }) => {
33001
33147
  var _a21;
33002
33148
  const urlText = url2.toString();
33149
+ validateDownloadUrl(urlText);
33003
33150
  try {
33004
33151
  const response = await fetch(urlText, {
33005
33152
  headers: withUserAgentSuffix$1(
@@ -34105,6 +34252,44 @@ function stringifyForTelemetry(prompt) {
34105
34252
  }))
34106
34253
  );
34107
34254
  }
34255
+ function getGlobalTelemetryIntegrations() {
34256
+ var _a21;
34257
+ return (_a21 = globalThis.AI_SDK_TELEMETRY_INTEGRATIONS) != null ? _a21 : [];
34258
+ }
34259
+ function getGlobalTelemetryIntegration() {
34260
+ const globalIntegrations = getGlobalTelemetryIntegrations();
34261
+ return (integrations) => {
34262
+ const localIntegrations = asArray(integrations);
34263
+ const allIntegrations = [...globalIntegrations, ...localIntegrations];
34264
+ function createTelemetryComposite(getListenerFromIntegration) {
34265
+ const listeners = allIntegrations.map(getListenerFromIntegration).filter(Boolean);
34266
+ return async (event) => {
34267
+ for (const listener of listeners) {
34268
+ try {
34269
+ await listener(event);
34270
+ } catch (_ignored) {
34271
+ }
34272
+ }
34273
+ };
34274
+ }
34275
+ return {
34276
+ onStart: createTelemetryComposite((integration) => integration.onStart),
34277
+ onStepStart: createTelemetryComposite(
34278
+ (integration) => integration.onStepStart
34279
+ ),
34280
+ onToolCallStart: createTelemetryComposite(
34281
+ (integration) => integration.onToolCallStart
34282
+ ),
34283
+ onToolCallFinish: createTelemetryComposite(
34284
+ (integration) => integration.onToolCallFinish
34285
+ ),
34286
+ onStepFinish: createTelemetryComposite(
34287
+ (integration) => integration.onStepFinish
34288
+ ),
34289
+ onFinish: createTelemetryComposite((integration) => integration.onFinish)
34290
+ };
34291
+ };
34292
+ }
34108
34293
  function asLanguageModelUsage(usage) {
34109
34294
  return {
34110
34295
  inputTokens: usage.inputTokens.total,
@@ -35655,6 +35840,7 @@ async function generateText({
35655
35840
  ...settings
35656
35841
  }) {
35657
35842
  const model = resolveLanguageModel(modelArg);
35843
+ const createGlobalTelemetry = getGlobalTelemetryIntegration();
35658
35844
  const stopConditions = asArray(stopWhen);
35659
35845
  const totalTimeoutMs = getTotalTimeoutMs(timeout);
35660
35846
  const stepTimeoutMs = getStepTimeoutMs(timeout);
@@ -35685,6 +35871,7 @@ async function generateText({
35685
35871
  prompt,
35686
35872
  messages
35687
35873
  });
35874
+ const globalTelemetry = createGlobalTelemetry(telemetry == null ? void 0 : telemetry.integrations);
35688
35875
  await notify({
35689
35876
  event: {
35690
35877
  model: modelInfo,
@@ -35714,7 +35901,10 @@ async function generateText({
35714
35901
  metadata: telemetry == null ? void 0 : telemetry.metadata,
35715
35902
  experimental_context
35716
35903
  },
35717
- callbacks: onStart
35904
+ callbacks: [
35905
+ onStart,
35906
+ globalTelemetry.onStart
35907
+ ]
35718
35908
  });
35719
35909
  const tracer = getTracer(telemetry);
35720
35910
  try {
@@ -35759,8 +35949,14 @@ async function generateText({
35759
35949
  experimental_context,
35760
35950
  stepNumber: 0,
35761
35951
  model: modelInfo,
35762
- onToolCallStart,
35763
- onToolCallFinish
35952
+ onToolCallStart: [
35953
+ onToolCallStart,
35954
+ globalTelemetry.onToolCallStart
35955
+ ],
35956
+ onToolCallFinish: [
35957
+ onToolCallFinish,
35958
+ globalTelemetry.onToolCallFinish
35959
+ ]
35764
35960
  });
35765
35961
  const toolContent = [];
35766
35962
  for (const output2 of toolOutputs) {
@@ -35769,7 +35965,7 @@ async function generateText({
35769
35965
  input: output2.input,
35770
35966
  tool: tools == null ? void 0 : tools[output2.toolName],
35771
35967
  output: output2.type === "tool-result" ? output2.output : output2.error,
35772
- errorMode: output2.type === "tool-error" ? "json" : "none"
35968
+ errorMode: output2.type === "tool-error" ? "text" : "none"
35773
35969
  });
35774
35970
  toolContent.push({
35775
35971
  type: "tool-result",
@@ -35886,7 +36082,10 @@ async function generateText({
35886
36082
  metadata: telemetry == null ? void 0 : telemetry.metadata,
35887
36083
  experimental_context
35888
36084
  },
35889
- callbacks: onStepStart
36085
+ callbacks: [
36086
+ onStepStart,
36087
+ globalTelemetry.onStepStart
36088
+ ]
35890
36089
  });
35891
36090
  currentModelResponse = await retry(
35892
36091
  () => {
@@ -36064,8 +36263,14 @@ async function generateText({
36064
36263
  experimental_context,
36065
36264
  stepNumber: steps.length,
36066
36265
  model: stepModelInfo,
36067
- onToolCallStart,
36068
- onToolCallFinish
36266
+ onToolCallStart: [
36267
+ onToolCallStart,
36268
+ globalTelemetry.onToolCallStart
36269
+ ],
36270
+ onToolCallFinish: [
36271
+ onToolCallFinish,
36272
+ globalTelemetry.onToolCallFinish
36273
+ ]
36069
36274
  })
36070
36275
  );
36071
36276
  }
@@ -36132,7 +36337,10 @@ async function generateText({
36132
36337
  model: stepModelInfo.modelId
36133
36338
  });
36134
36339
  steps.push(currentStepResult);
36135
- await notify({ event: currentStepResult, callbacks: onStepFinish });
36340
+ await notify({
36341
+ event: currentStepResult,
36342
+ callbacks: [onStepFinish, globalTelemetry.onStepFinish]
36343
+ });
36136
36344
  } finally {
36137
36345
  if (stepTimeoutId != null) {
36138
36346
  clearTimeout(stepTimeoutId);
@@ -36213,7 +36421,10 @@ async function generateText({
36213
36421
  steps,
36214
36422
  totalUsage
36215
36423
  },
36216
- callbacks: onFinish
36424
+ callbacks: [
36425
+ onFinish,
36426
+ globalTelemetry.onFinish
36427
+ ]
36217
36428
  });
36218
36429
  let resolvedOutput;
36219
36430
  if (lastStep.finishReason === "stop") {
@@ -36832,7 +37043,8 @@ function processUIMessageStream({
36832
37043
  state.message.parts.push({
36833
37044
  type: "file",
36834
37045
  mediaType: chunk.mediaType,
36835
- url: chunk.url
37046
+ url: chunk.url,
37047
+ ...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {}
36836
37048
  });
36837
37049
  write();
36838
37050
  break;
@@ -37489,7 +37701,8 @@ function runToolsTransformation({
37489
37701
  file: new DefaultGeneratedFileWithType({
37490
37702
  data: chunk.data,
37491
37703
  mediaType: chunk.mediaType
37492
- })
37704
+ }),
37705
+ ...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {}
37493
37706
  });
37494
37707
  break;
37495
37708
  }
@@ -37877,6 +38090,8 @@ var DefaultStreamTextResult = class {
37877
38090
  this.outputSpecification = output;
37878
38091
  this.includeRawChunks = includeRawChunks;
37879
38092
  this.tools = tools;
38093
+ const createGlobalTelemetry = getGlobalTelemetryIntegration();
38094
+ const globalTelemetry = createGlobalTelemetry(telemetry == null ? void 0 : telemetry.integrations);
37880
38095
  let stepFinish;
37881
38096
  let recordedContent = [];
37882
38097
  const recordedResponseMessages = [];
@@ -37978,7 +38193,11 @@ var DefaultStreamTextResult = class {
37978
38193
  delete activeReasoningContent[part.id];
37979
38194
  }
37980
38195
  if (part.type === "file") {
37981
- recordedContent.push({ type: "file", file: part.file });
38196
+ recordedContent.push({
38197
+ type: "file",
38198
+ file: part.file,
38199
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
38200
+ });
37982
38201
  }
37983
38202
  if (part.type === "source") {
37984
38203
  recordedContent.push(part);
@@ -38024,7 +38243,10 @@ var DefaultStreamTextResult = class {
38024
38243
  },
38025
38244
  providerMetadata: part.providerMetadata
38026
38245
  });
38027
- await notify({ event: currentStepResult, callbacks: onStepFinish });
38246
+ await notify({
38247
+ event: currentStepResult,
38248
+ callbacks: [onStepFinish, globalTelemetry.onStepFinish]
38249
+ });
38028
38250
  logWarnings({
38029
38251
  warnings: recordedWarnings,
38030
38252
  provider: modelInfo.provider,
@@ -38088,7 +38310,10 @@ var DefaultStreamTextResult = class {
38088
38310
  providerMetadata: finalStep.providerMetadata,
38089
38311
  steps: recordedSteps
38090
38312
  },
38091
- callbacks: onFinish
38313
+ callbacks: [
38314
+ onFinish,
38315
+ globalTelemetry.onFinish
38316
+ ]
38092
38317
  });
38093
38318
  rootSpan.setAttributes(
38094
38319
  await selectTelemetryAttributes({
@@ -38245,7 +38470,10 @@ var DefaultStreamTextResult = class {
38245
38470
  ...callbackTelemetryProps,
38246
38471
  experimental_context
38247
38472
  },
38248
- callbacks: onStart
38473
+ callbacks: [
38474
+ onStart,
38475
+ globalTelemetry.onStart
38476
+ ]
38249
38477
  });
38250
38478
  const initialMessages = initialPrompt.messages;
38251
38479
  const initialResponseMessages = [];
@@ -38295,8 +38523,14 @@ var DefaultStreamTextResult = class {
38295
38523
  experimental_context,
38296
38524
  stepNumber: recordedSteps.length,
38297
38525
  model: modelInfo,
38298
- onToolCallStart,
38299
- onToolCallFinish,
38526
+ onToolCallStart: [
38527
+ onToolCallStart,
38528
+ globalTelemetry.onToolCallStart
38529
+ ],
38530
+ onToolCallFinish: [
38531
+ onToolCallFinish,
38532
+ globalTelemetry.onToolCallFinish
38533
+ ],
38300
38534
  onPreliminaryToolResult: (result2) => {
38301
38535
  toolExecutionStepStreamController == null ? void 0 : toolExecutionStepStreamController.enqueue(result2);
38302
38536
  }
@@ -38333,7 +38567,7 @@ var DefaultStreamTextResult = class {
38333
38567
  input: output2.input,
38334
38568
  tool: tools == null ? void 0 : tools[output2.toolName],
38335
38569
  output: output2.type === "tool-result" ? output2.output : output2.error,
38336
- errorMode: output2.type === "tool-error" ? "json" : "none"
38570
+ errorMode: output2.type === "tool-error" ? "text" : "none"
38337
38571
  })
38338
38572
  });
38339
38573
  }
@@ -38447,7 +38681,10 @@ var DefaultStreamTextResult = class {
38447
38681
  ...callbackTelemetryProps,
38448
38682
  experimental_context
38449
38683
  },
38450
- callbacks: onStepStart
38684
+ callbacks: [
38685
+ onStepStart,
38686
+ globalTelemetry.onStepStart
38687
+ ]
38451
38688
  });
38452
38689
  const {
38453
38690
  result: { stream: stream2, response, request },
@@ -38523,8 +38760,14 @@ var DefaultStreamTextResult = class {
38523
38760
  generateId: generateId2,
38524
38761
  stepNumber: recordedSteps.length,
38525
38762
  model: stepModelInfo,
38526
- onToolCallStart,
38527
- onToolCallFinish
38763
+ onToolCallStart: [
38764
+ onToolCallStart,
38765
+ globalTelemetry.onToolCallStart
38766
+ ],
38767
+ onToolCallFinish: [
38768
+ onToolCallFinish,
38769
+ globalTelemetry.onToolCallFinish
38770
+ ]
38528
38771
  });
38529
38772
  const stepRequest = ((_i = include == null ? void 0 : include.requestBody) != null ? _i : true) ? request != null ? request : {} : { ...request, body: void 0 };
38530
38773
  const stepToolCalls = [];
@@ -39106,7 +39349,8 @@ var DefaultStreamTextResult = class {
39106
39349
  controller.enqueue({
39107
39350
  type: "file",
39108
39351
  mediaType: part.file.mediaType,
39109
- url: `data:${part.file.mediaType};base64,${part.file.base64}`
39352
+ url: `data:${part.file.mediaType};base64,${part.file.base64}`,
39353
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
39110
39354
  });
39111
39355
  break;
39112
39356
  }
@@ -41428,7 +41672,7 @@ var openaiFailedResponseHandler = createJsonErrorResponseHandler$1({
41428
41672
  function getOpenAILanguageModelCapabilities(modelId) {
41429
41673
  const supportsFlexProcessing = modelId.startsWith("o3") || modelId.startsWith("o4-mini") || modelId.startsWith("gpt-5") && !modelId.startsWith("gpt-5-chat");
41430
41674
  const supportsPriorityProcessing = modelId.startsWith("gpt-4") || modelId.startsWith("gpt-5-mini") || modelId.startsWith("gpt-5") && !modelId.startsWith("gpt-5-nano") && !modelId.startsWith("gpt-5-chat") || modelId.startsWith("o3") || modelId.startsWith("o4-mini");
41431
- const isReasoningModel = modelId.startsWith("o1") || modelId.startsWith("o3") || modelId.startsWith("o4-mini") || modelId.startsWith("codex-mini") || modelId.startsWith("computer-use-preview") || modelId.startsWith("gpt-5") && !modelId.startsWith("gpt-5-chat");
41675
+ const isReasoningModel = modelId.startsWith("o1") || modelId.startsWith("o3") || modelId.startsWith("o4-mini") || modelId.startsWith("gpt-5") && !modelId.startsWith("gpt-5-chat");
41432
41676
  const supportsNonReasoningParameters = modelId.startsWith("gpt-5.1") || modelId.startsWith("gpt-5.2");
41433
41677
  const systemMessageMode = isReasoningModel ? "developer" : "system";
41434
41678
  return {
@@ -43335,6 +43579,30 @@ var codeInterpreterToolFactory = createProviderToolFactoryWithOutputSchema({
43335
43579
  var codeInterpreter = (args = {}) => {
43336
43580
  return codeInterpreterToolFactory(args);
43337
43581
  };
43582
+ var customArgsSchema = lazySchema(
43583
+ () => zodSchema(
43584
+ object$2({
43585
+ name: string(),
43586
+ description: string().optional(),
43587
+ format: union([
43588
+ object$2({
43589
+ type: literal("grammar"),
43590
+ syntax: _enum(["regex", "lark"]),
43591
+ definition: string()
43592
+ }),
43593
+ object$2({
43594
+ type: literal("text")
43595
+ })
43596
+ ]).optional()
43597
+ })
43598
+ )
43599
+ );
43600
+ var customInputSchema = lazySchema(() => zodSchema(string()));
43601
+ var customToolFactory = createProviderToolFactory({
43602
+ id: "openai.custom",
43603
+ inputSchema: customInputSchema
43604
+ });
43605
+ var customTool = (args) => customToolFactory(args);
43338
43606
  var comparisonFilterSchema = object$2({
43339
43607
  key: string(),
43340
43608
  type: _enum(["eq", "ne", "gt", "gte", "lt", "lte", "in", "nin"]),
@@ -43687,6 +43955,16 @@ var openaiTools = {
43687
43955
  *
43688
43956
  */
43689
43957
  applyPatch,
43958
+ /**
43959
+ * Custom tools let callers constrain model output to a grammar (regex or
43960
+ * Lark syntax). The model returns a `custom_tool_call` output item whose
43961
+ * `input` field is a string matching the specified grammar.
43962
+ *
43963
+ * @param name - The name of the custom tool.
43964
+ * @param description - An optional description of the tool.
43965
+ * @param format - The output format constraint (grammar type, syntax, and definition).
43966
+ */
43967
+ customTool,
43690
43968
  /**
43691
43969
  * The Code Interpreter tool allows models to write and run Python code in a
43692
43970
  * sandboxed environment to solve complex problems in domains like data analysis,
@@ -43727,7 +44005,7 @@ var openaiTools = {
43727
44005
  * Local shell is a tool that allows agents to run shell commands locally
43728
44006
  * on a machine you or the user provides.
43729
44007
  *
43730
- * Supported models: `gpt-5-codex` and `codex-mini-latest`
44008
+ * Supported models: `gpt-5-codex`
43731
44009
  */
43732
44010
  localShell,
43733
44011
  /**
@@ -43825,9 +44103,10 @@ async function convertToOpenAIResponsesInput({
43825
44103
  hasConversation = false,
43826
44104
  hasLocalShellTool = false,
43827
44105
  hasShellTool = false,
43828
- hasApplyPatchTool = false
44106
+ hasApplyPatchTool = false,
44107
+ customProviderToolNames
43829
44108
  }) {
43830
- var _a10, _b9, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
44109
+ var _a10, _b9, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
43831
44110
  const input = [];
43832
44111
  const warnings = [];
43833
44112
  const processedApprovalIds = /* @__PURE__ */ new Set();
@@ -43996,6 +44275,16 @@ async function convertToOpenAIResponsesInput({
43996
44275
  });
43997
44276
  break;
43998
44277
  }
44278
+ if (customProviderToolNames == null ? void 0 : customProviderToolNames.has(resolvedToolName)) {
44279
+ input.push({
44280
+ type: "custom_tool_call",
44281
+ call_id: part.toolCallId,
44282
+ name: resolvedToolName,
44283
+ input: typeof part.input === "string" ? part.input : JSON.stringify(part.input),
44284
+ id: id2
44285
+ });
44286
+ break;
44287
+ }
43999
44288
  input.push({
44000
44289
  type: "function_call",
44001
44290
  call_id: part.toolCallId,
@@ -44200,6 +44489,61 @@ async function convertToOpenAIResponsesInput({
44200
44489
  });
44201
44490
  continue;
44202
44491
  }
44492
+ if (customProviderToolNames == null ? void 0 : customProviderToolNames.has(resolvedToolName)) {
44493
+ let outputValue;
44494
+ switch (output.type) {
44495
+ case "text":
44496
+ case "error-text":
44497
+ outputValue = output.value;
44498
+ break;
44499
+ case "execution-denied":
44500
+ outputValue = (_l = output.reason) != null ? _l : "Tool execution denied.";
44501
+ break;
44502
+ case "json":
44503
+ case "error-json":
44504
+ outputValue = JSON.stringify(output.value);
44505
+ break;
44506
+ case "content":
44507
+ outputValue = output.value.map((item) => {
44508
+ var _a22;
44509
+ switch (item.type) {
44510
+ case "text":
44511
+ return { type: "input_text", text: item.text };
44512
+ case "image-data":
44513
+ return {
44514
+ type: "input_image",
44515
+ image_url: `data:${item.mediaType};base64,${item.data}`
44516
+ };
44517
+ case "image-url":
44518
+ return {
44519
+ type: "input_image",
44520
+ image_url: item.url
44521
+ };
44522
+ case "file-data":
44523
+ return {
44524
+ type: "input_file",
44525
+ filename: (_a22 = item.filename) != null ? _a22 : "data",
44526
+ file_data: `data:${item.mediaType};base64,${item.data}`
44527
+ };
44528
+ default:
44529
+ warnings.push({
44530
+ type: "other",
44531
+ message: `unsupported custom tool content part type: ${item.type}`
44532
+ });
44533
+ return void 0;
44534
+ }
44535
+ }).filter(isNonNullable);
44536
+ break;
44537
+ default:
44538
+ outputValue = "";
44539
+ }
44540
+ input.push({
44541
+ type: "custom_tool_call_output",
44542
+ call_id: part.toolCallId,
44543
+ output: outputValue
44544
+ });
44545
+ continue;
44546
+ }
44203
44547
  let contentValue;
44204
44548
  switch (output.type) {
44205
44549
  case "text":
@@ -44207,7 +44551,7 @@ async function convertToOpenAIResponsesInput({
44207
44551
  contentValue = output.value;
44208
44552
  break;
44209
44553
  case "execution-denied":
44210
- contentValue = (_l = output.reason) != null ? _l : "Tool execution denied.";
44554
+ contentValue = (_m = output.reason) != null ? _m : "Tool execution denied.";
44211
44555
  break;
44212
44556
  case "json":
44213
44557
  case "error-json":
@@ -44416,6 +44760,13 @@ var openaiResponsesChunkSchema = lazySchema(
44416
44760
  })
44417
44761
  ])
44418
44762
  }),
44763
+ object$2({
44764
+ type: literal("custom_tool_call"),
44765
+ id: string(),
44766
+ call_id: string(),
44767
+ name: string(),
44768
+ input: string()
44769
+ }),
44419
44770
  object$2({
44420
44771
  type: literal("shell_call"),
44421
44772
  id: string(),
@@ -44468,6 +44819,14 @@ var openaiResponsesChunkSchema = lazySchema(
44468
44819
  arguments: string(),
44469
44820
  status: literal("completed")
44470
44821
  }),
44822
+ object$2({
44823
+ type: literal("custom_tool_call"),
44824
+ id: string(),
44825
+ call_id: string(),
44826
+ name: string(),
44827
+ input: string(),
44828
+ status: literal("completed")
44829
+ }),
44471
44830
  object$2({
44472
44831
  type: literal("code_interpreter_call"),
44473
44832
  id: string(),
@@ -44651,6 +45010,12 @@ var openaiResponsesChunkSchema = lazySchema(
44651
45010
  output_index: number$1(),
44652
45011
  delta: string()
44653
45012
  }),
45013
+ object$2({
45014
+ type: literal("response.custom_tool_call_input.delta"),
45015
+ item_id: string(),
45016
+ output_index: number$1(),
45017
+ delta: string()
45018
+ }),
44654
45019
  object$2({
44655
45020
  type: literal("response.image_generation_call.partial_image"),
44656
45021
  item_id: string(),
@@ -44898,6 +45263,13 @@ var openaiResponsesResponseSchema = lazySchema(
44898
45263
  arguments: string(),
44899
45264
  id: string()
44900
45265
  }),
45266
+ object$2({
45267
+ type: literal("custom_tool_call"),
45268
+ call_id: string(),
45269
+ name: string(),
45270
+ input: string(),
45271
+ id: string()
45272
+ }),
44901
45273
  object$2({
44902
45274
  type: literal("computer_call"),
44903
45275
  id: string(),
@@ -45181,14 +45553,18 @@ var openaiLanguageModelResponsesOptionsSchema = lazySchema(
45181
45553
  );
45182
45554
  async function prepareResponsesTools({
45183
45555
  tools,
45184
- toolChoice
45556
+ toolChoice,
45557
+ toolNameMapping,
45558
+ customProviderToolNames
45185
45559
  }) {
45560
+ var _a10;
45186
45561
  tools = (tools == null ? void 0 : tools.length) ? tools : void 0;
45187
45562
  const toolWarnings = [];
45188
45563
  if (tools == null) {
45189
45564
  return { tools: void 0, toolChoice: void 0, toolWarnings };
45190
45565
  }
45191
45566
  const openaiTools2 = [];
45567
+ const resolvedCustomProviderToolNames = customProviderToolNames != null ? customProviderToolNames : /* @__PURE__ */ new Set();
45192
45568
  for (const tool2 of tools) {
45193
45569
  switch (tool2.type) {
45194
45570
  case "function":
@@ -45330,6 +45706,20 @@ async function prepareResponsesTools({
45330
45706
  });
45331
45707
  break;
45332
45708
  }
45709
+ case "openai.custom": {
45710
+ const args = await validateTypes$1({
45711
+ value: tool2.args,
45712
+ schema: customArgsSchema
45713
+ });
45714
+ openaiTools2.push({
45715
+ type: "custom",
45716
+ name: args.name,
45717
+ description: args.description,
45718
+ format: args.format
45719
+ });
45720
+ resolvedCustomProviderToolNames.add(args.name);
45721
+ break;
45722
+ }
45333
45723
  }
45334
45724
  break;
45335
45725
  }
@@ -45350,12 +45740,14 @@ async function prepareResponsesTools({
45350
45740
  case "none":
45351
45741
  case "required":
45352
45742
  return { tools: openaiTools2, toolChoice: type2, toolWarnings };
45353
- case "tool":
45743
+ case "tool": {
45744
+ const resolvedToolName = (_a10 = toolNameMapping == null ? void 0 : toolNameMapping.toProviderToolName(toolChoice.toolName)) != null ? _a10 : toolChoice.toolName;
45354
45745
  return {
45355
45746
  tools: openaiTools2,
45356
- toolChoice: toolChoice.toolName === "code_interpreter" || toolChoice.toolName === "file_search" || toolChoice.toolName === "image_generation" || toolChoice.toolName === "web_search_preview" || toolChoice.toolName === "web_search" || toolChoice.toolName === "mcp" || toolChoice.toolName === "apply_patch" ? { type: toolChoice.toolName } : { type: "function", name: toolChoice.toolName },
45747
+ toolChoice: resolvedToolName === "code_interpreter" || resolvedToolName === "file_search" || resolvedToolName === "image_generation" || resolvedToolName === "web_search_preview" || resolvedToolName === "web_search" || resolvedToolName === "mcp" || resolvedToolName === "apply_patch" ? { type: resolvedToolName } : resolvedCustomProviderToolNames.has(resolvedToolName) ? { type: "custom", name: resolvedToolName } : { type: "function", name: resolvedToolName },
45357
45748
  toolWarnings
45358
45749
  };
45750
+ }
45359
45751
  default: {
45360
45752
  const _exhaustiveCheck = type2;
45361
45753
  throw new UnsupportedFunctionalityError$1({
@@ -45504,7 +45896,19 @@ var OpenAIResponsesLanguageModel = class {
45504
45896
  "openai.web_search_preview": "web_search_preview",
45505
45897
  "openai.mcp": "mcp",
45506
45898
  "openai.apply_patch": "apply_patch"
45507
- }
45899
+ },
45900
+ resolveProviderToolName: (tool2) => tool2.id === "openai.custom" ? tool2.args.name : void 0
45901
+ });
45902
+ const customProviderToolNames = /* @__PURE__ */ new Set();
45903
+ const {
45904
+ tools: openaiTools2,
45905
+ toolChoice: openaiToolChoice,
45906
+ toolWarnings
45907
+ } = await prepareResponsesTools({
45908
+ tools,
45909
+ toolChoice,
45910
+ toolNameMapping,
45911
+ customProviderToolNames
45508
45912
  });
45509
45913
  const { input, warnings: inputWarnings } = await convertToOpenAIResponsesInput({
45510
45914
  prompt,
@@ -45516,7 +45920,8 @@ var OpenAIResponsesLanguageModel = class {
45516
45920
  hasConversation: (openaiOptions == null ? void 0 : openaiOptions.conversation) != null,
45517
45921
  hasLocalShellTool: hasOpenAITool("openai.local_shell"),
45518
45922
  hasShellTool: hasOpenAITool("openai.shell"),
45519
- hasApplyPatchTool: hasOpenAITool("openai.apply_patch")
45923
+ hasApplyPatchTool: hasOpenAITool("openai.apply_patch"),
45924
+ customProviderToolNames: customProviderToolNames.size > 0 ? customProviderToolNames : void 0
45520
45925
  });
45521
45926
  warnings.push(...inputWarnings);
45522
45927
  const strictJsonSchema = (_d = openaiOptions == null ? void 0 : openaiOptions.strictJsonSchema) != null ? _d : true;
@@ -45649,14 +46054,6 @@ var OpenAIResponsesLanguageModel = class {
45649
46054
  });
45650
46055
  delete baseArgs.service_tier;
45651
46056
  }
45652
- const {
45653
- tools: openaiTools2,
45654
- toolChoice: openaiToolChoice,
45655
- toolWarnings
45656
- } = await prepareResponsesTools({
45657
- tools,
45658
- toolChoice
45659
- });
45660
46057
  const shellToolEnvType = (_i = (_h = (_g = tools == null ? void 0 : tools.find(
45661
46058
  (tool2) => tool2.type === "provider" && tool2.id === "openai.shell"
45662
46059
  )) == null ? void 0 : _g.args) == null ? void 0 : _h.environment) == null ? void 0 : _i.type;
@@ -45906,6 +46303,22 @@ var OpenAIResponsesLanguageModel = class {
45906
46303
  });
45907
46304
  break;
45908
46305
  }
46306
+ case "custom_tool_call": {
46307
+ hasFunctionCall = true;
46308
+ const toolName = toolNameMapping.toCustomToolName(part.name);
46309
+ content.push({
46310
+ type: "tool-call",
46311
+ toolCallId: part.call_id,
46312
+ toolName,
46313
+ input: JSON.stringify(part.input),
46314
+ providerMetadata: {
46315
+ [providerOptionsName]: {
46316
+ itemId: part.id
46317
+ }
46318
+ }
46319
+ });
46320
+ break;
46321
+ }
45909
46322
  case "web_search_call": {
45910
46323
  content.push({
45911
46324
  type: "tool-call",
@@ -46164,6 +46577,19 @@ var OpenAIResponsesLanguageModel = class {
46164
46577
  id: value.item.call_id,
46165
46578
  toolName: value.item.name
46166
46579
  });
46580
+ } else if (value.item.type === "custom_tool_call") {
46581
+ const toolName = toolNameMapping.toCustomToolName(
46582
+ value.item.name
46583
+ );
46584
+ ongoingToolCalls[value.output_index] = {
46585
+ toolName,
46586
+ toolCallId: value.item.call_id
46587
+ };
46588
+ controller.enqueue({
46589
+ type: "tool-input-start",
46590
+ id: value.item.call_id,
46591
+ toolName
46592
+ });
46167
46593
  } else if (value.item.type === "web_search_call") {
46168
46594
  ongoingToolCalls[value.output_index] = {
46169
46595
  toolName: toolNameMapping.toCustomToolName(
@@ -46348,6 +46774,27 @@ var OpenAIResponsesLanguageModel = class {
46348
46774
  }
46349
46775
  }
46350
46776
  });
46777
+ } else if (value.item.type === "custom_tool_call") {
46778
+ ongoingToolCalls[value.output_index] = void 0;
46779
+ hasFunctionCall = true;
46780
+ const toolName = toolNameMapping.toCustomToolName(
46781
+ value.item.name
46782
+ );
46783
+ controller.enqueue({
46784
+ type: "tool-input-end",
46785
+ id: value.item.call_id
46786
+ });
46787
+ controller.enqueue({
46788
+ type: "tool-call",
46789
+ toolCallId: value.item.call_id,
46790
+ toolName,
46791
+ input: JSON.stringify(value.item.input),
46792
+ providerMetadata: {
46793
+ [providerOptionsName]: {
46794
+ itemId: value.item.id
46795
+ }
46796
+ }
46797
+ });
46351
46798
  } else if (value.item.type === "web_search_call") {
46352
46799
  ongoingToolCalls[value.output_index] = void 0;
46353
46800
  controller.enqueue({
@@ -46597,6 +47044,15 @@ var OpenAIResponsesLanguageModel = class {
46597
47044
  delta: value.delta
46598
47045
  });
46599
47046
  }
47047
+ } else if (isResponseCustomToolCallInputDeltaChunk(value)) {
47048
+ const toolCall = ongoingToolCalls[value.output_index];
47049
+ if (toolCall != null) {
47050
+ controller.enqueue({
47051
+ type: "tool-input-delta",
47052
+ id: toolCall.toolCallId,
47053
+ delta: value.delta
47054
+ });
47055
+ }
46600
47056
  } else if (isResponseApplyPatchCallOperationDiffDeltaChunk(value)) {
46601
47057
  const toolCall = ongoingToolCalls[value.output_index];
46602
47058
  if (toolCall == null ? void 0 : toolCall.applyPatch) {
@@ -46857,6 +47313,9 @@ function isResponseCreatedChunk(chunk) {
46857
47313
  function isResponseFunctionCallArgumentsDeltaChunk(chunk) {
46858
47314
  return chunk.type === "response.function_call_arguments.delta";
46859
47315
  }
47316
+ function isResponseCustomToolCallInputDeltaChunk(chunk) {
47317
+ return chunk.type === "response.custom_tool_call_input.delta";
47318
+ }
46860
47319
  function isResponseImageGenerationCallPartialImageChunk(chunk) {
46861
47320
  return chunk.type === "response.image_generation_call.partial_image";
46862
47321
  }
@@ -47238,7 +47697,7 @@ var OpenAITranscriptionModel = class {
47238
47697
  };
47239
47698
  }
47240
47699
  };
47241
- var VERSION$2 = "3.0.36";
47700
+ var VERSION$2 = "3.0.41";
47242
47701
  function createOpenAI(options = {}) {
47243
47702
  var _a10, _b9;
47244
47703
  const baseURL = (_a10 = withoutTrailingSlash$1(
@@ -49058,9 +49517,13 @@ function generateReActToolsPrompt(tools) {
49058
49517
  if (toolEntries.length === 0) {
49059
49518
  return "";
49060
49519
  }
49061
- let prompt = "\n\n# 工具调用\n\n";
49062
- prompt += "你可以根据需要调用以下工具:\n\n";
49063
- prompt += "<tools>\n";
49520
+ let prompt = `
49521
+ # 工具调用
49522
+
49523
+ 你可以根据需要调用以下工具:
49524
+
49525
+ <tools>
49526
+ `;
49064
49527
  toolEntries.forEach(([toolName, tool2]) => {
49065
49528
  const toolInfo = tool2;
49066
49529
  const description2 = toolInfo.description || "无描述";
@@ -49073,23 +49536,36 @@ function generateReActToolsPrompt(tools) {
49073
49536
  prompt += `${JSON.stringify(toolJson, null, 2)}
49074
49537
  `;
49075
49538
  });
49076
- prompt += "</tools>\n\n";
49077
- prompt += "## 工具调用格式\n\n";
49078
- prompt += "要调用工具,请使用以下 XML 格式:\n";
49079
- prompt += "Thought: [你的思考过程]\n";
49080
- prompt += '<tool_call>{"name": "toolName", "arguments": {"arg1": "value1"}}</tool_call>\n\n';
49081
- prompt += "工具执行后,你将收到 <tool_response> 格式的结果。你可以继续思考或调用其他工具。\n\n";
49082
- prompt += "## 使用示例\n\n";
49083
- prompt += '如果用户要求"获取今天的日期",你可以这样调用工具:\n';
49084
- prompt += "Thought: 用户想要获取今天的日期,我需要调用日期相关的工具。\n";
49085
- prompt += '<tool_call>{"name": "get-today", "arguments": {}}</tool_call>\n\n';
49086
- prompt += "然后等待工具返回结果(Observation),再根据结果给出最终答案。\n\n";
49087
- prompt += "## 任务完成\n\n";
49088
- prompt += "当任务完成或无法继续时,直接给出最终答案即可。\n\n";
49089
- prompt += "**重要提示**:\n";
49090
- prompt += "- 必须严格按照 XML 格式调用工具\n";
49091
- prompt += "- arguments 必须是有效的 JSON 格式\n";
49092
- prompt += "- 如果不需要调用工具,直接给出最终答案即可\n";
49539
+ prompt += `
49540
+ </tools>
49541
+
49542
+ ## 工具调用格式
49543
+
49544
+ 要调用工具,请使用以下 XML 格式:
49545
+ Thought: [你的思考过程]
49546
+ <tool_call>
49547
+ {"name": "toolName", "arguments": {"arg1": "value1"}}
49548
+ </tool_call>
49549
+
49550
+ 工具执行后,你将收到 <tool_response> 格式的结果。你可以继续思考或调用其他工具。
49551
+
49552
+ ## 使用示例
49553
+
49554
+ 如果用户要求"获取今天的日期",你可以这样调用工具:
49555
+ Thought: 用户想要获取今天的日期,我需要调用日期相关的工具。
49556
+ <tool_call>{"name": "get-today", "arguments": {}}</tool_call>
49557
+
49558
+ 然后等待工具返回结果(Observation),再根据结果给出最终答案。
49559
+
49560
+ ## 任务完成
49561
+
49562
+ 当任务完成或无法继续时,直接给出最终答案即可。
49563
+
49564
+ **重要提示**:
49565
+ - 必须严格按照 XML 格式调用工具
49566
+ - arguments 必须是有效的 JSON 格式
49567
+ - 如果不需要调用工具,直接给出最终答案即可
49568
+ `;
49093
49569
  return prompt;
49094
49570
  }
49095
49571
  function parseReActAction(text2, availableTools) {
@@ -49309,15 +49785,24 @@ class AgentModelProvider {
49309
49785
  }
49310
49786
  this.onUpdatedTools?.();
49311
49787
  }
49312
- /** 创建临时允许调用的tools集合 */
49313
- _tempMergeTools(extraTool = {}) {
49314
- const toolsResult = Object.values(this.mcpTools).reduce((acc, curr) => ({ ...acc, ...curr }), {});
49788
+ /** 创建临时允许调用的 tools 集合,合并 mcpTools 与 extraTool */
49789
+ _tempMergeTools(extraTool = {}, deleteIgnored = true) {
49790
+ const toolsResult = Object.values(this.mcpTools).reduce(
49791
+ (acc, curr) => ({ ...acc, ...curr }),
49792
+ {}
49793
+ );
49315
49794
  Object.assign(toolsResult, extraTool);
49316
- this.ignoreToolnames.forEach((name16) => {
49317
- delete toolsResult[name16];
49318
- });
49795
+ if (deleteIgnored) {
49796
+ this.ignoreToolnames.forEach((name16) => {
49797
+ delete toolsResult[name16];
49798
+ });
49799
+ }
49319
49800
  return toolsResult;
49320
49801
  }
49802
+ /** 获取当前激活的 tools 名称列表(过滤 ignoreToolnames) */
49803
+ _getActiveToolNames(tools) {
49804
+ return Object.keys(tools).filter((name16) => !this.ignoreToolnames.includes(name16));
49805
+ }
49321
49806
  /** 生成 ReAct 模式的系统提示词(包含工具描述) */
49322
49807
  _generateReActSystemPrompt(tools, modelName, baseSystemPrompt) {
49323
49808
  const toolsPrompt = generateReActToolsPrompt(tools);
@@ -49661,12 +50146,14 @@ ${observationText}
49661
50146
  throw new Error("LLM is not initialized");
49662
50147
  }
49663
50148
  await this.initClientsAndTools();
50149
+ const allTools = this._tempMergeTools(options.tools, false);
49664
50150
  const chatOptions = {
49665
50151
  // @ts-ignore ProviderV2 是所有llm的父类, 在每一个具体的llm 类都有一个选择model的函数用法
49666
50152
  model: this.llm(model),
49667
50153
  stopWhen: stepCountIs(maxSteps),
49668
50154
  ...options,
49669
- tools: this._tempMergeTools(options.tools)
50155
+ tools: allTools,
50156
+ activeTools: this._getActiveToolNames(allTools)
49670
50157
  };
49671
50158
  let lastUserMessage = null;
49672
50159
  if (options.message && !options.messages) {
@@ -49696,6 +50183,454 @@ ${observationText}
49696
50183
  return this._chat(streamText, options);
49697
50184
  }
49698
50185
  }
50186
+ let overlayElement = null;
50187
+ let labelElement = null;
50188
+ let styleElement = null;
50189
+ let activeCount = 0;
50190
+ const BODY_GLOW_CLASS = "next-sdk-tool-body-glow";
50191
+ function ensureDomReady() {
50192
+ return typeof window !== "undefined" && typeof document !== "undefined";
50193
+ }
50194
+ function ensureStyleElement() {
50195
+ if (!ensureDomReady()) return;
50196
+ if (styleElement) return;
50197
+ const style = document.createElement("style");
50198
+ style.textContent = `
50199
+ .${BODY_GLOW_CLASS} {
50200
+ position: relative;
50201
+ }
50202
+
50203
+ .next-sdk-tool-overlay {
50204
+ position: fixed;
50205
+ inset: 0;
50206
+ z-index: 999999;
50207
+ pointer-events: none;
50208
+ display: flex;
50209
+ align-items: flex-end;
50210
+ justify-content: flex-start;
50211
+ padding: 0 0 18px 18px;
50212
+ background: transparent;
50213
+ animation: next-sdk-overlay-fade-in 260ms ease-out;
50214
+ }
50215
+
50216
+ .next-sdk-tool-overlay--exit {
50217
+ animation: next-sdk-overlay-fade-out 220ms ease-in forwards;
50218
+ }
50219
+
50220
+ .next-sdk-tool-overlay__glow-ring {
50221
+ display: none;
50222
+ }
50223
+
50224
+ .next-sdk-tool-overlay__panel {
50225
+ position: relative;
50226
+ min-width: min(320px, 78vw);
50227
+ max-width: min(420px, 82vw);
50228
+ padding: 10px 14px;
50229
+ border-radius: 999px;
50230
+ background:
50231
+ linear-gradient(135deg, rgba(15, 23, 42, 0.9), rgba(17, 24, 39, 0.9)),
50232
+ radial-gradient(circle at top left, rgba(96, 165, 250, 0.25), transparent 55%),
50233
+ radial-gradient(circle at bottom right, rgba(45, 212, 191, 0.22), transparent 60%);
50234
+ box-shadow:
50235
+ 0 12px 28px rgba(15, 23, 42, 0.78),
50236
+ 0 0 0 1px rgba(148, 163, 184, 0.26);
50237
+ display: flex;
50238
+ align-items: center;
50239
+ gap: 10px;
50240
+ pointer-events: none;
50241
+ transform-origin: center;
50242
+ animation: next-sdk-panel-pop-in 260ms cubic-bezier(0.18, 0.89, 0.32, 1.28);
50243
+ color: #e5e7eb;
50244
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif;
50245
+ }
50246
+
50247
+ .next-sdk-tool-overlay__indicator {
50248
+ width: 26px;
50249
+ height: 26px;
50250
+ border-radius: 999px;
50251
+ background: radial-gradient(circle at 30% 10%, #f9fafb, #93c5fd);
50252
+ box-shadow:
50253
+ 0 0 0 1px rgba(191, 219, 254, 0.6),
50254
+ 0 8px 18px rgba(37, 99, 235, 0.8),
50255
+ 0 0 28px rgba(56, 189, 248, 0.9);
50256
+ position: relative;
50257
+ flex-shrink: 0;
50258
+ display: flex;
50259
+ align-items: center;
50260
+ justify-content: center;
50261
+ overflow: hidden;
50262
+ }
50263
+
50264
+ .next-sdk-tool-overlay__indicator-orbit {
50265
+ position: absolute;
50266
+ inset: 2px;
50267
+ border-radius: inherit;
50268
+ border: 1px solid rgba(248, 250, 252, 0.6);
50269
+ box-sizing: border-box;
50270
+ opacity: 0.9;
50271
+ }
50272
+
50273
+ .next-sdk-tool-overlay__indicator-orbit::before {
50274
+ content: '';
50275
+ position: absolute;
50276
+ width: 6px;
50277
+ height: 6px;
50278
+ border-radius: 999px;
50279
+ background: #f9fafb;
50280
+ box-shadow:
50281
+ 0 0 12px rgba(248, 250, 252, 0.9),
50282
+ 0 0 24px rgba(250, 249, 246, 0.9);
50283
+ top: 0;
50284
+ left: 50%;
50285
+ transform: translate(-50%, -50%);
50286
+ transform-origin: 50% 18px;
50287
+ animation: next-sdk-indicator-orbit 1.4s linear infinite;
50288
+ }
50289
+
50290
+ .next-sdk-tool-overlay__indicator-core {
50291
+ width: 14px;
50292
+ height: 14px;
50293
+ border-radius: inherit;
50294
+ background: radial-gradient(circle at 30% 20%, #f9fafb, #bfdbfe);
50295
+ box-shadow:
50296
+ 0 0 12px rgba(248, 250, 252, 0.9),
50297
+ 0 0 32px rgba(191, 219, 254, 0.8);
50298
+ opacity: 0.96;
50299
+ }
50300
+
50301
+ .next-sdk-tool-overlay__content {
50302
+ display: flex;
50303
+ flex-direction: column;
50304
+ gap: 1px;
50305
+ min-width: 0;
50306
+ }
50307
+
50308
+ .next-sdk-tool-overlay__title {
50309
+ font-size: 11px;
50310
+ letter-spacing: 0.08em;
50311
+ text-transform: uppercase;
50312
+ color: rgba(156, 163, 175, 0.96);
50313
+ display: flex;
50314
+ align-items: center;
50315
+ gap: 6px;
50316
+ }
50317
+
50318
+ .next-sdk-tool-overlay__title-dot {
50319
+ width: 6px;
50320
+ height: 6px;
50321
+ border-radius: 999px;
50322
+ background: #22c55e;
50323
+ box-shadow:
50324
+ 0 0 8px rgba(34, 197, 94, 0.9),
50325
+ 0 0 14px rgba(22, 163, 74, 0.9);
50326
+ }
50327
+
50328
+ .next-sdk-tool-overlay__label {
50329
+ font-size: 12px;
50330
+ font-weight: 500;
50331
+ color: #e5e7eb;
50332
+ white-space: nowrap;
50333
+ text-overflow: ellipsis;
50334
+ overflow: hidden;
50335
+ }
50336
+
50337
+ @keyframes next-sdk-overlay-fade-in {
50338
+ from { opacity: 0; }
50339
+ to { opacity: 1; }
50340
+ }
50341
+
50342
+ @keyframes next-sdk-overlay-fade-out {
50343
+ from { opacity: 1; }
50344
+ to { opacity: 0; }
50345
+ }
50346
+
50347
+ @keyframes next-sdk-indicator-orbit {
50348
+ from {
50349
+ transform: translate(-50%, -50%) rotate(0deg) translateY(0);
50350
+ }
50351
+ to {
50352
+ transform: translate(-50%, -50%) rotate(360deg) translateY(0);
50353
+ }
50354
+ }
50355
+
50356
+ @keyframes next-sdk-panel-pop-in {
50357
+ 0% {
50358
+ opacity: 0;
50359
+ transform: scale(0.92) translateY(10px);
50360
+ }
50361
+ 100% {
50362
+ opacity: 1;
50363
+ transform: scale(1) translateY(0);
50364
+ }
50365
+ }
50366
+ `;
50367
+ document.head.appendChild(style);
50368
+ styleElement = style;
50369
+ }
50370
+ function ensureOverlayElement() {
50371
+ if (!ensureDomReady()) return;
50372
+ if (overlayElement) return;
50373
+ ensureStyleElement();
50374
+ const overlay = document.createElement("div");
50375
+ overlay.className = "next-sdk-tool-overlay";
50376
+ const glowRing = document.createElement("div");
50377
+ glowRing.className = "next-sdk-tool-overlay__glow-ring";
50378
+ const panel = document.createElement("div");
50379
+ panel.className = "next-sdk-tool-overlay__panel";
50380
+ const indicator = document.createElement("div");
50381
+ indicator.className = "next-sdk-tool-overlay__indicator";
50382
+ const indicatorOrbit = document.createElement("div");
50383
+ indicatorOrbit.className = "next-sdk-tool-overlay__indicator-orbit";
50384
+ const indicatorCore = document.createElement("div");
50385
+ indicatorCore.className = "next-sdk-tool-overlay__indicator-core";
50386
+ const content = document.createElement("div");
50387
+ content.className = "next-sdk-tool-overlay__content";
50388
+ const titleRow = document.createElement("div");
50389
+ titleRow.className = "next-sdk-tool-overlay__title";
50390
+ titleRow.textContent = "AI 正在调用页面工具";
50391
+ const titleDot = document.createElement("span");
50392
+ titleDot.className = "next-sdk-tool-overlay__title-dot";
50393
+ const label = document.createElement("div");
50394
+ label.className = "next-sdk-tool-overlay__label";
50395
+ titleRow.prepend(titleDot);
50396
+ content.appendChild(titleRow);
50397
+ content.appendChild(label);
50398
+ indicator.appendChild(indicatorOrbit);
50399
+ indicator.appendChild(indicatorCore);
50400
+ panel.appendChild(indicator);
50401
+ panel.appendChild(content);
50402
+ overlay.appendChild(glowRing);
50403
+ overlay.appendChild(panel);
50404
+ document.body.appendChild(overlay);
50405
+ overlayElement = overlay;
50406
+ labelElement = label;
50407
+ }
50408
+ function updateOverlay(config2) {
50409
+ if (!ensureDomReady()) return;
50410
+ ensureOverlayElement();
50411
+ if (!overlayElement || !labelElement) return;
50412
+ overlayElement.classList.remove("next-sdk-tool-overlay--exit");
50413
+ labelElement.textContent = config2.label;
50414
+ }
50415
+ function removeOverlayWithAnimation() {
50416
+ if (!overlayElement) return;
50417
+ overlayElement.classList.add("next-sdk-tool-overlay--exit");
50418
+ const localOverlay = overlayElement;
50419
+ let handled = false;
50420
+ let timerId;
50421
+ const handle = () => {
50422
+ if (handled) return;
50423
+ handled = true;
50424
+ if (timerId !== void 0) {
50425
+ clearTimeout(timerId);
50426
+ timerId = void 0;
50427
+ }
50428
+ if (localOverlay.parentNode) {
50429
+ localOverlay.parentNode.removeChild(localOverlay);
50430
+ }
50431
+ if (overlayElement === localOverlay) {
50432
+ overlayElement = null;
50433
+ labelElement = null;
50434
+ }
50435
+ localOverlay.removeEventListener("animationend", handle);
50436
+ };
50437
+ localOverlay.addEventListener("animationend", handle);
50438
+ timerId = setTimeout(handle, 500);
50439
+ }
50440
+ function showToolInvokeEffect(config2) {
50441
+ if (!ensureDomReady()) return;
50442
+ activeCount += 1;
50443
+ updateOverlay(config2);
50444
+ }
50445
+ function hideToolInvokeEffect() {
50446
+ if (!ensureDomReady() || activeCount <= 0) return;
50447
+ activeCount -= 1;
50448
+ if (activeCount === 0) {
50449
+ removeOverlayWithAnimation();
50450
+ }
50451
+ }
50452
+ function resolveRuntimeEffectConfig(toolName, toolTitle, value) {
50453
+ if (!value) return void 0;
50454
+ const baseLabel = toolTitle || toolName;
50455
+ if (typeof value === "boolean") {
50456
+ return value ? { label: baseLabel } : void 0;
50457
+ }
50458
+ return {
50459
+ label: value.label || baseLabel
50460
+ };
50461
+ }
50462
+ const MSG_TOOL_CALL = "next-sdk:tool-call";
50463
+ const MSG_TOOL_RESPONSE = "next-sdk:tool-response";
50464
+ const MSG_PAGE_READY = "next-sdk:page-ready";
50465
+ const MSG_PAGE_LEAVE = "next-sdk:page-leave";
50466
+ const MSG_REMOTER_READY = "next-sdk:remoter-ready";
50467
+ const MSG_ROUTE_STATE_INITIAL = "next-sdk:route-state-initial";
50468
+ const activePages = /* @__PURE__ */ new Map();
50469
+ const broadcastTargets = /* @__PURE__ */ new Set();
50470
+ function initBroadcastTargets() {
50471
+ if (typeof window !== "undefined") {
50472
+ broadcastTargets.add({ win: window, origin: window.location.origin || "*" });
50473
+ }
50474
+ }
50475
+ initBroadcastTargets();
50476
+ function broadcastRouteChange(type2, route) {
50477
+ const msg = { type: type2, route };
50478
+ broadcastTargets.forEach(({ win, origin }) => {
50479
+ try {
50480
+ win.postMessage(msg, origin);
50481
+ } catch {
50482
+ }
50483
+ });
50484
+ }
50485
+ function setupIframeRemoterBridge() {
50486
+ if (typeof window === "undefined") return;
50487
+ window.addEventListener("message", (event) => {
50488
+ if (event.data?.type !== MSG_REMOTER_READY || !event.source) return;
50489
+ if (event.origin !== window.location.origin) return;
50490
+ const target = event.source;
50491
+ broadcastTargets.add({ win: target, origin: event.origin || "*" });
50492
+ const payload = {
50493
+ type: MSG_ROUTE_STATE_INITIAL,
50494
+ toolRouteMap: Array.from(toolRouteMap.entries()),
50495
+ activeRoutes: Array.from(activePages.keys())
50496
+ };
50497
+ try {
50498
+ target.postMessage(payload, event.origin || "*");
50499
+ } catch {
50500
+ }
50501
+ });
50502
+ }
50503
+ setupIframeRemoterBridge();
50504
+ const toolRouteMap = /* @__PURE__ */ new Map();
50505
+ function getToolRouteMap() {
50506
+ return new Map(toolRouteMap);
50507
+ }
50508
+ function getActiveRoutes() {
50509
+ return new Set(activePages.keys());
50510
+ }
50511
+ let _navigator = null;
50512
+ function setNavigator(fn) {
50513
+ _navigator = fn;
50514
+ }
50515
+ function buildPageHandler(name16, route, timeout = 3e4, effectConfig) {
50516
+ return (input) => {
50517
+ const callId = randomUUID();
50518
+ return new Promise((resolve2, reject) => {
50519
+ let timer;
50520
+ let readyHandler;
50521
+ const cleanup = () => {
50522
+ clearTimeout(timer);
50523
+ window.removeEventListener("message", responseHandler);
50524
+ if (readyHandler) {
50525
+ window.removeEventListener("message", readyHandler);
50526
+ }
50527
+ if (effectConfig) {
50528
+ hideToolInvokeEffect();
50529
+ }
50530
+ };
50531
+ timer = setTimeout(() => {
50532
+ cleanup();
50533
+ reject(new Error(`工具 [${name16}] 调用超时 (${timeout}ms),请检查目标页面是否正确调用了 registerPageTool`));
50534
+ }, timeout);
50535
+ const responseHandler = (event) => {
50536
+ if (event.source === window && event.data?.type === MSG_TOOL_RESPONSE && event.data.callId === callId) {
50537
+ cleanup();
50538
+ event.data.error ? reject(new Error(event.data.error)) : resolve2(event.data.result);
50539
+ }
50540
+ };
50541
+ window.addEventListener("message", responseHandler);
50542
+ const sendCall = () => {
50543
+ window.postMessage({ type: MSG_TOOL_CALL, callId, toolName: name16, route, input }, window.location.origin || "*");
50544
+ };
50545
+ let callSent = false;
50546
+ const sendCallOnce = () => {
50547
+ if (callSent) return;
50548
+ callSent = true;
50549
+ sendCall();
50550
+ };
50551
+ const run = async () => {
50552
+ try {
50553
+ if (effectConfig) {
50554
+ showToolInvokeEffect(effectConfig);
50555
+ }
50556
+ if (activePages.get(route)) {
50557
+ sendCallOnce();
50558
+ return;
50559
+ }
50560
+ readyHandler = (event) => {
50561
+ if (event.source === window && event.data?.type === MSG_PAGE_READY && event.data.route === route) {
50562
+ window.removeEventListener("message", readyHandler);
50563
+ sendCallOnce();
50564
+ }
50565
+ };
50566
+ window.addEventListener("message", readyHandler);
50567
+ if (_navigator) {
50568
+ await _navigator(route);
50569
+ }
50570
+ if (activePages.get(route)) {
50571
+ window.removeEventListener("message", readyHandler);
50572
+ sendCallOnce();
50573
+ }
50574
+ } catch (err) {
50575
+ cleanup();
50576
+ reject(err instanceof Error ? err : new Error(String(err)));
50577
+ }
50578
+ };
50579
+ void run();
50580
+ });
50581
+ };
50582
+ }
50583
+ function withPageTools(server) {
50584
+ return new Proxy(server, {
50585
+ get(target, prop, receiver) {
50586
+ if (prop === "registerTool") {
50587
+ return (name16, config2, handlerOrRoute) => {
50588
+ const rawRegister = target.registerTool.bind(target);
50589
+ if (typeof handlerOrRoute === "function") {
50590
+ return rawRegister(name16, config2, handlerOrRoute);
50591
+ }
50592
+ const { route, timeout, invokeEffect } = handlerOrRoute;
50593
+ toolRouteMap.set(name16, route);
50594
+ const effectConfig = resolveRuntimeEffectConfig(name16, config2?.title, invokeEffect);
50595
+ return rawRegister(name16, config2, buildPageHandler(name16, route, timeout, effectConfig));
50596
+ };
50597
+ }
50598
+ return Reflect.get(target, prop, receiver);
50599
+ }
50600
+ });
50601
+ }
50602
+ function registerPageTool(options) {
50603
+ const { route: routeOption, handlers } = options;
50604
+ const normalizeRoute = (value) => value.replace(/\/+$/, "") || "/";
50605
+ const route = normalizeRoute(routeOption ?? window.location.pathname);
50606
+ const handleMessage = async (event) => {
50607
+ if (event.source !== window || event.data?.type !== MSG_TOOL_CALL || normalizeRoute(String(event.data?.route ?? "")) !== route || !(event.data.toolName in handlers)) {
50608
+ return;
50609
+ }
50610
+ const { callId, toolName, input } = event.data;
50611
+ try {
50612
+ const result = await handlers[toolName](input);
50613
+ window.postMessage({ type: MSG_TOOL_RESPONSE, callId, result }, window.location.origin || "*");
50614
+ } catch (err) {
50615
+ window.postMessage(
50616
+ {
50617
+ type: MSG_TOOL_RESPONSE,
50618
+ callId,
50619
+ error: err instanceof Error ? err.message : String(err)
50620
+ },
50621
+ window.location.origin || "*"
50622
+ );
50623
+ }
50624
+ };
50625
+ activePages.set(route, true);
50626
+ window.addEventListener("message", handleMessage);
50627
+ broadcastRouteChange(MSG_PAGE_READY, route);
50628
+ return () => {
50629
+ activePages.delete(route);
50630
+ window.removeEventListener("message", handleMessage);
50631
+ broadcastRouteChange(MSG_PAGE_LEAVE, route);
50632
+ };
50633
+ }
49699
50634
  const MAIN_SKILL_PATH_REG = /^\.\/[^/]+\/SKILL\.md$/;
49700
50635
  const FRONT_MATTER_BLOCK_REG = /^---\s*\n([\s\S]+?)\s*\n---/;
49701
50636
  function parseSkillFrontMatter(content) {
@@ -49708,14 +50643,27 @@ function parseSkillFrontMatter(content) {
49708
50643
  const description2 = descMatch?.[1]?.trim();
49709
50644
  return name16 && description2 ? { name: name16, description: description2 } : null;
49710
50645
  }
50646
+ function normalizeSkillModuleKeys(modules) {
50647
+ const result = {};
50648
+ for (const [key, content] of Object.entries(modules)) {
50649
+ const normalizedKey = key.replace(/\\/g, "/");
50650
+ const skillsIndex = normalizedKey.lastIndexOf("skills/");
50651
+ const relativePath = skillsIndex >= 0 ? normalizedKey.slice(skillsIndex + 7) : normalizedKey;
50652
+ const standardPath = relativePath.startsWith("./") ? relativePath : `./${relativePath}`;
50653
+ result[standardPath] = content;
50654
+ }
50655
+ return result;
50656
+ }
49711
50657
  function getMainSkillPaths(modules) {
49712
- return Object.keys(modules).filter((path) => MAIN_SKILL_PATH_REG.test(path));
50658
+ const normalized = normalizeSkillModuleKeys(modules);
50659
+ return Object.keys(normalized).filter((path) => MAIN_SKILL_PATH_REG.test(path));
49713
50660
  }
49714
50661
  function getSkillOverviews(modules) {
49715
- const mainPaths = getMainSkillPaths(modules);
50662
+ const normalized = normalizeSkillModuleKeys(modules);
50663
+ const mainPaths = Object.keys(normalized).filter((path) => MAIN_SKILL_PATH_REG.test(path));
49716
50664
  const list = [];
49717
50665
  for (const path of mainPaths) {
49718
- const content = modules[path];
50666
+ const content = normalized[path];
49719
50667
  if (!content) continue;
49720
50668
  const parsed = parseSkillFrontMatter(content);
49721
50669
  if (!parsed) continue;
@@ -49737,34 +50685,100 @@ ${lines.join("\n")}
49737
50685
  当需要用到某技能时,请使用 get_skill_content 工具获取该技能的完整文档内容。`;
49738
50686
  }
49739
50687
  function getSkillMdPaths(modules) {
49740
- return Object.keys(modules);
50688
+ const normalized = normalizeSkillModuleKeys(modules);
50689
+ return Object.keys(normalized);
49741
50690
  }
49742
50691
  function getSkillMdContent(modules, path) {
49743
- return modules[path];
50692
+ const normalized = normalizeSkillModuleKeys(modules);
50693
+ const exactMatch = normalized[path];
50694
+ if (exactMatch) return exactMatch;
50695
+ const suffix = path.replace(/^\.?\//, "/");
50696
+ const matchingKey = Object.keys(normalized).find((key) => key.endsWith(suffix));
50697
+ return matchingKey ? normalized[matchingKey] : void 0;
49744
50698
  }
49745
50699
  function getMainSkillPathByName(modules, name16) {
49746
- return getMainSkillPaths(modules).find((p) => p.startsWith(`./${name16}/SKILL.md`));
50700
+ const normalizedModules = normalizeSkillModuleKeys(modules);
50701
+ const paths = getMainSkillPaths(normalizedModules);
50702
+ const dirMatch = paths.find((p) => p.startsWith(`./${name16}/SKILL.md`));
50703
+ if (dirMatch) return dirMatch;
50704
+ for (const p of paths) {
50705
+ const content = normalizedModules[p];
50706
+ if (content) {
50707
+ const parsed = parseSkillFrontMatter(content);
50708
+ if (parsed && parsed.name === name16) {
50709
+ return p;
50710
+ }
50711
+ }
50712
+ }
50713
+ return void 0;
49747
50714
  }
50715
+ const SKILL_INPUT_SCHEMA = objectType({
50716
+ skillName: stringType().optional().describe(
50717
+ '进入某个技能的主入口名称。优先匹配技能的目录名(如 ecommerce),或者技能的中文名称(如"客户价保单创建及审核")。'
50718
+ ),
50719
+ path: stringType().optional().describe("你想查阅的文档的路径。如 ./calculator/SKILL.md 或从其他文档里看到的相对路径 ./reference/inventory.md。"),
50720
+ currentPath: stringType().optional().describe(
50721
+ "你当前正在阅读的文档路径(如果有)。比如你刚刚读取了 ./ecommerce/SKILL.md,请把这个路径原样传回来,这样系统才能根据你的相对路径准确找到下一份文件。"
50722
+ )
50723
+ });
49748
50724
  function createSkillTools(modules) {
50725
+ const normalizedModules = normalizeSkillModuleKeys(modules);
49749
50726
  const getSkillContent = tool({
49750
- description: "根据技能名称或文档路径获取该技能的完整文档内容。传入 skillName(如 calculator)或 path(如 ./calculator/SKILL.md)。支持 .md、.json、.xml 等各类文本格式文件。",
49751
- inputSchema: objectType({
49752
- skillName: stringType().optional().describe("技能名称,与目录名一致,如 calculator"),
49753
- path: stringType().optional().describe("文档相对路径,如 ./calculator/SKILL.md 或 ./product-guide/reference/xxx.json")
49754
- }),
50727
+ description: "根据技能名称或文档路径获取该技能的完整文档内容。如果你想根据相对路径查阅文件,请务必同时提供你当前所在的文件路径 currentPath。",
50728
+ inputSchema: SKILL_INPUT_SCHEMA,
49755
50729
  execute: (args) => {
49756
- const { skillName, path: pathArg } = args;
50730
+ const { skillName, path: pathArg, currentPath: currentPathArg } = args;
49757
50731
  let content;
50732
+ let resolvedPath = "";
49758
50733
  if (pathArg) {
49759
- content = getSkillMdContent(modules, pathArg);
50734
+ let basePathContext = ".";
50735
+ if (currentPathArg) {
50736
+ const lastSlashIndex = currentPathArg.lastIndexOf("/");
50737
+ if (lastSlashIndex >= 0) {
50738
+ basePathContext = currentPathArg.slice(0, lastSlashIndex);
50739
+ }
50740
+ }
50741
+ const dummyBase = `http://localhost/${basePathContext}/`;
50742
+ const url2 = new URL(pathArg, dummyBase);
50743
+ resolvedPath = "." + url2.pathname;
50744
+ content = getSkillMdContent(normalizedModules, resolvedPath);
50745
+ if (content === void 0 && (pathArg.startsWith("./") || pathArg.startsWith("../")) && currentPathArg) {
50746
+ const baseParts = currentPathArg.split("/");
50747
+ if (baseParts.length >= 2) {
50748
+ const skillRoot = baseParts[1];
50749
+ const fallbackDummyBase = `http://localhost/${skillRoot}/`;
50750
+ const fallbackUrl = new URL(pathArg, fallbackDummyBase);
50751
+ const fallbackPath = "." + fallbackUrl.pathname;
50752
+ content = getSkillMdContent(normalizedModules, fallbackPath);
50753
+ if (content) {
50754
+ resolvedPath = fallbackPath;
50755
+ }
50756
+ }
50757
+ }
50758
+ if (content && !normalizedModules[resolvedPath]) {
50759
+ const suffix = resolvedPath.replace(/^\.?\//, "/");
50760
+ const matchingKey = Object.keys(normalizedModules).find((key) => key.endsWith(suffix));
50761
+ if (matchingKey) {
50762
+ resolvedPath = matchingKey;
50763
+ }
50764
+ }
49760
50765
  } else if (skillName) {
49761
- const mainPath = getMainSkillPathByName(modules, skillName);
49762
- content = mainPath ? getSkillMdContent(modules, mainPath) : void 0;
50766
+ const mainPath = getMainSkillPathByName(normalizedModules, skillName);
50767
+ if (mainPath) {
50768
+ resolvedPath = mainPath;
50769
+ content = getSkillMdContent(normalizedModules, mainPath);
50770
+ }
49763
50771
  }
49764
50772
  if (content === void 0) {
49765
- return { error: "未找到对应技能文档", skillName: skillName ?? pathArg };
50773
+ return {
50774
+ error: "未找到对应技能文档",
50775
+ skillName,
50776
+ path: pathArg,
50777
+ providedCurrentPath: currentPathArg,
50778
+ attemptedPath: resolvedPath
50779
+ };
49766
50780
  }
49767
- return { content, path: pathArg ?? getMainSkillPathByName(modules, skillName) };
50781
+ return { content, path: resolvedPath };
49768
50782
  }
49769
50783
  });
49770
50784
  return {
@@ -49779,6 +50793,9 @@ export {
49779
50793
  ExtensionClientTransport,
49780
50794
  ExtensionPageServerTransport,
49781
50795
  InMemoryTransport,
50796
+ MSG_PAGE_LEAVE,
50797
+ MSG_REMOTER_READY,
50798
+ MSG_ROUTE_STATE_INITIAL,
49782
50799
  QrCode,
49783
50800
  ResourceTemplate,
49784
50801
  UriTemplate,
@@ -49794,12 +50811,14 @@ export {
49794
50811
  createStreamableHTTPClientTransport,
49795
50812
  formatSkillsForSystemPrompt,
49796
50813
  getAISDKTools,
50814
+ getActiveRoutes,
49797
50815
  getDisplayName,
49798
50816
  getMainSkillPathByName,
49799
50817
  getMainSkillPaths,
49800
50818
  getSkillMdContent,
49801
50819
  getSkillMdPaths,
49802
50820
  getSkillOverviews,
50821
+ getToolRouteMap,
49803
50822
  isMcpClient,
49804
50823
  isMcpServer,
49805
50824
  isMessageChannelClientTransport,
@@ -49807,5 +50826,8 @@ export {
49807
50826
  isSSEClientTransport,
49808
50827
  isStreamableHTTPClientTransport,
49809
50828
  parseSkillFrontMatter,
50829
+ registerPageTool,
50830
+ setNavigator,
50831
+ withPageTools,
49810
50832
  z
49811
50833
  };