import { computed, onScopeDispose, shallowRef } from "vue";
import { z } from "#compiled/zod/index.js";

//#region src/protocol/routes.ts
const EVE_ROUTE_PREFIX = "/eve/v1";
const EVE_HEALTH_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/health`;
const EVE_INFO_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/info`;
const EVE_CREATE_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session`;
const EVE_CONTINUE_SESSION_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId`;
const EVE_MESSAGE_STREAM_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId/stream`;
const EVE_CANCEL_TURN_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId/cancel`;
const EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/dev/schedules/:scheduleId`;
const EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/dev/runtime-artifacts`;
const EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH = `${EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}/rebuild`;
const EVE_CONNECTION_CALLBACK_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/connections/:name/callback/:token`;
const EVE_CALLBACK_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/callback/:token`;
function createEveMessageStreamRoutePath(sessionId) {
	return `${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(sessionId)}/stream`;
}
function createEveContinueSessionRoutePath(sessionId) {
	return `${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(sessionId)}`;
}
function createEveCancelTurnRoutePath(sessionId) {
	return `${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(sessionId)}/cancel`;
}

//#endregion
//#region src/client/agent-info-error.ts
var AgentInfoResponseError = class extends Error {
	issues;
	constructor(issues = []) {
		const detail = issues.length === 0 ? "" : ` (${issues.join("; ")})`;
		super(`The server returned an unrecognized response from the eve agent info route.${detail}`);
		this.name = "AgentInfoResponseError";
		this.issues = issues;
	}
};

//#endregion
//#region src/internal/http/basic-auth.ts
function encodeBasicCredentials(username, password) {
	const bytes = new TextEncoder().encode(`${username}:${password}`);
	const binaryString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join("");
	return btoa(binaryString);
}

//#endregion
//#region src/client/agent-info-schema.ts
const source = z.object({
	exportName: z.string().optional(),
	logicalPath: z.string(),
	sourceId: z.string().optional(),
	sourceKind: z.string()
});
const entry = source.extend({ name: z.string() });
const modelRouting = z.discriminatedUnion("kind", [z.object({
	kind: z.literal("gateway"),
	target: z.string(),
	byok: z.string().optional()
}), z.object({
	kind: z.literal("external"),
	provider: z.string()
})]);
const modelEndpoint = z.union([
	z.object({
		kind: z.literal("external"),
		provider: z.string()
	}),
	z.object({
		kind: z.literal("gateway"),
		connected: z.literal(true),
		credential: z.enum(["api-key", "oidc"])
	}),
	z.object({
		kind: z.literal("gateway"),
		connected: z.literal(false)
	})
]);
const tool = entry.extend({
	description: z.string(),
	hasAuth: z.boolean(),
	hasExecute: z.boolean(),
	hasModelOutputProjection: z.boolean(),
	hasOutputSchema: z.boolean(),
	inputSchema: z.unknown(),
	origin: z.enum(["authored", "framework"]),
	outputSchema: z.unknown().optional(),
	replacesFrameworkTool: z.boolean(),
	requiresApproval: z.boolean()
});
const frameworkTool = tool.extend({
	disabledByAuthor: z.boolean(),
	replacedByAuthoredTool: z.boolean(),
	status: z.enum([
		"active",
		"disabled",
		"replaced"
	])
});
const dynamicResolver = source.extend({
	eventNames: z.array(z.string()),
	origin: z.enum(["authored", "framework"]),
	slug: z.string()
});
const skill = entry.extend({
	description: z.string(),
	license: z.string().optional(),
	markdown: z.string(),
	metadata: z.record(z.string(), z.string()).optional()
});
const instructions = entry.extend({ markdown: z.string() });
const schedule = entry.extend({
	cron: z.string(),
	hasRun: z.boolean(),
	markdown: z.string().optional()
});
const subagent = entry.extend({
	description: z.string(),
	entryPath: z.string(),
	nodeId: z.string(),
	rootPath: z.string(),
	summary: z.object({
		channels: z.number(),
		connections: z.number(),
		hooks: z.number(),
		instructions: z.boolean(),
		schedules: z.number(),
		skills: z.number(),
		tools: z.number()
	})
});
const channel = entry.extend({
	adapterKind: z.string().optional(),
	method: z.string(),
	origin: z.enum(["authored", "framework"]),
	urlPath: z.string()
});
const frameworkChannel = channel.extend({
	disabledByAuthor: z.boolean(),
	replacedByAuthoredChannel: z.boolean(),
	status: z.enum([
		"active",
		"disabled",
		"replaced"
	])
});
const connection = source.extend({
	connectionName: z.string(),
	description: z.string(),
	hasApproval: z.boolean(),
	hasAuthorization: z.boolean(),
	hasHeaders: z.boolean(),
	protocol: z.string(),
	toolFilter: z.unknown().optional(),
	url: z.string()
});
const hook = source.extend({
	eventNames: z.array(z.string()),
	slug: z.string()
});
const sandbox = source.extend({
	backendKind: z.string().optional(),
	description: z.string().optional(),
	hasBootstrap: z.boolean(),
	hasOnSession: z.boolean(),
	revalidationKey: z.string().optional(),
	sourceHash: z.string().optional()
});
const AgentInfoResultSchema = z.object({
	agent: z.object({
		agentRoot: z.string(),
		appRoot: z.string(),
		configSource: source.optional(),
		description: z.string().optional(),
		model: z.object({
			contextWindowTokens: z.number().optional(),
			id: z.string(),
			providerOptions: z.unknown().optional(),
			reasoning: z.enum([
				"provider-default",
				"none",
				"minimal",
				"low",
				"medium",
				"high",
				"xhigh"
			]).optional().catch(void 0),
			source: source.optional(),
			routing: modelRouting.optional(),
			endpoint: modelEndpoint.optional()
		}),
		name: z.string(),
		outputSchema: z.unknown().optional()
	}),
	capabilities: z.object({ devRoutes: z.boolean() }),
	channels: z.object({
		authored: z.array(channel),
		available: z.array(channel),
		disabledFramework: z.array(z.string()),
		framework: z.array(frameworkChannel)
	}),
	connections: z.array(connection),
	diagnostics: z.object({
		discoveryErrors: z.number(),
		discoveryWarnings: z.number()
	}),
	hooks: z.array(hook),
	instructions: z.object({
		dynamic: z.array(dynamicResolver),
		static: instructions.nullable()
	}),
	kind: z.literal("eve-agent-info"),
	mode: z.enum(["development", "production"]),
	sandbox: sandbox.nullable(),
	schedules: z.array(schedule),
	skills: z.object({
		dynamic: z.array(dynamicResolver),
		static: z.array(skill)
	}),
	subagents: z.object({
		local: z.array(subagent),
		total: z.number()
	}),
	tools: z.object({
		authored: z.array(tool),
		available: z.array(tool),
		disabledFramework: z.array(z.string()),
		dynamic: z.array(dynamicResolver),
		framework: z.array(frameworkTool),
		reserved: z.array(z.string())
	}),
	version: z.literal(1),
	workflow: z.object({
		enabled: z.boolean(),
		toolName: z.string()
	}),
	workspace: z.object({
		resourceRoot: z.unknown(),
		rootEntries: z.array(z.string())
	})
});

//#endregion
//#region src/shared/guards.ts
function isObject(value) {
	return typeof value === "object" && value !== null && !Array.isArray(value);
}

//#endregion
//#region src/client/client-error.ts
var ClientError = class extends Error {
	status;
	body;
	headers;
	constructor(status, body, headers) {
		let message = body || `Server returned ${status}.`;
		try {
			const parsed = JSON.parse(body);
			if (isObject(parsed) && typeof parsed.error === "string") message = parsed.error;
		} catch {}
		super(message);
		this.name = "ClientError";
		this.status = status;
		this.body = body;
		this.headers = Object.freeze(Object.fromEntries(new Headers(headers).entries()));
	}
};

//#endregion
//#region src/shared/errors.ts
function toErrorMessage(error) {
	if (error instanceof Error) return error.message;
	if (typeof error === "string") return error;
	if (error === null || error === void 0) return String(error);
	if (isObject(error)) {
		if (typeof error.message === "string" && error.message.length > 0) return error.message;
		return safeJsonStringify(error);
	}
	return String(error);
}
function toError(raw) {
	if (raw instanceof Error) return raw;
	const error = new Error(toErrorMessage(raw));
	if (!isObject(raw)) return error;
	if (typeof raw.name === "string" && raw.name.length > 0) error.name = raw.name;
	if (typeof raw.stack === "string" && raw.stack.length > 0) error.stack = raw.stack;
	if ("cause" in raw && raw.cause !== void 0 && raw.cause !== raw) error.cause = raw.cause;
	return error;
}
function safeJsonStringify(value) {
	try {
		return JSON.stringify(value) ?? String(value);
	} catch {
		return String(value);
	}
}

//#endregion
//#region src/protocol/message.ts
const EVE_SESSION_ID_HEADER = "x-eve-session-id";
const textEncoder = new TextEncoder();
function isCurrentTurnBoundaryEvent(event) {
	return event.type === "session.completed" || event.type === "session.failed" || event.type === "session.waiting";
}

//#endregion
//#region src/protocol/cancel-turn.ts
const CancelTurnResponseSchema = z.object({
	ok: z.literal(true),
	sessionId: z.string().min(1),
	status: z.enum(["accepted", "no_active_turn"])
});

//#endregion
//#region src/client/output-schema.ts
function extractCompletedResult(events) {
	let result;
	for (const event of events) if (isResultCompletedEvent(event)) result = event.data.result;
	return result;
}
function isResultCompletedEvent(event) {
	return event.type === "result.completed";
}

//#endregion
//#region src/client/session-utils.ts
function createInitialSessionState() {
	return { streamIndex: 0 };
}
function advanceSession(input) {
	const boundaryEvent = findBoundaryEvent(input.events);
	const streamIndex = input.session.streamIndex + input.events.length;
	if (boundaryEvent?.type === "session.waiting" || input.preserveCompletedSessions === true && boundaryEvent?.type === "session.completed") return {
		continuationToken: boundaryEvent?.type === "session.waiting" ? boundaryEvent.data.continuationToken : input.continuationToken ?? input.session.continuationToken,
		sessionId: input.sessionId,
		streamIndex
	};
	if (boundaryEvent === void 0) return {
		continuationToken: input.continuationToken ?? input.session.continuationToken,
		sessionId: input.sessionId,
		streamIndex
	};
	return createInitialSessionState();
}
function extractCompletedMessage(events) {
	let lastMessage;
	for (const event of events) if (isFinalMessageCompleted(event)) lastMessage = event.data.message ?? void 0;
	return lastMessage;
}
function deriveResultStatus(events) {
	const boundary = findBoundaryEvent(events);
	if (boundary?.type === "session.waiting") return "waiting";
	if (boundary?.type === "session.failed") return "failed";
	return "completed";
}
function extractInputRequests(events) {
	const requests = [];
	for (const event of events) if (event.type === "input.requested") requests.push(...event.data.requests);
	return requests;
}
function findBoundaryEvent(events) {
	for (let i = events.length - 1; i >= 0; i--) {
		const event = events[i];
		if (event !== void 0 && isCurrentTurnBoundaryEvent(event)) return event;
	}
}
function isFinalMessageCompleted(event) {
	return event.type === "message.completed" && event.data.finishReason !== "tool-calls";
}

//#endregion
//#region src/client/message-response.ts
var MessageResponse = class {
	continuationToken;
	sessionId;
	#consumed = false;
	#createStream;
	constructor(input) {
		this.continuationToken = input.continuationToken;
		this.sessionId = input.sessionId;
		this.#createStream = input.createStream;
	}
	async result() {
		const events = [];
		for await (const event of this) events.push(event);
		return {
			data: extractCompletedResult(events),
			events,
			inputRequests: extractInputRequests(events),
			message: extractCompletedMessage(events),
			sessionId: this.sessionId,
			status: deriveResultStatus(events)
		};
	}
	[Symbol.asyncIterator]() {
		if (this.#consumed) throw new Error("MessageResponse has already been consumed.");
		this.#consumed = true;
		return this.#createStream();
	}
};

//#endregion
//#region src/client/ndjson.ts
function isStreamDisconnectError(error) {
	if (error instanceof DOMException) return error.name === "AbortError";
	if (!(error instanceof Error)) return false;
	const errorCode = "code" in error && typeof error.code === "string" ? error.code : void 0;
	return error.name === "AbortError" || error.message === "terminated" || errorCode === "UND_ERR_SOCKET" || error instanceof TypeError && /^(?:failed to fetch|fetch failed)$/i.test(error.message) || /abort|cancel|disconnect|premature close|socket|terminated/i.test(error.message);
}
async function* readNdjsonStream(body) {
	const reader = body.getReader();
	const decoder = new TextDecoder();
	let buffer = "";
	let reachedEof = false;
	try {
		while (true) {
			const result = await reader.read();
			if (result.done) {
				reachedEof = true;
				buffer += decoder.decode();
				break;
			}
			if (result.value) buffer += decoder.decode(result.value, { stream: true });
			let newlineIndex = buffer.indexOf("\n");
			while (newlineIndex !== -1) {
				const line = buffer.slice(0, newlineIndex).trim();
				buffer = buffer.slice(newlineIndex + 1);
				if (line.length > 0) yield JSON.parse(line);
				newlineIndex = buffer.indexOf("\n");
			}
		}
		const trailing = buffer.trim();
		if (trailing.length > 0) yield JSON.parse(trailing);
	} finally {
		if (!reachedEof) await reader.cancel().catch(() => {});
		reader.releaseLock();
	}
}

//#endregion
//#region src/client/url.ts
function createClientUrl(host, routePath, searchParams) {
	const normalizedRoute = routePath.startsWith("/") ? routePath : `/${routePath}`;
	if (isAbsoluteUrl(host)) {
		const url = new URL(host);
		url.pathname = `${trimTrailingSlash(url.pathname)}${normalizedRoute}`;
		mergeSearchParams(url.searchParams, searchParams);
		url.hash = "";
		return url.toString();
	}
	const url = new URL(host, "http://eve.local");
	const basePath = trimTrailingSlash(url.pathname);
	mergeSearchParams(url.searchParams, searchParams);
	return `${basePath}${normalizedRoute}${formatSearch(url.searchParams)}`;
}
function isAbsoluteUrl(value) {
	return /^[a-z][a-z\d+\-.]*:/i.test(value);
}
function trimTrailingSlash(value) {
	if (value === "/") return "";
	return value.endsWith("/") ? value.slice(0, -1) : value;
}
function mergeSearchParams(target, searchParams) {
	if (searchParams === void 0) return;
	for (const [name, value] of Object.entries(searchParams)) target.set(name, value);
}
function formatSearch(searchParams) {
	const value = searchParams.toString();
	return value.length === 0 ? "" : `?${value}`;
}

//#endregion
//#region src/client/open-stream.ts
const STREAM_OPEN_RETRY_ATTEMPTS = 12;
const STREAM_OPEN_RETRY_BASE_DELAY_MS = 250;
const STREAM_OPEN_RETRY_MAX_DELAY_MS = 5e3;
const STREAM_OPEN_RETRYABLE_STATUS = new Set([
	404,
	409,
	425,
	500,
	502,
	503,
	504
]);
const STREAM_RECONNECT_BASE_DELAY_MS = 250;
const STREAM_RECONNECT_MAX_DELAY_MS = 4e3;
const STREAM_MAX_IDLE_RECONNECTS = 5;
async function* followStreamIterable(input) {
	let startIndex = input.startIndex;
	let reconnectDelayMs = STREAM_RECONNECT_BASE_DELAY_MS;
	let idleReconnects = 0;
	let initialConnection = true;
	while (true) {
		let body;
		try {
			body = await openStreamBody({
				...input,
				startIndex
			});
		} catch (error) {
			if (input.signal?.aborted) return;
			throw error;
		}
		let deliveredEvent = false;
		try {
			for await (const event of readNdjsonStream(body)) {
				startIndex += 1;
				deliveredEvent = true;
				reconnectDelayMs = STREAM_RECONNECT_BASE_DELAY_MS;
				idleReconnects = 0;
				yield event;
			}
		} catch (error) {
			if (!isStreamDisconnectError(error)) throw error;
		}
		if (input.signal?.aborted || input.startIndex < 0) return;
		if (!deliveredEvent && !initialConnection && (idleReconnects += 1) >= STREAM_MAX_IDLE_RECONNECTS) return;
		initialConnection = false;
		await sleep$1(reconnectDelayMs, input.signal);
		if (input.signal?.aborted) return;
		reconnectDelayMs = Math.min(reconnectDelayMs * 2, STREAM_RECONNECT_MAX_DELAY_MS);
	}
}
async function openStreamBody(input) {
	let lastStatus;
	let lastBody;
	let lastHeaders;
	let retryDelayMs = STREAM_OPEN_RETRY_BASE_DELAY_MS;
	for (let attempt = 0; attempt < STREAM_OPEN_RETRY_ATTEMPTS; attempt += 1) {
		const url = createClientUrl(input.host, createEveMessageStreamRoutePath(input.sessionId), input.startIndex !== 0 ? { startIndex: String(input.startIndex) } : void 0);
		const headers = await input.resolveHeaders();
		let response;
		try {
			response = await fetch(url, {
				headers,
				redirect: input.redirect,
				signal: input.signal ?? null
			});
		} catch (error) {
			if (input.signal?.aborted || !isStreamDisconnectError(error) || attempt === STREAM_OPEN_RETRY_ATTEMPTS - 1) throw error;
			await sleep$1(retryDelayMs, input.signal);
			retryDelayMs = Math.min(retryDelayMs * 2, STREAM_OPEN_RETRY_MAX_DELAY_MS);
			continue;
		}
		if (response.ok) {
			if (!response.body) throw new ClientError(response.status, "Response body is null.", response.headers);
			return response.body;
		}
		lastStatus = response.status;
		lastBody = await response.text();
		lastHeaders = response.headers;
		if (!STREAM_OPEN_RETRYABLE_STATUS.has(response.status)) throw new ClientError(response.status, lastBody, response.headers);
		if (attempt < STREAM_OPEN_RETRY_ATTEMPTS - 1) {
			await sleep$1(retryDelayMs, input.signal);
			retryDelayMs = Math.min(retryDelayMs * 2, STREAM_OPEN_RETRY_MAX_DELAY_MS);
		}
	}
	throw new ClientError(lastStatus ?? 0, lastBody ?? "Failed to open message stream.", lastHeaders);
}
async function sleep$1(ms, signal) {
	if (signal?.aborted) return;
	await new Promise((resolve) => {
		const onAbort = () => {
			clearTimeout(timer);
			resolve();
		};
		const timer = setTimeout(() => {
			signal?.removeEventListener("abort", onAbort);
			resolve();
		}, ms);
		signal?.addEventListener("abort", onAbort, { once: true });
	});
}

//#endregion
//#region src/shared/json.ts
const INVALID_JSON_VALUE_CANDIDATE = Symbol("invalid-json-value-candidate");
const JSON_VALUE_ERROR_MESSAGE = "Expected a JSON-serializable value.";
const JSON_OBJECT_ERROR_MESSAGE = "Expected a JSON-serializable object.";
function parseJsonValue(value) {
	const normalized = normalizeJsonValueCandidate(value);
	if (normalized === INVALID_JSON_VALUE_CANDIDATE) throw new TypeError(JSON_VALUE_ERROR_MESSAGE);
	return normalized;
}
function parseJsonObject(value) {
	const normalized = parseJsonValue(value);
	if (!isJsonObjectValue(normalized)) throw new TypeError(JSON_OBJECT_ERROR_MESSAGE);
	return normalized;
}
function normalizeJsonValueCandidate(value, seen = /* @__PURE__ */ new WeakSet()) {
	if (value === null || typeof value === "boolean" || typeof value === "string") return value;
	if (typeof value === "number") return Number.isFinite(value) ? value : INVALID_JSON_VALUE_CANDIDATE;
	if (Array.isArray(value)) {
		const normalizedItems = [];
		for (const item of value) {
			const normalizedItem = normalizeJsonValueCandidate(item, seen);
			if (normalizedItem === INVALID_JSON_VALUE_CANDIDATE) return INVALID_JSON_VALUE_CANDIDATE;
			normalizedItems.push(normalizedItem);
		}
		return normalizedItems;
	}
	if (typeof value !== "object" || value === void 0) return INVALID_JSON_VALUE_CANDIDATE;
	if (!isPlainObject(value)) return INVALID_JSON_VALUE_CANDIDATE;
	if (seen.has(value)) return INVALID_JSON_VALUE_CANDIDATE;
	seen.add(value);
	const normalized = {};
	for (const [key, entry] of Object.entries(value)) {
		if (entry === void 0) continue;
		const normalizedEntry = normalizeJsonValueCandidate(entry, seen);
		if (normalizedEntry === INVALID_JSON_VALUE_CANDIDATE) return INVALID_JSON_VALUE_CANDIDATE;
		normalized[key] = normalizedEntry;
	}
	seen.delete(value);
	return normalized;
}
function isJsonObjectValue(value) {
	return value !== null && !Array.isArray(value) && typeof value === "object";
}
function isPlainObject(value) {
	const prototype = Object.getPrototypeOf(value);
	return prototype === null || prototype === Object.prototype;
}

//#endregion
//#region src/shared/tool-schema.ts
const JSON_SCHEMA_TARGET = "draft-07";
function serializeOutputSchema(source) {
	return serializeSchema(source, "output");
}
const UNSPECIFIED_INPUT_SCHEMA = z.fromJSONSchema({});
function serializeSchema(source, direction) {
	if (source === null || source === void 0) return source;
	return toJsonObject(source, direction);
}
function toJsonObject(source, direction) {
	const { $schema: _schemaVersion, ...canonical } = isStandardJsonSchema(source) ? parseJsonObject(source["~standard"].jsonSchema[direction]({ target: JSON_SCHEMA_TARGET })) : parseJsonObject(source);
	return canonical;
}
function isStandardJsonSchema(value) {
	return value !== null && typeof value === "object" && "~standard" in value;
}

//#endregion
//#region src/client/session.ts
const DELIVER_RETRY_ATTEMPTS = 10;
const DELIVER_RETRY_DELAY_MS = 200;
var ClientSession = class {
	#context;
	#state;
	constructor(context, state) {
		this.#context = context;
		this.#state = state;
	}
	get state() {
		return this.#state;
	}
	async send(input) {
		const payload = normalizeSendTurnInput(input);
		const state = this.#state;
		const { continuationToken, sessionId } = await this.#postTurn(payload, state);
		if (this.#state === state) this.#state = {
			...state,
			sessionId
		};
		return new MessageResponse({
			continuationToken,
			createStream: () => this.#createEventStream(sessionId, continuationToken, state, payload),
			sessionId
		});
	}
	async cancel(options) {
		const sessionId = this.#state.sessionId;
		if (!sessionId) throw new Error("Session has no session ID. Send a message first.");
		const url = createClientUrl(this.#context.host, createEveCancelTurnRoutePath(sessionId));
		const headers = await this.#context.resolveHeaders();
		headers.set("content-type", "application/json");
		const response = await fetch(url, withRedirectPolicy$1({
			headers,
			method: "POST",
			body: options ? JSON.stringify(options) : void 0
		}, this.#context.redirect));
		const body = await response.text();
		if (!response.ok) throw new ClientError(response.status, body, response.headers);
		let payload;
		try {
			payload = JSON.parse(body);
		} catch {
			throw new Error(`Cancel route returned invalid JSON (${response.status}).`);
		}
		const result = CancelTurnResponseSchema.safeParse(payload);
		if (!result.success || result.data.sessionId !== sessionId) throw new Error(`Cancel route returned an invalid response (${response.status}).`);
		return {
			sessionId: result.data.sessionId,
			status: result.data.status
		};
	}
	stream(options) {
		const sessionId = this.#state.sessionId;
		if (!sessionId) throw new Error("Session has no session ID. Send a message first.");
		return this.#streamAndAdvance(sessionId, options);
	}
	async #postTurn(input, session) {
		const routePath = session.sessionId ? createEveContinueSessionRoutePath(session.sessionId) : EVE_CREATE_SESSION_ROUTE_PATH;
		const url = createClientUrl(this.#context.host, routePath);
		const headers = await this.#context.resolveHeaders(input.headers);
		headers.set("content-type", "application/json");
		const body = createHandleMessageBody({
			input,
			outputSchema: serializeOutputSchema(input.outputSchema),
			session
		});
		if (body === null) throw new Error("Session.send requires a non-empty message, inputResponses, or both.");
		const response = await postTurnWithRetry({
			body: JSON.stringify(body),
			headers,
			mustDeliver: (input.inputResponses?.length ?? 0) > 0,
			redirect: this.#context.redirect,
			signal: input.signal,
			url
		});
		const payload = await response.json();
		const sessionId = (typeof payload.sessionId === "string" ? payload.sessionId : void 0) ?? response.headers.get("x-eve-session-id")?.trim() ?? session.sessionId;
		if (!sessionId) throw new Error("Message route did not return a session id.");
		return {
			continuationToken: typeof payload.continuationToken === "string" ? payload.continuationToken : void 0,
			sessionId
		};
	}
	async *#createEventStream(sessionId, continuationToken, initialState, input) {
		const events = [];
		try {
			for await (const event of followStreamIterable({
				host: this.#context.host,
				resolveHeaders: () => this.#context.resolveHeaders(input.headers),
				redirect: this.#context.redirect,
				sessionId,
				signal: input.signal,
				startIndex: initialState.sessionId === sessionId ? initialState.streamIndex : 0
			})) {
				events.push(event);
				yield event;
				if (isCurrentTurnBoundaryEvent(event)) break;
			}
		} finally {
			this.#state = advanceSession({
				continuationToken,
				events,
				preserveCompletedSessions: this.#context.preserveCompletedSessions,
				sessionId,
				session: initialState
			});
		}
	}
	async *#streamAndAdvance(sessionId, options) {
		const initialState = this.#state;
		const streamIndex = options?.startIndex ?? initialState.streamIndex;
		const events = [];
		try {
			for await (const event of followStreamIterable({
				host: this.#context.host,
				resolveHeaders: () => this.#context.resolveHeaders(),
				redirect: this.#context.redirect,
				sessionId,
				signal: options?.signal,
				startIndex: streamIndex
			})) {
				events.push(event);
				yield event;
			}
		} finally {
			if (streamIndex >= 0) this.#state = advanceSession({
				continuationToken: initialState.continuationToken,
				events,
				preserveCompletedSessions: this.#context.preserveCompletedSessions,
				session: {
					...initialState,
					sessionId,
					streamIndex
				},
				sessionId
			});
		}
	}
};
async function postTurnWithRetry(input) {
	const attempts = input.mustDeliver ? DELIVER_RETRY_ATTEMPTS : 1;
	let lastStatus;
	let lastBody;
	let lastHeaders;
	for (let attempt = 0; attempt < attempts; attempt += 1) {
		const response = await fetch(input.url, {
			body: input.body,
			headers: input.headers,
			method: "POST",
			redirect: input.redirect,
			signal: input.signal ?? null
		});
		if (response.ok) return response;
		lastStatus = response.status;
		lastBody = await response.text();
		lastHeaders = response.headers;
		if (!isRetryableDeliveryFailure(response.status, lastBody)) throw new ClientError(response.status, lastBody, response.headers);
		if (attempt < attempts - 1) await sleep(DELIVER_RETRY_DELAY_MS);
	}
	throw new ClientError(lastStatus ?? 0, lastBody ?? "Failed to deliver session turn.", lastHeaders);
}
function isRetryableDeliveryFailure(status, body) {
	return status === 500 && /target session was not found/i.test(body);
}
async function sleep(ms) {
	await new Promise((resolve) => setTimeout(resolve, ms));
}
function normalizeSendTurnInput(input) {
	return typeof input === "string" ? { message: input } : input;
}
function createHandleMessageBody(input) {
	const body = {};
	if (input.input.message !== void 0) body.message = input.input.message;
	if (input.input.inputResponses !== void 0 && input.input.inputResponses.length > 0) body.inputResponses = input.input.inputResponses;
	if (input.input.clientContext !== void 0) body.clientContext = input.input.clientContext;
	if (input.outputSchema !== void 0) body.outputSchema = input.outputSchema;
	if (input.session.continuationToken !== void 0) body.continuationToken = input.session.continuationToken;
	if (Object.keys(body).length === 0) return null;
	if (input.session.continuationToken === void 0 && body.message === void 0) return null;
	if (input.session.continuationToken !== void 0 && body.message === void 0 && body.inputResponses === void 0) return null;
	return body;
}
function withRedirectPolicy$1(init, redirect) {
	return redirect === void 0 ? init : {
		...init,
		redirect
	};
}

//#endregion
//#region src/client/types.ts
const VERCEL_TRUSTED_OIDC_IDP_TOKEN_HEADER = "x-vercel-trusted-oidc-idp-token";

//#endregion
//#region src/client/client.ts
var Client = class {
	#auth;
	#headers;
	#host;
	#preserveCompletedSessions;
	#redirect;
	constructor(options) {
		this.#host = options.host;
		this.#auth = options.auth;
		this.#headers = options.headers;
		this.#preserveCompletedSessions = options.preserveCompletedSessions ?? false;
		this.#redirect = options.redirect;
	}
	async health() {
		const url = createClientUrl(this.#host, EVE_HEALTH_ROUTE_PATH);
		const headers = await this.#resolveHeaders();
		const response = await fetch(url, withRedirectPolicy({ headers }, this.#redirect));
		if (!response.ok) {
			const body = await response.text();
			throw new ClientError(response.status, body, response.headers);
		}
		return await response.json();
	}
	async info() {
		const response = await this.fetch(EVE_INFO_ROUTE_PATH);
		if (!response.ok) {
			const body = await response.text();
			throw new ClientError(response.status, body, response.headers);
		}
		let payload;
		try {
			payload = await response.json();
		} catch {
			throw new AgentInfoResponseError();
		}
		const result = AgentInfoResultSchema.safeParse(payload);
		if (!result.success) throw new AgentInfoResponseError(result.error.issues.slice(0, 5).map((issue) => {
			const path = issue.path.join(".");
			return path.length === 0 ? issue.message : `${path}: ${issue.message}`;
		}));
		return result.data;
	}
	async fetch(path, init = {}) {
		const url = createClientUrl(this.#host, path);
		const headers = await this.#resolveHeaders(headersInitToRecord(init.headers));
		return await fetch(url, withRedirectPolicy({
			...init,
			headers
		}, this.#redirect));
	}
	session(state) {
		let resolved;
		if (typeof state === "string") resolved = {
			continuationToken: state,
			streamIndex: 0
		};
		else if (state) resolved = state;
		else resolved = createInitialSessionState();
		return new ClientSession({
			host: this.#host,
			preserveCompletedSessions: this.#preserveCompletedSessions,
			redirect: this.#redirect,
			resolveHeaders: (perRequest) => this.#resolveHeaders(perRequest)
		}, resolved);
	}
	async #resolveHeaders(perRequest) {
		const headers = new Headers();
		const [baseHeaders, authHeaders] = await Promise.all([resolveHeadersValue(this.#headers), this.#resolveAuthHeaders()]);
		for (const [key, value] of Object.entries(baseHeaders)) headers.set(key, value);
		if (perRequest) for (const [key, value] of Object.entries(perRequest)) headers.set(key, value);
		for (const [key, value] of Object.entries(authHeaders)) headers.set(key, value);
		return headers;
	}
	async #resolveAuthHeaders() {
		const auth = this.#auth;
		if (!auth) return {};
		if ("vercelOidc" in auth) {
			const token = (await resolveTokenValue(auth.vercelOidc.token)).trim();
			if (token.length === 0) return {};
			return {
				authorization: `Bearer ${token}`,
				[VERCEL_TRUSTED_OIDC_IDP_TOKEN_HEADER]: token
			};
		}
		if ("bearer" in auth) {
			const token = (await resolveTokenValue(auth.bearer)).trim();
			return token.length === 0 ? {} : { authorization: `Bearer ${token}` };
		}
		if ("basic" in auth) {
			const password = await resolveTokenValue(auth.basic.password);
			return { authorization: `Basic ${encodeBasicCredentials(auth.basic.username, password)}` };
		}
		return {};
	}
};
async function resolveTokenValue(value) {
	return typeof value === "function" ? value() : value;
}
async function resolveHeadersValue(value) {
	if (value === void 0) return {};
	return typeof value === "function" ? await value() : value;
}
function headersInitToRecord(headers) {
	if (headers === void 0) return {};
	return Object.fromEntries(new Headers(headers).entries());
}
function withRedirectPolicy(init, redirect) {
	return redirect === void 0 ? init : {
		...init,
		redirect
	};
}

//#endregion
//#region src/client/eve-agent-store.ts
var EveAgentStore = class {
	#createSession;
	#optimistic;
	#reducer;
	#subscribers = /* @__PURE__ */ new Set();
	#abortController;
	#callbacks = {};
	#data;
	#error;
	#events;
	#operationId = 0;
	#pendingMessageSubmission;
	#projectionEvents;
	#session;
	#snapshot;
	#status = "ready";
	constructor(init) {
		this.#createSession = init.session ? void 0 : () => new Client({
			auth: init.auth,
			headers: init.headers,
			host: init.host ?? ""
		}).session(init.initialSession);
		this.#events = [...init.initialEvents ?? []];
		this.#projectionEvents = [...this.#events];
		this.#optimistic = init.optimistic ?? true;
		this.#reducer = init.reducer;
		this.#session = init.session ?? this.#createOwnedSession();
		this.#data = this.#reduceProjectionEvents(this.#projectionEvents);
		this.#snapshot = this.#createSnapshot();
	}
	get snapshot() {
		return this.#snapshot;
	}
	setCallbacks(callbacks) {
		this.#callbacks = callbacks;
	}
	subscribe(callback) {
		this.#subscribers.add(callback);
		return () => {
			this.#subscribers.delete(callback);
		};
	}
	async send(input) {
		if (this.#status === "streaming" || this.#status === "submitted") throw new Error("eve session is already processing a turn.");
		const operationId = this.#startOperation();
		const abortController = new AbortController();
		this.#abortController = abortController;
		this.#error = void 0;
		this.#status = "submitted";
		this.#publish();
		try {
			const preparedInput = await this.#callbacks.prepareSend?.(input) ?? input;
			if (!this.#isCurrentOperation(operationId)) return;
			this.#projectOptimisticMessage(preparedInput);
			this.#projectInputResponses(preparedInput);
			this.#publish();
			const response = await this.#session.send({
				...preparedInput,
				signal: createAbortSignal(preparedInput.signal, abortController.signal)
			});
			let sawEvent = false;
			for await (const event of response) {
				if (!this.#isCurrentOperation(operationId)) return;
				if (!sawEvent) {
					sawEvent = true;
					this.#status = "streaming";
				}
				this.#events = [...this.#events, event];
				this.#applyServerEvent(event);
				this.#callbacks.onEvent?.(event);
				this.#applyTerminalStreamFailure(event);
				this.#publish();
			}
			if (!this.#isCurrentOperation(operationId)) return;
			this.#status = this.#error === void 0 ? "ready" : "error";
		} catch (error) {
			if (!this.#isCurrentOperation(operationId)) return;
			if (isAbortError(error)) {
				this.#status = "ready";
				this.#failPendingMessageSubmission(toError(error));
			} else {
				this.#error = toError(error);
				this.#status = "error";
				this.#failPendingMessageSubmission(this.#error);
				this.#callbacks.onError?.(this.#error);
			}
		} finally {
			if (this.#isCurrentOperation(operationId)) {
				this.#abortController = void 0;
				this.#callbacks.onSessionChange?.(this.#session.state);
				this.#publish();
				this.#callbacks.onFinish?.(this.#snapshot);
			}
		}
	}
	stop() {
		this.#abortController?.abort();
	}
	reset() {
		this.#invalidateOperation();
		this.stop();
		this.#abortController = void 0;
		this.#session = this.#createSession?.() ?? this.#session;
		this.#events = [];
		this.#pendingMessageSubmission = void 0;
		this.#projectionEvents = [];
		this.#data = this.#reducer.initial();
		this.#error = void 0;
		this.#status = "ready";
		this.#callbacks.onSessionChange?.(this.#session.state);
		this.#publish();
	}
	#createOwnedSession() {
		if (!this.#createSession) throw new Error("Cannot create an owned eve session from an external session.");
		return this.#createSession();
	}
	#startOperation() {
		this.#operationId += 1;
		return this.#operationId;
	}
	#invalidateOperation() {
		this.#operationId += 1;
	}
	#isCurrentOperation(operationId) {
		return this.#operationId === operationId;
	}
	#projectOptimisticMessage(input) {
		if (!this.#optimistic || input.message === void 0) return;
		const id = createSubmissionId();
		const pending = {
			createdAt: Date.now(),
			id,
			message: summarizeUserContent(input.message)
		};
		this.#pendingMessageSubmission = pending;
		this.#appendProjectionEvent({
			data: {
				createdAt: pending.createdAt,
				message: pending.message,
				submissionId: pending.id
			},
			type: "client.message.submitted"
		});
	}
	#projectInputResponses(input) {
		if (input.inputResponses === void 0 || input.inputResponses.length === 0) return;
		this.#appendProjectionEvent({
			data: {
				createdAt: Date.now(),
				responses: input.inputResponses
			},
			type: "client.input.responded"
		});
	}
	#applyServerEvent(event) {
		if (event.type === "message.received" && this.#pendingMessageSubmission !== void 0) {
			const submissionId = this.#pendingMessageSubmission.id;
			this.#pendingMessageSubmission = void 0;
			this.#replaceProjectionEvent((candidate) => candidate.type === "client.message.submitted" && candidate.data.submissionId === submissionId, event);
			return;
		}
		this.#appendProjectionEvent(event);
	}
	#applyTerminalStreamFailure(event) {
		const error = toTerminalStreamFailureError(event);
		if (error === void 0) return;
		this.#status = "error";
		this.#failPendingMessageSubmission(error);
		if (this.#error === void 0) {
			this.#error = error;
			this.#callbacks.onError?.(error);
		}
	}
	#failPendingMessageSubmission(error) {
		const pending = this.#pendingMessageSubmission;
		if (pending === void 0) return;
		this.#pendingMessageSubmission = void 0;
		this.#replaceProjectionEvent((event) => event.type === "client.message.submitted" && event.data.submissionId === pending.id, {
			data: {
				createdAt: pending.createdAt,
				error: { message: error.message },
				message: pending.message,
				submissionId: pending.id
			},
			type: "client.message.failed"
		});
	}
	#appendProjectionEvent(event) {
		this.#projectionEvents = [...this.#projectionEvents, event];
		this.#data = this.#reducer.reduce(this.#data, event);
	}
	#replaceProjectionEvent(predicate, replacement) {
		let replaced = false;
		this.#projectionEvents = this.#projectionEvents.map((event) => {
			if (!replaced && predicate(event)) {
				replaced = true;
				return replacement;
			}
			return event;
		});
		if (!replaced) this.#projectionEvents = [...this.#projectionEvents, replacement];
		this.#data = this.#reduceProjectionEvents(this.#projectionEvents);
	}
	#reduceProjectionEvents(events) {
		let data = this.#reducer.initial();
		for (const event of events) data = this.#reducer.reduce(data, event);
		return data;
	}
	#createSnapshot() {
		return {
			data: this.#data,
			error: this.#error,
			events: this.#events,
			session: this.#session.state,
			status: this.#status
		};
	}
	#publish() {
		this.#snapshot = this.#createSnapshot();
		for (const subscriber of this.#subscribers) subscriber();
	}
};
let submissionSequence = 0;
function createSubmissionId() {
	const randomUUID = globalThis.crypto?.randomUUID;
	if (randomUUID !== void 0) return randomUUID.call(globalThis.crypto);
	submissionSequence += 1;
	return `submission_${submissionSequence.toString()}`;
}
function createAbortSignal(first, second) {
	return first ? AbortSignal.any([first, second]) : second;
}
function summarizeUserContent(message) {
	if (typeof message === "string") return message;
	const parts = [];
	for (const part of message) {
		if (part.type === "text") {
			parts.push(part.text);
			continue;
		}
		if (part.type === "file") parts.push(part.filename ? `[file: ${part.filename}]` : "[file]");
	}
	return parts.join("\n");
}
function isAbortError(error) {
	return error instanceof Error && error.name === "AbortError";
}
function toTerminalStreamFailureError(event) {
	if (event.type !== "session.failed") return;
	const error = new Error(event.data.message);
	error.name = event.data.code;
	return error;
}

//#endregion
//#region src/client/agent-host.ts
const AGENT_NAME_PATTERN = /^[a-z0-9][a-z0-9_-]*$/;
const EVE_NAMED_AGENT_ROUTE_PREFIX = "/eve/agents";
function resolveEveAgentHost(input) {
	if (input.agent === void 0) return input.host ?? "";
	if (input.host !== void 0) throw new Error("useEveAgent cannot combine agent and host. Use one target option.");
	assertValidAgentName(input.agent);
	return `${EVE_NAMED_AGENT_ROUTE_PREFIX}/${input.agent}`;
}
function assertValidAgentName(name) {
	if (!AGENT_NAME_PATTERN.test(name)) throw new Error(`eve agent name ${JSON.stringify(name)} is invalid. Use lowercase letters, numbers, underscores, or hyphens, starting with a letter or number.`);
}

//#endregion
//#region src/client/authorization-message-parts.ts
function createAuthorizationRequiredPart(event) {
	const displayName = event.data.authorization?.displayName ?? formatAuthorizationDisplayName(event.data.name);
	return {
		authorization: event.data.authorization,
		description: normalizeAuthorizationDescription(event.data.description, event.data.name, displayName),
		displayName,
		name: event.data.name,
		state: "required",
		stepIndex: event.data.stepIndex,
		turnId: event.data.turnId,
		type: "authorization"
	};
}
function createAuthorizationCompletedPart(event, existing) {
	const displayName = event.data.authorization?.displayName ?? existing?.displayName ?? formatAuthorizationDisplayName(event.data.name);
	return {
		authorization: existing?.authorization || event.data.authorization ? {
			...existing?.authorization,
			...event.data.authorization
		} : void 0,
		description: existing?.description ?? buildCompletedAuthorizationDescription(displayName, event.data.outcome, event.data.reason),
		displayName,
		name: event.data.name,
		outcome: event.data.outcome,
		reason: event.data.reason,
		state: "completed",
		stepIndex: existing?.stepIndex ?? event.data.stepIndex,
		turnId: existing?.turnId ?? event.data.turnId,
		type: "authorization"
	};
}
function buildCompletedAuthorizationDescription(displayName, outcome, reason) {
	if (outcome === "authorized") return `${displayName} connected.`;
	return `${displayName} authorization ${outcome}${reason !== void 0 ? ` (${reason})` : ""}.`;
}
function normalizeAuthorizationDescription(description, name, displayName) {
	if (description === `Authorization required for ${name}`) return `Authorization required for ${displayName}`;
	return description;
}
function formatAuthorizationDisplayName(name) {
	if (name.length === 0) return name;
	return `${name.charAt(0).toUpperCase()}${name.slice(1)}`;
}

//#endregion
//#region src/client/message-action-parts.ts
function toMessageInputRequest(request) {
	return {
		allowFreeform: request.allowFreeform,
		display: request.display,
		options: request.options,
		prompt: request.prompt,
		requestId: request.requestId
	};
}
function createToolMetadata(descriptor, extra) {
	return { eve: {
		inputRequest: extra?.inputRequest,
		kind: descriptor.kind,
		name: descriptor.name
	} };
}
function mergeToolMetadata(current, next) {
	const kind = next.eve?.kind ?? current?.eve?.kind ?? "unknown";
	const name = next.eve?.name ?? current?.eve?.name ?? "unknown";
	return { eve: {
		...current?.eve,
		...next.eve,
		inputRequest: next.eve?.inputRequest ?? current?.eve?.inputRequest,
		inputResponse: next.eve?.inputResponse ?? current?.eve?.inputResponse,
		kind,
		name
	} };
}
function approvedApproval(part) {
	if (!part?.approval?.id) return;
	return {
		approved: true,
		id: part.approval.id,
		isAutomatic: part.approval.isAutomatic,
		reason: part.approval.reason
	};
}
function normalizeActionRequest(action) {
	switch (action.kind) {
		case "load-skill": return {
			kind: "load-skill",
			name: "load_skill",
			toolName: "eve:load-skill"
		};
		case "tool-call": return {
			kind: "tool-call",
			name: action.toolName,
			toolName: action.toolName
		};
		case "subagent-call": return {
			kind: "subagent-call",
			name: action.subagentName,
			toolName: `eve:subagent:${action.subagentName}`
		};
		case "remote-agent-call": return {
			kind: "subagent-call",
			name: action.remoteAgentName,
			toolName: `eve:subagent:${action.remoteAgentName}`
		};
	}
}
function normalizeActionResult(result) {
	switch (result.kind) {
		case "load-skill-result": return {
			kind: "load-skill",
			name: result.name ?? "load_skill",
			toolName: "eve:load-skill"
		};
		case "tool-result": return {
			kind: "tool-call",
			name: result.toolName,
			toolName: result.toolName
		};
		case "subagent-result": return {
			kind: "subagent-call",
			name: result.subagentName,
			toolName: `eve:subagent:${result.subagentName}`
		};
	}
}
function stringifyUnknown(value) {
	if (typeof value === "string") return value;
	try {
		return JSON.stringify(value);
	} catch {
		return "Action failed.";
	}
}

//#endregion
//#region src/client/message-reducer.ts
function defaultMessageReducer() {
	return {
		initial() {
			return { messages: [] };
		},
		reduce(data, event) {
			return reduceMessageData(data, event);
		}
	};
}
function reduceMessageData(data, event) {
	switch (event.type) {
		case "client.message.submitted": return upsertMessage(data, {
			id: optimisticUserMessageId(event.data.submissionId),
			metadata: {
				optimistic: true,
				status: "submitted"
			},
			parts: [{
				type: "text",
				text: event.data.message
			}],
			role: "user"
		});
		case "client.message.failed": return upsertMessage(data, {
			id: optimisticUserMessageId(event.data.submissionId),
			metadata: {
				optimistic: true,
				status: "failed"
			},
			parts: [{
				type: "text",
				text: event.data.message
			}],
			role: "user"
		});
		case "client.input.responded": {
			let next = data;
			for (const response of event.data.responses) next = respondToInputRequest(next, response);
			return next;
		}
		case "message.received": return upsertMessage(data, {
			id: `${event.data.turnId}:user`,
			metadata: {
				status: "complete",
				turnId: event.data.turnId
			},
			parts: projectReceivedParts(event.data.parts, event.data.message),
			role: "user"
		});
		case "step.started": return updateAssistantMessage(data, event.data.turnId, (message) => ensureStepStartPart(message, event.data.stepIndex));
		case "reasoning.appended": return updateAssistantMessage(data, event.data.turnId, (message) => upsertRun(ensureStepStartPart(message, event.data.stepIndex), {
			state: "streaming",
			stepIndex: event.data.stepIndex,
			text: event.data.reasoningSoFar,
			type: "reasoning"
		}));
		case "reasoning.completed": return updateAssistantMessage(data, event.data.turnId, (message) => upsertRun(ensureStepStartPart(message, event.data.stepIndex), {
			state: "done",
			stepIndex: event.data.stepIndex,
			text: event.data.reasoning,
			type: "reasoning"
		}));
		case "actions.requested": {
			let next = data;
			for (const action of event.data.actions) {
				const descriptor = normalizeActionRequest(action);
				next = updateAssistantMessage(next, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), {
					input: "input" in action ? action.input : void 0,
					state: "input-available",
					stepIndex: event.data.stepIndex,
					toolCallId: action.callId,
					toolMetadata: createToolMetadata(descriptor),
					toolName: descriptor.toolName,
					type: "dynamic-tool"
				}));
			}
			return next;
		}
		case "input.requested": {
			let next = data;
			for (const request of event.data.requests) {
				const descriptor = normalizeActionRequest(request.action);
				next = updateAssistantMessage(next, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), {
					approval: { id: request.requestId },
					input: request.action.input,
					state: "approval-requested",
					stepIndex: event.data.stepIndex,
					toolCallId: request.action.callId,
					toolMetadata: createToolMetadata(descriptor, { inputRequest: toMessageInputRequest(request) }),
					toolName: descriptor.toolName,
					type: "dynamic-tool"
				}));
			}
			return next;
		}
		case "action.result": {
			const descriptor = normalizeActionResult(event.data.result);
			const existing = findToolPart(data, event.data.result.callId);
			const denied = event.data.error?.code === "TOOL_EXECUTION_DENIED";
			const failed = event.data.status === "failed" && !denied;
			const approvalId = existing?.approval?.id ?? event.data.result.callId;
			const toolMetadata = mergeToolMetadata(existing?.toolMetadata, createToolMetadata(descriptor));
			const resultPartBase = {
				input: existing?.input,
				stepIndex: event.data.stepIndex,
				toolCallId: event.data.result.callId,
				toolMetadata,
				toolName: existing?.toolName ?? descriptor.toolName,
				type: "dynamic-tool"
			};
			let nextPart;
			if (denied) nextPart = {
				...resultPartBase,
				approval: {
					approved: false,
					id: approvalId,
					reason: event.data.error?.message
				},
				state: "output-denied"
			};
			else if (failed) nextPart = {
				...resultPartBase,
				approval: approvedApproval(existing),
				errorText: event.data.error?.message ?? stringifyUnknown(event.data.result.output),
				state: "output-error"
			};
			else nextPart = {
				...resultPartBase,
				approval: approvedApproval(existing),
				output: event.data.result.output,
				state: "output-available"
			};
			if (existing !== void 0) return updateToolPart(data, event.data.result.callId, nextPart);
			return updateAssistantMessage(data, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), nextPart));
		}
		case "authorization.required": return updateAssistantMessage(data, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), createAuthorizationRequiredPart(event)));
		case "authorization.completed": return completeAuthorization(data, event);
		case "message.appended": return updateAssistantMessage(data, event.data.turnId, (message) => upsertRun(ensureStepStartPart(message, event.data.stepIndex), {
			state: "streaming",
			stepIndex: event.data.stepIndex,
			text: event.data.messageSoFar,
			type: "text"
		}));
		case "message.completed": return updateAssistantMessage(data, event.data.turnId, (message) => {
			if (event.data.message === null) return removeTextPart(message, event.data.stepIndex);
			return upsertRun(ensureStepStartPart(message, event.data.stepIndex), {
				state: "done",
				stepIndex: event.data.stepIndex,
				text: event.data.message,
				type: "text"
			});
		});
		case "result.completed": return updateAssistantMetadata(data, event.data.turnId, { result: event.data.result });
		case "turn.completed": return updateAssistantMetadata(data, event.data.turnId, { status: "complete" });
		case "turn.cancelled": return updateAssistantMessage(data, event.data.turnId, (message) => ({
			...message,
			metadata: {
				...message.metadata,
				status: "complete"
			},
			parts: message.parts.map((part) => (part.type === "text" || part.type === "reasoning") && part.state === "streaming" ? {
				...part,
				state: "done"
			} : part)
		}));
		case "turn.failed":
		case "session.failed": return data;
		default: return data;
	}
}
function respondToInputRequest(data, response) {
	const existing = findToolPartByApprovalId(data, response.requestId);
	if (!existing) return data;
	const approval = { id: response.requestId };
	if (response.text !== void 0) approval.reason = response.text;
	return updateToolPart(data, existing.toolCallId, {
		approval,
		input: existing.input,
		state: "approval-responded",
		stepIndex: existing.stepIndex,
		toolCallId: existing.toolCallId,
		toolMetadata: mergeToolMetadata(existing.toolMetadata, { eve: {
			inputResponse: response,
			kind: existing.toolMetadata?.eve?.kind ?? "unknown",
			name: existing.toolMetadata?.eve?.name ?? existing.toolName
		} }),
		toolName: existing.toolName,
		type: "dynamic-tool"
	});
}
function updateAssistantMessage(data, turnId, update) {
	return upsertMessage(data, update(data.messages.find((message) => message.role === "assistant" && message.metadata?.turnId === turnId) ?? createAssistantMessage(turnId)));
}
function updateAssistantMetadata(data, turnId, metadata) {
	return updateAssistantMessage(data, turnId, (message) => ({
		...message,
		metadata: {
			...message.metadata,
			...metadata
		}
	}));
}
function createAssistantMessage(turnId) {
	return {
		id: `${turnId}:assistant`,
		metadata: {
			status: "streaming",
			turnId
		},
		parts: [],
		role: "assistant"
	};
}
function ensureStepStartPart(message, stepIndex) {
	const stepStartCount = message.parts.filter((part) => part.type === "step-start").length;
	if (stepStartCount > stepIndex) return message;
	const missingCount = stepIndex - stepStartCount + 1;
	return {
		...message,
		parts: [...message.parts, ...Array.from({ length: missingCount }, () => ({ type: "step-start" }))]
	};
}
function upsertPart(message, next) {
	const index = message.parts.findIndex((part) => partKey(part) === partKey(next));
	const parts = index === -1 ? [...message.parts, next] : [
		...message.parts.slice(0, index),
		next,
		...message.parts.slice(index + 1)
	];
	return {
		...message,
		metadata: {
			...message.metadata,
			status: next.type === "text" && next.state === "done" ? "complete" : "streaming"
		},
		parts
	};
}
function upsertRun(message, next) {
	let lastIndex = -1;
	for (let index = message.parts.length - 1; index >= 0; index -= 1) {
		const part = message.parts[index];
		if (part?.type === next.type && part.stepIndex === next.stepIndex) {
			lastIndex = index;
			break;
		}
	}
	const parts = lastIndex !== -1 && message.parts[lastIndex].state === "streaming" ? [
		...message.parts.slice(0, lastIndex),
		next,
		...message.parts.slice(lastIndex + 1)
	] : [...message.parts, next];
	return {
		...message,
		metadata: {
			...message.metadata,
			status: next.type === "text" && next.state === "done" ? "complete" : "streaming"
		},
		parts
	};
}
function removeTextPart(message, stepIndex) {
	const parts = message.parts.filter((part) => part.type !== "text" || part.stepIndex !== stepIndex);
	if (parts.length === message.parts.length) return message;
	return {
		...message,
		metadata: {
			...message.metadata,
			status: "complete"
		},
		parts
	};
}
function updateToolPart(data, toolCallId, next) {
	const message = data.messages.find((candidate) => candidate.role === "assistant" && candidate.parts.some((part) => part.type === "dynamic-tool" && part.toolCallId === toolCallId));
	if (!message) return data;
	return upsertMessage(data, upsertPart(message, next));
}
function completeAuthorization(data, event) {
	const existing = findLatestPendingAuthorizationPart(data, event.data.name);
	const next = createAuthorizationCompletedPart(event, existing);
	if (existing !== void 0) return updateAuthorizationPart(data, existing, next);
	return updateAssistantMessage(data, event.data.turnId, (message) => upsertPart(ensureStepStartPart(message, event.data.stepIndex), next));
}
function updateAuthorizationPart(data, existing, next) {
	const message = data.messages.find((candidate) => candidate.role === "assistant" && candidate.parts.some((part) => part === existing));
	if (!message) return data;
	return upsertMessage(data, upsertPart(message, next));
}
function findToolPart(data, toolCallId) {
	for (const message of data.messages) for (const part of message.parts) if (part.type === "dynamic-tool" && part.toolCallId === toolCallId) return part;
}
function findLatestPendingAuthorizationPart(data, name) {
	for (let messageIndex = data.messages.length - 1; messageIndex >= 0; messageIndex -= 1) {
		const message = data.messages[messageIndex];
		if (message?.role !== "assistant") continue;
		for (let partIndex = message.parts.length - 1; partIndex >= 0; partIndex -= 1) {
			const part = message.parts[partIndex];
			if (part?.type === "authorization" && part.state === "required" && part.name === name) return part;
		}
	}
}
function findToolPartByApprovalId(data, approvalId) {
	for (const message of data.messages) for (const part of message.parts) if (part.type === "dynamic-tool" && part.approval?.id === approvalId) return part;
}
function projectReceivedParts(parts, message) {
	return parts?.map((part) => part.type === "text" ? {
		state: "done",
		text: part.text,
		type: "text"
	} : {
		filename: part.filename,
		mediaType: part.mediaType,
		size: part.size,
		type: "file",
		url: part.url
	}) ?? [{
		state: "done",
		text: message,
		type: "text"
	}];
}
function partKey(part) {
	switch (part.type) {
		case "text": return `text:${part.stepIndex ?? 0}`;
		case "reasoning": return `reasoning:${part.stepIndex ?? 0}`;
		case "file": return `file:${part.stepIndex ?? 0}:${part.filename ?? part.url ?? part.mediaType}`;
		case "step-start": return "step-start";
		case "authorization": return `authorization:${part.turnId}:${part.stepIndex}:${part.name}`;
		case "dynamic-tool": return `dynamic-tool:${part.toolCallId}`;
	}
}
function upsertMessage(data, next) {
	const index = data.messages.findIndex((message) => message.id === next.id);
	if (index === -1) return { messages: [...data.messages, next] };
	return { messages: [
		...data.messages.slice(0, index),
		next,
		...data.messages.slice(index + 1)
	] };
}
function optimisticUserMessageId(submissionId) {
	return `optimistic:${submissionId}:user`;
}

//#endregion
//#region src/vue/use-eve-agent.ts
function useEveAgent(options = {}) {
	const reducer = options.reducer ?? defaultMessageReducer();
	const store = new EveAgentStore({
		auth: options.auth,
		headers: options.headers,
		host: resolveEveAgentHost({
			agent: options.agent,
			host: options.host
		}),
		initialEvents: options.initialEvents,
		initialSession: options.initialSession,
		optimistic: options.optimistic,
		reducer,
		session: options.session
	});
	store.setCallbacks({
		onError: options.onError,
		onEvent: options.onEvent,
		onFinish: options.onFinish,
		onSessionChange: options.onSessionChange,
		prepareSend: options.prepareSend
	});
	const snapshot = shallowRef(store.snapshot);
	if ("window" in globalThis) {
		const unsubscribe = store.subscribe(() => {
			snapshot.value = store.snapshot;
		});
		onScopeDispose(() => {
			unsubscribe();
			store.stop();
		});
	}
	return {
		data: computed(() => snapshot.value.data),
		error: computed(() => snapshot.value.error),
		events: computed(() => snapshot.value.events),
		reset: () => store.reset(),
		send: (input) => store.send(input),
		session: computed(() => snapshot.value.session),
		status: computed(() => snapshot.value.status),
		stop: () => store.stop()
	};
}

//#endregion
export { defaultMessageReducer as n, useEveAgent as t };