
























@@ -115,6 +115,39 @@ function requireNativeCommand(name: string, provider?: string): ChatCommandDefin
115115return command;
116116}
117117118+function requireCommandArg(
119+command: ChatCommandDefinition,
120+name: string,
121+): NonNullable<ChatCommandDefinition["args"]>[number] {
122+const arg = command.args?.find((candidate) => candidate.name === name);
123+if (!arg) {
124+throw new Error(`Expected ${command.key} command arg "${name}"`);
125+}
126+return arg;
127+}
128+129+function requireCommandArgAt(
130+command: ChatCommandDefinition,
131+index: number,
132+): NonNullable<ChatCommandDefinition["args"]>[number] {
133+const arg = command.args?.[index];
134+if (!arg) {
135+throw new Error(`Expected ${command.key} command arg ${index}`);
136+}
137+return arg;
138+}
139+140+function requireCommandArgMenu(
141+params: Parameters<typeof resolveCommandArgMenu>[0],
142+): NonNullable<ReturnType<typeof resolveCommandArgMenu>> {
143+const menu = resolveCommandArgMenu(params);
144+expect(menu).not.toBeNull();
145+if (!menu) {
146+throw new Error(`Expected arg menu for ${params.command.key}`);
147+}
148+return menu;
149+}
150+118151describe("commands registry", () => {
119152it("builds command text with args", () => {
120153expect(buildCommandText("status")).toBe("/status");
@@ -301,8 +334,8 @@ describe("commands registry", () => {
301334302335it("keeps ACP native action choices aligned with implemented handlers", () => {
303336const acp = requireChatCommand("acp");
304-const actionArg = acp.args?.find((arg) => arg.name === "action");
305-expect(actionArg?.choices).toEqual([
337+const actionArg = requireCommandArg(acp, "action");
338+expect(actionArg.choices).toEqual([
306339"spawn",
307340"cancel",
308341"steer",
@@ -323,14 +356,14 @@ describe("commands registry", () => {
323356});
324357325358it("registers fast mode as a first-class options command", () => {
326-const fast = listChatCommands().find((command) => command.key === "fast");
359+const fast = requireChatCommand("fast");
327360expect(fast).toMatchObject({
328361nativeName: "fast",
329362textAliases: ["/fast"],
330363category: "options",
331364});
332-const modeArg = fast?.args?.find((arg) => arg.name === "mode");
333-expect(modeArg?.choices).toEqual(["status", "on", "off"]);
365+const modeArg = requireCommandArg(fast, "mode");
366+expect(modeArg.choices).toEqual(["status", "on", "off"]);
334367});
335368336369it("detects known text commands", () => {
@@ -458,7 +491,7 @@ describe("commands registry args", () => {
458491};
459492460493const args = parseCommandArgs(command, "set foo bar baz");
461-expect(args?.values).toEqual({ action: "set", path: "foo", value: "bar baz" });
494+expect(args).toMatchObject({ values: { action: "set", path: "foo", value: "bar baz" } });
462495});
463496464497it("serializes args via raw first, then values", () => {
@@ -481,9 +514,9 @@ describe("commands registry args", () => {
481514it("resolves auto arg menus when missing a choice arg", () => {
482515const command = createUsageModeCommand();
483516484-const menu = resolveCommandArgMenu({ command, args: undefined, cfg: {} as never });
485-expect(menu?.arg.name).toBe("mode");
486-expect(menu?.choices).toEqual([
517+const menu = requireCommandArgMenu({ command, args: undefined, cfg: {} as never });
518+expect(menu.arg.name).toBe("mode");
519+expect(menu.choices).toEqual([
487520{ label: "off", value: "off" },
488521{ label: "tokens", value: "tokens" },
489522{ label: "full", value: "full" },
@@ -492,11 +525,12 @@ describe("commands registry args", () => {
492525});
493526494527it("keeps verbose full available while preserving no-arg status dispatch", () => {
495-const verbose = listChatCommands().find((command) => command.key === "verbose");
528+const verbose = requireChatCommand("verbose");
496529497-expect(verbose?.args?.[0]?.choices).toEqual(["on", "off", "full"]);
530+const modeArg = requireCommandArgAt(verbose, 0);
531+expect(modeArg.choices).toEqual(["on", "off", "full"]);
498532expect(
499-resolveCommandArgMenu({ command: verbose!, args: undefined, cfg: {} as never }),
533+resolveCommandArgMenu({ command: verbose, args: undefined, cfg: {} as never }),
500534).toBeNull();
501535});
502536此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。