

























@@ -8,16 +8,35 @@ import {
88registerChatAttachmentPayload,
99resetChatAttachmentPayloadStoreForTest,
1010} from "./chat/attachment-payload-store.ts";
11+import type { executeSlashCommand } from "./chat/slash-command-executor.ts";
1112import type { GatewaySessionRow, SessionsListResult } from "./types.ts";
121313-const { setLastActiveSessionKeyMock } = vi.hoisted(() => ({
14+type ExecuteSlashCommand = typeof executeSlashCommand;
15+16+const { executeSlashCommandMock, setLastActiveSessionKeyMock } = vi.hoisted(() => ({
17+executeSlashCommandMock: vi.fn(),
1418setLastActiveSessionKeyMock: vi.fn(),
1519}));
16201721vi.mock("./app-last-active-session.ts", () => ({
1822setLastActiveSessionKey: (...args: unknown[]) => setLastActiveSessionKeyMock(...args),
1923}));
202425+vi.mock("./chat/slash-command-executor.ts", async (importOriginal) => {
26+const actual = await importOriginal<typeof import("./chat/slash-command-executor.ts")>();
27+return {
28+ ...actual,
29+executeSlashCommand: (...args: Parameters<ExecuteSlashCommand>) => {
30+const implementation = executeSlashCommandMock.getMockImplementation() as
31+| ExecuteSlashCommand
32+| undefined;
33+return implementation
34+ ? executeSlashCommandMock(...args)
35+ : actual.executeSlashCommand(...args);
36+},
37+};
38+});
39+2140let handleSendChat: typeof import("./app-chat.ts").handleSendChat;
2241let steerQueuedChatMessage: typeof import("./app-chat.ts").steerQueuedChatMessage;
2342let navigateChatInputHistory: typeof import("./app-chat.ts").navigateChatInputHistory;
@@ -420,6 +439,7 @@ describe("handleSendChat", () => {
420439});
421440422441beforeEach(() => {
442+executeSlashCommandMock.mockReset();
423443setLastActiveSessionKeyMock.mockReset();
424444});
425445@@ -619,6 +639,48 @@ describe("handleSendChat", () => {
619639expect(onSlashAction).toHaveBeenCalledWith("refresh-tools-effective");
620640});
621641642+it("shows local slash-command feedback when the gateway client is unavailable", async () => {
643+const host = makeHost({
644+client: null,
645+chatMessage: "/think",
646+connected: true,
647+});
648+649+await handleSendChat(host);
650+651+expect(host.chatMessage).toBe("");
652+expect(host.chatMessages).toEqual([
653+expect.objectContaining({
654+role: "system",
655+content: "Cannot run `/think`: Control UI is not connected to the Gateway.",
656+}),
657+]);
658+});
659+660+it("shows local slash-command feedback when dispatch fails unexpectedly", async () => {
661+executeSlashCommandMock.mockRejectedValue(new Error("dispatch failed"));
662+const request = vi.fn(async (method: string) => {
663+throw new Error(`Unexpected request: ${method}`);
664+});
665+const host = makeHost({
666+client: { request } as unknown as ChatHost["client"],
667+chatMessage: "/think",
668+connected: true,
669+});
670+671+await handleSendChat(host);
672+673+expect(executeSlashCommandMock).toHaveBeenCalledTimes(1);
674+expect(host.chatMessage).toBe("");
675+expect(host.lastError).toBe("Error: dispatch failed");
676+expect(host.chatMessages).toEqual([
677+expect.objectContaining({
678+role: "system",
679+content: "Command `/think` failed unexpectedly.",
680+}),
681+]);
682+});
683+622684it("sends /btw immediately while a main run is active without queueing it", async () => {
623685const request = vi.fn(async (method: string) => {
624686if (method === "chat.send") {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。