@lyellr88/buddy-mcp 1.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/README.md +219 -0
- package/dist/config/claude-config.d.ts +7 -0
- package/dist/config/claude-config.d.ts.map +1 -0
- package/dist/config/claude-config.js +107 -0
- package/dist/config/claude-config.js.map +1 -0
- package/dist/config/hooks.d.ts +22 -0
- package/dist/config/hooks.d.ts.map +1 -0
- package/dist/config/hooks.js +58 -0
- package/dist/config/hooks.js.map +1 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +6 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/pet-config.d.ts +12 -0
- package/dist/config/pet-config.d.ts.map +1 -0
- package/dist/config/pet-config.js +150 -0
- package/dist/config/pet-config.js.map +1 -0
- package/dist/constants.d.ts +24 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +94 -0
- package/dist/constants.js.map +1 -0
- package/dist/finder/estimator.d.ts +3 -0
- package/dist/finder/estimator.d.ts.map +1 -0
- package/dist/finder/estimator.js +27 -0
- package/dist/finder/estimator.js.map +1 -0
- package/dist/finder/index.d.ts +3 -0
- package/dist/finder/index.d.ts.map +1 -0
- package/dist/finder/index.js +3 -0
- package/dist/finder/index.js.map +1 -0
- package/dist/finder/orchestrator.d.ts +8 -0
- package/dist/finder/orchestrator.d.ts.map +1 -0
- package/dist/finder/orchestrator.js +163 -0
- package/dist/finder/orchestrator.js.map +1 -0
- package/dist/finder/worker.d.ts +3 -0
- package/dist/finder/worker.d.ts.map +1 -0
- package/dist/finder/worker.js +130 -0
- package/dist/finder/worker.js.map +1 -0
- package/dist/generation/hash.d.ts +5 -0
- package/dist/generation/hash.d.ts.map +1 -0
- package/dist/generation/hash.js +37 -0
- package/dist/generation/hash.js.map +1 -0
- package/dist/generation/index.d.ts +4 -0
- package/dist/generation/index.d.ts.map +1 -0
- package/dist/generation/index.js +4 -0
- package/dist/generation/index.js.map +1 -0
- package/dist/generation/rng.d.ts +4 -0
- package/dist/generation/rng.d.ts.map +1 -0
- package/dist/generation/rng.js +14 -0
- package/dist/generation/rng.js.map +1 -0
- package/dist/generation/roll.d.ts +7 -0
- package/dist/generation/roll.d.ts.map +1 -0
- package/dist/generation/roll.js +51 -0
- package/dist/generation/roll.js.map +1 -0
- package/dist/mcp/index.d.ts +5 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +273 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/persistence.d.ts +6 -0
- package/dist/mcp/persistence.d.ts.map +1 -0
- package/dist/mcp/persistence.js +129 -0
- package/dist/mcp/persistence.js.map +1 -0
- package/dist/mcp/state.d.ts +74 -0
- package/dist/mcp/state.d.ts.map +1 -0
- package/dist/mcp/state.js +20 -0
- package/dist/mcp/state.js.map +1 -0
- package/dist/mcp/tools/auto.d.ts +4 -0
- package/dist/mcp/tools/auto.d.ts.map +1 -0
- package/dist/mcp/tools/auto.js +15 -0
- package/dist/mcp/tools/auto.js.map +1 -0
- package/dist/mcp/tools/core.d.ts +2 -0
- package/dist/mcp/tools/core.d.ts.map +1 -0
- package/dist/mcp/tools/core.js +350 -0
- package/dist/mcp/tools/core.js.map +1 -0
- package/dist/mcp/tools/export.d.ts +2 -0
- package/dist/mcp/tools/export.d.ts.map +1 -0
- package/dist/mcp/tools/export.js +161 -0
- package/dist/mcp/tools/export.js.map +1 -0
- package/dist/mcp/tools/interact.d.ts +2 -0
- package/dist/mcp/tools/interact.d.ts.map +1 -0
- package/dist/mcp/tools/interact.js +56 -0
- package/dist/mcp/tools/interact.js.map +1 -0
- package/dist/mcp/tools/stats.d.ts +4 -0
- package/dist/mcp/tools/stats.d.ts.map +1 -0
- package/dist/mcp/tools/stats.js +87 -0
- package/dist/mcp/tools/stats.js.map +1 -0
- package/dist/mcp/watcher.d.ts +3 -0
- package/dist/mcp/watcher.d.ts.map +1 -0
- package/dist/mcp/watcher.js +117 -0
- package/dist/mcp/watcher.js.map +1 -0
- package/dist/patcher/binary-finder.d.ts +3 -0
- package/dist/patcher/binary-finder.d.ts.map +1 -0
- package/dist/patcher/binary-finder.js +169 -0
- package/dist/patcher/binary-finder.js.map +1 -0
- package/dist/patcher/index.d.ts +5 -0
- package/dist/patcher/index.d.ts.map +1 -0
- package/dist/patcher/index.js +5 -0
- package/dist/patcher/index.js.map +1 -0
- package/dist/patcher/patch.d.ts +5 -0
- package/dist/patcher/patch.d.ts.map +1 -0
- package/dist/patcher/patch.js +148 -0
- package/dist/patcher/patch.js.map +1 -0
- package/dist/patcher/preflight.d.ts +5 -0
- package/dist/patcher/preflight.d.ts.map +1 -0
- package/dist/patcher/preflight.js +145 -0
- package/dist/patcher/preflight.js.map +1 -0
- package/dist/patcher/salt-ops.d.ts +18 -0
- package/dist/patcher/salt-ops.d.ts.map +1 -0
- package/dist/patcher/salt-ops.js +93 -0
- package/dist/patcher/salt-ops.js.map +1 -0
- package/dist/personalities.d.ts +10 -0
- package/dist/personalities.d.ts.map +1 -0
- package/dist/personalities.js +295 -0
- package/dist/personalities.js.map +1 -0
- package/dist/presets.d.ts +11 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +207 -0
- package/dist/presets.js.map +1 -0
- package/dist/sprites/data.d.ts +4 -0
- package/dist/sprites/data.d.ts.map +1 -0
- package/dist/sprites/data.js +103 -0
- package/dist/sprites/data.js.map +1 -0
- package/dist/sprites/index.d.ts +3 -0
- package/dist/sprites/index.d.ts.map +1 -0
- package/dist/sprites/index.js +3 -0
- package/dist/sprites/index.js.map +1 -0
- package/dist/sprites/render.d.ts +15 -0
- package/dist/sprites/render.d.ts.map +1 -0
- package/dist/sprites/render.js +77 -0
- package/dist/sprites/render.js.map +1 -0
- package/dist/tui/animator.d.ts +13 -0
- package/dist/tui/animator.d.ts.map +1 -0
- package/dist/tui/animator.js +39 -0
- package/dist/tui/animator.js.map +1 -0
- package/dist/tui/apply/index.d.ts +9 -0
- package/dist/tui/apply/index.d.ts.map +1 -0
- package/dist/tui/apply/index.js +553 -0
- package/dist/tui/apply/index.js.map +1 -0
- package/dist/tui/builder/colors.d.ts +15 -0
- package/dist/tui/builder/colors.d.ts.map +1 -0
- package/dist/tui/builder/colors.js +20 -0
- package/dist/tui/builder/colors.js.map +1 -0
- package/dist/tui/builder/index.d.ts +6 -0
- package/dist/tui/builder/index.d.ts.map +1 -0
- package/dist/tui/builder/index.js +172 -0
- package/dist/tui/builder/index.js.map +1 -0
- package/dist/tui/builder/keyboard.d.ts +17 -0
- package/dist/tui/builder/keyboard.d.ts.map +1 -0
- package/dist/tui/builder/keyboard.js +76 -0
- package/dist/tui/builder/keyboard.js.map +1 -0
- package/dist/tui/builder/preview-panel.d.ts +9 -0
- package/dist/tui/builder/preview-panel.d.ts.map +1 -0
- package/dist/tui/builder/preview-panel.js +103 -0
- package/dist/tui/builder/preview-panel.js.map +1 -0
- package/dist/tui/builder/selection-panel.d.ts +11 -0
- package/dist/tui/builder/selection-panel.d.ts.map +1 -0
- package/dist/tui/builder/selection-panel.js +446 -0
- package/dist/tui/builder/selection-panel.js.map +1 -0
- package/dist/tui/builder/stat-bars.d.ts +4 -0
- package/dist/tui/builder/stat-bars.d.ts.map +1 -0
- package/dist/tui/builder/stat-bars.js +46 -0
- package/dist/tui/builder/stat-bars.js.map +1 -0
- package/dist/tui/builder/state.d.ts +22 -0
- package/dist/tui/builder/state.d.ts.map +1 -0
- package/dist/tui/builder/state.js +92 -0
- package/dist/tui/builder/state.js.map +1 -0
- package/dist/tui/cli.d.ts +3 -0
- package/dist/tui/cli.d.ts.map +1 -0
- package/dist/tui/cli.js +26 -0
- package/dist/tui/cli.js.map +1 -0
- package/dist/tui/commands/buddies.d.ts +2 -0
- package/dist/tui/commands/buddies.d.ts.map +1 -0
- package/dist/tui/commands/buddies.js +172 -0
- package/dist/tui/commands/buddies.js.map +1 -0
- package/dist/tui/commands/current.d.ts +2 -0
- package/dist/tui/commands/current.d.ts.map +1 -0
- package/dist/tui/commands/current.js +35 -0
- package/dist/tui/commands/current.js.map +1 -0
- package/dist/tui/commands/interactive.d.ts +6 -0
- package/dist/tui/commands/interactive.d.ts.map +1 -0
- package/dist/tui/commands/interactive.js +385 -0
- package/dist/tui/commands/interactive.js.map +1 -0
- package/dist/tui/commands/preview.d.ts +3 -0
- package/dist/tui/commands/preview.d.ts.map +1 -0
- package/dist/tui/commands/preview.js +94 -0
- package/dist/tui/commands/preview.js.map +1 -0
- package/dist/tui/commands/rehatch.d.ts +2 -0
- package/dist/tui/commands/rehatch.d.ts.map +1 -0
- package/dist/tui/commands/rehatch.js +30 -0
- package/dist/tui/commands/rehatch.js.map +1 -0
- package/dist/tui/commands/restore.d.ts +2 -0
- package/dist/tui/commands/restore.d.ts.map +1 -0
- package/dist/tui/commands/restore.js +52 -0
- package/dist/tui/commands/restore.js.map +1 -0
- package/dist/tui/commands/share.d.ts +2 -0
- package/dist/tui/commands/share.d.ts.map +1 -0
- package/dist/tui/commands/share.js +105 -0
- package/dist/tui/commands/share.js.map +1 -0
- package/dist/tui/commands/start-screen.d.ts +3 -0
- package/dist/tui/commands/start-screen.d.ts.map +1 -0
- package/dist/tui/commands/start-screen.js +93 -0
- package/dist/tui/commands/start-screen.js.map +1 -0
- package/dist/tui/display.d.ts +5 -0
- package/dist/tui/display.d.ts.map +1 -0
- package/dist/tui/display.js +33 -0
- package/dist/tui/display.js.map +1 -0
- package/dist/tui/format.d.ts +5 -0
- package/dist/tui/format.d.ts.map +1 -0
- package/dist/tui/format.js +21 -0
- package/dist/tui/format.js.map +1 -0
- package/dist/tui/gallery/index.d.ts +12 -0
- package/dist/tui/gallery/index.d.ts.map +1 -0
- package/dist/tui/gallery/index.js +153 -0
- package/dist/tui/gallery/index.js.map +1 -0
- package/dist/tui/gallery/keyboard.d.ts +15 -0
- package/dist/tui/gallery/keyboard.d.ts.map +1 -0
- package/dist/tui/gallery/keyboard.js +41 -0
- package/dist/tui/gallery/keyboard.js.map +1 -0
- package/dist/tui/gallery/profile-list-panel.d.ts +10 -0
- package/dist/tui/gallery/profile-list-panel.d.ts.map +1 -0
- package/dist/tui/gallery/profile-list-panel.js +66 -0
- package/dist/tui/gallery/profile-list-panel.js.map +1 -0
- package/dist/tui/gallery/profile-preview-panel.d.ts +9 -0
- package/dist/tui/gallery/profile-preview-panel.d.ts.map +1 -0
- package/dist/tui/gallery/profile-preview-panel.js +121 -0
- package/dist/tui/gallery/profile-preview-panel.js.map +1 -0
- package/dist/tui/gallery/state.d.ts +13 -0
- package/dist/tui/gallery/state.d.ts.map +1 -0
- package/dist/tui/gallery/state.js +33 -0
- package/dist/tui/gallery/state.js.map +1 -0
- package/dist/tui/index.d.ts +9 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +9 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/launcher.d.ts +3 -0
- package/dist/tui/launcher.d.ts.map +1 -0
- package/dist/tui/launcher.js +24 -0
- package/dist/tui/launcher.js.map +1 -0
- package/dist/tui/presets/index.d.ts +3 -0
- package/dist/tui/presets/index.d.ts.map +1 -0
- package/dist/tui/presets/index.js +202 -0
- package/dist/tui/presets/index.js.map +1 -0
- package/dist/tui/presets/preset-list-panel.d.ts +9 -0
- package/dist/tui/presets/preset-list-panel.d.ts.map +1 -0
- package/dist/tui/presets/preset-list-panel.js +52 -0
- package/dist/tui/presets/preset-list-panel.js.map +1 -0
- package/dist/tui/prompts.d.ts +13 -0
- package/dist/tui/prompts.d.ts.map +1 -0
- package/dist/tui/prompts.js +126 -0
- package/dist/tui/prompts.js.map +1 -0
- package/dist/tui/start/index.d.ts +3 -0
- package/dist/tui/start/index.d.ts.map +1 -0
- package/dist/tui/start/index.js +170 -0
- package/dist/tui/start/index.js.map +1 -0
- package/dist/types.d.ts +113 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { STAT_TOOL_RESPONSES } from '../../personalities.js';
|
|
2
|
+
import { S, dynamicTools } from '../state.js';
|
|
3
|
+
import { getPersonalityRemark } from '../../personalities.js';
|
|
4
|
+
// --- Stat personality tools ---
|
|
5
|
+
export const STAT_TOOL_NAMES = new Set([
|
|
6
|
+
// DEBUGGING
|
|
7
|
+
'deep_trace', 'trace_nightmare', 'null_hunt', 'stack_dive',
|
|
8
|
+
// PATIENCE
|
|
9
|
+
'patience_check', 'wait_wisdom', 'vibe_check', 'still_point',
|
|
10
|
+
// CHAOS
|
|
11
|
+
'chaos_audit', 'chaos_roulette', 'chaos_spark', 'entropy_roll',
|
|
12
|
+
// WISDOM
|
|
13
|
+
'zen_consult', 'zen_mirror', 'oracle_seek', 'deep_thought',
|
|
14
|
+
// SNARK
|
|
15
|
+
'snark_roast', 'snark_savage', 'side_eye', 'snark_verdict',
|
|
16
|
+
]);
|
|
17
|
+
// Maps each stat to its 4 tools — 1 random shown when stat is in top 2 by raw value
|
|
18
|
+
export const STAT_TOOLS_MAP = {
|
|
19
|
+
DEBUGGING: ['deep_trace', 'trace_nightmare', 'null_hunt', 'stack_dive'],
|
|
20
|
+
PATIENCE: ['patience_check', 'wait_wisdom', 'vibe_check', 'still_point'],
|
|
21
|
+
CHAOS: ['chaos_audit', 'chaos_roulette', 'chaos_spark', 'entropy_roll'],
|
|
22
|
+
WISDOM: ['zen_consult', 'zen_mirror', 'oracle_seek', 'deep_thought'],
|
|
23
|
+
SNARK: ['snark_roast', 'snark_savage', 'side_eye', 'snark_verdict'],
|
|
24
|
+
};
|
|
25
|
+
const inputSchema = {
|
|
26
|
+
type: 'object',
|
|
27
|
+
properties: { target: { type: 'string', description: 'The file or code to look at' } },
|
|
28
|
+
};
|
|
29
|
+
function pick(pool) {
|
|
30
|
+
return pool[Math.floor(Math.random() * pool.length)] ?? pool[0];
|
|
31
|
+
}
|
|
32
|
+
function respond(stat, context, args) {
|
|
33
|
+
const buddy = S.currentBuddy;
|
|
34
|
+
if (!buddy)
|
|
35
|
+
return 'No buddy active. Initialize a buddy first.';
|
|
36
|
+
const pool = STAT_TOOL_RESPONSES[stat][context] ?? STAT_TOOL_RESPONSES[stat]['general'];
|
|
37
|
+
const quip = pick(pool);
|
|
38
|
+
const target = args['target'];
|
|
39
|
+
return target ? `${buddy.name}: "${quip}"\n\n*target: ${target}*` : `${buddy.name}: "${quip}"`;
|
|
40
|
+
}
|
|
41
|
+
function makeTool(toolName, description, stat, context) {
|
|
42
|
+
dynamicTools.set(toolName, {
|
|
43
|
+
tool: { name: toolName, description, inputSchema },
|
|
44
|
+
handler: async (args) => respond(stat, context, args),
|
|
45
|
+
_def: { toolName, description, logic: '', scope: 'global', inputSchema },
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
// DEBUGGING tools
|
|
49
|
+
makeTool('deep_trace', '[Buddy Tool] A focused search for bugs or null pointers. (global)', 'DEBUGGING', 'general');
|
|
50
|
+
makeTool('trace_nightmare', '[Buddy Tool] Deeper debugging — for when the stack trace stopped making sense. (global)', 'DEBUGGING', 'stuck');
|
|
51
|
+
makeTool('null_hunt', '[Buddy Tool] Hunt for null refs. Clinical. Relentless. (global)', 'DEBUGGING', 'hunt');
|
|
52
|
+
makeTool('stack_dive', '[Buddy Tool] Dive into the callstack. The bug is always deeper than you think. (global)', 'DEBUGGING', 'dive');
|
|
53
|
+
// PATIENCE tools — includes vibe_check (moved from core with its cosmic logic intact)
|
|
54
|
+
makeTool('patience_check', '[Buddy Tool] Check if the buddy is still willing to help you. (global)', 'PATIENCE', 'general');
|
|
55
|
+
makeTool('wait_wisdom', '[Buddy Tool] Slow down. Receive patience-encoded insight. (global)', 'PATIENCE', 'stuck');
|
|
56
|
+
makeTool('still_point', '[Buddy Tool] Stop. Be still. Let the answer come to you. (global)', 'PATIENCE', 'still');
|
|
57
|
+
// vibe_check keeps its special cosmic logic
|
|
58
|
+
dynamicTools.set('vibe_check', {
|
|
59
|
+
tool: { name: 'vibe_check', description: '[Buddy Tool] The ultimate mystery action. Your buddy reads the vibe. (global)', inputSchema },
|
|
60
|
+
handler: async () => {
|
|
61
|
+
const buddy = S.currentBuddy;
|
|
62
|
+
if (!buddy)
|
|
63
|
+
return 'No buddy active. Initialize a buddy first.';
|
|
64
|
+
if (Math.random() < 0.05) {
|
|
65
|
+
return `🌌 COSMIC EVENT 🌌\n\n${buddy.name} has transcended the terminal. They say: "I have seen the end of the universe. It's written in COBOL. We should probably use more Python."`;
|
|
66
|
+
}
|
|
67
|
+
const remark = getPersonalityRemark(buddy);
|
|
68
|
+
return `[Vibe Check: ${buddy.name}]\n\n${remark}`;
|
|
69
|
+
},
|
|
70
|
+
_def: { toolName: 'vibe_check', description: '[Buddy Tool] The ultimate mystery action. (global)', logic: '', scope: 'global', inputSchema },
|
|
71
|
+
});
|
|
72
|
+
// CHAOS tools
|
|
73
|
+
makeTool('chaos_audit', '[Buddy Tool] An unpredictable check that might not help at all. (global)', 'CHAOS', 'general');
|
|
74
|
+
makeTool('chaos_roulette', '[Buddy Tool] Spin the chaos wheel. Receive a wildly unpredictable suggestion. (global)', 'CHAOS', 'stuck');
|
|
75
|
+
makeTool('chaos_spark', '[Buddy Tool] Ignite a lateral idea. May or may not be relevant. (global)', 'CHAOS', 'spark');
|
|
76
|
+
makeTool('entropy_roll', '[Buddy Tool] Roll against entropy. The universe responds. (global)', 'CHAOS', 'entropy');
|
|
77
|
+
// WISDOM tools
|
|
78
|
+
makeTool('zen_consult', '[Buddy Tool] A deep, philosophical insight into your architecture. (global)', 'WISDOM', 'general');
|
|
79
|
+
makeTool('zen_mirror', '[Buddy Tool] Turn the question inward. Receive a reflection, not an answer. (global)', 'WISDOM', 'stuck');
|
|
80
|
+
makeTool('oracle_seek', '[Buddy Tool] Seek the oracle. The answer is already inside you. (global)', 'WISDOM', 'oracle');
|
|
81
|
+
makeTool('deep_thought', '[Buddy Tool] Think slower. The answer requires depth. (global)', 'WISDOM', 'deep');
|
|
82
|
+
// SNARK tools
|
|
83
|
+
makeTool('snark_roast', '[Buddy Tool] A sarcastic critique of your current work. (global)', 'SNARK', 'general');
|
|
84
|
+
makeTool('snark_savage', '[Buddy Tool] No mercy. Full roast. For when you need the unfiltered truth. (global)', 'SNARK', 'mistake');
|
|
85
|
+
makeTool('side_eye', '[Buddy Tool] Your buddy looks at your code. Then at you. Then back at the code. (global)', 'SNARK', 'side_eye');
|
|
86
|
+
makeTool('snark_verdict', '[Buddy Tool] Final ruling from the bench. The buddy has reviewed and judged. (global)', 'SNARK', 'verdict');
|
|
87
|
+
//# sourceMappingURL=stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../../src/mcp/tools/stats.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/mcp/watcher.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Detached background watcher — spawned by reroll_buddy when the binary is locked (Windows EPERM).
|
|
3
|
+
// Polls every 2 seconds until Claude Code closes, then auto-applies the pending patch and exits.
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync, unlinkSync } from 'fs';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { homedir } from 'os';
|
|
7
|
+
import { patchBinary } from '../patcher/patch.js';
|
|
8
|
+
import { saveProfile } from '../config/pet-config.js';
|
|
9
|
+
import { ORIGINAL_SALT } from '../constants.js';
|
|
10
|
+
const PENDING_PATCH_FILE = join(homedir(), '.buddy_mcp_pending.json');
|
|
11
|
+
const GACHA_STATE_FILE = join(homedir(), '.buddy_mcp_gacha.json');
|
|
12
|
+
const POLL_MS = 2000;
|
|
13
|
+
const TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
|
|
14
|
+
function log(msg) {
|
|
15
|
+
process.stderr.write(`[buddy-mcp watcher] ${msg}\n`);
|
|
16
|
+
}
|
|
17
|
+
function sleep(ms) {
|
|
18
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
19
|
+
}
|
|
20
|
+
async function main() {
|
|
21
|
+
if (!existsSync(PENDING_PATCH_FILE)) {
|
|
22
|
+
log('No pending patch found. Exiting.');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
let pending;
|
|
26
|
+
try {
|
|
27
|
+
pending = JSON.parse(readFileSync(PENDING_PATCH_FILE, 'utf-8'));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
log('Pending patch file is corrupted. Exiting.');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// Capture the salt we were spawned for — if the file changes (newer reroll), we yield to the new watcher
|
|
34
|
+
const ourSalt = pending.salt;
|
|
35
|
+
const { rarity, species, shiny } = pending.profile;
|
|
36
|
+
const shinyTag = shiny ? ' ✨' : '';
|
|
37
|
+
log(`Waiting for Claude to close — will auto-apply ${rarity} ${species}${shinyTag}...`);
|
|
38
|
+
const start = Date.now();
|
|
39
|
+
while (Date.now() - start < TIMEOUT_MS) {
|
|
40
|
+
await sleep(POLL_MS);
|
|
41
|
+
// Re-read pending file each cycle — if a newer reroll overwrote it, yield to the newer watcher
|
|
42
|
+
if (!existsSync(PENDING_PATCH_FILE)) {
|
|
43
|
+
log('Pending patch file gone — another watcher likely applied it. Exiting.');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const current = JSON.parse(readFileSync(PENDING_PATCH_FILE, 'utf-8'));
|
|
48
|
+
if (current.salt !== ourSalt) {
|
|
49
|
+
log(`Newer reroll detected (${current.salt}) — yielding. Exiting.`);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// Refresh pending in case other fields updated
|
|
53
|
+
pending = current;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// File temporarily unreadable — keep waiting
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
patchBinary(pending.binaryPath, pending.currentSalt, pending.salt);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
const msg = err.message ?? '';
|
|
64
|
+
if (msg.includes('EPERM') || msg.includes('EBUSY') || msg.includes('locked')) {
|
|
65
|
+
continue; // Claude still running — keep waiting
|
|
66
|
+
}
|
|
67
|
+
// Salt not found — binary updated and salt structure changed, try ORIGINAL_SALT fallback
|
|
68
|
+
if (msg.includes('Could not find salt')) {
|
|
69
|
+
try {
|
|
70
|
+
patchBinary(pending.binaryPath, ORIGINAL_SALT, pending.salt);
|
|
71
|
+
}
|
|
72
|
+
catch (fallbackErr) {
|
|
73
|
+
const fallbackMsg = fallbackErr.message ?? '';
|
|
74
|
+
if (fallbackMsg.includes('Could not find salt')) {
|
|
75
|
+
log('Claude updated and changed the salt structure — re-patch not possible automatically.\n' +
|
|
76
|
+
'Check for a buddy-mcp update, then run reroll_buddy again.');
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
log(`Unexpected fallback patch error: ${fallbackMsg}`);
|
|
80
|
+
}
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
// Fallback succeeded — update pending.currentSalt for the success path below
|
|
84
|
+
log('Re-patched using ORIGINAL_SALT after binary update.');
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
log(`Unexpected patch error: ${msg}`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Patch succeeded
|
|
92
|
+
saveProfile(pending.profile, { activate: true });
|
|
93
|
+
if (existsSync(GACHA_STATE_FILE)) {
|
|
94
|
+
try {
|
|
95
|
+
const raw = JSON.parse(readFileSync(GACHA_STATE_FILE, 'utf-8'));
|
|
96
|
+
if (!raw.discoveredSpecies.includes(pending.profile.species)) {
|
|
97
|
+
raw.discoveredSpecies.push(pending.profile.species);
|
|
98
|
+
}
|
|
99
|
+
if (pending.profile.shiny)
|
|
100
|
+
raw.shinyCount = (raw.shinyCount ?? 0) + 1;
|
|
101
|
+
writeFileSync(GACHA_STATE_FILE, JSON.stringify(raw, null, 2));
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Non-fatal — gacha state self-heals on next server start
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
unlinkSync(PENDING_PATCH_FILE);
|
|
108
|
+
log(`✅ ${rarity} ${species}${shinyTag} patched! Reopen Claude Code to see your new companion.`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
log('Timed out after 30 minutes. Run `npm run apply` manually if needed.');
|
|
112
|
+
}
|
|
113
|
+
main().catch((err) => {
|
|
114
|
+
process.stderr.write(`[buddy-mcp watcher] Fatal: ${err.message}\n`);
|
|
115
|
+
process.exit(1);
|
|
116
|
+
});
|
|
117
|
+
//# sourceMappingURL=watcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/mcp/watcher.ts"],"names":[],"mappings":";AACA,mGAAmG;AACnG,iGAAiG;AAEjG,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACzE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG/C,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,yBAAyB,CAAC,CAAC;AACtE,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,uBAAuB,CAAC,CAAC;AAClE,MAAM,OAAO,GAAG,IAAI,CAAC;AACrB,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AAiBhD,SAAS,GAAG,CAAC,GAAW;IACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACpC,GAAG,CAAC,kCAAkC,CAAC,CAAC;QACxC,OAAO;IACT,CAAC;IAED,IAAI,OAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAiB,CAAC;IAClF,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,CAAC,2CAA2C,CAAC,CAAC;QACjD,OAAO;IACT,CAAC;IAED,yGAAyG;IACzG,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAE7B,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACnC,GAAG,CAAC,iDAAiD,MAAM,IAAI,OAAO,GAAG,QAAQ,KAAK,CAAC,CAAC;IAExF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,UAAU,EAAE,CAAC;QACvC,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;QAErB,+FAA+F;QAC/F,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACpC,GAAG,CAAC,uEAAuE,CAAC,CAAC;YAC7E,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAiB,CAAC;YACtF,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC7B,GAAG,CAAC,0BAA0B,OAAO,CAAC,IAAI,wBAAwB,CAAC,CAAC;gBACpE,OAAO;YACT,CAAC;YACD,+CAA+C;YAC/C,OAAO,GAAG,OAAO,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,6CAA6C;YAC7C,SAAS;QACX,CAAC;QAED,IAAI,CAAC;YACH,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACrE,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,GAAG,GAAI,GAAa,CAAC,OAAO,IAAI,EAAE,CAAC;YAEzC,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC7E,SAAS,CAAC,sCAAsC;YAClD,CAAC;YAED,yFAAyF;YACzF,IAAI,GAAG,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC;gBACxC,IAAI,CAAC;oBACH,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE,aAAa,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC/D,CAAC;gBAAC,OAAO,WAAoB,EAAE,CAAC;oBAC9B,MAAM,WAAW,GAAI,WAAqB,CAAC,OAAO,IAAI,EAAE,CAAC;oBACzD,IAAI,WAAW,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC;wBAChD,GAAG,CACD,wFAAwF;4BACxF,4DAA4D,CAC7D,CAAC;oBACJ,CAAC;yBAAM,CAAC;wBACN,GAAG,CAAC,oCAAoC,WAAW,EAAE,CAAC,CAAC;oBACzD,CAAC;oBACD,OAAO;gBACT,CAAC;gBACD,6EAA6E;gBAC7E,GAAG,CAAC,qDAAqD,CAAC,CAAC;YAC7D,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC;gBACtC,OAAO;YACT,CAAC;QACH,CAAC;QAED,kBAAkB;QAClB,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAEjD,IAAI,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAe,CAAC;gBAC9E,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC7D,GAAG,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACtD,CAAC;gBACD,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK;oBAAE,GAAG,CAAC,UAAU,GAAG,CAAC,GAAG,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;gBACtE,aAAa,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAChE,CAAC;YAAC,MAAM,CAAC;gBACP,0DAA0D;YAC5D,CAAC;QACH,CAAC;QAED,UAAU,CAAC,kBAAkB,CAAC,CAAC;QAC/B,GAAG,CAAC,KAAK,MAAM,IAAI,OAAO,GAAG,QAAQ,yDAAyD,CAAC,CAAC;QAChG,OAAO;IACT,CAAC;IAED,GAAG,CAAC,qEAAqE,CAAC,CAAC;AAC7E,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA+B,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;IAC/E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binary-finder.d.ts","sourceRoot":"","sources":["../../src/patcher/binary-finder.ts"],"names":[],"mappings":"AAqGA,wBAAgB,gBAAgB,IAAI,MAAM,CA4DzC;AAED,wBAAgB,aAAa,IAAI,MAAM,CActC"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { readFileSync, existsSync, statSync, realpathSync } from 'fs';
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import { join, dirname } from 'path';
|
|
4
|
+
import { homedir, platform } from 'os';
|
|
5
|
+
import { ISSUE_URL, diagnostics } from '../constants.js';
|
|
6
|
+
const IS_WIN = platform() === 'win32';
|
|
7
|
+
const IS_MAC = platform() === 'darwin';
|
|
8
|
+
function which(cmd) {
|
|
9
|
+
try {
|
|
10
|
+
const shellCmd = IS_WIN ? `where ${cmd}` : `which ${cmd}`;
|
|
11
|
+
const result = execSync(shellCmd, {
|
|
12
|
+
encoding: 'utf-8',
|
|
13
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
14
|
+
}).trim();
|
|
15
|
+
const first = result.split(/\r?\n/)[0].trim();
|
|
16
|
+
if (first && existsSync(first))
|
|
17
|
+
return first;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
/* ignore */
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
function realpath(p) {
|
|
25
|
+
try {
|
|
26
|
+
return realpathSync(p);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return p;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function getPlatformCandidates() {
|
|
33
|
+
const home = homedir();
|
|
34
|
+
if (IS_WIN) {
|
|
35
|
+
const appData = process.env.APPDATA || join(home, 'AppData', 'Roaming');
|
|
36
|
+
const localAppData = process.env.LOCALAPPDATA || join(home, 'AppData', 'Local');
|
|
37
|
+
return [
|
|
38
|
+
join(localAppData, 'Programs', 'claude', 'claude.exe'),
|
|
39
|
+
join(appData, 'npm', 'claude.cmd'),
|
|
40
|
+
join(appData, 'npm', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
|
|
41
|
+
join(home, '.volta', 'bin', 'claude.exe'),
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
if (IS_MAC) {
|
|
45
|
+
return [
|
|
46
|
+
join(home, '.local', 'bin', 'claude'),
|
|
47
|
+
join(home, '.claude', 'local', 'claude'),
|
|
48
|
+
'/usr/local/bin/claude',
|
|
49
|
+
'/opt/homebrew/bin/claude',
|
|
50
|
+
join(home, '.npm-global', 'bin', 'claude'),
|
|
51
|
+
join(home, '.volta', 'bin', 'claude'),
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
return [
|
|
55
|
+
join(home, '.local', 'bin', 'claude'),
|
|
56
|
+
join(home, '.claude', 'local', 'claude'),
|
|
57
|
+
'/usr/local/bin/claude',
|
|
58
|
+
'/usr/bin/claude',
|
|
59
|
+
join(home, '.npm-global', 'bin', 'claude'),
|
|
60
|
+
join(home, '.volta', 'bin', 'claude'),
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
function resolveWindowsShim(cmdPath) {
|
|
64
|
+
try {
|
|
65
|
+
const content = readFileSync(cmdPath, 'utf-8');
|
|
66
|
+
const match = content.match(/node_modules[\\/]@anthropic-ai[\\/]claude-code[\\/][^\s"]+/);
|
|
67
|
+
if (match) {
|
|
68
|
+
const shimDir = dirname(cmdPath);
|
|
69
|
+
const target = join(shimDir, match[0]);
|
|
70
|
+
if (existsSync(target))
|
|
71
|
+
return target;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
/* ignore */
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
function resolveFromPackageDir(resolvedPath) {
|
|
80
|
+
try {
|
|
81
|
+
const ccPkg = join('@anthropic-ai', 'claude-code');
|
|
82
|
+
const idx = resolvedPath.indexOf(ccPkg);
|
|
83
|
+
if (idx === -1)
|
|
84
|
+
return null;
|
|
85
|
+
const pkgDir = resolvedPath.substring(0, idx + ccPkg.length);
|
|
86
|
+
const binaryName = IS_WIN ? 'claude.exe' : 'claude';
|
|
87
|
+
const candidate = join(pkgDir, binaryName);
|
|
88
|
+
if (existsSync(candidate)) {
|
|
89
|
+
const size = statSync(candidate).size;
|
|
90
|
+
if (size >= 1_000_000)
|
|
91
|
+
return candidate;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
/* ignore */
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
export function findClaudeBinary() {
|
|
100
|
+
if (process.env.CLAUDE_BINARY) {
|
|
101
|
+
const p = process.env.CLAUDE_BINARY;
|
|
102
|
+
if (existsSync(p))
|
|
103
|
+
return realpath(p);
|
|
104
|
+
throw new Error(`CLAUDE_BINARY="${p}" does not exist.`);
|
|
105
|
+
}
|
|
106
|
+
const onPath = which('claude');
|
|
107
|
+
if (onPath) {
|
|
108
|
+
const resolved = realpath(onPath);
|
|
109
|
+
if (IS_WIN && resolved.endsWith('.cmd')) {
|
|
110
|
+
const target = resolveWindowsShim(resolved);
|
|
111
|
+
if (target)
|
|
112
|
+
return target;
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
const size = statSync(resolved).size;
|
|
116
|
+
if (size >= 1_000_000) {
|
|
117
|
+
return resolved;
|
|
118
|
+
}
|
|
119
|
+
const fromPkg = resolveFromPackageDir(resolved);
|
|
120
|
+
if (fromPkg)
|
|
121
|
+
return fromPkg;
|
|
122
|
+
if (IS_WIN && !resolved.endsWith('.cmd')) {
|
|
123
|
+
const target = resolveWindowsShim(resolved + '.cmd');
|
|
124
|
+
if (target)
|
|
125
|
+
return target;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return resolved;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const candidates = getPlatformCandidates();
|
|
133
|
+
for (const candidate of candidates) {
|
|
134
|
+
if (existsSync(candidate)) {
|
|
135
|
+
return realpath(candidate);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const platformHint = IS_WIN
|
|
139
|
+
? 'On Windows, Claude Code is typically installed via npm or the desktop app.'
|
|
140
|
+
: IS_MAC
|
|
141
|
+
? 'On macOS, Claude Code is typically at ~/.claude/local/ or installed via npm/brew.'
|
|
142
|
+
: 'On Linux, Claude Code is typically at ~/.local/share/claude/versions/.';
|
|
143
|
+
const tried = candidates.map((c) => ` - ${c}`).join('\n');
|
|
144
|
+
throw new Error('Could not find Claude Code binary.\n' +
|
|
145
|
+
diagnostics({
|
|
146
|
+
Tried: '`' + (IS_WIN ? 'where' : 'which') + ' claude` and these paths:',
|
|
147
|
+
}) +
|
|
148
|
+
'\n' +
|
|
149
|
+
tried +
|
|
150
|
+
'\n\n ' +
|
|
151
|
+
platformHint +
|
|
152
|
+
'\n Set CLAUDE_BINARY=/path/to/binary to specify manually.' +
|
|
153
|
+
`\n\n If this is a bug, please report it at:\n ${ISSUE_URL}`);
|
|
154
|
+
}
|
|
155
|
+
export function findBunBinary() {
|
|
156
|
+
const onPath = which('bun');
|
|
157
|
+
if (onPath)
|
|
158
|
+
return onPath;
|
|
159
|
+
const home = homedir();
|
|
160
|
+
const candidates = IS_WIN
|
|
161
|
+
? [join(home, '.bun', 'bin', 'bun.exe'), join(home, '.volta', 'bin', 'bun.exe')]
|
|
162
|
+
: [join(home, '.bun', 'bin', 'bun'), '/usr/local/bin/bun', join(home, '.volta', 'bin', 'bun')];
|
|
163
|
+
for (const candidate of candidates) {
|
|
164
|
+
if (existsSync(candidate))
|
|
165
|
+
return realpath(candidate);
|
|
166
|
+
}
|
|
167
|
+
return 'bun';
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=binary-finder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binary-finder.js","sourceRoot":"","sources":["../../src/patcher/binary-finder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAExD,MAAM,MAAM,GAAG,QAAQ,EAAE,KAAK,OAAO,CAAC;AACtC,MAAM,MAAM,GAAG,QAAQ,EAAE,KAAK,QAAQ,CAAC;AAEvC,SAAS,KAAK,CAAC,GAAW;IACxB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC;QAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,EAAE;YAChC,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,IAAI,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,QAAQ,CAAC,CAAS;IACzB,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB;IAC5B,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QACxE,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAChF,OAAO;YACL,IAAI,CAAC,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,CAAC;YACtD,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,YAAY,CAAC;YAClC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,QAAQ,CAAC;YAC9E,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,CAAC;SAC1C,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,OAAO;YACL,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC;YACrC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC;YACxC,uBAAuB;YACvB,0BAA0B;YAC1B,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,CAAC;YAC1C,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC;SACtC,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC;QACrC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC;QACxC,uBAAuB;QACvB,iBAAiB;QACjB,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,CAAC;QAC1C,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAe;IACzC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC1F,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;YACjC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACvC,IAAI,UAAU,CAAC,MAAM,CAAC;gBAAE,OAAO,MAAM,CAAC;QACxC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,qBAAqB,CAAC,YAAoB;IACjD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;QACnD,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAE5B,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QAC7D,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC;QACpD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC3C,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC;YACtC,IAAI,IAAI,IAAI,SAAS;gBAAE,OAAO,SAAS,CAAC;QAC1C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;QACpC,IAAI,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC/B,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;QAElC,IAAI,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;YAC5C,IAAI,MAAM;gBAAE,OAAO,MAAM,CAAC;QAC5B,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;YACrC,IAAI,IAAI,IAAI,SAAS,EAAE,CAAC;gBACtB,OAAO,QAAQ,CAAC;YAClB,CAAC;YACD,MAAM,OAAO,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;YAChD,IAAI,OAAO;gBAAE,OAAO,OAAO,CAAC;YAE5B,IAAI,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzC,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC;gBACrD,IAAI,MAAM;oBAAE,OAAO,MAAM,CAAC;YAC5B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,QAAQ,CAAC;QAClB,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,qBAAqB,EAAE,CAAC;IAE3C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1B,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,MAAM,YAAY,GAAG,MAAM;QACzB,CAAC,CAAC,4EAA4E;QAC9E,CAAC,CAAC,MAAM;YACN,CAAC,CAAC,mFAAmF;YACrF,CAAC,CAAC,wEAAwE,CAAC;IAE/E,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7D,MAAM,IAAI,KAAK,CACb,sCAAsC;QACpC,WAAW,CAAC;YACV,KAAK,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,2BAA2B;SACxE,CAAC;QACF,IAAI;QACJ,KAAK;QACL,QAAQ;QACR,YAAY;QACZ,4DAA4D;QAC5D,mDAAmD,SAAS,EAAE,CACjE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5B,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,UAAU,GAAG,MAAM;QACvB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;QAChF,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,oBAAoB,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAEjG,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { findClaudeBinary, findBunBinary } from './binary-finder.ts';
|
|
2
|
+
export { findAllOccurrences, getCurrentSalt, verifySalt, isClaudeRunning, isNodeRuntime, getMinSaltCount, } from './salt-ops.ts';
|
|
3
|
+
export { patchBinary, restoreBinary } from './patch.ts';
|
|
4
|
+
export { runPreflight } from './preflight.ts';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/patcher/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,eAAe,EACf,aAAa,EACb,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { findClaudeBinary, findBunBinary } from "./binary-finder.js";
|
|
2
|
+
export { findAllOccurrences, getCurrentSalt, verifySalt, isClaudeRunning, isNodeRuntime, getMinSaltCount, } from "./salt-ops.js";
|
|
3
|
+
export { patchBinary, restoreBinary } from "./patch.js";
|
|
4
|
+
export { runPreflight } from "./preflight.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/patcher/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,eAAe,EACf,aAAa,EACb,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { PatchResult } from '../types.js';
|
|
2
|
+
export declare function patchBinary(binaryPath: string, oldSalt: string, newSalt: string): PatchResult;
|
|
3
|
+
export declare function findRestorableBackup(binaryPath: string): string | null;
|
|
4
|
+
export declare function restoreBinary(binaryPath: string): true;
|
|
5
|
+
//# sourceMappingURL=patch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch.d.ts","sourceRoot":"","sources":["../../src/patcher/patch.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAoB9C,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,CA2E7F;AAGD,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAetE;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CA2CtD"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, copyFileSync, statSync, chmodSync, unlinkSync, renameSync, existsSync, } from 'fs';
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import { platform } from 'os';
|
|
4
|
+
import { ORIGINAL_SALT } from '../constants.js';
|
|
5
|
+
import { findAllOccurrences } from "./salt-ops.js";
|
|
6
|
+
const IS_WIN = platform() === 'win32';
|
|
7
|
+
const IS_MAC = platform() === 'darwin';
|
|
8
|
+
function codesignBinary(binaryPath) {
|
|
9
|
+
if (!IS_MAC)
|
|
10
|
+
return { signed: false, error: null };
|
|
11
|
+
try {
|
|
12
|
+
execSync(`codesign --force --sign - "${binaryPath}"`, {
|
|
13
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
14
|
+
timeout: 30000,
|
|
15
|
+
});
|
|
16
|
+
return { signed: true, error: null };
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
return { signed: false, error: err.message };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function patchBinary(binaryPath, oldSalt, newSalt) {
|
|
23
|
+
if (oldSalt.length !== newSalt.length) {
|
|
24
|
+
throw new Error(`Salt length mismatch: old=${oldSalt.length}, new=${newSalt.length}. Must be ${ORIGINAL_SALT.length} chars.`);
|
|
25
|
+
}
|
|
26
|
+
const buf = readFileSync(binaryPath);
|
|
27
|
+
const offsets = findAllOccurrences(buf, oldSalt);
|
|
28
|
+
if (offsets.length === 0) {
|
|
29
|
+
throw new Error(`Could not find salt "${oldSalt}" in binary at ${binaryPath}.\n` +
|
|
30
|
+
' The binary may already be patched with a different salt, or Claude Code has changed.\n\n' +
|
|
31
|
+
' If you think this is a bug, please report it at:\n' +
|
|
32
|
+
' https://github.com/lyellr88/buddy-mcp/issues');
|
|
33
|
+
}
|
|
34
|
+
const backupPath = binaryPath + '.buddy-mcp-bak';
|
|
35
|
+
// Only write backup if this binary has the original salt — prevents poisoning
|
|
36
|
+
// the backup with a post-update binary that's already broken.
|
|
37
|
+
if (!existsSync(backupPath) && findAllOccurrences(buf, ORIGINAL_SALT).length > 0) {
|
|
38
|
+
copyFileSync(binaryPath, backupPath);
|
|
39
|
+
}
|
|
40
|
+
const newBuf = Buffer.from(newSalt, 'utf-8');
|
|
41
|
+
for (const offset of offsets) {
|
|
42
|
+
newBuf.copy(buf, offset);
|
|
43
|
+
}
|
|
44
|
+
const stats = statSync(binaryPath);
|
|
45
|
+
const tmpPath = binaryPath + '.buddy-mcp-tmp';
|
|
46
|
+
try {
|
|
47
|
+
writeFileSync(tmpPath, buf);
|
|
48
|
+
if (!IS_WIN)
|
|
49
|
+
chmodSync(tmpPath, stats.mode);
|
|
50
|
+
try {
|
|
51
|
+
renameSync(tmpPath, binaryPath);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
try {
|
|
55
|
+
unlinkSync(binaryPath);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
/* ignore */
|
|
59
|
+
}
|
|
60
|
+
renameSync(tmpPath, binaryPath);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
try {
|
|
65
|
+
unlinkSync(tmpPath);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
/* ignore */
|
|
69
|
+
}
|
|
70
|
+
if (IS_WIN && err.code === 'EPERM') {
|
|
71
|
+
throw new Error('Cannot patch: the binary is locked (Claude Code may be running).\n' +
|
|
72
|
+
' Close all Claude Code windows and try again.');
|
|
73
|
+
}
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
const verifyBuf = readFileSync(binaryPath);
|
|
77
|
+
const verify = findAllOccurrences(verifyBuf, newSalt);
|
|
78
|
+
const cs = codesignBinary(binaryPath);
|
|
79
|
+
return {
|
|
80
|
+
replacements: offsets.length,
|
|
81
|
+
verified: verify.length === offsets.length,
|
|
82
|
+
backupPath,
|
|
83
|
+
codesigned: cs.signed,
|
|
84
|
+
codesignError: cs.error,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// Returns the best available backup path that contains ORIGINAL_SALT, or null.
|
|
88
|
+
export function findRestorableBackup(binaryPath) {
|
|
89
|
+
const candidates = [
|
|
90
|
+
binaryPath + '.buddy-mcp-bak',
|
|
91
|
+
binaryPath + '.anybuddy-bak',
|
|
92
|
+
];
|
|
93
|
+
for (const candidate of candidates) {
|
|
94
|
+
if (!existsSync(candidate))
|
|
95
|
+
continue;
|
|
96
|
+
try {
|
|
97
|
+
const buf = readFileSync(candidate);
|
|
98
|
+
if (findAllOccurrences(buf, ORIGINAL_SALT).length > 0)
|
|
99
|
+
return candidate;
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
/* skip unreadable backups */
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
export function restoreBinary(binaryPath) {
|
|
108
|
+
const backupPath = findRestorableBackup(binaryPath);
|
|
109
|
+
if (!backupPath) {
|
|
110
|
+
throw new Error('No valid backup found containing the original salt.\n' +
|
|
111
|
+
` Tried: ${binaryPath}.buddy-mcp-bak, ${binaryPath}.anybuddy-bak\n` +
|
|
112
|
+
' Try reinstalling Claude Code to get a fresh binary.');
|
|
113
|
+
}
|
|
114
|
+
const stats = statSync(backupPath);
|
|
115
|
+
const tmpPath = binaryPath + '.buddy-mcp-tmp';
|
|
116
|
+
try {
|
|
117
|
+
copyFileSync(backupPath, tmpPath);
|
|
118
|
+
if (!IS_WIN)
|
|
119
|
+
chmodSync(tmpPath, stats.mode);
|
|
120
|
+
try {
|
|
121
|
+
renameSync(tmpPath, binaryPath);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
try {
|
|
125
|
+
unlinkSync(binaryPath);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
/* ignore */
|
|
129
|
+
}
|
|
130
|
+
renameSync(tmpPath, binaryPath);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
try {
|
|
135
|
+
unlinkSync(tmpPath);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
/* ignore */
|
|
139
|
+
}
|
|
140
|
+
if (IS_WIN && err.code === 'EPERM') {
|
|
141
|
+
throw new Error('Cannot restore: the binary is locked (Claude Code may be running).\n' +
|
|
142
|
+
' Close all Claude Code windows and try again.');
|
|
143
|
+
}
|
|
144
|
+
throw err;
|
|
145
|
+
}
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=patch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch.js","sourceRoot":"","sources":["../../src/patcher/patch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../../src/patcher/preflight.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAOlD,wBAAgB,YAAY,CAAC,EAAE,aAAoB,EAAE;;CAAK,GAAG,eAAe,CAgK3E"}
|