@owlmeans/llm 0.1.14
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 +193 -0
- package/agent-meta/instructions/llm.instructions.md +66 -0
- package/agent-meta/manifest.json +23 -0
- package/agent-meta/skills/llm/SKILL.md +121 -0
- package/build/consts.d.ts +67 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +76 -0
- package/build/consts.js.map +1 -0
- package/build/errors.d.ts +33 -0
- package/build/errors.d.ts.map +1 -0
- package/build/errors.js +52 -0
- package/build/errors.js.map +1 -0
- package/build/execution/index.d.ts +4 -0
- package/build/execution/index.d.ts.map +1 -0
- package/build/execution/index.js +3 -0
- package/build/execution/index.js.map +1 -0
- package/build/execution/service.d.ts +21 -0
- package/build/execution/service.d.ts.map +1 -0
- package/build/execution/service.js +129 -0
- package/build/execution/service.js.map +1 -0
- package/build/execution/types.d.ts +119 -0
- package/build/execution/types.d.ts.map +1 -0
- package/build/execution/types.js +2 -0
- package/build/execution/types.js.map +1 -0
- package/build/execution/utils.d.ts +28 -0
- package/build/execution/utils.d.ts.map +1 -0
- package/build/execution/utils.js +60 -0
- package/build/execution/utils.js.map +1 -0
- package/build/helpers/index.d.ts +5 -0
- package/build/helpers/index.d.ts.map +1 -0
- package/build/helpers/index.js +5 -0
- package/build/helpers/index.js.map +1 -0
- package/build/helpers/json.d.ts +24 -0
- package/build/helpers/json.d.ts.map +1 -0
- package/build/helpers/json.js +119 -0
- package/build/helpers/json.js.map +1 -0
- package/build/helpers/messages.d.ts +10 -0
- package/build/helpers/messages.d.ts.map +1 -0
- package/build/helpers/messages.js +9 -0
- package/build/helpers/messages.js.map +1 -0
- package/build/helpers/retry.d.ts +18 -0
- package/build/helpers/retry.d.ts.map +1 -0
- package/build/helpers/retry.js +57 -0
- package/build/helpers/retry.js.map +1 -0
- package/build/helpers/spectate.d.ts +8 -0
- package/build/helpers/spectate.d.ts.map +1 -0
- package/build/helpers/spectate.js +54 -0
- package/build/helpers/spectate.js.map +1 -0
- package/build/index.d.ts +13 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +11 -0
- package/build/index.js.map +1 -0
- package/build/model.d.ts +12 -0
- package/build/model.d.ts.map +1 -0
- package/build/model.js +297 -0
- package/build/model.js.map +1 -0
- package/build/plugins/anthropic.d.ts +4 -0
- package/build/plugins/anthropic.d.ts.map +1 -0
- package/build/plugins/anthropic.js +86 -0
- package/build/plugins/anthropic.js.map +1 -0
- package/build/plugins/compatible.d.ts +18 -0
- package/build/plugins/compatible.d.ts.map +1 -0
- package/build/plugins/compatible.js +54 -0
- package/build/plugins/compatible.js.map +1 -0
- package/build/plugins/export.d.ts +6 -0
- package/build/plugins/export.d.ts.map +1 -0
- package/build/plugins/export.js +5 -0
- package/build/plugins/export.js.map +1 -0
- package/build/plugins/index.d.ts +18 -0
- package/build/plugins/index.d.ts.map +1 -0
- package/build/plugins/index.js +42 -0
- package/build/plugins/index.js.map +1 -0
- package/build/plugins/openai.d.ts +28 -0
- package/build/plugins/openai.d.ts.map +1 -0
- package/build/plugins/openai.js +89 -0
- package/build/plugins/openai.js.map +1 -0
- package/build/plugins/types.d.ts +80 -0
- package/build/plugins/types.d.ts.map +1 -0
- package/build/plugins/types.js +2 -0
- package/build/plugins/types.js.map +1 -0
- package/build/plugins/utils.d.ts +27 -0
- package/build/plugins/utils.d.ts.map +1 -0
- package/build/plugins/utils.js +33 -0
- package/build/plugins/utils.js.map +1 -0
- package/build/service.d.ts +24 -0
- package/build/service.d.ts.map +1 -0
- package/build/service.js +95 -0
- package/build/service.js.map +1 -0
- package/build/types.d.ts +190 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/build/utils/config.d.ts +13 -0
- package/build/utils/config.d.ts.map +1 -0
- package/build/utils/config.js +15 -0
- package/build/utils/config.js.map +1 -0
- package/build/utils/null-report.d.ts +36 -0
- package/build/utils/null-report.d.ts.map +1 -0
- package/build/utils/null-report.js +84 -0
- package/build/utils/null-report.js.map +1 -0
- package/build/utils/prompt.d.ts +15 -0
- package/build/utils/prompt.d.ts.map +1 -0
- package/build/utils/prompt.js +45 -0
- package/build/utils/prompt.js.map +1 -0
- package/build/utils/schema.d.ts +20 -0
- package/build/utils/schema.d.ts.map +1 -0
- package/build/utils/schema.js +28 -0
- package/build/utils/schema.js.map +1 -0
- package/build/utils/stream.d.ts +22 -0
- package/build/utils/stream.d.ts.map +1 -0
- package/build/utils/stream.js +54 -0
- package/build/utils/stream.js.map +1 -0
- package/package.json +65 -0
- package/src/consts.ts +89 -0
- package/src/errors.ts +65 -0
- package/src/execution/index.ts +4 -0
- package/src/execution/service.ts +185 -0
- package/src/execution/types.ts +139 -0
- package/src/execution/utils.ts +79 -0
- package/src/helpers/index.ts +5 -0
- package/src/helpers/json.ts +117 -0
- package/src/helpers/messages.ts +12 -0
- package/src/helpers/retry.ts +59 -0
- package/src/helpers/spectate.ts +67 -0
- package/src/index.ts +13 -0
- package/src/model.ts +379 -0
- package/src/plugins/anthropic.ts +97 -0
- package/src/plugins/compatible.ts +62 -0
- package/src/plugins/export.ts +6 -0
- package/src/plugins/index.ts +53 -0
- package/src/plugins/openai.ts +108 -0
- package/src/plugins/types.ts +92 -0
- package/src/plugins/utils.ts +38 -0
- package/src/service.ts +125 -0
- package/src/types.ts +214 -0
- package/src/utils/config.ts +19 -0
- package/src/utils/null-report.ts +126 -0
- package/src/utils/prompt.ts +46 -0
- package/src/utils/schema.ts +35 -0
- package/src/utils/stream.ts +58 -0
- package/tests/context.ts +110 -0
- package/tests/execution.spec.ts +200 -0
- package/tests/helpers.spec.ts +192 -0
- package/tests/internals.spec.ts +141 -0
- package/tests/model.spec.ts +116 -0
- package/tests/plugins.spec.ts +227 -0
- package/tsconfig.json +19 -0
package/build/types.d.ts
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
|
2
|
+
import type { AIMessage, BaseMessage, MessageFieldWithRole } from '@langchain/core/messages';
|
|
3
|
+
import type { BaseCallbackHandler, CallbackHandlerMethods } from '@langchain/core/callbacks/base';
|
|
4
|
+
import type { JSONSchemaType } from 'ajv';
|
|
5
|
+
import type { InitializedService } from '@owlmeans/context';
|
|
6
|
+
import type { LlmPurpose, ModelProvider, NullCapture, SpectatorArgument, SpectatorEntryLogged } from '@owlmeans/llm-common';
|
|
7
|
+
export type MaybeArray<T> = T | T[];
|
|
8
|
+
/**
|
|
9
|
+
* Out-of-band result channel for a model call: the caller passes a `ref` and receives
|
|
10
|
+
* the raw message, the spectator entry it was logged under, and an optional callback
|
|
11
|
+
* fired as soon as the value is known (before the caller's own await resolves).
|
|
12
|
+
*/
|
|
13
|
+
export interface RefferedResult<T> {
|
|
14
|
+
spectatorEntry?: SpectatorEntryLogged;
|
|
15
|
+
value?: T;
|
|
16
|
+
callback?: (arg: T) => Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export interface RetryOptions {
|
|
19
|
+
retries: number;
|
|
20
|
+
outputErrors?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Abort the retry loop for this call. Return the error to throw, or `null` to keep
|
|
23
|
+
* retrying. Consulted in addition to the globally registered resolvers
|
|
24
|
+
* (`registerFatalError`) and the provider plugins' `isFatal`.
|
|
25
|
+
*/
|
|
26
|
+
fatal?: (e: unknown) => Error | null;
|
|
27
|
+
}
|
|
28
|
+
/** Decides whether an error must abort a retry loop instead of being retried. */
|
|
29
|
+
export interface FatalErrorResolver {
|
|
30
|
+
(e: unknown): Error | null;
|
|
31
|
+
}
|
|
32
|
+
export interface LlmLogging {
|
|
33
|
+
/** Print every swallowed retry error to the console. */
|
|
34
|
+
outputErrors?: boolean;
|
|
35
|
+
/** Hand a full {@link NullCapture} to the spectator when a call returns nothing usable. */
|
|
36
|
+
captureNull?: boolean;
|
|
37
|
+
purpose: LlmPurpose;
|
|
38
|
+
}
|
|
39
|
+
export interface LlmModelOptions extends LlmLogging {
|
|
40
|
+
model: BaseChatModel;
|
|
41
|
+
retries?: number;
|
|
42
|
+
}
|
|
43
|
+
export type ModelMessage = BaseMessage | MessageFieldWithRole;
|
|
44
|
+
export type ModelInputItem = ModelMessage | string;
|
|
45
|
+
export type ModelInput = MaybeArray<ModelInputItem>;
|
|
46
|
+
export interface LlmCallOptions {
|
|
47
|
+
/** Short name of the operation — used as the LangChain run name and in spectator entries. */
|
|
48
|
+
action: string;
|
|
49
|
+
/** Ask the provider to cache the prompt prefix (no-op for providers without prompt caching). */
|
|
50
|
+
useCache?: boolean;
|
|
51
|
+
/** How many leading messages to mark as cacheable (capped by the provider's own limit). */
|
|
52
|
+
cacheMax?: number;
|
|
53
|
+
}
|
|
54
|
+
export interface LlmAskOptions extends LlmCallOptions {
|
|
55
|
+
ref?: RefferedResult<AIMessage>;
|
|
56
|
+
filter?: (output: string, result: AIMessage) => (string | null) | Promise<string | null>;
|
|
57
|
+
}
|
|
58
|
+
export interface LlmTalkOptions extends LlmCallOptions {
|
|
59
|
+
ref?: RefferedResult<AIMessage>;
|
|
60
|
+
filter?: (result: AIMessage) => Promise<AIMessage | null>;
|
|
61
|
+
}
|
|
62
|
+
export interface LlmInvokeOptions<T> extends LlmCallOptions {
|
|
63
|
+
temperature?: number | undefined;
|
|
64
|
+
ref?: RefferedResult<AIMessage>;
|
|
65
|
+
filter?: (output: T, result: AIMessage) => (T | null) | Promise<T | null>;
|
|
66
|
+
}
|
|
67
|
+
export interface LlmRequestOptions extends LlmCallOptions {
|
|
68
|
+
ref?: RefferedResult<AIMessage>;
|
|
69
|
+
filter?: (result: AIMessage) => Promise<AIMessage | null>;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The four ways to talk to a model. Every method streams under an idle deadline,
|
|
73
|
+
* retries with escalating output budget, logs to the spectator and validates the result.
|
|
74
|
+
*
|
|
75
|
+
* - `ask` → plain text.
|
|
76
|
+
* - `talk` → the raw `AIMessage`.
|
|
77
|
+
* - `invoke` → a schema-validated object.
|
|
78
|
+
* - `request` → an `AIMessage` whose `content` is the schema-validated JSON.
|
|
79
|
+
*/
|
|
80
|
+
export interface LlmModel {
|
|
81
|
+
ask: (input: ModelInput, options: LlmAskOptions) => Promise<string>;
|
|
82
|
+
talk: (input: ModelInput, options: LlmTalkOptions) => Promise<AIMessage>;
|
|
83
|
+
invoke: <T>(input: ModelInput, schema: JSONSchemaType<T>, options: LlmInvokeOptions<T>) => Promise<T>;
|
|
84
|
+
request: <T>(input: ModelInput, schema: JSONSchemaType<T>, options: LlmRequestOptions) => Promise<AIMessage>;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Observability sink the model writes every call to. Deliberately minimal — a consumer's
|
|
88
|
+
* richer spectator (with `derive`, `update`, storage backends) satisfies it structurally.
|
|
89
|
+
*/
|
|
90
|
+
export interface LlmSpectator {
|
|
91
|
+
log: (arg: SpectatorArgument) => Promise<SpectatorEntryLogged>;
|
|
92
|
+
/** Optional sink for full diagnostics of a call that returned nothing usable. */
|
|
93
|
+
captureNull?: (capture: NullCapture) => Promise<void>;
|
|
94
|
+
}
|
|
95
|
+
/** Resolves a model of the same role at a different temperature. */
|
|
96
|
+
export interface TemperatureFactory {
|
|
97
|
+
(temperature?: number | undefined): BaseChatModel;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Full runtime configuration of one model alias. The JSON-safe subset that may travel
|
|
101
|
+
* inside an execution state is `ModelConfigPatch` (`@owlmeans/llm-common`) — this type
|
|
102
|
+
* additionally carries credentials and provider wiring and must never be serialized.
|
|
103
|
+
*/
|
|
104
|
+
export interface ModelConfig {
|
|
105
|
+
provider?: ModelProvider | string;
|
|
106
|
+
secret?: string;
|
|
107
|
+
alias: string;
|
|
108
|
+
/** Inherit every field of another alias in the same config list. */
|
|
109
|
+
preset?: string;
|
|
110
|
+
model?: string;
|
|
111
|
+
temperature?: number;
|
|
112
|
+
/** Initial output-token budget per request (`max_tokens`). */
|
|
113
|
+
maxTokens?: number;
|
|
114
|
+
/**
|
|
115
|
+
* Hard ceiling for output tokens used by the retry escalator. Each retry doubles
|
|
116
|
+
* `maxTokens` toward this cap; without it the escalator uses
|
|
117
|
+
* {@link DEFAULT_MAX_OUTPUT_CAP}, which exceeds many models' real per-request output
|
|
118
|
+
* limit and turns retries into 400 "max_tokens exceeds model limit" errors.
|
|
119
|
+
*/
|
|
120
|
+
maxTokensCap?: number;
|
|
121
|
+
topP?: number;
|
|
122
|
+
baseUrl?: string;
|
|
123
|
+
organization?: string;
|
|
124
|
+
/** Provider-routing hint for aggregators that expose one (e.g. HuggingFace). */
|
|
125
|
+
inferenceProvider?: string;
|
|
126
|
+
headers?: Record<string, string>;
|
|
127
|
+
/**
|
|
128
|
+
* Suppress the model's chain-of-thought / "thinking" tokens. For the Qwen3 family
|
|
129
|
+
* this injects the `/no_think` soft switch into the prompt; without it those models
|
|
130
|
+
* routinely spend the entire output budget on hidden reasoning and return empty
|
|
131
|
+
* content with `finish_reason="length"`.
|
|
132
|
+
*/
|
|
133
|
+
disableThinking?: boolean;
|
|
134
|
+
/**
|
|
135
|
+
* OpenAI-compatible reasoning control, forwarded verbatim as the top-level `reasoning`
|
|
136
|
+
* request-body field. Use `{ max_tokens: N }` to hard-cap the thinking budget —
|
|
137
|
+
* universal, and it works even for always-reasoning models (the request `max_tokens`
|
|
138
|
+
* must stay strictly higher) — or `{ effort: 'none' }` to disable thinking on hybrid
|
|
139
|
+
* models that enumerate effort levels. `{ exclude: true }` keeps reasoning internal but
|
|
140
|
+
* omits it from the response.
|
|
141
|
+
*/
|
|
142
|
+
reasoning?: {
|
|
143
|
+
effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
|
|
144
|
+
max_tokens?: number;
|
|
145
|
+
exclude?: boolean;
|
|
146
|
+
enabled?: boolean;
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Force how `invoke`/`request` obtain structured output, overriding the provider
|
|
150
|
+
* plugin's default: `true` → the provider's NATIVE JSON-schema mode, `false` → the
|
|
151
|
+
* forced-`tool_choice` tool-calling hack. Plugins that support only one mode
|
|
152
|
+
* (Anthropic — tool calling) ignore this flag.
|
|
153
|
+
*/
|
|
154
|
+
structuredOutput?: boolean;
|
|
155
|
+
/**
|
|
156
|
+
* Idle/inactivity timeout (ms) for a streamed response. NOT a total cap — the timer
|
|
157
|
+
* resets on every chunk. Falls back to {@link MODEL_STREAM_TIMEOUT_MS}.
|
|
158
|
+
*/
|
|
159
|
+
streamTimeout?: number;
|
|
160
|
+
/**
|
|
161
|
+
* Stronger model the retry escalator switches to once the primary has failed
|
|
162
|
+
* {@link FALLBACK_AFTER_ATTEMPTS} times. Specified inline as a partial config merged
|
|
163
|
+
* over the base config, so it inherits `secret`, `headers`, etc. The escalation only
|
|
164
|
+
* happens when the fallback belongs to the SAME plugin family as the primary —
|
|
165
|
+
* rotating providers mid-call would flip the structured-output format.
|
|
166
|
+
*/
|
|
167
|
+
fallback?: Partial<ModelConfig>;
|
|
168
|
+
}
|
|
169
|
+
export interface LlmServiceOptions {
|
|
170
|
+
/** The full config list; resolved by `alias` on every `getModel` call. */
|
|
171
|
+
models: () => ModelConfig[];
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Model factory and registry. Builds a `BaseChatModel` from a `ModelConfig` through the
|
|
175
|
+
* registered provider plugins, memoizing per alias+override so repeated resolution of a
|
|
176
|
+
* role does not rebuild the client.
|
|
177
|
+
*/
|
|
178
|
+
export interface LlmService extends InitializedService {
|
|
179
|
+
models: Map<string, BaseChatModel>;
|
|
180
|
+
callbacks: (BaseCallbackHandler | CallbackHandlerMethods)[];
|
|
181
|
+
addCallbacks: (callbacks: (BaseCallbackHandler | CallbackHandlerMethods)[]) => void;
|
|
182
|
+
/** Resolve (and cache) the model registered under `alias`, with an optional patch. */
|
|
183
|
+
getModel: (alias: string, override?: Partial<ModelConfig>, createNew?: boolean) => BaseChatModel;
|
|
184
|
+
/** The configured model list, as supplied by {@link LlmServiceOptions.models}. */
|
|
185
|
+
configs: () => ModelConfig[];
|
|
186
|
+
}
|
|
187
|
+
export interface WithLlmService {
|
|
188
|
+
llm: () => LlmService;
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/build/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
|
2
|
+
import type { ModelConfig } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Read the original `ModelConfig` back off a model instance. Every plugin's `build`
|
|
5
|
+
* passes `metadata: { config }` on the client constructor, so the config is reachable
|
|
6
|
+
* for any provider. Returns an empty object when unavailable — notably for a REFINED
|
|
7
|
+
* instance, which is rebuilt from `lc_kwargs` and does not reliably carry metadata.
|
|
8
|
+
* That is why callers read the config from the ORIGINAL model.
|
|
9
|
+
*/
|
|
10
|
+
export declare const readConfig: (model: BaseChatModel) => Partial<ModelConfig>;
|
|
11
|
+
/** Per-model idle stream timeout (ms), falling back to the package default. */
|
|
12
|
+
export declare const idleTimeout: (config: Partial<ModelConfig>) => number;
|
|
13
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAA;AAEhF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,aAAa,KAAG,OAAO,CAAC,WAAW,CAGpE,CAAA;AAED,+EAA+E;AAC/E,eAAO,MAAM,WAAW,GAAI,QAAQ,OAAO,CAAC,WAAW,CAAC,KAAG,MACV,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { MODEL_STREAM_TIMEOUT_MS } from '../consts.js';
|
|
2
|
+
/**
|
|
3
|
+
* Read the original `ModelConfig` back off a model instance. Every plugin's `build`
|
|
4
|
+
* passes `metadata: { config }` on the client constructor, so the config is reachable
|
|
5
|
+
* for any provider. Returns an empty object when unavailable — notably for a REFINED
|
|
6
|
+
* instance, which is rebuilt from `lc_kwargs` and does not reliably carry metadata.
|
|
7
|
+
* That is why callers read the config from the ORIGINAL model.
|
|
8
|
+
*/
|
|
9
|
+
export const readConfig = (model) => {
|
|
10
|
+
const meta = model.metadata;
|
|
11
|
+
return meta?.config ?? {};
|
|
12
|
+
};
|
|
13
|
+
/** Per-model idle stream timeout (ms), falling back to the package default. */
|
|
14
|
+
export const idleTimeout = (config) => config.streamTimeout ?? MODEL_STREAM_TIMEOUT_MS;
|
|
15
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAA;AAGtD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAoB,EAAwB,EAAE;IACvE,MAAM,IAAI,GAAI,KAAqE,CAAC,QAAQ,CAAA;IAC5F,OAAO,IAAI,EAAE,MAAM,IAAI,EAAE,CAAA;AAC3B,CAAC,CAAA;AAED,+EAA+E;AAC/E,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAA4B,EAAU,EAAE,CAClE,MAAM,CAAC,aAAa,IAAI,uBAAuB,CAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { AIMessageChunk, MessageFieldWithRole } from '@langchain/core/messages';
|
|
2
|
+
import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
|
3
|
+
import type { LlmPurpose, NullCapture, NullKind } from '@owlmeans/llm-common';
|
|
4
|
+
import type { LlmSpectator, ModelConfig } from '../types.js';
|
|
5
|
+
export interface NullReportParams {
|
|
6
|
+
kind: NullKind;
|
|
7
|
+
action: string;
|
|
8
|
+
purpose?: LlmPurpose;
|
|
9
|
+
attempt: number;
|
|
10
|
+
startedAt: number;
|
|
11
|
+
/** The instance that actually ran — its `lc_kwargs` carry the effective request shape. */
|
|
12
|
+
refined: BaseChatModel;
|
|
13
|
+
/** The ORIGINAL model config (refined instances do not reliably keep metadata). */
|
|
14
|
+
config: Partial<ModelConfig>;
|
|
15
|
+
msgs: MessageFieldWithRole[];
|
|
16
|
+
raw: AIMessageChunk | null;
|
|
17
|
+
schema?: {
|
|
18
|
+
toolName: string;
|
|
19
|
+
innerSchema: unknown;
|
|
20
|
+
};
|
|
21
|
+
useCache: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Assemble a complete, replayable record of a model call that returned nothing usable:
|
|
25
|
+
* the effective request, the raw response with its metadata, and the diagnostics that
|
|
26
|
+
* distinguish the common causes (budget spent on hidden reasoning vs. a refused tool
|
|
27
|
+
* call vs. an empty content array).
|
|
28
|
+
*/
|
|
29
|
+
export declare const buildNullReport: (p: NullReportParams) => NullCapture;
|
|
30
|
+
/**
|
|
31
|
+
* Print the diagnostics of a null result, and hand the full capture to the spectator
|
|
32
|
+
* sink when the caller opted into capturing. A failing sink must never mask the model
|
|
33
|
+
* error the caller is about to throw.
|
|
34
|
+
*/
|
|
35
|
+
export declare const reportNull: (spectator: LlmSpectator, captureNull: boolean, p: NullReportParams) => Promise<void>;
|
|
36
|
+
//# sourceMappingURL=null-report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"null-report.d.ts","sourceRoot":"","sources":["../../src/utils/null-report.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AACpF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAA;AAEhF,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,QAAQ,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,UAAU,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,0FAA0F;IAC1F,OAAO,EAAE,aAAa,CAAA;IACtB,mFAAmF;IACnF,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IAC5B,IAAI,EAAE,oBAAoB,EAAE,CAAA;IAC5B,GAAG,EAAE,cAAc,GAAG,IAAI,CAAA;IAC1B,MAAM,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE,CAAA;IACnD,QAAQ,EAAE,OAAO,CAAA;CAClB;AAKD;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,GAAG,gBAAgB,KAAG,WA4DrD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,GACrB,WAAW,YAAY,EACvB,aAAa,OAAO,EACpB,GAAG,gBAAgB,KAClB,OAAO,CAAC,IAAI,CAsBd,CAAA"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import util from 'util';
|
|
2
|
+
import { createIdOfLength } from '@owlmeans/basic-ids';
|
|
3
|
+
/** How many characters of each prompt message the console preview keeps. */
|
|
4
|
+
const PREVIEW_CHARS = 300;
|
|
5
|
+
/**
|
|
6
|
+
* Assemble a complete, replayable record of a model call that returned nothing usable:
|
|
7
|
+
* the effective request, the raw response with its metadata, and the diagnostics that
|
|
8
|
+
* distinguish the common causes (budget spent on hidden reasoning vs. a refused tool
|
|
9
|
+
* call vs. an empty content array).
|
|
10
|
+
*/
|
|
11
|
+
export const buildNullReport = (p) => {
|
|
12
|
+
const kwargs = p.refined.lc_kwargs;
|
|
13
|
+
const raw = p.raw;
|
|
14
|
+
const responseMeta = raw?.response_metadata;
|
|
15
|
+
const usageMeta = raw?.usage_metadata;
|
|
16
|
+
const toolCalls = raw?.tool_calls;
|
|
17
|
+
return {
|
|
18
|
+
meta: {
|
|
19
|
+
kind: p.kind,
|
|
20
|
+
action: p.action,
|
|
21
|
+
purpose: p.purpose,
|
|
22
|
+
attempt: p.attempt,
|
|
23
|
+
id: createIdOfLength(12),
|
|
24
|
+
timestamp: Date.now(),
|
|
25
|
+
elapsedMs: Date.now() - p.startedAt,
|
|
26
|
+
},
|
|
27
|
+
model: {
|
|
28
|
+
// The provider-side model slug (needed for replay); falls back to the config alias.
|
|
29
|
+
id: kwargs.model ?? p.config.model,
|
|
30
|
+
provider: p.config.provider,
|
|
31
|
+
baseUrl: kwargs.configuration?.baseURL,
|
|
32
|
+
maxTokens: p.refined.maxTokens,
|
|
33
|
+
reasoning: kwargs.modelKwargs?.reasoning,
|
|
34
|
+
temperature: p.refined.temperature,
|
|
35
|
+
topP: kwargs.topP,
|
|
36
|
+
},
|
|
37
|
+
request: {
|
|
38
|
+
messages: p.msgs,
|
|
39
|
+
schema: p.schema,
|
|
40
|
+
useCache: p.useCache,
|
|
41
|
+
},
|
|
42
|
+
response: raw != null ? {
|
|
43
|
+
content: raw.content,
|
|
44
|
+
additional_kwargs: raw.additional_kwargs,
|
|
45
|
+
response_metadata: raw.response_metadata,
|
|
46
|
+
usage_metadata: raw.usage_metadata,
|
|
47
|
+
tool_calls: toolCalls,
|
|
48
|
+
} : null,
|
|
49
|
+
diagnostics: {
|
|
50
|
+
finishReason: responseMeta?.finish_reason,
|
|
51
|
+
inputTokens: usageMeta?.input_tokens ?? responseMeta?.usage?.prompt_tokens,
|
|
52
|
+
outputTokens: usageMeta?.output_tokens ?? responseMeta?.usage?.completion_tokens,
|
|
53
|
+
reasoningTokens: responseMeta?.usage?.reasoning_tokens,
|
|
54
|
+
contentEmpty: raw == null || raw.content === '' || raw.content == null
|
|
55
|
+
|| (Array.isArray(raw.content) && raw.content.length === 0),
|
|
56
|
+
hadToolCall: Array.isArray(toolCalls) && toolCalls.length > 0,
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Print the diagnostics of a null result, and hand the full capture to the spectator
|
|
62
|
+
* sink when the caller opted into capturing. A failing sink must never mask the model
|
|
63
|
+
* error the caller is about to throw.
|
|
64
|
+
*/
|
|
65
|
+
export const reportNull = async (spectator, captureNull, p) => {
|
|
66
|
+
const capture = buildNullReport(p);
|
|
67
|
+
const requestPreview = p.msgs.map(msg => {
|
|
68
|
+
const text = typeof msg.content === 'string' ? msg.content.substring(0, PREVIEW_CHARS) : '[complex content]';
|
|
69
|
+
return `[${msg.role ?? 'unknown'}] ${text}`;
|
|
70
|
+
}).join('\n---\n');
|
|
71
|
+
console.error('[MODEL-NULL]', util.inspect({
|
|
72
|
+
meta: capture.meta, model: capture.model, diagnostics: capture.diagnostics,
|
|
73
|
+
response: capture.response, requestPreview,
|
|
74
|
+
}, { depth: null, maxStringLength: 2000, breakLength: 120 }));
|
|
75
|
+
if (captureNull) {
|
|
76
|
+
try {
|
|
77
|
+
await spectator.captureNull?.(capture);
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
console.warn('[MODEL-NULL] capture write failed', e);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=null-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"null-report.js","sourceRoot":"","sources":["../../src/utils/null-report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { MessageFieldWithRole } from '@langchain/core/messages';
|
|
2
|
+
/**
|
|
3
|
+
* Ensure the word "json" appears somewhere in the prompt. Several providers refuse or
|
|
4
|
+
* silently ignore a JSON mode unless it does; when it is missing the JSON instruction is
|
|
5
|
+
* appended in place.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ensureJsonMention: (msgs: MessageFieldWithRole[]) => void;
|
|
8
|
+
/**
|
|
9
|
+
* Append the `/no_think` soft switch when the config asks for it. Without it,
|
|
10
|
+
* thinking-mode models frequently spend their entire output budget on hidden reasoning
|
|
11
|
+
* and return empty content with `finish_reason="length"`, which then fails every filter
|
|
12
|
+
* and exhausts the retries.
|
|
13
|
+
*/
|
|
14
|
+
export declare const applyNoThink: (msgs: MessageFieldWithRole[], disableThinking: boolean | undefined) => void;
|
|
15
|
+
//# sourceMappingURL=prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/utils/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AAyBpE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,oBAAoB,EAAE,KAAG,IAGhE,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,oBAAoB,EAAE,EAAE,iBAAiB,OAAO,GAAG,SAAS,KAAG,IAIjG,CAAA"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { JSON_INSTRUCTION, NO_THINK_DIRECTIVE } from '../consts.js';
|
|
2
|
+
const messageMentions = (msg, needle) => {
|
|
3
|
+
if (typeof msg.content === 'string')
|
|
4
|
+
return msg.content.toLowerCase().includes(needle);
|
|
5
|
+
if (Array.isArray(msg.content)) {
|
|
6
|
+
return msg.content.some((part) => typeof part === 'object' && part !== null && 'text' in part
|
|
7
|
+
&& typeof part.text === 'string'
|
|
8
|
+
&& part.text.toLowerCase().includes(needle));
|
|
9
|
+
}
|
|
10
|
+
return false;
|
|
11
|
+
};
|
|
12
|
+
/** Append `text` to the last message, or push it as a new user message when that is not possible. */
|
|
13
|
+
const appendDirective = (msgs, text) => {
|
|
14
|
+
const last = msgs[msgs.length - 1];
|
|
15
|
+
if (last != null && typeof last.content === 'string') {
|
|
16
|
+
last.content = `${last.content}\n${text}`;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
msgs.push({ role: 'user', content: text });
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Ensure the word "json" appears somewhere in the prompt. Several providers refuse or
|
|
24
|
+
* silently ignore a JSON mode unless it does; when it is missing the JSON instruction is
|
|
25
|
+
* appended in place.
|
|
26
|
+
*/
|
|
27
|
+
export const ensureJsonMention = (msgs) => {
|
|
28
|
+
if (msgs.some(msg => messageMentions(msg, 'json')))
|
|
29
|
+
return;
|
|
30
|
+
appendDirective(msgs, JSON_INSTRUCTION);
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Append the `/no_think` soft switch when the config asks for it. Without it,
|
|
34
|
+
* thinking-mode models frequently spend their entire output budget on hidden reasoning
|
|
35
|
+
* and return empty content with `finish_reason="length"`, which then fails every filter
|
|
36
|
+
* and exhausts the retries.
|
|
37
|
+
*/
|
|
38
|
+
export const applyNoThink = (msgs, disableThinking) => {
|
|
39
|
+
if (disableThinking !== true)
|
|
40
|
+
return;
|
|
41
|
+
if (msgs.some(msg => typeof msg.content === 'string' && msg.content.includes(NO_THINK_DIRECTIVE)))
|
|
42
|
+
return;
|
|
43
|
+
appendDirective(msgs, NO_THINK_DIRECTIVE);
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/utils/prompt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAEnE,MAAM,eAAe,GAAG,CAAC,GAAyB,EAAE,MAAc,EAAW,EAAE;IAC7E,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IACtF,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/B,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CACrB,CAAC,IAAa,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,MAAM,IAAK,IAAgC;eACtG,OAAQ,IAA+B,CAAC,IAAI,KAAK,QAAQ;eACxD,IAA+B,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAC1E,CAAA;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED,qGAAqG;AACrG,MAAM,eAAe,GAAG,CAAC,IAA4B,EAAE,IAAY,EAAQ,EAAE;IAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAClC,IAAI,IAAI,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACrD,IAAI,CAAC,OAAO,GAAG,GAAG,IAAI,CAAC,OAAO,KAAK,IAAI,EAAE,CAAA;IAC3C,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;IAC5C,CAAC;AACH,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAA4B,EAAQ,EAAE;IACtE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAAE,OAAM;IAC1D,eAAe,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAA;AACzC,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAA4B,EAAE,eAAoC,EAAQ,EAAE;IACvG,IAAI,eAAe,KAAK,IAAI;QAAE,OAAM;IACpC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;QAAE,OAAM;IACzG,eAAe,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAA;AAC3C,CAAC,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Ajv, JSONSchemaType, ValidateFunction } from 'ajv';
|
|
2
|
+
/**
|
|
3
|
+
* Split the caller's schema into the optional wrapper `name` and the schema proper, and
|
|
4
|
+
* compile a validator for the latter. A `name` means the model is expected to answer
|
|
5
|
+
* `{ [name]: <object> }`; see {@link unwrapNamed}.
|
|
6
|
+
*/
|
|
7
|
+
export declare const resolveSchemaValidator: <T>(ajv: Ajv, schema: JSONSchemaType<T>) => {
|
|
8
|
+
name: string | undefined;
|
|
9
|
+
innerSchema: JSONSchemaType<T>;
|
|
10
|
+
validate: ValidateFunction<T>;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Derive a function/tool name for tool-calling structured output. Provider tool names
|
|
14
|
+
* must match `^[A-Za-z0-9_-]+$`, so the schema title/name is sanitised; falls back to
|
|
15
|
+
* {@link DEFAULT_TOOL_NAME} when nothing usable is present.
|
|
16
|
+
*/
|
|
17
|
+
export declare const toToolName: (raw: string | undefined) => string;
|
|
18
|
+
/** Unwrap `{ [name]: value }` when the schema declared a wrapper name. */
|
|
19
|
+
export declare const unwrapNamed: <T>(result: T, name: string | undefined) => T;
|
|
20
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/utils/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,KAAK,CAAA;AAGhE;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GAAI,CAAC,EAAE,KAAK,GAAG,EAAE,QAAQ,cAAc,CAAC,CAAC,CAAC,KAAG;IAC9E,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;IACxB,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC,CAAA;IAC9B,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;CAK9B,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,GAAG,SAAS,KAAG,MAGpD,CAAA;AAED,0EAA0E;AAC1E,eAAO,MAAM,WAAW,GAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,KAAG,CAKpE,CAAA"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DEFAULT_TOOL_NAME } from '../consts.js';
|
|
2
|
+
/**
|
|
3
|
+
* Split the caller's schema into the optional wrapper `name` and the schema proper, and
|
|
4
|
+
* compile a validator for the latter. A `name` means the model is expected to answer
|
|
5
|
+
* `{ [name]: <object> }`; see {@link unwrapNamed}.
|
|
6
|
+
*/
|
|
7
|
+
export const resolveSchemaValidator = (ajv, schema) => {
|
|
8
|
+
const { name, ...innerSchema } = schema;
|
|
9
|
+
const validate = ajv.compile(innerSchema);
|
|
10
|
+
return { name, innerSchema: innerSchema, validate };
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Derive a function/tool name for tool-calling structured output. Provider tool names
|
|
14
|
+
* must match `^[A-Za-z0-9_-]+$`, so the schema title/name is sanitised; falls back to
|
|
15
|
+
* {@link DEFAULT_TOOL_NAME} when nothing usable is present.
|
|
16
|
+
*/
|
|
17
|
+
export const toToolName = (raw) => {
|
|
18
|
+
const cleaned = (raw ?? '').replace(/[^A-Za-z0-9_-]+/g, '_').replace(/^_+|_+$/g, '');
|
|
19
|
+
return cleaned.length > 0 ? cleaned : DEFAULT_TOOL_NAME;
|
|
20
|
+
};
|
|
21
|
+
/** Unwrap `{ [name]: value }` when the schema declared a wrapper name. */
|
|
22
|
+
export const unwrapNamed = (result, name) => {
|
|
23
|
+
if (name != null && result != null && typeof result === 'object' && name in result) {
|
|
24
|
+
return result[name];
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/utils/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAEhD;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAI,GAAQ,EAAE,MAAyB,EAI3E,EAAE;IACF,MAAM,EAAE,IAAI,EAAE,GAAG,WAAW,EAAE,GAAG,MAA+C,CAAA;IAChF,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAI,WAAgC,CAAC,CAAA;IACjE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,WAAgC,EAAE,QAAQ,EAAE,CAAA;AAC1E,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAuB,EAAU,EAAE;IAC5D,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;IACpF,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAA;AACzD,CAAC,CAAA;AAED,0EAA0E;AAC1E,MAAM,CAAC,MAAM,WAAW,GAAG,CAAI,MAAS,EAAE,IAAwB,EAAK,EAAE;IACvE,IAAI,IAAI,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,IAAI,IAAK,MAAkC,EAAE,CAAC;QAChH,OAAQ,MAAkC,CAAC,IAAI,CAAM,CAAA;IACvD,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract `finish_reason` from a stream chunk regardless of whether it is a plain
|
|
3
|
+
* `AIMessageChunk` (ask/talk) or a `{ raw, parsed }` combined chunk (structured output).
|
|
4
|
+
*/
|
|
5
|
+
export declare const getChunkFinishReason: (chunk: unknown) => string | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* Iterate a model stream under an IDLE (inactivity) deadline. `start` receives an
|
|
8
|
+
* `AbortSignal` to forward to `model.stream(..., { signal })`; the timer is re-armed on
|
|
9
|
+
* every received chunk, so it only fires after `timeoutMs` of SILENCE — a provider that
|
|
10
|
+
* accepted the request but stalls and never streams another token. On fire the call is
|
|
11
|
+
* aborted and surfaced as a retryable {@link LlmModelError} so the retry escalator moves
|
|
12
|
+
* on instead of hanging forever. Because the timer resets per token, long but actively
|
|
13
|
+
* streaming generations are never aborted.
|
|
14
|
+
*
|
|
15
|
+
* The loop also breaks after the first chunk carrying a non-empty `finish_reason`. Some
|
|
16
|
+
* providers send the final SSE data event twice, which makes `AIMessageChunk.concat()`
|
|
17
|
+
* double-append every string field (`finish_reason` becomes `'stopstop'`, the model name
|
|
18
|
+
* doubles) and corrupts accumulated tool-call argument strings, breaking structured-output
|
|
19
|
+
* parsing. Nothing meaningful arrives after `finish_reason`, so breaking there is safe.
|
|
20
|
+
*/
|
|
21
|
+
export declare function streamWithDeadline<T>(start: (signal: AbortSignal) => Promise<AsyncIterable<T>>, timeoutMs?: number): AsyncGenerator<T>;
|
|
22
|
+
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/utils/stream.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,eAAO,MAAM,oBAAoB,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAM9D,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAuB,kBAAkB,CAAC,CAAC,EACzC,KAAK,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EACzD,SAAS,GAAE,MAAgC,GAC1C,cAAc,CAAC,CAAC,CAAC,CAwBnB"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { LlmModelError } from '../errors.js';
|
|
2
|
+
import { MODEL_STREAM_TIMEOUT_MS } from '../consts.js';
|
|
3
|
+
/**
|
|
4
|
+
* Extract `finish_reason` from a stream chunk regardless of whether it is a plain
|
|
5
|
+
* `AIMessageChunk` (ask/talk) or a `{ raw, parsed }` combined chunk (structured output).
|
|
6
|
+
*/
|
|
7
|
+
export const getChunkFinishReason = (chunk) => {
|
|
8
|
+
const c = chunk;
|
|
9
|
+
return c.response_metadata?.finish_reason ?? c.raw?.response_metadata?.finish_reason;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Iterate a model stream under an IDLE (inactivity) deadline. `start` receives an
|
|
13
|
+
* `AbortSignal` to forward to `model.stream(..., { signal })`; the timer is re-armed on
|
|
14
|
+
* every received chunk, so it only fires after `timeoutMs` of SILENCE — a provider that
|
|
15
|
+
* accepted the request but stalls and never streams another token. On fire the call is
|
|
16
|
+
* aborted and surfaced as a retryable {@link LlmModelError} so the retry escalator moves
|
|
17
|
+
* on instead of hanging forever. Because the timer resets per token, long but actively
|
|
18
|
+
* streaming generations are never aborted.
|
|
19
|
+
*
|
|
20
|
+
* The loop also breaks after the first chunk carrying a non-empty `finish_reason`. Some
|
|
21
|
+
* providers send the final SSE data event twice, which makes `AIMessageChunk.concat()`
|
|
22
|
+
* double-append every string field (`finish_reason` becomes `'stopstop'`, the model name
|
|
23
|
+
* doubles) and corrupts accumulated tool-call argument strings, breaking structured-output
|
|
24
|
+
* parsing. Nothing meaningful arrives after `finish_reason`, so breaking there is safe.
|
|
25
|
+
*/
|
|
26
|
+
export async function* streamWithDeadline(start, timeoutMs = MODEL_STREAM_TIMEOUT_MS) {
|
|
27
|
+
const controller = new AbortController();
|
|
28
|
+
let timer;
|
|
29
|
+
const arm = () => {
|
|
30
|
+
clearTimeout(timer);
|
|
31
|
+
timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
32
|
+
};
|
|
33
|
+
arm();
|
|
34
|
+
try {
|
|
35
|
+
const stream = await start(controller.signal);
|
|
36
|
+
for await (const chunk of stream) {
|
|
37
|
+
arm(); // reset the idle timer on each received token
|
|
38
|
+
yield chunk;
|
|
39
|
+
const reason = getChunkFinishReason(chunk);
|
|
40
|
+
if (reason != null && reason !== '')
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
if (controller.signal.aborted) {
|
|
46
|
+
throw new LlmModelError(`stream-stalled:no token for ${timeoutMs}ms (idle deadline)`);
|
|
47
|
+
}
|
|
48
|
+
throw e;
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
clearTimeout(timer);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/utils/stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAA;AAEtD;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAc,EAAsB,EAAE;IACzE,MAAM,CAAC,GAAG,KAGT,CAAA;IACD,OAAO,CAAC,CAAC,iBAAiB,EAAE,aAAa,IAAI,CAAC,CAAC,GAAG,EAAE,iBAAiB,EAAE,aAAa,CAAA;AACtF,CAAC,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,kBAAkB,CACvC,KAAyD,EACzD,YAAoB,uBAAuB;IAE3C,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;IACxC,IAAI,KAAoC,CAAA;IACxC,MAAM,GAAG,GAAG,GAAG,EAAE;QACf,YAAY,CAAC,KAAK,CAAC,CAAA;QACnB,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAA;IACzD,CAAC,CAAA;IACD,GAAG,EAAE,CAAA;IACL,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;QAC7C,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACjC,GAAG,EAAE,CAAA,CAAC,8CAA8C;YACpD,MAAM,KAAK,CAAA;YACX,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAA;YAC1C,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,KAAK,EAAE;gBAAE,MAAK;QAC5C,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAC9B,MAAM,IAAI,aAAa,CAAC,+BAA+B,SAAS,oBAAoB,CAAC,CAAA;QACvF,CAAC;QACD,MAAM,CAAC,CAAA;IACT,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAM,CAAC,CAAA;IACtB,CAAC;AACH,CAAC"}
|