@lark-apaas/aily-web-sdk 0.0.11 → 0.0.12-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,6 +45,33 @@ const sdk = await initAgentChat(container, {
45
45
  });
46
46
  ```
47
47
 
48
+ ```typescript
49
+ import { initAgentChat } from '@lark-apaas/aily-web-sdk'
50
+
51
+ const container = document.querySelector('.container');
52
+
53
+ const sdk = await initAgentChat(container, {
54
+ channelToken: 'wsk_xxx',
55
+ customParams: {
56
+ employee_id: {
57
+ value: '12345',
58
+ desc: '员工工号,可作为查询型技能的 user_id 入参'
59
+ }
60
+ }
61
+ });
62
+ ```
63
+
64
+ ```typescript
65
+ import { initAgentChat } from '@lark-apaas/aily-web-sdk'
66
+
67
+ const container = document.querySelector('.container');
68
+
69
+ const sdk = await initAgentChat(container, {
70
+ channelToken: 'wsk_xxx',
71
+ customParamsToken: 'jwt-token'
72
+ });
73
+ ```
74
+
48
75
  ## API
49
76
 
50
77
  ### `initAilyChat(root, config)`
@@ -87,6 +114,14 @@ const sdk = await initAgentChat(container, {
87
114
  - `root` (`HTMLElement`) - iframe 挂载的容器元素
88
115
  - `config` (`AgentSDKInitConfig`) - 配置项
89
116
  - `channelToken` (`string`) - agent 渠道 token
117
+ - `customParams` (`CustomParams`, 可选) - 宿主初始化时注入的明文上下文
118
+ - `customParamsToken` (`string`, 可选) - 宿主初始化时注入的 token 上下文
119
+
120
+ > `customParams` 与 `customParamsToken` 互斥,只能二选一。
121
+ >
122
+ > Agent custom context 不会进入 iframe URL。宿主会在 iframe 每次 `ready` 后,通过扩展版 `initParentContext` 的 `postMessage` payload 下发这些字段。
123
+ >
124
+ > 使用该能力时,iframe 内部页面需要支持 `ready` 的扩展 payload,以及扩展版 `initParentContext` request/response ack 协议。
90
125
 
91
126
  **返回:** `Promise<AgentSDKInstance>`
92
127
 
package/dist/index.cjs CHANGED
@@ -42,7 +42,7 @@ var IFRAME_ORIGIN = {
42
42
  production: "https://aily.feishu.cn",
43
43
  staging: "https://aily.feishu-pre.cn",
44
44
  boe: "https://aily.feishu-boe.cn",
45
- development: "http://localhost:8080"
45
+ development: "http://localhost:3000"
46
46
  };
47
47
  var CHAT_IFRAME_PATH = "/cui";
48
48
  var AGENT_IFRAME_PATH = "/custom_agent/cui";
@@ -487,8 +487,19 @@ var _AgentIframeManager = class _AgentIframeManager {
487
487
  __publicField(this, "messageBridge");
488
488
  __publicField(this, "config");
489
489
  __publicField(this, "root");
490
+ __publicField(this, "runtimeCustomContext");
491
+ __publicField(this, "contextVersion");
492
+ __publicField(this, "initialHandshakeCompleted", false);
493
+ __publicField(this, "handleSubsequentReady", /* @__PURE__ */ __name((data) => {
494
+ if (!this.initialHandshakeCompleted) {
495
+ return;
496
+ }
497
+ void this.sendParentContext(this.parseReadyEventData(data)).catch(() => void 0);
498
+ }, "handleSubsequentReady"));
490
499
  this.root = root;
491
500
  this.config = config;
501
+ this.runtimeCustomContext = this.resolveRuntimeCustomContext(config);
502
+ this.contextVersion = this.createContextVersion();
492
503
  this.messageBridge = new MessageBridge(getAgentIframeBaseURL());
493
504
  }
494
505
  async init() {
@@ -498,22 +509,29 @@ var _AgentIframeManager = class _AgentIframeManager {
498
509
  this.iframe.style.height = "100%";
499
510
  this.iframe.style.border = "none";
500
511
  this.iframe.allow = "microphone; clipboard-write";
501
- this.root.appendChild(this.iframe);
512
+ const readyPromise = this.waitForReady();
513
+ this.messageBridge.onEvent("ready", this.handleSubsequentReady);
502
514
  this.messageBridge.attach(this.iframe);
503
- await this.waitForReady();
504
- await this.messageBridge.send("initParentContext", this.buildParentContext());
515
+ this.root.appendChild(this.iframe);
516
+ try {
517
+ const readyData = await readyPromise;
518
+ await this.sendParentContext(readyData);
519
+ this.initialHandshakeCompleted = true;
520
+ } catch (error) {
521
+ this.cleanupAfterFailedInit();
522
+ throw error;
523
+ }
505
524
  return this.createAgentInstance();
506
525
  }
507
526
  async destroy() {
527
+ this.messageBridge.offEvent("ready", this.handleSubsequentReady);
508
528
  try {
509
529
  await this.messageBridge.send("destroy");
510
530
  } catch {
511
531
  }
512
532
  this.messageBridge.detach();
513
- if (this.iframe?.parentNode) {
514
- this.iframe.parentNode.removeChild(this.iframe);
515
- }
516
- this.iframe = null;
533
+ this.removeIframe();
534
+ this.initialHandshakeCompleted = false;
517
535
  }
518
536
  buildIframeURL() {
519
537
  const baseURL = getAgentIframeBaseURL();
@@ -524,26 +542,126 @@ var _AgentIframeManager = class _AgentIframeManager {
524
542
  return `${baseURL}?${params.toString()}`;
525
543
  }
526
544
  buildParentContext() {
527
- return {
545
+ const parentContext = {
528
546
  parentOrigin: window.location.origin
529
547
  };
548
+ return parentContext;
530
549
  }
531
550
  waitForReady() {
532
551
  return new Promise((resolve, reject) => {
552
+ const handleReady = /* @__PURE__ */ __name((data) => {
553
+ clearTimeout(timeout);
554
+ this.messageBridge.offEvent("ready", handleReady);
555
+ resolve(this.parseReadyEventData(data));
556
+ }, "handleReady");
533
557
  const timeout = setTimeout(() => {
534
- window.removeEventListener("message", checkMessage);
558
+ this.messageBridge.offEvent("ready", handleReady);
535
559
  reject(new Error("Iframe ready timeout"));
536
560
  }, 3e4);
537
- const checkMessage = /* @__PURE__ */ __name((event) => {
538
- if (event.data?.messageBizId === MESSAGE_BIZ_ID && event.data?.type === "event" && event.data?.eventName === "ready") {
539
- clearTimeout(timeout);
540
- window.removeEventListener("message", checkMessage);
541
- resolve();
542
- }
543
- }, "checkMessage");
544
- window.addEventListener("message", checkMessage);
561
+ this.messageBridge.onEvent("ready", handleReady);
545
562
  });
546
563
  }
564
+ async sendParentContext(readyData) {
565
+ const payload = this.buildParentContextForReady(readyData);
566
+ const response = await this.messageBridge.send("initParentContext", payload);
567
+ if (!this.runtimeCustomContext) {
568
+ return;
569
+ }
570
+ if (response?.accepted !== true) {
571
+ throw new Error("Iframe rejected initParentContext custom context");
572
+ }
573
+ if (payload.iframeSessionId && response.iframeSessionId && response.iframeSessionId !== payload.iframeSessionId) {
574
+ throw new Error("Iframe returned mismatched iframeSessionId");
575
+ }
576
+ if (payload.contextVersion && response.contextVersion && response.contextVersion !== payload.contextVersion) {
577
+ throw new Error("Iframe returned mismatched contextVersion");
578
+ }
579
+ }
580
+ buildParentContextForReady(readyData) {
581
+ const parentContext = this.buildParentContext();
582
+ if (!this.runtimeCustomContext) {
583
+ return parentContext;
584
+ }
585
+ this.assertReadySupportsRuntimeContext(readyData);
586
+ return {
587
+ ...parentContext,
588
+ protocolVersion: 2,
589
+ iframeSessionId: readyData.iframeSessionId,
590
+ contextVersion: this.contextVersion,
591
+ runtimeCustomContext: this.runtimeCustomContext
592
+ };
593
+ }
594
+ assertReadySupportsRuntimeContext(readyData) {
595
+ if (readyData?.protocolVersion !== 2 || !readyData.iframeSessionId || readyData.needsContext !== true) {
596
+ throw new Error("Current iframe version does not support custom context initParentContext protocol");
597
+ }
598
+ }
599
+ parseReadyEventData(data) {
600
+ if (!this.isRecord(data)) {
601
+ return void 0;
602
+ }
603
+ return data;
604
+ }
605
+ resolveRuntimeCustomContext(config) {
606
+ if (config.customParams !== void 0 && config.customParamsToken !== void 0) {
607
+ throw new Error("customParams and customParamsToken cannot be used together");
608
+ }
609
+ if (config.customParamsToken !== void 0) {
610
+ const token = config.customParamsToken.trim();
611
+ if (!token) {
612
+ throw new Error("customParamsToken cannot be empty");
613
+ }
614
+ return {
615
+ customParamsToken: token
616
+ };
617
+ }
618
+ if (config.customParams === void 0) {
619
+ return null;
620
+ }
621
+ if (!this.isRecord(config.customParams)) {
622
+ throw new Error("customParams must be an object");
623
+ }
624
+ for (const [key, entry] of Object.entries(config.customParams)) {
625
+ if (!this.isRecord(entry) || !("value" in entry) || entry.value === void 0) {
626
+ throw new Error(`customParams.${key} must include value`);
627
+ }
628
+ if ("desc" in entry && entry.desc !== void 0 && typeof entry.desc !== "string") {
629
+ throw new Error(`customParams.${key}.desc must be a string`);
630
+ }
631
+ if (!this.isValidCustomParamValue(entry.value)) {
632
+ throw new Error(`customParams.${key}.value has invalid type`);
633
+ }
634
+ }
635
+ return {
636
+ customParams: config.customParams
637
+ };
638
+ }
639
+ isValidCustomParamValue(value) {
640
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
641
+ return true;
642
+ }
643
+ if (Array.isArray(value)) {
644
+ return value.every((item) => typeof item === "string" || typeof item === "number" || typeof item === "boolean" || this.isRecord(item));
645
+ }
646
+ return this.isRecord(value);
647
+ }
648
+ isRecord(value) {
649
+ return typeof value === "object" && value !== null && !Array.isArray(value);
650
+ }
651
+ createContextVersion() {
652
+ return `ctx-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
653
+ }
654
+ cleanupAfterFailedInit() {
655
+ this.messageBridge.offEvent("ready", this.handleSubsequentReady);
656
+ this.messageBridge.detach();
657
+ this.removeIframe();
658
+ }
659
+ removeIframe() {
660
+ if (this.iframe?.parentNode) {
661
+ this.iframe.parentNode.removeChild(this.iframe);
662
+ }
663
+ this.iframe = null;
664
+ }
547
665
  createAgentInstance() {
548
666
  return {
549
667
  destroy: /* @__PURE__ */ __name(async () => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/iframe-manager.ts","../src/device-detector.ts","../src/message-bridge.ts","../src/agent-iframe-manager.ts"],"sourcesContent":["/*\n * index.ts\n * Author: perterpon.wang<perterpon.wang@bytedance.com>\n * Create: Tue Feb 10 2026\n */\n\nimport { IframeManager } from \"./iframe-manager\";\nimport { AgentIframeManager } from \"./agent-iframe-manager\";\n\nimport type {\n\tAgentSDKInitConfig,\n\tAgentSDKInstance,\n\tChatPanel,\n\tWebSDKConfig,\n} from \"./types/config\";\n\n/**\n * Initialize Aily Chat via iframe\n * This is the primary method for initializing the chat panel\n * @param root - Container element for the iframe\n * @param config - Configuration options\n * @returns ChatPanel instance for controlling the chat\n */\nexport async function initAilyChat(\n\troot: HTMLElement,\n\tconfig: WebSDKConfig,\n): Promise<ChatPanel> {\n\tconst manager = new IframeManager(root, config);\n\treturn manager.init();\n}\n\n/**\n * Initialize Agent Chat via iframe\n * @param root - Container element for the iframe\n * @param config - Agent SDK configuration\n * @returns Agent SDK instance for controlling the agent page\n */\nexport async function initAgentChat(\n\troot: HTMLElement,\n\tconfig: AgentSDKInitConfig,\n): Promise<AgentSDKInstance> {\n\tconst manager = new AgentIframeManager(root, config);\n\treturn manager.init();\n}\n\n// Export constants\nexport {\n\tAGENT_IFRAME_BASE_URL,\n\tDEFAULT_ANONYMOUS_CHANNEL_TYPE,\n\tDEFAULT_CHANNEL_TYPE,\n\tgetAgentIframeBaseURL,\n\tgetIframeBaseURL,\n\tIFRAME_BASE_URL,\n\tMESSAGE_TIMEOUT,\n} from \"./constants\";\n// Export types\nexport type {\n\tAgentSDKInitConfig,\n\tAgentSDKInstance,\n\tChatPanel,\n\tWebSDKCommonConfig,\n\tWebSDKConfig,\n\tWebSDKConversionConfig,\n\tWebSDKEditorConfig,\n\tWebSDKEvents,\n\tWebSDKSkillInfo,\n} from \"./types/config\";\n\n// Export message types\nexport type {\n\tIframeEventMessage,\n\tIframeMessage,\n\tIframeMessageType,\n\tIframeRequestMessage,\n\tIframeResponseMessage,\n} from \"./types/message\";\n","/**\n * Constants for Aily Web SDK\n */\n\n/** Message business ID for postMessage identification */\nexport const MESSAGE_BIZ_ID = 'cui-sdk-message' as const;\nexport const PARENT_ORIGIN_QUERY_KEY = '__parentOrigin' as const;\n\n/** Iframe origins by environment */\nexport const IFRAME_ORIGIN: Record<string, string> = {\n production: 'https://aily.feishu.cn',\n staging: 'https://aily.feishu-pre.cn',\n boe: 'https://aily.feishu-boe.cn',\n development: 'http://localhost:8080',\n};\n\n/** Page paths for iframe apps */\nexport const CHAT_IFRAME_PATH = '/cui' as const;\nexport const AGENT_IFRAME_PATH = '/custom_agent/cui' as const;\n\n/** Chat iframe base URLs by environment */\nexport const IFRAME_BASE_URL: Record<string, string> = {\n production: `${IFRAME_ORIGIN.production}${CHAT_IFRAME_PATH}`,\n staging: `${IFRAME_ORIGIN.staging}${CHAT_IFRAME_PATH}`,\n boe: `${IFRAME_ORIGIN.boe}${CHAT_IFRAME_PATH}`,\n development: `${IFRAME_ORIGIN.development}${CHAT_IFRAME_PATH}`,\n};\n\n/** Agent iframe base URLs by environment */\nexport const AGENT_IFRAME_BASE_URL: Record<string, string> = {\n production: `${IFRAME_ORIGIN.production}${AGENT_IFRAME_PATH}`,\n staging: `${IFRAME_ORIGIN.staging}${AGENT_IFRAME_PATH}`,\n boe: `${IFRAME_ORIGIN.boe}${AGENT_IFRAME_PATH}`,\n development: `${IFRAME_ORIGIN.development}${AGENT_IFRAME_PATH}`,\n};\n\ntype IframeEnv = keyof typeof IFRAME_BASE_URL;\n\ninterface AilyWebSdkDebugConfig {\n iframeEnv?: string;\n}\n\ndeclare global {\n interface Window {\n __DEBUG__?: {\n ailyWebSdk?: AilyWebSdkDebugConfig;\n [key: string]: unknown;\n };\n }\n}\n\nfunction isIframeEnv(env?: string): env is IframeEnv {\n return Boolean(env && env in IFRAME_BASE_URL);\n}\n\nfunction resolveDebugIframeEnv(): IframeEnv | undefined {\n if (typeof window === 'undefined') {\n return undefined;\n }\n\n const debugIframeEnv = window.__DEBUG__?.ailyWebSdk?.iframeEnv;\n return isIframeEnv(debugIframeEnv) ? debugIframeEnv : undefined;\n}\n\n/**\n * Get iframe base URL based on environment\n */\nfunction resolveIframeEnv(env?: string): IframeEnv {\n if (isIframeEnv(env)) {\n return env;\n }\n\n const debugIframeEnv = resolveDebugIframeEnv();\n if (debugIframeEnv) {\n return debugIframeEnv;\n }\n\n // Auto-detect based on hostname\n // MiaoDa 宿主域名: miaoda.feishu[-env].cn, *.aiforce[-env][-preview].bytedance.net, *.force-pre.feishuapp.net, *.fsapp.kundou.cn, *.aiforce.run, *.aiforce.cloud\n const hostname =\n typeof window !== 'undefined' ? window.location.hostname : '';\n\n if (hostname.includes('aiforce-boe')) {\n return 'boe';\n }\n if (\n hostname.includes('aiforce-pre') ||\n hostname.includes('force-pre.feishuapp.net') ||\n hostname.includes('fsapp.kundou.cn')\n ) {\n return 'staging';\n }\n\n return 'production';\n}\n\nexport function getIframeBaseURL(env?: string): string {\n return IFRAME_BASE_URL[resolveIframeEnv(env)];\n}\n\n/**\n * Get agent iframe base URL based on environment\n */\nexport function getAgentIframeBaseURL(env?: string): string {\n return AGENT_IFRAME_BASE_URL[resolveIframeEnv(env)];\n}\n\n/** Timeout for postMessage requests (30 seconds) */\nexport const MESSAGE_TIMEOUT = 30 * 1000;\n\n/** Miaoda 渠道标识默认值(用户可通过 config.common.channelType 覆盖) */\nexport const DEFAULT_CHANNEL_TYPE = 'MIAODA_CUI_SDK';\nexport const DEFAULT_ANONYMOUS_CHANNEL_TYPE = 'MIAODA_ANONYMOUS_CUI_SDK';\n\n/** Allowed origins for postMessage (cui-iframe 的 origin) */\nexport const ALLOWED_ORIGINS = [\n IFRAME_ORIGIN.production,\n IFRAME_ORIGIN.staging,\n IFRAME_ORIGIN.boe,\n 'http://localhost:3000',\n 'http://localhost:5173',\n IFRAME_ORIGIN.development,\n];\n","import {\n\tDEFAULT_ANONYMOUS_CHANNEL_TYPE,\n\tDEFAULT_CHANNEL_TYPE,\n\tgetIframeBaseURL,\n\tMESSAGE_BIZ_ID,\n} from \"./constants\";\nimport { slardar } from \"@lark-apaas/internal-slardar\";\nimport { DeviceDetector } from \"./device-detector\";\nimport { MessageBridge } from \"./message-bridge\";\n\nimport type { ChatPanel, WebSDKConfig } from \"./types/config\";\n\n/**\n * IframeManager handles iframe creation and lifecycle\n *\n * iframe 采用自初始化模式:配置通过 URL hash 传入,iframe 加载后自行解析并渲染,\n * 与旧版 copilot iframe 的行为保持一致。宿主通过 postMessage 进行后续操作。\n */\nexport class IframeManager {\n\tprivate iframe: HTMLIFrameElement | null = null;\n\tprivate messageBridge: MessageBridge;\n\tprivate config: WebSDKConfig;\n\tprivate channelType: string;\n\tprivate root: HTMLElement;\n\tprivate deviceDetector: DeviceDetector | null = null;\n\n\tconstructor(root: HTMLElement, config: WebSDKConfig) {\n\t\tthis.root = root;\n\t\tthis.config = config;\n\t\tconst defaultChannel = config.anonymous\n\t\t\t? DEFAULT_ANONYMOUS_CHANNEL_TYPE\n\t\t\t: DEFAULT_CHANNEL_TYPE;\n\t\tthis.channelType = config.common?.channelType || defaultChannel;\n\t\tthis.messageBridge = new MessageBridge(getIframeBaseURL());\n\t}\n\n\t/**\n\t * Initialize the iframe and establish communication\n\t * 配置通过 URL hash 编码传入 iframe,iframe 加载后自行初始化\n\t */\n\tasync init(): Promise<ChatPanel> {\n\t\tconst initStart = performance.now();\n\n\t\t// Auto-detect device if not explicitly provided\n\t\tif (!this.config.device) {\n\t\t\tthis.deviceDetector = new DeviceDetector();\n\t\t\tthis.config.device = this.deviceDetector.getDevice();\n\t\t}\n\n\t\t// Create iframe element\n\t\tthis.iframe = document.createElement(\"iframe\");\n\t\tthis.iframe.src = this.buildIframeURL();\n\t\tthis.iframe.style.width = \"100%\";\n\t\tthis.iframe.style.height = \"100%\";\n\t\tthis.iframe.style.border = \"none\";\n\t\tthis.iframe.allow = \"microphone; clipboard-write\";\n\n\t\t// Attach to DOM\n\t\tthis.root.appendChild(this.iframe);\n\n\t\t// Attach message bridge (开始监听消息)\n\t\tthis.messageBridge.attach(this.iframe);\n\n\t\t// Setup event handlers (在 iframe 初始化完成之前就开始监听,确保不丢失事件)\n\t\tthis.setupEventHandlers();\n\n\t\t// Listen for device changes and push updates to iframe\n\t\tif (this.deviceDetector) {\n\t\t\tthis.deviceDetector.observe((newDevice) => {\n\t\t\t\tthis.messageBridge.send(\"updateConfig\", { device: newDevice });\n\t\t\t});\n\t\t}\n\n\t\t// Wait for iframe to finish initialization (iframe 自行读取 URL 配置并渲染,完成后发送 ready 事件)\n\t\tawait this.waitForReady();\n\n\t\t// 上报 cui_init_total 耗时(iframe 创建 → init 完成)\n\t\tthis.reportInitMetrics(initStart);\n\n\t\t// Return ChatPanel interface\n\t\treturn this.createChatPanel();\n\t}\n\n\t/**\n\t * Destroy the iframe and cleanup\n\t */\n\tasync destroy(): Promise<void> {\n\t\ttry {\n\t\t\tawait this.messageBridge.send(\"destroy\");\n\t\t} catch {\n\t\t\t// Ignore errors during destroy\n\t\t}\n\n\t\tthis.messageBridge.detach();\n\n\t\tif (this.deviceDetector) {\n\t\t\tthis.deviceDetector.destroy();\n\t\t\tthis.deviceDetector = null;\n\t\t}\n\n\t\tif (this.iframe?.parentNode) {\n\t\t\tthis.iframe.parentNode.removeChild(this.iframe);\n\t\t}\n\n\t\tthis.iframe = null;\n\t}\n\n\t/**\n\t * 构建 iframe URL,将配置编码到 hash 中\n\t * 格式: {baseURL}#{params} 其中 config 为 base64(JSON.stringify(configWithoutEvents))\n\t *\n\t * 鉴权说明:SDK 不参与 token 获取/传递。iframe 自行处理飞书登录流程,\n\t * 允许用户在 iframe 中独立登录。匿名渠道跳过登录检查。\n\t */\n\tprivate buildIframeURL(): string {\n\t\tconst baseURL = getIframeBaseURL();\n\n\t\t// 移除 events(函数无法序列化)\n\t\tconst {\n\t\t\tevents: _events,\n\t\t\tanonymous: _anonymous,\n\t\t\t...configWithoutEvents\n\t\t} = this.config;\n\t\t// 注入 channelType/resourceType(SDK 内部控制,不暴露给消费者)\n\t\t// 补全 editor.skill 硬编码字段\n\t\tconst editorConfig = configWithoutEvents.editor?.skill\n\t\t\t? {\n\t\t\t\t\t...configWithoutEvents.editor,\n\t\t\t\t\tskill: {\n\t\t\t\t\t\ttype: \"custom\",\n\t\t\t\t\t\tbuiltinType: \"unspecified\",\n\t\t\t\t\t\t...configWithoutEvents.editor.skill,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: configWithoutEvents.editor;\n\n\t\tconst iframeConfig = {\n\t\t\t...configWithoutEvents,\n\t\t\tcommon: {\n\t\t\t\t...configWithoutEvents.common,\n\t\t\t\tchannelType: this.channelType,\n\t\t\t\tresourceType:\n\t\t\t\t\tconfigWithoutEvents.common?.resourceType || this.channelType,\n\t\t\t},\n\t\t\teditor: editorConfig,\n\t\t};\n\t\tconst configBase64 = btoa(encodeURIComponent(JSON.stringify(iframeConfig)));\n\n\t\tconst params = new URLSearchParams({\n\t\t\tappKey: this.config.appKey,\n\t\t\tconfig: encodeURIComponent(configBase64),\n\t\t});\n\n\t\treturn `${baseURL}#${params.toString()}`;\n\t}\n\n\t/**\n\t * 等待 iframe 自行初始化完成后发送 ready 事件\n\t */\n\tprivate waitForReady(): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\tconst error = new Error(\"Iframe ready timeout\");\n\t\t\t\tslardar.captureException(error, { source: 'aily-web-sdk', module: 'iframe-ready' });\n\t\t\t\treject(error);\n\t\t\t}, 30000);\n\n\t\t\tconst checkMessage = (event: MessageEvent) => {\n\t\t\t\tif (\n\t\t\t\t\tevent.data?.messageBizId === MESSAGE_BIZ_ID &&\n\t\t\t\t\tevent.data?.type === \"event\" &&\n\t\t\t\t\tevent.data?.eventName === \"ready\"\n\t\t\t\t) {\n\t\t\t\t\tclearTimeout(timeout);\n\t\t\t\t\twindow.removeEventListener(\"message\", checkMessage);\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\twindow.addEventListener(\"message\", checkMessage);\n\t\t});\n\t}\n\n\tprivate setupEventHandlers(): void {\n\t\tconst { events } = this.config;\n\t\tif (!events) return;\n\n\t\tif (events.onReady) {\n\t\t\tthis.messageBridge.onEvent(\"ready\", events.onReady);\n\t\t}\n\n\t\tif (events.onError) {\n\t\t\tthis.messageBridge.onEvent(\"error\", (data: unknown) => {\n\t\t\t\tconst msg = (data as { message?: string })?.message || \"Unknown error\";\n\t\t\t\tevents.onError?.(new Error(msg));\n\t\t\t});\n\t\t}\n\n\t\tif (events.onMessage) {\n\t\t\tthis.messageBridge.onEvent(\"onMessage\", events.onMessage);\n\t\t}\n\n\t\tif (events.onInited) {\n\t\t\tthis.messageBridge.onEvent(\n\t\t\t\t\"inited\",\n\t\t\t\tevents.onInited as (data: unknown) => void,\n\t\t\t);\n\t\t}\n\n\t\tif (events.onInitedWithWelcome) {\n\t\t\tthis.messageBridge.onEvent(\n\t\t\t\t\"initedWithWelcome\",\n\t\t\t\tevents.onInitedWithWelcome,\n\t\t\t);\n\t\t}\n\n\t\tif (events.onClose) {\n\t\t\tthis.messageBridge.onEvent(\"onClose\", events.onClose);\n\t\t}\n\t}\n\n\tprivate reportInitMetrics(initStart: number): void {\n\t\ttry {\n\t\t\tconst cost = performance.now() - initStart;\n\t\t\tslardar.sendEvent({\n\t\t\t\tname: \"cui_init_total\",\n\t\t\t\tmetrics: { cost },\n\t\t\t\tcategories: {\n\t\t\t\t\tarch: \"iframe-static\",\n\t\t\t\t\tappKey: this.config.appKey,\n\t\t\t\t\tchannelType: this.channelType,\n\t\t\t\t},\n\t\t\t});\n\t\t} catch {\n\t\t\t// 性能上报失败不影响功能\n\t\t}\n\t}\n\n\tprivate createChatPanel(): ChatPanel {\n\t\treturn {\n\t\t\tsendMessage: async (data) => {\n\t\t\t\tawait this.messageBridge.send(\"sendMessage\", data);\n\t\t\t},\n\t\t\tclear: async () => {\n\t\t\t\tawait this.messageBridge.send(\"clear\");\n\t\t\t},\n\t\t\tcancelMessage: async (messageItem) => {\n\t\t\t\tawait this.messageBridge.send(\"cancelMessage\", messageItem);\n\t\t\t},\n\t\t\tclearAndStop: async () => {\n\t\t\t\tawait this.messageBridge.send(\"clearAndStop\");\n\t\t\t},\n\t\t\tupdateWelcomeMessage: async () => {\n\t\t\t\tawait this.messageBridge.send(\"updateWelcomeMessage\");\n\t\t\t},\n\t\t\tupdateConfig: async (config) => {\n\t\t\t\tawait this.messageBridge.send(\"updateConfig\", config);\n\t\t\t},\n\t\t\tobserveSkill: async (skillId, name, skillType) => {\n\t\t\t\tawait this.messageBridge.send(\"observeSkill\", {\n\t\t\t\t\tskillId,\n\t\t\t\t\tname,\n\t\t\t\t\tskillType,\n\t\t\t\t});\n\t\t\t},\n\t\t\tsetCurrentSkill: async (skill) => {\n\t\t\t\tawait this.messageBridge.send(\"setCurrentSkill\", skill);\n\t\t\t},\n\t\t\tdestroy: async () => {\n\t\t\t\tawait this.destroy();\n\t\t\t},\n\t\t};\n\t}\n}\n","const MOBILE_BREAKPOINT = 768;\n\ntype DeviceType = 'pc' | 'mobile';\ntype DeviceChangeCallback = (device: DeviceType) => void;\n\n/**\n * 设备类型自动检测器\n *\n * 使用 matchMedia + 768px 断点检测设备类型,与 miaoda useIsMobile 逻辑一致。\n * 检测在宿主页面(而非 iframe)中执行,结果通过 postMessage 推送给 iframe。\n */\nexport class DeviceDetector {\n private mediaQuery: MediaQueryList;\n private currentDevice: DeviceType;\n private callback: DeviceChangeCallback | null = null;\n private handleChange: (() => void) | null = null;\n\n constructor() {\n this.mediaQuery = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);\n this.currentDevice = window.innerWidth < MOBILE_BREAKPOINT ? 'mobile' : 'pc';\n }\n\n getDevice(): DeviceType {\n return this.currentDevice;\n }\n\n observe(callback: DeviceChangeCallback): void {\n this.callback = callback;\n this.handleChange = () => {\n const newDevice: DeviceType = window.innerWidth < MOBILE_BREAKPOINT ? 'mobile' : 'pc';\n if (newDevice !== this.currentDevice) {\n this.currentDevice = newDevice;\n this.callback?.(newDevice);\n }\n };\n this.mediaQuery.addEventListener('change', this.handleChange);\n }\n\n destroy(): void {\n if (this.handleChange) {\n this.mediaQuery.removeEventListener('change', this.handleChange);\n this.handleChange = null;\n }\n this.callback = null;\n }\n}\n","import { MESSAGE_TIMEOUT, ALLOWED_ORIGINS } from './constants';\nimport {\n MESSAGE_BIZ_ID,\n type IframeMessage,\n type IframeRequestMessage,\n type IframeResponseMessage,\n type IframeEventMessage,\n type IframeMessageType,\n} from './types/message';\nimport { slardar } from '@lark-apaas/internal-slardar';\n\ninterface PendingRequest {\n resolve: (value: unknown) => void;\n reject: (reason: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\n/**\n * MessageBridge handles postMessage communication between parent and iframe\n */\nexport class MessageBridge {\n private iframe: HTMLIFrameElement | null = null;\n private requestId = 0;\n private pendingRequests = new Map<number, PendingRequest>();\n private eventHandlers = new Map<string, ((data: unknown) => void)[]>();\n private targetOrigin: string;\n\n constructor(targetOrigin: string) {\n this.targetOrigin = new URL(targetOrigin).origin;\n this.handleMessage = this.handleMessage.bind(this);\n }\n\n /**\n * Attach to an iframe and start listening for messages\n */\n attach(iframe: HTMLIFrameElement): void {\n this.iframe = iframe;\n window.addEventListener('message', this.handleMessage);\n }\n\n /**\n * Detach from iframe and clean up\n */\n detach(): void {\n window.removeEventListener('message', this.handleMessage);\n this.iframe = null;\n // Clear all pending requests\n this.pendingRequests.forEach(({ reject }) => {\n reject(new Error('MessageBridge detached'));\n });\n this.pendingRequests.clear();\n }\n\n /**\n * Send a message to the iframe and wait for response\n */\n send<T = unknown>(type: IframeMessageType, data?: unknown): Promise<T> {\n return new Promise((resolve, reject) => {\n if (!this.iframe?.contentWindow) {\n reject(new Error('Iframe not attached'));\n return;\n }\n\n this.requestId += 1;\n const id = this.requestId;\n const message: IframeRequestMessage = {\n messageBizId: MESSAGE_BIZ_ID,\n id,\n type,\n data,\n timestamp: Date.now(),\n isRequest: true,\n };\n\n const timer = setTimeout(() => {\n this.pendingRequests.delete(id);\n const error = new Error(`Message timeout: ${type}`);\n slardar.captureException(error, { source: 'aily-web-sdk', module: 'message-bridge', messageType: type });\n reject(error);\n }, MESSAGE_TIMEOUT);\n\n this.pendingRequests.set(id, { resolve: resolve as (value: unknown) => void, reject, timer });\n\n this.iframe.contentWindow.postMessage(message, this.targetOrigin);\n });\n }\n\n /**\n * Register an event handler\n */\n onEvent(eventName: string, handler: (data: unknown) => void): void {\n const handlers = this.eventHandlers.get(eventName) || [];\n handlers.push(handler);\n this.eventHandlers.set(eventName, handlers);\n }\n\n /**\n * Remove an event handler\n */\n offEvent(eventName: string, handler: (data: unknown) => void): void {\n const handlers = this.eventHandlers.get(eventName) || [];\n const index = handlers.indexOf(handler);\n if (index > -1) {\n handlers.splice(index, 1);\n this.eventHandlers.set(eventName, handlers);\n }\n }\n\n private handleMessage(event: MessageEvent<IframeMessage>): void {\n // Validate origin\n if (!ALLOWED_ORIGINS.includes(event.origin)) {\n return;\n }\n\n const { data } = event;\n\n // Validate message format\n if (data?.messageBizId !== MESSAGE_BIZ_ID) {\n return;\n }\n\n // Handle response messages\n if (this.isResponseMessage(data)) {\n const pending = this.pendingRequests.get(data.id);\n if (pending) {\n clearTimeout(pending.timer);\n this.pendingRequests.delete(data.id);\n\n if (data.error) {\n const error = new Error(data.error.message);\n slardar.captureException(error, { source: 'aily-web-sdk', module: 'message-bridge', errorCode: data.error.code });\n pending.reject(error);\n } else {\n pending.resolve(data.data);\n }\n }\n }\n\n // Handle event messages\n if (this.isEventMessage(data)) {\n const handlers = this.eventHandlers.get(data.eventName) || [];\n handlers.forEach((handler) => {\n try {\n handler(data.data);\n } catch {\n // Ignore handler errors\n }\n });\n }\n }\n\n private isResponseMessage(data: IframeMessage): data is IframeResponseMessage {\n return 'isResponse' in data && data.isResponse === true;\n }\n\n private isEventMessage(data: IframeMessage): data is IframeEventMessage {\n return data.type === 'event';\n }\n}\n","import {\n MESSAGE_BIZ_ID,\n PARENT_ORIGIN_QUERY_KEY,\n getAgentIframeBaseURL,\n} from './constants';\nimport { MessageBridge } from './message-bridge';\n\nimport type { AgentSDKInitConfig, AgentSDKInstance } from './types/config';\nimport type { ParentContextMessageData } from './types/message';\n\n/**\n * AgentIframeManager handles agent iframe creation and lifecycle.\n */\nexport class AgentIframeManager {\n private iframe: HTMLIFrameElement | null = null;\n private readonly messageBridge: MessageBridge;\n private readonly config: AgentSDKInitConfig;\n private readonly root: HTMLElement;\n\n constructor(root: HTMLElement, config: AgentSDKInitConfig) {\n this.root = root;\n this.config = config;\n this.messageBridge = new MessageBridge(getAgentIframeBaseURL());\n }\n\n async init(): Promise<AgentSDKInstance> {\n this.iframe = document.createElement('iframe');\n this.iframe.src = this.buildIframeURL();\n this.iframe.style.width = '100%';\n this.iframe.style.height = '100%';\n this.iframe.style.border = 'none';\n this.iframe.allow = 'microphone; clipboard-write';\n\n this.root.appendChild(this.iframe);\n this.messageBridge.attach(this.iframe);\n\n await this.waitForReady();\n await this.messageBridge.send(\n 'initParentContext',\n this.buildParentContext()\n );\n\n return this.createAgentInstance();\n }\n\n async destroy(): Promise<void> {\n try {\n await this.messageBridge.send('destroy');\n } catch {\n // Ignore errors during destroy.\n }\n\n this.messageBridge.detach();\n\n if (this.iframe?.parentNode) {\n this.iframe.parentNode.removeChild(this.iframe);\n }\n\n this.iframe = null;\n }\n\n private buildIframeURL(): string {\n const baseURL = getAgentIframeBaseURL();\n const params = new URLSearchParams({\n channelToken: this.config.channelToken,\n [PARENT_ORIGIN_QUERY_KEY]: window.location.origin,\n });\n\n return `${baseURL}?${params.toString()}`;\n }\n\n private buildParentContext(): ParentContextMessageData {\n return {\n parentOrigin: window.location.origin,\n };\n }\n\n private waitForReady(): Promise<void> {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n window.removeEventListener('message', checkMessage);\n reject(new Error('Iframe ready timeout'));\n }, 30000);\n\n const checkMessage = (event: MessageEvent) => {\n if (\n event.data?.messageBizId === MESSAGE_BIZ_ID &&\n event.data?.type === 'event' &&\n event.data?.eventName === 'ready'\n ) {\n clearTimeout(timeout);\n window.removeEventListener('message', checkMessage);\n resolve();\n }\n };\n\n window.addEventListener('message', checkMessage);\n });\n }\n\n private createAgentInstance(): AgentSDKInstance {\n return {\n destroy: async () => {\n await this.destroy();\n },\n };\n }\n}\n"],"mappings":"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","names":["MESSAGE_BIZ_ID","PARENT_ORIGIN_QUERY_KEY","IFRAME_ORIGIN","production","staging","boe","development","CHAT_IFRAME_PATH","AGENT_IFRAME_PATH","IFRAME_BASE_URL","AGENT_IFRAME_BASE_URL","isIframeEnv","env","Boolean","resolveDebugIframeEnv","window","undefined","debugIframeEnv","__DEBUG__","ailyWebSdk","iframeEnv","resolveIframeEnv","hostname","location","includes","getIframeBaseURL","getAgentIframeBaseURL","MESSAGE_TIMEOUT","DEFAULT_CHANNEL_TYPE","DEFAULT_ANONYMOUS_CHANNEL_TYPE","ALLOWED_ORIGINS","import_internal_slardar","MOBILE_BREAKPOINT","DeviceDetector","mediaQuery","currentDevice","callback","handleChange","window","matchMedia","innerWidth","getDevice","observe","newDevice","addEventListener","destroy","removeEventListener","MessageBridge","targetOrigin","iframe","requestId","pendingRequests","Map","eventHandlers","URL","origin","handleMessage","bind","attach","window","addEventListener","detach","removeEventListener","forEach","reject","Error","clear","send","type","data","Promise","resolve","contentWindow","id","message","messageBizId","MESSAGE_BIZ_ID","timestamp","Date","now","isRequest","timer","setTimeout","delete","error","slardar","captureException","source","module","messageType","MESSAGE_TIMEOUT","set","postMessage","onEvent","eventName","handler","handlers","get","push","offEvent","index","indexOf","splice","event","ALLOWED_ORIGINS","includes","isResponseMessage","pending","clearTimeout","errorCode","code","isEventMessage","isResponse","IframeManager","root","config","iframe","messageBridge","channelType","deviceDetector","defaultChannel","anonymous","DEFAULT_ANONYMOUS_CHANNEL_TYPE","DEFAULT_CHANNEL_TYPE","common","MessageBridge","getIframeBaseURL","init","initStart","performance","now","device","DeviceDetector","getDevice","document","createElement","src","buildIframeURL","style","width","height","border","allow","appendChild","attach","setupEventHandlers","observe","newDevice","send","waitForReady","reportInitMetrics","createChatPanel","destroy","detach","parentNode","removeChild","baseURL","events","_events","_anonymous","configWithoutEvents","editorConfig","editor","skill","type","builtinType","iframeConfig","resourceType","configBase64","btoa","encodeURIComponent","JSON","stringify","params","URLSearchParams","appKey","toString","Promise","resolve","reject","timeout","setTimeout","error","Error","slardar","captureException","source","module","checkMessage","event","data","messageBizId","MESSAGE_BIZ_ID","eventName","clearTimeout","window","removeEventListener","addEventListener","onReady","onEvent","onError","msg","message","onMessage","onInited","onInitedWithWelcome","onClose","cost","sendEvent","name","metrics","categories","arch","sendMessage","clear","cancelMessage","messageItem","clearAndStop","updateWelcomeMessage","updateConfig","observeSkill","skillId","skillType","setCurrentSkill","AgentIframeManager","root","config","iframe","messageBridge","MessageBridge","getAgentIframeBaseURL","init","document","createElement","src","buildIframeURL","style","width","height","border","allow","appendChild","attach","waitForReady","send","buildParentContext","createAgentInstance","destroy","detach","parentNode","removeChild","baseURL","params","URLSearchParams","channelToken","PARENT_ORIGIN_QUERY_KEY","window","location","origin","toString","parentOrigin","Promise","resolve","reject","timeout","setTimeout","removeEventListener","checkMessage","Error","event","data","messageBizId","MESSAGE_BIZ_ID","type","eventName","clearTimeout","addEventListener","initAilyChat","root","config","manager","IframeManager","init","initAgentChat","AgentIframeManager"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/iframe-manager.ts","../src/device-detector.ts","../src/message-bridge.ts","../src/agent-iframe-manager.ts"],"sourcesContent":["/*\n * index.ts\n * Author: perterpon.wang<perterpon.wang@bytedance.com>\n * Create: Tue Feb 10 2026\n */\n\nimport { IframeManager } from \"./iframe-manager\";\nimport { AgentIframeManager } from \"./agent-iframe-manager\";\n\nimport type {\n\tAgentSDKInitConfig,\n\tAgentSDKInstance,\n\tChatPanel,\n\tWebSDKConfig,\n} from \"./types/config\";\n\n/**\n * Initialize Aily Chat via iframe\n * This is the primary method for initializing the chat panel\n * @param root - Container element for the iframe\n * @param config - Configuration options\n * @returns ChatPanel instance for controlling the chat\n */\nexport async function initAilyChat(\n\troot: HTMLElement,\n\tconfig: WebSDKConfig,\n): Promise<ChatPanel> {\n\tconst manager = new IframeManager(root, config);\n\treturn manager.init();\n}\n\n/**\n * Initialize Agent Chat via iframe\n * @param root - Container element for the iframe\n * @param config - Agent SDK configuration\n * @returns Agent SDK instance for controlling the agent page\n */\nexport async function initAgentChat(\n\troot: HTMLElement,\n\tconfig: AgentSDKInitConfig,\n): Promise<AgentSDKInstance> {\n\tconst manager = new AgentIframeManager(root, config);\n\treturn manager.init();\n}\n\n// Export constants\nexport {\n\tAGENT_IFRAME_BASE_URL,\n\tDEFAULT_ANONYMOUS_CHANNEL_TYPE,\n\tDEFAULT_CHANNEL_TYPE,\n\tgetAgentIframeBaseURL,\n\tgetIframeBaseURL,\n\tIFRAME_BASE_URL,\n\tMESSAGE_TIMEOUT,\n} from \"./constants\";\n// Export types\nexport type {\n\tAgentSDKInitConfig,\n\tAgentSDKInstance,\n AgentSDKRuntimeCustomContext,\n\tChatPanel,\n CustomParamEntry,\n CustomParams,\n\tWebSDKCommonConfig,\n\tWebSDKConfig,\n\tWebSDKConversionConfig,\n\tWebSDKEditorConfig,\n\tWebSDKEvents,\n\tWebSDKSkillInfo,\n} from \"./types/config\";\n\n// Export message types\nexport type {\n\tIframeEventMessage,\n\tIframeMessage,\n\tIframeMessageType,\n\tIframeRequestMessage,\n\tIframeResponseMessage,\n} from \"./types/message\";\n","/**\n * Constants for Aily Web SDK\n */\n\n/** Message business ID for postMessage identification */\nexport const MESSAGE_BIZ_ID = 'cui-sdk-message' as const;\nexport const PARENT_ORIGIN_QUERY_KEY = '__parentOrigin' as const;\n\n/** Iframe origins by environment */\nexport const IFRAME_ORIGIN: Record<string, string> = {\n production: 'https://aily.feishu.cn',\n staging: 'https://aily.feishu-pre.cn',\n boe: 'https://aily.feishu-boe.cn',\n development: 'http://localhost:3000',\n};\n\n/** Page paths for iframe apps */\nexport const CHAT_IFRAME_PATH = '/cui' as const;\nexport const AGENT_IFRAME_PATH = '/custom_agent/cui' as const;\n\n/** Chat iframe base URLs by environment */\nexport const IFRAME_BASE_URL: Record<string, string> = {\n production: `${IFRAME_ORIGIN.production}${CHAT_IFRAME_PATH}`,\n staging: `${IFRAME_ORIGIN.staging}${CHAT_IFRAME_PATH}`,\n boe: `${IFRAME_ORIGIN.boe}${CHAT_IFRAME_PATH}`,\n development: `${IFRAME_ORIGIN.development}${CHAT_IFRAME_PATH}`,\n};\n\n/** Agent iframe base URLs by environment */\nexport const AGENT_IFRAME_BASE_URL: Record<string, string> = {\n production: `${IFRAME_ORIGIN.production}${AGENT_IFRAME_PATH}`,\n staging: `${IFRAME_ORIGIN.staging}${AGENT_IFRAME_PATH}`,\n boe: `${IFRAME_ORIGIN.boe}${AGENT_IFRAME_PATH}`,\n development: `${IFRAME_ORIGIN.development}${AGENT_IFRAME_PATH}`,\n};\n\ntype IframeEnv = keyof typeof IFRAME_BASE_URL;\n\ninterface AilyWebSdkDebugConfig {\n iframeEnv?: string;\n}\n\ndeclare global {\n interface Window {\n __DEBUG__?: {\n ailyWebSdk?: AilyWebSdkDebugConfig;\n [key: string]: unknown;\n };\n }\n}\n\nfunction isIframeEnv(env?: string): env is IframeEnv {\n return Boolean(env && env in IFRAME_BASE_URL);\n}\n\nfunction resolveDebugIframeEnv(): IframeEnv | undefined {\n if (typeof window === 'undefined') {\n return undefined;\n }\n\n const debugIframeEnv = window.__DEBUG__?.ailyWebSdk?.iframeEnv;\n return isIframeEnv(debugIframeEnv) ? debugIframeEnv : undefined;\n}\n\n/**\n * Get iframe base URL based on environment\n */\nfunction resolveIframeEnv(env?: string): IframeEnv {\n if (isIframeEnv(env)) {\n return env;\n }\n\n const debugIframeEnv = resolveDebugIframeEnv();\n if (debugIframeEnv) {\n return debugIframeEnv;\n }\n\n // Auto-detect based on hostname\n // MiaoDa 宿主域名: miaoda.feishu[-env].cn, *.aiforce[-env][-preview].bytedance.net, *.force-pre.feishuapp.net, *.fsapp.kundou.cn, *.aiforce.run, *.aiforce.cloud\n const hostname =\n typeof window !== 'undefined' ? window.location.hostname : '';\n\n if (hostname.includes('aiforce-boe')) {\n return 'boe';\n }\n if (\n hostname.includes('aiforce-pre') ||\n hostname.includes('force-pre.feishuapp.net') ||\n hostname.includes('fsapp.kundou.cn')\n ) {\n return 'staging';\n }\n\n return 'production';\n}\n\nexport function getIframeBaseURL(env?: string): string {\n return IFRAME_BASE_URL[resolveIframeEnv(env)];\n}\n\n/**\n * Get agent iframe base URL based on environment\n */\nexport function getAgentIframeBaseURL(env?: string): string {\n return AGENT_IFRAME_BASE_URL[resolveIframeEnv(env)];\n}\n\n/** Timeout for postMessage requests (30 seconds) */\nexport const MESSAGE_TIMEOUT = 30 * 1000;\n\n/** Miaoda 渠道标识默认值(用户可通过 config.common.channelType 覆盖) */\nexport const DEFAULT_CHANNEL_TYPE = 'MIAODA_CUI_SDK';\nexport const DEFAULT_ANONYMOUS_CHANNEL_TYPE = 'MIAODA_ANONYMOUS_CUI_SDK';\n\n/** Allowed origins for postMessage (cui-iframe 的 origin) */\nexport const ALLOWED_ORIGINS = [\n IFRAME_ORIGIN.production,\n IFRAME_ORIGIN.staging,\n IFRAME_ORIGIN.boe,\n 'http://localhost:3000',\n 'http://localhost:5173',\n IFRAME_ORIGIN.development,\n];\n","import {\n\tDEFAULT_ANONYMOUS_CHANNEL_TYPE,\n\tDEFAULT_CHANNEL_TYPE,\n\tgetIframeBaseURL,\n\tMESSAGE_BIZ_ID,\n} from \"./constants\";\nimport { slardar } from \"@lark-apaas/internal-slardar\";\nimport { DeviceDetector } from \"./device-detector\";\nimport { MessageBridge } from \"./message-bridge\";\n\nimport type { ChatPanel, WebSDKConfig } from \"./types/config\";\n\n/**\n * IframeManager handles iframe creation and lifecycle\n *\n * iframe 采用自初始化模式:配置通过 URL hash 传入,iframe 加载后自行解析并渲染,\n * 与旧版 copilot iframe 的行为保持一致。宿主通过 postMessage 进行后续操作。\n */\nexport class IframeManager {\n\tprivate iframe: HTMLIFrameElement | null = null;\n\tprivate messageBridge: MessageBridge;\n\tprivate config: WebSDKConfig;\n\tprivate channelType: string;\n\tprivate root: HTMLElement;\n\tprivate deviceDetector: DeviceDetector | null = null;\n\n\tconstructor(root: HTMLElement, config: WebSDKConfig) {\n\t\tthis.root = root;\n\t\tthis.config = config;\n\t\tconst defaultChannel = config.anonymous\n\t\t\t? DEFAULT_ANONYMOUS_CHANNEL_TYPE\n\t\t\t: DEFAULT_CHANNEL_TYPE;\n\t\tthis.channelType = config.common?.channelType || defaultChannel;\n\t\tthis.messageBridge = new MessageBridge(getIframeBaseURL());\n\t}\n\n\t/**\n\t * Initialize the iframe and establish communication\n\t * 配置通过 URL hash 编码传入 iframe,iframe 加载后自行初始化\n\t */\n\tasync init(): Promise<ChatPanel> {\n\t\tconst initStart = performance.now();\n\n\t\t// Auto-detect device if not explicitly provided\n\t\tif (!this.config.device) {\n\t\t\tthis.deviceDetector = new DeviceDetector();\n\t\t\tthis.config.device = this.deviceDetector.getDevice();\n\t\t}\n\n\t\t// Create iframe element\n\t\tthis.iframe = document.createElement(\"iframe\");\n\t\tthis.iframe.src = this.buildIframeURL();\n\t\tthis.iframe.style.width = \"100%\";\n\t\tthis.iframe.style.height = \"100%\";\n\t\tthis.iframe.style.border = \"none\";\n\t\tthis.iframe.allow = \"microphone; clipboard-write\";\n\n\t\t// Attach to DOM\n\t\tthis.root.appendChild(this.iframe);\n\n\t\t// Attach message bridge (开始监听消息)\n\t\tthis.messageBridge.attach(this.iframe);\n\n\t\t// Setup event handlers (在 iframe 初始化完成之前就开始监听,确保不丢失事件)\n\t\tthis.setupEventHandlers();\n\n\t\t// Listen for device changes and push updates to iframe\n\t\tif (this.deviceDetector) {\n\t\t\tthis.deviceDetector.observe((newDevice) => {\n\t\t\t\tthis.messageBridge.send(\"updateConfig\", { device: newDevice });\n\t\t\t});\n\t\t}\n\n\t\t// Wait for iframe to finish initialization (iframe 自行读取 URL 配置并渲染,完成后发送 ready 事件)\n\t\tawait this.waitForReady();\n\n\t\t// 上报 cui_init_total 耗时(iframe 创建 → init 完成)\n\t\tthis.reportInitMetrics(initStart);\n\n\t\t// Return ChatPanel interface\n\t\treturn this.createChatPanel();\n\t}\n\n\t/**\n\t * Destroy the iframe and cleanup\n\t */\n\tasync destroy(): Promise<void> {\n\t\ttry {\n\t\t\tawait this.messageBridge.send(\"destroy\");\n\t\t} catch {\n\t\t\t// Ignore errors during destroy\n\t\t}\n\n\t\tthis.messageBridge.detach();\n\n\t\tif (this.deviceDetector) {\n\t\t\tthis.deviceDetector.destroy();\n\t\t\tthis.deviceDetector = null;\n\t\t}\n\n\t\tif (this.iframe?.parentNode) {\n\t\t\tthis.iframe.parentNode.removeChild(this.iframe);\n\t\t}\n\n\t\tthis.iframe = null;\n\t}\n\n\t/**\n\t * 构建 iframe URL,将配置编码到 hash 中\n\t * 格式: {baseURL}#{params} 其中 config 为 base64(JSON.stringify(configWithoutEvents))\n\t *\n\t * 鉴权说明:SDK 不参与 token 获取/传递。iframe 自行处理飞书登录流程,\n\t * 允许用户在 iframe 中独立登录。匿名渠道跳过登录检查。\n\t */\n\tprivate buildIframeURL(): string {\n\t\tconst baseURL = getIframeBaseURL();\n\n\t\t// 移除 events(函数无法序列化)\n\t\tconst {\n\t\t\tevents: _events,\n\t\t\tanonymous: _anonymous,\n\t\t\t...configWithoutEvents\n\t\t} = this.config;\n\t\t// 注入 channelType/resourceType(SDK 内部控制,不暴露给消费者)\n\t\t// 补全 editor.skill 硬编码字段\n\t\tconst editorConfig = configWithoutEvents.editor?.skill\n\t\t\t? {\n\t\t\t\t\t...configWithoutEvents.editor,\n\t\t\t\t\tskill: {\n\t\t\t\t\t\ttype: \"custom\",\n\t\t\t\t\t\tbuiltinType: \"unspecified\",\n\t\t\t\t\t\t...configWithoutEvents.editor.skill,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: configWithoutEvents.editor;\n\n\t\tconst iframeConfig = {\n\t\t\t...configWithoutEvents,\n\t\t\tcommon: {\n\t\t\t\t...configWithoutEvents.common,\n\t\t\t\tchannelType: this.channelType,\n\t\t\t\tresourceType:\n\t\t\t\t\tconfigWithoutEvents.common?.resourceType || this.channelType,\n\t\t\t},\n\t\t\teditor: editorConfig,\n\t\t};\n\t\tconst configBase64 = btoa(encodeURIComponent(JSON.stringify(iframeConfig)));\n\n\t\tconst params = new URLSearchParams({\n\t\t\tappKey: this.config.appKey,\n\t\t\tconfig: encodeURIComponent(configBase64),\n\t\t});\n\n\t\treturn `${baseURL}#${params.toString()}`;\n\t}\n\n\t/**\n\t * 等待 iframe 自行初始化完成后发送 ready 事件\n\t */\n\tprivate waitForReady(): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\tconst error = new Error(\"Iframe ready timeout\");\n\t\t\t\tslardar.captureException(error, { source: 'aily-web-sdk', module: 'iframe-ready' });\n\t\t\t\treject(error);\n\t\t\t}, 30000);\n\n\t\t\tconst checkMessage = (event: MessageEvent) => {\n\t\t\t\tif (\n\t\t\t\t\tevent.data?.messageBizId === MESSAGE_BIZ_ID &&\n\t\t\t\t\tevent.data?.type === \"event\" &&\n\t\t\t\t\tevent.data?.eventName === \"ready\"\n\t\t\t\t) {\n\t\t\t\t\tclearTimeout(timeout);\n\t\t\t\t\twindow.removeEventListener(\"message\", checkMessage);\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\twindow.addEventListener(\"message\", checkMessage);\n\t\t});\n\t}\n\n\tprivate setupEventHandlers(): void {\n\t\tconst { events } = this.config;\n\t\tif (!events) return;\n\n\t\tif (events.onReady) {\n\t\t\tthis.messageBridge.onEvent(\"ready\", events.onReady);\n\t\t}\n\n\t\tif (events.onError) {\n\t\t\tthis.messageBridge.onEvent(\"error\", (data: unknown) => {\n\t\t\t\tconst msg = (data as { message?: string })?.message || \"Unknown error\";\n\t\t\t\tevents.onError?.(new Error(msg));\n\t\t\t});\n\t\t}\n\n\t\tif (events.onMessage) {\n\t\t\tthis.messageBridge.onEvent(\"onMessage\", events.onMessage);\n\t\t}\n\n\t\tif (events.onInited) {\n\t\t\tthis.messageBridge.onEvent(\n\t\t\t\t\"inited\",\n\t\t\t\tevents.onInited as (data: unknown) => void,\n\t\t\t);\n\t\t}\n\n\t\tif (events.onInitedWithWelcome) {\n\t\t\tthis.messageBridge.onEvent(\n\t\t\t\t\"initedWithWelcome\",\n\t\t\t\tevents.onInitedWithWelcome,\n\t\t\t);\n\t\t}\n\n\t\tif (events.onClose) {\n\t\t\tthis.messageBridge.onEvent(\"onClose\", events.onClose);\n\t\t}\n\t}\n\n\tprivate reportInitMetrics(initStart: number): void {\n\t\ttry {\n\t\t\tconst cost = performance.now() - initStart;\n\t\t\tslardar.sendEvent({\n\t\t\t\tname: \"cui_init_total\",\n\t\t\t\tmetrics: { cost },\n\t\t\t\tcategories: {\n\t\t\t\t\tarch: \"iframe-static\",\n\t\t\t\t\tappKey: this.config.appKey,\n\t\t\t\t\tchannelType: this.channelType,\n\t\t\t\t},\n\t\t\t});\n\t\t} catch {\n\t\t\t// 性能上报失败不影响功能\n\t\t}\n\t}\n\n\tprivate createChatPanel(): ChatPanel {\n\t\treturn {\n\t\t\tsendMessage: async (data) => {\n\t\t\t\tawait this.messageBridge.send(\"sendMessage\", data);\n\t\t\t},\n\t\t\tclear: async () => {\n\t\t\t\tawait this.messageBridge.send(\"clear\");\n\t\t\t},\n\t\t\tcancelMessage: async (messageItem) => {\n\t\t\t\tawait this.messageBridge.send(\"cancelMessage\", messageItem);\n\t\t\t},\n\t\t\tclearAndStop: async () => {\n\t\t\t\tawait this.messageBridge.send(\"clearAndStop\");\n\t\t\t},\n\t\t\tupdateWelcomeMessage: async () => {\n\t\t\t\tawait this.messageBridge.send(\"updateWelcomeMessage\");\n\t\t\t},\n\t\t\tupdateConfig: async (config) => {\n\t\t\t\tawait this.messageBridge.send(\"updateConfig\", config);\n\t\t\t},\n\t\t\tobserveSkill: async (skillId, name, skillType) => {\n\t\t\t\tawait this.messageBridge.send(\"observeSkill\", {\n\t\t\t\t\tskillId,\n\t\t\t\t\tname,\n\t\t\t\t\tskillType,\n\t\t\t\t});\n\t\t\t},\n\t\t\tsetCurrentSkill: async (skill) => {\n\t\t\t\tawait this.messageBridge.send(\"setCurrentSkill\", skill);\n\t\t\t},\n\t\t\tdestroy: async () => {\n\t\t\t\tawait this.destroy();\n\t\t\t},\n\t\t};\n\t}\n}\n","const MOBILE_BREAKPOINT = 768;\n\ntype DeviceType = 'pc' | 'mobile';\ntype DeviceChangeCallback = (device: DeviceType) => void;\n\n/**\n * 设备类型自动检测器\n *\n * 使用 matchMedia + 768px 断点检测设备类型,与 miaoda useIsMobile 逻辑一致。\n * 检测在宿主页面(而非 iframe)中执行,结果通过 postMessage 推送给 iframe。\n */\nexport class DeviceDetector {\n private mediaQuery: MediaQueryList;\n private currentDevice: DeviceType;\n private callback: DeviceChangeCallback | null = null;\n private handleChange: (() => void) | null = null;\n\n constructor() {\n this.mediaQuery = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);\n this.currentDevice = window.innerWidth < MOBILE_BREAKPOINT ? 'mobile' : 'pc';\n }\n\n getDevice(): DeviceType {\n return this.currentDevice;\n }\n\n observe(callback: DeviceChangeCallback): void {\n this.callback = callback;\n this.handleChange = () => {\n const newDevice: DeviceType = window.innerWidth < MOBILE_BREAKPOINT ? 'mobile' : 'pc';\n if (newDevice !== this.currentDevice) {\n this.currentDevice = newDevice;\n this.callback?.(newDevice);\n }\n };\n this.mediaQuery.addEventListener('change', this.handleChange);\n }\n\n destroy(): void {\n if (this.handleChange) {\n this.mediaQuery.removeEventListener('change', this.handleChange);\n this.handleChange = null;\n }\n this.callback = null;\n }\n}\n","import { MESSAGE_TIMEOUT, ALLOWED_ORIGINS } from './constants';\nimport {\n MESSAGE_BIZ_ID,\n type IframeMessage,\n type IframeRequestMessage,\n type IframeResponseMessage,\n type IframeEventMessage,\n type IframeMessageType,\n} from './types/message';\nimport { slardar } from '@lark-apaas/internal-slardar';\n\ninterface PendingRequest {\n resolve: (value: unknown) => void;\n reject: (reason: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\n/**\n * MessageBridge handles postMessage communication between parent and iframe\n */\nexport class MessageBridge {\n private iframe: HTMLIFrameElement | null = null;\n private requestId = 0;\n private pendingRequests = new Map<number, PendingRequest>();\n private eventHandlers = new Map<string, ((data: unknown) => void)[]>();\n private targetOrigin: string;\n\n constructor(targetOrigin: string) {\n this.targetOrigin = new URL(targetOrigin).origin;\n this.handleMessage = this.handleMessage.bind(this);\n }\n\n /**\n * Attach to an iframe and start listening for messages\n */\n attach(iframe: HTMLIFrameElement): void {\n this.iframe = iframe;\n window.addEventListener('message', this.handleMessage);\n }\n\n /**\n * Detach from iframe and clean up\n */\n detach(): void {\n window.removeEventListener('message', this.handleMessage);\n this.iframe = null;\n // Clear all pending requests\n this.pendingRequests.forEach(({ reject }) => {\n reject(new Error('MessageBridge detached'));\n });\n this.pendingRequests.clear();\n }\n\n /**\n * Send a message to the iframe and wait for response\n */\n send<T = unknown>(type: IframeMessageType, data?: unknown): Promise<T> {\n return new Promise((resolve, reject) => {\n if (!this.iframe?.contentWindow) {\n reject(new Error('Iframe not attached'));\n return;\n }\n\n this.requestId += 1;\n const id = this.requestId;\n const message: IframeRequestMessage = {\n messageBizId: MESSAGE_BIZ_ID,\n id,\n type,\n data,\n timestamp: Date.now(),\n isRequest: true,\n };\n\n const timer = setTimeout(() => {\n this.pendingRequests.delete(id);\n const error = new Error(`Message timeout: ${type}`);\n slardar.captureException(error, { source: 'aily-web-sdk', module: 'message-bridge', messageType: type });\n reject(error);\n }, MESSAGE_TIMEOUT);\n\n this.pendingRequests.set(id, { resolve: resolve as (value: unknown) => void, reject, timer });\n\n this.iframe.contentWindow.postMessage(message, this.targetOrigin);\n });\n }\n\n /**\n * Register an event handler\n */\n onEvent(eventName: string, handler: (data: unknown) => void): void {\n const handlers = this.eventHandlers.get(eventName) || [];\n handlers.push(handler);\n this.eventHandlers.set(eventName, handlers);\n }\n\n /**\n * Remove an event handler\n */\n offEvent(eventName: string, handler: (data: unknown) => void): void {\n const handlers = this.eventHandlers.get(eventName) || [];\n const index = handlers.indexOf(handler);\n if (index > -1) {\n handlers.splice(index, 1);\n this.eventHandlers.set(eventName, handlers);\n }\n }\n\n private handleMessage(event: MessageEvent<IframeMessage>): void {\n // Validate origin\n if (!ALLOWED_ORIGINS.includes(event.origin)) {\n return;\n }\n\n const { data } = event;\n\n // Validate message format\n if (data?.messageBizId !== MESSAGE_BIZ_ID) {\n return;\n }\n\n // Handle response messages\n if (this.isResponseMessage(data)) {\n const pending = this.pendingRequests.get(data.id);\n if (pending) {\n clearTimeout(pending.timer);\n this.pendingRequests.delete(data.id);\n\n if (data.error) {\n const error = new Error(data.error.message);\n slardar.captureException(error, { source: 'aily-web-sdk', module: 'message-bridge', errorCode: data.error.code });\n pending.reject(error);\n } else {\n pending.resolve(data.data);\n }\n }\n }\n\n // Handle event messages\n if (this.isEventMessage(data)) {\n const handlers = this.eventHandlers.get(data.eventName) || [];\n handlers.forEach((handler) => {\n try {\n handler(data.data);\n } catch {\n // Ignore handler errors\n }\n });\n }\n }\n\n private isResponseMessage(data: IframeMessage): data is IframeResponseMessage {\n return 'isResponse' in data && data.isResponse === true;\n }\n\n private isEventMessage(data: IframeMessage): data is IframeEventMessage {\n return data.type === 'event';\n }\n}\n","import { PARENT_ORIGIN_QUERY_KEY, getAgentIframeBaseURL } from './constants';\nimport { MessageBridge } from './message-bridge';\n\nimport type {\n AgentSDKInitConfig,\n AgentSDKInstance,\n AgentSDKRuntimeCustomContext,\n} from './types/config';\nimport type {\n AgentReadyEventData,\n ParentContextMessageData,\n ParentContextResponseData,\n} from './types/message';\n\n/**\n * AgentIframeManager handles agent iframe creation and lifecycle.\n */\nexport class AgentIframeManager {\n private iframe: HTMLIFrameElement | null = null;\n private readonly messageBridge: MessageBridge;\n private readonly config: AgentSDKInitConfig;\n private readonly root: HTMLElement;\n private readonly runtimeCustomContext: AgentSDKRuntimeCustomContext | null;\n private readonly contextVersion: string;\n private initialHandshakeCompleted = false;\n\n constructor(root: HTMLElement, config: AgentSDKInitConfig) {\n this.root = root;\n this.config = config;\n this.runtimeCustomContext = this.resolveRuntimeCustomContext(config);\n this.contextVersion = this.createContextVersion();\n this.messageBridge = new MessageBridge(getAgentIframeBaseURL());\n }\n\n async init(): Promise<AgentSDKInstance> {\n this.iframe = document.createElement('iframe');\n this.iframe.src = this.buildIframeURL();\n this.iframe.style.width = '100%';\n this.iframe.style.height = '100%';\n this.iframe.style.border = 'none';\n this.iframe.allow = 'microphone; clipboard-write';\n\n const readyPromise = this.waitForReady();\n this.messageBridge.onEvent('ready', this.handleSubsequentReady);\n this.messageBridge.attach(this.iframe);\n this.root.appendChild(this.iframe);\n\n try {\n const readyData = await readyPromise;\n await this.sendParentContext(readyData);\n this.initialHandshakeCompleted = true;\n } catch (error) {\n this.cleanupAfterFailedInit();\n throw error;\n }\n\n return this.createAgentInstance();\n }\n\n async destroy(): Promise<void> {\n this.messageBridge.offEvent('ready', this.handleSubsequentReady);\n\n try {\n await this.messageBridge.send('destroy');\n } catch {\n // Ignore errors during destroy.\n }\n\n this.messageBridge.detach();\n this.removeIframe();\n this.initialHandshakeCompleted = false;\n }\n\n private buildIframeURL(): string {\n const baseURL = getAgentIframeBaseURL();\n const params = new URLSearchParams({\n channelToken: this.config.channelToken,\n [PARENT_ORIGIN_QUERY_KEY]: window.location.origin,\n });\n\n return `${baseURL}?${params.toString()}`;\n }\n\n private buildParentContext(): ParentContextMessageData {\n const parentContext: ParentContextMessageData = {\n parentOrigin: window.location.origin,\n };\n\n return parentContext;\n }\n\n private waitForReady(): Promise<AgentReadyEventData | undefined> {\n return new Promise((resolve, reject) => {\n const handleReady = (data: unknown) => {\n clearTimeout(timeout);\n this.messageBridge.offEvent('ready', handleReady);\n resolve(this.parseReadyEventData(data));\n };\n\n const timeout = setTimeout(() => {\n this.messageBridge.offEvent('ready', handleReady);\n reject(new Error('Iframe ready timeout'));\n }, 30000);\n\n this.messageBridge.onEvent('ready', handleReady);\n });\n }\n\n private readonly handleSubsequentReady = (data: unknown): void => {\n if (!this.initialHandshakeCompleted) {\n return;\n }\n\n void this.sendParentContext(this.parseReadyEventData(data)).catch(\n () => undefined\n );\n };\n\n private async sendParentContext(\n readyData?: AgentReadyEventData\n ): Promise<void> {\n const payload = this.buildParentContextForReady(readyData);\n const response = await this.messageBridge.send<ParentContextResponseData>(\n 'initParentContext',\n payload\n );\n\n if (!this.runtimeCustomContext) {\n return;\n }\n\n if (response?.accepted !== true) {\n throw new Error('Iframe rejected initParentContext custom context');\n }\n\n if (\n payload.iframeSessionId &&\n response.iframeSessionId &&\n response.iframeSessionId !== payload.iframeSessionId\n ) {\n throw new Error('Iframe returned mismatched iframeSessionId');\n }\n\n if (\n payload.contextVersion &&\n response.contextVersion &&\n response.contextVersion !== payload.contextVersion\n ) {\n throw new Error('Iframe returned mismatched contextVersion');\n }\n }\n\n private buildParentContextForReady(\n readyData?: AgentReadyEventData\n ): ParentContextMessageData {\n const parentContext = this.buildParentContext();\n\n if (!this.runtimeCustomContext) {\n return parentContext;\n }\n\n this.assertReadySupportsRuntimeContext(readyData);\n\n return {\n ...parentContext,\n protocolVersion: 2,\n iframeSessionId: readyData.iframeSessionId,\n contextVersion: this.contextVersion,\n runtimeCustomContext: this.runtimeCustomContext,\n };\n }\n\n private assertReadySupportsRuntimeContext(\n readyData?: AgentReadyEventData\n ): asserts readyData is AgentReadyEventData & {\n protocolVersion: 2;\n iframeSessionId: string;\n needsContext: true;\n } {\n if (\n readyData?.protocolVersion !== 2 ||\n !readyData.iframeSessionId ||\n readyData.needsContext !== true\n ) {\n throw new Error(\n 'Current iframe version does not support custom context initParentContext protocol'\n );\n }\n }\n\n private parseReadyEventData(data: unknown): AgentReadyEventData | undefined {\n if (!this.isRecord(data)) {\n return undefined;\n }\n\n return data as AgentReadyEventData;\n }\n\n private resolveRuntimeCustomContext(\n config: AgentSDKInitConfig\n ): AgentSDKRuntimeCustomContext | null {\n if (\n config.customParams !== undefined &&\n config.customParamsToken !== undefined\n ) {\n throw new Error(\n 'customParams and customParamsToken cannot be used together'\n );\n }\n\n if (config.customParamsToken !== undefined) {\n const token = config.customParamsToken.trim();\n if (!token) {\n throw new Error('customParamsToken cannot be empty');\n }\n\n return { customParamsToken: token };\n }\n\n if (config.customParams === undefined) {\n return null;\n }\n\n if (!this.isRecord(config.customParams)) {\n throw new Error('customParams must be an object');\n }\n\n for (const [key, entry] of Object.entries(config.customParams)) {\n if (\n !this.isRecord(entry) ||\n !('value' in entry) ||\n entry.value === undefined\n ) {\n throw new Error(`customParams.${key} must include value`);\n }\n\n if (\n 'desc' in entry &&\n entry.desc !== undefined &&\n typeof entry.desc !== 'string'\n ) {\n throw new Error(`customParams.${key}.desc must be a string`);\n }\n\n if (!this.isValidCustomParamValue(entry.value)) {\n throw new Error(`customParams.${key}.value has invalid type`);\n }\n }\n\n return { customParams: config.customParams };\n }\n\n private isValidCustomParamValue(value: unknown): boolean {\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return true;\n }\n\n if (Array.isArray(value)) {\n return value.every(\n item =>\n typeof item === 'string' ||\n typeof item === 'number' ||\n typeof item === 'boolean' ||\n this.isRecord(item)\n );\n }\n\n return this.isRecord(value);\n }\n\n private isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n }\n\n private createContextVersion(): string {\n return `ctx-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n private cleanupAfterFailedInit(): void {\n this.messageBridge.offEvent('ready', this.handleSubsequentReady);\n this.messageBridge.detach();\n this.removeIframe();\n }\n\n private removeIframe(): void {\n if (this.iframe?.parentNode) {\n this.iframe.parentNode.removeChild(this.iframe);\n }\n\n this.iframe = null;\n }\n\n private createAgentInstance(): AgentSDKInstance {\n return {\n destroy: async () => {\n await this.destroy();\n },\n };\n }\n}\n"],"mappings":"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","names":["MESSAGE_BIZ_ID","PARENT_ORIGIN_QUERY_KEY","IFRAME_ORIGIN","production","staging","boe","development","CHAT_IFRAME_PATH","AGENT_IFRAME_PATH","IFRAME_BASE_URL","AGENT_IFRAME_BASE_URL","isIframeEnv","env","Boolean","resolveDebugIframeEnv","window","undefined","debugIframeEnv","__DEBUG__","ailyWebSdk","iframeEnv","resolveIframeEnv","hostname","location","includes","getIframeBaseURL","getAgentIframeBaseURL","MESSAGE_TIMEOUT","DEFAULT_CHANNEL_TYPE","DEFAULT_ANONYMOUS_CHANNEL_TYPE","ALLOWED_ORIGINS","import_internal_slardar","MOBILE_BREAKPOINT","DeviceDetector","mediaQuery","currentDevice","callback","handleChange","window","matchMedia","innerWidth","getDevice","observe","newDevice","addEventListener","destroy","removeEventListener","MessageBridge","targetOrigin","iframe","requestId","pendingRequests","Map","eventHandlers","URL","origin","handleMessage","bind","attach","window","addEventListener","detach","removeEventListener","forEach","reject","Error","clear","send","type","data","Promise","resolve","contentWindow","id","message","messageBizId","MESSAGE_BIZ_ID","timestamp","Date","now","isRequest","timer","setTimeout","delete","error","slardar","captureException","source","module","messageType","MESSAGE_TIMEOUT","set","postMessage","onEvent","eventName","handler","handlers","get","push","offEvent","index","indexOf","splice","event","ALLOWED_ORIGINS","includes","isResponseMessage","pending","clearTimeout","errorCode","code","isEventMessage","isResponse","IframeManager","root","config","iframe","messageBridge","channelType","deviceDetector","defaultChannel","anonymous","DEFAULT_ANONYMOUS_CHANNEL_TYPE","DEFAULT_CHANNEL_TYPE","common","MessageBridge","getIframeBaseURL","init","initStart","performance","now","device","DeviceDetector","getDevice","document","createElement","src","buildIframeURL","style","width","height","border","allow","appendChild","attach","setupEventHandlers","observe","newDevice","send","waitForReady","reportInitMetrics","createChatPanel","destroy","detach","parentNode","removeChild","baseURL","events","_events","_anonymous","configWithoutEvents","editorConfig","editor","skill","type","builtinType","iframeConfig","resourceType","configBase64","btoa","encodeURIComponent","JSON","stringify","params","URLSearchParams","appKey","toString","Promise","resolve","reject","timeout","setTimeout","error","Error","slardar","captureException","source","module","checkMessage","event","data","messageBizId","MESSAGE_BIZ_ID","eventName","clearTimeout","window","removeEventListener","addEventListener","onReady","onEvent","onError","msg","message","onMessage","onInited","onInitedWithWelcome","onClose","cost","sendEvent","name","metrics","categories","arch","sendMessage","clear","cancelMessage","messageItem","clearAndStop","updateWelcomeMessage","updateConfig","observeSkill","skillId","skillType","setCurrentSkill","AgentIframeManager","root","config","iframe","messageBridge","runtimeCustomContext","contextVersion","initialHandshakeCompleted","handleSubsequentReady","data","sendParentContext","parseReadyEventData","catch","undefined","resolveRuntimeCustomContext","createContextVersion","MessageBridge","getAgentIframeBaseURL","init","document","createElement","src","buildIframeURL","style","width","height","border","allow","readyPromise","waitForReady","onEvent","attach","appendChild","readyData","error","cleanupAfterFailedInit","createAgentInstance","destroy","offEvent","send","detach","removeIframe","baseURL","params","URLSearchParams","channelToken","PARENT_ORIGIN_QUERY_KEY","window","location","origin","toString","buildParentContext","parentContext","parentOrigin","Promise","resolve","reject","handleReady","clearTimeout","timeout","setTimeout","Error","payload","buildParentContextForReady","response","accepted","iframeSessionId","assertReadySupportsRuntimeContext","protocolVersion","needsContext","isRecord","customParams","customParamsToken","token","trim","key","entry","Object","entries","value","desc","isValidCustomParamValue","Array","isArray","every","item","Date","now","Math","random","slice","parentNode","removeChild","initAilyChat","root","config","manager","IframeManager","init","initAgentChat","AgentIframeManager"]}
package/dist/index.d.cts CHANGED
@@ -96,7 +96,7 @@ interface WebSDKConfig {
96
96
  /** User identifier */
97
97
  uuid?: string;
98
98
  /** Device type */
99
- device?: "pc" | "mobile";
99
+ device?: 'pc' | 'mobile';
100
100
  /**
101
101
  * Enable anonymous mode (skips login check). Default: false
102
102
  * 非匿名模式下,iframe 内自行完成飞书登录(用户在 iframe 中独立登录),
@@ -112,8 +112,25 @@ interface WebSDKConfig {
112
112
  /** Event callbacks */
113
113
  events?: WebSDKEvents;
114
114
  }
115
+ type CustomParamPrimitive = string | number | boolean;
116
+ type CustomParamObject = Record<string, unknown>;
117
+ type CustomParamValue = CustomParamPrimitive | CustomParamObject | Array<CustomParamPrimitive | CustomParamObject>;
118
+ interface CustomParamEntry {
119
+ value: CustomParamValue;
120
+ desc?: string;
121
+ }
122
+ type CustomParams = Record<string, CustomParamEntry>;
123
+ type AgentSDKRuntimeCustomContext = {
124
+ customParams: CustomParams;
125
+ customParamsToken?: never;
126
+ } | {
127
+ customParams?: never;
128
+ customParamsToken: string;
129
+ };
115
130
  interface AgentSDKInitConfig {
116
131
  channelToken: string;
132
+ customParams?: CustomParams;
133
+ customParamsToken?: string;
117
134
  }
118
135
  /**
119
136
  * Chat panel control interface
@@ -137,7 +154,7 @@ interface ChatPanel {
137
154
  /** Update panel config */
138
155
  updateConfig: (config: unknown) => Promise<void>;
139
156
  /** Observe a skill */
140
- observeSkill: (skillId: string, name: string, skillType: "qna" | "bi" | "dataCreate") => Promise<void>;
157
+ observeSkill: (skillId: string, name: string, skillType: 'qna' | 'bi' | 'dataCreate') => Promise<void>;
141
158
  /** Set current skill */
142
159
  setCurrentSkill: (skill: {
143
160
  id: string;
@@ -232,4 +249,4 @@ declare function initAilyChat(root: HTMLElement, config: WebSDKConfig): Promise<
232
249
  */
233
250
  declare function initAgentChat(root: HTMLElement, config: AgentSDKInitConfig): Promise<AgentSDKInstance>;
234
251
 
235
- export { AGENT_IFRAME_BASE_URL, type AgentSDKInitConfig, type AgentSDKInstance, type ChatPanel, DEFAULT_ANONYMOUS_CHANNEL_TYPE, DEFAULT_CHANNEL_TYPE, IFRAME_BASE_URL, type IframeEventMessage, type IframeMessage, type IframeMessageType, type IframeRequestMessage, type IframeResponseMessage, MESSAGE_TIMEOUT, type WebSDKCommonConfig, type WebSDKConfig, type WebSDKConversionConfig, type WebSDKEditorConfig, type WebSDKEvents, type WebSDKSkillInfo, getAgentIframeBaseURL, getIframeBaseURL, initAgentChat, initAilyChat };
252
+ export { AGENT_IFRAME_BASE_URL, type AgentSDKInitConfig, type AgentSDKInstance, type AgentSDKRuntimeCustomContext, type ChatPanel, type CustomParamEntry, type CustomParams, DEFAULT_ANONYMOUS_CHANNEL_TYPE, DEFAULT_CHANNEL_TYPE, IFRAME_BASE_URL, type IframeEventMessage, type IframeMessage, type IframeMessageType, type IframeRequestMessage, type IframeResponseMessage, MESSAGE_TIMEOUT, type WebSDKCommonConfig, type WebSDKConfig, type WebSDKConversionConfig, type WebSDKEditorConfig, type WebSDKEvents, type WebSDKSkillInfo, getAgentIframeBaseURL, getIframeBaseURL, initAgentChat, initAilyChat };
package/dist/index.d.ts CHANGED
@@ -96,7 +96,7 @@ interface WebSDKConfig {
96
96
  /** User identifier */
97
97
  uuid?: string;
98
98
  /** Device type */
99
- device?: "pc" | "mobile";
99
+ device?: 'pc' | 'mobile';
100
100
  /**
101
101
  * Enable anonymous mode (skips login check). Default: false
102
102
  * 非匿名模式下,iframe 内自行完成飞书登录(用户在 iframe 中独立登录),
@@ -112,8 +112,25 @@ interface WebSDKConfig {
112
112
  /** Event callbacks */
113
113
  events?: WebSDKEvents;
114
114
  }
115
+ type CustomParamPrimitive = string | number | boolean;
116
+ type CustomParamObject = Record<string, unknown>;
117
+ type CustomParamValue = CustomParamPrimitive | CustomParamObject | Array<CustomParamPrimitive | CustomParamObject>;
118
+ interface CustomParamEntry {
119
+ value: CustomParamValue;
120
+ desc?: string;
121
+ }
122
+ type CustomParams = Record<string, CustomParamEntry>;
123
+ type AgentSDKRuntimeCustomContext = {
124
+ customParams: CustomParams;
125
+ customParamsToken?: never;
126
+ } | {
127
+ customParams?: never;
128
+ customParamsToken: string;
129
+ };
115
130
  interface AgentSDKInitConfig {
116
131
  channelToken: string;
132
+ customParams?: CustomParams;
133
+ customParamsToken?: string;
117
134
  }
118
135
  /**
119
136
  * Chat panel control interface
@@ -137,7 +154,7 @@ interface ChatPanel {
137
154
  /** Update panel config */
138
155
  updateConfig: (config: unknown) => Promise<void>;
139
156
  /** Observe a skill */
140
- observeSkill: (skillId: string, name: string, skillType: "qna" | "bi" | "dataCreate") => Promise<void>;
157
+ observeSkill: (skillId: string, name: string, skillType: 'qna' | 'bi' | 'dataCreate') => Promise<void>;
141
158
  /** Set current skill */
142
159
  setCurrentSkill: (skill: {
143
160
  id: string;
@@ -232,4 +249,4 @@ declare function initAilyChat(root: HTMLElement, config: WebSDKConfig): Promise<
232
249
  */
233
250
  declare function initAgentChat(root: HTMLElement, config: AgentSDKInitConfig): Promise<AgentSDKInstance>;
234
251
 
235
- export { AGENT_IFRAME_BASE_URL, type AgentSDKInitConfig, type AgentSDKInstance, type ChatPanel, DEFAULT_ANONYMOUS_CHANNEL_TYPE, DEFAULT_CHANNEL_TYPE, IFRAME_BASE_URL, type IframeEventMessage, type IframeMessage, type IframeMessageType, type IframeRequestMessage, type IframeResponseMessage, MESSAGE_TIMEOUT, type WebSDKCommonConfig, type WebSDKConfig, type WebSDKConversionConfig, type WebSDKEditorConfig, type WebSDKEvents, type WebSDKSkillInfo, getAgentIframeBaseURL, getIframeBaseURL, initAgentChat, initAilyChat };
252
+ export { AGENT_IFRAME_BASE_URL, type AgentSDKInitConfig, type AgentSDKInstance, type AgentSDKRuntimeCustomContext, type ChatPanel, type CustomParamEntry, type CustomParams, DEFAULT_ANONYMOUS_CHANNEL_TYPE, DEFAULT_CHANNEL_TYPE, IFRAME_BASE_URL, type IframeEventMessage, type IframeMessage, type IframeMessageType, type IframeRequestMessage, type IframeResponseMessage, MESSAGE_TIMEOUT, type WebSDKCommonConfig, type WebSDKConfig, type WebSDKConversionConfig, type WebSDKEditorConfig, type WebSDKEvents, type WebSDKSkillInfo, getAgentIframeBaseURL, getIframeBaseURL, initAgentChat, initAilyChat };
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ var IFRAME_ORIGIN = {
10
10
  production: "https://aily.feishu.cn",
11
11
  staging: "https://aily.feishu-pre.cn",
12
12
  boe: "https://aily.feishu-boe.cn",
13
- development: "http://localhost:8080"
13
+ development: "http://localhost:3000"
14
14
  };
15
15
  var CHAT_IFRAME_PATH = "/cui";
16
16
  var AGENT_IFRAME_PATH = "/custom_agent/cui";
@@ -455,8 +455,19 @@ var _AgentIframeManager = class _AgentIframeManager {
455
455
  __publicField(this, "messageBridge");
456
456
  __publicField(this, "config");
457
457
  __publicField(this, "root");
458
+ __publicField(this, "runtimeCustomContext");
459
+ __publicField(this, "contextVersion");
460
+ __publicField(this, "initialHandshakeCompleted", false);
461
+ __publicField(this, "handleSubsequentReady", /* @__PURE__ */ __name((data) => {
462
+ if (!this.initialHandshakeCompleted) {
463
+ return;
464
+ }
465
+ void this.sendParentContext(this.parseReadyEventData(data)).catch(() => void 0);
466
+ }, "handleSubsequentReady"));
458
467
  this.root = root;
459
468
  this.config = config;
469
+ this.runtimeCustomContext = this.resolveRuntimeCustomContext(config);
470
+ this.contextVersion = this.createContextVersion();
460
471
  this.messageBridge = new MessageBridge(getAgentIframeBaseURL());
461
472
  }
462
473
  async init() {
@@ -466,22 +477,29 @@ var _AgentIframeManager = class _AgentIframeManager {
466
477
  this.iframe.style.height = "100%";
467
478
  this.iframe.style.border = "none";
468
479
  this.iframe.allow = "microphone; clipboard-write";
469
- this.root.appendChild(this.iframe);
480
+ const readyPromise = this.waitForReady();
481
+ this.messageBridge.onEvent("ready", this.handleSubsequentReady);
470
482
  this.messageBridge.attach(this.iframe);
471
- await this.waitForReady();
472
- await this.messageBridge.send("initParentContext", this.buildParentContext());
483
+ this.root.appendChild(this.iframe);
484
+ try {
485
+ const readyData = await readyPromise;
486
+ await this.sendParentContext(readyData);
487
+ this.initialHandshakeCompleted = true;
488
+ } catch (error) {
489
+ this.cleanupAfterFailedInit();
490
+ throw error;
491
+ }
473
492
  return this.createAgentInstance();
474
493
  }
475
494
  async destroy() {
495
+ this.messageBridge.offEvent("ready", this.handleSubsequentReady);
476
496
  try {
477
497
  await this.messageBridge.send("destroy");
478
498
  } catch {
479
499
  }
480
500
  this.messageBridge.detach();
481
- if (this.iframe?.parentNode) {
482
- this.iframe.parentNode.removeChild(this.iframe);
483
- }
484
- this.iframe = null;
501
+ this.removeIframe();
502
+ this.initialHandshakeCompleted = false;
485
503
  }
486
504
  buildIframeURL() {
487
505
  const baseURL = getAgentIframeBaseURL();
@@ -492,26 +510,126 @@ var _AgentIframeManager = class _AgentIframeManager {
492
510
  return `${baseURL}?${params.toString()}`;
493
511
  }
494
512
  buildParentContext() {
495
- return {
513
+ const parentContext = {
496
514
  parentOrigin: window.location.origin
497
515
  };
516
+ return parentContext;
498
517
  }
499
518
  waitForReady() {
500
519
  return new Promise((resolve, reject) => {
520
+ const handleReady = /* @__PURE__ */ __name((data) => {
521
+ clearTimeout(timeout);
522
+ this.messageBridge.offEvent("ready", handleReady);
523
+ resolve(this.parseReadyEventData(data));
524
+ }, "handleReady");
501
525
  const timeout = setTimeout(() => {
502
- window.removeEventListener("message", checkMessage);
526
+ this.messageBridge.offEvent("ready", handleReady);
503
527
  reject(new Error("Iframe ready timeout"));
504
528
  }, 3e4);
505
- const checkMessage = /* @__PURE__ */ __name((event) => {
506
- if (event.data?.messageBizId === MESSAGE_BIZ_ID && event.data?.type === "event" && event.data?.eventName === "ready") {
507
- clearTimeout(timeout);
508
- window.removeEventListener("message", checkMessage);
509
- resolve();
510
- }
511
- }, "checkMessage");
512
- window.addEventListener("message", checkMessage);
529
+ this.messageBridge.onEvent("ready", handleReady);
513
530
  });
514
531
  }
532
+ async sendParentContext(readyData) {
533
+ const payload = this.buildParentContextForReady(readyData);
534
+ const response = await this.messageBridge.send("initParentContext", payload);
535
+ if (!this.runtimeCustomContext) {
536
+ return;
537
+ }
538
+ if (response?.accepted !== true) {
539
+ throw new Error("Iframe rejected initParentContext custom context");
540
+ }
541
+ if (payload.iframeSessionId && response.iframeSessionId && response.iframeSessionId !== payload.iframeSessionId) {
542
+ throw new Error("Iframe returned mismatched iframeSessionId");
543
+ }
544
+ if (payload.contextVersion && response.contextVersion && response.contextVersion !== payload.contextVersion) {
545
+ throw new Error("Iframe returned mismatched contextVersion");
546
+ }
547
+ }
548
+ buildParentContextForReady(readyData) {
549
+ const parentContext = this.buildParentContext();
550
+ if (!this.runtimeCustomContext) {
551
+ return parentContext;
552
+ }
553
+ this.assertReadySupportsRuntimeContext(readyData);
554
+ return {
555
+ ...parentContext,
556
+ protocolVersion: 2,
557
+ iframeSessionId: readyData.iframeSessionId,
558
+ contextVersion: this.contextVersion,
559
+ runtimeCustomContext: this.runtimeCustomContext
560
+ };
561
+ }
562
+ assertReadySupportsRuntimeContext(readyData) {
563
+ if (readyData?.protocolVersion !== 2 || !readyData.iframeSessionId || readyData.needsContext !== true) {
564
+ throw new Error("Current iframe version does not support custom context initParentContext protocol");
565
+ }
566
+ }
567
+ parseReadyEventData(data) {
568
+ if (!this.isRecord(data)) {
569
+ return void 0;
570
+ }
571
+ return data;
572
+ }
573
+ resolveRuntimeCustomContext(config) {
574
+ if (config.customParams !== void 0 && config.customParamsToken !== void 0) {
575
+ throw new Error("customParams and customParamsToken cannot be used together");
576
+ }
577
+ if (config.customParamsToken !== void 0) {
578
+ const token = config.customParamsToken.trim();
579
+ if (!token) {
580
+ throw new Error("customParamsToken cannot be empty");
581
+ }
582
+ return {
583
+ customParamsToken: token
584
+ };
585
+ }
586
+ if (config.customParams === void 0) {
587
+ return null;
588
+ }
589
+ if (!this.isRecord(config.customParams)) {
590
+ throw new Error("customParams must be an object");
591
+ }
592
+ for (const [key, entry] of Object.entries(config.customParams)) {
593
+ if (!this.isRecord(entry) || !("value" in entry) || entry.value === void 0) {
594
+ throw new Error(`customParams.${key} must include value`);
595
+ }
596
+ if ("desc" in entry && entry.desc !== void 0 && typeof entry.desc !== "string") {
597
+ throw new Error(`customParams.${key}.desc must be a string`);
598
+ }
599
+ if (!this.isValidCustomParamValue(entry.value)) {
600
+ throw new Error(`customParams.${key}.value has invalid type`);
601
+ }
602
+ }
603
+ return {
604
+ customParams: config.customParams
605
+ };
606
+ }
607
+ isValidCustomParamValue(value) {
608
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
609
+ return true;
610
+ }
611
+ if (Array.isArray(value)) {
612
+ return value.every((item) => typeof item === "string" || typeof item === "number" || typeof item === "boolean" || this.isRecord(item));
613
+ }
614
+ return this.isRecord(value);
615
+ }
616
+ isRecord(value) {
617
+ return typeof value === "object" && value !== null && !Array.isArray(value);
618
+ }
619
+ createContextVersion() {
620
+ return `ctx-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
621
+ }
622
+ cleanupAfterFailedInit() {
623
+ this.messageBridge.offEvent("ready", this.handleSubsequentReady);
624
+ this.messageBridge.detach();
625
+ this.removeIframe();
626
+ }
627
+ removeIframe() {
628
+ if (this.iframe?.parentNode) {
629
+ this.iframe.parentNode.removeChild(this.iframe);
630
+ }
631
+ this.iframe = null;
632
+ }
515
633
  createAgentInstance() {
516
634
  return {
517
635
  destroy: /* @__PURE__ */ __name(async () => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/iframe-manager.ts","../src/device-detector.ts","../src/message-bridge.ts","../src/agent-iframe-manager.ts","../src/index.ts"],"sourcesContent":["/**\n * Constants for Aily Web SDK\n */\n\n/** Message business ID for postMessage identification */\nexport const MESSAGE_BIZ_ID = 'cui-sdk-message' as const;\nexport const PARENT_ORIGIN_QUERY_KEY = '__parentOrigin' as const;\n\n/** Iframe origins by environment */\nexport const IFRAME_ORIGIN: Record<string, string> = {\n production: 'https://aily.feishu.cn',\n staging: 'https://aily.feishu-pre.cn',\n boe: 'https://aily.feishu-boe.cn',\n development: 'http://localhost:8080',\n};\n\n/** Page paths for iframe apps */\nexport const CHAT_IFRAME_PATH = '/cui' as const;\nexport const AGENT_IFRAME_PATH = '/custom_agent/cui' as const;\n\n/** Chat iframe base URLs by environment */\nexport const IFRAME_BASE_URL: Record<string, string> = {\n production: `${IFRAME_ORIGIN.production}${CHAT_IFRAME_PATH}`,\n staging: `${IFRAME_ORIGIN.staging}${CHAT_IFRAME_PATH}`,\n boe: `${IFRAME_ORIGIN.boe}${CHAT_IFRAME_PATH}`,\n development: `${IFRAME_ORIGIN.development}${CHAT_IFRAME_PATH}`,\n};\n\n/** Agent iframe base URLs by environment */\nexport const AGENT_IFRAME_BASE_URL: Record<string, string> = {\n production: `${IFRAME_ORIGIN.production}${AGENT_IFRAME_PATH}`,\n staging: `${IFRAME_ORIGIN.staging}${AGENT_IFRAME_PATH}`,\n boe: `${IFRAME_ORIGIN.boe}${AGENT_IFRAME_PATH}`,\n development: `${IFRAME_ORIGIN.development}${AGENT_IFRAME_PATH}`,\n};\n\ntype IframeEnv = keyof typeof IFRAME_BASE_URL;\n\ninterface AilyWebSdkDebugConfig {\n iframeEnv?: string;\n}\n\ndeclare global {\n interface Window {\n __DEBUG__?: {\n ailyWebSdk?: AilyWebSdkDebugConfig;\n [key: string]: unknown;\n };\n }\n}\n\nfunction isIframeEnv(env?: string): env is IframeEnv {\n return Boolean(env && env in IFRAME_BASE_URL);\n}\n\nfunction resolveDebugIframeEnv(): IframeEnv | undefined {\n if (typeof window === 'undefined') {\n return undefined;\n }\n\n const debugIframeEnv = window.__DEBUG__?.ailyWebSdk?.iframeEnv;\n return isIframeEnv(debugIframeEnv) ? debugIframeEnv : undefined;\n}\n\n/**\n * Get iframe base URL based on environment\n */\nfunction resolveIframeEnv(env?: string): IframeEnv {\n if (isIframeEnv(env)) {\n return env;\n }\n\n const debugIframeEnv = resolveDebugIframeEnv();\n if (debugIframeEnv) {\n return debugIframeEnv;\n }\n\n // Auto-detect based on hostname\n // MiaoDa 宿主域名: miaoda.feishu[-env].cn, *.aiforce[-env][-preview].bytedance.net, *.force-pre.feishuapp.net, *.fsapp.kundou.cn, *.aiforce.run, *.aiforce.cloud\n const hostname =\n typeof window !== 'undefined' ? window.location.hostname : '';\n\n if (hostname.includes('aiforce-boe')) {\n return 'boe';\n }\n if (\n hostname.includes('aiforce-pre') ||\n hostname.includes('force-pre.feishuapp.net') ||\n hostname.includes('fsapp.kundou.cn')\n ) {\n return 'staging';\n }\n\n return 'production';\n}\n\nexport function getIframeBaseURL(env?: string): string {\n return IFRAME_BASE_URL[resolveIframeEnv(env)];\n}\n\n/**\n * Get agent iframe base URL based on environment\n */\nexport function getAgentIframeBaseURL(env?: string): string {\n return AGENT_IFRAME_BASE_URL[resolveIframeEnv(env)];\n}\n\n/** Timeout for postMessage requests (30 seconds) */\nexport const MESSAGE_TIMEOUT = 30 * 1000;\n\n/** Miaoda 渠道标识默认值(用户可通过 config.common.channelType 覆盖) */\nexport const DEFAULT_CHANNEL_TYPE = 'MIAODA_CUI_SDK';\nexport const DEFAULT_ANONYMOUS_CHANNEL_TYPE = 'MIAODA_ANONYMOUS_CUI_SDK';\n\n/** Allowed origins for postMessage (cui-iframe 的 origin) */\nexport const ALLOWED_ORIGINS = [\n IFRAME_ORIGIN.production,\n IFRAME_ORIGIN.staging,\n IFRAME_ORIGIN.boe,\n 'http://localhost:3000',\n 'http://localhost:5173',\n IFRAME_ORIGIN.development,\n];\n","import {\n\tDEFAULT_ANONYMOUS_CHANNEL_TYPE,\n\tDEFAULT_CHANNEL_TYPE,\n\tgetIframeBaseURL,\n\tMESSAGE_BIZ_ID,\n} from \"./constants\";\nimport { slardar } from \"@lark-apaas/internal-slardar\";\nimport { DeviceDetector } from \"./device-detector\";\nimport { MessageBridge } from \"./message-bridge\";\n\nimport type { ChatPanel, WebSDKConfig } from \"./types/config\";\n\n/**\n * IframeManager handles iframe creation and lifecycle\n *\n * iframe 采用自初始化模式:配置通过 URL hash 传入,iframe 加载后自行解析并渲染,\n * 与旧版 copilot iframe 的行为保持一致。宿主通过 postMessage 进行后续操作。\n */\nexport class IframeManager {\n\tprivate iframe: HTMLIFrameElement | null = null;\n\tprivate messageBridge: MessageBridge;\n\tprivate config: WebSDKConfig;\n\tprivate channelType: string;\n\tprivate root: HTMLElement;\n\tprivate deviceDetector: DeviceDetector | null = null;\n\n\tconstructor(root: HTMLElement, config: WebSDKConfig) {\n\t\tthis.root = root;\n\t\tthis.config = config;\n\t\tconst defaultChannel = config.anonymous\n\t\t\t? DEFAULT_ANONYMOUS_CHANNEL_TYPE\n\t\t\t: DEFAULT_CHANNEL_TYPE;\n\t\tthis.channelType = config.common?.channelType || defaultChannel;\n\t\tthis.messageBridge = new MessageBridge(getIframeBaseURL());\n\t}\n\n\t/**\n\t * Initialize the iframe and establish communication\n\t * 配置通过 URL hash 编码传入 iframe,iframe 加载后自行初始化\n\t */\n\tasync init(): Promise<ChatPanel> {\n\t\tconst initStart = performance.now();\n\n\t\t// Auto-detect device if not explicitly provided\n\t\tif (!this.config.device) {\n\t\t\tthis.deviceDetector = new DeviceDetector();\n\t\t\tthis.config.device = this.deviceDetector.getDevice();\n\t\t}\n\n\t\t// Create iframe element\n\t\tthis.iframe = document.createElement(\"iframe\");\n\t\tthis.iframe.src = this.buildIframeURL();\n\t\tthis.iframe.style.width = \"100%\";\n\t\tthis.iframe.style.height = \"100%\";\n\t\tthis.iframe.style.border = \"none\";\n\t\tthis.iframe.allow = \"microphone; clipboard-write\";\n\n\t\t// Attach to DOM\n\t\tthis.root.appendChild(this.iframe);\n\n\t\t// Attach message bridge (开始监听消息)\n\t\tthis.messageBridge.attach(this.iframe);\n\n\t\t// Setup event handlers (在 iframe 初始化完成之前就开始监听,确保不丢失事件)\n\t\tthis.setupEventHandlers();\n\n\t\t// Listen for device changes and push updates to iframe\n\t\tif (this.deviceDetector) {\n\t\t\tthis.deviceDetector.observe((newDevice) => {\n\t\t\t\tthis.messageBridge.send(\"updateConfig\", { device: newDevice });\n\t\t\t});\n\t\t}\n\n\t\t// Wait for iframe to finish initialization (iframe 自行读取 URL 配置并渲染,完成后发送 ready 事件)\n\t\tawait this.waitForReady();\n\n\t\t// 上报 cui_init_total 耗时(iframe 创建 → init 完成)\n\t\tthis.reportInitMetrics(initStart);\n\n\t\t// Return ChatPanel interface\n\t\treturn this.createChatPanel();\n\t}\n\n\t/**\n\t * Destroy the iframe and cleanup\n\t */\n\tasync destroy(): Promise<void> {\n\t\ttry {\n\t\t\tawait this.messageBridge.send(\"destroy\");\n\t\t} catch {\n\t\t\t// Ignore errors during destroy\n\t\t}\n\n\t\tthis.messageBridge.detach();\n\n\t\tif (this.deviceDetector) {\n\t\t\tthis.deviceDetector.destroy();\n\t\t\tthis.deviceDetector = null;\n\t\t}\n\n\t\tif (this.iframe?.parentNode) {\n\t\t\tthis.iframe.parentNode.removeChild(this.iframe);\n\t\t}\n\n\t\tthis.iframe = null;\n\t}\n\n\t/**\n\t * 构建 iframe URL,将配置编码到 hash 中\n\t * 格式: {baseURL}#{params} 其中 config 为 base64(JSON.stringify(configWithoutEvents))\n\t *\n\t * 鉴权说明:SDK 不参与 token 获取/传递。iframe 自行处理飞书登录流程,\n\t * 允许用户在 iframe 中独立登录。匿名渠道跳过登录检查。\n\t */\n\tprivate buildIframeURL(): string {\n\t\tconst baseURL = getIframeBaseURL();\n\n\t\t// 移除 events(函数无法序列化)\n\t\tconst {\n\t\t\tevents: _events,\n\t\t\tanonymous: _anonymous,\n\t\t\t...configWithoutEvents\n\t\t} = this.config;\n\t\t// 注入 channelType/resourceType(SDK 内部控制,不暴露给消费者)\n\t\t// 补全 editor.skill 硬编码字段\n\t\tconst editorConfig = configWithoutEvents.editor?.skill\n\t\t\t? {\n\t\t\t\t\t...configWithoutEvents.editor,\n\t\t\t\t\tskill: {\n\t\t\t\t\t\ttype: \"custom\",\n\t\t\t\t\t\tbuiltinType: \"unspecified\",\n\t\t\t\t\t\t...configWithoutEvents.editor.skill,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: configWithoutEvents.editor;\n\n\t\tconst iframeConfig = {\n\t\t\t...configWithoutEvents,\n\t\t\tcommon: {\n\t\t\t\t...configWithoutEvents.common,\n\t\t\t\tchannelType: this.channelType,\n\t\t\t\tresourceType:\n\t\t\t\t\tconfigWithoutEvents.common?.resourceType || this.channelType,\n\t\t\t},\n\t\t\teditor: editorConfig,\n\t\t};\n\t\tconst configBase64 = btoa(encodeURIComponent(JSON.stringify(iframeConfig)));\n\n\t\tconst params = new URLSearchParams({\n\t\t\tappKey: this.config.appKey,\n\t\t\tconfig: encodeURIComponent(configBase64),\n\t\t});\n\n\t\treturn `${baseURL}#${params.toString()}`;\n\t}\n\n\t/**\n\t * 等待 iframe 自行初始化完成后发送 ready 事件\n\t */\n\tprivate waitForReady(): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\tconst error = new Error(\"Iframe ready timeout\");\n\t\t\t\tslardar.captureException(error, { source: 'aily-web-sdk', module: 'iframe-ready' });\n\t\t\t\treject(error);\n\t\t\t}, 30000);\n\n\t\t\tconst checkMessage = (event: MessageEvent) => {\n\t\t\t\tif (\n\t\t\t\t\tevent.data?.messageBizId === MESSAGE_BIZ_ID &&\n\t\t\t\t\tevent.data?.type === \"event\" &&\n\t\t\t\t\tevent.data?.eventName === \"ready\"\n\t\t\t\t) {\n\t\t\t\t\tclearTimeout(timeout);\n\t\t\t\t\twindow.removeEventListener(\"message\", checkMessage);\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\twindow.addEventListener(\"message\", checkMessage);\n\t\t});\n\t}\n\n\tprivate setupEventHandlers(): void {\n\t\tconst { events } = this.config;\n\t\tif (!events) return;\n\n\t\tif (events.onReady) {\n\t\t\tthis.messageBridge.onEvent(\"ready\", events.onReady);\n\t\t}\n\n\t\tif (events.onError) {\n\t\t\tthis.messageBridge.onEvent(\"error\", (data: unknown) => {\n\t\t\t\tconst msg = (data as { message?: string })?.message || \"Unknown error\";\n\t\t\t\tevents.onError?.(new Error(msg));\n\t\t\t});\n\t\t}\n\n\t\tif (events.onMessage) {\n\t\t\tthis.messageBridge.onEvent(\"onMessage\", events.onMessage);\n\t\t}\n\n\t\tif (events.onInited) {\n\t\t\tthis.messageBridge.onEvent(\n\t\t\t\t\"inited\",\n\t\t\t\tevents.onInited as (data: unknown) => void,\n\t\t\t);\n\t\t}\n\n\t\tif (events.onInitedWithWelcome) {\n\t\t\tthis.messageBridge.onEvent(\n\t\t\t\t\"initedWithWelcome\",\n\t\t\t\tevents.onInitedWithWelcome,\n\t\t\t);\n\t\t}\n\n\t\tif (events.onClose) {\n\t\t\tthis.messageBridge.onEvent(\"onClose\", events.onClose);\n\t\t}\n\t}\n\n\tprivate reportInitMetrics(initStart: number): void {\n\t\ttry {\n\t\t\tconst cost = performance.now() - initStart;\n\t\t\tslardar.sendEvent({\n\t\t\t\tname: \"cui_init_total\",\n\t\t\t\tmetrics: { cost },\n\t\t\t\tcategories: {\n\t\t\t\t\tarch: \"iframe-static\",\n\t\t\t\t\tappKey: this.config.appKey,\n\t\t\t\t\tchannelType: this.channelType,\n\t\t\t\t},\n\t\t\t});\n\t\t} catch {\n\t\t\t// 性能上报失败不影响功能\n\t\t}\n\t}\n\n\tprivate createChatPanel(): ChatPanel {\n\t\treturn {\n\t\t\tsendMessage: async (data) => {\n\t\t\t\tawait this.messageBridge.send(\"sendMessage\", data);\n\t\t\t},\n\t\t\tclear: async () => {\n\t\t\t\tawait this.messageBridge.send(\"clear\");\n\t\t\t},\n\t\t\tcancelMessage: async (messageItem) => {\n\t\t\t\tawait this.messageBridge.send(\"cancelMessage\", messageItem);\n\t\t\t},\n\t\t\tclearAndStop: async () => {\n\t\t\t\tawait this.messageBridge.send(\"clearAndStop\");\n\t\t\t},\n\t\t\tupdateWelcomeMessage: async () => {\n\t\t\t\tawait this.messageBridge.send(\"updateWelcomeMessage\");\n\t\t\t},\n\t\t\tupdateConfig: async (config) => {\n\t\t\t\tawait this.messageBridge.send(\"updateConfig\", config);\n\t\t\t},\n\t\t\tobserveSkill: async (skillId, name, skillType) => {\n\t\t\t\tawait this.messageBridge.send(\"observeSkill\", {\n\t\t\t\t\tskillId,\n\t\t\t\t\tname,\n\t\t\t\t\tskillType,\n\t\t\t\t});\n\t\t\t},\n\t\t\tsetCurrentSkill: async (skill) => {\n\t\t\t\tawait this.messageBridge.send(\"setCurrentSkill\", skill);\n\t\t\t},\n\t\t\tdestroy: async () => {\n\t\t\t\tawait this.destroy();\n\t\t\t},\n\t\t};\n\t}\n}\n","const MOBILE_BREAKPOINT = 768;\n\ntype DeviceType = 'pc' | 'mobile';\ntype DeviceChangeCallback = (device: DeviceType) => void;\n\n/**\n * 设备类型自动检测器\n *\n * 使用 matchMedia + 768px 断点检测设备类型,与 miaoda useIsMobile 逻辑一致。\n * 检测在宿主页面(而非 iframe)中执行,结果通过 postMessage 推送给 iframe。\n */\nexport class DeviceDetector {\n private mediaQuery: MediaQueryList;\n private currentDevice: DeviceType;\n private callback: DeviceChangeCallback | null = null;\n private handleChange: (() => void) | null = null;\n\n constructor() {\n this.mediaQuery = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);\n this.currentDevice = window.innerWidth < MOBILE_BREAKPOINT ? 'mobile' : 'pc';\n }\n\n getDevice(): DeviceType {\n return this.currentDevice;\n }\n\n observe(callback: DeviceChangeCallback): void {\n this.callback = callback;\n this.handleChange = () => {\n const newDevice: DeviceType = window.innerWidth < MOBILE_BREAKPOINT ? 'mobile' : 'pc';\n if (newDevice !== this.currentDevice) {\n this.currentDevice = newDevice;\n this.callback?.(newDevice);\n }\n };\n this.mediaQuery.addEventListener('change', this.handleChange);\n }\n\n destroy(): void {\n if (this.handleChange) {\n this.mediaQuery.removeEventListener('change', this.handleChange);\n this.handleChange = null;\n }\n this.callback = null;\n }\n}\n","import { MESSAGE_TIMEOUT, ALLOWED_ORIGINS } from './constants';\nimport {\n MESSAGE_BIZ_ID,\n type IframeMessage,\n type IframeRequestMessage,\n type IframeResponseMessage,\n type IframeEventMessage,\n type IframeMessageType,\n} from './types/message';\nimport { slardar } from '@lark-apaas/internal-slardar';\n\ninterface PendingRequest {\n resolve: (value: unknown) => void;\n reject: (reason: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\n/**\n * MessageBridge handles postMessage communication between parent and iframe\n */\nexport class MessageBridge {\n private iframe: HTMLIFrameElement | null = null;\n private requestId = 0;\n private pendingRequests = new Map<number, PendingRequest>();\n private eventHandlers = new Map<string, ((data: unknown) => void)[]>();\n private targetOrigin: string;\n\n constructor(targetOrigin: string) {\n this.targetOrigin = new URL(targetOrigin).origin;\n this.handleMessage = this.handleMessage.bind(this);\n }\n\n /**\n * Attach to an iframe and start listening for messages\n */\n attach(iframe: HTMLIFrameElement): void {\n this.iframe = iframe;\n window.addEventListener('message', this.handleMessage);\n }\n\n /**\n * Detach from iframe and clean up\n */\n detach(): void {\n window.removeEventListener('message', this.handleMessage);\n this.iframe = null;\n // Clear all pending requests\n this.pendingRequests.forEach(({ reject }) => {\n reject(new Error('MessageBridge detached'));\n });\n this.pendingRequests.clear();\n }\n\n /**\n * Send a message to the iframe and wait for response\n */\n send<T = unknown>(type: IframeMessageType, data?: unknown): Promise<T> {\n return new Promise((resolve, reject) => {\n if (!this.iframe?.contentWindow) {\n reject(new Error('Iframe not attached'));\n return;\n }\n\n this.requestId += 1;\n const id = this.requestId;\n const message: IframeRequestMessage = {\n messageBizId: MESSAGE_BIZ_ID,\n id,\n type,\n data,\n timestamp: Date.now(),\n isRequest: true,\n };\n\n const timer = setTimeout(() => {\n this.pendingRequests.delete(id);\n const error = new Error(`Message timeout: ${type}`);\n slardar.captureException(error, { source: 'aily-web-sdk', module: 'message-bridge', messageType: type });\n reject(error);\n }, MESSAGE_TIMEOUT);\n\n this.pendingRequests.set(id, { resolve: resolve as (value: unknown) => void, reject, timer });\n\n this.iframe.contentWindow.postMessage(message, this.targetOrigin);\n });\n }\n\n /**\n * Register an event handler\n */\n onEvent(eventName: string, handler: (data: unknown) => void): void {\n const handlers = this.eventHandlers.get(eventName) || [];\n handlers.push(handler);\n this.eventHandlers.set(eventName, handlers);\n }\n\n /**\n * Remove an event handler\n */\n offEvent(eventName: string, handler: (data: unknown) => void): void {\n const handlers = this.eventHandlers.get(eventName) || [];\n const index = handlers.indexOf(handler);\n if (index > -1) {\n handlers.splice(index, 1);\n this.eventHandlers.set(eventName, handlers);\n }\n }\n\n private handleMessage(event: MessageEvent<IframeMessage>): void {\n // Validate origin\n if (!ALLOWED_ORIGINS.includes(event.origin)) {\n return;\n }\n\n const { data } = event;\n\n // Validate message format\n if (data?.messageBizId !== MESSAGE_BIZ_ID) {\n return;\n }\n\n // Handle response messages\n if (this.isResponseMessage(data)) {\n const pending = this.pendingRequests.get(data.id);\n if (pending) {\n clearTimeout(pending.timer);\n this.pendingRequests.delete(data.id);\n\n if (data.error) {\n const error = new Error(data.error.message);\n slardar.captureException(error, { source: 'aily-web-sdk', module: 'message-bridge', errorCode: data.error.code });\n pending.reject(error);\n } else {\n pending.resolve(data.data);\n }\n }\n }\n\n // Handle event messages\n if (this.isEventMessage(data)) {\n const handlers = this.eventHandlers.get(data.eventName) || [];\n handlers.forEach((handler) => {\n try {\n handler(data.data);\n } catch {\n // Ignore handler errors\n }\n });\n }\n }\n\n private isResponseMessage(data: IframeMessage): data is IframeResponseMessage {\n return 'isResponse' in data && data.isResponse === true;\n }\n\n private isEventMessage(data: IframeMessage): data is IframeEventMessage {\n return data.type === 'event';\n }\n}\n","import {\n MESSAGE_BIZ_ID,\n PARENT_ORIGIN_QUERY_KEY,\n getAgentIframeBaseURL,\n} from './constants';\nimport { MessageBridge } from './message-bridge';\n\nimport type { AgentSDKInitConfig, AgentSDKInstance } from './types/config';\nimport type { ParentContextMessageData } from './types/message';\n\n/**\n * AgentIframeManager handles agent iframe creation and lifecycle.\n */\nexport class AgentIframeManager {\n private iframe: HTMLIFrameElement | null = null;\n private readonly messageBridge: MessageBridge;\n private readonly config: AgentSDKInitConfig;\n private readonly root: HTMLElement;\n\n constructor(root: HTMLElement, config: AgentSDKInitConfig) {\n this.root = root;\n this.config = config;\n this.messageBridge = new MessageBridge(getAgentIframeBaseURL());\n }\n\n async init(): Promise<AgentSDKInstance> {\n this.iframe = document.createElement('iframe');\n this.iframe.src = this.buildIframeURL();\n this.iframe.style.width = '100%';\n this.iframe.style.height = '100%';\n this.iframe.style.border = 'none';\n this.iframe.allow = 'microphone; clipboard-write';\n\n this.root.appendChild(this.iframe);\n this.messageBridge.attach(this.iframe);\n\n await this.waitForReady();\n await this.messageBridge.send(\n 'initParentContext',\n this.buildParentContext()\n );\n\n return this.createAgentInstance();\n }\n\n async destroy(): Promise<void> {\n try {\n await this.messageBridge.send('destroy');\n } catch {\n // Ignore errors during destroy.\n }\n\n this.messageBridge.detach();\n\n if (this.iframe?.parentNode) {\n this.iframe.parentNode.removeChild(this.iframe);\n }\n\n this.iframe = null;\n }\n\n private buildIframeURL(): string {\n const baseURL = getAgentIframeBaseURL();\n const params = new URLSearchParams({\n channelToken: this.config.channelToken,\n [PARENT_ORIGIN_QUERY_KEY]: window.location.origin,\n });\n\n return `${baseURL}?${params.toString()}`;\n }\n\n private buildParentContext(): ParentContextMessageData {\n return {\n parentOrigin: window.location.origin,\n };\n }\n\n private waitForReady(): Promise<void> {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n window.removeEventListener('message', checkMessage);\n reject(new Error('Iframe ready timeout'));\n }, 30000);\n\n const checkMessage = (event: MessageEvent) => {\n if (\n event.data?.messageBizId === MESSAGE_BIZ_ID &&\n event.data?.type === 'event' &&\n event.data?.eventName === 'ready'\n ) {\n clearTimeout(timeout);\n window.removeEventListener('message', checkMessage);\n resolve();\n }\n };\n\n window.addEventListener('message', checkMessage);\n });\n }\n\n private createAgentInstance(): AgentSDKInstance {\n return {\n destroy: async () => {\n await this.destroy();\n },\n };\n }\n}\n","/*\n * index.ts\n * Author: perterpon.wang<perterpon.wang@bytedance.com>\n * Create: Tue Feb 10 2026\n */\n\nimport { IframeManager } from \"./iframe-manager\";\nimport { AgentIframeManager } from \"./agent-iframe-manager\";\n\nimport type {\n\tAgentSDKInitConfig,\n\tAgentSDKInstance,\n\tChatPanel,\n\tWebSDKConfig,\n} from \"./types/config\";\n\n/**\n * Initialize Aily Chat via iframe\n * This is the primary method for initializing the chat panel\n * @param root - Container element for the iframe\n * @param config - Configuration options\n * @returns ChatPanel instance for controlling the chat\n */\nexport async function initAilyChat(\n\troot: HTMLElement,\n\tconfig: WebSDKConfig,\n): Promise<ChatPanel> {\n\tconst manager = new IframeManager(root, config);\n\treturn manager.init();\n}\n\n/**\n * Initialize Agent Chat via iframe\n * @param root - Container element for the iframe\n * @param config - Agent SDK configuration\n * @returns Agent SDK instance for controlling the agent page\n */\nexport async function initAgentChat(\n\troot: HTMLElement,\n\tconfig: AgentSDKInitConfig,\n): Promise<AgentSDKInstance> {\n\tconst manager = new AgentIframeManager(root, config);\n\treturn manager.init();\n}\n\n// Export constants\nexport {\n\tAGENT_IFRAME_BASE_URL,\n\tDEFAULT_ANONYMOUS_CHANNEL_TYPE,\n\tDEFAULT_CHANNEL_TYPE,\n\tgetAgentIframeBaseURL,\n\tgetIframeBaseURL,\n\tIFRAME_BASE_URL,\n\tMESSAGE_TIMEOUT,\n} from \"./constants\";\n// Export types\nexport type {\n\tAgentSDKInitConfig,\n\tAgentSDKInstance,\n\tChatPanel,\n\tWebSDKCommonConfig,\n\tWebSDKConfig,\n\tWebSDKConversionConfig,\n\tWebSDKEditorConfig,\n\tWebSDKEvents,\n\tWebSDKSkillInfo,\n} from \"./types/config\";\n\n// Export message types\nexport type {\n\tIframeEventMessage,\n\tIframeMessage,\n\tIframeMessageType,\n\tIframeRequestMessage,\n\tIframeResponseMessage,\n} from \"./types/message\";\n"],"mappings":"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","names":["MESSAGE_BIZ_ID","PARENT_ORIGIN_QUERY_KEY","IFRAME_ORIGIN","production","staging","boe","development","CHAT_IFRAME_PATH","AGENT_IFRAME_PATH","IFRAME_BASE_URL","AGENT_IFRAME_BASE_URL","isIframeEnv","env","Boolean","resolveDebugIframeEnv","window","undefined","debugIframeEnv","__DEBUG__","ailyWebSdk","iframeEnv","resolveIframeEnv","hostname","location","includes","getIframeBaseURL","getAgentIframeBaseURL","MESSAGE_TIMEOUT","DEFAULT_CHANNEL_TYPE","DEFAULT_ANONYMOUS_CHANNEL_TYPE","ALLOWED_ORIGINS","slardar","MOBILE_BREAKPOINT","DeviceDetector","mediaQuery","currentDevice","callback","handleChange","window","matchMedia","innerWidth","getDevice","observe","newDevice","addEventListener","destroy","removeEventListener","slardar","MessageBridge","targetOrigin","iframe","requestId","pendingRequests","Map","eventHandlers","URL","origin","handleMessage","bind","attach","window","addEventListener","detach","removeEventListener","forEach","reject","Error","clear","send","type","data","Promise","resolve","contentWindow","id","message","messageBizId","MESSAGE_BIZ_ID","timestamp","Date","now","isRequest","timer","setTimeout","delete","error","slardar","captureException","source","module","messageType","MESSAGE_TIMEOUT","set","postMessage","onEvent","eventName","handler","handlers","get","push","offEvent","index","indexOf","splice","event","ALLOWED_ORIGINS","includes","isResponseMessage","pending","clearTimeout","errorCode","code","isEventMessage","isResponse","IframeManager","root","config","iframe","messageBridge","channelType","deviceDetector","defaultChannel","anonymous","DEFAULT_ANONYMOUS_CHANNEL_TYPE","DEFAULT_CHANNEL_TYPE","common","MessageBridge","getIframeBaseURL","init","initStart","performance","now","device","DeviceDetector","getDevice","document","createElement","src","buildIframeURL","style","width","height","border","allow","appendChild","attach","setupEventHandlers","observe","newDevice","send","waitForReady","reportInitMetrics","createChatPanel","destroy","detach","parentNode","removeChild","baseURL","events","_events","_anonymous","configWithoutEvents","editorConfig","editor","skill","type","builtinType","iframeConfig","resourceType","configBase64","btoa","encodeURIComponent","JSON","stringify","params","URLSearchParams","appKey","toString","Promise","resolve","reject","timeout","setTimeout","error","Error","slardar","captureException","source","module","checkMessage","event","data","messageBizId","MESSAGE_BIZ_ID","eventName","clearTimeout","window","removeEventListener","addEventListener","onReady","onEvent","onError","msg","message","onMessage","onInited","onInitedWithWelcome","onClose","cost","sendEvent","name","metrics","categories","arch","sendMessage","clear","cancelMessage","messageItem","clearAndStop","updateWelcomeMessage","updateConfig","observeSkill","skillId","skillType","setCurrentSkill","AgentIframeManager","root","config","iframe","messageBridge","MessageBridge","getAgentIframeBaseURL","init","document","createElement","src","buildIframeURL","style","width","height","border","allow","appendChild","attach","waitForReady","send","buildParentContext","createAgentInstance","destroy","detach","parentNode","removeChild","baseURL","params","URLSearchParams","channelToken","PARENT_ORIGIN_QUERY_KEY","window","location","origin","toString","parentOrigin","Promise","resolve","reject","timeout","setTimeout","removeEventListener","checkMessage","Error","event","data","messageBizId","MESSAGE_BIZ_ID","type","eventName","clearTimeout","addEventListener","initAilyChat","root","config","manager","IframeManager","init","initAgentChat","AgentIframeManager"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/iframe-manager.ts","../src/device-detector.ts","../src/message-bridge.ts","../src/agent-iframe-manager.ts","../src/index.ts"],"sourcesContent":["/**\n * Constants for Aily Web SDK\n */\n\n/** Message business ID for postMessage identification */\nexport const MESSAGE_BIZ_ID = 'cui-sdk-message' as const;\nexport const PARENT_ORIGIN_QUERY_KEY = '__parentOrigin' as const;\n\n/** Iframe origins by environment */\nexport const IFRAME_ORIGIN: Record<string, string> = {\n production: 'https://aily.feishu.cn',\n staging: 'https://aily.feishu-pre.cn',\n boe: 'https://aily.feishu-boe.cn',\n development: 'http://localhost:3000',\n};\n\n/** Page paths for iframe apps */\nexport const CHAT_IFRAME_PATH = '/cui' as const;\nexport const AGENT_IFRAME_PATH = '/custom_agent/cui' as const;\n\n/** Chat iframe base URLs by environment */\nexport const IFRAME_BASE_URL: Record<string, string> = {\n production: `${IFRAME_ORIGIN.production}${CHAT_IFRAME_PATH}`,\n staging: `${IFRAME_ORIGIN.staging}${CHAT_IFRAME_PATH}`,\n boe: `${IFRAME_ORIGIN.boe}${CHAT_IFRAME_PATH}`,\n development: `${IFRAME_ORIGIN.development}${CHAT_IFRAME_PATH}`,\n};\n\n/** Agent iframe base URLs by environment */\nexport const AGENT_IFRAME_BASE_URL: Record<string, string> = {\n production: `${IFRAME_ORIGIN.production}${AGENT_IFRAME_PATH}`,\n staging: `${IFRAME_ORIGIN.staging}${AGENT_IFRAME_PATH}`,\n boe: `${IFRAME_ORIGIN.boe}${AGENT_IFRAME_PATH}`,\n development: `${IFRAME_ORIGIN.development}${AGENT_IFRAME_PATH}`,\n};\n\ntype IframeEnv = keyof typeof IFRAME_BASE_URL;\n\ninterface AilyWebSdkDebugConfig {\n iframeEnv?: string;\n}\n\ndeclare global {\n interface Window {\n __DEBUG__?: {\n ailyWebSdk?: AilyWebSdkDebugConfig;\n [key: string]: unknown;\n };\n }\n}\n\nfunction isIframeEnv(env?: string): env is IframeEnv {\n return Boolean(env && env in IFRAME_BASE_URL);\n}\n\nfunction resolveDebugIframeEnv(): IframeEnv | undefined {\n if (typeof window === 'undefined') {\n return undefined;\n }\n\n const debugIframeEnv = window.__DEBUG__?.ailyWebSdk?.iframeEnv;\n return isIframeEnv(debugIframeEnv) ? debugIframeEnv : undefined;\n}\n\n/**\n * Get iframe base URL based on environment\n */\nfunction resolveIframeEnv(env?: string): IframeEnv {\n if (isIframeEnv(env)) {\n return env;\n }\n\n const debugIframeEnv = resolveDebugIframeEnv();\n if (debugIframeEnv) {\n return debugIframeEnv;\n }\n\n // Auto-detect based on hostname\n // MiaoDa 宿主域名: miaoda.feishu[-env].cn, *.aiforce[-env][-preview].bytedance.net, *.force-pre.feishuapp.net, *.fsapp.kundou.cn, *.aiforce.run, *.aiforce.cloud\n const hostname =\n typeof window !== 'undefined' ? window.location.hostname : '';\n\n if (hostname.includes('aiforce-boe')) {\n return 'boe';\n }\n if (\n hostname.includes('aiforce-pre') ||\n hostname.includes('force-pre.feishuapp.net') ||\n hostname.includes('fsapp.kundou.cn')\n ) {\n return 'staging';\n }\n\n return 'production';\n}\n\nexport function getIframeBaseURL(env?: string): string {\n return IFRAME_BASE_URL[resolveIframeEnv(env)];\n}\n\n/**\n * Get agent iframe base URL based on environment\n */\nexport function getAgentIframeBaseURL(env?: string): string {\n return AGENT_IFRAME_BASE_URL[resolveIframeEnv(env)];\n}\n\n/** Timeout for postMessage requests (30 seconds) */\nexport const MESSAGE_TIMEOUT = 30 * 1000;\n\n/** Miaoda 渠道标识默认值(用户可通过 config.common.channelType 覆盖) */\nexport const DEFAULT_CHANNEL_TYPE = 'MIAODA_CUI_SDK';\nexport const DEFAULT_ANONYMOUS_CHANNEL_TYPE = 'MIAODA_ANONYMOUS_CUI_SDK';\n\n/** Allowed origins for postMessage (cui-iframe 的 origin) */\nexport const ALLOWED_ORIGINS = [\n IFRAME_ORIGIN.production,\n IFRAME_ORIGIN.staging,\n IFRAME_ORIGIN.boe,\n 'http://localhost:3000',\n 'http://localhost:5173',\n IFRAME_ORIGIN.development,\n];\n","import {\n\tDEFAULT_ANONYMOUS_CHANNEL_TYPE,\n\tDEFAULT_CHANNEL_TYPE,\n\tgetIframeBaseURL,\n\tMESSAGE_BIZ_ID,\n} from \"./constants\";\nimport { slardar } from \"@lark-apaas/internal-slardar\";\nimport { DeviceDetector } from \"./device-detector\";\nimport { MessageBridge } from \"./message-bridge\";\n\nimport type { ChatPanel, WebSDKConfig } from \"./types/config\";\n\n/**\n * IframeManager handles iframe creation and lifecycle\n *\n * iframe 采用自初始化模式:配置通过 URL hash 传入,iframe 加载后自行解析并渲染,\n * 与旧版 copilot iframe 的行为保持一致。宿主通过 postMessage 进行后续操作。\n */\nexport class IframeManager {\n\tprivate iframe: HTMLIFrameElement | null = null;\n\tprivate messageBridge: MessageBridge;\n\tprivate config: WebSDKConfig;\n\tprivate channelType: string;\n\tprivate root: HTMLElement;\n\tprivate deviceDetector: DeviceDetector | null = null;\n\n\tconstructor(root: HTMLElement, config: WebSDKConfig) {\n\t\tthis.root = root;\n\t\tthis.config = config;\n\t\tconst defaultChannel = config.anonymous\n\t\t\t? DEFAULT_ANONYMOUS_CHANNEL_TYPE\n\t\t\t: DEFAULT_CHANNEL_TYPE;\n\t\tthis.channelType = config.common?.channelType || defaultChannel;\n\t\tthis.messageBridge = new MessageBridge(getIframeBaseURL());\n\t}\n\n\t/**\n\t * Initialize the iframe and establish communication\n\t * 配置通过 URL hash 编码传入 iframe,iframe 加载后自行初始化\n\t */\n\tasync init(): Promise<ChatPanel> {\n\t\tconst initStart = performance.now();\n\n\t\t// Auto-detect device if not explicitly provided\n\t\tif (!this.config.device) {\n\t\t\tthis.deviceDetector = new DeviceDetector();\n\t\t\tthis.config.device = this.deviceDetector.getDevice();\n\t\t}\n\n\t\t// Create iframe element\n\t\tthis.iframe = document.createElement(\"iframe\");\n\t\tthis.iframe.src = this.buildIframeURL();\n\t\tthis.iframe.style.width = \"100%\";\n\t\tthis.iframe.style.height = \"100%\";\n\t\tthis.iframe.style.border = \"none\";\n\t\tthis.iframe.allow = \"microphone; clipboard-write\";\n\n\t\t// Attach to DOM\n\t\tthis.root.appendChild(this.iframe);\n\n\t\t// Attach message bridge (开始监听消息)\n\t\tthis.messageBridge.attach(this.iframe);\n\n\t\t// Setup event handlers (在 iframe 初始化完成之前就开始监听,确保不丢失事件)\n\t\tthis.setupEventHandlers();\n\n\t\t// Listen for device changes and push updates to iframe\n\t\tif (this.deviceDetector) {\n\t\t\tthis.deviceDetector.observe((newDevice) => {\n\t\t\t\tthis.messageBridge.send(\"updateConfig\", { device: newDevice });\n\t\t\t});\n\t\t}\n\n\t\t// Wait for iframe to finish initialization (iframe 自行读取 URL 配置并渲染,完成后发送 ready 事件)\n\t\tawait this.waitForReady();\n\n\t\t// 上报 cui_init_total 耗时(iframe 创建 → init 完成)\n\t\tthis.reportInitMetrics(initStart);\n\n\t\t// Return ChatPanel interface\n\t\treturn this.createChatPanel();\n\t}\n\n\t/**\n\t * Destroy the iframe and cleanup\n\t */\n\tasync destroy(): Promise<void> {\n\t\ttry {\n\t\t\tawait this.messageBridge.send(\"destroy\");\n\t\t} catch {\n\t\t\t// Ignore errors during destroy\n\t\t}\n\n\t\tthis.messageBridge.detach();\n\n\t\tif (this.deviceDetector) {\n\t\t\tthis.deviceDetector.destroy();\n\t\t\tthis.deviceDetector = null;\n\t\t}\n\n\t\tif (this.iframe?.parentNode) {\n\t\t\tthis.iframe.parentNode.removeChild(this.iframe);\n\t\t}\n\n\t\tthis.iframe = null;\n\t}\n\n\t/**\n\t * 构建 iframe URL,将配置编码到 hash 中\n\t * 格式: {baseURL}#{params} 其中 config 为 base64(JSON.stringify(configWithoutEvents))\n\t *\n\t * 鉴权说明:SDK 不参与 token 获取/传递。iframe 自行处理飞书登录流程,\n\t * 允许用户在 iframe 中独立登录。匿名渠道跳过登录检查。\n\t */\n\tprivate buildIframeURL(): string {\n\t\tconst baseURL = getIframeBaseURL();\n\n\t\t// 移除 events(函数无法序列化)\n\t\tconst {\n\t\t\tevents: _events,\n\t\t\tanonymous: _anonymous,\n\t\t\t...configWithoutEvents\n\t\t} = this.config;\n\t\t// 注入 channelType/resourceType(SDK 内部控制,不暴露给消费者)\n\t\t// 补全 editor.skill 硬编码字段\n\t\tconst editorConfig = configWithoutEvents.editor?.skill\n\t\t\t? {\n\t\t\t\t\t...configWithoutEvents.editor,\n\t\t\t\t\tskill: {\n\t\t\t\t\t\ttype: \"custom\",\n\t\t\t\t\t\tbuiltinType: \"unspecified\",\n\t\t\t\t\t\t...configWithoutEvents.editor.skill,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: configWithoutEvents.editor;\n\n\t\tconst iframeConfig = {\n\t\t\t...configWithoutEvents,\n\t\t\tcommon: {\n\t\t\t\t...configWithoutEvents.common,\n\t\t\t\tchannelType: this.channelType,\n\t\t\t\tresourceType:\n\t\t\t\t\tconfigWithoutEvents.common?.resourceType || this.channelType,\n\t\t\t},\n\t\t\teditor: editorConfig,\n\t\t};\n\t\tconst configBase64 = btoa(encodeURIComponent(JSON.stringify(iframeConfig)));\n\n\t\tconst params = new URLSearchParams({\n\t\t\tappKey: this.config.appKey,\n\t\t\tconfig: encodeURIComponent(configBase64),\n\t\t});\n\n\t\treturn `${baseURL}#${params.toString()}`;\n\t}\n\n\t/**\n\t * 等待 iframe 自行初始化完成后发送 ready 事件\n\t */\n\tprivate waitForReady(): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\tconst error = new Error(\"Iframe ready timeout\");\n\t\t\t\tslardar.captureException(error, { source: 'aily-web-sdk', module: 'iframe-ready' });\n\t\t\t\treject(error);\n\t\t\t}, 30000);\n\n\t\t\tconst checkMessage = (event: MessageEvent) => {\n\t\t\t\tif (\n\t\t\t\t\tevent.data?.messageBizId === MESSAGE_BIZ_ID &&\n\t\t\t\t\tevent.data?.type === \"event\" &&\n\t\t\t\t\tevent.data?.eventName === \"ready\"\n\t\t\t\t) {\n\t\t\t\t\tclearTimeout(timeout);\n\t\t\t\t\twindow.removeEventListener(\"message\", checkMessage);\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\twindow.addEventListener(\"message\", checkMessage);\n\t\t});\n\t}\n\n\tprivate setupEventHandlers(): void {\n\t\tconst { events } = this.config;\n\t\tif (!events) return;\n\n\t\tif (events.onReady) {\n\t\t\tthis.messageBridge.onEvent(\"ready\", events.onReady);\n\t\t}\n\n\t\tif (events.onError) {\n\t\t\tthis.messageBridge.onEvent(\"error\", (data: unknown) => {\n\t\t\t\tconst msg = (data as { message?: string })?.message || \"Unknown error\";\n\t\t\t\tevents.onError?.(new Error(msg));\n\t\t\t});\n\t\t}\n\n\t\tif (events.onMessage) {\n\t\t\tthis.messageBridge.onEvent(\"onMessage\", events.onMessage);\n\t\t}\n\n\t\tif (events.onInited) {\n\t\t\tthis.messageBridge.onEvent(\n\t\t\t\t\"inited\",\n\t\t\t\tevents.onInited as (data: unknown) => void,\n\t\t\t);\n\t\t}\n\n\t\tif (events.onInitedWithWelcome) {\n\t\t\tthis.messageBridge.onEvent(\n\t\t\t\t\"initedWithWelcome\",\n\t\t\t\tevents.onInitedWithWelcome,\n\t\t\t);\n\t\t}\n\n\t\tif (events.onClose) {\n\t\t\tthis.messageBridge.onEvent(\"onClose\", events.onClose);\n\t\t}\n\t}\n\n\tprivate reportInitMetrics(initStart: number): void {\n\t\ttry {\n\t\t\tconst cost = performance.now() - initStart;\n\t\t\tslardar.sendEvent({\n\t\t\t\tname: \"cui_init_total\",\n\t\t\t\tmetrics: { cost },\n\t\t\t\tcategories: {\n\t\t\t\t\tarch: \"iframe-static\",\n\t\t\t\t\tappKey: this.config.appKey,\n\t\t\t\t\tchannelType: this.channelType,\n\t\t\t\t},\n\t\t\t});\n\t\t} catch {\n\t\t\t// 性能上报失败不影响功能\n\t\t}\n\t}\n\n\tprivate createChatPanel(): ChatPanel {\n\t\treturn {\n\t\t\tsendMessage: async (data) => {\n\t\t\t\tawait this.messageBridge.send(\"sendMessage\", data);\n\t\t\t},\n\t\t\tclear: async () => {\n\t\t\t\tawait this.messageBridge.send(\"clear\");\n\t\t\t},\n\t\t\tcancelMessage: async (messageItem) => {\n\t\t\t\tawait this.messageBridge.send(\"cancelMessage\", messageItem);\n\t\t\t},\n\t\t\tclearAndStop: async () => {\n\t\t\t\tawait this.messageBridge.send(\"clearAndStop\");\n\t\t\t},\n\t\t\tupdateWelcomeMessage: async () => {\n\t\t\t\tawait this.messageBridge.send(\"updateWelcomeMessage\");\n\t\t\t},\n\t\t\tupdateConfig: async (config) => {\n\t\t\t\tawait this.messageBridge.send(\"updateConfig\", config);\n\t\t\t},\n\t\t\tobserveSkill: async (skillId, name, skillType) => {\n\t\t\t\tawait this.messageBridge.send(\"observeSkill\", {\n\t\t\t\t\tskillId,\n\t\t\t\t\tname,\n\t\t\t\t\tskillType,\n\t\t\t\t});\n\t\t\t},\n\t\t\tsetCurrentSkill: async (skill) => {\n\t\t\t\tawait this.messageBridge.send(\"setCurrentSkill\", skill);\n\t\t\t},\n\t\t\tdestroy: async () => {\n\t\t\t\tawait this.destroy();\n\t\t\t},\n\t\t};\n\t}\n}\n","const MOBILE_BREAKPOINT = 768;\n\ntype DeviceType = 'pc' | 'mobile';\ntype DeviceChangeCallback = (device: DeviceType) => void;\n\n/**\n * 设备类型自动检测器\n *\n * 使用 matchMedia + 768px 断点检测设备类型,与 miaoda useIsMobile 逻辑一致。\n * 检测在宿主页面(而非 iframe)中执行,结果通过 postMessage 推送给 iframe。\n */\nexport class DeviceDetector {\n private mediaQuery: MediaQueryList;\n private currentDevice: DeviceType;\n private callback: DeviceChangeCallback | null = null;\n private handleChange: (() => void) | null = null;\n\n constructor() {\n this.mediaQuery = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);\n this.currentDevice = window.innerWidth < MOBILE_BREAKPOINT ? 'mobile' : 'pc';\n }\n\n getDevice(): DeviceType {\n return this.currentDevice;\n }\n\n observe(callback: DeviceChangeCallback): void {\n this.callback = callback;\n this.handleChange = () => {\n const newDevice: DeviceType = window.innerWidth < MOBILE_BREAKPOINT ? 'mobile' : 'pc';\n if (newDevice !== this.currentDevice) {\n this.currentDevice = newDevice;\n this.callback?.(newDevice);\n }\n };\n this.mediaQuery.addEventListener('change', this.handleChange);\n }\n\n destroy(): void {\n if (this.handleChange) {\n this.mediaQuery.removeEventListener('change', this.handleChange);\n this.handleChange = null;\n }\n this.callback = null;\n }\n}\n","import { MESSAGE_TIMEOUT, ALLOWED_ORIGINS } from './constants';\nimport {\n MESSAGE_BIZ_ID,\n type IframeMessage,\n type IframeRequestMessage,\n type IframeResponseMessage,\n type IframeEventMessage,\n type IframeMessageType,\n} from './types/message';\nimport { slardar } from '@lark-apaas/internal-slardar';\n\ninterface PendingRequest {\n resolve: (value: unknown) => void;\n reject: (reason: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\n/**\n * MessageBridge handles postMessage communication between parent and iframe\n */\nexport class MessageBridge {\n private iframe: HTMLIFrameElement | null = null;\n private requestId = 0;\n private pendingRequests = new Map<number, PendingRequest>();\n private eventHandlers = new Map<string, ((data: unknown) => void)[]>();\n private targetOrigin: string;\n\n constructor(targetOrigin: string) {\n this.targetOrigin = new URL(targetOrigin).origin;\n this.handleMessage = this.handleMessage.bind(this);\n }\n\n /**\n * Attach to an iframe and start listening for messages\n */\n attach(iframe: HTMLIFrameElement): void {\n this.iframe = iframe;\n window.addEventListener('message', this.handleMessage);\n }\n\n /**\n * Detach from iframe and clean up\n */\n detach(): void {\n window.removeEventListener('message', this.handleMessage);\n this.iframe = null;\n // Clear all pending requests\n this.pendingRequests.forEach(({ reject }) => {\n reject(new Error('MessageBridge detached'));\n });\n this.pendingRequests.clear();\n }\n\n /**\n * Send a message to the iframe and wait for response\n */\n send<T = unknown>(type: IframeMessageType, data?: unknown): Promise<T> {\n return new Promise((resolve, reject) => {\n if (!this.iframe?.contentWindow) {\n reject(new Error('Iframe not attached'));\n return;\n }\n\n this.requestId += 1;\n const id = this.requestId;\n const message: IframeRequestMessage = {\n messageBizId: MESSAGE_BIZ_ID,\n id,\n type,\n data,\n timestamp: Date.now(),\n isRequest: true,\n };\n\n const timer = setTimeout(() => {\n this.pendingRequests.delete(id);\n const error = new Error(`Message timeout: ${type}`);\n slardar.captureException(error, { source: 'aily-web-sdk', module: 'message-bridge', messageType: type });\n reject(error);\n }, MESSAGE_TIMEOUT);\n\n this.pendingRequests.set(id, { resolve: resolve as (value: unknown) => void, reject, timer });\n\n this.iframe.contentWindow.postMessage(message, this.targetOrigin);\n });\n }\n\n /**\n * Register an event handler\n */\n onEvent(eventName: string, handler: (data: unknown) => void): void {\n const handlers = this.eventHandlers.get(eventName) || [];\n handlers.push(handler);\n this.eventHandlers.set(eventName, handlers);\n }\n\n /**\n * Remove an event handler\n */\n offEvent(eventName: string, handler: (data: unknown) => void): void {\n const handlers = this.eventHandlers.get(eventName) || [];\n const index = handlers.indexOf(handler);\n if (index > -1) {\n handlers.splice(index, 1);\n this.eventHandlers.set(eventName, handlers);\n }\n }\n\n private handleMessage(event: MessageEvent<IframeMessage>): void {\n // Validate origin\n if (!ALLOWED_ORIGINS.includes(event.origin)) {\n return;\n }\n\n const { data } = event;\n\n // Validate message format\n if (data?.messageBizId !== MESSAGE_BIZ_ID) {\n return;\n }\n\n // Handle response messages\n if (this.isResponseMessage(data)) {\n const pending = this.pendingRequests.get(data.id);\n if (pending) {\n clearTimeout(pending.timer);\n this.pendingRequests.delete(data.id);\n\n if (data.error) {\n const error = new Error(data.error.message);\n slardar.captureException(error, { source: 'aily-web-sdk', module: 'message-bridge', errorCode: data.error.code });\n pending.reject(error);\n } else {\n pending.resolve(data.data);\n }\n }\n }\n\n // Handle event messages\n if (this.isEventMessage(data)) {\n const handlers = this.eventHandlers.get(data.eventName) || [];\n handlers.forEach((handler) => {\n try {\n handler(data.data);\n } catch {\n // Ignore handler errors\n }\n });\n }\n }\n\n private isResponseMessage(data: IframeMessage): data is IframeResponseMessage {\n return 'isResponse' in data && data.isResponse === true;\n }\n\n private isEventMessage(data: IframeMessage): data is IframeEventMessage {\n return data.type === 'event';\n }\n}\n","import { PARENT_ORIGIN_QUERY_KEY, getAgentIframeBaseURL } from './constants';\nimport { MessageBridge } from './message-bridge';\n\nimport type {\n AgentSDKInitConfig,\n AgentSDKInstance,\n AgentSDKRuntimeCustomContext,\n} from './types/config';\nimport type {\n AgentReadyEventData,\n ParentContextMessageData,\n ParentContextResponseData,\n} from './types/message';\n\n/**\n * AgentIframeManager handles agent iframe creation and lifecycle.\n */\nexport class AgentIframeManager {\n private iframe: HTMLIFrameElement | null = null;\n private readonly messageBridge: MessageBridge;\n private readonly config: AgentSDKInitConfig;\n private readonly root: HTMLElement;\n private readonly runtimeCustomContext: AgentSDKRuntimeCustomContext | null;\n private readonly contextVersion: string;\n private initialHandshakeCompleted = false;\n\n constructor(root: HTMLElement, config: AgentSDKInitConfig) {\n this.root = root;\n this.config = config;\n this.runtimeCustomContext = this.resolveRuntimeCustomContext(config);\n this.contextVersion = this.createContextVersion();\n this.messageBridge = new MessageBridge(getAgentIframeBaseURL());\n }\n\n async init(): Promise<AgentSDKInstance> {\n this.iframe = document.createElement('iframe');\n this.iframe.src = this.buildIframeURL();\n this.iframe.style.width = '100%';\n this.iframe.style.height = '100%';\n this.iframe.style.border = 'none';\n this.iframe.allow = 'microphone; clipboard-write';\n\n const readyPromise = this.waitForReady();\n this.messageBridge.onEvent('ready', this.handleSubsequentReady);\n this.messageBridge.attach(this.iframe);\n this.root.appendChild(this.iframe);\n\n try {\n const readyData = await readyPromise;\n await this.sendParentContext(readyData);\n this.initialHandshakeCompleted = true;\n } catch (error) {\n this.cleanupAfterFailedInit();\n throw error;\n }\n\n return this.createAgentInstance();\n }\n\n async destroy(): Promise<void> {\n this.messageBridge.offEvent('ready', this.handleSubsequentReady);\n\n try {\n await this.messageBridge.send('destroy');\n } catch {\n // Ignore errors during destroy.\n }\n\n this.messageBridge.detach();\n this.removeIframe();\n this.initialHandshakeCompleted = false;\n }\n\n private buildIframeURL(): string {\n const baseURL = getAgentIframeBaseURL();\n const params = new URLSearchParams({\n channelToken: this.config.channelToken,\n [PARENT_ORIGIN_QUERY_KEY]: window.location.origin,\n });\n\n return `${baseURL}?${params.toString()}`;\n }\n\n private buildParentContext(): ParentContextMessageData {\n const parentContext: ParentContextMessageData = {\n parentOrigin: window.location.origin,\n };\n\n return parentContext;\n }\n\n private waitForReady(): Promise<AgentReadyEventData | undefined> {\n return new Promise((resolve, reject) => {\n const handleReady = (data: unknown) => {\n clearTimeout(timeout);\n this.messageBridge.offEvent('ready', handleReady);\n resolve(this.parseReadyEventData(data));\n };\n\n const timeout = setTimeout(() => {\n this.messageBridge.offEvent('ready', handleReady);\n reject(new Error('Iframe ready timeout'));\n }, 30000);\n\n this.messageBridge.onEvent('ready', handleReady);\n });\n }\n\n private readonly handleSubsequentReady = (data: unknown): void => {\n if (!this.initialHandshakeCompleted) {\n return;\n }\n\n void this.sendParentContext(this.parseReadyEventData(data)).catch(\n () => undefined\n );\n };\n\n private async sendParentContext(\n readyData?: AgentReadyEventData\n ): Promise<void> {\n const payload = this.buildParentContextForReady(readyData);\n const response = await this.messageBridge.send<ParentContextResponseData>(\n 'initParentContext',\n payload\n );\n\n if (!this.runtimeCustomContext) {\n return;\n }\n\n if (response?.accepted !== true) {\n throw new Error('Iframe rejected initParentContext custom context');\n }\n\n if (\n payload.iframeSessionId &&\n response.iframeSessionId &&\n response.iframeSessionId !== payload.iframeSessionId\n ) {\n throw new Error('Iframe returned mismatched iframeSessionId');\n }\n\n if (\n payload.contextVersion &&\n response.contextVersion &&\n response.contextVersion !== payload.contextVersion\n ) {\n throw new Error('Iframe returned mismatched contextVersion');\n }\n }\n\n private buildParentContextForReady(\n readyData?: AgentReadyEventData\n ): ParentContextMessageData {\n const parentContext = this.buildParentContext();\n\n if (!this.runtimeCustomContext) {\n return parentContext;\n }\n\n this.assertReadySupportsRuntimeContext(readyData);\n\n return {\n ...parentContext,\n protocolVersion: 2,\n iframeSessionId: readyData.iframeSessionId,\n contextVersion: this.contextVersion,\n runtimeCustomContext: this.runtimeCustomContext,\n };\n }\n\n private assertReadySupportsRuntimeContext(\n readyData?: AgentReadyEventData\n ): asserts readyData is AgentReadyEventData & {\n protocolVersion: 2;\n iframeSessionId: string;\n needsContext: true;\n } {\n if (\n readyData?.protocolVersion !== 2 ||\n !readyData.iframeSessionId ||\n readyData.needsContext !== true\n ) {\n throw new Error(\n 'Current iframe version does not support custom context initParentContext protocol'\n );\n }\n }\n\n private parseReadyEventData(data: unknown): AgentReadyEventData | undefined {\n if (!this.isRecord(data)) {\n return undefined;\n }\n\n return data as AgentReadyEventData;\n }\n\n private resolveRuntimeCustomContext(\n config: AgentSDKInitConfig\n ): AgentSDKRuntimeCustomContext | null {\n if (\n config.customParams !== undefined &&\n config.customParamsToken !== undefined\n ) {\n throw new Error(\n 'customParams and customParamsToken cannot be used together'\n );\n }\n\n if (config.customParamsToken !== undefined) {\n const token = config.customParamsToken.trim();\n if (!token) {\n throw new Error('customParamsToken cannot be empty');\n }\n\n return { customParamsToken: token };\n }\n\n if (config.customParams === undefined) {\n return null;\n }\n\n if (!this.isRecord(config.customParams)) {\n throw new Error('customParams must be an object');\n }\n\n for (const [key, entry] of Object.entries(config.customParams)) {\n if (\n !this.isRecord(entry) ||\n !('value' in entry) ||\n entry.value === undefined\n ) {\n throw new Error(`customParams.${key} must include value`);\n }\n\n if (\n 'desc' in entry &&\n entry.desc !== undefined &&\n typeof entry.desc !== 'string'\n ) {\n throw new Error(`customParams.${key}.desc must be a string`);\n }\n\n if (!this.isValidCustomParamValue(entry.value)) {\n throw new Error(`customParams.${key}.value has invalid type`);\n }\n }\n\n return { customParams: config.customParams };\n }\n\n private isValidCustomParamValue(value: unknown): boolean {\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return true;\n }\n\n if (Array.isArray(value)) {\n return value.every(\n item =>\n typeof item === 'string' ||\n typeof item === 'number' ||\n typeof item === 'boolean' ||\n this.isRecord(item)\n );\n }\n\n return this.isRecord(value);\n }\n\n private isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n }\n\n private createContextVersion(): string {\n return `ctx-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n private cleanupAfterFailedInit(): void {\n this.messageBridge.offEvent('ready', this.handleSubsequentReady);\n this.messageBridge.detach();\n this.removeIframe();\n }\n\n private removeIframe(): void {\n if (this.iframe?.parentNode) {\n this.iframe.parentNode.removeChild(this.iframe);\n }\n\n this.iframe = null;\n }\n\n private createAgentInstance(): AgentSDKInstance {\n return {\n destroy: async () => {\n await this.destroy();\n },\n };\n }\n}\n","/*\n * index.ts\n * Author: perterpon.wang<perterpon.wang@bytedance.com>\n * Create: Tue Feb 10 2026\n */\n\nimport { IframeManager } from \"./iframe-manager\";\nimport { AgentIframeManager } from \"./agent-iframe-manager\";\n\nimport type {\n\tAgentSDKInitConfig,\n\tAgentSDKInstance,\n\tChatPanel,\n\tWebSDKConfig,\n} from \"./types/config\";\n\n/**\n * Initialize Aily Chat via iframe\n * This is the primary method for initializing the chat panel\n * @param root - Container element for the iframe\n * @param config - Configuration options\n * @returns ChatPanel instance for controlling the chat\n */\nexport async function initAilyChat(\n\troot: HTMLElement,\n\tconfig: WebSDKConfig,\n): Promise<ChatPanel> {\n\tconst manager = new IframeManager(root, config);\n\treturn manager.init();\n}\n\n/**\n * Initialize Agent Chat via iframe\n * @param root - Container element for the iframe\n * @param config - Agent SDK configuration\n * @returns Agent SDK instance for controlling the agent page\n */\nexport async function initAgentChat(\n\troot: HTMLElement,\n\tconfig: AgentSDKInitConfig,\n): Promise<AgentSDKInstance> {\n\tconst manager = new AgentIframeManager(root, config);\n\treturn manager.init();\n}\n\n// Export constants\nexport {\n\tAGENT_IFRAME_BASE_URL,\n\tDEFAULT_ANONYMOUS_CHANNEL_TYPE,\n\tDEFAULT_CHANNEL_TYPE,\n\tgetAgentIframeBaseURL,\n\tgetIframeBaseURL,\n\tIFRAME_BASE_URL,\n\tMESSAGE_TIMEOUT,\n} from \"./constants\";\n// Export types\nexport type {\n\tAgentSDKInitConfig,\n\tAgentSDKInstance,\n AgentSDKRuntimeCustomContext,\n\tChatPanel,\n CustomParamEntry,\n CustomParams,\n\tWebSDKCommonConfig,\n\tWebSDKConfig,\n\tWebSDKConversionConfig,\n\tWebSDKEditorConfig,\n\tWebSDKEvents,\n\tWebSDKSkillInfo,\n} from \"./types/config\";\n\n// Export message types\nexport type {\n\tIframeEventMessage,\n\tIframeMessage,\n\tIframeMessageType,\n\tIframeRequestMessage,\n\tIframeResponseMessage,\n} from \"./types/message\";\n"],"mappings":"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","names":["MESSAGE_BIZ_ID","PARENT_ORIGIN_QUERY_KEY","IFRAME_ORIGIN","production","staging","boe","development","CHAT_IFRAME_PATH","AGENT_IFRAME_PATH","IFRAME_BASE_URL","AGENT_IFRAME_BASE_URL","isIframeEnv","env","Boolean","resolveDebugIframeEnv","window","undefined","debugIframeEnv","__DEBUG__","ailyWebSdk","iframeEnv","resolveIframeEnv","hostname","location","includes","getIframeBaseURL","getAgentIframeBaseURL","MESSAGE_TIMEOUT","DEFAULT_CHANNEL_TYPE","DEFAULT_ANONYMOUS_CHANNEL_TYPE","ALLOWED_ORIGINS","slardar","MOBILE_BREAKPOINT","DeviceDetector","mediaQuery","currentDevice","callback","handleChange","window","matchMedia","innerWidth","getDevice","observe","newDevice","addEventListener","destroy","removeEventListener","slardar","MessageBridge","targetOrigin","iframe","requestId","pendingRequests","Map","eventHandlers","URL","origin","handleMessage","bind","attach","window","addEventListener","detach","removeEventListener","forEach","reject","Error","clear","send","type","data","Promise","resolve","contentWindow","id","message","messageBizId","MESSAGE_BIZ_ID","timestamp","Date","now","isRequest","timer","setTimeout","delete","error","slardar","captureException","source","module","messageType","MESSAGE_TIMEOUT","set","postMessage","onEvent","eventName","handler","handlers","get","push","offEvent","index","indexOf","splice","event","ALLOWED_ORIGINS","includes","isResponseMessage","pending","clearTimeout","errorCode","code","isEventMessage","isResponse","IframeManager","root","config","iframe","messageBridge","channelType","deviceDetector","defaultChannel","anonymous","DEFAULT_ANONYMOUS_CHANNEL_TYPE","DEFAULT_CHANNEL_TYPE","common","MessageBridge","getIframeBaseURL","init","initStart","performance","now","device","DeviceDetector","getDevice","document","createElement","src","buildIframeURL","style","width","height","border","allow","appendChild","attach","setupEventHandlers","observe","newDevice","send","waitForReady","reportInitMetrics","createChatPanel","destroy","detach","parentNode","removeChild","baseURL","events","_events","_anonymous","configWithoutEvents","editorConfig","editor","skill","type","builtinType","iframeConfig","resourceType","configBase64","btoa","encodeURIComponent","JSON","stringify","params","URLSearchParams","appKey","toString","Promise","resolve","reject","timeout","setTimeout","error","Error","slardar","captureException","source","module","checkMessage","event","data","messageBizId","MESSAGE_BIZ_ID","eventName","clearTimeout","window","removeEventListener","addEventListener","onReady","onEvent","onError","msg","message","onMessage","onInited","onInitedWithWelcome","onClose","cost","sendEvent","name","metrics","categories","arch","sendMessage","clear","cancelMessage","messageItem","clearAndStop","updateWelcomeMessage","updateConfig","observeSkill","skillId","skillType","setCurrentSkill","AgentIframeManager","root","config","iframe","messageBridge","runtimeCustomContext","contextVersion","initialHandshakeCompleted","handleSubsequentReady","data","sendParentContext","parseReadyEventData","catch","undefined","resolveRuntimeCustomContext","createContextVersion","MessageBridge","getAgentIframeBaseURL","init","document","createElement","src","buildIframeURL","style","width","height","border","allow","readyPromise","waitForReady","onEvent","attach","appendChild","readyData","error","cleanupAfterFailedInit","createAgentInstance","destroy","offEvent","send","detach","removeIframe","baseURL","params","URLSearchParams","channelToken","PARENT_ORIGIN_QUERY_KEY","window","location","origin","toString","buildParentContext","parentContext","parentOrigin","Promise","resolve","reject","handleReady","clearTimeout","timeout","setTimeout","Error","payload","buildParentContextForReady","response","accepted","iframeSessionId","assertReadySupportsRuntimeContext","protocolVersion","needsContext","isRecord","customParams","customParamsToken","token","trim","key","entry","Object","entries","value","desc","isValidCustomParamValue","Array","isArray","every","item","Date","now","Math","random","slice","parentNode","removeChild","initAilyChat","root","config","manager","IframeManager","init","initAgentChat","AgentIframeManager"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/aily-web-sdk",
3
- "version": "0.0.11",
3
+ "version": "0.0.12-alpha.0",
4
4
  "description": "Aily Web SDK - iframe-based chat panel integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",