@lark-apaas/aily-web-sdk 0.0.9 → 0.0.10
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 +44 -1
- package/dist/index.cjs +125 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -5
- package/dist/index.d.ts +21 -5
- package/dist/index.js +122 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,11 @@ npm install @lark-apaas/aily-web-sdk
|
|
|
16
16
|
|
|
17
17
|
## 使用
|
|
18
18
|
|
|
19
|
+
`@lark-apaas/aily-web-sdk` 当前提供两个初始化 API,分别面向不同的 Aily Chat 场景:
|
|
20
|
+
|
|
21
|
+
- `initAilyChat`:用于初始化 Aily 工作流应用 Chat 面板,适合接入已有工作流应用的对话能力。
|
|
22
|
+
- `initAgentChat`:用于初始化 Aily 新版智能体 Chat 面板,适合接入新版智能体会话页面。
|
|
23
|
+
|
|
19
24
|
```typescript
|
|
20
25
|
import { initAilyChat } from '@lark-apaas/aily-web-sdk'
|
|
21
26
|
|
|
@@ -30,11 +35,26 @@ const chatPanel = await initAilyChat(container, {
|
|
|
30
35
|
});
|
|
31
36
|
```
|
|
32
37
|
|
|
38
|
+
```typescript
|
|
39
|
+
import { initAgentChat } from '@lark-apaas/aily-web-sdk'
|
|
40
|
+
|
|
41
|
+
const container = document.querySelector('.container');
|
|
42
|
+
|
|
43
|
+
const sdk = await initAgentChat(container, {
|
|
44
|
+
channelToken: 'wsk_xxx',
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
33
48
|
## API
|
|
34
49
|
|
|
35
50
|
### `initAilyChat(root, config)`
|
|
36
51
|
|
|
37
|
-
初始化 Aily Chat 面板。
|
|
52
|
+
初始化 Aily 工作流应用 Chat 面板。
|
|
53
|
+
|
|
54
|
+
适用场景:
|
|
55
|
+
|
|
56
|
+
- 宿主页面需要接入 Aily 工作流应用的 Chat 能力
|
|
57
|
+
- 需要使用 `ChatPanel` 提供的消息发送、清空、更新配置等控制方法
|
|
38
58
|
|
|
39
59
|
**参数:**
|
|
40
60
|
|
|
@@ -53,6 +73,23 @@ const chatPanel = await initAilyChat(container, {
|
|
|
53
73
|
|
|
54
74
|
**返回:** `Promise<ChatPanel>`
|
|
55
75
|
|
|
76
|
+
### `initAgentChat(root, config)`
|
|
77
|
+
|
|
78
|
+
初始化 Aily 新版智能体 Chat 面板。
|
|
79
|
+
|
|
80
|
+
适用场景:
|
|
81
|
+
|
|
82
|
+
- 宿主页面需要嵌入 Aily 新版智能体的 Chat 页面
|
|
83
|
+
- 只需要完成智能体 Chat 面板的初始化与销毁管理
|
|
84
|
+
|
|
85
|
+
**参数:**
|
|
86
|
+
|
|
87
|
+
- `root` (`HTMLElement`) - iframe 挂载的容器元素
|
|
88
|
+
- `config` (`AgentSDKInitConfig`) - 配置项
|
|
89
|
+
- `channelToken` (`string`) - agent 渠道 token
|
|
90
|
+
|
|
91
|
+
**返回:** `Promise<AgentSDKInstance>`
|
|
92
|
+
|
|
56
93
|
### `ChatPanel`
|
|
57
94
|
|
|
58
95
|
| 方法 | 说明 |
|
|
@@ -65,6 +102,12 @@ const chatPanel = await initAilyChat(container, {
|
|
|
65
102
|
| `updateConfig(config)` | 更新面板配置 |
|
|
66
103
|
| `destroy()` | 销毁实例 |
|
|
67
104
|
|
|
105
|
+
### `AgentSDKInstance`
|
|
106
|
+
|
|
107
|
+
| 方法 | 说明 |
|
|
108
|
+
| --- | --- |
|
|
109
|
+
| `destroy()` | 销毁 agent iframe 实例 |
|
|
110
|
+
|
|
68
111
|
## License
|
|
69
112
|
|
|
70
113
|
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -23,50 +23,76 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
23
23
|
// src/index.ts
|
|
24
24
|
var index_exports = {};
|
|
25
25
|
__export(index_exports, {
|
|
26
|
+
AGENT_IFRAME_BASE_URL: () => AGENT_IFRAME_BASE_URL,
|
|
26
27
|
DEFAULT_ANONYMOUS_CHANNEL_TYPE: () => DEFAULT_ANONYMOUS_CHANNEL_TYPE,
|
|
27
28
|
DEFAULT_CHANNEL_TYPE: () => DEFAULT_CHANNEL_TYPE,
|
|
28
29
|
IFRAME_BASE_URL: () => IFRAME_BASE_URL,
|
|
29
30
|
MESSAGE_TIMEOUT: () => MESSAGE_TIMEOUT,
|
|
31
|
+
getAgentIframeBaseURL: () => getAgentIframeBaseURL,
|
|
30
32
|
getIframeBaseURL: () => getIframeBaseURL,
|
|
33
|
+
initAgentChat: () => initAgentChat,
|
|
31
34
|
initAilyChat: () => initAilyChat
|
|
32
35
|
});
|
|
33
36
|
module.exports = __toCommonJS(index_exports);
|
|
34
37
|
|
|
35
38
|
// src/constants.ts
|
|
36
39
|
var MESSAGE_BIZ_ID = "cui-sdk-message";
|
|
40
|
+
var PARENT_ORIGIN_QUERY_KEY = "__parentOrigin";
|
|
41
|
+
var IFRAME_ORIGIN = {
|
|
42
|
+
production: "https://aily.feishu.cn",
|
|
43
|
+
staging: "https://aily.feishu-pre.cn",
|
|
44
|
+
boe: "https://aily.feishu-boe.cn",
|
|
45
|
+
development: "http://localhost:8080"
|
|
46
|
+
};
|
|
47
|
+
var CHAT_IFRAME_PATH = "/cui";
|
|
48
|
+
var AGENT_IFRAME_PATH = "/custom_agent/cui";
|
|
37
49
|
var IFRAME_BASE_URL = {
|
|
38
|
-
production:
|
|
39
|
-
staging:
|
|
40
|
-
boe:
|
|
41
|
-
development:
|
|
50
|
+
production: `${IFRAME_ORIGIN.production}${CHAT_IFRAME_PATH}`,
|
|
51
|
+
staging: `${IFRAME_ORIGIN.staging}${CHAT_IFRAME_PATH}`,
|
|
52
|
+
boe: `${IFRAME_ORIGIN.boe}${CHAT_IFRAME_PATH}`,
|
|
53
|
+
development: `${IFRAME_ORIGIN.development}${CHAT_IFRAME_PATH}`
|
|
42
54
|
};
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
55
|
+
var AGENT_IFRAME_BASE_URL = {
|
|
56
|
+
production: `${IFRAME_ORIGIN.production}${AGENT_IFRAME_PATH}`,
|
|
57
|
+
staging: `${IFRAME_ORIGIN.staging}${AGENT_IFRAME_PATH}`,
|
|
58
|
+
boe: `${IFRAME_ORIGIN.boe}${AGENT_IFRAME_PATH}`,
|
|
59
|
+
development: `${IFRAME_ORIGIN.development}${AGENT_IFRAME_PATH}`
|
|
60
|
+
};
|
|
61
|
+
function resolveIframeEnv(env) {
|
|
62
|
+
if (env && env in IFRAME_BASE_URL) {
|
|
63
|
+
return env;
|
|
46
64
|
}
|
|
47
65
|
const hostname = typeof window !== "undefined" ? window.location.hostname : "";
|
|
48
66
|
if (hostname.includes("aiforce-boe")) {
|
|
49
|
-
return
|
|
67
|
+
return "boe";
|
|
50
68
|
}
|
|
51
69
|
if (hostname.includes("aiforce-pre") || hostname.includes("force-pre.feishuapp.net") || hostname.includes("fsapp.kundou.cn")) {
|
|
52
|
-
return
|
|
70
|
+
return "staging";
|
|
53
71
|
}
|
|
54
72
|
if (hostname.includes("localhost") || hostname.includes("127.0.0.1")) {
|
|
55
|
-
return
|
|
73
|
+
return "development";
|
|
56
74
|
}
|
|
57
|
-
return
|
|
75
|
+
return "production";
|
|
76
|
+
}
|
|
77
|
+
__name(resolveIframeEnv, "resolveIframeEnv");
|
|
78
|
+
function getIframeBaseURL(env) {
|
|
79
|
+
return IFRAME_BASE_URL[resolveIframeEnv(env)];
|
|
58
80
|
}
|
|
59
81
|
__name(getIframeBaseURL, "getIframeBaseURL");
|
|
82
|
+
function getAgentIframeBaseURL(env) {
|
|
83
|
+
return AGENT_IFRAME_BASE_URL[resolveIframeEnv(env)];
|
|
84
|
+
}
|
|
85
|
+
__name(getAgentIframeBaseURL, "getAgentIframeBaseURL");
|
|
60
86
|
var MESSAGE_TIMEOUT = 30 * 1e3;
|
|
61
87
|
var DEFAULT_CHANNEL_TYPE = "MIAODA_CUI_SDK";
|
|
62
88
|
var DEFAULT_ANONYMOUS_CHANNEL_TYPE = "MIAODA_ANONYMOUS_CUI_SDK";
|
|
63
89
|
var ALLOWED_ORIGINS = [
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
90
|
+
IFRAME_ORIGIN.production,
|
|
91
|
+
IFRAME_ORIGIN.staging,
|
|
92
|
+
IFRAME_ORIGIN.boe,
|
|
67
93
|
"http://localhost:3000",
|
|
68
94
|
"http://localhost:5173",
|
|
69
|
-
|
|
95
|
+
IFRAME_ORIGIN.development
|
|
70
96
|
];
|
|
71
97
|
|
|
72
98
|
// src/iframe-manager.ts
|
|
@@ -117,7 +143,7 @@ var _MessageBridge = class _MessageBridge {
|
|
|
117
143
|
__publicField(this, "pendingRequests", /* @__PURE__ */ new Map());
|
|
118
144
|
__publicField(this, "eventHandlers", /* @__PURE__ */ new Map());
|
|
119
145
|
__publicField(this, "targetOrigin");
|
|
120
|
-
this.targetOrigin = targetOrigin;
|
|
146
|
+
this.targetOrigin = new URL(targetOrigin).origin;
|
|
121
147
|
this.handleMessage = this.handleMessage.bind(this);
|
|
122
148
|
}
|
|
123
149
|
/**
|
|
@@ -441,19 +467,102 @@ var _IframeManager = class _IframeManager {
|
|
|
441
467
|
__name(_IframeManager, "IframeManager");
|
|
442
468
|
var IframeManager = _IframeManager;
|
|
443
469
|
|
|
470
|
+
// src/agent-iframe-manager.ts
|
|
471
|
+
var _AgentIframeManager = class _AgentIframeManager {
|
|
472
|
+
constructor(root, config) {
|
|
473
|
+
__publicField(this, "iframe", null);
|
|
474
|
+
__publicField(this, "messageBridge");
|
|
475
|
+
__publicField(this, "config");
|
|
476
|
+
__publicField(this, "root");
|
|
477
|
+
this.root = root;
|
|
478
|
+
this.config = config;
|
|
479
|
+
this.messageBridge = new MessageBridge(getAgentIframeBaseURL());
|
|
480
|
+
}
|
|
481
|
+
async init() {
|
|
482
|
+
this.iframe = document.createElement("iframe");
|
|
483
|
+
this.iframe.src = this.buildIframeURL();
|
|
484
|
+
this.iframe.style.width = "100%";
|
|
485
|
+
this.iframe.style.height = "100%";
|
|
486
|
+
this.iframe.style.border = "none";
|
|
487
|
+
this.iframe.allow = "microphone; clipboard-write";
|
|
488
|
+
this.root.appendChild(this.iframe);
|
|
489
|
+
this.messageBridge.attach(this.iframe);
|
|
490
|
+
await this.waitForReady();
|
|
491
|
+
await this.messageBridge.send("initParentContext", this.buildParentContext());
|
|
492
|
+
return this.createAgentInstance();
|
|
493
|
+
}
|
|
494
|
+
async destroy() {
|
|
495
|
+
try {
|
|
496
|
+
await this.messageBridge.send("destroy");
|
|
497
|
+
} catch {
|
|
498
|
+
}
|
|
499
|
+
this.messageBridge.detach();
|
|
500
|
+
if (this.iframe?.parentNode) {
|
|
501
|
+
this.iframe.parentNode.removeChild(this.iframe);
|
|
502
|
+
}
|
|
503
|
+
this.iframe = null;
|
|
504
|
+
}
|
|
505
|
+
buildIframeURL() {
|
|
506
|
+
const baseURL = getAgentIframeBaseURL();
|
|
507
|
+
const params = new URLSearchParams({
|
|
508
|
+
channelToken: this.config.channelToken,
|
|
509
|
+
[PARENT_ORIGIN_QUERY_KEY]: window.location.origin
|
|
510
|
+
});
|
|
511
|
+
return `${baseURL}?${params.toString()}`;
|
|
512
|
+
}
|
|
513
|
+
buildParentContext() {
|
|
514
|
+
return {
|
|
515
|
+
parentOrigin: window.location.origin
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
waitForReady() {
|
|
519
|
+
return new Promise((resolve, reject) => {
|
|
520
|
+
const timeout = setTimeout(() => {
|
|
521
|
+
window.removeEventListener("message", checkMessage);
|
|
522
|
+
reject(new Error("Iframe ready timeout"));
|
|
523
|
+
}, 3e4);
|
|
524
|
+
const checkMessage = /* @__PURE__ */ __name((event) => {
|
|
525
|
+
if (event.data?.messageBizId === MESSAGE_BIZ_ID && event.data?.type === "event" && event.data?.eventName === "ready") {
|
|
526
|
+
clearTimeout(timeout);
|
|
527
|
+
window.removeEventListener("message", checkMessage);
|
|
528
|
+
resolve();
|
|
529
|
+
}
|
|
530
|
+
}, "checkMessage");
|
|
531
|
+
window.addEventListener("message", checkMessage);
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
createAgentInstance() {
|
|
535
|
+
return {
|
|
536
|
+
destroy: /* @__PURE__ */ __name(async () => {
|
|
537
|
+
await this.destroy();
|
|
538
|
+
}, "destroy")
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
__name(_AgentIframeManager, "AgentIframeManager");
|
|
543
|
+
var AgentIframeManager = _AgentIframeManager;
|
|
544
|
+
|
|
444
545
|
// src/index.ts
|
|
445
546
|
async function initAilyChat(root, config) {
|
|
446
547
|
const manager = new IframeManager(root, config);
|
|
447
548
|
return manager.init();
|
|
448
549
|
}
|
|
449
550
|
__name(initAilyChat, "initAilyChat");
|
|
551
|
+
async function initAgentChat(root, config) {
|
|
552
|
+
const manager = new AgentIframeManager(root, config);
|
|
553
|
+
return manager.init();
|
|
554
|
+
}
|
|
555
|
+
__name(initAgentChat, "initAgentChat");
|
|
450
556
|
// Annotate the CommonJS export names for ESM import in node:
|
|
451
557
|
0 && (module.exports = {
|
|
558
|
+
AGENT_IFRAME_BASE_URL,
|
|
452
559
|
DEFAULT_ANONYMOUS_CHANNEL_TYPE,
|
|
453
560
|
DEFAULT_CHANNEL_TYPE,
|
|
454
561
|
IFRAME_BASE_URL,
|
|
455
562
|
MESSAGE_TIMEOUT,
|
|
563
|
+
getAgentIframeBaseURL,
|
|
456
564
|
getIframeBaseURL,
|
|
565
|
+
initAgentChat,
|
|
457
566
|
initAilyChat
|
|
458
567
|
});
|
|
459
568
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/iframe-manager.ts","../src/device-detector.ts","../src/message-bridge.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\";\n\nimport type { ChatPanel, WebSDKConfig } 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// Export constants\nexport {\n\tDEFAULT_ANONYMOUS_CHANNEL_TYPE,\n\tDEFAULT_CHANNEL_TYPE,\n\tgetIframeBaseURL,\n\tIFRAME_BASE_URL,\n\tMESSAGE_TIMEOUT,\n} from \"./constants\";\n// Export types\nexport type {\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;\n\n/** Iframe base URLs by environment */\nexport const IFRAME_BASE_URL: Record<string, string> = {\n\tproduction: \"https://aily.feishu.cn/cui\",\n\tstaging: \"https://aily.feishu-pre.cn/cui\",\n\tboe: \"https://aily.feishu-boe.cn/cui\",\n\tdevelopment: \"http://localhost:8080/cui\",\n};\n\n/**\n * Get iframe base URL based on environment\n */\nexport function getIframeBaseURL(env?: string): string {\n\tif (env && IFRAME_BASE_URL[env]) {\n\t\treturn IFRAME_BASE_URL[env];\n\t}\n\n\t// Auto-detect based on hostname\n\t// MiaoDa 宿主域名: miaoda.feishu[-env].cn, *.aiforce[-env][-preview].bytedance.net, *.force-pre.feishuapp.net, *.fsapp.kundou.cn, *.aiforce.run, *.aiforce.cloud\n\tconst hostname =\n\t\ttypeof window !== \"undefined\" ? window.location.hostname : \"\";\n\n\tif (hostname.includes(\"aiforce-boe\")) {\n\t\treturn IFRAME_BASE_URL.boe;\n\t}\n\tif (\n\t\thostname.includes(\"aiforce-pre\") ||\n\t\thostname.includes(\"force-pre.feishuapp.net\") ||\n\t\thostname.includes(\"fsapp.kundou.cn\")\n\t) {\n\t\treturn IFRAME_BASE_URL.staging;\n\t}\n\tif (hostname.includes(\"localhost\") || hostname.includes(\"127.0.0.1\")) {\n\t\treturn IFRAME_BASE_URL.development;\n\t}\n\n\treturn IFRAME_BASE_URL.production;\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\t\"https://aily.feishu.cn\",\n\t\"https://aily.feishu-pre.cn\",\n\t\"https://aily.feishu-boe.cn\",\n\t\"http://localhost:3000\",\n\t\"http://localhost:5173\",\n\t\"http://localhost:8080\",\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 = targetOrigin;\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"],"mappings":"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","names":["MESSAGE_BIZ_ID","IFRAME_BASE_URL","production","staging","boe","development","getIframeBaseURL","env","hostname","window","location","includes","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","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","origin","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","initAilyChat","root","config","manager","IframeManager","init"]}
|
|
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\n/**\n * Get iframe base URL based on environment\n */\nfunction resolveIframeEnv(env?: string): keyof typeof IFRAME_BASE_URL {\n if (env && env in IFRAME_BASE_URL) {\n return env as keyof typeof IFRAME_BASE_URL;\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 if (hostname.includes('localhost') || hostname.includes('127.0.0.1')) {\n return 'development';\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","resolveIframeEnv","env","hostname","window","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"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -112,6 +112,9 @@ interface WebSDKConfig {
|
|
|
112
112
|
/** Event callbacks */
|
|
113
113
|
events?: WebSDKEvents;
|
|
114
114
|
}
|
|
115
|
+
interface AgentSDKInitConfig {
|
|
116
|
+
channelToken: string;
|
|
117
|
+
}
|
|
115
118
|
/**
|
|
116
119
|
* Chat panel control interface
|
|
117
120
|
* 与 aily-cui-sdk 的 ChatPanel 接口保持一致
|
|
@@ -143,13 +146,19 @@ interface ChatPanel {
|
|
|
143
146
|
/** Destroy the chat panel instance */
|
|
144
147
|
destroy: () => Promise<void>;
|
|
145
148
|
}
|
|
149
|
+
interface AgentSDKInstance {
|
|
150
|
+
destroy: () => Promise<void>;
|
|
151
|
+
}
|
|
146
152
|
|
|
147
|
-
/**
|
|
153
|
+
/** Chat iframe base URLs by environment */
|
|
148
154
|
declare const IFRAME_BASE_URL: Record<string, string>;
|
|
155
|
+
/** Agent iframe base URLs by environment */
|
|
156
|
+
declare const AGENT_IFRAME_BASE_URL: Record<string, string>;
|
|
157
|
+
declare function getIframeBaseURL(env?: string): string;
|
|
149
158
|
/**
|
|
150
|
-
* Get iframe base URL based on environment
|
|
159
|
+
* Get agent iframe base URL based on environment
|
|
151
160
|
*/
|
|
152
|
-
declare function
|
|
161
|
+
declare function getAgentIframeBaseURL(env?: string): string;
|
|
153
162
|
/** Timeout for postMessage requests (30 seconds) */
|
|
154
163
|
declare const MESSAGE_TIMEOUT: number;
|
|
155
164
|
/** Miaoda 渠道标识默认值(用户可通过 config.common.channelType 覆盖) */
|
|
@@ -161,7 +170,7 @@ declare const DEFAULT_ANONYMOUS_CHANNEL_TYPE = "MIAODA_ANONYMOUS_CUI_SDK";
|
|
|
161
170
|
*/
|
|
162
171
|
|
|
163
172
|
/** Message types for iframe communication */
|
|
164
|
-
type IframeMessageType = 'sendMessage' | 'clear' | 'cancelMessage' | 'clearAndStop' | 'updateWelcomeMessage' | 'updateConfig' | 'observeSkill' | 'setCurrentSkill' | 'destroy';
|
|
173
|
+
type IframeMessageType = 'sendMessage' | 'clear' | 'cancelMessage' | 'clearAndStop' | 'initParentContext' | 'updateWelcomeMessage' | 'updateConfig' | 'observeSkill' | 'setCurrentSkill' | 'destroy';
|
|
165
174
|
/** Request message from parent to iframe */
|
|
166
175
|
interface IframeRequestMessage {
|
|
167
176
|
messageBizId: 'cui-sdk-message';
|
|
@@ -204,5 +213,12 @@ type IframeMessage = IframeRequestMessage | IframeResponseMessage | IframeEventM
|
|
|
204
213
|
* @returns ChatPanel instance for controlling the chat
|
|
205
214
|
*/
|
|
206
215
|
declare function initAilyChat(root: HTMLElement, config: WebSDKConfig): Promise<ChatPanel>;
|
|
216
|
+
/**
|
|
217
|
+
* Initialize Agent Chat via iframe
|
|
218
|
+
* @param root - Container element for the iframe
|
|
219
|
+
* @param config - Agent SDK configuration
|
|
220
|
+
* @returns Agent SDK instance for controlling the agent page
|
|
221
|
+
*/
|
|
222
|
+
declare function initAgentChat(root: HTMLElement, config: AgentSDKInitConfig): Promise<AgentSDKInstance>;
|
|
207
223
|
|
|
208
|
-
export { 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, getIframeBaseURL, initAilyChat };
|
|
224
|
+
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -112,6 +112,9 @@ interface WebSDKConfig {
|
|
|
112
112
|
/** Event callbacks */
|
|
113
113
|
events?: WebSDKEvents;
|
|
114
114
|
}
|
|
115
|
+
interface AgentSDKInitConfig {
|
|
116
|
+
channelToken: string;
|
|
117
|
+
}
|
|
115
118
|
/**
|
|
116
119
|
* Chat panel control interface
|
|
117
120
|
* 与 aily-cui-sdk 的 ChatPanel 接口保持一致
|
|
@@ -143,13 +146,19 @@ interface ChatPanel {
|
|
|
143
146
|
/** Destroy the chat panel instance */
|
|
144
147
|
destroy: () => Promise<void>;
|
|
145
148
|
}
|
|
149
|
+
interface AgentSDKInstance {
|
|
150
|
+
destroy: () => Promise<void>;
|
|
151
|
+
}
|
|
146
152
|
|
|
147
|
-
/**
|
|
153
|
+
/** Chat iframe base URLs by environment */
|
|
148
154
|
declare const IFRAME_BASE_URL: Record<string, string>;
|
|
155
|
+
/** Agent iframe base URLs by environment */
|
|
156
|
+
declare const AGENT_IFRAME_BASE_URL: Record<string, string>;
|
|
157
|
+
declare function getIframeBaseURL(env?: string): string;
|
|
149
158
|
/**
|
|
150
|
-
* Get iframe base URL based on environment
|
|
159
|
+
* Get agent iframe base URL based on environment
|
|
151
160
|
*/
|
|
152
|
-
declare function
|
|
161
|
+
declare function getAgentIframeBaseURL(env?: string): string;
|
|
153
162
|
/** Timeout for postMessage requests (30 seconds) */
|
|
154
163
|
declare const MESSAGE_TIMEOUT: number;
|
|
155
164
|
/** Miaoda 渠道标识默认值(用户可通过 config.common.channelType 覆盖) */
|
|
@@ -161,7 +170,7 @@ declare const DEFAULT_ANONYMOUS_CHANNEL_TYPE = "MIAODA_ANONYMOUS_CUI_SDK";
|
|
|
161
170
|
*/
|
|
162
171
|
|
|
163
172
|
/** Message types for iframe communication */
|
|
164
|
-
type IframeMessageType = 'sendMessage' | 'clear' | 'cancelMessage' | 'clearAndStop' | 'updateWelcomeMessage' | 'updateConfig' | 'observeSkill' | 'setCurrentSkill' | 'destroy';
|
|
173
|
+
type IframeMessageType = 'sendMessage' | 'clear' | 'cancelMessage' | 'clearAndStop' | 'initParentContext' | 'updateWelcomeMessage' | 'updateConfig' | 'observeSkill' | 'setCurrentSkill' | 'destroy';
|
|
165
174
|
/** Request message from parent to iframe */
|
|
166
175
|
interface IframeRequestMessage {
|
|
167
176
|
messageBizId: 'cui-sdk-message';
|
|
@@ -204,5 +213,12 @@ type IframeMessage = IframeRequestMessage | IframeResponseMessage | IframeEventM
|
|
|
204
213
|
* @returns ChatPanel instance for controlling the chat
|
|
205
214
|
*/
|
|
206
215
|
declare function initAilyChat(root: HTMLElement, config: WebSDKConfig): Promise<ChatPanel>;
|
|
216
|
+
/**
|
|
217
|
+
* Initialize Agent Chat via iframe
|
|
218
|
+
* @param root - Container element for the iframe
|
|
219
|
+
* @param config - Agent SDK configuration
|
|
220
|
+
* @returns Agent SDK instance for controlling the agent page
|
|
221
|
+
*/
|
|
222
|
+
declare function initAgentChat(root: HTMLElement, config: AgentSDKInitConfig): Promise<AgentSDKInstance>;
|
|
207
223
|
|
|
208
|
-
export { 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, getIframeBaseURL, initAilyChat };
|
|
224
|
+
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 };
|
package/dist/index.js
CHANGED
|
@@ -5,39 +5,62 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
5
5
|
|
|
6
6
|
// src/constants.ts
|
|
7
7
|
var MESSAGE_BIZ_ID = "cui-sdk-message";
|
|
8
|
+
var PARENT_ORIGIN_QUERY_KEY = "__parentOrigin";
|
|
9
|
+
var IFRAME_ORIGIN = {
|
|
10
|
+
production: "https://aily.feishu.cn",
|
|
11
|
+
staging: "https://aily.feishu-pre.cn",
|
|
12
|
+
boe: "https://aily.feishu-boe.cn",
|
|
13
|
+
development: "http://localhost:8080"
|
|
14
|
+
};
|
|
15
|
+
var CHAT_IFRAME_PATH = "/cui";
|
|
16
|
+
var AGENT_IFRAME_PATH = "/custom_agent/cui";
|
|
8
17
|
var IFRAME_BASE_URL = {
|
|
9
|
-
production:
|
|
10
|
-
staging:
|
|
11
|
-
boe:
|
|
12
|
-
development:
|
|
18
|
+
production: `${IFRAME_ORIGIN.production}${CHAT_IFRAME_PATH}`,
|
|
19
|
+
staging: `${IFRAME_ORIGIN.staging}${CHAT_IFRAME_PATH}`,
|
|
20
|
+
boe: `${IFRAME_ORIGIN.boe}${CHAT_IFRAME_PATH}`,
|
|
21
|
+
development: `${IFRAME_ORIGIN.development}${CHAT_IFRAME_PATH}`
|
|
13
22
|
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
23
|
+
var AGENT_IFRAME_BASE_URL = {
|
|
24
|
+
production: `${IFRAME_ORIGIN.production}${AGENT_IFRAME_PATH}`,
|
|
25
|
+
staging: `${IFRAME_ORIGIN.staging}${AGENT_IFRAME_PATH}`,
|
|
26
|
+
boe: `${IFRAME_ORIGIN.boe}${AGENT_IFRAME_PATH}`,
|
|
27
|
+
development: `${IFRAME_ORIGIN.development}${AGENT_IFRAME_PATH}`
|
|
28
|
+
};
|
|
29
|
+
function resolveIframeEnv(env) {
|
|
30
|
+
if (env && env in IFRAME_BASE_URL) {
|
|
31
|
+
return env;
|
|
17
32
|
}
|
|
18
33
|
const hostname = typeof window !== "undefined" ? window.location.hostname : "";
|
|
19
34
|
if (hostname.includes("aiforce-boe")) {
|
|
20
|
-
return
|
|
35
|
+
return "boe";
|
|
21
36
|
}
|
|
22
37
|
if (hostname.includes("aiforce-pre") || hostname.includes("force-pre.feishuapp.net") || hostname.includes("fsapp.kundou.cn")) {
|
|
23
|
-
return
|
|
38
|
+
return "staging";
|
|
24
39
|
}
|
|
25
40
|
if (hostname.includes("localhost") || hostname.includes("127.0.0.1")) {
|
|
26
|
-
return
|
|
41
|
+
return "development";
|
|
27
42
|
}
|
|
28
|
-
return
|
|
43
|
+
return "production";
|
|
44
|
+
}
|
|
45
|
+
__name(resolveIframeEnv, "resolveIframeEnv");
|
|
46
|
+
function getIframeBaseURL(env) {
|
|
47
|
+
return IFRAME_BASE_URL[resolveIframeEnv(env)];
|
|
29
48
|
}
|
|
30
49
|
__name(getIframeBaseURL, "getIframeBaseURL");
|
|
50
|
+
function getAgentIframeBaseURL(env) {
|
|
51
|
+
return AGENT_IFRAME_BASE_URL[resolveIframeEnv(env)];
|
|
52
|
+
}
|
|
53
|
+
__name(getAgentIframeBaseURL, "getAgentIframeBaseURL");
|
|
31
54
|
var MESSAGE_TIMEOUT = 30 * 1e3;
|
|
32
55
|
var DEFAULT_CHANNEL_TYPE = "MIAODA_CUI_SDK";
|
|
33
56
|
var DEFAULT_ANONYMOUS_CHANNEL_TYPE = "MIAODA_ANONYMOUS_CUI_SDK";
|
|
34
57
|
var ALLOWED_ORIGINS = [
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
58
|
+
IFRAME_ORIGIN.production,
|
|
59
|
+
IFRAME_ORIGIN.staging,
|
|
60
|
+
IFRAME_ORIGIN.boe,
|
|
38
61
|
"http://localhost:3000",
|
|
39
62
|
"http://localhost:5173",
|
|
40
|
-
|
|
63
|
+
IFRAME_ORIGIN.development
|
|
41
64
|
];
|
|
42
65
|
|
|
43
66
|
// src/iframe-manager.ts
|
|
@@ -88,7 +111,7 @@ var _MessageBridge = class _MessageBridge {
|
|
|
88
111
|
__publicField(this, "pendingRequests", /* @__PURE__ */ new Map());
|
|
89
112
|
__publicField(this, "eventHandlers", /* @__PURE__ */ new Map());
|
|
90
113
|
__publicField(this, "targetOrigin");
|
|
91
|
-
this.targetOrigin = targetOrigin;
|
|
114
|
+
this.targetOrigin = new URL(targetOrigin).origin;
|
|
92
115
|
this.handleMessage = this.handleMessage.bind(this);
|
|
93
116
|
}
|
|
94
117
|
/**
|
|
@@ -412,18 +435,101 @@ var _IframeManager = class _IframeManager {
|
|
|
412
435
|
__name(_IframeManager, "IframeManager");
|
|
413
436
|
var IframeManager = _IframeManager;
|
|
414
437
|
|
|
438
|
+
// src/agent-iframe-manager.ts
|
|
439
|
+
var _AgentIframeManager = class _AgentIframeManager {
|
|
440
|
+
constructor(root, config) {
|
|
441
|
+
__publicField(this, "iframe", null);
|
|
442
|
+
__publicField(this, "messageBridge");
|
|
443
|
+
__publicField(this, "config");
|
|
444
|
+
__publicField(this, "root");
|
|
445
|
+
this.root = root;
|
|
446
|
+
this.config = config;
|
|
447
|
+
this.messageBridge = new MessageBridge(getAgentIframeBaseURL());
|
|
448
|
+
}
|
|
449
|
+
async init() {
|
|
450
|
+
this.iframe = document.createElement("iframe");
|
|
451
|
+
this.iframe.src = this.buildIframeURL();
|
|
452
|
+
this.iframe.style.width = "100%";
|
|
453
|
+
this.iframe.style.height = "100%";
|
|
454
|
+
this.iframe.style.border = "none";
|
|
455
|
+
this.iframe.allow = "microphone; clipboard-write";
|
|
456
|
+
this.root.appendChild(this.iframe);
|
|
457
|
+
this.messageBridge.attach(this.iframe);
|
|
458
|
+
await this.waitForReady();
|
|
459
|
+
await this.messageBridge.send("initParentContext", this.buildParentContext());
|
|
460
|
+
return this.createAgentInstance();
|
|
461
|
+
}
|
|
462
|
+
async destroy() {
|
|
463
|
+
try {
|
|
464
|
+
await this.messageBridge.send("destroy");
|
|
465
|
+
} catch {
|
|
466
|
+
}
|
|
467
|
+
this.messageBridge.detach();
|
|
468
|
+
if (this.iframe?.parentNode) {
|
|
469
|
+
this.iframe.parentNode.removeChild(this.iframe);
|
|
470
|
+
}
|
|
471
|
+
this.iframe = null;
|
|
472
|
+
}
|
|
473
|
+
buildIframeURL() {
|
|
474
|
+
const baseURL = getAgentIframeBaseURL();
|
|
475
|
+
const params = new URLSearchParams({
|
|
476
|
+
channelToken: this.config.channelToken,
|
|
477
|
+
[PARENT_ORIGIN_QUERY_KEY]: window.location.origin
|
|
478
|
+
});
|
|
479
|
+
return `${baseURL}?${params.toString()}`;
|
|
480
|
+
}
|
|
481
|
+
buildParentContext() {
|
|
482
|
+
return {
|
|
483
|
+
parentOrigin: window.location.origin
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
waitForReady() {
|
|
487
|
+
return new Promise((resolve, reject) => {
|
|
488
|
+
const timeout = setTimeout(() => {
|
|
489
|
+
window.removeEventListener("message", checkMessage);
|
|
490
|
+
reject(new Error("Iframe ready timeout"));
|
|
491
|
+
}, 3e4);
|
|
492
|
+
const checkMessage = /* @__PURE__ */ __name((event) => {
|
|
493
|
+
if (event.data?.messageBizId === MESSAGE_BIZ_ID && event.data?.type === "event" && event.data?.eventName === "ready") {
|
|
494
|
+
clearTimeout(timeout);
|
|
495
|
+
window.removeEventListener("message", checkMessage);
|
|
496
|
+
resolve();
|
|
497
|
+
}
|
|
498
|
+
}, "checkMessage");
|
|
499
|
+
window.addEventListener("message", checkMessage);
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
createAgentInstance() {
|
|
503
|
+
return {
|
|
504
|
+
destroy: /* @__PURE__ */ __name(async () => {
|
|
505
|
+
await this.destroy();
|
|
506
|
+
}, "destroy")
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
__name(_AgentIframeManager, "AgentIframeManager");
|
|
511
|
+
var AgentIframeManager = _AgentIframeManager;
|
|
512
|
+
|
|
415
513
|
// src/index.ts
|
|
416
514
|
async function initAilyChat(root, config) {
|
|
417
515
|
const manager = new IframeManager(root, config);
|
|
418
516
|
return manager.init();
|
|
419
517
|
}
|
|
420
518
|
__name(initAilyChat, "initAilyChat");
|
|
519
|
+
async function initAgentChat(root, config) {
|
|
520
|
+
const manager = new AgentIframeManager(root, config);
|
|
521
|
+
return manager.init();
|
|
522
|
+
}
|
|
523
|
+
__name(initAgentChat, "initAgentChat");
|
|
421
524
|
export {
|
|
525
|
+
AGENT_IFRAME_BASE_URL,
|
|
422
526
|
DEFAULT_ANONYMOUS_CHANNEL_TYPE,
|
|
423
527
|
DEFAULT_CHANNEL_TYPE,
|
|
424
528
|
IFRAME_BASE_URL,
|
|
425
529
|
MESSAGE_TIMEOUT,
|
|
530
|
+
getAgentIframeBaseURL,
|
|
426
531
|
getIframeBaseURL,
|
|
532
|
+
initAgentChat,
|
|
427
533
|
initAilyChat
|
|
428
534
|
};
|
|
429
535
|
//# sourceMappingURL=index.js.map
|
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/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;\n\n/** Iframe base URLs by environment */\nexport const IFRAME_BASE_URL: Record<string, string> = {\n\tproduction: \"https://aily.feishu.cn/cui\",\n\tstaging: \"https://aily.feishu-pre.cn/cui\",\n\tboe: \"https://aily.feishu-boe.cn/cui\",\n\tdevelopment: \"http://localhost:8080/cui\",\n};\n\n/**\n * Get iframe base URL based on environment\n */\nexport function getIframeBaseURL(env?: string): string {\n\tif (env && IFRAME_BASE_URL[env]) {\n\t\treturn IFRAME_BASE_URL[env];\n\t}\n\n\t// Auto-detect based on hostname\n\t// MiaoDa 宿主域名: miaoda.feishu[-env].cn, *.aiforce[-env][-preview].bytedance.net, *.force-pre.feishuapp.net, *.fsapp.kundou.cn, *.aiforce.run, *.aiforce.cloud\n\tconst hostname =\n\t\ttypeof window !== \"undefined\" ? window.location.hostname : \"\";\n\n\tif (hostname.includes(\"aiforce-boe\")) {\n\t\treturn IFRAME_BASE_URL.boe;\n\t}\n\tif (\n\t\thostname.includes(\"aiforce-pre\") ||\n\t\thostname.includes(\"force-pre.feishuapp.net\") ||\n\t\thostname.includes(\"fsapp.kundou.cn\")\n\t) {\n\t\treturn IFRAME_BASE_URL.staging;\n\t}\n\tif (hostname.includes(\"localhost\") || hostname.includes(\"127.0.0.1\")) {\n\t\treturn IFRAME_BASE_URL.development;\n\t}\n\n\treturn IFRAME_BASE_URL.production;\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\t\"https://aily.feishu.cn\",\n\t\"https://aily.feishu-pre.cn\",\n\t\"https://aily.feishu-boe.cn\",\n\t\"http://localhost:3000\",\n\t\"http://localhost:5173\",\n\t\"http://localhost:8080\",\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 = targetOrigin;\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","/*\n * index.ts\n * Author: perterpon.wang<perterpon.wang@bytedance.com>\n * Create: Tue Feb 10 2026\n */\n\nimport { IframeManager } from \"./iframe-manager\";\n\nimport type { ChatPanel, WebSDKConfig } 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// Export constants\nexport {\n\tDEFAULT_ANONYMOUS_CHANNEL_TYPE,\n\tDEFAULT_CHANNEL_TYPE,\n\tgetIframeBaseURL,\n\tIFRAME_BASE_URL,\n\tMESSAGE_TIMEOUT,\n} from \"./constants\";\n// Export types\nexport type {\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","IFRAME_BASE_URL","production","staging","boe","development","getIframeBaseURL","env","hostname","window","location","includes","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","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","origin","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","initAilyChat","root","config","manager","IframeManager","init"]}
|
|
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\n/**\n * Get iframe base URL based on environment\n */\nfunction resolveIframeEnv(env?: string): keyof typeof IFRAME_BASE_URL {\n if (env && env in IFRAME_BASE_URL) {\n return env as keyof typeof IFRAME_BASE_URL;\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 if (hostname.includes('localhost') || hostname.includes('127.0.0.1')) {\n return 'development';\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":";;;;;;AAKO,IAAMA,iBAAiB;AACvB,IAAMC,0BAA0B;AAGhC,IAAMC,gBAAwC;EACnDC,YAAY;EACZC,SAAS;EACTC,KAAK;EACLC,aAAa;AACf;AAGO,IAAMC,mBAAmB;AACzB,IAAMC,oBAAoB;AAG1B,IAAMC,kBAA0C;EACrDN,YAAY,GAAGD,cAAcC,UAAU,GAAGI,gBAAAA;EAC1CH,SAAS,GAAGF,cAAcE,OAAO,GAAGG,gBAAAA;EACpCF,KAAK,GAAGH,cAAcG,GAAG,GAAGE,gBAAAA;EAC5BD,aAAa,GAAGJ,cAAcI,WAAW,GAAGC,gBAAAA;AAC9C;AAGO,IAAMG,wBAAgD;EAC3DP,YAAY,GAAGD,cAAcC,UAAU,GAAGK,iBAAAA;EAC1CJ,SAAS,GAAGF,cAAcE,OAAO,GAAGI,iBAAAA;EACpCH,KAAK,GAAGH,cAAcG,GAAG,GAAGG,iBAAAA;EAC5BF,aAAa,GAAGJ,cAAcI,WAAW,GAAGE,iBAAAA;AAC9C;AAKA,SAASG,iBAAiBC,KAAY;AACpC,MAAIA,OAAOA,OAAOH,iBAAiB;AACjC,WAAOG;EACT;AAIA,QAAMC,WACJ,OAAOC,WAAW,cAAcA,OAAOC,SAASF,WAAW;AAE7D,MAAIA,SAASG,SAAS,aAAA,GAAgB;AACpC,WAAO;EACT;AACA,MACEH,SAASG,SAAS,aAAA,KAClBH,SAASG,SAAS,yBAAA,KAClBH,SAASG,SAAS,iBAAA,GAClB;AACA,WAAO;EACT;AACA,MAAIH,SAASG,SAAS,WAAA,KAAgBH,SAASG,SAAS,WAAA,GAAc;AACpE,WAAO;EACT;AAEA,SAAO;AACT;AAzBSL;AA2BF,SAASM,iBAAiBL,KAAY;AAC3C,SAAOH,gBAAgBE,iBAAiBC,GAAAA,CAAAA;AAC1C;AAFgBK;AAOT,SAASC,sBAAsBN,KAAY;AAChD,SAAOF,sBAAsBC,iBAAiBC,GAAAA,CAAAA;AAChD;AAFgBM;AAKT,IAAMC,kBAAkB,KAAK;AAG7B,IAAMC,uBAAuB;AAC7B,IAAMC,iCAAiC;AAGvC,IAAMC,kBAAkB;EAC7BpB,cAAcC;EACdD,cAAcE;EACdF,cAAcG;EACd;EACA;EACAH,cAAcI;;;;ACrFhB,SAASiB,WAAAA,gBAAe;;;ACNxB,IAAMC,oBAAoB;AAWnB,IAAMC,kBAAN,MAAMA,gBAAAA;EAMX,cAAc;AALNC;AACAC;AACAC,oCAAwC;AACxCC,wCAAoC;AAG1C,SAAKH,aAAaI,OAAOC,WAAW,eAAeP,oBAAoB,CAAA,KAAM;AAC7E,SAAKG,gBAAgBG,OAAOE,aAAaR,oBAAoB,WAAW;EAC1E;EAEAS,YAAwB;AACtB,WAAO,KAAKN;EACd;EAEAO,QAAQN,UAAsC;AAC5C,SAAKA,WAAWA;AAChB,SAAKC,eAAe,MAAA;AAClB,YAAMM,YAAwBL,OAAOE,aAAaR,oBAAoB,WAAW;AACjF,UAAIW,cAAc,KAAKR,eAAe;AACpC,aAAKA,gBAAgBQ;AACrB,aAAKP,WAAWO,SAAAA;MAClB;IACF;AACA,SAAKT,WAAWU,iBAAiB,UAAU,KAAKP,YAAY;EAC9D;EAEAQ,UAAgB;AACd,QAAI,KAAKR,cAAc;AACrB,WAAKH,WAAWY,oBAAoB,UAAU,KAAKT,YAAY;AAC/D,WAAKA,eAAe;IACtB;AACA,SAAKD,WAAW;EAClB;AACF;AAlCaH;AAAN,IAAMA,iBAAN;;;ACFP,SAASc,eAAe;AAWjB,IAAMC,iBAAN,MAAMA,eAAAA;EAOX,YAAYC,cAAsB;AAN1BC,kCAAmC;AACnCC,qCAAY;AACZC,2CAAkB,oBAAIC,IAAAA;AACtBC,yCAAgB,oBAAID,IAAAA;AACpBJ;AAGN,SAAKA,eAAe,IAAIM,IAAIN,YAAAA,EAAcO;AAC1C,SAAKC,gBAAgB,KAAKA,cAAcC,KAAK,IAAI;EACnD;;;;EAKAC,OAAOT,QAAiC;AACtC,SAAKA,SAASA;AACdU,WAAOC,iBAAiB,WAAW,KAAKJ,aAAa;EACvD;;;;EAKAK,SAAe;AACbF,WAAOG,oBAAoB,WAAW,KAAKN,aAAa;AACxD,SAAKP,SAAS;AAEd,SAAKE,gBAAgBY,QAAQ,CAAC,EAAEC,OAAM,MAAE;AACtCA,aAAO,IAAIC,MAAM,wBAAA,CAAA;IACnB,CAAA;AACA,SAAKd,gBAAgBe,MAAK;EAC5B;;;;EAKAC,KAAkBC,MAAyBC,MAA4B;AACrE,WAAO,IAAIC,QAAQ,CAACC,SAASP,WAAAA;AAC3B,UAAI,CAAC,KAAKf,QAAQuB,eAAe;AAC/BR,eAAO,IAAIC,MAAM,qBAAA,CAAA;AACjB;MACF;AAEA,WAAKf,aAAa;AAClB,YAAMuB,KAAK,KAAKvB;AAChB,YAAMwB,UAAgC;QACpCC,cAAcC;QACdH;QACAL;QACAC;QACAQ,WAAWC,KAAKC,IAAG;QACnBC,WAAW;MACb;AAEA,YAAMC,QAAQC,WAAW,MAAA;AACvB,aAAK/B,gBAAgBgC,OAAOV,EAAAA;AAC5B,cAAMW,QAAQ,IAAInB,MAAM,oBAAoBG,IAAAA,EAAM;AAClDiB,gBAAQC,iBAAiBF,OAAO;UAAEG,QAAQ;UAAgBC,QAAQ;UAAkBC,aAAarB;QAAK,CAAA;AACtGJ,eAAOoB,KAAAA;MACT,GAAGM,eAAAA;AAEH,WAAKvC,gBAAgBwC,IAAIlB,IAAI;QAAEF;QAA8CP;QAAQiB;MAAM,CAAA;AAE3F,WAAKhC,OAAOuB,cAAcoB,YAAYlB,SAAS,KAAK1B,YAAY;IAClE,CAAA;EACF;;;;EAKA6C,QAAQC,WAAmBC,SAAwC;AACjE,UAAMC,WAAW,KAAK3C,cAAc4C,IAAIH,SAAAA,KAAc,CAAA;AACtDE,aAASE,KAAKH,OAAAA;AACd,SAAK1C,cAAcsC,IAAIG,WAAWE,QAAAA;EACpC;;;;EAKAG,SAASL,WAAmBC,SAAwC;AAClE,UAAMC,WAAW,KAAK3C,cAAc4C,IAAIH,SAAAA,KAAc,CAAA;AACtD,UAAMM,QAAQJ,SAASK,QAAQN,OAAAA;AAC/B,QAAIK,QAAQ,IAAI;AACdJ,eAASM,OAAOF,OAAO,CAAA;AACvB,WAAK/C,cAAcsC,IAAIG,WAAWE,QAAAA;IACpC;EACF;EAEQxC,cAAc+C,OAA0C;AAE9D,QAAI,CAACC,gBAAgBC,SAASF,MAAMhD,MAAM,GAAG;AAC3C;IACF;AAEA,UAAM,EAAEc,KAAI,IAAKkC;AAGjB,QAAIlC,MAAMM,iBAAiBC,gBAAgB;AACzC;IACF;AAGA,QAAI,KAAK8B,kBAAkBrC,IAAAA,GAAO;AAChC,YAAMsC,UAAU,KAAKxD,gBAAgB8C,IAAI5B,KAAKI,EAAE;AAChD,UAAIkC,SAAS;AACXC,qBAAaD,QAAQ1B,KAAK;AAC1B,aAAK9B,gBAAgBgC,OAAOd,KAAKI,EAAE;AAEnC,YAAIJ,KAAKe,OAAO;AACd,gBAAMA,QAAQ,IAAInB,MAAMI,KAAKe,MAAMV,OAAO;AAC1CW,kBAAQC,iBAAiBF,OAAO;YAAEG,QAAQ;YAAgBC,QAAQ;YAAkBqB,WAAWxC,KAAKe,MAAM0B;UAAK,CAAA;AAC/GH,kBAAQ3C,OAAOoB,KAAAA;QACjB,OAAO;AACLuB,kBAAQpC,QAAQF,KAAKA,IAAI;QAC3B;MACF;IACF;AAGA,QAAI,KAAK0C,eAAe1C,IAAAA,GAAO;AAC7B,YAAM2B,WAAW,KAAK3C,cAAc4C,IAAI5B,KAAKyB,SAAS,KAAK,CAAA;AAC3DE,eAASjC,QAAQ,CAACgC,YAAAA;AAChB,YAAI;AACFA,kBAAQ1B,KAAKA,IAAI;QACnB,QAAQ;QAER;MACF,CAAA;IACF;EACF;EAEQqC,kBAAkBrC,MAAoD;AAC5E,WAAO,gBAAgBA,QAAQA,KAAK2C,eAAe;EACrD;EAEQD,eAAe1C,MAAiD;AACtE,WAAOA,KAAKD,SAAS;EACvB;AACF;AA1IarB;AAAN,IAAMA,gBAAN;;;AFFA,IAAMkE,iBAAN,MAAMA,eAAAA;EAQZ,YAAYC,MAAmBC,QAAsB;AAP7CC,kCAAmC;AACnCC;AACAF;AACAG;AACAJ;AACAK,0CAAwC;AAG/C,SAAKL,OAAOA;AACZ,SAAKC,SAASA;AACd,UAAMK,iBAAiBL,OAAOM,YAC3BC,iCACAC;AACH,SAAKL,cAAcH,OAAOS,QAAQN,eAAeE;AACjD,SAAKH,gBAAgB,IAAIQ,cAAcC,iBAAAA,CAAAA;EACxC;;;;;EAMA,MAAMC,OAA2B;AAChC,UAAMC,YAAYC,YAAYC,IAAG;AAGjC,QAAI,CAAC,KAAKf,OAAOgB,QAAQ;AACxB,WAAKZ,iBAAiB,IAAIa,eAAAA;AAC1B,WAAKjB,OAAOgB,SAAS,KAAKZ,eAAec,UAAS;IACnD;AAGA,SAAKjB,SAASkB,SAASC,cAAc,QAAA;AACrC,SAAKnB,OAAOoB,MAAM,KAAKC,eAAc;AACrC,SAAKrB,OAAOsB,MAAMC,QAAQ;AAC1B,SAAKvB,OAAOsB,MAAME,SAAS;AAC3B,SAAKxB,OAAOsB,MAAMG,SAAS;AAC3B,SAAKzB,OAAO0B,QAAQ;AAGpB,SAAK5B,KAAK6B,YAAY,KAAK3B,MAAM;AAGjC,SAAKC,cAAc2B,OAAO,KAAK5B,MAAM;AAGrC,SAAK6B,mBAAkB;AAGvB,QAAI,KAAK1B,gBAAgB;AACxB,WAAKA,eAAe2B,QAAQ,CAACC,cAAAA;AAC5B,aAAK9B,cAAc+B,KAAK,gBAAgB;UAAEjB,QAAQgB;QAAU,CAAA;MAC7D,CAAA;IACD;AAGA,UAAM,KAAKE,aAAY;AAGvB,SAAKC,kBAAkBtB,SAAAA;AAGvB,WAAO,KAAKuB,gBAAe;EAC5B;;;;EAKA,MAAMC,UAAyB;AAC9B,QAAI;AACH,YAAM,KAAKnC,cAAc+B,KAAK,SAAA;IAC/B,QAAQ;IAER;AAEA,SAAK/B,cAAcoC,OAAM;AAEzB,QAAI,KAAKlC,gBAAgB;AACxB,WAAKA,eAAeiC,QAAO;AAC3B,WAAKjC,iBAAiB;IACvB;AAEA,QAAI,KAAKH,QAAQsC,YAAY;AAC5B,WAAKtC,OAAOsC,WAAWC,YAAY,KAAKvC,MAAM;IAC/C;AAEA,SAAKA,SAAS;EACf;;;;;;;;EASQqB,iBAAyB;AAChC,UAAMmB,UAAU9B,iBAAAA;AAGhB,UAAM,EACL+B,QAAQC,SACRrC,WAAWsC,YACX,GAAGC,oBAAAA,IACA,KAAK7C;AAGT,UAAM8C,eAAeD,oBAAoBE,QAAQC,QAC9C;MACA,GAAGH,oBAAoBE;MACvBC,OAAO;QACNC,MAAM;QACNC,aAAa;QACb,GAAGL,oBAAoBE,OAAOC;MAC/B;IACD,IACCH,oBAAoBE;AAEvB,UAAMI,eAAe;MACpB,GAAGN;MACHpC,QAAQ;QACP,GAAGoC,oBAAoBpC;QACvBN,aAAa,KAAKA;QAClBiD,cACCP,oBAAoBpC,QAAQ2C,gBAAgB,KAAKjD;MACnD;MACA4C,QAAQD;IACT;AACA,UAAMO,eAAeC,KAAKC,mBAAmBC,KAAKC,UAAUN,YAAAA,CAAAA,CAAAA;AAE5D,UAAMO,SAAS,IAAIC,gBAAgB;MAClCC,QAAQ,KAAK5D,OAAO4D;MACpB5D,QAAQuD,mBAAmBF,YAAAA;IAC5B,CAAA;AAEA,WAAO,GAAGZ,OAAAA,IAAWiB,OAAOG,SAAQ,CAAA;EACrC;;;;EAKQ3B,eAA8B;AACrC,WAAO,IAAI4B,QAAQ,CAACC,SAASC,WAAAA;AAC5B,YAAMC,UAAUC,WAAW,MAAA;AAC1B,cAAMC,QAAQ,IAAIC,MAAM,sBAAA;AACxBC,QAAAA,SAAQC,iBAAiBH,OAAO;UAAEI,QAAQ;UAAgBC,QAAQ;QAAe,CAAA;AACjFR,eAAOG,KAAAA;MACR,GAAG,GAAA;AAEH,YAAMM,eAAe,wBAACC,UAAAA;AACrB,YACCA,MAAMC,MAAMC,iBAAiBC,kBAC7BH,MAAMC,MAAM1B,SAAS,WACrByB,MAAMC,MAAMG,cAAc,SACzB;AACDC,uBAAad,OAAAA;AACbe,iBAAOC,oBAAoB,WAAWR,YAAAA;AACtCV,kBAAAA;QACD;MACD,GAVqB;AAYrBiB,aAAOE,iBAAiB,WAAWT,YAAAA;IACpC,CAAA;EACD;EAEQ3C,qBAA2B;AAClC,UAAM,EAAEY,OAAM,IAAK,KAAK1C;AACxB,QAAI,CAAC0C,OAAQ;AAEb,QAAIA,OAAOyC,SAAS;AACnB,WAAKjF,cAAckF,QAAQ,SAAS1C,OAAOyC,OAAO;IACnD;AAEA,QAAIzC,OAAO2C,SAAS;AACnB,WAAKnF,cAAckF,QAAQ,SAAS,CAACT,SAAAA;AACpC,cAAMW,MAAOX,MAA+BY,WAAW;AACvD7C,eAAO2C,UAAU,IAAIjB,MAAMkB,GAAAA,CAAAA;MAC5B,CAAA;IACD;AAEA,QAAI5C,OAAO8C,WAAW;AACrB,WAAKtF,cAAckF,QAAQ,aAAa1C,OAAO8C,SAAS;IACzD;AAEA,QAAI9C,OAAO+C,UAAU;AACpB,WAAKvF,cAAckF,QAClB,UACA1C,OAAO+C,QAAQ;IAEjB;AAEA,QAAI/C,OAAOgD,qBAAqB;AAC/B,WAAKxF,cAAckF,QAClB,qBACA1C,OAAOgD,mBAAmB;IAE5B;AAEA,QAAIhD,OAAOiD,SAAS;AACnB,WAAKzF,cAAckF,QAAQ,WAAW1C,OAAOiD,OAAO;IACrD;EACD;EAEQxD,kBAAkBtB,WAAyB;AAClD,QAAI;AACH,YAAM+E,OAAO9E,YAAYC,IAAG,IAAKF;AACjCwD,MAAAA,SAAQwB,UAAU;QACjBC,MAAM;QACNC,SAAS;UAAEH;QAAK;QAChBI,YAAY;UACXC,MAAM;UACNrC,QAAQ,KAAK5D,OAAO4D;UACpBzD,aAAa,KAAKA;QACnB;MACD,CAAA;IACD,QAAQ;IAER;EACD;EAEQiC,kBAA6B;AACpC,WAAO;MACN8D,aAAa,8BAAOvB,SAAAA;AACnB,cAAM,KAAKzE,cAAc+B,KAAK,eAAe0C,IAAAA;MAC9C,GAFa;MAGbwB,OAAO,mCAAA;AACN,cAAM,KAAKjG,cAAc+B,KAAK,OAAA;MAC/B,GAFO;MAGPmE,eAAe,8BAAOC,gBAAAA;AACrB,cAAM,KAAKnG,cAAc+B,KAAK,iBAAiBoE,WAAAA;MAChD,GAFe;MAGfC,cAAc,mCAAA;AACb,cAAM,KAAKpG,cAAc+B,KAAK,cAAA;MAC/B,GAFc;MAGdsE,sBAAsB,mCAAA;AACrB,cAAM,KAAKrG,cAAc+B,KAAK,sBAAA;MAC/B,GAFsB;MAGtBuE,cAAc,8BAAOxG,WAAAA;AACpB,cAAM,KAAKE,cAAc+B,KAAK,gBAAgBjC,MAAAA;MAC/C,GAFc;MAGdyG,cAAc,8BAAOC,SAASZ,MAAMa,cAAAA;AACnC,cAAM,KAAKzG,cAAc+B,KAAK,gBAAgB;UAC7CyE;UACAZ;UACAa;QACD,CAAA;MACD,GANc;MAOdC,iBAAiB,8BAAO5D,UAAAA;AACvB,cAAM,KAAK9C,cAAc+B,KAAK,mBAAmBe,KAAAA;MAClD,GAFiB;MAGjBX,SAAS,mCAAA;AACR,cAAM,KAAKA,QAAO;MACnB,GAFS;IAGV;EACD;AACD;AA/PavC;AAAN,IAAMA,gBAAN;;;AGLA,IAAM+G,sBAAN,MAAMA,oBAAAA;EAMX,YAAYC,MAAmBC,QAA4B;AALnDC,kCAAmC;AAC1BC;AACAF;AACAD;AAGf,SAAKA,OAAOA;AACZ,SAAKC,SAASA;AACd,SAAKE,gBAAgB,IAAIC,cAAcC,sBAAAA,CAAAA;EACzC;EAEA,MAAMC,OAAkC;AACtC,SAAKJ,SAASK,SAASC,cAAc,QAAA;AACrC,SAAKN,OAAOO,MAAM,KAAKC,eAAc;AACrC,SAAKR,OAAOS,MAAMC,QAAQ;AAC1B,SAAKV,OAAOS,MAAME,SAAS;AAC3B,SAAKX,OAAOS,MAAMG,SAAS;AAC3B,SAAKZ,OAAOa,QAAQ;AAEpB,SAAKf,KAAKgB,YAAY,KAAKd,MAAM;AACjC,SAAKC,cAAcc,OAAO,KAAKf,MAAM;AAErC,UAAM,KAAKgB,aAAY;AACvB,UAAM,KAAKf,cAAcgB,KACvB,qBACA,KAAKC,mBAAkB,CAAA;AAGzB,WAAO,KAAKC,oBAAmB;EACjC;EAEA,MAAMC,UAAyB;AAC7B,QAAI;AACF,YAAM,KAAKnB,cAAcgB,KAAK,SAAA;IAChC,QAAQ;IAER;AAEA,SAAKhB,cAAcoB,OAAM;AAEzB,QAAI,KAAKrB,QAAQsB,YAAY;AAC3B,WAAKtB,OAAOsB,WAAWC,YAAY,KAAKvB,MAAM;IAChD;AAEA,SAAKA,SAAS;EAChB;EAEQQ,iBAAyB;AAC/B,UAAMgB,UAAUrB,sBAAAA;AAChB,UAAMsB,SAAS,IAAIC,gBAAgB;MACjCC,cAAc,KAAK5B,OAAO4B;MAC1B,CAACC,uBAAAA,GAA0BC,OAAOC,SAASC;IAC7C,CAAA;AAEA,WAAO,GAAGP,OAAAA,IAAWC,OAAOO,SAAQ,CAAA;EACtC;EAEQd,qBAA+C;AACrD,WAAO;MACLe,cAAcJ,OAAOC,SAASC;IAChC;EACF;EAEQf,eAA8B;AACpC,WAAO,IAAIkB,QAAQ,CAACC,SAASC,WAAAA;AAC3B,YAAMC,UAAUC,WAAW,MAAA;AACzBT,eAAOU,oBAAoB,WAAWC,YAAAA;AACtCJ,eAAO,IAAIK,MAAM,sBAAA,CAAA;MACnB,GAAG,GAAA;AAEH,YAAMD,eAAe,wBAACE,UAAAA;AACpB,YACEA,MAAMC,MAAMC,iBAAiBC,kBAC7BH,MAAMC,MAAMG,SAAS,WACrBJ,MAAMC,MAAMI,cAAc,SAC1B;AACAC,uBAAaX,OAAAA;AACbR,iBAAOU,oBAAoB,WAAWC,YAAAA;AACtCL,kBAAAA;QACF;MACF,GAVqB;AAYrBN,aAAOoB,iBAAiB,WAAWT,YAAAA;IACrC,CAAA;EACF;EAEQrB,sBAAwC;AAC9C,WAAO;MACLC,SAAS,mCAAA;AACP,cAAM,KAAKA,QAAO;MACpB,GAFS;IAGX;EACF;AACF;AA9FavB;AAAN,IAAMA,qBAAN;;;ACUP,eAAsBqD,aACrBC,MACAC,QAAoB;AAEpB,QAAMC,UAAU,IAAIC,cAAcH,MAAMC,MAAAA;AACxC,SAAOC,QAAQE,KAAI;AACpB;AANsBL;AActB,eAAsBM,cACrBL,MACAC,QAA0B;AAE1B,QAAMC,UAAU,IAAII,mBAAmBN,MAAMC,MAAAA;AAC7C,SAAOC,QAAQE,KAAI;AACpB;AANsBC;","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","resolveIframeEnv","env","hostname","window","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"]}
|