svharness 0.14.11 → 0.14.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -580,6 +580,8 @@ convert-failures.json
580
580
 
581
581
  详细设计见 [`docs/agent-launcher-design.md`](docs/agent-launcher-design.md)。
582
582
 
583
+ **env 策略(单向,只写用户目录)**:可**读取**项目 `<workdir>/.claude/.env` 并同步到 `~/.claude/.env`;**绝不**在项目内创建或修改 `.claude/.env`。无 env 时内置模板**仅**生成 `~/.claude/.env`。
584
+
583
585
  #### 快速示例
584
586
 
585
587
  ```bash
@@ -603,7 +605,7 @@ svharness start-agent --work-dir . --no-sync-env --no-skip-permissions
603
605
  | `[workdir]` | 工作目录(前一参数为 agent 时使用) | — |
604
606
  | `--work-dir <path>` | Agent 工作目录(harness 项目根) | 当前目录 |
605
607
  | `--agent <agent>` | 目标 Agent(**当前仅 codechat 可实际启动**) | `codechat` |
606
- | `--no-sync-env` | 不同步 `<workdir>/.claude/.env` `~/.claude/.env` | false |
608
+ | `--no-sync-env` | 不读取项目 `.claude/.env` 同步到用户级(仍可用已有 `~/.claude/.env`;若无则仅写入用户级内置模板) | false |
607
609
  | `--no-skip-permissions` | 不传 `--dangerously-skip-permissions` | 默认传 |
608
610
 
609
611
  #### 平台说明
@@ -625,7 +627,7 @@ launch_codechat_cli ~/projects/my-app # Linux
625
627
 
626
628
  ### `shell` —— Windows 右键菜单(v0.16+,仅 win32)
627
629
 
628
- 在资源管理器**文件夹空白处**与**文件夹图标**右键增加「在此启动 CodeChat Agent」。
630
+ 在资源管理器**文件夹空白处**与**文件夹图标**右键增加「在此启动 CodeChat Agent」,点击后打开 **PowerShell** 窗口并启动 Agent。
629
631
 
630
632
  ```bash
631
633
  svharness shell install # 注册(幂等)
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
4
  const { runStartAgent } = require('../dist/lib/agent-launcher');
@@ -15,7 +15,8 @@ const os_1 = __importDefault(require("os"));
15
15
  const logger_1 = require("../utils/logger");
16
16
  const win_registry_1 = require("../lib/win-registry");
17
17
  const STUB_DIR = path_1.default.join(process.env.LOCALAPPDATA ?? path_1.default.join(os_1.default.homedir(), 'AppData', 'Local'), 'svharness', 'bin');
18
- const STUB_PATH = path_1.default.join(STUB_DIR, 'launch_codechat_cli.cmd');
18
+ const STUB_PATH = path_1.default.join(STUB_DIR, 'launch_codechat_cli.ps1');
19
+ const LEGACY_STUB_PATH = path_1.default.join(STUB_DIR, 'launch_codechat_cli.cmd');
19
20
  function logInfo(msg, silent) {
20
21
  if (!silent)
21
22
  logger_1.logger.info(msg);
@@ -50,18 +51,23 @@ function resolveLaunchScriptPath() {
50
51
  throw new Error(`未找到 launch-codechat-cli.js(预期:${fromDist})`);
51
52
  }
52
53
  function buildStubContent(launchScriptPath) {
53
- return `@echo off
54
- setlocal EnableExtensions
55
- set "WORKDIR=%~1"
56
- if "%WORKDIR%"=="" set "WORKDIR=%CD%"
57
- cd /d "%WORKDIR%"
58
- node "${launchScriptPath.replace(/"/g, '""')}" "%WORKDIR%"
59
- exit /b %ERRORLEVEL%
54
+ const escapedNodeScript = launchScriptPath.replace(/'/g, "''");
55
+ // ASCII-only + UTF-8 BOM: Windows PowerShell 5.1 misparses UTF-8 without BOM when comments contain non-ASCII.
56
+ return `param(
57
+ [string]$WorkDir = (Get-Location).Path
58
+ )
59
+
60
+ Set-Location -LiteralPath $WorkDir
61
+ & node '${escapedNodeScript}' $WorkDir
62
+ exit $LASTEXITCODE
60
63
  `;
61
64
  }
62
- function buildMenuCommand(stubPath, dirPlaceholder) {
63
- const quotedStub = stubPath.includes(' ') ? `"${stubPath}"` : stubPath;
64
- return `cmd.exe /s /k ${quotedStub} ${dirPlaceholder}`;
65
+ function writeStubFile(launchScriptPath) {
66
+ const content = buildStubContent(launchScriptPath);
67
+ return fs_extra_1.default.writeFile(STUB_PATH, `\uFEFF${content}`, 'utf8');
68
+ }
69
+ function buildMenuCommand(ps1Path, dirPlaceholder) {
70
+ return `powershell.exe -NoExit -NoProfile -ExecutionPolicy Bypass -File "${ps1Path}" ${dirPlaceholder}`;
65
71
  }
66
72
  function registerMenuKey(menuKey, command) {
67
73
  (0, win_registry_1.regSetDefault)(menuKey, win_registry_1.SHELL_MENU_LABEL);
@@ -74,12 +80,15 @@ async function runShellInstall(opts = {}) {
74
80
  assertWin32();
75
81
  const launchScriptPath = resolveLaunchScriptPath();
76
82
  await fs_extra_1.default.ensureDir(STUB_DIR);
77
- await fs_extra_1.default.writeFile(STUB_PATH, buildStubContent(launchScriptPath), 'utf8');
83
+ await writeStubFile(launchScriptPath);
84
+ if (await fs_extra_1.default.pathExists(LEGACY_STUB_PATH)) {
85
+ await fs_extra_1.default.remove(LEGACY_STUB_PATH);
86
+ }
78
87
  const bgCommand = buildMenuCommand(STUB_PATH, '"%V"');
79
88
  const dirCommand = buildMenuCommand(STUB_PATH, '"%1"');
80
89
  registerMenuKey(win_registry_1.SHELL_MENU_KEY_BG, bgCommand);
81
90
  registerMenuKey(win_registry_1.SHELL_MENU_KEY_DIR, dirCommand);
82
- logSuccess('Windows 右键菜单已注册:「在此启动 CodeChat Agent', opts.silent);
91
+ logSuccess('Windows 右键菜单已注册:「在此启动 CodeChat Agent」(PowerShell)', opts.silent);
83
92
  logInfo(` stub: ${STUB_PATH}`, opts.silent);
84
93
  logInfo(` 脚本: ${launchScriptPath}`, opts.silent);
85
94
  }
@@ -93,6 +102,9 @@ async function runShellUninstall(opts = {}) {
93
102
  if (await fs_extra_1.default.pathExists(STUB_PATH)) {
94
103
  await fs_extra_1.default.remove(STUB_PATH);
95
104
  }
105
+ if (await fs_extra_1.default.pathExists(LEGACY_STUB_PATH)) {
106
+ await fs_extra_1.default.remove(LEGACY_STUB_PATH);
107
+ }
96
108
  logSuccess('Windows 右键菜单已卸载', opts.silent);
97
109
  }
98
110
  /**
@@ -65,7 +65,7 @@ function printNextSteps(input) {
65
65
  lines.push(' - ' + picocolors_1.default.cyan('svharness start-agent --work-dir .'));
66
66
  lines.push(' - 或: ' + picocolors_1.default.cyan('launch_codechat_cli'));
67
67
  if (process.platform === 'win32') {
68
- lines.push(' - 或: 资源管理器右键 →「在此启动 CodeChat Agent');
68
+ lines.push(' - 或: 资源管理器右键 →「在此启动 CodeChat Agent」(PowerShell)');
69
69
  }
70
70
  lines.push('');
71
71
  }
package/dist/index.js CHANGED
@@ -422,7 +422,7 @@ function main() {
422
422
  .description('启动 Agent CLI 填充 harness(build 后 S10–S90)或 apply 后的业务开发。默认 agent=codechat,默认 workdir=当前目录。')
423
423
  .option('--work-dir <path>', 'Agent 工作目录(harness 项目根)')
424
424
  .option('--agent <agent>', '目标 Agent(当前仅 codechat 可启动)')
425
- .option('--no-sync-env', '不同步项目 .claude/.env 到用户级 ~/.claude/.env')
425
+ .option('--no-sync-env', '不读取项目 .claude/.env 同步到 ~/.claude/.env(永不写入项目目录)')
426
426
  .option('--no-skip-permissions', '不向 CodeChat CLI 传递 --dangerously-skip-permissions')
427
427
  .action(async (agentOrWorkdir, workdir, opts) => {
428
428
  try {
@@ -447,7 +447,7 @@ function main() {
447
447
  .description('Windows 资源管理器右键菜单管理(仅 win32)');
448
448
  shellCmd
449
449
  .command('install')
450
- .description('注册 HKCU 右键菜单「在此启动 CodeChat Agent」')
450
+ .description('注册 HKCU 右键菜单「在此启动 CodeChat CLI」')
451
451
  .action(async () => {
452
452
  try {
453
453
  await (0, shell_integration_1.runShellInstall)();
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.resolveWorkdir = resolveWorkdir;
7
+ exports.resolveDefaultEnvTemplatePath = resolveDefaultEnvTemplatePath;
7
8
  exports.runStartAgent = runStartAgent;
8
9
  exports.parseStartAgentPositionals = parseStartAgentPositionals;
9
10
  const fs_extra_1 = __importDefault(require("fs-extra"));
@@ -13,6 +14,7 @@ const child_process_1 = require("child_process");
13
14
  const logger_1 = require("../utils/logger");
14
15
  const validate_args_1 = require("../utils/validate-args");
15
16
  const SUPPORTED_START_AGENTS = ['codechat'];
17
+ const DEFAULT_ENV_TEMPLATE = 'default-claude.env';
16
18
  function homePath(...segments) {
17
19
  return path_1.default.join(os_1.default.homedir(), ...segments);
18
20
  }
@@ -62,14 +64,63 @@ function resolveWorkdir(opts) {
62
64
  }
63
65
  return resolved;
64
66
  }
65
- async function syncProjectEnv(workdir, config) {
67
+ /**
68
+ * Bundled templates/default-claude.env (shipped with npm package).
69
+ */
70
+ function resolveDefaultEnvTemplatePath() {
71
+ const candidates = [
72
+ path_1.default.resolve(__dirname, '..', '..', 'templates', DEFAULT_ENV_TEMPLATE),
73
+ path_1.default.resolve(__dirname, '..', '..', '..', 'templates', DEFAULT_ENV_TEMPLATE),
74
+ ];
75
+ for (const candidate of candidates) {
76
+ if (fs_extra_1.default.existsSync(candidate)) {
77
+ return candidate;
78
+ }
79
+ }
80
+ throw new Error(`未找到内置 env 模板(预期之一:\n ${candidates.join('\n ')})`);
81
+ }
82
+ /**
83
+ * Env writes are allowed ONLY on ~/.claude/.env — never on project workdir.
84
+ */
85
+ function assertUserEnvWriteTarget(userEnvPath) {
86
+ const expected = normalizeComparable(homePath('.claude', '.env'));
87
+ const actual = normalizeComparable(path_1.default.resolve(userEnvPath));
88
+ if (actual !== expected) {
89
+ throw new Error(`内部错误:env 只能写入用户目录 ${homePath('.claude', '.env')},禁止写入项目路径。`);
90
+ }
91
+ }
92
+ async function copyEnvToUserOnly(fromPath, userEnvPath) {
93
+ assertUserEnvWriteTarget(userEnvPath);
94
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(userEnvPath));
95
+ await fs_extra_1.default.copy(fromPath, userEnvPath, { overwrite: true });
96
+ }
97
+ /**
98
+ * Sync project env to user profile, or seed bundled default when none exists.
99
+ *
100
+ * **One-way only (read project, write user):**
101
+ * - May read `<workdir>/.claude/.env` as source
102
+ * - May write ONLY `~/.claude/.env`
103
+ * - NEVER creates or modifies `<workdir>/.claude/.env`
104
+ *
105
+ * Priority:
106
+ * 1. Project env exists + syncEnv → copy project → user (user overwritten, project untouched)
107
+ * 2. User env exists → keep
108
+ * 3. Bundled default → copy to user only
109
+ */
110
+ async function ensureUserEnv(workdir, config, syncEnv) {
66
111
  const projectEnv = path_1.default.join(workdir, config.envSyncFromRel);
67
- if (!(await fs_extra_1.default.pathExists(projectEnv))) {
112
+ const userEnv = config.envFile;
113
+ if (syncEnv && (await fs_extra_1.default.pathExists(projectEnv))) {
114
+ await copyEnvToUserOnly(projectEnv, userEnv);
115
+ logger_1.logger.info(`已读取项目 env 并同步到用户目录(未修改项目文件)→ ${userEnv}`);
116
+ return;
117
+ }
118
+ if (await fs_extra_1.default.pathExists(userEnv)) {
68
119
  return;
69
120
  }
70
- await fs_extra_1.default.ensureDir(path_1.default.dirname(config.envFile));
71
- await fs_extra_1.default.copy(projectEnv, config.envFile, { overwrite: true });
72
- logger_1.logger.info(`已同步项目 env ${config.envFile}`);
121
+ const defaultTemplate = resolveDefaultEnvTemplatePath();
122
+ await copyEnvToUserOnly(defaultTemplate, userEnv);
123
+ logger_1.logger.info(`已写入内置默认 env 到用户目录(未写入项目)→ ${userEnv}`);
73
124
  }
74
125
  function warnIfNotHarnessProject(workdir) {
75
126
  const hints = [];
@@ -118,15 +169,13 @@ async function runStartAgent(opts) {
118
169
  const config = getCodechatRunnerConfig();
119
170
  const syncEnv = opts.syncEnv !== false;
120
171
  const skipPermissions = opts.skipPermissions !== false;
121
- if (syncEnv) {
122
- await syncProjectEnv(workdir, config);
123
- }
172
+ await ensureUserEnv(workdir, config, syncEnv);
124
173
  if (!(await fs_extra_1.default.pathExists(config.runner))) {
125
174
  throw new Error(`未找到 CodeChat CLI:${config.runner}\n请先安装 CodeChat CLI 到用户目录。`);
126
175
  }
127
176
  if (!(await fs_extra_1.default.pathExists(config.envFile))) {
128
177
  throw new Error(`未找到 env 文件:${config.envFile}\n` +
129
- `请在 ${path_1.default.join(workdir, config.envSyncFromRel)} 或 ${config.envFile} 创建配置。`);
178
+ `请提供 ${path_1.default.join(workdir, config.envSyncFromRel)},或确保内置模板 templates/default-claude.env 可访问。`);
130
179
  }
131
180
  warnIfNotHarnessProject(workdir);
132
181
  const args = buildRunnerArgs(config, workdir, skipPermissions);
@@ -49,4 +49,4 @@ function regKeyExists(key) {
49
49
  }
50
50
  exports.SHELL_MENU_KEY_BG = 'HKCU\\Software\\Classes\\Directory\\Background\\shell\\SvharnessLaunchCodeChatAgent';
51
51
  exports.SHELL_MENU_KEY_DIR = 'HKCU\\Software\\Classes\\Directory\\shell\\SvharnessLaunchCodeChatAgent';
52
- exports.SHELL_MENU_LABEL = '在此启动 CodeChat Agent';
52
+ exports.SHELL_MENU_LABEL = '在此启动 CodeChat CLI';
@@ -36,7 +36,7 @@
36
36
  │ 入口层 │
37
37
  │ launch_codechat_cli [workdir] │
38
38
  │ svharness start-agent [agent] [workdir] [--work-dir ...] │
39
- │ Explorer 右键 → stub.cmd → launch-codechat-cli.js │
39
+ │ Explorer 右键 → stub.ps1 → launch-codechat-cli.js │
40
40
  └───────────────────────────┬─────────────────────────────────┘
41
41
 
42
42
  ┌───────────────────────────▼─────────────────────────────────┐
@@ -125,14 +125,26 @@ launch_codechat_cli ./my-app # 指定 workdir
125
125
 
126
126
  ## 5. env 同步策略
127
127
 
128
- | 步骤 | 行为 |
129
- |------|------|
130
- | 1 | 检查 `<workdir>/.claude/.env` |
131
- | 2 | 若存在且未指定 `--no-sync-env`,拷贝到 `~/.claude/.env`(覆盖) |
132
- | 3 | 自动创建 `~/.claude/` 目录 |
133
- | 4 | 启动时使用 `--env-file=~/.claude/.env` |
128
+ **铁律:单向同步,只写用户目录,永不碰项目。**
129
+
130
+ | 操作 | 允许 | 禁止 |
131
+ |------|------|------|
132
+ | 读取 `<workdir>/.claude/.env` | | |
133
+ | 写入 `~/.claude/.env` | ✅ | — |
134
+ | 写入 `<workdir>/.claude/.env` | — | ❌ |
135
+ | 覆盖 / 修改项目级 `.claude/.env` | — | ❌ |
136
+
137
+ 优先级(高 → 低):
138
+
139
+ | 优先级 | 条件 | 行为 |
140
+ |--------|------|------|
141
+ | 1 | 项目 `.claude/.env` 存在且未 `--no-sync-env` | **只读**项目文件,内容复制到 `~/.claude/.env`(覆盖用户级;**项目文件不变**) |
142
+ | 2 | `~/.claude/.env` 已存在 | 保持不变 |
143
+ | 3 | 以上均不满足 | 从 `templates/default-claude.env` **仅**生成 `~/.claude/.env` |
134
144
 
135
- 若同步后用户级 env 仍不存在 → 报错并提示创建方式。
145
+ 内置模板为德赛 CodeChat 通用配置。首次使用前请配置有效 `ANTHROPIC_AUTH_TOKEN`(改用户级 env 或项目 `.claude/.env`)。
146
+
147
+ 启动时 CodeChat 使用 `--env-file=~/.claude/.env`。
136
148
 
137
149
  ---
138
150
 
@@ -156,7 +168,7 @@ macOS (`darwin`) 路径约定与 Linux 相同;若 runner 不存在则报错。
156
168
  资源管理器触发的命令 **不保证** 含 `%AppData%\npm` PATH。因此 registry 指向固定路径:
157
169
 
158
170
  ```
159
- %LOCALAPPDATA%\svharness\bin\launch_codechat_cli.cmd
171
+ %LOCALAPPDATA%\svharness\bin\launch_codechat_cli.ps1
160
172
  ```
161
173
 
162
174
  stub 接收 Explorer 传入的目录参数,`cd` 后调用 **绝对路径** 的 `bin/launch-codechat-cli.js`。
@@ -168,13 +180,23 @@ stub 接收 Explorer 传入的目录参数,`cd` 后调用 **绝对路径** 的
168
180
  | 文件夹空白处 | `HKCU\Software\Classes\Directory\Background\shell\SvharnessLaunchCodeChatAgent` |
169
181
  | 文件夹图标 | `HKCU\Software\Classes\Directory\shell\SvharnessLaunchCodeChatAgent` |
170
182
 
171
- 菜单标题:`在此启动 CodeChat Agent`
183
+ 菜单标题:`在此启动 CodeChat CLI`
184
+
185
+ Command(Background):
186
+
187
+ ```text
188
+ powershell.exe -NoExit -NoProfile -ExecutionPolicy Bypass -File "<stub.ps1>" "%V"
189
+ ```
190
+
191
+ Command(Directory):
172
192
 
173
- Command(Background):`cmd.exe /s /k "<stub>" "%V"`
193
+ ```text
194
+ powershell.exe -NoExit -NoProfile -ExecutionPolicy Bypass -File "<stub.ps1>" "%1"
195
+ ```
174
196
 
175
- Command(Directory):`cmd.exe /s /k "<stub>" "%1"`
197
+ 使用 `-NoExit` 保持 PowerShell 窗口开启以便 CodeChat 交互;`-ExecutionPolicy Bypass` 避免本地脚本执行策略拦截 stub。
176
198
 
177
- 使用 `/k` 保持 CMD 窗口开启以便 CodeChat 交互。
199
+ stub 脚本须为 **UTF-8 BOM + ASCII 正文**(Windows PowerShell 5.1 对无 BOM 的 UTF-8 文件中的非 ASCII 注释会解析失败)。
178
200
 
179
201
  ---
180
202
 
@@ -239,7 +261,7 @@ svharness start-agent --work-dir . --no-skip-permissions
239
261
  **Q: 右键菜单无反应**
240
262
 
241
263
  1. `svharness shell status` 检查注册状态
242
- 2. 确认 stub 存在:`%LOCALAPPDATA%\svharness\bin\launch_codechat_cli.cmd`
264
+ 2. 确认 stub 存在:`%LOCALAPPDATA%\svharness\bin\launch_codechat_cli.ps1`
243
265
  3. 重新安装:`svharness shell install`
244
266
 
245
267
  **Q: 未找到 run.bat / run.sh**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svharness",
3
- "version": "0.14.11",
3
+ "version": "0.14.12",
4
4
  "description": "CLI scaffolder for SDD-Driven Agent-Agnostic Coding Framework (harness)",
5
5
  "bin": {
6
6
  "svharness": "./bin/cli.js",
@@ -0,0 +1,60 @@
1
+ # ============================================================
2
+ # CodeChat 接口(svharness 内置默认模板 → 仅 ~/.claude/.env)
3
+ # 仅写入用户目录;不会创建或修改项目 <workdir>/.claude/.env
4
+ # 若项目已有 .claude/.env,start-agent 只读并同步到 ~/.claude/.env
5
+ # ============================================================
6
+ ANTHROPIC_AUTH_TOKEN=YOUR_ANTHROPIC_AUTH_TOKEN
7
+ ANTHROPIC_BASE_URL=https://aiplus.desaysv.com/chatbot/anthropic
8
+ # ANTHROPIC_BASE_URL=http://127.0.0.1:6008/chatbot/anthropic # 德赛本地调试
9
+ ANTHROPIC_MODEL=deepseek
10
+ ANTHROPIC_DEFAULT_HAIKU_MODEL=deepseek
11
+ ANTHROPIC_DEFAULT_OPUS_MODEL=deepseek
12
+ API_TIMEOUT_MS=3000000
13
+
14
+ # ============================================================
15
+ # OpenAI(通过 LiteLLM 代理)
16
+ # 先启动: litellm --config litellm_config.yaml --port 4000
17
+ # ============================================================
18
+ # ANTHROPIC_AUTH_TOKEN=sk-anything
19
+ # ANTHROPIC_BASE_URL=http://localhost:4000
20
+ # ANTHROPIC_MODEL=gpt-4o
21
+ # ANTHROPIC_DEFAULT_SONNET_MODEL=gpt-4o
22
+ # ANTHROPIC_DEFAULT_HAIKU_MODEL=gpt-4o
23
+ # ANTHROPIC_DEFAULT_OPUS_MODEL=gpt-4o
24
+ # API_TIMEOUT_MS=3000000
25
+
26
+ # ============================================================
27
+ # DeepSeek(通过 LiteLLM 代理)
28
+ # ============================================================
29
+ # ANTHROPIC_AUTH_TOKEN=sk-anything
30
+ # ANTHROPIC_BASE_URL=http://localhost:4000
31
+ # ANTHROPIC_MODEL=deepseek-chat
32
+ # ANTHROPIC_DEFAULT_SONNET_MODEL=deepseek-chat
33
+ # ANTHROPIC_DEFAULT_HAIKU_MODEL=deepseek-chat
34
+ # ANTHROPIC_DEFAULT_OPUS_MODEL=deepseek-chat
35
+ # API_TIMEOUT_MS=3000000
36
+
37
+ # ============================================================
38
+ # OpenRouter(直连 Anthropic 兼容接口)
39
+ # ============================================================
40
+ # ANTHROPIC_AUTH_TOKEN=sk-or-v1-xxx
41
+ # ANTHROPIC_BASE_URL=https://openrouter.ai/api/v1
42
+ # ANTHROPIC_MODEL=openai/gpt-4o
43
+ # ANTHROPIC_DEFAULT_SONNET_MODEL=openai/gpt-4o
44
+ # ANTHROPIC_DEFAULT_HAIKU_MODEL=openai/gpt-4o-mini
45
+ # ANTHROPIC_DEFAULT_OPUS_MODEL=openai/gpt-4o
46
+
47
+ # ============================================================
48
+ # 德赛调试专用
49
+ # ============================================================
50
+ CLAUDE_CODE_TRACE_ENABLED=0
51
+ CLAUDE_CODE_TRACE_PIPELINE=0
52
+ CLAUDE_CODE_TRACE_PIPELINE_FILE=
53
+ CLAUDE_CODE_TRACE_WIRE_PARAMS=0
54
+
55
+ # ============================================================
56
+ # 通用设置(建议始终开启)
57
+ # ============================================================
58
+ DISABLE_TELEMETRY=1
59
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
60
+ ENABLE_TOOL_SEARCH=0