/** * Live editor-activity feed, exposed as a subscribable MCP resource. * * `get_editor_activity` already reports what the developer did, but only when * the agent remembers to ask, and the piggyback digest on tool responses only * arrives when a tool happens to be called. Between calls — exactly when the * developer is doing something the agent should know about — there is nothing. * * This closes that: the agent subscribes once (`resources/subscribe`) and the * server pushes `notifications/resources/updated` when the developer touches * something. The agent then reads the resource to see what changed. * * The addon pushes each human action over the WebSocket as it happens * (`editor_activity`), so nothing polls in the steady state. The timer is kept * as a fallback for an addon older than that push — it backs off to a slow * heartbeat as soon as the first pushed event arrives, and stops entirely while * nobody is subscribed. */ import type { Server } from '@modelcontextprotocol/sdk/server/index.js'; export declare const ACTIVITY_URI = "godot-mcp://editor/activity"; export interface ActivityEvent { /** * Per-source sequence, not global: the editor's activity log, the runtime * autoload and the debugger watch each number their own. `source` is what * tells the streams apart; only the editor's ids drive the poll cursor. */ id: number; type: string; detail: unknown; /** * `human` — the developer did it in the editor. `agent` — the agent's own * tool call caused it, and is filtered out. `runtime` — the running game * reported it (a scene swap from the autoload, a crash from the debugger). */ source: 'human' | 'agent' | 'runtime' | string; t_ms?: number; } /** Calls get_editor_activity. Returns null when the editor is not connected. */ export type ActivityFetcher = (sinceId: number) => Promise<{ events: ActivityEvent[]; latest_id: number; } | null>; export declare class ActivityFeed { private readonly server; private readonly fetch; private readonly log; private subscribers; private pollTimer; private coalesceTimer; private cursor; private buffered; private pendingNotify; private pushSeen; constructor(server: Server, fetch: ActivityFetcher, log?: (level: string, message: string) => void); subscribe(uri: string): void; unsubscribe(uri: string): void; /** * An event the addon pushed, unsolicited. Same filtering as a polled one: the * agent is told about the developer and about the running game, never about * its own edits. */ push(event: ActivityEvent): void; /** Current buffer, newest last, plus a plain-language summary of it. */ snapshot(): { summary: string; events: ActivityEvent[]; latest_id: number; subscribed: boolean; }; stop(): void; private startPolling; /** Re-arm the timer at whichever interval now applies. */ private restartPolling; private stopPolling; private poll; private scheduleNotify; } /** * Turn a run of raw events into one line of intent. * * "The developer saved 2 scenes and reselected nodes 12 times" is what an agent * can act on; twelve separate `selection` records are what it has to read and * discard. Selection churn in particular is almost all noise — a drag fires it * continuously — so it collapses to a count while the things that change the * project (saves, script edits, reimports, undo) are named individually. * * Deliberately rule-based, not a model call: this runs on every read of the * activity resource and has to be free. */ export declare function summarizeActivity(events: ActivityEvent[]): string; //# sourceMappingURL=activity-feed.d.ts.map