@cmetech/otto 1.0.9 → 1.1.0

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.
Files changed (66) hide show
  1. package/dist/resources/.managed-resources-content-hash +1 -1
  2. package/dist/resources/extensions/otto/commands/release-notes/_data.js +16 -0
  3. package/dist/resources/extensions/otto/commands/theme/command.js +75 -0
  4. package/dist/resources/extensions/otto/index.js +3 -0
  5. package/dist/resources/extensions/subagent/agents.js +160 -8
  6. package/dist/resources/extensions/subagent/index.js +45 -4
  7. package/dist/resources/extensions/subagent/skill-tool-stub.js +23 -0
  8. package/dist/seed-defaults.d.ts +16 -0
  9. package/dist/seed-defaults.js +69 -1
  10. package/package.json +6 -6
  11. package/packages/contracts/package.json +1 -1
  12. package/packages/daemon/package.json +3 -3
  13. package/packages/mcp-server/package.json +3 -3
  14. package/packages/native/package.json +1 -1
  15. package/packages/pi-agent-core/package.json +1 -1
  16. package/packages/pi-ai/package.json +1 -1
  17. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  18. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  19. package/packages/pi-coding-agent/dist/core/settings-manager.js +6 -0
  20. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  21. package/packages/pi-coding-agent/dist/core/skills.d.ts +11 -0
  22. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  23. package/packages/pi-coding-agent/dist/core/skills.js +22 -0
  24. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  25. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  26. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  27. package/packages/pi-coding-agent/dist/index.js +1 -1
  28. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  29. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  30. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -2
  31. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  32. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  33. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +4 -0
  34. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  35. package/packages/pi-coding-agent/package.json +2 -2
  36. package/packages/pi-coding-agent/src/core/settings-manager.ts +9 -0
  37. package/packages/pi-coding-agent/src/core/skills.ts +23 -1
  38. package/packages/pi-coding-agent/src/index.ts +4 -0
  39. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +13 -2
  40. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +4 -0
  41. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  42. package/packages/pi-tui/dist/autocomplete.d.ts +9 -0
  43. package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -1
  44. package/packages/pi-tui/dist/autocomplete.js +2 -0
  45. package/packages/pi-tui/dist/autocomplete.js.map +1 -1
  46. package/packages/pi-tui/dist/components/select-list.d.ts +10 -0
  47. package/packages/pi-tui/dist/components/select-list.d.ts.map +1 -1
  48. package/packages/pi-tui/dist/components/select-list.js +30 -17
  49. package/packages/pi-tui/dist/components/select-list.js.map +1 -1
  50. package/packages/pi-tui/package.json +1 -1
  51. package/packages/pi-tui/src/autocomplete.ts +11 -0
  52. package/packages/pi-tui/src/components/select-list.ts +41 -17
  53. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  54. package/packages/rpc-client/package.json +2 -2
  55. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  56. package/pkg/dist/modes/interactive/theme/theme.js +4 -0
  57. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  58. package/pkg/package.json +1 -1
  59. package/src/resources/extensions/otto/commands/release-notes/_data.ts +16 -0
  60. package/src/resources/extensions/otto/commands/theme/command.ts +89 -0
  61. package/src/resources/extensions/otto/index.ts +4 -0
  62. package/src/resources/extensions/subagent/agents.ts +166 -8
  63. package/src/resources/extensions/subagent/index.ts +46 -6
  64. package/src/resources/extensions/subagent/skill-tool-stub.ts +28 -0
  65. package/src/resources/extensions/subagent/tests/parse-agent-tools.test.ts +52 -0
  66. package/src/resources/extensions/subagent/tests/skill-tool-stub.test.ts +23 -0
@@ -2,10 +2,19 @@ export interface AutocompleteItem {
2
2
  value: string;
3
3
  label: string;
4
4
  description?: string;
5
+ /**
6
+ * Optional short origin tag rendered before the value as a colored chip
7
+ * (e.g. "claude", "codex", "kiro"). The color comes from `SelectListTheme.tag`.
8
+ * Kept short (< 12 chars) — long tags eat the visible width budget.
9
+ *
10
+ * Fork-specific addition. See docs/UPSTREAM-SYNC.md.
11
+ */
12
+ tag?: string;
5
13
  }
6
14
  export interface SlashCommand {
7
15
  name: string;
8
16
  description?: string;
17
+ tag?: string;
9
18
  getArgumentCompletions?(argumentPrefix: string): AutocompleteItem[] | null;
10
19
  }
11
20
  export interface AutocompleteProvider {
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../src/autocomplete.ts"],"names":[],"mappings":"AAuFA,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,sBAAsB,CAAC,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAAC;CAC3E;AAED,MAAM,WAAW,oBAAoB;IAGpC,cAAc,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QACF,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAC1B,MAAM,EAAE,MAAM,CAAC;KACf,GAAG,IAAI,CAAC;IAIT,eAAe,CACd,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACZ;QACF,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;CACF;AAGD,qBAAa,4BAA6B,YAAW,oBAAoB;IACxE,OAAO,CAAC,QAAQ,CAAsC;IACtD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,gBAAgB,CAAU;IAClC,OAAO,CAAC,WAAW,CAAc;gBAGhC,QAAQ,GAAE,CAAC,YAAY,GAAG,gBAAgB,CAAC,EAAO,EAClD,QAAQ,GAAE,MAAsB,EAChC,OAAO,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;IAQjE,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAIzC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI;IAIpC,cAAc,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAgGvD,eAAe,CACd,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACZ;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAmF7D,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,iBAAiB;IA8BzB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,uBAAuB;IA6B/B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,kBAAkB;IAwI1B,OAAO,CAAC,uBAAuB;IA4D/B,uBAAuB,CACtB,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAyBvD,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;CAW5F"}
1
+ {"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../src/autocomplete.ts"],"names":[],"mappings":"AAuFA,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IAGb,sBAAsB,CAAC,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAAC;CAC3E;AAED,MAAM,WAAW,oBAAoB;IAGpC,cAAc,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QACF,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAC1B,MAAM,EAAE,MAAM,CAAC;KACf,GAAG,IAAI,CAAC;IAIT,eAAe,CACd,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACZ;QACF,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;CACF;AAGD,qBAAa,4BAA6B,YAAW,oBAAoB;IACxE,OAAO,CAAC,QAAQ,CAAsC;IACtD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,gBAAgB,CAAU;IAClC,OAAO,CAAC,WAAW,CAAc;gBAGhC,QAAQ,GAAE,CAAC,YAAY,GAAG,gBAAgB,CAAC,EAAO,EAClD,QAAQ,GAAE,MAAsB,EAChC,OAAO,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;IAQjE,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAIzC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI;IAIpC,cAAc,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAkGvD,eAAe,CACd,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACZ;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAmF7D,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,iBAAiB;IA8BzB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,uBAAuB;IA6B/B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,kBAAkB;IAwI1B,OAAO,CAAC,uBAAuB;IA4D/B,uBAAuB,CACtB,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAyBvD,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;CAW5F"}
@@ -107,11 +107,13 @@ export class CombinedAutocompleteProvider {
107
107
  name: "name" in cmd ? cmd.name : cmd.value,
108
108
  label: "name" in cmd ? cmd.name : cmd.label,
109
109
  description: cmd.description,
110
+ tag: cmd.tag,
110
111
  }));
111
112
  const filtered = fuzzyFilter(commandItems, prefix, (item) => item.name).map((item) => ({
112
113
  value: item.name,
113
114
  label: item.label,
114
115
  ...(item.description && { description: item.description }),
116
+ ...(item.tag && { tag: item.tag }),
115
117
  }));
116
118
  if (filtered.length === 0)
117
119
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete.js","sourceRoot":"","sources":["../src/autocomplete.ts"],"names":[],"mappings":"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","sourcesContent":["import { readdirSync, statSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { basename, dirname, join } from \"path\";\nimport { fuzzyFind } from \"@otto/native/fd\";\nimport { fuzzyFilter } from \"./fuzzy.js\";\n\nconst PATH_DELIMITERS = new Set([\" \", \"\\t\", '\"', \"'\", \"=\"]);\nconst FUZZY_FILE_MAX_RESULTS = 20;\n\nfunction findLastDelimiter(text: string): number {\n\tfor (let i = text.length - 1; i >= 0; i -= 1) {\n\t\tif (PATH_DELIMITERS.has(text[i] ?? \"\")) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn -1;\n}\n\nfunction findUnclosedQuoteStart(text: string): number | null {\n\tlet inQuotes = false;\n\tlet quoteStart = -1;\n\n\tfor (let i = 0; i < text.length; i += 1) {\n\t\tif (text[i] === '\"') {\n\t\t\tinQuotes = !inQuotes;\n\t\t\tif (inQuotes) {\n\t\t\t\tquoteStart = i;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn inQuotes ? quoteStart : null;\n}\n\nfunction isTokenStart(text: string, index: number): boolean {\n\treturn index === 0 || PATH_DELIMITERS.has(text[index - 1] ?? \"\");\n}\n\nfunction extractQuotedPrefix(text: string): string | null {\n\tconst quoteStart = findUnclosedQuoteStart(text);\n\tif (quoteStart === null) {\n\t\treturn null;\n\t}\n\n\tif (quoteStart > 0 && text[quoteStart - 1] === \"@\") {\n\t\tif (!isTokenStart(text, quoteStart - 1)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn text.slice(quoteStart - 1);\n\t}\n\n\tif (!isTokenStart(text, quoteStart)) {\n\t\treturn null;\n\t}\n\n\treturn text.slice(quoteStart);\n}\n\nfunction parsePathPrefix(prefix: string): { rawPrefix: string; isAtPrefix: boolean; isQuotedPrefix: boolean } {\n\tif (prefix.startsWith('@\"')) {\n\t\treturn { rawPrefix: prefix.slice(2), isAtPrefix: true, isQuotedPrefix: true };\n\t}\n\tif (prefix.startsWith('\"')) {\n\t\treturn { rawPrefix: prefix.slice(1), isAtPrefix: false, isQuotedPrefix: true };\n\t}\n\tif (prefix.startsWith(\"@\")) {\n\t\treturn { rawPrefix: prefix.slice(1), isAtPrefix: true, isQuotedPrefix: false };\n\t}\n\treturn { rawPrefix: prefix, isAtPrefix: false, isQuotedPrefix: false };\n}\n\nfunction buildCompletionValue(\n\tpath: string,\n\toptions: { isDirectory: boolean; isAtPrefix: boolean; isQuotedPrefix: boolean },\n): string {\n\tconst needsQuotes = options.isQuotedPrefix || path.includes(\" \");\n\tconst prefix = options.isAtPrefix ? \"@\" : \"\";\n\n\tif (!needsQuotes) {\n\t\treturn `${prefix}${path}`;\n\t}\n\n\tconst openQuote = `${prefix}\"`;\n\tconst closeQuote = '\"';\n\treturn `${openQuote}${path}${closeQuote}`;\n}\n\nexport interface AutocompleteItem {\n\tvalue: string;\n\tlabel: string;\n\tdescription?: string;\n}\n\nexport interface SlashCommand {\n\tname: string;\n\tdescription?: string;\n\t// Function to get argument completions for this command\n\t// Returns null if no argument completion is available\n\tgetArgumentCompletions?(argumentPrefix: string): AutocompleteItem[] | null;\n}\n\nexport interface AutocompleteProvider {\n\t// Get autocomplete suggestions for current text/cursor position\n\t// Returns null if no suggestions available\n\tgetSuggestions(\n\t\tlines: string[],\n\t\tcursorLine: number,\n\t\tcursorCol: number,\n\t): {\n\t\titems: AutocompleteItem[];\n\t\tprefix: string; // What we're matching against (e.g., \"/\" or \"src/\")\n\t} | null;\n\n\t// Apply the selected item\n\t// Returns the new text and cursor position\n\tapplyCompletion(\n\t\tlines: string[],\n\t\tcursorLine: number,\n\t\tcursorCol: number,\n\t\titem: AutocompleteItem,\n\t\tprefix: string,\n\t): {\n\t\tlines: string[];\n\t\tcursorLine: number;\n\t\tcursorCol: number;\n\t};\n}\n\n// Combined provider that handles both slash commands and file paths\nexport class CombinedAutocompleteProvider implements AutocompleteProvider {\n\tprivate commands: (SlashCommand | AutocompleteItem)[];\n\tprivate basePath: string;\n\tprivate respectGitignore: boolean;\n\tprivate excludeDirs: Set<string>;\n\n\tconstructor(\n\t\tcommands: (SlashCommand | AutocompleteItem)[] = [],\n\t\tbasePath: string = process.cwd(),\n\t\toptions?: { respectGitignore?: boolean; excludeDirs?: string[] },\n\t) {\n\t\tthis.commands = commands;\n\t\tthis.basePath = basePath;\n\t\tthis.respectGitignore = options?.respectGitignore ?? true;\n\t\tthis.excludeDirs = new Set(options?.excludeDirs ?? []);\n\t}\n\n\tsetRespectGitignore(value: boolean): void {\n\t\tthis.respectGitignore = value;\n\t}\n\n\tsetExcludeDirs(dirs: string[]): void {\n\t\tthis.excludeDirs = new Set(dirs.filter(Boolean));\n\t}\n\n\tgetSuggestions(\n\t\tlines: string[],\n\t\tcursorLine: number,\n\t\tcursorCol: number,\n\t): { items: AutocompleteItem[]; prefix: string } | null {\n\t\tconst currentLine = lines[cursorLine] || \"\";\n\t\tconst textBeforeCursor = currentLine.slice(0, cursorCol);\n\t\tconst trimmedBeforeCursor = textBeforeCursor.trimStart();\n\n\t\t// Check for @ file reference (fuzzy search) - must be after a delimiter or at start\n\t\tconst atPrefix = this.extractAtPrefix(textBeforeCursor);\n\t\tif (atPrefix) {\n\t\t\tconst { rawPrefix, isQuotedPrefix } = parsePathPrefix(atPrefix);\n\t\t\tconst suggestions = this.getFuzzyFileSuggestions(rawPrefix, { isQuotedPrefix: isQuotedPrefix });\n\t\t\tif (suggestions.length === 0) return null;\n\n\t\t\treturn {\n\t\t\t\titems: suggestions,\n\t\t\t\tprefix: atPrefix,\n\t\t\t};\n\t\t}\n\n\t\t// Check for slash commands\n\t\tif (trimmedBeforeCursor.startsWith(\"/\")) {\n\t\t\tconst spaceIndex = trimmedBeforeCursor.indexOf(\" \");\n\n\t\t\tif (spaceIndex === -1) {\n\t\t\t\t// No space yet - complete command names with fuzzy matching\n\t\t\t\tconst prefix = trimmedBeforeCursor.slice(1); // Remove the \"/\"\n\t\t\t\tconst commandItems = this.commands.map((cmd) => ({\n\t\t\t\t\tname: \"name\" in cmd ? cmd.name : cmd.value,\n\t\t\t\t\tlabel: \"name\" in cmd ? cmd.name : cmd.label,\n\t\t\t\t\tdescription: cmd.description,\n\t\t\t\t}));\n\n\t\t\t\tconst filtered = fuzzyFilter(commandItems, prefix, (item) => item.name).map((item) => ({\n\t\t\t\t\tvalue: item.name,\n\t\t\t\t\tlabel: item.label,\n\t\t\t\t\t...(item.description && { description: item.description }),\n\t\t\t\t}));\n\n\t\t\t\tif (filtered.length === 0) return null;\n\n\t\t\t\treturn {\n\t\t\t\t\titems: filtered,\n\t\t\t\t\tprefix: `/${prefix}`,\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\t// Space found - complete command arguments\n\t\t\t\tconst commandName = trimmedBeforeCursor.slice(1, spaceIndex); // Command without \"/\"\n\t\t\t\tconst argumentText = trimmedBeforeCursor.slice(spaceIndex + 1); // Text after space\n\n\t\t\t\tconst command = this.commands.find((cmd) => {\n\t\t\t\t\tconst name = \"name\" in cmd ? cmd.name : cmd.value;\n\t\t\t\t\treturn name === commandName;\n\t\t\t\t});\n\t\t\t\tif (!command || !(\"getArgumentCompletions\" in command) || !command.getArgumentCompletions) {\n\t\t\t\t\treturn null; // No argument completion for this command\n\t\t\t\t}\n\n\t\t\t\tconst argumentSuggestions = command.getArgumentCompletions(argumentText);\n\t\t\t\tif (!argumentSuggestions || argumentSuggestions.length === 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\titems: argumentSuggestions,\n\t\t\t\t\tprefix: argumentText,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\t// Check for file paths - triggered by Tab or if we detect a path pattern\n\t\tconst pathMatch = this.extractPathPrefix(textBeforeCursor, false);\n\n\t\tif (pathMatch !== null) {\n\t\t\tconst suggestions = this.getFileSuggestions(pathMatch);\n\t\t\tif (suggestions.length === 0) return null;\n\n\t\t\t// Check if we have an exact match that is a directory\n\t\t\t// In that case, we might want to return suggestions for the directory content instead\n\t\t\t// But only if the prefix ends with /\n\t\t\tif (suggestions.length === 1 && suggestions[0]?.value === pathMatch && !pathMatch.endsWith(\"/\")) {\n\t\t\t\t// Exact match found (e.g. user typed \"src\" and \"src/\" is the only match)\n\t\t\t\t// We still return it so user can select it and add /\n\t\t\t\treturn {\n\t\t\t\t\titems: suggestions,\n\t\t\t\t\tprefix: pathMatch,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\titems: suggestions,\n\t\t\t\tprefix: pathMatch,\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tapplyCompletion(\n\t\tlines: string[],\n\t\tcursorLine: number,\n\t\tcursorCol: number,\n\t\titem: AutocompleteItem,\n\t\tprefix: string,\n\t): { lines: string[]; cursorLine: number; cursorCol: number } {\n\t\tconst currentLine = lines[cursorLine] || \"\";\n\t\tconst beforePrefix = currentLine.slice(0, cursorCol - prefix.length);\n\t\tconst afterCursor = currentLine.slice(cursorCol);\n\t\tconst isQuotedPrefix = prefix.startsWith('\"') || prefix.startsWith('@\"');\n\t\tconst hasLeadingQuoteAfterCursor = afterCursor.startsWith('\"');\n\t\tconst hasTrailingQuoteInItem = item.value.endsWith('\"');\n\t\tconst adjustedAfterCursor =\n\t\t\tisQuotedPrefix && hasTrailingQuoteInItem && hasLeadingQuoteAfterCursor ? afterCursor.slice(1) : afterCursor;\n\n\t\t// Check if we're completing a slash command (prefix starts with \"/\" but NOT a file path)\n\t\t// Slash commands are at the start of the line and don't contain path separators after the first /\n\t\tconst trimmedPrefix = prefix.trimStart();\n\t\tconst isSlashCommand = trimmedPrefix.startsWith(\"/\") && beforePrefix.trim() === \"\" && !trimmedPrefix.slice(1).includes(\"/\");\n\t\tif (isSlashCommand) {\n\t\t\t// This is a command name completion\n\t\t\tconst newLine = `${beforePrefix}/${item.value} ${adjustedAfterCursor}`;\n\t\t\tconst newLines = [...lines];\n\t\t\tnewLines[cursorLine] = newLine;\n\n\t\t\treturn {\n\t\t\t\tlines: newLines,\n\t\t\t\tcursorLine,\n\t\t\t\tcursorCol: beforePrefix.length + item.value.length + 2, // +2 for \"/\" and space\n\t\t\t};\n\t\t}\n\n\t\t// Check if we're completing a file attachment (prefix starts with \"@\")\n\t\tif (prefix.startsWith(\"@\")) {\n\t\t\t// This is a file attachment completion\n\t\t\t// Don't add space after directories so user can continue autocompleting\n\t\t\tconst isDirectory = item.label.endsWith(\"/\");\n\t\t\tconst suffix = isDirectory ? \"\" : \" \";\n\t\t\tconst newLine = `${beforePrefix + item.value}${suffix}${adjustedAfterCursor}`;\n\t\t\tconst newLines = [...lines];\n\t\t\tnewLines[cursorLine] = newLine;\n\n\t\t\tconst hasTrailingQuote = item.value.endsWith('\"');\n\t\t\tconst cursorOffset = isDirectory && hasTrailingQuote ? item.value.length - 1 : item.value.length;\n\n\t\t\treturn {\n\t\t\t\tlines: newLines,\n\t\t\t\tcursorLine,\n\t\t\t\tcursorCol: beforePrefix.length + cursorOffset + suffix.length,\n\t\t\t};\n\t\t}\n\n\t\t// Check if we're in a slash command context (beforePrefix contains \"/command \")\n\t\tconst textBeforeCursor = currentLine.slice(0, cursorCol);\n\t\tif (textBeforeCursor.includes(\"/\") && textBeforeCursor.includes(\" \")) {\n\t\t\t// This is likely a command argument completion\n\t\t\tconst newLine = beforePrefix + item.value + adjustedAfterCursor;\n\t\t\tconst newLines = [...lines];\n\t\t\tnewLines[cursorLine] = newLine;\n\n\t\t\tconst isDirectory = item.label.endsWith(\"/\");\n\t\t\tconst hasTrailingQuote = item.value.endsWith('\"');\n\t\t\tconst cursorOffset = isDirectory && hasTrailingQuote ? item.value.length - 1 : item.value.length;\n\n\t\t\treturn {\n\t\t\t\tlines: newLines,\n\t\t\t\tcursorLine,\n\t\t\t\tcursorCol: beforePrefix.length + cursorOffset,\n\t\t\t};\n\t\t}\n\n\t\t// For file paths, complete the path\n\t\tconst newLine = beforePrefix + item.value + adjustedAfterCursor;\n\t\tconst newLines = [...lines];\n\t\tnewLines[cursorLine] = newLine;\n\n\t\tconst isDirectory = item.label.endsWith(\"/\");\n\t\tconst hasTrailingQuote = item.value.endsWith('\"');\n\t\tconst cursorOffset = isDirectory && hasTrailingQuote ? item.value.length - 1 : item.value.length;\n\n\t\treturn {\n\t\t\tlines: newLines,\n\t\t\tcursorLine,\n\t\t\tcursorCol: beforePrefix.length + cursorOffset,\n\t\t};\n\t}\n\n\t// Extract @ prefix for fuzzy file suggestions\n\tprivate extractAtPrefix(text: string): string | null {\n\t\tconst quotedPrefix = extractQuotedPrefix(text);\n\t\tif (quotedPrefix?.startsWith('@\"')) {\n\t\t\treturn quotedPrefix;\n\t\t}\n\n\t\tconst lastDelimiterIndex = findLastDelimiter(text);\n\t\tconst tokenStart = lastDelimiterIndex === -1 ? 0 : lastDelimiterIndex + 1;\n\n\t\tif (text[tokenStart] === \"@\") {\n\t\t\treturn text.slice(tokenStart);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t// Extract a path-like prefix from the text before cursor\n\tprivate extractPathPrefix(text: string, forceExtract: boolean = false): string | null {\n\t\tconst quotedPrefix = extractQuotedPrefix(text);\n\t\tif (quotedPrefix) {\n\t\t\treturn quotedPrefix;\n\t\t}\n\n\t\tconst lastDelimiterIndex = findLastDelimiter(text);\n\t\tconst pathPrefix = lastDelimiterIndex === -1 ? text : text.slice(lastDelimiterIndex + 1);\n\n\t\t// For forced extraction (Tab key), always return something\n\t\tif (forceExtract) {\n\t\t\treturn pathPrefix;\n\t\t}\n\n\t\t// For natural triggers, return if it looks like a path, ends with /, starts with ~/, .\n\t\t// Only return empty string if the text looks like it's starting a path context\n\t\tif (pathPrefix.includes(\"/\") || pathPrefix.startsWith(\".\") || pathPrefix.startsWith(\"~/\")) {\n\t\t\treturn pathPrefix;\n\t\t}\n\n\t\t// Return empty string only after a space (not for completely empty text)\n\t\t// Empty text should not trigger file suggestions - that's for forced Tab completion\n\t\tif (pathPrefix === \"\" && text.endsWith(\" \")) {\n\t\t\treturn pathPrefix;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t// Expand home directory (~/) to actual home path\n\tprivate expandHomePath(path: string): string {\n\t\tif (path.startsWith(\"~/\")) {\n\t\t\tconst expandedPath = join(homedir(), path.slice(2));\n\t\t\t// Preserve trailing slash if original path had one\n\t\t\treturn path.endsWith(\"/\") && !expandedPath.endsWith(\"/\") ? `${expandedPath}/` : expandedPath;\n\t\t} else if (path === \"~\") {\n\t\t\treturn homedir();\n\t\t}\n\t\treturn path;\n\t}\n\n\tprivate resolveScopedFuzzyQuery(rawQuery: string): { baseDir: string; query: string; displayBase: string } | null {\n\t\tconst slashIndex = rawQuery.lastIndexOf(\"/\");\n\t\tif (slashIndex === -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst displayBase = rawQuery.slice(0, slashIndex + 1);\n\t\tconst query = rawQuery.slice(slashIndex + 1);\n\n\t\tlet baseDir: string;\n\t\tif (displayBase.startsWith(\"~/\")) {\n\t\t\tbaseDir = this.expandHomePath(displayBase);\n\t\t} else if (displayBase.startsWith(\"/\")) {\n\t\t\tbaseDir = displayBase;\n\t\t} else {\n\t\t\tbaseDir = join(this.basePath, displayBase);\n\t\t}\n\n\t\ttry {\n\t\t\tif (!statSync(baseDir).isDirectory()) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn { baseDir, query, displayBase };\n\t}\n\n\tprivate scopedPathForDisplay(displayBase: string, relativePath: string): string {\n\t\tif (displayBase === \"/\") {\n\t\t\treturn `/${relativePath}`;\n\t\t}\n\t\treturn `${displayBase}${relativePath}`;\n\t}\n\n\t// Get file/directory suggestions for a given path prefix\n\tprivate getFileSuggestions(prefix: string): AutocompleteItem[] {\n\t\ttry {\n\t\t\tlet searchDir: string;\n\t\t\tlet searchPrefix: string;\n\t\t\tconst { rawPrefix, isAtPrefix, isQuotedPrefix } = parsePathPrefix(prefix);\n\t\t\tlet expandedPrefix = rawPrefix;\n\n\t\t\t// Handle home directory expansion\n\t\t\tif (expandedPrefix.startsWith(\"~\")) {\n\t\t\t\texpandedPrefix = this.expandHomePath(expandedPrefix);\n\t\t\t}\n\n\t\t\tconst isRootPrefix =\n\t\t\t\trawPrefix === \"\" ||\n\t\t\t\trawPrefix === \"./\" ||\n\t\t\t\trawPrefix === \"../\" ||\n\t\t\t\trawPrefix === \"~\" ||\n\t\t\t\trawPrefix === \"~/\" ||\n\t\t\t\trawPrefix === \"/\" ||\n\t\t\t\t(isAtPrefix && rawPrefix === \"\");\n\n\t\t\tif (isRootPrefix) {\n\t\t\t\t// Complete from specified position\n\t\t\t\tif (rawPrefix.startsWith(\"~\") || expandedPrefix.startsWith(\"/\")) {\n\t\t\t\t\tsearchDir = expandedPrefix;\n\t\t\t\t} else {\n\t\t\t\t\tsearchDir = join(this.basePath, expandedPrefix);\n\t\t\t\t}\n\t\t\t\tsearchPrefix = \"\";\n\t\t\t} else if (rawPrefix.endsWith(\"/\")) {\n\t\t\t\t// If prefix ends with /, show contents of that directory\n\t\t\t\tif (rawPrefix.startsWith(\"~\") || expandedPrefix.startsWith(\"/\")) {\n\t\t\t\t\tsearchDir = expandedPrefix;\n\t\t\t\t} else {\n\t\t\t\t\tsearchDir = join(this.basePath, expandedPrefix);\n\t\t\t\t}\n\t\t\t\tsearchPrefix = \"\";\n\t\t\t} else {\n\t\t\t\t// Split into directory and file prefix\n\t\t\t\tconst dir = dirname(expandedPrefix);\n\t\t\t\tconst file = basename(expandedPrefix);\n\t\t\t\tif (rawPrefix.startsWith(\"~\") || expandedPrefix.startsWith(\"/\")) {\n\t\t\t\t\tsearchDir = dir;\n\t\t\t\t} else {\n\t\t\t\t\tsearchDir = join(this.basePath, dir);\n\t\t\t\t}\n\t\t\t\tsearchPrefix = file;\n\t\t\t}\n\n\t\t\tconst entries = readdirSync(searchDir, { withFileTypes: true });\n\t\t\tconst suggestions: AutocompleteItem[] = [];\n\n\t\t\tfor (const entry of entries) {\n\t\t\t\tif (!entry.name.toLowerCase().startsWith(searchPrefix.toLowerCase())) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Skip excluded directories\n\t\t\t\tif (this.excludeDirs.has(entry.name)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Check if entry is a directory (or a symlink pointing to a directory)\n\t\t\t\tlet isDirectory = entry.isDirectory();\n\t\t\t\tif (!isDirectory && entry.isSymbolicLink()) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst fullPath = join(searchDir, entry.name);\n\t\t\t\t\t\tisDirectory = statSync(fullPath).isDirectory();\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Broken symlink or permission error - treat as file\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlet relativePath: string;\n\t\t\t\tconst name = entry.name;\n\t\t\t\tconst displayPrefix = rawPrefix;\n\n\t\t\t\tif (displayPrefix.endsWith(\"/\")) {\n\t\t\t\t\t// If prefix ends with /, append entry to the prefix\n\t\t\t\t\trelativePath = displayPrefix + name;\n\t\t\t\t} else if (displayPrefix.includes(\"/\")) {\n\t\t\t\t\t// Preserve ~/ format for home directory paths\n\t\t\t\t\tif (displayPrefix.startsWith(\"~/\")) {\n\t\t\t\t\t\tconst homeRelativeDir = displayPrefix.slice(2); // Remove ~/\n\t\t\t\t\t\tconst dir = dirname(homeRelativeDir);\n\t\t\t\t\t\trelativePath = `~/${dir === \".\" ? name : join(dir, name)}`;\n\t\t\t\t\t} else if (displayPrefix.startsWith(\"/\")) {\n\t\t\t\t\t\t// Absolute path - construct properly\n\t\t\t\t\t\tconst dir = dirname(displayPrefix);\n\t\t\t\t\t\tif (dir === \"/\") {\n\t\t\t\t\t\t\trelativePath = `/${name}`;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\trelativePath = `${dir}/${name}`;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\trelativePath = join(dirname(displayPrefix), name);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// For standalone entries, preserve ~/ if original prefix was ~/\n\t\t\t\t\tif (displayPrefix.startsWith(\"~\")) {\n\t\t\t\t\t\trelativePath = `~/${name}`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\trelativePath = name;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst pathValue = isDirectory ? `${relativePath}/` : relativePath;\n\t\t\t\tconst value = buildCompletionValue(pathValue, {\n\t\t\t\t\tisDirectory,\n\t\t\t\t\tisAtPrefix,\n\t\t\t\t\tisQuotedPrefix,\n\t\t\t\t});\n\n\t\t\t\tsuggestions.push({\n\t\t\t\t\tvalue,\n\t\t\t\t\tlabel: name + (isDirectory ? \"/\" : \"\"),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Sort directories first, then alphabetically\n\t\t\tsuggestions.sort((a, b) => {\n\t\t\t\tconst aIsDir = a.value.endsWith(\"/\");\n\t\t\t\tconst bIsDir = b.value.endsWith(\"/\");\n\t\t\t\tif (aIsDir && !bIsDir) return -1;\n\t\t\t\tif (!aIsDir && bIsDir) return 1;\n\t\t\t\treturn a.label.localeCompare(b.label);\n\t\t\t});\n\n\t\t\treturn suggestions;\n\t\t} catch (_e) {\n\t\t\t// Directory doesn't exist or not accessible\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t// Fuzzy file search using the native fd module (fast, respects .gitignore)\n\tprivate getFuzzyFileSuggestions(query: string, options: { isQuotedPrefix: boolean }): AutocompleteItem[] {\n\t\ttry {\n\t\t\tconst scopedQuery = this.resolveScopedFuzzyQuery(query);\n\t\t\tconst searchQuery = scopedQuery?.query ?? query;\n\n\t\t\t// Skip the expensive filesystem walk when the query is empty.\n\t\t\t// An empty query (bare \"@\" with nothing typed yet) would walk the\n\t\t\t// entire directory tree via the native fuzzyFind call, blocking\n\t\t\t// the event loop and freezing the TUI on large repos.\n\t\t\tif (searchQuery.length === 0 && !scopedQuery) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tconst searchPath = scopedQuery?.baseDir ?? this.basePath;\n\n\t\t\tconst result = fuzzyFind({\n\t\t\t\tquery: searchQuery,\n\t\t\t\tpath: searchPath,\n\t\t\t\thidden: true,\n\t\t\t\tgitignore: this.respectGitignore,\n\t\t\t\tmaxResults: FUZZY_FILE_MAX_RESULTS,\n\t\t\t});\n\n\t\t\t// Build suggestions\n\t\t\tconst suggestions: AutocompleteItem[] = [];\n\t\t\tfor (const { path: entryPath, isDirectory } of result.matches) {\n\t\t\t\t// Native module includes trailing / for directories\n\t\t\t\tconst pathWithoutSlash = isDirectory ? entryPath.slice(0, -1) : entryPath;\n\n\t\t\t\t// Skip paths that start with or contain an excluded directory\n\t\t\t\tif (this.excludeDirs.size > 0) {\n\t\t\t\t\tconst segments = pathWithoutSlash.split(\"/\");\n\t\t\t\t\tif (segments.some(seg => this.excludeDirs.has(seg))) continue;\n\t\t\t\t}\n\n\t\t\t\tconst displayPath = scopedQuery\n\t\t\t\t\t? this.scopedPathForDisplay(scopedQuery.displayBase, pathWithoutSlash)\n\t\t\t\t\t: pathWithoutSlash;\n\t\t\t\tconst entryName = basename(pathWithoutSlash);\n\t\t\t\tconst completionPath = isDirectory ? `${displayPath}/` : displayPath;\n\t\t\t\tconst value = buildCompletionValue(completionPath, {\n\t\t\t\t\tisDirectory,\n\t\t\t\t\tisAtPrefix: true,\n\t\t\t\t\tisQuotedPrefix: options.isQuotedPrefix,\n\t\t\t\t});\n\n\t\t\t\tsuggestions.push({\n\t\t\t\t\tvalue,\n\t\t\t\t\tlabel: entryName + (isDirectory ? \"/\" : \"\"),\n\t\t\t\t\tdescription: displayPath,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn suggestions;\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t// Force file completion (called on Tab key) - always returns suggestions\n\tgetForceFileSuggestions(\n\t\tlines: string[],\n\t\tcursorLine: number,\n\t\tcursorCol: number,\n\t): { items: AutocompleteItem[]; prefix: string } | null {\n\t\tconst currentLine = lines[cursorLine] || \"\";\n\t\tconst textBeforeCursor = currentLine.slice(0, cursorCol);\n\n\t\t// Don't trigger if we're typing a slash command at the start of the line\n\t\tif (textBeforeCursor.trim().startsWith(\"/\") && !textBeforeCursor.trim().includes(\" \")) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Force extract path prefix - this will always return something\n\t\tconst pathMatch = this.extractPathPrefix(textBeforeCursor, true);\n\t\tif (pathMatch !== null) {\n\t\t\tconst suggestions = this.getFileSuggestions(pathMatch);\n\t\t\tif (suggestions.length === 0) return null;\n\n\t\t\treturn {\n\t\t\t\titems: suggestions,\n\t\t\t\tprefix: pathMatch,\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t// Check if we should trigger file completion (called on Tab key)\n\tshouldTriggerFileCompletion(lines: string[], cursorLine: number, cursorCol: number): boolean {\n\t\tconst currentLine = lines[cursorLine] || \"\";\n\t\tconst textBeforeCursor = currentLine.slice(0, cursorCol);\n\n\t\t// Don't trigger if we're typing a slash command at the start of the line\n\t\tif (textBeforeCursor.trim().startsWith(\"/\") && !textBeforeCursor.trim().includes(\" \")) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n}\n"]}
1
+ {"version":3,"file":"autocomplete.js","sourceRoot":"","sources":["../src/autocomplete.ts"],"names":[],"mappings":"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","sourcesContent":["import { readdirSync, statSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { basename, dirname, join } from \"path\";\nimport { fuzzyFind } from \"@otto/native/fd\";\nimport { fuzzyFilter } from \"./fuzzy.js\";\n\nconst PATH_DELIMITERS = new Set([\" \", \"\\t\", '\"', \"'\", \"=\"]);\nconst FUZZY_FILE_MAX_RESULTS = 20;\n\nfunction findLastDelimiter(text: string): number {\n\tfor (let i = text.length - 1; i >= 0; i -= 1) {\n\t\tif (PATH_DELIMITERS.has(text[i] ?? \"\")) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn -1;\n}\n\nfunction findUnclosedQuoteStart(text: string): number | null {\n\tlet inQuotes = false;\n\tlet quoteStart = -1;\n\n\tfor (let i = 0; i < text.length; i += 1) {\n\t\tif (text[i] === '\"') {\n\t\t\tinQuotes = !inQuotes;\n\t\t\tif (inQuotes) {\n\t\t\t\tquoteStart = i;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn inQuotes ? quoteStart : null;\n}\n\nfunction isTokenStart(text: string, index: number): boolean {\n\treturn index === 0 || PATH_DELIMITERS.has(text[index - 1] ?? \"\");\n}\n\nfunction extractQuotedPrefix(text: string): string | null {\n\tconst quoteStart = findUnclosedQuoteStart(text);\n\tif (quoteStart === null) {\n\t\treturn null;\n\t}\n\n\tif (quoteStart > 0 && text[quoteStart - 1] === \"@\") {\n\t\tif (!isTokenStart(text, quoteStart - 1)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn text.slice(quoteStart - 1);\n\t}\n\n\tif (!isTokenStart(text, quoteStart)) {\n\t\treturn null;\n\t}\n\n\treturn text.slice(quoteStart);\n}\n\nfunction parsePathPrefix(prefix: string): { rawPrefix: string; isAtPrefix: boolean; isQuotedPrefix: boolean } {\n\tif (prefix.startsWith('@\"')) {\n\t\treturn { rawPrefix: prefix.slice(2), isAtPrefix: true, isQuotedPrefix: true };\n\t}\n\tif (prefix.startsWith('\"')) {\n\t\treturn { rawPrefix: prefix.slice(1), isAtPrefix: false, isQuotedPrefix: true };\n\t}\n\tif (prefix.startsWith(\"@\")) {\n\t\treturn { rawPrefix: prefix.slice(1), isAtPrefix: true, isQuotedPrefix: false };\n\t}\n\treturn { rawPrefix: prefix, isAtPrefix: false, isQuotedPrefix: false };\n}\n\nfunction buildCompletionValue(\n\tpath: string,\n\toptions: { isDirectory: boolean; isAtPrefix: boolean; isQuotedPrefix: boolean },\n): string {\n\tconst needsQuotes = options.isQuotedPrefix || path.includes(\" \");\n\tconst prefix = options.isAtPrefix ? \"@\" : \"\";\n\n\tif (!needsQuotes) {\n\t\treturn `${prefix}${path}`;\n\t}\n\n\tconst openQuote = `${prefix}\"`;\n\tconst closeQuote = '\"';\n\treturn `${openQuote}${path}${closeQuote}`;\n}\n\nexport interface AutocompleteItem {\n\tvalue: string;\n\tlabel: string;\n\tdescription?: string;\n\t/**\n\t * Optional short origin tag rendered before the value as a colored chip\n\t * (e.g. \"claude\", \"codex\", \"kiro\"). The color comes from `SelectListTheme.tag`.\n\t * Kept short (< 12 chars) — long tags eat the visible width budget.\n\t *\n\t * Fork-specific addition. See docs/UPSTREAM-SYNC.md.\n\t */\n\ttag?: string;\n}\n\nexport interface SlashCommand {\n\tname: string;\n\tdescription?: string;\n\ttag?: string;\n\t// Function to get argument completions for this command\n\t// Returns null if no argument completion is available\n\tgetArgumentCompletions?(argumentPrefix: string): AutocompleteItem[] | null;\n}\n\nexport interface AutocompleteProvider {\n\t// Get autocomplete suggestions for current text/cursor position\n\t// Returns null if no suggestions available\n\tgetSuggestions(\n\t\tlines: string[],\n\t\tcursorLine: number,\n\t\tcursorCol: number,\n\t): {\n\t\titems: AutocompleteItem[];\n\t\tprefix: string; // What we're matching against (e.g., \"/\" or \"src/\")\n\t} | null;\n\n\t// Apply the selected item\n\t// Returns the new text and cursor position\n\tapplyCompletion(\n\t\tlines: string[],\n\t\tcursorLine: number,\n\t\tcursorCol: number,\n\t\titem: AutocompleteItem,\n\t\tprefix: string,\n\t): {\n\t\tlines: string[];\n\t\tcursorLine: number;\n\t\tcursorCol: number;\n\t};\n}\n\n// Combined provider that handles both slash commands and file paths\nexport class CombinedAutocompleteProvider implements AutocompleteProvider {\n\tprivate commands: (SlashCommand | AutocompleteItem)[];\n\tprivate basePath: string;\n\tprivate respectGitignore: boolean;\n\tprivate excludeDirs: Set<string>;\n\n\tconstructor(\n\t\tcommands: (SlashCommand | AutocompleteItem)[] = [],\n\t\tbasePath: string = process.cwd(),\n\t\toptions?: { respectGitignore?: boolean; excludeDirs?: string[] },\n\t) {\n\t\tthis.commands = commands;\n\t\tthis.basePath = basePath;\n\t\tthis.respectGitignore = options?.respectGitignore ?? true;\n\t\tthis.excludeDirs = new Set(options?.excludeDirs ?? []);\n\t}\n\n\tsetRespectGitignore(value: boolean): void {\n\t\tthis.respectGitignore = value;\n\t}\n\n\tsetExcludeDirs(dirs: string[]): void {\n\t\tthis.excludeDirs = new Set(dirs.filter(Boolean));\n\t}\n\n\tgetSuggestions(\n\t\tlines: string[],\n\t\tcursorLine: number,\n\t\tcursorCol: number,\n\t): { items: AutocompleteItem[]; prefix: string } | null {\n\t\tconst currentLine = lines[cursorLine] || \"\";\n\t\tconst textBeforeCursor = currentLine.slice(0, cursorCol);\n\t\tconst trimmedBeforeCursor = textBeforeCursor.trimStart();\n\n\t\t// Check for @ file reference (fuzzy search) - must be after a delimiter or at start\n\t\tconst atPrefix = this.extractAtPrefix(textBeforeCursor);\n\t\tif (atPrefix) {\n\t\t\tconst { rawPrefix, isQuotedPrefix } = parsePathPrefix(atPrefix);\n\t\t\tconst suggestions = this.getFuzzyFileSuggestions(rawPrefix, { isQuotedPrefix: isQuotedPrefix });\n\t\t\tif (suggestions.length === 0) return null;\n\n\t\t\treturn {\n\t\t\t\titems: suggestions,\n\t\t\t\tprefix: atPrefix,\n\t\t\t};\n\t\t}\n\n\t\t// Check for slash commands\n\t\tif (trimmedBeforeCursor.startsWith(\"/\")) {\n\t\t\tconst spaceIndex = trimmedBeforeCursor.indexOf(\" \");\n\n\t\t\tif (spaceIndex === -1) {\n\t\t\t\t// No space yet - complete command names with fuzzy matching\n\t\t\t\tconst prefix = trimmedBeforeCursor.slice(1); // Remove the \"/\"\n\t\t\t\tconst commandItems = this.commands.map((cmd) => ({\n\t\t\t\t\tname: \"name\" in cmd ? cmd.name : cmd.value,\n\t\t\t\t\tlabel: \"name\" in cmd ? cmd.name : cmd.label,\n\t\t\t\t\tdescription: cmd.description,\n\t\t\t\t\ttag: cmd.tag,\n\t\t\t\t}));\n\n\t\t\t\tconst filtered = fuzzyFilter(commandItems, prefix, (item) => item.name).map((item) => ({\n\t\t\t\t\tvalue: item.name,\n\t\t\t\t\tlabel: item.label,\n\t\t\t\t\t...(item.description && { description: item.description }),\n\t\t\t\t\t...(item.tag && { tag: item.tag }),\n\t\t\t\t}));\n\n\t\t\t\tif (filtered.length === 0) return null;\n\n\t\t\t\treturn {\n\t\t\t\t\titems: filtered,\n\t\t\t\t\tprefix: `/${prefix}`,\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\t// Space found - complete command arguments\n\t\t\t\tconst commandName = trimmedBeforeCursor.slice(1, spaceIndex); // Command without \"/\"\n\t\t\t\tconst argumentText = trimmedBeforeCursor.slice(spaceIndex + 1); // Text after space\n\n\t\t\t\tconst command = this.commands.find((cmd) => {\n\t\t\t\t\tconst name = \"name\" in cmd ? cmd.name : cmd.value;\n\t\t\t\t\treturn name === commandName;\n\t\t\t\t});\n\t\t\t\tif (!command || !(\"getArgumentCompletions\" in command) || !command.getArgumentCompletions) {\n\t\t\t\t\treturn null; // No argument completion for this command\n\t\t\t\t}\n\n\t\t\t\tconst argumentSuggestions = command.getArgumentCompletions(argumentText);\n\t\t\t\tif (!argumentSuggestions || argumentSuggestions.length === 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\titems: argumentSuggestions,\n\t\t\t\t\tprefix: argumentText,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\t// Check for file paths - triggered by Tab or if we detect a path pattern\n\t\tconst pathMatch = this.extractPathPrefix(textBeforeCursor, false);\n\n\t\tif (pathMatch !== null) {\n\t\t\tconst suggestions = this.getFileSuggestions(pathMatch);\n\t\t\tif (suggestions.length === 0) return null;\n\n\t\t\t// Check if we have an exact match that is a directory\n\t\t\t// In that case, we might want to return suggestions for the directory content instead\n\t\t\t// But only if the prefix ends with /\n\t\t\tif (suggestions.length === 1 && suggestions[0]?.value === pathMatch && !pathMatch.endsWith(\"/\")) {\n\t\t\t\t// Exact match found (e.g. user typed \"src\" and \"src/\" is the only match)\n\t\t\t\t// We still return it so user can select it and add /\n\t\t\t\treturn {\n\t\t\t\t\titems: suggestions,\n\t\t\t\t\tprefix: pathMatch,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\titems: suggestions,\n\t\t\t\tprefix: pathMatch,\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tapplyCompletion(\n\t\tlines: string[],\n\t\tcursorLine: number,\n\t\tcursorCol: number,\n\t\titem: AutocompleteItem,\n\t\tprefix: string,\n\t): { lines: string[]; cursorLine: number; cursorCol: number } {\n\t\tconst currentLine = lines[cursorLine] || \"\";\n\t\tconst beforePrefix = currentLine.slice(0, cursorCol - prefix.length);\n\t\tconst afterCursor = currentLine.slice(cursorCol);\n\t\tconst isQuotedPrefix = prefix.startsWith('\"') || prefix.startsWith('@\"');\n\t\tconst hasLeadingQuoteAfterCursor = afterCursor.startsWith('\"');\n\t\tconst hasTrailingQuoteInItem = item.value.endsWith('\"');\n\t\tconst adjustedAfterCursor =\n\t\t\tisQuotedPrefix && hasTrailingQuoteInItem && hasLeadingQuoteAfterCursor ? afterCursor.slice(1) : afterCursor;\n\n\t\t// Check if we're completing a slash command (prefix starts with \"/\" but NOT a file path)\n\t\t// Slash commands are at the start of the line and don't contain path separators after the first /\n\t\tconst trimmedPrefix = prefix.trimStart();\n\t\tconst isSlashCommand = trimmedPrefix.startsWith(\"/\") && beforePrefix.trim() === \"\" && !trimmedPrefix.slice(1).includes(\"/\");\n\t\tif (isSlashCommand) {\n\t\t\t// This is a command name completion\n\t\t\tconst newLine = `${beforePrefix}/${item.value} ${adjustedAfterCursor}`;\n\t\t\tconst newLines = [...lines];\n\t\t\tnewLines[cursorLine] = newLine;\n\n\t\t\treturn {\n\t\t\t\tlines: newLines,\n\t\t\t\tcursorLine,\n\t\t\t\tcursorCol: beforePrefix.length + item.value.length + 2, // +2 for \"/\" and space\n\t\t\t};\n\t\t}\n\n\t\t// Check if we're completing a file attachment (prefix starts with \"@\")\n\t\tif (prefix.startsWith(\"@\")) {\n\t\t\t// This is a file attachment completion\n\t\t\t// Don't add space after directories so user can continue autocompleting\n\t\t\tconst isDirectory = item.label.endsWith(\"/\");\n\t\t\tconst suffix = isDirectory ? \"\" : \" \";\n\t\t\tconst newLine = `${beforePrefix + item.value}${suffix}${adjustedAfterCursor}`;\n\t\t\tconst newLines = [...lines];\n\t\t\tnewLines[cursorLine] = newLine;\n\n\t\t\tconst hasTrailingQuote = item.value.endsWith('\"');\n\t\t\tconst cursorOffset = isDirectory && hasTrailingQuote ? item.value.length - 1 : item.value.length;\n\n\t\t\treturn {\n\t\t\t\tlines: newLines,\n\t\t\t\tcursorLine,\n\t\t\t\tcursorCol: beforePrefix.length + cursorOffset + suffix.length,\n\t\t\t};\n\t\t}\n\n\t\t// Check if we're in a slash command context (beforePrefix contains \"/command \")\n\t\tconst textBeforeCursor = currentLine.slice(0, cursorCol);\n\t\tif (textBeforeCursor.includes(\"/\") && textBeforeCursor.includes(\" \")) {\n\t\t\t// This is likely a command argument completion\n\t\t\tconst newLine = beforePrefix + item.value + adjustedAfterCursor;\n\t\t\tconst newLines = [...lines];\n\t\t\tnewLines[cursorLine] = newLine;\n\n\t\t\tconst isDirectory = item.label.endsWith(\"/\");\n\t\t\tconst hasTrailingQuote = item.value.endsWith('\"');\n\t\t\tconst cursorOffset = isDirectory && hasTrailingQuote ? item.value.length - 1 : item.value.length;\n\n\t\t\treturn {\n\t\t\t\tlines: newLines,\n\t\t\t\tcursorLine,\n\t\t\t\tcursorCol: beforePrefix.length + cursorOffset,\n\t\t\t};\n\t\t}\n\n\t\t// For file paths, complete the path\n\t\tconst newLine = beforePrefix + item.value + adjustedAfterCursor;\n\t\tconst newLines = [...lines];\n\t\tnewLines[cursorLine] = newLine;\n\n\t\tconst isDirectory = item.label.endsWith(\"/\");\n\t\tconst hasTrailingQuote = item.value.endsWith('\"');\n\t\tconst cursorOffset = isDirectory && hasTrailingQuote ? item.value.length - 1 : item.value.length;\n\n\t\treturn {\n\t\t\tlines: newLines,\n\t\t\tcursorLine,\n\t\t\tcursorCol: beforePrefix.length + cursorOffset,\n\t\t};\n\t}\n\n\t// Extract @ prefix for fuzzy file suggestions\n\tprivate extractAtPrefix(text: string): string | null {\n\t\tconst quotedPrefix = extractQuotedPrefix(text);\n\t\tif (quotedPrefix?.startsWith('@\"')) {\n\t\t\treturn quotedPrefix;\n\t\t}\n\n\t\tconst lastDelimiterIndex = findLastDelimiter(text);\n\t\tconst tokenStart = lastDelimiterIndex === -1 ? 0 : lastDelimiterIndex + 1;\n\n\t\tif (text[tokenStart] === \"@\") {\n\t\t\treturn text.slice(tokenStart);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t// Extract a path-like prefix from the text before cursor\n\tprivate extractPathPrefix(text: string, forceExtract: boolean = false): string | null {\n\t\tconst quotedPrefix = extractQuotedPrefix(text);\n\t\tif (quotedPrefix) {\n\t\t\treturn quotedPrefix;\n\t\t}\n\n\t\tconst lastDelimiterIndex = findLastDelimiter(text);\n\t\tconst pathPrefix = lastDelimiterIndex === -1 ? text : text.slice(lastDelimiterIndex + 1);\n\n\t\t// For forced extraction (Tab key), always return something\n\t\tif (forceExtract) {\n\t\t\treturn pathPrefix;\n\t\t}\n\n\t\t// For natural triggers, return if it looks like a path, ends with /, starts with ~/, .\n\t\t// Only return empty string if the text looks like it's starting a path context\n\t\tif (pathPrefix.includes(\"/\") || pathPrefix.startsWith(\".\") || pathPrefix.startsWith(\"~/\")) {\n\t\t\treturn pathPrefix;\n\t\t}\n\n\t\t// Return empty string only after a space (not for completely empty text)\n\t\t// Empty text should not trigger file suggestions - that's for forced Tab completion\n\t\tif (pathPrefix === \"\" && text.endsWith(\" \")) {\n\t\t\treturn pathPrefix;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t// Expand home directory (~/) to actual home path\n\tprivate expandHomePath(path: string): string {\n\t\tif (path.startsWith(\"~/\")) {\n\t\t\tconst expandedPath = join(homedir(), path.slice(2));\n\t\t\t// Preserve trailing slash if original path had one\n\t\t\treturn path.endsWith(\"/\") && !expandedPath.endsWith(\"/\") ? `${expandedPath}/` : expandedPath;\n\t\t} else if (path === \"~\") {\n\t\t\treturn homedir();\n\t\t}\n\t\treturn path;\n\t}\n\n\tprivate resolveScopedFuzzyQuery(rawQuery: string): { baseDir: string; query: string; displayBase: string } | null {\n\t\tconst slashIndex = rawQuery.lastIndexOf(\"/\");\n\t\tif (slashIndex === -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst displayBase = rawQuery.slice(0, slashIndex + 1);\n\t\tconst query = rawQuery.slice(slashIndex + 1);\n\n\t\tlet baseDir: string;\n\t\tif (displayBase.startsWith(\"~/\")) {\n\t\t\tbaseDir = this.expandHomePath(displayBase);\n\t\t} else if (displayBase.startsWith(\"/\")) {\n\t\t\tbaseDir = displayBase;\n\t\t} else {\n\t\t\tbaseDir = join(this.basePath, displayBase);\n\t\t}\n\n\t\ttry {\n\t\t\tif (!statSync(baseDir).isDirectory()) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn { baseDir, query, displayBase };\n\t}\n\n\tprivate scopedPathForDisplay(displayBase: string, relativePath: string): string {\n\t\tif (displayBase === \"/\") {\n\t\t\treturn `/${relativePath}`;\n\t\t}\n\t\treturn `${displayBase}${relativePath}`;\n\t}\n\n\t// Get file/directory suggestions for a given path prefix\n\tprivate getFileSuggestions(prefix: string): AutocompleteItem[] {\n\t\ttry {\n\t\t\tlet searchDir: string;\n\t\t\tlet searchPrefix: string;\n\t\t\tconst { rawPrefix, isAtPrefix, isQuotedPrefix } = parsePathPrefix(prefix);\n\t\t\tlet expandedPrefix = rawPrefix;\n\n\t\t\t// Handle home directory expansion\n\t\t\tif (expandedPrefix.startsWith(\"~\")) {\n\t\t\t\texpandedPrefix = this.expandHomePath(expandedPrefix);\n\t\t\t}\n\n\t\t\tconst isRootPrefix =\n\t\t\t\trawPrefix === \"\" ||\n\t\t\t\trawPrefix === \"./\" ||\n\t\t\t\trawPrefix === \"../\" ||\n\t\t\t\trawPrefix === \"~\" ||\n\t\t\t\trawPrefix === \"~/\" ||\n\t\t\t\trawPrefix === \"/\" ||\n\t\t\t\t(isAtPrefix && rawPrefix === \"\");\n\n\t\t\tif (isRootPrefix) {\n\t\t\t\t// Complete from specified position\n\t\t\t\tif (rawPrefix.startsWith(\"~\") || expandedPrefix.startsWith(\"/\")) {\n\t\t\t\t\tsearchDir = expandedPrefix;\n\t\t\t\t} else {\n\t\t\t\t\tsearchDir = join(this.basePath, expandedPrefix);\n\t\t\t\t}\n\t\t\t\tsearchPrefix = \"\";\n\t\t\t} else if (rawPrefix.endsWith(\"/\")) {\n\t\t\t\t// If prefix ends with /, show contents of that directory\n\t\t\t\tif (rawPrefix.startsWith(\"~\") || expandedPrefix.startsWith(\"/\")) {\n\t\t\t\t\tsearchDir = expandedPrefix;\n\t\t\t\t} else {\n\t\t\t\t\tsearchDir = join(this.basePath, expandedPrefix);\n\t\t\t\t}\n\t\t\t\tsearchPrefix = \"\";\n\t\t\t} else {\n\t\t\t\t// Split into directory and file prefix\n\t\t\t\tconst dir = dirname(expandedPrefix);\n\t\t\t\tconst file = basename(expandedPrefix);\n\t\t\t\tif (rawPrefix.startsWith(\"~\") || expandedPrefix.startsWith(\"/\")) {\n\t\t\t\t\tsearchDir = dir;\n\t\t\t\t} else {\n\t\t\t\t\tsearchDir = join(this.basePath, dir);\n\t\t\t\t}\n\t\t\t\tsearchPrefix = file;\n\t\t\t}\n\n\t\t\tconst entries = readdirSync(searchDir, { withFileTypes: true });\n\t\t\tconst suggestions: AutocompleteItem[] = [];\n\n\t\t\tfor (const entry of entries) {\n\t\t\t\tif (!entry.name.toLowerCase().startsWith(searchPrefix.toLowerCase())) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Skip excluded directories\n\t\t\t\tif (this.excludeDirs.has(entry.name)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Check if entry is a directory (or a symlink pointing to a directory)\n\t\t\t\tlet isDirectory = entry.isDirectory();\n\t\t\t\tif (!isDirectory && entry.isSymbolicLink()) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst fullPath = join(searchDir, entry.name);\n\t\t\t\t\t\tisDirectory = statSync(fullPath).isDirectory();\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Broken symlink or permission error - treat as file\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlet relativePath: string;\n\t\t\t\tconst name = entry.name;\n\t\t\t\tconst displayPrefix = rawPrefix;\n\n\t\t\t\tif (displayPrefix.endsWith(\"/\")) {\n\t\t\t\t\t// If prefix ends with /, append entry to the prefix\n\t\t\t\t\trelativePath = displayPrefix + name;\n\t\t\t\t} else if (displayPrefix.includes(\"/\")) {\n\t\t\t\t\t// Preserve ~/ format for home directory paths\n\t\t\t\t\tif (displayPrefix.startsWith(\"~/\")) {\n\t\t\t\t\t\tconst homeRelativeDir = displayPrefix.slice(2); // Remove ~/\n\t\t\t\t\t\tconst dir = dirname(homeRelativeDir);\n\t\t\t\t\t\trelativePath = `~/${dir === \".\" ? name : join(dir, name)}`;\n\t\t\t\t\t} else if (displayPrefix.startsWith(\"/\")) {\n\t\t\t\t\t\t// Absolute path - construct properly\n\t\t\t\t\t\tconst dir = dirname(displayPrefix);\n\t\t\t\t\t\tif (dir === \"/\") {\n\t\t\t\t\t\t\trelativePath = `/${name}`;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\trelativePath = `${dir}/${name}`;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\trelativePath = join(dirname(displayPrefix), name);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// For standalone entries, preserve ~/ if original prefix was ~/\n\t\t\t\t\tif (displayPrefix.startsWith(\"~\")) {\n\t\t\t\t\t\trelativePath = `~/${name}`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\trelativePath = name;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst pathValue = isDirectory ? `${relativePath}/` : relativePath;\n\t\t\t\tconst value = buildCompletionValue(pathValue, {\n\t\t\t\t\tisDirectory,\n\t\t\t\t\tisAtPrefix,\n\t\t\t\t\tisQuotedPrefix,\n\t\t\t\t});\n\n\t\t\t\tsuggestions.push({\n\t\t\t\t\tvalue,\n\t\t\t\t\tlabel: name + (isDirectory ? \"/\" : \"\"),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Sort directories first, then alphabetically\n\t\t\tsuggestions.sort((a, b) => {\n\t\t\t\tconst aIsDir = a.value.endsWith(\"/\");\n\t\t\t\tconst bIsDir = b.value.endsWith(\"/\");\n\t\t\t\tif (aIsDir && !bIsDir) return -1;\n\t\t\t\tif (!aIsDir && bIsDir) return 1;\n\t\t\t\treturn a.label.localeCompare(b.label);\n\t\t\t});\n\n\t\t\treturn suggestions;\n\t\t} catch (_e) {\n\t\t\t// Directory doesn't exist or not accessible\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t// Fuzzy file search using the native fd module (fast, respects .gitignore)\n\tprivate getFuzzyFileSuggestions(query: string, options: { isQuotedPrefix: boolean }): AutocompleteItem[] {\n\t\ttry {\n\t\t\tconst scopedQuery = this.resolveScopedFuzzyQuery(query);\n\t\t\tconst searchQuery = scopedQuery?.query ?? query;\n\n\t\t\t// Skip the expensive filesystem walk when the query is empty.\n\t\t\t// An empty query (bare \"@\" with nothing typed yet) would walk the\n\t\t\t// entire directory tree via the native fuzzyFind call, blocking\n\t\t\t// the event loop and freezing the TUI on large repos.\n\t\t\tif (searchQuery.length === 0 && !scopedQuery) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tconst searchPath = scopedQuery?.baseDir ?? this.basePath;\n\n\t\t\tconst result = fuzzyFind({\n\t\t\t\tquery: searchQuery,\n\t\t\t\tpath: searchPath,\n\t\t\t\thidden: true,\n\t\t\t\tgitignore: this.respectGitignore,\n\t\t\t\tmaxResults: FUZZY_FILE_MAX_RESULTS,\n\t\t\t});\n\n\t\t\t// Build suggestions\n\t\t\tconst suggestions: AutocompleteItem[] = [];\n\t\t\tfor (const { path: entryPath, isDirectory } of result.matches) {\n\t\t\t\t// Native module includes trailing / for directories\n\t\t\t\tconst pathWithoutSlash = isDirectory ? entryPath.slice(0, -1) : entryPath;\n\n\t\t\t\t// Skip paths that start with or contain an excluded directory\n\t\t\t\tif (this.excludeDirs.size > 0) {\n\t\t\t\t\tconst segments = pathWithoutSlash.split(\"/\");\n\t\t\t\t\tif (segments.some(seg => this.excludeDirs.has(seg))) continue;\n\t\t\t\t}\n\n\t\t\t\tconst displayPath = scopedQuery\n\t\t\t\t\t? this.scopedPathForDisplay(scopedQuery.displayBase, pathWithoutSlash)\n\t\t\t\t\t: pathWithoutSlash;\n\t\t\t\tconst entryName = basename(pathWithoutSlash);\n\t\t\t\tconst completionPath = isDirectory ? `${displayPath}/` : displayPath;\n\t\t\t\tconst value = buildCompletionValue(completionPath, {\n\t\t\t\t\tisDirectory,\n\t\t\t\t\tisAtPrefix: true,\n\t\t\t\t\tisQuotedPrefix: options.isQuotedPrefix,\n\t\t\t\t});\n\n\t\t\t\tsuggestions.push({\n\t\t\t\t\tvalue,\n\t\t\t\t\tlabel: entryName + (isDirectory ? \"/\" : \"\"),\n\t\t\t\t\tdescription: displayPath,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn suggestions;\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t// Force file completion (called on Tab key) - always returns suggestions\n\tgetForceFileSuggestions(\n\t\tlines: string[],\n\t\tcursorLine: number,\n\t\tcursorCol: number,\n\t): { items: AutocompleteItem[]; prefix: string } | null {\n\t\tconst currentLine = lines[cursorLine] || \"\";\n\t\tconst textBeforeCursor = currentLine.slice(0, cursorCol);\n\n\t\t// Don't trigger if we're typing a slash command at the start of the line\n\t\tif (textBeforeCursor.trim().startsWith(\"/\") && !textBeforeCursor.trim().includes(\" \")) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Force extract path prefix - this will always return something\n\t\tconst pathMatch = this.extractPathPrefix(textBeforeCursor, true);\n\t\tif (pathMatch !== null) {\n\t\t\tconst suggestions = this.getFileSuggestions(pathMatch);\n\t\t\tif (suggestions.length === 0) return null;\n\n\t\t\treturn {\n\t\t\t\titems: suggestions,\n\t\t\t\tprefix: pathMatch,\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t// Check if we should trigger file completion (called on Tab key)\n\tshouldTriggerFileCompletion(lines: string[], cursorLine: number, cursorCol: number): boolean {\n\t\tconst currentLine = lines[cursorLine] || \"\";\n\t\tconst textBeforeCursor = currentLine.slice(0, cursorCol);\n\n\t\t// Don't trigger if we're typing a slash command at the start of the line\n\t\tif (textBeforeCursor.trim().startsWith(\"/\") && !textBeforeCursor.trim().includes(\" \")) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n}\n"]}
@@ -3,6 +3,14 @@ export interface SelectItem {
3
3
  value: string;
4
4
  label: string;
5
5
  description?: string;
6
+ /**
7
+ * Optional short origin tag rendered as a colored chip before the value
8
+ * (e.g. "claude"). Color is `SelectListTheme.tag`. Adds `[<tag>] ` to the
9
+ * displayed line — counts against the visible-width budget.
10
+ *
11
+ * Fork-specific addition. See docs/UPSTREAM-SYNC.md.
12
+ */
13
+ tag?: string;
6
14
  }
7
15
  export interface SelectListTheme {
8
16
  selectedPrefix: (text: string) => string;
@@ -10,6 +18,8 @@ export interface SelectListTheme {
10
18
  description: (text: string) => string;
11
19
  scrollInfo: (text: string) => string;
12
20
  noMatch: (text: string) => string;
21
+ /** Optional. Color for the leading `[tag] ` chip when SelectItem.tag is set. */
22
+ tag?: (text: string) => string;
13
23
  }
14
24
  export declare class SelectList implements Component {
15
25
  private items;
@@ -1 +1 @@
1
- {"version":3,"file":"select-list.d.ts","sourceRoot":"","sources":["../../src/components/select-list.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAK3C,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC/B,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAClC;AAED,qBAAa,UAAW,YAAW,SAAS;IAC3C,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,KAAK,CAAkB;IAExB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;gBAE1C,KAAK,EAAE,UAAU,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe;IAO3E,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAM/B,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIrC,UAAU,IAAI,IAAI;IAIlB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAiG/B,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAiClC,OAAO,CAAC,qBAAqB;IAO7B,eAAe,IAAI,UAAU,GAAG,IAAI;CAIpC"}
1
+ {"version":3,"file":"select-list.d.ts","sourceRoot":"","sources":["../../src/components/select-list.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAK3C,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,eAAe;IAC/B,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAClC,gFAAgF;IAChF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC/B;AAED,qBAAa,UAAW,YAAW,SAAS;IAC3C,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,KAAK,CAAkB;IAExB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;gBAE1C,KAAK,EAAE,UAAU,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe;IAO3E,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAM/B,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIrC,UAAU,IAAI,IAAI;IAIlB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IA+G/B,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAiClC,OAAO,CAAC,qBAAqB;IAO7B,eAAe,IAAI,UAAU,GAAG,IAAI;CAIpC"}
@@ -40,6 +40,16 @@ export class SelectList {
40
40
  continue;
41
41
  const isSelected = i === this.selectedIndex;
42
42
  const descriptionSingleLine = item.description ? normalizeToSingleLine(item.description) : undefined;
43
+ // Optional origin chip rendered before the value. The plain text is
44
+ // ASCII-only (no ANSI), so .length equals visible width and feeds
45
+ // directly into layout math. The colored variant is only used when
46
+ // the row is NOT selected — selectedText wraps the whole row and
47
+ // would clobber any inner colors.
48
+ const tagChipText = item.tag ? `[${item.tag}] ` : "";
49
+ const tagChipWidth = tagChipText.length;
50
+ const tagChipColored = item.tag && this.theme.tag
51
+ ? this.theme.tag(tagChipText)
52
+ : tagChipText;
43
53
  let line = "";
44
54
  if (isSelected) {
45
55
  // Use arrow indicator for selection - entire line uses selectedText color
@@ -47,27 +57,30 @@ export class SelectList {
47
57
  const displayValue = item.label || item.value;
48
58
  if (descriptionSingleLine && width > 40) {
49
59
  // Calculate how much space we have for value + description
50
- const maxValueWidth = Math.min(30, width - prefixWidth - 4);
60
+ // (chip width is subtracted so descriptions stay aligned with
61
+ // non-chipped rows)
62
+ const maxValueWidth = Math.min(30, width - prefixWidth - 4 - tagChipWidth);
51
63
  const truncatedValue = truncateToWidth(displayValue, maxValueWidth, "");
52
- const spacing = " ".repeat(Math.max(1, 32 - truncatedValue.length));
64
+ const spacing = " ".repeat(Math.max(1, 32 - truncatedValue.length - tagChipWidth));
53
65
  // Calculate remaining space for description using visible widths
54
- const descriptionStart = prefixWidth + truncatedValue.length + spacing.length;
66
+ const descriptionStart = prefixWidth + tagChipWidth + truncatedValue.length + spacing.length;
55
67
  const remainingWidth = width - descriptionStart - 2; // -2 for safety
56
68
  if (remainingWidth > 10) {
57
69
  const truncatedDesc = truncateToWidth(descriptionSingleLine, remainingWidth, "");
58
- // Apply selectedText to entire line content
59
- line = this.theme.selectedText(`→ ${truncatedValue}${spacing}${truncatedDesc}`);
70
+ // Apply selectedText to entire line content (chip uncolored
71
+ // here the highlight already conveys selection state)
72
+ line = this.theme.selectedText(`→ ${tagChipText}${truncatedValue}${spacing}${truncatedDesc}`);
60
73
  }
61
74
  else {
62
75
  // Not enough space for description
63
- const maxWidth = width - prefixWidth - 2;
64
- line = this.theme.selectedText(`→ ${truncateToWidth(displayValue, maxWidth, "")}`);
76
+ const maxWidth = width - prefixWidth - 2 - tagChipWidth;
77
+ line = this.theme.selectedText(`→ ${tagChipText}${truncateToWidth(displayValue, maxWidth, "")}`);
65
78
  }
66
79
  }
67
80
  else {
68
81
  // No description or not enough width
69
- const maxWidth = width - prefixWidth - 2;
70
- line = this.theme.selectedText(`→ ${truncateToWidth(displayValue, maxWidth, "")}`);
82
+ const maxWidth = width - prefixWidth - 2 - tagChipWidth;
83
+ line = this.theme.selectedText(`→ ${tagChipText}${truncateToWidth(displayValue, maxWidth, "")}`);
71
84
  }
72
85
  }
73
86
  else {
@@ -75,27 +88,27 @@ export class SelectList {
75
88
  const prefix = " ";
76
89
  if (descriptionSingleLine && width > 40) {
77
90
  // Calculate how much space we have for value + description
78
- const maxValueWidth = Math.min(30, width - prefix.length - 4);
91
+ const maxValueWidth = Math.min(30, width - prefix.length - 4 - tagChipWidth);
79
92
  const truncatedValue = truncateToWidth(displayValue, maxValueWidth, "");
80
- const spacing = " ".repeat(Math.max(1, 32 - truncatedValue.length));
93
+ const spacing = " ".repeat(Math.max(1, 32 - truncatedValue.length - tagChipWidth));
81
94
  // Calculate remaining space for description
82
- const descriptionStart = prefix.length + truncatedValue.length + spacing.length;
95
+ const descriptionStart = prefix.length + tagChipWidth + truncatedValue.length + spacing.length;
83
96
  const remainingWidth = width - descriptionStart - 2; // -2 for safety
84
97
  if (remainingWidth > 10) {
85
98
  const truncatedDesc = truncateToWidth(descriptionSingleLine, remainingWidth, "");
86
99
  const descText = this.theme.description(spacing + truncatedDesc);
87
- line = prefix + truncatedValue + descText;
100
+ line = prefix + tagChipColored + truncatedValue + descText;
88
101
  }
89
102
  else {
90
103
  // Not enough space for description
91
- const maxWidth = width - prefix.length - 2;
92
- line = prefix + truncateToWidth(displayValue, maxWidth, "");
104
+ const maxWidth = width - prefix.length - 2 - tagChipWidth;
105
+ line = prefix + tagChipColored + truncateToWidth(displayValue, maxWidth, "");
93
106
  }
94
107
  }
95
108
  else {
96
109
  // No description or not enough width
97
- const maxWidth = width - prefix.length - 2;
98
- line = prefix + truncateToWidth(displayValue, maxWidth, "");
110
+ const maxWidth = width - prefix.length - 2 - tagChipWidth;
111
+ line = prefix + tagChipColored + truncateToWidth(displayValue, maxWidth, "");
99
112
  }
100
113
  }
101
114
  lines.push(line);
@@ -1 +1 @@
1
- {"version":3,"file":"select-list.js","sourceRoot":"","sources":["../../src/components/select-list.ts"],"names":[],"mappings":"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","sourcesContent":["import { getEditorKeybindings } from \"../keybindings.js\";\nimport type { Component } from \"../tui.js\";\nimport { truncateToWidth } from \"../utils.js\";\n\nconst normalizeToSingleLine = (text: string): string => text.replace(/[\\r\\n]+/g, \" \").trim();\n\nexport interface SelectItem {\n\tvalue: string;\n\tlabel: string;\n\tdescription?: string;\n}\n\nexport interface SelectListTheme {\n\tselectedPrefix: (text: string) => string;\n\tselectedText: (text: string) => string;\n\tdescription: (text: string) => string;\n\tscrollInfo: (text: string) => string;\n\tnoMatch: (text: string) => string;\n}\n\nexport class SelectList implements Component {\n\tprivate items: SelectItem[] = [];\n\tprivate filteredItems: SelectItem[] = [];\n\tprivate selectedIndex: number = 0;\n\tprivate maxVisible: number = 5;\n\tprivate theme: SelectListTheme;\n\n\tpublic onSelect?: (item: SelectItem) => void;\n\tpublic onCancel?: () => void;\n\tpublic onSelectionChange?: (item: SelectItem) => void;\n\n\tconstructor(items: SelectItem[], maxVisible: number, theme: SelectListTheme) {\n\t\tthis.items = items;\n\t\tthis.filteredItems = items;\n\t\tthis.maxVisible = maxVisible;\n\t\tthis.theme = theme;\n\t}\n\n\tsetFilter(filter: string): void {\n\t\tthis.filteredItems = this.items.filter((item) => item.value.toLowerCase().startsWith(filter.toLowerCase()));\n\t\t// Reset selection when filter changes\n\t\tthis.selectedIndex = 0;\n\t}\n\n\tsetSelectedIndex(index: number): void {\n\t\tthis.selectedIndex = Math.max(0, Math.min(index, this.filteredItems.length - 1));\n\t}\n\n\tinvalidate(): void {\n\t\t// No cached state to invalidate currently\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\n\t\t// If no items match filter, show message\n\t\tif (this.filteredItems.length === 0) {\n\t\t\tlines.push(this.theme.noMatch(\" No matching commands\"));\n\t\t\treturn lines;\n\t\t}\n\n\t\t// Calculate visible range with scrolling\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(this.maxVisible / 2), this.filteredItems.length - this.maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + this.maxVisible, this.filteredItems.length);\n\n\t\t// Render visible items\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst item = this.filteredItems[i];\n\t\t\tif (!item) continue;\n\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst descriptionSingleLine = item.description ? normalizeToSingleLine(item.description) : undefined;\n\n\t\t\tlet line = \"\";\n\t\t\tif (isSelected) {\n\t\t\t\t// Use arrow indicator for selection - entire line uses selectedText color\n\t\t\t\tconst prefixWidth = 2; // \"→ \" is 2 characters visually\n\t\t\t\tconst displayValue = item.label || item.value;\n\n\t\t\t\tif (descriptionSingleLine && width > 40) {\n\t\t\t\t\t// Calculate how much space we have for value + description\n\t\t\t\t\tconst maxValueWidth = Math.min(30, width - prefixWidth - 4);\n\t\t\t\t\tconst truncatedValue = truncateToWidth(displayValue, maxValueWidth, \"\");\n\t\t\t\t\tconst spacing = \" \".repeat(Math.max(1, 32 - truncatedValue.length));\n\n\t\t\t\t\t// Calculate remaining space for description using visible widths\n\t\t\t\t\tconst descriptionStart = prefixWidth + truncatedValue.length + spacing.length;\n\t\t\t\t\tconst remainingWidth = width - descriptionStart - 2; // -2 for safety\n\n\t\t\t\t\tif (remainingWidth > 10) {\n\t\t\t\t\t\tconst truncatedDesc = truncateToWidth(descriptionSingleLine, remainingWidth, \"\");\n\t\t\t\t\t\t// Apply selectedText to entire line content\n\t\t\t\t\t\tline = this.theme.selectedText(`→ ${truncatedValue}${spacing}${truncatedDesc}`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Not enough space for description\n\t\t\t\t\t\tconst maxWidth = width - prefixWidth - 2;\n\t\t\t\t\t\tline = this.theme.selectedText(`→ ${truncateToWidth(displayValue, maxWidth, \"\")}`);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// No description or not enough width\n\t\t\t\t\tconst maxWidth = width - prefixWidth - 2;\n\t\t\t\t\tline = this.theme.selectedText(`→ ${truncateToWidth(displayValue, maxWidth, \"\")}`);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst displayValue = item.label || item.value;\n\t\t\t\tconst prefix = \" \";\n\n\t\t\t\tif (descriptionSingleLine && width > 40) {\n\t\t\t\t\t// Calculate how much space we have for value + description\n\t\t\t\t\tconst maxValueWidth = Math.min(30, width - prefix.length - 4);\n\t\t\t\t\tconst truncatedValue = truncateToWidth(displayValue, maxValueWidth, \"\");\n\t\t\t\t\tconst spacing = \" \".repeat(Math.max(1, 32 - truncatedValue.length));\n\n\t\t\t\t\t// Calculate remaining space for description\n\t\t\t\t\tconst descriptionStart = prefix.length + truncatedValue.length + spacing.length;\n\t\t\t\t\tconst remainingWidth = width - descriptionStart - 2; // -2 for safety\n\n\t\t\t\t\tif (remainingWidth > 10) {\n\t\t\t\t\t\tconst truncatedDesc = truncateToWidth(descriptionSingleLine, remainingWidth, \"\");\n\t\t\t\t\t\tconst descText = this.theme.description(spacing + truncatedDesc);\n\t\t\t\t\t\tline = prefix + truncatedValue + descText;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Not enough space for description\n\t\t\t\t\t\tconst maxWidth = width - prefix.length - 2;\n\t\t\t\t\t\tline = prefix + truncateToWidth(displayValue, maxWidth, \"\");\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// No description or not enough width\n\t\t\t\t\tconst maxWidth = width - prefix.length - 2;\n\t\t\t\t\tline = prefix + truncateToWidth(displayValue, maxWidth, \"\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlines.push(line);\n\t\t}\n\n\t\t// Add scroll indicators if needed\n\t\tif (startIndex > 0 || endIndex < this.filteredItems.length) {\n\t\t\tconst scrollText = ` (${this.selectedIndex + 1}/${this.filteredItems.length})`;\n\t\t\t// Truncate if too long for terminal\n\t\t\tlines.push(this.theme.scrollInfo(truncateToWidth(scrollText, width - 2, \"\")));\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getEditorKeybindings();\n\t\t// Nothing to navigate or select when the filter matches no items.\n\t\t// Without this guard selectUp would set selectedIndex to -1.\n\t\tif (this.filteredItems.length === 0) {\n\t\t\tif (kb.matches(keyData, \"selectCancel\") && this.onCancel) this.onCancel();\n\t\t\treturn;\n\t\t}\n\t\t// Up arrow - wrap to bottom when at top\n\t\tif (kb.matches(keyData, \"selectUp\")) {\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.filteredItems.length - 1 : this.selectedIndex - 1;\n\t\t\tthis.notifySelectionChange();\n\t\t}\n\t\t// Down arrow - wrap to top when at bottom\n\t\telse if (kb.matches(keyData, \"selectDown\")) {\n\t\t\tthis.selectedIndex = this.selectedIndex === this.filteredItems.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\tthis.notifySelectionChange();\n\t\t}\n\t\t// Enter\n\t\telse if (kb.matches(keyData, \"selectConfirm\")) {\n\t\t\tconst selectedItem = this.filteredItems[this.selectedIndex];\n\t\t\tif (selectedItem && this.onSelect) {\n\t\t\t\tthis.onSelect(selectedItem);\n\t\t\t}\n\t\t}\n\t\t// Escape or Ctrl+C\n\t\telse if (kb.matches(keyData, \"selectCancel\")) {\n\t\t\tif (this.onCancel) {\n\t\t\t\tthis.onCancel();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate notifySelectionChange(): void {\n\t\tconst selectedItem = this.filteredItems[this.selectedIndex];\n\t\tif (selectedItem && this.onSelectionChange) {\n\t\t\tthis.onSelectionChange(selectedItem);\n\t\t}\n\t}\n\n\tgetSelectedItem(): SelectItem | null {\n\t\tconst item = this.filteredItems[this.selectedIndex];\n\t\treturn item || null;\n\t}\n}\n"]}
1
+ {"version":3,"file":"select-list.js","sourceRoot":"","sources":["../../src/components/select-list.ts"],"names":[],"mappings":"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","sourcesContent":["import { getEditorKeybindings } from \"../keybindings.js\";\nimport type { Component } from \"../tui.js\";\nimport { truncateToWidth } from \"../utils.js\";\n\nconst normalizeToSingleLine = (text: string): string => text.replace(/[\\r\\n]+/g, \" \").trim();\n\nexport interface SelectItem {\n\tvalue: string;\n\tlabel: string;\n\tdescription?: string;\n\t/**\n\t * Optional short origin tag rendered as a colored chip before the value\n\t * (e.g. \"claude\"). Color is `SelectListTheme.tag`. Adds `[<tag>] ` to the\n\t * displayed line — counts against the visible-width budget.\n\t *\n\t * Fork-specific addition. See docs/UPSTREAM-SYNC.md.\n\t */\n\ttag?: string;\n}\n\nexport interface SelectListTheme {\n\tselectedPrefix: (text: string) => string;\n\tselectedText: (text: string) => string;\n\tdescription: (text: string) => string;\n\tscrollInfo: (text: string) => string;\n\tnoMatch: (text: string) => string;\n\t/** Optional. Color for the leading `[tag] ` chip when SelectItem.tag is set. */\n\ttag?: (text: string) => string;\n}\n\nexport class SelectList implements Component {\n\tprivate items: SelectItem[] = [];\n\tprivate filteredItems: SelectItem[] = [];\n\tprivate selectedIndex: number = 0;\n\tprivate maxVisible: number = 5;\n\tprivate theme: SelectListTheme;\n\n\tpublic onSelect?: (item: SelectItem) => void;\n\tpublic onCancel?: () => void;\n\tpublic onSelectionChange?: (item: SelectItem) => void;\n\n\tconstructor(items: SelectItem[], maxVisible: number, theme: SelectListTheme) {\n\t\tthis.items = items;\n\t\tthis.filteredItems = items;\n\t\tthis.maxVisible = maxVisible;\n\t\tthis.theme = theme;\n\t}\n\n\tsetFilter(filter: string): void {\n\t\tthis.filteredItems = this.items.filter((item) => item.value.toLowerCase().startsWith(filter.toLowerCase()));\n\t\t// Reset selection when filter changes\n\t\tthis.selectedIndex = 0;\n\t}\n\n\tsetSelectedIndex(index: number): void {\n\t\tthis.selectedIndex = Math.max(0, Math.min(index, this.filteredItems.length - 1));\n\t}\n\n\tinvalidate(): void {\n\t\t// No cached state to invalidate currently\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\n\t\t// If no items match filter, show message\n\t\tif (this.filteredItems.length === 0) {\n\t\t\tlines.push(this.theme.noMatch(\" No matching commands\"));\n\t\t\treturn lines;\n\t\t}\n\n\t\t// Calculate visible range with scrolling\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(this.maxVisible / 2), this.filteredItems.length - this.maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + this.maxVisible, this.filteredItems.length);\n\n\t\t// Render visible items\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst item = this.filteredItems[i];\n\t\t\tif (!item) continue;\n\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst descriptionSingleLine = item.description ? normalizeToSingleLine(item.description) : undefined;\n\n\t\t\t// Optional origin chip rendered before the value. The plain text is\n\t\t\t// ASCII-only (no ANSI), so .length equals visible width and feeds\n\t\t\t// directly into layout math. The colored variant is only used when\n\t\t\t// the row is NOT selected — selectedText wraps the whole row and\n\t\t\t// would clobber any inner colors.\n\t\t\tconst tagChipText = item.tag ? `[${item.tag}] ` : \"\";\n\t\t\tconst tagChipWidth = tagChipText.length;\n\t\t\tconst tagChipColored = item.tag && this.theme.tag\n\t\t\t\t? this.theme.tag(tagChipText)\n\t\t\t\t: tagChipText;\n\n\t\t\tlet line = \"\";\n\t\t\tif (isSelected) {\n\t\t\t\t// Use arrow indicator for selection - entire line uses selectedText color\n\t\t\t\tconst prefixWidth = 2; // \"→ \" is 2 characters visually\n\t\t\t\tconst displayValue = item.label || item.value;\n\n\t\t\t\tif (descriptionSingleLine && width > 40) {\n\t\t\t\t\t// Calculate how much space we have for value + description\n\t\t\t\t\t// (chip width is subtracted so descriptions stay aligned with\n\t\t\t\t\t// non-chipped rows)\n\t\t\t\t\tconst maxValueWidth = Math.min(30, width - prefixWidth - 4 - tagChipWidth);\n\t\t\t\t\tconst truncatedValue = truncateToWidth(displayValue, maxValueWidth, \"\");\n\t\t\t\t\tconst spacing = \" \".repeat(Math.max(1, 32 - truncatedValue.length - tagChipWidth));\n\n\t\t\t\t\t// Calculate remaining space for description using visible widths\n\t\t\t\t\tconst descriptionStart = prefixWidth + tagChipWidth + truncatedValue.length + spacing.length;\n\t\t\t\t\tconst remainingWidth = width - descriptionStart - 2; // -2 for safety\n\n\t\t\t\t\tif (remainingWidth > 10) {\n\t\t\t\t\t\tconst truncatedDesc = truncateToWidth(descriptionSingleLine, remainingWidth, \"\");\n\t\t\t\t\t\t// Apply selectedText to entire line content (chip uncolored\n\t\t\t\t\t\t// here — the highlight already conveys selection state)\n\t\t\t\t\t\tline = this.theme.selectedText(`→ ${tagChipText}${truncatedValue}${spacing}${truncatedDesc}`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Not enough space for description\n\t\t\t\t\t\tconst maxWidth = width - prefixWidth - 2 - tagChipWidth;\n\t\t\t\t\t\tline = this.theme.selectedText(`→ ${tagChipText}${truncateToWidth(displayValue, maxWidth, \"\")}`);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// No description or not enough width\n\t\t\t\t\tconst maxWidth = width - prefixWidth - 2 - tagChipWidth;\n\t\t\t\t\tline = this.theme.selectedText(`→ ${tagChipText}${truncateToWidth(displayValue, maxWidth, \"\")}`);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst displayValue = item.label || item.value;\n\t\t\t\tconst prefix = \" \";\n\n\t\t\t\tif (descriptionSingleLine && width > 40) {\n\t\t\t\t\t// Calculate how much space we have for value + description\n\t\t\t\t\tconst maxValueWidth = Math.min(30, width - prefix.length - 4 - tagChipWidth);\n\t\t\t\t\tconst truncatedValue = truncateToWidth(displayValue, maxValueWidth, \"\");\n\t\t\t\t\tconst spacing = \" \".repeat(Math.max(1, 32 - truncatedValue.length - tagChipWidth));\n\n\t\t\t\t\t// Calculate remaining space for description\n\t\t\t\t\tconst descriptionStart = prefix.length + tagChipWidth + truncatedValue.length + spacing.length;\n\t\t\t\t\tconst remainingWidth = width - descriptionStart - 2; // -2 for safety\n\n\t\t\t\t\tif (remainingWidth > 10) {\n\t\t\t\t\t\tconst truncatedDesc = truncateToWidth(descriptionSingleLine, remainingWidth, \"\");\n\t\t\t\t\t\tconst descText = this.theme.description(spacing + truncatedDesc);\n\t\t\t\t\t\tline = prefix + tagChipColored + truncatedValue + descText;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Not enough space for description\n\t\t\t\t\t\tconst maxWidth = width - prefix.length - 2 - tagChipWidth;\n\t\t\t\t\t\tline = prefix + tagChipColored + truncateToWidth(displayValue, maxWidth, \"\");\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// No description or not enough width\n\t\t\t\t\tconst maxWidth = width - prefix.length - 2 - tagChipWidth;\n\t\t\t\t\tline = prefix + tagChipColored + truncateToWidth(displayValue, maxWidth, \"\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlines.push(line);\n\t\t}\n\n\t\t// Add scroll indicators if needed\n\t\tif (startIndex > 0 || endIndex < this.filteredItems.length) {\n\t\t\tconst scrollText = ` (${this.selectedIndex + 1}/${this.filteredItems.length})`;\n\t\t\t// Truncate if too long for terminal\n\t\t\tlines.push(this.theme.scrollInfo(truncateToWidth(scrollText, width - 2, \"\")));\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getEditorKeybindings();\n\t\t// Nothing to navigate or select when the filter matches no items.\n\t\t// Without this guard selectUp would set selectedIndex to -1.\n\t\tif (this.filteredItems.length === 0) {\n\t\t\tif (kb.matches(keyData, \"selectCancel\") && this.onCancel) this.onCancel();\n\t\t\treturn;\n\t\t}\n\t\t// Up arrow - wrap to bottom when at top\n\t\tif (kb.matches(keyData, \"selectUp\")) {\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.filteredItems.length - 1 : this.selectedIndex - 1;\n\t\t\tthis.notifySelectionChange();\n\t\t}\n\t\t// Down arrow - wrap to top when at bottom\n\t\telse if (kb.matches(keyData, \"selectDown\")) {\n\t\t\tthis.selectedIndex = this.selectedIndex === this.filteredItems.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\tthis.notifySelectionChange();\n\t\t}\n\t\t// Enter\n\t\telse if (kb.matches(keyData, \"selectConfirm\")) {\n\t\t\tconst selectedItem = this.filteredItems[this.selectedIndex];\n\t\t\tif (selectedItem && this.onSelect) {\n\t\t\t\tthis.onSelect(selectedItem);\n\t\t\t}\n\t\t}\n\t\t// Escape or Ctrl+C\n\t\telse if (kb.matches(keyData, \"selectCancel\")) {\n\t\t\tif (this.onCancel) {\n\t\t\t\tthis.onCancel();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate notifySelectionChange(): void {\n\t\tconst selectedItem = this.filteredItems[this.selectedIndex];\n\t\tif (selectedItem && this.onSelectionChange) {\n\t\t\tthis.onSelectionChange(selectedItem);\n\t\t}\n\t}\n\n\tgetSelectedItem(): SelectItem | null {\n\t\tconst item = this.filteredItems[this.selectedIndex];\n\t\treturn item || null;\n\t}\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@otto/pi-tui",
3
- "version": "1.0.9",
3
+ "version": "1.1.0",
4
4
  "description": "Terminal User Interface library (vendored from pi-mono)",
5
5
  "type": "module",
6
6
  "otto": {
@@ -89,11 +89,20 @@ export interface AutocompleteItem {
89
89
  value: string;
90
90
  label: string;
91
91
  description?: string;
92
+ /**
93
+ * Optional short origin tag rendered before the value as a colored chip
94
+ * (e.g. "claude", "codex", "kiro"). The color comes from `SelectListTheme.tag`.
95
+ * Kept short (< 12 chars) — long tags eat the visible width budget.
96
+ *
97
+ * Fork-specific addition. See docs/UPSTREAM-SYNC.md.
98
+ */
99
+ tag?: string;
92
100
  }
93
101
 
94
102
  export interface SlashCommand {
95
103
  name: string;
96
104
  description?: string;
105
+ tag?: string;
97
106
  // Function to get argument completions for this command
98
107
  // Returns null if no argument completion is available
99
108
  getArgumentCompletions?(argumentPrefix: string): AutocompleteItem[] | null;
@@ -185,12 +194,14 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
185
194
  name: "name" in cmd ? cmd.name : cmd.value,
186
195
  label: "name" in cmd ? cmd.name : cmd.label,
187
196
  description: cmd.description,
197
+ tag: cmd.tag,
188
198
  }));
189
199
 
190
200
  const filtered = fuzzyFilter(commandItems, prefix, (item) => item.name).map((item) => ({
191
201
  value: item.name,
192
202
  label: item.label,
193
203
  ...(item.description && { description: item.description }),
204
+ ...(item.tag && { tag: item.tag }),
194
205
  }));
195
206
 
196
207
  if (filtered.length === 0) return null;