@openqa/cli 1.0.6 → 1.0.8

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/dist/cli/index.js CHANGED
@@ -12,123 +12,171 @@ import { Tracer } from "@orka-js/observability";
12
12
  import { EventEmitter as EventEmitter3 } from "events";
13
13
 
14
14
  // database/index.ts
15
- import Database from "better-sqlite3";
16
- import { readFileSync } from "fs";
17
- import { join, dirname } from "path";
15
+ import { Low } from "lowdb";
16
+ import { JSONFile } from "lowdb/node";
17
+ import { dirname } from "path";
18
18
  import { fileURLToPath } from "url";
19
19
  import { mkdirSync } from "fs";
20
20
  var __filename = fileURLToPath(import.meta.url);
21
21
  var __dirname = dirname(__filename);
22
22
  var OpenQADatabase = class {
23
- db;
24
- constructor(dbPath = "./data/openqa.db") {
25
- const dir = dirname(dbPath);
26
- mkdirSync(dir, { recursive: true });
27
- this.db = new Database(dbPath);
23
+ constructor(dbPath = "./data/openqa.json") {
24
+ this.dbPath = dbPath;
28
25
  this.initialize();
29
26
  }
27
+ db = null;
30
28
  initialize() {
31
- const schema = readFileSync(join(__dirname, "schema.sql"), "utf-8");
32
- this.db.exec(schema);
33
- }
34
- getConfig(key) {
35
- const row = this.db.prepare("SELECT value FROM config WHERE key = ?").get(key);
36
- return row?.value || null;
37
- }
38
- setConfig(key, value) {
39
- this.db.prepare("INSERT OR REPLACE INTO config (key, value, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP)").run(key, value);
40
- }
41
- getAllConfig() {
42
- const rows = this.db.prepare("SELECT key, value FROM config").all();
43
- return Object.fromEntries(rows.map((r) => [r.key, r.value]));
44
- }
45
- createSession(id, metadata) {
46
- this.db.prepare("INSERT INTO test_sessions (id, status, metadata) VALUES (?, ?, ?)").run(
47
- id,
48
- "running",
49
- metadata ? JSON.stringify(metadata) : null
50
- );
51
- return this.getSession(id);
52
- }
53
- getSession(id) {
54
- return this.db.prepare("SELECT * FROM test_sessions WHERE id = ?").get(id);
29
+ const dir = dirname(this.dbPath);
30
+ mkdirSync(dir, { recursive: true });
31
+ const adapter = new JSONFile(this.dbPath);
32
+ this.db = new Low(adapter, {
33
+ config: {},
34
+ test_sessions: [],
35
+ actions: [],
36
+ bugs: [],
37
+ kanban_tickets: []
38
+ });
39
+ this.db.read();
40
+ if (!this.db.data) {
41
+ this.db.data = {
42
+ config: {},
43
+ test_sessions: [],
44
+ actions: [],
45
+ bugs: [],
46
+ kanban_tickets: []
47
+ };
48
+ this.db.write();
49
+ }
55
50
  }
56
- updateSession(id, updates) {
57
- const fields = Object.keys(updates).map((k) => `${k} = ?`).join(", ");
58
- const values = [...Object.values(updates), id];
59
- this.db.prepare(`UPDATE test_sessions SET ${fields} WHERE id = ?`).run(...values);
51
+ async ensureInitialized() {
52
+ if (!this.db) {
53
+ this.initialize();
54
+ }
55
+ await this.db.read();
60
56
  }
61
- getRecentSessions(limit = 10) {
62
- return this.db.prepare("SELECT * FROM test_sessions ORDER BY started_at DESC LIMIT ?").all(limit);
57
+ async getConfig(key) {
58
+ await this.ensureInitialized();
59
+ return this.db.data.config[key] || null;
63
60
  }
64
- createAction(action) {
65
- const id = `action_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
66
- this.db.prepare("INSERT INTO actions (id, session_id, type, description, input, output, screenshot_path) VALUES (?, ?, ?, ?, ?, ?, ?)").run(
67
- id,
68
- action.session_id,
69
- action.type,
70
- action.description,
71
- action.input || null,
72
- action.output || null,
73
- action.screenshot_path || null
74
- );
75
- return this.db.prepare("SELECT * FROM actions WHERE id = ?").get(id);
61
+ async setConfig(key, value) {
62
+ await this.ensureInitialized();
63
+ this.db.data.config[key] = value;
64
+ await this.db.write();
76
65
  }
77
- getSessionActions(sessionId) {
78
- return this.db.prepare("SELECT * FROM actions WHERE session_id = ? ORDER BY timestamp DESC").all(sessionId);
66
+ async getAllConfig() {
67
+ await this.ensureInitialized();
68
+ return this.db.data.config;
79
69
  }
80
- createBug(bug) {
81
- const id = `bug_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
82
- this.db.prepare("INSERT INTO bugs (id, session_id, title, description, severity, status, github_issue_url, screenshot_path) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(
70
+ async createSession(id, metadata) {
71
+ await this.ensureInitialized();
72
+ const session = {
83
73
  id,
84
- bug.session_id,
85
- bug.title,
86
- bug.description,
87
- bug.severity,
88
- bug.status,
89
- bug.github_issue_url || null,
90
- bug.screenshot_path || null
91
- );
92
- return this.db.prepare("SELECT * FROM bugs WHERE id = ?").get(id);
93
- }
94
- updateBug(id, updates) {
95
- const fields = Object.keys(updates).map((k) => `${k} = ?`).join(", ");
96
- const values = [...Object.values(updates), id];
97
- this.db.prepare(`UPDATE bugs SET ${fields}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`).run(...values);
98
- }
99
- getAllBugs() {
100
- return this.db.prepare("SELECT * FROM bugs ORDER BY created_at DESC").all();
74
+ started_at: (/* @__PURE__ */ new Date()).toISOString(),
75
+ status: "running",
76
+ total_actions: 0,
77
+ bugs_found: 0,
78
+ metadata: metadata ? JSON.stringify(metadata) : void 0
79
+ };
80
+ this.db.data.test_sessions.push(session);
81
+ await this.db.write();
82
+ return session;
83
+ }
84
+ async getSession(id) {
85
+ await this.ensureInitialized();
86
+ return this.db.data.test_sessions.find((s) => s.id === id) || null;
87
+ }
88
+ async updateSession(id, updates) {
89
+ await this.ensureInitialized();
90
+ const index = this.db.data.test_sessions.findIndex((s) => s.id === id);
91
+ if (index !== -1) {
92
+ this.db.data.test_sessions[index] = { ...this.db.data.test_sessions[index], ...updates };
93
+ await this.db.write();
94
+ }
101
95
  }
102
- getBugsByStatus(status) {
103
- return this.db.prepare("SELECT * FROM bugs WHERE status = ? ORDER BY created_at DESC").all(status);
96
+ async getRecentSessions(limit = 10) {
97
+ await this.ensureInitialized();
98
+ return this.db.data.test_sessions.sort((a, b) => new Date(b.started_at).getTime() - new Date(a.started_at).getTime()).slice(0, limit);
104
99
  }
105
- createKanbanTicket(ticket) {
106
- const id = `ticket_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
107
- this.db.prepare("INSERT INTO kanban_tickets (id, bug_id, title, description, priority, column, tags, screenshot_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(
108
- id,
109
- ticket.bug_id || null,
110
- ticket.title,
111
- ticket.description,
112
- ticket.priority,
113
- ticket.column,
114
- ticket.tags || null,
115
- ticket.screenshot_url || null
116
- );
117
- return this.db.prepare("SELECT * FROM kanban_tickets WHERE id = ?").get(id);
100
+ async createAction(action) {
101
+ await this.ensureInitialized();
102
+ const newAction = {
103
+ id: `action_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
104
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
105
+ ...action
106
+ };
107
+ this.db.data.actions.push(newAction);
108
+ await this.db.write();
109
+ return newAction;
110
+ }
111
+ async getSessionActions(sessionId) {
112
+ await this.ensureInitialized();
113
+ return this.db.data.actions.filter((a) => a.session_id === sessionId).sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
114
+ }
115
+ async createBug(bug) {
116
+ await this.ensureInitialized();
117
+ const newBug = {
118
+ id: `bug_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
119
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
120
+ updated_at: (/* @__PURE__ */ new Date()).toISOString(),
121
+ ...bug
122
+ };
123
+ this.db.data.bugs.push(newBug);
124
+ await this.db.write();
125
+ return newBug;
126
+ }
127
+ async updateBug(id, updates) {
128
+ await this.ensureInitialized();
129
+ const index = this.db.data.bugs.findIndex((b) => b.id === id);
130
+ if (index !== -1) {
131
+ this.db.data.bugs[index] = {
132
+ ...this.db.data.bugs[index],
133
+ ...updates,
134
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
135
+ };
136
+ await this.db.write();
137
+ }
118
138
  }
119
- updateKanbanTicket(id, updates) {
120
- const fields = Object.keys(updates).map((k) => `${k} = ?`).join(", ");
121
- const values = [...Object.values(updates), id];
122
- this.db.prepare(`UPDATE kanban_tickets SET ${fields}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`).run(...values);
139
+ async getAllBugs() {
140
+ await this.ensureInitialized();
141
+ return this.db.data.bugs.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
142
+ }
143
+ async getBugsByStatus(status) {
144
+ await this.ensureInitialized();
145
+ return this.db.data.bugs.filter((b) => b.status === status).sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
146
+ }
147
+ async createKanbanTicket(ticket) {
148
+ await this.ensureInitialized();
149
+ const newTicket = {
150
+ id: `ticket_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
151
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
152
+ updated_at: (/* @__PURE__ */ new Date()).toISOString(),
153
+ ...ticket
154
+ };
155
+ this.db.data.kanban_tickets.push(newTicket);
156
+ await this.db.write();
157
+ return newTicket;
158
+ }
159
+ async updateKanbanTicket(id, updates) {
160
+ await this.ensureInitialized();
161
+ const index = this.db.data.kanban_tickets.findIndex((t) => t.id === id);
162
+ if (index !== -1) {
163
+ this.db.data.kanban_tickets[index] = {
164
+ ...this.db.data.kanban_tickets[index],
165
+ ...updates,
166
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
167
+ };
168
+ await this.db.write();
169
+ }
123
170
  }
124
- getKanbanTickets() {
125
- return this.db.prepare("SELECT * FROM kanban_tickets ORDER BY created_at DESC").all();
171
+ async getKanbanTickets() {
172
+ await this.ensureInitialized();
173
+ return this.db.data.kanban_tickets.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
126
174
  }
127
- getKanbanTicketsByColumn(column) {
128
- return this.db.prepare("SELECT * FROM kanban_tickets WHERE column = ? ORDER BY created_at DESC").all(column);
175
+ async getKanbanTicketsByColumn(column) {
176
+ await this.ensureInitialized();
177
+ return this.db.data.kanban_tickets.filter((t) => t.column === column).sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
129
178
  }
130
- close() {
131
- this.db.close();
179
+ async close() {
132
180
  }
133
181
  };
134
182
 
@@ -179,8 +227,8 @@ var ConfigManager = class {
179
227
  }
180
228
  };
181
229
  }
182
- get(key) {
183
- const dbValue = this.db.getConfig(key);
230
+ async get(key) {
231
+ const dbValue = await this.db.getConfig(key);
184
232
  if (dbValue) return dbValue;
185
233
  const keys = key.split(".");
186
234
  let value = this.envConfig;
@@ -189,11 +237,11 @@ var ConfigManager = class {
189
237
  }
190
238
  return value?.toString() || null;
191
239
  }
192
- set(key, value) {
193
- this.db.setConfig(key, value);
240
+ async set(key, value) {
241
+ await this.db.setConfig(key, value);
194
242
  }
195
- getAll() {
196
- const dbConfig = this.db.getAllConfig();
243
+ async getAll() {
244
+ const dbConfig = await this.db.getAllConfig();
197
245
  const merged = { ...this.envConfig };
198
246
  for (const [key, value] of Object.entries(dbConfig)) {
199
247
  const keys = key.split(".");
@@ -206,8 +254,12 @@ var ConfigManager = class {
206
254
  }
207
255
  return merged;
208
256
  }
209
- getConfig() {
210
- return this.getAll();
257
+ async getConfig() {
258
+ return await this.getAll();
259
+ }
260
+ // Synchronous version that only uses env vars (no DB)
261
+ getConfigSync() {
262
+ return this.envConfig;
211
263
  }
212
264
  };
213
265
 
@@ -1325,11 +1377,11 @@ var OpenQAAgent = class extends EventEmitter3 {
1325
1377
  constructor(configPath) {
1326
1378
  super();
1327
1379
  this.config = new ConfigManager(configPath);
1328
- this.db = new OpenQADatabase(this.config.get("database.path") || void 0);
1380
+ this.db = new OpenQADatabase("./data/openqa.json");
1329
1381
  this.skillManager = new SkillManager(this.db);
1330
1382
  }
1331
1383
  createLLMAdapter() {
1332
- const cfg = this.config.getConfig();
1384
+ const cfg = this.config.getConfigSync();
1333
1385
  switch (cfg.llm.provider) {
1334
1386
  case "anthropic":
1335
1387
  return new AnthropicAdapter2({
@@ -1345,9 +1397,9 @@ var OpenQAAgent = class extends EventEmitter3 {
1345
1397
  }
1346
1398
  }
1347
1399
  async initialize(triggerType = "manual", triggerData) {
1348
- const cfg = this.config.getConfig();
1400
+ const cfg = this.config.getConfigSync();
1349
1401
  this.sessionId = `session_${Date.now()}`;
1350
- this.db.createSession(this.sessionId, {
1402
+ await this.db.createSession(this.sessionId, {
1351
1403
  config: cfg,
1352
1404
  started_at: (/* @__PURE__ */ new Date()).toISOString(),
1353
1405
  trigger_type: triggerType,
@@ -1583,7 +1635,7 @@ Always provide clear, actionable information with steps to reproduce. Think step
1583
1635
 
1584
1636
  // cli/index.ts
1585
1637
  import { spawn } from "child_process";
1586
- import { writeFileSync, readFileSync as readFileSync2, existsSync, unlinkSync } from "fs";
1638
+ import { writeFileSync as writeFileSync2, readFileSync as readFileSync2, existsSync, unlinkSync } from "fs";
1587
1639
  import { join as join3 } from "path";
1588
1640
  import chalk from "chalk";
1589
1641
  import ora from "ora";
@@ -1611,7 +1663,7 @@ program.command("start").description("Start the OpenQA agent and web UI").option
1611
1663
  stdio: "ignore"
1612
1664
  });
1613
1665
  child.unref();
1614
- writeFileSync(PID_FILE, child.pid.toString());
1666
+ writeFileSync2(PID_FILE, child.pid.toString());
1615
1667
  spinner.succeed(chalk.green("OpenQA started in daemon mode"));
1616
1668
  console.log(chalk.cyan(`PID: ${child.pid}`));
1617
1669
  } else {
@@ -1,121 +1,169 @@
1
1
  // database/index.ts
2
- import Database from "better-sqlite3";
3
- import { readFileSync } from "fs";
4
- import { join, dirname } from "path";
2
+ import { Low } from "lowdb";
3
+ import { JSONFile } from "lowdb/node";
4
+ import { dirname } from "path";
5
5
  import { fileURLToPath } from "url";
6
6
  import { mkdirSync } from "fs";
7
7
  var __filename = fileURLToPath(import.meta.url);
8
8
  var __dirname = dirname(__filename);
9
9
  var OpenQADatabase = class {
10
- db;
11
- constructor(dbPath = "./data/openqa.db") {
12
- const dir = dirname(dbPath);
13
- mkdirSync(dir, { recursive: true });
14
- this.db = new Database(dbPath);
10
+ constructor(dbPath = "./data/openqa.json") {
11
+ this.dbPath = dbPath;
15
12
  this.initialize();
16
13
  }
14
+ db = null;
17
15
  initialize() {
18
- const schema = readFileSync(join(__dirname, "schema.sql"), "utf-8");
19
- this.db.exec(schema);
20
- }
21
- getConfig(key) {
22
- const row = this.db.prepare("SELECT value FROM config WHERE key = ?").get(key);
23
- return row?.value || null;
24
- }
25
- setConfig(key, value) {
26
- this.db.prepare("INSERT OR REPLACE INTO config (key, value, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP)").run(key, value);
27
- }
28
- getAllConfig() {
29
- const rows = this.db.prepare("SELECT key, value FROM config").all();
30
- return Object.fromEntries(rows.map((r) => [r.key, r.value]));
31
- }
32
- createSession(id, metadata) {
33
- this.db.prepare("INSERT INTO test_sessions (id, status, metadata) VALUES (?, ?, ?)").run(
34
- id,
35
- "running",
36
- metadata ? JSON.stringify(metadata) : null
37
- );
38
- return this.getSession(id);
39
- }
40
- getSession(id) {
41
- return this.db.prepare("SELECT * FROM test_sessions WHERE id = ?").get(id);
42
- }
43
- updateSession(id, updates) {
44
- const fields = Object.keys(updates).map((k) => `${k} = ?`).join(", ");
45
- const values = [...Object.values(updates), id];
46
- this.db.prepare(`UPDATE test_sessions SET ${fields} WHERE id = ?`).run(...values);
47
- }
48
- getRecentSessions(limit = 10) {
49
- return this.db.prepare("SELECT * FROM test_sessions ORDER BY started_at DESC LIMIT ?").all(limit);
50
- }
51
- createAction(action) {
52
- const id = `action_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
53
- this.db.prepare("INSERT INTO actions (id, session_id, type, description, input, output, screenshot_path) VALUES (?, ?, ?, ?, ?, ?, ?)").run(
54
- id,
55
- action.session_id,
56
- action.type,
57
- action.description,
58
- action.input || null,
59
- action.output || null,
60
- action.screenshot_path || null
61
- );
62
- return this.db.prepare("SELECT * FROM actions WHERE id = ?").get(id);
63
- }
64
- getSessionActions(sessionId) {
65
- return this.db.prepare("SELECT * FROM actions WHERE session_id = ? ORDER BY timestamp DESC").all(sessionId);
66
- }
67
- createBug(bug) {
68
- const id = `bug_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
69
- this.db.prepare("INSERT INTO bugs (id, session_id, title, description, severity, status, github_issue_url, screenshot_path) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(
70
- id,
71
- bug.session_id,
72
- bug.title,
73
- bug.description,
74
- bug.severity,
75
- bug.status,
76
- bug.github_issue_url || null,
77
- bug.screenshot_path || null
78
- );
79
- return this.db.prepare("SELECT * FROM bugs WHERE id = ?").get(id);
80
- }
81
- updateBug(id, updates) {
82
- const fields = Object.keys(updates).map((k) => `${k} = ?`).join(", ");
83
- const values = [...Object.values(updates), id];
84
- this.db.prepare(`UPDATE bugs SET ${fields}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`).run(...values);
85
- }
86
- getAllBugs() {
87
- return this.db.prepare("SELECT * FROM bugs ORDER BY created_at DESC").all();
88
- }
89
- getBugsByStatus(status) {
90
- return this.db.prepare("SELECT * FROM bugs WHERE status = ? ORDER BY created_at DESC").all(status);
91
- }
92
- createKanbanTicket(ticket) {
93
- const id = `ticket_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
94
- this.db.prepare("INSERT INTO kanban_tickets (id, bug_id, title, description, priority, column, tags, screenshot_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(
16
+ const dir = dirname(this.dbPath);
17
+ mkdirSync(dir, { recursive: true });
18
+ const adapter = new JSONFile(this.dbPath);
19
+ this.db = new Low(adapter, {
20
+ config: {},
21
+ test_sessions: [],
22
+ actions: [],
23
+ bugs: [],
24
+ kanban_tickets: []
25
+ });
26
+ this.db.read();
27
+ if (!this.db.data) {
28
+ this.db.data = {
29
+ config: {},
30
+ test_sessions: [],
31
+ actions: [],
32
+ bugs: [],
33
+ kanban_tickets: []
34
+ };
35
+ this.db.write();
36
+ }
37
+ }
38
+ async ensureInitialized() {
39
+ if (!this.db) {
40
+ this.initialize();
41
+ }
42
+ await this.db.read();
43
+ }
44
+ async getConfig(key) {
45
+ await this.ensureInitialized();
46
+ return this.db.data.config[key] || null;
47
+ }
48
+ async setConfig(key, value) {
49
+ await this.ensureInitialized();
50
+ this.db.data.config[key] = value;
51
+ await this.db.write();
52
+ }
53
+ async getAllConfig() {
54
+ await this.ensureInitialized();
55
+ return this.db.data.config;
56
+ }
57
+ async createSession(id, metadata) {
58
+ await this.ensureInitialized();
59
+ const session = {
95
60
  id,
96
- ticket.bug_id || null,
97
- ticket.title,
98
- ticket.description,
99
- ticket.priority,
100
- ticket.column,
101
- ticket.tags || null,
102
- ticket.screenshot_url || null
103
- );
104
- return this.db.prepare("SELECT * FROM kanban_tickets WHERE id = ?").get(id);
105
- }
106
- updateKanbanTicket(id, updates) {
107
- const fields = Object.keys(updates).map((k) => `${k} = ?`).join(", ");
108
- const values = [...Object.values(updates), id];
109
- this.db.prepare(`UPDATE kanban_tickets SET ${fields}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`).run(...values);
110
- }
111
- getKanbanTickets() {
112
- return this.db.prepare("SELECT * FROM kanban_tickets ORDER BY created_at DESC").all();
113
- }
114
- getKanbanTicketsByColumn(column) {
115
- return this.db.prepare("SELECT * FROM kanban_tickets WHERE column = ? ORDER BY created_at DESC").all(column);
116
- }
117
- close() {
118
- this.db.close();
61
+ started_at: (/* @__PURE__ */ new Date()).toISOString(),
62
+ status: "running",
63
+ total_actions: 0,
64
+ bugs_found: 0,
65
+ metadata: metadata ? JSON.stringify(metadata) : void 0
66
+ };
67
+ this.db.data.test_sessions.push(session);
68
+ await this.db.write();
69
+ return session;
70
+ }
71
+ async getSession(id) {
72
+ await this.ensureInitialized();
73
+ return this.db.data.test_sessions.find((s) => s.id === id) || null;
74
+ }
75
+ async updateSession(id, updates) {
76
+ await this.ensureInitialized();
77
+ const index = this.db.data.test_sessions.findIndex((s) => s.id === id);
78
+ if (index !== -1) {
79
+ this.db.data.test_sessions[index] = { ...this.db.data.test_sessions[index], ...updates };
80
+ await this.db.write();
81
+ }
82
+ }
83
+ async getRecentSessions(limit = 10) {
84
+ await this.ensureInitialized();
85
+ return this.db.data.test_sessions.sort((a, b) => new Date(b.started_at).getTime() - new Date(a.started_at).getTime()).slice(0, limit);
86
+ }
87
+ async createAction(action) {
88
+ await this.ensureInitialized();
89
+ const newAction = {
90
+ id: `action_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
91
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
92
+ ...action
93
+ };
94
+ this.db.data.actions.push(newAction);
95
+ await this.db.write();
96
+ return newAction;
97
+ }
98
+ async getSessionActions(sessionId) {
99
+ await this.ensureInitialized();
100
+ return this.db.data.actions.filter((a) => a.session_id === sessionId).sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
101
+ }
102
+ async createBug(bug) {
103
+ await this.ensureInitialized();
104
+ const newBug = {
105
+ id: `bug_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
106
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
107
+ updated_at: (/* @__PURE__ */ new Date()).toISOString(),
108
+ ...bug
109
+ };
110
+ this.db.data.bugs.push(newBug);
111
+ await this.db.write();
112
+ return newBug;
113
+ }
114
+ async updateBug(id, updates) {
115
+ await this.ensureInitialized();
116
+ const index = this.db.data.bugs.findIndex((b) => b.id === id);
117
+ if (index !== -1) {
118
+ this.db.data.bugs[index] = {
119
+ ...this.db.data.bugs[index],
120
+ ...updates,
121
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
122
+ };
123
+ await this.db.write();
124
+ }
125
+ }
126
+ async getAllBugs() {
127
+ await this.ensureInitialized();
128
+ return this.db.data.bugs.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
129
+ }
130
+ async getBugsByStatus(status) {
131
+ await this.ensureInitialized();
132
+ return this.db.data.bugs.filter((b) => b.status === status).sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
133
+ }
134
+ async createKanbanTicket(ticket) {
135
+ await this.ensureInitialized();
136
+ const newTicket = {
137
+ id: `ticket_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
138
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
139
+ updated_at: (/* @__PURE__ */ new Date()).toISOString(),
140
+ ...ticket
141
+ };
142
+ this.db.data.kanban_tickets.push(newTicket);
143
+ await this.db.write();
144
+ return newTicket;
145
+ }
146
+ async updateKanbanTicket(id, updates) {
147
+ await this.ensureInitialized();
148
+ const index = this.db.data.kanban_tickets.findIndex((t) => t.id === id);
149
+ if (index !== -1) {
150
+ this.db.data.kanban_tickets[index] = {
151
+ ...this.db.data.kanban_tickets[index],
152
+ ...updates,
153
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
154
+ };
155
+ await this.db.write();
156
+ }
157
+ }
158
+ async getKanbanTickets() {
159
+ await this.ensureInitialized();
160
+ return this.db.data.kanban_tickets.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
161
+ }
162
+ async getKanbanTicketsByColumn(column) {
163
+ await this.ensureInitialized();
164
+ return this.db.data.kanban_tickets.filter((t) => t.column === column).sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
165
+ }
166
+ async close() {
119
167
  }
120
168
  };
121
169
  export {