@forgezero/providers 0.1.4 → 0.1.6

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/binance.js CHANGED
@@ -144,7 +144,7 @@ function createRegistry(options) {
144
144
  }
145
145
  return { call };
146
146
  }
147
- var VERSION = "0.1.4";
147
+ var VERSION = "0.1.6";
148
148
 
149
149
  // src/http.ts
150
150
  class BudgetExhausted extends ProviderError {
package/dist/chain.js CHANGED
@@ -144,7 +144,7 @@ function createRegistry(options) {
144
144
  }
145
145
  return { call };
146
146
  }
147
- var VERSION = "0.1.4";
147
+ var VERSION = "0.1.6";
148
148
 
149
149
  // src/chain.ts
150
150
  var hexToNumber = (value) => Number(BigInt(value));
@@ -13,36 +13,108 @@
13
13
  * HEALTH three failed connections mark it degraded, and the same admin
14
14
  * screen that shows email relays shows the database
15
15
  *
16
- * `failover: false` is therefore the default and a deliberate one. Set it true
17
- * only for read replicas, where answering from a stale replica beats not
18
- * answering.
16
+ * Coordinator routing below remains inside one authenticated cluster. It never
17
+ * treats a different database or replica as an automatic write destination.
19
18
  */
20
19
  /** Just enough of an ArangoDB client that this package imports nothing. */
21
20
  export interface ArangoLike {
22
- query<T = unknown>(query: unknown, bindVars?: Record<string, unknown>): Promise<{
21
+ query<T = unknown>(query: unknown, bindVars?: Record<string, unknown>, options?: {
22
+ allowDirtyRead?: boolean;
23
+ }): Promise<{
23
24
  all(): Promise<T[]>;
24
25
  }>;
25
26
  version?(): Promise<{
26
27
  version: string;
27
28
  }>;
29
+ close?(): void | Promise<void>;
28
30
  }
29
- export interface ArangoConfig {
31
+ export interface ArangoConnectOptions {
32
+ /** One coordinator from the verified list; the adapter owns selection. */
30
33
  url: string;
31
34
  database: string;
32
35
  username: string;
36
+ password: string;
37
+ loadBalancingStrategy: 'NONE';
38
+ /** Always zero: only this adapter may decide whether replay is safe. */
39
+ maxRetries: number;
40
+ }
41
+ export interface ArangoConfig {
42
+ /** Backwards-compatible single-coordinator coordinate. */
43
+ url?: string;
44
+ /** Explicit authenticated private coordinators. Bounded to prevent config abuse. */
45
+ urls?: readonly string[];
46
+ /**
47
+ * Dynamic membership is accepted only as a signed/attested envelope verified
48
+ * by the host. A Worker/KV node list by itself is discovery data, not routing
49
+ * authority.
50
+ */
51
+ membership?: ArangoMembershipSnapshot;
52
+ verifyMembership?: ArangoMembershipVerifier;
53
+ /** Required with dynamic membership, preventing a valid list crossing clusters. */
54
+ clusterId?: string;
55
+ database: string;
56
+ username: string;
33
57
  /** Built by the host, because a connection pool must outlive one call. */
34
- connect?: (options: {
35
- url: string;
36
- database: string;
37
- username: string;
38
- password: string;
39
- }) => ArangoLike;
40
- failover?: boolean;
58
+ connect?: (options: ArangoConnectOptions) => ArangoLike;
59
+ /** Maximum coordinator attempts for an explicitly safe request. */
60
+ maxCoordinatorAttempts?: number;
61
+ /** Local transport-failure quarantine. Primarily injectable for tests. */
62
+ unhealthyForMs?: number;
63
+ now?: () => number;
41
64
  }
42
65
  export interface Query {
43
66
  query: unknown;
44
67
  bindVars?: Record<string, unknown>;
68
+ /**
69
+ * No retry is the secure default. `read` and `idempotent` are explicit
70
+ * caller assertions; this adapter never guesses AQL semantics from text.
71
+ */
72
+ retrySafety?: 'read' | 'idempotent' | 'never';
73
+ /** Required when `retrySafety` is `idempotent`; retained for audit correlation. */
74
+ idempotencyKey?: string;
45
75
  }
76
+ export interface ArangoCoordinatorMember {
77
+ url: string;
78
+ /** Clients address Coordinators; Community 3.11.14 has no read-only joiner role. */
79
+ role: 'coordinator';
80
+ /** Actual `/_admin/server/mode` state for this Coordinator. */
81
+ serverMode: 'default';
82
+ capabilities: {
83
+ /** Always false for the exact Community 3.11.14 contract. */
84
+ dirtyFollowerReads: false;
85
+ };
86
+ status: 'healthy' | 'degraded' | 'unhealthy';
87
+ /** Milliseconds since epoch, covered by the membership signature/attestation. */
88
+ observedAt: number;
89
+ /** Enrolled hybrid identity. The node key is its Ed25519 public half. */
90
+ nodeKey: string;
91
+ publicKeys: {
92
+ ed25519: string;
93
+ mlDsa: string;
94
+ };
95
+ }
96
+ export interface ArangoMembershipSnapshot {
97
+ authority: 'forgezero-platform-signed' | 'node-attested';
98
+ edition: 'community';
99
+ version: '3.11.14';
100
+ clusterId: string;
101
+ revision: string;
102
+ issuedAt: number;
103
+ expiresAt: number;
104
+ coordinators: readonly ArangoCoordinatorMember[];
105
+ }
106
+ export type ArangoMembershipVerifier = (snapshot: ArangoMembershipSnapshot, signal?: AbortSignal) => Promise<boolean>;
107
+ export declare const MAX_ARANGO_COORDINATORS = 16;
108
+ export declare const ARANGO_COMMUNITY_VERSION: "3.11.14";
109
+ /** Protected API used to attest cluster-wide `default`/maintenance mode. */
110
+ export declare const ARANGO_SERVER_MODE_PATH: "/_admin/server/mode";
111
+ /**
112
+ * Accept only an explicit, bounded set of private authenticated endpoints.
113
+ * Service discovery may propose a new list, but it must pass this authority
114
+ * boundary before a fresh pool is created; public Worker/KV state is never a
115
+ * database routing authority.
116
+ */
117
+ export declare function arangoCoordinatorUrls(config: Pick<ArangoConfig, 'url' | 'urls'>): readonly string[];
46
118
  export declare const arangodb: import("./index").ProviderSpec<Query, unknown[]>;
47
119
  /** Drop memoised connections. Tests, and after a credential rotation. */
48
120
  export declare function resetPools(): void;
package/dist/database.js CHANGED
@@ -144,15 +144,148 @@ function createRegistry(options) {
144
144
  }
145
145
  return { call };
146
146
  }
147
- var VERSION = "0.1.4";
147
+ var VERSION = "0.1.6";
148
148
 
149
149
  // src/database.ts
150
150
  var pools = new Map;
151
+ var MAX_ARANGO_COORDINATORS = 16;
152
+ var ARANGO_COMMUNITY_VERSION = "3.11.14";
153
+ var ARANGO_SERVER_MODE_PATH = "/_admin/server/mode";
154
+ function arangoCoordinatorUrls(config) {
155
+ const input = config.urls ?? (config.url ? [config.url] : []);
156
+ if (input.length < 1 || input.length > MAX_ARANGO_COORDINATORS) {
157
+ throw new ProviderError("ARANGO_COORDINATORS_INVALID", `ArangoDB needs from 1 to ${MAX_ARANGO_COORDINATORS} private coordinator URLs.`);
158
+ }
159
+ const normalized = input.map((raw) => {
160
+ let value;
161
+ try {
162
+ value = new URL(raw);
163
+ } catch {
164
+ throw new ProviderError("ARANGO_COORDINATORS_INVALID", "ArangoDB coordinator URL is malformed.");
165
+ }
166
+ if (value.protocol !== "http:" && value.protocol !== "https:") {
167
+ throw new ProviderError("ARANGO_COORDINATORS_INVALID", "ArangoDB coordinators must use HTTP or HTTPS.");
168
+ }
169
+ if (value.username || value.password || value.search || value.hash || value.pathname && value.pathname !== "/") {
170
+ throw new ProviderError("ARANGO_COORDINATORS_INVALID", "ArangoDB coordinator URLs contain origins only; credentials and paths are separate.");
171
+ }
172
+ const hostname = value.hostname.replace(/^\[|\]$/g, "").toLowerCase();
173
+ const ipv4 = hostname.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)?.slice(1).map(Number);
174
+ const privateV4 = ipv4 && ipv4.every((part) => part >= 0 && part <= 255) && (ipv4[0] === 10 || ipv4[0] === 127 || ipv4[0] === 172 && ipv4[1] >= 16 && ipv4[1] <= 31 || ipv4[0] === 192 && ipv4[1] === 168);
175
+ const privateV6 = hostname === "::1" || /^f[cd][0-9a-f]:/i.test(hostname);
176
+ if (!privateV4 && !privateV6 && hostname !== "localhost") {
177
+ throw new ProviderError("ARANGO_COORDINATORS_INVALID", "ArangoDB coordinators must be literal private or loopback endpoints.");
178
+ }
179
+ value.hostname = value.hostname.toLowerCase();
180
+ return value.toString().replace(/\/$/, "");
181
+ });
182
+ if (new Set(normalized).size !== normalized.length) {
183
+ throw new ProviderError("ARANGO_COORDINATORS_INVALID", "ArangoDB coordinator URLs must be unique.");
184
+ }
185
+ return normalized;
186
+ }
187
+ async function resolveMembership(config, signal) {
188
+ if (!config.membership) {
189
+ const urls = arangoCoordinatorUrls(config);
190
+ return {
191
+ members: urls.map((url) => ({
192
+ url,
193
+ role: "coordinator",
194
+ serverMode: "default",
195
+ capabilities: { dirtyFollowerReads: false },
196
+ status: "healthy"
197
+ })),
198
+ identity: `static:${urls.join(",")}`
199
+ };
200
+ }
201
+ if (config.url || config.urls) {
202
+ throw new ProviderError("ARANGO_MEMBERSHIP_AMBIGUOUS", "Configure static coordinator URLs or verified membership, not both.");
203
+ }
204
+ if (!config.clusterId || config.membership.clusterId !== config.clusterId) {
205
+ throw new ProviderError("ARANGO_MEMBERSHIP_CLUSTER", "Verified ArangoDB membership does not match the configured cluster.");
206
+ }
207
+ if (!config.verifyMembership || !await config.verifyMembership(config.membership, signal)) {
208
+ throw new ProviderError("ARANGO_MEMBERSHIP_UNVERIFIED", "Dynamic ArangoDB membership must pass the host signature or attestation verifier.");
209
+ }
210
+ const now = (config.now ?? Date.now)();
211
+ const snapshot = config.membership;
212
+ if (snapshot.edition !== "community" || snapshot.version !== ARANGO_COMMUNITY_VERSION) {
213
+ throw new ProviderError("ARANGO_MEMBERSHIP_CONTRACT", `Dynamic ArangoDB membership must describe Community ${ARANGO_COMMUNITY_VERSION}.`);
214
+ }
215
+ if (!Number.isFinite(snapshot.issuedAt) || !Number.isFinite(snapshot.expiresAt) || snapshot.issuedAt > now || snapshot.expiresAt <= now) {
216
+ throw new ProviderError("ARANGO_MEMBERSHIP_EXPIRED", "Dynamic ArangoDB membership is not currently valid.");
217
+ }
218
+ const validAuthority = snapshot.authority === "forgezero-platform-signed" || snapshot.authority === "node-attested";
219
+ const validNodes = snapshot.coordinators.every((node) => Number.isFinite(node.observedAt) && node.nodeKey.length > 0 && node.nodeKey === node.publicKeys?.ed25519 && Boolean(node.publicKeys.mlDsa) && (node.status === "healthy" || node.status === "degraded" || node.status === "unhealthy") && node.role === "coordinator" && node.serverMode === "default" && node.capabilities?.dirtyFollowerReads === false);
220
+ if (!validAuthority || !snapshot.revision || !validNodes) {
221
+ throw new ProviderError("ARANGO_MEMBERSHIP_INVALID", "Dynamic ArangoDB membership needs a revision and observed timestamps.");
222
+ }
223
+ const allUrls = arangoCoordinatorUrls({ urls: snapshot.coordinators.map((node) => node.url) });
224
+ const members = allUrls.map((url, index) => ({ ...snapshot.coordinators[index], url })).filter((member) => member.status !== "unhealthy");
225
+ if (members.length === 0) {
226
+ throw new ProviderError("ARANGO_COORDINATORS_UNAVAILABLE", "Verified membership has no healthy or degraded ArangoDB coordinator.");
227
+ }
228
+ return {
229
+ members,
230
+ identity: `membership:${snapshot.clusterId}`,
231
+ issuedAt: snapshot.issuedAt,
232
+ revision: snapshot.revision
233
+ };
234
+ }
235
+ function retryableCoordinatorFailure(error) {
236
+ const failure = error;
237
+ const status = typeof failure.code === "number" ? failure.code : failure.status;
238
+ if (status === 408 || status === 429 || status === 502 || status === 503 || status === 504)
239
+ return true;
240
+ return typeof failure.code === "string" && [
241
+ "ECONNREFUSED",
242
+ "ECONNRESET",
243
+ "EHOSTUNREACH",
244
+ "ENETUNREACH",
245
+ "ETIMEDOUT"
246
+ ].includes(failure.code);
247
+ }
248
+ function boundedAttempts(config, available, safe) {
249
+ if (!safe)
250
+ return 1;
251
+ const requested = config.maxCoordinatorAttempts ?? available;
252
+ if (!Number.isInteger(requested) || requested < 1 || requested > MAX_ARANGO_COORDINATORS) {
253
+ throw new ProviderError("ARANGO_ATTEMPTS_INVALID", `ArangoDB coordinator attempts must be from 1 to ${MAX_ARANGO_COORDINATORS}.`);
254
+ }
255
+ return Math.min(requested, available);
256
+ }
257
+ function requestIsSafe(request) {
258
+ if (request.retrySafety === "read")
259
+ return true;
260
+ if (request.retrySafety !== "idempotent")
261
+ return false;
262
+ if (!request.idempotencyKey || request.idempotencyKey.length > 128) {
263
+ throw new ProviderError("ARANGO_IDEMPOTENCY_KEY_INVALID", "An idempotent ArangoDB retry needs a non-empty idempotency key of at most 128 characters.");
264
+ }
265
+ return true;
266
+ }
267
+ function selectNode(pool, excluded, now, eligibleMember) {
268
+ const eligible = pool.nodes.filter((node) => !excluded.has(node.url) && node.unhealthyUntil <= now && eligibleMember(node));
269
+ if (eligible.length === 0)
270
+ return;
271
+ const least = Math.min(...eligible.map((node) => node.inFlight));
272
+ for (let offset = 0;offset < pool.nodes.length; offset += 1) {
273
+ const index = (pool.cursor + offset) % pool.nodes.length;
274
+ const node = pool.nodes[index];
275
+ if (!excluded.has(node.url) && node.unhealthyUntil <= now && eligibleMember(node) && node.inFlight === least) {
276
+ pool.cursor = (index + 1) % pool.nodes.length;
277
+ return node;
278
+ }
279
+ }
280
+ return;
281
+ }
282
+ function nodeForRequest(pool, excluded, now) {
283
+ return selectNode(pool, excluded, now, () => true);
284
+ }
151
285
  var arangodb = defineProvider({
152
286
  id: "arangodb",
153
287
  service: "database",
154
288
  label: "ArangoDB",
155
- multiInstance: true,
156
289
  credentials: {
157
290
  type: "object",
158
291
  additionalProperties: false,
@@ -164,20 +297,45 @@ var arangodb = defineProvider({
164
297
  config: {
165
298
  type: "object",
166
299
  additionalProperties: false,
167
- required: ["url", "database", "username"],
300
+ required: ["database", "username"],
301
+ anyOf: [
302
+ { required: ["url"] },
303
+ { required: ["urls"] },
304
+ { required: ["clusterId"] }
305
+ ],
168
306
  properties: {
169
307
  url: {
170
308
  type: "string",
171
309
  title: "URL",
172
310
  description: "Bind to loopback. A database reachable from the internet is a database that will be."
173
311
  },
312
+ urls: {
313
+ type: "array",
314
+ minItems: 1,
315
+ maxItems: MAX_ARANGO_COORDINATORS,
316
+ uniqueItems: true,
317
+ items: { type: "string" },
318
+ title: "Coordinator URLs",
319
+ description: "Authenticated private coordinators in this one logical cluster."
320
+ },
321
+ clusterId: {
322
+ type: "string",
323
+ title: "Cluster ID",
324
+ description: "Binds host-verified dynamic membership to one logical cluster."
325
+ },
174
326
  database: { type: "string", title: "Database" },
175
327
  username: { type: "string", title: "Username" },
176
- failover: {
177
- type: "boolean",
178
- default: false,
179
- title: "Allow failover",
180
- description: "Off by default. Writing to a different database because the first was slow is data loss with extra steps. Enable only for read replicas."
328
+ maxCoordinatorAttempts: {
329
+ type: "integer",
330
+ minimum: 1,
331
+ maximum: MAX_ARANGO_COORDINATORS,
332
+ title: "Safe request attempts"
333
+ },
334
+ unhealthyForMs: {
335
+ type: "integer",
336
+ minimum: 1000,
337
+ maximum: 300000,
338
+ title: "Local coordinator quarantine (ms)"
181
339
  }
182
340
  }
183
341
  },
@@ -186,35 +344,111 @@ var arangodb = defineProvider({
186
344
  if (!config.connect) {
187
345
  throw new ProviderError("ARANGO_NO_CONNECT", "Provide a connect function in this provider's config — arangojs on a server; a database is not reachable from an edge runtime.");
188
346
  }
189
- const key = `${config.url}/${config.database}/${config.username}`;
190
- let client = pools.get(key);
191
- if (!client) {
192
- client = config.connect({
193
- url: config.url,
194
- database: config.database,
195
- username: config.username,
196
- password: await context.secret("password")
347
+ const membership = await resolveMembership(config, context.signal);
348
+ const members = membership.members;
349
+ const urls = members.map(({ url }) => url);
350
+ const safe = requestIsSafe(request);
351
+ const available = members.length;
352
+ if (available === 0) {
353
+ throw new ProviderError("ARANGO_COORDINATORS_UNAVAILABLE", "No verified authoritative ArangoDB coordinator is available.");
354
+ }
355
+ const attempts = boundedAttempts(config, available, safe);
356
+ const key = `${membership.identity}/${config.database}/${config.username}`;
357
+ let pool = pools.get(key);
358
+ if (!pool) {
359
+ const password = await context.secret("password");
360
+ pool = {
361
+ nodes: members.map((member) => ({
362
+ url: member.url,
363
+ member,
364
+ client: config.connect({
365
+ url: member.url,
366
+ database: config.database,
367
+ username: config.username,
368
+ password,
369
+ loadBalancingStrategy: "NONE",
370
+ maxRetries: 0
371
+ }),
372
+ inFlight: 0,
373
+ unhealthyUntil: 0
374
+ })),
375
+ cursor: 0,
376
+ membershipIssuedAt: membership.issuedAt,
377
+ membershipRevision: membership.revision
378
+ };
379
+ pools.set(key, pool);
380
+ } else if (membership.issuedAt !== undefined) {
381
+ if (pool.membershipIssuedAt !== undefined && membership.issuedAt < pool.membershipIssuedAt) {
382
+ throw new ProviderError("ARANGO_MEMBERSHIP_ROLLBACK", "ArangoDB membership is older than the last accepted signed revision.");
383
+ }
384
+ const existing = new Map(pool.nodes.map((node) => [node.url, node]));
385
+ const missing = urls.filter((url) => !existing.has(url));
386
+ const password = missing.length > 0 ? await context.secret("password") : undefined;
387
+ const nextNodes = members.map((member) => {
388
+ const retained2 = existing.get(member.url);
389
+ if (retained2) {
390
+ retained2.member = member;
391
+ return retained2;
392
+ }
393
+ return {
394
+ url: member.url,
395
+ member,
396
+ client: config.connect({
397
+ url: member.url,
398
+ database: config.database,
399
+ username: config.username,
400
+ password,
401
+ loadBalancingStrategy: "NONE",
402
+ maxRetries: 0
403
+ }),
404
+ inFlight: 0,
405
+ unhealthyUntil: 0
406
+ };
197
407
  });
198
- pools.set(key, client);
408
+ const retained = new Set(urls);
409
+ for (const removed of pool.nodes.filter((node) => !retained.has(node.url) && node.inFlight === 0)) {
410
+ try {
411
+ await removed.client.close?.();
412
+ } catch {}
413
+ }
414
+ pool.nodes = nextNodes;
415
+ pool.cursor %= nextNodes.length;
416
+ pool.membershipIssuedAt = membership.issuedAt;
417
+ pool.membershipRevision = membership.revision;
418
+ }
419
+ const tried = new Set;
420
+ let lastError;
421
+ for (let attempt = 0;attempt < attempts; attempt += 1) {
422
+ if (context.signal?.aborted) {
423
+ throw context.signal.reason ?? new ProviderError("ARANGO_ABORTED", "ArangoDB request was cancelled.");
424
+ }
425
+ const now = (config.now ?? Date.now)();
426
+ const node = nodeForRequest(pool, tried, now);
427
+ if (!node)
428
+ break;
429
+ tried.add(node.url);
430
+ node.inFlight += 1;
431
+ try {
432
+ const cursor = await node.client.query(request.query, request.bindVars);
433
+ const result = await cursor.all();
434
+ node.unhealthyUntil = 0;
435
+ return result;
436
+ } catch (error) {
437
+ lastError = error;
438
+ if (!retryableCoordinatorFailure(error))
439
+ throw error;
440
+ const quarantine = Math.min(Math.max(config.unhealthyForMs ?? 15000, 1000), 300000);
441
+ node.unhealthyUntil = now + quarantine;
442
+ if (!safe)
443
+ throw error;
444
+ } finally {
445
+ node.inFlight -= 1;
446
+ }
199
447
  }
200
- const cursor = await client.query(request.query, request.bindVars);
201
- return cursor.all();
448
+ throw lastError ?? new ProviderError("ARANGO_COORDINATORS_UNAVAILABLE", "No healthy ArangoDB coordinator is available.");
202
449
  },
203
- classify(error) {
204
- const arango = error;
205
- if (arango.errorNum === 1210)
206
- return "terminal";
207
- if (arango.errorNum === 1202)
208
- return "terminal";
209
- if (arango.errorNum === 1501)
210
- return "terminal";
211
- if (arango.code === 400 || arango.code === 404 || arango.code === 409)
212
- return "terminal";
213
- if (arango.code === 401 || arango.code === 403)
214
- return "retryable";
215
- if (arango.code === 503)
216
- return "backoff";
217
- return "retryable";
450
+ classify() {
451
+ return "terminal";
218
452
  }
219
453
  });
220
454
  function resetPools() {
@@ -224,5 +458,9 @@ var databaseProviders = [arangodb];
224
458
  export {
225
459
  resetPools,
226
460
  databaseProviders,
227
- arangodb
461
+ arangodb,
462
+ arangoCoordinatorUrls,
463
+ MAX_ARANGO_COORDINATORS,
464
+ ARANGO_SERVER_MODE_PATH,
465
+ ARANGO_COMMUNITY_VERSION
228
466
  };
package/dist/email.js CHANGED
@@ -144,7 +144,7 @@ function createRegistry(options) {
144
144
  }
145
145
  return { call };
146
146
  }
147
- var VERSION = "0.1.4";
147
+ var VERSION = "0.1.6";
148
148
 
149
149
  // src/email.ts
150
150
  var recipients = (to) => Array.isArray(to) ? [...to] : [to];
package/dist/http.js CHANGED
@@ -144,7 +144,7 @@ function createRegistry(options) {
144
144
  }
145
145
  return { call };
146
146
  }
147
- var VERSION = "0.1.4";
147
+ var VERSION = "0.1.6";
148
148
 
149
149
  // src/http.ts
150
150
  class BudgetExhausted extends ProviderError {
package/dist/index.d.ts CHANGED
@@ -156,4 +156,4 @@ export interface EmailMessage {
156
156
  from?: string;
157
157
  replyTo?: string;
158
158
  }
159
- export declare const VERSION = "0.1.4";
159
+ export declare const VERSION = "0.1.6";
package/dist/index.js CHANGED
@@ -144,7 +144,7 @@ function createRegistry(options) {
144
144
  }
145
145
  return { call };
146
146
  }
147
- var VERSION = "0.1.4";
147
+ var VERSION = "0.1.6";
148
148
  export {
149
149
  staticConfig,
150
150
  nextHealth,
package/dist/pool.js CHANGED
@@ -144,7 +144,7 @@ function createRegistry(options) {
144
144
  }
145
145
  return { call };
146
146
  }
147
- var VERSION = "0.1.4";
147
+ var VERSION = "0.1.6";
148
148
 
149
149
  // src/http.ts
150
150
  class BudgetExhausted extends ProviderError {
package/dist/storage.js CHANGED
@@ -144,7 +144,7 @@ function createRegistry(options) {
144
144
  }
145
145
  return { call };
146
146
  }
147
- var VERSION = "0.1.4";
147
+ var VERSION = "0.1.6";
148
148
 
149
149
  // src/storage.ts
150
150
  var encoder = new TextEncoder;
@@ -144,7 +144,7 @@ function createRegistry(options) {
144
144
  }
145
145
  return { call };
146
146
  }
147
- var VERSION = "0.1.4";
147
+ var VERSION = "0.1.6";
148
148
 
149
149
  // src/translation.ts
150
150
  var GOOGLE_ENDPOINT = "https://generativelanguage.googleapis.com/v1beta/models";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgezero/providers",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public",