/**
 * Shared test fixtures for the Task 10 integration coverage matrix.
 *
 * Factors out the `AgentManager` + `SessionStore` + `WorkspaceBackendRegistry`
 * + `SessionSummaryMaterializer` + `DefaultCapacityValidator` wiring that
 * every integration test rebuilds. Keeping this in an underscore-prefixed
 * internal module (Convention #4: `_fixtures.ts` does not bleed into any
 * barrel) lets the 11 integration files focus on invariant assertions rather
 * than boilerplate.
 *
 * DO NOT export from `src/session/index.ts` or any other public barrel.
 * This module is test-only and has no runtime consumers.
 */
import { vi } from 'vitest';
import { EMPTY_TOKEN_USAGE } from '../../../constants/limits.js';
import { AgentManager } from '../../../manager/agent/lifecycle.js';
import { ThreadManager } from '../../../manager/thread/lifecycle.js';
import { AgentRegistry } from '../../../registry/agent/definitions.js';
import { InMemorySessionStore } from '../../../store/session/memory.js';
import { InMemoryThreadStore } from '../../../store/thread/memory.js';
import { createAssistantMessage } from '../../../types/message/index.js';
import { ZERO_COST } from '../../../utils/cost.js';
import { DefaultCapacityValidator } from '../../handoff/capacity.js';
import { SessionSummaryMaterializer } from '../../summary/materialize.js';
import { GitWorktreeDriver } from '../../workspace/git-worktree.js';
import { WorkspaceBackendRegistry } from '../../workspace/registry.js';
export const DEFAULT_TENANT = 'tnt_alpha';
export const OTHER_TENANT = 'tnt_beta';
export function stubLogger() {
    return {
        debug: vi.fn(),
        info: vi.fn(),
        warn: vi.fn(),
        error: vi.fn(),
        child() {
            return stubLogger();
        },
    };
}
export function okExec(stdout = '', stderr = '') {
    return { stdout, stderr };
}
export function userActor(userId, tenantId = DEFAULT_TENANT) {
    return { kind: 'user', userId: userId, tenantId };
}
export function agentActor(agentId, tenantId = DEFAULT_TENANT) {
    return { kind: 'agent', agentId: agentId, tenantId };
}
const BASE_CAPABILITIES = {
    supportsTools: false,
    supportsStreaming: false,
    supportsConcurrency: false,
    supportsSubAgents: false,
};
/**
 * Builds a minimal {@link Agent} whose `run` produces a deterministic
 * assistant message. Tests that need custom output shape override via
 * {@link buildAgentCustom}.
 */
export function buildAgent(id, result = 'child did the work') {
    return {
        type: 'reactive',
        metadata: {
            type: 'reactive',
            id,
            name: id,
            version: '1.0.0',
            category: 'test',
            description: id,
            capabilities: BASE_CAPABILITIES,
        },
        run: async (_input, _config) => ({
            runId: `run_${id}_result`,
            status: 'completed',
            usage: { ...EMPTY_TOKEN_USAGE },
            cost: { ...ZERO_COST },
            iterations: 1,
            durationMs: 1,
            messages: [createAssistantMessage(result)],
            result,
        }),
        cancel: async () => undefined,
        getCapabilities: () => BASE_CAPABILITIES,
    };
}
/**
 * Builds an agent with a caller-supplied `run`. Useful for tests that need
 * to simulate failures or spawn cascading agents.
 */
export function buildAgentCustom(id, run) {
    return {
        type: 'reactive',
        metadata: {
            type: 'reactive',
            id,
            name: id,
            version: '1.0.0',
            category: 'test',
            description: id,
            capabilities: BASE_CAPABILITIES,
        },
        run,
        cancel: async () => undefined,
        getCapabilities: () => BASE_CAPABILITIES,
    };
}
export function buildDefinition(agent) {
    return {
        info: {
            id: agent.metadata.id,
            name: agent.metadata.name,
            version: agent.metadata.version,
            category: agent.metadata.category,
            description: agent.metadata.description,
            tools: [],
            defaults: { model: 'test', tokenBudget: 1_000 },
        },
        typedAgent: agent,
    };
}
/**
 * Builds a full AgentManager + SessionStore + Materializer harness wired with
 * real components (not mocks). The `GitWorktreeDriver` uses a stubbed
 * `execFile` that returns empty stdout by default — tests exercising failure
 * modes inject a real {@link ExecFile}.
 */
export function buildHarness(options = {}) {
    const tenantId = options.tenantId ?? DEFAULT_TENANT;
    const store = new InMemorySessionStore();
    const threadStore = new InMemoryThreadStore();
    const workspaceRegistry = new WorkspaceBackendRegistry();
    if (options.withWorktreeDriver !== false) {
        const exec = options.execFile ?? (async () => okExec());
        const driver = new GitWorktreeDriver({
            repoRoot: '/repo',
            logger: stubLogger(),
            execFile: exec,
        });
        workspaceRegistry.register(driver);
    }
    let counter = 0;
    const generateSummaryId = options.summaryIdGenerator ?? (() => `sum_test_${++counter}`);
    const materializer = new SessionSummaryMaterializer({
        store,
        generateSummaryId,
    });
    const capacity = new DefaultCapacityValidator(store);
    const threadManager = new ThreadManager({ threadStore, sessionStore: store });
    const registry = new AgentRegistry();
    const manager = new AgentManager(registry, undefined, {
        sessionStore: store,
        summaryMaterializer: materializer,
        workspaceRegistry,
        capacity,
        threadManager,
    });
    return {
        store,
        threadStore,
        threadManager,
        registry,
        manager,
        materializer,
        workspaceRegistry,
        capacity,
        tenantId,
    };
}
/**
 * Seeds a Tenant → Project → Thread → Session quadruple and flips the session
 * into `active` so it is a legal spawn parent. Returns the project, thread,
 * and active session for the caller to drive spawns against.
 */
export async function seedActiveParent(harness, options) {
    const tenantId = options?.tenantId ?? harness.tenantId;
    const actor = options?.actor ?? userActor('usr_root', tenantId);
    const project = await harness.store.createProject({ tenantId, name: options?.projectName ?? 'integration-project' }, tenantId);
    const thread = await harness.threadStore.createThread({ projectId: project.id, title: options?.threadTitle ?? 'default' }, tenantId);
    const session = await harness.store.createSession({ threadId: thread.id, projectId: project.id, currentActor: actor }, tenantId);
    await harness.store.updateSession({ ...session, status: 'active' }, tenantId);
    return { project, thread, session, actor };
}
/**
 * Constructs a fully populated {@link AgentTaskContext} bound to the supplied
 * parent session + actor. Tests override individual fields (depth, budget)
 * by merging.
 */
export function buildTaskContext(params) {
    return {
        parentRunId: params.parentRunId ?? 'run_parent',
        parentAgentId: 'supervisor',
        parentAbortController: new AbortController(),
        depth: params.depth ?? 0,
        budgetTracker: {
            total: params.budget ?? 100_000,
            remaining: params.budget ?? 100_000,
        },
        tenantId: params.tenantId,
        threadId: params.threadId,
        sessionId: params.sessionId,
        projectId: params.projectId,
        parentActor: params.parentActor,
    };
}
export function buildSendMessageOptions(params) {
    return {
        agentId: params.agentId,
        input: { messages: [], workingDirectory: '/tmp' },
        parentSessionId: params.parentSessionId,
        tenantId: params.tenantId,
        projectId: params.projectId,
        parentActor: params.parentActor,
    };
}
//# sourceMappingURL=_fixtures.js.map