(sdk: OpencodeClient)
| 668 | } |
| 669 | |
| 670 | async function execute(sdk: OpencodeClient) { |
| 671 | const sess = await session(sdk) |
| 672 | if (!sess?.id) { |
| 673 | UI.error("Session not found") |
| 674 | process.exit(1) |
| 675 | } |
| 676 | const sessionID = sess.id |
| 677 | |
| 678 | function emit(type: string, data: Record<string, unknown>) { |
| 679 | if (args.format === "json") { |
| 680 | process.stdout.write( |
| 681 | JSON.stringify({ |
| 682 | type, |
| 683 | timestamp: Date.now(), |
| 684 | sessionID, |
| 685 | ...data, |
| 686 | }) + EOL, |
| 687 | ) |
| 688 | return true |
| 689 | } |
| 690 | return false |
| 691 | } |
| 692 | |
| 693 | // Consume one subscribed event stream for the active session and mirror it |
| 694 | // to stdout/UI. `client` is passed explicitly because attach mode may |
| 695 | // rebind the SDK to the session's directory after the subscription is |
| 696 | // created, and replies issued from inside the loop must use that client. |
| 697 | async function loop(client: OpencodeClient, events: Awaited<ReturnType<typeof sdk.event.subscribe>>) { |
| 698 | const toggles = new Map<string, boolean>() |
| 699 | let error: string | undefined |
| 700 | |
| 701 | for await (const event of events.stream) { |
| 702 | if ( |
| 703 | event.type === "message.updated" && |
| 704 | event.properties.sessionID === sessionID && |
| 705 | event.properties.info.role === "assistant" && |
| 706 | args.format !== "json" && |
| 707 | toggles.get("start") !== true |
| 708 | ) { |
| 709 | UI.empty() |
| 710 | UI.println(`> ${event.properties.info.agent} · ${event.properties.info.modelID}`) |
| 711 | UI.empty() |
| 712 | toggles.set("start", true) |
| 713 | } |
| 714 | |
| 715 | if (event.type === "message.part.updated") { |
| 716 | const part = event.properties.part |
| 717 | if (part.sessionID !== sessionID) continue |
| 718 | |
| 719 | if (part.type === "tool" && (part.state.status === "completed" || part.state.status === "error")) { |
| 720 | if (emit("tool_use", { part })) continue |
| 721 | if (part.state.status === "completed") { |
| 722 | await tool(part) |
| 723 | continue |
| 724 | } |
| 725 | await toolError(part) |
| 726 | UI.error(part.state.error) |
| 727 | } |
no test coverage detected