{"version":3,"file":"slash-live-state.d.ts","sourceRoot":"","sources":["../../../src/slash/slash-live-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAClF,OAAO,EAAE,KAAK,OAAO,EAAoD,MAAM,oBAAoB,CAAC;AAEpG,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAEpF,MAAM,WAAW,mBAAmB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;CACjC;AAED,UAAU,aAAa;IACtB,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;CAChB;AA0LD,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,mBAAmB,CAU1G;AAeD,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAmBrF;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,mBAAmB,CAWxF;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAoBnH;AAUD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,GAAG,SAAS,CAE1F;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,mBAAmB,GAAG,aAAa,CAKtF;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAUnE;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAG1C","sourcesContent":["import type { AgentToolResult } from \"@lpb-work/pi-agent-core\";\nimport type { Message } from \"@lpb-work/pi-ai\";\nimport type { SubagentParamsLike } from \"../runs/foreground/subagent-executor.ts\";\nimport { type Details, type SingleResult, SLASH_RESULT_TYPE, type Usage } from \"../shared/types.ts\";\nimport { previewSimpleWorkflowRun } from \"../workflows/scripted-workflow.ts\";\nimport type { SlashSubagentResponse, SlashSubagentUpdate } from \"./slash-bridge.ts\";\n\nexport interface SlashMessageDetails {\n\trequestId: string;\n\tresult: AgentToolResult<Details>;\n}\n\ninterface SlashSnapshot {\n\tresult: AgentToolResult<Details>;\n\tversion: number;\n}\n\ninterface SequentialChainStepLike {\n\tagent: string;\n\ttask?: string;\n}\n\ninterface ParallelChainStepLike {\n\tparallel: Array<{ agent: string; task?: string }>;\n}\n\ntype ChainStepLike = SequentialChainStepLike | ParallelChainStepLike;\n\nconst liveSnapshots = new Map<string, SlashSnapshot>();\nconst finalSnapshots = new Map<string, SlashSnapshot>();\nlet versionCounter = 1;\n\nconst EMPTY_MESSAGES: Message[] = [];\nconst EMPTY_USAGE: Usage = {\n\tinput: 0,\n\toutput: 0,\n\tcacheRead: 0,\n\tcacheWrite: 0,\n\tcost: 0,\n\tturns: 0,\n};\n\nfunction nextVersion(): number {\n\treturn versionCounter++;\n}\n\nfunction cloneUsage(): Usage {\n\treturn { ...EMPTY_USAGE };\n}\n\nfunction createPlaceholderResult(\n\tagent: string,\n\ttask: string,\n\tstatus: \"pending\" | \"running\",\n\tindex: number,\n): SingleResult {\n\treturn {\n\t\tagent,\n\t\ttask,\n\t\tindex,\n\t\texitCode: 0,\n\t\tmessages: EMPTY_MESSAGES,\n\t\tusage: cloneUsage(),\n\t\tprogress: {\n\t\t\tindex,\n\t\t\tagent,\n\t\t\tstatus,\n\t\t\ttask,\n\t\t\trecentTools: [],\n\t\t\trecentOutput: [],\n\t\t\ttoolCount: 0,\n\t\t\ttokens: 0,\n\t\t\tdurationMs: 0,\n\t\t},\n\t};\n}\n\nfunction buildParallelInitialResult(params: SubagentParamsLike): AgentToolResult<Details> {\n\tconst tasks = params.tasks ?? [];\n\treturn {\n\t\tcontent: [{ type: \"text\", text: tasks.map((task) => `${task.agent}: ${task.task}`).join(\"\\n\\n\") }],\n\t\tdetails: {\n\t\t\tmode: \"parallel\",\n\t\t\t...(params.context ? { context: params.context } : {}),\n\t\t\tresults: tasks.map((task, index) => createPlaceholderResult(task.agent, task.task, \"running\", index)),\n\t\t\tprogress: tasks.map((task, index) => ({\n\t\t\t\tindex,\n\t\t\t\tagent: task.agent,\n\t\t\t\tstatus: \"running\" as const,\n\t\t\t\ttask: task.task,\n\t\t\t\trecentTools: [],\n\t\t\t\trecentOutput: [],\n\t\t\t\ttoolCount: 0,\n\t\t\t\ttokens: 0,\n\t\t\t\tdurationMs: 0,\n\t\t\t})),\n\t\t},\n\t};\n}\n\nfunction isParallelChainStep(step: ChainStepLike): step is ParallelChainStepLike {\n\treturn \"parallel\" in step && Array.isArray(step.parallel);\n}\n\nfunction chainStepLabel(step: ChainStepLike): string {\n\tif (isParallelChainStep(step)) {\n\t\treturn `[${step.parallel.map((entry) => entry.agent).join(\"+\")}]`;\n\t}\n\treturn step.agent;\n}\n\nfunction flattenChainResults(chain: ChainStepLike[], fallbackTask: string | undefined): SingleResult[] {\n\tconst results: SingleResult[] = [];\n\tlet flatIndex = 0;\n\tfor (const step of chain) {\n\t\tif (isParallelChainStep(step)) {\n\t\t\tfor (const task of step.parallel) {\n\t\t\t\tresults.push(\n\t\t\t\t\tcreatePlaceholderResult(\n\t\t\t\t\t\ttask.agent,\n\t\t\t\t\t\ttask.task ?? fallbackTask ?? \"\",\n\t\t\t\t\t\tresults.length === 0 ? \"running\" : \"pending\",\n\t\t\t\t\t\tflatIndex,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tflatIndex++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tresults.push(\n\t\t\tcreatePlaceholderResult(\n\t\t\t\tstep.agent,\n\t\t\t\tstep.task ?? fallbackTask ?? \"\",\n\t\t\t\tresults.length === 0 ? \"running\" : \"pending\",\n\t\t\t\tflatIndex,\n\t\t\t),\n\t\t);\n\t\tflatIndex++;\n\t}\n\treturn results;\n}\n\nfunction buildChainInitialResult(params: SubagentParamsLike): AgentToolResult<Details> {\n\tconst chain = (params.chain ?? []) as ChainStepLike[];\n\tconst results = flattenChainResults(chain, params.task);\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: results.map((result, index) => `Step ${index + 1}: ${result.agent}\\n${result.task}`).join(\"\\n\\n\"),\n\t\t\t},\n\t\t],\n\t\tdetails: {\n\t\t\tmode: \"chain\",\n\t\t\t...(params.context ? { context: params.context } : {}),\n\t\t\tresults,\n\t\t\tprogress: results.map((result, index) => ({\n\t\t\t\tindex,\n\t\t\t\tagent: result.agent,\n\t\t\t\tstatus: index === 0 ? (\"running\" as const) : (\"pending\" as const),\n\t\t\t\ttask: result.task,\n\t\t\t\trecentTools: [],\n\t\t\t\trecentOutput: [],\n\t\t\t\ttoolCount: 0,\n\t\t\t\ttokens: 0,\n\t\t\t\tdurationMs: 0,\n\t\t\t})),\n\t\t\tchainAgents: chain.map((step) => chainStepLabel(step)),\n\t\t\ttotalSteps: chain.length,\n\t\t\tcurrentStepIndex: 0,\n\t\t},\n\t};\n}\n\nfunction buildSingleInitialResult(params: SubagentParamsLike): AgentToolResult<Details> {\n\tconst preview = previewSimpleWorkflowRun(params.workflowScript) ?? {};\n\tconst agent = params.agent ?? preview.agent ?? \"subagent\";\n\tconst task = params.task ?? preview.task ?? \"\";\n\treturn {\n\t\tcontent: [{ type: \"text\", text: task }],\n\t\tdetails: {\n\t\t\tmode: \"single\",\n\t\t\t...(params.context ? { context: params.context } : {}),\n\t\t\tresults: [createPlaceholderResult(agent, task, \"running\", 0)],\n\t\t\tprogress: [\n\t\t\t\t{\n\t\t\t\t\tindex: 0,\n\t\t\t\t\tagent,\n\t\t\t\t\tstatus: \"running\",\n\t\t\t\t\ttask,\n\t\t\t\t\trecentTools: [],\n\t\t\t\t\trecentOutput: [],\n\t\t\t\t\ttoolCount: 0,\n\t\t\t\t\ttokens: 0,\n\t\t\t\t\tdurationMs: 0,\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t};\n}\n\nexport function buildSlashInitialResult(requestId: string, params: SubagentParamsLike): SlashMessageDetails {\n\tconst result =\n\t\t(params.tasks?.length ?? 0) > 0\n\t\t\t? buildParallelInitialResult(params)\n\t\t\t: (params.chain?.length ?? 0) > 0\n\t\t\t\t? buildChainInitialResult(params)\n\t\t\t\t: buildSingleInitialResult(params);\n\tliveSnapshots.set(requestId, { result, version: nextVersion() });\n\tfinalSnapshots.delete(requestId);\n\treturn { requestId, result };\n}\n\nfunction cloneResultsWithProgress(\n\tresults: SingleResult[],\n\tprogress: NonNullable<Details[\"progress\"]> | undefined,\n): SingleResult[] {\n\treturn results.map((result, index) => {\n\t\tconst nextProgress =\n\t\t\tprogress?.find(\n\t\t\t\t(entry) => entry.index === index || (entry.index === undefined && entry.agent === result.agent),\n\t\t\t) ?? result.progress;\n\t\treturn nextProgress ? { ...result, progress: nextProgress } : result;\n\t});\n}\n\nexport function applySlashUpdate(requestId: string, update: SlashSubagentUpdate): void {\n\tconst snapshot = liveSnapshots.get(requestId);\n\tif (!snapshot) return;\n\tconst progress = update.progress;\n\tif (!progress || !snapshot.result.details) return;\n\tconst currentStepIndex = progress.findIndex((entry) => entry.status === \"running\");\n\tconst nextDetails: Details = {\n\t\t...snapshot.result.details,\n\t\tprogress,\n\t\tresults: cloneResultsWithProgress(snapshot.result.details.results, progress),\n\t\t...(snapshot.result.details.mode === \"chain\" && currentStepIndex >= 0 ? { currentStepIndex } : {}),\n\t};\n\tliveSnapshots.set(requestId, {\n\t\tresult: {\n\t\t\t...snapshot.result,\n\t\t\tdetails: nextDetails,\n\t\t},\n\t\tversion: nextVersion(),\n\t});\n}\n\nexport function finalizeSlashResult(response: SlashSubagentResponse): SlashMessageDetails {\n\tconst snapshot = {\n\t\tresult: response.result,\n\t\tversion: nextVersion(),\n\t};\n\tfinalSnapshots.set(response.requestId, snapshot);\n\tliveSnapshots.delete(response.requestId);\n\treturn {\n\t\trequestId: response.requestId,\n\t\tresult: response.result,\n\t};\n}\n\nexport function failSlashResult(requestId: string, params: SubagentParamsLike, message: string): SlashMessageDetails {\n\tconst initial = buildSlashInitialResult(requestId, params).result;\n\tconst failedResults = initial.details.results.map((result) => ({\n\t\t...result,\n\t\texitCode: 1,\n\t\terror: message,\n\t\tprogress: result.progress ? { ...result.progress, status: \"failed\" as const } : result.progress,\n\t}));\n\tconst result: AgentToolResult<Details> = {\n\t\tcontent: [{ type: \"text\", text: message }],\n\t\tdetails: {\n\t\t\t...initial.details,\n\t\t\tresults: failedResults,\n\t\t\tprogress: failedResults.map((entry) => entry.progress!).filter(Boolean),\n\t\t},\n\t};\n\tconst snapshot = { result, version: nextVersion() };\n\tfinalSnapshots.set(requestId, snapshot);\n\tliveSnapshots.delete(requestId);\n\treturn { requestId, result };\n}\n\nfunction isSlashMessageDetails(value: unknown): value is SlashMessageDetails {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst v = value as { requestId?: string; result?: { content?: unknown; details?: { results?: unknown } } };\n\tif (typeof v.requestId !== \"string\" || !v.requestId) return false;\n\tif (!v.result || !Array.isArray(v.result.content)) return false;\n\treturn !!v.result.details && Array.isArray(v.result.details.results);\n}\n\nexport function resolveSlashMessageDetails(value: unknown): SlashMessageDetails | undefined {\n\treturn isSlashMessageDetails(value) ? value : undefined;\n}\n\nexport function getSlashRenderableSnapshot(details: SlashMessageDetails): SlashSnapshot {\n\treturn (\n\t\tfinalSnapshots.get(details.requestId) ??\n\t\tliveSnapshots.get(details.requestId) ?? { result: details.result, version: 0 }\n\t);\n}\n\nexport function restoreSlashFinalSnapshots(entries: unknown[]): void {\n\tliveSnapshots.clear();\n\tfinalSnapshots.clear();\n\tfor (const entry of entries) {\n\t\tconst e = entry as { type?: string; customType?: string; details?: unknown };\n\t\tif (e?.type !== \"custom_message\" || e.customType !== SLASH_RESULT_TYPE) continue;\n\t\tconst details = resolveSlashMessageDetails(e.details);\n\t\tif (!details) continue;\n\t\tfinalSnapshots.set(details.requestId, { result: details.result, version: nextVersion() });\n\t}\n}\n\nexport function clearSlashSnapshots(): void {\n\tliveSnapshots.clear();\n\tfinalSnapshots.clear();\n}\n"]}