import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; import { StringEnum } from "@earendil-works/pi-ai"; import { Type } from "typebox"; import type { OneDevSourceWatchManager } from "../source-watch.js"; import { toolResult } from "./common.js"; export function registerWatchTool( pi: ExtensionAPI, watches: OneDevSourceWatchManager, ): void { pi.registerTool({ name: "onedev_watch", label: "OneDev Watch", description: "Start/list/stop one-shot build or PR-attention watches.", parameters: Type.Object( { action: StringEnum([ "watch_build", "watch_pull_attention", "list", "stop", ]), ref: Type.Optional(Type.String()), watch_id: Type.Optional(Type.String()), interval_seconds: Type.Optional( Type.Integer({ minimum: 15, maximum: 300, default: 30 }), ), ttl_minutes: Type.Optional( Type.Integer({ minimum: 1, maximum: 1440, default: 60 }), ), }, { additionalProperties: false }, ), async execute(_toolCallId, params, signal) { if (params.action === "list") { const active = watches.list(); return toolResult( active.length > 0 ? JSON.stringify(active, null, 2) : "No active OneDev watches.", { watches: active }, ); } if (params.action === "stop") { if (!params.watch_id) throw new Error("stop requires watch_id"); const stopped = watches.stop(params.watch_id); return toolResult( stopped ? `Stopped OneDev watch ${params.watch_id}.` : `OneDev watch ${params.watch_id} was not active.`, { watch_id: params.watch_id, stopped }, ); } if (!params.ref) throw new Error(`${params.action} requires ref`); const result = await watches.add({ kind: params.action === "watch_build" ? "build" : "pull_attention", ref: params.ref, intervalSeconds: params.interval_seconds, ttlMinutes: params.ttl_minutes, signal, }); return toolResult(result.message, result.watch ?? { active: false }); }, }); }