@indy2kro/agentenv 0.1.0
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/LICENSE +21 -0
- package/README.md +320 -0
- package/dist/adapters/base.d.ts +58 -0
- package/dist/adapters/base.d.ts.map +1 -0
- package/dist/adapters/base.js +16 -0
- package/dist/adapters/base.js.map +1 -0
- package/dist/adapters/claude.d.ts +21 -0
- package/dist/adapters/claude.d.ts.map +1 -0
- package/dist/adapters/claude.js +198 -0
- package/dist/adapters/claude.js.map +1 -0
- package/dist/adapters/codex.d.ts +23 -0
- package/dist/adapters/codex.d.ts.map +1 -0
- package/dist/adapters/codex.js +134 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/copilot.d.ts +21 -0
- package/dist/adapters/copilot.d.ts.map +1 -0
- package/dist/adapters/copilot.js +111 -0
- package/dist/adapters/copilot.js.map +1 -0
- package/dist/adapters/detect.d.ts +23 -0
- package/dist/adapters/detect.d.ts.map +1 -0
- package/dist/adapters/detect.js +80 -0
- package/dist/adapters/detect.js.map +1 -0
- package/dist/adapters/index.d.ts +12 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +11 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/opencode.d.ts +19 -0
- package/dist/adapters/opencode.d.ts.map +1 -0
- package/dist/adapters/opencode.js +107 -0
- package/dist/adapters/opencode.js.map +1 -0
- package/dist/commands/apply.d.ts +21 -0
- package/dist/commands/apply.d.ts.map +1 -0
- package/dist/commands/apply.js +113 -0
- package/dist/commands/apply.js.map +1 -0
- package/dist/commands/configure.d.ts +13 -0
- package/dist/commands/configure.d.ts.map +1 -0
- package/dist/commands/configure.js +151 -0
- package/dist/commands/configure.js.map +1 -0
- package/dist/commands/setup.d.ts +11 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +78 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +152 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/config/schema.d.ts +142 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +778 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/scopes.d.ts +14 -0
- package/dist/config/scopes.d.ts.map +1 -0
- package/dist/config/scopes.js +32 -0
- package/dist/config/scopes.js.map +1 -0
- package/dist/generate/agentsmd.d.ts +44 -0
- package/dist/generate/agentsmd.d.ts.map +1 -0
- package/dist/generate/agentsmd.js +340 -0
- package/dist/generate/agentsmd.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/base.d.ts +33 -0
- package/dist/integrations/base.d.ts.map +1 -0
- package/dist/integrations/base.js +9 -0
- package/dist/integrations/base.js.map +1 -0
- package/dist/integrations/index.d.ts +7 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +5 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/superpowers.d.ts +48 -0
- package/dist/integrations/superpowers.d.ts.map +1 -0
- package/dist/integrations/superpowers.js +191 -0
- package/dist/integrations/superpowers.js.map +1 -0
- package/dist/shell/detector.d.ts +92 -0
- package/dist/shell/detector.d.ts.map +1 -0
- package/dist/shell/detector.js +714 -0
- package/dist/shell/detector.js.map +1 -0
- package/dist/toolchain/fallbacks.d.ts +77 -0
- package/dist/toolchain/fallbacks.d.ts.map +1 -0
- package/dist/toolchain/fallbacks.js +238 -0
- package/dist/toolchain/fallbacks.js.map +1 -0
- package/dist/toolchain/gh.d.ts +20 -0
- package/dist/toolchain/gh.d.ts.map +1 -0
- package/dist/toolchain/gh.js +36 -0
- package/dist/toolchain/gh.js.map +1 -0
- package/dist/toolchain/mise.d.ts +92 -0
- package/dist/toolchain/mise.d.ts.map +1 -0
- package/dist/toolchain/mise.js +346 -0
- package/dist/toolchain/mise.js.map +1 -0
- package/dist/toolchain/rtk.d.ts +27 -0
- package/dist/toolchain/rtk.d.ts.map +1 -0
- package/dist/toolchain/rtk.js +76 -0
- package/dist/toolchain/rtk.js.map +1 -0
- package/dist/wizard/build.d.ts +24 -0
- package/dist/wizard/build.d.ts.map +1 -0
- package/dist/wizard/build.js +64 -0
- package/dist/wizard/build.js.map +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,778 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentenv Configuration Schema
|
|
3
|
+
* Defines the structure and validation for agentenv.toml
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import toml from 'toml';
|
|
8
|
+
// Default configuration values
|
|
9
|
+
export const DEFAULT_CONFIG = {
|
|
10
|
+
scope: 'project',
|
|
11
|
+
agents: {
|
|
12
|
+
claude_code: true,
|
|
13
|
+
codex_cli: true,
|
|
14
|
+
copilot: true,
|
|
15
|
+
opencode: true,
|
|
16
|
+
},
|
|
17
|
+
tools: {
|
|
18
|
+
// Tier 1 - always enabled by default
|
|
19
|
+
ripgrep: true,
|
|
20
|
+
fd: true,
|
|
21
|
+
jq: true,
|
|
22
|
+
rtk: true,
|
|
23
|
+
// Tier 2 - enabled by default
|
|
24
|
+
ast_grep: true,
|
|
25
|
+
git_delta: true,
|
|
26
|
+
gh: true,
|
|
27
|
+
difftastic: true,
|
|
28
|
+
// Tier 3 - disabled by default
|
|
29
|
+
universal_ctags: false,
|
|
30
|
+
yq: false,
|
|
31
|
+
bat: false,
|
|
32
|
+
eza: false,
|
|
33
|
+
miller: false,
|
|
34
|
+
tokei: false,
|
|
35
|
+
hyperfine: false,
|
|
36
|
+
fzf: false,
|
|
37
|
+
just: false,
|
|
38
|
+
watchexec: false,
|
|
39
|
+
direnv: false,
|
|
40
|
+
},
|
|
41
|
+
rtk: {
|
|
42
|
+
enabled: true,
|
|
43
|
+
init: {
|
|
44
|
+
claude_code: true,
|
|
45
|
+
codex_cli: true,
|
|
46
|
+
copilot: true,
|
|
47
|
+
opencode: true,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
tier0: {
|
|
51
|
+
check_enabled: true,
|
|
52
|
+
},
|
|
53
|
+
generate: {
|
|
54
|
+
marker_start: '<!-- agentenv-managed-start -->',
|
|
55
|
+
marker_end: '<!-- agentenv-managed-end -->',
|
|
56
|
+
files: ['AGENTS.md', 'CLAUDE.md'],
|
|
57
|
+
},
|
|
58
|
+
integrations: {
|
|
59
|
+
superpowers: {
|
|
60
|
+
enabled: false,
|
|
61
|
+
source: 'github:obra/superpowers',
|
|
62
|
+
ref: 'v6.3.0',
|
|
63
|
+
agents: ['claude_code', 'codex_cli', 'copilot', 'opencode'],
|
|
64
|
+
allow_hooks: false,
|
|
65
|
+
allow_external_requests: false,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
// Known agent keys for validation
|
|
70
|
+
export const AGENT_KEYS = ['claude_code', 'codex_cli', 'copilot', 'opencode'];
|
|
71
|
+
// Known integration keys for validation
|
|
72
|
+
export const INTEGRATION_KEYS = ['superpowers'];
|
|
73
|
+
// Known tool keys for validation
|
|
74
|
+
export const TOOL_KEYS = [
|
|
75
|
+
'ripgrep',
|
|
76
|
+
'fd',
|
|
77
|
+
'jq',
|
|
78
|
+
'rtk',
|
|
79
|
+
'ast_grep',
|
|
80
|
+
'git_delta',
|
|
81
|
+
'universal_ctags',
|
|
82
|
+
'gh',
|
|
83
|
+
'difftastic',
|
|
84
|
+
'yq',
|
|
85
|
+
'bat',
|
|
86
|
+
'eza',
|
|
87
|
+
'miller',
|
|
88
|
+
'tokei',
|
|
89
|
+
'hyperfine',
|
|
90
|
+
'fzf',
|
|
91
|
+
'just',
|
|
92
|
+
'watchexec',
|
|
93
|
+
'direnv',
|
|
94
|
+
];
|
|
95
|
+
// Tool tiers for categorization
|
|
96
|
+
export const TOOL_TIERS = {
|
|
97
|
+
// Tier 1 - essential
|
|
98
|
+
ripgrep: 1,
|
|
99
|
+
fd: 1,
|
|
100
|
+
jq: 1,
|
|
101
|
+
rtk: 1,
|
|
102
|
+
// Tier 2 - AI-coding value-add
|
|
103
|
+
ast_grep: 2,
|
|
104
|
+
git_delta: 2,
|
|
105
|
+
universal_ctags: 2,
|
|
106
|
+
gh: 2,
|
|
107
|
+
difftastic: 2,
|
|
108
|
+
// Tier 3 - power-user
|
|
109
|
+
yq: 3,
|
|
110
|
+
bat: 3,
|
|
111
|
+
eza: 3,
|
|
112
|
+
miller: 3,
|
|
113
|
+
tokei: 3,
|
|
114
|
+
hyperfine: 3,
|
|
115
|
+
fzf: 3,
|
|
116
|
+
just: 3,
|
|
117
|
+
watchexec: 3,
|
|
118
|
+
direnv: 3,
|
|
119
|
+
};
|
|
120
|
+
// Binary name mappings (TOML key -> binary name)
|
|
121
|
+
export const BINARY_MAP = {
|
|
122
|
+
ripgrep: 'rg',
|
|
123
|
+
fd: 'fd',
|
|
124
|
+
jq: 'jq',
|
|
125
|
+
rtk: 'rtk',
|
|
126
|
+
ast_grep: 'sg',
|
|
127
|
+
git_delta: 'delta',
|
|
128
|
+
universal_ctags: 'ctags',
|
|
129
|
+
gh: 'gh',
|
|
130
|
+
difftastic: 'difft',
|
|
131
|
+
yq: 'yq',
|
|
132
|
+
bat: 'bat',
|
|
133
|
+
eza: 'eza',
|
|
134
|
+
miller: 'mlr',
|
|
135
|
+
tokei: 'tokei',
|
|
136
|
+
hyperfine: 'hyperfine',
|
|
137
|
+
fzf: 'fzf',
|
|
138
|
+
just: 'just',
|
|
139
|
+
watchexec: 'watchexec',
|
|
140
|
+
direnv: 'direnv',
|
|
141
|
+
};
|
|
142
|
+
// Tool descriptions
|
|
143
|
+
export const TOOL_DESCRIPTIONS = {
|
|
144
|
+
ripgrep: 'Fast text search (use instead of grep -r)',
|
|
145
|
+
fd: 'Fast, user-friendly file finder',
|
|
146
|
+
jq: 'Lightweight and flexible command-line JSON processor',
|
|
147
|
+
rtk: 'CLI proxy that reduces LLM token consumption by 60-90%',
|
|
148
|
+
ast_grep: 'Structural/AST-based code search and rewrite',
|
|
149
|
+
git_delta: 'Syntax-highlighted git diff pager',
|
|
150
|
+
universal_ctags: 'Universal ctags for code navigation',
|
|
151
|
+
difftastic: 'Structural diff tool that understands syntax',
|
|
152
|
+
gh: 'GitHub CLI for repository operations',
|
|
153
|
+
yq: 'YAML/TOML processor (jq for YAML)',
|
|
154
|
+
bat: 'cat clone with syntax highlighting and git integration',
|
|
155
|
+
eza: 'Modern replacement for ls',
|
|
156
|
+
miller: 'CSV/TSV data processing',
|
|
157
|
+
tokei: 'Fast code statistics (LOC, etc.)',
|
|
158
|
+
hyperfine: 'Command-line benchmarking tool',
|
|
159
|
+
fzf: 'Fuzzy finder with non-interactive filter mode',
|
|
160
|
+
just: 'Command runner for project recipes',
|
|
161
|
+
watchexec: 'File watcher that runs commands on changes',
|
|
162
|
+
direnv: 'Environment variable manager',
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* Load configuration from agentenv.toml file
|
|
166
|
+
* Searches in current directory, then user config directory
|
|
167
|
+
*/
|
|
168
|
+
export function loadConfig(configPath) {
|
|
169
|
+
let pathToLoad = configPath;
|
|
170
|
+
if (!pathToLoad) {
|
|
171
|
+
// Try current directory
|
|
172
|
+
try {
|
|
173
|
+
if (fs.existsSync('agentenv.toml')) {
|
|
174
|
+
pathToLoad = 'agentenv.toml';
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
// Ignore
|
|
179
|
+
}
|
|
180
|
+
// Try user config directory
|
|
181
|
+
if (!pathToLoad) {
|
|
182
|
+
const home = process.env.HOME || process.env.USERPROFILE || '';
|
|
183
|
+
const userConfigPath = path.join(home, '.config', 'agentenv', 'agentenv.toml');
|
|
184
|
+
try {
|
|
185
|
+
if (fs.existsSync(userConfigPath)) {
|
|
186
|
+
pathToLoad = userConfigPath;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
// Ignore
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (!pathToLoad) {
|
|
195
|
+
return { ...DEFAULT_CONFIG };
|
|
196
|
+
}
|
|
197
|
+
try {
|
|
198
|
+
const data = fs.readFileSync(pathToLoad, 'utf-8');
|
|
199
|
+
const parsed = toml.parse(data);
|
|
200
|
+
return mergeWithDefaults(normalizeConfig(parsed));
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
throw new Error(`Invalid agentenv configuration at ${pathToLoad}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Save configuration to agentenv.toml file
|
|
208
|
+
*/
|
|
209
|
+
export function saveConfig(config, configPath) {
|
|
210
|
+
try {
|
|
211
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
212
|
+
const tomlString = configToToml(config);
|
|
213
|
+
fs.writeFileSync(configPath, tomlString);
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
throw new Error(`Failed to save config: ${err}`, { cause: err });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Convert configuration object to TOML string
|
|
221
|
+
*/
|
|
222
|
+
export function configToToml(config) {
|
|
223
|
+
const lines = [];
|
|
224
|
+
// Scope
|
|
225
|
+
if (config.scope) {
|
|
226
|
+
lines.push(`scope = ${tomlString(config.scope)}`);
|
|
227
|
+
}
|
|
228
|
+
// Agents
|
|
229
|
+
if (config.agents) {
|
|
230
|
+
lines.push('\n[agents]');
|
|
231
|
+
if (config.agents.claude_code !== undefined)
|
|
232
|
+
lines.push(`claude_code = ${config.agents.claude_code}`);
|
|
233
|
+
if (config.agents.codex_cli !== undefined)
|
|
234
|
+
lines.push(`codex_cli = ${config.agents.codex_cli}`);
|
|
235
|
+
if (config.agents.copilot !== undefined)
|
|
236
|
+
lines.push(`copilot = ${config.agents.copilot}`);
|
|
237
|
+
if (config.agents.opencode !== undefined)
|
|
238
|
+
lines.push(`opencode = ${config.agents.opencode}`);
|
|
239
|
+
}
|
|
240
|
+
// Tools
|
|
241
|
+
if (config.tools) {
|
|
242
|
+
lines.push('\n[tools]');
|
|
243
|
+
const toolKeys = [
|
|
244
|
+
'ripgrep',
|
|
245
|
+
'fd',
|
|
246
|
+
'jq',
|
|
247
|
+
'rtk',
|
|
248
|
+
'ast_grep',
|
|
249
|
+
'git_delta',
|
|
250
|
+
'universal_ctags',
|
|
251
|
+
'gh',
|
|
252
|
+
'difftastic',
|
|
253
|
+
'yq',
|
|
254
|
+
'bat',
|
|
255
|
+
'eza',
|
|
256
|
+
'miller',
|
|
257
|
+
'tokei',
|
|
258
|
+
'hyperfine',
|
|
259
|
+
'fzf',
|
|
260
|
+
'just',
|
|
261
|
+
'watchexec',
|
|
262
|
+
'direnv',
|
|
263
|
+
];
|
|
264
|
+
for (const key of toolKeys) {
|
|
265
|
+
if (config.tools[key] !== undefined) {
|
|
266
|
+
lines.push(`${key} = ${config.tools[key]}`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// Custom tools
|
|
271
|
+
if (config.custom_tools && config.custom_tools.length > 0) {
|
|
272
|
+
for (const ct of config.custom_tools) {
|
|
273
|
+
lines.push('\n[[custom_tools]]');
|
|
274
|
+
lines.push(`name = ${tomlString(ct.name)}`);
|
|
275
|
+
lines.push(`description = ${tomlString(ct.description)}`);
|
|
276
|
+
if (ct.already_installed !== undefined)
|
|
277
|
+
lines.push(`already_installed = ${ct.already_installed}`);
|
|
278
|
+
if (ct.mise_source)
|
|
279
|
+
lines.push(`mise_source = ${tomlString(ct.mise_source)}`);
|
|
280
|
+
if (ct.version)
|
|
281
|
+
lines.push(`version = ${tomlString(ct.version)}`);
|
|
282
|
+
if (ct.path_windows)
|
|
283
|
+
lines.push(`path_windows = ${tomlString(ct.path_windows)}`);
|
|
284
|
+
if (ct.path_macos)
|
|
285
|
+
lines.push(`path_macos = ${tomlString(ct.path_macos)}`);
|
|
286
|
+
if (ct.path_linux)
|
|
287
|
+
lines.push(`path_linux = ${tomlString(ct.path_linux)}`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
// RTK
|
|
291
|
+
if (config.rtk) {
|
|
292
|
+
lines.push('\n[rtk]');
|
|
293
|
+
if (config.rtk.enabled !== undefined)
|
|
294
|
+
lines.push(`enabled = ${config.rtk.enabled}`);
|
|
295
|
+
if (config.rtk.init) {
|
|
296
|
+
lines.push('\n[rtk.init]');
|
|
297
|
+
if (config.rtk.init.claude_code !== undefined)
|
|
298
|
+
lines.push(`claude_code = ${config.rtk.init.claude_code}`);
|
|
299
|
+
if (config.rtk.init.codex_cli !== undefined)
|
|
300
|
+
lines.push(`codex_cli = ${config.rtk.init.codex_cli}`);
|
|
301
|
+
if (config.rtk.init.copilot !== undefined)
|
|
302
|
+
lines.push(`copilot = ${config.rtk.init.copilot}`);
|
|
303
|
+
if (config.rtk.init.opencode !== undefined)
|
|
304
|
+
lines.push(`opencode = ${config.rtk.init.opencode}`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// Tier0
|
|
308
|
+
if (config.tier0) {
|
|
309
|
+
lines.push('\n[tier0]');
|
|
310
|
+
if (config.tier0.check_enabled !== undefined)
|
|
311
|
+
lines.push(`check_enabled = ${config.tier0.check_enabled}`);
|
|
312
|
+
if (config.tier0.git_bash_path)
|
|
313
|
+
lines.push(`git_bash_path = ${tomlString(config.tier0.git_bash_path)}`);
|
|
314
|
+
}
|
|
315
|
+
// Generate
|
|
316
|
+
if (config.generate) {
|
|
317
|
+
lines.push('\n[generate]');
|
|
318
|
+
if (config.generate.marker_start)
|
|
319
|
+
lines.push(`marker_start = ${tomlString(config.generate.marker_start)}`);
|
|
320
|
+
if (config.generate.marker_end)
|
|
321
|
+
lines.push(`marker_end = ${tomlString(config.generate.marker_end)}`);
|
|
322
|
+
if (config.generate.files)
|
|
323
|
+
lines.push(`files = [${config.generate.files.map(tomlString).join(', ')}]`);
|
|
324
|
+
}
|
|
325
|
+
// Integrations
|
|
326
|
+
if (config.integrations?.superpowers) {
|
|
327
|
+
const superpowers = config.integrations.superpowers;
|
|
328
|
+
lines.push('\n[integrations.superpowers]');
|
|
329
|
+
if (superpowers.enabled !== undefined)
|
|
330
|
+
lines.push(`enabled = ${superpowers.enabled}`);
|
|
331
|
+
if (superpowers.source)
|
|
332
|
+
lines.push(`source = ${tomlString(superpowers.source)}`);
|
|
333
|
+
if (superpowers.ref)
|
|
334
|
+
lines.push(`ref = ${tomlString(superpowers.ref)}`);
|
|
335
|
+
if (superpowers.scope)
|
|
336
|
+
lines.push(`scope = ${tomlString(superpowers.scope)}`);
|
|
337
|
+
if (superpowers.agents)
|
|
338
|
+
lines.push(`agents = [${superpowers.agents.map(tomlString).join(', ')}]`);
|
|
339
|
+
if (superpowers.allow_hooks !== undefined)
|
|
340
|
+
lines.push(`allow_hooks = ${superpowers.allow_hooks}`);
|
|
341
|
+
if (superpowers.allow_external_requests !== undefined)
|
|
342
|
+
lines.push(`allow_external_requests = ${superpowers.allow_external_requests}`);
|
|
343
|
+
}
|
|
344
|
+
return lines.join('\n');
|
|
345
|
+
}
|
|
346
|
+
function tomlString(value) {
|
|
347
|
+
return JSON.stringify(value);
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Merge provided config with defaults (missing properties get default values)
|
|
351
|
+
*/
|
|
352
|
+
function mergeWithDefaults(config) {
|
|
353
|
+
const result = { ...DEFAULT_CONFIG };
|
|
354
|
+
// Merge scope
|
|
355
|
+
if (config.scope !== undefined) {
|
|
356
|
+
result.scope = config.scope;
|
|
357
|
+
}
|
|
358
|
+
// Merge agents
|
|
359
|
+
if (config.agents) {
|
|
360
|
+
result.agents = {
|
|
361
|
+
claude_code: config.agents.claude_code ?? DEFAULT_CONFIG.agents?.claude_code,
|
|
362
|
+
codex_cli: config.agents.codex_cli ?? DEFAULT_CONFIG.agents?.codex_cli,
|
|
363
|
+
copilot: config.agents.copilot ?? DEFAULT_CONFIG.agents?.copilot,
|
|
364
|
+
opencode: config.agents.opencode ?? DEFAULT_CONFIG.agents?.opencode,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
// Merge tools
|
|
368
|
+
if (config.tools) {
|
|
369
|
+
result.tools = {
|
|
370
|
+
ripgrep: config.tools.ripgrep ?? DEFAULT_CONFIG.tools?.ripgrep,
|
|
371
|
+
fd: config.tools.fd ?? DEFAULT_CONFIG.tools?.fd,
|
|
372
|
+
jq: config.tools.jq ?? DEFAULT_CONFIG.tools?.jq,
|
|
373
|
+
rtk: config.tools.rtk ?? DEFAULT_CONFIG.tools?.rtk,
|
|
374
|
+
ast_grep: config.tools.ast_grep ?? DEFAULT_CONFIG.tools?.ast_grep,
|
|
375
|
+
git_delta: config.tools.git_delta ?? DEFAULT_CONFIG.tools?.git_delta,
|
|
376
|
+
universal_ctags: config.tools.universal_ctags ?? DEFAULT_CONFIG.tools?.universal_ctags,
|
|
377
|
+
gh: config.tools.gh ?? DEFAULT_CONFIG.tools?.gh,
|
|
378
|
+
difftastic: config.tools.difftastic ?? DEFAULT_CONFIG.tools?.difftastic,
|
|
379
|
+
yq: config.tools.yq ?? DEFAULT_CONFIG.tools?.yq,
|
|
380
|
+
bat: config.tools.bat ?? DEFAULT_CONFIG.tools?.bat,
|
|
381
|
+
eza: config.tools.eza ?? DEFAULT_CONFIG.tools?.eza,
|
|
382
|
+
miller: config.tools.miller ?? DEFAULT_CONFIG.tools?.miller,
|
|
383
|
+
tokei: config.tools.tokei ?? DEFAULT_CONFIG.tools?.tokei,
|
|
384
|
+
hyperfine: config.tools.hyperfine ?? DEFAULT_CONFIG.tools?.hyperfine,
|
|
385
|
+
fzf: config.tools.fzf ?? DEFAULT_CONFIG.tools?.fzf,
|
|
386
|
+
just: config.tools.just ?? DEFAULT_CONFIG.tools?.just,
|
|
387
|
+
watchexec: config.tools.watchexec ?? DEFAULT_CONFIG.tools?.watchexec,
|
|
388
|
+
direnv: config.tools.direnv ?? DEFAULT_CONFIG.tools?.direnv,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
// Merge custom_tools
|
|
392
|
+
if (config.custom_tools) {
|
|
393
|
+
result.custom_tools = config.custom_tools;
|
|
394
|
+
}
|
|
395
|
+
// Merge rtk
|
|
396
|
+
if (config.rtk) {
|
|
397
|
+
result.rtk = {
|
|
398
|
+
enabled: config.rtk.enabled ?? DEFAULT_CONFIG.rtk?.enabled,
|
|
399
|
+
init: {
|
|
400
|
+
claude_code: config.rtk.init?.claude_code ?? DEFAULT_CONFIG.rtk?.init?.claude_code,
|
|
401
|
+
codex_cli: config.rtk.init?.codex_cli ?? DEFAULT_CONFIG.rtk?.init?.codex_cli,
|
|
402
|
+
copilot: config.rtk.init?.copilot ?? DEFAULT_CONFIG.rtk?.init?.copilot,
|
|
403
|
+
opencode: config.rtk.init?.opencode ?? DEFAULT_CONFIG.rtk?.init?.opencode,
|
|
404
|
+
},
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
// Merge tier0
|
|
408
|
+
if (config.tier0) {
|
|
409
|
+
result.tier0 = {
|
|
410
|
+
check_enabled: config.tier0.check_enabled ?? DEFAULT_CONFIG.tier0?.check_enabled,
|
|
411
|
+
git_bash_path: config.tier0.git_bash_path ?? DEFAULT_CONFIG.tier0?.git_bash_path,
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
// Merge generate
|
|
415
|
+
if (config.generate) {
|
|
416
|
+
result.generate = {
|
|
417
|
+
marker_start: config.generate.marker_start ?? DEFAULT_CONFIG.generate?.marker_start,
|
|
418
|
+
marker_end: config.generate.marker_end ?? DEFAULT_CONFIG.generate?.marker_end,
|
|
419
|
+
files: config.generate.files ?? DEFAULT_CONFIG.generate?.files,
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
// Merge integrations
|
|
423
|
+
if (config.integrations) {
|
|
424
|
+
result.integrations = {
|
|
425
|
+
superpowers: config.integrations.superpowers
|
|
426
|
+
? {
|
|
427
|
+
enabled: config.integrations.superpowers.enabled ??
|
|
428
|
+
DEFAULT_CONFIG.integrations?.superpowers?.enabled,
|
|
429
|
+
source: config.integrations.superpowers.source ??
|
|
430
|
+
DEFAULT_CONFIG.integrations?.superpowers?.source,
|
|
431
|
+
ref: config.integrations.superpowers.ref ?? DEFAULT_CONFIG.integrations?.superpowers?.ref,
|
|
432
|
+
scope: config.integrations.superpowers.scope ??
|
|
433
|
+
DEFAULT_CONFIG.integrations?.superpowers?.scope,
|
|
434
|
+
agents: config.integrations.superpowers.agents ??
|
|
435
|
+
DEFAULT_CONFIG.integrations?.superpowers?.agents,
|
|
436
|
+
allow_hooks: config.integrations.superpowers.allow_hooks ??
|
|
437
|
+
DEFAULT_CONFIG.integrations?.superpowers?.allow_hooks,
|
|
438
|
+
allow_external_requests: config.integrations.superpowers.allow_external_requests ??
|
|
439
|
+
DEFAULT_CONFIG.integrations?.superpowers?.allow_external_requests,
|
|
440
|
+
}
|
|
441
|
+
: DEFAULT_CONFIG.integrations?.superpowers,
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
// Merge advanced
|
|
445
|
+
if (config.advanced) {
|
|
446
|
+
result.advanced = {
|
|
447
|
+
default_mode: config.advanced.default_mode ?? DEFAULT_CONFIG.advanced?.default_mode,
|
|
448
|
+
show_diff_preview: config.advanced.show_diff_preview ?? DEFAULT_CONFIG.advanced?.show_diff_preview,
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
return result;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Get enabled agents from config
|
|
455
|
+
*/
|
|
456
|
+
export function getEnabledAgents(config) {
|
|
457
|
+
const agents = config.agents || DEFAULT_CONFIG.agents || {};
|
|
458
|
+
const enabled = [];
|
|
459
|
+
if (agents.claude_code)
|
|
460
|
+
enabled.push('claude_code');
|
|
461
|
+
if (agents.codex_cli)
|
|
462
|
+
enabled.push('codex_cli');
|
|
463
|
+
if (agents.copilot)
|
|
464
|
+
enabled.push('copilot');
|
|
465
|
+
if (agents.opencode)
|
|
466
|
+
enabled.push('opencode');
|
|
467
|
+
return enabled;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Normalize a config parsed from TOML into the canonical schema shape.
|
|
471
|
+
* Accepts the dotted `path.windows` / `version.windows` forms used in the
|
|
472
|
+
* docs example (§6.3) and flattens them to the `path_windows` keys the rest
|
|
473
|
+
* of the pipeline expects.
|
|
474
|
+
*/
|
|
475
|
+
function normalizeConfig(config) {
|
|
476
|
+
if (!Array.isArray(config.custom_tools)) {
|
|
477
|
+
return config;
|
|
478
|
+
}
|
|
479
|
+
const normalized = {
|
|
480
|
+
...config,
|
|
481
|
+
custom_tools: config.custom_tools.map((ct) => {
|
|
482
|
+
const result = { ...ct };
|
|
483
|
+
const paths = ct.path;
|
|
484
|
+
if (paths && typeof paths === 'object') {
|
|
485
|
+
if (paths.windows)
|
|
486
|
+
result.path_windows = paths.windows;
|
|
487
|
+
if (paths.macos)
|
|
488
|
+
result.path_macos = paths.macos;
|
|
489
|
+
if (paths.linux)
|
|
490
|
+
result.path_linux = paths.linux;
|
|
491
|
+
}
|
|
492
|
+
const versions = ct.version;
|
|
493
|
+
if (versions && typeof versions === 'object' && !Array.isArray(versions)) {
|
|
494
|
+
result.version = versions[process.platform];
|
|
495
|
+
}
|
|
496
|
+
return result;
|
|
497
|
+
}),
|
|
498
|
+
};
|
|
499
|
+
return normalized;
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Validate a config and report problems, separating hard errors from warnings.
|
|
503
|
+
* The CLI refuses to proceed when there are errors; warnings are surfaced but
|
|
504
|
+
* non-fatal (e.g. a catalog tool that mise cannot install from its registry).
|
|
505
|
+
*/
|
|
506
|
+
export function validateConfig(config) {
|
|
507
|
+
const errors = [];
|
|
508
|
+
const warnings = [];
|
|
509
|
+
if (config.scope !== undefined && config.scope !== 'project' && config.scope !== 'user') {
|
|
510
|
+
errors.push(`scope must be "project" or "user", got "${String(config.scope)}"`);
|
|
511
|
+
}
|
|
512
|
+
const agents = config.agents ?? {};
|
|
513
|
+
for (const key of Object.keys(agents)) {
|
|
514
|
+
if (!AGENT_KEYS.includes(key)) {
|
|
515
|
+
errors.push(`Unknown agent "${key}"`);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
const tools = (config.tools ?? {});
|
|
519
|
+
for (const key of Object.keys(tools)) {
|
|
520
|
+
if (!TOOL_KEYS.includes(key)) {
|
|
521
|
+
errors.push(`Unknown tool "${key}"`);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
if (Array.isArray(config.custom_tools)) {
|
|
525
|
+
for (const ct of config.custom_tools) {
|
|
526
|
+
if (!ct.name) {
|
|
527
|
+
errors.push('A custom tool entry is missing its "name"');
|
|
528
|
+
}
|
|
529
|
+
else if (ct.already_installed && !ct.path_windows && !ct.path_macos && !ct.path_linux) {
|
|
530
|
+
warnings.push(`custom tool "${ct.name}" is marked already_installed but has no OS path set`);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
// Tools Phase 0 flagged as not resolvable from the mise registry.
|
|
535
|
+
const registryGapNote = {
|
|
536
|
+
universal_ctags: 'not in the mise registry; add a custom_tools fallback',
|
|
537
|
+
tokei: 'not in the mise registry; add a custom_tools fallback or local toolchain',
|
|
538
|
+
};
|
|
539
|
+
for (const [tool, note] of Object.entries(registryGapNote)) {
|
|
540
|
+
if (tools[tool]) {
|
|
541
|
+
warnings.push(`${tool}: ${note}`);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
const integrations = (config.integrations ?? {});
|
|
545
|
+
for (const key of Object.keys(integrations)) {
|
|
546
|
+
if (!INTEGRATION_KEYS.includes(key)) {
|
|
547
|
+
errors.push(`Unknown integration "${key}"`);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
const superpowers = config.integrations?.superpowers;
|
|
551
|
+
if (superpowers) {
|
|
552
|
+
if (superpowers.scope !== undefined &&
|
|
553
|
+
superpowers.scope !== 'project' &&
|
|
554
|
+
superpowers.scope !== 'user') {
|
|
555
|
+
errors.push(`integrations.superpowers.scope must be "project" or "user", got "${String(superpowers.scope)}"`);
|
|
556
|
+
}
|
|
557
|
+
if (superpowers.agents) {
|
|
558
|
+
for (const agent of superpowers.agents) {
|
|
559
|
+
if (!AGENT_KEYS.includes(agent)) {
|
|
560
|
+
errors.push(`integrations.superpowers.agents contains unknown agent "${agent}"`);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
if (superpowers.source !== undefined && superpowers.source.trim() === '') {
|
|
565
|
+
errors.push('integrations.superpowers.source must not be empty');
|
|
566
|
+
}
|
|
567
|
+
if (superpowers.ref !== undefined) {
|
|
568
|
+
if (superpowers.ref.trim() === '') {
|
|
569
|
+
errors.push('integrations.superpowers.ref must not be empty');
|
|
570
|
+
}
|
|
571
|
+
else if (!/^[A-Za-z0-9._/-]+$/.test(superpowers.ref)) {
|
|
572
|
+
errors.push(`integrations.superpowers.ref "${superpowers.ref}" contains characters that are not valid in a git ref`);
|
|
573
|
+
}
|
|
574
|
+
else if (['main', 'master', 'HEAD'].includes(superpowers.ref)) {
|
|
575
|
+
warnings.push(`integrations.superpowers.ref "${superpowers.ref}" is a floating branch; pin to a tag or commit for reproducibility`);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
return { errors, warnings };
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Structurally diff two configs for the pre-write review in `agentenv
|
|
583
|
+
* configure` and for drift reporting in `agentenv status` (§6.5).
|
|
584
|
+
* Tools/agents flip toggles as added/removed; scalar settings as changed.
|
|
585
|
+
*/
|
|
586
|
+
export function diffConfigs(oldConfig, newConfig) {
|
|
587
|
+
const entries = [];
|
|
588
|
+
const oldAgents = oldConfig.agents ?? {};
|
|
589
|
+
const newAgents = newConfig.agents ?? {};
|
|
590
|
+
const oldTools = (oldConfig.tools ?? {});
|
|
591
|
+
const newTools = (newConfig.tools ?? {});
|
|
592
|
+
if (oldConfig.scope !== newConfig.scope) {
|
|
593
|
+
entries.push({
|
|
594
|
+
kind: 'changed',
|
|
595
|
+
key: 'scope',
|
|
596
|
+
oldValue: oldConfig.scope,
|
|
597
|
+
newValue: newConfig.scope,
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
for (const key of AGENT_KEYS) {
|
|
601
|
+
const oldValue = oldAgents[key] === true;
|
|
602
|
+
const newValue = newAgents[key] === true;
|
|
603
|
+
if (oldValue !== newValue) {
|
|
604
|
+
entries.push({
|
|
605
|
+
kind: newValue ? 'added' : 'removed',
|
|
606
|
+
key: `agents.${key}`,
|
|
607
|
+
oldValue: oldValue,
|
|
608
|
+
newValue: newValue,
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
for (const key of TOOL_KEYS) {
|
|
613
|
+
const oldValue = oldTools[key] === true;
|
|
614
|
+
const newValue = newTools[key] === true;
|
|
615
|
+
if (oldValue !== newValue) {
|
|
616
|
+
entries.push({
|
|
617
|
+
kind: newValue ? 'added' : 'removed',
|
|
618
|
+
key: `tools.${key}`,
|
|
619
|
+
oldValue: oldValue,
|
|
620
|
+
newValue: newValue,
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
diffCustomTools(oldConfig.custom_tools ?? [], newConfig.custom_tools ?? [], entries);
|
|
625
|
+
diffNestedSettings([
|
|
626
|
+
['rtk.enabled', oldConfig.rtk?.enabled, newConfig.rtk?.enabled],
|
|
627
|
+
['rtk.init.claude_code', oldConfig.rtk?.init?.claude_code, newConfig.rtk?.init?.claude_code],
|
|
628
|
+
['rtk.init.codex_cli', oldConfig.rtk?.init?.codex_cli, newConfig.rtk?.init?.codex_cli],
|
|
629
|
+
['rtk.init.copilot', oldConfig.rtk?.init?.copilot, newConfig.rtk?.init?.copilot],
|
|
630
|
+
['rtk.init.opencode', oldConfig.rtk?.init?.opencode, newConfig.rtk?.init?.opencode],
|
|
631
|
+
['tier0.check_enabled', oldConfig.tier0?.check_enabled, newConfig.tier0?.check_enabled],
|
|
632
|
+
['tier0.git_bash_path', oldConfig.tier0?.git_bash_path, newConfig.tier0?.git_bash_path],
|
|
633
|
+
['generate.marker_start', oldConfig.generate?.marker_start, newConfig.generate?.marker_start],
|
|
634
|
+
['generate.marker_end', oldConfig.generate?.marker_end, newConfig.generate?.marker_end],
|
|
635
|
+
['generate.files', jsonOr(oldConfig.generate?.files), jsonOr(newConfig.generate?.files)],
|
|
636
|
+
['advanced.default_mode', oldConfig.advanced?.default_mode, newConfig.advanced?.default_mode],
|
|
637
|
+
[
|
|
638
|
+
'advanced.show_diff_preview',
|
|
639
|
+
oldConfig.advanced?.show_diff_preview,
|
|
640
|
+
newConfig.advanced?.show_diff_preview,
|
|
641
|
+
],
|
|
642
|
+
[
|
|
643
|
+
'integrations.superpowers.enabled',
|
|
644
|
+
oldConfig.integrations?.superpowers?.enabled,
|
|
645
|
+
newConfig.integrations?.superpowers?.enabled,
|
|
646
|
+
],
|
|
647
|
+
[
|
|
648
|
+
'integrations.superpowers.source',
|
|
649
|
+
oldConfig.integrations?.superpowers?.source,
|
|
650
|
+
newConfig.integrations?.superpowers?.source,
|
|
651
|
+
],
|
|
652
|
+
[
|
|
653
|
+
'integrations.superpowers.ref',
|
|
654
|
+
oldConfig.integrations?.superpowers?.ref,
|
|
655
|
+
newConfig.integrations?.superpowers?.ref,
|
|
656
|
+
],
|
|
657
|
+
[
|
|
658
|
+
'integrations.superpowers.scope',
|
|
659
|
+
oldConfig.integrations?.superpowers?.scope,
|
|
660
|
+
newConfig.integrations?.superpowers?.scope,
|
|
661
|
+
],
|
|
662
|
+
[
|
|
663
|
+
'integrations.superpowers.agents',
|
|
664
|
+
jsonOr(oldConfig.integrations?.superpowers?.agents),
|
|
665
|
+
jsonOr(newConfig.integrations?.superpowers?.agents),
|
|
666
|
+
],
|
|
667
|
+
[
|
|
668
|
+
'integrations.superpowers.allow_hooks',
|
|
669
|
+
oldConfig.integrations?.superpowers?.allow_hooks,
|
|
670
|
+
newConfig.integrations?.superpowers?.allow_hooks,
|
|
671
|
+
],
|
|
672
|
+
[
|
|
673
|
+
'integrations.superpowers.allow_external_requests',
|
|
674
|
+
oldConfig.integrations?.superpowers?.allow_external_requests,
|
|
675
|
+
newConfig.integrations?.superpowers?.allow_external_requests,
|
|
676
|
+
],
|
|
677
|
+
], entries);
|
|
678
|
+
return entries;
|
|
679
|
+
}
|
|
680
|
+
function diffCustomTools(oldTools, newTools, entries) {
|
|
681
|
+
const byName = (tools) => new Map(tools.map((tool) => [tool.name, tool]));
|
|
682
|
+
const oldByName = byName(oldTools);
|
|
683
|
+
const newByName = byName(newTools);
|
|
684
|
+
for (const [name, oldTool] of oldByName) {
|
|
685
|
+
if (!newByName.has(name)) {
|
|
686
|
+
entries.push({ kind: 'removed', key: `custom_tools.${name}`, oldValue: oldTool });
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
for (const [name, newTool] of newByName) {
|
|
690
|
+
if (!oldByName.has(name)) {
|
|
691
|
+
entries.push({ kind: 'added', key: `custom_tools.${name}`, newValue: newTool });
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
for (const [name, oldTool] of oldByName) {
|
|
695
|
+
if (!newByName.has(name))
|
|
696
|
+
continue;
|
|
697
|
+
const newTool = newByName.get(name);
|
|
698
|
+
const fields = [
|
|
699
|
+
['description', oldTool.description, newTool.description],
|
|
700
|
+
['already_installed', oldTool.already_installed, newTool.already_installed],
|
|
701
|
+
['mise_source', oldTool.mise_source, newTool.mise_source],
|
|
702
|
+
['version', oldTool.version, newTool.version],
|
|
703
|
+
['path_windows', oldTool.path_windows, newTool.path_windows],
|
|
704
|
+
['path_macos', oldTool.path_macos, newTool.path_macos],
|
|
705
|
+
['path_linux', oldTool.path_linux, newTool.path_linux],
|
|
706
|
+
];
|
|
707
|
+
for (const [field, oldValue, newValue] of fields) {
|
|
708
|
+
if (oldValue !== newValue) {
|
|
709
|
+
entries.push({
|
|
710
|
+
kind: 'changed',
|
|
711
|
+
key: `custom_tools.${name}.${field}`,
|
|
712
|
+
oldValue,
|
|
713
|
+
newValue,
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
function jsonOr(value) {
|
|
720
|
+
return value === undefined ? undefined : JSON.stringify(value);
|
|
721
|
+
}
|
|
722
|
+
function diffNestedSettings(pairs, entries) {
|
|
723
|
+
for (const [key, oldValue, newValue] of pairs) {
|
|
724
|
+
if (oldValue !== newValue) {
|
|
725
|
+
entries.push({ kind: 'changed', key, oldValue, newValue });
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* Get enabled tools from config
|
|
731
|
+
*/
|
|
732
|
+
export function getEnabledTools(config) {
|
|
733
|
+
const tools = config.tools || DEFAULT_CONFIG.tools || {};
|
|
734
|
+
const enabled = [];
|
|
735
|
+
const toolKeys = [
|
|
736
|
+
'ripgrep',
|
|
737
|
+
'fd',
|
|
738
|
+
'jq',
|
|
739
|
+
'rtk',
|
|
740
|
+
'ast_grep',
|
|
741
|
+
'git_delta',
|
|
742
|
+
'universal_ctags',
|
|
743
|
+
'gh',
|
|
744
|
+
'difftastic',
|
|
745
|
+
'yq',
|
|
746
|
+
'bat',
|
|
747
|
+
'eza',
|
|
748
|
+
'miller',
|
|
749
|
+
'tokei',
|
|
750
|
+
'hyperfine',
|
|
751
|
+
'fzf',
|
|
752
|
+
'just',
|
|
753
|
+
'watchexec',
|
|
754
|
+
'direnv',
|
|
755
|
+
];
|
|
756
|
+
for (const key of toolKeys) {
|
|
757
|
+
if (tools[key]) {
|
|
758
|
+
enabled.push(key);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
// Add custom tools
|
|
762
|
+
if (config.custom_tools) {
|
|
763
|
+
for (const ct of config.custom_tools) {
|
|
764
|
+
if (ct.already_installed || ct.mise_source) {
|
|
765
|
+
enabled.push(ct.name);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
return enabled;
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Resolve the effective scope for an integration: its own `scope` field when
|
|
773
|
+
* set, otherwise the agentenv-level scope, defaulting to "project".
|
|
774
|
+
*/
|
|
775
|
+
export function resolveIntegrationScope(config, integration) {
|
|
776
|
+
return integration?.scope ?? config.scope ?? 'project';
|
|
777
|
+
}
|
|
778
|
+
//# sourceMappingURL=schema.js.map
|