octaflow 0.29.2 → 0.30.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.
- package/README.md +3 -2
- package/dist/ai/index.d.ts +168 -4
- package/dist/ai/index.js +383 -3
- package/dist/ai/providers/index.d.ts +3 -1
- package/dist/ai/providers/index.js +2 -2
- package/dist/{core-C9h3-KFr.js → core-DBqxBk3R.js} +34 -23
- package/dist/{dispatcher-B4haXU4w.d.ts → dispatcher-ClQMXA9E.d.ts} +1 -1
- package/dist/gate-BRq-t3K_.js +109 -0
- package/dist/{hooks-BV-Vany9.d.ts → hooks-mWaAKHqn.d.ts} +1 -1
- package/dist/{index-B8SvtiYn.d.ts → index-Du05Lnwr.d.ts} +95 -3
- package/dist/index.d.ts +5 -5
- package/dist/index.js +83 -123
- package/dist/logger-epkdcXDA.js +18 -0
- package/dist/{observability-DRUJOpiQ.d.ts → observability-CkC4FRCp.d.ts} +46 -13
- package/dist/pg-boss/index.d.ts +2 -2
- package/dist/postgres/index.d.ts +4 -4
- package/dist/postgres/index.js +51 -29
- package/dist/provider-probe-CGN2MpaZ.js +691 -0
- package/dist/provider-probe-l2Jmpuhr.d.ts +187 -0
- package/package.json +1 -1
- package/skills/add-a-decision/SKILL.md +1 -1
- package/skills/add-an-ai-proposal-workflow/SKILL.md +11 -4
- package/dist/refusal-BsL2HPDb.js +0 -104
package/README.md
CHANGED
|
@@ -198,13 +198,14 @@ next to what your steps actually do.
|
|
|
198
198
|
| 🧩 | **Typed DAG** — Zod-validated input/output per step; dependency outputs are typed |
|
|
199
199
|
| ⚡ | **Auto-parallelism** — dependency-free steps run concurrently; a step starts when all its deps complete |
|
|
200
200
|
| 🔁 | **Retry & timeout** — per-step `maxAttempts`, fixed/exponential backoff, wall-clock timeout |
|
|
201
|
+
| 🩹 | **Best-effort steps** — `onFailure: { output }` completes a step with a stand-in once its budget is spent, so one analysis that could not run costs a section of the result, not the run |
|
|
201
202
|
| 💤 | **Durable sleep** — hold a step in the queue for N ms (survives restarts) |
|
|
202
203
|
| 🔀 | **Conditional branching** — `when` guards skip a step and its branch; `join: 'any'` converges |
|
|
203
204
|
| 🎯 | **Decisions** — typed choices with a confidence from a swappable decider (a function, a model, your own); below a threshold a person settles it |
|
|
204
205
|
| ⏳ | **Deadlines** — a budget on a suspended step (fail, or continue with a stand-in answer) and on a whole run |
|
|
205
206
|
| ♻️ | **Retry a failed run** — `retryWorkflow` resumes from the failure point; completed steps keep their output |
|
|
206
207
|
| 🧹 | **Delete the runs about a record** — `purgeWorkflows({ entityRef })` cancels and deletes them with their sub-workflow runs and steps, for an erasure or a deleted record; refuses only while a step is executing |
|
|
207
|
-
| 🚦 | **Concurrency & rate limiting** —
|
|
208
|
+
| 🚦 | **Concurrency & rate limiting** — caps and token buckets per step type or per shared resource (`resources: ['llm:local']`), via a pluggable gate |
|
|
208
209
|
| ⏰ | **Cron / scheduled starts** — fire workflows on a schedule (pg-boss) |
|
|
209
210
|
| 🔑 | **Start idempotency** — a dedup key collapses double-clicks / overlapping ticks |
|
|
210
211
|
| 🗺️ | **Dynamic fan-out / map** — spawn one child step per item of a runtime-sized list |
|
|
@@ -214,7 +215,7 @@ next to what your steps actually do.
|
|
|
214
215
|
| 🚑 | **Crash recovery** — a step whose worker died is re-queued while its attempt budget lasts |
|
|
215
216
|
| 💓 | **Heartbeats** — a long step proves it is alive, so a dead one is caught in seconds, not minutes |
|
|
216
217
|
| 🔭 | **Observability** — lifecycle events (run history), per-step spans, and `createMeterObserver` turning the events into OpenTelemetry-style metrics — all pluggable, all structural |
|
|
217
|
-
| 🤖 | **AI add-on** — instrumented models, token/cost capture, quota, daily rollups |
|
|
218
|
+
| 🤖 | **AI add-on** — instrumented models, token/cost capture, quota, daily rollups, refusal-aware models, lenient JSON from local models (`withJsonRepair`), a vendor's refusal explained by key and hint (`explainProviderError`), a per-run circuit breaker, a connection test (`testProvider`) |
|
|
218
219
|
| 🧱 | **Pluggable everything** — `WorkflowStore`, `Dispatcher`, `StepGate`, `FlowObserver`, hooks |
|
|
219
220
|
|
|
220
221
|
---
|
package/dist/ai/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { A as TypedStep, H as RetryPolicy, M as TypedWorkflow,
|
|
1
|
+
import { A as TypedStep, H as RetryPolicy, M as TypedWorkflow, bt as Result, f as Decider, j as TypedStepContext, yt as FlowErrorShape } from "../index-Du05Lnwr.js";
|
|
2
2
|
import { n as Logger } from "../logger-BCus3AOa.js";
|
|
3
|
-
import { i as BuildStepContextArgs, o as WorkflowHooks } from "../hooks-
|
|
3
|
+
import { i as BuildStepContextArgs, o as WorkflowHooks } from "../hooks-mWaAKHqn.js";
|
|
4
4
|
import { C as isSubprocessorResidency, S as embeddingDimensionsFor, _ as EmbeddingProviderMeta, a as AiProcessingRegion, b as OpenAiCompatibleProviderId, c as AiProviderModelOption, d as AiVendorResidency, f as DEFAULT_AI_PROVIDER, g as EmbeddingProviderId, h as EMBEDDING_PROVIDER_IDS, i as AiEndpointResidency, l as AiResidencyError, m as EMBEDDING_PROVIDERS, n as AI_PROVIDER_IDS, o as AiProviderId, p as DEFAULT_EMBEDDING_PROVIDER, r as AiEndpointRegion, s as AiProviderMeta, t as AI_PROVIDERS, u as AiResidencyResult, v as OPENAI_COMPATIBLE_PROVIDER, w as resolveEndpointResidency, x as OpenAiCompatibleProviderMeta, y as OPENAI_COMPATIBLE_PROVIDER_ID } from "../provider-registry-C_mOfdHH.js";
|
|
5
|
+
import { A as maskKeys, C as ProviderErrorExplanation, D as explainProviderError, E as ProviderErrorPreset, O as isFatalProviderError, S as ProviderError, T as ProviderErrorPhrase, _ as ExplainProviderErrorOptions, a as OllamaProbeReport, b as PROVIDER_ERROR_REDACTED, c as ProviderProbeOptions, d as testProvider, f as CircuitBreaker, g as DEFAULT_PROVIDER_ERROR_DETAIL_LENGTH, h as withCircuitBreaker, i as OllamaProbeOptions, k as isProviderError, l as ProviderProbeReport, m as createCircuitBreaker, n as DEFAULT_PROVIDER_PROBE_PROMPT, o as ProbeableProvider, p as CircuitBreakerOptions, r as DEFAULT_PROVIDER_PROBE_TIMEOUT_MS, s as ProviderProbeFailure, t as DEFAULT_OLLAMA_PROBE_TIMEOUT_MS, u as testOllamaModel, v as FATAL_PROVIDER_ERROR_KEYS, w as ProviderErrorKey, x as PROVIDER_ERROR_STATUS, y as PROVIDER_ERROR_PHRASES } from "../provider-probe-l2Jmpuhr.js";
|
|
5
6
|
import { z } from "zod";
|
|
6
|
-
import { EmbeddingModelV4, LanguageModelV4, SharedV4ProviderMetadata } from "@ai-sdk/provider";
|
|
7
|
+
import { EmbeddingModelV4, LanguageModelV4, LanguageModelV4Usage, SharedV4ProviderMetadata } from "@ai-sdk/provider";
|
|
7
8
|
//#region src/ai/instrumented-model.d.ts
|
|
8
9
|
export interface AccumulatedUsage {
|
|
9
10
|
inputTokens: number;
|
|
@@ -134,6 +135,16 @@ interface DefineAiStepConfig<TInput extends Record<string, unknown>, TOutput ext
|
|
|
134
135
|
timeoutMs?: number;
|
|
135
136
|
/** Optional durable start delay in ms — held in the queue once the step is ready. */
|
|
136
137
|
delayMs?: number;
|
|
138
|
+
/**
|
|
139
|
+
* What a terminal failure does — see `defineStep`'s `onFailure`. `{ output }`
|
|
140
|
+
* completes the step with a stand-in and the DAG carries on; the model's
|
|
141
|
+
* refusal or outage then costs one section of the result, not the run.
|
|
142
|
+
*/
|
|
143
|
+
onFailure?: 'fail' | {
|
|
144
|
+
output: TOutput;
|
|
145
|
+
};
|
|
146
|
+
/** Resources the step draws on (the model, a vendor), for the admission gate — see `defineStep`. */
|
|
147
|
+
resources?: readonly string[];
|
|
137
148
|
}
|
|
138
149
|
/**
|
|
139
150
|
* Define a type-safe AI workflow step. Identical to flow-core's `defineStep`
|
|
@@ -576,4 +587,157 @@ export declare function thinkingSettingsFor(providerId: string, modelId: string,
|
|
|
576
587
|
budgetTokens: number;
|
|
577
588
|
}): ThinkingSettings;
|
|
578
589
|
//#endregion
|
|
579
|
-
|
|
590
|
+
//#region src/ai/model-json.d.ts
|
|
591
|
+
/** Which step produced the JSON. `retry` and `convert` are `withJsonRepair`'s. */
|
|
592
|
+
export type ModelJsonRepair = 'fence' | 'prose' | 'array_merge' | 'retry' | 'convert';
|
|
593
|
+
/**
|
|
594
|
+
* The span or metric attribute that names a repair, in the GenAI convention's
|
|
595
|
+
* namespace so `@octabits-io/telemetry`'s redaction leaves it alone: its last
|
|
596
|
+
* segment is `repaired`, not a credential or a person's data. Set it on the
|
|
597
|
+
* step's span from `withJsonRepair`'s `onRepair`, and a dashboard counts
|
|
598
|
+
* repairs per model.
|
|
599
|
+
*/
|
|
600
|
+
export declare const MODEL_JSON_REPAIRED_ATTRIBUTE = "gen_ai.response.repaired";
|
|
601
|
+
/** Where a repaired answer is also reported: `result.providerMetadata.octaflow.repaired`. */
|
|
602
|
+
export declare const MODEL_JSON_PROVIDER_METADATA_KEY = "octaflow";
|
|
603
|
+
export type ModelJsonErrorKey =
|
|
604
|
+
/** Nothing but whitespace, or an empty fence. */
|
|
605
|
+
'model_json_empty' |
|
|
606
|
+
/** No step produced JSON: not valid as it is, and no outermost object or array parses. */
|
|
607
|
+
'model_json_invalid' |
|
|
608
|
+
/** The JSON is not an object or an array of objects (a scalar, an array of scalars, a mixed array). */
|
|
609
|
+
'model_json_not_object' |
|
|
610
|
+
/** The JSON parsed but the schema refused it; `issues` carries why. */
|
|
611
|
+
'model_json_schema';
|
|
612
|
+
/** The default length of the excerpt a {@link ModelJsonError} keeps. */
|
|
613
|
+
export declare const DEFAULT_MODEL_JSON_EXCERPT_LENGTH = 500;
|
|
614
|
+
/**
|
|
615
|
+
* The answer could not be read as the JSON that was asked for.
|
|
616
|
+
*
|
|
617
|
+
* `message` names the reason and never quotes the answer: it is what lands in
|
|
618
|
+
* a step's `error` column and in a log line. `excerpt` is the first
|
|
619
|
+
* `excerptLength` characters (500 by default) for a debug trace that wants to
|
|
620
|
+
* see what the model said.
|
|
621
|
+
*/
|
|
622
|
+
export declare class ModelJsonError extends Error {
|
|
623
|
+
readonly name = "ModelJsonError";
|
|
624
|
+
readonly key: ModelJsonErrorKey;
|
|
625
|
+
/** The first characters of the answer, cut at the configured length. */
|
|
626
|
+
readonly excerpt: string;
|
|
627
|
+
/** The schema's issues, for `model_json_schema`. */
|
|
628
|
+
readonly issues?: readonly unknown[];
|
|
629
|
+
/** The step that produced the JSON the schema then refused. */
|
|
630
|
+
readonly repair?: ModelJsonRepair;
|
|
631
|
+
constructor(args: {
|
|
632
|
+
key: ModelJsonErrorKey;
|
|
633
|
+
excerpt: string;
|
|
634
|
+
issues?: readonly unknown[];
|
|
635
|
+
repair?: ModelJsonRepair;
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
/** True when `error` is a {@link ModelJsonError}, or wraps one as its `cause` (`generateObject` re-wraps). */
|
|
639
|
+
export declare function isModelJsonError(error: unknown): error is ModelJsonError;
|
|
640
|
+
export interface ParseModelJsonOptions<T> {
|
|
641
|
+
/** Validate the value; the issues go on the error. */
|
|
642
|
+
schema?: z.ZodType<T>;
|
|
643
|
+
/**
|
|
644
|
+
* Merge an array of objects into one object: array fields concatenated in
|
|
645
|
+
* order, the first non-empty scalar kept, `null` never overwriting a value,
|
|
646
|
+
* nested objects merged the same way. For a model that answered one object
|
|
647
|
+
* per image when one object was asked for. Off by default: an array answer
|
|
648
|
+
* is then returned as the array.
|
|
649
|
+
*/
|
|
650
|
+
merge?: boolean;
|
|
651
|
+
/** How many characters of the answer the error keeps. Default 500. */
|
|
652
|
+
excerptLength?: number;
|
|
653
|
+
}
|
|
654
|
+
export interface ModelJsonParsed<T> {
|
|
655
|
+
value: T;
|
|
656
|
+
/** The step that produced the JSON; absent when the answer parsed as it was. */
|
|
657
|
+
repair?: ModelJsonRepair;
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Read a model's answer as JSON, leniently — see the module header for the
|
|
661
|
+
* steps. Returns the value, and which repair it took, or a {@link ModelJsonError}.
|
|
662
|
+
*/
|
|
663
|
+
export declare function parseModelJson<T = unknown>(text: string, options?: ParseModelJsonOptions<T>): Result<ModelJsonParsed<T>, ModelJsonError>;
|
|
664
|
+
/**
|
|
665
|
+
* The same recovery as a `repairText` function for the AI SDK's
|
|
666
|
+
* `generateObject` / `Output.object`: given the raw text the SDK could not
|
|
667
|
+
* parse, the repaired JSON as a string, or `null` when no step helps (the SDK
|
|
668
|
+
* then reports its own `NoObjectGeneratedError`).
|
|
669
|
+
*
|
|
670
|
+
* ```ts
|
|
671
|
+
* await generateObject({ model, schema, prompt, repairText: modelJsonRepairText({ merge: true }) });
|
|
672
|
+
* ```
|
|
673
|
+
*/
|
|
674
|
+
export declare function modelJsonRepairText(options?: {
|
|
675
|
+
merge?: boolean;
|
|
676
|
+
}): (args: {
|
|
677
|
+
text: string;
|
|
678
|
+
error: unknown;
|
|
679
|
+
}) => Promise<string | null>;
|
|
680
|
+
/** Internal: the recovery without the schema, shared with `withJsonRepair`. */
|
|
681
|
+
export type RecoveredModelJson = {
|
|
682
|
+
ok: true;
|
|
683
|
+
value: Record<string, unknown> | Record<string, unknown>[];
|
|
684
|
+
repair?: ModelJsonRepair;
|
|
685
|
+
} | {
|
|
686
|
+
ok: false;
|
|
687
|
+
key: Exclude<ModelJsonErrorKey, 'model_json_schema'>;
|
|
688
|
+
};
|
|
689
|
+
/** @internal */
|
|
690
|
+
export declare function recoverModelJson(text: string, options: {
|
|
691
|
+
merge: boolean;
|
|
692
|
+
}): RecoveredModelJson;
|
|
693
|
+
/**
|
|
694
|
+
* Merge objects a model answered "per item" into one: array fields are
|
|
695
|
+
* concatenated in order, nested objects merged the same way, and for a scalar
|
|
696
|
+
* the first non-empty value is kept — `null` and `''` never overwrite a value.
|
|
697
|
+
*/
|
|
698
|
+
export declare function mergeModelJsonObjects(objects: readonly Record<string, unknown>[]): Record<string, unknown>;
|
|
699
|
+
/** @internal */
|
|
700
|
+
export declare function excerptOf(text: string, length?: number): string;
|
|
701
|
+
//#endregion
|
|
702
|
+
//#region src/ai/json-repair.d.ts
|
|
703
|
+
/** What `onRepair` is told: once per repaired answer, after the answer is final. */
|
|
704
|
+
export interface ModelJsonRepairEvent {
|
|
705
|
+
/** The wrapped model's id. */
|
|
706
|
+
modelId: string;
|
|
707
|
+
/** The step that produced the JSON — the value for `gen_ai.response.repaired`. */
|
|
708
|
+
repair: ModelJsonRepair;
|
|
709
|
+
/** Requests made beyond the first: 0 for a parse-level repair, 1 for a retry or a conversion, 2 for both. */
|
|
710
|
+
extraRequests: number;
|
|
711
|
+
}
|
|
712
|
+
export interface JsonRepairOptions {
|
|
713
|
+
/** Merge an array of objects into one — see `parseModelJson`. Skipped when the requested schema is itself an array. */
|
|
714
|
+
merge?: boolean;
|
|
715
|
+
/** On a parse failure, one more request with the provider's JSON mode off. Default `false`. */
|
|
716
|
+
retryWithoutJsonMode?: boolean;
|
|
717
|
+
/**
|
|
718
|
+
* On a parse failure (after the retry, when both are on), one call that is
|
|
719
|
+
* handed the schema and the prose and asked for the JSON. `true` uses the
|
|
720
|
+
* wrapped model; a `LanguageModelV4` uses that one, for a cheaper converter.
|
|
721
|
+
* Default off.
|
|
722
|
+
*/
|
|
723
|
+
convertWith?: LanguageModelV4 | true;
|
|
724
|
+
/** How many characters of the answer the error keeps. Default 500. */
|
|
725
|
+
excerptLength?: number;
|
|
726
|
+
/** Told of every repaired answer: set `MODEL_JSON_REPAIRED_ATTRIBUTE` on the step's span, count it on a meter. Must not throw. */
|
|
727
|
+
onRepair?: (event: ModelJsonRepairEvent) => void;
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* Wrap a model so a JSON answer that is nearly JSON is read as the JSON it
|
|
731
|
+
* meant — see the module header. The result's text becomes the canonical
|
|
732
|
+
* JSON, and `providerMetadata.octaflow.repaired` names the step taken.
|
|
733
|
+
*/
|
|
734
|
+
export declare function withJsonRepair(model: LanguageModelV4, options?: JsonRepairOptions): LanguageModelV4;
|
|
735
|
+
/**
|
|
736
|
+
* Two usages added field by field — `inputTokens`, `outputTokens` and
|
|
737
|
+
* whatever a provider adds — so the instrumented model outside the wrapper
|
|
738
|
+
* counts every request the repair made. An undefined on one side keeps the
|
|
739
|
+
* other; `raw` is the last call's.
|
|
740
|
+
*/
|
|
741
|
+
export declare function addUsage(a: LanguageModelV4Usage, b: LanguageModelV4Usage): LanguageModelV4Usage;
|
|
742
|
+
//#endregion
|
|
743
|
+
export { AI_PROVIDERS, AI_PROVIDER_IDS, AiEndpointRegion, AiEndpointResidency, AiProcessingRegion, AiProviderId, AiProviderMeta, AiProviderModelOption, AiResidencyError, AiResidencyResult, AiVendorResidency, CircuitBreaker, CircuitBreakerOptions, DEFAULT_AI_PROVIDER, DEFAULT_EMBEDDING_PROVIDER, DEFAULT_OLLAMA_PROBE_TIMEOUT_MS, DEFAULT_PROVIDER_ERROR_DETAIL_LENGTH, DEFAULT_PROVIDER_PROBE_PROMPT, DEFAULT_PROVIDER_PROBE_TIMEOUT_MS, EMBEDDING_PROVIDERS, EMBEDDING_PROVIDER_IDS, EmbeddingProviderId, EmbeddingProviderMeta, ExplainProviderErrorOptions, FATAL_PROVIDER_ERROR_KEYS, OPENAI_COMPATIBLE_PROVIDER, OPENAI_COMPATIBLE_PROVIDER_ID, OllamaProbeOptions, OllamaProbeReport, OpenAiCompatibleProviderId, OpenAiCompatibleProviderMeta, PROVIDER_ERROR_PHRASES, PROVIDER_ERROR_REDACTED, PROVIDER_ERROR_STATUS, ProbeableProvider, ProviderError, ProviderErrorExplanation, ProviderErrorKey, ProviderErrorPhrase, ProviderErrorPreset, ProviderProbeFailure, ProviderProbeOptions, ProviderProbeReport, createCircuitBreaker, embeddingDimensionsFor, explainProviderError, isFatalProviderError, isProviderError, isSubprocessorResidency, maskKeys, resolveEndpointResidency, testOllamaModel, testProvider, withCircuitBreaker };
|
package/dist/ai/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { n as err, r as ok, t as noopLogger } from "../logger-epkdcXDA.js";
|
|
2
|
+
import { _ as defineStep, m as buildWorkflow } from "../core-DBqxBk3R.js";
|
|
3
|
+
import { S as readRefusalDetails, _ as maskKeys, a as testProvider, b as createRefusalAwareModel, c as DEFAULT_PROVIDER_ERROR_DETAIL_LENGTH, d as PROVIDER_ERROR_REDACTED, f as PROVIDER_ERROR_STATUS, g as isProviderError, h as isFatalProviderError, i as testOllamaModel, l as FATAL_PROVIDER_ERROR_KEYS, m as explainProviderError, n as DEFAULT_PROVIDER_PROBE_PROMPT, o as createCircuitBreaker, p as ProviderError, r as DEFAULT_PROVIDER_PROBE_TIMEOUT_MS, s as withCircuitBreaker, t as DEFAULT_OLLAMA_PROBE_TIMEOUT_MS, u as PROVIDER_ERROR_PHRASES, v as AiRefusalError, x as isAiRefusalError, y as REFUSAL_FINISH_REASON } from "../provider-probe-CGN2MpaZ.js";
|
|
3
4
|
import { a as EMBEDDING_PROVIDERS, c as OPENAI_COMPATIBLE_PROVIDER_ID, d as resolveEndpointResidency, i as DEFAULT_EMBEDDING_PROVIDER, l as embeddingDimensionsFor, n as AI_PROVIDER_IDS, o as EMBEDDING_PROVIDER_IDS, r as DEFAULT_AI_PROVIDER, s as OPENAI_COMPATIBLE_PROVIDER, t as AI_PROVIDERS, u as isSubprocessorResidency } from "../provider-registry-B91lgOmu.js";
|
|
4
5
|
import { z } from "zod";
|
|
5
6
|
import { Output, generateText, wrapEmbeddingModel, wrapLanguageModel } from "ai";
|
|
@@ -754,4 +755,383 @@ function thinkingSettingsFor(providerId, modelId, opts) {
|
|
|
754
755
|
return { temperature: opts.temperature };
|
|
755
756
|
}
|
|
756
757
|
//#endregion
|
|
757
|
-
|
|
758
|
+
//#region src/ai/model-json.ts
|
|
759
|
+
/**
|
|
760
|
+
* The span or metric attribute that names a repair, in the GenAI convention's
|
|
761
|
+
* namespace so `@octabits-io/telemetry`'s redaction leaves it alone: its last
|
|
762
|
+
* segment is `repaired`, not a credential or a person's data. Set it on the
|
|
763
|
+
* step's span from `withJsonRepair`'s `onRepair`, and a dashboard counts
|
|
764
|
+
* repairs per model.
|
|
765
|
+
*/
|
|
766
|
+
const MODEL_JSON_REPAIRED_ATTRIBUTE = "gen_ai.response.repaired";
|
|
767
|
+
/** Where a repaired answer is also reported: `result.providerMetadata.octaflow.repaired`. */
|
|
768
|
+
const MODEL_JSON_PROVIDER_METADATA_KEY = "octaflow";
|
|
769
|
+
/** The default length of the excerpt a {@link ModelJsonError} keeps. */
|
|
770
|
+
const DEFAULT_MODEL_JSON_EXCERPT_LENGTH = 500;
|
|
771
|
+
/**
|
|
772
|
+
* The answer could not be read as the JSON that was asked for.
|
|
773
|
+
*
|
|
774
|
+
* `message` names the reason and never quotes the answer: it is what lands in
|
|
775
|
+
* a step's `error` column and in a log line. `excerpt` is the first
|
|
776
|
+
* `excerptLength` characters (500 by default) for a debug trace that wants to
|
|
777
|
+
* see what the model said.
|
|
778
|
+
*/
|
|
779
|
+
var ModelJsonError = class extends Error {
|
|
780
|
+
name = "ModelJsonError";
|
|
781
|
+
key;
|
|
782
|
+
/** The first characters of the answer, cut at the configured length. */
|
|
783
|
+
excerpt;
|
|
784
|
+
/** The schema's issues, for `model_json_schema`. */
|
|
785
|
+
issues;
|
|
786
|
+
/** The step that produced the JSON the schema then refused. */
|
|
787
|
+
repair;
|
|
788
|
+
constructor(args) {
|
|
789
|
+
super(modelJsonMessage(args.key, args.issues));
|
|
790
|
+
this.key = args.key;
|
|
791
|
+
this.excerpt = args.excerpt;
|
|
792
|
+
if (args.issues) this.issues = args.issues;
|
|
793
|
+
if (args.repair) this.repair = args.repair;
|
|
794
|
+
}
|
|
795
|
+
};
|
|
796
|
+
function modelJsonMessage(key, issues) {
|
|
797
|
+
switch (key) {
|
|
798
|
+
case "model_json_empty": return "The model answered with no JSON.";
|
|
799
|
+
case "model_json_invalid": return "The model answer is not JSON: no fenced block, outermost object or outermost array parses.";
|
|
800
|
+
case "model_json_not_object": return "The model answer is JSON but not an object or an array of objects.";
|
|
801
|
+
case "model_json_schema": {
|
|
802
|
+
const count = issues?.length ?? 0;
|
|
803
|
+
return `The model answer is JSON but not the shape asked for (${count} ${count === 1 ? "issue" : "issues"}).`;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
/** True when `error` is a {@link ModelJsonError}, or wraps one as its `cause` (`generateObject` re-wraps). */
|
|
808
|
+
function isModelJsonError(error) {
|
|
809
|
+
const seen = /* @__PURE__ */ new Set();
|
|
810
|
+
let current = error;
|
|
811
|
+
for (let depth = 0; depth < 8; depth++) {
|
|
812
|
+
if (typeof current !== "object" || current === null || seen.has(current)) return false;
|
|
813
|
+
if (current instanceof ModelJsonError) return true;
|
|
814
|
+
seen.add(current);
|
|
815
|
+
current = current.cause;
|
|
816
|
+
}
|
|
817
|
+
return false;
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* Read a model's answer as JSON, leniently — see the module header for the
|
|
821
|
+
* steps. Returns the value, and which repair it took, or a {@link ModelJsonError}.
|
|
822
|
+
*/
|
|
823
|
+
function parseModelJson(text, options = {}) {
|
|
824
|
+
const excerpt = excerptOf(text, options.excerptLength);
|
|
825
|
+
const recovered = recoverModelJson(text, { merge: options.merge ?? false });
|
|
826
|
+
if (!recovered.ok) return {
|
|
827
|
+
ok: false,
|
|
828
|
+
error: new ModelJsonError({
|
|
829
|
+
key: recovered.key,
|
|
830
|
+
excerpt
|
|
831
|
+
})
|
|
832
|
+
};
|
|
833
|
+
const repair = recovered.repair;
|
|
834
|
+
if (!options.schema) return {
|
|
835
|
+
ok: true,
|
|
836
|
+
value: repair ? {
|
|
837
|
+
value: recovered.value,
|
|
838
|
+
repair
|
|
839
|
+
} : { value: recovered.value }
|
|
840
|
+
};
|
|
841
|
+
const checked = options.schema.safeParse(recovered.value);
|
|
842
|
+
if (!checked.success) return {
|
|
843
|
+
ok: false,
|
|
844
|
+
error: new ModelJsonError({
|
|
845
|
+
key: "model_json_schema",
|
|
846
|
+
excerpt,
|
|
847
|
+
issues: checked.error.issues,
|
|
848
|
+
...repair ? { repair } : {}
|
|
849
|
+
})
|
|
850
|
+
};
|
|
851
|
+
return {
|
|
852
|
+
ok: true,
|
|
853
|
+
value: repair ? {
|
|
854
|
+
value: checked.data,
|
|
855
|
+
repair
|
|
856
|
+
} : { value: checked.data }
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* The same recovery as a `repairText` function for the AI SDK's
|
|
861
|
+
* `generateObject` / `Output.object`: given the raw text the SDK could not
|
|
862
|
+
* parse, the repaired JSON as a string, or `null` when no step helps (the SDK
|
|
863
|
+
* then reports its own `NoObjectGeneratedError`).
|
|
864
|
+
*
|
|
865
|
+
* ```ts
|
|
866
|
+
* await generateObject({ model, schema, prompt, repairText: modelJsonRepairText({ merge: true }) });
|
|
867
|
+
* ```
|
|
868
|
+
*/
|
|
869
|
+
function modelJsonRepairText(options = {}) {
|
|
870
|
+
return async ({ text }) => {
|
|
871
|
+
const recovered = recoverModelJson(text, { merge: options.merge ?? false });
|
|
872
|
+
return recovered.ok && recovered.repair ? JSON.stringify(recovered.value) : null;
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
/** @internal */
|
|
876
|
+
function recoverModelJson(text, options) {
|
|
877
|
+
const trimmed = text.trim();
|
|
878
|
+
if (!trimmed) return {
|
|
879
|
+
ok: false,
|
|
880
|
+
key: "model_json_empty"
|
|
881
|
+
};
|
|
882
|
+
let body = trimmed;
|
|
883
|
+
let repair;
|
|
884
|
+
const fenced = unfence(trimmed);
|
|
885
|
+
if (fenced !== void 0) {
|
|
886
|
+
body = fenced.trim();
|
|
887
|
+
repair = "fence";
|
|
888
|
+
if (!body) return {
|
|
889
|
+
ok: false,
|
|
890
|
+
key: "model_json_empty"
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
let value = tryParse(body);
|
|
894
|
+
if (value === INVALID) {
|
|
895
|
+
const cut = outermost(body);
|
|
896
|
+
if (cut === void 0) return {
|
|
897
|
+
ok: false,
|
|
898
|
+
key: "model_json_invalid"
|
|
899
|
+
};
|
|
900
|
+
value = cut;
|
|
901
|
+
repair = "prose";
|
|
902
|
+
}
|
|
903
|
+
if (isPlainObject(value)) return repair ? {
|
|
904
|
+
ok: true,
|
|
905
|
+
value,
|
|
906
|
+
repair
|
|
907
|
+
} : {
|
|
908
|
+
ok: true,
|
|
909
|
+
value
|
|
910
|
+
};
|
|
911
|
+
if (Array.isArray(value) && value.every(isPlainObject)) {
|
|
912
|
+
const objects = value;
|
|
913
|
+
if (!options.merge) return repair ? {
|
|
914
|
+
ok: true,
|
|
915
|
+
value: objects,
|
|
916
|
+
repair
|
|
917
|
+
} : {
|
|
918
|
+
ok: true,
|
|
919
|
+
value: objects
|
|
920
|
+
};
|
|
921
|
+
return {
|
|
922
|
+
ok: true,
|
|
923
|
+
value: mergeModelJsonObjects(objects),
|
|
924
|
+
repair: "array_merge"
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
return {
|
|
928
|
+
ok: false,
|
|
929
|
+
key: "model_json_not_object"
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
const INVALID = Symbol("invalid");
|
|
933
|
+
function tryParse(text) {
|
|
934
|
+
try {
|
|
935
|
+
return JSON.parse(text);
|
|
936
|
+
} catch {
|
|
937
|
+
return INVALID;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
const FENCE_RE = /```[A-Za-z0-9_-]*[ \t]*\r?\n?([\s\S]*?)(?:```|$)/;
|
|
941
|
+
/** The content of the first fenced block, or `undefined` when there is none. An unterminated fence runs to the end. */
|
|
942
|
+
function unfence(text) {
|
|
943
|
+
const match = FENCE_RE.exec(text);
|
|
944
|
+
return match ? match[1] : void 0;
|
|
945
|
+
}
|
|
946
|
+
/**
|
|
947
|
+
* The outermost `{ … }` or `[ … ]` in the text, by first opener and last
|
|
948
|
+
* closer; whichever opener comes first is tried first, the other after it.
|
|
949
|
+
* Only a candidate that parses *and* has an accepted shape wins, so a stray
|
|
950
|
+
* `[1]` in the prose before the object does not shadow it; a cut that is JSON
|
|
951
|
+
* of another shape (`["paid"]` inside an object the prose broke) is not the
|
|
952
|
+
* answer either, and the whole is refused as invalid.
|
|
953
|
+
*/
|
|
954
|
+
function outermost(text) {
|
|
955
|
+
const candidates = [["{", "}"], ["[", "]"]];
|
|
956
|
+
const objectAt = text.indexOf("{");
|
|
957
|
+
const arrayAt = text.indexOf("[");
|
|
958
|
+
if (arrayAt !== -1 && (objectAt === -1 || arrayAt < objectAt)) candidates.reverse();
|
|
959
|
+
for (const [open, close] of candidates) {
|
|
960
|
+
const start = text.indexOf(open);
|
|
961
|
+
const end = text.lastIndexOf(close);
|
|
962
|
+
if (start === -1 || end <= start) continue;
|
|
963
|
+
const parsed = tryParse(text.slice(start, end + 1));
|
|
964
|
+
if (parsed === INVALID) continue;
|
|
965
|
+
if (isPlainObject(parsed) || Array.isArray(parsed) && parsed.every(isPlainObject)) return parsed;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
function isPlainObject(value) {
|
|
969
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
970
|
+
}
|
|
971
|
+
function isEmpty(value) {
|
|
972
|
+
return value === void 0 || value === null || value === "";
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* Merge objects a model answered "per item" into one: array fields are
|
|
976
|
+
* concatenated in order, nested objects merged the same way, and for a scalar
|
|
977
|
+
* the first non-empty value is kept — `null` and `''` never overwrite a value.
|
|
978
|
+
*/
|
|
979
|
+
function mergeModelJsonObjects(objects) {
|
|
980
|
+
const out = {};
|
|
981
|
+
for (const object of objects) for (const [key, incoming] of Object.entries(object)) {
|
|
982
|
+
const current = out[key];
|
|
983
|
+
if (Array.isArray(current) && Array.isArray(incoming)) out[key] = [...current, ...incoming];
|
|
984
|
+
else if (isPlainObject(current) && isPlainObject(incoming)) out[key] = mergeModelJsonObjects([current, incoming]);
|
|
985
|
+
else if (!(key in out) || isEmpty(current)) out[key] = incoming;
|
|
986
|
+
}
|
|
987
|
+
return out;
|
|
988
|
+
}
|
|
989
|
+
/** @internal */
|
|
990
|
+
function excerptOf(text, length = 500) {
|
|
991
|
+
return text.length > length ? text.slice(0, length) : text;
|
|
992
|
+
}
|
|
993
|
+
//#endregion
|
|
994
|
+
//#region src/ai/json-repair.ts
|
|
995
|
+
/**
|
|
996
|
+
* Wrap a model so a JSON answer that is nearly JSON is read as the JSON it
|
|
997
|
+
* meant — see the module header. The result's text becomes the canonical
|
|
998
|
+
* JSON, and `providerMetadata.octaflow.repaired` names the step taken.
|
|
999
|
+
*/
|
|
1000
|
+
function withJsonRepair(model, options = {}) {
|
|
1001
|
+
return wrapLanguageModel({
|
|
1002
|
+
model,
|
|
1003
|
+
middleware: {
|
|
1004
|
+
specificationVersion: "v4",
|
|
1005
|
+
wrapGenerate: async ({ doGenerate, params, model: inner }) => {
|
|
1006
|
+
const format = params.responseFormat;
|
|
1007
|
+
if (format?.type !== "json") return doGenerate();
|
|
1008
|
+
const merge = (options.merge ?? false) && format.schema?.type !== "array";
|
|
1009
|
+
const first = await doGenerate();
|
|
1010
|
+
const text = textOf(first);
|
|
1011
|
+
if (text === void 0) return first;
|
|
1012
|
+
const read = recoverModelJson(text, { merge });
|
|
1013
|
+
if (read.ok) {
|
|
1014
|
+
if (!read.repair) return first;
|
|
1015
|
+
return repaired(first, read.value, read.repair, 0, inner, options);
|
|
1016
|
+
}
|
|
1017
|
+
let usage = first.usage;
|
|
1018
|
+
let prose = text;
|
|
1019
|
+
let lastKey = read.key;
|
|
1020
|
+
let extraRequests = 0;
|
|
1021
|
+
if (options.retryWithoutJsonMode) {
|
|
1022
|
+
const second = await inner.doGenerate({
|
|
1023
|
+
...params,
|
|
1024
|
+
responseFormat: { type: "text" }
|
|
1025
|
+
});
|
|
1026
|
+
extraRequests += 1;
|
|
1027
|
+
usage = addUsage(usage, second.usage);
|
|
1028
|
+
const retried = textOf(second) ?? "";
|
|
1029
|
+
const again = recoverModelJson(retried, { merge });
|
|
1030
|
+
if (again.ok) return repaired({
|
|
1031
|
+
...second,
|
|
1032
|
+
usage
|
|
1033
|
+
}, again.value, "retry", extraRequests, inner, options);
|
|
1034
|
+
prose = retried;
|
|
1035
|
+
lastKey = again.key;
|
|
1036
|
+
}
|
|
1037
|
+
if (options.convertWith) {
|
|
1038
|
+
const third = await (options.convertWith === true ? inner : options.convertWith).doGenerate(conversionCall(params, prose, format.schema));
|
|
1039
|
+
extraRequests += 1;
|
|
1040
|
+
usage = addUsage(usage, third.usage);
|
|
1041
|
+
const converted = textOf(third) ?? "";
|
|
1042
|
+
const again = recoverModelJson(converted, { merge });
|
|
1043
|
+
if (again.ok) return repaired({
|
|
1044
|
+
...third,
|
|
1045
|
+
usage
|
|
1046
|
+
}, again.value, "convert", extraRequests, inner, options);
|
|
1047
|
+
prose = converted;
|
|
1048
|
+
lastKey = again.key;
|
|
1049
|
+
}
|
|
1050
|
+
throw new ModelJsonError({
|
|
1051
|
+
key: lastKey,
|
|
1052
|
+
excerpt: excerptOf(prose, options.excerptLength)
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
});
|
|
1057
|
+
}
|
|
1058
|
+
/** The answer's text, all text parts joined; `undefined` when the answer carries no text (tool calls alone). */
|
|
1059
|
+
function textOf(result) {
|
|
1060
|
+
const parts = result.content.filter((part) => part.type === "text");
|
|
1061
|
+
if (parts.length === 0) return void 0;
|
|
1062
|
+
return parts.map((part) => part.text).join("");
|
|
1063
|
+
}
|
|
1064
|
+
function repaired(result, value, repair, extraRequests, inner, options) {
|
|
1065
|
+
options.onRepair?.({
|
|
1066
|
+
modelId: inner.modelId,
|
|
1067
|
+
repair,
|
|
1068
|
+
extraRequests
|
|
1069
|
+
});
|
|
1070
|
+
return {
|
|
1071
|
+
...result,
|
|
1072
|
+
content: [...result.content.filter((part) => part.type !== "text"), {
|
|
1073
|
+
type: "text",
|
|
1074
|
+
text: JSON.stringify(value)
|
|
1075
|
+
}],
|
|
1076
|
+
providerMetadata: {
|
|
1077
|
+
...result.providerMetadata,
|
|
1078
|
+
[MODEL_JSON_PROVIDER_METADATA_KEY]: {
|
|
1079
|
+
...result.providerMetadata?.[MODEL_JSON_PROVIDER_METADATA_KEY],
|
|
1080
|
+
repaired: repair
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
/** The conversion request: the schema and the prose, JSON asked for, nothing of the original prompt. */
|
|
1086
|
+
function conversionCall(params, prose, schema) {
|
|
1087
|
+
return {
|
|
1088
|
+
prompt: [{
|
|
1089
|
+
role: "user",
|
|
1090
|
+
content: [{
|
|
1091
|
+
type: "text",
|
|
1092
|
+
text: [
|
|
1093
|
+
"Convert the answer below into a single JSON value that matches the schema. Output the JSON only: no fence, no prose.",
|
|
1094
|
+
schema ? `Schema:\n${JSON.stringify(schema)}` : "Shape: one JSON object.",
|
|
1095
|
+
`Answer:\n${prose}`
|
|
1096
|
+
].join("\n\n")
|
|
1097
|
+
}]
|
|
1098
|
+
}],
|
|
1099
|
+
responseFormat: params.responseFormat,
|
|
1100
|
+
temperature: 0,
|
|
1101
|
+
...params.maxOutputTokens !== void 0 ? { maxOutputTokens: params.maxOutputTokens } : {},
|
|
1102
|
+
...params.abortSignal ? { abortSignal: params.abortSignal } : {},
|
|
1103
|
+
...params.headers ? { headers: params.headers } : {}
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Two usages added field by field — `inputTokens`, `outputTokens` and
|
|
1108
|
+
* whatever a provider adds — so the instrumented model outside the wrapper
|
|
1109
|
+
* counts every request the repair made. An undefined on one side keeps the
|
|
1110
|
+
* other; `raw` is the last call's.
|
|
1111
|
+
*/
|
|
1112
|
+
function addUsage(a, b) {
|
|
1113
|
+
const { raw: _rawA, ...restA } = a;
|
|
1114
|
+
const { raw: rawB, ...restB } = b;
|
|
1115
|
+
const sum = addNumbers(restA, restB);
|
|
1116
|
+
return rawB ? {
|
|
1117
|
+
...sum,
|
|
1118
|
+
raw: rawB
|
|
1119
|
+
} : sum;
|
|
1120
|
+
}
|
|
1121
|
+
function addNumbers(a, b) {
|
|
1122
|
+
const out = {};
|
|
1123
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)])) {
|
|
1124
|
+
const x = a[key];
|
|
1125
|
+
const y = b[key];
|
|
1126
|
+
if (typeof x === "number" && typeof y === "number") out[key] = x + y;
|
|
1127
|
+
else if (typeof x === "number" || typeof y === "number") out[key] = typeof x === "number" ? x : y;
|
|
1128
|
+
else if (isRecord(x) && isRecord(y)) out[key] = addNumbers(x, y);
|
|
1129
|
+
else out[key] = x ?? y;
|
|
1130
|
+
}
|
|
1131
|
+
return out;
|
|
1132
|
+
}
|
|
1133
|
+
function isRecord(value) {
|
|
1134
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1135
|
+
}
|
|
1136
|
+
//#endregion
|
|
1137
|
+
export { AI_PROVIDERS, AI_PROVIDER_IDS, AiRefusalError, DEFAULT_AI_PROVIDER, DEFAULT_AI_QUOTA, DEFAULT_EMBEDDING_PROVIDER, DEFAULT_MODEL_JSON_EXCERPT_LENGTH, DEFAULT_MODEL_PRICING, DEFAULT_OLLAMA_PROBE_TIMEOUT_MS, DEFAULT_PROVIDER_ERROR_DETAIL_LENGTH, DEFAULT_PROVIDER_PROBE_PROMPT, DEFAULT_PROVIDER_PROBE_TIMEOUT_MS, EMBEDDING_PROVIDERS, EMBEDDING_PROVIDER_IDS, FATAL_PROVIDER_ERROR_KEYS, MODEL_JSON_PROVIDER_METADATA_KEY, MODEL_JSON_REPAIRED_ATTRIBUTE, ModelJsonError, OPENAI_COMPATIBLE_PROVIDER, OPENAI_COMPATIBLE_PROVIDER_ID, PROVIDER_ERROR_PHRASES, PROVIDER_ERROR_REDACTED, PROVIDER_ERROR_STATUS, ProviderError, REFUSAL_FINISH_REASON, ZERO_MODEL_PRICING, addUsage, anthropicThinkingSettings, buildAiWorkflow, createAiQuotaService, createAiUsageAggregationService, createAiWorkflowHooks, createCircuitBreaker, createCostEstimator, createEmbeddingUsageAccumulator, createInstrumentedEmbeddingModel, createInstrumentedModel, createModelDecider, createRefusalAwareModel, createUsageAccumulator, defineAiStep, embeddingDimensionsFor, estimateCostMicros, excerptOf, explainProviderError, isAiRefusalError, isFatalProviderError, isModelJsonError, isProviderError, isSubprocessorResidency, maskKeys, mergeModelJsonObjects, modelJsonRepairText, parseModelJson, readRefusalDetails, recoverModelJson, resolveEndpointResidency, supportsAdaptiveThinking, supportsToolSearch, testOllamaModel, testProvider, thinkingSettingsFor, withCircuitBreaker, withJsonRepair };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { b as OpenAiCompatibleProviderId, g as EmbeddingProviderId, i as AiEndpointResidency, o as AiProviderId } from "../../provider-registry-C_mOfdHH.js";
|
|
2
|
+
import { A as maskKeys, C as ProviderErrorExplanation, D as explainProviderError, E as ProviderErrorPreset, O as isFatalProviderError, S as ProviderError, T as ProviderErrorPhrase, _ as ExplainProviderErrorOptions, a as OllamaProbeReport, c as ProviderProbeOptions, d as testProvider, f as CircuitBreaker, h as withCircuitBreaker, i as OllamaProbeOptions, k as isProviderError, l as ProviderProbeReport, m as createCircuitBreaker, o as ProbeableProvider, p as CircuitBreakerOptions, s as ProviderProbeFailure, u as testOllamaModel, v as FATAL_PROVIDER_ERROR_KEYS, w as ProviderErrorKey, x as PROVIDER_ERROR_STATUS, y as PROVIDER_ERROR_PHRASES } from "../../provider-probe-l2Jmpuhr.js";
|
|
2
3
|
import { EmbeddingModelV4, LanguageModelV4 } from "@ai-sdk/provider";
|
|
3
4
|
//#region src/ai/providers/index.d.ts
|
|
4
5
|
export type LanguageModelFactory = (modelId: string) => LanguageModelV4;
|
|
@@ -205,4 +206,5 @@ export interface OpenAiCompatibleGatewayProvider {
|
|
|
205
206
|
* in the same review.
|
|
206
207
|
*/
|
|
207
208
|
export declare function createOpenAiCompatibleGatewayProvider(config: OpenAiCompatibleGatewayConfig): Promise<OpenAiCompatibleGatewayProvider>;
|
|
208
|
-
//#endregion
|
|
209
|
+
//#endregion
|
|
210
|
+
export { type CircuitBreaker, type CircuitBreakerOptions, type ExplainProviderErrorOptions, FATAL_PROVIDER_ERROR_KEYS, type OllamaProbeOptions, type OllamaProbeReport, PROVIDER_ERROR_PHRASES, PROVIDER_ERROR_STATUS, type ProbeableProvider, ProviderError, type ProviderErrorExplanation, type ProviderErrorKey, type ProviderErrorPhrase, type ProviderErrorPreset, type ProviderProbeFailure, type ProviderProbeOptions, type ProviderProbeReport, createCircuitBreaker, explainProviderError, isFatalProviderError, isProviderError, maskKeys, testOllamaModel, testProvider, withCircuitBreaker };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as maskKeys, a as testProvider, b as createRefusalAwareModel, f as PROVIDER_ERROR_STATUS, g as isProviderError, h as isFatalProviderError, i as testOllamaModel, l as FATAL_PROVIDER_ERROR_KEYS, m as explainProviderError, o as createCircuitBreaker, p as ProviderError, s as withCircuitBreaker, u as PROVIDER_ERROR_PHRASES } from "../../provider-probe-CGN2MpaZ.js";
|
|
2
2
|
import { a as EMBEDDING_PROVIDERS, c as OPENAI_COMPATIBLE_PROVIDER_ID, d as resolveEndpointResidency, t as AI_PROVIDERS } from "../../provider-registry-B91lgOmu.js";
|
|
3
3
|
import { wrapLanguageModel } from "ai";
|
|
4
4
|
//#region src/ai/providers/index.ts
|
|
@@ -280,4 +280,4 @@ async function createOpenAiCompatibleGatewayProvider(config) {
|
|
|
280
280
|
};
|
|
281
281
|
}
|
|
282
282
|
//#endregion
|
|
283
|
-
export { AiProviderConfigError, createEmbeddingModelFactory, createEmbeddingModelProvider, createLanguageModelFactory, createLanguageModelProvider, createLazyEmbeddingModel, createOpenAiCompatibleEmbeddingProvider, createOpenAiCompatibleGatewayProvider, createOpenAiCompatibleModelProvider };
|
|
283
|
+
export { AiProviderConfigError, FATAL_PROVIDER_ERROR_KEYS, PROVIDER_ERROR_PHRASES, PROVIDER_ERROR_STATUS, ProviderError, createCircuitBreaker, createEmbeddingModelFactory, createEmbeddingModelProvider, createLanguageModelFactory, createLanguageModelProvider, createLazyEmbeddingModel, createOpenAiCompatibleEmbeddingProvider, createOpenAiCompatibleGatewayProvider, createOpenAiCompatibleModelProvider, explainProviderError, isFatalProviderError, isProviderError, maskKeys, testOllamaModel, testProvider, withCircuitBreaker };
|