@kafca/agentdock 0.1.56 → 0.1.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/dist/renderer/assets/{Badge-DjcoXx2J.js → Badge-CDTbmw1h.js} +1 -1
- package/dist/renderer/assets/Card-DayUo35w.js +1 -0
- package/dist/renderer/assets/Config-ByGMQuzR.js +21 -0
- package/dist/renderer/assets/CronList-XqHdVlgu.js +1 -0
- package/dist/renderer/assets/Dashboard-CZj-oANw.js +41 -0
- package/dist/renderer/assets/{EmptyState-DIZLiccW.js → EmptyState-EFMkOjZO.js} +1 -1
- package/dist/renderer/assets/HighlightedMarkdown-DyvF3DHK.js +12 -0
- package/dist/renderer/assets/Input-DxoWVc9d.js +1 -0
- package/dist/renderer/assets/{KnowledgeDetail-CJ9IYOsa.js → KnowledgeDetail-CbUb2tG7.js} +2 -2
- package/dist/renderer/assets/{KnowledgeHome-BLGPwnBO.js → KnowledgeHome-BWV1gz4f.js} +3 -3
- package/dist/renderer/assets/Logs-DqnanQTc.js +6 -0
- package/dist/renderer/assets/{Modal-CQiUpfl4.js → Modal-yY7TzR0x.js} +3 -3
- package/dist/renderer/assets/MonitorList-CIjGQkFs.js +1 -0
- package/dist/renderer/assets/Page-vwHNUdoj.js +1 -0
- package/dist/renderer/assets/{Select-D6z65IT3.js → Select-CmbK36pN.js} +2 -2
- package/dist/renderer/assets/ThreadChat-4OceMgM4.js +86 -0
- package/dist/renderer/assets/Workspace-DplPJOjJ.js +19 -0
- package/dist/renderer/assets/{arrow-left-CV5cL3f4.js → arrow-left-C8HfBt2K.js} +1 -1
- package/dist/renderer/assets/{book-open-DThvB7pj.js → book-open-BCdZWncQ.js} +1 -1
- package/dist/renderer/assets/channels-hgO3cAIx.js +6 -0
- package/dist/renderer/assets/chevron-down-BPk77tqY.js +11 -0
- package/dist/renderer/assets/index-BIKL3fTP.css +11 -0
- package/dist/renderer/assets/index-BlA4xPdd.js +41 -0
- package/dist/renderer/assets/index-wYpjqVqC.js +167 -0
- package/dist/renderer/assets/knowledge-7pl06KuH.js +1 -0
- package/dist/renderer/assets/{pencil-Dv5WxhdC.js → pencil-CB1SWZ9A.js} +1 -1
- package/dist/renderer/assets/{play-DnCnft83.js → play-BvsoXUrM.js} +1 -1
- package/dist/renderer/assets/{plus-DsxIagzS.js → plus-CokBDnaL.js} +1 -1
- package/dist/renderer/assets/{save-CST01lIc.js → save-D-w4kATO.js} +1 -1
- package/dist/renderer/assets/{search-B_bqy6Wd.js → search-Cnsn6i4Q.js} +1 -1
- package/dist/renderer/assets/{shield-check-D6lG5Aoc.js → shield-check-Cjja2Gh6.js} +1 -1
- package/dist/renderer/assets/threads-BCm6j4eI.js +1 -0
- package/dist/renderer/assets/{trash-2-Cefngb6Q.js → trash-2-CIxz9qYY.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/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 +52 -486
- package/dist-electron/services/local-ai-core/src/channel/lark/outbound-transport.js +124 -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 +50 -469
- package/dist-electron/services/local-ai-core/src/channel/weixin/runtime-state.js +156 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/text-utils.js +100 -0
- package/dist-electron/services/local-ai-core/src/cli/lac.js +6 -6
- 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/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/sandbox-config.js +8 -8
- 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/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/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
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LarkOutboundTransport = void 0;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const file_utils_js_1 = require("../shared/file-utils.js");
|
|
7
|
+
const cards_js_1 = require("./cards.js");
|
|
8
|
+
const messages_js_1 = require("./rendering/messages.js");
|
|
9
|
+
const LARK_MAX_UPLOAD_FILE_SIZE = 30 * 1024 * 1024;
|
|
10
|
+
class LarkOutboundTransport {
|
|
11
|
+
log;
|
|
12
|
+
constructor(log) {
|
|
13
|
+
this.log = log;
|
|
14
|
+
}
|
|
15
|
+
async sendFilePart(state, channelId, part) {
|
|
16
|
+
const file = await (0, file_utils_js_1.prepareChannelFile)({
|
|
17
|
+
path: part.path,
|
|
18
|
+
fileName: part.fileName,
|
|
19
|
+
workspacePath: typeof part.metadata?.workspacePath === 'string' ? part.metadata.workspacePath : undefined,
|
|
20
|
+
maxBytes: LARK_MAX_UPLOAD_FILE_SIZE,
|
|
21
|
+
platformLabel: 'Lark',
|
|
22
|
+
});
|
|
23
|
+
const upload = await state.client.im.file.create({
|
|
24
|
+
data: {
|
|
25
|
+
file_type: resolveLarkUploadFileType(file.fileName),
|
|
26
|
+
file_name: file.fileName,
|
|
27
|
+
file: (0, node_fs_1.createReadStream)(file.path),
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
const fileKey = String(upload?.file_key || upload?.data?.file_key || '').trim();
|
|
31
|
+
if (!fileKey) {
|
|
32
|
+
throw new Error('Lark file upload did not return a file key');
|
|
33
|
+
}
|
|
34
|
+
const response = await state.client.im.message.create({
|
|
35
|
+
params: {
|
|
36
|
+
receive_id_type: resolveReceiveIdType(channelId),
|
|
37
|
+
},
|
|
38
|
+
data: {
|
|
39
|
+
receive_id: channelId,
|
|
40
|
+
msg_type: 'file',
|
|
41
|
+
content: JSON.stringify({ file_key: fileKey }),
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
const messageId = String(response?.data?.message_id || '').trim();
|
|
45
|
+
if (!messageId) {
|
|
46
|
+
throw new Error('Lark file message did not return a message id');
|
|
47
|
+
}
|
|
48
|
+
this.log?.(`localcore-lark sent file ${file.fileName} (${file.fileSize} bytes) to ${channelId}`);
|
|
49
|
+
return { messageId, fileKey, file };
|
|
50
|
+
}
|
|
51
|
+
async sendTextAsCard(state, chatId, text, buttonRows = [], sessionKey, threadId) {
|
|
52
|
+
const startedAt = Date.now();
|
|
53
|
+
const response = await state.client.im.message.create({
|
|
54
|
+
params: { receive_id_type: resolveReceiveIdType(chatId) },
|
|
55
|
+
data: {
|
|
56
|
+
receive_id: chatId,
|
|
57
|
+
msg_type: 'interactive',
|
|
58
|
+
content: JSON.stringify((0, cards_js_1.buildInteractiveCard)(text, buttonRows, sessionKey, threadId)),
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
this.log?.(`localcore-lark card create took ${Date.now() - startedAt}ms textBytes=${Buffer.byteLength(text || '', 'utf8')}`);
|
|
62
|
+
return String(response?.data?.message_id || '').trim();
|
|
63
|
+
}
|
|
64
|
+
async sendSessionCommandCard(state, chatId, text, actionRows, sessionKey, threadId) {
|
|
65
|
+
const startedAt = Date.now();
|
|
66
|
+
const response = await state.client.im.message.create({
|
|
67
|
+
params: { receive_id_type: resolveReceiveIdType(chatId) },
|
|
68
|
+
data: {
|
|
69
|
+
receive_id: chatId,
|
|
70
|
+
msg_type: 'interactive',
|
|
71
|
+
content: JSON.stringify((0, cards_js_1.buildSessionCommandCard)(text, actionRows, sessionKey, threadId)),
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
this.log?.(`localcore-lark session card create took ${Date.now() - startedAt}ms textBytes=${Buffer.byteLength(text || '', 'utf8')}`);
|
|
75
|
+
return String(response?.data?.message_id || '').trim();
|
|
76
|
+
}
|
|
77
|
+
async sendTextAsMessage(state, chatId, text) {
|
|
78
|
+
const startedAt = Date.now();
|
|
79
|
+
const rendered = (0, messages_js_1.renderLarkTextMessage)(text);
|
|
80
|
+
const response = await state.client.im.message.create({
|
|
81
|
+
params: { receive_id_type: resolveReceiveIdType(chatId) },
|
|
82
|
+
data: {
|
|
83
|
+
receive_id: chatId,
|
|
84
|
+
msg_type: rendered.msgType,
|
|
85
|
+
content: JSON.stringify(rendered.content),
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
this.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')}`);
|
|
89
|
+
return {
|
|
90
|
+
messageId: String(response?.data?.message_id || '').trim(),
|
|
91
|
+
renderKind: rendered.renderKind,
|
|
92
|
+
msgType: rendered.msgType,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
async patchTextCard(state, messageId, text, buttonRows = [], sessionKey, threadId) {
|
|
96
|
+
const startedAt = Date.now();
|
|
97
|
+
await state.client.im.message.patch({
|
|
98
|
+
path: { message_id: messageId },
|
|
99
|
+
data: { content: JSON.stringify((0, cards_js_1.buildInteractiveCard)(text, buttonRows, sessionKey, threadId)) },
|
|
100
|
+
});
|
|
101
|
+
this.log?.(`localcore-lark card patch took ${Date.now() - startedAt}ms message=${messageId} textBytes=${Buffer.byteLength(text || '', 'utf8')}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.LarkOutboundTransport = LarkOutboundTransport;
|
|
105
|
+
function resolveReceiveIdType(receiveId) {
|
|
106
|
+
return receiveId.startsWith('oc_') ? 'chat_id' : receiveId.startsWith('ou_') ? 'open_id' : 'user_id';
|
|
107
|
+
}
|
|
108
|
+
function resolveLarkUploadFileType(fileName) {
|
|
109
|
+
switch ((0, node_path_1.extname)(fileName).toLowerCase()) {
|
|
110
|
+
case '.opus': return 'opus';
|
|
111
|
+
case '.mp4':
|
|
112
|
+
case '.mov':
|
|
113
|
+
case '.m4v': return 'mp4';
|
|
114
|
+
case '.pdf': return 'pdf';
|
|
115
|
+
case '.doc':
|
|
116
|
+
case '.docx': return 'doc';
|
|
117
|
+
case '.xls':
|
|
118
|
+
case '.xlsx':
|
|
119
|
+
case '.csv': return 'xls';
|
|
120
|
+
case '.ppt':
|
|
121
|
+
case '.pptx': return 'ppt';
|
|
122
|
+
default: return 'stream';
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveInboundChannelAuthorization = resolveInboundChannelAuthorization;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const DEFAULT_PAIRING_EXPIRY_MS = 10 * 60 * 1000;
|
|
6
|
+
function resolveInboundChannelAuthorization(input) {
|
|
7
|
+
const { store, identity } = input;
|
|
8
|
+
store.expirePendingPairings();
|
|
9
|
+
let authorized = store.getAuthorizedUser(identity.workspaceId, identity.platformUserId, identity.platformKey);
|
|
10
|
+
let autoApproved = false;
|
|
11
|
+
if (!authorized && input.autoApprove) {
|
|
12
|
+
const authorizedAt = (input.now?.() || new Date()).toISOString();
|
|
13
|
+
store.createAuthorizedUser({
|
|
14
|
+
id: `${input.authorizedUserIdPrefix}-${(0, node_crypto_1.randomUUID)()}`,
|
|
15
|
+
workspace_id: identity.workspaceId,
|
|
16
|
+
platform: identity.platformKey,
|
|
17
|
+
platform_user_id: identity.platformUserId,
|
|
18
|
+
chat_id: identity.chatId,
|
|
19
|
+
display_name: identity.displayName,
|
|
20
|
+
thread_id: null,
|
|
21
|
+
authorized_at: authorizedAt,
|
|
22
|
+
});
|
|
23
|
+
authorized = store.getAuthorizedUser(identity.workspaceId, identity.platformUserId, identity.platformKey);
|
|
24
|
+
autoApproved = Boolean(authorized);
|
|
25
|
+
if (autoApproved) {
|
|
26
|
+
input.onStateChanged?.();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (authorized) {
|
|
30
|
+
return { status: 'authorized', authorized, autoApproved };
|
|
31
|
+
}
|
|
32
|
+
const existingPending = store.listPendingPairings(identity.workspaceId).find((item) => item.platform === identity.platformKey &&
|
|
33
|
+
item.platform_user_id === identity.platformUserId &&
|
|
34
|
+
item.chat_id === identity.chatId &&
|
|
35
|
+
item.status === 'pending');
|
|
36
|
+
if (existingPending) {
|
|
37
|
+
return { status: 'pending', pairingCode: existingPending.code };
|
|
38
|
+
}
|
|
39
|
+
const now = input.now?.() || new Date();
|
|
40
|
+
const pairingCode = input.generatePairingCode();
|
|
41
|
+
store.createPairingRequest({
|
|
42
|
+
code: pairingCode,
|
|
43
|
+
workspace_id: identity.workspaceId,
|
|
44
|
+
platform: identity.platformKey,
|
|
45
|
+
platform_user_id: identity.platformUserId,
|
|
46
|
+
chat_id: identity.chatId,
|
|
47
|
+
display_name: identity.displayName,
|
|
48
|
+
requested_at: now.toISOString(),
|
|
49
|
+
expires_at: new Date(now.getTime() + (input.pairingExpiryMs || DEFAULT_PAIRING_EXPIRY_MS)).toISOString(),
|
|
50
|
+
status: 'pending',
|
|
51
|
+
});
|
|
52
|
+
input.onStateChanged?.();
|
|
53
|
+
return { status: 'pending', pairingCode };
|
|
54
|
+
}
|
|
@@ -15,7 +15,7 @@ exports.saveWeixinBuf = saveWeixinBuf;
|
|
|
15
15
|
exports.collectWeixinWorkspaceBindings = collectWeixinWorkspaceBindings;
|
|
16
16
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
17
17
|
const node_path_1 = __importDefault(require("node:path"));
|
|
18
|
-
const
|
|
18
|
+
const superai_contracts_1 = require("../../../../../packages/contracts/src/index.js");
|
|
19
19
|
const channel_keys_js_1 = require("../shared/channel-keys.js");
|
|
20
20
|
exports.DEFAULT_BASE_URL = 'https://ilinkai.weixin.qq.com';
|
|
21
21
|
exports.DEFAULT_CDN_BASE_URL = 'https://novac2c.cdn.weixin.qq.com/c2c';
|
|
@@ -75,7 +75,7 @@ function collectWeixinWorkspaceBindings(config) {
|
|
|
75
75
|
const platforms = Array.isArray(project.platforms) ? project.platforms : [];
|
|
76
76
|
return platforms
|
|
77
77
|
.map((platform) => ({
|
|
78
|
-
platformType: (0,
|
|
78
|
+
platformType: (0, superai_contracts_1.normalizeDesktopPlatformType)(platform?.type),
|
|
79
79
|
options: platform?.options && typeof platform.options === 'object'
|
|
80
80
|
? platform.options
|
|
81
81
|
: {},
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createWeixinAttachmentContentPart = createWeixinAttachmentContentPart;
|
|
4
|
+
function createWeixinAttachmentContentPart(att) {
|
|
5
|
+
if (att.kind === 'image') {
|
|
6
|
+
if (!att.data)
|
|
7
|
+
return null;
|
|
8
|
+
return {
|
|
9
|
+
type: 'image',
|
|
10
|
+
data: att.data,
|
|
11
|
+
...(att.uri ? { uri: att.uri } : {}),
|
|
12
|
+
mimeType: att.mimeType,
|
|
13
|
+
fileName: att.name,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
type: 'file',
|
|
18
|
+
path: att.path,
|
|
19
|
+
fileName: att.name,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runWeixinInboundPoller = runWeixinInboundPoller;
|
|
4
|
+
const node_path_1 = require("node:path");
|
|
5
|
+
const local_core_errors_js_1 = require("../../kernel/local-core-errors.js");
|
|
6
|
+
const config_js_1 = require("./config.js");
|
|
7
|
+
const transport_js_1 = require("./transport.js");
|
|
8
|
+
const text_utils_js_1 = require("./text-utils.js");
|
|
9
|
+
const inbound_media_js_1 = require("./inbound-media.js");
|
|
10
|
+
const RETRY_DELAY_MS = 2_000;
|
|
11
|
+
const MAX_CONSECUTIVE_FAILURES = 3;
|
|
12
|
+
const ERROR_LOG_WINDOW_MS = 5 * 60 * 1000;
|
|
13
|
+
function computeRetryDelay(failures) {
|
|
14
|
+
if (failures <= 1)
|
|
15
|
+
return RETRY_DELAY_MS;
|
|
16
|
+
if (failures === 2)
|
|
17
|
+
return 5_000;
|
|
18
|
+
if (failures === 3)
|
|
19
|
+
return 15_000;
|
|
20
|
+
if (failures === 4)
|
|
21
|
+
return 30_000;
|
|
22
|
+
return 60_000;
|
|
23
|
+
}
|
|
24
|
+
async function runWeixinInboundPoller(input) {
|
|
25
|
+
const { binding, signal } = input;
|
|
26
|
+
const errorLogWindows = new Map();
|
|
27
|
+
let buf = (0, config_js_1.loadWeixinBuf)(binding);
|
|
28
|
+
let consecutiveFailures = 0;
|
|
29
|
+
const logPollError = (errorKey, message) => {
|
|
30
|
+
const key = `${binding.workspaceId}:${binding.instanceId}`;
|
|
31
|
+
const now = Date.now();
|
|
32
|
+
const current = errorLogWindows.get(key);
|
|
33
|
+
if (!current || current.errorKey !== errorKey || now - current.at >= ERROR_LOG_WINDOW_MS) {
|
|
34
|
+
input.log?.(current?.count && current.count > 1 ? `${message} (repeated ${current.count} times)` : message);
|
|
35
|
+
errorLogWindows.set(key, { at: now, count: 1, errorKey });
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
current.count += 1;
|
|
39
|
+
errorLogWindows.set(key, current);
|
|
40
|
+
};
|
|
41
|
+
while (!signal.aborted) {
|
|
42
|
+
try {
|
|
43
|
+
const resp = await (0, transport_js_1.getWeixinUpdates)(binding, buf, signal);
|
|
44
|
+
const isApiError = (resp.ret !== undefined && resp.ret !== 0) || (resp.errcode !== undefined && resp.errcode !== 0);
|
|
45
|
+
if (isApiError) {
|
|
46
|
+
consecutiveFailures += 1;
|
|
47
|
+
const state = input.getRuntimeState();
|
|
48
|
+
const retryDelayMs = computeRetryDelay(consecutiveFailures);
|
|
49
|
+
if (resp.errcode === -14 || resp.ret === -14) {
|
|
50
|
+
if (state) {
|
|
51
|
+
state.status = 'error';
|
|
52
|
+
state.connected = false;
|
|
53
|
+
state.consecutiveFailures = consecutiveFailures;
|
|
54
|
+
state.nextRetryAt = new Date(Date.now() + retryDelayMs).toISOString();
|
|
55
|
+
input.setRuntimeError(state, (0, local_core_errors_js_1.toLocalCoreErrorInfo)(new local_core_errors_js_1.LocalCoreError('channel_session_expired', 'WeChat login expired.')));
|
|
56
|
+
input.notifyRuntimeStateChanged();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
logPollError(`ret=${resp.ret} errcode=${resp.errcode} errmsg=${resp.errmsg || ''}`, `localcore-weixin getUpdates failed for ${binding.workspaceId}: ret=${resp.ret} errcode=${resp.errcode}${resp.errmsg ? ` errmsg=${resp.errmsg}` : ''} (${consecutiveFailures})`);
|
|
60
|
+
if (state && resp.errcode !== -14 && resp.ret !== -14) {
|
|
61
|
+
state.consecutiveFailures = consecutiveFailures;
|
|
62
|
+
state.nextRetryAt = new Date(Date.now() + retryDelayMs).toISOString();
|
|
63
|
+
}
|
|
64
|
+
await (0, text_utils_js_1.waitForWeixinRetry)(retryDelayMs, signal);
|
|
65
|
+
if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
|
|
66
|
+
consecutiveFailures = MAX_CONSECUTIVE_FAILURES;
|
|
67
|
+
}
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
consecutiveFailures = 0;
|
|
71
|
+
const state = input.getRuntimeState();
|
|
72
|
+
if (state) {
|
|
73
|
+
input.clearRuntimeError(state);
|
|
74
|
+
state.status = 'running';
|
|
75
|
+
state.connected = true;
|
|
76
|
+
input.notifyRuntimeStateChanged();
|
|
77
|
+
}
|
|
78
|
+
if (resp.get_updates_buf) {
|
|
79
|
+
buf = resp.get_updates_buf;
|
|
80
|
+
(0, config_js_1.saveWeixinBuf)(binding, buf);
|
|
81
|
+
}
|
|
82
|
+
for (const msg of resp.msgs ?? []) {
|
|
83
|
+
const items = msg.item_list ?? [];
|
|
84
|
+
const textItem = items.find((item) => item.type === transport_js_1.TEXT_ITEM_TYPE);
|
|
85
|
+
const voiceTextItems = items.filter((item) => item.type === transport_js_1.VOICE_ITEM_TYPE && item.voice_item?.text);
|
|
86
|
+
const mediaItems = items.filter((item) => item.type === transport_js_1.IMAGE_ITEM_TYPE || item.type === transport_js_1.FILE_ITEM_TYPE);
|
|
87
|
+
if (!textItem && voiceTextItems.length === 0 && mediaItems.length === 0)
|
|
88
|
+
continue;
|
|
89
|
+
const conversationId = msg.from_user_id ?? '';
|
|
90
|
+
const text = [textItem?.text_item?.text?.trim(), ...voiceTextItems.map((item) => item.voice_item?.text?.trim())]
|
|
91
|
+
.filter((part) => Boolean(part))
|
|
92
|
+
.join('\n\n');
|
|
93
|
+
const msgId = msg.msg_id ?? String(Date.now());
|
|
94
|
+
let attachmentText = '';
|
|
95
|
+
const attachmentParts = [];
|
|
96
|
+
if (mediaItems.length > 0) {
|
|
97
|
+
const uploadsDir = (0, node_path_1.join)(binding.stateDir, 'weixin-uploads');
|
|
98
|
+
const mayMaterializeAttachments = binding.allowFrom === '*' || Boolean(input.getAuthorizedUser(binding.workspaceId, conversationId, binding.platformKey));
|
|
99
|
+
if (!mayMaterializeAttachments) {
|
|
100
|
+
for (const item of mediaItems) {
|
|
101
|
+
const itemData = item.image_item ?? item.file_item ?? null;
|
|
102
|
+
const declaredName = String(itemData?.file_name ?? (item.type === transport_js_1.IMAGE_ITEM_TYPE ? 'image' : 'file'));
|
|
103
|
+
attachmentText += attachmentText ? '\n' : '';
|
|
104
|
+
attachmentText += item.type === transport_js_1.IMAGE_ITEM_TYPE ? '[Image]' : `[File: ${declaredName}]`;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
const downloads = await Promise.all(mediaItems.map(async (item, index) => {
|
|
109
|
+
try {
|
|
110
|
+
return await input.downloadMediaItem(item, msgId, index, uploadsDir, binding);
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
input.log?.(`localcore-weixin attachment download failed (${conversationId}#${index}): ${(0, text_utils_js_1.formatWeixinError)(error)}`);
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}));
|
|
117
|
+
for (const attachment of downloads) {
|
|
118
|
+
if (!attachment) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
attachmentText += attachmentText ? '\n' : '';
|
|
122
|
+
attachmentText += attachment.kind === 'image'
|
|
123
|
+
? `[Image: ${attachment.path}]`
|
|
124
|
+
: `[File "${attachment.name}": ${attachment.path}]`;
|
|
125
|
+
const part = (0, inbound_media_js_1.createWeixinAttachmentContentPart)(attachment);
|
|
126
|
+
if (part)
|
|
127
|
+
attachmentParts.push(part);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const fullText = [text, attachmentText].filter(Boolean).join('\n\n');
|
|
132
|
+
if (!fullText)
|
|
133
|
+
continue;
|
|
134
|
+
await input.handleInboundMessage({
|
|
135
|
+
workspaceId: binding.workspaceId,
|
|
136
|
+
instanceId: binding.instanceId,
|
|
137
|
+
platformKey: binding.platformKey,
|
|
138
|
+
platformUserId: conversationId,
|
|
139
|
+
chatId: conversationId,
|
|
140
|
+
displayName: conversationId.slice(-6),
|
|
141
|
+
text: fullText,
|
|
142
|
+
messageId: msgId,
|
|
143
|
+
contextToken: msg.context_token,
|
|
144
|
+
contentParts: [
|
|
145
|
+
...(text ? [{ type: 'text', text }] : []),
|
|
146
|
+
...attachmentParts,
|
|
147
|
+
],
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (signal.aborted)
|
|
153
|
+
return;
|
|
154
|
+
consecutiveFailures += 1;
|
|
155
|
+
const retryDelayMs = computeRetryDelay(consecutiveFailures);
|
|
156
|
+
const state = input.getRuntimeState();
|
|
157
|
+
if (state) {
|
|
158
|
+
state.consecutiveFailures = consecutiveFailures;
|
|
159
|
+
state.nextRetryAt = new Date(Date.now() + retryDelayMs).toISOString();
|
|
160
|
+
input.setRuntimeError(state, (0, local_core_errors_js_1.toLocalCoreErrorInfo)(error));
|
|
161
|
+
input.notifyRuntimeStateChanged();
|
|
162
|
+
}
|
|
163
|
+
logPollError((0, text_utils_js_1.formatWeixinError)(error), `localcore-weixin getUpdates error for ${binding.workspaceId} (${consecutiveFailures}): ${(0, text_utils_js_1.formatWeixinError)(error)}`);
|
|
164
|
+
await (0, text_utils_js_1.waitForWeixinRetry)(retryDelayMs, signal);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|