feat(dashboard): wire skills autocomplete configuration to session cards

Connect the skills enumeration API to session card input fields for
slash command autocomplete:

App.js:
- Add skillsConfig state for Claude and Codex skill configs
- Fetch skills for both agent types on mount using Promise.all
- Pass agent-appropriate autocompleteConfig to each SessionCard

SessionCard.js:
- Accept autocompleteConfig prop and forward to SimpleInput
- Move context usage display from header to footer status bar for
  better information hierarchy (activity indicator + context together)

SimpleInput.js:
- Fix autocomplete dropdown padding (py-2 -> py-1.5)
- Fix font inheritance (add font-mono to skill name)
- Fix description tooltip whitespace handling (add font-sans,
  whitespace-normal)

SpawnModal.js:
- Add SPAWN_TIMEOUT_MS (2x default) to handle pending spawn registry
  wait time plus session file confirmation polling

AgentActivityIndicator.js:
- Minor styling refinement for status display

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
teernisse
2026-02-28 00:47:49 -05:00
parent d3c6af9b00
commit fa1fe8613a
5 changed files with 43 additions and 18 deletions

View File

@@ -1,5 +1,5 @@
import { html, useState, useEffect, useCallback, useMemo, useRef } from '../lib/preact.js';
import { API_STATE, API_STREAM, API_DISMISS, API_DISMISS_DEAD, API_RESPOND, API_CONVERSATION, API_HEALTH, POLL_MS, fetchWithTimeout } from '../utils/api.js';
import { API_STATE, API_STREAM, API_DISMISS, API_DISMISS_DEAD, API_RESPOND, API_CONVERSATION, API_HEALTH, POLL_MS, fetchWithTimeout, fetchSkills } from '../utils/api.js';
import { groupSessionsByProject } from '../utils/status.js';
import { Sidebar } from './Sidebar.js';
import { SessionCard } from './SessionCard.js';
@@ -23,6 +23,7 @@ export function App() {
const [zellijAvailable, setZellijAvailable] = useState(true);
const [newlySpawnedIds, setNewlySpawnedIds] = useState(new Set());
const pendingSpawnIdsRef = useRef(new Set());
const [skillsConfig, setSkillsConfig] = useState({ claude: null, codex: null });
// Background conversation refresh with error tracking
const refreshConversationSilent = useCallback(async (sessionId, projectDir, agent = 'claude') => {
@@ -353,6 +354,18 @@ export function App() {
return () => clearInterval(interval);
}, []);
// Fetch skills for autocomplete on mount
useEffect(() => {
const loadSkills = async () => {
const [claude, codex] = await Promise.all([
fetchSkills('claude'),
fetchSkills('codex')
]);
setSkillsConfig({ claude, codex });
};
loadSkills();
}, []);
// Group sessions by project
const projectGroups = groupSessionsByProject(sessions);
@@ -524,6 +537,7 @@ export function App() {
onRespond=${respondToSession}
onDismiss=${dismissSession}
isNewlySpawned=${newlySpawnedIds.has(session.session_id)}
autocompleteConfig=${skillsConfig[session.agent === 'codex' ? 'codex' : 'claude']}
/>
`)}
</div>
@@ -577,6 +591,7 @@ export function App() {
onFetchConversation=${fetchConversation}
onRespond=${respondToSession}
onDismiss=${dismissSession}
autocompleteConfig=${skillsConfig[session.agent === 'codex' ? 'codex' : 'claude']}
/>
`)}
</div>