- Added maintenance module to the agent-teams-controller, enabling the reconciliation of stale kanban entries and linked inbox comments. - Implemented garbage collection logic in kanbanStore to remove invalid task references and clean up column orders. - Updated controller to expose maintenance functionalities, allowing for better task and comment management. - Enhanced tests to validate the new reconciliation process, ensuring idempotency and correctness in handling stale data. - Integrated new CLI argument options for worktree and custom arguments in team launch and creation dialogs, improving user flexibility.
152 lines
4.8 KiB
TypeScript
152 lines
4.8 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
extractFlagsFromHelp,
|
|
extractUserFlags,
|
|
parseCliArgs,
|
|
PROTECTED_CLI_FLAGS,
|
|
} from '@shared/utils/cliArgsParser';
|
|
|
|
describe('parseCliArgs', () => {
|
|
it('returns empty array for undefined', () => {
|
|
expect(parseCliArgs(undefined)).toEqual([]);
|
|
});
|
|
|
|
it('returns empty array for empty string', () => {
|
|
expect(parseCliArgs('')).toEqual([]);
|
|
});
|
|
|
|
it('splits simple flags and values', () => {
|
|
expect(parseCliArgs('--verbose --max-turns 5')).toEqual(['--verbose', '--max-turns', '5']);
|
|
});
|
|
|
|
it('handles double-quoted strings', () => {
|
|
expect(parseCliArgs('--message "hello world"')).toEqual(['--message', 'hello world']);
|
|
});
|
|
|
|
it('handles single-quoted strings', () => {
|
|
expect(parseCliArgs("--message 'it works'")).toEqual(['--message', 'it works']);
|
|
});
|
|
|
|
it('trims leading/trailing whitespace', () => {
|
|
expect(parseCliArgs(' --verbose ')).toEqual(['--verbose']);
|
|
});
|
|
|
|
it('handles multiple consecutive spaces', () => {
|
|
expect(parseCliArgs('--foo --bar baz')).toEqual(['--foo', '--bar', 'baz']);
|
|
});
|
|
|
|
it('handles tabs as separators', () => {
|
|
expect(parseCliArgs('--foo\t--bar')).toEqual(['--foo', '--bar']);
|
|
});
|
|
|
|
it('handles mixed quotes', () => {
|
|
expect(parseCliArgs(`--a "hello 'inner'" --b 'world "nested"'`)).toEqual([
|
|
'--a',
|
|
"hello 'inner'",
|
|
'--b',
|
|
'world "nested"',
|
|
]);
|
|
});
|
|
|
|
it('handles short flags', () => {
|
|
expect(parseCliArgs('-p "prompt text" -w name')).toEqual(['-p', 'prompt text', '-w', 'name']);
|
|
});
|
|
|
|
it('handles flag=value format', () => {
|
|
expect(parseCliArgs('--model=opus-4')).toEqual(['--model=opus-4']);
|
|
});
|
|
|
|
it('handles empty quoted strings', () => {
|
|
expect(parseCliArgs('--value ""')).toEqual(['--value', '']);
|
|
});
|
|
});
|
|
|
|
describe('extractFlagsFromHelp', () => {
|
|
const SAMPLE_HELP = `
|
|
Usage: claude [options] [prompt]
|
|
|
|
Options:
|
|
-p, --print Print response without interactive mode
|
|
-w, --worktree [name] Run in a git worktree
|
|
--model <model> Specify the model to use
|
|
--max-turns <number> Maximum conversation turns
|
|
--verbose Enable verbose logging
|
|
--dangerously-skip-permissions Skip permission checks
|
|
--input-format <format> Input format (text, stream-json)
|
|
--output-format <format> Output format
|
|
--no-session-persistence Don't persist session
|
|
-h, --help Display this help
|
|
-V, --version Display version
|
|
|
|
For more information, visit https://docs.anthropic.com
|
|
This is a non-interactive tool for automated workflows.
|
|
`;
|
|
|
|
it('extracts long flags', () => {
|
|
const flags = extractFlagsFromHelp(SAMPLE_HELP);
|
|
expect(flags.has('--model')).toBe(true);
|
|
expect(flags.has('--max-turns')).toBe(true);
|
|
expect(flags.has('--verbose')).toBe(true);
|
|
expect(flags.has('--dangerously-skip-permissions')).toBe(true);
|
|
expect(flags.has('--input-format')).toBe(true);
|
|
expect(flags.has('--output-format')).toBe(true);
|
|
expect(flags.has('--no-session-persistence')).toBe(true);
|
|
expect(flags.has('--worktree')).toBe(true);
|
|
});
|
|
|
|
it('extracts short flags', () => {
|
|
const flags = extractFlagsFromHelp(SAMPLE_HELP);
|
|
expect(flags.has('-p')).toBe(true);
|
|
expect(flags.has('-w')).toBe(true);
|
|
expect(flags.has('-h')).toBe(true);
|
|
expect(flags.has('-V')).toBe(true);
|
|
});
|
|
|
|
it('does not match hyphens in regular text', () => {
|
|
const flags = extractFlagsFromHelp(SAMPLE_HELP);
|
|
// "non-interactive" should not produce --non or -n from hyphenated words
|
|
expect(flags.has('--non')).toBe(false);
|
|
});
|
|
|
|
it('returns empty set for empty input', () => {
|
|
expect(extractFlagsFromHelp('').size).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe('extractUserFlags', () => {
|
|
it('extracts flags from mixed input', () => {
|
|
expect(extractUserFlags('--verbose --max-turns 5 foo')).toEqual([
|
|
'--verbose',
|
|
'--max-turns',
|
|
]);
|
|
});
|
|
|
|
it('extracts short flags', () => {
|
|
expect(extractUserFlags('-p -w')).toEqual(['-p', '-w']);
|
|
});
|
|
|
|
it('returns empty for empty string', () => {
|
|
expect(extractUserFlags('')).toEqual([]);
|
|
});
|
|
|
|
it('returns empty when no flags present', () => {
|
|
expect(extractUserFlags('hello world')).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('PROTECTED_CLI_FLAGS', () => {
|
|
it('contains expected flags', () => {
|
|
expect(PROTECTED_CLI_FLAGS.has('--input-format')).toBe(true);
|
|
expect(PROTECTED_CLI_FLAGS.has('--output-format')).toBe(true);
|
|
expect(PROTECTED_CLI_FLAGS.has('--mcp-config')).toBe(true);
|
|
expect(PROTECTED_CLI_FLAGS.has('--disallowedTools')).toBe(true);
|
|
expect(PROTECTED_CLI_FLAGS.has('--verbose')).toBe(true);
|
|
});
|
|
|
|
it('does not contain user-facing flags', () => {
|
|
expect(PROTECTED_CLI_FLAGS.has('--model')).toBe(false);
|
|
expect(PROTECTED_CLI_FLAGS.has('--effort')).toBe(false);
|
|
expect(PROTECTED_CLI_FLAGS.has('--worktree')).toBe(false);
|
|
});
|
|
});
|