/** * HTTP-backed store adapter for Medicine Wheel MCP Server * * When MW_API_URL is set, delegates storage operations to the server's * REST API instead of local JSONL files. This enables the MCP tools * to read/write the same relational state the server holds. * * Opt-in: only used when MW_API_URL is explicitly set. * Default behavior (MW_DATA_DIR / local JSONL) is preserved. */ import { type WebHubHold } from './relational-web.js'; import type { NodeFilters } from './types.js'; interface StoredNode { id: string; type: string; name: string; description?: string; direction?: string; metadata?: Record; created_at: string; updated_at: string; } interface StoredEdge { id?: string; from_id: string; to_id: string; relationship_type: string; strength: number; ceremony_honored: boolean; ceremony_id?: string; obligations: string[]; /** Why the two are related, in the words of whoever wove the relation. */ description?: string; created_at: string; } interface StoredCeremony { id: string; type: string; direction: string; participants: string[]; medicines_used: string[]; intentions: string[]; timestamp: string; research_context?: string; relations_honored?: string[]; episode_path?: string; episode_number?: number; circle_id?: string; subject_id?: string; closes?: string; source?: string; } interface StoredBeat { id: string; direction: string; title: string; description: string; prose?: string; ceremonies: string[]; learnings: string[]; timestamp: string; act: number; relations_honored: string[]; cycle_id?: string; parent_beat_id?: string; sub_beats?: string[]; origin?: { producer: string; source_ref?: string; method?: string; }; } interface StoredCycle { id: string; research_question: string; current_direction: string; start_date: string; beats?: string[]; ceremonies_conducted: number; relations_mapped: number; wilson_alignment: number; ocap_compliant: boolean; archived?: boolean; } interface StoredChart { id: string; desired_outcome: string; current_reality: string; direction: string; action_steps: any[]; due_date?: string; created_at: string; updated_at: string; phase: string; ceremonies_linked: string[]; wilson_alignment?: number; cycle_id?: string; } interface StoredMmot { id: string; chart_id: string; timestamp: string; step1_expected: string; step1_actual: string; step2_analysis: string; step3_adjustments: string[]; step4_feedback: string; } interface StoredInquiryWeave { id: string; weave: 1; artefact: { id: string; path?: string; [key: string]: unknown; }; issue: string; issue_url?: string; episode: { path: string; number: number; [key: string]: unknown; }; last_sync: { state: 'never-synced' | 'in-sync' | 'stale' | 'episode-copy-diverged'; at?: string; tree_sha256?: string; file_count?: number; bytes_total?: number; [key: string]: unknown; }; source: { package: string; record_path?: string; registered_at: string; updated_at: string; [key: string]: unknown; }; [key: string]: unknown; } interface InquiryWeaveFilters { episode_path?: string; episode_number?: number; issue?: string; artefact?: string; } interface StoredPlanPerspective { id: string; perspective: 1; plan: { session_id: string; plan_path?: string; plan_filename: string; plan_sha256: string; captured_at?: string; [key: string]: unknown; }; narrative: { title: string; body_markdown: string; mia_context?: string; [key: string]: unknown; }; lineage?: { user_inputs_path?: string; input_count?: number; first_input_at?: string; last_input_at?: string; excerpts?: string[]; [key: string]: unknown; }; episodes: { path: string; number?: number; [key: string]: unknown; }[]; source: { package?: string; generator?: { system?: string; agent?: string; model?: string; producer_session_id?: string; [key: string]: unknown; }; registered_at: string; updated_at: string; [key: string]: unknown; }; [key: string]: unknown; } interface PlanPerspectiveFilters { episode_path?: string; session_id?: string; id?: string; } /** Carries the HTTP status so callers can tell "endpoint absent" from "server broke". */ export declare class HttpStoreError extends Error { readonly status?: number; readonly url: string; constructor(message: string, url: string, status?: number); } /** A write that did not land. Kept so a failure survives past the console. */ export interface WriteFailure { operation: string; url: string; message: string; at: string; } export declare class HttpStore { readonly name = "http"; private readonly baseUrl; private readonly failures; private readonly inFlight; constructor(baseUrl: string); /** * Writes keep their statement-call shape — `store.createNode(node)` still * compiles and still returns immediately — but the promise now comes back, * so a caller that awaits learns the truth instead of being told "created" * over a request that 404'd. The internal catch is what keeps a rejection * nobody awaited from taking the server down as an unhandled rejection. */ private track; /** Writes that did not land, oldest first. Non-destructive. */ getWriteFailures(): WriteFailure[]; /** Drain the record — for a caller that has reported the failures onward. */ takeWriteFailures(): WriteFailure[]; /** Wait for every in-flight write to land or fail. Never rejects. */ settleWrites(): Promise; createNode(node: StoredNode): Promise; getNode(id: string): Promise; /** * `?limit=all`, always. * * A bare `GET /api/nodes` returns the provider's default page — 100 rows on a * store of 205 — so this method used to answer "all nodes" with the newest * 100, and `getNode()` above, which reads all and then finds, reported every * node past row 100 as missing. Client-side `.slice(limit)` on top of that was * slicing an already-truncated window. * * The server has understood `?limit=` since 2026-09-03. Older servers reject * it with a 400 naming what they accept, which is loud — and far better than * the silent short read this replaces. */ getAllNodes(limit?: number): Promise; getNodesByType(type: string): Promise; getNodesByDirection(direction: string): Promise; /** * Every supplied filter narrows (AND). Unlike the JSONL twin this pushes the * terms into the query string, so the wheel answers the question rather than * shipping the whole graph for the client to sift — which is what this method * exists to stop doing. * * A server that predates `kind`/`parent_id` answers 400 with an `accepted` * list rather than silently ignoring them, so a filter that arrives at an old * wheel fails loudly instead of returning an unfiltered set the caller * believes was filtered. * * @see mcp/src/jsonl-store.ts — the local twin, same contract * @see app/api/nodes/route.ts — the route that serves these params */ getNodesFiltered(filters: NodeFilters): Promise; searchNodes(query: string, opts?: { type?: string; direction?: string; kind?: string; limit?: number; }): Promise; createEdge(edge: StoredEdge): Promise; /** `?limit=all` for the same reason as `getAllNodes` — the default was 100 of 292. */ getAllEdges(): Promise; getEdgesForNode(nodeId: string): Promise; getRelatedNodeIds(nodeId: string): Promise; updateEdgeCeremony(fromId: string, toId: string, ceremonyId: string): Promise; getRelationalWeb(nodeId: string, depth?: number): Promise<{ nodes: StoredNode[]; edges: StoredEdge[]; hubs: WebHubHold[]; truncated: boolean; capped?: { returned: number; available: number; }; }>; logCeremony(ceremony: StoredCeremony): Promise; getCeremony(id: string): Promise; getAllCeremonies(limit?: number): Promise; getCeremoniesByDirection(direction: string): Promise; getCeremoniesByType(type: string): Promise; /** * Filters combine, and the read is unbounded before they are applied. * * `list_ceremonies` used to pick ONE filter with an if/else-if chain, so * `{ direction: "east", type: "closing" }` sent only the direction and * returned 82 opening ceremonies while echoing `type: "closing"` back as * honored. That is the same shadowing `list_relational_nodes` had removed, in * the tool immediately beside it. */ getCeremoniesFiltered(filters?: { direction?: string; type?: string; episode_path?: string; }): Promise; createBeat(beat: StoredBeat): Promise; getBeat(id: string): Promise; getAllBeats(limit?: number): Promise; getBeatsByDirection(direction: string): Promise; createCycle(cycle: StoredCycle): Promise; private listCycles; getCycle(id: string): Promise; getAllCycles(): Promise<{ active: StoredCycle[]; archived: StoredCycle[]; }>; archiveCycle(id: string): Promise; saveChart(chart: StoredChart): Promise; getChart(id: string): Promise; getAllCharts(direction?: string): Promise; saveMmot(mmot: StoredMmot): Promise; getMmotsByChart(chartId: string): Promise; registerInquiryWeave(record: StoredInquiryWeave): Promise; getInquiryWeave(id: string): Promise; listInquiryWeaves(filters?: InquiryWeaveFilters): Promise; registerPlanPerspective(record: StoredPlanPerspective): Promise; getPlanPerspective(id: string): Promise; listPlanPerspectives(filters?: PlanPerspectiveFilters): Promise; } export declare function getHttpStore(baseUrl: string): HttpStore; export {}; //# sourceMappingURL=http-store.d.ts.map