diff options
| author | akbash <akbash@herdr.dev> | 2026-08-10 14:57:44 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-10 14:57:44 +0300 |
| commit | ccccda54c21f6ef1649a44bb098d7c498724404d (patch) | |
| tree | 86f28b85086ef36fd7ebc0f1d928b7606d76c487 /src/integration/assets/opencode/herdr-tui-session.js | |
| parent | 2e8cc9060d723a5ac32a2325e695fd8750ff60fe (diff) | |
fix: track opencode tui session selection (#2455)
refs #2450
Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>
Diffstat (limited to 'src/integration/assets/opencode/herdr-tui-session.js')
| -rw-r--r-- | src/integration/assets/opencode/herdr-tui-session.js | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/integration/assets/opencode/herdr-tui-session.js b/src/integration/assets/opencode/herdr-tui-session.js new file mode 100644 index 00000000..b5be5bbc --- /dev/null +++ b/src/integration/assets/opencode/herdr-tui-session.js @@ -0,0 +1,113 @@ +// installed by herdr +// managed by herdr; reinstalling or updating the integration overwrites this file. +// HERDR_INTEGRATION_ID=opencode-tui +// HERDR_INTEGRATION_VERSION=10 + +import net from "node:net"; + +const SOURCE = "herdr:opencode"; +const AGENT = "opencode"; +const ROUTE_POLL_INTERVAL_MS = 100; +const SELECTION_RETRY_DELAYS_MS = [100, 400, 1_000]; + +function requestOnce(sessionID) { + const paneId = process.env.HERDR_PANE_ID; + const socketPath = process.env.HERDR_SOCKET_PATH; + if (!paneId || !socketPath) { + return Promise.resolve(); + } + + const socketEndpoint = + process.platform === "win32" ? `\\\\.\\pipe\\${socketPath}` : socketPath; + const request = { + id: `${SOURCE}:tui:${Date.now()}:${Math.floor(Math.random() * 1_000_000) + .toString() + .padStart(6, "0")}`, + method: "pane.report_agent_session", + params: { + pane_id: paneId, + source: SOURCE, + agent: AGENT, + agent_session_id: sessionID, + session_start_source: "select", + }, + }; + + return new Promise((resolve) => { + const client = net.createConnection(socketEndpoint, () => { + client.write(`${JSON.stringify(request)}\n`); + }); + const finish = () => { + client.destroy(); + resolve(); + }; + + client.setTimeout(500, finish); + client.on("data", finish); + client.on("error", finish); + client.on("end", finish); + client.on("close", resolve); + }); +} + +export default { + id: "herdr.opencode.session-selection", + tui: async (api) => { + if ( + process.env.HERDR_ENV !== "1" || + !process.env.HERDR_SOCKET_PATH || + !process.env.HERDR_PANE_ID + ) { + return; + } + + let selectedSessionID; + let retryIndex = 0; + let nextReportAt = 0; + let reportPending = false; + const syncSelectedSession = async () => { + const route = api.route.current; + const sessionID = route?.name === "session" ? route.params?.sessionID : undefined; + const session = + typeof sessionID === "string" && sessionID + ? api.state.session.get(sessionID) + : undefined; + if (!session || session.parentID) { + selectedSessionID = undefined; + retryIndex = 0; + nextReportAt = 0; + return; + } + if (sessionID !== selectedSessionID) { + selectedSessionID = sessionID; + retryIndex = 0; + nextReportAt = 0; + } + if (reportPending || Date.now() < nextReportAt) { + return; + } + + const reportingSessionID = sessionID; + reportPending = true; + try { + await requestOnce(reportingSessionID); + } catch { + // Best-effort reporting retries below while the selected route remains active. + } finally { + reportPending = false; + } + if (selectedSessionID !== reportingSessionID) { + retryIndex = 0; + nextReportAt = 0; + return; + } + const retryDelay = SELECTION_RETRY_DELAYS_MS[retryIndex]; + retryIndex += 1; + nextReportAt = retryDelay === undefined ? Number.POSITIVE_INFINITY : Date.now() + retryDelay; + }; + + await syncSelectedSession(); + const routePoll = setInterval(() => void syncSelectedSession(), ROUTE_POLL_INTERVAL_MS); + api.lifecycle.onDispose(() => clearInterval(routePoll)); + }, +}; |
