Skip to content

Commit fdbfea4

Browse files
committed
feat: implement temperature support for settings.json
1 parent 285ae56 commit fdbfea4

8 files changed

Lines changed: 67 additions & 6 deletions

File tree

docs/configuration.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Deep Code 使用 `settings.json` 设置文件进行持久化配置,支持两
3535
| `notify` | string | 任务完成通知脚本的完整路径(如 Slack 通知脚本) |
3636
| `webSearchTool` | string | 自定义联网搜索脚本的完整路径 |
3737
| `mcpServers` | object | MCP 服务器配置(键为服务名,值为 McpServerConfig 对象) |
38+
| `temperature` | number | 模型采样温度,范围 `0``2` |
3839

3940
#### `env` 子字段
4041

@@ -43,6 +44,7 @@ Deep Code 使用 `settings.json` 设置文件进行持久化配置,支持两
4344
| `MODEL` | string | 模型名称。例如 `"deepseek-v4-pro"``"deepseek-v4-flash"` |
4445
| `BASE_URL` | string | API 请求的基础 URL。例如 `"https://api.deepseek.com"` |
4546
| `API_KEY` | string | API 密钥 |
47+
| `TEMPERATURE` | string | Chat Completions 采样温度,范围 `"0"``"2"` |
4648
| `THINKING_ENABLED` | string | 是否启用思考模式 |
4749
| `REASONING_EFFORT` | string | 推理强度 |
4850
| `DEBUG_LOG_ENABLED` | string | 是否启用调试日志输出 |

docs/configuration_en.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ The following are all the top-level fields supported in `settings.json`, along w
3535
| `notify` | string | Full path to a task-completion notification script (e.g., Slack notification script) |
3636
| `webSearchTool` | string | Full path to a custom web search script |
3737
| `mcpServers` | object | MCP server configurations (keys are service names, values are McpServerConfig objects) |
38+
| `temperature` | number | Sampling temperature for LLM, from `0` to `2` |
3839

3940
#### `env` Sub-fields
4041

@@ -43,6 +44,7 @@ The following are all the top-level fields supported in `settings.json`, along w
4344
| `MODEL` | string | Model name, e.g. `"deepseek-v4-pro"`, `"deepseek-v4-flash"` |
4445
| `BASE_URL` | string | Base URL for API requests, e.g. `"https://api.deepseek.com"` |
4546
| `API_KEY` | string | API key |
47+
| `TEMPERATURE` | string | Sampling temperature for chat completions, from `"0"` to `"2"` |
4648
| `THINKING_ENABLED`| string | Enable thinking mode |
4749
| `REASONING_EFFORT`| string | Reasoning intensity |
4850
| `DEBUG_LOG_ENABLED`| string| Enable debug log output |
@@ -193,4 +195,4 @@ Applied in the following priority order (lower-numbered overridden by higher-num
193195
2. User-level settings.json: `{"env": {"MCP_GITHUB_PERSONAL_ACCESS_TOKEN": "..."}}`
194196
3. Project-level settings.json: `{"mcpServers":{"github":{"env":{"GITHUB_PERSONAL_ACCESS_TOKEN":"..."}}}}`
195197
4. Project-level settings.json: `{"env": {"MCP_GITHUB_PERSONAL_ACCESS_TOKEN": "..."}}`
196-
5. System environment variable: `DEEPCODE_MCP_GITHUB_PERSONAL_ACCESS_TOKEN=... deepcode`
198+
5. System environment variable: `DEEPCODE_MCP_GITHUB_PERSONAL_ACCESS_TOKEN=... deepcode`

src/common/openai-client.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export function createOpenAIClient(projectRoot: string = process.cwd()): {
2323
client: OpenAI | null;
2424
model: string;
2525
baseURL: string;
26+
temperature?: number;
2627
thinkingEnabled: boolean;
2728
reasoningEffort: "high" | "max";
2829
debugLogEnabled: boolean;
@@ -38,6 +39,7 @@ export function createOpenAIClient(projectRoot: string = process.cwd()): {
3839
client: null,
3940
model: settings.model,
4041
baseURL: settings.baseURL,
42+
temperature: settings.temperature,
4143
thinkingEnabled: settings.thinkingEnabled,
4244
reasoningEffort: settings.reasoningEffort,
4345
debugLogEnabled: settings.debugLogEnabled,
@@ -55,6 +57,7 @@ export function createOpenAIClient(projectRoot: string = process.cwd()): {
5557
client: cachedOpenAI,
5658
model: settings.model,
5759
baseURL: settings.baseURL,
60+
temperature: settings.temperature,
5861
thinkingEnabled: settings.thinkingEnabled,
5962
reasoningEffort: settings.reasoningEffort,
6063
debugLogEnabled: settings.debugLogEnabled,
@@ -91,6 +94,7 @@ export function createOpenAIClient(projectRoot: string = process.cwd()): {
9194
client: cachedOpenAI,
9295
model: settings.model,
9396
baseURL: settings.baseURL,
97+
temperature: settings.temperature,
9498
thinkingEnabled: settings.thinkingEnabled,
9599
reasoningEffort: settings.reasoningEffort,
96100
debugLogEnabled: settings.debugLogEnabled,

src/session.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,7 +1197,7 @@ ${skillMd}
11971197
permissionPrompt?: UserPromptContent
11981198
): Promise<void> {
11991199
const startedAt = Date.now();
1200-
const { client, model, baseURL, thinkingEnabled, reasoningEffort, debugLogEnabled, notify, env } =
1200+
const { client, model, baseURL, temperature, thinkingEnabled, reasoningEffort, debugLogEnabled, notify, env } =
12011201
this.createOpenAIClient();
12021202
const now = new Date().toISOString();
12031203
rebuildSessionStateFromHistory(sessionId, this.listSessionMessages(sessionId));
@@ -1300,6 +1300,7 @@ ${skillMd}
13001300
client,
13011301
{
13021302
model,
1303+
...(temperature !== undefined ? { temperature } : {}),
13031304
messages,
13041305
tools: getTools(this.getPromptToolOptions(), this.mcpToolDefinitions),
13051306
...thinkingOptions,
@@ -1310,7 +1311,7 @@ ${skillMd}
13101311
enabled: debugLogEnabled,
13111312
location: "SessionManager.activateSession",
13121313
baseURL,
1313-
params: { iteration, thinkingEnabled, reasoningEffort },
1314+
params: { iteration, temperature, thinkingEnabled, reasoningEffort },
13141315
}
13151316
);
13161317

@@ -1440,7 +1441,8 @@ ${skillMd}
14401441

14411442
async compactSession(sessionId: string, signal?: AbortSignal): Promise<void> {
14421443
this.throwIfAborted(signal);
1443-
const { client, model, baseURL, thinkingEnabled, reasoningEffort, debugLogEnabled } = this.createOpenAIClient();
1444+
const { client, model, baseURL, temperature, thinkingEnabled, reasoningEffort, debugLogEnabled } =
1445+
this.createOpenAIClient();
14441446
if (!client) {
14451447
return;
14461448
}
@@ -1472,6 +1474,7 @@ ${skillMd}
14721474
client,
14731475
{
14741476
model,
1477+
...(temperature !== undefined ? { temperature } : {}),
14751478
messages: [{ role: "user", content: compactPrompt }],
14761479
...thinkingOptions,
14771480
},
@@ -1481,7 +1484,7 @@ ${skillMd}
14811484
enabled: debugLogEnabled,
14821485
location: "SessionManager.compactSession",
14831486
baseURL,
1484-
params: { thinkingEnabled, reasoningEffort },
1487+
params: { temperature, thinkingEnabled, reasoningEffort },
14851488
}
14861489
);
14871490
this.throwIfAborted(signal);

src/settings.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export type DeepcodingEnv = Record<string, string | undefined> & {
77
MODEL?: string;
88
BASE_URL?: string;
99
API_KEY?: string;
10+
TEMPERATURE?: string;
1011
THINKING_ENABLED?: string;
1112
REASONING_EFFORT?: string;
1213
DEBUG_LOG_ENABLED?: string;
@@ -45,6 +46,7 @@ export type PermissionSettings = {
4546
export type DeepcodingSettings = {
4647
env?: DeepcodingEnv;
4748
model?: string;
49+
temperature?: number;
4850
thinkingEnabled?: boolean;
4951
reasoningEffort?: ReasoningEffort;
5052
debugLogEnabled?: boolean;
@@ -60,6 +62,7 @@ export type ResolvedDeepcodingSettings = {
6062
apiKey?: string;
6163
baseURL: string;
6264
model: string;
65+
temperature?: number;
6366
thinkingEnabled: boolean;
6467
reasoningEffort: ReasoningEffort;
6568
debugLogEnabled: boolean;
@@ -100,6 +103,14 @@ function parseBoolean(value: unknown): boolean | undefined {
100103
return undefined;
101104
}
102105

106+
function parseTemperature(value: unknown): number | undefined {
107+
const raw = typeof value === "number" ? value : typeof value === "string" && value.trim() ? Number(value) : NaN;
108+
if (!Number.isFinite(raw) || raw < 0 || raw > 2) {
109+
return undefined;
110+
}
111+
return raw;
112+
}
113+
103114
function trimString(value: unknown): string {
104115
return typeof value === "string" ? value.trim() : "";
105116
}
@@ -308,6 +319,13 @@ export function resolveSettingsSources(
308319
resolveReasoningEffort(userEnv.REASONING_EFFORT) ??
309320
"max";
310321

322+
const temperature =
323+
parseTemperature(systemEnv.TEMPERATURE) ??
324+
parseTemperature(projectSettings?.temperature) ??
325+
parseTemperature(projectEnv.TEMPERATURE) ??
326+
parseTemperature(userSettings?.temperature) ??
327+
parseTemperature(userEnv.TEMPERATURE);
328+
311329
const debugLogEnabled =
312330
parseBoolean(systemEnv.DEBUG_LOG_ENABLED) ??
313331
parseBoolean(projectSettings?.debugLogEnabled) ??
@@ -337,6 +355,7 @@ export function resolveSettingsSources(
337355
apiKey: trimString(env.API_KEY) || undefined,
338356
baseURL: trimString(env.BASE_URL) || defaults.baseURL,
339357
model,
358+
temperature,
340359
thinkingEnabled,
341360
reasoningEffort,
342361
debugLogEnabled,

src/tests/session.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2759,6 +2759,7 @@ test("SessionManager streams chat completions and counts reasoning progress", as
27592759
create: async (request: Record<string, unknown>) => {
27602760
assert.equal(request.stream, true);
27612761
assert.deepEqual(request.stream_options, { include_usage: true });
2762+
assert.equal(request.temperature, 0.25);
27622763
return createChatStreamResponse([
27632764
{ choices: [{ delta: { reasoning_content: "思考" } }] },
27642765
{ choices: [{ delta: { content: "hello" } }] },
@@ -2782,6 +2783,7 @@ test("SessionManager streams chat completions and counts reasoning progress", as
27822783
client: client as any,
27832784
model: "test-model",
27842785
baseURL: "https://api.deepseek.com",
2786+
temperature: 0.25,
27852787
thinkingEnabled: false,
27862788
}),
27872789
getResolvedSettings: () => ({ model: "test-model" }),

src/tests/settings-and-notify.test.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ test("resolveSettings reads top-level thinkingEnabled, notify, and webSearchTool
1919
BASE_URL: "https://example.com/v1",
2020
API_KEY: "sk-test",
2121
},
22+
temperature: 0.3,
2223
thinkingEnabled: true,
2324
reasoningEffort: "high",
2425
debugLogEnabled: true,
@@ -35,6 +36,7 @@ test("resolveSettings reads top-level thinkingEnabled, notify, and webSearchTool
3536
assert.equal(resolved.model, "deepseek-v3.2");
3637
assert.equal(resolved.baseURL, "https://example.com/v1");
3738
assert.equal(resolved.apiKey, "sk-test");
39+
assert.equal(resolved.temperature, 0.3);
3840
assert.equal(resolved.thinkingEnabled, true);
3941
assert.equal(resolved.reasoningEffort, "high");
4042
assert.equal(resolved.debugLogEnabled, true);
@@ -60,10 +62,11 @@ test("resolveSettings gives top-level model priority over env MODEL", () => {
6062
assert.equal(resolved.model, "deepseek-v4-flash");
6163
});
6264

63-
test("resolveSettings reads THINKING_ENABLED, REASONING_EFFORT, and DEBUG_LOG_ENABLED from env", () => {
65+
test("resolveSettings reads TEMPERATURE, THINKING_ENABLED, REASONING_EFFORT, and DEBUG_LOG_ENABLED from env", () => {
6466
const resolved = resolveSettings(
6567
{
6668
env: {
69+
TEMPERATURE: "0.7",
6770
THINKING_ENABLED: "true",
6871
REASONING_EFFORT: "high",
6972
DEBUG_LOG_ENABLED: "true",
@@ -77,6 +80,7 @@ test("resolveSettings reads THINKING_ENABLED, REASONING_EFFORT, and DEBUG_LOG_EN
7780
);
7881

7982
assert.equal(resolved.thinkingEnabled, true);
83+
assert.equal(resolved.temperature, 0.7);
8084
assert.equal(resolved.reasoningEffort, "high");
8185
assert.equal(resolved.debugLogEnabled, true);
8286
assert.equal(resolved.model, "default-model");
@@ -138,12 +142,14 @@ test("resolveSettingsSources applies user, project, and DEEPCODE environment pre
138142
MODEL: "user-env-model",
139143
THINKING_ENABLED: "false",
140144
REASONING_EFFORT: "high",
145+
TEMPERATURE: "0.2",
141146
DEBUG_LOG_ENABLED: "false",
142147
WEBHOOK: "user-webhook",
143148
},
144149
model: "user-top-model",
145150
thinkingEnabled: true,
146151
reasoningEffort: "max",
152+
temperature: 0.4,
147153
debugLogEnabled: true,
148154
telemetryEnabled: false,
149155
},
@@ -153,9 +159,11 @@ test("resolveSettingsSources applies user, project, and DEEPCODE environment pre
153159
MODEL: "project-env-model",
154160
THINKING_ENABLED: "false",
155161
DEBUG_LOG_ENABLED: "false",
162+
TEMPERATURE: "0.6",
156163
},
157164
model: "project-top-model",
158165
thinkingEnabled: true,
166+
temperature: 0.8,
159167
telemetryEnabled: true,
160168
},
161169
{
@@ -166,6 +174,7 @@ test("resolveSettingsSources applies user, project, and DEEPCODE environment pre
166174
DEEPCODE_MODEL: "system-model",
167175
DEEPCODE_THINKING_ENABLED: "false",
168176
DEEPCODE_REASONING_EFFORT: "high",
177+
DEEPCODE_TEMPERATURE: "1.2",
169178
DEEPCODE_DEBUG_LOG_ENABLED: "true",
170179
DEEPCODE_TELEMETRY_ENABLED: "false",
171180
DEEPCODE_WEBHOOK: "system-webhook",
@@ -176,6 +185,7 @@ test("resolveSettingsSources applies user, project, and DEEPCODE environment pre
176185
assert.equal(resolved.apiKey, "project-key");
177186
assert.equal(resolved.thinkingEnabled, false);
178187
assert.equal(resolved.reasoningEffort, "high");
188+
assert.equal(resolved.temperature, 1.2);
179189
assert.equal(resolved.debugLogEnabled, true);
180190
assert.equal(resolved.telemetryEnabled, false);
181191
assert.equal(resolved.env.WEBHOOK, "system-webhook");
@@ -341,6 +351,24 @@ test("resolveSettings defaults invalid reasoning effort to max", () => {
341351
assert.equal(resolved.reasoningEffort, "max");
342352
});
343353

354+
test("resolveSettings ignores invalid temperature values", () => {
355+
const resolved = resolveSettings(
356+
{
357+
env: {
358+
TEMPERATURE: "hot",
359+
},
360+
temperature: 3,
361+
},
362+
{
363+
model: "default-model",
364+
baseURL: "https://default.example.com",
365+
},
366+
TEST_PROCESS_ENV
367+
);
368+
369+
assert.equal(resolved.temperature, undefined);
370+
});
371+
344372
test("applyModelConfigSelection writes model only when the effective model changes or already exists", () => {
345373
const result = applyModelConfigSelection(
346374
{

src/tools/executor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export type CreateOpenAIClient = () => {
1313
client: OpenAI | null;
1414
model: string;
1515
baseURL?: string;
16+
temperature?: number;
1617
thinkingEnabled: boolean;
1718
reasoningEffort?: ReasoningEffort;
1819
debugLogEnabled?: boolean;

0 commit comments

Comments
 (0)