@sophonsai/agent-embed-sdk 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,17 +2,13 @@
2
2
 
3
3
  ## 应用接入
4
4
 
5
- 传入服务地址 `endpoint` 和 Agent 的应用接入 `token`;可选 `baseUrl` 默认是 `/e/v1/embed`。
6
- 最终 iframe 地址是 `endpoint + baseUrl + '/' + encodeURIComponent(token)`。
5
+ 传入 SAAP 服务地址 `endpoint` 和智能体的应用接入凭证 `token`。
7
6
 
8
7
  ```ts
9
8
  const client = createAgentEmbed({ endpoint: 'https://agent.example.com', token: '应用接入Token' })
10
9
  await client.mount(document.getElementById('agent-embed')!)
11
10
  ```
12
11
 
13
- 不再接收完整 `url`、旧 `initConfig`、Agent ID 或平台用户凭证。
14
- `threadId`、外观配置、实例命令和事件回调继续支持。
15
-
16
12
  ## 安装
17
13
 
18
14
  ```bash
@@ -82,15 +78,13 @@ client.destroy()
82
78
 
83
79
  | 配置 | 类型 | 必填 | 说明 |
84
80
  | ------------------- | ----------------------- | ---- | ----------------------------------------------- |
85
- | `endpoint` | `string` | 是 | Gateway / Extension 服务地址,包含 HTTP(S) 协议 |
81
+ | `endpoint` | `string` | 是 | SAAP 服务地址,包含 HTTP(S) 协议 |
86
82
  | `token` | `string` | 是 | Agent 应用接入凭证 |
87
- | `baseUrl` | `string` | 否 | 嵌入页面路径,默认 `/e/v1/embed` |
88
83
  | `threadId` | `string` | 否 | 初始会话 ID |
89
84
  | `runtime_variables` | `AgentRuntimeVariables` | 否 | 新会话绑定的运行时变量,值必须为 JSON |
90
85
  | `appearance` | `AgentAppearance` | 否 | 主题、字号与 Header 按钮 |
91
86
 
92
- `endpoint` 可包含反向代理路径前缀;`baseUrl` 必须是以 `/` 开头的路径。
93
- 凭证只写入 iframe 路径,bridge 初始化消息不再传递凭证或 Agent ID。
87
+ `endpoint` 可包含反向代理路径前缀。
94
88
  配置与回调在创建 client 时保存为快照;切换接入地址、token、会话或回调时,销毁并重新创建 client。
95
89
  外观可以使用 `updateTheme`、`updateFontSize`、`updateHeader` 更新。
96
90
 
@@ -108,7 +102,7 @@ const appearance: AgentAppearance = {
108
102
  }
109
103
  ```
110
104
 
111
- `header.themeSettingButton` 默认值为 `false`,只有显式设置为 `true` 时才显示主题设置按钮。
105
+ `header.themeSettingButton` 默认值为 `true`,显式设置为 `false` 时隐藏主题设置按钮。
112
106
 
113
107
  ### 可用主题
114
108
 
@@ -247,6 +241,8 @@ agent.focusInput()
247
241
 
248
242
  ## 会话事件
249
243
 
244
+ SDK 自动以 `clientTools` 的键声明本次运行支持的客户端工具;未提供或为空时不注入客户端工具,子智能体也不注入。
245
+
250
246
  可以在 `createAgentEmbed()` 中传入以下全部运行事件回调:
251
247
 
252
248
  | 回调 | 参数 | 说明 |
@@ -254,7 +250,7 @@ agent.focusInput()
254
250
  | `onConcurrentSend` | 无 | 回复生成期间再次发送消息 |
255
251
  | `onEvent` | `AgentServerEvent` | 接收原始服务端事件 |
256
252
  | `onSessionContextReady` | `AgentSessionContext` | 会话上下文可用,包含 `threadId` 和 `turnId` |
257
- | `onToolCallCreated` | `AgentToolCallCreatedEvent`, `AgentSessionEventContext` | 创建一个工具调用 |
253
+ | `onToolCallReady` | `AgentToolCallReadyEvent`, `AgentSessionEventContext` | 创建一个工具调用 |
258
254
  | `onToolApprovalRequested` | `AgentToolApprovalRequestedEvent`, `AgentSessionEventContext` | 一组工具调用需要确认 |
259
255
  | `onToolCallStarted` | `AgentToolCallStartedEvent`, `AgentSessionEventContext` | 工具调用开始 |
260
256
  | `onToolCallProgressUpdated` | `AgentToolCallProgressUpdatedEvent`, `AgentSessionEventContext` | 工具调用进度更新 |
@@ -262,6 +258,7 @@ agent.focusInput()
262
258
  | `onToolCallSucceeded` | `AgentToolCallSucceededEvent`, `AgentSessionEventContext` | 工具调用成功 |
263
259
  | `onToolCallFailed` | `AgentToolCallFailedEvent`, `AgentSessionEventContext` | 工具调用失败 |
264
260
  | `onToolCallCancelled` | `AgentToolCallCancelledEvent`, `AgentSessionEventContext` | 工具调用取消 |
261
+ | `onClientToolRequest` | `AgentToolCallStartedEvent`, `AgentSessionEventContext` | 客户端工具执行请求;需领取并回传结果,或使用 SDK `clientTools` 自动执行 |
265
262
  | `onClientActionRequest` | `AgentClientActionRequestEvent`, `AgentSessionEventContext` | 智能体请求宿主执行客户端动作 |
266
263
  | `onUserFeedbackConsumed` | `AgentUserFeedbackConsumedEvent`, `AgentSessionEventContext` | 用户反馈已被处理 |
267
264
  | `onUserSteerConsumed` | `AgentUserSteerConsumedEvent`, `AgentSessionEventContext` | 用户 steer 指令已被处理 |
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { AgentAppearance as AgentAppearance$1, AgentEmbedHeaderAppearance, AgentEmbedInitError, AgentEmbedInstance, AgentEmbedTheme as AgentEmbedTheme$1, AgentEvents, AgentRuntimeVariables } from "@sophonsai/agent-embed-core";
1
+ import { AgentAppearance as AgentAppearance$1, AgentEmbedHeaderAppearance, AgentEmbedInitError, AgentEmbedInstance, AgentEmbedTheme as AgentEmbedTheme$1, AgentEvents, AgentRuntimeValue, AgentRuntimeVariables, AgentSessionEventContext } from "@sophonsai/agent-embed-core";
2
2
  export * from "@sophonsai/agent-embed-core";
3
3
  //#region src/theme-presets.d.ts
4
4
  declare const AgentEmbedThemePreset: {
@@ -29,7 +29,10 @@ interface AgentEmbedOptions extends AgentEvents {
29
29
  onFontSizeChange?: (fontSize: number) => void;
30
30
  onInitError?: (error: AgentEmbedInitError) => void;
31
31
  }
32
+ type AgentClientToolHandler = (arguments_: Record<string, unknown>, context: AgentSessionEventContext) => AgentRuntimeValue | Promise<AgentRuntimeValue>;
32
33
  interface CreateAgentEmbedOptions extends AgentEmbedOptions {
34
+ /** Host implementations keyed by the platform client tool name; returned values are sent to the Agent. */
35
+ clientTools?: Record<string, AgentClientToolHandler>;
33
36
  /** Gateway / Extension service address, including HTTP or HTTPS scheme. */
34
37
  endpoint: string;
35
38
  /** Shared Agent access token. */
@@ -51,4 +54,4 @@ interface AgentEmbedClient {
51
54
  declare const DEFAULT_AGENT_EMBED_BASE_URL = "/e/v1/embed";
52
55
  declare const createAgentEmbed: (options: CreateAgentEmbedOptions) => AgentEmbedClient;
53
56
  //#endregion
54
- export { AgentAppearance, AgentEmbedClient, AgentEmbedTheme, AgentEmbedThemePreset, CreateAgentEmbedOptions, DEFAULT_AGENT_EMBED_BASE_URL, createAgentEmbed };
57
+ export { AgentAppearance, AgentClientToolHandler, AgentEmbedClient, AgentEmbedTheme, AgentEmbedThemePreset, CreateAgentEmbedOptions, DEFAULT_AGENT_EMBED_BASE_URL, createAgentEmbed };
package/dist/index.mjs CHANGED
@@ -27,6 +27,8 @@ const cloneAppearance = (appearance) => {
27
27
  };
28
28
  var AgentEmbedClientImpl = class {
29
29
  constructor(options) {
30
+ this.toolClientId = `client-${globalThis.crypto.randomUUID()}`;
31
+ this.handledToolCalls = /* @__PURE__ */ new Set();
30
32
  this.instanceId = createInstanceId();
31
33
  this.mounted = false;
32
34
  this.initialized = false;
@@ -80,6 +82,13 @@ var AgentEmbedClientImpl = class {
80
82
  this.failInitialization(message.args?.[0]);
81
83
  return;
82
84
  }
85
+ if (message.callback === "onClientToolRequest" && this.clientTools) this.executeClientTool(message.args?.[0], message.args?.[1]).catch((error) => {
86
+ this.events.onError?.({
87
+ status: "failure",
88
+ context: null,
89
+ error
90
+ });
91
+ });
83
92
  const callback = this.events[message.callback];
84
93
  try {
85
94
  callback?.(...message.args ?? []);
@@ -101,6 +110,9 @@ var AgentEmbedClientImpl = class {
101
110
  this.targetOrigin = endpoint.origin;
102
111
  this.appearance = cloneAppearance(options.appearance);
103
112
  this.events = pickAgentEvents(options);
113
+ this.clientTools = options.clientTools ? { ...options.clientTools } : void 0;
114
+ this.toolAccessToken = options.token;
115
+ this.toolApiUrl = new URL("/webapi/v1/agent/client-tools", options.endpoint).toString();
104
116
  this.onReady = options.onReady;
105
117
  this.onThemeChange = options.onThemeChange;
106
118
  this.onFontSizeChange = options.onFontSizeChange;
@@ -230,6 +242,7 @@ var AgentEmbedClientImpl = class {
230
242
  type: "init",
231
243
  config: {
232
244
  mode: "url",
245
+ client_tool_names: Object.keys(this.clientTools ?? {}),
233
246
  threadId: this.threadId,
234
247
  appearance: this.appearance,
235
248
  ...this.runtimeVariables === void 0 ? {} : { runtime_variables: this.runtimeVariables }
@@ -267,6 +280,49 @@ var AgentEmbedClientImpl = class {
267
280
  this.onInitError?.(failure);
268
281
  } catch {}
269
282
  }
283
+ async postTool(path, body) {
284
+ const response = await fetch(`${this.toolApiUrl}/${path}`, {
285
+ method: "POST",
286
+ headers: {
287
+ "Content-Type": "application/json",
288
+ Authorization: `Bearer ${this.toolAccessToken}`
289
+ },
290
+ body: JSON.stringify(body)
291
+ });
292
+ const envelope = await response.json();
293
+ if (!response.ok || envelope.code !== 200) throw new Error(envelope.msg ?? `Client tool request failed (${response.status}).`);
294
+ return envelope.data;
295
+ }
296
+ async executeClientTool(event, context) {
297
+ const handler = this.clientTools && Object.hasOwn(this.clientTools, event.toolName) ? this.clientTools[event.toolName] : void 0;
298
+ if (!handler) return;
299
+ const key = `${context.turnId}:${event.toolCallId}`;
300
+ if (this.destroyed || this.handledToolCalls.has(key)) return;
301
+ this.handledToolCalls.add(key);
302
+ const call = {
303
+ turn_id: context.turnId,
304
+ tool_call_id: event.toolCallId,
305
+ client_id: this.toolClientId
306
+ };
307
+ if (await this.postTool("claim", call) !== true) return;
308
+ let result;
309
+ try {
310
+ const value = await handler(event.arguments, context);
311
+ result = {
312
+ status: "success",
313
+ result: typeof value === "string" ? value : JSON.stringify(value)
314
+ };
315
+ } catch (error) {
316
+ result = {
317
+ status: "error",
318
+ error: error instanceof Error ? error.message : String(error)
319
+ };
320
+ }
321
+ await this.postTool("result", {
322
+ ...call,
323
+ ...result
324
+ });
325
+ }
270
326
  };
271
327
  const createAgentEmbed = (options) => new AgentEmbedClientImpl(options);
272
328
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sophonsai/agent-embed-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Framework-independent browser SDK for integrating Sophon Agent Embed.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -25,7 +25,7 @@
25
25
  "dist"
26
26
  ],
27
27
  "dependencies": {
28
- "@sophonsai/agent-embed-core": "0.1.0"
28
+ "@sophonsai/agent-embed-core": "0.2.0"
29
29
  },
30
30
  "devDependencies": {
31
31
  "jsdom": "^27.4.0",