agents 0.13.1 → 0.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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/package.json +11 -1
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import {
|
|
2
|
+
$ as SubAgentStub,
|
|
3
|
+
Q as SubAgentClass,
|
|
4
|
+
v as Agent
|
|
5
|
+
} from "../agent-tool-types-Dn9n-3SI.js";
|
|
6
|
+
import { Lock, QueueEntry, StateAdapter } from "chat";
|
|
7
|
+
|
|
8
|
+
//#region src/chat-sdk/agent.d.ts
|
|
9
|
+
interface StoredLock {
|
|
10
|
+
threadId: string;
|
|
11
|
+
token: string;
|
|
12
|
+
expiresAt: number;
|
|
13
|
+
}
|
|
14
|
+
declare class ChatSdkStateAgent extends Agent {
|
|
15
|
+
onStart(): void;
|
|
16
|
+
subscribe(threadId: string): void;
|
|
17
|
+
unsubscribe(threadId: string): void;
|
|
18
|
+
isSubscribed(threadId: string): boolean;
|
|
19
|
+
acquireLock(threadId: string, ttlMs: number): Promise<StoredLock | null>;
|
|
20
|
+
releaseLock(threadId: string, token: string): void;
|
|
21
|
+
extendLock(threadId: string, token: string, ttlMs: number): Promise<boolean>;
|
|
22
|
+
forceReleaseLock(threadId: string): void;
|
|
23
|
+
enqueue(threadId: string, value: string, maxSize: number): Promise<number>;
|
|
24
|
+
popQueue(threadId: string): string | null;
|
|
25
|
+
queueDepth(threadId: string): number;
|
|
26
|
+
listAppend(
|
|
27
|
+
key: string,
|
|
28
|
+
value: string,
|
|
29
|
+
maxLength?: number,
|
|
30
|
+
ttlMs?: number
|
|
31
|
+
): Promise<void>;
|
|
32
|
+
listGet(key: string): string[];
|
|
33
|
+
cacheGet(key: string): string | null;
|
|
34
|
+
cacheSet(key: string, value: string, ttlMs?: number): Promise<void>;
|
|
35
|
+
cacheSetIfNotExists(
|
|
36
|
+
key: string,
|
|
37
|
+
value: string,
|
|
38
|
+
ttlMs?: number
|
|
39
|
+
): Promise<boolean>;
|
|
40
|
+
cacheDelete(key: string): void;
|
|
41
|
+
cleanupExpired(payload?: { expiresAt?: number }): Promise<void>;
|
|
42
|
+
private migrate;
|
|
43
|
+
private readCacheValue;
|
|
44
|
+
private upsertCacheValue;
|
|
45
|
+
private scheduleCleanupForExpiry;
|
|
46
|
+
private scheduleNextCleanup;
|
|
47
|
+
private ensureCleanupScheduled;
|
|
48
|
+
private nextExpiry;
|
|
49
|
+
private readCleanupMetadata;
|
|
50
|
+
private writeCleanupMetadata;
|
|
51
|
+
private clearCleanupMetadata;
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/chat-sdk/types.d.ts
|
|
55
|
+
interface ChatSdkStateParent {
|
|
56
|
+
subAgent<T extends ChatSdkStateAgent>(
|
|
57
|
+
agentClass: SubAgentClass<T>,
|
|
58
|
+
name: string
|
|
59
|
+
): Promise<SubAgentStub<T>>;
|
|
60
|
+
}
|
|
61
|
+
interface ChatSdkStateAdapterOptions {
|
|
62
|
+
agent?: SubAgentClass<ChatSdkStateAgent>;
|
|
63
|
+
parent?: ChatSdkStateParent;
|
|
64
|
+
name?: string;
|
|
65
|
+
keyShard?: (key: string) => string | undefined;
|
|
66
|
+
shardKey?: (threadId: string) => string;
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/chat-sdk/adapter.d.ts
|
|
70
|
+
declare function defaultThreadShard(threadId: string): string;
|
|
71
|
+
declare function defaultKeyShard(
|
|
72
|
+
key: string,
|
|
73
|
+
shardThread?: (threadId: string) => string
|
|
74
|
+
): string | undefined;
|
|
75
|
+
declare class ChatSdkStateAdapter implements StateAdapter {
|
|
76
|
+
private readonly parent;
|
|
77
|
+
private readonly agentClass;
|
|
78
|
+
private readonly defaultName;
|
|
79
|
+
private readonly keyShard?;
|
|
80
|
+
private readonly shardKey;
|
|
81
|
+
private connected;
|
|
82
|
+
constructor(options?: ChatSdkStateAdapterOptions);
|
|
83
|
+
connect(): Promise<void>;
|
|
84
|
+
disconnect(): Promise<void>;
|
|
85
|
+
subscribe(threadId: string): Promise<void>;
|
|
86
|
+
unsubscribe(threadId: string): Promise<void>;
|
|
87
|
+
isSubscribed(threadId: string): Promise<boolean>;
|
|
88
|
+
acquireLock(threadId: string, ttlMs: number): Promise<Lock | null>;
|
|
89
|
+
releaseLock(lock: Lock): Promise<void>;
|
|
90
|
+
extendLock(lock: Lock, ttlMs: number): Promise<boolean>;
|
|
91
|
+
forceReleaseLock(threadId: string): Promise<void>;
|
|
92
|
+
enqueue(
|
|
93
|
+
threadId: string,
|
|
94
|
+
entry: QueueEntry,
|
|
95
|
+
maxSize: number
|
|
96
|
+
): Promise<number>;
|
|
97
|
+
dequeue(threadId: string): Promise<QueueEntry | null>;
|
|
98
|
+
queueDepth(threadId: string): Promise<number>;
|
|
99
|
+
appendToList(
|
|
100
|
+
key: string,
|
|
101
|
+
value: unknown,
|
|
102
|
+
options?: {
|
|
103
|
+
maxLength?: number;
|
|
104
|
+
ttlMs?: number;
|
|
105
|
+
}
|
|
106
|
+
): Promise<void>;
|
|
107
|
+
getList<T = unknown>(key: string): Promise<T[]>;
|
|
108
|
+
get<T = unknown>(key: string): Promise<T | null>;
|
|
109
|
+
set<T = unknown>(key: string, value: T, ttlMs?: number): Promise<void>;
|
|
110
|
+
setIfNotExists<T = unknown>(
|
|
111
|
+
key: string,
|
|
112
|
+
value: T,
|
|
113
|
+
ttlMs?: number
|
|
114
|
+
): Promise<boolean>;
|
|
115
|
+
delete(key: string): Promise<void>;
|
|
116
|
+
private stateAgent;
|
|
117
|
+
private stateAgentForKey;
|
|
118
|
+
private ensureConnected;
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/chat-sdk/index.d.ts
|
|
122
|
+
declare function createChatSdkState(
|
|
123
|
+
options?: ChatSdkStateAdapterOptions
|
|
124
|
+
): ChatSdkStateAdapter;
|
|
125
|
+
//#endregion
|
|
126
|
+
export {
|
|
127
|
+
ChatSdkStateAdapter,
|
|
128
|
+
type ChatSdkStateAdapterOptions,
|
|
129
|
+
ChatSdkStateAgent,
|
|
130
|
+
type ChatSdkStateParent,
|
|
131
|
+
createChatSdkState,
|
|
132
|
+
defaultKeyShard,
|
|
133
|
+
defaultThreadShard
|
|
134
|
+
};
|
|
135
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -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/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"durable objects"
|
|
10
10
|
],
|
|
11
11
|
"type": "module",
|
|
12
|
-
"version": "0.13.
|
|
12
|
+
"version": "0.13.2",
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"repository": {
|
|
15
15
|
"directory": "packages/agents",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"@x402/core": "^2.12.0",
|
|
45
45
|
"@x402/evm": "^2.12.0",
|
|
46
46
|
"ai": "^6.0.185",
|
|
47
|
+
"chat": "^4.29.0",
|
|
47
48
|
"react": "^19.2.6",
|
|
48
49
|
"vitest-browser-react": "^2.2.0",
|
|
49
50
|
"zod": "^4.4.3"
|
|
@@ -55,6 +56,7 @@
|
|
|
55
56
|
"@x402/core": "^2.0.0",
|
|
56
57
|
"@x402/evm": "^2.0.0",
|
|
57
58
|
"ai": "^6.0.0",
|
|
59
|
+
"chat": "^4.29.0",
|
|
58
60
|
"react": "^19.0.0",
|
|
59
61
|
"vite": ">=6.0.0 <9.0.0",
|
|
60
62
|
"zod": "^4.0.0"
|
|
@@ -75,6 +77,9 @@
|
|
|
75
77
|
"@x402/evm": {
|
|
76
78
|
"optional": true
|
|
77
79
|
},
|
|
80
|
+
"chat": {
|
|
81
|
+
"optional": true
|
|
82
|
+
},
|
|
78
83
|
"vite": {
|
|
79
84
|
"optional": true
|
|
80
85
|
}
|
|
@@ -166,6 +171,11 @@
|
|
|
166
171
|
"import": "./dist/chat/index.js",
|
|
167
172
|
"require": "./dist/chat/index.js"
|
|
168
173
|
},
|
|
174
|
+
"./chat-sdk": {
|
|
175
|
+
"types": "./dist/chat-sdk/index.d.ts",
|
|
176
|
+
"import": "./dist/chat-sdk/index.js",
|
|
177
|
+
"require": "./dist/chat-sdk/index.js"
|
|
178
|
+
},
|
|
169
179
|
"./ai-chat-agent": {
|
|
170
180
|
"types": "./dist/ai-chat-agent.d.ts",
|
|
171
181
|
"import": "./dist/ai-chat-agent.js",
|