@gigaai/newton 0.4.0 → 0.4.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 +1 -1
- package/dist/executor.js +78 -33
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ script body. The body runs as an async function with these in scope:
|
|
|
61
61
|
|
|
62
62
|
| Primitive | What it does |
|
|
63
63
|
|---|---|
|
|
64
|
-
| `agent(prompt, opts?)` | Run one agent turn; returns its final text, or a schema-validated object when `opts.schema` is set.
|
|
64
|
+
| `agent(prompt, opts?)` | Run one agent turn; returns its final text, or a schema-validated object when `opts.schema` is set. Transient failures (provider 5xx/overload, rate limits, dropped connections) retry up to twice with backoff; returns `null` on lasting failure — filter with `.filter(Boolean)`. |
|
|
65
65
|
| `parallel(thunks)` | Run `() => …` tasks concurrently; a failed task resolves to `null`. Barrier: waits for all. |
|
|
66
66
|
| `pipeline(items, ...stages)` | Each item flows through the stages independently — no barrier between stages. Stage signature: `(prev, item, index)`. |
|
|
67
67
|
| `phase(title)` | Group subsequent agents in progress output. |
|
package/dist/executor.js
CHANGED
|
@@ -9,6 +9,32 @@ import { checkCompile, createRealm } from "./sandbox.js";
|
|
|
9
9
|
import { balancedSlice, extractJson, INVALID, structuredOutputInstruction, structuredOutputRetryPrompt, validateAgainstSchema, } from "./schema.js";
|
|
10
10
|
import { createWorktree, finishWorktree } from "./worktree.js";
|
|
11
11
|
const SCRIPT_PARAMS = ["agent", "parallel", "pipeline", "phase", "log", "args", "budget", "workflow"];
|
|
12
|
+
const AGENT_MAX_ATTEMPTS = 3;
|
|
13
|
+
const AGENT_RETRY_BASE_MS = 2_000;
|
|
14
|
+
/**
|
|
15
|
+
* Failures worth a fresh attempt: provider 5xx/overload/rate-limit responses
|
|
16
|
+
* and dropped connections. Deterministic failures (auth, missing binaries,
|
|
17
|
+
* bad model ids, structured-output exhaustion) return null without retrying.
|
|
18
|
+
*/
|
|
19
|
+
const TRANSIENT_AGENT_ERROR = new RegExp([
|
|
20
|
+
"\\b(?:429|500|502|503|504|529)\\b",
|
|
21
|
+
"overloaded",
|
|
22
|
+
"rate.?limit",
|
|
23
|
+
"too many requests",
|
|
24
|
+
"internal server error",
|
|
25
|
+
"service unavailable",
|
|
26
|
+
"bad gateway",
|
|
27
|
+
"gateway timeout",
|
|
28
|
+
"econn(?:reset|refused|aborted)",
|
|
29
|
+
"etimedout",
|
|
30
|
+
"epipe",
|
|
31
|
+
"eai_again",
|
|
32
|
+
"socket hang.?up",
|
|
33
|
+
"connection (?:reset|refused|closed|error)",
|
|
34
|
+
"fetch failed",
|
|
35
|
+
"network error",
|
|
36
|
+
"stream (?:closed|disconnected)",
|
|
37
|
+
].join("|"), "i");
|
|
12
38
|
function errorMessage(error) {
|
|
13
39
|
return typeof error === "object" &&
|
|
14
40
|
error !== null &&
|
|
@@ -257,45 +283,64 @@ export async function runWorkflow(options) {
|
|
|
257
283
|
: callOptions.cwd
|
|
258
284
|
? resolve(workspace, callOptions.cwd)
|
|
259
285
|
: workspace;
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
286
|
+
let turn;
|
|
287
|
+
let result;
|
|
288
|
+
let failure;
|
|
289
|
+
for (let attempt = 1;; attempt++) {
|
|
290
|
+
session = new AcpAgentSession({
|
|
291
|
+
spec,
|
|
292
|
+
prompt: fullPrompt,
|
|
293
|
+
cwd,
|
|
294
|
+
timeoutMs: callOptions.timeoutMs ?? agentTimeoutMs,
|
|
295
|
+
mcpServers,
|
|
296
|
+
config,
|
|
297
|
+
trace,
|
|
298
|
+
});
|
|
299
|
+
liveSessions.set(id, session);
|
|
300
|
+
turn = await session.prompt();
|
|
301
|
+
result = turn.text;
|
|
302
|
+
failure = turn.error;
|
|
303
|
+
if (!failure && callOptions.schema) {
|
|
304
|
+
for (let retry = 0;; retry++) {
|
|
305
|
+
const parsed = extractJson(turn.text);
|
|
306
|
+
const errors = parsed === INVALID
|
|
307
|
+
? ["response contained no parseable JSON"]
|
|
308
|
+
: validateAgainstSchema(parsed, callOptions.schema);
|
|
309
|
+
if (errors.length === 0) {
|
|
310
|
+
result = parsed;
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
if (retry >= 2) {
|
|
314
|
+
failure = `structured output failed after ${retry + 1} attempts: ${errors.join("; ")}`;
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
turn = await session.promptAgain(structuredOutputRetryPrompt(errors, callOptions.schema));
|
|
318
|
+
if (turn.error) {
|
|
319
|
+
failure = turn.error;
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
291
322
|
}
|
|
292
323
|
}
|
|
324
|
+
liveSessions.delete(id);
|
|
325
|
+
session.close();
|
|
326
|
+
outputTokens += turn.usage?.outputTokens ?? 0;
|
|
327
|
+
if (!failure ||
|
|
328
|
+
attempt >= AGENT_MAX_ATTEMPTS ||
|
|
329
|
+
turn.stopReason === "timeout" ||
|
|
330
|
+
turn.stopReason === "cancelled" ||
|
|
331
|
+
!TRANSIENT_AGENT_ERROR.test(failure)) {
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
const delayMs = AGENT_RETRY_BASE_MS * 4 ** (attempt - 1);
|
|
335
|
+
journal.append({ type: "agent_retry", id, key, label, phase, attempt, error: failure, delayMs });
|
|
336
|
+
reporter.log(`↻ agent #${id} transient error, retry ${attempt}/${AGENT_MAX_ATTEMPTS - 1} in ${delayMs / 1000}s: ${failure.split("\n")[0]}`);
|
|
337
|
+
await new Promise((resolveDelay) => setTimeout(resolveDelay, delayMs));
|
|
338
|
+
if (skipped.has(id))
|
|
339
|
+
break;
|
|
293
340
|
}
|
|
294
|
-
session.close();
|
|
295
341
|
const worktree = await finishCreatedWorktree();
|
|
296
342
|
const seconds = Math.round((Date.now() - agentStartedAt) / 1000);
|
|
297
343
|
const turnTokens = turn.usage?.outputTokens ?? 0;
|
|
298
|
-
outputTokens += turnTokens;
|
|
299
344
|
if (failure) {
|
|
300
345
|
journal.append({
|
|
301
346
|
type: "agent_end",
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = "0.4.
|
|
1
|
+
export const VERSION = "0.4.1";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gigaai/newton",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Deterministic multi-agent workflow executor. Write workflows in plain JavaScript; Newton drives coding agents over the Agent Client Protocol.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|