{"version":3,"file":"tool-availability.d.ts","sourceRoot":"","sources":["../../../../src/runs/shared/tool-availability.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,wBAAwB,+BAA+B,CAAC;AACrE,eAAO,MAAM,0BAA0B,iCAAiC,CAAC;AACzE,eAAO,MAAM,8BAA8B,qCAAqC,CAAC;AAEjF,MAAM,WAAW,mBAAmB;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAID,wBAAgB,wBAAwB,CACvC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAAE,EAClB,SAAS,EAAE,MAAM,EAAE,EACnB,KAAK,CAAC,EAAE,MAAM,EACd,cAAc,CAAC,EAAE,MAAM,EAAE,GACvB,mBAAmB,GAAG,SAAS,CAmBjC;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,mBAAmB,GAAG,SAAS,CAqBrG;AAED,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,mBAAmB,GAAG,MAAM,CAajF;AAED,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAO7F","sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nexport const REQUIRED_CHILD_TOOLS_ENV = \"PI_SUBAGENT_REQUIRED_TOOLS\";\nexport const MCP_DIRECT_CHILD_TOOLS_ENV = \"PI_SUBAGENT_MCP_DIRECT_TOOLS\";\nexport const CHILD_TOOL_DIAGNOSTIC_PATH_ENV = \"PI_SUBAGENT_TOOL_DIAGNOSTIC_PATH\";\n\nexport interface ChildToolDiagnostic {\n\tagent?: string;\n\trequired: string[];\n\tavailable: string[];\n\tmissing: string[];\n\tmissingMcpDirectTools?: string[];\n}\n\nconst PI_CORE_CHILD_TOOLS = new Set([\"bash\", \"edit\", \"find\", \"grep\", \"ls\", \"read\", \"write\"]);\n\nexport function writeChildToolDiagnostic(\n\tfilePath: string,\n\trequired: string[],\n\tavailable: string[],\n\tagent?: string,\n\tmcpDirectTools?: string[],\n): ChildToolDiagnostic | undefined {\n\tconst availableNames = new Set([...available, ...PI_CORE_CHILD_TOOLS]);\n\tconst missing = required.filter((name) => !availableNames.has(name));\n\tif (missing.length === 0) {\n\t\tfs.rmSync(filePath, { force: true });\n\t\treturn undefined;\n\t}\n\n\tconst missingMcpDirectTools = mcpDirectTools?.length ? missing.filter((name) => mcpDirectTools.includes(name)) : [];\n\tconst diagnostic: ChildToolDiagnostic = {\n\t\tagent,\n\t\trequired,\n\t\tavailable,\n\t\tmissing,\n\t\t...(missingMcpDirectTools.length > 0 ? { missingMcpDirectTools } : {}),\n\t};\n\tfs.mkdirSync(path.dirname(filePath), { recursive: true });\n\tfs.writeFileSync(filePath, JSON.stringify(diagnostic), { mode: 0o600 });\n\treturn diagnostic;\n}\n\nexport function readChildToolDiagnostic(filePath: string | undefined): ChildToolDiagnostic | undefined {\n\tif (!filePath || !fs.existsSync(filePath)) return undefined;\n\tconst parsed = JSON.parse(fs.readFileSync(filePath, \"utf-8\")) as Partial<ChildToolDiagnostic>;\n\tconst stringArray = (value: unknown): value is string[] =>\n\t\tArray.isArray(value) && value.every((entry) => typeof entry === \"string\" && entry.length > 0);\n\tif (\n\t\t!stringArray(parsed.required) ||\n\t\t!stringArray(parsed.available) ||\n\t\t!stringArray(parsed.missing) ||\n\t\t(parsed.agent !== undefined && typeof parsed.agent !== \"string\") ||\n\t\t(parsed.missingMcpDirectTools !== undefined && !stringArray(parsed.missingMcpDirectTools))\n\t) {\n\t\tthrow new Error(`Malformed child tool diagnostic at '${filePath}'.`);\n\t}\n\treturn {\n\t\t...(parsed.agent ? { agent: parsed.agent } : {}),\n\t\trequired: parsed.required,\n\t\tavailable: parsed.available,\n\t\tmissing: parsed.missing,\n\t\t...(parsed.missingMcpDirectTools ? { missingMcpDirectTools: parsed.missingMcpDirectTools } : {}),\n\t};\n}\n\nexport function formatChildToolDiagnostic(diagnostic: ChildToolDiagnostic): string {\n\tconst subject = diagnostic.agent ? `Agent '${diagnostic.agent}'` : \"Subagent\";\n\treturn [\n\t\t`${subject} requested unavailable child tools: ${diagnostic.missing.join(\", \")}.`,\n\t\t\"The `tools` field is a strict allowlist; it does not load extension code.\",\n\t\t...(diagnostic.missingMcpDirectTools?.length\n\t\t\t? [\n\t\t\t\t\t`Resolved MCP direct tools missing from the child registry: ${diagnostic.missingMcpDirectTools.join(\", \")}. This indicates a host/pi-mcp-adapter registration problem, not a tool-call failure.`,\n\t\t\t\t]\n\t\t\t: []),\n\t\t\"For extension tools, add the provider path to `subagentOnlyExtensions` (child-only), `extensions`, or as a path-like entry in `tools`, while keeping each registered tool name in `tools`.\",\n\t\t\"For MCP tools, verify the MCP adapter configuration and selected tool names. For builtin tools, verify the name against the installed Pi version.\",\n\t].join(\"\\n\");\n}\n\nexport function readChildToolDiagnosticError(filePath: string | undefined): string | undefined {\n\ttry {\n\t\tconst diagnostic = readChildToolDiagnostic(filePath);\n\t\treturn diagnostic ? formatChildToolDiagnostic(diagnostic) : undefined;\n\t} catch (error) {\n\t\treturn `Failed to read child tool availability diagnostic: ${error instanceof Error ? error.message : String(error)}`;\n\t}\n}\n"]}