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