/** * Identify the Pi context-mode adapter from registered tool provenance. * * Checking the adapter path, rather than merely a `ctx_*` tool name, avoids * trusting an unrelated extension that happens to use the same naming scheme. */ const CONTEXT_MODE_PI_ADAPTER = "context-mode:build/adapters/pi/extension.js"; const CONTEXT_MODE_PI_ADAPTER_PATH = "context-mode/build/adapters/pi/extension.js"; interface ToolInfoLike { name: string; sourceInfo?: unknown; } function isContextModeAdapterSource(sourceInfo: unknown): boolean { if (!sourceInfo || typeof sourceInfo !== "object") return false; const values = Object.values(sourceInfo as Record); return values.some( (value) => typeof value === "string" && (() => { const path = value.replaceAll("\\", "/"); return ( path.endsWith(CONTEXT_MODE_PI_ADAPTER) || path.endsWith(CONTEXT_MODE_PI_ADAPTER_PATH) ); })(), ); } export function hasContextModePiAdapter( tools: readonly ToolInfoLike[], ): boolean { return tools.some( (tool) => tool.name === "ctx_execute" && isContextModeAdapterSource(tool.sourceInfo), ); }