@maintainer-pro/ai-cli 0.1.0
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/db-entry.cjs +388 -0
- package/dist/db-entry.d.cts +43 -0
- package/dist/db-entry.d.ts +43 -0
- package/dist/db-entry.js +238 -0
- package/dist/index.cjs +1117 -0
- package/dist/index.d.cts +239 -0
- package/dist/index.d.ts +239 -0
- package/dist/index.js +1057 -0
- package/dist/mysql-EKKUF6CP.js +34 -0
- package/dist/pg-QSUOKTP3.js +33 -0
- package/dist/sqlite-6L33HVYQ.js +28 -0
- package/drizzle/mysql/0001_init.sql +24 -0
- package/drizzle/postgres/0001_init.sql +26 -0
- package/drizzle/sqlite/0001_init.sql +26 -0
- package/package.json +64 -0
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
11
|
+
var __export = (target, all) => {
|
|
12
|
+
for (var name in all)
|
|
13
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
|
+
};
|
|
15
|
+
var __copyProps = (to, from, except, desc) => {
|
|
16
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
17
|
+
for (let key of __getOwnPropNames(from))
|
|
18
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
19
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
24
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
25
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
26
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
27
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
28
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
29
|
+
mod
|
|
30
|
+
));
|
|
31
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
|
+
|
|
33
|
+
// src/db/schema/pg.ts
|
|
34
|
+
var pg_exports = {};
|
|
35
|
+
__export(pg_exports, {
|
|
36
|
+
conversations: () => conversations,
|
|
37
|
+
messages: () => messages,
|
|
38
|
+
toolEvents: () => toolEvents
|
|
39
|
+
});
|
|
40
|
+
var import_pg_core, conversations, messages, toolEvents;
|
|
41
|
+
var init_pg = __esm({
|
|
42
|
+
"src/db/schema/pg.ts"() {
|
|
43
|
+
"use strict";
|
|
44
|
+
import_pg_core = require("drizzle-orm/pg-core");
|
|
45
|
+
conversations = (0, import_pg_core.pgTable)("ai_cli_conversations", {
|
|
46
|
+
id: (0, import_pg_core.text)("id").primaryKey(),
|
|
47
|
+
createdAt: (0, import_pg_core.timestamp)("created_at", { withTimezone: true }).defaultNow().notNull(),
|
|
48
|
+
updatedAt: (0, import_pg_core.timestamp)("updated_at", { withTimezone: true }).defaultNow().notNull()
|
|
49
|
+
});
|
|
50
|
+
messages = (0, import_pg_core.pgTable)("ai_cli_messages", {
|
|
51
|
+
id: (0, import_pg_core.uuid)("id").defaultRandom().primaryKey(),
|
|
52
|
+
conversationId: (0, import_pg_core.text)("conversation_id").notNull().references(() => conversations.id, { onDelete: "cascade" }),
|
|
53
|
+
role: (0, import_pg_core.text)("role").notNull(),
|
|
54
|
+
content: (0, import_pg_core.text)("content").notNull(),
|
|
55
|
+
provider: (0, import_pg_core.text)("provider"),
|
|
56
|
+
createdAt: (0, import_pg_core.timestamp)("created_at", { withTimezone: true }).defaultNow().notNull()
|
|
57
|
+
});
|
|
58
|
+
toolEvents = (0, import_pg_core.pgTable)("ai_cli_tool_events", {
|
|
59
|
+
id: (0, import_pg_core.uuid)("id").defaultRandom().primaryKey(),
|
|
60
|
+
conversationId: (0, import_pg_core.text)("conversation_id").notNull().references(() => conversations.id, { onDelete: "cascade" }),
|
|
61
|
+
tool: (0, import_pg_core.text)("tool").notNull(),
|
|
62
|
+
args: (0, import_pg_core.jsonb)("args").$type().notNull(),
|
|
63
|
+
createdAt: (0, import_pg_core.timestamp)("created_at", { withTimezone: true }).defaultNow().notNull()
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// src/db/schema/mysql.ts
|
|
69
|
+
var mysql_exports = {};
|
|
70
|
+
__export(mysql_exports, {
|
|
71
|
+
conversations: () => conversations2,
|
|
72
|
+
messages: () => messages2,
|
|
73
|
+
toolEvents: () => toolEvents2
|
|
74
|
+
});
|
|
75
|
+
var import_mysql_core, import_drizzle_orm, conversations2, messages2, toolEvents2;
|
|
76
|
+
var init_mysql = __esm({
|
|
77
|
+
"src/db/schema/mysql.ts"() {
|
|
78
|
+
"use strict";
|
|
79
|
+
import_mysql_core = require("drizzle-orm/mysql-core");
|
|
80
|
+
import_drizzle_orm = require("drizzle-orm");
|
|
81
|
+
conversations2 = (0, import_mysql_core.mysqlTable)("ai_cli_conversations", {
|
|
82
|
+
id: (0, import_mysql_core.varchar)("id", { length: 128 }).primaryKey(),
|
|
83
|
+
createdAt: (0, import_mysql_core.timestamp)("created_at").default(import_drizzle_orm.sql`CURRENT_TIMESTAMP`).notNull(),
|
|
84
|
+
updatedAt: (0, import_mysql_core.timestamp)("updated_at").default(import_drizzle_orm.sql`CURRENT_TIMESTAMP`).notNull()
|
|
85
|
+
});
|
|
86
|
+
messages2 = (0, import_mysql_core.mysqlTable)("ai_cli_messages", {
|
|
87
|
+
id: (0, import_mysql_core.varchar)("id", { length: 36 }).primaryKey(),
|
|
88
|
+
conversationId: (0, import_mysql_core.varchar)("conversation_id", { length: 128 }).notNull(),
|
|
89
|
+
role: (0, import_mysql_core.varchar)("role", { length: 32 }).notNull(),
|
|
90
|
+
content: (0, import_mysql_core.text)("content").notNull(),
|
|
91
|
+
provider: (0, import_mysql_core.varchar)("provider", { length: 64 }),
|
|
92
|
+
createdAt: (0, import_mysql_core.timestamp)("created_at").default(import_drizzle_orm.sql`CURRENT_TIMESTAMP`).notNull()
|
|
93
|
+
});
|
|
94
|
+
toolEvents2 = (0, import_mysql_core.mysqlTable)("ai_cli_tool_events", {
|
|
95
|
+
id: (0, import_mysql_core.varchar)("id", { length: 36 }).primaryKey(),
|
|
96
|
+
conversationId: (0, import_mysql_core.varchar)("conversation_id", { length: 128 }).notNull(),
|
|
97
|
+
tool: (0, import_mysql_core.varchar)("tool", { length: 128 }).notNull(),
|
|
98
|
+
args: (0, import_mysql_core.json)("args").$type().notNull(),
|
|
99
|
+
createdAt: (0, import_mysql_core.timestamp)("created_at").default(import_drizzle_orm.sql`CURRENT_TIMESTAMP`).notNull()
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// src/db/schema/sqlite.ts
|
|
105
|
+
var sqlite_exports = {};
|
|
106
|
+
__export(sqlite_exports, {
|
|
107
|
+
conversations: () => conversations3,
|
|
108
|
+
messages: () => messages3,
|
|
109
|
+
toolEvents: () => toolEvents3
|
|
110
|
+
});
|
|
111
|
+
var import_sqlite_core, import_drizzle_orm2, conversations3, messages3, toolEvents3;
|
|
112
|
+
var init_sqlite = __esm({
|
|
113
|
+
"src/db/schema/sqlite.ts"() {
|
|
114
|
+
"use strict";
|
|
115
|
+
import_sqlite_core = require("drizzle-orm/sqlite-core");
|
|
116
|
+
import_drizzle_orm2 = require("drizzle-orm");
|
|
117
|
+
conversations3 = (0, import_sqlite_core.sqliteTable)("ai_cli_conversations", {
|
|
118
|
+
id: (0, import_sqlite_core.text)("id").primaryKey(),
|
|
119
|
+
createdAt: (0, import_sqlite_core.integer)("created_at", { mode: "timestamp_ms" }).default(import_drizzle_orm2.sql`(unixepoch() * 1000)`).notNull(),
|
|
120
|
+
updatedAt: (0, import_sqlite_core.integer)("updated_at", { mode: "timestamp_ms" }).default(import_drizzle_orm2.sql`(unixepoch() * 1000)`).notNull()
|
|
121
|
+
});
|
|
122
|
+
messages3 = (0, import_sqlite_core.sqliteTable)("ai_cli_messages", {
|
|
123
|
+
id: (0, import_sqlite_core.text)("id").primaryKey(),
|
|
124
|
+
conversationId: (0, import_sqlite_core.text)("conversation_id").notNull(),
|
|
125
|
+
role: (0, import_sqlite_core.text)("role").notNull(),
|
|
126
|
+
content: (0, import_sqlite_core.text)("content").notNull(),
|
|
127
|
+
provider: (0, import_sqlite_core.text)("provider"),
|
|
128
|
+
createdAt: (0, import_sqlite_core.integer)("created_at", { mode: "timestamp_ms" }).default(import_drizzle_orm2.sql`(unixepoch() * 1000)`).notNull()
|
|
129
|
+
});
|
|
130
|
+
toolEvents3 = (0, import_sqlite_core.sqliteTable)("ai_cli_tool_events", {
|
|
131
|
+
id: (0, import_sqlite_core.text)("id").primaryKey(),
|
|
132
|
+
conversationId: (0, import_sqlite_core.text)("conversation_id").notNull(),
|
|
133
|
+
tool: (0, import_sqlite_core.text)("tool").notNull(),
|
|
134
|
+
args: (0, import_sqlite_core.text)("args", { mode: "json" }).$type().notNull(),
|
|
135
|
+
createdAt: (0, import_sqlite_core.integer)("created_at", { mode: "timestamp_ms" }).default(import_drizzle_orm2.sql`(unixepoch() * 1000)`).notNull()
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// src/db-entry.ts
|
|
141
|
+
var db_entry_exports = {};
|
|
142
|
+
__export(db_entry_exports, {
|
|
143
|
+
createAiCliDb: () => createAiCliDb,
|
|
144
|
+
createAiCliDbFromEnv: () => createAiCliDbFromEnv,
|
|
145
|
+
runMigrations: () => runMigrations,
|
|
146
|
+
runMigrationsFromEnv: () => runMigrationsFromEnv
|
|
147
|
+
});
|
|
148
|
+
module.exports = __toCommonJS(db_entry_exports);
|
|
149
|
+
|
|
150
|
+
// src/db/client.ts
|
|
151
|
+
var import_node_crypto = require("crypto");
|
|
152
|
+
var import_drizzle_orm3 = require("drizzle-orm");
|
|
153
|
+
function toStored(row) {
|
|
154
|
+
return {
|
|
155
|
+
id: row.id,
|
|
156
|
+
conversationId: row.conversationId,
|
|
157
|
+
role: row.role,
|
|
158
|
+
content: row.content,
|
|
159
|
+
provider: row.provider,
|
|
160
|
+
createdAt: row.createdAt instanceof Date ? row.createdAt : new Date(row.createdAt)
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
async function createPostgresStore(url) {
|
|
164
|
+
const { drizzle } = await import("drizzle-orm/postgres-js");
|
|
165
|
+
const postgres = (await import("postgres")).default;
|
|
166
|
+
const schema = await Promise.resolve().then(() => (init_pg(), pg_exports));
|
|
167
|
+
const client = postgres(url);
|
|
168
|
+
const db = drizzle(client, { schema });
|
|
169
|
+
return {
|
|
170
|
+
async ensureConversation(id) {
|
|
171
|
+
await db.insert(schema.conversations).values({ id }).onConflictDoNothing();
|
|
172
|
+
},
|
|
173
|
+
async saveMessage(input) {
|
|
174
|
+
const [row] = await db.insert(schema.messages).values({
|
|
175
|
+
conversationId: input.conversationId,
|
|
176
|
+
role: input.role,
|
|
177
|
+
content: input.content,
|
|
178
|
+
provider: input.provider
|
|
179
|
+
}).returning();
|
|
180
|
+
return toStored(row);
|
|
181
|
+
},
|
|
182
|
+
async listMessages(conversationId) {
|
|
183
|
+
const rows = await db.select().from(schema.messages).where((0, import_drizzle_orm3.eq)(schema.messages.conversationId, conversationId));
|
|
184
|
+
return rows.map(toStored);
|
|
185
|
+
},
|
|
186
|
+
async saveToolEvents(conversationId, events) {
|
|
187
|
+
if (events.length === 0) return;
|
|
188
|
+
await db.insert(schema.toolEvents).values(
|
|
189
|
+
events.map((e) => ({
|
|
190
|
+
conversationId,
|
|
191
|
+
tool: e.tool,
|
|
192
|
+
args: e.args
|
|
193
|
+
}))
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
async function createMysqlStore(url) {
|
|
199
|
+
const { drizzle } = await import("drizzle-orm/mysql2");
|
|
200
|
+
const mysql = await import("mysql2/promise");
|
|
201
|
+
const schema = await Promise.resolve().then(() => (init_mysql(), mysql_exports));
|
|
202
|
+
const pool = mysql.createPool(url);
|
|
203
|
+
const db = drizzle(pool, { schema, mode: "default" });
|
|
204
|
+
return {
|
|
205
|
+
async ensureConversation(id) {
|
|
206
|
+
await db.insert(schema.conversations).values({ id }).onDuplicateKeyUpdate({
|
|
207
|
+
set: { updatedAt: /* @__PURE__ */ new Date() }
|
|
208
|
+
});
|
|
209
|
+
},
|
|
210
|
+
async saveMessage(input) {
|
|
211
|
+
const id = (0, import_node_crypto.randomUUID)();
|
|
212
|
+
await db.insert(schema.messages).values({
|
|
213
|
+
id,
|
|
214
|
+
conversationId: input.conversationId,
|
|
215
|
+
role: input.role,
|
|
216
|
+
content: input.content,
|
|
217
|
+
provider: input.provider ?? null
|
|
218
|
+
});
|
|
219
|
+
return {
|
|
220
|
+
id,
|
|
221
|
+
conversationId: input.conversationId,
|
|
222
|
+
role: input.role,
|
|
223
|
+
content: input.content,
|
|
224
|
+
provider: input.provider ?? null,
|
|
225
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
226
|
+
};
|
|
227
|
+
},
|
|
228
|
+
async listMessages(conversationId) {
|
|
229
|
+
const rows = await db.select().from(schema.messages).where((0, import_drizzle_orm3.eq)(schema.messages.conversationId, conversationId));
|
|
230
|
+
return rows.map(
|
|
231
|
+
(row) => toStored({
|
|
232
|
+
...row,
|
|
233
|
+
provider: row.provider ?? null
|
|
234
|
+
})
|
|
235
|
+
);
|
|
236
|
+
},
|
|
237
|
+
async saveToolEvents(conversationId, events) {
|
|
238
|
+
if (events.length === 0) return;
|
|
239
|
+
await db.insert(schema.toolEvents).values(
|
|
240
|
+
events.map((e) => ({
|
|
241
|
+
id: (0, import_node_crypto.randomUUID)(),
|
|
242
|
+
conversationId,
|
|
243
|
+
tool: e.tool,
|
|
244
|
+
args: e.args
|
|
245
|
+
}))
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
async function createSqliteStore(url) {
|
|
251
|
+
const { drizzle } = await import("drizzle-orm/better-sqlite3");
|
|
252
|
+
const Database = (await import("better-sqlite3")).default;
|
|
253
|
+
const schema = await Promise.resolve().then(() => (init_sqlite(), sqlite_exports));
|
|
254
|
+
const file = url.replace(/^file:/, "");
|
|
255
|
+
const sqlite = new Database(file);
|
|
256
|
+
const db = drizzle(sqlite, { schema });
|
|
257
|
+
return {
|
|
258
|
+
async ensureConversation(id) {
|
|
259
|
+
await db.insert(schema.conversations).values({ id }).onConflictDoNothing();
|
|
260
|
+
},
|
|
261
|
+
async saveMessage(input) {
|
|
262
|
+
const id = (0, import_node_crypto.randomUUID)();
|
|
263
|
+
const [row] = await db.insert(schema.messages).values({
|
|
264
|
+
id,
|
|
265
|
+
conversationId: input.conversationId,
|
|
266
|
+
role: input.role,
|
|
267
|
+
content: input.content,
|
|
268
|
+
provider: input.provider ?? null
|
|
269
|
+
}).returning();
|
|
270
|
+
return toStored({
|
|
271
|
+
...row,
|
|
272
|
+
provider: row.provider ?? null
|
|
273
|
+
});
|
|
274
|
+
},
|
|
275
|
+
async listMessages(conversationId) {
|
|
276
|
+
const rows = await db.select().from(schema.messages).where((0, import_drizzle_orm3.eq)(schema.messages.conversationId, conversationId));
|
|
277
|
+
return rows.map(
|
|
278
|
+
(row) => toStored({
|
|
279
|
+
...row,
|
|
280
|
+
provider: row.provider ?? null
|
|
281
|
+
})
|
|
282
|
+
);
|
|
283
|
+
},
|
|
284
|
+
async saveToolEvents(conversationId, events) {
|
|
285
|
+
if (events.length === 0) return;
|
|
286
|
+
await db.insert(schema.toolEvents).values(
|
|
287
|
+
events.map((e) => ({
|
|
288
|
+
id: (0, import_node_crypto.randomUUID)(),
|
|
289
|
+
conversationId,
|
|
290
|
+
tool: e.tool,
|
|
291
|
+
args: e.args
|
|
292
|
+
}))
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
async function createAiCliDb(options) {
|
|
298
|
+
switch (options.dialect) {
|
|
299
|
+
case "postgres":
|
|
300
|
+
return createPostgresStore(options.url);
|
|
301
|
+
case "mysql":
|
|
302
|
+
return createMysqlStore(options.url);
|
|
303
|
+
case "sqlite":
|
|
304
|
+
return createSqliteStore(options.url);
|
|
305
|
+
default:
|
|
306
|
+
throw new Error(`Unsupported dialect: ${options.dialect}`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
function createAiCliDbFromEnv() {
|
|
310
|
+
const url = process.env.AI_CLI_DB_URL?.trim();
|
|
311
|
+
const dialect = process.env.AI_CLI_DB_DIALECT?.trim();
|
|
312
|
+
if (!url || !dialect) return null;
|
|
313
|
+
if (dialect !== "postgres" && dialect !== "mysql" && dialect !== "sqlite") {
|
|
314
|
+
throw new Error(
|
|
315
|
+
`Invalid AI_CLI_DB_DIALECT="${dialect}". Use postgres|mysql|sqlite.`
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
return createAiCliDb({ dialect, url });
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// src/db/migrate.ts
|
|
322
|
+
var import_node_fs = __toESM(require("fs"), 1);
|
|
323
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
324
|
+
function migrationsDir() {
|
|
325
|
+
const candidates = [
|
|
326
|
+
import_node_path.default.join(__dirname, "..", "drizzle"),
|
|
327
|
+
import_node_path.default.join(process.cwd(), "drizzle"),
|
|
328
|
+
import_node_path.default.join(process.cwd(), "packages", "ai-cli", "drizzle")
|
|
329
|
+
];
|
|
330
|
+
for (const dir of candidates) {
|
|
331
|
+
if (import_node_fs.default.existsSync(dir)) return dir;
|
|
332
|
+
}
|
|
333
|
+
throw new Error("Could not locate ai-cli drizzle migrations folder");
|
|
334
|
+
}
|
|
335
|
+
async function runMigrations(options) {
|
|
336
|
+
const sqlPath = import_node_path.default.join(migrationsDir(), options.dialect, "0001_init.sql");
|
|
337
|
+
if (!import_node_fs.default.existsSync(sqlPath)) {
|
|
338
|
+
throw new Error(`Migration file missing: ${sqlPath}`);
|
|
339
|
+
}
|
|
340
|
+
const sql3 = import_node_fs.default.readFileSync(sqlPath, "utf8");
|
|
341
|
+
if (options.dialect === "postgres") {
|
|
342
|
+
const postgres = (await import("postgres")).default;
|
|
343
|
+
const client = postgres(options.url, { max: 1 });
|
|
344
|
+
try {
|
|
345
|
+
await client.unsafe(sql3);
|
|
346
|
+
} finally {
|
|
347
|
+
await client.end();
|
|
348
|
+
}
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
if (options.dialect === "mysql") {
|
|
352
|
+
const mysql = await import("mysql2/promise");
|
|
353
|
+
const conn = await mysql.createConnection(options.url);
|
|
354
|
+
try {
|
|
355
|
+
for (const statement of sql3.split(";").map((s) => s.trim()).filter(Boolean)) {
|
|
356
|
+
await conn.query(statement);
|
|
357
|
+
}
|
|
358
|
+
} finally {
|
|
359
|
+
await conn.end();
|
|
360
|
+
}
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
const Database = (await import("better-sqlite3")).default;
|
|
364
|
+
const file = options.url.replace(/^file:/, "");
|
|
365
|
+
const db = new Database(file);
|
|
366
|
+
try {
|
|
367
|
+
db.exec(sql3);
|
|
368
|
+
} finally {
|
|
369
|
+
db.close();
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async function runMigrationsFromEnv() {
|
|
373
|
+
const url = process.env.AI_CLI_DB_URL?.trim();
|
|
374
|
+
const dialect = process.env.AI_CLI_DB_DIALECT?.trim();
|
|
375
|
+
if (!url || !dialect) {
|
|
376
|
+
throw new Error(
|
|
377
|
+
"Set AI_CLI_DB_URL and AI_CLI_DB_DIALECT to run migrations"
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
await runMigrations({ dialect, url });
|
|
381
|
+
}
|
|
382
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
383
|
+
0 && (module.exports = {
|
|
384
|
+
createAiCliDb,
|
|
385
|
+
createAiCliDbFromEnv,
|
|
386
|
+
runMigrations,
|
|
387
|
+
runMigrationsFromEnv
|
|
388
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
type DbDialect = "postgres" | "mysql" | "sqlite";
|
|
2
|
+
interface SaveMessageInput {
|
|
3
|
+
conversationId: string;
|
|
4
|
+
role: "user" | "assistant" | "system";
|
|
5
|
+
content: string;
|
|
6
|
+
provider?: string;
|
|
7
|
+
}
|
|
8
|
+
interface StoredMessage {
|
|
9
|
+
id: string;
|
|
10
|
+
conversationId: string;
|
|
11
|
+
role: string;
|
|
12
|
+
content: string;
|
|
13
|
+
provider: string | null;
|
|
14
|
+
createdAt: Date;
|
|
15
|
+
}
|
|
16
|
+
interface ToolEventInput {
|
|
17
|
+
tool: string;
|
|
18
|
+
args: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
/** Persistence API used by createChatHandler. */
|
|
21
|
+
interface AiCliStore {
|
|
22
|
+
ensureConversation(id: string): Promise<void>;
|
|
23
|
+
saveMessage(input: SaveMessageInput): Promise<StoredMessage>;
|
|
24
|
+
listMessages(conversationId: string): Promise<StoredMessage[]>;
|
|
25
|
+
saveToolEvents?(conversationId: string, events: ToolEventInput[]): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
interface CreateAiCliDbOptions {
|
|
28
|
+
dialect: DbDialect;
|
|
29
|
+
/** Connection URL, or file path for sqlite (e.g. file:./ai-cli.db). */
|
|
30
|
+
url: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
declare function createAiCliDb(options: CreateAiCliDbOptions): Promise<AiCliStore>;
|
|
34
|
+
declare function createAiCliDbFromEnv(): Promise<AiCliStore> | null;
|
|
35
|
+
|
|
36
|
+
/** Apply SQL migrations for the selected dialect. */
|
|
37
|
+
declare function runMigrations(options: {
|
|
38
|
+
dialect: DbDialect;
|
|
39
|
+
url: string;
|
|
40
|
+
}): Promise<void>;
|
|
41
|
+
declare function runMigrationsFromEnv(): Promise<void>;
|
|
42
|
+
|
|
43
|
+
export { type AiCliStore, type CreateAiCliDbOptions, type DbDialect, type SaveMessageInput, type StoredMessage, type ToolEventInput, createAiCliDb, createAiCliDbFromEnv, runMigrations, runMigrationsFromEnv };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
type DbDialect = "postgres" | "mysql" | "sqlite";
|
|
2
|
+
interface SaveMessageInput {
|
|
3
|
+
conversationId: string;
|
|
4
|
+
role: "user" | "assistant" | "system";
|
|
5
|
+
content: string;
|
|
6
|
+
provider?: string;
|
|
7
|
+
}
|
|
8
|
+
interface StoredMessage {
|
|
9
|
+
id: string;
|
|
10
|
+
conversationId: string;
|
|
11
|
+
role: string;
|
|
12
|
+
content: string;
|
|
13
|
+
provider: string | null;
|
|
14
|
+
createdAt: Date;
|
|
15
|
+
}
|
|
16
|
+
interface ToolEventInput {
|
|
17
|
+
tool: string;
|
|
18
|
+
args: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
/** Persistence API used by createChatHandler. */
|
|
21
|
+
interface AiCliStore {
|
|
22
|
+
ensureConversation(id: string): Promise<void>;
|
|
23
|
+
saveMessage(input: SaveMessageInput): Promise<StoredMessage>;
|
|
24
|
+
listMessages(conversationId: string): Promise<StoredMessage[]>;
|
|
25
|
+
saveToolEvents?(conversationId: string, events: ToolEventInput[]): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
interface CreateAiCliDbOptions {
|
|
28
|
+
dialect: DbDialect;
|
|
29
|
+
/** Connection URL, or file path for sqlite (e.g. file:./ai-cli.db). */
|
|
30
|
+
url: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
declare function createAiCliDb(options: CreateAiCliDbOptions): Promise<AiCliStore>;
|
|
34
|
+
declare function createAiCliDbFromEnv(): Promise<AiCliStore> | null;
|
|
35
|
+
|
|
36
|
+
/** Apply SQL migrations for the selected dialect. */
|
|
37
|
+
declare function runMigrations(options: {
|
|
38
|
+
dialect: DbDialect;
|
|
39
|
+
url: string;
|
|
40
|
+
}): Promise<void>;
|
|
41
|
+
declare function runMigrationsFromEnv(): Promise<void>;
|
|
42
|
+
|
|
43
|
+
export { type AiCliStore, type CreateAiCliDbOptions, type DbDialect, type SaveMessageInput, type StoredMessage, type ToolEventInput, createAiCliDb, createAiCliDbFromEnv, runMigrations, runMigrationsFromEnv };
|