@witqq/agent-sdk 0.7.0 → 0.9.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/{types-CqvUAYxt.d.ts → agent-C6H2CgJA.d.cts} +139 -102
- package/dist/{types-CqvUAYxt.d.cts → agent-F7oB6eKp.d.ts} +139 -102
- package/dist/auth/index.cjs +72 -1
- package/dist/auth/index.cjs.map +1 -1
- package/dist/auth/index.d.cts +21 -154
- package/dist/auth/index.d.ts +21 -154
- package/dist/auth/index.js +72 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/backends/claude.cjs +480 -261
- package/dist/backends/claude.cjs.map +1 -1
- package/dist/backends/claude.d.cts +3 -1
- package/dist/backends/claude.d.ts +3 -1
- package/dist/backends/claude.js +480 -261
- package/dist/backends/claude.js.map +1 -1
- package/dist/backends/copilot.cjs +337 -112
- package/dist/backends/copilot.cjs.map +1 -1
- package/dist/backends/copilot.d.cts +12 -4
- package/dist/backends/copilot.d.ts +12 -4
- package/dist/backends/copilot.js +337 -112
- package/dist/backends/copilot.js.map +1 -1
- package/dist/backends/mock-llm.cjs +719 -0
- package/dist/backends/mock-llm.cjs.map +1 -0
- package/dist/backends/mock-llm.d.cts +37 -0
- package/dist/backends/mock-llm.d.ts +37 -0
- package/dist/backends/mock-llm.js +717 -0
- package/dist/backends/mock-llm.js.map +1 -0
- package/dist/backends/vercel-ai.cjs +301 -61
- package/dist/backends/vercel-ai.cjs.map +1 -1
- package/dist/backends/vercel-ai.d.cts +3 -1
- package/dist/backends/vercel-ai.d.ts +3 -1
- package/dist/backends/vercel-ai.js +301 -61
- package/dist/backends/vercel-ai.js.map +1 -1
- package/dist/backends-Cno0gZjy.d.cts +114 -0
- package/dist/backends-Cno0gZjy.d.ts +114 -0
- package/dist/chat/accumulator.cjs +1 -1
- package/dist/chat/accumulator.cjs.map +1 -1
- package/dist/chat/accumulator.d.cts +5 -2
- package/dist/chat/accumulator.d.ts +5 -2
- package/dist/chat/accumulator.js +1 -1
- package/dist/chat/accumulator.js.map +1 -1
- package/dist/chat/backends.cjs +1084 -821
- package/dist/chat/backends.cjs.map +1 -1
- package/dist/chat/backends.d.cts +10 -6
- package/dist/chat/backends.d.ts +10 -6
- package/dist/chat/backends.js +1082 -800
- package/dist/chat/backends.js.map +1 -1
- package/dist/chat/context.cjs +50 -0
- package/dist/chat/context.cjs.map +1 -1
- package/dist/chat/context.d.cts +27 -3
- package/dist/chat/context.d.ts +27 -3
- package/dist/chat/context.js +50 -0
- package/dist/chat/context.js.map +1 -1
- package/dist/chat/core.cjs +60 -27
- package/dist/chat/core.cjs.map +1 -1
- package/dist/chat/core.d.cts +41 -382
- package/dist/chat/core.d.ts +41 -382
- package/dist/chat/core.js +58 -28
- package/dist/chat/core.js.map +1 -1
- package/dist/chat/errors.cjs +48 -26
- package/dist/chat/errors.cjs.map +1 -1
- package/dist/chat/errors.d.cts +6 -31
- package/dist/chat/errors.d.ts +6 -31
- package/dist/chat/errors.js +48 -25
- package/dist/chat/errors.js.map +1 -1
- package/dist/chat/events.cjs.map +1 -1
- package/dist/chat/events.d.cts +6 -2
- package/dist/chat/events.d.ts +6 -2
- package/dist/chat/events.js.map +1 -1
- package/dist/chat/index.cjs +1612 -1125
- package/dist/chat/index.cjs.map +1 -1
- package/dist/chat/index.d.cts +35 -10
- package/dist/chat/index.d.ts +35 -10
- package/dist/chat/index.js +1600 -1097
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/react/theme.css +2517 -0
- package/dist/chat/react.cjs +2212 -1158
- package/dist/chat/react.cjs.map +1 -1
- package/dist/chat/react.d.cts +665 -122
- package/dist/chat/react.d.ts +665 -122
- package/dist/chat/react.js +2191 -1156
- package/dist/chat/react.js.map +1 -1
- package/dist/chat/runtime.cjs +405 -186
- package/dist/chat/runtime.cjs.map +1 -1
- package/dist/chat/runtime.d.cts +92 -28
- package/dist/chat/runtime.d.ts +92 -28
- package/dist/chat/runtime.js +405 -186
- package/dist/chat/runtime.js.map +1 -1
- package/dist/chat/server.cjs +2247 -212
- package/dist/chat/server.cjs.map +1 -1
- package/dist/chat/server.d.cts +451 -90
- package/dist/chat/server.d.ts +451 -90
- package/dist/chat/server.js +2234 -213
- package/dist/chat/server.js.map +1 -1
- package/dist/chat/sessions.cjs +64 -66
- package/dist/chat/sessions.cjs.map +1 -1
- package/dist/chat/sessions.d.cts +37 -118
- package/dist/chat/sessions.d.ts +37 -118
- package/dist/chat/sessions.js +65 -67
- package/dist/chat/sessions.js.map +1 -1
- package/dist/chat/sqlite.cjs +536 -0
- package/dist/chat/sqlite.cjs.map +1 -0
- package/dist/chat/sqlite.d.cts +164 -0
- package/dist/chat/sqlite.d.ts +164 -0
- package/dist/chat/sqlite.js +527 -0
- package/dist/chat/sqlite.js.map +1 -0
- package/dist/chat/state.cjs +14 -1
- package/dist/chat/state.cjs.map +1 -1
- package/dist/chat/state.d.cts +5 -2
- package/dist/chat/state.d.ts +5 -2
- package/dist/chat/state.js +14 -1
- package/dist/chat/state.js.map +1 -1
- package/dist/chat/storage.cjs +58 -33
- package/dist/chat/storage.cjs.map +1 -1
- package/dist/chat/storage.d.cts +18 -8
- package/dist/chat/storage.d.ts +18 -8
- package/dist/chat/storage.js +59 -34
- package/dist/chat/storage.js.map +1 -1
- package/dist/errors-C-so0M4t.d.cts +33 -0
- package/dist/errors-C-so0M4t.d.ts +33 -0
- package/dist/errors-CmVvczxZ.d.cts +28 -0
- package/dist/errors-CmVvczxZ.d.ts +28 -0
- package/dist/{in-process-transport-C2oPTYs6.d.ts → in-process-transport-7EIit9Xk.d.ts} +72 -33
- package/dist/{in-process-transport-DG-w5G6k.d.cts → in-process-transport-Ct9YcX8I.d.cts} +72 -33
- package/dist/index.cjs +354 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +294 -123
- package/dist/index.d.ts +294 -123
- package/dist/index.js +347 -60
- package/dist/index.js.map +1 -1
- package/dist/provider-types-PTSlRPNB.d.cts +39 -0
- package/dist/provider-types-PTSlRPNB.d.ts +39 -0
- package/dist/refresh-manager-B81PpYBr.d.cts +153 -0
- package/dist/refresh-manager-Dlv_iNZi.d.ts +153 -0
- package/dist/testing.cjs +1107 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +144 -0
- package/dist/testing.d.ts +144 -0
- package/dist/testing.js +1101 -0
- package/dist/testing.js.map +1 -0
- package/dist/token-store-CSUBgYwn.d.ts +48 -0
- package/dist/token-store-CuC4hB9Z.d.cts +48 -0
- package/dist/{transport-DX1Nhm4N.d.cts → transport-DLWCN18G.d.cts} +5 -4
- package/dist/{transport-D1OaUgRk.d.ts → transport-DsuS-GeM.d.ts} +5 -4
- package/dist/{types-CGF7AEX1.d.cts → types-4vbcmPTp.d.cts} +4 -2
- package/dist/{types-Bh5AhqD-.d.ts → types-BxggH0Yh.d.ts} +4 -2
- package/dist/types-DgtI1hzh.d.ts +364 -0
- package/dist/types-DkSXALKg.d.cts +364 -0
- package/package.json +41 -5
- package/LICENSE +0 -21
- package/README.md +0 -948
- package/dist/errors-BDLbNu9w.d.cts +0 -13
- package/dist/errors-BDLbNu9w.d.ts +0 -13
- package/dist/types-DLZzlJxt.d.ts +0 -39
- package/dist/types-tE0CXwBl.d.cts +0 -39
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
import 'fs';
|
|
3
|
+
import 'fs/promises';
|
|
4
|
+
import 'path';
|
|
5
|
+
|
|
6
|
+
// src/chat/sqlite/factory.ts
|
|
7
|
+
|
|
8
|
+
// src/chat/types.ts
|
|
9
|
+
function createChatId() {
|
|
10
|
+
return crypto.randomUUID();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// src/errors.ts
|
|
14
|
+
var AgentSDKError = class extends Error {
|
|
15
|
+
/** @internal Marker for cross-bundle identity checks */
|
|
16
|
+
_agentSDKError = true;
|
|
17
|
+
/** Machine-readable error code. Prefer values from the ErrorCode enum. */
|
|
18
|
+
code;
|
|
19
|
+
/** Whether this error is safe to retry */
|
|
20
|
+
retryable;
|
|
21
|
+
/** HTTP status code hint for error classification */
|
|
22
|
+
httpStatus;
|
|
23
|
+
constructor(message, options) {
|
|
24
|
+
super(message, options);
|
|
25
|
+
this.name = "AgentSDKError";
|
|
26
|
+
this.code = options?.code;
|
|
27
|
+
this.retryable = options?.retryable ?? false;
|
|
28
|
+
this.httpStatus = options?.httpStatus;
|
|
29
|
+
}
|
|
30
|
+
/** Check if an error is an AgentSDKError (works across bundled copies) */
|
|
31
|
+
static is(error) {
|
|
32
|
+
return error instanceof Error && "_agentSDKError" in error && error._agentSDKError === true;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// src/chat/storage.ts
|
|
37
|
+
var StorageError = class extends AgentSDKError {
|
|
38
|
+
/** Machine-readable error code from the unified ErrorCode enum */
|
|
39
|
+
code;
|
|
40
|
+
constructor(message, code) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.name = "StorageError";
|
|
43
|
+
this.code = code;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// src/chat/sqlite/session-store.ts
|
|
48
|
+
var CREATE_SESSIONS_TABLE = `
|
|
49
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
50
|
+
id TEXT PRIMARY KEY,
|
|
51
|
+
title TEXT,
|
|
52
|
+
config TEXT NOT NULL,
|
|
53
|
+
metadata TEXT NOT NULL,
|
|
54
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
55
|
+
backend_session_id TEXT,
|
|
56
|
+
created_at TEXT NOT NULL,
|
|
57
|
+
updated_at TEXT NOT NULL
|
|
58
|
+
)
|
|
59
|
+
`;
|
|
60
|
+
var CREATE_MESSAGES_TABLE = `
|
|
61
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
62
|
+
id TEXT PRIMARY KEY,
|
|
63
|
+
session_id TEXT NOT NULL,
|
|
64
|
+
role TEXT NOT NULL,
|
|
65
|
+
parts TEXT NOT NULL,
|
|
66
|
+
metadata TEXT,
|
|
67
|
+
status TEXT NOT NULL DEFAULT 'complete',
|
|
68
|
+
created_at TEXT NOT NULL,
|
|
69
|
+
updated_at TEXT,
|
|
70
|
+
position INTEGER NOT NULL,
|
|
71
|
+
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
72
|
+
)
|
|
73
|
+
`;
|
|
74
|
+
var CREATE_MESSAGES_SESSION_IDX = `
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id, position)
|
|
76
|
+
`;
|
|
77
|
+
var SQLiteSessionStore = class {
|
|
78
|
+
db;
|
|
79
|
+
constructor(db) {
|
|
80
|
+
this.db = db;
|
|
81
|
+
this.db.exec(CREATE_SESSIONS_TABLE);
|
|
82
|
+
this.db.exec(CREATE_MESSAGES_TABLE);
|
|
83
|
+
this.db.exec(CREATE_MESSAGES_SESSION_IDX);
|
|
84
|
+
}
|
|
85
|
+
async createSession(options = {}) {
|
|
86
|
+
const id = createChatId();
|
|
87
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
88
|
+
const config = {
|
|
89
|
+
model: "default",
|
|
90
|
+
backend: "default",
|
|
91
|
+
...options.config
|
|
92
|
+
};
|
|
93
|
+
const metadata = {
|
|
94
|
+
messageCount: 0,
|
|
95
|
+
totalTokens: 0,
|
|
96
|
+
tags: options.tags,
|
|
97
|
+
custom: options.custom
|
|
98
|
+
};
|
|
99
|
+
this.db.prepare(`
|
|
100
|
+
INSERT INTO sessions (id, title, config, metadata, status, created_at, updated_at)
|
|
101
|
+
VALUES (?, ?, ?, ?, 'active', ?, ?)
|
|
102
|
+
`).run(id, options.title ?? null, JSON.stringify(config), JSON.stringify(metadata), now, now);
|
|
103
|
+
return this.buildSession(id, options.title, config, metadata, "active", now, now, []);
|
|
104
|
+
}
|
|
105
|
+
async getSession(id) {
|
|
106
|
+
const row = this.db.prepare("SELECT * FROM sessions WHERE id = ?").get(id);
|
|
107
|
+
if (!row) return null;
|
|
108
|
+
const messages = this.loadAllMessages(row.id);
|
|
109
|
+
return this.rowToSession(row, messages);
|
|
110
|
+
}
|
|
111
|
+
async listSessions(options) {
|
|
112
|
+
const rows = this.db.prepare("SELECT * FROM sessions ORDER BY updated_at DESC").all();
|
|
113
|
+
let sessions = rows.map((r) => this.rowToSession(r, []));
|
|
114
|
+
if (options?.filter) sessions = sessions.filter(options.filter);
|
|
115
|
+
if (options?.sort) sessions.sort(options.sort);
|
|
116
|
+
if (options?.offset) sessions = sessions.slice(options.offset);
|
|
117
|
+
if (options?.limit) sessions = sessions.slice(0, options.limit);
|
|
118
|
+
return sessions;
|
|
119
|
+
}
|
|
120
|
+
async updateTitle(id, title) {
|
|
121
|
+
const result = this.db.prepare(
|
|
122
|
+
"UPDATE sessions SET title = ?, updated_at = ? WHERE id = ?"
|
|
123
|
+
).run(title, (/* @__PURE__ */ new Date()).toISOString(), id);
|
|
124
|
+
if (result.changes === 0) throw new StorageError(`Session not found: ${id}`, "STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */);
|
|
125
|
+
}
|
|
126
|
+
async updateConfig(id, config) {
|
|
127
|
+
const row = this.db.prepare("SELECT config FROM sessions WHERE id = ?").get(id);
|
|
128
|
+
if (!row) throw new StorageError(`Session not found: ${id}`, "STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */);
|
|
129
|
+
const merged = { ...JSON.parse(row.config), ...config };
|
|
130
|
+
this.db.prepare(
|
|
131
|
+
"UPDATE sessions SET config = ?, updated_at = ? WHERE id = ?"
|
|
132
|
+
).run(JSON.stringify(merged), (/* @__PURE__ */ new Date()).toISOString(), id);
|
|
133
|
+
}
|
|
134
|
+
async deleteSession(id) {
|
|
135
|
+
const result = this.db.prepare("DELETE FROM sessions WHERE id = ?").run(id);
|
|
136
|
+
if (result.changes === 0) throw new StorageError(`Session not found: ${id}`, "STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */);
|
|
137
|
+
}
|
|
138
|
+
async appendMessage(sessionId, message) {
|
|
139
|
+
const session = this.db.prepare("SELECT id FROM sessions WHERE id = ?").get(sessionId);
|
|
140
|
+
if (!session) throw new StorageError(`Session not found: ${sessionId}`, "STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */);
|
|
141
|
+
const position = this.getNextPosition(sessionId);
|
|
142
|
+
this.db.prepare(`
|
|
143
|
+
INSERT INTO messages (id, session_id, role, parts, metadata, status, created_at, updated_at, position)
|
|
144
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
145
|
+
`).run(
|
|
146
|
+
message.id,
|
|
147
|
+
sessionId,
|
|
148
|
+
message.role,
|
|
149
|
+
JSON.stringify(message.parts),
|
|
150
|
+
message.metadata ? JSON.stringify(message.metadata) : null,
|
|
151
|
+
message.status,
|
|
152
|
+
message.createdAt,
|
|
153
|
+
message.updatedAt ?? null,
|
|
154
|
+
position
|
|
155
|
+
);
|
|
156
|
+
this.incrementMessageCount(sessionId);
|
|
157
|
+
}
|
|
158
|
+
async saveMessages(sessionId, messages) {
|
|
159
|
+
if (messages.length === 0) return;
|
|
160
|
+
const session = this.db.prepare("SELECT id FROM sessions WHERE id = ?").get(sessionId);
|
|
161
|
+
if (!session) throw new StorageError(`Session not found: ${sessionId}`, "STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */);
|
|
162
|
+
const insertMsg = this.db.prepare(`
|
|
163
|
+
INSERT INTO messages (id, session_id, role, parts, metadata, status, created_at, updated_at, position)
|
|
164
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
165
|
+
`);
|
|
166
|
+
const tx = this.db.transaction(() => {
|
|
167
|
+
let pos = this.getNextPosition(sessionId);
|
|
168
|
+
for (const msg of messages) {
|
|
169
|
+
insertMsg.run(
|
|
170
|
+
msg.id,
|
|
171
|
+
sessionId,
|
|
172
|
+
msg.role,
|
|
173
|
+
JSON.stringify(msg.parts),
|
|
174
|
+
msg.metadata ? JSON.stringify(msg.metadata) : null,
|
|
175
|
+
msg.status,
|
|
176
|
+
msg.createdAt,
|
|
177
|
+
msg.updatedAt ?? null,
|
|
178
|
+
pos++
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
this.updateSessionMeta(sessionId, messages.length);
|
|
182
|
+
});
|
|
183
|
+
tx();
|
|
184
|
+
}
|
|
185
|
+
async loadMessages(sessionId, options) {
|
|
186
|
+
const session = this.db.prepare("SELECT id FROM sessions WHERE id = ?").get(sessionId);
|
|
187
|
+
if (!session) throw new StorageError(`Session not found: ${sessionId}`, "STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */);
|
|
188
|
+
const total = this.db.prepare(
|
|
189
|
+
"SELECT COUNT(*) as cnt FROM messages WHERE session_id = ?"
|
|
190
|
+
).get(sessionId).cnt;
|
|
191
|
+
const limit = options?.limit ?? 50;
|
|
192
|
+
const offset = options?.offset ?? 0;
|
|
193
|
+
const rows = this.db.prepare(
|
|
194
|
+
"SELECT * FROM messages WHERE session_id = ? ORDER BY position ASC LIMIT ? OFFSET ?"
|
|
195
|
+
).all(sessionId, limit, offset);
|
|
196
|
+
return {
|
|
197
|
+
messages: rows.map(rowToMessage),
|
|
198
|
+
total,
|
|
199
|
+
hasMore: offset + limit < total
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
async searchSessions(options) {
|
|
203
|
+
const pattern = `%${options.query}%`;
|
|
204
|
+
const limit = options.limit ?? 20;
|
|
205
|
+
const titleMatches = this.db.prepare(
|
|
206
|
+
"SELECT * FROM sessions WHERE title LIKE ? COLLATE NOCASE LIMIT ?"
|
|
207
|
+
).all(pattern, limit);
|
|
208
|
+
const contentMatches = this.db.prepare(`
|
|
209
|
+
SELECT DISTINCT s.* FROM sessions s
|
|
210
|
+
JOIN messages m ON m.session_id = s.id
|
|
211
|
+
WHERE m.parts LIKE ? COLLATE NOCASE
|
|
212
|
+
LIMIT ?
|
|
213
|
+
`).all(pattern, limit);
|
|
214
|
+
const seen = /* @__PURE__ */ new Set();
|
|
215
|
+
const results = [];
|
|
216
|
+
for (const row of [...titleMatches, ...contentMatches]) {
|
|
217
|
+
if (!seen.has(row.id)) {
|
|
218
|
+
seen.add(row.id);
|
|
219
|
+
results.push(this.rowToSession(row, []));
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return results.slice(0, limit);
|
|
223
|
+
}
|
|
224
|
+
async count() {
|
|
225
|
+
return this.db.prepare("SELECT COUNT(*) as cnt FROM sessions").get().cnt;
|
|
226
|
+
}
|
|
227
|
+
async clear() {
|
|
228
|
+
this.db.exec("DELETE FROM messages");
|
|
229
|
+
this.db.exec("DELETE FROM sessions");
|
|
230
|
+
}
|
|
231
|
+
// ─── Private Helpers ─────────────────────────────────────────
|
|
232
|
+
getNextPosition(sessionId) {
|
|
233
|
+
const result = this.db.prepare(
|
|
234
|
+
"SELECT MAX(position) as maxPos FROM messages WHERE session_id = ?"
|
|
235
|
+
).get(sessionId);
|
|
236
|
+
return (result.maxPos ?? -1) + 1;
|
|
237
|
+
}
|
|
238
|
+
incrementMessageCount(sessionId) {
|
|
239
|
+
this.db.prepare(`
|
|
240
|
+
UPDATE sessions
|
|
241
|
+
SET metadata = json_set(metadata, '$.messageCount', json_extract(metadata, '$.messageCount') + 1),
|
|
242
|
+
updated_at = ?
|
|
243
|
+
WHERE id = ?
|
|
244
|
+
`).run((/* @__PURE__ */ new Date()).toISOString(), sessionId);
|
|
245
|
+
}
|
|
246
|
+
updateSessionMeta(sessionId, addedCount) {
|
|
247
|
+
this.db.prepare(`
|
|
248
|
+
UPDATE sessions
|
|
249
|
+
SET metadata = json_set(metadata, '$.messageCount', json_extract(metadata, '$.messageCount') + ?),
|
|
250
|
+
updated_at = ?
|
|
251
|
+
WHERE id = ?
|
|
252
|
+
`).run(addedCount, (/* @__PURE__ */ new Date()).toISOString(), sessionId);
|
|
253
|
+
}
|
|
254
|
+
loadAllMessages(sessionId) {
|
|
255
|
+
const rows = this.db.prepare(
|
|
256
|
+
"SELECT * FROM messages WHERE session_id = ? ORDER BY position ASC"
|
|
257
|
+
).all(sessionId);
|
|
258
|
+
return rows.map(rowToMessage);
|
|
259
|
+
}
|
|
260
|
+
rowToSession(row, messages) {
|
|
261
|
+
return this.buildSession(
|
|
262
|
+
row.id,
|
|
263
|
+
row.title,
|
|
264
|
+
JSON.parse(row.config),
|
|
265
|
+
JSON.parse(row.metadata),
|
|
266
|
+
row.status,
|
|
267
|
+
row.created_at,
|
|
268
|
+
row.updated_at,
|
|
269
|
+
messages
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
buildSession(id, title, config, metadata, status, createdAt, updatedAt, messages) {
|
|
273
|
+
return {
|
|
274
|
+
id,
|
|
275
|
+
title: title ?? void 0,
|
|
276
|
+
messages,
|
|
277
|
+
config,
|
|
278
|
+
metadata,
|
|
279
|
+
status,
|
|
280
|
+
createdAt,
|
|
281
|
+
updatedAt
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
function rowToMessage(row) {
|
|
286
|
+
return {
|
|
287
|
+
id: row.id,
|
|
288
|
+
role: row.role,
|
|
289
|
+
parts: JSON.parse(row.parts),
|
|
290
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : void 0,
|
|
291
|
+
status: row.status,
|
|
292
|
+
createdAt: row.created_at,
|
|
293
|
+
updatedAt: row.updated_at ?? void 0
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// src/chat/sqlite/provider-store.ts
|
|
298
|
+
var CREATE_PROVIDERS_TABLE = `
|
|
299
|
+
CREATE TABLE IF NOT EXISTS providers (
|
|
300
|
+
id TEXT PRIMARY KEY,
|
|
301
|
+
backend TEXT NOT NULL,
|
|
302
|
+
model TEXT NOT NULL,
|
|
303
|
+
label TEXT NOT NULL,
|
|
304
|
+
created_at INTEGER NOT NULL
|
|
305
|
+
)
|
|
306
|
+
`;
|
|
307
|
+
var SQLiteProviderStore = class {
|
|
308
|
+
db;
|
|
309
|
+
constructor(db) {
|
|
310
|
+
this.db = db;
|
|
311
|
+
this.db.exec(CREATE_PROVIDERS_TABLE);
|
|
312
|
+
}
|
|
313
|
+
async create(config) {
|
|
314
|
+
this.db.prepare(`
|
|
315
|
+
INSERT INTO providers (id, backend, model, label, created_at)
|
|
316
|
+
VALUES (?, ?, ?, ?, ?)
|
|
317
|
+
`).run(config.id, config.backend, config.model, config.label, config.createdAt);
|
|
318
|
+
}
|
|
319
|
+
async get(id) {
|
|
320
|
+
const row = this.db.prepare("SELECT * FROM providers WHERE id = ?").get(id);
|
|
321
|
+
return row ? rowToProvider(row) : null;
|
|
322
|
+
}
|
|
323
|
+
async update(id, changes) {
|
|
324
|
+
const existing = this.db.prepare("SELECT id FROM providers WHERE id = ?").get(id);
|
|
325
|
+
if (!existing) throw new Error(`Provider "${id}" not found`);
|
|
326
|
+
const sets = [];
|
|
327
|
+
const values = [];
|
|
328
|
+
if (changes.backend !== void 0) {
|
|
329
|
+
sets.push("backend = ?");
|
|
330
|
+
values.push(changes.backend);
|
|
331
|
+
}
|
|
332
|
+
if (changes.model !== void 0) {
|
|
333
|
+
sets.push("model = ?");
|
|
334
|
+
values.push(changes.model);
|
|
335
|
+
}
|
|
336
|
+
if (changes.label !== void 0) {
|
|
337
|
+
sets.push("label = ?");
|
|
338
|
+
values.push(changes.label);
|
|
339
|
+
}
|
|
340
|
+
if (sets.length > 0) {
|
|
341
|
+
values.push(id);
|
|
342
|
+
this.db.prepare(`UPDATE providers SET ${sets.join(", ")} WHERE id = ?`).run(...values);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
async delete(id) {
|
|
346
|
+
this.db.prepare("DELETE FROM providers WHERE id = ?").run(id);
|
|
347
|
+
}
|
|
348
|
+
async list() {
|
|
349
|
+
const rows = this.db.prepare("SELECT * FROM providers ORDER BY created_at ASC").all();
|
|
350
|
+
return rows.map(rowToProvider);
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
function rowToProvider(row) {
|
|
354
|
+
return {
|
|
355
|
+
id: row.id,
|
|
356
|
+
backend: row.backend,
|
|
357
|
+
model: row.model,
|
|
358
|
+
label: row.label,
|
|
359
|
+
createdAt: row.created_at
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// src/chat/sqlite/token-store.ts
|
|
364
|
+
var CREATE_TOKENS_TABLE = `
|
|
365
|
+
CREATE TABLE IF NOT EXISTS tokens (
|
|
366
|
+
provider TEXT PRIMARY KEY,
|
|
367
|
+
token_json TEXT NOT NULL,
|
|
368
|
+
saved_at INTEGER NOT NULL
|
|
369
|
+
)
|
|
370
|
+
`;
|
|
371
|
+
var SQLiteTokenStore = class {
|
|
372
|
+
db;
|
|
373
|
+
constructor(db) {
|
|
374
|
+
this.db = db;
|
|
375
|
+
this.db.exec(CREATE_TOKENS_TABLE);
|
|
376
|
+
}
|
|
377
|
+
async save(provider, token) {
|
|
378
|
+
this.db.prepare(`
|
|
379
|
+
INSERT OR REPLACE INTO tokens (provider, token_json, saved_at)
|
|
380
|
+
VALUES (?, ?, ?)
|
|
381
|
+
`).run(provider, JSON.stringify(token), Date.now());
|
|
382
|
+
}
|
|
383
|
+
async load(provider) {
|
|
384
|
+
const row = this.db.prepare("SELECT token_json FROM tokens WHERE provider = ?").get(provider);
|
|
385
|
+
return row ? JSON.parse(row.token_json) : null;
|
|
386
|
+
}
|
|
387
|
+
async clear(provider) {
|
|
388
|
+
this.db.prepare("DELETE FROM tokens WHERE provider = ?").run(provider);
|
|
389
|
+
}
|
|
390
|
+
async clearAll() {
|
|
391
|
+
this.db.exec("DELETE FROM tokens");
|
|
392
|
+
}
|
|
393
|
+
async list() {
|
|
394
|
+
const rows = this.db.prepare("SELECT provider FROM tokens ORDER BY saved_at ASC").all();
|
|
395
|
+
return rows.map((r) => r.provider);
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
// src/chat/sqlite/migrations.ts
|
|
400
|
+
var CREATE_VERSION_TABLE = `
|
|
401
|
+
CREATE TABLE IF NOT EXISTS schema_version (
|
|
402
|
+
version INTEGER PRIMARY KEY,
|
|
403
|
+
applied_at TEXT NOT NULL,
|
|
404
|
+
description TEXT
|
|
405
|
+
)
|
|
406
|
+
`;
|
|
407
|
+
var migrations = [
|
|
408
|
+
{
|
|
409
|
+
version: 1,
|
|
410
|
+
description: "Initial schema \u2014 sessions, messages, providers, tokens",
|
|
411
|
+
up: (db) => {
|
|
412
|
+
db.exec(`
|
|
413
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
414
|
+
id TEXT PRIMARY KEY,
|
|
415
|
+
title TEXT,
|
|
416
|
+
config TEXT NOT NULL,
|
|
417
|
+
metadata TEXT NOT NULL,
|
|
418
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
419
|
+
backend_session_id TEXT,
|
|
420
|
+
created_at TEXT NOT NULL,
|
|
421
|
+
updated_at TEXT NOT NULL
|
|
422
|
+
)
|
|
423
|
+
`);
|
|
424
|
+
db.exec(`
|
|
425
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
426
|
+
id TEXT PRIMARY KEY,
|
|
427
|
+
session_id TEXT NOT NULL,
|
|
428
|
+
role TEXT NOT NULL,
|
|
429
|
+
parts TEXT NOT NULL,
|
|
430
|
+
metadata TEXT,
|
|
431
|
+
status TEXT NOT NULL DEFAULT 'complete',
|
|
432
|
+
created_at TEXT NOT NULL,
|
|
433
|
+
updated_at TEXT,
|
|
434
|
+
position INTEGER NOT NULL,
|
|
435
|
+
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
436
|
+
)
|
|
437
|
+
`);
|
|
438
|
+
db.exec(`
|
|
439
|
+
CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id, position)
|
|
440
|
+
`);
|
|
441
|
+
db.exec(`
|
|
442
|
+
CREATE TABLE IF NOT EXISTS providers (
|
|
443
|
+
id TEXT PRIMARY KEY,
|
|
444
|
+
backend TEXT NOT NULL,
|
|
445
|
+
model TEXT NOT NULL,
|
|
446
|
+
label TEXT NOT NULL,
|
|
447
|
+
created_at INTEGER NOT NULL
|
|
448
|
+
)
|
|
449
|
+
`);
|
|
450
|
+
db.exec(`
|
|
451
|
+
CREATE TABLE IF NOT EXISTS tokens (
|
|
452
|
+
provider TEXT PRIMARY KEY,
|
|
453
|
+
token_json TEXT NOT NULL,
|
|
454
|
+
saved_at INTEGER NOT NULL
|
|
455
|
+
)
|
|
456
|
+
`);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
];
|
|
460
|
+
function getSchemaVersion(db) {
|
|
461
|
+
db.exec(CREATE_VERSION_TABLE);
|
|
462
|
+
const row = db.prepare("SELECT MAX(version) as v FROM schema_version").get();
|
|
463
|
+
return row?.v ?? 0;
|
|
464
|
+
}
|
|
465
|
+
function runMigrations(db) {
|
|
466
|
+
db.exec(CREATE_VERSION_TABLE);
|
|
467
|
+
let current = getSchemaVersion(db);
|
|
468
|
+
if (current === 0 && tableExists(db, "sessions")) {
|
|
469
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
470
|
+
db.prepare("INSERT INTO schema_version (version, applied_at, description) VALUES (?, ?, ?)").run(1, now, "Initial schema (pre-existing database)");
|
|
471
|
+
current = 1;
|
|
472
|
+
}
|
|
473
|
+
const pending = migrations.filter((m) => m.version > current);
|
|
474
|
+
if (pending.length === 0) return;
|
|
475
|
+
for (const migration of pending) {
|
|
476
|
+
const txn = db.transaction(() => {
|
|
477
|
+
migration.up(db);
|
|
478
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
479
|
+
db.prepare("INSERT INTO schema_version (version, applied_at, description) VALUES (?, ?, ?)").run(migration.version, now, migration.description);
|
|
480
|
+
});
|
|
481
|
+
txn();
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
function tableExists(db, name) {
|
|
485
|
+
const row = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(name);
|
|
486
|
+
return !!row;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// src/chat/sqlite/factory.ts
|
|
490
|
+
function createSQLiteStorage(pathOrOptions) {
|
|
491
|
+
let db;
|
|
492
|
+
if (typeof pathOrOptions === "string") {
|
|
493
|
+
db = createDatabase(pathOrOptions);
|
|
494
|
+
} else if (pathOrOptions.db) {
|
|
495
|
+
db = pathOrOptions.db;
|
|
496
|
+
} else {
|
|
497
|
+
db = createDatabase(pathOrOptions.dbPath);
|
|
498
|
+
}
|
|
499
|
+
db.pragma("journal_mode = WAL");
|
|
500
|
+
db.pragma("foreign_keys = ON");
|
|
501
|
+
runMigrations(db);
|
|
502
|
+
return {
|
|
503
|
+
db,
|
|
504
|
+
sessionStore: new SQLiteSessionStore(db),
|
|
505
|
+
providerStore: new SQLiteProviderStore(db),
|
|
506
|
+
tokenStore: new SQLiteTokenStore(db)
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
function createDatabase(dbPath) {
|
|
510
|
+
try {
|
|
511
|
+
const esmRequire = createRequire(import.meta.url);
|
|
512
|
+
const BetterSqlite3 = esmRequire("better-sqlite3");
|
|
513
|
+
return new BetterSqlite3(dbPath);
|
|
514
|
+
} catch (err) {
|
|
515
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
516
|
+
if (message.includes("Cannot find module") || message.includes("MODULE_NOT_FOUND")) {
|
|
517
|
+
throw new Error(
|
|
518
|
+
"better-sqlite3 is required for SQLite storage. Install it: npm install better-sqlite3"
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
throw err;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
export { SQLiteProviderStore, SQLiteSessionStore, SQLiteTokenStore, createSQLiteStorage, getSchemaVersion, migrations, runMigrations };
|
|
526
|
+
//# sourceMappingURL=sqlite.js.map
|
|
527
|
+
//# sourceMappingURL=sqlite.js.map
|