@kafca/agentdock 0.1.44 → 0.1.46

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 (126) hide show
  1. package/README.md +76 -11
  2. package/bin/agentdock.mjs +5 -5
  3. package/dist/renderer/assets/{Badge-Qk9qHovH.js → Badge-BIesaDYG.js} +1 -1
  4. package/dist/renderer/assets/Chat-CpataoDh.js +2 -0
  5. package/dist/renderer/assets/{ChatMarkdown-BKdW8OON.js → ChatMarkdown-_Mdmltgv.js} +1 -1
  6. package/dist/renderer/assets/Config-Pe5-zKZk.js +21 -0
  7. package/dist/renderer/assets/CronList-BnaOSPT8.js +1 -0
  8. package/dist/renderer/assets/Dashboard-D05l8GKE.js +26 -0
  9. package/dist/renderer/assets/{EmptyState-kD9yAwtw.js → EmptyState-BDBavDll.js} +1 -1
  10. package/dist/renderer/assets/{KnowledgeDetail-BAMCLrjz.js → KnowledgeDetail-DvR798l_.js} +2 -2
  11. package/dist/renderer/assets/KnowledgeHome-r2ZuvU8-.js +11 -0
  12. package/dist/renderer/assets/Logs-BaljtmAV.js +1 -0
  13. package/dist/renderer/assets/{Modal-DwY4lecS.js → Modal-CXhD_OWR.js} +1 -1
  14. package/dist/renderer/assets/MonitorList-D7tyipbx.js +1 -0
  15. package/dist/renderer/assets/{Page-CnB9ePsb.js → Page-KUuFYgjg.js} +1 -1
  16. package/dist/renderer/assets/ProjectDetail-Ddq94-yu.js +11 -0
  17. package/dist/renderer/assets/ProjectList-CbdHd5Ev.js +1 -0
  18. package/dist/renderer/assets/{Select-zfoksLGB.js → Select-Djc8BXMC.js} +1 -1
  19. package/dist/renderer/assets/SessionChat-DOy0iKQR.js +1 -0
  20. package/dist/renderer/assets/SessionList-DHgl1s1D.js +1 -0
  21. package/dist/renderer/assets/ThreadChat-I7dYibDc.js +23 -0
  22. package/dist/renderer/assets/Workspace-DTocqY-F.js +19 -0
  23. package/dist/renderer/assets/{arrow-left-CNEAuElg.js → arrow-left-CXyya3hP.js} +1 -1
  24. package/dist/renderer/assets/{book-open-BNJMhNI-.js → book-open-9n4Kxc7E.js} +1 -1
  25. package/dist/renderer/assets/bot-C9HBk5XH.js +6 -0
  26. package/dist/renderer/assets/{check-BnclClRU.js → check-CutSg9a5.js} +1 -1
  27. package/dist/renderer/assets/{chevron-down-Bh53e0O-.js → chevron-down-DrydR4i3.js} +1 -1
  28. package/dist/renderer/assets/{circle-ClZTWCWO.js → circle-BEjtahw6.js} +1 -1
  29. package/dist/renderer/assets/desktop-DATgk_ka.js +1 -0
  30. package/dist/renderer/assets/{desktop-C6q6wBae.js → desktop-JQkhNOF4.js} +5 -5
  31. package/dist/renderer/assets/en-CmAr_0e6.js +1 -0
  32. package/dist/renderer/assets/es-Cs9x52ca.js +1 -0
  33. package/dist/renderer/assets/{funnel-_5hsz0xI.js → funnel-BhqZpS4f.js} +1 -1
  34. package/dist/renderer/assets/{heart-u4Q1aOqj.js → heart-Dp8Vs-7_.js} +1 -1
  35. package/dist/renderer/assets/{index-BNFx4uYv.js → index-BKpv0P0s.js} +2 -2
  36. package/dist/renderer/assets/index-CO4fGqmv.css +11 -0
  37. package/dist/renderer/assets/{index-B36eowj-.js → index-cI3pWBnN.js} +36 -36
  38. package/dist/renderer/assets/ja-DtvtBRTW.js +1 -0
  39. package/dist/renderer/assets/{pencil-DLh9QNmT.js → pencil-ywcJzeOo.js} +1 -1
  40. package/dist/renderer/assets/{play-BDTk9Scm.js → play-AtN492Cx.js} +1 -1
  41. package/dist/renderer/assets/{plus-BSc8POsz.js → plus-BEj14BBV.js} +1 -1
  42. package/dist/renderer/assets/projects-Clar8lgb.js +1 -0
  43. package/dist/renderer/assets/save-D6ov4CNv.js +11 -0
  44. package/dist/renderer/assets/{search-CniPk7Ey.js → search-C3bvw7AR.js} +1 -1
  45. package/dist/renderer/assets/{server-GsXyQAZm.js → server-C1Uyedyx.js} +1 -1
  46. package/dist/renderer/assets/{session-utils-BDxzgTBC.js → session-utils-DpRwJ6Nh.js} +1 -1
  47. package/dist/renderer/assets/{sessions-CLcKA1Tt.js → sessions-BWmAppwK.js} +1 -1
  48. package/dist/renderer/assets/{shield-check-4i0E3hmf.js → shield-check-CVx1mEs2.js} +1 -1
  49. package/dist/renderer/assets/{trash-2-DhtOCsO5.js → trash-2-o-heXOgs.js} +1 -1
  50. package/dist/renderer/assets/user-dPOzUqIc.js +6 -0
  51. package/dist/renderer/assets/{wifi-off-BHPzPY_B.js → wifi-off-Fz5c3_x_.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/inbound.js +55 -1
  67. package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +65 -10
  68. package/dist-electron/services/local-ai-core/src/channel/shared/session-command-runtime.js +4 -2
  69. package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +139 -29
  70. package/dist-electron/services/local-ai-core/src/execution/agent-execution-backend.js +56 -0
  71. package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +18 -57
  72. package/dist-electron/services/local-ai-core/src/kernel/local-core-errors.js +255 -0
  73. package/dist-electron/services/local-ai-core/src/plugins/builtin/catalog.js +78 -0
  74. package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +3 -1
  75. package/dist-electron/services/local-ai-core/src/router/workspace-router.js +64 -9
  76. package/dist-electron/services/local-ai-core/src/runtime/agent-runtime-detector.js +5 -2
  77. package/dist-electron/services/local-ai-core/src/runtime/config-migration.js +152 -0
  78. package/dist-electron/services/local-ai-core/src/runtime/deployment-diagnostics.js +175 -0
  79. package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +330 -3
  80. package/dist-electron/services/local-ai-core/src/runtime/local-core-runtime-state.js +11 -2
  81. package/dist-electron/services/local-ai-core/src/runtime/provider-config-migration.js +32 -0
  82. package/dist-electron/services/local-ai-core/src/runtime/runtime-detection-service.js +76 -8
  83. package/dist-electron/services/local-ai-core/src/runtime/server-routes.js +62 -0
  84. package/dist-electron/services/local-ai-core/src/runtime/server.js +708 -4
  85. package/dist-electron/services/local-ai-core/src/runtime/standalone.js +13 -3
  86. package/dist-electron/services/local-ai-core/src/sandbox/opensandbox-client.js +113 -0
  87. package/dist-electron/services/local-ai-core/src/sandbox/sandbox-config.js +273 -0
  88. package/dist-electron/services/local-ai-core/src/sandbox/sandbox-manager.js +215 -0
  89. package/dist-electron/services/local-ai-core/src/sandbox/sandbox-stdio-proxy.js +188 -0
  90. package/dist-electron/services/local-ai-core/src/thread/slash-command-registry.js +3 -0
  91. package/dist-electron/services/local-ai-core/src/thread/thread-command-service.js +32 -0
  92. package/dist-electron/services/local-ai-core/src/thread/thread-slash-command-dispatcher.js +71 -0
  93. package/dist-electron/shared/desktop.js +85 -1
  94. package/dist-electron/tests/contracts/architecture-docs.test.js +83 -0
  95. package/dist-electron/tests/electron/plugin-kernel.test.js +225 -18
  96. package/dist-electron/tests/electron/runtime-detection-service.test.js +57 -5
  97. package/dist-electron/tests/electron/sandbox-config.test.js +541 -0
  98. package/dist-electron/tests/electron/workspace-task-store.test.js +257 -0
  99. package/dist-electron/tests/integration/lark-gateway.test.js +139 -0
  100. package/dist-electron/tests/integration/local-core-refactor.test.js +183 -20
  101. package/dist-electron/tests/integration/local-core-routes.test.js +34 -0
  102. package/package.json +2 -3
  103. package/dist/renderer/assets/Chat-BK-fm0Xr.js +0 -2
  104. package/dist/renderer/assets/Config-B93CQGvY.js +0 -16
  105. package/dist/renderer/assets/CronList-Z3TvSRKP.js +0 -1
  106. package/dist/renderer/assets/Dashboard-Ch3QkWwf.js +0 -26
  107. package/dist/renderer/assets/KnowledgeHome-ChvjOfrc.js +0 -11
  108. package/dist/renderer/assets/Logs-Cv0nth3j.js +0 -1
  109. package/dist/renderer/assets/MonitorList-JEvMoWUm.js +0 -1
  110. package/dist/renderer/assets/ProjectDetail-DJa3sMmU.js +0 -11
  111. package/dist/renderer/assets/ProjectList-D6CXumR_.js +0 -1
  112. package/dist/renderer/assets/SessionChat-DUTh4WoM.js +0 -1
  113. package/dist/renderer/assets/SessionList-D9o-lUst.js +0 -1
  114. package/dist/renderer/assets/ThreadChat-BYXlT-Kc.js +0 -23
  115. package/dist/renderer/assets/Workspace-BrhSwRQ-.js +0 -14
  116. package/dist/renderer/assets/desktop-C5vBT0yM.js +0 -1
  117. package/dist/renderer/assets/en-D2SkCrhG.js +0 -1
  118. package/dist/renderer/assets/es-C8UBPhxM.js +0 -1
  119. package/dist/renderer/assets/index-CaQZSRbg.css +0 -11
  120. package/dist/renderer/assets/ja-ChF4vbBL.js +0 -1
  121. package/dist/renderer/assets/plug-BG0JHW6B.js +0 -6
  122. package/dist/renderer/assets/projects-DwfZwxDW.js +0 -1
  123. package/dist/renderer/assets/save-D5AO_G6a.js +0 -6
  124. package/dist/renderer/assets/user-BtC_pVXV.js +0 -11
  125. package/dist/renderer/assets/zh-DIcdHycM.js +0 -1
  126. package/dist/renderer/assets/zh-TW-BtRwreY_.js +0 -1
@@ -11,11 +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
18
  const thread_routing_js_1 = require("../shared/thread-routing.js");
18
- const session_command_service_js_1 = require("../../thread/session-command-service.js");
19
+ const thread_slash_command_dispatcher_js_1 = require("../../thread/thread-slash-command-dispatcher.js");
19
20
  const config_js_1 = require("./config.js");
20
21
  const transport_js_1 = require("./transport.js");
21
22
  // ==================== Constants ====================
@@ -31,6 +32,7 @@ const WEIXIN_RESERVED_TERMINAL_SENDS = 1;
31
32
  const WEIXIN_PROGRESS_SEND_BUDGET = WEIXIN_CONTEXT_SEND_LIMIT - WEIXIN_RESERVED_TERMINAL_SENDS;
32
33
  const RESPONSE_TIMEOUT_MS = 5 * 60 * 1000;
33
34
  const WEIXIN_MAX_UPLOAD_FILE_SIZE = 30 * 1024 * 1024;
35
+ const ERROR_LOG_WINDOW_MS = 5 * 60 * 1000;
34
36
  // ==================== Utilities ====================
35
37
  function stripHtml(html) {
36
38
  let result = html;
@@ -153,21 +155,36 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
153
155
  outboundTurns = new Map();
154
156
  processedInboundMessages = new Map();
155
157
  mutedThreadBridgeCounts = new Map();
158
+ pollErrorLogWindows = new Map();
156
159
  sessionCommandRuntime;
157
160
  platform = 'weixin';
158
161
  routeType = 'channel.chat';
159
162
  constructor(options) {
160
163
  super();
161
164
  this.options = options;
162
- const sessionCommandService = new session_command_service_js_1.SessionCommandService({
163
- listThreads: (workspaceId) => this.options.getWorkspaceRouter().listThreads(workspaceId),
164
- getThread: (threadId) => this.options.getWorkspaceRouter().getThread(threadId),
165
- createThread: (workspaceId, title) => this.options.getWorkspaceRouter().createThread(workspaceId, title),
166
- renameThread: (threadId, title) => this.options.getWorkspaceRouter().renameThread(threadId, title),
167
- 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
+ },
168
185
  });
169
186
  this.sessionCommandRuntime = new session_command_runtime_js_1.ChannelSessionCommandRuntime({
170
- service: sessionCommandService,
187
+ dispatcher: slashCommands,
171
188
  store: this.options.store,
172
189
  getThreadSessionKey: (threadId) => this.options.getWorkspaceRouter().getThreadSessionKey(threadId),
173
190
  setThreadRoute: (sessionKey, route) => {
@@ -260,6 +277,10 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
260
277
  status: binding?.status || 'disabled',
261
278
  appId: binding?.accountId || '',
262
279
  lastError: binding?.lastError,
280
+ lastErrorInfo: binding?.lastErrorInfo,
281
+ lastErrorAt: binding?.lastErrorAt,
282
+ consecutiveFailures: binding?.consecutiveFailures,
283
+ nextRetryAt: binding?.nextRetryAt,
263
284
  connectedAt: binding?.connectedAt,
264
285
  pendingPairings: pairings.length,
265
286
  authorizedUsers: users.length,
@@ -690,6 +711,7 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
690
711
  currentThreadId: threadId,
691
712
  text: input.text,
692
713
  defaultTitle: `${input.displayName || 'WeChat'} ${new Date().toLocaleTimeString()}`,
714
+ defaultAgentType: slashCommand ? await this.resolveDefaultAgentType(input.workspaceId, threadId) : '',
693
715
  chatId: input.chatId,
694
716
  platformUserId: input.platformUserId,
695
717
  platformKey,
@@ -723,6 +745,13 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
723
745
  }
724
746
  await this.sendTextMessage(state, input.chatId, result.displayText, input.contextToken);
725
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
+ }
726
755
  // ==================== Private: Bindings ====================
727
756
  resolveRuntimeState(workspaceId, instanceId) {
728
757
  if (instanceId) {
@@ -769,20 +798,28 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
769
798
  status.status = 'stopped';
770
799
  status.connected = false;
771
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();
772
806
  this.notifyRuntimeStateChanged();
773
807
  return;
774
808
  }
775
809
  status.status = 'running';
776
810
  status.connected = true;
777
811
  status.connectedAt = new Date().toISOString();
778
- status.lastError = undefined;
812
+ this.clearRuntimeError(status);
779
813
  // Start long-poll loop in background
780
814
  this.runMonitorLoop(binding, abortController.signal).catch((err) => {
781
815
  if (!abortController.signal.aborted) {
782
- this.options.log?.(`localcore-weixin monitor terminated for ${binding.workspaceId}: ${formatError(err)}`);
783
816
  status.status = 'error';
784
817
  status.connected = false;
785
- status.lastError = formatError(err);
818
+ this.setRuntimeError(status, err, 'internal_error', {
819
+ workspaceId: binding.workspaceId,
820
+ instanceId: binding.instanceId,
821
+ runtimeId: 'weixin',
822
+ });
786
823
  this.notifyRuntimeStateChanged();
787
824
  }
788
825
  });
@@ -790,8 +827,11 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
790
827
  catch (error) {
791
828
  status.status = 'error';
792
829
  status.connected = false;
793
- status.lastError = formatError(error);
794
- 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
+ });
795
835
  }
796
836
  this.notifyRuntimeStateChanged();
797
837
  }
@@ -839,27 +879,47 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
839
879
  const isApiError = (resp.ret !== undefined && resp.ret !== 0) || (resp.errcode !== undefined && resp.errcode !== 0);
840
880
  if (isApiError) {
841
881
  consecutiveFailures++;
842
- const errorText = resp.errmsg ? ` errmsg=${resp.errmsg}` : '';
843
- 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);
844
884
  if (resp.errcode === -14 || resp.ret === -14) {
845
- const state = this.runtime.get((0, config_js_1.runtimeKey)(binding.workspaceId, binding.instanceId));
846
885
  if (state) {
847
886
  state.status = 'error';
848
887
  state.connected = false;
849
- 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
+ });
850
901
  this.notifyRuntimeStateChanged();
851
902
  }
852
903
  }
853
- if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
854
- consecutiveFailures = 0;
855
- 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();
856
908
  }
857
- else {
858
- await sleep(RETRY_DELAY_MS, signal);
909
+ await sleep(retryDelayMs, signal);
910
+ if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
911
+ consecutiveFailures = MAX_CONSECUTIVE_FAILURES;
859
912
  }
860
913
  continue;
861
914
  }
862
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
+ }
863
923
  if (resp.get_updates_buf) {
864
924
  buf = resp.get_updates_buf;
865
925
  (0, config_js_1.saveWeixinBuf)(binding, buf);
@@ -921,14 +981,20 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
921
981
  if (signal.aborted)
922
982
  return;
923
983
  consecutiveFailures++;
924
- this.options.log?.(`localcore-weixin getUpdates error for ${binding.workspaceId} (${consecutiveFailures}/${MAX_CONSECUTIVE_FAILURES}): ${formatError(err)}`);
925
- if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
926
- consecutiveFailures = 0;
927
- await sleep(BACKOFF_DELAY_MS, signal);
928
- }
929
- else {
930
- 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();
931
995
  }
996
+ this.logPollError(binding, formatError(err), `localcore-weixin getUpdates error for ${binding.workspaceId} (${consecutiveFailures}): ${formatError(err)}`);
997
+ await sleep(retryDelayMs, signal);
932
998
  }
933
999
  }
934
1000
  }
@@ -1267,6 +1333,50 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
1267
1333
  payload: { reason: 'channel-bindings' },
1268
1334
  });
1269
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
+ }
1270
1380
  }
1271
1381
  exports.LocalCoreWeixinGateway = LocalCoreWeixinGateway;
1272
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)]