@kafca/agentdock 0.1.57 → 0.1.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/renderer/assets/{Badge-CDTbmw1h.js → Badge-BfY1VaHS.js} +1 -1
  2. package/dist/renderer/assets/{Card-DayUo35w.js → Card-DWA_Tww_.js} +1 -1
  3. package/dist/renderer/assets/{Config-ByGMQuzR.js → Config-nHj3g1U5.js} +1 -1
  4. package/dist/renderer/assets/{CronList-XqHdVlgu.js → CronList-BwkA_I7v.js} +1 -1
  5. package/dist/renderer/assets/{Dashboard-CZj-oANw.js → Dashboard-D0_A7k02.js} +2 -2
  6. package/dist/renderer/assets/{EmptyState-EFMkOjZO.js → EmptyState-zatDjLj_.js} +1 -1
  7. package/dist/renderer/assets/{HighlightedMarkdown-DyvF3DHK.js → HighlightedMarkdown-CsM5n70d.js} +1 -1
  8. package/dist/renderer/assets/{Input-DxoWVc9d.js → Input-R1XdFK1K.js} +1 -1
  9. package/dist/renderer/assets/{KnowledgeDetail-CbUb2tG7.js → KnowledgeDetail-Co5sxeGd.js} +1 -1
  10. package/dist/renderer/assets/{KnowledgeHome-BWV1gz4f.js → KnowledgeHome-DwziPw5m.js} +1 -1
  11. package/dist/renderer/assets/{Logs-DqnanQTc.js → Logs-NwZUtR_G.js} +1 -1
  12. package/dist/renderer/assets/{Modal-yY7TzR0x.js → Modal-CrcIwIFL.js} +1 -1
  13. package/dist/renderer/assets/{MonitorList-CIjGQkFs.js → MonitorList-CS1uLS5A.js} +1 -1
  14. package/dist/renderer/assets/{Page-vwHNUdoj.js → Page-Dp0obeSw.js} +1 -1
  15. package/dist/renderer/assets/{Select-CmbK36pN.js → Select-6mVQaf84.js} +1 -1
  16. package/dist/renderer/assets/{ThreadChat-4OceMgM4.js → ThreadChat-BFzbn3L6.js} +3 -3
  17. package/dist/renderer/assets/{Workspace-DplPJOjJ.js → Workspace-DCmo8BMm.js} +1 -1
  18. package/dist/renderer/assets/{arrow-left-C8HfBt2K.js → arrow-left-9rjg_Hp4.js} +1 -1
  19. package/dist/renderer/assets/{book-open-BCdZWncQ.js → book-open-Bu8GCHnG.js} +1 -1
  20. package/dist/renderer/assets/{channels-hgO3cAIx.js → channels-BxVbG-6j.js} +1 -1
  21. package/dist/renderer/assets/{chevron-down-BPk77tqY.js → chevron-down-BE8uQmWM.js} +1 -1
  22. package/dist/renderer/assets/{index-BlA4xPdd.js → index-B7TeF6Es.js} +1 -1
  23. package/dist/renderer/assets/{index-wYpjqVqC.js → index-BkI9POxj.js} +2 -2
  24. package/dist/renderer/assets/{knowledge-7pl06KuH.js → knowledge-Kl19SqGS.js} +1 -1
  25. package/dist/renderer/assets/{pencil-CB1SWZ9A.js → pencil-CPB7SK1m.js} +1 -1
  26. package/dist/renderer/assets/{play-BvsoXUrM.js → play-DGAO4OCu.js} +1 -1
  27. package/dist/renderer/assets/{plus-CokBDnaL.js → plus-Bt26z-4q.js} +1 -1
  28. package/dist/renderer/assets/{save-D-w4kATO.js → save-Une7GMxT.js} +1 -1
  29. package/dist/renderer/assets/{search-Cnsn6i4Q.js → search-DE0agJjJ.js} +1 -1
  30. package/dist/renderer/assets/{shield-check-Cjja2Gh6.js → shield-check-De7xaXZh.js} +1 -1
  31. package/dist/renderer/assets/{threads-BCm6j4eI.js → threads-BnsNL5ei.js} +1 -1
  32. package/dist/renderer/assets/{trash-2-CIxz9qYY.js → trash-2-6iGF59Ac.js} +1 -1
  33. package/dist/renderer/index.html +1 -1
  34. package/dist-electron/services/local-ai-core/src/automation/automation-conversation-executor.js +6 -47
  35. package/dist-electron/services/local-ai-core/src/automation/automation-monitor-service.js +2 -5
  36. package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +6 -53
  37. package/dist-electron/services/local-ai-core/src/channel/lark/outbound-transport.js +25 -37
  38. package/dist-electron/services/local-ai-core/src/channel/lark/runtime-state.js +5 -20
  39. package/dist-electron/services/local-ai-core/src/channel/shared/base-channel-gateway.js +37 -0
  40. package/dist-electron/services/local-ai-core/src/channel/shared/bridge-event-helpers.js +23 -0
  41. package/dist-electron/services/local-ai-core/src/channel/shared/channel-keys.js +6 -0
  42. package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-poller.js +2 -2
  43. package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +6 -44
  44. package/dist-electron/services/local-ai-core/src/channel/weixin/runtime-state.js +4 -11
  45. package/dist-electron/services/local-ai-core/src/channel/weixin/text-utils.js +0 -8
  46. package/dist-electron/services/local-ai-core/src/cli/lac.js +3 -5
  47. package/dist-electron/services/local-ai-core/src/kernel/local-core-errors.js +8 -0
  48. package/dist-electron/services/local-ai-core/src/sandbox/opensandbox-client.js +3 -2
  49. package/dist-electron/services/local-ai-core/src/scheduler/base-channel-schedule-adapter.js +77 -0
  50. package/dist-electron/services/local-ai-core/src/scheduler/lark-schedule-adapter.js +13 -79
  51. package/dist-electron/services/local-ai-core/src/scheduler/local-schedule-adapter.js +2 -10
  52. package/dist-electron/services/local-ai-core/src/scheduler/run-polling.js +19 -0
  53. package/dist-electron/services/local-ai-core/src/scheduler/scheduled-conversation-executor.js +3 -37
  54. package/dist-electron/services/local-ai-core/src/scheduler/scheduled-job-route.js +20 -0
  55. package/dist-electron/services/local-ai-core/src/scheduler/scheduler-service.js +15 -28
  56. package/dist-electron/services/local-ai-core/src/scheduler/thread-resolution.js +12 -0
  57. package/dist-electron/services/local-ai-core/src/scheduler/weixin-schedule-adapter.js +13 -79
  58. package/dist-electron/tests/integration/local-core-refactor.test.js +15 -8
  59. package/package.json +1 -1
  60. package/dist-electron/services/local-ai-core/src/scheduler/lark-execution-policies.js +0 -13
  61. package/dist-electron/services/local-ai-core/src/scheduler/weixin-execution-policies.js +0 -13
@@ -1 +1 @@
1
- import{z as n,Z as l}from"./index-wYpjqVqC.js";function c(){return n("GET","/knowledge/config")}function f(){return n("GET","/knowledge/folders")}function g(e){return n("POST","/knowledge/folders",e)}function i(e,o){return n("PATCH",`/knowledge/folders/${encodeURIComponent(e)}`,o)}function w(e){return n("DELETE",`/knowledge/folders/${encodeURIComponent(e)}`)}function u(){return n("GET","/knowledge/bases")}function p(e){return n("POST","/knowledge/bases",e)}function E(e){return n("GET",`/knowledge/bases/${encodeURIComponent(e)}`)}function k(e,o){return n("PATCH",`/knowledge/bases/${encodeURIComponent(e)}`,o)}function m(e){return n("DELETE",`/knowledge/bases/${encodeURIComponent(e)}`)}function C(e){return n("GET",`/knowledge/bases/${encodeURIComponent(e)}/files`)}async function K(e,o){const s=new FormData;s.append("collection",o.collection),s.append("knowledgebase_id",e),o.folder&&s.append("folder",o.folder),o.files.forEach(a=>{s.append("files",a,a.name)});const d=await fetch(`${l}/knowledge/bases/${encodeURIComponent(e)}/files`,{method:"POST",body:s}),t=await d.json();if(!d.ok||!t.ok)throw new Error(t.error||`Local AI Core upload failed: ${d.status}`);return t.data}function T(e,o){return n("DELETE",`/knowledge/bases/${encodeURIComponent(e)}/files/${encodeURIComponent(o)}`)}function b(e,o){return n("POST",`/knowledge/bases/${encodeURIComponent(e)}/search`,o)}export{f as a,p as b,g as c,w as d,k as e,m as f,c as g,E as h,C as i,K as j,T as k,u as l,b as s,i as u};
1
+ import{z as n,Z as l}from"./index-BkI9POxj.js";function c(){return n("GET","/knowledge/config")}function f(){return n("GET","/knowledge/folders")}function g(e){return n("POST","/knowledge/folders",e)}function i(e,o){return n("PATCH",`/knowledge/folders/${encodeURIComponent(e)}`,o)}function w(e){return n("DELETE",`/knowledge/folders/${encodeURIComponent(e)}`)}function u(){return n("GET","/knowledge/bases")}function p(e){return n("POST","/knowledge/bases",e)}function E(e){return n("GET",`/knowledge/bases/${encodeURIComponent(e)}`)}function k(e,o){return n("PATCH",`/knowledge/bases/${encodeURIComponent(e)}`,o)}function m(e){return n("DELETE",`/knowledge/bases/${encodeURIComponent(e)}`)}function C(e){return n("GET",`/knowledge/bases/${encodeURIComponent(e)}/files`)}async function K(e,o){const s=new FormData;s.append("collection",o.collection),s.append("knowledgebase_id",e),o.folder&&s.append("folder",o.folder),o.files.forEach(a=>{s.append("files",a,a.name)});const d=await fetch(`${l}/knowledge/bases/${encodeURIComponent(e)}/files`,{method:"POST",body:s}),t=await d.json();if(!d.ok||!t.ok)throw new Error(t.error||`Local AI Core upload failed: ${d.status}`);return t.data}function T(e,o){return n("DELETE",`/knowledge/bases/${encodeURIComponent(e)}/files/${encodeURIComponent(o)}`)}function b(e,o){return n("POST",`/knowledge/bases/${encodeURIComponent(e)}/search`,o)}export{f as a,p as b,g as c,w as d,k as e,m as f,c as g,E as h,C as i,K as j,T as k,u as l,b as s,i as u};
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-wYpjqVqC.js";/**
1
+ import{c as a}from"./index-BkI9POxj.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as o}from"./index-wYpjqVqC.js";/**
1
+ import{c as o}from"./index-BkI9POxj.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-wYpjqVqC.js";/**
1
+ import{c as e}from"./index-BkI9POxj.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-wYpjqVqC.js";/**
1
+ import{c as a}from"./index-BkI9POxj.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c}from"./index-wYpjqVqC.js";/**
1
+ import{c}from"./index-BkI9POxj.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c}from"./index-wYpjqVqC.js";/**
1
+ import{c}from"./index-BkI9POxj.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{z as t,A as r}from"./index-wYpjqVqC.js";function s(){return t("GET","/workspaces")}function a(e){return t("GET",`/threads${r({workspace_id:e})}`)}function d(e,n){return t("POST","/threads",{workspaceId:e,title:n})}function u(e){return t("GET",`/threads/${encodeURIComponent(e)}`)}function c(e,n){return t("PATCH",`/threads/${encodeURIComponent(e)}`,{title:n})}function i(e,n){return t("PATCH",`/threads/${encodeURIComponent(e)}/knowledge-bases`,{knowledgeBaseIds:n})}function T(e,n){return t("PATCH",`/threads/${encodeURIComponent(e)}/mode`,{mode:n})}function p(e){return t("DELETE",`/threads/${encodeURIComponent(e)}`)}function h(e,n){return t("POST",`/threads/${encodeURIComponent(e)}/messages`,{content:n})}function m(e,n){return t("POST",`/threads/${encodeURIComponent(e)}/actions`,{content:n})}function f(e){return t("POST",`/runs/${encodeURIComponent(e)}/interrupt`)}export{a,i as b,d as c,h as d,p as e,u as g,f as i,s as l,c as r,m as s,T as u};
1
+ import{z as t,A as r}from"./index-BkI9POxj.js";function s(){return t("GET","/workspaces")}function a(e){return t("GET",`/threads${r({workspace_id:e})}`)}function d(e,n){return t("POST","/threads",{workspaceId:e,title:n})}function u(e){return t("GET",`/threads/${encodeURIComponent(e)}`)}function c(e,n){return t("PATCH",`/threads/${encodeURIComponent(e)}`,{title:n})}function i(e,n){return t("PATCH",`/threads/${encodeURIComponent(e)}/knowledge-bases`,{knowledgeBaseIds:n})}function T(e,n){return t("PATCH",`/threads/${encodeURIComponent(e)}/mode`,{mode:n})}function p(e){return t("DELETE",`/threads/${encodeURIComponent(e)}`)}function h(e,n){return t("POST",`/threads/${encodeURIComponent(e)}/messages`,{content:n})}function m(e,n){return t("POST",`/threads/${encodeURIComponent(e)}/actions`,{content:n})}function f(e){return t("POST",`/runs/${encodeURIComponent(e)}/interrupt`)}export{a,i as b,d as c,h as d,p as e,u as g,f as i,s as l,c as r,m as s,T as u};
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-wYpjqVqC.js";/**
1
+ import{c as e}from"./index-BkI9POxj.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -5,7 +5,7 @@
5
5
  <link rel="icon" type="image/svg+xml" href="./favicon.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>AgentDock</title>
8
- <script type="module" crossorigin src="./assets/index-wYpjqVqC.js"></script>
8
+ <script type="module" crossorigin src="./assets/index-BkI9POxj.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="./assets/index-BIKL3fTP.css">
10
10
  </head>
11
11
  <body class="bg-[#f5f5f7] dark:bg-[#151516]">
@@ -4,7 +4,8 @@ exports.AutomationConversationExecutor = void 0;
4
4
  exports.renderMonitorPrompt = renderMonitorPrompt;
5
5
  const scheduled_bridge_session_js_1 = require("../scheduler/scheduled-bridge-session.js");
6
6
  const scheduled_job_route_js_1 = require("../scheduler/scheduled-job-route.js");
7
- const TERMINAL_RUN_STATES = new Set(['completed', 'failed', 'interrupted']);
7
+ const run_polling_js_1 = require("../scheduler/run-polling.js");
8
+ const thread_resolution_js_1 = require("../scheduler/thread-resolution.js");
8
9
  const MONITOR_RUN_PERMISSION_MODE = 'bypassPermissions';
9
10
  class AutomationConversationExecutor {
10
11
  options;
@@ -36,9 +37,9 @@ class AutomationConversationExecutor {
36
37
  try {
37
38
  const sendResult = await workspaceRouter.sendThreadMessage(threadId, prompt, {
38
39
  permissionMode: MONITOR_RUN_PERMISSION_MODE,
39
- runtimeEnv: this.buildRuntimeEnv(monitor),
40
+ runtimeEnv: (0, scheduled_job_route_js_1.buildPlatformRuntimeEnv)(monitor.platform, monitor.route),
40
41
  });
41
- await this.waitForRun(sendResult.runId, timeoutMs);
42
+ await (0, run_polling_js_1.waitForRunCompletion)(this.options.store, sendResult.runId, timeoutMs, 'Monitor');
42
43
  const thread = await workspaceRouter.getThread(threadId);
43
44
  const replyText = [...thread.messages]
44
45
  .reverse()
@@ -61,10 +62,10 @@ class AutomationConversationExecutor {
61
62
  const workspaceRouter = this.options.getWorkspaceRouter();
62
63
  if (monitor.executionMode === 'same-thread') {
63
64
  const binding = this.options.store.getPlatformThreadBinding(monitor.workspaceId, monitor.route.channelId, monitor.route.participantId || '', monitor.platform);
64
- if (binding?.thread_id && await this.threadExists(binding.thread_id)) {
65
+ if (binding?.thread_id && await (0, thread_resolution_js_1.threadExists)(workspaceRouter, binding.thread_id)) {
65
66
  return binding.thread_id;
66
67
  }
67
- if (monitor.route.threadId && await this.threadExists(monitor.route.threadId)) {
68
+ if (monitor.route.threadId && await (0, thread_resolution_js_1.threadExists)(workspaceRouter, monitor.route.threadId)) {
68
69
  return monitor.route.threadId;
69
70
  }
70
71
  }
@@ -79,48 +80,6 @@ class AutomationConversationExecutor {
79
80
  const created = await workspaceRouter.createThread(monitor.workspaceId, title);
80
81
  return created.id;
81
82
  }
82
- async threadExists(threadId) {
83
- try {
84
- await this.options.getWorkspaceRouter().getThread(threadId);
85
- return true;
86
- }
87
- catch {
88
- return false;
89
- }
90
- }
91
- buildRuntimeEnv(monitor) {
92
- const basePlatform = (0, scheduled_job_route_js_1.getChannelPlatformBase)(monitor.platform);
93
- const env = {};
94
- if (basePlatform && basePlatform !== 'local') {
95
- env.LOCAL_AI_PLATFORM = basePlatform;
96
- env.LOCAL_AI_ROUTE_TYPE = (0, scheduled_job_route_js_1.routeTypeForPlatform)(monitor.platform);
97
- }
98
- const instanceId = monitor.route.instanceId || (0, scheduled_job_route_js_1.getChannelPlatformInstanceId)(monitor.platform);
99
- if (instanceId) {
100
- env.LOCAL_AI_PLATFORM_INSTANCE_ID = instanceId;
101
- }
102
- if (monitor.route.channelId) {
103
- env.LOCAL_AI_CHAT_ID = monitor.route.channelId;
104
- }
105
- if (monitor.route.participantId) {
106
- env.LOCAL_AI_PLATFORM_USER_ID = monitor.route.participantId;
107
- }
108
- return env;
109
- }
110
- async waitForRun(runId, timeoutMs) {
111
- const startedAt = Date.now();
112
- while (Date.now() - startedAt < timeoutMs) {
113
- const run = this.options.store.getRun(runId);
114
- if (run && TERMINAL_RUN_STATES.has(run.status)) {
115
- if (run.status !== 'completed') {
116
- throw new Error(`Monitor run finished with status ${run.status}`);
117
- }
118
- return run;
119
- }
120
- await new Promise((resolve) => setTimeout(resolve, 300));
121
- }
122
- throw new Error(`Timed out waiting for monitor run ${runId}`);
123
- }
124
83
  }
125
84
  exports.AutomationConversationExecutor = AutomationConversationExecutor;
126
85
  function renderMonitorPrompt(template, event, monitor) {
@@ -5,6 +5,7 @@ const scheduled_job_route_js_1 = require("../scheduler/scheduled-job-route.js");
5
5
  const condition_evaluator_js_1 = require("./condition-evaluator.js");
6
6
  const automation_conversation_executor_js_1 = require("./automation-conversation-executor.js");
7
7
  const automation_monitor_repository_js_1 = require("./automation-monitor-repository.js");
8
+ const monitor_id_js_1 = require("./monitor-id.js");
8
9
  class AutomationMonitorService {
9
10
  options;
10
11
  timer = null;
@@ -278,7 +279,7 @@ class AutomationMonitorService {
278
279
  }
279
280
  const matches = this.repository
280
281
  .list()
281
- .filter((monitor) => publicMonitorId(monitor.id) === monitorId);
282
+ .filter((monitor) => (0, monitor_id_js_1.toPublicAutomationMonitorId)(monitor.id) === monitorId);
282
283
  if (matches.length === 0) {
283
284
  return '';
284
285
  }
@@ -353,7 +354,3 @@ class AutomationMonitorService {
353
354
  }
354
355
  }
355
356
  exports.AutomationMonitorService = AutomationMonitorService;
356
- function publicMonitorId(monitorId) {
357
- const normalized = monitorId.startsWith('monitor:') ? monitorId.slice('monitor:'.length) : monitorId;
358
- return normalized.includes('-') ? normalized.split('-')[0] || normalized : normalized;
359
- }
@@ -48,6 +48,7 @@ const inbound_js_1 = require("./inbound.js");
48
48
  const inbound_handler_js_1 = require("./inbound-handler.js");
49
49
  const outbound_transport_js_1 = require("./outbound-transport.js");
50
50
  const runtime_state_js_1 = require("./runtime-state.js");
51
+ const local_core_slash_commands_js_1 = require("../../acp/local-core-slash-commands.js");
51
52
  const gateway_utils_js_1 = require("./gateway-utils.js");
52
53
  const LARK_FINAL_PATCH_INTERVAL_MS = 900;
53
54
  const LARK_PROGRESS_PATCH_INTERVAL_MS = 3000;
@@ -139,7 +140,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
139
140
  return this.sendScheduledCard(workspaceId, route.channelId, text);
140
141
  }
141
142
  registerScheduledThreadBridge(input) {
142
- const instanceId = input.route.instanceId || getLarkInstanceId(input.platform) || 'default';
143
+ const instanceId = input.route.instanceId || (0, channel_keys_js_1.extractChannelInstanceId)(input.platform, 'lark') || 'default';
143
144
  const platformKey = (0, channel_keys_js_1.channelPlatformKey)('lark', instanceId);
144
145
  const route = {
145
146
  workspaceId: input.workspaceId,
@@ -269,10 +270,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
269
270
  this.options.log?.(`localcore-lark bridge event ignored type=${event.type}`);
270
271
  return;
271
272
  }
272
- const previous = this.outboundEventChains.get(sessionKey) || Promise.resolve();
273
- const current = previous
274
- .catch(() => undefined)
275
- .then(async () => {
273
+ const current = this.scheduleOutboundChain(sessionKey, async () => {
276
274
  const binding = this.options.store.getPlatformThreadBinding(route.workspaceId, route.chatId, route.platformUserId, routePlatformKey);
277
275
  if (!binding) {
278
276
  this.options.log?.(`localcore-lark bridge binding disappeared for sessionKey=${sessionKey}`);
@@ -365,15 +363,9 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
365
363
  }
366
364
  }
367
365
  catch (error) {
368
- this.options.log?.(`localcore-lark bridge send failed for sessionKey=${sessionKey}: ${error instanceof Error ? error.message : String(error)}`);
369
- }
370
- })
371
- .finally(() => {
372
- if (this.outboundEventChains.get(sessionKey) === current) {
373
- this.outboundEventChains.delete(sessionKey);
366
+ this.options.log?.(`localcore-lark bridge send failed for sessionKey=${sessionKey}: ${(0, local_core_errors_js_1.formatSafeError)(error)}`);
374
367
  }
375
368
  });
376
- this.outboundEventChains.set(sessionKey, current);
377
369
  await current;
378
370
  }
379
371
  async handleInboundMessage(input) {
@@ -455,7 +447,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
455
447
  });
456
448
  const acknowledgement = this.createTurnState(effectiveSessionKey, msg.messageId);
457
449
  await this.addAcknowledgementReaction(msg.workspaceId, msg.messageId, acknowledgement, instanceId);
458
- const slashCommand = this.parseSlashCommand(msg.text);
450
+ const slashCommand = (0, local_core_slash_commands_js_1.parseSlashCommand)(msg.text);
459
451
  const sessionCommand = await this.executeSessionCommand({
460
452
  workspaceId: msg.workspaceId,
461
453
  currentThreadId: threadId,
@@ -712,34 +704,6 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
712
704
  generatePairingCode() {
713
705
  return String((0, node_crypto_1.randomInt)(100000, 1000000));
714
706
  }
715
- findAwaitingPermissionThreadId(workspaceId, chatId, platformUserId) {
716
- for (const [sessionKey, route] of this.threadRouting.entries()) {
717
- if (route.workspaceId !== workspaceId
718
- || route.chatId !== chatId
719
- || route.platformUserId !== platformUserId) {
720
- continue;
721
- }
722
- const turn = this.outboundTurns.get(sessionKey);
723
- if (turn?.awaitingPermission && route.threadId) {
724
- return route.threadId;
725
- }
726
- }
727
- return '';
728
- }
729
- parseSlashCommand(text) {
730
- const normalized = String(text || '').trim();
731
- if (!normalized.startsWith('/')) {
732
- return null;
733
- }
734
- const [name = '', ...args] = normalized.slice(1).split(/\s+/);
735
- if (!name) {
736
- return null;
737
- }
738
- return {
739
- name: name.trim().toLowerCase(),
740
- args,
741
- };
742
- }
743
707
  createTurnState(sessionKey, sourceMessageId) {
744
708
  const turn = (0, runtime_state_js_1.createLarkTurnState)(sessionKey, sourceMessageId);
745
709
  this.outboundTurns.set(sessionKey, turn);
@@ -805,7 +769,7 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
805
769
  if (!binding || (binding.platform !== 'lark' && !binding.platform.startsWith('lark:'))) {
806
770
  return undefined;
807
771
  }
808
- const bindingInstanceId = getLarkInstanceId(binding.platform) || instanceId || 'default';
772
+ const bindingInstanceId = (0, channel_keys_js_1.extractChannelInstanceId)(binding.platform, 'lark') || instanceId || 'default';
809
773
  return {
810
774
  workspaceId: binding.workspace_id,
811
775
  instanceId: bindingInstanceId,
@@ -815,13 +779,6 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
815
779
  threadId: binding.thread_id,
816
780
  };
817
781
  }
818
- async resolveDefaultAgentType(workspaceId, threadId) {
819
- const router = this.options.getWorkspaceRouter();
820
- if (typeof router.getWorkspaceDefaultAgentType === 'function') {
821
- return router.getWorkspaceDefaultAgentType(workspaceId);
822
- }
823
- return this.options.store.getThreadRow(threadId)?.agent_type || 'codex';
824
- }
825
782
  async markPermissionCardActionHandled(workspaceId, instanceId, rootPayload, payload, value, response, threadId) {
826
783
  const state = this.resolveRuntimeState(workspaceId, instanceId).state;
827
784
  if (!state?.client) {
@@ -904,7 +861,3 @@ class LocalCoreLarkGateway extends base_channel_gateway_js_1.BaseChannelGateway
904
861
  }
905
862
  }
906
863
  exports.LocalCoreLarkGateway = LocalCoreLarkGateway;
907
- function getLarkInstanceId(platform) {
908
- const normalized = String(platform || '').trim();
909
- return normalized.startsWith('lark:') ? normalized.slice('lark:'.length).trim() : '';
910
- }
@@ -49,56 +49,44 @@ class LarkOutboundTransport {
49
49
  return { messageId, fileKey, file };
50
50
  }
51
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();
52
+ return this.timed('card create', '', text, () => this.createMessage(state, chatId, 'interactive', (0, cards_js_1.buildInteractiveCard)(text, buttonRows, sessionKey, threadId)));
63
53
  }
64
54
  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();
55
+ return this.timed('session card create', '', text, () => this.createMessage(state, chatId, 'interactive', (0, cards_js_1.buildSessionCommandCard)(text, actionRows, sessionKey, threadId)));
76
56
  }
77
57
  async sendTextAsMessage(state, chatId, text) {
78
- const startedAt = Date.now();
79
58
  const rendered = (0, messages_js_1.renderLarkTextMessage)(text);
59
+ const messageId = await this.timed(`${rendered.renderKind} create`, `msgType=${rendered.msgType} reason=${rendered.reason} tableCount=${rendered.tableCount}`, text, () => this.createMessage(state, chatId, rendered.msgType, rendered.content));
60
+ return {
61
+ messageId,
62
+ renderKind: rendered.renderKind,
63
+ msgType: rendered.msgType,
64
+ };
65
+ }
66
+ async patchTextCard(state, messageId, text, buttonRows = [], sessionKey, threadId) {
67
+ await this.timed('card patch', `message=${messageId}`, text, async () => {
68
+ await state.client.im.message.patch({
69
+ path: { message_id: messageId },
70
+ data: { content: JSON.stringify((0, cards_js_1.buildInteractiveCard)(text, buttonRows, sessionKey, threadId)) },
71
+ });
72
+ });
73
+ }
74
+ async createMessage(state, chatId, msgType, content) {
80
75
  const response = await state.client.im.message.create({
81
76
  params: { receive_id_type: resolveReceiveIdType(chatId) },
82
77
  data: {
83
78
  receive_id: chatId,
84
- msg_type: rendered.msgType,
85
- content: JSON.stringify(rendered.content),
79
+ msg_type: msgType,
80
+ content: JSON.stringify(content),
86
81
  },
87
82
  });
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
- };
83
+ return String(response?.data?.message_id || '').trim();
94
84
  }
95
- async patchTextCard(state, messageId, text, buttonRows = [], sessionKey, threadId) {
85
+ async timed(label, fields, text, action) {
96
86
  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')}`);
87
+ const result = await action();
88
+ this.log?.(`localcore-lark ${label} took ${Date.now() - startedAt}ms${fields ? ` ${fields}` : ''} textBytes=${Buffer.byteLength(text || '', 'utf8')}`);
89
+ return result;
102
90
  }
103
91
  }
104
92
  exports.LarkOutboundTransport = LarkOutboundTransport;
@@ -9,6 +9,7 @@ exports.renderLarkBridgeEventMessage = renderLarkBridgeEventMessage;
9
9
  exports.renderLarkBridgeEventMessages = renderLarkBridgeEventMessages;
10
10
  exports.getLarkRenderedMessageId = getLarkRenderedMessageId;
11
11
  exports.setLarkRenderedMessageId = setLarkRenderedMessageId;
12
+ const bridge_event_helpers_js_1 = require("../shared/bridge-event-helpers.js");
12
13
  function createLarkTurnState(sessionKey, sourceMessageId) {
13
14
  const turn = {
14
15
  sessionKey,
@@ -49,7 +50,7 @@ function isPendingToolProgressForLark(event) {
49
50
  }
50
51
  function consumeLarkBridgeEvent(turn, event, options) {
51
52
  const content = foldToolResultForLark(String(event.content || '').trim());
52
- const bridgeKind = resolveBridgeEventKind(event);
53
+ const bridgeKind = (0, bridge_event_helpers_js_1.resolveBridgeEventKind)(event);
53
54
  if (event.type === 'typing_start') {
54
55
  turn.messageId = undefined;
55
56
  turn.finalMessageId = undefined;
@@ -123,7 +124,7 @@ function consumeLarkBridgeEvent(turn, event, options) {
123
124
  }
124
125
  function renderLarkBridgeEventMessage(turn, event) {
125
126
  const content = foldToolResultForLark(String(event.content || '').trim());
126
- const bridgeKind = resolveBridgeEventKind(event);
127
+ const bridgeKind = (0, bridge_event_helpers_js_1.resolveBridgeEventKind)(event);
127
128
  if (event.type === 'preview_start' || event.type === 'update_message') {
128
129
  if (bridgeKind === 'thought') {
129
130
  return { key: 'noop', text: '', buttonRows: [], isFinal: false };
@@ -240,15 +241,9 @@ function progressKey(prefix, event) {
240
241
  return `${prefix}:${content.slice(0, 120)}`;
241
242
  }
242
243
  function isThoughtBridgeEvent(event) {
243
- const kind = resolveBridgeEventKind(event);
244
+ const kind = (0, bridge_event_helpers_js_1.resolveBridgeEventKind)(event);
244
245
  return kind === 'thought' || kind === 'plan';
245
246
  }
246
- function resolveBridgeEventKind(event) {
247
- if (event.bridgeKind) {
248
- return event.bridgeKind;
249
- }
250
- return event.type === 'status' ? 'status' : 'assistant';
251
- }
252
247
  function renderProcessText(kind, content) {
253
248
  const text = content.trim();
254
249
  return kind === 'plan' ? `计划\n${text}` : text;
@@ -279,15 +274,5 @@ function fencedCode(value, language = '') {
279
274
  return `${fence}${language}\n${normalized}\n${fence}`;
280
275
  }
281
276
  function pushUniqueLarkTurnLine(target, value) {
282
- const normalized = value.trim();
283
- if (!normalized) {
284
- return;
285
- }
286
- if (target[target.length - 1] === normalized) {
287
- return;
288
- }
289
- target.push(normalized);
290
- if (target.length > 6) {
291
- target.splice(0, target.length - 6);
292
- }
277
+ (0, bridge_event_helpers_js_1.pushUniqueLine)(target, value, 6);
293
278
  }
@@ -232,6 +232,30 @@ class BaseChannelGateway extends node_events_1.EventEmitter {
232
232
  async executeSessionCommand(input) {
233
233
  return this.sessionCommandRuntime.execute(input);
234
234
  }
235
+ async resolveDefaultAgentType(workspaceId, threadId) {
236
+ const router = this.options.getWorkspaceRouter();
237
+ if (typeof router.getWorkspaceDefaultAgentType === 'function') {
238
+ return router.getWorkspaceDefaultAgentType(workspaceId);
239
+ }
240
+ return this.options.store.getThreadRow(threadId)?.agent_type || 'codex';
241
+ }
242
+ findAwaitingPermissionThreadId(workspaceId, chatId, platformUserId, platformKey) {
243
+ for (const [sessionKey, route] of this.threadRouting.entries()) {
244
+ if (route.workspaceId !== workspaceId
245
+ || route.chatId !== chatId
246
+ || route.platformUserId !== platformUserId) {
247
+ continue;
248
+ }
249
+ if (platformKey !== undefined && route.platformKey !== platformKey) {
250
+ continue;
251
+ }
252
+ const turn = this.outboundTurns.get(sessionKey);
253
+ if (turn?.awaitingPermission && route.threadId) {
254
+ return route.threadId;
255
+ }
256
+ }
257
+ return '';
258
+ }
235
259
  // ==================== Runtime Management ====================
236
260
  resolveRuntimeState(workspaceId, instanceId) {
237
261
  const key = resolveRuntimeKey(workspaceId, instanceId);
@@ -280,6 +304,19 @@ class BaseChannelGateway extends node_events_1.EventEmitter {
280
304
  },
281
305
  });
282
306
  }
307
+ scheduleOutboundChain(sessionKey, work) {
308
+ const previous = this.outboundEventChains.get(sessionKey) || Promise.resolve();
309
+ const current = previous
310
+ .catch(() => undefined)
311
+ .then(work)
312
+ .finally(() => {
313
+ if (this.outboundEventChains.get(sessionKey) === current) {
314
+ this.outboundEventChains.delete(sessionKey);
315
+ }
316
+ });
317
+ this.outboundEventChains.set(sessionKey, current);
318
+ return current;
319
+ }
283
320
  clearRuntimeError(state) {
284
321
  state.lastError = undefined;
285
322
  state.lastErrorInfo = undefined;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveBridgeEventKind = resolveBridgeEventKind;
4
+ exports.pushUniqueLine = pushUniqueLine;
5
+ function resolveBridgeEventKind(event) {
6
+ if (event.bridgeKind) {
7
+ return event.bridgeKind;
8
+ }
9
+ return event.type === 'status' ? 'status' : 'assistant';
10
+ }
11
+ function pushUniqueLine(target, value, maxLines) {
12
+ const normalized = value.trim();
13
+ if (!normalized) {
14
+ return;
15
+ }
16
+ if (target[target.length - 1] === normalized) {
17
+ return;
18
+ }
19
+ target.push(normalized);
20
+ if (target.length > maxLines) {
21
+ target.splice(0, target.length - maxLines);
22
+ }
23
+ }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.normalizeChannelInstanceId = normalizeChannelInstanceId;
4
4
  exports.channelPlatformKey = channelPlatformKey;
5
+ exports.extractChannelInstanceId = extractChannelInstanceId;
5
6
  exports.runtimeKey = runtimeKey;
6
7
  function normalizeChannelInstanceId(value, fallback) {
7
8
  const raw = String(value || '').trim();
@@ -11,6 +12,11 @@ function normalizeChannelInstanceId(value, fallback) {
11
12
  function channelPlatformKey(platform, instanceId) {
12
13
  return instanceId === 'default' ? platform : `${platform}:${instanceId}`;
13
14
  }
15
+ function extractChannelInstanceId(platform, prefix) {
16
+ const normalized = String(platform || '').trim();
17
+ const tag = `${prefix}:`;
18
+ return normalized.startsWith(tag) ? normalized.slice(tag.length).trim() : '';
19
+ }
14
20
  function runtimeKey(workspaceId, instanceId) {
15
21
  return `${workspaceId}::${instanceId}`;
16
22
  }
@@ -110,7 +110,7 @@ async function runWeixinInboundPoller(input) {
110
110
  return await input.downloadMediaItem(item, msgId, index, uploadsDir, binding);
111
111
  }
112
112
  catch (error) {
113
- input.log?.(`localcore-weixin attachment download failed (${conversationId}#${index}): ${(0, text_utils_js_1.formatWeixinError)(error)}`);
113
+ input.log?.(`localcore-weixin attachment download failed (${conversationId}#${index}): ${(0, local_core_errors_js_1.formatSafeError)(error)}`);
114
114
  return null;
115
115
  }
116
116
  }));
@@ -160,7 +160,7 @@ async function runWeixinInboundPoller(input) {
160
160
  input.setRuntimeError(state, (0, local_core_errors_js_1.toLocalCoreErrorInfo)(error));
161
161
  input.notifyRuntimeStateChanged();
162
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)}`);
163
+ logPollError((0, local_core_errors_js_1.formatSafeError)(error), `localcore-weixin getUpdates error for ${binding.workspaceId} (${consecutiveFailures}): ${(0, local_core_errors_js_1.formatSafeError)(error)}`);
164
164
  await (0, text_utils_js_1.waitForWeixinRetry)(retryDelayMs, signal);
165
165
  }
166
166
  }