@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.
- package/README.md +7 -0
- package/dist/renderer/assets/{Badge-DjcoXx2J.js → Badge-BfY1VaHS.js} +1 -1
- package/dist/renderer/assets/Card-DWA_Tww_.js +1 -0
- package/dist/renderer/assets/Config-nHj3g1U5.js +21 -0
- package/dist/renderer/assets/CronList-BwkA_I7v.js +1 -0
- package/dist/renderer/assets/Dashboard-D0_A7k02.js +41 -0
- package/dist/renderer/assets/{EmptyState-DIZLiccW.js → EmptyState-zatDjLj_.js} +1 -1
- package/dist/renderer/assets/HighlightedMarkdown-CsM5n70d.js +12 -0
- package/dist/renderer/assets/Input-R1XdFK1K.js +1 -0
- package/dist/renderer/assets/{KnowledgeDetail-CJ9IYOsa.js → KnowledgeDetail-Co5sxeGd.js} +2 -2
- package/dist/renderer/assets/{KnowledgeHome-BLGPwnBO.js → KnowledgeHome-DwziPw5m.js} +3 -3
- package/dist/renderer/assets/Logs-NwZUtR_G.js +6 -0
- package/dist/renderer/assets/{Modal-CQiUpfl4.js → Modal-CrcIwIFL.js} +3 -3
- package/dist/renderer/assets/MonitorList-CS1uLS5A.js +1 -0
- package/dist/renderer/assets/Page-Dp0obeSw.js +1 -0
- package/dist/renderer/assets/{Select-D6z65IT3.js → Select-6mVQaf84.js} +2 -2
- package/dist/renderer/assets/ThreadChat-BFzbn3L6.js +86 -0
- package/dist/renderer/assets/Workspace-DCmo8BMm.js +19 -0
- package/dist/renderer/assets/{arrow-left-CV5cL3f4.js → arrow-left-9rjg_Hp4.js} +1 -1
- package/dist/renderer/assets/{book-open-DThvB7pj.js → book-open-Bu8GCHnG.js} +1 -1
- package/dist/renderer/assets/channels-BxVbG-6j.js +6 -0
- package/dist/renderer/assets/chevron-down-BE8uQmWM.js +11 -0
- package/dist/renderer/assets/index-B7TeF6Es.js +41 -0
- package/dist/renderer/assets/index-BIKL3fTP.css +11 -0
- package/dist/renderer/assets/index-BkI9POxj.js +167 -0
- package/dist/renderer/assets/knowledge-Kl19SqGS.js +1 -0
- package/dist/renderer/assets/{pencil-Dv5WxhdC.js → pencil-CPB7SK1m.js} +1 -1
- package/dist/renderer/assets/{play-DnCnft83.js → play-DGAO4OCu.js} +1 -1
- package/dist/renderer/assets/{plus-DsxIagzS.js → plus-Bt26z-4q.js} +1 -1
- package/dist/renderer/assets/{save-CST01lIc.js → save-Une7GMxT.js} +1 -1
- package/dist/renderer/assets/{search-B_bqy6Wd.js → search-DE0agJjJ.js} +1 -1
- package/dist/renderer/assets/{shield-check-D6lG5Aoc.js → shield-check-De7xaXZh.js} +1 -1
- package/dist/renderer/assets/threads-BnsNL5ei.js +1 -0
- package/dist/renderer/assets/{trash-2-Cefngb6Q.js → trash-2-6iGF59Ac.js} +1 -1
- package/dist/renderer/index.html +2 -2
- package/dist-electron/packages/contracts/src/automation.js +2 -0
- package/dist-electron/packages/contracts/src/channels.js +2 -0
- package/dist-electron/packages/contracts/src/knowledge.js +2 -0
- package/dist-electron/packages/contracts/src/local-core.js +15 -0
- package/dist-electron/packages/contracts/src/runtime.js +2 -0
- package/dist-electron/packages/contracts/src/scheduler.js +2 -0
- package/dist-electron/packages/contracts/src/threads.js +2 -0
- package/dist-electron/packages/core-sdk/src/automation.js +32 -0
- package/dist-electron/packages/core-sdk/src/channels.js +121 -0
- package/dist-electron/packages/core-sdk/src/client.js +455 -0
- package/dist-electron/packages/core-sdk/src/index.js +43 -607
- package/dist-electron/packages/core-sdk/src/knowledge.js +85 -0
- package/dist-electron/packages/core-sdk/src/request.js +22 -0
- package/dist-electron/packages/core-sdk/src/runtime.js +214 -0
- package/dist-electron/packages/core-sdk/src/scheduler.js +32 -0
- package/dist-electron/packages/core-sdk/src/threads.js +67 -0
- package/dist-electron/packages/plugin-sdk/src/agents.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/automation.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/channels.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/index.js +21 -0
- package/dist-electron/packages/plugin-sdk/src/knowledge.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/runtime.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/scheduler.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/threads.js +2 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +5 -8
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-content.js +2 -2
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +3 -3
- package/dist-electron/services/local-ai-core/src/acp/store/agent-task-store.js +5 -5
- package/dist-electron/services/local-ai-core/src/acp/store/automation-monitor-store.js +12 -12
- package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +2 -2
- package/dist-electron/services/local-ai-core/src/acp/store/scheduler-store.js +11 -11
- package/dist-electron/services/local-ai-core/src/acp/store/security-store.js +3 -3
- package/dist-electron/services/local-ai-core/src/acp/store/thread-store.js +7 -7
- package/dist-electron/services/local-ai-core/src/acp/workspace-acp-permissions.js +2 -2
- package/dist-electron/services/local-ai-core/src/agents/claudecode/definition.js +3 -3
- package/dist-electron/services/local-ai-core/src/agents/codex/definition.js +3 -3
- package/dist-electron/services/local-ai-core/src/agents/localcore-acp/definition.js +2 -2
- package/dist-electron/services/local-ai-core/src/agents/localcore-acp/index.js +4 -4
- package/dist-electron/services/local-ai-core/src/agents/opencode/launch.js +2 -2
- package/dist-electron/services/local-ai-core/src/agents/pi/definition.js +2 -2
- package/dist-electron/services/local-ai-core/src/agents/pi/launch.js +3 -3
- package/dist-electron/services/local-ai-core/src/agents/pi/provider-materializer.js +1 -1
- package/dist-electron/services/local-ai-core/src/agents/shared/agent-plugin.js +4 -4
- package/dist-electron/services/local-ai-core/src/automation/automation-conversation-executor.js +6 -47
- package/dist-electron/services/local-ai-core/src/automation/automation-monitor-service.js +2 -5
- package/dist-electron/services/local-ai-core/src/channel/lark/cards.js +33 -18
- package/dist-electron/services/local-ai-core/src/channel/lark/config.js +2 -2
- package/dist-electron/services/local-ai-core/src/channel/lark/gateway-utils.js +91 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/inbound-handler.js +180 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +58 -539
- package/dist-electron/services/local-ai-core/src/channel/lark/outbound-transport.js +112 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/runtime-state.js +5 -20
- package/dist-electron/services/local-ai-core/src/channel/shared/base-channel-gateway.js +37 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/bridge-event-helpers.js +23 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/channel-keys.js +6 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/inbound-authorization.js +54 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/config.js +2 -2
- package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-media.js +21 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-poller.js +167 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +55 -512
- package/dist-electron/services/local-ai-core/src/channel/weixin/runtime-state.js +149 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/text-utils.js +92 -0
- package/dist-electron/services/local-ai-core/src/cli/lac.js +9 -11
- package/dist-electron/services/local-ai-core/src/cli/monitor-cli-parsers.js +2 -2
- package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +28 -70
- package/dist-electron/services/local-ai-core/src/kernel/local-core-errors.js +8 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-ai-vector-plugin.js +2 -2
- package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-noop-plugin.js +2 -2
- package/dist-electron/services/local-ai-core/src/router/workspace-bridge-event-stream.js +29 -0
- package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +5 -5
- package/dist-electron/services/local-ai-core/src/router/workspace-router.js +47 -60
- package/dist-electron/services/local-ai-core/src/runtime/agent-runtime-detector.js +5 -5
- package/dist-electron/services/local-ai-core/src/runtime/config-migration.js +6 -6
- package/dist-electron/services/local-ai-core/src/runtime/deployment-diagnostics.js +3 -3
- package/dist-electron/services/local-ai-core/src/runtime/external-service.js +3 -1
- package/dist-electron/services/local-ai-core/src/runtime/handlers/automation-handler.js +11 -2
- package/dist-electron/services/local-ai-core/src/runtime/handlers/channel-handler.js +12 -6
- package/dist-electron/services/local-ai-core/src/runtime/handlers/external-handler.js +10 -2
- package/dist-electron/services/local-ai-core/src/runtime/handlers/knowledge-handler.js +18 -6
- package/dist-electron/services/local-ai-core/src/runtime/handlers/provider-handler.js +7 -2
- package/dist-electron/services/local-ai-core/src/runtime/handlers/runtime-handler.js +28 -3
- package/dist-electron/services/local-ai-core/src/runtime/handlers/scheduler-handler.js +10 -2
- package/dist-electron/services/local-ai-core/src/runtime/handlers/security-handler.js +18 -5
- package/dist-electron/services/local-ai-core/src/runtime/handlers/task-handler.js +14 -2
- package/dist-electron/services/local-ai-core/src/runtime/handlers/thread-handler.js +18 -15
- package/dist-electron/services/local-ai-core/src/runtime/handlers/workspace-handler.js +13 -2
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +35 -8
- package/dist-electron/services/local-ai-core/src/runtime/request-validation.js +79 -0
- package/dist-electron/services/local-ai-core/src/runtime/runtime-detection-service.js +9 -9
- package/dist-electron/services/local-ai-core/src/runtime/server-helpers.js +10 -1
- package/dist-electron/services/local-ai-core/src/runtime/server.js +2 -1
- package/dist-electron/services/local-ai-core/src/runtime/workspace-project-registry.js +76 -0
- package/dist-electron/services/local-ai-core/src/sandbox/opensandbox-client.js +3 -2
- package/dist-electron/services/local-ai-core/src/sandbox/sandbox-config.js +8 -8
- package/dist-electron/services/local-ai-core/src/scheduler/base-channel-schedule-adapter.js +77 -0
- package/dist-electron/services/local-ai-core/src/scheduler/lark-schedule-adapter.js +13 -79
- package/dist-electron/services/local-ai-core/src/scheduler/local-schedule-adapter.js +2 -10
- package/dist-electron/services/local-ai-core/src/scheduler/run-polling.js +19 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-conversation-executor.js +3 -37
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-job-route.js +20 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduler-service.js +15 -28
- package/dist-electron/services/local-ai-core/src/scheduler/thread-resolution.js +12 -0
- package/dist-electron/services/local-ai-core/src/scheduler/weixin-schedule-adapter.js +13 -79
- package/dist-electron/services/local-ai-core/src/thread/agent-message-policy.js +75 -0
- package/dist-electron/shared/desktop.js +1 -64
- package/dist-electron/src/components/chat/chat-controller-state.js +60 -0
- package/dist-electron/src/components/chat/chat-event-gate.js +146 -0
- package/dist-electron/src/components/chat/markdown-code-block.js +8 -0
- package/dist-electron/src/pages/Desktop/workspace-model.js +212 -0
- package/dist-electron/src/pages/Threads/thread-chat-model.js +50 -51
- package/dist-electron/tests/contracts/agent-message-policy.test.js +21 -0
- package/dist-electron/tests/contracts/architecture-docs.test.js +56 -33
- package/dist-electron/tests/contracts/chat-event-gate.test.js +114 -0
- package/dist-electron/tests/contracts/chat-markdown.test.js +16 -0
- package/dist-electron/tests/contracts/thread-task-state.test.js +32 -0
- package/dist-electron/tests/contracts/workspace-identity.test.js +23 -0
- package/dist-electron/tests/electron/core-client.test.js +284 -0
- package/dist-electron/tests/electron/plugin-kernel.test.js +54 -0
- package/dist-electron/tests/electron/renderer-packaging.test.js +9 -0
- package/dist-electron/tests/electron/workspace-task-store.test.js +31 -0
- package/dist-electron/tests/integration/channel-inbound-authorization.test.js +80 -0
- package/dist-electron/tests/integration/lark-gateway-utils.test.js +13 -0
- package/dist-electron/tests/integration/lark-gateway.test.js +4 -4
- package/dist-electron/tests/integration/local-core-refactor.test.js +15 -8
- package/dist-electron/tests/integration/weixin-runtime-state.test.js +32 -0
- package/dist-electron/tests/integration/weixin-text-utils.test.js +15 -0
- package/package.json +9 -4
- package/dist/renderer/assets/Chat-C5Bkm9-M.js +0 -2
- package/dist/renderer/assets/ChatMarkdown-uc36EzyD.js +0 -45
- package/dist/renderer/assets/Config-DHtQuuLy.js +0 -21
- package/dist/renderer/assets/CronList-BYUnhzSC.js +0 -1
- package/dist/renderer/assets/Dashboard-BPnGMDg3.js +0 -26
- package/dist/renderer/assets/Logs-Dyd2Uwlt.js +0 -1
- package/dist/renderer/assets/MonitorList-Byg3E3Gt.js +0 -1
- package/dist/renderer/assets/Page-7DxXvTMm.js +0 -1
- package/dist/renderer/assets/ProjectDetail-Dfr5s0Ja.js +0 -11
- package/dist/renderer/assets/ProjectList-CDDQjAQ_.js +0 -1
- package/dist/renderer/assets/SessionChat-s7CAaCPL.js +0 -1
- package/dist/renderer/assets/SessionList-D-OycKKS.js +0 -1
- package/dist/renderer/assets/ThreadChat-CLdFynB5.js +0 -28
- package/dist/renderer/assets/Workspace-xfT5z4j_.js +0 -19
- package/dist/renderer/assets/bot-CWQ5-ovl.js +0 -6
- package/dist/renderer/assets/check-DKM7zfWG.js +0 -6
- package/dist/renderer/assets/chevron-down-Dfw2KU87.js +0 -6
- package/dist/renderer/assets/circle-CoP4RA4s.js +0 -6
- package/dist/renderer/assets/desktop-CsDYrOOU.js +0 -1
- package/dist/renderer/assets/desktop-JQkhNOF4.js +0 -5
- package/dist/renderer/assets/funnel-DpVLlG3g.js +0 -6
- package/dist/renderer/assets/heart-BMD36ejP.js +0 -6
- package/dist/renderer/assets/index-COxSYBjE.js +0 -182
- package/dist/renderer/assets/index-CTGTI-cm.js +0 -41
- package/dist/renderer/assets/index-CjCuR6DI.css +0 -11
- package/dist/renderer/assets/projects-DgjHcNgt.js +0 -1
- package/dist/renderer/assets/server-ecH4GNwa.js +0 -11
- package/dist/renderer/assets/session-utils-Dd_WKMYW.js +0 -6
- package/dist/renderer/assets/sessions-BQ33Mv4k.js +0 -1
- package/dist/renderer/assets/user-D_8RSH-T.js +0 -6
- package/dist/renderer/assets/wifi-off-DB9D-pOu.js +0 -11
- package/dist-electron/services/local-ai-core/src/scheduler/lark-execution-policies.js +0 -13
- package/dist-electron/services/local-ai-core/src/scheduler/weixin-execution-policies.js +0 -13
- package/dist-electron/src/api/client.js +0 -73
- package/dist-electron/src/api/sessions.js +0 -21
- package/dist-electron/src/lib/session-utils.js +0 -51
- package/dist-electron/src/pages/Projects/project-provider-config.js +0 -75
- 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
|
|
55
|
-
const
|
|
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
|
-
|
|
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 ||
|
|
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
|
|
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}: ${
|
|
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
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
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 =
|
|
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
|
-
|
|
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=${
|
|
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}: ${
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
}
|