@kafca/agentdock 0.1.43 → 0.1.45

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 (119) hide show
  1. package/README.md +77 -11
  2. package/bin/agentdock.mjs +5 -5
  3. package/dist/renderer/assets/{Badge-CbG6yRSm.js → Badge-BIojwD6s.js} +1 -1
  4. package/dist/renderer/assets/{Chat-BvNNWGGX.js → Chat-wjBR3XEX.js} +1 -1
  5. package/dist/renderer/assets/{ChatMarkdown-Ct-PvJB8.js → ChatMarkdown-DqszsPB_.js} +1 -1
  6. package/dist/renderer/assets/Config-BDCHs5A2.js +21 -0
  7. package/dist/renderer/assets/{CronList-Dj_3muVG.js → CronList-CEWQYTov.js} +1 -1
  8. package/dist/renderer/assets/Dashboard-DrWftfk3.js +26 -0
  9. package/dist/renderer/assets/{EmptyState-Bn2Qh14U.js → EmptyState-BqCx1oWr.js} +1 -1
  10. package/dist/renderer/assets/{KnowledgeDetail-Bsz6Ou41.js → KnowledgeDetail-BwK8Gpfa.js} +2 -2
  11. package/dist/renderer/assets/{KnowledgeHome-Cgj4XFXn.js → KnowledgeHome-hhDTZMDO.js} +3 -3
  12. package/dist/renderer/assets/{Logs-Dp-NF6GN.js → Logs-C9xPEhFT.js} +1 -1
  13. package/dist/renderer/assets/{Modal-B6YPPBN6.js → Modal-D2U4r2V0.js} +1 -1
  14. package/dist/renderer/assets/{MonitorList-xEZWg460.js → MonitorList-CayKbfwJ.js} +1 -1
  15. package/dist/renderer/assets/{Page-Bn7RjGOS.js → Page-urf5GcT_.js} +1 -1
  16. package/dist/renderer/assets/ProjectDetail-B1GyAr7a.js +11 -0
  17. package/dist/renderer/assets/{ProjectList-BDk5_gqY.js → ProjectList-BoipQypE.js} +1 -1
  18. package/dist/renderer/assets/{Select-xshfMIEQ.js → Select-CAscWpy5.js} +1 -1
  19. package/dist/renderer/assets/{SessionChat-BkHy90z3.js → SessionChat-BAVy5221.js} +1 -1
  20. package/dist/renderer/assets/{SessionList-BZyXT92L.js → SessionList-BZpuMvh0.js} +1 -1
  21. package/dist/renderer/assets/{ThreadChat-DUOIyXrS.js → ThreadChat-JX7m9biG.js} +1 -1
  22. package/dist/renderer/assets/Workspace-CFW8otjU.js +14 -0
  23. package/dist/renderer/assets/{arrow-left-C54ZI-AS.js → arrow-left-7HrNuS-V.js} +1 -1
  24. package/dist/renderer/assets/{book-open-Dl7GO0zn.js → book-open-BDoAu82s.js} +1 -1
  25. package/dist/renderer/assets/{check-CiqgtrOL.js → check-DGlyq4xX.js} +1 -1
  26. package/dist/renderer/assets/{chevron-down-DTL2OuVh.js → chevron-down-Bb_3EHq9.js} +1 -1
  27. package/dist/renderer/assets/{circle-DaVKfa3P.js → circle-DIpqZnYw.js} +1 -1
  28. package/dist/renderer/assets/desktop-Ci1fnRDR.js +1 -0
  29. package/dist/renderer/assets/{desktop-C6q6wBae.js → desktop-Do_UrC-o.js} +5 -5
  30. package/dist/renderer/assets/en-CmAr_0e6.js +1 -0
  31. package/dist/renderer/assets/es-Cs9x52ca.js +1 -0
  32. package/dist/renderer/assets/{funnel-CrmnLMJI.js → funnel-Bbf0ERLP.js} +1 -1
  33. package/dist/renderer/assets/{heart-BMfQI7y_.js → heart-CGqU-qfw.js} +1 -1
  34. package/dist/renderer/assets/{index-nreiKY1f.js → index-Df-Trovt.js} +2 -2
  35. package/dist/renderer/assets/{index-HPNb1zfx.js → index-DwhTjLA1.js} +36 -36
  36. package/dist/renderer/assets/index-RaTga2BC.css +11 -0
  37. package/dist/renderer/assets/ja-DtvtBRTW.js +1 -0
  38. package/dist/renderer/assets/{pencil-wTQ4l465.js → pencil-CHiy1MvK.js} +1 -1
  39. package/dist/renderer/assets/{play-BK--MXmw.js → play-CGYnmC4Q.js} +1 -1
  40. package/dist/renderer/assets/{plug-BIx9fjip.js → plug-Mexu4gyV.js} +1 -1
  41. package/dist/renderer/assets/{plus-Dn7JFWQ8.js → plus-B_Q5-Oj7.js} +1 -1
  42. package/dist/renderer/assets/projects-C6bbkC-O.js +1 -0
  43. package/dist/renderer/assets/{save-CC3zOSWb.js → save-CJ_QFPw0.js} +1 -1
  44. package/dist/renderer/assets/{search-CDTy9Czu.js → search-D8Dkhsyq.js} +1 -1
  45. package/dist/renderer/assets/{server-DtQk3t2a.js → server-Cd96R7WL.js} +1 -1
  46. package/dist/renderer/assets/{session-utils-4ep5D66T.js → session-utils-BNUbQBfF.js} +1 -1
  47. package/dist/renderer/assets/{sessions-Dor1LteH.js → sessions-BACfV8s1.js} +1 -1
  48. package/dist/renderer/assets/{shield-check-Cz2LpU6r.js → shield-check-Cnn-yQUA.js} +1 -1
  49. package/dist/renderer/assets/{trash-2-C2EmWFZV.js → trash-2-oWCxwQ9D.js} +1 -1
  50. package/dist/renderer/assets/{user-I8B-cs5A.js → user-BzE9BwsY.js} +1 -1
  51. package/dist/renderer/assets/{wifi-off-CPevTQJn.js → wifi-off-DHxnNkdY.js} +1 -1
  52. package/dist/renderer/assets/zh-CcJ9vBZj.js +1 -0
  53. package/dist/renderer/assets/zh-TW-elI72AC1.js +1 -0
  54. package/dist/renderer/index.html +2 -2
  55. package/dist-electron/electron/main.js +26 -1
  56. package/dist-electron/packages/core-sdk/src/index.js +28 -0
  57. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +111 -62
  58. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-session-coordinator.js +80 -7
  59. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-transport.js +78 -5
  60. package/dist-electron/services/local-ai-core/src/acp/store/external-store.js +98 -0
  61. package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +33 -0
  62. package/dist-electron/services/local-ai-core/src/acp/store/model-provider-store.js +88 -0
  63. package/dist-electron/services/local-ai-core/src/acp/store/schema.js +43 -0
  64. package/dist-electron/services/local-ai-core/src/agents/pi/launch.js +2 -119
  65. package/dist-electron/services/local-ai-core/src/agents/pi/provider-materializer.js +148 -0
  66. package/dist-electron/services/local-ai-core/src/channel/lark/config.js +2 -0
  67. package/dist-electron/services/local-ai-core/src/channel/lark/inbound.js +114 -0
  68. package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +117 -75
  69. package/dist-electron/services/local-ai-core/src/channel/shared/session-command-runtime.js +4 -2
  70. package/dist-electron/services/local-ai-core/src/channel/shared/thread-routing.js +34 -0
  71. package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +151 -47
  72. package/dist-electron/services/local-ai-core/src/execution/agent-execution-backend.js +56 -0
  73. package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +18 -57
  74. package/dist-electron/services/local-ai-core/src/kernel/local-core-errors.js +255 -0
  75. package/dist-electron/services/local-ai-core/src/plugins/builtin/catalog.js +78 -0
  76. package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +3 -1
  77. package/dist-electron/services/local-ai-core/src/router/workspace-router.js +64 -9
  78. package/dist-electron/services/local-ai-core/src/runtime/agent-runtime-detector.js +5 -2
  79. package/dist-electron/services/local-ai-core/src/runtime/config-migration.js +152 -0
  80. package/dist-electron/services/local-ai-core/src/runtime/deployment-diagnostics.js +175 -0
  81. package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +330 -3
  82. package/dist-electron/services/local-ai-core/src/runtime/local-core-runtime-state.js +11 -2
  83. package/dist-electron/services/local-ai-core/src/runtime/provider-config-migration.js +32 -0
  84. package/dist-electron/services/local-ai-core/src/runtime/runtime-detection-service.js +76 -8
  85. package/dist-electron/services/local-ai-core/src/runtime/server-routes.js +62 -0
  86. package/dist-electron/services/local-ai-core/src/runtime/server.js +708 -4
  87. package/dist-electron/services/local-ai-core/src/runtime/standalone.js +13 -3
  88. package/dist-electron/services/local-ai-core/src/sandbox/opensandbox-client.js +113 -0
  89. package/dist-electron/services/local-ai-core/src/sandbox/sandbox-config.js +273 -0
  90. package/dist-electron/services/local-ai-core/src/sandbox/sandbox-manager.js +215 -0
  91. package/dist-electron/services/local-ai-core/src/sandbox/sandbox-stdio-proxy.js +188 -0
  92. package/dist-electron/services/local-ai-core/src/thread/slash-command-registry.js +3 -0
  93. package/dist-electron/services/local-ai-core/src/thread/thread-command-service.js +32 -0
  94. package/dist-electron/services/local-ai-core/src/thread/thread-slash-command-dispatcher.js +71 -0
  95. package/dist-electron/shared/desktop.js +85 -1
  96. package/dist-electron/tests/contracts/architecture-docs.test.js +83 -0
  97. package/dist-electron/tests/electron/plugin-kernel.test.js +225 -18
  98. package/dist-electron/tests/electron/runtime-detection-service.test.js +57 -5
  99. package/dist-electron/tests/electron/sandbox-config.test.js +541 -0
  100. package/dist-electron/tests/electron/workspace-task-store.test.js +257 -0
  101. package/dist-electron/tests/integration/channel-gateways.test.js +32 -0
  102. package/dist-electron/tests/integration/lark-gateway.test.js +1977 -0
  103. package/dist-electron/tests/integration/local-core-acp-progress.test.js +1772 -0
  104. package/dist-electron/tests/integration/local-core-refactor.test.js +775 -5156
  105. package/dist-electron/tests/integration/local-core-routes.test.js +238 -0
  106. package/dist-electron/tests/integration/weixin-gateway.test.js +927 -0
  107. package/package.json +2 -3
  108. package/dist/renderer/assets/Config-lQX2qVVV.js +0 -16
  109. package/dist/renderer/assets/Dashboard-eh_RhGYb.js +0 -26
  110. package/dist/renderer/assets/ProjectDetail-Cv_jIE61.js +0 -11
  111. package/dist/renderer/assets/Workspace-Dl80fNEC.js +0 -14
  112. package/dist/renderer/assets/desktop-jaAiayNB.js +0 -1
  113. package/dist/renderer/assets/en-D2SkCrhG.js +0 -1
  114. package/dist/renderer/assets/es-C8UBPhxM.js +0 -1
  115. package/dist/renderer/assets/index-CaQZSRbg.css +0 -11
  116. package/dist/renderer/assets/ja-ChF4vbBL.js +0 -1
  117. package/dist/renderer/assets/projects-brJZgwEJ.js +0 -1
  118. package/dist/renderer/assets/zh-DIcdHycM.js +0 -1
  119. package/dist/renderer/assets/zh-TW-BtRwreY_.js +0 -1
@@ -11,10 +11,12 @@ const node_path_1 = __importDefault(require("node:path"));
11
11
  const node_events_1 = require("node:events");
12
12
  const node_crypto_2 = require("node:crypto");
13
13
  const desktop_js_1 = require("../../../../../shared/desktop.js");
14
+ const local_core_errors_js_1 = require("../../kernel/local-core-errors.js");
14
15
  const content_js_1 = require("../shared/content.js");
15
16
  const file_utils_js_1 = require("../shared/file-utils.js");
16
17
  const session_command_runtime_js_1 = require("../shared/session-command-runtime.js");
17
- const session_command_service_js_1 = require("../../thread/session-command-service.js");
18
+ const thread_routing_js_1 = require("../shared/thread-routing.js");
19
+ const thread_slash_command_dispatcher_js_1 = require("../../thread/thread-slash-command-dispatcher.js");
18
20
  const config_js_1 = require("./config.js");
19
21
  const transport_js_1 = require("./transport.js");
20
22
  // ==================== Constants ====================
@@ -30,6 +32,7 @@ const WEIXIN_RESERVED_TERMINAL_SENDS = 1;
30
32
  const WEIXIN_PROGRESS_SEND_BUDGET = WEIXIN_CONTEXT_SEND_LIMIT - WEIXIN_RESERVED_TERMINAL_SENDS;
31
33
  const RESPONSE_TIMEOUT_MS = 5 * 60 * 1000;
32
34
  const WEIXIN_MAX_UPLOAD_FILE_SIZE = 30 * 1024 * 1024;
35
+ const ERROR_LOG_WINDOW_MS = 5 * 60 * 1000;
33
36
  // ==================== Utilities ====================
34
37
  function stripHtml(html) {
35
38
  let result = html;
@@ -152,21 +155,36 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
152
155
  outboundTurns = new Map();
153
156
  processedInboundMessages = new Map();
154
157
  mutedThreadBridgeCounts = new Map();
158
+ pollErrorLogWindows = new Map();
155
159
  sessionCommandRuntime;
156
160
  platform = 'weixin';
157
161
  routeType = 'channel.chat';
158
162
  constructor(options) {
159
163
  super();
160
164
  this.options = options;
161
- const sessionCommandService = new session_command_service_js_1.SessionCommandService({
162
- listThreads: (workspaceId) => this.options.getWorkspaceRouter().listThreads(workspaceId),
163
- getThread: (threadId) => this.options.getWorkspaceRouter().getThread(threadId),
164
- createThread: (workspaceId, title) => this.options.getWorkspaceRouter().createThread(workspaceId, title),
165
- renameThread: (threadId, title) => this.options.getWorkspaceRouter().renameThread(threadId, title),
166
- deleteThread: (threadId) => this.options.getWorkspaceRouter().deleteThread(threadId),
165
+ const slashCommands = new thread_slash_command_dispatcher_js_1.ThreadSlashCommandDispatcher({
166
+ session: {
167
+ listThreads: (workspaceId) => this.options.getWorkspaceRouter().listThreads(workspaceId),
168
+ getThread: (threadId) => this.options.getWorkspaceRouter().getThread(threadId),
169
+ createThread: (workspaceId, title) => this.options.getWorkspaceRouter().createThread(workspaceId, title),
170
+ renameThread: (threadId, title) => this.options.getWorkspaceRouter().renameThread(threadId, title),
171
+ deleteThread: (threadId) => this.options.getWorkspaceRouter().deleteThread(threadId),
172
+ },
173
+ thread: {
174
+ getThreadRow: (threadId) => this.options.store.getThreadRow(threadId),
175
+ updateThreadAgentMode: (threadId, mode) => this.options.store.updateThreadAgentMode(threadId, mode),
176
+ updateThreadAgentType: (threadId, agentType) => this.options.store.updateThreadAgentType(threadId, agentType),
177
+ getLatestRunForThread: (threadId) => this.options.store.getLatestRunForThread(threadId),
178
+ createAuditEvent: (input) => this.options.store.createAuditEvent(input),
179
+ getAgentTypes: () => this.options.getWorkspaceRouter().getAgentTypes(),
180
+ setThreadMode: (threadId, mode) => this.options.getWorkspaceRouter().setThreadMode(threadId, mode),
181
+ closeThreadSession: (threadId) => this.options.getWorkspaceRouter().closeThreadSession(threadId),
182
+ interruptRun: (runId) => this.options.getWorkspaceRouter().interruptRun(runId),
183
+ log: this.options.log,
184
+ },
167
185
  });
168
186
  this.sessionCommandRuntime = new session_command_runtime_js_1.ChannelSessionCommandRuntime({
169
- service: sessionCommandService,
187
+ dispatcher: slashCommands,
170
188
  store: this.options.store,
171
189
  getThreadSessionKey: (threadId) => this.options.getWorkspaceRouter().getThreadSessionKey(threadId),
172
190
  setThreadRoute: (sessionKey, route) => {
@@ -259,6 +277,10 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
259
277
  status: binding?.status || 'disabled',
260
278
  appId: binding?.accountId || '',
261
279
  lastError: binding?.lastError,
280
+ lastErrorInfo: binding?.lastErrorInfo,
281
+ lastErrorAt: binding?.lastErrorAt,
282
+ consecutiveFailures: binding?.consecutiveFailures,
283
+ nextRetryAt: binding?.nextRetryAt,
262
284
  connectedAt: binding?.connectedAt,
263
285
  pendingPairings: pairings.length,
264
286
  authorizedUsers: users.length,
@@ -657,24 +679,17 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
657
679
  return { paired: false };
658
680
  }
659
681
  const router = this.options.getWorkspaceRouter();
660
- const threadBinding = this.options.store.getPlatformThreadBinding(input.workspaceId, input.chatId, input.platformUserId, platformKey);
661
- let threadId = threadBinding?.thread_id || authorized.thread_id || '';
662
- if (!threadId) {
663
- const thread = await router.createThread(input.workspaceId, input.displayName || `WeChat ${input.chatId}`);
664
- threadId = thread.id;
665
- this.options.store.updateAuthorizedUserThread(input.workspaceId, input.platformUserId, threadId, platformKey);
666
- const now = new Date().toISOString();
667
- this.options.store.upsertPlatformThreadBinding({
668
- workspace_id: input.workspaceId,
669
- platform: platformKey,
670
- chat_id: input.chatId,
671
- platform_user_id: input.platformUserId,
672
- thread_id: threadId,
673
- last_platform_message_id: null,
674
- created_at: now,
675
- updated_at: now,
676
- });
677
- }
682
+ let { threadId } = await (0, thread_routing_js_1.resolveChannelThreadRoute)({
683
+ store: this.options.store,
684
+ router,
685
+ workspaceId: input.workspaceId,
686
+ platformKey,
687
+ chatId: input.chatId,
688
+ platformUserId: input.platformUserId,
689
+ displayName: input.displayName,
690
+ fallbackTitlePrefix: 'WeChat',
691
+ authorized,
692
+ });
678
693
  const normalizedText = String(input.text || '').trim().toLowerCase();
679
694
  const permissionThreadId = (normalizedText === 'allow' || normalizedText === 'allow all' || normalizedText === 'deny') ? this.findAwaitingPermissionThreadId(input.workspaceId, input.chatId, input.platformUserId, input.platformKey) : '';
680
695
  if (permissionThreadId && permissionThreadId !== threadId) {
@@ -696,6 +711,7 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
696
711
  currentThreadId: threadId,
697
712
  text: input.text,
698
713
  defaultTitle: `${input.displayName || 'WeChat'} ${new Date().toLocaleTimeString()}`,
714
+ defaultAgentType: slashCommand ? await this.resolveDefaultAgentType(input.workspaceId, threadId) : '',
699
715
  chatId: input.chatId,
700
716
  platformUserId: input.platformUserId,
701
717
  platformKey,
@@ -729,6 +745,13 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
729
745
  }
730
746
  await this.sendTextMessage(state, input.chatId, result.displayText, input.contextToken);
731
747
  }
748
+ async resolveDefaultAgentType(workspaceId, threadId) {
749
+ const router = this.options.getWorkspaceRouter();
750
+ if (typeof router.getWorkspaceDefaultAgentType === 'function') {
751
+ return router.getWorkspaceDefaultAgentType(workspaceId);
752
+ }
753
+ return this.options.store.getThreadRow(threadId)?.agent_type || 'codex';
754
+ }
732
755
  // ==================== Private: Bindings ====================
733
756
  resolveRuntimeState(workspaceId, instanceId) {
734
757
  if (instanceId) {
@@ -775,20 +798,28 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
775
798
  status.status = 'stopped';
776
799
  status.connected = false;
777
800
  status.lastError = 'Scan the WeChat QR code to finish login before starting message polling.';
801
+ status.lastErrorInfo = new local_core_errors_js_1.LocalCoreError('channel_auth_failed', status.lastError, {
802
+ userMessage: 'WeChat is not connected.',
803
+ suggestedAction: 'Scan the WeChat QR code to finish login.',
804
+ }).info;
805
+ status.lastErrorAt = new Date().toISOString();
778
806
  this.notifyRuntimeStateChanged();
779
807
  return;
780
808
  }
781
809
  status.status = 'running';
782
810
  status.connected = true;
783
811
  status.connectedAt = new Date().toISOString();
784
- status.lastError = undefined;
812
+ this.clearRuntimeError(status);
785
813
  // Start long-poll loop in background
786
814
  this.runMonitorLoop(binding, abortController.signal).catch((err) => {
787
815
  if (!abortController.signal.aborted) {
788
- this.options.log?.(`localcore-weixin monitor terminated for ${binding.workspaceId}: ${formatError(err)}`);
789
816
  status.status = 'error';
790
817
  status.connected = false;
791
- status.lastError = formatError(err);
818
+ this.setRuntimeError(status, err, 'internal_error', {
819
+ workspaceId: binding.workspaceId,
820
+ instanceId: binding.instanceId,
821
+ runtimeId: 'weixin',
822
+ });
792
823
  this.notifyRuntimeStateChanged();
793
824
  }
794
825
  });
@@ -796,8 +827,11 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
796
827
  catch (error) {
797
828
  status.status = 'error';
798
829
  status.connected = false;
799
- status.lastError = formatError(error);
800
- this.options.log?.(`localcore-weixin start failed for ${binding.workspaceId}: ${status.lastError}`);
830
+ this.setRuntimeError(status, error, 'internal_error', {
831
+ workspaceId: binding.workspaceId,
832
+ instanceId: binding.instanceId,
833
+ runtimeId: 'weixin',
834
+ });
801
835
  }
802
836
  this.notifyRuntimeStateChanged();
803
837
  }
@@ -845,27 +879,47 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
845
879
  const isApiError = (resp.ret !== undefined && resp.ret !== 0) || (resp.errcode !== undefined && resp.errcode !== 0);
846
880
  if (isApiError) {
847
881
  consecutiveFailures++;
848
- const errorText = resp.errmsg ? ` errmsg=${resp.errmsg}` : '';
849
- this.options.log?.(`localcore-weixin getUpdates failed for ${binding.workspaceId}: ret=${resp.ret} errcode=${resp.errcode}${errorText} (${consecutiveFailures}/${MAX_CONSECUTIVE_FAILURES})`);
882
+ const state = this.runtime.get((0, config_js_1.runtimeKey)(binding.workspaceId, binding.instanceId));
883
+ const retryDelayMs = this.computeRetryDelay(consecutiveFailures);
850
884
  if (resp.errcode === -14 || resp.ret === -14) {
851
- const state = this.runtime.get((0, config_js_1.runtimeKey)(binding.workspaceId, binding.instanceId));
852
885
  if (state) {
853
886
  state.status = 'error';
854
887
  state.connected = false;
855
- state.lastError = 'WeChat login expired. Generate and scan a new QR code.';
888
+ state.consecutiveFailures = consecutiveFailures;
889
+ state.nextRetryAt = new Date(Date.now() + retryDelayMs).toISOString();
890
+ this.setRuntimeError(state, new local_core_errors_js_1.LocalCoreError('channel_session_expired', 'WeChat login expired. Generate and scan a new QR code.', {
891
+ suggestedAction: 'Generate and scan a new WeChat QR code.',
892
+ details: {
893
+ errcode: resp.errcode ?? resp.ret ?? -14,
894
+ },
895
+ }), 'channel_session_expired', {
896
+ workspaceId: binding.workspaceId,
897
+ instanceId: binding.instanceId,
898
+ runtimeId: 'weixin',
899
+ errcode: resp.errcode ?? resp.ret ?? -14,
900
+ });
856
901
  this.notifyRuntimeStateChanged();
857
902
  }
858
903
  }
859
- if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
860
- consecutiveFailures = 0;
861
- await sleep(BACKOFF_DELAY_MS, signal);
904
+ this.logPollError(binding, `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})`);
905
+ if (state && resp.errcode !== -14 && resp.ret !== -14) {
906
+ state.consecutiveFailures = consecutiveFailures;
907
+ state.nextRetryAt = new Date(Date.now() + retryDelayMs).toISOString();
862
908
  }
863
- else {
864
- await sleep(RETRY_DELAY_MS, signal);
909
+ await sleep(retryDelayMs, signal);
910
+ if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
911
+ consecutiveFailures = MAX_CONSECUTIVE_FAILURES;
865
912
  }
866
913
  continue;
867
914
  }
868
915
  consecutiveFailures = 0;
916
+ const state = this.runtime.get((0, config_js_1.runtimeKey)(binding.workspaceId, binding.instanceId));
917
+ if (state) {
918
+ this.clearRuntimeError(state);
919
+ state.status = 'running';
920
+ state.connected = true;
921
+ this.notifyRuntimeStateChanged();
922
+ }
869
923
  if (resp.get_updates_buf) {
870
924
  buf = resp.get_updates_buf;
871
925
  (0, config_js_1.saveWeixinBuf)(binding, buf);
@@ -927,14 +981,20 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
927
981
  if (signal.aborted)
928
982
  return;
929
983
  consecutiveFailures++;
930
- this.options.log?.(`localcore-weixin getUpdates error for ${binding.workspaceId} (${consecutiveFailures}/${MAX_CONSECUTIVE_FAILURES}): ${formatError(err)}`);
931
- if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
932
- consecutiveFailures = 0;
933
- await sleep(BACKOFF_DELAY_MS, signal);
934
- }
935
- else {
936
- await sleep(RETRY_DELAY_MS, signal);
984
+ const retryDelayMs = this.computeRetryDelay(consecutiveFailures);
985
+ const state = this.runtime.get((0, config_js_1.runtimeKey)(binding.workspaceId, binding.instanceId));
986
+ if (state) {
987
+ state.consecutiveFailures = consecutiveFailures;
988
+ state.nextRetryAt = new Date(Date.now() + retryDelayMs).toISOString();
989
+ this.setRuntimeError(state, err, 'internal_error', {
990
+ workspaceId: binding.workspaceId,
991
+ instanceId: binding.instanceId,
992
+ runtimeId: 'weixin',
993
+ });
994
+ this.notifyRuntimeStateChanged();
937
995
  }
996
+ this.logPollError(binding, formatError(err), `localcore-weixin getUpdates error for ${binding.workspaceId} (${consecutiveFailures}): ${formatError(err)}`);
997
+ await sleep(retryDelayMs, signal);
938
998
  }
939
999
  }
940
1000
  }
@@ -1273,6 +1333,50 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
1273
1333
  payload: { reason: 'channel-bindings' },
1274
1334
  });
1275
1335
  }
1336
+ clearRuntimeError(state) {
1337
+ state.lastError = undefined;
1338
+ state.lastErrorInfo = undefined;
1339
+ state.lastErrorAt = undefined;
1340
+ state.consecutiveFailures = 0;
1341
+ state.nextRetryAt = undefined;
1342
+ }
1343
+ setRuntimeError(state, error, fallbackCode, context) {
1344
+ const errorInfo = (0, local_core_errors_js_1.toLocalCoreErrorInfo)(error, fallbackCode, context);
1345
+ state.lastError = errorInfo.message;
1346
+ state.lastErrorInfo = errorInfo;
1347
+ state.lastErrorAt = new Date().toISOString();
1348
+ this.options.eventBus.emit({
1349
+ type: 'localcore.error',
1350
+ payload: {
1351
+ scope: 'channel.weixin',
1352
+ errorInfo,
1353
+ context,
1354
+ },
1355
+ });
1356
+ }
1357
+ computeRetryDelay(failures) {
1358
+ if (failures <= 1)
1359
+ return RETRY_DELAY_MS;
1360
+ if (failures === 2)
1361
+ return 5_000;
1362
+ if (failures === 3)
1363
+ return 15_000;
1364
+ if (failures === 4)
1365
+ return 30_000;
1366
+ return 60_000;
1367
+ }
1368
+ logPollError(binding, errorKey, message) {
1369
+ const key = (0, config_js_1.runtimeKey)(binding.workspaceId, binding.instanceId);
1370
+ const current = this.pollErrorLogWindows.get(key);
1371
+ const now = Date.now();
1372
+ if (!current || current.errorKey !== errorKey || now - current.at >= ERROR_LOG_WINDOW_MS) {
1373
+ this.pollErrorLogWindows.set(key, { at: now, count: 1, errorKey });
1374
+ this.options.log?.(message);
1375
+ return;
1376
+ }
1377
+ current.count += 1;
1378
+ this.pollErrorLogWindows.set(key, current);
1379
+ }
1276
1380
  }
1277
1381
  exports.LocalCoreWeixinGateway = LocalCoreWeixinGateway;
1278
1382
  function getWeixinInstanceId(platform) {
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OpenSandboxExecutionBackend = exports.LocalAgentExecutionBackend = void 0;
4
+ exports.prepareAgentExecutionLaunch = prepareAgentExecutionLaunch;
5
+ const sandbox_config_js_1 = require("../sandbox/sandbox-config.js");
6
+ class LocalAgentExecutionBackend {
7
+ mode = 'local';
8
+ prepareLaunch(input) {
9
+ return {
10
+ ...input.launchConfig,
11
+ execution: {
12
+ mode: 'local',
13
+ transport: 'stdio',
14
+ },
15
+ };
16
+ }
17
+ }
18
+ exports.LocalAgentExecutionBackend = LocalAgentExecutionBackend;
19
+ class OpenSandboxExecutionBackend {
20
+ mode = 'sandbox';
21
+ prepareLaunch(input) {
22
+ const sandbox = (0, sandbox_config_js_1.normalizeSandboxLaunchConfig)(input);
23
+ if (!sandbox) {
24
+ return new LocalAgentExecutionBackend().prepareLaunch(input);
25
+ }
26
+ return {
27
+ ...input.launchConfig,
28
+ command: process.execPath,
29
+ args: [(0, sandbox_config_js_1.sandboxProxyScriptPath)()],
30
+ env: {
31
+ ...(0, sandbox_config_js_1.sandboxProxyLaunchEnv)(sandbox),
32
+ AGENTDOCK_SANDBOX_AGENT_TYPE: input.launchConfig.agentType,
33
+ },
34
+ execution: {
35
+ mode: 'sandbox',
36
+ transport: `sandbox-${sandbox.transport}-stdio-proxy`,
37
+ provider: sandbox.provider,
38
+ sandbox: {
39
+ image: sandbox.image,
40
+ transport: sandbox.transport,
41
+ acpPort: sandbox.acpPort,
42
+ stateScope: sandbox.stateScope,
43
+ stateMountPath: sandbox.stateMountPath,
44
+ },
45
+ },
46
+ sandbox,
47
+ };
48
+ }
49
+ }
50
+ exports.OpenSandboxExecutionBackend = OpenSandboxExecutionBackend;
51
+ function prepareAgentExecutionLaunch(input) {
52
+ const backend = (0, sandbox_config_js_1.isProjectSandboxEnabled)(input.project)
53
+ ? new OpenSandboxExecutionBackend()
54
+ : new LocalAgentExecutionBackend();
55
+ return backend.prepareLaunch(input);
56
+ }
@@ -8,16 +8,7 @@ const diagnostics_js_1 = require("./diagnostics.js");
8
8
  const event_bus_js_1 = require("./event-bus.js");
9
9
  const lifecycle_manager_js_1 = require("./lifecycle-manager.js");
10
10
  const plugin_registry_js_1 = require("./plugin-registry.js");
11
- const index_js_1 = require("../agents/index.js");
12
- const channel_lark_plugin_js_1 = require("../plugins/builtin/channel-lark-plugin.js");
13
- const channel_weixin_plugin_js_1 = require("../plugins/builtin/channel-weixin-plugin.js");
14
- const knowledge_ai_vector_plugin_js_1 = require("../plugins/builtin/knowledge-ai-vector-plugin.js");
15
- const knowledge_noop_plugin_js_1 = require("../plugins/builtin/knowledge-noop-plugin.js");
16
- const scheduler_cron_plugin_js_1 = require("../plugins/builtin/scheduler-cron-plugin.js");
17
- const scheduler_lark_plugin_js_1 = require("../plugins/builtin/scheduler-lark-plugin.js");
18
- const scheduler_local_plugin_js_1 = require("../plugins/builtin/scheduler-local-plugin.js");
19
- const scheduler_weixin_plugin_js_1 = require("../plugins/builtin/scheduler-weixin-plugin.js");
20
- const monitor_stock_plugin_js_1 = require("../plugins/builtin/monitor-stock-plugin.js");
11
+ const catalog_js_1 = require("../plugins/builtin/catalog.js");
21
12
  const workspace_router_js_1 = require("../router/workspace-router.js");
22
13
  const local_core_runtime_state_js_1 = require("../runtime/local-core-runtime-state.js");
23
14
  const scheduled_job_application_service_js_1 = require("../scheduler/scheduled-job-application-service.js");
@@ -37,12 +28,7 @@ function bootstrapLocalCoreKernel(options) {
37
28
  };
38
29
  const lifecycle = new lifecycle_manager_js_1.LocalCoreLifecycleManager(plugins, context);
39
30
  const diagnostics = new diagnostics_js_1.LocalCoreDiagnostics(plugins, lifecycle);
40
- const builtIns = [
41
- ...(0, index_js_1.getStaticAgentRuntimeDefinitions)().map((definition) => (0, index_js_1.createBuiltinStaticAgentCapabilityPlugin)(definition.agentType, definition.displayName)),
42
- (0, index_js_1.createBuiltinLocalCoreAcpAgentPlugin)(),
43
- (0, scheduler_cron_plugin_js_1.createBuiltinCronSchedulerPlugin)(),
44
- ];
45
- for (const plugin of builtIns) {
31
+ for (const plugin of (0, catalog_js_1.createKernelBuiltinPlugins)()) {
46
32
  plugins.register(plugin);
47
33
  options?.log?.(`[plugin:${plugin.manifest.id}] registered`);
48
34
  if (plugin.capabilities && plugins.isEnabled(plugin.manifest.id)) {
@@ -184,56 +170,31 @@ function bootstrapLocalCoreRuntime(options) {
184
170
  if (!localCoreAgentPlugin) {
185
171
  throw new Error('Missing built-in LocalCore ACP agent plugin.');
186
172
  }
187
- const agentPlugins = [
188
- localCoreAgentPlugin,
189
- (0, index_js_1.createBuiltinPiAgentPlugin)(),
190
- (0, index_js_1.createBuiltinOpencodeAgentPlugin)(),
191
- (0, index_js_1.createBuiltinCodexAgentPlugin)(),
192
- (0, index_js_1.createBuiltinClaudeCodeAgentPlugin)(),
193
- (0, index_js_1.createBuiltinHermesAgentPlugin)(),
194
- ];
173
+ const agentPlugins = (0, catalog_js_1.createRuntimeAgentPlugins)(localCoreAgentPlugin);
195
174
  let workspaceRouter;
196
175
  let weixinChannelRuntime;
197
- const channelPlugin = (0, channel_lark_plugin_js_1.createBuiltinLarkChannelPlugin)({
176
+ const channelPlugins = (0, catalog_js_1.createRuntimeChannelPlugins)({
198
177
  store,
199
178
  readConfig: async () => (await state.readConfigFile()).parsed,
200
179
  getWorkspaceRouter: () => workspaceRouter,
201
180
  log: options.log,
202
181
  });
203
- const weixinChannelPlugin = (0, channel_weixin_plugin_js_1.createBuiltinWeixinChannelPlugin)({
182
+ const channelPlugin = channelPlugins.lark;
183
+ const weixinChannelPlugin = channelPlugins.weixin;
184
+ const knowledgePlugin = (0, catalog_js_1.createRuntimeKnowledgePlugin)({
185
+ enableKnowledge: options.enableKnowledge,
186
+ userDataPath: options.userDataPath,
187
+ getConfig: () => state.getKnowledgeConfig(),
188
+ setConfig: (input) => state.updateKnowledgeConfig(input),
189
+ });
190
+ const schedulerPlugins = (0, catalog_js_1.createRuntimeSchedulerPlugins)({
204
191
  store,
205
- readConfig: async () => (await state.readConfigFile()).parsed,
206
192
  getWorkspaceRouter: () => workspaceRouter,
193
+ getLarkChannelRuntime: () => channelRuntime,
194
+ getWeixinChannelRuntime: () => weixinChannelRuntime,
207
195
  log: options.log,
208
196
  });
209
- const knowledgePlugin = options.enableKnowledge === false
210
- ? (0, knowledge_noop_plugin_js_1.createBuiltinNoopKnowledgePlugin)()
211
- : (0, knowledge_ai_vector_plugin_js_1.createBuiltinAiVectorKnowledgePlugin)({
212
- userDataPath: options.userDataPath,
213
- getConfig: () => state.getKnowledgeConfig(),
214
- setConfig: (input) => state.updateKnowledgeConfig(input),
215
- });
216
- const schedulerPlugins = [
217
- (0, scheduler_local_plugin_js_1.createBuiltinLocalSchedulerPlugin)({
218
- store,
219
- getWorkspaceRouter: () => workspaceRouter,
220
- }),
221
- (0, scheduler_lark_plugin_js_1.createBuiltinLarkSchedulerPlugin)({
222
- store,
223
- getWorkspaceRouter: () => workspaceRouter,
224
- getChannelRuntime: () => channelRuntime,
225
- log: options.log,
226
- }),
227
- (0, scheduler_weixin_plugin_js_1.createBuiltinWeixinSchedulerPlugin)({
228
- store,
229
- getWorkspaceRouter: () => workspaceRouter,
230
- getChannelRuntime: () => weixinChannelRuntime,
231
- log: options.log,
232
- }),
233
- ];
234
- const monitorPlugins = [
235
- (0, monitor_stock_plugin_js_1.createBuiltinStockMonitorPlugin)(),
236
- ];
197
+ const monitorPlugins = (0, catalog_js_1.createRuntimeMonitorPlugins)();
237
198
  for (const plugin of agentPlugins.filter((plugin) => plugin !== localCoreAgentPlugin)) {
238
199
  registerPlugin(kernel, plugin);
239
200
  }
@@ -257,8 +218,8 @@ function bootstrapLocalCoreRuntime(options) {
257
218
  ];
258
219
  const knowledgeRuntime = kernel.plugins.isEnabled(knowledgePlugin.manifest.id)
259
220
  ? resolveKnowledgeRuntime(knowledgePlugin, kernel.context)
260
- : resolveKnowledgeRuntime((0, knowledge_noop_plugin_js_1.createBuiltinNoopKnowledgePlugin)(), kernel.context);
261
- const cronSchedulerPlugin = (0, scheduler_cron_plugin_js_1.createBuiltinCronSchedulerPlugin)();
221
+ : resolveKnowledgeRuntime((0, catalog_js_1.createBuiltinNoopKnowledgePlugin)(), kernel.context);
222
+ const cronSchedulerPlugin = (0, catalog_js_1.createBuiltinCronSchedulerPlugin)();
262
223
  const schedulerRuntimes = [
263
224
  ...(kernel.plugins.isEnabled(cronSchedulerPlugin.manifest.id)
264
225
  ? [resolveSchedulerRuntime(cronSchedulerPlugin, kernel.context)]