@kafca/agentdock 0.1.48 → 0.1.50

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 (58) hide show
  1. package/README.md +1 -0
  2. package/dist/renderer/assets/{Badge-C92lMj9Q.js → Badge-DphzI84h.js} +1 -1
  3. package/dist/renderer/assets/{Chat-DqoKCPwz.js → Chat-BkMHNdkV.js} +1 -1
  4. package/dist/renderer/assets/{ChatMarkdown-C4psQvmt.js → ChatMarkdown-nmZelMA9.js} +1 -1
  5. package/dist/renderer/assets/{Config-1uk8FQL7.js → Config-CY2peXi1.js} +1 -1
  6. package/dist/renderer/assets/{CronList-DnKCiYWC.js → CronList-Ds9TTT0f.js} +1 -1
  7. package/dist/renderer/assets/{Dashboard-rOAQcJA0.js → Dashboard-DeWrprYz.js} +2 -2
  8. package/dist/renderer/assets/{EmptyState-bF6Sc61O.js → EmptyState-JnMCDgRB.js} +1 -1
  9. package/dist/renderer/assets/{KnowledgeDetail-C5-Dp95R.js → KnowledgeDetail-CQ3VlctJ.js} +1 -1
  10. package/dist/renderer/assets/{KnowledgeHome-DGa1EWXD.js → KnowledgeHome-DsCVW1re.js} +1 -1
  11. package/dist/renderer/assets/{Logs-CKKVW2k8.js → Logs-4ENSRVB4.js} +1 -1
  12. package/dist/renderer/assets/{Modal-DIc9HxD5.js → Modal-BIm0iRtp.js} +1 -1
  13. package/dist/renderer/assets/{MonitorList-D2YOJRIX.js → MonitorList-CCj0KIGD.js} +1 -1
  14. package/dist/renderer/assets/{Page-vZ-_l6Kn.js → Page-uCVGTzRo.js} +1 -1
  15. package/dist/renderer/assets/{ProjectDetail-CqTa6kAh.js → ProjectDetail-DJ0Z_Ixk.js} +1 -1
  16. package/dist/renderer/assets/{ProjectList-LgDQVVyZ.js → ProjectList-DglTyk-r.js} +1 -1
  17. package/dist/renderer/assets/{Select-BN2HMOmY.js → Select-wnvxGX9B.js} +1 -1
  18. package/dist/renderer/assets/{SessionChat-Beco1N1T.js → SessionChat-BvrFUqiK.js} +1 -1
  19. package/dist/renderer/assets/{SessionList-3NkskCJJ.js → SessionList-DN0k8lCt.js} +1 -1
  20. package/dist/renderer/assets/{ThreadChat-Ji8pOm5p.js → ThreadChat-DqZwWTdK.js} +1 -1
  21. package/dist/renderer/assets/{Workspace-yarrGItB.js → Workspace-VrjbrPbA.js} +1 -1
  22. package/dist/renderer/assets/{arrow-left-DNovvfPp.js → arrow-left-BflzNl62.js} +1 -1
  23. package/dist/renderer/assets/{book-open-CarZFsXv.js → book-open-D2ttV2IU.js} +1 -1
  24. package/dist/renderer/assets/{bot-g16rGMp6.js → bot-cb9OifGp.js} +1 -1
  25. package/dist/renderer/assets/{check-DjFX73Zi.js → check-B47n4xeR.js} +1 -1
  26. package/dist/renderer/assets/{chevron-down-B02YlQS_.js → chevron-down-CGsttXF_.js} +1 -1
  27. package/dist/renderer/assets/{circle-DPfWdG1F.js → circle-BnHI6FDe.js} +1 -1
  28. package/dist/renderer/assets/{desktop-DMkue1T6.js → desktop-CRlWIOU3.js} +1 -1
  29. package/dist/renderer/assets/{funnel-Dy1VL-D9.js → funnel-DPnOoche.js} +1 -1
  30. package/dist/renderer/assets/{heart-YjvGwq5-.js → heart-Bdhq7IqP.js} +1 -1
  31. package/dist/renderer/assets/{index-CZN1STMc.js → index-BfJ1LHHo.js} +1 -1
  32. package/dist/renderer/assets/{index-mvjDN9uV.js → index-CrZRrTuv.js} +2 -2
  33. package/dist/renderer/assets/{pencil-qpMjLIFd.js → pencil-0zLgPSJa.js} +1 -1
  34. package/dist/renderer/assets/{play-CPCcNQcH.js → play-fVd6Sq-t.js} +1 -1
  35. package/dist/renderer/assets/{plus-B76JWGKd.js → plus-DmNVnnyt.js} +1 -1
  36. package/dist/renderer/assets/projects-Cm9nXtkn.js +1 -0
  37. package/dist/renderer/assets/{save-DtvrD3W1.js → save-CSIMXP6Z.js} +1 -1
  38. package/dist/renderer/assets/{search-Ddth-YHH.js → search-Ddn9yqyb.js} +1 -1
  39. package/dist/renderer/assets/{server-D0zmghb3.js → server-BVPINrD2.js} +1 -1
  40. package/dist/renderer/assets/{session-utils-C9oe-21F.js → session-utils-BcyJwUyK.js} +1 -1
  41. package/dist/renderer/assets/{sessions-BXOnLLah.js → sessions-BtcQ4TyW.js} +1 -1
  42. package/dist/renderer/assets/{shield-check-Cv5d_blH.js → shield-check-B2sF2E4F.js} +1 -1
  43. package/dist/renderer/assets/{trash-2-C2mimX2b.js → trash-2-BwMAwl5Q.js} +1 -1
  44. package/dist/renderer/assets/{user-BrLJ4elW.js → user-BEZW7eDN.js} +1 -1
  45. package/dist/renderer/assets/{wifi-off-DvRJYLbG.js → wifi-off-C1uypxZf.js} +1 -1
  46. package/dist/renderer/index.html +1 -1
  47. package/dist-electron/services/local-ai-core/src/router/workspace-router.js +2 -2
  48. package/dist-electron/services/local-ai-core/src/scheduler/channel-execution-policy.js +3 -1
  49. package/dist-electron/services/local-ai-core/src/scheduler/lark-execution-policies.js +2 -1
  50. package/dist-electron/services/local-ai-core/src/scheduler/lark-schedule-adapter.js +10 -1
  51. package/dist-electron/services/local-ai-core/src/scheduler/scheduled-conversation-executor.js +1 -1
  52. package/dist-electron/services/local-ai-core/src/scheduler/scheduler-service.js +24 -0
  53. package/dist-electron/services/local-ai-core/src/scheduler/weixin-execution-policies.js +2 -1
  54. package/dist-electron/services/local-ai-core/src/scheduler/weixin-schedule-adapter.js +10 -1
  55. package/dist-electron/tests/electron/workspace-task-store.test.js +54 -0
  56. package/dist-electron/tests/integration/local-core-refactor.test.js +76 -0
  57. package/package.json +1 -1
  58. package/dist/renderer/assets/projects-C1nFINjh.js +0 -1
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-mvjDN9uV.js";/**
1
+ import{c as a}from"./index-CrZRrTuv.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as o}from"./index-mvjDN9uV.js";/**
1
+ import{c as o}from"./index-CrZRrTuv.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-mvjDN9uV.js";/**
1
+ import{c as e}from"./index-CrZRrTuv.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -0,0 +1 @@
1
+ import{D as t}from"./index-CrZRrTuv.js";const e=()=>t.get("/projects"),r=o=>t.get(`/projects/${o}`);export{r as g,e as l};
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-mvjDN9uV.js";/**
1
+ import{c as a}from"./index-CrZRrTuv.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c}from"./index-mvjDN9uV.js";/**
1
+ import{c}from"./index-CrZRrTuv.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-mvjDN9uV.js";/**
1
+ import{c as e}from"./index-CrZRrTuv.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as o}from"./index-mvjDN9uV.js";/**
1
+ import{c as o}from"./index-CrZRrTuv.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{D as o}from"./index-mvjDN9uV.js";const i=s=>o.get(`/projects/${s}/sessions`),c=(s,e,t)=>o.get(`/projects/${s}/sessions/${e}`,{history_limit:String(t)}),r=(s,e,t)=>o.patch(`/projects/${s}/sessions/${e}`,t),a=(s,e)=>o.delete(`/projects/${s}/sessions/${e}`),p=(s,e)=>o.post(`/projects/${s}/sessions/switch`,e),$=(s,e)=>o.post(`/projects/${s}/send`,e);export{$ as a,a as d,c as g,i as l,r,p as s};
1
+ import{D as o}from"./index-CrZRrTuv.js";const i=s=>o.get(`/projects/${s}/sessions`),c=(s,e,t)=>o.get(`/projects/${s}/sessions/${e}`,{history_limit:String(t)}),r=(s,e,t)=>o.patch(`/projects/${s}/sessions/${e}`,t),a=(s,e)=>o.delete(`/projects/${s}/sessions/${e}`),p=(s,e)=>o.post(`/projects/${s}/sessions/switch`,e),$=(s,e)=>o.post(`/projects/${s}/send`,e);export{$ as a,a as d,c as g,i as l,r,p as s};
@@ -1,4 +1,4 @@
1
- import{c}from"./index-mvjDN9uV.js";/**
1
+ import{c}from"./index-CrZRrTuv.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-mvjDN9uV.js";/**
1
+ import{c as e}from"./index-CrZRrTuv.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c}from"./index-mvjDN9uV.js";/**
1
+ import{c}from"./index-CrZRrTuv.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-mvjDN9uV.js";/**
1
+ import{c as a}from"./index-CrZRrTuv.js";/**
2
2
  * @license lucide-react v0.487.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -5,7 +5,7 @@
5
5
  <link rel="icon" type="image/svg+xml" href="./favicon.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>AgentDock</title>
8
- <script type="module" crossorigin src="./assets/index-mvjDN9uV.js"></script>
8
+ <script type="module" crossorigin src="./assets/index-CrZRrTuv.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="./assets/index-CjCuR6DI.css">
10
10
  </head>
11
11
  <body class="bg-[#f5f5f7] dark:bg-[#151516]">
@@ -177,9 +177,9 @@ class WorkspaceRouter {
177
177
  await this.getWorkspaceRoute(workspaceId);
178
178
  return this.localCoreAcp.listThreads(workspaceId);
179
179
  }
180
- async createThread(workspaceId, title) {
180
+ async createThread(workspaceId, title, agentType) {
181
181
  const route = await this.getWorkspaceRoute(workspaceId);
182
- return this.withKnowledge(await this.localCoreAcp.createThread(workspaceId, title || `New thread ${new Date().toLocaleTimeString()}`, route.agentType));
182
+ return this.withKnowledge(await this.localCoreAcp.createThread(workspaceId, title || `New thread ${new Date().toLocaleTimeString()}`, agentType || route.agentType));
183
183
  }
184
184
  async getThread(threadId) {
185
185
  const { workspaceId } = (0, workspace_thread_id_js_1.decodeThreadId)(threadId);
@@ -55,7 +55,9 @@ class SideThreadChannelExecutionPolicy {
55
55
  ]);
56
56
  const existing = (await this.options.workspaceRouter.listThreads(job.workspaceId))
57
57
  .find((thread) => reusableTitles.has(thread.title));
58
- const threadId = existing?.id || (await this.options.workspaceRouter.createThread(job.workspaceId, title)).id;
58
+ const preferredAgent = this.config.preferredAgentType?.(job) || '';
59
+ const threadId = existing?.id
60
+ || (await this.options.workspaceRouter.createThread(job.workspaceId, title, preferredAgent || undefined)).id;
59
61
  return {
60
62
  kind: `${this.config.platformBase}:side-thread`,
61
63
  threadId,
@@ -2,11 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createLarkExecutionPolicy = createLarkExecutionPolicy;
4
4
  const channel_execution_policy_js_1 = require("./channel-execution-policy.js");
5
- function createLarkExecutionPolicy(job, options, resolveSameThread) {
5
+ function createLarkExecutionPolicy(job, options, resolveSameThread, preferredAgentType) {
6
6
  return (0, channel_execution_policy_js_1.createChannelExecutionPolicy)(job, options, {
7
7
  platformBase: 'lark',
8
8
  resolveSameThread,
9
9
  sideThreadTitle: (nextJob) => `[Scheduled:Lark] ${nextJob.description || nextJob.id}`,
10
10
  legacySideThreadTitles: (nextJob) => [`[Scheduled] ${nextJob.description || nextJob.id}`],
11
+ preferredAgentType,
11
12
  });
12
13
  }
@@ -24,7 +24,7 @@ class LarkScheduleAdapter {
24
24
  store: this.options.store,
25
25
  workspaceRouter: this.options.getWorkspaceRouter(),
26
26
  getChannelRuntime: this.options.getChannelRuntime,
27
- }, (nextJob) => this.resolveThread(nextJob));
27
+ }, (nextJob) => this.resolveThread(nextJob), (nextJob) => this.preferredAgentFor(nextJob));
28
28
  const execution = await this.executor.execute(job, job.promptTemplate, executionPolicy);
29
29
  return {
30
30
  threadId: execution.threadId,
@@ -74,5 +74,14 @@ class LarkScheduleAdapter {
74
74
  return false;
75
75
  }
76
76
  }
77
+ preferredAgentFor(job) {
78
+ const route = job.route;
79
+ const channelId = route.channelId;
80
+ if (!channelId)
81
+ return '';
82
+ const participantId = route.participantId || '';
83
+ const binding = this.options.store.getPlatformThreadBinding(job.workspaceId, channelId, participantId, job.platform);
84
+ return binding?.preferred_agent_type || '';
85
+ }
77
86
  }
78
87
  exports.LarkScheduleAdapter = LarkScheduleAdapter;
@@ -9,7 +9,7 @@ class ScheduledConversationExecutor {
9
9
  constructor(options) {
10
10
  this.options = options;
11
11
  }
12
- async execute(job, prompt, policy, timeoutMs = 15 * 60 * 1000) {
12
+ async execute(job, prompt, policy, timeoutMs = 60 * 60 * 1000) {
13
13
  const target = await policy.resolveTarget(job);
14
14
  await policy.beforeExecute?.(target, job);
15
15
  try {
@@ -4,6 +4,7 @@ exports.SchedulerService = void 0;
4
4
  const node_events_1 = require("node:events");
5
5
  const job_id_js_1 = require("./job-id.js");
6
6
  const scheduler_run_lifecycle_js_1 = require("./scheduler-run-lifecycle.js");
7
+ const SCHEDULER_AUTO_DISABLE_THRESHOLD = 5;
7
8
  class SchedulerService extends node_events_1.EventEmitter {
8
9
  options;
9
10
  timer = null;
@@ -148,11 +149,34 @@ class SchedulerService extends node_events_1.EventEmitter {
148
149
  this.options.eventBus.emit({ type: 'scheduler.job.updated', payload: nextJob });
149
150
  }
150
151
  this.options.log?.(`scheduler job failed ${job.id}: ${failed.error || 'unknown error'}`);
152
+ this.maybeAutoDisableAfterFailure(job.id);
151
153
  return failed;
152
154
  }
153
155
  finally {
154
156
  this.runningJobs.delete(job.id);
155
157
  }
156
158
  }
159
+ maybeAutoDisableAfterFailure(jobId) {
160
+ const runs = this.options.store.listScheduledJobRuns(jobId);
161
+ let consecutiveFailures = 0;
162
+ for (const run of runs) {
163
+ if (run.status === 'failed') {
164
+ consecutiveFailures += 1;
165
+ }
166
+ else {
167
+ break;
168
+ }
169
+ }
170
+ if (consecutiveFailures < SCHEDULER_AUTO_DISABLE_THRESHOLD) {
171
+ return;
172
+ }
173
+ this.options.store.updateScheduledJobStatus(jobId, { enabled: false });
174
+ const disabled = this.options.store.getScheduledJob(jobId);
175
+ if (disabled) {
176
+ this.emit('job', disabled);
177
+ this.options.eventBus.emit({ type: 'scheduler.job.updated', payload: disabled });
178
+ }
179
+ this.options.log?.(`scheduler auto-disabled job ${jobId} after ${consecutiveFailures} consecutive failures`);
180
+ }
157
181
  }
158
182
  exports.SchedulerService = SchedulerService;
@@ -2,11 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createWeixinExecutionPolicy = createWeixinExecutionPolicy;
4
4
  const channel_execution_policy_js_1 = require("./channel-execution-policy.js");
5
- function createWeixinExecutionPolicy(job, options, resolveSameThread) {
5
+ function createWeixinExecutionPolicy(job, options, resolveSameThread, preferredAgentType) {
6
6
  return (0, channel_execution_policy_js_1.createChannelExecutionPolicy)(job, options, {
7
7
  platformBase: 'weixin',
8
8
  resolveSameThread,
9
9
  sideThreadTitle: (nextJob) => `[Scheduled:Weixin] ${nextJob.description || nextJob.id}`,
10
10
  legacySideThreadTitles: (nextJob) => [`[Scheduled] ${nextJob.description || nextJob.id}`],
11
+ preferredAgentType,
11
12
  });
12
13
  }
@@ -24,7 +24,7 @@ class WeixinScheduleAdapter {
24
24
  store: this.options.store,
25
25
  workspaceRouter: this.options.getWorkspaceRouter(),
26
26
  getChannelRuntime: this.options.getChannelRuntime,
27
- }, (nextJob) => this.resolveThread(nextJob));
27
+ }, (nextJob) => this.resolveThread(nextJob), (nextJob) => this.preferredAgentFor(nextJob));
28
28
  const execution = await this.executor.execute(job, job.promptTemplate, executionPolicy);
29
29
  return {
30
30
  threadId: execution.threadId,
@@ -74,5 +74,14 @@ class WeixinScheduleAdapter {
74
74
  return false;
75
75
  }
76
76
  }
77
+ preferredAgentFor(job) {
78
+ const route = job.route;
79
+ const channelId = route.channelId;
80
+ if (!channelId)
81
+ return '';
82
+ const participantId = route.participantId || '';
83
+ const binding = this.options.store.getPlatformThreadBinding(job.workspaceId, channelId, participantId, job.platform);
84
+ return binding?.preferred_agent_type || '';
85
+ }
77
86
  }
78
87
  exports.WeixinScheduleAdapter = WeixinScheduleAdapter;
@@ -972,6 +972,60 @@ const env_utils_js_1 = require("../../services/local-ai-core/src/runtime/env-uti
972
972
  (0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
973
973
  }
974
974
  });
975
+ (0, node_test_1.default)('scheduler auto-disables a job after 5 consecutive failures', async () => {
976
+ const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'scheduler-autodisable-'));
977
+ try {
978
+ const store = new local_core_acp_store_js_1.LocalCoreAcpStore(userDataPath);
979
+ const created = store.createScheduledJob({
980
+ workspaceId: 'workspace-a',
981
+ platform: 'local',
982
+ route: { type: 'local.thread', channelId: 'workspace-a', threadId: 'thread-1' },
983
+ executionMode: 'side-thread',
984
+ triggerType: 'cron',
985
+ cronExpr: '* * * * *',
986
+ promptTemplate: 'broken',
987
+ description: 'always-failing job',
988
+ enabled: true,
989
+ });
990
+ const logs = [];
991
+ const jobUpdates = [];
992
+ const scheduler = new scheduler_service_js_1.SchedulerService({
993
+ store,
994
+ triggers: [{
995
+ triggerTypes: ['cron'],
996
+ supports: () => true,
997
+ isDue: () => true,
998
+ }],
999
+ executors: [{
1000
+ deliveryTargets: ['local'],
1001
+ supports: () => true,
1002
+ execute: async () => {
1003
+ throw new Error("The 'gpt-5.3-codex' model is not supported");
1004
+ },
1005
+ }],
1006
+ eventBus: {
1007
+ emit: (event) => {
1008
+ if (event?.type === 'scheduler.job.updated') {
1009
+ jobUpdates.push({ enabled: event.payload.enabled });
1010
+ }
1011
+ },
1012
+ on: () => () => { },
1013
+ },
1014
+ log: (message) => logs.push(message),
1015
+ });
1016
+ for (let i = 0; i < 5; i += 1) {
1017
+ await scheduler.runJobNow(created.id);
1018
+ }
1019
+ const jobAfter = store.getScheduledJob(created.id);
1020
+ strict_1.default.equal(jobAfter?.enabled, false);
1021
+ strict_1.default.ok(logs.some((msg) => msg.includes('auto-disabled') && msg.includes('5 consecutive failures')), `expected auto-disable log, got: ${JSON.stringify(logs)}`);
1022
+ strict_1.default.ok(jobUpdates.some((update) => update.enabled === false));
1023
+ store.close();
1024
+ }
1025
+ finally {
1026
+ (0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
1027
+ }
1028
+ });
975
1029
  (0, node_test_1.default)('scheduled jobs normalize enum-like input before persistence', () => {
976
1030
  const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'scheduler-enum-store-'));
977
1031
  try {
@@ -858,6 +858,82 @@ const thread_slash_command_dispatcher_js_1 = require("../../services/local-ai-co
858
858
  policy.afterExecute?.(target, job);
859
859
  strict_1.default.equal(unregisteredBridge, true);
860
860
  });
861
+ (0, node_test_1.default)('lark side-thread execution policy applies preferred agent when creating a new scheduled thread', async () => {
862
+ const job = {
863
+ id: 'job-1',
864
+ workspaceId: '知识库',
865
+ platform: 'lark',
866
+ route: { type: 'channel.chat', channelId: 'chat-1', participantId: 'user-1', threadId: 'thread-origin' },
867
+ executionMode: 'side-thread',
868
+ triggerType: 'cron',
869
+ cronExpr: '*/2 * * * *',
870
+ promptTemplate: 'ping',
871
+ description: 'two-minute ping',
872
+ enabled: true,
873
+ concurrencyPolicy: 'skip_if_running',
874
+ createdAt: '2026-04-22T06:00:00.000Z',
875
+ updatedAt: '2026-04-22T06:00:00.000Z',
876
+ };
877
+ const createThreadCalls = [];
878
+ const policy = (0, lark_execution_policies_js_1.createLarkExecutionPolicy)(job, {
879
+ store: {},
880
+ workspaceRouter: {
881
+ getThreadSessionKey: (threadId) => `session:${threadId}`,
882
+ listThreads: async () => [],
883
+ createThread: async (workspaceId, title, agentType) => {
884
+ createThreadCalls.push({ workspaceId, title: title || '', agentType });
885
+ return { id: 'thread-new' };
886
+ },
887
+ },
888
+ getChannelRuntime: () => ({
889
+ registerScheduledThreadBridge: () => () => { },
890
+ }),
891
+ }, async () => 'thread-origin', () => 'claudecode');
892
+ const target = await policy.resolveTarget(job);
893
+ strict_1.default.equal(target.threadId, 'thread-new');
894
+ strict_1.default.equal(createThreadCalls.length, 1);
895
+ strict_1.default.deepEqual(createThreadCalls[0], {
896
+ workspaceId: '知识库',
897
+ title: '[Scheduled:Lark] two-minute ping',
898
+ agentType: 'claudecode',
899
+ });
900
+ });
901
+ (0, node_test_1.default)('lark side-thread execution policy falls back to workspace default when no preferred agent is set', async () => {
902
+ const job = {
903
+ id: 'job-1',
904
+ workspaceId: '知识库',
905
+ platform: 'lark',
906
+ route: { type: 'channel.chat', channelId: 'chat-1', participantId: 'user-1', threadId: 'thread-origin' },
907
+ executionMode: 'side-thread',
908
+ triggerType: 'cron',
909
+ cronExpr: '*/2 * * * *',
910
+ promptTemplate: 'ping',
911
+ description: 'two-minute ping',
912
+ enabled: true,
913
+ concurrencyPolicy: 'skip_if_running',
914
+ createdAt: '2026-04-22T06:00:00.000Z',
915
+ updatedAt: '2026-04-22T06:00:00.000Z',
916
+ };
917
+ const createThreadCalls = [];
918
+ const policy = (0, lark_execution_policies_js_1.createLarkExecutionPolicy)(job, {
919
+ store: {},
920
+ workspaceRouter: {
921
+ getThreadSessionKey: (threadId) => `session:${threadId}`,
922
+ listThreads: async () => [],
923
+ createThread: async (workspaceId, title, agentType) => {
924
+ createThreadCalls.push({ workspaceId, title: title || '', agentType });
925
+ return { id: 'thread-new' };
926
+ },
927
+ },
928
+ getChannelRuntime: () => ({
929
+ registerScheduledThreadBridge: () => () => { },
930
+ }),
931
+ }, async () => 'thread-origin', () => '');
932
+ const target = await policy.resolveTarget(job);
933
+ strict_1.default.equal(target.threadId, 'thread-new');
934
+ strict_1.default.equal(createThreadCalls.length, 1);
935
+ strict_1.default.equal(createThreadCalls[0].agentType, undefined);
936
+ });
861
937
  (0, node_test_1.default)('lark same-thread execution policy keeps the original thread target', async () => {
862
938
  const job = {
863
939
  id: 'job-1',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kafca/agentdock",
3
- "version": "0.1.48",
3
+ "version": "0.1.50",
4
4
  "license": "PolyForm-Noncommercial-1.0.0",
5
5
  "type": "module",
6
6
  "main": "dist-electron/electron/main.js",
@@ -1 +0,0 @@
1
- import{D as t}from"./index-mvjDN9uV.js";const e=()=>t.get("/projects"),r=o=>t.get(`/projects/${o}`);export{r as g,e as l};