@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
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.resolvePiModel = resolvePiModel;
4
4
  exports.buildPiLaunchConfig = buildPiLaunchConfig;
5
- const node_path_1 = require("node:path");
6
5
  const desktop_js_1 = require("../../../../../shared/desktop.js");
7
6
  const launch_utils_js_1 = require("../shared/launch-utils.js");
7
+ const provider_materializer_js_1 = require("./provider-materializer.js");
8
8
  function resolvePiModel(input) {
9
9
  return input.rawModel || (0, launch_utils_js_1.getFirstProviderModelId)(input.providers);
10
10
  }
@@ -15,125 +15,8 @@ function buildPiLaunchConfig(input) {
15
15
  command: bundledPiAcp.command,
16
16
  args: [...bundledPiAcp.args],
17
17
  env: {
18
- ...collectPiProviderEnv(input.providers),
19
- ...writePiProviderRuntimeConfig(input),
18
+ ...(0, provider_materializer_js_1.materializePiProviderConfig)(input),
20
19
  PI_ACP_PI_COMMAND: bundledPiCommand,
21
20
  },
22
21
  };
23
22
  }
24
- function collectPiProviderEnv(providers) {
25
- const env = {};
26
- for (const provider of providers) {
27
- const apiKey = String(provider.api_key || '').trim();
28
- const envName = piProviderApiKeyEnvName(provider.name);
29
- if (apiKey && envName) {
30
- env[envName] = apiKey;
31
- }
32
- }
33
- return env;
34
- }
35
- function writePiProviderRuntimeConfig(input) {
36
- if (input.providers.length === 0) {
37
- return {};
38
- }
39
- const { providerId, modelId } = resolvePiProviderModel(input.providers, input.model);
40
- const agentDir = (0, launch_utils_js_1.projectLocalStateDir)(input.configState, '.pi-agent', input.project.name);
41
- (0, launch_utils_js_1.ensurePrivateDir)(agentDir);
42
- const auth = {};
43
- const modelProviders = {};
44
- for (const provider of input.providers) {
45
- const id = normalizePiProviderId(provider.name);
46
- if (!id) {
47
- continue;
48
- }
49
- const apiKey = String(provider.api_key || '').trim();
50
- const baseUrl = String(provider.base_url || '').trim();
51
- if (apiKey) {
52
- auth[id] = { type: 'api_key', key: apiKey };
53
- }
54
- if (baseUrl || apiKey) {
55
- modelProviders[id] = {
56
- name: String(provider.name || id).trim() || id,
57
- ...(baseUrl ? { baseUrl } : {}),
58
- ...(apiKey ? { apiKey } : {}),
59
- };
60
- }
61
- }
62
- (0, launch_utils_js_1.writeJsonFile)((0, node_path_1.resolve)(agentDir, 'auth.json'), auth);
63
- (0, launch_utils_js_1.writeJsonFile)((0, node_path_1.resolve)(agentDir, 'models.json'), { providers: modelProviders });
64
- (0, launch_utils_js_1.writeJsonFile)((0, node_path_1.resolve)(agentDir, 'settings.json'), {
65
- ...(providerId ? { defaultProvider: providerId } : {}),
66
- ...(modelId ? { defaultModel: modelId } : {}),
67
- quietStartup: true,
68
- }, 0o644);
69
- return {
70
- PI_CODING_AGENT_DIR: agentDir,
71
- };
72
- }
73
- function resolvePiProviderModel(providers, model) {
74
- const [explicitProvider, explicitModel] = (0, launch_utils_js_1.splitProviderModelRef)(model);
75
- if (explicitProvider && explicitModel) {
76
- return {
77
- providerId: normalizePiProviderId(explicitProvider),
78
- modelId: explicitModel,
79
- };
80
- }
81
- for (const provider of providers) {
82
- const providerId = normalizePiProviderId(provider.name);
83
- const modelId = (0, launch_utils_js_1.getProviderDefaultModelId)(provider);
84
- if (providerId && modelId && (!model || model === modelId)) {
85
- return { providerId, modelId };
86
- }
87
- }
88
- const fallbackProvider = providers.find((provider) => normalizePiProviderId(provider.name));
89
- return {
90
- providerId: normalizePiProviderId(fallbackProvider?.name),
91
- modelId: model,
92
- };
93
- }
94
- function normalizePiProviderId(providerName) {
95
- const providerId = (0, launch_utils_js_1.normalizeProviderId)(providerName);
96
- const aliases = {
97
- google: 'google',
98
- gemini: 'google',
99
- kimi: 'kimi-coding',
100
- moonshot: 'moonshotai',
101
- zhipuai: 'zai',
102
- };
103
- return aliases[providerId] || providerId;
104
- }
105
- function piProviderApiKeyEnvName(providerName) {
106
- const providerId = (0, launch_utils_js_1.normalizeProviderId)(providerName);
107
- const envNames = {
108
- anthropic: 'ANTHROPIC_API_KEY',
109
- 'azure-openai': 'AZURE_OPENAI_API_KEY',
110
- 'azure-openai-responses': 'AZURE_OPENAI_API_KEY',
111
- cerebras: 'CEREBRAS_API_KEY',
112
- cloudflare: 'CLOUDFLARE_API_KEY',
113
- 'cloudflare-ai-gateway': 'CLOUDFLARE_API_KEY',
114
- 'cloudflare-workers-ai': 'CLOUDFLARE_API_KEY',
115
- deepseek: 'DEEPSEEK_API_KEY',
116
- fireworks: 'FIREWORKS_API_KEY',
117
- gemini: 'GEMINI_API_KEY',
118
- google: 'GEMINI_API_KEY',
119
- groq: 'GROQ_API_KEY',
120
- huggingface: 'HF_TOKEN',
121
- kimi: 'KIMI_API_KEY',
122
- 'kimi-coding': 'KIMI_API_KEY',
123
- minimax: 'MINIMAX_API_KEY',
124
- 'minimax-cn': 'MINIMAX_CN_API_KEY',
125
- mistral: 'MISTRAL_API_KEY',
126
- moonshot: 'KIMI_API_KEY',
127
- openai: 'OPENAI_API_KEY',
128
- opencode: 'OPENCODE_API_KEY',
129
- 'opencode-go': 'OPENCODE_API_KEY',
130
- openrouter: 'OPENROUTER_API_KEY',
131
- siliconflow: 'SILICONFLOW_API_KEY',
132
- vercel: 'AI_GATEWAY_API_KEY',
133
- 'vercel-ai-gateway': 'AI_GATEWAY_API_KEY',
134
- xai: 'XAI_API_KEY',
135
- zai: 'ZAI_API_KEY',
136
- zhipuai: 'ZAI_API_KEY',
137
- };
138
- return envNames[providerId] || '';
139
- }
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.materializePiProviderConfig = materializePiProviderConfig;
4
+ exports.collectPiProviderEnv = collectPiProviderEnv;
5
+ exports.writePiProviderRuntimeConfig = writePiProviderRuntimeConfig;
6
+ exports.resolvePiProviderModel = resolvePiProviderModel;
7
+ exports.normalizePiProviderIdFromConfig = normalizePiProviderIdFromConfig;
8
+ exports.normalizePiProviderId = normalizePiProviderId;
9
+ exports.piProviderApiKeyEnvName = piProviderApiKeyEnvName;
10
+ const node_path_1 = require("node:path");
11
+ const launch_utils_js_1 = require("../shared/launch-utils.js");
12
+ function materializePiProviderConfig(input) {
13
+ return {
14
+ ...collectPiProviderEnv(input.providers),
15
+ ...writePiProviderRuntimeConfig(input),
16
+ };
17
+ }
18
+ function collectPiProviderEnv(providers) {
19
+ const env = {};
20
+ for (const provider of providers) {
21
+ const apiKey = String(provider.api_key || '').trim();
22
+ const envName = piProviderApiKeyEnvName(normalizePiProviderIdFromConfig(provider));
23
+ if (apiKey && envName) {
24
+ env[envName] = apiKey;
25
+ }
26
+ }
27
+ return env;
28
+ }
29
+ function writePiProviderRuntimeConfig(input) {
30
+ if (input.providers.length === 0) {
31
+ return {};
32
+ }
33
+ const { providerId, modelId } = resolvePiProviderModel(input.providers, input.model);
34
+ const agentDir = (0, launch_utils_js_1.projectLocalStateDir)(input.configState, '.pi-agent', input.project.name);
35
+ (0, launch_utils_js_1.ensurePrivateDir)(agentDir);
36
+ const auth = {};
37
+ const modelProviders = {};
38
+ for (const provider of input.providers) {
39
+ const id = normalizePiProviderIdFromConfig(provider);
40
+ if (!id) {
41
+ continue;
42
+ }
43
+ const apiKey = String(provider.api_key || '').trim();
44
+ const baseUrl = String(provider.base_url || '').trim();
45
+ if (apiKey) {
46
+ auth[id] = { type: 'api_key', key: apiKey };
47
+ }
48
+ if (baseUrl || apiKey) {
49
+ modelProviders[id] = {
50
+ name: String(provider.name || id).trim() || id,
51
+ ...(baseUrl ? { baseUrl } : {}),
52
+ ...(apiKey ? { apiKey } : {}),
53
+ };
54
+ }
55
+ }
56
+ (0, launch_utils_js_1.writeJsonFile)((0, node_path_1.resolve)(agentDir, 'auth.json'), auth);
57
+ (0, launch_utils_js_1.writeJsonFile)((0, node_path_1.resolve)(agentDir, 'models.json'), { providers: modelProviders });
58
+ (0, launch_utils_js_1.writeJsonFile)((0, node_path_1.resolve)(agentDir, 'settings.json'), {
59
+ ...(providerId ? { defaultProvider: providerId } : {}),
60
+ ...(modelId ? { defaultModel: modelId } : {}),
61
+ quietStartup: true,
62
+ }, 0o644);
63
+ return {
64
+ PI_CODING_AGENT_DIR: agentDir,
65
+ };
66
+ }
67
+ function resolvePiProviderModel(providers, model) {
68
+ const [explicitProvider, explicitModel] = (0, launch_utils_js_1.splitProviderModelRef)(model);
69
+ if (explicitProvider && explicitModel) {
70
+ return {
71
+ providerId: normalizePiProviderId(explicitProvider),
72
+ modelId: explicitModel,
73
+ };
74
+ }
75
+ for (const provider of providers) {
76
+ const providerId = normalizePiProviderIdFromConfig(provider);
77
+ const modelId = (0, launch_utils_js_1.getProviderDefaultModelId)(provider);
78
+ if (providerId && modelId && (!model || model === modelId)) {
79
+ return { providerId, modelId };
80
+ }
81
+ }
82
+ const fallbackProvider = providers.find((provider) => normalizePiProviderId(provider.name));
83
+ return {
84
+ providerId: fallbackProvider ? normalizePiProviderIdFromConfig(fallbackProvider) : '',
85
+ modelId: model,
86
+ };
87
+ }
88
+ function normalizePiProviderIdFromConfig(provider) {
89
+ const providerId = normalizePiProviderId(provider.name);
90
+ if (providerId && piProviderApiKeyEnvName(providerId)) {
91
+ return providerId;
92
+ }
93
+ const providerName = (0, launch_utils_js_1.normalizeProviderId)(provider.name);
94
+ if (providerName.startsWith('deepseek-')) {
95
+ return 'deepseek';
96
+ }
97
+ const baseUrl = String(provider.base_url || '').toLowerCase();
98
+ if (baseUrl.includes('api.deepseek.com') || baseUrl.includes('deepseek.com')) {
99
+ return 'deepseek';
100
+ }
101
+ return providerId;
102
+ }
103
+ function normalizePiProviderId(providerName) {
104
+ const providerId = (0, launch_utils_js_1.normalizeProviderId)(providerName);
105
+ const aliases = {
106
+ google: 'google',
107
+ gemini: 'google',
108
+ kimi: 'kimi-coding',
109
+ moonshot: 'moonshotai',
110
+ zhipuai: 'zai',
111
+ };
112
+ return aliases[providerId] || providerId;
113
+ }
114
+ function piProviderApiKeyEnvName(providerName) {
115
+ const providerId = (0, launch_utils_js_1.normalizeProviderId)(providerName);
116
+ const envNames = {
117
+ anthropic: 'ANTHROPIC_API_KEY',
118
+ 'azure-openai': 'AZURE_OPENAI_API_KEY',
119
+ 'azure-openai-responses': 'AZURE_OPENAI_API_KEY',
120
+ cerebras: 'CEREBRAS_API_KEY',
121
+ cloudflare: 'CLOUDFLARE_API_KEY',
122
+ 'cloudflare-ai-gateway': 'CLOUDFLARE_API_KEY',
123
+ 'cloudflare-workers-ai': 'CLOUDFLARE_API_KEY',
124
+ deepseek: 'DEEPSEEK_API_KEY',
125
+ fireworks: 'FIREWORKS_API_KEY',
126
+ gemini: 'GEMINI_API_KEY',
127
+ google: 'GEMINI_API_KEY',
128
+ groq: 'GROQ_API_KEY',
129
+ huggingface: 'HF_TOKEN',
130
+ kimi: 'KIMI_API_KEY',
131
+ 'kimi-coding': 'KIMI_API_KEY',
132
+ minimax: 'MINIMAX_API_KEY',
133
+ 'minimax-cn': 'MINIMAX_CN_API_KEY',
134
+ mistral: 'MISTRAL_API_KEY',
135
+ moonshot: 'KIMI_API_KEY',
136
+ openai: 'OPENAI_API_KEY',
137
+ opencode: 'OPENCODE_API_KEY',
138
+ 'opencode-go': 'OPENCODE_API_KEY',
139
+ openrouter: 'OPENROUTER_API_KEY',
140
+ siliconflow: 'SILICONFLOW_API_KEY',
141
+ vercel: 'AI_GATEWAY_API_KEY',
142
+ 'vercel-ai-gateway': 'AI_GATEWAY_API_KEY',
143
+ xai: 'XAI_API_KEY',
144
+ zai: 'ZAI_API_KEY',
145
+ zhipuai: 'ZAI_API_KEY',
146
+ };
147
+ return envNames[providerId] || '';
148
+ }
@@ -32,7 +32,10 @@ function normalizeLarkInboundMessageEvent(data, options = {}) {
32
32
  detail: `chat=${String(message.chat_id || '')} message=${String(message.message_id || '')}`,
33
33
  };
34
34
  }
35
- const text = stripLarkMentions(String(parsedContent.text || '').trim(), mentions, botOpenId);
35
+ const rawText = messageType === 'post'
36
+ ? extractLarkPostText(parsedContent, botOpenId)
37
+ : String(parsedContent.text || '').trim();
38
+ const text = stripLarkMentions(rawText, mentions, botOpenId);
36
39
  const platformUserId = String(sender.sender_id?.user_id || sender.sender_id?.open_id || '').trim();
37
40
  const chatId = String(message.chat_id || platformUserId).trim();
38
41
  if (!platformUserId || !chatId) {
@@ -112,3 +115,54 @@ function getMentionOpenId(item) {
112
115
  const id = item.id || item.user_id || item.userId || {};
113
116
  return String(id.open_id || id.openId || item.open_id || item.openId || '').trim();
114
117
  }
118
+ function extractLarkPostText(content, botOpenId) {
119
+ const title = String(content.title || '').trim();
120
+ const lines = readLarkPostLines(content)
121
+ .map((line) => readLarkPostLineText(line, botOpenId).trim())
122
+ .filter(Boolean);
123
+ return [
124
+ ...(title ? [title] : []),
125
+ ...lines,
126
+ ].join('\n').trim();
127
+ }
128
+ function readLarkPostLines(content) {
129
+ const directContent = content.content;
130
+ if (Array.isArray(directContent)) {
131
+ return directContent;
132
+ }
133
+ const localizedContent = content.zh_cn?.content || content.en_us?.content;
134
+ return Array.isArray(localizedContent) ? localizedContent : [];
135
+ }
136
+ function readLarkPostLineText(line, botOpenId) {
137
+ if (Array.isArray(line)) {
138
+ return line.map((item) => readLarkPostInlineText(item, botOpenId)).join('');
139
+ }
140
+ return readLarkPostInlineText(line, botOpenId);
141
+ }
142
+ function readLarkPostInlineText(item, botOpenId) {
143
+ if (!item || typeof item !== 'object') {
144
+ return '';
145
+ }
146
+ const node = item;
147
+ const tag = String(node.tag || '').trim().toLowerCase();
148
+ if (tag === 'at') {
149
+ if (botOpenId && getMentionOpenId(node) === botOpenId) {
150
+ return '';
151
+ }
152
+ const name = String(node.user_name || node.name || node.display_name || node.text || '').trim();
153
+ return name ? `@${name}` : '';
154
+ }
155
+ if (tag === 'a') {
156
+ return String(node.text || node.href || '').trim();
157
+ }
158
+ if (typeof node.text === 'string') {
159
+ return node.text;
160
+ }
161
+ if (Array.isArray(node.children)) {
162
+ return node.children.map((child) => readLarkPostInlineText(child, botOpenId)).join('');
163
+ }
164
+ if (Array.isArray(node.content)) {
165
+ return node.content.map((child) => readLarkPostInlineText(child, botOpenId)).join('');
166
+ }
167
+ return '';
168
+ }
@@ -38,6 +38,7 @@ const node_events_1 = require("node:events");
38
38
  const node_crypto_1 = require("node:crypto");
39
39
  const node_fs_1 = require("node:fs");
40
40
  const node_path_1 = require("node:path");
41
+ const local_core_errors_js_1 = require("../../kernel/local-core-errors.js");
41
42
  const desktop_js_1 = require("../../../../../shared/desktop.js");
42
43
  const content_js_1 = require("../shared/content.js");
43
44
  const file_utils_js_1 = require("../shared/file-utils.js");
@@ -49,7 +50,7 @@ const registration_js_1 = require("./registration.js");
49
50
  const messages_js_1 = require("./rendering/messages.js");
50
51
  const inbound_js_1 = require("./inbound.js");
51
52
  const runtime_state_js_1 = require("./runtime-state.js");
52
- const session_command_service_js_1 = require("../../thread/session-command-service.js");
53
+ const thread_slash_command_dispatcher_js_1 = require("../../thread/thread-slash-command-dispatcher.js");
53
54
  const PAIRING_EXPIRY_MS = 10 * 60 * 1000;
54
55
  const LARK_MAX_UPLOAD_FILE_SIZE = 30 * 1024 * 1024;
55
56
  const LARK_FINAL_PATCH_INTERVAL_MS = 900;
@@ -73,15 +74,29 @@ class LocalCoreLarkGateway extends node_events_1.EventEmitter {
73
74
  constructor(options) {
74
75
  super();
75
76
  this.options = options;
76
- const sessionCommandService = new session_command_service_js_1.SessionCommandService({
77
- listThreads: (workspaceId) => this.options.getWorkspaceRouter().listThreads(workspaceId),
78
- getThread: (threadId) => this.options.getWorkspaceRouter().getThread(threadId),
79
- createThread: (workspaceId, title) => this.options.getWorkspaceRouter().createThread(workspaceId, title),
80
- renameThread: (threadId, title) => this.options.getWorkspaceRouter().renameThread(threadId, title),
81
- deleteThread: (threadId) => this.options.getWorkspaceRouter().deleteThread(threadId),
77
+ const slashCommands = new thread_slash_command_dispatcher_js_1.ThreadSlashCommandDispatcher({
78
+ session: {
79
+ listThreads: (workspaceId) => this.options.getWorkspaceRouter().listThreads(workspaceId),
80
+ getThread: (threadId) => this.options.getWorkspaceRouter().getThread(threadId),
81
+ createThread: (workspaceId, title) => this.options.getWorkspaceRouter().createThread(workspaceId, title),
82
+ renameThread: (threadId, title) => this.options.getWorkspaceRouter().renameThread(threadId, title),
83
+ deleteThread: (threadId) => this.options.getWorkspaceRouter().deleteThread(threadId),
84
+ },
85
+ thread: {
86
+ getThreadRow: (threadId) => this.options.store.getThreadRow(threadId),
87
+ updateThreadAgentMode: (threadId, mode) => this.options.store.updateThreadAgentMode(threadId, mode),
88
+ updateThreadAgentType: (threadId, agentType) => this.options.store.updateThreadAgentType(threadId, agentType),
89
+ getLatestRunForThread: (threadId) => this.options.store.getLatestRunForThread(threadId),
90
+ createAuditEvent: (input) => this.options.store.createAuditEvent(input),
91
+ getAgentTypes: () => this.options.getWorkspaceRouter().getAgentTypes(),
92
+ setThreadMode: (threadId, mode) => this.options.getWorkspaceRouter().setThreadMode(threadId, mode),
93
+ closeThreadSession: (threadId) => this.options.getWorkspaceRouter().closeThreadSession(threadId),
94
+ interruptRun: (runId) => this.options.getWorkspaceRouter().interruptRun(runId),
95
+ log: this.options.log,
96
+ },
82
97
  });
83
98
  this.sessionCommandRuntime = new session_command_runtime_js_1.ChannelSessionCommandRuntime({
84
- service: sessionCommandService,
99
+ dispatcher: slashCommands,
85
100
  store: this.options.store,
86
101
  getThreadSessionKey: (threadId) => this.options.getWorkspaceRouter().getThreadSessionKey(threadId),
87
102
  setThreadRoute: (sessionKey, route) => {
@@ -382,6 +397,8 @@ class LocalCoreLarkGateway extends node_events_1.EventEmitter {
382
397
  status: binding?.status || 'disabled',
383
398
  appId: binding?.appId || '',
384
399
  lastError: binding?.lastError,
400
+ lastErrorInfo: binding?.lastErrorInfo,
401
+ lastErrorAt: binding?.lastErrorAt,
385
402
  connectedAt: binding?.connectedAt,
386
403
  pendingPairings: pairings.length,
387
404
  authorizedUsers: users.length,
@@ -698,6 +715,7 @@ class LocalCoreLarkGateway extends node_events_1.EventEmitter {
698
715
  currentThreadId: threadId,
699
716
  text: input.text,
700
717
  defaultTitle: `${input.displayName || 'Lark'} ${new Date().toLocaleTimeString()}`,
718
+ defaultAgentType: slashCommand ? await this.resolveDefaultAgentType(input.workspaceId, threadId) : '',
701
719
  chatId: input.chatId,
702
720
  platformUserId: input.platformUserId,
703
721
  platformKey,
@@ -841,13 +859,20 @@ class LocalCoreLarkGateway extends node_events_1.EventEmitter {
841
859
  status.status = 'running';
842
860
  status.connected = true;
843
861
  status.connectedAt = new Date().toISOString();
844
- status.lastError = undefined;
862
+ this.clearRuntimeError(status);
845
863
  this.options.log?.(`localcore-lark ws ready for ${binding.workspaceId}`);
846
864
  }
847
865
  catch (error) {
848
866
  status.status = 'error';
849
867
  status.connected = false;
850
- status.lastError = error instanceof Error ? error.message : String(error);
868
+ const errorInfo = (0, local_core_errors_js_1.toLocalCoreErrorInfo)(error instanceof local_core_errors_js_1.LocalCoreError
869
+ ? error
870
+ : new local_core_errors_js_1.LocalCoreError('channel_auth_failed', error instanceof Error ? error.message : String(error), {
871
+ userMessage: 'Lark is not connected.',
872
+ suggestedAction: 'Check app credentials and restart the Lark gateway.',
873
+ details: { workspaceId: binding.workspaceId, instanceId: binding.instanceId },
874
+ }), 'channel_auth_failed');
875
+ this.setRuntimeError(status, errorInfo);
851
876
  this.options.log?.(`localcore-lark start failed for ${binding.workspaceId}: ${status.lastError}`);
852
877
  }
853
878
  this.notifyRuntimeStateChanged();
@@ -894,6 +919,28 @@ class LocalCoreLarkGateway extends node_events_1.EventEmitter {
894
919
  },
895
920
  });
896
921
  }
922
+ clearRuntimeError(state) {
923
+ state.lastError = undefined;
924
+ state.lastErrorInfo = undefined;
925
+ state.lastErrorAt = undefined;
926
+ }
927
+ setRuntimeError(state, errorInfo) {
928
+ state.lastError = errorInfo.message;
929
+ state.lastErrorInfo = errorInfo;
930
+ state.lastErrorAt = new Date().toISOString();
931
+ this.options.eventBus.emit({
932
+ type: 'localcore.error',
933
+ payload: {
934
+ scope: 'channel.lark',
935
+ errorInfo,
936
+ context: {
937
+ workspaceId: state.workspaceId,
938
+ instanceId: state.instanceId,
939
+ platform: 'lark',
940
+ },
941
+ },
942
+ });
943
+ }
897
944
  async handleMessageEvent(workspaceId, instanceIdOrData, platformKeyOrData, maybeData) {
898
945
  const legacyCall = typeof instanceIdOrData === 'object';
899
946
  const instanceId = legacyCall ? 'default' : instanceIdOrData;
@@ -1308,6 +1355,7 @@ class LocalCoreLarkGateway extends node_events_1.EventEmitter {
1308
1355
  currentThreadId: sessionAction.threadId,
1309
1356
  text: sessionAction.command,
1310
1357
  defaultTitle: `Lark ${new Date().toLocaleTimeString()}`,
1358
+ defaultAgentType: await this.resolveDefaultAgentType(workspaceId, sessionAction.threadId),
1311
1359
  chatId: route.chatId,
1312
1360
  platformUserId: route.platformUserId,
1313
1361
  platformKey: route.platformKey,
@@ -1344,6 +1392,13 @@ class LocalCoreLarkGateway extends node_events_1.EventEmitter {
1344
1392
  threadId: binding.thread_id,
1345
1393
  };
1346
1394
  }
1395
+ async resolveDefaultAgentType(workspaceId, threadId) {
1396
+ const router = this.options.getWorkspaceRouter();
1397
+ if (typeof router.getWorkspaceDefaultAgentType === 'function') {
1398
+ return router.getWorkspaceDefaultAgentType(workspaceId);
1399
+ }
1400
+ return this.options.store.getThreadRow(threadId)?.agent_type || 'codex';
1401
+ }
1347
1402
  async markPermissionCardActionHandled(workspaceId, instanceId, rootPayload, payload, value, response, threadId) {
1348
1403
  const state = this.resolveRuntimeState(workspaceId, instanceId).state;
1349
1404
  if (!state?.client) {
@@ -7,10 +7,12 @@ class ChannelSessionCommandRuntime {
7
7
  this.options = options;
8
8
  }
9
9
  async execute(input) {
10
- const result = await this.options.service.execute(input.text, {
10
+ const result = await this.options.dispatcher.execute({
11
11
  workspaceId: input.workspaceId,
12
- currentThreadId: input.currentThreadId,
12
+ threadId: input.currentThreadId,
13
+ content: input.text,
13
14
  defaultTitle: input.defaultTitle,
15
+ defaultAgentType: input.defaultAgentType,
14
16
  });
15
17
  if (!result.handled) {
16
18
  return { handled: false, threadId: input.currentThreadId };