@managoat/fountain-sdk 1.28.0 → 1.30.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/CHANGELOG.md CHANGED
@@ -11,6 +11,21 @@ server releases.
11
11
 
12
12
  ---
13
13
 
14
+ ## [1.30.0] - 2026-09-11
15
+
16
+ ### Added
17
+
18
+ - Generated types carry a conversation's `pending_requests`, the permission requests that outlived a turn and are still waiting for an answer. Each entry has the request id, the tool, the options the agent offered, when it was asked and when it expires.
19
+ - Generated types carry a turn's `waiting`, true when the turn ended with such a request still open.
20
+ - `permission_policy` accepts `ask_timeout`, a number of seconds a request that outlived its turn waits before it is denied. It is the one policy key whose value is a number rather than a verdict, so the value type is now a union of the verdict enum and a number.
21
+
22
+ ## [1.29.0] - 2026-09-11
23
+
24
+ ### Changed
25
+
26
+ - Generated types carry `queue` on a conversation create, and the `SandboxRequest` shape a queued start answers with (ADR 0042). At the tenant sandbox cap or the fleet ceiling, a start that sets `queue: true` gets 202 and a request id instead of 429 or 503.
27
+ - `/api/sandbox-queue` is deliberately not wrapped. The run handle promises an immediate conversation, and a queued start hands back a request first; reach the three routes over the raw HTTP client until a queued-run handle owns the polling and the cancellation.
28
+
14
29
  ## [1.28.0] - 2026-09-10
15
30
 
16
31
  ### Added
@@ -1306,6 +1306,8 @@ export interface paths {
1306
1306
  * @description Answers a `session/request_permission` the agent is blocked on (#940). The request and its options arrive as a `permission_request` block on the conversation's event stream; `option_id` must be one of the `optionId` values that block carried. Never send an option the agent did not offer.
1307
1307
  *
1308
1308
  * First answer wins: another attached client, the timeout, or the turn ending may already have resolved it, and all of those return 409. The resolution appears on the stream as a `request` stage event with state `done`.
1309
+ *
1310
+ * A request that outlived its turn (#1635) is answered here too. The agent ended that turn with stop reason `waiting`, so the conversation is idle and the sandbox may be suspended; GET /api/conversations/{id} lists such requests as `pending_requests`. Answering one resolves it and opens a new turn carrying the request id and the option, which wakes the sandbox.
1309
1311
  */
1310
1312
  post: operations["FountainWeb.ConversationController.answer_request"];
1311
1313
  delete?: never;
@@ -1687,6 +1689,50 @@ export interface paths {
1687
1689
  patch?: never;
1688
1690
  trace?: never;
1689
1691
  };
1692
+ "/api/sandbox-queue": {
1693
+ parameters: {
1694
+ query?: never;
1695
+ header?: never;
1696
+ path?: never;
1697
+ cookie?: never;
1698
+ };
1699
+ /**
1700
+ * List queued sandbox requests
1701
+ * @description The caller's waiting requests, oldest first, each with its one-based position. Only requests that are still waiting appear here. One the drainer has already claimed is not listed, and neither is one that finished; read either by id instead.
1702
+ */
1703
+ get: operations["FountainWeb.SandboxQueueController.index"];
1704
+ put?: never;
1705
+ post?: never;
1706
+ delete?: never;
1707
+ options?: never;
1708
+ head?: never;
1709
+ patch?: never;
1710
+ trace?: never;
1711
+ };
1712
+ "/api/sandbox-queue/{id}": {
1713
+ parameters: {
1714
+ query?: never;
1715
+ header?: never;
1716
+ path?: never;
1717
+ cookie?: never;
1718
+ };
1719
+ /**
1720
+ * Get a sandbox request
1721
+ * @description The request's current status. `conversation_id` is set once it started; `error` says why if it failed. A request nobody else owns reads as 404.
1722
+ */
1723
+ get: operations["FountainWeb.SandboxQueueController.show"];
1724
+ put?: never;
1725
+ post?: never;
1726
+ /**
1727
+ * Cancel a queued sandbox request
1728
+ * @description Gives up a request that is still waiting. A request the drainer has already claimed reads as 404 rather than being cancelled out from under a start in flight.
1729
+ */
1730
+ delete: operations["FountainWeb.SandboxQueueController.delete"];
1731
+ options?: never;
1732
+ head?: never;
1733
+ patch?: never;
1734
+ trace?: never;
1735
+ };
1690
1736
  "/api/sandboxes": {
1691
1737
  parameters: {
1692
1738
  query?: never;
@@ -3618,6 +3664,8 @@ export interface components {
3618
3664
  last_read_at?: string | null;
3619
3665
  /** Format: uuid */
3620
3666
  parent_conversation_id?: string | null;
3667
+ /** @description Permission requests that outlived a turn and are still waiting for an answer (#1635). Served on GET /api/conversations/{id} only; absent from the list and from the create response. */
3668
+ pending_requests?: components["schemas"]["PendingPermissionRequest"][];
3621
3669
  /** @description The per-launch permission override this conversation was started with, or null if it had none. The policy actually in force is this merged with the agent's, taking the stricter of the two per tool. */
3622
3670
  permission_policy?: ({
3623
3671
  /** @description Seconds a permission request that outlived its turn waits before it is denied (#1635). Names no tool, so it is the one key whose value is a number rather than a verdict, which is why the value schema below is a union. Absent leaves the global ask timeout. A request may shorten it with `_meta.fountain.timeout` on its own session/request_permission, and may not lengthen it. A launch may only shorten what the agent set, or the global ask timeout where the agent set nothing. Capped at a year, which is where the deadline stops fitting in a timestamp rather than a limit on how long a wait is useful. */
@@ -4192,6 +4240,28 @@ export interface components {
4192
4240
  /** @description From the reset email. */
4193
4241
  token: string;
4194
4242
  };
4243
+ /**
4244
+ * PendingPermissionRequest
4245
+ * @description A permission request that outlived its turn (#1635). The agent ended the turn with stop reason `waiting` while this request was open, so the conversation is idle, the sandbox may be suspended, and the request is still waiting for an answer. Answer it at POST /api/conversations/{id}/requests/{request_id}, which resolves it and opens a new turn carrying the outcome to the agent.
4246
+ */
4247
+ PendingPermissionRequest: {
4248
+ /** Format: date-time */
4249
+ asked_at?: string | null;
4250
+ /**
4251
+ * Format: date-time
4252
+ * @description When the request is denied for want of an answer. Set from the request's own `_meta.fountain.timeout`, else the policy's `ask_timeout`, else the global ask timeout.
4253
+ */
4254
+ deadline?: string | null;
4255
+ /** @description The options the agent offered, verbatim. `option_id` must be one of these `optionId` values; an id from another runtime is refused. */
4256
+ options: {
4257
+ [key: string]: unknown;
4258
+ }[];
4259
+ request_id: string;
4260
+ /** @description The tool the agent asked about, as the transcript labels it. */
4261
+ tool?: string | null;
4262
+ /** Format: uuid */
4263
+ turn_id?: string;
4264
+ };
4195
4265
  /** PermissionAnswerRequest */
4196
4266
  PermissionAnswerRequest: {
4197
4267
  /** @description One of the `optionId` values from the request's own `options` list, as carried on the `permission_request` block. An id the agent did not offer is refused (422 unknown_option) rather than forwarded. */
@@ -4538,6 +4608,10 @@ export interface components {
4538
4608
  /** @enum {string} */
4539
4609
  status: "queued" | "starting" | "started" | "cancelled" | "expired" | "failed";
4540
4610
  };
4611
+ /** SandboxRequestListResponse */
4612
+ SandboxRequestListResponse: {
4613
+ data: components["schemas"]["SandboxRequest"][];
4614
+ };
4541
4615
  /** SandboxRequestResponse */
4542
4616
  SandboxRequestResponse: {
4543
4617
  data: components["schemas"]["SandboxRequest"];
@@ -5015,6 +5089,8 @@ export interface components {
5015
5089
  turn_number: number;
5016
5090
  /** @description The end-of-turn token figure; null while the turn runs, when the runtime reported none, or on turns that predate the field. */
5017
5091
  usage?: components["schemas"]["TurnUsage"] | null;
5092
+ /** @description The turn ended with a permission request still open (#1635): the agent answered with stop reason `waiting`, the turn is `completed` and the request is on the conversation as a `pending_requests` entry. */
5093
+ waiting?: boolean;
5018
5094
  };
5019
5095
  /** TurnListResponse */
5020
5096
  TurnListResponse: {
@@ -11099,6 +11175,15 @@ export interface operations {
11099
11175
  "application/json": components["schemas"]["PermissionAnswerResponse"];
11100
11176
  };
11101
11177
  };
11178
+ /** @description Busy */
11179
+ 400: {
11180
+ headers: {
11181
+ [name: string]: unknown;
11182
+ };
11183
+ content: {
11184
+ "application/json": components["schemas"]["Error"];
11185
+ };
11186
+ };
11102
11187
  /** @description Unauthorized */
11103
11188
  401: {
11104
11189
  headers: {
@@ -11108,7 +11193,16 @@ export interface operations {
11108
11193
  "application/json": components["schemas"]["Error"];
11109
11194
  };
11110
11195
  };
11111
- /** @description Forbidden */
11196
+ /** @description Insufficient credits */
11197
+ 402: {
11198
+ headers: {
11199
+ [name: string]: unknown;
11200
+ };
11201
+ content: {
11202
+ "application/json": components["schemas"]["Error"];
11203
+ };
11204
+ };
11205
+ /** @description The sandbox may not answer */
11112
11206
  403: {
11113
11207
  headers: {
11114
11208
  [name: string]: unknown;
@@ -11135,7 +11229,7 @@ export interface operations {
11135
11229
  "application/json": components["schemas"]["NegotiationError"];
11136
11230
  };
11137
11231
  };
11138
- /** @description Already resolved */
11232
+ /** @description Already resolved, or resolved but not delivered */
11139
11233
  409: {
11140
11234
  headers: {
11141
11235
  [name: string]: unknown;
@@ -12992,6 +13086,194 @@ export interface operations {
12992
13086
  };
12993
13087
  };
12994
13088
  };
13089
+ "FountainWeb.SandboxQueueController.index": {
13090
+ parameters: {
13091
+ query?: never;
13092
+ header?: never;
13093
+ path?: never;
13094
+ cookie?: never;
13095
+ };
13096
+ requestBody?: never;
13097
+ responses: {
13098
+ /** @description Sandbox requests */
13099
+ 200: {
13100
+ headers: {
13101
+ [name: string]: unknown;
13102
+ };
13103
+ content: {
13104
+ "application/json": components["schemas"]["SandboxRequestListResponse"];
13105
+ };
13106
+ };
13107
+ /** @description Unauthorized */
13108
+ 401: {
13109
+ headers: {
13110
+ [name: string]: unknown;
13111
+ };
13112
+ content: {
13113
+ "application/json": components["schemas"]["Error"];
13114
+ };
13115
+ };
13116
+ /** @description Forbidden */
13117
+ 403: {
13118
+ headers: {
13119
+ [name: string]: unknown;
13120
+ };
13121
+ content: {
13122
+ "application/json": components["schemas"]["Error"];
13123
+ };
13124
+ };
13125
+ /** @description No acceptable representation */
13126
+ 406: {
13127
+ headers: {
13128
+ [name: string]: unknown;
13129
+ };
13130
+ content: {
13131
+ "application/json": components["schemas"]["NegotiationError"];
13132
+ };
13133
+ };
13134
+ /** @description Too Many Requests */
13135
+ 429: {
13136
+ headers: {
13137
+ [name: string]: unknown;
13138
+ };
13139
+ content: {
13140
+ "application/json": components["schemas"]["Error"];
13141
+ };
13142
+ };
13143
+ };
13144
+ };
13145
+ "FountainWeb.SandboxQueueController.show": {
13146
+ parameters: {
13147
+ query?: never;
13148
+ header?: never;
13149
+ path: {
13150
+ id: string;
13151
+ };
13152
+ cookie?: never;
13153
+ };
13154
+ requestBody?: never;
13155
+ responses: {
13156
+ /** @description Sandbox request */
13157
+ 200: {
13158
+ headers: {
13159
+ [name: string]: unknown;
13160
+ };
13161
+ content: {
13162
+ "application/json": components["schemas"]["SandboxRequestResponse"];
13163
+ };
13164
+ };
13165
+ /** @description Unauthorized */
13166
+ 401: {
13167
+ headers: {
13168
+ [name: string]: unknown;
13169
+ };
13170
+ content: {
13171
+ "application/json": components["schemas"]["Error"];
13172
+ };
13173
+ };
13174
+ /** @description Forbidden */
13175
+ 403: {
13176
+ headers: {
13177
+ [name: string]: unknown;
13178
+ };
13179
+ content: {
13180
+ "application/json": components["schemas"]["Error"];
13181
+ };
13182
+ };
13183
+ /** @description Not found */
13184
+ 404: {
13185
+ headers: {
13186
+ [name: string]: unknown;
13187
+ };
13188
+ content: {
13189
+ "application/json": components["schemas"]["Error"];
13190
+ };
13191
+ };
13192
+ /** @description No acceptable representation */
13193
+ 406: {
13194
+ headers: {
13195
+ [name: string]: unknown;
13196
+ };
13197
+ content: {
13198
+ "application/json": components["schemas"]["NegotiationError"];
13199
+ };
13200
+ };
13201
+ /** @description Too Many Requests */
13202
+ 429: {
13203
+ headers: {
13204
+ [name: string]: unknown;
13205
+ };
13206
+ content: {
13207
+ "application/json": components["schemas"]["Error"];
13208
+ };
13209
+ };
13210
+ };
13211
+ };
13212
+ "FountainWeb.SandboxQueueController.delete": {
13213
+ parameters: {
13214
+ query?: never;
13215
+ header?: never;
13216
+ path: {
13217
+ id: string;
13218
+ };
13219
+ cookie?: never;
13220
+ };
13221
+ requestBody?: never;
13222
+ responses: {
13223
+ /** @description Cancelled */
13224
+ 204: {
13225
+ headers: {
13226
+ [name: string]: unknown;
13227
+ };
13228
+ content?: never;
13229
+ };
13230
+ /** @description Unauthorized */
13231
+ 401: {
13232
+ headers: {
13233
+ [name: string]: unknown;
13234
+ };
13235
+ content: {
13236
+ "application/json": components["schemas"]["Error"];
13237
+ };
13238
+ };
13239
+ /** @description Forbidden */
13240
+ 403: {
13241
+ headers: {
13242
+ [name: string]: unknown;
13243
+ };
13244
+ content: {
13245
+ "application/json": components["schemas"]["Error"];
13246
+ };
13247
+ };
13248
+ /** @description Not found or no longer queued */
13249
+ 404: {
13250
+ headers: {
13251
+ [name: string]: unknown;
13252
+ };
13253
+ content: {
13254
+ "application/json": components["schemas"]["Error"];
13255
+ };
13256
+ };
13257
+ /** @description No acceptable representation */
13258
+ 406: {
13259
+ headers: {
13260
+ [name: string]: unknown;
13261
+ };
13262
+ content: {
13263
+ "application/json": components["schemas"]["NegotiationError"];
13264
+ };
13265
+ };
13266
+ /** @description Too Many Requests */
13267
+ 429: {
13268
+ headers: {
13269
+ [name: string]: unknown;
13270
+ };
13271
+ content: {
13272
+ "application/json": components["schemas"]["Error"];
13273
+ };
13274
+ };
13275
+ };
13276
+ };
12995
13277
  "FountainWeb.SandboxController.index": {
12996
13278
  parameters: {
12997
13279
  query?: {
package/dist/http.d.ts CHANGED
@@ -15,7 +15,7 @@ export interface RequestOptions {
15
15
  * this string is already what Fountain's request logs are keyed on. The
16
16
  * version half is asserted against `package.json` by a test.
17
17
  */
18
- export declare const USER_AGENT = "fountain-sdk-js/1.28.0";
18
+ export declare const USER_AGENT = "fountain-sdk-js/1.30.0";
19
19
  export declare class HttpClient {
20
20
  readonly config: ResolvedConfig;
21
21
  private readonly fetchImpl;
package/dist/http.js CHANGED
@@ -5,7 +5,7 @@ import { AuthError, ConnectionError, FountainError, errorForStatus } from "./err
5
5
  * this string is already what Fountain's request logs are keyed on. The
6
6
  * version half is asserted against `package.json` by a test.
7
7
  */
8
- export const USER_AGENT = "fountain-sdk-js/1.28.0";
8
+ export const USER_AGENT = "fountain-sdk-js/1.30.0";
9
9
  /**
10
10
  * The thin layer everything else is built on: one bearer token, JSON in and
11
11
  * out, and errors that say which call failed. `Fountain#api` exposes it
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@managoat/fountain-sdk",
3
- "version": "1.28.0",
3
+ "version": "1.30.0",
4
4
  "description": "Run a coding agent on a real computer, with your repos and your credentials, in one call.",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {