import { hostname } from "node:os";
import { HUB_PROTOCOL_VERSION } from "../../hub/index.js";
import { SocketPeerClient } from "../client/socket-client.js";
import { PeerAppState } from "../state/peer-app-state.js";
import { PeerUiState } from "../state/peer-ui-state.js";
const DEFAULT_RESPONSE_TIMEOUT_MS = 10 * 60 * 1000;
const DEFAULT_ONE_SHOT_PEER_ID = "d-pi-peer-message";
export async function sendOneShotPeerMessage(options) {
    const message = options.message.trim();
    if (!message) {
        throw new Error("Message text is required.");
    }
    const appState = new PeerAppState();
    const uiState = new PeerUiState();
    const hostId = options.peerId?.trim() || DEFAULT_ONE_SHOT_PEER_ID;
    const client = new SocketPeerClient({
        hubUrl: options.hubUrl,
        hello: {
            peerId: hostId,
            ...(options.agentId?.trim() ? { agentId: options.agentId.trim() } : {}),
            token: options.token ?? "",
            clientKind: "host",
            protocolVersion: HUB_PROTOCOL_VERSION,
            displayName: hostId,
            version: options.version,
            platform: process.platform,
            hostname: hostname(),
            cwd: process.cwd(),
            executorEnabled: false,
        },
        appState,
        uiState,
        onHandshakeLog: options.onHandshakeLog,
        reconnection: false,
    });
    try {
        await client.connect();
        let response;
        if (options.noResponse !== true) {
            await client.waitForInitialSync();
            response = waitForOneShotResponse(appState, {
                hostId,
                message,
                baseline: createResponseBaseline(appState.getSnapshot()),
                timeoutMs: options.responseTimeoutMs ?? DEFAULT_RESPONSE_TIMEOUT_MS,
            });
        }
        await client.queueWrite(message);
        await client.queueFlush();
        return response ? await response : undefined;
    }
    finally {
        await client.disconnect().catch(() => { });
    }
}
function createResponseBaseline(snapshot) {
    const agent = snapshot.selectedAgent;
    if (!agent) {
        throw new Error("Hub session sync did not include a selected agent.");
    }
    return {
        itemCount: agent.items.length,
        lastError: agent.lastError,
    };
}
function waitForOneShotResponse(appState, options) {
    return new Promise((resolve, reject) => {
        let settled = false;
        let unsubscribe;
        const settle = (callback) => {
            if (settled) {
                return;
            }
            settled = true;
            clearTimeout(timeoutId);
            unsubscribe?.();
            callback();
        };
        const timeoutId = setTimeout(() => {
            settle(() => reject(new Error(`Timed out waiting for assistant response after ${options.timeoutMs}ms.`)));
        }, options.timeoutMs);
        timeoutId.unref?.();
        const evaluate = (snapshot) => {
            const result = findOneShotResponse(snapshot.selectedAgent, options);
            if (result.type === "pending") {
                return;
            }
            if (result.type === "error") {
                settle(() => reject(new Error(result.message)));
                return;
            }
            settle(() => resolve(result.text));
        };
        unsubscribe = appState.subscribe(evaluate);
        evaluate(appState.getSnapshot());
    });
}
function findOneShotResponse(agent, options) {
    if (!agent) {
        return { type: "pending" };
    }
    const items = agent.items.slice(options.baseline.itemCount);
    const userIndex = items.findIndex((item) => isMatchingHostUserMessage(item, options.hostId, options.message));
    if (userIndex === -1) {
        return { type: "pending" };
    }
    const assistant = findLastAssistantMessage(items.slice(userIndex + 1));
    if (agent.status.isRunning) {
        return { type: "pending" };
    }
    if (!assistant && agent.lastError && agent.lastError !== options.baseline.lastError) {
        return { type: "error", message: agent.lastError };
    }
    if (!assistant) {
        return { type: "pending" };
    }
    return { type: "response", text: getAssistantText(assistant) };
}
function isMatchingHostUserMessage(item, hostId, message) {
    if (item.type !== "message" || item.message.role !== "user") {
        return false;
    }
    const source = "messageSource" in item.message ? item.message.messageSource : undefined;
    return getMessageText(item.message) === message && source?.kind === "host" && source.name === hostId;
}
function findLastAssistantMessage(items) {
    for (let i = items.length - 1; i >= 0; i -= 1) {
        const item = items[i];
        if (item?.type === "message" && item.message.role === "assistant") {
            return item.message;
        }
    }
    return undefined;
}
function getAssistantText(message) {
    return message.content
        .filter((part) => part.type === "text")
        .map((part) => part.text)
        .join("\n");
}
function getMessageText(message) {
    const content = message.content;
    if (typeof content === "string") {
        return content;
    }
    return content
        .filter((part) => part.type === "text")
        .map((part) => part.text)
        .join("\n");
}
//# sourceMappingURL=send-message.js.map