@hebo-ai/gateway 0.9.2 → 0.9.3

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 (213) hide show
  1. package/dist/config.d.ts +2 -0
  2. package/dist/config.js +125 -0
  3. package/dist/endpoints/chat-completions/converters.d.ts +26 -0
  4. package/dist/endpoints/chat-completions/converters.js +525 -0
  5. package/dist/endpoints/chat-completions/handler.d.ts +2 -0
  6. package/dist/endpoints/chat-completions/handler.js +152 -0
  7. package/dist/endpoints/chat-completions/index.d.ts +4 -0
  8. package/dist/endpoints/chat-completions/index.js +4 -0
  9. package/dist/endpoints/chat-completions/otel.d.ts +5 -0
  10. package/dist/endpoints/chat-completions/otel.js +178 -0
  11. package/dist/endpoints/chat-completions/schema.d.ts +1170 -0
  12. package/dist/endpoints/chat-completions/schema.js +252 -0
  13. package/dist/endpoints/conversations/converters.d.ts +8 -0
  14. package/dist/endpoints/conversations/converters.js +29 -0
  15. package/dist/endpoints/conversations/handler.d.ts +2 -0
  16. package/dist/endpoints/conversations/handler.js +259 -0
  17. package/dist/endpoints/conversations/index.d.ts +3 -0
  18. package/dist/endpoints/conversations/index.js +3 -0
  19. package/dist/endpoints/conversations/schema.d.ts +1511 -0
  20. package/dist/endpoints/conversations/schema.js +74 -0
  21. package/dist/endpoints/conversations/storage/dialects/greptime.d.ts +10 -0
  22. package/dist/endpoints/conversations/storage/dialects/greptime.js +87 -0
  23. package/dist/endpoints/conversations/storage/dialects/mysql.d.ts +12 -0
  24. package/dist/endpoints/conversations/storage/dialects/mysql.js +118 -0
  25. package/dist/endpoints/conversations/storage/dialects/postgres.d.ts +16 -0
  26. package/dist/endpoints/conversations/storage/dialects/postgres.js +185 -0
  27. package/dist/endpoints/conversations/storage/dialects/sqlite.d.ts +11 -0
  28. package/dist/endpoints/conversations/storage/dialects/sqlite.js +176 -0
  29. package/dist/endpoints/conversations/storage/dialects/types.d.ts +42 -0
  30. package/dist/endpoints/conversations/storage/dialects/types.js +0 -0
  31. package/dist/endpoints/conversations/storage/dialects/utils.d.ts +25 -0
  32. package/dist/endpoints/conversations/storage/dialects/utils.js +80 -0
  33. package/dist/endpoints/conversations/storage/memory.d.ts +25 -0
  34. package/dist/endpoints/conversations/storage/memory.js +200 -0
  35. package/dist/endpoints/conversations/storage/sql.d.ts +33 -0
  36. package/dist/endpoints/conversations/storage/sql.js +276 -0
  37. package/dist/endpoints/conversations/storage/types.d.ts +39 -0
  38. package/dist/endpoints/conversations/storage/types.js +0 -0
  39. package/dist/endpoints/embeddings/converters.d.ts +10 -0
  40. package/dist/endpoints/embeddings/converters.js +31 -0
  41. package/dist/endpoints/embeddings/handler.d.ts +2 -0
  42. package/dist/endpoints/embeddings/handler.js +99 -0
  43. package/dist/endpoints/embeddings/index.d.ts +4 -0
  44. package/dist/endpoints/embeddings/index.js +4 -0
  45. package/dist/endpoints/embeddings/otel.d.ts +5 -0
  46. package/dist/endpoints/embeddings/otel.js +29 -0
  47. package/dist/endpoints/embeddings/schema.d.ts +44 -0
  48. package/dist/endpoints/embeddings/schema.js +29 -0
  49. package/dist/endpoints/models/converters.d.ts +6 -0
  50. package/dist/endpoints/models/converters.js +42 -0
  51. package/dist/endpoints/models/handler.d.ts +2 -0
  52. package/dist/endpoints/models/handler.js +29 -0
  53. package/dist/endpoints/models/index.d.ts +3 -0
  54. package/dist/endpoints/models/index.js +3 -0
  55. package/dist/endpoints/models/schema.d.ts +42 -0
  56. package/dist/endpoints/models/schema.js +31 -0
  57. package/dist/endpoints/responses/converters.d.ts +17 -0
  58. package/dist/endpoints/responses/converters.js +1037 -0
  59. package/dist/endpoints/responses/handler.d.ts +2 -0
  60. package/dist/endpoints/responses/handler.js +141 -0
  61. package/dist/endpoints/responses/index.d.ts +4 -0
  62. package/dist/endpoints/responses/index.js +4 -0
  63. package/dist/endpoints/responses/otel.d.ts +6 -0
  64. package/dist/endpoints/responses/otel.js +226 -0
  65. package/dist/endpoints/responses/schema.d.ts +2109 -0
  66. package/dist/endpoints/responses/schema.js +314 -0
  67. package/dist/endpoints/shared/converters.d.ts +56 -0
  68. package/dist/endpoints/shared/converters.js +180 -0
  69. package/dist/endpoints/shared/schema.d.ts +70 -0
  70. package/dist/endpoints/shared/schema.js +46 -0
  71. package/dist/errors/ai-sdk.d.ts +2 -0
  72. package/dist/errors/ai-sdk.js +52 -0
  73. package/dist/errors/gateway.d.ts +5 -0
  74. package/dist/errors/gateway.js +13 -0
  75. package/dist/errors/openai.d.ts +15 -0
  76. package/dist/errors/openai.js +40 -0
  77. package/dist/errors/utils.d.ts +24 -0
  78. package/dist/errors/utils.js +46 -0
  79. package/dist/gateway.d.ts +11 -0
  80. package/dist/gateway.js +44 -0
  81. package/dist/index.d.ts +11 -0
  82. package/dist/index.js +10 -0
  83. package/dist/lifecycle.d.ts +3 -0
  84. package/dist/lifecycle.js +114 -0
  85. package/dist/logger/default.d.ts +4 -0
  86. package/dist/logger/default.js +81 -0
  87. package/dist/logger/index.d.ts +11 -0
  88. package/dist/logger/index.js +25 -0
  89. package/dist/middleware/common.d.ts +12 -0
  90. package/dist/middleware/common.js +146 -0
  91. package/dist/middleware/debug.d.ts +3 -0
  92. package/dist/middleware/debug.js +27 -0
  93. package/dist/middleware/matcher.d.ts +28 -0
  94. package/dist/middleware/matcher.js +118 -0
  95. package/dist/middleware/utils.d.ts +2 -0
  96. package/dist/middleware/utils.js +24 -0
  97. package/dist/models/amazon/index.d.ts +2 -0
  98. package/dist/models/amazon/index.js +2 -0
  99. package/dist/models/amazon/middleware.d.ts +3 -0
  100. package/dist/models/amazon/middleware.js +69 -0
  101. package/dist/models/amazon/presets.d.ts +345 -0
  102. package/dist/models/amazon/presets.js +80 -0
  103. package/dist/models/anthropic/index.d.ts +2 -0
  104. package/dist/models/anthropic/index.js +2 -0
  105. package/dist/models/anthropic/middleware.d.ts +5 -0
  106. package/dist/models/anthropic/middleware.js +128 -0
  107. package/dist/models/anthropic/presets.d.ts +711 -0
  108. package/dist/models/anthropic/presets.js +140 -0
  109. package/dist/models/catalog.d.ts +4 -0
  110. package/dist/models/catalog.js +8 -0
  111. package/dist/models/cohere/index.d.ts +2 -0
  112. package/dist/models/cohere/index.js +2 -0
  113. package/dist/models/cohere/middleware.d.ts +3 -0
  114. package/dist/models/cohere/middleware.js +62 -0
  115. package/dist/models/cohere/presets.d.ts +411 -0
  116. package/dist/models/cohere/presets.js +134 -0
  117. package/dist/models/google/index.d.ts +2 -0
  118. package/dist/models/google/index.js +2 -0
  119. package/dist/models/google/middleware.d.ts +8 -0
  120. package/dist/models/google/middleware.js +118 -0
  121. package/dist/models/google/presets.d.ts +815 -0
  122. package/dist/models/google/presets.js +184 -0
  123. package/dist/models/meta/index.d.ts +1 -0
  124. package/dist/models/meta/index.js +1 -0
  125. package/dist/models/meta/presets.d.ts +483 -0
  126. package/dist/models/meta/presets.js +105 -0
  127. package/dist/models/openai/index.d.ts +2 -0
  128. package/dist/models/openai/index.js +2 -0
  129. package/dist/models/openai/middleware.d.ts +4 -0
  130. package/dist/models/openai/middleware.js +89 -0
  131. package/dist/models/openai/presets.d.ts +1319 -0
  132. package/dist/models/openai/presets.js +277 -0
  133. package/dist/models/types.d.ts +20 -0
  134. package/dist/models/types.js +100 -0
  135. package/dist/models/voyage/index.d.ts +2 -0
  136. package/dist/models/voyage/index.js +2 -0
  137. package/dist/models/voyage/middleware.d.ts +2 -0
  138. package/dist/models/voyage/middleware.js +19 -0
  139. package/dist/models/voyage/presets.d.ts +436 -0
  140. package/dist/models/voyage/presets.js +85 -0
  141. package/dist/providers/anthropic/canonical.d.ts +3 -0
  142. package/dist/providers/anthropic/canonical.js +9 -0
  143. package/dist/providers/anthropic/index.d.ts +1 -0
  144. package/dist/providers/anthropic/index.js +1 -0
  145. package/dist/providers/bedrock/canonical.d.ts +17 -0
  146. package/dist/providers/bedrock/canonical.js +64 -0
  147. package/dist/providers/bedrock/index.d.ts +2 -0
  148. package/dist/providers/bedrock/index.js +2 -0
  149. package/dist/providers/bedrock/middleware.d.ts +5 -0
  150. package/dist/providers/bedrock/middleware.js +133 -0
  151. package/dist/providers/cohere/canonical.d.ts +3 -0
  152. package/dist/providers/cohere/canonical.js +17 -0
  153. package/dist/providers/cohere/index.d.ts +1 -0
  154. package/dist/providers/cohere/index.js +1 -0
  155. package/dist/providers/groq/canonical.d.ts +3 -0
  156. package/dist/providers/groq/canonical.js +12 -0
  157. package/dist/providers/groq/index.d.ts +2 -0
  158. package/dist/providers/groq/index.js +2 -0
  159. package/dist/providers/groq/middleware.d.ts +2 -0
  160. package/dist/providers/groq/middleware.js +30 -0
  161. package/dist/providers/openai/canonical.d.ts +3 -0
  162. package/dist/providers/openai/canonical.js +8 -0
  163. package/dist/providers/openai/index.d.ts +1 -0
  164. package/dist/providers/openai/index.js +1 -0
  165. package/dist/providers/registry.d.ts +24 -0
  166. package/dist/providers/registry.js +103 -0
  167. package/dist/providers/types.d.ts +7 -0
  168. package/dist/providers/types.js +11 -0
  169. package/dist/providers/vertex/canonical.d.ts +3 -0
  170. package/dist/providers/vertex/canonical.js +8 -0
  171. package/dist/providers/vertex/index.d.ts +2 -0
  172. package/dist/providers/vertex/index.js +2 -0
  173. package/dist/providers/vertex/middleware.d.ts +2 -0
  174. package/dist/providers/vertex/middleware.js +47 -0
  175. package/dist/providers/voyage/canonical.d.ts +3 -0
  176. package/dist/providers/voyage/canonical.js +7 -0
  177. package/dist/providers/voyage/index.d.ts +1 -0
  178. package/dist/providers/voyage/index.js +1 -0
  179. package/dist/telemetry/ai-sdk.d.ts +2 -0
  180. package/dist/telemetry/ai-sdk.js +31 -0
  181. package/dist/telemetry/baggage.d.ts +1 -0
  182. package/dist/telemetry/baggage.js +24 -0
  183. package/dist/telemetry/fetch.d.ts +2 -0
  184. package/dist/telemetry/fetch.js +49 -0
  185. package/dist/telemetry/gen-ai.d.ts +7 -0
  186. package/dist/telemetry/gen-ai.js +108 -0
  187. package/dist/telemetry/http.d.ts +3 -0
  188. package/dist/telemetry/http.js +54 -0
  189. package/dist/telemetry/index.d.ts +1 -0
  190. package/dist/telemetry/index.js +1 -0
  191. package/dist/telemetry/memory.d.ts +2 -0
  192. package/dist/telemetry/memory.js +43 -0
  193. package/dist/telemetry/span.d.ts +13 -0
  194. package/dist/telemetry/span.js +60 -0
  195. package/dist/types.d.ts +231 -0
  196. package/dist/types.js +2 -0
  197. package/dist/utils/body.d.ts +19 -0
  198. package/dist/utils/body.js +99 -0
  199. package/dist/utils/env.d.ts +2 -0
  200. package/dist/utils/env.js +7 -0
  201. package/dist/utils/headers.d.ts +4 -0
  202. package/dist/utils/headers.js +22 -0
  203. package/dist/utils/preset.d.ts +10 -0
  204. package/dist/utils/preset.js +41 -0
  205. package/dist/utils/request.d.ts +2 -0
  206. package/dist/utils/request.js +43 -0
  207. package/dist/utils/response.d.ts +6 -0
  208. package/dist/utils/response.js +55 -0
  209. package/dist/utils/stream.d.ts +9 -0
  210. package/dist/utils/stream.js +100 -0
  211. package/dist/utils/url.d.ts +4 -0
  212. package/dist/utils/url.js +21 -0
  213. package/package.json +1 -1
@@ -0,0 +1,176 @@
1
+ import { LRUCache } from "lru-cache";
2
+ import { createParamsMapper, dateToNumber, escapeSqlString, jsonStringify } from "./utils";
3
+ const mapParams = createParamsMapper([dateToNumber, jsonStringify]);
4
+ export const SQLiteDialectConfig = {
5
+ placeholder: () => "?",
6
+ quote: (i) => `"${i}"`,
7
+ selectJson: (c) => c,
8
+ jsonExtract: (c, k) => `json_extract(${c}, '$.${escapeSqlString(k)}')`,
9
+ upsertSuffix: (q, pk, cols) => `ON CONFLICT (${pk.map((c) => q(c)).join(", ")}) DO UPDATE SET ${cols
10
+ .map((c) => `${q(c)} = EXCLUDED.${q(c)}`)
11
+ .join(", ")}`,
12
+ supportCreateIndexIfNotExists: true,
13
+ types: {
14
+ varchar: "TEXT",
15
+ json: "TEXT",
16
+ timestamp: "BIGINT",
17
+ index: "B-TREE",
18
+ },
19
+ };
20
+ const MAX_CACHE_SIZE = 100;
21
+ function isBetterSqlite3(client) {
22
+ const c = client;
23
+ return !!client && typeof c["prepare"] === "function" && typeof c["transaction"] === "function";
24
+ }
25
+ function isLibsql(client) {
26
+ const c = client;
27
+ return !!client && typeof c["execute"] === "function" && typeof c["batch"] === "function";
28
+ }
29
+ function isBunSql(client) {
30
+ const c = client;
31
+ return !!client && typeof c["unsafe"] === "function" && typeof c["transaction"] === "function";
32
+ }
33
+ function createBetterSqlite3Executor(db) {
34
+ const cache = new LRUCache({ max: MAX_CACHE_SIZE });
35
+ const getStmt = (sql) => {
36
+ let stmt = cache.get(sql);
37
+ if (!stmt) {
38
+ stmt = db.prepare(sql);
39
+ cache.set(sql, stmt);
40
+ }
41
+ return stmt;
42
+ };
43
+ const executor = {
44
+ all(sql, params) {
45
+ const stmt = getStmt(sql);
46
+ return Promise.resolve(stmt.all.apply(stmt, mapParams(params) ?? []));
47
+ },
48
+ get(sql, params) {
49
+ const stmt = getStmt(sql);
50
+ return Promise.resolve(stmt.get.apply(stmt, mapParams(params) ?? []));
51
+ },
52
+ run(sql, params) {
53
+ const stmt = getStmt(sql);
54
+ const info = stmt.run.apply(stmt, mapParams(params) ?? []);
55
+ return Promise.resolve({ changes: info.changes });
56
+ },
57
+ async transaction(fn) {
58
+ const inTransaction = db.inTransaction;
59
+ if (inTransaction) {
60
+ const savepoint = `sp_${Math.random().toString(36).slice(2)}`;
61
+ db.exec(`SAVEPOINT ${savepoint}`);
62
+ try {
63
+ const result = await fn(executor);
64
+ db.exec(`RELEASE SAVEPOINT ${savepoint}`);
65
+ return result;
66
+ }
67
+ catch (err) {
68
+ db.exec(`ROLLBACK TO SAVEPOINT ${savepoint}`);
69
+ throw err;
70
+ }
71
+ }
72
+ else {
73
+ db.exec("BEGIN");
74
+ try {
75
+ const result = await fn(executor);
76
+ db.exec("COMMIT");
77
+ return result;
78
+ }
79
+ catch (err) {
80
+ db.exec("ROLLBACK");
81
+ throw err;
82
+ }
83
+ }
84
+ },
85
+ };
86
+ return executor;
87
+ }
88
+ function createLibsqlExecutor(client) {
89
+ const executor = {
90
+ async all(sql, params) {
91
+ const rs = await client.execute({ sql, args: mapParams(params) ?? [] });
92
+ return rs.rows;
93
+ },
94
+ async get(sql, params) {
95
+ const rs = await client.execute({ sql, args: mapParams(params) ?? [] });
96
+ return rs.rows?.[0];
97
+ },
98
+ async run(sql, params) {
99
+ const rs = await client.execute({ sql, args: mapParams(params) ?? [] });
100
+ return { changes: rs.rowsAffected };
101
+ },
102
+ async transaction(fn) {
103
+ const tx = await client.transaction("deferred");
104
+ const txExecutor = {
105
+ async all(sql, params) {
106
+ const rs = await tx.execute({ sql, args: mapParams(params) ?? [] });
107
+ return rs.rows;
108
+ },
109
+ async get(sql, params) {
110
+ const rs = await tx.execute({ sql, args: mapParams(params) ?? [] });
111
+ return rs.rows?.[0];
112
+ },
113
+ async run(sql, params) {
114
+ const rs = await tx.execute({ sql, args: mapParams(params) ?? [] });
115
+ return { changes: rs.rowsAffected };
116
+ },
117
+ transaction(txCallback) {
118
+ return txCallback(txExecutor);
119
+ },
120
+ };
121
+ try {
122
+ const result = await fn(txExecutor);
123
+ await tx.commit();
124
+ return result;
125
+ }
126
+ catch (err) {
127
+ await tx.rollback();
128
+ throw err;
129
+ }
130
+ },
131
+ };
132
+ return executor;
133
+ }
134
+ function createBunSqliteExecutor(sql) {
135
+ const executor = {
136
+ all(query, params) {
137
+ return sql.unsafe(query, mapParams(params));
138
+ },
139
+ async get(query, params) {
140
+ const rows = await sql.unsafe(query, mapParams(params));
141
+ return rows?.[0];
142
+ },
143
+ async run(query, params) {
144
+ const res = (await sql.unsafe(query, mapParams(params)));
145
+ const result = res;
146
+ return { changes: result.affectedRows ?? result.count ?? 0 };
147
+ },
148
+ transaction(fn) {
149
+ return sql.transaction((tx) => {
150
+ const txExecutor = createBunSqliteExecutor(tx);
151
+ txExecutor.transaction = (f) => f(txExecutor);
152
+ return fn(txExecutor);
153
+ });
154
+ },
155
+ };
156
+ return executor;
157
+ }
158
+ export class SqliteDialect {
159
+ executor;
160
+ config = SQLiteDialectConfig;
161
+ constructor(options) {
162
+ const { client } = options;
163
+ if (isBetterSqlite3(client)) {
164
+ this.executor = createBetterSqlite3Executor(client);
165
+ }
166
+ else if (isLibsql(client)) {
167
+ this.executor = createLibsqlExecutor(client);
168
+ }
169
+ else if (isBunSql(client)) {
170
+ this.executor = createBunSqliteExecutor(client);
171
+ }
172
+ else {
173
+ throw new Error("Unsupported SQLite client");
174
+ }
175
+ }
176
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Lightweight interface for Bun's SQL client.
3
+ *
4
+ * We define this locally instead of importing from "bun" to avoid leaking Bun-only
5
+ * types in our public API. This prevents TypeScript compilation errors for users
6
+ * who are not using Bun and don't have @types/bun installed.
7
+ *
8
+ * Because TypeScript uses structural typing, a real Bun SQL instance will still
9
+ * match this interface perfectly.
10
+ */
11
+ export interface BunSql {
12
+ unsafe<T = any>(query: string, params?: unknown[]): Promise<T>;
13
+ transaction<T>(fn: (tx: BunSql) => Promise<T>): Promise<T>;
14
+ }
15
+ export interface QueryExecutor {
16
+ all<T>(sql: string, params?: unknown[]): Promise<T[]>;
17
+ get<T>(sql: string, params?: unknown[]): Promise<T | undefined>;
18
+ run(sql: string, params?: unknown[]): Promise<{
19
+ changes: number;
20
+ }>;
21
+ transaction<T>(fn: (executor: QueryExecutor) => Promise<T>): Promise<T>;
22
+ }
23
+ export interface DialectConfig {
24
+ placeholder: (index: number) => string;
25
+ quote: (name: string) => string;
26
+ selectJson: (column: string) => string;
27
+ jsonExtract: (column: string, key: string) => string;
28
+ upsertSuffix?: (q: (n: string) => string, pk: string[], updateCols: string[]) => string;
29
+ supportCreateIndexIfNotExists?: boolean;
30
+ limitAsLiteral?: boolean;
31
+ partitionClause?: (columns: string[]) => string;
32
+ types: {
33
+ varchar: string;
34
+ json: string;
35
+ timestamp: string;
36
+ index: "BRIN" | "B-TREE" | "TIME";
37
+ };
38
+ }
39
+ export interface SqlDialect {
40
+ executor: QueryExecutor;
41
+ config: DialectConfig;
42
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Normalizes a list of parameters by applying a chain of atomic mappers to each value.
3
+ */
4
+ export declare function createParamsMapper(mappers: ((v: unknown) => unknown)[]): (params?: unknown[]) => (string | number | bigint | boolean | null)[];
5
+ /**
6
+ * Normalizes an object (row) by applying a chain of atomic mappers.
7
+ * Mappers are expected to mutate the object for performance and to avoid spreads.
8
+ */
9
+ export declare function createRowMapper<T>(mappers: ((row: Record<string, unknown>) => Record<string, unknown>)[]): (row: Record<string, unknown>) => T;
10
+ /**
11
+ * Atomic mappers for input parameters.
12
+ */
13
+ export declare const dateToNumber: (v: unknown) => unknown;
14
+ export declare const dateToBigInt: (v: unknown) => unknown;
15
+ export declare const jsonStringify: (v: unknown, asBinary?: boolean) => unknown;
16
+ /**
17
+ * Escapes single quotes in a string for use in SQL literals.
18
+ */
19
+ export declare const escapeSqlString: (str: string) => string;
20
+ /**
21
+ * Atomic mappers for database rows.
22
+ */
23
+ export declare const parseJson: (key: string) => (row: Record<string, unknown>) => Record<string, unknown>;
24
+ export declare const toMilliseconds: (key: string) => (row: Record<string, unknown>) => Record<string, unknown>;
25
+ export declare const mergeData: (key: string) => (row: Record<string, unknown>) => Record<string, unknown>;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Generic utility to chain multiple functions together.
3
+ */
4
+ function pipe(fns) {
5
+ return (v) => {
6
+ let result = v;
7
+ for (let i = 0; i < fns.length; i++) {
8
+ const fn = fns[i];
9
+ if (fn) {
10
+ result = fn(result);
11
+ }
12
+ }
13
+ return result;
14
+ };
15
+ }
16
+ /**
17
+ * Normalizes a list of parameters by applying a chain of atomic mappers to each value.
18
+ */
19
+ export function createParamsMapper(mappers) {
20
+ const p = pipe(mappers);
21
+ return (params) => params?.map((v) => p(v));
22
+ }
23
+ /**
24
+ * Normalizes an object (row) by applying a chain of atomic mappers.
25
+ * Mappers are expected to mutate the object for performance and to avoid spreads.
26
+ */
27
+ export function createRowMapper(mappers) {
28
+ const p = pipe(mappers);
29
+ return (row) => p(row);
30
+ }
31
+ /**
32
+ * Atomic mappers for input parameters.
33
+ */
34
+ export const dateToNumber = (v) => (v instanceof Date ? v.getTime() : v);
35
+ export const dateToBigInt = (v) => (v instanceof Date ? BigInt(v.getTime()) : v);
36
+ export const jsonStringify = (v, asBinary = false) => v !== null && typeof v === "object" && !(v instanceof Date)
37
+ ? asBinary
38
+ ? new TextEncoder().encode(JSON.stringify(v))
39
+ : JSON.stringify(v)
40
+ : v;
41
+ /**
42
+ * Escapes single quotes in a string for use in SQL literals.
43
+ */
44
+ export const escapeSqlString = (str) => str.replaceAll("'", "''");
45
+ /**
46
+ * WORKAROUND: GreptimeDB can return Rust-style Unicode escapes (\u{xxxx})
47
+ * inside JSON strings, which is invalid JSON and causes crashes in JSON.parse.
48
+ * This normalization converts those escapes back into literal characters before parsing.
49
+ */
50
+ function normalizeJsonUnicodeEscapes(value) {
51
+ return value.replaceAll(/\\u\{([0-9a-fA-F]+)\}/g, (_, hex) => String.fromCodePoint(+`0x${hex}`));
52
+ }
53
+ /**
54
+ * Atomic mappers for database rows.
55
+ */
56
+ export const parseJson = (key) => (row) => {
57
+ const val = row[key];
58
+ if (typeof val === "string") {
59
+ row[key] = val === "" || val === "{}" ? {} : JSON.parse(normalizeJsonUnicodeEscapes(val));
60
+ }
61
+ return row;
62
+ };
63
+ export const toMilliseconds = (key) => (row) => {
64
+ const v = row[key];
65
+ if (v instanceof Date) {
66
+ row[key] = v.getTime();
67
+ }
68
+ else if (typeof v === "number" || typeof v === "bigint" || typeof v === "string") {
69
+ row[key] = Number(v);
70
+ }
71
+ return row;
72
+ };
73
+ export const mergeData = (key) => (row) => {
74
+ const data = row[key];
75
+ if (data !== null && typeof data === "object") {
76
+ Object.assign(row, data);
77
+ delete row[key];
78
+ }
79
+ return row;
80
+ };
@@ -0,0 +1,25 @@
1
+ import type { ConversationStorage, ConversationEntity, ConversationItemEntity, ConversationMetadata, ConversationItemInput, ConversationQueryOptions } from "./types";
2
+ export declare class InMemoryStorage implements ConversationStorage {
3
+ private conversations;
4
+ private items;
5
+ constructor(options?: {
6
+ maxSize?: number;
7
+ });
8
+ private estimateSize;
9
+ private mapItem;
10
+ createConversation(params: {
11
+ metadata?: ConversationMetadata;
12
+ items?: ConversationItemInput[];
13
+ }): Promise<ConversationEntity>;
14
+ getConversation(id: string): Promise<ConversationEntity | undefined>;
15
+ listConversations(params: ConversationQueryOptions): Promise<ConversationEntity[]>;
16
+ updateConversation(id: string, metadata: ConversationMetadata): Promise<ConversationEntity | undefined>;
17
+ deleteConversation(id: string): Promise<{
18
+ id: string;
19
+ deleted: boolean;
20
+ }>;
21
+ addItems(conversationId: string, items: ConversationItemInput[]): Promise<ConversationItemEntity[] | undefined>;
22
+ getItem(conversationId: string, itemId: string): Promise<ConversationItemEntity | undefined>;
23
+ deleteItem(conversationId: string, itemId: string): Promise<ConversationEntity | undefined>;
24
+ listItems(conversationId: string, params: ConversationQueryOptions): Promise<ConversationItemEntity[] | undefined>;
25
+ }
@@ -0,0 +1,200 @@
1
+ import { LRUCache } from "lru-cache";
2
+ import { v7 as uuidv7 } from "uuid";
3
+ export class InMemoryStorage {
4
+ conversations = new Map();
5
+ items;
6
+ constructor(options) {
7
+ // Default to 256MB
8
+ const maxSize = options?.maxSize ?? 256 * 1024 * 1024;
9
+ this.items = new LRUCache({
10
+ maxSize,
11
+ sizeCalculation: (items) => Math.max(1, this.estimateSize(items)),
12
+ noDisposeOnSet: true,
13
+ dispose: (_value, key) => {
14
+ this.conversations.delete(key);
15
+ },
16
+ });
17
+ }
18
+ estimateSize(root) {
19
+ let total = 0;
20
+ const stack = [root];
21
+ while (stack.length > 0) {
22
+ const obj = stack.pop();
23
+ if (obj === null || obj === undefined)
24
+ continue;
25
+ const t = typeof obj;
26
+ if (t === "string") {
27
+ total += obj.length * 2;
28
+ continue;
29
+ }
30
+ if (t !== "object")
31
+ continue;
32
+ if (ArrayBuffer.isView(obj)) {
33
+ total += obj.byteLength;
34
+ continue;
35
+ }
36
+ if (Array.isArray(obj)) {
37
+ const arr = obj;
38
+ for (let i = 0, n = arr.length; i < n; i++)
39
+ stack.push(arr[i]);
40
+ continue;
41
+ }
42
+ if (obj instanceof Map) {
43
+ for (const [k, v] of obj) {
44
+ stack.push(k);
45
+ stack.push(v);
46
+ }
47
+ continue;
48
+ }
49
+ const rec = obj;
50
+ for (const k in rec)
51
+ stack.push(rec[k]);
52
+ }
53
+ return total;
54
+ }
55
+ mapItem(conversationId, input) {
56
+ const item = input;
57
+ item.id ??= uuidv7();
58
+ item.conversation_id = conversationId;
59
+ item.created_at = Date.now();
60
+ return item;
61
+ }
62
+ createConversation(params) {
63
+ const id = uuidv7();
64
+ const conversation = {
65
+ id,
66
+ created_at: Date.now(),
67
+ metadata: params.metadata ?? null,
68
+ };
69
+ const itemMap = new Map();
70
+ if (params.items) {
71
+ for (const input of params.items) {
72
+ const item = this.mapItem(id, input);
73
+ itemMap.set(item.id, item);
74
+ }
75
+ }
76
+ this.conversations.set(id, conversation);
77
+ this.items.set(id, itemMap);
78
+ return Promise.resolve(conversation);
79
+ }
80
+ getConversation(id) {
81
+ // Updates the LRU position
82
+ if (this.items.get(id) === undefined) {
83
+ return Promise.resolve(undefined);
84
+ }
85
+ return Promise.resolve(this.conversations.get(id));
86
+ }
87
+ listConversations(params) {
88
+ const { after, order, limit, metadata } = params;
89
+ if (limit <= 0)
90
+ return Promise.resolve([]);
91
+ let results = Array.from(this.conversations.values());
92
+ // Filter by metadata
93
+ if (metadata) {
94
+ results = results.filter((conv) => {
95
+ if (!conv.metadata)
96
+ return false;
97
+ for (const [key, value] of Object.entries(metadata)) {
98
+ if (conv.metadata[key] !== value)
99
+ return false;
100
+ }
101
+ return true;
102
+ });
103
+ }
104
+ // Sort by created_at (and ID as tiebreaker for cursor consistency)
105
+ results.sort((a, b) => {
106
+ if (a.created_at !== b.created_at) {
107
+ return order === "asc" ? a.created_at - b.created_at : b.created_at - a.created_at;
108
+ }
109
+ return order === "asc" ? a.id.localeCompare(b.id) : b.id.localeCompare(a.id);
110
+ });
111
+ // Pagination: after
112
+ if (after) {
113
+ const index = results.findIndex((conv) => conv.id === after);
114
+ if (index === -1)
115
+ return Promise.resolve([]);
116
+ results = results.slice(index + 1);
117
+ }
118
+ return Promise.resolve(results.slice(0, limit));
119
+ }
120
+ updateConversation(id, metadata) {
121
+ // Updates the LRU position
122
+ if (this.items.get(id) === undefined) {
123
+ return Promise.resolve(undefined);
124
+ }
125
+ const conversation = this.conversations.get(id);
126
+ if (conversation) {
127
+ conversation.metadata = metadata ?? null;
128
+ }
129
+ return Promise.resolve(conversation);
130
+ }
131
+ deleteConversation(id) {
132
+ // Triggers the dispose handler which cleans up this.conversations
133
+ const deleted = this.items.delete(id);
134
+ return Promise.resolve({ id, deleted });
135
+ }
136
+ addItems(conversationId, items) {
137
+ const existing = this.items.get(conversationId);
138
+ if (!existing) {
139
+ return Promise.resolve(undefined);
140
+ }
141
+ const mappedItems = [];
142
+ for (const input of items) {
143
+ const item = this.mapItem(conversationId, input);
144
+ existing.set(item.id, item);
145
+ mappedItems.push(item);
146
+ }
147
+ // Recalculate the cache size
148
+ this.items.set(conversationId, existing);
149
+ return Promise.resolve(mappedItems);
150
+ }
151
+ getItem(conversationId, itemId) {
152
+ return Promise.resolve(this.items.get(conversationId)?.get(itemId));
153
+ }
154
+ deleteItem(conversationId, itemId) {
155
+ const existing = this.items.get(conversationId);
156
+ if (!existing)
157
+ return Promise.resolve(undefined);
158
+ if (existing.delete(itemId)) {
159
+ // Recalculate the cache size
160
+ this.items.set(conversationId, existing);
161
+ }
162
+ return Promise.resolve(this.conversations.get(conversationId));
163
+ }
164
+ listItems(conversationId, params) {
165
+ const { after, order, limit } = params;
166
+ const existing = this.items.get(conversationId);
167
+ if (!existing)
168
+ return Promise.resolve(undefined);
169
+ if (limit <= 0)
170
+ return Promise.resolve([]);
171
+ // If after is provided but doesn't exist, return empty list
172
+ if (after && !existing.has(after))
173
+ return Promise.resolve([]);
174
+ const out = [];
175
+ if (order === "asc") {
176
+ let seen = after === null || after === undefined;
177
+ for (const item of existing.values()) {
178
+ if (!seen) {
179
+ if (item.id === after)
180
+ seen = true;
181
+ continue;
182
+ }
183
+ out.push(item);
184
+ if (out.length === limit)
185
+ break;
186
+ }
187
+ return Promise.resolve(out);
188
+ }
189
+ // desc
190
+ for (const item of existing.values()) {
191
+ if (after !== null && after !== undefined && item.id === after)
192
+ break;
193
+ out.push(item);
194
+ if (out.length > limit)
195
+ out.shift(); // bounded buffer
196
+ }
197
+ out.reverse();
198
+ return Promise.resolve(out);
199
+ }
200
+ }
@@ -0,0 +1,33 @@
1
+ import type { SqlDialect } from "./dialects/types";
2
+ import type { ConversationStorage, ConversationEntity, ConversationItemEntity, ConversationMetadata, ConversationItemInput, ConversationQueryOptions } from "./types";
3
+ export declare class SqlStorage implements ConversationStorage {
4
+ readonly dialect: SqlDialect;
5
+ constructor(options: SqlDialect | {
6
+ dialect: SqlDialect;
7
+ });
8
+ private get executor();
9
+ private get config();
10
+ migrate(): Promise<void>;
11
+ createConversation(params: {
12
+ metadata?: ConversationMetadata;
13
+ items?: ConversationItemInput[];
14
+ }): Promise<ConversationEntity>;
15
+ getConversation(id: string): Promise<ConversationEntity | undefined>;
16
+ private getConversationInternal;
17
+ listConversations(params: ConversationQueryOptions): Promise<ConversationEntity[]>;
18
+ updateConversation(id: string, metadata: ConversationMetadata): Promise<ConversationEntity | undefined>;
19
+ deleteConversation(id: string): Promise<{
20
+ id: string;
21
+ deleted: boolean;
22
+ }>;
23
+ addItems(conversationId: string, items: ConversationItemInput[]): Promise<ConversationItemEntity[] | undefined>;
24
+ private addItemsInternal;
25
+ getItem(conversationId: string, itemId: string): Promise<ConversationItemEntity | undefined>;
26
+ deleteItem(conversationId: string, itemId: string): Promise<ConversationEntity | undefined>;
27
+ listItems(conversationId: string, params: ConversationQueryOptions): Promise<ConversationItemEntity[] | undefined>;
28
+ }
29
+ export * from "./dialects/greptime";
30
+ export * from "./dialects/mysql";
31
+ export * from "./dialects/postgres";
32
+ export * from "./dialects/sqlite";
33
+ export * from "./dialects/types";