@kafca/agentdock 0.1.56 → 0.1.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/README.md +7 -0
  2. package/dist/renderer/assets/{Badge-DjcoXx2J.js → Badge-CDTbmw1h.js} +1 -1
  3. package/dist/renderer/assets/Card-DayUo35w.js +1 -0
  4. package/dist/renderer/assets/Config-ByGMQuzR.js +21 -0
  5. package/dist/renderer/assets/CronList-XqHdVlgu.js +1 -0
  6. package/dist/renderer/assets/Dashboard-CZj-oANw.js +41 -0
  7. package/dist/renderer/assets/{EmptyState-DIZLiccW.js → EmptyState-EFMkOjZO.js} +1 -1
  8. package/dist/renderer/assets/HighlightedMarkdown-DyvF3DHK.js +12 -0
  9. package/dist/renderer/assets/Input-DxoWVc9d.js +1 -0
  10. package/dist/renderer/assets/{KnowledgeDetail-CJ9IYOsa.js → KnowledgeDetail-CbUb2tG7.js} +2 -2
  11. package/dist/renderer/assets/{KnowledgeHome-BLGPwnBO.js → KnowledgeHome-BWV1gz4f.js} +3 -3
  12. package/dist/renderer/assets/Logs-DqnanQTc.js +6 -0
  13. package/dist/renderer/assets/{Modal-CQiUpfl4.js → Modal-yY7TzR0x.js} +3 -3
  14. package/dist/renderer/assets/MonitorList-CIjGQkFs.js +1 -0
  15. package/dist/renderer/assets/Page-vwHNUdoj.js +1 -0
  16. package/dist/renderer/assets/{Select-D6z65IT3.js → Select-CmbK36pN.js} +2 -2
  17. package/dist/renderer/assets/ThreadChat-4OceMgM4.js +86 -0
  18. package/dist/renderer/assets/Workspace-DplPJOjJ.js +19 -0
  19. package/dist/renderer/assets/{arrow-left-CV5cL3f4.js → arrow-left-C8HfBt2K.js} +1 -1
  20. package/dist/renderer/assets/{book-open-DThvB7pj.js → book-open-BCdZWncQ.js} +1 -1
  21. package/dist/renderer/assets/channels-hgO3cAIx.js +6 -0
  22. package/dist/renderer/assets/chevron-down-BPk77tqY.js +11 -0
  23. package/dist/renderer/assets/index-BIKL3fTP.css +11 -0
  24. package/dist/renderer/assets/index-BlA4xPdd.js +41 -0
  25. package/dist/renderer/assets/index-wYpjqVqC.js +167 -0
  26. package/dist/renderer/assets/knowledge-7pl06KuH.js +1 -0
  27. package/dist/renderer/assets/{pencil-Dv5WxhdC.js → pencil-CB1SWZ9A.js} +1 -1
  28. package/dist/renderer/assets/{play-DnCnft83.js → play-BvsoXUrM.js} +1 -1
  29. package/dist/renderer/assets/{plus-DsxIagzS.js → plus-CokBDnaL.js} +1 -1
  30. package/dist/renderer/assets/{save-CST01lIc.js → save-D-w4kATO.js} +1 -1
  31. package/dist/renderer/assets/{search-B_bqy6Wd.js → search-Cnsn6i4Q.js} +1 -1
  32. package/dist/renderer/assets/{shield-check-D6lG5Aoc.js → shield-check-Cjja2Gh6.js} +1 -1
  33. package/dist/renderer/assets/threads-BCm6j4eI.js +1 -0
  34. package/dist/renderer/assets/{trash-2-Cefngb6Q.js → trash-2-CIxz9qYY.js} +1 -1
  35. package/dist/renderer/index.html +2 -2
  36. package/dist-electron/packages/contracts/src/automation.js +2 -0
  37. package/dist-electron/packages/contracts/src/channels.js +2 -0
  38. package/dist-electron/packages/contracts/src/knowledge.js +2 -0
  39. package/dist-electron/packages/contracts/src/local-core.js +15 -0
  40. package/dist-electron/packages/contracts/src/runtime.js +2 -0
  41. package/dist-electron/packages/contracts/src/scheduler.js +2 -0
  42. package/dist-electron/packages/contracts/src/threads.js +2 -0
  43. package/dist-electron/packages/core-sdk/src/automation.js +32 -0
  44. package/dist-electron/packages/core-sdk/src/channels.js +121 -0
  45. package/dist-electron/packages/core-sdk/src/client.js +455 -0
  46. package/dist-electron/packages/core-sdk/src/index.js +43 -607
  47. package/dist-electron/packages/core-sdk/src/knowledge.js +85 -0
  48. package/dist-electron/packages/core-sdk/src/request.js +22 -0
  49. package/dist-electron/packages/core-sdk/src/runtime.js +214 -0
  50. package/dist-electron/packages/core-sdk/src/scheduler.js +32 -0
  51. package/dist-electron/packages/core-sdk/src/threads.js +67 -0
  52. package/dist-electron/packages/plugin-sdk/src/agents.js +2 -0
  53. package/dist-electron/packages/plugin-sdk/src/automation.js +2 -0
  54. package/dist-electron/packages/plugin-sdk/src/channels.js +2 -0
  55. package/dist-electron/packages/plugin-sdk/src/index.js +21 -0
  56. package/dist-electron/packages/plugin-sdk/src/knowledge.js +2 -0
  57. package/dist-electron/packages/plugin-sdk/src/runtime.js +2 -0
  58. package/dist-electron/packages/plugin-sdk/src/scheduler.js +2 -0
  59. package/dist-electron/packages/plugin-sdk/src/threads.js +2 -0
  60. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +5 -8
  61. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-content.js +2 -2
  62. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +3 -3
  63. package/dist-electron/services/local-ai-core/src/acp/store/agent-task-store.js +5 -5
  64. package/dist-electron/services/local-ai-core/src/acp/store/automation-monitor-store.js +12 -12
  65. package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +2 -2
  66. package/dist-electron/services/local-ai-core/src/acp/store/scheduler-store.js +11 -11
  67. package/dist-electron/services/local-ai-core/src/acp/store/security-store.js +3 -3
  68. package/dist-electron/services/local-ai-core/src/acp/store/thread-store.js +7 -7
  69. package/dist-electron/services/local-ai-core/src/acp/workspace-acp-permissions.js +2 -2
  70. package/dist-electron/services/local-ai-core/src/agents/claudecode/definition.js +3 -3
  71. package/dist-electron/services/local-ai-core/src/agents/codex/definition.js +3 -3
  72. package/dist-electron/services/local-ai-core/src/agents/localcore-acp/definition.js +2 -2
  73. package/dist-electron/services/local-ai-core/src/agents/localcore-acp/index.js +4 -4
  74. package/dist-electron/services/local-ai-core/src/agents/opencode/launch.js +2 -2
  75. package/dist-electron/services/local-ai-core/src/agents/pi/definition.js +2 -2
  76. package/dist-electron/services/local-ai-core/src/agents/pi/launch.js +3 -3
  77. package/dist-electron/services/local-ai-core/src/agents/pi/provider-materializer.js +1 -1
  78. package/dist-electron/services/local-ai-core/src/agents/shared/agent-plugin.js +4 -4
  79. package/dist-electron/services/local-ai-core/src/channel/lark/cards.js +33 -18
  80. package/dist-electron/services/local-ai-core/src/channel/lark/config.js +2 -2
  81. package/dist-electron/services/local-ai-core/src/channel/lark/gateway-utils.js +91 -0
  82. package/dist-electron/services/local-ai-core/src/channel/lark/inbound-handler.js +180 -0
  83. package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +52 -486
  84. package/dist-electron/services/local-ai-core/src/channel/lark/outbound-transport.js +124 -0
  85. package/dist-electron/services/local-ai-core/src/channel/shared/inbound-authorization.js +54 -0
  86. package/dist-electron/services/local-ai-core/src/channel/weixin/config.js +2 -2
  87. package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-media.js +21 -0
  88. package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-poller.js +167 -0
  89. package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +50 -469
  90. package/dist-electron/services/local-ai-core/src/channel/weixin/runtime-state.js +156 -0
  91. package/dist-electron/services/local-ai-core/src/channel/weixin/text-utils.js +100 -0
  92. package/dist-electron/services/local-ai-core/src/cli/lac.js +6 -6
  93. package/dist-electron/services/local-ai-core/src/cli/monitor-cli-parsers.js +2 -2
  94. package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +28 -70
  95. package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-ai-vector-plugin.js +2 -2
  96. package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-noop-plugin.js +2 -2
  97. package/dist-electron/services/local-ai-core/src/router/workspace-bridge-event-stream.js +29 -0
  98. package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +5 -5
  99. package/dist-electron/services/local-ai-core/src/router/workspace-router.js +47 -60
  100. package/dist-electron/services/local-ai-core/src/runtime/agent-runtime-detector.js +5 -5
  101. package/dist-electron/services/local-ai-core/src/runtime/config-migration.js +6 -6
  102. package/dist-electron/services/local-ai-core/src/runtime/deployment-diagnostics.js +3 -3
  103. package/dist-electron/services/local-ai-core/src/runtime/external-service.js +3 -1
  104. package/dist-electron/services/local-ai-core/src/runtime/handlers/automation-handler.js +11 -2
  105. package/dist-electron/services/local-ai-core/src/runtime/handlers/channel-handler.js +12 -6
  106. package/dist-electron/services/local-ai-core/src/runtime/handlers/external-handler.js +10 -2
  107. package/dist-electron/services/local-ai-core/src/runtime/handlers/knowledge-handler.js +18 -6
  108. package/dist-electron/services/local-ai-core/src/runtime/handlers/provider-handler.js +7 -2
  109. package/dist-electron/services/local-ai-core/src/runtime/handlers/runtime-handler.js +28 -3
  110. package/dist-electron/services/local-ai-core/src/runtime/handlers/scheduler-handler.js +10 -2
  111. package/dist-electron/services/local-ai-core/src/runtime/handlers/security-handler.js +18 -5
  112. package/dist-electron/services/local-ai-core/src/runtime/handlers/task-handler.js +14 -2
  113. package/dist-electron/services/local-ai-core/src/runtime/handlers/thread-handler.js +18 -15
  114. package/dist-electron/services/local-ai-core/src/runtime/handlers/workspace-handler.js +13 -2
  115. package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +35 -8
  116. package/dist-electron/services/local-ai-core/src/runtime/request-validation.js +79 -0
  117. package/dist-electron/services/local-ai-core/src/runtime/runtime-detection-service.js +9 -9
  118. package/dist-electron/services/local-ai-core/src/runtime/server-helpers.js +10 -1
  119. package/dist-electron/services/local-ai-core/src/runtime/server.js +2 -1
  120. package/dist-electron/services/local-ai-core/src/runtime/workspace-project-registry.js +76 -0
  121. package/dist-electron/services/local-ai-core/src/sandbox/sandbox-config.js +8 -8
  122. package/dist-electron/services/local-ai-core/src/thread/agent-message-policy.js +75 -0
  123. package/dist-electron/shared/desktop.js +1 -64
  124. package/dist-electron/src/components/chat/chat-controller-state.js +60 -0
  125. package/dist-electron/src/components/chat/chat-event-gate.js +146 -0
  126. package/dist-electron/src/components/chat/markdown-code-block.js +8 -0
  127. package/dist-electron/src/pages/Desktop/workspace-model.js +212 -0
  128. package/dist-electron/src/pages/Threads/thread-chat-model.js +50 -51
  129. package/dist-electron/tests/contracts/agent-message-policy.test.js +21 -0
  130. package/dist-electron/tests/contracts/architecture-docs.test.js +56 -33
  131. package/dist-electron/tests/contracts/chat-event-gate.test.js +114 -0
  132. package/dist-electron/tests/contracts/chat-markdown.test.js +16 -0
  133. package/dist-electron/tests/contracts/thread-task-state.test.js +32 -0
  134. package/dist-electron/tests/contracts/workspace-identity.test.js +23 -0
  135. package/dist-electron/tests/electron/core-client.test.js +284 -0
  136. package/dist-electron/tests/electron/plugin-kernel.test.js +54 -0
  137. package/dist-electron/tests/electron/renderer-packaging.test.js +9 -0
  138. package/dist-electron/tests/electron/workspace-task-store.test.js +31 -0
  139. package/dist-electron/tests/integration/channel-inbound-authorization.test.js +80 -0
  140. package/dist-electron/tests/integration/lark-gateway-utils.test.js +13 -0
  141. package/dist-electron/tests/integration/lark-gateway.test.js +4 -4
  142. package/dist-electron/tests/integration/weixin-runtime-state.test.js +32 -0
  143. package/dist-electron/tests/integration/weixin-text-utils.test.js +15 -0
  144. package/package.json +9 -4
  145. package/dist/renderer/assets/Chat-C5Bkm9-M.js +0 -2
  146. package/dist/renderer/assets/ChatMarkdown-uc36EzyD.js +0 -45
  147. package/dist/renderer/assets/Config-DHtQuuLy.js +0 -21
  148. package/dist/renderer/assets/CronList-BYUnhzSC.js +0 -1
  149. package/dist/renderer/assets/Dashboard-BPnGMDg3.js +0 -26
  150. package/dist/renderer/assets/Logs-Dyd2Uwlt.js +0 -1
  151. package/dist/renderer/assets/MonitorList-Byg3E3Gt.js +0 -1
  152. package/dist/renderer/assets/Page-7DxXvTMm.js +0 -1
  153. package/dist/renderer/assets/ProjectDetail-Dfr5s0Ja.js +0 -11
  154. package/dist/renderer/assets/ProjectList-CDDQjAQ_.js +0 -1
  155. package/dist/renderer/assets/SessionChat-s7CAaCPL.js +0 -1
  156. package/dist/renderer/assets/SessionList-D-OycKKS.js +0 -1
  157. package/dist/renderer/assets/ThreadChat-CLdFynB5.js +0 -28
  158. package/dist/renderer/assets/Workspace-xfT5z4j_.js +0 -19
  159. package/dist/renderer/assets/bot-CWQ5-ovl.js +0 -6
  160. package/dist/renderer/assets/check-DKM7zfWG.js +0 -6
  161. package/dist/renderer/assets/chevron-down-Dfw2KU87.js +0 -6
  162. package/dist/renderer/assets/circle-CoP4RA4s.js +0 -6
  163. package/dist/renderer/assets/desktop-CsDYrOOU.js +0 -1
  164. package/dist/renderer/assets/desktop-JQkhNOF4.js +0 -5
  165. package/dist/renderer/assets/funnel-DpVLlG3g.js +0 -6
  166. package/dist/renderer/assets/heart-BMD36ejP.js +0 -6
  167. package/dist/renderer/assets/index-COxSYBjE.js +0 -182
  168. package/dist/renderer/assets/index-CTGTI-cm.js +0 -41
  169. package/dist/renderer/assets/index-CjCuR6DI.css +0 -11
  170. package/dist/renderer/assets/projects-DgjHcNgt.js +0 -1
  171. package/dist/renderer/assets/server-ecH4GNwa.js +0 -11
  172. package/dist/renderer/assets/session-utils-Dd_WKMYW.js +0 -6
  173. package/dist/renderer/assets/sessions-BQ33Mv4k.js +0 -1
  174. package/dist/renderer/assets/user-D_8RSH-T.js +0 -6
  175. package/dist/renderer/assets/wifi-off-DB9D-pOu.js +0 -11
  176. package/dist-electron/src/api/client.js +0 -73
  177. package/dist-electron/src/api/sessions.js +0 -21
  178. package/dist-electron/src/lib/session-utils.js +0 -51
  179. package/dist-electron/src/pages/Projects/project-provider-config.js +0 -75
  180. package/dist-electron/tests/electron/project-provider-config.test.js +0 -71
@@ -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 desktop_js_1 = require("../../../../../shared/desktop.js");
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, desktop_js_1.normalizeDesktopPlatformType)(platform?.type),
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
+ }