mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-06 23:49:41 +02:00
fix(doctor): resolve CLIs via searchDirs, single-flight runs, admin-gate the group (#536 review)
- doctor probes each CLI's discovery.searchDirs when which misses and runs --version on the resolved path, so a service with a minimal PATH no longer reports installed CLIs as missing - GET /api/doctor shares one in-flight run per category - Diagnostics group hidden from non-admins in multi-user mode (_applyDoctorAdminGate) - 500 uses INTERNAL_ERROR; a killed child reports 'timed out after 30 s' - browser test blocks service workers so page.route() is reliable - wiki: Diagnostics sentence Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JrzFKEdBLwVfu6ev2ZscJS
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
1b89d7a387
commit
db9a39405b
@@ -1,4 +1,4 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { dependencyRegistry } from '../src/config/dependency-registry.js';
|
||||
import {
|
||||
detectEnvironment,
|
||||
@@ -259,6 +259,53 @@ describe('checkTool with requireVersionMatch (generic binary names)', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkTool with searchDirs (service PATH is minimal)', () => {
|
||||
const claudeLike: ToolDependency = {
|
||||
...tmuxTool,
|
||||
id: 'claude',
|
||||
label: 'Claude CLI',
|
||||
resolvers: [
|
||||
{
|
||||
match: ['linux'],
|
||||
resolver: { kind: 'path', bins: ['claude'], searchDirs: ['/home/u/.local/bin', '/opt/npm/bin/'] },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
it('finds a CLI that only lives in a searchDirs entry and runs --version on the absolute path', () => {
|
||||
const runVersion = vi.fn(() => 'claude 2.1.0');
|
||||
const host = fakeHost('linux', { fileExists: (p) => p === '/opt/npm/bin/claude', runVersion });
|
||||
expect(checkTool(claudeLike, host)).toMatchObject({
|
||||
status: 'ok',
|
||||
path: '/opt/npm/bin/claude',
|
||||
version: '2.1.0',
|
||||
});
|
||||
expect(runVersion).toHaveBeenCalledWith('/opt/npm/bin/claude', ['--version']);
|
||||
});
|
||||
|
||||
it('still reports missing when neither PATH nor any search dir has it', () => {
|
||||
expect(checkTool(claudeLike, fakeHost('linux'))).toMatchObject({ status: 'missing' });
|
||||
});
|
||||
|
||||
it('prefers the PATH hit over a search dir', () => {
|
||||
const host = fakeHost('linux', {
|
||||
which: () => '/usr/bin/claude',
|
||||
fileExists: () => true,
|
||||
runVersion: () => '1.0.0',
|
||||
});
|
||||
expect(checkTool(claudeLike, host)).toMatchObject({ path: '/usr/bin/claude' });
|
||||
});
|
||||
|
||||
it('carries each enabled CLI’s expanded discovery.searchDirs onto its registry row', () => {
|
||||
const rows = dependencyRegistry().flatMap((t) => t.resolvers.map((r) => r.resolver));
|
||||
const withDirs = rows.filter((r) => r.kind === 'path' && r.searchDirs?.length);
|
||||
expect(withDirs.length).toBeGreaterThan(0);
|
||||
for (const r of withDirs) {
|
||||
if (r.kind === 'path') for (const d of r.searchDirs ?? []) expect(d.startsWith('~')).toBe(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkAll', () => {
|
||||
it('maps every tool to a result', () => {
|
||||
const results = checkAll([tmuxTool, msTool], fakeHost('linux'));
|
||||
|
||||
Reference in New Issue
Block a user