auxilo-mcp 0.9.21 → 0.9.22
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/bin/auxilo-cli.js +2 -0
- package/lib/installer.js +25 -0
- package/mcp-server.js +1 -1
- package/package.json +1 -1
- package/scripts/providers/claude-code.js +55 -10
package/bin/auxilo-cli.js
CHANGED
|
@@ -299,6 +299,8 @@ async function cmdSetup(flags) {
|
|
|
299
299
|
console.log('');
|
|
300
300
|
try {
|
|
301
301
|
const { binRoot } = installer.installRunner(HOME);
|
|
302
|
+
const claudeBin = installer.recordClaudeBin(HOME, process.env.PATH);
|
|
303
|
+
if (claudeBin !== null) console.log(` ✓ Claude Code CLI recorded: ${claudeBin}`);
|
|
302
304
|
console.log(` ✓ Extraction runner installed to ${binRoot}`);
|
|
303
305
|
} catch (err) {
|
|
304
306
|
console.error(` ✗ Runner install failed: ${err.message}`);
|
package/lib/installer.js
CHANGED
|
@@ -1061,6 +1061,29 @@ function writeRunnerConfig(homeDir, patch) {
|
|
|
1061
1061
|
return merged;
|
|
1062
1062
|
}
|
|
1063
1063
|
|
|
1064
|
+
/** Find the first regular executable in PATH, preserving its symlink path. */
|
|
1065
|
+
function findExecutableOnPath(name, envPath, fsImpl = fs) {
|
|
1066
|
+
if (typeof envPath !== 'string' || !envPath) return null;
|
|
1067
|
+
for (const dir of envPath.split(path.delimiter)) {
|
|
1068
|
+
if (!dir) continue;
|
|
1069
|
+
const candidate = path.resolve(dir, name);
|
|
1070
|
+
try {
|
|
1071
|
+
if (!fsImpl.statSync(candidate).isFile()) continue;
|
|
1072
|
+
fsImpl.accessSync(candidate, fs.constants.X_OK);
|
|
1073
|
+
return candidate;
|
|
1074
|
+
} catch (_) { /* missing, inaccessible or non-executable — try the next entry */ }
|
|
1075
|
+
}
|
|
1076
|
+
return null;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
/** Setup only: record the user's CLI and confirm the best-effort write persisted. */
|
|
1080
|
+
function recordClaudeBin(homeDir, envPath, fsImpl = fs) {
|
|
1081
|
+
const bin = findExecutableOnPath('claude', envPath, fsImpl);
|
|
1082
|
+
if (bin === null) return null;
|
|
1083
|
+
writeRunnerConfig(homeDir, { claude_bin: bin });
|
|
1084
|
+
return readRunnerConfig(homeDir).claude_bin === bin ? bin : null;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1064
1087
|
// ─── Device-code auth (spec §LW-12 step 2; server.js /auth/device) ──────────
|
|
1065
1088
|
|
|
1066
1089
|
/**
|
|
@@ -2411,6 +2434,8 @@ module.exports = {
|
|
|
2411
2434
|
runnerConfigPath,
|
|
2412
2435
|
readRunnerConfig,
|
|
2413
2436
|
writeRunnerConfig,
|
|
2437
|
+
findExecutableOnPath,
|
|
2438
|
+
recordClaudeBin,
|
|
2414
2439
|
writeEnvFile,
|
|
2415
2440
|
deviceLogin,
|
|
2416
2441
|
binRootFor,
|
package/mcp-server.js
CHANGED
|
@@ -198,7 +198,7 @@ async function postBulkChunks(headers, decisions) {
|
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
const server = new Server(
|
|
201
|
-
{ name: 'auxilo', version: '0.9.
|
|
201
|
+
{ name: 'auxilo', version: '0.9.22' },
|
|
202
202
|
{
|
|
203
203
|
capabilities: { tools: {} },
|
|
204
204
|
instructions: `You are connected to Auxilo, a knowledge marketplace where AI agents buy and sell operational learnings.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "auxilo-mcp",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.22",
|
|
4
4
|
"mcpName": "io.github.silent-architects/auxilo",
|
|
5
5
|
"description": "MCP server for Auxilo. Your agent stops solving the same problem twice: auto-extracted learnings, free self-unlocks, and earnings when other agents unlock yours.",
|
|
6
6
|
"main": "mcp-server.js",
|
|
@@ -22,23 +22,56 @@ const fs = require('fs');
|
|
|
22
22
|
const path = require('path');
|
|
23
23
|
const os = require('os');
|
|
24
24
|
|
|
25
|
-
/**
|
|
25
|
+
/** Leading major.minor.patch only; unreadable versions retain fallback behavior. */
|
|
26
|
+
function versionParts(version) {
|
|
27
|
+
const match = typeof version === 'string' && /^(\d+)\.(\d+)\.(\d+)/.exec(version);
|
|
28
|
+
return match ? match.slice(1).map(Number) : null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function compareVersions(left, right) {
|
|
32
|
+
for (let i = 0; i < 3; i += 1) {
|
|
33
|
+
if (left[i] !== right[i]) return left[i] > right[i] ? 1 : -1;
|
|
34
|
+
}
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Resolve the newest readable CLI — hook/launchd env may have a minimal PATH. */
|
|
26
39
|
function resolveClaudeBin(opts = {}) {
|
|
27
40
|
const homeDir = typeof opts.homeDir === 'string' ? opts.homeDir : os.homedir();
|
|
28
41
|
const existsSync = typeof opts.existsSync === 'function' ? opts.existsSync : fs.existsSync;
|
|
42
|
+
const readFileSyncImpl = typeof opts.readFileSyncImpl === 'function' ? opts.readFileSyncImpl : fs.readFileSync;
|
|
29
43
|
const candidates = [
|
|
30
44
|
path.join(homeDir, '.claude', 'local', 'claude'),
|
|
31
45
|
'/usr/local/bin/claude',
|
|
32
46
|
'/opt/homebrew/bin/claude',
|
|
33
47
|
path.join(homeDir, '.local', 'bin', 'claude'),
|
|
48
|
+
path.join(homeDir, '.npm-global', 'bin', 'claude'),
|
|
34
49
|
];
|
|
50
|
+
// Read directly: the sweeper install does not include lib/installer.js.
|
|
51
|
+
try {
|
|
52
|
+
const config = JSON.parse(readFileSyncImpl(path.join(homeDir, '.auxilo', 'runner-config.json'), 'utf8'));
|
|
53
|
+
const recorded = config && config.claude_bin;
|
|
54
|
+
if (typeof recorded === 'string' && path.isAbsolute(recorded) && path.basename(recorded) === 'claude') {
|
|
55
|
+
candidates.unshift(recorded);
|
|
56
|
+
}
|
|
57
|
+
} catch (_) { /* missing/malformed config means no recorded candidate */ }
|
|
58
|
+
|
|
59
|
+
let firstExisting;
|
|
60
|
+
let newest;
|
|
61
|
+
let newestVersion;
|
|
35
62
|
for (const c of candidates) {
|
|
36
63
|
try {
|
|
37
|
-
if (existsSync(c))
|
|
64
|
+
if (!existsSync(c)) continue;
|
|
65
|
+
if (!firstExisting) firstExisting = c;
|
|
66
|
+
const version = versionParts(getClaudeCliVersion(c, opts));
|
|
67
|
+
if (version && (!newestVersion || compareVersions(version, newestVersion) > 0)) {
|
|
68
|
+
newest = c;
|
|
69
|
+
newestVersion = version;
|
|
70
|
+
}
|
|
38
71
|
} catch (_) { /* ignore */ }
|
|
39
72
|
}
|
|
40
73
|
// Absolute launchd fallbacks are absent; let PATH resolve the final option.
|
|
41
|
-
return 'claude';
|
|
74
|
+
return newest || firstExisting || 'claude';
|
|
42
75
|
}
|
|
43
76
|
|
|
44
77
|
// ─── Child settings/hooks isolation (EXTRACTION-CHILD-HOOKS, PUNCH-LIST P1,
|
|
@@ -105,27 +138,35 @@ function _resetSettingSourcesCacheForTests() {
|
|
|
105
138
|
cachedSettingSourcesUnsupported = undefined;
|
|
106
139
|
}
|
|
107
140
|
|
|
108
|
-
// ─── CLI version, for
|
|
141
|
+
// ─── CLI version, for selection, auth gating and provenance (no spawn) ──────
|
|
109
142
|
//
|
|
110
143
|
// Resolves the installed package's own package.json version by following the
|
|
111
144
|
// resolved binary's real path (e.g. `/usr/local/bin/claude` -> `.../
|
|
112
145
|
// node_modules/@anthropic-ai/claude-code/cli.js`) and reading the sibling
|
|
113
|
-
// package.json
|
|
146
|
+
// package.json, or the named parent package for the native bin/claude.exe
|
|
147
|
+
// layout — filesystem-only, so it never adds a spawn to the extraction
|
|
114
148
|
// path (verified live: realpath + package.json read, no `claude --version`
|
|
115
149
|
// call). Best-effort: any failure (bare `claude` unresolved via PATH, an
|
|
116
|
-
// install layout that doesn't carry
|
|
150
|
+
// install layout that doesn't carry either package.json, a fixture path in
|
|
117
151
|
// tests) yields null, never throws.
|
|
118
152
|
function getClaudeCliVersion(bin, opts = {}) {
|
|
119
153
|
const realpathSyncImpl = typeof opts.realpathSyncImpl === 'function' ? opts.realpathSyncImpl : fs.realpathSync;
|
|
120
154
|
const readFileSyncImpl = typeof opts.readFileSyncImpl === 'function' ? opts.readFileSyncImpl : fs.readFileSync;
|
|
121
155
|
try {
|
|
122
156
|
const real = realpathSyncImpl(bin);
|
|
123
|
-
const
|
|
124
|
-
const
|
|
125
|
-
|
|
157
|
+
const dir = path.dirname(real);
|
|
158
|
+
for (const [pkgDir, requireName] of [[dir, false], [path.dirname(dir), true]]) {
|
|
159
|
+
try {
|
|
160
|
+
const pkg = JSON.parse(readFileSyncImpl(path.join(pkgDir, 'package.json'), 'utf8'));
|
|
161
|
+
if (pkg && typeof pkg.version === 'string' && (!requireName || pkg.name === '@anthropic-ai/claude-code')) {
|
|
162
|
+
return pkg.version;
|
|
163
|
+
}
|
|
164
|
+
} catch (_) { /* unreadable sibling may still have a valid parent */ }
|
|
165
|
+
}
|
|
126
166
|
} catch {
|
|
127
|
-
|
|
167
|
+
/* unresolved binary */
|
|
128
168
|
}
|
|
169
|
+
return null;
|
|
129
170
|
}
|
|
130
171
|
|
|
131
172
|
// ─── Env scrub (EXTRACT-TOOLS-LOCK, PUNCH-LIST) ────────────────────────────
|
|
@@ -345,6 +386,10 @@ function detectBillingHelperConfigured(opts = {}) {
|
|
|
345
386
|
function checkAuthStatus(opts = {}) {
|
|
346
387
|
const spawnSyncImpl = typeof opts.spawnSyncImpl === 'function' ? opts.spawnSyncImpl : spawnSync;
|
|
347
388
|
const bin = typeof opts.claudeBin === 'string' ? opts.claudeBin : resolveClaudeBin(opts);
|
|
389
|
+
const version = versionParts(getClaudeCliVersion(bin, opts));
|
|
390
|
+
// Older CLIs treat `auth status` as a model prompt. Unknown versions retain
|
|
391
|
+
// the existing probe; only a known-old build can safely skip it here.
|
|
392
|
+
if (version && compareVersions(version, [2, 1, 41]) < 0) return 'unknown';
|
|
348
393
|
let res;
|
|
349
394
|
try {
|
|
350
395
|
res = spawnSyncImpl(bin, ['auth', 'status'], {
|