@columenlabs/lumen-ai 0.1.93 → 0.1.94
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/assistant/store.d.ts +11 -0
- package/dist/assistant/store.js +40 -1
- package/package.json +3 -3
|
@@ -25,6 +25,13 @@ export interface AssistantStore {
|
|
|
25
25
|
/** Creates the table. Safe to call often. */
|
|
26
26
|
init(): Promise<void>;
|
|
27
27
|
get(scope: string, key: string): Promise<StoredDoc | null>;
|
|
28
|
+
/** Several documents in one call, in the order asked (null where missing). Optional: a store
|
|
29
|
+
* across a network hop (a Durable Object stub) gives it so a request's reads in one tick are one
|
|
30
|
+
* call; `Docs.cached` uses it when present and `get` otherwise. */
|
|
31
|
+
getMany?(refs: {
|
|
32
|
+
scope: string;
|
|
33
|
+
key: string;
|
|
34
|
+
}[]): Promise<(StoredDoc | null)[]>;
|
|
28
35
|
put(scope: string, key: string, value: string, meta?: string | null): Promise<void>;
|
|
29
36
|
remove(scope: string, key: string): Promise<void>;
|
|
30
37
|
/** Keys starting with `prefix`, newest first, without their values. */
|
|
@@ -77,6 +84,10 @@ export declare class Docs {
|
|
|
77
84
|
private open;
|
|
78
85
|
private id;
|
|
79
86
|
private fresh;
|
|
87
|
+
/** Reads asked in the same tick, waiting to go as one `getMany` call. */
|
|
88
|
+
private batch;
|
|
89
|
+
/** One stored doc, joined with the other reads of this tick when the store can batch them. */
|
|
90
|
+
private batched;
|
|
80
91
|
read<T>(scope: string, key: string): Promise<T | null>;
|
|
81
92
|
write<T>(scope: string, key: string, value: T, meta?: string): Promise<void>;
|
|
82
93
|
/** Read (from the store, never the request's copy), change and write back; `change` returning
|
package/dist/assistant/store.js
CHANGED
|
@@ -55,6 +55,24 @@ export function sqlAssistantStore(sql) {
|
|
|
55
55
|
}
|
|
56
56
|
: null;
|
|
57
57
|
},
|
|
58
|
+
async getMany(refs) {
|
|
59
|
+
await init();
|
|
60
|
+
if (!refs.length)
|
|
61
|
+
return [];
|
|
62
|
+
const rows = await sql.all(`SELECT scope, key, meta, value, at FROM ${TABLE} WHERE ${refs.map(() => '(scope = ? AND key = ?)').join(' OR ')}`, ...refs.flatMap((r) => [r.scope, r.key]));
|
|
63
|
+
const by = new Map(rows.map((r) => [`${r.scope}\u0000${r.key}`, r]));
|
|
64
|
+
return refs.map(({ scope, key }) => {
|
|
65
|
+
const r = by.get(`${scope}\u0000${key}`);
|
|
66
|
+
return r
|
|
67
|
+
? {
|
|
68
|
+
key: String(r.key),
|
|
69
|
+
meta: r.meta == null ? null : String(r.meta),
|
|
70
|
+
value: String(r.value),
|
|
71
|
+
at: Number(r.at),
|
|
72
|
+
}
|
|
73
|
+
: null;
|
|
74
|
+
});
|
|
75
|
+
},
|
|
58
76
|
async put(scope, key, value, meta = null) {
|
|
59
77
|
await init();
|
|
60
78
|
await sql.run(`INSERT INTO ${TABLE} (scope, key, meta, value, at) VALUES (?, ?, ?, ?, ?) ON CONFLICT (scope, key) DO UPDATE SET meta = excluded.meta, value = excluded.value, at = excluded.at`, scope, key, meta, value, Date.now());
|
|
@@ -108,12 +126,33 @@ export class Docs {
|
|
|
108
126
|
const d = await this.store.get(scope, key);
|
|
109
127
|
return d ? this.open(d.value) : null;
|
|
110
128
|
}
|
|
129
|
+
/** Reads asked in the same tick, waiting to go as one `getMany` call. */
|
|
130
|
+
batch = null;
|
|
131
|
+
/** One stored doc, joined with the other reads of this tick when the store can batch them. */
|
|
132
|
+
batched(scope, key) {
|
|
133
|
+
const many = this.store.getMany?.bind(this.store);
|
|
134
|
+
if (!many)
|
|
135
|
+
return this.fresh(scope, key);
|
|
136
|
+
const doc = new Promise((resolve, reject) => {
|
|
137
|
+
if (!this.batch) {
|
|
138
|
+
const queue = [];
|
|
139
|
+
this.batch = queue;
|
|
140
|
+
queueMicrotask(() => {
|
|
141
|
+
this.batch = null;
|
|
142
|
+
const all = Promise.resolve().then(() => many(queue.map(({ scope, key }) => ({ scope, key }))));
|
|
143
|
+
queue.forEach((q, i) => q.done(all.then((docs) => docs[i] ?? null)));
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
this.batch.push({ scope, key, done: (d) => d.then(resolve, reject) });
|
|
147
|
+
});
|
|
148
|
+
return doc.then((d) => (d ? this.open(d.value) : null));
|
|
149
|
+
}
|
|
111
150
|
async read(scope, key) {
|
|
112
151
|
let text;
|
|
113
152
|
if (this.memo) {
|
|
114
153
|
const id = this.id(scope, key);
|
|
115
154
|
const hit = this.memo.get(id);
|
|
116
|
-
text = hit ?? this.
|
|
155
|
+
text = hit ?? this.batched(scope, key);
|
|
117
156
|
if (!hit) {
|
|
118
157
|
this.memo.set(id, text);
|
|
119
158
|
text.catch(() => this.memo?.delete(id));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ai",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.94",
|
|
4
4
|
"description": "Lumen's assistant and agent parts: a chat assistant's server (Claude tiers, tools over MCP, the web, hand off, spend caps), serving an MCP server from a Worker, read-only tool sets and metered tool calls.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@anthropic-ai/sdk": "0.133.0",
|
|
44
|
-
"@columenlabs/lumen-ops": "0.1.
|
|
45
|
-
"@columenlabs/lumen-ui-types": "0.1.
|
|
44
|
+
"@columenlabs/lumen-ops": "0.1.94",
|
|
45
|
+
"@columenlabs/lumen-ui-types": "0.1.94",
|
|
46
46
|
"openai": "7.32.0",
|
|
47
47
|
"zod": "^4.3.6"
|
|
48
48
|
},
|