{"version":3,"file":"subagent-pool-instance.d.ts","sourceRoot":"","sources":["../../src/core/subagent-pool-instance.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAI1D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AASlD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,eAAe,GAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAO,GAAG,YAAY,CAgCtG;AAgCD;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,YAAY,GAAG,SAAS,CAE3D;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAG9D;AAED,mFAAmF;AACnF,wBAAgB,mBAAmB,IAAI,IAAI,CAI1C;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI,CAElF","sourcesContent":["/**\n * Process-wide SubagentPool singleton.\n *\n * The subagent tool and the `/subagent` command both delegate through one pool\n * so concurrency limits, lifeguard monitoring, and token budgets are shared\n * across every delegation in the session. Created lazily on first use and torn\n * down on process exit.\n */\n\nimport type { Api, Model } from \"@kolisachint/hoocode-ai\";\nimport { getAgentDir, getSubagentSpawnCommand } from \"../config.js\";\nimport { SettingsManager } from \"./settings-manager.js\";\nimport { poolConcurrencyForDepth } from \"./subagent-depth.js\";\nimport { SubagentPool } from \"./subagent-pool.js\";\nimport { taskStore } from \"./task-store.js\";\n\nlet pool: SubagentPool | undefined;\nlet override: SubagentPool | undefined;\nlet exitHandlerRegistered = false;\n/** Latest non-default skill paths to forward to subagents, kept in sync with the resource loader. */\nlet latestSkillPaths: string[] = [];\n\n/**\n * Get the shared pool for a given working directory, creating it on first use.\n *\n * `availableModels` (the caller's `ModelRegistry.getAvailable()`) is snapshotted\n * on first creation and used to derive default model-category mappings for any\n * tier the user has not explicitly configured. Later calls reuse the existing\n * pool, so pass it on the first dispatch of a session.\n */\nexport function getSubagentPool(cwd: string, availableModels: readonly Model<Api>[] = []): SubagentPool {\n\tif (override) return override;\n\tif (!pool) {\n\t\tconst { executable, prefixArgs } = getSubagentSpawnCommand();\n\t\t// Pools created inside a nested subagent (depth >= 1) run with a reduced\n\t\t// concurrency cap so deep delegation trees stay bounded; the root keeps the\n\t\t// SubagentPool default.\n\t\t// Load settings for model category resolution\n\t\tconst settingsManager = SettingsManager.create(cwd, getAgentDir());\n\t\tconst globalSettings = settingsManager.getGlobalSettings();\n\t\tconst projectSettings = settingsManager.getProjectSettings();\n\t\t// Merge settings (project overrides global)\n\t\tconst settings = { ...globalSettings, ...projectSettings };\n\n\t\tpool = new SubagentPool({\n\t\t\texecutable,\n\t\t\tprefixArgs,\n\t\t\tcwd,\n\t\t\tskillPaths: latestSkillPaths,\n\t\t\tmaxConcurrency: poolConcurrencyForDepth(),\n\t\t\tsettings,\n\t\t\tavailableModels,\n\t\t});\n\n\t\twireProgressToTaskStore(pool);\n\n\t\tif (!exitHandlerRegistered) {\n\t\t\texitHandlerRegistered = true;\n\t\t\tprocess.once(\"exit\", () => pool?.dispose());\n\t\t}\n\t}\n\treturn pool;\n}\n\n/**\n * Surface live subagent progress on the task panel's agent roster row. The pool\n * forwards only coarse lifecycle events; we map the currently-executing tool onto\n * the run's `activity` and clear it between tools and on completion. Roster rows\n * are keyed per run by the pool task id (see registerSubagentDispatch), so\n * concurrent same-type subagents update their own rows; patching an unknown id\n * is a no-op. This touches only the roster row, never task nodes — so it cannot\n * collide with the end-of-run task-tree merge. Render coalescing is handled by\n * the TUI's `requestRender`, so per-event patches are fine.\n */\nfunction wireProgressToTaskStore(p: SubagentPool): void {\n\tp.on(\"task_progress\", (data: { task_id: string; event: { type?: string; toolName?: string } }) => {\n\t\tconst { task_id, event } = data;\n\t\tif (event.type === \"tool_execution_start\") {\n\t\t\ttaskStore.patchAgent(task_id, { activity: typeof event.toolName === \"string\" ? event.toolName : \"\" });\n\t\t} else if (event.type === \"turn_end\") {\n\t\t\t// Between turns the subagent is reasoning, not idle — mirror the inbox's\n\t\t\t// \"thinking\" so the panel and TaskOutput agree on what the run is doing.\n\t\t\ttaskStore.patchAgent(task_id, { activity: \"thinking\" });\n\t\t} else if (event.type === \"tool_execution_end\") {\n\t\t\ttaskStore.patchAgent(task_id, { activity: \"\" });\n\t\t}\n\t});\n\tfor (const terminal of [\"task_done\", \"task_failed\", \"task_stalled\", \"task_timeout\", \"task_cancelled\"] as const) {\n\t\tp.on(terminal, (data: { task_id?: string }) => {\n\t\t\tif (data.task_id) taskStore.patchAgent(data.task_id, { activity: \"\" });\n\t\t});\n\t}\n}\n\n/**\n * Return the shared pool if one already exists, without creating it. Use this for\n * best-effort signaling (e.g. reporting external load) that must not spin up a pool\n * and its lifeguard just because the signal fired before any subagent was dispatched.\n */\nexport function peekSubagentPool(): SubagentPool | undefined {\n\treturn override ?? pool;\n}\n\n/**\n * Update the skill paths forwarded to every subagent.\n * Call this after the resource loader reloads or extends its skill set.\n * If the pool has already been created, updates it immediately.\n * If not, the paths will be passed in when the pool is first created.\n */\nexport function updateSubagentSkillPaths(paths: string[]): void {\n\tlatestSkillPaths = paths;\n\tpool?.updateSkillPaths(paths);\n}\n\n/** Dispose and clear the shared pool. Intended for test isolation and shutdown. */\nexport function disposeSubagentPool(): void {\n\tpool?.dispose();\n\tpool = undefined;\n\tlatestSkillPaths = [];\n}\n\n/**\n * Inject a pool instance for tests, bypassing real child-process spawning.\n * Pass `undefined` to clear the override.\n */\nexport function setSubagentPoolForTesting(testPool: SubagentPool | undefined): void {\n\toverride = testPool;\n}\n"]}