@kafca/agentdock 0.1.28 → 0.1.30
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 +5 -0
- package/dist/renderer/assets/{Badge-B-Ayib4h.js → Badge-DlVJI1Ys.js} +1 -1
- package/dist/renderer/assets/{Chat-CNEOxtyz.js → Chat-oa8OjaHQ.js} +1 -1
- package/dist/renderer/assets/{ChatMarkdown-BTd1QBj9.js → ChatMarkdown-C-N8KS5C.js} +1 -1
- package/dist/renderer/assets/{Config-ByKhcLa6.js → Config-D9sL_d4D.js} +1 -1
- package/dist/renderer/assets/{CronList-0mi8dcC5.js → CronList-Z5JU3DHk.js} +1 -1
- package/dist/renderer/assets/{Dashboard-C8-tB_qg.js → Dashboard-D3BwbG43.js} +2 -2
- package/dist/renderer/assets/{EmptyState-TR-9nr5e.js → EmptyState-QOj765Ul.js} +1 -1
- package/dist/renderer/assets/{KnowledgeDetail-DKAxFOXc.js → KnowledgeDetail-J7n01mPu.js} +1 -1
- package/dist/renderer/assets/{KnowledgeHome-CM-1IDr4.js → KnowledgeHome-BFnH0NVk.js} +1 -1
- package/dist/renderer/assets/{Logs-DI5RFPri.js → Logs-DfSUifXc.js} +1 -1
- package/dist/renderer/assets/{Modal-CQpa4NPP.js → Modal-QjEGhyru.js} +1 -1
- package/dist/renderer/assets/{Page-BHXEAwzQ.js → Page-qdHFSw7x.js} +1 -1
- package/dist/renderer/assets/{ProjectDetail-Dn5elnHx.js → ProjectDetail-DS_rfvhh.js} +1 -1
- package/dist/renderer/assets/{ProjectList-D6yvEgb5.js → ProjectList-COtyZd7H.js} +1 -1
- package/dist/renderer/assets/{Select-BbkcXnXL.js → Select-BQ8mncVu.js} +1 -1
- package/dist/renderer/assets/{SessionChat-Vkf-7gvX.js → SessionChat-DjVnjuQy.js} +1 -1
- package/dist/renderer/assets/{SessionList-c5encjWd.js → SessionList-88dgGZJ8.js} +1 -1
- package/dist/renderer/assets/ThreadChat-BCdbTxBo.js +23 -0
- package/dist/renderer/assets/{Workspace-BC7hWqhP.js → Workspace-D_hzSJjX.js} +1 -1
- package/dist/renderer/assets/{arrow-left-I_Y1kdN9.js → arrow-left-BMpknulW.js} +1 -1
- package/dist/renderer/assets/{book-open-B3anUYvp.js → book-open-CiaOeQbU.js} +1 -1
- package/dist/renderer/assets/{check-BPNCDKgS.js → check-CgwYH4GF.js} +1 -1
- package/dist/renderer/assets/{chevron-down-BaxUcOIV.js → chevron-down-BzD2S1OO.js} +1 -1
- package/dist/renderer/assets/{circle-DJQiypFS.js → circle-BDHD7g7l.js} +1 -1
- package/dist/renderer/assets/{desktop-Cv51clcN.js → desktop-BiR5LPL5.js} +1 -1
- package/dist/renderer/assets/{funnel-DqKBtiqE.js → funnel-Bruf5FYA.js} +1 -1
- package/dist/renderer/assets/{heart-CmoNjvMO.js → heart-D7Mz04B0.js} +1 -1
- package/dist/renderer/assets/{index-DXJl2HOK.js → index-CL1e8m3U.js} +2 -2
- package/dist/renderer/assets/{index-BfXqhQ1Z.js → index-gZIRr4_o.js} +1 -1
- package/dist/renderer/assets/{pencil-CLUBszbw.js → pencil-C6gzDMse.js} +1 -1
- package/dist/renderer/assets/{play-l2RPZuAi.js → play-DqTXX-Pr.js} +1 -1
- package/dist/renderer/assets/{plug-CeUPIjRt.js → plug-ykmbeaO3.js} +1 -1
- package/dist/renderer/assets/{plus-BjkefS2P.js → plus-DHE60vMX.js} +1 -1
- package/dist/renderer/assets/projects-Bx5p10th.js +1 -0
- package/dist/renderer/assets/{save-D0yYt9tz.js → save-CGIvrdQI.js} +1 -1
- package/dist/renderer/assets/{search-B7s473Y4.js → search-D7IFAwyE.js} +1 -1
- package/dist/renderer/assets/{server-Dz_h8X_8.js → server-aOsirp7I.js} +1 -1
- package/dist/renderer/assets/{session-utils-BvNRTRXA.js → session-utils-Dxfp4ohQ.js} +1 -1
- package/dist/renderer/assets/{sessions-KPJsgKbQ.js → sessions-Db1XPbG2.js} +1 -1
- package/dist/renderer/assets/{shield-check-Wc5wfUUs.js → shield-check-ChXeQK-d.js} +1 -1
- package/dist/renderer/assets/{trash-2-7INdaB9w.js → trash-2-CfN-c1zw.js} +1 -1
- package/dist/renderer/assets/{user-CLbCgWNR.js → user-C7OHaBp4.js} +1 -1
- package/dist/renderer/assets/{wifi-off-BfDVPXbO.js → wifi-off-CpaJigye.js} +1 -1
- package/dist/renderer/index.html +1 -1
- package/dist-electron/electron/agent-runtime-detector.test.js +20 -0
- package/dist-electron/electron/lac-cli.test.js +2 -13
- package/dist-electron/electron/local-core-refactor.test.js +424 -64
- package/dist-electron/electron/workspace-task-store.test.js +118 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +17 -10
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-progress.js +245 -9
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-session-coordinator.js +24 -11
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-store.js +36 -11
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-transport.js +2 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +90 -7
- package/dist-electron/services/local-ai-core/src/channel/lark/runtime-state.js +35 -40
- package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +43 -18
- package/dist-electron/services/local-ai-core/src/cli/lac.js +1 -17
- package/dist-electron/services/local-ai-core/src/router/workspace-router.js +2 -2
- package/dist-electron/services/local-ai-core/src/runtime/agent-runtime-detector.js +1 -1
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +31 -1
- package/dist-electron/services/local-ai-core/src/scheduler/local-schedule-adapter.js +4 -1
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-conversation-executor.js +4 -1
- package/dist-electron/src/pages/Threads/thread-chat-message-blocks.js +4 -114
- package/dist-electron/src/pages/Threads/thread-chat-model.js +14 -23
- package/dist-electron/src/pages/Threads/thread-chat-page-state.js +1 -1
- package/dist-electron/src/pages/Threads/thread-chat-permission.test.js +58 -31
- package/package.json +1 -1
- package/dist/renderer/assets/ThreadChat-DY4wzomi.js +0 -23
- package/dist/renderer/assets/projects-De73QY_o.js +0 -1
|
@@ -458,6 +458,7 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
458
458
|
});
|
|
459
459
|
(0, node_test_1.default)('ACP progress projection applies assistant and thought chunks with bridge metadata', () => {
|
|
460
460
|
const currentTurn = {
|
|
461
|
+
runId: 'run-1',
|
|
461
462
|
previewHandle: 'preview-1',
|
|
462
463
|
thoughtPreviewHandle: 'thought-preview-1',
|
|
463
464
|
thoughtMessageId: 'run-1-thought',
|
|
@@ -470,27 +471,33 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
470
471
|
bridgeType: 'preview_start',
|
|
471
472
|
previewHandle: 'preview-1',
|
|
472
473
|
content: 'hello',
|
|
474
|
+
bridgeKind: 'assistant',
|
|
473
475
|
});
|
|
474
476
|
strict_1.default.deepEqual((0, local_core_acp_progress_js_1.applyAssistantMessageChunk)(currentTurn, ' world'), {
|
|
475
477
|
bridgeType: 'update_message',
|
|
476
478
|
previewHandle: 'preview-1',
|
|
477
479
|
content: 'hello world',
|
|
480
|
+
bridgeKind: 'assistant',
|
|
478
481
|
});
|
|
479
482
|
strict_1.default.deepEqual((0, local_core_acp_progress_js_1.applyThoughtChunk)(currentTurn, '先理解'), {
|
|
480
483
|
bridgeType: 'preview_start',
|
|
481
484
|
previewHandle: 'thought-preview-1',
|
|
482
485
|
messageId: 'run-1-thought',
|
|
483
|
-
content: '
|
|
486
|
+
content: '先理解',
|
|
487
|
+
bridgeKind: 'thought',
|
|
484
488
|
});
|
|
485
489
|
strict_1.default.deepEqual((0, local_core_acp_progress_js_1.applyThoughtChunk)(currentTurn, ',再修改'), {
|
|
486
490
|
bridgeType: 'update_message',
|
|
487
491
|
previewHandle: 'thought-preview-1',
|
|
488
492
|
messageId: 'run-1-thought',
|
|
489
|
-
content: '
|
|
493
|
+
content: '先理解,再修改',
|
|
494
|
+
bridgeKind: 'thought',
|
|
490
495
|
});
|
|
496
|
+
strict_1.default.equal(currentTurn.thoughtText, '先理解,再修改');
|
|
491
497
|
});
|
|
492
498
|
(0, node_test_1.default)('ACP thought chunks merge provider snapshots without duplicating text', () => {
|
|
493
499
|
const currentTurn = {
|
|
500
|
+
runId: 'run-1',
|
|
494
501
|
thoughtPreviewHandle: 'thought-preview-1',
|
|
495
502
|
thoughtMessageId: 'run-1-thought',
|
|
496
503
|
thoughtText: '',
|
|
@@ -500,16 +507,47 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
500
507
|
bridgeType: 'preview_start',
|
|
501
508
|
previewHandle: 'thought-preview-1',
|
|
502
509
|
messageId: 'run-1-thought',
|
|
503
|
-
content: '
|
|
510
|
+
content: 'The user wants to see their desktop files.',
|
|
511
|
+
bridgeKind: 'thought',
|
|
504
512
|
});
|
|
505
513
|
strict_1.default.deepEqual((0, local_core_acp_progress_js_1.applyThoughtChunk)(currentTurn, 'The user wants to see their desktop files. Let me show them.'), {
|
|
506
514
|
bridgeType: 'update_message',
|
|
507
515
|
previewHandle: 'thought-preview-1',
|
|
508
516
|
messageId: 'run-1-thought',
|
|
509
|
-
content: '
|
|
517
|
+
content: 'The user wants to see their desktop files. Let me show them.',
|
|
518
|
+
bridgeKind: 'thought',
|
|
510
519
|
});
|
|
511
520
|
strict_1.default.equal(currentTurn.thoughtText, 'The user wants to see their desktop files. Let me show them.');
|
|
512
521
|
});
|
|
522
|
+
(0, node_test_1.default)('ACP thought segment close starts a new streaming preview for web and app', () => {
|
|
523
|
+
const currentTurn = {
|
|
524
|
+
runId: 'run-1',
|
|
525
|
+
thoughtPreviewHandle: 'thought-preview-1',
|
|
526
|
+
thoughtMessageId: 'run-1-thought-1',
|
|
527
|
+
thoughtText: '',
|
|
528
|
+
thoughtSequence: 1,
|
|
529
|
+
thoughtPreviewStarted: false,
|
|
530
|
+
};
|
|
531
|
+
strict_1.default.deepEqual((0, local_core_acp_progress_js_1.applyThoughtChunk)(currentTurn, 'first thought'), {
|
|
532
|
+
bridgeType: 'preview_start',
|
|
533
|
+
previewHandle: 'thought-preview-1',
|
|
534
|
+
messageId: 'run-1-thought-1',
|
|
535
|
+
content: 'first thought',
|
|
536
|
+
bridgeKind: 'thought',
|
|
537
|
+
});
|
|
538
|
+
(0, local_core_acp_progress_js_1.closeThoughtSegment)(currentTurn);
|
|
539
|
+
strict_1.default.equal(currentTurn.thoughtText, '');
|
|
540
|
+
strict_1.default.equal(currentTurn.thoughtPreviewStarted, false);
|
|
541
|
+
strict_1.default.equal(currentTurn.thoughtMessageId, 'run-1-thought-2');
|
|
542
|
+
strict_1.default.equal(currentTurn.thoughtPreviewHandle, 'run-1-thought-preview-2');
|
|
543
|
+
strict_1.default.deepEqual((0, local_core_acp_progress_js_1.applyThoughtChunk)(currentTurn, 'second thought'), {
|
|
544
|
+
bridgeType: 'preview_start',
|
|
545
|
+
previewHandle: 'run-1-thought-preview-2',
|
|
546
|
+
messageId: 'run-1-thought-2',
|
|
547
|
+
content: 'second thought',
|
|
548
|
+
bridgeKind: 'thought',
|
|
549
|
+
});
|
|
550
|
+
});
|
|
513
551
|
(0, node_test_1.default)('ACP progress projection registers pending tool calls in order', () => {
|
|
514
552
|
const currentTurn = {
|
|
515
553
|
toolCallSequence: 0,
|
|
@@ -557,7 +595,7 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
557
595
|
{ content: '检查消息流' },
|
|
558
596
|
{ content: ' ' },
|
|
559
597
|
{ content: '修复持久化' },
|
|
560
|
-
]), '
|
|
598
|
+
]), '检查消息流 | 修复持久化');
|
|
561
599
|
strict_1.default.equal((0, local_core_acp_progress_js_1.formatPlanProgress)([{ content: '' }]), '');
|
|
562
600
|
});
|
|
563
601
|
(0, node_test_1.default)('ACP tool call running and completed updates share one message id', () => {
|
|
@@ -863,10 +901,11 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
863
901
|
strict_1.default.match(upserted[0]?.content || '', /ls -la ~\/Desktop/);
|
|
864
902
|
strict_1.default.match(upserted[0]?.content || '', /completed - Desktop file list/);
|
|
865
903
|
});
|
|
866
|
-
(0, node_test_1.default)('ACP permission button rows preserve always allow actions', () => {
|
|
904
|
+
(0, node_test_1.default)('ACP permission button rows preserve always allow actions with structured status', () => {
|
|
905
|
+
const appended = [];
|
|
867
906
|
const emitted = [];
|
|
868
907
|
const coordinator = new local_core_acp_turn_coordinator_js_1.LocalCoreAcpTurnCoordinator({
|
|
869
|
-
appendMessage: () => { },
|
|
908
|
+
appendMessage: (_threadId, _role, content, kind, _toolCall, bridgeKind, bridgeStatus) => appended.push({ content, kind, bridgeKind, bridgeStatus }),
|
|
870
909
|
emitBridge: (event) => emitted.push(event),
|
|
871
910
|
updateRunStatus: () => { },
|
|
872
911
|
sendRaw: () => true,
|
|
@@ -905,6 +944,10 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
905
944
|
],
|
|
906
945
|
},
|
|
907
946
|
});
|
|
947
|
+
strict_1.default.equal(appended[0]?.bridgeKind, 'permission');
|
|
948
|
+
strict_1.default.equal(appended[0]?.bridgeStatus, 'awaiting_input');
|
|
949
|
+
strict_1.default.equal(emitted[0]?.bridgeKind, 'permission');
|
|
950
|
+
strict_1.default.equal(emitted[0]?.bridgeStatus, 'awaiting_input');
|
|
908
951
|
strict_1.default.deepEqual(emitted[0]?.buttonRows, [[
|
|
909
952
|
{ text: 'allow', data: 'allow' },
|
|
910
953
|
{ text: 'allow all', data: 'allow all' },
|
|
@@ -1014,6 +1057,177 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1014
1057
|
strict_1.default.equal(emitted[0]?.content, '🔧 Terminal');
|
|
1015
1058
|
strict_1.default.equal(session.currentTurn.assistantText, 'done');
|
|
1016
1059
|
});
|
|
1060
|
+
(0, node_test_1.default)('ACP tool-scoped assistant chunks stay out of final assistant buffer', () => {
|
|
1061
|
+
const appended = [];
|
|
1062
|
+
const emitted = [];
|
|
1063
|
+
const coordinator = new local_core_acp_turn_coordinator_js_1.LocalCoreAcpTurnCoordinator({
|
|
1064
|
+
appendMessage: (_threadId, _role, content, _kind, _toolCall, bridgeKind) => appended.push({ content, bridgeKind }),
|
|
1065
|
+
emitBridge: (event) => emitted.push(event),
|
|
1066
|
+
updateRunStatus: () => { },
|
|
1067
|
+
sendRaw: () => true,
|
|
1068
|
+
});
|
|
1069
|
+
const session = {
|
|
1070
|
+
threadId: 'thread-1',
|
|
1071
|
+
bridgeSessionKey: 'session:thread-1',
|
|
1072
|
+
currentRunId: 'run-1',
|
|
1073
|
+
currentTurn: {
|
|
1074
|
+
runId: 'run-1',
|
|
1075
|
+
replyCtx: 'run-1',
|
|
1076
|
+
previewHandle: 'preview-1',
|
|
1077
|
+
assistantText: '',
|
|
1078
|
+
typingStarted: true,
|
|
1079
|
+
previewStarted: false,
|
|
1080
|
+
permission: null,
|
|
1081
|
+
},
|
|
1082
|
+
loadReplayMode: false,
|
|
1083
|
+
schedulerJobCreatedByRun: new Map(),
|
|
1084
|
+
};
|
|
1085
|
+
coordinator.handleAgentNotification(session, {
|
|
1086
|
+
method: 'session/update',
|
|
1087
|
+
params: {
|
|
1088
|
+
update: {
|
|
1089
|
+
sessionUpdate: 'agent_message_chunk',
|
|
1090
|
+
_meta: {
|
|
1091
|
+
claudeCode: {
|
|
1092
|
+
parentToolUseId: 'tool-1',
|
|
1093
|
+
},
|
|
1094
|
+
},
|
|
1095
|
+
content: {
|
|
1096
|
+
type: 'text',
|
|
1097
|
+
text: 'tool scoped transcript',
|
|
1098
|
+
},
|
|
1099
|
+
},
|
|
1100
|
+
},
|
|
1101
|
+
});
|
|
1102
|
+
coordinator.handleAgentNotification(session, {
|
|
1103
|
+
method: 'session/update',
|
|
1104
|
+
params: {
|
|
1105
|
+
update: {
|
|
1106
|
+
sessionUpdate: 'agent_message_chunk',
|
|
1107
|
+
content: { type: 'text', text: 'final answer' },
|
|
1108
|
+
},
|
|
1109
|
+
},
|
|
1110
|
+
});
|
|
1111
|
+
strict_1.default.deepEqual(appended, [{ content: 'tool scoped transcript', bridgeKind: 'tool' }]);
|
|
1112
|
+
strict_1.default.equal(emitted[0]?.bridgeKind, 'tool');
|
|
1113
|
+
strict_1.default.equal(emitted[0]?.content, 'tool scoped transcript');
|
|
1114
|
+
strict_1.default.equal(session.currentTurn.assistantText, 'final answer');
|
|
1115
|
+
});
|
|
1116
|
+
(0, node_test_1.default)('ACP raw local command output assistant chunks stay out of final assistant buffer', () => {
|
|
1117
|
+
const appended = [];
|
|
1118
|
+
const coordinator = new local_core_acp_turn_coordinator_js_1.LocalCoreAcpTurnCoordinator({
|
|
1119
|
+
appendMessage: (_threadId, _role, content, _kind, _toolCall, bridgeKind) => appended.push({ content, bridgeKind }),
|
|
1120
|
+
emitBridge: () => { },
|
|
1121
|
+
updateRunStatus: () => { },
|
|
1122
|
+
sendRaw: () => true,
|
|
1123
|
+
});
|
|
1124
|
+
const session = {
|
|
1125
|
+
threadId: 'thread-1',
|
|
1126
|
+
bridgeSessionKey: 'session:thread-1',
|
|
1127
|
+
currentRunId: 'run-1',
|
|
1128
|
+
currentTurn: {
|
|
1129
|
+
runId: 'run-1',
|
|
1130
|
+
replyCtx: 'run-1',
|
|
1131
|
+
previewHandle: 'preview-1',
|
|
1132
|
+
assistantText: '',
|
|
1133
|
+
typingStarted: true,
|
|
1134
|
+
previewStarted: false,
|
|
1135
|
+
permission: null,
|
|
1136
|
+
},
|
|
1137
|
+
loadReplayMode: false,
|
|
1138
|
+
schedulerJobCreatedByRun: new Map(),
|
|
1139
|
+
pendingRawAssistantProgressChunks: [],
|
|
1140
|
+
};
|
|
1141
|
+
coordinator.handleAgentNotification(session, {
|
|
1142
|
+
method: '_claude/sdkMessage',
|
|
1143
|
+
params: {
|
|
1144
|
+
message: {
|
|
1145
|
+
type: 'system',
|
|
1146
|
+
subtype: 'local_command_output',
|
|
1147
|
+
content: 'raw command output',
|
|
1148
|
+
},
|
|
1149
|
+
},
|
|
1150
|
+
});
|
|
1151
|
+
coordinator.handleAgentNotification(session, {
|
|
1152
|
+
method: 'session/update',
|
|
1153
|
+
params: {
|
|
1154
|
+
update: {
|
|
1155
|
+
sessionUpdate: 'agent_message_chunk',
|
|
1156
|
+
content: { type: 'text', text: 'raw command output' },
|
|
1157
|
+
},
|
|
1158
|
+
},
|
|
1159
|
+
});
|
|
1160
|
+
coordinator.handleAgentNotification(session, {
|
|
1161
|
+
method: 'session/update',
|
|
1162
|
+
params: {
|
|
1163
|
+
update: {
|
|
1164
|
+
sessionUpdate: 'agent_message_chunk',
|
|
1165
|
+
content: { type: 'text', text: 'final answer' },
|
|
1166
|
+
},
|
|
1167
|
+
},
|
|
1168
|
+
});
|
|
1169
|
+
strict_1.default.deepEqual(appended, [{ content: 'raw command output', bridgeKind: 'tool' }]);
|
|
1170
|
+
strict_1.default.equal(session.currentTurn.assistantText, 'final answer');
|
|
1171
|
+
});
|
|
1172
|
+
(0, node_test_1.default)('ACP final text strips observed provider tool transcript prefix', () => {
|
|
1173
|
+
const currentTurn = {
|
|
1174
|
+
runId: 'run-1',
|
|
1175
|
+
replyCtx: 'run-1',
|
|
1176
|
+
previewHandle: 'preview-1',
|
|
1177
|
+
assistantText: '',
|
|
1178
|
+
thoughtText: '',
|
|
1179
|
+
typingStarted: true,
|
|
1180
|
+
previewStarted: false,
|
|
1181
|
+
thoughtPreviewStarted: false,
|
|
1182
|
+
permission: null,
|
|
1183
|
+
toolObservations: [],
|
|
1184
|
+
};
|
|
1185
|
+
(0, local_core_acp_progress_js_1.recordToolObservation)(currentTurn, {
|
|
1186
|
+
name: 'webReader',
|
|
1187
|
+
title: 'webReader',
|
|
1188
|
+
input: {
|
|
1189
|
+
url: 'https://github.com/Thysrael/Horizon',
|
|
1190
|
+
return_format: 'markdown',
|
|
1191
|
+
retain_images: false,
|
|
1192
|
+
},
|
|
1193
|
+
status: 'completed',
|
|
1194
|
+
outputText: JSON.stringify([{
|
|
1195
|
+
title: 'GitHub - Thysrael/Horizon: Your own AI-powered news radar',
|
|
1196
|
+
description: 'Your own AI-powered news radar. Generates daily briefings in English & Chinese.',
|
|
1197
|
+
url: 'https://github.com/Thysrael/Horizon',
|
|
1198
|
+
}]),
|
|
1199
|
+
});
|
|
1200
|
+
const polluted = [
|
|
1201
|
+
'**🌐 Z.ai Built-in Tool: webReader**',
|
|
1202
|
+
'',
|
|
1203
|
+
'**Input:**',
|
|
1204
|
+
'```json',
|
|
1205
|
+
'{"url":"https://github.com/Thysrael/Horizon","return_format":"markdown","retain_images":false}',
|
|
1206
|
+
'```',
|
|
1207
|
+
'',
|
|
1208
|
+
'*Executing on server...*',
|
|
1209
|
+
' **Output:**',
|
|
1210
|
+
'**webReader_result_summary:** [{"text": {"title": "GitHub - Thysrael/Horizon: Your own AI-powered news radar", "description": "Your own AI-powered news radar. Generates daily briefings in English & Chinese.", "url": "https...',
|
|
1211
|
+
' 已放入 `00-Inbox/Horizon.md`。这个项目和咱们的 AI 早报 skill 功能高度重叠,架构可以作为参考。',
|
|
1212
|
+
].join('\n');
|
|
1213
|
+
strict_1.default.equal((0, local_core_acp_progress_js_1.stripObservedToolTranscriptsFromAssistantText)(polluted, currentTurn.toolObservations), '已放入 `00-Inbox/Horizon.md`。这个项目和咱们的 AI 早报 skill 功能高度重叠,架构可以作为参考。');
|
|
1214
|
+
strict_1.default.equal((0, local_core_acp_progress_js_1.stripObservedToolTranscriptsFromAssistantText)(polluted, []), polluted.trim());
|
|
1215
|
+
});
|
|
1216
|
+
(0, node_test_1.default)('ACP final text keeps normal answers that mention observed tool evidence', () => {
|
|
1217
|
+
const observations = [{
|
|
1218
|
+
name: 'webReader',
|
|
1219
|
+
input: { url: 'https://github.com/Thysrael/Horizon' },
|
|
1220
|
+
outputText: JSON.stringify([{
|
|
1221
|
+
title: 'GitHub - Thysrael/Horizon: Your own AI-powered news radar',
|
|
1222
|
+
url: 'https://github.com/Thysrael/Horizon',
|
|
1223
|
+
}]),
|
|
1224
|
+
}];
|
|
1225
|
+
const answer = [
|
|
1226
|
+
'我看了 https://github.com/Thysrael/Horizon,它是一个 AI 新闻雷达项目。',
|
|
1227
|
+
'结论:可以作为早报 skill 的参考,但不需要直接照搬。',
|
|
1228
|
+
].join('\n');
|
|
1229
|
+
strict_1.default.equal((0, local_core_acp_progress_js_1.stripObservedToolTranscriptsFromAssistantText)(answer, observations), answer);
|
|
1230
|
+
});
|
|
1017
1231
|
(0, node_test_1.default)('ACP plan updates are persisted and emitted as thinking progress', () => {
|
|
1018
1232
|
const appended = [];
|
|
1019
1233
|
const emitted = [];
|
|
@@ -1053,15 +1267,16 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1053
1267
|
});
|
|
1054
1268
|
strict_1.default.deepEqual(appended, [
|
|
1055
1269
|
{
|
|
1056
|
-
content: '
|
|
1270
|
+
content: '检查消息流 | 修复持久化',
|
|
1057
1271
|
kind: 'progress',
|
|
1058
1272
|
},
|
|
1059
1273
|
]);
|
|
1060
1274
|
strict_1.default.equal(emitted.length, 1);
|
|
1061
1275
|
strict_1.default.equal(emitted[0]?.type, 'reply');
|
|
1276
|
+
strict_1.default.equal(emitted[0]?.bridgeKind, 'plan');
|
|
1062
1277
|
strict_1.default.equal(emitted[0]?.content, appended[0]?.content);
|
|
1063
1278
|
});
|
|
1064
|
-
(0, node_test_1.default)('ACP thought chunks
|
|
1279
|
+
(0, node_test_1.default)('ACP thought chunks stream for web/app and start a fresh segment at tool boundaries', () => {
|
|
1065
1280
|
const appended = [];
|
|
1066
1281
|
const upserted = [];
|
|
1067
1282
|
const emitted = [];
|
|
@@ -1081,9 +1296,10 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1081
1296
|
replyCtx: 'run-1',
|
|
1082
1297
|
previewHandle: 'preview-1',
|
|
1083
1298
|
thoughtPreviewHandle: 'thought-preview-1',
|
|
1084
|
-
thoughtMessageId: 'run-1-thought',
|
|
1299
|
+
thoughtMessageId: 'run-1-thought-1',
|
|
1085
1300
|
assistantText: '',
|
|
1086
1301
|
thoughtText: '',
|
|
1302
|
+
thoughtSequence: 1,
|
|
1087
1303
|
typingStarted: true,
|
|
1088
1304
|
previewStarted: false,
|
|
1089
1305
|
thoughtPreviewStarted: false,
|
|
@@ -1101,6 +1317,16 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1101
1317
|
},
|
|
1102
1318
|
},
|
|
1103
1319
|
});
|
|
1320
|
+
strict_1.default.deepEqual(appended, []);
|
|
1321
|
+
strict_1.default.deepEqual(upserted, [
|
|
1322
|
+
{
|
|
1323
|
+
id: 'run-1-thought-1',
|
|
1324
|
+
content: '先理解问题',
|
|
1325
|
+
kind: 'progress',
|
|
1326
|
+
},
|
|
1327
|
+
]);
|
|
1328
|
+
strict_1.default.deepEqual(emitted.map((event) => event.type), ['preview_start']);
|
|
1329
|
+
strict_1.default.equal(emitted[0]?.content, '先理解问题');
|
|
1104
1330
|
coordinator.handleAgentNotification(session, {
|
|
1105
1331
|
method: 'session/update',
|
|
1106
1332
|
params: {
|
|
@@ -1111,37 +1337,40 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1111
1337
|
},
|
|
1112
1338
|
});
|
|
1113
1339
|
strict_1.default.deepEqual(appended, []);
|
|
1114
|
-
strict_1.default.deepEqual(upserted, [
|
|
1115
|
-
{
|
|
1116
|
-
id: 'run-1-thought',
|
|
1117
|
-
content: '💭 先理解问题',
|
|
1118
|
-
kind: 'progress',
|
|
1119
|
-
},
|
|
1120
|
-
{
|
|
1121
|
-
id: 'run-1-thought',
|
|
1122
|
-
content: '💭 先理解问题,再检查代码',
|
|
1123
|
-
kind: 'progress',
|
|
1124
|
-
},
|
|
1125
|
-
]);
|
|
1340
|
+
strict_1.default.deepEqual(upserted.map((entry) => entry.content), ['先理解问题', '先理解问题,再检查代码']);
|
|
1126
1341
|
strict_1.default.deepEqual(emitted.map((event) => event.type), ['preview_start', 'update_message']);
|
|
1127
|
-
strict_1.default.equal(emitted[
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1342
|
+
strict_1.default.equal(emitted[1]?.content, '先理解问题,再检查代码');
|
|
1343
|
+
coordinator.handleAgentNotification(session, {
|
|
1344
|
+
method: 'session/update',
|
|
1345
|
+
params: {
|
|
1346
|
+
update: {
|
|
1347
|
+
sessionUpdate: 'tool_call',
|
|
1348
|
+
title: 'webReader',
|
|
1349
|
+
},
|
|
1350
|
+
},
|
|
1351
|
+
});
|
|
1352
|
+
strict_1.default.deepEqual(appended, []);
|
|
1353
|
+
strict_1.default.equal(session.currentTurn.thoughtText, '');
|
|
1354
|
+
strict_1.default.equal(session.currentTurn.thoughtMessageId, 'run-1-thought-2');
|
|
1355
|
+
strict_1.default.equal(session.currentTurn.thoughtPreviewHandle, 'run-1-thought-preview-2');
|
|
1131
1356
|
});
|
|
1132
|
-
(0, node_test_1.default)('ACP store
|
|
1357
|
+
(0, node_test_1.default)('ACP store preserves structured progress metadata', () => {
|
|
1133
1358
|
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-thought-store-'));
|
|
1134
1359
|
const store = new local_core_acp_store_js_1.LocalCoreAcpStore(userDataPath);
|
|
1135
1360
|
try {
|
|
1136
1361
|
const thread = store.createThread('project-1', 'Thread');
|
|
1137
|
-
store.upsertMessage(thread.id, 'run-1-thought', 'assistant', '
|
|
1138
|
-
store.upsertMessage(thread.id, 'run-1-thought', 'assistant', '
|
|
1362
|
+
store.upsertMessage(thread.id, 'run-1-thought', 'assistant', '先理解问题', 'progress', undefined, 'thought');
|
|
1363
|
+
store.upsertMessage(thread.id, 'run-1-thought', 'assistant', '先理解问题,再检查代码', 'progress', undefined, 'thought');
|
|
1364
|
+
store.appendMessage(thread.id, 'assistant', '等待确认', 'progress', undefined, 'permission', 'awaiting_input');
|
|
1139
1365
|
const detail = store.getThread(thread.id, []);
|
|
1140
|
-
strict_1.default.equal(detail.messages.length,
|
|
1366
|
+
strict_1.default.equal(detail.messages.length, 2);
|
|
1141
1367
|
strict_1.default.equal(detail.messages[0]?.id, 'run-1-thought');
|
|
1142
1368
|
strict_1.default.equal(detail.messages[0]?.kind, 'progress');
|
|
1143
|
-
strict_1.default.equal(detail.messages[0]?.
|
|
1144
|
-
strict_1.default.equal(detail.
|
|
1369
|
+
strict_1.default.equal(detail.messages[0]?.bridgeKind, 'thought');
|
|
1370
|
+
strict_1.default.equal(detail.messages[0]?.content, '先理解问题,再检查代码');
|
|
1371
|
+
strict_1.default.equal(detail.messages[1]?.bridgeKind, 'permission');
|
|
1372
|
+
strict_1.default.equal(detail.messages[1]?.bridgeStatus, 'awaiting_input');
|
|
1373
|
+
strict_1.default.equal(detail.historyCount, 2);
|
|
1145
1374
|
}
|
|
1146
1375
|
finally {
|
|
1147
1376
|
store.close();
|
|
@@ -1240,14 +1469,16 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1240
1469
|
sessionKey: 'session:thread-1',
|
|
1241
1470
|
replyCtx: 'run-1',
|
|
1242
1471
|
previewHandle: 'thought-preview-1',
|
|
1243
|
-
|
|
1472
|
+
bridgeKind: 'thought',
|
|
1473
|
+
content: '先理解问题',
|
|
1244
1474
|
});
|
|
1245
1475
|
await gateway.onBridgeEvent({
|
|
1246
1476
|
type: 'update_message',
|
|
1247
1477
|
sessionKey: 'session:thread-1',
|
|
1248
1478
|
replyCtx: 'run-1',
|
|
1249
1479
|
previewHandle: 'thought-preview-1',
|
|
1250
|
-
|
|
1480
|
+
bridgeKind: 'thought',
|
|
1481
|
+
content: '先理解问题,再检查代码',
|
|
1251
1482
|
});
|
|
1252
1483
|
await gateway.onBridgeEvent({
|
|
1253
1484
|
type: 'reply',
|
|
@@ -1256,7 +1487,7 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1256
1487
|
content: '最终回答',
|
|
1257
1488
|
});
|
|
1258
1489
|
strict_1.default.equal(createdCards.length, 2);
|
|
1259
|
-
strict_1.default.equal(createdCards[0]?.text, '
|
|
1490
|
+
strict_1.default.equal(createdCards[0]?.text, '先理解问题,再检查代码');
|
|
1260
1491
|
strict_1.default.equal(createdCards[1]?.text, '最终回答');
|
|
1261
1492
|
strict_1.default.equal(patchedCards.length, 0);
|
|
1262
1493
|
strict_1.default.deepEqual(storedMessageIds, ['lark-msg-2']);
|
|
@@ -1336,6 +1567,77 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1336
1567
|
strict_1.default.deepEqual(patchedCards, []);
|
|
1337
1568
|
strict_1.default.deepEqual(storedMessageIds, ['lark-msg-1']);
|
|
1338
1569
|
});
|
|
1570
|
+
(0, node_test_1.default)('lark bridge creates final replies without patching prior final cards', async () => {
|
|
1571
|
+
const createdCards = [];
|
|
1572
|
+
const patchedCards = [];
|
|
1573
|
+
const client = {
|
|
1574
|
+
im: {
|
|
1575
|
+
message: {
|
|
1576
|
+
create: async (request) => {
|
|
1577
|
+
const messageId = `lark-msg-${createdCards.length + 1}`;
|
|
1578
|
+
const card = JSON.parse(String(request.data.content || '{}'));
|
|
1579
|
+
createdCards.push({
|
|
1580
|
+
messageId,
|
|
1581
|
+
text: String(card.elements?.[0]?.content || ''),
|
|
1582
|
+
});
|
|
1583
|
+
return { data: { message_id: messageId } };
|
|
1584
|
+
},
|
|
1585
|
+
patch: async (request) => {
|
|
1586
|
+
const card = JSON.parse(String(request.data.content || '{}'));
|
|
1587
|
+
patchedCards.push({
|
|
1588
|
+
messageId: String(request.path.message_id || ''),
|
|
1589
|
+
text: String(card.elements?.[0]?.content || ''),
|
|
1590
|
+
});
|
|
1591
|
+
},
|
|
1592
|
+
},
|
|
1593
|
+
},
|
|
1594
|
+
};
|
|
1595
|
+
const gateway = new local_core_lark_gateway_js_1.LocalCoreLarkGateway({
|
|
1596
|
+
store: {
|
|
1597
|
+
getPlatformThreadBinding: () => ({
|
|
1598
|
+
workspace_id: 'default',
|
|
1599
|
+
platform: 'lark',
|
|
1600
|
+
chat_id: 'chat-1',
|
|
1601
|
+
platform_user_id: 'user-1',
|
|
1602
|
+
thread_id: 'thread-1',
|
|
1603
|
+
last_platform_message_id: null,
|
|
1604
|
+
}),
|
|
1605
|
+
updatePlatformThreadMessageId: () => { },
|
|
1606
|
+
},
|
|
1607
|
+
readConfig: async () => null,
|
|
1608
|
+
getWorkspaceRouter: () => ({}),
|
|
1609
|
+
eventBus: { emit: () => { }, on: () => () => { } },
|
|
1610
|
+
});
|
|
1611
|
+
const internals = gateway;
|
|
1612
|
+
internals.runtime.set('default', {
|
|
1613
|
+
workspaceId: 'default',
|
|
1614
|
+
enabled: true,
|
|
1615
|
+
status: 'running',
|
|
1616
|
+
connected: true,
|
|
1617
|
+
appId: 'app-1',
|
|
1618
|
+
client,
|
|
1619
|
+
});
|
|
1620
|
+
internals.threadRouting.set('session:thread-1', {
|
|
1621
|
+
workspaceId: 'default',
|
|
1622
|
+
platformUserId: 'user-1',
|
|
1623
|
+
chatId: 'chat-1',
|
|
1624
|
+
threadId: 'thread-1',
|
|
1625
|
+
});
|
|
1626
|
+
await gateway.onBridgeEvent({
|
|
1627
|
+
type: 'reply',
|
|
1628
|
+
sessionKey: 'session:thread-1',
|
|
1629
|
+
replyCtx: 'run-1',
|
|
1630
|
+
content: 'first final',
|
|
1631
|
+
});
|
|
1632
|
+
await gateway.onBridgeEvent({
|
|
1633
|
+
type: 'reply',
|
|
1634
|
+
sessionKey: 'session:thread-1',
|
|
1635
|
+
replyCtx: 'run-2',
|
|
1636
|
+
content: 'second final',
|
|
1637
|
+
});
|
|
1638
|
+
strict_1.default.deepEqual(createdCards.map((card) => card.text), ['first final', 'second final']);
|
|
1639
|
+
strict_1.default.deepEqual(patchedCards, []);
|
|
1640
|
+
});
|
|
1339
1641
|
(0, node_test_1.default)('lark bridge sends tool and final as separate cards without patching tool progress', async () => {
|
|
1340
1642
|
const createdCards = [];
|
|
1341
1643
|
const patchedCards = [];
|
|
@@ -1406,7 +1708,14 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1406
1708
|
sessionKey: 'session:thread-1',
|
|
1407
1709
|
replyCtx: 'run-1',
|
|
1408
1710
|
messageId: 'tool-1',
|
|
1409
|
-
|
|
1711
|
+
bridgeKind: 'tool',
|
|
1712
|
+
content: 'bash completed',
|
|
1713
|
+
toolCall: {
|
|
1714
|
+
id: 'tool-1',
|
|
1715
|
+
name: 'bash',
|
|
1716
|
+
status: 'completed',
|
|
1717
|
+
output: 'Sent file CLAUDE.md to chat-1: msg-file-1',
|
|
1718
|
+
},
|
|
1410
1719
|
});
|
|
1411
1720
|
await gateway.onBridgeEvent({
|
|
1412
1721
|
type: 'reply',
|
|
@@ -1485,25 +1794,30 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1485
1794
|
sessionKey: 'session:thread-1',
|
|
1486
1795
|
replyCtx: 'run-1',
|
|
1487
1796
|
previewHandle: 'thought-preview-1',
|
|
1488
|
-
|
|
1797
|
+
bridgeKind: 'thought',
|
|
1798
|
+
content: '先理解',
|
|
1489
1799
|
});
|
|
1490
1800
|
await gateway.onBridgeEvent({
|
|
1491
1801
|
type: 'update_message',
|
|
1492
1802
|
sessionKey: 'session:thread-1',
|
|
1493
1803
|
replyCtx: 'run-1',
|
|
1494
1804
|
previewHandle: 'thought-preview-1',
|
|
1495
|
-
|
|
1805
|
+
bridgeKind: 'thought',
|
|
1806
|
+
content: '先理解用户需求',
|
|
1496
1807
|
});
|
|
1497
1808
|
await gateway.onBridgeEvent({
|
|
1498
1809
|
type: 'reply',
|
|
1499
1810
|
sessionKey: 'session:thread-1',
|
|
1500
1811
|
replyCtx: 'run-1',
|
|
1501
1812
|
messageId: 'run-1-tool-1',
|
|
1502
|
-
|
|
1813
|
+
bridgeKind: 'tool',
|
|
1814
|
+
content: 'Terminal running',
|
|
1503
1815
|
toolCall: {
|
|
1504
1816
|
id: 'call-1',
|
|
1505
1817
|
name: 'Terminal',
|
|
1818
|
+
status: 'running',
|
|
1506
1819
|
input: { command: 'uname -a', description: 'Get system info' },
|
|
1820
|
+
output: '',
|
|
1507
1821
|
},
|
|
1508
1822
|
});
|
|
1509
1823
|
await gateway.onBridgeEvent({
|
|
@@ -1511,11 +1825,14 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1511
1825
|
sessionKey: 'session:thread-1',
|
|
1512
1826
|
replyCtx: 'run-1',
|
|
1513
1827
|
messageId: 'run-1-tool-1',
|
|
1514
|
-
|
|
1828
|
+
bridgeKind: 'tool',
|
|
1829
|
+
content: 'Terminal completed',
|
|
1515
1830
|
toolCall: {
|
|
1516
1831
|
id: 'call-1',
|
|
1517
1832
|
name: 'Terminal',
|
|
1833
|
+
status: 'completed',
|
|
1518
1834
|
input: { command: 'uname -a', description: 'Get system info' },
|
|
1835
|
+
output: 'Linux',
|
|
1519
1836
|
},
|
|
1520
1837
|
});
|
|
1521
1838
|
await gateway.onBridgeEvent({
|
|
@@ -1523,7 +1840,8 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1523
1840
|
sessionKey: 'session:thread-1',
|
|
1524
1841
|
replyCtx: 'run-1',
|
|
1525
1842
|
previewHandle: 'thought-preview-1',
|
|
1526
|
-
|
|
1843
|
+
bridgeKind: 'thought',
|
|
1844
|
+
content: '看到了 Linux',
|
|
1527
1845
|
});
|
|
1528
1846
|
await gateway.onBridgeEvent({
|
|
1529
1847
|
type: 'reply',
|
|
@@ -1532,9 +1850,9 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1532
1850
|
content: '最终回答',
|
|
1533
1851
|
});
|
|
1534
1852
|
strict_1.default.deepEqual(createdCards.map((card) => card.text), [
|
|
1535
|
-
'
|
|
1853
|
+
'先理解用户需求',
|
|
1536
1854
|
'🔧 Terminal\n\n参数:`{"command":"uname -a","description":"Get system info"}`',
|
|
1537
|
-
'
|
|
1855
|
+
'看到了 Linux',
|
|
1538
1856
|
'最终回答',
|
|
1539
1857
|
]);
|
|
1540
1858
|
strict_1.default.deepEqual(patchedCards, []);
|
|
@@ -1606,28 +1924,31 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1606
1924
|
sessionKey: 'session:thread-1',
|
|
1607
1925
|
replyCtx: 'run-1',
|
|
1608
1926
|
previewHandle: 'thought-preview-1',
|
|
1609
|
-
|
|
1927
|
+
bridgeKind: 'thought',
|
|
1928
|
+
content: 'The user',
|
|
1610
1929
|
});
|
|
1611
1930
|
await gateway.onBridgeEvent({
|
|
1612
1931
|
type: 'update_message',
|
|
1613
1932
|
sessionKey: 'session:thread-1',
|
|
1614
1933
|
replyCtx: 'run-1',
|
|
1615
1934
|
previewHandle: 'thought-preview-1',
|
|
1616
|
-
|
|
1935
|
+
bridgeKind: 'thought',
|
|
1936
|
+
content: 'The user sent a short casual message.',
|
|
1617
1937
|
});
|
|
1618
1938
|
await gateway.onBridgeEvent({
|
|
1619
1939
|
type: 'update_message',
|
|
1620
1940
|
sessionKey: 'session:thread-1',
|
|
1621
1941
|
replyCtx: 'run-1',
|
|
1622
1942
|
previewHandle: 'thought-preview-1',
|
|
1623
|
-
|
|
1943
|
+
bridgeKind: 'thought',
|
|
1944
|
+
content: 'The user sent a short casual message. I should reply briefly.',
|
|
1624
1945
|
});
|
|
1625
1946
|
await gateway.onBridgeEvent({
|
|
1626
1947
|
type: 'typing_stop',
|
|
1627
1948
|
sessionKey: 'session:thread-1',
|
|
1628
1949
|
replyCtx: 'run-1',
|
|
1629
1950
|
});
|
|
1630
|
-
strict_1.default.deepEqual(createdCards.map((card) => card.text), ['
|
|
1951
|
+
strict_1.default.deepEqual(createdCards.map((card) => card.text), ['The user sent a short casual message. I should reply briefly.']);
|
|
1631
1952
|
strict_1.default.deepEqual(patchedCards.map((card) => card.text), []);
|
|
1632
1953
|
strict_1.default.ok(!createdCards.some((card) => /处理中|正在思考/.test(card.text)));
|
|
1633
1954
|
});
|
|
@@ -1905,7 +2226,8 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1905
2226
|
sessionKey: 'session:thread-1',
|
|
1906
2227
|
replyCtx: 'run-1',
|
|
1907
2228
|
messageId: 'tool-1',
|
|
1908
|
-
|
|
2229
|
+
bridgeKind: 'tool',
|
|
2230
|
+
content: 'Terminal running',
|
|
1909
2231
|
toolCall: {
|
|
1910
2232
|
id: 'tool-1',
|
|
1911
2233
|
name: 'Terminal',
|
|
@@ -1919,7 +2241,8 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
1919
2241
|
sessionKey: 'session:thread-1',
|
|
1920
2242
|
replyCtx: 'run-1',
|
|
1921
2243
|
messageId: 'tool-1',
|
|
1922
|
-
|
|
2244
|
+
bridgeKind: 'tool',
|
|
2245
|
+
content: 'Terminal completed',
|
|
1923
2246
|
toolCall: {
|
|
1924
2247
|
id: 'tool-1',
|
|
1925
2248
|
name: 'Terminal',
|
|
@@ -2590,7 +2913,14 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
2590
2913
|
sessionKey: 'session-1',
|
|
2591
2914
|
replyCtx: 'run-1',
|
|
2592
2915
|
previewHandle: 'tool-1',
|
|
2593
|
-
|
|
2916
|
+
bridgeKind: 'tool',
|
|
2917
|
+
content: 'bash pending',
|
|
2918
|
+
toolCall: {
|
|
2919
|
+
id: 'tool-1',
|
|
2920
|
+
name: 'bash',
|
|
2921
|
+
status: 'pending',
|
|
2922
|
+
output: '',
|
|
2923
|
+
},
|
|
2594
2924
|
});
|
|
2595
2925
|
strict_1.default.equal(rendered.text, '');
|
|
2596
2926
|
strict_1.default.equal(rendered.key, 'noop');
|
|
@@ -2599,7 +2929,14 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
2599
2929
|
sessionKey: 'session-1',
|
|
2600
2930
|
replyCtx: 'run-1',
|
|
2601
2931
|
previewHandle: 'tool-1',
|
|
2602
|
-
|
|
2932
|
+
bridgeKind: 'tool',
|
|
2933
|
+
content: 'bash completed',
|
|
2934
|
+
toolCall: {
|
|
2935
|
+
id: 'tool-1',
|
|
2936
|
+
name: 'bash: Tool update',
|
|
2937
|
+
status: 'completed',
|
|
2938
|
+
output: 'verbose output',
|
|
2939
|
+
},
|
|
2603
2940
|
});
|
|
2604
2941
|
strict_1.default.equal(completed.text, '🔧 bash: Tool update');
|
|
2605
2942
|
});
|
|
@@ -2773,8 +3110,8 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
2773
3110
|
getRun: () => ({ status: 'completed' }),
|
|
2774
3111
|
},
|
|
2775
3112
|
workspaceRouter: {
|
|
2776
|
-
sendThreadMessage: async (threadId, prompt) => {
|
|
2777
|
-
calls.push(`send:${threadId}:${prompt}`);
|
|
3113
|
+
sendThreadMessage: async (threadId, prompt, options) => {
|
|
3114
|
+
calls.push(`send:${threadId}:${prompt}:${options?.permissionMode || ''}`);
|
|
2778
3115
|
return { runId: 'run-1' };
|
|
2779
3116
|
},
|
|
2780
3117
|
getThread: async (threadId) => ({
|
|
@@ -2802,7 +3139,7 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
2802
3139
|
}, 1000);
|
|
2803
3140
|
strict_1.default.deepEqual(calls, [
|
|
2804
3141
|
'before:thread-1',
|
|
2805
|
-
'send:thread-1:ping',
|
|
3142
|
+
'send:thread-1:ping:bypassPermissions',
|
|
2806
3143
|
'after:thread-1',
|
|
2807
3144
|
]);
|
|
2808
3145
|
strict_1.default.equal(result.replyText, 'done');
|
|
@@ -2837,8 +3174,8 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
2837
3174
|
calls.push(`create:${workspaceId}:${title}`);
|
|
2838
3175
|
return { id: 'thread-local-1', title };
|
|
2839
3176
|
},
|
|
2840
|
-
sendThreadMessage: async (threadId, prompt) => {
|
|
2841
|
-
calls.push(`send:${threadId}:${prompt}`);
|
|
3177
|
+
sendThreadMessage: async (threadId, prompt, options) => {
|
|
3178
|
+
calls.push(`send:${threadId}:${prompt}:${options?.permissionMode || ''}`);
|
|
2842
3179
|
return { runId: 'run-local-1' };
|
|
2843
3180
|
},
|
|
2844
3181
|
getThread: async (threadId) => ({
|
|
@@ -2853,7 +3190,7 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
2853
3190
|
strict_1.default.deepEqual(calls, [
|
|
2854
3191
|
'list:知识库',
|
|
2855
3192
|
'create:知识库:[Scheduled] local ping',
|
|
2856
|
-
'send:thread-local-1:ping local',
|
|
3193
|
+
'send:thread-local-1:ping local:bypassPermissions',
|
|
2857
3194
|
]);
|
|
2858
3195
|
strict_1.default.equal(result.threadId, 'thread-local-1');
|
|
2859
3196
|
strict_1.default.equal(result.runId, 'run-local-1');
|
|
@@ -3635,14 +3972,24 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
3635
3972
|
threadId: 'thread-1',
|
|
3636
3973
|
});
|
|
3637
3974
|
try {
|
|
3638
|
-
await gateway.onBridgeEvent({
|
|
3975
|
+
await gateway.onBridgeEvent({
|
|
3976
|
+
type: 'reply',
|
|
3977
|
+
sessionKey: 'session:thread-1',
|
|
3978
|
+
bridgeKind: 'tool',
|
|
3979
|
+
content: 'list desktop',
|
|
3980
|
+
toolCall: {
|
|
3981
|
+
name: 'list desktop',
|
|
3982
|
+
status: 'running',
|
|
3983
|
+
output: '',
|
|
3984
|
+
},
|
|
3985
|
+
});
|
|
3639
3986
|
await gateway.onBridgeEvent({ type: 'reply', sessionKey: 'session:thread-1', content: 'final reply' });
|
|
3640
3987
|
strict_1.default.equal(sentBodies.length, 2);
|
|
3641
3988
|
strict_1.default.equal(sentBodies[0]?.msg?.message_state, 2);
|
|
3642
3989
|
strict_1.default.equal(sentBodies[1]?.msg?.message_state, 2);
|
|
3643
3990
|
strict_1.default.equal(sentBodies[0]?.msg?.context_token, 'ctx-1');
|
|
3644
3991
|
strict_1.default.equal(sentBodies[1]?.msg?.context_token, 'ctx-1');
|
|
3645
|
-
strict_1.default.equal(sentBodies[0]?.msg?.item_list?.[0]?.text_item?.text, '
|
|
3992
|
+
strict_1.default.equal(sentBodies[0]?.msg?.item_list?.[0]?.text_item?.text, '**处理中**\n• list desktop - running');
|
|
3646
3993
|
strict_1.default.equal(sentBodies[1]?.msg?.item_list?.[0]?.text_item?.text, 'final reply');
|
|
3647
3994
|
}
|
|
3648
3995
|
finally {
|
|
@@ -3700,7 +4047,13 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
3700
4047
|
await gateway.onBridgeEvent({
|
|
3701
4048
|
type: 'reply',
|
|
3702
4049
|
sessionKey: 'session:thread-1',
|
|
3703
|
-
|
|
4050
|
+
bridgeKind: 'tool',
|
|
4051
|
+
content: 'Tool update completed',
|
|
4052
|
+
toolCall: {
|
|
4053
|
+
name: 'Tool update',
|
|
4054
|
+
status: 'completed',
|
|
4055
|
+
output: '/Users/mochuxian/Desktop has many files and this result should not be sent',
|
|
4056
|
+
},
|
|
3704
4057
|
});
|
|
3705
4058
|
await gateway.onBridgeEvent({ type: 'reply', sessionKey: 'session:thread-1', content: 'final reply' });
|
|
3706
4059
|
strict_1.default.equal(sentBodies.length, 1);
|
|
@@ -3762,10 +4115,16 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
3762
4115
|
await gateway.onBridgeEvent({
|
|
3763
4116
|
type: 'reply',
|
|
3764
4117
|
sessionKey: 'session:thread-1',
|
|
3765
|
-
|
|
4118
|
+
bridgeKind: 'tool',
|
|
4119
|
+
content: 'Tool update failed',
|
|
4120
|
+
toolCall: {
|
|
4121
|
+
name: 'Tool update',
|
|
4122
|
+
status: 'failed',
|
|
4123
|
+
output: 'stack trace and command output should not be sent',
|
|
4124
|
+
},
|
|
3766
4125
|
});
|
|
3767
4126
|
strict_1.default.equal(sentBodies.length, 1);
|
|
3768
|
-
strict_1.default.equal(sentBodies[0]?.msg?.item_list?.[0]?.text_item?.text, '
|
|
4127
|
+
strict_1.default.equal(sentBodies[0]?.msg?.item_list?.[0]?.text_item?.text, '**处理中**\n• Tool update - failed');
|
|
3769
4128
|
}
|
|
3770
4129
|
finally {
|
|
3771
4130
|
globalThis.fetch = originalFetch;
|
|
@@ -3823,13 +4182,14 @@ const server_routes_js_1 = require("../services/local-ai-core/src/runtime/server
|
|
|
3823
4182
|
await gateway.onBridgeEvent({
|
|
3824
4183
|
type: 'reply',
|
|
3825
4184
|
sessionKey: 'session:thread-1',
|
|
4185
|
+
bridgeKind: 'status',
|
|
3826
4186
|
content: `🔧 tool ${index}`,
|
|
3827
4187
|
});
|
|
3828
4188
|
}
|
|
3829
4189
|
await gateway.onBridgeEvent({ type: 'reply', sessionKey: 'session:thread-1', content: 'final reply' });
|
|
3830
4190
|
strict_1.default.equal(sentBodies.length, 10);
|
|
3831
|
-
strict_1.default.equal(sentBodies[0]?.msg?.item_list?.[0]?.text_item?.text, '🔧 tool 1');
|
|
3832
|
-
strict_1.default.
|
|
4191
|
+
strict_1.default.equal(sentBodies[0]?.msg?.item_list?.[0]?.text_item?.text, '**处理中**\n• 🔧 tool 1');
|
|
4192
|
+
strict_1.default.match(sentBodies[8]?.msg?.item_list?.[0]?.text_item?.text, /🔧 tool 9/);
|
|
3833
4193
|
strict_1.default.doesNotMatch(sentBodies.map((body) => body?.msg?.item_list?.[0]?.text_item?.text || '').join('\n'), /🔧 tool 10|🔧 tool 11|🔧 tool 12/);
|
|
3834
4194
|
strict_1.default.match(sentBodies[9]?.msg?.item_list?.[0]?.text_item?.text, /已省略 3 条过程消息/);
|
|
3835
4195
|
strict_1.default.match(sentBodies[9]?.msg?.item_list?.[0]?.text_item?.text, /final reply/);
|