@mcoda/db 0.1.4

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.
@@ -0,0 +1,71 @@
1
+ import { Database } from "sqlite";
2
+ import { Agent, AgentAuthMetadata, AgentAuthSecret, AgentHealth, AgentModel, AgentPromptManifest, CreateAgentInput, UpdateAgentInput, WorkspaceDefault } from "@mcoda/shared";
3
+ import { Connection } from "../../sqlite/connection.js";
4
+ export type GlobalCommandStatus = "running" | "succeeded" | "failed";
5
+ export interface GlobalCommandRunInsert {
6
+ commandName: string;
7
+ startedAt: string;
8
+ status: GlobalCommandStatus;
9
+ exitCode?: number | null;
10
+ errorSummary?: string | null;
11
+ payload?: Record<string, unknown>;
12
+ }
13
+ export interface GlobalCommandRun extends GlobalCommandRunInsert {
14
+ id: string;
15
+ completedAt?: string | null;
16
+ result?: Record<string, unknown>;
17
+ }
18
+ export interface GlobalTokenUsageInsert {
19
+ agentId?: string | null;
20
+ commandRunId?: string | null;
21
+ modelName?: string | null;
22
+ tokensPrompt?: number | null;
23
+ tokensCompletion?: number | null;
24
+ tokensTotal?: number | null;
25
+ costEstimate?: number | null;
26
+ durationSeconds?: number | null;
27
+ timestamp: string;
28
+ metadata?: Record<string, unknown>;
29
+ }
30
+ export declare class GlobalRepository {
31
+ private db;
32
+ private connection?;
33
+ constructor(db: Database, connection?: Connection | undefined);
34
+ static create(): Promise<GlobalRepository>;
35
+ close(): Promise<void>;
36
+ listAgents(): Promise<Agent[]>;
37
+ getAgentById(id: string): Promise<Agent | undefined>;
38
+ getAgentBySlug(slug: string): Promise<Agent | undefined>;
39
+ createAgent(input: CreateAgentInput): Promise<Agent>;
40
+ updateAgent(id: string, patch: UpdateAgentInput): Promise<Agent | undefined>;
41
+ deleteAgent(id: string): Promise<void>;
42
+ setAgentCapabilities(agentId: string, capabilities: string[]): Promise<void>;
43
+ getAgentCapabilities(agentId: string): Promise<string[]>;
44
+ setAgentModels(agentId: string, models: AgentModel[]): Promise<void>;
45
+ getAgentModels(agentId: string): Promise<AgentModel[]>;
46
+ setAgentPrompts(agentId: string, prompts: AgentPromptManifest): Promise<void>;
47
+ getAgentPrompts(agentId: string): Promise<AgentPromptManifest | undefined>;
48
+ setAgentAuth(agentId: string, encryptedSecret: string, lastVerifiedAt?: string): Promise<void>;
49
+ getAgentAuthMetadata(agentId: string): Promise<AgentAuthMetadata>;
50
+ getAgentAuthSecret(agentId: string): Promise<AgentAuthSecret | undefined>;
51
+ setAgentHealth(health: AgentHealth): Promise<void>;
52
+ getAgentHealth(agentId: string): Promise<AgentHealth | undefined>;
53
+ listAgentHealthSummary(): Promise<AgentHealth[]>;
54
+ setWorkspaceDefault(workspaceId: string, commandName: string, agentId: string, options?: {
55
+ qaProfile?: string;
56
+ docdexScope?: string;
57
+ }): Promise<void>;
58
+ getWorkspaceDefaults(workspaceId: string): Promise<WorkspaceDefault[]>;
59
+ removeWorkspaceDefault(workspaceId: string, commandName: string): Promise<void>;
60
+ findWorkspaceReferences(agentId: string): Promise<WorkspaceDefault[]>;
61
+ createCommandRun(record: GlobalCommandRunInsert): Promise<GlobalCommandRun>;
62
+ completeCommandRun(id: string, update: {
63
+ status: GlobalCommandStatus;
64
+ completedAt: string;
65
+ exitCode?: number | null;
66
+ errorSummary?: string | null;
67
+ result?: Record<string, unknown>;
68
+ }): Promise<void>;
69
+ recordTokenUsage(entry: GlobalTokenUsageInsert): Promise<void>;
70
+ }
71
+ //# sourceMappingURL=GlobalRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GlobalRepository.d.ts","sourceRoot":"","sources":["../../../src/repositories/global/GlobalRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EACL,KAAK,EACL,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,UAAU,EACV,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAiBxD,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;AAErE,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,gBAAiB,SAAQ,sBAAsB;IAC9D,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,qBAAa,gBAAgB;IACf,OAAO,CAAC,EAAE;IAAY,OAAO,CAAC,UAAU,CAAC;gBAAjC,EAAE,EAAE,QAAQ,EAAU,UAAU,CAAC,EAAE,UAAU,YAAA;WAEpD,MAAM,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAM1C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB,UAAU,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAO9B,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC;IAQpD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC;IAQxD,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,KAAK,CAAC;IA+BpD,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC;IAiD5E,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAItC,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAW5E,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAQxD,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAapE,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAetD,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB7E,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC;IAiB1E,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB9F,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAajE,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAezE,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBlD,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAejE,sBAAsB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAehD,mBAAmB,CACvB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GACzD,OAAO,CAAC,IAAI,CAAC;IAmBV,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAiBtE,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/E,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAiBrE,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoB3E,kBAAkB,CACtB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE;QACN,MAAM,EAAE,mBAAmB,CAAC;QAC5B,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,GACA,OAAO,CAAC,IAAI,CAAC;IAcV,gBAAgB,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;CAoBrE"}
@@ -0,0 +1,281 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { Connection } from "../../sqlite/connection.js";
3
+ import { GlobalMigrations } from "../../migrations/global/GlobalMigrations.js";
4
+ const mapAgentRow = (row) => ({
5
+ id: row.id,
6
+ slug: row.slug,
7
+ adapter: row.adapter,
8
+ defaultModel: row.default_model ?? undefined,
9
+ rating: row.rating ?? undefined,
10
+ reasoningRating: row.reasoning_rating ?? undefined,
11
+ bestUsage: row.best_usage ?? undefined,
12
+ costPerMillion: row.cost_per_million ?? undefined,
13
+ config: row.config_json ? JSON.parse(row.config_json) : undefined,
14
+ createdAt: row.created_at,
15
+ updatedAt: row.updated_at,
16
+ });
17
+ export class GlobalRepository {
18
+ constructor(db, connection) {
19
+ this.db = db;
20
+ this.connection = connection;
21
+ }
22
+ static async create() {
23
+ const connection = await Connection.openGlobal();
24
+ await GlobalMigrations.run(connection.db);
25
+ return new GlobalRepository(connection.db, connection);
26
+ }
27
+ async close() {
28
+ if (this.connection) {
29
+ await this.connection.close();
30
+ }
31
+ }
32
+ async listAgents() {
33
+ const rows = await this.db.all("SELECT id, slug, adapter, default_model, rating, reasoning_rating, best_usage, cost_per_million, config_json, created_at, updated_at FROM agents ORDER BY slug ASC");
34
+ return rows.map(mapAgentRow);
35
+ }
36
+ async getAgentById(id) {
37
+ const row = await this.db.get("SELECT id, slug, adapter, default_model, rating, reasoning_rating, best_usage, cost_per_million, config_json, created_at, updated_at FROM agents WHERE id = ?", id);
38
+ return row ? mapAgentRow(row) : undefined;
39
+ }
40
+ async getAgentBySlug(slug) {
41
+ const row = await this.db.get("SELECT id, slug, adapter, default_model, rating, reasoning_rating, best_usage, cost_per_million, config_json, created_at, updated_at FROM agents WHERE slug = ?", slug);
42
+ return row ? mapAgentRow(row) : undefined;
43
+ }
44
+ async createAgent(input) {
45
+ const now = new Date().toISOString();
46
+ const id = randomUUID();
47
+ await this.db.run(`INSERT INTO agents (id, slug, adapter, default_model, rating, reasoning_rating, best_usage, cost_per_million, config_json, created_at, updated_at)
48
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, id, input.slug, input.adapter, input.defaultModel ?? null, input.rating ?? null, input.reasoningRating ?? null, input.bestUsage ?? null, input.costPerMillion ?? null, input.config ? JSON.stringify(input.config) : null, now, now);
49
+ if (input.capabilities) {
50
+ await this.setAgentCapabilities(id, input.capabilities);
51
+ }
52
+ if (input.models) {
53
+ await this.setAgentModels(id, input.models);
54
+ }
55
+ if (input.prompts) {
56
+ await this.setAgentPrompts(id, { ...input.prompts, agentId: id });
57
+ }
58
+ return (await this.getAgentById(id));
59
+ }
60
+ async updateAgent(id, patch) {
61
+ const updates = [];
62
+ const params = [];
63
+ if (patch.adapter !== undefined) {
64
+ updates.push("adapter = ?");
65
+ params.push(patch.adapter);
66
+ }
67
+ if (patch.defaultModel !== undefined) {
68
+ updates.push("default_model = ?");
69
+ params.push(patch.defaultModel);
70
+ }
71
+ if (patch.rating !== undefined) {
72
+ updates.push("rating = ?");
73
+ params.push(patch.rating);
74
+ }
75
+ if (patch.reasoningRating !== undefined) {
76
+ updates.push("reasoning_rating = ?");
77
+ params.push(patch.reasoningRating);
78
+ }
79
+ if (patch.bestUsage !== undefined) {
80
+ updates.push("best_usage = ?");
81
+ params.push(patch.bestUsage);
82
+ }
83
+ if (patch.costPerMillion !== undefined) {
84
+ updates.push("cost_per_million = ?");
85
+ params.push(patch.costPerMillion);
86
+ }
87
+ if (patch.config !== undefined) {
88
+ updates.push("config_json = ?");
89
+ params.push(patch.config ? JSON.stringify(patch.config) : null);
90
+ }
91
+ if (updates.length > 0) {
92
+ updates.push("updated_at = ?");
93
+ params.push(new Date().toISOString());
94
+ params.push(id);
95
+ await this.db.run(`UPDATE agents SET ${updates.join(", ")} WHERE id = ?`, ...params);
96
+ }
97
+ if (patch.capabilities) {
98
+ await this.setAgentCapabilities(id, patch.capabilities);
99
+ }
100
+ if (patch.models) {
101
+ await this.setAgentModels(id, patch.models);
102
+ }
103
+ if (patch.prompts) {
104
+ await this.setAgentPrompts(id, { ...patch.prompts, agentId: id });
105
+ }
106
+ return this.getAgentById(id);
107
+ }
108
+ async deleteAgent(id) {
109
+ await this.db.run("DELETE FROM agents WHERE id = ?", id);
110
+ }
111
+ async setAgentCapabilities(agentId, capabilities) {
112
+ await this.db.run("DELETE FROM agent_capabilities WHERE agent_id = ?", agentId);
113
+ for (const capability of [...new Set(capabilities)]) {
114
+ await this.db.run("INSERT INTO agent_capabilities (agent_id, capability) VALUES (?, ?)", agentId, capability);
115
+ }
116
+ }
117
+ async getAgentCapabilities(agentId) {
118
+ const rows = await this.db.all("SELECT capability FROM agent_capabilities WHERE agent_id = ? ORDER BY capability ASC", agentId);
119
+ return rows.map((r) => r.capability);
120
+ }
121
+ async setAgentModels(agentId, models) {
122
+ await this.db.run("DELETE FROM agent_models WHERE agent_id = ?", agentId);
123
+ for (const model of models) {
124
+ await this.db.run("INSERT INTO agent_models (agent_id, model_name, is_default, config_json) VALUES (?, ?, ?, ?)", agentId, model.modelName, model.isDefault ? 1 : 0, model.config ? JSON.stringify(model.config) : null);
125
+ }
126
+ }
127
+ async getAgentModels(agentId) {
128
+ const rows = await this.db.all("SELECT agent_id, model_name, is_default, config_json FROM agent_models WHERE agent_id = ? ORDER BY model_name ASC", agentId);
129
+ return rows.map((row) => ({
130
+ agentId: row.agent_id,
131
+ modelName: row.model_name,
132
+ isDefault: Boolean(row.is_default),
133
+ config: row.config_json ? JSON.parse(row.config_json) : undefined,
134
+ }));
135
+ }
136
+ async setAgentPrompts(agentId, prompts) {
137
+ const now = new Date().toISOString();
138
+ const commandPromptsJson = prompts.commandPrompts ? JSON.stringify(prompts.commandPrompts) : null;
139
+ await this.db.run(`INSERT INTO agent_prompts (agent_id, job_prompt, character_prompt, command_prompts_json, job_path, character_path, created_at, updated_at)
140
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
141
+ ON CONFLICT(agent_id) DO UPDATE SET
142
+ job_prompt=excluded.job_prompt,
143
+ character_prompt=excluded.character_prompt,
144
+ command_prompts_json=excluded.command_prompts_json,
145
+ job_path=excluded.job_path,
146
+ character_path=excluded.character_path,
147
+ updated_at=excluded.updated_at`, agentId, prompts.jobPrompt ?? null, prompts.characterPrompt ?? null, commandPromptsJson, prompts.jobPath ?? null, prompts.characterPath ?? null, now, now);
148
+ }
149
+ async getAgentPrompts(agentId) {
150
+ const row = await this.db.get(`SELECT job_prompt, character_prompt, command_prompts_json, job_path, character_path
151
+ FROM agent_prompts WHERE agent_id = ?`, agentId);
152
+ if (!row)
153
+ return undefined;
154
+ return {
155
+ agentId,
156
+ jobPrompt: row.job_prompt ?? undefined,
157
+ characterPrompt: row.character_prompt ?? undefined,
158
+ commandPrompts: row.command_prompts_json ? JSON.parse(row.command_prompts_json) : undefined,
159
+ jobPath: row.job_path ?? undefined,
160
+ characterPath: row.character_path ?? undefined,
161
+ };
162
+ }
163
+ async setAgentAuth(agentId, encryptedSecret, lastVerifiedAt) {
164
+ const now = new Date().toISOString();
165
+ await this.db.run(`INSERT INTO agent_auth (agent_id, encrypted_secret, last_verified_at, created_at, updated_at)
166
+ VALUES (?, ?, ?, ?, ?)
167
+ ON CONFLICT(agent_id) DO UPDATE SET
168
+ encrypted_secret=excluded.encrypted_secret,
169
+ last_verified_at=excluded.last_verified_at,
170
+ updated_at=excluded.updated_at`, agentId, encryptedSecret, lastVerifiedAt ?? null, now, now);
171
+ }
172
+ async getAgentAuthMetadata(agentId) {
173
+ const row = await this.db.get("SELECT agent_id, encrypted_secret, last_verified_at, updated_at FROM agent_auth WHERE agent_id = ?", agentId);
174
+ return {
175
+ agentId,
176
+ configured: Boolean(row?.encrypted_secret),
177
+ lastUpdatedAt: row?.updated_at,
178
+ lastVerifiedAt: row?.last_verified_at ?? undefined,
179
+ };
180
+ }
181
+ async getAgentAuthSecret(agentId) {
182
+ const row = await this.db.get("SELECT agent_id, encrypted_secret, last_verified_at, updated_at FROM agent_auth WHERE agent_id = ?", agentId);
183
+ if (!row)
184
+ return undefined;
185
+ return {
186
+ agentId,
187
+ configured: true,
188
+ encryptedSecret: row.encrypted_secret,
189
+ lastVerifiedAt: row.last_verified_at ?? undefined,
190
+ lastUpdatedAt: row.updated_at,
191
+ };
192
+ }
193
+ async setAgentHealth(health) {
194
+ await this.db.run(`INSERT INTO agent_health (agent_id, status, last_checked_at, latency_ms, details_json)
195
+ VALUES (?, ?, ?, ?, ?)
196
+ ON CONFLICT(agent_id) DO UPDATE SET
197
+ status=excluded.status,
198
+ last_checked_at=excluded.last_checked_at,
199
+ latency_ms=excluded.latency_ms,
200
+ details_json=excluded.details_json`, health.agentId, health.status, health.lastCheckedAt, health.latencyMs ?? null, health.details ? JSON.stringify(health.details) : null);
201
+ }
202
+ async getAgentHealth(agentId) {
203
+ const row = await this.db.get("SELECT agent_id, status, last_checked_at, latency_ms, details_json FROM agent_health WHERE agent_id = ?", agentId);
204
+ if (!row)
205
+ return undefined;
206
+ return {
207
+ agentId,
208
+ status: row.status,
209
+ lastCheckedAt: row.last_checked_at,
210
+ latencyMs: row.latency_ms ?? undefined,
211
+ details: row.details_json ? JSON.parse(row.details_json) : undefined,
212
+ };
213
+ }
214
+ async listAgentHealthSummary() {
215
+ const rows = await this.db.all("SELECT agent_id, status, last_checked_at, latency_ms, details_json FROM agent_health");
216
+ return rows.map((row) => ({
217
+ agentId: row.agent_id,
218
+ status: row.status,
219
+ lastCheckedAt: row.last_checked_at,
220
+ latencyMs: row.latency_ms ?? undefined,
221
+ details: row.details_json ? JSON.parse(row.details_json) : undefined,
222
+ }));
223
+ }
224
+ async setWorkspaceDefault(workspaceId, commandName, agentId, options = {}) {
225
+ const now = new Date().toISOString();
226
+ await this.db.run(`INSERT INTO workspace_defaults (workspace_id, command_name, agent_id, qa_profile, docdex_scope, updated_at)
227
+ VALUES (?, ?, ?, ?, ?, ?)
228
+ ON CONFLICT(workspace_id, command_name) DO UPDATE SET
229
+ agent_id=excluded.agent_id,
230
+ qa_profile=excluded.qa_profile,
231
+ docdex_scope=excluded.docdex_scope,
232
+ updated_at=excluded.updated_at`, workspaceId, commandName, agentId, options.qaProfile ?? null, options.docdexScope ?? null, now);
233
+ }
234
+ async getWorkspaceDefaults(workspaceId) {
235
+ const rows = await this.db.all("SELECT workspace_id, command_name, agent_id, qa_profile, docdex_scope, updated_at FROM workspace_defaults WHERE workspace_id = ?", workspaceId);
236
+ return rows.map((row) => ({
237
+ workspaceId: row.workspace_id,
238
+ commandName: row.command_name,
239
+ agentId: row.agent_id,
240
+ qaProfile: row.qa_profile ?? undefined,
241
+ docdexScope: row.docdex_scope ?? undefined,
242
+ updatedAt: row.updated_at,
243
+ }));
244
+ }
245
+ async removeWorkspaceDefault(workspaceId, commandName) {
246
+ await this.db.run("DELETE FROM workspace_defaults WHERE workspace_id = ? AND command_name = ?", workspaceId, commandName);
247
+ }
248
+ async findWorkspaceReferences(agentId) {
249
+ const rows = await this.db.all("SELECT workspace_id, command_name, agent_id, qa_profile, docdex_scope, updated_at FROM workspace_defaults WHERE agent_id = ?", agentId);
250
+ return rows.map((row) => ({
251
+ workspaceId: row.workspace_id,
252
+ commandName: row.command_name,
253
+ agentId: row.agent_id,
254
+ qaProfile: row.qa_profile ?? undefined,
255
+ docdexScope: row.docdex_scope ?? undefined,
256
+ updatedAt: row.updated_at,
257
+ }));
258
+ }
259
+ async createCommandRun(record) {
260
+ const id = randomUUID();
261
+ await this.db.run(`INSERT INTO command_runs (id, command_name, started_at, status, exit_code, error_summary, payload_json)
262
+ VALUES (?, ?, ?, ?, ?, ?, ?)`, id, record.commandName, record.startedAt, record.status, record.exitCode ?? null, record.errorSummary ?? null, record.payload ? JSON.stringify(record.payload) : null);
263
+ return {
264
+ id,
265
+ ...record,
266
+ completedAt: null,
267
+ };
268
+ }
269
+ async completeCommandRun(id, update) {
270
+ await this.db.run(`UPDATE command_runs
271
+ SET status = ?, completed_at = ?, exit_code = ?, error_summary = ?, result_json = ?
272
+ WHERE id = ?`, update.status, update.completedAt, update.exitCode ?? null, update.errorSummary ?? null, update.result ? JSON.stringify(update.result) : null, id);
273
+ }
274
+ async recordTokenUsage(entry) {
275
+ const id = randomUUID();
276
+ await this.db.run(`INSERT INTO token_usage (
277
+ id, agent_id, command_run_id, model_name, tokens_prompt, tokens_completion, tokens_total,
278
+ cost_estimate, duration_seconds, timestamp, metadata_json
279
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, id, entry.agentId ?? null, entry.commandRunId ?? null, entry.modelName ?? null, entry.tokensPrompt ?? null, entry.tokensCompletion ?? null, entry.tokensTotal ?? null, entry.costEstimate ?? null, entry.durationSeconds ?? null, entry.timestamp, entry.metadata ? JSON.stringify(entry.metadata) : null);
280
+ }
281
+ }