daishi-sdk 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -38,7 +38,7 @@ Seats play on the provider keys stored on your account. Every plan can read and
38
38
 
39
39
  - **One method per API operation**, named after its operation id: `getRun`, `listRuns`, `launch`, `cancel`, `getBatch`, `createScenario`, `createExperiment`, `getExperiment` and the rest. Request bodies and responses are typed from the API's OpenAPI document.
40
40
  - **Errors** throw `DaishiError` with the API's `code` (`unknown_run`, `plan_quota`, ...), `status`, `message`, `retryAfterSeconds`, and `docs`, a link to what the code means.
41
- - **Retries** are safe by construction. A 429 is retried after the seconds its `Retry-After` header names, and a cancel refused with `run_launching` after a pause, on any method, because the server refused before doing anything. A gateway error or a dropped connection is retried on GET only, so a write is never sent twice.
41
+ - **Retries** are safe by construction. A 429 is retried after the seconds its `Retry-After` header names, and a cancel refused with `run_launching` after a pause, on any method, because the server refused before doing anything. So is a `503 handover`, the few seconds a deploy moves the world to a new release: the old release refuses every write before reading it. Any other gateway error or a dropped connection is retried on GET only, so a write is never sent twice.
42
42
  - **Waiting.** `waitForRun`, `waitForBatch` and `waitForExperiment` poll every 30 seconds until the run, batch or experiment ends. `waitForRun` also waits for a finished run's results, which arrive when the match archives. Pass `signal: AbortSignal.timeout(ms)` for a deadline. To be told instead of asking, set up [run-end notices](https://daishi.ai/docs/developer/runs#run-end-notices).
43
43
 
44
44
  ```ts
@@ -5,7 +5,7 @@ export type JsonObject = {
5
5
  /** The API version these types describe. */
6
6
  export declare const API_VERSION = "1.0.0";
7
7
  /** Every error code the API documents. */
8
- export type ErrorCode = 'token_required' | 'scope_required' | 'plan_api' | 'rate_limited' | 'bad_request' | 'bad_scenario' | 'bad_replicates' | 'profile_required' | 'bad_season_ticks' | 'bad_frame' | 'bad_env' | 'too_many_scenarios' | 'unknown_scenario' | 'bad_skill' | 'too_many_skills' | 'unknown_skill' | 'bad_roster' | 'bad_model' | 'bad_name' | 'bad_provider' | 'provider_key_required' | 'openrouter_key_required' | 'openrouter_balance_low' | 'billing_frozen' | 'email_unverified' | 'bad_trials' | 'bad_spend_cap' | 'plan_seats' | 'plan_ticks' | 'plan_series' | 'plan_quota' | 'too_many_runs' | 'run_history_full' | 'seed_not_allowed' | 'unknown_run' | 'unknown_batch' | 'unknown_experiment' | 'experiment_trial' | 'experiment_not_running' | 'experiment_arms' | 'bad_experiment' | 'experiment_scenario' | 'experiment_world_only' | 'experiment_env_seed' | 'experiment_stopping' | 'bad_metric' | 'bad_design' | 'design_final' | 'design_late' | 'no_design' | 'experiment_effort_roster' | 'plan_experiment_arms' | 'plan_rerun' | 'unknown_log' | 'plan_invites' | 'invite_world' | 'invite_series' | 'too_many_open_worlds' | 'no_invite' | 'invite_fixed' | 'bad_invite' | 'never_played' | 'run_playing' | 'bad_note' | 'note_too_long' | 'run_launching' | 'internal_error';
8
+ export type ErrorCode = 'token_required' | 'scope_required' | 'plan_api' | 'rate_limited' | 'handover' | 'bad_request' | 'bad_scenario' | 'bad_replicates' | 'profile_required' | 'bad_season_ticks' | 'bad_frame' | 'bad_env' | 'too_many_scenarios' | 'unknown_scenario' | 'bad_skill' | 'too_many_skills' | 'unknown_skill' | 'bad_roster' | 'bad_model' | 'bad_name' | 'bad_provider' | 'provider_key_required' | 'openrouter_key_required' | 'openrouter_balance_low' | 'billing_frozen' | 'email_unverified' | 'bad_trials' | 'bad_spend_cap' | 'plan_seats' | 'plan_ticks' | 'plan_series' | 'plan_quota' | 'too_many_runs' | 'run_history_full' | 'seed_not_allowed' | 'unknown_run' | 'unknown_batch' | 'unknown_experiment' | 'experiment_trial' | 'experiment_not_running' | 'experiment_arms' | 'bad_experiment' | 'experiment_scenario' | 'experiment_world_only' | 'experiment_env_seed' | 'experiment_stopping' | 'bad_metric' | 'bad_design' | 'design_final' | 'design_late' | 'no_design' | 'experiment_effort_roster' | 'plan_experiment_arms' | 'plan_rerun' | 'unknown_log' | 'plan_invites' | 'invite_world' | 'invite_series' | 'too_many_open_worlds' | 'no_invite' | 'invite_fixed' | 'bad_invite' | 'never_played' | 'run_playing' | 'bad_note' | 'note_too_long' | 'run_launching' | 'internal_error';
9
9
  export type Method = 'GET' | 'POST' | 'PUT' | 'DELETE';
10
10
  export interface RequestParts {
11
11
  query?: Record<string, string | number | boolean | undefined | null>;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Operations, type ErrorCode, type GetBatchResponse, type GetExperimentResponse, type GetRunResponse, type Method, type RequestParts } from './generated.js';
2
2
  export * from './generated.js';
3
- export declare const VERSION = "0.2.5";
3
+ export declare const VERSION = "0.2.6";
4
4
  export declare const DEFAULT_BASE_URL = "https://daishi.ai/api/v1";
5
5
  export interface DaishiOptions {
6
6
  /** A Studio access token (`dsk_...`). Default: the `DAISHI_TOKEN` environment variable. */
@@ -52,9 +52,11 @@ export declare class DaishiError extends Error {
52
52
  *
53
53
  * Retries: a 429 is retried after the seconds its `Retry-After` names, and
54
54
  * a `run_launching` refusal after a short pause, on any method, because the
55
- * server refused before doing anything. A gateway error (502, 503, 504) or
56
- * a dropped connection is retried on GET only: a write that may have landed
57
- * is never sent twice.
55
+ * server refused before doing anything. So is a `503 handover`: for the few
56
+ * seconds a deploy moves the world to a new release, the old one refuses
57
+ * every write before reading it, and says so in that code. Any other gateway
58
+ * error (502, 503, 504) or a dropped connection is retried on GET only: a
59
+ * write that may have landed is never sent twice.
58
60
  */
59
61
  export declare class Daishi extends Operations {
60
62
  readonly baseUrl: string;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Operations } from './generated.js';
2
2
  export * from './generated.js';
3
- export const VERSION = '0.2.5';
3
+ export const VERSION = '0.2.6';
4
4
  export const DEFAULT_BASE_URL = 'https://daishi.ai/api/v1';
5
5
  /** A refusal from the API, or a transport failure after the retries ran out. */
6
6
  export class DaishiError extends Error {
@@ -56,9 +56,11 @@ function envToken() {
56
56
  *
57
57
  * Retries: a 429 is retried after the seconds its `Retry-After` names, and
58
58
  * a `run_launching` refusal after a short pause, on any method, because the
59
- * server refused before doing anything. A gateway error (502, 503, 504) or
60
- * a dropped connection is retried on GET only: a write that may have landed
61
- * is never sent twice.
59
+ * server refused before doing anything. So is a `503 handover`: for the few
60
+ * seconds a deploy moves the world to a new release, the old one refuses
61
+ * every write before reading it, and says so in that code. Any other gateway
62
+ * error (502, 503, 504) or a dropped connection is retried on GET only: a
63
+ * write that may have landed is never sent twice.
62
64
  */
63
65
  export class Daishi extends Operations {
64
66
  baseUrl;
@@ -113,7 +115,7 @@ export class Daishi extends Operations {
113
115
  }
114
116
  const code = parsed?.error ?? `http_${res.status}`;
115
117
  const retryAfter = parseRetryAfter(res.headers.get('retry-after'));
116
- const retryable = res.status === 429 || code === 'run_launching' || (method === 'GET' && GATEWAY.has(res.status));
118
+ const retryable = res.status === 429 || code === 'run_launching' || code === 'handover' || (method === 'GET' && GATEWAY.has(res.status));
117
119
  if (retryable && canRetry) {
118
120
  await sleep(retryAfter !== null ? retryAfter * 1000 : backoffMs(attempt));
119
121
  continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "daishi-sdk",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "Typed client for the Daishi Studio API: scenarios, runs, series batches and paired experiments, with retries and waiting helpers.",
5
5
  "keywords": [
6
6
  "daishi",