Skip to content

feat(tui): Command palette fuzzy-find any action with Ctrl+P or : prefix#438

Open
jaeko44 wants to merge 7 commits intomainfrom
task/2316d3215b65-feat-tui-command-palette-fuzzy-find-any-action-w
Open

feat(tui): Command palette fuzzy-find any action with Ctrl+P or : prefix#438
jaeko44 wants to merge 7 commits intomainfrom
task/2316d3215b65-feat-tui-command-palette-fuzzy-find-any-action-w

Conversation

@jaeko44
Copy link
Copy Markdown
Member

@jaeko44 jaeko44 commented Mar 25, 2026

Task-ID: 2316d321-5b65-4768-be5d-952e1c5cdec8\n\nAutomated PR for task 2316d321-5b65-4768-be5d-952e1c5cdec8

@jaeko44 jaeko44 added the bosun-attached Bosun PR attachment marker label Mar 25, 2026
Copilot AI review requested due to automatic review settings March 25, 2026 18:19
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 25, 2026

Bosun CI signal: Bosun-created PR currently has failing checks.

@github-actions github-actions bot added the bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair label Mar 25, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a TUI command palette that can fuzzy-find and execute actions, intended to open via Ctrl+P or : and remember recent commands across runs.

Changes:

  • Introduces command-palette helpers to build/rank actions and persist a small recent-history file.
  • Wires a new Ink CommandPalette component into the TUI app, including workflow template fetching and action execution.
  • Adds unit + integration test coverage for palette ranking, history, and basic execution.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
ui/tui/fuzzy.js Adds a small re-export shim for fuzzy scoring helpers.
tui/lib/command-palette.mjs New helpers for palette actions, fuzzy ranking, and persisted history.
tui/app.mjs Integrates palette open/close, action execution, workflow fetching, and recent-history wiring.
tui/CommandPalette.js New Ink UI component for querying and selecting actions.
tests/tui/command-palette.test.mjs Unit tests for ranking and history helpers.
tests/tui/command-palette.integration.test.mjs Ink integration test for opening palette and executing an action.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +279 to +283
const handleInput = useCallback((input, key) => {
if (key?.ctrl && String(input || "") === "p") {
setPaletteOpen(true);
return;
}
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ctrl+P detection is checking input === "p", but Ink typically reports Ctrl key combos as a control character in input (e.g. Ctrl+P is \u0010) with the letter in key.name. This will likely prevent the palette from opening in real terminals. Prefer checking key.ctrl && key.name === "p" (or matching the control sequence) instead of comparing input to "p".

Copilot uses AI. Check for mistakes.
Comment on lines +297 to +301
if (screenInputLocked) {
if (key?.ctrl && String(input || "") === "p") {
setPaletteOpen(true);
}
return;
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same Ctrl+P handling issue as above inside the screenInputLocked branch: comparing input to "p" may not match Ctrl+P. Use key.name / key.sequence so the palette can still open while inputs are captured by a screen.

Copilot uses AI. Check for mistakes.
Comment on lines +55 to +62
async function fetchJson(url, init = {}) {
const response = await fetch(url, init);
const payload = await response.json().catch(() => ({}));
if (!response.ok || payload?.ok === false) {
throw new Error(payload?.error || `Request failed: ${response.status}`);
}
return payload;
}
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fetchJson duplicates logic that already exists in TuiWsBridge.requestJson() (including https/ws protocol mapping and Bearer token injection). Using hard-coded http://${host}:${port} here can break when the UI server is https/wss or requires the token header. Consider routing these requests through bridge.requestJson() (with a fallback for injected mock clients) instead of direct fetch().

Copilot uses AI. Check for mistakes.
Comment on lines +264 to +267
} else if (action.type === "config") {
if (action.id.startsWith("config:refresh:")) {
setRefreshCountdownSec(Number(action.id.split(":").at(-1) || 2));
}
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Config palette actions currently only call setRefreshCountdownSec(...), which changes the displayed countdown but doesn’t update the underlying refreshMs value used by resetRefreshCountdown() (so it can revert on the next stats tick). Either make refresh interval configurable via state and use it consistently, or remove these config actions until they have an effect.

Suggested change
} else if (action.type === "config") {
if (action.id.startsWith("config:refresh:")) {
setRefreshCountdownSec(Number(action.id.split(":").at(-1) || 2));
}

Copilot uses AI. Check for mistakes.
@@ -0,0 +1 @@
export { scoreFuzzyMatch, rankFuzzyMatches } from "../../tui/lib/fuzzy-score.mjs";
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file re-exports fuzzy helpers but isn’t referenced anywhere in the repo (no imports found). If it’s not needed, consider removing it; if it is intended as a shared entrypoint, add the corresponding import(s) or documentation so it’s clear why it exists.

Copilot uses AI. Check for mistakes.
Comment on lines +66 to +81
for (const task of Array.isArray(tasks) ? tasks : []) {
const taskId = String(task?.id || "").trim();
if (!taskId) continue;
for (const action of TASK_ACTIONS) {
actions.push(actionWithSearch({
id: `task:${action.key}:${taskId}`,
type: "task",
command: action.key,
icon: action.icon,
label: action.key === "create" ? `${action.label}` : `${action.label} ${task.title || taskId}`,
shortcut: action.shortcut,
context: action.key === "create" ? "Tasks" : `Task ${taskId}`,
payload: { taskId, task },
keywords: [task.title, task.status, taskId],
}));
}
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TASK_ACTIONS includes create, and the per-task loop generates a "Create task" action for every existing task (task:create:<taskId>). This produces many duplicate create entries (plus the separate task:create:new action) and can crowd out the result list. Consider removing create from the per-task loop (handle create as a single global action) so only update/delete are task-scoped.

Copilot uses AI. Check for mistakes.
Comment on lines +25 to +26
{ key: "config:connectOnly:on", label: "Enable connect-only mode", icon: "⚙", context: "Config" },
{ key: "config:connectOnly:off", label: "Disable connect-only mode", icon: "⚙", context: "Config" },
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONFIG_ACTIONS defines connect-only toggles, but executePaletteAction in tui/app.mjs doesn’t implement any behavior for config:connectOnly:on/off. Either implement these actions end-to-end or remove them from the palette so users don’t select a no-op command.

Suggested change
{ key: "config:connectOnly:on", label: "Enable connect-only mode", icon: "⚙", context: "Config" },
{ key: "config:connectOnly:off", label: "Disable connect-only mode", icon: "⚙", context: "Config" },

Copilot uses AI. Check for mistakes.
@jaeko44 jaeko44 force-pushed the task/2316d3215b65-feat-tui-command-palette-fuzzy-find-any-action-w branch from 8ef73c2 to 63dae12 Compare March 25, 2026 23:08
@github-actions github-actions bot added the bosun-pr-public PR observed by Bosun but not trusted for high-risk automation label Mar 25, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 25, 2026

Bosun PR classification: Bosun-created.
This PR is tracked by Bosun attachment automation.

  • PR class label: bosun-pr-bosun-created
  • Attach label: bosun-attached (yes, because Bosun-created PRs remain attached regardless of human PR attach mode)
  • Attach mode policy: all
  • Trusted author: no
  • Bosun-created label present: yes
  • Automation scope: Eligible for Bosun repair and merge automation (Bosun-created PR).
  • CI failure signal label: bosun-needs-fix
  • CI failure marker:
  • Trigger: pull_request_target / synchronize

@jaeko44 jaeko44 added bosun-pr-bosun-created PR created by Bosun and eligible for Bosun automation and removed bosun-pr-public PR observed by Bosun but not trusted for high-risk automation labels Mar 26, 2026
jaeko44 and others added 4 commits March 26, 2026 22:46
Co-authored-by: bosun-ve[bot] <262908237+bosun-ve[bot]@users.noreply.github.com>
Co-authored-by: bosun-ve[bot] <262908237+bosun-ve[bot]@users.noreply.github.com>
Co-authored-by: bosun-ve[bot] <262908237+bosun-ve[bot]@users.noreply.github.com>
@jaeko44 jaeko44 added bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair and removed bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair labels Mar 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bosun-attached Bosun PR attachment marker bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair bosun-pr-bosun-created PR created by Bosun and eligible for Bosun automation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants