@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
@@ -6,6 +6,8 @@ const node_crypto_1 = require("node:crypto");
6
6
  const node_fs_1 = require("node:fs");
7
7
  const node_sqlite_1 = require("node:sqlite");
8
8
  const node_path_1 = require("node:path");
9
+ const index_js_1 = require("../../../../packages/contracts/src/index.js");
10
+ const job_id_js_1 = require("../scheduler/job-id.js");
9
11
  const desktop_js_1 = require("../../../../shared/desktop.js");
10
12
  const workspace_thread_mappers_js_1 = require("../thread/workspace-thread-mappers.js");
11
13
  const workspace_thread_id_js_1 = require("../thread/workspace-thread-id.js");
@@ -378,31 +380,34 @@ class LocalCoreAcpStore {
378
380
  }
379
381
  updateRun(runId, threadId, status) {
380
382
  const now = new Date().toISOString();
383
+ const normalizedStatus = (0, index_js_1.normalizeRunStatus)(status);
381
384
  const existing = this.db.prepare('SELECT id FROM runs WHERE id = ?').get(runId);
382
385
  if (existing) {
383
- this.db.prepare('UPDATE runs SET status = ?, updated_at = ? WHERE id = ?').run(status, now, runId);
386
+ this.db.prepare('UPDATE runs SET status = ?, updated_at = ? WHERE id = ?').run(normalizedStatus, now, runId);
384
387
  return;
385
388
  }
386
389
  this.db.prepare(`
387
390
  INSERT INTO runs (id, thread_id, status, started_at, updated_at)
388
391
  VALUES (?, ?, ?, ?, ?)
389
- `).run(runId, threadId, status, now, now);
392
+ `).run(runId, threadId, normalizedStatus, now, now);
390
393
  }
391
394
  getLatestRunForThread(threadId) {
392
- return this.db.prepare(`
395
+ const row = this.db.prepare(`
393
396
  SELECT id, thread_id, status, started_at, updated_at
394
397
  FROM runs
395
398
  WHERE thread_id = ?
396
399
  ORDER BY updated_at DESC
397
400
  LIMIT 1
398
401
  `).get(threadId);
402
+ return row ? { ...row, status: (0, index_js_1.normalizeRunStatus)(row.status) } : undefined;
399
403
  }
400
404
  getRun(runId) {
401
- return this.db.prepare(`
405
+ const row = this.db.prepare(`
402
406
  SELECT id, thread_id, status, started_at, updated_at
403
407
  FROM runs
404
408
  WHERE id = ?
405
409
  `).get(runId);
410
+ return row ? { ...row, status: (0, index_js_1.normalizeRunStatus)(row.status) } : undefined;
406
411
  }
407
412
  listWorkspaceRegistry() {
408
413
  const rows = this.db.prepare(`
@@ -573,7 +578,7 @@ class LocalCoreAcpStore {
573
578
  params.push(query.taskId);
574
579
  }
575
580
  if (query.status) {
576
- const statuses = Array.isArray(query.status) ? query.status : [query.status];
581
+ const statuses = (Array.isArray(query.status) ? query.status : [query.status]).map((status) => (0, index_js_1.normalizeApprovalRequestStatus)(status));
577
582
  predicates.push(`status IN (${statuses.map(() => '?').join(', ')})`);
578
583
  params.push(...statuses);
579
584
  }
@@ -669,7 +674,7 @@ class LocalCoreAcpStore {
669
674
  createAgentTask(input) {
670
675
  const id = `task:${(0, node_crypto_1.randomUUID)()}`;
671
676
  const now = new Date().toISOString();
672
- const status = input.status || 'created';
677
+ const status = (0, index_js_1.normalizeAgentTaskStatus)(input.status);
673
678
  const timeline = [{
674
679
  id: `timeline:${(0, node_crypto_1.randomUUID)()}`,
675
680
  type: 'status_change',
@@ -706,7 +711,7 @@ class LocalCoreAcpStore {
706
711
  params.push(query.runtimeId);
707
712
  }
708
713
  if (query.status) {
709
- const statuses = Array.isArray(query.status) ? query.status : [query.status];
714
+ const statuses = (Array.isArray(query.status) ? query.status : [query.status]).map((status) => (0, index_js_1.normalizeAgentTaskStatus)(status));
710
715
  predicates.push(`status IN (${statuses.map(() => '?').join(', ')})`);
711
716
  params.push(...statuses);
712
717
  }
@@ -735,17 +740,17 @@ class LocalCoreAcpStore {
735
740
  throw new Error(`Task not found: ${taskId}`);
736
741
  }
737
742
  const now = new Date().toISOString();
738
- const nextStatus = input.status || existing.status;
743
+ const nextStatus = input.status ? (0, index_js_1.normalizeAgentTaskStatus)(input.status) : existing.status;
739
744
  const timeline = [...existing.timeline];
740
745
  const logs = [...existing.logs];
741
746
  const artifacts = [...existing.artifacts];
742
747
  const approvalIds = [...existing.approvalIds];
743
- if (input.status && input.status !== existing.status) {
748
+ if (input.status && nextStatus !== existing.status) {
744
749
  timeline.push({
745
750
  id: `timeline:${(0, node_crypto_1.randomUUID)()}`,
746
751
  type: 'status_change',
747
- title: `Task ${input.status}`,
748
- status: input.status,
752
+ title: `Task ${nextStatus}`,
753
+ status: nextStatus,
749
754
  timestamp: now,
750
755
  });
751
756
  }
@@ -780,14 +785,14 @@ class LocalCoreAcpStore {
780
785
  WHERE id = ?
781
786
  `).run(nextStatus, input.threadId || existing.threadId || null, input.runId || existing.runId || null, input.title || existing.title, now, existing.queuedAt || (nextStatus === 'queued' ? now : null), existing.startedAt || (nextStatus === 'running' ? now : null), existing.completedAt || (['completed', 'failed', 'cancelled'].includes(nextStatus) ? now : null), input.summary ?? existing.summary ?? null, input.error === null ? null : input.error ?? existing.error ?? null, JSON.stringify(timeline), JSON.stringify(logs), JSON.stringify(artifacts), JSON.stringify(approvalIds), JSON.stringify(input.metadata || existing.metadata || {}), taskId);
782
787
  const task = this.getAgentTask(taskId);
783
- if (input.status && input.status !== existing.status) {
788
+ if (input.status && nextStatus !== existing.status) {
784
789
  this.createAuditEvent({
785
790
  type: 'task.updated',
786
791
  workspaceId: task.workspaceId,
787
792
  taskId: task.taskId,
788
793
  actor: 'local',
789
- summary: `Task status changed to ${input.status}.`,
790
- metadata: { previousStatus: existing.status, status: input.status, runId: task.runId },
794
+ summary: `Task status changed to ${nextStatus}.`,
795
+ metadata: { previousStatus: existing.status, status: nextStatus, runId: task.runId },
791
796
  });
792
797
  }
793
798
  return task;
@@ -820,14 +825,20 @@ class LocalCoreAcpStore {
820
825
  return row ? this.toScheduledJob(row) : undefined;
821
826
  }
822
827
  createScheduledJob(input) {
823
- const id = `job:${(0, node_crypto_1.randomUUID)()}`;
828
+ let id = (0, job_id_js_1.createScheduledJobId)();
829
+ for (let attempt = 0; attempt < 5 && this.getScheduledJob(id); attempt += 1) {
830
+ id = (0, job_id_js_1.createScheduledJobId)();
831
+ }
832
+ if (this.getScheduledJob(id)) {
833
+ throw new Error('Unable to allocate a unique scheduled job id.');
834
+ }
824
835
  const now = new Date().toISOString();
825
836
  this.db.prepare(`
826
837
  INSERT INTO scheduled_jobs (
827
838
  id, workspace_id, platform, route_type, route_config, execution_mode, trigger_type, cron_expr, run_at,
828
839
  prompt_template, description, enabled, concurrency_policy, created_at, updated_at
829
840
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'skip_if_running', ?, ?)
830
- `).run(id, input.workspaceId, input.platform, input.route.type, JSON.stringify(input.route), input.executionMode || 'same-thread', input.triggerType, input.cronExpr || null, input.runAt || null, input.promptTemplate, input.description || '', input.enabled === false ? 0 : 1, now, now);
841
+ `).run(id, input.workspaceId, (0, index_js_1.normalizeChannelPlatform)(input.platform), input.route.type, JSON.stringify(input.route), (0, index_js_1.normalizeScheduledJobExecutionMode)(input.executionMode), (0, index_js_1.normalizeScheduledJobTriggerType)(input.triggerType), input.cronExpr || null, input.runAt || null, input.promptTemplate, input.description || '', input.enabled === false ? 0 : 1, now, now);
831
842
  return this.getScheduledJob(id);
832
843
  }
833
844
  updateScheduledJob(jobId, input) {
@@ -838,8 +849,8 @@ class LocalCoreAcpStore {
838
849
  const next = {
839
850
  ...existing,
840
851
  ...(input.route ? { route: input.route } : {}),
841
- ...(input.executionMode ? { executionMode: input.executionMode } : {}),
842
- ...(input.triggerType ? { triggerType: input.triggerType } : {}),
852
+ ...(input.executionMode ? { executionMode: (0, index_js_1.normalizeScheduledJobExecutionMode)(input.executionMode) } : {}),
853
+ ...(input.triggerType ? { triggerType: (0, index_js_1.normalizeScheduledJobTriggerType)(input.triggerType) } : {}),
843
854
  ...(Object.prototype.hasOwnProperty.call(input, 'cronExpr') ? { cronExpr: input.cronExpr || undefined } : {}),
844
855
  ...(Object.prototype.hasOwnProperty.call(input, 'runAt') ? { runAt: input.runAt || undefined } : {}),
845
856
  ...(typeof input.promptTemplate === 'string' ? { promptTemplate: input.promptTemplate } : {}),
@@ -856,7 +867,10 @@ class LocalCoreAcpStore {
856
867
  return this.getScheduledJob(jobId);
857
868
  }
858
869
  deleteScheduledJob(jobId) {
859
- this.db.prepare('DELETE FROM scheduled_jobs WHERE id = ?').run(jobId);
870
+ const result = this.db.prepare('DELETE FROM scheduled_jobs WHERE id = ?').run(jobId);
871
+ if (result.changes === 0) {
872
+ throw new Error(`Scheduled job not found: ${jobId}`);
873
+ }
860
874
  return { deleted: true };
861
875
  }
862
876
  listScheduledJobRuns(jobId) {
@@ -871,13 +885,14 @@ class LocalCoreAcpStore {
871
885
  createScheduledJobRun(jobId, status, input = {}) {
872
886
  const id = `jobrun:${(0, node_crypto_1.randomUUID)()}`;
873
887
  const triggeredAt = input.triggeredAt || new Date().toISOString();
888
+ const normalizedStatus = (0, index_js_1.normalizeScheduledJobRunStatus)(status);
874
889
  this.db.prepare(`
875
890
  INSERT INTO scheduled_job_runs (id, job_id, status, triggered_at, started_at, finished_at, error, thread_id, run_id, platform_message_id)
876
891
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
877
- `).run(id, jobId, status, triggeredAt, input.startedAt || null, input.finishedAt || null, input.error || null, input.threadId || null, input.runId || null, input.platformMessageId || null);
892
+ `).run(id, jobId, normalizedStatus, triggeredAt, input.startedAt || null, input.finishedAt || null, input.error || null, input.threadId || null, input.runId || null, input.platformMessageId || null);
878
893
  this.updateScheduledJobStatus(jobId, {
879
894
  lastRunAt: triggeredAt,
880
- lastStatus: status,
895
+ lastStatus: normalizedStatus,
881
896
  lastError: input.error || '',
882
897
  });
883
898
  return this.getScheduledJobRun(id);
@@ -898,6 +913,7 @@ class LocalCoreAcpStore {
898
913
  const next = {
899
914
  ...existing,
900
915
  ...input,
916
+ ...(input.status ? { status: (0, index_js_1.normalizeScheduledJobRunStatus)(input.status) } : {}),
901
917
  };
902
918
  this.db.prepare(`
903
919
  UPDATE scheduled_job_runs
@@ -1113,10 +1129,10 @@ class LocalCoreAcpStore {
1113
1129
  return {
1114
1130
  id: row.id,
1115
1131
  workspaceId: row.workspace_id,
1116
- platform: row.platform,
1132
+ platform: (0, index_js_1.normalizeChannelPlatform)(row.platform),
1117
1133
  route,
1118
- executionMode: row.execution_mode || 'same-thread',
1119
- triggerType: row.trigger_type,
1134
+ executionMode: (0, index_js_1.normalizeScheduledJobExecutionMode)(row.execution_mode),
1135
+ triggerType: (0, index_js_1.normalizeScheduledJobTriggerType)(row.trigger_type),
1120
1136
  cronExpr: row.cron_expr || undefined,
1121
1137
  runAt: row.run_at || undefined,
1122
1138
  promptTemplate: row.prompt_template,
@@ -1126,7 +1142,7 @@ class LocalCoreAcpStore {
1126
1142
  createdAt: row.created_at,
1127
1143
  updatedAt: row.updated_at,
1128
1144
  lastRunAt: row.last_run_at || undefined,
1129
- lastStatus: row.last_status || undefined,
1145
+ lastStatus: row.last_status ? (0, index_js_1.normalizeScheduledJobRunStatus)(row.last_status) : undefined,
1130
1146
  lastError: row.last_error || undefined,
1131
1147
  };
1132
1148
  }
@@ -1134,7 +1150,7 @@ class LocalCoreAcpStore {
1134
1150
  return {
1135
1151
  id: row.id,
1136
1152
  jobId: row.job_id,
1137
- status: row.status,
1153
+ status: (0, index_js_1.normalizeScheduledJobRunStatus)(row.status),
1138
1154
  triggeredAt: row.triggered_at,
1139
1155
  startedAt: row.started_at || undefined,
1140
1156
  finishedAt: row.finished_at || undefined,
@@ -1187,7 +1203,7 @@ class LocalCoreAcpStore {
1187
1203
  runId: row.run_id || undefined,
1188
1204
  title: row.title,
1189
1205
  prompt: row.prompt || undefined,
1190
- status: row.status,
1206
+ status: (0, index_js_1.normalizeAgentTaskStatus)(row.status),
1191
1207
  createdAt: row.created_at,
1192
1208
  updatedAt: row.updated_at,
1193
1209
  queuedAt: row.queued_at || undefined,
@@ -1224,7 +1240,7 @@ class LocalCoreAcpStore {
1224
1240
  runId: row.run_id || undefined,
1225
1241
  deviceId: row.device_id,
1226
1242
  kind: row.kind,
1227
- status: row.status,
1243
+ status: (0, index_js_1.normalizeApprovalRequestStatus)(row.status),
1228
1244
  riskLevel: row.risk_level,
1229
1245
  title: row.title,
1230
1246
  description: row.description,
@@ -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,19 +1,28 @@
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;
7
+ const desktop_js_1 = require("../../../../shared/desktop.js");
6
8
  function normalizePermissionAction(kind) {
7
- const normalized = String(kind || '').trim().toLowerCase();
8
- if (normalized === 'allow_always') {
9
+ return (0, desktop_js_1.normalizePermissionResponse)(kind) || '';
10
+ }
11
+ function normalizePermissionOptionAction(option) {
12
+ const fields = [
13
+ option?.kind,
14
+ option?.name,
15
+ option?.optionId,
16
+ ].map((value) => String(value || '').trim().toLowerCase()).filter(Boolean);
17
+ if (fields.some((field) => normalizePermissionAction(field) === 'deny')) {
18
+ return 'deny';
19
+ }
20
+ if (fields.some((field) => normalizePermissionAction(field) === 'allow all')) {
9
21
  return 'allow all';
10
22
  }
11
- if (normalized.startsWith('allow')) {
23
+ if (fields.some((field) => normalizePermissionAction(field) === 'allow')) {
12
24
  return 'allow';
13
25
  }
14
- if (normalized.startsWith('reject')) {
15
- return 'deny';
16
- }
17
26
  return '';
18
27
  }
19
28
  function formatToolCallContent(toolCall) {
@@ -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
+ }