@arikusi/deepseek-mcp-server 1.1.1 → 1.3.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.
Files changed (67) hide show
  1. package/CHANGELOG.md +44 -1
  2. package/README.md +134 -18
  3. package/dist/circuit-breaker.d.ts +37 -0
  4. package/dist/circuit-breaker.d.ts.map +1 -0
  5. package/dist/circuit-breaker.js +101 -0
  6. package/dist/circuit-breaker.js.map +1 -0
  7. package/dist/config.d.ts +9 -0
  8. package/dist/config.d.ts.map +1 -1
  9. package/dist/config.js +10 -0
  10. package/dist/config.js.map +1 -1
  11. package/dist/cost.d.ts +30 -13
  12. package/dist/cost.d.ts.map +1 -1
  13. package/dist/cost.js +58 -19
  14. package/dist/cost.js.map +1 -1
  15. package/dist/deepseek-client.d.ts +23 -5
  16. package/dist/deepseek-client.d.ts.map +1 -1
  17. package/dist/deepseek-client.js +256 -115
  18. package/dist/deepseek-client.js.map +1 -1
  19. package/dist/errors.d.ts +13 -0
  20. package/dist/errors.d.ts.map +1 -1
  21. package/dist/errors.js +18 -0
  22. package/dist/errors.js.map +1 -1
  23. package/dist/index.js +5 -2
  24. package/dist/index.js.map +1 -1
  25. package/dist/resources/config.d.ts +7 -0
  26. package/dist/resources/config.d.ts.map +1 -0
  27. package/dist/resources/config.js +44 -0
  28. package/dist/resources/config.js.map +1 -0
  29. package/dist/resources/index.d.ts +7 -0
  30. package/dist/resources/index.d.ts.map +1 -0
  31. package/dist/resources/index.js +13 -0
  32. package/dist/resources/index.js.map +1 -0
  33. package/dist/resources/models.d.ts +7 -0
  34. package/dist/resources/models.d.ts.map +1 -0
  35. package/dist/resources/models.js +62 -0
  36. package/dist/resources/models.js.map +1 -0
  37. package/dist/resources/usage.d.ts +7 -0
  38. package/dist/resources/usage.d.ts.map +1 -0
  39. package/dist/resources/usage.js +31 -0
  40. package/dist/resources/usage.js.map +1 -0
  41. package/dist/schemas.d.ts +72 -20
  42. package/dist/schemas.d.ts.map +1 -1
  43. package/dist/schemas.js +15 -2
  44. package/dist/schemas.js.map +1 -1
  45. package/dist/session.d.ts +68 -0
  46. package/dist/session.d.ts.map +1 -0
  47. package/dist/session.js +184 -0
  48. package/dist/session.js.map +1 -0
  49. package/dist/tools/deepseek-chat.d.ts +2 -1
  50. package/dist/tools/deepseek-chat.d.ts.map +1 -1
  51. package/dist/tools/deepseek-chat.js +97 -32
  52. package/dist/tools/deepseek-chat.js.map +1 -1
  53. package/dist/tools/deepseek-sessions.d.ts +7 -0
  54. package/dist/tools/deepseek-sessions.d.ts.map +1 -0
  55. package/dist/tools/deepseek-sessions.js +101 -0
  56. package/dist/tools/deepseek-sessions.js.map +1 -0
  57. package/dist/tools/index.d.ts.map +1 -1
  58. package/dist/tools/index.js +2 -0
  59. package/dist/tools/index.js.map +1 -1
  60. package/dist/types.d.ts +71 -0
  61. package/dist/types.d.ts.map +1 -1
  62. package/dist/types.js.map +1 -1
  63. package/dist/usage-tracker.d.ts +40 -0
  64. package/dist/usage-tracker.d.ts.map +1 -0
  65. package/dist/usage-tracker.js +76 -0
  66. package/dist/usage-tracker.js.map +1 -0
  67. package/package.json +5 -2
package/CHANGELOG.md CHANGED
@@ -16,6 +16,45 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
16
  ### Fixed
17
17
  - Nothing yet
18
18
 
19
+ ## [1.3.0] - 2026-03-04
20
+
21
+ ### Added
22
+ - **Multi-Turn Sessions**: `session_id` parameter on `deepseek_chat` for multi-turn conversations. Session history is stored in memory and automatically prepended to requests. Sessions have configurable TTL and max count.
23
+ - **Session Management Tool**: `deepseek_sessions` tool with `list`, `delete`, and `clear` actions for managing active sessions.
24
+ - **Circuit Breaker**: Protects against cascading API failures. After 5 consecutive failures, fast-fails for 30 seconds, then probes for recovery.
25
+ - **Model Fallback**: Automatic fallback between `deepseek-chat` and `deepseek-reasoner` on retryable errors (429, 503, timeout). Configurable via `FALLBACK_ENABLED`.
26
+ - **MCP Resources**: 3 read-only resources following MCP Resources spec:
27
+ - `deepseek://models`: Model list with capabilities, context limits, and pricing
28
+ - `deepseek://config`: Current server configuration (API key masked)
29
+ - `deepseek://usage`: Real-time usage statistics (requests, tokens, costs, sessions)
30
+ - **Usage Tracker**: Global usage statistics tracking across all requests.
31
+ - **New Error Classes**: `FallbackExhaustedError`, `CircuitBreakerOpenError` for resilience error handling.
32
+ - **New Config**: `SESSION_TTL_MINUTES` (default: 30), `MAX_SESSIONS` (default: 100), `FALLBACK_ENABLED` (default: true).
33
+ - **198 Tests**: Up from 150, covering sessions, circuit breaker, fallback, and MCP resources.
34
+
35
+ ### Changed
36
+ - `deepseek-client.ts` now wraps API calls in circuit breaker and supports automatic model fallback.
37
+ - `deepseek_chat` tool description updated to mention sessions, fallback, and circuit breaker.
38
+ - `tools/index.ts` now registers both `deepseek_chat` and `deepseek_sessions` tools.
39
+ - `index.ts` now registers MCP resources via `registerAllResources()`.
40
+
41
+ ## [1.2.0] - 2026-02-26
42
+
43
+ ### Added
44
+ - **Thinking Mode**: Enable enhanced reasoning on deepseek-chat with `thinking: {type: "enabled"}` parameter. Automatically filters incompatible params (temperature, top_p, etc.) with logged warnings.
45
+ - **JSON Output Mode**: Structured JSON responses with `json_mode: true`. Supported by both models. Warns if "json" word missing from prompt.
46
+ - **Cache-Aware Cost Tracking**: V3.2 API returns `prompt_cache_hit_tokens` and `prompt_cache_miss_tokens`. Cost display now shows cache hit ratio and savings.
47
+ - **CostBreakdown Interface**: `calculateCost()` returns structured `{inputCost, outputCost, totalCost, cacheHitRatio?, cacheSavings?}` instead of flat number.
48
+
49
+ ### Changed
50
+ - **DeepSeek V3.2 Pricing**: Unified pricing for both models — cache hit $0.028/1M, cache miss $0.28/1M, output $0.42/1M (replaces old per-model pricing).
51
+ - **max_tokens Limit**: Updated from 32768 to 65536 (reasoner max). Model-specific warnings: deepseek-chat warns above 8192, deepseek-reasoner warns above 65536.
52
+ - **Tool Description**: Updated to mention V3.2, thinking mode, JSON mode, and cache-aware cost tracking.
53
+ - **150 Tests**: Up from 126, covering thinking mode, JSON mode, cache tokens, and cost breakdown.
54
+
55
+ ### Fixed
56
+ - **Incorrect Cost Reports**: Old flat pricing ($0.14/$0.28 chat, $0.55/$2.19 reasoner) replaced with accurate V3.2 unified pricing.
57
+
19
58
  ## [1.1.1] - 2026-02-11
20
59
 
21
60
  ### Added
@@ -154,6 +193,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
154
193
 
155
194
  ## Version History
156
195
 
196
+ - **1.3.0** (2026-03-04): Sessions, circuit breaker, model fallback, MCP resources, 198 tests
197
+ - **1.2.0** (2026-02-26): DeepSeek V3.2 support — thinking mode, JSON mode, cache-aware pricing, 150 tests
157
198
  - **1.1.1** (2026-02-11): Modular architecture, type safety, security fixes, 126 tests
158
199
  - **1.1.0** (2026-02-10): Function calling, config system, test suite
159
200
  - **1.0.3** (2025-02-07): Cost tracking and prompt templates
@@ -166,7 +207,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
166
207
  - [GitHub repository](https://github.com/arikusi/deepseek-mcp-server)
167
208
  - [Issue tracker](https://github.com/arikusi/deepseek-mcp-server/issues)
168
209
 
169
- [Unreleased]: https://github.com/arikusi/deepseek-mcp-server/compare/v1.1.1...HEAD
210
+ [Unreleased]: https://github.com/arikusi/deepseek-mcp-server/compare/v1.3.0...HEAD
211
+ [1.3.0]: https://github.com/arikusi/deepseek-mcp-server/compare/v1.2.0...v1.3.0
212
+ [1.2.0]: https://github.com/arikusi/deepseek-mcp-server/compare/v1.1.1...v1.2.0
170
213
  [1.1.1]: https://github.com/arikusi/deepseek-mcp-server/compare/v1.1.0...v1.1.1
171
214
  [1.1.0]: https://github.com/arikusi/deepseek-mcp-server/compare/v1.0.3...v1.1.0
172
215
  [1.0.3]: https://github.com/arikusi/deepseek-mcp-server/releases/tag/v1.0.3
package/README.md CHANGED
@@ -7,12 +7,12 @@
7
7
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.7-blue.svg)](https://www.typescriptlang.org/)
8
8
  [![Build Status](https://github.com/arikusi/deepseek-mcp-server/workflows/CI/badge.svg)](https://github.com/arikusi/deepseek-mcp-server/actions)
9
9
 
10
- A Model Context Protocol (MCP) server that integrates DeepSeek AI models with MCP-compatible clients. Access DeepSeek's powerful chat and reasoning models directly from your development environment.
10
+ A Model Context Protocol (MCP) server that integrates DeepSeek AI models with MCP-compatible clients. Access DeepSeek's powerful chat and reasoning models with multi-turn sessions, automatic model fallback, and MCP Resources directly from your development environment.
11
11
 
12
12
  **Compatible with:**
13
13
  - Claude Code CLI
14
- - Gemini CLI (if MCP support is available)
15
- - Any MCP-compatible client
14
+ - Gemini CLI
15
+ - Any MCP-compatible client (Cursor, Windsurf, etc.)
16
16
 
17
17
  > **Note**: This is an unofficial community project and is not affiliated with DeepSeek.
18
18
 
@@ -48,14 +48,19 @@ That's it! Your MCP client can now use DeepSeek models!
48
48
 
49
49
  ## Features
50
50
 
51
- - **DeepSeek Chat**: Fast and capable general-purpose model
52
- - **DeepSeek Reasoner (R1)**: Advanced reasoning with chain-of-thought explanations
51
+ - **DeepSeek V3.2**: Both models now run DeepSeek-V3.2 (since Sept 2025)
52
+ - **Multi-Turn Sessions**: Conversation context preserved across requests via `session_id` parameter
53
+ - **Model Fallback & Circuit Breaker**: Automatic fallback between models with circuit breaker protection against cascading failures
54
+ - **MCP Resources**: `deepseek://models`, `deepseek://config`, `deepseek://usage` — query model info, config, and usage stats
55
+ - **Thinking Mode**: Enable enhanced reasoning on deepseek-chat with `thinking: {type: "enabled"}`
56
+ - **JSON Output Mode**: Structured JSON responses with `json_mode: true`
53
57
  - **Function Calling**: OpenAI-compatible tool use with up to 128 tool definitions
54
- - **Cost Tracking**: Automatic cost calculation for every request (USD)
58
+ - **Cache-Aware Cost Tracking**: Automatic cost calculation with cache hit/miss breakdown
59
+ - **Session Management Tool**: List, delete, and clear sessions via `deepseek_sessions` tool
55
60
  - **Configurable**: Environment-based configuration with validation
56
61
  - **12 Prompt Templates**: Pre-built templates for debugging, code review, function calling, and more
57
62
  - **Streaming Support**: Real-time response generation
58
- - **Tested**: 126 tests with 90%+ code coverage
63
+ - **Tested**: 198 tests with 90%+ code coverage
59
64
  - **Type-Safe**: Full TypeScript implementation
60
65
  - **MCP Compatible**: Works with any MCP-compatible CLI (Claude Code, Gemini CLI, etc.)
61
66
 
@@ -97,7 +102,7 @@ npm run build
97
102
 
98
103
  ## Usage
99
104
 
100
- Once configured, your MCP client will have access to the `deepseek_chat` tool and can use DeepSeek models.
105
+ Once configured, your MCP client will have access to `deepseek_chat` and `deepseek_sessions` tools, plus 3 MCP resources.
101
106
 
102
107
  **Example prompts:**
103
108
  ```
@@ -142,11 +147,14 @@ Chat with DeepSeek AI models with automatic cost tracking and function calling s
142
147
  - `content`: Message text
143
148
  - `tool_call_id` (optional): Required for tool role messages
144
149
  - `model` (optional): "deepseek-chat" (default) or "deepseek-reasoner"
145
- - `temperature` (optional): 0-2, controls randomness (default: 1.0)
146
- - `max_tokens` (optional): Maximum tokens to generate
150
+ - `temperature` (optional): 0-2, controls randomness (default: 1.0). Ignored when thinking mode is enabled.
151
+ - `max_tokens` (optional): Maximum tokens to generate (deepseek-chat: max 8192, deepseek-reasoner: max 65536)
147
152
  - `stream` (optional): Enable streaming mode (default: false)
148
153
  - `tools` (optional): Array of tool definitions for function calling (max 128)
149
154
  - `tool_choice` (optional): "auto" | "none" | "required" | `{type: "function", function: {name: "..."}}`
155
+ - `thinking` (optional): Enable thinking mode `{type: "enabled"}` for enhanced reasoning
156
+ - `json_mode` (optional): Enable JSON output mode (supported by both models)
157
+ - `session_id` (optional): Session ID for multi-turn conversations. Previous context is automatically prepended.
150
158
 
151
159
  **Response includes:**
152
160
  - Content with formatting
@@ -221,6 +229,94 @@ The reasoner model will show its thinking process in `<thinking>` tags followed
221
229
 
222
230
  When the model decides to call a function, the response includes `tool_calls` with the function name and arguments. You can then send the result back using a `tool` role message with the matching `tool_call_id`.
223
231
 
232
+ **Thinking Mode Example:**
233
+
234
+ ```json
235
+ {
236
+ "messages": [
237
+ {
238
+ "role": "user",
239
+ "content": "Analyze the time complexity of quicksort"
240
+ }
241
+ ],
242
+ "model": "deepseek-chat",
243
+ "thinking": { "type": "enabled" }
244
+ }
245
+ ```
246
+
247
+ When thinking mode is enabled, `temperature`, `top_p`, `frequency_penalty`, and `presence_penalty` are automatically ignored. The model provides enhanced reasoning capabilities similar to deepseek-reasoner.
248
+
249
+ **JSON Output Mode Example:**
250
+
251
+ ```json
252
+ {
253
+ "messages": [
254
+ {
255
+ "role": "user",
256
+ "content": "Return a json object with name, age, and city fields for a sample user"
257
+ }
258
+ ],
259
+ "model": "deepseek-chat",
260
+ "json_mode": true
261
+ }
262
+ ```
263
+
264
+ JSON mode ensures the model outputs valid JSON. Include the word "json" in your prompt for best results. Supported by both `deepseek-chat` and `deepseek-reasoner`.
265
+
266
+ **Multi-Turn Session Example:**
267
+
268
+ ```json
269
+ {
270
+ "messages": [
271
+ {
272
+ "role": "user",
273
+ "content": "What is the capital of France?"
274
+ }
275
+ ],
276
+ "session_id": "my-session-1"
277
+ }
278
+ ```
279
+
280
+ Use the same `session_id` across requests to maintain conversation context. The server stores messages in memory and automatically prepends history to each request.
281
+
282
+ ### `deepseek_sessions`
283
+
284
+ Manage conversation sessions.
285
+
286
+ **Parameters:**
287
+ - `action` (required): "list" | "clear" | "delete"
288
+ - `session_id` (optional): Required when action is "delete"
289
+
290
+ **Examples:**
291
+ ```json
292
+ {"action": "list"}
293
+ {"action": "delete", "session_id": "my-session-1"}
294
+ {"action": "clear"}
295
+ ```
296
+
297
+ ## Available Resources
298
+
299
+ MCP Resources provide read-only data about the server:
300
+
301
+ | Resource URI | Description |
302
+ |-------------|-------------|
303
+ | `deepseek://models` | Available models with capabilities, context limits, and pricing |
304
+ | `deepseek://config` | Current server configuration (API key masked) |
305
+ | `deepseek://usage` | Real-time usage statistics (requests, tokens, costs, sessions) |
306
+
307
+ ## Model Fallback & Circuit Breaker
308
+
309
+ When a model fails with a retryable error (429, 503, timeout), the server automatically falls back to the other model:
310
+ - `deepseek-chat` fails → tries `deepseek-reasoner`
311
+ - `deepseek-reasoner` fails → tries `deepseek-chat`
312
+
313
+ The circuit breaker protects against cascading failures:
314
+ - After 5 consecutive failures, the circuit **opens** (fast-fail mode)
315
+ - After 30 seconds, it enters **half-open** state and sends a probe request
316
+ - If the probe succeeds, the circuit **closes** and normal operation resumes
317
+
318
+ Fallback can be disabled with `FALLBACK_ENABLED=false`.
319
+
224
320
  ## Available Prompts
225
321
 
226
322
  Pre-built prompt templates for common tasks (12 total):
@@ -247,20 +343,28 @@ Each prompt is optimized for the DeepSeek Reasoner model to provide detailed rea
247
343
 
248
344
  ## Models
249
345
 
346
+ Both models run **DeepSeek-V3.2** with unified pricing.
347
+
250
348
  ### deepseek-chat
251
349
 
252
350
  - **Best for**: General conversations, coding, content generation
253
351
  - **Speed**: Fast
254
- - **Context**: 64K tokens
255
- - **Cost**: Most economical
352
+ - **Context**: 128K tokens
353
+ - **Max Output**: 8K tokens (default 4K)
354
+ - **Mode**: Non-thinking (can enable thinking via parameter)
355
+ - **Features**: Thinking mode, JSON mode, function calling, FIM completion
356
+ - **Pricing**: $0.028/1M cache hit, $0.28/1M cache miss, $0.42/1M output
256
357
 
257
- ### deepseek-reasoner (R1)
358
+ ### deepseek-reasoner
258
359
 
259
360
  - **Best for**: Complex reasoning, math, logic problems, multi-step tasks
260
361
  - **Speed**: Slower (shows thinking process)
261
- - **Context**: 64K tokens
262
- - **Special**: Provides chain-of-thought reasoning
362
+ - **Context**: 128K tokens
363
+ - **Max Output**: 64K tokens (default 32K)
364
+ - **Mode**: Thinking (always active, chain-of-thought reasoning)
365
+ - **Features**: JSON mode, function calling
263
366
  - **Output**: Both reasoning process and final answer
367
+ - **Pricing**: $0.028/1M cache hit, $0.28/1M cache miss, $0.42/1M output
264
368
 
265
369
  ## Configuration
266
370
 
@@ -275,6 +379,9 @@ The server is configured via environment variables. All settings except `DEEPSEE
275
379
  | `MAX_RETRIES` | `2` | Maximum retry count for failed requests |
276
380
  | `SKIP_CONNECTION_TEST` | `false` | Skip startup API connection test |
277
381
  | `MAX_MESSAGE_LENGTH` | `100000` | Maximum message content length (characters) |
382
+ | `SESSION_TTL_MINUTES` | `30` | Session time-to-live in minutes |
383
+ | `MAX_SESSIONS` | `100` | Maximum number of concurrent sessions |
384
+ | `FALLBACK_ENABLED` | `true` | Enable automatic model fallback on errors |
278
385
 
279
386
  **Example with custom config:**
280
387
  ```bash
@@ -291,17 +398,26 @@ claude mcp add -s user deepseek npx @arikusi/deepseek-mcp-server \
291
398
  ```
292
399
  deepseek-mcp-server/
293
400
  ├── src/
294
- │ ├── index.ts # Entry point, bootstrap (~80 lines)
401
+ │ ├── index.ts # Entry point, bootstrap
295
402
  │ ├── server.ts # McpServer factory (auto-version)
296
- │ ├── deepseek-client.ts # DeepSeek API wrapper (OpenAI SDK)
403
+ │ ├── deepseek-client.ts # DeepSeek API wrapper (circuit breaker + fallback)
297
404
  │ ├── config.ts # Centralized config with Zod validation
298
405
  │ ├── cost.ts # Cost calculation and formatting
299
406
  │ ├── schemas.ts # Zod input validation schemas
300
407
  │ ├── types.ts # TypeScript types + type guards
301
408
  │ ├── errors.ts # Custom error classes
409
+ │ ├── session.ts # In-memory session store (multi-turn)
410
+ │ ├── circuit-breaker.ts # Circuit breaker pattern
411
+ │ ├── usage-tracker.ts # Usage statistics tracker
302
412
  │ ├── tools/
303
- │ │ ├── deepseek-chat.ts # deepseek_chat tool handler
413
+ │ │ ├── deepseek-chat.ts # deepseek_chat tool (sessions + fallback)
414
+ │ │ ├── deepseek-sessions.ts # deepseek_sessions tool
304
415
  │ │ └── index.ts # Tool registration aggregator
416
+ │ ├── resources/
417
+ │ │ ├── models.ts # deepseek://models resource
418
+ │ │ ├── config.ts # deepseek://config resource
419
+ │ │ ├── usage.ts # deepseek://usage resource
420
+ │ │ └── index.ts # Resource registration aggregator
305
421
  │ └── prompts/
306
422
  │ ├── core.ts # 5 core reasoning prompts
307
423
  │ ├── advanced.ts # 5 advanced prompts
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Circuit Breaker Pattern
3
+ * Prevents cascading failures by fast-failing when the API is unhealthy
4
+ *
5
+ * States:
6
+ * CLOSED → normal operation, requests pass through
7
+ * OPEN → API is unhealthy, requests are immediately rejected
8
+ * HALF_OPEN → testing if API has recovered with a single probe request
9
+ */
10
+ import type { CircuitBreakerStatus } from './types.js';
11
+ export declare class CircuitBreaker {
12
+ private readonly threshold;
13
+ private readonly openTimeout;
14
+ private state;
15
+ private failureCount;
16
+ private lastFailureTime;
17
+ private halfOpenInProgress;
18
+ constructor(threshold?: number, openTimeout?: number);
19
+ /**
20
+ * Execute a function through the circuit breaker.
21
+ * - CLOSED: pass through, track failures
22
+ * - OPEN: reject immediately (fast-fail) unless timeout elapsed → HALF_OPEN
23
+ * - HALF_OPEN: allow one probe request
24
+ */
25
+ execute<T>(fn: () => Promise<T>): Promise<T>;
26
+ /**
27
+ * Get current circuit breaker status
28
+ */
29
+ getStatus(): CircuitBreakerStatus;
30
+ /**
31
+ * Manually reset the circuit breaker to CLOSED state
32
+ */
33
+ reset(): void;
34
+ private onSuccess;
35
+ private onFailure;
36
+ }
37
+ //# sourceMappingURL=circuit-breaker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../src/circuit-breaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAuB,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAE5E,qBAAa,cAAc;IAOvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAP9B,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,kBAAkB,CAAS;gBAGhB,SAAS,GAAE,MAAU,EACrB,WAAW,GAAE,MAAc;IAG9C;;;;;OAKG;IACG,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA+BlD;;OAEG;IACH,SAAS,IAAI,oBAAoB;IAiBjC;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,SAAS;CAYlB"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Circuit Breaker Pattern
3
+ * Prevents cascading failures by fast-failing when the API is unhealthy
4
+ *
5
+ * States:
6
+ * CLOSED → normal operation, requests pass through
7
+ * OPEN → API is unhealthy, requests are immediately rejected
8
+ * HALF_OPEN → testing if API has recovered with a single probe request
9
+ */
10
+ import { CircuitBreakerOpenError } from './errors.js';
11
+ export class CircuitBreaker {
12
+ threshold;
13
+ openTimeout;
14
+ state = 'CLOSED';
15
+ failureCount = 0;
16
+ lastFailureTime = 0;
17
+ halfOpenInProgress = false;
18
+ constructor(threshold = 5, openTimeout = 30000) {
19
+ this.threshold = threshold;
20
+ this.openTimeout = openTimeout;
21
+ }
22
+ /**
23
+ * Execute a function through the circuit breaker.
24
+ * - CLOSED: pass through, track failures
25
+ * - OPEN: reject immediately (fast-fail) unless timeout elapsed → HALF_OPEN
26
+ * - HALF_OPEN: allow one probe request
27
+ */
28
+ async execute(fn) {
29
+ if (this.state === 'OPEN') {
30
+ // Check if enough time has elapsed to try half-open
31
+ if (Date.now() - this.lastFailureTime >= this.openTimeout) {
32
+ this.state = 'HALF_OPEN';
33
+ this.halfOpenInProgress = false;
34
+ }
35
+ else {
36
+ throw new CircuitBreakerOpenError();
37
+ }
38
+ }
39
+ if (this.state === 'HALF_OPEN' && this.halfOpenInProgress) {
40
+ throw new CircuitBreakerOpenError('Circuit breaker is half-open — probe request in progress');
41
+ }
42
+ if (this.state === 'HALF_OPEN') {
43
+ this.halfOpenInProgress = true;
44
+ }
45
+ try {
46
+ const result = await fn();
47
+ this.onSuccess();
48
+ return result;
49
+ }
50
+ catch (error) {
51
+ this.onFailure();
52
+ throw error;
53
+ }
54
+ }
55
+ /**
56
+ * Get current circuit breaker status
57
+ */
58
+ getStatus() {
59
+ // Auto-transition from OPEN to HALF_OPEN if timeout elapsed
60
+ if (this.state === 'OPEN' &&
61
+ Date.now() - this.lastFailureTime >= this.openTimeout) {
62
+ this.state = 'HALF_OPEN';
63
+ this.halfOpenInProgress = false;
64
+ }
65
+ return {
66
+ state: this.state,
67
+ failureCount: this.failureCount,
68
+ lastFailureTime: this.lastFailureTime,
69
+ };
70
+ }
71
+ /**
72
+ * Manually reset the circuit breaker to CLOSED state
73
+ */
74
+ reset() {
75
+ this.state = 'CLOSED';
76
+ this.failureCount = 0;
77
+ this.lastFailureTime = 0;
78
+ this.halfOpenInProgress = false;
79
+ }
80
+ onSuccess() {
81
+ if (this.state === 'HALF_OPEN') {
82
+ // Probe succeeded → close circuit
83
+ this.state = 'CLOSED';
84
+ this.halfOpenInProgress = false;
85
+ }
86
+ this.failureCount = 0;
87
+ }
88
+ onFailure() {
89
+ this.failureCount++;
90
+ this.lastFailureTime = Date.now();
91
+ if (this.state === 'HALF_OPEN') {
92
+ // Probe failed → re-open
93
+ this.state = 'OPEN';
94
+ this.halfOpenInProgress = false;
95
+ }
96
+ else if (this.failureCount >= this.threshold) {
97
+ this.state = 'OPEN';
98
+ }
99
+ }
100
+ }
101
+ //# sourceMappingURL=circuit-breaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../src/circuit-breaker.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -11,6 +11,9 @@ declare const ConfigSchema: z.ZodObject<{
11
11
  maxRetries: z.ZodDefault<z.ZodNumber>;
12
12
  skipConnectionTest: z.ZodDefault<z.ZodBoolean>;
13
13
  maxMessageLength: z.ZodDefault<z.ZodNumber>;
14
+ sessionTtlMinutes: z.ZodDefault<z.ZodNumber>;
15
+ maxSessions: z.ZodDefault<z.ZodNumber>;
16
+ fallbackEnabled: z.ZodDefault<z.ZodBoolean>;
14
17
  }, "strip", z.ZodTypeAny, {
15
18
  apiKey: string;
16
19
  baseUrl: string;
@@ -19,6 +22,9 @@ declare const ConfigSchema: z.ZodObject<{
19
22
  maxRetries: number;
20
23
  skipConnectionTest: boolean;
21
24
  maxMessageLength: number;
25
+ sessionTtlMinutes: number;
26
+ maxSessions: number;
27
+ fallbackEnabled: boolean;
22
28
  }, {
23
29
  apiKey: string;
24
30
  baseUrl?: string | undefined;
@@ -27,6 +33,9 @@ declare const ConfigSchema: z.ZodObject<{
27
33
  maxRetries?: number | undefined;
28
34
  skipConnectionTest?: boolean | undefined;
29
35
  maxMessageLength?: number | undefined;
36
+ sessionTtlMinutes?: number | undefined;
37
+ maxSessions?: number | undefined;
38
+ fallbackEnabled?: boolean | undefined;
30
39
  }>;
31
40
  export type Config = z.infer<typeof ConfigSchema>;
32
41
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;EAQhB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAIlD;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAqCnC;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAKlC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWhB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAIlD;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,CA4CnC;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAKlC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC"}
package/dist/config.js CHANGED
@@ -12,6 +12,9 @@ const ConfigSchema = z.object({
12
12
  maxRetries: z.number().min(0).max(10).default(2),
13
13
  skipConnectionTest: z.boolean().default(false),
14
14
  maxMessageLength: z.number().positive().default(100_000),
15
+ sessionTtlMinutes: z.number().positive().default(30),
16
+ maxSessions: z.number().positive().default(100),
17
+ fallbackEnabled: z.boolean().default(true),
15
18
  });
16
19
  let cachedConfig = null;
17
20
  /**
@@ -34,6 +37,13 @@ export function loadConfig() {
34
37
  maxMessageLength: process.env.MAX_MESSAGE_LENGTH
35
38
  ? parseInt(process.env.MAX_MESSAGE_LENGTH, 10)
36
39
  : 100_000,
40
+ sessionTtlMinutes: process.env.SESSION_TTL_MINUTES
41
+ ? parseInt(process.env.SESSION_TTL_MINUTES, 10)
42
+ : 30,
43
+ maxSessions: process.env.MAX_SESSIONS
44
+ ? parseInt(process.env.MAX_SESSIONS, 10)
45
+ : 100,
46
+ fallbackEnabled: process.env.FALLBACK_ENABLED !== 'false',
37
47
  };
38
48
  const result = ConfigSchema.safeParse(raw);
39
49
  if (!result.success) {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,8BAA8B,CAAC;IACzD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,0BAA0B,CAAC;IAC7D,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACvC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACpD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAChD,kBAAkB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IAC9C,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;CACzD,CAAC,CAAC;AAIH,IAAI,YAAY,GAAkB,IAAI,CAAC;AAEvC;;;;GAIG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,GAAG,GAAG;QACV,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE;QAC1C,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,0BAA0B;QACpE,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,OAAO;QACpD,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe;YACzC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,EAAE,CAAC;YAC3C,CAAC,CAAC,KAAK;QACT,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW;YACjC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;YACvC,CAAC,CAAC,CAAC;QACL,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,MAAM;QAC/D,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;YAC9C,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,EAAE,CAAC;YAC9C,CAAC,CAAC,OAAO;KACZ,CAAC;IAEF,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAE3C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACjD,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;YAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC,CAAC;QAEJ,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM;YACtB,CAAC,CAAC,oFAAoF;YACtF,CAAC,CAAC,EAAE,CAAC;QAEP,MAAM,IAAI,WAAW,CACnB,kCAAkC,IAAI,EAAE,EACxC,MAAM,CACP,CAAC;IACJ,CAAC;IAED,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC;IAC3B,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW;IACzB,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/cost.d.ts CHANGED
@@ -1,24 +1,41 @@
1
1
  /**
2
2
  * Cost Calculation Module
3
3
  * Handles pricing and cost formatting for DeepSeek API requests
4
+ *
5
+ * DeepSeek V3.2 unified pricing (both deepseek-chat and deepseek-reasoner):
6
+ * - Cache hit input: $0.028/1M tokens
7
+ * - Cache miss input: $0.28/1M tokens
8
+ * - Output: $0.42/1M tokens
4
9
  */
5
- /** DeepSeek pricing per 1M tokens (USD) */
10
+ /** DeepSeek V3.2 unified pricing per 1M tokens (USD) */
6
11
  export declare const PRICING: {
7
- readonly 'deepseek-chat': {
8
- readonly prompt: 0.14;
9
- readonly completion: 0.28;
10
- };
11
- readonly 'deepseek-reasoner': {
12
- readonly prompt: 0.55;
13
- readonly completion: 2.19;
14
- };
12
+ readonly cache_hit: 0.028;
13
+ readonly cache_miss: 0.28;
14
+ readonly output: 0.42;
15
15
  };
16
16
  /**
17
- * Calculate cost for a request based on token usage
17
+ * Cost breakdown for a request
18
18
  */
19
- export declare function calculateCost(promptTokens: number, completionTokens: number, model: string): number;
19
+ export interface CostBreakdown {
20
+ inputCost: number;
21
+ outputCost: number;
22
+ totalCost: number;
23
+ cacheHitRatio?: number;
24
+ cacheSavings?: number;
25
+ }
20
26
  /**
21
- * Format cost as readable USD string
27
+ * Calculate cost for a request based on token usage.
28
+ * Supports V3.2 cache hit/miss pricing. If cache fields are absent,
29
+ * treats all input tokens as cache miss (backward compatible).
22
30
  */
23
- export declare function formatCost(cost: number): string;
31
+ export declare function calculateCost(usage: {
32
+ prompt_tokens: number;
33
+ completion_tokens: number;
34
+ prompt_cache_hit_tokens?: number;
35
+ prompt_cache_miss_tokens?: number;
36
+ }): CostBreakdown;
37
+ /**
38
+ * Format cost as readable USD string with optional cache savings info
39
+ */
40
+ export declare function formatCost(breakdown: CostBreakdown): string;
24
41
  //# sourceMappingURL=cost.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,2CAA2C;AAC3C,eAAO,MAAM,OAAO;;;;;;;;;CASV,CAAC;AAEX;;GAEG;AACH,wBAAgB,aAAa,CAC3B,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,MAAM,EACxB,KAAK,EAAE,MAAM,GACZ,MAAM,CASR;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/C"}
1
+ {"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,wDAAwD;AACxD,eAAO,MAAM,OAAO;;;;CAIV,CAAC;AAEX;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC,GAAG,aAAa,CA4ChB;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,aAAa,GAAG,MAAM,CAqB3D"}