@kafca/agentdock 0.1.22 → 0.1.24
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 +4 -0
- package/dist/renderer/assets/{Badge-B_rgzxYO.js → Badge-CXcUMqb-.js} +1 -1
- package/dist/renderer/assets/{Chat-CYtp6m7T.js → Chat-BRxdPzi-.js} +1 -1
- package/dist/renderer/assets/{ChatMarkdown-DOBMwa9d.js → ChatMarkdown-sWGBIfIb.js} +1 -1
- package/dist/renderer/assets/{Config-DppMSPHF.js → Config-DqxuxIGg.js} +1 -1
- package/dist/renderer/assets/{CronList-BDtB1SuA.js → CronList-OgHxbti5.js} +1 -1
- package/dist/renderer/assets/{Dashboard-iFlRnd7Y.js → Dashboard-DmklXiH1.js} +2 -2
- package/dist/renderer/assets/{EmptyState-bKDt_T88.js → EmptyState-BvDmi8dq.js} +1 -1
- package/dist/renderer/assets/{KnowledgeDetail-CKPhKPIg.js → KnowledgeDetail-Bj59Hdpo.js} +2 -2
- package/dist/renderer/assets/{KnowledgeHome-CFeJre6i.js → KnowledgeHome-CigQ-nSo.js} +3 -3
- package/dist/renderer/assets/{Logs-CyxSVOFK.js → Logs-Bfc7gBpY.js} +1 -1
- package/dist/renderer/assets/{Modal-CxPnk1Ey.js → Modal-CfmiFknz.js} +1 -1
- package/dist/renderer/assets/{Page-kU9vubzj.js → Page-BxtLEw_b.js} +1 -1
- package/dist/renderer/assets/{ProjectDetail-D9FY9NWZ.js → ProjectDetail-CcUphxGm.js} +1 -1
- package/dist/renderer/assets/{ProjectList-DIwr2TXg.js → ProjectList-CVkvDIfy.js} +1 -1
- package/dist/renderer/assets/{Select-BaWoz5Dn.js → Select-DgQMZ0MD.js} +1 -1
- package/dist/renderer/assets/{SessionChat-Cm9CW8Zx.js → SessionChat-CRmGKfBx.js} +1 -1
- package/dist/renderer/assets/{SessionList-UPnWlXXO.js → SessionList-D0E8XbYw.js} +1 -1
- package/dist/renderer/assets/ThreadChat-DUgqZSBB.js +23 -0
- package/dist/renderer/assets/Workspace-Q4g4rlRT.js +14 -0
- package/dist/renderer/assets/{arrow-left-BmZAVGV7.js → arrow-left-BySN_zhF.js} +1 -1
- package/dist/renderer/assets/{book-open-DZ3GXFgI.js → book-open-BGlrnrTc.js} +1 -1
- package/dist/renderer/assets/{check-CeVSvDCv.js → check-BiJogEa5.js} +1 -1
- package/dist/renderer/assets/{chevron-down-yryuMoQ-.js → chevron-down-D2fHRJv6.js} +1 -1
- package/dist/renderer/assets/{circle-eASsFISH.js → circle-CIcjixmI.js} +1 -1
- package/dist/renderer/assets/desktop-DAXY9Bxv.js +4 -0
- package/dist/renderer/assets/desktop-DyA_NYew.js +1 -0
- package/dist/renderer/assets/{funnel-pwAe2Ixp.js → funnel-BUzwb-id.js} +1 -1
- package/dist/renderer/assets/{heart-B2Sp-bCm.js → heart-DZEQ1z_V.js} +1 -1
- package/dist/renderer/assets/{index-BC3MWbS1.js → index-CB_KyLOr.js} +39 -39
- package/dist/renderer/assets/{index-Cse2Br64.js → index-DgsIo4vJ.js} +3 -3
- package/dist/renderer/assets/{pencil-BfEunUF3.js → pencil-DGL4agcl.js} +1 -1
- package/dist/renderer/assets/{play-Dcs9Lj_Z.js → play-DzasCLM4.js} +1 -1
- package/dist/renderer/assets/{plug-B_YschQe.js → plug-dubNMe_m.js} +1 -1
- package/dist/renderer/assets/{plus-Pqo-cXHQ.js → plus-DN4kML4k.js} +1 -1
- package/dist/renderer/assets/projects-migPtfRe.js +1 -0
- package/dist/renderer/assets/{save-BKM5yi1A.js → save-CNIc9tjl.js} +1 -1
- package/dist/renderer/assets/{search-BU42h10M.js → search-C0EGbF3I.js} +1 -1
- package/dist/renderer/assets/{server-DA5t3Rtr.js → server-BMxQ4zmc.js} +1 -1
- package/dist/renderer/assets/{session-utils-Cr9VhNSq.js → session-utils-Bf5O-iMi.js} +1 -1
- package/dist/renderer/assets/{sessions-bvV8ZMfX.js → sessions-BMSs6rEI.js} +1 -1
- package/dist/renderer/assets/{shield-check-BeOJKur_.js → shield-check-i3Tf1TUz.js} +1 -1
- package/dist/renderer/assets/{trash-2-CQ7HKO3q.js → trash-2-SKrcp18f.js} +1 -1
- package/dist/renderer/assets/{user-CtFjY9SV.js → user-cNUZddjZ.js} +1 -1
- package/dist/renderer/assets/{wifi-off-Ci5m0ysf.js → wifi-off-Dyb84ANR.js} +1 -1
- package/dist/renderer/index.html +1 -1
- package/dist-electron/electron/channel-content.test.js +29 -0
- package/dist-electron/electron/lac-cli.test.js +49 -4
- package/dist-electron/electron/local-core-acp-content.test.js +39 -0
- package/dist-electron/electron/local-core-contracts.test.js +67 -0
- package/dist-electron/electron/local-core-refactor.test.js +628 -0
- package/dist-electron/electron/plugin-kernel.test.js +74 -14
- package/dist-electron/electron/workspace-task-store.test.js +124 -0
- package/dist-electron/packages/contracts/src/local-core.js +110 -0
- package/dist-electron/packages/core-sdk/src/index.js +40 -20
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-content.js +25 -4
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-response-processor.js +3 -2
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-store.js +44 -28
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +5 -1
- package/dist-electron/services/local-ai-core/src/acp/workspace-acp-permissions.js +15 -6
- package/dist-electron/services/local-ai-core/src/channel/lark/cards.js +210 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/config.js +54 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +280 -496
- package/dist-electron/services/local-ai-core/src/channel/lark/registration.js +50 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/runtime-state.js +191 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/types.js +2 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/content.js +23 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/plugin.js +31 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/config.js +125 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +164 -352
- package/dist-electron/services/local-ai-core/src/channel/weixin/transport.js +169 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/types.js +2 -0
- package/dist-electron/services/local-ai-core/src/cli/lac.js +19 -16
- package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +5 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/channel-lark-plugin.js +18 -39
- package/dist-electron/services/local-ai-core/src/plugins/builtin/channel-weixin-plugin.js +18 -39
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +55 -44
- package/dist-electron/services/local-ai-core/src/runtime/server.js +10 -8
- package/dist-electron/services/local-ai-core/src/scheduler/job-id.js +15 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduler-service.js +30 -5
- package/dist-electron/shared/desktop.js +37 -5
- package/dist-electron/src/pages/Threads/thread-chat-model.js +57 -0
- package/dist-electron/src/pages/Threads/thread-chat-permission.test.js +70 -0
- package/package.json +1 -1
- package/dist/renderer/assets/ThreadChat-YvVsACW3.js +0 -23
- package/dist/renderer/assets/Workspace-ST7V8u6T.js +0 -14
- package/dist/renderer/assets/desktop-Che1cbpE.js +0 -4
- package/dist/renderer/assets/desktop-DkrP_s-b.js +0 -1
- package/dist/renderer/assets/projects-BCj0k_Gy.js +0 -1
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const node_test_1 = __importDefault(require("node:test"));
|
|
7
7
|
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
8
|
+
const node_events_1 = require("node:events");
|
|
8
9
|
const node_fs_1 = require("node:fs");
|
|
9
10
|
const node_os_1 = require("node:os");
|
|
10
11
|
const node_path_1 = require("node:path");
|
|
@@ -15,6 +16,7 @@ const event_bus_js_1 = require("../services/local-ai-core/src/kernel/event-bus.j
|
|
|
15
16
|
const lifecycle_manager_js_1 = require("../services/local-ai-core/src/kernel/lifecycle-manager.js");
|
|
16
17
|
const plugin_registry_js_1 = require("../services/local-ai-core/src/kernel/plugin-registry.js");
|
|
17
18
|
const local_core_controller_js_1 = require("../services/local-ai-core/src/runtime/local-core-controller.js");
|
|
19
|
+
const server_js_1 = require("../services/local-ai-core/src/runtime/server.js");
|
|
18
20
|
function plugin(id, dependsOn = []) {
|
|
19
21
|
return {
|
|
20
22
|
manifest: {
|
|
@@ -334,6 +336,29 @@ type = "codex"
|
|
|
334
336
|
let stopped = false;
|
|
335
337
|
let channelRefreshes = 0;
|
|
336
338
|
let weixinRefreshes = 0;
|
|
339
|
+
const channelRuntime = {
|
|
340
|
+
platform: 'test-channel',
|
|
341
|
+
routeType: 'channel.test',
|
|
342
|
+
refreshBindings: async () => {
|
|
343
|
+
channelRefreshes++;
|
|
344
|
+
},
|
|
345
|
+
getQrCode: async (workspaceId, instanceId) => ({
|
|
346
|
+
ticket: `ticket:${workspaceId}`,
|
|
347
|
+
expiresIn: 60,
|
|
348
|
+
qrCodeUrl: 'https://example.test/qr',
|
|
349
|
+
instanceId,
|
|
350
|
+
}),
|
|
351
|
+
checkQrCodeStatus: async (_workspaceId, ticket) => ({
|
|
352
|
+
status: ticket === 'signed-ticket' ? 'signed' : 'wait',
|
|
353
|
+
}),
|
|
354
|
+
};
|
|
355
|
+
const weixinChannelRuntime = {
|
|
356
|
+
platform: 'weixin',
|
|
357
|
+
routeType: 'channel.chat',
|
|
358
|
+
refreshBindings: async () => {
|
|
359
|
+
weixinRefreshes++;
|
|
360
|
+
},
|
|
361
|
+
};
|
|
337
362
|
const controller = new local_core_controller_js_1.LocalCoreController('/tmp/local-core-controller-injected', {
|
|
338
363
|
kernel: {
|
|
339
364
|
context: {
|
|
@@ -389,20 +414,9 @@ type = "codex"
|
|
|
389
414
|
},
|
|
390
415
|
store: {},
|
|
391
416
|
agentRuntimes: [],
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
refreshBindings: async () => {
|
|
396
|
-
channelRefreshes++;
|
|
397
|
-
},
|
|
398
|
-
},
|
|
399
|
-
weixinChannelRuntime: {
|
|
400
|
-
platform: 'weixin',
|
|
401
|
-
routeType: 'channel.chat',
|
|
402
|
-
refreshBindings: async () => {
|
|
403
|
-
weixinRefreshes++;
|
|
404
|
-
},
|
|
405
|
-
},
|
|
417
|
+
channelRuntimes: [channelRuntime, weixinChannelRuntime],
|
|
418
|
+
channelRuntime,
|
|
419
|
+
weixinChannelRuntime,
|
|
406
420
|
knowledgeProvider: {},
|
|
407
421
|
knowledgeAttachments: {},
|
|
408
422
|
workspaceRouter: {},
|
|
@@ -417,6 +431,15 @@ type = "codex"
|
|
|
417
431
|
await controller.init();
|
|
418
432
|
strict_1.default.equal(started, true);
|
|
419
433
|
strict_1.default.deepEqual(await controller.getCapabilities(), capabilitySnapshot);
|
|
434
|
+
strict_1.default.deepEqual(await controller.getChannelQrCode('test-channel', 'workspace-1', 'instance-1'), {
|
|
435
|
+
ticket: 'ticket:workspace-1',
|
|
436
|
+
expiresIn: 60,
|
|
437
|
+
qrCodeUrl: 'https://example.test/qr',
|
|
438
|
+
instanceId: 'instance-1',
|
|
439
|
+
});
|
|
440
|
+
strict_1.default.deepEqual(await controller.checkChannelQrCodeStatus('test-channel', 'workspace-1', 'signed-ticket'), {
|
|
441
|
+
status: 'signed',
|
|
442
|
+
});
|
|
420
443
|
await controller.saveStructuredConfigFile({ projects: [] });
|
|
421
444
|
strict_1.default.equal(channelRefreshes, 1);
|
|
422
445
|
strict_1.default.equal(weixinRefreshes, 1);
|
|
@@ -505,6 +528,43 @@ type = "codex"
|
|
|
505
528
|
await lifecycle.stopAll();
|
|
506
529
|
strict_1.default.deepEqual(calls, ['init', 'start', 'stop']);
|
|
507
530
|
});
|
|
531
|
+
(0, node_test_1.default)('server QR routes dispatch through generic channel bindings', async () => {
|
|
532
|
+
const calls = [];
|
|
533
|
+
const bindings = Object.assign(new node_events_1.EventEmitter(), {
|
|
534
|
+
getChannelQrCode: async (platform, workspaceId, instanceId) => {
|
|
535
|
+
calls.push(`get:${platform}:${workspaceId}:${instanceId || ''}`);
|
|
536
|
+
return {
|
|
537
|
+
ticket: 'ticket-1',
|
|
538
|
+
expiresIn: 60,
|
|
539
|
+
qrCodeUrl: 'https://example.test/qr',
|
|
540
|
+
instanceId,
|
|
541
|
+
};
|
|
542
|
+
},
|
|
543
|
+
checkChannelQrCodeStatus: async (platform, workspaceId, ticket, instanceId) => {
|
|
544
|
+
calls.push(`check:${platform}:${workspaceId}:${ticket}:${instanceId || ''}`);
|
|
545
|
+
return { status: 'signed' };
|
|
546
|
+
},
|
|
547
|
+
});
|
|
548
|
+
const server = new server_js_1.LocalAiCoreServer(bindings, { port: 0 });
|
|
549
|
+
await server.start();
|
|
550
|
+
try {
|
|
551
|
+
const address = server.server.address();
|
|
552
|
+
const baseUrl = `http://127.0.0.1:${address.port}/api/local/v1`;
|
|
553
|
+
const qrResponse = await fetch(`${baseUrl}/platforms/slack/workspace-1/qrcode?instance_id=bot-1`, { method: 'POST' });
|
|
554
|
+
const qrBody = await qrResponse.json();
|
|
555
|
+
strict_1.default.equal(qrBody.data.ticket, 'ticket-1');
|
|
556
|
+
const statusResponse = await fetch(`${baseUrl}/platforms/slack/workspace-1/qrcode/status?ticket=ticket-1&instance_id=bot-1`);
|
|
557
|
+
const statusBody = await statusResponse.json();
|
|
558
|
+
strict_1.default.equal(statusBody.data.status, 'signed');
|
|
559
|
+
strict_1.default.deepEqual(calls, [
|
|
560
|
+
'get:slack:workspace-1:bot-1',
|
|
561
|
+
'check:slack:workspace-1:ticket-1:bot-1',
|
|
562
|
+
]);
|
|
563
|
+
}
|
|
564
|
+
finally {
|
|
565
|
+
await server.stop();
|
|
566
|
+
}
|
|
567
|
+
});
|
|
508
568
|
(0, node_test_1.default)('channel and scheduler capabilities use registry targets instead of Lark-specific routing', () => {
|
|
509
569
|
const registry = new plugin_registry_js_1.LocalCorePluginRegistry();
|
|
510
570
|
const capabilities = new capability_registry_js_1.LocalCoreCapabilityRegistry();
|
|
@@ -9,6 +9,7 @@ const node_fs_1 = require("node:fs");
|
|
|
9
9
|
const node_path_1 = require("node:path");
|
|
10
10
|
const node_os_1 = require("node:os");
|
|
11
11
|
const local_core_acp_store_js_1 = require("../services/local-ai-core/src/acp/local-core-acp-store.js");
|
|
12
|
+
const scheduler_service_js_1 = require("../services/local-ai-core/src/scheduler/scheduler-service.js");
|
|
12
13
|
(0, node_test_1.default)('workspace registry entries persist in LocalCoreAcpStore', () => {
|
|
13
14
|
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'workspace-registry-'));
|
|
14
15
|
try {
|
|
@@ -34,6 +35,86 @@ const local_core_acp_store_js_1 = require("../services/local-ai-core/src/acp/loc
|
|
|
34
35
|
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
35
36
|
}
|
|
36
37
|
});
|
|
38
|
+
(0, node_test_1.default)('scheduler uses short ids for new jobs and resolves legacy full ids by short id', () => {
|
|
39
|
+
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'scheduler-id-store-'));
|
|
40
|
+
try {
|
|
41
|
+
const store = new local_core_acp_store_js_1.LocalCoreAcpStore(userDataPath);
|
|
42
|
+
const scheduler = new scheduler_service_js_1.SchedulerService({
|
|
43
|
+
store,
|
|
44
|
+
triggers: [],
|
|
45
|
+
executors: [],
|
|
46
|
+
eventBus: { emit: () => { }, on: () => () => { } },
|
|
47
|
+
});
|
|
48
|
+
const created = scheduler.createJob({
|
|
49
|
+
workspaceId: 'workspace-a',
|
|
50
|
+
platform: 'local',
|
|
51
|
+
route: { type: 'local.thread', channelId: 'workspace-a', threadId: 'thread-1' },
|
|
52
|
+
executionMode: 'side-thread',
|
|
53
|
+
triggerType: 'cron',
|
|
54
|
+
cronExpr: '30 18 * * *',
|
|
55
|
+
promptTemplate: 'ping',
|
|
56
|
+
description: 'daily ping',
|
|
57
|
+
enabled: true,
|
|
58
|
+
});
|
|
59
|
+
strict_1.default.match(created.id, /^[0-9a-f]{8}$/);
|
|
60
|
+
const legacy = store.createScheduledJob({
|
|
61
|
+
workspaceId: 'workspace-a',
|
|
62
|
+
platform: 'local',
|
|
63
|
+
route: { type: 'local.thread', channelId: 'workspace-a', threadId: 'thread-1' },
|
|
64
|
+
executionMode: 'side-thread',
|
|
65
|
+
triggerType: 'cron',
|
|
66
|
+
cronExpr: '0 9 * * *',
|
|
67
|
+
promptTemplate: 'legacy',
|
|
68
|
+
description: 'legacy job',
|
|
69
|
+
enabled: true,
|
|
70
|
+
});
|
|
71
|
+
store.db.prepare('UPDATE scheduled_jobs SET id = ? WHERE id = ?').run('job:826aff79-570b-4308-822e-18318e2c96ba', legacy.id);
|
|
72
|
+
strict_1.default.equal(scheduler.getJob('826aff79')?.id, 'job:826aff79-570b-4308-822e-18318e2c96ba');
|
|
73
|
+
scheduler.updateJob('826aff79', { description: 'updated legacy job' });
|
|
74
|
+
strict_1.default.equal(scheduler.getJob('826aff79')?.description, 'updated legacy job');
|
|
75
|
+
scheduler.deleteJob('826aff79');
|
|
76
|
+
strict_1.default.equal(scheduler.getJob('826aff79'), undefined);
|
|
77
|
+
strict_1.default.throws(() => scheduler.deleteJob('826aff79'), /Scheduled job not found: 826aff79/);
|
|
78
|
+
store.close();
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
(0, node_test_1.default)('scheduled jobs normalize enum-like input before persistence', () => {
|
|
85
|
+
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'scheduler-enum-store-'));
|
|
86
|
+
try {
|
|
87
|
+
const store = new local_core_acp_store_js_1.LocalCoreAcpStore(userDataPath);
|
|
88
|
+
const created = store.createScheduledJob({
|
|
89
|
+
workspaceId: 'workspace-a',
|
|
90
|
+
platform: ' Lark ',
|
|
91
|
+
route: { type: 'channel.chat', channelId: 'chat-1', participantId: 'user-1' },
|
|
92
|
+
executionMode: 'side_thread',
|
|
93
|
+
triggerType: 'CRON',
|
|
94
|
+
cronExpr: '30 18 * * *',
|
|
95
|
+
promptTemplate: 'ping',
|
|
96
|
+
description: 'daily ping',
|
|
97
|
+
enabled: true,
|
|
98
|
+
});
|
|
99
|
+
strict_1.default.equal(created.platform, 'lark');
|
|
100
|
+
strict_1.default.equal(created.executionMode, 'side-thread');
|
|
101
|
+
strict_1.default.equal(created.triggerType, 'cron');
|
|
102
|
+
const updated = store.updateScheduledJob(created.id, {
|
|
103
|
+
executionMode: 'same_thread',
|
|
104
|
+
triggerType: 'one time',
|
|
105
|
+
runAt: '2026-05-04T10:00:00.000Z',
|
|
106
|
+
cronExpr: '',
|
|
107
|
+
});
|
|
108
|
+
strict_1.default.equal(updated.executionMode, 'same-thread');
|
|
109
|
+
strict_1.default.equal(updated.triggerType, 'once');
|
|
110
|
+
strict_1.default.equal(updated.runAt, '2026-05-04T10:00:00.000Z');
|
|
111
|
+
strict_1.default.equal(updated.cronExpr, undefined);
|
|
112
|
+
store.close();
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
116
|
+
}
|
|
117
|
+
});
|
|
37
118
|
(0, node_test_1.default)('agent tasks persist, update status, and can be found by run id', () => {
|
|
38
119
|
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agent-task-store-'));
|
|
39
120
|
try {
|
|
@@ -64,3 +145,46 @@ const local_core_acp_store_js_1 = require("../services/local-ai-core/src/acp/loc
|
|
|
64
145
|
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
65
146
|
}
|
|
66
147
|
});
|
|
148
|
+
(0, node_test_1.default)('agent task and run statuses normalize before persistence', () => {
|
|
149
|
+
const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'task-run-status-store-'));
|
|
150
|
+
try {
|
|
151
|
+
const store = new local_core_acp_store_js_1.LocalCoreAcpStore(userDataPath);
|
|
152
|
+
const task = store.createAgentTask({
|
|
153
|
+
workspaceId: 'workspace-a',
|
|
154
|
+
deviceId: 'device-a',
|
|
155
|
+
runtimeId: 'runtime-a',
|
|
156
|
+
title: 'Normalize states',
|
|
157
|
+
status: 'waiting for user',
|
|
158
|
+
});
|
|
159
|
+
strict_1.default.equal(task.status, 'waiting_for_user');
|
|
160
|
+
strict_1.default.equal(store.listAgentTasks({ status: 'waiting for user' }).tasks.length, 1);
|
|
161
|
+
const updated = store.updateAgentTask(task.taskId, { status: 'canceled' });
|
|
162
|
+
strict_1.default.equal(updated.status, 'cancelled');
|
|
163
|
+
strict_1.default.equal(updated.timeline.at(-1)?.status, 'cancelled');
|
|
164
|
+
const thread = store.createThread('workspace-a', 'Thread');
|
|
165
|
+
store.updateRun('run-1', thread.id, 'awaiting input');
|
|
166
|
+
strict_1.default.equal(store.getRun('run-1')?.status, 'awaiting_input');
|
|
167
|
+
store.updateRun('run-1', thread.id, 'canceled');
|
|
168
|
+
strict_1.default.equal(store.getRun('run-1')?.status, 'interrupted');
|
|
169
|
+
const job = store.createScheduledJob({
|
|
170
|
+
workspaceId: 'workspace-a',
|
|
171
|
+
platform: 'local',
|
|
172
|
+
route: { type: 'local.thread', channelId: 'workspace-a', threadId: 'thread-1' },
|
|
173
|
+
executionMode: 'same-thread',
|
|
174
|
+
triggerType: 'cron',
|
|
175
|
+
cronExpr: '0 9 * * *',
|
|
176
|
+
promptTemplate: 'ping',
|
|
177
|
+
description: 'daily ping',
|
|
178
|
+
enabled: true,
|
|
179
|
+
});
|
|
180
|
+
const run = store.createScheduledJobRun(job.id, 'complete');
|
|
181
|
+
strict_1.default.equal(run.status, 'succeeded');
|
|
182
|
+
const skipped = store.updateScheduledJobRun(run.id, { status: 'cancelled' });
|
|
183
|
+
strict_1.default.equal(skipped.status, 'skipped');
|
|
184
|
+
strict_1.default.equal(store.getScheduledJob(job.id)?.lastStatus, 'skipped');
|
|
185
|
+
store.close();
|
|
186
|
+
}
|
|
187
|
+
finally {
|
|
188
|
+
(0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
|
|
189
|
+
}
|
|
190
|
+
});
|
|
@@ -1,2 +1,112 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeApprovalRequestStatus = normalizeApprovalRequestStatus;
|
|
4
|
+
exports.normalizeAgentTaskStatus = normalizeAgentTaskStatus;
|
|
5
|
+
exports.normalizeChannelContentPartType = normalizeChannelContentPartType;
|
|
6
|
+
exports.normalizeScheduledJobExecutionMode = normalizeScheduledJobExecutionMode;
|
|
7
|
+
exports.normalizeScheduledJobTriggerType = normalizeScheduledJobTriggerType;
|
|
8
|
+
exports.normalizeChannelPlatform = normalizeChannelPlatform;
|
|
9
|
+
exports.normalizeRunStatus = normalizeRunStatus;
|
|
10
|
+
exports.normalizeScheduledJobRunStatus = normalizeScheduledJobRunStatus;
|
|
11
|
+
function normalizeApprovalRequestStatus(value, fallback = 'pending') {
|
|
12
|
+
const normalized = normalizeContractEnumValue(value || fallback).replace(/-/g, '_');
|
|
13
|
+
if (normalized === 'pending' ||
|
|
14
|
+
normalized === 'approved' ||
|
|
15
|
+
normalized === 'rejected' ||
|
|
16
|
+
normalized === 'cancelled' ||
|
|
17
|
+
normalized === 'expired') {
|
|
18
|
+
return normalized;
|
|
19
|
+
}
|
|
20
|
+
if (normalized === 'approve') {
|
|
21
|
+
return 'approved';
|
|
22
|
+
}
|
|
23
|
+
if (normalized === 'reject') {
|
|
24
|
+
return 'rejected';
|
|
25
|
+
}
|
|
26
|
+
if (normalized === 'canceled') {
|
|
27
|
+
return 'cancelled';
|
|
28
|
+
}
|
|
29
|
+
throw new Error('Approval request status must be pending, approved, rejected, cancelled, or expired.');
|
|
30
|
+
}
|
|
31
|
+
function normalizeAgentTaskStatus(value, fallback = 'created') {
|
|
32
|
+
const normalized = normalizeContractEnumValue(value || fallback).replace(/-/g, '_');
|
|
33
|
+
if (normalized === 'created' ||
|
|
34
|
+
normalized === 'queued' ||
|
|
35
|
+
normalized === 'running' ||
|
|
36
|
+
normalized === 'waiting_for_user' ||
|
|
37
|
+
normalized === 'completed' ||
|
|
38
|
+
normalized === 'failed' ||
|
|
39
|
+
normalized === 'cancelled') {
|
|
40
|
+
return normalized;
|
|
41
|
+
}
|
|
42
|
+
if (normalized === 'canceled') {
|
|
43
|
+
return 'cancelled';
|
|
44
|
+
}
|
|
45
|
+
throw new Error('Agent task status must be created, queued, running, waiting_for_user, completed, failed, or cancelled.');
|
|
46
|
+
}
|
|
47
|
+
function normalizeChannelContentPartType(value) {
|
|
48
|
+
const normalized = normalizeContractEnumValue(value).replace(/-/g, '_');
|
|
49
|
+
if (normalized === 'text' ||
|
|
50
|
+
normalized === 'image' ||
|
|
51
|
+
normalized === 'file' ||
|
|
52
|
+
normalized === 'permission_card') {
|
|
53
|
+
return normalized;
|
|
54
|
+
}
|
|
55
|
+
throw new Error('Channel content part type must be text, image, file, or permission_card.');
|
|
56
|
+
}
|
|
57
|
+
function normalizeContractEnumValue(value) {
|
|
58
|
+
return String(value || '').trim().toLowerCase().replace(/[\s_]+/g, '-');
|
|
59
|
+
}
|
|
60
|
+
function normalizeScheduledJobExecutionMode(value, fallback = 'same-thread') {
|
|
61
|
+
const normalized = normalizeContractEnumValue(value || fallback);
|
|
62
|
+
if (normalized === 'same-thread' || normalized === 'side-thread') {
|
|
63
|
+
return normalized;
|
|
64
|
+
}
|
|
65
|
+
throw new Error('Scheduled job execution mode must be same-thread or side-thread.');
|
|
66
|
+
}
|
|
67
|
+
function normalizeScheduledJobTriggerType(value, fallback = 'cron') {
|
|
68
|
+
const normalized = normalizeContractEnumValue(value || fallback);
|
|
69
|
+
if (normalized === 'cron' || normalized === 'once' || normalized === 'one-time') {
|
|
70
|
+
return normalized === 'one-time' ? 'once' : normalized;
|
|
71
|
+
}
|
|
72
|
+
throw new Error('Scheduled job trigger type must be cron or once.');
|
|
73
|
+
}
|
|
74
|
+
function normalizeChannelPlatform(value) {
|
|
75
|
+
const normalized = String(value || '').trim().toLowerCase();
|
|
76
|
+
if (!normalized) {
|
|
77
|
+
throw new Error('Channel platform is required.');
|
|
78
|
+
}
|
|
79
|
+
return normalized;
|
|
80
|
+
}
|
|
81
|
+
function normalizeRunStatus(value, fallback = 'queued') {
|
|
82
|
+
const normalized = normalizeContractEnumValue(value || fallback).replace(/-/g, '_');
|
|
83
|
+
if (normalized === 'queued' ||
|
|
84
|
+
normalized === 'running' ||
|
|
85
|
+
normalized === 'awaiting_input' ||
|
|
86
|
+
normalized === 'completed' ||
|
|
87
|
+
normalized === 'failed' ||
|
|
88
|
+
normalized === 'interrupted') {
|
|
89
|
+
return normalized;
|
|
90
|
+
}
|
|
91
|
+
if (normalized === 'cancelled' || normalized === 'canceled') {
|
|
92
|
+
return 'interrupted';
|
|
93
|
+
}
|
|
94
|
+
throw new Error('Run status must be queued, running, awaiting_input, completed, failed, or interrupted.');
|
|
95
|
+
}
|
|
96
|
+
function normalizeScheduledJobRunStatus(value, fallback = 'queued') {
|
|
97
|
+
const normalized = normalizeContractEnumValue(value || fallback).replace(/-/g, '_');
|
|
98
|
+
if (normalized === 'queued' ||
|
|
99
|
+
normalized === 'running' ||
|
|
100
|
+
normalized === 'succeeded' ||
|
|
101
|
+
normalized === 'failed' ||
|
|
102
|
+
normalized === 'skipped') {
|
|
103
|
+
return normalized;
|
|
104
|
+
}
|
|
105
|
+
if (normalized === 'complete' || normalized === 'completed' || normalized === 'success') {
|
|
106
|
+
return 'succeeded';
|
|
107
|
+
}
|
|
108
|
+
if (normalized === 'cancelled' || normalized === 'canceled') {
|
|
109
|
+
return 'skipped';
|
|
110
|
+
}
|
|
111
|
+
throw new Error('Scheduled job run status must be queued, running, succeeded, failed, or skipped.');
|
|
112
|
+
}
|
|
@@ -26,6 +26,8 @@ exports.listChannelPendingPairings = listChannelPendingPairings;
|
|
|
26
26
|
exports.approveChannelPairing = approveChannelPairing;
|
|
27
27
|
exports.rejectChannelPairing = rejectChannelPairing;
|
|
28
28
|
exports.listChannelAuthorizedUsers = listChannelAuthorizedUsers;
|
|
29
|
+
exports.getChannelQrCode = getChannelQrCode;
|
|
30
|
+
exports.checkChannelQrCodeStatus = checkChannelQrCodeStatus;
|
|
29
31
|
exports.listLarkGateways = listLarkGateways;
|
|
30
32
|
exports.getLarkGatewayStatus = getLarkGatewayStatus;
|
|
31
33
|
exports.testLarkConnection = testLarkConnection;
|
|
@@ -35,6 +37,8 @@ exports.listLarkPendingPairings = listLarkPendingPairings;
|
|
|
35
37
|
exports.approveLarkPairing = approveLarkPairing;
|
|
36
38
|
exports.rejectLarkPairing = rejectLarkPairing;
|
|
37
39
|
exports.listLarkAuthorizedUsers = listLarkAuthorizedUsers;
|
|
40
|
+
exports.getLarkQrCode = getLarkQrCode;
|
|
41
|
+
exports.checkLarkQrCodeStatus = checkLarkQrCodeStatus;
|
|
38
42
|
exports.getWeixinQrCode = getWeixinQrCode;
|
|
39
43
|
exports.checkWeixinQrCodeStatus = checkWeixinQrCodeStatus;
|
|
40
44
|
exports.listWorkspaces = listWorkspaces;
|
|
@@ -236,17 +240,20 @@ async function saveCoreSettings(input) {
|
|
|
236
240
|
async function listChannelGateways(platform) {
|
|
237
241
|
return coreRequest('GET', `/platforms/${encodeURIComponent(platform)}`);
|
|
238
242
|
}
|
|
239
|
-
|
|
240
|
-
return
|
|
243
|
+
function instanceSuffix(instanceId) {
|
|
244
|
+
return instanceId ? `?instance_id=${encodeURIComponent(instanceId)}` : '';
|
|
241
245
|
}
|
|
242
|
-
async function
|
|
243
|
-
return coreRequest('
|
|
246
|
+
async function getChannelGatewayStatus(platform, workspaceId, instanceId) {
|
|
247
|
+
return coreRequest('GET', `/platforms/${encodeURIComponent(platform)}/${encodeURIComponent(workspaceId)}${instanceSuffix(instanceId)}`);
|
|
244
248
|
}
|
|
245
|
-
async function
|
|
246
|
-
return coreRequest('POST', `/platforms/${encodeURIComponent(platform)}/${encodeURIComponent(workspaceId)}/
|
|
249
|
+
async function testChannelConnection(platform, workspaceId, instanceId) {
|
|
250
|
+
return coreRequest('POST', `/platforms/${encodeURIComponent(platform)}/${encodeURIComponent(workspaceId)}/test${instanceSuffix(instanceId)}`);
|
|
247
251
|
}
|
|
248
|
-
async function
|
|
249
|
-
return coreRequest('POST', `/platforms/${encodeURIComponent(platform)}/${encodeURIComponent(workspaceId)}/
|
|
252
|
+
async function enableChannelGateway(platform, workspaceId, instanceId) {
|
|
253
|
+
return coreRequest('POST', `/platforms/${encodeURIComponent(platform)}/${encodeURIComponent(workspaceId)}/enable${instanceSuffix(instanceId)}`);
|
|
254
|
+
}
|
|
255
|
+
async function disableChannelGateway(platform, workspaceId, instanceId) {
|
|
256
|
+
return coreRequest('POST', `/platforms/${encodeURIComponent(platform)}/${encodeURIComponent(workspaceId)}/disable${instanceSuffix(instanceId)}`);
|
|
250
257
|
}
|
|
251
258
|
async function listChannelPendingPairings(platform, workspaceId) {
|
|
252
259
|
const suffix = workspaceId ? `?workspace_id=${encodeURIComponent(workspaceId)}` : '';
|
|
@@ -262,20 +269,27 @@ async function listChannelAuthorizedUsers(platform, workspaceId) {
|
|
|
262
269
|
const suffix = workspaceId ? `?workspace_id=${encodeURIComponent(workspaceId)}` : '';
|
|
263
270
|
return coreRequest('GET', `/platforms/${encodeURIComponent(platform)}/users${suffix}`);
|
|
264
271
|
}
|
|
272
|
+
async function getChannelQrCode(platform, workspaceId, instanceId) {
|
|
273
|
+
return coreRequest('POST', `/platforms/${encodeURIComponent(platform)}/${encodeURIComponent(workspaceId)}/qrcode${instanceSuffix(instanceId)}`);
|
|
274
|
+
}
|
|
275
|
+
async function checkChannelQrCodeStatus(platform, workspaceId, ticket, instanceId) {
|
|
276
|
+
const suffix = `?ticket=${encodeURIComponent(ticket)}${instanceId ? `&instance_id=${encodeURIComponent(instanceId)}` : ''}`;
|
|
277
|
+
return coreRequest('GET', `/platforms/${encodeURIComponent(platform)}/${encodeURIComponent(workspaceId)}/qrcode/status${suffix}`);
|
|
278
|
+
}
|
|
265
279
|
async function listLarkGateways() {
|
|
266
280
|
return listChannelGateways('lark');
|
|
267
281
|
}
|
|
268
|
-
async function getLarkGatewayStatus(workspaceId) {
|
|
269
|
-
return getChannelGatewayStatus('lark', workspaceId);
|
|
282
|
+
async function getLarkGatewayStatus(workspaceId, instanceId) {
|
|
283
|
+
return getChannelGatewayStatus('lark', workspaceId, instanceId);
|
|
270
284
|
}
|
|
271
|
-
async function testLarkConnection(workspaceId) {
|
|
272
|
-
return testChannelConnection('lark', workspaceId);
|
|
285
|
+
async function testLarkConnection(workspaceId, instanceId) {
|
|
286
|
+
return testChannelConnection('lark', workspaceId, instanceId);
|
|
273
287
|
}
|
|
274
|
-
async function enableLarkGateway(workspaceId) {
|
|
275
|
-
return enableChannelGateway('lark', workspaceId);
|
|
288
|
+
async function enableLarkGateway(workspaceId, instanceId) {
|
|
289
|
+
return enableChannelGateway('lark', workspaceId, instanceId);
|
|
276
290
|
}
|
|
277
|
-
async function disableLarkGateway(workspaceId) {
|
|
278
|
-
return disableChannelGateway('lark', workspaceId);
|
|
291
|
+
async function disableLarkGateway(workspaceId, instanceId) {
|
|
292
|
+
return disableChannelGateway('lark', workspaceId, instanceId);
|
|
279
293
|
}
|
|
280
294
|
async function listLarkPendingPairings(workspaceId) {
|
|
281
295
|
return listChannelPendingPairings('lark', workspaceId);
|
|
@@ -289,11 +303,17 @@ async function rejectLarkPairing(code) {
|
|
|
289
303
|
async function listLarkAuthorizedUsers(workspaceId) {
|
|
290
304
|
return listChannelAuthorizedUsers('lark', workspaceId);
|
|
291
305
|
}
|
|
292
|
-
async function
|
|
293
|
-
return
|
|
306
|
+
async function getLarkQrCode(workspaceId, instanceId) {
|
|
307
|
+
return getChannelQrCode('lark', workspaceId, instanceId);
|
|
308
|
+
}
|
|
309
|
+
async function checkLarkQrCodeStatus(workspaceId, ticket, instanceId) {
|
|
310
|
+
return checkChannelQrCodeStatus('lark', workspaceId, ticket, instanceId);
|
|
311
|
+
}
|
|
312
|
+
async function getWeixinQrCode(workspaceId, instanceId) {
|
|
313
|
+
return getChannelQrCode('weixin', workspaceId, instanceId);
|
|
294
314
|
}
|
|
295
|
-
async function checkWeixinQrCodeStatus(workspaceId, ticket) {
|
|
296
|
-
return
|
|
315
|
+
async function checkWeixinQrCodeStatus(workspaceId, ticket, instanceId) {
|
|
316
|
+
return checkChannelQrCodeStatus('weixin', workspaceId, ticket, instanceId);
|
|
297
317
|
}
|
|
298
318
|
async function listWorkspaces() {
|
|
299
319
|
return coreRequest('GET', '/workspaces');
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.normalizeThreadMessageInput = normalizeThreadMessageInput;
|
|
4
4
|
exports.createTextMessageInput = createTextMessageInput;
|
|
5
|
+
const index_js_1 = require("../../../../packages/contracts/src/index.js");
|
|
5
6
|
function normalizeThreadMessageInput(input) {
|
|
6
7
|
if (typeof input === 'string') {
|
|
7
8
|
return {
|
|
@@ -32,7 +33,13 @@ function isSupportedContentPart(part) {
|
|
|
32
33
|
if (!part || typeof part !== 'object') {
|
|
33
34
|
return false;
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
+
let type;
|
|
37
|
+
try {
|
|
38
|
+
type = (0, index_js_1.normalizeChannelContentPartType)(part.type);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
36
43
|
if (type === 'text') {
|
|
37
44
|
return Boolean(String(part.text || ''));
|
|
38
45
|
}
|
|
@@ -40,6 +47,10 @@ function isSupportedContentPart(part) {
|
|
|
40
47
|
const image = part;
|
|
41
48
|
return Boolean(String(image.data || image.uri || ''));
|
|
42
49
|
}
|
|
50
|
+
if (type === 'file') {
|
|
51
|
+
const file = part;
|
|
52
|
+
return Boolean(String(file.data || file.uri || file.path || ''));
|
|
53
|
+
}
|
|
43
54
|
return false;
|
|
44
55
|
}
|
|
45
56
|
function summarizeContentParts(parts) {
|
|
@@ -52,9 +63,19 @@ function summarizeContentParts(parts) {
|
|
|
52
63
|
if (text) {
|
|
53
64
|
return text;
|
|
54
65
|
}
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
66
|
+
const summaries = parts
|
|
67
|
+
.map((part) => {
|
|
68
|
+
if (part.type === 'image') {
|
|
69
|
+
return part.fileName ? `[Image: ${part.fileName}]` : '[Image]';
|
|
70
|
+
}
|
|
71
|
+
if (part.type === 'file') {
|
|
72
|
+
return part.fileName ? `[File: ${part.fileName}]` : '[File]';
|
|
73
|
+
}
|
|
74
|
+
return '';
|
|
75
|
+
})
|
|
76
|
+
.filter(Boolean);
|
|
77
|
+
if (summaries.length > 0) {
|
|
78
|
+
return summaries.join('\n');
|
|
58
79
|
}
|
|
59
80
|
return '';
|
|
60
81
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.LocalCoreAcpResponseProcessor = void 0;
|
|
4
4
|
const cron_command_detector_js_1 = require("../scheduler/cron-command-detector.js");
|
|
5
|
+
const job_id_js_1 = require("../scheduler/job-id.js");
|
|
5
6
|
class LocalCoreAcpResponseProcessor {
|
|
6
7
|
options;
|
|
7
8
|
constructor(options) {
|
|
@@ -82,7 +83,7 @@ class LocalCoreAcpResponseProcessor {
|
|
|
82
83
|
scheduleDescription: command.scheduleDescription,
|
|
83
84
|
message: command.message,
|
|
84
85
|
});
|
|
85
|
-
return `已创建定时任务:${job.description || command.name},计划 ${command.scheduleDescription}(${command.schedule}),ID: ${job.id}`;
|
|
86
|
+
return `已创建定时任务:${job.description || command.name},计划 ${command.scheduleDescription}(${command.schedule}),ID: ${(0, job_id_js_1.toPublicScheduledJobId)(job.id)}`;
|
|
86
87
|
}
|
|
87
88
|
case 'list': {
|
|
88
89
|
const jobs = await this.options.scheduler.listJobsForThread(threadId);
|
|
@@ -91,7 +92,7 @@ class LocalCoreAcpResponseProcessor {
|
|
|
91
92
|
}
|
|
92
93
|
return [
|
|
93
94
|
'当前对话定时任务:',
|
|
94
|
-
...jobs.map((job) => `- ${job.description || job.id} | ${job.triggerType === 'cron' ? job.cronExpr : job.runAt} | ${job.enabled ? 'enabled' : 'disabled'} | ${job.id}`),
|
|
95
|
+
...jobs.map((job) => `- ${job.description || (0, job_id_js_1.toPublicScheduledJobId)(job.id)} | ${job.triggerType === 'cron' ? job.cronExpr : job.runAt} | ${job.enabled ? 'enabled' : 'disabled'} | ${(0, job_id_js_1.toPublicScheduledJobId)(job.id)}`),
|
|
95
96
|
].join('\n');
|
|
96
97
|
}
|
|
97
98
|
case 'delete': {
|