simple-agents-wasm 0.3.11 → 0.4.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
@@ -36,7 +36,10 @@ import { Client } from "simple-agents-wasm";
36
36
 
37
37
  const client = new Client("openai", {
38
38
  apiKey: "<BYOK>",
39
- baseUrl: "https://api.openai.com/v1"
39
+ baseUrl: "https://api.openai.com/v1",
40
+ timeoutSeconds: 60,
41
+ retryAttempts: 3,
42
+ retryStrategy: "exponential"
40
43
  });
41
44
 
42
45
  const result = await client.complete("gpt-4o-mini", "Say hi in one line.");
package/index.d.ts CHANGED
@@ -112,6 +112,9 @@ export interface ClientConfig {
112
112
  apiKey: string;
113
113
  fetchImpl?: typeof fetch;
114
114
  headers?: Record<string, string>;
115
+ timeoutSeconds?: number;
116
+ retryAttempts?: number;
117
+ retryStrategy?: "none" | "fixed" | "exponential";
115
118
  }
116
119
 
117
120
  /** Matches Rust `YamlWorkflowTelemetryConfig` JSON (snake_case). */
@@ -210,6 +213,7 @@ export interface WorkflowExecutionFlags {
210
213
  workflow_streaming?: boolean;
211
214
  node_llm_streaming?: boolean;
212
215
  split_stream_deltas?: boolean;
216
+ debug_stream_parse?: boolean;
213
217
  }
214
218
 
215
219
  export interface WorkflowExecutionRequest {
package/index.js CHANGED
@@ -58,6 +58,105 @@ function assertWorkflowResultShape(result) {
58
58
  return result;
59
59
  }
60
60
 
61
+ function parseClientOptions(config) {
62
+ const timeoutSeconds = config.timeoutSeconds;
63
+ if (timeoutSeconds !== undefined) {
64
+ if (typeof timeoutSeconds !== "number" || !Number.isFinite(timeoutSeconds) || timeoutSeconds <= 0) {
65
+ throw configError("config.timeoutSeconds must be a positive finite number");
66
+ }
67
+ }
68
+
69
+ const retryAttempts = config.retryAttempts ?? 3;
70
+ if (!Number.isInteger(retryAttempts) || retryAttempts < 1) {
71
+ throw configError("config.retryAttempts must be greater than or equal to 1");
72
+ }
73
+
74
+ const retryStrategy = config.retryStrategy ?? "exponential";
75
+ if (!["none", "fixed", "exponential"].includes(retryStrategy)) {
76
+ throw configError("config.retryStrategy must be 'none', 'fixed', or 'exponential'");
77
+ }
78
+
79
+ return { timeoutSeconds, retryAttempts, retryStrategy };
80
+ }
81
+
82
+ function retryDelayMs(strategy, failedAttempt) {
83
+ if (strategy === "none") {
84
+ return 0;
85
+ }
86
+ const baseMs = 1000;
87
+ if (strategy === "fixed") {
88
+ return baseMs;
89
+ }
90
+ return Math.min(baseMs * (2 ** Math.max(0, failedAttempt - 1)), 10000);
91
+ }
92
+
93
+ function retryAfterMs(response) {
94
+ const header = response?.headers?.get?.("retry-after");
95
+ if (!header) {
96
+ return undefined;
97
+ }
98
+ const seconds = Number(header);
99
+ return Number.isFinite(seconds) && seconds >= 0 ? seconds * 1000 : undefined;
100
+ }
101
+
102
+ function isRetryableResponse(response) {
103
+ const status = Number(response?.status ?? 0);
104
+ return status === 429 || (status >= 500 && status <= 599);
105
+ }
106
+
107
+ function sleep(ms) {
108
+ return new Promise((resolve) => setTimeout(resolve, ms));
109
+ }
110
+
111
+ function createManagedFetch(fetchImpl, options) {
112
+ const sourceFetch = typeof fetchImpl === "function" ? fetchImpl : globalThis.fetch;
113
+ if (typeof sourceFetch !== "function") {
114
+ throw configError("fetch is unavailable; pass config.fetchImpl");
115
+ }
116
+
117
+ return async function managedFetch(input, init = {}) {
118
+ let attempt = 1;
119
+ while (true) {
120
+ const controller = options.timeoutSeconds && typeof AbortController === "function"
121
+ ? new AbortController()
122
+ : undefined;
123
+ const timeoutId = controller
124
+ ? setTimeout(() => controller.abort(), options.timeoutSeconds * 1000)
125
+ : undefined;
126
+ const requestInit = controller ? { ...init, signal: controller.signal } : init;
127
+
128
+ try {
129
+ const response = await sourceFetch(input, requestInit);
130
+ if (
131
+ attempt >= options.retryAttempts
132
+ || options.retryStrategy === "none"
133
+ || !isRetryableResponse(response)
134
+ ) {
135
+ return response;
136
+ }
137
+ const delay = retryAfterMs(response) ?? retryDelayMs(options.retryStrategy, attempt);
138
+ if (delay > 0) {
139
+ await sleep(delay);
140
+ }
141
+ attempt += 1;
142
+ } catch (error) {
143
+ if (attempt >= options.retryAttempts || options.retryStrategy === "none") {
144
+ throw error;
145
+ }
146
+ const delay = retryDelayMs(options.retryStrategy, attempt);
147
+ if (delay > 0) {
148
+ await sleep(delay);
149
+ }
150
+ attempt += 1;
151
+ } finally {
152
+ if (timeoutId !== undefined) {
153
+ clearTimeout(timeoutId);
154
+ }
155
+ }
156
+ }
157
+ };
158
+ }
159
+
61
160
  function normalizeWorkflowResult(result) {
62
161
  if (result === null || typeof result !== "object") {
63
162
  return result;
@@ -108,7 +207,12 @@ export class Client {
108
207
  }
109
208
 
110
209
  this.provider = provider;
111
- this.config = config;
210
+ const clientOptions = parseClientOptions(config);
211
+ this.config = {
212
+ ...config,
213
+ fetchImpl: createManagedFetch(config.fetchImpl, clientOptions),
214
+ };
215
+ this.clientOptions = clientOptions;
112
216
  this.rustClient = null;
113
217
  this.readyPromise = null;
114
218
  this.fetchOverrideQueue = Promise.resolve();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simple-agents-wasm",
3
- "version": "0.3.11",
3
+ "version": "0.4.0",
4
4
  "description": "Browser-compatible SimpleAgents client for OpenAI-compatible providers",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -36,9 +36,9 @@ export interface InitOutput {
36
36
  readonly wasmclient_runWorkflowYamlString: (a: number, b: number, c: number, d: any, e: number) => any;
37
37
  readonly wasmclient_runYamlString: (a: number, b: number, c: number, d: any, e: number) => any;
38
38
  readonly wasmclient_streamEvents: (a: number, b: number, c: number, d: any, e: any, f: number) => any;
39
- readonly wasm_bindgen__convert__closures_____invoke__h9f53f643b01d7c8e: (a: number, b: number, c: any) => [number, number];
40
- readonly wasm_bindgen__convert__closures_____invoke__h05acb8c479b21d4b: (a: number, b: number, c: any, d: any) => void;
41
- readonly wasm_bindgen__convert__closures_____invoke__h8bdb42cdb6bde112: (a: number, b: number, c: any) => void;
39
+ readonly wasm_bindgen__convert__closures_____invoke__h327a4c82efcf6931: (a: number, b: number, c: any) => [number, number];
40
+ readonly wasm_bindgen__convert__closures_____invoke__h67e61867e7d8792e: (a: number, b: number, c: any, d: any) => void;
41
+ readonly wasm_bindgen__convert__closures_____invoke__h5cfabd7a8f920681: (a: number, b: number, c: any) => void;
42
42
  readonly __wbindgen_malloc: (a: number, b: number) => number;
43
43
  readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
44
44
  readonly __wbindgen_exn_store: (a: number) => void;
@@ -329,7 +329,7 @@ function __wbg_get_imports() {
329
329
  const a = state0.a;
330
330
  state0.a = 0;
331
331
  try {
332
- return wasm_bindgen__convert__closures_____invoke__h05acb8c479b21d4b(a, state0.b, arg0, arg1);
332
+ return wasm_bindgen__convert__closures_____invoke__h67e61867e7d8792e(a, state0.b, arg0, arg1);
333
333
  } finally {
334
334
  state0.a = a;
335
335
  }
@@ -410,12 +410,12 @@ function __wbg_get_imports() {
410
410
  },
411
411
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
412
412
  // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 157, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
413
- const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h9f53f643b01d7c8e);
413
+ const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h327a4c82efcf6931);
414
414
  return ret;
415
415
  },
416
416
  __wbindgen_cast_0000000000000002: function(arg0, arg1) {
417
- // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 78, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
418
- const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h8bdb42cdb6bde112);
417
+ // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 68, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
418
+ const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h5cfabd7a8f920681);
419
419
  return ret;
420
420
  },
421
421
  __wbindgen_cast_0000000000000003: function(arg0) {
@@ -454,19 +454,19 @@ function __wbg_get_imports() {
454
454
  };
455
455
  }
456
456
 
457
- function wasm_bindgen__convert__closures_____invoke__h8bdb42cdb6bde112(arg0, arg1, arg2) {
458
- wasm.wasm_bindgen__convert__closures_____invoke__h8bdb42cdb6bde112(arg0, arg1, arg2);
457
+ function wasm_bindgen__convert__closures_____invoke__h5cfabd7a8f920681(arg0, arg1, arg2) {
458
+ wasm.wasm_bindgen__convert__closures_____invoke__h5cfabd7a8f920681(arg0, arg1, arg2);
459
459
  }
460
460
 
461
- function wasm_bindgen__convert__closures_____invoke__h9f53f643b01d7c8e(arg0, arg1, arg2) {
462
- const ret = wasm.wasm_bindgen__convert__closures_____invoke__h9f53f643b01d7c8e(arg0, arg1, arg2);
461
+ function wasm_bindgen__convert__closures_____invoke__h327a4c82efcf6931(arg0, arg1, arg2) {
462
+ const ret = wasm.wasm_bindgen__convert__closures_____invoke__h327a4c82efcf6931(arg0, arg1, arg2);
463
463
  if (ret[1]) {
464
464
  throw takeFromExternrefTable0(ret[0]);
465
465
  }
466
466
  }
467
467
 
468
- function wasm_bindgen__convert__closures_____invoke__h05acb8c479b21d4b(arg0, arg1, arg2, arg3) {
469
- wasm.wasm_bindgen__convert__closures_____invoke__h05acb8c479b21d4b(arg0, arg1, arg2, arg3);
468
+ function wasm_bindgen__convert__closures_____invoke__h67e61867e7d8792e(arg0, arg1, arg2, arg3) {
469
+ wasm.wasm_bindgen__convert__closures_____invoke__h67e61867e7d8792e(arg0, arg1, arg2, arg3);
470
470
  }
471
471
 
472
472
  const WasmClientFinalization = (typeof FinalizationRegistry === 'undefined')
Binary file
@@ -9,9 +9,9 @@ export const wasmclient_runWorkflowYaml: (a: number, b: number, c: number, d: an
9
9
  export const wasmclient_runWorkflowYamlString: (a: number, b: number, c: number, d: any, e: number) => any;
10
10
  export const wasmclient_runYamlString: (a: number, b: number, c: number, d: any, e: number) => any;
11
11
  export const wasmclient_streamEvents: (a: number, b: number, c: number, d: any, e: any, f: number) => any;
12
- export const wasm_bindgen__convert__closures_____invoke__h9f53f643b01d7c8e: (a: number, b: number, c: any) => [number, number];
13
- export const wasm_bindgen__convert__closures_____invoke__h05acb8c479b21d4b: (a: number, b: number, c: any, d: any) => void;
14
- export const wasm_bindgen__convert__closures_____invoke__h8bdb42cdb6bde112: (a: number, b: number, c: any) => void;
12
+ export const wasm_bindgen__convert__closures_____invoke__h327a4c82efcf6931: (a: number, b: number, c: any) => [number, number];
13
+ export const wasm_bindgen__convert__closures_____invoke__h67e61867e7d8792e: (a: number, b: number, c: any, d: any) => void;
14
+ export const wasm_bindgen__convert__closures_____invoke__h5cfabd7a8f920681: (a: number, b: number, c: any) => void;
15
15
  export const __wbindgen_malloc: (a: number, b: number) => number;
16
16
  export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
17
17
  export const __wbindgen_exn_store: (a: number) => void;
package/rust/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "simple-agents-wasm-rust"
3
- version = "0.3.11"
3
+ version = "0.4.0"
4
4
  edition = "2021"
5
5
  license = "MIT OR Apache-2.0"
6
6