diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-09 15:59:34 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-09 15:59:34 +0300 |
| commit | df7880c54b8b5d337421cb4b1dd8daea27008801 (patch) | |
| tree | 4d0cc6290ad71c413bac71cfaab4ef41ea017ecb /src/integration/assets/kilo | |
| parent | eeacb45b4b6ab4446c5bea1331f743fee5e5b9f8 (diff) | |
feat: update agent lifecycle integrations
Diffstat (limited to 'src/integration/assets/kilo')
| -rw-r--r-- | src/integration/assets/kilo/herdr-agent-state.js | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/src/integration/assets/kilo/herdr-agent-state.js b/src/integration/assets/kilo/herdr-agent-state.js new file mode 100644 index 00000000..aa1a0c1b --- /dev/null +++ b/src/integration/assets/kilo/herdr-agent-state.js @@ -0,0 +1,159 @@ +// installed by herdr +// managed by herdr; reinstalling or updating the integration overwrites this file. +// add custom hooks/plugins beside this file instead of editing it. +// HERDR_INTEGRATION_ID=kilo +// HERDR_INTEGRATION_VERSION=1 + +import net from "node:net"; + +const SOURCE = "herdr:kilo"; +const AGENT = "kilo"; +let reportSeq = Date.now() * 1000; + +function nextReportSeq() { + reportSeq += 1; + return reportSeq; +} + +function sessionIDFromProperties(properties) { + return typeof properties?.sessionID === "string" && properties.sessionID + ? properties.sessionID + : undefined; +} + +function stateFromSessionStatus(status) { + if (typeof status !== "string") { + return undefined; + } + switch (status.toLowerCase()) { + case "idle": + return "idle"; + case "active": + case "busy": + case "pending": + case "running": + case "streaming": + case "working": + return "working"; + default: + return undefined; + } +} + +function request(method, params) { + const paneId = process.env.HERDR_PANE_ID; + const socketPath = process.env.HERDR_SOCKET_PATH; + + if (!paneId || !socketPath) { + return Promise.resolve(); + } + + const requestId = `${SOURCE}:${Date.now()}:${Math.floor(Math.random() * 1_000_000) + .toString() + .padStart(6, "0")}`; + const request = { + id: requestId, + method, + params: { + pane_id: paneId, + source: SOURCE, + agent: AGENT, + seq: nextReportSeq(), + ...params, + }, + }; + + return new Promise((resolve) => { + const client = net.createConnection(socketPath, () => { + 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); + }); +} + +function reportSession(sessionID) { + if (!sessionID) { + return Promise.resolve(); + } + return request("pane.report_agent_session", { agent_session_id: sessionID }); +} + +function reportState(state, sessionID) { + const params = { state }; + if (sessionID) { + params.agent_session_id = sessionID; + } + return request("pane.report_agent", params); +} + +function releaseAgent() { + return request("pane.release_agent", {}); +} + +export const HerdrAgentStatePlugin = async () => { + if ( + process.env.HERDR_ENV !== "1" || + !process.env.HERDR_SOCKET_PATH || + !process.env.HERDR_PANE_ID + ) { + return {}; + } + + return { + "chat.message": async ({ sessionID }) => { + await reportState("working", sessionID); + }, + event: async ({ event }) => { + const type = event?.type; + const properties = event?.properties ?? {}; + const sessionID = sessionIDFromProperties(properties); + + switch (type) { + case "session.created": + case "session.updated": + await reportSession(sessionID); + break; + case "session.status": { + const state = stateFromSessionStatus(properties.status); + if (state) { + await reportState(state, sessionID); + } else { + await reportSession(sessionID); + } + break; + } + case "tool.execute.before": + case "tool.execute.after": + case "permission.replied": + case "question.replied": + case "question.rejected": + case "session.compacted": + await reportState("working", sessionID); + break; + case "permission.asked": + case "question.asked": + case "session.error": + await reportState("blocked", sessionID); + break; + case "session.idle": + await reportState("idle", sessionID); + break; + case "session.deleted": + await releaseAgent(); + break; + default: + break; + } + }, + }; +}; |
