@medicine-wheel/mcp 4.5.0 → 4.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/http-store.d.ts +47 -9
- package/dist/http-store.d.ts.map +1 -1
- package/dist/http-store.js +220 -90
- package/dist/http-store.js.map +1 -1
- package/dist/jsonl-store.d.ts +10 -2
- package/dist/jsonl-store.d.ts.map +1 -1
- package/dist/jsonl-store.js +22 -13
- package/dist/jsonl-store.js.map +1 -1
- package/dist/store.d.ts +2 -0
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +20 -6
- package/dist/store.js.map +1 -1
- package/dist/tools/integrations.d.ts.map +1 -1
- package/dist/tools/integrations.js +175 -11
- package/dist/tools/integrations.js.map +1 -1
- package/package.json +15 -15
package/dist/http-store.d.ts
CHANGED
|
@@ -50,6 +50,14 @@ interface StoredBeat {
|
|
|
50
50
|
timestamp: string;
|
|
51
51
|
act: number;
|
|
52
52
|
relations_honored: string[];
|
|
53
|
+
cycle_id?: string;
|
|
54
|
+
parent_beat_id?: string;
|
|
55
|
+
sub_beats?: string[];
|
|
56
|
+
origin?: {
|
|
57
|
+
producer: string;
|
|
58
|
+
source_ref?: string;
|
|
59
|
+
method?: string;
|
|
60
|
+
};
|
|
53
61
|
}
|
|
54
62
|
interface StoredCycle {
|
|
55
63
|
id: string;
|
|
@@ -175,11 +183,40 @@ interface PlanPerspectiveFilters {
|
|
|
175
183
|
session_id?: string;
|
|
176
184
|
id?: string;
|
|
177
185
|
}
|
|
186
|
+
/** Carries the HTTP status so callers can tell "endpoint absent" from "server broke". */
|
|
187
|
+
export declare class HttpStoreError extends Error {
|
|
188
|
+
readonly status?: number;
|
|
189
|
+
readonly url: string;
|
|
190
|
+
constructor(message: string, url: string, status?: number);
|
|
191
|
+
}
|
|
192
|
+
/** A write that did not land. Kept so a failure survives past the console. */
|
|
193
|
+
export interface WriteFailure {
|
|
194
|
+
operation: string;
|
|
195
|
+
url: string;
|
|
196
|
+
message: string;
|
|
197
|
+
at: string;
|
|
198
|
+
}
|
|
178
199
|
export declare class HttpStore {
|
|
179
200
|
readonly name = "http";
|
|
180
201
|
private readonly baseUrl;
|
|
202
|
+
private readonly failures;
|
|
203
|
+
private readonly inFlight;
|
|
181
204
|
constructor(baseUrl: string);
|
|
182
|
-
|
|
205
|
+
/**
|
|
206
|
+
* Writes keep their statement-call shape — `store.createNode(node)` still
|
|
207
|
+
* compiles and still returns immediately — but the promise now comes back,
|
|
208
|
+
* so a caller that awaits learns the truth instead of being told "created"
|
|
209
|
+
* over a request that 404'd. The internal catch is what keeps a rejection
|
|
210
|
+
* nobody awaited from taking the server down as an unhandled rejection.
|
|
211
|
+
*/
|
|
212
|
+
private track;
|
|
213
|
+
/** Writes that did not land, oldest first. Non-destructive. */
|
|
214
|
+
getWriteFailures(): WriteFailure[];
|
|
215
|
+
/** Drain the record — for a caller that has reported the failures onward. */
|
|
216
|
+
takeWriteFailures(): WriteFailure[];
|
|
217
|
+
/** Wait for every in-flight write to land or fail. Never rejects. */
|
|
218
|
+
settleWrites(): Promise<void>;
|
|
219
|
+
createNode(node: StoredNode): Promise<void>;
|
|
183
220
|
getNode(id: string): Promise<StoredNode | undefined>;
|
|
184
221
|
getAllNodes(limit?: number): Promise<StoredNode[]>;
|
|
185
222
|
getNodesByType(type: string): Promise<StoredNode[]>;
|
|
@@ -189,35 +226,36 @@ export declare class HttpStore {
|
|
|
189
226
|
direction?: string;
|
|
190
227
|
limit?: number;
|
|
191
228
|
}): Promise<StoredNode[]>;
|
|
192
|
-
createEdge(edge: StoredEdge): void
|
|
229
|
+
createEdge(edge: StoredEdge): Promise<void>;
|
|
193
230
|
getAllEdges(): Promise<StoredEdge[]>;
|
|
194
231
|
getEdgesForNode(nodeId: string): Promise<StoredEdge[]>;
|
|
195
232
|
getRelatedNodeIds(nodeId: string): Promise<string[]>;
|
|
196
|
-
updateEdgeCeremony(fromId: string, toId: string, ceremonyId: string): void
|
|
233
|
+
updateEdgeCeremony(fromId: string, toId: string, ceremonyId: string): Promise<void>;
|
|
197
234
|
getRelationalWeb(nodeId: string, depth?: number): Promise<{
|
|
198
235
|
nodes: StoredNode[];
|
|
199
236
|
edges: StoredEdge[];
|
|
200
237
|
}>;
|
|
201
|
-
logCeremony(ceremony: StoredCeremony): void
|
|
238
|
+
logCeremony(ceremony: StoredCeremony): Promise<void>;
|
|
202
239
|
getCeremony(id: string): Promise<StoredCeremony | undefined>;
|
|
203
240
|
getAllCeremonies(limit?: number): Promise<StoredCeremony[]>;
|
|
204
241
|
getCeremoniesByDirection(direction: string): Promise<StoredCeremony[]>;
|
|
205
242
|
getCeremoniesByType(type: string): Promise<StoredCeremony[]>;
|
|
206
|
-
createBeat(beat: StoredBeat): void
|
|
243
|
+
createBeat(beat: StoredBeat): Promise<void>;
|
|
207
244
|
getBeat(id: string): Promise<StoredBeat | undefined>;
|
|
208
245
|
getAllBeats(limit?: number): Promise<StoredBeat[]>;
|
|
209
246
|
getBeatsByDirection(direction: string): Promise<StoredBeat[]>;
|
|
210
|
-
createCycle(cycle: StoredCycle): void
|
|
247
|
+
createCycle(cycle: StoredCycle): Promise<void>;
|
|
248
|
+
private listCycles;
|
|
211
249
|
getCycle(id: string): Promise<StoredCycle | undefined>;
|
|
212
250
|
getAllCycles(): Promise<{
|
|
213
251
|
active: StoredCycle[];
|
|
214
252
|
archived: StoredCycle[];
|
|
215
253
|
}>;
|
|
216
|
-
archiveCycle(id: string): void
|
|
217
|
-
saveChart(chart: StoredChart): void
|
|
254
|
+
archiveCycle(id: string): Promise<void>;
|
|
255
|
+
saveChart(chart: StoredChart): Promise<void>;
|
|
218
256
|
getChart(id: string): Promise<StoredChart | undefined>;
|
|
219
257
|
getAllCharts(direction?: string): Promise<StoredChart[]>;
|
|
220
|
-
saveMmot(mmot: StoredMmot): void
|
|
258
|
+
saveMmot(mmot: StoredMmot): Promise<void>;
|
|
221
259
|
getMmotsByChart(chartId: string): Promise<StoredMmot[]>;
|
|
222
260
|
registerInquiryWeave(record: StoredInquiryWeave): Promise<void>;
|
|
223
261
|
getInquiryWeave(id: string): Promise<StoredInquiryWeave | undefined>;
|
package/dist/http-store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-store.d.ts","sourceRoot":"","sources":["../src/http-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,UAAU;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,iBAAiB,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"http-store.d.ts","sourceRoot":"","sources":["../src/http-store.ts"],"names":[],"mappings":"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"}
|
package/dist/http-store.js
CHANGED
|
@@ -9,54 +9,183 @@
|
|
|
9
9
|
* Default behavior (MW_DATA_DIR / local JSONL) is preserved.
|
|
10
10
|
*/
|
|
11
11
|
// ── Helpers ──
|
|
12
|
+
/** Carries the HTTP status so callers can tell "endpoint absent" from "server broke". */
|
|
13
|
+
export class HttpStoreError extends Error {
|
|
14
|
+
status;
|
|
15
|
+
url;
|
|
16
|
+
constructor(message, url, status) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.name = 'HttpStoreError';
|
|
19
|
+
this.url = url;
|
|
20
|
+
this.status = status;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
24
|
+
const MAX_TRACKED_FAILURES = 50;
|
|
25
|
+
function requestTimeoutMs() {
|
|
26
|
+
const parsed = Number(process.env.MW_HTTP_TIMEOUT_MS);
|
|
27
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_TIMEOUT_MS;
|
|
28
|
+
}
|
|
29
|
+
function errorMessage(error) {
|
|
30
|
+
return error instanceof Error ? error.message : String(error);
|
|
31
|
+
}
|
|
32
|
+
function snippet(text) {
|
|
33
|
+
const flat = text.replace(/\s+/g, ' ').trim();
|
|
34
|
+
return flat.length > 200 ? `${flat.slice(0, 200)}…` : flat;
|
|
35
|
+
}
|
|
36
|
+
function describeShape(value) {
|
|
37
|
+
if (value === null)
|
|
38
|
+
return 'null';
|
|
39
|
+
if (Array.isArray(value))
|
|
40
|
+
return 'an array';
|
|
41
|
+
return `a ${typeof value}`;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Every request carries a deadline. Without one, a server that accepts the
|
|
45
|
+
* connection and then never answers parks the MCP server's single thread of
|
|
46
|
+
* conversation forever — the tool call never returns and never errors.
|
|
47
|
+
*/
|
|
48
|
+
async function httpFetch(url, init) {
|
|
49
|
+
const method = init?.method ?? 'GET';
|
|
50
|
+
const timeoutMs = requestTimeoutMs();
|
|
51
|
+
const controller = new AbortController();
|
|
52
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
53
|
+
try {
|
|
54
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (controller.signal.aborted) {
|
|
58
|
+
throw new HttpStoreError(`HTTP ${method} ${url} timed out after ${timeoutMs}ms`, url);
|
|
59
|
+
}
|
|
60
|
+
throw new HttpStoreError(`HTTP ${method} ${url} failed: ${errorMessage(error)}`, url);
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
clearTimeout(timer);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* A reverse proxy or a misrouted path answers 200 with an HTML page. Left to
|
|
68
|
+
* res.json(), that surfaces as "Unexpected token <" — which names neither the
|
|
69
|
+
* endpoint that lied nor what it actually said.
|
|
70
|
+
*/
|
|
71
|
+
async function readJson(res, url, method) {
|
|
72
|
+
const text = await res.text();
|
|
73
|
+
try {
|
|
74
|
+
return JSON.parse(text);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
const contentType = res.headers.get('content-type') ?? 'no content-type';
|
|
78
|
+
throw new HttpStoreError(`HTTP ${method} ${url} returned non-JSON (${contentType}): ${snippet(text)}`, url, res.status);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The server has drifted between `[...]` and `{ nodes: [...] }` for the same
|
|
83
|
+
* collection. Accept either. A payload that is neither is a real failure and
|
|
84
|
+
* must not reach the caller disguised as an empty collection.
|
|
85
|
+
*/
|
|
86
|
+
function readCollection(payload, key, url) {
|
|
87
|
+
if (Array.isArray(payload))
|
|
88
|
+
return payload;
|
|
89
|
+
if (payload !== null && typeof payload === 'object') {
|
|
90
|
+
const inner = payload[key];
|
|
91
|
+
if (Array.isArray(inner))
|
|
92
|
+
return inner;
|
|
93
|
+
}
|
|
94
|
+
throw new HttpStoreError(`HTTP GET ${url} returned ${describeShape(payload)} — expected an array or { ${key}: [...] }`, url);
|
|
95
|
+
}
|
|
96
|
+
/** True only when the endpoint itself is absent — never for a server that broke. */
|
|
97
|
+
function isEndpointMissing(error) {
|
|
98
|
+
return error instanceof HttpStoreError && error.status === 404;
|
|
99
|
+
}
|
|
12
100
|
async function httpGet(url) {
|
|
13
|
-
const res = await
|
|
101
|
+
const res = await httpFetch(url);
|
|
14
102
|
if (!res.ok) {
|
|
15
|
-
|
|
103
|
+
const text = await res.text().catch(() => '');
|
|
104
|
+
throw new HttpStoreError(`HTTP GET ${url} failed: ${res.status} ${res.statusText} — ${snippet(text)}`, url, res.status);
|
|
16
105
|
}
|
|
17
|
-
return res
|
|
106
|
+
return (await readJson(res, url, 'GET'));
|
|
18
107
|
}
|
|
19
108
|
async function httpPost(url, body) {
|
|
20
|
-
const res = await
|
|
109
|
+
const res = await httpFetch(url, {
|
|
21
110
|
method: 'POST',
|
|
22
111
|
headers: { 'Content-Type': 'application/json' },
|
|
23
112
|
body: JSON.stringify(body),
|
|
24
113
|
});
|
|
25
114
|
if (!res.ok) {
|
|
26
115
|
const text = await res.text().catch(() => '');
|
|
27
|
-
throw new
|
|
116
|
+
throw new HttpStoreError(`HTTP POST ${url} failed: ${res.status} ${res.statusText} — ${snippet(text)}`, url, res.status);
|
|
28
117
|
}
|
|
29
|
-
return res
|
|
118
|
+
return (await readJson(res, url, 'POST'));
|
|
30
119
|
}
|
|
31
120
|
// ── HttpStore ──
|
|
32
121
|
export class HttpStore {
|
|
33
122
|
name = 'http';
|
|
34
123
|
baseUrl;
|
|
124
|
+
failures = [];
|
|
125
|
+
inFlight = new Set();
|
|
35
126
|
constructor(baseUrl) {
|
|
36
127
|
// Strip trailing slash for consistent URL construction
|
|
37
128
|
this.baseUrl = baseUrl.replace(/\/+$/, '');
|
|
38
129
|
}
|
|
130
|
+
// === Write accountability ===
|
|
131
|
+
/**
|
|
132
|
+
* Writes keep their statement-call shape — `store.createNode(node)` still
|
|
133
|
+
* compiles and still returns immediately — but the promise now comes back,
|
|
134
|
+
* so a caller that awaits learns the truth instead of being told "created"
|
|
135
|
+
* over a request that 404'd. The internal catch is what keeps a rejection
|
|
136
|
+
* nobody awaited from taking the server down as an unhandled rejection.
|
|
137
|
+
*/
|
|
138
|
+
track(operation, url, request) {
|
|
139
|
+
const settled = request.then(() => undefined, (error) => {
|
|
140
|
+
const message = errorMessage(error);
|
|
141
|
+
console.error(`[http-store] ${operation} failed: ${message}`);
|
|
142
|
+
this.failures.push({ operation, url, message, at: new Date().toISOString() });
|
|
143
|
+
if (this.failures.length > MAX_TRACKED_FAILURES)
|
|
144
|
+
this.failures.shift();
|
|
145
|
+
throw error;
|
|
146
|
+
});
|
|
147
|
+
// Attaching a handler to `settled` is what marks it handled for the
|
|
148
|
+
// call sites that ignore the returned promise.
|
|
149
|
+
const quiet = settled.catch(() => undefined);
|
|
150
|
+
this.inFlight.add(quiet);
|
|
151
|
+
void quiet.then(() => { this.inFlight.delete(quiet); });
|
|
152
|
+
return settled;
|
|
153
|
+
}
|
|
154
|
+
/** Writes that did not land, oldest first. Non-destructive. */
|
|
155
|
+
getWriteFailures() {
|
|
156
|
+
return [...this.failures];
|
|
157
|
+
}
|
|
158
|
+
/** Drain the record — for a caller that has reported the failures onward. */
|
|
159
|
+
takeWriteFailures() {
|
|
160
|
+
return this.failures.splice(0, this.failures.length);
|
|
161
|
+
}
|
|
162
|
+
/** Wait for every in-flight write to land or fail. Never rejects. */
|
|
163
|
+
async settleWrites() {
|
|
164
|
+
while (this.inFlight.size > 0) {
|
|
165
|
+
await Promise.all([...this.inFlight]);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
39
168
|
// === Nodes ===
|
|
40
169
|
createNode(node) {
|
|
41
|
-
|
|
42
|
-
|
|
170
|
+
const url = `${this.baseUrl}/api/nodes`;
|
|
171
|
+
return this.track('createNode', url, httpPost(url, node));
|
|
43
172
|
}
|
|
44
173
|
async getNode(id) {
|
|
45
174
|
const all = await this.getAllNodes();
|
|
46
175
|
return all.find(n => n.id === id);
|
|
47
176
|
}
|
|
48
177
|
async getAllNodes(limit) {
|
|
49
|
-
const
|
|
50
|
-
const nodes =
|
|
178
|
+
const url = `${this.baseUrl}/api/nodes`;
|
|
179
|
+
const nodes = readCollection(await httpGet(url), 'nodes', url);
|
|
51
180
|
return limit !== undefined ? nodes.slice(0, limit) : nodes;
|
|
52
181
|
}
|
|
53
182
|
async getNodesByType(type) {
|
|
54
|
-
const
|
|
55
|
-
return
|
|
183
|
+
const url = `${this.baseUrl}/api/nodes?type=${encodeURIComponent(type)}`;
|
|
184
|
+
return readCollection(await httpGet(url), 'nodes', url);
|
|
56
185
|
}
|
|
57
186
|
async getNodesByDirection(direction) {
|
|
58
|
-
const
|
|
59
|
-
return
|
|
187
|
+
const url = `${this.baseUrl}/api/nodes?direction=${encodeURIComponent(direction)}`;
|
|
188
|
+
return readCollection(await httpGet(url), 'nodes', url);
|
|
60
189
|
}
|
|
61
190
|
async searchNodes(query, opts = {}) {
|
|
62
191
|
// Server has no search endpoint yet — fetch all and filter client-side
|
|
@@ -72,10 +201,12 @@ export class HttpStore {
|
|
|
72
201
|
}
|
|
73
202
|
// === Edges ===
|
|
74
203
|
createEdge(edge) {
|
|
75
|
-
|
|
204
|
+
const url = `${this.baseUrl}/api/edges`;
|
|
205
|
+
return this.track('createEdge', url, httpPost(url, edge));
|
|
76
206
|
}
|
|
77
207
|
async getAllEdges() {
|
|
78
|
-
|
|
208
|
+
const url = `${this.baseUrl}/api/edges`;
|
|
209
|
+
return readCollection(await httpGet(url), 'edges', url);
|
|
79
210
|
}
|
|
80
211
|
async getEdgesForNode(nodeId) {
|
|
81
212
|
const edges = await this.getAllEdges();
|
|
@@ -94,28 +225,20 @@ export class HttpStore {
|
|
|
94
225
|
}
|
|
95
226
|
updateEdgeCeremony(fromId, toId, ceremonyId) {
|
|
96
227
|
// No dedicated server endpoint — fetch, update, and re-post
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
...edge,
|
|
105
|
-
ceremony_honored: true,
|
|
106
|
-
ceremony_id: ceremonyId,
|
|
107
|
-
});
|
|
108
|
-
}
|
|
228
|
+
const url = `${this.baseUrl}/api/edges`;
|
|
229
|
+
return this.track('updateEdgeCeremony', url, (async () => {
|
|
230
|
+
const edges = await this.getAllEdges();
|
|
231
|
+
for (const edge of edges) {
|
|
232
|
+
if ((edge.from_id === fromId && edge.to_id === toId) ||
|
|
233
|
+
(edge.from_id === toId && edge.to_id === fromId)) {
|
|
234
|
+
await httpPost(url, { ...edge, ceremony_honored: true, ceremony_id: ceremonyId });
|
|
109
235
|
}
|
|
110
236
|
}
|
|
111
|
-
|
|
112
|
-
console.error(`[http-store] updateEdgeCeremony failed: ${err}`);
|
|
113
|
-
}
|
|
114
|
-
})();
|
|
237
|
+
})());
|
|
115
238
|
}
|
|
116
239
|
async getRelationalWeb(nodeId, depth = 2) {
|
|
117
240
|
const allNodes = await this.getAllNodes();
|
|
118
|
-
const allEdges = await
|
|
241
|
+
const allEdges = await this.getAllEdges();
|
|
119
242
|
const nodeMap = new Map(allNodes.map(n => [n.id, n]));
|
|
120
243
|
const visited = new Set();
|
|
121
244
|
const resultNodes = [];
|
|
@@ -143,35 +266,38 @@ export class HttpStore {
|
|
|
143
266
|
}
|
|
144
267
|
// === Ceremonies ===
|
|
145
268
|
logCeremony(ceremony) {
|
|
146
|
-
|
|
269
|
+
const url = `${this.baseUrl}/api/ceremonies`;
|
|
270
|
+
return this.track('logCeremony', url, httpPost(url, ceremony));
|
|
147
271
|
}
|
|
148
272
|
async getCeremony(id) {
|
|
149
273
|
const all = await this.getAllCeremonies();
|
|
150
274
|
return all.find(c => c.id === id);
|
|
151
275
|
}
|
|
152
276
|
async getAllCeremonies(limit) {
|
|
153
|
-
const
|
|
154
|
-
const sorted = (
|
|
277
|
+
const url = `${this.baseUrl}/api/ceremonies`;
|
|
278
|
+
const sorted = readCollection(await httpGet(url), 'ceremonies', url).sort((a, b) => Date.parse(b.timestamp) - Date.parse(a.timestamp));
|
|
155
279
|
return limit !== undefined ? sorted.slice(0, limit) : sorted;
|
|
156
280
|
}
|
|
157
281
|
async getCeremoniesByDirection(direction) {
|
|
158
|
-
const
|
|
159
|
-
return
|
|
282
|
+
const url = `${this.baseUrl}/api/ceremonies?direction=${encodeURIComponent(direction)}`;
|
|
283
|
+
return readCollection(await httpGet(url), 'ceremonies', url);
|
|
160
284
|
}
|
|
161
285
|
async getCeremoniesByType(type) {
|
|
162
|
-
const
|
|
163
|
-
return
|
|
286
|
+
const url = `${this.baseUrl}/api/ceremonies?type=${encodeURIComponent(type)}`;
|
|
287
|
+
return readCollection(await httpGet(url), 'ceremonies', url);
|
|
164
288
|
}
|
|
165
289
|
// === Beats ===
|
|
166
290
|
createBeat(beat) {
|
|
167
|
-
|
|
291
|
+
const url = `${this.baseUrl}/api/narrative/beats`;
|
|
292
|
+
return this.track('createBeat', url, httpPost(url, beat));
|
|
168
293
|
}
|
|
169
294
|
async getBeat(id) {
|
|
170
295
|
const all = await this.getAllBeats();
|
|
171
296
|
return all.find(b => b.id === id);
|
|
172
297
|
}
|
|
173
298
|
async getAllBeats(limit) {
|
|
174
|
-
const
|
|
299
|
+
const url = `${this.baseUrl}/api/narrative/beats`;
|
|
300
|
+
const beats = readCollection(await httpGet(url), 'beats', url);
|
|
175
301
|
return limit !== undefined ? beats.slice(0, limit) : beats;
|
|
176
302
|
}
|
|
177
303
|
async getBeatsByDirection(direction) {
|
|
@@ -180,14 +306,19 @@ export class HttpStore {
|
|
|
180
306
|
}
|
|
181
307
|
// === Cycles ===
|
|
182
308
|
createCycle(cycle) {
|
|
183
|
-
|
|
309
|
+
const url = `${this.baseUrl}/api/narrative/cycles`;
|
|
310
|
+
return this.track('createCycle', url, httpPost(url, cycle));
|
|
311
|
+
}
|
|
312
|
+
async listCycles() {
|
|
313
|
+
const url = `${this.baseUrl}/api/narrative/cycles`;
|
|
314
|
+
return readCollection(await httpGet(url), 'cycles', url);
|
|
184
315
|
}
|
|
185
316
|
async getCycle(id) {
|
|
186
|
-
const all = await
|
|
317
|
+
const all = await this.listCycles();
|
|
187
318
|
return all.find(c => c.id === id);
|
|
188
319
|
}
|
|
189
320
|
async getAllCycles() {
|
|
190
|
-
const all = await
|
|
321
|
+
const all = await this.listCycles();
|
|
191
322
|
return {
|
|
192
323
|
active: all.filter(c => !c.archived),
|
|
193
324
|
archived: all.filter(c => c.archived),
|
|
@@ -195,62 +326,59 @@ export class HttpStore {
|
|
|
195
326
|
}
|
|
196
327
|
archiveCycle(id) {
|
|
197
328
|
// No dedicated archive endpoint — fetch, mark archived, and re-post
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
catch (err) {
|
|
210
|
-
console.error(`[http-store] archiveCycle failed: ${err}`);
|
|
211
|
-
}
|
|
212
|
-
})();
|
|
329
|
+
const url = `${this.baseUrl}/api/narrative/cycles`;
|
|
330
|
+
return this.track('archiveCycle', url, (async () => {
|
|
331
|
+
const all = await this.listCycles();
|
|
332
|
+
const cycle = all.find(c => c.id === id);
|
|
333
|
+
// An archive that found nothing to archive is a failed archive. Reported
|
|
334
|
+
// as success it tells the circle a cycle was closed that is still open.
|
|
335
|
+
if (!cycle)
|
|
336
|
+
throw new HttpStoreError(`archiveCycle: cycle ${id} not found`, url, 404);
|
|
337
|
+
await httpPost(url, { ...cycle, archived: true });
|
|
338
|
+
})());
|
|
213
339
|
}
|
|
214
340
|
// === Charts ===
|
|
215
|
-
//
|
|
216
|
-
//
|
|
341
|
+
// A deployment may predate /api/charts. That absence (404) is a fact worth
|
|
342
|
+
// degrading over; a 500, a timeout or an HTML page is not, and returning []
|
|
343
|
+
// for those tells the caller "no charts exist" when the truth is unknown.
|
|
217
344
|
saveChart(chart) {
|
|
218
|
-
|
|
345
|
+
const url = `${this.baseUrl}/api/charts`;
|
|
346
|
+
return this.track('saveChart', url, httpPost(url, chart));
|
|
219
347
|
}
|
|
220
348
|
async getChart(id) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
return all.find(c => c.id === id);
|
|
224
|
-
}
|
|
225
|
-
catch {
|
|
226
|
-
console.error(`[http-store] getChart: /api/charts not available`);
|
|
227
|
-
return undefined;
|
|
228
|
-
}
|
|
349
|
+
const all = await this.getAllCharts();
|
|
350
|
+
return all.find(c => c.id === id);
|
|
229
351
|
}
|
|
230
352
|
async getAllCharts(direction) {
|
|
353
|
+
const url = `${this.baseUrl}/api/charts`;
|
|
354
|
+
let charts;
|
|
231
355
|
try {
|
|
232
|
-
|
|
233
|
-
let result = Array.isArray(charts) ? charts : [];
|
|
234
|
-
if (direction)
|
|
235
|
-
result = result.filter(c => c.direction === direction);
|
|
236
|
-
return result.sort((a, b) => Date.parse(b.updated_at) - Date.parse(a.updated_at));
|
|
356
|
+
charts = readCollection(await httpGet(url), 'charts', url);
|
|
237
357
|
}
|
|
238
|
-
catch {
|
|
239
|
-
|
|
358
|
+
catch (error) {
|
|
359
|
+
if (!isEndpointMissing(error))
|
|
360
|
+
throw error;
|
|
361
|
+
console.error(`[http-store] getAllCharts: ${url} not available`);
|
|
240
362
|
return [];
|
|
241
363
|
}
|
|
364
|
+
const result = direction ? charts.filter(c => c.direction === direction) : [...charts];
|
|
365
|
+
return result.sort((a, b) => Date.parse(b.updated_at) - Date.parse(a.updated_at));
|
|
242
366
|
}
|
|
243
367
|
// === MMOT ===
|
|
244
368
|
saveMmot(mmot) {
|
|
245
|
-
|
|
369
|
+
const url = `${this.baseUrl}/api/mmots`;
|
|
370
|
+
return this.track('saveMmot', url, httpPost(url, mmot));
|
|
246
371
|
}
|
|
247
372
|
async getMmotsByChart(chartId) {
|
|
373
|
+
const url = `${this.baseUrl}/api/mmots`;
|
|
248
374
|
try {
|
|
249
|
-
const all = await httpGet(
|
|
250
|
-
return
|
|
375
|
+
const all = readCollection(await httpGet(url), 'mmots', url);
|
|
376
|
+
return all.filter(m => m.chart_id === chartId);
|
|
251
377
|
}
|
|
252
|
-
catch {
|
|
253
|
-
|
|
378
|
+
catch (error) {
|
|
379
|
+
if (!isEndpointMissing(error))
|
|
380
|
+
throw error;
|
|
381
|
+
console.error(`[http-store] getMmotsByChart: ${url} not available`);
|
|
254
382
|
return [];
|
|
255
383
|
}
|
|
256
384
|
}
|
|
@@ -273,8 +401,8 @@ export class HttpStore {
|
|
|
273
401
|
if (filters.artefact !== undefined)
|
|
274
402
|
params.set('artefact', filters.artefact);
|
|
275
403
|
const query = params.size > 0 ? `?${params.toString()}` : '';
|
|
276
|
-
const
|
|
277
|
-
return
|
|
404
|
+
const url = `${this.baseUrl}/api/inquiry-weaves${query}`;
|
|
405
|
+
return readCollection(await httpGet(url), 'inquiry_weaves', url);
|
|
278
406
|
}
|
|
279
407
|
// === Plan Perspectives ===
|
|
280
408
|
async registerPlanPerspective(record) {
|
|
@@ -282,13 +410,15 @@ export class HttpStore {
|
|
|
282
410
|
return data.record ?? record;
|
|
283
411
|
}
|
|
284
412
|
async getPlanPerspective(id) {
|
|
285
|
-
const
|
|
413
|
+
const url = `${this.baseUrl}/api/plan-perspectives/${encodeURIComponent(id)}`;
|
|
414
|
+
const res = await httpFetch(url);
|
|
286
415
|
if (res.status === 404)
|
|
287
416
|
return undefined;
|
|
288
417
|
if (!res.ok) {
|
|
289
|
-
|
|
418
|
+
const text = await res.text().catch(() => '');
|
|
419
|
+
throw new HttpStoreError(`HTTP GET ${url} failed: ${res.status} ${res.statusText} — ${snippet(text)}`, url, res.status);
|
|
290
420
|
}
|
|
291
|
-
const data = (await res
|
|
421
|
+
const data = (await readJson(res, url, 'GET'));
|
|
292
422
|
return data.record ?? undefined;
|
|
293
423
|
}
|
|
294
424
|
async listPlanPerspectives(filters = {}) {
|
|
@@ -300,8 +430,8 @@ export class HttpStore {
|
|
|
300
430
|
if (filters.id !== undefined)
|
|
301
431
|
params.set('id', filters.id);
|
|
302
432
|
const query = params.size > 0 ? `?${params.toString()}` : '';
|
|
303
|
-
const
|
|
304
|
-
return
|
|
433
|
+
const url = `${this.baseUrl}/api/plan-perspectives${query}`;
|
|
434
|
+
return readCollection(await httpGet(url), 'plan_perspectives', url);
|
|
305
435
|
}
|
|
306
436
|
}
|
|
307
437
|
// ── Factory ──
|