feat(config): add heartbeat interval configuration with default 30 minutes
feat(state): migrate state file from workspace root to state directory
feat(channels): skip internal channels in outbound dispatcher
feat(agent): record last active channel for heartbeat context
refactor(subagent): use configurable default model instead of provider default
1. Remove duplicate ToolResult definition in heartbeat package
- Import tools.ToolResult instead of local definition
- Add nil check for handler before execution
2. Fix SpawnTool to return AsyncResult and implement AsyncTool
- Add callback field and SetCallback method
- Return AsyncResult instead of NewToolResult
3. Add context cancellation support to SubagentManager
- Check ctx.Done() before and during task execution
- Set task status to "cancelled" on cancellation
- Call callback with result on completion
4. Fix data race window in CronTool.addJob
- Use Lock instead of RLock for channel/chatID access
- Ensure consistent snapshot during job creation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Created new SubagentTool for synchronous subagent execution:
- Implements Tool interface with Name(), Description(), Parameters(), SetContext(), Execute()
- Returns ToolResult with ForUser (summary), ForLLM (full details), Silent=false, Async=false
- Registered in AgentLoop with context support
- Comprehensive test file subagent_tool_test.go with 9 passing tests
Acceptance criteria met:
- ForUser contains subagent output summary (truncated to 500 chars)
- ForLLM contains full execution details with label and result
- Typecheck passes (go build ./... succeeds)
- go test ./pkg/tools -run TestSubagentTool passes (all 9 tests pass)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>