

























@@ -3,9 +3,16 @@ import { createCommandHandlers } from "./tui-command-handlers.js";
3344type LoadHistoryMock = ReturnType<typeof vi.fn> & (() => Promise<void>);
55type RunAuthFlow = NonNullable<Parameters<typeof createCommandHandlers>[0]["runAuthFlow"]>;
6+type SelectableOverlay = {
7+onSelect?: (item: { value: string; label?: string; description?: string }) => void;
8+};
69type SetActivityStatusMock = ReturnType<typeof vi.fn> & ((text: string) => void);
710type SetSessionMock = ReturnType<typeof vi.fn> & ((key: string) => Promise<void>);
81112+async function flushAsyncSelect() {
13+await new Promise<void>((resolve) => setImmediate(resolve));
14+}
15+916function createHarness(params?: {
1017sendChat?: ReturnType<typeof vi.fn>;
1118getGatewayStatus?: ReturnType<typeof vi.fn>;
@@ -37,6 +44,8 @@ function createHarness(params?: {
3744const refreshSessionInfo = params?.refreshSessionInfo ?? vi.fn().mockResolvedValue(undefined);
3845const applySessionInfoFromPatch = params?.applySessionInfoFromPatch ?? vi.fn();
3946const setActivityStatus = params?.setActivityStatus ?? (vi.fn() as SetActivityStatusMock);
47+const openOverlay = vi.fn();
48+const closeOverlay = vi.fn();
4049const requestExit = vi.fn();
4150const runAuthFlow: RunAuthFlow | undefined =
4251params?.runAuthFlow ??
@@ -59,8 +68,8 @@ function createHarness(params?: {
5968opts: params?.opts ?? {},
6069state: state as never,
6170deliverDefault: false,
62-openOverlay: vi.fn(),
63-closeOverlay: vi.fn(),
71+ openOverlay,
72+ closeOverlay,
6473refreshSessionInfo: refreshSessionInfo as never,
6574 loadHistory,
6675 setSession,
@@ -81,6 +90,8 @@ function createHarness(params?: {
8190 handleCommand,
8291 getGatewayStatus,
8392 sendChat,
93+ openOverlay,
94+ closeOverlay,
8495 patchSession,
8596 resetSession,
8697 setSession,
@@ -115,7 +126,7 @@ describe("tui command handlers", () => {
115126 setActivityStatus,
116127});
117128118-const pending = handleCommand("/context");
129+const pending = handleCommand("/context detail");
119130await Promise.resolve();
120131121132expect(setActivityStatus).toHaveBeenCalledWith("sending");
@@ -131,19 +142,73 @@ describe("tui command handlers", () => {
131142it("forwards unknown slash commands to the gateway", async () => {
132143const { handleCommand, sendChat, addUser, addSystem, requestRender } = createHarness();
133144134-await handleCommand("/context");
145+await handleCommand("/unregistered-command");
135146136147expect(addSystem).not.toHaveBeenCalled();
137-expect(addUser).toHaveBeenCalledWith("/context");
148+expect(addUser).toHaveBeenCalledWith("/unregistered-command");
138149expect(sendChat).toHaveBeenCalledWith(
139150expect.objectContaining({
140151sessionKey: "agent:main:main",
141-message: "/context",
152+message: "/unregistered-command",
142153}),
143154);
144155expect(requestRender).toHaveBeenCalled();
145156});
146157158+it("opens a context mode selector for /context without sending immediately", async () => {
159+const { handleCommand, sendChat, openOverlay } = createHarness();
160+161+await handleCommand("/context");
162+163+expect(sendChat).not.toHaveBeenCalled();
164+expect(openOverlay).toHaveBeenCalledTimes(1);
165+});
166+167+it("sends the selected context mode through the gateway command path", async () => {
168+const { handleCommand, sendChat, openOverlay, closeOverlay } = createHarness();
169+170+await handleCommand("/context");
171+const selector = openOverlay.mock.calls[0]?.[0] as SelectableOverlay | undefined;
172+selector?.onSelect?.({ value: "detail", label: "detail" });
173+await flushAsyncSelect();
174+175+expect(sendChat).toHaveBeenCalledWith(
176+expect.objectContaining({
177+sessionKey: "agent:main:main",
178+message: "/context detail",
179+}),
180+);
181+expect(closeOverlay).toHaveBeenCalledTimes(1);
182+});
183+184+it("forwards /context list directly", async () => {
185+const { handleCommand, sendChat, openOverlay } = createHarness();
186+187+await handleCommand("/context list");
188+189+expect(openOverlay).not.toHaveBeenCalled();
190+expect(sendChat).toHaveBeenCalledWith(
191+expect.objectContaining({
192+sessionKey: "agent:main:main",
193+message: "/context list",
194+}),
195+);
196+});
197+198+it("forwards /context help directly", async () => {
199+const { handleCommand, sendChat, openOverlay } = createHarness();
200+201+await handleCommand("/context help");
202+203+expect(openOverlay).not.toHaveBeenCalled();
204+expect(sendChat).toHaveBeenCalledWith(
205+expect.objectContaining({
206+sessionKey: "agent:main:main",
207+message: "/context help",
208+}),
209+);
210+});
211+147212it("forwards /status to the shared gateway command path", async () => {
148213const { handleCommand, sendChat, addUser, addSystem } = createHarness();
149214@@ -202,7 +267,7 @@ describe("tui command handlers", () => {
202267it("defers local run binding until gateway events provide a real run id", async () => {
203268const { handleCommand, noteLocalRunId, state } = createHarness();
204269205-await handleCommand("/context");
270+await handleCommand("/context detail");
206271207272expect(noteLocalRunId).not.toHaveBeenCalled();
208273expect(state.activeChatRunId).toBeNull();
@@ -261,7 +326,7 @@ describe("tui command handlers", () => {
261326 setActivityStatus,
262327});
263328264-await handleCommand("/context");
329+await handleCommand("/context detail");
265330266331expect(addSystem).toHaveBeenCalledWith("send failed: Error: gateway down");
267332expect(setActivityStatus).toHaveBeenLastCalledWith("error");
@@ -288,7 +353,7 @@ describe("tui command handlers", () => {
288353isConnected: false,
289354});
290355291-await handleCommand("/context");
356+await handleCommand("/context detail");
292357293358expect(sendChat).not.toHaveBeenCalled();
294359expect(addUser).not.toHaveBeenCalled();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。