@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
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sprint 1c-revive-3-D-13 (2026-06-05): 默认静态规则.
|
|
3
|
+
* Sprint 1c-revive-3-D-13 review P1 修复 (2026-06-05):
|
|
4
|
+
* - 合并 command + args 成 1 条字符串再 regex match (解决 `mv a b` / `cp a b` 等
|
|
5
|
+
* command-only regex 漏判的问题). 不引 shlex dep, 拍板 MVP 接受 edge case 漏判.
|
|
6
|
+
* - 拍板 (用户 2026-06-05 review): "v1.0 红线是'未经确认不 mv', 不只是 /etc/系统路径;
|
|
7
|
+
* cp 一起收, 宁可多弹确认". 加 mv / cp 全部 → require_confirmation.
|
|
8
|
+
*
|
|
9
|
+
* 拍板 (用户 2026-06-05):
|
|
10
|
+
* - A1: 默认规则 (read/find/grep 全 allow, write/edit 全 require_confirmation)
|
|
11
|
+
* - B1: bash 用 regex/argv-light 检测危险模式 → require_confirmation (不直接 deny,
|
|
12
|
+
* 误判只是多弹确认, 比 deny 漏判安全)
|
|
13
|
+
* - R-1: race 接受为 MVP 风险, D-15 用 inotify / mutex 收
|
|
14
|
+
* - R-2: bash 漏判 (e.g. shlex quote 拆分) 接受, 走 require_confirmation 而非 deny
|
|
15
|
+
*
|
|
16
|
+
* 不做 (D-15):
|
|
17
|
+
* - 用户 config 注入 (ToolPolicy 透传, D-13 默认走 static)
|
|
18
|
+
* - 路径白名单/黑名单
|
|
19
|
+
* - Bash argv deep parse (e.g. shlex)
|
|
20
|
+
* - Secret 强检测 (redact API key in reason)
|
|
21
|
+
*/
|
|
22
|
+
// bash 危险模式 (regex) — argv-light, 不深 parse
|
|
23
|
+
// 拍板 (用户 2026-06-05): 走 require_confirmation 而非 deny, 误判只是多弹确认
|
|
24
|
+
// 注: tool-loop 调 evaluateBashCommand 时会把 command + args 合并成 1 条字符串再 match,
|
|
25
|
+
// 解决 `mv a b` / `cp a b` 等 command-only regex 漏判的问题
|
|
26
|
+
const DANGEROUS_BASH_PATTERNS = [
|
|
27
|
+
// === 文件破坏 (v1.0 红线) ===
|
|
28
|
+
// rm -rf / or rm -fr / (path start with /)
|
|
29
|
+
/\brm\s+(?:-[a-zA-Z]*[rf][a-zA-Z]*)+[^\n]*\//i,
|
|
30
|
+
// rm -rf ~ (home dir wipe)
|
|
31
|
+
/\brm\s+(?:-[a-zA-Z]*[rf][a-zA-Z]*)+[^\n]*~/i,
|
|
32
|
+
// mv 全部 (用户 review 拍板: "v1.0 红线是'未经确认不 mv', 不只是 /etc/系统路径")
|
|
33
|
+
// 拍板 (2026-06-05): 宁多弹确认, 漏 mv 风险太高
|
|
34
|
+
/\bmv\b/,
|
|
35
|
+
// cp 全部 (跟 mv 同拍板: 宁多弹确认)
|
|
36
|
+
/\bcp\b/,
|
|
37
|
+
// chown / chmod 改权限 (chmod 777 是经典写错场景)
|
|
38
|
+
/\bchown\b/i,
|
|
39
|
+
/\bchmod\b/i,
|
|
40
|
+
// === 系统 / 磁盘 ===
|
|
41
|
+
// mkfs (format filesystem)
|
|
42
|
+
/\bmkfs(?:\.\w+)?\b/i,
|
|
43
|
+
// dd if= (raw disk write)
|
|
44
|
+
/\bdd\s+if=/i,
|
|
45
|
+
// shutdown / reboot / halt / poweroff
|
|
46
|
+
/\b(shutdown|reboot|halt|poweroff)\b/i,
|
|
47
|
+
// redirect to /dev/sda or /dev/nvme* (raw disk overwrite)
|
|
48
|
+
/>\s*\/dev\/(sda|nvme\d)/i,
|
|
49
|
+
// === 远程下载 + 执行 (curl|sh, wget|bash) ===
|
|
50
|
+
// curl ... | sh / bash / python
|
|
51
|
+
/\bcurl\b[^\n]*\|\s*(sh|bash|python\d*|zsh|ksh|fish)/i,
|
|
52
|
+
/\bwget\b[^\n]*\|\s*(sh|bash|python\d*|zsh|ksh|fish)/i,
|
|
53
|
+
// curl -o /path + chmod + execute 套路 (远程 dropper)
|
|
54
|
+
/\bcurl\b[^\n]*-o\s+\/tmp\//i,
|
|
55
|
+
/\bwget\b[^\n]*-O\s+\/tmp\//i,
|
|
56
|
+
];
|
|
57
|
+
/**
|
|
58
|
+
* bash regex 危险模式 — 暴露给 tool-loop 在 bash 工具自身层也用 (双重防线)
|
|
59
|
+
*
|
|
60
|
+
* Sprint 1c-revive-3-D-13 review P1 修复 (2026-06-05):
|
|
61
|
+
* 拍板 (用户 2026-06-05): "bash 检测先轻量合并 command + args"
|
|
62
|
+
* 不引 shlex dep, MVP 接受 quote 拆分漏判 (R-2 拍板).
|
|
63
|
+
*/
|
|
64
|
+
export function evaluateBashCommand(cmd, args) {
|
|
65
|
+
// 拍板: 合并 command + " " + args.join(" ") 一条字符串再 regex match.
|
|
66
|
+
// 拍板: 不 strip quote, 不引 shlex (R-2 拍板). 漏判走 require_confirmation 而非 deny.
|
|
67
|
+
const merged = args.length > 0 ? `${cmd} ${args.join(' ')}` : cmd;
|
|
68
|
+
for (const pat of DANGEROUS_BASH_PATTERNS) {
|
|
69
|
+
if (pat.test(merged)) {
|
|
70
|
+
return {
|
|
71
|
+
decision: 'require_confirmation',
|
|
72
|
+
reason: `bash command matches dangerous pattern: ${pat.source}`,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return { decision: 'allow' };
|
|
77
|
+
}
|
|
78
|
+
function evaluateByToolName(name, _argsDigest) {
|
|
79
|
+
switch (name) {
|
|
80
|
+
case 'read_file':
|
|
81
|
+
case 'find':
|
|
82
|
+
case 'grep':
|
|
83
|
+
return { decision: 'allow' };
|
|
84
|
+
case 'write_file':
|
|
85
|
+
case 'edit_file':
|
|
86
|
+
return { decision: 'require_confirmation', reason: 'writes to filesystem' };
|
|
87
|
+
case 'bash':
|
|
88
|
+
// bash 实际 evaluate 需要 parse cmd + args. 这层拿不到, tool-loop 层 bash 工具自身用 evaluateBashCommand 拍.
|
|
89
|
+
// 保守返 allow (bash tool 会自己再过一遍 evaluateBashCommand).
|
|
90
|
+
return { decision: 'allow' };
|
|
91
|
+
default: {
|
|
92
|
+
// 兜底: "未在白名单" 的 tool (含 caller 自注册 tool, e.g. test 'hanger') 走 allow.
|
|
93
|
+
// 拍板 (D-13): 'tool-not-found' 已经在 executeToolCall 上层 (registry.get 拍)
|
|
94
|
+
// 拦了, policy 这层不需要再判 unknown. 给 caller 自定义 tool 留口 (D-15 user config 接入
|
|
95
|
+
// 也会用 default 分支).
|
|
96
|
+
return { decision: 'allow' };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export const staticToolPolicy = {
|
|
101
|
+
evaluate(toolCall, _ctx) {
|
|
102
|
+
return evaluateByToolName(toolCall.name, toolCall.argsDigest);
|
|
103
|
+
},
|
|
104
|
+
// confirm 留 undefined — REPL / RPC 模式注入自己的 confirm 实现 (D-13 MVP 留空)
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=static-rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static-rules.js","sourceRoot":"","sources":["../../src/policy/static-rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAKH,2CAA2C;AAC3C,+DAA+D;AAC/D,2EAA2E;AAC3E,oDAAoD;AACpD,MAAM,uBAAuB,GAA0B;IACrD,yBAAyB;IACzB,2CAA2C;IAC3C,8CAA8C;IAC9C,2BAA2B;IAC3B,6CAA6C;IAC7C,4DAA4D;IAC5D,oCAAoC;IACpC,QAAQ;IACR,0BAA0B;IAC1B,QAAQ;IACR,wCAAwC;IACxC,YAAY;IACZ,YAAY;IAEZ,kBAAkB;IAClB,2BAA2B;IAC3B,qBAAqB;IACrB,0BAA0B;IAC1B,aAAa;IACb,sCAAsC;IACtC,sCAAsC;IACtC,0DAA0D;IAC1D,0BAA0B;IAE1B,yCAAyC;IACzC,gCAAgC;IAChC,sDAAsD;IACtD,sDAAsD;IACtD,kDAAkD;IAClD,6BAA6B;IAC7B,6BAA6B;CAC9B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAW,EAAE,IAA2B;IAC1E,4DAA4D;IAC5D,0EAA0E;IAC1E,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;IAClE,KAAK,MAAM,GAAG,IAAI,uBAAuB,EAAE,CAAC;QAC1C,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACrB,OAAO;gBACL,QAAQ,EAAE,sBAAsB;gBAChC,MAAM,EAAE,2CAA2C,GAAG,CAAC,MAAM,EAAE;aAChE,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC/B,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAc,EAAE,WAAmB;IAC7D,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,WAAW,CAAC;QACjB,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM;YACT,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QAC/B,KAAK,YAAY,CAAC;QAClB,KAAK,WAAW;YACd,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;QAC9E,KAAK,MAAM;YACT,6FAA6F;YAC7F,qDAAqD;YACrD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QAC/B,OAAO,CAAC,CAAC,CAAC;YACR,sEAAsE;YACtE,sEAAsE;YACtE,wEAAwE;YACxE,mBAAmB;YACnB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAe;IAC1C,QAAQ,CAAC,QAAwB,EAAE,IAAmB;QACpD,OAAO,kBAAkB,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IAChE,CAAC;IACD,oEAAoE;CACrE,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sprint 1c-revive-3-D-13 (2026-06-05)
|
|
3
|
+
*
|
|
4
|
+
* ToolPolicy interface + PolicyDecision 联合 + PolicyContext 拍板.
|
|
5
|
+
*
|
|
6
|
+
* 拍板红线 (用户 2026-06-05):
|
|
7
|
+
* - 'allow' 不写 session, 只有 'deny' / 'require_confirmation' / 用户确认结果
|
|
8
|
+
* ('user_approved' / 'user_denied') 落 'policy_decision' event
|
|
9
|
+
* - argsDigest 不存原始 args, 用 sha256: 前 12 位稳定关联
|
|
10
|
+
* - 拍板: deny 不被 --yes bypass
|
|
11
|
+
*/
|
|
12
|
+
import type { ToolName } from '@deepwhale/core';
|
|
13
|
+
/** Policy 决策 — 3 个判别式 + 2 个 user_* 终态 (session audit 用) */
|
|
14
|
+
export type PolicyDecision = {
|
|
15
|
+
decision: 'allow';
|
|
16
|
+
} | {
|
|
17
|
+
decision: 'deny';
|
|
18
|
+
reason: string;
|
|
19
|
+
} | {
|
|
20
|
+
decision: 'require_confirmation';
|
|
21
|
+
reason: string;
|
|
22
|
+
};
|
|
23
|
+
/** tool call 描述 — 不带原始 args, 用 argsDigest 关联 (拍板: 不暴露 secret) */
|
|
24
|
+
export interface PolicyToolCall {
|
|
25
|
+
readonly name: ToolName;
|
|
26
|
+
/** sha256:<12hex> 拍板 */
|
|
27
|
+
readonly argsDigest: string;
|
|
28
|
+
}
|
|
29
|
+
export interface PolicyContext {
|
|
30
|
+
/** 模式是否可交互 (REPL = true, print / rpc 默认 = false) */
|
|
31
|
+
readonly isInteractive: boolean;
|
|
32
|
+
/** --yes 标志: 只 bypass require_confirmation, 不 bypass deny */
|
|
33
|
+
readonly yes: boolean;
|
|
34
|
+
/** tool call args 的稳定 sha256: 前 12 位 */
|
|
35
|
+
readonly argsDigest: string;
|
|
36
|
+
}
|
|
37
|
+
export interface ToolPolicy {
|
|
38
|
+
/**
|
|
39
|
+
* 拍板: 调用一次返回最终 decision. 拍板: 不抛异常, 内部失败也返 deny.
|
|
40
|
+
* 拍板: 纯函数, 不读 stdin, 不打 console. caller (tool-loop) 负责 IO.
|
|
41
|
+
*/
|
|
42
|
+
evaluate(toolCall: PolicyToolCall, ctx: PolicyContext): PolicyDecision;
|
|
43
|
+
/**
|
|
44
|
+
* 拍板: 用户确认回调. REPL 走 readline, RPC 走 NDJSON "confirm" 通知 (D-15).
|
|
45
|
+
* 拍板: undefined = "未实现" 兜底, caller 走 fail-closed deny.
|
|
46
|
+
* 拍板: return true = 用户同意, false = 拒绝, null = dismiss (也走 deny).
|
|
47
|
+
*
|
|
48
|
+
* Sprint 1c-revive-3-D-19 (2026-06-05): opts.signal 可选 — REPL SIGINT/turn
|
|
49
|
+
* 取消时, 注入 turn-level AbortSignal, confirm 收到 abort 立刻 resolve null.
|
|
50
|
+
* 老实现 (单参) 继续合法 (opts 默认 undefined).
|
|
51
|
+
*/
|
|
52
|
+
confirm?(prompt: string, opts?: {
|
|
53
|
+
signal?: AbortSignal;
|
|
54
|
+
}): Promise<boolean | null>;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/policy/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD,2DAA2D;AAC3D,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,GACrB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,QAAQ,EAAE,sBAAsB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD,iEAAiE;AACjE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,wBAAwB;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,oDAAoD;IACpD,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,6DAA6D;IAC7D,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,wCAAwC;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,aAAa,GAAG,cAAc,CAAC;IAEvE;;;;;;;;OAQG;IACH,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;CACpF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sprint 1c-revive-3-D-13 (2026-06-05)
|
|
3
|
+
*
|
|
4
|
+
* ToolPolicy interface + PolicyDecision 联合 + PolicyContext 拍板.
|
|
5
|
+
*
|
|
6
|
+
* 拍板红线 (用户 2026-06-05):
|
|
7
|
+
* - 'allow' 不写 session, 只有 'deny' / 'require_confirmation' / 用户确认结果
|
|
8
|
+
* ('user_approved' / 'user_denied') 落 'policy_decision' event
|
|
9
|
+
* - argsDigest 不存原始 args, 用 sha256: 前 12 位稳定关联
|
|
10
|
+
* - 拍板: deny 不被 --yes bypass
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/policy/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* REPL y/N confirmation prompt — Sprint 1c-revive-3-D-19 (2026-06-05).
|
|
3
|
+
*
|
|
4
|
+
* 历史:
|
|
5
|
+
* D-15 (2026-06-05): 工厂函数 + 内部 createInterface, 用 rl.question 收 y/N.
|
|
6
|
+
* 留 P1 (review blocker): 同流上主 rl + 子 rl 抢同一行, 用户输 y 时主 rl
|
|
7
|
+
* 会把 y 当新 chat turn 启动 (实测 Node repro 确认).
|
|
8
|
+
* D-19 (2026-06-05): 拆掉自创 readline, 改成 "caller 喂 line" 的纯 resolver.
|
|
9
|
+
* 主 REPL 的 rl.on('line') 是唯一 stdin 消费者, 确认期间把 line 喂给
|
|
10
|
+
* pending resolver, 解析完才放行, P1 串行化彻底.
|
|
11
|
+
*
|
|
12
|
+
* 拍板 (D-19, 2026-06-05):
|
|
13
|
+
* - API 形状: createReplConfirm(opts) 返回的 confirm() 不再内部读 stdin,
|
|
14
|
+
* 而是用 offerLine(rawLine) + 内部 Promise<boolean | null> 状态机.
|
|
15
|
+
* - prompt 格式: caller 拼好 "Allow <tool_name>? (<reason>) [y/N]: ",
|
|
16
|
+
* confirm() 内部只负责 "收一行 → 解析 → resolve".
|
|
17
|
+
* - 输入识别: y/yes/Y/YES → true; n/no/N/NO/空/other → false; abort → null.
|
|
18
|
+
* - abort signal 触发立即 resolve null (dismissed).
|
|
19
|
+
* - 同时只能有一个 pending 确认 (REPL 串行 chat-turn 拓扑保证).
|
|
20
|
+
* - offerLine 二次调用 = 抛错 (caller bug, 不能丢 silent).
|
|
21
|
+
*
|
|
22
|
+
* 拍板 (D-19 §out of scope): 不接 RPC confirmedTools (D-17), 不接 user policy
|
|
23
|
+
* config (D-16), 不做 TUI (D-18).
|
|
24
|
+
*/
|
|
25
|
+
export interface ReplConfirmOptions {
|
|
26
|
+
/**
|
|
27
|
+
* REPL 的 out (拿 prompt 字符出口). 用 NodeJS.WritableStream 是为了兼容
|
|
28
|
+
* startRepl 传进来的 NodeJS.WritableStream 类型 (vs node:stream Writable).
|
|
29
|
+
* D-19 内部只写 prompt, 不读.
|
|
30
|
+
*/
|
|
31
|
+
output: NodeJS.WritableStream;
|
|
32
|
+
}
|
|
33
|
+
export interface ReplConfirmCallOptions {
|
|
34
|
+
/** AbortSignal — 触发时 confirm 立即 resolve null (dismissed). D-19 修 Ctrl+C 链路. */
|
|
35
|
+
signal?: AbortSignal;
|
|
36
|
+
}
|
|
37
|
+
export type ReplConfirm = (prompt: string, options?: ReplConfirmCallOptions) => Promise<boolean | null>;
|
|
38
|
+
export interface ReplConfirmController {
|
|
39
|
+
/** 提示用户 (写到 output, 加 [y/N]: 后缀). 内部 start 一个 pending. */
|
|
40
|
+
confirm: ReplConfirm;
|
|
41
|
+
/** REPL 主 line handler 拿到 line 后调: 若有 pending → 喂给 confirm; 若无 → false (caller 走 chat). */
|
|
42
|
+
offerLine: (rawLine: string) => boolean;
|
|
43
|
+
/** 当前是否有 in-flight 确认 (caller 用此守卫主 rl.line). */
|
|
44
|
+
hasPending: () => boolean;
|
|
45
|
+
/** 强制取消 (caller 进程退出/EOF/cleanup). */
|
|
46
|
+
dismiss: () => void;
|
|
47
|
+
}
|
|
48
|
+
export declare function createReplConfirm(opts: ReplConfirmOptions): ReplConfirmController;
|
|
49
|
+
//# sourceMappingURL=repl-confirm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repl-confirm.d.ts","sourceRoot":"","sources":["../../src/repl/repl-confirm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;CAC/B;AAED,MAAM,WAAW,sBAAsB;IACrC,+EAA+E;IAC/E,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,MAAM,WAAW,GAAG,CACxB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,sBAAsB,KAC7B,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;AAQ7B,MAAM,WAAW,qBAAqB;IACpC,0DAA0D;IAC1D,OAAO,EAAE,WAAW,CAAC;IACrB,2FAA2F;IAC3F,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,iDAAiD;IACjD,UAAU,EAAE,MAAM,OAAO,CAAC;IAC1B,sCAAsC;IACtC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,GAAG,qBAAqB,CAqEjF"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* REPL y/N confirmation prompt — Sprint 1c-revive-3-D-19 (2026-06-05).
|
|
3
|
+
*
|
|
4
|
+
* 历史:
|
|
5
|
+
* D-15 (2026-06-05): 工厂函数 + 内部 createInterface, 用 rl.question 收 y/N.
|
|
6
|
+
* 留 P1 (review blocker): 同流上主 rl + 子 rl 抢同一行, 用户输 y 时主 rl
|
|
7
|
+
* 会把 y 当新 chat turn 启动 (实测 Node repro 确认).
|
|
8
|
+
* D-19 (2026-06-05): 拆掉自创 readline, 改成 "caller 喂 line" 的纯 resolver.
|
|
9
|
+
* 主 REPL 的 rl.on('line') 是唯一 stdin 消费者, 确认期间把 line 喂给
|
|
10
|
+
* pending resolver, 解析完才放行, P1 串行化彻底.
|
|
11
|
+
*
|
|
12
|
+
* 拍板 (D-19, 2026-06-05):
|
|
13
|
+
* - API 形状: createReplConfirm(opts) 返回的 confirm() 不再内部读 stdin,
|
|
14
|
+
* 而是用 offerLine(rawLine) + 内部 Promise<boolean | null> 状态机.
|
|
15
|
+
* - prompt 格式: caller 拼好 "Allow <tool_name>? (<reason>) [y/N]: ",
|
|
16
|
+
* confirm() 内部只负责 "收一行 → 解析 → resolve".
|
|
17
|
+
* - 输入识别: y/yes/Y/YES → true; n/no/N/NO/空/other → false; abort → null.
|
|
18
|
+
* - abort signal 触发立即 resolve null (dismissed).
|
|
19
|
+
* - 同时只能有一个 pending 确认 (REPL 串行 chat-turn 拓扑保证).
|
|
20
|
+
* - offerLine 二次调用 = 抛错 (caller bug, 不能丢 silent).
|
|
21
|
+
*
|
|
22
|
+
* 拍板 (D-19 §out of scope): 不接 RPC confirmedTools (D-17), 不接 user policy
|
|
23
|
+
* config (D-16), 不做 TUI (D-18).
|
|
24
|
+
*/
|
|
25
|
+
export function createReplConfirm(opts) {
|
|
26
|
+
let pending = null;
|
|
27
|
+
const settle = (v) => {
|
|
28
|
+
if (!pending)
|
|
29
|
+
return;
|
|
30
|
+
const p = pending;
|
|
31
|
+
pending = null;
|
|
32
|
+
if (p.abortHandler && p.abortHandler !== null) {
|
|
33
|
+
// no-op: signal listener 已被 offerLine / abortHandler 清理
|
|
34
|
+
}
|
|
35
|
+
p.resolve(v);
|
|
36
|
+
};
|
|
37
|
+
const confirm = (prompt, callOpts) => {
|
|
38
|
+
if (pending) {
|
|
39
|
+
// 拍板 (D-19): 同时只能有一个 pending, 二次 confirm 抛错 (caller bug).
|
|
40
|
+
return Promise.reject(new Error('repl-confirm: confirm() called while another confirmation is in flight. ' +
|
|
41
|
+
'Caller must serialize via hasPending() guard.'));
|
|
42
|
+
}
|
|
43
|
+
// 拍板 (D-19): caller 拼好 prompt, 我们只追加 [y/N]: 后缀.
|
|
44
|
+
const fullPrompt = `${prompt} [y/N]: `;
|
|
45
|
+
opts.output.write(fullPrompt);
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
const p = {
|
|
48
|
+
prompt: fullPrompt,
|
|
49
|
+
resolve,
|
|
50
|
+
abortHandler: null,
|
|
51
|
+
};
|
|
52
|
+
pending = p;
|
|
53
|
+
// abort signal — 立即 resolve null (dismissed)
|
|
54
|
+
if (callOpts?.signal) {
|
|
55
|
+
if (callOpts.signal.aborted) {
|
|
56
|
+
settle(null);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const handler = () => settle(null);
|
|
60
|
+
callOpts.signal.addEventListener('abort', handler, { once: true });
|
|
61
|
+
p.abortHandler = handler;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
const offerLine = (rawLine) => {
|
|
66
|
+
if (!pending)
|
|
67
|
+
return false;
|
|
68
|
+
const answer = rawLine.trim().toLowerCase();
|
|
69
|
+
if (answer === 'y' || answer === 'yes') {
|
|
70
|
+
settle(true);
|
|
71
|
+
}
|
|
72
|
+
else if (answer === 'n' || answer === 'no' || answer === '') {
|
|
73
|
+
settle(false);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// 拍板 (D-15 §Decision 3, D-19 沿用): other 当 N 处理 (不打扰)
|
|
77
|
+
settle(false);
|
|
78
|
+
}
|
|
79
|
+
return true;
|
|
80
|
+
};
|
|
81
|
+
const hasPending = () => pending !== null;
|
|
82
|
+
const dismiss = () => {
|
|
83
|
+
if (pending)
|
|
84
|
+
settle(null);
|
|
85
|
+
};
|
|
86
|
+
return { confirm, offerLine, hasPending, dismiss };
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=repl-confirm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repl-confirm.js","sourceRoot":"","sources":["../../src/repl/repl-confirm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAsCH,MAAM,UAAU,iBAAiB,CAAC,IAAwB;IACxD,IAAI,OAAO,GAA0B,IAAI,CAAC;IAE1C,MAAM,MAAM,GAAG,CAAC,CAAiB,EAAQ,EAAE;QACzC,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,MAAM,CAAC,GAAG,OAAO,CAAC;QAClB,OAAO,GAAG,IAAI,CAAC;QACf,IAAI,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;YAC9C,wDAAwD;QAC1D,CAAC;QACD,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACf,CAAC,CAAC;IAEF,MAAM,OAAO,GAAgB,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;QAChD,IAAI,OAAO,EAAE,CAAC;YACZ,0DAA0D;YAC1D,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,KAAK,CACP,0EAA0E;gBACxE,+CAA+C,CAClD,CACF,CAAC;QACJ,CAAC;QACD,gDAAgD;QAChD,MAAM,UAAU,GAAG,GAAG,MAAM,UAAU,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAE9B,OAAO,IAAI,OAAO,CAAiB,CAAC,OAAO,EAAE,EAAE;YAC7C,MAAM,CAAC,GAAmB;gBACxB,MAAM,EAAE,UAAU;gBAClB,OAAO;gBACP,YAAY,EAAE,IAAI;aACnB,CAAC;YACF,OAAO,GAAG,CAAC,CAAC;YAEZ,6CAA6C;YAC7C,IAAI,QAAQ,EAAE,MAAM,EAAE,CAAC;gBACrB,IAAI,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBAC5B,MAAM,CAAC,IAAI,CAAC,CAAC;oBACb,OAAO;gBACT,CAAC;gBACD,MAAM,OAAO,GAAG,GAAS,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACzC,QAAQ,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBACnE,CAAC,CAAC,YAAY,GAAG,OAAO,CAAC;YAC3B,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,CAAC,OAAe,EAAW,EAAE;QAC7C,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAC3B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YACvC,MAAM,CAAC,IAAI,CAAC,CAAC;QACf,CAAC;aAAM,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;YAC9D,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC;aAAM,CAAC;YACN,qDAAqD;YACrD,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,GAAY,EAAE,CAAC,OAAO,KAAK,IAAI,CAAC;IAEnD,MAAM,OAAO,GAAG,GAAS,EAAE;QACzB,IAAI,OAAO;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;AACrD,CAAC"}
|
package/dist/repl.d.ts
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* deepwhale REPL — Sprint 1a 接入 tool loop + session
|
|
3
|
+
*
|
|
4
|
+
* Sprint 0.3 范围:单轮 chat + 内建命令。
|
|
5
|
+
* Sprint 1a 扩展:
|
|
6
|
+
* - 接 Session JSONL:启动时 load(可选路径),退出时 close(flush)
|
|
7
|
+
* - 接 runToolLoop:每轮 user → tool loop → 持久化 steps
|
|
8
|
+
* - 流式:onChunk 实时打印 final.content(assistant 增量)
|
|
9
|
+
* - 命令:保留 /help / /exit / exit / quit
|
|
10
|
+
*
|
|
11
|
+
* Sprint 1a 简化:
|
|
12
|
+
* - 不做 plan mode、recovery、自动压缩
|
|
13
|
+
* - 不做 multi-session 切换
|
|
14
|
+
* - 错误用 i18n + 不污染 messages
|
|
15
|
+
*
|
|
16
|
+
* 文件职责:
|
|
17
|
+
* - runOneTurn: 仍保留为低层单轮 API(不持久化,无 tool loop)
|
|
18
|
+
* - startRepl: 接 tool loop + session 的入口
|
|
19
|
+
*/
|
|
20
|
+
import { SessionWriter } from '@deepwhale/core';
|
|
21
|
+
import { ChatMessage, LLMClient, type Usage } from '@deepwhale/llm';
|
|
22
|
+
import { type AgentCompactionConfig } from './agent/index.js';
|
|
23
|
+
import { type Provider } from './llm-factory.js';
|
|
24
|
+
import type { ToolPolicy } from './policy/types.js';
|
|
25
|
+
import type { SandboxRunner } from './sandbox/types.js';
|
|
26
|
+
export interface ReplOptions {
|
|
27
|
+
/** 注入 LLM 客户端(默认 createDefaultClient env 推断, Sprint 1b.5 Step 2 C3 拍板)。单测用。 */
|
|
28
|
+
client?: LLMClient;
|
|
29
|
+
/**
|
|
30
|
+
* Sprint 1c-revive-3-D-13 (2026-06-05): --yes 标志.
|
|
31
|
+
* yes=true bypass require_confirmation (write_file / edit_file / 危险 bash),
|
|
32
|
+
* 不 bypass deny. 拍板: REPL = 交互模式 (isInteractive=true), policy=staticToolPolicy.
|
|
33
|
+
*/
|
|
34
|
+
yes?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Sprint 1b.5 Step 2 (2.5 拍板, C3 拍板 2026-06-03): 显式 provider. 跟 env 推断冲突时优先.
|
|
37
|
+
* 跟 options.client 互斥 — 传 client 时 provider 忽略 (单测路径).
|
|
38
|
+
*/
|
|
39
|
+
provider?: Provider;
|
|
40
|
+
/** Sprint 1b.5 Step 2: 显式 model. 不传则用 provider 默认 (deepseek → deepseek-v4-flash, anthropic → claude-sonnet-4-5). */
|
|
41
|
+
model?: string;
|
|
42
|
+
/** 注入输入流(默认 stdin)。单测用。 */
|
|
43
|
+
input?: NodeJS.ReadableStream;
|
|
44
|
+
/** 注入输出流(默认 stdout)。单测用。 */
|
|
45
|
+
output?: NodeJS.WritableStream;
|
|
46
|
+
/** 注入错误流(默认 stderr)。单测用。 */
|
|
47
|
+
errorOutput?: NodeJS.WritableStream;
|
|
48
|
+
/** 注入退出函数(默认 process.exit)。单测用。 */
|
|
49
|
+
exit?: (code?: number) => never;
|
|
50
|
+
/**
|
|
51
|
+
* Session JSONL 路径。提供则启动时 load + 退出时 append + close。
|
|
52
|
+
* 不提供则不持久化(Sprint 0.3 行为)。
|
|
53
|
+
*/
|
|
54
|
+
sessionPath?: string;
|
|
55
|
+
/** 是否启用 tool loop(默认 true)。false = 退化为 Sprint 0.3 单轮 chat。 */
|
|
56
|
+
enableToolLoop?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Session compaction 集成 (Sprint 1c-revive-2-D-6, review P1 修复 2026-06-04).
|
|
59
|
+
*
|
|
60
|
+
* 传 = 走 runToolLoopWithCompaction, turn 入口测 token 触发则 compact + 写
|
|
61
|
+
* 'compaction' event 到 SessionWriter. 不传 = 走裸 runToolLoop (向后兼容,
|
|
62
|
+
* 现有 baseline 244 测试不变).
|
|
63
|
+
*
|
|
64
|
+
* 拍板: 提供 AgentCompactionConfig 即可, CompactionState 内部持有 (startRepl
|
|
65
|
+
* 闭包). writer 字段 REPL 自动注入 (跟 startRepl 内部 sessionPath writer
|
|
66
|
+
* 同 instance, 让 compaction 事件写到同一 JSONL).
|
|
67
|
+
*
|
|
68
|
+
* 拍板 contextWindow=0 = 关闭 (跟 core compact() 行为契约一致). 默认
|
|
69
|
+
* (不传此参数) = 不接 compaction.
|
|
70
|
+
*/
|
|
71
|
+
compactionConfig?: Omit<AgentCompactionConfig, 'writer' | 'state'> | null;
|
|
72
|
+
/**
|
|
73
|
+
* Sprint 1c-revive-2-D-11-4 (2026-06-04): verify 自定义 check.
|
|
74
|
+
* 不传 = 走 runVerify() 默认 4 步 (corepack pnpm build/lint/typecheck/test).
|
|
75
|
+
* 单测用: 传 4 个简单 pass check, 避免 30-60s 真跑 build.
|
|
76
|
+
*/
|
|
77
|
+
verifyChecks?: import('./verify/index.js').VerifyCheck[];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* 单轮 chat 工具函数:把 user 输入 → LLM chat → 输出 assistant 文本。
|
|
81
|
+
* 不修改 messages;不调工具;不持久化。
|
|
82
|
+
*
|
|
83
|
+
* Sprint 1a 保留作为低层 API。Sprint 1a 之后 REPL 入口推荐用 startRepl +
|
|
84
|
+
* enableToolLoop=true 走完整 agent loop。
|
|
85
|
+
*/
|
|
86
|
+
export declare function runOneTurn(client: LLMClient, line: string, messages: ChatMessage[], options?: {
|
|
87
|
+
signal?: AbortSignal;
|
|
88
|
+
}): Promise<{
|
|
89
|
+
kind: 'chat';
|
|
90
|
+
assistant: string;
|
|
91
|
+
} | {
|
|
92
|
+
kind: 'error';
|
|
93
|
+
error: string;
|
|
94
|
+
} | {
|
|
95
|
+
kind: 'empty';
|
|
96
|
+
}>;
|
|
97
|
+
/**
|
|
98
|
+
* 启动 REPL。返回 Promise,resolve 时为退出码。
|
|
99
|
+
*/
|
|
100
|
+
export declare function startRepl(options?: ReplOptions): Promise<number>;
|
|
101
|
+
/**
|
|
102
|
+
* 跑一轮 agent turn:append user → runToolLoop → 持久化 → 打印 final content。
|
|
103
|
+
*
|
|
104
|
+
* workingMessages 由 caller 持有(startRepl 闭包),turn 跑完后 caller 用新 messages 覆盖。
|
|
105
|
+
*
|
|
106
|
+
* Sprint 1a 修 P1:user 必须进 LLM。Sprint 1a 修 P2-A:流式不再重复打印 final content。
|
|
107
|
+
* Sprint 1c-revive-2-D-6 (review P1 修复, 2026-06-04): 可选 compactionConfig — 传
|
|
108
|
+
* 时调 runToolLoopWithCompaction (入口测 token, 触发则 compact + 写 event),
|
|
109
|
+
* 不传 = 走裸 runToolLoop (向后兼容, 单测 baseline 244 不变). summaryFn 内部
|
|
110
|
+
* 用 client + 固定 prompt 模板生成, 跟 test 1c-revive-2-D-5 cluster 拍板一致.
|
|
111
|
+
* 单测通过 export 暴露,直接注入 mock LLMClient + WritableStream 验证行为。
|
|
112
|
+
*/
|
|
113
|
+
export declare function runAgentTurn(client: LLMClient, userInput: string, workingMessages: ChatMessage[], writer: SessionWriter | null, out: NodeJS.WritableStream, err: NodeJS.WritableStream, signal: AbortSignal, compactionConfig?: AgentCompactionConfig | null, sandboxRunner?: SandboxRunner, yes?: boolean, policy?: ToolPolicy): Promise<void>;
|
|
114
|
+
/**
|
|
115
|
+
* Sprint 1b: 把 usage 翻译成人类可读的一行 status, 写到 stderr (不污染 stdout 流式输出)。
|
|
116
|
+
*
|
|
117
|
+
* 显示规则 (Hermes footer 教训应用 — 多字段同值时去冗余):
|
|
118
|
+
* - 满 usage (有 cached_tokens) → 完整 4 字段: cache: 90% | ¥0.05/turn | prompt 1.2k (1.1k cached)
|
|
119
|
+
* - 无 cached_tokens → 简化为: usage: 1.2k prompt / 200 completion
|
|
120
|
+
* (不打 cache% / cost, 避免没数据时显示 0% 误导)
|
|
121
|
+
* - 无 usage → 完全不打印 (LLM 没返 usage 时不污染 stderr)
|
|
122
|
+
*
|
|
123
|
+
* Sprint 1c 抽 pricing 到 config.toml, 此函数签名不变。
|
|
124
|
+
*/
|
|
125
|
+
export declare function formatUsageStatus(usage: Usage | undefined): string | null;
|
|
126
|
+
//# sourceMappingURL=repl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repl.d.ts","sourceRoot":"","sources":["../src/repl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,EAAiB,aAAa,EAAqB,MAAM,iBAAiB,CAAC;AAClF,OAAO,EAEL,WAAW,EAGX,SAAS,EAKT,KAAK,KAAK,EACX,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAQL,KAAK,qBAAqB,EAG3B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAuB,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAKtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIxD,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;;;OAIG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC;IACd;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,oHAAoH;IACpH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC/B,4BAA4B;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IACpC,mCAAmC;IACnC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,KAAK,CAAC;IAChC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,EAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC;IAC1E;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,mBAAmB,EAAE,WAAW,EAAE,CAAC;CAC1D;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,WAAW,EAAE,EACvB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAA;CAAO,GACrC,OAAO,CACR;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAC3F,CAcA;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4b1E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,WAAW,EAAE,EAC9B,MAAM,EAAE,aAAa,GAAG,IAAI,EAC5B,GAAG,EAAE,MAAM,CAAC,cAAc,EAC1B,GAAG,EAAE,MAAM,CAAC,cAAc,EAC1B,MAAM,EAAE,WAAW,EACnB,gBAAgB,GAAE,qBAAqB,GAAG,IAAW,EAGrD,aAAa,CAAC,EAAE,aAAa,EAE7B,GAAG,CAAC,EAAE,OAAO,EAGb,MAAM,CAAC,EAAE,UAAU,GAClB,OAAO,CAAC,IAAI,CAAC,CA+Gf;AAiBD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAqBzE"}
|