test: add tests for --agent override and codex plugin registration
- Session manager: agent override uses correct agent, unknown agent throws, default used without override - CLI spawn: --agent flag passthrough with and without issue ID - Plugin registry: multiple agent plugins registered via loadBuiltins importFn Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b0965693c2
commit
2bdc6bb59c
|
|
@ -234,6 +234,62 @@ describe("spawn command", () => {
|
|||
expect(output).toContain("8474d6f29887-app-7");
|
||||
});
|
||||
|
||||
it("passes --agent flag to sessionManager.spawn()", async () => {
|
||||
const fakeSession: Session = {
|
||||
id: "app-1",
|
||||
projectId: "my-app",
|
||||
status: "spawning",
|
||||
activity: null,
|
||||
branch: null,
|
||||
issueId: null,
|
||||
pr: null,
|
||||
workspacePath: "/tmp/wt",
|
||||
runtimeHandle: { id: "hash-app-1", runtimeName: "tmux", data: {} },
|
||||
agentInfo: null,
|
||||
createdAt: new Date(),
|
||||
lastActivityAt: new Date(),
|
||||
metadata: {},
|
||||
};
|
||||
|
||||
mockSessionManager.spawn.mockResolvedValue(fakeSession);
|
||||
|
||||
await program.parseAsync(["node", "test", "spawn", "my-app", "--agent", "codex"]);
|
||||
|
||||
expect(mockSessionManager.spawn).toHaveBeenCalledWith({
|
||||
projectId: "my-app",
|
||||
issueId: undefined,
|
||||
agent: "codex",
|
||||
});
|
||||
});
|
||||
|
||||
it("passes --agent flag with issue ID", async () => {
|
||||
const fakeSession: Session = {
|
||||
id: "app-1",
|
||||
projectId: "my-app",
|
||||
status: "spawning",
|
||||
activity: null,
|
||||
branch: "feat/INT-42",
|
||||
issueId: "INT-42",
|
||||
pr: null,
|
||||
workspacePath: "/tmp/wt",
|
||||
runtimeHandle: { id: "hash-app-1", runtimeName: "tmux", data: {} },
|
||||
agentInfo: null,
|
||||
createdAt: new Date(),
|
||||
lastActivityAt: new Date(),
|
||||
metadata: {},
|
||||
};
|
||||
|
||||
mockSessionManager.spawn.mockResolvedValue(fakeSession);
|
||||
|
||||
await program.parseAsync(["node", "test", "spawn", "my-app", "INT-42", "--agent", "codex"]);
|
||||
|
||||
expect(mockSessionManager.spawn).toHaveBeenCalledWith({
|
||||
projectId: "my-app",
|
||||
issueId: "INT-42",
|
||||
agent: "codex",
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects unknown project ID", async () => {
|
||||
await expect(
|
||||
program.parseAsync(["node", "test", "spawn", "nonexistent"]),
|
||||
|
|
|
|||
|
|
@ -140,6 +140,26 @@ describe("loadBuiltins", () => {
|
|||
// In the test environment, most are not resolvable — should not throw.
|
||||
await expect(registry.loadBuiltins()).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it("registers multiple agent plugins from importFn", async () => {
|
||||
const registry = createPluginRegistry();
|
||||
|
||||
const fakeClaudeCode = makePlugin("agent", "claude-code");
|
||||
const fakeCodex = makePlugin("agent", "codex");
|
||||
|
||||
await registry.loadBuiltins(undefined, async (pkg: string) => {
|
||||
if (pkg === "@composio/ao-plugin-agent-claude-code") return fakeClaudeCode;
|
||||
if (pkg === "@composio/ao-plugin-agent-codex") return fakeCodex;
|
||||
throw new Error(`Not found: ${pkg}`);
|
||||
});
|
||||
|
||||
const agents = registry.list("agent");
|
||||
expect(agents).toContainEqual(expect.objectContaining({ name: "claude-code", slot: "agent" }));
|
||||
expect(agents).toContainEqual(expect.objectContaining({ name: "codex", slot: "agent" }));
|
||||
|
||||
expect(registry.get("agent", "codex")).not.toBeNull();
|
||||
expect(registry.get("agent", "claude-code")).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("extractPluginConfig (via register with config)", () => {
|
||||
|
|
|
|||
|
|
@ -227,6 +227,64 @@ describe("spawn", () => {
|
|||
await expect(sm.spawn({ projectId: "my-app" })).rejects.toThrow("not found");
|
||||
});
|
||||
|
||||
describe("agent override", () => {
|
||||
let mockCodexAgent: Agent;
|
||||
let registryWithMultipleAgents: PluginRegistry;
|
||||
|
||||
beforeEach(() => {
|
||||
mockCodexAgent = {
|
||||
name: "codex",
|
||||
processName: "codex",
|
||||
getLaunchCommand: vi.fn().mockReturnValue("codex --start"),
|
||||
getEnvironment: vi.fn().mockReturnValue({ CODEX_VAR: "1" }),
|
||||
detectActivity: vi.fn().mockReturnValue("active"),
|
||||
getActivityState: vi.fn().mockResolvedValue(null),
|
||||
isProcessRunning: vi.fn().mockResolvedValue(true),
|
||||
getSessionInfo: vi.fn().mockResolvedValue(null),
|
||||
};
|
||||
|
||||
registryWithMultipleAgents = {
|
||||
...mockRegistry,
|
||||
get: vi.fn().mockImplementation((slot: string, name: string) => {
|
||||
if (slot === "runtime") return mockRuntime;
|
||||
if (slot === "agent") {
|
||||
if (name === "mock-agent") return mockAgent;
|
||||
if (name === "codex") return mockCodexAgent;
|
||||
return null;
|
||||
}
|
||||
if (slot === "workspace") return mockWorkspace;
|
||||
return null;
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
it("uses overridden agent when spawnConfig.agent is provided", async () => {
|
||||
const sm = createSessionManager({ config, registry: registryWithMultipleAgents });
|
||||
|
||||
await sm.spawn({ projectId: "my-app", agent: "codex" });
|
||||
|
||||
expect(mockCodexAgent.getLaunchCommand).toHaveBeenCalled();
|
||||
expect(mockAgent.getLaunchCommand).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("throws when agent override plugin is not found", async () => {
|
||||
const sm = createSessionManager({ config, registry: registryWithMultipleAgents });
|
||||
|
||||
await expect(
|
||||
sm.spawn({ projectId: "my-app", agent: "nonexistent" }),
|
||||
).rejects.toThrow("Agent plugin 'nonexistent' not found");
|
||||
});
|
||||
|
||||
it("uses default agent when no override specified", async () => {
|
||||
const sm = createSessionManager({ config, registry: registryWithMultipleAgents });
|
||||
|
||||
await sm.spawn({ projectId: "my-app" });
|
||||
|
||||
expect(mockAgent.getLaunchCommand).toHaveBeenCalled();
|
||||
expect(mockCodexAgent.getLaunchCommand).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("validates issue exists when issueId provided", async () => {
|
||||
const mockTracker: Tracker = {
|
||||
name: "mock-tracker",
|
||||
|
|
|
|||
Loading…
Reference in New Issue