@witqq/agent-sdk 0.7.0 → 0.8.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.
Files changed (147) hide show
  1. package/README.md +140 -34
  2. package/dist/{types-CqvUAYxt.d.cts → agent-CW9XbmG_.d.ts} +137 -102
  3. package/dist/{types-CqvUAYxt.d.ts → agent-DxY68NZL.d.cts} +137 -102
  4. package/dist/auth/index.cjs +72 -1
  5. package/dist/auth/index.cjs.map +1 -1
  6. package/dist/auth/index.d.cts +21 -154
  7. package/dist/auth/index.d.ts +21 -154
  8. package/dist/auth/index.js +72 -1
  9. package/dist/auth/index.js.map +1 -1
  10. package/dist/backends/claude.cjs +480 -261
  11. package/dist/backends/claude.cjs.map +1 -1
  12. package/dist/backends/claude.d.cts +3 -1
  13. package/dist/backends/claude.d.ts +3 -1
  14. package/dist/backends/claude.js +480 -261
  15. package/dist/backends/claude.js.map +1 -1
  16. package/dist/backends/copilot.cjs +329 -97
  17. package/dist/backends/copilot.cjs.map +1 -1
  18. package/dist/backends/copilot.d.cts +12 -4
  19. package/dist/backends/copilot.d.ts +12 -4
  20. package/dist/backends/copilot.js +329 -97
  21. package/dist/backends/copilot.js.map +1 -1
  22. package/dist/backends/vercel-ai.cjs +294 -61
  23. package/dist/backends/vercel-ai.cjs.map +1 -1
  24. package/dist/backends/vercel-ai.d.cts +3 -1
  25. package/dist/backends/vercel-ai.d.ts +3 -1
  26. package/dist/backends/vercel-ai.js +294 -61
  27. package/dist/backends/vercel-ai.js.map +1 -1
  28. package/dist/backends-BSrsBYFn.d.cts +39 -0
  29. package/dist/backends-BSrsBYFn.d.ts +39 -0
  30. package/dist/chat/accumulator.cjs +1 -1
  31. package/dist/chat/accumulator.cjs.map +1 -1
  32. package/dist/chat/accumulator.d.cts +5 -2
  33. package/dist/chat/accumulator.d.ts +5 -2
  34. package/dist/chat/accumulator.js +1 -1
  35. package/dist/chat/accumulator.js.map +1 -1
  36. package/dist/chat/backends.cjs +736 -746
  37. package/dist/chat/backends.cjs.map +1 -1
  38. package/dist/chat/backends.d.cts +10 -6
  39. package/dist/chat/backends.d.ts +10 -6
  40. package/dist/chat/backends.js +736 -725
  41. package/dist/chat/backends.js.map +1 -1
  42. package/dist/chat/context.cjs +50 -0
  43. package/dist/chat/context.cjs.map +1 -1
  44. package/dist/chat/context.d.cts +27 -3
  45. package/dist/chat/context.d.ts +27 -3
  46. package/dist/chat/context.js +50 -0
  47. package/dist/chat/context.js.map +1 -1
  48. package/dist/chat/core.cjs +25 -2
  49. package/dist/chat/core.cjs.map +1 -1
  50. package/dist/chat/core.d.cts +30 -381
  51. package/dist/chat/core.d.ts +30 -381
  52. package/dist/chat/core.js +24 -3
  53. package/dist/chat/core.js.map +1 -1
  54. package/dist/chat/errors.cjs +48 -26
  55. package/dist/chat/errors.cjs.map +1 -1
  56. package/dist/chat/errors.d.cts +6 -31
  57. package/dist/chat/errors.d.ts +6 -31
  58. package/dist/chat/errors.js +48 -25
  59. package/dist/chat/errors.js.map +1 -1
  60. package/dist/chat/events.cjs.map +1 -1
  61. package/dist/chat/events.d.cts +6 -2
  62. package/dist/chat/events.d.ts +6 -2
  63. package/dist/chat/events.js.map +1 -1
  64. package/dist/chat/index.cjs +1199 -1008
  65. package/dist/chat/index.cjs.map +1 -1
  66. package/dist/chat/index.d.cts +35 -10
  67. package/dist/chat/index.d.ts +35 -10
  68. package/dist/chat/index.js +1196 -987
  69. package/dist/chat/index.js.map +1 -1
  70. package/dist/chat/react/theme.css +2517 -0
  71. package/dist/chat/react.cjs +2003 -1153
  72. package/dist/chat/react.cjs.map +1 -1
  73. package/dist/chat/react.d.cts +590 -121
  74. package/dist/chat/react.d.ts +590 -121
  75. package/dist/chat/react.js +1984 -1151
  76. package/dist/chat/react.js.map +1 -1
  77. package/dist/chat/runtime.cjs +401 -186
  78. package/dist/chat/runtime.cjs.map +1 -1
  79. package/dist/chat/runtime.d.cts +92 -28
  80. package/dist/chat/runtime.d.ts +92 -28
  81. package/dist/chat/runtime.js +401 -186
  82. package/dist/chat/runtime.js.map +1 -1
  83. package/dist/chat/server.cjs +2234 -209
  84. package/dist/chat/server.cjs.map +1 -1
  85. package/dist/chat/server.d.cts +451 -90
  86. package/dist/chat/server.d.ts +451 -90
  87. package/dist/chat/server.js +2221 -210
  88. package/dist/chat/server.js.map +1 -1
  89. package/dist/chat/sessions.cjs +25 -43
  90. package/dist/chat/sessions.cjs.map +1 -1
  91. package/dist/chat/sessions.d.cts +37 -118
  92. package/dist/chat/sessions.d.ts +37 -118
  93. package/dist/chat/sessions.js +25 -43
  94. package/dist/chat/sessions.js.map +1 -1
  95. package/dist/chat/sqlite.cjs +441 -0
  96. package/dist/chat/sqlite.cjs.map +1 -0
  97. package/dist/chat/sqlite.d.cts +128 -0
  98. package/dist/chat/sqlite.d.ts +128 -0
  99. package/dist/chat/sqlite.js +435 -0
  100. package/dist/chat/sqlite.js.map +1 -0
  101. package/dist/chat/state.cjs +14 -1
  102. package/dist/chat/state.cjs.map +1 -1
  103. package/dist/chat/state.d.cts +5 -2
  104. package/dist/chat/state.d.ts +5 -2
  105. package/dist/chat/state.js +14 -1
  106. package/dist/chat/state.js.map +1 -1
  107. package/dist/chat/storage.cjs +19 -10
  108. package/dist/chat/storage.cjs.map +1 -1
  109. package/dist/chat/storage.d.cts +11 -5
  110. package/dist/chat/storage.d.ts +11 -5
  111. package/dist/chat/storage.js +19 -10
  112. package/dist/chat/storage.js.map +1 -1
  113. package/dist/errors-C-so0M4t.d.cts +33 -0
  114. package/dist/errors-C-so0M4t.d.ts +33 -0
  115. package/dist/errors-CmVvczxZ.d.cts +28 -0
  116. package/dist/errors-CmVvczxZ.d.ts +28 -0
  117. package/dist/{in-process-transport-C2oPTYs6.d.ts → in-process-transport-C1JnJGVR.d.ts} +28 -23
  118. package/dist/{in-process-transport-DG-w5G6k.d.cts → in-process-transport-C7DSqPyX.d.cts} +28 -23
  119. package/dist/index.cjs +340 -46
  120. package/dist/index.cjs.map +1 -1
  121. package/dist/index.d.cts +292 -123
  122. package/dist/index.d.ts +292 -123
  123. package/dist/index.js +334 -47
  124. package/dist/index.js.map +1 -1
  125. package/dist/provider-types-PTSlRPNB.d.cts +39 -0
  126. package/dist/provider-types-PTSlRPNB.d.ts +39 -0
  127. package/dist/refresh-manager-B81PpYBr.d.cts +153 -0
  128. package/dist/refresh-manager-Dlv_iNZi.d.ts +153 -0
  129. package/dist/testing.cjs +383 -0
  130. package/dist/testing.cjs.map +1 -0
  131. package/dist/testing.d.cts +132 -0
  132. package/dist/testing.d.ts +132 -0
  133. package/dist/testing.js +377 -0
  134. package/dist/testing.js.map +1 -0
  135. package/dist/token-store-CSUBgYwn.d.ts +48 -0
  136. package/dist/token-store-CuC4hB9Z.d.cts +48 -0
  137. package/dist/{transport-DX1Nhm4N.d.cts → transport-Cdh3M0tS.d.cts} +5 -4
  138. package/dist/{transport-D1OaUgRk.d.ts → transport-Ciap4PWK.d.ts} +5 -4
  139. package/dist/{types-CGF7AEX1.d.cts → types-4vbcmPTp.d.cts} +4 -2
  140. package/dist/{types-Bh5AhqD-.d.ts → types-BxggH0Yh.d.ts} +4 -2
  141. package/dist/types-DRgd_9R7.d.cts +363 -0
  142. package/dist/types-ajANVzf7.d.ts +363 -0
  143. package/package.json +31 -6
  144. package/dist/errors-BDLbNu9w.d.cts +0 -13
  145. package/dist/errors-BDLbNu9w.d.ts +0 -13
  146. package/dist/types-DLZzlJxt.d.ts +0 -39
  147. package/dist/types-tE0CXwBl.d.cts +0 -39
@@ -0,0 +1,128 @@
1
+ import Database from 'better-sqlite3';
2
+ import { IChatSessionStore, CreateSessionOptions, SessionListOptions, PaginatedMessages, SessionSearchOptions } from './sessions.cjs';
3
+ import { I as IProviderStore, P as ProviderConfig } from '../provider-types-PTSlRPNB.cjs';
4
+ import { I as ITokenStore } from '../token-store-CuC4hB9Z.cjs';
5
+ import { g as ChatSession, b as ChatId, j as ChatSessionConfig, c as ChatMessage } from '../types-DRgd_9R7.cjs';
6
+ import { A as AuthToken } from '../types-4vbcmPTp.cjs';
7
+ import './storage.cjs';
8
+ import '../errors-CmVvczxZ.cjs';
9
+ import '../errors-C-so0M4t.cjs';
10
+ import '../agent-DxY68NZL.cjs';
11
+ import 'zod';
12
+
13
+ /**
14
+ * Factory function for creating all three SQLite stores from a single database path.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { createSQLiteStorage } from "@witqq/agent-sdk/chat/sqlite";
19
+ *
20
+ * const storage = createSQLiteStorage("/data/chat.db");
21
+ * // storage.sessionStore — IChatSessionStore
22
+ * // storage.providerStore — IProviderStore
23
+ * // storage.tokenStore — ITokenStore
24
+ * // storage.db — raw Database instance
25
+ * ```
26
+ */
27
+
28
+ interface SQLiteStorageOptions {
29
+ /** Path to SQLite database file. Use ":memory:" for in-memory database. */
30
+ dbPath: string;
31
+ /** Optional pre-created Database instance. If provided, dbPath is ignored. */
32
+ db?: Database.Database;
33
+ }
34
+ interface SQLiteStorage {
35
+ /** The underlying better-sqlite3 Database instance */
36
+ db: Database.Database;
37
+ /** Session store for chat sessions and messages */
38
+ sessionStore: IChatSessionStore;
39
+ /** Provider store for provider configurations */
40
+ providerStore: IProviderStore;
41
+ /** Token store for auth tokens */
42
+ tokenStore: ITokenStore;
43
+ }
44
+ /**
45
+ * Create all three SQLite stores sharing a single database.
46
+ *
47
+ * Requires `better-sqlite3` as a peer dependency.
48
+ * Schema tables are auto-created on first use.
49
+ *
50
+ * @param pathOrOptions - Database file path string, or options object
51
+ * @returns Object with db, sessionStore, providerStore, tokenStore
52
+ *
53
+ * @throws If better-sqlite3 is not installed
54
+ */
55
+ declare function createSQLiteStorage(pathOrOptions: string | SQLiteStorageOptions): SQLiteStorage;
56
+
57
+ /**
58
+ * SQLite-backed session store implementing IChatSessionStore.
59
+ *
60
+ * Uses better-sqlite3 for synchronous database access wrapped in
61
+ * async interface. Messages are stored with position ordering for
62
+ * deterministic retrieval. Parts and metadata are JSON-serialized.
63
+ *
64
+ * Accepts a shared Database instance — multiple stores can share
65
+ * a single SQLite file via the factory function.
66
+ */
67
+
68
+ declare class SQLiteSessionStore implements IChatSessionStore {
69
+ private readonly db;
70
+ constructor(db: Database.Database);
71
+ createSession(options?: CreateSessionOptions): Promise<ChatSession>;
72
+ getSession(id: ChatId): Promise<ChatSession | null>;
73
+ listSessions(options?: SessionListOptions): Promise<ChatSession[]>;
74
+ updateTitle(id: ChatId, title: string): Promise<void>;
75
+ updateConfig(id: ChatId, config: Partial<ChatSessionConfig>): Promise<void>;
76
+ deleteSession(id: ChatId): Promise<void>;
77
+ appendMessage(sessionId: ChatId, message: ChatMessage): Promise<void>;
78
+ saveMessages(sessionId: ChatId, messages: ChatMessage[]): Promise<void>;
79
+ loadMessages(sessionId: ChatId, options?: {
80
+ limit?: number;
81
+ offset?: number;
82
+ }): Promise<PaginatedMessages>;
83
+ searchSessions(options: SessionSearchOptions): Promise<ChatSession[]>;
84
+ count(): Promise<number>;
85
+ clear(): Promise<void>;
86
+ private getNextPosition;
87
+ private incrementMessageCount;
88
+ private updateSessionMeta;
89
+ private loadAllMessages;
90
+ private rowToSession;
91
+ private buildSession;
92
+ }
93
+
94
+ /**
95
+ * SQLite-backed provider store implementing IProviderStore.
96
+ *
97
+ * Stores provider configurations in a `providers` table within
98
+ * a shared SQLite database. Schema auto-created on construction.
99
+ */
100
+
101
+ declare class SQLiteProviderStore implements IProviderStore {
102
+ private readonly db;
103
+ constructor(db: Database.Database);
104
+ create(config: ProviderConfig): Promise<void>;
105
+ get(id: string): Promise<ProviderConfig | null>;
106
+ update(id: string, changes: Partial<Omit<ProviderConfig, "id" | "createdAt">>): Promise<void>;
107
+ delete(id: string): Promise<void>;
108
+ list(): Promise<ProviderConfig[]>;
109
+ }
110
+
111
+ /**
112
+ * SQLite-backed token store implementing ITokenStore.
113
+ *
114
+ * Stores auth tokens as JSON in a `tokens` table within
115
+ * a shared SQLite database. Schema auto-created on construction.
116
+ */
117
+
118
+ declare class SQLiteTokenStore implements ITokenStore {
119
+ private readonly db;
120
+ constructor(db: Database.Database);
121
+ save(provider: string, token: AuthToken): Promise<void>;
122
+ load(provider: string): Promise<AuthToken | null>;
123
+ clear(provider: string): Promise<void>;
124
+ clearAll(): Promise<void>;
125
+ list(): Promise<string[]>;
126
+ }
127
+
128
+ export { SQLiteProviderStore, SQLiteSessionStore, type SQLiteStorage, type SQLiteStorageOptions, SQLiteTokenStore, createSQLiteStorage };
@@ -0,0 +1,128 @@
1
+ import Database from 'better-sqlite3';
2
+ import { IChatSessionStore, CreateSessionOptions, SessionListOptions, PaginatedMessages, SessionSearchOptions } from './sessions.js';
3
+ import { I as IProviderStore, P as ProviderConfig } from '../provider-types-PTSlRPNB.js';
4
+ import { I as ITokenStore } from '../token-store-CSUBgYwn.js';
5
+ import { g as ChatSession, b as ChatId, j as ChatSessionConfig, c as ChatMessage } from '../types-ajANVzf7.js';
6
+ import { A as AuthToken } from '../types-BxggH0Yh.js';
7
+ import './storage.js';
8
+ import '../errors-CmVvczxZ.js';
9
+ import '../errors-C-so0M4t.js';
10
+ import '../agent-CW9XbmG_.js';
11
+ import 'zod';
12
+
13
+ /**
14
+ * Factory function for creating all three SQLite stores from a single database path.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { createSQLiteStorage } from "@witqq/agent-sdk/chat/sqlite";
19
+ *
20
+ * const storage = createSQLiteStorage("/data/chat.db");
21
+ * // storage.sessionStore — IChatSessionStore
22
+ * // storage.providerStore — IProviderStore
23
+ * // storage.tokenStore — ITokenStore
24
+ * // storage.db — raw Database instance
25
+ * ```
26
+ */
27
+
28
+ interface SQLiteStorageOptions {
29
+ /** Path to SQLite database file. Use ":memory:" for in-memory database. */
30
+ dbPath: string;
31
+ /** Optional pre-created Database instance. If provided, dbPath is ignored. */
32
+ db?: Database.Database;
33
+ }
34
+ interface SQLiteStorage {
35
+ /** The underlying better-sqlite3 Database instance */
36
+ db: Database.Database;
37
+ /** Session store for chat sessions and messages */
38
+ sessionStore: IChatSessionStore;
39
+ /** Provider store for provider configurations */
40
+ providerStore: IProviderStore;
41
+ /** Token store for auth tokens */
42
+ tokenStore: ITokenStore;
43
+ }
44
+ /**
45
+ * Create all three SQLite stores sharing a single database.
46
+ *
47
+ * Requires `better-sqlite3` as a peer dependency.
48
+ * Schema tables are auto-created on first use.
49
+ *
50
+ * @param pathOrOptions - Database file path string, or options object
51
+ * @returns Object with db, sessionStore, providerStore, tokenStore
52
+ *
53
+ * @throws If better-sqlite3 is not installed
54
+ */
55
+ declare function createSQLiteStorage(pathOrOptions: string | SQLiteStorageOptions): SQLiteStorage;
56
+
57
+ /**
58
+ * SQLite-backed session store implementing IChatSessionStore.
59
+ *
60
+ * Uses better-sqlite3 for synchronous database access wrapped in
61
+ * async interface. Messages are stored with position ordering for
62
+ * deterministic retrieval. Parts and metadata are JSON-serialized.
63
+ *
64
+ * Accepts a shared Database instance — multiple stores can share
65
+ * a single SQLite file via the factory function.
66
+ */
67
+
68
+ declare class SQLiteSessionStore implements IChatSessionStore {
69
+ private readonly db;
70
+ constructor(db: Database.Database);
71
+ createSession(options?: CreateSessionOptions): Promise<ChatSession>;
72
+ getSession(id: ChatId): Promise<ChatSession | null>;
73
+ listSessions(options?: SessionListOptions): Promise<ChatSession[]>;
74
+ updateTitle(id: ChatId, title: string): Promise<void>;
75
+ updateConfig(id: ChatId, config: Partial<ChatSessionConfig>): Promise<void>;
76
+ deleteSession(id: ChatId): Promise<void>;
77
+ appendMessage(sessionId: ChatId, message: ChatMessage): Promise<void>;
78
+ saveMessages(sessionId: ChatId, messages: ChatMessage[]): Promise<void>;
79
+ loadMessages(sessionId: ChatId, options?: {
80
+ limit?: number;
81
+ offset?: number;
82
+ }): Promise<PaginatedMessages>;
83
+ searchSessions(options: SessionSearchOptions): Promise<ChatSession[]>;
84
+ count(): Promise<number>;
85
+ clear(): Promise<void>;
86
+ private getNextPosition;
87
+ private incrementMessageCount;
88
+ private updateSessionMeta;
89
+ private loadAllMessages;
90
+ private rowToSession;
91
+ private buildSession;
92
+ }
93
+
94
+ /**
95
+ * SQLite-backed provider store implementing IProviderStore.
96
+ *
97
+ * Stores provider configurations in a `providers` table within
98
+ * a shared SQLite database. Schema auto-created on construction.
99
+ */
100
+
101
+ declare class SQLiteProviderStore implements IProviderStore {
102
+ private readonly db;
103
+ constructor(db: Database.Database);
104
+ create(config: ProviderConfig): Promise<void>;
105
+ get(id: string): Promise<ProviderConfig | null>;
106
+ update(id: string, changes: Partial<Omit<ProviderConfig, "id" | "createdAt">>): Promise<void>;
107
+ delete(id: string): Promise<void>;
108
+ list(): Promise<ProviderConfig[]>;
109
+ }
110
+
111
+ /**
112
+ * SQLite-backed token store implementing ITokenStore.
113
+ *
114
+ * Stores auth tokens as JSON in a `tokens` table within
115
+ * a shared SQLite database. Schema auto-created on construction.
116
+ */
117
+
118
+ declare class SQLiteTokenStore implements ITokenStore {
119
+ private readonly db;
120
+ constructor(db: Database.Database);
121
+ save(provider: string, token: AuthToken): Promise<void>;
122
+ load(provider: string): Promise<AuthToken | null>;
123
+ clear(provider: string): Promise<void>;
124
+ clearAll(): Promise<void>;
125
+ list(): Promise<string[]>;
126
+ }
127
+
128
+ export { SQLiteProviderStore, SQLiteSessionStore, type SQLiteStorage, type SQLiteStorageOptions, SQLiteTokenStore, createSQLiteStorage };
@@ -0,0 +1,435 @@
1
+ import { createRequire } from 'module';
2
+ import 'fs';
3
+ import 'path';
4
+
5
+ // src/chat/sqlite/factory.ts
6
+
7
+ // src/chat/types.ts
8
+ function createChatId() {
9
+ return crypto.randomUUID();
10
+ }
11
+
12
+ // src/errors.ts
13
+ var AgentSDKError = class extends Error {
14
+ /** @internal Marker for cross-bundle identity checks */
15
+ _agentSDKError = true;
16
+ /** Machine-readable error code. Prefer values from the ErrorCode enum. */
17
+ code;
18
+ /** Whether this error is safe to retry */
19
+ retryable;
20
+ /** HTTP status code hint for error classification */
21
+ httpStatus;
22
+ constructor(message, options) {
23
+ super(message, options);
24
+ this.name = "AgentSDKError";
25
+ this.code = options?.code;
26
+ this.retryable = options?.retryable ?? false;
27
+ this.httpStatus = options?.httpStatus;
28
+ }
29
+ /** Check if an error is an AgentSDKError (works across bundled copies) */
30
+ static is(error) {
31
+ return error instanceof Error && "_agentSDKError" in error && error._agentSDKError === true;
32
+ }
33
+ };
34
+
35
+ // src/chat/storage.ts
36
+ var StorageError = class extends AgentSDKError {
37
+ /** Machine-readable error code from the unified ErrorCode enum */
38
+ code;
39
+ constructor(message, code) {
40
+ super(message);
41
+ this.name = "StorageError";
42
+ this.code = code;
43
+ }
44
+ };
45
+
46
+ // src/chat/sqlite/session-store.ts
47
+ var CREATE_SESSIONS_TABLE = `
48
+ CREATE TABLE IF NOT EXISTS sessions (
49
+ id TEXT PRIMARY KEY,
50
+ title TEXT,
51
+ config TEXT NOT NULL,
52
+ metadata TEXT NOT NULL,
53
+ status TEXT NOT NULL DEFAULT 'active',
54
+ backend_session_id TEXT,
55
+ created_at TEXT NOT NULL,
56
+ updated_at TEXT NOT NULL
57
+ )
58
+ `;
59
+ var CREATE_MESSAGES_TABLE = `
60
+ CREATE TABLE IF NOT EXISTS messages (
61
+ id TEXT PRIMARY KEY,
62
+ session_id TEXT NOT NULL,
63
+ role TEXT NOT NULL,
64
+ parts TEXT NOT NULL,
65
+ metadata TEXT,
66
+ status TEXT NOT NULL DEFAULT 'complete',
67
+ created_at TEXT NOT NULL,
68
+ updated_at TEXT,
69
+ position INTEGER NOT NULL,
70
+ FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
71
+ )
72
+ `;
73
+ var CREATE_MESSAGES_SESSION_IDX = `
74
+ CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id, position)
75
+ `;
76
+ var SQLiteSessionStore = class {
77
+ db;
78
+ constructor(db) {
79
+ this.db = db;
80
+ this.db.exec(CREATE_SESSIONS_TABLE);
81
+ this.db.exec(CREATE_MESSAGES_TABLE);
82
+ this.db.exec(CREATE_MESSAGES_SESSION_IDX);
83
+ }
84
+ async createSession(options = {}) {
85
+ const id = createChatId();
86
+ const now = (/* @__PURE__ */ new Date()).toISOString();
87
+ const config = {
88
+ model: "default",
89
+ backend: "default",
90
+ ...options.config
91
+ };
92
+ const metadata = {
93
+ messageCount: 0,
94
+ totalTokens: 0,
95
+ tags: options.tags,
96
+ custom: options.custom
97
+ };
98
+ this.db.prepare(`
99
+ INSERT INTO sessions (id, title, config, metadata, status, created_at, updated_at)
100
+ VALUES (?, ?, ?, ?, 'active', ?, ?)
101
+ `).run(id, options.title ?? null, JSON.stringify(config), JSON.stringify(metadata), now, now);
102
+ return this.buildSession(id, options.title, config, metadata, "active", now, now, []);
103
+ }
104
+ async getSession(id) {
105
+ const row = this.db.prepare("SELECT * FROM sessions WHERE id = ?").get(id);
106
+ if (!row) return null;
107
+ const messages = this.loadAllMessages(row.id);
108
+ return this.rowToSession(row, messages);
109
+ }
110
+ async listSessions(options) {
111
+ const rows = this.db.prepare("SELECT * FROM sessions ORDER BY updated_at DESC").all();
112
+ let sessions = rows.map((r) => this.rowToSession(r, []));
113
+ if (options?.filter) sessions = sessions.filter(options.filter);
114
+ if (options?.sort) sessions.sort(options.sort);
115
+ if (options?.offset) sessions = sessions.slice(options.offset);
116
+ if (options?.limit) sessions = sessions.slice(0, options.limit);
117
+ return sessions;
118
+ }
119
+ async updateTitle(id, title) {
120
+ const result = this.db.prepare(
121
+ "UPDATE sessions SET title = ?, updated_at = ? WHERE id = ?"
122
+ ).run(title, (/* @__PURE__ */ new Date()).toISOString(), id);
123
+ if (result.changes === 0) throw new StorageError(`Session not found: ${id}`, "STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */);
124
+ }
125
+ async updateConfig(id, config) {
126
+ const row = this.db.prepare("SELECT config FROM sessions WHERE id = ?").get(id);
127
+ if (!row) throw new StorageError(`Session not found: ${id}`, "STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */);
128
+ const merged = { ...JSON.parse(row.config), ...config };
129
+ this.db.prepare(
130
+ "UPDATE sessions SET config = ?, updated_at = ? WHERE id = ?"
131
+ ).run(JSON.stringify(merged), (/* @__PURE__ */ new Date()).toISOString(), id);
132
+ }
133
+ async deleteSession(id) {
134
+ const result = this.db.prepare("DELETE FROM sessions WHERE id = ?").run(id);
135
+ if (result.changes === 0) throw new StorageError(`Session not found: ${id}`, "STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */);
136
+ }
137
+ async appendMessage(sessionId, message) {
138
+ const session = this.db.prepare("SELECT id FROM sessions WHERE id = ?").get(sessionId);
139
+ if (!session) throw new StorageError(`Session not found: ${sessionId}`, "STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */);
140
+ const position = this.getNextPosition(sessionId);
141
+ this.db.prepare(`
142
+ INSERT INTO messages (id, session_id, role, parts, metadata, status, created_at, updated_at, position)
143
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
144
+ `).run(
145
+ message.id,
146
+ sessionId,
147
+ message.role,
148
+ JSON.stringify(message.parts),
149
+ message.metadata ? JSON.stringify(message.metadata) : null,
150
+ message.status,
151
+ message.createdAt,
152
+ message.updatedAt ?? null,
153
+ position
154
+ );
155
+ this.incrementMessageCount(sessionId);
156
+ }
157
+ async saveMessages(sessionId, messages) {
158
+ if (messages.length === 0) return;
159
+ const session = this.db.prepare("SELECT id FROM sessions WHERE id = ?").get(sessionId);
160
+ if (!session) throw new StorageError(`Session not found: ${sessionId}`, "STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */);
161
+ const insertMsg = this.db.prepare(`
162
+ INSERT INTO messages (id, session_id, role, parts, metadata, status, created_at, updated_at, position)
163
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
164
+ `);
165
+ const tx = this.db.transaction(() => {
166
+ let pos = this.getNextPosition(sessionId);
167
+ for (const msg of messages) {
168
+ insertMsg.run(
169
+ msg.id,
170
+ sessionId,
171
+ msg.role,
172
+ JSON.stringify(msg.parts),
173
+ msg.metadata ? JSON.stringify(msg.metadata) : null,
174
+ msg.status,
175
+ msg.createdAt,
176
+ msg.updatedAt ?? null,
177
+ pos++
178
+ );
179
+ }
180
+ this.updateSessionMeta(sessionId, messages.length);
181
+ });
182
+ tx();
183
+ }
184
+ async loadMessages(sessionId, options) {
185
+ const session = this.db.prepare("SELECT id FROM sessions WHERE id = ?").get(sessionId);
186
+ if (!session) throw new StorageError(`Session not found: ${sessionId}`, "STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */);
187
+ const total = this.db.prepare(
188
+ "SELECT COUNT(*) as cnt FROM messages WHERE session_id = ?"
189
+ ).get(sessionId).cnt;
190
+ const limit = options?.limit ?? 50;
191
+ const offset = options?.offset ?? 0;
192
+ const rows = this.db.prepare(
193
+ "SELECT * FROM messages WHERE session_id = ? ORDER BY position ASC LIMIT ? OFFSET ?"
194
+ ).all(sessionId, limit, offset);
195
+ return {
196
+ messages: rows.map(rowToMessage),
197
+ total,
198
+ hasMore: offset + limit < total
199
+ };
200
+ }
201
+ async searchSessions(options) {
202
+ const pattern = `%${options.query}%`;
203
+ const limit = options.limit ?? 20;
204
+ const titleMatches = this.db.prepare(
205
+ "SELECT * FROM sessions WHERE title LIKE ? COLLATE NOCASE LIMIT ?"
206
+ ).all(pattern, limit);
207
+ const contentMatches = this.db.prepare(`
208
+ SELECT DISTINCT s.* FROM sessions s
209
+ JOIN messages m ON m.session_id = s.id
210
+ WHERE m.parts LIKE ? COLLATE NOCASE
211
+ LIMIT ?
212
+ `).all(pattern, limit);
213
+ const seen = /* @__PURE__ */ new Set();
214
+ const results = [];
215
+ for (const row of [...titleMatches, ...contentMatches]) {
216
+ if (!seen.has(row.id)) {
217
+ seen.add(row.id);
218
+ results.push(this.rowToSession(row, []));
219
+ }
220
+ }
221
+ return results.slice(0, limit);
222
+ }
223
+ async count() {
224
+ return this.db.prepare("SELECT COUNT(*) as cnt FROM sessions").get().cnt;
225
+ }
226
+ async clear() {
227
+ this.db.exec("DELETE FROM messages");
228
+ this.db.exec("DELETE FROM sessions");
229
+ }
230
+ // ─── Private Helpers ─────────────────────────────────────────
231
+ getNextPosition(sessionId) {
232
+ const result = this.db.prepare(
233
+ "SELECT MAX(position) as maxPos FROM messages WHERE session_id = ?"
234
+ ).get(sessionId);
235
+ return (result.maxPos ?? -1) + 1;
236
+ }
237
+ incrementMessageCount(sessionId) {
238
+ this.db.prepare(`
239
+ UPDATE sessions
240
+ SET metadata = json_set(metadata, '$.messageCount', json_extract(metadata, '$.messageCount') + 1),
241
+ updated_at = ?
242
+ WHERE id = ?
243
+ `).run((/* @__PURE__ */ new Date()).toISOString(), sessionId);
244
+ }
245
+ updateSessionMeta(sessionId, addedCount) {
246
+ this.db.prepare(`
247
+ UPDATE sessions
248
+ SET metadata = json_set(metadata, '$.messageCount', json_extract(metadata, '$.messageCount') + ?),
249
+ updated_at = ?
250
+ WHERE id = ?
251
+ `).run(addedCount, (/* @__PURE__ */ new Date()).toISOString(), sessionId);
252
+ }
253
+ loadAllMessages(sessionId) {
254
+ const rows = this.db.prepare(
255
+ "SELECT * FROM messages WHERE session_id = ? ORDER BY position ASC"
256
+ ).all(sessionId);
257
+ return rows.map(rowToMessage);
258
+ }
259
+ rowToSession(row, messages) {
260
+ return this.buildSession(
261
+ row.id,
262
+ row.title,
263
+ JSON.parse(row.config),
264
+ JSON.parse(row.metadata),
265
+ row.status,
266
+ row.created_at,
267
+ row.updated_at,
268
+ messages
269
+ );
270
+ }
271
+ buildSession(id, title, config, metadata, status, createdAt, updatedAt, messages) {
272
+ return {
273
+ id,
274
+ title: title ?? void 0,
275
+ messages,
276
+ config,
277
+ metadata,
278
+ status,
279
+ createdAt,
280
+ updatedAt
281
+ };
282
+ }
283
+ };
284
+ function rowToMessage(row) {
285
+ return {
286
+ id: row.id,
287
+ role: row.role,
288
+ parts: JSON.parse(row.parts),
289
+ metadata: row.metadata ? JSON.parse(row.metadata) : void 0,
290
+ status: row.status,
291
+ createdAt: row.created_at,
292
+ updatedAt: row.updated_at ?? void 0
293
+ };
294
+ }
295
+
296
+ // src/chat/sqlite/provider-store.ts
297
+ var CREATE_PROVIDERS_TABLE = `
298
+ CREATE TABLE IF NOT EXISTS providers (
299
+ id TEXT PRIMARY KEY,
300
+ backend TEXT NOT NULL,
301
+ model TEXT NOT NULL,
302
+ label TEXT NOT NULL,
303
+ created_at INTEGER NOT NULL
304
+ )
305
+ `;
306
+ var SQLiteProviderStore = class {
307
+ db;
308
+ constructor(db) {
309
+ this.db = db;
310
+ this.db.exec(CREATE_PROVIDERS_TABLE);
311
+ }
312
+ async create(config) {
313
+ this.db.prepare(`
314
+ INSERT INTO providers (id, backend, model, label, created_at)
315
+ VALUES (?, ?, ?, ?, ?)
316
+ `).run(config.id, config.backend, config.model, config.label, config.createdAt);
317
+ }
318
+ async get(id) {
319
+ const row = this.db.prepare("SELECT * FROM providers WHERE id = ?").get(id);
320
+ return row ? rowToProvider(row) : null;
321
+ }
322
+ async update(id, changes) {
323
+ const existing = this.db.prepare("SELECT id FROM providers WHERE id = ?").get(id);
324
+ if (!existing) throw new Error(`Provider "${id}" not found`);
325
+ const sets = [];
326
+ const values = [];
327
+ if (changes.backend !== void 0) {
328
+ sets.push("backend = ?");
329
+ values.push(changes.backend);
330
+ }
331
+ if (changes.model !== void 0) {
332
+ sets.push("model = ?");
333
+ values.push(changes.model);
334
+ }
335
+ if (changes.label !== void 0) {
336
+ sets.push("label = ?");
337
+ values.push(changes.label);
338
+ }
339
+ if (sets.length > 0) {
340
+ values.push(id);
341
+ this.db.prepare(`UPDATE providers SET ${sets.join(", ")} WHERE id = ?`).run(...values);
342
+ }
343
+ }
344
+ async delete(id) {
345
+ this.db.prepare("DELETE FROM providers WHERE id = ?").run(id);
346
+ }
347
+ async list() {
348
+ const rows = this.db.prepare("SELECT * FROM providers ORDER BY created_at ASC").all();
349
+ return rows.map(rowToProvider);
350
+ }
351
+ };
352
+ function rowToProvider(row) {
353
+ return {
354
+ id: row.id,
355
+ backend: row.backend,
356
+ model: row.model,
357
+ label: row.label,
358
+ createdAt: row.created_at
359
+ };
360
+ }
361
+
362
+ // src/chat/sqlite/token-store.ts
363
+ var CREATE_TOKENS_TABLE = `
364
+ CREATE TABLE IF NOT EXISTS tokens (
365
+ provider TEXT PRIMARY KEY,
366
+ token_json TEXT NOT NULL,
367
+ saved_at INTEGER NOT NULL
368
+ )
369
+ `;
370
+ var SQLiteTokenStore = class {
371
+ db;
372
+ constructor(db) {
373
+ this.db = db;
374
+ this.db.exec(CREATE_TOKENS_TABLE);
375
+ }
376
+ async save(provider, token) {
377
+ this.db.prepare(`
378
+ INSERT OR REPLACE INTO tokens (provider, token_json, saved_at)
379
+ VALUES (?, ?, ?)
380
+ `).run(provider, JSON.stringify(token), Date.now());
381
+ }
382
+ async load(provider) {
383
+ const row = this.db.prepare("SELECT token_json FROM tokens WHERE provider = ?").get(provider);
384
+ return row ? JSON.parse(row.token_json) : null;
385
+ }
386
+ async clear(provider) {
387
+ this.db.prepare("DELETE FROM tokens WHERE provider = ?").run(provider);
388
+ }
389
+ async clearAll() {
390
+ this.db.exec("DELETE FROM tokens");
391
+ }
392
+ async list() {
393
+ const rows = this.db.prepare("SELECT provider FROM tokens ORDER BY saved_at ASC").all();
394
+ return rows.map((r) => r.provider);
395
+ }
396
+ };
397
+
398
+ // src/chat/sqlite/factory.ts
399
+ function createSQLiteStorage(pathOrOptions) {
400
+ let db;
401
+ if (typeof pathOrOptions === "string") {
402
+ db = createDatabase(pathOrOptions);
403
+ } else if (pathOrOptions.db) {
404
+ db = pathOrOptions.db;
405
+ } else {
406
+ db = createDatabase(pathOrOptions.dbPath);
407
+ }
408
+ db.pragma("journal_mode = WAL");
409
+ db.pragma("foreign_keys = ON");
410
+ return {
411
+ db,
412
+ sessionStore: new SQLiteSessionStore(db),
413
+ providerStore: new SQLiteProviderStore(db),
414
+ tokenStore: new SQLiteTokenStore(db)
415
+ };
416
+ }
417
+ function createDatabase(dbPath) {
418
+ try {
419
+ const esmRequire = createRequire(import.meta.url);
420
+ const BetterSqlite3 = esmRequire("better-sqlite3");
421
+ return new BetterSqlite3(dbPath);
422
+ } catch (err) {
423
+ const message = err instanceof Error ? err.message : String(err);
424
+ if (message.includes("Cannot find module") || message.includes("MODULE_NOT_FOUND")) {
425
+ throw new Error(
426
+ "better-sqlite3 is required for SQLite storage. Install it: npm install better-sqlite3"
427
+ );
428
+ }
429
+ throw err;
430
+ }
431
+ }
432
+
433
+ export { SQLiteProviderStore, SQLiteSessionStore, SQLiteTokenStore, createSQLiteStorage };
434
+ //# sourceMappingURL=sqlite.js.map
435
+ //# sourceMappingURL=sqlite.js.map