@method-ai-hq/sdk 0.18.0 → 0.18.1

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
@@ -3,7 +3,7 @@
3
3
  MIT-licensed JavaScript API and the `method` CLI. Source and releases: https://github.com/method-ai-hq/method-sdk
4
4
 
5
5
  ```sh
6
- npm install https://github.com/method-ai-hq/method-sdk/releases/download/v0.18.0/method-ai-hq-sdk-0.18.0.tgz
6
+ npm install https://github.com/method-ai-hq/method-sdk/releases/download/v0.18.1/method-ai-hq-sdk-0.18.1.tgz
7
7
  npx method --version
8
8
  ```
9
9
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@method-ai-hq/sdk",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
4
4
  "description": "Build and run reusable .method files with checked steps and saved results.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -79,8 +79,14 @@ export async function runCurrentFile(file, flags, syncFactory, onEvent, client =
79
79
  catch (error) {
80
80
  process.stderr.write(`Run records stay on this computer: ${error.message}\n`);
81
81
  }
82
- // Records the start; sends nothing. The outbox starts when the run starts.
83
- await sync?.start(method, json(flags.inputs) ?? {}, {}, false);
82
+ // Records the start; sends nothing. The outbox starts when the run starts. An inputs file that cannot be read fails
83
+ // the run below, with this record and no inputs.
84
+ let inputs = {};
85
+ try {
86
+ inputs = json(flags.inputs) ?? {};
87
+ }
88
+ catch { /* the run's setup failure */ }
89
+ await sync?.start(method, inputs, {}, false);
84
90
  // A run with its own OpenRouter key (config.classification.api_key_env) needs no Method sign-in for classification.
85
91
  const needs = accountNeeds(method, config);
86
92
  const classification = needs.classification ? managedClassification(client) : undefined;
@@ -22,6 +22,8 @@ export declare class MethodClient {
22
22
  onProgress?: (sent: number) => void;
23
23
  attempts?: number;
24
24
  }): Promise<Uint8Array>;
25
+ /** A lost connection: code network, and the message says which server. */
26
+ private unreachable;
25
27
  /** Send bytes in chunks and read the answer in chunks; a watchdog aborts when no bytes moved for stallMs. */
26
28
  private send;
27
29
  login(openBrowser?: (url: string) => void): Promise<void>;
@@ -75,7 +75,7 @@ export class MethodClient {
75
75
  continue;
76
76
  }
77
77
  if (lost)
78
- throw Object.assign(Error(`Method cannot be reached at ${this.server} (${method} ${path}): ${error.cause?.code ?? error.message}. Check the connection and run again.`), { code: "network" });
78
+ throw this.unreachable(method, path, error);
79
79
  throw error;
80
80
  }
81
81
  }
@@ -109,11 +109,15 @@ export class MethodClient {
109
109
  }
110
110
  catch (error) {
111
111
  if (attempt >= (options.attempts ?? 3) || error.retryable === false)
112
- throw error;
112
+ throw error?.name === 'TypeError' ? this.unreachable(data ? 'PUT' : 'GET', path, error) : error;
113
113
  await new Promise(resolve => setTimeout(resolve, 500 * 2 ** (attempt - 1)));
114
114
  }
115
115
  }
116
116
  }
117
+ /** A lost connection: code network, and the message says which server. */
118
+ unreachable(method, path, error) {
119
+ return Object.assign(Error(`Method cannot be reached at ${this.server} (${method} ${path}): ${error.cause?.code ?? error.message}. Check the connection and run again.`), { code: "network" });
120
+ }
117
121
  /** Send bytes in chunks and read the answer in chunks; a watchdog aborts when no bytes moved for stallMs. */
118
122
  async send(path, method, options) {
119
123
  const stallMs = options.stallMs ?? 15_000, controller = new AbortController();
@@ -56,7 +56,7 @@ export declare function lastSaved(server: string, methodId: string): {
56
56
  export declare function recordKnownVersion(server: string, methodId: string, versionId: string, versionNumber: number): void;
57
57
  /** A checkout of a saved version: the next save of this Method on this computer has it as its parent. */
58
58
  export declare function recordCheckout(server: string, methodId: string, versionId: string, versionNumber: number, workflow: unknown): void;
59
- /** Errors that a retry can fix: no response, a stalled transfer, a server error, or too many requests. */
59
+ /** Errors that a retry can fix: no connection, a stalled transfer, a server error, or too many requests. */
60
60
  export declare function retryable(error: any): boolean;
61
61
  export declare class Outbox {
62
62
  readonly client: MethodClient;
@@ -40,12 +40,13 @@ function recordSaved(item, versionNumber) {
40
40
  writePrivateJson(savedFile(item.server), { ...savedVersions(item.server), [item.version_id]: { method_id: item.method_id, version_number: versionNumber } });
41
41
  writePrivateJson(methodFile(item.server, item.method_id), { version_id: item.version_id, version_number: versionNumber, workflow: item.body.workflow });
42
42
  }
43
- /** Errors that a retry can fix: no response, a stalled transfer, a server error, or too many requests. */
43
+ /** Errors that a retry can fix: no connection, a stalled transfer, a server error, or too many requests. */
44
44
  export function retryable(error) {
45
45
  const status = error?.status ?? Number(/^(\d{3}):/.exec(String(error?.message))?.[1]);
46
- return !status || status >= 500 || status === 429 || status === 408;
46
+ return status ? status >= 500 || status === 429 || status === 408 : unreachable(error) || error?.code === 'stalled';
47
47
  }
48
- const networkError = (error) => !(error?.status ?? /^\d{3}:/.test(String(error?.message))) && error?.code !== 'stalled';
48
+ /** The server cannot be reached. An error on this computer (an unreadable run folder) is not one. */
49
+ const unreachable = (error) => error?.code === 'network';
49
50
  export class Outbox {
50
51
  client;
51
52
  options;
@@ -221,7 +222,7 @@ export class Outbox {
221
222
  }
222
223
  // No response, a server error, or too many requests: after 3 in a row, stop and keep the items for a later
223
224
  // command. A finished run never waits for a server that keeps failing.
224
- if (networkError(error) || status >= 500 || status === 429)
225
+ if (unreachable(error) || status >= 500 || status === 429)
225
226
  this.networkFailures++;
226
227
  const attempt = (this.retryAt.get(key)?.attempt ?? 0) + 1;
227
228
  this.retryAt.set(key, { at: Date.now() + Math.min(30_000, 500 * 2 ** (attempt - 1)), attempt });
@@ -256,7 +257,7 @@ export class Outbox {
256
257
  }
257
258
  catch (error) {
258
259
  const status = error?.status ?? Number(/^(\d{3}):/.exec(String(error?.message))?.[1]);
259
- if (networkError(error) || status >= 500 || status === 429)
260
+ if (unreachable(error) || status >= 500 || status === 429)
260
261
  this.networkFailures++;
261
262
  }
262
263
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@method-ai-hq/sdk",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
4
4
  "description": "Build and run reusable .method files with checked steps and saved results.",
5
5
  "license": "MIT",
6
6
  "type": "module",