@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.
@@ -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 };