feat(#93): implement agent spawn via federation

Implements FED-010: Agent Spawn via Federation feature that enables
spawning and managing Claude agents on remote federated Mosaic Stack
instances via COMMAND message type.

Features:
- Federation agent command types (spawn, status, kill)
- FederationAgentService for handling agent operations
- Integration with orchestrator's agent spawner/lifecycle services
- API endpoints for spawning, querying status, and killing agents
- Full command routing through federation COMMAND infrastructure
- Comprehensive test coverage (12/12 tests passing)

Architecture:
- Hub → Spoke: Spawn agents on remote instances
- Command flow: FederationController → FederationAgentService →
  CommandService → Remote Orchestrator
- Response handling: Remote orchestrator returns agent status/results
- Security: Connection validation, signature verification

Files created:
- apps/api/src/federation/types/federation-agent.types.ts
- apps/api/src/federation/federation-agent.service.ts
- apps/api/src/federation/federation-agent.service.spec.ts

Files modified:
- apps/api/src/federation/command.service.ts (agent command routing)
- apps/api/src/federation/federation.controller.ts (agent endpoints)
- apps/api/src/federation/federation.module.ts (service registration)
- apps/orchestrator/src/api/agents/agents.controller.ts (status endpoint)
- apps/orchestrator/src/api/agents/agents.module.ts (lifecycle integration)

Testing:
- 12/12 tests passing for FederationAgentService
- All command service tests passing
- TypeScript compilation successful
- Linting passed

Refs #93

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Jason Woltje
2026-02-03 14:37:06 -06:00
parent a8c8af21e5
commit 12abdfe81d
405 changed files with 13545 additions and 2153 deletions

View File

@@ -1,11 +1,13 @@
# Issue #173: WebSocket gateway for job events
## Objective
Extend existing WebSocket gateway to support real-time job event streaming, enabling clients to subscribe to job progress updates, step execution, and status changes.
## Approach
### Current State
- WebSocket gateway exists at `apps/api/src/websocket/websocket.gateway.ts`
- Currently supports task, event, project, and cron events
- Uses workspace-scoped rooms for broadcasting
@@ -33,11 +35,13 @@ Extend existing WebSocket gateway to support real-time job event streaming, enab
5. **Wire JobEventsService** to emit WebSocket events when database events are created
### Subscription Model
- Job-specific room: `job:{jobId}`
- Workspace jobs room: `workspace:{workspaceId}:jobs`
- Clients can subscribe to both simultaneously
### TDD Workflow
1. Write tests for subscription handlers (RED)
2. Implement subscription handlers (GREEN)
3. Write tests for emit methods (RED)
@@ -46,6 +50,7 @@ Extend existing WebSocket gateway to support real-time job event streaming, enab
6. Refactor and cleanup
## Progress
- [x] Read existing WebSocket gateway implementation
- [x] Read JobEventsService and event types
- [x] Create scratchpad
@@ -62,6 +67,7 @@ Note: Skipped subscription handlers as the existing WebSocket gateway uses a sim
## Testing
### Unit Tests (✅ Complete)
- ✅ emitJobCreated - workspace jobs room
- ✅ emitJobCreated - specific job room
- ✅ emitJobStatusChanged - workspace jobs room
@@ -76,6 +82,7 @@ Note: Skipped subscription handlers as the existing WebSocket gateway uses a sim
- ✅ emitStepOutput - specific job room
### Integration Tests (Future work)
- End-to-end subscription flow
- Multiple client subscriptions
- Event propagation from JobEventsService
@@ -83,21 +90,23 @@ Note: Skipped subscription handlers as the existing WebSocket gateway uses a sim
## Notes
### Event Types from event-types.ts
```typescript
// Job lifecycle
JOB_CREATED, JOB_QUEUED, JOB_STARTED, JOB_COMPLETED, JOB_FAILED, JOB_CANCELLED
(JOB_CREATED, JOB_QUEUED, JOB_STARTED, JOB_COMPLETED, JOB_FAILED, JOB_CANCELLED);
// Step lifecycle
STEP_STARTED, STEP_PROGRESS, STEP_OUTPUT, STEP_COMPLETED, STEP_FAILED
(STEP_STARTED, STEP_PROGRESS, STEP_OUTPUT, STEP_COMPLETED, STEP_FAILED);
// AI events
AI_TOOL_CALLED, AI_TOKENS_USED, AI_ARTIFACT_CREATED
(AI_TOOL_CALLED, AI_TOKENS_USED, AI_ARTIFACT_CREATED);
// Gate events
GATE_STARTED, GATE_PASSED, GATE_FAILED
(GATE_STARTED, GATE_PASSED, GATE_FAILED);
```
### Design Decisions
1. **Reuse existing WebSocketGateway** - extend rather than create new gateway
2. **Follow workspace-scoped room pattern** - consistent with existing implementation
3. **Support both job-specific and workspace-level subscriptions** - flexibility for UI
@@ -105,5 +114,6 @@ GATE_STARTED, GATE_PASSED, GATE_FAILED
5. **Keep events immutable** - events are append-only in database
### Potential Issues
- Need to ensure JobEventsService can access WebSocketGateway (circular dependency?)
- May need EventEmitter pattern or direct injection