'use strict';

// src/types/errors.ts
var RECOVERABLE_CODES = /* @__PURE__ */ new Set([
  "TIMEOUT" /* TIMEOUT */,
  "RATE_LIMIT" /* RATE_LIMIT */,
  "NETWORK" /* NETWORK */,
  "TOOL_EXECUTION" /* TOOL_EXECUTION */,
  "MODEL_OVERLOADED" /* MODEL_OVERLOADED */,
  "PROVIDER_ERROR" /* PROVIDER_ERROR */
]);
function isRecoverableErrorCode(code) {
  return RECOVERABLE_CODES.has(code);
}
function classifyAgentError(error) {
  const msg = (error instanceof Error ? error.message : error).toLowerCase();
  if (msg.includes("timeout") || msg.includes("timed out") || msg.includes("timedout") || msg.includes("etimedout")) {
    return "TIMEOUT" /* TIMEOUT */;
  }
  if (msg.includes("rate limit") || msg.includes("rate_limit") || msg.includes("429") || msg.includes("too many requests")) {
    return "RATE_LIMIT" /* RATE_LIMIT */;
  }
  if (msg.includes("unauthorized") || msg.includes("401") || msg.includes("auth") && (msg.includes("expired") || msg.includes("invalid") || msg.includes("denied") || msg.includes("failed"))) {
    return "AUTH_EXPIRED" /* AUTH_EXPIRED */;
  }
  if (msg.includes("econnrefused") || msg.includes("econnreset") || msg.includes("enotfound") || msg.includes("network") || msg.includes("fetch failed") || msg.includes("socket hang up")) {
    return "NETWORK" /* NETWORK */;
  }
  if (msg.includes("subprocess") || msg.includes("process exited") || msg.includes("spawn") || msg.includes("enoent") || msg.includes("killed")) {
    return "DEPENDENCY_MISSING" /* DEPENDENCY_MISSING */;
  }
  if (msg.includes("abort") || msg.includes("cancel")) {
    return "ABORTED" /* ABORTED */;
  }
  if (msg.includes("500") || msg.includes("502") || msg.includes("503") || msg.includes("internal server error") || msg.includes("service unavailable") || msg.includes("bad gateway") || msg.includes("overloaded")) {
    return "PROVIDER_ERROR" /* PROVIDER_ERROR */;
  }
  return "PROVIDER_ERROR" /* PROVIDER_ERROR */;
}

// src/types/guards.ts
function getTextContent(content) {
  if (typeof content === "string") return content;
  return content.filter((p) => p.type === "text").map((p) => p.text).join("\n");
}

// src/errors.ts
var AgentSDKError = class extends Error {
  /** @internal Marker for cross-bundle identity checks */
  _agentSDKError = true;
  /** Machine-readable error code. Prefer values from the ErrorCode enum. */
  code;
  /** Whether this error is safe to retry */
  retryable;
  /** HTTP status code hint for error classification */
  httpStatus;
  constructor(message, options) {
    super(message, options);
    this.name = "AgentSDKError";
    this.code = options?.code;
    this.retryable = options?.retryable ?? false;
    this.httpStatus = options?.httpStatus;
  }
  /** Check if an error is an AgentSDKError (works across bundled copies) */
  static is(error) {
    return error instanceof Error && "_agentSDKError" in error && error._agentSDKError === true;
  }
};
var ReentrancyError = class extends AgentSDKError {
  constructor() {
    super("Agent is already running. Await the current run before starting another.", {
      code: "REENTRANCY" /* REENTRANCY */
    });
    this.name = "ReentrancyError";
  }
};
var DisposedError = class extends AgentSDKError {
  constructor(entity) {
    super(`${entity} has been disposed and cannot be used.`, {
      code: "DISPOSED" /* DISPOSED */
    });
    this.name = "DisposedError";
  }
};
var DependencyError = class extends AgentSDKError {
  packageName;
  constructor(packageName) {
    super(`${packageName} is not installed. Install it: npm install ${packageName}`, {
      code: "DEPENDENCY_MISSING" /* DEPENDENCY_MISSING */
    });
    this.name = "DependencyError";
    this.packageName = packageName;
  }
};
var AbortError = class extends AgentSDKError {
  constructor() {
    super("Agent run was aborted.", { code: "ABORTED" /* ABORTED */ });
    this.name = "AbortError";
  }
};
var ToolExecutionError = class extends AgentSDKError {
  toolName;
  constructor(toolName, message, options) {
    super(`Tool "${toolName}" failed: ${message}`, { ...options, code: "TOOL_EXECUTION" /* TOOL_EXECUTION */ });
    this.name = "ToolExecutionError";
    this.toolName = toolName;
  }
};
var ActivityTimeoutError = class extends AgentSDKError {
  constructor(timeoutMs) {
    super(`Stream activity timeout: no event received within ${timeoutMs}ms.`, {
      code: "TIMEOUT" /* TIMEOUT */,
      retryable: true
    });
    this.name = "ActivityTimeoutError";
  }
};

// src/base-agent.ts
var BaseAgent = class {
  state = "idle";
  abortController = null;
  config;
  _cleanupExternalSignal = null;
  _streamMiddleware = [];
  /** CLI session ID for persistent mode. Override in backends that support it. */
  get sessionId() {
    return void 0;
  }
  constructor(config) {
    this.config = Object.freeze({ ...config });
  }
  // ─── Public Interface ─────────────────────────────────────────
  async run(prompt, options) {
    this.guardReentrancy();
    this.guardDisposed();
    const ac = this.createAbortController(options?.signal);
    this.state = "running";
    try {
      const messages = [{ role: "user", content: prompt }];
      const result = await this.withRetry(
        () => this.executeRun(messages, options, ac.signal),
        options
      );
      this.enrichAndNotifyUsage(result, options);
      return result;
    } finally {
      this.cleanupRun();
    }
  }
  async runWithContext(messages, options) {
    this.guardReentrancy();
    this.guardDisposed();
    const ac = this.createAbortController(options?.signal);
    this.state = "running";
    try {
      const result = await this.withRetry(
        () => this.executeRun(messages, options, ac.signal),
        options
      );
      this.enrichAndNotifyUsage(result, options);
      return result;
    } finally {
      this.cleanupRun();
    }
  }
  async runStructured(prompt, schema, options) {
    this.guardReentrancy();
    this.guardDisposed();
    const ac = this.createAbortController(options?.signal);
    this.state = "running";
    try {
      const messages = [{ role: "user", content: prompt }];
      const result = await this.withRetry(
        () => this.executeRunStructured(messages, schema, options, ac.signal),
        options
      );
      this.enrichAndNotifyUsage(result, options);
      return result;
    } finally {
      this.cleanupRun();
    }
  }
  async *stream(prompt, options) {
    this.guardReentrancy();
    this.guardDisposed();
    const ac = this.createAbortController(options?.signal);
    this.state = "streaming";
    try {
      const messages = [{ role: "user", content: prompt }];
      yield* this.streamWithRetry(
        () => this.applyStreamPipeline(this.executeStream(messages, options, ac.signal), options, ac),
        options
      );
    } finally {
      this.cleanupRun();
    }
  }
  async *streamWithContext(messages, options) {
    this.guardReentrancy();
    this.guardDisposed();
    const ac = this.createAbortController(options?.signal);
    this.state = "streaming";
    try {
      yield* this.streamWithRetry(
        () => this.applyStreamPipeline(this.executeStream(messages, options, ac.signal), options, ac),
        options
      );
    } finally {
      this.cleanupRun();
    }
  }
  /** Register a stream middleware. Applied in registration order after built-in transforms. */
  addStreamMiddleware(middleware) {
    this.guardDisposed();
    this._streamMiddleware.push(middleware);
  }
  /** Apply built-in transforms (enrich→timeout→heartbeat) then custom middleware */
  async *applyStreamPipeline(source, options, ac) {
    let stream = this.enrichStream(source, options);
    stream = this.activityTimeoutStream(stream, options?.activityTimeoutMs, ac);
    stream = this.heartbeatStream(stream);
    if (this._streamMiddleware.length > 0) {
      const ctx = {
        model: options.model,
        backend: this.backendName,
        abortController: ac,
        config: Object.freeze({ ...this.config })
      };
      for (const mw of this._streamMiddleware) {
        stream = mw(stream, ctx);
      }
    }
    yield* stream;
  }
  abort() {
    if (this.abortController) {
      this.abortController.abort();
    }
  }
  /** Default interrupt — falls back to abort(). Backends may override with graceful shutdown. */
  async interrupt() {
    this.abort();
  }
  getState() {
    return this.state;
  }
  getConfig() {
    return this.config;
  }
  /** Mark agent as disposed. Override to add cleanup. */
  dispose() {
    this._cleanupExternalSignal?.();
    this._cleanupExternalSignal = null;
    this.abort();
    this.state = "disposed";
  }
  // ─── Retry Logic ─────────────────────────────────────────────
  /** Check if an error should be retried given the retry configuration. */
  isRetryableError(error, retry) {
    if (error instanceof AbortError || error instanceof ReentrancyError || error instanceof DisposedError) {
      return false;
    }
    if (AgentSDKError.is(error)) {
      if (retry.retryableErrors && retry.retryableErrors.length > 0 && error.code) {
        return retry.retryableErrors.includes(error.code);
      }
      if (error.retryable) return true;
      if (error.code) return isRecoverableErrorCode(error.code);
    }
    return false;
  }
  /** Execute a function with retry logic per RetryConfig. */
  async withRetry(fn, options) {
    const retry = options?.retry;
    if (!retry || !retry.maxRetries || retry.maxRetries <= 0) {
      return fn();
    }
    const maxRetries = retry.maxRetries;
    const initialDelay = retry.initialDelayMs ?? 1e3;
    const multiplier = retry.backoffMultiplier ?? 2;
    let lastError;
    for (let attempt = 0; attempt <= maxRetries; attempt++) {
      try {
        return await fn();
      } catch (err) {
        lastError = err;
        if (attempt >= maxRetries || !this.isRetryableError(err, retry)) {
          throw err;
        }
        const delay = initialDelay * Math.pow(multiplier, attempt);
        await new Promise((resolve) => setTimeout(resolve, delay));
        if (options?.signal?.aborted || this.abortController?.signal.aborted) {
          throw err;
        }
      }
    }
    throw lastError;
  }
  /** Execute a stream factory with pre-stream retry: retries until first event, then committed. */
  async *streamWithRetry(factory, options) {
    const retry = options?.retry;
    if (!retry || !retry.maxRetries || retry.maxRetries <= 0) {
      yield* factory();
      return;
    }
    const maxRetries = retry.maxRetries;
    const initialDelay = retry.initialDelayMs ?? 1e3;
    const multiplier = retry.backoffMultiplier ?? 2;
    for (let attempt = 0; attempt <= maxRetries; attempt++) {
      try {
        const stream = factory();
        const iterator = stream[Symbol.asyncIterator]();
        const first = await iterator.next();
        if (first.done) return;
        yield first.value;
        while (true) {
          const next = await iterator.next();
          if (next.done) break;
          yield next.value;
        }
        return;
      } catch (err) {
        if (attempt >= maxRetries || !this.isRetryableError(err, retry)) {
          throw err;
        }
        const delay = initialDelay * Math.pow(multiplier, attempt);
        await new Promise((resolve) => setTimeout(resolve, delay));
        if (options?.signal?.aborted || this.abortController?.signal.aborted) {
          throw err;
        }
      }
    }
  }
  // ─── CallOptions Resolution ──────────────────────────────────
  /** Resolve tools to use for this call (per-call override > config default) */
  resolveTools(options) {
    return options?.tools ?? this.config.tools ?? [];
  }
  // ─── Usage Enrichment ───────────────────────────────────────────
  /** Enrich result usage with model/backend and fire onUsage callback */
  enrichAndNotifyUsage(result, options) {
    if (result.usage) {
      result.usage = {
        ...result.usage,
        model: options.model,
        backend: this.backendName
      };
      this.callOnUsage(result.usage);
    }
  }
  /** Wrap a stream to enrich usage_update events and fire onUsage callback */
  async *enrichStream(source, options) {
    const model = options.model;
    for await (const event of source) {
      if (event.type === "usage_update") {
        const usage = {
          promptTokens: event.promptTokens,
          completionTokens: event.completionTokens,
          model,
          backend: this.backendName
        };
        this.callOnUsage(usage);
        yield { type: "usage_update", ...usage };
      } else {
        yield event;
      }
    }
  }
  /** Fire onUsage callback (fire-and-forget: errors logged, not propagated) */
  callOnUsage(usage) {
    if (!this.config.onUsage) return;
    try {
      this.config.onUsage(usage);
    } catch (e) {
      console.warn(
        "[agent-sdk] onUsage callback error:",
        e instanceof Error ? e.message : String(e)
      );
    }
  }
  // ─── Heartbeat ───────────────────────────────────────────────
  /** Wrap a stream to emit heartbeat events at configured intervals.
   *  When heartbeatInterval is not set, passes through directly. */
  async *heartbeatStream(source) {
    const interval = this.config.heartbeatInterval;
    if (!interval || interval <= 0) {
      yield* source;
      return;
    }
    const iterator = source[Symbol.asyncIterator]();
    let pendingEvent = null;
    let heartbeatResolve = null;
    const timer = setInterval(() => {
      if (heartbeatResolve) {
        const resolve = heartbeatResolve;
        heartbeatResolve = null;
        resolve();
      }
    }, interval);
    try {
      while (true) {
        if (!pendingEvent) {
          pendingEvent = iterator.next();
        }
        const heartbeatPromise = new Promise((resolve) => {
          heartbeatResolve = resolve;
        });
        const eventDone = pendingEvent.then(
          (r) => ({ kind: "event", result: r })
        );
        const heartbeatDone = heartbeatPromise.then(
          () => ({ kind: "heartbeat" })
        );
        const winner = await Promise.race([eventDone, heartbeatDone]);
        if (winner.kind === "heartbeat") {
          yield { type: "heartbeat" };
        } else {
          pendingEvent = null;
          heartbeatResolve = null;
          if (winner.result.done) break;
          yield winner.result.value;
        }
      }
    } finally {
      clearInterval(timer);
      heartbeatResolve = null;
    }
  }
  // ─── Activity Timeout ────────────────────────────────────────
  /** Wrap a stream to abort on inactivity. Resets timer on every event.
   *  When timeoutMs is not set, passes through directly. */
  async *activityTimeoutStream(source, timeoutMs, ac) {
    if (!timeoutMs || timeoutMs <= 0) {
      yield* source;
      return;
    }
    const iterator = source[Symbol.asyncIterator]();
    let timerId;
    try {
      while (true) {
        const timeoutPromise = new Promise((_, reject) => {
          timerId = setTimeout(() => reject(new ActivityTimeoutError(timeoutMs)), timeoutMs);
        });
        const result = await Promise.race([iterator.next(), timeoutPromise]);
        clearTimeout(timerId);
        if (result.done) break;
        yield result.value;
      }
    } catch (err) {
      if (err instanceof ActivityTimeoutError) {
        ac.abort(err);
      }
      throw err;
    } finally {
      clearTimeout(timerId);
    }
  }
  // ─── Guards ───────────────────────────────────────────────────
  guardReentrancy() {
    if (this.state === "running" || this.state === "streaming") {
      throw new ReentrancyError();
    }
  }
  guardDisposed() {
    if (this.state === "disposed") {
      throw new DisposedError("Agent");
    }
  }
  /** Throw AbortError if signal is already aborted */
  checkAbort(signal) {
    if (signal.aborted) {
      throw new AbortError();
    }
  }
  // ─── Internal Helpers ─────────────────────────────────────────
  /** Clean up after a run completes (success, error, or abort). */
  cleanupRun() {
    this._cleanupExternalSignal?.();
    this._cleanupExternalSignal = null;
    this.state = "idle";
    this.abortController = null;
  }
  createAbortController(externalSignal) {
    const ac = new AbortController();
    this.abortController = ac;
    this._cleanupExternalSignal = null;
    if (externalSignal) {
      if (externalSignal.aborted) {
        ac.abort();
      } else {
        const listener = () => ac.abort();
        externalSignal.addEventListener("abort", listener, { once: true });
        this._cleanupExternalSignal = () => externalSignal.removeEventListener("abort", listener);
      }
    }
    return ac;
  }
};

// src/utils/schema.ts
function zodToJsonSchema(schema) {
  const schemaAny = schema;
  if ("toJSONSchema" in schema && typeof schemaAny.toJSONSchema === "function") {
    return schemaAny.toJSONSchema();
  }
  if ("jsonSchema" in schema && typeof schemaAny.jsonSchema === "function") {
    return schemaAny.jsonSchema();
  }
  return extractSchemaFromDef(schema);
}
function extractSchemaFromDef(schema) {
  const def = schema._def;
  const typeName = def.typeName;
  switch (typeName) {
    case "ZodString":
      return { type: "string" };
    case "ZodNumber":
      return { type: "number" };
    case "ZodBoolean":
      return { type: "boolean" };
    case "ZodNull":
      return { type: "null" };
    case "ZodArray":
      return {
        type: "array",
        items: extractSchemaFromDef(def.type)
      };
    case "ZodObject": {
      const shape = schema.shape;
      const properties = {};
      const required = [];
      for (const [key, value] of Object.entries(shape)) {
        const valueDef = value._def;
        if (valueDef.typeName === "ZodOptional") {
          properties[key] = extractSchemaFromDef(valueDef.innerType);
        } else {
          properties[key] = extractSchemaFromDef(value);
          required.push(key);
        }
      }
      return {
        type: "object",
        properties,
        ...required.length > 0 ? { required } : {}
      };
    }
    case "ZodOptional":
      return extractSchemaFromDef(def.innerType);
    case "ZodEnum":
      return { type: "string", enum: def.values };
    default:
      return {};
  }
}

// src/backends/vercel-ai.ts
var _sdkMock = null;
var _compatMock = null;
async function loadSDK() {
  if (_sdkMock) return _sdkMock;
  try {
    return await import('ai');
  } catch {
    throw new DependencyError("ai");
  }
}
async function loadCompat() {
  if (_compatMock) return _compatMock;
  try {
    return await import('@ai-sdk/openai-compatible');
  } catch {
    throw new DependencyError("@ai-sdk/openai-compatible");
  }
}
function _injectSDK(mock) {
  _sdkMock = mock;
}
function _injectCompat(mock) {
  _compatMock = mock;
}
function _resetSDK() {
  _sdkMock = null;
  _compatMock = null;
}
var DEFAULT_BASE_URL = "https://openrouter.ai/api/v1";
var DEFAULT_PROVIDER = "openrouter";
var DEFAULT_MAX_TURNS = 10;
function mapToolsToSDK(sdk, tools, config, sessionApprovals, permissionStore, signal) {
  const toolMap = {};
  const supervisor = config.supervisor;
  for (const ourTool of tools) {
    const jsonSchema = zodToJsonSchema(ourTool.parameters);
    toolMap[ourTool.name] = sdk.tool({
      description: ourTool.description,
      inputSchema: sdk.jsonSchema(jsonSchema),
      execute: wrapToolExecute(ourTool, supervisor, sessionApprovals, permissionStore, signal),
      ...ourTool.needsApproval && supervisor?.onPermission ? {
        needsApproval: async (_input) => {
          if (permissionStore && await permissionStore.isApproved(ourTool.name)) return false;
          if (sessionApprovals.has(ourTool.name)) return false;
          return true;
        }
      } : {}
    });
  }
  if (supervisor?.onAskUser) {
    const onAskUser = supervisor.onAskUser;
    toolMap["ask_user"] = sdk.tool({
      description: "Ask the user a question and wait for their response",
      inputSchema: sdk.jsonSchema({
        type: "object",
        properties: {
          question: { type: "string", description: "The question to ask the user" }
        },
        required: ["question"]
      }),
      execute: async (args) => {
        const response = await onAskUser(
          { question: args.question, allowFreeform: true },
          signal
        );
        return response.answer;
      }
    });
  }
  return toolMap;
}
function wrapToolExecute(ourTool, supervisor, sessionApprovals, permissionStore, signal) {
  return async (args, options) => {
    if (ourTool.needsApproval && supervisor?.onPermission) {
      const storeApproved = permissionStore && await permissionStore.isApproved(ourTool.name);
      if (!storeApproved && !sessionApprovals.has(ourTool.name)) {
        const request = {
          toolName: ourTool.name,
          toolArgs: args ?? {},
          toolCallId: options?.toolCallId
        };
        const decision = await supervisor.onPermission(
          request,
          signal
        );
        if (!decision.allowed) {
          throw new ToolExecutionError(
            ourTool.name,
            decision.reason ?? "Permission denied"
          );
        }
        if (permissionStore && decision.scope) {
          await permissionStore.approve(ourTool.name, decision.scope);
        }
        if (decision.scope === "session" || decision.scope === "always" || decision.scope === "project") {
          sessionApprovals.add(ourTool.name);
        }
        if (decision.modifiedInput) {
          args = decision.modifiedInput;
        }
      }
    }
    try {
      const result = await ourTool.execute(args);
      return result;
    } catch (e) {
      if (e instanceof ToolExecutionError) throw e;
      throw new ToolExecutionError(
        ourTool.name,
        e instanceof Error ? e.message : String(e)
      );
    }
  };
}
function messagesToSDK(messages) {
  return messages.map((msg) => {
    switch (msg.role) {
      case "user":
        return { role: "user", content: getTextContent(msg.content) };
      case "assistant": {
        let content = getTextContent(msg.content);
        const thinking = msg.thinking;
        if (thinking) {
          content = `[reasoning: ${thinking}]
${content}`;
        }
        const mapped = { role: "assistant", content };
        if (msg.toolCalls && msg.toolCalls.length > 0) {
          mapped.toolCalls = msg.toolCalls.map((tc) => ({
            id: tc.id,
            name: tc.name,
            args: tc.args
          }));
        }
        return mapped;
      }
      case "system":
        return { role: "system", content: msg.content };
      case "tool": {
        if (msg.toolResults && msg.toolResults.length > 0) {
          return {
            role: "tool",
            toolResults: msg.toolResults.map((tr) => ({
              toolCallId: tr.toolCallId,
              name: tr.name,
              result: tr.result,
              isError: tr.isError ?? false
            }))
          };
        }
        return { role: "tool", content: msg.content ?? "" };
      }
      default:
        return { role: "user", content: "" };
    }
  });
}
function mapStreamPart(part) {
  switch (part.type) {
    case "text-delta": {
      const p = part;
      return { type: "text_delta", text: p.text ?? "" };
    }
    case "tool-call": {
      const p = part;
      return {
        type: "tool_call_start",
        toolCallId: String(p.toolCallId ?? ""),
        toolName: p.toolName ?? "unknown",
        args: p.input ?? {}
      };
    }
    case "tool-result": {
      const p = part;
      return {
        type: "tool_call_end",
        toolCallId: String(p.toolCallId ?? ""),
        toolName: p.toolName ?? "unknown",
        result: p.output ?? null
      };
    }
    case "tool-error": {
      const p = part;
      return {
        type: "error",
        error: p.error instanceof Error ? p.error.message : String(p.error ?? "Tool execution failed"),
        recoverable: true,
        code: "TOOL_EXECUTION" /* TOOL_EXECUTION */
      };
    }
    case "reasoning-start":
      return { type: "thinking_start" };
    case "reasoning-end":
      return { type: "thinking_end" };
    case "reasoning-delta": {
      const p = part;
      return { type: "thinking_delta", text: p.text ?? "" };
    }
    case "finish-step": {
      const p = part;
      return {
        type: "usage_update",
        promptTokens: Number(p.usage?.inputTokens ?? 0),
        completionTokens: Number(p.usage?.outputTokens ?? 0)
      };
    }
    case "error": {
      const p = part;
      const errorMsg = p.error instanceof Error ? p.error.message : String(p.error ?? "Unknown error");
      const code = classifyAgentError(errorMsg);
      return {
        type: "error",
        error: errorMsg,
        recoverable: isRecoverableErrorCode(code),
        code
      };
    }
    default:
      return null;
  }
}
var VercelAIAgent = class extends BaseAgent {
  backendName = "vercel-ai";
  backendOptions;
  sessionApprovals = /* @__PURE__ */ new Set();
  model = null;
  constructor(config, backendOptions) {
    super(config);
    this.backendOptions = backendOptions;
  }
  async getModel(options) {
    const requestedModel = options.model;
    const defaultModel = this.config.model;
    if (requestedModel === defaultModel && this.model) return this.model;
    const compat = await loadCompat();
    const provider = compat.createOpenAICompatible({
      name: this.backendOptions.provider ?? DEFAULT_PROVIDER,
      baseURL: this.backendOptions.baseUrl ?? DEFAULT_BASE_URL,
      apiKey: this.backendOptions.apiKey
    });
    const model = provider.chatModel(requestedModel);
    if (requestedModel === defaultModel) {
      this.model = model;
    }
    return model;
  }
  async getSDKTools(signal, options) {
    const sdk = await loadSDK();
    const tools = this.resolveTools(options);
    return mapToolsToSDK(sdk, tools, this.config, this.sessionApprovals, this.config.permissionStore, signal);
  }
  // ─── executeRun ─────────────────────────────────────────────────
  async executeRun(messages, options, signal) {
    this.checkAbort(signal);
    const sdk = await loadSDK();
    const model = await this.getModel(options);
    const tools = await this.getSDKTools(signal, options);
    const maxTurns = this.config.maxTurns ?? DEFAULT_MAX_TURNS;
    const sdkMessages = messagesToSDK(messages);
    const hasTools = Object.keys(tools).length > 0;
    const result = await sdk.generateText({
      model,
      system: this.config.systemPrompt,
      messages: sdkMessages,
      tools: hasTools ? tools : void 0,
      stopWhen: sdk.stepCountIs(maxTurns),
      abortSignal: signal,
      ...this.config.modelParams?.temperature !== void 0 && {
        temperature: this.config.modelParams.temperature
      },
      ...this.config.modelParams?.maxTokens !== void 0 && {
        maxTokens: this.config.modelParams.maxTokens
      },
      ...this.config.modelParams?.topP !== void 0 && {
        topP: this.config.modelParams.topP
      },
      ...this.config.providerOptions && {
        providerOptions: this.config.providerOptions
      }
    });
    const toolCalls = [];
    for (const step of result.steps) {
      for (const tc of step.toolCalls) {
        const matchingResult = step.toolResults.find(
          (tr) => tr.toolCallId === tc.toolCallId
        );
        toolCalls.push({
          toolName: tc.toolName,
          args: tc.input ?? {},
          result: matchingResult?.output ?? null,
          approved: true
        });
      }
    }
    const usage = {
      promptTokens: Number(result.totalUsage?.inputTokens ?? 0),
      completionTokens: Number(result.totalUsage?.outputTokens ?? 0)
    };
    const lastStep = result.steps.length > 0 ? result.steps[result.steps.length - 1] : null;
    const outputText = lastStep?.text || null;
    return {
      output: outputText,
      structuredOutput: void 0,
      toolCalls,
      messages: [
        ...messages,
        ...outputText ? [{ role: "assistant", content: outputText }] : []
      ],
      usage
    };
  }
  // ─── executeRunStructured ───────────────────────────────────────
  async executeRunStructured(messages, schema, options, signal) {
    this.checkAbort(signal);
    const sdk = await loadSDK();
    const model = await this.getModel(options);
    const sdkMessages = messagesToSDK(messages);
    const jsonSchema = zodToJsonSchema(schema.schema);
    const result = await sdk.generateObject({
      model,
      system: this.config.systemPrompt,
      messages: sdkMessages,
      schema: sdk.jsonSchema(jsonSchema),
      schemaName: schema.name,
      schemaDescription: schema.description,
      abortSignal: signal,
      ...this.config.modelParams?.temperature !== void 0 && {
        temperature: this.config.modelParams.temperature
      },
      ...this.config.modelParams?.maxTokens !== void 0 && {
        maxTokens: this.config.modelParams.maxTokens
      },
      ...this.config.providerOptions && {
        providerOptions: this.config.providerOptions
      }
    });
    let structuredOutput;
    try {
      structuredOutput = schema.schema.parse(result.object);
    } catch {
    }
    const usage = {
      promptTokens: Number(result.usage?.inputTokens ?? 0),
      completionTokens: Number(result.usage?.outputTokens ?? 0)
    };
    return {
      output: JSON.stringify(result.object),
      structuredOutput,
      toolCalls: [],
      messages: [
        ...messages,
        ...result.object != null ? [{ role: "assistant", content: JSON.stringify(result.object) }] : []
      ],
      usage
    };
  }
  // ─── executeStream ──────────────────────────────────────────────
  async *executeStream(messages, options, signal) {
    this.checkAbort(signal);
    const sdk = await loadSDK();
    const model = await this.getModel(options);
    const tools = await this.getSDKTools(signal, options);
    const maxTurns = this.config.maxTurns ?? DEFAULT_MAX_TURNS;
    const sdkMessages = messagesToSDK(messages);
    const hasTools = Object.keys(tools).length > 0;
    const result = sdk.streamText({
      model,
      system: this.config.systemPrompt,
      messages: sdkMessages,
      tools: hasTools ? tools : void 0,
      stopWhen: sdk.stepCountIs(maxTurns),
      abortSignal: signal,
      ...this.config.modelParams?.temperature !== void 0 && {
        temperature: this.config.modelParams.temperature
      },
      ...this.config.modelParams?.maxTokens !== void 0 && {
        maxTokens: this.config.modelParams.maxTokens
      },
      ...this.config.modelParams?.topP !== void 0 && {
        topP: this.config.modelParams.topP
      },
      ...this.config.providerOptions && {
        providerOptions: this.config.providerOptions
      }
    });
    let finalText = "";
    try {
      for await (const part of result.fullStream) {
        if (signal.aborted) throw new AbortError();
        const event = mapStreamPart(part);
        if (event) yield event;
        if (part.type === "text-delta") {
          finalText += part.text ?? "";
        }
        if (part.type === "finish-step") {
          const p = part;
          if (p.finishReason === "tool-calls") {
            finalText = "";
          }
        }
      }
      const totalUsage = await result.totalUsage;
      yield {
        type: "usage_update",
        promptTokens: Number(totalUsage?.inputTokens ?? 0),
        completionTokens: Number(totalUsage?.outputTokens ?? 0)
      };
      const hasStreamed = finalText.length > 0;
      yield {
        type: "done",
        finalOutput: hasStreamed ? null : finalText || null,
        ...hasStreamed ? { streamed: true } : {}
      };
    } catch (e) {
      if (signal.aborted) throw new AbortError();
      throw e;
    }
  }
  dispose() {
    this.sessionApprovals.clear();
    this.model = null;
    super.dispose();
  }
};
var VercelAIAgentService = class {
  name = "vercel-ai";
  disposed = false;
  options;
  constructor(options) {
    this.options = options;
  }
  createAgent(config) {
    if (this.disposed) throw new DisposedError("VercelAIAgentService");
    return new VercelAIAgent(config, this.options);
  }
  async listModels() {
    if (this.disposed) throw new DisposedError("VercelAIAgentService");
    const baseUrl = (this.options.baseUrl || "https://api.openai.com/v1").replace(/\/+$/, "");
    try {
      const res = await globalThis.fetch(`${baseUrl}/models`, {
        headers: {
          Authorization: `Bearer ${this.options.apiKey}`,
          // OpenRouter requires HTTP-Referer for API access
          "HTTP-Referer": "https://github.com/nicepkg/agent-sdk"
        }
      });
      if (!res.ok) {
        return [];
      }
      const body = await res.json();
      if (body.data && Array.isArray(body.data)) {
        return body.data.filter((m) => typeof m.id === "string").map((m) => ({
          id: m.id,
          ...typeof m.name === "string" && { name: m.name },
          ...typeof m.description === "string" && { description: m.description },
          ...typeof m.context_length === "number" && { contextWindow: m.context_length }
        }));
      }
      if (Array.isArray(body)) {
        return body.filter((m) => typeof m.id === "string").map((m) => ({
          id: m.id,
          ...typeof m.name === "string" && { name: m.name },
          ...typeof m.description === "string" && { description: m.description },
          ...typeof m.context_length === "number" && { contextWindow: m.context_length }
        }));
      }
      return [];
    } catch {
      return [];
    }
  }
  async validate() {
    if (this.disposed) throw new DisposedError("VercelAIAgentService");
    const errors = [];
    if (!this.options.apiKey) {
      errors.push("apiKey is required for Vercel AI backend.");
    }
    try {
      await loadSDK();
    } catch (e) {
      errors.push(e instanceof Error ? e.message : String(e));
    }
    try {
      await loadCompat();
    } catch (e) {
      errors.push(e instanceof Error ? e.message : String(e));
    }
    return { valid: errors.length === 0, errors };
  }
  async dispose() {
    if (this.disposed) return;
    this.disposed = true;
  }
};
function createVercelAIService(options) {
  return new VercelAIAgentService(options);
}

exports._injectCompat = _injectCompat;
exports._injectSDK = _injectSDK;
exports._resetSDK = _resetSDK;
exports.createVercelAIService = createVercelAIService;
//# sourceMappingURL=vercel-ai.cjs.map
//# sourceMappingURL=vercel-ai.cjs.map