diff options
Diffstat (limited to 'packages/cli')
| -rw-r--r-- | packages/cli/src/args.test.ts | 33 | ||||
| -rw-r--r-- | packages/cli/src/args.ts | 17 | ||||
| -rw-r--r-- | packages/cli/src/http.test.ts | 12 | ||||
| -rw-r--r-- | packages/cli/src/main.ts | 5 | ||||
| -rw-r--r-- | packages/cli/src/message.test.ts | 50 | ||||
| -rw-r--r-- | packages/cli/src/message.ts | 2 | ||||
| -rw-r--r-- | packages/cli/src/render.test.ts | 1 |
7 files changed, 117 insertions, 3 deletions
diff --git a/packages/cli/src/args.test.ts b/packages/cli/src/args.test.ts index 992d09f..3d07c96 100644 --- a/packages/cli/src/args.test.ts +++ b/packages/cli/src/args.test.ts @@ -52,6 +52,7 @@ describe("parseArgs", () => { reasoningEffort: undefined, showReasoning: false, open: false, + workspaceId: undefined, }); }); @@ -68,6 +69,7 @@ describe("parseArgs", () => { reasoningEffort: undefined, showReasoning: false, open: false, + workspaceId: undefined, }); }); @@ -103,6 +105,7 @@ describe("parseArgs", () => { reasoningEffort: undefined, showReasoning: true, open: false, + workspaceId: undefined, }); }); @@ -119,6 +122,7 @@ describe("parseArgs", () => { reasoningEffort: "high", showReasoning: false, open: false, + workspaceId: undefined, }); }); @@ -183,6 +187,35 @@ describe("parseArgs", () => { const result = parseArgs(["m", "--text", "x", "--conversation"], { defaultServer }); expect(result.kind).toBe("error"); }); + + it("parses --workspace flag", () => { + const result = parseArgs(["m", "--text", "x", "--workspace", "my-work"], { defaultServer }); + expect(result).toEqual({ + kind: "chat", + server: "http://localhost:24203", + modelName: "m", + text: "x", + file: undefined, + cwd: undefined, + conversationId: undefined, + reasoningEffort: undefined, + showReasoning: false, + open: false, + workspaceId: "my-work", + }); + }); + + it("parses -w shorthand", () => { + const result = parseArgs(["m", "--text", "x", "-w", "ws"], { defaultServer }); + expect(result.kind).toBe("chat"); + if (result.kind === "chat") expect(result.workspaceId).toBe("ws"); + }); + + it("errors when --workspace has no value", () => { + const result = parseArgs(["m", "--text", "x", "--workspace"], { defaultServer }); + expect(result.kind).toBe("error"); + if (result.kind === "error") expect(result.message).toContain("--workspace requires a value"); + }); }); describe("list", () => { diff --git a/packages/cli/src/args.ts b/packages/cli/src/args.ts index ac5dd4a..8a63777 100644 --- a/packages/cli/src/args.ts +++ b/packages/cli/src/args.ts @@ -26,6 +26,7 @@ export type ParsedCommand = readonly reasoningEffort?: ReasoningEffort | undefined; readonly showReasoning: boolean; readonly open: boolean; + readonly workspaceId?: string | undefined; } | { readonly kind: "list"; @@ -46,6 +47,7 @@ export type ParsedCommand = readonly open: boolean; readonly cwd?: string; readonly reasoningEffort?: ReasoningEffort; + readonly workspaceId?: string; } | { readonly kind: "stop"; readonly server: string; readonly conversationId: string } | { readonly kind: "help" } @@ -206,6 +208,7 @@ export function parseArgs(argv: readonly string[], opts: ParseOpts): ParsedComma let open = false; let cwd: string | undefined; let reasoningEffort: ReasoningEffort | undefined; + let workspaceId: string | undefined; for (let i = 1; i < argv.length; i++) { const arg = argv[i] as string; @@ -243,6 +246,12 @@ export function parseArgs(argv: readonly string[], opts: ParseOpts): ParsedComma reasoningEffort = val; break; } + case "--workspace": + case "-w": + if (i + 1 >= argv.length) + return { kind: "error", message: "--workspace requires a value" }; + workspaceId = argv[++i]; + break; default: if (arg.startsWith("--")) return { kind: "error", message: `Unknown flag: ${arg}` }; if (conversationId !== undefined) @@ -267,6 +276,7 @@ export function parseArgs(argv: readonly string[], opts: ParseOpts): ParsedComma open, ...(cwd !== undefined && { cwd }), ...(reasoningEffort !== undefined && { reasoningEffort }), + ...(workspaceId !== undefined && { workspaceId }), }; } @@ -280,6 +290,7 @@ export function parseArgs(argv: readonly string[], opts: ParseOpts): ParsedComma let showReasoning = false; let open = false; let server = opts.defaultServer; + let workspaceId: string | undefined; for (let i = 1; i < argv.length; i++) { const arg = argv[i] as string; @@ -327,6 +338,11 @@ export function parseArgs(argv: readonly string[], opts: ParseOpts): ParsedComma reasoningEffort = val; } break; + case "--workspace": + case "-w": + if (i + 1 >= argv.length) return { kind: "error", message: "--workspace requires a value" }; + workspaceId = argv[++i]; + break; default: return { kind: "error", message: `Unknown flag: ${arg}` }; } @@ -350,5 +366,6 @@ export function parseArgs(argv: readonly string[], opts: ParseOpts): ParsedComma reasoningEffort, showReasoning, open, + ...(workspaceId !== undefined && { workspaceId }), }; } diff --git a/packages/cli/src/http.test.ts b/packages/cli/src/http.test.ts index 3e7befe..2aa61e9 100644 --- a/packages/cli/src/http.test.ts +++ b/packages/cli/src/http.test.ts @@ -252,7 +252,14 @@ describe("fetchConversations", () => { let calledUrl: string | undefined; const list: ConversationListResponse = { conversations: [ - { id: "abcdef1234567890", title: "first", createdAt: 1, lastActivityAt: 2, status: "idle" }, + { + id: "abcdef1234567890", + title: "first", + createdAt: 1, + lastActivityAt: 2, + status: "idle", + workspaceId: "default", + }, ], }; const fakeFetch = (async (url: string | URL | Request): Promise<Response> => { @@ -408,6 +415,7 @@ describe("resolveConversationId", () => { createdAt: 1, lastActivityAt: 2, status: "idle", + workspaceId: "default", }, ], }); @@ -440,6 +448,7 @@ describe("resolveConversationId", () => { createdAt: 1, lastActivityAt: 2, status: "idle", + workspaceId: "default", }, { id: "abcdef1234567890bbbbbbbbbbbbbbbb", @@ -447,6 +456,7 @@ describe("resolveConversationId", () => { createdAt: 1, lastActivityAt: 3, status: "idle", + workspaceId: "default", }, ], }); diff --git a/packages/cli/src/main.ts b/packages/cli/src/main.ts index 5935bab..9dfc317 100644 --- a/packages/cli/src/main.ts +++ b/packages/cli/src/main.ts @@ -29,8 +29,8 @@ const USAGE = `Usage: dispatch compact <conversationId> [--server <url>] dispatch read <conversationId> [--server <url>] dispatch open <conversationId> [--server <url>] - dispatch send <conversationId> --text "..." [--queue] [--open] [--cwd <dir>] [--effort <level>] [--server <url>] - dispatch <modelName> --text "..." [--file <path>] [--cwd <dir>] [--conversation <id>] [--effort <level>] [--server <url>] [--show-reasoning] [--open] + dispatch send <conversationId> --text "..." [--queue] [--open] [--cwd <dir>] [--effort <level>] [--workspace <id>] [--server <url>] + dispatch <modelName> --text "..." [--file <path>] [--cwd <dir>] [--conversation <id>] [--effort <level>] [--workspace <id>] [--server <url>] [--show-reasoning] [--open] dispatch --help Effort levels: low, medium, high (default), xhigh, max`; @@ -171,6 +171,7 @@ async function main(): Promise<void> { message: parsed.text, ...(parsed.cwd !== undefined && { cwd: parsed.cwd }), ...(parsed.reasoningEffort !== undefined && { reasoningEffort: parsed.reasoningEffort }), + ...(parsed.workspaceId !== undefined && { workspaceId: parsed.workspaceId }), }; const { events } = await streamChat( { fetchImpl: globalThis.fetch }, diff --git a/packages/cli/src/message.test.ts b/packages/cli/src/message.test.ts index a3f1e0b..440ec85 100644 --- a/packages/cli/src/message.test.ts +++ b/packages/cli/src/message.test.ts @@ -1,4 +1,5 @@ import { describe, expect, it } from "vitest"; +import { parseArgs } from "./args.js"; import { buildChatRequest, composeMessage } from "./message.js"; describe("composeMessage", () => { @@ -94,4 +95,53 @@ describe("buildChatRequest", () => { ); expect(req).not.toHaveProperty("reasoningEffort"); }); + + it("includes workspaceId when provided", () => { + const req = buildChatRequest( + { modelName: "m", text: "x", workspaceId: "my-work", showReasoning: false }, + { cwd: "/work", message: "x" }, + ); + expect(req.workspaceId).toBe("my-work"); + }); + + it("omits workspaceId when not provided", () => { + const req = buildChatRequest( + { modelName: "m", text: "x", showReasoning: false }, + { cwd: "/work", message: "x" }, + ); + expect(req).not.toHaveProperty("workspaceId"); + }); +}); + +describe("workspace flag → ChatRequest", () => { + const defaultServer = "http://localhost:24203"; + + it("--workspace flag sets workspaceId on request", () => { + const parsed = parseArgs(["my-model", "--text", "hi", "--workspace", "my-work"], { + defaultServer, + }); + expect(parsed.kind).toBe("chat"); + if (parsed.kind !== "chat") return; + const req = buildChatRequest(parsed, { cwd: "/work", message: "hi" }); + expect(req.workspaceId).toBe("my-work"); + }); + + it("--workspace flag omitted sends no workspaceId", () => { + const parsed = parseArgs(["my-model", "--text", "hi"], { defaultServer }); + expect(parsed.kind).toBe("chat"); + if (parsed.kind !== "chat") return; + const req = buildChatRequest(parsed, { cwd: "/work", message: "hi" }); + expect(req.workspaceId).toBeUndefined(); + expect(req).not.toHaveProperty("workspaceId"); + }); + + it("-w shorthand sets workspaceId on request", () => { + const parsed = parseArgs(["my-model", "--text", "hi", "-w", "shorthand"], { + defaultServer, + }); + expect(parsed.kind).toBe("chat"); + if (parsed.kind !== "chat") return; + const req = buildChatRequest(parsed, { cwd: "/work", message: "hi" }); + expect(req.workspaceId).toBe("shorthand"); + }); }); diff --git a/packages/cli/src/message.ts b/packages/cli/src/message.ts index 80befec..ec4d6d1 100644 --- a/packages/cli/src/message.ts +++ b/packages/cli/src/message.ts @@ -38,6 +38,7 @@ interface ChatCmd { readonly cwd?: string | undefined; readonly conversationId?: string | undefined; readonly reasoningEffort?: ReasoningEffort | undefined; + readonly workspaceId?: string | undefined; readonly showReasoning: boolean; } @@ -53,5 +54,6 @@ export function buildChatRequest(cmd: ChatCmd, ctx: BuildCtx): ChatRequest { ...(cmd.conversationId !== undefined && { conversationId: cmd.conversationId }), ...(cmd.cwd !== undefined ? { cwd: cmd.cwd } : { cwd: ctx.cwd }), ...(cmd.reasoningEffort !== undefined && { reasoningEffort: cmd.reasoningEffort }), + ...(cmd.workspaceId !== undefined && { workspaceId: cmd.workspaceId }), }; } diff --git a/packages/cli/src/render.test.ts b/packages/cli/src/render.test.ts index eb89300..1c92733 100644 --- a/packages/cli/src/render.test.ts +++ b/packages/cli/src/render.test.ts @@ -230,6 +230,7 @@ describe("formatConversationList", () => { createdAt: now - ageMs - 1000, lastActivityAt: now - ageMs, status: "idle", + workspaceId: "default", }); it("returns empty string for an empty list", () => { |
