@kafca/agentdock 0.1.22 → 0.1.23

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 (72) hide show
  1. package/README.md +3 -0
  2. package/dist/renderer/assets/{Badge-B_rgzxYO.js → Badge-C2K5apfV.js} +1 -1
  3. package/dist/renderer/assets/{Chat-CYtp6m7T.js → Chat-DI2YeVKb.js} +1 -1
  4. package/dist/renderer/assets/{ChatMarkdown-DOBMwa9d.js → ChatMarkdown-DMAr15Oi.js} +1 -1
  5. package/dist/renderer/assets/{Config-DppMSPHF.js → Config-7rP3EuUf.js} +1 -1
  6. package/dist/renderer/assets/{CronList-BDtB1SuA.js → CronList-81QslYE8.js} +1 -1
  7. package/dist/renderer/assets/{Dashboard-iFlRnd7Y.js → Dashboard-Db2T7rSZ.js} +2 -2
  8. package/dist/renderer/assets/{EmptyState-bKDt_T88.js → EmptyState-BBJ3cTvB.js} +1 -1
  9. package/dist/renderer/assets/{KnowledgeDetail-CKPhKPIg.js → KnowledgeDetail-Dz_6flG3.js} +2 -2
  10. package/dist/renderer/assets/{KnowledgeHome-CFeJre6i.js → KnowledgeHome-DIh046mN.js} +3 -3
  11. package/dist/renderer/assets/{Logs-CyxSVOFK.js → Logs-BXBtHJLf.js} +1 -1
  12. package/dist/renderer/assets/{Modal-CxPnk1Ey.js → Modal-BB2Av_Xs.js} +1 -1
  13. package/dist/renderer/assets/{Page-kU9vubzj.js → Page-DPSdvMgU.js} +1 -1
  14. package/dist/renderer/assets/{ProjectDetail-D9FY9NWZ.js → ProjectDetail-C6EWGvGg.js} +1 -1
  15. package/dist/renderer/assets/{ProjectList-DIwr2TXg.js → ProjectList-BBo5ygnS.js} +1 -1
  16. package/dist/renderer/assets/{Select-BaWoz5Dn.js → Select-CNX-Tx_O.js} +1 -1
  17. package/dist/renderer/assets/{SessionChat-Cm9CW8Zx.js → SessionChat-BIn46jqZ.js} +1 -1
  18. package/dist/renderer/assets/{SessionList-UPnWlXXO.js → SessionList-CZt6f1Rd.js} +1 -1
  19. package/dist/renderer/assets/{ThreadChat-YvVsACW3.js → ThreadChat-BotD0gKQ.js} +1 -1
  20. package/dist/renderer/assets/Workspace-C_4tdpjX.js +14 -0
  21. package/dist/renderer/assets/{arrow-left-BmZAVGV7.js → arrow-left-cHr5wkpq.js} +1 -1
  22. package/dist/renderer/assets/{book-open-DZ3GXFgI.js → book-open-4nx5C8T-.js} +1 -1
  23. package/dist/renderer/assets/{check-CeVSvDCv.js → check-exTS-R-x.js} +1 -1
  24. package/dist/renderer/assets/{chevron-down-yryuMoQ-.js → chevron-down-DSvxXQa0.js} +1 -1
  25. package/dist/renderer/assets/{circle-eASsFISH.js → circle-DyvEovdw.js} +1 -1
  26. package/dist/renderer/assets/desktop-B-KVT10D.js +1 -0
  27. package/dist/renderer/assets/{desktop-Che1cbpE.js → desktop-CVibRyAw.js} +3 -3
  28. package/dist/renderer/assets/{funnel-pwAe2Ixp.js → funnel-DA9qVdTy.js} +1 -1
  29. package/dist/renderer/assets/{heart-B2Sp-bCm.js → heart-DuEV0ZRJ.js} +1 -1
  30. package/dist/renderer/assets/{index-Cse2Br64.js → index-BgflqkCN.js} +3 -3
  31. package/dist/renderer/assets/{index-BC3MWbS1.js → index-Biz-aexG.js} +39 -39
  32. package/dist/renderer/assets/{pencil-BfEunUF3.js → pencil-DBDxeNmO.js} +1 -1
  33. package/dist/renderer/assets/{play-Dcs9Lj_Z.js → play-IzlP83_7.js} +1 -1
  34. package/dist/renderer/assets/{plug-B_YschQe.js → plug-CuT-qFnW.js} +1 -1
  35. package/dist/renderer/assets/{plus-Pqo-cXHQ.js → plus-DEqgkn63.js} +1 -1
  36. package/dist/renderer/assets/projects-DDtDN1rc.js +1 -0
  37. package/dist/renderer/assets/{save-BKM5yi1A.js → save-D4sRo07y.js} +1 -1
  38. package/dist/renderer/assets/{search-BU42h10M.js → search-DbPZLuV8.js} +1 -1
  39. package/dist/renderer/assets/{server-DA5t3Rtr.js → server-D1jUQmwN.js} +1 -1
  40. package/dist/renderer/assets/{session-utils-Cr9VhNSq.js → session-utils-Aife8ep2.js} +1 -1
  41. package/dist/renderer/assets/{sessions-bvV8ZMfX.js → sessions-DaH3H7gC.js} +1 -1
  42. package/dist/renderer/assets/{shield-check-BeOJKur_.js → shield-check-BGwUFWNr.js} +1 -1
  43. package/dist/renderer/assets/{trash-2-CQ7HKO3q.js → trash-2-CIFBioBa.js} +1 -1
  44. package/dist/renderer/assets/{user-CtFjY9SV.js → user-CnKcvHdo.js} +1 -1
  45. package/dist/renderer/assets/{wifi-off-Ci5m0ysf.js → wifi-off-ClO53WGa.js} +1 -1
  46. package/dist/renderer/index.html +1 -1
  47. package/dist-electron/electron/local-core-refactor.test.js +505 -0
  48. package/dist-electron/electron/plugin-kernel.test.js +74 -14
  49. package/dist-electron/packages/core-sdk/src/index.js +40 -20
  50. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +5 -1
  51. package/dist-electron/services/local-ai-core/src/acp/workspace-acp-permissions.js +55 -3
  52. package/dist-electron/services/local-ai-core/src/channel/lark/cards.js +210 -0
  53. package/dist-electron/services/local-ai-core/src/channel/lark/config.js +54 -0
  54. package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +212 -471
  55. package/dist-electron/services/local-ai-core/src/channel/lark/registration.js +50 -0
  56. package/dist-electron/services/local-ai-core/src/channel/lark/runtime-state.js +191 -0
  57. package/dist-electron/services/local-ai-core/src/channel/lark/types.js +2 -0
  58. package/dist-electron/services/local-ai-core/src/channel/shared/plugin.js +31 -0
  59. package/dist-electron/services/local-ai-core/src/channel/weixin/config.js +125 -0
  60. package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +141 -324
  61. package/dist-electron/services/local-ai-core/src/channel/weixin/transport.js +169 -0
  62. package/dist-electron/services/local-ai-core/src/channel/weixin/types.js +2 -0
  63. package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +5 -0
  64. package/dist-electron/services/local-ai-core/src/plugins/builtin/channel-lark-plugin.js +18 -39
  65. package/dist-electron/services/local-ai-core/src/plugins/builtin/channel-weixin-plugin.js +18 -39
  66. package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +55 -44
  67. package/dist-electron/services/local-ai-core/src/runtime/server.js +10 -8
  68. package/dist-electron/shared/desktop.js +10 -0
  69. package/package.json +1 -1
  70. package/dist/renderer/assets/Workspace-ST7V8u6T.js +0 -14
  71. package/dist/renderer/assets/desktop-DkrP_s-b.js +0 -1
  72. 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();
@@ -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');
@@ -86,7 +86,11 @@ class LocalCoreAcpTurnCoordinator {
86
86
  optionId: String(option?.optionId || '').trim(),
87
87
  name: String(option?.name || option?.optionId || '').trim(),
88
88
  kind: String(option?.kind || '').trim(),
89
- normalizedAction: (0, workspace_acp_permissions_js_1.normalizePermissionAction)(option?.kind),
89
+ normalizedAction: (0, workspace_acp_permissions_js_1.normalizePermissionOptionAction)({
90
+ optionId: option?.optionId,
91
+ name: option?.name,
92
+ kind: option?.kind,
93
+ }),
90
94
  }))
91
95
  .filter((option) => option.optionId)
92
96
  : [];
@@ -1,21 +1,73 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.normalizePermissionAction = normalizePermissionAction;
4
+ exports.normalizePermissionOptionAction = normalizePermissionOptionAction;
4
5
  exports.formatToolCallContent = formatToolCallContent;
5
6
  exports.toPermissionButtonRows = toPermissionButtonRows;
6
7
  function normalizePermissionAction(kind) {
7
8
  const normalized = String(kind || '').trim().toLowerCase();
8
- if (normalized === 'allow_always') {
9
+ if (isAllowAllPermissionToken(normalized)) {
9
10
  return 'allow all';
10
11
  }
11
- if (normalized.startsWith('allow')) {
12
+ if (isAllowPermissionToken(normalized)) {
12
13
  return 'allow';
13
14
  }
14
- if (normalized.startsWith('reject')) {
15
+ if (isDenyPermissionToken(normalized)) {
16
+ return 'deny';
17
+ }
18
+ return '';
19
+ }
20
+ function normalizePermissionOptionAction(option) {
21
+ const fields = [
22
+ option?.kind,
23
+ option?.name,
24
+ option?.optionId,
25
+ ].map((value) => String(value || '').trim().toLowerCase()).filter(Boolean);
26
+ if (fields.some(isDenyPermissionToken)) {
15
27
  return 'deny';
16
28
  }
29
+ if (fields.some(isAllowAllPermissionToken)) {
30
+ return 'allow all';
31
+ }
32
+ if (fields.some(isAllowPermissionToken)) {
33
+ return 'allow';
34
+ }
17
35
  return '';
18
36
  }
37
+ function isAllowAllPermissionToken(normalized) {
38
+ if (normalized === 'allow_always' ||
39
+ normalized === 'allow_all' ||
40
+ normalized === 'allowall' ||
41
+ normalized === 'always' ||
42
+ normalized === 'always_allow' ||
43
+ normalized === 'alwaysallow' ||
44
+ normalized.includes('allow_all') ||
45
+ normalized.includes('allow-always') ||
46
+ normalized.includes('allow_always') ||
47
+ normalized.includes('allow always') ||
48
+ normalized.includes('always allow') ||
49
+ normalized.includes('allow all') ||
50
+ normalized.includes('始终允许') ||
51
+ normalized.includes('永久允许')) {
52
+ return true;
53
+ }
54
+ return false;
55
+ }
56
+ function isAllowPermissionToken(normalized) {
57
+ if (normalized.startsWith('allow')) {
58
+ return true;
59
+ }
60
+ return false;
61
+ }
62
+ function isDenyPermissionToken(normalized) {
63
+ if (normalized.startsWith('reject')) {
64
+ return true;
65
+ }
66
+ if (normalized.startsWith('deny')) {
67
+ return true;
68
+ }
69
+ return false;
70
+ }
19
71
  function formatToolCallContent(toolCall) {
20
72
  if (!toolCall || typeof toolCall !== 'object') {
21
73
  return 'Permission required before continuing.';
@@ -0,0 +1,210 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildInteractiveCard = buildInteractiveCard;
4
+ exports.renderPermissionCard = renderPermissionCard;
5
+ exports.renderPendingPairingCard = renderPendingPairingCard;
6
+ exports.extractCardActionMessageId = extractCardActionMessageId;
7
+ exports.extractCardActionValue = extractCardActionValue;
8
+ exports.formatPermissionButtonLabel = formatPermissionButtonLabel;
9
+ exports.formatPermissionResponseLabel = formatPermissionResponseLabel;
10
+ const desktop_js_1 = require("../../../../../shared/desktop.js");
11
+ function buildInteractiveCard(text, buttonRows = [], sessionKey, threadId) {
12
+ const elements = [];
13
+ if (text) {
14
+ elements.push({ tag: 'markdown', content: text });
15
+ }
16
+ for (const row of buttonRows) {
17
+ const actions = row
18
+ .filter((button) => button.text && button.data)
19
+ .map((button, index) => ({
20
+ tag: 'button',
21
+ text: {
22
+ tag: 'plain_text',
23
+ content: formatPermissionButtonLabel(button),
24
+ },
25
+ type: resolveLarkButtonType(button, index),
26
+ value: {
27
+ action: 'permission_response',
28
+ response: (0, desktop_js_1.normalizePermissionResponse)(button.data) || button.data,
29
+ session_key: sessionKey || '',
30
+ thread_id: threadId || '',
31
+ },
32
+ }));
33
+ if (actions.length) {
34
+ elements.push({
35
+ tag: 'action',
36
+ actions,
37
+ });
38
+ }
39
+ }
40
+ return {
41
+ config: { wide_screen_mode: true },
42
+ elements,
43
+ };
44
+ }
45
+ function renderPermissionCard(turn, event, cardActionsEnabled) {
46
+ const summary = buildPermissionSummary(turn, String(event.content || '').trim());
47
+ const sections = [
48
+ '**需要工具确认**',
49
+ summary.command ? `\`${summary.command}\`` : '',
50
+ summary.reason || '',
51
+ cardActionsEnabled
52
+ ? '也可以直接回复:`allow` / `allow all` / `deny`'
53
+ : '请直接回复:`allow` / `allow all` / `deny`',
54
+ ].filter(Boolean);
55
+ const buttonRows = cardActionsEnabled && Array.isArray(event.buttonRows)
56
+ ? event.buttonRows
57
+ .map((row) => Array.isArray(row)
58
+ ? row
59
+ .filter((button) => Boolean(button?.text && button?.data))
60
+ .map((button) => ({
61
+ text: formatPermissionButtonLabel(button),
62
+ data: (0, desktop_js_1.normalizePermissionResponse)(button.data) || button.data,
63
+ }))
64
+ : [])
65
+ .filter((row) => row.length > 0)
66
+ : [];
67
+ return {
68
+ text: sections.join('\n\n').trim(),
69
+ buttonRows,
70
+ };
71
+ }
72
+ function renderPendingPairingCard(code) {
73
+ const lines = [
74
+ '**已收到消息**',
75
+ '当前账号还未授权接入这个工作区。',
76
+ '请在桌面端完成审批后再次发送消息。',
77
+ ];
78
+ if (code) {
79
+ lines.push(`配对码:\`${code}\``);
80
+ }
81
+ return lines.join('\n\n');
82
+ }
83
+ function extractCardActionMessageId(...payloads) {
84
+ for (const payload of payloads) {
85
+ const messageId = extractKnownCardActionMessageId(payload);
86
+ if (messageId) {
87
+ return messageId;
88
+ }
89
+ }
90
+ for (const payload of payloads) {
91
+ const messageId = findNestedCardActionMessageId(payload);
92
+ if (messageId) {
93
+ return messageId;
94
+ }
95
+ }
96
+ return '';
97
+ }
98
+ function extractCardActionValue(payload) {
99
+ const event = (payload?.event && typeof payload.event === 'object')
100
+ ? payload.event
101
+ : payload;
102
+ const value = event?.action?.value;
103
+ if (!value || value.action !== 'permission_response') {
104
+ return null;
105
+ }
106
+ const response = (0, desktop_js_1.normalizePermissionResponse)(String(value.response || '').trim()) || String(value.response || '').trim();
107
+ const threadId = String(value.thread_id || '').trim();
108
+ const sessionKey = String(value.session_key || '').trim();
109
+ if (!response || !threadId) {
110
+ return null;
111
+ }
112
+ return {
113
+ event,
114
+ value: value,
115
+ response,
116
+ threadId,
117
+ sessionKey,
118
+ };
119
+ }
120
+ function formatPermissionButtonLabel(button) {
121
+ return formatPermissionResponseLabel(button.data || button.text);
122
+ }
123
+ function formatPermissionResponseLabel(response) {
124
+ switch ((0, desktop_js_1.normalizePermissionResponse)(response) || response) {
125
+ case 'allow':
126
+ return '允许一次';
127
+ case 'allow all':
128
+ return '始终允许';
129
+ case 'deny':
130
+ return '拒绝';
131
+ default:
132
+ return response;
133
+ }
134
+ }
135
+ function resolveLarkButtonType(button, index) {
136
+ const response = (0, desktop_js_1.normalizePermissionResponse)(button.data) || (0, desktop_js_1.normalizePermissionResponse)(button.text);
137
+ if (response === 'deny') {
138
+ return 'danger';
139
+ }
140
+ if (response === 'allow') {
141
+ return 'primary';
142
+ }
143
+ return index === 0 ? 'primary' : 'default';
144
+ }
145
+ function buildPermissionSummary(turn, rawContent) {
146
+ const lastTool = turn.toolCalls[turn.toolCalls.length - 1] || '';
147
+ const [commandPart = '', reasonPart = ''] = lastTool.split(/\s+-\s+/, 2);
148
+ const compactContent = rawContent
149
+ .replace(/\s+/g, ' ')
150
+ .replace(/请选择一个选项继续执行。?/g, '')
151
+ .replace(/若按钮没有显示,请直接回复:?\s*allow all \/ allow \/ deny/gi, '')
152
+ .replace(/等待工具确认/gi, '')
153
+ .trim();
154
+ return {
155
+ command: commandPart.trim(),
156
+ reason: reasonPart.trim() || compactContent,
157
+ };
158
+ }
159
+ function extractKnownCardActionMessageId(payload) {
160
+ const source = payload;
161
+ if (!source || typeof source !== 'object') {
162
+ return '';
163
+ }
164
+ const candidates = [
165
+ source?.permission_message_id,
166
+ source?.action_message_id,
167
+ source?.context?.open_message_id,
168
+ source?.context?.message_id,
169
+ source?.event?.context?.open_message_id,
170
+ source?.event?.context?.message_id,
171
+ source?.event_context?.open_message_id,
172
+ source?.event_context?.message_id,
173
+ source?.message?.message_id,
174
+ source?.message?.open_message_id,
175
+ source?.event?.message?.message_id,
176
+ source?.event?.message?.open_message_id,
177
+ source?.message_id,
178
+ source?.open_message_id,
179
+ ];
180
+ return candidates
181
+ .map((candidate) => String(candidate || '').trim())
182
+ .find(Boolean) || '';
183
+ }
184
+ function findNestedCardActionMessageId(payload, seen = new Set()) {
185
+ if (!payload || typeof payload !== 'object' || seen.has(payload)) {
186
+ return '';
187
+ }
188
+ seen.add(payload);
189
+ if (Array.isArray(payload)) {
190
+ for (const item of payload) {
191
+ const nested = findNestedCardActionMessageId(item, seen);
192
+ if (nested)
193
+ return nested;
194
+ }
195
+ return '';
196
+ }
197
+ const source = payload;
198
+ for (const key of ['open_message_id', 'message_id', 'permission_message_id', 'action_message_id']) {
199
+ const value = source[key];
200
+ if (typeof value === 'string' && value.trim()) {
201
+ return value.trim();
202
+ }
203
+ }
204
+ for (const value of Object.values(source)) {
205
+ const nested = findNestedCardActionMessageId(value, seen);
206
+ if (nested)
207
+ return nested;
208
+ }
209
+ return '';
210
+ }
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeChannelInstanceId = normalizeChannelInstanceId;
4
+ exports.channelPlatformKey = channelPlatformKey;
5
+ exports.runtimeKey = runtimeKey;
6
+ exports.collectLarkWorkspaceBindings = collectLarkWorkspaceBindings;
7
+ const desktop_js_1 = require("../../../../../shared/desktop.js");
8
+ function normalizeChannelInstanceId(value, fallback) {
9
+ const raw = String(value || '').trim();
10
+ const normalized = raw.replace(/[^a-zA-Z0-9._-]/g, '-').replace(/-+/g, '-').slice(0, 80);
11
+ return normalized || fallback;
12
+ }
13
+ function channelPlatformKey(platform, instanceId) {
14
+ return instanceId === 'default' ? platform : `${platform}:${instanceId}`;
15
+ }
16
+ function runtimeKey(workspaceId, instanceId) {
17
+ return `${workspaceId}::${instanceId}`;
18
+ }
19
+ function collectLarkWorkspaceBindings(config, options) {
20
+ const projects = Array.isArray(config?.projects) ? config.projects : [];
21
+ return projects.flatMap((project) => {
22
+ const platforms = Array.isArray(project.platforms) ? project.platforms : [];
23
+ return platforms
24
+ .map((platform) => ({
25
+ platformType: (0, desktop_js_1.normalizeDesktopPlatformType)(platform?.type),
26
+ options: platform?.options && typeof platform.options === 'object'
27
+ ? platform.options
28
+ : {},
29
+ }))
30
+ .filter((platform) => platform.platformType === 'lark')
31
+ .map((platform, index) => {
32
+ const instanceId = normalizeChannelInstanceId(platform.options.instance_id || platform.options.id, index === 0 ? 'default' : `lark-${index + 1}`);
33
+ return {
34
+ workspaceId: project.name,
35
+ instanceId,
36
+ displayName: String(platform.options.name || platform.options.display_name || `Lark ${index + 1}`).trim(),
37
+ platformKey: channelPlatformKey('lark', instanceId),
38
+ appId: String(platform.options.app_id || '').trim(),
39
+ appSecret: String(platform.options.app_secret || '').trim(),
40
+ encryptKey: String(platform.options.encrypt_key || '').trim(),
41
+ verificationToken: String(platform.options.verification_token || '').trim(),
42
+ autoApprove: String(platform.options.auto_approve || '').trim().toLowerCase() === 'true'
43
+ || platform.options.auto_approve === true,
44
+ cardActionsEnabled: String(platform.options.card_actions || platform.options.enable_card_actions || '').trim().toLowerCase() === 'true'
45
+ || platform.options.card_actions === true
46
+ || platform.options.enable_card_actions === true
47
+ || options.defaultCardActionsEnabled,
48
+ brand: String(platform.options.brand || platform.options.lark_brand || '').trim().toLowerCase() === 'lark' ? 'lark' : 'feishu',
49
+ enabled: Boolean(String(platform.options.app_id || '').trim() && String(platform.options.app_secret || '').trim()),
50
+ project,
51
+ };
52
+ });
53
+ });
54
+ }