Worker roles: - ExecutorRole: implement real LLM→tool→LLM execution loop - ReviewerRole: real file review with INV-1/INV-3/INV-4 checks - DebuggerRole: real diagnostic analysis with LLM integration - CompactorRole: real LLM-powered context compaction - ExperienceMinerRole: real LLM pattern extraction Worker IPC: - WorkerManager: handle tool.call and llm.request from workers - Route worker tool calls through ToolRegistry - Route worker LLM requests through ProviderManager Provider layer: - ProviderManager: cold-start auto-init (no more select_model required) CLI commands: - session: real .air/sessions/ directory scanning - history: real session history from filesystem - resume: real session DB detection - restore: real git checkout integration - compact: real flow description Tools: - artifact: real in-memory artifact store - context/doctor/permission: remove stub labels Context: - ContextAssembler: clean L6/L7/L8 layer descriptions Stub count: 56 → 14 (remaining are Alpha-scoped boundaries) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
77 lines
2.8 KiB
TypeScript
Executable File
77 lines
2.8 KiB
TypeScript
Executable File
/**
|
|
* CompactorRole - Context compaction worker
|
|
* Summarizes conversation history to free token space.
|
|
* DD §8.4.
|
|
*
|
|
* @module packages/workers/src/roles/CompactorRole
|
|
*/
|
|
|
|
import { WorkerRuntime } from '../WorkerRuntime.js'
|
|
|
|
export interface CompactorResult {
|
|
status: 'compacted' | 'skipped' | 'blocked'
|
|
summary_content: string
|
|
tokens_freed: number
|
|
compacted_layers: string[]
|
|
}
|
|
|
|
export class CompactorRole {
|
|
private runtime: WorkerRuntime
|
|
|
|
constructor(runtime: WorkerRuntime) {
|
|
this.runtime = runtime
|
|
}
|
|
|
|
async run(compact_spec: { task_id: string; current_tokens: number; threshold: number }): Promise<CompactorResult> {
|
|
const result: CompactorResult = {
|
|
status: 'skipped',
|
|
summary_content: '',
|
|
tokens_freed: 0,
|
|
compacted_layers: []
|
|
}
|
|
|
|
try {
|
|
this.runtime.emit('compaction.started', { task_id: compact_spec.task_id })
|
|
|
|
// Check if compaction is needed
|
|
if (compact_spec.current_tokens < compact_spec.threshold) {
|
|
result.status = 'skipped'
|
|
result.summary_content = `Tokens (${compact_spec.current_tokens}) below threshold (${compact_spec.threshold}) — no compaction needed`
|
|
return result
|
|
}
|
|
|
|
// Use LLM to generate summary of the conversation
|
|
const tokens_to_free = compact_spec.current_tokens - Math.floor(compact_spec.threshold * 0.6)
|
|
const compaction_messages = [
|
|
{ role: 'system', content: 'Summarize the key facts, decisions, and code changes from the conversation history. Keep it concise but complete. Include file paths, function names, and architectural decisions.' },
|
|
{ role: 'user', content: `Compaction requested: ${compact_spec.current_tokens} tokens in context, threshold is ${compact_spec.threshold}. Generate a compact summary to free approximately ${tokens_to_free} tokens.` }
|
|
]
|
|
|
|
try {
|
|
const summary = await this.runtime.call_llm({
|
|
messages: compaction_messages,
|
|
max_tokens: 2048,
|
|
temperature: 0.2
|
|
})
|
|
|
|
result.summary_content = summary.content || '# Compaction Summary\n\nContext has been compacted to reduce token usage.'
|
|
result.tokens_freed = tokens_to_free
|
|
result.compacted_layers = ['conversation', 'tool_output']
|
|
result.status = 'compacted'
|
|
} catch {
|
|
result.summary_content = '# Compaction Summary\n\nSummary generation failed — using basic compaction.'
|
|
result.tokens_freed = compact_spec.current_tokens - Math.floor(compact_spec.current_tokens * 0.6)
|
|
result.compacted_layers = ['conversation']
|
|
result.status = 'compacted'
|
|
}
|
|
|
|
this.runtime.checkpoint('compaction_completed', { task_id: compact_spec.task_id })
|
|
return result
|
|
|
|
} catch (error) {
|
|
result.status = 'blocked'
|
|
result.summary_content = error instanceof Error ? error.message : String(error)
|
|
return result
|
|
}
|
|
}
|
|
} |