{"version":3,"file":"proactive-skills.d.ts","sourceRoot":"","sources":["../../../src/agents/proactive-skills.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAmB,MAAM,aAAa,CAAC;AAS7E,MAAM,WAAW,qCAAqC;IACrD,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oCAAoC;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAQD,wBAAgB,oCAAoC,CACnD,MAAM,CAAC,EAAE,6BAA6B,GAAG,KAAK,GAC5C,qCAAqC,CAoBvC;AA+DD,wBAAgB,gCAAgC,CAAC,KAAK,EAAE;IACvD,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;IACvB,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,MAAM,CAAC,EAAE,6BAA6B,GAAG,KAAK,CAAC;CAC/C,GAAG,oCAAoC,EAAE,CA8CzC;AAED,wBAAgB,2CAA2C,CAC1D,eAAe,EAAE,oCAAoC,EAAE,GACrD,MAAM,EAAE,CAYV;AAED,wBAAgB,8CAA8C,CAAC,KAAK,EAAE;IACrE,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,6BAA6B,GAAG,KAAK,CAAC;IAC/C,uBAAuB,EAAE,MAAM,cAAc,EAAE,CAAC;CAChD,GAAG,MAAM,EAAE,CAgBX","sourcesContent":["import type { ProactiveSkillSubagentsConfig } from \"../shared/types.ts\";\nimport type { AgentConfig, ChainConfig, ChainStepConfig } from \"./agents.ts\";\n\nconst SUBAGENT_ORCHESTRATION_SKILL = \"pi-subagents\";\nconst DEFAULT_MIN_REFERENCES = 2;\nconst DEFAULT_MAX_RECOMMENDATIONS = 3;\nconst DEFAULT_PREFERRED_AGENT = \"reviewer\";\nconst FALLBACK_AGENT_ORDER = [\"reviewer\", \"delegate\"];\nconst MAX_RECOMMENDATION_CAP = 5;\n\nexport interface ResolvedProactiveSkillSubagentsConfig {\n\tenabled: boolean;\n\tminReferences: number;\n\tmaxRecommendations: number;\n\tpreferredAgent: string;\n}\n\nexport interface ProactiveSkillSubagentRecommendation {\n\tskill: string;\n\tagent: string;\n\treferences: number;\n\tsources: string[];\n\tdescription?: string;\n\treason: string;\n}\n\nexport interface AvailableSkill {\n\tname: string;\n\tdescription?: string;\n}\n\nfunction positiveInteger(value: unknown): number | undefined {\n\tif (typeof value !== \"number\") return undefined;\n\tif (!Number.isInteger(value) || !Number.isFinite(value) || value < 1) return undefined;\n\treturn value;\n}\n\nexport function resolveProactiveSkillSubagentsConfig(\n\tconfig?: ProactiveSkillSubagentsConfig | false,\n): ResolvedProactiveSkillSubagentsConfig {\n\tif (config === false) {\n\t\treturn {\n\t\t\tenabled: false,\n\t\t\tminReferences: DEFAULT_MIN_REFERENCES,\n\t\t\tmaxRecommendations: DEFAULT_MAX_RECOMMENDATIONS,\n\t\t\tpreferredAgent: DEFAULT_PREFERRED_AGENT,\n\t\t};\n\t}\n\n\tconst maxRecommendations = positiveInteger(config?.maxRecommendations) ?? DEFAULT_MAX_RECOMMENDATIONS;\n\treturn {\n\t\tenabled: config?.enabled ?? true,\n\t\tminReferences: positiveInteger(config?.minReferences) ?? DEFAULT_MIN_REFERENCES,\n\t\tmaxRecommendations: Math.min(maxRecommendations, MAX_RECOMMENDATION_CAP),\n\t\tpreferredAgent:\n\t\t\ttypeof config?.preferredAgent === \"string\" && config.preferredAgent.trim()\n\t\t\t\t? config.preferredAgent.trim()\n\t\t\t\t: DEFAULT_PREFERRED_AGENT,\n\t};\n}\n\nfunction normalizeSkillNames(value: unknown): string[] {\n\tif (value === false || value === true || value === undefined || value === null) return [];\n\tif (Array.isArray(value)) {\n\t\treturn [\n\t\t\t...new Set(\n\t\t\t\tvalue\n\t\t\t\t\t.filter((entry): entry is string => typeof entry === \"string\")\n\t\t\t\t\t.map((entry) => entry.trim())\n\t\t\t\t\t.filter(Boolean),\n\t\t\t),\n\t\t];\n\t}\n\tif (typeof value === \"string\") {\n\t\treturn [\n\t\t\t...new Set(\n\t\t\t\tvalue\n\t\t\t\t\t.split(\",\")\n\t\t\t\t\t.map((entry) => entry.trim())\n\t\t\t\t\t.filter(Boolean),\n\t\t\t),\n\t\t];\n\t}\n\treturn [];\n}\n\nfunction collectStepSkills(step: ChainStepConfig, out: Set<string>): void {\n\tfor (const skill of normalizeSkillNames(step.skills ?? (step as { skill?: unknown }).skill)) {\n\t\tout.add(skill);\n\t}\n\n\tconst parallel = step.parallel;\n\tif (!parallel) return;\n\tif (Array.isArray(parallel)) {\n\t\tfor (const child of parallel) {\n\t\t\tif (child && typeof child === \"object\" && !Array.isArray(child)) {\n\t\t\t\tcollectStepSkills(child as ChainStepConfig, out);\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\tif (typeof parallel === \"object\") {\n\t\tcollectStepSkills(parallel as ChainStepConfig, out);\n\t}\n}\n\nfunction chooseRecommendationAgent(agents: AgentConfig[], preferredAgent: string): string | undefined {\n\tconst enabled = agents.filter((agent) => !agent.disabled);\n\tif (enabled.some((agent) => agent.name === preferredAgent)) return preferredAgent;\n\tfor (const name of FALLBACK_AGENT_ORDER) {\n\t\tif (enabled.some((agent) => agent.name === name)) return name;\n\t}\n\treturn enabled[0]?.name;\n}\n\nfunction addSource(counts: Map<string, Set<string>>, skill: string, source: string): void {\n\tif (skill === SUBAGENT_ORCHESTRATION_SKILL) return;\n\tconst sources = counts.get(skill) ?? new Set<string>();\n\tsources.add(source);\n\tcounts.set(skill, sources);\n}\n\nexport function recommendProactiveSkillSubagents(input: {\n\tagents: AgentConfig[];\n\tchains?: ChainConfig[];\n\tavailableSkills?: AvailableSkill[];\n\tconfig?: ProactiveSkillSubagentsConfig | false;\n}): ProactiveSkillSubagentRecommendation[] {\n\tconst config = resolveProactiveSkillSubagentsConfig(input.config);\n\tif (!config.enabled) return [];\n\n\tconst agent = chooseRecommendationAgent(input.agents, config.preferredAgent);\n\tif (!agent) return [];\n\n\tconst availableByName = input.availableSkills\n\t\t? new Map(input.availableSkills.map((skill) => [skill.name, skill]))\n\t\t: undefined;\n\tconst counts = new Map<string, Set<string>>();\n\n\tfor (const candidate of input.agents) {\n\t\tif (candidate.disabled) continue;\n\t\tfor (const skill of candidate.skills ?? []) {\n\t\t\taddSource(counts, skill, `agent:${candidate.name}`);\n\t\t}\n\t}\n\n\tfor (const chain of input.chains ?? []) {\n\t\tconst chainSkills = new Set<string>();\n\t\tfor (const step of chain.steps) {\n\t\t\tcollectStepSkills(step, chainSkills);\n\t\t}\n\t\tfor (const skill of chainSkills) {\n\t\t\taddSource(counts, skill, `chain:${chain.name}`);\n\t\t}\n\t}\n\n\treturn [...counts.entries()]\n\t\t.filter(\n\t\t\t([skill, sources]) => sources.size >= config.minReferences && (!availableByName || availableByName.has(skill)),\n\t\t)\n\t\t.map(([skill, sources]) => {\n\t\t\tconst description = availableByName?.get(skill)?.description;\n\t\t\treturn {\n\t\t\t\tskill,\n\t\t\t\tagent,\n\t\t\t\treferences: sources.size,\n\t\t\t\tsources: [...sources].sort((a, b) => a.localeCompare(b)),\n\t\t\t\t...(description !== undefined ? { description } : {}),\n\t\t\t\treason: `referenced by ${sources.size} configured agents/chains`,\n\t\t\t};\n\t\t})\n\t\t.sort((a, b) => b.references - a.references || a.skill.localeCompare(b.skill))\n\t\t.slice(0, config.maxRecommendations);\n}\n\nexport function formatProactiveSkillSubagentRecommendations(\n\trecommendations: ProactiveSkillSubagentRecommendation[],\n): string[] {\n\tif (recommendations.length === 0) return [];\n\treturn [\n\t\t\"Proactive skill subagent suggestions:\",\n\t\t...recommendations.map((recommendation) => {\n\t\t\tconst sampleSources = recommendation.sources.slice(0, 3).join(\", \");\n\t\t\tconst extra = recommendation.sources.length > 3 ? `, +${recommendation.sources.length - 3} more` : \"\";\n\t\t\tconst description = recommendation.description ? ` - ${recommendation.description}` : \"\";\n\t\t\treturn `- ${recommendation.skill} via ${recommendation.agent} (${recommendation.reason}; ${sampleSources}${extra})${description}`;\n\t\t}),\n\t\t\"Guardrails: use these for broad tasks where a skill-specialist pass is useful; keep fanout small, use fresh context unless private/session context is explicitly needed, and skip when the user asks for a direct answer.\",\n\t];\n}\n\nexport function buildProactiveSkillSubagentRecommendationLines(input: {\n\tagents: AgentConfig[];\n\tchains?: ChainConfig[];\n\tconfig?: ProactiveSkillSubagentsConfig | false;\n\tdiscoverAvailableSkills: () => AvailableSkill[];\n}): string[] {\n\tif (!resolveProactiveSkillSubagentsConfig(input.config).enabled) return [];\n\tlet availableSkills: AvailableSkill[];\n\ttry {\n\t\tavailableSkills = input.discoverAvailableSkills();\n\t} catch {\n\t\tavailableSkills = [];\n\t}\n\treturn formatProactiveSkillSubagentRecommendations(\n\t\trecommendProactiveSkillSubagents({\n\t\t\tagents: input.agents,\n\t\t\t...(input.chains !== undefined ? { chains: input.chains } : {}),\n\t\t\tavailableSkills,\n\t\t\t...(input.config !== undefined ? { config: input.config } : {}),\n\t\t}),\n\t);\n}\n"]}