@kafca/agentdock 0.1.33 → 0.1.35
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 +67 -0
- package/dist/renderer/assets/{Badge-VeSLCPPV.js → Badge-BM4WCcua.js} +1 -1
- package/dist/renderer/assets/{Chat-DWTQeTgn.js → Chat-DoyBHOsx.js} +1 -1
- package/dist/renderer/assets/{ChatMarkdown-C9gSQIVb.js → ChatMarkdown-BWj04kgW.js} +1 -1
- package/dist/renderer/assets/{Config-CTA-pZNR.js → Config-A95OuazQ.js} +1 -1
- package/dist/renderer/assets/{CronList-BngBCnFY.js → CronList-DsPU4zGT.js} +1 -1
- package/dist/renderer/assets/{Dashboard-D4pGvDpc.js → Dashboard-D8Vpj97x.js} +2 -2
- package/dist/renderer/assets/{EmptyState-DMf8rzDs.js → EmptyState-x1uVoSxZ.js} +1 -1
- package/dist/renderer/assets/{KnowledgeDetail-C1Ym_cHk.js → KnowledgeDetail-C9TbcyNJ.js} +1 -1
- package/dist/renderer/assets/{KnowledgeHome-DPRiR72G.js → KnowledgeHome-Cg9Fb41Q.js} +1 -1
- package/dist/renderer/assets/Logs-oWaKA60u.js +1 -0
- package/dist/renderer/assets/{Modal-BDhhPv2l.js → Modal-24hTXXHK.js} +1 -1
- package/dist/renderer/assets/{Page-DdDZN7AE.js → Page-YRtQonKZ.js} +1 -1
- package/dist/renderer/assets/{ProjectDetail-DCsr3LkW.js → ProjectDetail-DScsxJO-.js} +1 -1
- package/dist/renderer/assets/{ProjectList-Cnm-iLvg.js → ProjectList-8L5GD7PN.js} +1 -1
- package/dist/renderer/assets/{Select-Dw4FCXhJ.js → Select-BI8Uw_DF.js} +1 -1
- package/dist/renderer/assets/{SessionChat-O-6abK8x.js → SessionChat-BIoCWdDD.js} +1 -1
- package/dist/renderer/assets/{SessionList-5yptvVL9.js → SessionList-BsEJeDxI.js} +1 -1
- package/dist/renderer/assets/{ThreadChat-CIM_o2HO.js → ThreadChat-DJi0UBta.js} +1 -1
- package/dist/renderer/assets/{Workspace-D9UeUCNr.js → Workspace-tlJxrgC5.js} +1 -1
- package/dist/renderer/assets/{arrow-left-CKfxNOXE.js → arrow-left-pzaBhi9y.js} +1 -1
- package/dist/renderer/assets/{book-open-CQddlENV.js → book-open-CNhlVyqh.js} +1 -1
- package/dist/renderer/assets/{check-CZYvOmIS.js → check-Cg2LLCdl.js} +1 -1
- package/dist/renderer/assets/{chevron-down-CVIWFoXF.js → chevron-down-Dgqg07wf.js} +1 -1
- package/dist/renderer/assets/{circle-DSfdQM7k.js → circle-BBd_jIS2.js} +1 -1
- package/dist/renderer/assets/{desktop-B9KUgeOV.js → desktop-C0S-Yv8G.js} +1 -1
- package/dist/renderer/assets/{funnel-pB5NegZB.js → funnel-DwSh-SrX.js} +1 -1
- package/dist/renderer/assets/{heart-BT5laZ_b.js → heart-CWVc-KhZ.js} +1 -1
- package/dist/renderer/assets/{index-DFiJR0vv.css → index-CaQZSRbg.css} +1 -1
- package/dist/renderer/assets/{index-BYyDk28K.js → index-DZbeAYVk.js} +2 -2
- package/dist/renderer/assets/{index-zTUUYax3.js → index-HYmDNQ9k.js} +1 -1
- package/dist/renderer/assets/{pencil-C0thxLi6.js → pencil-tI4tCLz0.js} +1 -1
- package/dist/renderer/assets/{play-CmZ0kWtt.js → play-Coi2HA1w.js} +1 -1
- package/dist/renderer/assets/{plug-CeDQatBe.js → plug-D4TCyW9b.js} +1 -1
- package/dist/renderer/assets/{plus-Di__xFOZ.js → plus-p62AgpoB.js} +1 -1
- package/dist/renderer/assets/projects-CTDuVxeQ.js +1 -0
- package/dist/renderer/assets/{save-BDatCjfO.js → save-fpMhkVV0.js} +1 -1
- package/dist/renderer/assets/{search-DnTOjP0C.js → search-BHKIStdA.js} +1 -1
- package/dist/renderer/assets/{server-Ey_iHY6m.js → server-0oTWed8U.js} +1 -1
- package/dist/renderer/assets/{session-utils-DWaM7Rkr.js → session-utils-D0Qv0I0-.js} +1 -1
- package/dist/renderer/assets/{sessions-CYYjLD5I.js → sessions-C8ApKQgC.js} +1 -1
- package/dist/renderer/assets/{shield-check-Br8BQzcn.js → shield-check-BAJI9jzC.js} +1 -1
- package/dist/renderer/assets/{trash-2-7YD616fw.js → trash-2-B-Ygm-x6.js} +1 -1
- package/dist/renderer/assets/{user-BR_5jmr9.js → user-Cv8rzw8l.js} +1 -1
- package/dist/renderer/assets/{wifi-off-By9QdREz.js → wifi-off-BImS3nkm.js} +1 -1
- package/dist/renderer/index.html +2 -2
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +3 -5
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-session-coordinator.js +23 -6
- package/dist-electron/services/local-ai-core/src/cli/lac.js +7 -1
- package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +9 -19
- package/dist-electron/services/local-ai-core/src/kernel/rotating-logger.js +232 -0
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +12 -44
- package/dist-electron/services/local-ai-core/src/runtime/local-core-runtime-state.js +40 -84
- package/dist-electron/services/local-ai-core/src/runtime/server-routes.js +3 -0
- package/dist-electron/services/local-ai-core/src/runtime/server.js +14 -0
- package/dist-electron/services/local-ai-core/src/scheduler/lark-schedule-adapter.js +6 -5
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-conversation-executor.js +22 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-job-application-service.js +84 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-job-route.js +35 -2
- package/dist-electron/services/local-ai-core/src/scheduler/weixin-schedule-adapter.js +5 -5
- package/dist-electron/src/api/client.js +1 -1
- package/dist-electron/tests/electron/lac-cli.test.js +50 -0
- package/dist-electron/tests/electron/plugin-kernel.test.js +162 -44
- package/dist-electron/tests/electron/workspace-task-store.test.js +123 -0
- package/dist-electron/tests/integration/local-core-refactor.test.js +13 -3
- package/package.json +1 -1
- package/dist/renderer/assets/Logs-CRHecmzO.js +0 -1
- package/dist/renderer/assets/projects-B-pbhhtH.js +0 -1
|
@@ -18,6 +18,60 @@ const plugin_registry_js_1 = require("../../services/local-ai-core/src/kernel/pl
|
|
|
18
18
|
const local_core_controller_js_1 = require("../../services/local-ai-core/src/runtime/local-core-controller.js");
|
|
19
19
|
const local_core_runtime_state_js_1 = require("../../services/local-ai-core/src/runtime/local-core-runtime-state.js");
|
|
20
20
|
const server_js_1 = require("../../services/local-ai-core/src/runtime/server.js");
|
|
21
|
+
function withLogEnv(logDir, fn, options = {}) {
|
|
22
|
+
const previousLogDir = process.env.AGENTDOCK_LOG_DIR;
|
|
23
|
+
const previousMaxBytes = process.env.AGENTDOCK_LOG_MAX_BYTES;
|
|
24
|
+
const previousMaxFiles = process.env.AGENTDOCK_LOG_MAX_FILES;
|
|
25
|
+
process.env.AGENTDOCK_LOG_DIR = logDir;
|
|
26
|
+
if (options.maxBytes !== undefined) {
|
|
27
|
+
process.env.AGENTDOCK_LOG_MAX_BYTES = String(options.maxBytes);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
delete process.env.AGENTDOCK_LOG_MAX_BYTES;
|
|
31
|
+
}
|
|
32
|
+
if (options.maxFiles !== undefined) {
|
|
33
|
+
process.env.AGENTDOCK_LOG_MAX_FILES = String(options.maxFiles);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
delete process.env.AGENTDOCK_LOG_MAX_FILES;
|
|
37
|
+
}
|
|
38
|
+
const restore = () => {
|
|
39
|
+
if (previousLogDir === undefined) {
|
|
40
|
+
delete process.env.AGENTDOCK_LOG_DIR;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
process.env.AGENTDOCK_LOG_DIR = previousLogDir;
|
|
44
|
+
}
|
|
45
|
+
if (previousMaxBytes === undefined) {
|
|
46
|
+
delete process.env.AGENTDOCK_LOG_MAX_BYTES;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
process.env.AGENTDOCK_LOG_MAX_BYTES = previousMaxBytes;
|
|
50
|
+
}
|
|
51
|
+
if (previousMaxFiles === undefined) {
|
|
52
|
+
delete process.env.AGENTDOCK_LOG_MAX_FILES;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
process.env.AGENTDOCK_LOG_MAX_FILES = previousMaxFiles;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
try {
|
|
59
|
+
const result = fn();
|
|
60
|
+
const maybePromise = result;
|
|
61
|
+
if (maybePromise && typeof maybePromise.finally === 'function') {
|
|
62
|
+
return maybePromise.finally(restore);
|
|
63
|
+
}
|
|
64
|
+
restore();
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
restore();
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function parseLogLine(line) {
|
|
73
|
+
return JSON.parse(line);
|
|
74
|
+
}
|
|
21
75
|
function plugin(id, dependsOn = []) {
|
|
22
76
|
return {
|
|
23
77
|
manifest: {
|
|
@@ -540,6 +594,7 @@ model = "deepseek-v4-flash"
|
|
|
540
594
|
plugins: {},
|
|
541
595
|
}),
|
|
542
596
|
getLogs: () => [],
|
|
597
|
+
getLogEntries: () => [],
|
|
543
598
|
readConfigFile: async () => ({
|
|
544
599
|
path: '',
|
|
545
600
|
exists: false,
|
|
@@ -562,6 +617,7 @@ model = "deepseek-v4-flash"
|
|
|
562
617
|
knowledgeAttachments: {},
|
|
563
618
|
workspaceRouter: {},
|
|
564
619
|
scheduler: {},
|
|
620
|
+
scheduledJobs: {},
|
|
565
621
|
start: async () => {
|
|
566
622
|
started = true;
|
|
567
623
|
},
|
|
@@ -587,20 +643,41 @@ model = "deepseek-v4-flash"
|
|
|
587
643
|
await controller.close();
|
|
588
644
|
strict_1.default.equal(stopped, true);
|
|
589
645
|
});
|
|
590
|
-
(0, node_test_1.default)('runtime logs are persisted to
|
|
646
|
+
(0, node_test_1.default)('runtime logs are persisted to unified sys and level logs', () => {
|
|
591
647
|
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-logs-'));
|
|
648
|
+
const logDir = (0, node_path_1.join)(userDataPath, 'logs');
|
|
592
649
|
try {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
650
|
+
withLogEnv(logDir, () => {
|
|
651
|
+
const runtime = (0, bootstrap_js_2.bootstrapLocalCoreRuntime)({
|
|
652
|
+
userDataPath,
|
|
653
|
+
enableKnowledge: false,
|
|
654
|
+
log: () => { },
|
|
655
|
+
});
|
|
656
|
+
runtime.state.pushLog('localcore-weixin send failed for sessionKey=test');
|
|
657
|
+
runtime.state.pushLog('second line');
|
|
658
|
+
const sysRaw = (0, node_fs_1.readFileSync)((0, node_path_1.join)(logDir, 'sys.log'), 'utf-8');
|
|
659
|
+
const errorRaw = (0, node_fs_1.readFileSync)((0, node_path_1.join)(logDir, 'error.log'), 'utf-8');
|
|
660
|
+
const infoRaw = (0, node_fs_1.readFileSync)((0, node_path_1.join)(logDir, 'info.log'), 'utf-8');
|
|
661
|
+
const sysLines = sysRaw.trim().split(/\r?\n/).map(parseLogLine);
|
|
662
|
+
strict_1.default.equal(runtime.state.logPath, (0, node_path_1.join)(logDir, 'sys.log'));
|
|
663
|
+
for (const fileName of ['sys.log', 'debug.log', 'info.log', 'warn.log', 'error.log']) {
|
|
664
|
+
strict_1.default.equal((0, node_fs_1.existsSync)((0, node_path_1.join)(logDir, fileName)), true);
|
|
665
|
+
}
|
|
666
|
+
strict_1.default.equal(sysLines.at(-2)?.level, 'error');
|
|
667
|
+
strict_1.default.match(sysLines.at(-2)?.ts || '', /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}$/);
|
|
668
|
+
strict_1.default.equal(sysLines.at(-2)?.message, 'localcore-weixin send failed for sessionKey=test');
|
|
669
|
+
strict_1.default.equal(sysLines.at(-1)?.level, 'info');
|
|
670
|
+
strict_1.default.equal(sysLines.at(-1)?.message, 'second line');
|
|
671
|
+
strict_1.default.match(errorRaw, /localcore-weixin send failed for sessionKey=test/);
|
|
672
|
+
strict_1.default.match(infoRaw, /second line/);
|
|
673
|
+
strict_1.default.deepEqual(runtime.state.getLogEntries('error', 10).map((entry) => entry.message), [
|
|
674
|
+
'localcore-weixin send failed for sessionKey=test',
|
|
675
|
+
]);
|
|
676
|
+
strict_1.default.deepEqual(runtime.state.getLogEntries('sys', 2).map((entry) => entry.message), [
|
|
677
|
+
'localcore-weixin send failed for sessionKey=test',
|
|
678
|
+
'second line',
|
|
679
|
+
]);
|
|
597
680
|
});
|
|
598
|
-
runtime.state.pushLog('localcore-weixin send failed for sessionKey=test');
|
|
599
|
-
runtime.state.pushLog('second line');
|
|
600
|
-
const logPath = (0, node_path_1.join)(userDataPath, 'runtime', 'local-core.log');
|
|
601
|
-
const raw = (0, node_fs_1.readFileSync)(logPath, 'utf-8');
|
|
602
|
-
strict_1.default.match(raw, /^\d{4}-\d{2}-\d{2}T.* localcore-weixin send failed for sessionKey=test/m);
|
|
603
|
-
strict_1.default.match(raw, /^\d{4}-\d{2}-\d{2}T.* second line/m);
|
|
604
681
|
}
|
|
605
682
|
finally {
|
|
606
683
|
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
@@ -608,15 +685,18 @@ model = "deepseek-v4-flash"
|
|
|
608
685
|
});
|
|
609
686
|
(0, node_test_1.default)('runtime getLogs reads from disk after state is recreated', () => {
|
|
610
687
|
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-disk-logs-'));
|
|
688
|
+
const logDir = (0, node_path_1.join)(userDataPath, 'logs');
|
|
611
689
|
try {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
690
|
+
withLogEnv(logDir, () => {
|
|
691
|
+
const state = (0, local_core_runtime_state_js_1.createLocalCoreRuntimeState)({ userDataPath });
|
|
692
|
+
state.pushLog('first persisted line');
|
|
693
|
+
state.pushLog('second persisted line');
|
|
694
|
+
const recreated = (0, local_core_runtime_state_js_1.createLocalCoreRuntimeState)({ userDataPath });
|
|
695
|
+
strict_1.default.deepEqual(recreated.getLogs(2).map((line) => parseLogLine(line).message), [
|
|
696
|
+
'first persisted line',
|
|
697
|
+
'second persisted line',
|
|
698
|
+
]);
|
|
699
|
+
});
|
|
620
700
|
}
|
|
621
701
|
finally {
|
|
622
702
|
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
@@ -624,11 +704,19 @@ model = "deepseek-v4-flash"
|
|
|
624
704
|
});
|
|
625
705
|
(0, node_test_1.default)('runtime getLogs fills from rotated log when current log has fewer lines', () => {
|
|
626
706
|
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-rotated-logs-'));
|
|
707
|
+
const logDir = (0, node_path_1.join)(userDataPath, 'logs');
|
|
627
708
|
try {
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
709
|
+
withLogEnv(logDir, () => {
|
|
710
|
+
const state = (0, local_core_runtime_state_js_1.createLocalCoreRuntimeState)({ userDataPath });
|
|
711
|
+
(0, node_fs_1.writeFileSync)(`${state.logPath}.1`, [
|
|
712
|
+
JSON.stringify({ ts: '2026-01-01 00:00:00.000', level: 'info', scope: 'test', message: 'old-1' }),
|
|
713
|
+
JSON.stringify({ ts: '2026-01-01 00:00:01.000', level: 'info', scope: 'test', message: 'old-2' }),
|
|
714
|
+
JSON.stringify({ ts: '2026-01-01 00:00:02.000', level: 'info', scope: 'test', message: 'old-3' }),
|
|
715
|
+
'',
|
|
716
|
+
].join('\n'), 'utf8');
|
|
717
|
+
(0, node_fs_1.writeFileSync)(state.logPath, `${JSON.stringify({ ts: '2026-01-01 00:00:03.000', level: 'info', scope: 'test', message: 'new-1' })}\n`, 'utf8');
|
|
718
|
+
strict_1.default.deepEqual(state.getLogs(3).map((line) => parseLogLine(line).message), ['old-2', 'old-3', 'new-1']);
|
|
719
|
+
});
|
|
632
720
|
}
|
|
633
721
|
finally {
|
|
634
722
|
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
@@ -636,30 +724,58 @@ model = "deepseek-v4-flash"
|
|
|
636
724
|
});
|
|
637
725
|
(0, node_test_1.default)('runtime getLogs returns only the requested tail lines from disk', () => {
|
|
638
726
|
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-tail-logs-'));
|
|
727
|
+
const logDir = (0, node_path_1.join)(userDataPath, 'logs');
|
|
639
728
|
try {
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
729
|
+
withLogEnv(logDir, () => {
|
|
730
|
+
const state = (0, local_core_runtime_state_js_1.createLocalCoreRuntimeState)({ userDataPath });
|
|
731
|
+
(0, node_fs_1.writeFileSync)(state.logPath, Array.from({ length: 1000 }, (_, index) => JSON.stringify({ ts: '2026-01-01 00:00:00.000', level: 'info', scope: 'test', message: `line-${index + 1}` })).join('\n') + '\n', 'utf8');
|
|
732
|
+
strict_1.default.deepEqual(state.getLogs(4).map((line) => parseLogLine(line).message), ['line-997', 'line-998', 'line-999', 'line-1000']);
|
|
733
|
+
});
|
|
643
734
|
}
|
|
644
735
|
finally {
|
|
645
736
|
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
646
737
|
}
|
|
647
738
|
});
|
|
648
|
-
(0, node_test_1.default)('
|
|
739
|
+
(0, node_test_1.default)('runtime logs rotate by file size', () => {
|
|
740
|
+
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-size-rotated-logs-'));
|
|
741
|
+
const logDir = (0, node_path_1.join)(userDataPath, 'logs');
|
|
742
|
+
try {
|
|
743
|
+
withLogEnv(logDir, () => {
|
|
744
|
+
const state = (0, local_core_runtime_state_js_1.createLocalCoreRuntimeState)({ userDataPath });
|
|
745
|
+
state.pushLog('first failed line with enough text to rotate');
|
|
746
|
+
state.pushLog('second failed line with enough text to rotate');
|
|
747
|
+
state.pushLog('third failed line with enough text to rotate');
|
|
748
|
+
const currentSys = (0, node_fs_1.readFileSync)((0, node_path_1.join)(logDir, 'sys.log'), 'utf8');
|
|
749
|
+
const rotatedSys = (0, node_fs_1.readFileSync)((0, node_path_1.join)(logDir, 'sys.log.1'), 'utf8');
|
|
750
|
+
const currentError = (0, node_fs_1.readFileSync)((0, node_path_1.join)(logDir, 'error.log'), 'utf8');
|
|
751
|
+
const rotatedError = (0, node_fs_1.readFileSync)((0, node_path_1.join)(logDir, 'error.log.1'), 'utf8');
|
|
752
|
+
strict_1.default.match(currentSys, /third failed line/);
|
|
753
|
+
strict_1.default.match(rotatedSys, /second failed line/);
|
|
754
|
+
strict_1.default.match(currentError, /third failed line/);
|
|
755
|
+
strict_1.default.match(rotatedError, /second failed line/);
|
|
756
|
+
}, { maxBytes: 120, maxFiles: 2 });
|
|
757
|
+
}
|
|
758
|
+
finally {
|
|
759
|
+
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
(0, node_test_1.default)('controller logs are persisted to sys.log', () => {
|
|
649
763
|
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-controller-logs-'));
|
|
764
|
+
const logDir = (0, node_path_1.join)(userDataPath, 'logs');
|
|
650
765
|
try {
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
766
|
+
withLogEnv(logDir, () => {
|
|
767
|
+
const runtime = (0, bootstrap_js_2.bootstrapLocalCoreRuntime)({
|
|
768
|
+
userDataPath,
|
|
769
|
+
enableKnowledge: false,
|
|
770
|
+
});
|
|
771
|
+
const controller = new local_core_controller_js_1.LocalCoreController(userDataPath, runtime);
|
|
772
|
+
const emittedLogs = [];
|
|
773
|
+
controller.on('logs', (line) => emittedLogs.push(line));
|
|
774
|
+
controller.handleLog('localcore-lark inbound message for project-1');
|
|
775
|
+
const raw = (0, node_fs_1.readFileSync)((0, node_path_1.join)(logDir, 'sys.log'), 'utf-8');
|
|
776
|
+
strict_1.default.deepEqual(emittedLogs, ['localcore-lark inbound message for project-1']);
|
|
777
|
+
strict_1.default.equal(parseLogLine(raw.trim().split(/\r?\n/).at(-1) || '').message, 'localcore-lark inbound message for project-1');
|
|
654
778
|
});
|
|
655
|
-
const controller = new local_core_controller_js_1.LocalCoreController(userDataPath, runtime);
|
|
656
|
-
const emittedLogs = [];
|
|
657
|
-
controller.on('logs', (line) => emittedLogs.push(line));
|
|
658
|
-
controller.handleLog('localcore-lark inbound message for project-1');
|
|
659
|
-
const logPath = (0, node_path_1.join)(userDataPath, 'runtime', 'local-core.log');
|
|
660
|
-
const raw = (0, node_fs_1.readFileSync)(logPath, 'utf-8');
|
|
661
|
-
strict_1.default.deepEqual(emittedLogs, ['localcore-lark inbound message for project-1']);
|
|
662
|
-
strict_1.default.match(raw, /^\d{4}-\d{2}-\d{2}T.* localcore-lark inbound message for project-1/m);
|
|
663
779
|
}
|
|
664
780
|
finally {
|
|
665
781
|
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
@@ -667,13 +783,15 @@ model = "deepseek-v4-flash"
|
|
|
667
783
|
});
|
|
668
784
|
(0, node_test_1.default)('controller buffers bootstrap logs until runtime state is assigned', () => {
|
|
669
785
|
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-bootstrap-logs-'));
|
|
786
|
+
const logDir = (0, node_path_1.join)(userDataPath, 'logs');
|
|
670
787
|
try {
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
788
|
+
withLogEnv(logDir, () => {
|
|
789
|
+
const controller = new local_core_controller_js_1.LocalCoreController(userDataPath);
|
|
790
|
+
const raw = (0, node_fs_1.readFileSync)((0, node_path_1.join)(logDir, 'sys.log'), 'utf-8');
|
|
791
|
+
strict_1.default.match(raw, /\[plugin:builtin\.agent-codex\] registered/);
|
|
792
|
+
strict_1.default.equal((raw.match(/\[plugin:builtin\.agent-codex\] registered/g) || []).length, 1);
|
|
793
|
+
void controller.close();
|
|
794
|
+
});
|
|
677
795
|
}
|
|
678
796
|
finally {
|
|
679
797
|
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
@@ -82,6 +82,50 @@ const local_core_controller_js_1 = require("../../services/local-ai-core/src/run
|
|
|
82
82
|
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
83
83
|
}
|
|
84
84
|
});
|
|
85
|
+
(0, node_test_1.default)('scheduler create from a bound thread preserves channel instance route', async () => {
|
|
86
|
+
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'scheduler-instance-route-'));
|
|
87
|
+
try {
|
|
88
|
+
const runtime = (0, bootstrap_js_1.bootstrapLocalCoreRuntime)({
|
|
89
|
+
userDataPath,
|
|
90
|
+
enableKnowledge: false,
|
|
91
|
+
log: () => { },
|
|
92
|
+
});
|
|
93
|
+
const controller = new local_core_controller_js_1.LocalCoreController(userDataPath, runtime);
|
|
94
|
+
const thread = runtime.store.createThread('workspace-a', 'Lark instance thread');
|
|
95
|
+
const now = new Date().toISOString();
|
|
96
|
+
runtime.store.upsertPlatformThreadBinding({
|
|
97
|
+
workspace_id: 'workspace-a',
|
|
98
|
+
platform: 'lark:lark-1',
|
|
99
|
+
chat_id: 'chat-1',
|
|
100
|
+
platform_user_id: 'user-1',
|
|
101
|
+
thread_id: thread.id,
|
|
102
|
+
last_platform_message_id: null,
|
|
103
|
+
created_at: now,
|
|
104
|
+
updated_at: now,
|
|
105
|
+
});
|
|
106
|
+
const job = await controller.createScheduledJob({
|
|
107
|
+
workspaceId: 'workspace-a',
|
|
108
|
+
threadId: thread.id,
|
|
109
|
+
executionMode: 'side-thread',
|
|
110
|
+
triggerType: 'cron',
|
|
111
|
+
cronExpr: '30 18 * * *',
|
|
112
|
+
promptTemplate: 'ping',
|
|
113
|
+
description: 'bound lark task',
|
|
114
|
+
enabled: true,
|
|
115
|
+
});
|
|
116
|
+
strict_1.default.equal(job.platform, 'lark:lark-1');
|
|
117
|
+
strict_1.default.deepEqual(job.route, {
|
|
118
|
+
type: 'channel.chat',
|
|
119
|
+
channelId: 'chat-1',
|
|
120
|
+
instanceId: 'lark-1',
|
|
121
|
+
participantId: 'user-1',
|
|
122
|
+
});
|
|
123
|
+
await controller.close();
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
127
|
+
}
|
|
128
|
+
});
|
|
85
129
|
(0, node_test_1.default)('Lark scheduled same-thread execution resolves the latest channel thread and keeps channel delivery', async () => {
|
|
86
130
|
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'scheduler-lark-latest-thread-'));
|
|
87
131
|
try {
|
|
@@ -170,6 +214,85 @@ const local_core_controller_js_1 = require("../../services/local-ai-core/src/run
|
|
|
170
214
|
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
171
215
|
}
|
|
172
216
|
});
|
|
217
|
+
(0, node_test_1.default)('Lark scheduled execution supports instance-qualified platform keys', async () => {
|
|
218
|
+
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'scheduler-lark-instance-'));
|
|
219
|
+
try {
|
|
220
|
+
const store = new local_core_acp_store_js_1.LocalCoreAcpStore(userDataPath);
|
|
221
|
+
const thread = store.createThread('workspace-a', 'Lark instance thread');
|
|
222
|
+
const now = new Date().toISOString();
|
|
223
|
+
store.upsertPlatformThreadBinding({
|
|
224
|
+
workspace_id: 'workspace-a',
|
|
225
|
+
platform: 'lark:lark-1',
|
|
226
|
+
chat_id: 'chat-1',
|
|
227
|
+
platform_user_id: 'user-1',
|
|
228
|
+
thread_id: thread.id,
|
|
229
|
+
last_platform_message_id: null,
|
|
230
|
+
created_at: now,
|
|
231
|
+
updated_at: now,
|
|
232
|
+
});
|
|
233
|
+
const job = store.createScheduledJob({
|
|
234
|
+
workspaceId: 'workspace-a',
|
|
235
|
+
platform: 'lark:lark-1',
|
|
236
|
+
route: { type: 'channel.chat', channelId: 'chat-1', participantId: 'user-1' },
|
|
237
|
+
executionMode: 'same-thread',
|
|
238
|
+
triggerType: 'cron',
|
|
239
|
+
cronExpr: '30 18 * * *',
|
|
240
|
+
promptTemplate: 'ping',
|
|
241
|
+
description: 'bound lark task',
|
|
242
|
+
enabled: true,
|
|
243
|
+
});
|
|
244
|
+
let deliveredRoute;
|
|
245
|
+
const adapter = new lark_schedule_adapter_js_1.LarkScheduleAdapter({
|
|
246
|
+
store,
|
|
247
|
+
getWorkspaceRouter: () => ({
|
|
248
|
+
getThread: async (threadId) => ({
|
|
249
|
+
id: threadId,
|
|
250
|
+
workspaceId: 'workspace-a',
|
|
251
|
+
title: 'Thread',
|
|
252
|
+
live: false,
|
|
253
|
+
updatedAt: now,
|
|
254
|
+
createdAt: now,
|
|
255
|
+
historyCount: 1,
|
|
256
|
+
excerpt: '',
|
|
257
|
+
bridgeSessionKey: '',
|
|
258
|
+
agentType: 'localcore-acp',
|
|
259
|
+
selectedKnowledgeBaseIds: [],
|
|
260
|
+
pendingPermissionRequest: null,
|
|
261
|
+
messages: [{ id: 'message-1', role: 'assistant', kind: 'final', content: 'pong', timestamp: now }],
|
|
262
|
+
}),
|
|
263
|
+
sendThreadMessage: async (threadId, _prompt, options) => {
|
|
264
|
+
strict_1.default.equal(threadId, thread.id);
|
|
265
|
+
strict_1.default.equal(options?.runtimeEnv?.LOCAL_AI_PLATFORM, 'lark');
|
|
266
|
+
strict_1.default.equal(options?.runtimeEnv?.LOCAL_AI_PLATFORM_INSTANCE_ID, 'lark-1');
|
|
267
|
+
strict_1.default.equal(options?.runtimeEnv?.LOCAL_AI_CHAT_ID, 'chat-1');
|
|
268
|
+
store.updateRun('run-1', threadId, 'completed');
|
|
269
|
+
return { runId: 'run-1' };
|
|
270
|
+
},
|
|
271
|
+
}),
|
|
272
|
+
getChannelRuntime: () => ({
|
|
273
|
+
muteThreadBridge: () => { },
|
|
274
|
+
unmuteThreadBridge: () => { },
|
|
275
|
+
sendScheduledMessage: async (_workspaceId, route) => {
|
|
276
|
+
deliveredRoute = route;
|
|
277
|
+
return 'platform-message-1';
|
|
278
|
+
},
|
|
279
|
+
}),
|
|
280
|
+
});
|
|
281
|
+
const result = await adapter.execute({ job, triggeredAt: now });
|
|
282
|
+
strict_1.default.equal(result.threadId, thread.id);
|
|
283
|
+
strict_1.default.equal(result.platformMessageId, 'platform-message-1');
|
|
284
|
+
strict_1.default.deepEqual(deliveredRoute, {
|
|
285
|
+
type: 'channel.chat',
|
|
286
|
+
channelId: 'chat-1',
|
|
287
|
+
instanceId: 'lark-1',
|
|
288
|
+
participantId: 'user-1',
|
|
289
|
+
});
|
|
290
|
+
store.close();
|
|
291
|
+
}
|
|
292
|
+
finally {
|
|
293
|
+
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
294
|
+
}
|
|
295
|
+
});
|
|
173
296
|
(0, node_test_1.default)('ACP runtime env includes the current workspace path for file returns', async () => {
|
|
174
297
|
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'workspace-env-'));
|
|
175
298
|
try {
|
|
@@ -25,6 +25,7 @@ const local_core_acp_permission_lifecycle_js_1 = require("../../services/local-a
|
|
|
25
25
|
const workspace_acp_permissions_js_1 = require("../../services/local-ai-core/src/acp/workspace-acp-permissions.js");
|
|
26
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
|
+
strict_1.default.deepEqual((0, server_routes_js_1.parseLocalAiCoreRoute)('GET', '/api/local/v1/logs'), { name: 'logs.list' });
|
|
28
29
|
strict_1.default.deepEqual((0, server_routes_js_1.parseLocalAiCoreRoute)('GET', '/api/local/v1/runtimes'), { name: 'runtimes.list' });
|
|
29
30
|
strict_1.default.deepEqual((0, server_routes_js_1.parseLocalAiCoreRoute)('POST', '/api/local/v1/runtimes/refresh'), { name: 'runtimes.refresh' });
|
|
30
31
|
strict_1.default.deepEqual((0, server_routes_js_1.parseLocalAiCoreRoute)('GET', '/api/local/v1/runtimes/codex'), {
|
|
@@ -3512,11 +3513,12 @@ const server_routes_js_1 = require("../../services/local-ai-core/src/runtime/ser
|
|
|
3512
3513
|
});
|
|
3513
3514
|
(0, node_test_1.default)('scheduled conversation executor uses execution policy hooks around a thread run', async () => {
|
|
3514
3515
|
const calls = [];
|
|
3516
|
+
let runtimeEnv;
|
|
3515
3517
|
const job = {
|
|
3516
3518
|
id: 'job-1',
|
|
3517
3519
|
workspaceId: '知识库',
|
|
3518
|
-
platform: 'lark',
|
|
3519
|
-
route: { type: 'channel.chat', channelId: 'chat-1', participantId: 'user-1', threadId: 'thread-1' },
|
|
3520
|
+
platform: 'lark:lark-1',
|
|
3521
|
+
route: { type: 'channel.chat', channelId: 'chat-1', instanceId: 'lark-1', participantId: 'user-1', threadId: 'thread-1' },
|
|
3520
3522
|
executionMode: 'same-thread',
|
|
3521
3523
|
triggerType: 'cron',
|
|
3522
3524
|
cronExpr: '*/2 * * * *',
|
|
@@ -3533,6 +3535,7 @@ const server_routes_js_1 = require("../../services/local-ai-core/src/runtime/ser
|
|
|
3533
3535
|
},
|
|
3534
3536
|
workspaceRouter: {
|
|
3535
3537
|
sendThreadMessage: async (threadId, prompt, options) => {
|
|
3538
|
+
runtimeEnv = options?.runtimeEnv;
|
|
3536
3539
|
calls.push(`send:${threadId}:${prompt}:${options?.permissionMode || ''}`);
|
|
3537
3540
|
return { runId: 'run-1' };
|
|
3538
3541
|
},
|
|
@@ -3549,7 +3552,7 @@ const server_routes_js_1 = require("../../services/local-ai-core/src/runtime/ser
|
|
|
3549
3552
|
kind: 'thread',
|
|
3550
3553
|
threadId: 'thread-1',
|
|
3551
3554
|
workspaceId: '知识库',
|
|
3552
|
-
platform: 'lark',
|
|
3555
|
+
platform: 'lark:lark-1',
|
|
3553
3556
|
route: job.route,
|
|
3554
3557
|
}),
|
|
3555
3558
|
beforeExecute: (target) => {
|
|
@@ -3564,6 +3567,13 @@ const server_routes_js_1 = require("../../services/local-ai-core/src/runtime/ser
|
|
|
3564
3567
|
'send:thread-1:ping:bypassPermissions',
|
|
3565
3568
|
'after:thread-1',
|
|
3566
3569
|
]);
|
|
3570
|
+
strict_1.default.deepEqual(runtimeEnv, {
|
|
3571
|
+
LOCAL_AI_PLATFORM: 'lark',
|
|
3572
|
+
LOCAL_AI_ROUTE_TYPE: 'channel.chat',
|
|
3573
|
+
LOCAL_AI_PLATFORM_INSTANCE_ID: 'lark-1',
|
|
3574
|
+
LOCAL_AI_CHAT_ID: 'chat-1',
|
|
3575
|
+
LOCAL_AI_PLATFORM_USER_ID: 'user-1',
|
|
3576
|
+
});
|
|
3567
3577
|
strict_1.default.equal(result.replyText, 'done');
|
|
3568
3578
|
});
|
|
3569
3579
|
(0, node_test_1.default)('local scheduler adapter runs a workspace thread without channel delivery', async () => {
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as h,r as t,az as v,j as e,L as j,B as d,C as y}from"./index-BYyDk28K.js";import{B as N}from"./Badge-VeSLCPPV.js";import{S as m}from"./Select-Dw4FCXhJ.js";import{P as b}from"./Page-DdDZN7AE.js";import{A as w}from"./arrow-left-CKfxNOXE.js";import{F as L}from"./funnel-pB5NegZB.js";import"./index-zTUUYax3.js";import"./chevron-down-CVIWFoXF.js";import"./check-CZYvOmIS.js";const C={debug:"text-gray-400",info:"text-blue-400",warn:"text-amber-400",error:"text-red-400"},S={debug:"default",info:"info",warn:"warning",error:"danger"};function I(){const{t:a}=h(),[i,x]=t.useState([]),[r,u]=t.useState("info"),[n,f]=t.useState("100"),[g,l]=t.useState(!0),o=t.useCallback(async()=>{l(!0);try{const s=await v({level:r,limit:n});x(s.entries||[])}finally{l(!1)}},[r,n]);return t.useEffect(()=>{o()},[o]),e.jsxs("div",{className:"space-y-4 animate-fade-in",children:[e.jsx(b,{title:a("system.logs"),description:"Filtered runtime logs for troubleshooting.",actions:e.jsx(j,{to:"/system",children:e.jsxs(d,{variant:"secondary",size:"sm",children:[e.jsx(w,{size:14})," ",a("nav.system")]})})}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(L,{size:14,className:"text-muted-foreground"}),e.jsxs(m,{value:r,onChange:s=>u(s.target.value),className:"w-auto",children:[e.jsx("option",{value:"debug",children:"Debug"}),e.jsx("option",{value:"info",children:"Info"}),e.jsx("option",{value:"warn",children:"Warn"}),e.jsx("option",{value:"error",children:"Error"})]})]}),e.jsxs(m,{value:n,onChange:s=>f(s.target.value),className:"w-auto",children:[e.jsx("option",{value:"50",children:"50"}),e.jsx("option",{value:"100",children:"100"}),e.jsx("option",{value:"500",children:"500"}),e.jsx("option",{value:"1000",children:"1000"})]}),e.jsx(d,{size:"sm",variant:"secondary",onClick:o,children:a("common.refresh")})]}),e.jsx(y,{children:g?e.jsx("div",{className:"text-muted-foreground animate-pulse text-sm",children:"Loading..."}):i.length===0?e.jsx("p",{className:"text-sm text-muted-foreground text-center py-8",children:a("common.noData")}):e.jsx("div",{className:"space-y-1 max-h-[65vh] overflow-y-auto font-mono text-xs",children:i.map((s,p)=>{var c;return e.jsxs("div",{className:"flex items-start gap-3 py-1.5 border-b last:border-0",children:[e.jsx("span",{className:"text-muted-foreground shrink-0 w-36",children:(c=s.time)==null?void 0:c.slice(0,19)}),e.jsx(N,{variant:S[s.level]||"default",children:s.level}),e.jsx("span",{className:`${C[s.level]||"text-gray-500"} flex-1`,children:s.message})]},p)})})})]})}export{I as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{z as t}from"./index-BYyDk28K.js";const e=()=>t.get("/projects"),r=o=>t.get(`/projects/${o}`);export{r as g,e as l};
|