maestro-agent-sdk 0.1.38 → 0.1.39

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.
Files changed (58) hide show
  1. package/README.md +30 -64
  2. package/dist/core/loop.d.ts.map +1 -1
  3. package/dist/core/loop.js +5 -43
  4. package/dist/core/loop.js.map +1 -1
  5. package/dist/index.d.ts +0 -5
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +0 -6
  8. package/dist/index.js.map +1 -1
  9. package/dist/memory/aux-model-map.d.ts +2 -43
  10. package/dist/memory/aux-model-map.d.ts.map +1 -1
  11. package/dist/memory/aux-model-map.js +3 -85
  12. package/dist/memory/aux-model-map.js.map +1 -1
  13. package/dist/platform/config.d.ts +0 -7
  14. package/dist/platform/config.d.ts.map +1 -1
  15. package/dist/platform/config.js +0 -14
  16. package/dist/platform/config.js.map +1 -1
  17. package/dist/platform/version.d.ts +1 -1
  18. package/dist/platform/version.js +1 -1
  19. package/dist/provider.d.ts +6 -57
  20. package/dist/provider.d.ts.map +1 -1
  21. package/dist/provider.js +72 -157
  22. package/dist/provider.js.map +1 -1
  23. package/dist/registry.d.ts +6 -39
  24. package/dist/registry.d.ts.map +1 -1
  25. package/dist/registry.js +9 -76
  26. package/dist/registry.js.map +1 -1
  27. package/dist/sub-agent/runner.d.ts.map +1 -1
  28. package/dist/sub-agent/runner.js +0 -3
  29. package/dist/sub-agent/runner.js.map +1 -1
  30. package/dist/types.d.ts +1 -1
  31. package/dist/types.d.ts.map +1 -1
  32. package/dist/types.js +2 -2
  33. package/dist/types.js.map +1 -1
  34. package/package.json +2 -24
  35. package/dist/providers/anthropic.d.ts +0 -328
  36. package/dist/providers/anthropic.d.ts.map +0 -1
  37. package/dist/providers/anthropic.js +0 -857
  38. package/dist/providers/anthropic.js.map +0 -1
  39. package/dist/providers/codex-auth.d.ts +0 -149
  40. package/dist/providers/codex-auth.d.ts.map +0 -1
  41. package/dist/providers/codex-auth.js +0 -332
  42. package/dist/providers/codex-auth.js.map +0 -1
  43. package/dist/providers/codex-stream.d.ts +0 -42
  44. package/dist/providers/codex-stream.d.ts.map +0 -1
  45. package/dist/providers/codex-stream.js +0 -345
  46. package/dist/providers/codex-stream.js.map +0 -1
  47. package/dist/providers/codex-translators.d.ts +0 -105
  48. package/dist/providers/codex-translators.d.ts.map +0 -1
  49. package/dist/providers/codex-translators.js +0 -244
  50. package/dist/providers/codex-translators.js.map +0 -1
  51. package/dist/providers/codex.d.ts +0 -234
  52. package/dist/providers/codex.d.ts.map +0 -1
  53. package/dist/providers/codex.js +0 -461
  54. package/dist/providers/codex.js.map +0 -1
  55. package/dist/providers/fallback.d.ts +0 -71
  56. package/dist/providers/fallback.d.ts.map +0 -1
  57. package/dist/providers/fallback.js +0 -223
  58. package/dist/providers/fallback.js.map +0 -1
@@ -1,223 +0,0 @@
1
- import { isAbortError } from "../core/is-abort-error.js";
2
- import { logger } from "../platform/logger.js";
3
- import { getNativeMaxOutputTokens } from "../registry.js";
4
- /**
5
- * Provider wrapper that falls back from a `primary` to a `fallback` provider
6
- * when the primary fails *before producing any output*.
7
- *
8
- * Motivating case: the Codex `/responses` backend (ChatGPT-OAuth) is the
9
- * primary for `gpt-5.*` models, but its OAuth refresh, HTTP round-trip, and
10
- * time-to-first-byte all happen INSIDE `stream()` before the first chunk is
11
- * yielded (see `codex.ts` — `fromEnv()` only constructs; auth resolves at
12
- * stream time). When any of those legs throws — OAuth dead, HTTP 401/429/5xx,
13
- * connect/TTFB timeout, network reset — this wrapper retries the turn against
14
- * DeepSeek instead of surfacing a hard `error` event.
15
- *
16
- * ## Why pre-first-chunk only
17
- *
18
- * Once the primary has yielded ANY chunk, the host has already displayed text
19
- * (or a tool_use has started) and the assistant turn's history is half-built.
20
- * Restarting against a different provider there would double-emit content and
21
- * desync the loop's message accumulation. So the switch is only safe before
22
- * the first chunk — after that, errors propagate unchanged. This covers the
23
- * overwhelming majority of "codex isn't working" failures, which are all
24
- * pre-stream by construction.
25
- *
26
- * ## Model id + maxTokens rewrite
27
- *
28
- * The agent loop passes the primary's resolved model id (e.g. `gpt-5.5`) in
29
- * `ProviderCompleteOptions.model`. DeepSeek would 400 on that slug, so the
30
- * fallback delegation rewrites `opts.model` to `fallbackModel` and clamps
31
- * `opts.maxTokens` to the fallback model's native output ceiling (a gpt-5.5
32
- * `maxTokens` could exceed a flash-tier fallback's cap). `thinkingBudget` is
33
- * harmlessly ignored by DeepSeek; `effort` is honored natively. Tools and
34
- * messages pass through untouched — each provider runs its own translation
35
- * from the shared `ProviderMessage` shape.
36
- *
37
- * ## Compaction props
38
- *
39
- * `compactionTriggerRatio` / `compactionTailProtect` / `guidedCompaction` are
40
- * read once by the loop *before* the turn, so they reflect the PRIMARY's
41
- * preference (Codex compacts early + guided). If the fallback fires, DeepSeek
42
- * runs against a slightly-more-aggressively-compacted history — harmless, and
43
- * not worth the complexity of swapping mid-turn.
44
- */
45
- export class FallbackProvider {
46
- primary;
47
- fallbackFactory;
48
- fallbackModel;
49
- fallbackInstance = null;
50
- /**
51
- * @param primary The preferred provider (e.g. Codex).
52
- * @param fallbackFactory Lazily constructs the fallback provider. Deferred so
53
- * a process that never trips the fallback never pays its construction cost
54
- * (and never requires its env to be present until actually needed).
55
- * @param fallbackModel Wire model id handed to the fallback provider, e.g.
56
- * `deepseek-v4-pro`. Replaces the primary's model id on delegation.
57
- */
58
- constructor(primary, fallbackFactory, fallbackModel) {
59
- this.primary = primary;
60
- this.fallbackFactory = fallbackFactory;
61
- this.fallbackModel = fallbackModel;
62
- }
63
- // Surface the PRIMARY's compaction preferences to the loop (see class doc).
64
- get compactionTriggerRatio() {
65
- return this.primary.compactionTriggerRatio;
66
- }
67
- get compactionTailProtect() {
68
- return this.primary.compactionTailProtect;
69
- }
70
- get guidedCompaction() {
71
- return this.primary.guidedCompaction;
72
- }
73
- getFallback() {
74
- if (!this.fallbackInstance) {
75
- this.fallbackInstance = this.fallbackFactory();
76
- }
77
- return this.fallbackInstance;
78
- }
79
- /** Rewrite the request for the fallback provider: swap model id, clamp
80
- * maxTokens to the fallback's native output ceiling. */
81
- rewriteOpts(opts) {
82
- const cap = getNativeMaxOutputTokens(this.fallbackModel);
83
- // Treat a missing OR non-positive maxTokens as "use the fallback's native
84
- // cap". A literal `0` would otherwise survive the `??` (it's not nullish)
85
- // and clamp to `Math.min(0, cap) === 0`, sending `max_tokens: 0` to the
86
- // fallback — DeepSeek 400s on that, turning a recoverable codex failure
87
- // into a hard error. The codex primary silently drops maxTokens, so a 0
88
- // only becomes fatal after the fallback rewrite.
89
- const want = opts.maxTokens && opts.maxTokens > 0 ? opts.maxTokens : cap;
90
- return {
91
- ...opts,
92
- model: this.fallbackModel,
93
- maxTokens: Math.min(want, cap),
94
- };
95
- }
96
- shouldRethrow(e, opts) {
97
- return isAbortError(e) || opts.abortSignal?.aborted === true;
98
- }
99
- async *stream(opts) {
100
- // Single source for the primary stream so the pre-first-chunk guard below
101
- // applies uniformly whether the primary streams natively or is adapted
102
- // from `complete()`. Codex/DeepSeek both implement `stream()`; the
103
- // complete()-adapter branch only guards a future stream-less primary.
104
- const iter = this.primary.stream
105
- ? this.primary.stream(opts)
106
- : this.streamViaComplete(this.primary, opts);
107
- let started = false;
108
- try {
109
- while (true) {
110
- let result;
111
- try {
112
- result = await iter.next();
113
- }
114
- catch (e) {
115
- // After the first chunk, or on a user abort, the error is terminal.
116
- if (started || this.shouldRethrow(e, opts))
117
- throw e;
118
- logger.warn({
119
- err: e,
120
- errName: e instanceof Error ? e.name : typeof e,
121
- errMessage: e instanceof Error ? e.message : String(e),
122
- primaryModel: opts.model,
123
- fallbackModel: this.fallbackModel,
124
- }, "FallbackProvider: primary failed before first chunk — falling back");
125
- const fb = this.getFallback();
126
- if (!fb.stream) {
127
- throw new Error("FallbackProvider: fallback provider has no stream()");
128
- }
129
- // Attach the primary failure as `cause` so a double-failure (DeepSeek
130
- // also down) doesn't hide why codex died — the surfaced error message
131
- // is DeepSeek's, but the codex error is recoverable from `.cause`.
132
- try {
133
- yield* fb.stream(this.rewriteOpts(opts));
134
- }
135
- catch (fallbackErr) {
136
- throw attachCause(fallbackErr, e);
137
- }
138
- return;
139
- }
140
- if (result.done)
141
- return;
142
- started = true;
143
- yield result.value;
144
- }
145
- }
146
- finally {
147
- // The primary is driven manually via `iter.next()` (not `yield*`), so a
148
- // consumer `.return()` / `.throw()` — early `break`, downstream
149
- // exception, host abort — does NOT auto-forward to it. Without this, the
150
- // primary's cleanup `finally` (codex `parseSseFrames`: reader.releaseLock
151
- // + abort-listener removal) never runs, leaking the ReadableStream reader
152
- // lock and the abort listener. No-op when the primary already finished or
153
- // errored. (The fallback path uses `yield*`, which forwards `.return()`
154
- // on its own.)
155
- await iter.return?.(undefined);
156
- }
157
- }
158
- async complete(opts) {
159
- try {
160
- return await this.primary.complete(opts);
161
- }
162
- catch (e) {
163
- if (this.shouldRethrow(e, opts))
164
- throw e;
165
- logger.warn({
166
- err: e,
167
- errName: e instanceof Error ? e.name : typeof e,
168
- primaryModel: opts.model,
169
- fallbackModel: this.fallbackModel,
170
- }, "FallbackProvider: primary complete() failed — falling back");
171
- try {
172
- return await this.getFallback().complete(this.rewriteOpts(opts));
173
- }
174
- catch (fallbackErr) {
175
- // Preserve the primary failure as `.cause` (see stream() for rationale).
176
- throw attachCause(fallbackErr, e);
177
- }
178
- }
179
- }
180
- /** Adapt a `complete()`-only primary into the streaming shape. Defensive
181
- * helper for the stream-less-primary branch; unused for Codex/DeepSeek. */
182
- async *streamViaComplete(provider, opts) {
183
- const res = await provider.complete(opts);
184
- for (const block of res.content) {
185
- if (block.type === "text") {
186
- yield { type: "text_delta", text: block.text };
187
- }
188
- else if (block.type === "thinking") {
189
- yield { type: "thinking_complete", block };
190
- }
191
- else if (block.type === "tool_use") {
192
- yield { type: "tool_use_start", id: block.id, name: block.name };
193
- yield {
194
- type: "tool_use_input_delta",
195
- id: block.id,
196
- partial_json: JSON.stringify(block.input),
197
- };
198
- yield { type: "tool_use_complete", id: block.id, name: block.name };
199
- }
200
- }
201
- yield { type: "message_complete", stopReason: res.stopReason, usage: res.usage };
202
- }
203
- }
204
- /**
205
- * Attach `cause` to a thrown fallback error so a double-failure keeps a trail
206
- * back to the primary failure. The surfaced `.message` stays the fallback's
207
- * (that's what actually failed last), but `.cause` recovers why the primary
208
- * tripped the fallback in the first place. Only sets `cause` when the error is
209
- * an `Error` without one already, and swallows the rare read-only-`cause` case
210
- * — attaching debug context must never itself throw.
211
- */
212
- function attachCause(error, cause) {
213
- if (error instanceof Error && error.cause === undefined) {
214
- try {
215
- error.cause = cause;
216
- }
217
- catch {
218
- // `cause` is non-writable on some custom error subclasses — ignore.
219
- }
220
- }
221
- return error;
222
- }
223
- //# sourceMappingURL=fallback.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fallback.js","sourceRoot":"","sources":["../../src/providers/fallback.ts"],"names":[],"mappings":"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"}