{"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../../src/harness/runtime/reducer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGtF,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,SAAS,CAAC;AAiBzD,2GAA2G;AAC3G,wBAAgB,kBAAkB,CACjC,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,YAAY,GAAG,cAAc,GAClC,qBAAqB,CA+MvB","sourcesContent":["import type { HarnessEvent, LaneSnapshot, LaneWatchEvent } from \"../agent-harness.ts\";\nimport type { OperationResultRecord } from \"../session/types.ts\";\n\nexport type LaneSnapshotReduction = \"rebase\" | undefined;\n\ntype LaneOperationSnapshot = NonNullable<LaneSnapshot[\"operation\"]>;\n\nfunction upsertTool(operation: LaneOperationSnapshot, tool: LaneOperationSnapshot[\"runningTools\"][number]): void {\n\tconst index = operation.runningTools.findIndex((candidate) => candidate.toolCallId === tool.toolCallId);\n\tif (index === -1) operation.runningTools.push(tool);\n\telse operation.runningTools[index] = tool;\n}\n\nfunction matchingOperation(\n\tsnapshot: LaneSnapshot,\n\toperationId: string,\n): NonNullable<LaneSnapshot[\"operation\"]> | undefined {\n\treturn snapshot.operation?.id === operationId ? snapshot.operation : undefined;\n}\n\n/** Apply one harness event to a mutable lane snapshot. Navigation completion requires a fresh snapshot. */\nexport function reduceLaneSnapshot(\n\tsnapshot: LaneSnapshot,\n\tevent: HarnessEvent | LaneWatchEvent,\n): LaneSnapshotReduction {\n\tif (\"lane\" in event && event.lane !== undefined && event.lane !== snapshot.lane && event.type !== \"usage\") return;\n\tswitch (event.type) {\n\t\tcase \"run_start\":\n\t\t\tsnapshot.operation = {\n\t\t\t\tid: event.runId,\n\t\t\t\tkind: \"run\",\n\t\t\t\tstartedAt: event.startedAt,\n\t\t\t\tfromTipId: snapshot.tipId,\n\t\t\t\tstatus: \"open\",\n\t\t\t\trunningTools: [],\n\t\t\t};\n\t\t\treturn;\n\t\tcase \"compaction_start\":\n\t\t\tif (snapshot.operation !== null) return;\n\t\t\tsnapshot.operation = {\n\t\t\t\tid: event.runId,\n\t\t\t\tkind: \"compaction\",\n\t\t\t\tstartedAt: event.startedAt,\n\t\t\t\tfromTipId: snapshot.tipId,\n\t\t\t\tstatus: \"open\",\n\t\t\t\trunningTools: [],\n\t\t\t};\n\t\t\treturn;\n\t\tcase \"navigation_start\":\n\t\t\tsnapshot.operation = {\n\t\t\t\tid: event.runId,\n\t\t\t\tkind: \"navigation\",\n\t\t\t\tstartedAt: event.startedAt,\n\t\t\t\tfromTipId: snapshot.tipId,\n\t\t\t\tstatus: \"open\",\n\t\t\t\trunningTools: [],\n\t\t\t};\n\t\t\treturn;\n\t\tcase \"operation_abort\": {\n\t\t\tconst operation = matchingOperation(snapshot, event.operationId);\n\t\t\tif (operation !== undefined) operation.status = \"aborting\";\n\t\t\treturn;\n\t\t}\n\t\tcase \"run_resume\": {\n\t\t\tconst operation = matchingOperation(snapshot, event.runId);\n\t\t\tif (operation !== undefined) delete operation.deferred;\n\t\t\treturn;\n\t\t}\n\t\tcase \"run_suspend\": {\n\t\t\tconst operation = matchingOperation(snapshot, event.runId);\n\t\t\tif (operation === undefined) return;\n\t\t\tdelete operation.streamingMessage;\n\t\t\toperation.deferred = { handle: event.deferred, poll: event.poll };\n\t\t\treturn;\n\t\t}\n\t\tcase \"retry_scheduled\": {\n\t\t\tconst operation = matchingOperation(snapshot, event.runId);\n\t\t\tif (operation !== undefined) {\n\t\t\t\toperation.retry = {\n\t\t\t\t\tattempt: event.attempt,\n\t\t\t\t\tmaxAttempts: event.maxAttempts,\n\t\t\t\t\tnextAttemptAt: event.notBefore,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tcase \"retry_start\":\n\t\tcase \"retry_end\": {\n\t\t\tconst operation = matchingOperation(snapshot, event.runId);\n\t\t\tif (operation !== undefined) delete operation.retry;\n\t\t\treturn;\n\t\t}\n\t\tcase \"message_start\": {\n\t\t\tif (\n\t\t\t\tevent.runId === undefined ||\n\t\t\t\tevent.message.role !== \"assistant\" ||\n\t\t\t\tevent.message.stopReason !== \"pending\"\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst operation = matchingOperation(snapshot, event.runId);\n\t\t\tif (operation !== undefined) operation.streamingMessage = event.message;\n\t\t\treturn;\n\t\t}\n\t\tcase \"message_update\": {\n\t\t\tif (event.message.role !== \"assistant\") return;\n\t\t\tconst operation = matchingOperation(snapshot, event.runId);\n\t\t\tif (operation !== undefined) operation.streamingMessage = event.message;\n\t\t\treturn;\n\t\t}\n\t\tcase \"message_end\": {\n\t\t\tif (event.runId === undefined) return;\n\t\t\tconst operation = matchingOperation(snapshot, event.runId);\n\t\t\tif (operation !== undefined) delete operation.streamingMessage;\n\t\t\treturn;\n\t\t}\n\t\tcase \"tool_start\": {\n\t\t\tconst operation = matchingOperation(snapshot, event.runId);\n\t\t\tif (operation === undefined) return;\n\t\t\tupsertTool(operation, {\n\t\t\t\tstatus: \"running\",\n\t\t\t\ttoolCallId: event.toolCallId,\n\t\t\t\ttoolName: event.toolName,\n\t\t\t\targs: event.args,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tcase \"tool_update\": {\n\t\t\tconst operation = matchingOperation(snapshot, event.runId);\n\t\t\tconst tool = operation?.runningTools.find((candidate) => candidate.toolCallId === event.toolCallId);\n\t\t\tif (tool?.status === \"running\") tool.result = event.partialResult;\n\t\t\treturn;\n\t\t}\n\t\tcase \"tool_end\": {\n\t\t\tconst operation = matchingOperation(snapshot, event.runId);\n\t\t\tif (operation === undefined) return;\n\t\t\tconst index = operation.runningTools.findIndex((candidate) => candidate.toolCallId === event.toolCallId);\n\t\t\tconst current = operation.runningTools[index];\n\t\t\tif (current === undefined) return;\n\t\t\toperation.runningTools[index] = {\n\t\t\t\tstatus: \"settled\",\n\t\t\t\ttoolCallId: event.toolCallId,\n\t\t\t\ttoolName: event.toolName,\n\t\t\t\targs: current.args,\n\t\t\t\tresult: event.result,\n\t\t\t\tisError: event.isError,\n\t\t\t};\n\t\t\treturn;\n\t\t}\n\t\tcase \"entry_added\": {\n\t\t\tif (event.entry.type === \"message\" && event.entry.message.role === \"toolResult\") {\n\t\t\t\tconst operation = snapshot.operation;\n\t\t\t\tif (operation !== null) {\n\t\t\t\t\tconst toolCallId = event.entry.message.toolCallId;\n\t\t\t\t\tconst index = operation.runningTools.findIndex((candidate) => candidate.toolCallId === toolCallId);\n\t\t\t\t\tif (index !== -1) operation.runningTools.splice(index, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (event.entry.type === \"compaction\") snapshot.transcript.splice(0, snapshot.transcript.length, event.entry);\n\t\t\telse snapshot.transcript.push(event.entry);\n\t\t\tsnapshot.tipId = event.entry.id;\n\t\t\tif (event.entry.type === \"message\") snapshot.stats.messageCount += 1;\n\t\t\treturn;\n\t\t}\n\t\tcase \"queue_update\":\n\t\t\tsnapshot.queues = event.queues;\n\t\t\treturn;\n\t\tcase \"usage\":\n\t\t\tsnapshot.stats.usage = event.totals;\n\t\t\treturn;\n\t\tcase \"config_update\":\n\t\t\tif (!(\"lane\" in event) || event.lane !== snapshot.lane) return;\n\t\t\tswitch (event.property) {\n\t\t\t\tcase \"model\":\n\t\t\t\t\tsnapshot.configuration.model = event.value;\n\t\t\t\t\treturn;\n\t\t\t\tcase \"thinkingLevel\":\n\t\t\t\t\tsnapshot.configuration.thinkingLevel = event.value;\n\t\t\t\t\treturn;\n\t\t\t\tcase \"activeTools\":\n\t\t\t\t\tsnapshot.configuration.activeToolNames = event.value;\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t\treturn;\n\t\tcase \"run_end\": {\n\t\t\tconst operation = matchingOperation(snapshot, event.runId);\n\t\t\tif (operation?.kind !== \"run\") return;\n\t\t\tconst record: OperationResultRecord = {\n\t\t\t\toperationId: event.runId,\n\t\t\t\tkind: \"run\",\n\t\t\t\tstatus: event.status,\n\t\t\t\t...(event.status === \"failed\" ? { error: event.error } : {}),\n\t\t\t\tfromTipId: event.fromTipId,\n\t\t\t\ttipId: event.tipId,\n\t\t\t\tstartedAt: operation.startedAt,\n\t\t\t\tendedAt: event.endedAt,\n\t\t\t};\n\t\t\tsnapshot.lastResult = record;\n\t\t\tsnapshot.operation = null;\n\t\t\tsnapshot.tipId = event.tipId;\n\t\t\treturn;\n\t\t}\n\t\tcase \"compaction_end\": {\n\t\t\tconst operation = matchingOperation(snapshot, event.runId);\n\t\t\tif (operation?.kind !== \"compaction\") return;\n\t\t\tconst record: OperationResultRecord = {\n\t\t\t\toperationId: event.runId,\n\t\t\t\tkind: \"compaction\",\n\t\t\t\tstatus: event.status,\n\t\t\t\t...(event.status === \"failed\" ? { error: event.error } : {}),\n\t\t\t\tfromTipId: operation.fromTipId,\n\t\t\t\ttipId: snapshot.tipId,\n\t\t\t\tstartedAt: operation.startedAt,\n\t\t\t\tendedAt: event.endedAt,\n\t\t\t};\n\t\t\tsnapshot.lastResult = record;\n\t\t\tsnapshot.operation = null;\n\t\t\treturn;\n\t\t}\n\t\tcase \"navigation_end\":\n\t\t\treturn \"rebase\";\n\t\tcase \"fault\":\n\t\t\tsnapshot.faulted = true;\n\t\t\treturn;\n\t\tcase \"handler_error\":\n\t\tcase \"turn_start\":\n\t\tcase \"turn_end\":\n\t\tcase \"value_update\":\n\t\tcase \"lane_created\":\n\t\t\treturn;\n\t}\n}\n"]}