gencode-ai 0.1.1 → 0.1.2

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 (263) hide show
  1. package/.gencode/settings.local.json +7 -0
  2. package/README.md +11 -11
  3. package/dist/agent/agent.d.ts +42 -1
  4. package/dist/agent/agent.d.ts.map +1 -1
  5. package/dist/agent/agent.js +82 -15
  6. package/dist/agent/agent.js.map +1 -1
  7. package/dist/cli/components/App.d.ts +8 -1
  8. package/dist/cli/components/App.d.ts.map +1 -1
  9. package/dist/cli/components/App.js +231 -29
  10. package/dist/cli/components/App.js.map +1 -1
  11. package/dist/cli/components/CommandSuggestions.d.ts.map +1 -1
  12. package/dist/cli/components/CommandSuggestions.js +2 -0
  13. package/dist/cli/components/CommandSuggestions.js.map +1 -1
  14. package/dist/cli/components/Header.d.ts +1 -1
  15. package/dist/cli/components/Header.d.ts.map +1 -1
  16. package/dist/cli/components/Header.js +4 -6
  17. package/dist/cli/components/Header.js.map +1 -1
  18. package/dist/cli/components/Logo.d.ts +1 -0
  19. package/dist/cli/components/Logo.d.ts.map +1 -1
  20. package/dist/cli/components/Logo.js +16 -3
  21. package/dist/cli/components/Logo.js.map +1 -1
  22. package/dist/cli/components/Messages.d.ts +4 -4
  23. package/dist/cli/components/Messages.d.ts.map +1 -1
  24. package/dist/cli/components/Messages.js +51 -25
  25. package/dist/cli/components/Messages.js.map +1 -1
  26. package/dist/cli/components/PermissionPrompt.d.ts +60 -0
  27. package/dist/cli/components/PermissionPrompt.d.ts.map +1 -0
  28. package/dist/cli/components/PermissionPrompt.js +192 -0
  29. package/dist/cli/components/PermissionPrompt.js.map +1 -0
  30. package/dist/cli/components/ProviderManager.js +3 -3
  31. package/dist/cli/components/ProviderManager.js.map +1 -1
  32. package/dist/cli/components/Spinner.d.ts +7 -2
  33. package/dist/cli/components/Spinner.d.ts.map +1 -1
  34. package/dist/cli/components/Spinner.js +116 -25
  35. package/dist/cli/components/Spinner.js.map +1 -1
  36. package/dist/cli/components/TodoList.d.ts +7 -0
  37. package/dist/cli/components/TodoList.d.ts.map +1 -0
  38. package/dist/cli/components/TodoList.js +34 -0
  39. package/dist/cli/components/TodoList.js.map +1 -0
  40. package/dist/cli/components/index.d.ts +1 -0
  41. package/dist/cli/components/index.d.ts.map +1 -1
  42. package/dist/cli/components/index.js +1 -0
  43. package/dist/cli/components/index.js.map +1 -1
  44. package/dist/cli/index.js +47 -7
  45. package/dist/cli/index.js.map +1 -1
  46. package/dist/config/index.d.ts +13 -4
  47. package/dist/config/index.d.ts.map +1 -1
  48. package/dist/config/index.js +18 -3
  49. package/dist/config/index.js.map +1 -1
  50. package/dist/config/levels.d.ts +49 -0
  51. package/dist/config/levels.d.ts.map +1 -0
  52. package/dist/config/levels.js +222 -0
  53. package/dist/config/levels.js.map +1 -0
  54. package/dist/config/loader.d.ts +46 -0
  55. package/dist/config/loader.d.ts.map +1 -0
  56. package/dist/config/loader.js +153 -0
  57. package/dist/config/loader.js.map +1 -0
  58. package/dist/config/manager.d.ts +115 -15
  59. package/dist/config/manager.d.ts.map +1 -1
  60. package/dist/config/manager.js +260 -34
  61. package/dist/config/manager.js.map +1 -1
  62. package/dist/config/manager.test.d.ts +5 -0
  63. package/dist/config/manager.test.d.ts.map +1 -0
  64. package/dist/config/manager.test.js +192 -0
  65. package/dist/config/manager.test.js.map +1 -0
  66. package/dist/config/merger.d.ts +56 -0
  67. package/dist/config/merger.d.ts.map +1 -0
  68. package/dist/config/merger.js +177 -0
  69. package/dist/config/merger.js.map +1 -0
  70. package/dist/config/test-utils.d.ts +24 -0
  71. package/dist/config/test-utils.d.ts.map +1 -0
  72. package/dist/config/test-utils.js +55 -0
  73. package/dist/config/test-utils.js.map +1 -0
  74. package/dist/config/types.d.ts +78 -9
  75. package/dist/config/types.d.ts.map +1 -1
  76. package/dist/config/types.js +52 -2
  77. package/dist/config/types.js.map +1 -1
  78. package/dist/memory/import-resolver.d.ts +46 -0
  79. package/dist/memory/import-resolver.d.ts.map +1 -0
  80. package/dist/memory/import-resolver.js +117 -0
  81. package/dist/memory/import-resolver.js.map +1 -0
  82. package/dist/memory/index.d.ts +7 -6
  83. package/dist/memory/index.d.ts.map +1 -1
  84. package/dist/memory/index.js +7 -5
  85. package/dist/memory/index.js.map +1 -1
  86. package/dist/memory/init-prompt.d.ts +22 -0
  87. package/dist/memory/init-prompt.d.ts.map +1 -0
  88. package/dist/memory/init-prompt.js +103 -0
  89. package/dist/memory/init-prompt.js.map +1 -0
  90. package/dist/memory/memory-manager.d.ts +119 -0
  91. package/dist/memory/memory-manager.d.ts.map +1 -0
  92. package/dist/memory/memory-manager.js +587 -0
  93. package/dist/memory/memory-manager.js.map +1 -0
  94. package/dist/memory/rules-parser.d.ts +38 -0
  95. package/dist/memory/rules-parser.d.ts.map +1 -0
  96. package/dist/memory/rules-parser.js +69 -0
  97. package/dist/memory/rules-parser.js.map +1 -0
  98. package/dist/memory/test-utils.d.ts +20 -0
  99. package/dist/memory/test-utils.d.ts.map +1 -0
  100. package/dist/memory/test-utils.js +44 -0
  101. package/dist/memory/test-utils.js.map +1 -0
  102. package/dist/memory/types.d.ts +70 -63
  103. package/dist/memory/types.d.ts.map +1 -1
  104. package/dist/memory/types.js +42 -2
  105. package/dist/memory/types.js.map +1 -1
  106. package/dist/permissions/audit.d.ts +82 -0
  107. package/dist/permissions/audit.d.ts.map +1 -0
  108. package/dist/permissions/audit.js +229 -0
  109. package/dist/permissions/audit.js.map +1 -0
  110. package/dist/permissions/index.d.ts +11 -1
  111. package/dist/permissions/index.d.ts.map +1 -1
  112. package/dist/permissions/index.js +15 -0
  113. package/dist/permissions/index.js.map +1 -1
  114. package/dist/permissions/manager.d.ts +149 -13
  115. package/dist/permissions/manager.d.ts.map +1 -1
  116. package/dist/permissions/manager.js +480 -35
  117. package/dist/permissions/manager.js.map +1 -1
  118. package/dist/permissions/manager.test.d.ts +5 -0
  119. package/dist/permissions/manager.test.d.ts.map +1 -0
  120. package/dist/permissions/manager.test.js +213 -0
  121. package/dist/permissions/manager.test.js.map +1 -0
  122. package/dist/permissions/persistence.d.ts +74 -0
  123. package/dist/permissions/persistence.d.ts.map +1 -0
  124. package/dist/permissions/persistence.js +248 -0
  125. package/dist/permissions/persistence.js.map +1 -0
  126. package/dist/permissions/persistence.test.d.ts +5 -0
  127. package/dist/permissions/persistence.test.d.ts.map +1 -0
  128. package/dist/permissions/persistence.test.js +171 -0
  129. package/dist/permissions/persistence.test.js.map +1 -0
  130. package/dist/permissions/prompt-matcher.d.ts +64 -0
  131. package/dist/permissions/prompt-matcher.d.ts.map +1 -0
  132. package/dist/permissions/prompt-matcher.js +415 -0
  133. package/dist/permissions/prompt-matcher.js.map +1 -0
  134. package/dist/permissions/prompt-matcher.test.d.ts +5 -0
  135. package/dist/permissions/prompt-matcher.test.d.ts.map +1 -0
  136. package/dist/permissions/prompt-matcher.test.js +107 -0
  137. package/dist/permissions/prompt-matcher.test.js.map +1 -0
  138. package/dist/permissions/types.d.ts +157 -0
  139. package/dist/permissions/types.d.ts.map +1 -1
  140. package/dist/permissions/types.js +43 -8
  141. package/dist/permissions/types.js.map +1 -1
  142. package/dist/prompts/index.d.ts +92 -0
  143. package/dist/prompts/index.d.ts.map +1 -0
  144. package/dist/prompts/index.js +241 -0
  145. package/dist/prompts/index.js.map +1 -0
  146. package/dist/tools/builtin/bash.d.ts.map +1 -1
  147. package/dist/tools/builtin/bash.js +2 -1
  148. package/dist/tools/builtin/bash.js.map +1 -1
  149. package/dist/tools/builtin/edit.d.ts.map +1 -1
  150. package/dist/tools/builtin/edit.js +2 -1
  151. package/dist/tools/builtin/edit.js.map +1 -1
  152. package/dist/tools/builtin/glob.d.ts.map +1 -1
  153. package/dist/tools/builtin/glob.js +2 -1
  154. package/dist/tools/builtin/glob.js.map +1 -1
  155. package/dist/tools/builtin/grep.d.ts.map +1 -1
  156. package/dist/tools/builtin/grep.js +2 -1
  157. package/dist/tools/builtin/grep.js.map +1 -1
  158. package/dist/tools/builtin/read.d.ts.map +1 -1
  159. package/dist/tools/builtin/read.js +2 -1
  160. package/dist/tools/builtin/read.js.map +1 -1
  161. package/dist/tools/builtin/todowrite.d.ts +15 -0
  162. package/dist/tools/builtin/todowrite.d.ts.map +1 -0
  163. package/dist/tools/builtin/todowrite.js +88 -0
  164. package/dist/tools/builtin/todowrite.js.map +1 -0
  165. package/dist/tools/builtin/webfetch.d.ts.map +1 -1
  166. package/dist/tools/builtin/webfetch.js +2 -5
  167. package/dist/tools/builtin/webfetch.js.map +1 -1
  168. package/dist/tools/builtin/websearch.d.ts.map +1 -1
  169. package/dist/tools/builtin/websearch.js +2 -16
  170. package/dist/tools/builtin/websearch.js.map +1 -1
  171. package/dist/tools/builtin/write.d.ts.map +1 -1
  172. package/dist/tools/builtin/write.js +2 -1
  173. package/dist/tools/builtin/write.js.map +1 -1
  174. package/dist/tools/index.d.ts +7 -0
  175. package/dist/tools/index.d.ts.map +1 -1
  176. package/dist/tools/index.js +4 -0
  177. package/dist/tools/index.js.map +1 -1
  178. package/dist/tools/types.d.ts +22 -0
  179. package/dist/tools/types.d.ts.map +1 -1
  180. package/dist/tools/types.js +8 -0
  181. package/dist/tools/types.js.map +1 -1
  182. package/docs/config-system-comparison.md +707 -0
  183. package/docs/memory-system.md +238 -0
  184. package/docs/permissions.md +368 -0
  185. package/docs/proposals/0005-todo-system.md +350 -85
  186. package/docs/proposals/0006-memory-system.md +11 -10
  187. package/docs/proposals/0012-ask-user-question.md +941 -206
  188. package/docs/proposals/0023-permission-enhancements.md +61 -2
  189. package/docs/proposals/0041-configuration-system.md +33 -2
  190. package/docs/proposals/0042-prompt-optimization.md +866 -0
  191. package/docs/proposals/README.md +6 -5
  192. package/jest.config.js +26 -0
  193. package/package.json +8 -2
  194. package/src/agent/agent.ts +111 -16
  195. package/src/cli/components/App.tsx +309 -36
  196. package/src/cli/components/CommandSuggestions.tsx +2 -0
  197. package/src/cli/components/Header.tsx +11 -17
  198. package/src/cli/components/Logo.tsx +76 -9
  199. package/src/cli/components/Messages.tsx +73 -53
  200. package/src/cli/components/PermissionPrompt.tsx +388 -0
  201. package/src/cli/components/ProviderManager.tsx +5 -5
  202. package/src/cli/components/Spinner.tsx +138 -25
  203. package/src/cli/components/TodoList.tsx +54 -0
  204. package/src/cli/components/index.ts +6 -0
  205. package/src/cli/index.tsx +54 -6
  206. package/src/config/index.ts +78 -4
  207. package/src/config/levels.test.ts +163 -0
  208. package/src/config/levels.ts +285 -0
  209. package/src/config/loader.test.ts +120 -0
  210. package/src/config/loader.ts +178 -0
  211. package/src/config/manager.test.ts +215 -0
  212. package/src/config/manager.ts +328 -40
  213. package/src/config/merger.test.ts +360 -0
  214. package/src/config/merger.ts +221 -0
  215. package/src/config/test-utils.ts +79 -0
  216. package/src/config/types.ts +152 -9
  217. package/src/memory/import-resolver.test.ts +117 -0
  218. package/src/memory/import-resolver.ts +149 -0
  219. package/src/memory/index.ts +11 -0
  220. package/src/memory/init-prompt.ts +113 -0
  221. package/src/memory/memory-manager.test.ts +198 -0
  222. package/src/memory/memory-manager.ts +716 -0
  223. package/src/memory/rules-parser.test.ts +182 -0
  224. package/src/memory/rules-parser.ts +82 -0
  225. package/src/memory/test-utils.ts +60 -0
  226. package/src/memory/types.ts +119 -0
  227. package/src/permissions/audit.ts +284 -0
  228. package/src/permissions/index.ts +20 -1
  229. package/src/permissions/manager.test.ts +260 -0
  230. package/src/permissions/manager.ts +592 -40
  231. package/src/permissions/persistence.test.ts +220 -0
  232. package/src/permissions/persistence.ts +301 -0
  233. package/src/permissions/prompt-matcher.test.ts +213 -0
  234. package/src/permissions/prompt-matcher.ts +472 -0
  235. package/src/permissions/types.ts +236 -8
  236. package/src/prompts/index.test.ts +279 -0
  237. package/src/prompts/index.ts +306 -0
  238. package/src/prompts/system/anthropic.txt +29 -0
  239. package/src/prompts/system/base.txt +124 -0
  240. package/src/prompts/system/gemini.txt +35 -0
  241. package/src/prompts/system/generic.txt +128 -0
  242. package/src/prompts/system/openai.txt +29 -0
  243. package/src/prompts/tools/bash.txt +60 -0
  244. package/src/prompts/tools/edit.txt +29 -0
  245. package/src/prompts/tools/glob.txt +35 -0
  246. package/src/prompts/tools/grep.txt +43 -0
  247. package/src/prompts/tools/read.txt +22 -0
  248. package/src/prompts/tools/todowrite.txt +71 -0
  249. package/src/prompts/tools/webfetch.txt +34 -0
  250. package/src/prompts/tools/websearch.txt +41 -0
  251. package/src/prompts/tools/write.txt +23 -0
  252. package/src/tools/builtin/bash.ts +2 -1
  253. package/src/tools/builtin/edit.ts +2 -1
  254. package/src/tools/builtin/glob.ts +2 -1
  255. package/src/tools/builtin/grep.ts +2 -1
  256. package/src/tools/builtin/read.ts +2 -1
  257. package/src/tools/builtin/todowrite.ts +102 -0
  258. package/src/tools/builtin/webfetch.ts +2 -5
  259. package/src/tools/builtin/websearch.ts +2 -16
  260. package/src/tools/builtin/write.ts +2 -1
  261. package/src/tools/index.ts +4 -0
  262. package/src/tools/types.ts +12 -0
  263. package/tsconfig.json +1 -1
@@ -0,0 +1,171 @@
1
+ /**
2
+ * PermissionPersistence Tests
3
+ */
4
+ import * as fs from 'fs/promises';
5
+ import * as path from 'path';
6
+ import * as os from 'os';
7
+ import { PermissionPersistence } from './persistence.js';
8
+ describe('PermissionPersistence', () => {
9
+ let tempDir;
10
+ let projectDir;
11
+ beforeEach(async () => {
12
+ // Create temp directories for testing
13
+ tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'gencode-perm-test-'));
14
+ projectDir = path.join(tempDir, 'project');
15
+ await fs.mkdir(projectDir, { recursive: true });
16
+ });
17
+ afterEach(async () => {
18
+ // Cleanup temp directories
19
+ await fs.rm(tempDir, { recursive: true, force: true });
20
+ });
21
+ describe('addRule', () => {
22
+ it('should add a rule to project scope', async () => {
23
+ const projectPermDir = path.join(projectDir, '.claude');
24
+ await fs.mkdir(projectPermDir, { recursive: true });
25
+ const persistence = new PermissionPersistence(projectDir);
26
+ const rule = await persistence.addRule('WebSearch', 'auto', {
27
+ scope: 'project',
28
+ });
29
+ expect(rule.id).toBeDefined();
30
+ expect(rule.tool).toBe('WebSearch');
31
+ expect(rule.mode).toBe('auto');
32
+ expect(rule.scope).toBe('project');
33
+ });
34
+ it('should add a rule with pattern', async () => {
35
+ const projectPermDir = path.join(projectDir, '.claude');
36
+ await fs.mkdir(projectPermDir, { recursive: true });
37
+ const persistence = new PermissionPersistence(projectDir);
38
+ const rule = await persistence.addRule('Bash', 'auto', {
39
+ pattern: 'git add:*',
40
+ scope: 'project',
41
+ description: 'Test rule',
42
+ });
43
+ expect(rule.pattern).toBe('git add:*');
44
+ expect(rule.description).toBe('Test rule');
45
+ });
46
+ });
47
+ describe('getRules', () => {
48
+ it('should return empty array for non-existent project file', async () => {
49
+ const projectPermDir = path.join(projectDir, '.claude');
50
+ await fs.mkdir(projectPermDir, { recursive: true });
51
+ const persistence = new PermissionPersistence(projectDir);
52
+ const rules = await persistence.getRules('project');
53
+ expect(rules).toEqual([]);
54
+ });
55
+ it('should return saved project rules', async () => {
56
+ const projectPermDir = path.join(projectDir, '.claude');
57
+ await fs.mkdir(projectPermDir, { recursive: true });
58
+ const persistence = new PermissionPersistence(projectDir);
59
+ await persistence.addRule('Bash', 'auto', {
60
+ pattern: 'npm test:*',
61
+ scope: 'project',
62
+ });
63
+ const rules = await persistence.getRules('project');
64
+ expect(rules.length).toBe(1);
65
+ expect(rules[0].tool).toBe('Bash');
66
+ });
67
+ });
68
+ describe('removeRule', () => {
69
+ it('should remove a rule by ID', async () => {
70
+ const projectPermDir = path.join(projectDir, '.claude');
71
+ await fs.mkdir(projectPermDir, { recursive: true });
72
+ const persistence = new PermissionPersistence(projectDir);
73
+ const rule = await persistence.addRule('Bash', 'auto', {
74
+ pattern: 'npm:*',
75
+ scope: 'project',
76
+ });
77
+ const removed = await persistence.removeRule(rule.id, 'project');
78
+ expect(removed).toBe(true);
79
+ const rules = await persistence.getRules('project');
80
+ expect(rules.length).toBe(0);
81
+ });
82
+ it('should return false for non-existent rule', async () => {
83
+ const projectPermDir = path.join(projectDir, '.claude');
84
+ await fs.mkdir(projectPermDir, { recursive: true });
85
+ const persistence = new PermissionPersistence(projectDir);
86
+ const removed = await persistence.removeRule('non-existent-id', 'project');
87
+ expect(removed).toBe(false);
88
+ });
89
+ });
90
+ describe('parseSettingsPermissions', () => {
91
+ it('should parse allow rules', () => {
92
+ const persistence = new PermissionPersistence(projectDir);
93
+ const rules = persistence.parseSettingsPermissions({
94
+ allow: ['Bash(git add:*)', 'WebSearch'],
95
+ });
96
+ expect(rules.length).toBe(2);
97
+ expect(rules[0].tool).toBe('Bash');
98
+ expect(rules[0].mode).toBe('auto');
99
+ expect(rules[0].pattern).toBe('git add:*');
100
+ expect(rules[1].tool).toBe('WebSearch');
101
+ expect(rules[1].mode).toBe('auto');
102
+ });
103
+ it('should parse ask rules', () => {
104
+ const persistence = new PermissionPersistence(projectDir);
105
+ const rules = persistence.parseSettingsPermissions({
106
+ ask: ['Bash(npm run:*)'],
107
+ });
108
+ expect(rules.length).toBe(1);
109
+ expect(rules[0].tool).toBe('Bash');
110
+ expect(rules[0].mode).toBe('confirm');
111
+ expect(rules[0].pattern).toBe('npm run:*');
112
+ });
113
+ it('should parse deny rules', () => {
114
+ const persistence = new PermissionPersistence(projectDir);
115
+ const rules = persistence.parseSettingsPermissions({
116
+ deny: ['Bash(rm -rf:*)'],
117
+ });
118
+ expect(rules.length).toBe(1);
119
+ expect(rules[0].tool).toBe('Bash');
120
+ expect(rules[0].mode).toBe('deny');
121
+ expect(rules[0].pattern).toBe('rm -rf:*');
122
+ });
123
+ it('should parse mixed rules', () => {
124
+ const persistence = new PermissionPersistence(projectDir);
125
+ const rules = persistence.parseSettingsPermissions({
126
+ allow: ['Bash(git:*)'],
127
+ ask: ['Bash(npm run:*)'],
128
+ deny: ['Bash(rm -rf:*)'],
129
+ });
130
+ expect(rules.length).toBe(3);
131
+ const allowRule = rules.find(r => r.pattern === 'git:*');
132
+ const askRule = rules.find(r => r.pattern === 'npm run:*');
133
+ const denyRule = rules.find(r => r.pattern === 'rm -rf:*');
134
+ expect(allowRule?.mode).toBe('auto');
135
+ expect(askRule?.mode).toBe('confirm');
136
+ expect(denyRule?.mode).toBe('deny');
137
+ });
138
+ });
139
+ describe('persistedToRuntime', () => {
140
+ it('should convert persisted rules to runtime format', () => {
141
+ const persistence = new PermissionPersistence(projectDir);
142
+ const persisted = [
143
+ {
144
+ id: 'test-id',
145
+ tool: 'Bash',
146
+ pattern: 'git:*',
147
+ mode: 'auto',
148
+ scope: 'global',
149
+ createdAt: new Date().toISOString(),
150
+ description: 'Test',
151
+ },
152
+ ];
153
+ const runtime = persistence.persistedToRuntime(persisted);
154
+ expect(runtime.length).toBe(1);
155
+ expect(runtime[0].tool).toBe('Bash');
156
+ expect(runtime[0].mode).toBe('auto');
157
+ expect(runtime[0].pattern).toBe('git:*');
158
+ });
159
+ });
160
+ describe('clearRules', () => {
161
+ it('should clear all rules for a scope', async () => {
162
+ const persistence = new PermissionPersistence(projectDir);
163
+ await persistence.addRule('Bash', 'auto', { scope: 'global' });
164
+ await persistence.addRule('WebSearch', 'auto', { scope: 'global' });
165
+ await persistence.clearRules('global');
166
+ const rules = await persistence.getRules('global');
167
+ expect(rules.length).toBe(0);
168
+ });
169
+ });
170
+ });
171
+ //# sourceMappingURL=persistence.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.test.js","sourceRoot":"","sources":["../../src/permissions/persistence.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Prompt Matcher - Semantic permission matching for Claude Code style prompts
3
+ *
4
+ * Matches semantic descriptions like "run tests" to actual commands like "npm test".
5
+ * Used for ExitPlanMode allowedPrompts feature.
6
+ */
7
+ /**
8
+ * Pattern matcher function type
9
+ */
10
+ type PatternMatcher = (input: unknown) => boolean;
11
+ /**
12
+ * Prompt Matcher class
13
+ * Matches semantic permission prompts to actual tool inputs
14
+ */
15
+ export declare class PromptMatcher {
16
+ private customPatterns;
17
+ /**
18
+ * Register a custom pattern
19
+ */
20
+ registerPattern(prompt: string, matcher: PatternMatcher): void;
21
+ /**
22
+ * Check if input matches a semantic prompt
23
+ */
24
+ matches(prompt: string, input: unknown): boolean;
25
+ /**
26
+ * Fuzzy keyword-based matching for custom prompts
27
+ */
28
+ private fuzzyMatch;
29
+ /**
30
+ * Convert input to searchable string
31
+ */
32
+ private inputToString;
33
+ /**
34
+ * Get list of available built-in patterns
35
+ */
36
+ getBuiltinPatterns(): string[];
37
+ /**
38
+ * Get list of custom patterns
39
+ */
40
+ getCustomPatterns(): string[];
41
+ }
42
+ /**
43
+ * Pattern string parser for Claude Code style patterns
44
+ * Parses "Bash(git add:*)" into { tool: "Bash", pattern: "git add:*" }
45
+ */
46
+ export declare function parsePatternString(pattern: string): {
47
+ tool: string;
48
+ pattern?: string;
49
+ } | null;
50
+ /**
51
+ * Check if an input matches a pattern string
52
+ * Pattern format: "git add:*" or "npm install:*"
53
+ *
54
+ * Supports:
55
+ * - "git:*" - prefix matching (: becomes whitespace)
56
+ * - "npm *" - wildcard matching
57
+ * - "* install" - suffix matching
58
+ * - "git * main" - middle wildcard
59
+ * - Shell operator awareness: "safe-cmd:*" won't match "safe-cmd && malicious-cmd"
60
+ * - Path patterns for Read/Edit: "src/**", "~/.zshrc"
61
+ */
62
+ export declare function matchesPatternString(pattern: string, input: unknown, tool?: string): boolean;
63
+ export {};
64
+ //# sourceMappingURL=prompt-matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-matcher.d.ts","sourceRoot":"","sources":["../../src/permissions/prompt-matcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,KAAK,cAAc,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;AAgOlD;;;GAGG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,cAAc,CAA0C;IAEhE;;OAEG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI;IAI9D;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO;IAmBhD;;OAEG;IACH,OAAO,CAAC,UAAU;IAiBlB;;OAEG;IACH,OAAO,CAAC,aAAa;IAwBrB;;OAEG;IACH,kBAAkB,IAAI,MAAM,EAAE;IAI9B;;OAEG;IACH,iBAAiB,IAAI,MAAM,EAAE;CAG9B;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAS7F;AAyED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAyC5F"}
@@ -0,0 +1,415 @@
1
+ /**
2
+ * Prompt Matcher - Semantic permission matching for Claude Code style prompts
3
+ *
4
+ * Matches semantic descriptions like "run tests" to actual commands like "npm test".
5
+ * Used for ExitPlanMode allowedPrompts feature.
6
+ */
7
+ /**
8
+ * Built-in semantic patterns for common development operations
9
+ */
10
+ const BUILTIN_PATTERNS = new Map();
11
+ /**
12
+ * Command extraction helpers
13
+ */
14
+ function getCommand(input) {
15
+ if (typeof input === 'string')
16
+ return input;
17
+ if (input && typeof input === 'object' && 'command' in input) {
18
+ return String(input.command);
19
+ }
20
+ return '';
21
+ }
22
+ function getFilePath(input) {
23
+ if (typeof input === 'string')
24
+ return input;
25
+ if (input && typeof input === 'object') {
26
+ const obj = input;
27
+ return String(obj.file_path || obj.filePath || obj.path || '');
28
+ }
29
+ return '';
30
+ }
31
+ function getUrl(input) {
32
+ if (typeof input === 'string')
33
+ return input;
34
+ if (input && typeof input === 'object' && 'url' in input) {
35
+ return String(input.url);
36
+ }
37
+ return '';
38
+ }
39
+ /**
40
+ * Initialize built-in semantic patterns
41
+ */
42
+ function initBuiltinPatterns() {
43
+ // ============================================================================
44
+ // Testing
45
+ // ============================================================================
46
+ BUILTIN_PATTERNS.set('run tests', (input) => {
47
+ const cmd = getCommand(input).toLowerCase();
48
+ return (cmd.startsWith('npm test') ||
49
+ cmd.startsWith('npm run test') ||
50
+ cmd.startsWith('yarn test') ||
51
+ cmd.startsWith('pnpm test') ||
52
+ cmd.startsWith('bun test') ||
53
+ cmd.startsWith('pytest') ||
54
+ cmd.startsWith('python -m pytest') ||
55
+ cmd.startsWith('go test') ||
56
+ cmd.startsWith('jest') ||
57
+ cmd.startsWith('vitest') ||
58
+ cmd.startsWith('mocha') ||
59
+ cmd.startsWith('cargo test') ||
60
+ cmd.startsWith('make test') ||
61
+ cmd.includes('npm run test') ||
62
+ cmd.includes('npx jest') ||
63
+ cmd.includes('npx vitest'));
64
+ });
65
+ // ============================================================================
66
+ // Dependencies
67
+ // ============================================================================
68
+ BUILTIN_PATTERNS.set('install dependencies', (input) => {
69
+ const cmd = getCommand(input).toLowerCase();
70
+ return (cmd.startsWith('npm install') ||
71
+ cmd.startsWith('npm i') ||
72
+ cmd.startsWith('npm ci') ||
73
+ cmd.startsWith('yarn install') ||
74
+ cmd.startsWith('yarn add') ||
75
+ cmd.startsWith('pnpm install') ||
76
+ cmd.startsWith('pnpm add') ||
77
+ cmd.startsWith('bun install') ||
78
+ cmd.startsWith('bun add') ||
79
+ cmd.startsWith('pip install') ||
80
+ cmd.startsWith('pip3 install') ||
81
+ cmd.startsWith('poetry install') ||
82
+ cmd.startsWith('go mod download') ||
83
+ cmd.startsWith('go get') ||
84
+ cmd.startsWith('cargo build') ||
85
+ cmd.startsWith('cargo fetch') ||
86
+ cmd.startsWith('bundle install') ||
87
+ cmd.startsWith('composer install'));
88
+ });
89
+ // ============================================================================
90
+ // Building
91
+ // ============================================================================
92
+ BUILTIN_PATTERNS.set('build the project', (input) => {
93
+ const cmd = getCommand(input).toLowerCase();
94
+ return (cmd.startsWith('npm run build') ||
95
+ cmd.startsWith('yarn build') ||
96
+ cmd.startsWith('pnpm build') ||
97
+ cmd.startsWith('bun run build') ||
98
+ cmd.startsWith('make') ||
99
+ cmd.startsWith('go build') ||
100
+ cmd.startsWith('cargo build') ||
101
+ cmd.startsWith('mvn package') ||
102
+ cmd.startsWith('gradle build') ||
103
+ cmd.startsWith('tsc') ||
104
+ cmd.includes('webpack') ||
105
+ cmd.includes('vite build') ||
106
+ cmd.includes('rollup'));
107
+ });
108
+ // ============================================================================
109
+ // Git Operations
110
+ // ============================================================================
111
+ BUILTIN_PATTERNS.set('git operations', (input) => {
112
+ const cmd = getCommand(input).toLowerCase();
113
+ return cmd.startsWith('git ');
114
+ });
115
+ BUILTIN_PATTERNS.set('git status', (input) => {
116
+ const cmd = getCommand(input).toLowerCase();
117
+ return cmd.startsWith('git status') || cmd.startsWith('git diff') || cmd.startsWith('git log');
118
+ });
119
+ BUILTIN_PATTERNS.set('git commit', (input) => {
120
+ const cmd = getCommand(input).toLowerCase();
121
+ return (cmd.startsWith('git add') ||
122
+ cmd.startsWith('git commit') ||
123
+ cmd.startsWith('git stash'));
124
+ });
125
+ BUILTIN_PATTERNS.set('git push', (input) => {
126
+ const cmd = getCommand(input).toLowerCase();
127
+ return cmd.startsWith('git push');
128
+ });
129
+ BUILTIN_PATTERNS.set('git pull', (input) => {
130
+ const cmd = getCommand(input).toLowerCase();
131
+ return cmd.startsWith('git pull') || cmd.startsWith('git fetch');
132
+ });
133
+ // ============================================================================
134
+ // Linting & Formatting
135
+ // ============================================================================
136
+ BUILTIN_PATTERNS.set('lint code', (input) => {
137
+ const cmd = getCommand(input).toLowerCase();
138
+ return (cmd.startsWith('npm run lint') ||
139
+ cmd.startsWith('eslint') ||
140
+ cmd.startsWith('npx eslint') ||
141
+ cmd.startsWith('pylint') ||
142
+ cmd.startsWith('flake8') ||
143
+ cmd.startsWith('golint') ||
144
+ cmd.startsWith('cargo clippy'));
145
+ });
146
+ BUILTIN_PATTERNS.set('format code', (input) => {
147
+ const cmd = getCommand(input).toLowerCase();
148
+ return (cmd.startsWith('npm run format') ||
149
+ cmd.startsWith('prettier') ||
150
+ cmd.startsWith('npx prettier') ||
151
+ cmd.startsWith('black') ||
152
+ cmd.startsWith('gofmt') ||
153
+ cmd.startsWith('cargo fmt'));
154
+ });
155
+ // ============================================================================
156
+ // Development Server
157
+ // ============================================================================
158
+ BUILTIN_PATTERNS.set('start dev server', (input) => {
159
+ const cmd = getCommand(input).toLowerCase();
160
+ return (cmd.startsWith('npm run dev') ||
161
+ cmd.startsWith('npm start') ||
162
+ cmd.startsWith('yarn dev') ||
163
+ cmd.startsWith('pnpm dev') ||
164
+ cmd.startsWith('bun dev') ||
165
+ cmd.startsWith('python manage.py runserver') ||
166
+ cmd.startsWith('go run') ||
167
+ cmd.startsWith('cargo run'));
168
+ });
169
+ // ============================================================================
170
+ // Read Operations (file system)
171
+ // ============================================================================
172
+ BUILTIN_PATTERNS.set('read files', (input) => {
173
+ const cmd = getCommand(input).toLowerCase();
174
+ return (cmd.startsWith('cat ') ||
175
+ cmd.startsWith('less ') ||
176
+ cmd.startsWith('head ') ||
177
+ cmd.startsWith('tail ') ||
178
+ cmd.startsWith('ls ') ||
179
+ cmd.startsWith('find ') ||
180
+ cmd.startsWith('grep '));
181
+ });
182
+ // ============================================================================
183
+ // Type Checking
184
+ // ============================================================================
185
+ BUILTIN_PATTERNS.set('type check', (input) => {
186
+ const cmd = getCommand(input).toLowerCase();
187
+ return (cmd.startsWith('tsc --noEmit') ||
188
+ cmd.startsWith('npx tsc') ||
189
+ cmd.startsWith('npm run typecheck') ||
190
+ cmd.startsWith('mypy') ||
191
+ cmd.startsWith('pyright'));
192
+ });
193
+ }
194
+ // Initialize patterns on module load
195
+ initBuiltinPatterns();
196
+ /**
197
+ * Prompt Matcher class
198
+ * Matches semantic permission prompts to actual tool inputs
199
+ */
200
+ export class PromptMatcher {
201
+ customPatterns = new Map();
202
+ /**
203
+ * Register a custom pattern
204
+ */
205
+ registerPattern(prompt, matcher) {
206
+ this.customPatterns.set(prompt.toLowerCase(), matcher);
207
+ }
208
+ /**
209
+ * Check if input matches a semantic prompt
210
+ */
211
+ matches(prompt, input) {
212
+ const normalizedPrompt = prompt.toLowerCase().trim();
213
+ // Check custom patterns first
214
+ const customMatcher = this.customPatterns.get(normalizedPrompt);
215
+ if (customMatcher) {
216
+ return customMatcher(input);
217
+ }
218
+ // Check built-in patterns
219
+ const builtinMatcher = BUILTIN_PATTERNS.get(normalizedPrompt);
220
+ if (builtinMatcher) {
221
+ return builtinMatcher(input);
222
+ }
223
+ // Fuzzy matching: check if any keywords from prompt appear in input
224
+ return this.fuzzyMatch(normalizedPrompt, input);
225
+ }
226
+ /**
227
+ * Fuzzy keyword-based matching for custom prompts
228
+ */
229
+ fuzzyMatch(prompt, input) {
230
+ const inputStr = this.inputToString(input).toLowerCase();
231
+ // Extract meaningful keywords (skip common words)
232
+ const stopWords = new Set([
233
+ 'the', 'a', 'an', 'to', 'for', 'in', 'on', 'at', 'with',
234
+ 'run', 'execute', 'do', 'perform', 'make', 'this', 'that',
235
+ ]);
236
+ const keywords = prompt
237
+ .split(/\s+/)
238
+ .filter((word) => word.length > 2 && !stopWords.has(word));
239
+ // Require at least one keyword match
240
+ return keywords.some((keyword) => inputStr.includes(keyword));
241
+ }
242
+ /**
243
+ * Convert input to searchable string
244
+ */
245
+ inputToString(input) {
246
+ if (typeof input === 'string')
247
+ return input;
248
+ if (input === null || input === undefined)
249
+ return '';
250
+ // Extract relevant fields
251
+ const parts = [];
252
+ if (typeof input === 'object') {
253
+ const obj = input;
254
+ // Common input fields
255
+ if (obj.command)
256
+ parts.push(String(obj.command));
257
+ if (obj.file_path)
258
+ parts.push(String(obj.file_path));
259
+ if (obj.filePath)
260
+ parts.push(String(obj.filePath));
261
+ if (obj.path)
262
+ parts.push(String(obj.path));
263
+ if (obj.url)
264
+ parts.push(String(obj.url));
265
+ if (obj.query)
266
+ parts.push(String(obj.query));
267
+ if (obj.pattern)
268
+ parts.push(String(obj.pattern));
269
+ if (obj.content)
270
+ parts.push(String(obj.content).slice(0, 100));
271
+ }
272
+ return parts.join(' ');
273
+ }
274
+ /**
275
+ * Get list of available built-in patterns
276
+ */
277
+ getBuiltinPatterns() {
278
+ return Array.from(BUILTIN_PATTERNS.keys());
279
+ }
280
+ /**
281
+ * Get list of custom patterns
282
+ */
283
+ getCustomPatterns() {
284
+ return Array.from(this.customPatterns.keys());
285
+ }
286
+ }
287
+ /**
288
+ * Pattern string parser for Claude Code style patterns
289
+ * Parses "Bash(git add:*)" into { tool: "Bash", pattern: "git add:*" }
290
+ */
291
+ export function parsePatternString(pattern) {
292
+ // Format: Tool(pattern) or just Tool
293
+ const match = pattern.match(/^(\w+)(?:\(([^)]+)\))?$/);
294
+ if (!match)
295
+ return null;
296
+ return {
297
+ tool: match[1],
298
+ pattern: match[2],
299
+ };
300
+ }
301
+ /**
302
+ * Check if command contains shell operators (&&, ||, ;, |).
303
+ * Commands with shell operators should NOT be auto-approved for security.
304
+ */
305
+ function containsShellOperators(command) {
306
+ // Check for shell operators: &&, ||, ;, |
307
+ // Order matters: check || before | to avoid partial matching
308
+ const operatorPattern = /(?:&&|\|\||[;|])/;
309
+ return operatorPattern.test(command);
310
+ }
311
+ /**
312
+ * Extract the first command from a shell command string (for display/logging).
313
+ */
314
+ function extractFirstCommand(command) {
315
+ const operatorPattern = /\s*(?:&&|\|\||[;|])\s*/;
316
+ const match = command.match(operatorPattern);
317
+ if (match && match.index !== undefined) {
318
+ return command.slice(0, match.index).trim();
319
+ }
320
+ return command.trim();
321
+ }
322
+ /**
323
+ * Extract file path from input for Read/Edit tools
324
+ */
325
+ function extractFilePath(input) {
326
+ if (typeof input === 'string')
327
+ return input;
328
+ if (input && typeof input === 'object') {
329
+ const obj = input;
330
+ const path = obj.file_path ?? obj.filePath ?? obj.path;
331
+ if (typeof path === 'string')
332
+ return path;
333
+ }
334
+ return null;
335
+ }
336
+ /**
337
+ * Match a path pattern against a file path (gitignore-style)
338
+ * Supports:
339
+ * - ** for any depth
340
+ * - * for single directory level
341
+ * - ~ for home directory
342
+ */
343
+ function matchesPathPattern(pattern, filePath) {
344
+ // Expand ~ to home directory
345
+ let expandedPattern = pattern;
346
+ if (pattern.startsWith('~/')) {
347
+ const home = process.env.HOME ?? process.env.USERPROFILE ?? '';
348
+ expandedPattern = home + pattern.slice(1);
349
+ }
350
+ // Convert glob pattern to regex
351
+ // First escape special regex chars except * and /
352
+ let regexStr = expandedPattern
353
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&');
354
+ // Handle ** (any depth) - must be done before * handling
355
+ regexStr = regexStr.replace(/\*\*/g, '{{DOUBLE_STAR}}');
356
+ // Handle * (single level, no slashes)
357
+ regexStr = regexStr.replace(/\*/g, '[^/]*');
358
+ // Restore ** as .* (any characters including /)
359
+ regexStr = regexStr.replace(/\{\{DOUBLE_STAR\}\}/g, '.*');
360
+ const regex = new RegExp(`^${regexStr}`);
361
+ return regex.test(filePath);
362
+ }
363
+ /**
364
+ * Check if an input matches a pattern string
365
+ * Pattern format: "git add:*" or "npm install:*"
366
+ *
367
+ * Supports:
368
+ * - "git:*" - prefix matching (: becomes whitespace)
369
+ * - "npm *" - wildcard matching
370
+ * - "* install" - suffix matching
371
+ * - "git * main" - middle wildcard
372
+ * - Shell operator awareness: "safe-cmd:*" won't match "safe-cmd && malicious-cmd"
373
+ * - Path patterns for Read/Edit: "src/**", "~/.zshrc"
374
+ */
375
+ export function matchesPatternString(pattern, input, tool) {
376
+ // For file operations, use path matching
377
+ if (tool && ['Read', 'Edit', 'Write', 'Glob'].includes(tool)) {
378
+ const filePath = extractFilePath(input);
379
+ if (filePath) {
380
+ return matchesPathPattern(pattern, filePath);
381
+ }
382
+ }
383
+ // Extract command string from input
384
+ let inputStr;
385
+ if (typeof input === 'string') {
386
+ inputStr = input;
387
+ }
388
+ else if (input && typeof input === 'object') {
389
+ const obj = input;
390
+ if (obj.command && typeof obj.command === 'string') {
391
+ const command = obj.command;
392
+ // Shell operator awareness: reject commands with operators for security
393
+ // This prevents bypassing permissions with "safe-cmd && malicious-cmd"
394
+ if (containsShellOperators(command)) {
395
+ return false;
396
+ }
397
+ inputStr = command;
398
+ }
399
+ else {
400
+ inputStr = JSON.stringify(input);
401
+ }
402
+ }
403
+ else {
404
+ inputStr = JSON.stringify(input);
405
+ }
406
+ // Convert glob pattern to regex
407
+ // : is a separator (e.g., "git add:*" means "git add" followed by anything)
408
+ const regexStr = pattern
409
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&') // Escape special chars except * and :
410
+ .replace(/:/g, '\\s*') // : becomes optional whitespace
411
+ .replace(/\*/g, '.*'); // * becomes .*
412
+ const regex = new RegExp(`^${regexStr}`, 'i');
413
+ return regex.test(inputStr);
414
+ }
415
+ //# sourceMappingURL=prompt-matcher.js.map