@teammates/cli 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli-args.js CHANGED
@@ -97,28 +97,28 @@ export async function resolveAdapter(name, opts = {}) {
97
97
  }
98
98
  // ─── Usage ───────────────────────────────────────────────────────────
99
99
  export function printUsage() {
100
- console.log(`
101
- ${chalk.bold("@teammates/cli")} — Agent-agnostic teammate orchestrator
102
-
103
- ${chalk.bold("Usage:")}
104
- teammates <agent> Launch session with an agent
105
- teammates codex Use OpenAI Codex
106
- teammates aider Use Aider
107
-
108
- ${chalk.bold("Options:")}
109
- --model <model> Override the agent model
110
- --dir <path> Override .teammates/ location
111
-
112
- ${chalk.bold("Agents:")}
113
- claude Claude Code CLI (requires 'claude' on PATH)
114
- codex OpenAI Codex CLI (requires 'codex' on PATH)
115
- aider Aider CLI (requires 'aider' on PATH)
116
- echo Test adapter — echoes prompts (no external agent)
117
-
118
- ${chalk.bold("In-session:")}
119
- @teammate <task> Assign directly via @mention
120
- <text> Auto-route to the best teammate
121
- /status Session overview
122
- /help All commands
100
+ console.log(`
101
+ ${chalk.bold("@teammates/cli")} — Agent-agnostic teammate orchestrator
102
+
103
+ ${chalk.bold("Usage:")}
104
+ teammates <agent> Launch session with an agent
105
+ teammates codex Use OpenAI Codex
106
+ teammates aider Use Aider
107
+
108
+ ${chalk.bold("Options:")}
109
+ --model <model> Override the agent model
110
+ --dir <path> Override .teammates/ location
111
+
112
+ ${chalk.bold("Agents:")}
113
+ claude Claude Code CLI (requires 'claude' on PATH)
114
+ codex OpenAI Codex CLI (requires 'codex' on PATH)
115
+ aider Aider CLI (requires 'aider' on PATH)
116
+ echo Test adapter — echoes prompts (no external agent)
117
+
118
+ ${chalk.bold("In-session:")}
119
+ @teammate <task> Assign directly via @mention
120
+ <text> Auto-route to the best teammate
121
+ /status Session overview
122
+ /help All commands
123
123
  `.trim());
124
124
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,125 @@
1
+ import { mkdir, rm } from "node:fs/promises";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
5
+ import { findTeammatesDir, PKG_VERSION, parseCliArgs, printUsage, } from "./cli-args.js";
6
+ describe("parseCliArgs", () => {
7
+ it("returns defaults with no arguments", () => {
8
+ const result = parseCliArgs([]);
9
+ expect(result).toEqual({
10
+ showHelp: false,
11
+ modelOverride: undefined,
12
+ dirOverride: undefined,
13
+ adapterName: "echo",
14
+ agentPassthrough: [],
15
+ });
16
+ });
17
+ it("parses --help flag", () => {
18
+ const result = parseCliArgs(["--help"]);
19
+ expect(result.showHelp).toBe(true);
20
+ });
21
+ it("parses --model option with value", () => {
22
+ const result = parseCliArgs(["--model", "gpt-4"]);
23
+ expect(result.modelOverride).toBe("gpt-4");
24
+ });
25
+ it("parses --dir option with value", () => {
26
+ const result = parseCliArgs(["--dir", "/custom/path"]);
27
+ expect(result.dirOverride).toBe("/custom/path");
28
+ });
29
+ it("extracts adapter name as first positional argument", () => {
30
+ const result = parseCliArgs(["claude"]);
31
+ expect(result.adapterName).toBe("claude");
32
+ });
33
+ it("passes remaining args as agentPassthrough", () => {
34
+ const result = parseCliArgs(["claude", "--verbose", "--debug"]);
35
+ expect(result.adapterName).toBe("claude");
36
+ expect(result.agentPassthrough).toEqual(["--verbose", "--debug"]);
37
+ });
38
+ it("handles all options together", () => {
39
+ const result = parseCliArgs([
40
+ "--help",
41
+ "--model",
42
+ "sonnet",
43
+ "--dir",
44
+ "/tmp/tm",
45
+ "codex",
46
+ "--extra",
47
+ ]);
48
+ expect(result.showHelp).toBe(true);
49
+ expect(result.modelOverride).toBe("sonnet");
50
+ expect(result.dirOverride).toBe("/tmp/tm");
51
+ expect(result.adapterName).toBe("codex");
52
+ expect(result.agentPassthrough).toEqual(["--extra"]);
53
+ });
54
+ it("does not consume --model when no value follows", () => {
55
+ const result = parseCliArgs(["--model"]);
56
+ // getOption finds --model but no value after it, so it's left in args
57
+ // args.shift() then picks it up as the adapter name
58
+ expect(result.modelOverride).toBeUndefined();
59
+ expect(result.adapterName).toBe("--model");
60
+ });
61
+ it("does not treat --help value as an option value", () => {
62
+ const result = parseCliArgs(["--help", "claude"]);
63
+ expect(result.showHelp).toBe(true);
64
+ expect(result.adapterName).toBe("claude");
65
+ });
66
+ });
67
+ // ── PKG_VERSION ────────────────────────────────────────────────────
68
+ describe("PKG_VERSION", () => {
69
+ it("is a valid semver-like string", () => {
70
+ expect(PKG_VERSION).toMatch(/^\d+\.\d+\.\d+/);
71
+ });
72
+ });
73
+ // ── findTeammatesDir ───────────────────────────────────────────────
74
+ describe("findTeammatesDir", () => {
75
+ let testDir;
76
+ beforeEach(async () => {
77
+ testDir = join(tmpdir(), `cli-args-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
78
+ await mkdir(testDir, { recursive: true });
79
+ });
80
+ afterEach(async () => {
81
+ await rm(testDir, { recursive: true, force: true });
82
+ });
83
+ it("returns dirOverride when provided", async () => {
84
+ const result = await findTeammatesDir("/some/custom/dir");
85
+ expect(result).toContain("some");
86
+ });
87
+ it("returns .teammates dir when it exists under cwd", async () => {
88
+ const tmDir = join(testDir, ".teammates");
89
+ await mkdir(tmDir, { recursive: true });
90
+ // Mock process.cwd to return our test dir
91
+ const origCwd = process.cwd;
92
+ process.cwd = () => testDir;
93
+ try {
94
+ const result = await findTeammatesDir(undefined);
95
+ expect(result).toBe(tmDir);
96
+ }
97
+ finally {
98
+ process.cwd = origCwd;
99
+ }
100
+ });
101
+ it("returns null when no .teammates dir exists", async () => {
102
+ const origCwd = process.cwd;
103
+ process.cwd = () => testDir;
104
+ try {
105
+ const result = await findTeammatesDir(undefined);
106
+ expect(result).toBeNull();
107
+ }
108
+ finally {
109
+ process.cwd = origCwd;
110
+ }
111
+ });
112
+ });
113
+ // ── printUsage ────────────────────────────────────────────────────
114
+ describe("printUsage", () => {
115
+ it("prints usage text to console", () => {
116
+ const spy = vi.spyOn(console, "log").mockImplementation(() => { });
117
+ printUsage();
118
+ expect(spy).toHaveBeenCalled();
119
+ const output = spy.mock.calls[0][0];
120
+ expect(output).toContain("teammates");
121
+ expect(output).toContain("--model");
122
+ expect(output).toContain("--dir");
123
+ spy.mockRestore();
124
+ });
125
+ });