fix: resolve deployment crashes in coordinator and API services
Coordinator: install all dependencies from pyproject.toml instead of hardcoded subset (missing slowapi, anthropic, opentelemetry-*). API: FederationAgentService now gracefully disables when orchestrator URL is not configured instead of throwing and crashing the app. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -44,6 +44,7 @@ export interface AgentCommandResponse {
|
|||||||
export class FederationAgentService {
|
export class FederationAgentService {
|
||||||
private readonly logger = new Logger(FederationAgentService.name);
|
private readonly logger = new Logger(FederationAgentService.name);
|
||||||
private readonly orchestratorUrl: string;
|
private readonly orchestratorUrl: string;
|
||||||
|
private readonly enabled: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly prisma: PrismaService,
|
private readonly prisma: PrismaService,
|
||||||
@@ -60,18 +61,28 @@ export class FederationAgentService {
|
|||||||
const validationResult = validateUrl(url, isDevelopment);
|
const validationResult = validateUrl(url, isDevelopment);
|
||||||
if (!validationResult.valid) {
|
if (!validationResult.valid) {
|
||||||
const errorMessage = validationResult.error ?? "Unknown validation error";
|
const errorMessage = validationResult.error ?? "Unknown validation error";
|
||||||
this.logger.error(`Invalid orchestrator URL: ${errorMessage}`);
|
this.logger.warn(
|
||||||
// Log security event
|
`Federation agent service disabled: ${errorMessage}. Set orchestrator.url to enable.`
|
||||||
|
);
|
||||||
this.auditService.logInvalidOrchestratorUrl(url, errorMessage);
|
this.auditService.logInvalidOrchestratorUrl(url, errorMessage);
|
||||||
throw new Error(errorMessage);
|
this.orchestratorUrl = "";
|
||||||
|
this.enabled = false;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.orchestratorUrl = url;
|
this.orchestratorUrl = url;
|
||||||
|
this.enabled = true;
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
`FederationAgentService initialized with orchestrator URL: ${this.orchestratorUrl}`
|
`FederationAgentService initialized with orchestrator URL: ${this.orchestratorUrl}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private assertEnabled(): void {
|
||||||
|
if (!this.enabled) {
|
||||||
|
throw new Error("Federation agent service is disabled: orchestrator URL not configured");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spawn an agent on a remote federated instance
|
* Spawn an agent on a remote federated instance
|
||||||
* @param workspaceId Workspace ID
|
* @param workspaceId Workspace ID
|
||||||
@@ -84,6 +95,7 @@ export class FederationAgentService {
|
|||||||
connectionId: string,
|
connectionId: string,
|
||||||
payload: SpawnAgentCommandPayload
|
payload: SpawnAgentCommandPayload
|
||||||
): Promise<CommandMessageDetails> {
|
): Promise<CommandMessageDetails> {
|
||||||
|
this.assertEnabled();
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
`Spawning agent on remote instance via connection ${connectionId} for task ${payload.taskId}`
|
`Spawning agent on remote instance via connection ${connectionId} for task ${payload.taskId}`
|
||||||
);
|
);
|
||||||
@@ -126,6 +138,7 @@ export class FederationAgentService {
|
|||||||
connectionId: string,
|
connectionId: string,
|
||||||
agentId: string
|
agentId: string
|
||||||
): Promise<CommandMessageDetails> {
|
): Promise<CommandMessageDetails> {
|
||||||
|
this.assertEnabled();
|
||||||
this.logger.log(`Getting agent status for ${agentId} via connection ${connectionId}`);
|
this.logger.log(`Getting agent status for ${agentId} via connection ${connectionId}`);
|
||||||
|
|
||||||
// Validate connection exists and is active
|
// Validate connection exists and is active
|
||||||
@@ -167,6 +180,7 @@ export class FederationAgentService {
|
|||||||
connectionId: string,
|
connectionId: string,
|
||||||
agentId: string
|
agentId: string
|
||||||
): Promise<CommandMessageDetails> {
|
): Promise<CommandMessageDetails> {
|
||||||
|
this.assertEnabled();
|
||||||
this.logger.log(`Killing agent ${agentId} via connection ${connectionId}`);
|
this.logger.log(`Killing agent ${agentId} via connection ${connectionId}`);
|
||||||
|
|
||||||
// Validate connection exists and is active
|
// Validate connection exists and is active
|
||||||
@@ -208,6 +222,7 @@ export class FederationAgentService {
|
|||||||
commandType: string,
|
commandType: string,
|
||||||
payload: Record<string, unknown>
|
payload: Record<string, unknown>
|
||||||
): Promise<AgentCommandResponse> {
|
): Promise<AgentCommandResponse> {
|
||||||
|
this.assertEnabled();
|
||||||
this.logger.log(`Handling agent command ${commandType} from ${remoteInstanceId}`);
|
this.logger.log(`Handling agent command ${commandType} from ${remoteInstanceId}`);
|
||||||
|
|
||||||
// Verify connection exists for remote instance
|
// Verify connection exists for remote instance
|
||||||
|
|||||||
@@ -15,14 +15,9 @@ COPY pyproject.toml .
|
|||||||
# Create virtual environment and install dependencies
|
# Create virtual environment and install dependencies
|
||||||
RUN python -m venv /opt/venv
|
RUN python -m venv /opt/venv
|
||||||
ENV PATH="/opt/venv/bin:$PATH"
|
ENV PATH="/opt/venv/bin:$PATH"
|
||||||
|
COPY src/ ./src/
|
||||||
RUN pip install --no-cache-dir --upgrade pip && \
|
RUN pip install --no-cache-dir --upgrade pip && \
|
||||||
pip install --no-cache-dir hatchling && \
|
pip install --no-cache-dir .
|
||||||
pip install --no-cache-dir \
|
|
||||||
fastapi>=0.109.0 \
|
|
||||||
uvicorn[standard]>=0.27.0 \
|
|
||||||
pydantic>=2.5.0 \
|
|
||||||
pydantic-settings>=2.1.0 \
|
|
||||||
python-dotenv>=1.0.0
|
|
||||||
|
|
||||||
# Production stage
|
# Production stage
|
||||||
FROM python:3.11-slim
|
FROM python:3.11-slim
|
||||||
|
|||||||
Reference in New Issue
Block a user