* Load a remote canonical skill and inject its SKILL.md content into the * conversation. Unlike local skills (which go through processPromptSlashCommand * for !command / $ARGUMENTS expansion), remote skills are declarative markdown * — we wrap the content directly in a user message. * * The ski
( slug: string, commandName: string, parentMessage: AssistantMessage, context: ToolUseContext, )
| 968 | * call() — remoteSkillModules is non-null here. |
| 969 | */ |
| 970 | async function executeRemoteSkill( |
| 971 | slug: string, |
| 972 | commandName: string, |
| 973 | parentMessage: AssistantMessage, |
| 974 | context: ToolUseContext, |
| 975 | ): Promise<ToolResult<Output>> { |
| 976 | const { getDiscoveredRemoteSkill, loadRemoteSkill, logRemoteSkillLoaded } = |
| 977 | remoteSkillModules! |
| 978 | |
| 979 | // validateInput already confirmed this slug is in session state, but we |
| 980 | // re-fetch here to get the URL. If it's somehow gone (e.g., state cleared |
| 981 | // mid-session), fail with a clear error rather than crashing. |
| 982 | const meta = getDiscoveredRemoteSkill(slug) |
| 983 | if (!meta) { |
| 984 | throw new Error( |
| 985 | `Remote skill ${slug} was not discovered in this session. Use DiscoverSkills to find remote skills first.`, |
| 986 | ) |
| 987 | } |
| 988 | |
| 989 | const urlScheme = extractUrlScheme(meta.url) |
| 990 | let loadResult |
| 991 | try { |
| 992 | loadResult = await loadRemoteSkill(slug, meta.url) |
| 993 | } catch (e) { |
| 994 | const msg = errorMessage(e) |
| 995 | logRemoteSkillLoaded({ |
| 996 | slug, |
| 997 | cacheHit: false, |
| 998 | latencyMs: 0, |
| 999 | urlScheme, |
| 1000 | error: msg, |
| 1001 | }) |
| 1002 | throw new Error(`Failed to load remote skill ${slug}: ${msg}`) |
| 1003 | } |
| 1004 | |
| 1005 | const { |
| 1006 | cacheHit, |
| 1007 | latencyMs, |
| 1008 | skillPath, |
| 1009 | content, |
| 1010 | fileCount, |
| 1011 | totalBytes, |
| 1012 | fetchMethod, |
| 1013 | } = loadResult |
| 1014 | |
| 1015 | logRemoteSkillLoaded({ |
| 1016 | slug, |
| 1017 | cacheHit, |
| 1018 | latencyMs, |
| 1019 | urlScheme, |
| 1020 | fileCount, |
| 1021 | totalBytes, |
| 1022 | fetchMethod, |
| 1023 | }) |
| 1024 | |
| 1025 | // Remote skills are always model-discovered (never in static skill_listing), |
| 1026 | // so was_discovered is always true. is_remote lets BQ queries separate |
| 1027 | // remote from local invocations without joining on skill name prefixes. |
no test coverage detected