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.
- package/.gencode/settings.local.json +7 -0
- package/README.md +11 -11
- package/dist/agent/agent.d.ts +42 -1
- package/dist/agent/agent.d.ts.map +1 -1
- package/dist/agent/agent.js +82 -15
- package/dist/agent/agent.js.map +1 -1
- package/dist/cli/components/App.d.ts +8 -1
- package/dist/cli/components/App.d.ts.map +1 -1
- package/dist/cli/components/App.js +231 -29
- package/dist/cli/components/App.js.map +1 -1
- package/dist/cli/components/CommandSuggestions.d.ts.map +1 -1
- package/dist/cli/components/CommandSuggestions.js +2 -0
- package/dist/cli/components/CommandSuggestions.js.map +1 -1
- package/dist/cli/components/Header.d.ts +1 -1
- package/dist/cli/components/Header.d.ts.map +1 -1
- package/dist/cli/components/Header.js +4 -6
- package/dist/cli/components/Header.js.map +1 -1
- package/dist/cli/components/Logo.d.ts +1 -0
- package/dist/cli/components/Logo.d.ts.map +1 -1
- package/dist/cli/components/Logo.js +16 -3
- package/dist/cli/components/Logo.js.map +1 -1
- package/dist/cli/components/Messages.d.ts +4 -4
- package/dist/cli/components/Messages.d.ts.map +1 -1
- package/dist/cli/components/Messages.js +51 -25
- package/dist/cli/components/Messages.js.map +1 -1
- package/dist/cli/components/PermissionPrompt.d.ts +60 -0
- package/dist/cli/components/PermissionPrompt.d.ts.map +1 -0
- package/dist/cli/components/PermissionPrompt.js +192 -0
- package/dist/cli/components/PermissionPrompt.js.map +1 -0
- package/dist/cli/components/ProviderManager.js +3 -3
- package/dist/cli/components/ProviderManager.js.map +1 -1
- package/dist/cli/components/Spinner.d.ts +7 -2
- package/dist/cli/components/Spinner.d.ts.map +1 -1
- package/dist/cli/components/Spinner.js +116 -25
- package/dist/cli/components/Spinner.js.map +1 -1
- package/dist/cli/components/TodoList.d.ts +7 -0
- package/dist/cli/components/TodoList.d.ts.map +1 -0
- package/dist/cli/components/TodoList.js +34 -0
- package/dist/cli/components/TodoList.js.map +1 -0
- package/dist/cli/components/index.d.ts +1 -0
- package/dist/cli/components/index.d.ts.map +1 -1
- package/dist/cli/components/index.js +1 -0
- package/dist/cli/components/index.js.map +1 -1
- package/dist/cli/index.js +47 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.d.ts +13 -4
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +18 -3
- package/dist/config/index.js.map +1 -1
- package/dist/config/levels.d.ts +49 -0
- package/dist/config/levels.d.ts.map +1 -0
- package/dist/config/levels.js +222 -0
- package/dist/config/levels.js.map +1 -0
- package/dist/config/loader.d.ts +46 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +153 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/manager.d.ts +115 -15
- package/dist/config/manager.d.ts.map +1 -1
- package/dist/config/manager.js +260 -34
- package/dist/config/manager.js.map +1 -1
- package/dist/config/manager.test.d.ts +5 -0
- package/dist/config/manager.test.d.ts.map +1 -0
- package/dist/config/manager.test.js +192 -0
- package/dist/config/manager.test.js.map +1 -0
- package/dist/config/merger.d.ts +56 -0
- package/dist/config/merger.d.ts.map +1 -0
- package/dist/config/merger.js +177 -0
- package/dist/config/merger.js.map +1 -0
- package/dist/config/test-utils.d.ts +24 -0
- package/dist/config/test-utils.d.ts.map +1 -0
- package/dist/config/test-utils.js +55 -0
- package/dist/config/test-utils.js.map +1 -0
- package/dist/config/types.d.ts +78 -9
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +52 -2
- package/dist/config/types.js.map +1 -1
- package/dist/memory/import-resolver.d.ts +46 -0
- package/dist/memory/import-resolver.d.ts.map +1 -0
- package/dist/memory/import-resolver.js +117 -0
- package/dist/memory/import-resolver.js.map +1 -0
- package/dist/memory/index.d.ts +7 -6
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +7 -5
- package/dist/memory/index.js.map +1 -1
- package/dist/memory/init-prompt.d.ts +22 -0
- package/dist/memory/init-prompt.d.ts.map +1 -0
- package/dist/memory/init-prompt.js +103 -0
- package/dist/memory/init-prompt.js.map +1 -0
- package/dist/memory/memory-manager.d.ts +119 -0
- package/dist/memory/memory-manager.d.ts.map +1 -0
- package/dist/memory/memory-manager.js +587 -0
- package/dist/memory/memory-manager.js.map +1 -0
- package/dist/memory/rules-parser.d.ts +38 -0
- package/dist/memory/rules-parser.d.ts.map +1 -0
- package/dist/memory/rules-parser.js +69 -0
- package/dist/memory/rules-parser.js.map +1 -0
- package/dist/memory/test-utils.d.ts +20 -0
- package/dist/memory/test-utils.d.ts.map +1 -0
- package/dist/memory/test-utils.js +44 -0
- package/dist/memory/test-utils.js.map +1 -0
- package/dist/memory/types.d.ts +70 -63
- package/dist/memory/types.d.ts.map +1 -1
- package/dist/memory/types.js +42 -2
- package/dist/memory/types.js.map +1 -1
- package/dist/permissions/audit.d.ts +82 -0
- package/dist/permissions/audit.d.ts.map +1 -0
- package/dist/permissions/audit.js +229 -0
- package/dist/permissions/audit.js.map +1 -0
- package/dist/permissions/index.d.ts +11 -1
- package/dist/permissions/index.d.ts.map +1 -1
- package/dist/permissions/index.js +15 -0
- package/dist/permissions/index.js.map +1 -1
- package/dist/permissions/manager.d.ts +149 -13
- package/dist/permissions/manager.d.ts.map +1 -1
- package/dist/permissions/manager.js +480 -35
- package/dist/permissions/manager.js.map +1 -1
- package/dist/permissions/manager.test.d.ts +5 -0
- package/dist/permissions/manager.test.d.ts.map +1 -0
- package/dist/permissions/manager.test.js +213 -0
- package/dist/permissions/manager.test.js.map +1 -0
- package/dist/permissions/persistence.d.ts +74 -0
- package/dist/permissions/persistence.d.ts.map +1 -0
- package/dist/permissions/persistence.js +248 -0
- package/dist/permissions/persistence.js.map +1 -0
- package/dist/permissions/persistence.test.d.ts +5 -0
- package/dist/permissions/persistence.test.d.ts.map +1 -0
- package/dist/permissions/persistence.test.js +171 -0
- package/dist/permissions/persistence.test.js.map +1 -0
- package/dist/permissions/prompt-matcher.d.ts +64 -0
- package/dist/permissions/prompt-matcher.d.ts.map +1 -0
- package/dist/permissions/prompt-matcher.js +415 -0
- package/dist/permissions/prompt-matcher.js.map +1 -0
- package/dist/permissions/prompt-matcher.test.d.ts +5 -0
- package/dist/permissions/prompt-matcher.test.d.ts.map +1 -0
- package/dist/permissions/prompt-matcher.test.js +107 -0
- package/dist/permissions/prompt-matcher.test.js.map +1 -0
- package/dist/permissions/types.d.ts +157 -0
- package/dist/permissions/types.d.ts.map +1 -1
- package/dist/permissions/types.js +43 -8
- package/dist/permissions/types.js.map +1 -1
- package/dist/prompts/index.d.ts +92 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +241 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts.map +1 -1
- package/dist/tools/builtin/bash.js +2 -1
- package/dist/tools/builtin/bash.js.map +1 -1
- package/dist/tools/builtin/edit.d.ts.map +1 -1
- package/dist/tools/builtin/edit.js +2 -1
- package/dist/tools/builtin/edit.js.map +1 -1
- package/dist/tools/builtin/glob.d.ts.map +1 -1
- package/dist/tools/builtin/glob.js +2 -1
- package/dist/tools/builtin/glob.js.map +1 -1
- package/dist/tools/builtin/grep.d.ts.map +1 -1
- package/dist/tools/builtin/grep.js +2 -1
- package/dist/tools/builtin/grep.js.map +1 -1
- package/dist/tools/builtin/read.d.ts.map +1 -1
- package/dist/tools/builtin/read.js +2 -1
- package/dist/tools/builtin/read.js.map +1 -1
- package/dist/tools/builtin/todowrite.d.ts +15 -0
- package/dist/tools/builtin/todowrite.d.ts.map +1 -0
- package/dist/tools/builtin/todowrite.js +88 -0
- package/dist/tools/builtin/todowrite.js.map +1 -0
- package/dist/tools/builtin/webfetch.d.ts.map +1 -1
- package/dist/tools/builtin/webfetch.js +2 -5
- package/dist/tools/builtin/webfetch.js.map +1 -1
- package/dist/tools/builtin/websearch.d.ts.map +1 -1
- package/dist/tools/builtin/websearch.js +2 -16
- package/dist/tools/builtin/websearch.js.map +1 -1
- package/dist/tools/builtin/write.d.ts.map +1 -1
- package/dist/tools/builtin/write.js +2 -1
- package/dist/tools/builtin/write.js.map +1 -1
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +4 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/types.d.ts +22 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js +8 -0
- package/dist/tools/types.js.map +1 -1
- package/docs/config-system-comparison.md +707 -0
- package/docs/memory-system.md +238 -0
- package/docs/permissions.md +368 -0
- package/docs/proposals/0005-todo-system.md +350 -85
- package/docs/proposals/0006-memory-system.md +11 -10
- package/docs/proposals/0012-ask-user-question.md +941 -206
- package/docs/proposals/0023-permission-enhancements.md +61 -2
- package/docs/proposals/0041-configuration-system.md +33 -2
- package/docs/proposals/0042-prompt-optimization.md +866 -0
- package/docs/proposals/README.md +6 -5
- package/jest.config.js +26 -0
- package/package.json +8 -2
- package/src/agent/agent.ts +111 -16
- package/src/cli/components/App.tsx +309 -36
- package/src/cli/components/CommandSuggestions.tsx +2 -0
- package/src/cli/components/Header.tsx +11 -17
- package/src/cli/components/Logo.tsx +76 -9
- package/src/cli/components/Messages.tsx +73 -53
- package/src/cli/components/PermissionPrompt.tsx +388 -0
- package/src/cli/components/ProviderManager.tsx +5 -5
- package/src/cli/components/Spinner.tsx +138 -25
- package/src/cli/components/TodoList.tsx +54 -0
- package/src/cli/components/index.ts +6 -0
- package/src/cli/index.tsx +54 -6
- package/src/config/index.ts +78 -4
- package/src/config/levels.test.ts +163 -0
- package/src/config/levels.ts +285 -0
- package/src/config/loader.test.ts +120 -0
- package/src/config/loader.ts +178 -0
- package/src/config/manager.test.ts +215 -0
- package/src/config/manager.ts +328 -40
- package/src/config/merger.test.ts +360 -0
- package/src/config/merger.ts +221 -0
- package/src/config/test-utils.ts +79 -0
- package/src/config/types.ts +152 -9
- package/src/memory/import-resolver.test.ts +117 -0
- package/src/memory/import-resolver.ts +149 -0
- package/src/memory/index.ts +11 -0
- package/src/memory/init-prompt.ts +113 -0
- package/src/memory/memory-manager.test.ts +198 -0
- package/src/memory/memory-manager.ts +716 -0
- package/src/memory/rules-parser.test.ts +182 -0
- package/src/memory/rules-parser.ts +82 -0
- package/src/memory/test-utils.ts +60 -0
- package/src/memory/types.ts +119 -0
- package/src/permissions/audit.ts +284 -0
- package/src/permissions/index.ts +20 -1
- package/src/permissions/manager.test.ts +260 -0
- package/src/permissions/manager.ts +592 -40
- package/src/permissions/persistence.test.ts +220 -0
- package/src/permissions/persistence.ts +301 -0
- package/src/permissions/prompt-matcher.test.ts +213 -0
- package/src/permissions/prompt-matcher.ts +472 -0
- package/src/permissions/types.ts +236 -8
- package/src/prompts/index.test.ts +279 -0
- package/src/prompts/index.ts +306 -0
- package/src/prompts/system/anthropic.txt +29 -0
- package/src/prompts/system/base.txt +124 -0
- package/src/prompts/system/gemini.txt +35 -0
- package/src/prompts/system/generic.txt +128 -0
- package/src/prompts/system/openai.txt +29 -0
- package/src/prompts/tools/bash.txt +60 -0
- package/src/prompts/tools/edit.txt +29 -0
- package/src/prompts/tools/glob.txt +35 -0
- package/src/prompts/tools/grep.txt +43 -0
- package/src/prompts/tools/read.txt +22 -0
- package/src/prompts/tools/todowrite.txt +71 -0
- package/src/prompts/tools/webfetch.txt +34 -0
- package/src/prompts/tools/websearch.txt +41 -0
- package/src/prompts/tools/write.txt +23 -0
- package/src/tools/builtin/bash.ts +2 -1
- package/src/tools/builtin/edit.ts +2 -1
- package/src/tools/builtin/glob.ts +2 -1
- package/src/tools/builtin/grep.ts +2 -1
- package/src/tools/builtin/read.ts +2 -1
- package/src/tools/builtin/todowrite.ts +102 -0
- package/src/tools/builtin/webfetch.ts +2 -5
- package/src/tools/builtin/websearch.ts +2 -16
- package/src/tools/builtin/write.ts +2 -1
- package/src/tools/index.ts +4 -0
- package/src/tools/types.ts +12 -0
- package/tsconfig.json +1 -1
package/dist/config/manager.js
CHANGED
|
@@ -1,65 +1,291 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
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
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
36
|
+
* Load and merge all configuration sources
|
|
19
37
|
*/
|
|
20
|
-
async
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
25
|
-
|
|
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
|
-
*
|
|
68
|
+
* Get the full merged config with sources info
|
|
30
69
|
*/
|
|
31
|
-
|
|
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(
|
|
34
|
-
|
|
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
|
|
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
|
|
114
|
+
* Save to global user settings (default)
|
|
45
115
|
*/
|
|
46
116
|
async save(updates) {
|
|
47
|
-
await this.
|
|
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
|
-
*
|
|
120
|
+
* Add a permission rule
|
|
54
121
|
*/
|
|
55
|
-
|
|
56
|
-
|
|
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
|
|
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.
|
|
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
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/config/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -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"}
|