var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
var __typeError = (msg) => {
  throw TypeError(msg);
};
var __using = (stack, value, async) => {
  if (value != null) {
    if (typeof value !== "object" && typeof value !== "function") __typeError("Object expected");
    var dispose, inner;
    if (async) dispose = value[__knownSymbol("asyncDispose")];
    if (dispose === void 0) {
      dispose = value[__knownSymbol("dispose")];
      if (async) inner = dispose;
    }
    if (typeof dispose !== "function") __typeError("Object not disposable");
    if (inner) dispose = function() {
      try {
        inner.call(this);
      } catch (e) {
        return Promise.reject(e);
      }
    };
    stack.push([async, dispose, value]);
  } else if (async) {
    stack.push([async]);
  }
  return value;
};
var __callDispose = (stack, error, hasError) => {
  var E = typeof SuppressedError === "function" ? SuppressedError : function(e, s, m, _) {
    return _ = Error(m), _.name = "SuppressedError", _.error = e, _.suppressed = s, _;
  };
  var fail = (e) => error = hasError ? new E(e, error, "An error was suppressed during disposal") : (hasError = true, e);
  var next = (it2) => {
    while (it2 = stack.pop()) {
      try {
        var result = it2[1] && it2[1].call(it2[2]);
        if (it2[0]) return Promise.resolve(result).then(next, (e) => (fail(e), next()));
      } catch (e) {
        fail(e);
      }
    }
    if (hasError) throw error;
  };
  return next();
};
import { ReadableStream } from "node:stream/web";
import { describe, expect, it } from "vitest";
import { z } from "zod";
import { FunctionCall } from "../../llm/chat_context.js";
import { ToolContext, tool } from "../../llm/tool_context.js";
import { Agent } from "../agent.js";
import { performToolExecutions } from "../generation.js";
import { SpeechHandle } from "../speech_handle.js";
import { activeMockTools, withMockTools } from "./run_result.js";
class AgentA extends Agent {
  constructor() {
    super({ instructions: "a" });
  }
}
class AgentB extends Agent {
  constructor() {
    super({ instructions: "b" });
  }
}
describe("withMockTools", () => {
  it("sets the mock registry for the given agent inside the block", () => {
    var _a, _b;
    const mock = () => "mocked";
    {
      var _stack = [];
      try {
        const _mock = __using(_stack, withMockTools(AgentA, { tool1: mock }));
        expect(activeMockTools).toBeDefined();
        expect((_b = (_a = activeMockTools) == null ? void 0 : _a.get(AgentA)) == null ? void 0 : _b.tool1).toBe(mock);
      } catch (_) {
        var _error = _, _hasError = true;
      } finally {
        __callDispose(_stack, _error, _hasError);
      }
    }
    expect(activeMockTools).toBeUndefined();
  });
  it("merges mocks across nested blocks and isolates per agent", () => {
    var _a, _b, _c, _d, _e, _f, _g;
    const mockA = () => "a";
    const mockB = () => "b";
    {
      var _stack2 = [];
      try {
        const _mockA = __using(_stack2, withMockTools(AgentA, { toolA: mockA }));
        {
          var _stack = [];
          try {
            const _mockB = __using(_stack, withMockTools(AgentB, { toolB: mockB }));
            expect((_b = (_a = activeMockTools) == null ? void 0 : _a.get(AgentA)) == null ? void 0 : _b.toolA).toBe(mockA);
            expect((_d = (_c = activeMockTools) == null ? void 0 : _c.get(AgentB)) == null ? void 0 : _d.toolB).toBe(mockB);
          } catch (_) {
            var _error = _, _hasError = true;
          } finally {
            __callDispose(_stack, _error, _hasError);
          }
        }
        expect((_f = (_e = activeMockTools) == null ? void 0 : _e.get(AgentA)) == null ? void 0 : _f.toolA).toBe(mockA);
        expect((_g = activeMockTools) == null ? void 0 : _g.get(AgentB)).toBeUndefined();
      } catch (_2) {
        var _error2 = _2, _hasError2 = true;
      } finally {
        __callDispose(_stack2, _error2, _hasError2);
      }
    }
  });
  it("inner block for same agent overrides outer mocks", () => {
    var _a, _b, _c, _d;
    const outer = () => "outer";
    const inner = () => "inner";
    {
      var _stack2 = [];
      try {
        const _outer = __using(_stack2, withMockTools(AgentA, { tool1: outer }));
        {
          var _stack = [];
          try {
            const _inner = __using(_stack, withMockTools(AgentA, { tool1: inner }));
            expect((_b = (_a = activeMockTools) == null ? void 0 : _a.get(AgentA)) == null ? void 0 : _b.tool1).toBe(inner);
          } catch (_) {
            var _error = _, _hasError = true;
          } finally {
            __callDispose(_stack, _error, _hasError);
          }
        }
        expect((_d = (_c = activeMockTools) == null ? void 0 : _c.get(AgentA)) == null ? void 0 : _d.tool1).toBe(outer);
      } catch (_2) {
        var _error2 = _2, _hasError2 = true;
      } finally {
        __callDispose(_stack2, _error2, _hasError2);
      }
    }
  });
  it("exposes the mock for invocation within the block", async () => {
    var _a, _b;
    var _stack = [];
    try {
      const _mock = __using(_stack, withMockTools(AgentA, { tool1: async () => 42 }));
      const mock = (_b = (_a = activeMockTools) == null ? void 0 : _a.get(AgentA)) == null ? void 0 : _b.tool1;
      expect(await (mock == null ? void 0 : mock())).toBe(42);
    } catch (_) {
      var _error = _, _hasError = true;
    } finally {
      __callDispose(_stack, _error, _hasError);
    }
  });
  it("routes performToolExecutions to the mock when set, original otherwise", async () => {
    var _a, _b;
    let realCalled = false;
    const realTool = tool({
      name: "greet",
      description: "real",
      parameters: z.object({ name: z.string() }),
      execute: async ({ name }) => {
        realCalled = true;
        return `real:${name}`;
      }
    });
    const toolCtx = new ToolContext([realTool]);
    const speechHandle = SpeechHandle.create({ allowInterruptions: false });
    const agent = new AgentA();
    const session = { currentAgent: agent };
    const makeStream = (call2) => new ReadableStream({
      start(controller2) {
        controller2.enqueue(call2);
        controller2.close();
      }
    });
    {
      var _stack = [];
      try {
        const _mock = __using(_stack, withMockTools(AgentA, { greet: () => "mocked" }));
        const controller2 = new AbortController();
        const call2 = FunctionCall.create({
          callId: "call_1",
          name: "greet",
          args: JSON.stringify({ name: "world" })
        });
        const [task2, output2] = performToolExecutions({
          session,
          speechHandle,
          toolCtx,
          toolCallStream: makeStream(call2),
          controller: controller2
        });
        await task2.result;
        expect(realCalled).toBe(false);
        expect((_a = output2.output[0]) == null ? void 0 : _a.rawOutput).toBe("mocked");
      } catch (_) {
        var _error = _, _hasError = true;
      } finally {
        __callDispose(_stack, _error, _hasError);
      }
    }
    const controller = new AbortController();
    const call = FunctionCall.create({
      callId: "call_2",
      name: "greet",
      args: JSON.stringify({ name: "world" })
    });
    const [task, output] = performToolExecutions({
      session,
      speechHandle,
      toolCtx,
      toolCallStream: makeStream(call),
      controller
    });
    await task.result;
    expect(realCalled).toBe(true);
    expect((_b = output.output[0]) == null ? void 0 : _b.rawOutput).toBe("real:world");
  });
  it("propagates thrown errors from mocks as tool errors", async () => {
    var _a, _b, _c, _d;
    var _stack = [];
    try {
      const realTool = tool({
        name: "failing",
        description: "real",
        parameters: z.object({}),
        execute: async () => "ok"
      });
      const toolCtx = new ToolContext([realTool]);
      const speechHandle = SpeechHandle.create({ allowInterruptions: false });
      const session = { currentAgent: new AgentA() };
      const _mock = __using(_stack, withMockTools(AgentA, {
        failing: () => {
          throw new Error("test failure");
        }
      }));
      const controller = new AbortController();
      const call = FunctionCall.create({
        callId: "call_err",
        name: "failing",
        args: "{}"
      });
      const stream = new ReadableStream({
        start(c) {
          c.enqueue(call);
          c.close();
        }
      });
      const [task, output] = performToolExecutions({
        session,
        speechHandle,
        toolCtx,
        toolCallStream: stream,
        controller
      });
      await task.result;
      expect((_b = (_a = output.output[0]) == null ? void 0 : _a.rawException) == null ? void 0 : _b.message).toBe("test failure");
      expect((_d = (_c = output.output[0]) == null ? void 0 : _c.toolCallOutput) == null ? void 0 : _d.isError).toBe(true);
    } catch (_) {
      var _error = _, _hasError = true;
    } finally {
      __callDispose(_stack, _error, _hasError);
    }
  });
});
//# sourceMappingURL=run_result.test.js.map