Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
849 lines
24 KiB
TypeScript
849 lines
24 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
resolveSlashCommandsForProvider,
|
|
resolveSlashCommandSelectionEffect,
|
|
resolveSlashCommandSubmitEffect
|
|
} from "./agentSlashCommandProviderPolicy";
|
|
import type { AgentSlashCommandPolicy } from "./agentSlashCommandProviderPolicy";
|
|
|
|
const CODEX_POLICY = {
|
|
fallbackCommands: ["compact", "status", "fast", "goal", "review"],
|
|
commandEffects: [
|
|
{ command: "init", effect: "submitImmediate" },
|
|
{ command: "compact", effect: "submitImmediate" },
|
|
{ command: "review", effect: "showReviewPicker" },
|
|
{ command: "goal", effect: "activateGoalMode" },
|
|
{ command: "plan", effect: "togglePlanMode" },
|
|
{ command: "status", effect: "showStatus" },
|
|
{ command: "fast", effect: "toggleSpeed" }
|
|
]
|
|
} as const;
|
|
|
|
const CLAUDE_POLICY = {
|
|
fallbackCommands: ["compact", "status", "fast", "goal", "review"],
|
|
commandCatalogAuthoritative: true,
|
|
commandEffects: [
|
|
{ command: "compact", effect: "submitImmediate" },
|
|
{ command: "context", effect: "submitImmediate" },
|
|
{ command: "usage", effect: "submitImmediate" },
|
|
{ command: "review", effect: "showReviewPicker" },
|
|
{ command: "goal", effect: "activateGoalMode" },
|
|
{ command: "plan", effect: "togglePlanMode" },
|
|
{ command: "status", effect: "showStatus" },
|
|
{ command: "fast", effect: "toggleSpeed" }
|
|
]
|
|
} as const;
|
|
|
|
const CURSOR_POLICY = {
|
|
fallbackCommands: ["plan"],
|
|
commandCatalogAuthoritative: true,
|
|
commandEffects: [{ command: "plan", effect: "togglePlanMode" }]
|
|
} as const;
|
|
|
|
const OPENCODE_POLICY = {
|
|
fallbackCommands: ["compact", "goal", "review"],
|
|
commandEffects: [
|
|
{ command: "compact", effect: "submitImmediate" },
|
|
{ command: "review", effect: "showReviewPicker" },
|
|
{ command: "goal", effect: "activateGoalMode" },
|
|
{ command: "plan", effect: "togglePlanMode" }
|
|
]
|
|
} as const;
|
|
|
|
describe("agentSlashCommandProviderPolicy", () => {
|
|
const reviewPickerProviders = ["codex", "claude-code"] as const;
|
|
|
|
it("surfaces compatible Plan and Tutti modifiers as independent slash entries", () => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands: [],
|
|
planSupported: true,
|
|
tuttiSupported: true
|
|
});
|
|
|
|
expect(commands.map((command) => command.name)).toEqual([
|
|
"compact",
|
|
"status",
|
|
"fast",
|
|
"goal",
|
|
"review",
|
|
"plan",
|
|
"tutti"
|
|
]);
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
command: commands.find((command) => command.name === "plan")!,
|
|
currentDraft: "/plan"
|
|
})
|
|
).toEqual({ kind: "enablePlanMode" });
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
command: commands.find((command) => command.name === "tutti")!,
|
|
currentDraft: "/tutti"
|
|
})
|
|
).toEqual({ kind: "activateTuttiMode" });
|
|
});
|
|
|
|
it("activates Tutti mode independently without synthesizing a capability reference or agent prompt", () => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
commands: [],
|
|
tuttiSupported: true
|
|
});
|
|
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
commands,
|
|
draft: "/tutti",
|
|
tuttiSupported: true
|
|
})
|
|
).toEqual({ kind: "activateTuttiMode" });
|
|
});
|
|
|
|
it("keeps /tutti arguments in the draft for normal agent submission", () => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands: [],
|
|
tuttiSupported: true
|
|
});
|
|
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands,
|
|
draft: "/tutti inspect the failing tests",
|
|
tuttiSupported: true
|
|
})
|
|
).toBeNull();
|
|
});
|
|
|
|
it("reserves the local Tutti command when a provider advertises the same name", () => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider: "extension-provider",
|
|
commands: [{ name: "tutti" }, { name: "provider-status" }],
|
|
tuttiSupported: true
|
|
});
|
|
|
|
expect(commands.map((command) => command.name)).toEqual([
|
|
"provider-status",
|
|
"tutti"
|
|
]);
|
|
const tutti = commands.find((command) => command.name === "tutti")!;
|
|
expect("kind" in tutti && tutti.kind).toBe("capability");
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "extension-provider",
|
|
commands,
|
|
draft: "/tutti",
|
|
tuttiSupported: true
|
|
})
|
|
).toEqual({ kind: "activateTuttiMode" });
|
|
});
|
|
|
|
it("reserves the local Plan command when Plan is supported", () => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands: [{ name: "plan" }],
|
|
planSupported: true
|
|
});
|
|
|
|
expect(commands.filter((command) => command.name === "plan")).toEqual([
|
|
{ name: "plan" }
|
|
]);
|
|
});
|
|
|
|
it("adds browser-use as a composer capability when browser use is supported", () => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands: [],
|
|
browserSupported: true
|
|
});
|
|
|
|
expect(
|
|
commands.find(
|
|
(command) => "kind" in command && command.kind === "capability"
|
|
)
|
|
).toEqual({
|
|
kind: "capability",
|
|
capability: "browserUse",
|
|
name: "browser",
|
|
aliases: ["浏览器"]
|
|
});
|
|
});
|
|
|
|
it("keeps OpenCode descriptor commands beside browser capability entries", () => {
|
|
expect(
|
|
resolveSlashCommandsForProvider({
|
|
provider: "opencode",
|
|
policy: OPENCODE_POLICY,
|
|
commands: [],
|
|
planSupported: true,
|
|
browserSupported: true
|
|
}).map((command) => command.name)
|
|
).toEqual(["compact", "goal", "review", "plan", "browser"]);
|
|
});
|
|
|
|
it("fills a canonical browser token from Chinese and English slash capability names", () => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands: [],
|
|
browserSupported: true
|
|
});
|
|
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
command: commands.find((command) => command.name === "browser")!,
|
|
currentDraft: "/浏览"
|
|
})
|
|
).toEqual({ kind: "enableBrowserUse", draft: "/browser " });
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands,
|
|
draft: "/浏览器",
|
|
browserSupported: true
|
|
})
|
|
).toEqual({
|
|
kind: "submitPrompt",
|
|
prompt: expect.stringContaining("browser-use"),
|
|
displayPrompt: "/browser",
|
|
requiredSettingsPatch: { browserUse: true }
|
|
});
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "extension-provider",
|
|
browserSupported: true,
|
|
commands,
|
|
draft: "/browser打开百度"
|
|
})
|
|
).toEqual({
|
|
kind: "submitPrompt",
|
|
prompt: expect.stringMatching(/browser-use[\s\S]*打开百度/),
|
|
displayPrompt: "/browser 打开百度",
|
|
requiredSettingsPatch: { browserUse: true }
|
|
});
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
browserSupported: true,
|
|
commands,
|
|
draft: "$browser 帮我访问下 google.com"
|
|
})
|
|
).toEqual({
|
|
kind: "submitPrompt",
|
|
prompt: expect.stringContaining("帮我访问下 google.com"),
|
|
displayPrompt: "/browser 帮我访问下 google.com",
|
|
requiredSettingsPatch: { browserUse: true }
|
|
});
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
browserSupported: false,
|
|
commands,
|
|
draft: "$browser test"
|
|
})
|
|
).toBeNull();
|
|
});
|
|
|
|
it("routes computer capability invocations through the local computer-use handoff", () => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
commands: [],
|
|
computerSupported: true
|
|
});
|
|
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
command: commands.find((command) => command.name === "computer")!,
|
|
currentDraft: "/comp"
|
|
})
|
|
).toEqual({ kind: "enableComputerUse", draft: "/computer " });
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
computerSupported: true,
|
|
commands,
|
|
draft: "/computer 你好"
|
|
})
|
|
).toEqual({
|
|
kind: "submitPrompt",
|
|
prompt: expect.stringMatching(/computer-use[\s\S]*你好/),
|
|
displayPrompt: "/computer 你好",
|
|
requiredSettingsPatch: { computerUse: true }
|
|
});
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
computerSupported: true,
|
|
commands,
|
|
draft: "$电脑 点击确认"
|
|
})
|
|
).toEqual({
|
|
kind: "submitPrompt",
|
|
prompt: expect.stringMatching(/computer-use[\s\S]*点击确认/),
|
|
displayPrompt: "/computer 点击确认",
|
|
requiredSettingsPatch: { computerUse: true }
|
|
});
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
computerSupported: false,
|
|
commands,
|
|
draft: "/computer test"
|
|
})
|
|
).toBeNull();
|
|
});
|
|
|
|
it("adds Codex compact, status, fast, goal, and review fallback commands after provider commands", () => {
|
|
expect(
|
|
resolveSlashCommandsForProvider({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands: [{ name: "web" }, { name: "compact", description: "ACP" }]
|
|
})
|
|
).toEqual([
|
|
{ name: "web" },
|
|
{ name: "compact", description: "ACP" },
|
|
{ name: "status" },
|
|
{ name: "fast" },
|
|
{ name: "goal" },
|
|
{ name: "review" }
|
|
]);
|
|
});
|
|
|
|
it("adds Claude Code fallback commands including goal when SDK commands are empty", () => {
|
|
expect(
|
|
resolveSlashCommandsForProvider({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
commands: []
|
|
}).map((command) => command.name)
|
|
).toEqual(["compact", "status", "fast", "goal", "review"]);
|
|
});
|
|
|
|
it("keeps noisy Claude Code discovered commands out of the slash palette", () => {
|
|
expect(
|
|
resolveSlashCommandsForProvider({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
commands: [
|
|
{ name: "browser-use-tutti-10" },
|
|
{ name: "lark-mail" },
|
|
{ name: "context", description: "Show context" },
|
|
{ name: "goal" },
|
|
{ name: "security-review" },
|
|
{ name: "usage" }
|
|
]
|
|
}).map((command) => command.name)
|
|
).toEqual([
|
|
"context",
|
|
"goal",
|
|
"usage",
|
|
"compact",
|
|
"status",
|
|
"fast",
|
|
"review"
|
|
]);
|
|
});
|
|
|
|
it("trusts typed Claude Code policy commands instead of the legacy allowlist", () => {
|
|
expect(
|
|
resolveSlashCommandsForProvider({
|
|
provider: "claude-code",
|
|
policy: {
|
|
fallbackCommands: ["custom-command"],
|
|
commandCatalogAuthoritative: true,
|
|
commandEffects: []
|
|
},
|
|
commands: [{ name: "descriptor-command" }]
|
|
}).map((command) => command.name)
|
|
).toEqual(["custom-command"]);
|
|
});
|
|
|
|
it("filters compact when the session has no compactable context", () => {
|
|
expect(
|
|
resolveSlashCommandsForProvider({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands: [{ name: "compact", description: "from provider" }],
|
|
hasCompactableContext: false
|
|
})
|
|
).toEqual([
|
|
{ name: "status" },
|
|
{ name: "fast" },
|
|
{ name: "goal" },
|
|
{ name: "review" }
|
|
]);
|
|
});
|
|
|
|
it("filters Claude Code plan commands from provider and fallback commands", () => {
|
|
expect(
|
|
resolveSlashCommandsForProvider({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
commands: [{ name: "plan", description: "provider plan" }]
|
|
})
|
|
).toEqual([
|
|
{ name: "compact" },
|
|
{ name: "status" },
|
|
{ name: "fast" },
|
|
{ name: "goal" },
|
|
{ name: "review" }
|
|
]);
|
|
});
|
|
|
|
it("submits Codex init and compact commands immediately", () => {
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
command: { name: "init" },
|
|
currentDraft: "/"
|
|
})
|
|
).toEqual({ kind: "submitPrompt", prompt: "/init" });
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
command: { name: " compact " },
|
|
currentDraft: "/"
|
|
})
|
|
).toEqual({ kind: "submitPrompt", prompt: "/compact" });
|
|
});
|
|
|
|
it("does not apply legacy immediate-command behavior over a typed policy", () => {
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "codex",
|
|
policy: { fallbackCommands: ["compact"], commandEffects: [] },
|
|
command: { name: "compact" },
|
|
currentDraft: "/"
|
|
})
|
|
).toEqual({ kind: "fillDraft", draft: "/compact " });
|
|
});
|
|
|
|
it("activates goal mode instead of filling a raw /goal draft", () => {
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
command: { name: "web" },
|
|
currentDraft: "/"
|
|
})
|
|
).toEqual({ kind: "fillDraft", draft: "/web " });
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
command: { name: "goal" },
|
|
currentDraft: "/"
|
|
})
|
|
).toEqual({ kind: "activateGoalMode" });
|
|
});
|
|
|
|
it("does not infer Codex goal behavior when the typed policy omits it", () => {
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "codex",
|
|
policy: { fallbackCommands: ["goal"], commandEffects: [] },
|
|
command: { name: "goal" },
|
|
currentDraft: "/"
|
|
})
|
|
).toEqual({ kind: "fillDraft", draft: "/goal " });
|
|
});
|
|
|
|
it("handles Codex local status without provider prompts", () => {
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
command: { name: "status" },
|
|
currentDraft: "/sta"
|
|
})
|
|
).toEqual({ kind: "showStatus" });
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
command: { name: "plan" },
|
|
currentDraft: "/pla"
|
|
})
|
|
).toEqual({ kind: "enablePlanMode" });
|
|
});
|
|
|
|
it("handles Claude Code local status without provider prompts", () => {
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
command: { name: "status" },
|
|
currentDraft: "/sta"
|
|
})
|
|
).toEqual({ kind: "showStatus" });
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
command: { name: "plan" },
|
|
currentDraft: "/pla"
|
|
})
|
|
).toEqual({ kind: "enablePlanMode" });
|
|
});
|
|
|
|
it("submits advertised Claude Code compact command as provider-native prompt", () => {
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
command: { name: "compact" },
|
|
currentDraft: "/"
|
|
})
|
|
).toEqual({ kind: "submitPrompt", prompt: "/compact" });
|
|
});
|
|
|
|
it("activates goal mode for Claude Code goal command selection", () => {
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
command: { name: "goal" },
|
|
currentDraft: "/"
|
|
})
|
|
).toEqual({ kind: "activateGoalMode" });
|
|
});
|
|
|
|
it("parses manual Codex status and toggles plan mode on submit", () => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands: [],
|
|
planSupported: true
|
|
});
|
|
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands,
|
|
draft: "/status"
|
|
})
|
|
).toEqual({ kind: "showStatus" });
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands,
|
|
draft: "/plan"
|
|
})
|
|
).toEqual({ kind: "enablePlanMode" });
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands,
|
|
draft: "/goal"
|
|
})
|
|
).toEqual({ kind: "activateGoalMode" });
|
|
});
|
|
|
|
it("parses manual Claude Code status and toggles plan mode on submit", () => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
commands: [],
|
|
planSupported: true
|
|
});
|
|
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
commands,
|
|
draft: "/status"
|
|
})
|
|
).toEqual({ kind: "showStatus" });
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
commands,
|
|
draft: "/plan"
|
|
})
|
|
).toEqual({ kind: "enablePlanMode" });
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
commands,
|
|
draft: "/plan refactor auth"
|
|
})
|
|
).toBeNull();
|
|
});
|
|
|
|
it("surfaces /plan only when plan mode is supported", () => {
|
|
expect(
|
|
resolveSlashCommandsForProvider({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands: [{ name: "plan" }],
|
|
planSupported: false
|
|
}).some((command) => command.name === "plan")
|
|
).toBe(false);
|
|
expect(
|
|
resolveSlashCommandsForProvider({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands: [],
|
|
planSupported: true
|
|
}).filter((command) => command.name === "plan")
|
|
).toHaveLength(1);
|
|
});
|
|
|
|
it("surfaces only /plan for Cursor and hides agent-advertised slash commands", () => {
|
|
expect(
|
|
resolveSlashCommandsForProvider({
|
|
provider: "cursor",
|
|
policy: CURSOR_POLICY,
|
|
commands: [
|
|
{ name: "compact" },
|
|
{ name: "goal" },
|
|
{ name: "review" },
|
|
{ name: "browser-use-tutti-10" }
|
|
],
|
|
planSupported: true
|
|
}).map((command) => command.name)
|
|
).toEqual(["plan"]);
|
|
expect(
|
|
resolveSlashCommandsForProvider({
|
|
provider: "cursor",
|
|
policy: CURSOR_POLICY,
|
|
commands: [{ name: "plan", description: "provider plan" }],
|
|
planSupported: false
|
|
})
|
|
).toEqual([]);
|
|
});
|
|
|
|
it("keeps runtime commands provider-native when a descriptor policy is missing", () => {
|
|
expect(
|
|
resolveSlashCommandsForProvider({
|
|
provider: "cursor",
|
|
commands: [{ name: "plan" }, { name: "compact" }],
|
|
planSupported: true
|
|
})
|
|
).toEqual([{ name: "plan" }, { name: "compact" }]);
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "cursor",
|
|
command: { name: "plan" },
|
|
currentDraft: "/"
|
|
})
|
|
).toEqual({ kind: "fillDraft", draft: "/plan " });
|
|
});
|
|
|
|
it("shows open-provider runtime commands without a descriptor policy", () => {
|
|
expect(
|
|
resolveSlashCommandsForProvider({
|
|
provider: "other-provider",
|
|
commands: [{ name: "compact" }]
|
|
})
|
|
).toEqual([{ name: "compact" }]);
|
|
});
|
|
|
|
it("shows extension fallback commands when command effects are absent", () => {
|
|
const policy = {
|
|
fallbackCommands: ["compact", "status"],
|
|
commandCatalogAuthoritative: true
|
|
} as unknown as AgentSlashCommandPolicy;
|
|
|
|
expect(
|
|
resolveSlashCommandsForProvider({
|
|
provider: "acp:hermes",
|
|
policy,
|
|
commands: []
|
|
})
|
|
).toEqual([{ name: "compact" }, { name: "status" }]);
|
|
});
|
|
|
|
it("keeps non-plan advertised Claude Code controls provider-native", () => {
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
commands: resolveSlashCommandsForProvider({
|
|
provider: "claude-code",
|
|
policy: CLAUDE_POLICY,
|
|
commands: [{ name: "context", description: "provider context" }]
|
|
}),
|
|
draft: "/context"
|
|
})
|
|
).toEqual({ kind: "submitPrompt", prompt: "/context" });
|
|
});
|
|
|
|
it("does not intercept unknown slash text", () => {
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands: resolveSlashCommandsForProvider({
|
|
provider: "codex",
|
|
policy: CODEX_POLICY,
|
|
commands: []
|
|
}),
|
|
draft: "/unknown"
|
|
})
|
|
).toBeNull();
|
|
});
|
|
|
|
it.each(reviewPickerProviders)(
|
|
"opens the review picker when picking %s /review from the palette",
|
|
(provider) => {
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider,
|
|
|
|
policy: provider === "codex" ? CODEX_POLICY : CLAUDE_POLICY,
|
|
command: { name: "review", description: "Review code changes" },
|
|
currentDraft: "/rev"
|
|
})
|
|
).toEqual({ kind: "showReviewPicker" });
|
|
}
|
|
);
|
|
|
|
it.each(reviewPickerProviders)(
|
|
"opens the review picker when submitting bare /review on %s",
|
|
(provider) => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider,
|
|
|
|
policy: provider === "codex" ? CODEX_POLICY : CLAUDE_POLICY,
|
|
commands: [{ name: "review", description: "Review code changes" }]
|
|
});
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider,
|
|
|
|
policy: provider === "codex" ? CODEX_POLICY : CLAUDE_POLICY,
|
|
commands,
|
|
draft: "/review"
|
|
})
|
|
).toEqual({ kind: "showReviewPicker" });
|
|
}
|
|
);
|
|
|
|
it.each(reviewPickerProviders)(
|
|
"opens the review picker from %s fallback /review before provider commands arrive",
|
|
(provider) => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider,
|
|
|
|
policy: provider === "codex" ? CODEX_POLICY : CLAUDE_POLICY,
|
|
commands: [],
|
|
hasCompactableContext: false
|
|
});
|
|
expect(commands.map((command) => command.name)).toContain("review");
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider,
|
|
|
|
policy: provider === "codex" ? CODEX_POLICY : CLAUDE_POLICY,
|
|
commands,
|
|
draft: "/review"
|
|
})
|
|
).toEqual({ kind: "showReviewPicker" });
|
|
}
|
|
);
|
|
|
|
it.each(reviewPickerProviders)(
|
|
"submits /review <text> straight through as a %s custom review",
|
|
(provider) => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider,
|
|
|
|
policy: provider === "codex" ? CODEX_POLICY : CLAUDE_POLICY,
|
|
commands: [{ name: "review", description: "Review code changes" }]
|
|
});
|
|
expect(
|
|
resolveSlashCommandSubmitEffect({
|
|
provider,
|
|
|
|
policy: provider === "codex" ? CODEX_POLICY : CLAUDE_POLICY,
|
|
commands,
|
|
draft: "/review check the auth flow"
|
|
})
|
|
).toBeNull();
|
|
}
|
|
);
|
|
|
|
it("keeps review provider-native for unknown providers", () => {
|
|
expect(
|
|
resolveSlashCommandSelectionEffect({
|
|
provider: "other-provider",
|
|
command: { name: "review", description: "Review" },
|
|
currentDraft: "/rev"
|
|
})
|
|
).toEqual({ kind: "fillDraft", draft: "/review " });
|
|
});
|
|
});
|
|
|
|
describe("compact capability gating", () => {
|
|
const policy = {
|
|
commandCatalogAuthoritative: true,
|
|
commandEffects: [],
|
|
fallbackCommands: ["compact", "status"]
|
|
};
|
|
|
|
it("keeps descriptor compact when capability is unknown", () => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider: "codex",
|
|
commands: [{ name: "compact" }, { name: "status" }],
|
|
policy
|
|
});
|
|
expect(commands.some((command) => command.name === "compact")).toBe(true);
|
|
});
|
|
|
|
it("keeps compact when capability resolves true", () => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider: "codex",
|
|
commands: [{ name: "compact" }],
|
|
compactSupported: true,
|
|
policy
|
|
});
|
|
expect(commands.some((command) => command.name === "compact")).toBe(true);
|
|
});
|
|
|
|
it("drops compact (including fallback) when capability resolves false", () => {
|
|
const commands = resolveSlashCommandsForProvider({
|
|
provider: "codex",
|
|
commands: [{ name: "compact" }, { name: "status" }],
|
|
compactSupported: false,
|
|
policy
|
|
});
|
|
expect(commands.some((command) => command.name === "compact")).toBe(false);
|
|
expect(commands.some((command) => command.name === "status")).toBe(true);
|
|
});
|
|
});
|