@kafca/agentdock 0.1.56 → 0.1.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/README.md +7 -0
  2. package/dist/renderer/assets/{Badge-DjcoXx2J.js → Badge-CDTbmw1h.js} +1 -1
  3. package/dist/renderer/assets/Card-DayUo35w.js +1 -0
  4. package/dist/renderer/assets/Config-ByGMQuzR.js +21 -0
  5. package/dist/renderer/assets/CronList-XqHdVlgu.js +1 -0
  6. package/dist/renderer/assets/Dashboard-CZj-oANw.js +41 -0
  7. package/dist/renderer/assets/{EmptyState-DIZLiccW.js → EmptyState-EFMkOjZO.js} +1 -1
  8. package/dist/renderer/assets/HighlightedMarkdown-DyvF3DHK.js +12 -0
  9. package/dist/renderer/assets/Input-DxoWVc9d.js +1 -0
  10. package/dist/renderer/assets/{KnowledgeDetail-CJ9IYOsa.js → KnowledgeDetail-CbUb2tG7.js} +2 -2
  11. package/dist/renderer/assets/{KnowledgeHome-BLGPwnBO.js → KnowledgeHome-BWV1gz4f.js} +3 -3
  12. package/dist/renderer/assets/Logs-DqnanQTc.js +6 -0
  13. package/dist/renderer/assets/{Modal-CQiUpfl4.js → Modal-yY7TzR0x.js} +3 -3
  14. package/dist/renderer/assets/MonitorList-CIjGQkFs.js +1 -0
  15. package/dist/renderer/assets/Page-vwHNUdoj.js +1 -0
  16. package/dist/renderer/assets/{Select-D6z65IT3.js → Select-CmbK36pN.js} +2 -2
  17. package/dist/renderer/assets/ThreadChat-4OceMgM4.js +86 -0
  18. package/dist/renderer/assets/Workspace-DplPJOjJ.js +19 -0
  19. package/dist/renderer/assets/{arrow-left-CV5cL3f4.js → arrow-left-C8HfBt2K.js} +1 -1
  20. package/dist/renderer/assets/{book-open-DThvB7pj.js → book-open-BCdZWncQ.js} +1 -1
  21. package/dist/renderer/assets/channels-hgO3cAIx.js +6 -0
  22. package/dist/renderer/assets/chevron-down-BPk77tqY.js +11 -0
  23. package/dist/renderer/assets/index-BIKL3fTP.css +11 -0
  24. package/dist/renderer/assets/index-BlA4xPdd.js +41 -0
  25. package/dist/renderer/assets/index-wYpjqVqC.js +167 -0
  26. package/dist/renderer/assets/knowledge-7pl06KuH.js +1 -0
  27. package/dist/renderer/assets/{pencil-Dv5WxhdC.js → pencil-CB1SWZ9A.js} +1 -1
  28. package/dist/renderer/assets/{play-DnCnft83.js → play-BvsoXUrM.js} +1 -1
  29. package/dist/renderer/assets/{plus-DsxIagzS.js → plus-CokBDnaL.js} +1 -1
  30. package/dist/renderer/assets/{save-CST01lIc.js → save-D-w4kATO.js} +1 -1
  31. package/dist/renderer/assets/{search-B_bqy6Wd.js → search-Cnsn6i4Q.js} +1 -1
  32. package/dist/renderer/assets/{shield-check-D6lG5Aoc.js → shield-check-Cjja2Gh6.js} +1 -1
  33. package/dist/renderer/assets/threads-BCm6j4eI.js +1 -0
  34. package/dist/renderer/assets/{trash-2-Cefngb6Q.js → trash-2-CIxz9qYY.js} +1 -1
  35. package/dist/renderer/index.html +2 -2
  36. package/dist-electron/packages/contracts/src/automation.js +2 -0
  37. package/dist-electron/packages/contracts/src/channels.js +2 -0
  38. package/dist-electron/packages/contracts/src/knowledge.js +2 -0
  39. package/dist-electron/packages/contracts/src/local-core.js +15 -0
  40. package/dist-electron/packages/contracts/src/runtime.js +2 -0
  41. package/dist-electron/packages/contracts/src/scheduler.js +2 -0
  42. package/dist-electron/packages/contracts/src/threads.js +2 -0
  43. package/dist-electron/packages/core-sdk/src/automation.js +32 -0
  44. package/dist-electron/packages/core-sdk/src/channels.js +121 -0
  45. package/dist-electron/packages/core-sdk/src/client.js +455 -0
  46. package/dist-electron/packages/core-sdk/src/index.js +43 -607
  47. package/dist-electron/packages/core-sdk/src/knowledge.js +85 -0
  48. package/dist-electron/packages/core-sdk/src/request.js +22 -0
  49. package/dist-electron/packages/core-sdk/src/runtime.js +214 -0
  50. package/dist-electron/packages/core-sdk/src/scheduler.js +32 -0
  51. package/dist-electron/packages/core-sdk/src/threads.js +67 -0
  52. package/dist-electron/packages/plugin-sdk/src/agents.js +2 -0
  53. package/dist-electron/packages/plugin-sdk/src/automation.js +2 -0
  54. package/dist-electron/packages/plugin-sdk/src/channels.js +2 -0
  55. package/dist-electron/packages/plugin-sdk/src/index.js +21 -0
  56. package/dist-electron/packages/plugin-sdk/src/knowledge.js +2 -0
  57. package/dist-electron/packages/plugin-sdk/src/runtime.js +2 -0
  58. package/dist-electron/packages/plugin-sdk/src/scheduler.js +2 -0
  59. package/dist-electron/packages/plugin-sdk/src/threads.js +2 -0
  60. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +5 -8
  61. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-content.js +2 -2
  62. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +3 -3
  63. package/dist-electron/services/local-ai-core/src/acp/store/agent-task-store.js +5 -5
  64. package/dist-electron/services/local-ai-core/src/acp/store/automation-monitor-store.js +12 -12
  65. package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +2 -2
  66. package/dist-electron/services/local-ai-core/src/acp/store/scheduler-store.js +11 -11
  67. package/dist-electron/services/local-ai-core/src/acp/store/security-store.js +3 -3
  68. package/dist-electron/services/local-ai-core/src/acp/store/thread-store.js +7 -7
  69. package/dist-electron/services/local-ai-core/src/acp/workspace-acp-permissions.js +2 -2
  70. package/dist-electron/services/local-ai-core/src/agents/claudecode/definition.js +3 -3
  71. package/dist-electron/services/local-ai-core/src/agents/codex/definition.js +3 -3
  72. package/dist-electron/services/local-ai-core/src/agents/localcore-acp/definition.js +2 -2
  73. package/dist-electron/services/local-ai-core/src/agents/localcore-acp/index.js +4 -4
  74. package/dist-electron/services/local-ai-core/src/agents/opencode/launch.js +2 -2
  75. package/dist-electron/services/local-ai-core/src/agents/pi/definition.js +2 -2
  76. package/dist-electron/services/local-ai-core/src/agents/pi/launch.js +3 -3
  77. package/dist-electron/services/local-ai-core/src/agents/pi/provider-materializer.js +1 -1
  78. package/dist-electron/services/local-ai-core/src/agents/shared/agent-plugin.js +4 -4
  79. package/dist-electron/services/local-ai-core/src/channel/lark/cards.js +33 -18
  80. package/dist-electron/services/local-ai-core/src/channel/lark/config.js +2 -2
  81. package/dist-electron/services/local-ai-core/src/channel/lark/gateway-utils.js +91 -0
  82. package/dist-electron/services/local-ai-core/src/channel/lark/inbound-handler.js +180 -0
  83. package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +52 -486
  84. package/dist-electron/services/local-ai-core/src/channel/lark/outbound-transport.js +124 -0
  85. package/dist-electron/services/local-ai-core/src/channel/shared/inbound-authorization.js +54 -0
  86. package/dist-electron/services/local-ai-core/src/channel/weixin/config.js +2 -2
  87. package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-media.js +21 -0
  88. package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-poller.js +167 -0
  89. package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +50 -469
  90. package/dist-electron/services/local-ai-core/src/channel/weixin/runtime-state.js +156 -0
  91. package/dist-electron/services/local-ai-core/src/channel/weixin/text-utils.js +100 -0
  92. package/dist-electron/services/local-ai-core/src/cli/lac.js +6 -6
  93. package/dist-electron/services/local-ai-core/src/cli/monitor-cli-parsers.js +2 -2
  94. package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +28 -70
  95. package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-ai-vector-plugin.js +2 -2
  96. package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-noop-plugin.js +2 -2
  97. package/dist-electron/services/local-ai-core/src/router/workspace-bridge-event-stream.js +29 -0
  98. package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +5 -5
  99. package/dist-electron/services/local-ai-core/src/router/workspace-router.js +47 -60
  100. package/dist-electron/services/local-ai-core/src/runtime/agent-runtime-detector.js +5 -5
  101. package/dist-electron/services/local-ai-core/src/runtime/config-migration.js +6 -6
  102. package/dist-electron/services/local-ai-core/src/runtime/deployment-diagnostics.js +3 -3
  103. package/dist-electron/services/local-ai-core/src/runtime/external-service.js +3 -1
  104. package/dist-electron/services/local-ai-core/src/runtime/handlers/automation-handler.js +11 -2
  105. package/dist-electron/services/local-ai-core/src/runtime/handlers/channel-handler.js +12 -6
  106. package/dist-electron/services/local-ai-core/src/runtime/handlers/external-handler.js +10 -2
  107. package/dist-electron/services/local-ai-core/src/runtime/handlers/knowledge-handler.js +18 -6
  108. package/dist-electron/services/local-ai-core/src/runtime/handlers/provider-handler.js +7 -2
  109. package/dist-electron/services/local-ai-core/src/runtime/handlers/runtime-handler.js +28 -3
  110. package/dist-electron/services/local-ai-core/src/runtime/handlers/scheduler-handler.js +10 -2
  111. package/dist-electron/services/local-ai-core/src/runtime/handlers/security-handler.js +18 -5
  112. package/dist-electron/services/local-ai-core/src/runtime/handlers/task-handler.js +14 -2
  113. package/dist-electron/services/local-ai-core/src/runtime/handlers/thread-handler.js +18 -15
  114. package/dist-electron/services/local-ai-core/src/runtime/handlers/workspace-handler.js +13 -2
  115. package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +35 -8
  116. package/dist-electron/services/local-ai-core/src/runtime/request-validation.js +79 -0
  117. package/dist-electron/services/local-ai-core/src/runtime/runtime-detection-service.js +9 -9
  118. package/dist-electron/services/local-ai-core/src/runtime/server-helpers.js +10 -1
  119. package/dist-electron/services/local-ai-core/src/runtime/server.js +2 -1
  120. package/dist-electron/services/local-ai-core/src/runtime/workspace-project-registry.js +76 -0
  121. package/dist-electron/services/local-ai-core/src/sandbox/sandbox-config.js +8 -8
  122. package/dist-electron/services/local-ai-core/src/thread/agent-message-policy.js +75 -0
  123. package/dist-electron/shared/desktop.js +1 -64
  124. package/dist-electron/src/components/chat/chat-controller-state.js +60 -0
  125. package/dist-electron/src/components/chat/chat-event-gate.js +146 -0
  126. package/dist-electron/src/components/chat/markdown-code-block.js +8 -0
  127. package/dist-electron/src/pages/Desktop/workspace-model.js +212 -0
  128. package/dist-electron/src/pages/Threads/thread-chat-model.js +50 -51
  129. package/dist-electron/tests/contracts/agent-message-policy.test.js +21 -0
  130. package/dist-electron/tests/contracts/architecture-docs.test.js +56 -33
  131. package/dist-electron/tests/contracts/chat-event-gate.test.js +114 -0
  132. package/dist-electron/tests/contracts/chat-markdown.test.js +16 -0
  133. package/dist-electron/tests/contracts/thread-task-state.test.js +32 -0
  134. package/dist-electron/tests/contracts/workspace-identity.test.js +23 -0
  135. package/dist-electron/tests/electron/core-client.test.js +284 -0
  136. package/dist-electron/tests/electron/plugin-kernel.test.js +54 -0
  137. package/dist-electron/tests/electron/renderer-packaging.test.js +9 -0
  138. package/dist-electron/tests/electron/workspace-task-store.test.js +31 -0
  139. package/dist-electron/tests/integration/channel-inbound-authorization.test.js +80 -0
  140. package/dist-electron/tests/integration/lark-gateway-utils.test.js +13 -0
  141. package/dist-electron/tests/integration/lark-gateway.test.js +4 -4
  142. package/dist-electron/tests/integration/weixin-runtime-state.test.js +32 -0
  143. package/dist-electron/tests/integration/weixin-text-utils.test.js +15 -0
  144. package/package.json +9 -4
  145. package/dist/renderer/assets/Chat-C5Bkm9-M.js +0 -2
  146. package/dist/renderer/assets/ChatMarkdown-uc36EzyD.js +0 -45
  147. package/dist/renderer/assets/Config-DHtQuuLy.js +0 -21
  148. package/dist/renderer/assets/CronList-BYUnhzSC.js +0 -1
  149. package/dist/renderer/assets/Dashboard-BPnGMDg3.js +0 -26
  150. package/dist/renderer/assets/Logs-Dyd2Uwlt.js +0 -1
  151. package/dist/renderer/assets/MonitorList-Byg3E3Gt.js +0 -1
  152. package/dist/renderer/assets/Page-7DxXvTMm.js +0 -1
  153. package/dist/renderer/assets/ProjectDetail-Dfr5s0Ja.js +0 -11
  154. package/dist/renderer/assets/ProjectList-CDDQjAQ_.js +0 -1
  155. package/dist/renderer/assets/SessionChat-s7CAaCPL.js +0 -1
  156. package/dist/renderer/assets/SessionList-D-OycKKS.js +0 -1
  157. package/dist/renderer/assets/ThreadChat-CLdFynB5.js +0 -28
  158. package/dist/renderer/assets/Workspace-xfT5z4j_.js +0 -19
  159. package/dist/renderer/assets/bot-CWQ5-ovl.js +0 -6
  160. package/dist/renderer/assets/check-DKM7zfWG.js +0 -6
  161. package/dist/renderer/assets/chevron-down-Dfw2KU87.js +0 -6
  162. package/dist/renderer/assets/circle-CoP4RA4s.js +0 -6
  163. package/dist/renderer/assets/desktop-CsDYrOOU.js +0 -1
  164. package/dist/renderer/assets/desktop-JQkhNOF4.js +0 -5
  165. package/dist/renderer/assets/funnel-DpVLlG3g.js +0 -6
  166. package/dist/renderer/assets/heart-BMD36ejP.js +0 -6
  167. package/dist/renderer/assets/index-COxSYBjE.js +0 -182
  168. package/dist/renderer/assets/index-CTGTI-cm.js +0 -41
  169. package/dist/renderer/assets/index-CjCuR6DI.css +0 -11
  170. package/dist/renderer/assets/projects-DgjHcNgt.js +0 -1
  171. package/dist/renderer/assets/server-ecH4GNwa.js +0 -11
  172. package/dist/renderer/assets/session-utils-Dd_WKMYW.js +0 -6
  173. package/dist/renderer/assets/sessions-BQ33Mv4k.js +0 -1
  174. package/dist/renderer/assets/user-D_8RSH-T.js +0 -6
  175. package/dist/renderer/assets/wifi-off-DB9D-pOu.js +0 -11
  176. package/dist-electron/src/api/client.js +0 -73
  177. package/dist-electron/src/api/sessions.js +0 -21
  178. package/dist-electron/src/lib/session-utils.js +0 -51
  179. package/dist-electron/src/pages/Projects/project-provider-config.js +0 -75
  180. package/dist-electron/tests/electron/project-provider-config.test.js +0 -71
@@ -0,0 +1,284 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const strict_1 = __importDefault(require("node:assert/strict"));
7
+ const node_test_1 = __importDefault(require("node:test"));
8
+ const client_js_1 = require("../../packages/core-sdk/src/client.js");
9
+ class FakeEventSource {
10
+ listeners = new Map();
11
+ onerror = null;
12
+ onopen = null;
13
+ closed = false;
14
+ addEventListener(type, listener) {
15
+ const listeners = this.listeners.get(type) || new Set();
16
+ listeners.add(listener);
17
+ this.listeners.set(type, listeners);
18
+ }
19
+ emit(type, payload) {
20
+ for (const listener of this.listeners.get(type) || []) {
21
+ listener({ data: typeof payload === 'string' ? payload : JSON.stringify(payload) });
22
+ }
23
+ }
24
+ close() {
25
+ this.closed = true;
26
+ }
27
+ }
28
+ (0, node_test_1.default)('core client shares one event source across subscribers and closes it after the last unsubscribe', () => {
29
+ const sources = [];
30
+ const client = (0, client_js_1.createCoreClient)({
31
+ baseUrl: 'http://127.0.0.1:9831/api/local/v1/',
32
+ eventSourceFactory: () => {
33
+ const source = new FakeEventSource();
34
+ sources.push(source);
35
+ return source;
36
+ },
37
+ });
38
+ const first = client.events.subscribe(() => { });
39
+ const second = client.events.subscribe(() => { });
40
+ strict_1.default.equal(sources.length, 1);
41
+ strict_1.default.equal(client.baseUrl, 'http://127.0.0.1:9831/api/local/v1');
42
+ first();
43
+ strict_1.default.equal(sources[0].closed, false);
44
+ second();
45
+ strict_1.default.equal(sources[0].closed, true);
46
+ });
47
+ (0, node_test_1.default)('core clients with the same base URL share one event source across instances', () => {
48
+ const sources = [];
49
+ const firstClient = (0, client_js_1.createCoreClient)({
50
+ baseUrl: 'http://127.0.0.1:9831/api/local/v1/',
51
+ eventSourceFactory: () => {
52
+ const source = new FakeEventSource();
53
+ sources.push(source);
54
+ return source;
55
+ },
56
+ });
57
+ const secondClient = (0, client_js_1.createCoreClient)({
58
+ baseUrl: 'http://127.0.0.1:9831/api/local/v1',
59
+ eventSourceFactory: () => {
60
+ const source = new FakeEventSource();
61
+ sources.push(source);
62
+ return source;
63
+ },
64
+ });
65
+ const firstEventTypes = [];
66
+ const secondEventTypes = [];
67
+ const stopFirst = firstClient.events.subscribe((event) => firstEventTypes.push(event.type));
68
+ const stopSecond = secondClient.events.subscribe((event) => secondEventTypes.push(event.type));
69
+ strict_1.default.equal(sources.length, 1);
70
+ sources[0].emit('presence.updated', { type: 'presence.updated', live: true });
71
+ strict_1.default.deepEqual(firstEventTypes, ['presence.updated']);
72
+ strict_1.default.deepEqual(secondEventTypes, ['presence.updated']);
73
+ stopFirst();
74
+ strict_1.default.equal(sources[0].closed, false);
75
+ stopSecond();
76
+ strict_1.default.equal(sources[0].closed, true);
77
+ });
78
+ (0, node_test_1.default)('core client ignores malformed events and maps stream events to bridge subscribers', () => {
79
+ const source = new FakeEventSource();
80
+ const events = [];
81
+ const bridgeContents = [];
82
+ const client = (0, client_js_1.createCoreClient)({
83
+ baseUrl: 'http://127.0.0.1:9831/api/local/v1',
84
+ eventSourceFactory: () => source,
85
+ });
86
+ const stopEvents = client.events.subscribe((event) => events.push(event.type));
87
+ const stopBridge = client.events.subscribeBridge((event) => bridgeContents.push(event.content || ''));
88
+ source.emit('stream.updated', '{not-json');
89
+ source.emit('stream.updated', {
90
+ type: 'stream.updated',
91
+ stream: { type: 'reply', sessionKey: 'workspace:thread', content: 'done' },
92
+ });
93
+ strict_1.default.deepEqual(events, ['stream.updated']);
94
+ strict_1.default.deepEqual(bridgeContents, ['done']);
95
+ stopBridge();
96
+ stopEvents();
97
+ });
98
+ (0, node_test_1.default)('core client ignores valid JSON events that do not match the event contract', () => {
99
+ const source = new FakeEventSource();
100
+ const events = [];
101
+ const client = (0, client_js_1.createCoreClient)({
102
+ baseUrl: 'http://127.0.0.1:9841/api/local/v1',
103
+ eventSourceFactory: () => source,
104
+ });
105
+ const stop = client.events.subscribe((event) => events.push(event.type));
106
+ source.emit('runtime.updated', { type: 'runtime.updated' });
107
+ source.emit('presence.updated', { type: 'presence.updated', live: 'yes' });
108
+ source.emit('stream.updated', { type: 'stream.updated', stream: { content: 'missing bridge type' } });
109
+ source.emit('presence.updated', { type: 'presence.updated', live: false });
110
+ strict_1.default.deepEqual(events, ['presence.updated']);
111
+ stop();
112
+ });
113
+ (0, node_test_1.default)('core client rejects events whose nested payload misses required contract fields', () => {
114
+ const source = new FakeEventSource();
115
+ const events = [];
116
+ const client = (0, client_js_1.createCoreClient)({
117
+ baseUrl: 'http://127.0.0.1:9831/api/local/v1',
118
+ eventSourceFactory: () => source,
119
+ });
120
+ const stop = client.events.subscribe((event) => events.push(event.type));
121
+ source.emit('run.updated', { type: 'run.updated', run: {} });
122
+ source.emit('message.created', { type: 'message.created', threadId: 'thread-1', message: {} });
123
+ source.emit('scheduler.run.updated', { type: 'scheduler.run.updated', run: { id: 'run-1' } });
124
+ source.emit('run.updated', {
125
+ type: 'run.updated',
126
+ run: {
127
+ id: 'run-1',
128
+ threadId: 'thread-1',
129
+ status: 'running',
130
+ startedAt: '2026-06-21T00:00:00.000Z',
131
+ updatedAt: '2026-06-21T00:00:01.000Z',
132
+ },
133
+ });
134
+ strict_1.default.deepEqual(events, ['run.updated']);
135
+ stop();
136
+ });
137
+ (0, node_test_1.default)('identical listener functions retain independent subscriptions', () => {
138
+ const source = new FakeEventSource();
139
+ let calls = 0;
140
+ const listener = () => {
141
+ calls += 1;
142
+ };
143
+ const client = (0, client_js_1.createCoreClient)({
144
+ baseUrl: 'http://127.0.0.1:9831/api/local/v1',
145
+ eventSourceFactory: () => source,
146
+ });
147
+ const stopFirst = client.events.subscribe(listener);
148
+ const stopSecond = client.events.subscribe(listener);
149
+ stopFirst();
150
+ strict_1.default.equal(source.closed, false);
151
+ source.emit('presence.updated', { type: 'presence.updated', live: true });
152
+ strict_1.default.equal(calls, 1);
153
+ stopSecond();
154
+ strict_1.default.equal(source.closed, true);
155
+ });
156
+ (0, node_test_1.default)('one failing event listener does not prevent other subscribers from receiving the event', () => {
157
+ const source = new FakeEventSource();
158
+ const events = [];
159
+ const client = (0, client_js_1.createCoreClient)({
160
+ baseUrl: 'http://127.0.0.1:9844/api/local/v1',
161
+ eventSourceFactory: () => source,
162
+ });
163
+ const stopFailing = client.events.subscribe(() => {
164
+ throw new Error('listener failed');
165
+ });
166
+ const stopHealthy = client.events.subscribe((event) => events.push(event.type));
167
+ source.emit('presence.updated', { type: 'presence.updated', live: true });
168
+ strict_1.default.deepEqual(events, ['presence.updated']);
169
+ stopFailing();
170
+ stopHealthy();
171
+ });
172
+ (0, node_test_1.default)('core client schedules only one reconnect while an error is outstanding', () => {
173
+ const sources = [];
174
+ const reconnects = [];
175
+ const client = (0, client_js_1.createCoreClient)({
176
+ baseUrl: 'http://127.0.0.1:9831/api/local/v1',
177
+ eventSourceFactory: () => {
178
+ const source = new FakeEventSource();
179
+ sources.push(source);
180
+ return source;
181
+ },
182
+ scheduleReconnect: (callback) => {
183
+ reconnects.push(callback);
184
+ return reconnects.length;
185
+ },
186
+ cancelReconnect: () => { },
187
+ });
188
+ const stop = client.events.subscribe(() => { });
189
+ sources[0].onerror?.();
190
+ sources[0].onerror?.();
191
+ strict_1.default.equal(reconnects.length, 1);
192
+ reconnects[0]();
193
+ strict_1.default.equal(sources.length, 2);
194
+ stop();
195
+ });
196
+ (0, node_test_1.default)('an obsolete event source cannot schedule another reconnect after replacement', () => {
197
+ const sources = [];
198
+ const reconnects = [];
199
+ const client = (0, client_js_1.createCoreClient)({
200
+ baseUrl: 'http://127.0.0.1:9842/api/local/v1',
201
+ eventSourceFactory: () => {
202
+ const source = new FakeEventSource();
203
+ sources.push(source);
204
+ return source;
205
+ },
206
+ scheduleReconnect: (callback) => {
207
+ reconnects.push(callback);
208
+ return reconnects.length;
209
+ },
210
+ cancelReconnect: () => { },
211
+ });
212
+ const stop = client.events.subscribe(() => { });
213
+ sources[0].onerror?.();
214
+ reconnects[0]();
215
+ sources[0].onerror?.();
216
+ strict_1.default.equal(reconnects.length, 1);
217
+ stop();
218
+ });
219
+ (0, node_test_1.default)('core client reports reconnect so consumers can recover missed state', () => {
220
+ const sources = [];
221
+ const reconnects = [];
222
+ const states = [];
223
+ const client = (0, client_js_1.createCoreClient)({
224
+ baseUrl: 'http://127.0.0.1:9845/api/local/v1',
225
+ eventSourceFactory: () => {
226
+ const source = new FakeEventSource();
227
+ sources.push(source);
228
+ return source;
229
+ },
230
+ scheduleReconnect: (callback) => {
231
+ reconnects.push(callback);
232
+ return reconnects.length;
233
+ },
234
+ cancelReconnect: () => { },
235
+ });
236
+ const stop = client.events.subscribeConnectionState((state) => states.push(state));
237
+ sources[0].onopen?.();
238
+ sources[0].onerror?.();
239
+ reconnects[0]();
240
+ sources[1].onopen?.();
241
+ strict_1.default.deepEqual(states, ['connected', 'disconnected', 'connected']);
242
+ stop();
243
+ strict_1.default.equal(sources[1].closed, true);
244
+ });
245
+ (0, node_test_1.default)('core client rejects partially populated scheduler and automation payloads', () => {
246
+ const source = new FakeEventSource();
247
+ const events = [];
248
+ const client = (0, client_js_1.createCoreClient)({
249
+ baseUrl: 'http://127.0.0.1:9843/api/local/v1',
250
+ eventSourceFactory: () => source,
251
+ });
252
+ const stop = client.events.subscribe((event) => events.push(event.type));
253
+ source.emit('scheduler.job.updated', {
254
+ type: 'scheduler.job.updated',
255
+ job: {
256
+ id: 'job-1',
257
+ workspaceId: 'workspace-1',
258
+ platform: 'local',
259
+ triggerType: 'cron',
260
+ promptTemplate: 'run',
261
+ enabled: true,
262
+ createdAt: '',
263
+ updatedAt: '',
264
+ },
265
+ });
266
+ source.emit('automation.monitor.updated', {
267
+ type: 'automation.monitor.updated',
268
+ monitor: {
269
+ id: 'monitor-1',
270
+ workspaceId: 'workspace-1',
271
+ title: 'price',
272
+ sourceType: 'stock.quote',
273
+ sourceConfig: {},
274
+ condition: {},
275
+ promptTemplate: 'analyze',
276
+ enabled: true,
277
+ cooldownMs: 1000,
278
+ createdAt: '',
279
+ updatedAt: '',
280
+ },
281
+ });
282
+ strict_1.default.deepEqual(events, []);
283
+ stop();
284
+ });
@@ -1021,6 +1021,60 @@ model = "deepseek-v4-flash"
1021
1021
  strict_1.default.match(response.body.error, /Unknown route/);
1022
1022
  strict_1.default.equal(response.body.errorInfo?.severity, 'error');
1023
1023
  });
1024
+ (0, node_test_1.default)('server rejects malformed endpoint input with a 400 response before domain dispatch', async () => {
1025
+ let dispatched = false;
1026
+ const controller = new node_events_1.EventEmitter();
1027
+ const workspaceRouter = {
1028
+ createThread: async () => {
1029
+ dispatched = true;
1030
+ return {};
1031
+ },
1032
+ };
1033
+ const server = new server_js_1.LocalAiCoreServer({ controller, workspaceRouter }, { port: 0 });
1034
+ const response = await invokeServer(server, 'POST', '/api/local/v1/threads', { workspaceId: 42 });
1035
+ strict_1.default.equal(response.statusCode, 400);
1036
+ strict_1.default.equal(response.body.ok, false);
1037
+ strict_1.default.match(response.body.error, /workspaceId/);
1038
+ strict_1.default.equal(dispatched, false);
1039
+ const emptyResponse = await invokeServer(server, 'POST', '/api/local/v1/threads', { workspaceId: ' ' });
1040
+ strict_1.default.equal(emptyResponse.statusCode, 400);
1041
+ strict_1.default.match(emptyResponse.body.error, /workspaceId/);
1042
+ strict_1.default.equal(dispatched, false);
1043
+ });
1044
+ (0, node_test_1.default)('server validates the actual desktop settings contract before dispatch', async () => {
1045
+ let dispatched = false;
1046
+ const controller = new node_events_1.EventEmitter();
1047
+ controller.saveSettings = async () => {
1048
+ dispatched = true;
1049
+ return {};
1050
+ };
1051
+ const server = new server_js_1.LocalAiCoreServer({ controller }, { port: 0 });
1052
+ const invalidKnowledge = await invokeServer(server, 'POST', '/api/local/v1/runtime/settings', { knowledge: 42 });
1053
+ strict_1.default.equal(invalidKnowledge.statusCode, 400);
1054
+ strict_1.default.match(invalidKnowledge.body.error, /knowledge/);
1055
+ const invalidPlugins = await invokeServer(server, 'POST', '/api/local/v1/runtime/settings', { plugins: [] });
1056
+ strict_1.default.equal(invalidPlugins.statusCode, 400);
1057
+ strict_1.default.match(invalidPlugins.body.error, /plugins/);
1058
+ const invalidPluginSettings = await invokeServer(server, 'POST', '/api/local/v1/runtime/settings', {
1059
+ plugins: { 'channel.lark': { enabled: 'yes' } },
1060
+ });
1061
+ strict_1.default.equal(invalidPluginSettings.statusCode, 400);
1062
+ strict_1.default.match(invalidPluginSettings.body.error, /plugins\.channel\.lark\.enabled/);
1063
+ const invalidAuthMode = await invokeServer(server, 'POST', '/api/local/v1/runtime/settings', {
1064
+ knowledge: { authMode: 'cookie' },
1065
+ });
1066
+ strict_1.default.equal(invalidAuthMode.statusCode, 400);
1067
+ strict_1.default.match(invalidAuthMode.body.error, /knowledge\.authMode/);
1068
+ strict_1.default.equal(dispatched, false);
1069
+ const valid = await invokeServer(server, 'POST', '/api/local/v1/runtime/settings', {
1070
+ autoStartService: true,
1071
+ defaultProject: 'workspace-stable',
1072
+ knowledge: { authMode: 'bearer', token: 'secret' },
1073
+ plugins: { 'channel.lark': { enabled: true, config: { appId: 'app-id' } } },
1074
+ });
1075
+ strict_1.default.equal(valid.statusCode, 200);
1076
+ strict_1.default.equal(dispatched, true);
1077
+ });
1024
1078
  (0, node_test_1.default)('server diagnostics routes dispatch through generic bindings', async () => {
1025
1079
  const calls = [];
1026
1080
  const controller = Object.assign(new node_events_1.EventEmitter(), {
@@ -31,6 +31,15 @@ const rootDir = node_process_1.default.cwd();
31
31
  strict_1.default.ok(buildIndex >= 0, 'pnpm e2e:smoke must start from a production build');
32
32
  strict_1.default.ok(smokeIndex > buildIndex, 'pnpm e2e:smoke must run smoke checks after the production build');
33
33
  });
34
+ (0, node_test_1.default)('development startup rewrites workspace aliases before launching Electron', () => {
35
+ const devScript = (0, node_fs_1.readFileSync)((0, node_path_1.join)(rootDir, 'scripts', 'dev.mjs'), 'utf8');
36
+ const aliasCommandIndex = devScript.indexOf("['exec', 'tsc-alias', '-p', 'tsconfig.electron.json']");
37
+ const readyAssignmentIndex = devScript.indexOf('electronReady = true', aliasCommandIndex);
38
+ const launchIndex = devScript.indexOf('maybeLaunchElectron()', readyAssignmentIndex);
39
+ strict_1.default.ok(aliasCommandIndex >= 0, 'pnpm dev must rewrite emitted @cc/* aliases');
40
+ strict_1.default.ok(readyAssignmentIndex > aliasCommandIndex, 'Electron must become ready only after alias rewriting is configured');
41
+ strict_1.default.ok(launchIndex > readyAssignmentIndex, 'Electron must launch only after alias rewriting completes');
42
+ });
34
43
  (0, node_test_1.default)('production renderer build has a loadable entry document and assets', () => {
35
44
  const rendererDir = (0, node_path_1.join)(rootDir, 'dist', 'renderer');
36
45
  const indexPath = (0, node_path_1.join)(rendererDir, 'index.html');
@@ -42,6 +42,37 @@ const env_utils_js_1 = require("../../services/local-ai-core/src/runtime/env-uti
42
42
  (0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
43
43
  }
44
44
  });
45
+ (0, node_test_1.default)('runtime project migration makes workspace registry authoritative and preserves identity across rename', async () => {
46
+ const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'workspace-project-migration-'));
47
+ try {
48
+ const runtime = (0, bootstrap_js_1.bootstrapLocalCoreRuntime)({ userDataPath, enableKnowledge: false, log: () => { } });
49
+ const controller = new local_core_controller_js_1.LocalCoreController(userDataPath, runtime);
50
+ await controller.saveRuntimeConfig({
51
+ projects: [{
52
+ name: 'Workspace A',
53
+ agent: { type: 'pi', options: { work_dir: '/tmp/workspace-a' } },
54
+ platforms: [],
55
+ }],
56
+ });
57
+ const first = await controller.readRuntimeConfig();
58
+ const workspaceId = first.config.projects?.[0]?.workspace_id;
59
+ strict_1.default.ok(workspaceId);
60
+ strict_1.default.equal(controller.store.getWorkspaceRegistryEntry(workspaceId)?.displayName, 'Workspace A');
61
+ strict_1.default.equal(controller.store.readRuntimeConfig().config.projects, undefined);
62
+ await controller.saveRuntimeConfig({
63
+ ...first.config,
64
+ projects: [{ ...first.config.projects[0], name: 'Workspace B' }],
65
+ });
66
+ const renamed = await controller.readRuntimeConfig();
67
+ strict_1.default.equal(renamed.config.projects?.[0]?.workspace_id, workspaceId);
68
+ strict_1.default.equal(controller.store.getWorkspaceRegistryEntry(workspaceId)?.displayName, 'Workspace B');
69
+ strict_1.default.equal((await controller.workspaceRouter.listWorkspaces())[0]?.id, workspaceId);
70
+ await controller.close();
71
+ }
72
+ finally {
73
+ (0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
74
+ }
75
+ });
45
76
  (0, node_test_1.default)('model providers persist independently from workspace config', () => {
46
77
  const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'model-provider-store-'));
47
78
  try {
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const strict_1 = __importDefault(require("node:assert/strict"));
7
+ const node_test_1 = __importDefault(require("node:test"));
8
+ const inbound_authorization_js_1 = require("../../services/local-ai-core/src/channel/shared/inbound-authorization.js");
9
+ function createStore() {
10
+ const authorizedUsers = [];
11
+ const pairings = [];
12
+ return {
13
+ authorizedUsers,
14
+ pairings,
15
+ store: {
16
+ expirePendingPairings() { },
17
+ getAuthorizedUser(workspaceId, platformUserId, platform) {
18
+ return authorizedUsers.find((row) => row.workspace_id === workspaceId &&
19
+ row.platform_user_id === platformUserId &&
20
+ row.platform === platform);
21
+ },
22
+ createAuthorizedUser(input) {
23
+ authorizedUsers.push(input);
24
+ },
25
+ listPendingPairings() {
26
+ return pairings;
27
+ },
28
+ createPairingRequest(input) {
29
+ pairings.push(input);
30
+ },
31
+ },
32
+ };
33
+ }
34
+ const identity = {
35
+ workspaceId: 'workspace-1',
36
+ platformKey: 'lark:default',
37
+ platformUserId: 'user-1',
38
+ chatId: 'chat-1',
39
+ displayName: 'User One',
40
+ };
41
+ (0, node_test_1.default)('shared inbound authorization auto-approves and returns the stored user', () => {
42
+ const fixture = createStore();
43
+ let changes = 0;
44
+ const result = (0, inbound_authorization_js_1.resolveInboundChannelAuthorization)({
45
+ store: fixture.store,
46
+ identity,
47
+ autoApprove: true,
48
+ authorizedUserIdPrefix: 'lark-user',
49
+ generatePairingCode: () => '123456',
50
+ onStateChanged: () => { changes += 1; },
51
+ });
52
+ strict_1.default.equal(result.status, 'authorized');
53
+ strict_1.default.equal(fixture.authorizedUsers.length, 1);
54
+ strict_1.default.equal(changes, 1);
55
+ });
56
+ (0, node_test_1.default)('shared inbound authorization reuses an existing pending pairing', () => {
57
+ const fixture = createStore();
58
+ fixture.pairings.push({
59
+ code: '654321',
60
+ workspace_id: 'workspace-1',
61
+ platform: 'lark:default',
62
+ platform_user_id: 'user-1',
63
+ chat_id: 'chat-1',
64
+ status: 'pending',
65
+ });
66
+ let generated = 0;
67
+ const result = (0, inbound_authorization_js_1.resolveInboundChannelAuthorization)({
68
+ store: fixture.store,
69
+ identity,
70
+ autoApprove: false,
71
+ authorizedUserIdPrefix: 'lark-user',
72
+ generatePairingCode: () => {
73
+ generated += 1;
74
+ return '123456';
75
+ },
76
+ });
77
+ strict_1.default.deepEqual(result, { status: 'pending', pairingCode: '654321' });
78
+ strict_1.default.equal(generated, 0);
79
+ strict_1.default.equal(fixture.pairings.length, 1);
80
+ });
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const strict_1 = __importDefault(require("node:assert/strict"));
7
+ const node_test_1 = __importDefault(require("node:test"));
8
+ const gateway_utils_js_1 = require("../../services/local-ai-core/src/channel/lark/gateway-utils.js");
9
+ (0, node_test_1.default)('lark gateway attachment utilities preserve content summaries and mime detection', () => {
10
+ strict_1.default.equal((0, gateway_utils_js_1.summarizeLarkInboundContentParts)([{ type: 'file', fileName: 'report.pdf' }]), '[File: report.pdf]');
11
+ strict_1.default.equal((0, gateway_utils_js_1.extractLarkHeaderMimeType)({ 'Content-Type': 'image/png; charset=binary' }), 'image/png');
12
+ strict_1.default.equal((0, gateway_utils_js_1.sniffLarkImageExtension)(Buffer.from([0x89, 0x50, 0x4e, 0x47])), 'png');
13
+ });
@@ -1265,7 +1265,7 @@ function findLarkPostMdText(content) {
1265
1265
  });
1266
1266
  strict_1.default.equal(sentMessages.length, 1);
1267
1267
  strict_1.default.equal(sentMessages[0]?.threadId, 'thread-1');
1268
- strict_1.default.match(sentMessages[0]?.content?.displayText, /\[User Message\]\n\[Image\]\n\[\/User Message\]/);
1268
+ strict_1.default.equal(sentMessages[0]?.content?.displayText, '[Image]');
1269
1269
  strict_1.default.deepEqual(sentMessages[0]?.content?.contentParts?.map((part) => part.type), ['text', 'image']);
1270
1270
  strict_1.default.equal(sentMessages[0]?.content?.contentParts?.[1]?.mimeType, 'image/png');
1271
1271
  strict_1.default.equal(sentMessages[0]?.content?.contentParts?.[1]?.data, pngBytes.toString('base64'));
@@ -1366,7 +1366,7 @@ function findLarkPostMdText(content) {
1366
1366
  });
1367
1367
  strict_1.default.equal(sentMessages.length, 1);
1368
1368
  strict_1.default.equal(sentMessages[0]?.threadId, 'thread-1');
1369
- strict_1.default.match(sentMessages[0]?.content?.displayText, /\[User Message\]\n\[File: report\.pdf\]\n\[\/User Message\]/);
1369
+ strict_1.default.equal(sentMessages[0]?.content?.displayText, '[File: report.pdf]');
1370
1370
  strict_1.default.deepEqual(sentMessages[0]?.content?.contentParts?.map((part) => part.type), ['text', 'file']);
1371
1371
  strict_1.default.equal(sentMessages[0]?.content?.contentParts?.[1]?.mimeType, 'application/pdf');
1372
1372
  strict_1.default.equal(sentMessages[0]?.content?.contentParts?.[1]?.data, undefined);
@@ -1494,7 +1494,7 @@ function findLarkPostMdText(content) {
1494
1494
  });
1495
1495
  strict_1.default.equal(sentMessages.length, 1);
1496
1496
  strict_1.default.equal(sentMessages[0]?.threadId, 'thread-1');
1497
- strict_1.default.match(sentMessages[0]?.content, /\[User Message\]\nask @张三 to review\n\[\/User Message\]/);
1497
+ strict_1.default.equal(sentMessages[0]?.content, 'ask @张三 to review');
1498
1498
  });
1499
1499
  (0, node_test_1.default)('lark group text messages ignore non-mentioned bot messages by default', async () => {
1500
1500
  const sentMessages = [];
@@ -1620,7 +1620,7 @@ function findLarkPostMdText(content) {
1620
1620
  });
1621
1621
  strict_1.default.equal(sentMessages.length, 1);
1622
1622
  strict_1.default.equal(sentMessages[0]?.threadId, 'thread-1');
1623
- strict_1.default.match(sentMessages[0]?.content, /\[User Message\]\n1\. hi\n2\. hello\n\[\/User Message\]/);
1623
+ strict_1.default.equal(sentMessages[0]?.content, '1. hi\n2. hello');
1624
1624
  });
1625
1625
  (0, node_test_1.default)('lark inbound messages create a chat binding when an authorized user has an old direct thread', async () => {
1626
1626
  const bindings = [];
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const strict_1 = __importDefault(require("node:assert/strict"));
7
+ const node_test_1 = __importDefault(require("node:test"));
8
+ const runtime_state_js_1 = require("../../services/local-ai-core/src/channel/weixin/runtime-state.js");
9
+ (0, node_test_1.default)('weixin turn state keeps thought, tool progress, and final reply ordered', () => {
10
+ const turn = (0, runtime_state_js_1.createWeixinTurnState)('workspace:thread');
11
+ (0, runtime_state_js_1.consumeWeixinBridgeEvent)(turn, { type: 'typing_start', sessionKey: turn.sessionKey });
12
+ (0, runtime_state_js_1.consumeWeixinBridgeEvent)(turn, { type: 'update_message', sessionKey: turn.sessionKey, bridgeKind: 'thought', content: 'Inspecting' });
13
+ (0, runtime_state_js_1.consumeWeixinBridgeEvent)(turn, { type: 'reply', sessionKey: turn.sessionKey, bridgeKind: 'tool', content: 'Search - running' });
14
+ const finalEvent = { type: 'reply', sessionKey: turn.sessionKey, bridgeKind: 'assistant', content: 'Done' };
15
+ (0, runtime_state_js_1.consumeWeixinBridgeEvent)(turn, finalEvent);
16
+ const rendered = (0, runtime_state_js_1.renderWeixinTurnText)(turn);
17
+ strict_1.default.match(rendered, /Inspecting/);
18
+ strict_1.default.match(rendered, /Done/);
19
+ strict_1.default.equal((0, runtime_state_js_1.isTerminalWeixinBridgeMessage)(finalEvent, rendered), true);
20
+ });
21
+ (0, node_test_1.default)('weixin permission events remain terminal and render fallback actions', () => {
22
+ const turn = (0, runtime_state_js_1.createWeixinTurnState)('workspace:thread');
23
+ const event = {
24
+ type: 'buttons',
25
+ sessionKey: turn.sessionKey,
26
+ buttonRows: [[{ text: 'Allow', data: 'allow' }]],
27
+ };
28
+ (0, runtime_state_js_1.consumeWeixinBridgeEvent)(turn, event);
29
+ const rendered = (0, runtime_state_js_1.renderWeixinTurnText)(turn);
30
+ strict_1.default.match(rendered, /allow all/);
31
+ strict_1.default.equal((0, runtime_state_js_1.isTerminalWeixinBridgeMessage)(event, rendered), true);
32
+ });
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const strict_1 = __importDefault(require("node:assert/strict"));
7
+ const node_test_1 = __importDefault(require("node:test"));
8
+ const text_utils_js_1 = require("../../services/local-ai-core/src/channel/weixin/text-utils.js");
9
+ (0, node_test_1.default)('weixin text utilities preserve utf8 boundaries and decode simple html', () => {
10
+ strict_1.default.equal((0, text_utils_js_1.stripWeixinHtml)('<p>A&amp;B</p>'), 'A&B');
11
+ const chunks = (0, text_utils_js_1.splitTextByUtf8Bytes)('你好世界', 6);
12
+ strict_1.default.deepEqual(chunks, ['你好', '世界']);
13
+ strict_1.default.ok(chunks.every((chunk) => (0, text_utils_js_1.utf8ByteLength)(chunk) <= 6));
14
+ strict_1.default.ok((0, text_utils_js_1.utf8ByteLength)((0, text_utils_js_1.truncateTextByUtf8Bytes)('很长的内容'.repeat(20), 80)) <= 80);
15
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kafca/agentdock",
3
- "version": "0.1.56",
3
+ "version": "0.1.57",
4
4
  "license": "PolyForm-Noncommercial-1.0.0",
5
5
  "type": "module",
6
6
  "main": "dist-electron/electron/main.js",
@@ -26,13 +26,14 @@
26
26
  "dev": "node scripts/dev.mjs",
27
27
  "dev:web": "pnpm exec vite --host 127.0.0.1 --port 5173",
28
28
  "dev:core": "pnpm build:electron && node scripts/launch-core.mjs",
29
- "build": "vite build && node scripts/write-electron-package.mjs && tsc -p tsconfig.electron.json",
29
+ "build": "vite build && node scripts/write-electron-package.mjs && tsc -p tsconfig.electron.json && tsc-alias -p tsconfig.electron.json",
30
30
  "build:npm": "VITE_LOCAL_AI_CORE_BASE=/api/local/v1 pnpm build",
31
31
  "build:web": "vite build",
32
32
  "build:renderer": "vite build",
33
- "build:electron": "node scripts/write-electron-package.mjs && tsc -p tsconfig.electron.json",
33
+ "build:electron": "node scripts/write-electron-package.mjs && tsc -p tsconfig.electron.json && tsc-alias -p tsconfig.electron.json",
34
34
  "build:core": "pnpm build:electron",
35
- "test": "pnpm build:renderer && pnpm build:electron && node --test dist-electron/tests/electron/*.test.js dist-electron/tests/contracts/*.test.js dist-electron/tests/integration/*.test.js dist-electron/packages/knowledge-api/test/*.test.js dist-electron/src/pages/Threads/thread-chat-permission.test.js",
35
+ "typecheck": "tsc -p tsconfig.json --noEmit",
36
+ "test": "pnpm typecheck && pnpm build:renderer && pnpm build:electron && node --test dist-electron/tests/electron/*.test.js dist-electron/tests/contracts/*.test.js dist-electron/tests/integration/*.test.js dist-electron/packages/knowledge-api/test/*.test.js dist-electron/src/pages/Threads/thread-chat-permission.test.js",
36
37
  "e2e:smoke": "pnpm build && node scripts/e2e-smoke.mjs",
37
38
  "e2e:compose": "node scripts/e2e-compose.mjs",
38
39
  "dist:mac": "pnpm build && electron-builder --mac dmg zip --arm64",
@@ -45,6 +46,9 @@
45
46
  },
46
47
  "dependencies": {
47
48
  "@agentclientprotocol/claude-agent-acp": "^0.30.0",
49
+ "@cc/core-sdk": "workspace:*",
50
+ "@cc/plugin-sdk": "workspace:*",
51
+ "@cc/superai-contracts": "workspace:*",
48
52
  "@iarna/toml": "^2.2.5",
49
53
  "@larksuiteoapi/node-sdk": "^1.58.0",
50
54
  "@mariozechner/pi-coding-agent": "^0.72.1",
@@ -78,6 +82,7 @@
78
82
  "electron-builder": "^26.8.1",
79
83
  "postcss": "^8.5.3",
80
84
  "tailwindcss": "^3.4.17",
85
+ "tsc-alias": "^1.8.17",
81
86
  "typescript": "~5.8.3",
82
87
  "vite": "^6.3.2"
83
88
  },