Refactor pipeline policies, MCP registry, and unified config/runtime
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { getConfig, loadConfig, type AppConfig } from "../config.js";
|
||||
import { AgentManager, type AgentManagerLimits } from "./manager.js";
|
||||
import {
|
||||
createDefaultResourceProvisioningOrchestrator,
|
||||
@@ -5,143 +6,58 @@ import {
|
||||
type ResourceProvisioningOrchestrator,
|
||||
} from "./provisioning.js";
|
||||
|
||||
const DEFAULT_LIMITS: AgentManagerLimits = {
|
||||
maxConcurrentAgents: 4,
|
||||
maxSessionAgents: 2,
|
||||
maxRecursiveDepth: 3,
|
||||
};
|
||||
|
||||
const DEFAULT_PROVISIONING_CONFIG: BuiltInProvisioningConfigInput = {
|
||||
gitWorktree: {
|
||||
rootDirectory: ".ai_ops/worktrees",
|
||||
baseRef: "HEAD",
|
||||
},
|
||||
portRange: {
|
||||
basePort: 36000,
|
||||
blockSize: 32,
|
||||
blockCount: 512,
|
||||
primaryPortOffset: 0,
|
||||
lockDirectory: ".ai_ops/locks/ports",
|
||||
},
|
||||
};
|
||||
|
||||
function readPositiveIntegerEnv(
|
||||
key: "AGENT_MAX_CONCURRENT" | "AGENT_MAX_SESSION" | "AGENT_MAX_RECURSIVE_DEPTH",
|
||||
fallback: number,
|
||||
): number {
|
||||
const rawValue = process.env[key]?.trim();
|
||||
if (!rawValue) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
const parsed = Number(rawValue);
|
||||
if (!Number.isInteger(parsed) || parsed < 1) {
|
||||
throw new Error(`Environment variable ${key} must be a positive integer.`);
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
function readOptionalStringEnv(key: string, fallback: string): string {
|
||||
const rawValue = process.env[key]?.trim();
|
||||
if (!rawValue) {
|
||||
return fallback;
|
||||
}
|
||||
return rawValue;
|
||||
}
|
||||
|
||||
function readIntegerEnv(
|
||||
key: string,
|
||||
fallback: number,
|
||||
bounds: {
|
||||
min: number;
|
||||
},
|
||||
): number {
|
||||
const rawValue = process.env[key]?.trim();
|
||||
if (!rawValue) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
const parsed = Number(rawValue);
|
||||
if (!Number.isInteger(parsed) || parsed < bounds.min) {
|
||||
throw new Error(`Environment variable ${key} must be an integer >= ${String(bounds.min)}.`);
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
||||
export function loadAgentManagerLimitsFromEnv(): AgentManagerLimits {
|
||||
function toProvisioningConfig(input: Readonly<AppConfig>): BuiltInProvisioningConfigInput {
|
||||
return {
|
||||
maxConcurrentAgents: readPositiveIntegerEnv(
|
||||
"AGENT_MAX_CONCURRENT",
|
||||
DEFAULT_LIMITS.maxConcurrentAgents,
|
||||
),
|
||||
maxSessionAgents: readPositiveIntegerEnv(
|
||||
"AGENT_MAX_SESSION",
|
||||
DEFAULT_LIMITS.maxSessionAgents,
|
||||
),
|
||||
maxRecursiveDepth: readPositiveIntegerEnv(
|
||||
"AGENT_MAX_RECURSIVE_DEPTH",
|
||||
DEFAULT_LIMITS.maxRecursiveDepth,
|
||||
),
|
||||
gitWorktree: {
|
||||
rootDirectory: input.provisioning.gitWorktree.rootDirectory,
|
||||
baseRef: input.provisioning.gitWorktree.baseRef,
|
||||
},
|
||||
portRange: {
|
||||
basePort: input.provisioning.portRange.basePort,
|
||||
blockSize: input.provisioning.portRange.blockSize,
|
||||
blockCount: input.provisioning.portRange.blockCount,
|
||||
primaryPortOffset: input.provisioning.portRange.primaryPortOffset,
|
||||
lockDirectory: input.provisioning.portRange.lockDirectory,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function loadAgentManagerLimitsFromEnv(env: NodeJS.ProcessEnv = process.env): AgentManagerLimits {
|
||||
const config = loadConfig(env);
|
||||
return {
|
||||
maxConcurrentAgents: config.agentManager.maxConcurrentAgents,
|
||||
maxSessionAgents: config.agentManager.maxSessionAgents,
|
||||
maxRecursiveDepth: config.agentManager.maxRecursiveDepth,
|
||||
};
|
||||
}
|
||||
|
||||
let managerSingleton: AgentManager | undefined;
|
||||
let provisioningSingleton: ResourceProvisioningOrchestrator | undefined;
|
||||
|
||||
export function getAgentManager(): AgentManager {
|
||||
export function getAgentManager(config: Readonly<AppConfig> = getConfig()): AgentManager {
|
||||
if (!managerSingleton) {
|
||||
managerSingleton = new AgentManager(loadAgentManagerLimitsFromEnv());
|
||||
managerSingleton = new AgentManager({
|
||||
maxConcurrentAgents: config.agentManager.maxConcurrentAgents,
|
||||
maxSessionAgents: config.agentManager.maxSessionAgents,
|
||||
maxRecursiveDepth: config.agentManager.maxRecursiveDepth,
|
||||
});
|
||||
}
|
||||
|
||||
return managerSingleton;
|
||||
}
|
||||
|
||||
export function loadProvisioningConfigFromEnv(): BuiltInProvisioningConfigInput {
|
||||
return {
|
||||
gitWorktree: {
|
||||
rootDirectory: readOptionalStringEnv(
|
||||
"AGENT_WORKTREE_ROOT",
|
||||
DEFAULT_PROVISIONING_CONFIG.gitWorktree?.rootDirectory ?? ".ai_ops/worktrees",
|
||||
),
|
||||
baseRef: readOptionalStringEnv(
|
||||
"AGENT_WORKTREE_BASE_REF",
|
||||
DEFAULT_PROVISIONING_CONFIG.gitWorktree?.baseRef ?? "HEAD",
|
||||
),
|
||||
},
|
||||
portRange: {
|
||||
basePort: readIntegerEnv(
|
||||
"AGENT_PORT_BASE",
|
||||
DEFAULT_PROVISIONING_CONFIG.portRange?.basePort ?? 36000,
|
||||
{ min: 1 },
|
||||
),
|
||||
blockSize: readIntegerEnv(
|
||||
"AGENT_PORT_BLOCK_SIZE",
|
||||
DEFAULT_PROVISIONING_CONFIG.portRange?.blockSize ?? 32,
|
||||
{ min: 1 },
|
||||
),
|
||||
blockCount: readIntegerEnv(
|
||||
"AGENT_PORT_BLOCK_COUNT",
|
||||
DEFAULT_PROVISIONING_CONFIG.portRange?.blockCount ?? 512,
|
||||
{ min: 1 },
|
||||
),
|
||||
primaryPortOffset: readIntegerEnv(
|
||||
"AGENT_PORT_PRIMARY_OFFSET",
|
||||
DEFAULT_PROVISIONING_CONFIG.portRange?.primaryPortOffset ?? 0,
|
||||
{ min: 0 },
|
||||
),
|
||||
lockDirectory: readOptionalStringEnv(
|
||||
"AGENT_PORT_LOCK_DIR",
|
||||
DEFAULT_PROVISIONING_CONFIG.portRange?.lockDirectory ?? ".ai_ops/locks/ports",
|
||||
),
|
||||
},
|
||||
};
|
||||
export function loadProvisioningConfigFromEnv(
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): BuiltInProvisioningConfigInput {
|
||||
return toProvisioningConfig(loadConfig(env));
|
||||
}
|
||||
|
||||
export function getResourceProvisioningOrchestrator(): ResourceProvisioningOrchestrator {
|
||||
export function getResourceProvisioningOrchestrator(
|
||||
config: Readonly<AppConfig> = getConfig(),
|
||||
): ResourceProvisioningOrchestrator {
|
||||
if (!provisioningSingleton) {
|
||||
provisioningSingleton = createDefaultResourceProvisioningOrchestrator(
|
||||
loadProvisioningConfigFromEnv(),
|
||||
toProvisioningConfig(config),
|
||||
);
|
||||
}
|
||||
return provisioningSingleton;
|
||||
|
||||
Reference in New Issue
Block a user