feat: schedule cache, workflow-aligned prompts, dispatchInbound wakeup
1. ScheduleCache: local cache of today's schedule, synced every 5 min
from HF backend via new getDaySchedule() API
2. Wakeup prompts updated to reference daily-routine skill workflows
(task-handson, plan-schedule, slot-complete)
3. Agent wakeup via dispatchInboundMessageWithDispatcher (in-process)
- Same mechanism as Discord plugin
- Creates unique session per slot: agent:{agentId}:hf-calendar:slot-{slotId}
- No WebSocket, CLI, or cron dependency
- Verified working on test environment
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
118
REFACTOR_PLAN.md
Normal file
118
REFACTOR_PLAN.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# CalendarScheduler Refactor Plan (v2)
|
||||
|
||||
> Updated 2026-04-19 based on architecture discussion with hang
|
||||
|
||||
## Current Issues
|
||||
|
||||
1. `process.env.AGENT_ID` doesn't exist in plugins subprocess — always 'unknown'
|
||||
2. Heartbeat is per-agent but should be per-claw-instance (global)
|
||||
3. Scheduler only handles one agent — should manage all agents on this instance
|
||||
4. wakeAgent used api.spawn (non-existent) → now uses dispatchInboundMessage (verified)
|
||||
|
||||
## Target Design
|
||||
|
||||
### Plugin State
|
||||
|
||||
```typescript
|
||||
// Local schedule cache: { agentId → [slots] }
|
||||
const schedules: Map<string, CalendarSlotResponse[]> = new Map();
|
||||
```
|
||||
|
||||
### Sync Flow (every 5 min)
|
||||
|
||||
```
|
||||
1. GET /calendar/sync?claw_identifier=xxx
|
||||
- First call: server returns full { agentId → [slots] }
|
||||
- Subsequent: server returns diff since last sync
|
||||
2. Update local schedules map
|
||||
3. Scan schedules for due slots:
|
||||
for each agentId in schedules:
|
||||
if has slot where scheduled_at <= now && status == not_started:
|
||||
getAgentStatus(agentId, clawIdentifier) → busy?
|
||||
if not busy → wakeAgent(agentId)
|
||||
```
|
||||
|
||||
### Heartbeat (every 60s)
|
||||
|
||||
Simplified to liveness ping only:
|
||||
```
|
||||
POST /monitor/server/heartbeat
|
||||
claw_identifier: xxx
|
||||
→ server returns empty/ack
|
||||
```
|
||||
|
||||
No slot data in heartbeat response.
|
||||
|
||||
### Wake Flow
|
||||
|
||||
```
|
||||
dispatchInboundMessage:
|
||||
SessionKey: agent:{agentId}:hf-wakeup
|
||||
Body: "You have due slots. Follow the hf-wakeup workflow of skill hf-hangman-lab to proceed. Only reply WAKEUP_OK in this session."
|
||||
|
||||
Agent reads workflow → calls hf tools → sets own status to busy
|
||||
```
|
||||
|
||||
### Agent ID Resolution
|
||||
|
||||
- **Sync**: agentId comes from server response (dict keys)
|
||||
- **Wake**: agentId from local schedules dict key
|
||||
- **Tool calls by agent**: agentId from tool ctx (same as padded-cell)
|
||||
|
||||
## Backend API Changes Needed
|
||||
|
||||
### New: GET /calendar/sync
|
||||
|
||||
```
|
||||
GET /calendar/sync?claw_identifier=xxx
|
||||
Headers: X-Claw-Identifier
|
||||
|
||||
Response (first call):
|
||||
{
|
||||
"full": true,
|
||||
"schedules": {
|
||||
"developer": [slot1, slot2, ...],
|
||||
"operator": [slot3, ...]
|
||||
},
|
||||
"syncToken": "abc123"
|
||||
}
|
||||
|
||||
Response (subsequent, with ?since=abc123):
|
||||
{
|
||||
"full": false,
|
||||
"diff": [
|
||||
{ "op": "add", "agent": "developer", "slot": {...} },
|
||||
{ "op": "update", "agent": "developer", "slotId": 5, "patch": {...} },
|
||||
{ "op": "remove", "agent": "operator", "slotId": 3 }
|
||||
],
|
||||
"syncToken": "def456"
|
||||
}
|
||||
```
|
||||
|
||||
### Existing: POST /calendar/agent/status
|
||||
|
||||
Keep as-is but ensure it accepts agentId + clawIdentifier as params:
|
||||
```
|
||||
POST /calendar/agent/status
|
||||
{ agent_id, claw_identifier, status }
|
||||
```
|
||||
|
||||
## Implementation Order
|
||||
|
||||
1. Backend: Add /calendar/sync endpoint
|
||||
2. Plugin: Replace CalendarBridgeClient single-agent design with multi-agent
|
||||
3. Plugin: Replace CalendarScheduler with new sync+check loop
|
||||
4. Plugin: wakeAgent uses dispatchInboundMessage (done)
|
||||
5. Plugin: Tool handlers get agentId from ctx (like padded-cell)
|
||||
|
||||
## Files to Change
|
||||
|
||||
### Backend (HarborForge.Backend)
|
||||
- New route: `/calendar/sync`
|
||||
- New service: schedule diff tracking per claw_identifier
|
||||
|
||||
### Plugin
|
||||
- `plugin/calendar/calendar-bridge.ts` — remove agentId binding, add sync()
|
||||
- `plugin/calendar/scheduler.ts` — rewrite to multi-agent sync+check
|
||||
- `plugin/calendar/schedule-cache.ts` — already exists, adapt to multi-agent
|
||||
- `plugin/index.ts` — update wakeAgent, getAgentStatus to accept agentId
|
||||
Reference in New Issue
Block a user