diff options
| author | Adam Malczewski <[email protected]> | 2026-06-05 21:20:34 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-05 21:20:34 +0900 |
| commit | 552c22d74e5df915088d9e9ff4a286c96c2a54d6 (patch) | |
| tree | 7d9db1052bab91ef994446d80efc3bfc38026cad /packages/cli/src/args.ts | |
| parent | 7fb3269c698ae583ea7997ce206c4ae252fd3218 (diff) | |
| download | dispatch-552c22d74e5df915088d9e9ff4a286c96c2a54d6.tar.gz dispatch-552c22d74e5df915088d9e9ff4a286c96c2a54d6.zip | |
feat(cli): one-shot terminal client (models, chat, --text/--file/--cwd/--conversation)
HTTP client of transport-contract; pure-core arg/render/ndjson + injected fetch/fs shell.
Docs: GLOSSARY (credential/key/model name/model catalog), tasks.md milestone, ORCHESTRATOR geography.
Diffstat (limited to 'packages/cli/src/args.ts')
| -rw-r--r-- | packages/cli/src/args.ts | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/packages/cli/src/args.ts b/packages/cli/src/args.ts new file mode 100644 index 0000000..2c554e8 --- /dev/null +++ b/packages/cli/src/args.ts @@ -0,0 +1,108 @@ +/** + * Pure argument parser — zero I/O, zero ambient state. + * + * Parses process.argv-style strings into a discriminated command union. + * Validates required flags and reports unknown flags as errors. + */ + +export type ParsedCommand = + | { readonly kind: "models"; readonly server: string } + | { + readonly kind: "chat"; + readonly server: string; + readonly modelName: string; + readonly text?: string | undefined; + readonly file?: string | undefined; + readonly cwd?: string | undefined; + readonly conversationId?: string | undefined; + readonly showReasoning: boolean; + } + | { readonly kind: "help" } + | { readonly kind: "error"; readonly message: string }; + +interface ParseOpts { + readonly defaultServer: string; +} + +export function parseArgs(argv: readonly string[], opts: ParseOpts): ParsedCommand { + if (argv.length === 0) { + return { kind: "help" }; + } + + const first = argv[0] as string; + + if (first === "--help" || first === "-h") { + return { kind: "help" }; + } + + if (first === "models") { + let server = opts.defaultServer; + for (let i = 1; i < argv.length; i++) { + if (argv[i] === "--server" && i + 1 < argv.length) { + server = argv[++i] as string; + } else { + return { kind: "error", message: `Unknown argument for 'models': ${argv[i]}` }; + } + } + return { kind: "models", server }; + } + + // Chat mode: first arg is the model name + const modelName = first; + let text: string | undefined; + let file: string | undefined; + let cwd: string | undefined; + let conversationId: string | undefined; + let showReasoning = false; + let server = opts.defaultServer; + + for (let i = 1; i < argv.length; i++) { + const arg = argv[i] as string; + switch (arg) { + case "--text": + if (i + 1 >= argv.length) return { kind: "error", message: "--text requires a value" }; + text = argv[++i]; + break; + case "--file": + if (i + 1 >= argv.length) return { kind: "error", message: "--file requires a value" }; + file = argv[++i]; + break; + case "--cwd": + if (i + 1 >= argv.length) return { kind: "error", message: "--cwd requires a value" }; + cwd = argv[++i]; + break; + case "--conversation": + if (i + 1 >= argv.length) + return { kind: "error", message: "--conversation requires a value" }; + conversationId = argv[++i]; + break; + case "--server": + if (i + 1 >= argv.length) return { kind: "error", message: "--server requires a value" }; + server = argv[++i] as string; + break; + case "--show-reasoning": + showReasoning = true; + break; + default: + return { kind: "error", message: `Unknown flag: ${arg}` }; + } + } + + if (!text && !file) { + return { + kind: "error", + message: "At least one of --text or --file is required for a chat command", + }; + } + + return { + kind: "chat", + server, + modelName, + text, + file, + cwd, + conversationId, + showReasoning, + }; +} |
