@creatornader/agent-bridge 0.5.2 → 0.6.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/CHANGELOG.md +57 -1
- package/README.md +59 -34
- package/ROADMAP.md +74 -17
- package/SECURITY.md +6 -5
- package/SKILL.md +4 -1
- package/dist/archive.d.ts +2 -2
- package/dist/{bridge-service-CNBKdYXh.d.ts → bridge-service-DjSYfjKt.d.ts} +4 -2
- package/dist/{bridge-store-ByJ6CaJk.d.ts → bridge-store-Bi_LCX8e.d.ts} +5 -1
- package/dist/bridge.d.ts +9 -37
- package/dist/bridge.js +6 -10
- package/dist/chunk-23UDQZMT.js +54 -0
- package/dist/chunk-23UDQZMT.js.map +1 -0
- package/dist/{chunk-AWE3DFZV.js → chunk-4V2PFJEF.js} +11 -4
- package/dist/chunk-4V2PFJEF.js.map +1 -0
- package/dist/{chunk-E4OWHGUE.js → chunk-63JKCBC6.js} +10 -8
- package/dist/chunk-63JKCBC6.js.map +1 -0
- package/dist/chunk-6ZOLE3E3.js +242 -0
- package/dist/chunk-6ZOLE3E3.js.map +1 -0
- package/dist/chunk-7B3XRRNI.js +27 -0
- package/dist/chunk-7B3XRRNI.js.map +1 -0
- package/dist/{chunk-7VJI2MXI.js → chunk-IF5OKPBK.js} +32 -14
- package/dist/chunk-IF5OKPBK.js.map +1 -0
- package/dist/{chunk-QPC6JHA3.js → chunk-IXNQG4SB.js} +12 -16
- package/dist/chunk-IXNQG4SB.js.map +1 -0
- package/dist/{chunk-HUHG7XTB.js → chunk-JIRNR75D.js} +30 -193
- package/dist/chunk-JIRNR75D.js.map +1 -0
- package/dist/{chunk-JUTJRAMA.js → chunk-LF37B6KL.js} +6 -4
- package/dist/chunk-LF37B6KL.js.map +1 -0
- package/dist/{chunk-2EVLG3YA.js → chunk-UKFRCP6X.js} +10 -7
- package/dist/chunk-UKFRCP6X.js.map +1 -0
- package/dist/{chunk-SN7PIVDF.js → chunk-ZUZ7TCIH.js} +13 -1
- package/dist/{chunk-SN7PIVDF.js.map → chunk-ZUZ7TCIH.js.map} +1 -1
- package/dist/cli.js +45 -40
- package/dist/cli.js.map +1 -1
- package/dist/client-config.d.ts +1 -1
- package/dist/client-config.js +1 -1
- package/dist/client-runtime.d.ts +3 -3
- package/dist/client-runtime.js +5 -5
- package/dist/contracts/generate.js +3 -3
- package/dist/contracts/generate.js.map +1 -1
- package/dist/dr.d.ts +8 -0
- package/dist/dr.js +1 -1
- package/dist/{gateway-CW-61lvs.d.ts → gateway-DWZ3pX48.d.ts} +7 -2
- package/dist/gateway-main.js +12 -3
- package/dist/gateway-main.js.map +1 -1
- package/dist/gateway.d.ts +3 -3
- package/dist/gateway.js +3 -3
- package/dist/index.js +8 -7
- package/dist/index.js.map +1 -1
- package/dist/{postgres-bridge-store-C9KG9Z69.d.ts → postgres-bridge-store-ChoOuFEY.d.ts} +1 -1
- package/dist/server.d.ts +0 -2
- package/dist/server.js +8 -7
- package/dist/{sqlite-edge-store-CdMIOrho.d.ts → sqlite-edge-store-BAFUeysk.d.ts} +1 -1
- package/dist/sqlite.d.ts +7 -3
- package/dist/sqlite.js +1 -1
- package/docs/architecture-v2.md +26 -14
- package/docs/decisions/0001-protocol-layers-and-acknowledgment-semantics.md +2 -1
- package/docs/decisions/0002-canonical-operation-contract-registry.md +11 -1
- package/docs/decisions/0005-retire-direct-supabase-runtime.md +52 -0
- package/docs/deployment.md +41 -17
- package/docs/ecosystem.md +6 -4
- package/docs/troubleshooting.md +15 -0
- package/llms.txt +4 -4
- package/openapi/agent-bridge-v2.openapi.json +11 -6
- package/package.json +5 -3
- package/schemas/agent-bridge-v2.capabilities.json +11 -5
- package/schemas/agent-bridge-v2.mcp.json +13 -12
- package/schemas/agent-bridge-v2.schema.json +26 -24
- package/scripts/gateway-release-check.mjs +92 -0
- package/dist/chunk-2EVLG3YA.js.map +0 -1
- package/dist/chunk-7VJI2MXI.js.map +0 -1
- package/dist/chunk-AWE3DFZV.js.map +0 -1
- package/dist/chunk-E4OWHGUE.js.map +0 -1
- package/dist/chunk-HUHG7XTB.js.map +0 -1
- package/dist/chunk-JUTJRAMA.js.map +0 -1
- package/dist/chunk-QPC6JHA3.js.map +0 -1
- package/dist/chunk-Z6JP6MYD.js +0 -584
- package/dist/chunk-Z6JP6MYD.js.map +0 -1
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
ContractResponseError,
|
|
4
|
+
PROTOCOL_HEADER,
|
|
5
|
+
PROTOCOL_VERSION,
|
|
6
|
+
SUPPORTED_PROTOCOL_HEADER,
|
|
7
|
+
SUPPORTED_PROTOCOL_VERSIONS,
|
|
8
|
+
parseResponse
|
|
9
|
+
} from "./chunk-63JKCBC6.js";
|
|
10
|
+
|
|
11
|
+
// src/http-bridge-store.ts
|
|
12
|
+
var BridgeHttpError = class extends Error {
|
|
13
|
+
constructor(status, code, requestId, details, message = `Agent Bridge request failed: ${code}`) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.status = status;
|
|
16
|
+
this.code = code;
|
|
17
|
+
this.requestId = requestId;
|
|
18
|
+
this.details = details;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
var HttpBridgeStore = class {
|
|
22
|
+
constructor(options) {
|
|
23
|
+
this.options = options;
|
|
24
|
+
this.closeController = new AbortController();
|
|
25
|
+
this.closed = false;
|
|
26
|
+
const url = new URL(options.baseUrl);
|
|
27
|
+
const loopback = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]";
|
|
28
|
+
if (url.protocol !== "https:" && !(url.protocol === "http:" && loopback) && !options.allowInsecureRemoteHttp) {
|
|
29
|
+
throw new Error("Agent Bridge requires HTTPS for non-loopback gateways");
|
|
30
|
+
}
|
|
31
|
+
this.fetchImpl = options.fetch ?? fetch;
|
|
32
|
+
}
|
|
33
|
+
async initialize(options = {}) {
|
|
34
|
+
if (options.mode === "passive") return;
|
|
35
|
+
await this.request(void 0, "/readyz", { authenticated: false, signal: options.signal });
|
|
36
|
+
const status = await this.request("status", "/v2/status", { signal: options.signal });
|
|
37
|
+
this.assertBoundPrincipal(status);
|
|
38
|
+
}
|
|
39
|
+
assertBoundPrincipal(status) {
|
|
40
|
+
const principal = status?.principal;
|
|
41
|
+
if (!principal || principal.workspace !== this.options.principal.workspace || principal.agent !== this.options.principal.agent) {
|
|
42
|
+
throw new BridgeHttpError(403, "principal_mismatch");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async request(operationId, path, options = {}) {
|
|
46
|
+
if (options.method === "POST" && !options.skipProtocolProbe) await this.ensureProtocol(options.signal);
|
|
47
|
+
if (this.closed) throw new BridgeHttpError(0, "store_closed");
|
|
48
|
+
if (options.signal?.aborted) throw new BridgeHttpError(0, "request_cancelled");
|
|
49
|
+
const requestController = new AbortController();
|
|
50
|
+
const abort = () => requestController.abort(this.closeController.signal.reason);
|
|
51
|
+
const abortRequest = () => requestController.abort(options.signal?.reason);
|
|
52
|
+
this.closeController.signal.addEventListener("abort", abort, { once: true });
|
|
53
|
+
options.signal?.addEventListener("abort", abortRequest, { once: true });
|
|
54
|
+
let timedOut = false;
|
|
55
|
+
const timeout = setTimeout(() => {
|
|
56
|
+
timedOut = true;
|
|
57
|
+
requestController.abort(new Error("request timeout"));
|
|
58
|
+
}, this.options.timeoutMs ?? 1e4);
|
|
59
|
+
timeout.unref?.();
|
|
60
|
+
try {
|
|
61
|
+
const response = await this.fetchImpl(`${this.options.baseUrl.replace(/\/$/, "")}${path}`, {
|
|
62
|
+
method: options.method ?? "GET",
|
|
63
|
+
signal: requestController.signal,
|
|
64
|
+
headers: {
|
|
65
|
+
[PROTOCOL_HEADER]: this.selectedProtocolVersion ?? PROTOCOL_VERSION,
|
|
66
|
+
...options.authenticated === false ? {} : { authorization: `Bearer ${this.options.token}` },
|
|
67
|
+
...this.options.principal.instance ? { "x-agent-bridge-instance": this.options.principal.instance } : {},
|
|
68
|
+
...options.body === void 0 ? {} : { "content-type": "application/json" }
|
|
69
|
+
},
|
|
70
|
+
body: options.body === void 0 ? void 0 : JSON.stringify(options.body)
|
|
71
|
+
});
|
|
72
|
+
const requestId = response.headers.get("x-request-id") ?? void 0;
|
|
73
|
+
const selectedHeader = response.headers.get(PROTOCOL_HEADER);
|
|
74
|
+
const supportedHeader = response.headers.get(SUPPORTED_PROTOCOL_HEADER);
|
|
75
|
+
const supportedProtocols = supportedHeader?.split(",").map((value) => value.trim()).filter(Boolean) ?? [];
|
|
76
|
+
const inconsistentProtocol = selectedHeader === null || supportedHeader === null || !SUPPORTED_PROTOCOL_VERSIONS.includes(selectedHeader) || !supportedProtocols.includes(selectedHeader) || selectedHeader !== PROTOCOL_VERSION;
|
|
77
|
+
if (operationId && inconsistentProtocol) {
|
|
78
|
+
throw new BridgeHttpError(502, "protocol_mismatch", requestId, {
|
|
79
|
+
expected: PROTOCOL_VERSION,
|
|
80
|
+
selected: selectedHeader,
|
|
81
|
+
supported: supportedHeader
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
85
|
+
const payload = contentType.startsWith("application/json") ? await response.json().catch(() => ({})) : await response.text();
|
|
86
|
+
if (!response.ok) {
|
|
87
|
+
const envelope = payload && typeof payload === "object" ? payload.error : void 0;
|
|
88
|
+
throw new BridgeHttpError(
|
|
89
|
+
response.status,
|
|
90
|
+
envelope?.code ?? "request_failed",
|
|
91
|
+
envelope?.requestId ?? requestId,
|
|
92
|
+
envelope?.details ?? envelope,
|
|
93
|
+
envelope?.message ?? `Agent Bridge request failed: ${envelope?.code ?? "request_failed"}`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
if (operationId) this.selectedProtocolVersion = PROTOCOL_VERSION;
|
|
97
|
+
if (!operationId) return payload;
|
|
98
|
+
return parseResponse(operationId, payload);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
if (error instanceof BridgeHttpError) throw error;
|
|
101
|
+
if (error instanceof ContractResponseError) {
|
|
102
|
+
throw new BridgeHttpError(error.status, error.code, void 0, {
|
|
103
|
+
operation: error.operation,
|
|
104
|
+
issues: error.issues
|
|
105
|
+
}, error.message);
|
|
106
|
+
}
|
|
107
|
+
if (this.closed) throw new BridgeHttpError(0, "store_closed");
|
|
108
|
+
if (options.signal?.aborted) throw new BridgeHttpError(0, "request_cancelled");
|
|
109
|
+
if (timedOut) throw new BridgeHttpError(504, "request_timeout");
|
|
110
|
+
if (error instanceof Error && (error.name === "TimeoutError" || error.name === "AbortError")) {
|
|
111
|
+
throw new BridgeHttpError(504, "request_timeout");
|
|
112
|
+
}
|
|
113
|
+
throw new BridgeHttpError(0, "network_error");
|
|
114
|
+
} finally {
|
|
115
|
+
clearTimeout(timeout);
|
|
116
|
+
this.closeController.signal.removeEventListener("abort", abort);
|
|
117
|
+
options.signal?.removeEventListener("abort", abortRequest);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
ensureProtocol(signal) {
|
|
121
|
+
if (this.selectedProtocolVersion) return Promise.resolve(this.selectedProtocolVersion);
|
|
122
|
+
if (!this.protocolProbe) {
|
|
123
|
+
this.protocolProbe = this.request("status", "/v2/status", { signal, skipProtocolProbe: true }).then(() => this.selectedProtocolVersion).finally(() => {
|
|
124
|
+
this.protocolProbe = void 0;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return this.protocolProbe;
|
|
128
|
+
}
|
|
129
|
+
async capabilities() {
|
|
130
|
+
return this.request("capabilities", "/v2/capabilities");
|
|
131
|
+
}
|
|
132
|
+
assertPrincipal(principal, includeInstance = true) {
|
|
133
|
+
const expected = this.options.principal;
|
|
134
|
+
if (principal.workspace !== expected.workspace || principal.agent !== expected.agent || includeInstance && principal.instance !== expected.instance) {
|
|
135
|
+
throw new BridgeHttpError(403, "principal_mismatch");
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async insertMessage(message, options = {}) {
|
|
139
|
+
this.assertPrincipal({ workspace: message.workspace, agent: message.source }, false);
|
|
140
|
+
await this.ensureProtocol(options.signal);
|
|
141
|
+
const { workspace: _workspace, source: _source, ...draft } = message;
|
|
142
|
+
return this.request("publish_message", "/v2/messages", { method: "POST", body: draft, signal: options.signal });
|
|
143
|
+
}
|
|
144
|
+
async listMessages(principal, query = {}, options = {}) {
|
|
145
|
+
this.assertPrincipal(principal);
|
|
146
|
+
const requestQuery = query;
|
|
147
|
+
const params = new URLSearchParams();
|
|
148
|
+
if (requestQuery.cursor) params.set("cursor", requestQuery.cursor);
|
|
149
|
+
if (requestQuery.mailbox) params.set("mailbox", requestQuery.mailbox);
|
|
150
|
+
if (requestQuery.receiptState) params.set("receiptState", requestQuery.receiptState);
|
|
151
|
+
if (requestQuery.limit) params.set("limit", String(requestQuery.limit));
|
|
152
|
+
if (requestQuery.includeExpired) params.set("includeExpired", "true");
|
|
153
|
+
if (requestQuery.source) params.set("source", requestQuery.source);
|
|
154
|
+
if (requestQuery.project) params.set("project", requestQuery.project);
|
|
155
|
+
if (requestQuery.since) params.set("since", requestQuery.since);
|
|
156
|
+
if (requestQuery.threadId) params.set("threadId", requestQuery.threadId);
|
|
157
|
+
if (requestQuery.latest) params.set("latest", "true");
|
|
158
|
+
for (const type of requestQuery.types ?? []) params.append("type", type);
|
|
159
|
+
return this.request("history", `/v2/history${params.size ? `?${params}` : ""}`, { signal: options.signal });
|
|
160
|
+
}
|
|
161
|
+
async recordReceipt(principal, ids) {
|
|
162
|
+
this.assertPrincipal(principal, false);
|
|
163
|
+
return (await this.request("record_receipt", "/v2/receipts", { method: "POST", body: { messageIds: ids } })).recorded;
|
|
164
|
+
}
|
|
165
|
+
async diagnostics(principal) {
|
|
166
|
+
this.assertPrincipal(principal);
|
|
167
|
+
const status = await this.request("status", "/v2/status");
|
|
168
|
+
this.assertBoundPrincipal(status);
|
|
169
|
+
return status;
|
|
170
|
+
}
|
|
171
|
+
async claimDelivery(principal, options) {
|
|
172
|
+
this.assertPrincipal(principal);
|
|
173
|
+
return (await this.request("claim_delivery", "/v2/deliveries/claim", { method: "POST", body: options }))?.delivery ?? null;
|
|
174
|
+
}
|
|
175
|
+
async listDeliveries(principal, query = {}) {
|
|
176
|
+
this.assertPrincipal(principal);
|
|
177
|
+
const params = new URLSearchParams();
|
|
178
|
+
if (query.cursor) params.set("cursor", query.cursor);
|
|
179
|
+
if (query.limit) params.set("limit", String(query.limit));
|
|
180
|
+
if (query.role) params.set("role", query.role);
|
|
181
|
+
if (query.messageId) params.set("messageId", query.messageId);
|
|
182
|
+
if (query.recipient) params.set("recipient", query.recipient);
|
|
183
|
+
for (const state of query.states ?? []) params.append("state", state);
|
|
184
|
+
return this.request("list_deliveries", `/v2/deliveries${params.size ? `?${params}` : ""}`);
|
|
185
|
+
}
|
|
186
|
+
async listDeliveryEvents(principal, id, query = {}) {
|
|
187
|
+
this.assertPrincipal(principal);
|
|
188
|
+
const params = new URLSearchParams();
|
|
189
|
+
if (query.cursor) params.set("cursor", query.cursor);
|
|
190
|
+
if (query.limit) params.set("limit", String(query.limit));
|
|
191
|
+
return this.request("list_delivery_events", `/v2/deliveries/${id}/events${params.size ? `?${params}` : ""}`);
|
|
192
|
+
}
|
|
193
|
+
async cancelDelivery(principal, id) {
|
|
194
|
+
this.assertPrincipal(principal);
|
|
195
|
+
return (await this.request("cancel_delivery", `/v2/deliveries/${id}/cancel`, { method: "POST", body: {} })).delivery;
|
|
196
|
+
}
|
|
197
|
+
async requeueDelivery(principal, id) {
|
|
198
|
+
this.assertPrincipal(principal);
|
|
199
|
+
return (await this.request("requeue_delivery", `/v2/deliveries/${id}/requeue`, { method: "POST", body: {} })).delivery;
|
|
200
|
+
}
|
|
201
|
+
async renewDelivery(principal, id, token, leaseMs) {
|
|
202
|
+
this.assertPrincipal(principal);
|
|
203
|
+
try {
|
|
204
|
+
return (await this.request("extend_delivery", `/v2/deliveries/${id}/extend`, { method: "POST", body: { leaseToken: token, leaseMs } })).delivery;
|
|
205
|
+
} catch (error) {
|
|
206
|
+
if (error instanceof BridgeHttpError && error.status === 409) return null;
|
|
207
|
+
throw error;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async settleDelivery(principal, id, token, state, error, _retryPolicy) {
|
|
211
|
+
this.assertPrincipal(principal);
|
|
212
|
+
await this.ensureProtocol();
|
|
213
|
+
const action = state === "acked" ? "ack" : "nack";
|
|
214
|
+
try {
|
|
215
|
+
const operationId = action === "ack" ? "acknowledge_delivery" : "negative_acknowledge_delivery";
|
|
216
|
+
const nackBody = { leaseToken: token, error, disposition: state === "dead" ? "dead" : "retry" };
|
|
217
|
+
return (await this.request(operationId, `/v2/deliveries/${id}/${action}`, { method: "POST", body: action === "ack" ? { leaseToken: token } : nackBody })).delivery;
|
|
218
|
+
} catch (caught) {
|
|
219
|
+
if (caught instanceof BridgeHttpError && caught.status === 409) return null;
|
|
220
|
+
throw caught;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
async heartbeat(principal, leaseMs, runtimeType, capabilities = []) {
|
|
224
|
+
this.assertPrincipal(principal);
|
|
225
|
+
return this.request("heartbeat", "/v2/presence/heartbeat", { method: "POST", body: { leaseMs, runtimeType, capabilities } });
|
|
226
|
+
}
|
|
227
|
+
async listPresence(principal) {
|
|
228
|
+
this.assertPrincipal(principal);
|
|
229
|
+
return (await this.request("presence", "/v2/presence")).agents;
|
|
230
|
+
}
|
|
231
|
+
async close() {
|
|
232
|
+
if (this.closed) return;
|
|
233
|
+
this.closed = true;
|
|
234
|
+
this.closeController.abort(new Error("store closed"));
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export {
|
|
239
|
+
BridgeHttpError,
|
|
240
|
+
HttpBridgeStore
|
|
241
|
+
};
|
|
242
|
+
//# sourceMappingURL=chunk-6ZOLE3E3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/http-bridge-store.ts"],"sourcesContent":["import type { AgentPresence, BridgeDelivery, BridgeMessage, BridgePrincipal } from \"./bridge-domain.js\";\nimport type { BridgeDiagnostics, BridgeStore, ClaimOptions, InsertMessageResult, MessagePage, MessageQuery } from \"./bridge-store.js\";\nimport {\n ContractResponseError,\n parseResponse,\n PROTOCOL_HEADER,\n PROTOCOL_VERSION,\n SUPPORTED_PROTOCOL_HEADER,\n SUPPORTED_PROTOCOL_VERSIONS,\n type OperationId,\n} from \"./contracts/registry.js\";\n\nexport interface HttpBridgeStoreOptions {\n baseUrl: string;\n token: string;\n principal: BridgePrincipal;\n timeoutMs?: number;\n allowInsecureRemoteHttp?: boolean;\n fetch?: typeof fetch;\n}\n\nexport class BridgeHttpError extends Error {\n constructor(\n readonly status: number,\n readonly code: string,\n readonly requestId?: string,\n readonly details?: unknown,\n message = `Agent Bridge request failed: ${code}`,\n ) {\n super(message);\n }\n}\n\nexport class HttpBridgeStore implements BridgeStore {\n private readonly fetchImpl: typeof fetch;\n private readonly closeController = new AbortController();\n private closed = false;\n private selectedProtocolVersion?: string;\n private protocolProbe?: Promise<string>;\n constructor(private readonly options: HttpBridgeStoreOptions) {\n const url = new URL(options.baseUrl);\n const loopback = url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\" || url.hostname === \"[::1]\";\n if (url.protocol !== \"https:\" && !(url.protocol === \"http:\" && loopback) && !options.allowInsecureRemoteHttp) {\n throw new Error(\"Agent Bridge requires HTTPS for non-loopback gateways\");\n }\n this.fetchImpl = options.fetch ?? fetch;\n }\n async initialize(options: { signal?: AbortSignal; mode?: \"active\" | \"passive\" } = {}): Promise<void> {\n if (options.mode === \"passive\") return;\n await this.request(undefined, \"/readyz\", { authenticated: false, signal: options.signal });\n const status = await this.request(\"status\", \"/v2/status\", { signal: options.signal });\n this.assertBoundPrincipal(status);\n }\n\n private assertBoundPrincipal(status: any): void {\n const principal = status?.principal;\n if (\n !principal ||\n principal.workspace !== this.options.principal.workspace ||\n principal.agent !== this.options.principal.agent\n ) {\n throw new BridgeHttpError(403, \"principal_mismatch\");\n }\n }\n\n private async request(operationId: OperationId | undefined, path: string, options: { method?: string; body?: unknown; authenticated?: boolean; signal?: AbortSignal; skipProtocolProbe?: boolean } = {}): Promise<any> {\n if (options.method === \"POST\" && !options.skipProtocolProbe) await this.ensureProtocol(options.signal);\n if (this.closed) throw new BridgeHttpError(0, \"store_closed\");\n if (options.signal?.aborted) throw new BridgeHttpError(0, \"request_cancelled\");\n const requestController = new AbortController();\n const abort = () => requestController.abort(this.closeController.signal.reason);\n const abortRequest = () => requestController.abort(options.signal?.reason);\n this.closeController.signal.addEventListener(\"abort\", abort, { once: true });\n options.signal?.addEventListener(\"abort\", abortRequest, { once: true });\n let timedOut = false;\n const timeout = setTimeout(() => {\n timedOut = true;\n requestController.abort(new Error(\"request timeout\"));\n }, this.options.timeoutMs ?? 10_000);\n timeout.unref?.();\n try {\n const response = await this.fetchImpl(`${this.options.baseUrl.replace(/\\/$/, \"\")}${path}`, {\n method: options.method ?? \"GET\", signal: requestController.signal,\n headers: {\n [PROTOCOL_HEADER]: this.selectedProtocolVersion ?? PROTOCOL_VERSION,\n ...(options.authenticated === false ? {} : { authorization: `Bearer ${this.options.token}` }),\n ...(this.options.principal.instance ? { \"x-agent-bridge-instance\": this.options.principal.instance } : {}),\n ...(options.body === undefined ? {} : { \"content-type\": \"application/json\" }),\n },\n body: options.body === undefined ? undefined : JSON.stringify(options.body),\n });\n const requestId = response.headers.get(\"x-request-id\") ?? undefined;\n const selectedHeader = response.headers.get(PROTOCOL_HEADER);\n const supportedHeader = response.headers.get(SUPPORTED_PROTOCOL_HEADER);\n const supportedProtocols = supportedHeader?.split(\",\").map((value) => value.trim()).filter(Boolean) ?? [];\n const inconsistentProtocol = (\n selectedHeader === null || supportedHeader === null ||\n !(SUPPORTED_PROTOCOL_VERSIONS as readonly string[]).includes(selectedHeader) ||\n !supportedProtocols.includes(selectedHeader) ||\n selectedHeader !== PROTOCOL_VERSION\n );\n if (operationId && inconsistentProtocol) {\n throw new BridgeHttpError(502, \"protocol_mismatch\", requestId, {\n expected: PROTOCOL_VERSION,\n selected: selectedHeader,\n supported: supportedHeader,\n });\n }\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n const payload = contentType.startsWith(\"application/json\")\n ? await response.json().catch(() => ({}))\n : await response.text();\n if (!response.ok) {\n const envelope = payload && typeof payload === \"object\" ? (payload as any).error : undefined;\n throw new BridgeHttpError(\n response.status,\n envelope?.code ?? \"request_failed\",\n envelope?.requestId ?? requestId,\n envelope?.details ?? envelope,\n envelope?.message ?? `Agent Bridge request failed: ${envelope?.code ?? \"request_failed\"}`,\n );\n }\n if (operationId) this.selectedProtocolVersion = PROTOCOL_VERSION;\n if (!operationId) return payload;\n return parseResponse(operationId, payload);\n } catch (error) {\n if (error instanceof BridgeHttpError) throw error;\n if (error instanceof ContractResponseError) {\n throw new BridgeHttpError(error.status, error.code, undefined, {\n operation: error.operation,\n issues: error.issues,\n }, error.message);\n }\n if (this.closed) throw new BridgeHttpError(0, \"store_closed\");\n if (options.signal?.aborted) throw new BridgeHttpError(0, \"request_cancelled\");\n if (timedOut) throw new BridgeHttpError(504, \"request_timeout\");\n if (error instanceof Error && (error.name === \"TimeoutError\" || error.name === \"AbortError\")) {\n throw new BridgeHttpError(504, \"request_timeout\");\n }\n throw new BridgeHttpError(0, \"network_error\");\n } finally {\n clearTimeout(timeout);\n this.closeController.signal.removeEventListener(\"abort\", abort);\n options.signal?.removeEventListener(\"abort\", abortRequest);\n }\n }\n\n private ensureProtocol(signal?: AbortSignal): Promise<string> {\n if (this.selectedProtocolVersion) return Promise.resolve(this.selectedProtocolVersion);\n if (!this.protocolProbe) {\n this.protocolProbe = this.request(\"status\", \"/v2/status\", { signal, skipProtocolProbe: true })\n .then(() => this.selectedProtocolVersion!)\n .finally(() => { this.protocolProbe = undefined; });\n }\n return this.protocolProbe;\n }\n async capabilities(): Promise<unknown> { return this.request(\"capabilities\", \"/v2/capabilities\"); }\n\n private assertPrincipal(principal: BridgePrincipal, includeInstance = true): void {\n const expected = this.options.principal;\n if (\n principal.workspace !== expected.workspace ||\n principal.agent !== expected.agent ||\n (includeInstance && principal.instance !== expected.instance)\n ) {\n throw new BridgeHttpError(403, \"principal_mismatch\");\n }\n }\n\n async insertMessage(message: Omit<BridgeMessage, \"sequence\" | \"createdAt\">, options: { signal?: AbortSignal } = {}): Promise<InsertMessageResult> {\n this.assertPrincipal({ workspace: message.workspace, agent: message.source }, false);\n await this.ensureProtocol(options.signal);\n const { workspace: _workspace, source: _source, ...draft } = message;\n return this.request(\"publish_message\", \"/v2/messages\", { method: \"POST\", body: draft, signal: options.signal });\n }\n async listMessages(principal: BridgePrincipal, query: MessageQuery = {}, options: { signal?: AbortSignal } = {}): Promise<MessagePage> {\n this.assertPrincipal(principal);\n const requestQuery = query;\n const params = new URLSearchParams();\n if (requestQuery.cursor) params.set(\"cursor\", requestQuery.cursor);\n if (requestQuery.mailbox) params.set(\"mailbox\", requestQuery.mailbox);\n if (requestQuery.receiptState) params.set(\"receiptState\", requestQuery.receiptState);\n if (requestQuery.limit) params.set(\"limit\", String(requestQuery.limit));\n if (requestQuery.includeExpired) params.set(\"includeExpired\", \"true\");\n if (requestQuery.source) params.set(\"source\", requestQuery.source);\n if (requestQuery.project) params.set(\"project\", requestQuery.project);\n if (requestQuery.since) params.set(\"since\", requestQuery.since);\n if (requestQuery.threadId) params.set(\"threadId\", requestQuery.threadId);\n if (requestQuery.latest) params.set(\"latest\", \"true\");\n for (const type of requestQuery.types ?? []) params.append(\"type\", type);\n return this.request(\"history\", `/v2/history${params.size ? `?${params}` : \"\"}`, { signal: options.signal });\n }\n async recordReceipt(principal: BridgePrincipal, ids: string[]): Promise<number> {\n this.assertPrincipal(principal, false);\n return (await this.request(\"record_receipt\", \"/v2/receipts\", { method: \"POST\", body: { messageIds: ids } })).recorded;\n }\n async diagnostics(principal: BridgePrincipal): Promise<BridgeDiagnostics> {\n this.assertPrincipal(principal);\n const status = await this.request(\"status\", \"/v2/status\");\n this.assertBoundPrincipal(status);\n return status;\n }\n async claimDelivery(principal: BridgePrincipal, options: ClaimOptions): Promise<BridgeDelivery | null> {\n this.assertPrincipal(principal);\n return (await this.request(\"claim_delivery\", \"/v2/deliveries/claim\", { method: \"POST\", body: options }))?.delivery ?? null;\n }\n async listDeliveries(principal: BridgePrincipal, query: import(\"./bridge-store.js\").DeliveryQuery = {}) {\n this.assertPrincipal(principal); const params=new URLSearchParams(); if(query.cursor)params.set(\"cursor\",query.cursor);if(query.limit)params.set(\"limit\",String(query.limit));if(query.role)params.set(\"role\",query.role);if(query.messageId)params.set(\"messageId\",query.messageId);if(query.recipient)params.set(\"recipient\",query.recipient);for(const state of query.states??[])params.append(\"state\",state);return this.request(\"list_deliveries\",`/v2/deliveries${params.size?`?${params}`:\"\"}`);\n }\n async listDeliveryEvents(principal: BridgePrincipal,id:string,query:{cursor?:string;limit?:number}={}) { this.assertPrincipal(principal);const params=new URLSearchParams();if(query.cursor)params.set(\"cursor\",query.cursor);if(query.limit)params.set(\"limit\",String(query.limit));return this.request(\"list_delivery_events\",`/v2/deliveries/${id}/events${params.size?`?${params}`:\"\"}`); }\n async cancelDelivery(principal:BridgePrincipal,id:string){this.assertPrincipal(principal);return (await this.request(\"cancel_delivery\",`/v2/deliveries/${id}/cancel`,{method:\"POST\",body:{}})).delivery;}\n async requeueDelivery(principal:BridgePrincipal,id:string){this.assertPrincipal(principal);return (await this.request(\"requeue_delivery\",`/v2/deliveries/${id}/requeue`,{method:\"POST\",body:{}})).delivery;}\n async renewDelivery(principal: BridgePrincipal, id: string, token: string, leaseMs: number): Promise<BridgeDelivery | null> {\n this.assertPrincipal(principal);\n try {\n return (await this.request(\"extend_delivery\", `/v2/deliveries/${id}/extend`, { method: \"POST\", body: { leaseToken: token, leaseMs } })).delivery;\n } catch (error) {\n if (error instanceof BridgeHttpError && error.status === 409) return null;\n throw error;\n }\n }\n async settleDelivery(principal: BridgePrincipal, id: string, token: string, state: \"acked\" | \"retrying\" | \"dead\", error?: string, _retryPolicy?: import(\"./bridge-domain.js\").RetryPolicy): Promise<BridgeDelivery | null> {\n this.assertPrincipal(principal);\n await this.ensureProtocol();\n const action = state === \"acked\" ? \"ack\" : \"nack\";\n try {\n const operationId = action === \"ack\" ? \"acknowledge_delivery\" : \"negative_acknowledge_delivery\";\n const nackBody = { leaseToken: token, error, disposition: state === \"dead\" ? \"dead\" : \"retry\" };\n return (await this.request(operationId, `/v2/deliveries/${id}/${action}`, { method: \"POST\", body: action === \"ack\" ? { leaseToken: token } : nackBody })).delivery;\n } catch (caught) {\n if (caught instanceof BridgeHttpError && caught.status === 409) return null;\n throw caught;\n }\n }\n async heartbeat(principal: BridgePrincipal, leaseMs: number, runtimeType?: string, capabilities: string[] = []): Promise<AgentPresence> {\n this.assertPrincipal(principal);\n return this.request(\"heartbeat\", \"/v2/presence/heartbeat\", { method: \"POST\", body: { leaseMs, runtimeType, capabilities } });\n }\n async listPresence(principal: BridgePrincipal): Promise<AgentPresence[]> {\n this.assertPrincipal(principal);\n return (await this.request(\"presence\", \"/v2/presence\")).agents;\n }\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n this.closeController.abort(new Error(\"store closed\"));\n }\n}\n"],"mappings":";;;;;;;;;;;AAqBO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EACzC,YACW,QACA,MACA,WACA,SACT,UAAU,gCAAgC,IAAI,IAC9C;AACA,UAAM,OAAO;AANJ;AACA;AACA;AACA;AAAA,EAIX;AACF;AAEO,IAAM,kBAAN,MAA6C;AAAA,EAMlD,YAA6B,SAAiC;AAAjC;AAJ7B,SAAiB,kBAAkB,IAAI,gBAAgB;AACvD,SAAQ,SAAS;AAIf,UAAM,MAAM,IAAI,IAAI,QAAQ,OAAO;AACnC,UAAM,WAAW,IAAI,aAAa,eAAe,IAAI,aAAa,eAAe,IAAI,aAAa;AAClG,QAAI,IAAI,aAAa,YAAY,EAAE,IAAI,aAAa,WAAW,aAAa,CAAC,QAAQ,yBAAyB;AAC5G,YAAM,IAAI,MAAM,uDAAuD;AAAA,IACzE;AACA,SAAK,YAAY,QAAQ,SAAS;AAAA,EACpC;AAAA,EACA,MAAM,WAAW,UAAiE,CAAC,GAAkB;AACnG,QAAI,QAAQ,SAAS,UAAW;AAChC,UAAM,KAAK,QAAQ,QAAW,WAAW,EAAE,eAAe,OAAO,QAAQ,QAAQ,OAAO,CAAC;AACzF,UAAM,SAAS,MAAM,KAAK,QAAQ,UAAU,cAAc,EAAE,QAAQ,QAAQ,OAAO,CAAC;AACpF,SAAK,qBAAqB,MAAM;AAAA,EAClC;AAAA,EAEQ,qBAAqB,QAAmB;AAC9C,UAAM,YAAY,QAAQ;AAC1B,QACE,CAAC,aACD,UAAU,cAAc,KAAK,QAAQ,UAAU,aAC/C,UAAU,UAAU,KAAK,QAAQ,UAAU,OAC3C;AACA,YAAM,IAAI,gBAAgB,KAAK,oBAAoB;AAAA,IACrD;AAAA,EACF;AAAA,EAEA,MAAc,QAAQ,aAAsC,MAAc,UAA2H,CAAC,GAAiB;AACrN,QAAI,QAAQ,WAAW,UAAU,CAAC,QAAQ,kBAAmB,OAAM,KAAK,eAAe,QAAQ,MAAM;AACrG,QAAI,KAAK,OAAQ,OAAM,IAAI,gBAAgB,GAAG,cAAc;AAC5D,QAAI,QAAQ,QAAQ,QAAS,OAAM,IAAI,gBAAgB,GAAG,mBAAmB;AAC7E,UAAM,oBAAoB,IAAI,gBAAgB;AAC9C,UAAM,QAAQ,MAAM,kBAAkB,MAAM,KAAK,gBAAgB,OAAO,MAAM;AAC9E,UAAM,eAAe,MAAM,kBAAkB,MAAM,QAAQ,QAAQ,MAAM;AACzE,SAAK,gBAAgB,OAAO,iBAAiB,SAAS,OAAO,EAAE,MAAM,KAAK,CAAC;AAC3E,YAAQ,QAAQ,iBAAiB,SAAS,cAAc,EAAE,MAAM,KAAK,CAAC;AACtE,QAAI,WAAW;AACf,UAAM,UAAU,WAAW,MAAM;AAC/B,iBAAW;AACX,wBAAkB,MAAM,IAAI,MAAM,iBAAiB,CAAC;AAAA,IACtD,GAAG,KAAK,QAAQ,aAAa,GAAM;AACnC,YAAQ,QAAQ;AAChB,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,UAAU,GAAG,KAAK,QAAQ,QAAQ,QAAQ,OAAO,EAAE,CAAC,GAAG,IAAI,IAAI;AAAA,QACzF,QAAQ,QAAQ,UAAU;AAAA,QAAO,QAAQ,kBAAkB;AAAA,QAC3D,SAAS;AAAA,UACP,CAAC,eAAe,GAAG,KAAK,2BAA2B;AAAA,UACnD,GAAI,QAAQ,kBAAkB,QAAQ,CAAC,IAAI,EAAE,eAAe,UAAU,KAAK,QAAQ,KAAK,GAAG;AAAA,UAC3F,GAAI,KAAK,QAAQ,UAAU,WAAW,EAAE,2BAA2B,KAAK,QAAQ,UAAU,SAAS,IAAI,CAAC;AAAA,UACxG,GAAI,QAAQ,SAAS,SAAY,CAAC,IAAI,EAAE,gBAAgB,mBAAmB;AAAA,QAC7E;AAAA,QACA,MAAM,QAAQ,SAAS,SAAY,SAAY,KAAK,UAAU,QAAQ,IAAI;AAAA,MAC5E,CAAC;AACD,YAAM,YAAY,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC1D,YAAM,iBAAiB,SAAS,QAAQ,IAAI,eAAe;AAC3D,YAAM,kBAAkB,SAAS,QAAQ,IAAI,yBAAyB;AACtE,YAAM,qBAAqB,iBAAiB,MAAM,GAAG,EAAE,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAAE,OAAO,OAAO,KAAK,CAAC;AACxG,YAAM,uBACJ,mBAAmB,QAAQ,oBAAoB,QAC/C,CAAE,4BAAkD,SAAS,cAAc,KAC3E,CAAC,mBAAmB,SAAS,cAAc,KAC3C,mBAAmB;AAErB,UAAI,eAAe,sBAAsB;AACvC,cAAM,IAAI,gBAAgB,KAAK,qBAAqB,WAAW;AAAA,UAC7D,UAAU;AAAA,UACV,UAAU;AAAA,UACV,WAAW;AAAA,QACb,CAAC;AAAA,MACH;AACA,YAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC5D,YAAM,UAAU,YAAY,WAAW,kBAAkB,IACrD,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE,IACtC,MAAM,SAAS,KAAK;AACxB,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,WAAW,WAAW,OAAO,YAAY,WAAY,QAAgB,QAAQ;AACnF,cAAM,IAAI;AAAA,UACR,SAAS;AAAA,UACT,UAAU,QAAQ;AAAA,UAClB,UAAU,aAAa;AAAA,UACvB,UAAU,WAAW;AAAA,UACrB,UAAU,WAAW,gCAAgC,UAAU,QAAQ,gBAAgB;AAAA,QACzF;AAAA,MACF;AACA,UAAI,YAAa,MAAK,0BAA0B;AAChD,UAAI,CAAC,YAAa,QAAO;AACzB,aAAO,cAAc,aAAa,OAAO;AAAA,IAC3C,SAAS,OAAO;AACd,UAAI,iBAAiB,gBAAiB,OAAM;AAC5C,UAAI,iBAAiB,uBAAuB;AAC1C,cAAM,IAAI,gBAAgB,MAAM,QAAQ,MAAM,MAAM,QAAW;AAAA,UAC7D,WAAW,MAAM;AAAA,UACjB,QAAQ,MAAM;AAAA,QAChB,GAAG,MAAM,OAAO;AAAA,MAClB;AACA,UAAI,KAAK,OAAQ,OAAM,IAAI,gBAAgB,GAAG,cAAc;AAC5D,UAAI,QAAQ,QAAQ,QAAS,OAAM,IAAI,gBAAgB,GAAG,mBAAmB;AAC7E,UAAI,SAAU,OAAM,IAAI,gBAAgB,KAAK,iBAAiB;AAC9D,UAAI,iBAAiB,UAAU,MAAM,SAAS,kBAAkB,MAAM,SAAS,eAAe;AAC5F,cAAM,IAAI,gBAAgB,KAAK,iBAAiB;AAAA,MAClD;AACA,YAAM,IAAI,gBAAgB,GAAG,eAAe;AAAA,IAC9C,UAAE;AACA,mBAAa,OAAO;AACpB,WAAK,gBAAgB,OAAO,oBAAoB,SAAS,KAAK;AAC9D,cAAQ,QAAQ,oBAAoB,SAAS,YAAY;AAAA,IAC3D;AAAA,EACF;AAAA,EAEQ,eAAe,QAAuC;AAC5D,QAAI,KAAK,wBAAyB,QAAO,QAAQ,QAAQ,KAAK,uBAAuB;AACrF,QAAI,CAAC,KAAK,eAAe;AACvB,WAAK,gBAAgB,KAAK,QAAQ,UAAU,cAAc,EAAE,QAAQ,mBAAmB,KAAK,CAAC,EAC1F,KAAK,MAAM,KAAK,uBAAwB,EACxC,QAAQ,MAAM;AAAE,aAAK,gBAAgB;AAAA,MAAW,CAAC;AAAA,IACtD;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EACA,MAAM,eAAiC;AAAE,WAAO,KAAK,QAAQ,gBAAgB,kBAAkB;AAAA,EAAG;AAAA,EAE1F,gBAAgB,WAA4B,kBAAkB,MAAY;AAChF,UAAM,WAAW,KAAK,QAAQ;AAC9B,QACE,UAAU,cAAc,SAAS,aACjC,UAAU,UAAU,SAAS,SAC5B,mBAAmB,UAAU,aAAa,SAAS,UACpD;AACA,YAAM,IAAI,gBAAgB,KAAK,oBAAoB;AAAA,IACrD;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,SAAwD,UAAoC,CAAC,GAAiC;AAChJ,SAAK,gBAAgB,EAAE,WAAW,QAAQ,WAAW,OAAO,QAAQ,OAAO,GAAG,KAAK;AACnF,UAAM,KAAK,eAAe,QAAQ,MAAM;AACxC,UAAM,EAAE,WAAW,YAAY,QAAQ,SAAS,GAAG,MAAM,IAAI;AAC7D,WAAO,KAAK,QAAQ,mBAAmB,gBAAgB,EAAE,QAAQ,QAAQ,MAAM,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAAA,EAChH;AAAA,EACA,MAAM,aAAa,WAA4B,QAAsB,CAAC,GAAG,UAAoC,CAAC,GAAyB;AACrI,SAAK,gBAAgB,SAAS;AAC9B,UAAM,eAAe;AACrB,UAAM,SAAS,IAAI,gBAAgB;AACnC,QAAI,aAAa,OAAQ,QAAO,IAAI,UAAU,aAAa,MAAM;AACjE,QAAI,aAAa,QAAS,QAAO,IAAI,WAAW,aAAa,OAAO;AACpE,QAAI,aAAa,aAAc,QAAO,IAAI,gBAAgB,aAAa,YAAY;AACnF,QAAI,aAAa,MAAO,QAAO,IAAI,SAAS,OAAO,aAAa,KAAK,CAAC;AACtE,QAAI,aAAa,eAAgB,QAAO,IAAI,kBAAkB,MAAM;AACpE,QAAI,aAAa,OAAQ,QAAO,IAAI,UAAU,aAAa,MAAM;AACjE,QAAI,aAAa,QAAS,QAAO,IAAI,WAAW,aAAa,OAAO;AACpE,QAAI,aAAa,MAAO,QAAO,IAAI,SAAS,aAAa,KAAK;AAC9D,QAAI,aAAa,SAAU,QAAO,IAAI,YAAY,aAAa,QAAQ;AACvE,QAAI,aAAa,OAAQ,QAAO,IAAI,UAAU,MAAM;AACpD,eAAW,QAAQ,aAAa,SAAS,CAAC,EAAG,QAAO,OAAO,QAAQ,IAAI;AACvE,WAAO,KAAK,QAAQ,WAAW,cAAc,OAAO,OAAO,IAAI,MAAM,KAAK,EAAE,IAAI,EAAE,QAAQ,QAAQ,OAAO,CAAC;AAAA,EAC5G;AAAA,EACA,MAAM,cAAc,WAA4B,KAAgC;AAC9E,SAAK,gBAAgB,WAAW,KAAK;AACrC,YAAQ,MAAM,KAAK,QAAQ,kBAAkB,gBAAgB,EAAE,QAAQ,QAAQ,MAAM,EAAE,YAAY,IAAI,EAAE,CAAC,GAAG;AAAA,EAC/G;AAAA,EACA,MAAM,YAAY,WAAwD;AACxE,SAAK,gBAAgB,SAAS;AAC9B,UAAM,SAAS,MAAM,KAAK,QAAQ,UAAU,YAAY;AACxD,SAAK,qBAAqB,MAAM;AAChC,WAAO;AAAA,EACT;AAAA,EACA,MAAM,cAAc,WAA4B,SAAuD;AACrG,SAAK,gBAAgB,SAAS;AAC9B,YAAQ,MAAM,KAAK,QAAQ,kBAAkB,wBAAwB,EAAE,QAAQ,QAAQ,MAAM,QAAQ,CAAC,IAAI,YAAY;AAAA,EACxH;AAAA,EACA,MAAM,eAAe,WAA4B,QAAmD,CAAC,GAAG;AACtG,SAAK,gBAAgB,SAAS;AAAG,UAAM,SAAO,IAAI,gBAAgB;AAAG,QAAG,MAAM,OAAO,QAAO,IAAI,UAAS,MAAM,MAAM;AAAE,QAAG,MAAM,MAAM,QAAO,IAAI,SAAQ,OAAO,MAAM,KAAK,CAAC;AAAE,QAAG,MAAM,KAAK,QAAO,IAAI,QAAO,MAAM,IAAI;AAAE,QAAG,MAAM,UAAU,QAAO,IAAI,aAAY,MAAM,SAAS;AAAE,QAAG,MAAM,UAAU,QAAO,IAAI,aAAY,MAAM,SAAS;AAAE,eAAU,SAAS,MAAM,UAAQ,CAAC,EAAE,QAAO,OAAO,SAAQ,KAAK;AAAE,WAAO,KAAK,QAAQ,mBAAkB,iBAAiB,OAAO,OAAK,IAAI,MAAM,KAAG,EAAE,EAAE;AAAA,EACve;AAAA,EACA,MAAM,mBAAmB,WAA2B,IAAU,QAAqC,CAAC,GAAG;AAAE,SAAK,gBAAgB,SAAS;AAAE,UAAM,SAAO,IAAI,gBAAgB;AAAE,QAAG,MAAM,OAAO,QAAO,IAAI,UAAS,MAAM,MAAM;AAAE,QAAG,MAAM,MAAM,QAAO,IAAI,SAAQ,OAAO,MAAM,KAAK,CAAC;AAAE,WAAO,KAAK,QAAQ,wBAAuB,kBAAkB,EAAE,UAAU,OAAO,OAAK,IAAI,MAAM,KAAG,EAAE,EAAE;AAAA,EAAG;AAAA,EAC9X,MAAM,eAAe,WAA0B,IAAU;AAAC,SAAK,gBAAgB,SAAS;AAAE,YAAQ,MAAM,KAAK,QAAQ,mBAAkB,kBAAkB,EAAE,WAAU,EAAC,QAAO,QAAO,MAAK,CAAC,EAAC,CAAC,GAAG;AAAA,EAAS;AAAA,EACxM,MAAM,gBAAgB,WAA0B,IAAU;AAAC,SAAK,gBAAgB,SAAS;AAAE,YAAQ,MAAM,KAAK,QAAQ,oBAAmB,kBAAkB,EAAE,YAAW,EAAC,QAAO,QAAO,MAAK,CAAC,EAAC,CAAC,GAAG;AAAA,EAAS;AAAA,EAC3M,MAAM,cAAc,WAA4B,IAAY,OAAe,SAAiD;AAC1H,SAAK,gBAAgB,SAAS;AAC9B,QAAI;AACF,cAAQ,MAAM,KAAK,QAAQ,mBAAmB,kBAAkB,EAAE,WAAW,EAAE,QAAQ,QAAQ,MAAM,EAAE,YAAY,OAAO,QAAQ,EAAE,CAAC,GAAG;AAAA,IAC1I,SAAS,OAAO;AACd,UAAI,iBAAiB,mBAAmB,MAAM,WAAW,IAAK,QAAO;AACrE,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EACA,MAAM,eAAe,WAA4B,IAAY,OAAe,OAAsC,OAAgB,cAAyF;AACzN,SAAK,gBAAgB,SAAS;AAC9B,UAAM,KAAK,eAAe;AAC1B,UAAM,SAAS,UAAU,UAAU,QAAQ;AAC3C,QAAI;AACF,YAAM,cAAc,WAAW,QAAQ,yBAAyB;AAChE,YAAM,WAAW,EAAE,YAAY,OAAO,OAAO,aAAa,UAAU,SAAS,SAAS,QAAQ;AAC9F,cAAQ,MAAM,KAAK,QAAQ,aAAa,kBAAkB,EAAE,IAAI,MAAM,IAAI,EAAE,QAAQ,QAAQ,MAAM,WAAW,QAAQ,EAAE,YAAY,MAAM,IAAI,SAAS,CAAC,GAAG;AAAA,IAC5J,SAAS,QAAQ;AACf,UAAI,kBAAkB,mBAAmB,OAAO,WAAW,IAAK,QAAO;AACvE,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EACA,MAAM,UAAU,WAA4B,SAAiB,aAAsB,eAAyB,CAAC,GAA2B;AACtI,SAAK,gBAAgB,SAAS;AAC9B,WAAO,KAAK,QAAQ,aAAa,0BAA0B,EAAE,QAAQ,QAAQ,MAAM,EAAE,SAAS,aAAa,aAAa,EAAE,CAAC;AAAA,EAC7H;AAAA,EACA,MAAM,aAAa,WAAsD;AACvE,SAAK,gBAAgB,SAAS;AAC9B,YAAQ,MAAM,KAAK,QAAQ,YAAY,cAAc,GAAG;AAAA,EAC1D;AAAA,EACA,MAAM,QAAuB;AAC3B,QAAI,KAAK,OAAQ;AACjB,SAAK,SAAS;AACd,SAAK,gBAAgB,MAAM,IAAI,MAAM,cAAc,CAAC;AAAA,EACtD;AACF;","names":[]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/package-metadata.ts
|
|
4
|
+
import { readFileSync } from "fs";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
function packageVersion() {
|
|
7
|
+
const manifest = JSON.parse(
|
|
8
|
+
readFileSync(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8")
|
|
9
|
+
);
|
|
10
|
+
if (typeof manifest.version !== "string" || !manifest.version) {
|
|
11
|
+
throw new Error("package version is unavailable");
|
|
12
|
+
}
|
|
13
|
+
return manifest.version;
|
|
14
|
+
}
|
|
15
|
+
function buildRevision(value) {
|
|
16
|
+
if (value === void 0 || value === "") return void 0;
|
|
17
|
+
if (!/^[0-9a-f]{7,40}$/u.test(value)) {
|
|
18
|
+
throw new Error("AGENT_BRIDGE_BUILD_REVISION must be a lowercase Git commit hash");
|
|
19
|
+
}
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
packageVersion,
|
|
25
|
+
buildRevision
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=chunk-7B3XRRNI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/package-metadata.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\n\nexport function packageVersion(): string {\n const manifest = JSON.parse(\n readFileSync(fileURLToPath(new URL(\"../package.json\", import.meta.url)), \"utf8\"),\n ) as { version?: unknown };\n if (typeof manifest.version !== \"string\" || !manifest.version) {\n throw new Error(\"package version is unavailable\");\n }\n return manifest.version;\n}\n\nexport function buildRevision(value: string | undefined): string | undefined {\n if (value === undefined || value === \"\") return undefined;\n if (!/^[0-9a-f]{7,40}$/u.test(value)) {\n throw new Error(\"AGENT_BRIDGE_BUILD_REVISION must be a lowercase Git commit hash\");\n }\n return value;\n}\n"],"mappings":";;;AAAA,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAEvB,SAAS,iBAAyB;AACvC,QAAM,WAAW,KAAK;AAAA,IACpB,aAAa,cAAc,IAAI,IAAI,mBAAmB,YAAY,GAAG,CAAC,GAAG,MAAM;AAAA,EACjF;AACA,MAAI,OAAO,SAAS,YAAY,YAAY,CAAC,SAAS,SAAS;AAC7D,UAAM,IAAI,MAAM,gCAAgC;AAAA,EAClD;AACA,SAAO,SAAS;AAClB;AAEO,SAAS,cAAc,OAA+C;AAC3E,MAAI,UAAU,UAAa,UAAU,GAAI,QAAO;AAChD,MAAI,CAAC,oBAAoB,KAAK,KAAK,GAAG;AACpC,UAAM,IAAI,MAAM,iEAAiE;AAAA,EACnF;AACA,SAAO;AACT;","names":[]}
|
|
@@ -1301,21 +1301,24 @@ async function collectPostgresRoleInventory(client, databaseName) {
|
|
|
1301
1301
|
CROSS JOIN LATERAL pg_catalog.aclexplode(type.typacl) acl WHERE namespace.nspname='agent_bridge' AND acl.grantee<>0
|
|
1302
1302
|
UNION SELECT defaults.defaclrole, 'object-role' FROM pg_catalog.pg_default_acl defaults
|
|
1303
1303
|
LEFT JOIN pg_catalog.pg_namespace namespace ON namespace.oid=defaults.defaclnamespace
|
|
1304
|
-
WHERE namespace.nspname='agent_bridge' OR
|
|
1305
|
-
|
|
1304
|
+
WHERE namespace.nspname='agent_bridge' OR (
|
|
1305
|
+
defaults.defaclnamespace=0 AND defaults.defaclrole=(
|
|
1306
|
+
SELECT nspowner FROM pg_catalog.pg_namespace WHERE nspname='agent_bridge'))
|
|
1306
1307
|
OR (defaults.defaclnamespace=0 AND defaults.defaclrole=(SELECT oid FROM pg_catalog.pg_roles
|
|
1307
1308
|
WHERE rolname='agent_bridge_control_owner_'||substr(pg_catalog.md5(pg_catalog.current_database()),1,16)))
|
|
1308
1309
|
UNION SELECT acl.grantor, 'object-role' FROM pg_catalog.pg_default_acl defaults
|
|
1309
1310
|
LEFT JOIN pg_catalog.pg_namespace namespace ON namespace.oid=defaults.defaclnamespace
|
|
1310
1311
|
CROSS JOIN LATERAL pg_catalog.aclexplode(defaults.defaclacl) acl WHERE namespace.nspname='agent_bridge'
|
|
1311
|
-
OR defaults.
|
|
1312
|
+
OR (defaults.defaclnamespace=0 AND defaults.defaclrole=(
|
|
1313
|
+
SELECT nspowner FROM pg_catalog.pg_namespace WHERE nspname='agent_bridge'))
|
|
1312
1314
|
OR (defaults.defaclnamespace=0 AND defaults.defaclrole=(SELECT oid FROM pg_catalog.pg_roles
|
|
1313
1315
|
WHERE rolname='agent_bridge_control_owner_'||substr(pg_catalog.md5(pg_catalog.current_database()),1,16)))
|
|
1314
1316
|
UNION SELECT acl.grantee, 'object-role' FROM pg_catalog.pg_default_acl defaults
|
|
1315
1317
|
LEFT JOIN pg_catalog.pg_namespace namespace ON namespace.oid=defaults.defaclnamespace
|
|
1316
1318
|
CROSS JOIN LATERAL pg_catalog.aclexplode(defaults.defaclacl) acl WHERE acl.grantee<>0 AND (
|
|
1317
|
-
namespace.nspname='agent_bridge' OR
|
|
1318
|
-
|
|
1319
|
+
namespace.nspname='agent_bridge' OR (
|
|
1320
|
+
defaults.defaclnamespace=0 AND defaults.defaclrole=(
|
|
1321
|
+
SELECT nspowner FROM pg_catalog.pg_namespace WHERE nspname='agent_bridge'))
|
|
1319
1322
|
OR (defaults.defaclnamespace=0 AND defaults.defaclrole=(SELECT oid FROM pg_catalog.pg_roles
|
|
1320
1323
|
WHERE rolname='agent_bridge_control_owner_'||substr(pg_catalog.md5(pg_catalog.current_database()),1,16))))
|
|
1321
1324
|
), base_roles AS (
|
|
@@ -1325,12 +1328,19 @@ async function collectPostgresRoleInventory(client, databaseName) {
|
|
|
1325
1328
|
UNION
|
|
1326
1329
|
SELECT role.oid, 'derived' FROM pg_catalog.pg_roles role
|
|
1327
1330
|
WHERE role.rolname IN (SELECT name FROM derived_names)
|
|
1331
|
+
), canonical_base_roles AS (
|
|
1332
|
+
SELECT oid, CASE WHEN bool_or(kind='schema-owner') THEN 'schema-owner'
|
|
1333
|
+
WHEN bool_or(kind='derived') THEN 'derived'
|
|
1334
|
+
ELSE 'object-role' END AS kind
|
|
1335
|
+
FROM base_roles GROUP BY oid
|
|
1328
1336
|
), related_roles AS (
|
|
1329
|
-
SELECT oid, kind FROM
|
|
1337
|
+
SELECT oid, kind FROM canonical_base_roles
|
|
1330
1338
|
UNION SELECT membership.roleid, 'external-principal' FROM pg_catalog.pg_auth_members membership
|
|
1331
|
-
WHERE membership.member IN (
|
|
1339
|
+
WHERE membership.member IN (
|
|
1340
|
+
SELECT oid FROM canonical_base_roles WHERE kind<>'schema-owner')
|
|
1332
1341
|
UNION SELECT membership.member, 'external-principal' FROM pg_catalog.pg_auth_members membership
|
|
1333
|
-
WHERE membership.roleid IN (
|
|
1342
|
+
WHERE membership.roleid IN (
|
|
1343
|
+
SELECT oid FROM canonical_base_roles WHERE kind<>'schema-owner')
|
|
1334
1344
|
)
|
|
1335
1345
|
SELECT role.rolname AS name,
|
|
1336
1346
|
CASE WHEN bool_or(related.kind='schema-owner') THEN 'schema-owner'
|
|
@@ -1340,6 +1350,7 @@ async function collectPostgresRoleInventory(client, databaseName) {
|
|
|
1340
1350
|
FROM related_roles related JOIN pg_catalog.pg_roles role ON role.oid=related.oid
|
|
1341
1351
|
GROUP BY role.rolname ORDER BY role.rolname`);
|
|
1342
1352
|
const names = roleRows.rows.map((row) => row.name);
|
|
1353
|
+
const schemaOwnerNames = roleRows.rows.filter((row) => row.kind === "schema-owner").map((row) => row.name);
|
|
1343
1354
|
const membershipRows = names.length === 0 ? { rows: [], rowCount: 0 } : await client.query(`
|
|
1344
1355
|
SELECT granted.rolname AS role, member.rolname AS member,
|
|
1345
1356
|
bool_or(membership.admin_option) AS "adminOption",
|
|
@@ -1353,15 +1364,21 @@ async function collectPostgresRoleInventory(client, databaseName) {
|
|
|
1353
1364
|
ORDER BY granted.rolname,member.rolname`, [names]);
|
|
1354
1365
|
if (names.length > 0) {
|
|
1355
1366
|
const boundary = await client.query(`
|
|
1356
|
-
SELECT
|
|
1367
|
+
SELECT granted.rolname AS role, member.rolname AS member
|
|
1368
|
+
FROM pg_catalog.pg_auth_members membership
|
|
1357
1369
|
JOIN pg_catalog.pg_roles granted ON granted.oid=membership.roleid
|
|
1358
1370
|
JOIN pg_catalog.pg_roles member ON member.oid=membership.member
|
|
1359
1371
|
WHERE (granted.rolname=ANY($1::text[])) <> (member.rolname=ANY($1::text[]))
|
|
1360
|
-
|
|
1372
|
+
AND NOT (
|
|
1373
|
+
granted.rolname=ANY($1::text[]) AND granted.rolname=ANY($2::text[])
|
|
1374
|
+
OR member.rolname=ANY($1::text[]) AND member.rolname=ANY($2::text[])
|
|
1375
|
+
)
|
|
1376
|
+
ORDER BY granted.rolname,member.rolname LIMIT 10`, [names, schemaOwnerNames]);
|
|
1361
1377
|
if (boundary.rows.length > 0) {
|
|
1362
1378
|
throw new PostgresNativeDrError(
|
|
1363
1379
|
"TRANSITIVE_ROLE_MEMBERSHIP_UNSUPPORTED",
|
|
1364
|
-
"PostgreSQL role inventory has a transitive external membership outside the bounded restore graph"
|
|
1380
|
+
"PostgreSQL role inventory has a transitive external membership outside the bounded restore graph",
|
|
1381
|
+
{ roleMemberships: boundary.rows }
|
|
1365
1382
|
);
|
|
1366
1383
|
}
|
|
1367
1384
|
}
|
|
@@ -1380,8 +1397,9 @@ async function collectPostgresRoleInventory(client, databaseName) {
|
|
|
1380
1397
|
LEFT JOIN LATERAL pg_catalog.aclexplode(defaults.defaclacl) acl ON true
|
|
1381
1398
|
LEFT JOIN pg_catalog.pg_roles grantor ON grantor.oid=acl.grantor
|
|
1382
1399
|
LEFT JOIN pg_catalog.pg_roles grantee ON grantee.oid=acl.grantee
|
|
1383
|
-
WHERE namespace.nspname='agent_bridge' OR
|
|
1384
|
-
|
|
1400
|
+
WHERE namespace.nspname='agent_bridge' OR (
|
|
1401
|
+
defaults.defaclnamespace=0 AND defaults.defaclrole=(
|
|
1402
|
+
SELECT nspowner FROM pg_catalog.pg_namespace WHERE nspname='agent_bridge'))
|
|
1385
1403
|
OR (defaults.defaclnamespace=0 AND defaults.defaclrole=(SELECT oid FROM pg_catalog.pg_roles
|
|
1386
1404
|
WHERE rolname='agent_bridge_control_owner_'||substr(pg_catalog.md5(pg_catalog.current_database()),1,16)))
|
|
1387
1405
|
ORDER BY owner.rolname,namespace.nspname NULLS FIRST,defaults.defaclobjtype,
|
|
@@ -2668,4 +2686,4 @@ export {
|
|
|
2668
2686
|
restoreLocalSqlite,
|
|
2669
2687
|
SQLITE_EDGE_APPLICATION_ID
|
|
2670
2688
|
};
|
|
2671
|
-
//# sourceMappingURL=chunk-
|
|
2689
|
+
//# sourceMappingURL=chunk-IF5OKPBK.js.map
|