ai-hist 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/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # ai-hist (TypeScript SDK)
2
+
3
+ Thin TypeScript SDK for the [ai-hist](../README.md) SQLite database. Reads the same file the Python `ai-hist sync` tool writes — this package never writes, sync stays the Python tool's job.
4
+
5
+ Built to let Electron / Node consumers (e.g. the `pear` desktop app) render a Codex/Claude-style "previous conversations" list backed by your local ai-hist history.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install ai-hist
11
+ ```
12
+
13
+ `better-sqlite3` is a native dep — when bundling into an Electron app, run `electron-rebuild` (or your bundler's equivalent) after install.
14
+
15
+ ## Quick start
16
+
17
+ ```ts
18
+ import { AiHist, resumeCommand } from 'ai-hist';
19
+
20
+ const hist = new AiHist(); // uses $AI_HIST_DB or ~/.local/share/ai-hist/ai-history.db
21
+ try {
22
+ const sessions = hist.listSessions({ limit: 20 });
23
+ for (const s of sessions) {
24
+ console.log(`[${s.source}] ${s.firstPrompt.slice(0, 60)} (${s.promptCount} prompts)`);
25
+ console.log(' resume:', resumeCommand(s));
26
+ }
27
+ } finally {
28
+ hist.close();
29
+ }
30
+ ```
31
+
32
+ ## API
33
+
34
+ ```ts
35
+ new AiHist(opts?: { dbPath?: string }) // readonly open
36
+ hist.close()
37
+ hist.dbPath: string
38
+
39
+ hist.recent(opts?): HistoryEntry[] // newest prompts first
40
+ hist.listSessions(opts?): SessionSummary[] // grouped by session_id, last-activity DESC
41
+ hist.getSession(sessionId): HistoryEntry[] // all prompts in a session, oldest first
42
+ hist.search(query, opts?): HistoryEntry[] // FTS5 query, recent matches first
43
+ hist.stats(): Stats // counts + date range
44
+ ```
45
+
46
+ All list-style methods accept `{ source?, project?, limit?, beforeMs? }`. `beforeMs` is the cursor for paginating older results.
47
+
48
+ ```ts
49
+ resumeCommand(entry): string | null // shell command per source; null for relay
50
+ defaultDbPath(): string // resolve env / OS default
51
+ ```
52
+
53
+ ## Schema (canonical, owned by the Python tool)
54
+
55
+ ```sql
56
+ CREATE TABLE history (
57
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
58
+ source TEXT NOT NULL, -- 'claude' | 'codex' | 'cursor' | 'relay'
59
+ session_id TEXT,
60
+ project TEXT,
61
+ prompt TEXT NOT NULL,
62
+ timestamp_ms INTEGER NOT NULL,
63
+ UNIQUE(source, timestamp_ms, prompt)
64
+ );
65
+
66
+ CREATE VIRTUAL TABLE history_fts USING fts5(prompt, project, content='history', content_rowid='id');
67
+ ```
68
+
69
+ If the Python sync tool's schema changes, bump this SDK's major version. Consumers pin the SDK version they were built against.
70
+
71
+ ## License
72
+
73
+ MIT
@@ -0,0 +1,102 @@
1
+ /**
2
+ * TypeScript SDK for reading the ai-hist SQLite database.
3
+ *
4
+ * Backed by sql.js (WASM SQLite) so the package has zero native build
5
+ * requirements — works in Electron, Node, and browser contexts without
6
+ * needing electron-rebuild. The SDK reads the same file the Python CLI
7
+ * maintains (default `~/.local/share/ai-hist/ai-history.db`, or
8
+ * `$AI_HIST_DB`); the Python tool stays the canonical sync engine.
9
+ *
10
+ * Trade-off vs better-sqlite3: sql.js loads the whole DB file into
11
+ * memory. Fine for the ai-hist scale (tens of thousands of rows, MBs
12
+ * of data); revisit if anyone hits millions.
13
+ */
14
+ import { type Database } from 'sql.js';
15
+ export type Source = 'claude' | 'codex' | 'cursor' | 'relay';
16
+ export interface HistoryEntry {
17
+ id: number;
18
+ source: Source;
19
+ sessionId: string | null;
20
+ project: string | null;
21
+ prompt: string;
22
+ timestampMs: number;
23
+ }
24
+ export interface SessionSummary {
25
+ sessionId: string;
26
+ source: Source;
27
+ project: string | null;
28
+ firstPrompt: string;
29
+ lastActivityMs: number;
30
+ firstActivityMs: number;
31
+ promptCount: number;
32
+ }
33
+ export interface ListOptions {
34
+ source?: Source;
35
+ project?: string;
36
+ /** Default 50. */
37
+ limit?: number;
38
+ /**
39
+ * Paginate older than this timestamp (exclusive). Use the
40
+ * `lastActivityMs` / `timestampMs` of the last item from the previous page.
41
+ */
42
+ beforeMs?: number;
43
+ }
44
+ export type SearchOptions = ListOptions;
45
+ export interface Stats {
46
+ total: number;
47
+ bySource: Partial<Record<Source, number>>;
48
+ byProject: Array<{
49
+ project: string;
50
+ count: number;
51
+ }>;
52
+ firstTimestampMs: number | null;
53
+ lastTimestampMs: number | null;
54
+ }
55
+ /** Resolve the SQLite path the Python CLI writes to. */
56
+ export declare function defaultDbPath(): string;
57
+ /**
58
+ * Open an `AiHist` reader. Async because sql.js initializes its WASM
59
+ * runtime lazily. Each call reads the DB file from disk; the resulting
60
+ * instance is a snapshot — to see new prompts written by the Python sync,
61
+ * call `reload()` (or open a fresh instance).
62
+ */
63
+ export declare function openAiHist(opts?: {
64
+ dbPath?: string;
65
+ }): Promise<AiHist>;
66
+ export declare class AiHist {
67
+ private readonly db;
68
+ private readonly _dbPath;
69
+ private closed;
70
+ /** @internal — use `openAiHist({ dbPath })` to construct. */
71
+ constructor(db: Database, dbPath: string);
72
+ get dbPath(): string;
73
+ close(): void;
74
+ /** Most recent prompts, newest first. */
75
+ recent(opts?: ListOptions): HistoryEntry[];
76
+ /**
77
+ * Group history into sessions, ordered by last activity (newest first).
78
+ * Sessions without a `session_id` are skipped.
79
+ */
80
+ listSessions(opts?: ListOptions): SessionSummary[];
81
+ /** All prompts in a session, ordered oldest → newest. */
82
+ getSession(sessionId: string): HistoryEntry[];
83
+ /**
84
+ * Substring search across prompt + project, case-insensitive, recent
85
+ * matches first. The Python CLI uses FTS5; this SDK uses LIKE because
86
+ * sql.js's default WASM build doesn't ship the FTS5 module. Plenty fast
87
+ * for the ai-hist scale (~tens of thousands of rows); revisit if a
88
+ * future consumer needs phrase/boolean queries.
89
+ *
90
+ * The query is matched literally — `%` and `_` are escaped so users can
91
+ * search for them. Empty queries return an empty array.
92
+ */
93
+ search(query: string, opts?: SearchOptions): HistoryEntry[];
94
+ /** Counts + date range, mirroring `ai-hist stats`. */
95
+ stats(): Stats;
96
+ }
97
+ /**
98
+ * Resume command for an entry/session, matching what `ai-hist show` prints.
99
+ * Returns `null` for sources that don't have a resume affordance (relay).
100
+ */
101
+ export declare function resumeCommand(entry: Pick<HistoryEntry, 'source' | 'sessionId' | 'project'>): string | null;
102
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAkB,EAAE,KAAK,QAAQ,EAAoB,MAAM,QAAQ,CAAC;AAKpE,MAAM,MAAM,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,aAAa,GAAG,WAAW,CAAC;AAExC,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1C,SAAS,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,wDAAwD;AACxD,wBAAgB,aAAa,IAAI,MAAM,CAItC;AAUD;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBhF;AAyDD,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAW;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,MAAM,CAAS;IAEvB,6DAA6D;gBACjD,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM;IAKxC,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,KAAK,IAAI,IAAI;IAMb,yCAAyC;IACzC,MAAM,CAAC,IAAI,GAAE,WAAgB,GAAG,YAAY,EAAE;IAc9C;;;OAGG;IACH,YAAY,CAAC,IAAI,GAAE,WAAgB,GAAG,cAAc,EAAE;IAsDtD,yDAAyD;IACzD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,EAAE;IAW7C;;;;;;;;;OASG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,aAAkB,GAAG,YAAY,EAAE;IAiC/D,sDAAsD;IACtD,KAAK,IAAI,KAAK;CAgCf;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAC,GAC5D,MAAM,GAAG,IAAI,CAkBf"}
package/dist/index.js ADDED
@@ -0,0 +1,267 @@
1
+ /**
2
+ * TypeScript SDK for reading the ai-hist SQLite database.
3
+ *
4
+ * Backed by sql.js (WASM SQLite) so the package has zero native build
5
+ * requirements — works in Electron, Node, and browser contexts without
6
+ * needing electron-rebuild. The SDK reads the same file the Python CLI
7
+ * maintains (default `~/.local/share/ai-hist/ai-history.db`, or
8
+ * `$AI_HIST_DB`); the Python tool stays the canonical sync engine.
9
+ *
10
+ * Trade-off vs better-sqlite3: sql.js loads the whole DB file into
11
+ * memory. Fine for the ai-hist scale (tens of thousands of rows, MBs
12
+ * of data); revisit if anyone hits millions.
13
+ */
14
+ import initSqlJs from 'sql.js';
15
+ import { readFileSync, statSync } from 'node:fs';
16
+ import { homedir } from 'node:os';
17
+ import { join } from 'node:path';
18
+ /** Resolve the SQLite path the Python CLI writes to. */
19
+ export function defaultDbPath() {
20
+ const fromEnv = process.env.AI_HIST_DB;
21
+ if (fromEnv && fromEnv.trim().length > 0)
22
+ return fromEnv;
23
+ return join(homedir(), '.local', 'share', 'ai-hist', 'ai-history.db');
24
+ }
25
+ let _sqlPromise = null;
26
+ function getSqlJs() {
27
+ if (!_sqlPromise) {
28
+ _sqlPromise = initSqlJs();
29
+ }
30
+ return _sqlPromise;
31
+ }
32
+ /**
33
+ * Open an `AiHist` reader. Async because sql.js initializes its WASM
34
+ * runtime lazily. Each call reads the DB file from disk; the resulting
35
+ * instance is a snapshot — to see new prompts written by the Python sync,
36
+ * call `reload()` (or open a fresh instance).
37
+ */
38
+ export async function openAiHist(opts = {}) {
39
+ const dbPath = opts.dbPath ?? defaultDbPath();
40
+ // Surface a clearer error than sql.js's bare "file not found" when the
41
+ // user hasn't run the Python sync at least once yet.
42
+ try {
43
+ statSync(dbPath);
44
+ }
45
+ catch {
46
+ throw new Error(`ai-hist database not found at ${dbPath}. Run \`ai-hist sync\` first ` +
47
+ `(see https://github.com/khaliqgant/ai-hist).`);
48
+ }
49
+ const SQL = await getSqlJs();
50
+ const fileBuffer = readFileSync(dbPath);
51
+ const db = new SQL.Database(fileBuffer);
52
+ return new AiHist(db, dbPath);
53
+ }
54
+ function rowToEntry(row) {
55
+ return {
56
+ id: row.id,
57
+ source: row.source,
58
+ sessionId: row.session_id,
59
+ project: row.project,
60
+ prompt: row.prompt,
61
+ timestampMs: row.timestamp_ms,
62
+ };
63
+ }
64
+ function buildFilters(opts) {
65
+ const clauses = [];
66
+ const params = [];
67
+ if (opts.source) {
68
+ clauses.push('source = ?');
69
+ params.push(opts.source);
70
+ }
71
+ if (opts.project) {
72
+ clauses.push('project = ?');
73
+ params.push(opts.project);
74
+ }
75
+ if (typeof opts.beforeMs === 'number') {
76
+ clauses.push('timestamp_ms < ?');
77
+ params.push(opts.beforeMs);
78
+ }
79
+ return {
80
+ sql: clauses.length > 0 ? ` AND ${clauses.join(' AND ')}` : '',
81
+ params,
82
+ };
83
+ }
84
+ function runQuery(db, sql, params) {
85
+ const stmt = db.prepare(sql);
86
+ try {
87
+ stmt.bind(params);
88
+ const rows = [];
89
+ while (stmt.step()) {
90
+ rows.push(stmt.getAsObject());
91
+ }
92
+ return rows;
93
+ }
94
+ finally {
95
+ stmt.free();
96
+ }
97
+ }
98
+ export class AiHist {
99
+ db;
100
+ _dbPath;
101
+ closed = false;
102
+ /** @internal — use `openAiHist({ dbPath })` to construct. */
103
+ constructor(db, dbPath) {
104
+ this.db = db;
105
+ this._dbPath = dbPath;
106
+ }
107
+ get dbPath() {
108
+ return this._dbPath;
109
+ }
110
+ close() {
111
+ if (this.closed)
112
+ return;
113
+ this.db.close();
114
+ this.closed = true;
115
+ }
116
+ /** Most recent prompts, newest first. */
117
+ recent(opts = {}) {
118
+ const limit = opts.limit ?? 50;
119
+ const { sql, params } = buildFilters(opts);
120
+ return runQuery(this.db, `SELECT id, source, session_id, project, prompt, timestamp_ms
121
+ FROM history
122
+ WHERE 1=1${sql}
123
+ ORDER BY timestamp_ms DESC
124
+ LIMIT ?`, [...params, limit]).map(rowToEntry);
125
+ }
126
+ /**
127
+ * Group history into sessions, ordered by last activity (newest first).
128
+ * Sessions without a `session_id` are skipped.
129
+ */
130
+ listSessions(opts = {}) {
131
+ const limit = opts.limit ?? 50;
132
+ const { sql, params } = buildFilters(opts);
133
+ const rows = runQuery(this.db, `WITH filtered AS (
134
+ SELECT id, source, session_id, project, prompt, timestamp_ms
135
+ FROM history
136
+ WHERE session_id IS NOT NULL AND session_id != ''${sql}
137
+ )
138
+ SELECT
139
+ session_id,
140
+ source,
141
+ project,
142
+ prompt_count,
143
+ first_activity_ms,
144
+ last_activity_ms,
145
+ (SELECT prompt FROM filtered f2
146
+ WHERE f2.session_id = grouped.session_id
147
+ ORDER BY f2.timestamp_ms ASC LIMIT 1) AS first_prompt
148
+ FROM (
149
+ SELECT
150
+ session_id,
151
+ source,
152
+ project,
153
+ COUNT(*) AS prompt_count,
154
+ MIN(timestamp_ms) AS first_activity_ms,
155
+ MAX(timestamp_ms) AS last_activity_ms
156
+ FROM filtered
157
+ GROUP BY session_id, source, project
158
+ ) AS grouped
159
+ ORDER BY last_activity_ms DESC
160
+ LIMIT ?`, [...params, limit]);
161
+ return rows.map((row) => ({
162
+ sessionId: row.session_id,
163
+ source: row.source,
164
+ project: row.project,
165
+ firstPrompt: row.first_prompt,
166
+ lastActivityMs: row.last_activity_ms,
167
+ firstActivityMs: row.first_activity_ms,
168
+ promptCount: row.prompt_count,
169
+ }));
170
+ }
171
+ /** All prompts in a session, ordered oldest → newest. */
172
+ getSession(sessionId) {
173
+ return runQuery(this.db, `SELECT id, source, session_id, project, prompt, timestamp_ms
174
+ FROM history
175
+ WHERE session_id = ?
176
+ ORDER BY timestamp_ms ASC`, [sessionId]).map(rowToEntry);
177
+ }
178
+ /**
179
+ * Substring search across prompt + project, case-insensitive, recent
180
+ * matches first. The Python CLI uses FTS5; this SDK uses LIKE because
181
+ * sql.js's default WASM build doesn't ship the FTS5 module. Plenty fast
182
+ * for the ai-hist scale (~tens of thousands of rows); revisit if a
183
+ * future consumer needs phrase/boolean queries.
184
+ *
185
+ * The query is matched literally — `%` and `_` are escaped so users can
186
+ * search for them. Empty queries return an empty array.
187
+ */
188
+ search(query, opts = {}) {
189
+ const trimmed = query.trim();
190
+ if (!trimmed)
191
+ return [];
192
+ const limit = opts.limit ?? 50;
193
+ const escaped = trimmed.replace(/\\/g, '\\\\').replace(/%/g, '\\%').replace(/_/g, '\\_');
194
+ const pattern = `%${escaped}%`;
195
+ const clauses = [
196
+ `(LOWER(prompt) LIKE LOWER(?) ESCAPE '\\' OR LOWER(COALESCE(project, '')) LIKE LOWER(?) ESCAPE '\\')`,
197
+ ];
198
+ const params = [pattern, pattern];
199
+ if (opts.source) {
200
+ clauses.push('source = ?');
201
+ params.push(opts.source);
202
+ }
203
+ if (opts.project) {
204
+ clauses.push('project = ?');
205
+ params.push(opts.project);
206
+ }
207
+ if (typeof opts.beforeMs === 'number') {
208
+ clauses.push('timestamp_ms < ?');
209
+ params.push(opts.beforeMs);
210
+ }
211
+ return runQuery(this.db, `SELECT id, source, session_id, project, prompt, timestamp_ms
212
+ FROM history
213
+ WHERE ${clauses.join(' AND ')}
214
+ ORDER BY timestamp_ms DESC
215
+ LIMIT ?`, [...params, limit]).map(rowToEntry);
216
+ }
217
+ /** Counts + date range, mirroring `ai-hist stats`. */
218
+ stats() {
219
+ const total = runQuery(this.db, 'SELECT COUNT(*) AS c FROM history', [])[0]?.c ?? 0;
220
+ const bySourceRows = runQuery(this.db, 'SELECT source, COUNT(*) AS c FROM history GROUP BY source', []);
221
+ const bySource = {};
222
+ for (const row of bySourceRows) {
223
+ bySource[row.source] = row.c;
224
+ }
225
+ const byProject = runQuery(this.db, `SELECT project, COUNT(*) AS c FROM history
226
+ WHERE project IS NOT NULL AND project != ''
227
+ GROUP BY project ORDER BY c DESC LIMIT 10`, []).map((row) => ({ project: row.project, count: row.c }));
228
+ const range = runQuery(this.db, 'SELECT MIN(timestamp_ms) AS mn, MAX(timestamp_ms) AS mx FROM history', [])[0];
229
+ return {
230
+ total,
231
+ bySource,
232
+ byProject,
233
+ firstTimestampMs: range?.mn ?? null,
234
+ lastTimestampMs: range?.mx ?? null,
235
+ };
236
+ }
237
+ }
238
+ /**
239
+ * Resume command for an entry/session, matching what `ai-hist show` prints.
240
+ * Returns `null` for sources that don't have a resume affordance (relay).
241
+ */
242
+ export function resumeCommand(entry) {
243
+ if (!entry.sessionId)
244
+ return null;
245
+ switch (entry.source) {
246
+ case 'claude':
247
+ return entry.project
248
+ ? `cd ${shellQuote(entry.project)} && claude --resume ${shellQuote(entry.sessionId)}`
249
+ : `claude --resume ${shellQuote(entry.sessionId)}`;
250
+ case 'codex':
251
+ return `codex resume ${shellQuote(entry.sessionId)}`;
252
+ case 'cursor':
253
+ return entry.project
254
+ ? `cd ${shellQuote(entry.project)} && cursor-agent --resume=${shellQuote(entry.sessionId)}`
255
+ : `cursor-agent --resume=${shellQuote(entry.sessionId)}`;
256
+ case 'relay':
257
+ return null;
258
+ default:
259
+ return null;
260
+ }
261
+ }
262
+ function shellQuote(value) {
263
+ if (/^[A-Za-z0-9_\-./]+$/.test(value))
264
+ return value;
265
+ return `'${value.replace(/'/g, `'\\''`)}'`;
266
+ }
267
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "ai-hist",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript SDK for reading the ai-hist SQLite database (recent prompts, sessions, search).",
5
+ "license": "MIT",
6
+ "private": false,
7
+ "type": "module",
8
+ "main": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "./package.json": "./package.json"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "package.json"
21
+ ],
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/AgentWorkforce/ai-hist",
25
+ "directory": "sdk-ts"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "scripts": {
31
+ "build": "tsc -p tsconfig.json",
32
+ "dev": "tsc -p tsconfig.json --watch --preserveWatchOutput",
33
+ "typecheck": "tsc -p tsconfig.json --noEmit",
34
+ "test": "tsc -p tsconfig.json && node --test dist/*.test.js",
35
+ "lint": "tsc -p tsconfig.json --noEmit",
36
+ "prepare": "npm run build"
37
+ },
38
+ "dependencies": {
39
+ "sql.js": "^1.13.0"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^22.18.0",
43
+ "@types/sql.js": "^1.4.9",
44
+ "typescript": "^5.9.2"
45
+ },
46
+ "engines": {
47
+ "node": ">=18"
48
+ }
49
+ }