@saadnvd1/agent-os 0.3.587 → 0.3.588

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -163,7 +163,8 @@ export function ComposerBody({
163
163
  insertMarkdown(editor, content, insert.append);
164
164
  }, [insert, editor]);
165
165
 
166
- const query = slashQuery(text);
166
+ const slash = slashQuery(caret.before);
167
+ const query = slash?.query ?? null;
167
168
  const mentions = useMentions(editor, caret, query === null, requestFiles);
168
169
  const matches = useMemo(() => {
169
170
  if (query === null) return [];
@@ -173,8 +174,9 @@ export function ComposerBody({
173
174
  ];
174
175
  return rankCommands(query, all);
175
176
  }, [query, commands, onSetModel]);
176
- // One menu at a time: "/" commands at the start, "@" files at the caret.
177
- const menuKey = query !== null ? `/${text}` : mentions.key;
177
+ // One menu at a time: "/" commands or "@" files at the caret.
178
+ const menuKey =
179
+ query !== null ? `/${caret.pos}:${caret.before}` : mentions.key;
178
180
  const menuOpen = menuKey !== null && dismissed !== menuKey;
179
181
  const options: MenuOption[] =
180
182
  query !== null
@@ -205,12 +207,18 @@ export function ComposerBody({
205
207
  );
206
208
 
207
209
  const pickCommand = (command: ChatCommand) => {
210
+ if (!editor || !slash) return;
211
+ // The "/" and what follows it, up to the caret.
212
+ const from = caret.pos - (caret.before.length - slash.start);
213
+ const chain = editor.chain().focus().deleteRange({ from, to: caret.pos });
208
214
  if (command === MODEL_COMMAND) {
209
- setText("");
215
+ chain.run();
210
216
  setModelOpen(true);
211
217
  return;
212
218
  }
213
- setText(insertCommand(command.name), true);
219
+ chain
220
+ .insertContent({ type: "text", text: insertCommand(command.name) })
221
+ .run();
214
222
  };
215
223
  const pick = (index: number) => {
216
224
  if (query !== null) {
@@ -1,10 +1,14 @@
1
1
  import type { ChatCommand } from "./events";
2
2
 
3
- // The command being typed, if the message is still just "/something".
4
- // Agents only run a command that opens the message.
5
- export function slashQuery(text: string): string | null {
6
- const m = /^\/(\S*)$/.exec(text);
7
- return m ? m[1].toLowerCase() : null;
3
+ // The /command being typed: a "/" at the start of a line or after whitespace,
4
+ // then the partial name, right up to the caret. Not "a/b" or "http://x".
5
+ // `start` is where the "/" sits in the text before the caret.
6
+ export function slashQuery(
7
+ beforeCaret: string
8
+ ): { query: string; start: number } | null {
9
+ const m = /(^|\s)\/([^\s/]*)$/.exec(beforeCaret);
10
+ if (!m) return null;
11
+ return { query: m[2].toLowerCase(), start: m.index + m[1].length };
8
12
  }
9
13
 
10
14
  function isSubsequence(q: string, s: string): boolean {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saadnvd1/agent-os",
3
- "version": "0.3.587",
3
+ "version": "0.3.588",
4
4
  "description": "Self-hosted web UI for managing Claude Code sessions",
5
5
  "bin": {
6
6
  "agent-os": "scripts/agent-os"