@kafca/agentdock 0.1.41 → 0.1.43

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 (102) hide show
  1. package/README.md +10 -0
  2. package/dist/renderer/assets/{Badge-BX3RC8l6.js → Badge-CbG6yRSm.js} +1 -1
  3. package/dist/renderer/assets/{Chat-DJwIciel.js → Chat-BvNNWGGX.js} +1 -1
  4. package/dist/renderer/assets/{ChatMarkdown-DfGbRR0S.js → ChatMarkdown-Ct-PvJB8.js} +1 -1
  5. package/dist/renderer/assets/{Config-2x2RDL3j.js → Config-lQX2qVVV.js} +2 -2
  6. package/dist/renderer/assets/CronList-Dj_3muVG.js +1 -0
  7. package/dist/renderer/assets/{Dashboard-2Wcx_bvJ.js → Dashboard-eh_RhGYb.js} +2 -2
  8. package/dist/renderer/assets/{EmptyState-DoCpF2tn.js → EmptyState-Bn2Qh14U.js} +1 -1
  9. package/dist/renderer/assets/{KnowledgeDetail-CBRu2bXX.js → KnowledgeDetail-Bsz6Ou41.js} +2 -2
  10. package/dist/renderer/assets/{KnowledgeHome-CItdlDVR.js → KnowledgeHome-Cgj4XFXn.js} +2 -2
  11. package/dist/renderer/assets/{Logs-Cd_7ZOXc.js → Logs-Dp-NF6GN.js} +1 -1
  12. package/dist/renderer/assets/{Modal-B4eOiBsB.js → Modal-B6YPPBN6.js} +1 -1
  13. package/dist/renderer/assets/MonitorList-xEZWg460.js +1 -0
  14. package/dist/renderer/assets/{Page-C5VH4D9U.js → Page-Bn7RjGOS.js} +1 -1
  15. package/dist/renderer/assets/{ProjectDetail-D_DA--IP.js → ProjectDetail-Cv_jIE61.js} +2 -2
  16. package/dist/renderer/assets/{ProjectList-CtCXJ50u.js → ProjectList-BDk5_gqY.js} +1 -1
  17. package/dist/renderer/assets/{Select-B6E68LcN.js → Select-xshfMIEQ.js} +1 -1
  18. package/dist/renderer/assets/SessionChat-BkHy90z3.js +1 -0
  19. package/dist/renderer/assets/{SessionList-Do-5-Xx6.js → SessionList-BZyXT92L.js} +1 -1
  20. package/dist/renderer/assets/{ThreadChat-B1tEtE3V.js → ThreadChat-DUOIyXrS.js} +7 -7
  21. package/dist/renderer/assets/{Workspace-BlhS2RFw.js → Workspace-Dl80fNEC.js} +1 -1
  22. package/dist/renderer/assets/{arrow-left-DF1_F9Pk.js → arrow-left-C54ZI-AS.js} +1 -1
  23. package/dist/renderer/assets/{book-open-DxRTGpWO.js → book-open-Dl7GO0zn.js} +1 -1
  24. package/dist/renderer/assets/{check-BAqPPYkf.js → check-CiqgtrOL.js} +1 -1
  25. package/dist/renderer/assets/{chevron-down-DIZZgSb3.js → chevron-down-DTL2OuVh.js} +1 -1
  26. package/dist/renderer/assets/{circle-B5raL_XK.js → circle-DaVKfa3P.js} +1 -1
  27. package/dist/renderer/assets/desktop-C6q6wBae.js +5 -0
  28. package/dist/renderer/assets/desktop-jaAiayNB.js +1 -0
  29. package/dist/renderer/assets/en-D2SkCrhG.js +1 -0
  30. package/dist/renderer/assets/{funnel-BPjLpVSB.js → funnel-CrmnLMJI.js} +1 -1
  31. package/dist/renderer/assets/{heart-D2M1xN1N.js → heart-BMfQI7y_.js} +1 -1
  32. package/dist/renderer/assets/{index-Cx71F_Lz.js → index-HPNb1zfx.js} +39 -34
  33. package/dist/renderer/assets/{index-BijJAYmo.js → index-nreiKY1f.js} +3 -3
  34. package/dist/renderer/assets/{pencil-DlDr8Mmp.js → pencil-wTQ4l465.js} +1 -1
  35. package/dist/renderer/assets/{play-BOEG_mY8.js → play-BK--MXmw.js} +1 -1
  36. package/dist/renderer/assets/{plug-BI27elC-.js → plug-BIx9fjip.js} +1 -1
  37. package/dist/renderer/assets/{plus-BhURuFIQ.js → plus-Dn7JFWQ8.js} +1 -1
  38. package/dist/renderer/assets/projects-brJZgwEJ.js +1 -0
  39. package/dist/renderer/assets/{save-RwkHNm9e.js → save-CC3zOSWb.js} +1 -1
  40. package/dist/renderer/assets/{search-DMNtm2WP.js → search-CDTy9Czu.js} +1 -1
  41. package/dist/renderer/assets/{server-CNaxKyAq.js → server-DtQk3t2a.js} +1 -1
  42. package/dist/renderer/assets/{session-utils-vsALZkZN.js → session-utils-4ep5D66T.js} +1 -1
  43. package/dist/renderer/assets/{sessions-BY-R1IL_.js → sessions-Dor1LteH.js} +1 -1
  44. package/dist/renderer/assets/{shield-check-BF-4oJbj.js → shield-check-Cz2LpU6r.js} +1 -1
  45. package/dist/renderer/assets/{trash-2-DduflM4q.js → trash-2-C2EmWFZV.js} +1 -1
  46. package/dist/renderer/assets/{user-DBcvnuW4.js → user-I8B-cs5A.js} +1 -1
  47. package/dist/renderer/assets/{wifi-off-X1nXESYu.js → wifi-off-CPevTQJn.js} +1 -1
  48. package/dist/renderer/assets/zh-DIcdHycM.js +1 -0
  49. package/dist/renderer/index.html +1 -1
  50. package/dist-electron/packages/contracts/src/local-core.js +28 -0
  51. package/dist-electron/packages/core-sdk/src/index.js +32 -0
  52. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +76 -39
  53. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-session-coordinator.js +13 -0
  54. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-store.js +4 -1357
  55. package/dist-electron/services/local-ai-core/src/acp/local-core-slash-commands.js +28 -0
  56. package/dist-electron/services/local-ai-core/src/acp/store/agent-task-store.js +166 -0
  57. package/dist-electron/services/local-ai-core/src/acp/store/automation-monitor-store.js +231 -0
  58. package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +263 -0
  59. package/dist-electron/services/local-ai-core/src/acp/store/platform-store.js +186 -0
  60. package/dist-electron/services/local-ai-core/src/acp/store/scheduler-store.js +201 -0
  61. package/dist-electron/services/local-ai-core/src/acp/store/schema.js +275 -0
  62. package/dist-electron/services/local-ai-core/src/acp/store/security-store.js +266 -0
  63. package/dist-electron/services/local-ai-core/src/acp/store/thread-store.js +232 -0
  64. package/dist-electron/services/local-ai-core/src/acp/store/utils.js +47 -0
  65. package/dist-electron/services/local-ai-core/src/acp/store/workspace-registry-store.js +109 -0
  66. package/dist-electron/services/local-ai-core/src/automation/automation-conversation-executor.js +136 -0
  67. package/dist-electron/services/local-ai-core/src/automation/automation-monitor-repository.js +56 -0
  68. package/dist-electron/services/local-ai-core/src/automation/automation-monitor-service.js +359 -0
  69. package/dist-electron/services/local-ai-core/src/automation/condition-evaluator.js +77 -0
  70. package/dist-electron/services/local-ai-core/src/automation/mock-stock-provider.js +40 -0
  71. package/dist-electron/services/local-ai-core/src/automation/monitor-id.js +10 -0
  72. package/dist-electron/services/local-ai-core/src/channel/lark/cards.js +55 -0
  73. package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +101 -29
  74. package/dist-electron/services/local-ai-core/src/channel/shared/session-command-runtime.js +53 -0
  75. package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +51 -33
  76. package/dist-electron/services/local-ai-core/src/cli/lac.js +196 -0
  77. package/dist-electron/services/local-ai-core/src/cli/monitor-cli-parsers.js +37 -0
  78. package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +43 -0
  79. package/dist-electron/services/local-ai-core/src/kernel/capability-registry.js +12 -0
  80. package/dist-electron/services/local-ai-core/src/plugins/builtin/monitor-stock-plugin.js +30 -0
  81. package/dist-electron/services/local-ai-core/src/router/workspace-router.js +40 -4
  82. package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +41 -0
  83. package/dist-electron/services/local-ai-core/src/runtime/server-routes.js +31 -0
  84. package/dist-electron/services/local-ai-core/src/runtime/server.js +36 -0
  85. package/dist-electron/services/local-ai-core/src/scheduler/scheduled-bridge-session.js +25 -11
  86. package/dist-electron/services/local-ai-core/src/thread/session-command-service.js +275 -0
  87. package/dist-electron/services/local-ai-core/src/thread/slash-command-registry.js +27 -0
  88. package/dist-electron/services/local-ai-core/src/thread/thread-command-service.js +134 -0
  89. package/dist-electron/shared/desktop.js +21 -1
  90. package/dist-electron/tests/contracts/local-core-contracts.test.js +9 -0
  91. package/dist-electron/tests/electron/automation-monitor.test.js +38 -0
  92. package/dist-electron/tests/electron/lac-cli.test.js +146 -0
  93. package/dist-electron/tests/electron/plugin-kernel.test.js +26 -0
  94. package/dist-electron/tests/integration/local-core-refactor.test.js +359 -0
  95. package/package.json +1 -1
  96. package/dist/renderer/assets/CronList-C6nPAmEo.js +0 -1
  97. package/dist/renderer/assets/SessionChat-D1HtMdQS.js +0 -1
  98. package/dist/renderer/assets/desktop-CFcnzwcY.js +0 -1
  99. package/dist/renderer/assets/desktop-O8_6ZCVZ.js +0 -4
  100. package/dist/renderer/assets/en-CKhCF6St.js +0 -1
  101. package/dist/renderer/assets/projects-DpR972HM.js +0 -1
  102. package/dist/renderer/assets/zh-Dz5FLTBV.js +0 -1
@@ -5,7 +5,17 @@ exports.parseSlashCommand = parseSlashCommand;
5
5
  exports.normalizeAgentMode = normalizeAgentMode;
6
6
  exports.formatAgentMode = formatAgentMode;
7
7
  exports.modeHelpText = modeHelpText;
8
+ exports.normalizeAgentCommandTarget = normalizeAgentCommandTarget;
9
+ exports.formatAgentList = formatAgentList;
10
+ exports.agentHelpText = agentHelpText;
8
11
  exports.DEFAULT_AGENT_MODE = 'default';
12
+ const AGENT_ALIASES = {
13
+ claude: 'claudecode',
14
+ 'claude-code': 'claudecode',
15
+ claude_code: 'claudecode',
16
+ claudecode: 'claudecode',
17
+ cc: 'claudecode',
18
+ };
9
19
  const MODE_ALIASES = {
10
20
  auto: 'auto',
11
21
  default: 'default',
@@ -58,3 +68,21 @@ function modeHelpText(currentMode) {
58
68
  '`/mode yolo` 会跳过工具权限申请;使用 `/mode default` 可恢复默认权限。'
59
69
  ].join('\n');
60
70
  }
71
+ function normalizeAgentCommandTarget(agent) {
72
+ const key = String(agent || '').trim().toLowerCase();
73
+ return AGENT_ALIASES[key] || key;
74
+ }
75
+ function formatAgentList(agents) {
76
+ return [...new Set(agents.map(normalizeAgentCommandTarget).filter(Boolean))].sort();
77
+ }
78
+ function agentHelpText(input) {
79
+ const currentAgent = normalizeAgentCommandTarget(input.currentAgent) || 'unknown';
80
+ const defaultAgent = normalizeAgentCommandTarget(input.defaultAgent) || 'unknown';
81
+ const availableAgents = formatAgentList(input.availableAgents);
82
+ return [
83
+ `当前线程 Agent:${currentAgent}`,
84
+ `默认 Agent:${defaultAgent}`,
85
+ `可用 Agent:${availableAgents.length ? availableAgents.join(', ') : '无'}`,
86
+ '可用命令:`/agent list`、`/agent current`、`/agent use <agent-id>`、`/agent reset`。',
87
+ ].join('\n');
88
+ }
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LocalAgentTaskStore = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const index_js_1 = require("../../../../../packages/contracts/src/index.js");
6
+ const utils_js_1 = require("./utils.js");
7
+ class LocalAgentTaskStore {
8
+ db;
9
+ createAuditEvent;
10
+ constructor(db, createAuditEvent) {
11
+ this.db = db;
12
+ this.createAuditEvent = createAuditEvent;
13
+ }
14
+ create(input) {
15
+ const id = `task:${(0, node_crypto_1.randomUUID)()}`;
16
+ const now = new Date().toISOString();
17
+ const status = (0, index_js_1.normalizeAgentTaskStatus)(input.status);
18
+ const timeline = [{
19
+ id: `timeline:${(0, node_crypto_1.randomUUID)()}`,
20
+ type: 'status_change',
21
+ title: `Task ${status}`,
22
+ status,
23
+ timestamp: now,
24
+ }];
25
+ this.db.prepare(`
26
+ INSERT INTO agent_tasks (
27
+ id, workspace_id, device_id, runtime_id, thread_id, run_id, title, prompt, status, created_at, updated_at, queued_at,
28
+ started_at, completed_at, summary, error, timeline_json, logs_json, artifacts_json, approval_ids_json, metadata_json
29
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, NULL, ?, '[]', '[]', '[]', ?)
30
+ `).run(id, input.workspaceId, input.deviceId, input.runtimeId, input.threadId || null, input.runId || null, input.title, input.prompt ? (0, utils_js_1.redactSecrets)(input.prompt) : null, status, now, now, status === 'queued' ? now : null, status === 'running' ? now : null, JSON.stringify(timeline), JSON.stringify(input.metadata || {}));
31
+ const task = this.get(id);
32
+ this.createAuditEvent({
33
+ type: 'task.created',
34
+ workspaceId: task.workspaceId,
35
+ taskId: task.taskId,
36
+ actor: 'local',
37
+ summary: `Task created: ${task.title}`,
38
+ metadata: { runtimeId: task.runtimeId, threadId: task.threadId, runId: task.runId },
39
+ });
40
+ return task;
41
+ }
42
+ list(query = {}) {
43
+ const predicates = [];
44
+ const params = [];
45
+ if (query.workspaceId) {
46
+ predicates.push('workspace_id = ?');
47
+ params.push(query.workspaceId);
48
+ }
49
+ if (query.runtimeId) {
50
+ predicates.push('runtime_id = ?');
51
+ params.push(query.runtimeId);
52
+ }
53
+ if (query.status) {
54
+ const statuses = (Array.isArray(query.status) ? query.status : [query.status]).map((status) => (0, index_js_1.normalizeAgentTaskStatus)(status));
55
+ predicates.push(`status IN (${statuses.map(() => '?').join(', ')})`);
56
+ params.push(...statuses);
57
+ }
58
+ const limit = Math.max(1, Math.min(Number(query.limit || 50), 100));
59
+ const where = predicates.length ? `WHERE ${predicates.join(' AND ')}` : '';
60
+ const rows = this.db.prepare(`
61
+ SELECT *
62
+ FROM agent_tasks
63
+ ${where}
64
+ ORDER BY updated_at DESC
65
+ LIMIT ?
66
+ `).all(...params, limit);
67
+ return { tasks: rows.map((row) => this.toAgentTask(row)) };
68
+ }
69
+ get(taskId) {
70
+ const row = this.db.prepare('SELECT * FROM agent_tasks WHERE id = ?').get(taskId);
71
+ return row ? this.toAgentTask(row) : undefined;
72
+ }
73
+ getByRunId(runId) {
74
+ const row = this.db.prepare('SELECT * FROM agent_tasks WHERE run_id = ? ORDER BY updated_at DESC LIMIT 1').get(runId);
75
+ return row ? this.toAgentTask(row) : undefined;
76
+ }
77
+ update(taskId, input) {
78
+ const existing = this.get(taskId);
79
+ if (!existing) {
80
+ throw new Error(`Task not found: ${taskId}`);
81
+ }
82
+ const now = new Date().toISOString();
83
+ const nextStatus = input.status ? (0, index_js_1.normalizeAgentTaskStatus)(input.status) : existing.status;
84
+ const timeline = [...existing.timeline];
85
+ const logs = [...existing.logs];
86
+ const artifacts = [...existing.artifacts];
87
+ const approvalIds = [...existing.approvalIds];
88
+ if (input.status && nextStatus !== existing.status) {
89
+ timeline.push({
90
+ id: `timeline:${(0, node_crypto_1.randomUUID)()}`,
91
+ type: 'status_change',
92
+ title: `Task ${nextStatus}`,
93
+ status: nextStatus,
94
+ timestamp: now,
95
+ });
96
+ }
97
+ if (input.timelineItem) {
98
+ timeline.push({
99
+ id: input.timelineItem.id || `timeline:${(0, node_crypto_1.randomUUID)()}`,
100
+ timestamp: input.timelineItem.timestamp || now,
101
+ ...input.timelineItem,
102
+ });
103
+ }
104
+ if (input.log) {
105
+ logs.push({
106
+ id: input.log.id || `log:${(0, node_crypto_1.randomUUID)()}`,
107
+ timestamp: input.log.timestamp || now,
108
+ ...input.log,
109
+ message: (0, utils_js_1.redactSecrets)(input.log.message),
110
+ });
111
+ }
112
+ if (input.artifact) {
113
+ artifacts.push({
114
+ id: input.artifact.id || `artifact:${(0, node_crypto_1.randomUUID)()}`,
115
+ ...input.artifact,
116
+ });
117
+ }
118
+ if (input.approvalId && !approvalIds.includes(input.approvalId)) {
119
+ approvalIds.push(input.approvalId);
120
+ }
121
+ this.db.prepare(`
122
+ UPDATE agent_tasks
123
+ SET status = ?, thread_id = ?, run_id = ?, title = ?, updated_at = ?, queued_at = ?, started_at = ?, completed_at = ?,
124
+ summary = ?, error = ?, timeline_json = ?, logs_json = ?, artifacts_json = ?, approval_ids_json = ?, metadata_json = ?
125
+ WHERE id = ?
126
+ `).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);
127
+ const task = this.get(taskId);
128
+ if (input.status && nextStatus !== existing.status) {
129
+ this.createAuditEvent({
130
+ type: 'task.updated',
131
+ workspaceId: task.workspaceId,
132
+ taskId: task.taskId,
133
+ actor: 'local',
134
+ summary: `Task status changed to ${nextStatus}.`,
135
+ metadata: { previousStatus: existing.status, status: nextStatus, runId: task.runId },
136
+ });
137
+ }
138
+ return task;
139
+ }
140
+ toAgentTask(row) {
141
+ return {
142
+ taskId: row.id,
143
+ workspaceId: row.workspace_id,
144
+ deviceId: row.device_id,
145
+ runtimeId: row.runtime_id,
146
+ threadId: row.thread_id || undefined,
147
+ runId: row.run_id || undefined,
148
+ title: row.title,
149
+ prompt: row.prompt || undefined,
150
+ status: (0, index_js_1.normalizeAgentTaskStatus)(row.status),
151
+ createdAt: row.created_at,
152
+ updatedAt: row.updated_at,
153
+ queuedAt: row.queued_at || undefined,
154
+ startedAt: row.started_at || undefined,
155
+ completedAt: row.completed_at || undefined,
156
+ summary: row.summary || undefined,
157
+ error: row.error || undefined,
158
+ timeline: (0, utils_js_1.parseJson)(row.timeline_json, []),
159
+ logs: (0, utils_js_1.parseJson)(row.logs_json, []),
160
+ artifacts: (0, utils_js_1.parseJson)(row.artifacts_json, []),
161
+ approvalIds: (0, utils_js_1.parseJson)(row.approval_ids_json, []),
162
+ metadata: (0, utils_js_1.parseJson)(row.metadata_json, {}),
163
+ };
164
+ }
165
+ }
166
+ exports.LocalAgentTaskStore = LocalAgentTaskStore;
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LocalAutomationMonitorStore = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const index_js_1 = require("../../../../../packages/contracts/src/index.js");
6
+ class LocalAutomationMonitorStore {
7
+ db;
8
+ constructor(db) {
9
+ this.db = db;
10
+ }
11
+ list(workspaceId) {
12
+ const query = workspaceId
13
+ ? `
14
+ SELECT id, workspace_id, title, source_type, source_config_json, condition_json, prompt_template, platform, route_type, route_config,
15
+ execution_mode, enabled, cooldown_ms, concurrency_policy, last_state_json, created_at, updated_at, last_triggered_at, last_status, last_error
16
+ FROM automation_monitors
17
+ WHERE workspace_id = ?
18
+ ORDER BY updated_at DESC
19
+ `
20
+ : `
21
+ SELECT id, workspace_id, title, source_type, source_config_json, condition_json, prompt_template, platform, route_type, route_config,
22
+ execution_mode, enabled, cooldown_ms, concurrency_policy, last_state_json, created_at, updated_at, last_triggered_at, last_status, last_error
23
+ FROM automation_monitors
24
+ ORDER BY updated_at DESC
25
+ `;
26
+ const rows = this.db.prepare(query).all(...(workspaceId ? [workspaceId] : []));
27
+ return rows.map((row) => this.toMonitor(row));
28
+ }
29
+ get(monitorId) {
30
+ const row = this.db.prepare(`
31
+ SELECT id, workspace_id, title, source_type, source_config_json, condition_json, prompt_template, platform, route_type, route_config,
32
+ execution_mode, enabled, cooldown_ms, concurrency_policy, last_state_json, created_at, updated_at, last_triggered_at, last_status, last_error
33
+ FROM automation_monitors
34
+ WHERE id = ?
35
+ `).get(monitorId);
36
+ return row ? this.toMonitor(row) : undefined;
37
+ }
38
+ create(input) {
39
+ const title = String(input.title || '').trim();
40
+ if (!title)
41
+ throw new Error('Automation monitor title is required.');
42
+ const sourceType = String(input.sourceType || '').trim();
43
+ if (!sourceType)
44
+ throw new Error('Automation monitor source type is required.');
45
+ const condition = {
46
+ ...input.condition,
47
+ metric: String(input.condition?.metric || '').trim(),
48
+ operator: (0, index_js_1.normalizeAutomationMonitorConditionOperator)(input.condition?.operator),
49
+ };
50
+ if (!condition.metric)
51
+ throw new Error('Automation monitor condition metric is required.');
52
+ const id = this.createMonitorId();
53
+ const now = new Date().toISOString();
54
+ this.db.prepare(`
55
+ INSERT INTO automation_monitors (
56
+ id, workspace_id, title, source_type, source_config_json, condition_json, prompt_template, platform, route_type, route_config,
57
+ execution_mode, enabled, cooldown_ms, concurrency_policy, last_state_json, created_at, updated_at
58
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'skip_if_running', ?, ?, ?)
59
+ `).run(id, input.workspaceId, title, sourceType, JSON.stringify(input.sourceConfig || {}), JSON.stringify(condition), input.promptTemplate, (0, index_js_1.normalizeChannelPlatform)(input.platform), input.route.type, JSON.stringify(input.route), (0, index_js_1.normalizeScheduledJobExecutionMode)(input.executionMode, 'side-thread'), input.enabled === false ? 0 : 1, Math.max(0, Number(input.cooldownMs ?? 15 * 60 * 1000)), null, now, now);
60
+ return this.get(id);
61
+ }
62
+ update(monitorId, input) {
63
+ const existing = this.get(monitorId);
64
+ if (!existing)
65
+ throw new Error(`Automation monitor not found: ${monitorId}`);
66
+ const nextCondition = input.condition
67
+ ? {
68
+ ...input.condition,
69
+ metric: String(input.condition.metric || '').trim(),
70
+ operator: (0, index_js_1.normalizeAutomationMonitorConditionOperator)(input.condition.operator),
71
+ }
72
+ : existing.condition;
73
+ const next = {
74
+ ...existing,
75
+ ...(typeof input.title === 'string' ? { title: input.title.trim() } : {}),
76
+ ...(input.sourceConfig ? { sourceConfig: input.sourceConfig } : {}),
77
+ condition: nextCondition,
78
+ ...(typeof input.promptTemplate === 'string' ? { promptTemplate: input.promptTemplate } : {}),
79
+ ...(input.route ? { route: input.route } : {}),
80
+ ...(input.executionMode ? { executionMode: (0, index_js_1.normalizeScheduledJobExecutionMode)(input.executionMode, 'side-thread') } : {}),
81
+ ...(typeof input.enabled === 'boolean' ? { enabled: input.enabled } : {}),
82
+ ...(typeof input.cooldownMs === 'number' ? { cooldownMs: Math.max(0, input.cooldownMs) } : {}),
83
+ updatedAt: new Date().toISOString(),
84
+ };
85
+ if (!next.title)
86
+ throw new Error('Automation monitor title is required.');
87
+ this.db.prepare(`
88
+ UPDATE automation_monitors
89
+ SET title = ?, source_config_json = ?, condition_json = ?, prompt_template = ?, route_type = ?, route_config = ?,
90
+ execution_mode = ?, enabled = ?, cooldown_ms = ?, updated_at = ?
91
+ WHERE id = ?
92
+ `).run(next.title, JSON.stringify(next.sourceConfig || {}), JSON.stringify(next.condition), next.promptTemplate, next.route.type, JSON.stringify(next.route), next.executionMode, next.enabled ? 1 : 0, next.cooldownMs, next.updatedAt, monitorId);
93
+ return this.get(monitorId);
94
+ }
95
+ updateState(monitorId, input) {
96
+ this.db.prepare(`
97
+ UPDATE automation_monitors
98
+ SET last_state_json = CASE WHEN ? IS NULL THEN last_state_json ELSE ? END,
99
+ last_triggered_at = COALESCE(?, last_triggered_at),
100
+ last_status = COALESCE(?, last_status),
101
+ last_error = CASE WHEN ? IS NULL THEN last_error ELSE ? END,
102
+ enabled = CASE WHEN ? IS NULL THEN enabled ELSE ? END,
103
+ updated_at = ?
104
+ WHERE id = ?
105
+ `).run(input.lastState == null ? null : JSON.stringify(input.lastState), input.lastState == null ? null : JSON.stringify(input.lastState), input.lastTriggeredAt || null, input.lastStatus || null, input.lastError == null ? null : input.lastError, input.lastError == null ? null : input.lastError, typeof input.enabled === 'boolean' ? (input.enabled ? 1 : 0) : null, typeof input.enabled === 'boolean' ? (input.enabled ? 1 : 0) : null, new Date().toISOString(), monitorId);
106
+ }
107
+ delete(monitorId) {
108
+ const result = this.db.prepare('DELETE FROM automation_monitors WHERE id = ?').run(monitorId);
109
+ if (result.changes === 0)
110
+ throw new Error(`Automation monitor not found: ${monitorId}`);
111
+ return { deleted: true };
112
+ }
113
+ listRuns(monitorId) {
114
+ const rows = this.db.prepare(`
115
+ SELECT id, monitor_id, status, triggered_at, started_at, finished_at, error, event_snapshot_json, thread_id, run_id, delivery_mode, delivery_status, delivery_error, last_bridge_event_at
116
+ FROM automation_monitor_runs
117
+ WHERE monitor_id = ?
118
+ ORDER BY triggered_at DESC
119
+ `).all(monitorId);
120
+ return rows.map((row) => this.toRun(row));
121
+ }
122
+ createRun(monitorId, status, input = {}) {
123
+ const id = `monitorrun:${(0, node_crypto_1.randomUUID)()}`;
124
+ const triggeredAt = input.triggeredAt || new Date().toISOString();
125
+ const normalizedStatus = (0, index_js_1.normalizeAutomationMonitorStatus)(status);
126
+ this.db.prepare(`
127
+ INSERT INTO automation_monitor_runs (id, monitor_id, status, triggered_at, started_at, finished_at, error, event_snapshot_json, thread_id, run_id, delivery_mode, delivery_status, delivery_error, last_bridge_event_at)
128
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
129
+ `).run(id, monitorId, normalizedStatus, triggeredAt, input.startedAt || null, input.finishedAt || null, input.error || null, input.eventSnapshot ? JSON.stringify(input.eventSnapshot) : null, input.threadId || null, input.runId || null, input.deliveryMode || null, input.deliveryStatus || null, input.deliveryError || null, input.lastBridgeEventAt || null);
130
+ this.updateState(monitorId, {
131
+ lastTriggeredAt: triggeredAt,
132
+ lastStatus: normalizedStatus,
133
+ lastError: input.error || '',
134
+ });
135
+ return this.getRun(id);
136
+ }
137
+ getRun(runId) {
138
+ const row = this.db.prepare(`
139
+ SELECT id, monitor_id, status, triggered_at, started_at, finished_at, error, event_snapshot_json, thread_id, run_id, delivery_mode, delivery_status, delivery_error, last_bridge_event_at
140
+ FROM automation_monitor_runs
141
+ WHERE id = ?
142
+ `).get(runId);
143
+ return row ? this.toRun(row) : undefined;
144
+ }
145
+ updateRun(runId, input) {
146
+ const existing = this.getRun(runId);
147
+ if (!existing)
148
+ throw new Error(`Automation monitor run not found: ${runId}`);
149
+ const next = {
150
+ ...existing,
151
+ ...input,
152
+ ...(input.status ? { status: (0, index_js_1.normalizeAutomationMonitorStatus)(input.status) } : {}),
153
+ };
154
+ this.db.prepare(`
155
+ UPDATE automation_monitor_runs
156
+ SET status = ?, triggered_at = ?, started_at = ?, finished_at = ?, error = ?, event_snapshot_json = ?, thread_id = ?, run_id = ?, delivery_mode = ?, delivery_status = ?, delivery_error = ?, last_bridge_event_at = ?
157
+ WHERE id = ?
158
+ `).run(next.status, next.triggeredAt, next.startedAt || null, next.finishedAt || null, next.error || null, next.eventSnapshot ? JSON.stringify(next.eventSnapshot) : null, next.threadId || null, next.runId || null, next.deliveryMode || null, next.deliveryStatus || null, next.deliveryError || null, next.lastBridgeEventAt || null, runId);
159
+ if (input.status || Object.prototype.hasOwnProperty.call(input, 'error') || input.finishedAt || input.triggeredAt) {
160
+ this.updateState(existing.monitorId, {
161
+ lastTriggeredAt: next.triggeredAt,
162
+ lastStatus: next.status,
163
+ lastError: next.error || '',
164
+ });
165
+ }
166
+ return this.getRun(runId);
167
+ }
168
+ toMonitor(row) {
169
+ const condition = parseJson(row.condition_json, {});
170
+ return {
171
+ id: row.id,
172
+ workspaceId: row.workspace_id,
173
+ title: row.title,
174
+ sourceType: row.source_type,
175
+ sourceConfig: parseJson(row.source_config_json || '{}', {}),
176
+ condition: {
177
+ ...condition,
178
+ operator: (0, index_js_1.normalizeAutomationMonitorConditionOperator)(condition.operator),
179
+ },
180
+ promptTemplate: row.prompt_template,
181
+ platform: (0, index_js_1.normalizeChannelPlatform)(row.platform),
182
+ route: JSON.parse(row.route_config),
183
+ executionMode: (0, index_js_1.normalizeScheduledJobExecutionMode)(row.execution_mode, 'side-thread'),
184
+ enabled: Boolean(row.enabled),
185
+ cooldownMs: Number(row.cooldown_ms || 0),
186
+ concurrencyPolicy: row.concurrency_policy,
187
+ lastState: row.last_state_json ? parseJson(row.last_state_json, {}) : undefined,
188
+ createdAt: row.created_at,
189
+ updatedAt: row.updated_at,
190
+ lastTriggeredAt: row.last_triggered_at || undefined,
191
+ lastStatus: row.last_status ? (0, index_js_1.normalizeAutomationMonitorStatus)(row.last_status) : undefined,
192
+ lastError: row.last_error || undefined,
193
+ };
194
+ }
195
+ toRun(row) {
196
+ return {
197
+ id: row.id,
198
+ monitorId: row.monitor_id,
199
+ status: (0, index_js_1.normalizeAutomationMonitorStatus)(row.status),
200
+ triggeredAt: row.triggered_at,
201
+ startedAt: row.started_at || undefined,
202
+ finishedAt: row.finished_at || undefined,
203
+ error: row.error || undefined,
204
+ eventSnapshot: row.event_snapshot_json ? parseJson(row.event_snapshot_json, {}) : undefined,
205
+ threadId: row.thread_id || undefined,
206
+ runId: row.run_id || undefined,
207
+ deliveryMode: row.delivery_mode || undefined,
208
+ deliveryStatus: row.delivery_status || undefined,
209
+ deliveryError: row.delivery_error || undefined,
210
+ lastBridgeEventAt: row.last_bridge_event_at || undefined,
211
+ };
212
+ }
213
+ createMonitorId() {
214
+ let id = `monitor:${(0, node_crypto_1.randomUUID)()}`;
215
+ for (let attempt = 0; attempt < 5 && this.get(id); attempt += 1) {
216
+ id = `monitor:${(0, node_crypto_1.randomUUID)()}`;
217
+ }
218
+ if (this.get(id))
219
+ throw new Error('Unable to allocate a unique automation monitor id.');
220
+ return id;
221
+ }
222
+ }
223
+ exports.LocalAutomationMonitorStore = LocalAutomationMonitorStore;
224
+ function parseJson(value, fallback) {
225
+ try {
226
+ return JSON.parse(value);
227
+ }
228
+ catch {
229
+ return fallback;
230
+ }
231
+ }