@evilstar9527/tool-bridge 0.1.0

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 (46) hide show
  1. package/README.md +288 -0
  2. package/dist/sdk/admin.js +157 -0
  3. package/dist/sdk/chunks/client-BWz3o-l-.js +36 -0
  4. package/dist/sdk/chunks/errors-DJj3RaDk.js +54 -0
  5. package/dist/sdk/host.js +98 -0
  6. package/dist/sdk/index.js +6 -0
  7. package/dist/sdk/tb.js +0 -0
  8. package/dist/sdk/transport.js +14 -0
  9. package/dist/sdk/tunnel-agent.js +43 -0
  10. package/dist/sdk/worker.js +2940 -0
  11. package/dist/types/sdk/admin/index.d.ts +237 -0
  12. package/dist/types/sdk/client.d.ts +17 -0
  13. package/dist/types/sdk/host/index.d.ts +65 -0
  14. package/dist/types/sdk/index.d.ts +5 -0
  15. package/dist/types/sdk/transport.d.ts +8 -0
  16. package/dist/types/sdk/tunnel-agent/index.d.ts +29 -0
  17. package/dist/types/worker/index.d.ts +19 -0
  18. package/dist/types/worker/tb/adapters/builtin.d.ts +4 -0
  19. package/dist/types/worker/tb/adapters/directory.d.ts +6 -0
  20. package/dist/types/worker/tb/adapters/http.d.ts +2 -0
  21. package/dist/types/worker/tb/adapters/index.d.ts +2 -0
  22. package/dist/types/worker/tb/adapters/mcp.d.ts +2 -0
  23. package/dist/types/worker/tb/adapters/mount.d.ts +2 -0
  24. package/dist/types/worker/tb/adapters/remote.d.ts +2 -0
  25. package/dist/types/worker/tb/audit.d.ts +56 -0
  26. package/dist/types/worker/tb/crawl.d.ts +11 -0
  27. package/dist/types/worker/tb/device.d.ts +80 -0
  28. package/dist/types/worker/tb/dynamic-servers.d.ts +12 -0
  29. package/dist/types/worker/tb/entities.d.ts +74 -0
  30. package/dist/types/worker/tb/errors.d.ts +34 -0
  31. package/dist/types/worker/tb/help.d.ts +2 -0
  32. package/dist/types/worker/tb/host-api.d.ts +12 -0
  33. package/dist/types/worker/tb/materialize.d.ts +4 -0
  34. package/dist/types/worker/tb/mcp-client.d.ts +17 -0
  35. package/dist/types/worker/tb/provider-api.d.ts +11 -0
  36. package/dist/types/worker/tb/registry.d.ts +11 -0
  37. package/dist/types/worker/tb/remote-client.d.ts +3 -0
  38. package/dist/types/worker/tb/resolve.d.ts +8 -0
  39. package/dist/types/worker/tb/storage-r2.d.ts +2 -0
  40. package/dist/types/worker/tb/tenant.d.ts +28 -0
  41. package/dist/types/worker/tb/testing/fake-kv.d.ts +20 -0
  42. package/dist/types/worker/tb/types.d.ts +155 -0
  43. package/dist/types/worker/tb/util.d.ts +18 -0
  44. package/dist/types/worker/tb/virtualize.d.ts +7 -0
  45. package/docs/sdk.md +149 -0
  46. package/package.json +79 -0
@@ -0,0 +1,2940 @@
1
+ import { a as e, c as t, i as n, n as r, o as i, r as a, s as o, t as s } from "./chunks/errors-DJj3RaDk.js";
2
+ import { createRemoteJWKSet as c, jwtVerify as l } from "jose";
3
+ //#region src/worker/tb/util.ts
4
+ var u = "2025-11-25", d = "tool-bridge", f = "draft", p = 1e6, m = 5e3;
5
+ function h(e, t = {}) {
6
+ let n = new Headers(t.headers);
7
+ return n.set("Content-Type", "application/json; charset=utf-8"), new Response(JSON.stringify(e, null, 2), {
8
+ ...t,
9
+ headers: n
10
+ });
11
+ }
12
+ function g(e, t = {}) {
13
+ let n = new Headers(t.headers);
14
+ return n.set("Content-Type", n.get("Content-Type") ?? "text/plain; charset=utf-8"), new Response(e, {
15
+ ...t,
16
+ headers: n
17
+ });
18
+ }
19
+ function _(e) {
20
+ return !!e && typeof e == "object" && !Array.isArray(e);
21
+ }
22
+ function v(e, t) {
23
+ let n = e[t];
24
+ return typeof n == "string" && n.length > 0 ? n : void 0;
25
+ }
26
+ function y(e) {
27
+ if (!_(e)) return;
28
+ let t = {};
29
+ for (let [n, r] of Object.entries(e)) typeof r == "string" && (t[n] = r);
30
+ return t;
31
+ }
32
+ function b(e) {
33
+ if (Array.isArray(e)) return e.filter((e) => typeof e == "string");
34
+ }
35
+ function x(e) {
36
+ return e.replace(/\s+/g, " ").trim();
37
+ }
38
+ function S(e) {
39
+ return e instanceof Error ? e.message : String(e);
40
+ }
41
+ async function C(e, t) {
42
+ if (!e.body) return "";
43
+ let n = e.body.getReader(), r = new TextDecoder(), i = 0, a = "";
44
+ for (;;) {
45
+ let { done: e, value: o } = await n.read();
46
+ if (e) return a + r.decode();
47
+ if (i += o.byteLength, i > t) throw Error("Response body exceeded the maximum size.");
48
+ a += r.decode(o, { stream: !0 });
49
+ }
50
+ }
51
+ async function ee(e) {
52
+ try {
53
+ return await C(e, 8e3);
54
+ } catch {
55
+ return "";
56
+ }
57
+ }
58
+ //#endregion
59
+ //#region src/worker/tb/registry.ts
60
+ var w = "/htbp";
61
+ function te(e) {
62
+ return ne(e.MCP_SERVERS_JSON || "{}");
63
+ }
64
+ function ne(e) {
65
+ let t = JSON.parse(e || "{}");
66
+ if (_(t) && (t.type === "directory" || Array.isArray(t.children))) {
67
+ let e = ie({
68
+ id: "root",
69
+ ...t
70
+ }, "root");
71
+ if (e.kind !== "directory") throw Error("Root tree node must be a directory.");
72
+ return T(e), e;
73
+ }
74
+ let n = {
75
+ kind: "directory",
76
+ id: "root",
77
+ title: "Tool Bridge",
78
+ children: re(t)
79
+ };
80
+ return T(n), n;
81
+ }
82
+ function re(e) {
83
+ let t = [];
84
+ if (Array.isArray(e)) {
85
+ for (let n of e) t.push(oe(n));
86
+ return t;
87
+ }
88
+ if (_(e)) for (let [n, r] of Object.entries(e)) t.push(oe({
89
+ id: n,
90
+ ..._(r) ? r : {}
91
+ }));
92
+ return t;
93
+ }
94
+ function ie(e, t) {
95
+ if (!_(e)) throw Error(`Tree node at '${t}' must be an object.`);
96
+ let n = v(e, "type") || (e.children ? "directory" : "mcp");
97
+ switch (n) {
98
+ case "directory": return ae(e, t);
99
+ case "mcp": return oe(e);
100
+ case "http": return ce(e, t);
101
+ case "remote": return ue(e, t);
102
+ case "mount": return de(e, t);
103
+ case "builtin": return fe(e, t);
104
+ default: throw Error(`Unknown tree node type '${n}' at '${t}'.`);
105
+ }
106
+ }
107
+ function ae(e, t) {
108
+ let n = v(e, "id") || v(e, "name");
109
+ if (!n) throw Error(`Directory node at '${t}' is missing id/name.`);
110
+ let r = (Array.isArray(e.children) ? e.children : []).map((e, r) => ie(e, `${t}/${n}[${r}]`));
111
+ return he(r, `${t}/${n}`), {
112
+ kind: "directory",
113
+ id: n,
114
+ title: v(e, "title") || v(e, "name") || n,
115
+ summary: v(e, "summary") || v(e, "description"),
116
+ children: r
117
+ };
118
+ }
119
+ function oe(e) {
120
+ if (!_(e)) throw Error("MCP server config must be an object.");
121
+ let t = v(e, "id") || v(e, "name"), n = v(e, "endpoint") || v(e, "url") || v(e, "baseUrl");
122
+ if (!t) throw Error("MCP server config is missing id/name.");
123
+ if (!n) throw Error(`MCP server '${t}' is missing endpoint.`);
124
+ return {
125
+ kind: "mcp",
126
+ id: t,
127
+ title: v(e, "name") || t,
128
+ endpoint: n,
129
+ description: v(e, "description"),
130
+ headers: y(e.headers),
131
+ allowedTools: b(e.allowedTools) ?? b(e.allowed_tools),
132
+ namespace: v(e, "namespace"),
133
+ toolOverrides: se(e.toolOverrides ?? e.tool_overrides)
134
+ };
135
+ }
136
+ function se(e) {
137
+ if (!_(e)) return;
138
+ let t = {};
139
+ for (let [n, r] of Object.entries(e)) _(r) && (t[n] = {
140
+ hide: r.hide === !0,
141
+ rename: v(r, "rename"),
142
+ description: v(r, "description"),
143
+ effect: me(r.effect),
144
+ scope: v(r, "scope"),
145
+ confirm: r.confirm === !0 ? !0 : void 0
146
+ });
147
+ return Object.keys(t).length > 0 ? t : void 0;
148
+ }
149
+ function ce(e, t) {
150
+ let n = v(e, "id") || v(e, "name");
151
+ if (!n) throw Error(`HTTP node at '${t}' is missing id/name.`);
152
+ let r = (Array.isArray(e.endpoints) ? e.endpoints : []).map((e, r) => le(e, `${t}/${n}[${r}]`));
153
+ if (r.length === 0) throw Error(`HTTP node '${n}' must declare at least one endpoint.`);
154
+ return he(r.map((e) => ({ id: e.name })), `${t}/${n}`), {
155
+ kind: "http",
156
+ id: n,
157
+ title: v(e, "title") || v(e, "name") || n,
158
+ summary: v(e, "summary") || v(e, "description"),
159
+ endpoints: r
160
+ };
161
+ }
162
+ function le(e, t) {
163
+ if (!_(e)) throw Error(`HTTP endpoint at '${t}' must be an object.`);
164
+ let n = v(e, "name"), r = v(e, "method"), i = v(e, "url");
165
+ if (!n) throw Error(`HTTP endpoint at '${t}' is missing name.`);
166
+ if (!r) throw Error(`HTTP endpoint '${n}' is missing method.`);
167
+ if (!i) throw Error(`HTTP endpoint '${n}' is missing url.`);
168
+ return {
169
+ name: n,
170
+ method: r.toUpperCase(),
171
+ url: i,
172
+ description: v(e, "description"),
173
+ inputSchema: e.inputSchema,
174
+ outputSchema: e.outputSchema,
175
+ example: e.example,
176
+ headers: y(e.headers),
177
+ effect: me(e.effect),
178
+ scope: v(e, "scope"),
179
+ confirm: e.confirm === !0 ? !0 : void 0
180
+ };
181
+ }
182
+ function ue(e, t) {
183
+ let n = v(e, "id") || v(e, "name");
184
+ if (!n) throw Error(`Remote node at '${t}' is missing id/name.`);
185
+ let r = v(e, "helpUrl") || v(e, "help_url") || v(e, "url");
186
+ if (!r) throw Error(`Remote node '${n}' is missing helpUrl.`);
187
+ return {
188
+ kind: "remote",
189
+ id: n,
190
+ title: v(e, "title") || v(e, "name") || n,
191
+ summary: v(e, "summary") || v(e, "description"),
192
+ helpUrl: r,
193
+ headers: y(e.headers)
194
+ };
195
+ }
196
+ function de(e, t) {
197
+ let n = v(e, "id") || v(e, "name");
198
+ if (!n) throw Error(`Mount node at '${t}' is missing id/name.`);
199
+ let r = v(e, "bucket") || v(e, "binding");
200
+ if (!r) throw Error(`Mount node '${n}' is missing bucket binding name.`);
201
+ return {
202
+ kind: "mount",
203
+ id: n,
204
+ title: v(e, "title") || v(e, "name") || n,
205
+ summary: v(e, "summary") || v(e, "description"),
206
+ bucket: r,
207
+ prefix: v(e, "prefix"),
208
+ description: v(e, "description")
209
+ };
210
+ }
211
+ function fe(e, t) {
212
+ let n = v(e, "id") || v(e, "name");
213
+ if (!n) throw Error(`Builtin node at '${t}' is missing id/name.`);
214
+ let r = _(e.builtin) ? e.builtin : e, i = (Array.isArray(r.tools) ? r.tools : []).map((e, r) => pe(e, `${t}/${n}[${r}]`));
215
+ if (i.length === 0) throw Error(`Builtin node '${n}' must declare at least one tool.`);
216
+ return he(i.map((e) => ({ id: e.name })), `${t}/${n}`), {
217
+ kind: "builtin",
218
+ id: n,
219
+ title: v(e, "title") || v(e, "name") || n,
220
+ summary: v(e, "summary") || v(e, "description"),
221
+ description: v(e, "description"),
222
+ tools: i
223
+ };
224
+ }
225
+ function pe(e, t) {
226
+ if (!_(e)) throw Error(`Builtin tool at '${t}' must be an object.`);
227
+ let n = v(e, "name"), r = v(e, "handler");
228
+ if (!n) throw Error(`Builtin tool at '${t}' is missing name.`);
229
+ if (!r) throw Error(`Builtin tool '${n}' is missing handler.`);
230
+ return {
231
+ name: n,
232
+ handler: r,
233
+ description: v(e, "description"),
234
+ inputSchema: e.inputSchema,
235
+ outputSchema: e.outputSchema,
236
+ effect: me(e.effect),
237
+ scope: v(e, "scope"),
238
+ confirm: e.confirm === !0 ? !0 : void 0
239
+ };
240
+ }
241
+ function me(e) {
242
+ if (e === "read" || e === "write" || e === "destructive" || e === "external") return e;
243
+ }
244
+ function he(e, t) {
245
+ let n = /* @__PURE__ */ new Set();
246
+ for (let r of e) {
247
+ if (n.has(r.id)) throw Error(`Duplicate sibling id '${r.id}' under '${t}'.`);
248
+ n.add(r.id);
249
+ }
250
+ }
251
+ function ge(e, t) {
252
+ return ie(e, t);
253
+ }
254
+ function T(e) {
255
+ if (e.kind === "directory") for (let t of e.children) Object.defineProperty(t, "parent", {
256
+ value: e,
257
+ enumerable: !1,
258
+ writable: !0,
259
+ configurable: !0
260
+ }), T(t);
261
+ }
262
+ function _e(e) {
263
+ let t = [], n = e;
264
+ for (; n && n.parent;) t.unshift(n.id), n = n.parent;
265
+ return t.length === 0 ? w : `${w}/${t.map(encodeURIComponent).join("/")}`;
266
+ }
267
+ function E(e, t) {
268
+ let n = e;
269
+ for (let e = 0; e < t.length; e += 1) {
270
+ let r = t[e];
271
+ if (n.kind !== "directory") return {
272
+ node: n,
273
+ sub: t.slice(e)
274
+ };
275
+ let i = n.children.find((e) => e.id === r);
276
+ if (!i) return;
277
+ n = i;
278
+ }
279
+ return {
280
+ node: n,
281
+ sub: []
282
+ };
283
+ }
284
+ //#endregion
285
+ //#region src/worker/tb/audit.ts
286
+ var ve = 168 * 3600, ye = 0x9184e72a000;
287
+ function be(e) {
288
+ return !!e.TENANTS && e.AUDIT_MODE !== "off";
289
+ }
290
+ function xe(e) {
291
+ let t = e.headers.get("X-TB-Trace-Id");
292
+ return t && /^[A-Za-z0-9._-]{1,128}$/.test(t) ? t : crypto.randomUUID();
293
+ }
294
+ function Se(e) {
295
+ if (e === void 0) return;
296
+ let t = 0;
297
+ try {
298
+ t = JSON.stringify(e)?.length ?? 0;
299
+ } catch {
300
+ t = 0;
301
+ }
302
+ return {
303
+ bytes: t,
304
+ keys: _(e) ? Object.keys(e).slice(0, 32) : void 0
305
+ };
306
+ }
307
+ function Ce(e) {
308
+ return e ?? "_global";
309
+ }
310
+ function we(e, t) {
311
+ let n = E(e, t);
312
+ if (!n) return {};
313
+ let r = n.node, i = {
314
+ tool: n.sub.length > 0 ? n.sub.join("/") : void 0,
315
+ provider: r.tbProviderId
316
+ }, a = n.sub[0];
317
+ if (a) {
318
+ if (r.kind === "http") {
319
+ let e = r.endpoints.find((e) => e.name === a);
320
+ i.effect = e?.effect, i.scope = e?.scope;
321
+ } else if (r.kind === "builtin") {
322
+ let e = r.tools.find((e) => e.name === a);
323
+ i.effect = e?.effect, i.scope = e?.scope;
324
+ } else if (r.kind === "mcp") {
325
+ let e = r.toolOverrides?.[a];
326
+ i.effect = e?.effect, i.scope = e?.scope;
327
+ }
328
+ }
329
+ return i;
330
+ }
331
+ async function Te(e) {
332
+ try {
333
+ let t = await e.clone().json();
334
+ return typeof t?.error?.code == "string" ? t.error.code : void 0;
335
+ } catch {
336
+ return;
337
+ }
338
+ }
339
+ async function Ee(e, t) {
340
+ if (!be(e)) return;
341
+ let n = e.TENANTS, r = String(ye - Date.parse(t.ts)).padStart(14, "0"), i = crypto.randomUUID().slice(0, 8), a = Number(e.AUDIT_TTL_SECONDS), o = Number.isFinite(a) && a >= 60 ? a : ve;
342
+ await n.put(`audit:${Ce(t.tenantId)}:${r}:${i}`, JSON.stringify(t), { expirationTtl: o });
343
+ }
344
+ function De(e, t, n) {
345
+ let r = Ee(e, n).catch(() => {});
346
+ return t?.waitUntil ? (t.waitUntil(r), Promise.resolve()) : r;
347
+ }
348
+ async function Oe(e, t, n) {
349
+ let r = new URL(e.url);
350
+ if (r.pathname !== "/api/audit/events") return;
351
+ if (e.method !== "GET") return o(405, "method_not_allowed", "Use GET /api/audit/events.");
352
+ if (!be(t)) return o(501, "not_supported", "Audit requires the TENANTS KV binding.");
353
+ if (!n.isAdmin && !n.tenantId) return o(403, "Forbidden", "Audit query requires an admin or tenant-bound key.");
354
+ let i = Math.min(Math.max(Number(r.searchParams.get("limit")) || 50, 1), 200), a = r.searchParams.get("tenant") ?? void 0, s = n.isAdmin ? a : Ce(n.tenantId), c = s ? `audit:${s}:` : "audit:", l = t.TENANTS, u = [], d;
355
+ for (; u.length < i;) {
356
+ let e = await l.list({
357
+ prefix: c,
358
+ cursor: d,
359
+ limit: Math.min(i - u.length, 100)
360
+ });
361
+ for (let t of e.keys) {
362
+ let e = await l.get(t.name, "json");
363
+ if (e && u.push(e), u.length >= i) break;
364
+ }
365
+ if (e.list_complete) break;
366
+ d = e.cursor;
367
+ }
368
+ return h({
369
+ scope: s ?? "all",
370
+ events: u
371
+ });
372
+ }
373
+ //#endregion
374
+ //#region src/worker/tb/adapters/builtin.ts
375
+ var ke = {
376
+ kind: "builtin",
377
+ async describe(e, t, n) {
378
+ if (n.length === 0) return {
379
+ htbp: "draft",
380
+ kind: "builtin",
381
+ title: e.title,
382
+ description: e.description,
383
+ cachable: !0,
384
+ resources: e.tools.map(Ae)
385
+ };
386
+ let r = je(e, n[0]);
387
+ return {
388
+ htbp: "draft",
389
+ kind: "builtin",
390
+ title: r.name,
391
+ description: r.description,
392
+ cachable: !0,
393
+ endpoint: {
394
+ method: "POST",
395
+ inputSchema: r.inputSchema ?? { type: "object" },
396
+ outputSchema: r.outputSchema,
397
+ example: {},
398
+ effect: r.effect,
399
+ scope: r.scope,
400
+ confirm: r.confirm
401
+ }
402
+ };
403
+ },
404
+ async call(e, t, n, r) {
405
+ if (n.length === 0) throw Error(`Builtin node '${e.id}' requires a tool: call POST {path}/{tool}.`);
406
+ let i = je(e, n[0]), a = (t.builtinHandlers ?? {})[i.handler];
407
+ if (!a) throw Error(`Builtin tool '${i.name}' references handler '${i.handler}', which the host did not register.`);
408
+ return a(Me(r), t);
409
+ }
410
+ };
411
+ function Ae(e) {
412
+ return {
413
+ name: e.name,
414
+ path: `./${encodeURIComponent(e.name)}`,
415
+ description: e.description ? x(e.description) : void 0
416
+ };
417
+ }
418
+ function je(e, t) {
419
+ let r = e.tools.find((e) => e.name === t);
420
+ if (!r) throw new n(`Tool '${t}' is not exposed by builtin node '${e.id}'.`);
421
+ return r;
422
+ }
423
+ function Me(e) {
424
+ return e && typeof e == "object" && !Array.isArray(e) && "arguments" in e ? e.arguments ?? {} : e ?? {};
425
+ }
426
+ //#endregion
427
+ //#region src/worker/tb/materialize.ts
428
+ function Ne(e, t) {
429
+ let n = {};
430
+ for (let [r, i] of Object.entries(t ?? {})) n[r] = Pe(e, i);
431
+ return n;
432
+ }
433
+ function Pe(e, t) {
434
+ return t.startsWith("$env:") ? Fe(e, t.slice(5)) : t.replace(/\$\{([A-Z0-9_]+)\}/g, (t, n) => Fe(e, n));
435
+ }
436
+ function Fe(e, t) {
437
+ let n = e[t];
438
+ if (typeof n != "string" || n.length === 0) throw Error(`Environment variable '${t}' is required for header substitution.`);
439
+ return n;
440
+ }
441
+ function Ie(e, t, n) {
442
+ let r = new URL(t);
443
+ if (r.protocol !== "https:" && e.ALLOW_INSECURE_MCP_HTTP !== "true") throw Error(`${n} must use https://.`);
444
+ return r.toString();
445
+ }
446
+ function Le(e, t) {
447
+ let n = (e.HTBP_REMOTE_ALLOWLIST || "").split(",").map((e) => e.trim().toLowerCase()).filter((e) => e.length > 0);
448
+ if (n.length === 0) return;
449
+ let r = new URL(t).hostname.toLowerCase();
450
+ if (!n.some((e) => r === e || r.endsWith(`.${e}`))) throw Error(`Remote host '${r}' is not in HTBP_REMOTE_ALLOWLIST.`);
451
+ }
452
+ //#endregion
453
+ //#region src/worker/tb/remote-client.ts
454
+ var Re = [
455
+ "directory",
456
+ "mcp",
457
+ "http",
458
+ "remote"
459
+ ];
460
+ async function ze(t, n, r) {
461
+ let a = Ie(t, n, `Remote help URL '${n}'`);
462
+ Le(t, a);
463
+ let o = new Headers(Ne(t, r));
464
+ o.set("Accept", "application/json");
465
+ let s = new AbortController(), c = setTimeout(() => s.abort(), m);
466
+ try {
467
+ let e = await fetch(a, {
468
+ method: "GET",
469
+ headers: o,
470
+ signal: s.signal
471
+ });
472
+ if (!e.ok) throw new i(`Remote help '${a}' returned ${e.status}: ${await ee(e)}`, {
473
+ upstream: a,
474
+ status: e.status
475
+ });
476
+ return Be(await C(e, p));
477
+ } catch (t) {
478
+ throw t instanceof e ? t : new i(`Remote help '${a}' failed: ${S(t)}`, { upstream: a });
479
+ } finally {
480
+ clearTimeout(c);
481
+ }
482
+ }
483
+ function Be(e) {
484
+ let t = JSON.parse(e);
485
+ if (!_(t)) throw Error("Remote help payload is not a JSON object.");
486
+ return {
487
+ htbp: "draft",
488
+ kind: typeof t.kind == "string" && Re.includes(t.kind) ? t.kind : "directory",
489
+ title: typeof t.title == "string" ? t.title : "Remote TB Server",
490
+ description: typeof t.description == "string" ? t.description : void 0,
491
+ cachable: t.cachable === !0,
492
+ resources: Ve(t.resources),
493
+ endpoint: _(t.endpoint) ? He(t.endpoint) : void 0
494
+ };
495
+ }
496
+ function Ve(e) {
497
+ if (!Array.isArray(e)) return;
498
+ let t = [];
499
+ for (let n of e) _(n) && typeof n.name == "string" && typeof n.path == "string" && t.push({
500
+ name: n.name,
501
+ path: n.path,
502
+ description: typeof n.description == "string" ? n.description : void 0
503
+ });
504
+ return t;
505
+ }
506
+ function He(e) {
507
+ let t = (Array.isArray(e.tools) ? e.tools : void 0)?.filter((e) => _(e) && typeof e.name == "string").map((e) => ({
508
+ name: e.name,
509
+ description: typeof e.description == "string" ? e.description : void 0,
510
+ inputSchema: e.inputSchema,
511
+ outputSchema: e.outputSchema
512
+ }));
513
+ return {
514
+ method: typeof e.method == "string" ? e.method : "POST",
515
+ inputSchema: e.inputSchema,
516
+ outputSchema: e.outputSchema,
517
+ example: e.example,
518
+ tools: t
519
+ };
520
+ }
521
+ //#endregion
522
+ //#region src/worker/tb/adapters/directory.ts
523
+ var Ue = {
524
+ kind: "directory",
525
+ async describe(e, t, r) {
526
+ if (r.length > 0) throw new n(`No child '${r[0]}' under directory '${e.id}'.`);
527
+ let i = await Promise.all(e.children.map((e) => We(e, t)));
528
+ return {
529
+ htbp: "draft",
530
+ kind: "directory",
531
+ title: e.title,
532
+ description: e.summary,
533
+ cachable: !0,
534
+ resources: i
535
+ };
536
+ },
537
+ async call(e) {
538
+ throw Error(`Directory '${e.id}' is not callable; descend to an end-path resource.`);
539
+ }
540
+ };
541
+ async function We(e, t) {
542
+ let n = {
543
+ name: e.title,
544
+ path: `./${encodeURIComponent(e.id)}`,
545
+ description: Ke(e)
546
+ };
547
+ return e.kind === "remote" && await Ge(e, t, n), n;
548
+ }
549
+ async function Ge(e, t, n) {
550
+ try {
551
+ let r = await ze(t.env, e.helpUrl, e.headers);
552
+ r.title && (n.name = r.title), r.description && (n.description = r.description);
553
+ } catch {}
554
+ }
555
+ function Ke(e) {
556
+ return e.kind === "directory" || e.kind === "http" || e.kind === "remote" ? e.summary : e.description;
557
+ }
558
+ //#endregion
559
+ //#region src/worker/tb/adapters/http.ts
560
+ var qe = {
561
+ kind: "http",
562
+ async describe(e, t, n) {
563
+ if (n.length === 0) return {
564
+ htbp: "draft",
565
+ kind: "http",
566
+ title: e.title,
567
+ description: e.summary,
568
+ cachable: !0,
569
+ resources: e.endpoints.map(Je)
570
+ };
571
+ let r = Ye(e, n[0]);
572
+ return {
573
+ htbp: "draft",
574
+ kind: "http",
575
+ title: r.name,
576
+ description: r.description,
577
+ cachable: !0,
578
+ endpoint: {
579
+ method: r.method,
580
+ inputSchema: r.inputSchema ?? {},
581
+ outputSchema: r.outputSchema,
582
+ example: r.example,
583
+ effect: r.effect,
584
+ scope: r.scope,
585
+ confirm: r.confirm
586
+ }
587
+ };
588
+ },
589
+ async call(e, t, n, r) {
590
+ if (n.length === 0) throw Error(`HTTP node '${e.id}' requires an endpoint name to call.`);
591
+ let a = Ye(e, n[0]), o = Ie(t.env, a.url, `HTTP endpoint '${a.name}'`);
592
+ Le(t.env, o);
593
+ let s = new Headers(Ne(t.env, a.headers)), c = a.method !== "GET" && a.method !== "HEAD";
594
+ c && !s.has("Content-Type") && s.set("Content-Type", "application/json"), s.set("Accept", s.get("Accept") ?? "application/json"), s.has("User-Agent") || s.set("User-Agent", "tool-bridge");
595
+ let l = new AbortController(), u = setTimeout(() => l.abort(), m);
596
+ try {
597
+ let t;
598
+ try {
599
+ t = await fetch(o, {
600
+ method: a.method,
601
+ headers: s,
602
+ body: c ? JSON.stringify(r ?? {}) : void 0,
603
+ signal: l.signal
604
+ });
605
+ } catch (t) {
606
+ throw new i(`HTTP endpoint '${a.name}' fetch failed: ${S(t)}`, {
607
+ upstream: e.id,
608
+ endpoint: a.name
609
+ });
610
+ }
611
+ if (!t.ok) throw new i(`HTTP endpoint '${a.name}' returned ${t.status}: ${await ee(t)}`, {
612
+ upstream: e.id,
613
+ endpoint: a.name,
614
+ status: t.status
615
+ });
616
+ let n = await C(t, p), u = t.headers.get("Content-Type") ?? "";
617
+ try {
618
+ return u.includes("application/json") && n ? JSON.parse(n) : n;
619
+ } catch (t) {
620
+ throw new i(`HTTP endpoint '${a.name}' returned malformed JSON: ${S(t)}`, {
621
+ upstream: e.id,
622
+ endpoint: a.name
623
+ });
624
+ }
625
+ } finally {
626
+ clearTimeout(u);
627
+ }
628
+ }
629
+ };
630
+ function Je(e) {
631
+ return {
632
+ name: e.name,
633
+ path: `./${encodeURIComponent(e.name)}`,
634
+ description: e.description ? x(e.description) : void 0
635
+ };
636
+ }
637
+ function Ye(e, t) {
638
+ let r = e.endpoints.find((e) => e.name === t);
639
+ if (!r) throw new n(`Endpoint '${t}' not found on HTTP node '${e.id}'.`);
640
+ return r;
641
+ }
642
+ //#endregion
643
+ //#region src/worker/tb/mcp-client.ts
644
+ function Xe(e, t) {
645
+ return {
646
+ id: t.id,
647
+ endpoint: Ie(e, t.endpoint, `MCP endpoint for '${t.id}'`),
648
+ allowedTools: t.allowedTools,
649
+ resolvedHeaders: Ne(e, t.headers)
650
+ };
651
+ }
652
+ async function Ze(e) {
653
+ let t = await $e(e, "tools/list", {}), n = (_(t) && Array.isArray(t.tools) ? t.tools : []).map(ct).filter(Boolean);
654
+ if (!e.allowedTools || e.allowedTools.length === 0) return n;
655
+ let r = new Set(e.allowedTools);
656
+ return n.filter((e) => r.has(e.name));
657
+ }
658
+ async function Qe(e, t, r) {
659
+ if (e.allowedTools && e.allowedTools.length > 0 && !e.allowedTools.includes(t)) throw new n(`Tool '${t}' is not allowed for server '${e.id}'.`);
660
+ return $e(e, "tools/call", {
661
+ name: t,
662
+ arguments: _(r) ? r : {}
663
+ });
664
+ }
665
+ async function $e(t, n, r) {
666
+ try {
667
+ let e = await et(t);
668
+ try {
669
+ return await tt(t, e.sessionId, "notifications/initialized", {}), (await nt(t, e.sessionId, n, r)).result;
670
+ } finally {
671
+ e.sessionId && await st(t, e.sessionId).catch(() => {});
672
+ }
673
+ } catch (r) {
674
+ throw r instanceof e ? r : new i(`MCP server '${t.id}': ${S(r)}`, {
675
+ upstream: t.id,
676
+ method: n
677
+ });
678
+ }
679
+ }
680
+ async function et(e) {
681
+ return { sessionId: (await nt(e, void 0, "initialize", {
682
+ protocolVersion: u,
683
+ capabilities: {},
684
+ clientInfo: {
685
+ name: d,
686
+ version: f
687
+ }
688
+ })).sessionId };
689
+ }
690
+ async function tt(e, t, n, r) {
691
+ let i = await fetch(e.endpoint, {
692
+ method: "POST",
693
+ headers: rt(e, t),
694
+ body: JSON.stringify({
695
+ jsonrpc: "2.0",
696
+ method: n,
697
+ params: r
698
+ })
699
+ });
700
+ if (i.status !== 202 && !i.ok) throw Error(`MCP notification '${n}' failed with HTTP ${i.status}.`);
701
+ }
702
+ async function nt(e, t, n, r) {
703
+ let i = crypto.randomUUID(), a = await fetch(e.endpoint, {
704
+ method: "POST",
705
+ headers: rt(e, t),
706
+ body: JSON.stringify({
707
+ jsonrpc: "2.0",
708
+ id: i,
709
+ method: n,
710
+ params: r
711
+ })
712
+ });
713
+ if (!a.ok) throw Error(`MCP request '${n}' failed with HTTP ${a.status}: ${await ee(a)}`);
714
+ let o = await it(a, i);
715
+ if (o.error) throw Error(`MCP error ${o.error.code}: ${o.error.message}`);
716
+ return {
717
+ result: o.result,
718
+ sessionId: a.headers.get("MCP-Session-Id") ?? void 0
719
+ };
720
+ }
721
+ function rt(e, t) {
722
+ let n = new Headers(e.resolvedHeaders);
723
+ return n.set("Accept", "application/json, text/event-stream"), n.set("Content-Type", "application/json"), n.set("MCP-Protocol-Version", u), t && n.set("MCP-Session-Id", t), n;
724
+ }
725
+ async function it(e, t) {
726
+ if ((e.headers.get("Content-Type") ?? "").includes("text/event-stream")) return at(e, t);
727
+ let n = await C(e, p), r = JSON.parse(n);
728
+ if (r.id !== t) throw Error(`Unexpected MCP response id '${String(r.id)}'.`);
729
+ return r;
730
+ }
731
+ async function at(e, t) {
732
+ if (!e.body) throw Error("MCP server returned an empty SSE response.");
733
+ let n = e.body.getReader(), r = new TextDecoder(), i = "", a = [], o = 0;
734
+ for (;;) {
735
+ let { done: e, value: s } = await n.read();
736
+ if (e) break;
737
+ if (o += s.byteLength, o > 4e6) throw Error("MCP SSE response exceeded the maximum size.");
738
+ i += r.decode(s, { stream: !0 });
739
+ let c = i.indexOf("\n");
740
+ for (; c >= 0;) {
741
+ let e = i.slice(0, c);
742
+ i = i.slice(c + 1);
743
+ let n = e.endsWith("\r") ? e.slice(0, -1) : e;
744
+ if (n === "") {
745
+ let e = ot(a);
746
+ if (a = [], e && e.id === t) return e;
747
+ } else n.startsWith("data:") && a.push(n.slice(5).trimStart());
748
+ c = i.indexOf("\n");
749
+ }
750
+ }
751
+ let s = ot(a);
752
+ if (s && s.id === t) return s;
753
+ throw Error(`MCP SSE stream ended before response '${t}' was received.`);
754
+ }
755
+ function ot(e) {
756
+ if (e.length === 0) return;
757
+ let t = e.join("\n").trim();
758
+ if (t.startsWith("{")) return JSON.parse(t);
759
+ }
760
+ async function st(e, t) {
761
+ await fetch(e.endpoint, {
762
+ method: "DELETE",
763
+ headers: rt(e, t)
764
+ });
765
+ }
766
+ function ct(e) {
767
+ if (!(!_(e) || typeof e.name != "string")) return {
768
+ name: e.name,
769
+ description: typeof e.description == "string" ? e.description : void 0,
770
+ inputSchema: e.inputSchema,
771
+ outputSchema: e.outputSchema,
772
+ annotations: e.annotations
773
+ };
774
+ }
775
+ //#endregion
776
+ //#region src/worker/tb/virtualize.ts
777
+ function lt(e, t) {
778
+ let n = e.toolOverrides ?? {}, r = [], i = /* @__PURE__ */ new Map();
779
+ for (let a of t) {
780
+ let t = n[a.name];
781
+ if (t?.hide) continue;
782
+ let o = dt(e.namespace, t?.rename ?? a.name);
783
+ i.set(o, a.name), r.push({
784
+ name: o,
785
+ description: t?.description ?? a.description,
786
+ inputSchema: a.inputSchema,
787
+ outputSchema: a.outputSchema,
788
+ effect: t?.effect ?? a.effect,
789
+ scope: t?.scope ?? a.scope,
790
+ confirm: t?.confirm ?? a.confirm
791
+ });
792
+ }
793
+ return {
794
+ exposed: r,
795
+ reverse: i
796
+ };
797
+ }
798
+ function ut(e, t, r) {
799
+ let { reverse: i } = lt(e, t), a = i.get(r);
800
+ if (!a) throw new n(`Tool '${r}' is not exposed by node '${e.id}'.`);
801
+ return a;
802
+ }
803
+ function dt(e, t) {
804
+ return e ? `${e}__${t}` : t;
805
+ }
806
+ //#endregion
807
+ //#region src/worker/tb/adapters/mcp.ts
808
+ var ft = {
809
+ kind: "mcp",
810
+ async describe(e, t, r) {
811
+ let { exposed: i } = lt(e, (await Ze(Xe(t.env, e))).map(mt));
812
+ if (r.length === 0) return {
813
+ htbp: "draft",
814
+ kind: "mcp",
815
+ title: e.title,
816
+ description: e.description,
817
+ cachable: !0,
818
+ resources: i.map(pt)
819
+ };
820
+ let a = r[0], o = i.find((e) => e.name === a);
821
+ if (!o) throw new n(`Tool '${a}' is not exposed by node '${e.id}'.`);
822
+ return {
823
+ htbp: "draft",
824
+ kind: "mcp",
825
+ title: o.name,
826
+ description: o.description,
827
+ cachable: !0,
828
+ endpoint: {
829
+ method: "POST",
830
+ inputSchema: o.inputSchema ?? { type: "object" },
831
+ outputSchema: o.outputSchema,
832
+ example: {},
833
+ effect: o.effect,
834
+ scope: o.scope,
835
+ confirm: o.confirm
836
+ }
837
+ };
838
+ },
839
+ async call(e, t, n, r) {
840
+ if (n.length === 0) throw Error(`MCP node '${e.id}' requires a tool: call POST {path}/{tool}.`);
841
+ let i = Xe(t.env, e);
842
+ return Qe(i, ut(e, (await Ze(i)).map(mt), n[0]), ht(r));
843
+ }
844
+ };
845
+ function pt(e) {
846
+ return {
847
+ name: e.name,
848
+ path: `./${encodeURIComponent(e.name)}`,
849
+ description: e.description
850
+ };
851
+ }
852
+ function mt(e) {
853
+ return {
854
+ name: e.name,
855
+ description: e.description ? x(e.description) : void 0,
856
+ inputSchema: e.inputSchema,
857
+ outputSchema: e.outputSchema
858
+ };
859
+ }
860
+ function ht(e) {
861
+ return e && typeof e == "object" && !Array.isArray(e) && "arguments" in e ? e.arguments ?? {} : e ?? {};
862
+ }
863
+ //#endregion
864
+ //#region src/worker/tb/storage-r2.ts
865
+ var gt = "/", _t = 1e6;
866
+ function vt(e, t) {
867
+ let n = e[t];
868
+ if (!n || typeof n.list != "function") throw Error(`R2 bucket binding '${t}' is not configured on this Worker.`);
869
+ return {
870
+ async list(e) {
871
+ let t = e && !e.endsWith(gt) ? `${e}${gt}` : e, r = await n.list({
872
+ prefix: t,
873
+ delimiter: gt
874
+ }), i = r.delimitedPrefixes.map((e) => ({
875
+ name: yt(e.replace(/\/$/, ""), t),
876
+ key: e,
877
+ isDir: !0
878
+ })), a = r.objects.filter((e) => e.key !== t).map((e) => ({
879
+ name: yt(e.key, t),
880
+ key: e.key,
881
+ isDir: !1
882
+ }));
883
+ return [...i, ...a];
884
+ },
885
+ async get(e) {
886
+ let t = await n.get(e);
887
+ if (!t) return null;
888
+ if (typeof t.size == "number" && t.size > _t) throw Error(`Object '${e}' exceeds the maximum readable size.`);
889
+ return {
890
+ key: e,
891
+ body: await t.text(),
892
+ contentType: t.httpMetadata?.contentType,
893
+ size: t.size
894
+ };
895
+ }
896
+ };
897
+ }
898
+ function yt(e, t) {
899
+ return t && e.startsWith(t) ? e.slice(t.length) : e;
900
+ }
901
+ //#endregion
902
+ //#region src/worker/tb/adapters/mount.ts
903
+ var bt = {
904
+ kind: "mount",
905
+ async describe(e, t, r) {
906
+ let i = xt(t, e), a = St(e, r), o = await i.get(a);
907
+ if (o) return {
908
+ htbp: "draft",
909
+ kind: "mount",
910
+ title: r[r.length - 1] ?? e.title,
911
+ description: `File ${a} (${o.contentType ?? "application/octet-stream"})`,
912
+ cachable: !0,
913
+ endpoint: {
914
+ method: "GET",
915
+ inputSchema: {},
916
+ outputSchema: { type: "string" },
917
+ example: {}
918
+ }
919
+ };
920
+ let s = await i.list(a);
921
+ if (s.length === 0 && r.length > 0) throw new n(`No file or folder at '${a}'.`);
922
+ return {
923
+ htbp: "draft",
924
+ kind: "mount",
925
+ title: r.length === 0 ? e.title : r[r.length - 1] ?? e.title,
926
+ description: e.description,
927
+ cachable: !0,
928
+ resources: s.map(wt)
929
+ };
930
+ },
931
+ async call(e, t, r) {
932
+ let i = xt(t, e), a = St(e, r), o = await i.get(a);
933
+ if (!o) throw new n(`File '${a}' not found.`);
934
+ return {
935
+ key: o.key,
936
+ contentType: o.contentType,
937
+ content: o.body
938
+ };
939
+ }
940
+ };
941
+ function xt(e, t) {
942
+ return vt(e.env, t.bucket);
943
+ }
944
+ function St(e, t) {
945
+ return [e.prefix ? Ct(e.prefix) : "", t.map((e) => decodeURIComponent(e)).join("/")].filter((e) => e.length > 0).join("/");
946
+ }
947
+ function Ct(e) {
948
+ return e.replace(/^\/+|\/+$/g, "");
949
+ }
950
+ function wt(e) {
951
+ return {
952
+ name: e.name,
953
+ path: `./${encodeURIComponent(e.name)}`,
954
+ description: e.isDir ? "folder" : "file"
955
+ };
956
+ }
957
+ //#endregion
958
+ //#region src/worker/tb/adapters/index.ts
959
+ var Tt = {
960
+ directory: Ue,
961
+ mcp: ft,
962
+ http: qe,
963
+ remote: {
964
+ kind: "remote",
965
+ async describe(e, t) {
966
+ let n = await ze(t.env, e.helpUrl, e.headers);
967
+ return {
968
+ ...n,
969
+ kind: "remote",
970
+ title: n.title || e.title
971
+ };
972
+ },
973
+ async call(e) {
974
+ throw Error(`Remote node '${e.id}' is a federation pointer; call the remote TB Server directly at its own endpoint.`);
975
+ }
976
+ },
977
+ mount: bt,
978
+ builtin: ke
979
+ };
980
+ function Et(e) {
981
+ let t = Tt[e.kind];
982
+ if (!t) throw Error(`No adapter registered for node kind '${e.kind}'.`);
983
+ return t;
984
+ }
985
+ //#endregion
986
+ //#region src/worker/tb/crawl.ts
987
+ var Dt = {
988
+ maxDepth: 8,
989
+ maxNodes: 200
990
+ }, Ot = 8, kt = 200;
991
+ function At(e) {
992
+ return {
993
+ maxDepth: Ut(e?.maxDepth ?? Dt.maxDepth, 1, Ot),
994
+ maxNodes: Ut(e?.maxNodes ?? Dt.maxNodes, 1, kt)
995
+ };
996
+ }
997
+ async function jt(e, t, n, r, i = Dt) {
998
+ let a = {
999
+ env: e,
1000
+ root: t,
1001
+ authMode: r,
1002
+ opts: i,
1003
+ visited: /* @__PURE__ */ new Set(),
1004
+ count: 0
1005
+ };
1006
+ return n.url ? Nt(a, n.url, 0) : Mt(a, It(n.path ?? ""), 0);
1007
+ }
1008
+ async function Mt(e, t, n) {
1009
+ let r = E(e.root, t), i = t.length === 0 ? w : `${w}/${t.join("/")}`;
1010
+ if (!r) return {
1011
+ kind: "directory",
1012
+ path: i,
1013
+ helpUrl: `${i}/~help`,
1014
+ children: [],
1015
+ error: "Resource not found."
1016
+ };
1017
+ let a = i, o = {
1018
+ env: e.env,
1019
+ authMode: e.authMode,
1020
+ basePath: _e(r.node)
1021
+ };
1022
+ if (r.node.kind === "remote") return Nt(e, r.node.helpUrl, n, a);
1023
+ let s;
1024
+ try {
1025
+ s = await Et(r.node).describe(r.node, o, r.sub);
1026
+ } catch (e) {
1027
+ return {
1028
+ kind: r.node.kind,
1029
+ path: a,
1030
+ helpUrl: `${a}/~help`,
1031
+ children: [],
1032
+ error: Ht(e)
1033
+ };
1034
+ }
1035
+ return Pt(e, Ft(s, a, `${a}/~help`), s, n, (t) => Mt(e, t, n + 1), a);
1036
+ }
1037
+ async function Nt(e, t, n, r) {
1038
+ let i = Vt(t), a = r ?? t, o;
1039
+ try {
1040
+ o = await ze(e.env, t, void 0);
1041
+ } catch (e) {
1042
+ return {
1043
+ kind: "remote",
1044
+ path: a,
1045
+ helpUrl: t,
1046
+ children: [],
1047
+ error: Ht(e)
1048
+ };
1049
+ }
1050
+ let s = Ft(o, a, t);
1051
+ return s.kind = "remote", Pt(e, s, o, n, (t, r) => Nt(e, r, n + 1), i, t);
1052
+ }
1053
+ async function Pt(e, t, n, r, i, a, o) {
1054
+ if (n.endpoint) return t.endpoint = n.endpoint, t;
1055
+ if (e.visited.has(a) || (e.visited.add(a), r >= e.opts.maxDepth)) return t.truncated = !0, t;
1056
+ for (let r of n.resources ?? []) {
1057
+ if (e.count >= e.opts.maxNodes) {
1058
+ t.truncated = !0;
1059
+ break;
1060
+ }
1061
+ if (e.count += 1, o) {
1062
+ let e = zt(o, r.path);
1063
+ t.children.push(await i([], e));
1064
+ } else {
1065
+ let e = Lt(t.path, r.path);
1066
+ t.children.push(await i(e, ""));
1067
+ }
1068
+ }
1069
+ return t;
1070
+ }
1071
+ function Ft(e, t, n) {
1072
+ return {
1073
+ kind: e.kind,
1074
+ path: t,
1075
+ title: e.title,
1076
+ description: e.description,
1077
+ helpUrl: n,
1078
+ children: []
1079
+ };
1080
+ }
1081
+ function It(e) {
1082
+ return e.replace(/^\/?htbp\/?/, "").split("/").map((e) => e.trim()).filter((e) => e.length > 0);
1083
+ }
1084
+ function Lt(e, t) {
1085
+ let n = It(e);
1086
+ return t.startsWith("../") ? [...n.slice(0, -1), ...Rt(t.slice(3))] : t.startsWith("./") ? [...n, ...Rt(t.slice(2))] : [...n, ...Rt(t)];
1087
+ }
1088
+ function Rt(e) {
1089
+ return e.split("/").filter((e) => e.length > 0);
1090
+ }
1091
+ function zt(e, t) {
1092
+ let n = e.replace(/\/~help$/, "/");
1093
+ return new URL(t.endsWith("/~help") ? t : `${Bt(t)}/~help`, n).toString();
1094
+ }
1095
+ function Bt(e) {
1096
+ return e.endsWith("/") ? e.slice(0, -1) : e;
1097
+ }
1098
+ function Vt(e) {
1099
+ try {
1100
+ return new URL(e).toString();
1101
+ } catch {
1102
+ return e;
1103
+ }
1104
+ }
1105
+ function Ht(e) {
1106
+ return e instanceof Error ? e.message : String(e);
1107
+ }
1108
+ function Ut(e, t, n) {
1109
+ return Number.isFinite(e) ? Math.max(t, Math.min(n, Math.floor(e))) : t;
1110
+ }
1111
+ //#endregion
1112
+ //#region src/worker/tb/entities.ts
1113
+ var Wt = "_global";
1114
+ function D(e) {
1115
+ return e ?? Wt;
1116
+ }
1117
+ function O() {
1118
+ return (/* @__PURE__ */ new Date()).toISOString();
1119
+ }
1120
+ function k(e) {
1121
+ if (!e.TENANTS) throw new s("Provider entities require the TENANTS KV binding.");
1122
+ return e.TENANTS;
1123
+ }
1124
+ function Gt(e) {
1125
+ return !!e.TENANTS;
1126
+ }
1127
+ var Kt = [
1128
+ "builtin",
1129
+ "first-party",
1130
+ "verified",
1131
+ "community",
1132
+ "federated"
1133
+ ], qt = [
1134
+ "active",
1135
+ "suspended",
1136
+ "retired"
1137
+ ], Jt = [
1138
+ "draft",
1139
+ "published",
1140
+ "deprecated",
1141
+ "retired"
1142
+ ], Yt = /^[a-z0-9][a-z0-9._-]{0,63}$/;
1143
+ function A(e, t) {
1144
+ if (!e || !Yt.test(e)) throw new s(`${t} must match ${Yt} (lowercase alphanumeric, ".", "_", "-").`);
1145
+ return e;
1146
+ }
1147
+ async function j(e, t) {
1148
+ return await k(e).get(`provider:${t}`, "json");
1149
+ }
1150
+ async function M(e, t) {
1151
+ await k(e).put(`provider:${t.id}`, JSON.stringify(t));
1152
+ }
1153
+ async function Xt(e, t) {
1154
+ await k(e).delete(`provider:${t}`);
1155
+ }
1156
+ async function Zt(e) {
1157
+ return hn(e, "provider:");
1158
+ }
1159
+ function Qt(e, t) {
1160
+ if (!_(e)) throw new s("Provider must be a JSON object.");
1161
+ let n = t?.id ?? A(v(e, "id"), "provider id"), r = v(e, "trustTier") ?? t?.trustTier ?? "community";
1162
+ if (!Kt.includes(r)) throw new s(`trustTier must be one of ${Kt.join(", ")}.`);
1163
+ let i = v(e, "status") ?? t?.status ?? "active";
1164
+ if (!qt.includes(i)) throw new s(`status must be one of ${qt.join(", ")}.`);
1165
+ return {
1166
+ id: n,
1167
+ displayName: v(e, "displayName") ?? t?.displayName ?? n,
1168
+ contact: v(e, "contact") ?? t?.contact,
1169
+ trustTier: r,
1170
+ status: i,
1171
+ createdAt: t?.createdAt ?? O(),
1172
+ updatedAt: O()
1173
+ };
1174
+ }
1175
+ async function N(e, t, n) {
1176
+ return await k(e).get(`pub:${t}:${n}`, "json");
1177
+ }
1178
+ async function P(e, t) {
1179
+ await k(e).put(`pub:${t.providerId}:${t.pubId}`, JSON.stringify(t));
1180
+ }
1181
+ async function $t(e, t, n) {
1182
+ await k(e).delete(`pub:${t}:${n}`);
1183
+ }
1184
+ async function F(e, t) {
1185
+ return hn(e, `pub:${t}:`);
1186
+ }
1187
+ function en(e, t, n) {
1188
+ if (!_(e)) throw new s("Publication must be a JSON object.");
1189
+ let r = n?.pubId ?? A(v(e, "pubId") ?? v(e, "id"), "pubId"), i = v(e, "status") ?? n?.status ?? "draft";
1190
+ if (!Jt.includes(i)) throw new s(`status must be one of ${Jt.join(", ")}.`);
1191
+ let a = _(e.binding) ? e.binding : n?.binding;
1192
+ if (!a) throw new s("Publication binding is required.");
1193
+ let o = _(e.shaping) ? e.shaping : n?.shaping, c = tn(e.semantics) ?? n?.semantics, l = {
1194
+ providerId: t,
1195
+ pubId: r,
1196
+ version: v(e, "version") ?? n?.version ?? "0.1.0",
1197
+ binding: a,
1198
+ shaping: o,
1199
+ semantics: c,
1200
+ status: i,
1201
+ createdAt: n?.createdAt ?? O(),
1202
+ updatedAt: O()
1203
+ };
1204
+ return ln(l, "binding-check"), l;
1205
+ }
1206
+ function tn(e) {
1207
+ if (!_(e)) return;
1208
+ let t = {};
1209
+ for (let [n, r] of Object.entries(e)) {
1210
+ if (!_(r)) continue;
1211
+ let e = r.effect;
1212
+ t[n] = {
1213
+ effect: e === "read" || e === "write" || e === "destructive" || e === "external" ? e : void 0,
1214
+ scope: v(r, "scope"),
1215
+ confirm: r.confirm === !0 ? !0 : void 0
1216
+ };
1217
+ }
1218
+ return Object.keys(t).length > 0 ? t : void 0;
1219
+ }
1220
+ async function nn(e, t, n) {
1221
+ return await k(e).get(`placement:${D(t)}:${n}`, "json");
1222
+ }
1223
+ async function rn(e, t) {
1224
+ await k(e).put(`placement:${D(t.tenantId)}:${t.id}`, JSON.stringify(t));
1225
+ }
1226
+ async function an(e, t, n) {
1227
+ await k(e).delete(`placement:${D(t)}:${n}`);
1228
+ }
1229
+ async function on(e, t) {
1230
+ return hn(e, `placement:${D(t)}:`);
1231
+ }
1232
+ function sn(e) {
1233
+ let t = (e ?? "").split("/").map((e) => e.trim()).filter((e) => e.length > 0);
1234
+ if (t.length === 0) throw new s("Placement path is required.");
1235
+ for (let e of t) if (e.startsWith("~") || e === "." || e === ".." || !Yt.test(e)) throw new s(`Placement path segment '${e}' is not allowed.`);
1236
+ return t;
1237
+ }
1238
+ function cn() {
1239
+ return `plc_${[...crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(6))].map((e) => e.toString(16).padStart(2, "0")).join("")}`;
1240
+ }
1241
+ function ln(e, t) {
1242
+ let n = {
1243
+ ...un(e.binding),
1244
+ id: t
1245
+ };
1246
+ return e.shaping?.namespace && (n.namespace = e.shaping.namespace), e.shaping?.toolOverrides && (n.toolOverrides = {
1247
+ ..._(n.toolOverrides) ? n.toolOverrides : {},
1248
+ ...e.shaping.toolOverrides
1249
+ }), dn(n, e.semantics), ge(n, `pub:${e.providerId}:${e.pubId}`);
1250
+ }
1251
+ function un(e) {
1252
+ return JSON.parse(JSON.stringify(e));
1253
+ }
1254
+ function dn(e, t) {
1255
+ if (!t) return;
1256
+ let n = e.type ?? "mcp";
1257
+ if (n === "mcp") {
1258
+ let n = _(e.toolOverrides) ? { ...e.toolOverrides } : {};
1259
+ for (let [e, r] of Object.entries(t)) n[e] = {
1260
+ ..._(n[e]) ? n[e] : {},
1261
+ ...r
1262
+ };
1263
+ e.toolOverrides = n;
1264
+ return;
1265
+ }
1266
+ let r = n === "http" ? e.endpoints : n === "builtin" ? e.tools : void 0;
1267
+ if (Array.isArray(r)) for (let e of r) _(e) && typeof e.name == "string" && t[e.name] && Object.assign(e, t[e.name]);
1268
+ }
1269
+ async function fn(e, t, n) {
1270
+ let r = {
1271
+ applied: 0,
1272
+ skipped: []
1273
+ };
1274
+ if (!Gt(e)) return r;
1275
+ let i = await on(e, n);
1276
+ if (i.length === 0) return r;
1277
+ let a = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map();
1278
+ for (let n of i) {
1279
+ if (!n.enabled) {
1280
+ r.skipped.push({
1281
+ placementId: n.id,
1282
+ reason: "disabled"
1283
+ });
1284
+ continue;
1285
+ }
1286
+ let { providerId: i, pubId: s, version: c } = n.pubRef;
1287
+ a.has(i) || a.set(i, await j(e, i));
1288
+ let l = a.get(i);
1289
+ if (!l || l.status !== "active") {
1290
+ r.skipped.push({
1291
+ placementId: n.id,
1292
+ reason: `provider ${l ? l.status : "missing"}`
1293
+ });
1294
+ continue;
1295
+ }
1296
+ let u = `${i}:${s}`;
1297
+ o.has(u) || o.set(u, await N(e, i, s));
1298
+ let d = o.get(u);
1299
+ if (!d || d.status !== "published" && d.status !== "deprecated") {
1300
+ r.skipped.push({
1301
+ placementId: n.id,
1302
+ reason: `publication ${d ? d.status : "missing"}`
1303
+ });
1304
+ continue;
1305
+ }
1306
+ if (c && pn(c) !== pn(d.version)) {
1307
+ r.skipped.push({
1308
+ placementId: n.id,
1309
+ reason: `version pin ${c} != ${d.version}`
1310
+ });
1311
+ continue;
1312
+ }
1313
+ let f, p;
1314
+ try {
1315
+ f = sn(n.path), p = ln(d, f[f.length - 1]);
1316
+ } catch (e) {
1317
+ r.skipped.push({
1318
+ placementId: n.id,
1319
+ reason: e instanceof Error ? e.message : "invalid"
1320
+ });
1321
+ continue;
1322
+ }
1323
+ Object.defineProperty(p, "tbProviderId", {
1324
+ value: l.id,
1325
+ enumerable: !1,
1326
+ writable: !0,
1327
+ configurable: !0
1328
+ }), mn(t, f.slice(0, -1), p) ? r.applied += 1 : r.skipped.push({
1329
+ placementId: n.id,
1330
+ reason: "path conflict"
1331
+ });
1332
+ }
1333
+ return r.applied > 0 && T(t), r;
1334
+ }
1335
+ function pn(e) {
1336
+ return e.split(".")[0] ?? e;
1337
+ }
1338
+ function mn(e, t, n) {
1339
+ let r = e;
1340
+ for (let e of t) {
1341
+ let t = r.children.find((t) => t.id === e);
1342
+ if (t || (t = {
1343
+ kind: "directory",
1344
+ id: e,
1345
+ title: e,
1346
+ children: []
1347
+ }, r.children.push(t)), t.kind !== "directory") return !1;
1348
+ r = t;
1349
+ }
1350
+ return r.children.some((e) => e.id === n.id) ? !1 : (r.children.push(n), !0);
1351
+ }
1352
+ async function hn(e, t) {
1353
+ let n = k(e), r = [], i;
1354
+ do {
1355
+ let e = await n.list({
1356
+ prefix: t,
1357
+ cursor: i
1358
+ }), a = await Promise.all(e.keys.map((e) => n.get(e.name, "json")));
1359
+ for (let e of a) e && r.push(e);
1360
+ i = e.list_complete ? void 0 : e.cursor;
1361
+ } while (i);
1362
+ return r;
1363
+ }
1364
+ //#endregion
1365
+ //#region src/worker/tb/tenant.ts
1366
+ function gn(e) {
1367
+ return !!e.TENANTS && e.TENANT_MODE === "true";
1368
+ }
1369
+ async function _n(e) {
1370
+ let t = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(e));
1371
+ return [...new Uint8Array(t)].map((e) => e.toString(16).padStart(2, "0")).join("");
1372
+ }
1373
+ var vn = [
1374
+ "agent",
1375
+ "provider",
1376
+ "host",
1377
+ "admin",
1378
+ "service"
1379
+ ];
1380
+ async function yn(e, t) {
1381
+ if (!e.TENANTS) return null;
1382
+ let n = await _n(t), r = await e.TENANTS.get(`apikey:${n}`, "json");
1383
+ if (!_(r)) return null;
1384
+ let i = vn.includes(r.principal) ? r.principal : "agent", a = {
1385
+ principal: i,
1386
+ tenantId: typeof r.tenantId == "string" ? r.tenantId : void 0,
1387
+ providerId: typeof r.providerId == "string" ? r.providerId : void 0,
1388
+ hostId: typeof r.hostId == "string" ? r.hostId : void 0,
1389
+ label: typeof r.label == "string" ? r.label : void 0,
1390
+ createdAt: typeof r.createdAt == "string" ? r.createdAt : void 0,
1391
+ expiresAt: typeof r.expiresAt == "string" ? r.expiresAt : void 0
1392
+ };
1393
+ if (a.expiresAt && Date.parse(a.expiresAt) < Date.now()) return null;
1394
+ if (a.tenantId) {
1395
+ let t = await e.TENANTS.get(`tenant:${a.tenantId}`);
1396
+ if (t) a.root = ne(t);
1397
+ else if (i === "agent") return null;
1398
+ } else if (i === "agent") return null;
1399
+ return a;
1400
+ }
1401
+ function bn(e) {
1402
+ return `${e}_${[...crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(16))].map((e) => e.toString(16).padStart(2, "0")).join("")}`;
1403
+ }
1404
+ async function xn(e, t, n) {
1405
+ if (!e.TENANTS) throw Error("API keys require the TENANTS KV binding.");
1406
+ if (n.expiresAt && Number.isNaN(Date.parse(n.expiresAt))) throw new s("expiresAt must be a valid date string.");
1407
+ await e.TENANTS.put(`apikey:${await _n(t)}`, JSON.stringify(n));
1408
+ }
1409
+ async function Sn(e) {
1410
+ if (!e.TENANTS) return [];
1411
+ let t = [], n;
1412
+ do {
1413
+ let r = await e.TENANTS.list({
1414
+ prefix: "apikey:",
1415
+ cursor: n
1416
+ });
1417
+ for (let n of r.keys) {
1418
+ let r = await e.TENANTS.get(n.name, "json");
1419
+ r && t.push({
1420
+ hash: n.name.slice(7),
1421
+ record: r
1422
+ });
1423
+ }
1424
+ n = r.list_complete ? void 0 : r.cursor;
1425
+ } while (n);
1426
+ return t;
1427
+ }
1428
+ //#endregion
1429
+ //#region src/worker/tb/host-api.ts
1430
+ var Cn = /^[a-z0-9][a-z0-9._-]{0,63}$/, wn = "mnt-", Tn = "mnt_";
1431
+ function I(e) {
1432
+ if (!e.TENANTS) throw new s("Hosts require the TENANTS KV binding.");
1433
+ return e.TENANTS;
1434
+ }
1435
+ async function En(e, t) {
1436
+ return await I(e).get(`host:${t}`, "json");
1437
+ }
1438
+ async function Dn(e, t, r) {
1439
+ let i = new URL(e.url).pathname;
1440
+ if (!i.startsWith("/api/hosts")) return;
1441
+ if (!Gt(t)) return o(501, "not_supported", "Host registration requires the TENANTS KV binding.");
1442
+ if (i === "/api/hosts" && e.method === "POST") return On(r, "Registering hosts"), An(e, t);
1443
+ let s = /^\/api\/hosts\/([^/]+)(?:\/(.*))?$/.exec(i);
1444
+ if (!s) return o(404, "not_found", "API route not found.");
1445
+ let c = decodeURIComponent(s[1] ?? ""), l = s[2] ?? "";
1446
+ if (!r.isAdmin && !(r.principal === "host" && r.hostId === c)) throw new a(`Not allowed to access host '${c}'.`);
1447
+ let u = await En(t, c);
1448
+ if (!u) throw new n(`Host '${c}' not found.`);
1449
+ if (l === "" && e.method === "GET") return h({ host: u });
1450
+ if (l === "keys" && e.method === "POST") {
1451
+ On(r, "Minting host keys");
1452
+ let n = await kn(e), i = bn("tbk"), a = {
1453
+ principal: "host",
1454
+ hostId: c,
1455
+ tenantId: u.tenantId,
1456
+ providerId: u.providerId,
1457
+ label: v(n, "label"),
1458
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1459
+ expiresAt: v(n, "expiresAt")
1460
+ };
1461
+ return await xn(t, i, a), h({
1462
+ key: i,
1463
+ record: a
1464
+ }, { status: 201 });
1465
+ }
1466
+ return l === "mounts:sync" && e.method === "POST" ? Mn(e, t, u) : o(404, "not_found", "API route not found.");
1467
+ }
1468
+ function On(e, t) {
1469
+ if (!e.isAdmin) throw new a(`${t} requires an admin key.`);
1470
+ }
1471
+ async function kn(e) {
1472
+ let t = await e.json().catch(() => void 0);
1473
+ if (!_(t)) throw new s("Request body must be a JSON object.");
1474
+ return t;
1475
+ }
1476
+ async function An(e, t) {
1477
+ let n = await kn(e), r = v(n, "id");
1478
+ if (!r || !Cn.test(r)) throw new s(`Host id must match ${Cn}.`);
1479
+ if (await En(t, r)) return o(409, "conflict", `Host '${r}' already exists.`);
1480
+ let i = v(n, "tenantId") ?? r, a = (/* @__PURE__ */ new Date()).toISOString(), c = {
1481
+ id: r,
1482
+ tenantId: i,
1483
+ providerId: r,
1484
+ confirmDelegated: n.confirmDelegated === !0 ? !0 : void 0,
1485
+ createdAt: a,
1486
+ updatedAt: a
1487
+ };
1488
+ return await j(t, r) || await M(t, {
1489
+ id: r,
1490
+ displayName: v(n, "displayName") ?? r,
1491
+ trustTier: "first-party",
1492
+ status: "active",
1493
+ createdAt: a,
1494
+ updatedAt: a
1495
+ }), await I(t).get(`tenant:${i}`) || await I(t).put(`tenant:${i}`, JSON.stringify({
1496
+ type: "directory",
1497
+ id: "root",
1498
+ title: c.id,
1499
+ children: []
1500
+ })), await I(t).put(`host:${r}`, JSON.stringify(c)), h({ host: c }, { status: 201 });
1501
+ }
1502
+ function jn(e) {
1503
+ return e.replace(/\//g, "-");
1504
+ }
1505
+ async function Mn(e, t, n) {
1506
+ let r = await kn(e);
1507
+ if (!Array.isArray(r.mounts)) throw new s("mounts must be an array of {path, binding}.");
1508
+ let i = r.prune !== !1, a = (/* @__PURE__ */ new Date()).toISOString(), o = [], c = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Set();
1509
+ for (let e of r.mounts) {
1510
+ if (!_(e)) throw new s("Each mount must be an object.");
1511
+ let r = e;
1512
+ if (typeof r.path != "string" || !_(r.binding)) throw new s("Each mount needs a path and a binding object.");
1513
+ let i = jn(r.path), u = `${wn}${i}`;
1514
+ await P(t, en({
1515
+ pubId: u,
1516
+ version: r.version ?? "0.1.0",
1517
+ binding: r.binding,
1518
+ shaping: r.shaping,
1519
+ semantics: r.semantics,
1520
+ status: "published"
1521
+ }, n.providerId)), l.add(u);
1522
+ let d = {
1523
+ id: `${Tn}${i}`,
1524
+ tenantId: n.tenantId,
1525
+ path: r.path,
1526
+ pubRef: {
1527
+ providerId: n.providerId,
1528
+ pubId: u
1529
+ },
1530
+ enabled: !0,
1531
+ createdAt: a,
1532
+ updatedAt: a
1533
+ };
1534
+ await rn(t, d), c.add(d.id), o.push(d);
1535
+ }
1536
+ let u = 0;
1537
+ if (i) {
1538
+ for (let e of await on(t, n.tenantId)) e.id.startsWith(Tn) && !c.has(e.id) && (await an(t, n.tenantId, e.id), u += 1);
1539
+ for (let e of await F(t, n.providerId)) e.pubId.startsWith(wn) && !l.has(e.pubId) && await $t(t, n.providerId, e.pubId);
1540
+ }
1541
+ return await I(t).put(`host:${n.id}`, JSON.stringify({
1542
+ ...n,
1543
+ updatedAt: a
1544
+ })), h({
1545
+ ok: !0,
1546
+ applied: o.length,
1547
+ removed: u,
1548
+ placements: o
1549
+ });
1550
+ }
1551
+ //#endregion
1552
+ //#region src/worker/tb/provider-api.ts
1553
+ var Nn = 1e6;
1554
+ async function L(e) {
1555
+ let t = e.headers.get("Content-Length");
1556
+ if (t && Number(t) > Nn) throw new s("Request body is too large.");
1557
+ let n = await e.json().catch(() => void 0);
1558
+ if (!_(n)) throw new s("Request body must be a JSON object.");
1559
+ return n;
1560
+ }
1561
+ function Pn(e, t) {
1562
+ if (!e.isAdmin && !(e.principal === "provider" && e.providerId === t)) throw new a(`Not allowed to access provider '${t}'.`);
1563
+ }
1564
+ function R(e, t) {
1565
+ if (!e.isAdmin) throw new a(`${t} requires an admin key.`);
1566
+ }
1567
+ async function Fn(e, t, r) {
1568
+ let i = new URL(e.url), s = i.pathname;
1569
+ if (!s.startsWith("/api/providers") && !s.startsWith("/api/placements")) return;
1570
+ if (!Gt(t)) return o(501, "not_supported", "Provider entities require the TENANTS KV binding.");
1571
+ if (s === "/api/placements" && e.method === "GET") {
1572
+ R(r, "Listing placements");
1573
+ let e = i.searchParams.get("tenant"), n = !e || e === "_global" ? null : e;
1574
+ return h({
1575
+ tenantId: D(n),
1576
+ placements: await on(t, n)
1577
+ });
1578
+ }
1579
+ if (s === "/api/placements" && e.method === "POST") return R(r, "Writing placements"), In(e, t);
1580
+ let c = /^\/api\/placements\/([^/]+)$/.exec(s);
1581
+ if (c && e.method === "DELETE") return R(r, "Deleting placements"), Ln(e, t, decodeURIComponent(c[1] ?? ""), i);
1582
+ if (s === "/api/providers" && e.method === "GET") {
1583
+ if (r.isAdmin) return h({ providers: await Zt(t) });
1584
+ if (r.principal === "provider" && r.providerId) {
1585
+ let e = await j(t, r.providerId);
1586
+ return h({ providers: e ? [e] : [] });
1587
+ }
1588
+ throw new a("Listing providers requires an admin or provider key.");
1589
+ }
1590
+ if (s === "/api/providers" && e.method === "POST") {
1591
+ R(r, "Creating providers");
1592
+ let n = Qt(await L(e));
1593
+ return await j(t, n.id) ? o(409, "conflict", `Provider '${n.id}' already exists.`) : (await M(t, n), h({ provider: n }, { status: 201 }));
1594
+ }
1595
+ let l = /^\/api\/providers\/([^/]+)(?:\/(.*))?$/.exec(s);
1596
+ if (!l) return o(404, "not_found", "API route not found.");
1597
+ let u = decodeURIComponent(l[1] ?? ""), d = l[2] ?? "";
1598
+ Pn(r, u);
1599
+ let f = await j(t, u);
1600
+ if (!f && !(d === "" && e.method === "PUT" && r.isAdmin)) throw new n(`Provider '${u}' not found.`);
1601
+ if (d === "") {
1602
+ if (e.method === "GET") return h({ provider: f });
1603
+ if (e.method === "PUT") {
1604
+ let n = await L(e), i = Qt(r.isAdmin ? n : {
1605
+ displayName: n.displayName,
1606
+ contact: n.contact
1607
+ }, f ?? Qt({ id: u }));
1608
+ return await M(t, i), h({ provider: i });
1609
+ }
1610
+ if (e.method === "DELETE") {
1611
+ R(r, "Deleting providers");
1612
+ let e = await F(t, u);
1613
+ return e.length > 0 ? o(409, "conflict", `Provider '${u}' still has ${e.length} publication(s).`) : (await Xt(t, u), h({ ok: !0 }));
1614
+ }
1615
+ }
1616
+ if (d === "keys" && e.method === "POST") {
1617
+ R(r, "Minting provider keys");
1618
+ let n = await L(e), i = bn("tbp"), a = {
1619
+ principal: "provider",
1620
+ providerId: u,
1621
+ label: v(n, "label"),
1622
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1623
+ expiresAt: v(n, "expiresAt")
1624
+ };
1625
+ return await xn(t, i, a), h({
1626
+ key: i,
1627
+ record: a
1628
+ }, { status: 201 });
1629
+ }
1630
+ if (d === "pubs") {
1631
+ if (e.method === "GET") return h({ publications: await F(t, u) });
1632
+ if (e.method === "POST") {
1633
+ let n = en(await L(e), u);
1634
+ return await N(t, u, n.pubId) ? o(409, "conflict", `Publication '${n.pubId}' already exists.`) : (await P(t, n), h({ publication: n }, { status: 201 }));
1635
+ }
1636
+ }
1637
+ let p = /^pubs\/([^/]+)(\/publish)?$/.exec(d);
1638
+ if (p) {
1639
+ let r = decodeURIComponent(p[1] ?? ""), i = await N(t, u, r);
1640
+ if (p[2] === "/publish" && e.method === "POST") {
1641
+ if (!i) throw new n(`Publication '${r}' not found.`);
1642
+ let e = {
1643
+ ...i,
1644
+ status: "published",
1645
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1646
+ };
1647
+ return await P(t, e), h({ publication: e });
1648
+ }
1649
+ if (e.method === "GET") {
1650
+ if (!i) throw new n(`Publication '${r}' not found.`);
1651
+ return h({ publication: i });
1652
+ }
1653
+ if (e.method === "PUT") {
1654
+ let n = en({
1655
+ ...await L(e),
1656
+ pubId: r
1657
+ }, u, i ?? void 0);
1658
+ return await P(t, n), h({ publication: n }, { status: i ? 200 : 201 });
1659
+ }
1660
+ if (e.method === "DELETE") return await $t(t, u, r), h({ ok: !0 });
1661
+ }
1662
+ return o(404, "not_found", "API route not found.");
1663
+ }
1664
+ async function In(e, t) {
1665
+ let n = await L(e), r = v(n, "tenantId") ?? null, i = sn(v(n, "path")), a = _(n.pubRef) ? n.pubRef : void 0, o = {
1666
+ providerId: A(a && v(a, "providerId"), "pubRef.providerId"),
1667
+ pubId: A(a && v(a, "pubId"), "pubRef.pubId"),
1668
+ version: a ? v(a, "version") : void 0
1669
+ };
1670
+ if (!await j(t, o.providerId)) throw new s(`pubRef.providerId '${o.providerId}' does not exist.`);
1671
+ if (!await N(t, o.providerId, o.pubId)) throw new s(`pubRef.pubId '${o.pubId}' does not exist under '${o.providerId}'.`);
1672
+ let c = v(n, "id"), l = c ? await nn(t, r, c) : null, u = i.join("/"), d = {
1673
+ id: l?.id ?? c ?? cn(),
1674
+ tenantId: r,
1675
+ path: u,
1676
+ pubRef: o,
1677
+ enabled: n.enabled !== !1,
1678
+ createdAt: l?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
1679
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1680
+ }, f = n.dryRun === !0 || new URL(e.url).searchParams.get("dryRun") === "true", p = l ? l.path === u ? "update" : "move" : "create", m = l && l.path !== u ? [l.path, u] : [u];
1681
+ return f ? h({
1682
+ dryRun: !0,
1683
+ action: p,
1684
+ placement: d,
1685
+ affected: await Rn(t, r, m)
1686
+ }) : (await rn(t, d), h({
1687
+ placement: d,
1688
+ action: p
1689
+ }, { status: l ? 200 : 201 }));
1690
+ }
1691
+ async function Ln(e, t, r, i) {
1692
+ let a = i.searchParams.get("tenant"), o = !a || a === "_global" ? null : a, s = await nn(t, o, r);
1693
+ if (!s) throw new n(`Placement '${r}' not found in scope '${D(o)}'.`);
1694
+ return i.searchParams.get("dryRun") === "true" ? h({
1695
+ dryRun: !0,
1696
+ action: "delete",
1697
+ placement: s,
1698
+ affected: await Rn(t, o, [s.path])
1699
+ }) : (await an(t, o, r), h({ ok: !0 }));
1700
+ }
1701
+ async function Rn(e, t, n) {
1702
+ return t === null ? {
1703
+ tenantId: D(t),
1704
+ paths: n,
1705
+ grants: [],
1706
+ note: "Global tree: affects every non-tenant caller of /htbp."
1707
+ } : {
1708
+ tenantId: t,
1709
+ paths: n,
1710
+ grants: (await Sn(e)).filter((e) => e.record.tenantId === t).map((e) => ({
1711
+ keyHash: e.hash.slice(0, 12),
1712
+ principal: e.record.principal ?? "agent",
1713
+ label: e.record.label
1714
+ }))
1715
+ };
1716
+ }
1717
+ //#endregion
1718
+ //#region src/worker/tb/device.ts
1719
+ var zn = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/, Bn = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/, Vn = [
1720
+ "exec.run",
1721
+ "fs.read",
1722
+ "logs.tail"
1723
+ ], Hn = 3e4, z = 1e6, Un = /* @__PURE__ */ new Set([
1724
+ "rm",
1725
+ "mkfs",
1726
+ "dd",
1727
+ "shutdown",
1728
+ "reboot",
1729
+ "halt",
1730
+ "sudo",
1731
+ "su"
1732
+ ]), Wn = [
1733
+ /\brm\s+-[^\s]*r[^\s]*f\b.*(?:\s\/|\s\*)/,
1734
+ /:\s*\(\s*\)\s*\{/,
1735
+ />\s*\/dev\/sd[a-z]/,
1736
+ /\bcurl\b.*\|\s*(?:sh|bash)\b/,
1737
+ /\bwget\b.*\|\s*(?:sh|bash)\b/
1738
+ ];
1739
+ function B(e) {
1740
+ if (!e.TENANTS) throw new s("Tunnel endpoints require the TENANTS KV binding.");
1741
+ return e.TENANTS;
1742
+ }
1743
+ function Gn(e) {
1744
+ return !!e.TENANTS;
1745
+ }
1746
+ async function V(e, t) {
1747
+ return await B(e).get(`endpoint:${t}`, "json");
1748
+ }
1749
+ async function H(e, t) {
1750
+ await B(e).put(`endpoint:${t.id}`, JSON.stringify(t));
1751
+ }
1752
+ async function Kn(e) {
1753
+ let t = [], n;
1754
+ do {
1755
+ let r = await B(e).list({
1756
+ prefix: "endpoint:",
1757
+ cursor: n
1758
+ });
1759
+ for (let n of r.keys) {
1760
+ let r = await B(e).get(n.name, "json");
1761
+ r && t.push(r);
1762
+ }
1763
+ n = r.list_complete ? void 0 : r.cursor;
1764
+ } while (n);
1765
+ return t;
1766
+ }
1767
+ async function qn(e, t) {
1768
+ return await B(e).get(`command-policy:${t}`, "json");
1769
+ }
1770
+ async function Jn(e, t) {
1771
+ await B(e).put(`command-policy:${t.id}`, JSON.stringify(t));
1772
+ }
1773
+ async function Yn(e) {
1774
+ let t = [], n;
1775
+ do {
1776
+ let r = await B(e).list({
1777
+ prefix: "command-policy:",
1778
+ cursor: n
1779
+ });
1780
+ for (let n of r.keys) {
1781
+ let r = await B(e).get(n.name, "json");
1782
+ r && t.push(r);
1783
+ }
1784
+ n = r.list_complete ? void 0 : r.cursor;
1785
+ } while (n);
1786
+ return t;
1787
+ }
1788
+ async function Xn(e, t, r) {
1789
+ let i = new URL(e.url).pathname;
1790
+ if (!i.startsWith("/api/endpoints") && !i.startsWith("/api/command-policies")) return;
1791
+ if (!Gn(t)) return o(501, "not_supported", "Tunnel endpoints require the TENANTS KV binding.");
1792
+ if (sr(r, "Managing tunnel endpoints"), i === "/api/endpoints") {
1793
+ if (e.method === "GET") return h({ endpoints: await Kn(t) });
1794
+ if (e.method === "POST") {
1795
+ let n = cr(await U(e));
1796
+ return await H(t, n), h({ endpoint: n }, { status: 201 });
1797
+ }
1798
+ }
1799
+ let a = /^\/api\/endpoints\/([^/]+)$/.exec(i);
1800
+ if (a) {
1801
+ let r = decodeURIComponent(a[1] ?? ""), i = await V(t, r);
1802
+ if (!i) throw new n(`Endpoint '${r}' not found.`);
1803
+ if (e.method === "GET") return h({ endpoint: i });
1804
+ if (e.method === "PUT") {
1805
+ let n = cr(await U(e), i);
1806
+ return await H(t, n), h({ endpoint: n });
1807
+ }
1808
+ if (e.method === "DELETE") {
1809
+ let e = {
1810
+ ...i,
1811
+ status: "revoked",
1812
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1813
+ };
1814
+ return await H(t, e), h({ endpoint: e });
1815
+ }
1816
+ }
1817
+ if (i === "/api/command-policies") {
1818
+ if (e.method === "GET") return h({ policies: await Yn(t) });
1819
+ if (e.method === "POST") {
1820
+ let n = lr(await U(e));
1821
+ return await Jn(t, n), h({ policy: n }, { status: 201 });
1822
+ }
1823
+ }
1824
+ let s = /^\/api\/command-policies\/([^/]+)$/.exec(i);
1825
+ if (s) {
1826
+ let r = decodeURIComponent(s[1] ?? ""), i = await qn(t, r);
1827
+ if (!i) throw new n(`Command policy '${r}' not found.`);
1828
+ if (e.method === "GET") return h({ policy: i });
1829
+ if (e.method === "PUT") {
1830
+ let n = lr(await U(e), i);
1831
+ return await Jn(t, n), h({ policy: n });
1832
+ }
1833
+ if (e.method === "DELETE") return await B(t).delete(`command-policy:${r}`), h({ ok: !0 });
1834
+ }
1835
+ return o(404, "not_found", "API route not found.");
1836
+ }
1837
+ async function Zn(e, t, n) {
1838
+ let r = new URL(e.url);
1839
+ if (r.pathname.startsWith("/tunnel/")) {
1840
+ if (!Gn(t)) return o(501, "not_supported", "Tunnel endpoints require the TENANTS KV binding.");
1841
+ if (e.method !== "POST") return o(405, "method_not_allowed", "Use POST for tunnel control-plane calls.");
1842
+ if (r.pathname === "/tunnel/connect") {
1843
+ let r = await fr(e, t), i = await n?.connect?.(r), a = (/* @__PURE__ */ new Date()).toISOString(), o = i?.sessionId ?? crypto.randomUUID();
1844
+ return await H(t, {
1845
+ ...r,
1846
+ status: "online",
1847
+ sessionId: o,
1848
+ lastSeenAt: a,
1849
+ updatedAt: a
1850
+ }), h({
1851
+ ok: !0,
1852
+ endpointId: r.id,
1853
+ sessionId: o,
1854
+ capabilities: r.capabilities
1855
+ });
1856
+ }
1857
+ if (r.pathname === "/tunnel/heartbeat") {
1858
+ let r = await pr(t, await U(e));
1859
+ await n?.heartbeat?.(r);
1860
+ let i = (/* @__PURE__ */ new Date()).toISOString();
1861
+ return await H(t, {
1862
+ ...r,
1863
+ lastSeenAt: i,
1864
+ updatedAt: i
1865
+ }), h({
1866
+ ok: !0,
1867
+ endpointId: r.id
1868
+ });
1869
+ }
1870
+ if (r.pathname === "/tunnel/capabilities") {
1871
+ let n = await U(e), r = await pr(t, n), i = ur(n.capabilities, r.capabilities);
1872
+ if (i.some((e) => !r.capabilities.includes(e))) throw new a("Endpoint cannot report capabilities outside its registered maximum.");
1873
+ let o = (/* @__PURE__ */ new Date()).toISOString();
1874
+ return await H(t, {
1875
+ ...r,
1876
+ activeCapabilities: i,
1877
+ lastSeenAt: o,
1878
+ updatedAt: o
1879
+ }), h({
1880
+ ok: !0,
1881
+ endpointId: r.id,
1882
+ capabilities: i
1883
+ });
1884
+ }
1885
+ return o(404, "not_found", "Tunnel route not found.");
1886
+ }
1887
+ }
1888
+ async function Qn(e) {
1889
+ let { env: t, principal: i, segments: o, isHelp: c, input: l, traceId: u, broker: d } = e;
1890
+ if (o[0] !== "~device") throw new n("Device route not found.");
1891
+ if (o.length === 1) {
1892
+ if (!c) throw new s("Device root is describe-only; select /~device/{id}/{tool}.");
1893
+ return {
1894
+ response: h(await $n(t, i), { headers: { "Cache-Control": "private, max-age=30" } }),
1895
+ audit: {}
1896
+ };
1897
+ }
1898
+ let f = o[1], p = await V(t, f);
1899
+ if (!p || p.status === "revoked") throw new n(`Endpoint '${f}' not found.`);
1900
+ if (mr(i, p), o.length > 3) throw new n(`Device path '/${o.join("/")}' not found.`);
1901
+ let m = o[2], g = m ?? yr(l), _ = {
1902
+ tool: g,
1903
+ provider: p.providerId,
1904
+ effect: ar(g),
1905
+ scope: or(g)
1906
+ };
1907
+ if (c) return {
1908
+ response: h(m ? tr(p, m) : er(p), { headers: { "Cache-Control": "private, max-age=30" } }),
1909
+ audit: _,
1910
+ tenantId: p.tenantId
1911
+ };
1912
+ if (!g) throw new s("Device calls require a tool path or a body.tool field.");
1913
+ if (g === "shell.run") throw new a("shell.run is not exposed by default.");
1914
+ if (!Vn.includes(g)) throw new n(`Device tool '${g}' is not exposed.`);
1915
+ if (!rr(p).includes(g)) throw new n(`Device endpoint '${p.id}' does not expose '${g}'.`);
1916
+ if (p.status !== "online" || !p.sessionId || !d) throw new r(`Endpoint '${p.id}' is offline.`);
1917
+ let v = await hr(t, p, g, l);
1918
+ p.id;
1919
+ let y = await d.dispatch(p, {
1920
+ endpointId: p.id,
1921
+ sessionId: p.sessionId,
1922
+ tool: g,
1923
+ traceId: u,
1924
+ input: v.input,
1925
+ deadlineMs: v.deadlineMs,
1926
+ maxOutputBytes: v.maxOutputBytes
1927
+ });
1928
+ return {
1929
+ response: h({
1930
+ resource: `/htbp/${o.join("/")}`,
1931
+ result: y
1932
+ }),
1933
+ audit: _,
1934
+ tenantId: p.tenantId
1935
+ };
1936
+ }
1937
+ async function $n(e, t) {
1938
+ return {
1939
+ htbp: "draft",
1940
+ kind: "directory",
1941
+ title: "Devices",
1942
+ cachable: !1,
1943
+ resources: (await Kn(e)).filter((e) => e.status !== "revoked" && (t.isAdmin || !e.tenantId || e.tenantId === t.tenantId)).map((e) => ({
1944
+ name: e.id,
1945
+ path: `./${encodeURIComponent(e.id)}`,
1946
+ description: e.label
1947
+ }))
1948
+ };
1949
+ }
1950
+ function er(e) {
1951
+ return {
1952
+ htbp: "draft",
1953
+ kind: "builtin",
1954
+ title: e.label ?? e.id,
1955
+ description: `${e.kind} endpoint (${e.status})`,
1956
+ cachable: !1,
1957
+ resources: rr(e).map(nr)
1958
+ };
1959
+ }
1960
+ function tr(e, t) {
1961
+ if (!rr(e).includes(t)) throw new n(`Device endpoint '${e.id}' does not expose '${t}'.`);
1962
+ return {
1963
+ htbp: "draft",
1964
+ kind: "builtin",
1965
+ title: t,
1966
+ cachable: !1,
1967
+ endpoint: {
1968
+ method: "POST",
1969
+ inputSchema: ir(t),
1970
+ outputSchema: { type: "object" },
1971
+ effect: ar(t),
1972
+ scope: or(t)
1973
+ }
1974
+ };
1975
+ }
1976
+ function nr(e) {
1977
+ return {
1978
+ name: e,
1979
+ path: `./${encodeURIComponent(e)}`,
1980
+ description: e === "exec.run" ? "Run a structured argv command" : e === "fs.read" ? "Read a file from the endpoint" : "Tail endpoint logs"
1981
+ };
1982
+ }
1983
+ function rr(e) {
1984
+ return e.activeCapabilities ?? e.capabilities;
1985
+ }
1986
+ function ir(e) {
1987
+ return e === "exec.run" ? {
1988
+ type: "object",
1989
+ required: ["argv"],
1990
+ properties: {
1991
+ argv: {
1992
+ type: "array",
1993
+ items: { type: "string" },
1994
+ minItems: 1
1995
+ },
1996
+ cwd: { type: "string" },
1997
+ timeoutMs: { type: "number" },
1998
+ maxOutputBytes: { type: "number" }
1999
+ }
2000
+ } : e === "fs.read" ? {
2001
+ type: "object",
2002
+ required: ["path"],
2003
+ properties: {
2004
+ path: { type: "string" },
2005
+ maxBytes: { type: "number" }
2006
+ }
2007
+ } : {
2008
+ type: "object",
2009
+ properties: {
2010
+ stream: { type: "string" },
2011
+ lines: { type: "number" }
2012
+ }
2013
+ };
2014
+ }
2015
+ function ar(e) {
2016
+ if (e) return e === "exec.run" ? "destructive" : "read";
2017
+ }
2018
+ function or(e) {
2019
+ if (e) return e === "exec.run" ? "device:exec" : e === "fs.read" ? "device:fs.read" : "device:logs.tail";
2020
+ }
2021
+ function sr(e, t) {
2022
+ if (!e.isAdmin) throw new a(`${t} requires an admin key.`);
2023
+ }
2024
+ async function U(e) {
2025
+ let t = await e.json().catch(() => void 0);
2026
+ if (!_(t)) throw new s("Request body must be a JSON object.");
2027
+ return t;
2028
+ }
2029
+ function cr(e, t) {
2030
+ let n = v(e, "id") ?? t?.id;
2031
+ if (!n || !zn.test(n)) throw new s(`Endpoint id must match ${zn}.`);
2032
+ let r = (/* @__PURE__ */ new Date()).toISOString(), i = ur(e.capabilities, t?.capabilities ?? ["exec.run"]), a = dr(v(e, "kind") ?? t?.kind ?? "generic"), o = v(e, "status") ?? t?.status ?? "offline", c = o === "online" || o === "offline" || o === "revoked" ? o : t?.status ?? "offline";
2033
+ return {
2034
+ id: n,
2035
+ tenantId: v(e, "tenantId") ?? t?.tenantId,
2036
+ providerId: v(e, "providerId") ?? t?.providerId,
2037
+ kind: a,
2038
+ label: v(e, "label") ?? t?.label,
2039
+ capabilities: i,
2040
+ activeCapabilities: t?.activeCapabilities,
2041
+ status: c,
2042
+ commandPolicyId: v(e, "commandPolicyId") ?? t?.commandPolicyId,
2043
+ sessionId: t?.sessionId,
2044
+ lastSeenAt: t?.lastSeenAt,
2045
+ createdAt: t?.createdAt ?? r,
2046
+ updatedAt: r
2047
+ };
2048
+ }
2049
+ function lr(e, t) {
2050
+ let n = v(e, "id") ?? t?.id;
2051
+ if (!n || !Bn.test(n)) throw new s(`Command policy id must match ${Bn}.`);
2052
+ let r = (/* @__PURE__ */ new Date()).toISOString();
2053
+ return {
2054
+ id: n,
2055
+ defaultMode: e.defaultMode === "deny" || e.defaultMode === "allow" ? e.defaultMode : t?.defaultMode ?? "allow",
2056
+ allowCommands: b(e.allowCommands) ?? t?.allowCommands,
2057
+ denyCommands: b(e.denyCommands) ?? t?.denyCommands,
2058
+ denyPatterns: b(e.denyPatterns) ?? t?.denyPatterns,
2059
+ allowShell: typeof e.allowShell == "boolean" ? e.allowShell : t?.allowShell,
2060
+ allowedCwdPrefixes: b(e.allowedCwdPrefixes) ?? t?.allowedCwdPrefixes,
2061
+ maxTimeoutMs: W(e.maxTimeoutMs) ?? t?.maxTimeoutMs,
2062
+ maxOutputBytes: W(e.maxOutputBytes) ?? t?.maxOutputBytes,
2063
+ requireConfirmFor: b(e.requireConfirmFor) ?? t?.requireConfirmFor,
2064
+ envAllowlist: b(e.envAllowlist) ?? t?.envAllowlist,
2065
+ createdAt: t?.createdAt ?? r,
2066
+ updatedAt: r
2067
+ };
2068
+ }
2069
+ function ur(e, t) {
2070
+ let n = (Array.isArray(e) ? e : t).filter((e) => typeof e == "string" && Vn.includes(e));
2071
+ if (n.length === 0) throw new s("Endpoint capabilities must include at least one supported device tool.");
2072
+ return [...new Set(n)];
2073
+ }
2074
+ function dr(e) {
2075
+ if ([
2076
+ "sandbox",
2077
+ "k8s-pod",
2078
+ "pc",
2079
+ "browser-host",
2080
+ "mobile",
2081
+ "generic"
2082
+ ].includes(e)) return e;
2083
+ throw new s(`Unsupported endpoint kind '${e}'.`);
2084
+ }
2085
+ function W(e) {
2086
+ return typeof e == "number" && Number.isFinite(e) && e > 0 ? e : void 0;
2087
+ }
2088
+ async function fr(e, t) {
2089
+ let r = v(await U(e), "endpointId") ?? e.headers.get("X-TB-Endpoint-Id") ?? void 0;
2090
+ if (!r) throw new s("endpointId is required.");
2091
+ let i = await V(t, r);
2092
+ if (!i) throw new n(`Endpoint '${r}' not found.`);
2093
+ if (i.status === "revoked") throw new a(`Endpoint '${r}' is revoked.`);
2094
+ return i;
2095
+ }
2096
+ async function pr(e, t) {
2097
+ let r = v(t, "endpointId"), i = v(t, "sessionId");
2098
+ if (!r || !i) throw new s("endpointId and sessionId are required.");
2099
+ let o = await V(e, r);
2100
+ if (!o || o.status === "revoked") throw new n(`Endpoint '${r}' not found.`);
2101
+ if (o.sessionId !== i) throw new a("Endpoint session is invalid.");
2102
+ return o;
2103
+ }
2104
+ function mr(e, t) {
2105
+ if (!e.isAdmin && !(t.tenantId && e.tenantId === t.tenantId)) throw new n(`Endpoint '${t.id}' not found.`);
2106
+ }
2107
+ async function hr(e, t, n, r) {
2108
+ let i = vr(r);
2109
+ if (n === "exec.run") return gr(e, t, i);
2110
+ if (n === "fs.read") {
2111
+ let e = v(i, "path");
2112
+ if (!e) throw new s("fs.read requires path.");
2113
+ let t = Math.min(W(i.maxBytes) ?? z, z);
2114
+ return {
2115
+ input: {
2116
+ path: e,
2117
+ maxBytes: t
2118
+ },
2119
+ deadlineMs: Hn,
2120
+ maxOutputBytes: t
2121
+ };
2122
+ }
2123
+ let a = Math.min(Math.max(W(i.lines) ?? 100, 1), 1e3);
2124
+ return {
2125
+ input: {
2126
+ stream: v(i, "stream") ?? "default",
2127
+ lines: a
2128
+ },
2129
+ deadlineMs: Hn,
2130
+ maxOutputBytes: z
2131
+ };
2132
+ }
2133
+ async function gr(e, t, n) {
2134
+ let r = b(n.argv);
2135
+ if (!r || r.length === 0 || r.some((e) => e.length === 0)) throw new s("exec.run requires non-empty argv: string[].");
2136
+ let i = t.commandPolicyId ? await qn(e, t.commandPolicyId) : null;
2137
+ if (t.commandPolicyId && !i) throw new a(`Command policy '${t.commandPolicyId}' not found.`);
2138
+ _r(r, n, i);
2139
+ let o = i?.maxTimeoutMs ?? Hn, c = i?.maxOutputBytes ?? z, l = Math.min(W(n.timeoutMs) ?? Hn, o), u = Math.min(W(n.maxOutputBytes) ?? z, c), d = {
2140
+ argv: r,
2141
+ timeoutMs: l,
2142
+ maxOutputBytes: u
2143
+ }, f = v(n, "cwd");
2144
+ return f && (d.cwd = f), {
2145
+ input: d,
2146
+ deadlineMs: l,
2147
+ maxOutputBytes: u
2148
+ };
2149
+ }
2150
+ function _r(e, t, n) {
2151
+ let r = e[0], i = e.join(" ");
2152
+ if (Un.has(r)) throw new a(`Command '${r}' is denied by the global policy.`);
2153
+ if (Wn.some((e) => e.test(i))) throw new a("Command is denied by the global policy.");
2154
+ if (n?.denyCommands?.includes(r)) throw new a(`Command '${r}' is denied by policy '${n.id}'.`);
2155
+ if (n?.denyPatterns?.some((e) => new RegExp(e).test(i))) throw new a(`Command is denied by policy '${n.id}'.`);
2156
+ if (n?.allowCommands && !n.allowCommands.includes(r) || n?.defaultMode === "deny" && !n.allowCommands?.includes(r)) throw new a(`Command '${r}' is not allowed by policy '${n.id}'.`);
2157
+ let o = v(t, "cwd");
2158
+ if (n?.allowedCwdPrefixes && n.allowedCwdPrefixes.length > 0) {
2159
+ if (!o) throw new a(`cwd is required by policy '${n.id}'.`);
2160
+ if (!n.allowedCwdPrefixes.some((e) => o.startsWith(e))) throw new a(`cwd '${o}' is outside policy '${n.id}'.`);
2161
+ }
2162
+ }
2163
+ function vr(e) {
2164
+ return _(e) && _(e.arguments) ? e.arguments : _(e) ? e : {};
2165
+ }
2166
+ function yr(e) {
2167
+ if (!_(e)) return;
2168
+ let t = v(e, "tool");
2169
+ return t && Vn.includes(t) ? t : void 0;
2170
+ }
2171
+ //#endregion
2172
+ //#region src/worker/tb/help.ts
2173
+ function br(e, t, n) {
2174
+ let r = [
2175
+ "htbp draft",
2176
+ `resource ${t}`,
2177
+ `title ${x(e.title)}`
2178
+ ];
2179
+ if (e.description && r.push(`summary ${x(e.description)}`), r.push("skill ./~skill", `auth ${n}`, ""), e.endpoint) {
2180
+ let { method: i, tools: a } = e.endpoint;
2181
+ if (a && a.length > 0) for (let e of a) r.push(`cmd ${e.name} ${i} ${t}`), r.push(` body application/json {"tool":"${e.name}","arguments":object?}`), r.push(` auth ${n}`), xr(r, e), r.push(" returns 200 application/json"), e.description && r.push(` note ${x(e.description)}`);
2182
+ else r.push(`cmd call ${i} ${t}`), r.push(" body application/json {\"arguments\":object?}"), r.push(` auth ${n}`), xr(r, e.endpoint), r.push(" returns 200 application/json");
2183
+ }
2184
+ for (let n of e.resources ?? []) r.push(`link child ${Sr(t, n.path)}/~help`), n.description && r.push(` note ${x(n.description)}`);
2185
+ return `${r.join("\n").trimEnd()}\n`;
2186
+ }
2187
+ function xr(e, t) {
2188
+ e.push(` effect ${t.effect ?? "external"}`), t.scope && e.push(` scope ${x(t.scope)}`), t.confirm && e.push(" confirm true");
2189
+ }
2190
+ function Sr(e, t) {
2191
+ return t.startsWith("./") ? `${e}/${t.slice(2)}` : t.startsWith("../") ? `${e.split("/").slice(0, -1).join("/")}/${t.slice(3)}` : `${e}/${t}`;
2192
+ }
2193
+ //#endregion
2194
+ //#region src/worker/tb/resolve.ts
2195
+ async function Cr(e, t, r, i, a) {
2196
+ let o = E(t, r);
2197
+ if (!o) throw new n(`No TB resource at '/${r.join("/")}'.`);
2198
+ let s = r.length > 0 ? `${w}/${r.join("/")}` : w, c = {
2199
+ env: e,
2200
+ authMode: i,
2201
+ basePath: _e(o.node),
2202
+ builtinHandlers: a
2203
+ };
2204
+ return {
2205
+ payload: await Et(o.node).describe(o.node, c, o.sub),
2206
+ resourcePath: s
2207
+ };
2208
+ }
2209
+ async function wr(e, t, n, r, i, a) {
2210
+ let { payload: o, resourcePath: s } = await Cr(e, t, n, r, a);
2211
+ return Er(i) ? g(br(o, s, r === "none" ? "none" : "bearer"), { headers: {
2212
+ "Content-Type": "text/plain; charset=utf-8",
2213
+ "Cache-Control": Dr(o, r)
2214
+ } }) : h(o, { headers: { "Cache-Control": Dr(o, r) } });
2215
+ }
2216
+ async function Tr(e, t, r, i, a, o) {
2217
+ let s = E(t, r);
2218
+ if (!s) throw new n(`No TB resource at '/${r.join("/")}'.`);
2219
+ let c = r.length > 0 ? `${w}/${r.join("/")}` : w, l = {
2220
+ env: e,
2221
+ authMode: i,
2222
+ basePath: _e(s.node),
2223
+ builtinHandlers: o
2224
+ };
2225
+ return h({
2226
+ resource: c,
2227
+ result: await Et(s.node).call(s.node, l, s.sub, a)
2228
+ });
2229
+ }
2230
+ function Er(e) {
2231
+ let t = e.toLowerCase();
2232
+ return t.includes("application/json") ? !1 : t.includes("text/plain") || t.includes("text/markdown");
2233
+ }
2234
+ function Dr(e, t) {
2235
+ let n = t === "none" ? "public" : "private";
2236
+ return e.cachable === !1 ? "no-store" : `${n}, max-age=300`;
2237
+ }
2238
+ //#endregion
2239
+ //#region src/worker/tb/dynamic-servers.ts
2240
+ var Or = "dynamic-server:", G = "dynamic";
2241
+ function kr(e) {
2242
+ return !!e.TENANTS;
2243
+ }
2244
+ async function Ar(e) {
2245
+ if (!e.TENANTS) return [];
2246
+ let t = await Pr(e), n = new Set(t.map((e) => e.id)), r = (await Fr(e)).filter((e) => !n.has(e.id));
2247
+ return [...t, ...r];
2248
+ }
2249
+ async function jr(e, t) {
2250
+ if (!e.TENANTS) throw Error("Dynamic servers require the TENANTS KV binding.");
2251
+ let n = (/* @__PURE__ */ new Date()).toISOString();
2252
+ await j(e, "dynamic") || await M(e, {
2253
+ id: G,
2254
+ displayName: "Dynamic Servers (compat)",
2255
+ trustTier: "community",
2256
+ status: "active",
2257
+ createdAt: n,
2258
+ updatedAt: n
2259
+ });
2260
+ let r = await N(e, G, t.id);
2261
+ await P(e, {
2262
+ providerId: G,
2263
+ pubId: t.id,
2264
+ version: r?.version ?? "0.0.0",
2265
+ binding: {
2266
+ type: "mcp",
2267
+ name: t.name,
2268
+ endpoint: t.endpoint,
2269
+ description: t.description
2270
+ },
2271
+ status: "published",
2272
+ createdAt: r?.createdAt ?? n,
2273
+ updatedAt: n
2274
+ }), await rn(e, {
2275
+ id: Nr(t.id),
2276
+ tenantId: null,
2277
+ path: t.id,
2278
+ pubRef: {
2279
+ providerId: G,
2280
+ pubId: t.id
2281
+ },
2282
+ enabled: !0,
2283
+ createdAt: n,
2284
+ updatedAt: n
2285
+ }), await e.TENANTS.delete(`${Or}${t.id}`);
2286
+ }
2287
+ async function Mr(e, t) {
2288
+ if (!e.TENANTS) throw Error("Dynamic servers require the TENANTS KV binding.");
2289
+ await e.TENANTS.delete(`${Or}${t}`), await $t(e, G, t), await an(e, null, Nr(t));
2290
+ }
2291
+ function Nr(e) {
2292
+ return `dyn_${e}`;
2293
+ }
2294
+ async function Pr(e) {
2295
+ let t = await F(e, G), n = [];
2296
+ for (let e of t) {
2297
+ let t = _(e.binding) ? e.binding : {}, r = v(t, "endpoint");
2298
+ r && n.push({
2299
+ id: e.pubId,
2300
+ name: v(t, "name") ?? e.pubId,
2301
+ endpoint: r,
2302
+ description: v(t, "description")
2303
+ });
2304
+ }
2305
+ return n;
2306
+ }
2307
+ async function Fr(e) {
2308
+ let t = e.TENANTS;
2309
+ if (!t) return [];
2310
+ let n = [], r;
2311
+ do {
2312
+ let e = await t.list({
2313
+ prefix: Or,
2314
+ cursor: r
2315
+ });
2316
+ for (let r of e.keys) {
2317
+ let e = await t.get(r.name);
2318
+ if (e) try {
2319
+ n.push(JSON.parse(e));
2320
+ } catch {}
2321
+ }
2322
+ r = e.list_complete ? void 0 : e.cursor;
2323
+ } while (r);
2324
+ return n;
2325
+ }
2326
+ //#endregion
2327
+ //#region src/worker/index.ts
2328
+ var Ir = "2025-11-25", Lr = "tool-bridge", Rr = "draft", zr = 1e6, Br = 4e6;
2329
+ function K(e, t = {}) {
2330
+ let n = new Headers(t.headers);
2331
+ return n.set("Content-Type", "application/json; charset=utf-8"), new Response(JSON.stringify(e, null, 2), {
2332
+ ...t,
2333
+ headers: n
2334
+ });
2335
+ }
2336
+ function Vr(e, t = {}) {
2337
+ let n = new Headers(t.headers);
2338
+ return n.set("Content-Type", n.get("Content-Type") ?? "text/plain; charset=utf-8"), new Response(e, {
2339
+ ...t,
2340
+ headers: n
2341
+ });
2342
+ }
2343
+ function q(e, t, n, r) {
2344
+ return K({ error: {
2345
+ code: t,
2346
+ message: n,
2347
+ details: r
2348
+ } }, { status: e });
2349
+ }
2350
+ function Hr(e) {
2351
+ return e.OAUTH_ISSUER ? "oauth" : e.AUTH_BEARER_TOKEN ? "bearer" : "none";
2352
+ }
2353
+ function Ur(e) {
2354
+ let t = e.headers.get("Authorization");
2355
+ if (t) return /^Bearer\s+(.+)$/i.exec(t)?.[1];
2356
+ }
2357
+ async function Wr(e) {
2358
+ return new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(e)));
2359
+ }
2360
+ async function Gr(e, t) {
2361
+ let n = await Wr(e), r = await Wr(t), i = n.length ^ r.length, a = Math.max(n.length, r.length);
2362
+ for (let e = 0; e < a; e += 1) i |= (n[e] ?? 0) ^ (r[e] ?? 0);
2363
+ return i === 0;
2364
+ }
2365
+ async function Kr(e, t) {
2366
+ let n = Hr(t);
2367
+ if (gn(t)) {
2368
+ let r = Ur(e);
2369
+ if (!r) return q(401, "unauthorized", "Secret Key (bearer token) required.");
2370
+ let i = await yn(t, r);
2371
+ return i ? {
2372
+ mode: n,
2373
+ subject: i.label ?? i.providerId ?? i.hostId ?? i.tenantId,
2374
+ tenantId: i.tenantId,
2375
+ root: i.root,
2376
+ principal: i.principal,
2377
+ providerId: i.providerId,
2378
+ hostId: i.hostId,
2379
+ isAdmin: i.principal === "admin"
2380
+ } : q(401, "unauthorized", "Secret Key is invalid.");
2381
+ }
2382
+ if (n === "none") return {
2383
+ mode: n,
2384
+ isAdmin: !t.TENANTS
2385
+ };
2386
+ let r = Ur(e);
2387
+ if (!r) return q(401, "unauthorized", "Bearer token required.");
2388
+ if (n === "bearer") {
2389
+ let e = t.AUTH_BEARER_TOKEN;
2390
+ return e ? await Gr(r, e) ? {
2391
+ mode: n,
2392
+ subject: "static-bearer",
2393
+ isAdmin: !0
2394
+ } : q(401, "unauthorized", "Bearer token is invalid.") : q(500, "auth_misconfigured", "AUTH_BEARER_TOKEN is required for bearer auth.");
2395
+ }
2396
+ try {
2397
+ let e = t.OAUTH_ISSUER;
2398
+ if (!e) return q(500, "auth_misconfigured", "OAUTH_ISSUER is required for OAuth auth.");
2399
+ let i = t.OAUTH_JWKS_URI || await qr(e), a = await l(r, c(new URL(i)), {
2400
+ issuer: e,
2401
+ audience: t.OAUTH_REQUIRED_AUDIENCE || void 0
2402
+ });
2403
+ return {
2404
+ mode: n,
2405
+ subject: typeof a.payload.sub == "string" ? a.payload.sub : void 0,
2406
+ isAdmin: !0
2407
+ };
2408
+ } catch (e) {
2409
+ return q(401, "unauthorized", "OAuth bearer token is invalid.", Ci(e));
2410
+ }
2411
+ }
2412
+ async function qr(e) {
2413
+ let t = e.endsWith("/") ? e.slice(0, -1) : e, n = await fetch(`${t}/.well-known/openid-configuration`, { headers: { Accept: "application/json" } });
2414
+ if (!n.ok) throw Error(`Unable to load OIDC metadata: HTTP ${n.status}`);
2415
+ let r = await n.json();
2416
+ if (typeof r.jwks_uri != "string" || r.jwks_uri.length === 0) throw Error("OIDC metadata does not include jwks_uri.");
2417
+ return r.jwks_uri;
2418
+ }
2419
+ function Jr(e) {
2420
+ return {
2421
+ mode: Hr(e),
2422
+ oauthIssuer: e.OAUTH_ISSUER || void 0,
2423
+ oauthAudience: e.OAUTH_REQUIRED_AUDIENCE || void 0
2424
+ };
2425
+ }
2426
+ async function J(e) {
2427
+ let t = e.headers.get("Content-Length");
2428
+ if (t && Number(t) > zr) throw Error("Request body is too large.");
2429
+ return await e.json();
2430
+ }
2431
+ function Yr(e) {
2432
+ let t = e.MCP_SERVERS_JSON || "{}", n = JSON.parse(t), r = [];
2433
+ if (Z(n) && (n.type === "directory" || Array.isArray(n.children))) return Xr(n, r), r;
2434
+ if (Array.isArray(n)) {
2435
+ for (let e of n) r.push(Zr(e));
2436
+ return r;
2437
+ }
2438
+ if (Z(n)) for (let [e, t] of Object.entries(n)) r.push(Zr({
2439
+ id: e,
2440
+ ...Z(t) ? t : {}
2441
+ }));
2442
+ return r;
2443
+ }
2444
+ function Xr(e, t) {
2445
+ if (Z(e)) {
2446
+ if (e.type === "mcp") {
2447
+ t.push(Zr(e));
2448
+ return;
2449
+ }
2450
+ if (Array.isArray(e.children)) for (let n of e.children) Xr(n, t);
2451
+ }
2452
+ }
2453
+ function Zr(e) {
2454
+ if (!Z(e)) throw Error("MCP server config must be an object.");
2455
+ let t = Q(e, "id") || Q(e, "name"), n = Q(e, "endpoint") || Q(e, "url") || Q(e, "baseUrl");
2456
+ if (!t) throw Error("MCP server config is missing id/name.");
2457
+ if (!n) throw Error(`MCP server '${t}' is missing endpoint.`);
2458
+ let r = xi(e.headers), i = Si(e.allowedTools) ?? Si(e.allowed_tools);
2459
+ return {
2460
+ id: t,
2461
+ name: Q(e, "name") || t,
2462
+ endpoint: n,
2463
+ description: Q(e, "description"),
2464
+ headers: r,
2465
+ allowedTools: i
2466
+ };
2467
+ }
2468
+ function Qr(e) {
2469
+ if (!e.endpoint) throw Error("Ad-hoc server endpoint is required.");
2470
+ let t = { ...e.headers ?? {} };
2471
+ return e.bearerToken && (t.Authorization = `Bearer ${e.bearerToken}`), {
2472
+ id: e.name || "adhoc",
2473
+ name: e.name || "Ad-hoc MCP",
2474
+ endpoint: e.endpoint,
2475
+ headers: t
2476
+ };
2477
+ }
2478
+ function $r(e) {
2479
+ return e.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "server";
2480
+ }
2481
+ async function ei(e, t) {
2482
+ let n = Yr(e).find((e) => e.id === t || e.name === t);
2483
+ if (n) return Y(e, n);
2484
+ let r = (await Ar(e)).find((e) => e.id === t || e.name === t);
2485
+ if (r) return Y(e, {
2486
+ id: r.id,
2487
+ name: r.name,
2488
+ endpoint: r.endpoint,
2489
+ description: r.description
2490
+ });
2491
+ throw Error(`Unknown MCP server '${t}'.`);
2492
+ }
2493
+ function Y(e, t) {
2494
+ let n = new URL(t.endpoint);
2495
+ if (n.protocol !== "https:" && e.ALLOW_INSECURE_MCP_HTTP !== "true") throw Error(`MCP endpoint for '${t.id}' must use https://.`);
2496
+ return {
2497
+ ...t,
2498
+ endpoint: n.toString(),
2499
+ resolvedHeaders: ti(e, t.headers)
2500
+ };
2501
+ }
2502
+ function ti(e, t) {
2503
+ let n = {};
2504
+ for (let [r, i] of Object.entries(t ?? {})) n[r] = ni(e, i);
2505
+ return n;
2506
+ }
2507
+ function ni(e, t) {
2508
+ return t.startsWith("$env:") ? ri(e, t.slice(5)) : t.replace(/\$\{([A-Z0-9_]+)\}/g, (t, n) => ri(e, n));
2509
+ }
2510
+ function ri(e, t) {
2511
+ let n = e[t];
2512
+ if (typeof n != "string" || n.length === 0) throw Error(`Environment variable '${t}' is required for MCP header substitution.`);
2513
+ return n;
2514
+ }
2515
+ async function X(e) {
2516
+ let t = await ai(e, "tools/list", {}), n = (Z(t) && Array.isArray(t.tools) ? t.tools : []).map(gi).filter(Boolean);
2517
+ if (!e.allowedTools || e.allowedTools.length === 0) return n;
2518
+ let r = new Set(e.allowedTools);
2519
+ return n.filter((e) => r.has(e.name));
2520
+ }
2521
+ async function ii(e, t, n) {
2522
+ if (e.allowedTools && e.allowedTools.length > 0 && !e.allowedTools.includes(t)) throw Error(`Tool '${t}' is not allowed for server '${e.id}'.`);
2523
+ return ai(e, "tools/call", {
2524
+ name: t,
2525
+ arguments: Z(n) ? n : {}
2526
+ });
2527
+ }
2528
+ async function ai(e, t, n) {
2529
+ let r = await oi(e);
2530
+ try {
2531
+ return await si(e, r.sessionId, "notifications/initialized", {}), (await ci(e, r.sessionId, t, n)).result;
2532
+ } finally {
2533
+ r.sessionId && await hi(e, r.sessionId).catch(() => {});
2534
+ }
2535
+ }
2536
+ async function oi(e) {
2537
+ return { sessionId: (await ci(e, void 0, "initialize", {
2538
+ protocolVersion: Ir,
2539
+ capabilities: {},
2540
+ clientInfo: {
2541
+ name: Lr,
2542
+ version: Rr
2543
+ }
2544
+ })).sessionId };
2545
+ }
2546
+ async function si(e, t, n, r) {
2547
+ let i = await fetch(e.endpoint, {
2548
+ method: "POST",
2549
+ headers: li(e, t),
2550
+ body: JSON.stringify({
2551
+ jsonrpc: "2.0",
2552
+ method: n,
2553
+ params: r
2554
+ })
2555
+ });
2556
+ if (i.status !== 202 && !i.ok) throw Error(`MCP notification '${n}' failed with HTTP ${i.status}.`);
2557
+ }
2558
+ async function ci(e, t, n, r) {
2559
+ let i = crypto.randomUUID(), a = await fetch(e.endpoint, {
2560
+ method: "POST",
2561
+ headers: li(e, t),
2562
+ body: JSON.stringify({
2563
+ jsonrpc: "2.0",
2564
+ id: i,
2565
+ method: n,
2566
+ params: r
2567
+ })
2568
+ });
2569
+ if (!a.ok) throw Error(`MCP request '${n}' failed with HTTP ${a.status}: ${await mi(a)}`);
2570
+ let o = await ui(a, i);
2571
+ if (o.error) throw Error(`MCP error ${o.error.code}: ${o.error.message}`);
2572
+ return {
2573
+ result: o.result,
2574
+ sessionId: a.headers.get("MCP-Session-Id") ?? void 0
2575
+ };
2576
+ }
2577
+ function li(e, t) {
2578
+ let n = new Headers(e.resolvedHeaders);
2579
+ return n.set("Accept", "application/json, text/event-stream"), n.set("Content-Type", "application/json"), n.set("MCP-Protocol-Version", Ir), t && n.set("MCP-Session-Id", t), n;
2580
+ }
2581
+ async function ui(e, t) {
2582
+ if ((e.headers.get("Content-Type") ?? "").includes("text/event-stream")) return di(e, t);
2583
+ let n = await pi(e, zr), r = JSON.parse(n);
2584
+ if (r.id !== t) throw Error(`Unexpected MCP response id '${String(r.id)}'.`);
2585
+ return r;
2586
+ }
2587
+ async function di(e, t) {
2588
+ if (!e.body) throw Error("MCP server returned an empty SSE response.");
2589
+ let n = e.body.getReader(), r = new TextDecoder(), i = "", a = [], o = 0;
2590
+ for (;;) {
2591
+ let { done: e, value: s } = await n.read();
2592
+ if (e) break;
2593
+ if (o += s.byteLength, o > Br) throw Error("MCP SSE response exceeded the maximum size.");
2594
+ i += r.decode(s, { stream: !0 });
2595
+ let c = i.indexOf("\n");
2596
+ for (; c >= 0;) {
2597
+ let e = i.slice(0, c);
2598
+ i = i.slice(c + 1);
2599
+ let n = e.endsWith("\r") ? e.slice(0, -1) : e;
2600
+ if (n === "") {
2601
+ let e = fi(a);
2602
+ if (a = [], e && e.id === t) return e;
2603
+ } else n.startsWith("data:") && a.push(n.slice(5).trimStart());
2604
+ c = i.indexOf("\n");
2605
+ }
2606
+ }
2607
+ let s = fi(a);
2608
+ if (s && s.id === t) return s;
2609
+ throw Error(`MCP SSE stream ended before response '${t}' was received.`);
2610
+ }
2611
+ function fi(e) {
2612
+ if (e.length === 0) return;
2613
+ let t = e.join("\n").trim();
2614
+ if (t.startsWith("{")) return JSON.parse(t);
2615
+ }
2616
+ async function pi(e, t) {
2617
+ if (!e.body) return "";
2618
+ let n = e.body.getReader(), r = new TextDecoder(), i = 0, a = "";
2619
+ for (;;) {
2620
+ let { done: e, value: o } = await n.read();
2621
+ if (e) return a + r.decode();
2622
+ if (i += o.byteLength, i > t) throw Error("Response body exceeded the maximum size.");
2623
+ a += r.decode(o, { stream: !0 });
2624
+ }
2625
+ }
2626
+ async function mi(e) {
2627
+ try {
2628
+ return await pi(e, 8e3);
2629
+ } catch {
2630
+ return "";
2631
+ }
2632
+ }
2633
+ async function hi(e, t) {
2634
+ await fetch(e.endpoint, {
2635
+ method: "DELETE",
2636
+ headers: li(e, t)
2637
+ });
2638
+ }
2639
+ function gi(e) {
2640
+ if (!(!Z(e) || typeof e.name != "string")) return {
2641
+ name: e.name,
2642
+ description: typeof e.description == "string" ? e.description : void 0,
2643
+ inputSchema: e.inputSchema,
2644
+ outputSchema: e.outputSchema,
2645
+ annotations: e.annotations
2646
+ };
2647
+ }
2648
+ function _i(e) {
2649
+ return e === "none" ? "none" : "bearer";
2650
+ }
2651
+ function vi(e, t, n, r) {
2652
+ let i = _i(r), a = [
2653
+ "htbp draft",
2654
+ `resource ${n}`,
2655
+ `title ${e.name}`,
2656
+ e.description ? `summary ${e.description}` : `summary MCP Streamable HTTP bridge for ${e.name}.`,
2657
+ "skill ./~skill",
2658
+ `auth ${i}`,
2659
+ ""
2660
+ ];
2661
+ for (let e of t) a.push(`cmd ${e.name} POST ${n}/tools/${encodeURIComponent(e.name)}`), a.push(" body application/json {\"arguments\":object?}"), a.push(` auth ${i}`), a.push(" effect external"), a.push(" returns 200 application/json"), e.description && a.push(` note ${bi(e.description)}`), a.push("");
2662
+ return `${a.join("\n").trimEnd()}\n`;
2663
+ }
2664
+ function yi(e, t, n, r) {
2665
+ let i = t.map((e) => `- \`${e.name}\`${e.description ? `:${bi(e.description)}` : ""}`).join("\n"), a = r === "none" ? "" : "Authorization: Bearer <token>\n";
2666
+ return `# ${e.name}
2667
+
2668
+ ## When To Use
2669
+
2670
+ 当需要通过 HTBP 调用 \`${e.name}\` 这个 MCP server 暴露的 tool 时,先读取 \`${n}/~help\`,再选择具体 tool endpoint。
2671
+
2672
+ ## Request Construction
2673
+
2674
+ 每个 MCP tool 都映射为一个普通 HTTP POST:
2675
+
2676
+ \`\`\`http
2677
+ POST ${n}/tools/{tool}
2678
+ ${a}Content-Type: application/json
2679
+ \`\`\`
2680
+
2681
+ 请求体:
2682
+
2683
+ \`\`\`json
2684
+ {
2685
+ "arguments": {}
2686
+ }
2687
+ \`\`\`
2688
+
2689
+ ## Available Tools
2690
+
2691
+ ${i || "当前没有可见 tool。"}
2692
+
2693
+ ## Safety
2694
+
2695
+ 这些调用会转发到上游 MCP server。执行 write、delete、external side effect 操作前,应先确认用户意图。
2696
+ `;
2697
+ }
2698
+ function bi(e) {
2699
+ return e.replace(/\s+/g, " ").trim();
2700
+ }
2701
+ function Z(e) {
2702
+ return !!e && typeof e == "object" && !Array.isArray(e);
2703
+ }
2704
+ function Q(e, t) {
2705
+ let n = e[t];
2706
+ return typeof n == "string" && n.length > 0 ? n : void 0;
2707
+ }
2708
+ function xi(e) {
2709
+ if (!Z(e)) return;
2710
+ let t = {};
2711
+ for (let [n, r] of Object.entries(e)) typeof r == "string" && (t[n] = r);
2712
+ return t;
2713
+ }
2714
+ function Si(e) {
2715
+ if (Array.isArray(e)) return e.filter((e) => typeof e == "string");
2716
+ }
2717
+ function Ci(e) {
2718
+ return e instanceof Error ? e.message : String(e);
2719
+ }
2720
+ async function wi(e, t) {
2721
+ let n = new URL(e.url).pathname;
2722
+ if (n === "/api/auth/config" && e.method === "GET") return K(Jr(t));
2723
+ let r = await Kr(e, t);
2724
+ if (r instanceof Response) return r;
2725
+ let i = await Fn(e, t, r);
2726
+ if (i) return i;
2727
+ let a = await Xn(e, t, r);
2728
+ if (a) return a;
2729
+ let o = await Dn(e, t, r);
2730
+ if (o) return o;
2731
+ let s = await Oe(e, t, r);
2732
+ if (s) return s;
2733
+ if (n === "/api/servers" && e.method === "GET") {
2734
+ let e = Yr(t).map(({ headers: e, ...t }) => ({
2735
+ ...t,
2736
+ source: "static"
2737
+ })), n = (await Ar(t)).map((e) => ({
2738
+ ...e,
2739
+ source: "dynamic"
2740
+ })), i = new Set(e.map((e) => e.id));
2741
+ return K({
2742
+ auth: r,
2743
+ servers: [...e, ...n.filter((e) => !i.has(e.id))],
2744
+ dynamicEnabled: kr(t)
2745
+ });
2746
+ }
2747
+ if (n === "/api/servers" && e.method === "POST") {
2748
+ if (!kr(t)) return q(501, "not_supported", "Saving servers requires the TENANTS KV binding.");
2749
+ let n = await J(e);
2750
+ if (!n.endpoint) return q(400, "bad_request", "endpoint is required.");
2751
+ let r = Y(t, Qr({
2752
+ name: n.name,
2753
+ endpoint: n.endpoint
2754
+ })), i = $r(n.name || r.id);
2755
+ return await jr(t, {
2756
+ id: i,
2757
+ name: n.name || i,
2758
+ endpoint: r.endpoint,
2759
+ description: n.description
2760
+ }), K({
2761
+ ok: !0,
2762
+ id: i
2763
+ });
2764
+ }
2765
+ let c = /^\/api\/servers\/([^/]+)$/.exec(n);
2766
+ if (c && e.method === "DELETE") return kr(t) ? (await Mr(t, decodeURIComponent(c[1] ?? "")), K({ ok: !0 })) : q(501, "not_supported", "Deleting servers requires the TENANTS KV binding.");
2767
+ if (n === "/api/bridge/tools" && e.method === "POST") {
2768
+ let n = Y(t, Qr((await J(e)).server ?? {})), r = await X(n);
2769
+ return K({
2770
+ server: $(n),
2771
+ tools: r
2772
+ });
2773
+ }
2774
+ if (n === "/api/bridge/call" && e.method === "POST") {
2775
+ let n = await J(e);
2776
+ if (!n.tool) return q(400, "bad_request", "Tool name is required.");
2777
+ let r = Y(t, Qr(n.server ?? {})), i = await ii(r, n.tool, n.arguments);
2778
+ return K({
2779
+ server: $(r),
2780
+ tool: n.tool,
2781
+ result: i
2782
+ });
2783
+ }
2784
+ if (n === "/api/tree" && e.method === "GET") return K({
2785
+ auth: r,
2786
+ tree: await jt(t, await Ti(r, t), { path: "" }, r.mode)
2787
+ });
2788
+ if (n === "/api/crawl" && e.method === "POST") {
2789
+ let n = await J(e), i = At({
2790
+ maxDepth: n.maxDepth,
2791
+ maxNodes: n.maxNodes
2792
+ });
2793
+ return K({
2794
+ auth: r,
2795
+ tree: await jt(t, await Ti(r, t), n.start ?? { path: "" }, r.mode, i)
2796
+ });
2797
+ }
2798
+ let l = /^\/api\/servers\/([^/]+)(\/.*)?$/.exec(n);
2799
+ if (l) {
2800
+ let n = await ei(t, decodeURIComponent(l[1] ?? ""));
2801
+ return Oi(e, n, l[2] ?? "", `/api/servers/${encodeURIComponent(n.id)}`, r.mode);
2802
+ }
2803
+ return q(404, "not_found", "API route not found.");
2804
+ }
2805
+ async function Ti(e, t) {
2806
+ let n = e.root ?? te(t);
2807
+ return await fn(t, n, e.root && e.tenantId ? e.tenantId : null), n;
2808
+ }
2809
+ async function Ei(e, n, r, i, o) {
2810
+ let s = Date.now(), c = xe(e), l = new URL(e.url), u = l.pathname.replace(/^\/htbp\/?/, "").split("/").filter((e) => e.length > 0), d = u[u.length - 1] === "~help", f = u.length === 0 || d, p = (d ? u.slice(0, -1) : u).map(decodeURIComponent), m = {
2811
+ principal: "anonymous",
2812
+ onBehalfOf: e.headers.get("X-TB-On-Behalf-Of") ?? void 0
2813
+ }, h, g = {}, _, v;
2814
+ try {
2815
+ let t = await Kr(e, n);
2816
+ if (t instanceof Response) v = t;
2817
+ else {
2818
+ if (m.principal = t.principal ?? (t.mode === "none" ? "anonymous" : t.mode === "bearer" ? "static-bearer" : "oauth"), m.subject = t.subject, h = t.tenantId, gn(n) && !t.root && !t.isAdmin) throw new a("This key is not bound to a tenant tree.");
2819
+ if (p[0] === "~device") if (!f && e.method !== "POST") v = q(405, "method_not_allowed", "Use GET {path}/~help or POST {path} to call.");
2820
+ else {
2821
+ let r = e.headers.get("Accept") ?? "", a = f ? void 0 : await J(e);
2822
+ _ = Se(a);
2823
+ let o = await Qn({
2824
+ env: n,
2825
+ principal: t,
2826
+ segments: p,
2827
+ isHelp: f,
2828
+ accept: r,
2829
+ input: a,
2830
+ traceId: c,
2831
+ broker: i
2832
+ });
2833
+ v = o.response, g = o.audit, h = o.tenantId ?? h;
2834
+ }
2835
+ else if (f) {
2836
+ let i = await Ti(t, n);
2837
+ g = we(i, p);
2838
+ let a = e.headers.get("Accept") ?? "";
2839
+ v = await wr(n, i, p, t.mode, a, r);
2840
+ } else if (e.method === "POST") {
2841
+ let i = await Ti(t, n);
2842
+ g = we(i, p);
2843
+ let a = await J(e);
2844
+ _ = Se(a), v = await Tr(n, i, p, t.mode, a, r);
2845
+ } else v = q(405, "method_not_allowed", "Use GET {path}/~help or POST {path} to call.");
2846
+ }
2847
+ } catch (e) {
2848
+ v = t(e);
2849
+ }
2850
+ return v = new Response(v.body, v), v.headers.set("X-TB-Trace-Id", c), await De(n, o, {
2851
+ ts: new Date(s).toISOString(),
2852
+ traceId: c,
2853
+ action: f ? "describe" : "call",
2854
+ actor: m,
2855
+ tenantId: h,
2856
+ path: l.pathname,
2857
+ tool: g.tool,
2858
+ provider: g.provider,
2859
+ effect: g.effect,
2860
+ scope: g.scope,
2861
+ decision: v.status === 401 || v.status === 403 ? "deny" : v.status === 404 ? "not_found" : "allow",
2862
+ result: v.ok ? "ok" : "error",
2863
+ status: v.status,
2864
+ errorCode: v.ok ? void 0 : await Te(v),
2865
+ latencyMs: Date.now() - s,
2866
+ reason: e.headers.get("X-TB-Reason") ?? void 0,
2867
+ input: _
2868
+ }), v;
2869
+ }
2870
+ async function Di(e, t) {
2871
+ let n = await Kr(e, t);
2872
+ if (n instanceof Response) return n;
2873
+ let r = new URL(e.url), i = /^\/mcp\/([^/]+)(\/.*)?$/.exec(r.pathname);
2874
+ if (!i) return q(404, "not_found", "MCP bridge route not found.");
2875
+ let a = await ei(t, decodeURIComponent(i[1] ?? ""));
2876
+ return Oi(e, a, i[2] ?? "", `/mcp/${encodeURIComponent(a.id)}`, n.mode);
2877
+ }
2878
+ async function Oi(e, t, n, r, i) {
2879
+ if (n === "" && e.method === "GET") return K({
2880
+ server: $(t),
2881
+ links: {
2882
+ help: `${r}/~help`,
2883
+ skill: `${r}/~skill`
2884
+ }
2885
+ });
2886
+ if (n === "/tools" && e.method === "GET") {
2887
+ let e = await X(t);
2888
+ return K({
2889
+ server: $(t),
2890
+ tools: e
2891
+ });
2892
+ }
2893
+ if (n === "/~help" && e.method === "GET") return Vr(vi(t, await X(t), r, i));
2894
+ if (n === "/~skill" && e.method === "GET") return Vr(yi(t, await X(t), r, i), { headers: { "Content-Type": "text/markdown; charset=utf-8" } });
2895
+ let a = /^\/tools\/([^/]+)(?:\/call)?$/.exec(n);
2896
+ if (a && e.method === "POST") {
2897
+ let n = await J(e), r = decodeURIComponent(a[1] ?? ""), i = await ii(t, r, n.arguments);
2898
+ return K({
2899
+ server: $(t),
2900
+ tool: r,
2901
+ result: i
2902
+ });
2903
+ }
2904
+ return q(404, "not_found", "Server route not found.");
2905
+ }
2906
+ function $(e) {
2907
+ return {
2908
+ id: e.id,
2909
+ name: e.name,
2910
+ endpoint: e.endpoint,
2911
+ description: e.description,
2912
+ allowedTools: e.allowedTools
2913
+ };
2914
+ }
2915
+ async function ki(e, n, r = {}, i) {
2916
+ let a = new URL(e.url);
2917
+ try {
2918
+ if (a.pathname.startsWith("/api/")) return await wi(e, n);
2919
+ if (a.pathname.startsWith("/tunnel/")) {
2920
+ let t = await Zn(e, n, r.tunnelBroker);
2921
+ if (t) return t;
2922
+ }
2923
+ if (a.pathname.startsWith("/mcp/")) return await Di(e, n);
2924
+ if (a.pathname === "/htbp" || a.pathname.startsWith("/htbp/")) {
2925
+ let t = await Ei(e, n, r.builtinHandlers, r.tunnelBroker, i), a = new Response(t.body, t);
2926
+ return a.headers.set("Access-Control-Allow-Origin", "*"), a;
2927
+ }
2928
+ return n.ASSETS.fetch(e);
2929
+ } catch (e) {
2930
+ return t(e);
2931
+ }
2932
+ }
2933
+ function Ai(e = {}) {
2934
+ return { fetch(t, n, r) {
2935
+ return ki(t, n, e, r);
2936
+ } };
2937
+ }
2938
+ var ji = Ai();
2939
+ //#endregion
2940
+ export { Ai as createBridge, ji as default };