summaryrefslogtreecommitdiffhomepage
path: root/packages/cli
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli')
-rw-r--r--packages/cli/src/args.test.ts33
-rw-r--r--packages/cli/src/args.ts17
-rw-r--r--packages/cli/src/http.test.ts12
-rw-r--r--packages/cli/src/main.ts5
-rw-r--r--packages/cli/src/message.test.ts50
-rw-r--r--packages/cli/src/message.ts2
-rw-r--r--packages/cli/src/render.test.ts1
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", () => {