@creatornader/agent-bridge 0.2.0 → 0.3.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 (115) hide show
  1. package/CHANGELOG.md +86 -4
  2. package/README.md +567 -55
  3. package/ROADMAP.md +114 -0
  4. package/SECURITY.md +90 -0
  5. package/SKILL.md +68 -2
  6. package/bin/agent-bridge +2 -2
  7. package/clients/claude-desktop.json +3 -1
  8. package/dist/archive.d.ts +163 -0
  9. package/dist/archive.js +50 -0
  10. package/dist/archive.js.map +1 -0
  11. package/dist/bridge-domain-CBX3IVqC.d.ts +153 -0
  12. package/dist/{bridge-service-CfqMcMAn.d.ts → bridge-service-hX1ZQp4W.d.ts} +15 -5
  13. package/dist/bridge-store-DPVSCwfs.d.ts +102 -0
  14. package/dist/bridge.d.ts +76 -17
  15. package/dist/bridge.js +52 -24
  16. package/dist/chunk-2DFNOLMO.js +618 -0
  17. package/dist/chunk-2DFNOLMO.js.map +1 -0
  18. package/dist/{chunk-KVR4JBRF.js → chunk-2EVLG3YA.js} +2 -2
  19. package/dist/{chunk-KVR4JBRF.js.map → chunk-2EVLG3YA.js.map} +1 -1
  20. package/dist/chunk-45BZGB77.js +709 -0
  21. package/dist/chunk-45BZGB77.js.map +1 -0
  22. package/dist/chunk-4VB44KJU.js +230 -0
  23. package/dist/chunk-4VB44KJU.js.map +1 -0
  24. package/dist/chunk-5GMB3A77.js +1013 -0
  25. package/dist/chunk-5GMB3A77.js.map +1 -0
  26. package/dist/chunk-A6W4QALF.js +1258 -0
  27. package/dist/chunk-A6W4QALF.js.map +1 -0
  28. package/dist/chunk-BZLMF5O5.js +328 -0
  29. package/dist/chunk-BZLMF5O5.js.map +1 -0
  30. package/dist/{chunk-AXL2I7FH.js → chunk-CEXBMOI5.js} +240 -79
  31. package/dist/chunk-CEXBMOI5.js.map +1 -0
  32. package/dist/chunk-GADH244D.js +527 -0
  33. package/dist/chunk-GADH244D.js.map +1 -0
  34. package/dist/chunk-MBPZXTJA.js +2428 -0
  35. package/dist/chunk-MBPZXTJA.js.map +1 -0
  36. package/dist/chunk-NCO7RLBM.js +146 -0
  37. package/dist/chunk-NCO7RLBM.js.map +1 -0
  38. package/dist/chunk-Q6PPMXJC.js +1050 -0
  39. package/dist/chunk-Q6PPMXJC.js.map +1 -0
  40. package/dist/{chunk-4KAOBC5X.js → chunk-SPSMZOCJ.js} +190 -165
  41. package/dist/chunk-SPSMZOCJ.js.map +1 -0
  42. package/dist/chunk-UAHMP6GC.js +54 -0
  43. package/dist/chunk-UAHMP6GC.js.map +1 -0
  44. package/dist/{chunk-YD6YJATN.js → chunk-VOQIDTCJ.js} +4 -2
  45. package/dist/chunk-VOQIDTCJ.js.map +1 -0
  46. package/dist/chunk-WAI2IYIQ.js +554 -0
  47. package/dist/chunk-WAI2IYIQ.js.map +1 -0
  48. package/dist/cli.d.ts +2 -1
  49. package/dist/cli.js +3555 -214
  50. package/dist/cli.js.map +1 -1
  51. package/dist/client-config.d.ts +1 -1
  52. package/dist/client-config.js +1 -1
  53. package/dist/client-runtime.d.ts +10 -6
  54. package/dist/client-runtime.js +9 -6
  55. package/dist/contracts/generate.d.ts +2 -0
  56. package/dist/contracts/generate.js +247 -0
  57. package/dist/contracts/generate.js.map +1 -0
  58. package/dist/dr.d.ts +324 -0
  59. package/dist/dr.js +124 -0
  60. package/dist/dr.js.map +1 -0
  61. package/dist/gateway-CggQ8vTC.d.ts +78 -0
  62. package/dist/gateway-main.js +190 -8
  63. package/dist/gateway-main.js.map +1 -1
  64. package/dist/gateway.d.ts +4 -3
  65. package/dist/gateway.js +4 -3
  66. package/dist/index.js +11 -8
  67. package/dist/index.js.map +1 -1
  68. package/dist/postgres-bridge-store-Bfd3hRId.d.ts +49 -0
  69. package/dist/server.d.ts +3 -2
  70. package/dist/server.js +13 -8
  71. package/dist/sqlite.d.ts +94 -12
  72. package/dist/sqlite.js +7 -4
  73. package/docs/architecture-v2.md +394 -0
  74. package/docs/decisions/0001-protocol-layers-and-acknowledgment-semantics.md +85 -0
  75. package/docs/decisions/0002-canonical-operation-contract-registry.md +46 -0
  76. package/docs/decisions/0003-host-adapters-and-consumer-instance-keys.md +88 -0
  77. package/docs/ecosystem.md +86 -0
  78. package/docs/postmortems/2026-07-08-wrapper-source-drift.md +82 -0
  79. package/docs/troubleshooting.md +89 -0
  80. package/llms.txt +107 -6
  81. package/openapi/agent-bridge-v2.openapi.json +9610 -0
  82. package/package.json +24 -4
  83. package/schemas/agent-bridge-v2.capabilities.json +1829 -0
  84. package/schemas/agent-bridge-v2.mcp.json +2074 -0
  85. package/schemas/agent-bridge-v2.schema.json +4560 -0
  86. package/sql/migrations/008_message_projects.sql +36 -0
  87. package/sql/migrations/009_mailbox_query_indexes.sql +28 -0
  88. package/sql/migrations/010_publisher_delivery_policy.sql +210 -0
  89. package/sql/migrations/011_credential_security.sql +875 -0
  90. package/sql/migrations/012_request_authority.sql +177 -0
  91. package/sql/migrations/013_row_isolation.sql +495 -0
  92. package/sql/migrations/014_owner_control_plane.sql +1641 -0
  93. package/sql/migrations/015_portable_archives.sql +1813 -0
  94. package/sql/migrations/016_native_dr_fence.sql +1005 -0
  95. package/bin/CLAUDE.md +0 -11
  96. package/dist/bridge-domain-BcnBeHOn.d.ts +0 -97
  97. package/dist/bridge-store-BuGjxTn4.d.ts +0 -61
  98. package/dist/chunk-4KAOBC5X.js.map +0 -1
  99. package/dist/chunk-6MAZ6YLZ.js +0 -146
  100. package/dist/chunk-6MAZ6YLZ.js.map +0 -1
  101. package/dist/chunk-AXL2I7FH.js.map +0 -1
  102. package/dist/chunk-BV6W4AJK.js +0 -211
  103. package/dist/chunk-BV6W4AJK.js.map +0 -1
  104. package/dist/chunk-CKSKUBDQ.js +0 -153
  105. package/dist/chunk-CKSKUBDQ.js.map +0 -1
  106. package/dist/chunk-JOUBDRYX.js +0 -272
  107. package/dist/chunk-JOUBDRYX.js.map +0 -1
  108. package/dist/chunk-JTC5YURG.js +0 -49
  109. package/dist/chunk-JTC5YURG.js.map +0 -1
  110. package/dist/chunk-O26W5QHS.js +0 -409
  111. package/dist/chunk-O26W5QHS.js.map +0 -1
  112. package/dist/chunk-WEULPMUY.js +0 -988
  113. package/dist/chunk-WEULPMUY.js.map +0 -1
  114. package/dist/chunk-YD6YJATN.js.map +0 -1
  115. package/dist/gateway-BULozv3K.d.ts +0 -54
@@ -1,409 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- assertIdempotentReplay
4
- } from "./chunk-YD6YJATN.js";
5
- import {
6
- decodeCursor,
7
- encodeCursor
8
- } from "./chunk-BV6W4AJK.js";
9
-
10
- // src/postgres-bridge-store.ts
11
- import { randomUUID } from "crypto";
12
- function json(value) {
13
- return value === void 0 ? null : JSON.stringify(value);
14
- }
15
- function parse(value) {
16
- return typeof value === "string" ? JSON.parse(value) : value;
17
- }
18
- function asTimestamp(value) {
19
- if (value === void 0 || value === null) return void 0;
20
- if (value instanceof Date) return value.toISOString();
21
- return String(value);
22
- }
23
- function asMessage(row) {
24
- return {
25
- id: String(row.id),
26
- workspace: String(row.workspace),
27
- source: String(row.source),
28
- sequence: String(row.sequence),
29
- type: String(row.type),
30
- content: String(row.content),
31
- contentType: String(row.content_type),
32
- data: parse(row.data),
33
- targets: parse(row.targets) ?? [],
34
- threadId: row.thread_id ?? void 0,
35
- replyToId: row.reply_to_id ?? void 0,
36
- correlationId: row.correlation_id ?? void 0,
37
- causationId: row.causation_id ?? void 0,
38
- priority: row.priority,
39
- expiresAt: asTimestamp(row.expires_at),
40
- idempotencyKey: row.idempotency_key ?? void 0,
41
- atribReceiptId: row.atrib_receipt_id ?? void 0,
42
- informedBy: parse(row.informed_by),
43
- metadata: parse(row.metadata),
44
- createdAt: asTimestamp(row.created_at) ?? ""
45
- };
46
- }
47
- function asDelivery(row) {
48
- return {
49
- id: String(row.id),
50
- messageId: String(row.message_id),
51
- workspace: String(row.workspace),
52
- recipient: String(row.recipient),
53
- state: row.state,
54
- attempt: Number(row.attempt),
55
- availableAt: asTimestamp(row.available_at) ?? "",
56
- leaseToken: row.lease_token ?? void 0,
57
- leaseOwner: row.lease_owner ?? void 0,
58
- leaseExpiresAt: asTimestamp(row.lease_expires_at),
59
- lastError: row.last_error ?? void 0
60
- };
61
- }
62
- function asPresence(row) {
63
- return {
64
- workspace: String(row.workspace),
65
- agent: String(row.agent),
66
- instance: String(row.instance),
67
- runtimeType: row.runtime_type ?? void 0,
68
- capabilities: parse(row.capabilities) ?? [],
69
- leaseExpiresAt: asTimestamp(row.lease_expires_at) ?? "",
70
- lastSeenAt: asTimestamp(row.last_seen_at) ?? ""
71
- };
72
- }
73
- function asDeliveryEvent(row) {
74
- return {
75
- sequence: String(row.sequence),
76
- deliveryId: String(row.delivery_id),
77
- messageId: String(row.message_id),
78
- workspace: String(row.workspace),
79
- recipient: String(row.recipient),
80
- fromState: row.from_state,
81
- toState: row.to_state,
82
- attempt: Number(row.attempt),
83
- leaseOwner: row.lease_owner ?? void 0,
84
- error: row.error ?? void 0,
85
- createdAt: asTimestamp(row.created_at) ?? ""
86
- };
87
- }
88
- var PostgresBridgeStore = class {
89
- constructor(db) {
90
- this.db = db;
91
- }
92
- async initialize() {
93
- }
94
- async insertMessage(input) {
95
- const values = [
96
- input.id,
97
- input.workspace,
98
- input.source,
99
- input.type,
100
- input.content,
101
- input.contentType,
102
- json(input.data),
103
- json(input.targets),
104
- input.threadId ?? null,
105
- input.replyToId ?? null,
106
- input.correlationId ?? null,
107
- input.causationId ?? null,
108
- input.priority,
109
- input.expiresAt ?? null,
110
- input.idempotencyKey ?? null,
111
- input.atribReceiptId ?? null,
112
- json(input.informedBy),
113
- json(input.metadata)
114
- ];
115
- const result = await this.db.query(
116
- `WITH inserted AS (
117
- INSERT INTO agent_bridge.messages (
118
- id, workspace, source, type, content, content_type, data, targets,
119
- thread_id, reply_to_id, correlation_id, causation_id, priority,
120
- expires_at, idempotency_key, atrib_receipt_id, informed_by, metadata
121
- )
122
- VALUES (
123
- $1, $2, $3, $4, $5, $6, $7::jsonb, $8::jsonb,
124
- $9, $10, $11, $12, $13, $14, $15, $16, $17::jsonb, $18::jsonb
125
- )
126
- ON CONFLICT (workspace, source, idempotency_key)
127
- WHERE idempotency_key IS NOT NULL
128
- DO NOTHING
129
- RETURNING *, true AS created
130
- ), selected AS (
131
- SELECT * FROM inserted
132
- UNION ALL
133
- SELECT existing.*, false AS created
134
- FROM agent_bridge.messages existing
135
- WHERE $15::text IS NOT NULL
136
- AND existing.workspace = $2
137
- AND existing.source = $3
138
- AND existing.idempotency_key = $15
139
- AND NOT EXISTS (SELECT 1 FROM inserted)
140
- LIMIT 1
141
- ), delivery_rows AS (
142
- INSERT INTO agent_bridge.deliveries (
143
- id, message_id, workspace, recipient, state, available_at
144
- )
145
- SELECT gen_random_uuid(), inserted.id, inserted.workspace, target, 'pending', now()
146
- FROM inserted
147
- CROSS JOIN LATERAL jsonb_array_elements_text(inserted.targets) AS target
148
- ON CONFLICT (message_id, recipient) DO NOTHING
149
- )
150
- SELECT * FROM selected`,
151
- values
152
- );
153
- let row = result.rows[0];
154
- if (!row && input.idempotencyKey) {
155
- const existing = await this.db.query(
156
- `SELECT *, false AS created
157
- FROM agent_bridge.messages
158
- WHERE workspace=$1 AND source=$2 AND idempotency_key=$3`,
159
- [input.workspace, input.source, input.idempotencyKey]
160
- );
161
- row = existing.rows[0];
162
- }
163
- if (!row) throw new Error("message insert did not return a row");
164
- const message = asMessage(row);
165
- if (row.created !== true) assertIdempotentReplay(message, input);
166
- return { message, created: row.created === true };
167
- }
168
- async listMessages(principal, query = {}) {
169
- const cursor = decodeCursor(query.cursor) ?? "0";
170
- const limit = Math.min(Math.max(Math.trunc(query.limit ?? 50), 1), 200);
171
- const boundary = query.latest ? void 0 : await this.db.query(
172
- "SELECT max(sequence)::text AS sequence FROM agent_bridge.messages WHERE workspace=$1",
173
- [principal.workspace]
174
- );
175
- const highWater = boundary?.rows[0]?.sequence;
176
- const values = query.latest ? [principal.workspace, principal.agent] : [principal.workspace, cursor, principal.agent];
177
- let sql = `SELECT * FROM agent_bridge.messages WHERE workspace=$1 ${query.latest ? "" : "AND sequence>$2::bigint "}AND (targets='[]'::jsonb OR targets ? $${query.latest ? 2 : 3})`;
178
- if (highWater) {
179
- values.push(highWater);
180
- sql += ` AND sequence <= $${values.length}::bigint`;
181
- }
182
- if (!query.includeExpired) {
183
- sql += " AND (expires_at IS NULL OR expires_at > now())";
184
- }
185
- if (query.types?.length) {
186
- values.push(query.types);
187
- sql += ` AND type = ANY($${values.length})`;
188
- }
189
- if (query.source) {
190
- values.push(query.source);
191
- sql += ` AND source = $${values.length}`;
192
- }
193
- if (query.since) {
194
- values.push(query.since);
195
- sql += ` AND created_at >= $${values.length}::timestamptz`;
196
- }
197
- if (query.unacknowledgedBy) {
198
- values.push(query.unacknowledgedBy);
199
- sql += ` AND NOT EXISTS (
200
- SELECT 1 FROM agent_bridge.receipts receipt
201
- WHERE receipt.workspace=agent_bridge.messages.workspace
202
- AND receipt.message_id=agent_bridge.messages.id
203
- AND receipt.principal=$${values.length}
204
- )`;
205
- }
206
- if (query.threadId) {
207
- values.push(query.threadId);
208
- sql += ` AND thread_id = $${values.length}`;
209
- }
210
- values.push(limit);
211
- const result = await this.db.query(
212
- `${sql} ORDER BY sequence ${query.latest ? "DESC" : "ASC"} LIMIT $${values.length}`,
213
- values
214
- );
215
- const messages = result.rows.map(asMessage);
216
- const last = messages[messages.length - 1];
217
- if (query.latest) return { messages, cursor: messages[0] ? encodeCursor(messages[0].sequence) : query.cursor };
218
- if (messages.length === limit) return { messages, cursor: encodeCursor(last.sequence) };
219
- return { messages, cursor: highWater ? encodeCursor(highWater) : query.cursor };
220
- }
221
- async recordReceipt(workspace, ids, principal, readAt = /* @__PURE__ */ new Date()) {
222
- const result = await this.db.query(
223
- `INSERT INTO agent_bridge.receipts (workspace, message_id, principal, read_at)
224
- SELECT message.workspace, message.id, $3, $4
225
- FROM agent_bridge.messages message
226
- WHERE message.workspace = $1 AND message.id = ANY($2::uuid[])
227
- AND (message.targets='[]'::jsonb OR message.targets ? $3)
228
- ON CONFLICT DO NOTHING`,
229
- [workspace, ids, principal, readAt]
230
- );
231
- return result.rowCount ?? 0;
232
- }
233
- async claimDelivery(principal, options) {
234
- const owner = principal.instance ?? principal.agent;
235
- const token = randomUUID();
236
- const result = await this.db.query(
237
- `WITH expired AS (
238
- UPDATE agent_bridge.deliveries delivery
239
- SET state='dead', last_error='message expired', lease_token=NULL,
240
- lease_owner=NULL, lease_expires_at=NULL
241
- FROM agent_bridge.messages message
242
- WHERE delivery.workspace=$1 AND delivery.recipient=$2
243
- AND delivery.state IN ('pending', 'retrying', 'claimed')
244
- AND message.workspace=delivery.workspace AND message.id=delivery.message_id
245
- AND message.expires_at IS NOT NULL AND message.expires_at <= now()
246
- RETURNING delivery.id
247
- ), exhausted AS (
248
- UPDATE agent_bridge.deliveries delivery
249
- SET state='dead', last_error='maximum attempts reached', lease_token=NULL,
250
- lease_owner=NULL, lease_expires_at=NULL
251
- WHERE delivery.workspace=$1 AND delivery.recipient=$2 AND delivery.attempt >= $6
252
- AND (
253
- delivery.state IN ('pending', 'retrying')
254
- OR (delivery.state='claimed' AND delivery.lease_expires_at <= now())
255
- )
256
- RETURNING delivery.id
257
- ), candidate AS (
258
- SELECT delivery.id
259
- FROM agent_bridge.deliveries delivery
260
- JOIN agent_bridge.messages message
261
- ON message.workspace=delivery.workspace AND message.id=delivery.message_id
262
- WHERE delivery.workspace=$1 AND delivery.recipient=$2
263
- AND (
264
- (delivery.state IN ('pending', 'retrying') AND delivery.available_at <= now())
265
- OR (delivery.state='claimed' AND delivery.lease_expires_at <= now())
266
- )
267
- AND delivery.attempt < $6
268
- AND (message.expires_at IS NULL OR message.expires_at > now())
269
- ORDER BY delivery.available_at, delivery.id
270
- FOR UPDATE OF delivery SKIP LOCKED
271
- LIMIT 1
272
- )
273
- UPDATE agent_bridge.deliveries delivery
274
- SET state='claimed', attempt=delivery.attempt+1, lease_token=$3,
275
- lease_owner=$4, lease_expires_at=now() + ($5 * interval '1 millisecond')
276
- FROM candidate
277
- WHERE delivery.id=candidate.id
278
- RETURNING delivery.*`,
279
- [principal.workspace, principal.agent, token, owner, options.leaseMs, options.maxAttempts ?? 5]
280
- );
281
- return result.rows[0] ? asDelivery(result.rows[0]) : null;
282
- }
283
- async renewDelivery(principal, id, token, leaseMs) {
284
- const result = await this.db.query(
285
- `UPDATE agent_bridge.deliveries
286
- SET lease_expires_at=now() + ($1 * interval '1 millisecond')
287
- WHERE workspace=$2 AND recipient=$3 AND lease_owner=$4 AND id=$5 AND lease_token=$6
288
- AND state='claimed' AND lease_expires_at>now()
289
- RETURNING *`,
290
- [leaseMs, principal.workspace, principal.agent, principal.instance ?? principal.agent, id, token]
291
- );
292
- return result.rows[0] ? asDelivery(result.rows[0]) : null;
293
- }
294
- async settleDelivery(principal, id, token, state, error, retryPolicy) {
295
- if (!retryPolicy) throw new Error("retry policy is required");
296
- const result = await this.db.query(
297
- `UPDATE agent_bridge.deliveries
298
- SET state=CASE
299
- WHEN $1='retrying' AND attempt >= $6 THEN 'dead'
300
- ELSE $1
301
- END,
302
- available_at=CASE
303
- WHEN $1='retrying' AND attempt < $6 THEN
304
- now() + (
305
- LEAST($8::double precision, $7::double precision * power(2, GREATEST(attempt - 1, 0)))
306
- * (1 + ((random() * 2) - 1) * $9::double precision)
307
- * interval '1 millisecond'
308
- )
309
- ELSE available_at
310
- END,
311
- last_error=$2, lease_token=NULL, lease_owner=NULL, lease_expires_at=NULL
312
- WHERE workspace=$3 AND recipient=$4 AND lease_owner=$5
313
- AND id=$10 AND lease_token=$11 AND state='claimed' AND lease_expires_at>now()
314
- RETURNING *`,
315
- [
316
- state,
317
- error?.slice(0, 1024) ?? null,
318
- principal.workspace,
319
- principal.agent,
320
- principal.instance ?? principal.agent,
321
- retryPolicy.maxAttempts,
322
- retryPolicy.baseDelayMs,
323
- retryPolicy.maxDelayMs,
324
- retryPolicy.jitterRatio,
325
- id,
326
- token
327
- ]
328
- );
329
- return result.rows[0] ? asDelivery(result.rows[0]) : null;
330
- }
331
- async diagnostics(principal) {
332
- const result = await this.db.query(
333
- `SELECT state, count(*)::integer AS count, min(available_at) AS oldest
334
- FROM agent_bridge.deliveries
335
- WHERE workspace=$1 AND recipient=$2
336
- GROUP BY state`,
337
- [principal.workspace, principal.agent]
338
- );
339
- const counts = new Map(result.rows.map((row) => [String(row.state), Number(row.count)]));
340
- const oldest = result.rows.filter((row) => row.state === "pending" || row.state === "retrying").map((row) => asTimestamp(row.oldest)).filter((value) => Boolean(value)).sort()[0];
341
- return {
342
- schemaVersion: "postgres-v2",
343
- deliverySupported: true,
344
- pending: counts.get("pending") ?? 0,
345
- claimed: counts.get("claimed") ?? 0,
346
- retrying: counts.get("retrying") ?? 0,
347
- dead: counts.get("dead") ?? 0,
348
- oldestAvailableAt: oldest
349
- };
350
- }
351
- async heartbeat(principal, leaseMs, runtimeType, capabilities = []) {
352
- await this.db.query(
353
- "DELETE FROM agent_bridge.agent_instances WHERE workspace=$1 AND lease_expires_at<=now()",
354
- [principal.workspace]
355
- );
356
- const result = await this.db.query(
357
- `WITH locked AS (
358
- SELECT pg_advisory_xact_lock(hashtextextended($1, 0))
359
- )
360
- INSERT INTO agent_bridge.agent_instances (workspace,agent,instance,runtime_type,capabilities,lease_expires_at,last_seen_at)
361
- SELECT $1,$2,$3,$4,$5::jsonb,now() + ($6 * interval '1 millisecond'),now()
362
- FROM locked
363
- WHERE EXISTS (
364
- SELECT 1 FROM agent_bridge.agent_instances
365
- WHERE workspace=$1 AND agent=$2 AND instance=$3
366
- ) OR ((
367
- SELECT count(*) < 128 FROM agent_bridge.agent_instances
368
- WHERE workspace=$1 AND agent=$2
369
- ) AND (
370
- SELECT count(*) < 4096 FROM agent_bridge.agent_instances
371
- WHERE workspace=$1
372
- )
373
- )
374
- ON CONFLICT (workspace,agent,instance) DO UPDATE SET runtime_type=excluded.runtime_type,capabilities=excluded.capabilities,lease_expires_at=excluded.lease_expires_at,last_seen_at=excluded.last_seen_at
375
- RETURNING *`,
376
- [principal.workspace, principal.agent, principal.instance, runtimeType ?? null, JSON.stringify(capabilities), leaseMs]
377
- );
378
- if (!result.rows[0]) {
379
- throw Object.assign(new Error("active instance limit reached"), {
380
- status: 429,
381
- code: "presence_limit"
382
- });
383
- }
384
- return asPresence(result.rows[0]);
385
- }
386
- async listPresence(principal) {
387
- await this.db.query(
388
- "DELETE FROM agent_bridge.agent_instances WHERE workspace=$1 AND lease_expires_at<=now()",
389
- [principal.workspace]
390
- );
391
- const result = await this.db.query(
392
- "SELECT * FROM agent_bridge.agent_instances WHERE workspace=$1 ORDER BY agent,instance",
393
- [principal.workspace]
394
- );
395
- return result.rows.map(asPresence);
396
- }
397
- async listDeliveryEvents(deliveryId) {
398
- const result = await this.db.query(
399
- "SELECT * FROM agent_bridge.delivery_events WHERE delivery_id=$1 ORDER BY sequence",
400
- [deliveryId]
401
- );
402
- return result.rows.map(asDeliveryEvent);
403
- }
404
- };
405
-
406
- export {
407
- PostgresBridgeStore
408
- };
409
- //# sourceMappingURL=chunk-O26W5QHS.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/postgres-bridge-store.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport {\n decodeCursor,\n encodeCursor,\n type AgentPresence,\n type BridgeDelivery,\n type BridgeDeliveryEvent,\n type BridgeMessage,\n type BridgePrincipal,\n type RetryPolicy,\n} from \"./bridge-domain.js\";\nimport type {\n BridgeStore,\n BridgeDiagnostics,\n ClaimOptions,\n InsertMessageResult,\n MessagePage,\n MessageQuery,\n} from \"./bridge-store.js\";\nimport { assertIdempotentReplay } from \"./idempotency.js\";\n\nexport interface PgQueryable {\n query<T extends Record<string, unknown> = Record<string, unknown>>(\n sql: string,\n values?: unknown[],\n ): Promise<{ rows: T[]; rowCount: number | null }>;\n}\n\ntype Row = Record<string, any>;\n\nfunction json(value: unknown): string | null {\n return value === undefined ? null : JSON.stringify(value);\n}\n\nfunction parse(value: unknown): any {\n return typeof value === \"string\" ? JSON.parse(value) : value;\n}\n\nfunction asTimestamp(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (value instanceof Date) return value.toISOString();\n return String(value);\n}\n\nfunction asMessage(row: Row): BridgeMessage {\n return {\n id: String(row.id),\n workspace: String(row.workspace),\n source: String(row.source),\n sequence: String(row.sequence),\n type: String(row.type),\n content: String(row.content),\n contentType: String(row.content_type),\n data: parse(row.data),\n targets: parse(row.targets) ?? [],\n threadId: row.thread_id ?? undefined,\n replyToId: row.reply_to_id ?? undefined,\n correlationId: row.correlation_id ?? undefined,\n causationId: row.causation_id ?? undefined,\n priority: row.priority,\n expiresAt: asTimestamp(row.expires_at),\n idempotencyKey: row.idempotency_key ?? undefined,\n atribReceiptId: row.atrib_receipt_id ?? undefined,\n informedBy: parse(row.informed_by),\n metadata: parse(row.metadata),\n createdAt: asTimestamp(row.created_at) ?? \"\",\n };\n}\n\nfunction asDelivery(row: Row): BridgeDelivery {\n return {\n id: String(row.id),\n messageId: String(row.message_id),\n workspace: String(row.workspace),\n recipient: String(row.recipient),\n state: row.state,\n attempt: Number(row.attempt),\n availableAt: asTimestamp(row.available_at) ?? \"\",\n leaseToken: row.lease_token ?? undefined,\n leaseOwner: row.lease_owner ?? undefined,\n leaseExpiresAt: asTimestamp(row.lease_expires_at),\n lastError: row.last_error ?? undefined,\n };\n}\n\nfunction asPresence(row: Row): AgentPresence {\n return {\n workspace: String(row.workspace), agent: String(row.agent), instance: String(row.instance),\n runtimeType: row.runtime_type ?? undefined, capabilities: parse(row.capabilities) ?? [],\n leaseExpiresAt: asTimestamp(row.lease_expires_at) ?? \"\", lastSeenAt: asTimestamp(row.last_seen_at) ?? \"\",\n };\n}\n\nfunction asDeliveryEvent(row: Row): BridgeDeliveryEvent {\n return {\n sequence: String(row.sequence), deliveryId: String(row.delivery_id),\n messageId: String(row.message_id), workspace: String(row.workspace),\n recipient: String(row.recipient), fromState: row.from_state as BridgeDeliveryEvent[\"fromState\"],\n toState: row.to_state as BridgeDeliveryEvent[\"toState\"], attempt: Number(row.attempt),\n leaseOwner: row.lease_owner ?? undefined, error: row.error ?? undefined,\n createdAt: asTimestamp(row.created_at) ?? \"\",\n };\n}\n\nexport class PostgresBridgeStore implements BridgeStore {\n constructor(private readonly db: PgQueryable) {}\n\n async initialize(): Promise<void> {\n // Deployments apply ordered migrations before starting the service.\n }\n\n async insertMessage(\n input: Omit<BridgeMessage, \"sequence\" | \"createdAt\">,\n ): Promise<InsertMessageResult> {\n const values = [\n input.id,\n input.workspace,\n input.source,\n input.type,\n input.content,\n input.contentType,\n json(input.data),\n json(input.targets),\n input.threadId ?? null,\n input.replyToId ?? null,\n input.correlationId ?? null,\n input.causationId ?? null,\n input.priority,\n input.expiresAt ?? null,\n input.idempotencyKey ?? null,\n input.atribReceiptId ?? null,\n json(input.informedBy),\n json(input.metadata),\n ];\n\n const result = await this.db.query<Row>(\n `WITH inserted AS (\n INSERT INTO agent_bridge.messages (\n id, workspace, source, type, content, content_type, data, targets,\n thread_id, reply_to_id, correlation_id, causation_id, priority,\n expires_at, idempotency_key, atrib_receipt_id, informed_by, metadata\n )\n VALUES (\n $1, $2, $3, $4, $5, $6, $7::jsonb, $8::jsonb,\n $9, $10, $11, $12, $13, $14, $15, $16, $17::jsonb, $18::jsonb\n )\n ON CONFLICT (workspace, source, idempotency_key)\n WHERE idempotency_key IS NOT NULL\n DO NOTHING\n RETURNING *, true AS created\n ), selected AS (\n SELECT * FROM inserted\n UNION ALL\n SELECT existing.*, false AS created\n FROM agent_bridge.messages existing\n WHERE $15::text IS NOT NULL\n AND existing.workspace = $2\n AND existing.source = $3\n AND existing.idempotency_key = $15\n AND NOT EXISTS (SELECT 1 FROM inserted)\n LIMIT 1\n ), delivery_rows AS (\n INSERT INTO agent_bridge.deliveries (\n id, message_id, workspace, recipient, state, available_at\n )\n SELECT gen_random_uuid(), inserted.id, inserted.workspace, target, 'pending', now()\n FROM inserted\n CROSS JOIN LATERAL jsonb_array_elements_text(inserted.targets) AS target\n ON CONFLICT (message_id, recipient) DO NOTHING\n )\n SELECT * FROM selected`,\n values,\n );\n\n let row = result.rows[0];\n if (!row && input.idempotencyKey) {\n const existing = await this.db.query<Row>(\n `SELECT *, false AS created\n FROM agent_bridge.messages\n WHERE workspace=$1 AND source=$2 AND idempotency_key=$3`,\n [input.workspace, input.source, input.idempotencyKey],\n );\n row = existing.rows[0];\n }\n if (!row) throw new Error(\"message insert did not return a row\");\n const message = asMessage(row);\n if (row.created !== true) assertIdempotentReplay(message, input);\n return { message, created: row.created === true };\n }\n\n async listMessages(\n principal: BridgePrincipal,\n query: MessageQuery = {},\n ): Promise<MessagePage> {\n const cursor = decodeCursor(query.cursor) ?? \"0\";\n const limit = Math.min(Math.max(Math.trunc(query.limit ?? 50), 1), 200);\n const boundary = query.latest ? undefined : await this.db.query<{ sequence: string | null }>(\n \"SELECT max(sequence)::text AS sequence FROM agent_bridge.messages WHERE workspace=$1\",\n [principal.workspace],\n );\n const highWater = boundary?.rows[0]?.sequence;\n const values: unknown[] = query.latest\n ? [principal.workspace, principal.agent]\n : [principal.workspace, cursor, principal.agent];\n let sql =\n `SELECT * FROM agent_bridge.messages WHERE workspace=$1 ${query.latest ? \"\" : \"AND sequence>$2::bigint \"}` +\n `AND (targets='[]'::jsonb OR targets ? $${query.latest ? 2 : 3})`;\n\n if (highWater) {\n values.push(highWater);\n sql += ` AND sequence <= $${values.length}::bigint`;\n }\n\n if (!query.includeExpired) {\n sql += \" AND (expires_at IS NULL OR expires_at > now())\";\n }\n if (query.types?.length) {\n values.push(query.types);\n sql += ` AND type = ANY($${values.length})`;\n }\n if (query.source) {\n values.push(query.source);\n sql += ` AND source = $${values.length}`;\n }\n if (query.since) {\n values.push(query.since);\n sql += ` AND created_at >= $${values.length}::timestamptz`;\n }\n if (query.unacknowledgedBy) {\n values.push(query.unacknowledgedBy);\n sql += ` AND NOT EXISTS (\n SELECT 1 FROM agent_bridge.receipts receipt\n WHERE receipt.workspace=agent_bridge.messages.workspace\n AND receipt.message_id=agent_bridge.messages.id\n AND receipt.principal=$${values.length}\n )`;\n }\n if (query.threadId) {\n values.push(query.threadId);\n sql += ` AND thread_id = $${values.length}`;\n }\n\n values.push(limit);\n const result = await this.db.query<Row>(\n `${sql} ORDER BY sequence ${query.latest ? \"DESC\" : \"ASC\"} LIMIT $${values.length}`,\n values,\n );\n const messages = result.rows.map(asMessage);\n const last = messages[messages.length - 1];\n if (query.latest) return { messages, cursor: messages[0] ? encodeCursor(messages[0].sequence) : query.cursor };\n if (messages.length === limit) return { messages, cursor: encodeCursor(last!.sequence) };\n return { messages, cursor: highWater ? encodeCursor(highWater) : query.cursor };\n }\n\n async recordReceipt(\n workspace: string,\n ids: string[],\n principal: string,\n readAt = new Date(),\n ): Promise<number> {\n const result = await this.db.query(\n `INSERT INTO agent_bridge.receipts (workspace, message_id, principal, read_at)\n SELECT message.workspace, message.id, $3, $4\n FROM agent_bridge.messages message\n WHERE message.workspace = $1 AND message.id = ANY($2::uuid[])\n AND (message.targets='[]'::jsonb OR message.targets ? $3)\n ON CONFLICT DO NOTHING`,\n [workspace, ids, principal, readAt],\n );\n return result.rowCount ?? 0;\n }\n\n async claimDelivery(\n principal: BridgePrincipal,\n options: ClaimOptions,\n ): Promise<BridgeDelivery | null> {\n const owner = principal.instance ?? principal.agent;\n const token = randomUUID();\n const result = await this.db.query<Row>(\n `WITH expired AS (\n UPDATE agent_bridge.deliveries delivery\n SET state='dead', last_error='message expired', lease_token=NULL,\n lease_owner=NULL, lease_expires_at=NULL\n FROM agent_bridge.messages message\n WHERE delivery.workspace=$1 AND delivery.recipient=$2\n AND delivery.state IN ('pending', 'retrying', 'claimed')\n AND message.workspace=delivery.workspace AND message.id=delivery.message_id\n AND message.expires_at IS NOT NULL AND message.expires_at <= now()\n RETURNING delivery.id\n ), exhausted AS (\n UPDATE agent_bridge.deliveries delivery\n SET state='dead', last_error='maximum attempts reached', lease_token=NULL,\n lease_owner=NULL, lease_expires_at=NULL\n WHERE delivery.workspace=$1 AND delivery.recipient=$2 AND delivery.attempt >= $6\n AND (\n delivery.state IN ('pending', 'retrying')\n OR (delivery.state='claimed' AND delivery.lease_expires_at <= now())\n )\n RETURNING delivery.id\n ), candidate AS (\n SELECT delivery.id\n FROM agent_bridge.deliveries delivery\n JOIN agent_bridge.messages message\n ON message.workspace=delivery.workspace AND message.id=delivery.message_id\n WHERE delivery.workspace=$1 AND delivery.recipient=$2\n AND (\n (delivery.state IN ('pending', 'retrying') AND delivery.available_at <= now())\n OR (delivery.state='claimed' AND delivery.lease_expires_at <= now())\n )\n AND delivery.attempt < $6\n AND (message.expires_at IS NULL OR message.expires_at > now())\n ORDER BY delivery.available_at, delivery.id\n FOR UPDATE OF delivery SKIP LOCKED\n LIMIT 1\n )\n UPDATE agent_bridge.deliveries delivery\n SET state='claimed', attempt=delivery.attempt+1, lease_token=$3,\n lease_owner=$4, lease_expires_at=now() + ($5 * interval '1 millisecond')\n FROM candidate\n WHERE delivery.id=candidate.id\n RETURNING delivery.*`,\n [principal.workspace, principal.agent, token, owner, options.leaseMs, options.maxAttempts ?? 5],\n );\n return result.rows[0] ? asDelivery(result.rows[0]) : null;\n }\n\n async renewDelivery(\n principal: BridgePrincipal,\n id: string,\n token: string,\n leaseMs: number,\n ): Promise<BridgeDelivery | null> {\n const result = await this.db.query<Row>(\n `UPDATE agent_bridge.deliveries\n SET lease_expires_at=now() + ($1 * interval '1 millisecond')\n WHERE workspace=$2 AND recipient=$3 AND lease_owner=$4 AND id=$5 AND lease_token=$6\n AND state='claimed' AND lease_expires_at>now()\n RETURNING *`,\n [leaseMs, principal.workspace, principal.agent, principal.instance ?? principal.agent, id, token],\n );\n return result.rows[0] ? asDelivery(result.rows[0]) : null;\n }\n\n async settleDelivery(\n principal: BridgePrincipal,\n id: string,\n token: string,\n state: \"acked\" | \"retrying\" | \"dead\",\n error?: string,\n retryPolicy?: RetryPolicy,\n ): Promise<BridgeDelivery | null> {\n if (!retryPolicy) throw new Error(\"retry policy is required\");\n const result = await this.db.query<Row>(\n `UPDATE agent_bridge.deliveries\n SET state=CASE\n WHEN $1='retrying' AND attempt >= $6 THEN 'dead'\n ELSE $1\n END,\n available_at=CASE\n WHEN $1='retrying' AND attempt < $6 THEN\n now() + (\n LEAST($8::double precision, $7::double precision * power(2, GREATEST(attempt - 1, 0)))\n * (1 + ((random() * 2) - 1) * $9::double precision)\n * interval '1 millisecond'\n )\n ELSE available_at\n END,\n last_error=$2, lease_token=NULL, lease_owner=NULL, lease_expires_at=NULL\n WHERE workspace=$3 AND recipient=$4 AND lease_owner=$5\n AND id=$10 AND lease_token=$11 AND state='claimed' AND lease_expires_at>now()\n RETURNING *`,\n [\n state,\n error?.slice(0, 1024) ?? null,\n principal.workspace,\n principal.agent,\n principal.instance ?? principal.agent,\n retryPolicy.maxAttempts,\n retryPolicy.baseDelayMs,\n retryPolicy.maxDelayMs,\n retryPolicy.jitterRatio,\n id,\n token,\n ],\n );\n return result.rows[0] ? asDelivery(result.rows[0]) : null;\n }\n\n async diagnostics(principal: BridgePrincipal): Promise<BridgeDiagnostics> {\n const result = await this.db.query<Row>(\n `SELECT state, count(*)::integer AS count, min(available_at) AS oldest\n FROM agent_bridge.deliveries\n WHERE workspace=$1 AND recipient=$2\n GROUP BY state`,\n [principal.workspace, principal.agent],\n );\n const counts = new Map(result.rows.map((row) => [String(row.state), Number(row.count)]));\n const oldest = result.rows\n .filter((row) => row.state === \"pending\" || row.state === \"retrying\")\n .map((row) => asTimestamp(row.oldest))\n .filter((value): value is string => Boolean(value))\n .sort()[0];\n return {\n schemaVersion: \"postgres-v2\",\n deliverySupported: true,\n pending: counts.get(\"pending\") ?? 0,\n claimed: counts.get(\"claimed\") ?? 0,\n retrying: counts.get(\"retrying\") ?? 0,\n dead: counts.get(\"dead\") ?? 0,\n oldestAvailableAt: oldest,\n };\n }\n\n async heartbeat(principal: BridgePrincipal, leaseMs: number, runtimeType?: string, capabilities: string[] = []): Promise<AgentPresence> {\n await this.db.query(\n \"DELETE FROM agent_bridge.agent_instances WHERE workspace=$1 AND lease_expires_at<=now()\",\n [principal.workspace],\n );\n const result = await this.db.query<Row>(\n `WITH locked AS (\n SELECT pg_advisory_xact_lock(hashtextextended($1, 0))\n )\n INSERT INTO agent_bridge.agent_instances (workspace,agent,instance,runtime_type,capabilities,lease_expires_at,last_seen_at)\n SELECT $1,$2,$3,$4,$5::jsonb,now() + ($6 * interval '1 millisecond'),now()\n FROM locked\n WHERE EXISTS (\n SELECT 1 FROM agent_bridge.agent_instances\n WHERE workspace=$1 AND agent=$2 AND instance=$3\n ) OR ((\n SELECT count(*) < 128 FROM agent_bridge.agent_instances\n WHERE workspace=$1 AND agent=$2\n ) AND (\n SELECT count(*) < 4096 FROM agent_bridge.agent_instances\n WHERE workspace=$1\n )\n )\n ON CONFLICT (workspace,agent,instance) DO UPDATE SET runtime_type=excluded.runtime_type,capabilities=excluded.capabilities,lease_expires_at=excluded.lease_expires_at,last_seen_at=excluded.last_seen_at\n RETURNING *`,\n [principal.workspace, principal.agent, principal.instance, runtimeType ?? null, JSON.stringify(capabilities), leaseMs],\n );\n if (!result.rows[0]) {\n throw Object.assign(new Error(\"active instance limit reached\"), {\n status: 429,\n code: \"presence_limit\",\n });\n }\n return asPresence(result.rows[0]!);\n }\n\n async listPresence(principal: BridgePrincipal): Promise<AgentPresence[]> {\n await this.db.query(\n \"DELETE FROM agent_bridge.agent_instances WHERE workspace=$1 AND lease_expires_at<=now()\",\n [principal.workspace],\n );\n const result = await this.db.query<Row>(\n \"SELECT * FROM agent_bridge.agent_instances WHERE workspace=$1 ORDER BY agent,instance\",\n [principal.workspace],\n );\n return result.rows.map(asPresence);\n }\n\n async listDeliveryEvents(deliveryId: string): Promise<BridgeDeliveryEvent[]> {\n const result = await this.db.query<Row>(\n \"SELECT * FROM agent_bridge.delivery_events WHERE delivery_id=$1 ORDER BY sequence\",\n [deliveryId],\n );\n return result.rows.map(asDeliveryEvent);\n }\n}\n"],"mappings":"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","names":[]}