@kafca/agentdock 0.1.19 → 0.1.21
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-DcFVSGwl.js → Badge-BRmQIqbd.js} +1 -1
- package/dist/renderer/assets/{Chat-CTy10fKR.js → Chat-D94ODABB.js} +1 -1
- package/dist/renderer/assets/{ChatMarkdown-C-ci0dQL.js → ChatMarkdown-DqW7OUvV.js} +1 -1
- package/dist/renderer/assets/{Config-Bl5vuqBS.js → Config-9lgzpTCp.js} +1 -1
- package/dist/renderer/assets/{CronList-BQOEXhHD.js → CronList-BYZ-x_bp.js} +1 -1
- package/dist/renderer/assets/{Dashboard-CauX4_SR.js → Dashboard-COISXbQy.js} +2 -2
- package/dist/renderer/assets/{EmptyState-DVYGGFl9.js → EmptyState-w5-I9zg7.js} +1 -1
- package/dist/renderer/assets/{KnowledgeDetail-BlV8Twrx.js → KnowledgeDetail-DVxwrTLw.js} +1 -1
- package/dist/renderer/assets/{KnowledgeHome-vd6AO-Fn.js → KnowledgeHome-BKkubcwi.js} +1 -1
- package/dist/renderer/assets/{Logs-BrtF26F7.js → Logs-D7HxZ8Nb.js} +1 -1
- package/dist/renderer/assets/{Modal-D6ucs8W2.js → Modal-Ceu_MP2e.js} +1 -1
- package/dist/renderer/assets/{Page-BdF9afpu.js → Page-CpSczAz8.js} +1 -1
- package/dist/renderer/assets/{ProjectDetail-RuoRHs1Q.js → ProjectDetail-FJ_bNXLF.js} +1 -1
- package/dist/renderer/assets/{ProjectList-r9MXhUu7.js → ProjectList-DZKL4K9C.js} +1 -1
- package/dist/renderer/assets/{Select-CEsAkZ5j.js → Select-BHQk6qCU.js} +1 -1
- package/dist/renderer/assets/{SessionChat-DwnZpTVu.js → SessionChat-DpgSXF3m.js} +1 -1
- package/dist/renderer/assets/{SessionList-C89Z6STB.js → SessionList-CU6drQ4N.js} +1 -1
- package/dist/renderer/assets/{ThreadChat-JB9GY3La.js → ThreadChat-D3s4GXGh.js} +1 -1
- package/dist/renderer/assets/Workspace-B7looTVo.js +14 -0
- package/dist/renderer/assets/{arrow-left-DuiS0IaQ.js → arrow-left-Dtal-eOi.js} +1 -1
- package/dist/renderer/assets/{book-open-B6l3y70b.js → book-open-q814R_Ov.js} +1 -1
- package/dist/renderer/assets/{check-CfewkzaJ.js → check-DjfCdLvw.js} +1 -1
- package/dist/renderer/assets/{circle-qzty4gzl.js → circle-vfhmyE8v.js} +1 -1
- package/dist/renderer/assets/{desktop-DTAjgvNs.js → desktop-BPIxWbkM.js} +1 -1
- package/dist/renderer/assets/desktop-DZHC4PDB.js +3 -0
- package/dist/renderer/assets/{funnel-CwjI0g4c.js → funnel-CUQibo1I.js} +1 -1
- package/dist/renderer/assets/{heart-CVHUi-lA.js → heart-DG9_b8P1.js} +1 -1
- package/dist/renderer/assets/{index-tQ6A4Zff.js → index-Bn8ane6_.js} +2 -2
- package/dist/renderer/assets/{index-BbDTSo1y.js → index-Ds0IN5rP.js} +1 -1
- package/dist/renderer/assets/{pencil-BvQPZxH6.js → pencil-Dij0LlRY.js} +1 -1
- package/dist/renderer/assets/{play-hJkkCcS6.js → play-CPFGjIyJ.js} +1 -1
- package/dist/renderer/assets/{plug-BGtbkjYJ.js → plug-DH3RKQyn.js} +1 -1
- package/dist/renderer/assets/{plus-DrYsrZyx.js → plus-afkK9_Y8.js} +1 -1
- package/dist/renderer/assets/projects-DTDS9SnT.js +1 -0
- package/dist/renderer/assets/{save-C8W3Wq2Z.js → save-B-cKgWcy.js} +1 -1
- package/dist/renderer/assets/{search-BuSByDes.js → search-DR6PeYkt.js} +1 -1
- package/dist/renderer/assets/{server-B9wEMLdo.js → server-BM6KOB5a.js} +1 -1
- package/dist/renderer/assets/{session-utils-K8E4S3Qx.js → session-utils-BDuThM0a.js} +1 -1
- package/dist/renderer/assets/{sessions-B-QTvESY.js → sessions-C1yKps4T.js} +1 -1
- package/dist/renderer/assets/{shield-check-C-oxstVp.js → shield-check-BFjMG-r2.js} +1 -1
- package/dist/renderer/assets/{trash-2-BQpE15-6.js → trash-2-CW1heMCf.js} +1 -1
- package/dist/renderer/assets/{user-CM4R9QVx.js → user-r_2sHG7m.js} +1 -1
- package/dist/renderer/assets/{wifi-off-CoaA7hVn.js → wifi-off-VMUokMpE.js} +1 -1
- package/dist/renderer/index.html +1 -1
- package/dist-electron/electron/agent-runtime-detector.test.js +11 -0
- package/dist-electron/electron/local-core-refactor.test.js +522 -0
- package/dist-electron/electron/plugin-kernel.test.js +77 -9
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +9 -9
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-content.js +60 -0
- package/dist-electron/services/local-ai-core/src/gateway/local-core-lark-gateway.js +337 -54
- package/dist-electron/services/local-ai-core/src/gateway/local-core-weixin-gateway.js +50 -2
- package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +2 -1
- package/dist-electron/services/local-ai-core/src/plugins/builtin/agent-localcore-acp-plugin.js +9 -0
- package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +19 -8
- package/dist-electron/services/local-ai-core/src/runtime/agent-runtime-detector.js +23 -12
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +34 -0
- package/dist-electron/shared/desktop.js +4 -2
- package/package.json +2 -1
- package/dist/renderer/assets/Workspace-Cftl8zps.js +0 -14
- package/dist/renderer/assets/desktop-D4Z7M9RM.js +0 -3
- package/dist/renderer/assets/projects-DcNm9FDK.js +0 -1
|
@@ -8,12 +8,14 @@ const strict_1 = __importDefault(require("node:assert/strict"));
|
|
|
8
8
|
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
|
+
const node_stream_1 = require("node:stream");
|
|
11
12
|
const local_core_acp_response_processor_js_1 = require("../services/local-ai-core/src/acp/local-core-acp-response-processor.js");
|
|
12
13
|
const scheduled_conversation_executor_js_1 = require("../services/local-ai-core/src/scheduler/scheduled-conversation-executor.js");
|
|
13
14
|
const scheduler_run_lifecycle_js_1 = require("../services/local-ai-core/src/scheduler/scheduler-run-lifecycle.js");
|
|
14
15
|
const lark_execution_policies_js_1 = require("../services/local-ai-core/src/scheduler/lark-execution-policies.js");
|
|
15
16
|
const local_schedule_adapter_js_1 = require("../services/local-ai-core/src/scheduler/local-schedule-adapter.js");
|
|
16
17
|
const local_core_weixin_gateway_js_1 = require("../services/local-ai-core/src/gateway/local-core-weixin-gateway.js");
|
|
18
|
+
const local_core_lark_gateway_js_1 = require("../services/local-ai-core/src/gateway/local-core-lark-gateway.js");
|
|
17
19
|
const local_core_acp_turn_coordinator_js_1 = require("../services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js");
|
|
18
20
|
const local_core_acp_store_js_1 = require("../services/local-ai-core/src/acp/local-core-acp-store.js");
|
|
19
21
|
(0, node_test_1.default)('ACP tool call update is emitted with its pending tool name', () => {
|
|
@@ -484,6 +486,526 @@ const local_core_acp_store_js_1 = require("../services/local-ai-core/src/acp/loc
|
|
|
484
486
|
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
485
487
|
}
|
|
486
488
|
});
|
|
489
|
+
(0, node_test_1.default)('lark bridge keeps thought preview and final answer in separate messages', async () => {
|
|
490
|
+
const createdCards = [];
|
|
491
|
+
const patchedCards = [];
|
|
492
|
+
const storedMessageIds = [];
|
|
493
|
+
const client = {
|
|
494
|
+
im: {
|
|
495
|
+
message: {
|
|
496
|
+
create: async (request) => {
|
|
497
|
+
const messageId = `lark-msg-${createdCards.length + 1}`;
|
|
498
|
+
const card = JSON.parse(String(request.data.content || '{}'));
|
|
499
|
+
createdCards.push({
|
|
500
|
+
messageId,
|
|
501
|
+
text: String(card.elements?.[0]?.content || ''),
|
|
502
|
+
});
|
|
503
|
+
return { data: { message_id: messageId } };
|
|
504
|
+
},
|
|
505
|
+
patch: async (request) => {
|
|
506
|
+
const card = JSON.parse(String(request.data.content || '{}'));
|
|
507
|
+
patchedCards.push({
|
|
508
|
+
messageId: String(request.path.message_id || ''),
|
|
509
|
+
text: String(card.elements?.[0]?.content || ''),
|
|
510
|
+
});
|
|
511
|
+
},
|
|
512
|
+
},
|
|
513
|
+
},
|
|
514
|
+
};
|
|
515
|
+
const gateway = new local_core_lark_gateway_js_1.LocalCoreLarkGateway({
|
|
516
|
+
store: {
|
|
517
|
+
getPlatformThreadBinding: () => ({
|
|
518
|
+
workspace_id: 'default',
|
|
519
|
+
platform: 'lark',
|
|
520
|
+
chat_id: 'chat-1',
|
|
521
|
+
platform_user_id: 'user-1',
|
|
522
|
+
thread_id: 'thread-1',
|
|
523
|
+
last_platform_message_id: null,
|
|
524
|
+
}),
|
|
525
|
+
updatePlatformThreadMessageId: (_workspaceId, _chatId, _platformUserId, messageId) => {
|
|
526
|
+
storedMessageIds.push(messageId);
|
|
527
|
+
},
|
|
528
|
+
},
|
|
529
|
+
readConfig: async () => null,
|
|
530
|
+
getWorkspaceRouter: () => ({}),
|
|
531
|
+
eventBus: { emit: () => { }, on: () => () => { } },
|
|
532
|
+
});
|
|
533
|
+
const internals = gateway;
|
|
534
|
+
internals.runtime.set('default', {
|
|
535
|
+
workspaceId: 'default',
|
|
536
|
+
enabled: true,
|
|
537
|
+
status: 'running',
|
|
538
|
+
connected: true,
|
|
539
|
+
appId: 'app-1',
|
|
540
|
+
client,
|
|
541
|
+
});
|
|
542
|
+
internals.threadRouting.set('session:thread-1', {
|
|
543
|
+
workspaceId: 'default',
|
|
544
|
+
platformUserId: 'user-1',
|
|
545
|
+
chatId: 'chat-1',
|
|
546
|
+
threadId: 'thread-1',
|
|
547
|
+
});
|
|
548
|
+
await gateway.onBridgeEvent({
|
|
549
|
+
type: 'preview_start',
|
|
550
|
+
sessionKey: 'session:thread-1',
|
|
551
|
+
replyCtx: 'run-1',
|
|
552
|
+
previewHandle: 'thought-preview-1',
|
|
553
|
+
content: '💭 先理解问题',
|
|
554
|
+
});
|
|
555
|
+
await gateway.onBridgeEvent({
|
|
556
|
+
type: 'update_message',
|
|
557
|
+
sessionKey: 'session:thread-1',
|
|
558
|
+
replyCtx: 'run-1',
|
|
559
|
+
previewHandle: 'thought-preview-1',
|
|
560
|
+
content: '💭 先理解问题,再检查代码',
|
|
561
|
+
});
|
|
562
|
+
await gateway.onBridgeEvent({
|
|
563
|
+
type: 'reply',
|
|
564
|
+
sessionKey: 'session:thread-1',
|
|
565
|
+
replyCtx: 'run-1',
|
|
566
|
+
content: '最终回答',
|
|
567
|
+
});
|
|
568
|
+
strict_1.default.equal(createdCards.length, 2);
|
|
569
|
+
strict_1.default.equal(createdCards[0]?.text, '💭 先理解问题');
|
|
570
|
+
strict_1.default.equal(createdCards[1]?.text, '最终回答');
|
|
571
|
+
strict_1.default.equal(patchedCards.length, 1);
|
|
572
|
+
strict_1.default.equal(patchedCards[0]?.messageId, 'lark-msg-1');
|
|
573
|
+
strict_1.default.equal(patchedCards[0]?.text, '💭 先理解问题,再检查代码');
|
|
574
|
+
strict_1.default.deepEqual(storedMessageIds, ['lark-msg-2']);
|
|
575
|
+
});
|
|
576
|
+
(0, node_test_1.default)('lark bridge does not leave typing placeholders or throttle thought updates', async () => {
|
|
577
|
+
const createdCards = [];
|
|
578
|
+
const patchedCards = [];
|
|
579
|
+
const client = {
|
|
580
|
+
im: {
|
|
581
|
+
message: {
|
|
582
|
+
create: async (request) => {
|
|
583
|
+
const messageId = `lark-msg-${createdCards.length + 1}`;
|
|
584
|
+
const card = JSON.parse(String(request.data.content || '{}'));
|
|
585
|
+
createdCards.push({
|
|
586
|
+
messageId,
|
|
587
|
+
text: String(card.elements?.[0]?.content || ''),
|
|
588
|
+
});
|
|
589
|
+
return { data: { message_id: messageId } };
|
|
590
|
+
},
|
|
591
|
+
patch: async (request) => {
|
|
592
|
+
const card = JSON.parse(String(request.data.content || '{}'));
|
|
593
|
+
patchedCards.push({
|
|
594
|
+
messageId: String(request.path.message_id || ''),
|
|
595
|
+
text: String(card.elements?.[0]?.content || ''),
|
|
596
|
+
});
|
|
597
|
+
},
|
|
598
|
+
},
|
|
599
|
+
},
|
|
600
|
+
};
|
|
601
|
+
const gateway = new local_core_lark_gateway_js_1.LocalCoreLarkGateway({
|
|
602
|
+
store: {
|
|
603
|
+
getPlatformThreadBinding: () => ({
|
|
604
|
+
workspace_id: 'default',
|
|
605
|
+
platform: 'lark',
|
|
606
|
+
chat_id: 'chat-1',
|
|
607
|
+
platform_user_id: 'user-1',
|
|
608
|
+
thread_id: 'thread-1',
|
|
609
|
+
last_platform_message_id: null,
|
|
610
|
+
}),
|
|
611
|
+
updatePlatformThreadMessageId: () => { },
|
|
612
|
+
},
|
|
613
|
+
readConfig: async () => null,
|
|
614
|
+
getWorkspaceRouter: () => ({}),
|
|
615
|
+
eventBus: { emit: () => { }, on: () => () => { } },
|
|
616
|
+
});
|
|
617
|
+
const internals = gateway;
|
|
618
|
+
internals.runtime.set('default', {
|
|
619
|
+
workspaceId: 'default',
|
|
620
|
+
enabled: true,
|
|
621
|
+
status: 'running',
|
|
622
|
+
connected: true,
|
|
623
|
+
appId: 'app-1',
|
|
624
|
+
client,
|
|
625
|
+
});
|
|
626
|
+
internals.threadRouting.set('session:thread-1', {
|
|
627
|
+
workspaceId: 'default',
|
|
628
|
+
platformUserId: 'user-1',
|
|
629
|
+
chatId: 'chat-1',
|
|
630
|
+
threadId: 'thread-1',
|
|
631
|
+
});
|
|
632
|
+
await gateway.onBridgeEvent({
|
|
633
|
+
type: 'typing_start',
|
|
634
|
+
sessionKey: 'session:thread-1',
|
|
635
|
+
replyCtx: 'run-1',
|
|
636
|
+
});
|
|
637
|
+
await gateway.onBridgeEvent({
|
|
638
|
+
type: 'preview_start',
|
|
639
|
+
sessionKey: 'session:thread-1',
|
|
640
|
+
replyCtx: 'run-1',
|
|
641
|
+
previewHandle: 'thought-preview-1',
|
|
642
|
+
content: '💭 The user',
|
|
643
|
+
});
|
|
644
|
+
await gateway.onBridgeEvent({
|
|
645
|
+
type: 'update_message',
|
|
646
|
+
sessionKey: 'session:thread-1',
|
|
647
|
+
replyCtx: 'run-1',
|
|
648
|
+
previewHandle: 'thought-preview-1',
|
|
649
|
+
content: '💭 The user sent a short casual message.',
|
|
650
|
+
});
|
|
651
|
+
await gateway.onBridgeEvent({
|
|
652
|
+
type: 'update_message',
|
|
653
|
+
sessionKey: 'session:thread-1',
|
|
654
|
+
replyCtx: 'run-1',
|
|
655
|
+
previewHandle: 'thought-preview-1',
|
|
656
|
+
content: '💭 The user sent a short casual message. I should reply briefly.',
|
|
657
|
+
});
|
|
658
|
+
await gateway.onBridgeEvent({
|
|
659
|
+
type: 'typing_stop',
|
|
660
|
+
sessionKey: 'session:thread-1',
|
|
661
|
+
replyCtx: 'run-1',
|
|
662
|
+
});
|
|
663
|
+
strict_1.default.deepEqual(createdCards.map((card) => card.text), ['💭 The user']);
|
|
664
|
+
strict_1.default.deepEqual(patchedCards.map((card) => card.text), [
|
|
665
|
+
'💭 The user sent a short casual message.',
|
|
666
|
+
'💭 The user sent a short casual message. I should reply briefly.',
|
|
667
|
+
]);
|
|
668
|
+
strict_1.default.ok(!createdCards.some((card) => /处理中|正在思考/.test(card.text)));
|
|
669
|
+
});
|
|
670
|
+
(0, node_test_1.default)('lark permission requests render as clickable card buttons', async () => {
|
|
671
|
+
const createdCards = [];
|
|
672
|
+
const threadActions = [];
|
|
673
|
+
const client = {
|
|
674
|
+
im: {
|
|
675
|
+
message: {
|
|
676
|
+
create: async (request) => {
|
|
677
|
+
createdCards.push(JSON.parse(String(request.data.content || '{}')));
|
|
678
|
+
return { data: { message_id: 'permission-msg-1' } };
|
|
679
|
+
},
|
|
680
|
+
patch: async () => { },
|
|
681
|
+
},
|
|
682
|
+
},
|
|
683
|
+
};
|
|
684
|
+
const gateway = new local_core_lark_gateway_js_1.LocalCoreLarkGateway({
|
|
685
|
+
store: {
|
|
686
|
+
getPlatformThreadBinding: () => ({
|
|
687
|
+
workspace_id: 'default',
|
|
688
|
+
platform: 'lark',
|
|
689
|
+
chat_id: 'chat-1',
|
|
690
|
+
platform_user_id: 'user-1',
|
|
691
|
+
thread_id: 'thread-1',
|
|
692
|
+
last_platform_message_id: null,
|
|
693
|
+
}),
|
|
694
|
+
},
|
|
695
|
+
readConfig: async () => null,
|
|
696
|
+
getWorkspaceRouter: () => ({
|
|
697
|
+
sendThreadAction: async (threadId, action) => {
|
|
698
|
+
threadActions.push({ threadId, action });
|
|
699
|
+
return { runId: 'run-1' };
|
|
700
|
+
},
|
|
701
|
+
}),
|
|
702
|
+
eventBus: { emit: () => { }, on: () => () => { } },
|
|
703
|
+
});
|
|
704
|
+
const internals = gateway;
|
|
705
|
+
internals.runtime.set('default', {
|
|
706
|
+
workspaceId: 'default',
|
|
707
|
+
enabled: true,
|
|
708
|
+
status: 'running',
|
|
709
|
+
connected: true,
|
|
710
|
+
appId: 'app-1',
|
|
711
|
+
cardActionsEnabled: true,
|
|
712
|
+
client,
|
|
713
|
+
});
|
|
714
|
+
internals.threadRouting.set('session:thread-1', {
|
|
715
|
+
workspaceId: 'default',
|
|
716
|
+
platformUserId: 'user-1',
|
|
717
|
+
chatId: 'chat-1',
|
|
718
|
+
threadId: 'thread-1',
|
|
719
|
+
});
|
|
720
|
+
await gateway.onBridgeEvent({
|
|
721
|
+
type: 'buttons',
|
|
722
|
+
sessionKey: 'session:thread-1',
|
|
723
|
+
replyCtx: 'run-1',
|
|
724
|
+
content: [
|
|
725
|
+
'等待工具确认',
|
|
726
|
+
'',
|
|
727
|
+
'Terminal',
|
|
728
|
+
'',
|
|
729
|
+
'parameters:',
|
|
730
|
+
'{"command":"ls"}',
|
|
731
|
+
'',
|
|
732
|
+
'请选择一个选项继续执行。',
|
|
733
|
+
].join('\n'),
|
|
734
|
+
buttonRows: [[
|
|
735
|
+
{ text: 'allow', data: 'allow' },
|
|
736
|
+
{ text: 'allow all', data: 'allow all' },
|
|
737
|
+
{ text: 'deny', data: 'deny' },
|
|
738
|
+
]],
|
|
739
|
+
});
|
|
740
|
+
const actionElement = createdCards[0]?.elements?.find((element) => element.tag === 'action');
|
|
741
|
+
strict_1.default.equal(createdCards.length, 1);
|
|
742
|
+
strict_1.default.match(createdCards[0]?.elements?.[0]?.content || '', /需要工具确认/);
|
|
743
|
+
strict_1.default.deepEqual(actionElement?.actions?.map((action) => ({
|
|
744
|
+
label: action.text?.content,
|
|
745
|
+
type: action.type,
|
|
746
|
+
response: action.value?.response,
|
|
747
|
+
threadId: action.value?.thread_id,
|
|
748
|
+
})), [
|
|
749
|
+
{ label: '允许一次', type: 'primary', response: 'allow', threadId: 'thread-1' },
|
|
750
|
+
{ label: '始终允许', type: 'default', response: 'allow all', threadId: 'thread-1' },
|
|
751
|
+
{ label: '拒绝', type: 'danger', response: 'deny', threadId: 'thread-1' },
|
|
752
|
+
]);
|
|
753
|
+
await internals.handleCardActionEvent('default', {
|
|
754
|
+
event: {
|
|
755
|
+
action: {
|
|
756
|
+
value: {
|
|
757
|
+
action: 'permission_response',
|
|
758
|
+
response: 'allow all',
|
|
759
|
+
thread_id: 'thread-1',
|
|
760
|
+
},
|
|
761
|
+
},
|
|
762
|
+
},
|
|
763
|
+
});
|
|
764
|
+
strict_1.default.deepEqual(threadActions, [
|
|
765
|
+
{ threadId: 'thread-1', action: 'allow all' },
|
|
766
|
+
]);
|
|
767
|
+
});
|
|
768
|
+
(0, node_test_1.default)('lark permission requests fall back to text commands when card actions are disabled', async () => {
|
|
769
|
+
const createdCards = [];
|
|
770
|
+
const gateway = new local_core_lark_gateway_js_1.LocalCoreLarkGateway({
|
|
771
|
+
store: {
|
|
772
|
+
getPlatformThreadBinding: () => ({
|
|
773
|
+
workspace_id: 'default',
|
|
774
|
+
platform: 'lark',
|
|
775
|
+
chat_id: 'chat-1',
|
|
776
|
+
platform_user_id: 'user-1',
|
|
777
|
+
thread_id: 'thread-1',
|
|
778
|
+
last_platform_message_id: null,
|
|
779
|
+
}),
|
|
780
|
+
},
|
|
781
|
+
readConfig: async () => null,
|
|
782
|
+
getWorkspaceRouter: () => ({}),
|
|
783
|
+
eventBus: { emit: () => { }, on: () => () => { } },
|
|
784
|
+
});
|
|
785
|
+
const internals = gateway;
|
|
786
|
+
internals.runtime.set('default', {
|
|
787
|
+
workspaceId: 'default',
|
|
788
|
+
enabled: true,
|
|
789
|
+
status: 'running',
|
|
790
|
+
connected: true,
|
|
791
|
+
appId: 'app-1',
|
|
792
|
+
cardActionsEnabled: false,
|
|
793
|
+
client: {
|
|
794
|
+
im: {
|
|
795
|
+
message: {
|
|
796
|
+
create: async (request) => {
|
|
797
|
+
createdCards.push(JSON.parse(String(request.data.content || '{}')));
|
|
798
|
+
return { data: { message_id: 'permission-msg-1' } };
|
|
799
|
+
},
|
|
800
|
+
patch: async () => { },
|
|
801
|
+
},
|
|
802
|
+
},
|
|
803
|
+
},
|
|
804
|
+
});
|
|
805
|
+
internals.threadRouting.set('session:thread-1', {
|
|
806
|
+
workspaceId: 'default',
|
|
807
|
+
platformUserId: 'user-1',
|
|
808
|
+
chatId: 'chat-1',
|
|
809
|
+
threadId: 'thread-1',
|
|
810
|
+
});
|
|
811
|
+
await gateway.onBridgeEvent({
|
|
812
|
+
type: 'buttons',
|
|
813
|
+
sessionKey: 'session:thread-1',
|
|
814
|
+
replyCtx: 'run-1',
|
|
815
|
+
content: '等待工具确认\n\nTerminal\n\n请选择一个选项继续执行。',
|
|
816
|
+
buttonRows: [[
|
|
817
|
+
{ text: 'allow', data: 'allow' },
|
|
818
|
+
{ text: 'deny', data: 'deny' },
|
|
819
|
+
]],
|
|
820
|
+
});
|
|
821
|
+
strict_1.default.equal(createdCards.length, 1);
|
|
822
|
+
strict_1.default.match(createdCards[0]?.elements?.[0]?.content || '', /请直接回复/);
|
|
823
|
+
strict_1.default.equal(createdCards[0]?.elements?.some((element) => element.tag === 'action'), false);
|
|
824
|
+
});
|
|
825
|
+
(0, node_test_1.default)('lark image messages are downloaded and forwarded as generic channel image parts', async () => {
|
|
826
|
+
const sentMessages = [];
|
|
827
|
+
const pngBytes = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
828
|
+
const client = {
|
|
829
|
+
im: {
|
|
830
|
+
messageResource: {
|
|
831
|
+
get: async (request) => {
|
|
832
|
+
strict_1.default.equal(request.path.message_id, 'msg-image-1');
|
|
833
|
+
strict_1.default.equal(request.path.file_key, 'img-key-1');
|
|
834
|
+
strict_1.default.equal(request.params.type, 'image');
|
|
835
|
+
return {
|
|
836
|
+
headers: { 'content-type': 'image/png' },
|
|
837
|
+
getReadableStream: () => node_stream_1.Readable.from([pngBytes]),
|
|
838
|
+
};
|
|
839
|
+
},
|
|
840
|
+
},
|
|
841
|
+
messageReaction: {
|
|
842
|
+
create: async () => ({ data: { reaction_id: 'reaction-1' } }),
|
|
843
|
+
},
|
|
844
|
+
},
|
|
845
|
+
};
|
|
846
|
+
const gateway = new local_core_lark_gateway_js_1.LocalCoreLarkGateway({
|
|
847
|
+
store: {
|
|
848
|
+
expirePendingPairings: () => { },
|
|
849
|
+
getAuthorizedUser: () => ({
|
|
850
|
+
id: 'auth-1',
|
|
851
|
+
workspace_id: 'default',
|
|
852
|
+
platform: 'lark',
|
|
853
|
+
platform_user_id: 'user-1',
|
|
854
|
+
chat_id: 'chat-1',
|
|
855
|
+
display_name: 'User',
|
|
856
|
+
thread_id: 'thread-1',
|
|
857
|
+
}),
|
|
858
|
+
getPlatformThreadBinding: () => ({
|
|
859
|
+
workspace_id: 'default',
|
|
860
|
+
platform: 'lark',
|
|
861
|
+
chat_id: 'chat-1',
|
|
862
|
+
platform_user_id: 'user-1',
|
|
863
|
+
thread_id: 'thread-1',
|
|
864
|
+
last_platform_message_id: null,
|
|
865
|
+
}),
|
|
866
|
+
getLatestRunForThread: () => null,
|
|
867
|
+
clearPlatformThreadMessageId: () => { },
|
|
868
|
+
},
|
|
869
|
+
readConfig: async () => ({
|
|
870
|
+
projects: [{
|
|
871
|
+
name: 'default',
|
|
872
|
+
root: '/tmp/project',
|
|
873
|
+
platforms: [{
|
|
874
|
+
type: 'lark',
|
|
875
|
+
options: {
|
|
876
|
+
app_id: 'app-1',
|
|
877
|
+
app_secret: 'secret-1',
|
|
878
|
+
},
|
|
879
|
+
}],
|
|
880
|
+
}],
|
|
881
|
+
}),
|
|
882
|
+
getWorkspaceRouter: () => ({
|
|
883
|
+
getThreadSessionKey: (threadId) => `session:${threadId}`,
|
|
884
|
+
sendThreadMessage: async (threadId, content) => {
|
|
885
|
+
sentMessages.push({ threadId, content });
|
|
886
|
+
return { runId: 'run-1' };
|
|
887
|
+
},
|
|
888
|
+
}),
|
|
889
|
+
eventBus: { emit: () => { }, on: () => () => { } },
|
|
890
|
+
});
|
|
891
|
+
const internals = gateway;
|
|
892
|
+
internals.runtime.set('default', {
|
|
893
|
+
workspaceId: 'default',
|
|
894
|
+
enabled: true,
|
|
895
|
+
status: 'running',
|
|
896
|
+
connected: true,
|
|
897
|
+
appId: 'app-1',
|
|
898
|
+
client,
|
|
899
|
+
});
|
|
900
|
+
await internals.handleMessageEvent('default', {
|
|
901
|
+
event: {
|
|
902
|
+
sender: {
|
|
903
|
+
sender_id: { user_id: 'user-1' },
|
|
904
|
+
},
|
|
905
|
+
message: {
|
|
906
|
+
message_id: 'msg-image-1',
|
|
907
|
+
message_type: 'image',
|
|
908
|
+
chat_id: 'chat-1',
|
|
909
|
+
content: JSON.stringify({ image_key: 'img-key-1' }),
|
|
910
|
+
},
|
|
911
|
+
},
|
|
912
|
+
});
|
|
913
|
+
strict_1.default.equal(sentMessages.length, 1);
|
|
914
|
+
strict_1.default.equal(sentMessages[0]?.threadId, 'thread-1');
|
|
915
|
+
strict_1.default.match(sentMessages[0]?.content?.displayText, /\[User Message\]\n\[Image\]\n\[\/User Message\]/);
|
|
916
|
+
strict_1.default.deepEqual(sentMessages[0]?.content?.contentParts?.map((part) => part.type), ['text', 'image']);
|
|
917
|
+
strict_1.default.equal(sentMessages[0]?.content?.contentParts?.[1]?.mimeType, 'image/png');
|
|
918
|
+
strict_1.default.equal(sentMessages[0]?.content?.contentParts?.[1]?.data, pngBytes.toString('base64'));
|
|
919
|
+
});
|
|
920
|
+
(0, node_test_1.default)('lark message callbacks acknowledge before long thread runs finish', async () => {
|
|
921
|
+
let registeredHandlers = {};
|
|
922
|
+
let sentMessages = 0;
|
|
923
|
+
const logs = [];
|
|
924
|
+
const gateway = new local_core_lark_gateway_js_1.LocalCoreLarkGateway({
|
|
925
|
+
store: {
|
|
926
|
+
expirePendingPairings: () => { },
|
|
927
|
+
getAuthorizedUser: () => ({
|
|
928
|
+
id: 'auth-1',
|
|
929
|
+
workspace_id: 'default',
|
|
930
|
+
platform_user_id: 'user-1',
|
|
931
|
+
chat_id: 'chat-1',
|
|
932
|
+
display_name: 'User',
|
|
933
|
+
thread_id: 'thread-1',
|
|
934
|
+
}),
|
|
935
|
+
getPlatformThreadBinding: () => ({
|
|
936
|
+
workspace_id: 'default',
|
|
937
|
+
platform: 'lark',
|
|
938
|
+
chat_id: 'chat-1',
|
|
939
|
+
platform_user_id: 'user-1',
|
|
940
|
+
thread_id: 'thread-1',
|
|
941
|
+
last_platform_message_id: null,
|
|
942
|
+
}),
|
|
943
|
+
getLatestRunForThread: () => null,
|
|
944
|
+
clearPlatformThreadMessageId: () => { },
|
|
945
|
+
listPendingPairings: () => [],
|
|
946
|
+
listAuthorizedUsers: () => [],
|
|
947
|
+
},
|
|
948
|
+
readConfig: async () => ({
|
|
949
|
+
projects: [
|
|
950
|
+
{
|
|
951
|
+
name: 'default',
|
|
952
|
+
agent: { type: 'claudecode', providers: [] },
|
|
953
|
+
platforms: [{ type: 'lark', options: { app_id: 'app-1', app_secret: 'secret-1', auto_approve: true } }],
|
|
954
|
+
},
|
|
955
|
+
],
|
|
956
|
+
}),
|
|
957
|
+
getWorkspaceRouter: () => ({
|
|
958
|
+
getThreadSessionKey: (threadId) => `session:${threadId}`,
|
|
959
|
+
sendThreadMessage: async () => {
|
|
960
|
+
sentMessages++;
|
|
961
|
+
return new Promise(() => { });
|
|
962
|
+
},
|
|
963
|
+
}),
|
|
964
|
+
eventBus: { emit: () => { }, on: () => () => { } },
|
|
965
|
+
log: (message) => logs.push(message),
|
|
966
|
+
});
|
|
967
|
+
gateway.larkModulePromise = Promise.resolve({
|
|
968
|
+
AppType: { SelfBuild: 'self-build' },
|
|
969
|
+
Domain: { Feishu: 'feishu' },
|
|
970
|
+
LoggerLevel: { info: 'info' },
|
|
971
|
+
Client: class {
|
|
972
|
+
},
|
|
973
|
+
EventDispatcher: class {
|
|
974
|
+
register(handlers) {
|
|
975
|
+
registeredHandlers = handlers;
|
|
976
|
+
}
|
|
977
|
+
},
|
|
978
|
+
WSClient: class {
|
|
979
|
+
async start() { }
|
|
980
|
+
},
|
|
981
|
+
});
|
|
982
|
+
await gateway.enable('default');
|
|
983
|
+
const handler = registeredHandlers['im.message.receive_v1'];
|
|
984
|
+
strict_1.default.equal(typeof handler, 'function');
|
|
985
|
+
const result = await Promise.race([
|
|
986
|
+
handler({
|
|
987
|
+
event: {
|
|
988
|
+
sender: { sender_id: { user_id: 'user-1' } },
|
|
989
|
+
message: {
|
|
990
|
+
message_id: 'msg-1',
|
|
991
|
+
chat_id: 'chat-1',
|
|
992
|
+
message_type: 'text',
|
|
993
|
+
content: JSON.stringify({ text: 'hi' }),
|
|
994
|
+
},
|
|
995
|
+
},
|
|
996
|
+
}),
|
|
997
|
+
new Promise((resolve) => setTimeout(() => resolve('timed-out'), 25)),
|
|
998
|
+
]);
|
|
999
|
+
strict_1.default.notEqual(result, 'timed-out');
|
|
1000
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
1001
|
+
strict_1.default.equal(sentMessages, 1);
|
|
1002
|
+
strict_1.default.ok(logs.some((line) => line.includes('received im.message.receive_v1') &&
|
|
1003
|
+
line.includes('message=msg-1') &&
|
|
1004
|
+
line.includes('type=text') &&
|
|
1005
|
+
line.includes('chat=chat-1') &&
|
|
1006
|
+
line.includes('sender=user-1')));
|
|
1007
|
+
strict_1.default.ok(logs.some((line) => line.includes('handling message event') && line.includes('contentBytes=')));
|
|
1008
|
+
});
|
|
487
1009
|
(0, node_test_1.default)('ACP skips empty generic running tool updates', () => {
|
|
488
1010
|
const appended = [];
|
|
489
1011
|
const emitted = [];
|