import { useCallback, useEffect, useState } from 'react'; import { getSkillRuntimeAdminConfig, listSkillRuntimeCatalog, updateSkillRuntimeAdminConfig, } from '../../api/client'; import type { SkillRuntimeAdminConfig, SkillRuntimeCatalogItem } from '../../types'; export function SkillRuntimePage() { const [config, setConfig] = useState({ router: { v2Enabled: false, manifestRoutingEnabled: false }, }); const [catalog, setCatalog] = useState([]); const [source, setSource] = useState('default'); const [updatedAt, setUpdatedAt] = useState(null); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); const [notice, setNotice] = useState(null); const load = useCallback(async () => { setLoading(true); setError(null); try { const [configResult, catalogRows] = await Promise.all([ getSkillRuntimeAdminConfig(), listSkillRuntimeCatalog(), ]); setConfig(configResult.config); setSource(configResult.source ?? 'default'); setUpdatedAt(configResult.updatedAt ?? null); setCatalog(catalogRows); } catch (err) { setError(err instanceof Error ? err.message : '加载 Skill Runtime 配置失败'); } finally { setLoading(false); } }, []); useEffect(() => { void load(); }, [load]); const handleSave = async () => { setSaving(true); setError(null); setNotice(null); try { const result = await updateSkillRuntimeAdminConfig(config); setConfig(result.config); setSource(result.source ?? 'admin-db'); setUpdatedAt(result.updatedAt ?? null); setNotice('Skill Runtime 配置已保存。H5 用户刷新或重新登录后会读取新开关。'); } catch (err) { setError(err instanceof Error ? err.message : '保存失败'); } finally { setSaving(false); } }; const manifestSkillCount = catalog.filter((item) => item.hasManifest && item.triggerKeywords.length > 0).length; return (

Skill Runtime

控制 H5 Skill Router v2 与 manifest 关键词路由(默认关闭)

{loading ?

加载中…

: null} {error ?

{error}

: null} {notice ?

{notice}

: null} {!loading ? ( <>

Router 开关

当前来源:{source} {updatedAt ? ` · 更新于 ${new Date(updatedAt).toLocaleString('zh-CN', { hour12: false })}` : ''}

开启后仅对已授予 skill 的用户生效;manifest 匹配失败会回退 legacy 路由。

技能 Catalog 预览

「Manifest」表示该 skill 目录下是否存在 skill.yaml(Router v2 关键词路由配置)。 目前 Phase 1 仅 product-campaign-page 做了 manifest 试点;其余 skill 仍只有 legacy{' '} SKILL.md,因此 Manifest 显示「否」是正常现象。

有 skill.yaml 且配置了关键词的条目会在 Router v2 开启后参与匹配。

{catalog.map((item) => ( ))}
Skill Manifest 关键词 Prompt 优先级
{item.name}
{item.description}
{item.hasManifest ? '是' : '否'} {item.triggerKeywords.length ? item.triggerKeywords.join('、') : '—'} {item.routerPromptKey ?? '—'} {item.routerPriority || '—'}
) : null}
); }