@kafca/agentdock 0.1.56 → 0.1.57

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 (180) hide show
  1. package/README.md +7 -0
  2. package/dist/renderer/assets/{Badge-DjcoXx2J.js → Badge-CDTbmw1h.js} +1 -1
  3. package/dist/renderer/assets/Card-DayUo35w.js +1 -0
  4. package/dist/renderer/assets/Config-ByGMQuzR.js +21 -0
  5. package/dist/renderer/assets/CronList-XqHdVlgu.js +1 -0
  6. package/dist/renderer/assets/Dashboard-CZj-oANw.js +41 -0
  7. package/dist/renderer/assets/{EmptyState-DIZLiccW.js → EmptyState-EFMkOjZO.js} +1 -1
  8. package/dist/renderer/assets/HighlightedMarkdown-DyvF3DHK.js +12 -0
  9. package/dist/renderer/assets/Input-DxoWVc9d.js +1 -0
  10. package/dist/renderer/assets/{KnowledgeDetail-CJ9IYOsa.js → KnowledgeDetail-CbUb2tG7.js} +2 -2
  11. package/dist/renderer/assets/{KnowledgeHome-BLGPwnBO.js → KnowledgeHome-BWV1gz4f.js} +3 -3
  12. package/dist/renderer/assets/Logs-DqnanQTc.js +6 -0
  13. package/dist/renderer/assets/{Modal-CQiUpfl4.js → Modal-yY7TzR0x.js} +3 -3
  14. package/dist/renderer/assets/MonitorList-CIjGQkFs.js +1 -0
  15. package/dist/renderer/assets/Page-vwHNUdoj.js +1 -0
  16. package/dist/renderer/assets/{Select-D6z65IT3.js → Select-CmbK36pN.js} +2 -2
  17. package/dist/renderer/assets/ThreadChat-4OceMgM4.js +86 -0
  18. package/dist/renderer/assets/Workspace-DplPJOjJ.js +19 -0
  19. package/dist/renderer/assets/{arrow-left-CV5cL3f4.js → arrow-left-C8HfBt2K.js} +1 -1
  20. package/dist/renderer/assets/{book-open-DThvB7pj.js → book-open-BCdZWncQ.js} +1 -1
  21. package/dist/renderer/assets/channels-hgO3cAIx.js +6 -0
  22. package/dist/renderer/assets/chevron-down-BPk77tqY.js +11 -0
  23. package/dist/renderer/assets/index-BIKL3fTP.css +11 -0
  24. package/dist/renderer/assets/index-BlA4xPdd.js +41 -0
  25. package/dist/renderer/assets/index-wYpjqVqC.js +167 -0
  26. package/dist/renderer/assets/knowledge-7pl06KuH.js +1 -0
  27. package/dist/renderer/assets/{pencil-Dv5WxhdC.js → pencil-CB1SWZ9A.js} +1 -1
  28. package/dist/renderer/assets/{play-DnCnft83.js → play-BvsoXUrM.js} +1 -1
  29. package/dist/renderer/assets/{plus-DsxIagzS.js → plus-CokBDnaL.js} +1 -1
  30. package/dist/renderer/assets/{save-CST01lIc.js → save-D-w4kATO.js} +1 -1
  31. package/dist/renderer/assets/{search-B_bqy6Wd.js → search-Cnsn6i4Q.js} +1 -1
  32. package/dist/renderer/assets/{shield-check-D6lG5Aoc.js → shield-check-Cjja2Gh6.js} +1 -1
  33. package/dist/renderer/assets/threads-BCm6j4eI.js +1 -0
  34. package/dist/renderer/assets/{trash-2-Cefngb6Q.js → trash-2-CIxz9qYY.js} +1 -1
  35. package/dist/renderer/index.html +2 -2
  36. package/dist-electron/packages/contracts/src/automation.js +2 -0
  37. package/dist-electron/packages/contracts/src/channels.js +2 -0
  38. package/dist-electron/packages/contracts/src/knowledge.js +2 -0
  39. package/dist-electron/packages/contracts/src/local-core.js +15 -0
  40. package/dist-electron/packages/contracts/src/runtime.js +2 -0
  41. package/dist-electron/packages/contracts/src/scheduler.js +2 -0
  42. package/dist-electron/packages/contracts/src/threads.js +2 -0
  43. package/dist-electron/packages/core-sdk/src/automation.js +32 -0
  44. package/dist-electron/packages/core-sdk/src/channels.js +121 -0
  45. package/dist-electron/packages/core-sdk/src/client.js +455 -0
  46. package/dist-electron/packages/core-sdk/src/index.js +43 -607
  47. package/dist-electron/packages/core-sdk/src/knowledge.js +85 -0
  48. package/dist-electron/packages/core-sdk/src/request.js +22 -0
  49. package/dist-electron/packages/core-sdk/src/runtime.js +214 -0
  50. package/dist-electron/packages/core-sdk/src/scheduler.js +32 -0
  51. package/dist-electron/packages/core-sdk/src/threads.js +67 -0
  52. package/dist-electron/packages/plugin-sdk/src/agents.js +2 -0
  53. package/dist-electron/packages/plugin-sdk/src/automation.js +2 -0
  54. package/dist-electron/packages/plugin-sdk/src/channels.js +2 -0
  55. package/dist-electron/packages/plugin-sdk/src/index.js +21 -0
  56. package/dist-electron/packages/plugin-sdk/src/knowledge.js +2 -0
  57. package/dist-electron/packages/plugin-sdk/src/runtime.js +2 -0
  58. package/dist-electron/packages/plugin-sdk/src/scheduler.js +2 -0
  59. package/dist-electron/packages/plugin-sdk/src/threads.js +2 -0
  60. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +5 -8
  61. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-content.js +2 -2
  62. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +3 -3
  63. package/dist-electron/services/local-ai-core/src/acp/store/agent-task-store.js +5 -5
  64. package/dist-electron/services/local-ai-core/src/acp/store/automation-monitor-store.js +12 -12
  65. package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +2 -2
  66. package/dist-electron/services/local-ai-core/src/acp/store/scheduler-store.js +11 -11
  67. package/dist-electron/services/local-ai-core/src/acp/store/security-store.js +3 -3
  68. package/dist-electron/services/local-ai-core/src/acp/store/thread-store.js +7 -7
  69. package/dist-electron/services/local-ai-core/src/acp/workspace-acp-permissions.js +2 -2
  70. package/dist-electron/services/local-ai-core/src/agents/claudecode/definition.js +3 -3
  71. package/dist-electron/services/local-ai-core/src/agents/codex/definition.js +3 -3
  72. package/dist-electron/services/local-ai-core/src/agents/localcore-acp/definition.js +2 -2
  73. package/dist-electron/services/local-ai-core/src/agents/localcore-acp/index.js +4 -4
  74. package/dist-electron/services/local-ai-core/src/agents/opencode/launch.js +2 -2
  75. package/dist-electron/services/local-ai-core/src/agents/pi/definition.js +2 -2
  76. package/dist-electron/services/local-ai-core/src/agents/pi/launch.js +3 -3
  77. package/dist-electron/services/local-ai-core/src/agents/pi/provider-materializer.js +1 -1
  78. package/dist-electron/services/local-ai-core/src/agents/shared/agent-plugin.js +4 -4
  79. package/dist-electron/services/local-ai-core/src/channel/lark/cards.js +33 -18
  80. package/dist-electron/services/local-ai-core/src/channel/lark/config.js +2 -2
  81. package/dist-electron/services/local-ai-core/src/channel/lark/gateway-utils.js +91 -0
  82. package/dist-electron/services/local-ai-core/src/channel/lark/inbound-handler.js +180 -0
  83. package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +52 -486
  84. package/dist-electron/services/local-ai-core/src/channel/lark/outbound-transport.js +124 -0
  85. package/dist-electron/services/local-ai-core/src/channel/shared/inbound-authorization.js +54 -0
  86. package/dist-electron/services/local-ai-core/src/channel/weixin/config.js +2 -2
  87. package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-media.js +21 -0
  88. package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-poller.js +167 -0
  89. package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +50 -469
  90. package/dist-electron/services/local-ai-core/src/channel/weixin/runtime-state.js +156 -0
  91. package/dist-electron/services/local-ai-core/src/channel/weixin/text-utils.js +100 -0
  92. package/dist-electron/services/local-ai-core/src/cli/lac.js +6 -6
  93. package/dist-electron/services/local-ai-core/src/cli/monitor-cli-parsers.js +2 -2
  94. package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +28 -70
  95. package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-ai-vector-plugin.js +2 -2
  96. package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-noop-plugin.js +2 -2
  97. package/dist-electron/services/local-ai-core/src/router/workspace-bridge-event-stream.js +29 -0
  98. package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +5 -5
  99. package/dist-electron/services/local-ai-core/src/router/workspace-router.js +47 -60
  100. package/dist-electron/services/local-ai-core/src/runtime/agent-runtime-detector.js +5 -5
  101. package/dist-electron/services/local-ai-core/src/runtime/config-migration.js +6 -6
  102. package/dist-electron/services/local-ai-core/src/runtime/deployment-diagnostics.js +3 -3
  103. package/dist-electron/services/local-ai-core/src/runtime/external-service.js +3 -1
  104. package/dist-electron/services/local-ai-core/src/runtime/handlers/automation-handler.js +11 -2
  105. package/dist-electron/services/local-ai-core/src/runtime/handlers/channel-handler.js +12 -6
  106. package/dist-electron/services/local-ai-core/src/runtime/handlers/external-handler.js +10 -2
  107. package/dist-electron/services/local-ai-core/src/runtime/handlers/knowledge-handler.js +18 -6
  108. package/dist-electron/services/local-ai-core/src/runtime/handlers/provider-handler.js +7 -2
  109. package/dist-electron/services/local-ai-core/src/runtime/handlers/runtime-handler.js +28 -3
  110. package/dist-electron/services/local-ai-core/src/runtime/handlers/scheduler-handler.js +10 -2
  111. package/dist-electron/services/local-ai-core/src/runtime/handlers/security-handler.js +18 -5
  112. package/dist-electron/services/local-ai-core/src/runtime/handlers/task-handler.js +14 -2
  113. package/dist-electron/services/local-ai-core/src/runtime/handlers/thread-handler.js +18 -15
  114. package/dist-electron/services/local-ai-core/src/runtime/handlers/workspace-handler.js +13 -2
  115. package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +35 -8
  116. package/dist-electron/services/local-ai-core/src/runtime/request-validation.js +79 -0
  117. package/dist-electron/services/local-ai-core/src/runtime/runtime-detection-service.js +9 -9
  118. package/dist-electron/services/local-ai-core/src/runtime/server-helpers.js +10 -1
  119. package/dist-electron/services/local-ai-core/src/runtime/server.js +2 -1
  120. package/dist-electron/services/local-ai-core/src/runtime/workspace-project-registry.js +76 -0
  121. package/dist-electron/services/local-ai-core/src/sandbox/sandbox-config.js +8 -8
  122. package/dist-electron/services/local-ai-core/src/thread/agent-message-policy.js +75 -0
  123. package/dist-electron/shared/desktop.js +1 -64
  124. package/dist-electron/src/components/chat/chat-controller-state.js +60 -0
  125. package/dist-electron/src/components/chat/chat-event-gate.js +146 -0
  126. package/dist-electron/src/components/chat/markdown-code-block.js +8 -0
  127. package/dist-electron/src/pages/Desktop/workspace-model.js +212 -0
  128. package/dist-electron/src/pages/Threads/thread-chat-model.js +50 -51
  129. package/dist-electron/tests/contracts/agent-message-policy.test.js +21 -0
  130. package/dist-electron/tests/contracts/architecture-docs.test.js +56 -33
  131. package/dist-electron/tests/contracts/chat-event-gate.test.js +114 -0
  132. package/dist-electron/tests/contracts/chat-markdown.test.js +16 -0
  133. package/dist-electron/tests/contracts/thread-task-state.test.js +32 -0
  134. package/dist-electron/tests/contracts/workspace-identity.test.js +23 -0
  135. package/dist-electron/tests/electron/core-client.test.js +284 -0
  136. package/dist-electron/tests/electron/plugin-kernel.test.js +54 -0
  137. package/dist-electron/tests/electron/renderer-packaging.test.js +9 -0
  138. package/dist-electron/tests/electron/workspace-task-store.test.js +31 -0
  139. package/dist-electron/tests/integration/channel-inbound-authorization.test.js +80 -0
  140. package/dist-electron/tests/integration/lark-gateway-utils.test.js +13 -0
  141. package/dist-electron/tests/integration/lark-gateway.test.js +4 -4
  142. package/dist-electron/tests/integration/weixin-runtime-state.test.js +32 -0
  143. package/dist-electron/tests/integration/weixin-text-utils.test.js +15 -0
  144. package/package.json +9 -4
  145. package/dist/renderer/assets/Chat-C5Bkm9-M.js +0 -2
  146. package/dist/renderer/assets/ChatMarkdown-uc36EzyD.js +0 -45
  147. package/dist/renderer/assets/Config-DHtQuuLy.js +0 -21
  148. package/dist/renderer/assets/CronList-BYUnhzSC.js +0 -1
  149. package/dist/renderer/assets/Dashboard-BPnGMDg3.js +0 -26
  150. package/dist/renderer/assets/Logs-Dyd2Uwlt.js +0 -1
  151. package/dist/renderer/assets/MonitorList-Byg3E3Gt.js +0 -1
  152. package/dist/renderer/assets/Page-7DxXvTMm.js +0 -1
  153. package/dist/renderer/assets/ProjectDetail-Dfr5s0Ja.js +0 -11
  154. package/dist/renderer/assets/ProjectList-CDDQjAQ_.js +0 -1
  155. package/dist/renderer/assets/SessionChat-s7CAaCPL.js +0 -1
  156. package/dist/renderer/assets/SessionList-D-OycKKS.js +0 -1
  157. package/dist/renderer/assets/ThreadChat-CLdFynB5.js +0 -28
  158. package/dist/renderer/assets/Workspace-xfT5z4j_.js +0 -19
  159. package/dist/renderer/assets/bot-CWQ5-ovl.js +0 -6
  160. package/dist/renderer/assets/check-DKM7zfWG.js +0 -6
  161. package/dist/renderer/assets/chevron-down-Dfw2KU87.js +0 -6
  162. package/dist/renderer/assets/circle-CoP4RA4s.js +0 -6
  163. package/dist/renderer/assets/desktop-CsDYrOOU.js +0 -1
  164. package/dist/renderer/assets/desktop-JQkhNOF4.js +0 -5
  165. package/dist/renderer/assets/funnel-DpVLlG3g.js +0 -6
  166. package/dist/renderer/assets/heart-BMD36ejP.js +0 -6
  167. package/dist/renderer/assets/index-COxSYBjE.js +0 -182
  168. package/dist/renderer/assets/index-CTGTI-cm.js +0 -41
  169. package/dist/renderer/assets/index-CjCuR6DI.css +0 -11
  170. package/dist/renderer/assets/projects-DgjHcNgt.js +0 -1
  171. package/dist/renderer/assets/server-ecH4GNwa.js +0 -11
  172. package/dist/renderer/assets/session-utils-Dd_WKMYW.js +0 -6
  173. package/dist/renderer/assets/sessions-BQ33Mv4k.js +0 -1
  174. package/dist/renderer/assets/user-D_8RSH-T.js +0 -6
  175. package/dist/renderer/assets/wifi-off-DB9D-pOu.js +0 -11
  176. package/dist-electron/src/api/client.js +0 -73
  177. package/dist-electron/src/api/sessions.js +0 -21
  178. package/dist-electron/src/lib/session-utils.js +0 -51
  179. package/dist-electron/src/pages/Projects/project-provider-config.js +0 -75
  180. package/dist-electron/tests/electron/project-provider-config.test.js +0 -71
@@ -35,24 +35,20 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.LocalCoreLarkGateway = void 0;
37
37
  const node_crypto_1 = require("node:crypto");
38
- const node_fs_1 = require("node:fs");
39
- const node_path_1 = require("node:path");
40
38
  const local_core_errors_js_1 = require("../../kernel/local-core-errors.js");
41
- const desktop_js_1 = require("../../../../../shared/desktop.js");
42
39
  const content_js_1 = require("../shared/content.js");
43
- const file_utils_js_1 = require("../shared/file-utils.js");
44
- const inbound_attachment_store_js_1 = require("../shared/inbound-attachment-store.js");
45
40
  const thread_routing_js_1 = require("../shared/thread-routing.js");
46
41
  const base_channel_gateway_js_1 = require("../shared/base-channel-gateway.js");
42
+ const inbound_authorization_js_1 = require("../shared/inbound-authorization.js");
47
43
  const cards_js_1 = require("./cards.js");
48
44
  const channel_keys_js_1 = require("../shared/channel-keys.js");
49
45
  const config_js_1 = require("./config.js");
50
46
  const registration_js_1 = require("./registration.js");
51
- const messages_js_1 = require("./rendering/messages.js");
52
47
  const inbound_js_1 = require("./inbound.js");
48
+ const inbound_handler_js_1 = require("./inbound-handler.js");
49
+ const outbound_transport_js_1 = require("./outbound-transport.js");
53
50
  const runtime_state_js_1 = require("./runtime-state.js");
54
- const PAIRING_EXPIRY_MS = 10 * 60 * 1000;
55
- const LARK_MAX_UPLOAD_FILE_SIZE = 30 * 1024 * 1024;
51
+ const gateway_utils_js_1 = require("./gateway-utils.js");
56
52
  const LARK_FINAL_PATCH_INTERVAL_MS = 900;
57
53
  const LARK_PROGRESS_PATCH_INTERVAL_MS = 3000;
58
54
  const LARK_EMPTY_RENDER_LOG_WINDOW_MS = 5 * 60 * 1000;
@@ -64,10 +60,20 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
64
60
  mirrorPermissionStateInMainCard = false;
65
61
  larkModulePromise = null;
66
62
  emptyRenderLogWindows = new Map();
67
- inboundAttachmentStore = new inbound_attachment_store_js_1.FileSystemInboundAttachmentStore();
63
+ inboundHandler;
64
+ outboundTransport;
68
65
  platform = 'lark';
69
66
  constructor(options) {
70
67
  super(options);
68
+ this.inboundHandler = new inbound_handler_js_1.LarkInboundHandler({
69
+ store: options.store,
70
+ getWorkspaceRouter: options.getWorkspaceRouter,
71
+ getRuntimeState: (workspaceId, instanceId) => this.resolveRuntimeState(workspaceId, instanceId).state,
72
+ getBinding: (workspaceId, instanceId) => this.getBinding(workspaceId, instanceId),
73
+ dispatchInboundMessage: (message) => this.handleInboundMessage(message),
74
+ log: options.log,
75
+ });
76
+ this.outboundTransport = new outbound_transport_js_1.LarkOutboundTransport(options.log);
71
77
  }
72
78
  // ==================== Lifecycle (platform-specific) ====================
73
79
  async testConnection(workspaceId, instanceId) {
@@ -160,7 +166,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
160
166
  async sendSessionCommandResult(input, result) {
161
167
  const state = this.resolveRuntimeState(input.workspaceId, input.instanceId).state;
162
168
  if (state?.client && state.connected && result.card?.actions?.length && state.cardActionsEnabled) {
163
- await this.sendSessionCommandCard(state, input.chatId, result.displayText, result.card.actions, this.options.getWorkspaceRouter().getThreadSessionKey(input.currentThreadId), input.currentThreadId);
169
+ await this.outboundTransport.sendSessionCommandCard(state, input.chatId, result.displayText, result.card.actions, this.options.getWorkspaceRouter().getThreadSessionKey(input.currentThreadId), input.currentThreadId);
164
170
  return;
165
171
  }
166
172
  await this.sendImmediateCard(input.workspaceId, input.chatId, result.displayText, input.instanceId);
@@ -185,7 +191,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
185
191
  continue;
186
192
  }
187
193
  if (part.type === 'file') {
188
- const sent = await this.sendFilePart(state, channelId, part);
194
+ const sent = await this.outboundTransport.sendFilePart(state, channelId, part);
189
195
  messageIds.push(sent.messageId);
190
196
  attachments.push({
191
197
  kind: 'file',
@@ -231,46 +237,6 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
231
237
  fileSize: attachment?.fileSize || 0,
232
238
  };
233
239
  }
234
- async sendFilePart(state, channelId, part) {
235
- const file = await (0, file_utils_js_1.prepareChannelFile)({
236
- path: part.path,
237
- fileName: part.fileName,
238
- workspacePath: typeof part.metadata?.workspacePath === 'string' ? part.metadata.workspacePath : undefined,
239
- maxBytes: LARK_MAX_UPLOAD_FILE_SIZE,
240
- platformLabel: 'Lark',
241
- });
242
- const upload = await state.client.im.file.create({
243
- data: {
244
- file_type: this.resolveLarkUploadFileType(file.fileName),
245
- file_name: file.fileName,
246
- file: (0, node_fs_1.createReadStream)(file.path),
247
- },
248
- });
249
- const fileKey = String(upload?.file_key || upload?.data?.file_key || '').trim();
250
- if (!fileKey) {
251
- throw new Error('Lark file upload did not return a file key');
252
- }
253
- const response = await state.client.im.message.create({
254
- params: {
255
- receive_id_type: this.resolveReceiveIdType(channelId),
256
- },
257
- data: {
258
- receive_id: channelId,
259
- msg_type: 'file',
260
- content: JSON.stringify({ file_key: fileKey }),
261
- },
262
- });
263
- const messageId = String(response?.data?.message_id || '').trim();
264
- if (!messageId) {
265
- throw new Error('Lark file message did not return a message id');
266
- }
267
- this.options.log?.(`localcore-lark sent file ${file.fileName} (${file.fileSize} bytes) to ${channelId}`);
268
- return {
269
- messageId,
270
- fileKey,
271
- file,
272
- };
273
- }
274
240
  async onBridgeEvent(event) {
275
241
  if (!event.sessionKey) {
276
242
  this.options.log?.(`localcore-lark bridge event ignored without sessionKey: ${event.type}`);
@@ -327,7 +293,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
327
293
  }
328
294
  if (event.type === 'typing_start' && (turn.permissionMessageId || turn.awaitingPermission)) {
329
295
  if (turn.permissionMessageId) {
330
- await this.patchTextCard(state, turn.permissionMessageId, '**工具确认已处理**\n\n继续生成中...', [], sessionKey, bridgeThreadId);
296
+ await this.outboundTransport.patchTextCard(state, turn.permissionMessageId, '**工具确认已处理**\n\n继续生成中...', [], sessionKey, bridgeThreadId);
331
297
  }
332
298
  turn.permissionMessageId = undefined;
333
299
  turn.awaitingPermission = false;
@@ -340,14 +306,14 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
340
306
  const permissionCard = (0, cards_js_1.renderPermissionCard)(turn, event, Boolean(state.cardActionsEnabled));
341
307
  if (permissionCard.text || permissionCard.buttonRows.length > 0) {
342
308
  if (!turn.permissionMessageId) {
343
- const createdId = await this.sendTextAsCard(state, route.chatId, permissionCard.text, permissionCard.buttonRows, sessionKey, bridgeThreadId);
309
+ const createdId = await this.outboundTransport.sendTextAsCard(state, route.chatId, permissionCard.text, permissionCard.buttonRows, sessionKey, bridgeThreadId);
344
310
  if (createdId) {
345
311
  turn.permissionMessageId = createdId;
346
312
  this.options.log?.(`localcore-lark sent permission card ${createdId} for sessionKey=${sessionKey}`);
347
313
  }
348
314
  }
349
315
  else {
350
- await this.patchTextCard(state, turn.permissionMessageId, permissionCard.text, permissionCard.buttonRows, sessionKey, bridgeThreadId);
316
+ await this.outboundTransport.patchTextCard(state, turn.permissionMessageId, permissionCard.text, permissionCard.buttonRows, sessionKey, bridgeThreadId);
351
317
  this.options.log?.(`localcore-lark patched permission card ${turn.permissionMessageId} for sessionKey=${sessionKey}`);
352
318
  }
353
319
  }
@@ -376,7 +342,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
376
342
  const sentMessage = sendAsPlainMessage
377
343
  ? await this.sendTextAsMessage(state, route.chatId, renderedMessage.text)
378
344
  : {
379
- messageId: await this.sendTextAsCard(state, route.chatId, renderedMessage.text, renderedMessage.buttonRows, sessionKey, bridgeThreadId),
345
+ messageId: await this.outboundTransport.sendTextAsCard(state, route.chatId, renderedMessage.text, renderedMessage.buttonRows, sessionKey, bridgeThreadId),
380
346
  renderKind: 'card',
381
347
  };
382
348
  const createdId = sentMessage.messageId;
@@ -392,7 +358,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
392
358
  if (renderedMessage.delivery === 'message') {
393
359
  continue;
394
360
  }
395
- await this.patchTextCard(state, existingMessageId, renderedMessage.text, renderedMessage.buttonRows, sessionKey, bridgeThreadId);
361
+ await this.outboundTransport.patchTextCard(state, existingMessageId, renderedMessage.text, renderedMessage.buttonRows, sessionKey, bridgeThreadId);
396
362
  turn.lastPatchedAt = Date.now();
397
363
  turn.lastPatchedAtByMessageId[existingMessageId] = turn.lastPatchedAt;
398
364
  this.options.log?.(`localcore-lark patched card message ${existingMessageId} for sessionKey=${sessionKey}`);
@@ -426,7 +392,6 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
426
392
  messageId: msg.messageId,
427
393
  },
428
394
  });
429
- this.options.store.expirePendingPairings();
430
395
  const runtimeState = this.resolveRuntimeState(msg.workspaceId, instanceId).state;
431
396
  let binding;
432
397
  try {
@@ -438,47 +403,28 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
438
403
  }
439
404
  this.options.log?.(`localcore-lark using active runtime binding snapshot for ${msg.workspaceId}/${instanceId}: ${error instanceof Error ? error.message : String(error)}`);
440
405
  }
441
- let authorized = this.options.store.getAuthorizedUser(msg.workspaceId, msg.platformUserId, platformKey);
442
- if (!authorized) {
443
- if (binding?.autoApprove || runtimeState?.autoApprove) {
444
- const authorizedAt = new Date().toISOString();
445
- this.options.store.createAuthorizedUser({
446
- id: `lark-user-${(0, node_crypto_1.randomUUID)()}`,
447
- workspace_id: msg.workspaceId,
448
- platform: platformKey,
449
- platform_user_id: msg.platformUserId,
450
- chat_id: msg.chatId,
451
- display_name: msg.displayName,
452
- thread_id: null,
453
- authorized_at: authorizedAt,
454
- });
455
- authorized = this.options.store.getAuthorizedUser(msg.workspaceId, msg.platformUserId, platformKey);
456
- this.options.log?.(`localcore-lark auto-approved user for ${msg.workspaceId}: ${msg.platformUserId}`);
457
- this.notifyRuntimeStateChanged();
458
- }
459
- }
460
- if (!authorized) {
461
- const existingPending = this.options.store.listPendingPairings(msg.workspaceId).find((item) => item.platform === platformKey && item.platform_user_id === msg.platformUserId && item.chat_id === msg.chatId && item.status === 'pending');
462
- let pairingCode = existingPending?.code || '';
463
- if (!existingPending) {
464
- const now = new Date();
465
- pairingCode = this.generatePairingCode();
466
- this.options.store.createPairingRequest({
467
- code: pairingCode,
468
- workspace_id: msg.workspaceId,
469
- platform: platformKey,
470
- platform_user_id: msg.platformUserId,
471
- chat_id: msg.chatId,
472
- display_name: msg.displayName,
473
- requested_at: now.toISOString(),
474
- expires_at: new Date(now.getTime() + PAIRING_EXPIRY_MS).toISOString(),
475
- status: 'pending',
476
- });
477
- this.notifyRuntimeStateChanged();
478
- }
479
- await this.sendImmediateCard(msg.workspaceId, msg.chatId, (0, cards_js_1.renderPendingPairingCard)(pairingCode), instanceId);
406
+ const authorization = (0, inbound_authorization_js_1.resolveInboundChannelAuthorization)({
407
+ store: this.options.store,
408
+ identity: {
409
+ workspaceId: msg.workspaceId,
410
+ platformKey,
411
+ platformUserId: msg.platformUserId,
412
+ chatId: msg.chatId,
413
+ displayName: msg.displayName,
414
+ },
415
+ autoApprove: Boolean(binding?.autoApprove || runtimeState?.autoApprove),
416
+ authorizedUserIdPrefix: 'lark-user',
417
+ generatePairingCode: () => this.generatePairingCode(),
418
+ onStateChanged: () => this.notifyRuntimeStateChanged(),
419
+ });
420
+ if (authorization.status === 'pending') {
421
+ await this.sendImmediateCard(msg.workspaceId, msg.chatId, (0, cards_js_1.renderPendingPairingCard)(authorization.pairingCode), instanceId);
480
422
  return; // { paired: false };
481
423
  }
424
+ if (authorization.autoApproved) {
425
+ this.options.log?.(`localcore-lark auto-approved user for ${msg.workspaceId}: ${msg.platformUserId}`);
426
+ }
427
+ const authorized = authorization.authorized;
482
428
  const router = this.options.getWorkspaceRouter();
483
429
  let { threadId } = await (0, thread_routing_js_1.resolveChannelThreadRoute)({
484
430
  store: this.options.store,
@@ -531,10 +477,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
531
477
  return; // { paired: true, threadId };
532
478
  }
533
479
  this.options.store.clearPlatformThreadMessageId(msg.workspaceId, msg.chatId, msg.platformUserId);
534
- const wrappedText = slashCommand
535
- ? msg.text
536
- : (0, desktop_js_1.wrapUserMessageWithSchedulerProtocol)(msg.text);
537
- await router.sendThreadMessage(threadId, (0, content_js_1.createChannelThreadMessageInput)(wrappedText, msg.contentParts));
480
+ await router.sendThreadMessage(threadId, (0, content_js_1.createChannelThreadMessageInput)(msg.text, msg.contentParts));
538
481
  return; // { paired: true, threadId };
539
482
  }
540
483
  async createSdkClientResult(binding) {
@@ -587,7 +530,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
587
530
  this.runtime.set(key, status);
588
531
  this.notifyRuntimeStateChanged();
589
532
  try {
590
- this.options.log?.(`localcore-lark starting workspace=${binding.workspaceId} app=${this.maskLarkAppId(binding.appId)} cardActions=${binding.cardActionsEnabled}`);
533
+ this.options.log?.(`localcore-lark starting workspace=${binding.workspaceId} app=${(0, gateway_utils_js_1.maskLarkAppId)(binding.appId)} cardActions=${binding.cardActionsEnabled}`);
591
534
  const mod = await this.getLarkModule();
592
535
  status.client = new mod.Client({
593
536
  appId: binding.appId,
@@ -610,7 +553,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
610
553
  });
611
554
  status.eventDispatcher.register({
612
555
  'im.message.receive_v1': async (data) => {
613
- this.options.log?.(`localcore-lark received im.message.receive_v1 for ${binding.workspaceId}/${binding.instanceId}: ${this.summarizeLarkEvent(data)}`);
556
+ this.options.log?.(`localcore-lark received im.message.receive_v1 for ${binding.workspaceId}/${binding.instanceId}: ${(0, inbound_js_1.summarizeLarkInboundPayload)(data)}`);
614
557
  void this.handleMessageEvent(binding.workspaceId, binding.instanceId, binding.platformKey, data).catch((error) => {
615
558
  this.options.log?.(`localcore-lark inbound message failed for ${binding.workspaceId}: ${error instanceof Error ? error.message : String(error)}`);
616
559
  });
@@ -629,7 +572,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
629
572
  domain: mod.Domain.Feishu,
630
573
  loggerLevel: mod.LoggerLevel.info,
631
574
  });
632
- this.attachWsDiagnostics(binding.workspaceId, status.wsClient);
575
+ (0, gateway_utils_js_1.attachLarkWsDiagnostics)(binding.workspaceId, status.wsClient, this.options.log);
633
576
  this.options.log?.(`localcore-lark ws starting for ${binding.workspaceId}`);
634
577
  await status.wsClient.start({
635
578
  eventDispatcher: status.eventDispatcher,
@@ -656,279 +599,13 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
656
599
  this.notifyRuntimeStateChanged();
657
600
  }
658
601
  async handleMessageEvent(workspaceId, instanceIdOrData, platformKeyOrData, maybeData) {
659
- const legacyCall = typeof instanceIdOrData === 'object';
660
- const instanceId = legacyCall ? 'default' : instanceIdOrData;
661
- const platformKey = legacyCall ? 'lark' : String(platformKeyOrData || (0, channel_keys_js_1.channelPlatformKey)('lark', instanceId));
662
- const data = (legacyCall ? instanceIdOrData : maybeData) || {};
663
- const runtimeState = this.resolveRuntimeState(workspaceId, instanceId).state;
664
- const normalized = (0, inbound_js_1.normalizeLarkInboundMessageEvent)(data, {
665
- botOpenId: runtimeState?.botOpenId,
666
- groupReplyAll: runtimeState?.groupReplyAll,
667
- });
668
- this.options.log?.(`localcore-lark handling message event for ${workspaceId}: ${(0, inbound_js_1.summarizeLarkInboundPayload)(data)}`);
669
- if (!normalized.ok) {
670
- this.options.log?.(`localcore-lark ignored message event for ${workspaceId}: reason=${normalized.reason}${normalized.detail ? ` ${normalized.detail}` : ''}`);
671
- return;
672
- }
673
- const { message, parsedContent, messageType, chatType, mentions, text, platformUserId, chatId, displayName, messageId, } = normalized.message;
674
- const mayMaterializeAttachments = Boolean(runtimeState?.autoApprove
675
- || this.options.store.getAuthorizedUser(workspaceId, platformUserId, platformKey));
676
- const contentParts = [];
677
- if (text) {
678
- contentParts.push({ type: 'text', text });
679
- }
680
- if (messageType === 'image') {
681
- const imageKey = String(parsedContent.image_key || parsedContent.file_key || '').trim();
682
- if (imageKey) {
683
- if (!mayMaterializeAttachments) {
684
- contentParts.push({ type: 'text', text: '[Image]' });
685
- }
686
- else {
687
- try {
688
- contentParts.push(await this.downloadMessageImage(workspaceId, String(message.message_id || ''), imageKey, instanceId));
689
- }
690
- catch (error) {
691
- const errorText = `[Image download failed: ${error instanceof Error ? error.message : String(error)}]`;
692
- contentParts.push({ type: 'text', text: errorText });
693
- this.options.log?.(`localcore-lark image download failed for ${workspaceId}: message=${String(message.message_id || '')} imageKey=${imageKey} error=${error instanceof Error ? error.message : String(error)}`);
694
- }
695
- }
696
- }
697
- }
698
- if (messageType === 'file') {
699
- const fileKey = String(parsedContent.file_key || '').trim();
700
- if (fileKey) {
701
- if (!mayMaterializeAttachments) {
702
- const inboundFileName = String(parsedContent.file_name || parsedContent.name || '').trim();
703
- contentParts.push({ type: 'text', text: inboundFileName ? `[File: ${inboundFileName}]` : '[File]' });
704
- }
705
- else {
706
- try {
707
- contentParts.push(await this.downloadMessageFile(workspaceId, String(message.message_id || ''), fileKey, String(parsedContent.file_name || parsedContent.name || '').trim(), instanceId));
708
- }
709
- catch (error) {
710
- const errorText = `[File download failed: ${error instanceof Error ? error.message : String(error)}]`;
711
- contentParts.push({ type: 'text', text: errorText });
712
- this.options.log?.(`localcore-lark file download failed for ${workspaceId}: message=${String(message.message_id || '')} fileKey=${fileKey} error=${error instanceof Error ? error.message : String(error)}`);
713
- }
714
- }
715
- }
716
- }
717
- if (contentParts.length === 0) {
718
- this.options.log?.(`localcore-lark ignored unsupported message for ${workspaceId}: type=${String(message.message_type || 'unknown')} contentKeys=${JSON.stringify(Object.keys(parsedContent))}`);
719
- return;
720
- }
721
- const displayText = text || this.summarizeInboundContentParts(contentParts);
722
- this.options.log?.(`localcore-lark inbound message for ${workspaceId}: chat=${chatId} user=${platformUserId} chatType=${chatType || 'unknown'} mentions=${mentions.length} type=${messageType || 'unknown'} text=${JSON.stringify(displayText.slice(0, 120))}`);
723
- await this.handleInboundMessage({
724
- workspaceId,
725
- instanceId,
726
- platformKey,
727
- platformUserId,
728
- chatId,
729
- displayName,
730
- text: displayText,
731
- messageId,
732
- contentParts,
733
- });
602
+ await this.inboundHandler.handleMessageEvent(workspaceId, instanceIdOrData, platformKeyOrData, maybeData);
734
603
  }
735
604
  async downloadMessageImage(workspaceId, messageId, imageKey, instanceId) {
736
- const state = this.resolveRuntimeState(workspaceId, instanceId).state;
737
- if (!state?.client) {
738
- throw new Error('Lark client is not connected');
739
- }
740
- if (!messageId) {
741
- throw new Error('Lark image message is missing message_id');
742
- }
743
- const downloadsDir = await this.resolveInboundDownloadsDir(workspaceId, instanceId, state.downloadsDir);
744
- const stored = await this.inboundAttachmentStore.save({
745
- directory: downloadsDir,
746
- storedFileName: `${messageId}-${imageKey}`,
747
- displayFileName: imageKey,
748
- maxBytes: LARK_MAX_UPLOAD_FILE_SIZE,
749
- includeBase64: true,
750
- finalizeStoredFileName: ({ storedFileName, prefix }) => `${storedFileName}.${this.sniffImageExtension(prefix)}`,
751
- source: {
752
- open: async () => {
753
- const resource = await state.client.im.messageResource.get({
754
- path: {
755
- message_id: messageId,
756
- file_key: imageKey,
757
- },
758
- params: {
759
- type: 'image',
760
- },
761
- });
762
- const stream = resource?.getReadableStream?.();
763
- if (!stream || typeof stream.pipe !== 'function') {
764
- throw new Error('Lark image resource did not provide a readable stream');
765
- }
766
- return {
767
- stream,
768
- mimeType: this.extractHeaderMimeType(resource?.headers),
769
- };
770
- },
771
- },
772
- });
773
- const extension = (0, node_path_1.extname)(stored.path).slice(1) || 'bin';
774
- const uri = await this.resolveInboundAttachmentUri(workspaceId, stored.path, instanceId);
775
- return {
776
- type: 'image',
777
- data: stored.data || '',
778
- ...(uri ? { uri } : {}),
779
- mimeType: stored.mimeType || this.sniffImageMimeType(stored.prefix),
780
- fileName: `${imageKey}.${extension}`,
781
- };
605
+ return this.inboundHandler.downloadMessageImage(workspaceId, messageId, imageKey, instanceId);
782
606
  }
783
607
  async downloadMessageFile(workspaceId, messageId, fileKey, fileName, instanceId) {
784
- const state = this.resolveRuntimeState(workspaceId, instanceId).state;
785
- if (!state?.client) {
786
- throw new Error('Lark client is not connected');
787
- }
788
- if (!messageId) {
789
- throw new Error('Lark file message is missing message_id');
790
- }
791
- const downloadsDir = await this.resolveInboundDownloadsDir(workspaceId, instanceId, state.downloadsDir);
792
- const displayFileName = fileName || fileKey;
793
- const stored = await this.inboundAttachmentStore.save({
794
- directory: downloadsDir,
795
- storedFileName: `${messageId}-${displayFileName}`,
796
- displayFileName,
797
- maxBytes: LARK_MAX_UPLOAD_FILE_SIZE,
798
- source: {
799
- open: async () => {
800
- const resource = await state.client.im.messageResource.get({
801
- path: {
802
- message_id: messageId,
803
- file_key: fileKey,
804
- },
805
- params: {
806
- type: 'file',
807
- },
808
- });
809
- const stream = resource?.getReadableStream?.();
810
- if (!stream || typeof stream.pipe !== 'function') {
811
- throw new Error('Lark file resource did not provide a readable stream');
812
- }
813
- return {
814
- stream,
815
- mimeType: this.extractHeaderMimeType(resource?.headers) || 'application/octet-stream',
816
- };
817
- },
818
- },
819
- });
820
- return {
821
- type: 'file',
822
- path: stored.path,
823
- fileName: stored.fileName,
824
- mimeType: stored.mimeType,
825
- size: stored.size,
826
- };
827
- }
828
- async resolveInboundDownloadsDir(workspaceId, instanceId = 'default', runtimeDownloadsDir) {
829
- const binding = runtimeDownloadsDir === undefined
830
- ? await this.getBinding(workspaceId, instanceId)
831
- : undefined;
832
- const configuredDir = String(runtimeDownloadsDir ?? binding?.downloadsDir ?? '').trim();
833
- if (configuredDir && (0, node_path_1.isAbsolute)(configuredDir)) {
834
- return configuredDir;
835
- }
836
- const workspace = await this.options.getWorkspaceRouter().getWorkspaceRegistryEntry(workspaceId);
837
- return configuredDir
838
- ? (0, node_path_1.resolve)(workspace.path, configuredDir)
839
- : (0, node_path_1.join)(workspace.path, '.agentdock', 'channel-uploads', 'lark', instanceId);
840
- }
841
- async resolveInboundAttachmentUri(workspaceId, filePath, instanceId = 'default') {
842
- const binding = await this.getBinding(workspaceId, instanceId).catch(() => undefined);
843
- if (!binding) {
844
- return undefined;
845
- }
846
- const sandbox = binding.project.agent?.options?.sandbox;
847
- if (!sandbox?.enabled) {
848
- return (0, inbound_attachment_store_js_1.resolveInboundAttachmentUri)({ filePath });
849
- }
850
- const workspace = await this.options.getWorkspaceRouter().getWorkspaceRegistryEntry(workspaceId).catch(() => undefined);
851
- if (!workspace) {
852
- return undefined;
853
- }
854
- return (0, inbound_attachment_store_js_1.resolveInboundAttachmentUri)({
855
- filePath,
856
- workspacePath: workspace.path,
857
- sandboxEnabled: true,
858
- sandboxWorkspacePath: sandbox.workspace_mount_path,
859
- });
860
- }
861
- summarizeInboundContentParts(parts) {
862
- const text = parts
863
- .filter((part) => part.type === 'text')
864
- .map((part) => part.text)
865
- .filter(Boolean)
866
- .join('\n\n')
867
- .trim();
868
- if (text)
869
- return text;
870
- const attachmentSummary = parts
871
- .map((part) => {
872
- if (part.type === 'image') {
873
- return '[Image]';
874
- }
875
- if (part.type === 'file') {
876
- return part.fileName ? `[File: ${part.fileName}]` : '[File]';
877
- }
878
- return '';
879
- })
880
- .filter(Boolean)
881
- .join('\n');
882
- return attachmentSummary;
883
- }
884
- extractHeaderMimeType(headers) {
885
- const value = headers && typeof headers === 'object'
886
- ? headers['content-type'] || headers['Content-Type']
887
- : '';
888
- return String(value || '').split(';')[0]?.trim() || '';
889
- }
890
- sniffImageMimeType(buffer) {
891
- if (buffer[0] === 0xff && buffer[1] === 0xd8)
892
- return 'image/jpeg';
893
- if (buffer[0] === 0x89 && buffer[1] === 0x50 && buffer[2] === 0x4e && buffer[3] === 0x47)
894
- return 'image/png';
895
- if (buffer[0] === 0x47 && buffer[1] === 0x49 && buffer[2] === 0x46)
896
- return 'image/gif';
897
- if (buffer[0] === 0x52 && buffer[1] === 0x49 && buffer[2] === 0x46 && buffer[3] === 0x46)
898
- return 'image/webp';
899
- return 'application/octet-stream';
900
- }
901
- sniffImageExtension(buffer) {
902
- const mimeType = this.sniffImageMimeType(buffer);
903
- if (mimeType === 'image/jpeg')
904
- return 'jpg';
905
- if (mimeType === 'image/png')
906
- return 'png';
907
- if (mimeType === 'image/gif')
908
- return 'gif';
909
- if (mimeType === 'image/webp')
910
- return 'webp';
911
- return 'bin';
912
- }
913
- attachWsDiagnostics(workspaceId, wsClient) {
914
- const on = typeof wsClient?.on === 'function' ? wsClient.on.bind(wsClient) : null;
915
- if (!on) {
916
- this.options.log?.(`localcore-lark ws diagnostics unavailable for ${workspaceId}: client has no on()`);
917
- return;
918
- }
919
- for (const eventName of ['open', 'connect', 'connected', 'ready', 'close', 'closed', 'disconnect', 'error', 'reconnect']) {
920
- try {
921
- on(eventName, (...args) => {
922
- this.options.log?.(`localcore-lark ws event ${eventName} for ${workspaceId}: ${this.summarizeWsArgs(args)}`);
923
- });
924
- }
925
- catch (error) {
926
- this.options.log?.(`localcore-lark ws diagnostic hook failed for ${workspaceId} event=${eventName}: ${error instanceof Error ? error.message : String(error)}`);
927
- }
928
- }
929
- }
930
- summarizeLarkEvent(data) {
931
- return (0, inbound_js_1.summarizeLarkInboundPayload)(data);
608
+ return this.inboundHandler.downloadMessageFile(workspaceId, messageId, fileKey, fileName, instanceId);
932
609
  }
933
610
  async fetchBotOpenId(state) {
934
611
  const response = await state.client.request({
@@ -942,30 +619,6 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
942
619
  }
943
620
  return openId;
944
621
  }
945
- summarizeWsArgs(args) {
946
- if (args.length === 0) {
947
- return 'no-args';
948
- }
949
- return args.map((arg) => {
950
- if (arg instanceof Error) {
951
- return `${arg.name}: ${arg.message}`;
952
- }
953
- if (typeof arg === 'string') {
954
- return arg.slice(0, 200);
955
- }
956
- if (arg && typeof arg === 'object') {
957
- return JSON.stringify(Object.keys(arg));
958
- }
959
- return String(arg);
960
- }).join(' ');
961
- }
962
- maskLarkAppId(appId) {
963
- const value = String(appId || '').trim();
964
- if (value.length <= 8) {
965
- return value ? '***' : '';
966
- }
967
- return `${value.slice(0, 6)}...${value.slice(-4)}`;
968
- }
969
622
  makeThreadRoute(input, threadId) {
970
623
  return {
971
624
  workspaceId: input.workspaceId,
@@ -982,7 +635,6 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
982
635
  });
983
636
  }
984
637
  buildStatusObject(state, _resolved) {
985
- this.options.store.expirePendingPairings();
986
638
  const resolved = this.resolveRuntimeState(state.workspaceId, state.instanceId);
987
639
  const binding = resolved.state;
988
640
  const platformKey = binding?.platformKey || (0, channel_keys_js_1.channelPlatformKey)('lark', resolved.instanceId);
@@ -1054,94 +706,8 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
1054
706
  }
1055
707
  return this.larkModulePromise;
1056
708
  }
1057
- async sendTextAsCard(state, chatId, text, buttonRows = [], sessionKey, threadId) {
1058
- const startedAt = Date.now();
1059
- const response = await state.client.im.message.create({
1060
- params: {
1061
- receive_id_type: this.resolveReceiveIdType(chatId),
1062
- },
1063
- data: {
1064
- receive_id: chatId,
1065
- msg_type: 'interactive',
1066
- content: JSON.stringify((0, cards_js_1.buildInteractiveCard)(text, buttonRows, sessionKey, threadId)),
1067
- },
1068
- });
1069
- this.options.log?.(`localcore-lark card create took ${Date.now() - startedAt}ms textBytes=${Buffer.byteLength(text || '', 'utf8')}`);
1070
- return String(response?.data?.message_id || '').trim();
1071
- }
1072
- async sendSessionCommandCard(state, chatId, text, actionRows, sessionKey, threadId) {
1073
- const startedAt = Date.now();
1074
- const response = await state.client.im.message.create({
1075
- params: {
1076
- receive_id_type: this.resolveReceiveIdType(chatId),
1077
- },
1078
- data: {
1079
- receive_id: chatId,
1080
- msg_type: 'interactive',
1081
- content: JSON.stringify((0, cards_js_1.buildSessionCommandCard)(text, actionRows, sessionKey, threadId)),
1082
- },
1083
- });
1084
- this.options.log?.(`localcore-lark session card create took ${Date.now() - startedAt}ms textBytes=${Buffer.byteLength(text || '', 'utf8')}`);
1085
- return String(response?.data?.message_id || '').trim();
1086
- }
1087
709
  async sendTextAsMessage(state, chatId, text) {
1088
- const startedAt = Date.now();
1089
- const rendered = (0, messages_js_1.renderLarkTextMessage)(text);
1090
- const response = await state.client.im.message.create({
1091
- params: {
1092
- receive_id_type: this.resolveReceiveIdType(chatId),
1093
- },
1094
- data: {
1095
- receive_id: chatId,
1096
- msg_type: rendered.msgType,
1097
- content: JSON.stringify(rendered.content),
1098
- },
1099
- });
1100
- this.options.log?.(`localcore-lark ${rendered.renderKind} create took ${Date.now() - startedAt}ms msgType=${rendered.msgType} reason=${rendered.reason} tableCount=${rendered.tableCount} textBytes=${Buffer.byteLength(text || '', 'utf8')}`);
1101
- return {
1102
- messageId: String(response?.data?.message_id || '').trim(),
1103
- renderKind: rendered.renderKind,
1104
- msgType: rendered.msgType,
1105
- };
1106
- }
1107
- resolveReceiveIdType(receiveId) {
1108
- return receiveId.startsWith('oc_') ? 'chat_id' : receiveId.startsWith('ou_') ? 'open_id' : 'user_id';
1109
- }
1110
- resolveLarkUploadFileType(fileName) {
1111
- switch ((0, node_path_1.extname)(fileName).toLowerCase()) {
1112
- case '.opus':
1113
- return 'opus';
1114
- case '.mp4':
1115
- case '.mov':
1116
- case '.m4v':
1117
- return 'mp4';
1118
- case '.pdf':
1119
- return 'pdf';
1120
- case '.doc':
1121
- case '.docx':
1122
- return 'doc';
1123
- case '.xls':
1124
- case '.xlsx':
1125
- case '.csv':
1126
- return 'xls';
1127
- case '.ppt':
1128
- case '.pptx':
1129
- return 'ppt';
1130
- default:
1131
- return 'stream';
1132
- }
1133
- }
1134
- async patchTextCard(state, messageId, text, buttonRows = [], sessionKey, threadId) {
1135
- const startedAt = Date.now();
1136
- await state.client.im.message.patch({
1137
- path: {
1138
- message_id: messageId,
1139
- },
1140
- data: {
1141
- content: JSON.stringify((0, cards_js_1.buildInteractiveCard)(text, buttonRows, sessionKey, threadId)),
1142
- },
1143
- });
1144
- this.options.log?.(`localcore-lark card patch took ${Date.now() - startedAt}ms message=${messageId} textBytes=${Buffer.byteLength(text || '', 'utf8')}`);
710
+ return this.outboundTransport.sendTextAsMessage(state, chatId, text);
1145
711
  }
1146
712
  generatePairingCode() {
1147
713
  return String((0, node_crypto_1.randomInt)(100000, 1000000));
@@ -1269,7 +835,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
1269
835
  return;
1270
836
  }
1271
837
  try {
1272
- await this.patchTextCard(state, messageId, [
838
+ await this.outboundTransport.patchTextCard(state, messageId, [
1273
839
  '**工具确认已处理**',
1274
840
  `已选择:${(0, cards_js_1.formatPermissionResponseLabel)(response)}`,
1275
841
  '等待代理继续执行...',
@@ -1290,7 +856,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
1290
856
  return '';
1291
857
  }
1292
858
  try {
1293
- return await this.sendTextAsCard(state, chatId, text);
859
+ return await this.outboundTransport.sendTextAsCard(state, chatId, text);
1294
860
  }
1295
861
  catch (error) {
1296
862
  this.options.log?.(`localcore-lark immediate card failed for ${workspaceId}: ${error instanceof Error ? error.message : String(error)}`);