@agentics.org/sparc2
Version:
SPARC 2.0 - Autonomous Vector Coding Agent + MCP. SPARC 2.0, vectorized AI code analysis, is an intelligent coding agent framework built to automate and streamline software development. It combines secure execution environments, and version control into a
151 lines (127 loc) • 4.96 kB
text/typescript
/**
* Agent Configuration Parser
* Parses TOML configuration files for the agent framework
*/
import { parse } from "https://deno.land/std@0.203.0/toml/mod.ts";
import { logMessage } from "../../logger.ts";
import { AgentConfig, AgentFlow, AgentStep, RawAgentConfig } from "../types.ts";
import { ProviderFactory } from "../providers/provider-factory.ts";
/**
* Parse a TOML configuration file for agent configuration
* @param configPath Path to the TOML configuration file
* @returns Parsed agent configuration
*/
export async function parseAgentConfig(configPath: string): Promise<AgentConfig> {
try {
// Read the TOML file
const tomlContent = await Deno.readTextFile(configPath);
// Parse the TOML content
const parsedConfig = parse(tomlContent) as Record<string, unknown>;
// Validate the parsed config has the required structure
if (!parsedConfig.agent || typeof parsedConfig.agent !== "object") {
throw new Error("Missing or invalid 'agent' section in configuration");
}
// Convert to RawAgentConfig with proper type checking
const config: RawAgentConfig = {
agent: parsedConfig.agent as RawAgentConfig["agent"],
providers: (parsedConfig.providers as Record<string, any>) || {},
flows: (parsedConfig.flows as Record<string, any>) || {},
};
// Process the configuration (resolve variables, etc.)
return processAgentConfig(config);
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : String(error);
await logMessage("error", "Failed to parse agent configuration", { error: errorMessage });
throw error;
}
}
/**
* Process a raw agent configuration
* @param config Raw agent configuration from TOML
* @returns Processed agent configuration
*/
function processAgentConfig(config: RawAgentConfig): AgentConfig {
// Create provider instances
const providers: Record<string, any> = {};
const factory = new ProviderFactory();
for (const [name, providerConfig] of Object.entries(config.providers || {})) {
switch (providerConfig.type) {
case "openai":
providers[name] = ProviderFactory.createOpenAIProvider(name, {
apiKeyEnv: providerConfig.api_key_env,
defaultModel: providerConfig.default_model,
});
break;
case "openrouter":
providers[name] = ProviderFactory.createOpenRouterProvider(name, {
apiKeyEnv: providerConfig.api_key_env,
defaultModel: providerConfig.default_model,
});
break;
case "mock":
providers[name] = ProviderFactory.createMockProvider(name, {
defaultModel: providerConfig.default_model,
mockResponses: providerConfig.mock_responses,
});
break;
default:
throw new Error(`Unknown provider type: ${providerConfig.type}`);
}
}
// Process flows
const flows: Record<string, AgentFlow> = {};
for (const [name, flowConfig] of Object.entries(config.flows || {})) {
if (typeof flowConfig !== "object" || flowConfig === null) {
throw new Error(`Invalid flow configuration for ${name}`);
}
const steps: Record<string, AgentStep> = {};
const flowSteps = (flowConfig as any).steps || {};
for (const [stepName, stepConfig] of Object.entries(flowSteps)) {
if (typeof stepConfig !== "object" || stepConfig === null) {
throw new Error(`Invalid step configuration for ${stepName}`);
}
// Resolve provider reference
const providerName = (stepConfig as any).provider;
const provider = providers[providerName];
if (!provider) {
throw new Error(`Provider not found: ${providerName}`);
}
// Resolve model reference (if it contains a variable)
let model = (stepConfig as any).model;
if (model && typeof model === "string" && model.startsWith("${") && model.endsWith("}")) {
const path = model.slice(2, -1).split(".");
let value: any = config;
for (const key of path) {
value = value[key];
if (value === undefined) {
throw new Error(`Variable not found: ${model}`);
}
}
model = value;
}
steps[stepName] = {
name: stepName,
provider: provider,
model: model,
description: (stepConfig as any).description,
systemPrompt: (stepConfig as any).system_prompt,
useAssistant: (stepConfig as any).use_assistant || false,
assistantInstructions: (stepConfig as any).assistant_instructions,
tools: (stepConfig as any).tools || [],
};
}
flows[name] = {
name,
description: (flowConfig as any).description,
steps,
transitions: (flowConfig as any).transitions || {},
};
}
return {
name: config.agent.name,
description: config.agent.description,
defaultFlow: config.agent.default_flow,
providers,
flows,
};
}