const require_rolldown_runtime = require("./rolldown-runtime-D_mwlA32.cjs");
const require_logger = require("./logger-DuG3amVa.cjs");
const require_fetch = require("./fetch-Hdu2Q-w3.cjs");
const require_createHash = require("./createHash-CF9Ylxcw.cjs");
const require_chat = require("./chat-Bl2LfE5B.cjs");
const require_embedding = require("./embedding-B-5e24ct.cjs");
const require_responses = require("./responses-Gq3p9VLZ.cjs");
let path = require("path");
path = require_rolldown_runtime.__toESM(path, 1);
let fs = require("fs");
fs = require_rolldown_runtime.__toESM(fs, 1);
let os = require("os");
os = require_rolldown_runtime.__toESM(os, 1);
let crypto = require("crypto");
crypto = require_rolldown_runtime.__toESM(crypto, 1);
let ws = require("ws");
ws = require_rolldown_runtime.__toESM(ws, 1);
let json5 = require("json5");
json5 = require_rolldown_runtime.__toESM(json5, 1);
//#region src/providers/openclaw/device-auth.ts
const DEFAULT_CLIENT_DIR = "openclaw";
const DEFAULT_DEVICE_IDENTITY_FILE = "device-identity.json";
const DEFAULT_DEVICE_AUTH_FILE = "device-auth.json";
function defaultOpenClawClientPath(fileName) {
	return path.default.join(require_logger.getConfigDirectoryPath(true), DEFAULT_CLIENT_DIR, fileName);
}
function getDefaultOpenClawDeviceIdentityPath() {
	return defaultOpenClawClientPath(DEFAULT_DEVICE_IDENTITY_FILE);
}
function getDefaultOpenClawDeviceAuthPath() {
	return defaultOpenClawClientPath(DEFAULT_DEVICE_AUTH_FILE);
}
function ensureParentDirectory(filePath) {
	fs.default.mkdirSync(path.default.dirname(filePath), {
		recursive: true,
		mode: 448
	});
}
function writeJsonSecure(filePath, value) {
	ensureParentDirectory(filePath);
	fs.default.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, {
		encoding: "utf-8",
		mode: 384
	});
	fs.default.chmodSync(filePath, 384);
}
function parseJsonObject(raw) {
	try {
		const parsed = JSON.parse(raw);
		return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
	} catch (err) {
		require_logger.logger.debug("[OpenClaw Device Auth] Failed to parse JSON", {
			err,
			rawLength: raw.length,
			rawPreview: raw.slice(0, 100)
		});
		return;
	}
}
function normalizeDeviceMetadataValue(value) {
	const trimmed = value?.trim();
	if (!trimmed) return "";
	return trimmed.replace(/[A-Z]/g, (letter) => letter.toLowerCase());
}
function normalizeScopes$1(scopes) {
	const seen = /* @__PURE__ */ new Set();
	for (const scope of scopes || []) {
		const trimmed = scope.trim();
		if (trimmed) seen.add(trimmed);
	}
	if (seen.has("operator.admin")) {
		seen.add("operator.read");
		seen.add("operator.write");
	} else if (seen.has("operator.write")) seen.add("operator.read");
	return Array.from(seen).sort();
}
function publicKeyBase64UrlFromPem(publicKeyPem) {
	const publicKey = crypto.default.createPublicKey(publicKeyPem);
	const jwk = publicKey.export({ format: "jwk" });
	if (typeof jwk.x === "string" && jwk.x.trim()) return jwk.x;
	const der = publicKey.export({
		type: "spki",
		format: "der"
	});
	return Buffer.from(der.subarray(Math.max(0, der.length - 32))).toString("base64url");
}
function deriveDeviceId(publicKeyPem) {
	return require_createHash.sha256(Buffer.from(publicKeyBase64UrlFromPem(publicKeyPem), "base64url"));
}
function isValidIdentity(identity) {
	try {
		const publicKeyFromPrivateKey = crypto.default.createPublicKey(identity.privateKeyPem).export({
			type: "spki",
			format: "pem"
		});
		return identity.deviceId === deriveDeviceId(identity.publicKeyPem) && publicKeyBase64UrlFromPem(identity.publicKeyPem) === publicKeyBase64UrlFromPem(publicKeyFromPrivateKey);
	} catch {
		return false;
	}
}
function parseIdentity(raw) {
	const parsed = parseJsonObject(raw);
	const identity = {
		deviceId: typeof parsed?.deviceId === "string" ? parsed.deviceId : "",
		publicKeyPem: typeof parsed?.publicKeyPem === "string" ? parsed.publicKeyPem : "",
		privateKeyPem: typeof parsed?.privateKeyPem === "string" ? parsed.privateKeyPem : ""
	};
	return isValidIdentity(identity) ? identity : void 0;
}
function createDeviceIdentity() {
	const keyPair = crypto.default.generateKeyPairSync("ed25519", {
		publicKeyEncoding: {
			type: "spki",
			format: "pem"
		},
		privateKeyEncoding: {
			type: "pkcs8",
			format: "pem"
		}
	});
	const publicKeyPem = keyPair.publicKey;
	return {
		deviceId: deriveDeviceId(publicKeyPem),
		publicKeyPem,
		privateKeyPem: keyPair.privateKey
	};
}
function loadOrCreateOpenClawDeviceIdentity(filePath) {
	const identityPath = filePath || getDefaultOpenClawDeviceIdentityPath();
	try {
		if (fs.default.existsSync(identityPath)) {
			const identity = parseIdentity(fs.default.readFileSync(identityPath, "utf-8"));
			if (identity) return identity;
		}
	} catch (err) {
		require_logger.logger.warn("[OpenClaw Device Auth] Failed to read device identity; generating new identity", {
			err,
			identityPath
		});
	}
	const identity = createDeviceIdentity();
	try {
		writeJsonSecure(identityPath, identity);
	} catch (err) {
		require_logger.logger.warn("[OpenClaw Device Auth] Failed to persist device identity", {
			err,
			identityPath
		});
	}
	return identity;
}
function buildOpenClawDeviceAuthPayloadV3(params) {
	return [
		"v3",
		params.deviceId,
		params.clientId,
		params.clientMode,
		params.role,
		params.scopes.join(","),
		String(params.signedAtMs),
		params.token ?? "",
		params.nonce,
		normalizeDeviceMetadataValue(params.platform),
		normalizeDeviceMetadataValue(params.deviceFamily)
	].join("|");
}
function signOpenClawDevicePayload(privateKeyPem, payload) {
	return crypto.default.sign(null, Buffer.from(payload), privateKeyPem).toString("base64url");
}
function buildSignedOpenClawDevice(params) {
	const signedAt = params.nowMs ?? Date.now();
	const payload = buildOpenClawDeviceAuthPayloadV3({
		deviceId: params.identity.deviceId,
		clientId: params.clientId,
		clientMode: params.clientMode,
		role: params.role,
		scopes: params.scopes,
		signedAtMs: signedAt,
		token: params.token,
		nonce: params.nonce,
		platform: params.platform,
		deviceFamily: params.deviceFamily
	});
	return {
		id: params.identity.deviceId,
		publicKey: publicKeyBase64UrlFromPem(params.identity.publicKeyPem),
		signature: signOpenClawDevicePayload(params.identity.privateKeyPem, payload),
		signedAt,
		nonce: params.nonce
	};
}
function parseDeviceAuthStore(raw) {
	const parsed = parseJsonObject(raw);
	if (!parsed || parsed.version !== 1 || typeof parsed.deviceId !== "string") return;
	const tokens = {};
	const rawTokens = parsed.tokens && typeof parsed.tokens === "object" && !Array.isArray(parsed.tokens) ? parsed.tokens : {};
	for (const [role, tokenRecord] of Object.entries(rawTokens)) {
		if (!tokenRecord || typeof tokenRecord !== "object" || Array.isArray(tokenRecord)) continue;
		const record = tokenRecord;
		if (typeof record.token !== "string" || !record.token.trim()) continue;
		tokens[role] = {
			token: record.token,
			role: typeof record.role === "string" ? record.role : role,
			scopes: Array.isArray(record.scopes) ? normalizeScopes$1(record.scopes.filter((scope) => typeof scope === "string")) : [],
			updatedAtMs: typeof record.updatedAtMs === "number" ? record.updatedAtMs : 0
		};
	}
	return {
		version: 1,
		deviceId: parsed.deviceId,
		tokens
	};
}
function readDeviceAuthStore(filePath) {
	try {
		if (!fs.default.existsSync(filePath)) return;
		return parseDeviceAuthStore(fs.default.readFileSync(filePath, "utf-8"));
	} catch (err) {
		require_logger.logger.debug("[OpenClaw Device Auth] Failed to read device auth store", {
			err,
			filePath
		});
		return;
	}
}
function loadOpenClawDeviceAuthToken(params) {
	const store = readDeviceAuthStore(params.filePath || getDefaultOpenClawDeviceAuthPath());
	if (!store || store.deviceId !== params.deviceId) return;
	const role = params.role.trim();
	const tokenRecord = store.tokens[role];
	const token = tokenRecord?.token.trim();
	return token ? {
		...tokenRecord,
		token
	} : void 0;
}
function storeOpenClawDeviceAuthToken(params) {
	const token = params.token.trim();
	const role = params.role.trim();
	if (!token || !role) return;
	const authPath = params.filePath || getDefaultOpenClawDeviceAuthPath();
	const existing = readDeviceAuthStore(authPath);
	const store = existing && existing.deviceId === params.deviceId ? existing : {
		version: 1,
		deviceId: params.deviceId,
		tokens: {}
	};
	store.tokens[role] = {
		token,
		role,
		scopes: normalizeScopes$1(params.scopes),
		updatedAtMs: Date.now()
	};
	try {
		writeJsonSecure(authPath, store);
	} catch (err) {
		require_logger.logger.warn("[OpenClaw Device Auth] Failed to persist device auth token", {
			err,
			authPath
		});
	}
}
function clearOpenClawDeviceAuthToken(params) {
	const authPath = params.filePath || getDefaultOpenClawDeviceAuthPath();
	const store = readDeviceAuthStore(authPath);
	if (!store || store.deviceId !== params.deviceId) return;
	delete store.tokens[params.role.trim()];
	try {
		writeJsonSecure(authPath, store);
	} catch (err) {
		require_logger.logger.warn("[OpenClaw Device Auth] Failed to clear device auth token", {
			err,
			authPath
		});
	}
}
//#endregion
//#region src/providers/openclaw/shared.ts
const DEFAULT_GATEWAY_PORT = 18789;
const DEFAULT_GATEWAY_HOST = "127.0.0.1";
/**
* Cached config to avoid re-reading the file multiple times during provider init.
*/
let cachedConfig;
let cachedConfigPath;
function resolveConfigPath(env) {
	return env?.OPENCLAW_CONFIG_PATH || require_logger.getEnvString("OPENCLAW_CONFIG_PATH") || path.default.join(os.default.homedir(), ".openclaw", "openclaw.json");
}
function normalizeGatewayUrl(url, transport) {
	const trimmed = url.trim();
	if (!trimmed) return;
	if (transport === "http") {
		if (trimmed.startsWith("wss://")) return `https://${trimmed.slice(6)}`;
		if (trimmed.startsWith("ws://")) return `http://${trimmed.slice(5)}`;
		return trimmed;
	}
	if (trimmed.startsWith("https://")) return `wss://${trimmed.slice(8)}`;
	if (trimmed.startsWith("http://")) return `ws://${trimmed.slice(7)}`;
	return trimmed;
}
function resolveGatewayHost(gatewayConfig) {
	const bind = gatewayConfig?.bind?.trim();
	const customBindHost = gatewayConfig?.customBindHost?.trim();
	if (!bind || bind === "auto" || bind === "loopback" || bind === "lan" || bind === "tailnet" || bind === "0.0.0.0" || bind === "::" || bind === "127.0.0.1" || bind === "localhost" || bind === "::1") return DEFAULT_GATEWAY_HOST;
	if (bind === "custom") {
		if (!customBindHost || customBindHost === "0.0.0.0" || customBindHost === "::" || customBindHost === "127.0.0.1" || customBindHost === "localhost" || customBindHost === "::1") return DEFAULT_GATEWAY_HOST;
		return customBindHost;
	}
	return bind;
}
function buildLocalGatewayUrl(gatewayConfig, transport, portOverride) {
	const scheme = transport === "ws" ? gatewayConfig?.tls?.enabled ? "wss" : "ws" : gatewayConfig?.tls?.enabled ? "https" : "http";
	const port = portOverride ?? gatewayConfig?.port ?? 18789;
	return `${scheme}://${resolveGatewayHost(gatewayConfig)}:${port}`;
}
function resolveGatewayUrlFromConfig(openclawConfig, transport, portOverride) {
	const gatewayConfig = openclawConfig?.gateway;
	if (!gatewayConfig) return;
	if (gatewayConfig.mode === "remote") {
		const remoteUrl = normalizeGatewayUrl(gatewayConfig.remote?.url ?? "", transport);
		if (remoteUrl) return remoteUrl;
	}
	return buildLocalGatewayUrl(gatewayConfig, transport, portOverride);
}
function resolveGatewayPortOverride(env) {
	const trimmedPort = (env?.OPENCLAW_GATEWAY_PORT || require_logger.getEnvString("OPENCLAW_GATEWAY_PORT"))?.trim();
	if (!trimmedPort || !/^\d+$/.test(trimmedPort)) return;
	const parsedPort = Number(trimmedPort);
	return Number.isInteger(parsedPort) && parsedPort > 0 && parsedPort <= 65535 ? parsedPort : void 0;
}
function toAuthSecret(kind, value) {
	if (typeof value !== "string") return;
	const trimmed = value?.trim();
	return trimmed ? {
		kind,
		value: trimmed
	} : void 0;
}
function resolveAuthSecretFromConfig(openclawConfig) {
	const gatewayConfig = openclawConfig?.gateway;
	const authMode = gatewayConfig?.auth?.mode?.trim();
	const preferRemoteCredentials = gatewayConfig?.mode === "remote";
	const localToken = toAuthSecret("token", gatewayConfig?.auth?.token);
	const localPassword = toAuthSecret("password", gatewayConfig?.auth?.password);
	const remoteToken = toAuthSecret("token", gatewayConfig?.remote?.token);
	const remotePassword = toAuthSecret("password", gatewayConfig?.remote?.password);
	if (preferRemoteCredentials) {
		if (authMode === "password") return remotePassword || localPassword || remoteToken || localToken;
		if (authMode === "token") return remoteToken || localToken || remotePassword || localPassword;
		return remoteToken || remotePassword || localToken || localPassword;
	}
	if (authMode === "password") return localPassword || remotePassword || localToken || remoteToken;
	if (authMode === "token") return localToken || remoteToken || localPassword || remotePassword;
	return localToken || localPassword || remoteToken || remotePassword;
}
/**
* Read and parse the active OpenClaw configuration file.
* Results are cached based on file modification time.
* Returns undefined if the file doesn't exist or can't be parsed.
*/
function readOpenClawConfig(env) {
	const configPath = resolveConfigPath(env);
	try {
		if (!fs.default.existsSync(configPath)) return;
		const mtime = fs.default.statSync(configPath).mtimeMs;
		if (cachedConfig && cachedConfigPath === configPath && cachedConfig.mtime === mtime) return cachedConfig.config;
		const raw = fs.default.readFileSync(configPath, "utf-8");
		const config = json5.default.parse(raw);
		cachedConfig = {
			config,
			mtime
		};
		cachedConfigPath = configPath;
		return config;
	} catch (err) {
		require_logger.logger.warn(`Failed to read OpenClaw config at ${configPath}`, { err });
		return;
	}
}
/**
* Auto-detect the OpenClaw gateway URL from config, env overrides, or the active config file.
*/
function resolveGatewayUrl(config, env) {
	return resolveGatewayTransportUrl(config, env, "http");
}
function resolveGatewayWsUrl(config, env) {
	return resolveGatewayTransportUrl(config, env, "ws");
}
function resolveGatewayTransportUrl(config, env, transport) {
	const configUrl = config?.gateway_url?.trim();
	if (configUrl) return normalizeGatewayUrl(configUrl, transport) || configUrl;
	const trimmedEnvUrl = (env?.OPENCLAW_GATEWAY_URL || require_logger.getEnvString("OPENCLAW_GATEWAY_URL") || env?.CLAWDBOT_GATEWAY_URL || require_logger.getEnvString("CLAWDBOT_GATEWAY_URL"))?.trim();
	if (trimmedEnvUrl) return normalizeGatewayUrl(trimmedEnvUrl, transport) || trimmedEnvUrl;
	const portOverride = resolveGatewayPortOverride(env);
	const resolvedUrl = resolveGatewayUrlFromConfig(readOpenClawConfig(env), transport, portOverride);
	if (resolvedUrl) return resolvedUrl;
	return `${transport === "ws" ? "ws" : "http"}://${DEFAULT_GATEWAY_HOST}:${portOverride ?? 18789}`;
}
function resolveAuthSecret(config, env) {
	if (config?.auth_token) return {
		kind: "token",
		value: config.auth_token
	};
	if (config?.auth_password) return {
		kind: "password",
		value: config.auth_password
	};
	const envToken = env?.OPENCLAW_GATEWAY_TOKEN || require_logger.getEnvString("OPENCLAW_GATEWAY_TOKEN") || env?.CLAWDBOT_GATEWAY_TOKEN || require_logger.getEnvString("CLAWDBOT_GATEWAY_TOKEN");
	if (envToken) return {
		kind: "token",
		value: envToken
	};
	const envPassword = env?.OPENCLAW_GATEWAY_PASSWORD || require_logger.getEnvString("OPENCLAW_GATEWAY_PASSWORD") || env?.CLAWDBOT_GATEWAY_PASSWORD || require_logger.getEnvString("CLAWDBOT_GATEWAY_PASSWORD");
	if (envPassword) return {
		kind: "password",
		value: envPassword
	};
	return resolveAuthSecretFromConfig(readOpenClawConfig(env));
}
/**
* Auto-detect the OpenClaw gateway bearer secret from config, env overrides, or the active
* config file. OpenClaw accepts either a token or password as the HTTP bearer secret.
*/
function resolveAuthToken(config, env) {
	return resolveAuthSecret(config, env)?.value;
}
/**
* Build the canonical OpenClaw model id for OpenAI-compatible endpoints.
*/
function buildOpenClawModelName(agentId) {
	const trimmedAgentId = agentId.trim();
	if (!trimmedAgentId || trimmedAgentId === "default" || trimmedAgentId === "openclaw") return "openclaw/default";
	if (trimmedAgentId.startsWith("openclaw/")) {
		const targetAgentId = trimmedAgentId.slice(9).trim();
		return targetAgentId ? `openclaw/${targetAgentId}` : "openclaw/default";
	}
	if (trimmedAgentId.startsWith("openclaw:")) {
		const targetAgentId = trimmedAgentId.slice(9).trim();
		return targetAgentId ? `openclaw/${targetAgentId}` : "openclaw/default";
	}
	if (trimmedAgentId.startsWith("agent:")) {
		const targetAgentId = trimmedAgentId.slice(6).trim();
		return targetAgentId ? `openclaw/${targetAgentId}` : "openclaw/default";
	}
	return `openclaw/${trimmedAgentId}`;
}
function normalizeHeaderValue(value) {
	return value?.trim() || void 0;
}
/**
* Build OpenClaw request context headers shared by HTTP-compatible endpoints.
*/
function buildOpenClawContextHeaders(config) {
	const headers = {};
	const backendModel = normalizeHeaderValue(config?.backend_model || config?.model_override);
	const messageChannel = normalizeHeaderValue(config?.message_channel);
	const accountId = normalizeHeaderValue(config?.account_id);
	const scopes = config?.scopes?.map((scope) => scope.trim()).filter(Boolean).join(",");
	if (backendModel) headers["x-openclaw-model"] = backendModel;
	if (messageChannel) headers["x-openclaw-message-channel"] = messageChannel;
	if (accountId) headers["x-openclaw-account-id"] = accountId;
	if (scopes) headers["x-openclaw-scopes"] = scopes;
	return headers;
}
function resolveOpenClawBillingModelName(config) {
	const backendModel = normalizeHeaderValue(config?.backend_model || config?.model_override);
	if (!backendModel) return;
	return backendModel.startsWith("openai/") ? backendModel.slice(7) : backendModel;
}
/**
* Build common OpenClaw headers for agent-id, session-key, and request context.
* Note: thinking_level is only supported by the WS Agent provider and is
* passed as an RPC param there, not as an HTTP header.
*/
function buildOpenClawHeaders(agentId, config) {
	const headers = { "x-openclaw-agent-id": agentId };
	if (config?.session_key) headers["x-openclaw-session-key"] = config.session_key;
	return {
		...headers,
		...buildOpenClawContextHeaders(config)
	};
}
/**
* Build provider options for OpenAI-compatible OpenClaw providers (chat, responses).
* Resolves gateway URL, auth token, and merges OpenClaw-specific headers.
*/
function buildOpenClawProviderOptions(agentId, providerOptions) {
	const config = providerOptions.config || {};
	const env = providerOptions.env;
	const gatewayUrl = resolveGatewayUrl(config, env);
	const authToken = resolveAuthToken(config, env);
	return {
		...providerOptions,
		config: {
			...config,
			apiBaseUrl: `${gatewayUrl}/v1`,
			...authToken && { apiKey: authToken },
			apiKeyRequired: false,
			headers: {
				...config.headers,
				...buildOpenClawHeaders(agentId, config)
			}
		}
	};
}
//#endregion
//#region src/providers/openclaw/agent.ts
const MIN_OPENCLAW_PROTOCOL_VERSION = 3;
const MAX_OPENCLAW_PROTOCOL_VERSION = 4;
const CLIENT_ID = "gateway-client";
const CLIENT_MODE = "cli";
const CLIENT_ROLE = "operator";
const DEFAULT_SCOPES = ["operator.read", "operator.write"];
function normalizeScopes(scopes) {
	const seen = /* @__PURE__ */ new Set();
	const normalized = [];
	for (const scope of scopes || []) {
		const trimmed = scope.trim();
		if (trimmed && !seen.has(trimmed)) {
			seen.add(trimmed);
			normalized.push(trimmed);
		}
	}
	return normalized;
}
function getStringArray(value) {
	if (!Array.isArray(value)) return;
	const strings = value.filter((item) => typeof item === "string");
	return strings.length > 0 ? strings : void 0;
}
function stripRetryMarker(result) {
	const { retryWithDeviceToken: _retryWithDeviceToken, ...providerResponse } = result;
	return providerResponse;
}
function buildOpenClawAgentSessionKey(agentId, sessionKey) {
	const trimmedSessionKey = sessionKey.trim();
	if (!trimmedSessionKey || trimmedSessionKey.toLowerCase().startsWith("agent:")) return trimmedSessionKey;
	const trimmedAgentId = agentId.trim();
	if (!trimmedAgentId || trimmedAgentId.toLowerCase() === "main") return trimmedSessionKey;
	return `agent:${trimmedAgentId}:${trimmedSessionKey}`;
}
/**
* OpenClaw WebSocket Agent Provider
*
* Custom provider that uses the native OpenClaw WS RPC protocol to invoke agents.
* Supports full streaming with event accumulation.
*
* Protocol flow:
*   1. Open WS connection to gateway
*   2. Receive connect.challenge event → send signed connect request
*   3. Receive connect response → persist device token and send agent request
*   4. Receive agent accepted response → send agent.wait
*   5. Accumulate streaming "agent" events (assistant text/delta, lifecycle errors, error streams)
*   6. Resolve on agent.wait response
*
* Usage:
*   openclaw:agent           - default agent (main)
*   openclaw:agent:main      - explicit agent ID
*   openclaw:agent:my-agent  - custom agent ID
*/
var OpenClawAgentProvider = class {
	agentId;
	gatewayUrl;
	authKind;
	authSecret;
	openclawConfig;
	timeoutMs;
	scopes;
	hasExplicitScopes;
	activeConnections = /* @__PURE__ */ new Set();
	constructor(agentId, providerOptions = {}) {
		this.agentId = agentId;
		this.openclawConfig = providerOptions.config || {};
		const env = providerOptions.env;
		this.gatewayUrl = resolveGatewayWsUrl(this.openclawConfig, env);
		const authSecret = resolveAuthSecret(this.openclawConfig, env);
		this.authKind = authSecret?.kind;
		this.authSecret = authSecret?.value;
		this.timeoutMs = this.openclawConfig.timeoutMs ?? require_fetch.getRequestTimeoutMs();
		this.scopes = normalizeScopes(this.openclawConfig.scopes);
		this.hasExplicitScopes = this.scopes.length > 0;
		if (!this.hasExplicitScopes) this.scopes = [...DEFAULT_SCOPES];
	}
	id() {
		return `openclaw:agent:${this.agentId}`;
	}
	toString() {
		return `[OpenClaw Agent Provider ${this.agentId}]`;
	}
	toJSON() {
		return { provider: this.id() };
	}
	async cleanup() {
		for (const ws$1 of this.activeConnections) ws$1.close();
		this.activeConnections.clear();
	}
	async callApi(prompt) {
		const sessionKey = buildOpenClawAgentSessionKey(this.agentId, this.openclawConfig.session_key || `promptfoo-${crypto.default.randomUUID()}`);
		const firstResult = await this.callApiOnce(prompt, sessionKey);
		if (firstResult.retryWithDeviceToken) {
			const retryDeviceToken = this.resolveDeviceTokenForRetry();
			if (retryDeviceToken) return stripRetryMarker(await this.callApiOnce(prompt, sessionKey, retryDeviceToken));
		}
		return stripRetryMarker(firstResult);
	}
	callApiOnce(prompt, sessionKey, retryDeviceToken) {
		return new Promise((resolve) => {
			const wsHeaders = this.buildWebSocketHeaders();
			const ws$2 = wsHeaders ? new ws.default(this.gatewayUrl, { headers: wsHeaders }) : new ws.default(this.gatewayUrl);
			this.activeConnections.add(ws$2);
			let resolved = false;
			let timeout;
			const finish = (result, closeSocket = true) => {
				if (resolved) return;
				resolved = true;
				clearTimeout(timeout);
				this.activeConnections.delete(ws$2);
				if (closeSocket) ws$2.close();
				resolve(result);
			};
			const state = {
				agentRequestId: crypto.default.randomUUID(),
				waitRequestId: crypto.default.randomUUID(),
				idempotencyKey: crypto.default.randomUUID(),
				lastText: "",
				lastError: "",
				connected: false,
				prompt,
				sessionKey,
				ws: ws$2,
				finish,
				retryDeviceToken
			};
			timeout = setTimeout(() => {
				finish({ error: `OpenClaw agent request timed out after ${this.timeoutMs}ms` });
			}, this.timeoutMs);
			ws$2.on("error", (err) => {
				finish({ error: `OpenClaw WebSocket error: ${err.message}` });
			});
			ws$2.on("close", () => {
				this.activeConnections.delete(ws$2);
				if (!resolved) finish({ error: "OpenClaw WebSocket connection closed unexpectedly" }, false);
			});
			ws$2.on("message", (data) => {
				const frame = this.parseFrame(data);
				if (frame) this.handleFrame(frame, state);
			});
		});
	}
	parseFrame(data) {
		try {
			const frame = JSON.parse(data.toString());
			require_logger.logger.debug("[OpenClaw Agent] Frame received", {
				type: frame.type,
				event: frame.event,
				id: frame.id,
				ok: frame.ok,
				payloadStatus: frame.payload && typeof frame.payload.status === "string" ? frame.payload.status : void 0,
				payloadStream: frame.payload && typeof frame.payload.stream === "string" ? frame.payload.stream : void 0
			});
			return frame;
		} catch {
			require_logger.logger.debug("[OpenClaw Agent] Failed to parse WS frame");
			return;
		}
	}
	handleFrame(frame, state) {
		try {
			if (frame.type === "event" && frame.event === "connect.challenge") {
				this.handleConnectChallenge(frame, state);
				return;
			}
			if (frame.type === "res" && !state.connected) {
				this.handleConnectResponse(frame, state);
				return;
			}
			if (frame.type === "res" && frame.id === state.agentRequestId) {
				this.handleAgentAccepted(frame, state);
				return;
			}
			if (frame.type === "event" && frame.event === "agent") {
				this.handleAgentEvent(frame, state);
				return;
			}
			if (frame.type === "res" && frame.id === state.waitRequestId) this.handleAgentWaitResponse(frame, state);
		} catch (err) {
			state.finish({ error: `OpenClaw WebSocket error: ${err instanceof Error ? err.message : String(err)}` });
		}
	}
	handleConnectChallenge(frame, state) {
		state.connectAuthState = this.buildConnectAuthState(state.retryDeviceToken);
		this.sendJson(state.ws, {
			type: "req",
			id: crypto.default.randomUUID(),
			method: "connect",
			params: this.buildConnectParams(frame, state.connectAuthState)
		});
	}
	handleConnectResponse(frame, state) {
		if (!frame.ok) {
			this.clearStoredDeviceTokenOnFailure(state.connectAuthState, frame.error);
			state.finish({
				error: this.formatConnectError(frame.error),
				retryWithDeviceToken: !state.retryDeviceToken && this.shouldRetryConnectWithDeviceToken(frame.error)
			});
			return;
		}
		state.connected = true;
		this.storeDeviceTokenFromHello(frame.payload, state.connectAuthState);
		this.sendJson(state.ws, {
			type: "req",
			id: state.agentRequestId,
			method: "agent",
			params: this.buildAgentRequestParams(state)
		});
	}
	buildAgentRequestParams(state) {
		return {
			message: state.prompt,
			agentId: this.agentId,
			idempotencyKey: state.idempotencyKey,
			sessionKey: state.sessionKey,
			...this.openclawConfig.message_channel && { channel: this.openclawConfig.message_channel },
			...this.openclawConfig.account_id && { accountId: this.openclawConfig.account_id },
			...this.openclawConfig.thinking_level && { thinking: this.openclawConfig.thinking_level },
			...this.openclawConfig.extra_system_prompt && { extraSystemPrompt: this.openclawConfig.extra_system_prompt }
		};
	}
	handleAgentAccepted(frame, state) {
		if (!frame.ok) {
			state.finish({ error: `OpenClaw agent error: ${frame.error?.message || "unknown error"}` });
			return;
		}
		const payload = frame.payload;
		state.runId = typeof payload?.runId === "string" && payload.runId.trim() ? payload.runId : void 0;
		if (!state.runId) {
			require_logger.logger.warn("[OpenClaw Agent] Missing runId in accepted response", {
				agentId: this.agentId,
				payload
			});
			state.finish({ error: "OpenClaw agent error: gateway accepted request without a runId" });
			return;
		}
		this.sendJson(state.ws, {
			type: "req",
			id: state.waitRequestId,
			method: "agent.wait",
			params: {
				runId: state.runId,
				timeoutMs: this.timeoutMs
			}
		});
	}
	handleAgentEvent(frame, state) {
		const payload = frame.payload;
		if (payload?.runId && state.runId && payload.runId !== state.runId) return;
		if (payload?.stream === "lifecycle" && payload.data?.phase === "error") {
			state.lastError = payload.data.error || "OpenClaw agent lifecycle error";
			return;
		}
		if (payload?.stream === "error") {
			state.lastError = payload.data?.error || payload.data?.reason || "OpenClaw agent stream error";
			return;
		}
		if (payload?.stream !== "assistant") return;
		if (typeof payload?.data?.text === "string") {
			state.lastText = payload.data.text;
			state.lastError = "";
			return;
		}
		if (typeof payload?.data?.delta === "string") {
			state.lastText += payload.data.delta;
			state.lastError = "";
		}
	}
	handleAgentWaitResponse(frame, state) {
		if (!frame.ok) {
			state.finish({ error: `OpenClaw agent error: ${frame.error?.message || "unknown error"}` });
			return;
		}
		const payload = frame.payload;
		if (payload?.status === "error") {
			state.finish({ error: `OpenClaw agent error: ${payload.error || "unknown error"}` });
			return;
		}
		if (payload?.status === "timeout") {
			state.finish({ error: `OpenClaw agent error: timed out waiting for run ${state.runId}` });
			return;
		}
		const finalText = typeof payload?.output === "string" ? payload.output : typeof payload?.text === "string" ? payload.text : void 0;
		if (state.lastText || finalText) {
			state.finish({ output: state.lastText || finalText });
			return;
		}
		if (state.lastError) {
			state.finish({ error: `OpenClaw agent error: ${state.lastError}` });
			return;
		}
		state.finish({ output: "No output from agent" });
	}
	sendJson(ws$3, payload) {
		ws$3.send(JSON.stringify(payload));
	}
	buildWebSocketHeaders() {
		const headers = {
			...this.openclawConfig.headers || {},
			...this.openclawConfig.ws_headers || {}
		};
		return Object.keys(headers).length > 0 ? headers : void 0;
	}
	buildConnectAuthState(retryDeviceToken) {
		const deviceIdentity = this.loadDeviceIdentity();
		const storedOrConfiguredDeviceToken = deviceIdentity ? this.resolveDeviceTokenForConnect(deviceIdentity) : void 0;
		const deviceToken = retryDeviceToken || storedOrConfiguredDeviceToken;
		if (retryDeviceToken) return {
			auth: { deviceToken: retryDeviceToken.token },
			deviceIdentity,
			deviceTokenSource: retryDeviceToken.source,
			kind: "deviceToken",
			scopes: this.resolveScopesForDeviceToken(retryDeviceToken),
			signatureToken: retryDeviceToken.token
		};
		if (this.authSecret && this.authKind) return {
			auth: this.authKind === "password" ? { password: this.authSecret } : { token: this.authSecret },
			deviceIdentity,
			kind: this.authKind,
			scopes: this.scopes,
			signatureToken: this.authKind === "token" ? this.authSecret : null
		};
		if (deviceToken) return {
			auth: { deviceToken: deviceToken.token },
			deviceIdentity,
			deviceTokenSource: deviceToken.source,
			kind: "deviceToken",
			scopes: this.resolveScopesForDeviceToken(deviceToken),
			signatureToken: deviceToken.token
		};
		return {
			deviceIdentity,
			kind: "none",
			scopes: this.scopes,
			signatureToken: null
		};
	}
	buildConnectParams(frame, authState) {
		const nonce = this.extractChallengeNonce(frame);
		const params = {
			minProtocol: MIN_OPENCLAW_PROTOCOL_VERSION,
			maxProtocol: MAX_OPENCLAW_PROTOCOL_VERSION,
			client: {
				id: CLIENT_ID,
				displayName: "promptfoo",
				version: require_fetch.VERSION,
				platform: process.platform,
				...this.openclawConfig.device_family && { deviceFamily: this.openclawConfig.device_family },
				mode: CLIENT_MODE
			},
			role: CLIENT_ROLE,
			scopes: authState.scopes,
			caps: [],
			commands: [],
			permissions: {},
			...authState.auth && { auth: authState.auth }
		};
		const device = this.buildSignedDevice(authState, nonce);
		if (device) params.device = device;
		return params;
	}
	buildSignedDevice(authState, nonce) {
		if (!authState.deviceIdentity || this.openclawConfig.disable_device_auth) return;
		try {
			return buildSignedOpenClawDevice({
				identity: authState.deviceIdentity,
				clientId: CLIENT_ID,
				clientMode: CLIENT_MODE,
				role: CLIENT_ROLE,
				scopes: authState.scopes,
				nonce,
				token: authState.signatureToken,
				platform: process.platform,
				deviceFamily: this.openclawConfig.device_family
			});
		} catch (err) {
			require_logger.logger.warn("[OpenClaw Agent] Failed to sign device identity; connecting without device auth", { err });
			return;
		}
	}
	loadDeviceIdentity() {
		if (this.openclawConfig.disable_device_auth) return;
		try {
			return loadOrCreateOpenClawDeviceIdentity(this.openclawConfig.device_identity_path);
		} catch (err) {
			require_logger.logger.warn("[OpenClaw Agent] Failed to load device identity", { err });
			return;
		}
	}
	resolveDeviceTokenForConnect(deviceIdentity) {
		const configDeviceToken = this.openclawConfig.device_token?.trim();
		if (configDeviceToken) return {
			token: configDeviceToken,
			scopes: this.scopes,
			source: "config"
		};
		const storedDeviceToken = loadOpenClawDeviceAuthToken({
			deviceId: deviceIdentity.deviceId,
			role: CLIENT_ROLE,
			filePath: this.openclawConfig.device_auth_path
		});
		if (!storedDeviceToken?.token) return;
		return {
			token: storedDeviceToken.token,
			scopes: this.hasExplicitScopes ? this.scopes : storedDeviceToken.scopes,
			source: "stored"
		};
	}
	resolveDeviceTokenForRetry() {
		const identity = this.loadDeviceIdentity();
		if (!identity) return;
		const deviceToken = this.resolveDeviceTokenForConnect(identity);
		return deviceToken ? {
			...deviceToken,
			source: "retry"
		} : void 0;
	}
	resolveScopesForDeviceToken(deviceToken) {
		if (this.hasExplicitScopes) return this.scopes;
		return normalizeScopes([...this.scopes, ...deviceToken.scopes || []]);
	}
	storeDeviceTokenFromHello(payload, authState) {
		if (!authState?.deviceIdentity) return;
		const authPayload = payload?.auth && typeof payload.auth === "object" && !Array.isArray(payload.auth) ? payload.auth : void 0;
		const deviceToken = typeof authPayload?.deviceToken === "string" ? authPayload.deviceToken : "";
		if (!deviceToken.trim()) return;
		const scopes = getStringArray(authPayload?.scopes) || authState.scopes;
		const role = typeof authPayload?.role === "string" && authPayload.role.trim() ? authPayload.role : CLIENT_ROLE;
		storeOpenClawDeviceAuthToken({
			deviceId: authState.deviceIdentity.deviceId,
			role,
			token: deviceToken,
			scopes,
			filePath: this.openclawConfig.device_auth_path
		});
	}
	clearStoredDeviceTokenOnFailure(authState, error) {
		if (!authState?.deviceIdentity || authState.kind !== "deviceToken" || authState.deviceTokenSource === "config") return;
		const detailCode = this.getConnectErrorDetailCode(error);
		const topLevelCode = error?.code;
		if (detailCode !== "AUTH_DEVICE_TOKEN_MISMATCH" && topLevelCode !== "AUTH_DEVICE_TOKEN_MISMATCH") return;
		clearOpenClawDeviceAuthToken({
			deviceId: authState.deviceIdentity.deviceId,
			role: CLIENT_ROLE,
			filePath: this.openclawConfig.device_auth_path
		});
	}
	extractChallengeNonce(frame) {
		const nonce = frame.payload?.nonce;
		return typeof nonce === "string" ? nonce : "";
	}
	getConnectErrorDetailCode(error) {
		return error?.details?.code || error?.code;
	}
	shouldRetryConnectWithDeviceToken(error) {
		const detailCode = this.getConnectErrorDetailCode(error);
		const recommendedNextStep = error?.details?.recommendedNextStep;
		return detailCode === "AUTH_TOKEN_MISMATCH" || error?.details?.canRetryWithDeviceToken === true || recommendedNextStep === "retry_with_device_token";
	}
	formatConnectError(error) {
		const message = error?.message || "unknown error";
		const detailCode = this.getConnectErrorDetailCode(error);
		return detailCode && !message.includes(detailCode) ? `OpenClaw connect failed: ${message} (${detailCode})` : `OpenClaw connect failed: ${message}`;
	}
};
//#endregion
//#region src/providers/openclaw/chat.ts
/**
* OpenClaw chat provider extends OpenAI chat completion provider.
*
* OpenClaw exposes an OpenAI-compatible HTTP API at /v1/chat/completions.
* This provider auto-detects gateway URL and bearer auth from:
*   1. Explicit config (gateway_url, auth_token, auth_password)
*   2. Environment variables (OPENCLAW_GATEWAY_URL, OPENCLAW_GATEWAY_TOKEN, OPENCLAW_GATEWAY_PASSWORD)
*   3. The active OpenClaw config file (OPENCLAW_CONFIG_PATH or ~/.openclaw/openclaw.json),
*      including gateway.remote.url and gateway.tls.enabled
*
* Usage:
*   openclaw              - default agent (main)
*   openclaw:main         - specific agent
*   openclaw:coding-agent - named agent
*/
var OpenClawChatProvider = class extends require_chat.OpenAiChatCompletionProvider {
	agentId;
	constructor(agentId, providerOptions = {}) {
		super(buildOpenClawModelName(agentId), buildOpenClawProviderOptions(agentId, providerOptions));
		this.agentId = agentId;
	}
	id() {
		return `openclaw:${this.agentId}`;
	}
	toString() {
		return `[OpenClaw Provider ${this.agentId}]`;
	}
	getApiUrlDefault() {
		return `http://${DEFAULT_GATEWAY_HOST}:${DEFAULT_GATEWAY_PORT}/v1`;
	}
	getApiKey() {
		return this.config.apiKey;
	}
	getApiUrl() {
		return this.config.apiBaseUrl || this.getApiUrlDefault();
	}
	getBillingModelName(config) {
		return resolveOpenClawBillingModelName(config) || this.modelName;
	}
};
//#endregion
//#region src/providers/openclaw/embedding.ts
/**
* OpenClaw embedding provider extends the OpenAI-compatible embeddings provider.
*
* The OpenClaw gateway accepts agent-target model ids at /v1/embeddings and
* optionally accepts x-openclaw-model as the backend embedding-model override.
*/
var OpenClawEmbeddingProvider = class extends require_embedding.OpenAiEmbeddingProvider {
	agentId;
	constructor(agentId, providerOptions = {}) {
		super(buildOpenClawModelName(agentId), buildOpenClawProviderOptions(agentId, providerOptions));
		this.agentId = agentId;
	}
	id() {
		return `openclaw:embedding:${this.agentId}`;
	}
	toString() {
		return `[OpenClaw Embedding Provider ${this.agentId}]`;
	}
	getApiUrlDefault() {
		return `http://${DEFAULT_GATEWAY_HOST}:${DEFAULT_GATEWAY_PORT}/v1`;
	}
	getApiKey() {
		return this.config.apiKey;
	}
	getApiUrl() {
		return this.config.apiBaseUrl || this.getApiUrlDefault();
	}
	getBillingModelName() {
		return resolveOpenClawBillingModelName(this.config) || this.modelName;
	}
};
//#endregion
//#region src/providers/openclaw/responses.ts
function inferHiddenCachedInputTokensFromOpenClawUsage(usage) {
	const inputTokens = usage?.input_tokens;
	const outputTokens = usage?.output_tokens;
	const totalTokens = usage?.total_tokens;
	if (typeof inputTokens !== "number" || typeof outputTokens !== "number" || typeof totalTokens !== "number") return 0;
	return Math.max(totalTokens - inputTokens - outputTokens, 0);
}
/**
* OpenClaw Responses API Provider
*
* Extends OpenAI Responses API provider with OpenClaw-specific configuration.
* Routes through the OpenClaw gateway's /v1/responses endpoint.
*
* Requires `gateway.http.endpoints.responses.enabled=true` in OpenClaw config.
*
* Usage:
*   openclaw:responses       - default agent (main)
*   openclaw:responses:main  - explicit agent ID
*   openclaw:responses:X     - custom agent ID
*/
var OpenClawResponsesProvider = class extends require_responses.OpenAiResponsesProvider {
	agentId;
	constructor(agentId, providerOptions = {}) {
		super(buildOpenClawModelName(agentId), buildOpenClawProviderOptions(agentId, providerOptions));
		this.agentId = agentId;
	}
	id() {
		return `openclaw:responses:${this.agentId}`;
	}
	toString() {
		return `[OpenClaw Responses Provider ${this.agentId}]`;
	}
	getApiUrlDefault() {
		return `http://${DEFAULT_GATEWAY_HOST}:${DEFAULT_GATEWAY_PORT}/v1`;
	}
	getApiKey() {
		return this.config.apiKey;
	}
	getApiUrl() {
		return this.config.apiBaseUrl || this.getApiUrlDefault();
	}
	getBillingModelName(config) {
		return resolveOpenClawBillingModelName(config) || this.modelName;
	}
	getBillingUsage(data, _config) {
		const usage = data.usage;
		const inferredCachedTokens = inferHiddenCachedInputTokensFromOpenClawUsage(usage);
		if (inferredCachedTokens <= 0) return usage;
		return {
			...usage,
			input_tokens: (usage?.input_tokens ?? 0) + inferredCachedTokens,
			input_tokens_details: {
				...usage?.input_tokens_details,
				cached_tokens: inferredCachedTokens
			}
		};
	}
	applyBilling(result, data, config, cached) {
		const usage = data.usage;
		const inferredCachedTokens = inferHiddenCachedInputTokensFromOpenClawUsage(usage);
		if (inferredCachedTokens <= 0) return super.applyBilling(result, data, config, cached);
		const adjustedResult = {
			...result,
			tokenUsage: result.tokenUsage ? {
				...result.tokenUsage,
				prompt: (result.tokenUsage.prompt ?? 0) + inferredCachedTokens,
				completionDetails: {
					...result.tokenUsage.completionDetails,
					cacheReadInputTokens: inferredCachedTokens
				}
			} : result.tokenUsage
		};
		return super.applyBilling(adjustedResult, data, config, cached);
	}
	async getOpenAiBody(prompt, context, callApiOptions) {
		const result = await super.getOpenAiBody(prompt, context, callApiOptions);
		if ("text" in result.body) delete result.body.text;
		return result;
	}
};
//#endregion
//#region src/providers/openclaw/tools.ts
/**
* OpenClaw Tool Invoke Provider
*
* Simple HTTP provider for direct tool invocation via POST /tools/invoke.
* The tool name is extracted from the provider path:
* openclaw:tools:sessions_list → tool="sessions_list"
*
* The prompt is parsed as JSON for tool arguments. If it's not valid JSON,
* it's passed as a single `input` argument.
*
* Usage:
*   openclaw:tools:sessions_list - invoke the sessions_list tool
*   openclaw:tools:session_status - invoke the session_status tool
*
* Optional config:
*   action  - tool sub-action, forwarded as body.action
*   dry_run - dry-run hint, forwarded as body.dryRun
*/
var OpenClawToolInvokeProvider = class {
	toolName;
	gatewayUrl;
	authToken;
	openclawConfig;
	timeoutMs;
	constructor(toolName, providerOptions = {}) {
		this.toolName = toolName;
		this.openclawConfig = providerOptions.config || {};
		const env = providerOptions.env;
		this.gatewayUrl = resolveGatewayUrl(this.openclawConfig, env);
		this.authToken = resolveAuthToken(this.openclawConfig, env);
		this.timeoutMs = this.openclawConfig.timeoutMs ?? require_fetch.getRequestTimeoutMs();
	}
	id() {
		return `openclaw:tools:${this.toolName}`;
	}
	toString() {
		return `[OpenClaw Tool Provider ${this.toolName}]`;
	}
	toJSON() {
		return { provider: this.id() };
	}
	async callApi(prompt) {
		let args;
		try {
			args = JSON.parse(prompt);
		} catch {
			args = { input: prompt };
		}
		const url = `${this.gatewayUrl}/tools/invoke`;
		const headers = {
			"Content-Type": "application/json",
			...this.openclawConfig.headers || {},
			...buildOpenClawContextHeaders(this.openclawConfig)
		};
		if (this.authToken) headers["Authorization"] = `Bearer ${this.authToken}`;
		const body = {
			tool: this.toolName,
			...this.openclawConfig.action && { action: this.openclawConfig.action },
			args,
			...typeof this.openclawConfig.dry_run === "boolean" && { dryRun: this.openclawConfig.dry_run },
			...this.openclawConfig.session_key && { sessionKey: this.openclawConfig.session_key }
		};
		require_logger.logger.debug(`[OpenClaw Tool] POST ${url}`, {
			tool: this.toolName,
			args
		});
		try {
			const controller = new AbortController();
			const fetchTimeout = setTimeout(() => controller.abort(), this.timeoutMs);
			const response = await require_fetch.fetchWithProxy(url, {
				method: "POST",
				headers,
				body: JSON.stringify(body),
				signal: controller.signal
			}).finally(() => clearTimeout(fetchTimeout));
			if (!response.ok) {
				const text = await response.text();
				return { error: `OpenClaw tool invoke failed (${response.status}): ${text}` };
			}
			const data = await response.json();
			if (data.ok) return { output: typeof data.result === "string" ? data.result : JSON.stringify(data.result) };
			if (typeof data.error === "string") return { error: data.error };
			return { error: data.error?.message || data.error?.type || data.error?.code || "Unknown tool error" };
		} catch (err) {
			return { error: `OpenClaw tool invoke error: ${err instanceof Error ? err.message : String(err)}` };
		}
	}
};
//#endregion
//#region src/providers/openclaw/index.ts
/**
* Create an OpenClaw provider from a provider path string.
*
* Routing:
*   openclaw                → OpenClawChatProvider('main')
*   openclaw:main           → OpenClawChatProvider('main')
*   openclaw:my-agent       → OpenClawChatProvider('my-agent')
*   openclaw:responses      → OpenClawResponsesProvider('main')
*   openclaw:responses:X    → OpenClawResponsesProvider('X')
*   openclaw:embedding      → OpenClawEmbeddingProvider('main')
*   openclaw:embedding:X    → OpenClawEmbeddingProvider('X')
*   openclaw:embeddings     → OpenClawEmbeddingProvider('main')
*   openclaw:embeddings:X   → OpenClawEmbeddingProvider('X')
*   openclaw:agent          → OpenClawAgentProvider('main')
*   openclaw:agent:X        → OpenClawAgentProvider('X')
*   openclaw:tools:sessions_list → OpenClawToolInvokeProvider('sessions_list')
*/
function createOpenClawProvider(providerPath, providerOptions = {}, env) {
	const splits = providerPath.split(":");
	const keyword = splits[1];
	const opts = {
		...providerOptions,
		env
	};
	if (keyword === "responses") return new OpenClawResponsesProvider(splits[2] || "main", opts);
	if (keyword === "embedding" || keyword === "embeddings") return new OpenClawEmbeddingProvider(splits[2] || "main", opts);
	if (keyword === "agent") return new OpenClawAgentProvider(splits[2] || "main", opts);
	if (keyword === "tools") {
		const toolName = splits.slice(2).join(":");
		if (!toolName) throw new Error("OpenClaw tools provider requires a tool name: openclaw:tools:<tool-name>");
		return new OpenClawToolInvokeProvider(toolName, opts);
	}
	return new OpenClawChatProvider(splits.length > 1 ? splits.slice(1).join(":") : "main", opts);
}
//#endregion
exports.createOpenClawProvider = createOpenClawProvider;

//# sourceMappingURL=openclaw-CM7YGvZE.cjs.map