@rarebit-one/harness-kernel 0.18.0 → 0.19.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.
Files changed (99) hide show
  1. package/README.md +255 -16
  2. package/dist/agent.d.ts +24 -0
  3. package/dist/agent.d.ts.map +1 -1
  4. package/dist/agent.js +138 -30
  5. package/dist/agent.js.map +1 -1
  6. package/dist/connectors/auth.d.ts +32 -0
  7. package/dist/connectors/auth.d.ts.map +1 -0
  8. package/dist/connectors/auth.js +85 -0
  9. package/dist/connectors/auth.js.map +1 -0
  10. package/dist/connectors/mcpClient.d.ts +14 -4
  11. package/dist/connectors/mcpClient.d.ts.map +1 -1
  12. package/dist/connectors/mcpClient.js +32 -11
  13. package/dist/connectors/mcpClient.js.map +1 -1
  14. package/dist/engines/acp.d.ts.map +1 -1
  15. package/dist/engines/acp.js +2 -1
  16. package/dist/engines/acp.js.map +1 -1
  17. package/dist/engines/capability.d.ts +1 -1
  18. package/dist/engines/capability.js +1 -1
  19. package/dist/engines/claudeCode.d.ts.map +1 -1
  20. package/dist/engines/claudeCode.js +2 -1
  21. package/dist/engines/claudeCode.js.map +1 -1
  22. package/dist/engines/claudeCodeDriver.d.ts.map +1 -1
  23. package/dist/engines/claudeCodeDriver.js +4 -3
  24. package/dist/engines/claudeCodeDriver.js.map +1 -1
  25. package/dist/engines/codex.d.ts +4 -4
  26. package/dist/engines/codex.d.ts.map +1 -1
  27. package/dist/engines/codex.js +6 -5
  28. package/dist/engines/codex.js.map +1 -1
  29. package/dist/engines/codexDriver.d.ts +1 -1
  30. package/dist/engines/codexDriver.js +1 -1
  31. package/dist/engines/connectorMcp.d.ts +13 -0
  32. package/dist/engines/connectorMcp.d.ts.map +1 -1
  33. package/dist/engines/connectorMcp.js +23 -0
  34. package/dist/engines/connectorMcp.js.map +1 -1
  35. package/dist/engines/gateway.d.ts +5 -2
  36. package/dist/engines/gateway.d.ts.map +1 -1
  37. package/dist/engines/gateway.js +7 -2
  38. package/dist/engines/gateway.js.map +1 -1
  39. package/dist/engines/native.d.ts.map +1 -1
  40. package/dist/engines/native.js +10 -3
  41. package/dist/engines/native.js.map +1 -1
  42. package/dist/engines/types.d.ts +10 -1
  43. package/dist/engines/types.d.ts.map +1 -1
  44. package/dist/events.d.ts +22 -8
  45. package/dist/events.d.ts.map +1 -1
  46. package/dist/events.js.map +1 -1
  47. package/dist/index.d.ts +10 -2
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +5 -1
  50. package/dist/index.js.map +1 -1
  51. package/dist/loop.d.ts +23 -0
  52. package/dist/loop.d.ts.map +1 -1
  53. package/dist/loop.js +1 -0
  54. package/dist/loop.js.map +1 -1
  55. package/dist/models/chat.d.ts +12 -6
  56. package/dist/models/chat.d.ts.map +1 -1
  57. package/dist/models/chat.js +11 -6
  58. package/dist/models/chat.js.map +1 -1
  59. package/dist/models/retry.d.ts +252 -0
  60. package/dist/models/retry.d.ts.map +1 -0
  61. package/dist/models/retry.js +400 -0
  62. package/dist/models/retry.js.map +1 -0
  63. package/dist/models/types.d.ts +7 -0
  64. package/dist/models/types.d.ts.map +1 -1
  65. package/dist/models/types.js.map +1 -1
  66. package/dist/private.d.ts.map +1 -1
  67. package/dist/private.js +12 -2
  68. package/dist/private.js.map +1 -1
  69. package/dist/secrets.d.ts +17 -7
  70. package/dist/secrets.d.ts.map +1 -1
  71. package/dist/secrets.js +38 -24
  72. package/dist/secrets.js.map +1 -1
  73. package/dist/tools/concurrency.d.ts +48 -0
  74. package/dist/tools/concurrency.d.ts.map +1 -0
  75. package/dist/tools/concurrency.js +64 -0
  76. package/dist/tools/concurrency.js.map +1 -0
  77. package/dist/tools/metadata.d.ts +18 -3
  78. package/dist/tools/metadata.d.ts.map +1 -1
  79. package/dist/tools/metadata.js +7 -0
  80. package/dist/tools/metadata.js.map +1 -1
  81. package/dist/tools/registry.d.ts +6 -4
  82. package/dist/tools/registry.d.ts.map +1 -1
  83. package/dist/tools/registry.js +5 -3
  84. package/dist/tools/registry.js.map +1 -1
  85. package/dist/tools/terminal.d.ts +8 -6
  86. package/dist/tools/terminal.d.ts.map +1 -1
  87. package/dist/tools/terminal.js +8 -6
  88. package/dist/tools/terminal.js.map +1 -1
  89. package/dist/tools/validate.d.ts +49 -0
  90. package/dist/tools/validate.d.ts.map +1 -0
  91. package/dist/tools/validate.js +346 -0
  92. package/dist/tools/validate.js.map +1 -0
  93. package/dist/transcript.d.ts +53 -0
  94. package/dist/transcript.d.ts.map +1 -0
  95. package/dist/transcript.js +104 -0
  96. package/dist/transcript.js.map +1 -0
  97. package/dist/types.d.ts +44 -5
  98. package/dist/types.d.ts.map +1 -1
  99. package/package.json +3 -3
@@ -1,4 +1,4 @@
1
- import { requireCapability, } from "./types.js";
1
+ import { CapabilityError, requireCapability, } from "./types.js";
2
2
  /** The kind string every chat model registers under. */
3
3
  export const CHAT_KIND = "chat";
4
4
  /**
@@ -11,11 +11,13 @@ export const CHAT_KIND = "chat";
11
11
  *
12
12
  * Capabilities are reported conservatively, from what the `Provider` interface
13
13
  * can actually express: it has no streaming method and no attachment channel,
14
- * so those stay false. `usage` follows the provider's own `reportsUsage`
15
- * declaration: the SDK-backed adapters set it (their `ConverseResult.usage`
16
- * becomes `ModelResult.usage`), while a provider that declares nothing — the
17
- * mock, a custom provider — reports `usage: false` rather than promising
18
- * accounting it does not deliver.
14
+ * so those stay false. A request carrying `parts` is refused with a
15
+ * `CapabilityError` even when `multimodalInput` is passed in `caps`, because
16
+ * there is no channel to forward them on. `usage` follows the provider's own
17
+ * `reportsUsage` declaration: the SDK-backed adapters set it (their
18
+ * `ConverseResult.usage` becomes `ModelResult.usage`), while a provider that
19
+ * declares nothing — the mock, a custom provider — reports `usage: false`
20
+ * rather than promising accounting it does not deliver.
19
21
  */
20
22
  export function chatModel(provider, caps = {}) {
21
23
  const resolved = {
@@ -32,6 +34,9 @@ export function chatModel(provider, caps = {}) {
32
34
  async invoke(req, ctx) {
33
35
  if (req.parts?.length) {
34
36
  requireCapability({ id: provider.name, kind: CHAT_KIND, caps: resolved }, "multimodalInput", "request carries parts");
37
+ // A declared capability is not a channel: `ConverseRequest` has nowhere
38
+ // to put an attachment, so forwarding would drop it. Refuse instead.
39
+ throw new CapabilityError({ id: provider.name, kind: CHAT_KIND, caps: resolved }, "multimodalInput", "declared, but not deliverable: the Provider interface has no attachment channel, so parts would be dropped");
35
40
  }
36
41
  if (req.tools.length > 0) {
37
42
  requireCapability({ id: provider.name, kind: CHAT_KIND, caps: resolved }, "tools", "request carries tool definitions");
@@ -1 +1 @@
1
- {"version":3,"file":"chat.js","sourceRoot":"","sources":["../../src/models/chat.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat.js","sourceRoot":"","sources":["../../src/models/chat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,252 @@
1
+ import { type ModelInvocation } from "./types.js";
2
+ /**
3
+ * Retry and fallback around a model invocation, as an opt-in decorator.
4
+ *
5
+ * The kernel leaves transient failures to the vendor SDKs by default. A caller
6
+ * that needs a policy those SDKs cannot express — a wait that knows the run's
7
+ * deadline, an honoured `Retry-After`, a named chain of other models to try
8
+ * once the primary is exhausted — wraps its model in {@link withRetry} and
9
+ * turns the SDK's own retries off (`providerOptions.maxRetries: 0`), so the two
10
+ * do not multiply.
11
+ *
12
+ * This is infrastructure, not a quality loop: an attempt is repeated only when
13
+ * the call FAILED (threw), never because its answer was judged poor. And it is
14
+ * explicit: there is no default fallback chain, so a call that ends up on
15
+ * another model does so because the caller listed that model.
16
+ *
17
+ * It wraps a {@link ModelInvocation} rather than being a `Middleware`
18
+ * because a fallback chain needs several invocations, and middleware is handed
19
+ * exactly one `next`. Being payload-generic, it covers every kind the same way
20
+ * middleware does: a chat model, a detector, a forecaster.
21
+ */
22
+ /**
23
+ * What to do after a failed attempt.
24
+ *
25
+ * - `retry` — a transient fault: try the same model again after a backoff, and
26
+ * move to the next model in the chain once its attempts run out.
27
+ * - `fallback` — this model will not answer soon: skip its remaining attempts
28
+ * and move to the next model at once.
29
+ * - `fatal` — a fault no other attempt can fix (a bad credential, an invalid
30
+ * request): rethrow it unchanged, trying nothing else.
31
+ */
32
+ export type RetryDecision = "retry" | "fallback" | "fatal";
33
+ /** One model in the chain giving up, or one wait before trying it again. */
34
+ export type RetryEvent = {
35
+ type: "retry";
36
+ /** The invocation id that failed and will be tried again. */
37
+ model: string;
38
+ /** The attempt on this model that just failed, from 1. */
39
+ attempt: number;
40
+ /** How long the wrapper waits before the next attempt. */
41
+ delayMs: number;
42
+ /** True when `delayMs` came from the server's `Retry-After`. */
43
+ retryAfter: boolean;
44
+ /** The failure. Absent when the wrapper was built with `private: true`. */
45
+ error?: unknown;
46
+ } | {
47
+ type: "fallback";
48
+ /** The invocation id given up on. */
49
+ from: string;
50
+ /** The next invocation id in the chain. */
51
+ to: string;
52
+ /**
53
+ * Why `from` was given up on: its retries or wait budget ran out
54
+ * (`exhausted`), the classifier said `fallback`, or it was skipped
55
+ * because an earlier call of this wrapper exhausted it (`sticky`).
56
+ */
57
+ reason: "exhausted" | "fallback" | "sticky";
58
+ error?: unknown;
59
+ };
60
+ /**
61
+ * What the wrapper did on a call that succeeded, reported as `meta.retry` on
62
+ * the result. Consumers audit which model actually served a call from it.
63
+ */
64
+ export interface RetryReport {
65
+ /**
66
+ * The id of the invocation that answered. When the chain entry that
67
+ * answered is itself a `withRetry` wrapper, this is the model inside it that
68
+ * answered, and `attempts`, `fellBackFrom` and `waitedMs` include its calls.
69
+ */
70
+ served: string;
71
+ /** The answering entry's position in this chain: 0 is the primary, n the n-th fallback. */
72
+ position: number;
73
+ /** Every call made for this invocation, including the one that answered. */
74
+ attempts: number;
75
+ /** Ids of the models tried and given up on, in order; empty when the primary served. */
76
+ fellBackFrom: string[];
77
+ /** Total time this invocation spent waiting between attempts. */
78
+ waitedMs: number;
79
+ }
80
+ /** Exponential backoff: `baseMs × 2^(retry−1)`, capped at `maxMs`. */
81
+ export interface BackoffOptions {
82
+ /** The first wait. Default 500. */
83
+ baseMs?: number;
84
+ /** The longest single wait. Default 8000. */
85
+ maxMs?: number;
86
+ /**
87
+ * Randomise each wait between half and all of its computed value, so many
88
+ * callers refused at once do not retry in step. Default true.
89
+ */
90
+ jitter?: boolean;
91
+ }
92
+ export interface RetryOptions<Req, Res> {
93
+ /**
94
+ * Calls per model, including the first. Default 3 (the SDK default this
95
+ * replaces: one call plus two retries). 1 means never retry, only fall back.
96
+ */
97
+ maxAttempts?: number;
98
+ /**
99
+ * The wait before retry `n` (from 1): exponential options, or a function for
100
+ * a fixed schedule (`(n) => [1000, 2000, 3000][n - 1] ?? 3000`).
101
+ */
102
+ backoff?: BackoffOptions | ((retry: number) => number);
103
+ /**
104
+ * Wait what the server's `Retry-After` (or `retry-after-ms`) header asks
105
+ * instead of the computed backoff. Default true. A server wait longer than
106
+ * the remaining budget is not shortened, since a shortened wait would only
107
+ * be refused again: that model is given up on and the chain moves on.
108
+ */
109
+ respectRetryAfter?: boolean;
110
+ /**
111
+ * The longest server-asked wait honoured. Default 60000, as the vendor SDKs
112
+ * do. A `Retry-After` above it is treated as a wait that does not fit: that
113
+ * model is given up on and the chain moves on, rather than sleeping for an
114
+ * implausible hour or day.
115
+ */
116
+ maxRetryAfterMs?: number;
117
+ /** Decide each failure. Default {@link defaultRetryClassifier}. */
118
+ classify?: (err: unknown) => RetryDecision;
119
+ /**
120
+ * The ordered models to try once the primary is given up on. Empty (the
121
+ * default) means retry only: the kernel never picks a fallback by itself.
122
+ */
123
+ fallbacks?: ModelInvocation<Req, Res>[];
124
+ /**
125
+ * The absolute deadline (epoch ms) every attempt must finish by, or a
126
+ * function returning it. The wrapper never starts a wait that would run past
127
+ * it. The call's context bounds it too: `InvokeContext.budget.deadlineAt`
128
+ * (which the native loop sets to the run's deadline, so a wrapped model in
129
+ * `runConversation` or `runAgent` knows how much of the run is left) and
130
+ * `budget.maxDurationMs` counted from the call's start. The earliest wins.
131
+ * Set this when the model is called outside the native loop, or when the
132
+ * caller's own deadline is earlier than the run's.
133
+ */
134
+ deadlineAt?: number | (() => number);
135
+ /**
136
+ * Time to leave for the call itself: a wait that would leave less than this
137
+ * before the deadline is not started. Default 0.
138
+ */
139
+ minCallMs?: number;
140
+ /**
141
+ * The most this wrapper waits in total, summed across every call made
142
+ * through it. Default unlimited.
143
+ *
144
+ * This budget belongs to the INSTANCE and never refills, so build one
145
+ * wrapper per run or turn when you set it. A wrapper registered once at
146
+ * startup and shared by every run would spend it on the first rate limit
147
+ * and never retry again.
148
+ */
149
+ waitBudgetMs?: number;
150
+ /**
151
+ * Once a model has been given up on because its retries or wait budget ran
152
+ * out, start every later call of this wrapper at the next model rather than
153
+ * asking it again (asking a rate-limited model again only adds a refusal
154
+ * under the same limit). A `fallback` decision does not make it sticky.
155
+ * Default false.
156
+ *
157
+ * Like `waitBudgetMs`, this is instance state that never resets: build one
158
+ * wrapper per run or turn when you set it. A wrapper with neither option
159
+ * keeps no state between calls and is safe to share.
160
+ */
161
+ stickyFallback?: boolean;
162
+ /**
163
+ * The run is private (`RunSpec.private`): its material must stay on the one
164
+ * model it was given. Retrying that model is allowed; a fallback chain is
165
+ * refused when the wrapper is built, because a fallback is exactly a way for
166
+ * the material to reach another model. That includes a primary that is
167
+ * itself a `withRetry` wrapper with fallbacks; a nested `withRetry` must also
168
+ * be built `private: true`, or it is refused, since it logs and reports on
169
+ * its own.
170
+ *
171
+ * An upstream error can quote the material, so none of its text leaves the
172
+ * wrapper by its own hand: `onEvent` receives no `error`, `ctx.log` lines
173
+ * name the HTTP status at most, and `RetryExhaustedError`'s `failures` and
174
+ * `cause` hold a narrowed error carrying only that status. A fatal error or
175
+ * an abort is still rethrown unchanged, exactly as the model threw it; that
176
+ * error is the caller's to keep off its own channels.
177
+ *
178
+ * Caller-declared today: the native engine selects its own provider and
179
+ * takes no injected model, so a private run cannot reach this wrapper. A
180
+ * hook that ever lets an engine wrap its model must pass `RunSpec.private`
181
+ * through here, or this refusal becomes a hope.
182
+ */
183
+ private?: boolean;
184
+ /** Told about each retry and fallback as it happens. A throwing observer is logged and skipped. */
185
+ onEvent?: (event: RetryEvent) => void;
186
+ /** Injectable for tests. Must reject with `signal.reason` when it aborts. */
187
+ sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
188
+ /** Injectable for tests. Default `Date.now`. */
189
+ now?: () => number;
190
+ /** Injectable for tests (jitter). Default `Math.random`. */
191
+ random?: () => number;
192
+ }
193
+ /**
194
+ * Thrown when every model in the chain failed without a fatal error: the last
195
+ * failure is its `cause`, every failure is in `failures`. A `fatal` error is
196
+ * never wrapped, and neither is an abort.
197
+ */
198
+ export declare class RetryExhaustedError extends Error {
199
+ /** Each failed call, in order. */
200
+ readonly failures: {
201
+ model: string;
202
+ error: unknown;
203
+ }[];
204
+ /** Why the chain stopped: every model was tried, or the deadline left no room for another attempt. */
205
+ readonly reason: "exhausted" | "deadline";
206
+ /** Total time spent waiting between those calls. */
207
+ readonly waitedMs: number;
208
+ constructor(failures: {
209
+ model: string;
210
+ error: unknown;
211
+ }[], reason: "exhausted" | "deadline", cause: unknown, waitedMs?: number);
212
+ }
213
+ /**
214
+ * The HTTP status a failed call carries: the SDK error's `status` (or
215
+ * `statusCode`), else a leading status in its message ("429 Rate limit
216
+ * exceeded"), which is how some gateways' errors arrive.
217
+ */
218
+ export declare function errorStatus(err: unknown): number | undefined;
219
+ /**
220
+ * The wait a failed call's server asked for, in ms: `retry-after-ms`, else
221
+ * `retry-after` as seconds or an HTTP date. Read from the error's `headers`,
222
+ * a `Headers` or a plain record, the way the SDKs attach them.
223
+ */
224
+ export declare function retryAfterMs(err: unknown, now?: number): number | undefined;
225
+ /**
226
+ * The default classification: rate limits, timeouts, server faults (but not
227
+ * 501/505) and dropped connections are retried; a nested `withRetry` that ran
228
+ * out moves this chain to its next model; everything else — auth (401/403), payment
229
+ * (402), an invalid request (400/404/422), a credential or option the kernel
230
+ * refused, and any error it cannot recognise — is fatal. Unknown errors are
231
+ * fatal on purpose: retrying what nobody classified hides it.
232
+ */
233
+ export declare function defaultRetryClassifier(err: unknown): RetryDecision;
234
+ /**
235
+ * Wrap a model in retry-and-fallback.
236
+ *
237
+ * The returned invocation keeps the primary's `id` and `kind`; its `caps` are
238
+ * what every model in the chain can do (a capability one fallback lacks is not
239
+ * advertised), and it streams only when all of them stream. `probe` asks the
240
+ * primary.
241
+ *
242
+ * On success the result is the serving model's, with `meta.retry` set to a
243
+ * {@link RetryReport}. A streaming call is never retried or sent to a fallback
244
+ * once its sink has received anything: the caller has already shown that
245
+ * output, and a second answer spliced after it would be a different reply.
246
+ *
247
+ * An abort (the call's `signal`) stops a wait at once and is rethrown as the
248
+ * signal's reason, the same as an abort mid-request, so the loop still reads
249
+ * it as a clean stop.
250
+ */
251
+ export declare function withRetry<Req, Res>(primary: ModelInvocation<Req, Res>, options?: RetryOptions<Req, Res>): ModelInvocation<Req, Res>;
252
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/models/retry.ts"],"names":[],"mappings":"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"}