@fonoster/community 0.0.0-stage → 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.
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
12
+ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
13
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
14
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
15
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
16
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
17
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
18
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
19
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
20
+ function fulfill(value) { resume("next", value); }
21
+ function reject(value) { resume("throw", value); }
22
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
23
+ };
24
+ var __importDefault = (this && this.__importDefault) || function (mod) {
25
+ return (mod && mod.__esModule) ? mod : { "default": mod };
26
+ };
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.FakeSttAdapter = exports.FakeTtsAdapter = void 0;
29
+ /**
30
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
31
+ * http://github.com/fonoster/fonoster
32
+ *
33
+ * This file is part of Fonoster
34
+ *
35
+ * Licensed under the MIT License (the "License");
36
+ * you may not use this file except in compliance with
37
+ * the License. You may obtain a copy of the License at
38
+ *
39
+ * https://opensource.org/licenses/MIT
40
+ *
41
+ * Unless required by applicable law or agreed to in writing, software
42
+ * distributed under the License is distributed on an "AS IS" BASIS,
43
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
44
+ * See the License for the specific language governing permissions and
45
+ * limitations under the License.
46
+ */
47
+ const events_1 = require("events");
48
+ const url_1 = require("url");
49
+ const ws_1 = __importDefault(require("ws"));
50
+ const speech_1 = require("../speech");
51
+ // The fake adapters speak the fake provider protocol (mods/conformance/PROVIDERS.md). They are
52
+ // built in, like every adapter, and enabled only in test mode.
53
+ class FakeTtsAdapter {
54
+ constructor(options) {
55
+ this.options = options;
56
+ }
57
+ synthesize(request, signal) {
58
+ return __awaiter(this, void 0, void 0, function* () {
59
+ const timeout = AbortSignal.timeout(this.options.timeoutMs);
60
+ const combined = anySignal([signal, timeout]);
61
+ let res;
62
+ try {
63
+ res = yield fetch(`${this.options.url}/v1/synthesize`, {
64
+ method: "POST",
65
+ headers: { "content-type": "application/json" },
66
+ body: JSON.stringify(Object.assign(Object.assign({}, request), { format: { codec: "pcm16", rate: 16000 } })),
67
+ signal: combined
68
+ });
69
+ }
70
+ catch (e) {
71
+ if (timeout.aborted)
72
+ throw new speech_1.SpeechError("provider_timeout", `TTS did not answer within ${this.options.timeoutMs} ms`);
73
+ throw signal.aborted
74
+ ? e
75
+ : new speech_1.SpeechError("provider_unavailable", `TTS unreachable: ${e.message}`);
76
+ }
77
+ if (res.status === 400)
78
+ throw new speech_1.SpeechError("bad_message", "TTS rejected the request");
79
+ if (!res.ok || !res.body)
80
+ throw new speech_1.SpeechError("provider_unavailable", `TTS answered HTTP ${res.status}`);
81
+ const words = res.headers.get("x-fake-word-timings");
82
+ const body = res.body;
83
+ return {
84
+ words: words ? JSON.parse(words) : undefined,
85
+ audio: (function () {
86
+ return __asyncGenerator(this, arguments, function* () {
87
+ const reader = body.getReader();
88
+ try {
89
+ for (;;) {
90
+ const { done, value } = yield __await(reader.read());
91
+ if (done)
92
+ return yield __await(void 0);
93
+ yield yield __await(Buffer.from(value));
94
+ }
95
+ }
96
+ catch (e) {
97
+ if (timeout.aborted)
98
+ throw new speech_1.SpeechError("provider_timeout", "TTS stalled");
99
+ if (!signal.aborted)
100
+ throw new speech_1.SpeechError("provider_unavailable", e.message);
101
+ }
102
+ });
103
+ })()
104
+ };
105
+ });
106
+ }
107
+ }
108
+ exports.FakeTtsAdapter = FakeTtsAdapter;
109
+ function anySignal(signals) {
110
+ const controller = new AbortController();
111
+ for (const s of signals) {
112
+ if (s.aborted) {
113
+ controller.abort();
114
+ break;
115
+ }
116
+ s.addEventListener("abort", () => controller.abort(), { once: true });
117
+ }
118
+ return controller.signal;
119
+ }
120
+ class FakeSttStream extends events_1.EventEmitter {
121
+ constructor(url, language, hints, model) {
122
+ super();
123
+ this.pending = [];
124
+ this.open = false;
125
+ const query = new url_1.URLSearchParams(Object.assign({ language, codec: "pcm16", rate: "16000" }, (model ? { model } : {})));
126
+ this.socket = new ws_1.default(`${url}/v1/listen?${query}`);
127
+ this.socket.on("open", () => {
128
+ this.open = true;
129
+ if (hints)
130
+ this.socket.send(JSON.stringify({ type: "config", hints }));
131
+ for (const p of this.pending)
132
+ this.socket.send(p);
133
+ this.pending = [];
134
+ });
135
+ this.socket.on("message", (raw) => {
136
+ const msg = JSON.parse(raw.toString());
137
+ if (msg.type === "transcript") {
138
+ const t = Object.assign({ text: msg.text, final: msg.final, language: msg.language, confidence: msg.confidence, startMs: msg.startMs, endMs: msg.endMs }, (msg.turn ? { turn: msg.turn } : {}));
139
+ this.emit("transcript", t);
140
+ }
141
+ });
142
+ this.socket.on("close", (code) => {
143
+ if (code === 1011)
144
+ this.emit("error", new speech_1.SpeechError("provider_unavailable", "STT closed the stream"));
145
+ if (code === 1008)
146
+ this.emit("error", new speech_1.SpeechError("bad_message", "STT rejected the stream"));
147
+ });
148
+ this.socket.on("error", (e) => this.emit("error", new speech_1.SpeechError("provider_unavailable", e.message)));
149
+ }
150
+ write(frame) {
151
+ this.send(frame);
152
+ }
153
+ update(options) {
154
+ this.send(JSON.stringify(Object.assign({ type: "config" }, options)));
155
+ }
156
+ close() {
157
+ this.removeAllListeners();
158
+ this.socket.removeAllListeners();
159
+ this.socket.on("error", () => undefined);
160
+ if (this.socket.readyState === ws_1.default.CONNECTING)
161
+ this.socket.terminate();
162
+ else
163
+ this.socket.close();
164
+ }
165
+ send(data) {
166
+ if (this.open && this.socket.readyState === ws_1.default.OPEN)
167
+ this.socket.send(data);
168
+ else if (!this.open)
169
+ this.pending.push(data);
170
+ }
171
+ }
172
+ class FakeSttAdapter {
173
+ constructor(options) {
174
+ this.options = options;
175
+ }
176
+ open(options) {
177
+ return new FakeSttStream(this.options.url, options.language, options.hints, options.model);
178
+ }
179
+ }
180
+ exports.FakeSttAdapter = FakeSttAdapter;
package/dist/http.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
3
+ * http://github.com/fonoster/fonoster
4
+ *
5
+ * This file is part of Fonoster
6
+ *
7
+ * Licensed under the MIT License (the "License");
8
+ * you may not use this file except in compliance with
9
+ * the License. You may obtain a copy of the License at
10
+ *
11
+ * https://opensource.org/licenses/MIT
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+ import { Synthesis } from "./speech";
20
+ /**
21
+ * Shared HTTP plumbing for streaming TTS vendors: timeouts, error mapping, body streaming.
22
+ * `timeoutMs` bounds the wait for the response and for each next chunk, not the whole body: the
23
+ * body is read at playback pace, so a reply longer than `timeoutMs` must not count as a stall
24
+ * (FN-B6: long replies were cut off with "Deepgram stalled").
25
+ */
26
+ export declare function streamingPost(url: string, init: {
27
+ headers: Record<string, string>;
28
+ body: string;
29
+ }, signal: AbortSignal, timeoutMs: number, vendor: string): Promise<Synthesis["audio"]>;
package/dist/http.js ADDED
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
12
+ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
13
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
14
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
15
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
16
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
17
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
18
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
19
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
20
+ function fulfill(value) { resume("next", value); }
21
+ function reject(value) { resume("throw", value); }
22
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.streamingPost = streamingPost;
26
+ /**
27
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
28
+ * http://github.com/fonoster/fonoster
29
+ *
30
+ * This file is part of Fonoster
31
+ *
32
+ * Licensed under the MIT License (the "License");
33
+ * you may not use this file except in compliance with
34
+ * the License. You may obtain a copy of the License at
35
+ *
36
+ * https://opensource.org/licenses/MIT
37
+ *
38
+ * Unless required by applicable law or agreed to in writing, software
39
+ * distributed under the License is distributed on an "AS IS" BASIS,
40
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
41
+ * See the License for the specific language governing permissions and
42
+ * limitations under the License.
43
+ */
44
+ const speech_1 = require("./speech");
45
+ /**
46
+ * Shared HTTP plumbing for streaming TTS vendors: timeouts, error mapping, body streaming.
47
+ * `timeoutMs` bounds the wait for the response and for each next chunk, not the whole body: the
48
+ * body is read at playback pace, so a reply longer than `timeoutMs` must not count as a stall
49
+ * (FN-B6: long replies were cut off with "Deepgram stalled").
50
+ */
51
+ function streamingPost(url, init, signal, timeoutMs, vendor) {
52
+ return __awaiter(this, void 0, void 0, function* () {
53
+ const controller = new AbortController();
54
+ const abort = () => controller.abort();
55
+ signal.addEventListener("abort", abort, { once: true });
56
+ const timeout = { aborted: false };
57
+ let timer;
58
+ const arm = () => {
59
+ timer = setTimeout(() => {
60
+ timeout.aborted = true;
61
+ controller.abort();
62
+ }, timeoutMs);
63
+ };
64
+ const disarm = () => clearTimeout(timer);
65
+ arm();
66
+ let res;
67
+ try {
68
+ res = yield fetch(url, {
69
+ method: "POST",
70
+ headers: init.headers,
71
+ body: init.body,
72
+ signal: controller.signal
73
+ });
74
+ }
75
+ catch (e) {
76
+ disarm();
77
+ if (timeout.aborted)
78
+ throw new speech_1.SpeechError("provider_timeout", `${vendor} did not answer within ${timeoutMs} ms`);
79
+ if (signal.aborted)
80
+ throw e;
81
+ throw new speech_1.SpeechError("provider_unavailable", `${vendor} unreachable: ${e.message}`);
82
+ }
83
+ disarm();
84
+ if (res.status === 400 || res.status === 422) {
85
+ throw new speech_1.SpeechError("bad_message", `${vendor} rejected the request (HTTP ${res.status}): ${(yield res.text()).slice(0, 200)}`);
86
+ }
87
+ if (!res.ok || !res.body)
88
+ throw new speech_1.SpeechError("provider_unavailable", `${vendor} answered HTTP ${res.status}`);
89
+ const body = res.body;
90
+ return (function () {
91
+ return __asyncGenerator(this, arguments, function* () {
92
+ const reader = body.getReader();
93
+ // Vendors may split samples across chunks; keep byte pairs together.
94
+ let odd;
95
+ try {
96
+ for (;;) {
97
+ arm();
98
+ const { done, value } = yield __await(reader.read());
99
+ disarm();
100
+ if (done)
101
+ return yield __await(void 0);
102
+ let chunk = Buffer.from(value);
103
+ if (odd) {
104
+ chunk = Buffer.concat([odd, chunk]);
105
+ odd = undefined;
106
+ }
107
+ if (chunk.length % 2) {
108
+ odd = chunk.subarray(chunk.length - 1);
109
+ chunk = chunk.subarray(0, chunk.length - 1);
110
+ }
111
+ if (chunk.length)
112
+ yield yield __await(chunk);
113
+ }
114
+ }
115
+ catch (e) {
116
+ if (timeout.aborted)
117
+ throw new speech_1.SpeechError("provider_timeout", `${vendor} stalled`);
118
+ if (!signal.aborted)
119
+ throw new speech_1.SpeechError("provider_unavailable", e.message);
120
+ }
121
+ finally {
122
+ disarm();
123
+ signal.removeEventListener("abort", abort);
124
+ }
125
+ });
126
+ })();
127
+ });
128
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
3
+ * http://github.com/fonoster/fonoster
4
+ *
5
+ * This file is part of Fonoster
6
+ *
7
+ * Licensed under the MIT License (the "License");
8
+ * you may not use this file except in compliance with
9
+ * the License. You may obtain a copy of the License at
10
+ *
11
+ * https://opensource.org/licenses/MIT
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+ export * from "./adapters";
20
+ export * from "./types";
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ /**
18
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
19
+ * http://github.com/fonoster/fonoster
20
+ *
21
+ * This file is part of Fonoster
22
+ *
23
+ * Licensed under the MIT License (the "License");
24
+ * you may not use this file except in compliance with
25
+ * the License. You may obtain a copy of the License at
26
+ *
27
+ * https://opensource.org/licenses/MIT
28
+ *
29
+ * Unless required by applicable law or agreed to in writing, software
30
+ * distributed under the License is distributed on an "AS IS" BASIS,
31
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32
+ * See the License for the specific language governing permissions and
33
+ * limitations under the License.
34
+ */
35
+ // @fonoster/community: the vendor adapters, one subpath per vendor
36
+ // (@fonoster/community/deepgram, /elevenlabs, /openai, /fake). The root exports the shared
37
+ // interfaces and the adapter table keyed by catalog adapter id.
38
+ __exportStar(require("./adapters"), exports);
39
+ __exportStar(require("./types"), exports);
package/dist/llm.d.ts ADDED
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
3
+ * http://github.com/fonoster/fonoster
4
+ *
5
+ * This file is part of Fonoster
6
+ *
7
+ * Licensed under the MIT License (the "License");
8
+ * you may not use this file except in compliance with
9
+ * the License. You may obtain a copy of the License at
10
+ *
11
+ * https://opensource.org/licenses/MIT
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+ export type ToolCall = {
20
+ id: string;
21
+ name: string;
22
+ arguments: string;
23
+ };
24
+ export type ChatMessage = {
25
+ role: "system" | "user";
26
+ content: string;
27
+ } | {
28
+ role: "assistant";
29
+ content: string;
30
+ tool_calls?: ToolCall[];
31
+ } | {
32
+ role: "tool";
33
+ tool_call_id: string;
34
+ content: string;
35
+ };
36
+ export type ThinkChunk = {
37
+ type: "text";
38
+ text: string;
39
+ } | {
40
+ type: "tool_calls";
41
+ calls: ToolCall[];
42
+ };
43
+ export type ToolSpec = {
44
+ name: string;
45
+ description: string;
46
+ parameters: Record<string, unknown>;
47
+ };
48
+ export interface Think {
49
+ stream(messages: ChatMessage[], tools: ToolSpec[], signal: AbortSignal): AsyncIterable<ThinkChunk>;
50
+ }
51
+ export type ThinkProvider = {
52
+ baseUrl: string;
53
+ apiKey?: string;
54
+ };
55
+ /**
56
+ * A language model vendor failed, named like the session error codes (registry "vendor errors
57
+ * map to provider_unavailable", task 1.5): unreachable or 401/403/429/5xx → provider_unavailable,
58
+ * 400/422 → bad_message. An abort is not a provider error and is rethrown as it is.
59
+ */
60
+ export declare class ThinkError extends Error {
61
+ readonly code: "provider_unavailable" | "provider_timeout" | "bad_message";
62
+ constructor(code: "provider_unavailable" | "provider_timeout" | "bad_message", message: string);
63
+ }
package/dist/llm.js ADDED
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
4
+ * http://github.com/fonoster/fonoster
5
+ *
6
+ * This file is part of Fonoster
7
+ *
8
+ * Licensed under the MIT License (the "License");
9
+ * you may not use this file except in compliance with
10
+ * the License. You may obtain a copy of the License at
11
+ *
12
+ * https://opensource.org/licenses/MIT
13
+ *
14
+ * Unless required by applicable law or agreed to in writing, software
15
+ * distributed under the License is distributed on an "AS IS" BASIS,
16
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ * See the License for the specific language governing permissions and
18
+ * limitations under the License.
19
+ */
20
+ // The LLM adapter interface (rework-autopilot A8: the Think plug): a streaming language model
21
+ // behind one interface. Implementations live in one subpath per vendor (openai covers
22
+ // OpenAI, Groq, Ollama and the conformance fake LLM).
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.ThinkError = void 0;
25
+ /**
26
+ * A language model vendor failed, named like the session error codes (registry "vendor errors
27
+ * map to provider_unavailable", task 1.5): unreachable or 401/403/429/5xx → provider_unavailable,
28
+ * 400/422 → bad_message. An abort is not a provider error and is rethrown as it is.
29
+ */
30
+ class ThinkError extends Error {
31
+ constructor(code, message) {
32
+ super(message);
33
+ this.code = code;
34
+ this.name = "ThinkError";
35
+ }
36
+ }
37
+ exports.ThinkError = ThinkError;
@@ -0,0 +1,20 @@
1
+ import { ChatMessage, Think, ThinkChunk, ThinkProvider, ToolSpec } from "../llm";
2
+ /** Adapters whose LLMs speak OpenAI-compatible Chat Completions, with their default endpoints. */
3
+ export declare const OPENAI_COMPATIBLE: Record<string, string | undefined>;
4
+ export declare class OpenAiCompatibleThink implements Think {
5
+ private readonly provider;
6
+ private readonly model;
7
+ private readonly options;
8
+ constructor(provider: ThinkProvider, model: string, options: {
9
+ temperature: number;
10
+ maxTokens: number;
11
+ /** Ask for a JSON object reply (catalog feature `json-mode`). */
12
+ jsonMode?: boolean;
13
+ });
14
+ stream(messages: ChatMessage[], tools: ToolSpec[], signal: AbortSignal): AsyncIterable<ThinkChunk>;
15
+ }
16
+ /** Resolves a catalog id (`<provider>/<model>`) against configured providers. */
17
+ export declare function resolveThink(catalogId: string, providers: Record<string, ThinkProvider>, options: {
18
+ temperature: number;
19
+ maxTokens: number;
20
+ }): Think;