deepccc 0.2.25 → 0.2.26
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 +3 -3
- package/bin/deepccc-cli.mjs +17 -17
- package/bin/deepccc.mjs +32 -32
- package/dist/completion-session.js +5 -3
- package/dist/decision-session.js +5 -3
- package/dist/json-mode-fetch.d.ts +2 -0
- package/dist/json-mode-fetch.js +12 -0
- package/dist/web-page.js +411 -411
- package/docs/completion-session.md +40 -36
- package/docs/decision-session.md +196 -192
- package/docs/workspace-understanding.md +41 -41
- package/os-prompts/darwin.md +8 -8
- package/os-prompts/linux.md +8 -8
- package/os-prompts/win32.md +11 -11
- package/package.json +68 -68
package/README.md
CHANGED
|
@@ -57,9 +57,9 @@ npm run dev
|
|
|
57
57
|
|
|
58
58
|

|
|
59
59
|
|
|
60
|
-
## 核心能力
|
|
61
|
-
|
|
62
|
-
- 有界结构化决策:程序化 `DecisionSession` 支持外部管理上下文、显式工具白名单、运行时结果校验和整轮截止时间;不改变默认聊天行为。详见 [接入文档](docs/decision-session.md)。
|
|
60
|
+
## 核心能力
|
|
61
|
+
|
|
62
|
+
- 有界结构化决策:程序化 `DecisionSession` 支持外部管理上下文、显式工具白名单、运行时结果校验和整轮截止时间;不改变默认聊天行为。详见 [接入文档](docs/decision-session.md)。
|
|
63
63
|
|
|
64
64
|
- Web-first:多会话、持久化历史、实时流式过程、停止和恢复
|
|
65
65
|
- 工具时间线:ChatCCC 风格 emoji 摘要、参数/结果折叠、省略行展开和状态记忆
|
package/bin/deepccc-cli.mjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
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
|
-
let args;
|
|
11
|
-
if (existsSync(distCli)) {
|
|
12
|
-
args = [distCli, ...process.argv.slice(2)];
|
|
13
|
-
} else {
|
|
14
|
-
args = [require.resolve("tsx/cli"), join(pkgRoot, "src", "cli.ts"), ...process.argv.slice(2)];
|
|
15
|
-
}
|
|
16
|
-
const result = spawnSync(process.execPath, args, { stdio: "inherit", cwd: process.cwd(), env: process.env });
|
|
17
|
-
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
|
+
let args;
|
|
11
|
+
if (existsSync(distCli)) {
|
|
12
|
+
args = [distCli, ...process.argv.slice(2)];
|
|
13
|
+
} else {
|
|
14
|
+
args = [require.resolve("tsx/cli"), join(pkgRoot, "src", "cli.ts"), ...process.argv.slice(2)];
|
|
15
|
+
}
|
|
16
|
+
const result = spawnSync(process.execPath, args, { stdio: "inherit", cwd: process.cwd(), env: process.env });
|
|
17
|
+
process.exit(result.status === null ? 1 : result.status);
|
package/bin/deepccc.mjs
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
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 rawArgs = process.argv.slice(2);
|
|
10
|
-
const distWebEntry = join(pkgRoot, "dist", "web-entry.js");
|
|
11
|
-
const distCli = join(pkgRoot, "dist", "cli.js");
|
|
12
|
-
const sourceMode = !existsSync(distWebEntry);
|
|
13
|
-
const isLegacy = rawArgs.length > 0 && rawArgs[0] !== "web" && !["--reuse-existing", "--port", "--no-open", "--help", "-h"].includes(rawArgs[0]);
|
|
14
|
-
|
|
15
|
-
if (isLegacy) {
|
|
16
|
-
console.error("[DeepCCC] CLI commands have moved to deepccc-cli; forwarding this invocation for compatibility.");
|
|
17
|
-
const args = sourceMode
|
|
18
|
-
? [require.resolve("tsx/cli"), join(pkgRoot, "src", "cli.ts"), ...rawArgs]
|
|
19
|
-
: [distCli, ...rawArgs];
|
|
20
|
-
const result = spawnSync(process.execPath, args, { stdio: "inherit", cwd: process.cwd(), env: process.env });
|
|
21
|
-
process.exit(result.status === null ? 1 : result.status);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (sourceMode) {
|
|
25
|
-
const result = spawnSync(process.execPath, [require.resolve("tsx/cli"), join(pkgRoot, "src", "web-entry.ts"), ...rawArgs], {
|
|
26
|
-
stdio: "inherit", cwd: process.cwd(), env: process.env,
|
|
27
|
-
});
|
|
28
|
-
process.exit(result.status === null ? 1 : result.status);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const { runWebEntry } = await import(new URL("../dist/web-entry.js", import.meta.url));
|
|
32
|
-
await runWebEntry(rawArgs);
|
|
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 rawArgs = process.argv.slice(2);
|
|
10
|
+
const distWebEntry = join(pkgRoot, "dist", "web-entry.js");
|
|
11
|
+
const distCli = join(pkgRoot, "dist", "cli.js");
|
|
12
|
+
const sourceMode = !existsSync(distWebEntry);
|
|
13
|
+
const isLegacy = rawArgs.length > 0 && rawArgs[0] !== "web" && !["--reuse-existing", "--port", "--no-open", "--help", "-h"].includes(rawArgs[0]);
|
|
14
|
+
|
|
15
|
+
if (isLegacy) {
|
|
16
|
+
console.error("[DeepCCC] CLI commands have moved to deepccc-cli; forwarding this invocation for compatibility.");
|
|
17
|
+
const args = sourceMode
|
|
18
|
+
? [require.resolve("tsx/cli"), join(pkgRoot, "src", "cli.ts"), ...rawArgs]
|
|
19
|
+
: [distCli, ...rawArgs];
|
|
20
|
+
const result = spawnSync(process.execPath, args, { stdio: "inherit", cwd: process.cwd(), env: process.env });
|
|
21
|
+
process.exit(result.status === null ? 1 : result.status);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (sourceMode) {
|
|
25
|
+
const result = spawnSync(process.execPath, [require.resolve("tsx/cli"), join(pkgRoot, "src", "web-entry.ts"), ...rawArgs], {
|
|
26
|
+
stdio: "inherit", cwd: process.cwd(), env: process.env,
|
|
27
|
+
});
|
|
28
|
+
process.exit(result.status === null ? 1 : result.status);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const { runWebEntry } = await import(new URL("../dist/web-entry.js", import.meta.url));
|
|
32
|
+
await runWebEntry(rawArgs);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** Opt-in stateless completion transport for integrations owning their complete prompts. */
|
|
2
2
|
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
|
3
|
-
import {
|
|
3
|
+
import { streamText } from 'ai';
|
|
4
|
+
import { jsonObjectFetch } from './json-mode-fetch.js';
|
|
4
5
|
const protectedKeys = new Set(['messages', 'model', 'stream', 'tools', 'tool_choice', 'response_format', 'temperature', 'max_tokens', 'max_completion_tokens']);
|
|
5
6
|
function positive(n) { if (!Number.isSafeInteger(n) || n < 1)
|
|
6
7
|
throw new Error('Positive integer budget required'); return n; }
|
|
@@ -45,11 +46,12 @@ export class CompletionSession {
|
|
|
45
46
|
try {
|
|
46
47
|
if (controller.signal.aborted)
|
|
47
48
|
throw new Error('Interrupted');
|
|
49
|
+
const transport = request.json ? jsonObjectFetch() : globalThis.fetch;
|
|
48
50
|
const client = createOpenAICompatible({ name: 'completion', ...this.config, includeUsage: true,
|
|
49
|
-
fetch: async (url, init) =>
|
|
51
|
+
fetch: async (url, init) => transport(url, { ...init, body: JSON.stringify({ ...JSON.parse(String(init?.body)), ...extensions }) }) });
|
|
50
52
|
calls++;
|
|
51
53
|
const result = streamText({ model: client(this.config.model), messages, allowSystemInMessages: true, temperature: request.temperature, maxOutputTokens: request.maxOutputTokens,
|
|
52
|
-
|
|
54
|
+
maxRetries: 0, abortSignal: controller.signal, onError: () => { } });
|
|
53
55
|
const iterator = result.fullStream[Symbol.asyncIterator]();
|
|
54
56
|
let content = '', reasoning = '', finish;
|
|
55
57
|
try {
|
package/dist/decision-session.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/** Bounded, text-only decisions with caller-owned context and explicit capabilities. */
|
|
2
2
|
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
|
3
3
|
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
4
|
-
import { asSchema,
|
|
4
|
+
import { asSchema, streamText, tool } from "ai";
|
|
5
|
+
import { jsonObjectFetch } from "./json-mode-fetch.js";
|
|
5
6
|
import { parseJsonResponse } from "./json-response.js";
|
|
6
7
|
import { performance } from "node:perf_hooks";
|
|
7
8
|
import { config, normalizeDeepCccProvider } from "./config.js";
|
|
@@ -92,7 +93,8 @@ export class DecisionSession {
|
|
|
92
93
|
const baseURL = overrides.baseURL ?? config.baseURL;
|
|
93
94
|
const client = provider === "anthropic"
|
|
94
95
|
? createAnthropic({ apiKey, baseURL: baseURL.trim().replace(/\/+$/, "") })
|
|
95
|
-
: createOpenAICompatible({ name: "deepccc", apiKey, baseURL, includeUsage: true
|
|
96
|
+
: createOpenAICompatible({ name: "deepccc", apiKey, baseURL, includeUsage: true,
|
|
97
|
+
...(this.outputMode === "json" ? { fetch: jsonObjectFetch() } : {}) });
|
|
96
98
|
this.model = client(overrides.model ?? config.model);
|
|
97
99
|
const effort = (overrides.effort ?? config.effort ?? "").trim();
|
|
98
100
|
this.providerOptions = effort ? provider === "anthropic"
|
|
@@ -240,7 +242,7 @@ export class DecisionSession {
|
|
|
240
242
|
const began = performance.now();
|
|
241
243
|
metrics.modelCalls++;
|
|
242
244
|
const result = streamText({ model: this.model, system: this.system, messages: [...messages],
|
|
243
|
-
...(this.outputMode === "json" ? {
|
|
245
|
+
...(this.outputMode === "json" ? {} : { tools: this.modelTools, toolChoice: "required" }),
|
|
244
246
|
maxRetries: 0, abortSignal: signal, maxOutputTokens: this.maxOutputTokens,
|
|
245
247
|
// The SDK default logs raw errors. Return allowlisted diagnostics instead.
|
|
246
248
|
onError: () => { },
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Protocol JSON mode without client-side parsing of partial objects. */
|
|
2
|
+
export function jsonObjectFetch(transport = globalThis.fetch) {
|
|
3
|
+
return async (input, init) => {
|
|
4
|
+
if (typeof init?.body !== "string")
|
|
5
|
+
throw new Error("JSON mode requires a serialized request body");
|
|
6
|
+
const body = JSON.parse(init.body);
|
|
7
|
+
return transport(input, {
|
|
8
|
+
...init,
|
|
9
|
+
body: JSON.stringify({ ...body, response_format: { type: "json_object" } }),
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
}
|