@tangle-network/hub-sdk 0.22.0-develop.20260814062836.bb3da78 → 0.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,240 @@
1
1
  import { SSEChunkParser } from "@tangle-network/sdk-telemetry";
2
+ //#region src/json-init.ts
3
+ /** The init of a request whose body is JSON. Every client builds its bodies
4
+ * here, so the content type cannot drift from the encoding. */
5
+ function jsonInit(method, body) {
6
+ return {
7
+ method,
8
+ body: JSON.stringify(body),
9
+ headers: { "Content-Type": "application/json" }
10
+ };
11
+ }
12
+ //#endregion
13
+ //#region src/allowances.ts
14
+ var HubAllowancesClient = class {
15
+ constructor(request) {
16
+ this.request = request;
17
+ }
18
+ async plan(meter) {
19
+ return (await this.request(this.path(meter), { method: "GET" })).plan;
20
+ }
21
+ async setPlan(meter, plan) {
22
+ return (await this.request(this.path(meter), this.body("PUT", plan))).plan;
23
+ }
24
+ /** Admit one turn or refuse it. Retrying the same `turnId` never counts twice. */
25
+ async admit(meter, input) {
26
+ return (await this.request(`${this.path(meter)}/turns`, this.body("POST", input))).allowance;
27
+ }
28
+ /** What the member's next turn would get, without counting anything. */
29
+ async status(meter, subject) {
30
+ const query = new URLSearchParams();
31
+ if (subject.role) query.set("role", subject.role);
32
+ if (subject.payer) query.set("payer", subject.payer);
33
+ if (subject.payerRole) query.set("payerRole", subject.payerRole);
34
+ const suffix = query.size ? `?${query}` : "";
35
+ return (await this.request(`${this.memberPath(meter, subject.member)}${suffix}`, { method: "GET" })).allowance;
36
+ }
37
+ /** Move a member to the paid allowance until `expiresAt` (the paid period's end). */
38
+ async grant(meter, member, input) {
39
+ return (await this.request(`${this.memberPath(meter, member)}/grant`, this.body("PUT", {
40
+ tier: "paid",
41
+ ...input
42
+ }))).grant;
43
+ }
44
+ /** Synchronize a paid grant by durable product revision. Null expiry writes
45
+ * a retained revocation. A delayed older update is refused, never reactivated.
46
+ * There is no fallback to the unversioned grant endpoint on older servers. */
47
+ async syncGrant(meter, member, input) {
48
+ const { grant } = await this.request(`${this.memberPath(meter, member)}/grant/sync`, this.body("PUT", input));
49
+ if (grant.member !== member || grant.source !== input.source || grant.revision !== input.revision || grant.reference !== input.reference || grant.expiresAt !== (input.expiresAt === null ? null : new Date(input.expiresAt).toISOString())) throw new Error("The Hub returned a mismatched grant synchronization receipt");
50
+ return grant;
51
+ }
52
+ async revoke(meter, member) {
53
+ await this.request(`${this.memberPath(meter, member)}/grant`, { method: "DELETE" });
54
+ }
55
+ /** Turns per member and per line on one UTC day (default today). */
56
+ async usage(meter, day) {
57
+ const suffix = day ? `?day=${encodeURIComponent(day)}` : "";
58
+ return (await this.request(`${this.path(meter)}/usage${suffix}`, { method: "GET" })).usage;
59
+ }
60
+ path(meter) {
61
+ return `/v1/hub/allowances/${encodeURIComponent(meter)}`;
62
+ }
63
+ memberPath(meter, member) {
64
+ return `${this.path(meter)}/members/${encodeURIComponent(member)}`;
65
+ }
66
+ body(method, body) {
67
+ return jsonInit(method, body);
68
+ }
69
+ };
70
+ //#endregion
71
+ //#region src/apps.ts
72
+ function encodedId(id) {
73
+ if (typeof id !== "string" || !id || id.length > 256 || id === "." || id === "..") throw new Error("A bounded app or grant id is required");
74
+ return encodeURIComponent(id);
75
+ }
76
+ var HubAppsClient = class {
77
+ grants;
78
+ constructor(request) {
79
+ this.request = request;
80
+ this.grants = {
81
+ list: () => this.request("/v1/me/app-grants", { method: "GET" }),
82
+ revoke: async (grantId) => this.request(`/v1/me/app-grants/${encodedId(grantId)}/revoke`, { method: "POST" })
83
+ };
84
+ }
85
+ list() {
86
+ return this.request("/v1/apps", { method: "GET" });
87
+ }
88
+ /** The secret is returned only by creation; keep it in your server vault. */
89
+ create(input) {
90
+ return this.request("/v1/apps", jsonInit("POST", input));
91
+ }
92
+ /** Immutable association of two existing records with the same owner. */
93
+ async linkOAuthClient(appId, clientId) {
94
+ return this.request(`/v1/apps/${encodedId(appId)}/oidc-client`, jsonInit("POST", { clientId }));
95
+ }
96
+ async revoke(appId) {
97
+ return this.request(`/v1/apps/${encodedId(appId)}/revoke`, { method: "POST" });
98
+ }
99
+ };
100
+ //#endregion
101
+ //#region src/inbound-webhooks.ts
102
+ var HubInboundWebhooksClient = class {
103
+ constructor(request) {
104
+ this.request = request;
105
+ }
106
+ async create(connectionId, options = {}) {
107
+ return this.request(this.path(connectionId), jsonInit("POST", options));
108
+ }
109
+ async get(connectionId) {
110
+ return this.request(this.path(connectionId), { method: "GET" });
111
+ }
112
+ /** Add one owned Linq WhatsApp number without rotating the webhook secret. */
113
+ async ensurePhoneNumber(connectionId, phoneNumberId) {
114
+ if (!phoneNumberId || phoneNumberId.length > 128 || !/^[\x21-\x7e]+$/.test(phoneNumberId)) throw new Error("A bounded phone-number id is required");
115
+ return this.request(`${this.path(connectionId)}/phone-numbers/ensure`, jsonInit("POST", { phoneNumberId }));
116
+ }
117
+ /** Remove event subscriptions first. This does not silently rotate a live URL. */
118
+ async delete(connectionId) {
119
+ return this.request(this.path(connectionId), { method: "DELETE" });
120
+ }
121
+ path(connectionId) {
122
+ if (!connectionId || connectionId.length > 256) throw new Error("A bounded connection id is required");
123
+ return `/v1/hub/connections/${encodeURIComponent(connectionId)}/inbound-webhook`;
124
+ }
125
+ };
126
+ //#endregion
127
+ //#region src/lines.ts
128
+ /** Line calls share HubClient authentication and envelope handling. */
129
+ var HubLinesClient = class {
130
+ members;
131
+ checkins;
132
+ constructor(request, createWorkflow) {
133
+ this.request = request;
134
+ this.createWorkflow = createWorkflow;
135
+ this.members = { list: async (lineId) => (await this.request(`/v1/hub/lines/${encodeURIComponent(lineId)}/members`, { method: "GET" })).members };
136
+ this.checkins = { schedule: (cron, options) => {
137
+ const name = options.name ?? `line-checkin-${crypto.randomUUID().slice(0, 8)}`;
138
+ const yaml = [
139
+ `name: ${JSON.stringify(name)}`,
140
+ "on:",
141
+ ` schedule: { cron: ${JSON.stringify(cron)}, timezone: ${JSON.stringify(options.timezone)} }`,
142
+ "do:",
143
+ " - agent.run:",
144
+ " line:",
145
+ ` id: ${JSON.stringify(options.lineId)}`,
146
+ ` member: ${JSON.stringify(options.member)}`,
147
+ ` prompt: ${JSON.stringify(options.prompt)}`
148
+ ].join("\n");
149
+ return this.createWorkflow(yaml);
150
+ } };
151
+ }
152
+ async scheduleSend(cron, options) {
153
+ const name = options.name ?? `line-send-${crypto.randomUUID().slice(0, 8)}`;
154
+ const yaml = [
155
+ `name: ${JSON.stringify(name)}`,
156
+ "on:",
157
+ ` schedule: { cron: ${JSON.stringify(cron)}, timezone: ${JSON.stringify(options.timezone)} }`,
158
+ "do:",
159
+ " - line.send:",
160
+ ` lineId: ${JSON.stringify(options.lineId)}`,
161
+ ` memberId: ${JSON.stringify(options.memberId)}`,
162
+ ` text: ${JSON.stringify(options.text)}`,
163
+ ...options.notBefore ? [` notBefore: ${JSON.stringify(options.notBefore)}`] : []
164
+ ].join("\n");
165
+ return this.createWorkflow(yaml);
166
+ }
167
+ async context() {
168
+ return this.request("/v1/hub/lines/context", { method: "GET" });
169
+ }
170
+ async send(lineId, input) {
171
+ return this.request(`/v1/hub/lines/${encodeURIComponent(lineId)}/send`, jsonInit("POST", input));
172
+ }
173
+ async remind(lineId, input) {
174
+ return this.request(`/v1/hub/lines/${encodeURIComponent(lineId)}/remind`, jsonInit("POST", input));
175
+ }
176
+ };
177
+ //#endregion
178
+ //#region src/managed-numbers.ts
179
+ /** Administrative number operations through Hub's authenticated transport.
180
+ * A mutation is one attempt; an uncertain create reuses its quote and reference. */
181
+ var HubManagedNumbersClient = class {
182
+ constructor(request) {
183
+ this.request = request;
184
+ }
185
+ readiness() {
186
+ return this.request("/v1/hub/numbers/readiness", { method: "GET" });
187
+ }
188
+ /** One page of orders. Scope by `clientReference` to ask about one binding,
189
+ * and follow `nextCursor` for the rest; a page is never ownership evidence. */
190
+ list(query = {}) {
191
+ const params = new URLSearchParams();
192
+ if (query.clientReference !== void 0) params.set("clientReference", query.clientReference);
193
+ if (query.cursor !== void 0) params.set("cursor", query.cursor);
194
+ if (query.limit !== void 0) params.set("limit", String(query.limit));
195
+ const search = params.toString();
196
+ return this.request(`/v1/hub/numbers${search ? `?${search}` : ""}`, { method: "GET" });
197
+ }
198
+ get(id) {
199
+ return this.request(this.path(id), { method: "GET" });
200
+ }
201
+ quote(input) {
202
+ return this.request("/v1/hub/numbers/quote", this.post(input));
203
+ }
204
+ /** `clientReference` and `transport`, when given, must match the signed
205
+ * quote or Hub refuses the purchase with a conflict. */
206
+ create(input) {
207
+ return this.request("/v1/hub/numbers", this.post(input));
208
+ }
209
+ /** Fences references so no order can take them again. Call it as the last
210
+ * step before retiring the resource they name: a purchase that races the
211
+ * retirement is then refused (`409 number_reference_fenced`) instead of
212
+ * binding a line to a resource that is gone. Refused with
213
+ * `409 number_reference_held` while a live order holds one of them; cancel
214
+ * it first. A cancelled order no longer holds its reference, so the fence
215
+ * succeeds as soon as `cancel` returns, whether or not its release is still
216
+ * pending. Repeating a fence is harmless. */
217
+ fence(input) {
218
+ return this.request("/v1/hub/numbers/fences", this.post(input));
219
+ }
220
+ advance(id) {
221
+ return this.request(`${this.path(id)}/advance`, this.post({}));
222
+ }
223
+ cancel(id) {
224
+ return this.request(`${this.path(id)}/cancel`, this.post({}));
225
+ }
226
+ path(id) {
227
+ if (!/^num_[a-f0-9]{36}$/.test(id)) throw new Error("Invalid managed number order id");
228
+ return `/v1/hub/numbers/${encodeURIComponent(id)}`;
229
+ }
230
+ post(body) {
231
+ return jsonInit("POST", body);
232
+ }
233
+ };
234
+ //#endregion
2
235
  //#region src/redaction.ts
3
236
  const SECRET_KEY_PATTERN = /(api[_-]?key|authorization|capability[_-]?token|token|secret)/i;
4
- const SECRET_VALUE_PATTERN = /\b(?:sk-tan[-_]|hubcap_|hct_|gh[pousr]_)[A-Za-z0-9_=-]+\b/g;
237
+ const SECRET_VALUE_PATTERN = /\b(?:sk-tan[-_]|hubcap_|hct_|lrc_|gh[pousr]_)[A-Za-z0-9_.=-]+\b/g;
5
238
  function redactHubValue(value) {
6
239
  if (typeof value === "string") return value.replace(SECRET_VALUE_PATTERN, "[REDACTED]");
7
240
  if (Array.isArray(value)) return value.map((item) => redactHubValue(item));
@@ -52,8 +285,10 @@ function isHubSuccessEnvelope(value) {
52
285
  function isRecord$1(value) {
53
286
  return typeof value === "object" && value !== null;
54
287
  }
55
- function optString(value) {
56
- return typeof value === "string" ? value : "";
288
+ /** Read a wire field as a string, or "" when the server sent anything else.
289
+ * `raw` is that field straight off the parsed payload, before any check. */
290
+ function optString(raw) {
291
+ return typeof raw === "string" ? raw : "";
57
292
  }
58
293
  /** An agent iteration's terminal status (`iteration.ended`) — only ever
59
294
  * succeeded/failed; an iteration is never guard-skipped. */
@@ -81,63 +316,63 @@ function isRunDoneStatus(value) {
81
316
  * malformed `token` can never reach a consumer as `{ delta: undefined }`, and
82
317
  * new server event kinds don't break older clients.
83
318
  */
84
- function toRunStreamEvent(eventType, data) {
319
+ function toRunStreamEvent(eventType, raw) {
85
320
  if (eventType === "ping") return { type: "ping" };
86
- if (!isRecord$1(data)) return null;
321
+ if (!isRecord$1(raw)) return null;
87
322
  switch (eventType) {
88
- case "snapshot": return typeof data.id === "string" && typeof data.workflowId === "string" && typeof data.status === "string" && Array.isArray(data.actionResults) ? {
323
+ case "snapshot": return typeof raw.id === "string" && typeof raw.workflowId === "string" && typeof raw.status === "string" && Array.isArray(raw.actionResults) ? {
89
324
  type: "snapshot",
90
- run: data
325
+ run: raw
91
326
  } : null;
92
- case "token": return typeof data.delta === "string" && typeof data.actionIndex === "number" ? {
327
+ case "token": return typeof raw.delta === "string" && typeof raw.actionIndex === "number" ? {
93
328
  type: "token",
94
- actionIndex: data.actionIndex,
95
- delta: data.delta,
96
- at: optString(data.at)
329
+ actionIndex: raw.actionIndex,
330
+ delta: raw.delta,
331
+ at: optString(raw.at)
97
332
  } : null;
98
- case "run.done": return isRunDoneStatus(data.status) ? {
333
+ case "run.done": return isRunDoneStatus(raw.status) ? {
99
334
  type: "run.done",
100
- status: data.status,
101
- error: typeof data.error === "string" ? data.error : null,
102
- ...typeof data.at === "string" ? { at: data.at } : {}
335
+ status: raw.status,
336
+ error: typeof raw.error === "string" ? raw.error : null,
337
+ ...typeof raw.at === "string" ? { at: raw.at } : {}
103
338
  } : null;
104
- case "run.waiting": return typeof data.decisionId === "string" && data.decisionId.length > 0 ? {
339
+ case "run.waiting": return typeof raw.decisionId === "string" && raw.decisionId.length > 0 ? {
105
340
  type: "run.waiting",
106
- decisionId: data.decisionId,
107
- ...typeof data.at === "string" ? { at: data.at } : {}
341
+ decisionId: raw.decisionId,
342
+ ...typeof raw.at === "string" ? { at: raw.at } : {}
108
343
  } : null;
109
- case "action.started": return typeof data.index === "number" && typeof data.kind === "string" && typeof data.at === "string" ? {
344
+ case "action.started": return typeof raw.index === "number" && typeof raw.kind === "string" && typeof raw.at === "string" ? {
110
345
  type: "action.started",
111
- index: data.index,
112
- kind: data.kind,
113
- at: data.at
346
+ index: raw.index,
347
+ kind: raw.kind,
348
+ at: raw.at
114
349
  } : null;
115
- case "action.finished": return typeof data.index === "number" && typeof data.kind === "string" && isActionFinishedStatus(data.status) && typeof data.at === "string" ? {
350
+ case "action.finished": return typeof raw.index === "number" && typeof raw.kind === "string" && isActionFinishedStatus(raw.status) && typeof raw.at === "string" ? {
116
351
  type: "action.finished",
117
- index: data.index,
118
- kind: data.kind,
119
- status: data.status,
120
- at: data.at,
121
- ...typeof data.costUsd === "number" ? { costUsd: data.costUsd } : {},
122
- ...typeof data.error === "string" ? { error: data.error } : {}
352
+ index: raw.index,
353
+ kind: raw.kind,
354
+ status: raw.status,
355
+ at: raw.at,
356
+ ...typeof raw.costUsd === "number" ? { costUsd: raw.costUsd } : {},
357
+ ...typeof raw.error === "string" ? { error: raw.error } : {}
123
358
  } : null;
124
- case "iteration.started": return typeof data.actionIndex === "number" && typeof data.iterationIndex === "number" && typeof data.at === "string" ? {
359
+ case "iteration.started": return typeof raw.actionIndex === "number" && typeof raw.iterationIndex === "number" && typeof raw.at === "string" ? {
125
360
  type: "iteration.started",
126
- actionIndex: data.actionIndex,
127
- iterationIndex: data.iterationIndex,
128
- at: data.at,
129
- ...typeof data.model === "string" ? { model: data.model } : {}
361
+ actionIndex: raw.actionIndex,
362
+ iterationIndex: raw.iterationIndex,
363
+ at: raw.at,
364
+ ...typeof raw.model === "string" ? { model: raw.model } : {}
130
365
  } : null;
131
- case "iteration.ended": return typeof data.actionIndex === "number" && typeof data.iterationIndex === "number" && isIterationStatus(data.status) && typeof data.at === "string" ? {
366
+ case "iteration.ended": return typeof raw.actionIndex === "number" && typeof raw.iterationIndex === "number" && isIterationStatus(raw.status) && typeof raw.at === "string" ? {
132
367
  type: "iteration.ended",
133
- actionIndex: data.actionIndex,
134
- iterationIndex: data.iterationIndex,
135
- status: data.status,
136
- at: data.at,
137
- ...typeof data.outputPreview === "string" ? { outputPreview: data.outputPreview } : {},
138
- ...typeof data.inputTokens === "number" ? { inputTokens: data.inputTokens } : {},
139
- ...typeof data.outputTokens === "number" ? { outputTokens: data.outputTokens } : {},
140
- ...typeof data.costUsd === "number" ? { costUsd: data.costUsd } : {}
368
+ actionIndex: raw.actionIndex,
369
+ iterationIndex: raw.iterationIndex,
370
+ status: raw.status,
371
+ at: raw.at,
372
+ ...typeof raw.outputPreview === "string" ? { outputPreview: raw.outputPreview } : {},
373
+ ...typeof raw.inputTokens === "number" ? { inputTokens: raw.inputTokens } : {},
374
+ ...typeof raw.outputTokens === "number" ? { outputTokens: raw.outputTokens } : {},
375
+ ...typeof raw.costUsd === "number" ? { costUsd: raw.costUsd } : {}
141
376
  } : null;
142
377
  default: return null;
143
378
  }
@@ -145,8 +380,8 @@ function toRunStreamEvent(eventType, data) {
145
380
  /** True for an aborted/timed-out fetch (or any abort). fetch rejects with the
146
381
  * signal's reason — a DOMException named `AbortError` (caller) or `TimeoutError`
147
382
  * (AbortSignal.timeout). */
148
- function isAbortError(err) {
149
- return err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError");
383
+ function isAbortError(cause) {
384
+ return cause instanceof Error && (cause.name === "AbortError" || cause.name === "TimeoutError");
150
385
  }
151
386
  /** A signal that aborts when the caller's signal aborts OR `timeoutMs` elapses.
152
387
  * Returns undefined when neither bound applies (no per-request abort needed). */
@@ -220,13 +455,50 @@ function nonEmpty(value) {
220
455
  function readProcessEnv() {
221
456
  return globalThis.process?.env ?? {};
222
457
  }
223
- var HubClient = class HubClient {
458
+ var HubTransport = class {
224
459
  baseUrl;
225
460
  fetch;
226
461
  apiKey;
227
462
  authHeaders;
463
+ constructor(options) {
464
+ this.baseUrl = options.baseUrl.replace(/\/+$/, "");
465
+ this.apiKey = options.apiKey;
466
+ this.authHeaders = options.authHeaders;
467
+ this.fetch = options.fetch ?? fetch.bind(globalThis);
468
+ }
469
+ async request(path, init) {
470
+ const response = await this.fetch(`${this.baseUrl}${path}`, {
471
+ ...init,
472
+ headers: await this.buildHeaders(init.headers)
473
+ });
474
+ const status = response.status;
475
+ const contentType = response.headers.get("content-type") ?? "";
476
+ const bodyText = await response.text();
477
+ if (!contentType.includes("application/json")) throw httpError(path, status, response.statusText, bodyText, contentType);
478
+ let parsed;
479
+ try {
480
+ parsed = JSON.parse(bodyText);
481
+ } catch {
482
+ throw httpError(path, status, response.statusText, bodyText, contentType);
483
+ }
484
+ if (isHubErrorEnvelope(parsed)) throw new HubSdkError(parsed.error, { status });
485
+ if (isHubSuccessEnvelope(parsed)) return parsed.data;
486
+ throw httpError(path, status, response.statusText, bodyText, contentType);
487
+ }
488
+ async buildHeaders(headers) {
489
+ const mergedHeaders = new Headers({ Accept: "application/json" });
490
+ if (this.apiKey) mergedHeaders.set("Authorization", `Bearer ${this.apiKey}`);
491
+ if (this.authHeaders) for (const [key, value] of new Headers(await this.authHeaders())) mergedHeaders.set(key, value);
492
+ for (const [key, value] of new Headers(headers)) mergedHeaders.set(key, value);
493
+ return mergedHeaders;
494
+ }
495
+ };
496
+ var HubClient = class HubClient extends HubTransport {
497
+ allowances;
498
+ apps;
228
499
  connections;
229
500
  channels;
501
+ numbers;
230
502
  eventSubscriptions;
231
503
  permissions;
232
504
  tokens;
@@ -235,11 +507,12 @@ var HubClient = class HubClient {
235
507
  audit;
236
508
  githubApp;
237
509
  workflows;
510
+ lines;
238
511
  constructor(options) {
239
- this.baseUrl = options.baseUrl.replace(/\/+$/, "");
240
- this.apiKey = options.apiKey;
241
- this.authHeaders = options.authHeaders;
242
- this.fetch = options.fetch ?? fetch.bind(globalThis);
512
+ super(options);
513
+ this.allowances = new HubAllowancesClient((path, init) => this.request(path, init));
514
+ this.apps = new HubAppsClient((path, init) => this.request(path, init));
515
+ this.numbers = new HubManagedNumbersClient((path, init) => this.request(path, init));
243
516
  this.connections = new HubConnectionsClient((path, init) => this.request(path, init));
244
517
  this.channels = new HubChannelsClient((path, init) => this.request(path, init));
245
518
  this.eventSubscriptions = new HubEventSubscriptionsClient((path, init) => this.request(path, init));
@@ -250,6 +523,7 @@ var HubClient = class HubClient {
250
523
  this.audit = new HubAuditClient((path, init) => this.request(path, init));
251
524
  this.githubApp = new HubGithubAppClient((path, init) => this.request(path, init));
252
525
  this.workflows = new HubWorkflowsClient((path, init) => this.request(path, init), (path, init) => this.stream(path, init), (path, init) => this.requestBytes(path, init));
526
+ this.lines = new HubLinesClient((path, init) => this.request(path, init), (yaml) => this.workflows.create(yaml));
253
527
  }
254
528
  static fromEnv(options = {}) {
255
529
  const env = options.env ?? readProcessEnv();
@@ -263,25 +537,6 @@ var HubClient = class HubClient {
263
537
  async status() {
264
538
  return this.request("/v1/hub/status", { method: "GET" });
265
539
  }
266
- async request(path, init) {
267
- const response = await this.fetch(`${this.baseUrl}${path}`, {
268
- ...init,
269
- headers: await this.buildHeaders(init.headers)
270
- });
271
- const status = response.status;
272
- const contentType = response.headers.get("content-type") ?? "";
273
- const bodyText = await response.text();
274
- if (!contentType.includes("application/json")) throw httpError(path, status, response.statusText, bodyText, contentType);
275
- let parsed;
276
- try {
277
- parsed = JSON.parse(bodyText);
278
- } catch {
279
- throw httpError(path, status, response.statusText, bodyText, contentType);
280
- }
281
- if (isHubErrorEnvelope(parsed)) throw new HubSdkError(parsed.error, { status });
282
- if (isHubSuccessEnvelope(parsed)) return parsed.data;
283
- throw httpError(path, status, response.statusText, bodyText, contentType);
284
- }
285
540
  /**
286
541
  * Open a streaming (Server-Sent Events) response and return its raw body.
287
542
  * Shares auth-header building + `fetch` with {@link request}, but does NOT
@@ -348,25 +603,13 @@ var HubClient = class HubClient {
348
603
  contentType
349
604
  };
350
605
  }
351
- async buildHeaders(headers) {
352
- const mergedHeaders = new Headers(headers);
353
- if (!mergedHeaders.has("Accept")) mergedHeaders.set("Accept", "application/json");
354
- if (this.apiKey) mergedHeaders.set("Authorization", `Bearer ${this.apiKey}`);
355
- if (this.authHeaders) for (const [key, value] of new Headers(await this.authHeaders())) mergedHeaders.set(key, value);
356
- for (const [key, value] of new Headers(headers)) mergedHeaders.set(key, value);
357
- return mergedHeaders;
358
- }
359
606
  };
360
607
  var HubTokensClient = class {
361
608
  constructor(request) {
362
609
  this.request = request;
363
610
  }
364
611
  async mint(options) {
365
- return this.request("/v1/hub/tokens", {
366
- method: "POST",
367
- body: JSON.stringify(options),
368
- headers: { "Content-Type": "application/json" }
369
- });
612
+ return this.request("/v1/hub/tokens", jsonInit("POST", options));
370
613
  }
371
614
  async list(options = {}) {
372
615
  const searchParams = new URLSearchParams();
@@ -400,38 +643,22 @@ var HubPermissionsClient = class {
400
643
  return this.request(`/v1/hub/policies?connectionId=${encodeURIComponent(connectionId)}`, { method: "GET" });
401
644
  }
402
645
  async set(input) {
403
- return this.request("/v1/hub/policies", {
404
- method: "PUT",
405
- body: JSON.stringify(input),
406
- headers: { "Content-Type": "application/json" }
407
- });
646
+ return this.request("/v1/hub/policies", jsonInit("PUT", input));
408
647
  }
409
648
  /** Reset an action to its default by deleting any stored override. */
410
649
  async delete(input) {
411
- return this.request("/v1/hub/policies", {
412
- method: "DELETE",
413
- body: JSON.stringify(input),
414
- headers: { "Content-Type": "application/json" }
415
- });
650
+ return this.request("/v1/hub/policies", jsonInit("DELETE", input));
416
651
  }
417
652
  /** Bulk-allow every write action of a connection's provider. Reads are
418
653
  * already allowed for sandbox agents; destructive actions stay `ask`.
419
654
  * Idempotent: actions with an existing policy are left untouched. */
420
655
  async allowWrites(connectionId) {
421
- return this.request("/v1/hub/policies/allow-writes", {
422
- method: "POST",
423
- body: JSON.stringify({ connectionId }),
424
- headers: { "Content-Type": "application/json" }
425
- });
656
+ return this.request("/v1/hub/policies/allow-writes", jsonInit("POST", { connectionId }));
426
657
  }
427
658
  /** Inverse of `allowWrites`: delete only the rows it created for this
428
659
  * connection. Manual per-action decisions are left intact. */
429
660
  async revertWrites(connectionId) {
430
- return this.request("/v1/hub/policies/revert-writes", {
431
- method: "POST",
432
- body: JSON.stringify({ connectionId }),
433
- headers: { "Content-Type": "application/json" }
434
- });
661
+ return this.request("/v1/hub/policies/revert-writes", jsonInit("POST", { connectionId }));
435
662
  }
436
663
  };
437
664
  var HubToolsClient = class {
@@ -439,34 +666,32 @@ var HubToolsClient = class {
439
666
  this.request = request;
440
667
  }
441
668
  async search(query, options = {}) {
442
- return this.request("/v1/hub/tools/search", {
443
- method: "POST",
444
- body: JSON.stringify({
445
- query,
446
- provider: options.provider,
447
- limit: options.limit
448
- }),
449
- headers: { "Content-Type": "application/json" }
450
- });
669
+ return this.request("/v1/hub/tools/search", jsonInit("POST", {
670
+ query,
671
+ provider: options.provider,
672
+ limit: options.limit
673
+ }));
451
674
  }
452
675
  async sources() {
453
676
  return this.request("/v1/hub/tools/sources", { method: "GET" });
454
677
  }
455
678
  async describe(path) {
456
- return this.request("/v1/hub/tools/describe", {
457
- method: "POST",
458
- body: JSON.stringify({ path }),
459
- headers: { "Content-Type": "application/json" }
460
- });
679
+ return this.request("/v1/hub/tools/describe", jsonInit("POST", { path }));
461
680
  }
462
- async invoke(path, input, options = {}) {
463
- const execInit = this.buildExecInit(path, input, options.connectionId);
681
+ /**
682
+ * Run one hub tool. `raw` is the tool input: the SDK forwards it verbatim as
683
+ * the request body's `input`, and the server validates it against the tool's
684
+ * own schema, so the client never gives it a shape.
685
+ */
686
+ async invoke(path, raw, options = {}) {
687
+ const execInit = this.buildExecInit(path, raw, options);
464
688
  try {
465
689
  return await this.request("/v1/hub/exec", execInit);
466
690
  } catch (error) {
467
691
  if (!(error instanceof HubSdkError) || !requiresCapabilityToken(error)) throw error;
692
+ const approvalId = getApprovalId(error);
693
+ if (approvalId && options.approve !== true) throw error;
468
694
  if (options.approve) {
469
- const approvalId = getApprovalId(error);
470
695
  if (!approvalId) throw error;
471
696
  const approved = await this.request(`/v1/hub/approvals/${encodeURIComponent(approvalId)}/approve`, { method: "POST" });
472
697
  validateApprovedExecution(approved, path, options.connectionId);
@@ -484,15 +709,11 @@ var HubToolsClient = class {
484
709
  });
485
710
  }
486
711
  }
487
- const minted = await this.request("/v1/hub/tokens", {
488
- method: "POST",
489
- body: JSON.stringify({
490
- actionPath: path,
491
- connectionId: options.connectionId,
492
- provider: options.connectionId ? void 0 : path.split(".")[0]
493
- }),
494
- headers: { "Content-Type": "application/json" }
495
- });
712
+ const minted = await this.request("/v1/hub/tokens", jsonInit("POST", {
713
+ actionPath: path,
714
+ connectionId: options.connectionId,
715
+ provider: options.connectionId ? void 0 : path.split(".")[0]
716
+ }));
496
717
  return this.request("/v1/hub/exec", {
497
718
  ...execInit,
498
719
  headers: {
@@ -501,16 +722,13 @@ var HubToolsClient = class {
501
722
  }
502
723
  });
503
724
  }
504
- buildExecInit(path, input, connectionId) {
505
- return {
506
- method: "POST",
507
- body: JSON.stringify({
508
- path,
509
- input,
510
- connectionId
511
- }),
512
- headers: { "Content-Type": "application/json" }
513
- };
725
+ buildExecInit(path, raw, options) {
726
+ return jsonInit("POST", {
727
+ path,
728
+ input: raw,
729
+ connectionId: options.connectionId,
730
+ idempotencyKey: options.idempotencyKey
731
+ });
514
732
  }
515
733
  };
516
734
  function requiresCapabilityToken(error) {
@@ -540,6 +758,17 @@ function validateApprovedExecution(approved, path, connectionId) {
540
758
  }
541
759
  });
542
760
  }
761
+ const GITHUB_EXACT_CONNECT_SCOPES = [
762
+ "read:user",
763
+ "repo",
764
+ "read:org"
765
+ ];
766
+ function sameOAuthScopeSet(left, right) {
767
+ if (!Array.isArray(left)) return false;
768
+ const leftSet = new Set(left);
769
+ const rightSet = new Set(right);
770
+ return leftSet.size === left.length && rightSet.size === right.length && leftSet.size === rightSet.size && [...leftSet].every((scope) => rightSet.has(scope));
771
+ }
543
772
  var HubChannelsClient = class {
544
773
  constructor(request) {
545
774
  this.request = request;
@@ -548,11 +777,7 @@ var HubChannelsClient = class {
548
777
  return this.request("/v1/hub/channels", { method: "GET" });
549
778
  }
550
779
  async createEmail(input = {}) {
551
- return this.request("/v1/hub/channels/email", {
552
- method: "POST",
553
- body: JSON.stringify(input),
554
- headers: { "Content-Type": "application/json" }
555
- });
780
+ return this.request("/v1/hub/channels/email", jsonInit("POST", input));
556
781
  }
557
782
  async delete(channelId) {
558
783
  return this.request(`/v1/hub/channels/${encodeURIComponent(channelId)}`, { method: "DELETE" });
@@ -566,19 +791,17 @@ var HubEventSubscriptionsClient = class {
566
791
  return this.request("/v1/hub/event-subscriptions", { method: "GET" });
567
792
  }
568
793
  async create(input) {
569
- return this.request("/v1/hub/event-subscriptions", {
570
- method: "POST",
571
- body: JSON.stringify(input),
572
- headers: { "Content-Type": "application/json" }
573
- });
794
+ return this.request("/v1/hub/event-subscriptions", jsonInit("POST", input));
574
795
  }
575
796
  async delete(subscriptionId) {
576
797
  return this.request(`/v1/hub/event-subscriptions/${encodeURIComponent(subscriptionId)}`, { method: "DELETE" });
577
798
  }
578
799
  };
579
800
  var HubConnectionsClient = class {
801
+ inboundWebhook;
580
802
  constructor(request) {
581
803
  this.request = request;
804
+ this.inboundWebhook = new HubInboundWebhooksClient(request);
582
805
  }
583
806
  async list() {
584
807
  return this.request("/v1/hub/connections", { method: "GET" });
@@ -590,40 +813,38 @@ var HubConnectionsClient = class {
590
813
  return this.request("/v1/hub/providers", { method: "GET" });
591
814
  }
592
815
  async start(provider, options = {}) {
593
- return this.request(`/v1/hub/connections/${encodeURIComponent(provider)}/start`, {
594
- method: "POST",
595
- body: JSON.stringify({
596
- returnUrl: options.returnUrl,
597
- cli: options.cli,
598
- connectionParameters: options.connectionParameters
599
- }),
600
- headers: { "Content-Type": "application/json" }
816
+ if (options.requestedScopes !== void 0 && (provider !== "github" || !sameOAuthScopeSet(options.requestedScopes, GITHUB_EXACT_CONNECT_SCOPES))) throw new HubSdkError({
817
+ code: "HUB_INVALID_INPUT",
818
+ message: "GitHub requestedScopes must be read:user, repo, and read:org"
601
819
  });
820
+ const started = await this.request(`/v1/hub/connections/${encodeURIComponent(provider)}/start`, jsonInit("POST", {
821
+ returnUrl: options.returnUrl,
822
+ cli: options.cli,
823
+ connectionParameters: options.connectionParameters,
824
+ requestedScopes: options.requestedScopes
825
+ }));
826
+ if (options.requestedScopes !== void 0 && (started.provider !== provider || !sameOAuthScopeSet(started.scopes, options.requestedScopes))) throw new HubSdkError({
827
+ code: "HUB_CONFIG_MISSING",
828
+ message: "Hub did not preserve the requested OAuth scopes"
829
+ });
830
+ return started;
602
831
  }
603
832
  async startWhatsappEmbeddedSignup(options = {}) {
604
- return this.request("/v1/hub/connections/whatsapp-business/embedded-signup/start", {
605
- method: "POST",
606
- body: JSON.stringify({ returnUrl: options.returnUrl }),
607
- headers: { "Content-Type": "application/json" }
608
- });
833
+ return this.request("/v1/hub/connections/whatsapp-business/embedded-signup/start", jsonInit("POST", { returnUrl: options.returnUrl }));
609
834
  }
610
835
  async completeWhatsappEmbeddedSignup(input) {
611
- return this.request("/v1/hub/connections/whatsapp-business/embedded-signup/complete", {
612
- method: "POST",
613
- body: JSON.stringify(input),
614
- headers: { "Content-Type": "application/json" }
615
- });
836
+ return this.request("/v1/hub/connections/whatsapp-business/embedded-signup/complete", jsonInit("POST", input));
616
837
  }
617
838
  /** Connect a non-OAuth (api-key) connector by submitting the user's key.
618
839
  * The server validates the key with a live probe before persisting and
619
840
  * returns the created (or reconnected) connection — there is no redirect,
620
- * unlike `start`. */
621
- async connectApiKey(provider, apiKey) {
622
- return this.request(`/v1/hub/connections/${encodeURIComponent(provider)}/connect-key`, {
623
- method: "POST",
624
- body: JSON.stringify({ apiKey }),
625
- headers: { "Content-Type": "application/json" }
626
- });
841
+ * unlike `start`. Cloudbeds requires propertyId metadata and PriceLabs
842
+ * requires listing ID/PMS pairs; other providers have no metadata. */
843
+ async connectApiKey(provider, apiKey, metadata) {
844
+ return this.request(`/v1/hub/connections/${encodeURIComponent(provider)}/connect-key`, jsonInit("POST", {
845
+ apiKey,
846
+ ...metadata === void 0 ? {} : { metadata }
847
+ }));
627
848
  }
628
849
  async revoke(connectionId) {
629
850
  return this.request(`/v1/hub/connections/${encodeURIComponent(connectionId)}`, { method: "DELETE" });
@@ -651,11 +872,7 @@ var HubGithubAppClient = class {
651
872
  this.request = request;
652
873
  }
653
874
  async mintInstallationToken(input) {
654
- return this.request("/v1/hub/github-app/mint-installation-token", {
655
- method: "POST",
656
- body: JSON.stringify(input),
657
- headers: { "Content-Type": "application/json" }
658
- });
875
+ return this.request("/v1/hub/github-app/mint-installation-token", jsonInit("POST", input));
659
876
  }
660
877
  /** Every installation the caller may act through — their own and any org's
661
878
  * they were verified against. The management surface's read. */
@@ -730,11 +947,7 @@ var HubWorkflowsClient = class {
730
947
  return this.request(`/v1/workflows/${encodeURIComponent(id)}`, { method: "GET" });
731
948
  }
732
949
  async create(yaml) {
733
- return this.request("/v1/workflows", {
734
- method: "POST",
735
- body: JSON.stringify({ yaml }),
736
- headers: { "Content-Type": "application/json" }
737
- });
950
+ return this.request("/v1/workflows", jsonInit("POST", { yaml }));
738
951
  }
739
952
  /**
740
953
  * Replace the workflow's definition from YAML (recompiled server-side,
@@ -745,14 +958,10 @@ var HubWorkflowsClient = class {
745
958
  * concurrent modification, `NOT_FOUND` for an unknown/foreign id.
746
959
  */
747
960
  async update(id, yaml, opts = {}) {
748
- return this.request(`/v1/workflows/${encodeURIComponent(id)}`, {
749
- method: "PUT",
750
- body: JSON.stringify({
751
- yaml,
752
- ...opts.note !== void 0 ? { note: opts.note } : {}
753
- }),
754
- headers: { "Content-Type": "application/json" }
755
- });
961
+ return this.request(`/v1/workflows/${encodeURIComponent(id)}`, jsonInit("PUT", {
962
+ yaml,
963
+ ...opts.note !== void 0 ? { note: opts.note } : {}
964
+ }));
756
965
  }
757
966
  async delete(id) {
758
967
  await this.request(`/v1/workflows/${encodeURIComponent(id)}`, { method: "DELETE" });
@@ -763,11 +972,7 @@ var HubWorkflowsClient = class {
763
972
  * via `update`, but it can still be paused/resumed here).
764
973
  */
765
974
  async setEnabled(id, enabled) {
766
- return this.request(`/v1/workflows/${encodeURIComponent(id)}`, {
767
- method: "PATCH",
768
- body: JSON.stringify({ enabled }),
769
- headers: { "Content-Type": "application/json" }
770
- });
975
+ return this.request(`/v1/workflows/${encodeURIComponent(id)}`, jsonInit("PATCH", { enabled }));
771
976
  }
772
977
  /**
773
978
  * One page of run history, newest first. Pass the previous page's
@@ -795,9 +1000,7 @@ var HubWorkflowsClient = class {
795
1000
  async run(id, inputs, opts = {}) {
796
1001
  const hasInputs = inputs !== void 0 && Object.keys(inputs).length > 0;
797
1002
  return this.request(`/v1/workflows/${encodeURIComponent(id)}/run`, {
798
- method: "POST",
799
- body: JSON.stringify(hasInputs ? { inputs } : {}),
800
- headers: { "Content-Type": "application/json" },
1003
+ ...jsonInit("POST", hasInputs ? { inputs } : {}),
801
1004
  ...opts.signal ? { signal: opts.signal } : {}
802
1005
  });
803
1006
  }
@@ -976,11 +1179,7 @@ var HubWorkflowsClient = class {
976
1179
  * YAML no longer compiles, `CONFLICT` on a concurrent modification.
977
1180
  */
978
1181
  async rollback(id, rev) {
979
- return this.request(`/v1/workflows/${encodeURIComponent(id)}/rollback`, {
980
- method: "POST",
981
- body: JSON.stringify({ rev }),
982
- headers: { "Content-Type": "application/json" }
983
- });
1182
+ return this.request(`/v1/workflows/${encodeURIComponent(id)}/rollback`, jsonInit("POST", { rev }));
984
1183
  }
985
1184
  /**
986
1185
  * Deterministic health stats over the workflow's last N terminal runs
@@ -1001,11 +1200,7 @@ var HubWorkflowsClient = class {
1001
1200
  * until an owner approves.
1002
1201
  */
1003
1202
  async propose(id, input) {
1004
- return this.request(`/v1/workflows/${encodeURIComponent(id)}/proposals`, {
1005
- method: "POST",
1006
- body: JSON.stringify(input),
1007
- headers: { "Content-Type": "application/json" }
1008
- });
1203
+ return this.request(`/v1/workflows/${encodeURIComponent(id)}/proposals`, jsonInit("POST", input));
1009
1204
  }
1010
1205
  /**
1011
1206
  * Pending (proposed) and declined (rejected) revisions, newest first, with
@@ -1032,11 +1227,7 @@ var HubWorkflowsClient = class {
1032
1227
  * pending proposal.
1033
1228
  */
1034
1229
  async rejectProposal(id, rev, opts = {}) {
1035
- return this.request(`/v1/workflows/${encodeURIComponent(id)}/proposals/${encodeURIComponent(String(rev))}/reject`, {
1036
- method: "POST",
1037
- body: JSON.stringify(opts.reason !== void 0 ? { reason: opts.reason } : {}),
1038
- headers: { "Content-Type": "application/json" }
1039
- });
1230
+ return this.request(`/v1/workflows/${encodeURIComponent(id)}/proposals/${encodeURIComponent(String(rev))}/reject`, jsonInit("POST", opts.reason !== void 0 ? { reason: opts.reason } : {}));
1040
1231
  }
1041
1232
  /**
1042
1233
  * Mint a fresh webhook hook token, retiring the current one immediately.
@@ -1112,29 +1303,24 @@ var HubWorkflowsClient = class {
1112
1303
  /**
1113
1304
  * Upsert a key; returns the entry with its NEW version (increments on every
1114
1305
  * write). Throws `HubSdkError(KV_VALUE_TOO_LARGE)` past the 64KiB value cap
1115
- * or `KV_KEY_LIMIT` past the per-workflow key cap.
1306
+ * or `KV_KEY_LIMIT` past the per-workflow key cap. `raw` is the caller's
1307
+ * value, stored and read back verbatim, so the client never gives it a shape.
1116
1308
  */
1117
- async putKv(id, key, value) {
1118
- return this.request(`/v1/workflows/${encodeURIComponent(id)}/kv/${encodeURIComponent(key)}`, {
1119
- method: "PUT",
1120
- body: JSON.stringify({ value }),
1121
- headers: { "Content-Type": "application/json" }
1122
- });
1309
+ async putKv(id, key, raw) {
1310
+ return this.request(`/v1/workflows/${encodeURIComponent(id)}/kv/${encodeURIComponent(key)}`, jsonInit("PUT", { value: raw }));
1123
1311
  }
1124
1312
  /**
1125
1313
  * Compare-and-swap: the write lands only when the stored version still
1126
1314
  * equals `expectedVersion`; otherwise `HubSdkError(KV_VERSION_CONFLICT)`
1127
- * (409) — re-read and retry. Creation is {@link putKv}'s job.
1315
+ * (409) — re-read and retry. Creation is {@link putKv}'s job. `raw` is the
1316
+ * caller's value, stored and read back verbatim, so the client never gives it
1317
+ * a shape.
1128
1318
  */
1129
- async casKv(id, key, expectedVersion, value) {
1130
- return this.request(`/v1/workflows/${encodeURIComponent(id)}/kv/${encodeURIComponent(key)}/cas`, {
1131
- method: "POST",
1132
- body: JSON.stringify({
1133
- expectedVersion,
1134
- value
1135
- }),
1136
- headers: { "Content-Type": "application/json" }
1137
- });
1319
+ async casKv(id, key, expectedVersion, raw) {
1320
+ return this.request(`/v1/workflows/${encodeURIComponent(id)}/kv/${encodeURIComponent(key)}/cas`, jsonInit("POST", {
1321
+ expectedVersion,
1322
+ value: raw
1323
+ }));
1138
1324
  }
1139
1325
  /** Delete a key; idempotent — `deleted` reports whether a row was removed. */
1140
1326
  async deleteKv(id, key) {
@@ -1154,11 +1340,7 @@ var HubWorkflowsClient = class {
1154
1340
  * (400); an unknown template id throws `NOT_FOUND`.
1155
1341
  */
1156
1342
  async instantiateTemplate(templateId, parameters) {
1157
- return this.request(`/v1/workflows/templates/${encodeURIComponent(templateId)}/instantiate`, {
1158
- method: "POST",
1159
- body: JSON.stringify(parameters ? { parameters } : {}),
1160
- headers: { "Content-Type": "application/json" }
1161
- });
1343
+ return this.request(`/v1/workflows/templates/${encodeURIComponent(templateId)}/instantiate`, jsonInit("POST", parameters ? { parameters } : {}));
1162
1344
  }
1163
1345
  /**
1164
1346
  * The caller's open decisions across all workflows — the always-available
@@ -1185,11 +1367,7 @@ var HubWorkflowsClient = class {
1185
1367
  * (409 — answered, timed out, or cancelled first).
1186
1368
  */
1187
1369
  async resolveRunDecision(id, runId, input) {
1188
- return this.request(`/v1/workflows/${encodeURIComponent(id)}/runs/${encodeURIComponent(runId)}/decision/resolve`, {
1189
- method: "POST",
1190
- body: JSON.stringify(input),
1191
- headers: { "Content-Type": "application/json" }
1192
- });
1370
+ return this.request(`/v1/workflows/${encodeURIComponent(id)}/runs/${encodeURIComponent(runId)}/decision/resolve`, jsonInit("POST", input));
1193
1371
  }
1194
1372
  /**
1195
1373
  * Dry-run a YAML definition against the platform compiler without saving it.
@@ -1202,14 +1380,10 @@ var HubWorkflowsClient = class {
1202
1380
  * the unconnected providers is the point.
1203
1381
  */
1204
1382
  async validate(yaml, opts = {}) {
1205
- return this.request("/v1/workflows/validate", {
1206
- method: "POST",
1207
- body: JSON.stringify({
1208
- yaml,
1209
- ...opts.structural ? { structural: true } : {}
1210
- }),
1211
- headers: { "Content-Type": "application/json" }
1212
- });
1383
+ return this.request("/v1/workflows/validate", jsonInit("POST", {
1384
+ yaml,
1385
+ ...opts.structural ? { structural: true } : {}
1386
+ }));
1213
1387
  }
1214
1388
  async schema() {
1215
1389
  return this.request("/v1/workflows/schema", { method: "GET" });
@@ -1473,6 +1647,40 @@ function requestFailure(code, status, error, headers) {
1473
1647
  };
1474
1648
  }
1475
1649
  //#endregion
1476
- export { HUB_API_KEY_ENV_VAR, HUB_CAPABILITY_TOKEN_ENV_VAR, HUB_URL_ENV_VAR, HubApprovalsClient, HubAuditClient, HubChannelsClient, HubClient, HubConnectionsClient, HubEventDeliveryError, HubEventSubscriptionsClient, HubGithubAppClient, HubPermissionsClient, HubSdkError, HubTokensClient, HubToolsClient, HubWorkflowsClient, authenticateHubEventRequest, deriveHubEventCallbackSecret, parseHubEventDelivery, redactHubValue, resolveHubAuth, resolveHubBaseUrl, verifyHubEventSignature };
1650
+ //#region src/line-grants.ts
1651
+ function path(binding, suffix = "") {
1652
+ if (!binding.workspaceId || !binding.workspaceAgentId) throw new Error("A workspace and agent are required for a line grant");
1653
+ return `/v1/hub/line-grants/current${suffix}?${new URLSearchParams({
1654
+ workspaceId: binding.workspaceId,
1655
+ workspaceAgentId: binding.workspaceAgentId
1656
+ })}`;
1657
+ }
1658
+ /** Every call uses HubTransport's authHeaders, so one-use app broker tokens can be minted per request. */
1659
+ var HubLineGrantsClient = class extends HubTransport {
1660
+ current(binding) {
1661
+ return this.request(path(binding), { method: "GET" });
1662
+ }
1663
+ async line(binding) {
1664
+ return (await this.request(path(binding, "/line"), { method: "GET" })).line;
1665
+ }
1666
+ async attach(binding, input) {
1667
+ return (await this.request(path(binding, "/attachment"), jsonInit("PUT", input))).attachment;
1668
+ }
1669
+ detach(binding) {
1670
+ return this.request(path(binding, "/attachment"), { method: "DELETE" });
1671
+ }
1672
+ async threads(binding) {
1673
+ return (await this.request(path(binding, "/threads"), { method: "GET" })).threads;
1674
+ }
1675
+ async messages(binding, threadId) {
1676
+ if (!threadId || threadId.length > 256) throw new Error("A bounded line thread id is required");
1677
+ return (await this.request(path(binding, `/threads/${encodeURIComponent(threadId)}/messages`), { method: "GET" })).messages;
1678
+ }
1679
+ revoke(binding) {
1680
+ return this.request(path(binding), { method: "DELETE" });
1681
+ }
1682
+ };
1683
+ //#endregion
1684
+ export { HUB_API_KEY_ENV_VAR, HUB_CAPABILITY_TOKEN_ENV_VAR, HUB_URL_ENV_VAR, HubAllowancesClient, HubApprovalsClient, HubAppsClient, HubAuditClient, HubChannelsClient, HubClient, HubConnectionsClient, HubEventDeliveryError, HubEventSubscriptionsClient, HubGithubAppClient, HubInboundWebhooksClient, HubLineGrantsClient, HubLinesClient, HubManagedNumbersClient, HubPermissionsClient, HubSdkError, HubTokensClient, HubToolsClient, HubWorkflowsClient, authenticateHubEventRequest, deriveHubEventCallbackSecret, parseHubEventDelivery, redactHubValue, resolveHubAuth, resolveHubBaseUrl, verifyHubEventSignature };
1477
1685
 
1478
1686
  //# sourceMappingURL=index.js.map