{"version":3,"file":"slash-bridge.d.ts","sourceRoot":"","sources":["../../../src/slash/slash-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAClF,OAAO,EACN,KAAK,OAAO,EAMZ,MAAM,oBAAoB,CAAC;AAS5B,MAAM,WAAW,qBAAqB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,QAAQ;IACjB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IAC9E,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;CACzC;AAED,UAAU,kBAAkB;IAC3B,MAAM,EAAE,QAAQ,CAAC;IACjB,UAAU,EAAE,MAAM,gBAAgB,GAAG,IAAI,CAAC;IAC1C,OAAO,EAAE,CACR,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,EAC7D,GAAG,EAAE,gBAAgB,KACjB,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;CACvC;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,kBAAkB,GAAG;IACzE,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,IAAI,CAAC;CACpB,CAyIA","sourcesContent":["import type { AgentToolResult } from \"@lpb-work/pi-agent-core\";\nimport type { ExtensionContext } from \"@lpb-work/pi-coding-agent\";\nimport { normalizePublicSubagentExecution } from \"../extension/public-execution.ts\";\nimport type { SubagentParamsLike } from \"../runs/foreground/subagent-executor.ts\";\nimport {\n\ttype Details,\n\tSLASH_SUBAGENT_CANCEL_EVENT,\n\tSLASH_SUBAGENT_REQUEST_EVENT,\n\tSLASH_SUBAGENT_RESPONSE_EVENT,\n\tSLASH_SUBAGENT_STARTED_EVENT,\n\tSLASH_SUBAGENT_UPDATE_EVENT,\n} from \"../shared/types.ts\";\n\ninterface SlashSubagentRequest {\n\trequestId: string;\n\tparams: SubagentParamsLike;\n\t/** Optional requester context for in-process extension bridge calls. */\n\tctx?: ExtensionContext;\n}\n\nexport interface SlashSubagentResponse {\n\trequestId: string;\n\tresult: AgentToolResult<Details>;\n\tisError: boolean;\n\terrorText?: string;\n}\n\nexport interface SlashSubagentUpdate {\n\trequestId: string;\n\tprogress?: Details[\"progress\"];\n\tcurrentTool?: string;\n\ttoolCount?: number;\n}\n\ninterface EventBus {\n\ton(event: string, handler: (data: unknown) => void): (() => void) | undefined;\n\temit(event: string, data: unknown): void;\n}\n\ninterface SlashBridgeOptions {\n\tevents: EventBus;\n\tgetContext: () => ExtensionContext | null;\n\texecute: (\n\t\tid: string,\n\t\tparams: SubagentParamsLike,\n\t\tsignal: AbortSignal,\n\t\tonUpdate: ((r: AgentToolResult<Details>) => void) | undefined,\n\t\tctx: ExtensionContext,\n\t) => Promise<AgentToolResult<Details>>;\n}\n\nexport function registerSlashSubagentBridge(options: SlashBridgeOptions): {\n\tcancelAll: () => void;\n\tdispose: () => void;\n} {\n\tconst controllers = new Map<string, AbortController>();\n\tconst pendingCancels = new Set<string>();\n\tconst subscriptions: Array<() => void> = [];\n\n\tconst subscribe = (event: string, handler: (data: unknown) => void): void => {\n\t\tconst unsubscribe = options.events.on(event, handler);\n\t\tif (typeof unsubscribe === \"function\") subscriptions.push(unsubscribe);\n\t};\n\n\tsubscribe(SLASH_SUBAGENT_CANCEL_EVENT, (data) => {\n\t\tif (!data || typeof data !== \"object\") return;\n\t\tconst requestId = (data as { requestId?: unknown }).requestId;\n\t\tif (typeof requestId !== \"string\") return;\n\t\tconst controller = controllers.get(requestId);\n\t\tif (controller) {\n\t\t\tcontroller.abort();\n\t\t\treturn;\n\t\t}\n\t\tpendingCancels.add(requestId);\n\t});\n\n\tsubscribe(SLASH_SUBAGENT_REQUEST_EVENT, async (data) => {\n\t\tif (!data || typeof data !== \"object\") return;\n\t\tconst request = data as Partial<SlashSubagentRequest>;\n\t\tif (typeof request.requestId !== \"string\" || !request.params) return;\n\t\tconst { requestId } = request as SlashSubagentRequest;\n\t\tconst normalized = normalizePublicSubagentExecution((request as SlashSubagentRequest).params);\n\t\tif (!normalized.ok) {\n\t\t\toptions.events.emit(SLASH_SUBAGENT_RESPONSE_EVENT, {\n\t\t\t\trequestId,\n\t\t\t\tresult: {\n\t\t\t\t\tcontent: [{ type: \"text\", text: normalized.error }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: { mode: normalized.mode, results: [] },\n\t\t\t\t},\n\t\t\t\tisError: true,\n\t\t\t\terrorText: normalized.error,\n\t\t\t} satisfies SlashSubagentResponse);\n\t\t\treturn;\n\t\t}\n\t\tconst params = normalized.params;\n\n\t\tconst ctx = request.ctx ?? options.getContext();\n\t\tif (!ctx) {\n\t\t\tconst response: SlashSubagentResponse = {\n\t\t\t\trequestId,\n\t\t\t\tresult: {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"No active extension context for slash subagent execution.\" }],\n\t\t\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t\t\t},\n\t\t\t\tisError: true,\n\t\t\t\terrorText: \"No active extension context.\",\n\t\t\t};\n\t\t\toptions.events.emit(SLASH_SUBAGENT_RESPONSE_EVENT, response);\n\t\t\treturn;\n\t\t}\n\n\t\tconst controller = new AbortController();\n\t\tcontrollers.set(requestId, controller);\n\n\t\tif (pendingCancels.delete(requestId)) {\n\t\t\tcontroller.abort();\n\t\t\tconst response: SlashSubagentResponse = {\n\t\t\t\trequestId,\n\t\t\t\tresult: {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"Cancelled.\" }],\n\t\t\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t\t\t},\n\t\t\t\tisError: true,\n\t\t\t\terrorText: \"Cancelled before start.\",\n\t\t\t};\n\t\t\toptions.events.emit(SLASH_SUBAGENT_RESPONSE_EVENT, response);\n\t\t\tcontrollers.delete(requestId);\n\t\t\treturn;\n\t\t}\n\n\t\toptions.events.emit(SLASH_SUBAGENT_STARTED_EVENT, { requestId });\n\n\t\ttry {\n\t\t\tconst result = await options.execute(\n\t\t\t\trequestId,\n\t\t\t\tparams,\n\t\t\t\tcontroller.signal,\n\t\t\t\t(update) => {\n\t\t\t\t\tconst progress = update.details?.progress;\n\t\t\t\t\tconst first = progress?.[0];\n\t\t\t\t\tconst payload: SlashSubagentUpdate = {\n\t\t\t\t\t\trequestId,\n\t\t\t\t\t\tprogress,\n\t\t\t\t\t\tcurrentTool: first?.currentTool,\n\t\t\t\t\t\ttoolCount: first?.toolCount,\n\t\t\t\t\t};\n\t\t\t\t\toptions.events.emit(SLASH_SUBAGENT_UPDATE_EVENT, payload);\n\t\t\t\t},\n\t\t\t\tctx,\n\t\t\t);\n\n\t\t\tconst response: SlashSubagentResponse = {\n\t\t\t\trequestId,\n\t\t\t\tresult,\n\t\t\t\tisError: (result as { isError?: boolean }).isError === true,\n\t\t\t\terrorText: (result as { isError?: boolean }).isError\n\t\t\t\t\t? result.content.find((c) => c.type === \"text\")?.text\n\t\t\t\t\t: undefined,\n\t\t\t};\n\t\t\toptions.events.emit(SLASH_SUBAGENT_RESPONSE_EVENT, response);\n\t\t} catch (error) {\n\t\t\tconst response: SlashSubagentResponse = {\n\t\t\t\trequestId,\n\t\t\t\tresult: {\n\t\t\t\t\tcontent: [{ type: \"text\", text: error instanceof Error ? error.message : String(error) }],\n\t\t\t\t\tdetails: { mode: \"single\" as const, results: [] },\n\t\t\t\t},\n\t\t\t\tisError: true,\n\t\t\t\terrorText: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t\toptions.events.emit(SLASH_SUBAGENT_RESPONSE_EVENT, response);\n\t\t} finally {\n\t\t\tcontrollers.delete(requestId);\n\t\t}\n\t});\n\n\treturn {\n\t\tcancelAll: () => {\n\t\t\tfor (const controller of controllers.values()) {\n\t\t\t\tcontroller.abort();\n\t\t\t}\n\t\t\tcontrollers.clear();\n\t\t\tpendingCancels.clear();\n\t\t},\n\t\tdispose: () => {\n\t\t\tfor (const unsubscribe of subscriptions) unsubscribe();\n\t\t\tsubscriptions.length = 0;\n\t\t\tpendingCancels.clear();\n\t\t},\n\t};\n}\n"]}