runcycles 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ [![npm](https://img.shields.io/npm/v/runcycles)](https://www.npmjs.com/package/runcycles)
2
+ [![CI](https://github.com/runcycles/cycles-client-typescript/actions/workflows/ci.yml/badge.svg)](https://github.com/runcycles/cycles-client-typescript/actions)
3
+ [![License](https://img.shields.io/badge/license-Apache%202.0-blue)](LICENSE)
4
+
1
5
  # Cycles TypeScript Client
2
6
 
3
7
  TypeScript client for the [Cycles](https://runcycles.io) budget-management protocol — govern spend on AI calls, API usage, and any metered resource.
@@ -58,8 +62,35 @@ const callLlm = withCycles(
58
62
  const result = await callLlm("Hello", 100);
59
63
  ```
60
64
 
65
+ > **Need an API key?** API keys are created via the Cycles Admin Server (port 7979). See the [deployment guide](https://runcycles.io/quickstart/deploying-the-full-cycles-stack#step-3-create-an-api-key) to create one, or run:
66
+ > ```bash
67
+ > curl -s -X POST http://localhost:7979/v1/admin/api-keys \
68
+ > -H "Content-Type: application/json" \
69
+ > -H "X-Admin-API-Key: admin-bootstrap-key" \
70
+ > -d '{"tenant_id":"acme-corp","name":"dev-key","permissions":["reservations:create","reservations:commit","reservations:release","reservations:extend","reservations:list","balances:read","decide","events:create"]}' | jq -r '.key_secret'
71
+ > ```
72
+ > The key (e.g. `cyc_live_abc123...`) is shown only once — save it immediately. For key rotation and lifecycle details, see [API Key Management](https://runcycles.io/how-to/api-key-management-in-cycles).
73
+
61
74
  **What happens:** `withCycles` reserves budget before calling your function, runs it inside an async context (so `getCyclesContext()` works), commits the actual cost on success, or releases the reservation on failure. A background heartbeat keeps the reservation alive.
62
75
 
76
+ ### Budget lifecycle
77
+
78
+ | Scenario | Outcome | Detail |
79
+ |---|---|---|
80
+ | Reservation denied | **Neither** | `BudgetExceededError`, `OverdraftLimitExceededError`, or `DebtOutstandingError` thrown; function never executes |
81
+ | `dryRun: true`, any decision | **Neither** | Returns `DryRunResult` or throws; no real reservation created |
82
+ | Function returns successfully | **Commit** | Actual amount charged; unused remainder auto-released |
83
+ | Function throws any error | **Release** | Full reserved amount returned to budget; error re-thrown |
84
+ | Commit fails (5xx / network) | **Retry** | Exponential backoff with configurable attempts |
85
+ | Commit fails (non-retryable 4xx) | **Release** | Reservation released after non-retryable client error |
86
+ | Commit gets RESERVATION_EXPIRED | **Neither** | Server already reclaimed budget on TTL expiry |
87
+ | Commit gets RESERVATION_FINALIZED | **Neither** | Already committed or released (idempotent replay) |
88
+ | Commit gets IDEMPOTENCY_MISMATCH | **Neither** | Previous commit already processed; no release attempted |
89
+
90
+ **Streaming (`reserveForStream`):** Call `handle.commit(actual)` on success or `handle.release(reason)` on failure. If neither is called, the server reclaims the budget when the reservation TTL expires.
91
+
92
+ All thrown errors from the guarded function trigger release. See [How Reserve-Commit Works](https://runcycles.io/protocol/how-reserve-commit-works-in-cycles) for the full protocol-level explanation.
93
+
63
94
  ### 2. Streaming adapter
64
95
 
65
96
  For LLM streaming where usage is only known after the stream finishes:
@@ -234,7 +265,7 @@ const config = CyclesConfig.fromEnv();
234
265
  | Variable | Required | Description |
235
266
  |----------|----------|-------------|
236
267
  | `CYCLES_BASE_URL` | Yes | Cycles server URL |
237
- | `CYCLES_API_KEY` | Yes | API key for authentication |
268
+ | `CYCLES_API_KEY` | Yes | API key for authentication (see [how to create one](https://runcycles.io/quickstart/deploying-the-full-cycles-stack#step-3-create-an-api-key)) |
238
269
  | `CYCLES_TENANT` | No | Default tenant |
239
270
  | `CYCLES_WORKSPACE` | No | Default workspace |
240
271
  | `CYCLES_APP` | No | Default app |
@@ -294,7 +325,7 @@ interface WithCyclesConfig {
294
325
  // Reservation settings
295
326
  ttlMs?: number; // Time-to-live in ms (default: 60000, range: 1000–86400000)
296
327
  gracePeriodMs?: number; // Grace period in ms (range: 0–60000)
297
- overagePolicy?: string; // "REJECT" (default), "ALLOW_IF_AVAILABLE", "ALLOW_WITH_OVERDRAFT"
328
+ overagePolicy?: string; // "ALLOW_IF_AVAILABLE" (default), "REJECT", "ALLOW_WITH_OVERDRAFT"
298
329
  dryRun?: boolean; // Shadow mode — evaluates budget without executing
299
330
 
300
331
  // Subject fields (override config defaults)
@@ -786,6 +817,29 @@ ErrorCode.INTERNAL_ERROR
786
817
  ErrorCode.UNKNOWN
787
818
  ```
788
819
 
820
+ ## Nested `withCycles` Calls
821
+
822
+ Calling a `withCycles`-wrapped function from inside another `withCycles`-wrapped function is allowed — it will not throw an error. However, each wrapper creates an **independent reservation** that deducts budget separately:
823
+
824
+ ```typescript
825
+ const inner = withCycles({ estimate: 100, actionName: "inner" }, async () => "done");
826
+ const outer = withCycles({ estimate: 500, actionName: "outer" }, async () => {
827
+ return await inner(); // creates a SECOND reservation — 600 total deducted, not 500
828
+ });
829
+ ```
830
+
831
+ This means nested guards **double-count budget**. The outer reservation already covers the full estimated cost of the operation, so an inner reservation deducts additional budget from the same pool.
832
+
833
+ **Recommended pattern:** Place `withCycles` at the outermost entry point only. Inner functions should be plain async functions without their own guard:
834
+
835
+ ```typescript
836
+ const inner = async () => "done"; // no withCycles — called within a guarded operation
837
+
838
+ const outer = withCycles({ estimate: 500, actionName: "outer" }, async () => {
839
+ return await inner(); // single reservation — 500 total
840
+ });
841
+ ```
842
+
789
843
  ## Examples
790
844
 
791
845
  See the [`examples/`](./examples/) directory:
@@ -815,6 +869,13 @@ See the [`examples/`](./examples/) directory:
815
869
  - **Dual ESM/CJS**: Works with both module systems
816
870
  - **Input validation**: Client-side validation of TTL, amounts, subject fields, and more
817
871
 
872
+ ## Documentation
873
+
874
+ - [Cycles Documentation](https://runcycles.io) — full docs site
875
+ - [TypeScript Quickstart](https://runcycles.io/quickstart/getting-started-with-the-typescript-client) — getting started guide
876
+ - [TypeScript Client Configuration Reference](https://runcycles.io/configuration/typescript-client-configuration-reference) — all configuration options
877
+ - [Error Handling Patterns in TypeScript](https://runcycles.io/how-to/error-handling-patterns-in-typescript) — handling budget errors
878
+
818
879
  ## License
819
880
 
820
881
  Apache-2.0
package/dist/index.cjs CHANGED
@@ -28,6 +28,7 @@ __export(index_exports, {
28
28
  CyclesError: () => CyclesError,
29
29
  CyclesProtocolError: () => CyclesProtocolError,
30
30
  CyclesResponse: () => CyclesResponse,
31
+ CyclesTransportError: () => CyclesTransportError,
31
32
  DebtOutstandingError: () => DebtOutstandingError,
32
33
  Decision: () => Decision,
33
34
  ErrorCode: () => ErrorCode,
@@ -722,6 +723,14 @@ var ReservationFinalizedError = class extends CyclesProtocolError {
722
723
  this.name = "ReservationFinalizedError";
723
724
  }
724
725
  };
726
+ var CyclesTransportError = class extends CyclesError {
727
+ cause;
728
+ constructor(message, options) {
729
+ super(message);
730
+ this.name = "CyclesTransportError";
731
+ this.cause = options?.cause;
732
+ }
733
+ };
725
734
 
726
735
  // src/errors.ts
727
736
  function buildProtocolException(prefix, response) {
@@ -826,12 +835,15 @@ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
826
835
  ErrorCode2["FORBIDDEN"] = "FORBIDDEN";
827
836
  ErrorCode2["NOT_FOUND"] = "NOT_FOUND";
828
837
  ErrorCode2["BUDGET_EXCEEDED"] = "BUDGET_EXCEEDED";
838
+ ErrorCode2["BUDGET_FROZEN"] = "BUDGET_FROZEN";
839
+ ErrorCode2["BUDGET_CLOSED"] = "BUDGET_CLOSED";
829
840
  ErrorCode2["RESERVATION_EXPIRED"] = "RESERVATION_EXPIRED";
830
841
  ErrorCode2["RESERVATION_FINALIZED"] = "RESERVATION_FINALIZED";
831
842
  ErrorCode2["IDEMPOTENCY_MISMATCH"] = "IDEMPOTENCY_MISMATCH";
832
843
  ErrorCode2["UNIT_MISMATCH"] = "UNIT_MISMATCH";
833
844
  ErrorCode2["OVERDRAFT_LIMIT_EXCEEDED"] = "OVERDRAFT_LIMIT_EXCEEDED";
834
845
  ErrorCode2["DEBT_OUTSTANDING"] = "DEBT_OUTSTANDING";
846
+ ErrorCode2["MAX_EXTENSIONS_EXCEEDED"] = "MAX_EXTENSIONS_EXCEEDED";
835
847
  ErrorCode2["INTERNAL_ERROR"] = "INTERNAL_ERROR";
836
848
  ErrorCode2["UNKNOWN"] = "UNKNOWN";
837
849
  return ErrorCode2;
@@ -953,7 +965,7 @@ function buildReservationBody(cfg, estimate, defaultSubject) {
953
965
  action,
954
966
  estimate: { unit, amount: estimate },
955
967
  ttl_ms: ttlMs,
956
- overage_policy: cfg.overagePolicy ?? "REJECT"
968
+ overage_policy: cfg.overagePolicy ?? "ALLOW_IF_AVAILABLE"
957
969
  };
958
970
  validateGracePeriodMs(cfg.gracePeriodMs);
959
971
  if (cfg.gracePeriodMs !== void 0) {
@@ -1275,7 +1287,7 @@ async function reserveForStream(options) {
1275
1287
  actionTags,
1276
1288
  ttlMs = DEFAULT_TTL_MS,
1277
1289
  gracePeriodMs,
1278
- overagePolicy = "REJECT",
1290
+ overagePolicy = "ALLOW_IF_AVAILABLE",
1279
1291
  dimensions
1280
1292
  } = options;
1281
1293
  validateNonNegative(estimate, "estimate");
@@ -1414,6 +1426,7 @@ async function reserveForStream(options) {
1414
1426
  CyclesError,
1415
1427
  CyclesProtocolError,
1416
1428
  CyclesResponse,
1429
+ CyclesTransportError,
1417
1430
  DebtOutstandingError,
1418
1431
  Decision,
1419
1432
  ErrorCode,
package/dist/index.d.cts CHANGED
@@ -76,12 +76,15 @@ declare enum ErrorCode {
76
76
  FORBIDDEN = "FORBIDDEN",
77
77
  NOT_FOUND = "NOT_FOUND",
78
78
  BUDGET_EXCEEDED = "BUDGET_EXCEEDED",
79
+ BUDGET_FROZEN = "BUDGET_FROZEN",
80
+ BUDGET_CLOSED = "BUDGET_CLOSED",
79
81
  RESERVATION_EXPIRED = "RESERVATION_EXPIRED",
80
82
  RESERVATION_FINALIZED = "RESERVATION_FINALIZED",
81
83
  IDEMPOTENCY_MISMATCH = "IDEMPOTENCY_MISMATCH",
82
84
  UNIT_MISMATCH = "UNIT_MISMATCH",
83
85
  OVERDRAFT_LIMIT_EXCEEDED = "OVERDRAFT_LIMIT_EXCEEDED",
84
86
  DEBT_OUTSTANDING = "DEBT_OUTSTANDING",
87
+ MAX_EXTENSIONS_EXCEEDED = "MAX_EXTENSIONS_EXCEEDED",
85
88
  INTERNAL_ERROR = "INTERNAL_ERROR",
86
89
  UNKNOWN = "UNKNOWN"
87
90
  }
@@ -213,6 +216,7 @@ interface DecisionResponse {
213
216
  interface EventCreateResponse {
214
217
  status: EventStatus;
215
218
  eventId: string;
219
+ charged?: Amount;
216
220
  balances?: Balance[];
217
221
  }
218
222
  interface DryRunResult {
@@ -335,9 +339,9 @@ declare class CyclesClient {
335
339
 
336
340
  /** Lifecycle orchestration: reserve -> execute -> commit/release. */
337
341
 
338
- interface WithCyclesConfig {
339
- estimate: number | ((...args: unknown[]) => number);
340
- actual?: number | ((result: unknown) => number);
342
+ interface WithCyclesConfig<TArgs extends unknown[] = unknown[], TResult = unknown> {
343
+ estimate: number | ((...args: TArgs) => number);
344
+ actual?: number | ((result: TResult) => number);
341
345
  actionKind?: string;
342
346
  actionName?: string;
343
347
  actionTags?: string[];
@@ -360,7 +364,7 @@ interface WithCyclesConfig {
360
364
 
361
365
  declare function setDefaultClient(client: CyclesClient): void;
362
366
  declare function setDefaultConfig(config: CyclesConfig): void;
363
- declare function withCycles<TArgs extends unknown[], TResult>(options: WithCyclesConfig & {
367
+ declare function withCycles<TArgs extends unknown[], TResult>(options: WithCyclesConfig<TArgs, TResult> & {
364
368
  client?: CyclesClient;
365
369
  }, fn: (...args: TArgs) => Promise<TResult>): (...args: TArgs) => Promise<TResult>;
366
370
 
@@ -508,6 +512,12 @@ declare class ReservationExpiredError extends CyclesProtocolError {
508
512
  declare class ReservationFinalizedError extends CyclesProtocolError {
509
513
  constructor(message: string, options?: ConstructorParameters<typeof CyclesProtocolError>[1]);
510
514
  }
515
+ declare class CyclesTransportError extends CyclesError {
516
+ readonly cause: Error | undefined;
517
+ constructor(message: string, options?: {
518
+ cause?: Error;
519
+ });
520
+ }
511
521
 
512
522
  /**
513
523
  * Explicit request/response mappers between camelCase TypeScript interfaces
@@ -543,4 +553,4 @@ declare function reservationExtendRequestToWire(req: ReservationExtendRequest):
543
553
  declare function decisionRequestToWire(req: DecisionRequest): Record<string, unknown>;
544
554
  declare function eventCreateRequestToWire(req: EventCreateRequest): Record<string, unknown>;
545
555
 
546
- export { type Action, type Amount, type Balance, type BalanceResponse, BudgetExceededError, type Caps, CommitOveragePolicy, type CommitRequest, type CommitResponse, CommitStatus, CyclesClient, CyclesConfig, type CyclesContext, CyclesError, type CyclesMetrics, CyclesProtocolError, CyclesResponse, DebtOutstandingError, Decision, type DecisionRequest, type DecisionResponse, type DryRunResult, ErrorCode, type ErrorResponse, type EventCreateRequest, type EventCreateResponse, EventStatus, ExtendStatus, OverdraftLimitExceededError, type ReleaseRequest, type ReleaseResponse, ReleaseStatus, type ReservationCreateRequest, type ReservationCreateResponse, type ReservationDetail, ReservationExpiredError, type ReservationExtendRequest, type ReservationExtendResponse, ReservationFinalizedError, type ReservationListResponse, ReservationStatus, type ReservationSummary, type SignedAmount, type StreamReservation, type StreamReservationOptions, type Subject, Unit, type WithCyclesConfig, balanceResponseFromWire, capsFromWire, commitRequestToWire, commitResponseFromWire, decisionRequestToWire, decisionResponseFromWire, errorCodeFromString, errorResponseFromWire, eventCreateRequestToWire, eventCreateResponseFromWire, getCyclesContext, isAllowed, isDenied, isMetricsEmpty, isRetryableErrorCode, isToolAllowed, metricsToWire, releaseRequestToWire, releaseResponseFromWire, reservationCreateRequestToWire, reservationCreateResponseFromWire, reservationDetailFromWire, reservationExtendRequestToWire, reservationExtendResponseFromWire, reservationListResponseFromWire, reservationSummaryFromWire, reserveForStream, setDefaultClient, setDefaultConfig, withCycles };
556
+ export { type Action, type Amount, type Balance, type BalanceResponse, BudgetExceededError, type Caps, CommitOveragePolicy, type CommitRequest, type CommitResponse, CommitStatus, CyclesClient, CyclesConfig, type CyclesContext, CyclesError, type CyclesMetrics, CyclesProtocolError, CyclesResponse, CyclesTransportError, DebtOutstandingError, Decision, type DecisionRequest, type DecisionResponse, type DryRunResult, ErrorCode, type ErrorResponse, type EventCreateRequest, type EventCreateResponse, EventStatus, ExtendStatus, OverdraftLimitExceededError, type ReleaseRequest, type ReleaseResponse, ReleaseStatus, type ReservationCreateRequest, type ReservationCreateResponse, type ReservationDetail, ReservationExpiredError, type ReservationExtendRequest, type ReservationExtendResponse, ReservationFinalizedError, type ReservationListResponse, ReservationStatus, type ReservationSummary, type SignedAmount, type StreamReservation, type StreamReservationOptions, type Subject, Unit, type WithCyclesConfig, balanceResponseFromWire, capsFromWire, commitRequestToWire, commitResponseFromWire, decisionRequestToWire, decisionResponseFromWire, errorCodeFromString, errorResponseFromWire, eventCreateRequestToWire, eventCreateResponseFromWire, getCyclesContext, isAllowed, isDenied, isMetricsEmpty, isRetryableErrorCode, isToolAllowed, metricsToWire, releaseRequestToWire, releaseResponseFromWire, reservationCreateRequestToWire, reservationCreateResponseFromWire, reservationDetailFromWire, reservationExtendRequestToWire, reservationExtendResponseFromWire, reservationListResponseFromWire, reservationSummaryFromWire, reserveForStream, setDefaultClient, setDefaultConfig, withCycles };
package/dist/index.d.ts CHANGED
@@ -76,12 +76,15 @@ declare enum ErrorCode {
76
76
  FORBIDDEN = "FORBIDDEN",
77
77
  NOT_FOUND = "NOT_FOUND",
78
78
  BUDGET_EXCEEDED = "BUDGET_EXCEEDED",
79
+ BUDGET_FROZEN = "BUDGET_FROZEN",
80
+ BUDGET_CLOSED = "BUDGET_CLOSED",
79
81
  RESERVATION_EXPIRED = "RESERVATION_EXPIRED",
80
82
  RESERVATION_FINALIZED = "RESERVATION_FINALIZED",
81
83
  IDEMPOTENCY_MISMATCH = "IDEMPOTENCY_MISMATCH",
82
84
  UNIT_MISMATCH = "UNIT_MISMATCH",
83
85
  OVERDRAFT_LIMIT_EXCEEDED = "OVERDRAFT_LIMIT_EXCEEDED",
84
86
  DEBT_OUTSTANDING = "DEBT_OUTSTANDING",
87
+ MAX_EXTENSIONS_EXCEEDED = "MAX_EXTENSIONS_EXCEEDED",
85
88
  INTERNAL_ERROR = "INTERNAL_ERROR",
86
89
  UNKNOWN = "UNKNOWN"
87
90
  }
@@ -213,6 +216,7 @@ interface DecisionResponse {
213
216
  interface EventCreateResponse {
214
217
  status: EventStatus;
215
218
  eventId: string;
219
+ charged?: Amount;
216
220
  balances?: Balance[];
217
221
  }
218
222
  interface DryRunResult {
@@ -335,9 +339,9 @@ declare class CyclesClient {
335
339
 
336
340
  /** Lifecycle orchestration: reserve -> execute -> commit/release. */
337
341
 
338
- interface WithCyclesConfig {
339
- estimate: number | ((...args: unknown[]) => number);
340
- actual?: number | ((result: unknown) => number);
342
+ interface WithCyclesConfig<TArgs extends unknown[] = unknown[], TResult = unknown> {
343
+ estimate: number | ((...args: TArgs) => number);
344
+ actual?: number | ((result: TResult) => number);
341
345
  actionKind?: string;
342
346
  actionName?: string;
343
347
  actionTags?: string[];
@@ -360,7 +364,7 @@ interface WithCyclesConfig {
360
364
 
361
365
  declare function setDefaultClient(client: CyclesClient): void;
362
366
  declare function setDefaultConfig(config: CyclesConfig): void;
363
- declare function withCycles<TArgs extends unknown[], TResult>(options: WithCyclesConfig & {
367
+ declare function withCycles<TArgs extends unknown[], TResult>(options: WithCyclesConfig<TArgs, TResult> & {
364
368
  client?: CyclesClient;
365
369
  }, fn: (...args: TArgs) => Promise<TResult>): (...args: TArgs) => Promise<TResult>;
366
370
 
@@ -508,6 +512,12 @@ declare class ReservationExpiredError extends CyclesProtocolError {
508
512
  declare class ReservationFinalizedError extends CyclesProtocolError {
509
513
  constructor(message: string, options?: ConstructorParameters<typeof CyclesProtocolError>[1]);
510
514
  }
515
+ declare class CyclesTransportError extends CyclesError {
516
+ readonly cause: Error | undefined;
517
+ constructor(message: string, options?: {
518
+ cause?: Error;
519
+ });
520
+ }
511
521
 
512
522
  /**
513
523
  * Explicit request/response mappers between camelCase TypeScript interfaces
@@ -543,4 +553,4 @@ declare function reservationExtendRequestToWire(req: ReservationExtendRequest):
543
553
  declare function decisionRequestToWire(req: DecisionRequest): Record<string, unknown>;
544
554
  declare function eventCreateRequestToWire(req: EventCreateRequest): Record<string, unknown>;
545
555
 
546
- export { type Action, type Amount, type Balance, type BalanceResponse, BudgetExceededError, type Caps, CommitOveragePolicy, type CommitRequest, type CommitResponse, CommitStatus, CyclesClient, CyclesConfig, type CyclesContext, CyclesError, type CyclesMetrics, CyclesProtocolError, CyclesResponse, DebtOutstandingError, Decision, type DecisionRequest, type DecisionResponse, type DryRunResult, ErrorCode, type ErrorResponse, type EventCreateRequest, type EventCreateResponse, EventStatus, ExtendStatus, OverdraftLimitExceededError, type ReleaseRequest, type ReleaseResponse, ReleaseStatus, type ReservationCreateRequest, type ReservationCreateResponse, type ReservationDetail, ReservationExpiredError, type ReservationExtendRequest, type ReservationExtendResponse, ReservationFinalizedError, type ReservationListResponse, ReservationStatus, type ReservationSummary, type SignedAmount, type StreamReservation, type StreamReservationOptions, type Subject, Unit, type WithCyclesConfig, balanceResponseFromWire, capsFromWire, commitRequestToWire, commitResponseFromWire, decisionRequestToWire, decisionResponseFromWire, errorCodeFromString, errorResponseFromWire, eventCreateRequestToWire, eventCreateResponseFromWire, getCyclesContext, isAllowed, isDenied, isMetricsEmpty, isRetryableErrorCode, isToolAllowed, metricsToWire, releaseRequestToWire, releaseResponseFromWire, reservationCreateRequestToWire, reservationCreateResponseFromWire, reservationDetailFromWire, reservationExtendRequestToWire, reservationExtendResponseFromWire, reservationListResponseFromWire, reservationSummaryFromWire, reserveForStream, setDefaultClient, setDefaultConfig, withCycles };
556
+ export { type Action, type Amount, type Balance, type BalanceResponse, BudgetExceededError, type Caps, CommitOveragePolicy, type CommitRequest, type CommitResponse, CommitStatus, CyclesClient, CyclesConfig, type CyclesContext, CyclesError, type CyclesMetrics, CyclesProtocolError, CyclesResponse, CyclesTransportError, DebtOutstandingError, Decision, type DecisionRequest, type DecisionResponse, type DryRunResult, ErrorCode, type ErrorResponse, type EventCreateRequest, type EventCreateResponse, EventStatus, ExtendStatus, OverdraftLimitExceededError, type ReleaseRequest, type ReleaseResponse, ReleaseStatus, type ReservationCreateRequest, type ReservationCreateResponse, type ReservationDetail, ReservationExpiredError, type ReservationExtendRequest, type ReservationExtendResponse, ReservationFinalizedError, type ReservationListResponse, ReservationStatus, type ReservationSummary, type SignedAmount, type StreamReservation, type StreamReservationOptions, type Subject, Unit, type WithCyclesConfig, balanceResponseFromWire, capsFromWire, commitRequestToWire, commitResponseFromWire, decisionRequestToWire, decisionResponseFromWire, errorCodeFromString, errorResponseFromWire, eventCreateRequestToWire, eventCreateResponseFromWire, getCyclesContext, isAllowed, isDenied, isMetricsEmpty, isRetryableErrorCode, isToolAllowed, metricsToWire, releaseRequestToWire, releaseResponseFromWire, reservationCreateRequestToWire, reservationCreateResponseFromWire, reservationDetailFromWire, reservationExtendRequestToWire, reservationExtendResponseFromWire, reservationListResponseFromWire, reservationSummaryFromWire, reserveForStream, setDefaultClient, setDefaultConfig, withCycles };
package/dist/index.js CHANGED
@@ -648,6 +648,14 @@ var ReservationFinalizedError = class extends CyclesProtocolError {
648
648
  this.name = "ReservationFinalizedError";
649
649
  }
650
650
  };
651
+ var CyclesTransportError = class extends CyclesError {
652
+ cause;
653
+ constructor(message, options) {
654
+ super(message);
655
+ this.name = "CyclesTransportError";
656
+ this.cause = options?.cause;
657
+ }
658
+ };
651
659
 
652
660
  // src/errors.ts
653
661
  function buildProtocolException(prefix, response) {
@@ -752,12 +760,15 @@ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
752
760
  ErrorCode2["FORBIDDEN"] = "FORBIDDEN";
753
761
  ErrorCode2["NOT_FOUND"] = "NOT_FOUND";
754
762
  ErrorCode2["BUDGET_EXCEEDED"] = "BUDGET_EXCEEDED";
763
+ ErrorCode2["BUDGET_FROZEN"] = "BUDGET_FROZEN";
764
+ ErrorCode2["BUDGET_CLOSED"] = "BUDGET_CLOSED";
755
765
  ErrorCode2["RESERVATION_EXPIRED"] = "RESERVATION_EXPIRED";
756
766
  ErrorCode2["RESERVATION_FINALIZED"] = "RESERVATION_FINALIZED";
757
767
  ErrorCode2["IDEMPOTENCY_MISMATCH"] = "IDEMPOTENCY_MISMATCH";
758
768
  ErrorCode2["UNIT_MISMATCH"] = "UNIT_MISMATCH";
759
769
  ErrorCode2["OVERDRAFT_LIMIT_EXCEEDED"] = "OVERDRAFT_LIMIT_EXCEEDED";
760
770
  ErrorCode2["DEBT_OUTSTANDING"] = "DEBT_OUTSTANDING";
771
+ ErrorCode2["MAX_EXTENSIONS_EXCEEDED"] = "MAX_EXTENSIONS_EXCEEDED";
761
772
  ErrorCode2["INTERNAL_ERROR"] = "INTERNAL_ERROR";
762
773
  ErrorCode2["UNKNOWN"] = "UNKNOWN";
763
774
  return ErrorCode2;
@@ -879,7 +890,7 @@ function buildReservationBody(cfg, estimate, defaultSubject) {
879
890
  action,
880
891
  estimate: { unit, amount: estimate },
881
892
  ttl_ms: ttlMs,
882
- overage_policy: cfg.overagePolicy ?? "REJECT"
893
+ overage_policy: cfg.overagePolicy ?? "ALLOW_IF_AVAILABLE"
883
894
  };
884
895
  validateGracePeriodMs(cfg.gracePeriodMs);
885
896
  if (cfg.gracePeriodMs !== void 0) {
@@ -1201,7 +1212,7 @@ async function reserveForStream(options) {
1201
1212
  actionTags,
1202
1213
  ttlMs = DEFAULT_TTL_MS,
1203
1214
  gracePeriodMs,
1204
- overagePolicy = "REJECT",
1215
+ overagePolicy = "ALLOW_IF_AVAILABLE",
1205
1216
  dimensions
1206
1217
  } = options;
1207
1218
  validateNonNegative(estimate, "estimate");
@@ -1339,6 +1350,7 @@ export {
1339
1350
  CyclesError,
1340
1351
  CyclesProtocolError,
1341
1352
  CyclesResponse,
1353
+ CyclesTransportError,
1342
1354
  DebtOutstandingError,
1343
1355
  Decision,
1344
1356
  ErrorCode,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runcycles",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "TypeScript client for the Cycles budget-management protocol",
5
5
  "license": "Apache-2.0",
6
6
  "author": "runcycles",
@@ -52,7 +52,7 @@
52
52
  "test": "vitest run",
53
53
  "test:watch": "vitest",
54
54
  "test:coverage": "vitest run --coverage",
55
- "typecheck": "tsc --noEmit",
55
+ "typecheck": "tsc --noEmit -p tsconfig.typecheck.json",
56
56
  "prepublishOnly": "npm run lint && npm run build"
57
57
  },
58
58
  "devDependencies": {