chatccc 0.2.243 → 0.2.244
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 +5 -5
- package/bin/cccagent.mjs +17 -17
- package/deepccc-agent/bin/deepccc.mjs +26 -26
- package/deepccc-agent/os-prompts/darwin.md +8 -0
- package/deepccc-agent/os-prompts/linux.md +8 -0
- package/deepccc-agent/os-prompts/win32.md +9 -0
- package/deepccc-agent/package.json +2 -1
- package/deepccc-agent/src/__tests__/chat-session.test.ts +39 -0
- package/deepccc-agent/src/__tests__/cli-json.test.ts +49 -49
- package/deepccc-agent/src/__tests__/config.test.ts +26 -26
- package/deepccc-agent/src/__tests__/context.test.ts +319 -319
- package/deepccc-agent/src/__tests__/file-tools.test.ts +240 -240
- package/deepccc-agent/src/__tests__/permissions.test.ts +195 -195
- package/deepccc-agent/src/__tests__/progress-reducer.test.ts +121 -121
- package/deepccc-agent/src/__tests__/session-search.test.ts +262 -262
- package/deepccc-agent/src/__tests__/session-select.test.ts +116 -116
- package/deepccc-agent/src/__tests__/sigint.test.ts +56 -56
- package/deepccc-agent/src/__tests__/skills.test.ts +284 -284
- package/deepccc-agent/src/__tests__/terminal-renderer.test.ts +247 -247
- package/deepccc-agent/src/__tests__/web-tools.test.ts +220 -220
- package/deepccc-agent/src/config.ts +84 -84
- package/deepccc-agent/src/context.ts +465 -465
- package/deepccc-agent/src/file-log.ts +38 -38
- package/deepccc-agent/src/index.ts +46 -16
- package/deepccc-agent/src/proc-tree-kill.ts +61 -61
- package/deepccc-agent/src/progress/cards-helpers.ts +76 -76
- package/deepccc-agent/src/progress/reducer.ts +113 -113
- package/deepccc-agent/src/progress/terminal-renderer.ts +294 -294
- package/deepccc-agent/src/progress/view.ts +77 -77
- package/deepccc-agent/src/raw-stream-log.ts +124 -124
- package/deepccc-agent/src/session-search.ts +370 -370
- package/deepccc-agent/src/session-select.ts +48 -48
- package/deepccc-agent/src/sigint.ts +50 -50
- package/deepccc-agent/src/skills.ts +205 -205
- package/deepccc-agent/src/web-tools.ts +313 -313
- package/deepccc-agent/tsconfig.build.json +13 -13
- package/deepccc-agent/tsconfig.json +13 -13
- package/deepccc-agent/vitest.config.ts +7 -7
- package/package.json +73 -73
- package/src/__tests__/builtin-chat-session.test.ts +522 -522
- package/src/__tests__/builtin-config.test.ts +26 -26
- package/src/__tests__/builtin-context.test.ts +319 -319
- package/src/__tests__/builtin-file-tools.test.ts +240 -240
- package/src/__tests__/builtin-permissions.test.ts +211 -211
- package/src/__tests__/builtin-session-search.test.ts +262 -262
- package/src/__tests__/builtin-session-select.test.ts +116 -116
- package/src/__tests__/builtin-sigint.test.ts +56 -56
- package/src/__tests__/builtin-skills.test.ts +284 -284
- package/src/__tests__/builtin-web-tools.test.ts +220 -220
- package/src/__tests__/config.test.ts +17 -17
- package/src/__tests__/progress-reducer.test.ts +121 -121
- package/src/__tests__/session-ccc-config.test.ts +45 -45
- package/src/__tests__/session.test.ts +298 -298
- package/src/adapters/ccc-adapter.ts +145 -145
- package/src/config-utils.ts +13 -13
- package/src/config.ts +13 -13
- package/src/progress/reducer.ts +113 -113
- package/src/session-chat-binding.ts +83 -83
- package/src/session.ts +311 -311
package/README.md
CHANGED
|
@@ -210,11 +210,11 @@ chatccc
|
|
|
210
210
|
|
|
211
211
|
Claude Code、Cursor 和 Codex 需要对应的本地工具;CCC Agent 内置于 ChatCCC,开箱即用,**模型接入不限于 DeepSeek**——它走 OpenAI 兼容协议,任意兼容端点都可以直接替换(详见下文 CCC Agent)。
|
|
212
212
|
|
|
213
|
-
#### CCC Agent
|
|
214
|
-
|
|
215
|
-
CCC Agent 是 ChatCCC 内置的编程 Agent,不需要额外安装 CLI,开箱即用。在首次配置向导或 Web 管理页中启用后,填写 API Key、Base URL 和模型即可使用;它可以设为 `/new` 的默认 Agent,也可以通过 `/new ccc` 显式创建会话。
|
|
216
|
-
|
|
217
|
-
ChatCCC 会把 `ccc.DEEPSEEK_API_KEY`、`ccc.DEEPSEEK_BASE_URL`、模型和 effort 显式传给内置 Agent;这些配置不会回退读取 `~/.deepccc/config.json`,因此用户无需安装或配置独立的 `deepccc` 包。API Key 为空时 CCC Agent 会自动保持禁用。
|
|
213
|
+
#### CCC Agent
|
|
214
|
+
|
|
215
|
+
CCC Agent 是 ChatCCC 内置的编程 Agent,不需要额外安装 CLI,开箱即用。在首次配置向导或 Web 管理页中启用后,填写 API Key、Base URL 和模型即可使用;它可以设为 `/new` 的默认 Agent,也可以通过 `/new ccc` 显式创建会话。
|
|
216
|
+
|
|
217
|
+
ChatCCC 会把 `ccc.DEEPSEEK_API_KEY`、`ccc.DEEPSEEK_BASE_URL`、模型和 effort 显式传给内置 Agent;这些配置不会回退读取 `~/.deepccc/config.json`,因此用户无需安装或配置独立的 `deepccc` 包。API Key 为空时 CCC Agent 会自动保持禁用。
|
|
218
218
|
|
|
219
219
|
**API 支持不限于 DeepSeek。** CCC Agent 底层使用 OpenAI 兼容协议(`@ai-sdk/openai-compatible`),DeepSeek 只是出厂默认端点。`ccc.DEEPSEEK_API_KEY` / `ccc.DEEPSEEK_BASE_URL` 可以指向**任意 OpenAI 兼容服务**,例如:
|
|
220
220
|
|
package/bin/cccagent.mjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { spawnSync } from "node:child_process";
|
|
3
|
-
import { createRequire } from "node:module";
|
|
4
|
-
import { dirname, join } from "node:path";
|
|
5
|
-
|
|
6
|
-
const require = createRequire(import.meta.url);
|
|
7
|
-
const pkgRoot = dirname(require.resolve("../package.json"));
|
|
8
|
-
const cliTs = join(pkgRoot, "deepccc-agent", "src", "cli.ts");
|
|
9
|
-
const tsxCli = require.resolve("tsx/cli");
|
|
10
|
-
|
|
11
|
-
const result = spawnSync(process.execPath, [tsxCli, cliTs, ...process.argv.slice(2)], {
|
|
12
|
-
stdio: "inherit",
|
|
13
|
-
cwd: process.cwd(),
|
|
14
|
-
env: process.env,
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
process.exit(result.status === null ? 1 : result.status);
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const pkgRoot = dirname(require.resolve("../package.json"));
|
|
8
|
+
const cliTs = join(pkgRoot, "deepccc-agent", "src", "cli.ts");
|
|
9
|
+
const tsxCli = require.resolve("tsx/cli");
|
|
10
|
+
|
|
11
|
+
const result = spawnSync(process.execPath, [tsxCli, cliTs, ...process.argv.slice(2)], {
|
|
12
|
+
stdio: "inherit",
|
|
13
|
+
cwd: process.cwd(),
|
|
14
|
+
env: process.env,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
process.exit(result.status === null ? 1 : result.status);
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
import { spawnSync } from "node:child_process";
|
|
4
|
-
import { createRequire } from "node:module";
|
|
5
|
-
import { dirname, join } from "node:path";
|
|
6
|
-
|
|
7
|
-
const require = createRequire(import.meta.url);
|
|
8
|
-
const pkgRoot = dirname(require.resolve("../package.json"));
|
|
9
|
-
const distCli = join(pkgRoot, "dist", "cli.js");
|
|
10
|
-
|
|
11
|
-
let args;
|
|
12
|
-
if (existsSync(distCli)) {
|
|
13
|
-
args = [distCli, ...process.argv.slice(2)];
|
|
14
|
-
} else {
|
|
15
|
-
const tsxCli = require.resolve("tsx/cli");
|
|
16
|
-
const sourceCli = join(pkgRoot, "src", "cli.ts");
|
|
17
|
-
args = [tsxCli, sourceCli, ...process.argv.slice(2)];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const result = spawnSync(process.execPath, args, {
|
|
21
|
-
stdio: "inherit",
|
|
22
|
-
cwd: process.cwd(),
|
|
23
|
-
env: process.env,
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
process.exit(result.status === null ? 1 : result.status);
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
const pkgRoot = dirname(require.resolve("../package.json"));
|
|
9
|
+
const distCli = join(pkgRoot, "dist", "cli.js");
|
|
10
|
+
|
|
11
|
+
let args;
|
|
12
|
+
if (existsSync(distCli)) {
|
|
13
|
+
args = [distCli, ...process.argv.slice(2)];
|
|
14
|
+
} else {
|
|
15
|
+
const tsxCli = require.resolve("tsx/cli");
|
|
16
|
+
const sourceCli = join(pkgRoot, "src", "cli.ts");
|
|
17
|
+
args = [tsxCli, sourceCli, ...process.argv.slice(2)];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const result = spawnSync(process.execPath, args, {
|
|
21
|
+
stdio: "inherit",
|
|
22
|
+
cwd: process.cwd(),
|
|
23
|
+
env: process.env,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
process.exit(result.status === null ? 1 : result.status);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
## macOS Command-Line Notes
|
|
2
|
+
|
|
3
|
+
You are running on macOS. run_command executes through zsh, a POSIX shell. Quoting follows standard POSIX conventions (the same habits you already know from bash):
|
|
4
|
+
|
|
5
|
+
- Double quotes are stripped and group an argument containing spaces: `echo "hello world"` prints `hello world`.
|
|
6
|
+
- Single quotes are literal quoting characters: `'a b'` is a single argument `a b`.
|
|
7
|
+
- Backticks and `$(...)` perform command substitution; quote them if you need literal text.
|
|
8
|
+
- Paths use `/` separators and `~` expands to the home directory.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
## Linux Command-Line Notes
|
|
2
|
+
|
|
3
|
+
You are running on Linux. run_command executes through a POSIX shell (bash/sh). Quoting follows standard POSIX conventions (the same habits you already know from bash):
|
|
4
|
+
|
|
5
|
+
- Double quotes are stripped and group an argument containing spaces: `echo "hello world"` prints `hello world`.
|
|
6
|
+
- Single quotes are literal quoting characters: `'a b'` is a single argument `a b`.
|
|
7
|
+
- Backticks and `$(...)` perform command substitution; quote them if you need literal text.
|
|
8
|
+
- Paths use `/` separators and `~` expands to the home directory.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
## Windows Command-Line Notes
|
|
2
|
+
|
|
3
|
+
You are running on Windows. run_command executes through cmd.exe, not bash. cmd quoting differs from bash and breaks common habits:
|
|
4
|
+
|
|
5
|
+
- Double quotes are NOT stripped: `echo "hello world"` prints `"hello world"` (quotes included), and `"a b" "c"` passes the literal arguments `"a b"` and `"c"` (quotes included) to the program.
|
|
6
|
+
- Single quotes are NOT quoting characters in cmd.exe: `'a b'` is parsed as two arguments (`'a` and `b'`).
|
|
7
|
+
- Multi-line or quote-heavy inline scripts (python -c "...\n...", ssh host "bash -c '...'") frequently break under cmd quoting; write the script to a temporary file and execute that file instead.
|
|
8
|
+
- PowerShell-only syntax (Get-Item, 2>$null, Select-Object) is unavailable; the shell is cmd.exe unless you explicitly invoke powershell.
|
|
9
|
+
- To pass an argument containing spaces, use double quotes and expect the quotes to reach the program literally; when the target accepts file input, prefer writing the value to a file.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deepccc",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "A lightweight DeepSeek-optimized coding agent with OpenAI-compatible model support.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"dist/",
|
|
35
35
|
"bin/",
|
|
36
36
|
"docs/",
|
|
37
|
+
"os-prompts/",
|
|
37
38
|
"package.json",
|
|
38
39
|
"README.md",
|
|
39
40
|
"LICENSE"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mkdir, mkdtemp, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
4
5
|
|
|
5
6
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
6
7
|
|
|
@@ -576,3 +577,41 @@ describe("estimateBuiltinContextTokens", () => {
|
|
|
576
577
|
expect(estimate).toBeLessThan(340);
|
|
577
578
|
});
|
|
578
579
|
});
|
|
580
|
+
|
|
581
|
+
describe("loadPlatformCommandPrompt", () => {
|
|
582
|
+
// 测试文件在 src/__tests__/,上两级即包根 os-prompts/
|
|
583
|
+
const builtinDir = fileURLToPath(new URL("../../os-prompts/", import.meta.url));
|
|
584
|
+
|
|
585
|
+
async function loadPrompt(
|
|
586
|
+
platform: string,
|
|
587
|
+
dirs?: { builtinDir?: string; userDir?: string },
|
|
588
|
+
): Promise<string> {
|
|
589
|
+
const mod = (await import("../index.js")) as {
|
|
590
|
+
loadPlatformCommandPrompt: (
|
|
591
|
+
platform: string,
|
|
592
|
+
dirs?: { builtinDir?: string; userDir?: string },
|
|
593
|
+
) => string;
|
|
594
|
+
};
|
|
595
|
+
return mod.loadPlatformCommandPrompt(platform, dirs);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
it("loads builtin guidance from os-prompts/<platform>.md", async () => {
|
|
599
|
+
const text = await loadPrompt("win32", { builtinDir });
|
|
600
|
+
expect(text).toContain("## Windows Command-Line Notes");
|
|
601
|
+
expect(text).toContain("cmd.exe");
|
|
602
|
+
expect(text).toMatch(/double quotes/i);
|
|
603
|
+
expect(text).toMatch(/single quotes/i);
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
it("prefers the user override at ~/.deepccc/prompts/<platform>.md", async () => {
|
|
607
|
+
const userDir = await mkdtemp(join(tmpdir(), "deepccc-os-prompt-override-"));
|
|
608
|
+
await writeFile(join(userDir, "win32.md"), "CUSTOM OVERRIDE GUIDANCE", "utf-8");
|
|
609
|
+
const text = await loadPrompt("win32", { builtinDir, userDir });
|
|
610
|
+
expect(text).toBe("CUSTOM OVERRIDE GUIDANCE");
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
it("returns empty string for unknown platforms or missing files", async () => {
|
|
614
|
+
expect(await loadPrompt("freebsd", { builtinDir })).toBe("");
|
|
615
|
+
expect(await loadPrompt("linux", { builtinDir: join(builtinDir, "missing") })).toBe("");
|
|
616
|
+
});
|
|
617
|
+
});
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import { execFile } from "node:child_process";
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { promisify } from "node:util";
|
|
6
|
-
|
|
7
|
-
import { describe, expect, it } from "vitest";
|
|
8
|
-
|
|
9
|
-
const execFileAsync = promisify(execFile);
|
|
10
|
-
|
|
11
|
-
// 兼容两种布局:<root>/deepccc-agent/src/__tests__(chatccc 子目录)或 <root>/src/__tests__(deepccc 镜像)
|
|
12
|
-
const here = dirname(fileURLToPath(import.meta.url));
|
|
13
|
-
const cliBin = [
|
|
14
|
-
join(here, "..", "..", "..", "bin", "deepccc.mjs"),
|
|
15
|
-
join(here, "..", "..", "bin", "deepccc.mjs"),
|
|
16
|
-
].find(existsSync);
|
|
17
|
-
|
|
18
|
-
describe("deepccc cli --stream-json", () => {
|
|
19
|
-
it("writes only JSON lines to stdout when startup fails", async () => {
|
|
20
|
-
let caught: unknown;
|
|
21
|
-
try {
|
|
22
|
-
await execFileAsync(process.execPath, [
|
|
23
|
-
cliBin!,
|
|
24
|
-
"--stream-json",
|
|
25
|
-
"--prompt",
|
|
26
|
-
"hello",
|
|
27
|
-
"--api-key",
|
|
28
|
-
"",
|
|
29
|
-
], {
|
|
30
|
-
cwd: dirname(cliBin!),
|
|
31
|
-
timeout: 10_000,
|
|
32
|
-
windowsHide: true,
|
|
33
|
-
});
|
|
34
|
-
} catch (err) {
|
|
35
|
-
caught = err;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
expect(caught).toMatchObject({ code: 1 });
|
|
39
|
-
const stdout = (caught as { stdout?: string }).stdout ?? "";
|
|
40
|
-
const lines = stdout.trim().split(/\r?\n/).filter(Boolean);
|
|
41
|
-
expect(lines.length).toBeGreaterThan(0);
|
|
42
|
-
for (const line of lines) {
|
|
43
|
-
expect(() => JSON.parse(line)).not.toThrow();
|
|
44
|
-
}
|
|
45
|
-
expect(JSON.parse(lines.at(-1)!)).toEqual(expect.objectContaining({
|
|
46
|
-
type: "error",
|
|
47
|
-
}));
|
|
48
|
-
});
|
|
49
|
-
});
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
|
|
7
|
+
import { describe, expect, it } from "vitest";
|
|
8
|
+
|
|
9
|
+
const execFileAsync = promisify(execFile);
|
|
10
|
+
|
|
11
|
+
// 兼容两种布局:<root>/deepccc-agent/src/__tests__(chatccc 子目录)或 <root>/src/__tests__(deepccc 镜像)
|
|
12
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
const cliBin = [
|
|
14
|
+
join(here, "..", "..", "..", "bin", "deepccc.mjs"),
|
|
15
|
+
join(here, "..", "..", "bin", "deepccc.mjs"),
|
|
16
|
+
].find(existsSync);
|
|
17
|
+
|
|
18
|
+
describe("deepccc cli --stream-json", () => {
|
|
19
|
+
it("writes only JSON lines to stdout when startup fails", async () => {
|
|
20
|
+
let caught: unknown;
|
|
21
|
+
try {
|
|
22
|
+
await execFileAsync(process.execPath, [
|
|
23
|
+
cliBin!,
|
|
24
|
+
"--stream-json",
|
|
25
|
+
"--prompt",
|
|
26
|
+
"hello",
|
|
27
|
+
"--api-key",
|
|
28
|
+
"",
|
|
29
|
+
], {
|
|
30
|
+
cwd: dirname(cliBin!),
|
|
31
|
+
timeout: 10_000,
|
|
32
|
+
windowsHide: true,
|
|
33
|
+
});
|
|
34
|
+
} catch (err) {
|
|
35
|
+
caught = err;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
expect(caught).toMatchObject({ code: 1 });
|
|
39
|
+
const stdout = (caught as { stdout?: string }).stdout ?? "";
|
|
40
|
+
const lines = stdout.trim().split(/\r?\n/).filter(Boolean);
|
|
41
|
+
expect(lines.length).toBeGreaterThan(0);
|
|
42
|
+
for (const line of lines) {
|
|
43
|
+
expect(() => JSON.parse(line)).not.toThrow();
|
|
44
|
+
}
|
|
45
|
+
expect(JSON.parse(lines.at(-1)!)).toEqual(expect.objectContaining({
|
|
46
|
+
type: "error",
|
|
47
|
+
}));
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it } from "vitest";
|
|
2
|
-
|
|
3
|
-
import { ChatSession } from "../index.js";
|
|
4
|
-
import { config } from "../config.js";
|
|
5
|
-
|
|
6
|
-
const originalDeepSeekApiKey = process.env.DEEPSEEK_API_KEY;
|
|
7
|
-
const originalDeepCccApiKey = config.apiKey;
|
|
8
|
-
|
|
9
|
-
afterEach(() => {
|
|
10
|
-
if (originalDeepSeekApiKey === undefined) {
|
|
11
|
-
delete process.env.DEEPSEEK_API_KEY;
|
|
12
|
-
} else {
|
|
13
|
-
process.env.DEEPSEEK_API_KEY = originalDeepSeekApiKey;
|
|
14
|
-
}
|
|
15
|
-
config.apiKey = originalDeepCccApiKey;
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
describe("builtin ChatSession config", () => {
|
|
19
|
-
it("uses the builtin ~/.deepccc config when no apiKey is passed", () => {
|
|
20
|
-
expect(() => new ChatSession()).not.toThrow();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("allows constructor parameters to override config defaults", () => {
|
|
24
|
-
expect(() => new ChatSession({ apiKey: "sk-test" })).not.toThrow();
|
|
25
|
-
});
|
|
26
|
-
});
|
|
1
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { ChatSession } from "../index.js";
|
|
4
|
+
import { config } from "../config.js";
|
|
5
|
+
|
|
6
|
+
const originalDeepSeekApiKey = process.env.DEEPSEEK_API_KEY;
|
|
7
|
+
const originalDeepCccApiKey = config.apiKey;
|
|
8
|
+
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
if (originalDeepSeekApiKey === undefined) {
|
|
11
|
+
delete process.env.DEEPSEEK_API_KEY;
|
|
12
|
+
} else {
|
|
13
|
+
process.env.DEEPSEEK_API_KEY = originalDeepSeekApiKey;
|
|
14
|
+
}
|
|
15
|
+
config.apiKey = originalDeepCccApiKey;
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe("builtin ChatSession config", () => {
|
|
19
|
+
it("uses the builtin ~/.deepccc config when no apiKey is passed", () => {
|
|
20
|
+
expect(() => new ChatSession()).not.toThrow();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("allows constructor parameters to override config defaults", () => {
|
|
24
|
+
expect(() => new ChatSession({ apiKey: "sk-test" })).not.toThrow();
|
|
25
|
+
});
|
|
26
|
+
});
|