chatccc 0.2.16 → 0.2.18
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 +105 -111
- package/bin/chatccc.mjs +2 -14
- package/config.sample.json +26 -0
- package/images/avatars/status_busy.png +0 -0
- package/images/avatars/status_idle.png +0 -0
- package/images/avatars/status_new.png +0 -0
- package/images/img_readme_0.jpg +0 -0
- package/images/img_readme_1.jpg +0 -0
- package/images/img_readme_callback.png +0 -0
- package/images/img_readme_event.png +0 -0
- package/images/img_readme_permission.png +0 -0
- package/package.json +13 -12
- package/src/__tests__/cards.test.ts +3 -3
- package/src/__tests__/claude-adapter.test.ts +301 -10
- package/src/__tests__/config-reload.test.ts +171 -0
- package/src/__tests__/config.test.ts +259 -2
- package/src/__tests__/crash-logging.test.ts +210 -0
- package/src/__tests__/session.test.ts +2 -2
- package/src/__tests__/web-ui.test.ts +178 -0
- package/src/adapters/claude-adapter.ts +57 -8
- package/src/adapters/codex-adapter.ts +294 -293
- package/src/adapters/cursor-adapter.ts +1 -1
- package/src/config-utils.ts +177 -0
- package/src/config.ts +412 -178
- package/src/exit-banner.ts +12 -2
- package/src/feishu-api.ts +4 -15
- package/src/index.ts +178 -64
- package/src/session.ts +27 -12
- package/src/shared.ts +189 -16
- package/src/web-ui.ts +1591 -0
- package/.env.example +0 -44
|
@@ -54,7 +54,44 @@ interface SdkMessageLike {
|
|
|
54
54
|
export interface ClaudeAdapterOptions {
|
|
55
55
|
model: string;
|
|
56
56
|
effort: string;
|
|
57
|
-
|
|
57
|
+
/** 判断字段是否为"不传给 SDK"的占位(项目约定:空字符串/全空白) */
|
|
58
|
+
isEmpty: (value: string) => boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Anthropic 兼容网关的 API key。
|
|
61
|
+
* 非空(trim 后)时会被注入到 SDK 子进程的 ANTHROPIC_API_KEY 环境变量;
|
|
62
|
+
* 留空 / 全空白 → 不覆盖,沿用主进程 process.env / 系统环境变量。
|
|
63
|
+
* 永远不会写入主进程的 process.env,避免污染其他依赖 env 的代码。
|
|
64
|
+
*/
|
|
65
|
+
apiKey?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Anthropic 兼容网关的 base URL。
|
|
68
|
+
* 非空(trim 后)时会被注入到 SDK 子进程的 ANTHROPIC_BASE_URL 环境变量;
|
|
69
|
+
* 留空 / 全空白 → 不覆盖,沿用主进程 process.env / 系统环境变量。
|
|
70
|
+
*/
|
|
71
|
+
baseUrl?: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// buildSdkEnv — 为 SDK 子进程构造 env
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// 行为契约(详见单测 "createClaudeAdapter — env 注入"):
|
|
78
|
+
// - apiKey 与 baseUrl 都为空(trim 后)→ 返回 undefined,让 SDK 走默认行为
|
|
79
|
+
// (即 process.env),避免无意义的拷贝。
|
|
80
|
+
// - 任一非空 → 返回 process.env 的浅拷贝,并按需覆盖 ANTHROPIC_API_KEY /
|
|
81
|
+
// ANTHROPIC_BASE_URL;其余 env 字段保持不变(PATH、HOME 等子进程必需)。
|
|
82
|
+
// - 主进程 process.env 永不被写入,主进程其他模块对 env 的读取不受影响。
|
|
83
|
+
function buildSdkEnv(
|
|
84
|
+
apiKey: string | undefined,
|
|
85
|
+
baseUrl: string | undefined,
|
|
86
|
+
): Record<string, string | undefined> | undefined {
|
|
87
|
+
const apiKeyTrim = (apiKey ?? "").trim();
|
|
88
|
+
const baseUrlTrim = (baseUrl ?? "").trim();
|
|
89
|
+
if (!apiKeyTrim && !baseUrlTrim) return undefined;
|
|
90
|
+
|
|
91
|
+
const env: Record<string, string | undefined> = { ...process.env };
|
|
92
|
+
if (apiKeyTrim) env.ANTHROPIC_API_KEY = apiKeyTrim;
|
|
93
|
+
if (baseUrlTrim) env.ANTHROPIC_BASE_URL = baseUrlTrim;
|
|
94
|
+
return env;
|
|
58
95
|
}
|
|
59
96
|
|
|
60
97
|
// ---------------------------------------------------------------------------
|
|
@@ -65,7 +102,9 @@ function buildSessionOptions(
|
|
|
65
102
|
cwd: string,
|
|
66
103
|
model: string,
|
|
67
104
|
effort: string,
|
|
68
|
-
|
|
105
|
+
isEmpty: (value: string) => boolean,
|
|
106
|
+
apiKey: string | undefined,
|
|
107
|
+
baseUrl: string | undefined,
|
|
69
108
|
): Record<string, unknown> {
|
|
70
109
|
const o: Record<string, unknown> = {
|
|
71
110
|
cwd,
|
|
@@ -74,8 +113,10 @@ function buildSessionOptions(
|
|
|
74
113
|
autoCompactEnabled: true,
|
|
75
114
|
settingSources: ["project", "local"],
|
|
76
115
|
};
|
|
77
|
-
if (!
|
|
78
|
-
if (!
|
|
116
|
+
if (!isEmpty(model)) o.model = model;
|
|
117
|
+
if (!isEmpty(effort)) o.effort = effort;
|
|
118
|
+
const env = buildSdkEnv(apiKey, baseUrl);
|
|
119
|
+
if (env) o.env = env;
|
|
79
120
|
return o;
|
|
80
121
|
}
|
|
81
122
|
|
|
@@ -150,12 +191,16 @@ class ClaudeAdapter implements ToolAdapter {
|
|
|
150
191
|
readonly sessionDescPrefix = "Claude Code Session:";
|
|
151
192
|
private model: string;
|
|
152
193
|
private effort: string;
|
|
153
|
-
private
|
|
194
|
+
private isEmpty: (value: string) => boolean;
|
|
195
|
+
private apiKey: string | undefined;
|
|
196
|
+
private baseUrl: string | undefined;
|
|
154
197
|
|
|
155
198
|
constructor(options: ClaudeAdapterOptions) {
|
|
156
199
|
this.model = options.model;
|
|
157
200
|
this.effort = options.effort;
|
|
158
|
-
this.
|
|
201
|
+
this.isEmpty = options.isEmpty;
|
|
202
|
+
this.apiKey = options.apiKey;
|
|
203
|
+
this.baseUrl = options.baseUrl;
|
|
159
204
|
}
|
|
160
205
|
|
|
161
206
|
async createSession(cwd: string): Promise<CreateSessionResult> {
|
|
@@ -163,7 +208,9 @@ class ClaudeAdapter implements ToolAdapter {
|
|
|
163
208
|
cwd,
|
|
164
209
|
this.model,
|
|
165
210
|
this.effort,
|
|
166
|
-
this.
|
|
211
|
+
this.isEmpty,
|
|
212
|
+
this.apiKey,
|
|
213
|
+
this.baseUrl,
|
|
167
214
|
);
|
|
168
215
|
const session = unstable_v2_createSession(sessionOpts as any);
|
|
169
216
|
|
|
@@ -205,7 +252,9 @@ class ClaudeAdapter implements ToolAdapter {
|
|
|
205
252
|
cwd,
|
|
206
253
|
this.model,
|
|
207
254
|
this.effort,
|
|
208
|
-
this.
|
|
255
|
+
this.isEmpty,
|
|
256
|
+
this.apiKey,
|
|
257
|
+
this.baseUrl,
|
|
209
258
|
);
|
|
210
259
|
const session = unstable_v2_resumeSession(
|
|
211
260
|
sessionId,
|