@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
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LocalThreadStore = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const index_js_1 = require("../../../../../packages/contracts/src/index.js");
6
+ const desktop_js_1 = require("../../../../../shared/desktop.js");
7
+ const workspace_thread_mappers_js_1 = require("../../thread/workspace-thread-mappers.js");
8
+ const workspace_thread_id_js_1 = require("../../thread/workspace-thread-id.js");
9
+ const utils_js_1 = require("./utils.js");
10
+ class LocalThreadStore {
11
+ db;
12
+ constructor(db) {
13
+ this.db = db;
14
+ }
15
+ listSummaries(workspaceId) {
16
+ const rows = this.db.prepare(`
17
+ SELECT id, workspace_id, session_id, bridge_session_key, title, agent_type, created_at, updated_at, history_count, excerpt, acp_session_id, acp_supports_load, agent_mode
18
+ FROM threads
19
+ WHERE workspace_id = ?
20
+ ORDER BY updated_at DESC
21
+ `).all(workspaceId);
22
+ return rows.map((row) => ({
23
+ id: row.id,
24
+ workspaceId: row.workspace_id,
25
+ title: row.title,
26
+ live: false,
27
+ updatedAt: row.updated_at,
28
+ createdAt: row.created_at,
29
+ historyCount: row.history_count,
30
+ excerpt: row.excerpt,
31
+ runId: undefined,
32
+ bridgeSessionKey: row.bridge_session_key,
33
+ agentType: row.agent_type,
34
+ }));
35
+ }
36
+ count(workspaceId) {
37
+ const row = this.db.prepare('SELECT COUNT(*) AS total FROM threads WHERE workspace_id = ?').get(workspaceId);
38
+ return Number(row?.total || 0);
39
+ }
40
+ create(workspaceId, title, agentType = desktop_js_1.LOCALCORE_ACP_AGENT_TYPE, agentMode = 'default') {
41
+ const sessionId = (0, node_crypto_1.randomUUID)();
42
+ const threadId = (0, workspace_thread_id_js_1.encodeThreadId)(workspaceId, sessionId);
43
+ const now = new Date().toISOString();
44
+ const bridgeSessionKey = `${desktop_js_1.LOCALCORE_ACP_AGENT_TYPE}:${workspaceId}:${sessionId}`;
45
+ this.db.prepare(`
46
+ INSERT INTO threads (id, workspace_id, session_id, bridge_session_key, title, agent_type, created_at, updated_at, history_count, excerpt, agent_mode)
47
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0, '', ?)
48
+ `).run(threadId, workspaceId, sessionId, bridgeSessionKey, title, agentType, now, now, agentMode || 'default');
49
+ return {
50
+ id: threadId,
51
+ workspaceId,
52
+ title,
53
+ live: false,
54
+ updatedAt: now,
55
+ createdAt: now,
56
+ historyCount: 0,
57
+ excerpt: '',
58
+ bridgeSessionKey,
59
+ agentType,
60
+ messages: [],
61
+ selectedKnowledgeBaseIds: [],
62
+ pendingPermissionRequest: null,
63
+ };
64
+ }
65
+ get(threadId, selectedKnowledgeBaseIds) {
66
+ const row = this.getRow(threadId);
67
+ if (!row) {
68
+ throw new Error(`Thread not found: ${threadId}`);
69
+ }
70
+ const messages = this.db.prepare(`
71
+ SELECT id, thread_id, role, content, tool_call_json, bridge_kind, bridge_status, timestamp, kind, seq
72
+ FROM messages
73
+ WHERE thread_id = ?
74
+ ORDER BY seq ASC
75
+ `).all(threadId);
76
+ return {
77
+ id: row.id,
78
+ workspaceId: row.workspace_id,
79
+ title: row.title,
80
+ live: false,
81
+ updatedAt: row.updated_at,
82
+ createdAt: row.created_at,
83
+ historyCount: row.history_count,
84
+ excerpt: row.excerpt,
85
+ bridgeSessionKey: row.bridge_session_key,
86
+ agentType: row.agent_type,
87
+ messages: messages.map((message) => ({
88
+ id: message.id,
89
+ role: message.role,
90
+ content: message.content,
91
+ toolCall: (0, utils_js_1.parseJson)(message.tool_call_json || 'null', null) || undefined,
92
+ bridgeKind: (0, utils_js_1.normalizeBridgeKind)(message.bridge_kind),
93
+ bridgeStatus: (0, utils_js_1.normalizeBridgeStatus)(message.bridge_status),
94
+ timestamp: message.timestamp,
95
+ kind: message.kind,
96
+ })),
97
+ selectedKnowledgeBaseIds,
98
+ pendingPermissionRequest: null,
99
+ };
100
+ }
101
+ rename(threadId, title) {
102
+ const now = new Date().toISOString();
103
+ this.db.prepare('UPDATE threads SET title = ?, updated_at = ? WHERE id = ?').run(title, now, threadId);
104
+ }
105
+ delete(threadId) {
106
+ this.db.prepare('DELETE FROM threads WHERE id = ?').run(threadId);
107
+ }
108
+ appendMessage(threadId, role, content, kind, toolCall, bridgeKind, bridgeStatus) {
109
+ const timestamp = new Date().toISOString();
110
+ const nextSequenceRow = this.db.prepare('SELECT COALESCE(MAX(seq), -1) + 1 AS next_seq FROM messages WHERE thread_id = ?').get(threadId);
111
+ const nextSeq = Number(nextSequenceRow?.next_seq || 0);
112
+ const id = `${timestamp}-${role}-${nextSeq}`;
113
+ const excerpt = (0, workspace_thread_mappers_js_1.normalizeMessageContent)(content);
114
+ this.db.exec('BEGIN IMMEDIATE');
115
+ try {
116
+ this.db.prepare(`
117
+ INSERT INTO messages (id, thread_id, role, content, tool_call_json, bridge_kind, bridge_status, timestamp, kind, seq)
118
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
119
+ `).run(id, threadId, role, content, toolCall ? JSON.stringify(toolCall) : null, bridgeKind || null, bridgeStatus || null, timestamp, kind, nextSeq);
120
+ this.db.prepare(`
121
+ UPDATE threads
122
+ SET updated_at = ?, history_count = history_count + 1, excerpt = ?
123
+ WHERE id = ?
124
+ `).run(timestamp, excerpt, threadId);
125
+ this.db.exec('COMMIT');
126
+ }
127
+ catch (error) {
128
+ this.db.exec('ROLLBACK');
129
+ throw error;
130
+ }
131
+ return { id, timestamp };
132
+ }
133
+ upsertMessage(threadId, id, role, content, kind, toolCall, bridgeKind, bridgeStatus) {
134
+ const timestamp = new Date().toISOString();
135
+ const excerpt = (0, workspace_thread_mappers_js_1.normalizeMessageContent)(content);
136
+ const existing = this.db.prepare('SELECT id FROM messages WHERE id = ? AND thread_id = ?').get(id, threadId);
137
+ this.db.exec('BEGIN IMMEDIATE');
138
+ try {
139
+ if (existing) {
140
+ this.db.prepare(`
141
+ UPDATE messages
142
+ SET content = ?, tool_call_json = ?, bridge_kind = ?, bridge_status = ?, timestamp = ?, kind = ?
143
+ WHERE id = ? AND thread_id = ?
144
+ `).run(content, toolCall ? JSON.stringify(toolCall) : null, bridgeKind || null, bridgeStatus || null, timestamp, kind, id, threadId);
145
+ }
146
+ else {
147
+ const nextSequenceRow = this.db.prepare('SELECT COALESCE(MAX(seq), -1) + 1 AS next_seq FROM messages WHERE thread_id = ?').get(threadId);
148
+ const nextSeq = Number(nextSequenceRow?.next_seq || 0);
149
+ this.db.prepare(`
150
+ INSERT INTO messages (id, thread_id, role, content, tool_call_json, bridge_kind, bridge_status, timestamp, kind, seq)
151
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
152
+ `).run(id, threadId, role, content, toolCall ? JSON.stringify(toolCall) : null, bridgeKind || null, bridgeStatus || null, timestamp, kind, nextSeq);
153
+ this.db.prepare(`
154
+ UPDATE threads
155
+ SET history_count = history_count + 1
156
+ WHERE id = ?
157
+ `).run(threadId);
158
+ }
159
+ this.db.prepare(`
160
+ UPDATE threads
161
+ SET updated_at = ?, excerpt = ?
162
+ WHERE id = ?
163
+ `).run(timestamp, excerpt, threadId);
164
+ this.db.exec('COMMIT');
165
+ }
166
+ catch (error) {
167
+ this.db.exec('ROLLBACK');
168
+ throw error;
169
+ }
170
+ return { id, timestamp };
171
+ }
172
+ updateRun(runId, threadId, status) {
173
+ const now = new Date().toISOString();
174
+ const normalizedStatus = (0, index_js_1.normalizeRunStatus)(status);
175
+ const existing = this.db.prepare('SELECT id FROM runs WHERE id = ?').get(runId);
176
+ if (existing) {
177
+ this.db.prepare('UPDATE runs SET status = ?, updated_at = ? WHERE id = ?').run(normalizedStatus, now, runId);
178
+ return;
179
+ }
180
+ this.db.prepare(`
181
+ INSERT INTO runs (id, thread_id, status, started_at, updated_at)
182
+ VALUES (?, ?, ?, ?, ?)
183
+ `).run(runId, threadId, normalizedStatus, now, now);
184
+ }
185
+ getLatestRunForThread(threadId) {
186
+ const row = this.db.prepare(`
187
+ SELECT id, thread_id, status, started_at, updated_at
188
+ FROM runs
189
+ WHERE thread_id = ?
190
+ ORDER BY updated_at DESC
191
+ LIMIT 1
192
+ `).get(threadId);
193
+ return row ? { ...row, status: (0, index_js_1.normalizeRunStatus)(row.status) } : undefined;
194
+ }
195
+ getRun(runId) {
196
+ const row = this.db.prepare(`
197
+ SELECT id, thread_id, status, started_at, updated_at
198
+ FROM runs
199
+ WHERE id = ?
200
+ `).get(runId);
201
+ return row ? { ...row, status: (0, index_js_1.normalizeRunStatus)(row.status) } : undefined;
202
+ }
203
+ getRow(threadId) {
204
+ return this.db.prepare(`
205
+ SELECT id, workspace_id, session_id, bridge_session_key, title, agent_type, created_at, updated_at, history_count, excerpt, acp_session_id, acp_supports_load, agent_mode
206
+ FROM threads
207
+ WHERE id = ?
208
+ `).get(threadId);
209
+ }
210
+ updateAgentMode(threadId, mode) {
211
+ this.db.prepare(`
212
+ UPDATE threads
213
+ SET agent_mode = ?, updated_at = ?
214
+ WHERE id = ?
215
+ `).run(mode, new Date().toISOString(), threadId);
216
+ }
217
+ updateAgentType(threadId, agentType) {
218
+ this.db.prepare(`
219
+ UPDATE threads
220
+ SET agent_type = ?, acp_session_id = NULL, acp_supports_load = 0, updated_at = ?
221
+ WHERE id = ?
222
+ `).run(agentType, new Date().toISOString(), threadId);
223
+ }
224
+ updateSession(threadId, sessionId, supportsLoad) {
225
+ this.db.prepare(`
226
+ UPDATE threads
227
+ SET acp_session_id = ?, acp_supports_load = ?, updated_at = COALESCE(updated_at, ?)
228
+ WHERE id = ?
229
+ `).run(sessionId, supportsLoad ? 1 : 0, new Date().toISOString(), threadId);
230
+ }
231
+ }
232
+ exports.LocalThreadStore = LocalThreadStore;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseJson = parseJson;
4
+ exports.normalizeBridgeKind = normalizeBridgeKind;
5
+ exports.normalizeBridgeStatus = normalizeBridgeStatus;
6
+ exports.defaultPermissions = defaultPermissions;
7
+ exports.redactSecrets = redactSecrets;
8
+ function parseJson(value, fallback) {
9
+ try {
10
+ return JSON.parse(value);
11
+ }
12
+ catch {
13
+ return fallback;
14
+ }
15
+ }
16
+ function normalizeBridgeKind(value) {
17
+ switch (value) {
18
+ case 'assistant':
19
+ case 'thought':
20
+ case 'plan':
21
+ case 'tool':
22
+ case 'status':
23
+ case 'permission':
24
+ return value;
25
+ default:
26
+ return undefined;
27
+ }
28
+ }
29
+ function normalizeBridgeStatus(value) {
30
+ return value === 'awaiting_input' ? value : undefined;
31
+ }
32
+ function defaultPermissions() {
33
+ return {
34
+ 'workspace.read': 'allow',
35
+ 'workspace.write': 'ask',
36
+ 'command.execute': 'ask',
37
+ 'network.access': 'ask',
38
+ 'secrets.access': 'deny',
39
+ 'git.modify': 'ask',
40
+ };
41
+ }
42
+ function redactSecrets(value) {
43
+ return value
44
+ .replace(/\b(sk-[A-Za-z0-9_-]{12,})\b/g, '[REDACTED_SECRET]')
45
+ .replace(/\b([A-Za-z0-9_]*TOKEN[A-Za-z0-9_]*|[A-Za-z0-9_]*SECRET[A-Za-z0-9_]*|[A-Za-z0-9_]*KEY[A-Za-z0-9_]*)=([^\s]+)/gi, '$1=[REDACTED_SECRET]')
46
+ .replace(/\b(Bearer\s+)[A-Za-z0-9._-]+/gi, '$1[REDACTED_SECRET]');
47
+ }
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LocalWorkspaceRegistryStore = void 0;
4
+ const utils_js_1 = require("./utils.js");
5
+ class LocalWorkspaceRegistryStore {
6
+ db;
7
+ constructor(db) {
8
+ this.db = db;
9
+ }
10
+ list() {
11
+ const rows = this.db.prepare(`
12
+ SELECT id, display_name, path, device_id, default_runtime_id, git_json, health_json, metadata_json, created_at, updated_at, last_opened_at
13
+ FROM workspace_registry
14
+ ORDER BY display_name ASC
15
+ `).all();
16
+ return rows.map((row) => this.toEntry(row));
17
+ }
18
+ get(workspaceId) {
19
+ const row = this.db.prepare(`
20
+ SELECT id, display_name, path, device_id, default_runtime_id, git_json, health_json, metadata_json, created_at, updated_at, last_opened_at
21
+ FROM workspace_registry
22
+ WHERE id = ?
23
+ `).get(workspaceId);
24
+ return row ? this.toEntry(row) : undefined;
25
+ }
26
+ upsert(input) {
27
+ const id = input.workspaceId || input.displayName;
28
+ const now = new Date().toISOString();
29
+ const existing = this.get(id);
30
+ const health = input.health || existing?.health || {
31
+ status: 'unknown',
32
+ summary: 'Workspace health has not been checked.',
33
+ issues: [],
34
+ };
35
+ this.db.prepare(`
36
+ INSERT INTO workspace_registry (
37
+ id, display_name, path, device_id, default_runtime_id, git_json, health_json, metadata_json, created_at, updated_at, last_opened_at
38
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
39
+ ON CONFLICT(id) DO UPDATE SET
40
+ display_name = excluded.display_name,
41
+ path = excluded.path,
42
+ device_id = excluded.device_id,
43
+ default_runtime_id = excluded.default_runtime_id,
44
+ git_json = excluded.git_json,
45
+ health_json = excluded.health_json,
46
+ metadata_json = excluded.metadata_json,
47
+ updated_at = excluded.updated_at
48
+ `).run(id, input.displayName, input.path, input.deviceId, input.defaultRuntimeId || null, JSON.stringify(input.git || existing?.git || {}), JSON.stringify(health), JSON.stringify(input.metadata || existing?.metadata || {}), existing?.createdAt || now, now, existing?.lastOpenedAt || null);
49
+ return this.get(id);
50
+ }
51
+ update(workspaceId, input) {
52
+ const existing = this.get(workspaceId);
53
+ if (!existing) {
54
+ throw new Error(`Workspace not found: ${workspaceId}`);
55
+ }
56
+ return this.upsert({
57
+ workspaceId,
58
+ displayName: input.displayName || existing.displayName,
59
+ path: input.path || existing.path,
60
+ deviceId: existing.deviceId,
61
+ defaultRuntimeId: input.defaultRuntimeId === null ? undefined : input.defaultRuntimeId || existing.defaultRuntimeId,
62
+ git: existing.git,
63
+ health: existing.health,
64
+ metadata: input.metadata || existing.metadata,
65
+ });
66
+ }
67
+ delete(workspaceId) {
68
+ this.db.prepare('DELETE FROM workspace_registry WHERE id = ?').run(workspaceId);
69
+ return { deleted: true };
70
+ }
71
+ touch(workspaceId) {
72
+ this.db.prepare('UPDATE workspace_registry SET last_opened_at = ?, updated_at = ? WHERE id = ?')
73
+ .run(new Date().toISOString(), new Date().toISOString(), workspaceId);
74
+ }
75
+ toEntry(row) {
76
+ const activeTaskCount = Number(this.db.prepare(`
77
+ SELECT COUNT(*) AS total
78
+ FROM agent_tasks
79
+ WHERE workspace_id = ? AND status IN ('created', 'queued', 'running', 'waiting_for_user')
80
+ `).get(row.id)?.total || 0);
81
+ const recentTaskRows = this.db.prepare(`
82
+ SELECT id
83
+ FROM agent_tasks
84
+ WHERE workspace_id = ?
85
+ ORDER BY updated_at DESC
86
+ LIMIT 8
87
+ `).all(row.id);
88
+ return {
89
+ workspaceId: row.id,
90
+ displayName: row.display_name,
91
+ path: row.path,
92
+ deviceId: row.device_id,
93
+ createdAt: row.created_at,
94
+ updatedAt: row.updated_at,
95
+ lastOpenedAt: row.last_opened_at || undefined,
96
+ defaultRuntimeId: row.default_runtime_id || undefined,
97
+ git: (0, utils_js_1.parseJson)(row.git_json, { isRepo: false }),
98
+ health: (0, utils_js_1.parseJson)(row.health_json, {
99
+ status: 'unknown',
100
+ summary: 'Workspace health has not been checked.',
101
+ issues: [],
102
+ }),
103
+ activeTaskCount,
104
+ recentTaskIds: recentTaskRows.map((item) => item.id),
105
+ metadata: (0, utils_js_1.parseJson)(row.metadata_json, {}),
106
+ };
107
+ }
108
+ }
109
+ exports.LocalWorkspaceRegistryStore = LocalWorkspaceRegistryStore;
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AutomationConversationExecutor = void 0;
4
+ exports.renderMonitorPrompt = renderMonitorPrompt;
5
+ const scheduled_bridge_session_js_1 = require("../scheduler/scheduled-bridge-session.js");
6
+ const scheduled_job_route_js_1 = require("../scheduler/scheduled-job-route.js");
7
+ const TERMINAL_RUN_STATES = new Set(['completed', 'failed', 'interrupted']);
8
+ const MONITOR_RUN_PERMISSION_MODE = 'bypassPermissions';
9
+ class AutomationConversationExecutor {
10
+ options;
11
+ constructor(options) {
12
+ this.options = options;
13
+ }
14
+ async execute(monitor, event, timeoutMs = 15 * 60 * 1000) {
15
+ const workspaceRouter = this.options.getWorkspaceRouter();
16
+ const threadId = await this.resolveThread(monitor);
17
+ const prompt = renderMonitorPrompt(monitor.promptTemplate, event, monitor);
18
+ const channelRuntime = monitor.platform === 'local' ? undefined : this.options.getChannelRuntime(monitor.platform);
19
+ const bridge = channelRuntime
20
+ ? await scheduled_bridge_session_js_1.ScheduledBridgeSession.open({
21
+ target: {
22
+ id: monitor.id,
23
+ workspaceId: monitor.workspaceId,
24
+ platform: monitor.platform,
25
+ route: monitor.route,
26
+ title: monitor.title,
27
+ promptTemplate: monitor.promptTemplate,
28
+ },
29
+ threadId,
30
+ workspaceRouter,
31
+ getChannelRuntime: () => channelRuntime,
32
+ noticeIcon: monitor.sourceType === 'stock.quote' ? '📈' : '🔔',
33
+ noticeTitle: monitor.title,
34
+ })
35
+ : undefined;
36
+ try {
37
+ const sendResult = await workspaceRouter.sendThreadMessage(threadId, prompt, {
38
+ permissionMode: MONITOR_RUN_PERMISSION_MODE,
39
+ runtimeEnv: this.buildRuntimeEnv(monitor),
40
+ });
41
+ await this.waitForRun(sendResult.runId, timeoutMs);
42
+ const thread = await workspaceRouter.getThread(threadId);
43
+ const replyText = [...thread.messages]
44
+ .reverse()
45
+ .find((message) => message.role === 'assistant' && message.kind === 'final')
46
+ ?.content;
47
+ return {
48
+ threadId,
49
+ runId: sendResult.runId,
50
+ replyText,
51
+ deliveryMode: bridge ? 'bridge-stream' : 'thread-only',
52
+ deliveryStatus: 'succeeded',
53
+ lastBridgeEventAt: bridge ? new Date().toISOString() : undefined,
54
+ };
55
+ }
56
+ finally {
57
+ await bridge?.close();
58
+ }
59
+ }
60
+ async resolveThread(monitor) {
61
+ const workspaceRouter = this.options.getWorkspaceRouter();
62
+ if (monitor.executionMode === 'same-thread') {
63
+ const binding = this.options.store.getPlatformThreadBinding(monitor.workspaceId, monitor.route.channelId, monitor.route.participantId || '', monitor.platform);
64
+ if (binding?.thread_id && await this.threadExists(binding.thread_id)) {
65
+ return binding.thread_id;
66
+ }
67
+ if (monitor.route.threadId && await this.threadExists(monitor.route.threadId)) {
68
+ return monitor.route.threadId;
69
+ }
70
+ }
71
+ const title = monitor.platform === 'local'
72
+ ? `[Monitor] ${monitor.title}`
73
+ : `[Monitor:${(0, scheduled_job_route_js_1.getChannelPlatformBase)(monitor.platform) || monitor.platform}] ${monitor.title}`;
74
+ const existing = (await workspaceRouter.listThreads(monitor.workspaceId))
75
+ .find((thread) => thread.title === title);
76
+ if (existing) {
77
+ return existing.id;
78
+ }
79
+ const created = await workspaceRouter.createThread(monitor.workspaceId, title);
80
+ return created.id;
81
+ }
82
+ async threadExists(threadId) {
83
+ try {
84
+ await this.options.getWorkspaceRouter().getThread(threadId);
85
+ return true;
86
+ }
87
+ catch {
88
+ return false;
89
+ }
90
+ }
91
+ buildRuntimeEnv(monitor) {
92
+ const basePlatform = (0, scheduled_job_route_js_1.getChannelPlatformBase)(monitor.platform);
93
+ const env = {};
94
+ if (basePlatform && basePlatform !== 'local') {
95
+ env.LOCAL_AI_PLATFORM = basePlatform;
96
+ env.LOCAL_AI_ROUTE_TYPE = (0, scheduled_job_route_js_1.routeTypeForPlatform)(monitor.platform);
97
+ }
98
+ const instanceId = monitor.route.instanceId || (0, scheduled_job_route_js_1.getChannelPlatformInstanceId)(monitor.platform);
99
+ if (instanceId) {
100
+ env.LOCAL_AI_PLATFORM_INSTANCE_ID = instanceId;
101
+ }
102
+ if (monitor.route.channelId) {
103
+ env.LOCAL_AI_CHAT_ID = monitor.route.channelId;
104
+ }
105
+ if (monitor.route.participantId) {
106
+ env.LOCAL_AI_PLATFORM_USER_ID = monitor.route.participantId;
107
+ }
108
+ return env;
109
+ }
110
+ async waitForRun(runId, timeoutMs) {
111
+ const startedAt = Date.now();
112
+ while (Date.now() - startedAt < timeoutMs) {
113
+ const run = this.options.store.getRun(runId);
114
+ if (run && TERMINAL_RUN_STATES.has(run.status)) {
115
+ if (run.status !== 'completed') {
116
+ throw new Error(`Monitor run finished with status ${run.status}`);
117
+ }
118
+ return run;
119
+ }
120
+ await new Promise((resolve) => setTimeout(resolve, 300));
121
+ }
122
+ throw new Error(`Timed out waiting for monitor run ${runId}`);
123
+ }
124
+ }
125
+ exports.AutomationConversationExecutor = AutomationConversationExecutor;
126
+ function renderMonitorPrompt(template, event, monitor) {
127
+ const values = {
128
+ title: monitor.title,
129
+ sourceType: event.sourceType,
130
+ subject: event.subject,
131
+ summary: event.summary || '',
132
+ timestamp: event.occurredAt,
133
+ ...event.payload,
134
+ };
135
+ return String(template || '').replace(/\{\{\s*([a-zA-Z0-9_.-]+)\s*\}\}/g, (_match, key) => String(values[key] ?? ''));
136
+ }
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AutomationMonitorRepository = void 0;
4
+ class AutomationMonitorRepository {
5
+ store;
6
+ constructor(store) {
7
+ this.store = store;
8
+ }
9
+ list(workspaceId) {
10
+ return this.store.listAutomationMonitors(workspaceId);
11
+ }
12
+ get(monitorId) {
13
+ return this.store.getAutomationMonitor(monitorId);
14
+ }
15
+ create(input) {
16
+ return this.store.createAutomationMonitor(input);
17
+ }
18
+ update(monitorId, input) {
19
+ return this.store.updateAutomationMonitor(monitorId, input);
20
+ }
21
+ updateState(monitorId, input) {
22
+ return this.store.updateAutomationMonitorState(monitorId, input);
23
+ }
24
+ delete(monitorId) {
25
+ return this.store.deleteAutomationMonitor(monitorId);
26
+ }
27
+ listRuns(monitorId) {
28
+ return this.store.listAutomationMonitorRuns(monitorId);
29
+ }
30
+ createRun(monitorId, status, input = {}) {
31
+ return this.store.createAutomationMonitorRun(monitorId, status, input);
32
+ }
33
+ updateRun(runId, input) {
34
+ return this.store.updateAutomationMonitorRun(runId, input);
35
+ }
36
+ getPlatformThreadBindingByThreadId(threadId) {
37
+ return this.store.getPlatformThreadBindingByThreadId(threadId);
38
+ }
39
+ toScheduledLike(monitor) {
40
+ return {
41
+ id: monitor.id,
42
+ workspaceId: monitor.workspaceId,
43
+ platform: monitor.platform,
44
+ route: monitor.route,
45
+ executionMode: monitor.executionMode,
46
+ triggerType: 'once',
47
+ promptTemplate: monitor.promptTemplate,
48
+ description: monitor.title,
49
+ enabled: monitor.enabled,
50
+ concurrencyPolicy: monitor.concurrencyPolicy,
51
+ createdAt: monitor.createdAt,
52
+ updatedAt: monitor.updatedAt,
53
+ };
54
+ }
55
+ }
56
+ exports.AutomationMonitorRepository = AutomationMonitorRepository;