@irogane/kaji 0.2.0-beta.11

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 (136) hide show
  1. package/LICENSE +105 -0
  2. package/README.md +598 -0
  3. package/contracts/README.md +14 -0
  4. package/contracts/beta-core-v1.json +52 -0
  5. package/contracts/cli/init-cases-v1.json +27 -0
  6. package/contracts/errors/error-codes.json +48 -0
  7. package/contracts/errors/integration-recovery-v1.json +127 -0
  8. package/contracts/errors/provider-normalization.json +111 -0
  9. package/contracts/events/conformance-invalid.json +20 -0
  10. package/contracts/events/conformance.json +511 -0
  11. package/contracts/events/new-kaji-event-v1.schema.json +1021 -0
  12. package/contracts/events/stored-kaji-event-v1.schema.json +1025 -0
  13. package/contracts/feature-tiers-v1.json +488 -0
  14. package/contracts/integrations/abi-index-v1.json +8 -0
  15. package/contracts/integrations/conformance-invalid.json +443 -0
  16. package/contracts/integrations/conformance-valid.json +121 -0
  17. package/contracts/integrations/copy-provenance-v1.schema.json +61 -0
  18. package/contracts/integrations/echo-tool-abi-v1.json +37 -0
  19. package/contracts/integrations/github-api-conformance-v1.json +644 -0
  20. package/contracts/integrations/github-tool-abi-typescript-v1.json +369 -0
  21. package/contracts/integrations/github-tool-abi-v1.json +146 -0
  22. package/contracts/integrations/gmail-api-conformance-v1.json +750 -0
  23. package/contracts/integrations/gmail-tool-abi-v1.json +62 -0
  24. package/contracts/integrations/index.schema.json +37 -0
  25. package/contracts/integrations/manifest.schema.json +119 -0
  26. package/contracts/parity/expected-normalized.json +4906 -0
  27. package/contracts/parity/scenarios.json +100 -0
  28. package/contracts/parity/scenarios.schema.json +214 -0
  29. package/contracts/providers/cost-conformance.json +112 -0
  30. package/contracts/release/github-proof-v1.schema.json +138 -0
  31. package/contracts/release/gmail-proof-v1.schema.json +138 -0
  32. package/contracts/release/kaji-ts-consumer-handoff-v1.schema.json +1289 -0
  33. package/contracts/release/publisher-identity-receipt-v1.schema.json +319 -0
  34. package/contracts/release/typescript-onboarding-evidence-v1.schema.json +740 -0
  35. package/contracts/tools/conformance-invalid.json +271 -0
  36. package/contracts/tools/conformance-valid.json +78 -0
  37. package/contracts/tools/tool-schema-v1.schema.json +18 -0
  38. package/dist/anthropic.cjs +1231 -0
  39. package/dist/anthropic.cjs.map +1 -0
  40. package/dist/anthropic.d.cts +26 -0
  41. package/dist/anthropic.d.ts +26 -0
  42. package/dist/anthropic.js +270 -0
  43. package/dist/anthropic.js.map +1 -0
  44. package/dist/auth.cjs +1507 -0
  45. package/dist/auth.cjs.map +1 -0
  46. package/dist/auth.d.cts +129 -0
  47. package/dist/auth.d.ts +129 -0
  48. package/dist/auth.js +1039 -0
  49. package/dist/auth.js.map +1 -0
  50. package/dist/base-B9FRMcP8.d.cts +140 -0
  51. package/dist/base-nHQd1VtS.d.ts +140 -0
  52. package/dist/chunk-AAM33KAO.js +4367 -0
  53. package/dist/chunk-AAM33KAO.js.map +1 -0
  54. package/dist/chunk-KAJ6BM64.js +153 -0
  55. package/dist/chunk-KAJ6BM64.js.map +1 -0
  56. package/dist/chunk-KCAXIOZS.js +308 -0
  57. package/dist/chunk-KCAXIOZS.js.map +1 -0
  58. package/dist/chunk-LSJ4AVO2.js +243 -0
  59. package/dist/chunk-LSJ4AVO2.js.map +1 -0
  60. package/dist/chunk-TM7ZGOJX.js +716 -0
  61. package/dist/chunk-TM7ZGOJX.js.map +1 -0
  62. package/dist/cli/bin.d.ts +2 -0
  63. package/dist/cli/bin.js +13 -0
  64. package/dist/cli/bin.js.map +1 -0
  65. package/dist/cli/chunk-2RCWPRVY.js +6277 -0
  66. package/dist/cli/chunk-2RCWPRVY.js.map +1 -0
  67. package/dist/cli/chunk-SEBX54TR.js +681 -0
  68. package/dist/cli/chunk-SEBX54TR.js.map +1 -0
  69. package/dist/cli/index.d.ts +232 -0
  70. package/dist/cli/index.js +11 -0
  71. package/dist/cli/index.js.map +1 -0
  72. package/dist/cli/init-worker.d.ts +2 -0
  73. package/dist/cli/init-worker.js +18 -0
  74. package/dist/cli/init-worker.js.map +1 -0
  75. package/dist/cli/integration-copy-worker.js +48 -0
  76. package/dist/cli/integration-copy-worker.js.map +1 -0
  77. package/dist/cli/package-entry-cjs.cjs +21 -0
  78. package/dist/cli/package-entry-cjs.cjs.map +1 -0
  79. package/dist/cli/package-entry-cjs.d.cts +2 -0
  80. package/dist/cli/package-entry.d.ts +2 -0
  81. package/dist/cli/package-entry.js +13 -0
  82. package/dist/cli/package-entry.js.map +1 -0
  83. package/dist/context-BaFHrQHv.d.cts +21 -0
  84. package/dist/context-BaFHrQHv.d.ts +21 -0
  85. package/dist/context-C-YPY-GS.d.cts +1538 -0
  86. package/dist/context-C-YPY-GS.d.ts +1538 -0
  87. package/dist/index.cjs +12346 -0
  88. package/dist/index.cjs.map +1 -0
  89. package/dist/index.d.cts +1560 -0
  90. package/dist/index.d.ts +1560 -0
  91. package/dist/index.js +7852 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/integrations/github.cjs +2092 -0
  94. package/dist/integrations/github.cjs.map +1 -0
  95. package/dist/integrations/github.d.cts +21 -0
  96. package/dist/integrations/github.d.ts +21 -0
  97. package/dist/integrations/github.js +2088 -0
  98. package/dist/integrations/github.js.map +1 -0
  99. package/dist/integrations.cjs +3370 -0
  100. package/dist/integrations.cjs.map +1 -0
  101. package/dist/integrations.d.cts +202 -0
  102. package/dist/integrations.d.ts +202 -0
  103. package/dist/integrations.js +2650 -0
  104. package/dist/integrations.js.map +1 -0
  105. package/dist/observability-Cj--OkME.d.cts +96 -0
  106. package/dist/observability-Cj--OkME.d.ts +96 -0
  107. package/dist/openai.cjs +1235 -0
  108. package/dist/openai.cjs.map +1 -0
  109. package/dist/openai.d.cts +32 -0
  110. package/dist/openai.d.ts +32 -0
  111. package/dist/openai.js +272 -0
  112. package/dist/openai.js.map +1 -0
  113. package/dist/testing.cjs +554 -0
  114. package/dist/testing.cjs.map +1 -0
  115. package/dist/testing.d.cts +43 -0
  116. package/dist/testing.d.ts +43 -0
  117. package/dist/testing.js +118 -0
  118. package/dist/testing.js.map +1 -0
  119. package/package.json +188 -0
  120. package/registry/echo/index.ts +53 -0
  121. package/registry/echo/manifest.json +53 -0
  122. package/registry/github/LICENSE +105 -0
  123. package/registry/github/client.ts +1727 -0
  124. package/registry/github/index.ts +263 -0
  125. package/registry/github/manifest.json +227 -0
  126. package/registry/github/owner-fixtures.json +10 -0
  127. package/registry/github/tests/github.test.ts +32 -0
  128. package/registry/gmail/LICENSE +105 -0
  129. package/registry/gmail/client.ts +548 -0
  130. package/registry/gmail/index.ts +165 -0
  131. package/registry/gmail/manifest.json +102 -0
  132. package/registry/gmail/owner-fixtures.json +10 -0
  133. package/registry/gmail/tests/gmail.test.ts +32 -0
  134. package/registry/index.json +21 -0
  135. package/registry/index.schema.json +37 -0
  136. package/registry/schema.json +119 -0
@@ -0,0 +1,716 @@
1
+ import { canonicalJsonValue, cloneAndFreezeJson } from './chunk-KAJ6BM64.js';
2
+ import { NOOP_METRICS, recordMetric } from './chunk-LSJ4AVO2.js';
3
+
4
+ // src/runtime/cancellation.ts
5
+ var CancellationError = class extends Error {
6
+ constructor(message = "Agent run was cancelled") {
7
+ super(message);
8
+ this.name = "CancellationError";
9
+ }
10
+ };
11
+ function throwIfCancellationRequested(token) {
12
+ if (!token?.isCancelled) return;
13
+ if (typeof token.throwIfCancelled === "function") {
14
+ token.throwIfCancelled();
15
+ }
16
+ throw new CancellationError();
17
+ }
18
+
19
+ // src/providers/base.ts
20
+ var PROVIDER_RESPONSE_DIAGNOSTICS = /* @__PURE__ */ Symbol.for(
21
+ "kaji.provider.responseDiagnostics"
22
+ );
23
+ function getProviderResponseDiagnostics(options) {
24
+ return options?.[PROVIDER_RESPONSE_DIAGNOSTICS];
25
+ }
26
+ var DEFAULT_PROVIDER_RESPONSE_LIMITS = Object.freeze({
27
+ textMaxBytes: 262144,
28
+ toolArgumentsMaxBytes: 65536,
29
+ responseMaxBytes: 524288,
30
+ toolCallsMax: 64
31
+ });
32
+ function resolveProviderResponseLimits(limits) {
33
+ const resolved = { ...DEFAULT_PROVIDER_RESPONSE_LIMITS, ...limits };
34
+ for (const [name, value] of Object.entries(resolved)) {
35
+ if (!Number.isSafeInteger(value) || value < 1) {
36
+ throw new RangeError(`${name} must be a positive safe integer`);
37
+ }
38
+ }
39
+ return Object.freeze(resolved);
40
+ }
41
+ function parseRetryAfterMs(error) {
42
+ if (typeof error !== "object" || error === null) return void 0;
43
+ const headers = "headers" in error ? error.headers : "response" in error && typeof error.response === "object" ? error.response?.headers ?? null : null;
44
+ if (typeof headers !== "object" || headers === null) return void 0;
45
+ const retryAfter = headers["retry-after"];
46
+ if (!retryAfter) return void 0;
47
+ const seconds = Number(retryAfter);
48
+ return Number.isFinite(seconds) ? seconds * 1e3 : void 0;
49
+ }
50
+ async function withRetry(fn, retry, cancellationToken, metricsSink = NOOP_METRICS, providerFamily = "custom") {
51
+ const { maxAttempts, baseDelayMs } = retry;
52
+ let lastError;
53
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
54
+ throwIfCancellationRequested(cancellationToken);
55
+ try {
56
+ return await fn();
57
+ } catch (error) {
58
+ const statusCode = typeof error === "object" && error !== null && "status" in error ? error.status : void 0;
59
+ if (statusCode !== 429 || attempt === maxAttempts) {
60
+ throw error;
61
+ }
62
+ const retryAfterMs = parseRetryAfterMs(error) ?? baseDelayMs * 2 ** (attempt - 1);
63
+ recordMetric(metricsSink, "kaji.provider.retries", 1, {
64
+ provider_family: providerFamily
65
+ });
66
+ lastError = error;
67
+ await cancellableDelay(retryAfterMs, cancellationToken);
68
+ }
69
+ }
70
+ throw lastError;
71
+ }
72
+ async function openStreamWithRetry(create, retry, cancellationToken, metricsSink = NOOP_METRICS, providerFamily = "custom") {
73
+ const opened = await withRetry(
74
+ async () => {
75
+ const stream = await create();
76
+ const iterator = stream[Symbol.asyncIterator]();
77
+ try {
78
+ return { iterator, first: await iterator.next() };
79
+ } catch (error) {
80
+ try {
81
+ await iterator.return?.();
82
+ } catch {
83
+ }
84
+ throw error;
85
+ }
86
+ },
87
+ retry,
88
+ cancellationToken,
89
+ metricsSink,
90
+ providerFamily
91
+ );
92
+ return new BufferedAsyncIterator(opened.iterator, opened.first);
93
+ }
94
+ var BufferedAsyncIterator = class {
95
+ constructor(inner, first) {
96
+ this.inner = inner;
97
+ this.first = first;
98
+ }
99
+ inner;
100
+ first;
101
+ firstPending = true;
102
+ closed = false;
103
+ closePromise;
104
+ async next() {
105
+ if (this.closed) return { value: void 0, done: true };
106
+ if (this.firstPending) {
107
+ this.firstPending = false;
108
+ if (this.first.done) this.markNaturallyClosed();
109
+ return this.first;
110
+ }
111
+ try {
112
+ const next = await this.inner.next();
113
+ if (next.done) this.markNaturallyClosed();
114
+ return next;
115
+ } catch (error) {
116
+ try {
117
+ await this.close();
118
+ } catch {
119
+ }
120
+ throw error;
121
+ }
122
+ }
123
+ async return(value) {
124
+ await this.close();
125
+ return { value, done: true };
126
+ }
127
+ async throw(error) {
128
+ await this.close();
129
+ throw error;
130
+ }
131
+ [Symbol.asyncIterator]() {
132
+ return this;
133
+ }
134
+ markNaturallyClosed() {
135
+ this.closed = true;
136
+ this.closePromise = Promise.resolve();
137
+ }
138
+ close() {
139
+ if (this.closePromise !== void 0) return this.closePromise;
140
+ this.closed = true;
141
+ this.firstPending = false;
142
+ try {
143
+ const result = this.inner.return?.();
144
+ this.closePromise = Promise.resolve(result).then(() => void 0);
145
+ } catch (error) {
146
+ this.closePromise = Promise.reject(error);
147
+ }
148
+ return this.closePromise;
149
+ }
150
+ };
151
+ async function cancellableDelay(delayMs, cancellationToken) {
152
+ throwIfCancellationRequested(cancellationToken);
153
+ if (cancellationToken === void 0) {
154
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
155
+ return;
156
+ }
157
+ const signal = cancellationToken?.signal;
158
+ if (signal === void 0) {
159
+ const deadline = globalThis.performance.now() + delayMs;
160
+ while (globalThis.performance.now() < deadline) {
161
+ throwIfCancellationRequested(cancellationToken);
162
+ await new Promise(
163
+ (resolve) => setTimeout(resolve, Math.min(10, deadline - globalThis.performance.now()))
164
+ );
165
+ }
166
+ throwIfCancellationRequested(cancellationToken);
167
+ return;
168
+ }
169
+ if (signal.aborted) throw new CancellationError();
170
+ await new Promise((resolve, reject) => {
171
+ const timer = setTimeout(() => {
172
+ signal.removeEventListener("abort", onAbort);
173
+ resolve();
174
+ }, delayMs);
175
+ const onAbort = () => {
176
+ clearTimeout(timer);
177
+ signal.removeEventListener("abort", onAbort);
178
+ reject(new CancellationError());
179
+ };
180
+ signal.addEventListener("abort", onAbort, { once: true });
181
+ });
182
+ }
183
+
184
+ // src/providers/errors.ts
185
+ var PROVIDER_ERROR_BRAND = /* @__PURE__ */ Symbol.for("kaji.ProviderError.v1");
186
+ var PROVIDER_CONFIG_ERROR_BRAND = /* @__PURE__ */ Symbol.for("kaji.ProviderConfigError.v1");
187
+ var PROVIDER_API_ERROR_BRAND = /* @__PURE__ */ Symbol.for("kaji.ProviderAPIError.v1");
188
+ var PROVIDER_CONNECTION_ERROR_BRAND = /* @__PURE__ */ Symbol.for("kaji.ProviderConnectionError.v1");
189
+ var PROVIDER_RATE_LIMITED_ERROR_BRAND = /* @__PURE__ */ Symbol.for("kaji.ProviderRateLimitedError.v1");
190
+ var PROVIDER_OUTPUT_LIMIT_ERROR_BRAND = /* @__PURE__ */ Symbol.for("kaji.ProviderOutputLimitError.v1");
191
+ function brand(value, key) {
192
+ Object.defineProperty(value, key, { value: true });
193
+ }
194
+ function hasBrand(value, key) {
195
+ return typeof value === "object" && value !== null && Reflect.get(value, key) === true;
196
+ }
197
+ var ProviderError = class extends Error {
198
+ service;
199
+ action;
200
+ statusCode;
201
+ static [Symbol.hasInstance](value) {
202
+ return hasBrand(value, PROVIDER_ERROR_BRAND);
203
+ }
204
+ constructor(message, options = {}) {
205
+ super(message);
206
+ brand(this, PROVIDER_ERROR_BRAND);
207
+ this.name = new.target.name;
208
+ this.service = options.service ?? "provider";
209
+ this.action = options.action ?? "request";
210
+ if (options.statusCode !== void 0) this.statusCode = options.statusCode;
211
+ }
212
+ };
213
+ var ProviderConfigError = class extends ProviderError {
214
+ static [Symbol.hasInstance](value) {
215
+ return hasBrand(value, PROVIDER_CONFIG_ERROR_BRAND);
216
+ }
217
+ constructor(message, options = {}) {
218
+ super(message, { ...options, action: "configure" });
219
+ brand(this, PROVIDER_CONFIG_ERROR_BRAND);
220
+ }
221
+ };
222
+ var ProviderAPIError = class extends ProviderError {
223
+ static [Symbol.hasInstance](value) {
224
+ return hasBrand(value, PROVIDER_API_ERROR_BRAND);
225
+ }
226
+ constructor(message, options = {}) {
227
+ super(message, { ...options, action: options.action ?? "api call" });
228
+ brand(this, PROVIDER_API_ERROR_BRAND);
229
+ }
230
+ };
231
+ var ProviderConnectionError = class extends ProviderError {
232
+ static [Symbol.hasInstance](value) {
233
+ return hasBrand(value, PROVIDER_CONNECTION_ERROR_BRAND);
234
+ }
235
+ constructor(message, options = {}) {
236
+ super(message, { ...options, action: options.action ?? "connect" });
237
+ brand(this, PROVIDER_CONNECTION_ERROR_BRAND);
238
+ }
239
+ };
240
+ var ProviderRateLimitedError = class extends ProviderError {
241
+ retryAfterMs;
242
+ attempts;
243
+ static [Symbol.hasInstance](value) {
244
+ return hasBrand(value, PROVIDER_RATE_LIMITED_ERROR_BRAND);
245
+ }
246
+ constructor(message, options) {
247
+ super(message, { ...options, action: "api call", statusCode: 429 });
248
+ brand(this, PROVIDER_RATE_LIMITED_ERROR_BRAND);
249
+ this.retryAfterMs = options.retryAfterMs;
250
+ this.attempts = options.attempts;
251
+ }
252
+ };
253
+ var ProviderOutputLimitError = class extends Error {
254
+ constructor(dimension, limit) {
255
+ if (!["text", "tool_arguments", "total_response", "tool_calls"].includes(dimension)) {
256
+ throw new TypeError("unknown provider output dimension");
257
+ }
258
+ if (!Number.isSafeInteger(limit) || limit < 1) {
259
+ throw new RangeError("provider output limit must be a positive safe integer");
260
+ }
261
+ const unit = dimension === "tool_calls" ? "calls" : "bytes";
262
+ super(`Provider output exceeded ${dimension} limit of ${limit} ${unit}`);
263
+ this.dimension = dimension;
264
+ this.limit = limit;
265
+ brand(this, PROVIDER_OUTPUT_LIMIT_ERROR_BRAND);
266
+ this.name = "ProviderOutputLimitError";
267
+ }
268
+ dimension;
269
+ limit;
270
+ code = "PROVIDER_OUTPUT_LIMIT";
271
+ phase = "provider_stream";
272
+ retryable = false;
273
+ outcome = "unknown";
274
+ static [Symbol.hasInstance](value) {
275
+ return hasBrand(value, PROVIDER_OUTPUT_LIMIT_ERROR_BRAND);
276
+ }
277
+ };
278
+ function errorStatusCode(error) {
279
+ if (typeof error !== "object" || error === null) return void 0;
280
+ const status = "status" in error ? error.status : void 0;
281
+ const statusCode = "statusCode" in error ? error.statusCode : void 0;
282
+ return typeof status === "number" ? status : typeof statusCode === "number" ? statusCode : void 0;
283
+ }
284
+ var NETWORK_ERROR_CODES = /* @__PURE__ */ new Set([
285
+ "EAI_AGAIN",
286
+ "ECONNABORTED",
287
+ "ECONNREFUSED",
288
+ "ECONNRESET",
289
+ "ENETUNREACH",
290
+ "ENOTFOUND",
291
+ "ETIMEDOUT",
292
+ "UND_ERR_CONNECT_TIMEOUT"
293
+ ]);
294
+ var NETWORK_ERROR_TYPE_NAMES = /* @__PURE__ */ new Set([
295
+ "APIConnectionError",
296
+ "APIConnectionTimeoutError",
297
+ "APITimeoutError"
298
+ ]);
299
+ function isNetworkError(error) {
300
+ if (typeof error !== "object" || error === null) return false;
301
+ const code = "code" in error ? error.code : void 0;
302
+ const constructorName = error.constructor?.name;
303
+ return typeof code === "string" && NETWORK_ERROR_CODES.has(code) || typeof constructorName === "string" && NETWORK_ERROR_TYPE_NAMES.has(constructorName);
304
+ }
305
+ function providerAPIErrorFromUnknown(service, error, action = "request") {
306
+ if (error instanceof ProviderConfigError) {
307
+ return new ProviderConfigError(`${service} configuration failed`, {
308
+ service,
309
+ statusCode: error.statusCode
310
+ });
311
+ }
312
+ if (error instanceof ProviderConnectionError) {
313
+ return new ProviderConnectionError(`${service} ${action} failed due to a network error`, {
314
+ service,
315
+ action,
316
+ statusCode: error.statusCode
317
+ });
318
+ }
319
+ if (error instanceof ProviderRateLimitedError) {
320
+ return new ProviderRateLimitedError(`${service} rate limit exceeded`, {
321
+ service,
322
+ retryAfterMs: error.retryAfterMs,
323
+ attempts: error.attempts
324
+ });
325
+ }
326
+ if (error instanceof ProviderError) {
327
+ return new ProviderAPIError(`${service} ${action} failed`, {
328
+ service,
329
+ action,
330
+ statusCode: error.statusCode
331
+ });
332
+ }
333
+ if (isNetworkError(error)) {
334
+ return new ProviderConnectionError(`${service} ${action} failed due to a network error`, {
335
+ service,
336
+ action
337
+ });
338
+ }
339
+ return new ProviderAPIError(`${service} ${action} failed`, {
340
+ service,
341
+ action,
342
+ statusCode: errorStatusCode(error)
343
+ });
344
+ }
345
+
346
+ // src/providers/args.ts
347
+ function jsonTypeName(value) {
348
+ if (value === null) return "null";
349
+ if (Array.isArray(value)) return "array";
350
+ return typeof value;
351
+ }
352
+ function isJsonObjectRecord(value) {
353
+ return typeof value === "object" && value !== null && !Array.isArray(value);
354
+ }
355
+ function parseToolArgsJSON(raw, providerLabel) {
356
+ if (raw === void 0 || raw === null || raw === "") return {};
357
+ try {
358
+ const parsed = JSON.parse(raw);
359
+ if (!isJsonObjectRecord(parsed)) {
360
+ return {
361
+ __parse_error: `${providerLabel} tool args must be a JSON object, got ${jsonTypeName(parsed)}`
362
+ };
363
+ }
364
+ return parsed;
365
+ } catch (err) {
366
+ const msg = err instanceof Error ? err.message : String(err);
367
+ return { __parse_error: `${providerLabel} tool args were not valid JSON: ${msg}` };
368
+ }
369
+ }
370
+
371
+ // src/providers/costs.ts
372
+ var COST_TABLE = {
373
+ "gpt-5.4-mini": { inputPer1M: 0.75, outputPer1M: 4.5 },
374
+ "claude-sonnet-4-6": { inputPer1M: 3, outputPer1M: 15 },
375
+ "gemini-2.5-flash": { inputPer1M: 0.3, outputPer1M: 2.5 },
376
+ "gemini-3.5-flash": { inputPer1M: 1.5, outputPer1M: 9 }
377
+ };
378
+ var SNAPSHOT_SUFFIX = /-(?:[0-9]{4}-[0-9]{2}-[0-9]{2}|[0-9]{8}|[0-9]{3})$/;
379
+ var MAX_SAFE_TOKEN_COUNT = 9007199254740991;
380
+ var TOKENS_PER_RATE_UNIT = 1000000n;
381
+ var USD_SCALE = 10000000000n;
382
+ var MAX_RATE_SIGNIFICANT_DIGITS = 32;
383
+ var MAX_RATE_FRACTIONAL_DIGITS = 32;
384
+ var MAX_RATE_ABSOLUTE_EXPONENT = 32n;
385
+ var MAX_RATE_TEXT_LENGTH = 65;
386
+ var DECIMAL_RATE = /^(0|[1-9][0-9]*)(?:\.([0-9]*[1-9]))?$/;
387
+ var SCIENTIFIC_RATE = /^([1-9])(?:\.([0-9]*[1-9]))?e(-?[1-9][0-9]*)$/;
388
+ function assertTokenCount(name, value) {
389
+ if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value)) {
390
+ throw new TypeError(`${name} must be an integer`);
391
+ }
392
+ if (value < 0 || value > MAX_SAFE_TOKEN_COUNT) {
393
+ throw new RangeError(`${name} must be between 0 and ${MAX_SAFE_TOKEN_COUNT}, inclusive`);
394
+ }
395
+ }
396
+ function boundedExponent(value) {
397
+ const negative = value.startsWith("-");
398
+ const digits = value.replace(/^[+-]/, "");
399
+ const normalized = digits.replace(/^0+/, "") || "0";
400
+ if (normalized.length > 2) throw new RangeError("cost rate exponent exceeds 32");
401
+ const magnitude = BigInt(normalized);
402
+ if (magnitude > MAX_RATE_ABSOLUTE_EXPONENT) {
403
+ throw new RangeError("cost rate exponent exceeds 32");
404
+ }
405
+ const bounded = Number(magnitude);
406
+ return negative ? -bounded : bounded;
407
+ }
408
+ function numericRateText(value) {
409
+ if (!Number.isFinite(value)) {
410
+ throw new TypeError("cost rate must be a finite number or canonical decimal string");
411
+ }
412
+ if (value < 0) throw new RangeError("cost rate must be non-negative");
413
+ if (value === 0) return "0";
414
+ const [rawMantissa, exponentText] = value.toString().toLowerCase().split("e");
415
+ const mantissa = rawMantissa.includes(".") ? rawMantissa.replace(/0+$/, "").replace(/\.$/, "") : rawMantissa;
416
+ if (exponentText === void 0) return mantissa;
417
+ const exponent = boundedExponent(exponentText);
418
+ return exponent === 0 ? mantissa : `${mantissa}e${exponent}`;
419
+ }
420
+ function decimalParts(value) {
421
+ if (typeof value !== "string" && typeof value !== "number") {
422
+ throw new TypeError("cost rate must be a finite number or canonical decimal string");
423
+ }
424
+ const source = typeof value === "number" ? numericRateText(value) : value;
425
+ if (source.length === 0 || source.length > MAX_RATE_TEXT_LENGTH) {
426
+ throw new RangeError("cost rate exceeds the canonical length bound");
427
+ }
428
+ let match = DECIMAL_RATE.exec(source);
429
+ let exponent = 0;
430
+ if (!match) {
431
+ match = SCIENTIFIC_RATE.exec(source);
432
+ if (!match) throw new TypeError("cost rate is not a canonical non-negative decimal");
433
+ exponent = boundedExponent(match[3]);
434
+ }
435
+ const fraction = match[2] ?? "";
436
+ const significant = `${match[1]}${fraction}`.replace(/^0+/, "") || "0";
437
+ if (significant.length > MAX_RATE_SIGNIFICANT_DIGITS) {
438
+ throw new RangeError("cost rate exceeds 32 significant digits");
439
+ }
440
+ if (fraction.length > MAX_RATE_FRACTIONAL_DIGITS) {
441
+ throw new RangeError("cost rate exceeds 32 fractional digits");
442
+ }
443
+ let coefficient = BigInt(`${match[1]}${fraction}`);
444
+ let scale = fraction.length - exponent;
445
+ if (scale < 0) {
446
+ coefficient *= 10n ** BigInt(-scale);
447
+ scale = 0;
448
+ }
449
+ return { coefficient, scale };
450
+ }
451
+ function canonicalUsd(units) {
452
+ const whole = units / USD_SCALE;
453
+ const fraction = (units % USD_SCALE).toString().padStart(10, "0").replace(/0+$/, "");
454
+ return fraction ? `${whole}.${fraction}` : whole.toString();
455
+ }
456
+ function calculateCostFromRatesUsdCanonical(inputTokens, outputTokens, inputPer1M, outputPer1M) {
457
+ assertTokenCount("inputTokens", inputTokens);
458
+ assertTokenCount("outputTokens", outputTokens);
459
+ const input = decimalParts(inputPer1M);
460
+ const output = decimalParts(outputPer1M);
461
+ const rateScale = Math.max(input.scale, output.scale);
462
+ const numerator = BigInt(inputTokens) * input.coefficient * 10n ** BigInt(rateScale - input.scale) + BigInt(outputTokens) * output.coefficient * 10n ** BigInt(rateScale - output.scale);
463
+ const denominator = TOKENS_PER_RATE_UNIT * 10n ** BigInt(rateScale);
464
+ const scaled = numerator * USD_SCALE;
465
+ let units = scaled / denominator;
466
+ const remainder = scaled % denominator;
467
+ const comparison = remainder * 2n - denominator;
468
+ if (comparison > 0n || comparison === 0n && units % 2n === 1n) units += 1n;
469
+ return canonicalUsd(units);
470
+ }
471
+ function lookupCost(model) {
472
+ if (model in COST_TABLE) return COST_TABLE[model];
473
+ const base = model.replace(SNAPSHOT_SUFFIX, "");
474
+ return base === model ? void 0 : COST_TABLE[base];
475
+ }
476
+ function calculateCostUsdCanonical(model, inputTokens, outputTokens) {
477
+ assertTokenCount("inputTokens", inputTokens);
478
+ assertTokenCount("outputTokens", outputTokens);
479
+ const entry = lookupCost(model);
480
+ if (!entry) return "0";
481
+ return calculateCostFromRatesUsdCanonical(
482
+ inputTokens,
483
+ outputTokens,
484
+ entry.inputPer1M,
485
+ entry.outputPer1M
486
+ );
487
+ }
488
+ function calculateCostUsd(model, inputTokens, outputTokens) {
489
+ return Number(calculateCostUsdCanonical(model, inputTokens, outputTokens));
490
+ }
491
+
492
+ // src/providers/response-budget.ts
493
+ function scanUtf8Scalars(fragment, pendingHighSurrogate) {
494
+ if (typeof fragment !== "string")
495
+ throw new TypeError("provider output fragments must be strings");
496
+ const input = `${pendingHighSurrogate ?? ""}${fragment}`;
497
+ const scalars = [];
498
+ let bytes = 0;
499
+ let pending;
500
+ for (let index = 0; index < input.length; index += 1) {
501
+ const unit = input.charCodeAt(index);
502
+ if (unit >= 55296 && unit <= 56319) {
503
+ if (index + 1 >= input.length) {
504
+ pending = input[index];
505
+ break;
506
+ }
507
+ const low = input.charCodeAt(index + 1);
508
+ if (!(low >= 56320 && low <= 57343)) {
509
+ throw new TypeError("provider output contains an unpaired Unicode surrogate");
510
+ }
511
+ scalars.push({ text: input.slice(index, index + 2), bytes: 4 });
512
+ bytes += 4;
513
+ index += 1;
514
+ continue;
515
+ }
516
+ if (unit >= 56320 && unit <= 57343) {
517
+ throw new TypeError("provider output contains an unpaired Unicode surrogate");
518
+ }
519
+ const scalarBytes = unit <= 127 ? 1 : unit <= 2047 ? 2 : 3;
520
+ scalars.push({ text: input[index], bytes: scalarBytes });
521
+ bytes += scalarBytes;
522
+ }
523
+ return pending === void 0 ? { scalars, bytes } : { scalars, bytes, pendingHighSurrogate: pending };
524
+ }
525
+ function utf8ByteLength(value) {
526
+ const scan = scanUtf8Scalars(value);
527
+ if (scan.pendingHighSurrogate !== void 0) {
528
+ throw new TypeError("provider output contains an unpaired Unicode surrogate");
529
+ }
530
+ return scan.bytes;
531
+ }
532
+ var LinearStringParts = class {
533
+ parts = [];
534
+ _fragmentCount = 0;
535
+ _joinOperations = 0;
536
+ get fragmentCount() {
537
+ return this._fragmentCount;
538
+ }
539
+ get joinOperations() {
540
+ return this._joinOperations;
541
+ }
542
+ append(fragment) {
543
+ if (!fragment) return;
544
+ this.parts.push(fragment);
545
+ this._fragmentCount += 1;
546
+ }
547
+ join() {
548
+ this._joinOperations += 1;
549
+ return this.parts.join("");
550
+ }
551
+ };
552
+ var ProviderResponseBudget = class {
553
+ limits;
554
+ textBytes = 0;
555
+ totalBytes = 0;
556
+ callCount = 0;
557
+ rawFragments = 0;
558
+ argumentJoins = 0;
559
+ textPendingHighSurrogate;
560
+ rawToolCalls = /* @__PURE__ */ new Map();
561
+ constructor(limits) {
562
+ this.limits = resolveProviderResponseLimits(limits);
563
+ }
564
+ get diagnostics() {
565
+ return Object.freeze({
566
+ textBytes: this.textBytes,
567
+ totalResponseBytes: this.totalBytes,
568
+ toolCalls: this.callCount,
569
+ rawFragments: this.rawFragments,
570
+ toolArgumentJoinOperations: this.argumentJoins
571
+ });
572
+ }
573
+ get providerDiagnostics() {
574
+ return Object.freeze({
575
+ rawFragments: this.rawFragments,
576
+ toolArgumentJoinOperations: this.argumentJoins
577
+ });
578
+ }
579
+ acceptRaw(input) {
580
+ const text = input.text ?? "";
581
+ const textScan = scanUtf8Scalars(text, this.textPendingHighSurrogate);
582
+ const nextTextBytes = this.textBytes + textScan.bytes;
583
+ if (nextTextBytes > this.limits.textMaxBytes) {
584
+ throw new ProviderOutputLimitError("text", this.limits.textMaxBytes);
585
+ }
586
+ const nextStates = new Map([...this.rawToolCalls].map(([key, state]) => [key, { ...state }]));
587
+ let addedTotal = textScan.bytes;
588
+ let addedCalls = 0;
589
+ let addedFragments = text ? 1 : 0;
590
+ for (const fragment of input.toolFragments ?? []) {
591
+ let state = nextStates.get(fragment.key);
592
+ if (fragment.startsCall) {
593
+ if (state !== void 0) throw new TypeError("provider tool call started more than once");
594
+ state = { argumentBytes: 0 };
595
+ nextStates.set(fragment.key, state);
596
+ addedCalls += 1;
597
+ } else if (state === void 0) {
598
+ throw new TypeError("provider tool fragment must start a call before appending");
599
+ }
600
+ const id = scanUtf8Scalars(fragment.idFragment ?? "", state.idPending);
601
+ const name = scanUtf8Scalars(fragment.nameFragment ?? "", state.namePending);
602
+ const args = scanUtf8Scalars(fragment.argumentsFragment ?? "", state.argumentsPending);
603
+ state.idPending = id.pendingHighSurrogate;
604
+ state.namePending = name.pendingHighSurrogate;
605
+ state.argumentsPending = args.pendingHighSurrogate;
606
+ state.argumentBytes += args.bytes;
607
+ if (state.argumentBytes > this.limits.toolArgumentsMaxBytes) {
608
+ throw new ProviderOutputLimitError("tool_arguments", this.limits.toolArgumentsMaxBytes);
609
+ }
610
+ addedTotal += id.bytes + name.bytes + args.bytes;
611
+ addedFragments += Number(Boolean(fragment.idFragment));
612
+ addedFragments += Number(Boolean(fragment.nameFragment));
613
+ addedFragments += Number(Boolean(fragment.argumentsFragment));
614
+ }
615
+ const nextCalls = this.callCount + addedCalls;
616
+ if (nextCalls > this.limits.toolCallsMax) {
617
+ throw new ProviderOutputLimitError("tool_calls", this.limits.toolCallsMax);
618
+ }
619
+ const nextTotal = this.totalBytes + addedTotal;
620
+ if (nextTotal > this.limits.responseMaxBytes) {
621
+ throw new ProviderOutputLimitError("total_response", this.limits.responseMaxBytes);
622
+ }
623
+ this.textBytes = nextTextBytes;
624
+ this.totalBytes = nextTotal;
625
+ this.callCount = nextCalls;
626
+ this.rawFragments += addedFragments;
627
+ this.textPendingHighSurrogate = textScan.pendingHighSurrogate;
628
+ this.rawToolCalls = nextStates;
629
+ }
630
+ acceptNormalized(delta, toolCalls) {
631
+ const textScan = scanUtf8Scalars(delta, this.textPendingHighSurrogate);
632
+ const nextTextBytes = this.textBytes + textScan.bytes;
633
+ if (nextTextBytes > this.limits.textMaxBytes) {
634
+ throw new ProviderOutputLimitError("text", this.limits.textMaxBytes);
635
+ }
636
+ let addedTotal = textScan.bytes;
637
+ const serializedCalls = [];
638
+ for (const call of toolCalls) {
639
+ const descriptors = Object.getOwnPropertyDescriptors(call);
640
+ const id = dataProperty(descriptors, "id");
641
+ const name = dataProperty(descriptors, "name");
642
+ const args = dataProperty(descriptors, "args");
643
+ if (typeof id !== "string" || typeof name !== "string") {
644
+ throw new TypeError("provider tool call id and name must be strings");
645
+ }
646
+ const encodedArguments = canonicalJsonValue(args ?? {}, "tool arguments");
647
+ const argumentBytes = utf8ByteLength(encodedArguments);
648
+ if (argumentBytes > this.limits.toolArgumentsMaxBytes) {
649
+ throw new ProviderOutputLimitError("tool_arguments", this.limits.toolArgumentsMaxBytes);
650
+ }
651
+ addedTotal += utf8ByteLength(id) + utf8ByteLength(name) + argumentBytes;
652
+ serializedCalls.push({ id, name, encodedArguments });
653
+ }
654
+ const nextCalls = this.callCount + serializedCalls.length;
655
+ if (nextCalls > this.limits.toolCallsMax) {
656
+ throw new ProviderOutputLimitError("tool_calls", this.limits.toolCallsMax);
657
+ }
658
+ const nextTotal = this.totalBytes + addedTotal;
659
+ if (nextTotal > this.limits.responseMaxBytes) {
660
+ throw new ProviderOutputLimitError("total_response", this.limits.responseMaxBytes);
661
+ }
662
+ const detached = serializedCalls.map(
663
+ ({ id, name, encodedArguments }) => Object.freeze({
664
+ id,
665
+ name,
666
+ args: cloneAndFreezeJson(JSON.parse(encodedArguments))
667
+ })
668
+ );
669
+ this.textBytes = nextTextBytes;
670
+ this.totalBytes = nextTotal;
671
+ this.callCount = nextCalls;
672
+ this.textPendingHighSurrogate = textScan.pendingHighSurrogate;
673
+ return Object.freeze({ delta, toolCalls: Object.freeze(detached) });
674
+ }
675
+ finishRawTool(key) {
676
+ const state = this.rawToolCalls.get(key);
677
+ if (state === void 0) throw new TypeError("unknown provider tool call");
678
+ assertNoPendingSurrogate(state.idPending);
679
+ assertNoPendingSurrogate(state.namePending);
680
+ assertNoPendingSurrogate(state.argumentsPending);
681
+ }
682
+ finish() {
683
+ assertNoPendingSurrogate(this.textPendingHighSurrogate);
684
+ for (const key of this.rawToolCalls.keys()) this.finishRawTool(key);
685
+ }
686
+ recordToolArgumentJoin() {
687
+ this.argumentJoins += 1;
688
+ }
689
+ };
690
+ function dataProperty(descriptors, key) {
691
+ const descriptor = descriptors[key];
692
+ if (descriptor === void 0) return void 0;
693
+ if (!descriptor.enumerable || !("value" in descriptor)) {
694
+ throw new TypeError("provider tool calls must contain enumerable data properties");
695
+ }
696
+ return descriptor.value;
697
+ }
698
+ function assertNoPendingSurrogate(pending) {
699
+ if (pending !== void 0) {
700
+ throw new TypeError("provider output contains an unpaired Unicode surrogate");
701
+ }
702
+ }
703
+ async function closeProviderStream(stream) {
704
+ if (typeof stream !== "object" || stream === null) return;
705
+ const candidate = stream;
706
+ const close = candidate.controller?.abort?.bind(candidate.controller) ?? candidate.abort?.bind(candidate) ?? candidate.return?.bind(candidate) ?? candidate.close?.bind(candidate);
707
+ if (close === void 0) return;
708
+ try {
709
+ await close();
710
+ } catch {
711
+ }
712
+ }
713
+
714
+ export { LinearStringParts, ProviderConfigError, ProviderError, ProviderOutputLimitError, ProviderResponseBudget, calculateCostUsd, closeProviderStream, getProviderResponseDiagnostics, lookupCost, openStreamWithRetry, parseToolArgsJSON, providerAPIErrorFromUnknown, throwIfCancellationRequested, withRetry };
715
+ //# sourceMappingURL=chunk-TM7ZGOJX.js.map
716
+ //# sourceMappingURL=chunk-TM7ZGOJX.js.map