@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.
Files changed (138) hide show
  1. package/bin/deepwhale.js +299 -0
  2. package/dist/agent/agent-compaction.d.ts +74 -0
  3. package/dist/agent/agent-compaction.d.ts.map +1 -0
  4. package/dist/agent/agent-compaction.js +145 -0
  5. package/dist/agent/agent-compaction.js.map +1 -0
  6. package/dist/agent/index.d.ts +16 -0
  7. package/dist/agent/index.d.ts.map +1 -0
  8. package/dist/agent/index.js +17 -0
  9. package/dist/agent/index.js.map +1 -0
  10. package/dist/agent/session-adapter.d.ts +177 -0
  11. package/dist/agent/session-adapter.d.ts.map +1 -0
  12. package/dist/agent/session-adapter.js +340 -0
  13. package/dist/agent/session-adapter.js.map +1 -0
  14. package/dist/agent/tool-loop.d.ts +123 -0
  15. package/dist/agent/tool-loop.d.ts.map +1 -0
  16. package/dist/agent/tool-loop.js +425 -0
  17. package/dist/agent/tool-loop.js.map +1 -0
  18. package/dist/env/load-project-env.d.ts +40 -0
  19. package/dist/env/load-project-env.d.ts.map +1 -0
  20. package/dist/env/load-project-env.js +80 -0
  21. package/dist/env/load-project-env.js.map +1 -0
  22. package/dist/index.d.ts +25 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +24 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/llm-factory.d.ts +47 -0
  27. package/dist/llm-factory.d.ts.map +1 -0
  28. package/dist/llm-factory.js +88 -0
  29. package/dist/llm-factory.js.map +1 -0
  30. package/dist/modes/index.d.ts +14 -0
  31. package/dist/modes/index.d.ts.map +1 -0
  32. package/dist/modes/index.js +14 -0
  33. package/dist/modes/index.js.map +1 -0
  34. package/dist/modes/print.d.ts +50 -0
  35. package/dist/modes/print.d.ts.map +1 -0
  36. package/dist/modes/print.js +236 -0
  37. package/dist/modes/print.js.map +1 -0
  38. package/dist/modes/rpc.d.ts +52 -0
  39. package/dist/modes/rpc.d.ts.map +1 -0
  40. package/dist/modes/rpc.js +316 -0
  41. package/dist/modes/rpc.js.map +1 -0
  42. package/dist/modes/tui.d.ts +54 -0
  43. package/dist/modes/tui.d.ts.map +1 -0
  44. package/dist/modes/tui.js +361 -0
  45. package/dist/modes/tui.js.map +1 -0
  46. package/dist/policy/args-digest.d.ts +13 -0
  47. package/dist/policy/args-digest.d.ts.map +1 -0
  48. package/dist/policy/args-digest.js +29 -0
  49. package/dist/policy/args-digest.js.map +1 -0
  50. package/dist/policy/chain.d.ts +19 -0
  51. package/dist/policy/chain.d.ts.map +1 -0
  52. package/dist/policy/chain.js +24 -0
  53. package/dist/policy/chain.js.map +1 -0
  54. package/dist/policy/sanitize-reason.d.ts +11 -0
  55. package/dist/policy/sanitize-reason.d.ts.map +1 -0
  56. package/dist/policy/sanitize-reason.js +24 -0
  57. package/dist/policy/sanitize-reason.js.map +1 -0
  58. package/dist/policy/static-rules.d.ts +32 -0
  59. package/dist/policy/static-rules.d.ts.map +1 -0
  60. package/dist/policy/static-rules.js +106 -0
  61. package/dist/policy/static-rules.js.map +1 -0
  62. package/dist/policy/types.d.ts +56 -0
  63. package/dist/policy/types.d.ts.map +1 -0
  64. package/dist/policy/types.js +13 -0
  65. package/dist/policy/types.js.map +1 -0
  66. package/dist/repl/repl-confirm.d.ts +49 -0
  67. package/dist/repl/repl-confirm.d.ts.map +1 -0
  68. package/dist/repl/repl-confirm.js +88 -0
  69. package/dist/repl/repl-confirm.js.map +1 -0
  70. package/dist/repl.d.ts +126 -0
  71. package/dist/repl.d.ts.map +1 -0
  72. package/dist/repl.js +734 -0
  73. package/dist/repl.js.map +1 -0
  74. package/dist/sandbox/docker-runner.d.ts +147 -0
  75. package/dist/sandbox/docker-runner.d.ts.map +1 -0
  76. package/dist/sandbox/docker-runner.js +426 -0
  77. package/dist/sandbox/docker-runner.js.map +1 -0
  78. package/dist/sandbox/env-gate.d.ts +28 -0
  79. package/dist/sandbox/env-gate.d.ts.map +1 -0
  80. package/dist/sandbox/env-gate.js +65 -0
  81. package/dist/sandbox/env-gate.js.map +1 -0
  82. package/dist/sandbox/local-runner.d.ts +29 -0
  83. package/dist/sandbox/local-runner.d.ts.map +1 -0
  84. package/dist/sandbox/local-runner.js +79 -0
  85. package/dist/sandbox/local-runner.js.map +1 -0
  86. package/dist/sandbox/types.d.ts +80 -0
  87. package/dist/sandbox/types.d.ts.map +1 -0
  88. package/dist/sandbox/types.js +25 -0
  89. package/dist/sandbox/types.js.map +1 -0
  90. package/dist/tools/bash.d.ts +35 -0
  91. package/dist/tools/bash.d.ts.map +1 -0
  92. package/dist/tools/bash.js +233 -0
  93. package/dist/tools/bash.js.map +1 -0
  94. package/dist/tools/edit-file.d.ts +22 -0
  95. package/dist/tools/edit-file.d.ts.map +1 -0
  96. package/dist/tools/edit-file.js +79 -0
  97. package/dist/tools/edit-file.js.map +1 -0
  98. package/dist/tools/find.d.ts +21 -0
  99. package/dist/tools/find.d.ts.map +1 -0
  100. package/dist/tools/find.js +168 -0
  101. package/dist/tools/find.js.map +1 -0
  102. package/dist/tools/grep.d.ts +19 -0
  103. package/dist/tools/grep.d.ts.map +1 -0
  104. package/dist/tools/grep.js +170 -0
  105. package/dist/tools/grep.js.map +1 -0
  106. package/dist/tools/index.d.ts +10 -0
  107. package/dist/tools/index.d.ts.map +1 -0
  108. package/dist/tools/index.js +10 -0
  109. package/dist/tools/index.js.map +1 -0
  110. package/dist/tools/read-file.d.ts +18 -0
  111. package/dist/tools/read-file.d.ts.map +1 -0
  112. package/dist/tools/read-file.js +52 -0
  113. package/dist/tools/read-file.js.map +1 -0
  114. package/dist/tools/registry.d.ts +39 -0
  115. package/dist/tools/registry.d.ts.map +1 -0
  116. package/dist/tools/registry.js +67 -0
  117. package/dist/tools/registry.js.map +1 -0
  118. package/dist/tools/write-file.d.ts +18 -0
  119. package/dist/tools/write-file.d.ts.map +1 -0
  120. package/dist/tools/write-file.js +47 -0
  121. package/dist/tools/write-file.js.map +1 -0
  122. package/dist/types.d.ts +89 -0
  123. package/dist/types.d.ts.map +1 -0
  124. package/dist/types.js +5 -0
  125. package/dist/types.js.map +1 -0
  126. package/dist/verify/format-report.d.ts +57 -0
  127. package/dist/verify/format-report.d.ts.map +1 -0
  128. package/dist/verify/format-report.js +128 -0
  129. package/dist/verify/format-report.js.map +1 -0
  130. package/dist/verify/index.d.ts +8 -0
  131. package/dist/verify/index.d.ts.map +1 -0
  132. package/dist/verify/index.js +8 -0
  133. package/dist/verify/index.js.map +1 -0
  134. package/dist/verify/verify-runner.d.ts +125 -0
  135. package/dist/verify/verify-runner.d.ts.map +1 -0
  136. package/dist/verify/verify-runner.js +524 -0
  137. package/dist/verify/verify-runner.js.map +1 -0
  138. package/package.json +30 -0
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Tool Registry — 6 工具的注册中心
3
+ *
4
+ * Sprint 0.2 范围:
5
+ * - register / get / list 基础 API
6
+ * - 默认注册全部 6 工具
7
+ * - name 重名启动时检测(pi #5316 教训)
8
+ *
9
+ * Sprint 1+ 扩展:
10
+ * - MCP / Plugin / Skill 注册入口(v1.5/v2.0)
11
+ * - 风险评级聚合(StormBreaker 用)
12
+ */
13
+ import type { Tool, ToolName } from '../types.js';
14
+ import type { SandboxRunner } from '../sandbox/types.js';
15
+ export declare class ToolRegistry {
16
+ private tools;
17
+ /** 注册工具,重名抛错(pi #5316 教训) */
18
+ register(tool: Tool): void;
19
+ get(name: ToolName | string): Tool | undefined;
20
+ /** 严格获取 — 不存在抛错(v1.0 tool 路由用) */
21
+ require(name: ToolName | string): Tool;
22
+ list(): ReadonlyArray<Tool>;
23
+ size(): number;
24
+ }
25
+ /** Sprint 1c-revive-3-D-12 review P1 修复: 显式注入 sandboxRunner. */
26
+ export interface CreateDefaultRegistryOptions {
27
+ /** 注入 BashTool 的 SandboxRunner. 不传 = LocalSandboxRunner (v1.0 行为). */
28
+ readonly sandboxRunner?: SandboxRunner;
29
+ }
30
+ /**
31
+ * 默认 6 工具的 registry 工厂
32
+ *
33
+ * Sprint 1c-revive-3-D-12 review P1 修复 (2026-06-05): 加 `sandboxRunner` 显式参数.
34
+ * 之前 `new BashTool()` 走默认 LocalSandboxRunner, `DEEPWHALE_SANDBOX=docker` 解析
35
+ * 出的 DockerSandboxRunner 不会进 tool loop. 修法: mode 调用点从 env 解析 runner 后
36
+ * 显式传入, 工具注册表跟 env 状态对齐.
37
+ */
38
+ export declare function createDefaultRegistry(options?: CreateDefaultRegistryOptions): ToolRegistry;
39
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AASzD,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAA6B;IAE1C,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAU1B,GAAG,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS;IAI9C,kCAAkC;IAClC,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI;IAQtC,IAAI,IAAI,aAAa,CAAC,IAAI,CAAC;IAI3B,IAAI,IAAI,MAAM;CAGf;AAED,gEAAgE;AAChE,MAAM,WAAW,4BAA4B;IAC3C,sEAAsE;IACtE,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;CACxC;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,4BAAiC,GAAG,YAAY,CAU9F"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Tool Registry — 6 工具的注册中心
3
+ *
4
+ * Sprint 0.2 范围:
5
+ * - register / get / list 基础 API
6
+ * - 默认注册全部 6 工具
7
+ * - name 重名启动时检测(pi #5316 教训)
8
+ *
9
+ * Sprint 1+ 扩展:
10
+ * - MCP / Plugin / Skill 注册入口(v1.5/v2.0)
11
+ * - 风险评级聚合(StormBreaker 用)
12
+ */
13
+ import { ReadFileTool } from './read-file.js';
14
+ import { WriteFileTool } from './write-file.js';
15
+ import { EditFileTool } from './edit-file.js';
16
+ import { BashTool } from './bash.js';
17
+ import { FindTool } from './find.js';
18
+ import { GrepTool } from './grep.js';
19
+ import { LocalSandboxRunner } from '../sandbox/local-runner.js';
20
+ export class ToolRegistry {
21
+ tools = new Map();
22
+ /** 注册工具,重名抛错(pi #5316 教训) */
23
+ register(tool) {
24
+ if (this.tools.has(tool.name)) {
25
+ throw new Error(`Tool name collision: '${tool.name}' already registered. ` +
26
+ `Extension tool 重名启动时检测(pi #5316 教训)`);
27
+ }
28
+ this.tools.set(tool.name, tool);
29
+ }
30
+ get(name) {
31
+ return this.tools.get(name);
32
+ }
33
+ /** 严格获取 — 不存在抛错(v1.0 tool 路由用) */
34
+ require(name) {
35
+ const tool = this.get(name);
36
+ if (!tool) {
37
+ throw new Error(`Tool not found: '${name}'`);
38
+ }
39
+ return tool;
40
+ }
41
+ list() {
42
+ return Array.from(this.tools.values());
43
+ }
44
+ size() {
45
+ return this.tools.size;
46
+ }
47
+ }
48
+ /**
49
+ * 默认 6 工具的 registry 工厂
50
+ *
51
+ * Sprint 1c-revive-3-D-12 review P1 修复 (2026-06-05): 加 `sandboxRunner` 显式参数.
52
+ * 之前 `new BashTool()` 走默认 LocalSandboxRunner, `DEEPWHALE_SANDBOX=docker` 解析
53
+ * 出的 DockerSandboxRunner 不会进 tool loop. 修法: mode 调用点从 env 解析 runner 后
54
+ * 显式传入, 工具注册表跟 env 状态对齐.
55
+ */
56
+ export function createDefaultRegistry(options = {}) {
57
+ const reg = new ToolRegistry();
58
+ const runner = options.sandboxRunner ?? new LocalSandboxRunner();
59
+ reg.register(new ReadFileTool());
60
+ reg.register(new WriteFileTool());
61
+ reg.register(new EditFileTool());
62
+ reg.register(new BashTool(runner));
63
+ reg.register(new FindTool());
64
+ reg.register(new GrepTool());
65
+ return reg;
66
+ }
67
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,MAAM,OAAO,YAAY;IACf,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE1C,6BAA6B;IAC7B,QAAQ,CAAC,IAAU;QACjB,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CACb,yBAAyB,IAAI,CAAC,IAAI,wBAAwB;gBACxD,qCAAqC,CACxC,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,GAAG,CAAC,IAAuB;QACzB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAgB,CAAC,CAAC;IAC1C,CAAC;IAED,kCAAkC;IAClC,OAAO,CAAC,IAAuB;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,GAAG,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF;AAQD;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,UAAwC,EAAE;IAC9E,MAAM,GAAG,GAAG,IAAI,YAAY,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,IAAI,IAAI,kBAAkB,EAAE,CAAC;IACjE,GAAG,CAAC,QAAQ,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC;IACjC,GAAG,CAAC,QAAQ,CAAC,IAAI,aAAa,EAAE,CAAC,CAAC;IAClC,GAAG,CAAC,QAAQ,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC;IACjC,GAAG,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACnC,GAAG,CAAC,QAAQ,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC;IAC7B,GAAG,CAAC,QAAQ,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC;IAC7B,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * write_file 工具 — 写入本地文件
3
+ *
4
+ * Sprint 0.2 范围:直接覆盖(不追加)
5
+ * Sprint 1 扩展:append 模式 + 原子写(write to tmp + rename)
6
+ *
7
+ * 风险:medium(覆盖原文件不可恢复)— v1.0 必须经用户确认(arch §2.2 决策)
8
+ */
9
+ import type { ToolName } from '@deepwhale/core';
10
+ import type { Tool, ToolInputSchema, ToolResult } from '../types.js';
11
+ export declare class WriteFileTool implements Tool {
12
+ readonly name: ToolName;
13
+ readonly description = "Write content to a local file. Overwrites existing file. Requires user confirmation (medium risk).";
14
+ readonly risk: 'low' | 'medium' | 'high';
15
+ readonly schema: ToolInputSchema;
16
+ execute(input: Record<string, unknown>): Promise<ToolResult>;
17
+ }
18
+ //# sourceMappingURL=write-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-file.d.ts","sourceRoot":"","sources":["../../src/tools/write-file.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErE,qBAAa,aAAc,YAAW,IAAI;IACxC,QAAQ,CAAC,IAAI,EAAmB,QAAQ,CAAC;IACzC,QAAQ,CAAC,WAAW,wGACmF;IACvG,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAY;IAEpD,QAAQ,CAAC,MAAM,EAAE,eAAe,CAO9B;IAEI,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;CAuBnE"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * write_file 工具 — 写入本地文件
3
+ *
4
+ * Sprint 0.2 范围:直接覆盖(不追加)
5
+ * Sprint 1 扩展:append 模式 + 原子写(write to tmp + rename)
6
+ *
7
+ * 风险:medium(覆盖原文件不可恢复)— v1.0 必须经用户确认(arch §2.2 决策)
8
+ */
9
+ import { promises as fs } from 'node:fs';
10
+ import { dirname } from 'node:path';
11
+ export class WriteFileTool {
12
+ name = 'write_file';
13
+ description = 'Write content to a local file. Overwrites existing file. Requires user confirmation (medium risk).';
14
+ risk = 'medium';
15
+ schema = {
16
+ type: 'object',
17
+ properties: {
18
+ path: { type: 'string', description: 'Absolute path to the file' },
19
+ content: { type: 'string', description: 'Full file content to write' },
20
+ },
21
+ required: ['path', 'content'],
22
+ };
23
+ async execute(input) {
24
+ const path = input['path'];
25
+ const content = input['content'];
26
+ if (typeof path !== 'string' || path.length === 0) {
27
+ return { success: false, content: '', error: 'invalid-input: path is required' };
28
+ }
29
+ if (typeof content !== 'string') {
30
+ return { success: false, content: '', error: 'invalid-input: content must be string' };
31
+ }
32
+ try {
33
+ await fs.mkdir(dirname(path), { recursive: true });
34
+ await fs.writeFile(path, content, 'utf8');
35
+ return {
36
+ success: true,
37
+ content: `Written ${content.length} bytes to ${path}`,
38
+ meta: { path, bytes: content.length },
39
+ };
40
+ }
41
+ catch (err) {
42
+ const e = err;
43
+ return { success: false, content: '', error: `io-error: ${e.message}`, meta: { path } };
44
+ }
45
+ }
46
+ }
47
+ //# sourceMappingURL=write-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-file.js","sourceRoot":"","sources":["../../src/tools/write-file.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,MAAM,OAAO,aAAa;IACf,IAAI,GAAG,YAAwB,CAAC;IAChC,WAAW,GAClB,oGAAoG,CAAC;IAC9F,IAAI,GAA8B,QAAQ,CAAC;IAE3C,MAAM,GAAoB;QACjC,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,2BAA2B,EAAE;YAClE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,4BAA4B,EAAE;SACvE;QACD,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;KAC9B,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,KAA8B;QAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3B,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;QACjC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,iCAAiC,EAAE,CAAC;QACnF,CAAC;QACD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,uCAAuC,EAAE,CAAC;QACzF,CAAC;QAED,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACnD,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;YAC1C,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,WAAW,OAAO,CAAC,MAAM,aAAa,IAAI,EAAE;gBACrD,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE;aACtC,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,GAAkE,CAAC;YAC7E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC;QAC1F,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * 跨包共享的 tool 类型(被工具实现和 registry 共同使用)
3
+ */
4
+ import type { ToolName } from '@deepwhale/core';
5
+ export type { ToolName };
6
+ /**
7
+ * 工具输入 schema — 用 zod-like 的简化结构(避免 Sprint 0 拉 zod 依赖)
8
+ * Sprint 1 再决定是否引入 zod
9
+ */
10
+ export type ToolInputSchema = {
11
+ readonly type: 'object';
12
+ readonly properties: Record<string, ToolParamSchema>;
13
+ readonly required?: ReadonlyArray<string>;
14
+ };
15
+ export type ToolParamSchema = {
16
+ type: 'string';
17
+ description: string;
18
+ enum?: ReadonlyArray<string>;
19
+ } | {
20
+ type: 'number';
21
+ description: string;
22
+ minimum?: number;
23
+ maximum?: number;
24
+ } | {
25
+ type: 'boolean';
26
+ description: string;
27
+ } | {
28
+ type: 'array';
29
+ description: string;
30
+ items: ToolParamSchema;
31
+ };
32
+ /**
33
+ * 工具执行结果 — Observation 4 字段(arch §2.3 / ECC 借鉴)
34
+ * - content: 工具输出
35
+ * - success: 是否成功
36
+ * - error: 失败时的错误信息
37
+ * - meta: 性能/调试元数据
38
+ */
39
+ export type ToolResult = {
40
+ success: true;
41
+ content: string;
42
+ meta?: Record<string, unknown>;
43
+ } | {
44
+ success: false;
45
+ content: string;
46
+ error: string;
47
+ meta?: Record<string, unknown>;
48
+ };
49
+ /**
50
+ * 工具接口 — 所有 6 工具必须实现
51
+ *
52
+ * 设计原则:
53
+ * - name/risk/description 让 LLM 看到
54
+ * - schema 让 LLM 知道参数结构
55
+ * - execute() 是真实实现(同步或异步)
56
+ * - 沙箱在 Sprint 2 加(v1.0 = Docker only,v1.0 不强制沙箱)
57
+ */
58
+ export interface Tool {
59
+ readonly name: ToolName;
60
+ readonly description: string;
61
+ readonly risk: 'low' | 'medium' | 'high';
62
+ readonly schema: ToolInputSchema;
63
+ execute(input: Record<string, unknown>): Promise<ToolResult>;
64
+ }
65
+ /** Tool 错误码(arch §ApplyError 对应,扩展到所有 tool) */
66
+ export type ToolError = {
67
+ kind: 'invalid-input';
68
+ param: string;
69
+ reason: string;
70
+ } | {
71
+ kind: 'not-found';
72
+ path: string;
73
+ } | {
74
+ kind: 'permission-denied';
75
+ path: string;
76
+ reason: string;
77
+ } | {
78
+ kind: 'execution-failed';
79
+ command: string;
80
+ stderr: string;
81
+ } | {
82
+ kind: 'io-error';
83
+ path: string;
84
+ message: string;
85
+ } | {
86
+ kind: 'unsupported';
87
+ reason: string;
88
+ };
89
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,QAAQ,EAAE,CAAC;AAEzB;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,GACrE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3E;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,eAAe,CAAA;CAAE,CAAC;AAEnE;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAClE;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC;AAEvF;;;;;;;;GAQG;AACH,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC9D;AAED,+CAA+C;AAC/C,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 跨包共享的 tool 类型(被工具实现和 registry 共同使用)
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @deepwhale/coding-agent — Verify report formatter
3
+ *
4
+ * Sprint 1c-revive-2-D-11 (2026-06-04): 把 `VerificationReport` 渲染成人类可读文本.
5
+ * REPL `/verify` 跟 CLI `deepwhale --verify` 都用这个 formatter, 风格统一.
6
+ *
7
+ * 拍板 (D-11, 2026-06-04):
8
+ * - 简洁优先, 跟 REPL greeting / goodbye 风格一致
9
+ * - 每步 1 行 status, 失败时附带 tail
10
+ * - 不打印 key, 不打印 session 路径, 不打印 .env 路径
11
+ * - summary 跟 nextSuggestedAction 由 formatter 拍 (跟 D-11 拍板 "runner 纯函数,
12
+ * formatter 写自然语言" 一致)
13
+ *
14
+ * @module @deepwhale/coding-agent/format-report
15
+ */
16
+ import type { VerifyCheckResult, VerifyCheckStatus, VerificationReport } from './verify-runner.js';
17
+ /**
18
+ * 把 `VerificationReport` 渲染成多行文本.
19
+ *
20
+ * 风格:
21
+ * deepwhale verify — pass (1m 23s)
22
+ *
23
+ * ✓ build 12.3s
24
+ * ✓ lint 4.1s
25
+ * ✗ test 67.0s (exit 1)
26
+ * stderr tail:
27
+ * ...last 8 lines of stderr...
28
+ *
29
+ * Summary: 1/4 checks failed (test exit 1).
30
+ * Next: re-run after fixing failing test, or see /tmp/deepwhale-verify.log.
31
+ *
32
+ * @param report `runVerify()` 返回的报告
33
+ * @param options.verbose 默认 false. true 时**不**截断 stdout/stderr 印全 (单测 debug 用)
34
+ */
35
+ export interface FormatReportOptions {
36
+ verbose?: boolean;
37
+ /** stderrTail / stdoutTail 印几行. 默认 8. */
38
+ tailLines?: number;
39
+ /** 报告写入文件路径建议 (显示在 nextSuggestedAction 里). 不传不写. */
40
+ logFilePath?: string;
41
+ }
42
+ export declare function formatReport(report: VerificationReport, options?: FormatReportOptions): string;
43
+ /**
44
+ * 简化 summary 跟 nextSuggestedAction — 之前 runner 留空, formatter 拍.
45
+ * 拍板 (D-11, 2026-06-04): summary 给"X/Y pass", nextSuggestedAction 给 fix 提示.
46
+ */
47
+ export declare function buildSummaryAndNext(report: VerificationReport, options?: {
48
+ logFilePath?: string;
49
+ }): {
50
+ summary: string;
51
+ nextSuggestedAction: string;
52
+ };
53
+ /** @internal — 单步 status helper, 跟 status 字段对齐. 单测用. */
54
+ export declare function _checkStatusIcon(status: VerifyCheckStatus): string;
55
+ /** @internal — 单测用: 提取 check 简短描述. */
56
+ export declare function _describeCheck(c: VerifyCheckResult): string;
57
+ //# sourceMappingURL=format-report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-report.d.ts","sourceRoot":"","sources":["../../src/verify/format-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAY5B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,kBAAkB,EAC1B,OAAO,GAAE,mBAAwB,GAChC,MAAM,CAkDR;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,kBAAkB,EAC1B,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACrC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAA;CAAE,CAsBlD;AAmBD,wDAAwD;AACxD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAElE;AAED,sCAAsC;AACtC,wBAAgB,cAAc,CAAC,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAE3D"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * @deepwhale/coding-agent — Verify report formatter
3
+ *
4
+ * Sprint 1c-revive-2-D-11 (2026-06-04): 把 `VerificationReport` 渲染成人类可读文本.
5
+ * REPL `/verify` 跟 CLI `deepwhale --verify` 都用这个 formatter, 风格统一.
6
+ *
7
+ * 拍板 (D-11, 2026-06-04):
8
+ * - 简洁优先, 跟 REPL greeting / goodbye 风格一致
9
+ * - 每步 1 行 status, 失败时附带 tail
10
+ * - 不打印 key, 不打印 session 路径, 不打印 .env 路径
11
+ * - summary 跟 nextSuggestedAction 由 formatter 拍 (跟 D-11 拍板 "runner 纯函数,
12
+ * formatter 写自然语言" 一致)
13
+ *
14
+ * @module @deepwhale/coding-agent/format-report
15
+ */
16
+ const STATUS_ICON = {
17
+ passed: '✓',
18
+ failed: '✗',
19
+ 'timed-out': '⏱',
20
+ 'spawn-error': '⚠',
21
+ // Sprint 1c-revive-2-D-11-4 review P2 修复: 新增 'aborted' 状态. 跟 spawn-error
22
+ // 视觉区分 (⚠ vs ⛔) 让 reviewer 一眼看到"被外部 signal 干掉" vs "spawn 失败".
23
+ aborted: '⛔',
24
+ };
25
+ export function formatReport(report, options = {}) {
26
+ const verbose = options.verbose ?? false;
27
+ const tailLines = options.tailLines ?? 8;
28
+ const lines = [];
29
+ // Header
30
+ const duration = formatDuration(report.durationMs);
31
+ const headerStatus = report.overallStatus === 'passed' ? 'pass' : 'FAIL';
32
+ lines.push(`deepwhale verify — ${headerStatus} (${duration})`);
33
+ lines.push('');
34
+ // 每步
35
+ for (const check of report.checks) {
36
+ const icon = STATUS_ICON[check.status];
37
+ const dur = formatDuration(check.durationMs);
38
+ const statusText = check.status === 'passed' ? '' : ` (${check.status}`;
39
+ const exitPart = check.exitCode !== null ? ` exit ${check.exitCode}` : '';
40
+ const closeParen = check.status === 'passed' ? '' : exitPart + ')';
41
+ lines.push(` ${icon} ${check.name.padEnd(10)} ${dur}${statusText}${closeParen}`);
42
+ // 失败时附 tail
43
+ if (check.status !== 'passed') {
44
+ if (check.errorMessage) {
45
+ lines.push(` error: ${check.errorMessage}`);
46
+ }
47
+ const stderrTail = tailLinesOf(check.stderrTail, tailLines);
48
+ if (stderrTail) {
49
+ lines.push(` stderr tail:`);
50
+ for (const line of stderrTail.split('\n')) {
51
+ lines.push(` ${line}`);
52
+ }
53
+ }
54
+ if (verbose) {
55
+ const stdoutTail = tailLinesOf(check.stdoutTail, tailLines);
56
+ if (stdoutTail) {
57
+ lines.push(` stdout tail (verbose):`);
58
+ for (const line of stdoutTail.split('\n')) {
59
+ lines.push(` ${line}`);
60
+ }
61
+ }
62
+ }
63
+ }
64
+ }
65
+ lines.push('');
66
+ lines.push(`Summary: ${report.summary}`);
67
+ if (report.nextSuggestedAction) {
68
+ lines.push(`Next: ${report.nextSuggestedAction}`);
69
+ }
70
+ return lines.join('\n');
71
+ }
72
+ /**
73
+ * 简化 summary 跟 nextSuggestedAction — 之前 runner 留空, formatter 拍.
74
+ * 拍板 (D-11, 2026-06-04): summary 给"X/Y pass", nextSuggestedAction 给 fix 提示.
75
+ */
76
+ export function buildSummaryAndNext(report, options = {}) {
77
+ const total = report.checks.length;
78
+ const passed = report.checks.filter((c) => c.status === 'passed').length;
79
+ const summary = `${passed}/${total} checks ${report.overallStatus === 'passed' ? 'passed' : 'failed'}`;
80
+ let next;
81
+ if (report.overallStatus === 'passed') {
82
+ next = options.logFilePath
83
+ ? `all green; full log: ${options.logFilePath}`
84
+ : 'all green; ready to commit';
85
+ }
86
+ else {
87
+ const failed = report.checks.filter((c) => c.status !== 'passed');
88
+ const firstFailed = failed[0];
89
+ if (firstFailed?.status === 'timed-out') {
90
+ next = `investigate timeout in ${firstFailed.name} (${firstFailed.durationMs}ms)`;
91
+ }
92
+ else if (firstFailed?.status === 'spawn-error') {
93
+ next = `fix spawn error in ${firstFailed.name}: ${firstFailed.errorMessage ?? 'unknown'}`;
94
+ }
95
+ else {
96
+ next = `fix failing check: ${firstFailed?.name ?? '?'} (see stderr tail above)`;
97
+ }
98
+ }
99
+ return { summary, nextSuggestedAction: next };
100
+ }
101
+ function formatDuration(ms) {
102
+ if (ms < 1000)
103
+ return `${ms}ms`;
104
+ const s = ms / 1000;
105
+ if (s < 60)
106
+ return `${s.toFixed(1)}s`;
107
+ const m = Math.floor(s / 60);
108
+ const rem = Math.floor(s - m * 60);
109
+ return `${m}m ${rem}s`;
110
+ }
111
+ function tailLinesOf(s, n) {
112
+ if (s.length === 0)
113
+ return '';
114
+ const lines = s.split('\n');
115
+ if (lines.length <= n)
116
+ return s.trimEnd();
117
+ // 取最后 n 行, 然后 join 回 "\n" (不是 "," 也不是 "")
118
+ return lines.slice(-n).join('\n');
119
+ }
120
+ /** @internal — 单步 status helper, 跟 status 字段对齐. 单测用. */
121
+ export function _checkStatusIcon(status) {
122
+ return STATUS_ICON[status];
123
+ }
124
+ /** @internal — 单测用: 提取 check 简短描述. */
125
+ export function _describeCheck(c) {
126
+ return `${c.name} ${c.status} (${c.durationMs}ms, exit ${c.exitCode ?? 'null'})`;
127
+ }
128
+ //# sourceMappingURL=format-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-report.js","sourceRoot":"","sources":["../../src/verify/format-report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @deepwhale/coding-agent — verify module entry
3
+ *
4
+ * 公开 runVerify + formatReport + 类型, 供 REPL `/verify` 跟 CLI `deepwhale --verify` 用.
5
+ */
6
+ export { runVerify, type VerifyCheck, type VerifyCheckResult, type VerifyCheckStatus, type VerificationReport, type VerificationOverallStatus, type RunVerifyOptions, } from './verify-runner.js';
7
+ export { formatReport, buildSummaryAndNext, type FormatReportOptions, } from './format-report.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/verify/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,SAAS,EACT,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @deepwhale/coding-agent — verify module entry
3
+ *
4
+ * 公开 runVerify + formatReport + 类型, 供 REPL `/verify` 跟 CLI `deepwhale --verify` 用.
5
+ */
6
+ export { runVerify, } from './verify-runner.js';
7
+ export { formatReport, buildSummaryAndNext, } from './format-report.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/verify/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,SAAS,GAOV,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,YAAY,EACZ,mBAAmB,GAEpB,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * @deepwhale/coding-agent — Verify runner
3
+ *
4
+ * Sprint 1c-revive-2-D-11 (2026-06-04): `deepwhale --verify` 跟 REPL `/verify`
5
+ * 内部统一走 `runVerify()` — 跑 4 步真验证 (build / lint / typecheck / test),
6
+ * 不走 LLM, 不走 tool loop, 生成 `VerificationReport`.
7
+ *
8
+ * 设计拍板:
9
+ * - 4 步默认: corepack pnpm build / lint / typecheck / test
10
+ * - 用户可覆盖 checks (单测用) / cwd (单测 tmpdir) / signal (取消)
11
+ * - 每步 spawn child_process 同步等 exit, **不**用 stream (避免长 stdout 卡 session)
12
+ * - stdout/stderr 截断: 默认 4 KB 尾, 防止 session JSONL 撑爆
13
+ * - timeout 默认 5 min/步, 总 timeout 默认 30 min (build+lint+typecheck+test 全跑)
14
+ * - 任何一步 fail → 整体 fail, **不**继续后续步 (用户拍的 D-11 review: fail-fast
15
+ * 比继续跑节省时间, 而且后续步基于 build 产物, fail-fast 防止假绿)
16
+ * - 不读 .env, 不动 LLM, 不调 tool loop — 真·本地 CLI
17
+ *
18
+ * 不变量 (跟 D-10c 集成测语义 hotfix 一脉相承):
19
+ * - 不打印 / 不写 key 值
20
+ * - 不做 ASCII-only sanitize
21
+ * - 不读 .env 文件 (D-7 loadProjectEnv 是 caller 职责)
22
+ * - 不依赖 LLM client (跑 verify 不需要 key)
23
+ *
24
+ * @module @deepwhale/coding-agent/verify-runner
25
+ */
26
+ /** 单步验证配置. */
27
+ export interface VerifyCheck {
28
+ /** 人类可读步骤名 (报告里显示). */
29
+ name: string;
30
+ /** 完整命令 (报告里显示). 例: "corepack pnpm build". */
31
+ command: string;
32
+ /** 实际 spawn 的 argv (不含 corepack, corepack 处理自动). */
33
+ args: ReadonlyArray<string>;
34
+ /** spawn cwd. 不传走 options.cwd / process.cwd(). */
35
+ cwd?: string;
36
+ /** 该步 timeout (ms). 不传走 options.defaultTimeoutMs / 300_000. */
37
+ timeoutMs?: number;
38
+ }
39
+ /** 单步结果. */
40
+ export type VerifyCheckStatus = 'passed' | 'failed' | 'timed-out' | 'spawn-error' | 'aborted';
41
+ export interface VerifyCheckResult {
42
+ name: string;
43
+ command: string;
44
+ status: VerifyCheckStatus;
45
+ /** spawn 退出码. spawn 失败或 timeout 时为 null. */
46
+ exitCode: number | null;
47
+ /** 该步 startedAt (epoch ms). */
48
+ startedAt: number;
49
+ /** 该步 endedAt (epoch ms). */
50
+ endedAt: number;
51
+ /** 该步 durationMs. */
52
+ durationMs: number;
53
+ /** stdout 末尾截断 (默认 4 KB). 永远不写原始大文件. */
54
+ stdoutTail: string;
55
+ /** stderr 末尾截断 (默认 4 KB). */
56
+ stderrTail: string;
57
+ /** spawn / abort 错时的 error.message. 否则 undefined. */
58
+ errorMessage?: string;
59
+ }
60
+ /** 整体报告. */
61
+ export type VerificationOverallStatus = 'passed' | 'failed';
62
+ export interface VerificationReport {
63
+ startedAt: number;
64
+ endedAt: number;
65
+ durationMs: number;
66
+ overallStatus: VerificationOverallStatus;
67
+ checks: ReadonlyArray<VerifyCheckResult>;
68
+ /** 一句话人类可读总结. */
69
+ summary: string;
70
+ /** 建议下一步. */
71
+ nextSuggestedAction: string;
72
+ }
73
+ export interface RunVerifyOptions {
74
+ /** 自定义 checks. 不传走默认 4 步. */
75
+ checks?: ReadonlyArray<VerifyCheck>;
76
+ /** 工作目录. 不传走 process.cwd(). */
77
+ cwd?: string;
78
+ /** 外部 AbortSignal (单测 / REPL / CLI 取消). */
79
+ signal?: AbortSignal;
80
+ /** 默认每步 timeout (ms). 默认 300_000 (5 min). */
81
+ defaultTimeoutMs?: number;
82
+ /** stdout/stderr 截断字节数. 默认 4096. */
83
+ stdoutCapBytes?: number;
84
+ /** 失败时是否继续. 默认 false (fail-fast). 单测可改. */
85
+ continueOnError?: boolean;
86
+ }
87
+ /**
88
+ * Sprint 1c-revive-2-D-11-4 review P1 修复: Windows 上 `corepack` 在 PATH 解析不到
89
+ * (Node `spawn('corepack', ...)` 在 Win32 默认走 CreateProcessW, 不接 .cmd shim).
90
+ * 实际 `where corepack` 只返 `corepack.cmd`. 修复: Win32 上把 'corepack' → 'corepack.cmd'.
91
+ *
92
+ * 设计: 接受 platform 参数, 默认用 process.platform, 单测可注入 'win32' 验证.
93
+ * 仅在 args0 严格 === 'corepack' 时转换; 其它可执行 (node / bash / .exe) 透传,
94
+ * 跟单测里 mock 各种 runner 的行为兼容.
95
+ */
96
+ export declare function resolveRunner(args0: string, platform?: NodeJS.Platform): string;
97
+ /**
98
+ * 判定 child close 时的 stderr / stdout 是不是 "启错" 文本 (Win32 shell:true
99
+ * 路径下, "命令不存在" / "No such file" 走 cmd.exe exit 1, 不会 sync spawn
100
+ * 抛). 跨 Win32 shell 启错模式: cmd.exe "X is not recognized" + PowerShell
101
+ * "term not recognized" + POSIX shell 偶发 (e.g. via /bin/sh -c) "No such
102
+ * file". 命中返 true, caller 报 'spawn-error' 跟 POSIX 语义对齐.
103
+ *
104
+ * 设计: 故意**不**用 ENOENT (Node child 不暴露), 也不查 PATH. 简单字符串匹配
105
+ * 几个高置信度关键词, 误伤率低. 留 D-20.8 用 stderr 双检 + Node fs.access
106
+ * 再强化.
107
+ *
108
+ * 拍板 (D-20.7.7, 2026-06-06): 保守匹配, 不命中普通命令 exit 1 (e.g. 编译失败,
109
+ * 测试 fail) 误报.
110
+ */
111
+ export declare function looksLikeSpawnError(stdout: string, stderr: string, exitCode: number | null): boolean;
112
+ /**
113
+ * 跑 4 步验证 (默认), 返回 `VerificationReport`.
114
+ *
115
+ * 拍板 (D-11, 2026-06-04):
116
+ * - 任一 step 失败 → 整体 fail, **不**继续后续 step (fail-fast).
117
+ * 后续 step 基于 build 产物, 跑也是浪费; 而且 build fail 时 typecheck/test 必挂,
118
+ * 显式 fail-fast 比假绿更诚实.
119
+ * - 步骤间**不**共享 stdout/stderr buffer: 每步清零 Buffer 防止污染.
120
+ * - 返回的报告 `overallStatus` = 'failed' iff 任一 step status ∈ {failed, timed-out, spawn-error}.
121
+ * - summary / nextSuggestedAction 由调用方 (REPL/CLI/format-report) 写.
122
+ * runner 不写自然语言, 保持纯函数语义 (便于单测 / roundtrip).
123
+ */
124
+ export declare function runVerify(options?: RunVerifyOptions): Promise<VerificationReport>;
125
+ //# sourceMappingURL=verify-runner.d.ts.map