Files
HarborForge.OpenclawPlugin/plugin/calendar/calendar-bridge.d.ts
zhi 55d7d11a52 feat(plugin): PLG-CAL-001 - define Calendar heartbeat request/response format
- Add plugin/calendar/types.ts: TypeScript interfaces for heartbeat
  request/response (CalendarHeartbeatRequest/Response, CalendarSlotResponse,
  SlotAgentUpdate, all enums: SlotType, SlotStatus, EventType)
- Add plugin/calendar/calendar-bridge.ts: CalendarBridgeClient HTTP client
  with heartbeat(), updateSlot(), updateVirtualSlot(), reportAgentStatus()
- Add plugin/calendar/index.ts: module entry point exporting all public types
- Add docs/PLG-CAL-001-calendar-heartbeat-format.md: full specification
  documenting claw_identifier and agent_id determination, request/response
  shapes, error handling, and endpoint summary
- Update plugin/openclaw.plugin.json: add calendarEnabled,
  calendarHeartbeatIntervalSec, calendarApiKey config options; clarify
  identifier description as claw_identifier

Refs: HarborForge.NEXT_WAVE_DEV_DIRECTION.md §6, BE-AGT-001
2026-04-01 07:51:39 +00:00

124 lines
5.0 KiB
TypeScript

/**
* 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<CalendarHeartbeatResponse | null>;
/**
* 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<boolean>;
/**
* 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<CalendarSlotResponse | null>;
/**
* 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<boolean>;
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<string, unknown>;
logger?: {
debug?: (...args: unknown[]) => void;
};
}, fallbackUrl: string, agentId: string): CalendarBridgeClient;
//# sourceMappingURL=calendar-bridge.d.ts.map