sparkecoder 0.1.3
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 +353 -0
- package/dist/agent/index.d.ts +5 -0
- package/dist/agent/index.js +1979 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +3779 -0
- package/dist/cli.js.map +1 -0
- package/dist/db/index.d.ts +85 -0
- package/dist/db/index.js +450 -0
- package/dist/db/index.js.map +1 -0
- package/dist/index-BxpkHy7X.d.ts +326 -0
- package/dist/index.d.ts +107 -0
- package/dist/index.js +3479 -0
- package/dist/index.js.map +1 -0
- package/dist/schema-EPbMMFza.d.ts +981 -0
- package/dist/server/index.d.ts +18 -0
- package/dist/server/index.js +3458 -0
- package/dist/server/index.js.map +1 -0
- package/dist/tools/index.d.ts +402 -0
- package/dist/tools/index.js +1366 -0
- package/dist/tools/index.js.map +1 -0
- package/package.json +99 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as drizzle_orm_better_sqlite3 from 'drizzle-orm/better-sqlite3';
|
|
2
|
+
import Database from 'better-sqlite3';
|
|
3
|
+
import { s as schema, M as ModelMessage, a as Message, N as NewSession, S as Session, L as LoadedSkill, b as NewTerminal, T as Terminal, c as NewTodoItem, d as TodoItem, e as NewToolExecution, f as ToolExecution } from '../schema-EPbMMFza.js';
|
|
4
|
+
export { g as SessionConfig } from '../schema-EPbMMFza.js';
|
|
5
|
+
import 'drizzle-orm/sqlite-core';
|
|
6
|
+
|
|
7
|
+
declare function initDatabase(dbPath: string): drizzle_orm_better_sqlite3.BetterSQLite3Database<typeof schema> & {
|
|
8
|
+
$client: Database.Database;
|
|
9
|
+
};
|
|
10
|
+
declare function getDb(): drizzle_orm_better_sqlite3.BetterSQLite3Database<typeof schema> & {
|
|
11
|
+
$client: Database.Database;
|
|
12
|
+
};
|
|
13
|
+
declare function closeDatabase(): void;
|
|
14
|
+
declare const sessionQueries: {
|
|
15
|
+
create(data: Omit<NewSession, "id" | "createdAt" | "updatedAt">): Session;
|
|
16
|
+
getById(id: string): Session | undefined;
|
|
17
|
+
list(limit?: number, offset?: number): Session[];
|
|
18
|
+
updateStatus(id: string, status: Session["status"]): Session | undefined;
|
|
19
|
+
delete(id: string): boolean;
|
|
20
|
+
};
|
|
21
|
+
declare const messageQueries: {
|
|
22
|
+
/**
|
|
23
|
+
* Get the next sequence number for a session
|
|
24
|
+
*/
|
|
25
|
+
getNextSequence(sessionId: string): number;
|
|
26
|
+
/**
|
|
27
|
+
* Create a single message from a ModelMessage
|
|
28
|
+
*/
|
|
29
|
+
create(sessionId: string, modelMessage: ModelMessage): Message;
|
|
30
|
+
/**
|
|
31
|
+
* Add multiple ModelMessages at once (from response.messages)
|
|
32
|
+
* Maintains insertion order via sequence numbers
|
|
33
|
+
*/
|
|
34
|
+
addMany(sessionId: string, modelMessages: ModelMessage[]): Message[];
|
|
35
|
+
/**
|
|
36
|
+
* Get all messages for a session as ModelMessage[]
|
|
37
|
+
* Ordered by sequence to maintain exact insertion order
|
|
38
|
+
*/
|
|
39
|
+
getBySession(sessionId: string): Message[];
|
|
40
|
+
/**
|
|
41
|
+
* Get ModelMessages directly (for passing to AI SDK)
|
|
42
|
+
*/
|
|
43
|
+
getModelMessages(sessionId: string): ModelMessage[];
|
|
44
|
+
getRecentBySession(sessionId: string, limit?: number): Message[];
|
|
45
|
+
countBySession(sessionId: string): number;
|
|
46
|
+
deleteBySession(sessionId: string): number;
|
|
47
|
+
};
|
|
48
|
+
declare const toolExecutionQueries: {
|
|
49
|
+
create(data: Omit<NewToolExecution, "id" | "startedAt">): ToolExecution;
|
|
50
|
+
getById(id: string): ToolExecution | undefined;
|
|
51
|
+
getByToolCallId(toolCallId: string): ToolExecution | undefined;
|
|
52
|
+
getPendingApprovals(sessionId: string): ToolExecution[];
|
|
53
|
+
approve(id: string): ToolExecution | undefined;
|
|
54
|
+
reject(id: string): ToolExecution | undefined;
|
|
55
|
+
complete(id: string, output: unknown, error?: string): ToolExecution | undefined;
|
|
56
|
+
getBySession(sessionId: string): ToolExecution[];
|
|
57
|
+
};
|
|
58
|
+
declare const todoQueries: {
|
|
59
|
+
create(data: Omit<NewTodoItem, "id" | "createdAt" | "updatedAt">): TodoItem;
|
|
60
|
+
createMany(sessionId: string, items: Array<{
|
|
61
|
+
content: string;
|
|
62
|
+
order?: number;
|
|
63
|
+
}>): TodoItem[];
|
|
64
|
+
getBySession(sessionId: string): TodoItem[];
|
|
65
|
+
updateStatus(id: string, status: TodoItem["status"]): TodoItem | undefined;
|
|
66
|
+
delete(id: string): boolean;
|
|
67
|
+
clearSession(sessionId: string): number;
|
|
68
|
+
};
|
|
69
|
+
declare const skillQueries: {
|
|
70
|
+
load(sessionId: string, skillName: string): LoadedSkill;
|
|
71
|
+
getBySession(sessionId: string): LoadedSkill[];
|
|
72
|
+
isLoaded(sessionId: string, skillName: string): boolean;
|
|
73
|
+
};
|
|
74
|
+
declare const terminalQueries: {
|
|
75
|
+
create(data: Omit<NewTerminal, "id" | "createdAt">): Terminal;
|
|
76
|
+
getById(id: string): Terminal | undefined;
|
|
77
|
+
getBySession(sessionId: string): Terminal[];
|
|
78
|
+
getRunning(sessionId: string): Terminal[];
|
|
79
|
+
updateStatus(id: string, status: Terminal["status"], exitCode?: number, error?: string): Terminal | undefined;
|
|
80
|
+
updatePid(id: string, pid: number): Terminal | undefined;
|
|
81
|
+
delete(id: string): boolean;
|
|
82
|
+
deleteBySession(sessionId: string): number;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export { Message, ModelMessage, Session, Terminal, TodoItem, ToolExecution, closeDatabase, getDb, initDatabase, messageQueries, sessionQueries, skillQueries, terminalQueries, todoQueries, toolExecutionQueries };
|
package/dist/db/index.js
ADDED
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// src/db/index.ts
|
|
8
|
+
import Database from "better-sqlite3";
|
|
9
|
+
import { drizzle } from "drizzle-orm/better-sqlite3";
|
|
10
|
+
import { eq, desc, and, sql } from "drizzle-orm";
|
|
11
|
+
import { nanoid } from "nanoid";
|
|
12
|
+
|
|
13
|
+
// src/db/schema.ts
|
|
14
|
+
var schema_exports = {};
|
|
15
|
+
__export(schema_exports, {
|
|
16
|
+
loadedSkills: () => loadedSkills,
|
|
17
|
+
messages: () => messages,
|
|
18
|
+
sessions: () => sessions,
|
|
19
|
+
terminals: () => terminals,
|
|
20
|
+
todoItems: () => todoItems,
|
|
21
|
+
toolExecutions: () => toolExecutions
|
|
22
|
+
});
|
|
23
|
+
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
|
|
24
|
+
var sessions = sqliteTable("sessions", {
|
|
25
|
+
id: text("id").primaryKey(),
|
|
26
|
+
name: text("name"),
|
|
27
|
+
workingDirectory: text("working_directory").notNull(),
|
|
28
|
+
model: text("model").notNull(),
|
|
29
|
+
status: text("status", { enum: ["active", "waiting", "completed", "error"] }).notNull().default("active"),
|
|
30
|
+
config: text("config", { mode: "json" }).$type(),
|
|
31
|
+
createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
|
|
32
|
+
updatedAt: integer("updated_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
|
|
33
|
+
});
|
|
34
|
+
var messages = sqliteTable("messages", {
|
|
35
|
+
id: text("id").primaryKey(),
|
|
36
|
+
sessionId: text("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
|
|
37
|
+
// Store the entire ModelMessage as JSON (role + content)
|
|
38
|
+
modelMessage: text("model_message", { mode: "json" }).$type().notNull(),
|
|
39
|
+
// Sequence number within session to maintain exact ordering
|
|
40
|
+
sequence: integer("sequence").notNull().default(0),
|
|
41
|
+
createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
|
|
42
|
+
});
|
|
43
|
+
var toolExecutions = sqliteTable("tool_executions", {
|
|
44
|
+
id: text("id").primaryKey(),
|
|
45
|
+
sessionId: text("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
|
|
46
|
+
messageId: text("message_id").references(() => messages.id, { onDelete: "cascade" }),
|
|
47
|
+
toolName: text("tool_name").notNull(),
|
|
48
|
+
toolCallId: text("tool_call_id").notNull(),
|
|
49
|
+
input: text("input", { mode: "json" }),
|
|
50
|
+
output: text("output", { mode: "json" }),
|
|
51
|
+
status: text("status", { enum: ["pending", "approved", "rejected", "completed", "error"] }).notNull().default("pending"),
|
|
52
|
+
requiresApproval: integer("requires_approval", { mode: "boolean" }).notNull().default(false),
|
|
53
|
+
error: text("error"),
|
|
54
|
+
startedAt: integer("started_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
|
|
55
|
+
completedAt: integer("completed_at", { mode: "timestamp" })
|
|
56
|
+
});
|
|
57
|
+
var todoItems = sqliteTable("todo_items", {
|
|
58
|
+
id: text("id").primaryKey(),
|
|
59
|
+
sessionId: text("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
|
|
60
|
+
content: text("content").notNull(),
|
|
61
|
+
status: text("status", { enum: ["pending", "in_progress", "completed", "cancelled"] }).notNull().default("pending"),
|
|
62
|
+
order: integer("order").notNull().default(0),
|
|
63
|
+
createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
|
|
64
|
+
updatedAt: integer("updated_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
|
|
65
|
+
});
|
|
66
|
+
var loadedSkills = sqliteTable("loaded_skills", {
|
|
67
|
+
id: text("id").primaryKey(),
|
|
68
|
+
sessionId: text("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
|
|
69
|
+
skillName: text("skill_name").notNull(),
|
|
70
|
+
loadedAt: integer("loaded_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
|
|
71
|
+
});
|
|
72
|
+
var terminals = sqliteTable("terminals", {
|
|
73
|
+
id: text("id").primaryKey(),
|
|
74
|
+
sessionId: text("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
|
|
75
|
+
name: text("name"),
|
|
76
|
+
// Optional friendly name (e.g., "dev-server")
|
|
77
|
+
command: text("command").notNull(),
|
|
78
|
+
// The command that was run
|
|
79
|
+
cwd: text("cwd").notNull(),
|
|
80
|
+
// Working directory
|
|
81
|
+
pid: integer("pid"),
|
|
82
|
+
// Process ID (null if not running)
|
|
83
|
+
status: text("status", { enum: ["running", "stopped", "error"] }).notNull().default("running"),
|
|
84
|
+
exitCode: integer("exit_code"),
|
|
85
|
+
// Exit code if stopped
|
|
86
|
+
error: text("error"),
|
|
87
|
+
// Error message if status is 'error'
|
|
88
|
+
createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
|
|
89
|
+
stoppedAt: integer("stopped_at", { mode: "timestamp" })
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// src/db/index.ts
|
|
93
|
+
var db = null;
|
|
94
|
+
var sqlite = null;
|
|
95
|
+
function initDatabase(dbPath) {
|
|
96
|
+
sqlite = new Database(dbPath);
|
|
97
|
+
sqlite.pragma("journal_mode = WAL");
|
|
98
|
+
db = drizzle(sqlite, { schema: schema_exports });
|
|
99
|
+
sqlite.exec(`
|
|
100
|
+
DROP TABLE IF EXISTS terminals;
|
|
101
|
+
DROP TABLE IF EXISTS loaded_skills;
|
|
102
|
+
DROP TABLE IF EXISTS todo_items;
|
|
103
|
+
DROP TABLE IF EXISTS tool_executions;
|
|
104
|
+
DROP TABLE IF EXISTS messages;
|
|
105
|
+
DROP TABLE IF EXISTS sessions;
|
|
106
|
+
|
|
107
|
+
CREATE TABLE sessions (
|
|
108
|
+
id TEXT PRIMARY KEY,
|
|
109
|
+
name TEXT,
|
|
110
|
+
working_directory TEXT NOT NULL,
|
|
111
|
+
model TEXT NOT NULL,
|
|
112
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
113
|
+
config TEXT,
|
|
114
|
+
created_at INTEGER NOT NULL,
|
|
115
|
+
updated_at INTEGER NOT NULL
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
CREATE TABLE messages (
|
|
119
|
+
id TEXT PRIMARY KEY,
|
|
120
|
+
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
121
|
+
model_message TEXT NOT NULL,
|
|
122
|
+
sequence INTEGER NOT NULL DEFAULT 0,
|
|
123
|
+
created_at INTEGER NOT NULL
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
CREATE TABLE tool_executions (
|
|
127
|
+
id TEXT PRIMARY KEY,
|
|
128
|
+
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
129
|
+
message_id TEXT REFERENCES messages(id) ON DELETE CASCADE,
|
|
130
|
+
tool_name TEXT NOT NULL,
|
|
131
|
+
tool_call_id TEXT NOT NULL,
|
|
132
|
+
input TEXT,
|
|
133
|
+
output TEXT,
|
|
134
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
135
|
+
requires_approval INTEGER NOT NULL DEFAULT 0,
|
|
136
|
+
error TEXT,
|
|
137
|
+
started_at INTEGER NOT NULL,
|
|
138
|
+
completed_at INTEGER
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
CREATE TABLE todo_items (
|
|
142
|
+
id TEXT PRIMARY KEY,
|
|
143
|
+
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
144
|
+
content TEXT NOT NULL,
|
|
145
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
146
|
+
"order" INTEGER NOT NULL DEFAULT 0,
|
|
147
|
+
created_at INTEGER NOT NULL,
|
|
148
|
+
updated_at INTEGER NOT NULL
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
CREATE TABLE loaded_skills (
|
|
152
|
+
id TEXT PRIMARY KEY,
|
|
153
|
+
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
154
|
+
skill_name TEXT NOT NULL,
|
|
155
|
+
loaded_at INTEGER NOT NULL
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
CREATE TABLE terminals (
|
|
159
|
+
id TEXT PRIMARY KEY,
|
|
160
|
+
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
161
|
+
name TEXT,
|
|
162
|
+
command TEXT NOT NULL,
|
|
163
|
+
cwd TEXT NOT NULL,
|
|
164
|
+
pid INTEGER,
|
|
165
|
+
status TEXT NOT NULL DEFAULT 'running',
|
|
166
|
+
exit_code INTEGER,
|
|
167
|
+
error TEXT,
|
|
168
|
+
created_at INTEGER NOT NULL,
|
|
169
|
+
stopped_at INTEGER
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id);
|
|
173
|
+
CREATE INDEX IF NOT EXISTS idx_tool_executions_session ON tool_executions(session_id);
|
|
174
|
+
CREATE INDEX IF NOT EXISTS idx_todo_items_session ON todo_items(session_id);
|
|
175
|
+
CREATE INDEX IF NOT EXISTS idx_loaded_skills_session ON loaded_skills(session_id);
|
|
176
|
+
CREATE INDEX IF NOT EXISTS idx_terminals_session ON terminals(session_id);
|
|
177
|
+
`);
|
|
178
|
+
return db;
|
|
179
|
+
}
|
|
180
|
+
function getDb() {
|
|
181
|
+
if (!db) {
|
|
182
|
+
throw new Error("Database not initialized. Call initDatabase first.");
|
|
183
|
+
}
|
|
184
|
+
return db;
|
|
185
|
+
}
|
|
186
|
+
function closeDatabase() {
|
|
187
|
+
if (sqlite) {
|
|
188
|
+
sqlite.close();
|
|
189
|
+
sqlite = null;
|
|
190
|
+
db = null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
var sessionQueries = {
|
|
194
|
+
create(data) {
|
|
195
|
+
const id = nanoid();
|
|
196
|
+
const now = /* @__PURE__ */ new Date();
|
|
197
|
+
const result = getDb().insert(sessions).values({
|
|
198
|
+
id,
|
|
199
|
+
...data,
|
|
200
|
+
createdAt: now,
|
|
201
|
+
updatedAt: now
|
|
202
|
+
}).returning().get();
|
|
203
|
+
return result;
|
|
204
|
+
},
|
|
205
|
+
getById(id) {
|
|
206
|
+
return getDb().select().from(sessions).where(eq(sessions.id, id)).get();
|
|
207
|
+
},
|
|
208
|
+
list(limit = 50, offset = 0) {
|
|
209
|
+
return getDb().select().from(sessions).orderBy(desc(sessions.createdAt)).limit(limit).offset(offset).all();
|
|
210
|
+
},
|
|
211
|
+
updateStatus(id, status) {
|
|
212
|
+
return getDb().update(sessions).set({ status, updatedAt: /* @__PURE__ */ new Date() }).where(eq(sessions.id, id)).returning().get();
|
|
213
|
+
},
|
|
214
|
+
delete(id) {
|
|
215
|
+
const result = getDb().delete(sessions).where(eq(sessions.id, id)).run();
|
|
216
|
+
return result.changes > 0;
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
var messageQueries = {
|
|
220
|
+
/**
|
|
221
|
+
* Get the next sequence number for a session
|
|
222
|
+
*/
|
|
223
|
+
getNextSequence(sessionId) {
|
|
224
|
+
const result = getDb().select({ maxSeq: sql`COALESCE(MAX(sequence), -1)` }).from(messages).where(eq(messages.sessionId, sessionId)).get();
|
|
225
|
+
return (result?.maxSeq ?? -1) + 1;
|
|
226
|
+
},
|
|
227
|
+
/**
|
|
228
|
+
* Create a single message from a ModelMessage
|
|
229
|
+
*/
|
|
230
|
+
create(sessionId, modelMessage) {
|
|
231
|
+
const id = nanoid();
|
|
232
|
+
const sequence = this.getNextSequence(sessionId);
|
|
233
|
+
const result = getDb().insert(messages).values({
|
|
234
|
+
id,
|
|
235
|
+
sessionId,
|
|
236
|
+
modelMessage,
|
|
237
|
+
sequence,
|
|
238
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
239
|
+
}).returning().get();
|
|
240
|
+
return result;
|
|
241
|
+
},
|
|
242
|
+
/**
|
|
243
|
+
* Add multiple ModelMessages at once (from response.messages)
|
|
244
|
+
* Maintains insertion order via sequence numbers
|
|
245
|
+
*/
|
|
246
|
+
addMany(sessionId, modelMessages) {
|
|
247
|
+
const results = [];
|
|
248
|
+
let sequence = this.getNextSequence(sessionId);
|
|
249
|
+
for (const msg of modelMessages) {
|
|
250
|
+
const id = nanoid();
|
|
251
|
+
const result = getDb().insert(messages).values({
|
|
252
|
+
id,
|
|
253
|
+
sessionId,
|
|
254
|
+
modelMessage: msg,
|
|
255
|
+
sequence,
|
|
256
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
257
|
+
}).returning().get();
|
|
258
|
+
results.push(result);
|
|
259
|
+
sequence++;
|
|
260
|
+
}
|
|
261
|
+
return results;
|
|
262
|
+
},
|
|
263
|
+
/**
|
|
264
|
+
* Get all messages for a session as ModelMessage[]
|
|
265
|
+
* Ordered by sequence to maintain exact insertion order
|
|
266
|
+
*/
|
|
267
|
+
getBySession(sessionId) {
|
|
268
|
+
return getDb().select().from(messages).where(eq(messages.sessionId, sessionId)).orderBy(messages.sequence).all();
|
|
269
|
+
},
|
|
270
|
+
/**
|
|
271
|
+
* Get ModelMessages directly (for passing to AI SDK)
|
|
272
|
+
*/
|
|
273
|
+
getModelMessages(sessionId) {
|
|
274
|
+
const messages2 = this.getBySession(sessionId);
|
|
275
|
+
return messages2.map((m) => m.modelMessage);
|
|
276
|
+
},
|
|
277
|
+
getRecentBySession(sessionId, limit = 50) {
|
|
278
|
+
return getDb().select().from(messages).where(eq(messages.sessionId, sessionId)).orderBy(desc(messages.sequence)).limit(limit).all().reverse();
|
|
279
|
+
},
|
|
280
|
+
countBySession(sessionId) {
|
|
281
|
+
const result = getDb().select({ count: sql`count(*)` }).from(messages).where(eq(messages.sessionId, sessionId)).get();
|
|
282
|
+
return result?.count ?? 0;
|
|
283
|
+
},
|
|
284
|
+
deleteBySession(sessionId) {
|
|
285
|
+
const result = getDb().delete(messages).where(eq(messages.sessionId, sessionId)).run();
|
|
286
|
+
return result.changes;
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
var toolExecutionQueries = {
|
|
290
|
+
create(data) {
|
|
291
|
+
const id = nanoid();
|
|
292
|
+
const result = getDb().insert(toolExecutions).values({
|
|
293
|
+
id,
|
|
294
|
+
...data,
|
|
295
|
+
startedAt: /* @__PURE__ */ new Date()
|
|
296
|
+
}).returning().get();
|
|
297
|
+
return result;
|
|
298
|
+
},
|
|
299
|
+
getById(id) {
|
|
300
|
+
return getDb().select().from(toolExecutions).where(eq(toolExecutions.id, id)).get();
|
|
301
|
+
},
|
|
302
|
+
getByToolCallId(toolCallId) {
|
|
303
|
+
return getDb().select().from(toolExecutions).where(eq(toolExecutions.toolCallId, toolCallId)).get();
|
|
304
|
+
},
|
|
305
|
+
getPendingApprovals(sessionId) {
|
|
306
|
+
return getDb().select().from(toolExecutions).where(
|
|
307
|
+
and(
|
|
308
|
+
eq(toolExecutions.sessionId, sessionId),
|
|
309
|
+
eq(toolExecutions.status, "pending"),
|
|
310
|
+
eq(toolExecutions.requiresApproval, true)
|
|
311
|
+
)
|
|
312
|
+
).all();
|
|
313
|
+
},
|
|
314
|
+
approve(id) {
|
|
315
|
+
return getDb().update(toolExecutions).set({ status: "approved" }).where(eq(toolExecutions.id, id)).returning().get();
|
|
316
|
+
},
|
|
317
|
+
reject(id) {
|
|
318
|
+
return getDb().update(toolExecutions).set({ status: "rejected" }).where(eq(toolExecutions.id, id)).returning().get();
|
|
319
|
+
},
|
|
320
|
+
complete(id, output, error) {
|
|
321
|
+
return getDb().update(toolExecutions).set({
|
|
322
|
+
status: error ? "error" : "completed",
|
|
323
|
+
output,
|
|
324
|
+
error,
|
|
325
|
+
completedAt: /* @__PURE__ */ new Date()
|
|
326
|
+
}).where(eq(toolExecutions.id, id)).returning().get();
|
|
327
|
+
},
|
|
328
|
+
getBySession(sessionId) {
|
|
329
|
+
return getDb().select().from(toolExecutions).where(eq(toolExecutions.sessionId, sessionId)).orderBy(toolExecutions.startedAt).all();
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
var todoQueries = {
|
|
333
|
+
create(data) {
|
|
334
|
+
const id = nanoid();
|
|
335
|
+
const now = /* @__PURE__ */ new Date();
|
|
336
|
+
const result = getDb().insert(todoItems).values({
|
|
337
|
+
id,
|
|
338
|
+
...data,
|
|
339
|
+
createdAt: now,
|
|
340
|
+
updatedAt: now
|
|
341
|
+
}).returning().get();
|
|
342
|
+
return result;
|
|
343
|
+
},
|
|
344
|
+
createMany(sessionId, items) {
|
|
345
|
+
const now = /* @__PURE__ */ new Date();
|
|
346
|
+
const values = items.map((item, index) => ({
|
|
347
|
+
id: nanoid(),
|
|
348
|
+
sessionId,
|
|
349
|
+
content: item.content,
|
|
350
|
+
order: item.order ?? index,
|
|
351
|
+
createdAt: now,
|
|
352
|
+
updatedAt: now
|
|
353
|
+
}));
|
|
354
|
+
return getDb().insert(todoItems).values(values).returning().all();
|
|
355
|
+
},
|
|
356
|
+
getBySession(sessionId) {
|
|
357
|
+
return getDb().select().from(todoItems).where(eq(todoItems.sessionId, sessionId)).orderBy(todoItems.order).all();
|
|
358
|
+
},
|
|
359
|
+
updateStatus(id, status) {
|
|
360
|
+
return getDb().update(todoItems).set({ status, updatedAt: /* @__PURE__ */ new Date() }).where(eq(todoItems.id, id)).returning().get();
|
|
361
|
+
},
|
|
362
|
+
delete(id) {
|
|
363
|
+
const result = getDb().delete(todoItems).where(eq(todoItems.id, id)).run();
|
|
364
|
+
return result.changes > 0;
|
|
365
|
+
},
|
|
366
|
+
clearSession(sessionId) {
|
|
367
|
+
const result = getDb().delete(todoItems).where(eq(todoItems.sessionId, sessionId)).run();
|
|
368
|
+
return result.changes;
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
var skillQueries = {
|
|
372
|
+
load(sessionId, skillName) {
|
|
373
|
+
const id = nanoid();
|
|
374
|
+
const result = getDb().insert(loadedSkills).values({
|
|
375
|
+
id,
|
|
376
|
+
sessionId,
|
|
377
|
+
skillName,
|
|
378
|
+
loadedAt: /* @__PURE__ */ new Date()
|
|
379
|
+
}).returning().get();
|
|
380
|
+
return result;
|
|
381
|
+
},
|
|
382
|
+
getBySession(sessionId) {
|
|
383
|
+
return getDb().select().from(loadedSkills).where(eq(loadedSkills.sessionId, sessionId)).orderBy(loadedSkills.loadedAt).all();
|
|
384
|
+
},
|
|
385
|
+
isLoaded(sessionId, skillName) {
|
|
386
|
+
const result = getDb().select().from(loadedSkills).where(
|
|
387
|
+
and(
|
|
388
|
+
eq(loadedSkills.sessionId, sessionId),
|
|
389
|
+
eq(loadedSkills.skillName, skillName)
|
|
390
|
+
)
|
|
391
|
+
).get();
|
|
392
|
+
return !!result;
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
var terminalQueries = {
|
|
396
|
+
create(data) {
|
|
397
|
+
const id = nanoid();
|
|
398
|
+
const result = getDb().insert(terminals).values({
|
|
399
|
+
id,
|
|
400
|
+
...data,
|
|
401
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
402
|
+
}).returning().get();
|
|
403
|
+
return result;
|
|
404
|
+
},
|
|
405
|
+
getById(id) {
|
|
406
|
+
return getDb().select().from(terminals).where(eq(terminals.id, id)).get();
|
|
407
|
+
},
|
|
408
|
+
getBySession(sessionId) {
|
|
409
|
+
return getDb().select().from(terminals).where(eq(terminals.sessionId, sessionId)).orderBy(desc(terminals.createdAt)).all();
|
|
410
|
+
},
|
|
411
|
+
getRunning(sessionId) {
|
|
412
|
+
return getDb().select().from(terminals).where(
|
|
413
|
+
and(
|
|
414
|
+
eq(terminals.sessionId, sessionId),
|
|
415
|
+
eq(terminals.status, "running")
|
|
416
|
+
)
|
|
417
|
+
).all();
|
|
418
|
+
},
|
|
419
|
+
updateStatus(id, status, exitCode, error) {
|
|
420
|
+
return getDb().update(terminals).set({
|
|
421
|
+
status,
|
|
422
|
+
exitCode,
|
|
423
|
+
error,
|
|
424
|
+
stoppedAt: status !== "running" ? /* @__PURE__ */ new Date() : void 0
|
|
425
|
+
}).where(eq(terminals.id, id)).returning().get();
|
|
426
|
+
},
|
|
427
|
+
updatePid(id, pid) {
|
|
428
|
+
return getDb().update(terminals).set({ pid }).where(eq(terminals.id, id)).returning().get();
|
|
429
|
+
},
|
|
430
|
+
delete(id) {
|
|
431
|
+
const result = getDb().delete(terminals).where(eq(terminals.id, id)).run();
|
|
432
|
+
return result.changes > 0;
|
|
433
|
+
},
|
|
434
|
+
deleteBySession(sessionId) {
|
|
435
|
+
const result = getDb().delete(terminals).where(eq(terminals.sessionId, sessionId)).run();
|
|
436
|
+
return result.changes;
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
export {
|
|
440
|
+
closeDatabase,
|
|
441
|
+
getDb,
|
|
442
|
+
initDatabase,
|
|
443
|
+
messageQueries,
|
|
444
|
+
sessionQueries,
|
|
445
|
+
skillQueries,
|
|
446
|
+
terminalQueries,
|
|
447
|
+
todoQueries,
|
|
448
|
+
toolExecutionQueries
|
|
449
|
+
};
|
|
450
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/db/index.ts","../../src/db/schema.ts"],"sourcesContent":["import Database from 'better-sqlite3';\nimport { drizzle } from 'drizzle-orm/better-sqlite3';\nimport { eq, desc, and, sql } from 'drizzle-orm';\nimport { nanoid } from 'nanoid';\nimport * as schema from './schema.js';\nimport type {\n Session,\n NewSession,\n Message,\n NewMessage,\n ToolExecution,\n NewToolExecution,\n TodoItem,\n NewTodoItem,\n SessionConfig,\n ModelMessage,\n Terminal,\n NewTerminal,\n} from './schema.js';\n\nlet db: ReturnType<typeof drizzle<typeof schema>> | null = null;\nlet sqlite: Database.Database | null = null;\n\nexport function initDatabase(dbPath: string) {\n sqlite = new Database(dbPath);\n sqlite.pragma('journal_mode = WAL');\n db = drizzle(sqlite, { schema });\n\n // Drop and recreate tables with new schema\n sqlite.exec(`\n DROP TABLE IF EXISTS terminals;\n DROP TABLE IF EXISTS loaded_skills;\n DROP TABLE IF EXISTS todo_items;\n DROP TABLE IF EXISTS tool_executions;\n DROP TABLE IF EXISTS messages;\n DROP TABLE IF EXISTS sessions;\n\n CREATE TABLE sessions (\n id TEXT PRIMARY KEY,\n name TEXT,\n working_directory TEXT NOT NULL,\n model TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'active',\n config TEXT,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n );\n\n CREATE TABLE messages (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,\n model_message TEXT NOT NULL,\n sequence INTEGER NOT NULL DEFAULT 0,\n created_at INTEGER NOT NULL\n );\n\n CREATE TABLE tool_executions (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,\n message_id TEXT REFERENCES messages(id) ON DELETE CASCADE,\n tool_name TEXT NOT NULL,\n tool_call_id TEXT NOT NULL,\n input TEXT,\n output TEXT,\n status TEXT NOT NULL DEFAULT 'pending',\n requires_approval INTEGER NOT NULL DEFAULT 0,\n error TEXT,\n started_at INTEGER NOT NULL,\n completed_at INTEGER\n );\n\n CREATE TABLE todo_items (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,\n content TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'pending',\n \"order\" INTEGER NOT NULL DEFAULT 0,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n );\n\n CREATE TABLE loaded_skills (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,\n skill_name TEXT NOT NULL,\n loaded_at INTEGER NOT NULL\n );\n\n CREATE TABLE terminals (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,\n name TEXT,\n command TEXT NOT NULL,\n cwd TEXT NOT NULL,\n pid INTEGER,\n status TEXT NOT NULL DEFAULT 'running',\n exit_code INTEGER,\n error TEXT,\n created_at INTEGER NOT NULL,\n stopped_at INTEGER\n );\n\n CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id);\n CREATE INDEX IF NOT EXISTS idx_tool_executions_session ON tool_executions(session_id);\n CREATE INDEX IF NOT EXISTS idx_todo_items_session ON todo_items(session_id);\n CREATE INDEX IF NOT EXISTS idx_loaded_skills_session ON loaded_skills(session_id);\n CREATE INDEX IF NOT EXISTS idx_terminals_session ON terminals(session_id);\n `);\n\n return db;\n}\n\nexport function getDb() {\n if (!db) {\n throw new Error('Database not initialized. Call initDatabase first.');\n }\n return db;\n}\n\nexport function closeDatabase() {\n if (sqlite) {\n sqlite.close();\n sqlite = null;\n db = null;\n }\n}\n\n// Session queries\nexport const sessionQueries = {\n create(data: Omit<NewSession, 'id' | 'createdAt' | 'updatedAt'>): Session {\n const id = nanoid();\n const now = new Date();\n const result = getDb()\n .insert(schema.sessions)\n .values({\n id,\n ...data,\n createdAt: now,\n updatedAt: now,\n })\n .returning()\n .get();\n return result;\n },\n\n getById(id: string): Session | undefined {\n return getDb().select().from(schema.sessions).where(eq(schema.sessions.id, id)).get();\n },\n\n list(limit = 50, offset = 0): Session[] {\n return getDb()\n .select()\n .from(schema.sessions)\n .orderBy(desc(schema.sessions.createdAt))\n .limit(limit)\n .offset(offset)\n .all();\n },\n\n updateStatus(id: string, status: Session['status']): Session | undefined {\n return getDb()\n .update(schema.sessions)\n .set({ status, updatedAt: new Date() })\n .where(eq(schema.sessions.id, id))\n .returning()\n .get();\n },\n\n delete(id: string): boolean {\n const result = getDb().delete(schema.sessions).where(eq(schema.sessions.id, id)).run();\n return result.changes > 0;\n },\n};\n\n// Message queries - stores AI SDK ModelMessage directly\nexport const messageQueries = {\n /**\n * Get the next sequence number for a session\n */\n getNextSequence(sessionId: string): number {\n const result = getDb()\n .select({ maxSeq: sql<number>`COALESCE(MAX(sequence), -1)` })\n .from(schema.messages)\n .where(eq(schema.messages.sessionId, sessionId))\n .get();\n return (result?.maxSeq ?? -1) + 1;\n },\n\n /**\n * Create a single message from a ModelMessage\n */\n create(sessionId: string, modelMessage: ModelMessage): Message {\n const id = nanoid();\n const sequence = this.getNextSequence(sessionId);\n const result = getDb()\n .insert(schema.messages)\n .values({\n id,\n sessionId,\n modelMessage,\n sequence,\n createdAt: new Date(),\n })\n .returning()\n .get();\n return result;\n },\n\n /**\n * Add multiple ModelMessages at once (from response.messages)\n * Maintains insertion order via sequence numbers\n */\n addMany(sessionId: string, modelMessages: ModelMessage[]): Message[] {\n const results: Message[] = [];\n let sequence = this.getNextSequence(sessionId);\n for (const msg of modelMessages) {\n const id = nanoid();\n const result = getDb()\n .insert(schema.messages)\n .values({\n id,\n sessionId,\n modelMessage: msg,\n sequence,\n createdAt: new Date(),\n })\n .returning()\n .get();\n results.push(result);\n sequence++;\n }\n return results;\n },\n\n /**\n * Get all messages for a session as ModelMessage[]\n * Ordered by sequence to maintain exact insertion order\n */\n getBySession(sessionId: string): Message[] {\n return getDb()\n .select()\n .from(schema.messages)\n .where(eq(schema.messages.sessionId, sessionId))\n .orderBy(schema.messages.sequence)\n .all();\n },\n\n /**\n * Get ModelMessages directly (for passing to AI SDK)\n */\n getModelMessages(sessionId: string): ModelMessage[] {\n const messages = this.getBySession(sessionId);\n return messages.map(m => m.modelMessage);\n },\n\n getRecentBySession(sessionId: string, limit = 50): Message[] {\n return getDb()\n .select()\n .from(schema.messages)\n .where(eq(schema.messages.sessionId, sessionId))\n .orderBy(desc(schema.messages.sequence))\n .limit(limit)\n .all()\n .reverse();\n },\n\n countBySession(sessionId: string): number {\n const result = getDb()\n .select({ count: sql<number>`count(*)` })\n .from(schema.messages)\n .where(eq(schema.messages.sessionId, sessionId))\n .get();\n return result?.count ?? 0;\n },\n\n deleteBySession(sessionId: string): number {\n const result = getDb()\n .delete(schema.messages)\n .where(eq(schema.messages.sessionId, sessionId))\n .run();\n return result.changes;\n },\n};\n\n// Tool execution queries\nexport const toolExecutionQueries = {\n create(data: Omit<NewToolExecution, 'id' | 'startedAt'>): ToolExecution {\n const id = nanoid();\n const result = getDb()\n .insert(schema.toolExecutions)\n .values({\n id,\n ...data,\n startedAt: new Date(),\n })\n .returning()\n .get();\n return result;\n },\n\n getById(id: string): ToolExecution | undefined {\n return getDb()\n .select()\n .from(schema.toolExecutions)\n .where(eq(schema.toolExecutions.id, id))\n .get();\n },\n\n getByToolCallId(toolCallId: string): ToolExecution | undefined {\n return getDb()\n .select()\n .from(schema.toolExecutions)\n .where(eq(schema.toolExecutions.toolCallId, toolCallId))\n .get();\n },\n\n getPendingApprovals(sessionId: string): ToolExecution[] {\n return getDb()\n .select()\n .from(schema.toolExecutions)\n .where(\n and(\n eq(schema.toolExecutions.sessionId, sessionId),\n eq(schema.toolExecutions.status, 'pending'),\n eq(schema.toolExecutions.requiresApproval, true)\n )\n )\n .all();\n },\n\n approve(id: string): ToolExecution | undefined {\n return getDb()\n .update(schema.toolExecutions)\n .set({ status: 'approved' })\n .where(eq(schema.toolExecutions.id, id))\n .returning()\n .get();\n },\n\n reject(id: string): ToolExecution | undefined {\n return getDb()\n .update(schema.toolExecutions)\n .set({ status: 'rejected' })\n .where(eq(schema.toolExecutions.id, id))\n .returning()\n .get();\n },\n\n complete(\n id: string,\n output: unknown,\n error?: string\n ): ToolExecution | undefined {\n return getDb()\n .update(schema.toolExecutions)\n .set({\n status: error ? 'error' : 'completed',\n output: output as any,\n error,\n completedAt: new Date(),\n })\n .where(eq(schema.toolExecutions.id, id))\n .returning()\n .get();\n },\n\n getBySession(sessionId: string): ToolExecution[] {\n return getDb()\n .select()\n .from(schema.toolExecutions)\n .where(eq(schema.toolExecutions.sessionId, sessionId))\n .orderBy(schema.toolExecutions.startedAt)\n .all();\n },\n};\n\n// Todo item queries\nexport const todoQueries = {\n create(data: Omit<NewTodoItem, 'id' | 'createdAt' | 'updatedAt'>): TodoItem {\n const id = nanoid();\n const now = new Date();\n const result = getDb()\n .insert(schema.todoItems)\n .values({\n id,\n ...data,\n createdAt: now,\n updatedAt: now,\n })\n .returning()\n .get();\n return result;\n },\n\n createMany(\n sessionId: string,\n items: Array<{ content: string; order?: number }>\n ): TodoItem[] {\n const now = new Date();\n const values = items.map((item, index) => ({\n id: nanoid(),\n sessionId,\n content: item.content,\n order: item.order ?? index,\n createdAt: now,\n updatedAt: now,\n }));\n\n return getDb().insert(schema.todoItems).values(values).returning().all();\n },\n\n getBySession(sessionId: string): TodoItem[] {\n return getDb()\n .select()\n .from(schema.todoItems)\n .where(eq(schema.todoItems.sessionId, sessionId))\n .orderBy(schema.todoItems.order)\n .all();\n },\n\n updateStatus(\n id: string,\n status: TodoItem['status']\n ): TodoItem | undefined {\n return getDb()\n .update(schema.todoItems)\n .set({ status, updatedAt: new Date() })\n .where(eq(schema.todoItems.id, id))\n .returning()\n .get();\n },\n\n delete(id: string): boolean {\n const result = getDb()\n .delete(schema.todoItems)\n .where(eq(schema.todoItems.id, id))\n .run();\n return result.changes > 0;\n },\n\n clearSession(sessionId: string): number {\n const result = getDb()\n .delete(schema.todoItems)\n .where(eq(schema.todoItems.sessionId, sessionId))\n .run();\n return result.changes;\n },\n};\n\n// Loaded skills queries\nexport const skillQueries = {\n load(sessionId: string, skillName: string): schema.LoadedSkill {\n const id = nanoid();\n const result = getDb()\n .insert(schema.loadedSkills)\n .values({\n id,\n sessionId,\n skillName,\n loadedAt: new Date(),\n })\n .returning()\n .get();\n return result;\n },\n\n getBySession(sessionId: string): schema.LoadedSkill[] {\n return getDb()\n .select()\n .from(schema.loadedSkills)\n .where(eq(schema.loadedSkills.sessionId, sessionId))\n .orderBy(schema.loadedSkills.loadedAt)\n .all();\n },\n\n isLoaded(sessionId: string, skillName: string): boolean {\n const result = getDb()\n .select()\n .from(schema.loadedSkills)\n .where(\n and(\n eq(schema.loadedSkills.sessionId, sessionId),\n eq(schema.loadedSkills.skillName, skillName)\n )\n )\n .get();\n return !!result;\n },\n};\n\n// Terminal queries\nexport const terminalQueries = {\n create(data: Omit<NewTerminal, 'id' | 'createdAt'>): Terminal {\n const id = nanoid();\n const result = getDb()\n .insert(schema.terminals)\n .values({\n id,\n ...data,\n createdAt: new Date(),\n })\n .returning()\n .get();\n return result;\n },\n\n getById(id: string): Terminal | undefined {\n return getDb()\n .select()\n .from(schema.terminals)\n .where(eq(schema.terminals.id, id))\n .get();\n },\n\n getBySession(sessionId: string): Terminal[] {\n return getDb()\n .select()\n .from(schema.terminals)\n .where(eq(schema.terminals.sessionId, sessionId))\n .orderBy(desc(schema.terminals.createdAt))\n .all();\n },\n\n getRunning(sessionId: string): Terminal[] {\n return getDb()\n .select()\n .from(schema.terminals)\n .where(\n and(\n eq(schema.terminals.sessionId, sessionId),\n eq(schema.terminals.status, 'running')\n )\n )\n .all();\n },\n\n updateStatus(\n id: string,\n status: Terminal['status'],\n exitCode?: number,\n error?: string\n ): Terminal | undefined {\n return getDb()\n .update(schema.terminals)\n .set({\n status,\n exitCode,\n error,\n stoppedAt: status !== 'running' ? new Date() : undefined,\n })\n .where(eq(schema.terminals.id, id))\n .returning()\n .get();\n },\n\n updatePid(id: string, pid: number): Terminal | undefined {\n return getDb()\n .update(schema.terminals)\n .set({ pid })\n .where(eq(schema.terminals.id, id))\n .returning()\n .get();\n },\n\n delete(id: string): boolean {\n const result = getDb()\n .delete(schema.terminals)\n .where(eq(schema.terminals.id, id))\n .run();\n return result.changes > 0;\n },\n\n deleteBySession(sessionId: string): number {\n const result = getDb()\n .delete(schema.terminals)\n .where(eq(schema.terminals.sessionId, sessionId))\n .run();\n return result.changes;\n },\n};\n\nexport type { \n Session, \n Message, \n ToolExecution, \n TodoItem, \n SessionConfig, \n ModelMessage,\n Terminal,\n};\n","import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';\n\n// Sessions table - represents an agent session/thread\nexport const sessions = sqliteTable('sessions', {\n id: text('id').primaryKey(),\n name: text('name'),\n workingDirectory: text('working_directory').notNull(),\n model: text('model').notNull(),\n status: text('status', { enum: ['active', 'waiting', 'completed', 'error'] })\n .notNull()\n .default('active'),\n config: text('config', { mode: 'json' }).$type<SessionConfig>(),\n createdAt: integer('created_at', { mode: 'timestamp' })\n .notNull()\n .$defaultFn(() => new Date()),\n updatedAt: integer('updated_at', { mode: 'timestamp' })\n .notNull()\n .$defaultFn(() => new Date()),\n});\n\n// Messages table - stores AI SDK ModelMessage directly\nexport const messages = sqliteTable('messages', {\n id: text('id').primaryKey(),\n sessionId: text('session_id')\n .notNull()\n .references(() => sessions.id, { onDelete: 'cascade' }),\n // Store the entire ModelMessage as JSON (role + content)\n modelMessage: text('model_message', { mode: 'json' }).$type<ModelMessage>().notNull(),\n // Sequence number within session to maintain exact ordering\n sequence: integer('sequence').notNull().default(0),\n createdAt: integer('created_at', { mode: 'timestamp' })\n .notNull()\n .$defaultFn(() => new Date()),\n});\n\n// Tool executions - tracks all tool calls and their results\nexport const toolExecutions = sqliteTable('tool_executions', {\n id: text('id').primaryKey(),\n sessionId: text('session_id')\n .notNull()\n .references(() => sessions.id, { onDelete: 'cascade' }),\n messageId: text('message_id').references(() => messages.id, { onDelete: 'cascade' }),\n toolName: text('tool_name').notNull(),\n toolCallId: text('tool_call_id').notNull(),\n input: text('input', { mode: 'json' }),\n output: text('output', { mode: 'json' }),\n status: text('status', { enum: ['pending', 'approved', 'rejected', 'completed', 'error'] })\n .notNull()\n .default('pending'),\n requiresApproval: integer('requires_approval', { mode: 'boolean' }).notNull().default(false),\n error: text('error'),\n startedAt: integer('started_at', { mode: 'timestamp' })\n .notNull()\n .$defaultFn(() => new Date()),\n completedAt: integer('completed_at', { mode: 'timestamp' }),\n});\n\n// Todo items for the planning tool\nexport const todoItems = sqliteTable('todo_items', {\n id: text('id').primaryKey(),\n sessionId: text('session_id')\n .notNull()\n .references(() => sessions.id, { onDelete: 'cascade' }),\n content: text('content').notNull(),\n status: text('status', { enum: ['pending', 'in_progress', 'completed', 'cancelled'] })\n .notNull()\n .default('pending'),\n order: integer('order').notNull().default(0),\n createdAt: integer('created_at', { mode: 'timestamp' })\n .notNull()\n .$defaultFn(() => new Date()),\n updatedAt: integer('updated_at', { mode: 'timestamp' })\n .notNull()\n .$defaultFn(() => new Date()),\n});\n\n// Skills loaded into sessions\nexport const loadedSkills = sqliteTable('loaded_skills', {\n id: text('id').primaryKey(),\n sessionId: text('session_id')\n .notNull()\n .references(() => sessions.id, { onDelete: 'cascade' }),\n skillName: text('skill_name').notNull(),\n loadedAt: integer('loaded_at', { mode: 'timestamp' })\n .notNull()\n .$defaultFn(() => new Date()),\n});\n\n// Terminal sessions - background processes managed by agents\nexport const terminals = sqliteTable('terminals', {\n id: text('id').primaryKey(),\n sessionId: text('session_id')\n .notNull()\n .references(() => sessions.id, { onDelete: 'cascade' }),\n name: text('name'), // Optional friendly name (e.g., \"dev-server\")\n command: text('command').notNull(), // The command that was run\n cwd: text('cwd').notNull(), // Working directory\n pid: integer('pid'), // Process ID (null if not running)\n status: text('status', { enum: ['running', 'stopped', 'error'] })\n .notNull()\n .default('running'),\n exitCode: integer('exit_code'), // Exit code if stopped\n error: text('error'), // Error message if status is 'error'\n createdAt: integer('created_at', { mode: 'timestamp' })\n .notNull()\n .$defaultFn(() => new Date()),\n stoppedAt: integer('stopped_at', { mode: 'timestamp' }),\n});\n\n// Types for JSON columns\nexport interface SessionConfig {\n toolApprovals?: Record<string, boolean>;\n approvalWebhook?: string;\n skillsDirectory?: string;\n maxContextChars?: number;\n}\n\n// AI SDK ModelMessage types - stored directly for accurate context passing\n// These match the exact format from AI SDK's response.messages\nexport type ModelMessage = \n | SystemModelMessage\n | UserModelMessage\n | AssistantModelMessage\n | ToolModelMessage;\n\nexport interface SystemModelMessage {\n role: 'system';\n content: string;\n}\n\nexport interface UserModelMessage {\n role: 'user';\n content: string;\n}\n\nexport interface AssistantModelMessage {\n role: 'assistant';\n content: string | AssistantContentPart[];\n}\n\nexport interface ToolModelMessage {\n role: 'tool';\n content: ToolResultPart[];\n}\n\nexport interface AssistantContentPart {\n type: 'text' | 'tool-call';\n text?: string;\n toolCallId?: string;\n toolName?: string;\n input?: unknown;\n}\n\nexport interface ToolResultPart {\n type: 'tool-result';\n toolCallId: string;\n toolName: string;\n output: unknown;\n}\n\n// Type exports for queries\nexport type Session = typeof sessions.$inferSelect;\nexport type NewSession = typeof sessions.$inferInsert;\nexport type Message = typeof messages.$inferSelect;\nexport type NewMessage = typeof messages.$inferInsert;\nexport type ToolExecution = typeof toolExecutions.$inferSelect;\nexport type NewToolExecution = typeof toolExecutions.$inferInsert;\nexport type TodoItem = typeof todoItems.$inferSelect;\nexport type NewTodoItem = typeof todoItems.$inferInsert;\nexport type LoadedSkill = typeof loadedSkills.$inferSelect;\nexport type Terminal = typeof terminals.$inferSelect;\nexport type NewTerminal = typeof terminals.$inferInsert;"],"mappings":"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","names":["messages"]}
|