mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-09-11 22:53:04 +00:00
fix: validate invalid wiki timeout values
Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/2f7def72-828c-419c-a5db-1bf1e2f10203
This commit is contained in:
parent
d05602112e
commit
f8981ed4ff
2 changed files with 102 additions and 3 deletions
|
|
@ -37,6 +37,15 @@ export interface WikiCommandOptions {
|
|||
retries?: string;
|
||||
}
|
||||
|
||||
function parsePositiveIntegerOption(value: string | undefined, flag: string): number | undefined {
|
||||
if (value === undefined) return undefined;
|
||||
const trimmed = value.trim();
|
||||
if (!/^[1-9]\d*$/.test(trimmed)) {
|
||||
throw new Error(`${flag} must be a positive integer`);
|
||||
}
|
||||
return parseInt(trimmed, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt the user for input via stdin.
|
||||
*/
|
||||
|
|
@ -127,6 +136,15 @@ export const wikiCommand = async (inputPath?: string, options?: WikiCommandOptio
|
|||
return;
|
||||
}
|
||||
|
||||
let timeoutSeconds: number | undefined;
|
||||
try {
|
||||
timeoutSeconds = parsePositiveIntegerOption(options?.timeout, '--timeout');
|
||||
} catch (error) {
|
||||
console.log(` Error: ${(error as Error).message}\n`);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// ── Resolve LLM config (with interactive fallback) ─────────────────
|
||||
// Save any CLI overrides immediately
|
||||
if (
|
||||
|
|
@ -350,9 +368,8 @@ export const wikiCommand = async (inputPath?: string, options?: WikiCommandOptio
|
|||
}
|
||||
|
||||
// ── Apply per-run overrides not saved to config ────────────────────
|
||||
if (options?.timeout) {
|
||||
const secs = parseInt(options.timeout, 10);
|
||||
if (!isNaN(secs) && secs > 0) llmConfig.requestTimeoutMs = secs * 1000;
|
||||
if (timeoutSeconds !== undefined) {
|
||||
llmConfig.requestTimeoutMs = timeoutSeconds * 1000;
|
||||
}
|
||||
if (options?.retries) {
|
||||
const n = parseInt(options.retries, 10);
|
||||
|
|
|
|||
|
|
@ -264,6 +264,88 @@ describe('WikiGenerator --review mode', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('wikiCommand --timeout validation', () => {
|
||||
const originalExitCode = process.exitCode;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
process.exitCode = undefined;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
vi.doUnmock('../../src/storage/git.js');
|
||||
vi.doUnmock('../../src/storage/repo-manager.js');
|
||||
vi.doUnmock('../../src/core/wiki/llm-client.js');
|
||||
vi.doUnmock('../../src/core/wiki/generator.js');
|
||||
vi.doUnmock('cli-progress');
|
||||
process.exitCode = originalExitCode;
|
||||
});
|
||||
|
||||
it.each(['0', '-1', 'abc'])(
|
||||
'rejects invalid --timeout value %s before starting generation',
|
||||
async (timeout) => {
|
||||
const generatorCtor = vi.fn().mockImplementation(() => ({
|
||||
run: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.doMock('../../src/storage/git.js', () => ({
|
||||
getGitRoot: vi.fn(),
|
||||
isGitRepo: vi.fn().mockReturnValue(true),
|
||||
}));
|
||||
vi.doMock('../../src/storage/repo-manager.js', () => ({
|
||||
getStoragePaths: vi
|
||||
.fn()
|
||||
.mockReturnValue({ storagePath: '/tmp/wiki-storage', lbugPath: '/tmp/wiki-db' }),
|
||||
loadMeta: vi.fn().mockResolvedValue({ createdAt: '2026-01-01T00:00:00Z' }),
|
||||
loadCLIConfig: vi.fn().mockResolvedValue({
|
||||
apiKey: 'sk-test',
|
||||
baseUrl: 'https://api.openai.com/v1',
|
||||
model: 'gpt-4o',
|
||||
provider: 'openai',
|
||||
}),
|
||||
saveCLIConfig: vi.fn(),
|
||||
}));
|
||||
vi.doMock('../../src/core/wiki/llm-client.js', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('../../src/core/wiki/llm-client.js')>();
|
||||
return {
|
||||
...actual,
|
||||
resolveLLMConfig: vi.fn().mockResolvedValue({
|
||||
apiKey: 'sk-test',
|
||||
baseUrl: 'https://api.openai.com/v1',
|
||||
model: 'gpt-4o',
|
||||
maxTokens: 16_384,
|
||||
temperature: 0,
|
||||
provider: 'openai',
|
||||
}),
|
||||
};
|
||||
});
|
||||
vi.doMock('../../src/core/wiki/generator.js', () => ({
|
||||
WikiGenerator: generatorCtor,
|
||||
}));
|
||||
vi.doMock('cli-progress', () => ({
|
||||
default: {
|
||||
SingleBar: vi.fn().mockImplementation(() => ({
|
||||
start: vi.fn(),
|
||||
update: vi.fn(),
|
||||
stop: vi.fn(),
|
||||
})),
|
||||
Presets: { shades_grey: {} },
|
||||
},
|
||||
}));
|
||||
|
||||
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
const { wikiCommand } = await import('../../src/cli/wiki.js');
|
||||
|
||||
await wikiCommand('/tmp/repo', { timeout });
|
||||
|
||||
expect(process.exitCode).toBe(1);
|
||||
expect(generatorCtor).not.toHaveBeenCalled();
|
||||
expect(consoleSpy).toHaveBeenCalledWith(' Error: --timeout must be a positive integer\n');
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
// ─── CLI config round-trip with cursor provider ──────────────────────
|
||||
|
||||
describe('CLI config round-trip with cursor provider', () => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue