@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.
- package/CHANGELOG.md +86 -4
- package/README.md +567 -55
- package/ROADMAP.md +114 -0
- package/SECURITY.md +90 -0
- package/SKILL.md +68 -2
- package/bin/agent-bridge +2 -2
- package/clients/claude-desktop.json +3 -1
- package/dist/archive.d.ts +163 -0
- package/dist/archive.js +50 -0
- package/dist/archive.js.map +1 -0
- package/dist/bridge-domain-CBX3IVqC.d.ts +153 -0
- package/dist/{bridge-service-CfqMcMAn.d.ts → bridge-service-hX1ZQp4W.d.ts} +15 -5
- package/dist/bridge-store-DPVSCwfs.d.ts +102 -0
- package/dist/bridge.d.ts +76 -17
- package/dist/bridge.js +52 -24
- package/dist/chunk-2DFNOLMO.js +618 -0
- package/dist/chunk-2DFNOLMO.js.map +1 -0
- package/dist/{chunk-KVR4JBRF.js → chunk-2EVLG3YA.js} +2 -2
- package/dist/{chunk-KVR4JBRF.js.map → chunk-2EVLG3YA.js.map} +1 -1
- package/dist/chunk-45BZGB77.js +709 -0
- package/dist/chunk-45BZGB77.js.map +1 -0
- package/dist/chunk-4VB44KJU.js +230 -0
- package/dist/chunk-4VB44KJU.js.map +1 -0
- package/dist/chunk-5GMB3A77.js +1013 -0
- package/dist/chunk-5GMB3A77.js.map +1 -0
- package/dist/chunk-A6W4QALF.js +1258 -0
- package/dist/chunk-A6W4QALF.js.map +1 -0
- package/dist/chunk-BZLMF5O5.js +328 -0
- package/dist/chunk-BZLMF5O5.js.map +1 -0
- package/dist/{chunk-AXL2I7FH.js → chunk-CEXBMOI5.js} +240 -79
- package/dist/chunk-CEXBMOI5.js.map +1 -0
- package/dist/chunk-GADH244D.js +527 -0
- package/dist/chunk-GADH244D.js.map +1 -0
- package/dist/chunk-MBPZXTJA.js +2428 -0
- package/dist/chunk-MBPZXTJA.js.map +1 -0
- package/dist/chunk-NCO7RLBM.js +146 -0
- package/dist/chunk-NCO7RLBM.js.map +1 -0
- package/dist/chunk-Q6PPMXJC.js +1050 -0
- package/dist/chunk-Q6PPMXJC.js.map +1 -0
- package/dist/{chunk-4KAOBC5X.js → chunk-SPSMZOCJ.js} +190 -165
- package/dist/chunk-SPSMZOCJ.js.map +1 -0
- package/dist/chunk-UAHMP6GC.js +54 -0
- package/dist/chunk-UAHMP6GC.js.map +1 -0
- package/dist/{chunk-YD6YJATN.js → chunk-VOQIDTCJ.js} +4 -2
- package/dist/chunk-VOQIDTCJ.js.map +1 -0
- package/dist/chunk-WAI2IYIQ.js +554 -0
- package/dist/chunk-WAI2IYIQ.js.map +1 -0
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +3555 -214
- 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 +10 -6
- package/dist/client-runtime.js +9 -6
- package/dist/contracts/generate.d.ts +2 -0
- package/dist/contracts/generate.js +247 -0
- package/dist/contracts/generate.js.map +1 -0
- package/dist/dr.d.ts +324 -0
- package/dist/dr.js +124 -0
- package/dist/dr.js.map +1 -0
- package/dist/gateway-CggQ8vTC.d.ts +78 -0
- package/dist/gateway-main.js +190 -8
- package/dist/gateway-main.js.map +1 -1
- package/dist/gateway.d.ts +4 -3
- package/dist/gateway.js +4 -3
- package/dist/index.js +11 -8
- package/dist/index.js.map +1 -1
- package/dist/postgres-bridge-store-Bfd3hRId.d.ts +49 -0
- package/dist/server.d.ts +3 -2
- package/dist/server.js +13 -8
- package/dist/sqlite.d.ts +94 -12
- package/dist/sqlite.js +7 -4
- package/docs/architecture-v2.md +394 -0
- package/docs/decisions/0001-protocol-layers-and-acknowledgment-semantics.md +85 -0
- package/docs/decisions/0002-canonical-operation-contract-registry.md +46 -0
- package/docs/decisions/0003-host-adapters-and-consumer-instance-keys.md +88 -0
- package/docs/ecosystem.md +86 -0
- package/docs/postmortems/2026-07-08-wrapper-source-drift.md +82 -0
- package/docs/troubleshooting.md +89 -0
- package/llms.txt +107 -6
- package/openapi/agent-bridge-v2.openapi.json +9610 -0
- package/package.json +24 -4
- package/schemas/agent-bridge-v2.capabilities.json +1829 -0
- package/schemas/agent-bridge-v2.mcp.json +2074 -0
- package/schemas/agent-bridge-v2.schema.json +4560 -0
- package/sql/migrations/008_message_projects.sql +36 -0
- package/sql/migrations/009_mailbox_query_indexes.sql +28 -0
- package/sql/migrations/010_publisher_delivery_policy.sql +210 -0
- package/sql/migrations/011_credential_security.sql +875 -0
- package/sql/migrations/012_request_authority.sql +177 -0
- package/sql/migrations/013_row_isolation.sql +495 -0
- package/sql/migrations/014_owner_control_plane.sql +1641 -0
- package/sql/migrations/015_portable_archives.sql +1813 -0
- package/sql/migrations/016_native_dr_fence.sql +1005 -0
- package/bin/CLAUDE.md +0 -11
- package/dist/bridge-domain-BcnBeHOn.d.ts +0 -97
- package/dist/bridge-store-BuGjxTn4.d.ts +0 -61
- package/dist/chunk-4KAOBC5X.js.map +0 -1
- package/dist/chunk-6MAZ6YLZ.js +0 -146
- package/dist/chunk-6MAZ6YLZ.js.map +0 -1
- package/dist/chunk-AXL2I7FH.js.map +0 -1
- package/dist/chunk-BV6W4AJK.js +0 -211
- package/dist/chunk-BV6W4AJK.js.map +0 -1
- package/dist/chunk-CKSKUBDQ.js +0 -153
- package/dist/chunk-CKSKUBDQ.js.map +0 -1
- package/dist/chunk-JOUBDRYX.js +0 -272
- package/dist/chunk-JOUBDRYX.js.map +0 -1
- package/dist/chunk-JTC5YURG.js +0 -49
- package/dist/chunk-JTC5YURG.js.map +0 -1
- package/dist/chunk-O26W5QHS.js +0 -409
- package/dist/chunk-O26W5QHS.js.map +0 -1
- package/dist/chunk-WEULPMUY.js +0 -988
- package/dist/chunk-WEULPMUY.js.map +0 -1
- package/dist/chunk-YD6YJATN.js.map +0 -1
- package/dist/gateway-BULozv3K.d.ts +0 -54
package/dist/chunk-JOUBDRYX.js
DELETED
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
BridgeService
|
|
4
|
-
} from "./chunk-CKSKUBDQ.js";
|
|
5
|
-
import {
|
|
6
|
-
BridgeValidationError
|
|
7
|
-
} from "./chunk-BV6W4AJK.js";
|
|
8
|
-
|
|
9
|
-
// src/gateway.ts
|
|
10
|
-
import { randomUUID } from "crypto";
|
|
11
|
-
import { createServer } from "http";
|
|
12
|
-
|
|
13
|
-
// src/gateway-auth.ts
|
|
14
|
-
import { createHash, timingSafeEqual } from "crypto";
|
|
15
|
-
function hashCredential(token) {
|
|
16
|
-
return createHash("sha256").update(token, "utf8").digest("hex");
|
|
17
|
-
}
|
|
18
|
-
var PostgresCredentialResolver = class {
|
|
19
|
-
constructor(db) {
|
|
20
|
-
this.db = db;
|
|
21
|
-
}
|
|
22
|
-
async resolve(token, signal) {
|
|
23
|
-
if (signal?.aborted) throw signal.reason;
|
|
24
|
-
const hash = hashCredential(token);
|
|
25
|
-
const result = await this.db.query(
|
|
26
|
-
`SELECT credential.id, credential.workspace_id, agent.principal
|
|
27
|
-
FROM agent_bridge.credentials credential
|
|
28
|
-
JOIN agent_bridge.agents agent
|
|
29
|
-
ON agent.id=credential.agent_id AND agent.workspace_id=credential.workspace_id
|
|
30
|
-
JOIN agent_bridge.workspaces workspace ON workspace.id=credential.workspace_id
|
|
31
|
-
WHERE credential.token_hash=$1 AND credential.revoked_at IS NULL
|
|
32
|
-
AND (credential.expires_at IS NULL OR credential.expires_at>now())
|
|
33
|
-
AND agent.disabled_at IS NULL AND workspace.disabled_at IS NULL
|
|
34
|
-
LIMIT 1`,
|
|
35
|
-
[hash]
|
|
36
|
-
);
|
|
37
|
-
const row = result.rows[0];
|
|
38
|
-
if (signal?.aborted) throw signal.reason;
|
|
39
|
-
return row ? { id: row.id, principal: { workspace: row.workspace_id, agent: row.principal } } : null;
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
function bearerToken(value) {
|
|
43
|
-
if (!value?.startsWith("Bearer ")) return null;
|
|
44
|
-
const token = value.slice(7);
|
|
45
|
-
if (!token || token.length > 4096 || /\s/.test(token)) return null;
|
|
46
|
-
return token;
|
|
47
|
-
}
|
|
48
|
-
function safeTokenHashEqual(token, expectedHash) {
|
|
49
|
-
const actual = Buffer.from(hashCredential(token));
|
|
50
|
-
const expected = Buffer.from(expectedHash);
|
|
51
|
-
return actual.length === expected.length && timingSafeEqual(actual, expected);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// src/gateway.ts
|
|
55
|
-
var jsonHeaders = { "content-type": "application/json; charset=utf-8", "cache-control": "no-store" };
|
|
56
|
-
function send(res, status, value, requestId) {
|
|
57
|
-
if (res.writableEnded) return;
|
|
58
|
-
res.writeHead(status, { ...jsonHeaders, "x-request-id": requestId });
|
|
59
|
-
res.end(JSON.stringify(value));
|
|
60
|
-
}
|
|
61
|
-
function failure(res, status, code, requestId) {
|
|
62
|
-
send(res, status, { error: { code, requestId } }, requestId);
|
|
63
|
-
}
|
|
64
|
-
async function body(req, limit, signal) {
|
|
65
|
-
return new Promise((resolve, reject) => {
|
|
66
|
-
const chunks = [];
|
|
67
|
-
let size = 0;
|
|
68
|
-
const cleanup = () => {
|
|
69
|
-
req.off("data", onData);
|
|
70
|
-
req.off("end", onEnd);
|
|
71
|
-
req.off("error", onError);
|
|
72
|
-
signal.removeEventListener("abort", onAbort);
|
|
73
|
-
};
|
|
74
|
-
const finish = (callback) => {
|
|
75
|
-
cleanup();
|
|
76
|
-
callback();
|
|
77
|
-
};
|
|
78
|
-
const onData = (chunk) => {
|
|
79
|
-
const buffer = Buffer.from(chunk);
|
|
80
|
-
size += buffer.length;
|
|
81
|
-
if (size > limit) {
|
|
82
|
-
finish(() => reject(Object.assign(new Error("body too large"), {
|
|
83
|
-
status: 413,
|
|
84
|
-
code: "body_too_large"
|
|
85
|
-
})));
|
|
86
|
-
req.resume();
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
chunks.push(buffer);
|
|
90
|
-
};
|
|
91
|
-
const onEnd = () => finish(() => {
|
|
92
|
-
if (!size) {
|
|
93
|
-
resolve({});
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
try {
|
|
97
|
-
const parsed = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
98
|
-
if (!parsed || Array.isArray(parsed) || typeof parsed !== "object") throw new Error();
|
|
99
|
-
resolve(parsed);
|
|
100
|
-
} catch {
|
|
101
|
-
reject(Object.assign(new Error("invalid JSON"), { status: 400, code: "malformed_json" }));
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
const onError = (error) => finish(() => reject(error));
|
|
105
|
-
const onAbort = () => {
|
|
106
|
-
finish(() => reject(signal.reason));
|
|
107
|
-
req.resume();
|
|
108
|
-
};
|
|
109
|
-
req.on("data", onData);
|
|
110
|
-
req.on("end", onEnd);
|
|
111
|
-
req.on("error", onError);
|
|
112
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
113
|
-
if (signal.aborted) onAbort();
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
function numberParam(value, name) {
|
|
117
|
-
if (value === null) return void 0;
|
|
118
|
-
const result = Number(value);
|
|
119
|
-
if (!Number.isSafeInteger(result)) throw new BridgeValidationError(`${name} is invalid`);
|
|
120
|
-
return result;
|
|
121
|
-
}
|
|
122
|
-
function active(signal) {
|
|
123
|
-
if (signal.aborted) throw signal.reason;
|
|
124
|
-
}
|
|
125
|
-
function createGateway(options) {
|
|
126
|
-
const service = new BridgeService(options.store);
|
|
127
|
-
const metrics = { requests: 0, errors: 0, timeouts: 0, authFailures: 0 };
|
|
128
|
-
const limit = options.bodyLimitBytes ?? 128 * 1024;
|
|
129
|
-
const deadline = options.requestDeadlineMs ?? 1e4;
|
|
130
|
-
const origins = new Set(options.allowedOrigins ?? []);
|
|
131
|
-
return createServer((req, res) => {
|
|
132
|
-
const requestId = randomUUID();
|
|
133
|
-
const abort = new AbortController();
|
|
134
|
-
let mutationStarted = false;
|
|
135
|
-
metrics.requests += 1;
|
|
136
|
-
const timer = setTimeout(() => {
|
|
137
|
-
abort.abort(new Error("request deadline exceeded"));
|
|
138
|
-
metrics.timeouts += 1;
|
|
139
|
-
metrics.errors += 1;
|
|
140
|
-
res.once("finish", () => {
|
|
141
|
-
if (!req.complete) req.destroy();
|
|
142
|
-
});
|
|
143
|
-
failure(
|
|
144
|
-
res,
|
|
145
|
-
504,
|
|
146
|
-
mutationStarted ? "mutation_outcome_unknown" : "request_timeout",
|
|
147
|
-
requestId
|
|
148
|
-
);
|
|
149
|
-
}, deadline);
|
|
150
|
-
void (async () => {
|
|
151
|
-
const url = new URL(req.url ?? "/", "http://gateway.invalid");
|
|
152
|
-
if (req.method === "GET" && url.pathname === "/readyz") {
|
|
153
|
-
let ready = false;
|
|
154
|
-
try {
|
|
155
|
-
ready = await (options.ready?.() ?? options.store.initialize().then(() => true));
|
|
156
|
-
} catch {
|
|
157
|
-
ready = false;
|
|
158
|
-
}
|
|
159
|
-
send(res, ready ? 200 : 503, { status: ready ? "ready" : "not_ready" }, requestId);
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
const origin = req.headers.origin;
|
|
163
|
-
if (origin && !origins.has(origin)) {
|
|
164
|
-
failure(res, 403, "origin_forbidden", requestId);
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
const token = bearerToken(req.headers.authorization);
|
|
168
|
-
const credential = token ? await options.credentials.resolve(token, abort.signal) : null;
|
|
169
|
-
active(abort.signal);
|
|
170
|
-
if (!credential) {
|
|
171
|
-
metrics.authFailures += 1;
|
|
172
|
-
failure(res, 401, "unauthorized", requestId);
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
if (req.method === "GET" && url.pathname === "/metrics") {
|
|
176
|
-
res.writeHead(200, { ...jsonHeaders, "content-type": "text/plain; version=0.0.4", "x-request-id": requestId });
|
|
177
|
-
res.end(Object.entries(metrics).map(([key, value]) => `agent_bridge_gateway_${key}_total ${value}`).join("\n") + "\n");
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
const instanceHeader = req.headers["x-agent-bridge-instance"];
|
|
181
|
-
const principal = {
|
|
182
|
-
...credential.principal,
|
|
183
|
-
instance: Array.isArray(instanceHeader) ? instanceHeader[0] : instanceHeader
|
|
184
|
-
};
|
|
185
|
-
if (req.method === "GET" && url.pathname === "/v2/status") {
|
|
186
|
-
if (!options.store.diagnostics) {
|
|
187
|
-
send(res, 200, { schemaVersion: "postgres-v2", deliverySupported: false, pending: null, claimed: null, retrying: null, dead: null, principal: credential.principal }, requestId);
|
|
188
|
-
} else {
|
|
189
|
-
send(res, 200, { ...await options.store.diagnostics(principal), principal: credential.principal }, requestId);
|
|
190
|
-
}
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
if (req.method === "POST" && req.headers["content-type"]?.split(";", 1)[0] !== "application/json") {
|
|
194
|
-
failure(res, 415, "unsupported_media_type", requestId);
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
if (req.method === "POST" && url.pathname === "/v2/messages") {
|
|
198
|
-
const input = await body(req, limit, abort.signal);
|
|
199
|
-
active(abort.signal);
|
|
200
|
-
mutationStarted = true;
|
|
201
|
-
send(res, 201, await service.publish(principal, input), requestId);
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
if (req.method === "GET" && url.pathname === "/v2/history") {
|
|
205
|
-
const types = url.searchParams.getAll("type");
|
|
206
|
-
send(res, 200, await service.history(principal, {
|
|
207
|
-
cursor: url.searchParams.get("cursor") ?? void 0,
|
|
208
|
-
limit: numberParam(url.searchParams.get("limit"), "limit"),
|
|
209
|
-
types: types.length ? types : void 0,
|
|
210
|
-
includeExpired: url.searchParams.get("includeExpired") === "true",
|
|
211
|
-
source: url.searchParams.get("source") ?? void 0,
|
|
212
|
-
since: url.searchParams.get("since") ?? void 0,
|
|
213
|
-
unacknowledgedBy: url.searchParams.get("unacknowledgedBy") ?? void 0,
|
|
214
|
-
threadId: url.searchParams.get("threadId") ?? void 0,
|
|
215
|
-
latest: url.searchParams.get("latest") === "true"
|
|
216
|
-
}), requestId);
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
if (req.method === "POST" && url.pathname === "/v2/receipts") {
|
|
220
|
-
const input = await body(req, limit, abort.signal);
|
|
221
|
-
active(abort.signal);
|
|
222
|
-
mutationStarted = true;
|
|
223
|
-
send(res, 200, { recorded: await service.acknowledge(principal, input.messageIds) }, requestId);
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
if (req.method === "POST" && url.pathname === "/v2/deliveries/claim") {
|
|
227
|
-
const input = await body(req, limit, abort.signal);
|
|
228
|
-
active(abort.signal);
|
|
229
|
-
mutationStarted = true;
|
|
230
|
-
send(res, 200, await service.claim(principal, input), requestId);
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
if (req.method === "POST" && url.pathname === "/v2/presence/heartbeat") {
|
|
234
|
-
const input = await body(req, limit, abort.signal);
|
|
235
|
-
active(abort.signal);
|
|
236
|
-
mutationStarted = true;
|
|
237
|
-
send(res, 200, await service.heartbeat(principal, input), requestId);
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
if (req.method === "GET" && url.pathname === "/v2/presence") {
|
|
241
|
-
send(res, 200, { agents: await service.presence(principal) }, requestId);
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
const match = url.pathname.match(/^\/v2\/deliveries\/([^/]+)\/(extend|ack|nack)$/);
|
|
245
|
-
if (req.method === "POST" && match) {
|
|
246
|
-
const input = await body(req, limit, abort.signal);
|
|
247
|
-
active(abort.signal);
|
|
248
|
-
mutationStarted = true;
|
|
249
|
-
const [, id, action] = match;
|
|
250
|
-
const result = action === "extend" ? await service.extend(principal, id, input.leaseToken, input.leaseMs) : action === "ack" ? await service.ack(principal, id, input.leaseToken) : await service.nack(principal, id, input.leaseToken, input.error, input.dead, input.retryPolicy);
|
|
251
|
-
if (!result) failure(res, 409, "lease_conflict", requestId);
|
|
252
|
-
else send(res, 200, result, requestId);
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
failure(res, 404, "not_found", requestId);
|
|
256
|
-
})().catch((error) => {
|
|
257
|
-
if (res.writableEnded) return;
|
|
258
|
-
metrics.errors += 1;
|
|
259
|
-
if (error instanceof BridgeValidationError) failure(res, 400, error.code, requestId);
|
|
260
|
-
else failure(res, error?.status ?? 500, error?.code ?? "internal_error", requestId);
|
|
261
|
-
}).finally(() => clearTimeout(timer));
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
export {
|
|
266
|
-
hashCredential,
|
|
267
|
-
PostgresCredentialResolver,
|
|
268
|
-
bearerToken,
|
|
269
|
-
safeTokenHashEqual,
|
|
270
|
-
createGateway
|
|
271
|
-
};
|
|
272
|
-
//# sourceMappingURL=chunk-JOUBDRYX.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/gateway.ts","../src/gateway-auth.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { BridgeValidationError, type MessageDraft } from \"./bridge-domain.js\";\nimport { BridgeService } from \"./bridge-service.js\";\nimport type { BridgeStore } from \"./bridge-store.js\";\nimport { bearerToken, type CredentialResolver } from \"./gateway-auth.js\";\n\nexport interface GatewayOptions {\n store: BridgeStore;\n credentials: CredentialResolver;\n allowedOrigins?: string[];\n bodyLimitBytes?: number;\n requestDeadlineMs?: number;\n ready?: () => Promise<boolean>;\n}\n\ntype Metrics = { requests: number; errors: number; timeouts: number; authFailures: number };\nconst jsonHeaders = { \"content-type\": \"application/json; charset=utf-8\", \"cache-control\": \"no-store\" };\n\nfunction send(res: ServerResponse, status: number, value: unknown, requestId: string): void {\n if (res.writableEnded) return;\n res.writeHead(status, { ...jsonHeaders, \"x-request-id\": requestId });\n res.end(JSON.stringify(value));\n}\n\nfunction failure(res: ServerResponse, status: number, code: string, requestId: string): void {\n send(res, status, { error: { code, requestId } }, requestId);\n}\n\nasync function body(\n req: IncomingMessage,\n limit: number,\n signal: AbortSignal,\n): Promise<Record<string, any>> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n const cleanup = () => {\n req.off(\"data\", onData);\n req.off(\"end\", onEnd);\n req.off(\"error\", onError);\n signal.removeEventListener(\"abort\", onAbort);\n };\n const finish = (callback: () => void) => {\n cleanup();\n callback();\n };\n const onData = (chunk: Buffer | string) => {\n const buffer = Buffer.from(chunk);\n size += buffer.length;\n if (size > limit) {\n finish(() => reject(Object.assign(new Error(\"body too large\"), {\n status: 413,\n code: \"body_too_large\",\n })));\n req.resume();\n return;\n }\n chunks.push(buffer);\n };\n const onEnd = () => finish(() => {\n if (!size) {\n resolve({});\n return;\n }\n try {\n const parsed = JSON.parse(Buffer.concat(chunks).toString(\"utf8\"));\n if (!parsed || Array.isArray(parsed) || typeof parsed !== \"object\") throw new Error();\n resolve(parsed);\n } catch {\n reject(Object.assign(new Error(\"invalid JSON\"), { status: 400, code: \"malformed_json\" }));\n }\n });\n const onError = (error: Error) => finish(() => reject(error));\n const onAbort = () => {\n finish(() => reject(signal.reason));\n req.resume();\n };\n req.on(\"data\", onData);\n req.on(\"end\", onEnd);\n req.on(\"error\", onError);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n if (signal.aborted) onAbort();\n });\n}\n\nfunction numberParam(value: string | null, name: string): number | undefined {\n if (value === null) return undefined;\n const result = Number(value);\n if (!Number.isSafeInteger(result)) throw new BridgeValidationError(`${name} is invalid`);\n return result;\n}\n\nfunction active(signal: AbortSignal): void {\n if (signal.aborted) throw signal.reason;\n}\n\nexport function createGateway(options: GatewayOptions) {\n const service = new BridgeService(options.store);\n const metrics: Metrics = { requests: 0, errors: 0, timeouts: 0, authFailures: 0 };\n const limit = options.bodyLimitBytes ?? 128 * 1024;\n const deadline = options.requestDeadlineMs ?? 10_000;\n const origins = new Set(options.allowedOrigins ?? []);\n\n return createServer((req, res) => {\n const requestId = randomUUID();\n const abort = new AbortController();\n let mutationStarted = false;\n metrics.requests += 1;\n const timer = setTimeout(() => {\n abort.abort(new Error(\"request deadline exceeded\"));\n metrics.timeouts += 1; metrics.errors += 1;\n res.once(\"finish\", () => {\n if (!req.complete) req.destroy();\n });\n failure(\n res,\n 504,\n mutationStarted ? \"mutation_outcome_unknown\" : \"request_timeout\",\n requestId,\n );\n }, deadline);\n\n void (async () => {\n const url = new URL(req.url ?? \"/\", \"http://gateway.invalid\");\n if (req.method === \"GET\" && url.pathname === \"/readyz\") {\n let ready = false;\n try {\n ready = await (options.ready?.() ?? options.store.initialize().then(() => true));\n } catch {\n ready = false;\n }\n send(res, ready ? 200 : 503, { status: ready ? \"ready\" : \"not_ready\" }, requestId);\n return;\n }\n const origin = req.headers.origin;\n if (origin && !origins.has(origin)) {\n failure(res, 403, \"origin_forbidden\", requestId); return;\n }\n const token = bearerToken(req.headers.authorization);\n const credential = token ? await options.credentials.resolve(token, abort.signal) : null;\n active(abort.signal);\n if (!credential) {\n metrics.authFailures += 1;\n failure(res, 401, \"unauthorized\", requestId); return;\n }\n if (req.method === \"GET\" && url.pathname === \"/metrics\") {\n res.writeHead(200, { ...jsonHeaders, \"content-type\": \"text/plain; version=0.0.4\", \"x-request-id\": requestId });\n res.end(Object.entries(metrics).map(([key, value]) => `agent_bridge_gateway_${key}_total ${value}`).join(\"\\n\") + \"\\n\");\n return;\n }\n const instanceHeader = req.headers[\"x-agent-bridge-instance\"];\n const principal = {\n ...credential.principal,\n instance: Array.isArray(instanceHeader) ? instanceHeader[0] : instanceHeader,\n };\n\n if (req.method === \"GET\" && url.pathname === \"/v2/status\") {\n if (!options.store.diagnostics) {\n send(res, 200, { schemaVersion: \"postgres-v2\", deliverySupported: false, pending: null, claimed: null, retrying: null, dead: null, principal: credential.principal }, requestId);\n } else {\n send(res, 200, { ...await options.store.diagnostics(principal), principal: credential.principal }, requestId);\n }\n return;\n }\n\n if (req.method === \"POST\" && req.headers[\"content-type\"]?.split(\";\", 1)[0] !== \"application/json\") {\n failure(res, 415, \"unsupported_media_type\", requestId); return;\n }\n\n if (req.method === \"POST\" && url.pathname === \"/v2/messages\") {\n const input = await body(req, limit, abort.signal) as unknown as MessageDraft;\n active(abort.signal);\n mutationStarted = true;\n send(res, 201, await service.publish(principal, input), requestId); return;\n }\n if (req.method === \"GET\" && url.pathname === \"/v2/history\") {\n const types = url.searchParams.getAll(\"type\");\n send(res, 200, await service.history(principal, {\n cursor: url.searchParams.get(\"cursor\") ?? undefined,\n limit: numberParam(url.searchParams.get(\"limit\"), \"limit\"),\n types: types.length ? types : undefined,\n includeExpired: url.searchParams.get(\"includeExpired\") === \"true\",\n source: url.searchParams.get(\"source\") ?? undefined,\n since: url.searchParams.get(\"since\") ?? undefined,\n unacknowledgedBy: url.searchParams.get(\"unacknowledgedBy\") ?? undefined,\n threadId: url.searchParams.get(\"threadId\") ?? undefined,\n latest: url.searchParams.get(\"latest\") === \"true\",\n }), requestId); return;\n }\n if (req.method === \"POST\" && url.pathname === \"/v2/receipts\") {\n const input = await body(req, limit, abort.signal);\n active(abort.signal);\n mutationStarted = true;\n send(res, 200, { recorded: await service.acknowledge(principal, input.messageIds) }, requestId); return;\n }\n if (req.method === \"POST\" && url.pathname === \"/v2/deliveries/claim\") {\n const input = await body(req, limit, abort.signal);\n active(abort.signal);\n mutationStarted = true;\n send(res, 200, await service.claim(principal, input), requestId); return;\n }\n if (req.method === \"POST\" && url.pathname === \"/v2/presence/heartbeat\") {\n const input = await body(req, limit, abort.signal);\n active(abort.signal);\n mutationStarted = true;\n send(res, 200, await service.heartbeat(principal, input), requestId); return;\n }\n if (req.method === \"GET\" && url.pathname === \"/v2/presence\") {\n send(res, 200, { agents: await service.presence(principal) }, requestId); return;\n }\n const match = url.pathname.match(/^\\/v2\\/deliveries\\/([^/]+)\\/(extend|ack|nack)$/);\n if (req.method === \"POST\" && match) {\n const input = await body(req, limit, abort.signal);\n active(abort.signal);\n mutationStarted = true;\n const [, id, action] = match;\n const result = action === \"extend\"\n ? await service.extend(principal, id, input.leaseToken, input.leaseMs)\n : action === \"ack\"\n ? await service.ack(principal, id, input.leaseToken)\n : await service.nack(principal, id, input.leaseToken, input.error, input.dead, input.retryPolicy);\n if (!result) failure(res, 409, \"lease_conflict\", requestId);\n else send(res, 200, result, requestId);\n return;\n }\n failure(res, 404, \"not_found\", requestId);\n })().catch((error: any) => {\n if (res.writableEnded) return;\n metrics.errors += 1;\n if (error instanceof BridgeValidationError) failure(res, 400, error.code, requestId);\n else failure(res, error?.status ?? 500, error?.code ?? \"internal_error\", requestId);\n }).finally(() => clearTimeout(timer));\n });\n}\n","import { createHash, timingSafeEqual } from \"node:crypto\";\nimport type { BridgePrincipal } from \"./bridge-domain.js\";\nimport type { PgQueryable } from \"./postgres-bridge-store.js\";\n\nexport interface AuthenticatedCredential {\n id: string;\n principal: BridgePrincipal;\n}\n\nexport interface CredentialResolver {\n resolve(token: string, signal?: AbortSignal): Promise<AuthenticatedCredential | null>;\n}\n\nexport function hashCredential(token: string): string {\n return createHash(\"sha256\").update(token, \"utf8\").digest(\"hex\");\n}\n\nexport class PostgresCredentialResolver implements CredentialResolver {\n constructor(private readonly db: PgQueryable) {}\n\n async resolve(token: string, signal?: AbortSignal): Promise<AuthenticatedCredential | null> {\n if (signal?.aborted) throw signal.reason;\n const hash = hashCredential(token);\n const result = await this.db.query<{\n id: string; workspace_id: string; principal: string;\n }>(\n `SELECT credential.id, credential.workspace_id, agent.principal\n FROM agent_bridge.credentials credential\n JOIN agent_bridge.agents agent\n ON agent.id=credential.agent_id AND agent.workspace_id=credential.workspace_id\n JOIN agent_bridge.workspaces workspace ON workspace.id=credential.workspace_id\n WHERE credential.token_hash=$1 AND credential.revoked_at IS NULL\n AND (credential.expires_at IS NULL OR credential.expires_at>now())\n AND agent.disabled_at IS NULL AND workspace.disabled_at IS NULL\n LIMIT 1`,\n [hash],\n );\n const row = result.rows[0];\n if (signal?.aborted) throw signal.reason;\n return row ? { id: row.id, principal: { workspace: row.workspace_id, agent: row.principal } } : null;\n }\n}\n\nexport function bearerToken(value: string | undefined): string | null {\n if (!value?.startsWith(\"Bearer \")) return null;\n const token = value.slice(7);\n if (!token || token.length > 4096 || /\\s/.test(token)) return null;\n return token;\n}\n\nexport function safeTokenHashEqual(token: string, expectedHash: string): boolean {\n const actual = Buffer.from(hashCredential(token));\n const expected = Buffer.from(expectedHash);\n return actual.length === expected.length && timingSafeEqual(actual, expected);\n}\n"],"mappings":"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","names":[]}
|
package/dist/chunk-JTC5YURG.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
HttpBridgeStore,
|
|
4
|
-
LegacySupabaseRestStore
|
|
5
|
-
} from "./chunk-AXL2I7FH.js";
|
|
6
|
-
import {
|
|
7
|
-
SQLiteBridgeStore,
|
|
8
|
-
SQLiteEdgeStore,
|
|
9
|
-
SyncingBridgeStore
|
|
10
|
-
} from "./chunk-WEULPMUY.js";
|
|
11
|
-
import {
|
|
12
|
-
BridgeService
|
|
13
|
-
} from "./chunk-CKSKUBDQ.js";
|
|
14
|
-
|
|
15
|
-
// src/client-runtime.ts
|
|
16
|
-
import { chmodSync, mkdirSync } from "fs";
|
|
17
|
-
import { basename, dirname } from "path";
|
|
18
|
-
function createStore(config) {
|
|
19
|
-
if (config.provider === "local") {
|
|
20
|
-
if (config.databasePath !== ":memory:") {
|
|
21
|
-
const directory = dirname(config.databasePath);
|
|
22
|
-
mkdirSync(directory, { recursive: true, mode: 448 });
|
|
23
|
-
if (basename(directory) === ".agent-bridge") chmodSync(directory, 448);
|
|
24
|
-
}
|
|
25
|
-
return new SQLiteBridgeStore(config.databasePath);
|
|
26
|
-
}
|
|
27
|
-
if (config.provider === "gateway") {
|
|
28
|
-
const directory = dirname(config.edgeDatabasePath);
|
|
29
|
-
mkdirSync(directory, { recursive: true, mode: 448 });
|
|
30
|
-
if (basename(directory) === ".agent-bridge") chmodSync(directory, 448);
|
|
31
|
-
const remote = new HttpBridgeStore({ baseUrl: config.url, token: config.credential, principal: config.principal });
|
|
32
|
-
const edge = new SQLiteEdgeStore(config.edgeDatabasePath, { endpoint: config.url, principal: config.principal });
|
|
33
|
-
return new SyncingBridgeStore(edge, remote, config.principal);
|
|
34
|
-
}
|
|
35
|
-
return new LegacySupabaseRestStore(config.url, config.credential);
|
|
36
|
-
}
|
|
37
|
-
async function createClientRuntime(config) {
|
|
38
|
-
const store = createStore(config);
|
|
39
|
-
await store.initialize();
|
|
40
|
-
return { config, store, service: new BridgeService(store), close: async () => {
|
|
41
|
-
await store.close?.();
|
|
42
|
-
} };
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export {
|
|
46
|
-
createStore,
|
|
47
|
-
createClientRuntime
|
|
48
|
-
};
|
|
49
|
-
//# sourceMappingURL=chunk-JTC5YURG.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client-runtime.ts"],"sourcesContent":["import { chmodSync, mkdirSync } from \"node:fs\";\nimport { basename, dirname } from \"node:path\";\nimport { BridgeService } from \"./bridge-service.js\";\nimport type { BridgeStore } from \"./bridge-store.js\";\nimport { HttpBridgeStore } from \"./http-bridge-store.js\";\nimport { SQLiteEdgeStore } from \"./sqlite-edge-store.js\";\nimport { SyncingBridgeStore } from \"./syncing-bridge-store.js\";\nimport { LegacySupabaseRestStore } from \"./legacy-supabase-store.js\";\nimport { SQLiteBridgeStore } from \"./sqlite-bridge-store.js\";\nimport type { ClientConfig } from \"./client-config.js\";\n\nexport interface ClientRuntime { config: ClientConfig; store: BridgeStore; service: BridgeService; close(): Promise<void>; }\n\nexport function createStore(config: ClientConfig): BridgeStore {\n if (config.provider === \"local\") {\n if (config.databasePath !== \":memory:\") {\n const directory = dirname(config.databasePath);\n mkdirSync(directory, { recursive: true, mode: 0o700 });\n if (basename(directory) === \".agent-bridge\") chmodSync(directory, 0o700);\n }\n return new SQLiteBridgeStore(config.databasePath);\n }\n if (config.provider === \"gateway\") {\n const directory = dirname(config.edgeDatabasePath);\n mkdirSync(directory, { recursive: true, mode: 0o700 });\n if (basename(directory) === \".agent-bridge\") chmodSync(directory, 0o700);\n const remote = new HttpBridgeStore({ baseUrl: config.url!, token: config.credential!, principal: config.principal });\n const edge = new SQLiteEdgeStore(config.edgeDatabasePath, { endpoint: config.url!, principal: config.principal });\n return new SyncingBridgeStore(edge, remote, config.principal);\n }\n return new LegacySupabaseRestStore(config.url!, config.credential!);\n}\n\nexport async function createClientRuntime(config: ClientConfig): Promise<ClientRuntime> {\n const store = createStore(config);\n await store.initialize();\n return { config, store, service: new BridgeService(store), close: async () => { await store.close?.(); } };\n}\n"],"mappings":";;;;;;;;;;;;;;;AAAA,SAAS,WAAW,iBAAiB;AACrC,SAAS,UAAU,eAAe;AAY3B,SAAS,YAAY,QAAmC;AAC7D,MAAI,OAAO,aAAa,SAAS;AAC/B,QAAI,OAAO,iBAAiB,YAAY;AACtC,YAAM,YAAY,QAAQ,OAAO,YAAY;AAC7C,gBAAU,WAAW,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AACrD,UAAI,SAAS,SAAS,MAAM,gBAAiB,WAAU,WAAW,GAAK;AAAA,IACzE;AACA,WAAO,IAAI,kBAAkB,OAAO,YAAY;AAAA,EAClD;AACA,MAAI,OAAO,aAAa,WAAW;AACjC,UAAM,YAAY,QAAQ,OAAO,gBAAgB;AACjD,cAAU,WAAW,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AACrD,QAAI,SAAS,SAAS,MAAM,gBAAiB,WAAU,WAAW,GAAK;AACvE,UAAM,SAAS,IAAI,gBAAgB,EAAE,SAAS,OAAO,KAAM,OAAO,OAAO,YAAa,WAAW,OAAO,UAAU,CAAC;AACnH,UAAM,OAAO,IAAI,gBAAgB,OAAO,kBAAkB,EAAE,UAAU,OAAO,KAAM,WAAW,OAAO,UAAU,CAAC;AAChH,WAAO,IAAI,mBAAmB,MAAM,QAAQ,OAAO,SAAS;AAAA,EAC9D;AACA,SAAO,IAAI,wBAAwB,OAAO,KAAM,OAAO,UAAW;AACpE;AAEA,eAAsB,oBAAoB,QAA8C;AACtF,QAAM,QAAQ,YAAY,MAAM;AAChC,QAAM,MAAM,WAAW;AACvB,SAAO,EAAE,QAAQ,OAAO,SAAS,IAAI,cAAc,KAAK,GAAG,OAAO,YAAY;AAAE,UAAM,MAAM,QAAQ;AAAA,EAAG,EAAE;AAC3G;","names":[]}
|