openclaw-openagent 1.0.13 → 1.0.14

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.
Files changed (128) hide show
  1. package/dist/src/messaging/executor.d.ts +2 -3
  2. package/dist/src/messaging/executor.js +4 -31
  3. package/dist/src/plugin-ui/assets/openagent-override.js +4 -5
  4. package/dist/src/runtime/update-checker.d.ts +1 -1
  5. package/dist/src/runtime/update-checker.js +9 -46
  6. package/package.json +1 -3
  7. package/src/app/channel-tools.ts +0 -249
  8. package/src/app/discovery-tools.ts +0 -273
  9. package/src/app/download-file-tool.ts +0 -133
  10. package/src/app/hooks.ts +0 -144
  11. package/src/app/index.ts +0 -84
  12. package/src/app/messaging-tools.ts +0 -79
  13. package/src/app/ops-tools.ts +0 -155
  14. package/src/app/remote-agent-tool.ts +0 -762
  15. package/src/app/types.ts +0 -68
  16. package/src/app/upload-file-tool.ts +0 -411
  17. package/src/app/verbose-preflight.ts +0 -190
  18. package/src/auth/config.ts +0 -266
  19. package/src/auth/credential-manager.ts +0 -146
  20. package/src/auth/index.ts +0 -24
  21. package/src/auth/verify.ts +0 -99
  22. package/src/channel.ts +0 -566
  23. package/src/compat.ts +0 -94
  24. package/src/config/config-schema.ts +0 -45
  25. package/src/messaging/aggregator.ts +0 -120
  26. package/src/messaging/collector.ts +0 -89
  27. package/src/messaging/executor.ts +0 -72
  28. package/src/messaging/inbound.ts +0 -150
  29. package/src/messaging/index.ts +0 -11
  30. package/src/messaging/mention-protocol.ts +0 -94
  31. package/src/messaging/process-c2c-request.ts +0 -564
  32. package/src/messaging/process-message.ts +0 -373
  33. package/src/messaging/scheduler.ts +0 -55
  34. package/src/messaging/types.ts +0 -38
  35. package/src/plugin-ui/adapters/oc-2026-04.js +0 -103
  36. package/src/plugin-ui/adapters/oc-2026-05.js +0 -125
  37. package/src/plugin-ui/adapters/oc-2026-06.js +0 -125
  38. package/src/plugin-ui/adapters/oc-unknown.js +0 -48
  39. package/src/plugin-ui/assets/agentbook-icon.svg +0 -5
  40. package/src/plugin-ui/assets/bg.png +0 -0
  41. package/src/plugin-ui/assets/icon.png +0 -0
  42. package/src/plugin-ui/assets/magic.svg +0 -5
  43. package/src/plugin-ui/assets/openagent-override.js +0 -11263
  44. package/src/plugin-ui/build.cjs +0 -463
  45. package/src/plugin-ui/index.ts +0 -18
  46. package/src/plugin-ui/modules/agent-book/panel/agent-book.js +0 -570
  47. package/src/plugin-ui/modules/agent-book/panel/agent-card.js +0 -170
  48. package/src/plugin-ui/modules/agent-book/panel/agent-data.js +0 -643
  49. package/src/plugin-ui/modules/agent-book/panel/inject-ui.js +0 -665
  50. package/src/plugin-ui/modules/agent-book/panel/mention-state.js +0 -206
  51. package/src/plugin-ui/modules/agent-book/panel/styles.js +0 -832
  52. package/src/plugin-ui/modules/agent-book/panel/theme-adapter.js +0 -86
  53. package/src/plugin-ui/modules/agent-book/remote-agent-tool/components-core.js +0 -295
  54. package/src/plugin-ui/modules/agent-book/remote-agent-tool/thought-chain-card.js +0 -211
  55. package/src/plugin-ui/modules/agent-book/scanner.js +0 -131
  56. package/src/plugin-ui/modules/agent-book/travelcard/travel-cards.js +0 -500
  57. package/src/plugin-ui/modules/agent-book/travelcard/travel-engine.js +0 -652
  58. package/src/plugin-ui/modules/agent-book/travelcard/travel-styles.js +0 -262
  59. package/src/plugin-ui/modules/loader/bootstrap.js +0 -133
  60. package/src/plugin-ui/modules/loader/shared-state.js +0 -838
  61. package/src/plugin-ui/modules/loader/ws-intercept.js +0 -199
  62. package/src/plugin-ui/modules/remote-agent/chunk-parser.js +0 -161
  63. package/src/plugin-ui/modules/remote-agent/execution-card.js +0 -530
  64. package/src/plugin-ui/modules/remote-agent/markdown-renderer.js +0 -256
  65. package/src/plugin-ui/modules/remote-agent/media-links.js +0 -151
  66. package/src/plugin-ui/modules/remote-agent/native-style-adapter.js +0 -134
  67. package/src/plugin-ui/modules/remote-agent/output-card.js +0 -342
  68. package/src/plugin-ui/modules/remote-agent/progress-store.js +0 -363
  69. package/src/plugin-ui/modules/remote-agent/render-hooks.js +0 -1700
  70. package/src/plugin-ui/modules/remote-agent/styles.js +0 -903
  71. package/src/plugin-ui/modules/remote-agent/tool-card-model.js +0 -130
  72. package/src/plugin-ui/postinstall-deploy.cjs +0 -52
  73. package/src/plugin-ui/ui-extension-loader/backup.ts +0 -92
  74. package/src/plugin-ui/ui-extension-loader/index.ts +0 -276
  75. package/src/plugin-ui/ui-extension-loader/locator.ts +0 -152
  76. package/src/plugin-ui/ui-extension-loader/manifest.ts +0 -57
  77. package/src/plugin-ui/ui-extension-loader/registry-regex.ts +0 -944
  78. package/src/plugin-ui/ui-extension-loader/removed-extensions.ts +0 -70
  79. package/src/plugin-ui/ui-extension-loader/types.ts +0 -72
  80. package/src/proxy/auth-proxy.ts +0 -414
  81. package/src/runtime/account.ts +0 -549
  82. package/src/runtime/index.ts +0 -7
  83. package/src/runtime/plugin-runtime.ts +0 -94
  84. package/src/runtime/registry.ts +0 -71
  85. package/src/runtime/update-checker.ts +0 -286
  86. package/src/sdk/CLASS_MAP.md +0 -143
  87. package/src/sdk/index.d.ts +0 -126
  88. package/src/sdk/index.js +0 -23990
  89. package/src/sdk/modules/cloud-search-module.js +0 -1117
  90. package/src/sdk/modules/follow-module.js +0 -1069
  91. package/src/sdk/modules/group-module.js +0 -7397
  92. package/src/sdk/modules/relationship-module.js +0 -2269
  93. package/src/sdk/modules/signaling-module.js +0 -1468
  94. package/src/sdk/modules/tim-upload-plugin.js +0 -730
  95. package/src/sdk/node-env/http-request.js +0 -90
  96. package/src/sdk/node-env/index.js +0 -57
  97. package/src/sdk/node-env/storage.js +0 -114
  98. package/src/sdk/package.json +0 -10
  99. package/src/sdk/tsconfig.json +0 -16
  100. package/src/state/pending-invocation-store.ts +0 -43
  101. package/src/state/store.ts +0 -756
  102. package/src/tim/c2c.ts +0 -451
  103. package/src/tim/channels.ts +0 -364
  104. package/src/tim/client.ts +0 -330
  105. package/src/tim/index.ts +0 -18
  106. package/src/tim/messages.ts +0 -166
  107. package/src/tim/sdk-logger-init.ts +0 -50
  108. package/src/tools.ts +0 -10
  109. package/src/transport/factory.ts +0 -95
  110. package/src/transport/oasn/index.ts +0 -17
  111. package/src/transport/oasn/oasn-agent-card.ts +0 -111
  112. package/src/transport/oasn/oasn-discovery.ts +0 -108
  113. package/src/transport/oasn/oasn-files.ts +0 -210
  114. package/src/transport/oasn/oasn-http.ts +0 -529
  115. package/src/transport/oasn/oasn-invocation.ts +0 -604
  116. package/src/transport/oasn/oasn-normalize.ts +0 -133
  117. package/src/transport/oasn/oasn-register.ts +0 -33
  118. package/src/transport/oasn/oasn-transport.ts +0 -318
  119. package/src/transport/oasn/oasn-types.ts +0 -404
  120. package/src/transport/tim/index.ts +0 -8
  121. package/src/transport/tim/tim-transport.ts +0 -515
  122. package/src/transport/types.ts +0 -538
  123. package/src/types/openclaw-plugin-sdk-media-store.d.ts +0 -9
  124. package/src/types/openclaw.d.ts +0 -97
  125. package/src/types/tencentcloud-chat.d.ts +0 -15
  126. package/src/util/http.ts +0 -113
  127. package/src/util/logger.ts +0 -131
  128. package/src/util/url-resolver.ts +0 -77
@@ -1,515 +0,0 @@
1
- /**
2
- * TimTransport —— 把现有 TIM SDK 代码封装到 AgentTransport 接口背后
3
- *
4
- * 设计依据:docs/specs/2026-06-16-oasn-transport-abstraction-design.md §2.3
5
- *
6
- * 实现策略:
7
- * - 直接复用现有 `src/tim/{client,c2c,messages,channels}.ts` 模块(不复制粘贴)
8
- * - 内部持有自己的 TIMClient 实例,不依赖 `runtime/registry`
9
- * - `sendC2CCustomMessage` 在 transport 内部就地重新实现一份(不用 registry),
10
- * 避免 c2c.ts 中的 `registry.getDefault()` 反向依赖运行时
11
- * - waitForC2CReply / 进度回调走原版 pendingRequests Map(c2c.ts 模块级单例 OK,
12
- * 因为 TimTransport 同进程只会有一个 active 实例)
13
- *
14
- * 不实现的方法:
15
- * - registerAgent / claimAgent / updateAgentCard / uploadFile / downloadArtifact
16
- * 这些是 OASN-only,TimTransport 不在能力接口里声明,调用方需先 narrow 类型。
17
- *
18
- * 注:当前是「在 openagent 基础上原地改造」,所以 TIM 代码仍存于 src/tim/ 而非 src/transport/tim/。
19
- * 等独立 npm 包发布时再做物理迁移。
20
- */
21
-
22
- import { EventEmitter } from 'node:events';
23
-
24
- import { logger } from '../../util/logger.js';
25
- import { TIMClient } from '../../tim/client.js';
26
- import {
27
- initC2CHandler,
28
- waitForC2CReply,
29
- type C2CMessagePayload,
30
- } from '../../tim/c2c.js';
31
- import {
32
- sendMessage as timSendMessage,
33
- fetchMessages as timFetchMessages,
34
- } from '../../tim/messages.js';
35
- import {
36
- listChannels as timListChannels,
37
- searchChannels as timSearchChannels,
38
- joinChannel as timJoinChannel,
39
- leaveChannel as timLeaveChannel,
40
- getMembers as timGetMembers,
41
- createChannel as timCreateChannel,
42
- getChannelSkill as timGetChannelSkill,
43
- setChannelSkill as timSetChannelSkill,
44
- } from '../../tim/channels.js';
45
- import type { TIMCredentials } from '../../auth/verify.js';
46
-
47
- import type {
48
- AgentCard,
49
- CategoryTree,
50
- ChannelInfo,
51
- CoreTransportEvent,
52
- MemberInfo,
53
- ProgressCallback,
54
- SearchQuery,
55
- SearchResult,
56
- TaskHandle,
57
- TaskHandler,
58
- TaskRequest,
59
- TaskResult,
60
- TimOnlyTransportEvent,
61
- TimTransport,
62
- TransportCredentials,
63
- TransportMessage,
64
- } from '../types.js';
65
- import { makeTransportError } from '../types.js';
66
-
67
- // 内部 SDK 引用 —— 仅用于 sendC2CCustomMessage 重新实现
68
- // (把 c2c.ts 中依赖 registry 的部分搬到 transport 内)
69
- // @ts-ignore — vendor JS module, typed as unknown
70
- import TencentCloudChat from '../../sdk/index.js';
71
-
72
- // ───────────────────────────────────────────────────────────────
73
- // 构造参数
74
- // ───────────────────────────────────────────────────────────────
75
-
76
- export interface TimTransportInitOptions {
77
- /** 实例 id(多账户场景区分用) */
78
- accountId: string;
79
- }
80
-
81
- // ───────────────────────────────────────────────────────────────
82
- // 实现类
83
- // ───────────────────────────────────────────────────────────────
84
-
85
- /**
86
- * TimTransport 具体实现。
87
- *
88
- * 事件路由:
89
- * - TIMClient 的 'message' / 'c2c_request' / 'credential_expired' / 'reconnected'
90
- * 在此处转发为 TransportEvent('message' / 'task_received' / 'credential_expired' / 'reconnected')
91
- * - 'task_progress' 不通过 EventEmitter 触发 —— C2C 进度走 c2c.ts 的 pendingRequests
92
- * 回调(waitForC2CReply 的 onProgress 参数),与 sendTask 调用方直接绑定
93
- */
94
- export class TimTransportImpl extends EventEmitter implements TimTransport {
95
- readonly transportType = 'tim' as const;
96
- readonly id: string;
97
-
98
- private _client: TIMClient | null = null;
99
- /** 用户注册的 T3 任务处理器(onTaskReceived) */
100
- private _taskHandler: TaskHandler | null = null;
101
- /** 当前是否就绪(= TIMClient SDK_READY) */
102
- private _isReady = false;
103
-
104
- constructor(options: TimTransportInitOptions) {
105
- super();
106
- this.id = options.accountId;
107
- }
108
-
109
- get isReady(): boolean {
110
- return this._isReady && (this._client?.isReady ?? false);
111
- }
112
-
113
- // ─────────────────────────────────────────────────────────────
114
- // CoreTransport
115
- // ─────────────────────────────────────────────────────────────
116
-
117
- /**
118
- * 验证凭证并登录 TIM SDK。
119
- *
120
- * TransportCredentials → TIMCredentials 字段映射:
121
- * identity → userId
122
- * token → userSig
123
- * 注:sdkAppId 来自外部 verify 接口结果,但在 AccountRuntime 拼装时
124
- * 会通过 TransportCredentials 之外的"已知字段"传入 —— 实际我们走旧逻辑:
125
- * credentials 直接是 TIMCredentials 子集 + sdkAppId 通过 verify 返回的结构。
126
- *
127
- * 为了类型安全,本方法接收的 credentials **必须**额外带 sdkAppId(通过
128
- * TIM-专属扩展类型 TimCredentialsExt 传入,详见 _resolveCredentials in account.ts)。
129
- */
130
- async ready(credentials: TransportCredentials): Promise<void> {
131
- // 从扩展字段中读取 sdkAppId(仅 TIM 路径会传入)
132
- const sdkAppId = (credentials as TransportCredentials & { sdkAppId?: number }).sdkAppId;
133
- if (!sdkAppId) {
134
- throw makeTransportError(
135
- 'TIM_MISSING_SDK_APP_ID',
136
- 'TimTransport.ready: credentials missing sdkAppId (TIM-specific field)',
137
- );
138
- }
139
-
140
- const timCreds: TIMCredentials = {
141
- sdkAppId,
142
- userSig: credentials.token,
143
- userId: credentials.identity,
144
- // expire 是相对秒数(TIM 约定),而 TransportCredentials.expiresAt 是绝对 epoch ms。
145
- // 这里换算回相对秒数(最低 1 小时,避免 0)。
146
- expire: credentials.expiresAt > 0
147
- ? Math.max(3600, Math.floor((credentials.expiresAt - Date.now()) / 1000))
148
- : 604800,
149
- };
150
-
151
- // 创建并连接 TIMClient
152
- this._client = new TIMClient();
153
-
154
- // SDK 'credential_expired' → transport 'credential_expired'(核心事件)
155
- this._client.on('credential_expired', () => {
156
- logger.warn(`[transport/tim] credential_expired emitted (account=${this.id})`);
157
- this._isReady = false;
158
- this.emit('credential_expired');
159
- });
160
-
161
- // SDK 'reconnected' → transport 'reconnected'
162
- this._client.on('reconnected', () => {
163
- logger.info(`[transport/tim] reconnected (account=${this.id})`);
164
- this._isReady = true;
165
- this.emit('reconnected');
166
- });
167
-
168
- // 群聊消息 → transport 'message'(仅 TIM-only 订阅者收到)
169
- this._client.on('message', (msg) => {
170
- // 适配 RawPushMessage → TransportMessage(字段语义一致)
171
- const transportMsg: TransportMessage = {
172
- id: msg.id,
173
- channelId: msg.channelId,
174
- from: msg.from,
175
- nick: msg.nick,
176
- text: msg.text,
177
- time: msg.time,
178
- mentionsMe: msg.mentionsMe,
179
- };
180
- this.emit('message', transportMsg);
181
- });
182
-
183
- // C2C 入站任务请求 → transport 'task_received'(T3 路径)
184
- // initC2CHandler 注册了 c2c.ts 内部的 pendingRequests 监听 +
185
- // 'c2c_request' 自定义事件(task_request 类型转发)
186
- this._client.on('c2c_request', (raw: {
187
- from: string;
188
- payload: { request_id: string; task: string; session_mode: string };
189
- time: number;
190
- }) => {
191
- const req: TaskRequest & { from: string } = {
192
- from: raw.from,
193
- requestId: raw.payload.request_id,
194
- task: raw.payload.task,
195
- };
196
- // 优先调用注册的 TaskHandler;同时 emit 事件给那些只想旁听的订阅者
197
- this.emit('task_received', req);
198
- if (this._taskHandler) {
199
- // 异步处理,不阻塞 c2c handler
200
- this._invokeTaskHandler(req).catch((err) =>
201
- logger.error(`[transport/tim] task handler error: ${(err as Error).message}`),
202
- );
203
- }
204
- });
205
-
206
- // 实际登录
207
- await this._client.connect(timCreds);
208
-
209
- // 初始化 C2C 消息处理器(解析 task_request/progress/result 自定义消息)
210
- initC2CHandler(this._client);
211
-
212
- this._isReady = true;
213
- logger.info(`[transport/tim] ready (account=${this.id} agentId=${credentials.identity})`);
214
- }
215
-
216
- async dispose(): Promise<void> {
217
- this._isReady = false;
218
- if (this._client) {
219
- try {
220
- await this._client.disconnect();
221
- } catch (err) {
222
- logger.warn(`[transport/tim] disconnect error: ${(err as Error).message}`);
223
- }
224
- this._client = null;
225
- }
226
- this.removeAllListeners();
227
- }
228
-
229
- // EventEmitter.on 已经支持 string;这里只是收窄类型,让上层只能订阅
230
- // CoreTransportEvent | TimOnlyTransportEvent。
231
- override on(
232
- event: CoreTransportEvent | TimOnlyTransportEvent,
233
- handler: (...args: any[]) => void,
234
- ): this {
235
- return super.on(event, handler);
236
- }
237
-
238
- override off(
239
- event: CoreTransportEvent | TimOnlyTransportEvent,
240
- handler: (...args: any[]) => void,
241
- ): this {
242
- return super.off(event, handler);
243
- }
244
-
245
- // ─────────────────────────────────────────────────────────────
246
- // TaskTransport
247
- // ─────────────────────────────────────────────────────────────
248
-
249
- /**
250
- * 发送 C2C 任务请求。
251
- *
252
- * TIM C2C 无独立的 invocation 概念,所以 TaskHandle.invocationId = requestId。
253
- * sessionId / effectiveTimeoutMs 字段 undefined。
254
- */
255
- async sendTask(targetAgentId: string, task: TaskRequest): Promise<TaskHandle> {
256
- this._ensureReady();
257
- const payload: C2CMessagePayload = {
258
- type: 'openagent_task_request',
259
- request_id: task.requestId,
260
- task: task.task,
261
- session_mode: 'default',
262
- };
263
- await this._sendC2CCustom(targetAgentId, payload);
264
- return {
265
- invocationId: task.requestId,
266
- // sessionId / effectiveTimeoutMs 故意不返回
267
- };
268
- }
269
-
270
- /**
271
- * 等待 C2C 回复(task_progress + task_result)。
272
- * 进度回调通过 c2c.ts 的 pendingRequests 注册。
273
- */
274
- async waitForTaskResult(
275
- handle: TaskHandle,
276
- options: { timeoutMs: number; signal?: AbortSignal; onProgress?: ProgressCallback },
277
- ): Promise<TaskResult> {
278
- const reply = await waitForC2CReply(handle.invocationId, {
279
- timeoutMs: options.timeoutMs,
280
- signal: options.signal,
281
- onProgress: options.onProgress
282
- ? (content: string) => options.onProgress!({
283
- requestId: handle.invocationId,
284
- content,
285
- })
286
- : undefined,
287
- });
288
-
289
- // mediaUrls (本地文件路径) → ArtifactRef[]
290
- // 注:TIM 路径走的是本地磁盘路径,contentUrl 直接是 file:// 风格的本地路径,
291
- // 上层 remote-agent-tool.ts 知道如何处理(fs.readFile 而非 fetch)。
292
- const artifacts = reply.mediaUrls?.map((path, idx) => ({
293
- id: `tim-file-${idx}`,
294
- displayName: path.split('/').pop() ?? `file-${idx}`,
295
- mimeType: 'application/octet-stream',
296
- sizeBytes: 0,
297
- contentAvailable: true,
298
- contentUrl: path,
299
- }));
300
-
301
- return {
302
- requestId: handle.invocationId,
303
- status: reply.status,
304
- content: reply.content,
305
- ...(artifacts && artifacts.length > 0 ? { artifacts } : {}),
306
- };
307
- }
308
-
309
- // ─────────────────────────────────────────────────────────────
310
- // DiscoveryTransport(TIM 把 channel 列表伪装成 AgentCard)
311
- // ─────────────────────────────────────────────────────────────
312
-
313
- async searchAgents(query: SearchQuery): Promise<SearchResult> {
314
- this._ensureReady();
315
- const channels = query.query
316
- ? await timSearchChannels(this._client!, query.query)
317
- : await timListChannels(this._client!);
318
-
319
- const cards: AgentCard[] = channels.map((ch) => ({
320
- agent_id: ch.id,
321
- agent_type: 'service',
322
- name: ch.name,
323
- description: ch.desc,
324
- MOM: null,
325
- tags: [],
326
- category: [],
327
- avatar_url: null,
328
- }));
329
-
330
- return {
331
- searchId: `tim-search-${Date.now()}`,
332
- agentCards: cards,
333
- pageNum: 1,
334
- pageSize: cards.length,
335
- hasNext: false,
336
- };
337
- }
338
-
339
- async getAgent(agentId: string): Promise<AgentCard | null> {
340
- // TIM 没有 AgentCard 概念,按 channelId 反查(如果是 channel id)
341
- this._ensureReady();
342
- const all = await timListChannels(this._client!);
343
- const ch = all.find((c) => c.id === agentId);
344
- if (!ch) return null;
345
- return {
346
- agent_id: ch.id,
347
- agent_type: 'service',
348
- name: ch.name,
349
- description: ch.desc,
350
- MOM: null,
351
- tags: [],
352
- category: [],
353
- avatar_url: null,
354
- };
355
- }
356
-
357
- /** TIM 没有 category 概念,返回空树 */
358
- async getCategories(): Promise<CategoryTree> {
359
- return { categories: [], updated_at: new Date().toISOString() };
360
- }
361
-
362
- // ─────────────────────────────────────────────────────────────
363
- // IMChannelTransport(TIM-only)
364
- // ─────────────────────────────────────────────────────────────
365
-
366
- onTaskReceived(handler: TaskHandler): void {
367
- this._taskHandler = handler;
368
- }
369
-
370
- async sendGroupMessage(
371
- channelId: string,
372
- text: string,
373
- atUserList?: string[],
374
- ): Promise<{ ok: boolean; messageId: string }> {
375
- this._ensureReady();
376
- return timSendMessage(this._client!, channelId, text, atUserList);
377
- }
378
-
379
- async fetchGroupHistory(channelId: string, count = 20): Promise<TransportMessage[]> {
380
- this._ensureReady();
381
- const msgs = await timFetchMessages(this._client!, channelId, count);
382
- return msgs.map((m) => ({
383
- id: m.id,
384
- channelId,
385
- from: m.from,
386
- nick: m.from,
387
- text: m.text,
388
- time: m.time,
389
- mentionsMe: false,
390
- }));
391
- }
392
-
393
- // 频道管理(DORMANT,接口保留)
394
- async listChannels(): Promise<ChannelInfo[]> {
395
- this._ensureReady();
396
- return timListChannels(this._client!);
397
- }
398
- async searchChannels(keyword: string): Promise<ChannelInfo[]> {
399
- this._ensureReady();
400
- return timSearchChannels(this._client!, keyword);
401
- }
402
- async joinChannel(channelId: string) {
403
- this._ensureReady();
404
- return timJoinChannel(this._client!, channelId);
405
- }
406
- async leaveChannel(channelId: string) {
407
- this._ensureReady();
408
- return timLeaveChannel(this._client!, channelId);
409
- }
410
- async getMembers(channelId: string): Promise<MemberInfo[]> {
411
- this._ensureReady();
412
- return timGetMembers(this._client!, channelId);
413
- }
414
- async createChannel(name: string, desc?: string) {
415
- this._ensureReady();
416
- return timCreateChannel(this._client!, name, desc);
417
- }
418
- async getChannelSkill(channelId: string) {
419
- this._ensureReady();
420
- return timGetChannelSkill(this._client!, channelId);
421
- }
422
- async setChannelSkill(channelId: string, skill: string) {
423
- this._ensureReady();
424
- return timSetChannelSkill(this._client!, channelId, skill);
425
- }
426
-
427
- // ─────────────────────────────────────────────────────────────
428
- // 内部工具
429
- // ─────────────────────────────────────────────────────────────
430
-
431
- /** 暴露底层 TIMClient 给老代码兼容(如 src/runtime/registry 等) */
432
- get _internalClient(): TIMClient | null {
433
- return this._client;
434
- }
435
-
436
- private _ensureReady(): void {
437
- if (!this.isReady || !this._client) {
438
- throw makeTransportError('TRANSPORT_NOT_READY', 'TimTransport not ready');
439
- }
440
- }
441
-
442
- /**
443
- * sendC2CCustomMessage 的 transport-local 实现。
444
- * 不走 runtime/registry —— 直接用 this._client 持有的 SDK 实例。
445
- *
446
- * 与 src/tim/c2c.ts 中的同名函数行为等价(含 10s SDK guard),
447
- * 但避免了"transport 反向依赖 runtime"。
448
- */
449
- private async _sendC2CCustom(
450
- userId: string,
451
- payload: C2CMessagePayload,
452
- ): Promise<void> {
453
- this._ensureReady();
454
- const chat = this._client!._chat;
455
- const types = this._client!._types;
456
- if (!chat) {
457
- throw makeTransportError('TIM_SDK_NULL', 'TIM SDK not initialized');
458
- }
459
- const message = chat.createCustomMessage({
460
- to: userId,
461
- conversationType: types.CONV_C2C,
462
- payload: {
463
- data: JSON.stringify(payload),
464
- description: payload.type,
465
- extension: '',
466
- },
467
- });
468
-
469
- // 10s SDK-call guard:避免死 WebSocket 让 Tool 永久阻塞
470
- let timeoutHandle: ReturnType<typeof setTimeout>;
471
- const timeoutPromise = new Promise<never>((_, reject) => {
472
- timeoutHandle = setTimeout(
473
- () => reject(new Error(`sendC2CCustomMessage timeout (10s) to=${userId}`)),
474
- 10_000,
475
- );
476
- });
477
-
478
- try {
479
- await Promise.race([chat.sendMessage(message), timeoutPromise]);
480
- logger.info(`[transport/tim] C2C sent: to=${userId} type=${payload.type}`);
481
- } finally {
482
- clearTimeout(timeoutHandle!);
483
- }
484
- }
485
-
486
- /** 调用注册的 TaskHandler 并把结果通过 C2C 回写给请求方 */
487
- private async _invokeTaskHandler(req: TaskRequest & { from: string }): Promise<void> {
488
- if (!this._taskHandler) return;
489
- try {
490
- const result = await this._taskHandler(req);
491
- await this._sendC2CCustom(req.from, {
492
- type: 'openagent_task_result',
493
- request_id: result.requestId,
494
- status: result.status,
495
- content: result.content,
496
- });
497
- } catch (err) {
498
- logger.error(`[transport/tim] _invokeTaskHandler failed: ${(err as Error).message}`);
499
- // 即使 handler 失败也回写 error 结果,避免对方永久阻塞
500
- try {
501
- await this._sendC2CCustom(req.from, {
502
- type: 'openagent_task_result',
503
- request_id: req.requestId,
504
- status: 'error',
505
- content: (err as Error).message,
506
- });
507
- } catch {
508
- /* swallow,已经记日志了 */
509
- }
510
- }
511
- }
512
- }
513
-
514
- // 引用未使用的导入做编译期检查,避免 lint 报 unused
515
- void TencentCloudChat;