@indy2kro/agentenv 0.4.1 → 1.0.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/README.md +1 -2
- package/dist/adapters/base.d.ts +9 -6
- package/dist/adapters/base.d.ts.map +1 -1
- package/dist/adapters/base.js +12 -0
- package/dist/adapters/base.js.map +1 -1
- package/dist/adapters/claude.d.ts +1 -0
- package/dist/adapters/claude.d.ts.map +1 -1
- package/dist/adapters/claude.js +5 -2
- package/dist/adapters/claude.js.map +1 -1
- package/dist/adapters/codex.d.ts.map +1 -1
- package/dist/adapters/codex.js +2 -1
- package/dist/adapters/codex.js.map +1 -1
- package/dist/adapters/copilot.d.ts +1 -0
- package/dist/adapters/copilot.d.ts.map +1 -1
- package/dist/adapters/copilot.js +4 -0
- package/dist/adapters/copilot.js.map +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/commands/apply.d.ts +8 -0
- package/dist/commands/apply.d.ts.map +1 -1
- package/dist/commands/apply.js +36 -9
- package/dist/commands/apply.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +18 -2
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/shell-fix.d.ts.map +1 -1
- package/dist/commands/shell-fix.js +2 -1
- package/dist/commands/shell-fix.js.map +1 -1
- package/dist/commands/status.js +1 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +2 -1
- package/dist/commands/update.js.map +1 -1
- package/dist/config/schema.d.ts +0 -4
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +19 -41
- package/dist/config/schema.js.map +1 -1
- package/dist/generate/agentsmd.d.ts +9 -1
- package/dist/generate/agentsmd.d.ts.map +1 -1
- package/dist/generate/agentsmd.js +24 -15
- package/dist/generate/agentsmd.js.map +1 -1
- package/dist/integrations/superpowers.d.ts.map +1 -1
- package/dist/integrations/superpowers.js +6 -1
- package/dist/integrations/superpowers.js.map +1 -1
- package/dist/shell/detector.d.ts +1 -1
- package/dist/shell/detector.d.ts.map +1 -1
- package/dist/shell/detector.js +53 -18
- package/dist/shell/detector.js.map +1 -1
- package/dist/shell/shell-fix-state.d.ts +9 -1
- package/dist/shell/shell-fix-state.d.ts.map +1 -1
- package/dist/shell/shell-fix-state.js.map +1 -1
- package/dist/toolchain/fallbacks.d.ts +7 -65
- package/dist/toolchain/fallbacks.d.ts.map +1 -1
- package/dist/toolchain/fallbacks.js +7 -210
- package/dist/toolchain/fallbacks.js.map +1 -1
- package/dist/toolchain/mise.d.ts +23 -19
- package/dist/toolchain/mise.d.ts.map +1 -1
- package/dist/toolchain/mise.js +92 -133
- package/dist/toolchain/mise.js.map +1 -1
- package/dist/ui/output.d.ts +1 -3
- package/dist/ui/output.d.ts.map +1 -1
- package/dist/ui/output.js +1 -7
- package/dist/ui/output.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,38 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Toolchain Fallbacks
|
|
3
|
+
* Marks tools that cannot be installed via mise (tokei) and tools whose only
|
|
4
|
+
* mise backend refuses to resolve on certain platforms, as documented in
|
|
5
|
+
* phase0-windows-findings.md. The old per-platform install/verify/advice
|
|
6
|
+
* helpers were dead public surface and were removed — tool installation is
|
|
7
|
+
* delegated to mise or handled through `[[custom_tools]]`.
|
|
5
8
|
*/
|
|
6
|
-
import * as child_process from 'child_process';
|
|
7
|
-
/**
|
|
8
|
-
* Fallback tools that cannot be installed via mise
|
|
9
|
-
* Based on Phase 0 findings:
|
|
10
|
-
* - tokei: aqua:XAMPPRocky/tokei doesn't work, needs cargo:tokei (requires Rust)
|
|
11
|
-
*/
|
|
12
|
-
export const FALLBACK_TOOLS = {
|
|
13
|
-
tokei: {
|
|
14
|
-
name: 'tokei',
|
|
15
|
-
description: 'Fast LOC/code-statistics tool',
|
|
16
|
-
install: {
|
|
17
|
-
macos: ['brew install --quiet tokei'],
|
|
18
|
-
linux: ['cargo install --quiet tokei', 'sudo apt-get install -y tokei'],
|
|
19
|
-
windows: ['cargo install --quiet tokei', 'choco install tokei'],
|
|
20
|
-
},
|
|
21
|
-
verify: {
|
|
22
|
-
macos: ['command -v tokei', 'tokei --version'],
|
|
23
|
-
linux: ['command -v tokei', 'tokei --version'],
|
|
24
|
-
windows: ['where tokei', 'tokei --version'],
|
|
25
|
-
},
|
|
26
|
-
paths: {
|
|
27
|
-
macos: '/usr/local/bin/tokei',
|
|
28
|
-
linux: '~/.cargo/bin/tokei',
|
|
29
|
-
windows: '%USERPROFILE%\\.cargo\\bin\\tokei.exe',
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
9
|
/**
|
|
34
10
|
* Tools that have special installation requirements
|
|
35
|
-
* These are marked as "Fallback required" in phase0-findings.md
|
|
11
|
+
* These are marked as "Fallback required" in phase0-windows-findings.md
|
|
36
12
|
*/
|
|
37
13
|
export const FALLBACK_REQUIRED_TOOLS = ['tokei'];
|
|
38
14
|
/**
|
|
@@ -57,183 +33,4 @@ export const PLATFORM_UNSUPPORTED_TOOLS = {
|
|
|
57
33
|
export function isPlatformUnsupported(toolName, platform = process.platform) {
|
|
58
34
|
return PLATFORM_UNSUPPORTED_TOOLS[toolName]?.includes(platform) ?? false;
|
|
59
35
|
}
|
|
60
|
-
/**
|
|
61
|
-
* Get the platform-specific installation command for a fallback tool
|
|
62
|
-
*/
|
|
63
|
-
export function getInstallCommand(toolName) {
|
|
64
|
-
const platform = process.platform;
|
|
65
|
-
const fallbackTool = FALLBACK_TOOLS[toolName];
|
|
66
|
-
if (!fallbackTool) {
|
|
67
|
-
return undefined;
|
|
68
|
-
}
|
|
69
|
-
if (platform === 'darwin') {
|
|
70
|
-
return fallbackTool.install.macos;
|
|
71
|
-
}
|
|
72
|
-
else if (platform === 'linux') {
|
|
73
|
-
return fallbackTool.install.linux;
|
|
74
|
-
}
|
|
75
|
-
else if (platform === 'win32') {
|
|
76
|
-
return fallbackTool.install.windows;
|
|
77
|
-
}
|
|
78
|
-
return undefined;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Get the platform-specific verification command for a fallback tool
|
|
82
|
-
*/
|
|
83
|
-
export function getVerifyCommand(toolName) {
|
|
84
|
-
const platform = process.platform;
|
|
85
|
-
const fallbackTool = FALLBACK_TOOLS[toolName];
|
|
86
|
-
if (!fallbackTool) {
|
|
87
|
-
return undefined;
|
|
88
|
-
}
|
|
89
|
-
if (platform === 'darwin') {
|
|
90
|
-
return fallbackTool.verify.macos;
|
|
91
|
-
}
|
|
92
|
-
else if (platform === 'linux') {
|
|
93
|
-
return fallbackTool.verify.linux;
|
|
94
|
-
}
|
|
95
|
-
else if (platform === 'win32') {
|
|
96
|
-
return fallbackTool.verify.windows;
|
|
97
|
-
}
|
|
98
|
-
return undefined;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Check if a fallback tool is installed on the current platform
|
|
102
|
-
*/
|
|
103
|
-
export function isFallbackToolInstalled(toolName) {
|
|
104
|
-
const verifyCommands = getVerifyCommand(toolName);
|
|
105
|
-
if (!verifyCommands || verifyCommands.length === 0) {
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
try {
|
|
109
|
-
// Try each verification command until one succeeds
|
|
110
|
-
for (const cmd of verifyCommands) {
|
|
111
|
-
const shell = process.platform === 'win32' ? 'cmd.exe' : 'sh';
|
|
112
|
-
const shellArgs = process.platform === 'win32' ? ['/c', cmd] : ['-c', cmd];
|
|
113
|
-
const result = child_process.spawnSync(shell, shellArgs, { stdio: 'ignore', shell: true });
|
|
114
|
-
if (result.status === 0)
|
|
115
|
-
return true;
|
|
116
|
-
}
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
catch {
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Install a fallback tool on the current platform
|
|
125
|
-
* Returns success status and any error message
|
|
126
|
-
*/
|
|
127
|
-
export function installFallbackTool(toolName) {
|
|
128
|
-
const installCommands = getInstallCommand(toolName);
|
|
129
|
-
if (!installCommands || installCommands.length === 0) {
|
|
130
|
-
return {
|
|
131
|
-
success: false,
|
|
132
|
-
message: `No installation commands defined for ${toolName} on ${process.platform}`,
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
const fallbackTool = FALLBACK_TOOLS[toolName];
|
|
136
|
-
try {
|
|
137
|
-
// Try each installation command until one succeeds
|
|
138
|
-
for (const cmd of installCommands) {
|
|
139
|
-
try {
|
|
140
|
-
const shell = process.platform === 'win32' ? 'cmd.exe' : 'sh';
|
|
141
|
-
const shellArgs = process.platform === 'win32' ? ['/c', cmd] : ['-c', cmd];
|
|
142
|
-
child_process.spawnSync(shell, shellArgs, { stdio: 'inherit', shell: true });
|
|
143
|
-
// Verify installation was successful
|
|
144
|
-
if (isFallbackToolInstalled(toolName)) {
|
|
145
|
-
return {
|
|
146
|
-
success: true,
|
|
147
|
-
message: `Successfully installed ${fallbackTool?.description || toolName} via: ${cmd}`,
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
catch {
|
|
152
|
-
// Try the next command
|
|
153
|
-
continue;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return {
|
|
157
|
-
success: false,
|
|
158
|
-
message: `Failed to install ${fallbackTool?.description || toolName}. Tried all available installation methods.`,
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
catch (err) {
|
|
162
|
-
return {
|
|
163
|
-
success: false,
|
|
164
|
-
message: `Error installing ${fallbackTool?.description || toolName}: ${err}`,
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Get the expected path for a fallback tool on the current platform
|
|
170
|
-
*/
|
|
171
|
-
export function getFallbackToolPath(toolName) {
|
|
172
|
-
const platform = process.platform;
|
|
173
|
-
const fallbackTool = FALLBACK_TOOLS[toolName];
|
|
174
|
-
if (!fallbackTool || !fallbackTool.paths) {
|
|
175
|
-
return undefined;
|
|
176
|
-
}
|
|
177
|
-
if (platform === 'darwin' && fallbackTool.paths.macos) {
|
|
178
|
-
return fallbackTool.paths.macos;
|
|
179
|
-
}
|
|
180
|
-
else if (platform === 'linux' && fallbackTool.paths.linux) {
|
|
181
|
-
return fallbackTool.paths.linux;
|
|
182
|
-
}
|
|
183
|
-
else if (platform === 'win32' && fallbackTool.paths.windows) {
|
|
184
|
-
return fallbackTool.paths.windows;
|
|
185
|
-
}
|
|
186
|
-
return undefined;
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Generate platform-specific advice for installing a fallback tool
|
|
190
|
-
*/
|
|
191
|
-
export function getFallbackInstallationAdvice(toolName) {
|
|
192
|
-
const platform = process.platform;
|
|
193
|
-
const fallbackTool = FALLBACK_TOOLS[toolName];
|
|
194
|
-
if (!fallbackTool) {
|
|
195
|
-
return `Tool ${toolName} requires manual installation. Please install it according to your platform's package manager.`;
|
|
196
|
-
}
|
|
197
|
-
const installCommands = getInstallCommand(toolName);
|
|
198
|
-
if (platform === 'darwin') {
|
|
199
|
-
return `To install ${fallbackTool.description} on macOS, run: ${installCommands?.join(' or ')}`;
|
|
200
|
-
}
|
|
201
|
-
else if (platform === 'linux') {
|
|
202
|
-
return `To install ${fallbackTool.description} on Linux, run: ${installCommands?.join(' or ')}`;
|
|
203
|
-
}
|
|
204
|
-
else if (platform === 'win32') {
|
|
205
|
-
return `To install ${fallbackTool.description} on Windows, run: ${installCommands?.join(' or ')}`;
|
|
206
|
-
}
|
|
207
|
-
return `Tool ${toolName} requires manual installation.`;
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Generate custom tool configuration for fallback tools
|
|
211
|
-
* This can be used when generating agentenv.toml for tools that need fallbacks
|
|
212
|
-
*/
|
|
213
|
-
export function generateFallbackCustomToolConfig(toolName) {
|
|
214
|
-
const fallbackTool = FALLBACK_TOOLS[toolName];
|
|
215
|
-
if (!fallbackTool) {
|
|
216
|
-
return '';
|
|
217
|
-
}
|
|
218
|
-
const lines = [];
|
|
219
|
-
lines.push(`# ${fallbackTool.description}`);
|
|
220
|
-
lines.push(`# Platform-specific fallback installation required`);
|
|
221
|
-
lines.push(`# macOS: ${fallbackTool.install.macos.join(' or ')}`);
|
|
222
|
-
lines.push(`# Linux: ${fallbackTool.install.linux.join(' or ')}`);
|
|
223
|
-
lines.push(`# Windows: ${fallbackTool.install.windows.join(' or ')}`);
|
|
224
|
-
lines.push(`[[custom_tools]]`);
|
|
225
|
-
lines.push(`name = "${toolName}"`);
|
|
226
|
-
lines.push(`description = "${fallbackTool.description}"`);
|
|
227
|
-
lines.push(`already_installed = true`);
|
|
228
|
-
if (fallbackTool.paths.macos) {
|
|
229
|
-
lines.push(`path.macos = "${fallbackTool.paths.macos}"`);
|
|
230
|
-
}
|
|
231
|
-
if (fallbackTool.paths.linux) {
|
|
232
|
-
lines.push(`path.linux = "${fallbackTool.paths.linux}"`);
|
|
233
|
-
}
|
|
234
|
-
if (fallbackTool.paths.windows) {
|
|
235
|
-
lines.push(`path.windows = "${fallbackTool.paths.windows}"`);
|
|
236
|
-
}
|
|
237
|
-
return lines.join('\n');
|
|
238
|
-
}
|
|
239
36
|
//# sourceMappingURL=fallbacks.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fallbacks.js","sourceRoot":"","sources":["../../src/toolchain/fallbacks.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"fallbacks.js","sourceRoot":"","sources":["../../src/toolchain/fallbacks.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,OAAO,CAAC,CAAC;AAEjD;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,OAAO,uBAAuB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAsC;IAC3E,WAAW,EAAE,CAAC,OAAO,CAAC;IACtB,KAAK,EAAE,CAAC,OAAO,CAAC;CACjB,CAAC;AAEF,0EAA0E;AAC1E,MAAM,UAAU,qBAAqB,CACnC,QAAgB,EAChB,WAA4B,OAAO,CAAC,QAAQ;IAE5C,OAAO,0BAA0B,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC;AAC3E,CAAC"}
|
package/dist/toolchain/mise.d.ts
CHANGED
|
@@ -13,16 +13,14 @@ export interface MiseTool {
|
|
|
13
13
|
tier: number;
|
|
14
14
|
category: string;
|
|
15
15
|
}
|
|
16
|
-
export interface MiseConfig {
|
|
17
|
-
tools: Record<string, string>;
|
|
18
|
-
env?: Record<string, string>;
|
|
19
|
-
settings?: Record<string, any>;
|
|
20
|
-
}
|
|
21
16
|
/**
|
|
22
17
|
* Tools agentenv invokes directly are pinned to versions we have verified;
|
|
23
18
|
* everything else resolves to latest. rtk is invoked by agentenv's delegation
|
|
24
19
|
* (its `init` flags are the hook contract), moves fast, and must stay pinned —
|
|
25
|
-
* bump deliberately per plan §10.
|
|
20
|
+
* bump deliberately per plan §10. A catalog tool is also pinned when its
|
|
21
|
+
* `latest` release is currently broken upstream (mise's aqua backend cannot
|
|
22
|
+
* install it), so the generated mise.toml ships a known-good version instead
|
|
23
|
+
* of reproducing the upstream failure on every user machine.
|
|
26
24
|
*/
|
|
27
25
|
export declare const PINNED_TOOL_VERSIONS: Record<string, string>;
|
|
28
26
|
/**
|
|
@@ -77,11 +75,25 @@ export declare function upsertShimsDir(content: string, dir: string): string;
|
|
|
77
75
|
* config, or null when it is absent. Used by `agentenv doctor`.
|
|
78
76
|
*/
|
|
79
77
|
export declare function getShimsDirValue(content: string): string | null;
|
|
78
|
+
/**
|
|
79
|
+
* Remove the `shims_dir` line that upsertShimsDir writes and, if that leaves
|
|
80
|
+
* the `[settings]` section with no other keys, the section header too ("other
|
|
81
|
+
* keys" means any non-empty line between the header and the next section).
|
|
82
|
+
* Returns the content unchanged when no `shims_dir` line is present. Surgical
|
|
83
|
+
* counterpart to upsertShimsDir, used by `shell-fix --revert`.
|
|
84
|
+
*/
|
|
85
|
+
export declare function removeShimsDirValue(content: string): string;
|
|
80
86
|
/**
|
|
81
87
|
* Ensure mise's GLOBAL config declares the shims_dir agentenv relies on, and
|
|
82
88
|
* tell the user whether the shims dir is actually on PATH. Idempotent.
|
|
89
|
+
*
|
|
90
|
+
* When `statePath` is given, a change made here is recorded in the shell-fix
|
|
91
|
+
* manifest (agent `mise`) so `agentenv shell-fix --revert` can undo it. The
|
|
92
|
+
* existing manifest's bashExe is preserved when merging so a Tier 0 entry and
|
|
93
|
+
* the mise entry coexist in one apply run without clobbering each other's
|
|
94
|
+
* revert comparison value.
|
|
83
95
|
*/
|
|
84
|
-
export declare function ensureGlobalShimsDir(): {
|
|
96
|
+
export declare function ensureGlobalShimsDir(statePath?: string): {
|
|
85
97
|
success: boolean;
|
|
86
98
|
message: string;
|
|
87
99
|
};
|
|
@@ -169,7 +181,6 @@ export interface MiseCapturedOutput {
|
|
|
169
181
|
status: number | null;
|
|
170
182
|
stdout: string;
|
|
171
183
|
stderr: string;
|
|
172
|
-
blockedWarn: boolean;
|
|
173
184
|
}
|
|
174
185
|
/**
|
|
175
186
|
* Run a single mise command with args passed as an array (never a
|
|
@@ -190,8 +201,6 @@ export declare function isMiseInstalled(): boolean;
|
|
|
190
201
|
* installed version, so it is dropped here).
|
|
191
202
|
*/
|
|
192
203
|
export declare function getMiseVersion(): string;
|
|
193
|
-
/** Alias used by prereq/status/doctor so version probes never surface mise WARN. */
|
|
194
|
-
export declare function getMiseVersionSilent(): string;
|
|
195
204
|
/**
|
|
196
205
|
* Check if a specific tool is installed via mise
|
|
197
206
|
*/
|
|
@@ -276,6 +285,10 @@ export interface VerifyToolOptions {
|
|
|
276
285
|
/** cwd / mise.toml for the lazy `mise ls --json` probe (scope-aware). */
|
|
277
286
|
cwd?: string;
|
|
278
287
|
miseTomlPath?: string;
|
|
288
|
+
/** Injectable PATH resolver; defaults to the real `resolveBinary`. */
|
|
289
|
+
resolveFn?: (binary: string) => string | null;
|
|
290
|
+
/** Injectable shim check; defaults to the real `shimExists`. */
|
|
291
|
+
shimCheck?: (binary: string) => boolean;
|
|
279
292
|
}
|
|
280
293
|
/**
|
|
281
294
|
* After `mise install`, check which enabled tools actually resolve on PATH so
|
|
@@ -382,13 +395,4 @@ export declare function parseInstalledToolState(raw: string): Record<string, Ins
|
|
|
382
395
|
* output (or an absent mise) yields an empty map rather than `null`.
|
|
383
396
|
*/
|
|
384
397
|
export declare function getInstalledToolState(raw?: string, opts?: RunMiseCapturedOptions): Record<string, InstalledToolState>;
|
|
385
|
-
/**
|
|
386
|
-
* Parse existing mise.toml file
|
|
387
|
-
*/
|
|
388
|
-
export declare function parseMiseToml(filePath: string): MiseConfig | null;
|
|
389
|
-
/**
|
|
390
|
-
* Merge existing mise.toml with new tools
|
|
391
|
-
* Preserves existing tools that are not in the new config
|
|
392
|
-
*/
|
|
393
|
-
export declare function mergeMiseConfigs(existing: MiseConfig | null, newConfig: MiseConfig): MiseConfig;
|
|
394
398
|
//# sourceMappingURL=mise.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mise.d.ts","sourceRoot":"","sources":["../../src/toolchain/mise.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,cAAc,EAAqC,MAAM,qBAAqB,CAAC;AAGxF,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"mise.d.ts","sourceRoot":"","sources":["../../src/toolchain/mise.ts"],"names":[],"mappings":"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"}
|
package/dist/toolchain/mise.js
CHANGED
|
@@ -10,6 +10,7 @@ import { BINARY_MAP, TOOL_KEYS, TOOL_TIERS } from '../config/schema.js';
|
|
|
10
10
|
import { resolveBinary } from '../adapters/detect.js';
|
|
11
11
|
import { writeFileWithVerify } from '../utils/fs-retry.js';
|
|
12
12
|
import { FALLBACK_REQUIRED_TOOLS, isPlatformUnsupported, requiresFallback } from './fallbacks.js';
|
|
13
|
+
import { mergeShellFixEntries, readShellFixState, writeShellFixState, } from '../shell/shell-fix-state.js';
|
|
13
14
|
// Tool to mise name mappings
|
|
14
15
|
export const MISE_TOOL_NAMES = {
|
|
15
16
|
ripgrep: 'ripgrep',
|
|
@@ -53,10 +54,20 @@ export { FALLBACK_REQUIRED_TOOLS, isPlatformUnsupported, requiresFallback };
|
|
|
53
54
|
* Tools agentenv invokes directly are pinned to versions we have verified;
|
|
54
55
|
* everything else resolves to latest. rtk is invoked by agentenv's delegation
|
|
55
56
|
* (its `init` flags are the hook contract), moves fast, and must stay pinned —
|
|
56
|
-
* bump deliberately per plan §10.
|
|
57
|
+
* bump deliberately per plan §10. A catalog tool is also pinned when its
|
|
58
|
+
* `latest` release is currently broken upstream (mise's aqua backend cannot
|
|
59
|
+
* install it), so the generated mise.toml ships a known-good version instead
|
|
60
|
+
* of reproducing the upstream failure on every user machine.
|
|
57
61
|
*/
|
|
58
62
|
export const PINNED_TOOL_VERSIONS = {
|
|
59
63
|
rtk: '0.49.0',
|
|
64
|
+
// difftastic 0.71.0+ renamed its release assets to `difft-<version>-…`
|
|
65
|
+
// (unversioned before), which the aqua registry's asset template does not
|
|
66
|
+
// match on any platform — `mise install` fails with "no asset found:
|
|
67
|
+
// difft-x86_64-unknown-linux-musl.tar.gz". 0.70.0 is the last verified
|
|
68
|
+
// installable release (phase0 research docs). Unpin when upstream fixes
|
|
69
|
+
// the asset naming or mise resolves it for us.
|
|
70
|
+
difftastic: '0.70.0',
|
|
60
71
|
};
|
|
61
72
|
/**
|
|
62
73
|
* Generate mise.toml content from agentenv config
|
|
@@ -219,19 +230,64 @@ export function getShimsDirValue(content) {
|
|
|
219
230
|
}
|
|
220
231
|
return null;
|
|
221
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Remove the `shims_dir` line that upsertShimsDir writes and, if that leaves
|
|
235
|
+
* the `[settings]` section with no other keys, the section header too ("other
|
|
236
|
+
* keys" means any non-empty line between the header and the next section).
|
|
237
|
+
* Returns the content unchanged when no `shims_dir` line is present. Surgical
|
|
238
|
+
* counterpart to upsertShimsDir, used by `shell-fix --revert`.
|
|
239
|
+
*/
|
|
240
|
+
export function removeShimsDirValue(content) {
|
|
241
|
+
const lines = content.split(/\r?\n/);
|
|
242
|
+
const shimsIdx = lines.findIndex((line) => /^\s*shims_dir\s*=/.test(line.trim()));
|
|
243
|
+
if (shimsIdx === -1)
|
|
244
|
+
return content;
|
|
245
|
+
lines.splice(shimsIdx, 1);
|
|
246
|
+
const headerIdx = lines.findIndex((line) => /^\s*\[settings\]\s*$/.test(line.trim()));
|
|
247
|
+
if (headerIdx !== -1) {
|
|
248
|
+
let empty = true;
|
|
249
|
+
for (let i = headerIdx + 1; i < lines.length; i++) {
|
|
250
|
+
const trimmed = lines[i].trim();
|
|
251
|
+
if (/^\s*\[.*\]$/.test(trimmed))
|
|
252
|
+
break;
|
|
253
|
+
if (trimmed !== '') {
|
|
254
|
+
empty = false;
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (empty) {
|
|
259
|
+
lines.splice(headerIdx, 1);
|
|
260
|
+
if (lines[headerIdx]?.trim() === '')
|
|
261
|
+
lines.splice(headerIdx, 1);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === '')
|
|
265
|
+
lines.pop();
|
|
266
|
+
return lines.length > 0 ? `${lines.join('\n')}\n` : '';
|
|
267
|
+
}
|
|
222
268
|
/**
|
|
223
269
|
* Ensure mise's GLOBAL config declares the shims_dir agentenv relies on, and
|
|
224
270
|
* tell the user whether the shims dir is actually on PATH. Idempotent.
|
|
271
|
+
*
|
|
272
|
+
* When `statePath` is given, a change made here is recorded in the shell-fix
|
|
273
|
+
* manifest (agent `mise`) so `agentenv shell-fix --revert` can undo it. The
|
|
274
|
+
* existing manifest's bashExe is preserved when merging so a Tier 0 entry and
|
|
275
|
+
* the mise entry coexist in one apply run without clobbering each other's
|
|
276
|
+
* revert comparison value.
|
|
225
277
|
*/
|
|
226
|
-
export function ensureGlobalShimsDir() {
|
|
278
|
+
export function ensureGlobalShimsDir(statePath) {
|
|
227
279
|
const dir = shimsDir();
|
|
228
280
|
const configPath = miseGlobalConfigPath();
|
|
229
281
|
try {
|
|
230
282
|
fs.mkdirSync(miseGlobalConfigDir(), { recursive: true });
|
|
231
283
|
const existing = fs.existsSync(configPath) ? fs.readFileSync(configPath, 'utf-8') : '';
|
|
232
284
|
const updated = upsertShimsDir(existing, dir);
|
|
233
|
-
if (updated !== existing)
|
|
285
|
+
if (updated !== existing) {
|
|
234
286
|
fs.writeFileSync(configPath, updated);
|
|
287
|
+
if (statePath) {
|
|
288
|
+
recordShimsDirState(configPath, existing, tomlPath(dir), statePath);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
235
291
|
const pathLine = shimsDirOnPath()
|
|
236
292
|
? `${dir} is on PATH`
|
|
237
293
|
: `Add ${dir} to PATH so the shims resolve (Windows: System Properties > Environment Variables > Path)`;
|
|
@@ -257,6 +313,28 @@ export function ensureGlobalShimsDir() {
|
|
|
257
313
|
function tomlPath(p) {
|
|
258
314
|
return p.replace(/\\/g, '/');
|
|
259
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* Record a mise shims_dir write in the shell-fix manifest, preserving the
|
|
318
|
+
* existing manifest's bashExe so Tier 0 entries keep comparing against the
|
|
319
|
+
* git-bash path they were written with. Advisory: a recording failure must
|
|
320
|
+
* never fail the (already-successful) shims config itself.
|
|
321
|
+
*/
|
|
322
|
+
function recordShimsDirState(configPath, existing, setValue, statePath) {
|
|
323
|
+
try {
|
|
324
|
+
const existingState = readShellFixState(statePath);
|
|
325
|
+
writeShellFixState(mergeShellFixEntries(existingState, [
|
|
326
|
+
{
|
|
327
|
+
agent: 'mise',
|
|
328
|
+
file: configPath,
|
|
329
|
+
createdFile: existing === '',
|
|
330
|
+
fields: [{ key: 'shims_dir', previous: getShimsDirValue(existing), set: setValue }],
|
|
331
|
+
},
|
|
332
|
+
], existingState?.bashExe ?? setValue), statePath);
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
// Recording is advisory; the fix itself already succeeded.
|
|
336
|
+
}
|
|
337
|
+
}
|
|
260
338
|
/**
|
|
261
339
|
* Save mise.toml to a file
|
|
262
340
|
*/
|
|
@@ -412,7 +490,6 @@ export function runMiseCaptured(args, opts = {}) {
|
|
|
412
490
|
status: null,
|
|
413
491
|
stdout: '',
|
|
414
492
|
stderr: err instanceof Error ? err.message : String(err),
|
|
415
|
-
blockedWarn: false,
|
|
416
493
|
};
|
|
417
494
|
}
|
|
418
495
|
const stderr = result.error ? result.error.message : (result.stderr ?? '');
|
|
@@ -420,7 +497,6 @@ export function runMiseCaptured(args, opts = {}) {
|
|
|
420
497
|
status: result.status,
|
|
421
498
|
stdout: result.stdout ?? '',
|
|
422
499
|
stderr,
|
|
423
|
-
blockedWarn: /warn|self-update|version .* available/i.test(stderr),
|
|
424
500
|
};
|
|
425
501
|
}
|
|
426
502
|
/**
|
|
@@ -440,10 +516,6 @@ export function getMiseVersion() {
|
|
|
440
516
|
const version = result.stdout.trim();
|
|
441
517
|
return result.status === 0 && version !== '' ? version : 'unknown';
|
|
442
518
|
}
|
|
443
|
-
/** Alias used by prereq/status/doctor so version probes never surface mise WARN. */
|
|
444
|
-
export function getMiseVersionSilent() {
|
|
445
|
-
return getMiseVersion();
|
|
446
|
-
}
|
|
447
519
|
/**
|
|
448
520
|
* Check if a specific tool is installed via mise
|
|
449
521
|
*/
|
|
@@ -593,8 +665,13 @@ export function toolResolvability(binary) {
|
|
|
593
665
|
* tests so a result cannot depend on the machine the test runs on.
|
|
594
666
|
*/
|
|
595
667
|
export function toolAvailabilityClassification(key, binary, installedState, resolveFn = resolveBinary, shimCheck = shimExists) {
|
|
596
|
-
if (requiresFallback(key) || isPlatformUnsupported(key))
|
|
597
|
-
|
|
668
|
+
if (requiresFallback(key) || isPlatformUnsupported(key)) {
|
|
669
|
+
// A tool agentenv never hands to mise (tokei) or can't install on this
|
|
670
|
+
// platform (jless/rga on Windows) may still be present on PATH: e.g.
|
|
671
|
+
// `apt install tokei` → /usr/bin/tokei on Linux. Report it as installed
|
|
672
|
+
// then; only absent ones are "manual / install manually", never drift.
|
|
673
|
+
return resolveFn(binary) !== null ? 'resolvable' : 'manual';
|
|
674
|
+
}
|
|
598
675
|
const miseName = MISE_TOOL_NAMES[key] ?? key;
|
|
599
676
|
const onPath = resolveFn(binary) !== null;
|
|
600
677
|
return classifyToolResolvability(onPath, shimCheck(binary), undefined, installedState[miseName]?.installed === true);
|
|
@@ -612,6 +689,8 @@ export function verifyToolAvailability(config, options = {}) {
|
|
|
612
689
|
getInstalledToolState(undefined, { cwd: options.cwd, miseTomlPath: options.miseTomlPath });
|
|
613
690
|
const tools = config.tools || {};
|
|
614
691
|
const result = [];
|
|
692
|
+
const resolveFn = options.resolveFn ?? resolveBinary;
|
|
693
|
+
const shimCheck = options.shimCheck ?? shimExists;
|
|
615
694
|
for (const key of TOOL_KEYS) {
|
|
616
695
|
if (tools[key] !== true)
|
|
617
696
|
continue;
|
|
@@ -619,8 +698,8 @@ export function verifyToolAvailability(config, options = {}) {
|
|
|
619
698
|
result.push({
|
|
620
699
|
key,
|
|
621
700
|
binary,
|
|
622
|
-
onPath:
|
|
623
|
-
status: toolAvailabilityClassification(key, binary, installedState),
|
|
701
|
+
onPath: resolveFn(binary) !== null,
|
|
702
|
+
status: toolAvailabilityClassification(key, binary, installedState, resolveFn, shimCheck),
|
|
624
703
|
});
|
|
625
704
|
}
|
|
626
705
|
return result;
|
|
@@ -866,124 +945,4 @@ export function parseInstalledToolState(raw) {
|
|
|
866
945
|
export function getInstalledToolState(raw, opts = {}) {
|
|
867
946
|
return parseInstalledToolState(raw ?? runMiseCaptured(['ls', '--json'], opts).stdout) ?? {};
|
|
868
947
|
}
|
|
869
|
-
/**
|
|
870
|
-
* Parse existing mise.toml file
|
|
871
|
-
*/
|
|
872
|
-
export function parseMiseToml(filePath) {
|
|
873
|
-
try {
|
|
874
|
-
if (!fs.existsSync(filePath)) {
|
|
875
|
-
return null;
|
|
876
|
-
}
|
|
877
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
878
|
-
return parseToml(content);
|
|
879
|
-
}
|
|
880
|
-
catch {
|
|
881
|
-
return null;
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
/**
|
|
885
|
-
* Simple TOML parser helper
|
|
886
|
-
*/
|
|
887
|
-
function parseToml(content) {
|
|
888
|
-
const result = {};
|
|
889
|
-
let currentTable = result;
|
|
890
|
-
const lines = content.split('\n');
|
|
891
|
-
for (const line of lines) {
|
|
892
|
-
const trimmed = line.trim();
|
|
893
|
-
// Skip comments and empty lines
|
|
894
|
-
if (trimmed === '' || trimmed.startsWith('#')) {
|
|
895
|
-
continue;
|
|
896
|
-
}
|
|
897
|
-
// Section header
|
|
898
|
-
if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
|
|
899
|
-
const section = trimmed.slice(1, -1);
|
|
900
|
-
if (section.includes('.')) {
|
|
901
|
-
// Nested section
|
|
902
|
-
const parts = section.split('.');
|
|
903
|
-
let parent = result;
|
|
904
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
905
|
-
if (!parent[parts[i]]) {
|
|
906
|
-
parent[parts[i]] = {};
|
|
907
|
-
}
|
|
908
|
-
parent = parent[parts[i]];
|
|
909
|
-
}
|
|
910
|
-
currentTable = parent;
|
|
911
|
-
}
|
|
912
|
-
else {
|
|
913
|
-
if (!result[section]) {
|
|
914
|
-
result[section] = {};
|
|
915
|
-
}
|
|
916
|
-
currentTable = result[section];
|
|
917
|
-
}
|
|
918
|
-
continue;
|
|
919
|
-
}
|
|
920
|
-
// Key-value pair
|
|
921
|
-
const equalsIndex = trimmed.indexOf('=');
|
|
922
|
-
if (equalsIndex > 0) {
|
|
923
|
-
const key = trimmed.slice(0, equalsIndex).trim();
|
|
924
|
-
const value = trimmed.slice(equalsIndex + 1).trim();
|
|
925
|
-
// Remove quotes if present
|
|
926
|
-
let cleanValue = value;
|
|
927
|
-
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
928
|
-
(value.startsWith("'") && value.endsWith("'"))) {
|
|
929
|
-
cleanValue = value.slice(1, -1);
|
|
930
|
-
}
|
|
931
|
-
// Parse boolean
|
|
932
|
-
if (cleanValue.toLowerCase() === 'true') {
|
|
933
|
-
cleanValue = true;
|
|
934
|
-
}
|
|
935
|
-
else if (cleanValue.toLowerCase() === 'false') {
|
|
936
|
-
cleanValue = false;
|
|
937
|
-
}
|
|
938
|
-
// Parse number
|
|
939
|
-
if (!isNaN(Number(cleanValue))) {
|
|
940
|
-
cleanValue = Number(cleanValue);
|
|
941
|
-
}
|
|
942
|
-
currentTable[key] = cleanValue;
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
return result;
|
|
946
|
-
}
|
|
947
|
-
/**
|
|
948
|
-
* Merge existing mise.toml with new tools
|
|
949
|
-
* Preserves existing tools that are not in the new config
|
|
950
|
-
*/
|
|
951
|
-
export function mergeMiseConfigs(existing, newConfig) {
|
|
952
|
-
const result = {
|
|
953
|
-
tools: { ...newConfig.tools },
|
|
954
|
-
env: { ...newConfig.env },
|
|
955
|
-
settings: { ...newConfig.settings },
|
|
956
|
-
};
|
|
957
|
-
if (existing) {
|
|
958
|
-
// Merge tools - preserve existing versions if not in new config
|
|
959
|
-
for (const [tool, version] of Object.entries(existing.tools || {})) {
|
|
960
|
-
if (!result.tools[tool]) {
|
|
961
|
-
result.tools[tool] = version;
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
// Merge env
|
|
965
|
-
if (existing.env) {
|
|
966
|
-
for (const [key, value] of Object.entries(existing.env)) {
|
|
967
|
-
if (!result.env || !result.env[key]) {
|
|
968
|
-
if (!result.env) {
|
|
969
|
-
result.env = {};
|
|
970
|
-
}
|
|
971
|
-
result.env[key] = value;
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
// Merge settings
|
|
976
|
-
if (existing.settings) {
|
|
977
|
-
for (const [key, value] of Object.entries(existing.settings)) {
|
|
978
|
-
if (!result.settings || result.settings[key] === undefined) {
|
|
979
|
-
if (!result.settings) {
|
|
980
|
-
result.settings = {};
|
|
981
|
-
}
|
|
982
|
-
result.settings[key] = value;
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
return result;
|
|
988
|
-
}
|
|
989
948
|
//# sourceMappingURL=mise.js.map
|