openclaw-openagent 1.0.12 → 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 (132) hide show
  1. package/dist/index.js +2 -0
  2. package/dist/src/config/config-schema.d.ts +9 -0
  3. package/dist/src/config/config-schema.js +6 -0
  4. package/dist/src/messaging/executor.d.ts +2 -3
  5. package/dist/src/messaging/executor.js +4 -31
  6. package/dist/src/plugin-ui/assets/openagent-override.js +124 -18
  7. package/dist/src/proxy/auth-proxy.js +5 -0
  8. package/dist/src/runtime/update-checker.d.ts +18 -0
  9. package/dist/src/runtime/update-checker.js +216 -0
  10. package/index.ts +3 -0
  11. package/package.json +1 -3
  12. package/src/app/channel-tools.ts +0 -249
  13. package/src/app/discovery-tools.ts +0 -273
  14. package/src/app/download-file-tool.ts +0 -133
  15. package/src/app/hooks.ts +0 -144
  16. package/src/app/index.ts +0 -84
  17. package/src/app/messaging-tools.ts +0 -79
  18. package/src/app/ops-tools.ts +0 -155
  19. package/src/app/remote-agent-tool.ts +0 -762
  20. package/src/app/types.ts +0 -68
  21. package/src/app/upload-file-tool.ts +0 -411
  22. package/src/app/verbose-preflight.ts +0 -190
  23. package/src/auth/config.ts +0 -266
  24. package/src/auth/credential-manager.ts +0 -146
  25. package/src/auth/index.ts +0 -24
  26. package/src/auth/verify.ts +0 -99
  27. package/src/channel.ts +0 -566
  28. package/src/compat.ts +0 -94
  29. package/src/config/config-schema.ts +0 -39
  30. package/src/messaging/aggregator.ts +0 -120
  31. package/src/messaging/collector.ts +0 -89
  32. package/src/messaging/executor.ts +0 -72
  33. package/src/messaging/inbound.ts +0 -150
  34. package/src/messaging/index.ts +0 -11
  35. package/src/messaging/mention-protocol.ts +0 -94
  36. package/src/messaging/process-c2c-request.ts +0 -564
  37. package/src/messaging/process-message.ts +0 -373
  38. package/src/messaging/scheduler.ts +0 -55
  39. package/src/messaging/types.ts +0 -38
  40. package/src/plugin-ui/adapters/oc-2026-04.js +0 -103
  41. package/src/plugin-ui/adapters/oc-2026-05.js +0 -125
  42. package/src/plugin-ui/adapters/oc-2026-06.js +0 -125
  43. package/src/plugin-ui/adapters/oc-unknown.js +0 -48
  44. package/src/plugin-ui/assets/agentbook-icon.svg +0 -5
  45. package/src/plugin-ui/assets/bg.png +0 -0
  46. package/src/plugin-ui/assets/icon.png +0 -0
  47. package/src/plugin-ui/assets/magic.svg +0 -5
  48. package/src/plugin-ui/assets/openagent-override.js +0 -11156
  49. package/src/plugin-ui/build.cjs +0 -463
  50. package/src/plugin-ui/index.ts +0 -18
  51. package/src/plugin-ui/modules/agent-book/panel/agent-book.js +0 -570
  52. package/src/plugin-ui/modules/agent-book/panel/agent-card.js +0 -170
  53. package/src/plugin-ui/modules/agent-book/panel/agent-data.js +0 -643
  54. package/src/plugin-ui/modules/agent-book/panel/inject-ui.js +0 -665
  55. package/src/plugin-ui/modules/agent-book/panel/mention-state.js +0 -206
  56. package/src/plugin-ui/modules/agent-book/panel/styles.js +0 -833
  57. package/src/plugin-ui/modules/agent-book/panel/theme-adapter.js +0 -86
  58. package/src/plugin-ui/modules/agent-book/remote-agent-tool/components-core.js +0 -295
  59. package/src/plugin-ui/modules/agent-book/remote-agent-tool/thought-chain-card.js +0 -211
  60. package/src/plugin-ui/modules/agent-book/scanner.js +0 -131
  61. package/src/plugin-ui/modules/agent-book/travelcard/travel-cards.js +0 -500
  62. package/src/plugin-ui/modules/agent-book/travelcard/travel-engine.js +0 -652
  63. package/src/plugin-ui/modules/agent-book/travelcard/travel-styles.js +0 -256
  64. package/src/plugin-ui/modules/loader/bootstrap.js +0 -38
  65. package/src/plugin-ui/modules/loader/shared-state.js +0 -838
  66. package/src/plugin-ui/modules/loader/ws-intercept.js +0 -199
  67. package/src/plugin-ui/modules/remote-agent/chunk-parser.js +0 -161
  68. package/src/plugin-ui/modules/remote-agent/execution-card.js +0 -530
  69. package/src/plugin-ui/modules/remote-agent/markdown-renderer.js +0 -256
  70. package/src/plugin-ui/modules/remote-agent/media-links.js +0 -151
  71. package/src/plugin-ui/modules/remote-agent/native-style-adapter.js +0 -134
  72. package/src/plugin-ui/modules/remote-agent/output-card.js +0 -342
  73. package/src/plugin-ui/modules/remote-agent/progress-store.js +0 -363
  74. package/src/plugin-ui/modules/remote-agent/render-hooks.js +0 -1700
  75. package/src/plugin-ui/modules/remote-agent/styles.js +0 -896
  76. package/src/plugin-ui/modules/remote-agent/tool-card-model.js +0 -130
  77. package/src/plugin-ui/postinstall-deploy.cjs +0 -52
  78. package/src/plugin-ui/ui-extension-loader/backup.ts +0 -92
  79. package/src/plugin-ui/ui-extension-loader/index.ts +0 -276
  80. package/src/plugin-ui/ui-extension-loader/locator.ts +0 -152
  81. package/src/plugin-ui/ui-extension-loader/manifest.ts +0 -57
  82. package/src/plugin-ui/ui-extension-loader/registry-regex.ts +0 -944
  83. package/src/plugin-ui/ui-extension-loader/removed-extensions.ts +0 -70
  84. package/src/plugin-ui/ui-extension-loader/types.ts +0 -72
  85. package/src/proxy/auth-proxy.ts +0 -409
  86. package/src/runtime/account.ts +0 -549
  87. package/src/runtime/index.ts +0 -7
  88. package/src/runtime/plugin-runtime.ts +0 -94
  89. package/src/runtime/registry.ts +0 -71
  90. package/src/sdk/CLASS_MAP.md +0 -143
  91. package/src/sdk/index.d.ts +0 -126
  92. package/src/sdk/index.js +0 -23990
  93. package/src/sdk/modules/cloud-search-module.js +0 -1117
  94. package/src/sdk/modules/follow-module.js +0 -1069
  95. package/src/sdk/modules/group-module.js +0 -7397
  96. package/src/sdk/modules/relationship-module.js +0 -2269
  97. package/src/sdk/modules/signaling-module.js +0 -1468
  98. package/src/sdk/modules/tim-upload-plugin.js +0 -730
  99. package/src/sdk/node-env/http-request.js +0 -90
  100. package/src/sdk/node-env/index.js +0 -57
  101. package/src/sdk/node-env/storage.js +0 -114
  102. package/src/sdk/package.json +0 -10
  103. package/src/sdk/tsconfig.json +0 -16
  104. package/src/state/pending-invocation-store.ts +0 -43
  105. package/src/state/store.ts +0 -756
  106. package/src/tim/c2c.ts +0 -451
  107. package/src/tim/channels.ts +0 -364
  108. package/src/tim/client.ts +0 -330
  109. package/src/tim/index.ts +0 -18
  110. package/src/tim/messages.ts +0 -166
  111. package/src/tim/sdk-logger-init.ts +0 -50
  112. package/src/tools.ts +0 -10
  113. package/src/transport/factory.ts +0 -95
  114. package/src/transport/oasn/index.ts +0 -17
  115. package/src/transport/oasn/oasn-agent-card.ts +0 -111
  116. package/src/transport/oasn/oasn-discovery.ts +0 -108
  117. package/src/transport/oasn/oasn-files.ts +0 -210
  118. package/src/transport/oasn/oasn-http.ts +0 -529
  119. package/src/transport/oasn/oasn-invocation.ts +0 -604
  120. package/src/transport/oasn/oasn-normalize.ts +0 -133
  121. package/src/transport/oasn/oasn-register.ts +0 -33
  122. package/src/transport/oasn/oasn-transport.ts +0 -318
  123. package/src/transport/oasn/oasn-types.ts +0 -404
  124. package/src/transport/tim/index.ts +0 -8
  125. package/src/transport/tim/tim-transport.ts +0 -515
  126. package/src/transport/types.ts +0 -538
  127. package/src/types/openclaw-plugin-sdk-media-store.d.ts +0 -9
  128. package/src/types/openclaw.d.ts +0 -97
  129. package/src/types/tencentcloud-chat.d.ts +0 -15
  130. package/src/util/http.ts +0 -113
  131. package/src/util/logger.ts +0 -131
  132. 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;