feat: close full execution chain — MainAgent→Scheduler→Worker→LLM→Tool→File

Verified end-to-end: user types task → file created by AI.

Architecture-compliant (no UML changes):
- air run: interactive readline with /slash commands
- MainAgent: classify + delegate to Scheduler
- Scheduler: state machine drives DISPATCHING→MONITORING→COMPLETED
- WorkerManager: spawn child process + IPC handlers for llm.request/tool.call
- Worker main.ts: routes llm.response to WorkerRuntime.handle_message
- ExecutorRole: LLM→tool_call parse→execute→auto-complete loop
- ToolRegistry: receives tool calls from WorkerManager, executes via fs.write/etc.
- File path resolution: project_root from RuntimeApp config

Key fixes:
- Worker main.ts: add llm.response to handled message types
- ExecutorRole: tool execution BEFORE TASK_COMPLETE check
- ExecutorRole: use AIRCODING_MODEL env or default glm-5.1 for LLM calls
- RuntimeApp: wire EventStore with real DB, MigrationRunner with exec()
- Scheduler: task status transitions (pending→running→completed)
- Scheduler: MONITORING event loop delay for worker completion

Tested: MainAgent→Scheduler→Worker→LLM→Tool→File 
tsc: 0 errors. E2E: 13/13 gates.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
AirCoding
2026-06-05 14:44:07 +08:00
parent 56a1dd0a7b
commit 2ef0af6a55
5 changed files with 151 additions and 68 deletions

View File

@@ -87,8 +87,13 @@ export class WorkerManager {
}
// Spawn worker process using Bun
// Worker must run from AirCoding repo root so Bun can resolve modules
const repo_root = process.env.AIRCODING_REPO_ROOT || config.project_root
const bun_path = this.find_bun()
const child = spawn(bun_path, ['run', config.entrypoint], {
const entrypoint = config.entrypoint.startsWith('/') ? config.entrypoint
: `${repo_root}/${config.entrypoint.replace(/^\.\//, '')}`
const child = spawn(bun_path, ['run', entrypoint], {
stdio: ['pipe', 'pipe', 'pipe'],
env: {
...process.env,
@@ -97,7 +102,7 @@ export class WorkerManager {
AIRCODING_SESSION_ID: config.session_id,
AIRCODING_PROJECT_ROOT: config.project_root
},
cwd: config.project_root
cwd: repo_root
})
proc.set_process(child)
@@ -186,6 +191,7 @@ export class WorkerManager {
content: result.output || result.error || {}
})
} catch (e: any) {
console.error('[WM] tool.call error:', e.message)
this.send_to_worker(agent_id, 'tool.result', {
call_id,
type: 'error',