add-coder 0.3.31 → 0.3.32

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 (74) hide show
  1. package/package.json +1 -1
  2. package/templates/.add-coder-src-hash.json +73 -1
  3. package/templates/adapters/claude/hooks/doc-format-guard.mjs +850 -0
  4. package/templates/adapters/claude/hooks/notification.mjs +256 -0
  5. package/templates/adapters/claude/hooks/permission-denied.mjs +167 -0
  6. package/templates/adapters/claude/hooks/permission-gate.mjs +150 -0
  7. package/templates/adapters/claude/hooks/post-tool-failure.mjs +3 -0
  8. package/templates/adapters/claude/hooks/post-tool-use.mjs +413 -0
  9. package/templates/adapters/claude/hooks/pre-compact.mjs +226 -0
  10. package/templates/adapters/claude/hooks/pre-tool-use.mjs +914 -0
  11. package/templates/adapters/claude/hooks/prompt-submit.mjs +847 -0
  12. package/templates/adapters/claude/hooks/review-checklist.mjs +3 -0
  13. package/templates/adapters/claude/hooks/session-end.mjs +287 -0
  14. package/templates/adapters/claude/hooks/session-start.mjs +566 -0
  15. package/templates/adapters/claude/hooks/stop-check.mjs +505 -0
  16. package/templates/adapters/claude/hooks/stop-failure.mjs +222 -0
  17. package/templates/adapters/claude/hooks/subagent-guard.mjs +224 -0
  18. package/templates/adapters/claude/hooks/subagent-stop.mjs +277 -0
  19. package/templates/adapters/codex/hooks/doc-format-guard.mjs +849 -0
  20. package/templates/adapters/codex/hooks/notification.mjs +254 -0
  21. package/templates/adapters/codex/hooks/permission-gate.mjs +169 -0
  22. package/templates/adapters/codex/hooks/post-tool-failure.mjs +176 -0
  23. package/templates/adapters/codex/hooks/post-tool-use.mjs +575 -0
  24. package/templates/adapters/codex/hooks/pre-compact.mjs +328 -0
  25. package/templates/adapters/codex/hooks/pre-tool-use.mjs +963 -0
  26. package/templates/adapters/codex/hooks/prompt-submit.mjs +623 -0
  27. package/templates/adapters/codex/hooks/review-checklist.mjs +3 -0
  28. package/templates/adapters/codex/hooks/session-end.mjs +389 -0
  29. package/templates/adapters/codex/hooks/session-start.mjs +583 -0
  30. package/templates/adapters/codex/hooks/stop-check.mjs +539 -0
  31. package/templates/adapters/codex/hooks/subagent-guard.mjs +218 -0
  32. package/templates/adapters/codex/hooks/subagent-stop.mjs +381 -0
  33. package/templates/adapters/qoder/hooks/doc-format-guard.mjs +858 -0
  34. package/templates/adapters/qoder/hooks/notification.mjs +269 -0
  35. package/templates/adapters/qoder/hooks/permission-gate.mjs +284 -0
  36. package/templates/adapters/qoder/hooks/post-tool-failure.mjs +294 -0
  37. package/templates/adapters/qoder/hooks/post-tool-use.mjs +535 -0
  38. package/templates/adapters/qoder/hooks/pre-compact.mjs +234 -0
  39. package/templates/adapters/qoder/hooks/pre-tool-use.mjs +948 -0
  40. package/templates/adapters/qoder/hooks/prompt-submit.mjs +789 -0
  41. package/templates/adapters/qoder/hooks/review-checklist.mjs +409 -0
  42. package/templates/adapters/qoder/hooks/session-end.mjs +301 -0
  43. package/templates/adapters/qoder/hooks/session-start.mjs +619 -0
  44. package/templates/adapters/qoder/hooks/stop-check.mjs +567 -0
  45. package/templates/adapters/qoder/hooks/subagent-guard.mjs +219 -0
  46. package/templates/adapters/qoder/hooks/subagent-stop.mjs +298 -0
  47. package/templates/adapters/trae/hooks/doc-format-guard.mjs +849 -0
  48. package/templates/adapters/trae/hooks/notification.mjs +251 -0
  49. package/templates/adapters/trae/hooks/permission-gate.mjs +169 -0
  50. package/templates/adapters/trae/hooks/post-tool-failure.mjs +176 -0
  51. package/templates/adapters/trae/hooks/post-tool-use.mjs +415 -0
  52. package/templates/adapters/trae/hooks/pre-compact.mjs +224 -0
  53. package/templates/adapters/trae/hooks/pre-tool-use.mjs +873 -0
  54. package/templates/adapters/trae/hooks/prompt-submit.mjs +614 -0
  55. package/templates/adapters/trae/hooks/review-checklist.mjs +3 -0
  56. package/templates/adapters/trae/hooks/session-end.mjs +285 -0
  57. package/templates/adapters/trae/hooks/session-start.mjs +555 -0
  58. package/templates/adapters/trae/hooks/stop-check.mjs +502 -0
  59. package/templates/adapters/trae/hooks/subagent-guard.mjs +218 -0
  60. package/templates/adapters/trae/hooks/subagent-stop.mjs +274 -0
  61. package/templates/adapters/vscode/hooks/doc-format-guard.mjs +847 -0
  62. package/templates/adapters/vscode/hooks/notification.mjs +251 -0
  63. package/templates/adapters/vscode/hooks/permission-gate.mjs +169 -0
  64. package/templates/adapters/vscode/hooks/post-tool-failure.mjs +192 -0
  65. package/templates/adapters/vscode/hooks/post-tool-use.mjs +415 -0
  66. package/templates/adapters/vscode/hooks/pre-compact.mjs +224 -0
  67. package/templates/adapters/vscode/hooks/pre-tool-use.mjs +906 -0
  68. package/templates/adapters/vscode/hooks/prompt-submit.mjs +838 -0
  69. package/templates/adapters/vscode/hooks/review-checklist.mjs +3 -0
  70. package/templates/adapters/vscode/hooks/session-end.mjs +285 -0
  71. package/templates/adapters/vscode/hooks/session-start.mjs +560 -0
  72. package/templates/adapters/vscode/hooks/stop-check.mjs +502 -0
  73. package/templates/adapters/vscode/hooks/subagent-guard.mjs +218 -0
  74. package/templates/adapters/vscode/hooks/subagent-stop.mjs +274 -0
@@ -0,0 +1,294 @@
1
+ // templates/core/governance/common.ts
2
+ import { existsSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
3
+ import { basename, dirname, join } from "node:path";
4
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
5
+ import { createHash } from "node:crypto";
6
+
7
+ // templates/core/governance/rules.ts
8
+ var protocol = {
9
+ "exit_codes": {
10
+ "pass": 0,
11
+ "block": 2,
12
+ "note": "\u5192\u70DF\u6821\u9A8C: \u4EA7\u7269\u9000\u51FA\u7801 \u2208 {0,2}\uFF08\u5176\u4F59\u4E3A\u975E\u9884\u671F\uFF0C\u9700\u4FEE\u590D\uFF09"
13
+ },
14
+ "output": {
15
+ "stdout_json_only": true,
16
+ "stderr_human_text": true,
17
+ "field_separator": "::",
18
+ "magic_dir_resolution": "\u6CE8\u5165\u4F18\u5148 \u2192 \u7269\u7406\u4F4D\u7F6E\u63A8\u5BFC \u2192 failClosed\uFF08\u7981\u6B62\u731C\u6D4B adapter \u540D\uFF09"
19
+ },
20
+ "adapters": {
21
+ "claude": {
22
+ "stdout_form": "plain-text",
23
+ "project_dir_env": "CLAUDE_PROJECT_DIR",
24
+ "magic_dir": ".claude",
25
+ "handlerTypes": [
26
+ "command",
27
+ "mcp_tool"
28
+ ]
29
+ },
30
+ "qoder": {
31
+ "stdout_form": "json",
32
+ "project_dir_env": "QODER_PROJECT_DIR",
33
+ "magic_dir": ".qoder",
34
+ "handlerTypes": [
35
+ "command",
36
+ "http"
37
+ ]
38
+ },
39
+ "codex": {
40
+ "stdout_form": "systemMessage",
41
+ "project_dir_env": "git-toplevel",
42
+ "magic_dir": ".codex",
43
+ "handlerTypes": [
44
+ "command"
45
+ ]
46
+ },
47
+ "vscode": {
48
+ "stdout_form": "plain-text",
49
+ "project_dir_env": "PWD",
50
+ "magic_dir": ".vscode",
51
+ "handlerTypes": [
52
+ "command"
53
+ ]
54
+ },
55
+ "trae": {
56
+ "stdout_form": "plain-text",
57
+ "project_dir_env": "PWD",
58
+ "magic_dir": ".trae",
59
+ "handlerTypes": [
60
+ "command"
61
+ ]
62
+ }
63
+ },
64
+ "event_outputs": {
65
+ "qoder": {
66
+ "SessionStart": "additionalContext",
67
+ "UserPromptSubmit": "additionalContext",
68
+ "PreToolUse": "permissionDecision",
69
+ "Stop": "additionalContext",
70
+ "PostToolUse": "feedback",
71
+ "SubagentStart": "additionalContext",
72
+ "SubagentStop": "additionalContext",
73
+ "PostToolUseFailure": "text",
74
+ "PermissionRequest": "text",
75
+ "SessionEnd": "text",
76
+ "PreCompact": "text",
77
+ "Notification": "text"
78
+ },
79
+ "claude": {
80
+ "SessionStart": "additionalContext",
81
+ "UserPromptSubmit": "additionalContext",
82
+ "PreToolUse": "permissionDecision",
83
+ "Stop": "text",
84
+ "PostToolUse": "feedback",
85
+ "SubagentStart": "text",
86
+ "SubagentStop": "text",
87
+ "PostToolUseFailure": "text",
88
+ "PermissionRequest": "text",
89
+ "SessionEnd": "text",
90
+ "PreCompact": "text",
91
+ "Notification": "text"
92
+ },
93
+ "codex": {
94
+ "Stop": "systemMessage",
95
+ "PostToolUse": "text"
96
+ },
97
+ "vscode": {
98
+ "PostToolUse": "text"
99
+ },
100
+ "trae": {
101
+ "PostToolUse": "text"
102
+ }
103
+ },
104
+ "core": {
105
+ "stdout_form": "json",
106
+ "magic_dir": ".add",
107
+ "note": "core \u5165\u53E3\u534F\u8BAE = qoder \u540C\u6784\u53C2\u8003\u5B9E\u73B0\uFF1Badapter \u4EC5\u4FDD\u7559\u672C\u8868\u58F0\u660E\u7684\u79C1\u6709\u5DEE\u5F02"
108
+ },
109
+ "adapter_defaults": {
110
+ "magic_dir_fallback": ".qoder",
111
+ "probe_magic_dirs": [
112
+ ".claude",
113
+ ".qoder",
114
+ ".vscode",
115
+ ".add",
116
+ ".trae",
117
+ ".codex"
118
+ ]
119
+ }
120
+ };
121
+
122
+ // node_modules/.pnpm/find-up@8.0.0/node_modules/find-up/index.js
123
+ import path2 from "node:path";
124
+
125
+ // node_modules/.pnpm/locate-path@8.0.0/node_modules/locate-path/index.js
126
+ import process2 from "node:process";
127
+ import path from "node:path";
128
+ import fs, { promises as fsPromises } from "node:fs";
129
+ import { fileURLToPath } from "node:url";
130
+ var typeMappings = {
131
+ directory: "isDirectory",
132
+ file: "isFile"
133
+ };
134
+ function checkType(type) {
135
+ if (type === "both" || Object.hasOwn(typeMappings, type)) {
136
+ return;
137
+ }
138
+ throw new Error(`Invalid type specified: ${type}`);
139
+ }
140
+ var matchType = (type, stat) => type === "both" ? stat.isFile() || stat.isDirectory() : stat[typeMappings[type]]();
141
+ var toPath = (urlOrPath) => urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;
142
+ function locatePathSync(paths, {
143
+ cwd = process2.cwd(),
144
+ type = "file",
145
+ allowSymlinks = true
146
+ } = {}) {
147
+ checkType(type);
148
+ cwd = toPath(cwd);
149
+ const statFunction = allowSymlinks ? fs.statSync : fs.lstatSync;
150
+ for (const path_ of paths) {
151
+ try {
152
+ const stat = statFunction(path.resolve(cwd, path_), {
153
+ throwIfNoEntry: false
154
+ });
155
+ if (!stat) {
156
+ continue;
157
+ }
158
+ if (matchType(type, stat)) {
159
+ return path_;
160
+ }
161
+ } catch {
162
+ }
163
+ }
164
+ }
165
+
166
+ // node_modules/.pnpm/unicorn-magic@0.3.0/node_modules/unicorn-magic/node.js
167
+ import { promisify } from "node:util";
168
+ import { execFile as execFileCallback, execFileSync as execFileSyncOriginal } from "node:child_process";
169
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
170
+ var execFileOriginal = promisify(execFileCallback);
171
+ function toPath2(urlOrPath) {
172
+ return urlOrPath instanceof URL ? fileURLToPath2(urlOrPath) : urlOrPath;
173
+ }
174
+ var TEN_MEGABYTES_IN_BYTES = 10 * 1024 * 1024;
175
+
176
+ // node_modules/.pnpm/find-up@8.0.0/node_modules/find-up/index.js
177
+ var findUpStop = /* @__PURE__ */ Symbol("findUpStop");
178
+ function findUpMultipleSync(name, options = {}) {
179
+ let directory = path2.resolve(toPath2(options.cwd) ?? "");
180
+ const { root } = path2.parse(directory);
181
+ const stopAt = path2.resolve(directory, toPath2(options.stopAt) ?? root);
182
+ const limit = options.limit ?? Number.POSITIVE_INFINITY;
183
+ const paths = [name].flat();
184
+ const runMatcher = (locateOptions) => {
185
+ if (typeof name !== "function") {
186
+ return locatePathSync(paths, locateOptions);
187
+ }
188
+ const foundPath = name(locateOptions.cwd);
189
+ if (typeof foundPath === "string") {
190
+ return locatePathSync([foundPath], locateOptions);
191
+ }
192
+ return foundPath;
193
+ };
194
+ const matches = [];
195
+ while (true) {
196
+ const foundPath = runMatcher({ ...options, cwd: directory });
197
+ if (foundPath === findUpStop) {
198
+ break;
199
+ }
200
+ if (foundPath) {
201
+ matches.push(path2.resolve(directory, foundPath));
202
+ }
203
+ if (directory === stopAt || matches.length >= limit) {
204
+ break;
205
+ }
206
+ directory = path2.dirname(directory);
207
+ }
208
+ return matches;
209
+ }
210
+ function findUpSync(name, options = {}) {
211
+ const matches = findUpMultipleSync(name, { ...options, limit: 1 });
212
+ return matches[0];
213
+ }
214
+
215
+ // templates/core/governance/common.ts
216
+ var EXIT_PASS = protocol.exit_codes.pass;
217
+ var EXIT_BLOCK = protocol.exit_codes.block;
218
+ var STATE_SEP = protocol.output.field_separator;
219
+ function readHookInput() {
220
+ if (process.stdin.isTTY) return "{}";
221
+ return readFileSync(0, "utf-8");
222
+ }
223
+ function tryResolveMagicDir() {
224
+ const injected = process.env.MAGIC_DIR;
225
+ if (injected) return injected;
226
+ const startDir = dirname(fileURLToPath3(import.meta.url));
227
+ const hit = findUpSync((dir) => basename(dir).startsWith(".") ? dir : void 0, {
228
+ cwd: startDir,
229
+ type: "directory"
230
+ });
231
+ return hit ? basename(hit) : "";
232
+ }
233
+ function projectHash() {
234
+ try {
235
+ return createHash("md5").update(`${process.env.PROJECT_DIR || process.cwd()}
236
+ `).digest("hex").slice(0, 8);
237
+ } catch {
238
+ return "default";
239
+ }
240
+ }
241
+ var DEV_FLAG = `/tmp/add_dev_${projectHash()}`;
242
+
243
+ // templates/core/governance/post-tool-failure-router.ts
244
+ function fieldOr(json, field, fallback) {
245
+ const re = new RegExp(`"${field}"\\s*:\\s*"([^"]*)"`);
246
+ const m = re.exec(json);
247
+ return m ? m[1] : fallback;
248
+ }
249
+ var PostToolFailureRouter = class {
250
+ /** 主路由:返回 exit code(0) */
251
+ run(input2) {
252
+ const empty = input2.trim() === "";
253
+ const toolName = empty ? this.emptyUsesFallback() ? this.fallbackToolName() : "" : fieldOr(input2, "tool_name", this.fallbackToolName());
254
+ const error = empty ? this.emptyUsesFallback() ? this.fallbackError() : "" : fieldOr(input2, "error", this.fallbackError());
255
+ this.emit(toolName, error);
256
+ return 0;
257
+ }
258
+ /** 空输入是否走 fallback(core/qoder: false——空串;vscode 子类 override: true——bash grep || echo 语义) */
259
+ emptyUsesFallback() {
260
+ return false;
261
+ }
262
+ /** tool_name 缺失回退(core: "";qoder 子类 override: "unknown") */
263
+ fallbackToolName() {
264
+ return "";
265
+ }
266
+ /** error 缺失回退(core: "";qoder 子类 override: "unknown";vscode 子类 override: "未知错误") */
267
+ fallbackError() {
268
+ return "";
269
+ }
270
+ /** 输出(core 默认: stdout 固定文本——bash 原文逐字;adapter 子类 override 用 toolName/error) */
271
+ emit(_toolName, _error) {
272
+ process.stdout.write("[ADD PostToolFailure] \u5DE5\u5177\u8C03\u7528\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u9519\u8BEF\u4FE1\u606F\u5E76\u4FEE\u590D\u3002\n");
273
+ }
274
+ };
275
+
276
+ // templates/adapters/qoder/hooks/post-tool-failure.ts
277
+ var QoderPostToolFailureRouter = class extends PostToolFailureRouter {
278
+ /** ① tool_name/error 缺失回退 "unknown"(bash jq `// \"unknown\"` 语义) */
279
+ fallbackToolName() {
280
+ return "unknown";
281
+ }
282
+ fallbackError() {
283
+ return "unknown";
284
+ }
285
+ /** ② qoder 协议: stderr 回退建议(bash 原文逐字) */
286
+ emit(toolName, error) {
287
+ process.stderr.write(`[ADD PostToolUseFailure] \u5DE5\u5177 ${toolName} \u5931\u8D25: ${error}\u3002\u68C0\u67E5\u662F\u5426\u9700\u8981\u56DE\u9000\u5230\u4E0A\u4E00 ADD Step \u91CD\u65B0\u6267\u884C\u3002
288
+ `);
289
+ }
290
+ };
291
+ var inferred = tryResolveMagicDir();
292
+ if (inferred && !process.env.MAGIC_DIR) process.env.MAGIC_DIR = inferred;
293
+ var input = readHookInput();
294
+ process.exit(new QoderPostToolFailureRouter().run(input));