@intentface/latch-drizzle 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +36 -0
  3. package/dist/adapter.d.ts +18 -0
  4. package/dist/adapter.d.ts.map +1 -0
  5. package/dist/adapter.js +33 -0
  6. package/dist/adapter.js.map +1 -0
  7. package/dist/adapter.pg.d.ts +10 -0
  8. package/dist/adapter.pg.d.ts.map +1 -0
  9. package/dist/adapter.pg.js +18 -0
  10. package/dist/adapter.pg.js.map +1 -0
  11. package/dist/adapter.shared.d.ts +55 -0
  12. package/dist/adapter.shared.d.ts.map +1 -0
  13. package/dist/adapter.shared.js +527 -0
  14. package/dist/adapter.shared.js.map +1 -0
  15. package/dist/agent-store.d.ts +34 -0
  16. package/dist/agent-store.d.ts.map +1 -0
  17. package/dist/agent-store.js +236 -0
  18. package/dist/agent-store.js.map +1 -0
  19. package/dist/agent-store.smoke.d.ts +2 -0
  20. package/dist/agent-store.smoke.d.ts.map +1 -0
  21. package/dist/agent-store.smoke.js +77 -0
  22. package/dist/agent-store.smoke.js.map +1 -0
  23. package/dist/index.d.ts +24 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +22 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/limit-store.d.ts +5 -0
  28. package/dist/limit-store.d.ts.map +1 -0
  29. package/dist/limit-store.js +7 -0
  30. package/dist/limit-store.js.map +1 -0
  31. package/dist/limit-store.pg.d.ts +5 -0
  32. package/dist/limit-store.pg.d.ts.map +1 -0
  33. package/dist/limit-store.pg.js +7 -0
  34. package/dist/limit-store.pg.js.map +1 -0
  35. package/dist/limit-store.shared.d.ts +14 -0
  36. package/dist/limit-store.shared.d.ts.map +1 -0
  37. package/dist/limit-store.shared.js +60 -0
  38. package/dist/limit-store.shared.js.map +1 -0
  39. package/dist/limit-store.smoke.shared.d.ts +7 -0
  40. package/dist/limit-store.smoke.shared.d.ts.map +1 -0
  41. package/dist/limit-store.smoke.shared.js +33 -0
  42. package/dist/limit-store.smoke.shared.js.map +1 -0
  43. package/dist/memory-job-store.d.ts +5 -0
  44. package/dist/memory-job-store.d.ts.map +1 -0
  45. package/dist/memory-job-store.js +7 -0
  46. package/dist/memory-job-store.js.map +1 -0
  47. package/dist/memory-job-store.pg.d.ts +5 -0
  48. package/dist/memory-job-store.pg.d.ts.map +1 -0
  49. package/dist/memory-job-store.pg.js +7 -0
  50. package/dist/memory-job-store.pg.js.map +1 -0
  51. package/dist/memory-job-store.shared.d.ts +23 -0
  52. package/dist/memory-job-store.shared.d.ts.map +1 -0
  53. package/dist/memory-job-store.shared.js +294 -0
  54. package/dist/memory-job-store.shared.js.map +1 -0
  55. package/dist/memory-job-store.smoke.shared.d.ts +18 -0
  56. package/dist/memory-job-store.smoke.shared.d.ts.map +1 -0
  57. package/dist/memory-job-store.smoke.shared.js +149 -0
  58. package/dist/memory-job-store.smoke.shared.js.map +1 -0
  59. package/dist/migrate.d.ts +10 -0
  60. package/dist/migrate.d.ts.map +1 -0
  61. package/dist/migrate.js +202 -0
  62. package/dist/migrate.js.map +1 -0
  63. package/dist/migrate.pg.d.ts +3 -0
  64. package/dist/migrate.pg.d.ts.map +1 -0
  65. package/dist/migrate.pg.js +120 -0
  66. package/dist/migrate.pg.js.map +1 -0
  67. package/dist/run-lease.smoke.shared.d.ts +13 -0
  68. package/dist/run-lease.smoke.shared.d.ts.map +1 -0
  69. package/dist/run-lease.smoke.shared.js +65 -0
  70. package/dist/run-lease.smoke.shared.js.map +1 -0
  71. package/dist/schedule.smoke.shared.d.ts +16 -0
  72. package/dist/schedule.smoke.shared.d.ts.map +1 -0
  73. package/dist/schedule.smoke.shared.js +104 -0
  74. package/dist/schedule.smoke.shared.js.map +1 -0
  75. package/dist/schema.d.ts +2348 -0
  76. package/dist/schema.d.ts.map +1 -0
  77. package/dist/schema.js +225 -0
  78. package/dist/schema.js.map +1 -0
  79. package/dist/schema.pg.d.ts +2215 -0
  80. package/dist/schema.pg.d.ts.map +1 -0
  81. package/dist/schema.pg.js +197 -0
  82. package/dist/schema.pg.js.map +1 -0
  83. package/dist/secret-store.d.ts +11 -0
  84. package/dist/secret-store.d.ts.map +1 -0
  85. package/dist/secret-store.js +11 -0
  86. package/dist/secret-store.js.map +1 -0
  87. package/dist/secret-store.pg.d.ts +6 -0
  88. package/dist/secret-store.pg.d.ts.map +1 -0
  89. package/dist/secret-store.pg.js +7 -0
  90. package/dist/secret-store.pg.js.map +1 -0
  91. package/dist/secret-store.shared.d.ts +25 -0
  92. package/dist/secret-store.shared.d.ts.map +1 -0
  93. package/dist/secret-store.shared.js +67 -0
  94. package/dist/secret-store.shared.js.map +1 -0
  95. package/dist/smoke.d.ts +2 -0
  96. package/dist/smoke.d.ts.map +1 -0
  97. package/dist/smoke.js +108 -0
  98. package/dist/smoke.js.map +1 -0
  99. package/dist/smoke.pg.d.ts +2 -0
  100. package/dist/smoke.pg.d.ts.map +1 -0
  101. package/dist/smoke.pg.js +107 -0
  102. package/dist/smoke.pg.js.map +1 -0
  103. package/package.json +62 -0
@@ -0,0 +1,236 @@
1
+ import { desc, eq, inArray, and, like, sql } from "drizzle-orm";
2
+ import { parseAgentRef } from "@intentface/latch-agent-builder";
3
+ import * as sqliteSchema from "./schema.js";
4
+ import * as pgSchema from "./schema.pg.js";
5
+ /**
6
+ * `AgentBuilderStore` on Drizzle — the persistence + dynamic-agent view for
7
+ * builder/editor-created agents (`latch_agents`). One shared core over a tiny
8
+ * query seam; SQLite and Postgres wrappers below.
9
+ */
10
+ function newId() {
11
+ return `agt_${crypto.randomUUID().replace(/-/g, "").slice(0, 20)}`;
12
+ }
13
+ /** Column value (INTEGER) ↔ AgentRecord.maxSteps: NULL=default, 0=unlimited, N=cap. */
14
+ const maxStepsToCol = (m) => m === "unlimited" ? 0 : typeof m === "number" ? m : null;
15
+ const maxStepsFromCol = (v) => v == null ? undefined : v === 0 ? "unlimited" : v;
16
+ const ownerKeyOf = (segments) => segments.map(encodeURIComponent).join("/");
17
+ function createStore(queries, opts) {
18
+ const ownerKey = (p, scope) => ownerKeyOf(opts.owner(p, scope));
19
+ const recordOf = (row) => ({
20
+ name: row.name,
21
+ title: row.title ?? undefined,
22
+ description: row.description ?? undefined,
23
+ modelId: row.modelId,
24
+ instructions: row.instructions,
25
+ connections: (row.connections ?? []),
26
+ maxSteps: maxStepsFromCol(row.maxSteps),
27
+ tools: (row.tools ?? undefined),
28
+ exec: (row.exec ?? undefined),
29
+ subagents: (row.subagents ?? undefined),
30
+ attachedEvals: (row.attachedEvals ?? undefined),
31
+ scope: row.scope,
32
+ });
33
+ async function find(p, name, scope) {
34
+ // Personal wins over org on a name clash — unless pinned to one scope.
35
+ const owners = scope === "org"
36
+ ? [ownerKey(p, "org")]
37
+ : scope === "user"
38
+ ? [ownerKey(p, "user")]
39
+ : [ownerKey(p, "user"), ownerKey(p, "org")];
40
+ const rows = await queries.byOwners(owners, name);
41
+ const personal = rows.find((r) => r.owner === ownerKey(p, "user"));
42
+ const row = personal ?? rows[0];
43
+ return row ? recordOf(row) : undefined;
44
+ }
45
+ return {
46
+ async resolve(name, principal) {
47
+ // Channel bindings pin resolution to one scope with an `org:`/`user:`
48
+ // prefix (stored names never contain `:` — normalizeAgentName strips
49
+ // it), so a same-named record in the OTHER scope can never shadow the
50
+ // agent the binding was created for.
51
+ const ref = parseAgentRef(name);
52
+ const rec = await find(principal, ref.name, ref.scope);
53
+ if (!rec)
54
+ return undefined;
55
+ const decorate = opts.decorateResolve ?? ((cfg) => cfg);
56
+ const sel = rec.tools;
57
+ const approvalEntries = Object.entries(sel?.approval ?? {});
58
+ // Authored tools attached to this agent, resolved per caller into a tool
59
+ // source. Marked alwaysActive so an `enabledTools` restriction on
60
+ // connection tools never hides them (they're capabilities, not picks).
61
+ const authored = rec.exec?.authoredTools?.length ? rec.exec.authoredTools : undefined;
62
+ const loadAuthoredTools = opts.loadAuthoredTools;
63
+ const toolSources = authored && loadAuthoredTools
64
+ ? [
65
+ {
66
+ async open(p) {
67
+ // Never let attached-tool resolution fail the whole turn.
68
+ try {
69
+ // Resolve under the AGENT's scope: an org agent gets org
70
+ // tools (shared with every member), not the caller's personal.
71
+ const tools = await loadAuthoredTools(p, authored, rec.scope);
72
+ return { tools, alwaysActive: Object.keys(tools), close: async () => { } };
73
+ }
74
+ catch (e) {
75
+ console.warn("Authored-tools attach failed; running without them:", e);
76
+ return { tools: {}, close: async () => { } };
77
+ }
78
+ },
79
+ },
80
+ ]
81
+ : undefined;
82
+ return decorate({
83
+ model: opts.modelFor(rec.modelId),
84
+ instructions: rec.instructions,
85
+ connections: rec.connections,
86
+ toolSources,
87
+ maxSteps: rec.maxSteps,
88
+ // Restrict callable tools (empty/undefined → all).
89
+ enabledTools: sel?.enabled?.length ? sel.enabled : undefined,
90
+ // Per-tool description overrides → applied to the resolved tools.
91
+ toolDescriptions: sel?.descriptions && Object.keys(sel.descriptions).length ? sel.descriptions : undefined,
92
+ // Agents this one may delegate to (→ the runtime's spawn_agent tool).
93
+ subagents: rec.subagents?.length ? rec.subagents : undefined,
94
+ // Per-tool approval override (agent wins): on → require, off → waive.
95
+ toolApproval: approvalEntries.length
96
+ ? Object.fromEntries(approvalEntries.map(([n, req]) => [n, req ? "user-approval" : "not-applicable"]))
97
+ : undefined,
98
+ // Code-execution capabilities (sandbox + default harness tools).
99
+ sandbox: rec.exec?.sandbox || undefined,
100
+ sandboxProvider: rec.exec?.provider,
101
+ defaultTools: rec.exec?.defaultTools,
102
+ disableTools: rec.exec?.disableTools,
103
+ providerWebTools: rec.exec?.providerWebTools || undefined,
104
+ renderTools: rec.exec?.renderTools || undefined,
105
+ effort: rec.exec?.effort,
106
+ // Persistent cross-session memory (needs a MemoryProvider on the runtime).
107
+ memory: rec.exec?.memory,
108
+ smoothStream: true,
109
+ }, rec, principal);
110
+ },
111
+ async list(principal) {
112
+ const rows = await queries.byOwners([ownerKey(principal, "user"), ownerKey(principal, "org")]);
113
+ return rows.map((r) => ({
114
+ name: r.name,
115
+ title: r.title ?? undefined,
116
+ description: r.description ?? undefined,
117
+ }));
118
+ },
119
+ async listRecords(principal) {
120
+ const rows = await queries.byOwners([ownerKey(principal, "user"), ownerKey(principal, "org")]);
121
+ return rows.map(recordOf);
122
+ },
123
+ async getRecord(principal, name) {
124
+ // Pin-aware like `resolve`: run records and channel bindings carry the
125
+ // `org:`/`user:` prefix, and hosts look rubrics/memory up by it.
126
+ const ref = parseAgentRef(name);
127
+ return find(principal, ref.name, ref.scope);
128
+ },
129
+ async listMemoryEnabledNames() {
130
+ return queries.memoryEnabledNames();
131
+ },
132
+ async upsert(principal, rec) {
133
+ await queries.upsert({
134
+ id: newId(),
135
+ owner: ownerKey(principal, rec.scope),
136
+ rec,
137
+ maxSteps: maxStepsToCol(rec.maxSteps),
138
+ now: Date.now(),
139
+ });
140
+ },
141
+ async remove(principal, scope, name) {
142
+ await queries.remove(ownerKey(principal, scope), name);
143
+ },
144
+ };
145
+ }
146
+ /** Shared upsert `set` payload (column shapes match across dialects). */
147
+ function upsertValues(row) {
148
+ const { id, owner, rec, maxSteps, now } = row;
149
+ return {
150
+ insert: {
151
+ id,
152
+ owner,
153
+ name: rec.name,
154
+ title: rec.title ?? null,
155
+ description: rec.description ?? null,
156
+ modelId: rec.modelId,
157
+ instructions: rec.instructions,
158
+ connections: rec.connections,
159
+ tools: rec.tools ?? null,
160
+ exec: rec.exec ?? null,
161
+ subagents: rec.subagents?.length ? rec.subagents : null,
162
+ attachedEvals: rec.attachedEvals?.length ? rec.attachedEvals : null,
163
+ maxSteps,
164
+ scope: rec.scope,
165
+ createdAt: now,
166
+ updatedAt: now,
167
+ },
168
+ update: {
169
+ title: rec.title ?? null,
170
+ description: rec.description ?? null,
171
+ modelId: rec.modelId,
172
+ instructions: rec.instructions,
173
+ connections: rec.connections,
174
+ tools: rec.tools ?? null,
175
+ exec: rec.exec ?? null,
176
+ subagents: rec.subagents?.length ? rec.subagents : null,
177
+ attachedEvals: rec.attachedEvals?.length ? rec.attachedEvals : null,
178
+ maxSteps,
179
+ scope: rec.scope,
180
+ updatedAt: now,
181
+ },
182
+ };
183
+ }
184
+ /** `AgentBuilderStore` on a Drizzle SQLite database (libsql / better-sqlite3 / Turso). */
185
+ export function createSqliteAgentBuilderStore(db, opts) {
186
+ const t = sqliteSchema.agents;
187
+ return createStore({
188
+ async byOwners(owners, name) {
189
+ const where = name ? and(inArray(t.owner, owners), eq(t.name, name)) : inArray(t.owner, owners);
190
+ return (await db.select().from(t).where(where).orderBy(desc(t.createdAt)));
191
+ },
192
+ async memoryEnabledNames() {
193
+ // The JSON column is text in both dialects' storage; a LIKE prefilter
194
+ // is what the sweep wants (cheap, tolerant of false positives).
195
+ const rows = (await db
196
+ .selectDistinct({ name: t.name })
197
+ .from(t)
198
+ .where(like(sql `CAST(${t.exec} AS TEXT)`, '%"memory"%')));
199
+ return rows.map((r) => r.name);
200
+ },
201
+ async upsert(row) {
202
+ const { insert, update } = upsertValues(row);
203
+ await db.insert(t).values(insert).onConflictDoUpdate({ target: [t.owner, t.name], set: update });
204
+ },
205
+ async remove(owner, name) {
206
+ await db.delete(t).where(and(eq(t.owner, owner), eq(t.name, name)));
207
+ },
208
+ }, opts);
209
+ }
210
+ /** `AgentBuilderStore` on a Drizzle Postgres database (node-postgres / postgres-js / PGlite). */
211
+ export function createPostgresAgentBuilderStore(db, opts) {
212
+ const t = pgSchema.agents;
213
+ return createStore({
214
+ async byOwners(owners, name) {
215
+ const where = name ? and(inArray(t.owner, owners), eq(t.name, name)) : inArray(t.owner, owners);
216
+ return (await db.select().from(t).where(where).orderBy(desc(t.createdAt)));
217
+ },
218
+ async memoryEnabledNames() {
219
+ // The JSON column is text in both dialects' storage; a LIKE prefilter
220
+ // is what the sweep wants (cheap, tolerant of false positives).
221
+ const rows = (await db
222
+ .selectDistinct({ name: t.name })
223
+ .from(t)
224
+ .where(like(sql `CAST(${t.exec} AS TEXT)`, '%"memory"%')));
225
+ return rows.map((r) => r.name);
226
+ },
227
+ async upsert(row) {
228
+ const { insert, update } = upsertValues(row);
229
+ await db.insert(t).values(insert).onConflictDoUpdate({ target: [t.owner, t.name], set: update });
230
+ },
231
+ async remove(owner, name) {
232
+ await db.delete(t).where(and(eq(t.owner, owner), eq(t.name, name)));
233
+ },
234
+ }, opts);
235
+ }
236
+ //# sourceMappingURL=agent-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-store.js","sourceRoot":"","sources":["../src/agent-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=agent-store.smoke.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-store.smoke.d.ts","sourceRoot":"","sources":["../src/agent-store.smoke.ts"],"names":[],"mappings":""}
@@ -0,0 +1,77 @@
1
+ import { createClient } from "@libsql/client";
2
+ import { drizzle } from "drizzle-orm/libsql";
3
+ import { migrate } from "./migrate.js";
4
+ import { createSqliteAgentBuilderStore } from "./agent-store.js";
5
+ const assert = (cond, msg) => {
6
+ if (!cond)
7
+ throw new Error(`FAIL: ${msg}`);
8
+ };
9
+ async function main() {
10
+ const p = { orgId: "o1", userId: "u1" };
11
+ const p2 = { orgId: "o1", userId: "u2" };
12
+ const client = createClient({ url: ":memory:" });
13
+ await migrate(client);
14
+ const store = createSqliteAgentBuilderStore(drizzle(client), {
15
+ owner: (pr, scope) => (scope === "org" ? [pr.orgId] : [pr.orgId, pr.userId]),
16
+ modelFor: (id) => ({ modelId: id }),
17
+ });
18
+ await store.upsert(p, {
19
+ name: "helper",
20
+ modelId: "m-1",
21
+ instructions: "help",
22
+ connections: ["github"],
23
+ maxSteps: "unlimited",
24
+ exec: { sandbox: true, effort: "low", memory: { scope: "agent-user", connection: "github" } },
25
+ subagents: ["assistant"],
26
+ attachedEvals: [{ name: "on-topic", prompt: "Stays on topic.", scale: "binary", enabled: true }],
27
+ scope: "user",
28
+ });
29
+ await store.upsert(p, {
30
+ name: "shared",
31
+ modelId: "m-2",
32
+ instructions: "org agent",
33
+ connections: [],
34
+ scope: "org",
35
+ });
36
+ // list: personal + org visible; another org member sees only org
37
+ assert((await store.list(p)).length === 2, "creator sees both");
38
+ const other = await store.list(p2);
39
+ assert(other.length === 1 && other[0].name === "shared", "other member sees org only");
40
+ // record fields round-trip
41
+ const recs = await store.listRecords(p);
42
+ const helper = recs.find((r) => r.name === "helper");
43
+ assert(helper.maxSteps === "unlimited", "maxSteps unlimited round-trips");
44
+ assert(helper.exec?.sandbox === true && helper.exec?.effort === "low", "exec round-trips");
45
+ assert(Array.isArray(helper.connections) && helper.connections[0] === "github", "connections round-trip");
46
+ assert(helper.attachedEvals?.[0]?.name === "on-topic", "attachedEvals round-trip");
47
+ assert(helper.exec?.memory?.connection === "github", "exec.memory round-trips");
48
+ // getRecord: bare name (personal wins), org: pin, user: pin miss
49
+ assert((await store.getRecord(p, "helper"))?.modelId === "m-1", "getRecord bare name");
50
+ assert((await store.getRecord(p2, "org:shared"))?.name === "shared", "getRecord org: pin");
51
+ assert(!(await store.getRecord(p2, "user:shared")), "getRecord user: pin misses org record");
52
+ // listMemoryEnabledNames: cross-tenant prefilter by exec JSON
53
+ const memNames = await store.listMemoryEnabledNames();
54
+ assert(memNames.includes("helper") && !memNames.includes("shared"), "listMemoryEnabledNames prefilter");
55
+ // resolve builds AgentConfig; scope pinning works
56
+ const cfg = await store.resolve("helper", p);
57
+ assert(cfg && cfg.instructions === "help" && cfg.maxSteps === "unlimited", "resolve builds config");
58
+ assert(cfg.memory?.scope === "agent-user", "resolve carries exec.memory");
59
+ assert(cfg.model.modelId === "m-1", "modelFor applied");
60
+ assert(cfg.subagents?.[0] === "assistant", "subagents resolve");
61
+ assert(await store.resolve("org:shared", p2), "org: pin resolves");
62
+ assert(!(await store.resolve("user:shared", p2)), "user: pin misses org record");
63
+ // upsert-by-name updates, not duplicates
64
+ await store.upsert(p, { name: "helper", modelId: "m-2", instructions: "help v2", connections: [], scope: "user" });
65
+ const after = await store.listRecords(p);
66
+ assert(after.filter((r) => r.name === "helper").length === 1, "upsert dedupes");
67
+ assert(after.find((r) => r.name === "helper").modelId === "m-2", "upsert updates");
68
+ // remove
69
+ await store.remove(p, "user", "helper");
70
+ assert(!(await store.resolve("helper", p)), "removed record no longer resolves");
71
+ console.log("agent-store smoke: ALL PASS");
72
+ }
73
+ main().catch((e) => {
74
+ console.error("❌ agent-store smoke failed:", e);
75
+ throw e; // unhandled rejection → non-zero exit (no @types/node dep here)
76
+ });
77
+ //# sourceMappingURL=agent-store.smoke.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-store.smoke.js","sourceRoot":"","sources":["../src/agent-store.smoke.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAKjE,MAAM,MAAM,GAAG,CAAC,IAAa,EAAE,GAAW,EAAE,EAAE;IAC5C,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC;AAC7C,CAAC,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,GAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC3C,MAAM,EAAE,GAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAE5C,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;IACjD,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACtB,MAAM,KAAK,GAAG,6BAA6B,CAAI,OAAO,CAAC,MAAM,CAAC,EAAE;QAC9D,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;QAC5E,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAU;KAC7C,CAAC,CAAC;IAEH,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE;QACpB,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,KAAK;QACd,YAAY,EAAE,MAAM;QACpB,WAAW,EAAE,CAAC,QAAQ,CAAC;QACvB,QAAQ,EAAE,WAAW;QACrB,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE;QAC7F,SAAS,EAAE,CAAC,WAAW,CAAC;QACxB,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAChG,KAAK,EAAE,MAAM;KACd,CAAC,CAAC;IACH,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE;QACpB,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,KAAK;QACd,YAAY,EAAE,WAAW;QACzB,WAAW,EAAE,EAAE;QACf,KAAK,EAAE,KAAK;KACb,CAAC,CAAC;IAEH,iEAAiE;IACjE,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,mBAAmB,CAAC,CAAC;IAChE,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnC,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,4BAA4B,CAAC,CAAC;IAExF,2BAA2B;IAC3B,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAE,CAAC;IACtD,MAAM,CAAC,MAAM,CAAC,QAAQ,KAAK,WAAW,EAAE,gCAAgC,CAAC,CAAC;IAC1E,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,EAAE,kBAAkB,CAAC,CAAC;IAC3F,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,wBAAwB,CAAC,CAAC;IAC1G,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,UAAU,EAAE,0BAA0B,CAAC,CAAC;IACnF,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,KAAK,QAAQ,EAAE,yBAAyB,CAAC,CAAC;IAEhF,iEAAiE;IACjE,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,OAAO,KAAK,KAAK,EAAE,qBAAqB,CAAC,CAAC;IACvF,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC,EAAE,IAAI,KAAK,QAAQ,EAAE,oBAAoB,CAAC,CAAC;IAC3F,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC,EAAE,uCAAuC,CAAC,CAAC;IAE7F,8DAA8D;IAC9D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,sBAAsB,EAAE,CAAC;IACtD,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,kCAAkC,CAAC,CAAC;IAExG,kDAAkD;IAClD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC7C,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,YAAY,KAAK,MAAM,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,EAAE,uBAAuB,CAAC,CAAC;IACpG,MAAM,CAAC,GAAI,CAAC,MAAM,EAAE,KAAK,KAAK,YAAY,EAAE,6BAA6B,CAAC,CAAC;IAC3E,MAAM,CAAE,GAAI,CAAC,KAA6B,CAAC,OAAO,KAAK,KAAK,EAAE,kBAAkB,CAAC,CAAC;IAClF,MAAM,CAAC,GAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,KAAK,WAAW,EAAE,mBAAmB,CAAC,CAAC;IACjE,MAAM,CAAC,MAAM,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,mBAAmB,CAAC,CAAC;IACnE,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,EAAE,6BAA6B,CAAC,CAAC;IAEjF,yCAAyC;IACzC,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACnH,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAChF,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAE,CAAC,OAAO,KAAK,KAAK,EAAE,gBAAgB,CAAC,CAAC;IAEpF,SAAS;IACT,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IACxC,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,mCAAmC,CAAC,CAAC;IAEjF,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;AAC7C,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,CAAC,CAAC,CAAC;IAChD,MAAM,CAAC,CAAC,CAAC,gEAAgE;AAC3E,CAAC,CAAC,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @intentface/latch-drizzle
3
+ *
4
+ * The StorageAdapter on Drizzle, in two dialects behind the same
5
+ * `StorageAdapter` contract: SQLite (libsql / better-sqlite3 / Turso) and
6
+ * Postgres (node-postgres / postgres-js / PGlite).
7
+ */
8
+ export { createSqliteAdapter, isUniqueViolation } from "./adapter.js";
9
+ export type { SqliteAdapterOptions } from "./adapter.js";
10
+ export { createSqliteSecretStore } from "./secret-store.js";
11
+ export type { SqliteSecretStoreOptions } from "./secret-store.js";
12
+ export { createSqliteAgentBuilderStore, createPostgresAgentBuilderStore } from "./agent-store.js";
13
+ export type { AgentStoreOptions } from "./agent-store.js";
14
+ export { migrate, migrateWith } from "./migrate.js";
15
+ export * as schema from "./schema.js";
16
+ export { createMemoryJobStore } from "./memory-job-store.js";
17
+ export { createSqliteLimitStore } from "./limit-store.js";
18
+ export { createPostgresAdapter } from "./adapter.pg.js";
19
+ export { createPostgresSecretStore } from "./secret-store.pg.js";
20
+ export { migratePostgres } from "./migrate.pg.js";
21
+ export * as pgSchema from "./schema.pg.js";
22
+ export { createPostgresMemoryJobStore } from "./memory-job-store.pg.js";
23
+ export { createPostgresLimitStore } from "./limit-store.pg.js";
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtE,YAAY,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,YAAY,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,6BAA6B,EAAE,+BAA+B,EAAE,MAAM,kBAAkB,CAAC;AAClG,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @intentface/latch-drizzle
3
+ *
4
+ * The StorageAdapter on Drizzle, in two dialects behind the same
5
+ * `StorageAdapter` contract: SQLite (libsql / better-sqlite3 / Turso) and
6
+ * Postgres (node-postgres / postgres-js / PGlite).
7
+ */
8
+ export { createSqliteAdapter, isUniqueViolation } from "./adapter.js";
9
+ export { createSqliteSecretStore } from "./secret-store.js";
10
+ export { createSqliteAgentBuilderStore, createPostgresAgentBuilderStore } from "./agent-store.js";
11
+ export { migrate, migrateWith } from "./migrate.js";
12
+ export * as schema from "./schema.js";
13
+ export { createMemoryJobStore } from "./memory-job-store.js";
14
+ export { createSqliteLimitStore } from "./limit-store.js";
15
+ // Postgres dialect (node-postgres / postgres-js in prod, PGlite for tests).
16
+ export { createPostgresAdapter } from "./adapter.pg.js";
17
+ export { createPostgresSecretStore } from "./secret-store.pg.js";
18
+ export { migratePostgres } from "./migrate.pg.js";
19
+ export * as pgSchema from "./schema.pg.js";
20
+ export { createPostgresMemoryJobStore } from "./memory-job-store.pg.js";
21
+ export { createPostgresLimitStore } from "./limit-store.pg.js";
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,OAAO,EAAE,6BAA6B,EAAE,+BAA+B,EAAE,MAAM,kBAAkB,CAAC;AAElG,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,4EAA4E;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core";
2
+ import type { LimitStore } from "@intentface/latch-core";
3
+ /** LimitStore (per org/user/agent budgets) on a Drizzle SQLite database. */
4
+ export declare function createSqliteLimitStore(db: BaseSQLiteDatabase<"sync" | "async", any, any>): LimitStore;
5
+ //# sourceMappingURL=limit-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limit-store.d.ts","sourceRoot":"","sources":["../src/limit-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAIzD,4EAA4E;AAC5E,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,kBAAkB,CAAC,MAAM,GAAG,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,UAAU,CAErG"}
@@ -0,0 +1,7 @@
1
+ import * as schema from "./schema.js";
2
+ import { makeLimitStore } from "./limit-store.shared.js";
3
+ /** LimitStore (per org/user/agent budgets) on a Drizzle SQLite database. */
4
+ export function createSqliteLimitStore(db) {
5
+ return makeLimitStore(db, schema);
6
+ }
7
+ //# sourceMappingURL=limit-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limit-store.js","sourceRoot":"","sources":["../src/limit-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,4EAA4E;AAC5E,MAAM,UAAU,sBAAsB,CAAC,EAAkD;IACvF,OAAO,cAAc,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { PgDatabase } from "drizzle-orm/pg-core";
2
+ import type { LimitStore } from "@intentface/latch-core";
3
+ /** LimitStore (per org/user/agent budgets) on a Drizzle Postgres database. */
4
+ export declare function createPostgresLimitStore(db: PgDatabase<any, any, any>): LimitStore;
5
+ //# sourceMappingURL=limit-store.pg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limit-store.pg.d.ts","sourceRoot":"","sources":["../src/limit-store.pg.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAIzD,8EAA8E;AAC9E,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,UAAU,CAElF"}
@@ -0,0 +1,7 @@
1
+ import * as schema from "./schema.pg.js";
2
+ import { makeLimitStore } from "./limit-store.shared.js";
3
+ /** LimitStore (per org/user/agent budgets) on a Drizzle Postgres database. */
4
+ export function createPostgresLimitStore(db) {
5
+ return makeLimitStore(db, schema);
6
+ }
7
+ //# sourceMappingURL=limit-store.pg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limit-store.pg.js","sourceRoot":"","sources":["../src/limit-store.pg.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,8EAA8E;AAC9E,MAAM,UAAU,wBAAwB,CAAC,EAA6B;IACpE,OAAO,cAAc,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { LimitStore } from "@intentface/latch-core";
2
+ /**
3
+ * Dialect-shared `LimitStore`: one row per (key, windowStart, windowMs) — the
4
+ * same key may carry several window lengths whose starts coincide. `add` is a single
5
+ * upsert per entry with `SET n = n + excluded.n`, so concurrent turns settling
6
+ * into the same window never lose an increment. Both dialects support the
7
+ * query-builder surface used here.
8
+ */
9
+ interface LimitSchema {
10
+ limitCounters: any;
11
+ }
12
+ export declare function makeLimitStore(db: any, s: LimitSchema): LimitStore;
13
+ export {};
14
+ //# sourceMappingURL=limit-store.shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limit-store.shared.d.ts","sourceRoot":"","sources":["../src/limit-store.shared.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAA8B,MAAM,wBAAwB,CAAC;AAGrF;;;;;;GAMG;AAEH,UAAU,WAAW;IACnB,aAAa,EAAE,GAAG,CAAC;CACpB;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,WAAW,GAAG,UAAU,CA2DlE"}
@@ -0,0 +1,60 @@
1
+ import { and, eq, lt, or, sql } from "drizzle-orm";
2
+ import { usageKey } from "@intentface/latch-core";
3
+ export function makeLimitStore(db, s) {
4
+ const t = s.limitCounters;
5
+ return {
6
+ async read(refs) {
7
+ if (refs.length === 0)
8
+ return {};
9
+ const rows = await db
10
+ .select()
11
+ .from(t)
12
+ .where(or(...refs.map((r) => and(eq(t.key, r.key), eq(t.windowStart, r.windowStart), eq(t.windowMs, r.windowMs)))));
13
+ const out = {};
14
+ for (const r of rows) {
15
+ out[usageKey({ key: r.key, windowStart: Number(r.windowStart), windowMs: Number(r.windowMs) })] = {
16
+ turns: Number(r.turns ?? 0),
17
+ tokens: Number(r.tokens ?? 0),
18
+ cost: Number(r.cost ?? 0),
19
+ };
20
+ }
21
+ return out;
22
+ },
23
+ async add(entries) {
24
+ const now = Date.now();
25
+ const out = {};
26
+ for (const e of entries) {
27
+ const turns = e.usage.turns ?? 0;
28
+ const tokens = e.usage.tokens ?? 0;
29
+ const cost = e.usage.cost ?? 0;
30
+ // One statement: upsert + RETURNING the post-increment row, so a
31
+ // reservation reads its own count and concurrent reservers get
32
+ // distinct, ordered counts.
33
+ const rows = await db
34
+ .insert(t)
35
+ .values({ key: e.key, windowStart: e.windowStart, windowMs: e.windowMs, turns, tokens, cost, updatedAt: now })
36
+ .onConflictDoUpdate({
37
+ target: [t.key, t.windowStart, t.windowMs],
38
+ set: {
39
+ turns: sql `${t.turns} + ${turns}`,
40
+ tokens: sql `${t.tokens} + ${tokens}`,
41
+ cost: sql `${t.cost} + ${cost}`,
42
+ updatedAt: now,
43
+ },
44
+ })
45
+ .returning();
46
+ const r = rows[0];
47
+ out[usageKey(e)] = {
48
+ turns: Number(r?.turns ?? turns),
49
+ tokens: Number(r?.tokens ?? tokens),
50
+ cost: Number(r?.cost ?? cost),
51
+ };
52
+ }
53
+ return out;
54
+ },
55
+ async prune(before) {
56
+ await db.delete(t).where(lt(sql `${t.windowStart} + ${t.windowMs}`, before));
57
+ },
58
+ };
59
+ }
60
+ //# sourceMappingURL=limit-store.shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limit-store.shared.js","sourceRoot":"","sources":["../src/limit-store.shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { LimitStore } from "@intentface/latch-core";
2
+ /** Dialect-shared smoke for the LimitStore: additive upserts, zero reads, prune. */
3
+ export declare function limitStoreSmoke(args: {
4
+ limits: LimitStore;
5
+ assert: (cond: boolean, msg: string) => void;
6
+ }): Promise<void>;
7
+ //# sourceMappingURL=limit-store.smoke.shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limit-store.smoke.shared.d.ts","sourceRoot":"","sources":["../src/limit-store.smoke.shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGzD,oFAAoF;AACpF,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C,GAAG,OAAO,CAAC,IAAI,CAAC,CAgChB"}
@@ -0,0 +1,33 @@
1
+ import { usageKey } from "@intentface/latch-core";
2
+ /** Dialect-shared smoke for the LimitStore: additive upserts, zero reads, prune. */
3
+ export async function limitStoreSmoke(args) {
4
+ const { limits, assert } = args;
5
+ const MINUTE = 60_000;
6
+ const now = 10 * MINUTE + 5_000;
7
+ const ref = { key: "user:org_a:u1", windowStart: 10 * MINUTE, windowMs: MINUTE };
8
+ const other = { key: "org:org_a", windowStart: 0, windowMs: 24 * 3_600_000 };
9
+ assert(Object.keys(await limits.read([ref])).length === 0, "limits: absent row reads as nothing");
10
+ const first = await limits.add([{ ...ref, usage: { turns: 1 } }]);
11
+ assert(first[usageKey(ref)]?.turns === 1, "limits: add returns the post-increment row (fresh)");
12
+ const again = await limits.add([{ ...ref, usage: { turns: 1 } }]);
13
+ assert(again[usageKey(ref)]?.turns === 2, "limits: add returns the post-increment row (existing)");
14
+ await limits.add([{ ...ref, usage: { turns: -1 } }]); // a refused reservation released
15
+ await limits.add([{ ...ref, usage: { tokens: 120, cost: 0.5 } }, { ...other, usage: { turns: 1, tokens: 120, cost: 0.5 } }]);
16
+ await limits.add([{ ...ref, usage: { tokens: 30, cost: 0.25 } }]);
17
+ const usage = await limits.read([ref, other]);
18
+ const u = usage[usageKey(ref)];
19
+ assert(u?.turns === 1 && u.tokens === 150 && Math.abs(u.cost - 0.75) < 1e-9, `limits: additive upsert (${JSON.stringify(u)})`);
20
+ assert(usage[usageKey(other)]?.tokens === 120, "limits: second key kept apart");
21
+ // Same key, two window lengths whose starts coincide (0): separate counters.
22
+ const dayRef = { key: "org:org_a", windowStart: 0, windowMs: 24 * 3_600_000 };
23
+ const hourRef = { key: "org:org_a", windowStart: 0, windowMs: 3_600_000 };
24
+ await limits.add([{ ...hourRef, usage: { tokens: 7 } }]);
25
+ const both = await limits.read([dayRef, hourRef]);
26
+ assert(both[usageKey(dayRef)]?.tokens === 120 && both[usageKey(hourRef)]?.tokens === 7, "limits: windowMs is part of the identity");
27
+ // A window that ended before `before` is pruned; a live one stays.
28
+ await limits.prune(now + 2 * MINUTE);
29
+ const after = await limits.read([ref, other]);
30
+ assert(after[usageKey(ref)] === undefined, "limits: ended window pruned");
31
+ assert(after[usageKey(other)] !== undefined, "limits: live window kept");
32
+ }
33
+ //# sourceMappingURL=limit-store.smoke.shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limit-store.smoke.shared.js","sourceRoot":"","sources":["../src/limit-store.smoke.shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core";
2
+ import type { MemoryJobStore } from "@intentface/latch-memory";
3
+ /** MemoryJobStore on a Drizzle SQLite database (libsql / better-sqlite3 / Turso). */
4
+ export declare function createMemoryJobStore(db: BaseSQLiteDatabase<"sync" | "async", any, any>): MemoryJobStore;
5
+ //# sourceMappingURL=memory-job-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-job-store.d.ts","sourceRoot":"","sources":["../src/memory-job-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAI/D,qFAAqF;AACrF,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,kBAAkB,CAAC,MAAM,GAAG,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,GACjD,cAAc,CAEhB"}
@@ -0,0 +1,7 @@
1
+ import * as schema from "./schema.js";
2
+ import { makeMemoryJobStore } from "./memory-job-store.shared.js";
3
+ /** MemoryJobStore on a Drizzle SQLite database (libsql / better-sqlite3 / Turso). */
4
+ export function createMemoryJobStore(db) {
5
+ return makeMemoryJobStore(db, schema);
6
+ }
7
+ //# sourceMappingURL=memory-job-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-job-store.js","sourceRoot":"","sources":["../src/memory-job-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAElE,qFAAqF;AACrF,MAAM,UAAU,oBAAoB,CAClC,EAAkD;IAElD,OAAO,kBAAkB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;AACxC,CAAC"}