@sandbox-agent/persist-sqlite 0.2.0 → 0.2.2
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/index.d.ts +0 -1
- package/dist/index.js +2 -4
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { SessionPersistDriver, SessionRecord, ListPageRequest, ListPage, ListEve
|
|
|
2
2
|
|
|
3
3
|
interface SQLiteSessionPersistDriverOptions {
|
|
4
4
|
filename?: string;
|
|
5
|
-
open?: boolean;
|
|
6
5
|
}
|
|
7
6
|
declare class SQLiteSessionPersistDriver implements SessionPersistDriver {
|
|
8
7
|
private readonly db;
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import
|
|
2
|
+
import Database from "better-sqlite3";
|
|
3
3
|
var DEFAULT_LIST_LIMIT = 100;
|
|
4
4
|
var SQLiteSessionPersistDriver = class {
|
|
5
5
|
db;
|
|
6
6
|
constructor(options = {}) {
|
|
7
|
-
this.db = new
|
|
8
|
-
open: options.open ?? true
|
|
9
|
-
});
|
|
7
|
+
this.db = new Database(options.filename ?? ":memory:");
|
|
10
8
|
this.initialize();
|
|
11
9
|
}
|
|
12
10
|
async getSession(id) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { DatabaseSync } from \"node:sqlite\";\nimport type {\n ListEventsRequest,\n ListPage,\n ListPageRequest,\n SessionEvent,\n SessionPersistDriver,\n SessionRecord,\n} from \"sandbox-agent\";\n\nconst DEFAULT_LIST_LIMIT = 100;\n\nexport interface SQLiteSessionPersistDriverOptions {\n filename?: string;\n open?: boolean;\n}\n\nexport class SQLiteSessionPersistDriver implements SessionPersistDriver {\n private readonly db: DatabaseSync;\n\n constructor(options: SQLiteSessionPersistDriverOptions = {}) {\n this.db = new DatabaseSync(options.filename ?? \":memory:\", {\n open: options.open ?? true,\n });\n this.initialize();\n }\n\n async getSession(id: string): Promise<SessionRecord | null> {\n const row = this.db\n .prepare(\n `SELECT id, agent, agent_session_id, last_connection_id, created_at, destroyed_at, session_init_json\n FROM sessions WHERE id = ?`,\n )\n .get(id) as SessionRow | undefined;\n\n if (!row) {\n return null;\n }\n\n return decodeSessionRow(row);\n }\n\n async listSessions(request: ListPageRequest = {}): Promise<ListPage<SessionRecord>> {\n const offset = parseCursor(request.cursor);\n const limit = normalizeLimit(request.limit);\n\n const rows = this.db\n .prepare(\n `SELECT id, agent, agent_session_id, last_connection_id, created_at, destroyed_at, session_init_json\n FROM sessions\n ORDER BY created_at ASC, id ASC\n LIMIT ? OFFSET ?`,\n )\n .all(limit, offset) as SessionRow[];\n\n const countRow = this.db.prepare(`SELECT COUNT(*) as count FROM sessions`).get() as { count: number };\n const nextOffset = offset + rows.length;\n\n return {\n items: rows.map(decodeSessionRow),\n nextCursor: nextOffset < countRow.count ? String(nextOffset) : undefined,\n };\n }\n\n async updateSession(session: SessionRecord): Promise<void> {\n this.db\n .prepare(\n `INSERT INTO sessions (\n id, agent, agent_session_id, last_connection_id, created_at, destroyed_at, session_init_json\n ) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET\n agent = excluded.agent,\n agent_session_id = excluded.agent_session_id,\n last_connection_id = excluded.last_connection_id,\n created_at = excluded.created_at,\n destroyed_at = excluded.destroyed_at,\n session_init_json = excluded.session_init_json`,\n )\n .run(\n session.id,\n session.agent,\n session.agentSessionId,\n session.lastConnectionId,\n session.createdAt,\n session.destroyedAt ?? null,\n session.sessionInit ? JSON.stringify(session.sessionInit) : null,\n );\n }\n\n async listEvents(request: ListEventsRequest): Promise<ListPage<SessionEvent>> {\n const offset = parseCursor(request.cursor);\n const limit = normalizeLimit(request.limit);\n\n const rows = this.db\n .prepare(\n `SELECT id, event_index, session_id, created_at, connection_id, sender, payload_json\n FROM events\n WHERE session_id = ?\n ORDER BY event_index ASC, id ASC\n LIMIT ? OFFSET ?`,\n )\n .all(request.sessionId, limit, offset) as EventRow[];\n\n const countRow = this.db\n .prepare(`SELECT COUNT(*) as count FROM events WHERE session_id = ?`)\n .get(request.sessionId) as { count: number };\n\n const nextOffset = offset + rows.length;\n\n return {\n items: rows.map(decodeEventRow),\n nextCursor: nextOffset < countRow.count ? String(nextOffset) : undefined,\n };\n }\n\n async insertEvent(event: SessionEvent): Promise<void> {\n this.db\n .prepare(\n `INSERT INTO events (\n id, event_index, session_id, created_at, connection_id, sender, payload_json\n ) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET\n event_index = excluded.event_index,\n session_id = excluded.session_id,\n created_at = excluded.created_at,\n connection_id = excluded.connection_id,\n sender = excluded.sender,\n payload_json = excluded.payload_json`,\n )\n .run(\n event.id,\n event.eventIndex,\n event.sessionId,\n event.createdAt,\n event.connectionId,\n event.sender,\n JSON.stringify(event.payload),\n );\n }\n\n close(): void {\n this.db.close();\n }\n\n private initialize(): void {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n agent TEXT NOT NULL,\n agent_session_id TEXT NOT NULL,\n last_connection_id TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n destroyed_at INTEGER,\n session_init_json TEXT\n )\n `);\n\n this.ensureEventsTable();\n }\n\n private ensureEventsTable(): void {\n const tableInfo = this.db.prepare(`PRAGMA table_info(events)`).all() as TableInfoRow[];\n if (tableInfo.length === 0) {\n this.createEventsTable();\n return;\n }\n\n const idColumn = tableInfo.find((column) => column.name === \"id\");\n const hasEventIndex = tableInfo.some((column) => column.name === \"event_index\");\n const idType = (idColumn?.type ?? \"\").trim().toUpperCase();\n const idIsText = idType === \"TEXT\";\n\n if (!idIsText || !hasEventIndex) {\n this.rebuildEventsTable(hasEventIndex);\n }\n\n this.db.exec(`\n CREATE INDEX IF NOT EXISTS idx_events_session_order\n ON events(session_id, event_index, id)\n `);\n }\n\n private createEventsTable(): void {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS events (\n id TEXT PRIMARY KEY,\n event_index INTEGER NOT NULL,\n session_id TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n connection_id TEXT NOT NULL,\n sender TEXT NOT NULL,\n payload_json TEXT NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_events_session_order\n ON events(session_id, event_index, id)\n `);\n }\n\n private rebuildEventsTable(hasEventIndex: boolean): void {\n this.db.exec(`\n ALTER TABLE events RENAME TO events_legacy;\n `);\n\n this.createEventsTable();\n\n if (hasEventIndex) {\n this.db.exec(`\n INSERT INTO events (id, event_index, session_id, created_at, connection_id, sender, payload_json)\n SELECT\n CAST(id AS TEXT),\n COALESCE(event_index, ROW_NUMBER() OVER (PARTITION BY session_id ORDER BY created_at ASC, id ASC)),\n session_id,\n created_at,\n connection_id,\n sender,\n payload_json\n FROM events_legacy\n `);\n } else {\n this.db.exec(`\n INSERT INTO events (id, event_index, session_id, created_at, connection_id, sender, payload_json)\n SELECT\n CAST(id AS TEXT),\n ROW_NUMBER() OVER (PARTITION BY session_id ORDER BY created_at ASC, id ASC),\n session_id,\n created_at,\n connection_id,\n sender,\n payload_json\n FROM events_legacy\n `);\n }\n\n this.db.exec(`DROP TABLE events_legacy`);\n }\n}\n\ntype SessionRow = {\n id: string;\n agent: string;\n agent_session_id: string;\n last_connection_id: string;\n created_at: number;\n destroyed_at: number | null;\n session_init_json: string | null;\n};\n\ntype EventRow = {\n id: string;\n event_index: number;\n session_id: string;\n created_at: number;\n connection_id: string;\n sender: \"client\" | \"agent\";\n payload_json: string;\n};\n\ntype TableInfoRow = {\n name: string;\n type: string;\n};\n\nfunction decodeSessionRow(row: SessionRow): SessionRecord {\n return {\n id: row.id,\n agent: row.agent,\n agentSessionId: row.agent_session_id,\n lastConnectionId: row.last_connection_id,\n createdAt: row.created_at,\n destroyedAt: row.destroyed_at ?? undefined,\n sessionInit: row.session_init_json\n ? (JSON.parse(row.session_init_json) as SessionRecord[\"sessionInit\"])\n : undefined,\n };\n}\n\nfunction decodeEventRow(row: EventRow): SessionEvent {\n return {\n id: row.id,\n eventIndex: row.event_index,\n sessionId: row.session_id,\n createdAt: row.created_at,\n connectionId: row.connection_id,\n sender: row.sender,\n payload: JSON.parse(row.payload_json),\n };\n}\n\nfunction normalizeLimit(limit: number | undefined): number {\n if (!Number.isFinite(limit) || (limit ?? 0) < 1) {\n return DEFAULT_LIST_LIMIT;\n }\n return Math.floor(limit as number);\n}\n\nfunction parseCursor(cursor: string | undefined): number {\n if (!cursor) {\n return 0;\n }\n const parsed = Number.parseInt(cursor, 10);\n if (!Number.isFinite(parsed) || parsed < 0) {\n return 0;\n }\n return parsed;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import Database from \"better-sqlite3\";\nimport type {\n ListEventsRequest,\n ListPage,\n ListPageRequest,\n SessionEvent,\n SessionPersistDriver,\n SessionRecord,\n} from \"sandbox-agent\";\n\nconst DEFAULT_LIST_LIMIT = 100;\n\nexport interface SQLiteSessionPersistDriverOptions {\n filename?: string;\n}\n\nexport class SQLiteSessionPersistDriver implements SessionPersistDriver {\n private readonly db: Database.Database;\n\n constructor(options: SQLiteSessionPersistDriverOptions = {}) {\n this.db = new Database(options.filename ?? \":memory:\");\n this.initialize();\n }\n\n async getSession(id: string): Promise<SessionRecord | null> {\n const row = this.db\n .prepare(\n `SELECT id, agent, agent_session_id, last_connection_id, created_at, destroyed_at, session_init_json\n FROM sessions WHERE id = ?`,\n )\n .get(id) as SessionRow | undefined;\n\n if (!row) {\n return null;\n }\n\n return decodeSessionRow(row);\n }\n\n async listSessions(request: ListPageRequest = {}): Promise<ListPage<SessionRecord>> {\n const offset = parseCursor(request.cursor);\n const limit = normalizeLimit(request.limit);\n\n const rows = this.db\n .prepare(\n `SELECT id, agent, agent_session_id, last_connection_id, created_at, destroyed_at, session_init_json\n FROM sessions\n ORDER BY created_at ASC, id ASC\n LIMIT ? OFFSET ?`,\n )\n .all(limit, offset) as SessionRow[];\n\n const countRow = this.db.prepare(`SELECT COUNT(*) as count FROM sessions`).get() as { count: number };\n const nextOffset = offset + rows.length;\n\n return {\n items: rows.map(decodeSessionRow),\n nextCursor: nextOffset < countRow.count ? String(nextOffset) : undefined,\n };\n }\n\n async updateSession(session: SessionRecord): Promise<void> {\n this.db\n .prepare(\n `INSERT INTO sessions (\n id, agent, agent_session_id, last_connection_id, created_at, destroyed_at, session_init_json\n ) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET\n agent = excluded.agent,\n agent_session_id = excluded.agent_session_id,\n last_connection_id = excluded.last_connection_id,\n created_at = excluded.created_at,\n destroyed_at = excluded.destroyed_at,\n session_init_json = excluded.session_init_json`,\n )\n .run(\n session.id,\n session.agent,\n session.agentSessionId,\n session.lastConnectionId,\n session.createdAt,\n session.destroyedAt ?? null,\n session.sessionInit ? JSON.stringify(session.sessionInit) : null,\n );\n }\n\n async listEvents(request: ListEventsRequest): Promise<ListPage<SessionEvent>> {\n const offset = parseCursor(request.cursor);\n const limit = normalizeLimit(request.limit);\n\n const rows = this.db\n .prepare(\n `SELECT id, event_index, session_id, created_at, connection_id, sender, payload_json\n FROM events\n WHERE session_id = ?\n ORDER BY event_index ASC, id ASC\n LIMIT ? OFFSET ?`,\n )\n .all(request.sessionId, limit, offset) as EventRow[];\n\n const countRow = this.db\n .prepare(`SELECT COUNT(*) as count FROM events WHERE session_id = ?`)\n .get(request.sessionId) as { count: number };\n\n const nextOffset = offset + rows.length;\n\n return {\n items: rows.map(decodeEventRow),\n nextCursor: nextOffset < countRow.count ? String(nextOffset) : undefined,\n };\n }\n\n async insertEvent(event: SessionEvent): Promise<void> {\n this.db\n .prepare(\n `INSERT INTO events (\n id, event_index, session_id, created_at, connection_id, sender, payload_json\n ) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET\n event_index = excluded.event_index,\n session_id = excluded.session_id,\n created_at = excluded.created_at,\n connection_id = excluded.connection_id,\n sender = excluded.sender,\n payload_json = excluded.payload_json`,\n )\n .run(\n event.id,\n event.eventIndex,\n event.sessionId,\n event.createdAt,\n event.connectionId,\n event.sender,\n JSON.stringify(event.payload),\n );\n }\n\n close(): void {\n this.db.close();\n }\n\n private initialize(): void {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n agent TEXT NOT NULL,\n agent_session_id TEXT NOT NULL,\n last_connection_id TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n destroyed_at INTEGER,\n session_init_json TEXT\n )\n `);\n\n this.ensureEventsTable();\n }\n\n private ensureEventsTable(): void {\n const tableInfo = this.db.prepare(`PRAGMA table_info(events)`).all() as TableInfoRow[];\n if (tableInfo.length === 0) {\n this.createEventsTable();\n return;\n }\n\n const idColumn = tableInfo.find((column) => column.name === \"id\");\n const hasEventIndex = tableInfo.some((column) => column.name === \"event_index\");\n const idType = (idColumn?.type ?? \"\").trim().toUpperCase();\n const idIsText = idType === \"TEXT\";\n\n if (!idIsText || !hasEventIndex) {\n this.rebuildEventsTable(hasEventIndex);\n }\n\n this.db.exec(`\n CREATE INDEX IF NOT EXISTS idx_events_session_order\n ON events(session_id, event_index, id)\n `);\n }\n\n private createEventsTable(): void {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS events (\n id TEXT PRIMARY KEY,\n event_index INTEGER NOT NULL,\n session_id TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n connection_id TEXT NOT NULL,\n sender TEXT NOT NULL,\n payload_json TEXT NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_events_session_order\n ON events(session_id, event_index, id)\n `);\n }\n\n private rebuildEventsTable(hasEventIndex: boolean): void {\n this.db.exec(`\n ALTER TABLE events RENAME TO events_legacy;\n `);\n\n this.createEventsTable();\n\n if (hasEventIndex) {\n this.db.exec(`\n INSERT INTO events (id, event_index, session_id, created_at, connection_id, sender, payload_json)\n SELECT\n CAST(id AS TEXT),\n COALESCE(event_index, ROW_NUMBER() OVER (PARTITION BY session_id ORDER BY created_at ASC, id ASC)),\n session_id,\n created_at,\n connection_id,\n sender,\n payload_json\n FROM events_legacy\n `);\n } else {\n this.db.exec(`\n INSERT INTO events (id, event_index, session_id, created_at, connection_id, sender, payload_json)\n SELECT\n CAST(id AS TEXT),\n ROW_NUMBER() OVER (PARTITION BY session_id ORDER BY created_at ASC, id ASC),\n session_id,\n created_at,\n connection_id,\n sender,\n payload_json\n FROM events_legacy\n `);\n }\n\n this.db.exec(`DROP TABLE events_legacy`);\n }\n}\n\ntype SessionRow = {\n id: string;\n agent: string;\n agent_session_id: string;\n last_connection_id: string;\n created_at: number;\n destroyed_at: number | null;\n session_init_json: string | null;\n};\n\ntype EventRow = {\n id: string;\n event_index: number;\n session_id: string;\n created_at: number;\n connection_id: string;\n sender: \"client\" | \"agent\";\n payload_json: string;\n};\n\ntype TableInfoRow = {\n name: string;\n type: string;\n};\n\nfunction decodeSessionRow(row: SessionRow): SessionRecord {\n return {\n id: row.id,\n agent: row.agent,\n agentSessionId: row.agent_session_id,\n lastConnectionId: row.last_connection_id,\n createdAt: row.created_at,\n destroyedAt: row.destroyed_at ?? undefined,\n sessionInit: row.session_init_json\n ? (JSON.parse(row.session_init_json) as SessionRecord[\"sessionInit\"])\n : undefined,\n };\n}\n\nfunction decodeEventRow(row: EventRow): SessionEvent {\n return {\n id: row.id,\n eventIndex: row.event_index,\n sessionId: row.session_id,\n createdAt: row.created_at,\n connectionId: row.connection_id,\n sender: row.sender,\n payload: JSON.parse(row.payload_json),\n };\n}\n\nfunction normalizeLimit(limit: number | undefined): number {\n if (!Number.isFinite(limit) || (limit ?? 0) < 1) {\n return DEFAULT_LIST_LIMIT;\n }\n return Math.floor(limit as number);\n}\n\nfunction parseCursor(cursor: string | undefined): number {\n if (!cursor) {\n return 0;\n }\n const parsed = Number.parseInt(cursor, 10);\n if (!Number.isFinite(parsed) || parsed < 0) {\n return 0;\n }\n return parsed;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sandbox-agent/persist-sqlite",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "SQLite persistence driver for the Sandbox Agent TypeScript SDK",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -17,12 +17,14 @@
|
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"
|
|
20
|
+
"better-sqlite3": "^11.0.0",
|
|
21
|
+
"sandbox-agent": "0.2.2"
|
|
21
22
|
},
|
|
22
23
|
"files": [
|
|
23
24
|
"dist"
|
|
24
25
|
],
|
|
25
26
|
"devDependencies": {
|
|
27
|
+
"@types/better-sqlite3": "^7.0.0",
|
|
26
28
|
"@types/node": "^22.0.0",
|
|
27
29
|
"tsup": "^8.0.0",
|
|
28
30
|
"typescript": "^5.7.0",
|