// @bun
import {
  getTypings
} from "./chunk-b8c41yvb.js";
import {
  convertObjectToZuiLiterals,
  isJsonSchema,
  isValidIdentifier,
  isZuiSchema
} from "./chunk-gspjbr79.js";
import {
  exports_exports,
  isEmpty_default,
  transforms_exports,
  uniq_default
} from "./chunk-wesykvkp.js";

// ../../node_modules/.bun/llmz@0.0.79+ed0f774122d294fe/node_modules/llmz/dist/chunk-UI6J4WKQ.js
var Tool = class _Tool {
  _staticInputValues;
  name;
  aliases = [];
  description;
  metadata;
  input;
  output;
  retry;
  MAX_RETRIES = 1000;
  setStaticInputValues(values) {
    if (values === null || values === undefined) {
      this._staticInputValues = undefined;
      return this;
    }
    const input = this.input ? transforms_exports.fromJSONSchemaLegacy(this.input) : exports_exports.any();
    if (exports_exports.is.zuiObject(input) && typeof values !== "object") {
      throw new Error(`Invalid static input values for tool ${this.name}. Expected an object, but got type "${typeof values}"`);
    }
    if (exports_exports.is.zuiArray(input) && !Array.isArray(values)) {
      throw new Error(`Invalid static input values for tool ${this.name}. Expected an array, but got type "${typeof values}"`);
    }
    this._staticInputValues = values;
    return this;
  }
  get zInput() {
    let input;
    if (this.input) {
      try {
        input = transforms_exports.fromJSONSchema(this.input);
      } catch {
        input = transforms_exports.fromJSONSchemaLegacy(this.input);
      }
    } else {
      input = exports_exports.any();
    }
    if (!isEmpty_default(this._staticInputValues)) {
      const inputExtensions = convertObjectToZuiLiterals(this._staticInputValues);
      if (exports_exports.is.zuiObject(input)) {
        input = input.extend(inputExtensions);
      } else if (exports_exports.is.zuiArray(input)) {
        input = exports_exports.array(input.element.extend(inputExtensions));
      } else {
        input = inputExtensions;
      }
    }
    return input;
  }
  get zOutput() {
    let output = exports_exports.void();
    if (this.output) {
      try {
        output = transforms_exports.fromJSONSchema(this.output);
      } catch {
        output = transforms_exports.fromJSONSchemaLegacy(this.output);
      }
    }
    return exports_exports.promise(output);
  }
  rename(name) {
    const before = this.name;
    if (!isValidIdentifier(name)) {
      throw new Error(`Invalid name for tool ${name}. A tool name must start with a letter and contain only letters, numbers, and underscores. It must be 1-50 characters long.`);
    }
    this.name = name;
    this.aliases = uniq_default([name, ...this.aliases.map((alias) => alias === before ? name : alias)]);
    return this;
  }
  clone(props = {}) {
    var _a, _b;
    try {
      let zInput;
      if (this.input) {
        try {
          zInput = transforms_exports.fromJSONSchema(this.input);
        } catch {
          zInput = transforms_exports.fromJSONSchemaLegacy(this.input);
        }
      }
      let zOutput;
      if (this.output) {
        try {
          zOutput = transforms_exports.fromJSONSchema(this.output);
        } catch {
          zOutput = transforms_exports.fromJSONSchemaLegacy(this.output);
        }
      }
      return new _Tool({
        name: props.name ?? this.name,
        aliases: props.aliases ?? [...this.aliases],
        description: props.description ?? this.description,
        metadata: JSON.parse(JSON.stringify(props.metadata ?? this.metadata)),
        input: typeof props.input === "function" ? (_a = props.input) == null ? undefined : _a.call(props, zInput) : exports_exports.is.zuiType(props.input) ? props.input : zInput,
        output: typeof props.output === "function" ? (_b = props.output) == null ? undefined : _b.call(props, zOutput) : exports_exports.is.zuiType(props.output) ? props.output : zOutput,
        handler: props.handler ?? this._handler,
        retry: props.retry ?? this.retry
      }).setStaticInputValues(props.staticInputValues ?? this._staticInputValues);
    } catch (e) {
      throw new Error(`Failed to clone tool "${this.name}": ${e}`);
    }
  }
  _handler;
  constructor(props) {
    if (!isValidIdentifier(props.name)) {
      throw new Error(`Invalid name for tool ${props.name}. A tool name must start with a letter and contain only letters, numbers, and underscores. It must be 1-50 characters long.`);
    }
    if (props.description !== undefined && typeof props.description !== "string") {
      throw new Error(`Invalid description for tool ${props.name}. Expected a string, but got type "${typeof props.description}"`);
    }
    if (props.metadata !== undefined && typeof props.metadata !== "object") {
      throw new Error(`Invalid metadata for tool ${props.name}. Expected an object, but got type "${typeof props.metadata}"`);
    }
    if (typeof props.handler !== "function") {
      throw new Error(`Invalid handler for tool ${props.name}. Expected a function, but got type "${typeof props.handler}"`);
    }
    if (props.aliases !== undefined && !Array.isArray(props.aliases)) {
      throw new Error(`Invalid aliases for tool ${props.name}. Expected an array, but got type "${typeof props.aliases}"`);
    }
    if (props.aliases && props.aliases.some((alias) => !isValidIdentifier(alias))) {
      throw new Error(`Invalid aliases for tool ${props.name}. Expected an array of valid identifiers.`);
    }
    if (typeof props.input !== "undefined") {
      if (isZuiSchema(props.input)) {
        try {
          this.input = transforms_exports.toJSONSchema(props.input);
        } catch {
          this.input = transforms_exports.toJSONSchemaLegacy(props.input);
        }
      } else if (isJsonSchema(props.input)) {
        this.input = props.input;
      } else {
        throw new Error(`Invalid input schema for tool ${props.name}. Expected a ZodType or JSONSchema, but got type "${typeof props.input}"`);
      }
    }
    if (typeof props.output !== "undefined") {
      if (isZuiSchema(props.output)) {
        try {
          this.output = transforms_exports.toJSONSchema(props.output);
        } catch {
          this.output = transforms_exports.toJSONSchemaLegacy(props.output);
        }
      } else if (isJsonSchema(props.output)) {
        this.output = props.output;
      } else {
        throw new Error(`Invalid output schema for tool ${props.name}. Expected a ZodType or JSONSchema, but got type "${typeof props.output}"`);
      }
    }
    this.name = props.name;
    this.aliases = uniq_default([props.name, ...props.aliases ?? []]);
    this.description = props.description;
    this.metadata = props.metadata ?? {};
    this._handler = props.handler;
    this.setStaticInputValues(props.staticInputValues);
    this.retry = props.retry;
  }
  async _executeHandler(input, ctx, chat, yieldedCount, setYieldedCount) {
    var _a;
    const handler = this._handler(input, ctx);
    const isGen = typeof handler === "object" && handler !== null && "next" in handler;
    if (!isGen) {
      return handler;
    }
    let yieldIndex = 0;
    while (true) {
      const { value, done } = await handler.next();
      if (done) {
        return value;
      }
      if (yieldIndex >= yieldedCount) {
        setYieldedCount(yieldIndex + 1);
        await ((_a = chat == null ? undefined : chat.handler) == null ? undefined : _a.call(chat, value));
      }
      yieldIndex++;
    }
  }
  async execute(rawInput, ctx, chat) {
    var _a;
    const isZodObject = this.zInput._def.typeName === "ZodObject";
    const input = isZodObject ? rawInput ?? {} : rawInput;
    const pInput = this.zInput.safeParse(input);
    if (!pInput.success) {
      throw new Error(`Tool "${this.name}" received invalid input: ${pInput.error.message}`);
    }
    let attempt = 0;
    let yieldedCount = 0;
    while (attempt < this.MAX_RETRIES) {
      try {
        const result = await this._executeHandler(pInput.data, ctx, chat, yieldedCount, (n) => {
          yieldedCount = n;
        });
        const pOutput = this.zOutput.safeParse(result);
        return pOutput.success ? pOutput.data : result;
      } catch (err) {
        const shouldRetry = await ((_a = this.retry) == null ? undefined : _a.call(this, {
          input: pInput.data,
          attempt: ++attempt,
          error: err
        }));
        if (!shouldRetry) {
          throw err;
        }
      }
    }
    throw new Error(`Tool "${this.name}" failed after ${this.MAX_RETRIES} attempts. Last error: ${JSON.stringify(input)}`);
  }
  async getTypings() {
    let input;
    if (this.input) {
      try {
        input = transforms_exports.fromJSONSchema(this.input);
      } catch {
        input = transforms_exports.fromJSONSchemaLegacy(this.input);
      }
    }
    let output;
    if (!this.output || Object.keys(this.output).length === 0) {
      output = exports_exports.void();
    } else {
      try {
        output = transforms_exports.fromJSONSchema(this.output);
      } catch {
        output = transforms_exports.fromJSONSchemaLegacy(this.output);
      }
    }
    if (input && exports_exports.is.zuiObject(input.naked()) && typeof this._staticInputValues === "object" && !isEmpty_default(this._staticInputValues)) {
      const inputExtensions = convertObjectToZuiLiterals(this._staticInputValues);
      input = input.extend(inputExtensions);
    } else if (this._staticInputValues !== undefined) {
      input = convertObjectToZuiLiterals(this._staticInputValues);
    }
    const fnType = exports_exports.function(input, exports_exports.promise(output)).title(this.name).describe(this.description ?? "");
    return getTypings(fnType, {
      declaration: true
    });
  }
  static withUniqueNames = (tools) => {
    const names = /* @__PURE__ */ new Set;
    return tools.map((tool) => {
      if (tools.filter((t) => t.name === tool.name).length === 1) {
        return tool;
      }
      let counter = 1;
      let toolName = tool.name + counter;
      while (names.has(toolName)) {
        toolName = `${tool.name}${++counter}`;
      }
      names.add(toolName);
      return tool.rename(toolName);
    });
  };
  toJSON() {
    return {
      name: this.name,
      aliases: [...this.aliases],
      description: this.description,
      metadata: this.metadata,
      input: this.input,
      output: this.output,
      staticInputValues: this._staticInputValues,
      maxRetries: this.MAX_RETRIES
    };
  }
};

export { Tool };
