import { extractAgentUserPlainText } from "../memory/user-message-text.js";
import { shouldSkipResetOverlapCommand } from "../../session/reset-triggers.js";
import { parseSlashCommand } from "../../chat-commands/command-parse.js";
import { commandRegistry } from "../../chat-commands/registry.js";
import "../../chat-commands/index.js";
import { runEmbeddedTurnForSession } from "../embedded/run-for-session.js";
import crypto from "node:crypto";
//#region src/agent/service/direct-turn-helpers.ts
/**
* Shared building blocks for the two direct-turn entry points (streaming
* webchat SSE and one-shot CLI). Both flows do the same hydrate → maybe-slash
* → run-embedded-turn → after-turn dance; this module captures that core so
* the entry points only manage their I/O specifics (event sink, voice STT,
* TTS, transcript persistence).
*/
/** Workspace + model + thinking level — common prep before any direct turn. */
async function hydratePerTurnState(deps, sessionKey, thinking) {
	await deps.hydrateSessionWorkspaceFromStore(sessionKey);
	await deps.hydrateSessionModelFromStore(sessionKey);
	await deps.applyResolvedThinkingLevel(sessionKey, thinking);
}
/**
* Detect a slash command and, if registered, execute it and aggregate the reply
* text. Errors thrown inside the command surface as `aggregatedText` so callers
* can persist the receipt or stream it as a token.
*/
async function tryRunSlashCommand(deps, ctx, content, options) {
	const parsed = parseSlashCommand(content);
	if (!parsed) return {
		matched: false,
		aggregatedText: ""
	};
	if (options?.skipResetCommands && shouldSkipResetOverlapCommand(parsed.command, true)) return {
		matched: false,
		aggregatedText: ""
	};
	if (!commandRegistry.has(parsed.command)) return {
		matched: false,
		aggregatedText: ""
	};
	try {
		const { aggregatedText } = await deps.commandHandler.executeCommandAndAggregateReply(parsed.command, parsed.args, {
			sessionKey: ctx.sessionKey,
			channel: ctx.channel,
			chatId: ctx.chatId,
			senderId: ctx.senderId ?? "",
			isGroup: ctx.isGroup ?? false,
			inboundMetadata: ctx.inboundMetadata ?? {}
		});
		return {
			matched: true,
			aggregatedText: aggregatedText ?? "",
			command: parsed.command
		};
	} catch (err) {
		const em = err instanceof Error ? err.message : String(err);
		deps.log.warn({
			err,
			sessionKey: ctx.sessionKey,
			command: parsed.command
		}, `Slash command failed: ${em}`);
		return {
			matched: true,
			aggregatedText: `Command error: ${em}`,
			command: parsed.command
		};
	}
}
/**
* Convert a user message into an embedded turn, including the standard memory
* prefetch + background-review nudge wiring used by every direct entry point.
*/
async function runDirectAgentTurn(deps, input) {
	const userPlain = extractAgentUserPlainText(input.userMessage);
	const userMessageForModel = await deps.agentManager.applyMemoryPrefetchToUserMessage(input.userMessage, input.sessionKey);
	const result = await runEmbeddedTurnForSession({
		sessionKey: input.sessionKey,
		runId: crypto.randomUUID(),
		userMessage: userMessageForModel,
		sessionStore: deps.sessionStore,
		agentManager: deps.agentManager,
		modelManager: deps.modelManager,
		getConfig: () => deps.config,
		abortSignal: input.abortSignal,
		beforeTurn: () => deps.agentManager.beginBackgroundReviewUserTurn(input.sessionKey),
		onEvent: input.onEvent
	});
	deps.agentManager.afterAgentTurn(input.sessionKey, userPlain);
	deps.agentManager.scheduleBackgroundReviewAfterUserTurn(input.sessionKey);
	return result;
}
//#endregion
export { hydratePerTurnState, runDirectAgentTurn, tryRunSlashCommand };

//# sourceMappingURL=direct-turn-helpers.js.map