{"version":3,"file":"register-child.d.ts","sourceRoot":"","sources":["../../../src/watchdog/register-child.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAGN,KAAK,mBAAmB,EAGxB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,KAAK,EAAE,sBAAsB,EAA0B,MAAM,YAAY,CAAC;AAGjF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,sBAAsB,CAsBvF;AAmBD,wBAAgB,qBAAqB,CACpC,EAAE,EAAE,YAAY,EAChB,SAAS,qBAAyC,GAChD,mBAAmB,GAAG,SAAS,CAkEjC","sourcesContent":["import type { ExtensionAPI, ExtensionContext } from \"@lpb-work/pi-coding-agent\";\nimport {\n\tCHILD_WATCHDOG_CONFIG_ENV,\n\tCHILD_WATCHDOG_STATUS_EVENT,\n\ttype ChildWatchdogConfig,\n\ttype ChildWatchdogPhase,\n\tdecodeChildWatchdogConfig,\n} from \"./child-status.ts\";\nimport { createMainWatchdogReview } from \"./review.ts\";\nimport { MainWatchdogRuntime } from \"./runtime.ts\";\nimport { DEFAULT_WATCHDOG_CONFIG } from \"./settings.ts\";\nimport type { ResolvedWatchdogConfig, WatchdogWarningDetails } from \"./types.ts\";\nimport { createWatchdogWarningMessage } from \"./warning-format.ts\";\n\nexport function childResolvedConfig(config: ChildWatchdogConfig): ResolvedWatchdogConfig {\n\treturn {\n\t\t...DEFAULT_WATCHDOG_CONFIG,\n\t\tenabled: true,\n\t\tagentEndTimeoutMs: config.agentEndTimeoutMs,\n\t\tmaxWarnings: config.maxWarnings,\n\t\tmain: {\n\t\t\tenabled: true,\n\t\t\t...(config.model ? { model: config.model } : {}),\n\t\t\t...(config.thinking !== undefined ? { thinking: config.thinking } : {}),\n\t\t},\n\t\tautoFollow: {\n\t\t\tblockers: config.autoFollowBlockers,\n\t\t\tmaxAttempts: config.autoFollowMaxAttempts,\n\t\t\tstalemateRepeats: config.stalemateRepeats,\n\t\t},\n\t\tchildren: {\n\t\t\t...DEFAULT_WATCHDOG_CONFIG.children,\n\t\t\twatchdogTailTimeoutMs: config.watchdogTailTimeoutMs,\n\t\t},\n\t\tlsp: { ...config.lsp },\n\t};\n}\n\nfunction childWarningDetails(details: WatchdogWarningDetails, config: ChildWatchdogConfig): WatchdogWarningDetails {\n\treturn {\n\t\t...details,\n\t\tsource: details.source === \"lsp\" ? \"lsp\" : \"child\",\n\t\t...(config.agent ? { agent: config.agent } : {}),\n\t\t...(config.runId ? { runId: config.runId } : {}),\n\t};\n}\n\nfunction writeStatus(event: unknown): void {\n\ttry {\n\t\tprocess.stdout.write(`${JSON.stringify(event)}\\n`);\n\t} catch {\n\t\t// Child watchdog status is advisory; stdout failures are handled by the child process itself.\n\t}\n}\n\nexport function registerChildWatchdog(\n\tpi: ExtensionAPI,\n\trawConfig = process.env[CHILD_WATCHDOG_CONFIG_ENV],\n): MainWatchdogRuntime | undefined {\n\tconst childConfig = decodeChildWatchdogConfig(rawConfig);\n\tif (!childConfig?.enabled) return undefined;\n\tlet currentContext: ExtensionContext | undefined;\n\tlet seq = 0;\n\tconst emitStatus = (phase: ChildWatchdogPhase, followUpPending = false, reason?: string): void => {\n\t\twriteStatus({\n\t\t\ttype: CHILD_WATCHDOG_STATUS_EVENT,\n\t\t\t...(childConfig.runId ? { runId: childConfig.runId } : {}),\n\t\t\t...(childConfig.agent ? { agent: childConfig.agent } : {}),\n\t\t\t...(childConfig.childIndex !== undefined\n\t\t\t\t? { childIndex: childConfig.childIndex, stepIndex: childConfig.childIndex }\n\t\t\t\t: {}),\n\t\t\tseq: ++seq,\n\t\t\tphase,\n\t\t\tts: Date.now(),\n\t\t\tfollowUpPending,\n\t\t\t...(reason ? { reason } : {}),\n\t\t});\n\t};\n\tconst resolved = childResolvedConfig(childConfig);\n\tconst runtime = new MainWatchdogRuntime({\n\t\tresolveConfig: () => ({ ok: true, config: resolved, errors: [], sources: [{ scope: \"session\", exists: true }] }),\n\t\treview: createMainWatchdogReview(() => currentContext, { getThinkingLevel: () => pi.getThinkingLevel() }),\n\t\treviewDescription: \"child model review\",\n\t\treviewChangesOnly: true,\n\t\tdisplayWarning: (details) => {\n\t\t\tconst childDetails = childWarningDetails(details, childConfig);\n\t\t\tpi.sendMessage(createWatchdogWarningMessage(childDetails, { display: true, details: childDetails }));\n\t\t},\n\t});\n\tconst rememberContext = (ctx: ExtensionContext) => {\n\t\tcurrentContext = ctx;\n\t};\n\tconst onRuntimeEvent = pi.on as unknown as (\n\t\tevent: string,\n\t\thandler: (event: unknown, ctx: ExtensionContext) => unknown,\n\t) => void;\n\tonRuntimeEvent(\"session_start\", (_event, ctx) => {\n\t\trememberContext(ctx);\n\t\truntime.bindSession(ctx);\n\t\temitStatus(\"idle\");\n\t});\n\tonRuntimeEvent(\"before_agent_start\", (event, ctx) => {\n\t\trememberContext(ctx);\n\t\truntime.handleBeforeAgentStart(event, ctx);\n\t});\n\tonRuntimeEvent(\"turn_end\", (event, ctx) => {\n\t\trememberContext(ctx);\n\t\truntime.handleTurnEnd(event, ctx);\n\t});\n\tonRuntimeEvent(\"agent_end\", async (event, ctx) => {\n\t\trememberContext(ctx);\n\t\temitStatus(\"reviewing\");\n\t\tawait runtime.handleAgentEnd(event, ctx);\n\t\tconst snapshot = runtime.getSnapshot(ctx.cwd);\n\t\tif (snapshot.status === \"failed\") emitStatus(\"failed\", false, snapshot.lastError);\n\t\telse if (snapshot.status === \"stale\") emitStatus(\"stale\", false, \"review stale\");\n\t\telse emitStatus(\"idle\");\n\t});\n\tonRuntimeEvent(\"session_shutdown\", () => {\n\t\tcurrentContext = undefined;\n\t\truntime.dispose();\n\t\temitStatus(\"idle\");\n\t});\n\treturn runtime;\n}\n"]}