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
@@ -1,65 +1,291 @@
1
1
  /**
2
- * Settings Manager - Persists user settings (Claude Code style)
2
+ * Configuration Manager - Unified multi-level configuration (Claude Code compatible)
3
+ *
4
+ * Configuration hierarchy (merged in order, later overrides earlier):
5
+ * 1. User: ~/.claude/ + ~/.gencode/ (gencode wins within level)
6
+ * 2. Extra: GENCODE_CONFIG_DIRS directories
7
+ * 3. Project: .claude/ + .gencode/ (gencode wins within level)
8
+ * 4. Local: *.local.* files (gencode wins within level)
9
+ * 5. CLI: Command line arguments
10
+ * 6. Managed: System-wide enforced settings (cannot be overridden)
11
+ *
12
+ * Within each level, both .claude and .gencode directories are loaded and merged,
13
+ * with .gencode taking higher priority.
3
14
  */
4
15
  import * as fs from 'fs/promises';
5
16
  import * as path from 'path';
6
- import * as os from 'os';
7
- import { DEFAULT_SETTINGS_DIR, SETTINGS_FILE_NAME } from './types.js';
8
- export class SettingsManager {
9
- settingsDir;
10
- settingsPath;
11
- settings = {};
17
+ import { SETTINGS_FILE_NAME, SETTINGS_LOCAL_FILE_NAME } from './types.js';
18
+ import { loadAllSources, getExistingConfigFiles } from './loader.js';
19
+ import { mergeAllSources, mergeWithCliArgs, deepMerge, createMergeSummary } from './merger.js';
20
+ import { findProjectRoot, getPrimarySettingsDir, getSettingsFilePath } from './levels.js';
21
+ /**
22
+ * Configuration Manager
23
+ *
24
+ * Manages multi-level configuration loading, merging, and persistence.
25
+ * Compatible with both GenCode (.gencode/) and Claude Code (.claude/) directories.
26
+ */
27
+ export class ConfigManager {
28
+ cwd;
29
+ projectRoot = null;
30
+ mergedConfig = null;
31
+ cliArgs = {};
12
32
  constructor(options = {}) {
13
- const dir = options.settingsDir ?? DEFAULT_SETTINGS_DIR;
14
- this.settingsDir = dir.replace('~', os.homedir());
15
- this.settingsPath = path.join(this.settingsDir, SETTINGS_FILE_NAME);
33
+ this.cwd = options.cwd ?? process.cwd();
16
34
  }
17
35
  /**
18
- * Ensure settings directory exists
36
+ * Load and merge all configuration sources
19
37
  */
20
- async ensureDir() {
21
- try {
22
- await fs.mkdir(this.settingsDir, { recursive: true });
38
+ async load() {
39
+ // Find project root
40
+ this.projectRoot = await findProjectRoot(this.cwd);
41
+ // Load all sources
42
+ const sources = await loadAllSources(this.cwd);
43
+ // Merge all sources
44
+ let merged = mergeAllSources(sources);
45
+ // Apply CLI arguments if any
46
+ if (Object.keys(this.cliArgs).length > 0) {
47
+ merged = mergeWithCliArgs(merged, this.cliArgs);
23
48
  }
24
- catch {
25
- // Directory may already exist
49
+ this.mergedConfig = merged;
50
+ return merged;
51
+ }
52
+ /**
53
+ * Set CLI argument overrides
54
+ */
55
+ setCliArgs(args) {
56
+ this.cliArgs = args;
57
+ }
58
+ /**
59
+ * Get the current merged settings
60
+ */
61
+ get() {
62
+ if (!this.mergedConfig) {
63
+ return {};
26
64
  }
65
+ return { ...this.mergedConfig.settings };
27
66
  }
28
67
  /**
29
- * Load settings from disk
68
+ * Get the full merged config with sources info
30
69
  */
31
- async load() {
70
+ getMergedConfig() {
71
+ return this.mergedConfig;
72
+ }
73
+ /**
74
+ * Get all loaded sources
75
+ */
76
+ getSources() {
77
+ return this.mergedConfig?.sources ?? [];
78
+ }
79
+ /**
80
+ * Get managed deny rules
81
+ */
82
+ getManagedDeny() {
83
+ return this.mergedConfig?.managedDeny ?? [];
84
+ }
85
+ /**
86
+ * Save settings to a specific level
87
+ */
88
+ async saveToLevel(updates, level) {
89
+ if (!this.projectRoot) {
90
+ this.projectRoot = await findProjectRoot(this.cwd);
91
+ }
92
+ const dir = getPrimarySettingsDir(level, this.projectRoot);
93
+ const fileName = level === 'local' ? SETTINGS_LOCAL_FILE_NAME : SETTINGS_FILE_NAME;
94
+ const filePath = path.join(dir, fileName);
95
+ // Ensure directory exists
96
+ await fs.mkdir(dir, { recursive: true });
97
+ // Load existing settings for this level
98
+ let existing = {};
32
99
  try {
33
- const content = await fs.readFile(this.settingsPath, 'utf-8');
34
- this.settings = JSON.parse(content);
35
- return this.settings;
100
+ const content = await fs.readFile(filePath, 'utf-8');
101
+ existing = JSON.parse(content);
36
102
  }
37
103
  catch {
38
- // File doesn't exist or is invalid
39
- this.settings = {};
40
- return this.settings;
104
+ // File doesn't exist, start fresh
41
105
  }
106
+ // Merge updates into existing
107
+ const merged = deepMerge(existing, updates);
108
+ // Write back
109
+ await fs.writeFile(filePath, JSON.stringify(merged, null, 2), 'utf-8');
110
+ // Reload configuration
111
+ await this.load();
42
112
  }
43
113
  /**
44
- * Save settings to disk (merges with existing)
114
+ * Save to global user settings (default)
45
115
  */
46
116
  async save(updates) {
47
- await this.ensureDir();
48
- // Merge updates with existing settings
49
- this.settings = { ...this.settings, ...updates };
50
- await fs.writeFile(this.settingsPath, JSON.stringify(this.settings, null, 2), 'utf-8');
117
+ await this.saveToLevel(updates, 'user');
51
118
  }
52
119
  /**
53
- * Get current settings
120
+ * Add a permission rule
54
121
  */
55
- get() {
56
- return { ...this.settings };
122
+ async addPermissionRule(pattern, type, level = 'project') {
123
+ const updates = {
124
+ permissions: {
125
+ [type]: [pattern],
126
+ },
127
+ };
128
+ await this.saveToLevel(updates, level);
57
129
  }
58
130
  /**
59
- * Get settings file path
131
+ * Get existing config files
60
132
  */
133
+ async getExistingFiles() {
134
+ return getExistingConfigFiles(this.cwd);
135
+ }
136
+ /**
137
+ * Get debug summary of configuration
138
+ */
139
+ getDebugSummary() {
140
+ if (!this.mergedConfig) {
141
+ return 'Configuration not loaded';
142
+ }
143
+ return createMergeSummary(this.mergedConfig);
144
+ }
145
+ /**
146
+ * Get the project root directory
147
+ */
148
+ getProjectRoot() {
149
+ return this.projectRoot ?? this.cwd;
150
+ }
151
+ /**
152
+ * Get the current working directory
153
+ */
154
+ getCwd() {
155
+ return this.cwd;
156
+ }
157
+ /**
158
+ * Get the primary settings file path for a level
159
+ */
160
+ getSettingsPath(level = 'user') {
161
+ const projectRoot = this.projectRoot ?? this.cwd;
162
+ return getSettingsFilePath(level, projectRoot);
163
+ }
164
+ /**
165
+ * Get effective permissions (merged from all sources)
166
+ */
167
+ getEffectivePermissions() {
168
+ const settings = this.get();
169
+ const permissions = settings.permissions ?? {};
170
+ return {
171
+ allow: permissions.allow ?? [],
172
+ ask: permissions.ask ?? [],
173
+ deny: permissions.deny ?? [],
174
+ managedDeny: this.getManagedDeny(),
175
+ };
176
+ }
177
+ /**
178
+ * Check if a permission pattern is allowed
179
+ */
180
+ isAllowed(pattern) {
181
+ const { allow, deny, managedDeny } = this.getEffectivePermissions();
182
+ // Managed deny always wins
183
+ if (managedDeny.some((p) => this.matchPattern(pattern, p))) {
184
+ return false;
185
+ }
186
+ // Check deny list
187
+ if (deny.some((p) => this.matchPattern(pattern, p))) {
188
+ return false;
189
+ }
190
+ // Check allow list
191
+ return allow.some((p) => this.matchPattern(pattern, p));
192
+ }
193
+ /**
194
+ * Check if a permission pattern requires asking
195
+ */
196
+ shouldAsk(pattern) {
197
+ const { ask, allow, deny, managedDeny } = this.getEffectivePermissions();
198
+ // Managed deny always wins
199
+ if (managedDeny.some((p) => this.matchPattern(pattern, p))) {
200
+ return false; // Don't ask, just deny
201
+ }
202
+ // If explicitly allowed, don't ask
203
+ if (allow.some((p) => this.matchPattern(pattern, p))) {
204
+ return false;
205
+ }
206
+ // If explicitly denied, don't ask
207
+ if (deny.some((p) => this.matchPattern(pattern, p))) {
208
+ return false;
209
+ }
210
+ // Check ask list
211
+ if (ask.some((p) => this.matchPattern(pattern, p))) {
212
+ return true;
213
+ }
214
+ // Default: ask for unknown patterns
215
+ return true;
216
+ }
217
+ /**
218
+ * Simple pattern matching (supports * and :* wildcards)
219
+ */
220
+ matchPattern(value, pattern) {
221
+ // Exact match
222
+ if (value === pattern)
223
+ return true;
224
+ // Handle :* suffix (e.g., "Bash(git:*)" matches "Bash(git:status)")
225
+ if (pattern.endsWith(':*)')) {
226
+ const prefix = pattern.slice(0, -3); // Remove ":*)"
227
+ const valuePrefix = value.slice(0, value.lastIndexOf(':'));
228
+ return valuePrefix.startsWith(prefix);
229
+ }
230
+ // Handle * wildcards
231
+ if (pattern.includes('*')) {
232
+ const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
233
+ return regex.test(value);
234
+ }
235
+ return false;
236
+ }
237
+ }
238
+ // =============================================================================
239
+ // Legacy SettingsManager (backward compatibility)
240
+ // =============================================================================
241
+ /**
242
+ * Legacy SettingsManager for backward compatibility
243
+ *
244
+ * @deprecated Use ConfigManager instead
245
+ */
246
+ export class SettingsManager {
247
+ configManager;
248
+ globalDir;
249
+ projectDir;
250
+ constructor(options = {}) {
251
+ this.configManager = new ConfigManager({ cwd: options.cwd });
252
+ // For legacy compatibility
253
+ const cwd = options.cwd ?? process.cwd();
254
+ this.globalDir = options.settingsDir ?? getPrimarySettingsDir('user', cwd);
255
+ this.projectDir = getPrimarySettingsDir('project', cwd);
256
+ }
257
+ async load() {
258
+ const merged = await this.configManager.load();
259
+ return merged.settings;
260
+ }
261
+ async save(updates) {
262
+ await this.configManager.save(updates);
263
+ }
264
+ async saveToLevel(updates, level) {
265
+ const mappedLevel = level === 'global' ? 'user' : level;
266
+ await this.configManager.saveToLevel(updates, mappedLevel);
267
+ }
268
+ async addPermissionRule(pattern, type, level = 'project') {
269
+ const mappedLevel = level === 'global' ? 'user' : level;
270
+ await this.configManager.addPermissionRule(pattern, type, mappedLevel);
271
+ }
272
+ get() {
273
+ return this.configManager.get();
274
+ }
61
275
  getPath() {
62
- return this.settingsPath;
276
+ return this.configManager.getSettingsPath('user');
277
+ }
278
+ getProjectPath() {
279
+ return this.configManager.getSettingsPath('project');
280
+ }
281
+ getLocalPath() {
282
+ return this.configManager.getSettingsPath('local');
283
+ }
284
+ getCwd() {
285
+ return this.configManager.getCwd();
286
+ }
287
+ getProjectDir() {
288
+ return this.projectDir;
63
289
  }
64
290
  }
65
291
  //# sourceMappingURL=manager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/config/manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEtE,MAAM,OAAO,eAAe;IAClB,WAAW,CAAS;IACpB,YAAY,CAAS;IACrB,QAAQ,GAAa,EAAE,CAAC;IAEhC,YAAY,UAAkC,EAAE;QAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,IAAI,oBAAoB,CAAC;QACxD,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;IACtE,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,SAAS;QACrB,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,8BAA8B;QAChC,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI;QACR,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YAC9D,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACpC,OAAO,IAAI,CAAC,QAAQ,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACP,mCAAmC;YACnC,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;YACnB,OAAO,IAAI,CAAC,QAAQ,CAAC;QACvB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI,CAAC,OAA0B;QACnC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QAEvB,uCAAuC;QACvC,IAAI,CAAC,QAAQ,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,OAAO,EAAE,CAAC;QAEjD,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EACtC,OAAO,CACR,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,GAAG;QACD,OAAO,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,OAAO;QACL,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;CACF"}
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/config/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * SettingsManager Tests
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=manager.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.test.d.ts","sourceRoot":"","sources":["../../src/config/manager.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * SettingsManager Tests
3
+ */
4
+ import * as fs from 'fs/promises';
5
+ import * as path from 'path';
6
+ import * as os from 'os';
7
+ import { SettingsManager } from './manager.js';
8
+ describe('SettingsManager', () => {
9
+ let tempDir;
10
+ let globalDir;
11
+ let projectDir;
12
+ beforeEach(async () => {
13
+ // Create temp directories for testing
14
+ tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'gencode-test-'));
15
+ globalDir = path.join(tempDir, 'global');
16
+ projectDir = path.join(tempDir, 'project');
17
+ await fs.mkdir(globalDir, { recursive: true });
18
+ await fs.mkdir(projectDir, { recursive: true });
19
+ });
20
+ afterEach(async () => {
21
+ // Cleanup temp directories
22
+ await fs.rm(tempDir, { recursive: true, force: true });
23
+ });
24
+ describe('load', () => {
25
+ it('should load settings from a single file', async () => {
26
+ const settingsPath = path.join(globalDir, 'settings.json');
27
+ await fs.writeFile(settingsPath, JSON.stringify({
28
+ model: 'gpt-4o',
29
+ provider: 'openai',
30
+ }));
31
+ const manager = new SettingsManager({
32
+ settingsDir: globalDir,
33
+ cwd: projectDir,
34
+ });
35
+ const settings = await manager.load();
36
+ expect(settings.model).toBe('gpt-4o');
37
+ expect(settings.provider).toBe('openai');
38
+ });
39
+ it('should merge settings from multiple levels', async () => {
40
+ // Global settings
41
+ const globalSettings = path.join(globalDir, 'settings.json');
42
+ await fs.writeFile(globalSettings, JSON.stringify({
43
+ model: 'gpt-4o',
44
+ provider: 'openai',
45
+ }));
46
+ // Project settings directory
47
+ const projectSettingsDir = path.join(projectDir, '.claude');
48
+ await fs.mkdir(projectSettingsDir, { recursive: true });
49
+ // Project settings
50
+ const projectSettings = path.join(projectSettingsDir, 'settings.json');
51
+ await fs.writeFile(projectSettings, JSON.stringify({
52
+ model: 'claude-sonnet',
53
+ }));
54
+ const manager = new SettingsManager({
55
+ settingsDir: globalDir,
56
+ cwd: projectDir,
57
+ });
58
+ const settings = await manager.load();
59
+ // Model should be overridden by project
60
+ expect(settings.model).toBe('claude-sonnet');
61
+ // Provider should be inherited from global
62
+ expect(settings.provider).toBe('openai');
63
+ });
64
+ it('should concatenate array fields (permissions)', async () => {
65
+ // Global settings
66
+ const globalSettings = path.join(globalDir, 'settings.json');
67
+ await fs.writeFile(globalSettings, JSON.stringify({
68
+ permissions: {
69
+ allow: ['Bash(git:*)'],
70
+ },
71
+ }));
72
+ // Project settings directory
73
+ const projectSettingsDir = path.join(projectDir, '.claude');
74
+ await fs.mkdir(projectSettingsDir, { recursive: true });
75
+ // Project local settings
76
+ const projectLocal = path.join(projectSettingsDir, 'settings.local.json');
77
+ await fs.writeFile(projectLocal, JSON.stringify({
78
+ permissions: {
79
+ allow: ['WebSearch'],
80
+ },
81
+ }));
82
+ const manager = new SettingsManager({
83
+ settingsDir: globalDir,
84
+ cwd: projectDir,
85
+ });
86
+ const settings = await manager.load();
87
+ // Arrays should be concatenated
88
+ expect(settings.permissions?.allow).toContain('Bash(git:*)');
89
+ expect(settings.permissions?.allow).toContain('WebSearch');
90
+ expect(settings.permissions?.allow?.length).toBe(2);
91
+ });
92
+ });
93
+ describe('saveToLevel', () => {
94
+ it('should save to global level', async () => {
95
+ const manager = new SettingsManager({
96
+ settingsDir: globalDir,
97
+ cwd: projectDir,
98
+ });
99
+ await manager.saveToLevel({ model: 'test-model' }, 'global');
100
+ const content = await fs.readFile(path.join(globalDir, 'settings.json'), 'utf-8');
101
+ const saved = JSON.parse(content);
102
+ expect(saved.model).toBe('test-model');
103
+ });
104
+ it('should save to project local level', async () => {
105
+ // Create project settings directory
106
+ const projectSettingsDir = path.join(projectDir, '.claude');
107
+ await fs.mkdir(projectSettingsDir, { recursive: true });
108
+ const manager = new SettingsManager({
109
+ settingsDir: globalDir,
110
+ cwd: projectDir,
111
+ });
112
+ await manager.saveToLevel({ model: 'local-model' }, 'local');
113
+ const content = await fs.readFile(path.join(projectSettingsDir, 'settings.local.json'), 'utf-8');
114
+ const saved = JSON.parse(content);
115
+ expect(saved.model).toBe('local-model');
116
+ });
117
+ });
118
+ describe('addPermissionRule', () => {
119
+ it('should add allow rule to local level', async () => {
120
+ // Create project settings directory
121
+ const projectSettingsDir = path.join(projectDir, '.claude');
122
+ await fs.mkdir(projectSettingsDir, { recursive: true });
123
+ const manager = new SettingsManager({
124
+ settingsDir: globalDir,
125
+ cwd: projectDir,
126
+ });
127
+ await manager.addPermissionRule('Bash(npm test:*)', 'allow', 'local');
128
+ const content = await fs.readFile(path.join(projectSettingsDir, 'settings.local.json'), 'utf-8');
129
+ const saved = JSON.parse(content);
130
+ expect(saved.permissions?.allow).toContain('Bash(npm test:*)');
131
+ });
132
+ it('should add deny rule', async () => {
133
+ const manager = new SettingsManager({
134
+ settingsDir: globalDir,
135
+ cwd: projectDir,
136
+ });
137
+ await manager.addPermissionRule('Bash(rm -rf:*)', 'deny', 'global');
138
+ const content = await fs.readFile(path.join(globalDir, 'settings.json'), 'utf-8');
139
+ const saved = JSON.parse(content);
140
+ expect(saved.permissions?.deny).toContain('Bash(rm -rf:*)');
141
+ });
142
+ });
143
+ describe('directory fallback', () => {
144
+ it('should use .claude as primary directory', async () => {
145
+ // Create .claude directory (primary)
146
+ const claudeDir = path.join(projectDir, '.claude');
147
+ await fs.mkdir(claudeDir, { recursive: true });
148
+ // Create settings in .claude
149
+ await fs.writeFile(path.join(claudeDir, 'settings.json'), JSON.stringify({ model: 'claude-model' }));
150
+ // Also create .gencode directory (fallback)
151
+ const gencodeDir = path.join(projectDir, '.gencode');
152
+ await fs.mkdir(gencodeDir, { recursive: true });
153
+ await fs.writeFile(path.join(gencodeDir, 'settings.json'), JSON.stringify({ model: 'gencode-model' }));
154
+ const manager = new SettingsManager({
155
+ settingsDir: globalDir,
156
+ cwd: projectDir,
157
+ });
158
+ const settings = await manager.load();
159
+ // Should use .claude (primary)
160
+ expect(settings.model).toBe('claude-model');
161
+ });
162
+ it('should use .gencode when explicitly created first', async () => {
163
+ // Create .gencode directory first, then .claude (to test priority)
164
+ const gencodeDir = path.join(projectDir, '.gencode');
165
+ await fs.mkdir(gencodeDir, { recursive: true });
166
+ await fs.writeFile(path.join(gencodeDir, 'settings.json'), JSON.stringify({ model: 'gencode-model' }));
167
+ // Now create .claude (primary) with different model
168
+ const claudeDir = path.join(projectDir, '.claude');
169
+ await fs.mkdir(claudeDir, { recursive: true });
170
+ await fs.writeFile(path.join(claudeDir, 'settings.json'), JSON.stringify({ model: 'claude-model' }));
171
+ const manager = new SettingsManager({
172
+ settingsDir: globalDir,
173
+ cwd: projectDir,
174
+ });
175
+ // .claude is primary, so it should be used
176
+ expect(manager.getProjectDir()).toContain('.claude');
177
+ const settings = await manager.load();
178
+ // Should use .claude (primary) over .gencode
179
+ expect(settings.model).toBe('claude-model');
180
+ });
181
+ });
182
+ describe('getCwd', () => {
183
+ it('should return the working directory', () => {
184
+ const manager = new SettingsManager({
185
+ settingsDir: globalDir,
186
+ cwd: projectDir,
187
+ });
188
+ expect(manager.getCwd()).toBe(projectDir);
189
+ });
190
+ });
191
+ });
192
+ //# sourceMappingURL=manager.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.test.js","sourceRoot":"","sources":["../../src/config/manager.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Configuration Merger - Merge settings from multiple sources
3
+ *
4
+ * Implements the merge strategy:
5
+ * - Scalar values: Higher priority replaces lower
6
+ * - Arrays (permissions.allow, permissions.deny): Concatenate with deduplication
7
+ * - Objects: Deep merge recursively
8
+ * - Managed deny rules: Cannot be overridden by any level
9
+ */
10
+ import type { Settings, ConfigSource, MergedConfig } from './types.js';
11
+ /**
12
+ * Deep merge two objects
13
+ *
14
+ * - Arrays are concatenated and deduplicated
15
+ * - Objects are recursively merged
16
+ * - Scalars from override replace base
17
+ */
18
+ export declare function deepMerge<T extends Record<string, unknown>>(base: T, override: Partial<T>): T;
19
+ /**
20
+ * Merge all configuration sources into a single settings object
21
+ *
22
+ * Sources should be in priority order (lowest first).
23
+ * Each source is merged on top of the previous result.
24
+ */
25
+ export declare function mergeSettings(sources: ConfigSource[]): Settings;
26
+ /**
27
+ * Extract managed deny rules from sources
28
+ *
29
+ * These rules are extracted from managed-level sources and cannot be
30
+ * overridden by any lower-level configuration.
31
+ */
32
+ export declare function extractManagedDeny(sources: ConfigSource[]): string[];
33
+ /**
34
+ * Apply managed restrictions to the merged settings
35
+ *
36
+ * - Ensures managed deny rules are always in the deny list
37
+ * - Removes managed deny patterns from allow list
38
+ */
39
+ export declare function applyManagedRestrictions(settings: Settings, managedDeny: string[]): Settings;
40
+ /**
41
+ * Merge all configuration sources and apply restrictions
42
+ *
43
+ * This is the main entry point for configuration merging.
44
+ */
45
+ export declare function mergeAllSources(sources: ConfigSource[]): MergedConfig;
46
+ /**
47
+ * Merge settings with CLI arguments
48
+ *
49
+ * CLI arguments have the highest priority (except managed restrictions).
50
+ */
51
+ export declare function mergeWithCliArgs(merged: MergedConfig, cliArgs: Partial<Settings>): MergedConfig;
52
+ /**
53
+ * Create a debug summary of the merge process
54
+ */
55
+ export declare function createMergeSummary(merged: MergedConfig): string;
56
+ //# sourceMappingURL=merger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merger.d.ts","sourceRoot":"","sources":["../../src/config/merger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAmB,MAAM,YAAY,CAAC;AASxF;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzD,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,GACnB,CAAC,CA8BH;AAoBD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,QAAQ,CAQ/D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,EAAE,CAapE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,MAAM,EAAE,GACpB,QAAQ,CAqBV;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,YAAY,CAerE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,GACzB,YAAY,CAoBd;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAiB/D"}