feat(tui): autocomplete skill references

This commit is contained in:
chengyongru
2026-08-25 23:11:24 +08:00
committed by chengyongru
parent 649e3958c5
commit b218d3e7f8
7 changed files with 436 additions and 6 deletions
+33
View File
@@ -262,6 +262,12 @@ export interface MentionCandidate {
session?: SessionMention
}
export interface SkillCandidate {
name: string
description: string
source: string
}
export interface MessageOptions {
cliApps?: Array<{ name: string }>
mcpPresets?: Array<{ name: string }>
@@ -299,6 +305,8 @@ export interface SessionSummary {
archived: boolean
}
const SKILL_REFERENCE_NAME = /^[A-Za-z0-9_-]+$/u
const SLASH_COMMAND_LIFECYCLES = new Set([
"side_channel",
"finalize_active_turn",
@@ -683,6 +691,31 @@ export async function fetchSlashCommands(
})
}
export async function fetchAvailableSkills(
apiUrl: string,
apiToken: string,
reauthenticate?: ApiReauthenticator,
): Promise<SkillCandidate[]> {
if (!apiUrl || !apiToken) return []
const response = await fetchApi(apiUrl, apiToken, "/api/webui/skills", reauthenticate)
if (!response.ok) throw new Error(`skill request failed: HTTP ${response.status}`)
const payload = await response.json() as { skills?: unknown[] }
return (payload.skills || []).flatMap((value) => {
if (
!isRecord(value)
|| typeof value.name !== "string"
|| !SKILL_REFERENCE_NAME.test(value.name)
|| value.enabled !== true
|| value.available !== true
) return []
return [{
name: value.name,
description: typeof value.description === "string" ? value.description : value.name,
source: typeof value.source === "string" ? value.source : "unknown",
}]
})
}
export async function fetchRuntimeControls(
apiUrl: string,
apiToken: string,