/** * HarborForge Calendar Bridge Client * * PLG-CAL-001: Handles HTTP communication between the OpenClaw plugin * and the HarborForge backend for Calendar heartbeat and slot updates. * * Request authentication: * • X-Agent-ID header — set to process.env.AGENT_ID * • X-Claw-Identifier header — set to the server's claw_identifier * (from plugin config or hostname fallback) * * Base URL: * Derived from plugin config: backendUrl + "/calendar" * Default backendUrl: "https://monitor.hangman-lab.top" * * Endpoints used: * GET /calendar/agent/heartbeat — fetch pending slots * PATCH /calendar/slots/{id}/agent-update — update real slot status * PATCH /calendar/slots/virtual/{vid}/agent-update — update virtual slot status * * References: * • NEXT_WAVE_DEV_DIRECTION.md §6.1 (Heartbeat flow) * • HarborForge.Backend/app/services/agent_heartbeat.py (BE-AGT-001) */ import { CalendarHeartbeatResponse, CalendarSlotResponse, SlotAgentUpdate } from './types'; export interface CalendarBridgeConfig { /** HarborForge backend base URL (e.g. "https://monitor.hangman-lab.top") */ backendUrl: string; /** Server/claw identifier (from plugin config or hostname fallback) */ clawIdentifier: string; /** OpenClaw agent ID ($AGENT_ID), set at agent startup */ agentId: string; /** HTTP request timeout in milliseconds (default: 5000) */ timeoutMs?: number; } export declare class CalendarBridgeClient { private baseUrl; private config; private timeoutMs; constructor(config: CalendarBridgeConfig); /** * Fetch today's pending calendar slots for this agent. * * Heartbeat flow (§6.1): * 1. Plugin sends heartbeat every minute * 2. Backend returns slots where status is NotStarted or Deferred * AND scheduled_at <= now * 3. Plugin selects highest-priority slot (if any) * 4. For remaining slots, plugin sets status = Deferred + priority += 1 * * @returns CalendarHeartbeatResponse or null if the backend is unreachable */ heartbeat(): Promise; /** * Update a real (materialized) slot's status after agent execution. * * Used by the plugin to report: * - Slot attended (attended=true, started_at=now, status=Ongoing) * - Slot finished (actual_duration set, status=Finished) * - Slot deferred (status=Deferred, priority += 1) * - Slot aborted (status=Aborted) * * @param slotId Real slot DB id * @param update Status update payload * @returns true on success, false on failure */ updateSlot(slotId: number, update: SlotAgentUpdate): Promise; /** * Update a virtual (plan-generated) slot's status after agent execution. * * When updating a virtual slot, the backend first materializes it * (creates a real TimeSlot row), then applies the update. * The returned slot will have a real id on subsequent calls. * * @param virtualId Virtual slot id in format "plan-{plan_id}-{date}" * @param update Status update payload * @returns Updated CalendarSlotResponse on success, null on failure */ updateVirtualSlot(virtualId: string, update: SlotAgentUpdate): Promise; /** * Report the agent's current runtime status to HarborForge. * * Used to push agent status transitions: * idle → busy / on_call (when starting a slot) * busy / on_call → idle (when finishing a slot) * → exhausted (on rate-limit / billing error, with recovery_at) * → offline (after 2 min with no heartbeat) * * @param status New agent status * @param recoveryAt ISO timestamp for expected Exhausted recovery (optional) * @param exhaustReason "rate_limit" | "billing" (required if status=exhausted) */ reportAgentStatus(params: { status: 'idle' | 'on_call' | 'busy' | 'exhausted' | 'offline'; recoveryAt?: string; exhaustReason?: 'rate_limit' | 'billing'; }): Promise; private fetchJson; private postBoolean; } export interface CalendarPluginConfig { /** Backend URL for calendar API (overrides monitor backendUrl) */ calendarBackendUrl?: string; /** Server identifier (overrides auto-detected hostname) */ identifier?: string; /** Agent ID from OpenClaw ($AGENT_ID) */ agentId: string; /** HTTP timeout for calendar API calls (default: 5000) */ timeoutMs?: number; } /** * Build a CalendarBridgeClient from the OpenClaw plugin API context. * * @param api OpenClaw plugin API (register() receives this) * @param fallbackUrl Fallback backend URL if not configured * @param agentId $AGENT_ID from OpenClaw environment */ export declare function createCalendarBridgeClient(api: { config?: Record; logger?: { debug?: (...args: unknown[]) => void; }; }, fallbackUrl: string, agentId: string): CalendarBridgeClient; //# sourceMappingURL=calendar-bridge.d.ts.map