(
name: string,
args: Record<string, unknown>,
options: { timeoutMs?: number } = {},
)
| 71 | } |
| 72 | |
| 73 | export async function executeTool( |
| 74 | name: string, |
| 75 | args: Record<string, unknown>, |
| 76 | options: { timeoutMs?: number } = {}, |
| 77 | ): Promise<ToolExecResult> { |
| 78 | const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS; |
| 79 | const url = `${kbApiBase()}/api/agent-tool`; |
| 80 | const t0 = Date.now(); |
| 81 | |
| 82 | const controller = new AbortController(); |
| 83 | const timer = setTimeout(() => controller.abort(), timeoutMs); |
| 84 | |
| 85 | try { |
| 86 | const res = await fetch(url, { |
| 87 | method: "POST", |
| 88 | headers: buildHeaders(), |
| 89 | body: JSON.stringify({ tool: name, args }), |
| 90 | signal: controller.signal, |
| 91 | }); |
| 92 | const duration_ms = Date.now() - t0; |
| 93 | |
| 94 | let parsed: unknown; |
| 95 | try { |
| 96 | parsed = await res.json(); |
| 97 | } catch { |
| 98 | return { ok: false, error: `non-json response (status ${res.status})`, duration_ms }; |
| 99 | } |
| 100 | |
| 101 | if (!res.ok) { |
| 102 | const errMsg = |
| 103 | parsed && typeof parsed === "object" && "error" in parsed |
| 104 | ? String((parsed as { error: unknown }).error) |
| 105 | : `http_${res.status}`; |
| 106 | return { ok: false, error: errMsg, duration_ms }; |
| 107 | } |
| 108 | |
| 109 | if ( |
| 110 | parsed && |
| 111 | typeof parsed === "object" && |
| 112 | "ok" in parsed && |
| 113 | (parsed as { ok: unknown }).ok === true && |
| 114 | "data" in parsed |
| 115 | ) { |
| 116 | return { ok: true, data: (parsed as { data: unknown }).data, duration_ms }; |
| 117 | } |
| 118 | |
| 119 | return { |
| 120 | ok: false, |
| 121 | error: "unexpected response shape", |
| 122 | duration_ms, |
| 123 | }; |
| 124 | } catch (e: unknown) { |
| 125 | const duration_ms = Date.now() - t0; |
| 126 | if (e instanceof Error && e.name === "AbortError") { |
| 127 | return { ok: false, error: `timeout (${timeoutMs}ms)`, duration_ms }; |
| 128 | } |
| 129 | return { |
| 130 | ok: false, |
no test coverage detected