@arikusi/deepseek-mcp-server 1.0.3 → 1.1.1

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 (59) hide show
  1. package/CHANGELOG.md +68 -1
  2. package/README.md +120 -23
  3. package/dist/config.d.ts +48 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +68 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/cost.d.ts +24 -0
  8. package/dist/cost.d.ts.map +1 -0
  9. package/dist/cost.js +34 -0
  10. package/dist/cost.js.map +1 -0
  11. package/dist/deepseek-client.d.ts +10 -3
  12. package/dist/deepseek-client.d.ts.map +1 -1
  13. package/dist/deepseek-client.js +99 -37
  14. package/dist/deepseek-client.js.map +1 -1
  15. package/dist/errors.d.ts +71 -0
  16. package/dist/errors.d.ts.map +1 -0
  17. package/dist/errors.js +74 -0
  18. package/dist/errors.js.map +1 -0
  19. package/dist/index.d.ts +0 -3
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +35 -505
  22. package/dist/index.js.map +1 -1
  23. package/dist/prompts/advanced.d.ts +8 -0
  24. package/dist/prompts/advanced.d.ts.map +1 -0
  25. package/dist/prompts/advanced.js +187 -0
  26. package/dist/prompts/advanced.js.map +1 -0
  27. package/dist/prompts/core.d.ts +8 -0
  28. package/dist/prompts/core.d.ts.map +1 -0
  29. package/dist/prompts/core.js +188 -0
  30. package/dist/prompts/core.js.map +1 -0
  31. package/dist/prompts/function-calling.d.ts +7 -0
  32. package/dist/prompts/function-calling.d.ts.map +1 -0
  33. package/dist/prompts/function-calling.js +87 -0
  34. package/dist/prompts/function-calling.js.map +1 -0
  35. package/dist/prompts/index.d.ts +7 -0
  36. package/dist/prompts/index.d.ts.map +1 -0
  37. package/dist/prompts/index.js +13 -0
  38. package/dist/prompts/index.js.map +1 -0
  39. package/dist/schemas.d.ts +258 -0
  40. package/dist/schemas.d.ts.map +1 -0
  41. package/dist/schemas.js +56 -0
  42. package/dist/schemas.js.map +1 -0
  43. package/dist/server.d.ts +9 -0
  44. package/dist/server.d.ts.map +1 -0
  45. package/dist/server.js +16 -0
  46. package/dist/server.js.map +1 -0
  47. package/dist/tools/deepseek-chat.d.ts +8 -0
  48. package/dist/tools/deepseek-chat.d.ts.map +1 -0
  49. package/dist/tools/deepseek-chat.js +162 -0
  50. package/dist/tools/deepseek-chat.js.map +1 -0
  51. package/dist/tools/index.d.ts +8 -0
  52. package/dist/tools/index.d.ts.map +1 -0
  53. package/dist/tools/index.js +9 -0
  54. package/dist/tools/index.js.map +1 -0
  55. package/dist/types.d.ts +135 -1
  56. package/dist/types.d.ts.map +1 -1
  57. package/dist/types.js +20 -1
  58. package/dist/types.js.map +1 -1
  59. package/package.json +10 -4
package/CHANGELOG.md CHANGED
@@ -16,6 +16,69 @@ 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.1.1] - 2026-02-11
20
+
21
+ ### Added
22
+ - **Custom Error Classes** (`src/errors.ts`): `BaseError`, `ConfigError`, `ApiError`, `RateLimitError`, `AuthenticationError`, `ValidationError`, `ConnectionError` with error cause chaining
23
+ - **DeepSeek Type Extensions** (`src/types.ts`): `DeepSeekRawResponse`, `DeepSeekStreamChunk`, `DeepSeekStreamDelta` types and `hasReasoningContent()`, `getErrorMessage()` type guards
24
+ - **Message Content Length Limit**: `MAX_MESSAGE_LENGTH` config (default: 100K chars) prevents excessive API costs
25
+ - **Optional Connection Test**: `SKIP_CONNECTION_TEST=true` env skips startup API call for faster boot
26
+ - **AI Discoverability**: `llms.txt` and `llms-full.txt` for LLM/AI agent consumption
27
+ - **New Tests**: 126 tests (up from 85) covering errors, server factory, tool handlers, prompt registration
28
+
29
+ ### Changed
30
+ - **Modular Architecture**: Monolithic `index.ts` (783 lines) split into focused modules:
31
+ - `src/server.ts`: McpServer factory with auto-version from package.json
32
+ - `src/tools/deepseek-chat.ts`: Tool handler (extracted from index.ts)
33
+ - `src/tools/index.ts`: Tool registration aggregator
34
+ - `src/prompts/core.ts`: 5 core reasoning prompts
35
+ - `src/prompts/advanced.ts`: 5 advanced prompts
36
+ - `src/prompts/function-calling.ts`: 2 function calling prompts
37
+ - `src/prompts/index.ts`: Prompt registration aggregator
38
+ - `src/index.ts`: Slim bootstrap (~80 lines)
39
+ - **DRY Refactoring** (`deepseek-client.ts`): Extracted `buildRequestParams()` and `wrapError()` methods (eliminated code duplication)
40
+ - **Type Safety**: Replaced 16 `any` casts with proper DeepSeek type extensions and type guards (`error: unknown` pattern)
41
+ - **Config**: `process.exit(1)` replaced with `throw ConfigError` for testability
42
+ - **Version**: Single source of truth from `package.json` via `createRequire` (no more manual sync)
43
+
44
+ ### Fixed
45
+ - **Security**: Updated `@modelcontextprotocol/sdk` to fix cross-client data leak (GHSA-345p-7cg4-v4c7)
46
+ - **Security**: Fixed `hono` transitive dependency vulnerabilities (XSS, cache deception, IP spoofing)
47
+ - CI dist check updated for new file structure
48
+
49
+ ## [1.1.0] - 2026-02-10
50
+
51
+ ### Added
52
+ - **Function Calling Support**: Full OpenAI-compatible function calling via `tools` and `tool_choice` parameters
53
+ - Define up to 128 tool definitions with JSON Schema parameters
54
+ - Control tool behavior with `tool_choice`: auto, none, required, or specific function
55
+ - Tool call results formatted in response with call IDs and arguments
56
+ - Streaming + function calling works together (delta accumulation)
57
+ - `tool` message role for sending tool results back
58
+ - **Centralized Config System** (`src/config.ts`)
59
+ - Zod-validated configuration from environment variables
60
+ - `DEEPSEEK_BASE_URL`: Custom API endpoint (default: `https://api.deepseek.com`)
61
+ - `SHOW_COST_INFO`: Toggle cost display in responses (default: true)
62
+ - `REQUEST_TIMEOUT`: API request timeout in ms (default: 60000)
63
+ - `MAX_RETRIES`: Maximum API retry count (default: 2)
64
+ - **Test Suite**: 85 tests with Vitest
65
+ - Config, Cost, Schemas, Client, and Function Calling tests
66
+ - 80%+ code coverage with v8 provider
67
+ - `npm test`, `npm run test:watch`, `npm run test:coverage` scripts
68
+ - **2 New Prompt Templates** (total: 12)
69
+ - `function_call_debug`: Debug function calling issues
70
+ - `create_function_schema`: Generate JSON Schema from natural language
71
+ - CI coverage job in GitHub Actions
72
+
73
+ ### Changed
74
+ - **Project Structure**: Modularized codebase
75
+ - `src/config.ts`: Centralized configuration
76
+ - `src/cost.ts`: Cost calculation (extracted from index.ts)
77
+ - `src/schemas.ts`: Zod validation schemas (extracted from index.ts)
78
+ - `DeepSeekClient` constructor now uses centralized config (no manual apiKey passing)
79
+ - Server version bumped to 1.1.0
80
+ - Updated `deepseek_chat` tool description to mention function calling
81
+
19
82
  ## [1.0.3] - 2025-02-07
20
83
 
21
84
  ### Added
@@ -91,6 +154,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
91
154
 
92
155
  ## Version History
93
156
 
157
+ - **1.1.1** (2026-02-11): Modular architecture, type safety, security fixes, 126 tests
158
+ - **1.1.0** (2026-02-10): Function calling, config system, test suite
94
159
  - **1.0.3** (2025-02-07): Cost tracking and prompt templates
95
160
  - **1.0.0** (2025-01-13): Initial public release
96
161
  - **0.1.0** (Development): Internal development version
@@ -101,7 +166,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
101
166
  - [GitHub repository](https://github.com/arikusi/deepseek-mcp-server)
102
167
  - [Issue tracker](https://github.com/arikusi/deepseek-mcp-server/issues)
103
168
 
104
- [Unreleased]: https://github.com/arikusi/deepseek-mcp-server/compare/v1.0.3...HEAD
169
+ [Unreleased]: https://github.com/arikusi/deepseek-mcp-server/compare/v1.1.1...HEAD
170
+ [1.1.1]: https://github.com/arikusi/deepseek-mcp-server/compare/v1.1.0...v1.1.1
171
+ [1.1.0]: https://github.com/arikusi/deepseek-mcp-server/compare/v1.0.3...v1.1.0
105
172
  [1.0.3]: https://github.com/arikusi/deepseek-mcp-server/releases/tag/v1.0.3
106
173
  [1.0.0]: https://github.com/arikusi/deepseek-mcp-server/releases/tag/v1.0.0
107
174
  [0.1.0]: https://github.com/arikusi/deepseek-mcp-server/releases/tag/v0.1.0
package/README.md CHANGED
@@ -14,9 +14,9 @@ A Model Context Protocol (MCP) server that integrates DeepSeek AI models with MC
14
14
  - Gemini CLI (if MCP support is available)
15
15
  - Any MCP-compatible client
16
16
 
17
- > **⚠️ Note**: This is an unofficial community project and is not affiliated with DeepSeek.
17
+ > **Note**: This is an unofficial community project and is not affiliated with DeepSeek.
18
18
 
19
- ## Quick Start
19
+ ## Quick Start
20
20
 
21
21
  ### For Claude Code
22
22
 
@@ -42,19 +42,22 @@ gemini mcp add deepseek npx @arikusi/deepseek-mcp-server -e DEEPSEEK_API_KEY=you
42
42
 
43
43
  **Get your API key:** [https://platform.deepseek.com](https://platform.deepseek.com)
44
44
 
45
- That's it! Your MCP client can now use DeepSeek models! 🎉
45
+ That's it! Your MCP client can now use DeepSeek models!
46
46
 
47
47
  ---
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
53
- - 💰 **Cost Tracking**: Automatic cost calculation for every request (USD)
54
- - 📋 **10 Prompt Templates**: Pre-built templates for debugging, code review, research, and more
55
- - 🔄 **Streaming Support**: Real-time response generation
56
- - 🛡️ **Type-Safe**: Full TypeScript implementation
57
- - 🎯 **MCP Compatible**: Works with any MCP-compatible CLI (Claude Code, Gemini CLI, etc.)
51
+ - **DeepSeek Chat**: Fast and capable general-purpose model
52
+ - **DeepSeek Reasoner (R1)**: Advanced reasoning with chain-of-thought explanations
53
+ - **Function Calling**: OpenAI-compatible tool use with up to 128 tool definitions
54
+ - **Cost Tracking**: Automatic cost calculation for every request (USD)
55
+ - **Configurable**: Environment-based configuration with validation
56
+ - **12 Prompt Templates**: Pre-built templates for debugging, code review, function calling, and more
57
+ - **Streaming Support**: Real-time response generation
58
+ - **Tested**: 126 tests with 90%+ code coverage
59
+ - **Type-Safe**: Full TypeScript implementation
60
+ - **MCP Compatible**: Works with any MCP-compatible CLI (Claude Code, Gemini CLI, etc.)
58
61
 
59
62
  ## Installation
60
63
 
@@ -130,22 +133,26 @@ If your MCP client doesn't support the `add` command, manually add to your confi
130
133
 
131
134
  ### `deepseek_chat`
132
135
 
133
- Chat with DeepSeek AI models with automatic cost tracking.
136
+ Chat with DeepSeek AI models with automatic cost tracking and function calling support.
134
137
 
135
138
  **Parameters:**
136
139
 
137
140
  - `messages` (required): Array of conversation messages
138
- - `role`: "system" | "user" | "assistant"
141
+ - `role`: "system" | "user" | "assistant" | "tool"
139
142
  - `content`: Message text
143
+ - `tool_call_id` (optional): Required for tool role messages
140
144
  - `model` (optional): "deepseek-chat" (default) or "deepseek-reasoner"
141
145
  - `temperature` (optional): 0-2, controls randomness (default: 1.0)
142
146
  - `max_tokens` (optional): Maximum tokens to generate
143
147
  - `stream` (optional): Enable streaming mode (default: false)
148
+ - `tools` (optional): Array of tool definitions for function calling (max 128)
149
+ - `tool_choice` (optional): "auto" | "none" | "required" | `{type: "function", function: {name: "..."}}`
144
150
 
145
151
  **Response includes:**
146
152
  - Content with formatting
153
+ - Function call results (if tools were used)
147
154
  - Request information (tokens, model, cost in USD)
148
- - Structured data with `cost_usd` field
155
+ - Structured data with `cost_usd` and `tool_calls` fields
149
156
 
150
157
  **Example:**
151
158
 
@@ -179,9 +186,44 @@ Chat with DeepSeek AI models with automatic cost tracking.
179
186
 
180
187
  The reasoner model will show its thinking process in `<thinking>` tags followed by the final answer.
181
188
 
189
+ **Function Calling Example:**
190
+
191
+ ```json
192
+ {
193
+ "messages": [
194
+ {
195
+ "role": "user",
196
+ "content": "What's the weather in Istanbul?"
197
+ }
198
+ ],
199
+ "tools": [
200
+ {
201
+ "type": "function",
202
+ "function": {
203
+ "name": "get_weather",
204
+ "description": "Get current weather for a location",
205
+ "parameters": {
206
+ "type": "object",
207
+ "properties": {
208
+ "location": {
209
+ "type": "string",
210
+ "description": "City name"
211
+ }
212
+ },
213
+ "required": ["location"]
214
+ }
215
+ }
216
+ }
217
+ ],
218
+ "tool_choice": "auto"
219
+ }
220
+ ```
221
+
222
+ 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
+
182
224
  ## Available Prompts
183
225
 
184
- Pre-built prompt templates for common tasks:
226
+ Pre-built prompt templates for common tasks (12 total):
185
227
 
186
228
  ### Core Reasoning
187
229
  - **debug_with_reasoning**: Debug code with step-by-step analysis
@@ -197,6 +239,10 @@ Pre-built prompt templates for common tasks:
197
239
  - **cost_comparison**: Compare LLM costs for tasks
198
240
  - **pair_programming**: Interactive coding with explanations
199
241
 
242
+ ### Function Calling
243
+ - **function_call_debug**: Debug function calling issues with tool definitions and messages
244
+ - **create_function_schema**: Generate JSON Schema for function calling from natural language
245
+
200
246
  Each prompt is optimized for the DeepSeek Reasoner model to provide detailed reasoning.
201
247
 
202
248
  ## Models
@@ -216,6 +262,28 @@ Each prompt is optimized for the DeepSeek Reasoner model to provide detailed rea
216
262
  - **Special**: Provides chain-of-thought reasoning
217
263
  - **Output**: Both reasoning process and final answer
218
264
 
265
+ ## Configuration
266
+
267
+ The server is configured via environment variables. All settings except `DEEPSEEK_API_KEY` are optional.
268
+
269
+ | Variable | Default | Description |
270
+ |----------|---------|-------------|
271
+ | `DEEPSEEK_API_KEY` | (required) | Your DeepSeek API key |
272
+ | `DEEPSEEK_BASE_URL` | `https://api.deepseek.com` | Custom API endpoint |
273
+ | `SHOW_COST_INFO` | `true` | Show cost info in responses |
274
+ | `REQUEST_TIMEOUT` | `60000` | Request timeout in milliseconds |
275
+ | `MAX_RETRIES` | `2` | Maximum retry count for failed requests |
276
+ | `SKIP_CONNECTION_TEST` | `false` | Skip startup API connection test |
277
+ | `MAX_MESSAGE_LENGTH` | `100000` | Maximum message content length (characters) |
278
+
279
+ **Example with custom config:**
280
+ ```bash
281
+ claude mcp add -s user deepseek npx @arikusi/deepseek-mcp-server \
282
+ -e DEEPSEEK_API_KEY=your-key \
283
+ -e SHOW_COST_INFO=false \
284
+ -e REQUEST_TIMEOUT=30000
285
+ ```
286
+
219
287
  ## Development
220
288
 
221
289
  ### Project Structure
@@ -223,10 +291,26 @@ Each prompt is optimized for the DeepSeek Reasoner model to provide detailed rea
223
291
  ```
224
292
  deepseek-mcp-server/
225
293
  ├── src/
226
- │ ├── index.ts # Main MCP server
227
- │ ├── deepseek-client.ts # DeepSeek API wrapper
228
- └── types.ts # TypeScript definitions
229
- ├── dist/ # Compiled JavaScript
294
+ │ ├── index.ts # Entry point, bootstrap (~80 lines)
295
+ │ ├── server.ts # McpServer factory (auto-version)
296
+ ├── deepseek-client.ts # DeepSeek API wrapper (OpenAI SDK)
297
+ ├── config.ts # Centralized config with Zod validation
298
+ │ ├── cost.ts # Cost calculation and formatting
299
+ │ ├── schemas.ts # Zod input validation schemas
300
+ │ ├── types.ts # TypeScript types + type guards
301
+ │ ├── errors.ts # Custom error classes
302
+ │ ├── tools/
303
+ │ │ ├── deepseek-chat.ts # deepseek_chat tool handler
304
+ │ │ └── index.ts # Tool registration aggregator
305
+ │ └── prompts/
306
+ │ ├── core.ts # 5 core reasoning prompts
307
+ │ ├── advanced.ts # 5 advanced prompts
308
+ │ ├── function-calling.ts # 2 function calling prompts
309
+ │ └── index.ts # Prompt registration aggregator
310
+ ├── dist/ # Compiled JavaScript
311
+ ├── llms.txt # AI discoverability index
312
+ ├── llms-full.txt # Full docs for LLM context
313
+ ├── vitest.config.ts # Test configuration
230
314
  ├── package.json
231
315
  ├── tsconfig.json
232
316
  └── README.md
@@ -244,6 +328,19 @@ npm run build
244
328
  npm run watch
245
329
  ```
246
330
 
331
+ ### Testing
332
+
333
+ ```bash
334
+ # Run all tests
335
+ npm test
336
+
337
+ # Watch mode
338
+ npm run test:watch
339
+
340
+ # With coverage report
341
+ npm run test:coverage
342
+ ```
343
+
247
344
  ### Testing Locally
248
345
 
249
346
  ```bash
@@ -357,10 +454,10 @@ MIT License - see [LICENSE](LICENSE) file for details
357
454
 
358
455
  ## Support
359
456
 
360
- - 📖 [Documentation](https://github.com/arikusi/deepseek-mcp-server#readme)
361
- - 🐛 [Bug Reports](https://github.com/arikusi/deepseek-mcp-server/issues)
362
- - 💬 [Discussions](https://github.com/arikusi/deepseek-mcp-server/discussions)
363
- - 📧 Contact: [GitHub Issues](https://github.com/arikusi/deepseek-mcp-server/issues)
457
+ - [Documentation](https://github.com/arikusi/deepseek-mcp-server#readme)
458
+ - [Bug Reports](https://github.com/arikusi/deepseek-mcp-server/issues)
459
+ - [Discussions](https://github.com/arikusi/deepseek-mcp-server/discussions)
460
+ - Contact: [GitHub Issues](https://github.com/arikusi/deepseek-mcp-server/issues)
364
461
 
365
462
  ## Resources
366
463
 
@@ -376,6 +473,6 @@ MIT License - see [LICENSE](LICENSE) file for details
376
473
 
377
474
  ---
378
475
 
379
- **Made with ❤️ by [@arikusi](https://github.com/arikusi)**
476
+ **Made by [@arikusi](https://github.com/arikusi)**
380
477
 
381
478
  This is an unofficial community project and is not affiliated with DeepSeek.
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Centralized Configuration
3
+ * Loads and validates configuration from environment variables
4
+ */
5
+ import { z } from 'zod';
6
+ declare const ConfigSchema: z.ZodObject<{
7
+ apiKey: z.ZodString;
8
+ baseUrl: z.ZodDefault<z.ZodString>;
9
+ showCostInfo: z.ZodDefault<z.ZodBoolean>;
10
+ requestTimeout: z.ZodDefault<z.ZodNumber>;
11
+ maxRetries: z.ZodDefault<z.ZodNumber>;
12
+ skipConnectionTest: z.ZodDefault<z.ZodBoolean>;
13
+ maxMessageLength: z.ZodDefault<z.ZodNumber>;
14
+ }, "strip", z.ZodTypeAny, {
15
+ apiKey: string;
16
+ baseUrl: string;
17
+ showCostInfo: boolean;
18
+ requestTimeout: number;
19
+ maxRetries: number;
20
+ skipConnectionTest: boolean;
21
+ maxMessageLength: number;
22
+ }, {
23
+ apiKey: string;
24
+ baseUrl?: string | undefined;
25
+ showCostInfo?: boolean | undefined;
26
+ requestTimeout?: number | undefined;
27
+ maxRetries?: number | undefined;
28
+ skipConnectionTest?: boolean | undefined;
29
+ maxMessageLength?: number | undefined;
30
+ }>;
31
+ export type Config = z.infer<typeof ConfigSchema>;
32
+ /**
33
+ * Load configuration from environment variables.
34
+ * Validates with Zod and caches the result.
35
+ * Throws ConfigError if validation fails.
36
+ */
37
+ export declare function loadConfig(): Config;
38
+ /**
39
+ * Get the cached configuration.
40
+ * Throws if loadConfig() hasn't been called yet.
41
+ */
42
+ export declare function getConfig(): Config;
43
+ /**
44
+ * Reset cached configuration (for testing).
45
+ */
46
+ export declare function resetConfig(): void;
47
+ export {};
48
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +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"}
package/dist/config.js ADDED
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Centralized Configuration
3
+ * Loads and validates configuration from environment variables
4
+ */
5
+ import { z } from 'zod';
6
+ import { ConfigError } from './errors.js';
7
+ const ConfigSchema = z.object({
8
+ apiKey: z.string().min(1, 'DEEPSEEK_API_KEY is required'),
9
+ baseUrl: z.string().url().default('https://api.deepseek.com'),
10
+ showCostInfo: z.boolean().default(true),
11
+ requestTimeout: z.number().positive().default(60000),
12
+ maxRetries: z.number().min(0).max(10).default(2),
13
+ skipConnectionTest: z.boolean().default(false),
14
+ maxMessageLength: z.number().positive().default(100_000),
15
+ });
16
+ let cachedConfig = null;
17
+ /**
18
+ * Load configuration from environment variables.
19
+ * Validates with Zod and caches the result.
20
+ * Throws ConfigError if validation fails.
21
+ */
22
+ export function loadConfig() {
23
+ const raw = {
24
+ apiKey: process.env.DEEPSEEK_API_KEY || '',
25
+ baseUrl: process.env.DEEPSEEK_BASE_URL || 'https://api.deepseek.com',
26
+ showCostInfo: process.env.SHOW_COST_INFO !== 'false',
27
+ requestTimeout: process.env.REQUEST_TIMEOUT
28
+ ? parseInt(process.env.REQUEST_TIMEOUT, 10)
29
+ : 60000,
30
+ maxRetries: process.env.MAX_RETRIES
31
+ ? parseInt(process.env.MAX_RETRIES, 10)
32
+ : 2,
33
+ skipConnectionTest: process.env.SKIP_CONNECTION_TEST === 'true',
34
+ maxMessageLength: process.env.MAX_MESSAGE_LENGTH
35
+ ? parseInt(process.env.MAX_MESSAGE_LENGTH, 10)
36
+ : 100_000,
37
+ };
38
+ const result = ConfigSchema.safeParse(raw);
39
+ if (!result.success) {
40
+ const issues = result.error.issues.map((issue) => ({
41
+ path: issue.path.join('.'),
42
+ message: issue.message,
43
+ }));
44
+ const hint = !raw.apiKey
45
+ ? '\nPlease set your DeepSeek API key:\n export DEEPSEEK_API_KEY="your-api-key-here"'
46
+ : '';
47
+ throw new ConfigError(`Configuration validation failed${hint}`, issues);
48
+ }
49
+ cachedConfig = result.data;
50
+ return cachedConfig;
51
+ }
52
+ /**
53
+ * Get the cached configuration.
54
+ * Throws if loadConfig() hasn't been called yet.
55
+ */
56
+ export function getConfig() {
57
+ if (!cachedConfig) {
58
+ throw new Error('Config not loaded. Call loadConfig() first.');
59
+ }
60
+ return cachedConfig;
61
+ }
62
+ /**
63
+ * Reset cached configuration (for testing).
64
+ */
65
+ export function resetConfig() {
66
+ cachedConfig = null;
67
+ }
68
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/cost.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Cost Calculation Module
3
+ * Handles pricing and cost formatting for DeepSeek API requests
4
+ */
5
+ /** DeepSeek pricing per 1M tokens (USD) */
6
+ 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
+ };
15
+ };
16
+ /**
17
+ * Calculate cost for a request based on token usage
18
+ */
19
+ export declare function calculateCost(promptTokens: number, completionTokens: number, model: string): number;
20
+ /**
21
+ * Format cost as readable USD string
22
+ */
23
+ export declare function formatCost(cost: number): string;
24
+ //# sourceMappingURL=cost.d.ts.map
@@ -0,0 +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"}
package/dist/cost.js ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Cost Calculation Module
3
+ * Handles pricing and cost formatting for DeepSeek API requests
4
+ */
5
+ /** DeepSeek pricing per 1M tokens (USD) */
6
+ export const PRICING = {
7
+ 'deepseek-chat': {
8
+ prompt: 0.14,
9
+ completion: 0.28,
10
+ },
11
+ 'deepseek-reasoner': {
12
+ prompt: 0.55,
13
+ completion: 2.19,
14
+ },
15
+ };
16
+ /**
17
+ * Calculate cost for a request based on token usage
18
+ */
19
+ export function calculateCost(promptTokens, completionTokens, model) {
20
+ const modelPricing = PRICING[model] || PRICING['deepseek-chat'];
21
+ const promptCost = (promptTokens / 1_000_000) * modelPricing.prompt;
22
+ const completionCost = (completionTokens / 1_000_000) * modelPricing.completion;
23
+ return promptCost + completionCost;
24
+ }
25
+ /**
26
+ * Format cost as readable USD string
27
+ */
28
+ export function formatCost(cost) {
29
+ if (cost < 0.01) {
30
+ return `$${cost.toFixed(4)}`;
31
+ }
32
+ return `$${cost.toFixed(2)}`;
33
+ }
34
+ //# sourceMappingURL=cost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost.js","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,2CAA2C;AAC3C,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,eAAe,EAAE;QACf,MAAM,EAAE,IAAI;QACZ,UAAU,EAAE,IAAI;KACjB;IACD,mBAAmB,EAAE;QACnB,MAAM,EAAE,IAAI;QACZ,UAAU,EAAE,IAAI;KACjB;CACO,CAAC;AAEX;;GAEG;AACH,MAAM,UAAU,aAAa,CAC3B,YAAoB,EACpB,gBAAwB,EACxB,KAAa;IAEb,MAAM,YAAY,GAChB,OAAO,CAAC,KAA6B,CAAC,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;IAErE,MAAM,UAAU,GAAG,CAAC,YAAY,GAAG,SAAS,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC;IACpE,MAAM,cAAc,GAClB,CAAC,gBAAgB,GAAG,SAAS,CAAC,GAAG,YAAY,CAAC,UAAU,CAAC;IAE3D,OAAO,UAAU,GAAG,cAAc,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC;QAChB,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/B,CAAC;IACD,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/B,CAAC"}
@@ -5,15 +5,22 @@
5
5
  import type { ChatCompletionParams, ChatCompletionResponse } from './types.js';
6
6
  export declare class DeepSeekClient {
7
7
  private client;
8
- private baseURL;
9
- constructor(apiKey: string);
8
+ constructor();
9
+ /**
10
+ * Build request params shared between streaming and non-streaming
11
+ */
12
+ private buildRequestParams;
13
+ /**
14
+ * Wrap caught errors with appropriate custom error class
15
+ */
16
+ private wrapError;
10
17
  /**
11
18
  * Create a chat completion (non-streaming)
12
19
  */
13
20
  createChatCompletion(params: ChatCompletionParams): Promise<ChatCompletionResponse>;
14
21
  /**
15
22
  * Create a streaming chat completion
16
- * Returns the full text after streaming completes
23
+ * Returns the full text after streaming completes (buffered)
17
24
  */
18
25
  createStreamingChatCompletion(params: ChatCompletionParams): Promise<ChatCompletionResponse>;
19
26
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"deepseek-client.d.ts","sourceRoot":"","sources":["../src/deepseek-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACV,oBAAoB,EACpB,sBAAsB,EAEvB,MAAM,YAAY,CAAC;AAEpB,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAA8B;gBAEjC,MAAM,EAAE,MAAM;IAW1B;;OAEG;IACG,oBAAoB,CACxB,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,sBAAsB,CAAC;IA4ClC;;;OAGG;IACG,6BAA6B,CACjC,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,sBAAsB,CAAC;IAsElC;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;CAazC"}
1
+ {"version":3,"file":"deepseek-client.d.ts","sourceRoot":"","sources":["../src/deepseek-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EACV,oBAAoB,EACpB,sBAAsB,EAKvB,MAAM,YAAY,CAAC;AAGpB,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAS;;IAavB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA2B1B;;OAEG;IACH,OAAO,CAAC,SAAS;IAOjB;;OAEG;IACG,oBAAoB,CACxB,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,sBAAsB,CAAC;IA6ClC;;;OAGG;IACG,6BAA6B,CACjC,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,sBAAsB,CAAC;IAoGlC;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;CAazC"}