@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.
- package/LICENSE +21 -0
- package/README.md +36 -0
- package/dist/adapter.d.ts +18 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +33 -0
- package/dist/adapter.js.map +1 -0
- package/dist/adapter.pg.d.ts +10 -0
- package/dist/adapter.pg.d.ts.map +1 -0
- package/dist/adapter.pg.js +18 -0
- package/dist/adapter.pg.js.map +1 -0
- package/dist/adapter.shared.d.ts +55 -0
- package/dist/adapter.shared.d.ts.map +1 -0
- package/dist/adapter.shared.js +527 -0
- package/dist/adapter.shared.js.map +1 -0
- package/dist/agent-store.d.ts +34 -0
- package/dist/agent-store.d.ts.map +1 -0
- package/dist/agent-store.js +236 -0
- package/dist/agent-store.js.map +1 -0
- package/dist/agent-store.smoke.d.ts +2 -0
- package/dist/agent-store.smoke.d.ts.map +1 -0
- package/dist/agent-store.smoke.js +77 -0
- package/dist/agent-store.smoke.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/limit-store.d.ts +5 -0
- package/dist/limit-store.d.ts.map +1 -0
- package/dist/limit-store.js +7 -0
- package/dist/limit-store.js.map +1 -0
- package/dist/limit-store.pg.d.ts +5 -0
- package/dist/limit-store.pg.d.ts.map +1 -0
- package/dist/limit-store.pg.js +7 -0
- package/dist/limit-store.pg.js.map +1 -0
- package/dist/limit-store.shared.d.ts +14 -0
- package/dist/limit-store.shared.d.ts.map +1 -0
- package/dist/limit-store.shared.js +60 -0
- package/dist/limit-store.shared.js.map +1 -0
- package/dist/limit-store.smoke.shared.d.ts +7 -0
- package/dist/limit-store.smoke.shared.d.ts.map +1 -0
- package/dist/limit-store.smoke.shared.js +33 -0
- package/dist/limit-store.smoke.shared.js.map +1 -0
- package/dist/memory-job-store.d.ts +5 -0
- package/dist/memory-job-store.d.ts.map +1 -0
- package/dist/memory-job-store.js +7 -0
- package/dist/memory-job-store.js.map +1 -0
- package/dist/memory-job-store.pg.d.ts +5 -0
- package/dist/memory-job-store.pg.d.ts.map +1 -0
- package/dist/memory-job-store.pg.js +7 -0
- package/dist/memory-job-store.pg.js.map +1 -0
- package/dist/memory-job-store.shared.d.ts +23 -0
- package/dist/memory-job-store.shared.d.ts.map +1 -0
- package/dist/memory-job-store.shared.js +294 -0
- package/dist/memory-job-store.shared.js.map +1 -0
- package/dist/memory-job-store.smoke.shared.d.ts +18 -0
- package/dist/memory-job-store.smoke.shared.d.ts.map +1 -0
- package/dist/memory-job-store.smoke.shared.js +149 -0
- package/dist/memory-job-store.smoke.shared.js.map +1 -0
- package/dist/migrate.d.ts +10 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +202 -0
- package/dist/migrate.js.map +1 -0
- package/dist/migrate.pg.d.ts +3 -0
- package/dist/migrate.pg.d.ts.map +1 -0
- package/dist/migrate.pg.js +120 -0
- package/dist/migrate.pg.js.map +1 -0
- package/dist/run-lease.smoke.shared.d.ts +13 -0
- package/dist/run-lease.smoke.shared.d.ts.map +1 -0
- package/dist/run-lease.smoke.shared.js +65 -0
- package/dist/run-lease.smoke.shared.js.map +1 -0
- package/dist/schedule.smoke.shared.d.ts +16 -0
- package/dist/schedule.smoke.shared.d.ts.map +1 -0
- package/dist/schedule.smoke.shared.js +104 -0
- package/dist/schedule.smoke.shared.js.map +1 -0
- package/dist/schema.d.ts +2348 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +225 -0
- package/dist/schema.js.map +1 -0
- package/dist/schema.pg.d.ts +2215 -0
- package/dist/schema.pg.d.ts.map +1 -0
- package/dist/schema.pg.js +197 -0
- package/dist/schema.pg.js.map +1 -0
- package/dist/secret-store.d.ts +11 -0
- package/dist/secret-store.d.ts.map +1 -0
- package/dist/secret-store.js +11 -0
- package/dist/secret-store.js.map +1 -0
- package/dist/secret-store.pg.d.ts +6 -0
- package/dist/secret-store.pg.d.ts.map +1 -0
- package/dist/secret-store.pg.js +7 -0
- package/dist/secret-store.pg.js.map +1 -0
- package/dist/secret-store.shared.d.ts +25 -0
- package/dist/secret-store.shared.d.ts.map +1 -0
- package/dist/secret-store.shared.js +67 -0
- package/dist/secret-store.shared.js.map +1 -0
- package/dist/smoke.d.ts +2 -0
- package/dist/smoke.d.ts.map +1 -0
- package/dist/smoke.js +108 -0
- package/dist/smoke.js.map +1 -0
- package/dist/smoke.pg.d.ts +2 -0
- package/dist/smoke.pg.d.ts.map +1 -0
- package/dist/smoke.pg.js +107 -0
- package/dist/smoke.pg.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.pg.d.ts","sourceRoot":"","sources":["../src/schema.pg.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { sql } from "drizzle-orm";
|
|
2
|
+
import { pgTable, text, integer, bigint, jsonb, doublePrecision, index, primaryKey, uniqueIndex, } from "drizzle-orm/pg-core";
|
|
3
|
+
/** The v1 tables, Postgres dialect. Same shape as SQLite; jsonb for parts/metadata,
|
|
4
|
+
* bigint (epoch ms) for timestamps, double precision for cost. */
|
|
5
|
+
export const chats = pgTable("latch_chats", {
|
|
6
|
+
id: text("id").primaryKey(),
|
|
7
|
+
owner: text("owner").notNull(),
|
|
8
|
+
agent: text("agent").notNull(),
|
|
9
|
+
title: text("title"),
|
|
10
|
+
/** Chat kind: 'user' (default) vs 'internal' sub-threads (ChatRecord.kind). */
|
|
11
|
+
kind: text("kind").notNull().default("user"),
|
|
12
|
+
createdAt: bigint("created_at", { mode: "number" }).notNull(),
|
|
13
|
+
updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
|
|
14
|
+
}, (t) => [
|
|
15
|
+
index("latch_chats_owner_idx").on(t.owner),
|
|
16
|
+
// The memory sweep enumerates idle chats system-wide (no owner filter).
|
|
17
|
+
index("latch_chats_sweep_idx").on(t.kind, t.updatedAt),
|
|
18
|
+
]);
|
|
19
|
+
export const messages = pgTable("latch_messages", {
|
|
20
|
+
id: text("id").notNull(),
|
|
21
|
+
chatId: text("chat_id").notNull(),
|
|
22
|
+
runId: text("run_id"),
|
|
23
|
+
seq: integer("seq").notNull(),
|
|
24
|
+
role: text("role").notNull(),
|
|
25
|
+
parts: jsonb("parts").notNull(),
|
|
26
|
+
metadata: jsonb("metadata"),
|
|
27
|
+
createdAt: bigint("created_at", { mode: "number" }).notNull(),
|
|
28
|
+
}, (t) => [
|
|
29
|
+
// Message ids are client/stream-generated, so they're only unique WITHIN a
|
|
30
|
+
// chat — a global PK on `id` would let an upsert in one chat overwrite a
|
|
31
|
+
// same-id row in another owner's chat. Scope the identity to the chat.
|
|
32
|
+
primaryKey({ columns: [t.chatId, t.id] }),
|
|
33
|
+
// One row per (chat, seq): guards concurrent appenders computing the same
|
|
34
|
+
// next seq. Doubles as the (chat_id, seq) read-ordering index.
|
|
35
|
+
uniqueIndex("latch_messages_chat_seq_idx").on(t.chatId, t.seq),
|
|
36
|
+
]);
|
|
37
|
+
export const runs = pgTable("latch_runs", {
|
|
38
|
+
id: text("id").primaryKey(),
|
|
39
|
+
chatId: text("chat_id").notNull(),
|
|
40
|
+
agent: text("agent").notNull(),
|
|
41
|
+
status: text("status").notNull(),
|
|
42
|
+
identity: jsonb("identity"),
|
|
43
|
+
leaseOwner: text("lease_owner"),
|
|
44
|
+
leaseExpiresAt: bigint("lease_expires_at", { mode: "number" }),
|
|
45
|
+
fencingToken: integer("fencing_token"),
|
|
46
|
+
heartbeatAt: bigint("heartbeat_at", { mode: "number" }),
|
|
47
|
+
attempt: integer("attempt"),
|
|
48
|
+
usageInputTokens: integer("usage_input_tokens"),
|
|
49
|
+
usageOutputTokens: integer("usage_output_tokens"),
|
|
50
|
+
usageCacheReadTokens: integer("usage_cache_read_tokens"),
|
|
51
|
+
usageCacheWriteTokens: integer("usage_cache_write_tokens"),
|
|
52
|
+
costTotal: doublePrecision("cost_total"),
|
|
53
|
+
/** Run kind: 'turn' (default) vs 'compaction' — keeps cache/hit-rate stats clean. */
|
|
54
|
+
kind: text("kind"),
|
|
55
|
+
/** Opaque fingerprint of the sorted tool names this turn sent (see
|
|
56
|
+
* `toolsetHash`) — detects toolset churn. */
|
|
57
|
+
toolsHash: text("tools_hash"),
|
|
58
|
+
error: text("error"),
|
|
59
|
+
startedAt: bigint("started_at", { mode: "number" }).notNull(),
|
|
60
|
+
endedAt: bigint("ended_at", { mode: "number" }),
|
|
61
|
+
}, (t) => [
|
|
62
|
+
index("latch_runs_chat_idx").on(t.chatId),
|
|
63
|
+
index("latch_runs_reaper_idx").on(t.status, t.leaseExpiresAt),
|
|
64
|
+
// One ACTIVE run per chat — the concurrency invariant (see ChatBusyError).
|
|
65
|
+
uniqueIndex("latch_runs_one_active_per_chat").on(t.chatId).where(sql `status = 'active'`),
|
|
66
|
+
]);
|
|
67
|
+
/** Envelope-encrypted connection credentials. No plaintext is ever stored. */
|
|
68
|
+
export const secrets = pgTable("latch_secrets", {
|
|
69
|
+
id: text("id").primaryKey(),
|
|
70
|
+
owner: text("owner").notNull(),
|
|
71
|
+
key: text("key").notNull(),
|
|
72
|
+
ciphertext: text("ciphertext").notNull(),
|
|
73
|
+
iv: text("iv").notNull(),
|
|
74
|
+
wrappedDek: text("wrapped_dek").notNull(),
|
|
75
|
+
dekIv: text("dek_iv").notNull(),
|
|
76
|
+
createdAt: bigint("created_at", { mode: "number" }).notNull(),
|
|
77
|
+
updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
|
|
78
|
+
}, (t) => [index("latch_secrets_owner_idx").on(t.owner)]);
|
|
79
|
+
export const usage = pgTable("latch_usage", {
|
|
80
|
+
id: text("id").primaryKey(),
|
|
81
|
+
owner: text("owner").notNull(),
|
|
82
|
+
runId: text("run_id").notNull(),
|
|
83
|
+
model: text("model").notNull(),
|
|
84
|
+
inputTokens: integer("input_tokens").notNull(),
|
|
85
|
+
outputTokens: integer("output_tokens").notNull(),
|
|
86
|
+
cacheReadTokens: integer("cache_read_tokens"),
|
|
87
|
+
cacheWriteTokens: integer("cache_write_tokens"),
|
|
88
|
+
cost: doublePrecision("cost").notNull(),
|
|
89
|
+
createdAt: bigint("created_at", { mode: "number" }).notNull(),
|
|
90
|
+
}, (t) => [index("latch_usage_owner_idx").on(t.owner)]);
|
|
91
|
+
/**
|
|
92
|
+
* Builder/editor-created agents (see `@intentface/latch-agent-builder`'s
|
|
93
|
+
* `AgentRecord`). Owner-keyed for org/personal scope; config isn't secret.
|
|
94
|
+
*/
|
|
95
|
+
export const agents = pgTable("latch_agents", {
|
|
96
|
+
id: text("id").primaryKey(),
|
|
97
|
+
/** Opaque ownership key derived from (principal, scope). */
|
|
98
|
+
owner: text("owner").notNull(),
|
|
99
|
+
name: text("name").notNull(),
|
|
100
|
+
title: text("title"),
|
|
101
|
+
description: text("description"),
|
|
102
|
+
modelId: text("model_id").notNull(),
|
|
103
|
+
instructions: text("instructions").notNull(),
|
|
104
|
+
/** string[] — connection names. */
|
|
105
|
+
connections: jsonb("connections").notNull(),
|
|
106
|
+
/** AgentRecord["tools"] — per-tool selection/approval overrides. */
|
|
107
|
+
tools: jsonb("tools"),
|
|
108
|
+
/** AgentRecord["exec"] — code-execution capabilities. */
|
|
109
|
+
exec: jsonb("exec"),
|
|
110
|
+
/** string[] — delegate agent names. */
|
|
111
|
+
subagents: jsonb("subagents"),
|
|
112
|
+
/** AgentRecord["attachedEvals"] — online judge rubrics (host eval feature). */
|
|
113
|
+
attachedEvals: jsonb("attached_evals"),
|
|
114
|
+
/** NULL=default, 0=unlimited, N=cap (AgentRecord["maxSteps"]). */
|
|
115
|
+
maxSteps: integer("max_steps"),
|
|
116
|
+
scope: text("scope").notNull(),
|
|
117
|
+
createdAt: bigint("created_at", { mode: "number" }).notNull(),
|
|
118
|
+
updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
|
|
119
|
+
}, (t) => [uniqueIndex("latch_agents_owner_name").on(t.owner, t.name)]);
|
|
120
|
+
/** Memory-sweep state per chat — see the SQLite schema for semantics. */
|
|
121
|
+
export const memoryChatState = pgTable("latch_memory_chat_state", {
|
|
122
|
+
chatId: text("chat_id").primaryKey(),
|
|
123
|
+
owner: text("owner").notNull(),
|
|
124
|
+
agent: text("agent").notNull(),
|
|
125
|
+
scopeKey: text("scope_key").notNull(),
|
|
126
|
+
lastExtractedSeq: integer("last_extracted_seq").notNull().default(-1),
|
|
127
|
+
/** Idempotency key of the last COMPLETED run (content hash + prompt version). */
|
|
128
|
+
lastExtractedKey: text("last_extracted_key"),
|
|
129
|
+
nextEligibleAt: bigint("next_eligible_at", { mode: "number" }).notNull().default(0),
|
|
130
|
+
failures: integer("failures").notNull().default(0),
|
|
131
|
+
leaseOwner: text("lease_owner"),
|
|
132
|
+
leaseExpiresAt: bigint("lease_expires_at", { mode: "number" }),
|
|
133
|
+
createdAt: bigint("created_at", { mode: "number" }).notNull(),
|
|
134
|
+
updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
|
|
135
|
+
}, (t) => [index("latch_memory_chat_state_scope_idx").on(t.scopeKey)]);
|
|
136
|
+
/** Memory-sweep state per scope — see the SQLite schema for semantics. */
|
|
137
|
+
export const memoryScopeState = pgTable("latch_memory_scope_state", {
|
|
138
|
+
scopeKey: text("scope_key").primaryKey(),
|
|
139
|
+
owner: text("owner").notNull(),
|
|
140
|
+
agent: text("agent").notNull(),
|
|
141
|
+
connection: text("connection").notNull(),
|
|
142
|
+
identity: jsonb("identity"),
|
|
143
|
+
hasNew: integer("has_new").notNull().default(0),
|
|
144
|
+
pendingEpisodes: jsonb("pending_episodes"),
|
|
145
|
+
consolidationWatermark: text("consolidation_watermark"),
|
|
146
|
+
lastConsolidatedAt: bigint("last_consolidated_at", { mode: "number" }),
|
|
147
|
+
nextEligibleAt: bigint("next_eligible_at", { mode: "number" }).notNull().default(0),
|
|
148
|
+
failures: integer("failures").notNull().default(0),
|
|
149
|
+
leaseOwner: text("lease_owner"),
|
|
150
|
+
leaseExpiresAt: bigint("lease_expires_at", { mode: "number" }),
|
|
151
|
+
createdAt: bigint("created_at", { mode: "number" }).notNull(),
|
|
152
|
+
updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
|
|
153
|
+
}, (t) => [index("latch_memory_scope_due_idx").on(t.hasNew, t.nextEligibleAt)]);
|
|
154
|
+
/** Recall tracking — see the SQLite schema for semantics. */
|
|
155
|
+
export const memoryUsage = pgTable("latch_memory_usage", {
|
|
156
|
+
scopeKey: text("scope_key").notNull(),
|
|
157
|
+
memoryId: text("memory_id").notNull(),
|
|
158
|
+
usageCount: integer("usage_count").notNull().default(0),
|
|
159
|
+
lastUsedAt: bigint("last_used_at", { mode: "number" }),
|
|
160
|
+
createdAt: bigint("created_at", { mode: "number" }).notNull(),
|
|
161
|
+
}, (t) => [primaryKey({ columns: [t.scopeKey, t.memoryId] })]);
|
|
162
|
+
/** Limit counters: one row per (key, fixed window) — see `limits.ts` in core. */
|
|
163
|
+
export const limitCounters = pgTable("latch_limit_counters", {
|
|
164
|
+
key: text("key").notNull(),
|
|
165
|
+
windowStart: bigint("window_start", { mode: "number" }).notNull(),
|
|
166
|
+
windowMs: bigint("window_ms", { mode: "number" }).notNull(),
|
|
167
|
+
turns: integer("turns").notNull().default(0),
|
|
168
|
+
tokens: bigint("tokens", { mode: "number" }).notNull().default(0),
|
|
169
|
+
cost: doublePrecision("cost").notNull().default(0),
|
|
170
|
+
updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
|
|
171
|
+
}, (t) => [primaryKey({ columns: [t.key, t.windowStart, t.windowMs] })]);
|
|
172
|
+
/** Cron-driven agent runs. Carries the identity blob so a tick can rebuild the caller. */
|
|
173
|
+
export const schedules = pgTable("latch_schedules", {
|
|
174
|
+
id: text("id").primaryKey(),
|
|
175
|
+
owner: text("owner").notNull(),
|
|
176
|
+
agent: text("agent").notNull(),
|
|
177
|
+
identity: jsonb("identity"),
|
|
178
|
+
cron: text("cron"),
|
|
179
|
+
timezone: text("timezone"),
|
|
180
|
+
prompt: text("prompt").notNull(),
|
|
181
|
+
/** Host-interpreted delivery target (e.g. a channel), opaque to core. */
|
|
182
|
+
delivery: jsonb("delivery"),
|
|
183
|
+
nextRunAt: bigint("next_run_at", { mode: "number" }).notNull(),
|
|
184
|
+
lastRunAt: bigint("last_run_at", { mode: "number" }),
|
|
185
|
+
/** Parked-predecessor policy ('skip' | 'fire'); null = the default ('skip'). */
|
|
186
|
+
onParked: text("on_parked"),
|
|
187
|
+
/** Chat of the last default-path fire (see StorageAdapter.noteScheduleFire). */
|
|
188
|
+
lastChatId: text("last_chat_id"),
|
|
189
|
+
enabled: integer("enabled").notNull(),
|
|
190
|
+
leaseOwner: text("lease_owner"),
|
|
191
|
+
leaseExpiresAt: bigint("lease_expires_at", { mode: "number" }),
|
|
192
|
+
createdAt: bigint("created_at", { mode: "number" }).notNull(),
|
|
193
|
+
}, (t) => [
|
|
194
|
+
index("latch_schedules_owner_idx").on(t.owner),
|
|
195
|
+
index("latch_schedules_due_idx").on(t.enabled, t.nextRunAt),
|
|
196
|
+
]);
|
|
197
|
+
//# sourceMappingURL=schema.pg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.pg.js","sourceRoot":"","sources":["../src/schema.pg.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core";
|
|
2
|
+
import type { SecretStore } from "@intentface/latch-core";
|
|
3
|
+
import type { SharedSecretStoreOptions } from "./secret-store.shared.js";
|
|
4
|
+
export type SqliteSecretStoreOptions<P> = SharedSecretStoreOptions<P>;
|
|
5
|
+
/**
|
|
6
|
+
* A `SecretStore` on a Drizzle SQLite database — persists the Vault's opaque
|
|
7
|
+
* encrypted records. It never sees plaintext; encryption/decryption happens in
|
|
8
|
+
* `createVault`. The caller owns the connection (pass a `drizzle(...)`).
|
|
9
|
+
*/
|
|
10
|
+
export declare function createSqliteSecretStore<P>(db: BaseSQLiteDatabase<"sync" | "async", any, any>, opts: SqliteSecretStoreOptions<P>): SecretStore<P>;
|
|
11
|
+
//# sourceMappingURL=secret-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-store.d.ts","sourceRoot":"","sources":["../src/secret-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAG1D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEzE,MAAM,MAAM,wBAAwB,CAAC,CAAC,IAAI,wBAAwB,CAAC,CAAC,CAAC,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EACvC,EAAE,EAAE,kBAAkB,CAAC,MAAM,GAAG,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,EAClD,IAAI,EAAE,wBAAwB,CAAC,CAAC,CAAC,GAChC,WAAW,CAAC,CAAC,CAAC,CAEhB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as schema from "./schema.js";
|
|
2
|
+
import { makeSecretStore } from "./secret-store.shared.js";
|
|
3
|
+
/**
|
|
4
|
+
* A `SecretStore` on a Drizzle SQLite database — persists the Vault's opaque
|
|
5
|
+
* encrypted records. It never sees plaintext; encryption/decryption happens in
|
|
6
|
+
* `createVault`. The caller owns the connection (pass a `drizzle(...)`).
|
|
7
|
+
*/
|
|
8
|
+
export function createSqliteSecretStore(db, opts) {
|
|
9
|
+
return makeSecretStore(db, schema, opts);
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=secret-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-store.js","sourceRoot":"","sources":["../src/secret-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAK3D;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACrC,EAAkD,EAClD,IAAiC;IAEjC,OAAO,eAAe,CAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PgDatabase } from "drizzle-orm/pg-core";
|
|
2
|
+
import type { SecretStore } from "@intentface/latch-core";
|
|
3
|
+
import type { SqliteSecretStoreOptions } from "./secret-store.js";
|
|
4
|
+
/** A `SecretStore` on Postgres — same contract + logic as the SQLite store. */
|
|
5
|
+
export declare function createPostgresSecretStore<P>(db: PgDatabase<any, any, any>, opts: SqliteSecretStoreOptions<P>): SecretStore<P>;
|
|
6
|
+
//# sourceMappingURL=secret-store.pg.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-store.pg.d.ts","sourceRoot":"","sources":["../src/secret-store.pg.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAG1D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAElE,+EAA+E;AAC/E,wBAAgB,yBAAyB,CAAC,CAAC,EACzC,EAAE,EAAE,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAC7B,IAAI,EAAE,wBAAwB,CAAC,CAAC,CAAC,GAChC,WAAW,CAAC,CAAC,CAAC,CAEhB"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as schema from "./schema.pg.js";
|
|
2
|
+
import { makeSecretStore } from "./secret-store.shared.js";
|
|
3
|
+
/** A `SecretStore` on Postgres — same contract + logic as the SQLite store. */
|
|
4
|
+
export function createPostgresSecretStore(db, opts) {
|
|
5
|
+
return makeSecretStore(db, schema, opts);
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=secret-store.pg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-store.pg.js","sourceRoot":"","sources":["../src/secret-store.pg.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAG3D,+EAA+E;AAC/E,MAAM,UAAU,yBAAyB,CACvC,EAA6B,EAC7B,IAAiC;IAEjC,OAAO,eAAe,CAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { SecretStore } from "@intentface/latch-core";
|
|
2
|
+
/**
|
|
3
|
+
* Dialect-shared `SecretStore` implementation — persists the Vault's opaque
|
|
4
|
+
* encrypted records. It never sees plaintext; encryption/decryption happens in
|
|
5
|
+
* `createVault`. The SQLite and Postgres entry points pass their dialect's
|
|
6
|
+
* schema; nothing else differs.
|
|
7
|
+
*/
|
|
8
|
+
export interface SecretStoreSchema {
|
|
9
|
+
secrets: any;
|
|
10
|
+
}
|
|
11
|
+
export interface SharedSecretStoreOptions<P> {
|
|
12
|
+
/**
|
|
13
|
+
* Derive the ownership key for a principal — credential isolation boundary.
|
|
14
|
+
* Can differ from the storage adapter's `owner` (e.g. credentials shared at the
|
|
15
|
+
* tenant level while chats are per-user). Server-derived only.
|
|
16
|
+
*
|
|
17
|
+
* The optional `key` argument enables secret-class scoping: a store can place
|
|
18
|
+
* a secret in a different owner bucket based on its key (e.g. workspace-shared
|
|
19
|
+
* OAuth tokens vs. per-user API keys). `list()` has no key context and passes
|
|
20
|
+
* none, so the derivation must be stable for the enumerated bucket.
|
|
21
|
+
*/
|
|
22
|
+
owner: (principal: P, key?: string) => string[];
|
|
23
|
+
}
|
|
24
|
+
export declare function makeSecretStore<P>(db: any, s: SecretStoreSchema, opts: SharedSecretStoreOptions<P>): SecretStore<P>;
|
|
25
|
+
//# sourceMappingURL=secret-store.shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-store.shared.d.ts","sourceRoot":"","sources":["../src/secret-store.shared.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAgB,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAExE;;;;;GAKG;AAEH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,GAAG,CAAC;CACd;AAED,MAAM,WAAW,wBAAwB,CAAC,CAAC;IACzC;;;;;;;;;OASG;IACH,KAAK,EAAE,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;CACjD;AAcD,wBAAgB,eAAe,CAAC,CAAC,EAC/B,EAAE,EAAE,GAAG,EACP,CAAC,EAAE,iBAAiB,EACpB,IAAI,EAAE,wBAAwB,CAAC,CAAC,CAAC,GAChC,WAAW,CAAC,CAAC,CAAC,CA+DhB"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { eq } from "drizzle-orm";
|
|
2
|
+
/** Join an `owner` path into one composite key, segment-encoded so it's unambiguous. */
|
|
3
|
+
function ownerKeyOf(owner, principal, key) {
|
|
4
|
+
return owner(principal, key).map(encodeURIComponent).join("/");
|
|
5
|
+
}
|
|
6
|
+
/** Stable composite id from the ownership key + secret key. */
|
|
7
|
+
const secretId = (ownerKey, key) => `${ownerKey}:${key}`;
|
|
8
|
+
export function makeSecretStore(db, s, opts) {
|
|
9
|
+
const ownerKey = (p, key) => ownerKeyOf(opts.owner, p, key);
|
|
10
|
+
const rowToRecord = (r) => ({
|
|
11
|
+
key: r.key,
|
|
12
|
+
ciphertext: r.ciphertext,
|
|
13
|
+
iv: r.iv,
|
|
14
|
+
wrappedDek: r.wrappedDek,
|
|
15
|
+
dekIv: r.dekIv,
|
|
16
|
+
createdAt: r.createdAt,
|
|
17
|
+
updatedAt: r.updatedAt,
|
|
18
|
+
});
|
|
19
|
+
return {
|
|
20
|
+
async put(principal, r) {
|
|
21
|
+
const owner = ownerKey(principal, r.key);
|
|
22
|
+
await db
|
|
23
|
+
.insert(s.secrets)
|
|
24
|
+
.values({
|
|
25
|
+
id: secretId(owner, r.key),
|
|
26
|
+
owner,
|
|
27
|
+
key: r.key,
|
|
28
|
+
ciphertext: r.ciphertext,
|
|
29
|
+
iv: r.iv,
|
|
30
|
+
wrappedDek: r.wrappedDek,
|
|
31
|
+
dekIv: r.dekIv,
|
|
32
|
+
createdAt: r.createdAt,
|
|
33
|
+
updatedAt: r.updatedAt,
|
|
34
|
+
})
|
|
35
|
+
.onConflictDoUpdate({
|
|
36
|
+
target: s.secrets.id,
|
|
37
|
+
set: {
|
|
38
|
+
ciphertext: r.ciphertext,
|
|
39
|
+
iv: r.iv,
|
|
40
|
+
wrappedDek: r.wrappedDek,
|
|
41
|
+
dekIv: r.dekIv,
|
|
42
|
+
updatedAt: r.updatedAt,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
async get(principal, key) {
|
|
47
|
+
const rows = await db
|
|
48
|
+
.select()
|
|
49
|
+
.from(s.secrets)
|
|
50
|
+
.where(eq(s.secrets.id, secretId(ownerKey(principal, key), key)));
|
|
51
|
+
return rows[0] ? rowToRecord(rows[0]) : null;
|
|
52
|
+
},
|
|
53
|
+
async delete(principal, key) {
|
|
54
|
+
await db
|
|
55
|
+
.delete(s.secrets)
|
|
56
|
+
.where(eq(s.secrets.id, secretId(ownerKey(principal, key), key)));
|
|
57
|
+
},
|
|
58
|
+
async list(principal) {
|
|
59
|
+
const rows = await db
|
|
60
|
+
.select({ key: s.secrets.key })
|
|
61
|
+
.from(s.secrets)
|
|
62
|
+
.where(eq(s.secrets.owner, ownerKey(principal)));
|
|
63
|
+
return rows.map((r) => r.key);
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=secret-store.shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-store.shared.js","sourceRoot":"","sources":["../src/secret-store.shared.ts"],"names":[],"mappings":"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"}
|
package/dist/smoke.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smoke.d.ts","sourceRoot":"","sources":["../src/smoke.ts"],"names":[],"mappings":""}
|
package/dist/smoke.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { createClient } from "@libsql/client";
|
|
2
|
+
import { drizzle } from "drizzle-orm/libsql";
|
|
3
|
+
import { migrate } from "./migrate.js";
|
|
4
|
+
import { createSqliteAdapter } from "./adapter.js";
|
|
5
|
+
import { createMemoryJobStore } from "./memory-job-store.js";
|
|
6
|
+
import { memoryJobStoreSmoke } from "./memory-job-store.smoke.shared.js";
|
|
7
|
+
import { scheduleSmoke } from "./schedule.smoke.shared.js";
|
|
8
|
+
import { limitStoreSmoke } from "./limit-store.smoke.shared.js";
|
|
9
|
+
import { runLeaseSmoke } from "./run-lease.smoke.shared.js";
|
|
10
|
+
import { createSqliteLimitStore } from "./limit-store.js";
|
|
11
|
+
import * as schema from "./schema.js";
|
|
12
|
+
async function main() {
|
|
13
|
+
const client = createClient({ url: ":memory:" });
|
|
14
|
+
await migrate(client);
|
|
15
|
+
const db = drizzle(client, { schema });
|
|
16
|
+
const store = createSqliteAdapter(db, {
|
|
17
|
+
owner: (p) => (p.user ? [p.org, p.user] : [p.org]),
|
|
18
|
+
});
|
|
19
|
+
const me = { org: "org_a", user: "user_1" };
|
|
20
|
+
const chat = await store.createChat(me, { agent: "support" });
|
|
21
|
+
const userMsg = {
|
|
22
|
+
id: "msg_1",
|
|
23
|
+
role: "user",
|
|
24
|
+
parts: [{ type: "text", text: "hello" }],
|
|
25
|
+
metadata: { visibility: "user", createdAt: Date.now() },
|
|
26
|
+
};
|
|
27
|
+
const asstMsg = {
|
|
28
|
+
id: "msg_2",
|
|
29
|
+
role: "assistant",
|
|
30
|
+
parts: [{ type: "text", text: "hi!" }],
|
|
31
|
+
metadata: {
|
|
32
|
+
visibility: "user",
|
|
33
|
+
model: "mock",
|
|
34
|
+
usage: { inputTokens: 5, outputTokens: 3 },
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
await store.appendMessages(chat.id, [userMsg, asstMsg]);
|
|
38
|
+
const loaded = await store.loadMessages(me, chat.id);
|
|
39
|
+
assert(loaded.length === 2, "loads 2 messages");
|
|
40
|
+
assert(loaded[0].id === "msg_1" && loaded[1].id === "msg_2", "ordered by seq");
|
|
41
|
+
assert(loaded[1].parts[0].text === "hi!", "parts round-trip through JSON");
|
|
42
|
+
// Owner isolation: a different tenant cannot read org_a's chat.
|
|
43
|
+
const otherOrg = await store.loadMessages({ org: "org_b" }, chat.id);
|
|
44
|
+
assert(otherOrg.length === 0, "owner isolation (org_b sees nothing)");
|
|
45
|
+
// Run + identity + usage.
|
|
46
|
+
const run = await store.createRun(me, { chatId: chat.id, agent: "support", kind: "turn" });
|
|
47
|
+
assert(JSON.stringify(run.identity) === JSON.stringify(me), "run stores the identity blob (for resume)");
|
|
48
|
+
await store.updateRun(run.id, {
|
|
49
|
+
status: "completed",
|
|
50
|
+
usageInputTokens: 5,
|
|
51
|
+
usageOutputTokens: 3,
|
|
52
|
+
toolsHash: "cafebabecafebabe",
|
|
53
|
+
endedAt: Date.now(),
|
|
54
|
+
});
|
|
55
|
+
await store.recordUsage(me, {
|
|
56
|
+
runId: run.id,
|
|
57
|
+
model: "mock",
|
|
58
|
+
inputTokens: 5,
|
|
59
|
+
outputTokens: 3,
|
|
60
|
+
cacheReadTokens: 2,
|
|
61
|
+
cacheWriteTokens: 1,
|
|
62
|
+
cost: 0.0001,
|
|
63
|
+
});
|
|
64
|
+
const gotRun = await store.getRun(run.id);
|
|
65
|
+
assert(gotRun?.status === "completed", "run updated to completed");
|
|
66
|
+
assert(gotRun?.kind === "turn", "run kind persisted");
|
|
67
|
+
assert(gotRun?.toolsHash === "cafebabecafebabe", "run toolsHash persisted");
|
|
68
|
+
// listChats projects the LATEST run's status onto each chat (lastRunStatus).
|
|
69
|
+
const listed = await store.listChats(me);
|
|
70
|
+
assert(listed[0]?.lastRunStatus === "completed", "listChats projects the latest run's status");
|
|
71
|
+
// A strictly later startedAt — "latest" must not tie with the first run.
|
|
72
|
+
await new Promise((r) => setTimeout(r, 2));
|
|
73
|
+
const parked = await store.createRun(me, { chatId: chat.id, agent: "support", kind: "turn" });
|
|
74
|
+
await store.updateRun(parked.id, { status: "awaiting_input" });
|
|
75
|
+
const listedParked = await store.listChats(me);
|
|
76
|
+
assert(listedParked[0]?.lastRunStatus === "awaiting_input", "a parked latest run surfaces awaiting_input on the chat list");
|
|
77
|
+
// Equal startedAt (ms precision can tie): the id-desc tie-break must pick
|
|
78
|
+
// the same row on every read and on both dialects.
|
|
79
|
+
const tieAt = Date.now() + 60_000;
|
|
80
|
+
await db.insert(schema.runs).values([
|
|
81
|
+
{ id: "run_tie_a", chatId: chat.id, agent: "support", status: "completed", startedAt: tieAt },
|
|
82
|
+
{ id: "run_tie_b", chatId: chat.id, agent: "support", status: "errored", startedAt: tieAt },
|
|
83
|
+
]);
|
|
84
|
+
const listedTied = await store.listChats(me);
|
|
85
|
+
assert(listedTied[0]?.lastRunStatus === "errored", "started_at ties break deterministically by id desc");
|
|
86
|
+
// Schedules: the opaque delivery blob and the owner-fenced "run now" bump.
|
|
87
|
+
await scheduleSmoke({ store, me, other: { org: "org_b", user: "user_2" }, assert });
|
|
88
|
+
// Memory job store: extraction/consolidation state machine + usage.
|
|
89
|
+
await runLeaseSmoke({ store, principal: me, assert });
|
|
90
|
+
await limitStoreSmoke({ limits: createSqliteLimitStore(db), assert });
|
|
91
|
+
await memoryJobStoreSmoke({
|
|
92
|
+
jobs: createMemoryJobStore(db),
|
|
93
|
+
store,
|
|
94
|
+
principal: me,
|
|
95
|
+
assert,
|
|
96
|
+
});
|
|
97
|
+
console.log("✅ smoke passed — persistence + owner isolation + run/identity/usage + memory jobs all work");
|
|
98
|
+
}
|
|
99
|
+
function assert(cond, msg) {
|
|
100
|
+
if (!cond)
|
|
101
|
+
throw new Error(`assertion failed: ${msg}`);
|
|
102
|
+
console.log(` ✓ ${msg}`);
|
|
103
|
+
}
|
|
104
|
+
main().catch((e) => {
|
|
105
|
+
console.error("❌ smoke failed:", e);
|
|
106
|
+
throw e; // unhandled rejection → non-zero exit
|
|
107
|
+
});
|
|
108
|
+
//# sourceMappingURL=smoke.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smoke.js","sourceRoot":"","sources":["../src/smoke.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smoke.pg.d.ts","sourceRoot":"","sources":["../src/smoke.pg.ts"],"names":[],"mappings":""}
|
package/dist/smoke.pg.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { PGlite } from "@electric-sql/pglite";
|
|
2
|
+
import { drizzle } from "drizzle-orm/pglite";
|
|
3
|
+
import { migratePostgres } from "./migrate.pg.js";
|
|
4
|
+
import { createPostgresAdapter } from "./adapter.pg.js";
|
|
5
|
+
import { createPostgresMemoryJobStore } from "./memory-job-store.pg.js";
|
|
6
|
+
import { memoryJobStoreSmoke } from "./memory-job-store.smoke.shared.js";
|
|
7
|
+
import { scheduleSmoke } from "./schedule.smoke.shared.js";
|
|
8
|
+
import { limitStoreSmoke } from "./limit-store.smoke.shared.js";
|
|
9
|
+
import { runLeaseSmoke } from "./run-lease.smoke.shared.js";
|
|
10
|
+
import { createPostgresLimitStore } from "./limit-store.pg.js";
|
|
11
|
+
import * as schema from "./schema.pg.js";
|
|
12
|
+
async function main() {
|
|
13
|
+
const pg = new PGlite();
|
|
14
|
+
const db = drizzle(pg, { schema });
|
|
15
|
+
await migratePostgres(db);
|
|
16
|
+
const store = createPostgresAdapter(db, {
|
|
17
|
+
owner: (p) => (p.user ? [p.org, p.user] : [p.org]),
|
|
18
|
+
});
|
|
19
|
+
const me = { org: "org_a", user: "user_1" };
|
|
20
|
+
const chat = await store.createChat(me, { agent: "support" });
|
|
21
|
+
const userMsg = {
|
|
22
|
+
id: "msg_1",
|
|
23
|
+
role: "user",
|
|
24
|
+
parts: [{ type: "text", text: "hello" }],
|
|
25
|
+
metadata: { visibility: "user", createdAt: Date.now() },
|
|
26
|
+
};
|
|
27
|
+
const asstMsg = {
|
|
28
|
+
id: "msg_2",
|
|
29
|
+
role: "assistant",
|
|
30
|
+
parts: [{ type: "text", text: "hi!" }],
|
|
31
|
+
metadata: {
|
|
32
|
+
visibility: "user",
|
|
33
|
+
model: "mock",
|
|
34
|
+
usage: { inputTokens: 5, outputTokens: 3 },
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
await store.appendMessages(chat.id, [userMsg, asstMsg]);
|
|
38
|
+
const loaded = await store.loadMessages(me, chat.id);
|
|
39
|
+
assert(loaded.length === 2, "loads 2 messages");
|
|
40
|
+
assert(loaded[0].id === "msg_1" && loaded[1].id === "msg_2", "ordered by seq");
|
|
41
|
+
assert(loaded[1].parts[0].text === "hi!", "parts round-trip through jsonb");
|
|
42
|
+
const otherOrg = await store.loadMessages({ org: "org_b" }, chat.id);
|
|
43
|
+
assert(otherOrg.length === 0, "owner isolation (org_b sees nothing)");
|
|
44
|
+
const run = await store.createRun(me, { chatId: chat.id, agent: "support", kind: "turn" });
|
|
45
|
+
await store.updateRun(run.id, {
|
|
46
|
+
status: "completed",
|
|
47
|
+
usageInputTokens: 5,
|
|
48
|
+
usageOutputTokens: 3,
|
|
49
|
+
toolsHash: "cafebabecafebabe",
|
|
50
|
+
endedAt: Date.now(),
|
|
51
|
+
});
|
|
52
|
+
await store.recordUsage(me, {
|
|
53
|
+
runId: run.id,
|
|
54
|
+
model: "mock",
|
|
55
|
+
inputTokens: 5,
|
|
56
|
+
outputTokens: 3,
|
|
57
|
+
cacheReadTokens: 2,
|
|
58
|
+
cacheWriteTokens: 1,
|
|
59
|
+
cost: 0.0001,
|
|
60
|
+
});
|
|
61
|
+
const gotRun = await store.getRun(run.id);
|
|
62
|
+
assert(gotRun?.status === "completed", "run updated to completed");
|
|
63
|
+
assert(gotRun?.kind === "turn", "run kind persisted");
|
|
64
|
+
assert(gotRun?.toolsHash === "cafebabecafebabe", "run toolsHash persisted");
|
|
65
|
+
// listChats projects the LATEST run's status onto each chat (lastRunStatus).
|
|
66
|
+
const listed = await store.listChats(me);
|
|
67
|
+
assert(listed[0]?.lastRunStatus === "completed", "listChats projects the latest run's status");
|
|
68
|
+
// A strictly later startedAt — "latest" must not tie with the first run.
|
|
69
|
+
await new Promise((r) => setTimeout(r, 2));
|
|
70
|
+
const parked = await store.createRun(me, { chatId: chat.id, agent: "support", kind: "turn" });
|
|
71
|
+
await store.updateRun(parked.id, { status: "awaiting_input" });
|
|
72
|
+
const listedParked = await store.listChats(me);
|
|
73
|
+
assert(listedParked[0]?.lastRunStatus === "awaiting_input", "a parked latest run surfaces awaiting_input on the chat list");
|
|
74
|
+
// Equal startedAt (ms precision can tie): the id-desc tie-break must pick
|
|
75
|
+
// the same row on every read and on both dialects.
|
|
76
|
+
const tieAt = Date.now() + 60_000;
|
|
77
|
+
await db.insert(schema.runs).values([
|
|
78
|
+
{ id: "run_tie_a", chatId: chat.id, agent: "support", status: "completed", startedAt: tieAt },
|
|
79
|
+
{ id: "run_tie_b", chatId: chat.id, agent: "support", status: "errored", startedAt: tieAt },
|
|
80
|
+
]);
|
|
81
|
+
const listedTied = await store.listChats(me);
|
|
82
|
+
assert(listedTied[0]?.lastRunStatus === "errored", "started_at ties break deterministically by id desc");
|
|
83
|
+
// Schedules: the opaque delivery blob and the owner-fenced "run now" bump.
|
|
84
|
+
// Worth running on BOTH dialects — `delivery` is jsonb here and json-in-text
|
|
85
|
+
// on sqlite, so a round trip is the only proof they agree.
|
|
86
|
+
await scheduleSmoke({ store, me, other: { org: "org_b", user: "user_2" }, assert });
|
|
87
|
+
// Memory job store: extraction/consolidation state machine + usage.
|
|
88
|
+
await runLeaseSmoke({ store, principal: me, assert });
|
|
89
|
+
await limitStoreSmoke({ limits: createPostgresLimitStore(db), assert });
|
|
90
|
+
await memoryJobStoreSmoke({
|
|
91
|
+
jobs: createPostgresMemoryJobStore(db),
|
|
92
|
+
store,
|
|
93
|
+
principal: me,
|
|
94
|
+
assert,
|
|
95
|
+
});
|
|
96
|
+
console.log("✅ pg smoke passed — same StorageAdapter, Postgres dialect (PGlite)");
|
|
97
|
+
}
|
|
98
|
+
function assert(cond, msg) {
|
|
99
|
+
if (!cond)
|
|
100
|
+
throw new Error(`assertion failed: ${msg}`);
|
|
101
|
+
console.log(` ✓ ${msg}`);
|
|
102
|
+
}
|
|
103
|
+
main().catch((e) => {
|
|
104
|
+
console.error("❌ pg smoke failed:", e);
|
|
105
|
+
throw e;
|
|
106
|
+
});
|
|
107
|
+
//# sourceMappingURL=smoke.pg.js.map
|