@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.
@@ -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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"}
@@ -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 maxConcurrency = 4;
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
- maxConcurrency = 4;
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
- return await callWithTimeout(this.createMessage, params, timeoutMs);
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 instanceof SamplingTimeoutError) {
73
- throw new ProviderError(`MCP Sampling request timed out after ${error.timeoutMs}ms.`, {
74
- code: "provider.sampling_timeout",
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: "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."
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
- class SamplingTimeoutError extends Error {
88
- timeoutMs;
89
- constructor(timeoutMs) {
90
- super(`MCP Sampling request timed out after ${timeoutMs}ms.`);
91
- this.timeoutMs = timeoutMs;
92
- this.name = "SamplingTimeoutError";
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([fn(params, { signal: controller.signal, timeout: timeoutMs }), timeoutPromise]);
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 (timer)
109
- clearTimeout(timer);
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
@@ -1 +1 @@
1
- {"version":3,"file":"sampling.js","sourceRoot":"","sources":["../src/sampling.ts"],"names":[],"mappings":"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"}
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.1.4",
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.1.4"
38
+ "@deepthonk/core": "0.2.0"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "tsc -p tsconfig.json",