@kafca/agentdock 0.1.42 → 0.1.44
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.
- package/README.md +10 -0
- package/dist/renderer/assets/{Badge-D-WU4kUV.js → Badge-Qk9qHovH.js} +1 -1
- package/dist/renderer/assets/{Chat-BGkC5tAe.js → Chat-BK-fm0Xr.js} +1 -1
- package/dist/renderer/assets/{ChatMarkdown-CfbC1jRd.js → ChatMarkdown-BKdW8OON.js} +1 -1
- package/dist/renderer/assets/{Config-qQb4bX5D.js → Config-B93CQGvY.js} +2 -2
- package/dist/renderer/assets/CronList-Z3TvSRKP.js +1 -0
- package/dist/renderer/assets/{Dashboard-xn6cUy_n.js → Dashboard-Ch3QkWwf.js} +2 -2
- package/dist/renderer/assets/{EmptyState-BdKBBUpr.js → EmptyState-kD9yAwtw.js} +1 -1
- package/dist/renderer/assets/{KnowledgeDetail-Duk8IQP3.js → KnowledgeDetail-BAMCLrjz.js} +2 -2
- package/dist/renderer/assets/{KnowledgeHome-BfjX_4Sv.js → KnowledgeHome-ChvjOfrc.js} +2 -2
- package/dist/renderer/assets/{Logs-Bfq61QMn.js → Logs-Cv0nth3j.js} +1 -1
- package/dist/renderer/assets/{Modal-B3vlBmBr.js → Modal-DwY4lecS.js} +1 -1
- package/dist/renderer/assets/MonitorList-JEvMoWUm.js +1 -0
- package/dist/renderer/assets/{Page-CPsLOP3z.js → Page-CnB9ePsb.js} +1 -1
- package/dist/renderer/assets/{ProjectDetail-D-g46wyF.js → ProjectDetail-DJa3sMmU.js} +2 -2
- package/dist/renderer/assets/{ProjectList-BrQEKDQ8.js → ProjectList-D6CXumR_.js} +1 -1
- package/dist/renderer/assets/{Select-C4CFMQmF.js → Select-zfoksLGB.js} +1 -1
- package/dist/renderer/assets/SessionChat-DUTh4WoM.js +1 -0
- package/dist/renderer/assets/{SessionList-DPWIUbOg.js → SessionList-D9o-lUst.js} +1 -1
- package/dist/renderer/assets/{ThreadChat-BjtU-j9q.js → ThreadChat-BYXlT-Kc.js} +7 -7
- package/dist/renderer/assets/{Workspace-BcNmHuJx.js → Workspace-BrhSwRQ-.js} +1 -1
- package/dist/renderer/assets/{arrow-left-DPzSmidS.js → arrow-left-CNEAuElg.js} +1 -1
- package/dist/renderer/assets/{book-open-B0xhoRqZ.js → book-open-BNJMhNI-.js} +1 -1
- package/dist/renderer/assets/{check-BTJTyd0C.js → check-BnclClRU.js} +1 -1
- package/dist/renderer/assets/{chevron-down-B6jJXlhi.js → chevron-down-Bh53e0O-.js} +1 -1
- package/dist/renderer/assets/{circle-qRhJR9qR.js → circle-ClZTWCWO.js} +1 -1
- package/dist/renderer/assets/desktop-C5vBT0yM.js +1 -0
- package/dist/renderer/assets/desktop-C6q6wBae.js +5 -0
- package/dist/renderer/assets/en-D2SkCrhG.js +1 -0
- package/dist/renderer/assets/{funnel-CbYKGTn8.js → funnel-_5hsz0xI.js} +1 -1
- package/dist/renderer/assets/{heart-DjwWJfkz.js → heart-u4Q1aOqj.js} +1 -1
- package/dist/renderer/assets/{index-BWmHJRhe.js → index-B36eowj-.js} +39 -34
- package/dist/renderer/assets/{index-CyZs_2NJ.js → index-BNFx4uYv.js} +3 -3
- package/dist/renderer/assets/{pencil-1dfAivmj.js → pencil-DLh9QNmT.js} +1 -1
- package/dist/renderer/assets/{play-CB3w1G6S.js → play-BDTk9Scm.js} +1 -1
- package/dist/renderer/assets/{plug-Bvep5o3r.js → plug-BG0JHW6B.js} +1 -1
- package/dist/renderer/assets/{plus-DJVg9m09.js → plus-BSc8POsz.js} +1 -1
- package/dist/renderer/assets/projects-DwfZwxDW.js +1 -0
- package/dist/renderer/assets/{save-xjJn3qf2.js → save-D5AO_G6a.js} +1 -1
- package/dist/renderer/assets/{search-BK3UrQxM.js → search-CniPk7Ey.js} +1 -1
- package/dist/renderer/assets/{server-Dyd2eXJu.js → server-GsXyQAZm.js} +1 -1
- package/dist/renderer/assets/{session-utils-eXC0020s.js → session-utils-BDxzgTBC.js} +1 -1
- package/dist/renderer/assets/{sessions-WLYpkyUt.js → sessions-CLcKA1Tt.js} +1 -1
- package/dist/renderer/assets/{shield-check-C0N6aWzF.js → shield-check-4i0E3hmf.js} +1 -1
- package/dist/renderer/assets/{trash-2-BGMTNJA6.js → trash-2-DhtOCsO5.js} +1 -1
- package/dist/renderer/assets/{user-BcGMLyhu.js → user-BtC_pVXV.js} +1 -1
- package/dist/renderer/assets/{wifi-off-FhcQx0HK.js → wifi-off-BHPzPY_B.js} +1 -1
- package/dist/renderer/assets/zh-DIcdHycM.js +1 -0
- package/dist/renderer/index.html +1 -1
- package/dist-electron/packages/contracts/src/local-core.js +28 -0
- package/dist-electron/packages/core-sdk/src/index.js +32 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +51 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-store.js +4 -1364
- package/dist-electron/services/local-ai-core/src/acp/store/agent-task-store.js +166 -0
- package/dist-electron/services/local-ai-core/src/acp/store/automation-monitor-store.js +231 -0
- package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +263 -0
- package/dist-electron/services/local-ai-core/src/acp/store/platform-store.js +186 -0
- package/dist-electron/services/local-ai-core/src/acp/store/scheduler-store.js +201 -0
- package/dist-electron/services/local-ai-core/src/acp/store/schema.js +275 -0
- package/dist-electron/services/local-ai-core/src/acp/store/security-store.js +266 -0
- package/dist-electron/services/local-ai-core/src/acp/store/thread-store.js +232 -0
- package/dist-electron/services/local-ai-core/src/acp/store/utils.js +47 -0
- package/dist-electron/services/local-ai-core/src/acp/store/workspace-registry-store.js +109 -0
- package/dist-electron/services/local-ai-core/src/automation/automation-conversation-executor.js +136 -0
- package/dist-electron/services/local-ai-core/src/automation/automation-monitor-repository.js +56 -0
- package/dist-electron/services/local-ai-core/src/automation/automation-monitor-service.js +359 -0
- package/dist-electron/services/local-ai-core/src/automation/condition-evaluator.js +77 -0
- package/dist-electron/services/local-ai-core/src/automation/mock-stock-provider.js +40 -0
- package/dist-electron/services/local-ai-core/src/automation/monitor-id.js +10 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/cards.js +55 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/config.js +2 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/inbound.js +114 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +153 -94
- package/dist-electron/services/local-ai-core/src/channel/shared/session-command-runtime.js +53 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/thread-routing.js +34 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +63 -51
- package/dist-electron/services/local-ai-core/src/cli/lac.js +196 -0
- package/dist-electron/services/local-ai-core/src/cli/monitor-cli-parsers.js +37 -0
- package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +43 -0
- package/dist-electron/services/local-ai-core/src/kernel/capability-registry.js +12 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/monitor-stock-plugin.js +30 -0
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +41 -0
- package/dist-electron/services/local-ai-core/src/runtime/server-routes.js +31 -0
- package/dist-electron/services/local-ai-core/src/runtime/server.js +36 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-bridge-session.js +25 -11
- package/dist-electron/services/local-ai-core/src/thread/session-command-service.js +275 -0
- package/dist-electron/services/local-ai-core/src/thread/slash-command-registry.js +27 -0
- package/dist-electron/services/local-ai-core/src/thread/thread-command-service.js +15 -15
- package/dist-electron/shared/desktop.js +21 -1
- package/dist-electron/tests/contracts/local-core-contracts.test.js +9 -0
- package/dist-electron/tests/electron/automation-monitor.test.js +38 -0
- package/dist-electron/tests/electron/lac-cli.test.js +146 -0
- package/dist-electron/tests/integration/channel-gateways.test.js +32 -0
- package/dist-electron/tests/integration/lark-gateway.test.js +1918 -0
- package/dist-electron/tests/integration/local-core-acp-progress.test.js +1772 -0
- package/dist-electron/tests/integration/local-core-refactor.test.js +216 -4566
- package/dist-electron/tests/integration/local-core-routes.test.js +204 -0
- package/dist-electron/tests/integration/weixin-gateway.test.js +927 -0
- package/package.json +1 -1
- package/dist/renderer/assets/CronList-CKhggzYk.js +0 -1
- package/dist/renderer/assets/SessionChat-06Jny5_G.js +0 -1
- package/dist/renderer/assets/desktop-DXmXjjUR.js +0 -1
- package/dist/renderer/assets/desktop-O8_6ZCVZ.js +0 -4
- package/dist/renderer/assets/en-CKhCF6St.js +0 -1
- package/dist/renderer/assets/projects-xnW0fTtq.js +0 -1
- package/dist/renderer/assets/zh-Dz5FLTBV.js +0 -1
|
@@ -1,1366 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LocalCoreAcpStore = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const node_sqlite_1 = require("node:sqlite");
|
|
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");
|
|
11
|
-
const desktop_js_1 = require("../../../../shared/desktop.js");
|
|
12
|
-
const workspace_thread_mappers_js_1 = require("../thread/workspace-thread-mappers.js");
|
|
13
|
-
const workspace_thread_id_js_1 = require("../thread/workspace-thread-id.js");
|
|
14
|
-
class LocalCoreAcpStore {
|
|
15
|
-
db;
|
|
16
|
-
constructor(userDataPath) {
|
|
17
|
-
const dbPath = (0, node_path_1.join)(userDataPath, 'runtime', 'local-core.db');
|
|
18
|
-
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(dbPath), { recursive: true });
|
|
19
|
-
this.db = new node_sqlite_1.DatabaseSync(dbPath);
|
|
20
|
-
this.db.exec(`
|
|
21
|
-
PRAGMA foreign_keys = ON;
|
|
22
|
-
CREATE TABLE IF NOT EXISTS threads (
|
|
23
|
-
id TEXT PRIMARY KEY,
|
|
24
|
-
workspace_id TEXT NOT NULL,
|
|
25
|
-
session_id TEXT NOT NULL,
|
|
26
|
-
bridge_session_key TEXT NOT NULL,
|
|
27
|
-
title TEXT NOT NULL,
|
|
28
|
-
agent_type TEXT NOT NULL,
|
|
29
|
-
created_at TEXT NOT NULL,
|
|
30
|
-
updated_at TEXT NOT NULL,
|
|
31
|
-
history_count INTEGER NOT NULL DEFAULT 0,
|
|
32
|
-
excerpt TEXT NOT NULL DEFAULT '',
|
|
33
|
-
acp_session_id TEXT,
|
|
34
|
-
acp_supports_load INTEGER NOT NULL DEFAULT 0,
|
|
35
|
-
agent_mode TEXT NOT NULL DEFAULT 'default'
|
|
36
|
-
);
|
|
37
|
-
CREATE INDEX IF NOT EXISTS idx_threads_workspace_updated ON threads (workspace_id, updated_at DESC);
|
|
38
|
-
CREATE TABLE IF NOT EXISTS messages (
|
|
39
|
-
id TEXT PRIMARY KEY,
|
|
40
|
-
thread_id TEXT NOT NULL,
|
|
41
|
-
role TEXT NOT NULL,
|
|
42
|
-
content TEXT NOT NULL,
|
|
43
|
-
tool_call_json TEXT,
|
|
44
|
-
bridge_kind TEXT,
|
|
45
|
-
bridge_status TEXT,
|
|
46
|
-
timestamp TEXT NOT NULL,
|
|
47
|
-
kind TEXT NOT NULL,
|
|
48
|
-
seq INTEGER NOT NULL,
|
|
49
|
-
FOREIGN KEY (thread_id) REFERENCES threads(id) ON DELETE CASCADE
|
|
50
|
-
);
|
|
51
|
-
CREATE INDEX IF NOT EXISTS idx_messages_thread_seq ON messages (thread_id, seq ASC);
|
|
52
|
-
CREATE TABLE IF NOT EXISTS runs (
|
|
53
|
-
id TEXT PRIMARY KEY,
|
|
54
|
-
thread_id TEXT NOT NULL,
|
|
55
|
-
status TEXT NOT NULL,
|
|
56
|
-
started_at TEXT NOT NULL,
|
|
57
|
-
updated_at TEXT NOT NULL,
|
|
58
|
-
FOREIGN KEY (thread_id) REFERENCES threads(id) ON DELETE CASCADE
|
|
59
|
-
);
|
|
60
|
-
CREATE INDEX IF NOT EXISTS idx_runs_thread_updated ON runs (thread_id, updated_at DESC);
|
|
61
|
-
CREATE TABLE IF NOT EXISTS platform_pairings (
|
|
62
|
-
code TEXT PRIMARY KEY,
|
|
63
|
-
workspace_id TEXT NOT NULL,
|
|
64
|
-
platform TEXT NOT NULL,
|
|
65
|
-
platform_user_id TEXT NOT NULL,
|
|
66
|
-
chat_id TEXT NOT NULL,
|
|
67
|
-
display_name TEXT NOT NULL,
|
|
68
|
-
requested_at TEXT NOT NULL,
|
|
69
|
-
expires_at TEXT NOT NULL,
|
|
70
|
-
status TEXT NOT NULL
|
|
71
|
-
);
|
|
72
|
-
CREATE INDEX IF NOT EXISTS idx_platform_pairings_workspace_status ON platform_pairings (workspace_id, status, expires_at DESC);
|
|
73
|
-
CREATE TABLE IF NOT EXISTS platform_users (
|
|
74
|
-
id TEXT PRIMARY KEY,
|
|
75
|
-
workspace_id TEXT NOT NULL,
|
|
76
|
-
platform TEXT NOT NULL,
|
|
77
|
-
platform_user_id TEXT NOT NULL,
|
|
78
|
-
chat_id TEXT NOT NULL,
|
|
79
|
-
display_name TEXT NOT NULL,
|
|
80
|
-
thread_id TEXT,
|
|
81
|
-
authorized_at TEXT NOT NULL,
|
|
82
|
-
UNIQUE(workspace_id, platform, platform_user_id)
|
|
83
|
-
);
|
|
84
|
-
CREATE INDEX IF NOT EXISTS idx_platform_users_workspace_platform ON platform_users (workspace_id, platform);
|
|
85
|
-
CREATE TABLE IF NOT EXISTS platform_thread_bindings (
|
|
86
|
-
workspace_id TEXT NOT NULL,
|
|
87
|
-
platform TEXT NOT NULL,
|
|
88
|
-
chat_id TEXT NOT NULL,
|
|
89
|
-
platform_user_id TEXT NOT NULL,
|
|
90
|
-
thread_id TEXT NOT NULL,
|
|
91
|
-
last_platform_message_id TEXT,
|
|
92
|
-
created_at TEXT NOT NULL,
|
|
93
|
-
updated_at TEXT NOT NULL,
|
|
94
|
-
PRIMARY KEY (workspace_id, platform, chat_id, platform_user_id)
|
|
95
|
-
);
|
|
96
|
-
CREATE INDEX IF NOT EXISTS idx_platform_thread_bindings_thread ON platform_thread_bindings (thread_id);
|
|
97
|
-
CREATE TABLE IF NOT EXISTS scheduled_jobs (
|
|
98
|
-
id TEXT PRIMARY KEY,
|
|
99
|
-
workspace_id TEXT NOT NULL,
|
|
100
|
-
platform TEXT NOT NULL,
|
|
101
|
-
route_type TEXT NOT NULL,
|
|
102
|
-
route_config TEXT NOT NULL,
|
|
103
|
-
execution_mode TEXT NOT NULL DEFAULT 'same-thread',
|
|
104
|
-
trigger_type TEXT NOT NULL,
|
|
105
|
-
cron_expr TEXT,
|
|
106
|
-
run_at TEXT,
|
|
107
|
-
prompt_template TEXT NOT NULL,
|
|
108
|
-
description TEXT NOT NULL DEFAULT '',
|
|
109
|
-
enabled INTEGER NOT NULL DEFAULT 1,
|
|
110
|
-
concurrency_policy TEXT NOT NULL DEFAULT 'skip_if_running',
|
|
111
|
-
created_at TEXT NOT NULL,
|
|
112
|
-
updated_at TEXT NOT NULL,
|
|
113
|
-
last_run_at TEXT,
|
|
114
|
-
last_status TEXT,
|
|
115
|
-
last_error TEXT
|
|
116
|
-
);
|
|
117
|
-
CREATE INDEX IF NOT EXISTS idx_scheduled_jobs_workspace_updated ON scheduled_jobs (workspace_id, updated_at DESC);
|
|
118
|
-
CREATE INDEX IF NOT EXISTS idx_scheduled_jobs_enabled ON scheduled_jobs (enabled, trigger_type, run_at);
|
|
119
|
-
CREATE TABLE IF NOT EXISTS scheduled_job_runs (
|
|
120
|
-
id TEXT PRIMARY KEY,
|
|
121
|
-
job_id TEXT NOT NULL,
|
|
122
|
-
status TEXT NOT NULL,
|
|
123
|
-
triggered_at TEXT NOT NULL,
|
|
124
|
-
started_at TEXT,
|
|
125
|
-
finished_at TEXT,
|
|
126
|
-
error TEXT,
|
|
127
|
-
thread_id TEXT,
|
|
128
|
-
run_id TEXT,
|
|
129
|
-
platform_message_id TEXT,
|
|
130
|
-
platform_message_ids_json TEXT,
|
|
131
|
-
delivery_mode TEXT,
|
|
132
|
-
delivery_status TEXT,
|
|
133
|
-
delivery_error TEXT,
|
|
134
|
-
last_bridge_event_at TEXT,
|
|
135
|
-
FOREIGN KEY (job_id) REFERENCES scheduled_jobs(id) ON DELETE CASCADE
|
|
136
|
-
);
|
|
137
|
-
CREATE INDEX IF NOT EXISTS idx_scheduled_job_runs_job_triggered ON scheduled_job_runs (job_id, triggered_at DESC);
|
|
138
|
-
CREATE TABLE IF NOT EXISTS workspace_registry (
|
|
139
|
-
id TEXT PRIMARY KEY,
|
|
140
|
-
display_name TEXT NOT NULL,
|
|
141
|
-
path TEXT NOT NULL,
|
|
142
|
-
device_id TEXT NOT NULL,
|
|
143
|
-
default_runtime_id TEXT,
|
|
144
|
-
git_json TEXT NOT NULL DEFAULT '{}',
|
|
145
|
-
health_json TEXT NOT NULL DEFAULT '{}',
|
|
146
|
-
metadata_json TEXT NOT NULL DEFAULT '{}',
|
|
147
|
-
created_at TEXT NOT NULL,
|
|
148
|
-
updated_at TEXT NOT NULL,
|
|
149
|
-
last_opened_at TEXT
|
|
150
|
-
);
|
|
151
|
-
CREATE INDEX IF NOT EXISTS idx_workspace_registry_updated ON workspace_registry (updated_at DESC);
|
|
152
|
-
CREATE TABLE IF NOT EXISTS agent_tasks (
|
|
153
|
-
id TEXT PRIMARY KEY,
|
|
154
|
-
workspace_id TEXT NOT NULL,
|
|
155
|
-
device_id TEXT NOT NULL,
|
|
156
|
-
runtime_id TEXT NOT NULL,
|
|
157
|
-
thread_id TEXT,
|
|
158
|
-
run_id TEXT,
|
|
159
|
-
title TEXT NOT NULL,
|
|
160
|
-
prompt TEXT,
|
|
161
|
-
status TEXT NOT NULL,
|
|
162
|
-
created_at TEXT NOT NULL,
|
|
163
|
-
updated_at TEXT NOT NULL,
|
|
164
|
-
queued_at TEXT,
|
|
165
|
-
started_at TEXT,
|
|
166
|
-
completed_at TEXT,
|
|
167
|
-
summary TEXT,
|
|
168
|
-
error TEXT,
|
|
169
|
-
timeline_json TEXT NOT NULL DEFAULT '[]',
|
|
170
|
-
logs_json TEXT NOT NULL DEFAULT '[]',
|
|
171
|
-
artifacts_json TEXT NOT NULL DEFAULT '[]',
|
|
172
|
-
approval_ids_json TEXT NOT NULL DEFAULT '[]',
|
|
173
|
-
metadata_json TEXT NOT NULL DEFAULT '{}'
|
|
174
|
-
);
|
|
175
|
-
CREATE INDEX IF NOT EXISTS idx_agent_tasks_workspace_updated ON agent_tasks (workspace_id, updated_at DESC);
|
|
176
|
-
CREATE INDEX IF NOT EXISTS idx_agent_tasks_status_updated ON agent_tasks (status, updated_at DESC);
|
|
177
|
-
CREATE INDEX IF NOT EXISTS idx_agent_tasks_run ON agent_tasks (run_id);
|
|
178
|
-
CREATE TABLE IF NOT EXISTS workspace_security_settings (
|
|
179
|
-
workspace_id TEXT PRIMARY KEY,
|
|
180
|
-
permissions_json TEXT NOT NULL,
|
|
181
|
-
allow_paths_json TEXT NOT NULL DEFAULT '[]',
|
|
182
|
-
deny_paths_json TEXT NOT NULL DEFAULT '[]',
|
|
183
|
-
updated_at TEXT NOT NULL,
|
|
184
|
-
updated_by TEXT
|
|
185
|
-
);
|
|
186
|
-
CREATE TABLE IF NOT EXISTS approval_requests (
|
|
187
|
-
id TEXT PRIMARY KEY,
|
|
188
|
-
workspace_id TEXT NOT NULL,
|
|
189
|
-
task_id TEXT,
|
|
190
|
-
thread_id TEXT,
|
|
191
|
-
run_id TEXT,
|
|
192
|
-
device_id TEXT NOT NULL,
|
|
193
|
-
kind TEXT NOT NULL,
|
|
194
|
-
status TEXT NOT NULL,
|
|
195
|
-
risk_level TEXT NOT NULL,
|
|
196
|
-
title TEXT NOT NULL,
|
|
197
|
-
description TEXT NOT NULL,
|
|
198
|
-
requested_action TEXT NOT NULL,
|
|
199
|
-
command TEXT,
|
|
200
|
-
scopes_json TEXT NOT NULL DEFAULT '[]',
|
|
201
|
-
options_json TEXT NOT NULL DEFAULT '[]',
|
|
202
|
-
requested_by TEXT,
|
|
203
|
-
resolved_by TEXT,
|
|
204
|
-
resolution TEXT,
|
|
205
|
-
created_at TEXT NOT NULL,
|
|
206
|
-
updated_at TEXT NOT NULL,
|
|
207
|
-
resolved_at TEXT,
|
|
208
|
-
expires_at TEXT,
|
|
209
|
-
metadata_json TEXT NOT NULL DEFAULT '{}'
|
|
210
|
-
);
|
|
211
|
-
CREATE INDEX IF NOT EXISTS idx_approval_requests_workspace_updated ON approval_requests (workspace_id, updated_at DESC);
|
|
212
|
-
CREATE INDEX IF NOT EXISTS idx_approval_requests_status_updated ON approval_requests (status, updated_at DESC);
|
|
213
|
-
CREATE INDEX IF NOT EXISTS idx_approval_requests_task ON approval_requests (task_id);
|
|
214
|
-
CREATE INDEX IF NOT EXISTS idx_approval_requests_run ON approval_requests (run_id);
|
|
215
|
-
CREATE TABLE IF NOT EXISTS audit_events (
|
|
216
|
-
id TEXT PRIMARY KEY,
|
|
217
|
-
type TEXT NOT NULL,
|
|
218
|
-
workspace_id TEXT,
|
|
219
|
-
task_id TEXT,
|
|
220
|
-
approval_id TEXT,
|
|
221
|
-
actor TEXT,
|
|
222
|
-
summary TEXT NOT NULL,
|
|
223
|
-
risk_level TEXT,
|
|
224
|
-
created_at TEXT NOT NULL,
|
|
225
|
-
metadata_json TEXT NOT NULL DEFAULT '{}'
|
|
226
|
-
);
|
|
227
|
-
CREATE INDEX IF NOT EXISTS idx_audit_events_workspace_created ON audit_events (workspace_id, created_at DESC);
|
|
228
|
-
CREATE INDEX IF NOT EXISTS idx_audit_events_task_created ON audit_events (task_id, created_at DESC);
|
|
229
|
-
CREATE INDEX IF NOT EXISTS idx_audit_events_type_created ON audit_events (type, created_at DESC);
|
|
230
|
-
`);
|
|
231
|
-
this.ensureColumn('messages', 'tool_call_json', 'TEXT');
|
|
232
|
-
this.ensureColumn('messages', 'bridge_kind', 'TEXT');
|
|
233
|
-
this.ensureColumn('messages', 'bridge_status', 'TEXT');
|
|
234
|
-
this.ensureColumn('scheduled_jobs', 'execution_mode', "TEXT NOT NULL DEFAULT 'same-thread'");
|
|
235
|
-
this.ensureColumn('scheduled_job_runs', 'platform_message_ids_json', 'TEXT');
|
|
236
|
-
this.ensureColumn('scheduled_job_runs', 'delivery_mode', 'TEXT');
|
|
237
|
-
this.ensureColumn('scheduled_job_runs', 'delivery_status', 'TEXT');
|
|
238
|
-
this.ensureColumn('scheduled_job_runs', 'delivery_error', 'TEXT');
|
|
239
|
-
this.ensureColumn('scheduled_job_runs', 'last_bridge_event_at', 'TEXT');
|
|
240
|
-
this.ensureColumn('threads', 'agent_mode', "TEXT NOT NULL DEFAULT 'default'");
|
|
241
|
-
}
|
|
242
|
-
close() {
|
|
243
|
-
this.db.close();
|
|
244
|
-
}
|
|
245
|
-
listThreadSummaries(workspaceId) {
|
|
246
|
-
const rows = this.db.prepare(`
|
|
247
|
-
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
|
|
248
|
-
FROM threads
|
|
249
|
-
WHERE workspace_id = ?
|
|
250
|
-
ORDER BY updated_at DESC
|
|
251
|
-
`).all(workspaceId);
|
|
252
|
-
return rows.map((row) => ({
|
|
253
|
-
id: row.id,
|
|
254
|
-
workspaceId: row.workspace_id,
|
|
255
|
-
title: row.title,
|
|
256
|
-
live: false,
|
|
257
|
-
updatedAt: row.updated_at,
|
|
258
|
-
createdAt: row.created_at,
|
|
259
|
-
historyCount: row.history_count,
|
|
260
|
-
excerpt: row.excerpt,
|
|
261
|
-
runId: undefined,
|
|
262
|
-
bridgeSessionKey: row.bridge_session_key,
|
|
263
|
-
agentType: row.agent_type,
|
|
264
|
-
}));
|
|
265
|
-
}
|
|
266
|
-
countThreads(workspaceId) {
|
|
267
|
-
const row = this.db.prepare('SELECT COUNT(*) AS total FROM threads WHERE workspace_id = ?').get(workspaceId);
|
|
268
|
-
return Number(row?.total || 0);
|
|
269
|
-
}
|
|
270
|
-
createThread(workspaceId, title, agentType = desktop_js_1.LOCALCORE_ACP_AGENT_TYPE, agentMode = 'default') {
|
|
271
|
-
const sessionId = (0, node_crypto_1.randomUUID)();
|
|
272
|
-
const threadId = (0, workspace_thread_id_js_1.encodeThreadId)(workspaceId, sessionId);
|
|
273
|
-
const now = new Date().toISOString();
|
|
274
|
-
const bridgeSessionKey = `${desktop_js_1.LOCALCORE_ACP_AGENT_TYPE}:${workspaceId}:${sessionId}`;
|
|
275
|
-
this.db.prepare(`
|
|
276
|
-
INSERT INTO threads (id, workspace_id, session_id, bridge_session_key, title, agent_type, created_at, updated_at, history_count, excerpt, agent_mode)
|
|
277
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0, '', ?)
|
|
278
|
-
`).run(threadId, workspaceId, sessionId, bridgeSessionKey, title, agentType, now, now, agentMode || 'default');
|
|
279
|
-
return {
|
|
280
|
-
id: threadId,
|
|
281
|
-
workspaceId,
|
|
282
|
-
title,
|
|
283
|
-
live: false,
|
|
284
|
-
updatedAt: now,
|
|
285
|
-
createdAt: now,
|
|
286
|
-
historyCount: 0,
|
|
287
|
-
excerpt: '',
|
|
288
|
-
bridgeSessionKey,
|
|
289
|
-
agentType,
|
|
290
|
-
messages: [],
|
|
291
|
-
selectedKnowledgeBaseIds: [],
|
|
292
|
-
pendingPermissionRequest: null,
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
getThread(threadId, selectedKnowledgeBaseIds) {
|
|
296
|
-
const row = this.getThreadRow(threadId);
|
|
297
|
-
if (!row) {
|
|
298
|
-
throw new Error(`Thread not found: ${threadId}`);
|
|
299
|
-
}
|
|
300
|
-
const messages = this.db.prepare(`
|
|
301
|
-
SELECT id, thread_id, role, content, tool_call_json, bridge_kind, bridge_status, timestamp, kind, seq
|
|
302
|
-
FROM messages
|
|
303
|
-
WHERE thread_id = ?
|
|
304
|
-
ORDER BY seq ASC
|
|
305
|
-
`).all(threadId);
|
|
306
|
-
return {
|
|
307
|
-
id: row.id,
|
|
308
|
-
workspaceId: row.workspace_id,
|
|
309
|
-
title: row.title,
|
|
310
|
-
live: false,
|
|
311
|
-
updatedAt: row.updated_at,
|
|
312
|
-
createdAt: row.created_at,
|
|
313
|
-
historyCount: row.history_count,
|
|
314
|
-
excerpt: row.excerpt,
|
|
315
|
-
bridgeSessionKey: row.bridge_session_key,
|
|
316
|
-
agentType: row.agent_type,
|
|
317
|
-
messages: messages.map((message) => ({
|
|
318
|
-
id: message.id,
|
|
319
|
-
role: message.role,
|
|
320
|
-
content: message.content,
|
|
321
|
-
toolCall: parseJson(message.tool_call_json || 'null', null) || undefined,
|
|
322
|
-
bridgeKind: normalizeBridgeKind(message.bridge_kind),
|
|
323
|
-
bridgeStatus: normalizeBridgeStatus(message.bridge_status),
|
|
324
|
-
timestamp: message.timestamp,
|
|
325
|
-
kind: message.kind,
|
|
326
|
-
})),
|
|
327
|
-
selectedKnowledgeBaseIds,
|
|
328
|
-
pendingPermissionRequest: null,
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
renameThread(threadId, title) {
|
|
332
|
-
const now = new Date().toISOString();
|
|
333
|
-
this.db.prepare('UPDATE threads SET title = ?, updated_at = ? WHERE id = ?').run(title, now, threadId);
|
|
334
|
-
}
|
|
335
|
-
deleteThread(threadId) {
|
|
336
|
-
this.db.prepare('DELETE FROM threads WHERE id = ?').run(threadId);
|
|
337
|
-
}
|
|
338
|
-
appendMessage(threadId, role, content, kind, toolCall, bridgeKind, bridgeStatus) {
|
|
339
|
-
const timestamp = new Date().toISOString();
|
|
340
|
-
const nextSequenceRow = this.db.prepare('SELECT COALESCE(MAX(seq), -1) + 1 AS next_seq FROM messages WHERE thread_id = ?').get(threadId);
|
|
341
|
-
const nextSeq = Number(nextSequenceRow?.next_seq || 0);
|
|
342
|
-
const id = `${timestamp}-${role}-${nextSeq}`;
|
|
343
|
-
const excerpt = (0, workspace_thread_mappers_js_1.normalizeMessageContent)(content);
|
|
344
|
-
this.db.exec('BEGIN IMMEDIATE');
|
|
345
|
-
try {
|
|
346
|
-
this.db.prepare(`
|
|
347
|
-
INSERT INTO messages (id, thread_id, role, content, tool_call_json, bridge_kind, bridge_status, timestamp, kind, seq)
|
|
348
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
349
|
-
`).run(id, threadId, role, content, toolCall ? JSON.stringify(toolCall) : null, bridgeKind || null, bridgeStatus || null, timestamp, kind, nextSeq);
|
|
350
|
-
this.db.prepare(`
|
|
351
|
-
UPDATE threads
|
|
352
|
-
SET updated_at = ?, history_count = history_count + 1, excerpt = ?
|
|
353
|
-
WHERE id = ?
|
|
354
|
-
`).run(timestamp, excerpt, threadId);
|
|
355
|
-
this.db.exec('COMMIT');
|
|
356
|
-
}
|
|
357
|
-
catch (error) {
|
|
358
|
-
this.db.exec('ROLLBACK');
|
|
359
|
-
throw error;
|
|
360
|
-
}
|
|
361
|
-
return { id, timestamp };
|
|
362
|
-
}
|
|
363
|
-
upsertMessage(threadId, id, role, content, kind, toolCall, bridgeKind, bridgeStatus) {
|
|
364
|
-
const timestamp = new Date().toISOString();
|
|
365
|
-
const excerpt = (0, workspace_thread_mappers_js_1.normalizeMessageContent)(content);
|
|
366
|
-
const existing = this.db.prepare('SELECT id FROM messages WHERE id = ? AND thread_id = ?').get(id, threadId);
|
|
367
|
-
this.db.exec('BEGIN IMMEDIATE');
|
|
368
|
-
try {
|
|
369
|
-
if (existing) {
|
|
370
|
-
this.db.prepare(`
|
|
371
|
-
UPDATE messages
|
|
372
|
-
SET content = ?, tool_call_json = ?, bridge_kind = ?, bridge_status = ?, timestamp = ?, kind = ?
|
|
373
|
-
WHERE id = ? AND thread_id = ?
|
|
374
|
-
`).run(content, toolCall ? JSON.stringify(toolCall) : null, bridgeKind || null, bridgeStatus || null, timestamp, kind, id, threadId);
|
|
375
|
-
}
|
|
376
|
-
else {
|
|
377
|
-
const nextSequenceRow = this.db.prepare('SELECT COALESCE(MAX(seq), -1) + 1 AS next_seq FROM messages WHERE thread_id = ?').get(threadId);
|
|
378
|
-
const nextSeq = Number(nextSequenceRow?.next_seq || 0);
|
|
379
|
-
this.db.prepare(`
|
|
380
|
-
INSERT INTO messages (id, thread_id, role, content, tool_call_json, bridge_kind, bridge_status, timestamp, kind, seq)
|
|
381
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
382
|
-
`).run(id, threadId, role, content, toolCall ? JSON.stringify(toolCall) : null, bridgeKind || null, bridgeStatus || null, timestamp, kind, nextSeq);
|
|
383
|
-
this.db.prepare(`
|
|
384
|
-
UPDATE threads
|
|
385
|
-
SET history_count = history_count + 1
|
|
386
|
-
WHERE id = ?
|
|
387
|
-
`).run(threadId);
|
|
388
|
-
}
|
|
389
|
-
this.db.prepare(`
|
|
390
|
-
UPDATE threads
|
|
391
|
-
SET updated_at = ?, excerpt = ?
|
|
392
|
-
WHERE id = ?
|
|
393
|
-
`).run(timestamp, excerpt, threadId);
|
|
394
|
-
this.db.exec('COMMIT');
|
|
395
|
-
}
|
|
396
|
-
catch (error) {
|
|
397
|
-
this.db.exec('ROLLBACK');
|
|
398
|
-
throw error;
|
|
399
|
-
}
|
|
400
|
-
return { id, timestamp };
|
|
401
|
-
}
|
|
402
|
-
updateRun(runId, threadId, status) {
|
|
403
|
-
const now = new Date().toISOString();
|
|
404
|
-
const normalizedStatus = (0, index_js_1.normalizeRunStatus)(status);
|
|
405
|
-
const existing = this.db.prepare('SELECT id FROM runs WHERE id = ?').get(runId);
|
|
406
|
-
if (existing) {
|
|
407
|
-
this.db.prepare('UPDATE runs SET status = ?, updated_at = ? WHERE id = ?').run(normalizedStatus, now, runId);
|
|
408
|
-
return;
|
|
409
|
-
}
|
|
410
|
-
this.db.prepare(`
|
|
411
|
-
INSERT INTO runs (id, thread_id, status, started_at, updated_at)
|
|
412
|
-
VALUES (?, ?, ?, ?, ?)
|
|
413
|
-
`).run(runId, threadId, normalizedStatus, now, now);
|
|
414
|
-
}
|
|
415
|
-
getLatestRunForThread(threadId) {
|
|
416
|
-
const row = this.db.prepare(`
|
|
417
|
-
SELECT id, thread_id, status, started_at, updated_at
|
|
418
|
-
FROM runs
|
|
419
|
-
WHERE thread_id = ?
|
|
420
|
-
ORDER BY updated_at DESC
|
|
421
|
-
LIMIT 1
|
|
422
|
-
`).get(threadId);
|
|
423
|
-
return row ? { ...row, status: (0, index_js_1.normalizeRunStatus)(row.status) } : undefined;
|
|
424
|
-
}
|
|
425
|
-
getRun(runId) {
|
|
426
|
-
const row = this.db.prepare(`
|
|
427
|
-
SELECT id, thread_id, status, started_at, updated_at
|
|
428
|
-
FROM runs
|
|
429
|
-
WHERE id = ?
|
|
430
|
-
`).get(runId);
|
|
431
|
-
return row ? { ...row, status: (0, index_js_1.normalizeRunStatus)(row.status) } : undefined;
|
|
432
|
-
}
|
|
433
|
-
listWorkspaceRegistry() {
|
|
434
|
-
const rows = this.db.prepare(`
|
|
435
|
-
SELECT id, display_name, path, device_id, default_runtime_id, git_json, health_json, metadata_json, created_at, updated_at, last_opened_at
|
|
436
|
-
FROM workspace_registry
|
|
437
|
-
ORDER BY display_name ASC
|
|
438
|
-
`).all();
|
|
439
|
-
return rows.map((row) => this.toWorkspaceRegistryEntry(row));
|
|
440
|
-
}
|
|
441
|
-
getWorkspaceRegistryEntry(workspaceId) {
|
|
442
|
-
const row = this.db.prepare(`
|
|
443
|
-
SELECT id, display_name, path, device_id, default_runtime_id, git_json, health_json, metadata_json, created_at, updated_at, last_opened_at
|
|
444
|
-
FROM workspace_registry
|
|
445
|
-
WHERE id = ?
|
|
446
|
-
`).get(workspaceId);
|
|
447
|
-
return row ? this.toWorkspaceRegistryEntry(row) : undefined;
|
|
448
|
-
}
|
|
449
|
-
upsertWorkspaceRegistryEntry(input) {
|
|
450
|
-
const id = input.workspaceId || input.displayName;
|
|
451
|
-
const now = new Date().toISOString();
|
|
452
|
-
const existing = this.getWorkspaceRegistryEntry(id);
|
|
453
|
-
const health = input.health || existing?.health || {
|
|
454
|
-
status: 'unknown',
|
|
455
|
-
summary: 'Workspace health has not been checked.',
|
|
456
|
-
issues: [],
|
|
457
|
-
};
|
|
458
|
-
this.db.prepare(`
|
|
459
|
-
INSERT INTO workspace_registry (
|
|
460
|
-
id, display_name, path, device_id, default_runtime_id, git_json, health_json, metadata_json, created_at, updated_at, last_opened_at
|
|
461
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
462
|
-
ON CONFLICT(id) DO UPDATE SET
|
|
463
|
-
display_name = excluded.display_name,
|
|
464
|
-
path = excluded.path,
|
|
465
|
-
device_id = excluded.device_id,
|
|
466
|
-
default_runtime_id = excluded.default_runtime_id,
|
|
467
|
-
git_json = excluded.git_json,
|
|
468
|
-
health_json = excluded.health_json,
|
|
469
|
-
metadata_json = excluded.metadata_json,
|
|
470
|
-
updated_at = excluded.updated_at
|
|
471
|
-
`).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);
|
|
472
|
-
return this.getWorkspaceRegistryEntry(id);
|
|
473
|
-
}
|
|
474
|
-
updateWorkspaceRegistryEntry(workspaceId, input) {
|
|
475
|
-
const existing = this.getWorkspaceRegistryEntry(workspaceId);
|
|
476
|
-
if (!existing) {
|
|
477
|
-
throw new Error(`Workspace not found: ${workspaceId}`);
|
|
478
|
-
}
|
|
479
|
-
return this.upsertWorkspaceRegistryEntry({
|
|
480
|
-
workspaceId,
|
|
481
|
-
displayName: input.displayName || existing.displayName,
|
|
482
|
-
path: input.path || existing.path,
|
|
483
|
-
deviceId: existing.deviceId,
|
|
484
|
-
defaultRuntimeId: input.defaultRuntimeId === null ? undefined : input.defaultRuntimeId || existing.defaultRuntimeId,
|
|
485
|
-
git: existing.git,
|
|
486
|
-
health: existing.health,
|
|
487
|
-
metadata: input.metadata || existing.metadata,
|
|
488
|
-
});
|
|
489
|
-
}
|
|
490
|
-
deleteWorkspaceRegistryEntry(workspaceId) {
|
|
491
|
-
this.db.prepare('DELETE FROM workspace_registry WHERE id = ?').run(workspaceId);
|
|
492
|
-
return { deleted: true };
|
|
493
|
-
}
|
|
494
|
-
touchWorkspaceRegistryEntry(workspaceId) {
|
|
495
|
-
this.db.prepare('UPDATE workspace_registry SET last_opened_at = ?, updated_at = ? WHERE id = ?')
|
|
496
|
-
.run(new Date().toISOString(), new Date().toISOString(), workspaceId);
|
|
497
|
-
}
|
|
498
|
-
getWorkspaceSecuritySettings(workspaceId) {
|
|
499
|
-
const row = this.db.prepare(`
|
|
500
|
-
SELECT workspace_id, permissions_json, allow_paths_json, deny_paths_json, updated_at, updated_by
|
|
501
|
-
FROM workspace_security_settings
|
|
502
|
-
WHERE workspace_id = ?
|
|
503
|
-
`).get(workspaceId);
|
|
504
|
-
if (row) {
|
|
505
|
-
return this.toWorkspaceSecuritySettings(row);
|
|
506
|
-
}
|
|
507
|
-
const now = new Date().toISOString();
|
|
508
|
-
return {
|
|
509
|
-
workspaceId,
|
|
510
|
-
permissions: defaultPermissions(),
|
|
511
|
-
allowPaths: [],
|
|
512
|
-
denyPaths: [],
|
|
513
|
-
updatedAt: now,
|
|
514
|
-
};
|
|
515
|
-
}
|
|
516
|
-
updateWorkspaceSecuritySettings(workspaceId, input) {
|
|
517
|
-
const existing = this.getWorkspaceSecuritySettings(workspaceId);
|
|
518
|
-
const now = new Date().toISOString();
|
|
519
|
-
const next = {
|
|
520
|
-
workspaceId,
|
|
521
|
-
permissions: {
|
|
522
|
-
...existing.permissions,
|
|
523
|
-
...(input.permissions || {}),
|
|
524
|
-
},
|
|
525
|
-
allowPaths: Array.isArray(input.allowPaths) ? input.allowPaths : existing.allowPaths,
|
|
526
|
-
denyPaths: Array.isArray(input.denyPaths) ? input.denyPaths : existing.denyPaths,
|
|
527
|
-
updatedAt: now,
|
|
528
|
-
updatedBy: input.updatedBy || existing.updatedBy,
|
|
529
|
-
};
|
|
530
|
-
this.db.prepare(`
|
|
531
|
-
INSERT INTO workspace_security_settings (workspace_id, permissions_json, allow_paths_json, deny_paths_json, updated_at, updated_by)
|
|
532
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
533
|
-
ON CONFLICT(workspace_id) DO UPDATE SET
|
|
534
|
-
permissions_json = excluded.permissions_json,
|
|
535
|
-
allow_paths_json = excluded.allow_paths_json,
|
|
536
|
-
deny_paths_json = excluded.deny_paths_json,
|
|
537
|
-
updated_at = excluded.updated_at,
|
|
538
|
-
updated_by = excluded.updated_by
|
|
539
|
-
`).run(workspaceId, JSON.stringify(next.permissions), JSON.stringify(next.allowPaths), JSON.stringify(next.denyPaths), now, next.updatedBy || null);
|
|
540
|
-
this.createAuditEvent({
|
|
541
|
-
type: 'permission.changed',
|
|
542
|
-
workspaceId,
|
|
543
|
-
actor: next.updatedBy || 'local',
|
|
544
|
-
summary: 'Workspace security settings changed.',
|
|
545
|
-
metadata: {
|
|
546
|
-
permissions: next.permissions,
|
|
547
|
-
allowPaths: next.allowPaths,
|
|
548
|
-
denyPaths: next.denyPaths,
|
|
549
|
-
},
|
|
550
|
-
});
|
|
551
|
-
return this.getWorkspaceSecuritySettings(workspaceId);
|
|
552
|
-
}
|
|
553
|
-
createApprovalRequest(input) {
|
|
554
|
-
const id = `approval:${(0, node_crypto_1.randomUUID)()}`;
|
|
555
|
-
const now = new Date().toISOString();
|
|
556
|
-
this.db.prepare(`
|
|
557
|
-
INSERT INTO approval_requests (
|
|
558
|
-
id, workspace_id, task_id, thread_id, run_id, device_id, kind, status, risk_level, title, description,
|
|
559
|
-
requested_action, command, scopes_json, options_json, requested_by, created_at, updated_at, expires_at, metadata_json
|
|
560
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, 'pending', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
561
|
-
`).run(id, input.workspaceId, input.taskId || null, input.threadId || null, input.runId || null, input.deviceId || 'local', input.kind, input.riskLevel, input.title, redactSecrets(input.description), redactSecrets(input.requestedAction), input.command ? redactSecrets(input.command) : null, JSON.stringify(input.scopes || []), JSON.stringify(input.options || []), input.requestedBy || null, now, now, input.expiresAt || null, JSON.stringify(input.metadata || {}));
|
|
562
|
-
const approval = this.getApprovalRequest(id);
|
|
563
|
-
this.createAuditEvent({
|
|
564
|
-
type: 'approval.requested',
|
|
565
|
-
workspaceId: approval.workspaceId,
|
|
566
|
-
taskId: approval.taskId,
|
|
567
|
-
approvalId: approval.approvalId,
|
|
568
|
-
actor: approval.requestedBy || 'agent',
|
|
569
|
-
summary: approval.title,
|
|
570
|
-
riskLevel: approval.riskLevel,
|
|
571
|
-
metadata: {
|
|
572
|
-
kind: approval.kind,
|
|
573
|
-
requestedAction: approval.requestedAction,
|
|
574
|
-
scopes: approval.scopes,
|
|
575
|
-
},
|
|
576
|
-
});
|
|
577
|
-
if (approval.taskId) {
|
|
578
|
-
this.updateAgentTask(approval.taskId, {
|
|
579
|
-
approvalId: approval.approvalId,
|
|
580
|
-
timelineItem: {
|
|
581
|
-
type: 'approval_requested',
|
|
582
|
-
title: approval.title,
|
|
583
|
-
description: approval.description,
|
|
584
|
-
metadata: { approvalId: approval.approvalId, riskLevel: approval.riskLevel },
|
|
585
|
-
},
|
|
586
|
-
});
|
|
587
|
-
}
|
|
588
|
-
return approval;
|
|
589
|
-
}
|
|
590
|
-
listApprovalRequests(query = {}) {
|
|
591
|
-
const predicates = [];
|
|
592
|
-
const params = [];
|
|
593
|
-
if (query.workspaceId) {
|
|
594
|
-
predicates.push('workspace_id = ?');
|
|
595
|
-
params.push(query.workspaceId);
|
|
596
|
-
}
|
|
597
|
-
if (query.taskId) {
|
|
598
|
-
predicates.push('task_id = ?');
|
|
599
|
-
params.push(query.taskId);
|
|
600
|
-
}
|
|
601
|
-
if (query.status) {
|
|
602
|
-
const statuses = (Array.isArray(query.status) ? query.status : [query.status]).map((status) => (0, index_js_1.normalizeApprovalRequestStatus)(status));
|
|
603
|
-
predicates.push(`status IN (${statuses.map(() => '?').join(', ')})`);
|
|
604
|
-
params.push(...statuses);
|
|
605
|
-
}
|
|
606
|
-
const limit = Math.max(1, Math.min(Number(query.limit || 50), 100));
|
|
607
|
-
const where = predicates.length ? `WHERE ${predicates.join(' AND ')}` : '';
|
|
608
|
-
const rows = this.db.prepare(`
|
|
609
|
-
SELECT *
|
|
610
|
-
FROM approval_requests
|
|
611
|
-
${where}
|
|
612
|
-
ORDER BY updated_at DESC
|
|
613
|
-
LIMIT ?
|
|
614
|
-
`).all(...params, limit);
|
|
615
|
-
return { approvals: rows.map((row) => this.toApprovalRequest(row)) };
|
|
616
|
-
}
|
|
617
|
-
getApprovalRequest(approvalId) {
|
|
618
|
-
const row = this.db.prepare('SELECT * FROM approval_requests WHERE id = ?').get(approvalId);
|
|
619
|
-
return row ? this.toApprovalRequest(row) : undefined;
|
|
620
|
-
}
|
|
621
|
-
resolveApprovalRequest(approvalId, input) {
|
|
622
|
-
const existing = this.getApprovalRequest(approvalId);
|
|
623
|
-
if (!existing) {
|
|
624
|
-
throw new Error(`Approval not found: ${approvalId}`);
|
|
625
|
-
}
|
|
626
|
-
const now = new Date().toISOString();
|
|
627
|
-
this.db.prepare(`
|
|
628
|
-
UPDATE approval_requests
|
|
629
|
-
SET status = ?, resolved_by = ?, resolution = ?, resolved_at = ?, updated_at = ?
|
|
630
|
-
WHERE id = ?
|
|
631
|
-
`).run(input.status, input.resolvedBy || existing.resolvedBy || 'local', input.resolution || existing.resolution || null, now, now, approvalId);
|
|
632
|
-
const approval = this.getApprovalRequest(approvalId);
|
|
633
|
-
this.createAuditEvent({
|
|
634
|
-
type: input.status === 'rejected' ? 'approval.rejected' : 'approval.resolved',
|
|
635
|
-
workspaceId: approval.workspaceId,
|
|
636
|
-
taskId: approval.taskId,
|
|
637
|
-
approvalId: approval.approvalId,
|
|
638
|
-
actor: approval.resolvedBy || 'local',
|
|
639
|
-
summary: `Approval ${input.status}: ${approval.title}`,
|
|
640
|
-
riskLevel: approval.riskLevel,
|
|
641
|
-
metadata: { resolution: approval.resolution },
|
|
642
|
-
});
|
|
643
|
-
if (approval.taskId) {
|
|
644
|
-
this.updateAgentTask(approval.taskId, {
|
|
645
|
-
timelineItem: {
|
|
646
|
-
type: 'approval_resolved',
|
|
647
|
-
title: `Approval ${input.status}`,
|
|
648
|
-
description: approval.resolution || approval.title,
|
|
649
|
-
metadata: { approvalId: approval.approvalId, status: input.status },
|
|
650
|
-
},
|
|
651
|
-
});
|
|
652
|
-
}
|
|
653
|
-
return approval;
|
|
654
|
-
}
|
|
655
|
-
createAuditEvent(input) {
|
|
656
|
-
const id = `audit:${(0, node_crypto_1.randomUUID)()}`;
|
|
657
|
-
const now = new Date().toISOString();
|
|
658
|
-
this.db.prepare(`
|
|
659
|
-
INSERT INTO audit_events (id, type, workspace_id, task_id, approval_id, actor, summary, risk_level, created_at, metadata_json)
|
|
660
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
661
|
-
`).run(id, input.type, input.workspaceId || null, input.taskId || null, input.approvalId || null, input.actor || null, redactSecrets(input.summary), input.riskLevel || null, now, JSON.stringify(input.metadata || {}));
|
|
662
|
-
return this.toAuditEvent(this.db.prepare('SELECT * FROM audit_events WHERE id = ?').get(id));
|
|
663
|
-
}
|
|
664
|
-
listAuditEvents(query = {}) {
|
|
665
|
-
const predicates = [];
|
|
666
|
-
const params = [];
|
|
667
|
-
if (query.workspaceId) {
|
|
668
|
-
predicates.push('workspace_id = ?');
|
|
669
|
-
params.push(query.workspaceId);
|
|
670
|
-
}
|
|
671
|
-
if (query.taskId) {
|
|
672
|
-
predicates.push('task_id = ?');
|
|
673
|
-
params.push(query.taskId);
|
|
674
|
-
}
|
|
675
|
-
if (query.approvalId) {
|
|
676
|
-
predicates.push('approval_id = ?');
|
|
677
|
-
params.push(query.approvalId);
|
|
678
|
-
}
|
|
679
|
-
if (query.type) {
|
|
680
|
-
const types = Array.isArray(query.type) ? query.type : [query.type];
|
|
681
|
-
predicates.push(`type IN (${types.map(() => '?').join(', ')})`);
|
|
682
|
-
params.push(...types);
|
|
683
|
-
}
|
|
684
|
-
const limit = Math.max(1, Math.min(Number(query.limit || 50), 100));
|
|
685
|
-
const where = predicates.length ? `WHERE ${predicates.join(' AND ')}` : '';
|
|
686
|
-
const rows = this.db.prepare(`
|
|
687
|
-
SELECT *
|
|
688
|
-
FROM audit_events
|
|
689
|
-
${where}
|
|
690
|
-
ORDER BY created_at DESC
|
|
691
|
-
LIMIT ?
|
|
692
|
-
`).all(...params, limit);
|
|
693
|
-
return { events: rows.map((row) => this.toAuditEvent(row)) };
|
|
694
|
-
}
|
|
695
|
-
createAgentTask(input) {
|
|
696
|
-
const id = `task:${(0, node_crypto_1.randomUUID)()}`;
|
|
697
|
-
const now = new Date().toISOString();
|
|
698
|
-
const status = (0, index_js_1.normalizeAgentTaskStatus)(input.status);
|
|
699
|
-
const timeline = [{
|
|
700
|
-
id: `timeline:${(0, node_crypto_1.randomUUID)()}`,
|
|
701
|
-
type: 'status_change',
|
|
702
|
-
title: `Task ${status}`,
|
|
703
|
-
status,
|
|
704
|
-
timestamp: now,
|
|
705
|
-
}];
|
|
706
|
-
this.db.prepare(`
|
|
707
|
-
INSERT INTO agent_tasks (
|
|
708
|
-
id, workspace_id, device_id, runtime_id, thread_id, run_id, title, prompt, status, created_at, updated_at, queued_at,
|
|
709
|
-
started_at, completed_at, summary, error, timeline_json, logs_json, artifacts_json, approval_ids_json, metadata_json
|
|
710
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, NULL, ?, '[]', '[]', '[]', ?)
|
|
711
|
-
`).run(id, input.workspaceId, input.deviceId, input.runtimeId, input.threadId || null, input.runId || null, input.title, input.prompt ? redactSecrets(input.prompt) : null, status, now, now, status === 'queued' ? now : null, status === 'running' ? now : null, JSON.stringify(timeline), JSON.stringify(input.metadata || {}));
|
|
712
|
-
const task = this.getAgentTask(id);
|
|
713
|
-
this.createAuditEvent({
|
|
714
|
-
type: 'task.created',
|
|
715
|
-
workspaceId: task.workspaceId,
|
|
716
|
-
taskId: task.taskId,
|
|
717
|
-
actor: 'local',
|
|
718
|
-
summary: `Task created: ${task.title}`,
|
|
719
|
-
metadata: { runtimeId: task.runtimeId, threadId: task.threadId, runId: task.runId },
|
|
720
|
-
});
|
|
721
|
-
return task;
|
|
722
|
-
}
|
|
723
|
-
listAgentTasks(query = {}) {
|
|
724
|
-
const predicates = [];
|
|
725
|
-
const params = [];
|
|
726
|
-
if (query.workspaceId) {
|
|
727
|
-
predicates.push('workspace_id = ?');
|
|
728
|
-
params.push(query.workspaceId);
|
|
729
|
-
}
|
|
730
|
-
if (query.runtimeId) {
|
|
731
|
-
predicates.push('runtime_id = ?');
|
|
732
|
-
params.push(query.runtimeId);
|
|
733
|
-
}
|
|
734
|
-
if (query.status) {
|
|
735
|
-
const statuses = (Array.isArray(query.status) ? query.status : [query.status]).map((status) => (0, index_js_1.normalizeAgentTaskStatus)(status));
|
|
736
|
-
predicates.push(`status IN (${statuses.map(() => '?').join(', ')})`);
|
|
737
|
-
params.push(...statuses);
|
|
738
|
-
}
|
|
739
|
-
const limit = Math.max(1, Math.min(Number(query.limit || 50), 100));
|
|
740
|
-
const where = predicates.length ? `WHERE ${predicates.join(' AND ')}` : '';
|
|
741
|
-
const rows = this.db.prepare(`
|
|
742
|
-
SELECT *
|
|
743
|
-
FROM agent_tasks
|
|
744
|
-
${where}
|
|
745
|
-
ORDER BY updated_at DESC
|
|
746
|
-
LIMIT ?
|
|
747
|
-
`).all(...params, limit);
|
|
748
|
-
return { tasks: rows.map((row) => this.toAgentTask(row)) };
|
|
749
|
-
}
|
|
750
|
-
getAgentTask(taskId) {
|
|
751
|
-
const row = this.db.prepare('SELECT * FROM agent_tasks WHERE id = ?').get(taskId);
|
|
752
|
-
return row ? this.toAgentTask(row) : undefined;
|
|
753
|
-
}
|
|
754
|
-
getAgentTaskByRunId(runId) {
|
|
755
|
-
const row = this.db.prepare('SELECT * FROM agent_tasks WHERE run_id = ? ORDER BY updated_at DESC LIMIT 1').get(runId);
|
|
756
|
-
return row ? this.toAgentTask(row) : undefined;
|
|
757
|
-
}
|
|
758
|
-
updateAgentTask(taskId, input) {
|
|
759
|
-
const existing = this.getAgentTask(taskId);
|
|
760
|
-
if (!existing) {
|
|
761
|
-
throw new Error(`Task not found: ${taskId}`);
|
|
762
|
-
}
|
|
763
|
-
const now = new Date().toISOString();
|
|
764
|
-
const nextStatus = input.status ? (0, index_js_1.normalizeAgentTaskStatus)(input.status) : existing.status;
|
|
765
|
-
const timeline = [...existing.timeline];
|
|
766
|
-
const logs = [...existing.logs];
|
|
767
|
-
const artifacts = [...existing.artifacts];
|
|
768
|
-
const approvalIds = [...existing.approvalIds];
|
|
769
|
-
if (input.status && nextStatus !== existing.status) {
|
|
770
|
-
timeline.push({
|
|
771
|
-
id: `timeline:${(0, node_crypto_1.randomUUID)()}`,
|
|
772
|
-
type: 'status_change',
|
|
773
|
-
title: `Task ${nextStatus}`,
|
|
774
|
-
status: nextStatus,
|
|
775
|
-
timestamp: now,
|
|
776
|
-
});
|
|
777
|
-
}
|
|
778
|
-
if (input.timelineItem) {
|
|
779
|
-
timeline.push({
|
|
780
|
-
id: input.timelineItem.id || `timeline:${(0, node_crypto_1.randomUUID)()}`,
|
|
781
|
-
timestamp: input.timelineItem.timestamp || now,
|
|
782
|
-
...input.timelineItem,
|
|
783
|
-
});
|
|
784
|
-
}
|
|
785
|
-
if (input.log) {
|
|
786
|
-
logs.push({
|
|
787
|
-
id: input.log.id || `log:${(0, node_crypto_1.randomUUID)()}`,
|
|
788
|
-
timestamp: input.log.timestamp || now,
|
|
789
|
-
...input.log,
|
|
790
|
-
message: redactSecrets(input.log.message),
|
|
791
|
-
});
|
|
792
|
-
}
|
|
793
|
-
if (input.artifact) {
|
|
794
|
-
artifacts.push({
|
|
795
|
-
id: input.artifact.id || `artifact:${(0, node_crypto_1.randomUUID)()}`,
|
|
796
|
-
...input.artifact,
|
|
797
|
-
});
|
|
798
|
-
}
|
|
799
|
-
if (input.approvalId && !approvalIds.includes(input.approvalId)) {
|
|
800
|
-
approvalIds.push(input.approvalId);
|
|
801
|
-
}
|
|
802
|
-
this.db.prepare(`
|
|
803
|
-
UPDATE agent_tasks
|
|
804
|
-
SET status = ?, thread_id = ?, run_id = ?, title = ?, updated_at = ?, queued_at = ?, started_at = ?, completed_at = ?,
|
|
805
|
-
summary = ?, error = ?, timeline_json = ?, logs_json = ?, artifacts_json = ?, approval_ids_json = ?, metadata_json = ?
|
|
806
|
-
WHERE id = ?
|
|
807
|
-
`).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);
|
|
808
|
-
const task = this.getAgentTask(taskId);
|
|
809
|
-
if (input.status && nextStatus !== existing.status) {
|
|
810
|
-
this.createAuditEvent({
|
|
811
|
-
type: 'task.updated',
|
|
812
|
-
workspaceId: task.workspaceId,
|
|
813
|
-
taskId: task.taskId,
|
|
814
|
-
actor: 'local',
|
|
815
|
-
summary: `Task status changed to ${nextStatus}.`,
|
|
816
|
-
metadata: { previousStatus: existing.status, status: nextStatus, runId: task.runId },
|
|
817
|
-
});
|
|
818
|
-
}
|
|
819
|
-
return task;
|
|
820
|
-
}
|
|
821
|
-
listScheduledJobs(workspaceId) {
|
|
822
|
-
const query = workspaceId
|
|
823
|
-
? `
|
|
824
|
-
SELECT id, workspace_id, platform, route_type, route_config, trigger_type, cron_expr, run_at, prompt_template, description,
|
|
825
|
-
enabled, concurrency_policy, created_at, updated_at, last_run_at, last_status, last_error, execution_mode
|
|
826
|
-
FROM scheduled_jobs
|
|
827
|
-
WHERE workspace_id = ?
|
|
828
|
-
ORDER BY updated_at DESC
|
|
829
|
-
`
|
|
830
|
-
: `
|
|
831
|
-
SELECT id, workspace_id, platform, route_type, route_config, trigger_type, cron_expr, run_at, prompt_template, description,
|
|
832
|
-
enabled, concurrency_policy, created_at, updated_at, last_run_at, last_status, last_error, execution_mode
|
|
833
|
-
FROM scheduled_jobs
|
|
834
|
-
ORDER BY updated_at DESC
|
|
835
|
-
`;
|
|
836
|
-
const rows = this.db.prepare(query).all(...(workspaceId ? [workspaceId] : []));
|
|
837
|
-
return rows.map((row) => this.toScheduledJob(row));
|
|
838
|
-
}
|
|
839
|
-
getScheduledJob(jobId) {
|
|
840
|
-
const row = this.db.prepare(`
|
|
841
|
-
SELECT id, workspace_id, platform, route_type, route_config, trigger_type, cron_expr, run_at, prompt_template, description,
|
|
842
|
-
enabled, concurrency_policy, created_at, updated_at, last_run_at, last_status, last_error, execution_mode
|
|
843
|
-
FROM scheduled_jobs
|
|
844
|
-
WHERE id = ?
|
|
845
|
-
`).get(jobId);
|
|
846
|
-
return row ? this.toScheduledJob(row) : undefined;
|
|
847
|
-
}
|
|
848
|
-
createScheduledJob(input) {
|
|
849
|
-
if (!input.platform || !input.route) {
|
|
850
|
-
throw new Error('Scheduled job creation requires a resolved platform and route.');
|
|
851
|
-
}
|
|
852
|
-
let id = (0, job_id_js_1.createScheduledJobId)();
|
|
853
|
-
for (let attempt = 0; attempt < 5 && this.getScheduledJob(id); attempt += 1) {
|
|
854
|
-
id = (0, job_id_js_1.createScheduledJobId)();
|
|
855
|
-
}
|
|
856
|
-
if (this.getScheduledJob(id)) {
|
|
857
|
-
throw new Error('Unable to allocate a unique scheduled job id.');
|
|
858
|
-
}
|
|
859
|
-
const now = new Date().toISOString();
|
|
860
|
-
this.db.prepare(`
|
|
861
|
-
INSERT INTO scheduled_jobs (
|
|
862
|
-
id, workspace_id, platform, route_type, route_config, execution_mode, trigger_type, cron_expr, run_at,
|
|
863
|
-
prompt_template, description, enabled, concurrency_policy, created_at, updated_at
|
|
864
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'skip_if_running', ?, ?)
|
|
865
|
-
`).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);
|
|
866
|
-
return this.getScheduledJob(id);
|
|
867
|
-
}
|
|
868
|
-
updateScheduledJob(jobId, input) {
|
|
869
|
-
const existing = this.getScheduledJob(jobId);
|
|
870
|
-
if (!existing) {
|
|
871
|
-
throw new Error(`Scheduled job not found: ${jobId}`);
|
|
872
|
-
}
|
|
873
|
-
const next = {
|
|
874
|
-
...existing,
|
|
875
|
-
...(input.route ? { route: input.route } : {}),
|
|
876
|
-
...(input.executionMode ? { executionMode: (0, index_js_1.normalizeScheduledJobExecutionMode)(input.executionMode) } : {}),
|
|
877
|
-
...(input.triggerType ? { triggerType: (0, index_js_1.normalizeScheduledJobTriggerType)(input.triggerType) } : {}),
|
|
878
|
-
...(Object.prototype.hasOwnProperty.call(input, 'cronExpr') ? { cronExpr: input.cronExpr || undefined } : {}),
|
|
879
|
-
...(Object.prototype.hasOwnProperty.call(input, 'runAt') ? { runAt: input.runAt || undefined } : {}),
|
|
880
|
-
...(typeof input.promptTemplate === 'string' ? { promptTemplate: input.promptTemplate } : {}),
|
|
881
|
-
...(typeof input.description === 'string' ? { description: input.description } : {}),
|
|
882
|
-
...(typeof input.enabled === 'boolean' ? { enabled: input.enabled } : {}),
|
|
883
|
-
updatedAt: new Date().toISOString(),
|
|
884
|
-
};
|
|
885
|
-
this.db.prepare(`
|
|
886
|
-
UPDATE scheduled_jobs
|
|
887
|
-
SET route_type = ?, route_config = ?, execution_mode = ?, trigger_type = ?, cron_expr = ?, run_at = ?, prompt_template = ?,
|
|
888
|
-
description = ?, enabled = ?, updated_at = ?
|
|
889
|
-
WHERE id = ?
|
|
890
|
-
`).run(next.route.type, JSON.stringify(next.route), next.executionMode, next.triggerType, next.cronExpr || null, next.runAt || null, next.promptTemplate, next.description, next.enabled ? 1 : 0, next.updatedAt, jobId);
|
|
891
|
-
return this.getScheduledJob(jobId);
|
|
892
|
-
}
|
|
893
|
-
deleteScheduledJob(jobId) {
|
|
894
|
-
const result = this.db.prepare('DELETE FROM scheduled_jobs WHERE id = ?').run(jobId);
|
|
895
|
-
if (result.changes === 0) {
|
|
896
|
-
throw new Error(`Scheduled job not found: ${jobId}`);
|
|
897
|
-
}
|
|
898
|
-
return { deleted: true };
|
|
899
|
-
}
|
|
900
|
-
listScheduledJobRuns(jobId) {
|
|
901
|
-
const rows = this.db.prepare(`
|
|
902
|
-
SELECT id, job_id, status, triggered_at, started_at, finished_at, error, thread_id, run_id, platform_message_id, platform_message_ids_json, delivery_mode, delivery_status, delivery_error, last_bridge_event_at
|
|
903
|
-
FROM scheduled_job_runs
|
|
904
|
-
WHERE job_id = ?
|
|
905
|
-
ORDER BY triggered_at DESC
|
|
906
|
-
`).all(jobId);
|
|
907
|
-
return rows.map((row) => this.toScheduledJobRun(row));
|
|
908
|
-
}
|
|
909
|
-
createScheduledJobRun(jobId, status, input = {}) {
|
|
910
|
-
const id = `jobrun:${(0, node_crypto_1.randomUUID)()}`;
|
|
911
|
-
const triggeredAt = input.triggeredAt || new Date().toISOString();
|
|
912
|
-
const normalizedStatus = (0, index_js_1.normalizeScheduledJobRunStatus)(status);
|
|
913
|
-
this.db.prepare(`
|
|
914
|
-
INSERT INTO scheduled_job_runs (id, job_id, status, triggered_at, started_at, finished_at, error, thread_id, run_id, platform_message_id, platform_message_ids_json, delivery_mode, delivery_status, delivery_error, last_bridge_event_at)
|
|
915
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
916
|
-
`).run(id, jobId, normalizedStatus, triggeredAt, input.startedAt || null, input.finishedAt || null, input.error || null, input.threadId || null, input.runId || null, input.platformMessageId || null, JSON.stringify(input.platformMessageIds || []), input.deliveryMode || null, input.deliveryStatus || null, input.deliveryError || null, input.lastBridgeEventAt || null);
|
|
917
|
-
this.updateScheduledJobStatus(jobId, {
|
|
918
|
-
lastRunAt: triggeredAt,
|
|
919
|
-
lastStatus: normalizedStatus,
|
|
920
|
-
lastError: input.error || '',
|
|
921
|
-
});
|
|
922
|
-
return this.getScheduledJobRun(id);
|
|
923
|
-
}
|
|
924
|
-
getScheduledJobRun(runId) {
|
|
925
|
-
const row = this.db.prepare(`
|
|
926
|
-
SELECT id, job_id, status, triggered_at, started_at, finished_at, error, thread_id, run_id, platform_message_id, platform_message_ids_json, delivery_mode, delivery_status, delivery_error, last_bridge_event_at
|
|
927
|
-
FROM scheduled_job_runs
|
|
928
|
-
WHERE id = ?
|
|
929
|
-
`).get(runId);
|
|
930
|
-
return row ? this.toScheduledJobRun(row) : undefined;
|
|
931
|
-
}
|
|
932
|
-
updateScheduledJobRun(runId, input) {
|
|
933
|
-
const existing = this.getScheduledJobRun(runId);
|
|
934
|
-
if (!existing) {
|
|
935
|
-
throw new Error(`Scheduled job run not found: ${runId}`);
|
|
936
|
-
}
|
|
937
|
-
const next = {
|
|
938
|
-
...existing,
|
|
939
|
-
...input,
|
|
940
|
-
...(input.status ? { status: (0, index_js_1.normalizeScheduledJobRunStatus)(input.status) } : {}),
|
|
941
|
-
};
|
|
942
|
-
this.db.prepare(`
|
|
943
|
-
UPDATE scheduled_job_runs
|
|
944
|
-
SET status = ?, triggered_at = ?, started_at = ?, finished_at = ?, error = ?, thread_id = ?, run_id = ?, platform_message_id = ?, platform_message_ids_json = ?, delivery_mode = ?, delivery_status = ?, delivery_error = ?, last_bridge_event_at = ?
|
|
945
|
-
WHERE id = ?
|
|
946
|
-
`).run(next.status, next.triggeredAt, next.startedAt || null, next.finishedAt || null, next.error || null, next.threadId || null, next.runId || null, next.platformMessageId || null, JSON.stringify(next.platformMessageIds || []), next.deliveryMode || null, next.deliveryStatus || null, next.deliveryError || null, next.lastBridgeEventAt || null, runId);
|
|
947
|
-
if (input.status || Object.prototype.hasOwnProperty.call(input, 'error') || input.finishedAt || input.triggeredAt) {
|
|
948
|
-
this.updateScheduledJobStatus(existing.jobId, {
|
|
949
|
-
lastRunAt: next.triggeredAt,
|
|
950
|
-
lastStatus: next.status,
|
|
951
|
-
lastError: next.error || '',
|
|
952
|
-
});
|
|
953
|
-
}
|
|
954
|
-
return this.getScheduledJobRun(runId);
|
|
955
|
-
}
|
|
956
|
-
updateScheduledJobStatus(jobId, input) {
|
|
957
|
-
this.db.prepare(`
|
|
958
|
-
UPDATE scheduled_jobs
|
|
959
|
-
SET last_run_at = COALESCE(?, last_run_at),
|
|
960
|
-
last_status = COALESCE(?, last_status),
|
|
961
|
-
last_error = CASE WHEN ? IS NULL THEN last_error ELSE ? END,
|
|
962
|
-
enabled = CASE WHEN ? IS NULL THEN enabled ELSE ? END,
|
|
963
|
-
updated_at = ?
|
|
964
|
-
WHERE id = ?
|
|
965
|
-
`).run(input.lastRunAt || 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(), jobId);
|
|
966
|
-
}
|
|
967
|
-
getThreadRow(threadId) {
|
|
968
|
-
return this.db.prepare(`
|
|
969
|
-
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
|
|
970
|
-
FROM threads
|
|
971
|
-
WHERE id = ?
|
|
972
|
-
`).get(threadId);
|
|
973
|
-
}
|
|
974
|
-
updateThreadAgentMode(threadId, mode) {
|
|
975
|
-
this.db.prepare(`
|
|
976
|
-
UPDATE threads
|
|
977
|
-
SET agent_mode = ?, updated_at = ?
|
|
978
|
-
WHERE id = ?
|
|
979
|
-
`).run(mode, new Date().toISOString(), threadId);
|
|
980
|
-
}
|
|
981
|
-
updateThreadAgentType(threadId, agentType) {
|
|
982
|
-
this.db.prepare(`
|
|
983
|
-
UPDATE threads
|
|
984
|
-
SET agent_type = ?, acp_session_id = NULL, acp_supports_load = 0, updated_at = ?
|
|
985
|
-
WHERE id = ?
|
|
986
|
-
`).run(agentType, new Date().toISOString(), threadId);
|
|
987
|
-
}
|
|
988
|
-
updateThreadSession(threadId, sessionId, supportsLoad) {
|
|
989
|
-
this.db.prepare(`
|
|
990
|
-
UPDATE threads
|
|
991
|
-
SET acp_session_id = ?, acp_supports_load = ?, updated_at = COALESCE(updated_at, ?)
|
|
992
|
-
WHERE id = ?
|
|
993
|
-
`).run(sessionId, supportsLoad ? 1 : 0, new Date().toISOString(), threadId);
|
|
994
|
-
}
|
|
995
|
-
createPairingRequest(input) {
|
|
996
|
-
this.db.prepare(`
|
|
997
|
-
INSERT INTO platform_pairings (code, workspace_id, platform, platform_user_id, chat_id, display_name, requested_at, expires_at, status)
|
|
998
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
999
|
-
`).run(input.code, input.workspace_id, input.platform || 'lark', input.platform_user_id, input.chat_id, input.display_name, input.requested_at, input.expires_at, input.status);
|
|
1000
|
-
}
|
|
1001
|
-
listPendingPairings(workspaceId) {
|
|
1002
|
-
const query = workspaceId
|
|
1003
|
-
? `
|
|
1004
|
-
SELECT code, workspace_id, platform, platform_user_id, chat_id, display_name, requested_at, expires_at, status
|
|
1005
|
-
FROM platform_pairings
|
|
1006
|
-
WHERE workspace_id = ? AND status = 'pending'
|
|
1007
|
-
ORDER BY requested_at DESC
|
|
1008
|
-
`
|
|
1009
|
-
: `
|
|
1010
|
-
SELECT code, workspace_id, platform, platform_user_id, chat_id, display_name, requested_at, expires_at, status
|
|
1011
|
-
FROM platform_pairings
|
|
1012
|
-
WHERE status = 'pending'
|
|
1013
|
-
ORDER BY requested_at DESC
|
|
1014
|
-
`;
|
|
1015
|
-
return this.db.prepare(query).all(...(workspaceId ? [workspaceId] : []));
|
|
1016
|
-
}
|
|
1017
|
-
getPairingRequest(code) {
|
|
1018
|
-
return this.db.prepare(`
|
|
1019
|
-
SELECT code, workspace_id, platform, platform_user_id, chat_id, display_name, requested_at, expires_at, status
|
|
1020
|
-
FROM platform_pairings
|
|
1021
|
-
WHERE code = ?
|
|
1022
|
-
`).get(code);
|
|
1023
|
-
}
|
|
1024
|
-
updatePairingStatus(code, status) {
|
|
1025
|
-
this.db.prepare('UPDATE platform_pairings SET status = ? WHERE code = ?').run(status, code);
|
|
1026
|
-
}
|
|
1027
|
-
expirePendingPairings(nowIso = new Date().toISOString()) {
|
|
1028
|
-
this.db.prepare(`
|
|
1029
|
-
UPDATE platform_pairings
|
|
1030
|
-
SET status = 'expired'
|
|
1031
|
-
WHERE status = 'pending' AND expires_at < ?
|
|
1032
|
-
`).run(nowIso);
|
|
1033
|
-
}
|
|
1034
|
-
getAuthorizedUser(workspaceId, platformUserId, platform = 'lark') {
|
|
1035
|
-
return this.db.prepare(`
|
|
1036
|
-
SELECT id, workspace_id, platform, platform_user_id, chat_id, display_name, thread_id, authorized_at
|
|
1037
|
-
FROM platform_users
|
|
1038
|
-
WHERE workspace_id = ? AND platform = ? AND platform_user_id = ?
|
|
1039
|
-
`).get(workspaceId, platform, platformUserId);
|
|
1040
|
-
}
|
|
1041
|
-
listAuthorizedUsers(workspaceId, platform) {
|
|
1042
|
-
const params = [];
|
|
1043
|
-
const predicates = [];
|
|
1044
|
-
if (workspaceId) {
|
|
1045
|
-
predicates.push('workspace_id = ?');
|
|
1046
|
-
params.push(workspaceId);
|
|
1047
|
-
}
|
|
1048
|
-
if (platform) {
|
|
1049
|
-
predicates.push('platform = ?');
|
|
1050
|
-
params.push(platform);
|
|
1051
|
-
}
|
|
1052
|
-
const where = predicates.length > 0 ? `WHERE ${predicates.join(' AND ')}` : '';
|
|
1053
|
-
const query = `
|
|
1054
|
-
SELECT id, workspace_id, platform, platform_user_id, chat_id, display_name, thread_id, authorized_at
|
|
1055
|
-
FROM platform_users
|
|
1056
|
-
${where}
|
|
1057
|
-
ORDER BY authorized_at DESC
|
|
1058
|
-
`;
|
|
1059
|
-
const rows = this.db.prepare(query).all(...params);
|
|
1060
|
-
return rows.map((row) => ({
|
|
1061
|
-
id: row.id,
|
|
1062
|
-
workspaceId: row.workspace_id,
|
|
1063
|
-
platform: row.platform,
|
|
1064
|
-
participantId: row.platform_user_id,
|
|
1065
|
-
channelId: row.chat_id,
|
|
1066
|
-
platformUserId: row.platform_user_id,
|
|
1067
|
-
chatId: row.chat_id,
|
|
1068
|
-
displayName: row.display_name,
|
|
1069
|
-
threadId: row.thread_id || undefined,
|
|
1070
|
-
authorizedAt: row.authorized_at,
|
|
1071
|
-
}));
|
|
1072
|
-
}
|
|
1073
|
-
createAuthorizedUser(input) {
|
|
1074
|
-
this.db.prepare(`
|
|
1075
|
-
INSERT INTO platform_users (id, workspace_id, platform, platform_user_id, chat_id, display_name, thread_id, authorized_at)
|
|
1076
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
1077
|
-
ON CONFLICT(workspace_id, platform, platform_user_id) DO UPDATE SET
|
|
1078
|
-
chat_id = excluded.chat_id,
|
|
1079
|
-
display_name = excluded.display_name,
|
|
1080
|
-
thread_id = COALESCE(excluded.thread_id, platform_users.thread_id),
|
|
1081
|
-
authorized_at = excluded.authorized_at
|
|
1082
|
-
`).run(input.id, input.workspace_id, input.platform || 'lark', input.platform_user_id, input.chat_id, input.display_name, input.thread_id, input.authorized_at);
|
|
1083
|
-
}
|
|
1084
|
-
updateAuthorizedUserThread(workspaceId, platformUserId, threadId, platform = 'lark') {
|
|
1085
|
-
this.db.prepare(`
|
|
1086
|
-
UPDATE platform_users
|
|
1087
|
-
SET thread_id = ?
|
|
1088
|
-
WHERE workspace_id = ? AND platform = ? AND platform_user_id = ?
|
|
1089
|
-
`).run(threadId, workspaceId, platform, platformUserId);
|
|
1090
|
-
}
|
|
1091
|
-
getPlatformThreadBinding(workspaceId, chatId, platformUserId, platform = 'lark') {
|
|
1092
|
-
return this.db.prepare(`
|
|
1093
|
-
SELECT workspace_id, platform, chat_id, platform_user_id, thread_id, last_platform_message_id, created_at, updated_at
|
|
1094
|
-
FROM platform_thread_bindings
|
|
1095
|
-
WHERE workspace_id = ? AND platform = ? AND chat_id = ? AND platform_user_id = ?
|
|
1096
|
-
`).get(workspaceId, platform, chatId, platformUserId);
|
|
1097
|
-
}
|
|
1098
|
-
getPlatformThreadBindingByThreadId(threadId) {
|
|
1099
|
-
return this.db.prepare(`
|
|
1100
|
-
SELECT workspace_id, platform, chat_id, platform_user_id, thread_id, last_platform_message_id, created_at, updated_at
|
|
1101
|
-
FROM platform_thread_bindings
|
|
1102
|
-
WHERE thread_id = ?
|
|
1103
|
-
ORDER BY updated_at DESC
|
|
1104
|
-
LIMIT 1
|
|
1105
|
-
`).get(threadId);
|
|
1106
|
-
}
|
|
1107
|
-
upsertPlatformThreadBinding(input) {
|
|
1108
|
-
this.db.prepare(`
|
|
1109
|
-
INSERT INTO platform_thread_bindings
|
|
1110
|
-
(workspace_id, platform, chat_id, platform_user_id, thread_id, last_platform_message_id, created_at, updated_at)
|
|
1111
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
1112
|
-
ON CONFLICT(workspace_id, platform, chat_id, platform_user_id) DO UPDATE SET
|
|
1113
|
-
thread_id = excluded.thread_id,
|
|
1114
|
-
last_platform_message_id = COALESCE(excluded.last_platform_message_id, platform_thread_bindings.last_platform_message_id),
|
|
1115
|
-
updated_at = excluded.updated_at
|
|
1116
|
-
`).run(input.workspace_id, input.platform || 'lark', input.chat_id, input.platform_user_id, input.thread_id, input.last_platform_message_id, input.created_at, input.updated_at);
|
|
1117
|
-
}
|
|
1118
|
-
updatePlatformThreadMessageId(workspaceId, chatId, platformUserId, messageId, platform = 'lark') {
|
|
1119
|
-
this.db.prepare(`
|
|
1120
|
-
UPDATE platform_thread_bindings
|
|
1121
|
-
SET last_platform_message_id = ?, updated_at = ?
|
|
1122
|
-
WHERE workspace_id = ? AND platform = ? AND chat_id = ? AND platform_user_id = ?
|
|
1123
|
-
`).run(messageId, new Date().toISOString(), workspaceId, platform, chatId, platformUserId);
|
|
1124
|
-
}
|
|
1125
|
-
clearPlatformThreadMessageId(workspaceId, chatId, platformUserId, platform = 'lark') {
|
|
1126
|
-
this.db.prepare(`
|
|
1127
|
-
UPDATE platform_thread_bindings
|
|
1128
|
-
SET last_platform_message_id = NULL, updated_at = ?
|
|
1129
|
-
WHERE workspace_id = ? AND platform = ? AND chat_id = ? AND platform_user_id = ?
|
|
1130
|
-
`).run(new Date().toISOString(), workspaceId, platform, chatId, platformUserId);
|
|
1131
|
-
}
|
|
1132
|
-
listPairingRequests(workspaceId, platform) {
|
|
1133
|
-
const params = [];
|
|
1134
|
-
const predicates = [];
|
|
1135
|
-
if (workspaceId) {
|
|
1136
|
-
predicates.push('workspace_id = ?');
|
|
1137
|
-
params.push(workspaceId);
|
|
1138
|
-
}
|
|
1139
|
-
if (platform) {
|
|
1140
|
-
predicates.push('platform = ?');
|
|
1141
|
-
params.push(platform);
|
|
1142
|
-
}
|
|
1143
|
-
const where = predicates.length > 0 ? `WHERE ${predicates.join(' AND ')}` : '';
|
|
1144
|
-
const query = `
|
|
1145
|
-
SELECT code, workspace_id, platform, platform_user_id, chat_id, display_name, requested_at, expires_at, status
|
|
1146
|
-
FROM platform_pairings
|
|
1147
|
-
${where}
|
|
1148
|
-
ORDER BY requested_at DESC
|
|
1149
|
-
`;
|
|
1150
|
-
const rows = this.db.prepare(query).all(...params);
|
|
1151
|
-
return rows.map((row) => ({
|
|
1152
|
-
code: row.code,
|
|
1153
|
-
workspaceId: row.workspace_id,
|
|
1154
|
-
platform: row.platform,
|
|
1155
|
-
participantId: row.platform_user_id,
|
|
1156
|
-
channelId: row.chat_id,
|
|
1157
|
-
platformUserId: row.platform_user_id,
|
|
1158
|
-
chatId: row.chat_id,
|
|
1159
|
-
displayName: row.display_name,
|
|
1160
|
-
requestedAt: row.requested_at,
|
|
1161
|
-
expiresAt: row.expires_at,
|
|
1162
|
-
status: row.status,
|
|
1163
|
-
}));
|
|
1164
|
-
}
|
|
1165
|
-
toScheduledJob(row) {
|
|
1166
|
-
const route = JSON.parse(row.route_config);
|
|
1167
|
-
return {
|
|
1168
|
-
id: row.id,
|
|
1169
|
-
workspaceId: row.workspace_id,
|
|
1170
|
-
platform: (0, index_js_1.normalizeChannelPlatform)(row.platform),
|
|
1171
|
-
route,
|
|
1172
|
-
executionMode: (0, index_js_1.normalizeScheduledJobExecutionMode)(row.execution_mode),
|
|
1173
|
-
triggerType: (0, index_js_1.normalizeScheduledJobTriggerType)(row.trigger_type),
|
|
1174
|
-
cronExpr: row.cron_expr || undefined,
|
|
1175
|
-
runAt: row.run_at || undefined,
|
|
1176
|
-
promptTemplate: row.prompt_template,
|
|
1177
|
-
description: row.description,
|
|
1178
|
-
enabled: Boolean(row.enabled),
|
|
1179
|
-
concurrencyPolicy: row.concurrency_policy,
|
|
1180
|
-
createdAt: row.created_at,
|
|
1181
|
-
updatedAt: row.updated_at,
|
|
1182
|
-
lastRunAt: row.last_run_at || undefined,
|
|
1183
|
-
lastStatus: row.last_status ? (0, index_js_1.normalizeScheduledJobRunStatus)(row.last_status) : undefined,
|
|
1184
|
-
lastError: row.last_error || undefined,
|
|
1185
|
-
};
|
|
1186
|
-
}
|
|
1187
|
-
toScheduledJobRun(row) {
|
|
1188
|
-
return {
|
|
1189
|
-
id: row.id,
|
|
1190
|
-
jobId: row.job_id,
|
|
1191
|
-
status: (0, index_js_1.normalizeScheduledJobRunStatus)(row.status),
|
|
1192
|
-
triggeredAt: row.triggered_at,
|
|
1193
|
-
startedAt: row.started_at || undefined,
|
|
1194
|
-
finishedAt: row.finished_at || undefined,
|
|
1195
|
-
error: row.error || undefined,
|
|
1196
|
-
threadId: row.thread_id || undefined,
|
|
1197
|
-
runId: row.run_id || undefined,
|
|
1198
|
-
platformMessageId: row.platform_message_id || undefined,
|
|
1199
|
-
platformMessageIds: parseJson(row.platform_message_ids_json || '[]', []),
|
|
1200
|
-
deliveryMode: row.delivery_mode || undefined,
|
|
1201
|
-
deliveryStatus: row.delivery_status || undefined,
|
|
1202
|
-
deliveryError: row.delivery_error || undefined,
|
|
1203
|
-
lastBridgeEventAt: row.last_bridge_event_at || undefined,
|
|
1204
|
-
};
|
|
1205
|
-
}
|
|
1206
|
-
toWorkspaceRegistryEntry(row) {
|
|
1207
|
-
const activeTaskCount = Number(this.db.prepare(`
|
|
1208
|
-
SELECT COUNT(*) AS total
|
|
1209
|
-
FROM agent_tasks
|
|
1210
|
-
WHERE workspace_id = ? AND status IN ('created', 'queued', 'running', 'waiting_for_user')
|
|
1211
|
-
`).get(row.id)?.total || 0);
|
|
1212
|
-
const recentTaskRows = this.db.prepare(`
|
|
1213
|
-
SELECT id
|
|
1214
|
-
FROM agent_tasks
|
|
1215
|
-
WHERE workspace_id = ?
|
|
1216
|
-
ORDER BY updated_at DESC
|
|
1217
|
-
LIMIT 8
|
|
1218
|
-
`).all(row.id);
|
|
1219
|
-
return {
|
|
1220
|
-
workspaceId: row.id,
|
|
1221
|
-
displayName: row.display_name,
|
|
1222
|
-
path: row.path,
|
|
1223
|
-
deviceId: row.device_id,
|
|
1224
|
-
createdAt: row.created_at,
|
|
1225
|
-
updatedAt: row.updated_at,
|
|
1226
|
-
lastOpenedAt: row.last_opened_at || undefined,
|
|
1227
|
-
defaultRuntimeId: row.default_runtime_id || undefined,
|
|
1228
|
-
git: parseJson(row.git_json, { isRepo: false }),
|
|
1229
|
-
health: parseJson(row.health_json, {
|
|
1230
|
-
status: 'unknown',
|
|
1231
|
-
summary: 'Workspace health has not been checked.',
|
|
1232
|
-
issues: [],
|
|
1233
|
-
}),
|
|
1234
|
-
activeTaskCount,
|
|
1235
|
-
recentTaskIds: recentTaskRows.map((item) => item.id),
|
|
1236
|
-
metadata: parseJson(row.metadata_json, {}),
|
|
1237
|
-
};
|
|
1238
|
-
}
|
|
1239
|
-
toAgentTask(row) {
|
|
1240
|
-
return {
|
|
1241
|
-
taskId: row.id,
|
|
1242
|
-
workspaceId: row.workspace_id,
|
|
1243
|
-
deviceId: row.device_id,
|
|
1244
|
-
runtimeId: row.runtime_id,
|
|
1245
|
-
threadId: row.thread_id || undefined,
|
|
1246
|
-
runId: row.run_id || undefined,
|
|
1247
|
-
title: row.title,
|
|
1248
|
-
prompt: row.prompt || undefined,
|
|
1249
|
-
status: (0, index_js_1.normalizeAgentTaskStatus)(row.status),
|
|
1250
|
-
createdAt: row.created_at,
|
|
1251
|
-
updatedAt: row.updated_at,
|
|
1252
|
-
queuedAt: row.queued_at || undefined,
|
|
1253
|
-
startedAt: row.started_at || undefined,
|
|
1254
|
-
completedAt: row.completed_at || undefined,
|
|
1255
|
-
summary: row.summary || undefined,
|
|
1256
|
-
error: row.error || undefined,
|
|
1257
|
-
timeline: parseJson(row.timeline_json, []),
|
|
1258
|
-
logs: parseJson(row.logs_json, []),
|
|
1259
|
-
artifacts: parseJson(row.artifacts_json, []),
|
|
1260
|
-
approvalIds: parseJson(row.approval_ids_json, []),
|
|
1261
|
-
metadata: parseJson(row.metadata_json, {}),
|
|
1262
|
-
};
|
|
1263
|
-
}
|
|
1264
|
-
toWorkspaceSecuritySettings(row) {
|
|
1265
|
-
return {
|
|
1266
|
-
workspaceId: row.workspace_id,
|
|
1267
|
-
permissions: {
|
|
1268
|
-
...defaultPermissions(),
|
|
1269
|
-
...parseJson(row.permissions_json, {}),
|
|
1270
|
-
},
|
|
1271
|
-
allowPaths: parseJson(row.allow_paths_json, []),
|
|
1272
|
-
denyPaths: parseJson(row.deny_paths_json, []),
|
|
1273
|
-
updatedAt: row.updated_at,
|
|
1274
|
-
updatedBy: row.updated_by || undefined,
|
|
1275
|
-
};
|
|
1276
|
-
}
|
|
1277
|
-
toApprovalRequest(row) {
|
|
1278
|
-
return {
|
|
1279
|
-
approvalId: row.id,
|
|
1280
|
-
workspaceId: row.workspace_id,
|
|
1281
|
-
taskId: row.task_id || undefined,
|
|
1282
|
-
threadId: row.thread_id || undefined,
|
|
1283
|
-
runId: row.run_id || undefined,
|
|
1284
|
-
deviceId: row.device_id,
|
|
1285
|
-
kind: row.kind,
|
|
1286
|
-
status: (0, index_js_1.normalizeApprovalRequestStatus)(row.status),
|
|
1287
|
-
riskLevel: row.risk_level,
|
|
1288
|
-
title: row.title,
|
|
1289
|
-
description: row.description,
|
|
1290
|
-
requestedAction: row.requested_action,
|
|
1291
|
-
command: row.command || undefined,
|
|
1292
|
-
scopes: parseJson(row.scopes_json, []),
|
|
1293
|
-
options: parseJson(row.options_json, []),
|
|
1294
|
-
requestedBy: row.requested_by || undefined,
|
|
1295
|
-
resolvedBy: row.resolved_by || undefined,
|
|
1296
|
-
resolution: row.resolution || undefined,
|
|
1297
|
-
createdAt: row.created_at,
|
|
1298
|
-
updatedAt: row.updated_at,
|
|
1299
|
-
resolvedAt: row.resolved_at || undefined,
|
|
1300
|
-
expiresAt: row.expires_at || undefined,
|
|
1301
|
-
metadata: parseJson(row.metadata_json, {}),
|
|
1302
|
-
};
|
|
1303
|
-
}
|
|
1304
|
-
toAuditEvent(row) {
|
|
1305
|
-
return {
|
|
1306
|
-
auditId: row.id,
|
|
1307
|
-
type: row.type,
|
|
1308
|
-
workspaceId: row.workspace_id || undefined,
|
|
1309
|
-
taskId: row.task_id || undefined,
|
|
1310
|
-
approvalId: row.approval_id || undefined,
|
|
1311
|
-
actor: row.actor || undefined,
|
|
1312
|
-
summary: row.summary,
|
|
1313
|
-
riskLevel: row.risk_level || undefined,
|
|
1314
|
-
createdAt: row.created_at,
|
|
1315
|
-
metadata: parseJson(row.metadata_json, {}),
|
|
1316
|
-
};
|
|
1317
|
-
}
|
|
1318
|
-
ensureColumn(table, column, definition) {
|
|
1319
|
-
const rows = this.db.prepare(`PRAGMA table_info(${table})`).all();
|
|
1320
|
-
if (rows.some((row) => row.name === column)) {
|
|
1321
|
-
return;
|
|
1322
|
-
}
|
|
1323
|
-
this.db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
exports.LocalCoreAcpStore = LocalCoreAcpStore;
|
|
1327
|
-
function parseJson(value, fallback) {
|
|
1328
|
-
try {
|
|
1329
|
-
return JSON.parse(value);
|
|
1330
|
-
}
|
|
1331
|
-
catch {
|
|
1332
|
-
return fallback;
|
|
1333
|
-
}
|
|
1334
|
-
}
|
|
1335
|
-
function normalizeBridgeKind(value) {
|
|
1336
|
-
switch (value) {
|
|
1337
|
-
case 'assistant':
|
|
1338
|
-
case 'thought':
|
|
1339
|
-
case 'plan':
|
|
1340
|
-
case 'tool':
|
|
1341
|
-
case 'status':
|
|
1342
|
-
case 'permission':
|
|
1343
|
-
return value;
|
|
1344
|
-
default:
|
|
1345
|
-
return undefined;
|
|
1346
|
-
}
|
|
1347
|
-
}
|
|
1348
|
-
function normalizeBridgeStatus(value) {
|
|
1349
|
-
return value === 'awaiting_input' ? value : undefined;
|
|
1350
|
-
}
|
|
1351
|
-
function defaultPermissions() {
|
|
1352
|
-
return {
|
|
1353
|
-
'workspace.read': 'allow',
|
|
1354
|
-
'workspace.write': 'ask',
|
|
1355
|
-
'command.execute': 'ask',
|
|
1356
|
-
'network.access': 'ask',
|
|
1357
|
-
'secrets.access': 'deny',
|
|
1358
|
-
'git.modify': 'ask',
|
|
1359
|
-
};
|
|
1360
|
-
}
|
|
1361
|
-
function redactSecrets(value) {
|
|
1362
|
-
return value
|
|
1363
|
-
.replace(/\b(sk-[A-Za-z0-9_-]{12,})\b/g, '[REDACTED_SECRET]')
|
|
1364
|
-
.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]')
|
|
1365
|
-
.replace(/\b(Bearer\s+)[A-Za-z0-9._-]+/gi, '$1[REDACTED_SECRET]');
|
|
1366
|
-
}
|
|
3
|
+
exports.redactSecrets = exports.LocalCoreAcpStore = void 0;
|
|
4
|
+
var local_core_acp_store_js_1 = require("./store/local-core-acp-store.js");
|
|
5
|
+
Object.defineProperty(exports, "LocalCoreAcpStore", { enumerable: true, get: function () { return local_core_acp_store_js_1.LocalCoreAcpStore; } });
|
|
6
|
+
Object.defineProperty(exports, "redactSecrets", { enumerable: true, get: function () { return local_core_acp_store_js_1.redactSecrets; } });
|