agents 0.13.1 → 0.13.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.
- package/dist/{agent-tool-types-Dn9n-3SI.d.ts → agent-tool-types-l98LCbBl.d.ts} +49 -9
- package/dist/agent-tool-types.d.ts +1 -1
- package/dist/{agent-tools-B1ttU-pq.d.ts → agent-tools-Bg5ilERh.d.ts} +2 -2
- package/dist/agent-tools.d.ts +1 -1
- package/dist/chat/index.d.ts +58 -5
- package/dist/chat/index.js +50 -1
- package/dist/chat/index.js.map +1 -1
- package/dist/chat-sdk/index.d.ts +135 -0
- package/dist/chat-sdk/index.js +453 -0
- package/dist/chat-sdk/index.js.map +1 -0
- package/dist/client.d.ts +1 -1
- package/dist/{compaction-helpers-DAe-xiVY.d.ts → compaction-helpers-B-pG5J22.d.ts} +35 -4
- package/dist/{compaction-helpers-DvcZnvQ1.js → compaction-helpers-fJyf8j4m.js} +16 -7
- package/dist/compaction-helpers-fJyf8j4m.js.map +1 -0
- package/dist/experimental/memory/session/index.d.ts +36 -6
- package/dist/experimental/memory/session/index.js +92 -8
- package/dist/experimental/memory/session/index.js.map +1 -1
- package/dist/experimental/memory/utils/index.d.ts +3 -3
- package/dist/experimental/memory/utils/index.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +140 -34
- package/dist/index.js.map +1 -1
- package/dist/mcp/client.d.ts +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/sub-routing.d.ts +1 -1
- package/dist/workflows.d.ts +1 -1
- package/package.json +11 -1
- package/dist/compaction-helpers-DvcZnvQ1.js.map +0 -1
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
import { Agent, getCurrentAgent } from "../index.js";
|
|
2
|
+
//#region src/chat-sdk/agent.ts
|
|
3
|
+
const NEXT_CLEANUP_AT_KEY = "next_cleanup_at";
|
|
4
|
+
const CLEANUP_SCHEDULE_ID_KEY = "cleanup_schedule_id";
|
|
5
|
+
var ChatSdkStateAgent = class extends Agent {
|
|
6
|
+
onStart() {
|
|
7
|
+
this.migrate();
|
|
8
|
+
this.scheduleNextCleanup();
|
|
9
|
+
}
|
|
10
|
+
subscribe(threadId) {
|
|
11
|
+
this.sql`
|
|
12
|
+
INSERT OR IGNORE INTO chat_sdk_state_subscriptions (thread_id)
|
|
13
|
+
VALUES (${threadId})
|
|
14
|
+
`;
|
|
15
|
+
}
|
|
16
|
+
unsubscribe(threadId) {
|
|
17
|
+
this.sql`
|
|
18
|
+
DELETE FROM chat_sdk_state_subscriptions
|
|
19
|
+
WHERE thread_id = ${threadId}
|
|
20
|
+
`;
|
|
21
|
+
}
|
|
22
|
+
isSubscribed(threadId) {
|
|
23
|
+
return this.sql`
|
|
24
|
+
SELECT 1 as found
|
|
25
|
+
FROM chat_sdk_state_subscriptions
|
|
26
|
+
WHERE thread_id = ${threadId}
|
|
27
|
+
LIMIT 1
|
|
28
|
+
`.length > 0;
|
|
29
|
+
}
|
|
30
|
+
async acquireLock(threadId, ttlMs) {
|
|
31
|
+
const result = this.ctx.storage.transactionSync(() => {
|
|
32
|
+
const now = Date.now();
|
|
33
|
+
this.ctx.storage.sql.exec("DELETE FROM chat_sdk_state_locks WHERE thread_id = ? AND expires_at <= ?", threadId, now);
|
|
34
|
+
if (this.ctx.storage.sql.exec("SELECT 1 FROM chat_sdk_state_locks WHERE thread_id = ? LIMIT 1", threadId).toArray().length > 0) return null;
|
|
35
|
+
const token = crypto.randomUUID();
|
|
36
|
+
const expiresAt = now + ttlMs;
|
|
37
|
+
this.ctx.storage.sql.exec("INSERT INTO chat_sdk_state_locks (thread_id, token, expires_at) VALUES (?, ?, ?)", threadId, token, expiresAt);
|
|
38
|
+
return {
|
|
39
|
+
threadId,
|
|
40
|
+
token,
|
|
41
|
+
expiresAt
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
await this.scheduleCleanupForExpiry(result?.expiresAt ?? null);
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
releaseLock(threadId, token) {
|
|
48
|
+
this.sql`
|
|
49
|
+
DELETE FROM chat_sdk_state_locks
|
|
50
|
+
WHERE thread_id = ${threadId} AND token = ${token}
|
|
51
|
+
`;
|
|
52
|
+
}
|
|
53
|
+
async extendLock(threadId, token, ttlMs) {
|
|
54
|
+
const result = this.ctx.storage.transactionSync(() => {
|
|
55
|
+
const now = Date.now();
|
|
56
|
+
return this.ctx.storage.sql.exec(`UPDATE chat_sdk_state_locks SET expires_at = ?
|
|
57
|
+
WHERE thread_id = ? AND token = ? AND expires_at > ?
|
|
58
|
+
RETURNING thread_id`, now + ttlMs, threadId, token, now).toArray().length > 0;
|
|
59
|
+
});
|
|
60
|
+
if (result) await this.scheduleCleanupForExpiry(Date.now() + ttlMs);
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
forceReleaseLock(threadId) {
|
|
64
|
+
this.sql`
|
|
65
|
+
DELETE FROM chat_sdk_state_locks
|
|
66
|
+
WHERE thread_id = ${threadId}
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
async enqueue(threadId, value, maxSize) {
|
|
70
|
+
const parsed = parseQueueEntry(value);
|
|
71
|
+
const count = this.ctx.storage.transactionSync(() => {
|
|
72
|
+
this.ctx.storage.sql.exec("INSERT INTO chat_sdk_state_queue (thread_id, value, enqueued_at, expires_at) VALUES (?, ?, ?, ?)", threadId, value, parsed.enqueuedAt, parsed.expiresAt);
|
|
73
|
+
this.ctx.storage.sql.exec(`DELETE FROM chat_sdk_state_queue WHERE thread_id = ? AND id NOT IN (
|
|
74
|
+
SELECT id FROM chat_sdk_state_queue
|
|
75
|
+
WHERE thread_id = ?
|
|
76
|
+
ORDER BY id DESC
|
|
77
|
+
LIMIT ?
|
|
78
|
+
)`, threadId, threadId, maxSize);
|
|
79
|
+
return this.ctx.storage.sql.exec("SELECT COUNT(*) as count FROM chat_sdk_state_queue WHERE thread_id = ?", threadId).one().count;
|
|
80
|
+
});
|
|
81
|
+
await this.scheduleCleanupForExpiry(parsed.expiresAt);
|
|
82
|
+
return count;
|
|
83
|
+
}
|
|
84
|
+
popQueue(threadId) {
|
|
85
|
+
return this.ctx.storage.transactionSync(() => {
|
|
86
|
+
const now = Date.now();
|
|
87
|
+
this.ctx.storage.sql.exec("DELETE FROM chat_sdk_state_queue WHERE thread_id = ? AND expires_at <= ?", threadId, now);
|
|
88
|
+
const row = this.ctx.storage.sql.exec("SELECT id, value FROM chat_sdk_state_queue WHERE thread_id = ? ORDER BY id ASC LIMIT 1", threadId).toArray()[0];
|
|
89
|
+
if (!row) return null;
|
|
90
|
+
this.ctx.storage.sql.exec("DELETE FROM chat_sdk_state_queue WHERE id = ?", row.id);
|
|
91
|
+
return row.value;
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
queueDepth(threadId) {
|
|
95
|
+
return this.sql`
|
|
96
|
+
SELECT COUNT(*) as count
|
|
97
|
+
FROM chat_sdk_state_queue
|
|
98
|
+
WHERE thread_id = ${threadId} AND expires_at > ${Date.now()}
|
|
99
|
+
`[0]?.count ?? 0;
|
|
100
|
+
}
|
|
101
|
+
async listAppend(key, value, maxLength, ttlMs) {
|
|
102
|
+
const expiresAt = ttlMs && ttlMs > 0 ? Date.now() + ttlMs : null;
|
|
103
|
+
this.ctx.storage.transactionSync(() => {
|
|
104
|
+
this.ctx.storage.sql.exec("INSERT INTO chat_sdk_state_lists (key, value, expires_at) VALUES (?, ?, ?)", key, value, expiresAt);
|
|
105
|
+
if (expiresAt !== null) this.ctx.storage.sql.exec("UPDATE chat_sdk_state_lists SET expires_at = ? WHERE key = ?", expiresAt, key);
|
|
106
|
+
if (maxLength != null && maxLength > 0) this.ctx.storage.sql.exec(`DELETE FROM chat_sdk_state_lists WHERE key = ? AND id NOT IN (
|
|
107
|
+
SELECT id FROM chat_sdk_state_lists
|
|
108
|
+
WHERE key = ?
|
|
109
|
+
ORDER BY id DESC
|
|
110
|
+
LIMIT ?
|
|
111
|
+
)`, key, key, maxLength);
|
|
112
|
+
});
|
|
113
|
+
await this.scheduleCleanupForExpiry(expiresAt);
|
|
114
|
+
}
|
|
115
|
+
listGet(key) {
|
|
116
|
+
const now = Date.now();
|
|
117
|
+
this.sql`
|
|
118
|
+
DELETE FROM chat_sdk_state_lists
|
|
119
|
+
WHERE key = ${key}
|
|
120
|
+
AND expires_at IS NOT NULL
|
|
121
|
+
AND expires_at <= ${now}
|
|
122
|
+
`;
|
|
123
|
+
return this.sql`
|
|
124
|
+
SELECT value
|
|
125
|
+
FROM chat_sdk_state_lists
|
|
126
|
+
WHERE key = ${key}
|
|
127
|
+
ORDER BY id ASC
|
|
128
|
+
`.map((row) => row.value);
|
|
129
|
+
}
|
|
130
|
+
cacheGet(key) {
|
|
131
|
+
return this.readCacheValue(key, Date.now());
|
|
132
|
+
}
|
|
133
|
+
async cacheSet(key, value, ttlMs) {
|
|
134
|
+
const expiresAt = ttlMs && ttlMs > 0 ? Date.now() + ttlMs : null;
|
|
135
|
+
this.upsertCacheValue(key, value, expiresAt);
|
|
136
|
+
await this.scheduleCleanupForExpiry(expiresAt);
|
|
137
|
+
}
|
|
138
|
+
async cacheSetIfNotExists(key, value, ttlMs) {
|
|
139
|
+
const now = Date.now();
|
|
140
|
+
const inserted = this.ctx.storage.transactionSync(() => {
|
|
141
|
+
this.ctx.storage.sql.exec("DELETE FROM chat_sdk_state_cache WHERE key = ? AND expires_at IS NOT NULL AND expires_at <= ?", key, now);
|
|
142
|
+
if (this.readCacheValue(key, now) !== null) return false;
|
|
143
|
+
const expiresAt = ttlMs && ttlMs > 0 ? now + ttlMs : null;
|
|
144
|
+
this.upsertCacheValue(key, value, expiresAt);
|
|
145
|
+
return true;
|
|
146
|
+
});
|
|
147
|
+
if (inserted) {
|
|
148
|
+
const expiresAt = ttlMs && ttlMs > 0 ? Date.now() + ttlMs : null;
|
|
149
|
+
await this.scheduleCleanupForExpiry(expiresAt);
|
|
150
|
+
}
|
|
151
|
+
return inserted;
|
|
152
|
+
}
|
|
153
|
+
cacheDelete(key) {
|
|
154
|
+
this.sql`
|
|
155
|
+
DELETE FROM chat_sdk_state_cache
|
|
156
|
+
WHERE key = ${key}
|
|
157
|
+
`;
|
|
158
|
+
}
|
|
159
|
+
async cleanupExpired(payload) {
|
|
160
|
+
const current = this.readCleanupMetadata();
|
|
161
|
+
if (payload?.expiresAt !== void 0 && current.nextCleanupAt !== null && payload.expiresAt !== current.nextCleanupAt) return;
|
|
162
|
+
const now = Date.now();
|
|
163
|
+
this.clearCleanupMetadata();
|
|
164
|
+
this.sql`
|
|
165
|
+
DELETE FROM chat_sdk_state_locks
|
|
166
|
+
WHERE expires_at <= ${now}
|
|
167
|
+
`;
|
|
168
|
+
this.sql`
|
|
169
|
+
DELETE FROM chat_sdk_state_cache
|
|
170
|
+
WHERE expires_at IS NOT NULL AND expires_at <= ${now}
|
|
171
|
+
`;
|
|
172
|
+
this.sql`
|
|
173
|
+
DELETE FROM chat_sdk_state_queue
|
|
174
|
+
WHERE expires_at <= ${now}
|
|
175
|
+
`;
|
|
176
|
+
this.sql`
|
|
177
|
+
DELETE FROM chat_sdk_state_lists
|
|
178
|
+
WHERE expires_at IS NOT NULL AND expires_at <= ${now}
|
|
179
|
+
`;
|
|
180
|
+
await this.scheduleNextCleanup();
|
|
181
|
+
}
|
|
182
|
+
migrate() {
|
|
183
|
+
this.sql`
|
|
184
|
+
CREATE TABLE IF NOT EXISTS chat_sdk_state_subscriptions (
|
|
185
|
+
thread_id TEXT PRIMARY KEY
|
|
186
|
+
)
|
|
187
|
+
`;
|
|
188
|
+
this.sql`
|
|
189
|
+
CREATE TABLE IF NOT EXISTS chat_sdk_state_locks (
|
|
190
|
+
thread_id TEXT PRIMARY KEY,
|
|
191
|
+
token TEXT NOT NULL,
|
|
192
|
+
expires_at INTEGER NOT NULL
|
|
193
|
+
)
|
|
194
|
+
`;
|
|
195
|
+
this.sql`
|
|
196
|
+
CREATE TABLE IF NOT EXISTS chat_sdk_state_cache (
|
|
197
|
+
key TEXT PRIMARY KEY,
|
|
198
|
+
value TEXT NOT NULL,
|
|
199
|
+
expires_at INTEGER
|
|
200
|
+
)
|
|
201
|
+
`;
|
|
202
|
+
this.sql`
|
|
203
|
+
CREATE TABLE IF NOT EXISTS chat_sdk_state_queue (
|
|
204
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
205
|
+
thread_id TEXT NOT NULL,
|
|
206
|
+
value TEXT NOT NULL,
|
|
207
|
+
enqueued_at INTEGER NOT NULL,
|
|
208
|
+
expires_at INTEGER NOT NULL
|
|
209
|
+
)
|
|
210
|
+
`;
|
|
211
|
+
this.sql`
|
|
212
|
+
CREATE TABLE IF NOT EXISTS chat_sdk_state_lists (
|
|
213
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
214
|
+
key TEXT NOT NULL,
|
|
215
|
+
value TEXT NOT NULL,
|
|
216
|
+
expires_at INTEGER
|
|
217
|
+
)
|
|
218
|
+
`;
|
|
219
|
+
this.sql`
|
|
220
|
+
CREATE TABLE IF NOT EXISTS chat_sdk_state_metadata (
|
|
221
|
+
key TEXT PRIMARY KEY,
|
|
222
|
+
value TEXT NOT NULL
|
|
223
|
+
)
|
|
224
|
+
`;
|
|
225
|
+
this.sql`
|
|
226
|
+
CREATE INDEX IF NOT EXISTS idx_chat_sdk_state_locks_expires
|
|
227
|
+
ON chat_sdk_state_locks(expires_at)
|
|
228
|
+
`;
|
|
229
|
+
this.sql`
|
|
230
|
+
CREATE INDEX IF NOT EXISTS idx_chat_sdk_state_cache_expires
|
|
231
|
+
ON chat_sdk_state_cache(expires_at)
|
|
232
|
+
WHERE expires_at IS NOT NULL
|
|
233
|
+
`;
|
|
234
|
+
this.sql`
|
|
235
|
+
CREATE INDEX IF NOT EXISTS idx_chat_sdk_state_queue_thread
|
|
236
|
+
ON chat_sdk_state_queue(thread_id, id)
|
|
237
|
+
`;
|
|
238
|
+
this.sql`
|
|
239
|
+
CREATE INDEX IF NOT EXISTS idx_chat_sdk_state_queue_expires
|
|
240
|
+
ON chat_sdk_state_queue(expires_at)
|
|
241
|
+
`;
|
|
242
|
+
this.sql`
|
|
243
|
+
CREATE INDEX IF NOT EXISTS idx_chat_sdk_state_lists_key
|
|
244
|
+
ON chat_sdk_state_lists(key, id)
|
|
245
|
+
`;
|
|
246
|
+
this.sql`
|
|
247
|
+
CREATE INDEX IF NOT EXISTS idx_chat_sdk_state_lists_expires
|
|
248
|
+
ON chat_sdk_state_lists(expires_at)
|
|
249
|
+
WHERE expires_at IS NOT NULL
|
|
250
|
+
`;
|
|
251
|
+
}
|
|
252
|
+
readCacheValue(key, now) {
|
|
253
|
+
return this.sql`
|
|
254
|
+
SELECT value
|
|
255
|
+
FROM chat_sdk_state_cache
|
|
256
|
+
WHERE key = ${key}
|
|
257
|
+
AND (expires_at IS NULL OR expires_at > ${now})
|
|
258
|
+
`[0]?.value ?? null;
|
|
259
|
+
}
|
|
260
|
+
upsertCacheValue(key, value, expiresAt) {
|
|
261
|
+
this.sql`
|
|
262
|
+
INSERT OR REPLACE INTO chat_sdk_state_cache (key, value, expires_at)
|
|
263
|
+
VALUES (${key}, ${value}, ${expiresAt})
|
|
264
|
+
`;
|
|
265
|
+
}
|
|
266
|
+
async scheduleCleanupForExpiry(expiresAt) {
|
|
267
|
+
if (expiresAt === null) return;
|
|
268
|
+
await this.ensureCleanupScheduled(expiresAt);
|
|
269
|
+
}
|
|
270
|
+
async scheduleNextCleanup() {
|
|
271
|
+
const next = this.nextExpiry();
|
|
272
|
+
if (next === null) {
|
|
273
|
+
const current = this.readCleanupMetadata();
|
|
274
|
+
if (current.scheduleId) await this.cancelSchedule(current.scheduleId).catch(() => false);
|
|
275
|
+
this.clearCleanupMetadata();
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
await this.ensureCleanupScheduled(next);
|
|
279
|
+
}
|
|
280
|
+
async ensureCleanupScheduled(expiresAt) {
|
|
281
|
+
const current = this.readCleanupMetadata();
|
|
282
|
+
if (current.nextCleanupAt !== null && current.nextCleanupAt <= expiresAt) return;
|
|
283
|
+
if (current.scheduleId) await this.cancelSchedule(current.scheduleId).catch(() => false);
|
|
284
|
+
const delaySeconds = Math.max(0, Math.ceil((expiresAt - Date.now()) / 1e3));
|
|
285
|
+
const schedule = await this.schedule(delaySeconds, "cleanupExpired", { expiresAt });
|
|
286
|
+
this.writeCleanupMetadata(expiresAt, schedule.id);
|
|
287
|
+
}
|
|
288
|
+
nextExpiry() {
|
|
289
|
+
return this.sql`
|
|
290
|
+
SELECT MIN(expires_at) as expires_at
|
|
291
|
+
FROM (
|
|
292
|
+
SELECT expires_at FROM chat_sdk_state_locks
|
|
293
|
+
UNION ALL
|
|
294
|
+
SELECT expires_at FROM chat_sdk_state_queue
|
|
295
|
+
UNION ALL
|
|
296
|
+
SELECT expires_at FROM chat_sdk_state_cache WHERE expires_at IS NOT NULL
|
|
297
|
+
UNION ALL
|
|
298
|
+
SELECT expires_at FROM chat_sdk_state_lists WHERE expires_at IS NOT NULL
|
|
299
|
+
)
|
|
300
|
+
`[0]?.expires_at ?? null;
|
|
301
|
+
}
|
|
302
|
+
readCleanupMetadata() {
|
|
303
|
+
const rows = this.sql`
|
|
304
|
+
SELECT key, value
|
|
305
|
+
FROM chat_sdk_state_metadata
|
|
306
|
+
WHERE key IN (${NEXT_CLEANUP_AT_KEY}, ${CLEANUP_SCHEDULE_ID_KEY})
|
|
307
|
+
`;
|
|
308
|
+
const values = new Map(rows.map((row) => [row.key, row.value]));
|
|
309
|
+
const nextCleanupAt = Number(values.get(NEXT_CLEANUP_AT_KEY));
|
|
310
|
+
return {
|
|
311
|
+
nextCleanupAt: Number.isFinite(nextCleanupAt) ? nextCleanupAt : null,
|
|
312
|
+
scheduleId: values.get(CLEANUP_SCHEDULE_ID_KEY) ?? null
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
writeCleanupMetadata(expiresAt, scheduleId) {
|
|
316
|
+
this.sql`
|
|
317
|
+
INSERT OR REPLACE INTO chat_sdk_state_metadata (key, value)
|
|
318
|
+
VALUES (${NEXT_CLEANUP_AT_KEY}, ${String(expiresAt)})
|
|
319
|
+
`;
|
|
320
|
+
this.sql`
|
|
321
|
+
INSERT OR REPLACE INTO chat_sdk_state_metadata (key, value)
|
|
322
|
+
VALUES (${CLEANUP_SCHEDULE_ID_KEY}, ${scheduleId})
|
|
323
|
+
`;
|
|
324
|
+
}
|
|
325
|
+
clearCleanupMetadata() {
|
|
326
|
+
this.sql`
|
|
327
|
+
DELETE FROM chat_sdk_state_metadata
|
|
328
|
+
WHERE key IN (${NEXT_CLEANUP_AT_KEY}, ${CLEANUP_SCHEDULE_ID_KEY})
|
|
329
|
+
`;
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
function parseQueueEntry(value) {
|
|
333
|
+
const raw = JSON.parse(value);
|
|
334
|
+
if (typeof raw.enqueuedAt !== "number" || typeof raw.expiresAt !== "number") throw new Error("ChatSdkStateAgent expected QueueEntry JSON with numeric TTLs");
|
|
335
|
+
return {
|
|
336
|
+
enqueuedAt: raw.enqueuedAt,
|
|
337
|
+
expiresAt: raw.expiresAt
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
//#endregion
|
|
341
|
+
//#region src/chat-sdk/adapter.ts
|
|
342
|
+
const THREAD_STATE_PREFIX = "thread-state:";
|
|
343
|
+
const CHANNEL_STATE_PREFIX = "channel-state:";
|
|
344
|
+
const MESSAGE_HISTORY_PREFIX = "msg-history:";
|
|
345
|
+
const TRANSCRIPTS_USER_PREFIX = "transcripts:user:";
|
|
346
|
+
function parseStoredJson(raw, label) {
|
|
347
|
+
try {
|
|
348
|
+
return JSON.parse(raw);
|
|
349
|
+
} catch (error) {
|
|
350
|
+
throw new Error(`ChatSdkStateAdapter expected JSON-encoded ${label}`, { cause: error });
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
function defaultThreadShard(threadId) {
|
|
354
|
+
return threadId.split(":").slice(0, 2).join(":") || "default";
|
|
355
|
+
}
|
|
356
|
+
function defaultKeyShard(key, shardThread = defaultThreadShard) {
|
|
357
|
+
for (const prefix of [
|
|
358
|
+
THREAD_STATE_PREFIX,
|
|
359
|
+
CHANNEL_STATE_PREFIX,
|
|
360
|
+
MESSAGE_HISTORY_PREFIX,
|
|
361
|
+
TRANSCRIPTS_USER_PREFIX
|
|
362
|
+
]) if (key.startsWith(prefix)) return shardThread(key.slice(prefix.length));
|
|
363
|
+
}
|
|
364
|
+
var ChatSdkStateAdapter = class {
|
|
365
|
+
constructor(options = {}) {
|
|
366
|
+
this.connected = false;
|
|
367
|
+
const parent = options.parent ?? getCurrentAgent().agent;
|
|
368
|
+
if (!parent) throw new Error("ChatSdkStateAdapter requires a parent Agent. Pass `parent` or create it inside an Agent context.");
|
|
369
|
+
this.parent = parent;
|
|
370
|
+
this.agentClass = options.agent ?? ChatSdkStateAgent;
|
|
371
|
+
this.defaultName = options.name ?? "default";
|
|
372
|
+
this.keyShard = options.keyShard;
|
|
373
|
+
this.shardKey = options.shardKey ?? defaultThreadShard;
|
|
374
|
+
}
|
|
375
|
+
async connect() {
|
|
376
|
+
this.connected = true;
|
|
377
|
+
}
|
|
378
|
+
async disconnect() {
|
|
379
|
+
this.connected = false;
|
|
380
|
+
}
|
|
381
|
+
async subscribe(threadId) {
|
|
382
|
+
await (await this.stateAgent(threadId)).subscribe(threadId);
|
|
383
|
+
}
|
|
384
|
+
async unsubscribe(threadId) {
|
|
385
|
+
await (await this.stateAgent(threadId)).unsubscribe(threadId);
|
|
386
|
+
}
|
|
387
|
+
async isSubscribed(threadId) {
|
|
388
|
+
return (await this.stateAgent(threadId)).isSubscribed(threadId);
|
|
389
|
+
}
|
|
390
|
+
async acquireLock(threadId, ttlMs) {
|
|
391
|
+
return (await this.stateAgent(threadId)).acquireLock(threadId, ttlMs);
|
|
392
|
+
}
|
|
393
|
+
async releaseLock(lock) {
|
|
394
|
+
await (await this.stateAgent(lock.threadId)).releaseLock(lock.threadId, lock.token);
|
|
395
|
+
}
|
|
396
|
+
async extendLock(lock, ttlMs) {
|
|
397
|
+
return (await this.stateAgent(lock.threadId)).extendLock(lock.threadId, lock.token, ttlMs);
|
|
398
|
+
}
|
|
399
|
+
async forceReleaseLock(threadId) {
|
|
400
|
+
await (await this.stateAgent(threadId)).forceReleaseLock(threadId);
|
|
401
|
+
}
|
|
402
|
+
async enqueue(threadId, entry, maxSize) {
|
|
403
|
+
return (await this.stateAgent(threadId)).enqueue(threadId, JSON.stringify(entry), maxSize);
|
|
404
|
+
}
|
|
405
|
+
async dequeue(threadId) {
|
|
406
|
+
const raw = await (await this.stateAgent(threadId)).popQueue(threadId);
|
|
407
|
+
return raw === null ? null : parseStoredJson(raw, `queue entry for ${threadId}`);
|
|
408
|
+
}
|
|
409
|
+
async queueDepth(threadId) {
|
|
410
|
+
return (await this.stateAgent(threadId)).queueDepth(threadId);
|
|
411
|
+
}
|
|
412
|
+
async appendToList(key, value, options) {
|
|
413
|
+
await (await this.stateAgentForKey(key)).listAppend(key, JSON.stringify(value), options?.maxLength, options?.ttlMs);
|
|
414
|
+
}
|
|
415
|
+
async getList(key) {
|
|
416
|
+
return (await (await this.stateAgentForKey(key)).listGet(key)).map((value) => parseStoredJson(value, `list entry for ${key}`));
|
|
417
|
+
}
|
|
418
|
+
async get(key) {
|
|
419
|
+
const raw = await (await this.stateAgentForKey(key)).cacheGet(key);
|
|
420
|
+
return raw === null ? null : parseStoredJson(raw, `cache key ${key}`);
|
|
421
|
+
}
|
|
422
|
+
async set(key, value, ttlMs) {
|
|
423
|
+
await (await this.stateAgentForKey(key)).cacheSet(key, JSON.stringify(value), ttlMs);
|
|
424
|
+
}
|
|
425
|
+
async setIfNotExists(key, value, ttlMs) {
|
|
426
|
+
return (await this.stateAgentForKey(key)).cacheSetIfNotExists(key, JSON.stringify(value), ttlMs);
|
|
427
|
+
}
|
|
428
|
+
async delete(key) {
|
|
429
|
+
await (await this.stateAgentForKey(key)).cacheDelete(key);
|
|
430
|
+
}
|
|
431
|
+
async stateAgent(threadId) {
|
|
432
|
+
this.ensureConnected();
|
|
433
|
+
const name = threadId ? this.shardKey(threadId) : this.defaultName;
|
|
434
|
+
return this.parent.subAgent(this.agentClass, name);
|
|
435
|
+
}
|
|
436
|
+
async stateAgentForKey(key) {
|
|
437
|
+
this.ensureConnected();
|
|
438
|
+
const name = this.keyShard?.(key) ?? defaultKeyShard(key, this.shardKey) ?? this.defaultName;
|
|
439
|
+
return this.parent.subAgent(this.agentClass, name);
|
|
440
|
+
}
|
|
441
|
+
ensureConnected() {
|
|
442
|
+
if (!this.connected) throw new Error("ChatSdkStateAdapter is not connected");
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
//#endregion
|
|
446
|
+
//#region src/chat-sdk/index.ts
|
|
447
|
+
function createChatSdkState(options = {}) {
|
|
448
|
+
return new ChatSdkStateAdapter(options);
|
|
449
|
+
}
|
|
450
|
+
//#endregion
|
|
451
|
+
export { ChatSdkStateAdapter, ChatSdkStateAgent, createChatSdkState, defaultKeyShard, defaultThreadShard };
|
|
452
|
+
|
|
453
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/chat-sdk/agent.ts","../../src/chat-sdk/adapter.ts","../../src/chat-sdk/index.ts"],"sourcesContent":["import { Agent } from \"../index\";\n\ninterface StoredLock {\n threadId: string;\n token: string;\n expiresAt: number;\n}\n\ninterface StoredQueueEntry {\n enqueuedAt: number;\n expiresAt: number;\n}\n\nconst NEXT_CLEANUP_AT_KEY = \"next_cleanup_at\";\nconst CLEANUP_SCHEDULE_ID_KEY = \"cleanup_schedule_id\";\n\nexport class ChatSdkStateAgent extends Agent {\n onStart(): void {\n this.migrate();\n void this.scheduleNextCleanup();\n }\n\n subscribe(threadId: string): void {\n this.sql`\n INSERT OR IGNORE INTO chat_sdk_state_subscriptions (thread_id)\n VALUES (${threadId})\n `;\n }\n\n unsubscribe(threadId: string): void {\n this.sql`\n DELETE FROM chat_sdk_state_subscriptions\n WHERE thread_id = ${threadId}\n `;\n }\n\n isSubscribed(threadId: string): boolean {\n const rows = this.sql<{ found: number }>`\n SELECT 1 as found\n FROM chat_sdk_state_subscriptions\n WHERE thread_id = ${threadId}\n LIMIT 1\n `;\n return rows.length > 0;\n }\n\n async acquireLock(\n threadId: string,\n ttlMs: number\n ): Promise<StoredLock | null> {\n const result = this.ctx.storage.transactionSync(() => {\n const now = Date.now();\n\n this.ctx.storage.sql.exec(\n \"DELETE FROM chat_sdk_state_locks WHERE thread_id = ? AND expires_at <= ?\",\n threadId,\n now\n );\n\n const existing = this.ctx.storage.sql\n .exec(\n \"SELECT 1 FROM chat_sdk_state_locks WHERE thread_id = ? LIMIT 1\",\n threadId\n )\n .toArray();\n if (existing.length > 0) {\n return null;\n }\n\n const token = crypto.randomUUID();\n const expiresAt = now + ttlMs;\n\n this.ctx.storage.sql.exec(\n \"INSERT INTO chat_sdk_state_locks (thread_id, token, expires_at) VALUES (?, ?, ?)\",\n threadId,\n token,\n expiresAt\n );\n\n return { threadId, token, expiresAt };\n });\n\n await this.scheduleCleanupForExpiry(result?.expiresAt ?? null);\n return result;\n }\n\n releaseLock(threadId: string, token: string): void {\n this.sql`\n DELETE FROM chat_sdk_state_locks\n WHERE thread_id = ${threadId} AND token = ${token}\n `;\n }\n\n async extendLock(\n threadId: string,\n token: string,\n ttlMs: number\n ): Promise<boolean> {\n const result = this.ctx.storage.transactionSync(() => {\n const now = Date.now();\n const rows = this.ctx.storage.sql\n .exec<{ thread_id: string }>(\n `UPDATE chat_sdk_state_locks SET expires_at = ?\n WHERE thread_id = ? AND token = ? AND expires_at > ?\n RETURNING thread_id`,\n now + ttlMs,\n threadId,\n token,\n now\n )\n .toArray();\n return rows.length > 0;\n });\n if (result) {\n await this.scheduleCleanupForExpiry(Date.now() + ttlMs);\n }\n return result;\n }\n\n forceReleaseLock(threadId: string): void {\n this.sql`\n DELETE FROM chat_sdk_state_locks\n WHERE thread_id = ${threadId}\n `;\n }\n\n async enqueue(\n threadId: string,\n value: string,\n maxSize: number\n ): Promise<number> {\n const parsed = parseQueueEntry(value);\n\n const count = this.ctx.storage.transactionSync(() => {\n this.ctx.storage.sql.exec(\n \"INSERT INTO chat_sdk_state_queue (thread_id, value, enqueued_at, expires_at) VALUES (?, ?, ?, ?)\",\n threadId,\n value,\n parsed.enqueuedAt,\n parsed.expiresAt\n );\n\n this.ctx.storage.sql.exec(\n `DELETE FROM chat_sdk_state_queue WHERE thread_id = ? AND id NOT IN (\n SELECT id FROM chat_sdk_state_queue\n WHERE thread_id = ?\n ORDER BY id DESC\n LIMIT ?\n )`,\n threadId,\n threadId,\n maxSize\n );\n\n const row = this.ctx.storage.sql\n .exec<{ count: number }>(\n \"SELECT COUNT(*) as count FROM chat_sdk_state_queue WHERE thread_id = ?\",\n threadId\n )\n .one();\n return row.count;\n });\n await this.scheduleCleanupForExpiry(parsed.expiresAt);\n return count;\n }\n\n popQueue(threadId: string): string | null {\n return this.ctx.storage.transactionSync(() => {\n const now = Date.now();\n\n this.ctx.storage.sql.exec(\n \"DELETE FROM chat_sdk_state_queue WHERE thread_id = ? AND expires_at <= ?\",\n threadId,\n now\n );\n\n const rows = this.ctx.storage.sql\n .exec<{ id: number; value: string }>(\n \"SELECT id, value FROM chat_sdk_state_queue WHERE thread_id = ? ORDER BY id ASC LIMIT 1\",\n threadId\n )\n .toArray();\n const row = rows[0];\n if (!row) {\n return null;\n }\n\n this.ctx.storage.sql.exec(\n \"DELETE FROM chat_sdk_state_queue WHERE id = ?\",\n row.id\n );\n return row.value;\n });\n }\n\n queueDepth(threadId: string): number {\n const rows = this.sql<{ count: number }>`\n SELECT COUNT(*) as count\n FROM chat_sdk_state_queue\n WHERE thread_id = ${threadId} AND expires_at > ${Date.now()}\n `;\n return rows[0]?.count ?? 0;\n }\n\n async listAppend(\n key: string,\n value: string,\n maxLength?: number,\n ttlMs?: number\n ): Promise<void> {\n const expiresAt = ttlMs && ttlMs > 0 ? Date.now() + ttlMs : null;\n\n this.ctx.storage.transactionSync(() => {\n this.ctx.storage.sql.exec(\n \"INSERT INTO chat_sdk_state_lists (key, value, expires_at) VALUES (?, ?, ?)\",\n key,\n value,\n expiresAt\n );\n\n if (expiresAt !== null) {\n // Chat SDK history lists use a list-level TTL: any append refreshes the\n // expiry for the whole logical list, not only the new row.\n this.ctx.storage.sql.exec(\n \"UPDATE chat_sdk_state_lists SET expires_at = ? WHERE key = ?\",\n expiresAt,\n key\n );\n }\n\n if (maxLength != null && maxLength > 0) {\n this.ctx.storage.sql.exec(\n `DELETE FROM chat_sdk_state_lists WHERE key = ? AND id NOT IN (\n SELECT id FROM chat_sdk_state_lists\n WHERE key = ?\n ORDER BY id DESC\n LIMIT ?\n )`,\n key,\n key,\n maxLength\n );\n }\n });\n await this.scheduleCleanupForExpiry(expiresAt);\n }\n\n listGet(key: string): string[] {\n const now = Date.now();\n\n this.sql`\n DELETE FROM chat_sdk_state_lists\n WHERE key = ${key}\n AND expires_at IS NOT NULL\n AND expires_at <= ${now}\n `;\n\n return this.sql<{ value: string }>`\n SELECT value\n FROM chat_sdk_state_lists\n WHERE key = ${key}\n ORDER BY id ASC\n `.map((row) => row.value);\n }\n\n cacheGet(key: string): string | null {\n return this.readCacheValue(key, Date.now());\n }\n\n async cacheSet(key: string, value: string, ttlMs?: number): Promise<void> {\n const expiresAt = ttlMs && ttlMs > 0 ? Date.now() + ttlMs : null;\n this.upsertCacheValue(key, value, expiresAt);\n await this.scheduleCleanupForExpiry(expiresAt);\n }\n\n async cacheSetIfNotExists(\n key: string,\n value: string,\n ttlMs?: number\n ): Promise<boolean> {\n const now = Date.now();\n\n const inserted = this.ctx.storage.transactionSync(() => {\n this.ctx.storage.sql.exec(\n \"DELETE FROM chat_sdk_state_cache WHERE key = ? AND expires_at IS NOT NULL AND expires_at <= ?\",\n key,\n now\n );\n\n if (this.readCacheValue(key, now) !== null) {\n return false;\n }\n\n const expiresAt = ttlMs && ttlMs > 0 ? now + ttlMs : null;\n this.upsertCacheValue(key, value, expiresAt);\n return true;\n });\n if (inserted) {\n const expiresAt = ttlMs && ttlMs > 0 ? Date.now() + ttlMs : null;\n await this.scheduleCleanupForExpiry(expiresAt);\n }\n return inserted;\n }\n\n cacheDelete(key: string): void {\n this.sql`\n DELETE FROM chat_sdk_state_cache\n WHERE key = ${key}\n `;\n }\n\n async cleanupExpired(payload?: { expiresAt?: number }): Promise<void> {\n const current = this.readCleanupMetadata();\n if (\n payload?.expiresAt !== undefined &&\n current.nextCleanupAt !== null &&\n payload.expiresAt !== current.nextCleanupAt\n ) {\n return;\n }\n\n const now = Date.now();\n this.clearCleanupMetadata();\n\n this.sql`\n DELETE FROM chat_sdk_state_locks\n WHERE expires_at <= ${now}\n `;\n this.sql`\n DELETE FROM chat_sdk_state_cache\n WHERE expires_at IS NOT NULL AND expires_at <= ${now}\n `;\n this.sql`\n DELETE FROM chat_sdk_state_queue\n WHERE expires_at <= ${now}\n `;\n this.sql`\n DELETE FROM chat_sdk_state_lists\n WHERE expires_at IS NOT NULL AND expires_at <= ${now}\n `;\n await this.scheduleNextCleanup();\n }\n\n private migrate(): void {\n this.sql`\n CREATE TABLE IF NOT EXISTS chat_sdk_state_subscriptions (\n thread_id TEXT PRIMARY KEY\n )\n `;\n\n this.sql`\n CREATE TABLE IF NOT EXISTS chat_sdk_state_locks (\n thread_id TEXT PRIMARY KEY,\n token TEXT NOT NULL,\n expires_at INTEGER NOT NULL\n )\n `;\n\n this.sql`\n CREATE TABLE IF NOT EXISTS chat_sdk_state_cache (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL,\n expires_at INTEGER\n )\n `;\n\n this.sql`\n CREATE TABLE IF NOT EXISTS chat_sdk_state_queue (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n thread_id TEXT NOT NULL,\n value TEXT NOT NULL,\n enqueued_at INTEGER NOT NULL,\n expires_at INTEGER NOT NULL\n )\n `;\n\n this.sql`\n CREATE TABLE IF NOT EXISTS chat_sdk_state_lists (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n key TEXT NOT NULL,\n value TEXT NOT NULL,\n expires_at INTEGER\n )\n `;\n\n this.sql`\n CREATE TABLE IF NOT EXISTS chat_sdk_state_metadata (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n )\n `;\n\n this.sql`\n CREATE INDEX IF NOT EXISTS idx_chat_sdk_state_locks_expires\n ON chat_sdk_state_locks(expires_at)\n `;\n this.sql`\n CREATE INDEX IF NOT EXISTS idx_chat_sdk_state_cache_expires\n ON chat_sdk_state_cache(expires_at)\n WHERE expires_at IS NOT NULL\n `;\n this.sql`\n CREATE INDEX IF NOT EXISTS idx_chat_sdk_state_queue_thread\n ON chat_sdk_state_queue(thread_id, id)\n `;\n this.sql`\n CREATE INDEX IF NOT EXISTS idx_chat_sdk_state_queue_expires\n ON chat_sdk_state_queue(expires_at)\n `;\n this.sql`\n CREATE INDEX IF NOT EXISTS idx_chat_sdk_state_lists_key\n ON chat_sdk_state_lists(key, id)\n `;\n this.sql`\n CREATE INDEX IF NOT EXISTS idx_chat_sdk_state_lists_expires\n ON chat_sdk_state_lists(expires_at)\n WHERE expires_at IS NOT NULL\n `;\n }\n\n private readCacheValue(key: string, now: number): string | null {\n const rows = this.sql<{ value: string }>`\n SELECT value\n FROM chat_sdk_state_cache\n WHERE key = ${key}\n AND (expires_at IS NULL OR expires_at > ${now})\n `;\n return rows[0]?.value ?? null;\n }\n\n private upsertCacheValue(\n key: string,\n value: string,\n expiresAt: number | null\n ): void {\n this.sql`\n INSERT OR REPLACE INTO chat_sdk_state_cache (key, value, expires_at)\n VALUES (${key}, ${value}, ${expiresAt})\n `;\n }\n\n private async scheduleCleanupForExpiry(\n expiresAt: number | null\n ): Promise<void> {\n if (expiresAt === null) {\n return;\n }\n\n await this.ensureCleanupScheduled(expiresAt);\n }\n\n private async scheduleNextCleanup(): Promise<void> {\n const next = this.nextExpiry();\n if (next === null) {\n const current = this.readCleanupMetadata();\n if (current.scheduleId) {\n await this.cancelSchedule(current.scheduleId).catch(() => false);\n }\n this.clearCleanupMetadata();\n return;\n }\n\n await this.ensureCleanupScheduled(next);\n }\n\n private async ensureCleanupScheduled(expiresAt: number): Promise<void> {\n const current = this.readCleanupMetadata();\n if (current.nextCleanupAt !== null && current.nextCleanupAt <= expiresAt) {\n return;\n }\n\n if (current.scheduleId) {\n await this.cancelSchedule(current.scheduleId).catch(() => false);\n }\n\n const delaySeconds = Math.max(\n 0,\n Math.ceil((expiresAt - Date.now()) / 1000)\n );\n const schedule = await this.schedule(delaySeconds, \"cleanupExpired\", {\n expiresAt\n });\n this.writeCleanupMetadata(expiresAt, schedule.id);\n }\n\n private nextExpiry(): number | null {\n const rows = this.sql<{ expires_at: number | null }>`\n SELECT MIN(expires_at) as expires_at\n FROM (\n SELECT expires_at FROM chat_sdk_state_locks\n UNION ALL\n SELECT expires_at FROM chat_sdk_state_queue\n UNION ALL\n SELECT expires_at FROM chat_sdk_state_cache WHERE expires_at IS NOT NULL\n UNION ALL\n SELECT expires_at FROM chat_sdk_state_lists WHERE expires_at IS NOT NULL\n )\n `;\n return rows[0]?.expires_at ?? null;\n }\n\n private readCleanupMetadata(): {\n nextCleanupAt: number | null;\n scheduleId: string | null;\n } {\n const rows = this.sql<{ key: string; value: string }>`\n SELECT key, value\n FROM chat_sdk_state_metadata\n WHERE key IN (${NEXT_CLEANUP_AT_KEY}, ${CLEANUP_SCHEDULE_ID_KEY})\n `;\n const values = new Map(rows.map((row) => [row.key, row.value]));\n const nextCleanupAt = Number(values.get(NEXT_CLEANUP_AT_KEY));\n return {\n nextCleanupAt: Number.isFinite(nextCleanupAt) ? nextCleanupAt : null,\n scheduleId: values.get(CLEANUP_SCHEDULE_ID_KEY) ?? null\n };\n }\n\n private writeCleanupMetadata(expiresAt: number, scheduleId: string): void {\n this.sql`\n INSERT OR REPLACE INTO chat_sdk_state_metadata (key, value)\n VALUES (${NEXT_CLEANUP_AT_KEY}, ${String(expiresAt)})\n `;\n this.sql`\n INSERT OR REPLACE INTO chat_sdk_state_metadata (key, value)\n VALUES (${CLEANUP_SCHEDULE_ID_KEY}, ${scheduleId})\n `;\n }\n\n private clearCleanupMetadata(): void {\n this.sql`\n DELETE FROM chat_sdk_state_metadata\n WHERE key IN (${NEXT_CLEANUP_AT_KEY}, ${CLEANUP_SCHEDULE_ID_KEY})\n `;\n }\n}\n\nfunction parseQueueEntry(value: string): StoredQueueEntry {\n const raw = JSON.parse(value) as Record<string, unknown>;\n if (typeof raw.enqueuedAt !== \"number\" || typeof raw.expiresAt !== \"number\") {\n throw new Error(\n \"ChatSdkStateAgent expected QueueEntry JSON with numeric TTLs\"\n );\n }\n\n return {\n enqueuedAt: raw.enqueuedAt,\n expiresAt: raw.expiresAt\n };\n}\n","import type {\n Lock as ChatSdkLock,\n QueueEntry as ChatSdkQueueEntry,\n StateAdapter as ChatSdkStateAdapterInterface\n} from \"chat\";\nimport {\n getCurrentAgent,\n type SubAgentClass,\n type SubAgentStub\n} from \"../index\";\nimport { ChatSdkStateAgent } from \"./agent\";\nimport type { ChatSdkStateAdapterOptions } from \"./types\";\n\nconst THREAD_STATE_PREFIX = \"thread-state:\";\nconst CHANNEL_STATE_PREFIX = \"channel-state:\";\nconst MESSAGE_HISTORY_PREFIX = \"msg-history:\";\nconst TRANSCRIPTS_USER_PREFIX = \"transcripts:user:\";\n\nfunction parseStoredJson<T>(raw: string, label: string): T {\n try {\n return JSON.parse(raw) as T;\n } catch (error) {\n throw new Error(`ChatSdkStateAdapter expected JSON-encoded ${label}`, {\n cause: error\n });\n }\n}\n\nexport function defaultThreadShard(threadId: string): string {\n return threadId.split(\":\").slice(0, 2).join(\":\") || \"default\";\n}\n\nexport function defaultKeyShard(\n key: string,\n shardThread: (threadId: string) => string = defaultThreadShard\n): string | undefined {\n for (const prefix of [\n THREAD_STATE_PREFIX,\n CHANNEL_STATE_PREFIX,\n MESSAGE_HISTORY_PREFIX,\n TRANSCRIPTS_USER_PREFIX\n ]) {\n if (key.startsWith(prefix)) {\n return shardThread(key.slice(prefix.length));\n }\n }\n\n return undefined;\n}\n\nexport class ChatSdkStateAdapter implements ChatSdkStateAdapterInterface {\n private readonly parent: NonNullable<ChatSdkStateAdapterOptions[\"parent\"]>;\n private readonly agentClass: SubAgentClass<ChatSdkStateAgent>;\n private readonly defaultName: string;\n private readonly keyShard?: (key: string) => string | undefined;\n private readonly shardKey: (threadId: string) => string;\n private connected = false;\n\n constructor(options: ChatSdkStateAdapterOptions = {}) {\n const parent = options.parent ?? getCurrentAgent().agent;\n if (!parent) {\n throw new Error(\n \"ChatSdkStateAdapter requires a parent Agent. Pass `parent` or create it inside an Agent context.\"\n );\n }\n\n this.parent = parent;\n this.agentClass = options.agent ?? ChatSdkStateAgent;\n this.defaultName = options.name ?? \"default\";\n this.keyShard = options.keyShard;\n this.shardKey = options.shardKey ?? defaultThreadShard;\n }\n\n async connect(): Promise<void> {\n this.connected = true;\n }\n\n async disconnect(): Promise<void> {\n this.connected = false;\n }\n\n async subscribe(threadId: string): Promise<void> {\n await (await this.stateAgent(threadId)).subscribe(threadId);\n }\n\n async unsubscribe(threadId: string): Promise<void> {\n await (await this.stateAgent(threadId)).unsubscribe(threadId);\n }\n\n async isSubscribed(threadId: string): Promise<boolean> {\n return (await this.stateAgent(threadId)).isSubscribed(threadId);\n }\n\n async acquireLock(\n threadId: string,\n ttlMs: number\n ): Promise<ChatSdkLock | null> {\n return (await this.stateAgent(threadId)).acquireLock(threadId, ttlMs);\n }\n\n async releaseLock(lock: ChatSdkLock): Promise<void> {\n await (\n await this.stateAgent(lock.threadId)\n ).releaseLock(lock.threadId, lock.token);\n }\n\n async extendLock(lock: ChatSdkLock, ttlMs: number): Promise<boolean> {\n return (await this.stateAgent(lock.threadId)).extendLock(\n lock.threadId,\n lock.token,\n ttlMs\n );\n }\n\n async forceReleaseLock(threadId: string): Promise<void> {\n await (await this.stateAgent(threadId)).forceReleaseLock(threadId);\n }\n\n async enqueue(\n threadId: string,\n entry: ChatSdkQueueEntry,\n maxSize: number\n ): Promise<number> {\n return (await this.stateAgent(threadId)).enqueue(\n threadId,\n JSON.stringify(entry),\n maxSize\n );\n }\n\n async dequeue(threadId: string): Promise<ChatSdkQueueEntry | null> {\n const raw = await (await this.stateAgent(threadId)).popQueue(threadId);\n return raw === null\n ? null\n : parseStoredJson<ChatSdkQueueEntry>(raw, `queue entry for ${threadId}`);\n }\n\n async queueDepth(threadId: string): Promise<number> {\n return (await this.stateAgent(threadId)).queueDepth(threadId);\n }\n\n async appendToList(\n key: string,\n value: unknown,\n options?: { maxLength?: number; ttlMs?: number }\n ): Promise<void> {\n await (\n await this.stateAgentForKey(key)\n ).listAppend(\n key,\n JSON.stringify(value),\n options?.maxLength,\n options?.ttlMs\n );\n }\n\n async getList<T = unknown>(key: string): Promise<T[]> {\n const raw = await (await this.stateAgentForKey(key)).listGet(key);\n return raw.map((value) =>\n parseStoredJson<T>(value, `list entry for ${key}`)\n );\n }\n\n async get<T = unknown>(key: string): Promise<T | null> {\n const raw = await (await this.stateAgentForKey(key)).cacheGet(key);\n return raw === null ? null : parseStoredJson<T>(raw, `cache key ${key}`);\n }\n\n async set<T = unknown>(key: string, value: T, ttlMs?: number): Promise<void> {\n await (\n await this.stateAgentForKey(key)\n ).cacheSet(key, JSON.stringify(value), ttlMs);\n }\n\n async setIfNotExists<T = unknown>(\n key: string,\n value: T,\n ttlMs?: number\n ): Promise<boolean> {\n return (await this.stateAgentForKey(key)).cacheSetIfNotExists(\n key,\n JSON.stringify(value),\n ttlMs\n );\n }\n\n async delete(key: string): Promise<void> {\n await (await this.stateAgentForKey(key)).cacheDelete(key);\n }\n\n private async stateAgent(\n threadId?: string\n ): Promise<SubAgentStub<ChatSdkStateAgent>> {\n this.ensureConnected();\n const name = threadId ? this.shardKey(threadId) : this.defaultName;\n return this.parent.subAgent(this.agentClass, name);\n }\n\n private async stateAgentForKey(\n key: string\n ): Promise<SubAgentStub<ChatSdkStateAgent>> {\n this.ensureConnected();\n const name =\n this.keyShard?.(key) ??\n defaultKeyShard(key, this.shardKey) ??\n this.defaultName;\n return this.parent.subAgent(this.agentClass, name);\n }\n\n private ensureConnected(): void {\n if (!this.connected) {\n throw new Error(\"ChatSdkStateAdapter is not connected\");\n }\n }\n}\n","export {\n ChatSdkStateAdapter,\n defaultKeyShard,\n defaultThreadShard\n} from \"./adapter\";\nexport { ChatSdkStateAgent } from \"./agent\";\nexport type { ChatSdkStateParent, ChatSdkStateAdapterOptions } from \"./types\";\n\nimport { ChatSdkStateAdapter } from \"./adapter\";\nimport type { ChatSdkStateAdapterOptions } from \"./types\";\n\nexport function createChatSdkState(\n options: ChatSdkStateAdapterOptions = {}\n): ChatSdkStateAdapter {\n return new ChatSdkStateAdapter(options);\n}\n"],"mappings":"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"}
|
package/dist/client.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { ToolSet } from "ai";
|
|
|
8
8
|
interface SessionMessagePart {
|
|
9
9
|
type: string;
|
|
10
10
|
text?: string;
|
|
11
|
+
reasoning?: string;
|
|
11
12
|
toolCallId?: string;
|
|
12
13
|
toolName?: string;
|
|
13
14
|
input?: unknown;
|
|
@@ -15,6 +16,28 @@ interface SessionMessagePart {
|
|
|
15
16
|
state?: string;
|
|
16
17
|
result?: unknown;
|
|
17
18
|
}
|
|
19
|
+
interface SessionTokenCounterInput {
|
|
20
|
+
/** Messages returned by `session.getHistory()` for the active branch. */
|
|
21
|
+
messages: SessionMessage[];
|
|
22
|
+
/** Frozen system prompt managed by the Session context system. */
|
|
23
|
+
systemPrompt: string;
|
|
24
|
+
/** Loaded context blocks that were used to build `systemPrompt`. */
|
|
25
|
+
contextBlocks: ContextBlock[];
|
|
26
|
+
}
|
|
27
|
+
type SessionTokenCounter = (
|
|
28
|
+
input: SessionTokenCounterInput
|
|
29
|
+
) => number | Promise<number>;
|
|
30
|
+
interface CompactAfterOptions {
|
|
31
|
+
/**
|
|
32
|
+
* Override the token estimate used by auto-compaction and status broadcasts.
|
|
33
|
+
*
|
|
34
|
+
* The default is a Workers-safe heuristic over message parts plus the
|
|
35
|
+
* Session-managed frozen system prompt. Callers that have model-reported
|
|
36
|
+
* usage or a tokenizer can provide a more precise counter here.
|
|
37
|
+
*/
|
|
38
|
+
tokenCounter?: SessionTokenCounter;
|
|
39
|
+
}
|
|
40
|
+
type CompactionErrorHandler = (error: unknown) => void | Promise<void>;
|
|
18
41
|
/**
|
|
19
42
|
* Minimal message shape used by Session internals.
|
|
20
43
|
* Vercel AI SDK's `UIMessage` is structurally compatible — you can pass
|
|
@@ -34,6 +57,10 @@ interface SessionOptions {
|
|
|
34
57
|
context?: ContextConfig[];
|
|
35
58
|
/** Provider for persisting the frozen system prompt. */
|
|
36
59
|
promptStore?: WritableContextProvider;
|
|
60
|
+
/** Custom token counter for auto-compaction/status estimates. */
|
|
61
|
+
tokenCounter?: SessionTokenCounter;
|
|
62
|
+
/** Called when automatic compaction fails after a threshold trigger. */
|
|
63
|
+
onCompactionError?: CompactionErrorHandler;
|
|
37
64
|
}
|
|
38
65
|
//#endregion
|
|
39
66
|
//#region src/experimental/memory/session/provider.d.ts
|
|
@@ -432,11 +459,14 @@ declare function createCompactFunction(
|
|
|
432
459
|
): (messages: SessionMessage[]) => Promise<CompactResult | null>;
|
|
433
460
|
//#endregion
|
|
434
461
|
export {
|
|
435
|
-
|
|
462
|
+
SessionMessage as A,
|
|
436
463
|
AgentSessionProvider as C,
|
|
437
464
|
StoredCompaction as D,
|
|
438
465
|
SessionProvider as E,
|
|
439
|
-
|
|
466
|
+
SessionOptions as M,
|
|
467
|
+
SessionTokenCounter as N,
|
|
468
|
+
CompactAfterOptions as O,
|
|
469
|
+
SessionTokenCounterInput as P,
|
|
440
470
|
isSearchProvider as S,
|
|
441
471
|
SearchResult as T,
|
|
442
472
|
R2SkillProvider as _,
|
|
@@ -448,7 +478,8 @@ export {
|
|
|
448
478
|
isWritableProvider as g,
|
|
449
479
|
WritableContextProvider as h,
|
|
450
480
|
alignBoundaryBackward as i,
|
|
451
|
-
SessionMessagePart as
|
|
481
|
+
SessionMessagePart as j,
|
|
482
|
+
CompactionErrorHandler as k,
|
|
452
483
|
findTailCutByTokens as l,
|
|
453
484
|
ContextProvider as m,
|
|
454
485
|
CompactOptions as n,
|
|
@@ -463,4 +494,4 @@ export {
|
|
|
463
494
|
SearchProvider as x,
|
|
464
495
|
isSkillProvider as y
|
|
465
496
|
};
|
|
466
|
-
//# sourceMappingURL=compaction-helpers-
|
|
497
|
+
//# sourceMappingURL=compaction-helpers-B-pG5J22.d.ts.map
|
|
@@ -20,10 +20,19 @@ function estimateStringTokens(text) {
|
|
|
20
20
|
const wordEstimate = text.split(/\s+/).filter(Boolean).length * WORDS_TOKEN_MULTIPLIER;
|
|
21
21
|
return Math.ceil(Math.max(charEstimate, wordEstimate));
|
|
22
22
|
}
|
|
23
|
+
function estimateUnknownTokens(value) {
|
|
24
|
+
if (value === null || value === void 0) return 0;
|
|
25
|
+
if (typeof value === "string") return estimateStringTokens(value);
|
|
26
|
+
try {
|
|
27
|
+
return estimateStringTokens(JSON.stringify(value));
|
|
28
|
+
} catch {
|
|
29
|
+
return estimateStringTokens(String(value));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
23
32
|
/**
|
|
24
33
|
* Estimate total token count for an array of UIMessages.
|
|
25
34
|
*
|
|
26
|
-
* Walks each message's parts (text, tool invocations, tool results)
|
|
35
|
+
* Walks each message's parts (text, reasoning, tool invocations, tool results)
|
|
27
36
|
* and applies per-message overhead.
|
|
28
37
|
*
|
|
29
38
|
* This is a heuristic. Do not use where exact counts are required.
|
|
@@ -32,12 +41,12 @@ function estimateMessageTokens(messages) {
|
|
|
32
41
|
let tokens = 0;
|
|
33
42
|
for (const msg of messages) {
|
|
34
43
|
tokens += 4;
|
|
35
|
-
for (const part of msg.parts) if (part.type === "text") tokens +=
|
|
44
|
+
for (const part of msg.parts) if (part.type === "text" || part.type === "reasoning") tokens += estimateUnknownTokens(part.text ?? part.reasoning);
|
|
36
45
|
else if (part.type.startsWith("tool-") || part.type === "dynamic-tool") {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
tokens += estimateUnknownTokens(part.input);
|
|
47
|
+
tokens += estimateUnknownTokens(part.output ?? part.result);
|
|
48
|
+
} else if (part.text !== void 0) tokens += estimateUnknownTokens(part.text);
|
|
49
|
+
else if (part.result !== void 0) tokens += estimateUnknownTokens(part.result);
|
|
41
50
|
}
|
|
42
51
|
return tokens;
|
|
43
52
|
}
|
|
@@ -309,4 +318,4 @@ function createCompactFunction(opts) {
|
|
|
309
318
|
//#endregion
|
|
310
319
|
export { computeSummaryBudget as a, isCompactionMessage as c, TOKENS_PER_MESSAGE as d, WORDS_TOKEN_MULTIPLIER as f, buildSummaryPrompt as i, sanitizeToolPairs as l, estimateStringTokens as m, alignBoundaryBackward as n, createCompactFunction as o, estimateMessageTokens as p, alignBoundaryForward as r, findTailCutByTokens as s, COMPACTION_PREFIX as t, CHARS_PER_TOKEN as u };
|
|
311
320
|
|
|
312
|
-
//# sourceMappingURL=compaction-helpers-
|
|
321
|
+
//# sourceMappingURL=compaction-helpers-fJyf8j4m.js.map
|