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,213 @@
1
+ /**
2
+ * PermissionManager Tests
3
+ */
4
+ import { jest } from '@jest/globals';
5
+ import { PermissionManager } from './manager.js';
6
+ describe('PermissionManager', () => {
7
+ describe('default behavior', () => {
8
+ it('should auto-approve read-only tools by default', async () => {
9
+ const manager = new PermissionManager();
10
+ const readDecision = await manager.checkPermission({
11
+ tool: 'Read',
12
+ input: { file_path: '/test/file.ts' },
13
+ });
14
+ expect(readDecision.allowed).toBe(true);
15
+ expect(readDecision.requiresConfirmation).toBe(false);
16
+ const globDecision = await manager.checkPermission({
17
+ tool: 'Glob',
18
+ input: { pattern: '*.ts' },
19
+ });
20
+ expect(globDecision.allowed).toBe(true);
21
+ const grepDecision = await manager.checkPermission({
22
+ tool: 'Grep',
23
+ input: { pattern: 'test' },
24
+ });
25
+ expect(grepDecision.allowed).toBe(true);
26
+ });
27
+ it('should require confirmation for write operations by default', async () => {
28
+ const manager = new PermissionManager();
29
+ const bashDecision = await manager.checkPermission({
30
+ tool: 'Bash',
31
+ input: { command: 'echo hello' },
32
+ });
33
+ expect(bashDecision.allowed).toBe(false);
34
+ expect(bashDecision.requiresConfirmation).toBe(true);
35
+ const writeDecision = await manager.checkPermission({
36
+ tool: 'Write',
37
+ input: { file_path: '/test/file.ts', content: 'test' },
38
+ });
39
+ expect(writeDecision.allowed).toBe(false);
40
+ expect(writeDecision.requiresConfirmation).toBe(true);
41
+ });
42
+ });
43
+ describe('allow rules', () => {
44
+ it('should auto-approve operations matching allow rules', async () => {
45
+ const manager = new PermissionManager({
46
+ config: {
47
+ defaultMode: 'confirm',
48
+ rules: [
49
+ { tool: 'Bash', mode: 'auto', pattern: 'git add:*' },
50
+ ],
51
+ allowedPrompts: [],
52
+ },
53
+ });
54
+ const decision = await manager.checkPermission({
55
+ tool: 'Bash',
56
+ input: { command: 'git add .' },
57
+ });
58
+ expect(decision.allowed).toBe(true);
59
+ expect(decision.requiresConfirmation).toBe(false);
60
+ });
61
+ it('should still require confirmation for non-matching operations', async () => {
62
+ const manager = new PermissionManager({
63
+ config: {
64
+ defaultMode: 'confirm',
65
+ rules: [
66
+ { tool: 'Bash', mode: 'auto', pattern: 'git add:*' },
67
+ ],
68
+ allowedPrompts: [],
69
+ },
70
+ });
71
+ const decision = await manager.checkPermission({
72
+ tool: 'Bash',
73
+ input: { command: 'rm -rf /' },
74
+ });
75
+ expect(decision.allowed).toBe(false);
76
+ expect(decision.requiresConfirmation).toBe(true);
77
+ });
78
+ });
79
+ describe('deny rules', () => {
80
+ it('should block operations matching deny rules', async () => {
81
+ const manager = new PermissionManager({
82
+ config: {
83
+ defaultMode: 'confirm',
84
+ rules: [
85
+ { tool: 'Bash', mode: 'deny', pattern: 'rm -rf:*' },
86
+ ],
87
+ allowedPrompts: [],
88
+ },
89
+ });
90
+ const decision = await manager.checkPermission({
91
+ tool: 'Bash',
92
+ input: { command: 'rm -rf /' },
93
+ });
94
+ expect(decision.allowed).toBe(false);
95
+ expect(decision.requiresConfirmation).toBe(false);
96
+ });
97
+ it('should prioritize deny over allow rules', async () => {
98
+ const manager = new PermissionManager({
99
+ config: {
100
+ defaultMode: 'confirm',
101
+ rules: [
102
+ { tool: 'Bash', mode: 'auto', pattern: 'rm:*' },
103
+ { tool: 'Bash', mode: 'deny', pattern: 'rm -rf:*' },
104
+ ],
105
+ allowedPrompts: [],
106
+ },
107
+ });
108
+ const decision = await manager.checkPermission({
109
+ tool: 'Bash',
110
+ input: { command: 'rm -rf /' },
111
+ });
112
+ expect(decision.allowed).toBe(false);
113
+ expect(decision.requiresConfirmation).toBe(false);
114
+ });
115
+ });
116
+ describe('session caching', () => {
117
+ it('should cache session approvals', async () => {
118
+ const manager = new PermissionManager();
119
+ manager.approveForSession('Bash', 'npm test');
120
+ const decision = await manager.checkPermission({
121
+ tool: 'Bash',
122
+ input: { command: 'npm test' },
123
+ });
124
+ expect(decision.allowed).toBe(true);
125
+ });
126
+ it('should clear session cache', async () => {
127
+ const manager = new PermissionManager();
128
+ manager.approveForSession('Bash', 'npm test');
129
+ manager.clearSessionApprovals();
130
+ const decision = await manager.checkPermission({
131
+ tool: 'Bash',
132
+ input: { command: 'npm test' },
133
+ });
134
+ expect(decision.requiresConfirmation).toBe(true);
135
+ });
136
+ });
137
+ describe('prompt-based permissions', () => {
138
+ it('should approve operations matching allowed prompts', async () => {
139
+ const manager = new PermissionManager();
140
+ manager.addAllowedPrompts([
141
+ { tool: 'Bash', prompt: 'run tests' },
142
+ ]);
143
+ const decision = await manager.checkPermission({
144
+ tool: 'Bash',
145
+ input: { command: 'npm test' },
146
+ });
147
+ expect(decision.allowed).toBe(true);
148
+ });
149
+ it('should clear allowed prompts', () => {
150
+ const manager = new PermissionManager();
151
+ manager.addAllowedPrompts([
152
+ { tool: 'Bash', prompt: 'run tests' },
153
+ ]);
154
+ manager.clearAllowedPrompts();
155
+ expect(manager.getAllowedPrompts()).toHaveLength(0);
156
+ });
157
+ });
158
+ describe('confirmation callback', () => {
159
+ it('should call enhanced confirm callback when confirmation required', async () => {
160
+ const manager = new PermissionManager();
161
+ const mockCallback = jest.fn().mockResolvedValue('allow_once');
162
+ manager.setConfirmCallback(mockCallback);
163
+ const result = await manager.requestPermission('Bash', { command: 'echo hello' });
164
+ expect(mockCallback).toHaveBeenCalledWith('Bash', { command: 'echo hello' }, expect.any(Array));
165
+ expect(result).toBe(true);
166
+ });
167
+ it('should call saveRuleCallback when allow_always is selected', async () => {
168
+ const manager = new PermissionManager();
169
+ const mockSaveCallback = jest.fn().mockResolvedValue(undefined);
170
+ const mockConfirmCallback = jest.fn().mockResolvedValue('allow_always');
171
+ manager.setConfirmCallback(mockConfirmCallback);
172
+ manager.setSaveRuleCallback(mockSaveCallback);
173
+ await manager.requestPermission('Bash', { command: 'npm run build' });
174
+ expect(mockSaveCallback).toHaveBeenCalledWith('Bash', 'npm run:*');
175
+ });
176
+ });
177
+ describe('getModeForTool', () => {
178
+ it('should return auto for read-only tools', () => {
179
+ const manager = new PermissionManager();
180
+ expect(manager.getModeForTool('Read')).toBe('auto');
181
+ expect(manager.getModeForTool('Glob')).toBe('auto');
182
+ expect(manager.getModeForTool('Grep')).toBe('auto');
183
+ });
184
+ it('should return confirm for write tools', () => {
185
+ const manager = new PermissionManager();
186
+ expect(manager.getModeForTool('Bash')).toBe('confirm');
187
+ expect(manager.getModeForTool('Write')).toBe('confirm');
188
+ expect(manager.getModeForTool('Edit')).toBe('confirm');
189
+ });
190
+ });
191
+ describe('audit logging', () => {
192
+ it('should log permission decisions', async () => {
193
+ const manager = new PermissionManager({ enableAudit: true });
194
+ await manager.checkPermission({
195
+ tool: 'Read',
196
+ input: { file_path: '/test/file.ts' },
197
+ });
198
+ const auditLog = manager.getAuditLog(10);
199
+ expect(auditLog.length).toBeGreaterThan(0);
200
+ expect(auditLog[0].tool).toBe('Read');
201
+ });
202
+ it('should provide audit stats', async () => {
203
+ const manager = new PermissionManager({ enableAudit: true });
204
+ await manager.checkPermission({
205
+ tool: 'Read',
206
+ input: { file_path: '/test/file.ts' },
207
+ });
208
+ const stats = manager.getAuditStats();
209
+ expect(stats.allowed).toBeGreaterThanOrEqual(1);
210
+ });
211
+ });
212
+ });
213
+ //# sourceMappingURL=manager.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.test.js","sourceRoot":"","sources":["../../src/permissions/manager.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Permission Persistence - Store and load permission rules
3
+ *
4
+ * Handles persistent storage of permission rules at:
5
+ * - Global: ~/.gencode/permissions.json
6
+ * - Project: .gencode/permissions.json
7
+ */
8
+ import type { PersistedPermissions, PersistedRule, PermissionRule, PermissionScope, PermissionMode, PermissionSettings } from './types.js';
9
+ /**
10
+ * Permission Persistence Manager
11
+ */
12
+ export declare class PermissionPersistence {
13
+ private globalDir;
14
+ private projectDir;
15
+ constructor(projectPath?: string);
16
+ /**
17
+ * Generate unique rule ID
18
+ */
19
+ private generateId;
20
+ /**
21
+ * Ensure directory exists
22
+ */
23
+ private ensureDir;
24
+ /**
25
+ * Get path for scope
26
+ */
27
+ private getPath;
28
+ /**
29
+ * Load permissions from file
30
+ */
31
+ load(scope?: PermissionScope): Promise<PersistedPermissions>;
32
+ /**
33
+ * Save permissions to file
34
+ */
35
+ save(permissions: PersistedPermissions, scope?: PermissionScope): Promise<void>;
36
+ /**
37
+ * Add a new permission rule
38
+ */
39
+ addRule(tool: string, mode: PermissionMode, options?: {
40
+ pattern?: string;
41
+ scope?: PermissionScope;
42
+ description?: string;
43
+ }): Promise<PersistedRule>;
44
+ /**
45
+ * Remove a permission rule by ID
46
+ */
47
+ removeRule(ruleId: string, scope?: PermissionScope): Promise<boolean>;
48
+ /**
49
+ * Get all persisted rules for a scope
50
+ */
51
+ getRules(scope?: PermissionScope): Promise<PersistedRule[]>;
52
+ /**
53
+ * Get all rules (global + project)
54
+ */
55
+ getAllRules(): Promise<PersistedRule[]>;
56
+ /**
57
+ * Convert persisted rules to runtime permission rules
58
+ */
59
+ persistedToRuntime(persisted: PersistedRule[]): PermissionRule[];
60
+ /**
61
+ * Parse settings-style permissions (from settings.json)
62
+ * Claude Code format: { allow: ["Bash(git add:*)"], ask: ["Bash(npm run:*)"], deny: ["Bash(rm -rf:*)"] }
63
+ */
64
+ parseSettingsPermissions(settings: PermissionSettings): PermissionRule[];
65
+ /**
66
+ * Clear all rules for a scope
67
+ */
68
+ clearRules(scope?: PermissionScope): Promise<void>;
69
+ /**
70
+ * Check if permissions file exists
71
+ */
72
+ exists(scope?: PermissionScope): Promise<boolean>;
73
+ }
74
+ //# sourceMappingURL=persistence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../src/permissions/persistence.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EACV,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,eAAe,EACf,cAAc,EACd,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAOpB;;GAEG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAgB;gBAEtB,WAAW,CAAC,EAAE,MAAM;IAKhC;;OAEG;IACH,OAAO,CAAC,UAAU;IAIlB;;OAEG;YACW,SAAS;IAQvB;;OAEG;IACH,OAAO,CAAC,OAAO;IAef;;OAEG;IACG,IAAI,CAAC,KAAK,GAAE,eAA0B,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAkB5E;;OAEG;IACG,IAAI,CAAC,WAAW,EAAE,oBAAoB,EAAE,KAAK,GAAE,eAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB/F;;OAEG;IACG,OAAO,CACX,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,cAAc,EACpB,OAAO,GAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,eAAe,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;KACjB,GACL,OAAO,CAAC,aAAa,CAAC;IA0BzB;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,eAA0B,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBrF;;OAEG;IACG,QAAQ,CAAC,KAAK,GAAE,eAA0B,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAS3E;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAe7C;;OAEG;IACH,kBAAkB,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,cAAc,EAAE;IAUhE;;;OAGG;IACH,wBAAwB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,cAAc,EAAE;IAsDxE;;OAEG;IACG,UAAU,CAAC,KAAK,GAAE,eAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;IAUlE;;OAEG;IACG,MAAM,CAAC,KAAK,GAAE,eAA0B,GAAG,OAAO,CAAC,OAAO,CAAC;CAalE"}
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Permission Persistence - Store and load permission rules
3
+ *
4
+ * Handles persistent storage of permission rules at:
5
+ * - Global: ~/.gencode/permissions.json
6
+ * - Project: .gencode/permissions.json
7
+ */
8
+ import * as fs from 'fs/promises';
9
+ import * as path from 'path';
10
+ import * as os from 'os';
11
+ import { parsePatternString } from './prompt-matcher.js';
12
+ const PERMISSIONS_VERSION = 1;
13
+ const PERMISSIONS_FILE = 'permissions.json';
14
+ const GLOBAL_DIR = path.join(os.homedir(), '.gencode');
15
+ /**
16
+ * Permission Persistence Manager
17
+ */
18
+ export class PermissionPersistence {
19
+ globalDir;
20
+ projectDir;
21
+ constructor(projectPath) {
22
+ this.globalDir = GLOBAL_DIR;
23
+ this.projectDir = projectPath ? path.join(projectPath, '.gencode') : null;
24
+ }
25
+ /**
26
+ * Generate unique rule ID
27
+ */
28
+ generateId() {
29
+ return `rule_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
30
+ }
31
+ /**
32
+ * Ensure directory exists
33
+ */
34
+ async ensureDir(dir) {
35
+ try {
36
+ await fs.mkdir(dir, { recursive: true });
37
+ }
38
+ catch {
39
+ // Directory may already exist
40
+ }
41
+ }
42
+ /**
43
+ * Get path for scope
44
+ */
45
+ getPath(scope) {
46
+ switch (scope) {
47
+ case 'global':
48
+ return path.join(this.globalDir, PERMISSIONS_FILE);
49
+ case 'project':
50
+ if (!this.projectDir) {
51
+ throw new Error('Project path not set for project-scoped permissions');
52
+ }
53
+ return path.join(this.projectDir, PERMISSIONS_FILE);
54
+ default:
55
+ // Session scope is not persisted
56
+ throw new Error('Session-scoped permissions are not persisted');
57
+ }
58
+ }
59
+ /**
60
+ * Load permissions from file
61
+ */
62
+ async load(scope = 'global') {
63
+ try {
64
+ const filePath = this.getPath(scope);
65
+ const content = await fs.readFile(filePath, 'utf-8');
66
+ const data = JSON.parse(content);
67
+ // Migration: add version if missing
68
+ if (!data.version) {
69
+ data.version = PERMISSIONS_VERSION;
70
+ }
71
+ return data;
72
+ }
73
+ catch {
74
+ // Return empty permissions
75
+ return { version: PERMISSIONS_VERSION, rules: [] };
76
+ }
77
+ }
78
+ /**
79
+ * Save permissions to file
80
+ */
81
+ async save(permissions, scope = 'global') {
82
+ const dir = scope === 'global' ? this.globalDir : this.projectDir;
83
+ if (!dir) {
84
+ throw new Error('Project path not set for project-scoped permissions');
85
+ }
86
+ await this.ensureDir(dir);
87
+ const filePath = this.getPath(scope);
88
+ await fs.writeFile(filePath, JSON.stringify(permissions, null, 2), 'utf-8');
89
+ }
90
+ /**
91
+ * Add a new permission rule
92
+ */
93
+ async addRule(tool, mode, options = {}) {
94
+ const scope = options.scope ?? 'global';
95
+ // Session rules are not persisted
96
+ if (scope === 'session') {
97
+ throw new Error('Session-scoped rules cannot be persisted');
98
+ }
99
+ const permissions = await this.load(scope);
100
+ const rule = {
101
+ id: this.generateId(),
102
+ tool,
103
+ pattern: options.pattern,
104
+ mode,
105
+ scope,
106
+ createdAt: new Date().toISOString(),
107
+ description: options.description,
108
+ };
109
+ permissions.rules.push(rule);
110
+ await this.save(permissions, scope);
111
+ return rule;
112
+ }
113
+ /**
114
+ * Remove a permission rule by ID
115
+ */
116
+ async removeRule(ruleId, scope = 'global') {
117
+ if (scope === 'session') {
118
+ return false;
119
+ }
120
+ const permissions = await this.load(scope);
121
+ const initialLength = permissions.rules.length;
122
+ permissions.rules = permissions.rules.filter((r) => r.id !== ruleId);
123
+ if (permissions.rules.length < initialLength) {
124
+ await this.save(permissions, scope);
125
+ return true;
126
+ }
127
+ return false;
128
+ }
129
+ /**
130
+ * Get all persisted rules for a scope
131
+ */
132
+ async getRules(scope = 'global') {
133
+ if (scope === 'session') {
134
+ return [];
135
+ }
136
+ const permissions = await this.load(scope);
137
+ return permissions.rules;
138
+ }
139
+ /**
140
+ * Get all rules (global + project)
141
+ */
142
+ async getAllRules() {
143
+ const globalRules = await this.getRules('global');
144
+ let projectRules = [];
145
+ if (this.projectDir) {
146
+ try {
147
+ projectRules = await this.getRules('project');
148
+ }
149
+ catch {
150
+ // Project permissions file may not exist
151
+ }
152
+ }
153
+ return [...projectRules, ...globalRules];
154
+ }
155
+ /**
156
+ * Convert persisted rules to runtime permission rules
157
+ */
158
+ persistedToRuntime(persisted) {
159
+ return persisted.map((p) => ({
160
+ tool: p.tool,
161
+ mode: p.mode,
162
+ pattern: p.pattern,
163
+ scope: p.scope,
164
+ description: p.description,
165
+ }));
166
+ }
167
+ /**
168
+ * Parse settings-style permissions (from settings.json)
169
+ * Claude Code format: { allow: ["Bash(git add:*)"], ask: ["Bash(npm run:*)"], deny: ["Bash(rm -rf:*)"] }
170
+ */
171
+ parseSettingsPermissions(settings) {
172
+ const rules = [];
173
+ // Parse allow rules (auto-approve)
174
+ if (settings.allow) {
175
+ for (const pattern of settings.allow) {
176
+ const parsed = parsePatternString(pattern);
177
+ if (parsed) {
178
+ rules.push({
179
+ tool: parsed.tool,
180
+ mode: 'auto',
181
+ pattern: parsed.pattern,
182
+ scope: 'global',
183
+ description: `Settings: ${pattern}`,
184
+ });
185
+ }
186
+ }
187
+ }
188
+ // Parse ask rules (require confirmation)
189
+ if (settings.ask) {
190
+ for (const pattern of settings.ask) {
191
+ const parsed = parsePatternString(pattern);
192
+ if (parsed) {
193
+ rules.push({
194
+ tool: parsed.tool,
195
+ mode: 'confirm',
196
+ pattern: parsed.pattern,
197
+ scope: 'global',
198
+ description: `Settings: ${pattern}`,
199
+ });
200
+ }
201
+ }
202
+ }
203
+ // Parse deny rules (block)
204
+ if (settings.deny) {
205
+ for (const pattern of settings.deny) {
206
+ const parsed = parsePatternString(pattern);
207
+ if (parsed) {
208
+ rules.push({
209
+ tool: parsed.tool,
210
+ mode: 'deny',
211
+ pattern: parsed.pattern,
212
+ scope: 'global',
213
+ description: `Settings: ${pattern}`,
214
+ });
215
+ }
216
+ }
217
+ }
218
+ return rules;
219
+ }
220
+ /**
221
+ * Clear all rules for a scope
222
+ */
223
+ async clearRules(scope = 'global') {
224
+ if (scope === 'session') {
225
+ return;
226
+ }
227
+ const permissions = await this.load(scope);
228
+ permissions.rules = [];
229
+ await this.save(permissions, scope);
230
+ }
231
+ /**
232
+ * Check if permissions file exists
233
+ */
234
+ async exists(scope = 'global') {
235
+ if (scope === 'session') {
236
+ return false;
237
+ }
238
+ try {
239
+ const filePath = this.getPath(scope);
240
+ await fs.access(filePath);
241
+ return true;
242
+ }
243
+ catch {
244
+ return false;
245
+ }
246
+ }
247
+ }
248
+ //# sourceMappingURL=persistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.js","sourceRoot":"","sources":["../../src/permissions/persistence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * PermissionPersistence Tests
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=persistence.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.test.d.ts","sourceRoot":"","sources":["../../src/permissions/persistence.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}