@deepwhale/coding-agent 1.0.0
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/bin/deepwhale.js +299 -0
- package/dist/agent/agent-compaction.d.ts +74 -0
- package/dist/agent/agent-compaction.d.ts.map +1 -0
- package/dist/agent/agent-compaction.js +145 -0
- package/dist/agent/agent-compaction.js.map +1 -0
- package/dist/agent/index.d.ts +16 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +17 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/session-adapter.d.ts +177 -0
- package/dist/agent/session-adapter.d.ts.map +1 -0
- package/dist/agent/session-adapter.js +340 -0
- package/dist/agent/session-adapter.js.map +1 -0
- package/dist/agent/tool-loop.d.ts +123 -0
- package/dist/agent/tool-loop.d.ts.map +1 -0
- package/dist/agent/tool-loop.js +425 -0
- package/dist/agent/tool-loop.js.map +1 -0
- package/dist/env/load-project-env.d.ts +40 -0
- package/dist/env/load-project-env.d.ts.map +1 -0
- package/dist/env/load-project-env.js +80 -0
- package/dist/env/load-project-env.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/llm-factory.d.ts +47 -0
- package/dist/llm-factory.d.ts.map +1 -0
- package/dist/llm-factory.js +88 -0
- package/dist/llm-factory.js.map +1 -0
- package/dist/modes/index.d.ts +14 -0
- package/dist/modes/index.d.ts.map +1 -0
- package/dist/modes/index.js +14 -0
- package/dist/modes/index.js.map +1 -0
- package/dist/modes/print.d.ts +50 -0
- package/dist/modes/print.d.ts.map +1 -0
- package/dist/modes/print.js +236 -0
- package/dist/modes/print.js.map +1 -0
- package/dist/modes/rpc.d.ts +52 -0
- package/dist/modes/rpc.d.ts.map +1 -0
- package/dist/modes/rpc.js +316 -0
- package/dist/modes/rpc.js.map +1 -0
- package/dist/modes/tui.d.ts +54 -0
- package/dist/modes/tui.d.ts.map +1 -0
- package/dist/modes/tui.js +361 -0
- package/dist/modes/tui.js.map +1 -0
- package/dist/policy/args-digest.d.ts +13 -0
- package/dist/policy/args-digest.d.ts.map +1 -0
- package/dist/policy/args-digest.js +29 -0
- package/dist/policy/args-digest.js.map +1 -0
- package/dist/policy/chain.d.ts +19 -0
- package/dist/policy/chain.d.ts.map +1 -0
- package/dist/policy/chain.js +24 -0
- package/dist/policy/chain.js.map +1 -0
- package/dist/policy/sanitize-reason.d.ts +11 -0
- package/dist/policy/sanitize-reason.d.ts.map +1 -0
- package/dist/policy/sanitize-reason.js +24 -0
- package/dist/policy/sanitize-reason.js.map +1 -0
- package/dist/policy/static-rules.d.ts +32 -0
- package/dist/policy/static-rules.d.ts.map +1 -0
- package/dist/policy/static-rules.js +106 -0
- package/dist/policy/static-rules.js.map +1 -0
- package/dist/policy/types.d.ts +56 -0
- package/dist/policy/types.d.ts.map +1 -0
- package/dist/policy/types.js +13 -0
- package/dist/policy/types.js.map +1 -0
- package/dist/repl/repl-confirm.d.ts +49 -0
- package/dist/repl/repl-confirm.d.ts.map +1 -0
- package/dist/repl/repl-confirm.js +88 -0
- package/dist/repl/repl-confirm.js.map +1 -0
- package/dist/repl.d.ts +126 -0
- package/dist/repl.d.ts.map +1 -0
- package/dist/repl.js +734 -0
- package/dist/repl.js.map +1 -0
- package/dist/sandbox/docker-runner.d.ts +147 -0
- package/dist/sandbox/docker-runner.d.ts.map +1 -0
- package/dist/sandbox/docker-runner.js +426 -0
- package/dist/sandbox/docker-runner.js.map +1 -0
- package/dist/sandbox/env-gate.d.ts +28 -0
- package/dist/sandbox/env-gate.d.ts.map +1 -0
- package/dist/sandbox/env-gate.js +65 -0
- package/dist/sandbox/env-gate.js.map +1 -0
- package/dist/sandbox/local-runner.d.ts +29 -0
- package/dist/sandbox/local-runner.d.ts.map +1 -0
- package/dist/sandbox/local-runner.js +79 -0
- package/dist/sandbox/local-runner.js.map +1 -0
- package/dist/sandbox/types.d.ts +80 -0
- package/dist/sandbox/types.d.ts.map +1 -0
- package/dist/sandbox/types.js +25 -0
- package/dist/sandbox/types.js.map +1 -0
- package/dist/tools/bash.d.ts +35 -0
- package/dist/tools/bash.d.ts.map +1 -0
- package/dist/tools/bash.js +233 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/edit-file.d.ts +22 -0
- package/dist/tools/edit-file.d.ts.map +1 -0
- package/dist/tools/edit-file.js +79 -0
- package/dist/tools/edit-file.js.map +1 -0
- package/dist/tools/find.d.ts +21 -0
- package/dist/tools/find.d.ts.map +1 -0
- package/dist/tools/find.js +168 -0
- package/dist/tools/find.js.map +1 -0
- package/dist/tools/grep.d.ts +19 -0
- package/dist/tools/grep.d.ts.map +1 -0
- package/dist/tools/grep.js +170 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +10 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/read-file.d.ts +18 -0
- package/dist/tools/read-file.d.ts.map +1 -0
- package/dist/tools/read-file.js +52 -0
- package/dist/tools/read-file.js.map +1 -0
- package/dist/tools/registry.d.ts +39 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +67 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/write-file.d.ts +18 -0
- package/dist/tools/write-file.d.ts.map +1 -0
- package/dist/tools/write-file.js +47 -0
- package/dist/tools/write-file.js.map +1 -0
- package/dist/types.d.ts +89 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/verify/format-report.d.ts +57 -0
- package/dist/verify/format-report.d.ts.map +1 -0
- package/dist/verify/format-report.js +128 -0
- package/dist/verify/format-report.js.map +1 -0
- package/dist/verify/index.d.ts +8 -0
- package/dist/verify/index.d.ts.map +1 -0
- package/dist/verify/index.js +8 -0
- package/dist/verify/index.js.map +1 -0
- package/dist/verify/verify-runner.d.ts +125 -0
- package/dist/verify/verify-runner.d.ts.map +1 -0
- package/dist/verify/verify-runner.js +524 -0
- package/dist/verify/verify-runner.js.map +1 -0
- package/package.json +30 -0
package/bin/deepwhale.js
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* deepwhale CLI 入口 — Sprint 1a
|
|
4
|
+
*
|
|
5
|
+
* 3 种运行模式:
|
|
6
|
+
* deepwhale # interactive REPL(默认)
|
|
7
|
+
* deepwhale -p "..." # print 模式:一次性 chat + tool loop
|
|
8
|
+
* deepwhale --rpc # RPC 模式:NDJSON over stdio(Sprint 1a stub)
|
|
9
|
+
*
|
|
10
|
+
* Sprint 0.3 极简:只启动 REPL。Sprint 1a 加 3 模式路由。
|
|
11
|
+
*
|
|
12
|
+
* 通用参数:
|
|
13
|
+
* --session <path> JSONL 持久化路径
|
|
14
|
+
* --provider <name> 显式 provider (deepseek | anthropic); 走 createDefaultClient
|
|
15
|
+
* 的 env 推断会被覆盖. 拍板 2026-06-04 review P2: 之前
|
|
16
|
+
* 解析没接, --provider 走 'unknown flag' 分支当 print prompt.
|
|
17
|
+
* --model <id> 显式 model id. 跟 createDefaultClient 的 model 字段对接.
|
|
18
|
+
* --no-tool-loop 退化到 Sprint 0.3 单轮 chat(不调工具)
|
|
19
|
+
* --max-steps <n> 工具循环上限(默认 5)
|
|
20
|
+
* --yes Sprint 1c-revive-3-D-13 (2026-06-05): bypass require_confirmation
|
|
21
|
+
* (write_file / edit_file / 危险 bash), 不 bypass deny.
|
|
22
|
+
* --version | -v 输出版本
|
|
23
|
+
* --help | -h 输出帮助
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { resolve as pathResolve } from 'node:path';
|
|
27
|
+
import process from 'node:process';
|
|
28
|
+
// Sprint 1c-revive-2-D-7 (review, 2026-06-04): 启动时加载项目根 .env (补缺不覆盖,
|
|
29
|
+
// CI / shell export 优先级最高). 必须在 import dist 之前调, 让 createDefaultClient
|
|
30
|
+
// factory 看到 process.env['DEEPSEEK_API_KEY'] / ['ANTHROPIC_AUTH_TOKEN'] 已就位.
|
|
31
|
+
import { loadProjectEnv } from '../dist/env/load-project-env.js';
|
|
32
|
+
loadProjectEnv();
|
|
33
|
+
import { startRepl } from '../dist/index.js';
|
|
34
|
+
import { runPrintMode } from '../dist/modes/print.js';
|
|
35
|
+
import { runRpcMode } from '../dist/modes/rpc.js';
|
|
36
|
+
import { runTuiMode } from '../dist/modes/tui.js';
|
|
37
|
+
import { runVerify } from '../dist/verify/index.js';
|
|
38
|
+
import { buildSummaryAndNext, formatReport } from '../dist/verify/index.js';
|
|
39
|
+
// Sprint 1c-revive-4-D-20.1 (2026-06-05): 友好错误处理.
|
|
40
|
+
// - APIKeyMissingError: REPL/print/rpc/tui 缺 key 时 → 印 setup hint + exit 2.
|
|
41
|
+
// - "invalid DEEPWHALE_SANDBOX=..." / "invalid DEEPWHALE_DOCKER_NETWORK=...":
|
|
42
|
+
// env-gate throw, CLI 入口接住转 stderr + exit 2.
|
|
43
|
+
import { APIKeyMissingError } from '@deepwhale/llm';
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @typedef {Object} CliArgs
|
|
47
|
+
* @property {'interactive'|'print'|'rpc'|'verify'} mode
|
|
48
|
+
* @property {string|undefined} prompt
|
|
49
|
+
* @property {string|undefined} sessionPath
|
|
50
|
+
* @property {string|undefined} provider
|
|
51
|
+
* @property {string|undefined} model
|
|
52
|
+
* @property {boolean} enableToolLoop
|
|
53
|
+
* @property {number} maxSteps
|
|
54
|
+
* @property {boolean} [yes] Sprint 1c-revive-3-D-13: --yes flag, 透传 3 mode.
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {ReadonlyArray<string>} argv
|
|
59
|
+
* @returns {CliArgs}
|
|
60
|
+
*/
|
|
61
|
+
function parseArgs(argv) {
|
|
62
|
+
const args = {
|
|
63
|
+
mode: 'interactive',
|
|
64
|
+
prompt: undefined,
|
|
65
|
+
sessionPath: undefined,
|
|
66
|
+
provider: undefined,
|
|
67
|
+
model: undefined,
|
|
68
|
+
enableToolLoop: true,
|
|
69
|
+
maxSteps: 5,
|
|
70
|
+
yes: undefined,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
let i = 0;
|
|
74
|
+
while (i < argv.length) {
|
|
75
|
+
const a = argv[i];
|
|
76
|
+
if (a === '--version' || a === '-v') {
|
|
77
|
+
process.stdout.write('deepwhale 0.1.0 (Sprint 1a)\n');
|
|
78
|
+
process.exit(0);
|
|
79
|
+
}
|
|
80
|
+
if (a === '--help' || a === '-h') {
|
|
81
|
+
process.stdout.write(HELP_TEXT);
|
|
82
|
+
process.exit(0);
|
|
83
|
+
}
|
|
84
|
+
if (a === '--rpc') {
|
|
85
|
+
args.mode = 'rpc';
|
|
86
|
+
i += 1;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
// Sprint 1c-revive-4-D-20.3 (2026-06-05): TUI mode (D-20.3 P0-B)
|
|
90
|
+
// `deepwhale tui` 启动 minimal ANSI TUI. 必须出现在 -p/--prompt 检查之前,
|
|
91
|
+
// 否则 'tui' 会被当 print mode 的 prompt (D-15 拍板: 非 '-' 开头的 argv 走 print).
|
|
92
|
+
if (a === 'tui') {
|
|
93
|
+
args.mode = 'tui';
|
|
94
|
+
i += 1;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (a === '--verify') {
|
|
98
|
+
// Sprint 1c-revive-2-D-11-4 (2026-06-04): CLI 接入 verify 模式.
|
|
99
|
+
// 走 runVerify() → formatReport() 印到 stdout, 不走 LLM / tool loop / session.
|
|
100
|
+
// 退出码: 0 = passed, 1 = failed (跟 runVerify overallStatus 对应),
|
|
101
|
+
// 2 = 参数错 (跟现有 mode 退出码一致)
|
|
102
|
+
args.mode = 'verify';
|
|
103
|
+
i += 1;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (a === '-p' || a === '--prompt') {
|
|
107
|
+
args.mode = 'print';
|
|
108
|
+
args.prompt = argv[i + 1] ?? '';
|
|
109
|
+
i += 2;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (a === '--session') {
|
|
113
|
+
args.sessionPath = pathResolve(argv[i + 1] ?? '');
|
|
114
|
+
i += 2;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (a === '--provider') {
|
|
118
|
+
// 拍板 2026-06-04 review P2: 之前未接, --provider X 被当 prompt 进入 print 模式.
|
|
119
|
+
// 校验: deepseek | anthropic (跟 llm-factory.ts 的 Provider 拍板一致).
|
|
120
|
+
const v = argv[i + 1] ?? '';
|
|
121
|
+
if (v !== 'deepseek' && v !== 'anthropic') {
|
|
122
|
+
process.stderr.write(`Error: --provider must be 'deepseek' or 'anthropic', got '${v}'\n`);
|
|
123
|
+
process.exit(2);
|
|
124
|
+
}
|
|
125
|
+
args.provider = v;
|
|
126
|
+
i += 2;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (a === '--yes') {
|
|
130
|
+
// Sprint 1c-revive-3-D-13 (2026-06-05): --yes 透传 3 mode.
|
|
131
|
+
// 拍板: bypass require_confirmation (write_file/edit_file/bash 危险模式),
|
|
132
|
+
// 不 bypass deny. 跟 R-3 拍板一致.
|
|
133
|
+
args.yes = true;
|
|
134
|
+
i += 1;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (a === '--model') {
|
|
138
|
+
args.model = argv[i + 1] ?? '';
|
|
139
|
+
i += 2;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (a === '--no-tool-loop') {
|
|
143
|
+
args.enableToolLoop = false;
|
|
144
|
+
i += 1;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (a === '--max-steps') {
|
|
148
|
+
const n = Number.parseInt(argv[i + 1] ?? '5', 10);
|
|
149
|
+
args.maxSteps = Number.isFinite(n) && n > 0 ? n : 5;
|
|
150
|
+
i += 2;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
// 未知参数 → 当作 print 模式的 prompt(Sprint 0.3 兼容)
|
|
154
|
+
if (!a.startsWith('-')) {
|
|
155
|
+
args.mode = 'print';
|
|
156
|
+
args.prompt = a;
|
|
157
|
+
}
|
|
158
|
+
i += 1;
|
|
159
|
+
}
|
|
160
|
+
return args;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const HELP_TEXT = `deepwhale — Coding Agent CLI
|
|
164
|
+
|
|
165
|
+
Usage:
|
|
166
|
+
deepwhale Start interactive REPL (default)
|
|
167
|
+
deepwhale -p "<prompt>" Print mode: single-shot chat + tool loop
|
|
168
|
+
deepwhale --verify Verify mode: run build/lint/typecheck/test, no LLM
|
|
169
|
+
deepwhale --rpc RPC mode: NDJSON over stdio (Sprint 1a stub)
|
|
170
|
+
deepwhale tui TUI mode: minimal ANSI TUI (D-20.3, ships in v1.0)
|
|
171
|
+
|
|
172
|
+
Options:
|
|
173
|
+
--session <path> Persist session to JSONL file
|
|
174
|
+
--provider <name> LLM provider: deepseek | anthropic (overrides env detection)
|
|
175
|
+
--model <id> LLM model id (e.g. deepseek-v4-flash, claude-sonnet-4-5)
|
|
176
|
+
--no-tool-loop Disable tool calling (single-turn chat only)
|
|
177
|
+
--max-steps <n> Max tool-loop steps (default 5)
|
|
178
|
+
--yes Bypass require_confirmation (write/edit/dangerous bash).
|
|
179
|
+
Does NOT bypass deny. Sprint 1c-revive-3-D-13.
|
|
180
|
+
--version, -v Print version and exit
|
|
181
|
+
--help, -h Print this help
|
|
182
|
+
|
|
183
|
+
Environment:
|
|
184
|
+
DEEPSEEK_API_KEY Required for deepseek (or --provider).
|
|
185
|
+
ANTHROPIC_AUTH_TOKEN Required for anthropic (or --provider). May also be
|
|
186
|
+
DEEPWHALE_SESSION_KEY for session-at-rest encryption.
|
|
187
|
+
DEEPWHALE_LANG Optional. 'en' (default) or 'zh-CN'.
|
|
188
|
+
DEEPWHALE_SANDBOX Optional. 'local' (default) or 'docker'.
|
|
189
|
+
DEEPWHALE_DOCKER_IMAGE Optional. default 'node:22-alpine'.
|
|
190
|
+
DEEPWHALE_DOCKER_NETWORK Optional. unset|'none' (default) or 'bridge'.
|
|
191
|
+
D-20.1: invalid value → fail-closed (exit 2).
|
|
192
|
+
|
|
193
|
+
Built-in REPL commands:
|
|
194
|
+
/help, /verify, /exit, exit, quit
|
|
195
|
+
|
|
196
|
+
Setup hint:
|
|
197
|
+
If you see "API key not set" on first run:
|
|
198
|
+
1. Set DEEPSEEK_API_KEY=<your-key> (or ANTHROPIC_AUTH_TOKEN=...)
|
|
199
|
+
2. Or place it in ./.env (project root, see .env.example)
|
|
200
|
+
3. --verify does not require any key (build/lint/typecheck/test only)
|
|
201
|
+
`;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* 路由到 3 种模式之一。
|
|
205
|
+
* Sprint 1a:interactive/print 接 tool loop + session;rpc 是 NDJSON 框架 stub。
|
|
206
|
+
* Sprint 1c-revive-2-D-5+ (review P2, 2026-06-04): --provider/--model 透传
|
|
207
|
+
* 3 mode, 跟 createDefaultClient factory 对接.
|
|
208
|
+
*
|
|
209
|
+
* @returns {Promise<number>}
|
|
210
|
+
*/
|
|
211
|
+
async function main() {
|
|
212
|
+
const args = parseArgs(process.argv.slice(2));
|
|
213
|
+
switch (args.mode) {
|
|
214
|
+
case 'interactive':
|
|
215
|
+
return startRepl({
|
|
216
|
+
...(args.sessionPath !== undefined ? { sessionPath: args.sessionPath } : {}),
|
|
217
|
+
...(args.provider !== undefined ? { provider: args.provider } : {}),
|
|
218
|
+
...(args.model !== undefined ? { model: args.model } : {}),
|
|
219
|
+
...(args.yes ? { yes: true } : {}),
|
|
220
|
+
enableToolLoop: args.enableToolLoop,
|
|
221
|
+
});
|
|
222
|
+
case 'print':
|
|
223
|
+
if (!args.prompt) {
|
|
224
|
+
process.stderr.write('Error: print mode requires -p "<prompt>" argument\n');
|
|
225
|
+
return 2;
|
|
226
|
+
}
|
|
227
|
+
return runPrintMode({
|
|
228
|
+
prompt: args.prompt,
|
|
229
|
+
...(args.sessionPath !== undefined ? { sessionPath: args.sessionPath } : {}),
|
|
230
|
+
...(args.provider !== undefined ? { provider: args.provider } : {}),
|
|
231
|
+
...(args.model !== undefined ? { model: args.model } : {}),
|
|
232
|
+
...(args.yes ? { yes: true } : {}),
|
|
233
|
+
enableToolLoop: args.enableToolLoop,
|
|
234
|
+
maxSteps: args.maxSteps,
|
|
235
|
+
});
|
|
236
|
+
case 'rpc':
|
|
237
|
+
return runRpcMode({
|
|
238
|
+
...(args.sessionPath !== undefined ? { sessionPath: args.sessionPath } : {}),
|
|
239
|
+
...(args.provider !== undefined ? { provider: args.provider } : {}),
|
|
240
|
+
...(args.model !== undefined ? { model: args.model } : {}),
|
|
241
|
+
...(args.yes ? { yes: true } : {}),
|
|
242
|
+
maxSteps: args.maxSteps,
|
|
243
|
+
});
|
|
244
|
+
case 'tui':
|
|
245
|
+
return runTuiMode({
|
|
246
|
+
...(args.sessionPath !== undefined ? { sessionPath: args.sessionPath } : {}),
|
|
247
|
+
...(args.provider !== undefined ? { provider: args.provider } : {}),
|
|
248
|
+
...(args.model !== undefined ? { model: args.model } : {}),
|
|
249
|
+
...(args.yes ? { yes: true } : {}),
|
|
250
|
+
enableToolLoop: args.enableToolLoop,
|
|
251
|
+
maxSteps: args.maxSteps,
|
|
252
|
+
});
|
|
253
|
+
case 'verify': // Sprint 1c-revive-2-D-11-4: 走 runVerify (4 步 default), formatReport 印到 stdout.
|
|
254
|
+
// 退出码: passed=0, failed=1 (跟 runVerify overallStatus 对应). 跟 Unix
|
|
255
|
+
// 惯例一致 (CI 脚本 \`if deepwhale --verify; then ...\`).
|
|
256
|
+
// 注: 不写 session event (verify 不是 chat 行为, session JSONL 是 chat 持久化,
|
|
257
|
+
// verify 跑完不污染 session). 后续 sprint 如要 audit log, 留 --verify-log 选项.
|
|
258
|
+
{
|
|
259
|
+
const report = await runVerify();
|
|
260
|
+
const filled = buildSummaryAndNext(report);
|
|
261
|
+
const text = formatReport({
|
|
262
|
+
...report,
|
|
263
|
+
summary: filled.summary,
|
|
264
|
+
nextSuggestedAction: filled.nextSuggestedAction,
|
|
265
|
+
});
|
|
266
|
+
process.stdout.write(text + '\n');
|
|
267
|
+
return report.overallStatus === 'passed' ? 0 : 1;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
main().then(
|
|
273
|
+
(code) => process.exit(code),
|
|
274
|
+
(err) => {
|
|
275
|
+
// Sprint 1c-revive-4-D-20.1 (2026-06-05) review-fix: 友好错误处理, 退出码 2 (跟参数错一致).
|
|
276
|
+
// - APIKeyMissingError: REPL/print/rpc/tui 缺 key → 印 setup hint
|
|
277
|
+
// - env-gate 抛 'invalid DEEPWHALE_SANDBOX=...' / 'invalid DEEPWHALE_DOCKER_NETWORK=...'
|
|
278
|
+
// → 直接 stderr 打印 (message 拼齐了 hint), exit 2
|
|
279
|
+
if (err instanceof APIKeyMissingError) {
|
|
280
|
+
process.stderr.write(
|
|
281
|
+
'Error: API key not set. deepwhale needs DEEPSEEK_API_KEY (or ANTHROPIC_AUTH_TOKEN),\n' +
|
|
282
|
+
' or pass --provider. See --help for full setup.\n' +
|
|
283
|
+
' Hint: --verify runs build/lint/typecheck/test and does NOT need a key.\n' +
|
|
284
|
+
` Underlying: ${err.message}\n`,
|
|
285
|
+
);
|
|
286
|
+
process.exit(2);
|
|
287
|
+
}
|
|
288
|
+
if (err instanceof Error && /^invalid DEEPWHALE_SANDBOX=/.test(err.message)) {
|
|
289
|
+
process.stderr.write(`Error: ${err.message}\n`);
|
|
290
|
+
process.exit(2);
|
|
291
|
+
}
|
|
292
|
+
if (err instanceof Error && /^invalid DEEPWHALE_DOCKER_NETWORK=/.test(err.message)) {
|
|
293
|
+
process.stderr.write(`Error: ${err.message}\n`);
|
|
294
|
+
process.exit(2);
|
|
295
|
+
}
|
|
296
|
+
process.stderr.write(`FATAL: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
297
|
+
process.exit(1);
|
|
298
|
+
},
|
|
299
|
+
);
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Loop + Compaction 集成 (Sprint 1c-revive-2-D-5 + D-5-2)
|
|
3
|
+
*
|
|
4
|
+
* 拍板 (跟 P21 / P27 跨协议 6 cell 一致):
|
|
5
|
+
* - runToolLoop 每次 LLM call 前, 测 messages token 数
|
|
6
|
+
* - 触发 (>= window * compactRatio) → 调 summaryFn (LLM 走同 client 拍板)
|
|
7
|
+
* - 成功 → 替换 working messages, 写 1 条 'compaction' event 到 SessionWriter
|
|
8
|
+
* - 失败 → CompactionState 累计; latch → 写 1 条 'compaction_paused' event
|
|
9
|
+
* - paused → 跳过 compaction (不浪费 LLM token 调 summaryFn, 防 death loop)
|
|
10
|
+
*
|
|
11
|
+
* 协议集成 (P38 拍板 + D-5-2 拍板):
|
|
12
|
+
* - protocol: 'openai' | 'anthropic' (用于 summaryFn, 不同协议 system prompt 不同)
|
|
13
|
+
* - 集成在 runToolLoop 入口, 跟 tool-loop.ts P21 6 cell 拍板一致:
|
|
14
|
+
* DeepSeek + Anthropic 协议都走同一 hook
|
|
15
|
+
*
|
|
16
|
+
* 不变量:
|
|
17
|
+
* - compaction 永不 throw 给 runToolLoop (防 LLM 续聊死锁)
|
|
18
|
+
* - 失败 event 总能写盘 (即使 writer.append 抛错, 也只 warn 不 throw)
|
|
19
|
+
* - paused 后仍跑 runToolLoop 正常 (不阻塞用户任务, 仅不再 compact)
|
|
20
|
+
*
|
|
21
|
+
* @module @deepwhale/coding-agent/agent-compaction
|
|
22
|
+
*/
|
|
23
|
+
import { type ChatMessage, type LLMClient } from '@deepwhale/llm';
|
|
24
|
+
import { type CompactionConfig, type SummarizeFn, CompactionState } from '@deepwhale/core';
|
|
25
|
+
import type { SessionWriter } from '@deepwhale/core';
|
|
26
|
+
import type { ToolLoopOptions, ToolLoopResult } from './tool-loop.js';
|
|
27
|
+
/**
|
|
28
|
+
* Compaction 集成配置 (runToolLoop 包装层用).
|
|
29
|
+
*
|
|
30
|
+
* 跟 core CompactionConfig 区别:
|
|
31
|
+
* - client 来自 coding-agent 包 (P21 拍板: 协议从 LLMClient 推断)
|
|
32
|
+
* - state 由集成层管 (caller 用 new CompactionState(...) 注入)
|
|
33
|
+
* - protocol 拍板: 'openai' (DeepSeek) | 'anthropic' — summaryFn 的 system prompt 不同
|
|
34
|
+
*/
|
|
35
|
+
export interface AgentCompactionConfig extends CompactionConfig {
|
|
36
|
+
/** 协议拍板 — 跟 P21 6 cell 一致. summaryFn 内部用此拍 system prompt 模板. */
|
|
37
|
+
readonly protocol: 'openai' | 'anthropic';
|
|
38
|
+
/** SessionWriter — 写 'compaction' / 'compaction_paused' event 用 */
|
|
39
|
+
readonly writer: SessionWriter;
|
|
40
|
+
/** CompactionState — caller 管, 跨 runToolLoop 调用持久化 */
|
|
41
|
+
readonly state: CompactionState;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 跑 runToolLoop 集成 compaction 触发.
|
|
45
|
+
*
|
|
46
|
+
* 拍板行为 (跟 P21 6 cell 一致):
|
|
47
|
+
* 1. 入口测 token → 触发则 compact → 替换 working
|
|
48
|
+
* 2. runToolLoop 内部每个 LLM call 前不重复触发 (避免 per-step 开销)
|
|
49
|
+
* 3. 失败 latch → 写 paused event, runToolLoop 继续跑 (不阻塞)
|
|
50
|
+
*
|
|
51
|
+
* Sprint 1c-revive-2-D-6 (review P1 修复, 2026-06-04): caller-side system prefix
|
|
52
|
+
* handling. 拍板: REPL/caller 可能把系统提示拼到 messages 最前面 (e.g. integration
|
|
53
|
+
* test fixture, 或未来 system prompt 注入). 传 compact() 之前先 **剥掉** 连续
|
|
54
|
+
* system 前缀, 让 compact 看到的 index 跟 session-adapter 累积 messages
|
|
55
|
+
* (user/assistant/tool + compaction summary) 同 index 空间, replaced_range
|
|
56
|
+
* 切 reload replay 同步. compact 后把 system 前缀 **原样 prepend 回** 替换后
|
|
57
|
+
* 的 messages, LLM 看到的 context 跟 caller 拼的一致.
|
|
58
|
+
*
|
|
59
|
+
* @param client LLM client
|
|
60
|
+
* @param messages 入口 messages (不变, 内部 copy)
|
|
61
|
+
* @param options runToolLoop 原生 options
|
|
62
|
+
* @param compaction 集成配置
|
|
63
|
+
* @param summaryFn 生成 summary text 的 callback (caller 决定 LLM 协议)
|
|
64
|
+
* @returns ToolLoopResult
|
|
65
|
+
*/
|
|
66
|
+
export declare function runToolLoopWithCompaction(client: LLMClient, messages: ReadonlyArray<ChatMessage>, options: ToolLoopOptions | undefined, compaction: AgentCompactionConfig, summaryFn: SummarizeFn): Promise<ToolLoopResult>;
|
|
67
|
+
/**
|
|
68
|
+
* 便捷工具: 估算当前 messages 的 token 数 (供 REPL / footer 拍板显示用).
|
|
69
|
+
*
|
|
70
|
+
* 跟 compaction.ts 的 estimateTokens 拍板一致 (char/4 粗估).
|
|
71
|
+
* 集成在 coding-agent 包, 供 REPL 端零成本 import core.
|
|
72
|
+
*/
|
|
73
|
+
export declare function estimateContextTokens(messages: ReadonlyArray<ChatMessage>): number;
|
|
74
|
+
//# sourceMappingURL=agent-compaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-compaction.d.ts","sourceRoot":"","sources":["../../src/agent/agent-compaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,SAAS,EACf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAEhB,eAAe,EAGhB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGtE;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC7D,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC1C,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,aAAa,CAAC,WAAW,CAAC,EACpC,OAAO,EAAE,eAAe,YAAK,EAC7B,UAAU,EAAE,qBAAqB,EACjC,SAAS,EAAE,WAAW,GACrB,OAAO,CAAC,cAAc,CAAC,CAUzB;AAyFD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,MAAM,CAElF"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Loop + Compaction 集成 (Sprint 1c-revive-2-D-5 + D-5-2)
|
|
3
|
+
*
|
|
4
|
+
* 拍板 (跟 P21 / P27 跨协议 6 cell 一致):
|
|
5
|
+
* - runToolLoop 每次 LLM call 前, 测 messages token 数
|
|
6
|
+
* - 触发 (>= window * compactRatio) → 调 summaryFn (LLM 走同 client 拍板)
|
|
7
|
+
* - 成功 → 替换 working messages, 写 1 条 'compaction' event 到 SessionWriter
|
|
8
|
+
* - 失败 → CompactionState 累计; latch → 写 1 条 'compaction_paused' event
|
|
9
|
+
* - paused → 跳过 compaction (不浪费 LLM token 调 summaryFn, 防 death loop)
|
|
10
|
+
*
|
|
11
|
+
* 协议集成 (P38 拍板 + D-5-2 拍板):
|
|
12
|
+
* - protocol: 'openai' | 'anthropic' (用于 summaryFn, 不同协议 system prompt 不同)
|
|
13
|
+
* - 集成在 runToolLoop 入口, 跟 tool-loop.ts P21 6 cell 拍板一致:
|
|
14
|
+
* DeepSeek + Anthropic 协议都走同一 hook
|
|
15
|
+
*
|
|
16
|
+
* 不变量:
|
|
17
|
+
* - compaction 永不 throw 给 runToolLoop (防 LLM 续聊死锁)
|
|
18
|
+
* - 失败 event 总能写盘 (即使 writer.append 抛错, 也只 warn 不 throw)
|
|
19
|
+
* - paused 后仍跑 runToolLoop 正常 (不阻塞用户任务, 仅不再 compact)
|
|
20
|
+
*
|
|
21
|
+
* @module @deepwhale/coding-agent/agent-compaction
|
|
22
|
+
*/
|
|
23
|
+
import { runCompactionWithLatch, estimateTokens, } from '@deepwhale/core';
|
|
24
|
+
import { runToolLoop } from './tool-loop.js';
|
|
25
|
+
/**
|
|
26
|
+
* 跑 runToolLoop 集成 compaction 触发.
|
|
27
|
+
*
|
|
28
|
+
* 拍板行为 (跟 P21 6 cell 一致):
|
|
29
|
+
* 1. 入口测 token → 触发则 compact → 替换 working
|
|
30
|
+
* 2. runToolLoop 内部每个 LLM call 前不重复触发 (避免 per-step 开销)
|
|
31
|
+
* 3. 失败 latch → 写 paused event, runToolLoop 继续跑 (不阻塞)
|
|
32
|
+
*
|
|
33
|
+
* Sprint 1c-revive-2-D-6 (review P1 修复, 2026-06-04): caller-side system prefix
|
|
34
|
+
* handling. 拍板: REPL/caller 可能把系统提示拼到 messages 最前面 (e.g. integration
|
|
35
|
+
* test fixture, 或未来 system prompt 注入). 传 compact() 之前先 **剥掉** 连续
|
|
36
|
+
* system 前缀, 让 compact 看到的 index 跟 session-adapter 累积 messages
|
|
37
|
+
* (user/assistant/tool + compaction summary) 同 index 空间, replaced_range
|
|
38
|
+
* 切 reload replay 同步. compact 后把 system 前缀 **原样 prepend 回** 替换后
|
|
39
|
+
* 的 messages, LLM 看到的 context 跟 caller 拼的一致.
|
|
40
|
+
*
|
|
41
|
+
* @param client LLM client
|
|
42
|
+
* @param messages 入口 messages (不变, 内部 copy)
|
|
43
|
+
* @param options runToolLoop 原生 options
|
|
44
|
+
* @param compaction 集成配置
|
|
45
|
+
* @param summaryFn 生成 summary text 的 callback (caller 决定 LLM 协议)
|
|
46
|
+
* @returns ToolLoopResult
|
|
47
|
+
*/
|
|
48
|
+
export async function runToolLoopWithCompaction(client, messages, options = {}, compaction, summaryFn) {
|
|
49
|
+
// 1) 剥掉 caller 拼的连续 system prefix, 保持 replaced_range 跟 JSONL 累积同空间
|
|
50
|
+
const headSystem = splitSystemPrefix(messages);
|
|
51
|
+
// 2) 入口测 token, 触发则 compact 替换 messages (在剥掉 system 的子集上跑)
|
|
52
|
+
const compactedTail = await maybeCompactBeforeLoop(headSystem.tail, compaction, summaryFn);
|
|
53
|
+
// 3) 拼回 system prefix → 跑原生 runToolLoop
|
|
54
|
+
const compactedMessages = [...headSystem.prefix, ...compactedTail];
|
|
55
|
+
return runToolLoop(client, compactedMessages, options);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 把 messages 切分为 "caller 自带的连续 system prefix" + "其余".
|
|
59
|
+
*
|
|
60
|
+
* 拍板 (D-6 review P1 修复, 2026-06-04):
|
|
61
|
+
* - prefix = messages[0..n), n = 头连续 system message 数量
|
|
62
|
+
* - tail = messages[n..)
|
|
63
|
+
* - 没 system prefix → prefix=[], tail=messages
|
|
64
|
+
* - 全 system (只有 1 条 system 也算) → tail=[] (compaction 看到空, 不触发)
|
|
65
|
+
*
|
|
66
|
+
* 用途: caller 把 system prompt 拼前面时, 传给 compact() 前先剥掉, 让
|
|
67
|
+
* replaced_range 的 index 空间 跟 session-adapter replay JSONL 时累积的
|
|
68
|
+
* messages (user/assistant/tool + 之前 reload 注入的 summary) 同空间,
|
|
69
|
+
* reload replay 不会 off-by-one.
|
|
70
|
+
*
|
|
71
|
+
* **不动** 中间或末尾的 system message (罕见, 但保留 — 不归 compaction 管).
|
|
72
|
+
* **不动** tool_call_id 关联, 因为 prefix 是 system role, 不会拖 tool pair.
|
|
73
|
+
*/
|
|
74
|
+
function splitSystemPrefix(messages) {
|
|
75
|
+
let n = 0;
|
|
76
|
+
while (n < messages.length && messages[n].role === 'system') {
|
|
77
|
+
n++;
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
prefix: messages.slice(0, n),
|
|
81
|
+
tail: messages.slice(n),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* 入口 compaction 触发 (one-shot, 不重入 runToolLoop 内部).
|
|
86
|
+
*
|
|
87
|
+
* 行为契约:
|
|
88
|
+
* - paused → 返 messages 原样, 不调 summaryFn, 不写 event (latched 拍板)
|
|
89
|
+
* - 不该 compact → 返 messages 原样, 不调 summaryFn, 不写 event
|
|
90
|
+
* - compact 成功 → 替换 messages, 写 'compaction' event
|
|
91
|
+
* - compact 失败 (未 latch) → 返 messages 原样, 不写 event (caller 该 retry)
|
|
92
|
+
* - compact latched → 写 'compaction_paused' event, 返 messages 原样
|
|
93
|
+
*/
|
|
94
|
+
async function maybeCompactBeforeLoop(messages, compaction, summaryFn) {
|
|
95
|
+
const { state, writer, protocol, contextWindow } = compaction;
|
|
96
|
+
// protocol 显式使用一次, 拍板留位 (跟 P21 6 cell summaryFn 拍 system prompt 模板用)
|
|
97
|
+
void protocol;
|
|
98
|
+
if (contextWindow <= 0)
|
|
99
|
+
return messages;
|
|
100
|
+
if (messages.length === 0)
|
|
101
|
+
return messages;
|
|
102
|
+
if (!state.shouldAttempt())
|
|
103
|
+
return messages;
|
|
104
|
+
let result;
|
|
105
|
+
try {
|
|
106
|
+
result = await runCompactionWithLatch(messages, compaction, summaryFn, state);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// 未触发 latch 的失败: caller 决定怎么处理 (e.g. 用户改配置), 这里不抛
|
|
110
|
+
// 拍板不阻塞 runToolLoop
|
|
111
|
+
return messages;
|
|
112
|
+
}
|
|
113
|
+
if (result === null) {
|
|
114
|
+
// 不该 compact 或 paused
|
|
115
|
+
return messages;
|
|
116
|
+
}
|
|
117
|
+
if (result.kind === 'ok') {
|
|
118
|
+
// 写 'compaction' event — writer.append 抛错只 warn, 不 throw
|
|
119
|
+
try {
|
|
120
|
+
await writer.append(result.event);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// 写盘失败不阻塞 loop
|
|
124
|
+
}
|
|
125
|
+
return result.result.messages;
|
|
126
|
+
}
|
|
127
|
+
// kind === 'latched'
|
|
128
|
+
try {
|
|
129
|
+
await writer.append(result.pausedEvent);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// 写盘失败不阻塞 loop
|
|
133
|
+
}
|
|
134
|
+
return messages;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* 便捷工具: 估算当前 messages 的 token 数 (供 REPL / footer 拍板显示用).
|
|
138
|
+
*
|
|
139
|
+
* 跟 compaction.ts 的 estimateTokens 拍板一致 (char/4 粗估).
|
|
140
|
+
* 集成在 coding-agent 包, 供 REPL 端零成本 import core.
|
|
141
|
+
*/
|
|
142
|
+
export function estimateContextTokens(messages) {
|
|
143
|
+
return estimateTokens(messages);
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=agent-compaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-compaction.js","sourceRoot":"","sources":["../../src/agent/agent-compaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @deepwhale/coding-agent/agent — Tool Loop & 调度
|
|
3
|
+
*
|
|
4
|
+
* Sprint 1a 落地:
|
|
5
|
+
* - runToolLoop: 最小 agent loop(LLM ↔ tool_calls ↔ LLM)
|
|
6
|
+
* - ToolLoopLimitError: maxSteps 触顶时抛
|
|
7
|
+
* - session-adapter: tool loop step ↔ JSONL SessionEvent 转换
|
|
8
|
+
*
|
|
9
|
+
* Sprint 1b 再加:plan mode、schema 校验、budget cap、onStep 实时回调。
|
|
10
|
+
* Sprint 2+ 再加:并行 tool_call、recovery 3-way、断点续传。
|
|
11
|
+
*/
|
|
12
|
+
export { runToolLoop, isToolLoopError, TOOL_LOOP_DEFAULT_MAX_STEPS, type ToolLoopOptions, type ToolLoopResult, type ToolLoopStep, ToolLoopLimitError, } from './tool-loop.js';
|
|
13
|
+
export { toolLoopStepToSessionEvent, sessionEventsToMessages, appendUserEvent, appendCompactionEvent, appendCompactionPausedEvent, appendVerificationEvent, persistToolLoopSteps, loadSession, } from './session-adapter.js';
|
|
14
|
+
export { runToolLoopWithCompaction, estimateContextTokens, type AgentCompactionConfig, } from './agent-compaction.js';
|
|
15
|
+
export { CompactionState, type CompactionConfig } from '@deepwhale/core';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,WAAW,EACX,eAAe,EACf,2BAA2B,EAC3B,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,eAAe,EACf,qBAAqB,EACrB,2BAA2B,EAC3B,uBAAuB,EACvB,oBAAoB,EACpB,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @deepwhale/coding-agent/agent — Tool Loop & 调度
|
|
3
|
+
*
|
|
4
|
+
* Sprint 1a 落地:
|
|
5
|
+
* - runToolLoop: 最小 agent loop(LLM ↔ tool_calls ↔ LLM)
|
|
6
|
+
* - ToolLoopLimitError: maxSteps 触顶时抛
|
|
7
|
+
* - session-adapter: tool loop step ↔ JSONL SessionEvent 转换
|
|
8
|
+
*
|
|
9
|
+
* Sprint 1b 再加:plan mode、schema 校验、budget cap、onStep 实时回调。
|
|
10
|
+
* Sprint 2+ 再加:并行 tool_call、recovery 3-way、断点续传。
|
|
11
|
+
*/
|
|
12
|
+
export { runToolLoop, isToolLoopError, TOOL_LOOP_DEFAULT_MAX_STEPS, ToolLoopLimitError, } from './tool-loop.js';
|
|
13
|
+
export { toolLoopStepToSessionEvent, sessionEventsToMessages, appendUserEvent, appendCompactionEvent, appendCompactionPausedEvent, appendVerificationEvent, persistToolLoopSteps, loadSession, } from './session-adapter.js';
|
|
14
|
+
export { runToolLoopWithCompaction, estimateContextTokens, } from './agent-compaction.js';
|
|
15
|
+
// Re-export core compaction types for caller convenience
|
|
16
|
+
export { CompactionState } from '@deepwhale/core';
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,WAAW,EACX,eAAe,EACf,2BAA2B,EAI3B,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,eAAe,EACf,qBAAqB,EACrB,2BAA2B,EAC3B,uBAAuB,EACvB,oBAAoB,EACpB,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,yBAAyB,EACzB,qBAAqB,GAEtB,MAAM,uBAAuB,CAAC;AAC/B,yDAAyD;AACzD,OAAO,EAAE,eAAe,EAAyB,MAAM,iBAAiB,CAAC"}
|