@kafca/agentdock 0.1.56 → 0.1.58

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 (200) hide show
  1. package/README.md +7 -0
  2. package/dist/renderer/assets/{Badge-DjcoXx2J.js → Badge-BfY1VaHS.js} +1 -1
  3. package/dist/renderer/assets/Card-DWA_Tww_.js +1 -0
  4. package/dist/renderer/assets/Config-nHj3g1U5.js +21 -0
  5. package/dist/renderer/assets/CronList-BwkA_I7v.js +1 -0
  6. package/dist/renderer/assets/Dashboard-D0_A7k02.js +41 -0
  7. package/dist/renderer/assets/{EmptyState-DIZLiccW.js → EmptyState-zatDjLj_.js} +1 -1
  8. package/dist/renderer/assets/HighlightedMarkdown-CsM5n70d.js +12 -0
  9. package/dist/renderer/assets/Input-R1XdFK1K.js +1 -0
  10. package/dist/renderer/assets/{KnowledgeDetail-CJ9IYOsa.js → KnowledgeDetail-Co5sxeGd.js} +2 -2
  11. package/dist/renderer/assets/{KnowledgeHome-BLGPwnBO.js → KnowledgeHome-DwziPw5m.js} +3 -3
  12. package/dist/renderer/assets/Logs-NwZUtR_G.js +6 -0
  13. package/dist/renderer/assets/{Modal-CQiUpfl4.js → Modal-CrcIwIFL.js} +3 -3
  14. package/dist/renderer/assets/MonitorList-CS1uLS5A.js +1 -0
  15. package/dist/renderer/assets/Page-Dp0obeSw.js +1 -0
  16. package/dist/renderer/assets/{Select-D6z65IT3.js → Select-6mVQaf84.js} +2 -2
  17. package/dist/renderer/assets/ThreadChat-BFzbn3L6.js +86 -0
  18. package/dist/renderer/assets/Workspace-DCmo8BMm.js +19 -0
  19. package/dist/renderer/assets/{arrow-left-CV5cL3f4.js → arrow-left-9rjg_Hp4.js} +1 -1
  20. package/dist/renderer/assets/{book-open-DThvB7pj.js → book-open-Bu8GCHnG.js} +1 -1
  21. package/dist/renderer/assets/channels-BxVbG-6j.js +6 -0
  22. package/dist/renderer/assets/chevron-down-BE8uQmWM.js +11 -0
  23. package/dist/renderer/assets/index-B7TeF6Es.js +41 -0
  24. package/dist/renderer/assets/index-BIKL3fTP.css +11 -0
  25. package/dist/renderer/assets/index-BkI9POxj.js +167 -0
  26. package/dist/renderer/assets/knowledge-Kl19SqGS.js +1 -0
  27. package/dist/renderer/assets/{pencil-Dv5WxhdC.js → pencil-CPB7SK1m.js} +1 -1
  28. package/dist/renderer/assets/{play-DnCnft83.js → play-DGAO4OCu.js} +1 -1
  29. package/dist/renderer/assets/{plus-DsxIagzS.js → plus-Bt26z-4q.js} +1 -1
  30. package/dist/renderer/assets/{save-CST01lIc.js → save-Une7GMxT.js} +1 -1
  31. package/dist/renderer/assets/{search-B_bqy6Wd.js → search-DE0agJjJ.js} +1 -1
  32. package/dist/renderer/assets/{shield-check-D6lG5Aoc.js → shield-check-De7xaXZh.js} +1 -1
  33. package/dist/renderer/assets/threads-BnsNL5ei.js +1 -0
  34. package/dist/renderer/assets/{trash-2-Cefngb6Q.js → trash-2-6iGF59Ac.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/automation/automation-conversation-executor.js +6 -47
  80. package/dist-electron/services/local-ai-core/src/automation/automation-monitor-service.js +2 -5
  81. package/dist-electron/services/local-ai-core/src/channel/lark/cards.js +33 -18
  82. package/dist-electron/services/local-ai-core/src/channel/lark/config.js +2 -2
  83. package/dist-electron/services/local-ai-core/src/channel/lark/gateway-utils.js +91 -0
  84. package/dist-electron/services/local-ai-core/src/channel/lark/inbound-handler.js +180 -0
  85. package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +58 -539
  86. package/dist-electron/services/local-ai-core/src/channel/lark/outbound-transport.js +112 -0
  87. package/dist-electron/services/local-ai-core/src/channel/lark/runtime-state.js +5 -20
  88. package/dist-electron/services/local-ai-core/src/channel/shared/base-channel-gateway.js +37 -0
  89. package/dist-electron/services/local-ai-core/src/channel/shared/bridge-event-helpers.js +23 -0
  90. package/dist-electron/services/local-ai-core/src/channel/shared/channel-keys.js +6 -0
  91. package/dist-electron/services/local-ai-core/src/channel/shared/inbound-authorization.js +54 -0
  92. package/dist-electron/services/local-ai-core/src/channel/weixin/config.js +2 -2
  93. package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-media.js +21 -0
  94. package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-poller.js +167 -0
  95. package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +55 -512
  96. package/dist-electron/services/local-ai-core/src/channel/weixin/runtime-state.js +149 -0
  97. package/dist-electron/services/local-ai-core/src/channel/weixin/text-utils.js +92 -0
  98. package/dist-electron/services/local-ai-core/src/cli/lac.js +9 -11
  99. package/dist-electron/services/local-ai-core/src/cli/monitor-cli-parsers.js +2 -2
  100. package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +28 -70
  101. package/dist-electron/services/local-ai-core/src/kernel/local-core-errors.js +8 -0
  102. package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-ai-vector-plugin.js +2 -2
  103. package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-noop-plugin.js +2 -2
  104. package/dist-electron/services/local-ai-core/src/router/workspace-bridge-event-stream.js +29 -0
  105. package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +5 -5
  106. package/dist-electron/services/local-ai-core/src/router/workspace-router.js +47 -60
  107. package/dist-electron/services/local-ai-core/src/runtime/agent-runtime-detector.js +5 -5
  108. package/dist-electron/services/local-ai-core/src/runtime/config-migration.js +6 -6
  109. package/dist-electron/services/local-ai-core/src/runtime/deployment-diagnostics.js +3 -3
  110. package/dist-electron/services/local-ai-core/src/runtime/external-service.js +3 -1
  111. package/dist-electron/services/local-ai-core/src/runtime/handlers/automation-handler.js +11 -2
  112. package/dist-electron/services/local-ai-core/src/runtime/handlers/channel-handler.js +12 -6
  113. package/dist-electron/services/local-ai-core/src/runtime/handlers/external-handler.js +10 -2
  114. package/dist-electron/services/local-ai-core/src/runtime/handlers/knowledge-handler.js +18 -6
  115. package/dist-electron/services/local-ai-core/src/runtime/handlers/provider-handler.js +7 -2
  116. package/dist-electron/services/local-ai-core/src/runtime/handlers/runtime-handler.js +28 -3
  117. package/dist-electron/services/local-ai-core/src/runtime/handlers/scheduler-handler.js +10 -2
  118. package/dist-electron/services/local-ai-core/src/runtime/handlers/security-handler.js +18 -5
  119. package/dist-electron/services/local-ai-core/src/runtime/handlers/task-handler.js +14 -2
  120. package/dist-electron/services/local-ai-core/src/runtime/handlers/thread-handler.js +18 -15
  121. package/dist-electron/services/local-ai-core/src/runtime/handlers/workspace-handler.js +13 -2
  122. package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +35 -8
  123. package/dist-electron/services/local-ai-core/src/runtime/request-validation.js +79 -0
  124. package/dist-electron/services/local-ai-core/src/runtime/runtime-detection-service.js +9 -9
  125. package/dist-electron/services/local-ai-core/src/runtime/server-helpers.js +10 -1
  126. package/dist-electron/services/local-ai-core/src/runtime/server.js +2 -1
  127. package/dist-electron/services/local-ai-core/src/runtime/workspace-project-registry.js +76 -0
  128. package/dist-electron/services/local-ai-core/src/sandbox/opensandbox-client.js +3 -2
  129. package/dist-electron/services/local-ai-core/src/sandbox/sandbox-config.js +8 -8
  130. package/dist-electron/services/local-ai-core/src/scheduler/base-channel-schedule-adapter.js +77 -0
  131. package/dist-electron/services/local-ai-core/src/scheduler/lark-schedule-adapter.js +13 -79
  132. package/dist-electron/services/local-ai-core/src/scheduler/local-schedule-adapter.js +2 -10
  133. package/dist-electron/services/local-ai-core/src/scheduler/run-polling.js +19 -0
  134. package/dist-electron/services/local-ai-core/src/scheduler/scheduled-conversation-executor.js +3 -37
  135. package/dist-electron/services/local-ai-core/src/scheduler/scheduled-job-route.js +20 -0
  136. package/dist-electron/services/local-ai-core/src/scheduler/scheduler-service.js +15 -28
  137. package/dist-electron/services/local-ai-core/src/scheduler/thread-resolution.js +12 -0
  138. package/dist-electron/services/local-ai-core/src/scheduler/weixin-schedule-adapter.js +13 -79
  139. package/dist-electron/services/local-ai-core/src/thread/agent-message-policy.js +75 -0
  140. package/dist-electron/shared/desktop.js +1 -64
  141. package/dist-electron/src/components/chat/chat-controller-state.js +60 -0
  142. package/dist-electron/src/components/chat/chat-event-gate.js +146 -0
  143. package/dist-electron/src/components/chat/markdown-code-block.js +8 -0
  144. package/dist-electron/src/pages/Desktop/workspace-model.js +212 -0
  145. package/dist-electron/src/pages/Threads/thread-chat-model.js +50 -51
  146. package/dist-electron/tests/contracts/agent-message-policy.test.js +21 -0
  147. package/dist-electron/tests/contracts/architecture-docs.test.js +56 -33
  148. package/dist-electron/tests/contracts/chat-event-gate.test.js +114 -0
  149. package/dist-electron/tests/contracts/chat-markdown.test.js +16 -0
  150. package/dist-electron/tests/contracts/thread-task-state.test.js +32 -0
  151. package/dist-electron/tests/contracts/workspace-identity.test.js +23 -0
  152. package/dist-electron/tests/electron/core-client.test.js +284 -0
  153. package/dist-electron/tests/electron/plugin-kernel.test.js +54 -0
  154. package/dist-electron/tests/electron/renderer-packaging.test.js +9 -0
  155. package/dist-electron/tests/electron/workspace-task-store.test.js +31 -0
  156. package/dist-electron/tests/integration/channel-inbound-authorization.test.js +80 -0
  157. package/dist-electron/tests/integration/lark-gateway-utils.test.js +13 -0
  158. package/dist-electron/tests/integration/lark-gateway.test.js +4 -4
  159. package/dist-electron/tests/integration/local-core-refactor.test.js +15 -8
  160. package/dist-electron/tests/integration/weixin-runtime-state.test.js +32 -0
  161. package/dist-electron/tests/integration/weixin-text-utils.test.js +15 -0
  162. package/package.json +9 -4
  163. package/dist/renderer/assets/Chat-C5Bkm9-M.js +0 -2
  164. package/dist/renderer/assets/ChatMarkdown-uc36EzyD.js +0 -45
  165. package/dist/renderer/assets/Config-DHtQuuLy.js +0 -21
  166. package/dist/renderer/assets/CronList-BYUnhzSC.js +0 -1
  167. package/dist/renderer/assets/Dashboard-BPnGMDg3.js +0 -26
  168. package/dist/renderer/assets/Logs-Dyd2Uwlt.js +0 -1
  169. package/dist/renderer/assets/MonitorList-Byg3E3Gt.js +0 -1
  170. package/dist/renderer/assets/Page-7DxXvTMm.js +0 -1
  171. package/dist/renderer/assets/ProjectDetail-Dfr5s0Ja.js +0 -11
  172. package/dist/renderer/assets/ProjectList-CDDQjAQ_.js +0 -1
  173. package/dist/renderer/assets/SessionChat-s7CAaCPL.js +0 -1
  174. package/dist/renderer/assets/SessionList-D-OycKKS.js +0 -1
  175. package/dist/renderer/assets/ThreadChat-CLdFynB5.js +0 -28
  176. package/dist/renderer/assets/Workspace-xfT5z4j_.js +0 -19
  177. package/dist/renderer/assets/bot-CWQ5-ovl.js +0 -6
  178. package/dist/renderer/assets/check-DKM7zfWG.js +0 -6
  179. package/dist/renderer/assets/chevron-down-Dfw2KU87.js +0 -6
  180. package/dist/renderer/assets/circle-CoP4RA4s.js +0 -6
  181. package/dist/renderer/assets/desktop-CsDYrOOU.js +0 -1
  182. package/dist/renderer/assets/desktop-JQkhNOF4.js +0 -5
  183. package/dist/renderer/assets/funnel-DpVLlG3g.js +0 -6
  184. package/dist/renderer/assets/heart-BMD36ejP.js +0 -6
  185. package/dist/renderer/assets/index-COxSYBjE.js +0 -182
  186. package/dist/renderer/assets/index-CTGTI-cm.js +0 -41
  187. package/dist/renderer/assets/index-CjCuR6DI.css +0 -11
  188. package/dist/renderer/assets/projects-DgjHcNgt.js +0 -1
  189. package/dist/renderer/assets/server-ecH4GNwa.js +0 -11
  190. package/dist/renderer/assets/session-utils-Dd_WKMYW.js +0 -6
  191. package/dist/renderer/assets/sessions-BQ33Mv4k.js +0 -1
  192. package/dist/renderer/assets/user-D_8RSH-T.js +0 -6
  193. package/dist/renderer/assets/wifi-off-DB9D-pOu.js +0 -11
  194. package/dist-electron/services/local-ai-core/src/scheduler/lark-execution-policies.js +0 -13
  195. package/dist-electron/services/local-ai-core/src/scheduler/weixin-execution-policies.js +0 -13
  196. package/dist-electron/src/api/client.js +0 -73
  197. package/dist-electron/src/api/sessions.js +0 -21
  198. package/dist-electron/src/lib/session-utils.js +0 -51
  199. package/dist-electron/src/pages/Projects/project-provider-config.js +0 -75
  200. package/dist-electron/tests/electron/project-provider-config.test.js +0 -71
@@ -35,24 +35,21 @@ 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 local_core_slash_commands_js_1 = require("../../acp/local-core-slash-commands.js");
52
+ const gateway_utils_js_1 = require("./gateway-utils.js");
56
53
  const LARK_FINAL_PATCH_INTERVAL_MS = 900;
57
54
  const LARK_PROGRESS_PATCH_INTERVAL_MS = 3000;
58
55
  const LARK_EMPTY_RENDER_LOG_WINDOW_MS = 5 * 60 * 1000;
@@ -64,10 +61,20 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
64
61
  mirrorPermissionStateInMainCard = false;
65
62
  larkModulePromise = null;
66
63
  emptyRenderLogWindows = new Map();
67
- inboundAttachmentStore = new inbound_attachment_store_js_1.FileSystemInboundAttachmentStore();
64
+ inboundHandler;
65
+ outboundTransport;
68
66
  platform = 'lark';
69
67
  constructor(options) {
70
68
  super(options);
69
+ this.inboundHandler = new inbound_handler_js_1.LarkInboundHandler({
70
+ store: options.store,
71
+ getWorkspaceRouter: options.getWorkspaceRouter,
72
+ getRuntimeState: (workspaceId, instanceId) => this.resolveRuntimeState(workspaceId, instanceId).state,
73
+ getBinding: (workspaceId, instanceId) => this.getBinding(workspaceId, instanceId),
74
+ dispatchInboundMessage: (message) => this.handleInboundMessage(message),
75
+ log: options.log,
76
+ });
77
+ this.outboundTransport = new outbound_transport_js_1.LarkOutboundTransport(options.log);
71
78
  }
72
79
  // ==================== Lifecycle (platform-specific) ====================
73
80
  async testConnection(workspaceId, instanceId) {
@@ -133,7 +140,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
133
140
  return this.sendScheduledCard(workspaceId, route.channelId, text);
134
141
  }
135
142
  registerScheduledThreadBridge(input) {
136
- const instanceId = input.route.instanceId || getLarkInstanceId(input.platform) || 'default';
143
+ const instanceId = input.route.instanceId || (0, channel_keys_js_1.extractChannelInstanceId)(input.platform, 'lark') || 'default';
137
144
  const platformKey = (0, channel_keys_js_1.channelPlatformKey)('lark', instanceId);
138
145
  const route = {
139
146
  workspaceId: input.workspaceId,
@@ -160,7 +167,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
160
167
  async sendSessionCommandResult(input, result) {
161
168
  const state = this.resolveRuntimeState(input.workspaceId, input.instanceId).state;
162
169
  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);
170
+ await this.outboundTransport.sendSessionCommandCard(state, input.chatId, result.displayText, result.card.actions, this.options.getWorkspaceRouter().getThreadSessionKey(input.currentThreadId), input.currentThreadId);
164
171
  return;
165
172
  }
166
173
  await this.sendImmediateCard(input.workspaceId, input.chatId, result.displayText, input.instanceId);
@@ -185,7 +192,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
185
192
  continue;
186
193
  }
187
194
  if (part.type === 'file') {
188
- const sent = await this.sendFilePart(state, channelId, part);
195
+ const sent = await this.outboundTransport.sendFilePart(state, channelId, part);
189
196
  messageIds.push(sent.messageId);
190
197
  attachments.push({
191
198
  kind: 'file',
@@ -231,46 +238,6 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
231
238
  fileSize: attachment?.fileSize || 0,
232
239
  };
233
240
  }
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
241
  async onBridgeEvent(event) {
275
242
  if (!event.sessionKey) {
276
243
  this.options.log?.(`localcore-lark bridge event ignored without sessionKey: ${event.type}`);
@@ -303,10 +270,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
303
270
  this.options.log?.(`localcore-lark bridge event ignored type=${event.type}`);
304
271
  return;
305
272
  }
306
- const previous = this.outboundEventChains.get(sessionKey) || Promise.resolve();
307
- const current = previous
308
- .catch(() => undefined)
309
- .then(async () => {
273
+ const current = this.scheduleOutboundChain(sessionKey, async () => {
310
274
  const binding = this.options.store.getPlatformThreadBinding(route.workspaceId, route.chatId, route.platformUserId, routePlatformKey);
311
275
  if (!binding) {
312
276
  this.options.log?.(`localcore-lark bridge binding disappeared for sessionKey=${sessionKey}`);
@@ -327,7 +291,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
327
291
  }
328
292
  if (event.type === 'typing_start' && (turn.permissionMessageId || turn.awaitingPermission)) {
329
293
  if (turn.permissionMessageId) {
330
- await this.patchTextCard(state, turn.permissionMessageId, '**工具确认已处理**\n\n继续生成中...', [], sessionKey, bridgeThreadId);
294
+ await this.outboundTransport.patchTextCard(state, turn.permissionMessageId, '**工具确认已处理**\n\n继续生成中...', [], sessionKey, bridgeThreadId);
331
295
  }
332
296
  turn.permissionMessageId = undefined;
333
297
  turn.awaitingPermission = false;
@@ -340,14 +304,14 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
340
304
  const permissionCard = (0, cards_js_1.renderPermissionCard)(turn, event, Boolean(state.cardActionsEnabled));
341
305
  if (permissionCard.text || permissionCard.buttonRows.length > 0) {
342
306
  if (!turn.permissionMessageId) {
343
- const createdId = await this.sendTextAsCard(state, route.chatId, permissionCard.text, permissionCard.buttonRows, sessionKey, bridgeThreadId);
307
+ const createdId = await this.outboundTransport.sendTextAsCard(state, route.chatId, permissionCard.text, permissionCard.buttonRows, sessionKey, bridgeThreadId);
344
308
  if (createdId) {
345
309
  turn.permissionMessageId = createdId;
346
310
  this.options.log?.(`localcore-lark sent permission card ${createdId} for sessionKey=${sessionKey}`);
347
311
  }
348
312
  }
349
313
  else {
350
- await this.patchTextCard(state, turn.permissionMessageId, permissionCard.text, permissionCard.buttonRows, sessionKey, bridgeThreadId);
314
+ await this.outboundTransport.patchTextCard(state, turn.permissionMessageId, permissionCard.text, permissionCard.buttonRows, sessionKey, bridgeThreadId);
351
315
  this.options.log?.(`localcore-lark patched permission card ${turn.permissionMessageId} for sessionKey=${sessionKey}`);
352
316
  }
353
317
  }
@@ -376,7 +340,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
376
340
  const sentMessage = sendAsPlainMessage
377
341
  ? await this.sendTextAsMessage(state, route.chatId, renderedMessage.text)
378
342
  : {
379
- messageId: await this.sendTextAsCard(state, route.chatId, renderedMessage.text, renderedMessage.buttonRows, sessionKey, bridgeThreadId),
343
+ messageId: await this.outboundTransport.sendTextAsCard(state, route.chatId, renderedMessage.text, renderedMessage.buttonRows, sessionKey, bridgeThreadId),
380
344
  renderKind: 'card',
381
345
  };
382
346
  const createdId = sentMessage.messageId;
@@ -392,22 +356,16 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
392
356
  if (renderedMessage.delivery === 'message') {
393
357
  continue;
394
358
  }
395
- await this.patchTextCard(state, existingMessageId, renderedMessage.text, renderedMessage.buttonRows, sessionKey, bridgeThreadId);
359
+ await this.outboundTransport.patchTextCard(state, existingMessageId, renderedMessage.text, renderedMessage.buttonRows, sessionKey, bridgeThreadId);
396
360
  turn.lastPatchedAt = Date.now();
397
361
  turn.lastPatchedAtByMessageId[existingMessageId] = turn.lastPatchedAt;
398
362
  this.options.log?.(`localcore-lark patched card message ${existingMessageId} for sessionKey=${sessionKey}`);
399
363
  }
400
364
  }
401
365
  catch (error) {
402
- this.options.log?.(`localcore-lark bridge send failed for sessionKey=${sessionKey}: ${error instanceof Error ? error.message : String(error)}`);
403
- }
404
- })
405
- .finally(() => {
406
- if (this.outboundEventChains.get(sessionKey) === current) {
407
- this.outboundEventChains.delete(sessionKey);
366
+ this.options.log?.(`localcore-lark bridge send failed for sessionKey=${sessionKey}: ${(0, local_core_errors_js_1.formatSafeError)(error)}`);
408
367
  }
409
368
  });
410
- this.outboundEventChains.set(sessionKey, current);
411
369
  await current;
412
370
  }
413
371
  async handleInboundMessage(input) {
@@ -426,7 +384,6 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
426
384
  messageId: msg.messageId,
427
385
  },
428
386
  });
429
- this.options.store.expirePendingPairings();
430
387
  const runtimeState = this.resolveRuntimeState(msg.workspaceId, instanceId).state;
431
388
  let binding;
432
389
  try {
@@ -438,47 +395,28 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
438
395
  }
439
396
  this.options.log?.(`localcore-lark using active runtime binding snapshot for ${msg.workspaceId}/${instanceId}: ${error instanceof Error ? error.message : String(error)}`);
440
397
  }
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);
398
+ const authorization = (0, inbound_authorization_js_1.resolveInboundChannelAuthorization)({
399
+ store: this.options.store,
400
+ identity: {
401
+ workspaceId: msg.workspaceId,
402
+ platformKey,
403
+ platformUserId: msg.platformUserId,
404
+ chatId: msg.chatId,
405
+ displayName: msg.displayName,
406
+ },
407
+ autoApprove: Boolean(binding?.autoApprove || runtimeState?.autoApprove),
408
+ authorizedUserIdPrefix: 'lark-user',
409
+ generatePairingCode: () => this.generatePairingCode(),
410
+ onStateChanged: () => this.notifyRuntimeStateChanged(),
411
+ });
412
+ if (authorization.status === 'pending') {
413
+ await this.sendImmediateCard(msg.workspaceId, msg.chatId, (0, cards_js_1.renderPendingPairingCard)(authorization.pairingCode), instanceId);
480
414
  return; // { paired: false };
481
415
  }
416
+ if (authorization.autoApproved) {
417
+ this.options.log?.(`localcore-lark auto-approved user for ${msg.workspaceId}: ${msg.platformUserId}`);
418
+ }
419
+ const authorized = authorization.authorized;
482
420
  const router = this.options.getWorkspaceRouter();
483
421
  let { threadId } = await (0, thread_routing_js_1.resolveChannelThreadRoute)({
484
422
  store: this.options.store,
@@ -509,7 +447,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
509
447
  });
510
448
  const acknowledgement = this.createTurnState(effectiveSessionKey, msg.messageId);
511
449
  await this.addAcknowledgementReaction(msg.workspaceId, msg.messageId, acknowledgement, instanceId);
512
- const slashCommand = this.parseSlashCommand(msg.text);
450
+ const slashCommand = (0, local_core_slash_commands_js_1.parseSlashCommand)(msg.text);
513
451
  const sessionCommand = await this.executeSessionCommand({
514
452
  workspaceId: msg.workspaceId,
515
453
  currentThreadId: threadId,
@@ -531,10 +469,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
531
469
  return; // { paired: true, threadId };
532
470
  }
533
471
  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));
472
+ await router.sendThreadMessage(threadId, (0, content_js_1.createChannelThreadMessageInput)(msg.text, msg.contentParts));
538
473
  return; // { paired: true, threadId };
539
474
  }
540
475
  async createSdkClientResult(binding) {
@@ -587,7 +522,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
587
522
  this.runtime.set(key, status);
588
523
  this.notifyRuntimeStateChanged();
589
524
  try {
590
- this.options.log?.(`localcore-lark starting workspace=${binding.workspaceId} app=${this.maskLarkAppId(binding.appId)} cardActions=${binding.cardActionsEnabled}`);
525
+ this.options.log?.(`localcore-lark starting workspace=${binding.workspaceId} app=${(0, gateway_utils_js_1.maskLarkAppId)(binding.appId)} cardActions=${binding.cardActionsEnabled}`);
591
526
  const mod = await this.getLarkModule();
592
527
  status.client = new mod.Client({
593
528
  appId: binding.appId,
@@ -610,7 +545,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
610
545
  });
611
546
  status.eventDispatcher.register({
612
547
  '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)}`);
548
+ this.options.log?.(`localcore-lark received im.message.receive_v1 for ${binding.workspaceId}/${binding.instanceId}: ${(0, inbound_js_1.summarizeLarkInboundPayload)(data)}`);
614
549
  void this.handleMessageEvent(binding.workspaceId, binding.instanceId, binding.platformKey, data).catch((error) => {
615
550
  this.options.log?.(`localcore-lark inbound message failed for ${binding.workspaceId}: ${error instanceof Error ? error.message : String(error)}`);
616
551
  });
@@ -629,7 +564,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
629
564
  domain: mod.Domain.Feishu,
630
565
  loggerLevel: mod.LoggerLevel.info,
631
566
  });
632
- this.attachWsDiagnostics(binding.workspaceId, status.wsClient);
567
+ (0, gateway_utils_js_1.attachLarkWsDiagnostics)(binding.workspaceId, status.wsClient, this.options.log);
633
568
  this.options.log?.(`localcore-lark ws starting for ${binding.workspaceId}`);
634
569
  await status.wsClient.start({
635
570
  eventDispatcher: status.eventDispatcher,
@@ -656,279 +591,13 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
656
591
  this.notifyRuntimeStateChanged();
657
592
  }
658
593
  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
- });
594
+ await this.inboundHandler.handleMessageEvent(workspaceId, instanceIdOrData, platformKeyOrData, maybeData);
734
595
  }
735
596
  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
- };
597
+ return this.inboundHandler.downloadMessageImage(workspaceId, messageId, imageKey, instanceId);
782
598
  }
783
599
  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);
600
+ return this.inboundHandler.downloadMessageFile(workspaceId, messageId, fileKey, fileName, instanceId);
932
601
  }
933
602
  async fetchBotOpenId(state) {
934
603
  const response = await state.client.request({
@@ -942,30 +611,6 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
942
611
  }
943
612
  return openId;
944
613
  }
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
614
  makeThreadRoute(input, threadId) {
970
615
  return {
971
616
  workspaceId: input.workspaceId,
@@ -982,7 +627,6 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
982
627
  });
983
628
  }
984
629
  buildStatusObject(state, _resolved) {
985
- this.options.store.expirePendingPairings();
986
630
  const resolved = this.resolveRuntimeState(state.workspaceId, state.instanceId);
987
631
  const binding = resolved.state;
988
632
  const platformKey = binding?.platformKey || (0, channel_keys_js_1.channelPlatformKey)('lark', resolved.instanceId);
@@ -1054,126 +698,12 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
1054
698
  }
1055
699
  return this.larkModulePromise;
1056
700
  }
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
701
  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')}`);
702
+ return this.outboundTransport.sendTextAsMessage(state, chatId, text);
1145
703
  }
1146
704
  generatePairingCode() {
1147
705
  return String((0, node_crypto_1.randomInt)(100000, 1000000));
1148
706
  }
1149
- findAwaitingPermissionThreadId(workspaceId, chatId, platformUserId) {
1150
- for (const [sessionKey, route] of this.threadRouting.entries()) {
1151
- if (route.workspaceId !== workspaceId
1152
- || route.chatId !== chatId
1153
- || route.platformUserId !== platformUserId) {
1154
- continue;
1155
- }
1156
- const turn = this.outboundTurns.get(sessionKey);
1157
- if (turn?.awaitingPermission && route.threadId) {
1158
- return route.threadId;
1159
- }
1160
- }
1161
- return '';
1162
- }
1163
- parseSlashCommand(text) {
1164
- const normalized = String(text || '').trim();
1165
- if (!normalized.startsWith('/')) {
1166
- return null;
1167
- }
1168
- const [name = '', ...args] = normalized.slice(1).split(/\s+/);
1169
- if (!name) {
1170
- return null;
1171
- }
1172
- return {
1173
- name: name.trim().toLowerCase(),
1174
- args,
1175
- };
1176
- }
1177
707
  createTurnState(sessionKey, sourceMessageId) {
1178
708
  const turn = (0, runtime_state_js_1.createLarkTurnState)(sessionKey, sourceMessageId);
1179
709
  this.outboundTurns.set(sessionKey, turn);
@@ -1239,7 +769,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
1239
769
  if (!binding || (binding.platform !== 'lark' && !binding.platform.startsWith('lark:'))) {
1240
770
  return undefined;
1241
771
  }
1242
- const bindingInstanceId = getLarkInstanceId(binding.platform) || instanceId || 'default';
772
+ const bindingInstanceId = (0, channel_keys_js_1.extractChannelInstanceId)(binding.platform, 'lark') || instanceId || 'default';
1243
773
  return {
1244
774
  workspaceId: binding.workspace_id,
1245
775
  instanceId: bindingInstanceId,
@@ -1249,13 +779,6 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
1249
779
  threadId: binding.thread_id,
1250
780
  };
1251
781
  }
1252
- async resolveDefaultAgentType(workspaceId, threadId) {
1253
- const router = this.options.getWorkspaceRouter();
1254
- if (typeof router.getWorkspaceDefaultAgentType === 'function') {
1255
- return router.getWorkspaceDefaultAgentType(workspaceId);
1256
- }
1257
- return this.options.store.getThreadRow(threadId)?.agent_type || 'codex';
1258
- }
1259
782
  async markPermissionCardActionHandled(workspaceId, instanceId, rootPayload, payload, value, response, threadId) {
1260
783
  const state = this.resolveRuntimeState(workspaceId, instanceId).state;
1261
784
  if (!state?.client) {
@@ -1269,7 +792,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
1269
792
  return;
1270
793
  }
1271
794
  try {
1272
- await this.patchTextCard(state, messageId, [
795
+ await this.outboundTransport.patchTextCard(state, messageId, [
1273
796
  '**工具确认已处理**',
1274
797
  `已选择:${(0, cards_js_1.formatPermissionResponseLabel)(response)}`,
1275
798
  '等待代理继续执行...',
@@ -1290,7 +813,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
1290
813
  return '';
1291
814
  }
1292
815
  try {
1293
- return await this.sendTextAsCard(state, chatId, text);
816
+ return await this.outboundTransport.sendTextAsCard(state, chatId, text);
1294
817
  }
1295
818
  catch (error) {
1296
819
  this.options.log?.(`localcore-lark immediate card failed for ${workspaceId}: ${error instanceof Error ? error.message : String(error)}`);
@@ -1338,7 +861,3 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
1338
861
  }
1339
862
  }
1340
863
  exports.LocalCoreLarkGateway = LocalCoreLarkGateway;
1341
- function getLarkInstanceId(platform) {
1342
- const normalized = String(platform || '').trim();
1343
- return normalized.startsWith('lark:') ? normalized.slice('lark:'.length).trim() : '';
1344
- }