@kafca/agentdock 0.1.30 → 0.1.33

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 (110) hide show
  1. package/LICENSE.md +73 -0
  2. package/README.md +15 -0
  3. package/dist/renderer/assets/{Badge-DlVJI1Ys.js → Badge-VeSLCPPV.js} +1 -1
  4. package/dist/renderer/assets/{Chat-oa8OjaHQ.js → Chat-DWTQeTgn.js} +1 -1
  5. package/dist/renderer/assets/{ChatMarkdown-C-N8KS5C.js → ChatMarkdown-C9gSQIVb.js} +1 -1
  6. package/dist/renderer/assets/{Config-D9sL_d4D.js → Config-CTA-pZNR.js} +1 -1
  7. package/dist/renderer/assets/{CronList-Z5JU3DHk.js → CronList-BngBCnFY.js} +1 -1
  8. package/dist/renderer/assets/{Dashboard-D3BwbG43.js → Dashboard-D4pGvDpc.js} +2 -2
  9. package/dist/renderer/assets/{EmptyState-QOj765Ul.js → EmptyState-DMf8rzDs.js} +1 -1
  10. package/dist/renderer/assets/{KnowledgeDetail-J7n01mPu.js → KnowledgeDetail-C1Ym_cHk.js} +1 -1
  11. package/dist/renderer/assets/{KnowledgeHome-BFnH0NVk.js → KnowledgeHome-DPRiR72G.js} +1 -1
  12. package/dist/renderer/assets/{Logs-DfSUifXc.js → Logs-CRHecmzO.js} +1 -1
  13. package/dist/renderer/assets/{Modal-QjEGhyru.js → Modal-BDhhPv2l.js} +1 -1
  14. package/dist/renderer/assets/{Page-qdHFSw7x.js → Page-DdDZN7AE.js} +1 -1
  15. package/dist/renderer/assets/{ProjectDetail-DS_rfvhh.js → ProjectDetail-DCsr3LkW.js} +1 -1
  16. package/dist/renderer/assets/{ProjectList-COtyZd7H.js → ProjectList-Cnm-iLvg.js} +1 -1
  17. package/dist/renderer/assets/{Select-BQ8mncVu.js → Select-Dw4FCXhJ.js} +1 -1
  18. package/dist/renderer/assets/{SessionChat-DjVnjuQy.js → SessionChat-O-6abK8x.js} +1 -1
  19. package/dist/renderer/assets/{SessionList-88dgGZJ8.js → SessionList-5yptvVL9.js} +1 -1
  20. package/dist/renderer/assets/ThreadChat-CIM_o2HO.js +23 -0
  21. package/dist/renderer/assets/{Workspace-D_hzSJjX.js → Workspace-D9UeUCNr.js} +1 -1
  22. package/dist/renderer/assets/{arrow-left-BMpknulW.js → arrow-left-CKfxNOXE.js} +1 -1
  23. package/dist/renderer/assets/{book-open-CiaOeQbU.js → book-open-CQddlENV.js} +1 -1
  24. package/dist/renderer/assets/{check-CgwYH4GF.js → check-CZYvOmIS.js} +1 -1
  25. package/dist/renderer/assets/{chevron-down-BzD2S1OO.js → chevron-down-CVIWFoXF.js} +1 -1
  26. package/dist/renderer/assets/{circle-BDHD7g7l.js → circle-DSfdQM7k.js} +1 -1
  27. package/dist/renderer/assets/{desktop-BiR5LPL5.js → desktop-B9KUgeOV.js} +1 -1
  28. package/dist/renderer/assets/{desktop-BkMW-h5p.js → desktop-O8_6ZCVZ.js} +2 -2
  29. package/dist/renderer/assets/{funnel-Bruf5FYA.js → funnel-pB5NegZB.js} +1 -1
  30. package/dist/renderer/assets/{heart-D7Mz04B0.js → heart-BT5laZ_b.js} +1 -1
  31. package/dist/renderer/assets/{index-CL1e8m3U.js → index-BYyDk28K.js} +2 -2
  32. package/dist/renderer/assets/{index-gZIRr4_o.js → index-zTUUYax3.js} +1 -1
  33. package/dist/renderer/assets/{pencil-C6gzDMse.js → pencil-C0thxLi6.js} +1 -1
  34. package/dist/renderer/assets/{play-DqTXX-Pr.js → play-CmZ0kWtt.js} +1 -1
  35. package/dist/renderer/assets/{plug-ykmbeaO3.js → plug-CeDQatBe.js} +1 -1
  36. package/dist/renderer/assets/{plus-DHE60vMX.js → plus-Di__xFOZ.js} +1 -1
  37. package/dist/renderer/assets/projects-B-pbhhtH.js +1 -0
  38. package/dist/renderer/assets/{save-CGIvrdQI.js → save-BDatCjfO.js} +1 -1
  39. package/dist/renderer/assets/{search-D7IFAwyE.js → search-DnTOjP0C.js} +1 -1
  40. package/dist/renderer/assets/{server-aOsirp7I.js → server-Ey_iHY6m.js} +1 -1
  41. package/dist/renderer/assets/{session-utils-Dxfp4ohQ.js → session-utils-DWaM7Rkr.js} +1 -1
  42. package/dist/renderer/assets/{sessions-Db1XPbG2.js → sessions-CYYjLD5I.js} +1 -1
  43. package/dist/renderer/assets/{shield-check-ChXeQK-d.js → shield-check-Br8BQzcn.js} +1 -1
  44. package/dist/renderer/assets/{trash-2-CfN-c1zw.js → trash-2-7YD616fw.js} +1 -1
  45. package/dist/renderer/assets/{user-C7OHaBp4.js → user-BR_5jmr9.js} +1 -1
  46. package/dist/renderer/assets/{wifi-off-CpaJigye.js → wifi-off-By9QdREz.js} +1 -1
  47. package/dist/renderer/index.html +1 -1
  48. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +28 -4
  49. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-response-processor.js +2 -4
  50. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +102 -15
  51. package/dist-electron/services/local-ai-core/src/agents/claudecode/behavior.js +5 -0
  52. package/dist-electron/services/local-ai-core/src/agents/claudecode/definition.js +36 -0
  53. package/dist-electron/services/local-ai-core/src/agents/claudecode/index.js +15 -0
  54. package/dist-electron/services/local-ai-core/src/agents/codex/behavior.js +5 -0
  55. package/dist-electron/services/local-ai-core/src/agents/codex/definition.js +24 -0
  56. package/dist-electron/services/local-ai-core/src/agents/codex/index.js +15 -0
  57. package/dist-electron/services/local-ai-core/src/agents/hermes/behavior.js +29 -0
  58. package/dist-electron/services/local-ai-core/src/agents/hermes/definition.js +22 -0
  59. package/dist-electron/services/local-ai-core/src/agents/hermes/index.js +15 -0
  60. package/dist-electron/services/local-ai-core/src/agents/index.js +98 -0
  61. package/dist-electron/services/local-ai-core/src/agents/localcore-acp/behavior.js +5 -0
  62. package/dist-electron/services/local-ai-core/src/agents/localcore-acp/definition.js +14 -0
  63. package/dist-electron/services/local-ai-core/src/agents/localcore-acp/index.js +27 -0
  64. package/dist-electron/services/local-ai-core/src/agents/opencode/behavior.js +5 -0
  65. package/dist-electron/services/local-ai-core/src/agents/opencode/definition.js +18 -0
  66. package/dist-electron/services/local-ai-core/src/agents/opencode/index.js +15 -0
  67. package/dist-electron/services/local-ai-core/src/agents/opencode/launch.js +119 -0
  68. package/dist-electron/services/local-ai-core/src/agents/pi/behavior.js +5 -0
  69. package/dist-electron/services/local-ai-core/src/agents/pi/definition.js +23 -0
  70. package/dist-electron/services/local-ai-core/src/agents/pi/index.js +15 -0
  71. package/dist-electron/services/local-ai-core/src/agents/pi/launch.js +139 -0
  72. package/dist-electron/services/local-ai-core/src/agents/shared/acp-behavior.js +11 -0
  73. package/dist-electron/services/local-ai-core/src/agents/shared/agent-plugin.js +60 -0
  74. package/dist-electron/services/local-ai-core/src/agents/shared/definition.js +12 -0
  75. package/dist-electron/services/local-ai-core/src/agents/shared/launch-utils.js +122 -0
  76. package/dist-electron/services/local-ai-core/src/agents/shared/progress-replay.js +19 -0
  77. package/dist-electron/services/local-ai-core/src/agents/shared/replay-prefix.js +68 -0
  78. package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +0 -2
  79. package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +0 -1
  80. package/dist-electron/services/local-ai-core/src/cli/lac.js +2 -1
  81. package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +17 -11
  82. package/dist-electron/services/local-ai-core/src/plugins/builtin/agent-localcore-acp-plugin.js +9 -130
  83. package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +22 -397
  84. package/dist-electron/services/local-ai-core/src/runtime/agent-runtime-detector.js +9 -45
  85. package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +9 -4
  86. package/dist-electron/services/local-ai-core/src/runtime/local-core-runtime-state.js +62 -1
  87. package/dist-electron/services/local-ai-core/src/runtime/runtime-detection-service.js +2 -12
  88. package/dist-electron/services/local-ai-core/src/scheduler/lark-schedule-adapter.js +16 -7
  89. package/dist-electron/services/local-ai-core/src/scheduler/local-schedule-adapter.js +10 -2
  90. package/dist-electron/services/local-ai-core/src/scheduler/scheduled-job-route.js +24 -0
  91. package/dist-electron/services/local-ai-core/src/scheduler/weixin-schedule-adapter.js +15 -6
  92. package/dist-electron/shared/desktop.js +3 -1
  93. package/dist-electron/src/pages/Threads/thread-chat-model.js +27 -18
  94. package/dist-electron/src/pages/Threads/thread-chat-permission.test.js +57 -18
  95. package/dist-electron/{electron → tests/contracts}/local-core-contracts.test.js +1 -1
  96. package/dist-electron/{electron → tests/electron}/agent-runtime-detector.test.js +31 -1
  97. package/dist-electron/{electron → tests/electron}/lac-cli.test.js +6 -3
  98. package/dist-electron/{electron → tests/electron}/plugin-kernel.test.js +93 -13
  99. package/dist-electron/{electron → tests/electron}/renderer-packaging.test.js +11 -6
  100. package/dist-electron/{electron → tests/electron}/runtime-detection-service.test.js +1 -1
  101. package/dist-electron/{electron → tests/electron}/security-approval-store.test.js +2 -2
  102. package/dist-electron/{electron → tests/electron}/workspace-task-store.test.js +95 -7
  103. package/dist-electron/{electron → tests/integration}/channel-content.test.js +2 -2
  104. package/dist-electron/{electron → tests/integration}/local-core-acp-content.test.js +1 -1
  105. package/dist-electron/{electron → tests/integration}/local-core-refactor.test.js +437 -15
  106. package/package.json +3 -2
  107. package/dist/renderer/assets/ThreadChat-BCdbTxBo.js +0 -23
  108. package/dist/renderer/assets/projects-Bx5p10th.js +0 -1
  109. /package/dist-electron/{electron → tests/contracts}/architecture-docs.test.js +0 -0
  110. /package/dist-electron/{electron → tests/electron}/knowledge-skill-script.test.js +0 -0
@@ -9,21 +9,21 @@ const node_fs_1 = require("node:fs");
9
9
  const node_os_1 = require("node:os");
10
10
  const node_path_1 = require("node:path");
11
11
  const node_stream_1 = require("node:stream");
12
- const local_core_acp_response_processor_js_1 = require("../services/local-ai-core/src/acp/local-core-acp-response-processor.js");
13
- const local_core_slash_commands_js_1 = require("../services/local-ai-core/src/acp/local-core-slash-commands.js");
14
- const scheduled_conversation_executor_js_1 = require("../services/local-ai-core/src/scheduler/scheduled-conversation-executor.js");
15
- const scheduler_run_lifecycle_js_1 = require("../services/local-ai-core/src/scheduler/scheduler-run-lifecycle.js");
16
- const lark_execution_policies_js_1 = require("../services/local-ai-core/src/scheduler/lark-execution-policies.js");
17
- const local_schedule_adapter_js_1 = require("../services/local-ai-core/src/scheduler/local-schedule-adapter.js");
18
- const local_core_weixin_gateway_js_1 = require("../services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js");
19
- const local_core_lark_gateway_js_1 = require("../services/local-ai-core/src/channel/lark/local-core-lark-gateway.js");
20
- const runtime_state_js_1 = require("../services/local-ai-core/src/channel/lark/runtime-state.js");
21
- const local_core_acp_turn_coordinator_js_1 = require("../services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js");
22
- const local_core_acp_store_js_1 = require("../services/local-ai-core/src/acp/local-core-acp-store.js");
23
- const local_core_acp_progress_js_1 = require("../services/local-ai-core/src/acp/local-core-acp-progress.js");
24
- const local_core_acp_permission_lifecycle_js_1 = require("../services/local-ai-core/src/acp/local-core-acp-permission-lifecycle.js");
25
- const workspace_acp_permissions_js_1 = require("../services/local-ai-core/src/acp/workspace-acp-permissions.js");
26
- const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server-routes.js");
12
+ const local_core_acp_response_processor_js_1 = require("../../services/local-ai-core/src/acp/local-core-acp-response-processor.js");
13
+ const local_core_slash_commands_js_1 = require("../../services/local-ai-core/src/acp/local-core-slash-commands.js");
14
+ const scheduled_conversation_executor_js_1 = require("../../services/local-ai-core/src/scheduler/scheduled-conversation-executor.js");
15
+ const scheduler_run_lifecycle_js_1 = require("../../services/local-ai-core/src/scheduler/scheduler-run-lifecycle.js");
16
+ const lark_execution_policies_js_1 = require("../../services/local-ai-core/src/scheduler/lark-execution-policies.js");
17
+ const local_schedule_adapter_js_1 = require("../../services/local-ai-core/src/scheduler/local-schedule-adapter.js");
18
+ const local_core_weixin_gateway_js_1 = require("../../services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js");
19
+ const local_core_lark_gateway_js_1 = require("../../services/local-ai-core/src/channel/lark/local-core-lark-gateway.js");
20
+ const runtime_state_js_1 = require("../../services/local-ai-core/src/channel/lark/runtime-state.js");
21
+ const local_core_acp_turn_coordinator_js_1 = require("../../services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js");
22
+ const local_core_acp_store_js_1 = require("../../services/local-ai-core/src/acp/local-core-acp-store.js");
23
+ const local_core_acp_progress_js_1 = require("../../services/local-ai-core/src/acp/local-core-acp-progress.js");
24
+ const local_core_acp_permission_lifecycle_js_1 = require("../../services/local-ai-core/src/acp/local-core-acp-permission-lifecycle.js");
25
+ const workspace_acp_permissions_js_1 = require("../../services/local-ai-core/src/acp/workspace-acp-permissions.js");
26
+ const server_routes_js_1 = require("../../services/local-ai-core/src/runtime/server-routes.js");
27
27
  (0, node_test_1.default)('local core route parser separates runtime refresh and runtime detail routes', () => {
28
28
  strict_1.default.deepEqual((0, server_routes_js_1.parseLocalAiCoreRoute)('GET', '/api/local/v1/runtimes'), { name: 'runtimes.list' });
29
29
  strict_1.default.deepEqual((0, server_routes_js_1.parseLocalAiCoreRoute)('POST', '/api/local/v1/runtimes/refresh'), { name: 'runtimes.refresh' });
@@ -955,6 +955,56 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
955
955
  ]]);
956
956
  strict_1.default.equal(session.pendingPermissionByRun.get('run-1')?.options[1]?.optionId, 'approve-always');
957
957
  });
958
+ (0, node_test_1.default)('Hermes ACP permission options respect allow_permanent false', () => {
959
+ const emitted = [];
960
+ const coordinator = new local_core_acp_turn_coordinator_js_1.LocalCoreAcpTurnCoordinator({
961
+ appendMessage: () => { },
962
+ emitBridge: (event) => emitted.push(event),
963
+ updateRunStatus: () => { },
964
+ sendRaw: () => true,
965
+ });
966
+ const session = {
967
+ threadId: 'thread-1',
968
+ bridgeSessionKey: 'session:thread-1',
969
+ currentRunId: 'run-1',
970
+ currentTurn: {
971
+ runId: 'run-1',
972
+ replyCtx: 'run-1',
973
+ previewHandle: 'preview-1',
974
+ assistantText: '',
975
+ typingStarted: true,
976
+ previewStarted: false,
977
+ permission: null,
978
+ agentType: 'hermes',
979
+ },
980
+ pendingPermissionByRun: new Map(),
981
+ loadReplayMode: false,
982
+ schedulerJobCreatedByRun: new Map(),
983
+ };
984
+ coordinator.handleAgentRequest(session, {
985
+ method: 'session/request_permission',
986
+ id: 42,
987
+ params: {
988
+ allow_permanent: false,
989
+ toolCall: {
990
+ title: 'Terminal',
991
+ parameters: {
992
+ command: 'system_profiler SPHardwareDataType',
993
+ },
994
+ },
995
+ options: [
996
+ { optionId: 'approve-once', name: 'Allow once', kind: 'allow' },
997
+ { optionId: 'approve-always', name: 'Always allow', kind: 'allow' },
998
+ { optionId: 'reject', name: 'Reject', kind: 'reject' },
999
+ ],
1000
+ },
1001
+ });
1002
+ strict_1.default.deepEqual(emitted[0]?.buttonRows, [[
1003
+ { text: 'allow', data: 'allow' },
1004
+ { text: 'deny', data: 'deny' },
1005
+ ]]);
1006
+ strict_1.default.deepEqual(session.pendingPermissionByRun.get('run-1')?.options.map((option) => option.optionId), ['approve-once', 'reject']);
1007
+ });
958
1008
  (0, node_test_1.default)('ACP yolo mode auto-selects permission requests without rendering cards', () => {
959
1009
  const emitted = [];
960
1010
  const appended = [];
@@ -1113,6 +1163,355 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
1113
1163
  strict_1.default.equal(emitted[0]?.content, 'tool scoped transcript');
1114
1164
  strict_1.default.equal(session.currentTurn.assistantText, 'final answer');
1115
1165
  });
1166
+ (0, node_test_1.default)('Hermes ACP assistant chunks strip restored history replay inside its own behavior', () => {
1167
+ const emitted = [];
1168
+ const coordinator = new local_core_acp_turn_coordinator_js_1.LocalCoreAcpTurnCoordinator({
1169
+ appendMessage: () => { },
1170
+ emitBridge: (event) => emitted.push(event),
1171
+ updateRunStatus: () => { },
1172
+ sendRaw: () => true,
1173
+ });
1174
+ const session = {
1175
+ threadId: 'thread-1',
1176
+ bridgeSessionKey: 'session:thread-1',
1177
+ currentRunId: 'run-1',
1178
+ currentTurn: {
1179
+ runId: 'run-1',
1180
+ replyCtx: 'run-1',
1181
+ previewHandle: 'preview-1',
1182
+ agentType: 'hermes',
1183
+ assistantText: '',
1184
+ rawAssistantText: '',
1185
+ priorAssistantFinalMessages: ['Hi! 😊 How can I help you today?', '我是 Hermes Agent。'],
1186
+ typingStarted: true,
1187
+ previewStarted: false,
1188
+ permission: null,
1189
+ },
1190
+ loadReplayMode: false,
1191
+ schedulerJobCreatedByRun: new Map(),
1192
+ };
1193
+ for (const text of ['Hi! 😊 How can I help you today?', '我是 Hermes Agent。', '确认删除前需要你确认。']) {
1194
+ coordinator.handleAgentNotification(session, {
1195
+ method: 'session/update',
1196
+ params: {
1197
+ update: {
1198
+ sessionUpdate: 'agent_message_chunk',
1199
+ content: { type: 'text', text },
1200
+ },
1201
+ },
1202
+ });
1203
+ }
1204
+ strict_1.default.equal(session.currentTurn.assistantText, '确认删除前需要你确认。');
1205
+ strict_1.default.deepEqual(emitted.map((event) => event.content), ['确认删除前需要你确认。']);
1206
+ });
1207
+ (0, node_test_1.default)('Hermes ACP assistant chunks strip replay even when stored prior final is already polluted', () => {
1208
+ const emitted = [];
1209
+ const coordinator = new local_core_acp_turn_coordinator_js_1.LocalCoreAcpTurnCoordinator({
1210
+ appendMessage: () => { },
1211
+ emitBridge: (event) => emitted.push(event),
1212
+ updateRunStatus: () => { },
1213
+ sendRaw: () => true,
1214
+ });
1215
+ const previousCleanFinal = '你确定要删除 **Sisyphus_介绍.txt** 这个文件吗?删除后无法恢复。确认的话我马上执行。';
1216
+ const pollutedStoredFinal = [
1217
+ 'Hi! How can I help you today?',
1218
+ '我是 Hermes Agent,你的 AI 助手。',
1219
+ '好的,让我看看你的桌面文件。',
1220
+ previousCleanFinal,
1221
+ ].join('');
1222
+ const session = {
1223
+ threadId: 'thread-1',
1224
+ bridgeSessionKey: 'session:thread-1',
1225
+ currentRunId: 'run-1',
1226
+ currentTurn: {
1227
+ runId: 'run-1',
1228
+ replyCtx: 'run-1',
1229
+ previewHandle: 'preview-1',
1230
+ agentType: 'hermes',
1231
+ assistantText: '',
1232
+ rawAssistantText: '',
1233
+ priorAssistantFinalMessages: [pollutedStoredFinal],
1234
+ typingStarted: true,
1235
+ previewStarted: false,
1236
+ permission: null,
1237
+ },
1238
+ loadReplayMode: false,
1239
+ schedulerJobCreatedByRun: new Map(),
1240
+ };
1241
+ for (const text of [
1242
+ 'Hi! How can I help you today?',
1243
+ '我是 Hermes Agent,你的 AI 助手。',
1244
+ '好的,让我看看你的桌面文件。',
1245
+ previousCleanFinal,
1246
+ '已删除 **Sisyphus_介绍.txt**,现在 Text 文件夹是空的了。',
1247
+ ]) {
1248
+ coordinator.handleAgentNotification(session, {
1249
+ method: 'session/update',
1250
+ params: {
1251
+ update: {
1252
+ sessionUpdate: 'agent_message_chunk',
1253
+ content: { type: 'text', text },
1254
+ },
1255
+ },
1256
+ });
1257
+ }
1258
+ strict_1.default.equal(session.currentTurn.assistantText, '已删除 **Sisyphus_介绍.txt**,现在 Text 文件夹是空的了。');
1259
+ strict_1.default.deepEqual(emitted.map((event) => event.content), ['已删除 **Sisyphus_介绍.txt**,现在 Text 文件夹是空的了。']);
1260
+ });
1261
+ (0, node_test_1.default)('Hermes ACP assistant chunks keep a fresh answer when no replay anchor is present', () => {
1262
+ const emitted = [];
1263
+ const coordinator = new local_core_acp_turn_coordinator_js_1.LocalCoreAcpTurnCoordinator({
1264
+ appendMessage: () => { },
1265
+ emitBridge: (event) => emitted.push(event),
1266
+ updateRunStatus: () => { },
1267
+ sendRaw: () => true,
1268
+ });
1269
+ const session = {
1270
+ threadId: 'thread-1',
1271
+ bridgeSessionKey: 'session:thread-1',
1272
+ currentRunId: 'run-1',
1273
+ currentTurn: {
1274
+ runId: 'run-1',
1275
+ replyCtx: 'run-1',
1276
+ previewHandle: 'preview-1',
1277
+ agentType: 'hermes',
1278
+ assistantText: '',
1279
+ rawAssistantText: '',
1280
+ priorAssistantFinalMessages: ['上一轮已经污染的历史,但是它不会出现在这次新回复里。'],
1281
+ typingStarted: true,
1282
+ previewStarted: false,
1283
+ permission: null,
1284
+ },
1285
+ loadReplayMode: false,
1286
+ schedulerJobCreatedByRun: new Map(),
1287
+ };
1288
+ coordinator.handleAgentNotification(session, {
1289
+ method: 'session/update',
1290
+ params: {
1291
+ update: {
1292
+ sessionUpdate: 'agent_message_chunk',
1293
+ content: { type: 'text', text: '已删除文件。' },
1294
+ },
1295
+ },
1296
+ });
1297
+ strict_1.default.equal(session.currentTurn.assistantText, '已删除文件。');
1298
+ strict_1.default.deepEqual(emitted.map((event) => event.content), ['已删除文件。']);
1299
+ });
1300
+ (0, node_test_1.default)('Hermes ACP progress updates suppress restored tool and thought replay only', () => {
1301
+ const upserted = [];
1302
+ const emitted = [];
1303
+ const coordinator = new local_core_acp_turn_coordinator_js_1.LocalCoreAcpTurnCoordinator({
1304
+ appendMessage: () => strict_1.default.fail('tool updates should be upserted'),
1305
+ upsertMessage: (_threadId, id, _role, content, _kind, _toolCall, bridgeKind) => {
1306
+ upserted.push({ id, content, bridgeKind });
1307
+ },
1308
+ emitBridge: (event) => emitted.push(event),
1309
+ updateRunStatus: () => { },
1310
+ sendRaw: () => true,
1311
+ });
1312
+ const session = {
1313
+ threadId: 'thread-1',
1314
+ bridgeSessionKey: 'session:thread-1',
1315
+ currentRunId: 'run-1',
1316
+ currentTurn: {
1317
+ runId: 'run-1',
1318
+ replyCtx: 'run-1',
1319
+ previewHandle: 'preview-1',
1320
+ thoughtPreviewHandle: 'thought-preview-1',
1321
+ thoughtMessageId: 'run-1-thought-1',
1322
+ agentType: 'hermes',
1323
+ assistantText: '',
1324
+ thoughtText: '',
1325
+ thoughtSequence: 1,
1326
+ typingStarted: true,
1327
+ previewStarted: false,
1328
+ thoughtPreviewStarted: false,
1329
+ priorAssistantProgressMessages: [
1330
+ {
1331
+ kind: 'tool',
1332
+ content: '🔧 terminal: rm ~/Desktop/Text/Sisyphus_介绍.txt: completed - terminal result\n- **exit_code:** 0',
1333
+ },
1334
+ {
1335
+ kind: 'thought',
1336
+ content: 'The user confirmed they want to delete the file. Let me delete it.',
1337
+ },
1338
+ ],
1339
+ permission: null,
1340
+ },
1341
+ loadReplayMode: false,
1342
+ schedulerJobCreatedByRun: new Map(),
1343
+ };
1344
+ coordinator.handleAgentNotification(session, {
1345
+ method: 'session/update',
1346
+ params: {
1347
+ update: {
1348
+ sessionUpdate: 'tool_call',
1349
+ id: 'old-tool',
1350
+ title: 'terminal',
1351
+ rawInput: { command: 'rm ~/Desktop/Text/Sisyphus_介绍.txt' },
1352
+ },
1353
+ },
1354
+ });
1355
+ coordinator.handleAgentNotification(session, {
1356
+ method: 'session/update',
1357
+ params: {
1358
+ update: {
1359
+ sessionUpdate: 'tool_call_update',
1360
+ id: 'old-tool',
1361
+ title: 'tool update',
1362
+ status: 'completed',
1363
+ content: [
1364
+ {
1365
+ type: 'content',
1366
+ content: {
1367
+ type: 'text',
1368
+ text: 'terminal result\n- **exit_code:** 0',
1369
+ },
1370
+ },
1371
+ ],
1372
+ },
1373
+ },
1374
+ });
1375
+ coordinator.handleAgentNotification(session, {
1376
+ method: 'session/update',
1377
+ params: {
1378
+ update: {
1379
+ sessionUpdate: 'agent_thought_chunk',
1380
+ content: {
1381
+ type: 'text',
1382
+ text: 'The user confirmed they want to delete the file. Let me delete it.',
1383
+ },
1384
+ },
1385
+ },
1386
+ });
1387
+ coordinator.handleAgentNotification(session, {
1388
+ method: 'session/update',
1389
+ params: {
1390
+ update: {
1391
+ sessionUpdate: 'tool_call',
1392
+ id: 'new-tool',
1393
+ title: 'terminal',
1394
+ rawInput: { command: 'ls -la ~/Desktop/PDF/' },
1395
+ },
1396
+ },
1397
+ });
1398
+ coordinator.handleAgentNotification(session, {
1399
+ method: 'session/update',
1400
+ params: {
1401
+ update: {
1402
+ sessionUpdate: 'tool_call_update',
1403
+ id: 'new-tool',
1404
+ title: 'tool update',
1405
+ status: 'completed',
1406
+ content: [
1407
+ {
1408
+ type: 'content',
1409
+ content: {
1410
+ type: 'text',
1411
+ text: 'terminal result\n- **output:** pdf files\n- **exit_code:** 0',
1412
+ },
1413
+ },
1414
+ ],
1415
+ },
1416
+ },
1417
+ });
1418
+ coordinator.handleAgentNotification(session, {
1419
+ method: 'session/update',
1420
+ params: {
1421
+ update: {
1422
+ sessionUpdate: 'agent_thought_chunk',
1423
+ content: {
1424
+ type: 'text',
1425
+ text: 'Let me present the PDF files to the user.',
1426
+ },
1427
+ },
1428
+ },
1429
+ });
1430
+ strict_1.default.deepEqual(upserted.map((entry) => entry.content), [
1431
+ '🔧 terminal: completed - terminal result\n- **output:** pdf files\n- **exit_code:** 0',
1432
+ 'Let me present the PDF files to the user.',
1433
+ ]);
1434
+ strict_1.default.deepEqual(emitted.map((event) => event.content), [
1435
+ '🔧 terminal: completed - terminal result\n- **output:** pdf files\n- **exit_code:** 0',
1436
+ 'Let me present the PDF files to the user.',
1437
+ ]);
1438
+ });
1439
+ (0, node_test_1.default)('Hermes ACP progress updates suppress restored plan and tool-scoped assistant chunks', () => {
1440
+ const appended = [];
1441
+ const emitted = [];
1442
+ const coordinator = new local_core_acp_turn_coordinator_js_1.LocalCoreAcpTurnCoordinator({
1443
+ appendMessage: (_threadId, _role, content, _kind, _toolCall, bridgeKind) => appended.push({ content, bridgeKind }),
1444
+ emitBridge: (event) => emitted.push(event),
1445
+ updateRunStatus: () => { },
1446
+ sendRaw: () => true,
1447
+ });
1448
+ const session = {
1449
+ threadId: 'thread-1',
1450
+ bridgeSessionKey: 'session:thread-1',
1451
+ currentRunId: 'run-1',
1452
+ currentTurn: {
1453
+ runId: 'run-1',
1454
+ replyCtx: 'run-1',
1455
+ previewHandle: 'preview-1',
1456
+ agentType: 'hermes',
1457
+ assistantText: '',
1458
+ priorAssistantProgressMessages: [
1459
+ { kind: 'plan', content: '旧计划 | 已完成' },
1460
+ { kind: 'tool', content: 'raw restored command output' },
1461
+ ],
1462
+ typingStarted: true,
1463
+ previewStarted: false,
1464
+ permission: null,
1465
+ },
1466
+ loadReplayMode: false,
1467
+ schedulerJobCreatedByRun: new Map(),
1468
+ pendingRawAssistantProgressChunks: ['raw restored command output', 'fresh command output'],
1469
+ };
1470
+ coordinator.handleAgentNotification(session, {
1471
+ method: 'session/update',
1472
+ params: {
1473
+ update: {
1474
+ sessionUpdate: 'plan',
1475
+ entries: [{ content: '旧计划' }, { content: '已完成' }],
1476
+ },
1477
+ },
1478
+ });
1479
+ coordinator.handleAgentNotification(session, {
1480
+ method: 'session/update',
1481
+ params: {
1482
+ update: {
1483
+ sessionUpdate: 'agent_message_chunk',
1484
+ content: { type: 'text', text: 'raw restored command output' },
1485
+ },
1486
+ },
1487
+ });
1488
+ coordinator.handleAgentNotification(session, {
1489
+ method: 'session/update',
1490
+ params: {
1491
+ update: {
1492
+ sessionUpdate: 'plan',
1493
+ entries: [{ content: '新计划' }, { content: '进行中' }],
1494
+ },
1495
+ },
1496
+ });
1497
+ coordinator.handleAgentNotification(session, {
1498
+ method: 'session/update',
1499
+ params: {
1500
+ update: {
1501
+ sessionUpdate: 'agent_message_chunk',
1502
+ content: { type: 'text', text: 'fresh command output' },
1503
+ },
1504
+ },
1505
+ });
1506
+ strict_1.default.deepEqual(appended, [
1507
+ { content: '新计划 | 进行中', bridgeKind: 'plan' },
1508
+ { content: 'fresh command output', bridgeKind: 'tool' },
1509
+ ]);
1510
+ strict_1.default.deepEqual(emitted.map((event) => ({ content: event.content, bridgeKind: event.bridgeKind })), [
1511
+ { content: '新计划 | 进行中', bridgeKind: 'plan' },
1512
+ { content: 'fresh command output', bridgeKind: 'tool' },
1513
+ ]);
1514
+ });
1116
1515
  (0, node_test_1.default)('ACP raw local command output assistant chunks stay out of final assistant buffer', () => {
1117
1516
  const appended = [];
1118
1517
  const coordinator = new local_core_acp_turn_coordinator_js_1.LocalCoreAcpTurnCoordinator({
@@ -1405,6 +1804,29 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
1405
1804
  (0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
1406
1805
  }
1407
1806
  });
1807
+ (0, node_test_1.default)('channel gateways ignore unowned bridge events without route miss log noise', async () => {
1808
+ const logs = [];
1809
+ const commonOptions = {
1810
+ store: {},
1811
+ readConfig: async () => null,
1812
+ getWorkspaceRouter: () => ({}),
1813
+ eventBus: { emit: () => { }, on: () => () => { } },
1814
+ log: (line) => logs.push(line),
1815
+ };
1816
+ const larkGateway = new local_core_lark_gateway_js_1.LocalCoreLarkGateway(commonOptions);
1817
+ const weixinGateway = new local_core_weixin_gateway_js_1.LocalCoreWeixinGateway(commonOptions);
1818
+ await larkGateway.onBridgeEvent({
1819
+ type: 'update_message',
1820
+ sessionKey: 'localcore-acp:project-1:thread-1',
1821
+ content: 'stream chunk',
1822
+ });
1823
+ await weixinGateway.onBridgeEvent({
1824
+ type: 'update_message',
1825
+ sessionKey: 'localcore-acp:project-1:thread-1',
1826
+ content: 'stream chunk',
1827
+ });
1828
+ strict_1.default.deepEqual(logs, []);
1829
+ });
1408
1830
  (0, node_test_1.default)('lark bridge sends completed thought once before final answer', async () => {
1409
1831
  const createdCards = [];
1410
1832
  const patchedCards = [];
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@kafca/agentdock",
3
- "version": "0.1.30",
3
+ "version": "0.1.33",
4
+ "license": "PolyForm-Noncommercial-1.0.0",
4
5
  "type": "module",
5
6
  "main": "dist-electron/electron/main.js",
6
7
  "bin": {
@@ -31,7 +32,7 @@
31
32
  "build:renderer": "vite build",
32
33
  "build:electron": "node scripts/write-electron-package.mjs && tsc -p tsconfig.electron.json",
33
34
  "build:core": "pnpm build:electron",
34
- "test": "pnpm build:renderer && pnpm build:electron && node --test dist-electron/electron/*.test.js dist-electron/packages/knowledge-api/test/*.test.js dist-electron/src/pages/Threads/thread-chat-permission.test.js",
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
36
  "e2e:smoke": "pnpm build && node scripts/e2e-smoke.mjs",
36
37
  "dist:mac": "pnpm build && electron-builder --mac dmg zip --arm64",
37
38
  "dist:win": "pnpm build && electron-builder --win nsis zip --x64",