chatccc 0.2.241 → 0.2.242

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 (58) hide show
  1. package/bin/cccagent.mjs +1 -1
  2. package/deepccc-agent/LICENSE +201 -0
  3. package/deepccc-agent/README.md +291 -0
  4. package/deepccc-agent/bin/deepccc.mjs +26 -0
  5. package/deepccc-agent/docs/cache-hit-rate-1.jpg +0 -0
  6. package/deepccc-agent/docs/cache-hit-rate-2.jpg +0 -0
  7. package/deepccc-agent/package-lock.json +1959 -0
  8. package/deepccc-agent/package.json +62 -0
  9. package/deepccc-agent/src/__tests__/chat-session.test.ts +522 -0
  10. package/deepccc-agent/src/__tests__/cli-json.test.ts +49 -0
  11. package/deepccc-agent/src/__tests__/config.test.ts +26 -0
  12. package/deepccc-agent/src/__tests__/context.test.ts +319 -0
  13. package/deepccc-agent/src/__tests__/file-tools.test.ts +240 -0
  14. package/deepccc-agent/src/__tests__/permissions.test.ts +195 -0
  15. package/deepccc-agent/src/__tests__/privacy.test.ts +311 -0
  16. package/deepccc-agent/src/__tests__/progress-reducer.test.ts +121 -0
  17. package/deepccc-agent/src/__tests__/session-search.test.ts +262 -0
  18. package/deepccc-agent/src/__tests__/session-select.test.ts +116 -0
  19. package/deepccc-agent/src/__tests__/sigint.test.ts +56 -0
  20. package/deepccc-agent/src/__tests__/skills.test.ts +284 -0
  21. package/deepccc-agent/src/__tests__/terminal-renderer.test.ts +247 -0
  22. package/deepccc-agent/src/__tests__/web-tools.test.ts +220 -0
  23. package/deepccc-agent/tsconfig.build.json +13 -0
  24. package/deepccc-agent/tsconfig.json +13 -0
  25. package/deepccc-agent/vitest.config.ts +7 -0
  26. package/package.json +3 -1
  27. package/src/__tests__/builtin-chat-session.test.ts +17 -17
  28. package/src/__tests__/builtin-config.test.ts +2 -2
  29. package/src/__tests__/builtin-context.test.ts +1 -1
  30. package/src/__tests__/builtin-file-tools.test.ts +1 -1
  31. package/src/__tests__/builtin-permissions.test.ts +4 -4
  32. package/src/__tests__/builtin-session-search.test.ts +1 -1
  33. package/src/__tests__/builtin-session-select.test.ts +2 -2
  34. package/src/__tests__/builtin-sigint.test.ts +1 -1
  35. package/src/__tests__/builtin-skills.test.ts +1 -1
  36. package/src/__tests__/builtin-web-tools.test.ts +1 -1
  37. package/src/__tests__/progress-reducer.test.ts +1 -1
  38. package/src/adapters/ccc-adapter.ts +2 -2
  39. package/src/progress/reducer.ts +1 -1
  40. /package/{src/builtin → deepccc-agent/src}/cli.ts +0 -0
  41. /package/{src/builtin → deepccc-agent/src}/config.ts +0 -0
  42. /package/{src/builtin → deepccc-agent/src}/context.ts +0 -0
  43. /package/{src/builtin → deepccc-agent/src}/file-log.ts +0 -0
  44. /package/{src/builtin → deepccc-agent/src}/file-tools.ts +0 -0
  45. /package/{src/builtin → deepccc-agent/src}/index.ts +0 -0
  46. /package/{src/builtin → deepccc-agent/src}/permissions.ts +0 -0
  47. /package/{src/builtin → deepccc-agent/src}/privacy.ts +0 -0
  48. /package/{src/builtin → deepccc-agent/src}/proc-tree-kill.ts +0 -0
  49. /package/{src/builtin → deepccc-agent/src}/progress/cards-helpers.ts +0 -0
  50. /package/{src/builtin → deepccc-agent/src}/progress/reducer.ts +0 -0
  51. /package/{src/builtin → deepccc-agent/src}/progress/terminal-renderer.ts +0 -0
  52. /package/{src/builtin → deepccc-agent/src}/progress/view.ts +0 -0
  53. /package/{src/builtin → deepccc-agent/src}/raw-stream-log.ts +0 -0
  54. /package/{src/builtin → deepccc-agent/src}/session-search.ts +0 -0
  55. /package/{src/builtin → deepccc-agent/src}/session-select.ts +0 -0
  56. /package/{src/builtin → deepccc-agent/src}/sigint.ts +0 -0
  57. /package/{src/builtin → deepccc-agent/src}/skills.ts +0 -0
  58. /package/{src/builtin → deepccc-agent/src}/web-tools.ts +0 -0
@@ -0,0 +1,220 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import {
4
+ decodeDdgHref,
5
+ extractHtmlTitle,
6
+ htmlToPlainText,
7
+ parseDuckDuckGoHtml,
8
+ webFetchForTool,
9
+ webSearchForTool,
10
+ type FetchLike,
11
+ } from "../web-tools.js";
12
+
13
+ const DDG_HTML = `<!DOCTYPE html>
14
+ <html>
15
+ <head><title>Search results</title></head>
16
+ <body>
17
+ <div class="result results_links results_links_deep web-result">
18
+ <h2 class="result__title">
19
+ <a rel="nofollow" class="result__a" href="//duckduckgo.com/l/?uddg=https%3A%2F%2Fnodejs.org%2Fen%2Fdocs&rut=abc">Node.js <b>Docs</b></a>
20
+ </h2>
21
+ <a rel="nofollow" class="result__snippet" href="//duckduckgo.com/l/?uddg=...">Official documentation for Node.js &amp; npm.</a>
22
+ </div>
23
+ <div class="result">
24
+ <a rel="nofollow" class="result__a" href="https://example.com/page">Example &quot;quoted&quot; page</a>
25
+ <a rel="nofollow" class="result__snippet" href="https://example.com/page">A plain snippet without highlight.</a>
26
+ </div>
27
+ </body>
28
+ </html>`;
29
+
30
+ const WEB_FETCH_HTML = `<!DOCTYPE html>
31
+ <html><head><title>Fetch &amp; Me</title></head>
32
+ <body>
33
+ <style>.x { color: red }</style>
34
+ <script>alert("x")</script>
35
+ <h1>Hello World</h1>
36
+ <p>First paragraph with &amp; entity.</p>
37
+ <p>Second paragraph<br>with a break.</p>
38
+ <footer>bye</footer>
39
+ </body></html>`;
40
+
41
+ describe("parseDuckDuckGoHtml", () => {
42
+ it("extracts title, decoded url, and snippet per result", () => {
43
+ const results = parseDuckDuckGoHtml(DDG_HTML);
44
+ expect(results).toHaveLength(2);
45
+ expect(results[0]).toEqual({
46
+ title: "Node.js Docs",
47
+ url: "https://nodejs.org/en/docs",
48
+ snippet: "Official documentation for Node.js & npm.",
49
+ });
50
+ expect(results[1]).toEqual({
51
+ title: 'Example "quoted" page',
52
+ url: "https://example.com/page",
53
+ snippet: "A plain snippet without highlight.",
54
+ });
55
+ });
56
+
57
+ it("returns empty array for pages without results", () => {
58
+ expect(parseDuckDuckGoHtml("<html><body>no results here</body></html>")).toEqual([]);
59
+ });
60
+ });
61
+
62
+ describe("decodeDdgHref", () => {
63
+ it("decodes uddg redirect params and restores protocol", () => {
64
+ expect(
65
+ decodeDdgHref("//duckduckgo.com/l/?uddg=https%3A%2F%2Fnodejs.org%2Fen%2Fdocs&rut=abc"),
66
+ ).toBe("https://nodejs.org/en/docs");
67
+ });
68
+
69
+ it("passes through plain urls", () => {
70
+ expect(decodeDdgHref("https://example.com/a?b=1")).toBe("https://example.com/a?b=1");
71
+ });
72
+
73
+ it("returns input untouched when unparseable", () => {
74
+ expect(decodeDdgHref("not a url")).toBe("not a url");
75
+ });
76
+ });
77
+
78
+ describe("htmlToPlainText", () => {
79
+ it("strips scripts/styles, keeps block boundaries, decodes entities, compresses whitespace", () => {
80
+ const text = htmlToPlainText(WEB_FETCH_HTML);
81
+ expect(text).not.toContain("alert");
82
+ expect(text).not.toContain(".x {");
83
+ expect(text).toContain("Hello World");
84
+ expect(text).toContain("First paragraph with & entity.");
85
+ expect(text).toContain("Second paragraph\nwith a break.");
86
+ expect(text).toContain("bye");
87
+ // 段落间允许单个空行,但不得出现连续空行
88
+ expect(text).not.toContain("\n\n\n");
89
+ });
90
+ });
91
+
92
+ describe("extractHtmlTitle", () => {
93
+ it("extracts and decodes the title", () => {
94
+ expect(extractHtmlTitle(WEB_FETCH_HTML)).toBe("Fetch & Me");
95
+ });
96
+
97
+ it("returns empty string when no title", () => {
98
+ expect(extractHtmlTitle("<html><body>x</body></html>")).toBe("");
99
+ });
100
+ });
101
+
102
+ describe("webSearchForTool", () => {
103
+ function mockFetch(html: string, status = 200): FetchLike {
104
+ return async () =>
105
+ new Response(html, {
106
+ status,
107
+ headers: { "content-type": "text/html; charset=utf-8" },
108
+ });
109
+ }
110
+
111
+ it("returns parsed results from the search page", async () => {
112
+ const output = await webSearchForTool(
113
+ { query: "nodejs docs" },
114
+ { fetchImpl: mockFetch(DDG_HTML) },
115
+ );
116
+ expect(output.query).toBe("nodejs docs");
117
+ expect(output.results).toHaveLength(2);
118
+ expect(output.results[0].url).toBe("https://nodejs.org/en/docs");
119
+ expect(output.results[0].snippet).toContain("Node.js");
120
+ expect(typeof output.durationMs).toBe("number");
121
+ });
122
+
123
+ it("respects maxResults and caps at 10", async () => {
124
+ const html = Array.from({ length: 12 }, (_, i) => {
125
+ const title = `<a rel="nofollow" class="result__a" href="https://e.com/${i}">R${i}</a>`;
126
+ const snippet = `<a rel="nofollow" class="result__snippet" href="https://e.com/${i}">s${i}</a>`;
127
+ return `<div>${title}${snippet}</div>`;
128
+ }).join("");
129
+ const output = await webSearchForTool({ query: "many" }, { fetchImpl: mockFetch(html) });
130
+ expect(output.results).toHaveLength(5);
131
+ expect(output.truncated).toBe(true);
132
+
133
+ const output2 = await webSearchForTool({ query: "many", maxResults: 20 }, { fetchImpl: mockFetch(html) });
134
+ expect(output2.results).toHaveLength(10);
135
+ });
136
+
137
+ it("returns empty results (not an error) when the page has no matches", async () => {
138
+ const output = await webSearchForTool(
139
+ { query: "zzz-nothing" },
140
+ { fetchImpl: mockFetch("<html><body>no results</body></html>") },
141
+ );
142
+ expect(output.results).toEqual([]);
143
+ expect(output.truncated).toBe(false);
144
+ });
145
+
146
+ it("throws on empty query", async () => {
147
+ await expect(webSearchForTool({ query: " " }, { fetchImpl: mockFetch("") })).rejects.toThrow(
148
+ "query is required",
149
+ );
150
+ });
151
+
152
+ it("throws on non-2xx response", async () => {
153
+ await expect(
154
+ webSearchForTool({ query: "x" }, { fetchImpl: mockFetch("blocked", 429) }),
155
+ ).rejects.toThrow("HTTP 429");
156
+ });
157
+ });
158
+
159
+ describe("webFetchForTool", () => {
160
+ function mockFetch(html: string, status = 200, contentType = "text/html; charset=utf-8"): FetchLike {
161
+ return async () =>
162
+ new Response(html, {
163
+ status,
164
+ headers: { "content-type": contentType },
165
+ });
166
+ }
167
+
168
+ it("fetches and converts html to plain text with title", async () => {
169
+ const output = await webFetchForTool(
170
+ { url: "https://example.com/page" },
171
+ { fetchImpl: mockFetch(WEB_FETCH_HTML) },
172
+ );
173
+ expect(output.title).toBe("Fetch & Me");
174
+ expect(output.text).toContain("Hello World");
175
+ expect(output.text).toContain("Second paragraph\nwith a break.");
176
+ expect(output.text).not.toContain("alert");
177
+ expect(output.contentType).toContain("text/html");
178
+ expect(output.chars).toBe(output.text.length);
179
+ expect(output.truncated).toBe(false);
180
+ });
181
+
182
+ it("truncates text beyond maxChars", async () => {
183
+ const output = await webFetchForTool(
184
+ { url: "https://example.com/long", maxChars: 10 },
185
+ { fetchImpl: mockFetch("<p>hello world and more</p>") },
186
+ );
187
+ expect(output.text).toBe("hello worl");
188
+ expect(output.truncated).toBe(true);
189
+ expect(output.chars).toBe(10);
190
+ });
191
+
192
+ it("truncates oversized response bodies", async () => {
193
+ const big = `<!DOCTYPE html><html><body><p>${"a".repeat(600 * 1024)}</p></body></html>`;
194
+ const output = await webFetchForTool(
195
+ { url: "https://example.com/big" },
196
+ { fetchImpl: mockFetch(big) },
197
+ );
198
+ expect(output.truncated).toBe(true);
199
+ expect(output.text.length).toBeLessThan(600 * 1024);
200
+ });
201
+
202
+ it("rejects non-http(s) protocols", async () => {
203
+ await expect(
204
+ webFetchForTool({ url: "file:///etc/passwd" }, { fetchImpl: mockFetch("") }),
205
+ ).rejects.toThrow("unsupported protocol");
206
+ });
207
+
208
+ it("rejects invalid urls", async () => {
209
+ await expect(
210
+ webFetchForTool({ url: "not a url" }, { fetchImpl: mockFetch("") }),
211
+ ).rejects.toThrow("invalid URL");
212
+ });
213
+
214
+ it("throws on missing url and non-2xx", async () => {
215
+ await expect(webFetchForTool({ url: " " })).rejects.toThrow("url is required");
216
+ await expect(
217
+ webFetchForTool({ url: "https://example.com/404" }, { fetchImpl: mockFetch("nf", 404) }),
218
+ ).rejects.toThrow("HTTP 404");
219
+ });
220
+ });
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "noEmit": false,
5
+ "outDir": "./dist",
6
+ "rootDir": "./src",
7
+ "declaration": true,
8
+ "declarationMap": false,
9
+ "sourceMap": false
10
+ },
11
+ "include": ["src/*.ts"],
12
+ "exclude": ["src/__tests__/**"]
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "noEmit": true
11
+ },
12
+ "include": ["src/**/*.ts", "vitest.config.ts"]
13
+ }
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ include: ["src/__tests__/**/*.test.ts"],
6
+ },
7
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chatccc",
3
- "version": "0.2.241",
3
+ "version": "0.2.242",
4
4
  "description": "Feishu bot bridge for Claude Code",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -11,6 +11,7 @@
11
11
  },
12
12
  "files": [
13
13
  "src/",
14
+ "deepccc-agent/",
14
15
  "bin/",
15
16
  "scripts/postinstall-sharp-check.mjs",
16
17
  "demo/ilink_echo_probe.ts",
@@ -43,6 +44,7 @@
43
44
  "demo:ilink-echo": "tsx demo/ilink_echo_probe.ts",
44
45
  "claude-proxy": "tsx src/litellm-proxy.ts",
45
46
  "test": "vitest run",
47
+ "test:deepccc": "vitest run --root deepccc-agent",
46
48
  "test:watch": "vitest",
47
49
  "postinstall": "node scripts/postinstall-sharp-check.mjs"
48
50
  },
@@ -4,8 +4,8 @@ import { join } from "node:path";
4
4
 
5
5
  import { afterEach, describe, expect, it, vi } from "vitest";
6
6
 
7
- import { config } from "../builtin/config.ts";
8
- import { estimateBuiltinContextTokens } from "../builtin/context.ts";
7
+ import { config } from "../../deepccc-agent/src/config.ts";
8
+ import { estimateBuiltinContextTokens } from "../../deepccc-agent/src/context.ts";
9
9
 
10
10
  const streamTextMock = vi.fn();
11
11
  const generateTextMock = vi.fn();
@@ -27,7 +27,7 @@ vi.mock("ai", () => ({
27
27
  tool: vi.fn((definition: unknown) => definition),
28
28
  }));
29
29
 
30
- vi.mock("../builtin/raw-stream-log.js", () => ({
30
+ vi.mock("../../deepccc-agent/src/raw-stream-log.js", () => ({
31
31
  createRawStreamLog: createRawStreamLogMock,
32
32
  }));
33
33
 
@@ -57,7 +57,7 @@ afterEach(() => {
57
57
 
58
58
  describe("ChatSession context management", () => {
59
59
  it("keeps the generalized evidence gate in the stable system prompt prefix", async () => {
60
- const { ChatSession } = await import("../builtin/index.ts");
60
+ const { ChatSession } = await import("../../deepccc-agent/src/index.ts");
61
61
  const dir = await mkdtemp(join(tmpdir(), "deepccc-session-evidence-gate-"));
62
62
  await writeFile(join(dir, "AGENTS.md"), "PROJECT GUIDANCE MARKER", "utf-8");
63
63
  streamTextMock.mockReturnValueOnce({ textStream: textStream("done") });
@@ -93,7 +93,7 @@ describe("ChatSession context management", () => {
93
93
  });
94
94
 
95
95
  it("keeps execution discipline sections in the stable system prompt prefix", async () => {
96
- const { ChatSession } = await import("../builtin/index.ts");
96
+ const { ChatSession } = await import("../../deepccc-agent/src/index.ts");
97
97
  const dir = await mkdtemp(join(tmpdir(), "deepccc-session-discipline-"));
98
98
  await writeFile(join(dir, "AGENTS.md"), "PROJECT GUIDANCE MARKER", "utf-8");
99
99
  streamTextMock.mockReturnValueOnce({ textStream: textStream("done") });
@@ -130,7 +130,7 @@ describe("ChatSession context management", () => {
130
130
  });
131
131
 
132
132
  it("injects cwd project instruction files before runtime workspace details", async () => {
133
- const { ChatSession } = await import("../builtin/index.ts");
133
+ const { ChatSession } = await import("../../deepccc-agent/src/index.ts");
134
134
  const dir = await mkdtemp(join(tmpdir(), "deepccc-session-instructions-"));
135
135
  await writeFile(join(dir, "AGENTS.md"), "agents root guidance", "utf-8");
136
136
  await writeFile(join(dir, "AGENTS.local.md"), "agents local guidance", "utf-8");
@@ -165,7 +165,7 @@ describe("ChatSession context management", () => {
165
165
  });
166
166
 
167
167
  it("places the volatile skills index at the very end of system prompt", async () => {
168
- const { ChatSession } = await import("../builtin/index.ts");
168
+ const { ChatSession } = await import("../../deepccc-agent/src/index.ts");
169
169
  const dir = await mkdtemp(join(tmpdir(), "deepccc-session-skill-order-"));
170
170
  const skillsDir = join(dir, "skills");
171
171
  await mkdir(join(skillsDir, "demo-skill"), { recursive: true });
@@ -199,7 +199,7 @@ describe("ChatSession context management", () => {
199
199
  });
200
200
 
201
201
  it("does not read project instruction files from parent directories", async () => {
202
- const { ChatSession } = await import("../builtin/index.ts");
202
+ const { ChatSession } = await import("../../deepccc-agent/src/index.ts");
203
203
  const parent = await mkdtemp(join(tmpdir(), "deepccc-session-parent-instructions-"));
204
204
  const child = join(parent, "child");
205
205
  await mkdir(child);
@@ -220,7 +220,7 @@ describe("ChatSession context management", () => {
220
220
  });
221
221
 
222
222
  it("uses loop-finished stopping by default", async () => {
223
- const { ChatSession } = await import("../builtin/index.ts");
223
+ const { ChatSession } = await import("../../deepccc-agent/src/index.ts");
224
224
  const dir = await mkdtemp(join(tmpdir(), "deepccc-session-unlimited-"));
225
225
  streamTextMock.mockReturnValueOnce({ textStream: textStream("done") });
226
226
 
@@ -239,7 +239,7 @@ describe("ChatSession context management", () => {
239
239
  });
240
240
 
241
241
  it("uses a configured tool step limit when provided", async () => {
242
- const { ChatSession } = await import("../builtin/index.ts");
242
+ const { ChatSession } = await import("../../deepccc-agent/src/index.ts");
243
243
  const dir = await mkdtemp(join(tmpdir(), "deepccc-session-step-budget-"));
244
244
  streamTextMock.mockReturnValueOnce({ textStream: textStream("done") });
245
245
 
@@ -259,7 +259,7 @@ describe("ChatSession context management", () => {
259
259
  });
260
260
 
261
261
  it("loads persisted context, compacts older messages, and persists the new assistant reply", async () => {
262
- const { ChatSession } = await import("../builtin/index.ts");
262
+ const { ChatSession } = await import("../../deepccc-agent/src/index.ts");
263
263
  const dir = await mkdtemp(join(tmpdir(), "deepccc-session-context-"));
264
264
 
265
265
  const seed = new ChatSession(
@@ -307,7 +307,7 @@ describe("ChatSession context management", () => {
307
307
 
308
308
  it("times out context compaction independently before reply generation", async () => {
309
309
  vi.useFakeTimers();
310
- const { ChatSession } = await import("../builtin/index.ts");
310
+ const { ChatSession } = await import("../../deepccc-agent/src/index.ts");
311
311
  const dir = await mkdtemp(join(tmpdir(), "deepccc-session-compaction-timeout-"));
312
312
  const seed = new ChatSession(
313
313
  { apiKey: "sk-test" },
@@ -341,7 +341,7 @@ describe("ChatSession context management", () => {
341
341
  });
342
342
 
343
343
  it("streams tool calls and tool results from fullStream", async () => {
344
- const { ChatSession } = await import("../builtin/index.ts");
344
+ const { ChatSession } = await import("../../deepccc-agent/src/index.ts");
345
345
  const dir = await mkdtemp(join(tmpdir(), "deepccc-session-tools-"));
346
346
  const session = new ChatSession(
347
347
  { apiKey: "sk-test" },
@@ -379,7 +379,7 @@ describe("ChatSession context management", () => {
379
379
  });
380
380
 
381
381
  it("caps the total persisted tool transcript for a turn", async () => {
382
- const { ChatSession } = await import("../builtin/index.ts");
382
+ const { ChatSession } = await import("../../deepccc-agent/src/index.ts");
383
383
  const dir = await mkdtemp(join(tmpdir(), "deepccc-session-tool-cap-"));
384
384
  const session = new ChatSession(
385
385
  { apiKey: "sk-test" },
@@ -403,7 +403,7 @@ describe("ChatSession context management", () => {
403
403
  });
404
404
 
405
405
  it("persists structured tool calls alongside the text transcript", async () => {
406
- const { ChatSession } = await import("../builtin/index.ts");
406
+ const { ChatSession } = await import("../../deepccc-agent/src/index.ts");
407
407
  const dir = await mkdtemp(join(tmpdir(), "deepccc-session-structured-tools-"));
408
408
  const session = new ChatSession(
409
409
  { apiKey: "sk-test" },
@@ -430,7 +430,7 @@ describe("ChatSession context management", () => {
430
430
  });
431
431
 
432
432
  it("records tool errors and preserves tool call order in structured tool calls", async () => {
433
- const { ChatSession } = await import("../builtin/index.ts");
433
+ const { ChatSession } = await import("../../deepccc-agent/src/index.ts");
434
434
  const dir = await mkdtemp(join(tmpdir(), "deepccc-session-structured-tools-order-"));
435
435
  const session = new ChatSession(
436
436
  { apiKey: "sk-test" },
@@ -459,7 +459,7 @@ describe("ChatSession context management", () => {
459
459
  });
460
460
 
461
461
  it("writes raw DeepCCC fullStream parts when raw stream logs are enabled", async () => {
462
- const { ChatSession } = await import("../builtin/index.ts");
462
+ const { ChatSession } = await import("../../deepccc-agent/src/index.ts");
463
463
  config.rawStreamLogs = {
464
464
  enabled: true,
465
465
  maxBytesPerTurn: 4096,
@@ -1,7 +1,7 @@
1
1
  import { afterEach, describe, expect, it } from "vitest";
2
2
 
3
- import { ChatSession } from "../builtin/index.ts";
4
- import { config } from "../builtin/config.ts";
3
+ import { ChatSession } from "../../deepccc-agent/src/index.ts";
4
+ import { config } from "../../deepccc-agent/src/config.ts";
5
5
 
6
6
  const originalDeepSeekApiKey = process.env.DEEPSEEK_API_KEY;
7
7
  const originalDeepCccApiKey = config.apiKey;
@@ -12,7 +12,7 @@ import {
12
12
  listBuiltinContextSessions,
13
13
  newBuiltinSessionId,
14
14
  serializeMessagesForSummary,
15
- } from "../builtin/context.ts";
15
+ } from "../../deepccc-agent/src/context.ts";
16
16
 
17
17
  describe("BuiltinContextManager", () => {
18
18
  it("keeps recent messages within the token budget instead of a fixed count", () => {
@@ -18,7 +18,7 @@ import {
18
18
  readFileForTool,
19
19
  runCommandForTool,
20
20
  searchCodeForTool,
21
- } from "../builtin/file-tools.ts";
21
+ } from "../../deepccc-agent/src/file-tools.ts";
22
22
 
23
23
  const execFileAsync = promisify(execFile);
24
24
  const tempDirs: string[] = [];
@@ -31,7 +31,7 @@ vi.mock("ai", () => ({
31
31
  tool: vi.fn((definition: unknown) => definition),
32
32
  }));
33
33
 
34
- vi.mock("../builtin/raw-stream-log.ts", () => ({
34
+ vi.mock("../../deepccc-agent/src/raw-stream-log.ts", () => ({
35
35
  createRawStreamLog: vi.fn().mockResolvedValue(null),
36
36
  }));
37
37
 
@@ -41,9 +41,9 @@ import {
41
41
  isDangerousCommand,
42
42
  matchRule,
43
43
  reloadAllowRules,
44
- } from "../builtin/permissions.ts";
45
- import { createBuiltinFileTools } from "../builtin/file-tools.ts";
46
- import { ChatSession } from "../builtin/index.ts";
44
+ } from "../../deepccc-agent/src/permissions.ts";
45
+ import { createBuiltinFileTools } from "../../deepccc-agent/src/file-tools.ts";
46
+ import { ChatSession } from "../../deepccc-agent/src/index.ts";
47
47
 
48
48
  const streamTextMock = aiMocks.streamText;
49
49
  const generateTextMock = aiMocks.generateText;
@@ -5,7 +5,7 @@ import { gzipSync } from "node:zlib";
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
 
8
- import { searchBuiltinSessions } from "../builtin/session-search.ts";
8
+ import { searchBuiltinSessions } from "../../deepccc-agent/src/session-search.ts";
9
9
 
10
10
  interface TestMessage {
11
11
  role: "user" | "assistant";
@@ -4,8 +4,8 @@ import { join } from "node:path";
4
4
 
5
5
  import { describe, expect, it } from "vitest";
6
6
 
7
- import { defaultBuiltinSessionId } from "../builtin/context.ts";
8
- import { resolveBuiltinSession } from "../builtin/session-select.ts";
7
+ import { defaultBuiltinSessionId } from "../../deepccc-agent/src/context.ts";
8
+ import { resolveBuiltinSession } from "../../deepccc-agent/src/session-select.ts";
9
9
 
10
10
  async function writeSession(
11
11
  contextDir: string,
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
 
3
- import { createCtrlCState } from "../builtin/sigint.ts";
3
+ import { createCtrlCState } from "../../deepccc-agent/src/sigint.ts";
4
4
 
5
5
  describe("builtin CLI Ctrl+C state", () => {
6
6
  it("requires two presses to interrupt an active generation", () => {
@@ -13,7 +13,7 @@ import {
13
13
  type SkillDirSpec,
14
14
  type SkillSource,
15
15
  type SkillScope,
16
- } from "../builtin/skills.ts";
16
+ } from "../../deepccc-agent/src/skills.ts";
17
17
 
18
18
  let tempRoot: string;
19
19
 
@@ -8,7 +8,7 @@ import {
8
8
  webFetchForTool,
9
9
  webSearchForTool,
10
10
  type FetchLike,
11
- } from "../builtin/web-tools.ts";
11
+ } from "../../deepccc-agent/src/web-tools.ts";
12
12
 
13
13
  const DDG_HTML = `<!DOCTYPE html>
14
14
  <html>
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
 
3
- import type { ChatEvent } from "../builtin/index.ts";
3
+ import type { ChatEvent } from "../../deepccc-agent/src/index.ts";
4
4
  import { reduceProgress, summarizeToolInput, summarizeToolResult } from "../progress/reducer.ts";
5
5
  import { progressView } from "../progress/view.ts";
6
6
 
@@ -1,9 +1,9 @@
1
- import { ChatSession, type ChatSessionConfig, type ChatSessionOptions } from "../builtin/index.ts";
1
+ import { ChatSession, type ChatSessionConfig, type ChatSessionOptions } from "../../deepccc-agent/src/index.ts";
2
2
  import {
3
3
  getBuiltinContextSession,
4
4
  newBuiltinSessionId,
5
5
  normalizeBuiltinSessionId,
6
- } from "../builtin/context.ts";
6
+ } from "../../deepccc-agent/src/context.ts";
7
7
  import { config, CCC_SESSION_PREFIX } from "../config.ts";
8
8
  import type {
9
9
  CreateSessionResult,
@@ -7,7 +7,7 @@
7
7
  * 看到的过程状态(正文累积、工具调用、终态判定)完全一致。
8
8
  */
9
9
 
10
- import type { ChatEvent } from "../builtin/index.ts";
10
+ import type { ChatEvent } from "../../deepccc-agent/src/index.ts";
11
11
  import {
12
12
  withProgressView,
13
13
  type ProgressToolCall,
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes