@deepwhale/coding-agent 1.0.10 → 1.0.12
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/LICENSE +21 -21
- package/package.json +1 -1
- package/dist/agent/agent-compaction.d.ts +0 -74
- package/dist/agent/agent-compaction.d.ts.map +0 -1
- package/dist/agent/agent-compaction.js +0 -145
- package/dist/agent/agent-compaction.js.map +0 -1
- package/dist/agent/index.d.ts +0 -16
- package/dist/agent/index.d.ts.map +0 -1
- package/dist/agent/index.js +0 -17
- package/dist/agent/index.js.map +0 -1
- package/dist/agent/session-adapter.d.ts +0 -177
- package/dist/agent/session-adapter.d.ts.map +0 -1
- package/dist/agent/session-adapter.js +0 -365
- package/dist/agent/session-adapter.js.map +0 -1
- package/dist/agent/tool-loop.d.ts +0 -123
- package/dist/agent/tool-loop.d.ts.map +0 -1
- package/dist/agent/tool-loop.js +0 -436
- package/dist/agent/tool-loop.js.map +0 -1
- package/dist/env/load-project-env.d.ts +0 -40
- package/dist/env/load-project-env.d.ts.map +0 -1
- package/dist/env/load-project-env.js +0 -80
- package/dist/env/load-project-env.js.map +0 -1
- package/dist/index.d.ts +0 -31
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -30
- package/dist/index.js.map +0 -1
- package/dist/llm-factory.d.ts +0 -50
- package/dist/llm-factory.d.ts.map +0 -1
- package/dist/llm-factory.js +0 -110
- package/dist/llm-factory.js.map +0 -1
- package/dist/modes/index.d.ts +0 -14
- package/dist/modes/index.d.ts.map +0 -1
- package/dist/modes/index.js +0 -14
- package/dist/modes/index.js.map +0 -1
- package/dist/modes/print.d.ts +0 -50
- package/dist/modes/print.d.ts.map +0 -1
- package/dist/modes/print.js +0 -236
- package/dist/modes/print.js.map +0 -1
- package/dist/modes/rpc.d.ts +0 -52
- package/dist/modes/rpc.d.ts.map +0 -1
- package/dist/modes/rpc.js +0 -316
- package/dist/modes/rpc.js.map +0 -1
- package/dist/modes/tui.d.ts +0 -112
- package/dist/modes/tui.d.ts.map +0 -1
- package/dist/modes/tui.js +0 -733
- package/dist/modes/tui.js.map +0 -1
- package/dist/policy/args-digest.d.ts +0 -13
- package/dist/policy/args-digest.d.ts.map +0 -1
- package/dist/policy/args-digest.js +0 -29
- package/dist/policy/args-digest.js.map +0 -1
- package/dist/policy/chain.d.ts +0 -19
- package/dist/policy/chain.d.ts.map +0 -1
- package/dist/policy/chain.js +0 -24
- package/dist/policy/chain.js.map +0 -1
- package/dist/policy/index.d.ts +0 -17
- package/dist/policy/index.d.ts.map +0 -1
- package/dist/policy/index.js +0 -16
- package/dist/policy/index.js.map +0 -1
- package/dist/policy/sanitize-reason.d.ts +0 -11
- package/dist/policy/sanitize-reason.d.ts.map +0 -1
- package/dist/policy/sanitize-reason.js +0 -24
- package/dist/policy/sanitize-reason.js.map +0 -1
- package/dist/policy/static-rules.d.ts +0 -32
- package/dist/policy/static-rules.d.ts.map +0 -1
- package/dist/policy/static-rules.js +0 -106
- package/dist/policy/static-rules.js.map +0 -1
- package/dist/policy/types.d.ts +0 -56
- package/dist/policy/types.d.ts.map +0 -1
- package/dist/policy/types.js +0 -13
- package/dist/policy/types.js.map +0 -1
- package/dist/repl/repl-confirm.d.ts +0 -49
- package/dist/repl/repl-confirm.d.ts.map +0 -1
- package/dist/repl/repl-confirm.js +0 -88
- package/dist/repl/repl-confirm.js.map +0 -1
- package/dist/repl.d.ts +0 -154
- package/dist/repl.d.ts.map +0 -1
- package/dist/repl.js +0 -780
- package/dist/repl.js.map +0 -1
- package/dist/sandbox/docker-runner.d.ts +0 -147
- package/dist/sandbox/docker-runner.d.ts.map +0 -1
- package/dist/sandbox/docker-runner.js +0 -426
- package/dist/sandbox/docker-runner.js.map +0 -1
- package/dist/sandbox/env-gate.d.ts +0 -28
- package/dist/sandbox/env-gate.d.ts.map +0 -1
- package/dist/sandbox/env-gate.js +0 -65
- package/dist/sandbox/env-gate.js.map +0 -1
- package/dist/sandbox/local-runner.d.ts +0 -29
- package/dist/sandbox/local-runner.d.ts.map +0 -1
- package/dist/sandbox/local-runner.js +0 -79
- package/dist/sandbox/local-runner.js.map +0 -1
- package/dist/sandbox/types.d.ts +0 -80
- package/dist/sandbox/types.d.ts.map +0 -1
- package/dist/sandbox/types.js +0 -25
- package/dist/sandbox/types.js.map +0 -1
- package/dist/tools/bash.d.ts +0 -35
- package/dist/tools/bash.d.ts.map +0 -1
- package/dist/tools/bash.js +0 -233
- package/dist/tools/bash.js.map +0 -1
- package/dist/tools/edit-file.d.ts +0 -22
- package/dist/tools/edit-file.d.ts.map +0 -1
- package/dist/tools/edit-file.js +0 -79
- package/dist/tools/edit-file.js.map +0 -1
- package/dist/tools/find.d.ts +0 -21
- package/dist/tools/find.d.ts.map +0 -1
- package/dist/tools/find.js +0 -168
- package/dist/tools/find.js.map +0 -1
- package/dist/tools/grep.d.ts +0 -19
- package/dist/tools/grep.d.ts.map +0 -1
- package/dist/tools/grep.js +0 -170
- package/dist/tools/grep.js.map +0 -1
- package/dist/tools/index.d.ts +0 -10
- package/dist/tools/index.d.ts.map +0 -1
- package/dist/tools/index.js +0 -10
- package/dist/tools/index.js.map +0 -1
- package/dist/tools/read-file.d.ts +0 -18
- package/dist/tools/read-file.d.ts.map +0 -1
- package/dist/tools/read-file.js +0 -52
- package/dist/tools/read-file.js.map +0 -1
- package/dist/tools/registry.d.ts +0 -39
- package/dist/tools/registry.d.ts.map +0 -1
- package/dist/tools/registry.js +0 -67
- package/dist/tools/registry.js.map +0 -1
- package/dist/tools/write-file.d.ts +0 -18
- package/dist/tools/write-file.d.ts.map +0 -1
- package/dist/tools/write-file.js +0 -47
- package/dist/tools/write-file.js.map +0 -1
- package/dist/tui-ink-bundle.js +0 -38587
- package/dist/types.d.ts +0 -89
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -5
- package/dist/types.js.map +0 -1
- package/dist/util/index.d.ts +0 -16
- package/dist/util/index.d.ts.map +0 -1
- package/dist/util/index.js +0 -16
- package/dist/util/index.js.map +0 -1
- package/dist/util/tui-history.d.ts +0 -37
- package/dist/util/tui-history.d.ts.map +0 -1
- package/dist/util/tui-history.js +0 -93
- package/dist/util/tui-history.js.map +0 -1
- package/dist/verify/format-report.d.ts +0 -57
- package/dist/verify/format-report.d.ts.map +0 -1
- package/dist/verify/format-report.js +0 -128
- package/dist/verify/format-report.js.map +0 -1
- package/dist/verify/index.d.ts +0 -8
- package/dist/verify/index.d.ts.map +0 -1
- package/dist/verify/index.js +0 -8
- package/dist/verify/index.js.map +0 -1
- package/dist/verify/verify-runner.d.ts +0 -186
- package/dist/verify/verify-runner.d.ts.map +0 -1
- package/dist/verify/verify-runner.js +0 -707
- package/dist/verify/verify-runner.js.map +0 -1
|
@@ -1,365 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Session ↔ Tool Loop 适配器(Sprint 1a)
|
|
3
|
-
*
|
|
4
|
-
* 把 tool loop 的 ToolLoopStep 事件 → SessionEvent JSONL 持久化,
|
|
5
|
-
* 同时支持从已有 JSONL 重建 messages 列表(让 LLM 看到"上次聊到哪")。
|
|
6
|
-
*
|
|
7
|
-
* Sprint 1a 范围(极简):
|
|
8
|
-
* - assistant step → 'assistant' event(保留 tool_calls)
|
|
9
|
-
* - tool step → 'tool' event(保留 tool_call_id + name + result)
|
|
10
|
-
* - 不持久化 user 消息(REPL 层自己 append 'user')
|
|
11
|
-
* - 不持久化 limit/error 事件(runtime 状态,不进 LLM context)
|
|
12
|
-
* - 不做 compaction、加密、压缩、分片(v1.5+)
|
|
13
|
-
*
|
|
14
|
-
* 重建 messages 规则(让 LLM 续聊):
|
|
15
|
-
* - 遍历 events,遇到 user/assistant/tool 都 push 成 ChatMessage
|
|
16
|
-
* - tool 消息需保留 tool_call_id
|
|
17
|
-
* - assistant 消息需保留 tool_calls
|
|
18
|
-
* - 系统提示由 caller 单独组装(repl.ts 拼),不存 JSONL
|
|
19
|
-
*
|
|
20
|
-
* @module @deepwhale/coding-agent/session-adapter
|
|
21
|
-
*/
|
|
22
|
-
/**
|
|
23
|
-
* 把 tool loop step 翻译成 SessionEvent。
|
|
24
|
-
*
|
|
25
|
-
* 只翻译能放进 LLM context 的 step:
|
|
26
|
-
* - 'assistant' → { kind: 'assistant', ts, content, tool_calls }
|
|
27
|
-
* - 'tool' → { kind: 'tool', ts, tool_call_id, name, result }
|
|
28
|
-
*
|
|
29
|
-
* limit/error 是 runtime 状态,**不**持久化(避免重启时把它们当 LLM context 喂回)。
|
|
30
|
-
*/
|
|
31
|
-
export function toolLoopStepToSessionEvent(step) {
|
|
32
|
-
if (step.kind === 'assistant') {
|
|
33
|
-
return {
|
|
34
|
-
kind: 'assistant',
|
|
35
|
-
ts: step.ts,
|
|
36
|
-
content: step.message.content,
|
|
37
|
-
...(step.message.tool_calls ? { tool_calls: [...step.message.tool_calls] } : {}),
|
|
38
|
-
// Sprint 1c-revive-2-D-21.1 (2026-06-06, 修 DeepSeek V4 thinking 400 bug):
|
|
39
|
-
// reasoning_content 透传到 session event. reload 重建 messages 时还原,
|
|
40
|
-
// 让 reload 后的下一轮 LLM call 仍能带 reasoning_content (避免 400).
|
|
41
|
-
// 不开 thinking 时 (V3 旧 alias / thinking 关) message.reasoning_content
|
|
42
|
-
// 是 undefined, 字段 absent — 跟旧 session 兼容, 不污染 JSONL.
|
|
43
|
-
...(step.message.reasoning_content !== undefined
|
|
44
|
-
? { reasoning_content: step.message.reasoning_content }
|
|
45
|
-
: {}),
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
if (step.kind === 'tool') {
|
|
49
|
-
return {
|
|
50
|
-
kind: 'tool',
|
|
51
|
-
ts: step.ts,
|
|
52
|
-
tool_call_id: step.tool_call.id,
|
|
53
|
-
name: step.tool_call.name,
|
|
54
|
-
result: {
|
|
55
|
-
success: step.result.success,
|
|
56
|
-
content: step.result.content,
|
|
57
|
-
...(step.result.success === false && step.result.error !== undefined
|
|
58
|
-
? { error: step.result.error }
|
|
59
|
-
: {}),
|
|
60
|
-
},
|
|
61
|
-
duration_ms: step.duration_ms,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
// 'limit' / 'error' 不持久化
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* 把 SessionEvent 列表重建为 LLM 的 ChatMessage 列表(用于 LLM 续聊)。
|
|
69
|
-
*
|
|
70
|
-
* Sprint 1c P2 修复: 过滤 dangling tool_call transcript.
|
|
71
|
-
*
|
|
72
|
-
* 背景: 二次启动恢复时, JSONL 里可能存在 "assistant(tool_calls=[c2]) 但
|
|
73
|
-
* tool(c2) 没落盘" 的孤立 assistant (crash 写完 assistant 还没写 tool result
|
|
74
|
-
* 就被杀). 旧实现直接 push 这个 assistant → LLM continuation 看到无对应
|
|
75
|
-
* tool result 的 tool_call, 形成非法 transcript, OpenAI API 拒收.
|
|
76
|
-
*
|
|
77
|
-
* 修复规则 (按 user 拍板 2026-06-04):
|
|
78
|
-
* 1. assistant(tool_calls): 只有在下一个 user/assistant 前, 所有
|
|
79
|
-
* tool_call_id 都有对应 tool event, 才保留 (整个 assistant message)
|
|
80
|
-
* 2. tool: 只有它的 tool_call_id 属于"当前未结算的 assistant tool_calls",
|
|
81
|
-
* 才保留; 否则丢 (孤儿)
|
|
82
|
-
* 3. 普通 assistant(content) / user 不受影响
|
|
83
|
-
* 4. **不改写 JSONL events**, 只在重建 messages 时过滤 — 后续补 tool
|
|
84
|
-
* result 后完整 tool_call 组自然重新合法化 (Sprint 1c P2 spec)
|
|
85
|
-
*
|
|
86
|
-
* 实现: 延迟 push 模式 — assistant(tool_calls) 进入 buffer, tool events
|
|
87
|
-
* 配对删除 pending. user/assistant 边界触发 buffer 结算: pending 非空
|
|
88
|
-
* → 整体 roll back (不 push); pending 空 → push buffer.
|
|
89
|
-
*
|
|
90
|
-
* Sprint 1c-revive-2-D-5+ reload 修复 (review P1, 2026-06-04):
|
|
91
|
-
* - JSONL 中的 'compaction' event 必须 **replay** 到 LLM context, 否则
|
|
92
|
-
* reload 后 messages 会从原始 user/assistant/tool events 重建, 旧
|
|
93
|
-
* compacted head 重新出现, 上下文不被压缩 (内存压缩成功但 reload
|
|
94
|
-
* 失效 = P1).
|
|
95
|
-
* - replay 协议: 见到 'compaction' event 时, 把当前累积 messages 的
|
|
96
|
-
* `replaced_range[0..replaced_range[1])` 段 (按 JSONL 累积 index)
|
|
97
|
-
* 替换为 1 条 system summary.
|
|
98
|
-
* - index 空间 (拍板 2026-06-04 review): compact() 入参 messages 来自
|
|
99
|
-
* caller 的 working 列表. REPL 路径下 working = loadSession() 返回
|
|
100
|
-
* 的 JSONL 累积 (纯 user/assistant/tool) + REPL startup 拼的 system
|
|
101
|
-
* prompt. 拍板 compact() 只对 working[0..end] 操作, 不含外部 system
|
|
102
|
-
* prompt, 所以 replaced_range 索引的就是 "JSONL 累积 messages" 的
|
|
103
|
-
* index. reload 时 messages 仍按 JSONL 累积重建, replaced_range 同
|
|
104
|
-
* index 空间, 不偏移. (多个 'compaction' event 串行: 第 1 次 applied
|
|
105
|
-
* 后累积 messages = 1 summary + N tail, 第 2 次 compact 入参就是
|
|
106
|
-
* reload 后的累积, index 重新从 0 计 — protocol 自洽.)
|
|
107
|
-
* - 'compaction_paused' event: 不入 messages. caller 决定是否 reset
|
|
108
|
-
* latch; UI/footer 可读 paused event 显式提示.
|
|
109
|
-
*/
|
|
110
|
-
export function sessionEventsToMessages(events) {
|
|
111
|
-
// Sprint 1c P2 修复: 过滤 dangling tool_call transcript. 延迟 push 模式
|
|
112
|
-
// — assistant(tool_calls) 进入 buffer, tool events 配对删除 pending.
|
|
113
|
-
// user/assistant 边界触发 flushBuffer 结算: pending 非空 → 整体 roll
|
|
114
|
-
// back; pending 空 → push buffer.
|
|
115
|
-
const out = [];
|
|
116
|
-
let buffer = [];
|
|
117
|
-
let pendingToolCalls = new Set();
|
|
118
|
-
const flushBuffer = () => {
|
|
119
|
-
if (pendingToolCalls.size > 0) {
|
|
120
|
-
// 上一个 assistant(tool_calls) 未完成 (user/assistant 边界), 整个 roll back
|
|
121
|
-
buffer = [];
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
out.push(...buffer);
|
|
125
|
-
buffer = [];
|
|
126
|
-
}
|
|
127
|
-
pendingToolCalls = new Set();
|
|
128
|
-
};
|
|
129
|
-
for (const ev of events) {
|
|
130
|
-
if (ev.kind === 'user') {
|
|
131
|
-
flushBuffer();
|
|
132
|
-
out.push({ role: 'user', content: ev.content });
|
|
133
|
-
}
|
|
134
|
-
else if (ev.kind === 'assistant') {
|
|
135
|
-
flushBuffer();
|
|
136
|
-
if (ev.tool_calls && ev.tool_calls.length > 0) {
|
|
137
|
-
// 进入延迟 push 模式
|
|
138
|
-
pendingToolCalls = new Set(ev.tool_calls.map((tc) => tc.id));
|
|
139
|
-
// Sprint 1c-revive-2-D-21.1 (2026-06-06, 修 DeepSeek V4 thinking 400 bug):
|
|
140
|
-
// reasoning_content 透传回 ChatMessage, 跟 content / tool_calls 一起 reload.
|
|
141
|
-
// 让 reload 后下轮 LLM call wire 仍带 reasoning_content, 避免 DeepSeek V4
|
|
142
|
-
// 多轮 400. 旧 session (无 reasoning_content 字段) 走 omit 分支, 行为不变.
|
|
143
|
-
const msg = {
|
|
144
|
-
role: 'assistant',
|
|
145
|
-
content: ev.content,
|
|
146
|
-
...(ev.reasoning_content !== undefined
|
|
147
|
-
? { reasoning_content: ev.reasoning_content }
|
|
148
|
-
: {}),
|
|
149
|
-
};
|
|
150
|
-
msg.tool_calls = [...ev.tool_calls];
|
|
151
|
-
buffer.push(msg);
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
// Sprint 1c-revive-2-D-21.1 (2026-06-06): 同样 reasoning_content 透传.
|
|
155
|
-
const msg = {
|
|
156
|
-
role: 'assistant',
|
|
157
|
-
content: ev.content,
|
|
158
|
-
...(ev.reasoning_content !== undefined
|
|
159
|
-
? { reasoning_content: ev.reasoning_content }
|
|
160
|
-
: {}),
|
|
161
|
-
};
|
|
162
|
-
out.push(msg);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
else if (ev.kind === 'tool') {
|
|
166
|
-
if (pendingToolCalls.has(ev.tool_call_id)) {
|
|
167
|
-
pendingToolCalls.delete(ev.tool_call_id);
|
|
168
|
-
buffer.push({
|
|
169
|
-
role: 'tool',
|
|
170
|
-
content: ev.result.content,
|
|
171
|
-
tool_call_id: ev.tool_call_id,
|
|
172
|
-
name: ev.name,
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
// 孤儿 tool (没匹配 assistant tool_call): 丢 — 不会出现无主 tool message
|
|
176
|
-
}
|
|
177
|
-
else if (ev.kind === 'compaction') {
|
|
178
|
-
// Sprint 1c-revive-2-D-5+ (review P1 修复, 2026-06-04): replay 到 messages.
|
|
179
|
-
// 协议 (see header comment L88-L102 for index space):
|
|
180
|
-
// 1. flushBuffer first, to flush any un-settled assistant(tool_calls)
|
|
181
|
-
// and prevent a dangling transcript (tool_call mid-way + compaction
|
|
182
|
-
// event = invalid half-transcript).
|
|
183
|
-
// 2. replaced_range is the JSONL-accumulated index space, equal to
|
|
184
|
-
// the current out accumulation.
|
|
185
|
-
// 3. Splice out[start..end) and insert 1 system summary at position
|
|
186
|
-
// start.
|
|
187
|
-
// 容错 (safe-fail):
|
|
188
|
-
// - start > out.length: skip (replaced_range is the trailing-tail
|
|
189
|
-
// index, already covered by a prior compaction; this event
|
|
190
|
-
// shouldn't occur unless JSONL was hand-edited, we take the
|
|
191
|
-
// safe path).
|
|
192
|
-
// - end > out.length but start <= out.length: splice out the
|
|
193
|
-
// remaining tail and insert summary at position start (a new
|
|
194
|
-
// user event may have pushed the tail off the end).
|
|
195
|
-
// - start < 0 or end < start: skip (corrupt event).
|
|
196
|
-
// 'compaction_paused' event: does NOT enter messages. The caller
|
|
197
|
-
// decides whether to reset the latch; UI/footer reads paused event
|
|
198
|
-
// explicitly for status display.
|
|
199
|
-
flushBuffer();
|
|
200
|
-
const [start, end] = ev.replaced_range;
|
|
201
|
-
if (start < 0 || end < start)
|
|
202
|
-
continue; // 损坏 event
|
|
203
|
-
if (start > out.length)
|
|
204
|
-
continue; // out 没积累到, 跳过 (见上)
|
|
205
|
-
const removeCount = Math.min(end - start, out.length - start);
|
|
206
|
-
out.splice(start, removeCount, {
|
|
207
|
-
role: 'system',
|
|
208
|
-
content: `[Session compaction summary]\n${ev.summary}`,
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
// 'system' / 'compaction_paused' / 'verification' / 'policy_decision' 跳过 — 4 种都是 metadata, 不进 LLM context:
|
|
212
|
-
// - 'system' caller 决定要不要用
|
|
213
|
-
// - 'compaction_paused' UI/footer 显式读
|
|
214
|
-
// - 'verification' (Sprint 1c-revive-2-D-11-3, 2026-06-04) audit log / viewer 显式读
|
|
215
|
-
// reload session 时验证历史不污染 LLM 看到的 messages 列表
|
|
216
|
-
// - 'policy_decision' (Sprint 1c-revive-3-D-13, 2026-06-05) tool policy 决策审计, 同 verification
|
|
217
|
-
// 不进 LLM context. 'allow' 不写 (避免 JSONL 刷爆), 只 deny / require_confirmation /
|
|
218
|
-
// user_approved / user_denied 4 个终态落盘, 跟 verification 同 metadata 拍板.
|
|
219
|
-
}
|
|
220
|
-
// EOF: 调 flushBuffer 而非硬清空.
|
|
221
|
-
// 修复: 旧实现 `buffer = []` 把"assistant(tool_calls) → tool 已配对完成但
|
|
222
|
-
// final assistant 还没落盘" 的合法 transcript 也丢了 — 这种 crash 真实存在
|
|
223
|
-
// (工具结果已 fsync, 进程在生成最终回答前被杀, LLM 续聊需要看到 tool result
|
|
224
|
-
// 才能继续生成). 现在 EOF 走 flushBuffer, pending 空时正常 push buffer.
|
|
225
|
-
flushBuffer();
|
|
226
|
-
return out;
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* 写一个 user event 到 session。
|
|
230
|
-
* Sprint 1a 简化:user 消息也走 SessionWriter(统一审计)。
|
|
231
|
-
*/
|
|
232
|
-
export async function appendUserEvent(writer, content, ts = Date.now()) {
|
|
233
|
-
await writer.append({ kind: 'user', ts, content });
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* 写一条 'compaction' event 到 session (Sprint 1c-revive-2-D-5-1 拍板).
|
|
237
|
-
*
|
|
238
|
-
* 用途: agent-compaction.ts 在 runCompactionWithLatch 返 kind='ok' 时调,
|
|
239
|
-
* 把 summary 拍板落盘 (供 reload 重建 messages 时知道哪段被总结过).
|
|
240
|
-
*
|
|
241
|
-
* 拍板: SessionReader 读到 kind='compaction' 时**不**重放进 LLM context
|
|
242
|
-
* (跟 sessionEventsToMessages L132 'system' 跳过 一致 — compaction event 是 metadata,
|
|
243
|
-
* 不是 LLM 看到的对话轮次).
|
|
244
|
-
*/
|
|
245
|
-
export async function appendCompactionEvent(writer, summary, replacedRange, meta, ts = Date.now()) {
|
|
246
|
-
await writer.append({
|
|
247
|
-
kind: 'compaction',
|
|
248
|
-
ts,
|
|
249
|
-
summary,
|
|
250
|
-
replaced_range: replacedRange,
|
|
251
|
-
...(meta !== undefined ? { meta } : {}),
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* 写一条 'compaction_paused' event 到 session (Sprint 1c-revive-2-D-5-2 拍板).
|
|
256
|
-
*
|
|
257
|
-
* 用途: agent-compaction.ts 在 CompactionState latch 触发时调,
|
|
258
|
-
* 记录"自动暂停, 防 death loop" 拍板 (供 reload 时 caller 知道状态).
|
|
259
|
-
*
|
|
260
|
-
* 拍板: SessionReader 读到 kind='compaction_paused' 时**不**重放进 LLM context
|
|
261
|
-
* (caller 该决定是否 reset CompactionState / 改 summaryFn / 改 config).
|
|
262
|
-
*/
|
|
263
|
-
export async function appendCompactionPausedEvent(writer, consecutiveFailures, reason, lastError, meta, ts = Date.now()) {
|
|
264
|
-
await writer.append({
|
|
265
|
-
kind: 'compaction_paused',
|
|
266
|
-
ts,
|
|
267
|
-
consecutive_failures: consecutiveFailures,
|
|
268
|
-
reason,
|
|
269
|
-
last_error: lastError,
|
|
270
|
-
...(meta !== undefined ? { meta } : {}),
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* 把 tool loop 跑完后产出的 steps 全部落盘(assistant + tool)。
|
|
275
|
-
* limit/error 跳过(toSessionEvent 返回 null 时不 append)。
|
|
276
|
-
*/
|
|
277
|
-
export async function persistToolLoopSteps(writer, steps) {
|
|
278
|
-
for (const step of steps) {
|
|
279
|
-
const ev = toolLoopStepToSessionEvent(step);
|
|
280
|
-
if (ev !== null) {
|
|
281
|
-
await writer.append(ev);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* 加载已有 session 并重建 messages。
|
|
287
|
-
*
|
|
288
|
-
* Sprint 1b: 内部自动调 reader.truncate() 把 partial last line 清掉。
|
|
289
|
-
* 之前 caller 必须自己记得调, Sprint 1a 全部漏调 → partial line 累积,
|
|
290
|
-
* 下次 append 拼坏 JSON。Sprint 1b 闭环在 adapter 里, 3 个 mode (repl/print/rpc) 自动受益。
|
|
291
|
-
*
|
|
292
|
-
* 行为契约:
|
|
293
|
-
* - 加载完整 events + 重建 messages
|
|
294
|
-
* - 若文件末尾有 partial line(崩溃恢复), 自动 truncate
|
|
295
|
-
* - truncate 失败不抛(不阻塞 agent 启动, 跟 Sprint 1a 容错语义一致)
|
|
296
|
-
*
|
|
297
|
-
* Sprint 1a 简化:返回 (events, messages) 两份数据, caller 决定要不要 ignore events。
|
|
298
|
-
*/
|
|
299
|
-
export async function loadSession(reader) {
|
|
300
|
-
const events = await reader.readAll();
|
|
301
|
-
// Sprint 1b: 闭环 truncate, 防止 partial line 累积污染下次 append
|
|
302
|
-
try {
|
|
303
|
-
await reader.truncate();
|
|
304
|
-
}
|
|
305
|
-
catch {
|
|
306
|
-
// truncate 失败不阻塞启动(可能是权限/磁盘满等, 但 events 已读到内存)
|
|
307
|
-
}
|
|
308
|
-
return { events, messages: sessionEventsToMessages(events) };
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* 写一个 'verification' event 到 session (Sprint 1c-revive-2-D-11-3, 2026-06-04).
|
|
312
|
-
*
|
|
313
|
-
* 调用场景: `deepwhale --verify` 或 REPL `/verify` 跑完, 把 VerificationReport
|
|
314
|
-
* 摘要写 1 条到 session JSONL. 跟 `appendUserEvent` / `appendCompactionEvent` 模式一致.
|
|
315
|
-
*
|
|
316
|
-
* 字段 (跟 core/src/session/jsonl.ts 'verification' union 一致):
|
|
317
|
-
* - status: 整体结果 passed / failed
|
|
318
|
-
* - durationMs: 整体耗时
|
|
319
|
-
* - command_count: 跑的 step 数
|
|
320
|
-
* - failed_count: 失败 step 数
|
|
321
|
-
* - summary: 人类可读 summary (来自 formatter.buildSummaryAndNext)
|
|
322
|
-
* - meta: 可选扩展 (e.g. log file path, git sha)
|
|
323
|
-
*
|
|
324
|
-
* 不变量 (跟其它 event 写入一致):
|
|
325
|
-
* - ts 默认 Date.now(), 单测可注入
|
|
326
|
-
* - 走 SessionWriter.append → fsync 串行化, 顺序保证
|
|
327
|
-
* - 'verification' 是 metadata, reload session 时 sessionEventsToMessages 跳过
|
|
328
|
-
* (跟 compaction_paused 同语义), 不污染 LLM 看到的 messages
|
|
329
|
-
*/
|
|
330
|
-
export async function appendVerificationEvent(writer, args) {
|
|
331
|
-
await writer.append({
|
|
332
|
-
kind: 'verification',
|
|
333
|
-
ts: args.ts ?? Date.now(),
|
|
334
|
-
status: args.status,
|
|
335
|
-
durationMs: args.durationMs,
|
|
336
|
-
command_count: args.commandCount,
|
|
337
|
-
failed_count: args.failedCount,
|
|
338
|
-
summary: args.summary,
|
|
339
|
-
...(args.meta !== undefined ? { meta: args.meta } : {}),
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* 写一条 'policy_decision' event (Sprint 1c-revive-3-D-13, 2026-06-05).
|
|
344
|
-
* 拍板 (用户 2026-06-05): 'allow' 不调本函数 (避免 JSONL 刷爆). 只对
|
|
345
|
-
* 'deny' / 'require_confirmation' / 'user_approved' / 'user_denied' 4 个
|
|
346
|
-
* 终态落盘.
|
|
347
|
-
*
|
|
348
|
-
* 字段拍板:
|
|
349
|
-
* - tool_call_id: 跟后续 'tool' event 配对 (reload 时 audit trace 完整)
|
|
350
|
-
* - argsDigest: sha256:<12hex>, 不存原始 args
|
|
351
|
-
* - reason: 已过 sanitize (长度 / 换行 / NUL, 拍板红线: 不存 secret)
|
|
352
|
-
*/
|
|
353
|
-
export async function appendPolicyDecisionEvent(writer, args) {
|
|
354
|
-
await writer.append({
|
|
355
|
-
kind: 'policy_decision',
|
|
356
|
-
ts: args.ts ?? Date.now(),
|
|
357
|
-
tool_call_id: args.tool_call_id,
|
|
358
|
-
name: args.name,
|
|
359
|
-
decision: args.decision,
|
|
360
|
-
argsDigest: args.argsDigest,
|
|
361
|
-
...(args.reason !== undefined ? { reason: args.reason } : {}),
|
|
362
|
-
...(args.meta !== undefined ? { meta: args.meta } : {}),
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
//# sourceMappingURL=session-adapter.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"session-adapter.js","sourceRoot":"","sources":["../../src/agent/session-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool Loop — minimal agent loop (Sprint 1a)
|
|
3
|
-
*
|
|
4
|
-
* 协议(Codex/oh-my-pi 借鉴):
|
|
5
|
-
* 1. 把 system + history 喂给 LLM
|
|
6
|
-
* 2. 如果 LLM 返回 tool_calls:
|
|
7
|
-
* - 用 ToolRegistry 调工具(schema 校验 Sprint 1b 加)
|
|
8
|
-
* - 把结果作为 tool 消息 push 回 messages
|
|
9
|
-
* - 回到 (1)
|
|
10
|
-
* 3. 如果 LLM 返回 content(finish_reason='stop')→ 终结
|
|
11
|
-
* 4. 如果 max_steps 触顶 → 抛 ToolLoopLimitError
|
|
12
|
-
*
|
|
13
|
-
* Sprint 1a 范围(极简):
|
|
14
|
-
* - 同步(不并发 tool_calls;DeepSeek V4 Flash 一次只调 1 个常见)
|
|
15
|
-
* - 不做 budget cap(v2.0)
|
|
16
|
-
* - 不做 schema 校验(trust LLM 输出,argparse 失败时 tool 返回 error 即可)
|
|
17
|
-
* - 不做 plan mode(v2.5)
|
|
18
|
-
* - 不做 cost accounting(1b 加)
|
|
19
|
-
* - 流式:可选 onChunk 回调(REPL 用)
|
|
20
|
-
*
|
|
21
|
-
* 错误处理:
|
|
22
|
-
* - tool 自身失败 → tool 消息 content 是 error,loop 继续
|
|
23
|
-
* - LLM 失败 → 抛 LLMError(caller 决定是否 retry/终止)
|
|
24
|
-
* - max_steps 触顶 → 抛 ToolLoopLimitError(caller 决定是否放弃)
|
|
25
|
-
*
|
|
26
|
-
* @module @deepwhale/coding-agent/agent
|
|
27
|
-
*/
|
|
28
|
-
import type { ChatMessage, ChatResult, LLMClient, ToolCall } from '@deepwhale/llm';
|
|
29
|
-
import type { ToolResult } from '../types.js';
|
|
30
|
-
import type { ToolRegistry } from '../tools/registry.js';
|
|
31
|
-
import type { ToolPolicy } from '../policy/types.js';
|
|
32
|
-
import type { SessionWriter } from '@deepwhale/core';
|
|
33
|
-
/** Sprint 1a 默认:跟 LLM 来回 5 轮(够用 coding agent 短任务,长任务 caller 调高)。 */
|
|
34
|
-
export declare const TOOL_LOOP_DEFAULT_MAX_STEPS = 5;
|
|
35
|
-
export interface ToolLoopOptions {
|
|
36
|
-
/** 注入工具注册表(默认 createDefaultRegistry())。 */
|
|
37
|
-
registry?: ToolRegistry;
|
|
38
|
-
/** 上限:单次 loop LLM call 次数(含 tool_calls 触发的回传)。默认 5。 */
|
|
39
|
-
maxSteps?: number;
|
|
40
|
-
/** 给所有 tool 调用的 timeout ms。Sprint 1a 不支持单 tool 自定义 timeout。 */
|
|
41
|
-
toolTimeoutMs?: number;
|
|
42
|
-
/** 流式 chunk 回调(null/undefined = 不流式)。REPL 接 onChunk 实时打印。 */
|
|
43
|
-
onChunk?: (chunk: {
|
|
44
|
-
content?: string;
|
|
45
|
-
tool_calls?: ReadonlyArray<ToolCall>;
|
|
46
|
-
}) => void;
|
|
47
|
-
/** 外部 abort signal(Ctrl-C / session 结束)。 */
|
|
48
|
-
signal?: AbortSignal;
|
|
49
|
-
/**
|
|
50
|
-
* Sprint 1c-revive-3-D-13 (2026-06-05): tool call policy.
|
|
51
|
-
* 默认 staticToolPolicy. 显式传 null = 不检查 (单测用).
|
|
52
|
-
* 拍板: 'allow' 不写 session, 只有 deny / require_confirmation 落 policy_decision.
|
|
53
|
-
*/
|
|
54
|
-
policy?: ToolPolicy | null;
|
|
55
|
-
/** Sprint 1c-revive-3-D-13: 模式是否可交互 (REPL = true, print/rpc 默认 = false). */
|
|
56
|
-
isInteractive?: boolean;
|
|
57
|
-
/** Sprint 1c-revive-3-D-13: --yes 标志. yes=true bypass require_confirmation, 不 bypass deny. */
|
|
58
|
-
yes?: boolean;
|
|
59
|
-
/** Sprint 1c-revive-3-D-13: session writer 注入 (写 policy_decision event 用). */
|
|
60
|
-
writer?: SessionWriter | null;
|
|
61
|
-
}
|
|
62
|
-
export type ToolLoopStep = {
|
|
63
|
-
kind: 'assistant';
|
|
64
|
-
ts: number;
|
|
65
|
-
message: ChatMessage;
|
|
66
|
-
result: ChatResult;
|
|
67
|
-
} | {
|
|
68
|
-
kind: 'tool';
|
|
69
|
-
ts: number;
|
|
70
|
-
tool_call: ToolCall;
|
|
71
|
-
result: ToolResult;
|
|
72
|
-
duration_ms: number;
|
|
73
|
-
} | {
|
|
74
|
-
kind: 'limit';
|
|
75
|
-
ts: number;
|
|
76
|
-
steps: number;
|
|
77
|
-
lastResult: ChatResult;
|
|
78
|
-
} | {
|
|
79
|
-
kind: 'error';
|
|
80
|
-
ts: number;
|
|
81
|
-
error: Error;
|
|
82
|
-
};
|
|
83
|
-
export interface ToolLoopResult {
|
|
84
|
-
/** 全部 messages(含 tool_calls 步骤),caller 用来继续下一轮。 */
|
|
85
|
-
messages: ChatMessage[];
|
|
86
|
-
/** 最后一次 assistant ChatResult(content + tool_calls + usage)。 */
|
|
87
|
-
final: ChatResult;
|
|
88
|
-
/**
|
|
89
|
-
* 完整 step 序列(含 tool 调用、limit、error),caller 用来回放/审计/持久化。
|
|
90
|
-
* Sprint 1a 极简:caller 通过 runToolLoop 后读取 .steps 自己落盘。
|
|
91
|
-
* Sprint 1b 加 onStep 实时回调(避免 caller 等跑完才落)。
|
|
92
|
-
*/
|
|
93
|
-
steps: ToolLoopStep[];
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* 错误:maxSteps 触顶、LLM 一直在调工具不收敛。
|
|
97
|
-
* caller 通常应当:缩短 prompt / 拆任务 / 主动放弃。
|
|
98
|
-
*/
|
|
99
|
-
export declare class ToolLoopLimitError extends Error {
|
|
100
|
-
readonly steps: number;
|
|
101
|
-
readonly lastResult: ChatResult;
|
|
102
|
-
readonly name: "ToolLoopLimitError";
|
|
103
|
-
readonly isToolLoopError: true;
|
|
104
|
-
constructor(steps: number, lastResult: ChatResult);
|
|
105
|
-
}
|
|
106
|
-
/** 类型守卫。 */
|
|
107
|
-
export declare function isToolLoopError(err: unknown): err is ToolLoopLimitError;
|
|
108
|
-
/**
|
|
109
|
-
* 执行一轮 tool loop。
|
|
110
|
-
*
|
|
111
|
-
* 行为契约:
|
|
112
|
-
* - 不修改输入 messages(immutable),返回**新**数组(带 tool 步骤)
|
|
113
|
-
* - 任何 LLM 调用失败 → 抛 LLMError(ToolLoopStep.error 事件也写入 steps)
|
|
114
|
-
* - tool 自身失败 → 不抛,包成 tool 消息的 error content 继续
|
|
115
|
-
* - maxSteps 触顶 → 抛 ToolLoopLimitError(steps 同时写入)
|
|
116
|
-
* - 外部 abort → 抛带 cause 的 LLMUnknownError(包装 AbortError)
|
|
117
|
-
*
|
|
118
|
-
* Sprint 1a 限制:
|
|
119
|
-
* - 只支持非流式调用时 onChunk=null;有 onChunk 时走 stream()。
|
|
120
|
-
* - onChunk 触发的内容**也**写入最终 final.content(assembled)
|
|
121
|
-
*/
|
|
122
|
-
export declare function runToolLoop(client: LLMClient, messages: ReadonlyArray<ChatMessage>, options?: ToolLoopOptions): Promise<ToolLoopResult>;
|
|
123
|
-
//# sourceMappingURL=tool-loop.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool-loop.d.ts","sourceRoot":"","sources":["../../src/agent/tool-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAiB,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAGlG,OAAO,KAAK,EAAQ,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAMrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,oEAAoE;AACpE,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;KAAE,KAAK,IAAI,CAAC;IACtF,4CAA4C;IAC5C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;OAIG;IACH,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC3B,4EAA4E;IAC5E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,8FAA8F;IAC9F,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,8EAA8E;IAC9E,MAAM,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,GAC3E;IACE,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,QAAQ,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB,GACD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,+DAA+D;IAC/D,KAAK,EAAE,UAAU,CAAC;IAClB;;;;OAIG;IACH,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;aAIzB,KAAK,EAAE,MAAM;aACb,UAAU,EAAE,UAAU;IAJxC,SAAkB,IAAI,EAAG,oBAAoB,CAAU;IACvD,QAAQ,CAAC,eAAe,EAAG,IAAI,CAAU;gBAEvB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,UAAU;CAIzC;AAED,YAAY;AACZ,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,kBAAkB,CAEvE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,aAAa,CAAC,WAAW,CAAC,EACpC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,cAAc,CAAC,CAgGzB"}
|