feat(councils): add deterministic councils engine and council.run tool
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import type { AgentConfigRegistry } from '../../agents/registry.js';
|
||||
import type { Tool, ToolResult } from '../types.js';
|
||||
import { CouncilsOrchestrator, type CouncilsConfig } from '../../councils/orchestrator.js';
|
||||
import { councilRunInputSchema } from '../../councils/types.js';
|
||||
|
||||
interface DelegateRunner {
|
||||
delegate(request: {
|
||||
tier: 'fast' | 'default' | 'complex' | 'local';
|
||||
systemPrompt: string;
|
||||
message: string;
|
||||
maxTokens?: number;
|
||||
}): Promise<{
|
||||
content: string;
|
||||
usage: { inputTokens: number; outputTokens: number };
|
||||
tier: 'fast' | 'default' | 'complex' | 'local';
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface CouncilRunDeps {
|
||||
registry: AgentConfigRegistry;
|
||||
orchestrator: DelegateRunner;
|
||||
config: CouncilsConfig;
|
||||
}
|
||||
|
||||
export function createCouncilRunTool(deps: CouncilRunDeps): Tool {
|
||||
return {
|
||||
name: 'council.run',
|
||||
description:
|
||||
'Run the deterministic dual-council pipeline (D/P groups with bridge-only exchange and meta merge).',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
task: { type: 'string', description: 'Primary task or question to explore' },
|
||||
constraints: { type: 'object', description: 'Optional constraints object (or pass string)' },
|
||||
success_definition: { type: 'string', description: 'What success looks like for this run' },
|
||||
budget: { type: 'object', description: 'Optional budget limits/time/cost constraints' },
|
||||
timebox: { type: 'string', description: 'Optional timebox (e.g. 30m)' },
|
||||
output_format: { type: 'string', description: 'Desired output format' },
|
||||
max_rounds: { type: 'number', description: 'Override configured max rounds (1-6)' },
|
||||
session_id: { type: 'string', description: 'Optional external session/run id' },
|
||||
},
|
||||
required: ['task'],
|
||||
},
|
||||
execute: async (rawArgs: unknown): Promise<ToolResult> => {
|
||||
try {
|
||||
const args = councilRunInputSchema.parse(rawArgs);
|
||||
const runner = new CouncilsOrchestrator({
|
||||
registry: deps.registry,
|
||||
orchestrator: deps.orchestrator,
|
||||
config: deps.config,
|
||||
});
|
||||
const result = await runner.run(args);
|
||||
|
||||
const lines = [
|
||||
`[Council pipeline v${result.pipeline_version}]`,
|
||||
`Stop reason: ${result.stop_snapshot.stop_reason} (round ${result.stop_snapshot.round_reached})`,
|
||||
`D shortlist: ${result.stop_snapshot.final_shortlist_D.join(', ') || 'none'}`,
|
||||
`P shortlist: ${result.stop_snapshot.final_shortlist_P.join(', ') || 'none'}`,
|
||||
`Bridge validated: ${result.stop_snapshot.bridge_validated ? 'yes' : 'no'}`,
|
||||
`Grounding failures: ${result.stop_snapshot.grounding_failures_count}`,
|
||||
'',
|
||||
'Meta selection:',
|
||||
`- Primary: ${result.meta.selected_primary.join(', ') || 'none'}`,
|
||||
`- Secondary: ${result.meta.selected_secondary.join(', ') || 'none'}`,
|
||||
`- Open questions: ${result.meta.open_questions.length}`,
|
||||
`- Next experiments: ${result.meta.next_experiments.length}`,
|
||||
];
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: `${lines.join('\n')}\n\n${JSON.stringify(result)}`,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
output: '',
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user