@kafca/agentdock 0.1.56 → 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.
- package/README.md +7 -0
- package/dist/renderer/assets/{Badge-DjcoXx2J.js → Badge-BfY1VaHS.js} +1 -1
- package/dist/renderer/assets/Card-DWA_Tww_.js +1 -0
- package/dist/renderer/assets/Config-nHj3g1U5.js +21 -0
- package/dist/renderer/assets/CronList-BwkA_I7v.js +1 -0
- package/dist/renderer/assets/Dashboard-D0_A7k02.js +41 -0
- package/dist/renderer/assets/{EmptyState-DIZLiccW.js → EmptyState-zatDjLj_.js} +1 -1
- package/dist/renderer/assets/HighlightedMarkdown-CsM5n70d.js +12 -0
- package/dist/renderer/assets/Input-R1XdFK1K.js +1 -0
- package/dist/renderer/assets/{KnowledgeDetail-CJ9IYOsa.js → KnowledgeDetail-Co5sxeGd.js} +2 -2
- package/dist/renderer/assets/{KnowledgeHome-BLGPwnBO.js → KnowledgeHome-DwziPw5m.js} +3 -3
- package/dist/renderer/assets/Logs-NwZUtR_G.js +6 -0
- package/dist/renderer/assets/{Modal-CQiUpfl4.js → Modal-CrcIwIFL.js} +3 -3
- package/dist/renderer/assets/MonitorList-CS1uLS5A.js +1 -0
- package/dist/renderer/assets/Page-Dp0obeSw.js +1 -0
- package/dist/renderer/assets/{Select-D6z65IT3.js → Select-6mVQaf84.js} +2 -2
- package/dist/renderer/assets/ThreadChat-BFzbn3L6.js +86 -0
- package/dist/renderer/assets/Workspace-DCmo8BMm.js +19 -0
- package/dist/renderer/assets/{arrow-left-CV5cL3f4.js → arrow-left-9rjg_Hp4.js} +1 -1
- package/dist/renderer/assets/{book-open-DThvB7pj.js → book-open-Bu8GCHnG.js} +1 -1
- package/dist/renderer/assets/channels-BxVbG-6j.js +6 -0
- package/dist/renderer/assets/chevron-down-BE8uQmWM.js +11 -0
- package/dist/renderer/assets/index-B7TeF6Es.js +41 -0
- package/dist/renderer/assets/index-BIKL3fTP.css +11 -0
- package/dist/renderer/assets/index-BkI9POxj.js +167 -0
- package/dist/renderer/assets/knowledge-Kl19SqGS.js +1 -0
- package/dist/renderer/assets/{pencil-Dv5WxhdC.js → pencil-CPB7SK1m.js} +1 -1
- package/dist/renderer/assets/{play-DnCnft83.js → play-DGAO4OCu.js} +1 -1
- package/dist/renderer/assets/{plus-DsxIagzS.js → plus-Bt26z-4q.js} +1 -1
- package/dist/renderer/assets/{save-CST01lIc.js → save-Une7GMxT.js} +1 -1
- package/dist/renderer/assets/{search-B_bqy6Wd.js → search-DE0agJjJ.js} +1 -1
- package/dist/renderer/assets/{shield-check-D6lG5Aoc.js → shield-check-De7xaXZh.js} +1 -1
- package/dist/renderer/assets/threads-BnsNL5ei.js +1 -0
- package/dist/renderer/assets/{trash-2-Cefngb6Q.js → trash-2-6iGF59Ac.js} +1 -1
- package/dist/renderer/index.html +2 -2
- package/dist-electron/packages/contracts/src/automation.js +2 -0
- package/dist-electron/packages/contracts/src/channels.js +2 -0
- package/dist-electron/packages/contracts/src/knowledge.js +2 -0
- package/dist-electron/packages/contracts/src/local-core.js +15 -0
- package/dist-electron/packages/contracts/src/runtime.js +2 -0
- package/dist-electron/packages/contracts/src/scheduler.js +2 -0
- package/dist-electron/packages/contracts/src/threads.js +2 -0
- package/dist-electron/packages/core-sdk/src/automation.js +32 -0
- package/dist-electron/packages/core-sdk/src/channels.js +121 -0
- package/dist-electron/packages/core-sdk/src/client.js +455 -0
- package/dist-electron/packages/core-sdk/src/index.js +43 -607
- package/dist-electron/packages/core-sdk/src/knowledge.js +85 -0
- package/dist-electron/packages/core-sdk/src/request.js +22 -0
- package/dist-electron/packages/core-sdk/src/runtime.js +214 -0
- package/dist-electron/packages/core-sdk/src/scheduler.js +32 -0
- package/dist-electron/packages/core-sdk/src/threads.js +67 -0
- package/dist-electron/packages/plugin-sdk/src/agents.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/automation.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/channels.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/index.js +21 -0
- package/dist-electron/packages/plugin-sdk/src/knowledge.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/runtime.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/scheduler.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/threads.js +2 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +5 -8
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-content.js +2 -2
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +3 -3
- package/dist-electron/services/local-ai-core/src/acp/store/agent-task-store.js +5 -5
- package/dist-electron/services/local-ai-core/src/acp/store/automation-monitor-store.js +12 -12
- package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +2 -2
- package/dist-electron/services/local-ai-core/src/acp/store/scheduler-store.js +11 -11
- package/dist-electron/services/local-ai-core/src/acp/store/security-store.js +3 -3
- package/dist-electron/services/local-ai-core/src/acp/store/thread-store.js +7 -7
- package/dist-electron/services/local-ai-core/src/acp/workspace-acp-permissions.js +2 -2
- package/dist-electron/services/local-ai-core/src/agents/claudecode/definition.js +3 -3
- package/dist-electron/services/local-ai-core/src/agents/codex/definition.js +3 -3
- package/dist-electron/services/local-ai-core/src/agents/localcore-acp/definition.js +2 -2
- package/dist-electron/services/local-ai-core/src/agents/localcore-acp/index.js +4 -4
- package/dist-electron/services/local-ai-core/src/agents/opencode/launch.js +2 -2
- package/dist-electron/services/local-ai-core/src/agents/pi/definition.js +2 -2
- package/dist-electron/services/local-ai-core/src/agents/pi/launch.js +3 -3
- package/dist-electron/services/local-ai-core/src/agents/pi/provider-materializer.js +1 -1
- package/dist-electron/services/local-ai-core/src/agents/shared/agent-plugin.js +4 -4
- package/dist-electron/services/local-ai-core/src/automation/automation-conversation-executor.js +6 -47
- package/dist-electron/services/local-ai-core/src/automation/automation-monitor-service.js +2 -5
- package/dist-electron/services/local-ai-core/src/channel/lark/cards.js +33 -18
- package/dist-electron/services/local-ai-core/src/channel/lark/config.js +2 -2
- package/dist-electron/services/local-ai-core/src/channel/lark/gateway-utils.js +91 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/inbound-handler.js +180 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +58 -539
- package/dist-electron/services/local-ai-core/src/channel/lark/outbound-transport.js +112 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/runtime-state.js +5 -20
- package/dist-electron/services/local-ai-core/src/channel/shared/base-channel-gateway.js +37 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/bridge-event-helpers.js +23 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/channel-keys.js +6 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/inbound-authorization.js +54 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/config.js +2 -2
- package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-media.js +21 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-poller.js +167 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +55 -512
- package/dist-electron/services/local-ai-core/src/channel/weixin/runtime-state.js +149 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/text-utils.js +92 -0
- package/dist-electron/services/local-ai-core/src/cli/lac.js +9 -11
- package/dist-electron/services/local-ai-core/src/cli/monitor-cli-parsers.js +2 -2
- package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +28 -70
- package/dist-electron/services/local-ai-core/src/kernel/local-core-errors.js +8 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-ai-vector-plugin.js +2 -2
- package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-noop-plugin.js +2 -2
- package/dist-electron/services/local-ai-core/src/router/workspace-bridge-event-stream.js +29 -0
- package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +5 -5
- package/dist-electron/services/local-ai-core/src/router/workspace-router.js +47 -60
- package/dist-electron/services/local-ai-core/src/runtime/agent-runtime-detector.js +5 -5
- package/dist-electron/services/local-ai-core/src/runtime/config-migration.js +6 -6
- package/dist-electron/services/local-ai-core/src/runtime/deployment-diagnostics.js +3 -3
- package/dist-electron/services/local-ai-core/src/runtime/external-service.js +3 -1
- package/dist-electron/services/local-ai-core/src/runtime/handlers/automation-handler.js +11 -2
- package/dist-electron/services/local-ai-core/src/runtime/handlers/channel-handler.js +12 -6
- package/dist-electron/services/local-ai-core/src/runtime/handlers/external-handler.js +10 -2
- package/dist-electron/services/local-ai-core/src/runtime/handlers/knowledge-handler.js +18 -6
- package/dist-electron/services/local-ai-core/src/runtime/handlers/provider-handler.js +7 -2
- package/dist-electron/services/local-ai-core/src/runtime/handlers/runtime-handler.js +28 -3
- package/dist-electron/services/local-ai-core/src/runtime/handlers/scheduler-handler.js +10 -2
- package/dist-electron/services/local-ai-core/src/runtime/handlers/security-handler.js +18 -5
- package/dist-electron/services/local-ai-core/src/runtime/handlers/task-handler.js +14 -2
- package/dist-electron/services/local-ai-core/src/runtime/handlers/thread-handler.js +18 -15
- package/dist-electron/services/local-ai-core/src/runtime/handlers/workspace-handler.js +13 -2
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +35 -8
- package/dist-electron/services/local-ai-core/src/runtime/request-validation.js +79 -0
- package/dist-electron/services/local-ai-core/src/runtime/runtime-detection-service.js +9 -9
- package/dist-electron/services/local-ai-core/src/runtime/server-helpers.js +10 -1
- package/dist-electron/services/local-ai-core/src/runtime/server.js +2 -1
- package/dist-electron/services/local-ai-core/src/runtime/workspace-project-registry.js +76 -0
- package/dist-electron/services/local-ai-core/src/sandbox/opensandbox-client.js +3 -2
- package/dist-electron/services/local-ai-core/src/sandbox/sandbox-config.js +8 -8
- package/dist-electron/services/local-ai-core/src/scheduler/base-channel-schedule-adapter.js +77 -0
- package/dist-electron/services/local-ai-core/src/scheduler/lark-schedule-adapter.js +13 -79
- package/dist-electron/services/local-ai-core/src/scheduler/local-schedule-adapter.js +2 -10
- package/dist-electron/services/local-ai-core/src/scheduler/run-polling.js +19 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-conversation-executor.js +3 -37
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-job-route.js +20 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduler-service.js +15 -28
- package/dist-electron/services/local-ai-core/src/scheduler/thread-resolution.js +12 -0
- package/dist-electron/services/local-ai-core/src/scheduler/weixin-schedule-adapter.js +13 -79
- package/dist-electron/services/local-ai-core/src/thread/agent-message-policy.js +75 -0
- package/dist-electron/shared/desktop.js +1 -64
- package/dist-electron/src/components/chat/chat-controller-state.js +60 -0
- package/dist-electron/src/components/chat/chat-event-gate.js +146 -0
- package/dist-electron/src/components/chat/markdown-code-block.js +8 -0
- package/dist-electron/src/pages/Desktop/workspace-model.js +212 -0
- package/dist-electron/src/pages/Threads/thread-chat-model.js +50 -51
- package/dist-electron/tests/contracts/agent-message-policy.test.js +21 -0
- package/dist-electron/tests/contracts/architecture-docs.test.js +56 -33
- package/dist-electron/tests/contracts/chat-event-gate.test.js +114 -0
- package/dist-electron/tests/contracts/chat-markdown.test.js +16 -0
- package/dist-electron/tests/contracts/thread-task-state.test.js +32 -0
- package/dist-electron/tests/contracts/workspace-identity.test.js +23 -0
- package/dist-electron/tests/electron/core-client.test.js +284 -0
- package/dist-electron/tests/electron/plugin-kernel.test.js +54 -0
- package/dist-electron/tests/electron/renderer-packaging.test.js +9 -0
- package/dist-electron/tests/electron/workspace-task-store.test.js +31 -0
- package/dist-electron/tests/integration/channel-inbound-authorization.test.js +80 -0
- package/dist-electron/tests/integration/lark-gateway-utils.test.js +13 -0
- package/dist-electron/tests/integration/lark-gateway.test.js +4 -4
- package/dist-electron/tests/integration/local-core-refactor.test.js +15 -8
- package/dist-electron/tests/integration/weixin-runtime-state.test.js +32 -0
- package/dist-electron/tests/integration/weixin-text-utils.test.js +15 -0
- package/package.json +9 -4
- package/dist/renderer/assets/Chat-C5Bkm9-M.js +0 -2
- package/dist/renderer/assets/ChatMarkdown-uc36EzyD.js +0 -45
- package/dist/renderer/assets/Config-DHtQuuLy.js +0 -21
- package/dist/renderer/assets/CronList-BYUnhzSC.js +0 -1
- package/dist/renderer/assets/Dashboard-BPnGMDg3.js +0 -26
- package/dist/renderer/assets/Logs-Dyd2Uwlt.js +0 -1
- package/dist/renderer/assets/MonitorList-Byg3E3Gt.js +0 -1
- package/dist/renderer/assets/Page-7DxXvTMm.js +0 -1
- package/dist/renderer/assets/ProjectDetail-Dfr5s0Ja.js +0 -11
- package/dist/renderer/assets/ProjectList-CDDQjAQ_.js +0 -1
- package/dist/renderer/assets/SessionChat-s7CAaCPL.js +0 -1
- package/dist/renderer/assets/SessionList-D-OycKKS.js +0 -1
- package/dist/renderer/assets/ThreadChat-CLdFynB5.js +0 -28
- package/dist/renderer/assets/Workspace-xfT5z4j_.js +0 -19
- package/dist/renderer/assets/bot-CWQ5-ovl.js +0 -6
- package/dist/renderer/assets/check-DKM7zfWG.js +0 -6
- package/dist/renderer/assets/chevron-down-Dfw2KU87.js +0 -6
- package/dist/renderer/assets/circle-CoP4RA4s.js +0 -6
- package/dist/renderer/assets/desktop-CsDYrOOU.js +0 -1
- package/dist/renderer/assets/desktop-JQkhNOF4.js +0 -5
- package/dist/renderer/assets/funnel-DpVLlG3g.js +0 -6
- package/dist/renderer/assets/heart-BMD36ejP.js +0 -6
- package/dist/renderer/assets/index-COxSYBjE.js +0 -182
- package/dist/renderer/assets/index-CTGTI-cm.js +0 -41
- package/dist/renderer/assets/index-CjCuR6DI.css +0 -11
- package/dist/renderer/assets/projects-DgjHcNgt.js +0 -1
- package/dist/renderer/assets/server-ecH4GNwa.js +0 -11
- package/dist/renderer/assets/session-utils-Dd_WKMYW.js +0 -6
- package/dist/renderer/assets/sessions-BQ33Mv4k.js +0 -1
- package/dist/renderer/assets/user-D_8RSH-T.js +0 -6
- package/dist/renderer/assets/wifi-off-DB9D-pOu.js +0 -11
- package/dist-electron/services/local-ai-core/src/scheduler/lark-execution-policies.js +0 -13
- package/dist-electron/services/local-ai-core/src/scheduler/weixin-execution-policies.js +0 -13
- package/dist-electron/src/api/client.js +0 -73
- package/dist-electron/src/api/sessions.js +0 -21
- package/dist-electron/src/lib/session-utils.js +0 -51
- package/dist-electron/src/pages/Projects/project-provider-config.js +0 -75
- package/dist-electron/tests/electron/project-provider-config.test.js +0 -71
|
@@ -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.
|
|
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.
|
|
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.
|
|
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.
|
|
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 = [];
|
|
@@ -12,7 +12,14 @@ const local_core_acp_response_processor_js_1 = require("../../services/local-ai-
|
|
|
12
12
|
const local_core_slash_commands_js_1 = require("../../services/local-ai-core/src/acp/local-core-slash-commands.js");
|
|
13
13
|
const scheduled_conversation_executor_js_1 = require("../../services/local-ai-core/src/scheduler/scheduled-conversation-executor.js");
|
|
14
14
|
const scheduler_run_lifecycle_js_1 = require("../../services/local-ai-core/src/scheduler/scheduler-run-lifecycle.js");
|
|
15
|
-
const
|
|
15
|
+
const channel_execution_policy_js_1 = require("../../services/local-ai-core/src/scheduler/channel-execution-policy.js");
|
|
16
|
+
const createLarkExecutionPolicy = (job, options, resolveSameThread, preferredAgentType) => (0, channel_execution_policy_js_1.createChannelExecutionPolicy)(job, options, {
|
|
17
|
+
platformBase: 'lark',
|
|
18
|
+
resolveSameThread,
|
|
19
|
+
sideThreadTitle: (nextJob) => `[Scheduled:Lark] ${nextJob.description || nextJob.id}`,
|
|
20
|
+
legacySideThreadTitles: (nextJob) => [`[Scheduled] ${nextJob.description || nextJob.id}`],
|
|
21
|
+
preferredAgentType,
|
|
22
|
+
});
|
|
16
23
|
const local_schedule_adapter_js_1 = require("../../services/local-ai-core/src/scheduler/local-schedule-adapter.js");
|
|
17
24
|
const cards_js_1 = require("../../services/local-ai-core/src/channel/lark/cards.js");
|
|
18
25
|
const session_command_runtime_js_1 = require("../../services/local-ai-core/src/channel/shared/session-command-runtime.js");
|
|
@@ -820,7 +827,7 @@ const thread_slash_command_dispatcher_js_1 = require("../../services/local-ai-co
|
|
|
820
827
|
let registeredBridge;
|
|
821
828
|
const bridgeEvents = [];
|
|
822
829
|
let unregisteredBridge = false;
|
|
823
|
-
const policy =
|
|
830
|
+
const policy = createLarkExecutionPolicy(job, {
|
|
824
831
|
store: {},
|
|
825
832
|
workspaceRouter: {
|
|
826
833
|
getThreadSessionKey: (threadId) => `session:${threadId}`,
|
|
@@ -876,7 +883,7 @@ const thread_slash_command_dispatcher_js_1 = require("../../services/local-ai-co
|
|
|
876
883
|
updatedAt: '2026-04-22T06:00:00.000Z',
|
|
877
884
|
};
|
|
878
885
|
const createThreadCalls = [];
|
|
879
|
-
const policy =
|
|
886
|
+
const policy = createLarkExecutionPolicy(job, {
|
|
880
887
|
store: {},
|
|
881
888
|
workspaceRouter: {
|
|
882
889
|
getThreadSessionKey: (threadId) => `session:${threadId}`,
|
|
@@ -916,7 +923,7 @@ const thread_slash_command_dispatcher_js_1 = require("../../services/local-ai-co
|
|
|
916
923
|
updatedAt: '2026-04-22T06:00:00.000Z',
|
|
917
924
|
};
|
|
918
925
|
const createThreadCalls = [];
|
|
919
|
-
const policy =
|
|
926
|
+
const policy = createLarkExecutionPolicy(job, {
|
|
920
927
|
store: {},
|
|
921
928
|
workspaceRouter: {
|
|
922
929
|
getThreadSessionKey: (threadId) => `session:${threadId}`,
|
|
@@ -958,7 +965,7 @@ const thread_slash_command_dispatcher_js_1 = require("../../services/local-ai-co
|
|
|
958
965
|
updatedAt: '2026-04-22T06:00:00.000Z',
|
|
959
966
|
};
|
|
960
967
|
let created = false;
|
|
961
|
-
const policy =
|
|
968
|
+
const policy = createLarkExecutionPolicy(job, {
|
|
962
969
|
store: {},
|
|
963
970
|
workspaceRouter: {
|
|
964
971
|
getThreadSessionKey: (threadId) => `session:${threadId}`,
|
|
@@ -995,7 +1002,7 @@ const thread_slash_command_dispatcher_js_1 = require("../../services/local-ai-co
|
|
|
995
1002
|
updatedAt: '2026-04-22T06:00:00.000Z',
|
|
996
1003
|
};
|
|
997
1004
|
const createThreadCalls = [];
|
|
998
|
-
const policy =
|
|
1005
|
+
const policy = createLarkExecutionPolicy(job, {
|
|
999
1006
|
store: {},
|
|
1000
1007
|
workspaceRouter: {
|
|
1001
1008
|
getThreadSessionKey: (threadId) => `session:${threadId}`,
|
|
@@ -1036,7 +1043,7 @@ const thread_slash_command_dispatcher_js_1 = require("../../services/local-ai-co
|
|
|
1036
1043
|
updatedAt: '2026-04-22T06:00:00.000Z',
|
|
1037
1044
|
};
|
|
1038
1045
|
const createThreadCalls = [];
|
|
1039
|
-
const policy =
|
|
1046
|
+
const policy = createLarkExecutionPolicy(job, {
|
|
1040
1047
|
store: {},
|
|
1041
1048
|
workspaceRouter: {
|
|
1042
1049
|
getThreadSessionKey: (threadId) => `session:${threadId}`,
|
|
@@ -1079,7 +1086,7 @@ const thread_slash_command_dispatcher_js_1 = require("../../services/local-ai-co
|
|
|
1079
1086
|
updatedAt: '2026-04-22T06:00:00.000Z',
|
|
1080
1087
|
};
|
|
1081
1088
|
let registeredBridge;
|
|
1082
|
-
const policy =
|
|
1089
|
+
const policy = createLarkExecutionPolicy(job, {
|
|
1083
1090
|
store: {},
|
|
1084
1091
|
workspaceRouter: {
|
|
1085
1092
|
getThreadSessionKey: (threadId) => `session:${threadId}`,
|
|
@@ -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&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.
|
|
3
|
+
"version": "0.1.58",
|
|
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
|
-
"
|
|
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
|
},
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{u as ze,y as Me,r as n,j as s,C as pe,I as ye,M as U,B as C,g as ee,R as De,T as Ae}from"./index-COxSYBjE.js";import{M as be}from"./Modal-CQiUpfl4.js";import{E as $}from"./EmptyState-DIZLiccW.js";import{C as Le,A as Be}from"./ChatMarkdown-uc36EzyD.js";import{l as Ke}from"./projects-DgjHcNgt.js";import{l as Ue,g as $e,s as qe,a as je,r as Fe,d as Oe}from"./sessions-BQ33Mv4k.js";import{s as We,a as we,b as w,L as _,t as He}from"./session-utils-Dd_WKMYW.js";import{S as Ve}from"./search-B_bqy6Wd.js";import{P as Ge}from"./pencil-Dv5WxhdC.js";import{T as Je}from"./trash-2-Cefngb6Q.js";import{B as Qe}from"./bot-CWQ5-ovl.js";import{U as Xe}from"./user-D_8RSH-T.js";import"./index-CTGTI-cm.js";import"./check-DKM7zfWG.js";const Ye=1500,Ze=9e4;function es(a){return String(a||"").startsWith("web:")}function ss(a){return(a||[]).map((d,y)=>({id:`${d.timestamp||y}-${d.role}-${y}`,role:d.role==="user"?"user":"assistant",content:d.content,timestamp:d.timestamp,kind:d.kind}))}function ts(a){return a.map(d=>`${d.role}:${d.kind||"final"}:${d.timestamp||""}:${d.content}`).join(`
|
|
2
|
-
`)}function as(a){return a.filter(d=>d.role!=="user").length}function rs(a,d){var y;return(y=a.last_message)!=null&&y.content?a.last_message.content.replace(/\n/g," "):d("sessions.noMessages")}function ve(a){return(a instanceof Error?a.message:String(a||"")).trim().toLowerCase().includes("no active session found")}function ns(a,d){return(a instanceof Error?a.message:String(a||"")).trim().toLowerCase()?ve(a)?d("sessions.sessionUnavailable"):a instanceof Error?a.message:d("sessions.sendFailed"):d("sessions.sendFailed")}function js(){const{t:a}=ze(),[d,y]=Me(),[se,ke]=n.useState([]),[te,ae]=n.useState({}),[i,G]=n.useState(d.get("project")||""),[b,R]=n.useState([]),[r,h]=n.useState(null),[I,v]=n.useState([]),[J,re]=n.useState(""),[T,Q]=n.useState(""),[Ne,ne]=n.useState(!0),[Se,ie]=n.useState(!1),[Ce,le]=n.useState(!1),[X,oe]=n.useState(!1),[E,P]=n.useState("idle"),[de,k]=n.useState(""),[z,q]=n.useState(null),[F,Y]=n.useState(""),[M,O]=n.useState(null),[ce,W]=n.useState(null),me=n.useRef(null),x=n.useRef({project:"",sessionId:""}),H=n.useRef(null),V=n.useRef(null),j=d.get("project")||"",D=d.get("session")||"",ue=n.useMemo(()=>new Set(Object.values(te)),[te]),N=n.useMemo(()=>{const e=J.trim().toLowerCase();return e?b.filter(t=>We(t,e)):b},[J,b]),A=!!(r&&(r.live||ue.has(r.id))),Ee=!!(i&&A&&T.trim()&&!X&&E!=="sending"&&E!=="activating"&&E!=="polling"),f=n.useCallback((e,t)=>{const l=new URLSearchParams;e&&l.set("project",e),t&&l.set("session",t),y(l,{replace:!0})},[y]),c=n.useCallback((e="idle")=>{H.current&&(window.clearTimeout(H.current),H.current=null),V.current=null,P(e)},[]),xe=n.useCallback(e=>{R(t=>{const l=t.some(o=>o.id===e.id)?t.map(o=>o.id===e.id?{...o,...e}:o):[...t,e];return we(l)})},[]),fe=n.useCallback(async()=>{ne(!0);try{const{projects:e}=await Ke();ke(e||[])}finally{ne(!1)}},[]),u=n.useCallback(async e=>{if(!e)return R([]),ae({}),[];ie(!0);try{const{sessions:t,active_keys:l}=await Ue(e),o=we((t||[]).filter(m=>!es(m.session_key)));return ae(l||{}),x.current.project===e&&R(o),o}finally{ie(!1)}},[]),S=n.useCallback(async(e,t,l)=>{if(!e||!t)return h(null),v([]),null;l!=null&&l.silent||le(!0);try{const o=await $e(e,t,200);return x.current.project!==e||x.current.sessionId!==t||(xe(o),h({id:o.id,project:e,sessionKey:o.session_key,name:o.name||w(o),live:o.live,isDraft:!1,detail:o}),v(ss(o.history)),k("")),o}catch(o){return x.current.project===e&&x.current.sessionId===t&&k(o instanceof Error?o.message:a("sessions.loadFailed")),null}finally{l!=null&&l.silent||le(!1)}},[xe,a]),Z=n.useCallback(e=>{V.current=e,H.current=window.setTimeout(async()=>{const t=V.current;if(!t)return;if(Date.now()-t.startedAt>=Ze){c("timed_out"),k(a("sessions.pollTimeout")),await u(t.project);return}const l=await S(t.project,t.sessionId,{silent:!0});if(!l||!V.current){c(),await u(t.project);return}if(x.current.project!==t.project||x.current.sessionId!==t.sessionId){c();return}const o=ts(l.history),m=as(l.history)>t.assistantCountBefore,g=m&&o===t.lastSignature?t.stableCount+1:0,K={...t,lastSignature:o,stableCount:g};if(m&&g>=2){c(),await u(t.project);return}P("polling"),Z(K)},Ye)},[S,u,c,a]),he=n.useCallback((e,t,l)=>{c(),P("polling"),Z({project:e,sessionId:t,assistantCountBefore:l,stableCount:0,lastSignature:"",startedAt:Date.now()})},[Z,c]),Pe=n.useCallback(async e=>{if(c(),G(e),re(""),k(""),Q(""),!e){x.current={project:"",sessionId:""},h(null),v([]),R([]),f("");return}x.current={project:e,sessionId:""},h(null),v([]),f(e),await u(e)},[u,c,f]),L=n.useCallback(async e=>{if(e.isDraft||e.live||!e.id)return e;P("activating");try{await qe(e.project,{session_key:e.sessionKey,session_id:e.id}),await u(e.project);const t=await S(e.project,e.id,{silent:!0}),l={...e,live:(t==null?void 0:t.live)??!0,isDraft:!1,detail:t??e.detail,name:(t==null?void 0:t.name)||e.name};return h(l),l}finally{P("idle")}},[S,u]),B=n.useCallback(async(e,t)=>{c(),k(""),x.current={project:e,sessionId:t.id},G(e),f(e,t.id),h({id:t.id,project:e,sessionKey:t.session_key,name:w(t),live:t.live,isDraft:!1,detail:null});const l=await S(e,t.id);l&&!l.live&&await L({id:l.id,project:e,sessionKey:l.session_key,name:l.name||w(l),live:l.live,isDraft:!1,detail:l})},[L,S,c,f]),_e=n.useCallback(async()=>{c(),i&&(await u(i),r!=null&&r.id&&(x.current={project:i,sessionId:r.id},await S(i,r.id)))},[r==null?void 0:r.id,S,u,i,c]),ge=n.useCallback(async()=>{if(!T.trim()||!i)return;if(!A){k(a("sessions.sessionUnavailable"));return}const e=T.trim(),t=`${crypto.randomUUID()}-user`,l={id:t,role:"user",content:e,timestamp:new Date().toISOString()};Q(""),oe(!0),P("sending"),k("");try{const o=r||N[0];if(!o)throw new Error(a("sessions.noAvailableChatTarget"));let m=r&&r.id===o.id?r:{id:o.id,project:i,sessionKey:"session_key"in o?o.session_key:o.sessionKey,name:"session_key"in o?w(o):o.name,live:o.live,isDraft:!1,detail:null};(!r||r.id!==m.id)&&(x.current={project:i,sessionId:m.id},f(i,m.id),h(m)),m=await L(m),v(p=>[...p,l]);try{await je(i,{session_key:m.sessionKey,message:e})}catch(p){if(!ve(p)||!m.id)throw p;m=await L({...m,live:!1}),await je(i,{session_key:m.sessionKey,message:e})}const g=m.id;if(!g)throw new Error(a("sessions.createFailed"));const K=I.filter(p=>p.role!=="user").length;x.current={project:i,sessionId:g},h(p=>p&&{...p,id:g,isDraft:!1}),f(i,g),he(i,g,K),await u(i)}catch(o){c(),v(g=>g.filter(K=>K.id!==t));const m=ns(o,a);k(m)}finally{oe(!1)}},[r,A,L,T,N,I,u,i,he,c,a,f]),Re=n.useCallback(async()=>{if(!(!z||!i||!F.trim())){W("rename");try{await Fe(i,z.id,{name:F.trim()});const t=(await u(i)).find(l=>l.id===z.id);t&&(r==null?void 0:r.id)===t.id&&h(l=>l&&{...l,name:w(t)}),q(null),Y("")}finally{W(null)}}},[r==null?void 0:r.id,u,F,z,i]),Ie=n.useCallback(async()=>{if(!(!M||!i)){W("delete");try{await Oe(i,M.id);const e=await u(i);(r==null?void 0:r.id)===M.id&&(c(),x.current={project:i,sessionId:""},h(null),v([]),f(i)),e.length===0&&v([]),O(null)}finally{W(null)}}},[r==null?void 0:r.id,M,u,i,c,f]);n.useEffect(()=>{fe()},[fe]),n.useEffect(()=>{j&&(i&&i===j||G(j))},[j,i]),n.useEffect(()=>{if(!i){R([]);return}x.current.project=i,u(i)},[u,i]),n.useEffect(()=>{!i||D||r!=null&&r.id||N.length===0||B(i,N[0])},[r==null?void 0:r.id,N,B,D,i]),n.useEffect(()=>{if(!j||!D||i!==j)return;const e=b.find(t=>t.id===D);if(!e){b.length>0&&f(j,b[0].id);return}(r==null?void 0:r.id)!==e.id&&B(j,e)},[r==null?void 0:r.id,B,j,D,i,b,f]),n.useEffect(()=>{var e;(e=me.current)==null||e.scrollIntoView({behavior:"smooth"})},[I]),n.useEffect(()=>()=>c(),[c]);const Te=(r==null?void 0:r.name)||a("sessions.activeChat");return s.jsxs("div",{className:"grid min-h-[calc(100vh-8rem)] grid-cols-1 gap-4 xl:grid-cols-[22rem_minmax(0,1fr)] animate-fade-in",children:[s.jsxs(pe,{className:"flex flex-col gap-4 border-gray-200/80 bg-[#fbfbfd] p-4 shadow-none xl:h-[calc(100vh-8rem)] xl:overflow-hidden dark:border-white/[0.08] dark:bg-[#111214]",children:[s.jsx("div",{className:"flex items-center gap-3",children:s.jsxs("div",{className:"flex-1",children:[s.jsx("p",{className:"text-xs font-medium uppercase tracking-[0.2em] text-gray-400",children:a("sessions.selectProject")}),s.jsxs("select",{value:i,onChange:e=>void Pe(e.target.value),className:"mt-2 w-full rounded-[18px] border border-gray-300/90 bg-white px-3 py-2 text-sm text-gray-900 transition-all focus:border-primary/40 focus:outline-none focus:ring-2 focus:ring-primary/10 dark:border-white/[0.1] dark:bg-[rgba(0,0,0,0.45)] dark:text-white",children:[s.jsx("option",{value:"",children:a("sessions.allProjects")}),se.map(e=>s.jsx("option",{value:e.name,children:e.name},e.name))]})]})}),s.jsxs("div",{className:"relative",children:[s.jsx(ye,{value:J,onChange:e=>re(e.target.value),placeholder:a("common.search"),className:"pl-9","aria-label":a("common.search")}),s.jsx(Ve,{size:16,className:"pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-gray-400"})]}),s.jsxs("div",{className:"flex min-h-0 flex-1 flex-col overflow-hidden",children:[s.jsxs("div",{className:"mb-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400",children:[s.jsx("span",{children:a("sessions.historyTitle")}),s.jsx("span",{children:N.length})]}),s.jsx("div",{className:"min-h-0 flex-1 overflow-y-auto space-y-2 pr-1",children:Ne?s.jsx("div",{className:"flex h-32 items-center justify-center text-gray-400",children:s.jsx(_,{className:"animate-spin",size:18})}):i?Se&&b.length===0?s.jsx("div",{className:"flex h-32 items-center justify-center text-gray-400",children:s.jsx(_,{className:"animate-spin",size:18})}):b.length===0?s.jsx($,{message:a("sessions.noSessions"),icon:U}):N.length===0?s.jsx($,{message:a("sessions.noSessions"),icon:U}):N.map(e=>{const t=e.id===(r==null?void 0:r.id);return s.jsxs("div",{className:ee("rounded-[18px] border p-3 transition-all",t?"border-primary/25 bg-primary/5":"border-gray-200/80 bg-white hover:border-gray-300 dark:border-white/[0.08] dark:bg-white/[0.03]"),children:[s.jsxs("button",{type:"button",onClick:()=>void B(i,e),className:"w-full text-left","data-testid":"web-chat-session-open",children:[s.jsxs("div",{className:"flex items-start justify-between gap-2",children:[s.jsxs("div",{className:"min-w-0",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx("span",{className:"truncate text-sm font-medium text-gray-900 dark:text-white",children:w(e)}),e.live||ue.has(e.id)?s.jsx("span",{className:"rounded-full bg-primary/10 px-2 py-0.5 text-[10px] text-primary",children:"live"}):s.jsx("span",{className:"rounded-full bg-gray-100 px-2 py-0.5 text-[10px] text-gray-400 dark:bg-white/[0.06] dark:text-gray-500",children:"history"})]}),s.jsx("p",{className:"mt-1 truncate text-xs text-gray-500 dark:text-gray-400",children:He(e.updated_at||e.created_at,a("sessions.justNow"))})]}),s.jsx("span",{className:"shrink-0 text-[10px] text-gray-400",children:e.history_count})]}),s.jsx("p",{className:"mt-2 line-clamp-2 text-xs text-gray-500 dark:text-gray-400",children:rs(e,a)})]}),s.jsxs("div",{className:"mt-3 flex items-center justify-end gap-1",children:[s.jsx(C,{size:"sm",variant:"ghost",onClick:()=>{q({id:e.id,name:w(e)}),Y(w(e))},"data-testid":"web-chat-session-rename",children:s.jsx(Ge,{size:14})}),s.jsx(C,{size:"sm",variant:"ghost",onClick:()=>O({id:e.id,name:w(e)}),"data-testid":"web-chat-session-delete",children:s.jsx(Je,{size:14})})]})]},e.id)}):s.jsx($,{message:a("sessions.projectRequired"),icon:U})})]})]}),s.jsxs(pe,{className:"flex min-h-[32rem] flex-col border-gray-200/80 bg-white p-0 shadow-none xl:h-[calc(100vh-8rem)] dark:border-white/[0.08] dark:bg-[#0b0d10]",children:[s.jsxs("div",{className:"flex items-center justify-between gap-3 border-b border-gray-200/80 px-5 py-4 dark:border-white/[0.08]",children:[s.jsxs("div",{className:"min-w-0",children:[s.jsx("div",{className:"flex items-center gap-2",children:s.jsx("h2",{className:"truncate text-lg font-semibold text-gray-900 dark:text-white",children:Te})}),s.jsx("p",{className:"mt-1 truncate text-sm text-gray-500 dark:text-gray-400",children:r?r.project:a("sessions.sendHint")})]}),s.jsxs(C,{size:"sm",variant:"secondary",onClick:()=>void _e(),"data-testid":"web-chat-refresh",children:[s.jsx(De,{size:14})," ",a("common.refresh")]})]}),s.jsx("div",{className:"flex-1 overflow-y-auto px-5 py-5",children:i?Ce?s.jsx("div",{className:"flex h-full items-center justify-center text-gray-400",children:s.jsx(_,{className:"animate-spin",size:22})}):I.length===0?s.jsx("div",{className:"flex h-full items-center justify-center",children:s.jsx($,{message:a(r?"sessions.noMessages":"sessions.sendHint"),icon:U})}):s.jsxs("div",{className:"mx-auto max-w-4xl space-y-5",children:[I.map(e=>{const t=e.role==="user";return s.jsxs("div",{className:ee("flex gap-3",t?"justify-end":"justify-start"),children:[!t&&s.jsx("div",{className:"mt-1 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[#f5f5f7] dark:bg-white/[0.06]",children:s.jsx(Qe,{size:16,className:"text-primary"})}),s.jsx("div",{className:ee("max-w-[78%] rounded-[20px] px-5 py-3.5 text-sm",t?"chat-user-glass rounded-br-sm text-slate-950 dark:text-slate-50":"rounded-bl-sm border border-gray-200 bg-[#fbfbfd] text-gray-900 dark:border-white/[0.08] dark:bg-[rgba(255,255,255,0.04)] dark:text-gray-100"),children:s.jsx(Le,{content:e.content,isUser:t})}),t&&s.jsx("div",{className:"mt-1 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[#f0f0f0] dark:bg-white/[0.08]",children:s.jsx(Xe,{size:16,className:"text-gray-500 dark:text-gray-300"})})]},e.id)}),s.jsx("div",{ref:me})]}):s.jsx("div",{className:"flex h-full items-center justify-center",children:s.jsx($,{message:a("sessions.emptySelection"),icon:U})})}),s.jsxs("div",{className:"border-t border-gray-200/80 px-5 py-4 dark:border-white/[0.08]",children:[de&&s.jsx("div",{className:"mb-3 rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-600 dark:border-red-900/40 dark:bg-red-950/20 dark:text-red-300",children:de}),E==="polling"&&s.jsxs("div",{className:"mb-3 flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400",children:[s.jsx(_,{size:14,className:"animate-spin"}),s.jsx("span",{children:a("sessions.waitingForReply")})]}),E==="activating"&&s.jsxs("div",{className:"mb-3 flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400",children:[s.jsx(_,{size:14,className:"animate-spin"}),s.jsx("span",{children:a("sessions.preparingChat")})]}),s.jsx("div",{className:"mx-auto max-w-4xl",children:s.jsxs("div",{className:"relative",children:[s.jsx(Ae,{value:T,onChange:e=>Q(e.target.value),onKeyDown:e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),ge())},rows:3,placeholder:a(i?"sessions.messageInput":"sessions.projectRequired"),disabled:!i||!A||X||E==="polling"||E==="activating",className:"min-h-[104px] rounded-[22px] border-gray-200 bg-[#fbfbfd] px-4 pb-16 pt-3 text-[15px] leading-6 dark:border-white/[0.08] dark:bg-[rgba(255,255,255,0.04)] sm:min-h-[112px] sm:px-5 sm:pt-4","data-testid":"web-chat-input"}),s.jsx(C,{onClick:()=>void ge(),disabled:!Ee,size:"icon","aria-label":a("sessions.send"),className:"absolute bottom-3 right-3 h-11 w-11 rounded-full bg-primary px-0 text-white shadow-none hover:bg-[#0071e3] disabled:bg-slate-300 disabled:text-white disabled:opacity-100 dark:bg-primary dark:text-white dark:hover:bg-[#2997ff] dark:disabled:bg-white/20 dark:disabled:text-white/55 sm:h-12 sm:w-12","data-testid":"web-chat-send",children:X?s.jsx(_,{size:18,className:"animate-spin"}):s.jsx(Be,{size:22,strokeWidth:2.2})})]})}),!A&&r&&s.jsx("div",{className:"mt-3 rounded-xl border border-gray-200 bg-gray-50 px-4 py-3 text-sm text-gray-500 dark:border-white/[0.08] dark:bg-white/[0.03] dark:text-gray-400",children:a("sessions.notLiveHint")})]})]}),s.jsx(be,{open:!!z,onClose:()=>q(null),title:a("sessions.renameTitle"),children:s.jsxs("div",{className:"space-y-4",children:[s.jsx(ye,{value:F,onChange:e=>Y(e.target.value),placeholder:a("sessions.renamePlaceholder"),"data-testid":"web-chat-rename-input"}),s.jsxs("div",{className:"flex justify-end gap-2",children:[s.jsx(C,{variant:"secondary",onClick:()=>q(null),children:a("common.cancel")}),s.jsx(C,{onClick:()=>void Re(),loading:ce==="rename","data-testid":"web-chat-rename-save",children:a("common.save")})]})]})}),s.jsx(be,{open:!!M,onClose:()=>O(null),title:a("sessions.deleteConfirmTitle"),children:s.jsxs("div",{className:"space-y-4",children:[s.jsx("p",{className:"text-sm text-gray-500 dark:text-gray-400",children:a("sessions.deleteConfirmBody")}),s.jsxs("div",{className:"flex justify-end gap-2",children:[s.jsx(C,{variant:"secondary",onClick:()=>O(null),children:a("common.cancel")}),s.jsx(C,{variant:"danger",onClick:()=>void Ie(),loading:ce==="delete","data-testid":"web-chat-delete-confirm",children:a("common.delete")})]})]})})]})}export{js as default};
|