({ agent, plan, ctx }: ExecIn)
| 13 | } |
| 14 | |
| 15 | export async function execDirect({ agent, plan, ctx }: ExecIn): Promise<ExecOut> { |
| 16 | const ag = get(agent) |
| 17 | if (!ag) throw new Error(`agent_not_found: ${agent}`) |
| 18 | |
| 19 | const threadId = randomBytes(12).toString("hex") |
| 20 | const trace: any[] = [] |
| 21 | let last: any = null |
| 22 | |
| 23 | for (let i = 0; i < (plan?.steps?.length || 0); i++) { |
| 24 | const st = plan.steps[i] || {} |
| 25 | const name = String(st.tool || "").trim() |
| 26 | const input = st.input ?? {} |
| 27 | const timeoutMs = Number.isFinite(st.timeoutMs) ? Number(st.timeoutMs) : 15000 |
| 28 | const retries = Number.isFinite(st.retries) ? Math.min(2, Math.max(0, Number(st.retries))) : 0 |
| 29 | |
| 30 | const tool = ag.tools.find(t => t.name === name) |
| 31 | if (!tool) throw new Error(`tool_not_found: "${name}" | have=${JSON.stringify(ag.tools.map(t => t.name))}`) |
| 32 | |
| 33 | let attempt = 0, ok = false, out: any, err: any |
| 34 | while (attempt <= retries && !ok) { |
| 35 | try { |
| 36 | out = await withTimeout(tool.run(input, ctx || {}), timeoutMs, name) |
| 37 | ok = true |
| 38 | } catch (e) { |
| 39 | err = e |
| 40 | attempt++ |
| 41 | if (attempt > retries) throw e |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | trace.push({ step: i + 1, tool: name, input, output: out, err: err ? String(err) : null, retries: attempt }) |
| 46 | last = out |
| 47 | } |
| 48 | |
| 49 | return { trace, result: last, threadId } |
| 50 | } |
no test coverage detected