@actor0/harness 0.0.0-stage → 0.5.2

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.
@@ -0,0 +1,10 @@
1
+ export * from "./answer-filter.js";
2
+ export * from "./tool-call-block.js";
3
+ export * from "./harness.js";
4
+ export * from "./model-client.js";
5
+ export * from "./plan-prefix.js";
6
+ export * from "./protocol.js";
7
+ export * from "./reasoning-summary.js";
8
+ export * from "./tool-host.js";
9
+ export * from "./types.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export * from "./answer-filter.js";
2
+ export * from "./tool-call-block.js";
3
+ export * from "./harness.js";
4
+ export * from "./model-client.js";
5
+ export * from "./plan-prefix.js";
6
+ export * from "./protocol.js";
7
+ export * from "./reasoning-summary.js";
8
+ export * from "./tool-host.js";
9
+ export * from "./types.js";
@@ -0,0 +1,165 @@
1
+ import type { ChatMessage, ModelClient, ModelEvent, ToolDefinition } from "./types.js";
2
+ export declare class ModelTransportError extends Error {
3
+ readonly retriable: boolean;
4
+ readonly retryAfterMs?: number | undefined;
5
+ /**
6
+ * @param retryAfterMs how long the server asked us to wait, when it said.
7
+ * A retriable error that carries one has a floor under its next attempt:
8
+ * see `retryDelay` in harness.ts.
9
+ */
10
+ constructor(message: string, retriable?: boolean, retryAfterMs?: number | undefined);
11
+ }
12
+ /**
13
+ * The longest server-requested wait this harness will sit through.
14
+ *
15
+ * A windowed rate limit can name a reset twenty minutes out. Honouring that
16
+ * in a terminal means the turn disappears for twenty minutes with nothing on
17
+ * screen, which the user reads as a hang; ignoring it means the retries land
18
+ * inside the window and the turn fails having proved nothing. So the wait is
19
+ * honoured up to here, and past it the failure is surfaced instead, with the
20
+ * time the limit lifts in the message the user reads.
21
+ */
22
+ export declare const MAX_HONOURED_RETRY_AFTER_MS = 120000;
23
+ /**
24
+ * How long the server asked us to wait, in milliseconds.
25
+ *
26
+ * `Retry-After` is a count of seconds per RFC 9110, and an HTTP-date in the
27
+ * dialect several providers actually send. Both are honoured; a value that is
28
+ * neither is ignored rather than guessed at, because a misread directive is
29
+ * worse than no directive.
30
+ */
31
+ export declare function retryAfterMs(headers: Headers, now?: number): number | undefined;
32
+ export type OpenAiCompatibleOptions = {
33
+ baseUrl: string;
34
+ apiKey?: string;
35
+ model: string;
36
+ fetchImpl?: typeof fetch;
37
+ headers?: Record<string, string>;
38
+ /**
39
+ * Override the request path. Defaults to `/chat/completions` appended to
40
+ * `baseUrl`. Gateways and application proxies routinely expose an
41
+ * OpenAI-shaped endpoint somewhere else — `/api/chat`, a tunnel, a route
42
+ * that also serves HTML — and forcing every one of them to sit at
43
+ * `baseUrl + /chat/completions` would be a transport limitation leaking
44
+ * into every host that has to work around it.
45
+ */
46
+ path?: string;
47
+ /**
48
+ * Reasoning effort for models that support it (o-series and reasoning
49
+ * models). Sent as `reasoning_effort`; omitted entirely when unset, so a
50
+ * non-reasoning endpoint never sees an unknown field.
51
+ */
52
+ reasoningEffort?: "low" | "medium" | "high";
53
+ };
54
+ export declare class OpenAiCompatibleModel implements ModelClient {
55
+ private readonly endpoint;
56
+ private readonly apiKey?;
57
+ private readonly model;
58
+ private readonly fetchImpl;
59
+ private readonly headers;
60
+ private readonly reasoningEffort?;
61
+ constructor(options: OpenAiCompatibleOptions);
62
+ stream(messages: ChatMessage[], tools: ToolDefinition[], signal: AbortSignal): AsyncIterable<ModelEvent>;
63
+ }
64
+ /**
65
+ * True when a response is an HTML document rather than a stream or a JSON
66
+ * error. Gateways, edge runtimes and bot checks all answer this way, and none
67
+ * of them say so in the body: the caller has to read the shape.
68
+ */
69
+ export declare function looksLikeHtml(contentType: string | null, body: string | null): boolean; /** True when the response claims to be the event stream we asked for. */
70
+ /**
71
+ * Whether an error delivered *inside* a 200 response can be fixed by asking
72
+ * again.
73
+ *
74
+ * A 200 means the request was accepted, so the status classification above
75
+ * never runs — there is no status left to read. Everything then arrives in
76
+ * one shape, `data: {"error": {...}}`: a dropped upstream connection, a rate
77
+ * limit, a rejected key, a request that does not fit the context window.
78
+ * Calling all of them retriable, which is what this did, replays a
79
+ * deterministic failure three times with 1s/2s/4s of backoff, at four times the
80
+ * token cost, and ends in exactly the same error.
81
+ *
82
+ * Code and type are read first because they are exact, and because they are
83
+ * the part OpenAI, Anthropic, Gemini and OpenRouter all agree on. The message
84
+ * is the fallback for the servers that send neither. An unrecognised error
85
+ * stays retriable: a stream that died mid-flight is far more often a dropped
86
+ * connection than a request the server will never accept, and guessing wrong
87
+ * in that direction costs one wasted attempt, while guessing wrong the other
88
+ * way refuses to start the turn at all.
89
+ */
90
+ export declare function isRetriableStreamError(message: string, code?: string, type?: string): boolean;
91
+ /**
92
+ * Is this failure the conversation not fitting the model?
93
+ *
94
+ * Named because it is the one transport failure with a real recovery, and
95
+ * recovery is not the transport layer's job: the caller has to shorten the
96
+ * history and ask again, which is a decision about the conversation.
97
+ */
98
+ export declare function isContextOverflow(message: string): boolean;
99
+ /**
100
+ * Is this thrown value the model saying the request is too big?
101
+ *
102
+ * Asked of the error rather than of the message so a host does not have to
103
+ * know which layer raised it, or re-derive that a retriable failure of the
104
+ * same shape must not be compacted around. Both spellings land here: a 400
105
+ * whose body is the diagnosis, and an error frame inside a 200.
106
+ */
107
+ /**
108
+ * A request the endpoint will never accept, however often it is
109
+ * sent — the one transport failure with a host-level recovery
110
+ * (compact the history and ask again), which is why this is a
111
+ * classifier and not just a message match.
112
+ *
113
+ * It also looks through a `FailedTurnError`: a turn that failed
114
+ * mid-flight wraps the transport error that ended it (see
115
+ * `failedTurn`), and without the unwrap every such failure reads
116
+ * as an unknown error, so the recovery never fires and a turn the
117
+ * endpoint merely refused rewinds the session instead of being
118
+ * asked again. That makes the return a plain boolean rather than
119
+ * a type predicate — in the wrapped case the error is a
120
+ * `FailedTurnError`, not the `ModelTransportError` the old
121
+ * signature claimed — and its one caller reads it as a gate.
122
+ */
123
+ export declare function isContextOverflowError(error: unknown): boolean;
124
+ /**
125
+ * The context window the endpoint said it has, in tokens, or undefined.
126
+ *
127
+ * The overflow message is not only a diagnosis, it is the one measurement of
128
+ * the limit the provider will ever volunteer, and reading it as a boolean
129
+ * throws the number away. A host recovering from an overflow has to decide
130
+ * how much history to keep, and a guess cannot be smaller than the truth: on
131
+ * a 4k-window model a recovery that targets 8,000 tokens does not fit by
132
+ * construction, and the one replay it is allowed fails exactly like the
133
+ * request it was meant to fix.
134
+ *
135
+ * Anchored on the number *and* the word "token" on purpose. The messages that
136
+ * carry a limit also carry the count that broke it — "your messages resulted
137
+ * in 91234 tokens" — and a looser pattern reads the wrong number, which is
138
+ * worse than reading none. A per-message char limit is not a window and is
139
+ * not returned for one; `OVERFLOW_TEXT` matches that shape too, deliberately,
140
+ * because it is a different failure with its own advice.
141
+ *
142
+ * Returned only for a failure that is a real refusal, so a retriable error
143
+ * carrying a similar string cannot talk a host into compacting a turn that
144
+ * was never the problem.
145
+ */
146
+ export declare function contextWindowTokens(error: unknown): number | undefined;
147
+ /**
148
+ * A failure message a person can act on.
149
+ *
150
+ * The endpoint is included because "request failed" tells the reader nothing
151
+ * when three of them are configured, and the status because a body alone
152
+ * cannot distinguish a rate limit from a crash. An HTML body is summarised
153
+ * rather than quoted: the previous behaviour pasted its first 600 characters
154
+ * into the transcript, which buried a one-line diagnosis under a wall of markup
155
+ * and still omitted the two facts that would have identified the fault.
156
+ *
157
+ * The closing line is derived from `retriable`, never from a guess about what
158
+ * "usually" happens. Telling someone a 403 will be retried when it will not is
159
+ * worse than saying nothing, because they wait for a retry that never comes.
160
+ *
161
+ * The URL is safe to print — the constructor clears any query string, so a key
162
+ * passed as a query parameter is already gone by this point.
163
+ */
164
+ export declare function describeHttpFailure(endpoint: string, response: Response, body: string, retriable: boolean, retryAfterMs?: number): string;
165
+ //# sourceMappingURL=model-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-client.d.ts","sourceRoot":"","sources":["../src/model-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAY,cAAc,EAAS,MAAM,YAAY,CAAC;AAExG,qBAAa,mBAAoB,SAAQ,KAAK;IAMf,QAAQ,CAAC,SAAS;IAAU,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM;IALvF;;;;OAIG;gBACS,OAAO,EAAE,MAAM,EAAW,SAAS,UAAQ,EAAW,YAAY,CAAC,EAAE,MAAM,YAAA;CAIxF;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,2BAA2B,SAAU,CAAC;AAEnD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,GAAE,MAAmB,GAAG,MAAM,GAAG,SAAS,CAa3F;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,eAAe,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC7C,CAAC;AAyBF,qBAAa,qBAAsB,YAAW,WAAW;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAA4B;gBAEjD,OAAO,EAAE,uBAAuB;IAqBrC,MAAM,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,MAAM,EAAE,WAAW,GAAG,aAAa,CAAC,UAAU,CAAC;CA+GhH;AAkGD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAMtF,CAAA,yEAAyE;AA0B1E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAQ7F;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;;;;;;GAOG;AACH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG9D;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAStE;AAqGD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,OAAO,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,CAyBR"}