chore: merge main into cw/small-change-flow
Integrates main branch changes (headquarters dashboard, task retry count, agent prompt persistence, remote sync improvements) with the initiative's errand agent feature. Both features coexist in the merged result. Key resolutions: - Schema: take main's errands table (nullable projectId, no conflictFiles, with errandsRelations); migrate to 0035_faulty_human_fly - Router: keep both errandProcedures and headquartersProcedures - Errand prompt: take main's simpler version (no question-asking flow) - Manager: take main's status check (running|idle only, no waiting_for_input) - Tests: update to match removed conflictFiles field and undefined vs null
This commit is contained in:
@@ -21,6 +21,7 @@ import type { RetryPolicy, AgentError } from './retry-policy.js';
|
||||
import { AgentExhaustedError, AgentFailureError } from './retry-policy.js';
|
||||
import type { AgentErrorAnalyzer } from './error-analyzer.js';
|
||||
import type { CleanupStrategy, AgentInfo } from './cleanup-strategy.js';
|
||||
import type { EventBus, AgentAccountSwitchedEvent } from '../../events/types.js';
|
||||
|
||||
const log = createModuleLogger('lifecycle-controller');
|
||||
|
||||
@@ -48,6 +49,7 @@ export class AgentLifecycleController {
|
||||
private cleanupStrategy: CleanupStrategy,
|
||||
private accountRepository?: AccountRepository,
|
||||
private debug: boolean = false,
|
||||
private eventBus?: EventBus,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -304,7 +306,7 @@ export class AgentLifecycleController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle account exhaustion by marking account as exhausted.
|
||||
* Handle account exhaustion by marking account as exhausted and emitting account_switched event.
|
||||
*/
|
||||
private async handleAccountExhaustion(agentId: string): Promise<void> {
|
||||
if (!this.accountRepository) {
|
||||
@@ -319,15 +321,34 @@ export class AgentLifecycleController {
|
||||
return;
|
||||
}
|
||||
|
||||
const previousAccountId = agent.accountId;
|
||||
|
||||
// Mark account as exhausted for 1 hour
|
||||
const exhaustedUntil = new Date(Date.now() + 60 * 60 * 1000);
|
||||
await this.accountRepository.markExhausted(agent.accountId, exhaustedUntil);
|
||||
await this.accountRepository.markExhausted(previousAccountId, exhaustedUntil);
|
||||
|
||||
log.info({
|
||||
agentId,
|
||||
accountId: agent.accountId,
|
||||
accountId: previousAccountId,
|
||||
exhaustedUntil
|
||||
}, 'marked account as exhausted due to usage limits');
|
||||
|
||||
// Find the next available account and emit account_switched event
|
||||
const newAccount = await this.accountRepository.findNextAvailable(agent.provider ?? 'claude');
|
||||
if (newAccount && this.eventBus) {
|
||||
const event: AgentAccountSwitchedEvent = {
|
||||
type: 'agent:account_switched',
|
||||
timestamp: new Date(),
|
||||
payload: {
|
||||
agentId,
|
||||
name: agent.name,
|
||||
previousAccountId,
|
||||
newAccountId: newAccount.id,
|
||||
reason: 'account_exhausted',
|
||||
},
|
||||
};
|
||||
this.eventBus.emit(event);
|
||||
}
|
||||
} catch (error) {
|
||||
log.warn({
|
||||
agentId,
|
||||
@@ -353,6 +374,7 @@ export class AgentLifecycleController {
|
||||
status: agent.status,
|
||||
initiativeId: agent.initiativeId,
|
||||
worktreeId: agent.worktreeId,
|
||||
exitCode: agent.exitCode ?? null,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user