Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1385,7 +1385,8 @@ app.whenReady().then(async () => {
let port: number;

if (isDev) {
port = 3000;
const envPort = process.env.PORT ? parseInt(process.env.PORT, 10) : NaN;
port = Number.isNaN(envPort) ? 3000 : envPort;
console.log(`Dev mode: connecting to http://127.0.0.1:${port}`);
serverPort = port;
createWindow(`http://127.0.0.1:${port}`);
Expand Down
10 changes: 8 additions & 2 deletions src/hooks/useSlashCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,15 @@ export function useSlashCommands(opts: {
// Block during streaming — badges dispatch as slash/skill prompts, not queueable
if (isStreaming) { closePopover(); return; }
setBadge(result.badge!);
setInputValue('');
setInputValue(result.newInputValue ?? '');
closePopover();
setTimeout(() => textareaRef.current?.focus(), 0);
setTimeout(() => {
const el = textareaRef.current;
if (!el) return;
el.focus();
const pos = el.value.length;
el.setSelectionRange(pos, pos);
}, 0);
return;

case 'insert_file_mention':
Expand Down
23 changes: 19 additions & 4 deletions src/lib/message-input-logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,21 @@ export function filterItems(items: PopoverItem[], filter: string): PopoverItem[]
);
}

/**
* Splits input text around a popover trigger, removing the trigger character
* and any filter text that was typed after it.
*/
function splitAroundTrigger(
inputValue: string,
triggerPos: number,
popoverFilter: string,
): { before: string; after: string } {
const before = inputValue.slice(0, triggerPos);
const cursorEnd = triggerPos + popoverFilter.length + 1; // +1 to consume the trigger character
const after = inputValue.slice(cursorEnd);
return { before, after };
}

/**
* Determines what happens when an item is selected from the popover.
* Used by insertItem in useSlashCommands.
Expand All @@ -100,8 +115,9 @@ export function resolveItemSelection(
return { action: 'immediate_command', commandValue: item.value };
}

// Non-immediate commands: show as badge
// Non-immediate commands: show as badge, preserving any text outside the trigger
if (popoverMode === 'skill') {
const { before, after } = splitAroundTrigger(inputValue, triggerPos, popoverFilter);
return {
action: 'set_badge',
badge: {
Expand All @@ -111,13 +127,12 @@ export function resolveItemSelection(
kind: item.kind || 'slash_command',
installedSource: item.installedSource,
},
newInputValue: before + after,
};
}

// File mention: insert into text
const before = inputValue.slice(0, triggerPos);
const cursorEnd = triggerPos + popoverFilter.length + 1;
const after = inputValue.slice(cursorEnd);
const { before, after } = splitAroundTrigger(inputValue, triggerPos, popoverFilter);
const insertText = `@${item.value} `;
return {
action: 'insert_file_mention',
Expand Down