@@ -1310,4 +1301,52 @@ const App: Component = () => {
)
}
+function commandRequiresArguments(template?: string) {
+ if (!template) return false
+ return /\$(?:\d+|ARGUMENTS)/.test(template)
+}
+
+function promptForCommandArguments(command: SDKCommand.Info) {
+ if (!commandRequiresArguments(command.template)) {
+ return ""
+ }
+ const input = window.prompt(`Arguments for /${command.name}`, "")
+ if (input === null) {
+ return null
+ }
+ return input
+}
+
+function formatCommandLabel(name: string) {
+ if (!name) return ""
+ return name.charAt(0).toUpperCase() + name.slice(1)
+}
+
+function buildCustomCommandEntries(instanceId: string, commands: SDKCommand.Info[]): Command[] {
+ return commands.map((cmd) => ({
+ id: `custom:${instanceId}:${cmd.name}`,
+ label: formatCommandLabel(cmd.name),
+ description: cmd.description ?? "Custom command",
+ category: "Custom Commands",
+ keywords: [cmd.name, ...(cmd.description ? cmd.description.split(/\s+/).filter(Boolean) : [])],
+ action: async () => {
+ const sessionId = activeSessionId().get(instanceId)
+ if (!sessionId || sessionId === "info") {
+ alert("Select a session before running a custom command.")
+ return
+ }
+ const args = promptForCommandArguments(cmd)
+ if (args === null) {
+ return
+ }
+ try {
+ await executeCustomCommand(instanceId, sessionId, cmd.name, args)
+ } catch (error) {
+ console.error("Failed to run custom command:", error)
+ alert("Failed to run custom command. Check the console for details.")
+ }
+ },
+ }))
+}
+
export default App
diff --git a/src/components/command-palette.tsx b/src/components/command-palette.tsx
index 9ed8c2b1..3d394f91 100644
--- a/src/components/command-palette.tsx
+++ b/src/components/command-palette.tsx
@@ -7,7 +7,7 @@ interface CommandPaletteProps {
open: boolean
onClose: () => void
commands: Command[]
- onExecute: (commandId: string) => void
+ onExecute: (command: Command) => void
}
function buildShortcutString(shortcut: Command["shortcut"]): string {
@@ -30,7 +30,7 @@ const CommandPalette: Component = (props) => {
let inputRef: HTMLInputElement | undefined
let listRef: HTMLDivElement | undefined
- const categoryOrder = ["Instance", "Session", "Agent & Model", "Input & Focus", "System", "Other"] as const
+ const categoryOrder = ["Custom Commands", "Instance", "Session", "Agent & Model", "Input & Focus", "System", "Other"] as const
type CommandGroup = { category: string; commands: Command[]; startIndex: number }
type ProcessedCommands = { groups: CommandGroup[]; ordered: Command[] }
@@ -167,13 +167,15 @@ const CommandPalette: Component = (props) => {
e.stopPropagation()
const index = selectedIndex()
if (index < 0 || index >= ordered.length) return
- props.onExecute(ordered[index].id)
+ const command = ordered[index]
+ if (!command) return
+ props.onExecute(command)
props.onClose()
}
}
- function handleCommandClick(commandId: string) {
- props.onExecute(commandId)
+ function handleCommandClick(command: Command) {
+ props.onExecute(command)
props.onClose()
}
@@ -241,7 +243,7 @@ const CommandPalette: Component = (props) => {