@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.
Files changed (89) hide show
  1. package/README.md +4 -0
  2. package/dist/renderer/assets/{Badge-B_rgzxYO.js → Badge-CXcUMqb-.js} +1 -1
  3. package/dist/renderer/assets/{Chat-CYtp6m7T.js → Chat-BRxdPzi-.js} +1 -1
  4. package/dist/renderer/assets/{ChatMarkdown-DOBMwa9d.js → ChatMarkdown-sWGBIfIb.js} +1 -1
  5. package/dist/renderer/assets/{Config-DppMSPHF.js → Config-DqxuxIGg.js} +1 -1
  6. package/dist/renderer/assets/{CronList-BDtB1SuA.js → CronList-OgHxbti5.js} +1 -1
  7. package/dist/renderer/assets/{Dashboard-iFlRnd7Y.js → Dashboard-DmklXiH1.js} +2 -2
  8. package/dist/renderer/assets/{EmptyState-bKDt_T88.js → EmptyState-BvDmi8dq.js} +1 -1
  9. package/dist/renderer/assets/{KnowledgeDetail-CKPhKPIg.js → KnowledgeDetail-Bj59Hdpo.js} +2 -2
  10. package/dist/renderer/assets/{KnowledgeHome-CFeJre6i.js → KnowledgeHome-CigQ-nSo.js} +3 -3
  11. package/dist/renderer/assets/{Logs-CyxSVOFK.js → Logs-Bfc7gBpY.js} +1 -1
  12. package/dist/renderer/assets/{Modal-CxPnk1Ey.js → Modal-CfmiFknz.js} +1 -1
  13. package/dist/renderer/assets/{Page-kU9vubzj.js → Page-BxtLEw_b.js} +1 -1
  14. package/dist/renderer/assets/{ProjectDetail-D9FY9NWZ.js → ProjectDetail-CcUphxGm.js} +1 -1
  15. package/dist/renderer/assets/{ProjectList-DIwr2TXg.js → ProjectList-CVkvDIfy.js} +1 -1
  16. package/dist/renderer/assets/{Select-BaWoz5Dn.js → Select-DgQMZ0MD.js} +1 -1
  17. package/dist/renderer/assets/{SessionChat-Cm9CW8Zx.js → SessionChat-CRmGKfBx.js} +1 -1
  18. package/dist/renderer/assets/{SessionList-UPnWlXXO.js → SessionList-D0E8XbYw.js} +1 -1
  19. package/dist/renderer/assets/ThreadChat-DUgqZSBB.js +23 -0
  20. package/dist/renderer/assets/Workspace-Q4g4rlRT.js +14 -0
  21. package/dist/renderer/assets/{arrow-left-BmZAVGV7.js → arrow-left-BySN_zhF.js} +1 -1
  22. package/dist/renderer/assets/{book-open-DZ3GXFgI.js → book-open-BGlrnrTc.js} +1 -1
  23. package/dist/renderer/assets/{check-CeVSvDCv.js → check-BiJogEa5.js} +1 -1
  24. package/dist/renderer/assets/{chevron-down-yryuMoQ-.js → chevron-down-D2fHRJv6.js} +1 -1
  25. package/dist/renderer/assets/{circle-eASsFISH.js → circle-CIcjixmI.js} +1 -1
  26. package/dist/renderer/assets/desktop-DAXY9Bxv.js +4 -0
  27. package/dist/renderer/assets/desktop-DyA_NYew.js +1 -0
  28. package/dist/renderer/assets/{funnel-pwAe2Ixp.js → funnel-BUzwb-id.js} +1 -1
  29. package/dist/renderer/assets/{heart-B2Sp-bCm.js → heart-DZEQ1z_V.js} +1 -1
  30. package/dist/renderer/assets/{index-BC3MWbS1.js → index-CB_KyLOr.js} +39 -39
  31. package/dist/renderer/assets/{index-Cse2Br64.js → index-DgsIo4vJ.js} +3 -3
  32. package/dist/renderer/assets/{pencil-BfEunUF3.js → pencil-DGL4agcl.js} +1 -1
  33. package/dist/renderer/assets/{play-Dcs9Lj_Z.js → play-DzasCLM4.js} +1 -1
  34. package/dist/renderer/assets/{plug-B_YschQe.js → plug-dubNMe_m.js} +1 -1
  35. package/dist/renderer/assets/{plus-Pqo-cXHQ.js → plus-DN4kML4k.js} +1 -1
  36. package/dist/renderer/assets/projects-migPtfRe.js +1 -0
  37. package/dist/renderer/assets/{save-BKM5yi1A.js → save-CNIc9tjl.js} +1 -1
  38. package/dist/renderer/assets/{search-BU42h10M.js → search-C0EGbF3I.js} +1 -1
  39. package/dist/renderer/assets/{server-DA5t3Rtr.js → server-BMxQ4zmc.js} +1 -1
  40. package/dist/renderer/assets/{session-utils-Cr9VhNSq.js → session-utils-Bf5O-iMi.js} +1 -1
  41. package/dist/renderer/assets/{sessions-bvV8ZMfX.js → sessions-BMSs6rEI.js} +1 -1
  42. package/dist/renderer/assets/{shield-check-BeOJKur_.js → shield-check-i3Tf1TUz.js} +1 -1
  43. package/dist/renderer/assets/{trash-2-CQ7HKO3q.js → trash-2-SKrcp18f.js} +1 -1
  44. package/dist/renderer/assets/{user-CtFjY9SV.js → user-cNUZddjZ.js} +1 -1
  45. package/dist/renderer/assets/{wifi-off-Ci5m0ysf.js → wifi-off-Dyb84ANR.js} +1 -1
  46. package/dist/renderer/index.html +1 -1
  47. package/dist-electron/electron/channel-content.test.js +29 -0
  48. package/dist-electron/electron/lac-cli.test.js +49 -4
  49. package/dist-electron/electron/local-core-acp-content.test.js +39 -0
  50. package/dist-electron/electron/local-core-contracts.test.js +67 -0
  51. package/dist-electron/electron/local-core-refactor.test.js +628 -0
  52. package/dist-electron/electron/plugin-kernel.test.js +74 -14
  53. package/dist-electron/electron/workspace-task-store.test.js +124 -0
  54. package/dist-electron/packages/contracts/src/local-core.js +110 -0
  55. package/dist-electron/packages/core-sdk/src/index.js +40 -20
  56. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-content.js +25 -4
  57. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-response-processor.js +3 -2
  58. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-store.js +44 -28
  59. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +5 -1
  60. package/dist-electron/services/local-ai-core/src/acp/workspace-acp-permissions.js +15 -6
  61. package/dist-electron/services/local-ai-core/src/channel/lark/cards.js +210 -0
  62. package/dist-electron/services/local-ai-core/src/channel/lark/config.js +54 -0
  63. package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +280 -496
  64. package/dist-electron/services/local-ai-core/src/channel/lark/registration.js +50 -0
  65. package/dist-electron/services/local-ai-core/src/channel/lark/runtime-state.js +191 -0
  66. package/dist-electron/services/local-ai-core/src/channel/lark/types.js +2 -0
  67. package/dist-electron/services/local-ai-core/src/channel/shared/content.js +23 -0
  68. package/dist-electron/services/local-ai-core/src/channel/shared/plugin.js +31 -0
  69. package/dist-electron/services/local-ai-core/src/channel/weixin/config.js +125 -0
  70. package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +164 -352
  71. package/dist-electron/services/local-ai-core/src/channel/weixin/transport.js +169 -0
  72. package/dist-electron/services/local-ai-core/src/channel/weixin/types.js +2 -0
  73. package/dist-electron/services/local-ai-core/src/cli/lac.js +19 -16
  74. package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +5 -0
  75. package/dist-electron/services/local-ai-core/src/plugins/builtin/channel-lark-plugin.js +18 -39
  76. package/dist-electron/services/local-ai-core/src/plugins/builtin/channel-weixin-plugin.js +18 -39
  77. package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +55 -44
  78. package/dist-electron/services/local-ai-core/src/runtime/server.js +10 -8
  79. package/dist-electron/services/local-ai-core/src/scheduler/job-id.js +15 -0
  80. package/dist-electron/services/local-ai-core/src/scheduler/scheduler-service.js +30 -5
  81. package/dist-electron/shared/desktop.js +37 -5
  82. package/dist-electron/src/pages/Threads/thread-chat-model.js +57 -0
  83. package/dist-electron/src/pages/Threads/thread-chat-permission.test.js +70 -0
  84. package/package.json +1 -1
  85. package/dist/renderer/assets/ThreadChat-YvVsACW3.js +0 -23
  86. package/dist/renderer/assets/Workspace-ST7V8u6T.js +0 -14
  87. package/dist/renderer/assets/desktop-Che1cbpE.js +0 -4
  88. package/dist/renderer/assets/desktop-DkrP_s-b.js +0 -1
  89. 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
- channelRuntime: {
393
- platform: 'test-channel',
394
- routeType: 'channel.test',
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
- async function getChannelGatewayStatus(platform, workspaceId) {
240
- return coreRequest('GET', `/platforms/${encodeURIComponent(platform)}/${encodeURIComponent(workspaceId)}`);
243
+ function instanceSuffix(instanceId) {
244
+ return instanceId ? `?instance_id=${encodeURIComponent(instanceId)}` : '';
241
245
  }
242
- async function testChannelConnection(platform, workspaceId) {
243
- return coreRequest('POST', `/platforms/${encodeURIComponent(platform)}/${encodeURIComponent(workspaceId)}/test`);
246
+ async function getChannelGatewayStatus(platform, workspaceId, instanceId) {
247
+ return coreRequest('GET', `/platforms/${encodeURIComponent(platform)}/${encodeURIComponent(workspaceId)}${instanceSuffix(instanceId)}`);
244
248
  }
245
- async function enableChannelGateway(platform, workspaceId) {
246
- return coreRequest('POST', `/platforms/${encodeURIComponent(platform)}/${encodeURIComponent(workspaceId)}/enable`);
249
+ async function testChannelConnection(platform, workspaceId, instanceId) {
250
+ return coreRequest('POST', `/platforms/${encodeURIComponent(platform)}/${encodeURIComponent(workspaceId)}/test${instanceSuffix(instanceId)}`);
247
251
  }
248
- async function disableChannelGateway(platform, workspaceId) {
249
- return coreRequest('POST', `/platforms/${encodeURIComponent(platform)}/${encodeURIComponent(workspaceId)}/disable`);
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 getWeixinQrCode(workspaceId) {
293
- return coreRequest('POST', `/platforms/weixin/${encodeURIComponent(workspaceId)}/qrcode`);
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 coreRequest('GET', `/platforms/weixin/${encodeURIComponent(workspaceId)}/qrcode/status?ticket=${encodeURIComponent(ticket)}`);
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
- const type = String(part.type || '');
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 imageCount = parts.filter((part) => part.type === 'image').length;
56
- if (imageCount > 0) {
57
- return imageCount === 1 ? '[Image]' : `[${imageCount} images]`;
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': {