@deepthonk/providers 0.1.4 → 0.2.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 +26 -11
- package/dist/defaults.d.ts +10 -0
- package/dist/defaults.js +18 -7
- package/dist/defaults.js.map +1 -1
- package/dist/externalConfig.d.ts +67 -0
- package/dist/externalConfig.js +318 -0
- package/dist/externalConfig.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/openaiCompatible.d.ts +5 -1
- package/dist/openaiCompatible.js +263 -89
- package/dist/openaiCompatible.js.map +1 -1
- package/dist/profileRegistry.js +4 -2
- package/dist/profileRegistry.js.map +1 -1
- package/dist/providerReplay.d.ts +282 -0
- package/dist/providerReplay.js +186 -0
- package/dist/providerReplay.js.map +1 -0
- package/dist/registry.d.ts +2 -0
- package/dist/registry.js +42 -3
- package/dist/registry.js.map +1 -1
- package/dist/routeLimiter.d.ts +36 -0
- package/dist/routeLimiter.js +164 -0
- package/dist/routeLimiter.js.map +1 -0
- package/dist/sampling.d.ts +2 -1
- package/dist/sampling.js +136 -70
- package/dist/sampling.js.map +1 -1
- package/dist/types.d.ts +7 -0
- package/package.json +2 -2
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { createHmac, randomBytes } from "node:crypto";
|
|
2
|
+
const DEFAULT_DIRECT_CONCURRENCY = 8;
|
|
3
|
+
const DEFAULT_SAMPLING_CONCURRENCY = 4;
|
|
4
|
+
const SUCCESSES_PER_INCREASE = 32;
|
|
5
|
+
const ROUTE_CREDENTIAL_SALT = randomBytes(32);
|
|
6
|
+
/** FIFO adaptive concurrency limiter shared by every matching provider route in this process. */
|
|
7
|
+
export class AdaptiveRouteLimiter {
|
|
8
|
+
key;
|
|
9
|
+
active = 0;
|
|
10
|
+
queue = [];
|
|
11
|
+
ceilingValue;
|
|
12
|
+
configuredMaxValue;
|
|
13
|
+
explicitMaxConfiguredValue;
|
|
14
|
+
successesTowardIncrease = 0;
|
|
15
|
+
constructor(key, initialCeiling, configuredMax, explicitMaxConfigured = true) {
|
|
16
|
+
this.key = key;
|
|
17
|
+
this.configuredMaxValue = positiveInteger(configuredMax, "configuredMax");
|
|
18
|
+
this.explicitMaxConfiguredValue = explicitMaxConfigured;
|
|
19
|
+
this.ceilingValue = Math.min(positiveInteger(initialCeiling, "initialCeiling"), this.configuredMaxValue);
|
|
20
|
+
}
|
|
21
|
+
acquire(signal) {
|
|
22
|
+
if (signal?.aborted)
|
|
23
|
+
return Promise.reject(abortError(signal));
|
|
24
|
+
if (this.active < this.ceilingValue) {
|
|
25
|
+
this.active += 1;
|
|
26
|
+
return Promise.resolve(this.releaseOnce());
|
|
27
|
+
}
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
const waiter = { resolve, reject, signal };
|
|
30
|
+
if (signal) {
|
|
31
|
+
waiter.onAbort = () => {
|
|
32
|
+
const index = this.queue.indexOf(waiter);
|
|
33
|
+
if (index >= 0)
|
|
34
|
+
this.queue.splice(index, 1);
|
|
35
|
+
reject(abortError(signal));
|
|
36
|
+
};
|
|
37
|
+
signal.addEventListener("abort", waiter.onAbort, { once: true });
|
|
38
|
+
}
|
|
39
|
+
this.queue.push(waiter);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
recordRateLimit() {
|
|
43
|
+
this.ceilingValue = Math.max(1, Math.floor(this.ceilingValue / 2));
|
|
44
|
+
this.successesTowardIncrease = 0;
|
|
45
|
+
}
|
|
46
|
+
recordSuccess() {
|
|
47
|
+
this.successesTowardIncrease += 1;
|
|
48
|
+
if (this.successesTowardIncrease < SUCCESSES_PER_INCREASE)
|
|
49
|
+
return;
|
|
50
|
+
this.successesTowardIncrease = 0;
|
|
51
|
+
if (this.ceilingValue < this.configuredMaxValue) {
|
|
52
|
+
this.ceilingValue += 1;
|
|
53
|
+
this.drain();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Unspecified defaults establish a starting point, not a permanent cap. Once a route
|
|
58
|
+
* receives explicit maxima, conflicting explicit values resolve to their conservative minimum.
|
|
59
|
+
*/
|
|
60
|
+
constrainConfiguredMax(configuredMax, explicitlyConfigured = true) {
|
|
61
|
+
if (!explicitlyConfigured)
|
|
62
|
+
return;
|
|
63
|
+
const validated = positiveInteger(configuredMax, "configuredMax");
|
|
64
|
+
this.configuredMaxValue = this.explicitMaxConfiguredValue
|
|
65
|
+
? Math.min(this.configuredMaxValue, validated)
|
|
66
|
+
: validated;
|
|
67
|
+
this.explicitMaxConfiguredValue = true;
|
|
68
|
+
this.ceilingValue = Math.min(this.ceilingValue, this.configuredMaxValue);
|
|
69
|
+
}
|
|
70
|
+
snapshot() {
|
|
71
|
+
return {
|
|
72
|
+
key: this.key,
|
|
73
|
+
active: this.active,
|
|
74
|
+
queued: this.queue.length,
|
|
75
|
+
ceiling: this.ceilingValue,
|
|
76
|
+
configuredMax: this.configuredMaxValue,
|
|
77
|
+
explicitMaxConfigured: this.explicitMaxConfiguredValue,
|
|
78
|
+
successesTowardIncrease: this.successesTowardIncrease
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
releaseOnce() {
|
|
82
|
+
let released = false;
|
|
83
|
+
return () => {
|
|
84
|
+
if (released)
|
|
85
|
+
return;
|
|
86
|
+
released = true;
|
|
87
|
+
this.active = Math.max(0, this.active - 1);
|
|
88
|
+
this.drain();
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
drain() {
|
|
92
|
+
while (this.active < this.ceilingValue && this.queue.length > 0) {
|
|
93
|
+
const waiter = this.queue.shift();
|
|
94
|
+
if (waiter.signal?.aborted) {
|
|
95
|
+
waiter.reject(abortError(waiter.signal));
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (waiter.signal && waiter.onAbort)
|
|
99
|
+
waiter.signal.removeEventListener("abort", waiter.onAbort);
|
|
100
|
+
this.active += 1;
|
|
101
|
+
waiter.resolve(this.releaseOnce());
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const sharedLimiters = new Map();
|
|
106
|
+
export function getSharedRouteLimiter(config) {
|
|
107
|
+
const key = providerRouteLimiterKey(config);
|
|
108
|
+
const defaultCeiling = config.provider === "sampling" ? DEFAULT_SAMPLING_CONCURRENCY : DEFAULT_DIRECT_CONCURRENCY;
|
|
109
|
+
const explicitMaxConfigured = config.providerMaxConcurrency !== undefined;
|
|
110
|
+
const configuredMax = config.providerMaxConcurrency ?? defaultCeiling;
|
|
111
|
+
const existing = sharedLimiters.get(key);
|
|
112
|
+
if (existing) {
|
|
113
|
+
existing.constrainConfiguredMax(configuredMax, explicitMaxConfigured);
|
|
114
|
+
return existing;
|
|
115
|
+
}
|
|
116
|
+
const limiter = new AdaptiveRouteLimiter(key, defaultCeiling, configuredMax, explicitMaxConfigured);
|
|
117
|
+
sharedLimiters.set(key, limiter);
|
|
118
|
+
return limiter;
|
|
119
|
+
}
|
|
120
|
+
export function providerRouteLimiterKey(config) {
|
|
121
|
+
const endpoint = normalizeEndpoint(config.baseUrl) ?? (config.provider === "sampling" ? "mcp:sampling" : "default");
|
|
122
|
+
const credentialIdentity = routeCredentialIdentity(config);
|
|
123
|
+
return `${config.provider}|${endpoint}|${credentialIdentity}`;
|
|
124
|
+
}
|
|
125
|
+
/** Test-only process registry reset. */
|
|
126
|
+
export function resetSharedRouteLimiters() {
|
|
127
|
+
sharedLimiters.clear();
|
|
128
|
+
}
|
|
129
|
+
function normalizeEndpoint(value) {
|
|
130
|
+
if (!value)
|
|
131
|
+
return undefined;
|
|
132
|
+
try {
|
|
133
|
+
const url = new URL(value);
|
|
134
|
+
url.hash = "";
|
|
135
|
+
url.username = "";
|
|
136
|
+
url.password = "";
|
|
137
|
+
url.hostname = url.hostname.toLowerCase();
|
|
138
|
+
url.pathname = url.pathname.replace(/\/+$/, "");
|
|
139
|
+
return url.toString().replace(/\/$/, "");
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return value.trim().replace(/\/+$/, "").toLowerCase();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function routeCredentialIdentity(config) {
|
|
146
|
+
const secret = config.apiKey ?? (config.apiKeyEnv ? process.env[config.apiKeyEnv] : undefined);
|
|
147
|
+
if (secret)
|
|
148
|
+
return `secret:${saltedDigest(secret)}`;
|
|
149
|
+
if (config.apiKeyEnv)
|
|
150
|
+
return `missing-env:${saltedDigest(config.apiKeyEnv)}`;
|
|
151
|
+
return "none";
|
|
152
|
+
}
|
|
153
|
+
function saltedDigest(value) {
|
|
154
|
+
return createHmac("sha256", ROUTE_CREDENTIAL_SALT).update(value).digest("hex");
|
|
155
|
+
}
|
|
156
|
+
function positiveInteger(value, name) {
|
|
157
|
+
if (!Number.isInteger(value) || value < 1)
|
|
158
|
+
throw new TypeError(`${name} must be a positive integer.`);
|
|
159
|
+
return value;
|
|
160
|
+
}
|
|
161
|
+
function abortError(signal) {
|
|
162
|
+
return signal.reason instanceof DOMException ? signal.reason : new DOMException("Aborted", "AbortError");
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=routeLimiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routeLimiter.js","sourceRoot":"","sources":["../src/routeLimiter.ts"],"names":[],"mappings":"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"}
|
package/dist/sampling.d.ts
CHANGED
|
@@ -8,12 +8,13 @@ export interface SamplingDriverConfig {
|
|
|
8
8
|
intelligencePriority?: number;
|
|
9
9
|
includeRawOutputs?: boolean;
|
|
10
10
|
requestTimeoutMs?: number;
|
|
11
|
+
providerMaxConcurrency?: number;
|
|
11
12
|
}
|
|
12
13
|
export type SamplingTransport = (params: CreateMessageRequestParamsBase, options?: RequestOptions) => Promise<CreateMessageResult>;
|
|
13
14
|
export declare class SamplingDriver implements ModelDriver {
|
|
14
15
|
private readonly createMessage;
|
|
15
16
|
private readonly config;
|
|
16
|
-
readonly
|
|
17
|
+
private readonly routeLimiter;
|
|
17
18
|
constructor(createMessage: SamplingTransport, config?: SamplingDriverConfig);
|
|
18
19
|
generate(input: GenerateInput): Promise<ModelTextResult>;
|
|
19
20
|
compare(input: CompareInput): Promise<ModelTextResult>;
|
package/dist/sampling.js
CHANGED
|
@@ -1,81 +1,116 @@
|
|
|
1
1
|
import { ProviderError } from "@deepthonk/core";
|
|
2
2
|
import { extractJsonObjectText } from "./jsonExtract.js";
|
|
3
|
+
import { getSharedRouteLimiter } from "./routeLimiter.js";
|
|
3
4
|
const DEFAULT_SAMPLING_TIMEOUT_MS = 60_000;
|
|
5
|
+
const DEFAULT_SAMPLING_RESPONSE_LIMIT_BYTES = 1024 * 1024;
|
|
6
|
+
const DEFAULT_OUTPUT_TOKENS = 4096;
|
|
7
|
+
const DEFAULT_JUDGE_OUTPUT_TOKENS = 1024;
|
|
4
8
|
export class SamplingDriver {
|
|
5
9
|
createMessage;
|
|
6
10
|
config;
|
|
7
|
-
|
|
11
|
+
routeLimiter;
|
|
8
12
|
constructor(createMessage, config = {}) {
|
|
9
13
|
this.createMessage = createMessage;
|
|
10
14
|
this.config = config;
|
|
15
|
+
this.routeLimiter = getSharedRouteLimiter({
|
|
16
|
+
provider: "sampling",
|
|
17
|
+
models: { generator: "sampling", mutator: "sampling", judge: "sampling" },
|
|
18
|
+
providerMaxConcurrency: config.providerMaxConcurrency
|
|
19
|
+
});
|
|
11
20
|
}
|
|
12
21
|
async generate(input) {
|
|
13
|
-
return this.sample(input.model, input.temperature, promptMessages(input.prompt));
|
|
22
|
+
return this.sample(input.model, input.temperature, promptMessages(input.prompt), input.maxOutputTokens ?? DEFAULT_OUTPUT_TOKENS, input.signal);
|
|
14
23
|
}
|
|
15
24
|
async compare(input) {
|
|
16
|
-
const result = await this.sample(input.model, input.temperature, promptMessages(input.prompt));
|
|
25
|
+
const result = await this.sample(input.model, input.temperature, promptMessages(input.prompt), input.maxOutputTokens ?? DEFAULT_JUDGE_OUTPUT_TOKENS, input.signal);
|
|
17
26
|
return { ...result, text: extractJsonTextOrOriginal(result.text) };
|
|
18
27
|
}
|
|
19
28
|
async mutate(input) {
|
|
20
|
-
return this.sample(input.model, input.temperature, promptMessages(input.prompt));
|
|
29
|
+
return this.sample(input.model, input.temperature, promptMessages(input.prompt), input.maxOutputTokens ?? DEFAULT_OUTPUT_TOKENS, input.signal);
|
|
21
30
|
}
|
|
22
31
|
async finalize(input) {
|
|
23
|
-
return this.sample(input.model, 0.2, promptMessages(input.prompt));
|
|
32
|
+
return this.sample(input.model, 0.2, promptMessages(input.prompt), input.maxOutputTokens ?? DEFAULT_OUTPUT_TOKENS, input.signal);
|
|
24
33
|
}
|
|
25
|
-
async sample(model, temperature, prompt) {
|
|
34
|
+
async sample(model, temperature, prompt, maxOutputTokens, signal) {
|
|
26
35
|
const started = Date.now();
|
|
27
|
-
const result = await this.callCreateMessage({
|
|
28
|
-
messages: prompt.user.trim()
|
|
29
|
-
? [
|
|
30
|
-
{
|
|
31
|
-
role: "user",
|
|
32
|
-
content: {
|
|
33
|
-
type: "text",
|
|
34
|
-
text: prompt.user
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
]
|
|
38
|
-
: [],
|
|
39
|
-
systemPrompt: prompt.system.trim() ? prompt.system : undefined,
|
|
40
|
-
modelPreferences: buildModelPreferences(model, this.config),
|
|
41
|
-
includeContext: "none",
|
|
42
|
-
temperature,
|
|
43
|
-
maxTokens: 4096
|
|
44
|
-
});
|
|
45
|
-
if (result.stopReason === "maxTokens") {
|
|
46
|
-
throw new ProviderError("MCP Sampling response was truncated by maxTokens.", {
|
|
47
|
-
code: "provider.output_truncated",
|
|
48
|
-
retryable: false,
|
|
49
|
-
fix: "Use a smaller prompt, a host model with larger output support, or reduce answer length."
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
const text = textContent(result);
|
|
53
|
-
return {
|
|
54
|
-
text,
|
|
55
|
-
model: result.model ?? model,
|
|
56
|
-
provider: "sampling",
|
|
57
|
-
usage: {
|
|
58
|
-
inputTokens: undefined,
|
|
59
|
-
outputTokens: undefined
|
|
60
|
-
},
|
|
61
|
-
latencyMs: Date.now() - started,
|
|
62
|
-
retryCount: 0,
|
|
63
|
-
raw: this.config.includeRawOutputs ? result : undefined
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
async callCreateMessage(params) {
|
|
67
36
|
const timeoutMs = this.config.requestTimeoutMs ?? DEFAULT_SAMPLING_TIMEOUT_MS;
|
|
37
|
+
const deadline = samplingDeadline(timeoutMs, signal);
|
|
38
|
+
let release;
|
|
68
39
|
try {
|
|
69
|
-
|
|
40
|
+
release = await this.routeLimiter.acquire(deadline.signal);
|
|
41
|
+
const result = await this.callCreateMessage({
|
|
42
|
+
messages: prompt.user.trim()
|
|
43
|
+
? [
|
|
44
|
+
{
|
|
45
|
+
role: "user",
|
|
46
|
+
content: {
|
|
47
|
+
type: "text",
|
|
48
|
+
text: prompt.user
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
: [],
|
|
53
|
+
systemPrompt: prompt.system.trim() ? prompt.system : undefined,
|
|
54
|
+
modelPreferences: buildModelPreferences(model, this.config),
|
|
55
|
+
includeContext: "none",
|
|
56
|
+
temperature,
|
|
57
|
+
maxTokens: maxOutputTokens
|
|
58
|
+
}, deadline);
|
|
59
|
+
if (result.stopReason === "maxTokens") {
|
|
60
|
+
throw new ProviderError("MCP Sampling response was truncated by maxTokens.", {
|
|
61
|
+
code: "provider.output_truncated",
|
|
62
|
+
retryable: false,
|
|
63
|
+
fix: "Use a smaller prompt, a host model with larger output support, or reduce answer length."
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
const text = textContent(result);
|
|
67
|
+
if (Buffer.byteLength(text, "utf8") > DEFAULT_SAMPLING_RESPONSE_LIMIT_BYTES) {
|
|
68
|
+
throw new ProviderError(`MCP Sampling response exceeded the ${DEFAULT_SAMPLING_RESPONSE_LIMIT_BYTES}-byte body limit.`, {
|
|
69
|
+
code: "provider.response_too_large",
|
|
70
|
+
retryable: false,
|
|
71
|
+
fix: "Use a host model with bounded text responses or reduce the requested output size."
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
this.routeLimiter.recordSuccess();
|
|
75
|
+
return {
|
|
76
|
+
text,
|
|
77
|
+
model: result.model ?? model,
|
|
78
|
+
provider: "sampling",
|
|
79
|
+
usage: {
|
|
80
|
+
inputTokens: undefined,
|
|
81
|
+
outputTokens: undefined
|
|
82
|
+
},
|
|
83
|
+
latencyMs: Date.now() - started,
|
|
84
|
+
retryCount: 0,
|
|
85
|
+
raw: this.config.includeRawOutputs ? result : undefined
|
|
86
|
+
};
|
|
70
87
|
}
|
|
71
88
|
catch (error) {
|
|
72
|
-
if (error
|
|
73
|
-
|
|
74
|
-
|
|
89
|
+
if (isRateLimitError(error))
|
|
90
|
+
this.routeLimiter.recordRateLimit();
|
|
91
|
+
if (deadline.timedOut())
|
|
92
|
+
throw samplingTimeoutError(timeoutMs);
|
|
93
|
+
if (signal?.aborted) {
|
|
94
|
+
throw new ProviderError("MCP Sampling request was aborted.", {
|
|
95
|
+
code: "provider.aborted",
|
|
75
96
|
retryable: false,
|
|
76
|
-
fix: "
|
|
97
|
+
fix: "Retry the run if the cancellation was unintended."
|
|
77
98
|
});
|
|
78
99
|
}
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
release?.();
|
|
104
|
+
deadline.dispose();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async callCreateMessage(params, deadline) {
|
|
108
|
+
try {
|
|
109
|
+
return await callWithDeadline(this.createMessage, params, deadline);
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
if (deadline.signal.aborted)
|
|
113
|
+
throw error;
|
|
79
114
|
throw new ProviderError(`MCP Sampling request failed: ${error instanceof Error ? error.message : String(error)}`, {
|
|
80
115
|
code: "provider.sampling_request_failed",
|
|
81
116
|
retryable: false,
|
|
@@ -84,31 +119,58 @@ export class SamplingDriver {
|
|
|
84
119
|
}
|
|
85
120
|
}
|
|
86
121
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
async function callWithTimeout(fn, params, timeoutMs) {
|
|
96
|
-
const controller = new AbortController();
|
|
97
|
-
let timer;
|
|
98
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
99
|
-
timer = setTimeout(() => {
|
|
100
|
-
controller.abort();
|
|
101
|
-
reject(new SamplingTimeoutError(timeoutMs));
|
|
102
|
-
}, timeoutMs);
|
|
122
|
+
async function callWithDeadline(fn, params, deadline) {
|
|
123
|
+
if (deadline.signal.aborted)
|
|
124
|
+
throw abortError(deadline.signal);
|
|
125
|
+
let rejectOnAbort;
|
|
126
|
+
const abortPromise = new Promise((_, reject) => {
|
|
127
|
+
rejectOnAbort = () => reject(abortError(deadline.signal));
|
|
128
|
+
deadline.signal.addEventListener("abort", rejectOnAbort, { once: true });
|
|
103
129
|
});
|
|
104
130
|
try {
|
|
105
|
-
return await Promise.race([
|
|
131
|
+
return await Promise.race([
|
|
132
|
+
fn(params, { signal: deadline.signal, timeout: Math.max(1, deadline.remainingMs()) }),
|
|
133
|
+
abortPromise
|
|
134
|
+
]);
|
|
106
135
|
}
|
|
107
136
|
finally {
|
|
108
|
-
if (
|
|
109
|
-
|
|
137
|
+
if (rejectOnAbort)
|
|
138
|
+
deadline.signal.removeEventListener("abort", rejectOnAbort);
|
|
110
139
|
}
|
|
111
140
|
}
|
|
141
|
+
function samplingDeadline(timeoutMs, inputSignal) {
|
|
142
|
+
const controller = new AbortController();
|
|
143
|
+
const expiresAt = Date.now() + timeoutMs;
|
|
144
|
+
let timeoutReached = false;
|
|
145
|
+
const onInputAbort = () => controller.abort(inputSignal?.reason);
|
|
146
|
+
if (inputSignal?.aborted)
|
|
147
|
+
controller.abort(inputSignal.reason);
|
|
148
|
+
else
|
|
149
|
+
inputSignal?.addEventListener("abort", onInputAbort, { once: true });
|
|
150
|
+
const timer = setTimeout(() => {
|
|
151
|
+
timeoutReached = true;
|
|
152
|
+
controller.abort(new DOMException("Timed out", "AbortError"));
|
|
153
|
+
}, timeoutMs);
|
|
154
|
+
return {
|
|
155
|
+
signal: controller.signal,
|
|
156
|
+
timedOut: () => timeoutReached,
|
|
157
|
+
remainingMs: () => Math.max(0, expiresAt - Date.now()),
|
|
158
|
+
dispose: () => {
|
|
159
|
+
clearTimeout(timer);
|
|
160
|
+
inputSignal?.removeEventListener("abort", onInputAbort);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function samplingTimeoutError(timeoutMs) {
|
|
165
|
+
return new ProviderError(`MCP Sampling request timed out after ${timeoutMs}ms.`, {
|
|
166
|
+
code: "provider.sampling_timeout",
|
|
167
|
+
retryable: false,
|
|
168
|
+
fix: "Increase retry.requestTimeoutMs, switch to a direct provider, or check the MCP host responsiveness. Use 'deepthonk resume <run-dir> --continue' to retry an interrupted run."
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
function abortError(signal) {
|
|
172
|
+
return signal.reason instanceof DOMException ? signal.reason : new DOMException("Aborted", "AbortError");
|
|
173
|
+
}
|
|
112
174
|
export function buildModelPreferences(roleModel, config) {
|
|
113
175
|
const hintNames = uniqueNonEmpty([roleModel, ...(config.modelHints ?? [])]);
|
|
114
176
|
const preferences = {};
|
|
@@ -156,4 +218,8 @@ function uniqueNonEmpty(values) {
|
|
|
156
218
|
}
|
|
157
219
|
return unique;
|
|
158
220
|
}
|
|
221
|
+
function isRateLimitError(error) {
|
|
222
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
223
|
+
return /\b429\b|rate.?limit/i.test(message);
|
|
224
|
+
}
|
|
159
225
|
//# sourceMappingURL=sampling.js.map
|
package/dist/sampling.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sampling.js","sourceRoot":"","sources":["../src/sampling.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAQd,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"sampling.js","sourceRoot":"","sources":["../src/sampling.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -7,14 +7,19 @@ export interface RoleProviderConfig {
|
|
|
7
7
|
apiKeyEnv?: string;
|
|
8
8
|
apiKey?: string;
|
|
9
9
|
model: string;
|
|
10
|
+
providerMaxConcurrency?: number;
|
|
10
11
|
retry?: {
|
|
11
12
|
httpRetries?: number;
|
|
12
13
|
requestTimeoutMs?: number;
|
|
14
|
+
responseBodyLimitBytes?: number;
|
|
15
|
+
maxRetryDelayMs?: number;
|
|
13
16
|
};
|
|
14
17
|
supportsJsonMode?: boolean;
|
|
15
18
|
}
|
|
16
19
|
export interface BaseProviderConfig extends SamplingDriverConfig {
|
|
17
20
|
provider: "fake" | "openai-compatible" | "deepseek" | string;
|
|
21
|
+
routeFingerprint?: string;
|
|
22
|
+
providerMaxConcurrency?: number;
|
|
18
23
|
baseUrl?: string;
|
|
19
24
|
apiKeyEnv?: string;
|
|
20
25
|
apiKey?: string;
|
|
@@ -28,6 +33,8 @@ export interface BaseProviderConfig extends SamplingDriverConfig {
|
|
|
28
33
|
retry?: {
|
|
29
34
|
httpRetries?: number;
|
|
30
35
|
requestTimeoutMs?: number;
|
|
36
|
+
responseBodyLimitBytes?: number;
|
|
37
|
+
maxRetryDelayMs?: number;
|
|
31
38
|
};
|
|
32
39
|
supportsJsonMode?: boolean;
|
|
33
40
|
roleProviders?: Partial<Record<ProviderRole, RoleProviderConfig>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepthonk/providers",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Provider drivers and routing for DeepThonk.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Xule Lin",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
36
36
|
"yaml": "^2.7.1",
|
|
37
37
|
"zod": "^3.25.28",
|
|
38
|
-
"@deepthonk/core": "0.
|
|
38
|
+
"@deepthonk/core": "0.2.0"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "tsc -p tsconfig.json",
|