import { __awaiter } from "tslib";
import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
import { resolveChatProvider, validateStaticAgentProviders } from './validate-providers';
const chatProvider = () => ({
    chat: () => __awaiter(void 0, void 0, void 0, function* () { return ({ role: 'assistant', content: '' }); }),
});
const promptOnlyProvider = () => ({
    prompt: () => __awaiter(void 0, void 0, void 0, function* () { return ''; }),
});
/**
 * Minimal in-test registry — implements only what the validation helpers
 * touch (`get`, `names`). Avoids depending on foundation-ai's concrete
 * registry impl, and keeps these tests Node-runnable.
 */
const makeRegistry = (providers) => {
    const map = new Map(Object.entries(providers));
    return {
        get: (name) => map.get(name),
        default: () => map.values().next().value,
        defaultName: () => map.keys().next().value,
        names: () => [...map.keys()],
        getStatus: () => __awaiter(void 0, void 0, void 0, function* () { return null; }),
        listStatuses: () => __awaiter(void 0, void 0, void 0, function* () { return []; }),
    };
};
const specialist = (overrides) => (Object.assign({ name: overrides.name, description: 'test specialist' }, overrides));
// ---------------------------------------------------------------------------
// resolveChatProvider
// ---------------------------------------------------------------------------
const resolve = createLogicSuite('resolveChatProvider');
resolve('returns the provider when the name is registered and has chat()', () => {
    const fast = chatProvider();
    const registry = makeRegistry({ fast });
    assert.is(resolveChatProvider(registry, 'fast', 'A'), fast);
});
resolve('throws on an unknown provider name with the agent name in the message', () => {
    const registry = makeRegistry({ fast: chatProvider() });
    assert.throws(() => resolveChatProvider(registry, 'deep', 'A'), /Agent "A" references unknown provider "deep"/);
});
resolve('throws including the registered names so the misconfiguration is debuggable', () => {
    const registry = makeRegistry({
        fast: chatProvider(),
        deep: chatProvider(),
        cheap: chatProvider(),
    });
    assert.throws(() => resolveChatProvider(registry, 'typo', 'A'), /Registered: fast, deep, cheap/);
});
resolve('throws when the resolved provider does not implement chat()', () => {
    const registry = makeRegistry({ chrome: promptOnlyProvider() });
    assert.throws(() => resolveChatProvider(registry, 'chrome', 'A'), /Agent "A" resolved to provider "chrome" which does not implement chat\(\)/);
});
resolve.run();
// ---------------------------------------------------------------------------
// validateStaticAgentProviders
// ---------------------------------------------------------------------------
const validate = createLogicSuite('validateStaticAgentProviders');
validate('accepts agents with no `provider` field (back-compat path)', () => {
    const registry = makeRegistry({ default: chatProvider() });
    assert.not.throws(() => validateStaticAgentProviders([specialist({ name: 'A' })], registry));
});
validate('accepts agents that name a registered chat-capable provider', () => {
    const registry = makeRegistry({ fast: chatProvider(), deep: chatProvider() });
    assert.not.throws(() => validateStaticAgentProviders([specialist({ name: 'A', provider: 'deep' })], registry));
});
validate('throws when a top-level agent references an unknown provider', () => {
    const registry = makeRegistry({ fast: chatProvider() });
    assert.throws(() => validateStaticAgentProviders([specialist({ name: 'A', provider: 'deep' })], registry), /Agent "A" references unknown provider "deep"/);
});
validate('recurses into subAgents — bad provider on a sub-agent throws', () => {
    const registry = makeRegistry({ fast: chatProvider() });
    const sub = specialist({ name: 'Sub', provider: 'missing' });
    assert.throws(() => validateStaticAgentProviders([specialist({ name: 'A', subAgents: [sub] })], registry), /Agent "Sub" references unknown provider "missing"/);
});
validate('recurses through multiple levels — bad provider on a deeply-nested sub-agent throws', () => {
    const registry = makeRegistry({ fast: chatProvider() });
    const deepest = specialist({ name: 'Deepest', provider: 'missing' });
    const middle = specialist({ name: 'Middle', subAgents: [deepest] });
    assert.throws(() => validateStaticAgentProviders([specialist({ name: 'Top', subAgents: [middle] })], registry), /Agent "Deepest" references unknown provider "missing"/);
});
validate('defers function-form `provider` — it is not invoked at validation time', () => {
    const registry = makeRegistry({ fast: chatProvider() });
    const agent = specialist({
        name: 'A',
        // If validateStaticAgentProviders eagerly resolved this, it would throw
        // here. The contract is that function-form is deferred to the driver's
        // per-turn resolver.
        provider: () => {
            throw new Error('function-form provider should not be invoked at validation time');
        },
    });
    assert.not.throws(() => validateStaticAgentProviders([agent], registry));
});
validate('shared sub-agent across two parents validates cleanly', () => {
    const registry = makeRegistry({ fast: chatProvider() });
    const shared = specialist({ name: 'Shared', provider: 'fast' });
    const parentA = specialist({ name: 'ParentA', subAgents: [shared] });
    const parentB = specialist({ name: 'ParentB', subAgents: [shared] });
    assert.not.throws(() => validateStaticAgentProviders([parentA, parentB], registry));
});
validate.run();
