withruntime 0.11.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/BLAXEL.md +3 -3
  2. package/COMPATIBILITY.md +74 -9
  3. package/DAYTONA.md +33 -5
  4. package/E2B.md +137 -48
  5. package/README.md +11 -9
  6. package/README.src.md +11 -9
  7. package/VERCEL.md +43 -5
  8. package/compatibility-lock.json +58 -49
  9. package/dist/billing-cli.d.ts +1 -1
  10. package/dist/billing-cli.js +77 -1
  11. package/dist/blaxel/errors.d.ts +14 -0
  12. package/dist/blaxel/errors.js +33 -4
  13. package/dist/blaxel/index.d.ts +2 -2
  14. package/dist/blaxel/index.js +4 -4
  15. package/dist/blaxel/interpreter.d.ts +2 -5
  16. package/dist/blaxel/sandbox.d.ts +15 -7
  17. package/dist/blaxel/sandbox.js +64 -9
  18. package/dist/blaxel/snapshot.d.ts +4 -0
  19. package/dist/blaxel/snapshot.js +4 -0
  20. package/dist/cli/logs.d.ts +21 -0
  21. package/dist/cli/logs.js +188 -0
  22. package/dist/cli/logs.test.d.ts +1 -0
  23. package/dist/cli/logs.test.js +272 -0
  24. package/dist/cli-extras.d.ts +3 -3
  25. package/dist/cli-extras.js +17 -12
  26. package/dist/cli-words.d.ts +10 -1
  27. package/dist/cli-words.js +18 -0
  28. package/dist/cli.d.ts +6 -2
  29. package/dist/cli.js +468 -219
  30. package/dist/client.d.ts +13 -63
  31. package/dist/client.js +35 -124
  32. package/dist/cloudflare/errors.d.ts +143 -0
  33. package/dist/cloudflare/errors.js +167 -0
  34. package/dist/cloudflare/index.d.ts +175 -6
  35. package/dist/cloudflare/index.js +416 -26
  36. package/dist/cloudflare/interpreter.d.ts +119 -0
  37. package/dist/cloudflare/interpreter.js +223 -0
  38. package/dist/cloudflare/streams.d.ts +38 -0
  39. package/dist/cloudflare/streams.js +145 -0
  40. package/dist/cloudflare/watch.d.ts +9 -0
  41. package/dist/cloudflare/watch.js +24 -0
  42. package/dist/codesandbox/index.d.ts +216 -28
  43. package/dist/codesandbox/index.js +478 -78
  44. package/dist/compat/core.d.ts +18 -0
  45. package/dist/compat/core.js +29 -0
  46. package/dist/compat/files.d.ts +1 -0
  47. package/dist/compat/files.js +25 -5
  48. package/dist/daytona/computer-use.d.ts +13 -4
  49. package/dist/daytona/computer-use.js +66 -8
  50. package/dist/daytona/daytona.d.ts +7 -2
  51. package/dist/daytona/daytona.js +31 -5
  52. package/dist/daytona/errors.d.ts +11 -0
  53. package/dist/daytona/errors.js +18 -0
  54. package/dist/daytona/filesystem.js +2 -1
  55. package/dist/daytona/image.d.ts +13 -9
  56. package/dist/daytona/image.js +18 -12
  57. package/dist/daytona/index.d.ts +1 -1
  58. package/dist/daytona/sandbox.d.ts +9 -3
  59. package/dist/daytona/sandbox.js +17 -3
  60. package/dist/domains/index.d.ts +9 -0
  61. package/dist/domains/index.js +10 -0
  62. package/dist/e2b/client.d.ts +15 -2
  63. package/dist/e2b/client.js +61 -7
  64. package/dist/e2b/commands.d.ts +4 -1
  65. package/dist/e2b/commands.js +17 -7
  66. package/dist/e2b/errors.d.ts +43 -2
  67. package/dist/e2b/errors.js +78 -6
  68. package/dist/e2b/filesystem.d.ts +1 -1
  69. package/dist/e2b/filesystem.js +82 -16
  70. package/dist/e2b/index.d.ts +3 -3
  71. package/dist/e2b/index.js +2 -2
  72. package/dist/e2b/sandbox.d.ts +50 -35
  73. package/dist/e2b/sandbox.js +228 -185
  74. package/dist/e2b/unsupported.d.ts +19 -0
  75. package/dist/e2b/unsupported.js +22 -1
  76. package/dist/e2b/users.d.ts +9 -0
  77. package/dist/e2b/users.js +22 -0
  78. package/dist/errors.d.ts +14 -5
  79. package/dist/errors.js +28 -14
  80. package/dist/freestyle/index.d.ts +285 -37
  81. package/dist/freestyle/index.js +656 -144
  82. package/dist/identity.d.ts +3 -0
  83. package/dist/identity.js +27 -0
  84. package/dist/images/index.d.ts +9 -0
  85. package/dist/images/index.js +10 -0
  86. package/dist/index.d.ts +1 -0
  87. package/dist/ips/index.d.ts +9 -0
  88. package/dist/ips/index.js +10 -0
  89. package/dist/jobs/index.d.ts +9 -0
  90. package/dist/jobs/index.js +10 -0
  91. package/dist/keys.js +2 -0
  92. package/dist/login.js +2 -0
  93. package/dist/machine.d.ts +189 -0
  94. package/dist/machine.js +521 -0
  95. package/dist/mcp.js +1 -1
  96. package/dist/modal/index.d.ts +339 -61
  97. package/dist/modal/index.js +781 -121
  98. package/dist/network-cli.d.ts +3 -1
  99. package/dist/network-cli.js +78 -36
  100. package/dist/networks/index.d.ts +11 -0
  101. package/dist/networks/index.js +10 -0
  102. package/dist/openai-agents/index.d.ts +1 -1
  103. package/dist/openai-agents/index.js +1 -1
  104. package/dist/ports/index.d.ts +9 -0
  105. package/dist/ports/index.js +10 -0
  106. package/dist/product-names.d.ts +52 -0
  107. package/dist/product-names.js +164 -0
  108. package/dist/product-renames.d.ts +103 -0
  109. package/dist/product-renames.js +189 -0
  110. package/dist/products/apps.d.ts +176 -0
  111. package/dist/products/apps.js +165 -0
  112. package/dist/products/billing.d.ts +41 -0
  113. package/dist/products/billing.js +13 -0
  114. package/dist/products/browser.d.ts +10 -0
  115. package/dist/products/browsers.d.ts +71 -0
  116. package/dist/products/browsers.js +102 -0
  117. package/dist/products/builds.d.ts +126 -0
  118. package/dist/products/builds.js +221 -0
  119. package/dist/products/index.d.ts +3 -16
  120. package/dist/products/index.js +3 -14
  121. package/dist/products/jobs.d.ts +19 -3
  122. package/dist/products/jobs.js +28 -12
  123. package/dist/products/limits.d.ts +4 -10
  124. package/dist/products/logs.d.ts +245 -0
  125. package/dist/products/logs.js +274 -0
  126. package/dist/products/logs.test.d.ts +1 -0
  127. package/dist/products/logs.test.js +343 -0
  128. package/dist/products/network-products.d.ts +38 -7
  129. package/dist/products/network-products.js +31 -18
  130. package/dist/products/network.d.ts +1 -1
  131. package/dist/products/observability.d.ts +3 -2
  132. package/dist/products/private-network.js +1 -1
  133. package/dist/products/queues.d.ts +149 -0
  134. package/dist/products/queues.js +213 -0
  135. package/dist/products/referrals.d.ts +21 -7
  136. package/dist/products/referrals.js +3 -3
  137. package/dist/products/secrets.d.ts +8 -4
  138. package/dist/products/secrets.js +39 -18
  139. package/dist/products/signed-requests.d.ts +21 -0
  140. package/dist/products/signed-requests.js +11 -0
  141. package/dist/products/streams.d.ts +73 -0
  142. package/dist/products/streams.js +17 -0
  143. package/dist/products/switching.d.ts +37 -10
  144. package/dist/products/switching.js +4 -3
  145. package/dist/products/volumes.d.ts +3 -0
  146. package/dist/record-cli.d.ts +23 -0
  147. package/dist/record-cli.js +308 -0
  148. package/dist/renamed-products.d.ts +38 -0
  149. package/dist/renamed-products.js +34 -0
  150. package/dist/runloop/index.d.ts +9 -2
  151. package/dist/runloop/index.js +29 -8
  152. package/dist/runloop/sdk.d.ts +131 -0
  153. package/dist/runloop/sdk.js +167 -0
  154. package/dist/sandbox.d.ts +10 -94
  155. package/dist/sandbox.js +22 -371
  156. package/dist/sandboxes/index.d.ts +11 -0
  157. package/dist/sandboxes/index.js +12 -0
  158. package/dist/snapshots/index.d.ts +9 -0
  159. package/dist/snapshots/index.js +11 -0
  160. package/dist/snapshots.d.ts +7 -4
  161. package/dist/sprites/index.d.ts +343 -31
  162. package/dist/sprites/index.js +866 -84
  163. package/dist/ssh.d.ts +1 -1
  164. package/dist/ssh.js +11 -11
  165. package/dist/terminal.d.ts +24 -0
  166. package/dist/terminal.js +32 -0
  167. package/dist/transport.d.ts +18 -2
  168. package/dist/transport.js +61 -6
  169. package/dist/tunnel.js +1 -1
  170. package/dist/types.d.ts +116 -8
  171. package/dist/vercel/sandbox.d.ts +1 -2
  172. package/dist/vercel/sandbox.js +6 -5
  173. package/dist/vercel/snapshot.js +10 -2
  174. package/dist/volumes/index.d.ts +9 -0
  175. package/dist/volumes/index.js +10 -0
  176. package/package.json +48 -2
@@ -129,9 +129,9 @@ export declare function ports(t: Transport): {
129
129
  deleted: true;
130
130
  }>;
131
131
  };
132
- /** `runtime.addresses`: a dedicated outbound address every sandbox of the
132
+ /** `runtime.ips`: a dedicated outbound address every sandbox of the
133
133
  * account sends from, for allow-lists. */
134
- export declare function addresses(t: Transport): {
134
+ export declare function ips(t: Transport): {
135
135
  reserve: (input?: {
136
136
  family?: 4 | 6;
137
137
  }, options?: RequestOptions) => Promise<EgressAddress>;
@@ -142,8 +142,8 @@ export declare function addresses(t: Transport): {
142
142
  deleted: true;
143
143
  }>;
144
144
  };
145
- /** `runtime.tunnel`: a WireGuard tunnel from your own network into your sandboxes. */
146
- export declare function tunnel(t: Transport): {
145
+ /** `runtime.networks.wireguard`: a WireGuard tunnel from your own network into your sandboxes. */
146
+ export declare function wireguard(t: Transport): {
147
147
  get: (options?: RequestOptions) => Promise<Tunnel>;
148
148
  /** Idempotent: returns the tunnel you have. */
149
149
  create: (input?: {
@@ -186,15 +186,39 @@ export type SetUpstreamProxy = {
186
186
  * every connection when absent. 1 to 16. */
187
187
  hosts?: string[];
188
188
  };
189
- /** `runtime.network`: the network settings of the whole account.
189
+ /** `runtime.networks`: the networks of the whole account: the WireGuard
190
+ * tunnel in, your sandboxes reaching each other, and the proxy out.
190
191
  *
191
- * await runtime.network.upstreamProxy.set({ url: "http://proxy.example.com:3128" });
192
+ * await runtime.networks.upstreamProxy.set({ url: "http://proxy.example.com:3128" });
192
193
  *
193
194
  * `upstreamProxy`: after Runtime's own rules allow a connection, the host
194
195
  * reaches it with CONNECT through your proxy, so your proxy's controls and
195
196
  * logs apply. A proxy that refuses or cannot be reached fails the connection
196
197
  * (upstream-proxy-failed); nothing goes around it. Needs a kept top-up. */
197
- export declare function network(t: Transport): {
198
+ export declare function networks(t: Transport): {
199
+ /** The WireGuard tunnel from your own network into your sandboxes. */
200
+ wireguard: {
201
+ get: (options?: RequestOptions) => Promise<Tunnel>;
202
+ /** Idempotent: returns the tunnel you have. */
203
+ create: (input?: {
204
+ subnet?: string;
205
+ }, options?: RequestOptions) => Promise<Tunnel>;
206
+ delete: (options?: RequestOptions) => Promise<{
207
+ id: string;
208
+ deleted: true;
209
+ }>;
210
+ /** Leave publicKey out and Runtime generates the pair; the private key is
211
+ * then in `config`, shown once. */
212
+ addPeer: (input: {
213
+ name: string;
214
+ publicKey?: string;
215
+ routes?: string[];
216
+ }, options?: RequestOptions) => Promise<TunnelPeerCreated>;
217
+ rotatePeer: (peerId: string, input?: {
218
+ publicKey?: string;
219
+ }, options?: RequestOptions) => Promise<TunnelPeerCreated>;
220
+ removePeer: (peerId: string, options?: RequestOptions) => Promise<Tunnel>;
221
+ };
198
222
  /** Your sandboxes reaching each other by name (`private-network.ts`). */
199
223
  private: {
200
224
  get: (options?: RequestOptions) => Promise<import("./private-network.js").PrivateNetwork>;
@@ -202,6 +226,13 @@ export declare function network(t: Transport): {
202
226
  enabled: boolean;
203
227
  }, options?: RequestOptions) => Promise<import("./private-network.js").PrivateNetwork>;
204
228
  };
229
+ /** Your sandboxes' requests signed as Runtime's agents (`signed-requests.ts`). */
230
+ signedRequests: {
231
+ get: (options?: RequestOptions) => Promise<import("./signed-requests.js").SignedRequests>;
232
+ set: (input: {
233
+ enabled: boolean;
234
+ }, options?: RequestOptions) => Promise<import("./signed-requests.js").SignedRequests>;
235
+ };
205
236
  upstreamProxy: {
206
237
  /** Send outbound connections through your proxy, replacing any set before. */
207
238
  set: (input: SetUpstreamProxy, options?: RequestOptions) => Promise<UpstreamProxy & {
@@ -1,4 +1,5 @@
1
1
  import { privateNetwork } from "./private-network.js";
2
+ import { signedRequests } from "./signed-requests.js";
2
3
  const enc = encodeURIComponent;
3
4
  /** `runtime.domains`: serve a sandbox's port at your own hostname, with HTTPS. */
4
5
  export function domains(t) {
@@ -43,57 +44,69 @@ export function ports(t) {
43
44
  }),
44
45
  };
45
46
  }
46
- /** `runtime.addresses`: a dedicated outbound address every sandbox of the
47
+ /** `runtime.ips`: a dedicated outbound address every sandbox of the
47
48
  * account sends from, for allow-lists. */
48
- export function addresses(t) {
49
+ export function ips(t) {
49
50
  return {
50
- reserve: (input = {}, options) => t.json({ method: "POST", path: "/v1/addresses", body: input, ...options }),
51
- list: async (options) => (await t.json({ method: "GET", path: "/v1/addresses", ...options }))
52
- .data,
51
+ reserve: (input = {}, options) => t.json({ method: "POST", path: "/v1/ips", body: input, ...options }),
52
+ list: async (options) => (await t.json({ method: "GET", path: "/v1/ips", ...options })).data,
53
53
  release: (addressId, options) => t.json({
54
54
  method: "DELETE",
55
- path: `/v1/addresses/${enc(addressId)}`,
55
+ path: `/v1/ips/${enc(addressId)}`,
56
56
  ...options,
57
57
  }),
58
58
  };
59
59
  }
60
- /** `runtime.tunnel`: a WireGuard tunnel from your own network into your sandboxes. */
61
- export function tunnel(t) {
60
+ /** `runtime.networks.wireguard`: a WireGuard tunnel from your own network into your sandboxes. */
61
+ export function wireguard(t) {
62
62
  return {
63
- get: (options) => t.json({ method: "GET", path: "/v1/tunnel", ...options }),
63
+ get: (options) => t.json({ method: "GET", path: "/v1/networks/wireguard", ...options }),
64
64
  /** Idempotent: returns the tunnel you have. */
65
- create: (input = {}, options) => t.json({ method: "POST", path: "/v1/tunnel", body: input, ...options }),
66
- delete: (options) => t.json({ method: "DELETE", path: "/v1/tunnel", ...options }),
65
+ create: (input = {}, options) => t.json({ method: "POST", path: "/v1/networks/wireguard", body: input, ...options }),
66
+ delete: (options) => t.json({
67
+ method: "DELETE",
68
+ path: "/v1/networks/wireguard",
69
+ ...options,
70
+ }),
67
71
  /** Leave publicKey out and Runtime generates the pair; the private key is
68
72
  * then in `config`, shown once. */
69
73
  addPeer: (input, options) => t.json({
70
74
  method: "POST",
71
- path: "/v1/tunnel/peers",
75
+ path: "/v1/networks/wireguard/peers",
72
76
  body: input,
73
77
  ...options,
74
78
  }),
75
79
  rotatePeer: (peerId, input = {}, options) => t.json({
76
80
  method: "POST",
77
- path: `/v1/tunnel/peers/${enc(peerId)}:rotate`,
81
+ path: `/v1/networks/wireguard/peers/${enc(peerId)}:rotate`,
78
82
  body: input,
79
83
  ...options,
80
84
  }),
81
- removePeer: (peerId, options) => t.json({ method: "DELETE", path: `/v1/tunnel/peers/${enc(peerId)}`, ...options }),
85
+ removePeer: (peerId, options) => t.json({
86
+ method: "DELETE",
87
+ path: `/v1/networks/wireguard/peers/${enc(peerId)}`,
88
+ ...options,
89
+ }),
82
90
  };
83
91
  }
84
- /** `runtime.network`: the network settings of the whole account.
92
+ /** `runtime.networks`: the networks of the whole account: the WireGuard
93
+ * tunnel in, your sandboxes reaching each other, and the proxy out.
85
94
  *
86
- * await runtime.network.upstreamProxy.set({ url: "http://proxy.example.com:3128" });
95
+ * await runtime.networks.upstreamProxy.set({ url: "http://proxy.example.com:3128" });
87
96
  *
88
97
  * `upstreamProxy`: after Runtime's own rules allow a connection, the host
89
98
  * reaches it with CONNECT through your proxy, so your proxy's controls and
90
99
  * logs apply. A proxy that refuses or cannot be reached fails the connection
91
100
  * (upstream-proxy-failed); nothing goes around it. Needs a kept top-up. */
92
- export function network(t) {
93
- const path = "/v1/network/upstream-proxy";
101
+ export function networks(t) {
102
+ const path = "/v1/networks/upstream-proxy";
94
103
  return {
104
+ /** The WireGuard tunnel from your own network into your sandboxes. */
105
+ wireguard: wireguard(t),
95
106
  /** Your sandboxes reaching each other by name (`private-network.ts`). */
96
107
  private: privateNetwork(t),
108
+ /** Your sandboxes' requests signed as Runtime's agents (`signed-requests.ts`). */
109
+ signedRequests: signedRequests(t),
97
110
  upstreamProxy: {
98
111
  /** Send outbound connections through your proxy, replacing any set before. */
99
112
  set: (input, options) => t.json({
@@ -24,7 +24,7 @@ export type NetworkPolicy = Required<NetworkRules> & {
24
24
  /** Ports reachable without a connect entry. */
25
25
  ports: number[];
26
26
  connectAllowed: boolean;
27
- /** paid, granted, not_paid, revoked, suspended, or trial (a trial sandbox reaches ports 80 and 443 only). */
27
+ /** paid, granted, not_paid, revoked, suspended, or trial (a sandbox without credit reaches ports 80 and 443 only). */
28
28
  connectReason: string;
29
29
  forbiddenPorts: number[];
30
30
  updatedAt: string | null;
@@ -35,7 +35,7 @@ export type SandboxMetrics = {
35
35
  latest: MetricPoint | null;
36
36
  points: MetricPoint[];
37
37
  };
38
- export type WebhookEventType = "sandbox.created" | "sandbox.running" | "sandbox.paused" | "sandbox.woken" | "sandbox.stopped" | "sandbox.start_failed" | "sandbox.wake_failed" | "sandbox.host_unreachable" | "sandbox.host_reachable" | "sandbox.recovered" | "sandbox.recovery_failed" | "snapshot.ready" | "snapshot.failed" | "snapshot.deleted" | "volume.ready" | "volume.failed" | "volume.deleted";
38
+ export type WebhookEventType = "sandbox.created" | "sandbox.running" | "sandbox.paused" | "sandbox.woken" | "sandbox.stopped" | "sandbox.start_failed" | "sandbox.wake_failed" | "sandbox.host_unreachable" | "sandbox.host_reachable" | "sandbox.recovered" | "sandbox.recovery_failed" | "sandbox.files.changed" | "sandbox.out_of_memory" | "sandbox.secret_not_applied" | "snapshot.ready" | "snapshot.failed" | "snapshot.deleted" | "volume.ready" | "volume.failed" | "volume.deleted" | "egress_secret.created" | "egress_secret.updated" | "egress_secret.deleted" | "upstream_proxy.set" | "upstream_proxy.removed";
39
39
  /** An event as /v1/events lists it and a webhook delivers it. */
40
40
  export type RuntimeEvent = {
41
41
  id: string;
@@ -113,7 +113,8 @@ export type UsageExportRow = {
113
113
  name: string | null;
114
114
  kind: string;
115
115
  meter: string;
116
- fundedBy: "credit" | "trial";
116
+ /** credit, the trial's hours, or the month's included usage. */
117
+ fundedBy: "credit" | "trial" | "allowance";
117
118
  startsAt: string;
118
119
  endsAt: string;
119
120
  settledAt: string;
@@ -1,5 +1,5 @@
1
1
  export function privateNetwork(t) {
2
- const path = "/v1/network/private";
2
+ const path = "/v1/networks/private";
3
3
  return {
4
4
  /** On or off, and whether this account may turn it on. */
5
5
  get: (options) => t.json({ method: "GET", path, ...options }),
@@ -0,0 +1,149 @@
1
+ import { Page } from "../page.js";
2
+ import type { RequestOptions, Transport } from "../transport.js";
3
+ /** Private until launch.
4
+ * This is the proposed management contract, not an installed API route.
5
+ * SQS clients use the returned sqs URL with their existing client. */
6
+ export type RecordState = "creating" | "ready" | "updating" | "deleting" | "deleted" | "failed";
7
+ export type RecordResource = {
8
+ id: string;
9
+ name: string;
10
+ labels: Record<string, string>;
11
+ state: RecordState;
12
+ createdAt: string;
13
+ error?: {
14
+ code: string;
15
+ message: string;
16
+ hint: string;
17
+ } | null;
18
+ };
19
+ export type QueueSettings = {
20
+ visibilityTimeoutSeconds: number;
21
+ retentionSeconds: number;
22
+ maxMessageBytes: number;
23
+ delaySeconds: number;
24
+ fifo: boolean;
25
+ deadLetter: {
26
+ queue: string;
27
+ maxReceives: number;
28
+ } | null;
29
+ };
30
+ export type Queue = RecordResource & {
31
+ settings: QueueSettings;
32
+ counts: {
33
+ visible: number;
34
+ inFlight: number;
35
+ delayed: number;
36
+ };
37
+ sqs: string;
38
+ };
39
+ export type CreateQueue = {
40
+ name: string;
41
+ labels?: Record<string, string>;
42
+ settings?: Partial<QueueSettings>;
43
+ };
44
+ export type UpdateQueue = Partial<CreateQueue>;
45
+ export type RecordListQuery = {
46
+ name?: string;
47
+ label?: readonly string[];
48
+ state?: readonly RecordState[];
49
+ limit?: number;
50
+ cursor?: string;
51
+ };
52
+ export type RecordWaitOptions = RequestOptions & {
53
+ pollMs?: number;
54
+ };
55
+ export type QueueAttribute = {
56
+ dataType: string;
57
+ stringValue?: string;
58
+ binaryValue?: string;
59
+ };
60
+ export type SendMessage = {
61
+ body: string;
62
+ attributes?: Record<string, QueueAttribute>;
63
+ delaySeconds?: number;
64
+ groupId?: string;
65
+ dedupId?: string;
66
+ };
67
+ export type ReceiveMessages = {
68
+ max?: number;
69
+ waitSeconds?: number;
70
+ visibilitySeconds?: number;
71
+ };
72
+ export type QueueMessage = SendMessage & {
73
+ id: string;
74
+ receiptHandle: string;
75
+ receives: number;
76
+ };
77
+ export type MessageSent = {
78
+ id: string;
79
+ md5: string;
80
+ sequenceNumber?: string;
81
+ };
82
+ export type ReceiptResult = {
83
+ successful: string[];
84
+ failed: {
85
+ receiptHandle: string;
86
+ code: string;
87
+ message: string;
88
+ hint: string;
89
+ }[];
90
+ };
91
+ /** A consume call handles messages sequentially. max counts handler attempts,
92
+ * including failures. Omit max to run until cancelled. timeoutMs bounds each
93
+ * network call, including settlement after cancellation, not the handler.
94
+ * Choose visibilitySeconds longer than the handler's work; delivery is at least once. */
95
+ export type ConsumeOptions = ReceiveMessages & {
96
+ signal?: AbortSignal;
97
+ timeoutMs?: number;
98
+ };
99
+ export type ConsumeResult = {
100
+ processed: number;
101
+ acknowledged: number;
102
+ retried: number;
103
+ aborted: boolean;
104
+ };
105
+ export type QueueHandler = (message: QueueMessage, signal: AbortSignal) => unknown;
106
+ /** Shared only by the private record products. The server owns field defaults
107
+ * and protocol refusals; the SDK preserves their codes and recovery hints. */
108
+ export declare function recordResources<R extends RecordResource, C, U>(t: Transport, plural: "queues" | "streams"): {
109
+ create: (input: C, options?: RequestOptions) => Promise<R>;
110
+ get: (id: string, options?: RequestOptions) => Promise<R>;
111
+ list: (query?: RecordListQuery, options?: RequestOptions) => Promise<Page<R>>;
112
+ update: (id: string, input: U, options?: RequestOptions) => Promise<R>;
113
+ delete: (id: string, options?: RequestOptions) => Promise<R>;
114
+ /** Poll one resource with a deadline across every read, including retries. */
115
+ wait(id: string, target?: "ready" | "deleted", options?: RecordWaitOptions): Promise<R>;
116
+ };
117
+ /** Private until launch. No public Runtime property is installed here. */
118
+ export declare function queues(t: Transport): {
119
+ send: (id: string, input: SendMessage, options?: RequestOptions) => Promise<MessageSent>;
120
+ receive: (id: string, input?: ReceiveMessages, options?: RequestOptions) => Promise<{
121
+ messages: QueueMessage[];
122
+ }>;
123
+ ack: (id: string, input: {
124
+ receiptHandles: string[];
125
+ }, options?: RequestOptions) => Promise<ReceiptResult>;
126
+ retry: (id: string, input: {
127
+ receiptHandle: string;
128
+ visibilitySeconds: number;
129
+ }, options?: RequestOptions) => Promise<{
130
+ receiptHandle: string;
131
+ visibilitySeconds: number;
132
+ }>;
133
+ /** Receive, handle, then acknowledge. No acknowledgement precedes success.
134
+ * A failed or cancelled handler releases its receipt at once. Aborting
135
+ * during receive can lose its reply; that lease expires without an ack.
136
+ * Settlement ignores the cancelled signal and has a bounded deadline.
137
+ * A lost settlement reply is retried once with the same key, even when
138
+ * transport retries were disabled. A remaining failure is thrown. */
139
+ consume(id: string, handler: QueueHandler, options?: ConsumeOptions): Promise<ConsumeResult>;
140
+ /** Purge returns the resource; follow its state with wait(id). */
141
+ purge: (id: string, options?: RequestOptions) => Promise<Queue>;
142
+ create: (input: CreateQueue, options?: RequestOptions) => Promise<Queue>;
143
+ get: (id: string, options?: RequestOptions) => Promise<Queue>;
144
+ list: (query?: RecordListQuery, options?: RequestOptions) => Promise<Page<Queue>>;
145
+ update: (id: string, input: Partial<CreateQueue>, options?: RequestOptions) => Promise<Queue>;
146
+ delete: (id: string, options?: RequestOptions) => Promise<Queue>;
147
+ /** Poll one resource with a deadline across every read, including retries. */
148
+ wait(id: string, target?: "ready" | "deleted", options?: RecordWaitOptions): Promise<Queue>;
149
+ };
@@ -0,0 +1,213 @@
1
+ import { RuntimeError } from "../errors.js";
2
+ import { Page } from "../page.js";
3
+ import { pause } from "../wait.js";
4
+ /** Stop waiting for user code on abort. Its rejection stays observed even if
5
+ * it finishes later. Handlers should use the signal to stop their own work. */
6
+ function handleMessage(handler, message, signal) {
7
+ return new Promise((resolve) => {
8
+ let finished = false;
9
+ const done = (success) => {
10
+ if (finished)
11
+ return;
12
+ finished = true;
13
+ signal.removeEventListener("abort", abort);
14
+ resolve(success);
15
+ };
16
+ const abort = () => done(false);
17
+ if (signal.aborted) {
18
+ done(false);
19
+ return;
20
+ }
21
+ signal.addEventListener("abort", abort, { once: true });
22
+ // Observe synchronous throws and late rejections by the same path.
23
+ Promise.resolve()
24
+ .then(() => signal.aborted ? false : Promise.resolve(handler(message, signal)).then(() => true))
25
+ .then(done, () => done(false));
26
+ });
27
+ }
28
+ /** Shared only by the private record products. The server owns field defaults
29
+ * and protocol refusals; the SDK preserves their codes and recovery hints. */
30
+ export function recordResources(t, plural) {
31
+ const base = `/v1/${plural}`;
32
+ const path = (id) => `${base}/${encodeURIComponent(id)}`;
33
+ const get = (id, options) => t.json({ ...options, method: "GET", path: path(id) });
34
+ const list = async (query = {}, options) => {
35
+ const page = await t.json({
36
+ ...options,
37
+ method: "GET",
38
+ path: base,
39
+ query,
40
+ });
41
+ return new Page(page.data, page.nextCursor, (cursor) => list({ ...query, cursor }, options));
42
+ };
43
+ return {
44
+ create: (input, options) => t.json({ ...options, method: "POST", path: base, body: input }),
45
+ get,
46
+ list,
47
+ update: (id, input, options) => t.json({ ...options, method: "POST", path: `${path(id)}:update`, body: input }),
48
+ delete: (id, options) => t.json({ ...options, method: "DELETE", path: path(id) }),
49
+ /** Poll one resource with a deadline across every read, including retries. */
50
+ async wait(id, target = "ready", options = {}) {
51
+ const { pollMs = 250, timeoutMs = 300_000, signal } = options;
52
+ if (!Number.isSafeInteger(pollMs) ||
53
+ pollMs < 0 ||
54
+ !Number.isSafeInteger(timeoutMs) ||
55
+ timeoutMs < 0)
56
+ throw new RuntimeError({
57
+ code: "invalid_request",
58
+ status: 0,
59
+ message: "pollMs and timeoutMs must be nonnegative safe integers.",
60
+ hint: "Use milliseconds; zero timeout disables the deadline.",
61
+ });
62
+ const deadline = new AbortController();
63
+ const combined = signal ? AbortSignal.any([signal, deadline.signal]) : deadline.signal;
64
+ const timer = timeoutMs ? setTimeout(() => deadline.abort(), timeoutMs) : undefined;
65
+ try {
66
+ for (;;) {
67
+ combined.throwIfAborted();
68
+ const current = await get(id, {
69
+ signal: combined,
70
+ timeoutMs: 0,
71
+ });
72
+ combined.throwIfAborted();
73
+ if (current.state === "failed" || (current.state === "deleted" && target !== "deleted"))
74
+ throw new RuntimeError({
75
+ code: current.error?.code ?? "unexpected_state",
76
+ status: 0,
77
+ message: current.error?.message ?? `Resource reached ${current.state}.`,
78
+ hint: current.error?.hint ?? "Read the resource before retrying the change.",
79
+ details: { id, target, state: current.state },
80
+ });
81
+ if (current.state === target)
82
+ return current;
83
+ await pause(pollMs, combined);
84
+ }
85
+ }
86
+ catch (cause) {
87
+ if (!combined.aborted)
88
+ throw cause;
89
+ throw new RuntimeError({
90
+ code: "timeout",
91
+ status: 0,
92
+ message: "Waiting ended before the target state was observed.",
93
+ hint: "Read the resource to resume; retry a write with its original idempotency key.",
94
+ cause,
95
+ });
96
+ }
97
+ finally {
98
+ clearTimeout(timer);
99
+ }
100
+ },
101
+ };
102
+ }
103
+ /** Private until launch. No public Runtime property is installed here. */
104
+ export function queues(t) {
105
+ const action = (id, verb, body, options) => t.json({
106
+ ...options,
107
+ method: "POST",
108
+ path: `/v1/queues/${encodeURIComponent(id)}:${verb}`,
109
+ body,
110
+ });
111
+ return {
112
+ ...recordResources(t, "queues"),
113
+ send: (id, input, options) => action(id, "send", input, options),
114
+ receive: (id, input = {}, options) => action(id, "receive", input, options),
115
+ ack: (id, input, options) => action(id, "ack", input, options),
116
+ retry: (id, input, options) => action(id, "retry", input, options),
117
+ /** Receive, handle, then acknowledge. No acknowledgement precedes success.
118
+ * A failed or cancelled handler releases its receipt at once. Aborting
119
+ * during receive can lose its reply; that lease expires without an ack.
120
+ * Settlement ignores the cancelled signal and has a bounded deadline.
121
+ * A lost settlement reply is retried once with the same key, even when
122
+ * transport retries were disabled. A remaining failure is thrown. */
123
+ async consume(id, handler, options = {}) {
124
+ const { max, waitSeconds = 20, visibilitySeconds, timeoutMs = 30_000 } = options;
125
+ for (const [field, value, minimum, maximum] of [
126
+ ["max", max, 0, Number.MAX_SAFE_INTEGER],
127
+ ["waitSeconds", waitSeconds, 0, 20],
128
+ ["visibilitySeconds", visibilitySeconds, 0, 43_200],
129
+ ["timeoutMs", timeoutMs, 1, 2_147_483_647],
130
+ ]) {
131
+ if (value !== undefined &&
132
+ (!Number.isSafeInteger(value) || value < minimum || value > maximum))
133
+ throw new RuntimeError({
134
+ code: "invalid_request",
135
+ status: 0,
136
+ message: `${field} must be an integer from ${minimum} to ${maximum}.`,
137
+ hint: "Correct the consume option; no message was received.",
138
+ });
139
+ }
140
+ const signal = options.signal ?? new AbortController().signal;
141
+ const result = { processed: 0, acknowledged: 0, retried: 0, aborted: false };
142
+ const settle = async (verb, body) => {
143
+ const request = { idempotencyKey: crypto.randomUUID(), timeoutMs };
144
+ try {
145
+ return await action(id, verb, body, request);
146
+ }
147
+ catch (error) {
148
+ if (!(error instanceof RuntimeError) ||
149
+ !["connection_error", "timeout"].includes(error.code))
150
+ throw error;
151
+ return action(id, verb, body, request);
152
+ }
153
+ };
154
+ while (!signal.aborted && (max === undefined || result.processed < max)) {
155
+ let received;
156
+ try {
157
+ received = await action(id, "receive", {
158
+ max: 1,
159
+ waitSeconds,
160
+ ...(visibilitySeconds === undefined ? {} : { visibilitySeconds }),
161
+ }, { signal, timeoutMs, idempotencyKey: crypto.randomUUID() });
162
+ }
163
+ catch (error) {
164
+ if (!signal.aborted)
165
+ throw error;
166
+ break;
167
+ }
168
+ if (received.messages.length > 1)
169
+ throw new RuntimeError({
170
+ code: "invalid_response",
171
+ status: 0,
172
+ message: "Receive returned more than the one message requested.",
173
+ hint: "No message was acknowledged; their visibility leases will expire.",
174
+ });
175
+ const message = received.messages[0];
176
+ if (!message) {
177
+ // Empty short polls must yield to cancellation and avoid a hot loop.
178
+ await pause(100, signal).catch(() => { });
179
+ continue;
180
+ }
181
+ let success = false;
182
+ if (!signal.aborted) {
183
+ result.processed++;
184
+ success = await handleMessage(handler, message, signal);
185
+ }
186
+ if (success && !signal.aborted) {
187
+ const ack = await settle("ack", {
188
+ receiptHandles: [message.receiptHandle],
189
+ });
190
+ const failed = ack.failed[0];
191
+ if (failed || !ack.successful.includes(message.receiptHandle))
192
+ throw new RuntimeError({
193
+ code: failed?.code ?? "invalid_response",
194
+ status: 0,
195
+ message: failed?.message ?? "The receipt was not acknowledged.",
196
+ hint: failed?.hint ??
197
+ "Do not assume delivery completed; this message can be delivered again.",
198
+ details: { receiptHandle: message.receiptHandle },
199
+ });
200
+ result.acknowledged++;
201
+ }
202
+ else {
203
+ await settle("retry", { receiptHandle: message.receiptHandle, visibilitySeconds: 0 });
204
+ result.retried++;
205
+ }
206
+ }
207
+ result.aborted = signal.aborted;
208
+ return result;
209
+ },
210
+ /** Purge returns the resource; follow its state with wait(id). */
211
+ purge: (id, options) => action(id, "purge", {}, options),
212
+ };
213
+ }
@@ -5,13 +5,16 @@ export type ReferralSummary = {
5
5
  code: string;
6
6
  /** Share this: https://withruntime.com/r/<code>. */
7
7
  link: string;
8
- /** The least each side gets: a first top-up is matched, never below this. */
8
+ /** The least each side gets on the referred company's first qualifying
9
+ * payment: a smaller one is matched up to this. */
9
10
  rewardMicros: string;
10
- /** The most each side gets: a first top-up is matched up to this. */
11
+ /** The most each side gets per referred company, all its matched payments
12
+ * together. */
11
13
  maxRewardMicros: string;
12
- /** The smallest first top-up that pays a referral. */
14
+ /** The smallest payment a referral matches. */
13
15
  minPurchaseMicros: string;
14
- /** The most referral credit you can earn in one calendar year (UTC). */
16
+ /** The most referral credit, matches and share together, you can earn in
17
+ * one calendar year (UTC). */
15
18
  yearlyCapMicros: string;
16
19
  enabled: boolean;
17
20
  year: number;
@@ -27,10 +30,21 @@ export type ReferralSummary = {
27
30
  status: "pending" | "paid" | "refused" | "reversed";
28
31
  creditMicros: string;
29
32
  } | null;
33
+ /** Referred companies with a matched payment still standing. */
34
+ payingCompanies: number;
35
+ /** Share credit you kept, all time. */
36
+ shareEarnedMicros: string;
37
+ /** Your share of what a referred company spends from credit it paid for,
38
+ * in basis points: 1000 is 10%. */
39
+ shareBasisPoints: number;
40
+ /** How long the share runs from a company's first matched payment. */
41
+ shareMonths: number;
42
+ /** How long after sign-up a referred company's payments are matched. */
43
+ windowDays: number;
30
44
  };
31
- /** `runtime.referrals.get()`: when a company that signs up with your link makes
32
- * its first top-up of at least $10, you and it each get credit equal to that
33
- * top-up, at least $25 and at most $500. */
45
+ /** `runtime.referrals`: a company that signs up with your link has every
46
+ * payment in its first 30 days matched, up to $1,000, and you get the same;
47
+ * then for 12 months you earn 10% of what it spends from credit it paid for. */
34
48
  export declare function referrals(t: Transport): {
35
49
  get: (options?: RequestOptions) => Promise<ReferralSummary>;
36
50
  };
@@ -1,6 +1,6 @@
1
- /** `runtime.referrals.get()`: when a company that signs up with your link makes
2
- * its first top-up of at least $10, you and it each get credit equal to that
3
- * top-up, at least $25 and at most $500. */
1
+ /** `runtime.referrals`: a company that signs up with your link has every
2
+ * payment in its first 30 days matched, up to $1,000, and you get the same;
3
+ * then for 12 months you earn 10% of what it spends from credit it paid for. */
4
4
  export function referrals(t) {
5
5
  return {
6
6
  get: (options) => t.json({ method: "GET", path: "/v1/referrals", ...options }),