@medicine-wheel/client 0.14.0

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/README.md ADDED
@@ -0,0 +1,17 @@
1
+ # @medicine-wheel/client
2
+
3
+ The door to a Medicine Wheel over HTTP: nodes, edges, ceremonies, beats and the ceremonial diary, typed against `@medicine-wheel/ontology-core`, with the wheel's paging honesty (`count`, `total`, `matched`, `truncated`) carried through and fail-fast errors that name the status.
4
+
5
+ ```ts
6
+ import { createMedicineWheelClient, wheelUrlFromEnv } from '@medicine-wheel/client';
7
+
8
+ const wheel = createMedicineWheelClient(wheelUrlFromEnv() ?? 'http://127.0.0.1:8040');
9
+ const page = await wheel.ceremonies.list({ episode_path: '2026-09-17-episode-349-…', limit: 'all' });
10
+ const opened = await wheel.ceremonies.create({ type: 'talking_circle', direction: 'east', participants: [], medicines_used: [], intentions: ['…'], circle_id: 'circle:…' });
11
+ const turn = await wheel.beats.create({ direction: 'east', title: 'Guillaume speaks', description: '…', ceremonies: [opened.id], speaker: 'node:human:…' });
12
+ await wheel.beats.witness(turn.id, { witnesses: ['node:human:…'] });
13
+ ```
14
+
15
+ No retry: an unreachable wheel throws `MedicineWheelClientError` with status 502; a refusal carries the wheel's status and body. `limit: 'all'` asks for the whole store.
16
+
17
+ Extracted in 0.14.0 from the MCP's `http-store.ts` and Miadi's `lib/chronicle-wheel.ts` (jgwill/Miadi#647). Spec: `rispecs/client.spec.md`.
@@ -0,0 +1,190 @@
1
+ /**
2
+ * @medicine-wheel/client — the door to a wheel over HTTP.
3
+ *
4
+ * Until 0.14.0 no package in the suite could reach a wheel over HTTP
5
+ * (`rispecs/client.spec.md`, measured 2026-09-08); the one working client was
6
+ * sealed inside the MCP server and every consumer (Miadi, gmtermux,
7
+ * forgewright) hand-rolled its own. This package is that door, extracted from
8
+ * the MCP's `http-store.ts` and from Miadi's `lib/chronicle-wheel.ts` seed.
9
+ *
10
+ * Three commitments, each answering one open question of the spec:
11
+ * 1. It sits BESIDE `storage-provider`, it does not wrap it. A consumer on the
12
+ * same host as the store may read the provider; a consumer on another host
13
+ * reads this.
14
+ * 2. It carries the paging honesty the routes gained in 0.9–0.11: every list
15
+ * returns `count`, `total` (when the wheel reports it) and `truncated`, so a
16
+ * caller can tell a page from an answer. `limit: 'all'` asks for the whole
17
+ * store, always.
18
+ * 3. It fails fast and lets the caller decide. No retry. An unreachable wheel
19
+ * is an error with status 502; a refusal carries the wheel's status and body.
20
+ */
21
+ import type { CeremonyLog, CeremonyType, DirectionName, NarrativeBeat, NodeType, RelationalEdge, RelationalNode } from '@medicine-wheel/ontology-core';
22
+ import type { DiaryEntryRecord } from '@medicine-wheel/storage-provider';
23
+ export type { CeremonyLog, CeremonyType, DirectionName, NarrativeBeat, NodeType, RelationalEdge, RelationalNode, DiaryEntryRecord };
24
+ export declare class MedicineWheelClientError extends Error {
25
+ /** 502 when the wheel could not be reached or refused; 503 when no URL was configured; else the wheel's own status. */
26
+ readonly status: number;
27
+ readonly url: string;
28
+ /** The wheel's response body when it refused, truncated. */
29
+ readonly body?: string | undefined;
30
+ constructor(message: string,
31
+ /** 502 when the wheel could not be reached or refused; 503 when no URL was configured; else the wheel's own status. */
32
+ status: number, url: string,
33
+ /** The wheel's response body when it refused, truncated. */
34
+ body?: string | undefined);
35
+ }
36
+ export type Limit = number | 'all';
37
+ /** The honesty contract: a caller must be able to tell a page from an answer. */
38
+ export interface Paged<T> {
39
+ items: T[];
40
+ /** Items in this page. */
41
+ count: number;
42
+ /** The whole collection, when the wheel reports it. */
43
+ total?: number;
44
+ /** What the filters selected before paging, when the wheel reports it. */
45
+ matched?: number;
46
+ /** True when `count < matched` (or `< total` unfiltered). */
47
+ truncated: boolean;
48
+ provider?: string;
49
+ }
50
+ export interface ListNodesOptions {
51
+ type?: NodeType;
52
+ direction?: DirectionName;
53
+ /** The wheel's `kind` metadata query (e.g. `chronicle_episode`). */
54
+ kind?: string;
55
+ limit?: Limit;
56
+ }
57
+ export interface NewNode {
58
+ id?: string;
59
+ name: string;
60
+ type: NodeType;
61
+ direction?: DirectionName;
62
+ description?: string;
63
+ metadata?: Record<string, unknown>;
64
+ }
65
+ export interface NodePatch {
66
+ name?: string;
67
+ type?: NodeType;
68
+ description?: string;
69
+ direction?: DirectionName | null;
70
+ metadata?: Record<string, unknown>;
71
+ }
72
+ export interface ListEdgesOptions {
73
+ from?: string;
74
+ to?: string;
75
+ limit?: Limit;
76
+ }
77
+ export interface NewEdge {
78
+ from_id: string;
79
+ to_id: string;
80
+ relationship_type: string;
81
+ strength?: number;
82
+ ceremony_honored?: boolean;
83
+ obligations?: string[];
84
+ }
85
+ export interface ListCeremoniesOptions {
86
+ direction?: DirectionName;
87
+ type?: CeremonyType;
88
+ episode_path?: string;
89
+ circle_id?: string;
90
+ /** The opening id: answers "which record closes this ceremony". */
91
+ closes?: string;
92
+ limit?: Limit;
93
+ }
94
+ /** The wheel mints the id and stamps `timestamp` unless one is given. */
95
+ export type NewCeremony = Omit<CeremonyLog, 'id' | 'timestamp'> & {
96
+ id?: string;
97
+ timestamp?: string;
98
+ };
99
+ export interface ListBeatsOptions {
100
+ direction?: DirectionName;
101
+ /** Only beats that name this ceremony in `ceremonies[]`. Filtered client-side: the beats door has no query. */
102
+ ceremony?: string;
103
+ limit?: Limit;
104
+ }
105
+ export type NewBeat = Omit<NarrativeBeat, 'id' | 'timestamp' | 'act' | 'ceremonies' | 'learnings' | 'relations_honored'> & {
106
+ id?: string;
107
+ timestamp?: string;
108
+ act?: number;
109
+ ceremonies?: string[];
110
+ learnings?: string[];
111
+ relations_honored?: string[];
112
+ };
113
+ export interface ListDiaryOptions {
114
+ participant?: string;
115
+ phase?: DiaryEntryRecord['phase'];
116
+ entryType?: DiaryEntryRecord['entryType'];
117
+ chronicle?: string;
118
+ ceremony_id?: string;
119
+ tags?: string[];
120
+ limit?: Limit;
121
+ }
122
+ export type NewDiaryEntry = Omit<DiaryEntryRecord, 'id' | 'timestamp' | 'metadata'> & {
123
+ id?: string;
124
+ timestamp?: string;
125
+ metadata?: DiaryEntryRecord['metadata'];
126
+ ceremony_id?: string;
127
+ };
128
+ export interface ClientOptions {
129
+ baseUrl: string;
130
+ /** Defaults to the global fetch. Inject one in tests. */
131
+ fetch?: typeof fetch;
132
+ /** Per-request timeout. Default 10 000 ms. */
133
+ timeoutMs?: number;
134
+ /** Extra headers on every request (an Authorization header, for a wheel that asks for one). */
135
+ headers?: Record<string, string>;
136
+ }
137
+ export interface MedicineWheelClient {
138
+ readonly baseUrl: string;
139
+ health(): Promise<{
140
+ ok: boolean;
141
+ status: number;
142
+ }>;
143
+ nodes: {
144
+ list(opts?: ListNodesOptions): Promise<Paged<RelationalNode>>;
145
+ get(id: string): Promise<RelationalNode | null>;
146
+ create(input: NewNode): Promise<RelationalNode>;
147
+ patch(id: string, patch: NodePatch): Promise<RelationalNode>;
148
+ };
149
+ edges: {
150
+ list(opts?: ListEdgesOptions): Promise<Paged<RelationalEdge>>;
151
+ create(input: NewEdge): Promise<RelationalEdge>;
152
+ remove(from_id: string, to_id: string): Promise<void>;
153
+ };
154
+ ceremonies: {
155
+ list(opts?: ListCeremoniesOptions): Promise<Paged<CeremonyLog>>;
156
+ get(id: string): Promise<CeremonyLog | null>;
157
+ create(input: NewCeremony): Promise<CeremonyLog>;
158
+ };
159
+ beats: {
160
+ list(opts?: ListBeatsOptions): Promise<Paged<NarrativeBeat>>;
161
+ get(id: string): Promise<NarrativeBeat | null>;
162
+ create(input: NewBeat): Promise<NarrativeBeat & {
163
+ warnings?: string[];
164
+ }>;
165
+ /** Add witnesses (a set) and, when given, name the speaker. */
166
+ witness(id: string, patch: {
167
+ witnesses?: string[];
168
+ speaker?: string;
169
+ }): Promise<NarrativeBeat>;
170
+ };
171
+ diary: {
172
+ list(opts?: ListDiaryOptions): Promise<Paged<DiaryEntryRecord>>;
173
+ get(id: string): Promise<DiaryEntryRecord | null>;
174
+ create(input: NewDiaryEntry): Promise<DiaryEntryRecord>;
175
+ remove(id: string): Promise<void>;
176
+ };
177
+ }
178
+ /** Build a client for one wheel. Throws (503) when the URL is empty. */
179
+ export declare function createMedicineWheelClient(options: ClientOptions | string): MedicineWheelClient;
180
+ /** The episode a ceremony is bound to: the typed field first (0.14.0), then the legacy JSON string in `research_context`. */
181
+ export declare function episodeOf(ceremony: Pick<CeremonyLog, 'episode_path' | 'episode_number' | 'source' | 'research_context'>): {
182
+ episode_path: string;
183
+ episode_number?: number;
184
+ source?: string;
185
+ } | null;
186
+ /** The opening a closing closes: the typed field first (0.14.0), then the MCP's convention of naming it in `research_context`. */
187
+ export declare function closingOf(ceremony: Pick<CeremonyLog, 'type' | 'closes' | 'research_context'>): string | null;
188
+ /** Read the wheel URL the way every Miadi tool does: `MIADI_CHRONICLE_MW_URL` first, then `MW_API_URL`. */
189
+ export declare function wheelUrlFromEnv(env?: Record<string, string | undefined>): string | null;
190
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,313 @@
1
+ /**
2
+ * @medicine-wheel/client — the door to a wheel over HTTP.
3
+ *
4
+ * Until 0.14.0 no package in the suite could reach a wheel over HTTP
5
+ * (`rispecs/client.spec.md`, measured 2026-09-08); the one working client was
6
+ * sealed inside the MCP server and every consumer (Miadi, gmtermux,
7
+ * forgewright) hand-rolled its own. This package is that door, extracted from
8
+ * the MCP's `http-store.ts` and from Miadi's `lib/chronicle-wheel.ts` seed.
9
+ *
10
+ * Three commitments, each answering one open question of the spec:
11
+ * 1. It sits BESIDE `storage-provider`, it does not wrap it. A consumer on the
12
+ * same host as the store may read the provider; a consumer on another host
13
+ * reads this.
14
+ * 2. It carries the paging honesty the routes gained in 0.9–0.11: every list
15
+ * returns `count`, `total` (when the wheel reports it) and `truncated`, so a
16
+ * caller can tell a page from an answer. `limit: 'all'` asks for the whole
17
+ * store, always.
18
+ * 3. It fails fast and lets the caller decide. No retry. An unreachable wheel
19
+ * is an error with status 502; a refusal carries the wheel's status and body.
20
+ */
21
+ // ── errors ──────────────────────────────────────────────────────────────────
22
+ export class MedicineWheelClientError extends Error {
23
+ status;
24
+ url;
25
+ body;
26
+ constructor(message,
27
+ /** 502 when the wheel could not be reached or refused; 503 when no URL was configured; else the wheel's own status. */
28
+ status, url,
29
+ /** The wheel's response body when it refused, truncated. */
30
+ body) {
31
+ super(message);
32
+ this.status = status;
33
+ this.url = url;
34
+ this.body = body;
35
+ this.name = 'MedicineWheelClientError';
36
+ }
37
+ }
38
+ function trimBase(url) {
39
+ return url.trim().replace(/\/+$/, '');
40
+ }
41
+ function limitParam(limit) {
42
+ if (limit === undefined)
43
+ return undefined;
44
+ return limit === 'all' ? 'all' : String(limit);
45
+ }
46
+ function num(value) {
47
+ return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
48
+ }
49
+ function pageFrom(body, key) {
50
+ if (Array.isArray(body)) {
51
+ return { items: body, count: body.length, truncated: false };
52
+ }
53
+ const record = (body ?? {});
54
+ const items = Array.isArray(record[key]) ? record[key] : [];
55
+ const total = num(record.total);
56
+ const matched = num(record.matched);
57
+ const truncated = typeof record.truncated === 'boolean'
58
+ ? record.truncated
59
+ : matched !== undefined
60
+ ? items.length < matched
61
+ : total !== undefined
62
+ ? items.length < total
63
+ : false;
64
+ return {
65
+ items,
66
+ count: items.length,
67
+ ...(total !== undefined ? { total } : {}),
68
+ ...(matched !== undefined ? { matched } : {}),
69
+ truncated,
70
+ ...(typeof record.provider === 'string' ? { provider: record.provider } : {}),
71
+ };
72
+ }
73
+ /** Build a client for one wheel. Throws (503) when the URL is empty. */
74
+ export function createMedicineWheelClient(options) {
75
+ const opts = typeof options === 'string' ? { baseUrl: options } : options;
76
+ const base = trimBase(opts.baseUrl ?? '');
77
+ if (!base) {
78
+ throw new MedicineWheelClientError('No wheel URL configured', 503, '');
79
+ }
80
+ const doFetch = opts.fetch ?? globalThis.fetch;
81
+ if (typeof doFetch !== 'function') {
82
+ throw new MedicineWheelClientError('No fetch available in this runtime', 503, base);
83
+ }
84
+ const timeoutMs = opts.timeoutMs ?? 10_000;
85
+ async function call(path, init) {
86
+ const url = `${base}${path}`;
87
+ const headers = { ...(opts.headers ?? {}) };
88
+ if (init?.body !== undefined)
89
+ headers['Content-Type'] = 'application/json';
90
+ try {
91
+ return await doFetch(url, {
92
+ ...init,
93
+ headers: { ...headers, ...(init?.headers ?? {}) },
94
+ cache: 'no-store',
95
+ signal: AbortSignal.timeout(timeoutMs),
96
+ });
97
+ }
98
+ catch (err) {
99
+ const reason = err instanceof Error ? err.message : String(err);
100
+ throw new MedicineWheelClientError(`wheel unreachable: ${reason}`, 502, url);
101
+ }
102
+ }
103
+ async function refused(res, what) {
104
+ let body = '';
105
+ try {
106
+ body = (await res.text()).slice(0, 500);
107
+ }
108
+ catch {
109
+ /* the status is enough */
110
+ }
111
+ throw new MedicineWheelClientError(`wheel ${what} (${res.status})`, res.status >= 500 ? 502 : res.status, res.url, body);
112
+ }
113
+ async function json(res, what) {
114
+ if (!res.ok)
115
+ return refused(res, what);
116
+ return (await res.json());
117
+ }
118
+ function query(params) {
119
+ const qs = new URLSearchParams();
120
+ for (const [k, v] of Object.entries(params))
121
+ if (v !== undefined && v !== '')
122
+ qs.set(k, v);
123
+ const s = qs.toString();
124
+ return s ? `?${s}` : '';
125
+ }
126
+ async function getOrNull(path, key, what) {
127
+ const res = await call(path);
128
+ if (res.status === 404)
129
+ return null;
130
+ const body = await json(res, what);
131
+ return (body && typeof body === 'object' && key in body ? body[key] : body) ?? null;
132
+ }
133
+ return {
134
+ baseUrl: base,
135
+ async health() {
136
+ try {
137
+ const res = await call('/api/health');
138
+ return { ok: res.ok, status: res.status };
139
+ }
140
+ catch (err) {
141
+ return { ok: false, status: err instanceof MedicineWheelClientError ? err.status : 502 };
142
+ }
143
+ },
144
+ nodes: {
145
+ async list(o = {}) {
146
+ const res = await call(`/api/nodes${query({ type: o.type, direction: o.direction, kind: o.kind, limit: limitParam(o.limit) })}`);
147
+ return pageFrom(await json(res, 'refused the node list'), 'nodes');
148
+ },
149
+ async get(id) {
150
+ return getOrNull(`/api/nodes/${encodeURIComponent(id)}`, 'node', 'refused the node read');
151
+ },
152
+ async create(input) {
153
+ const res = await call('/api/nodes', { method: 'POST', body: JSON.stringify(input) });
154
+ const body = await json(res, 'refused the node');
155
+ if (!body?.node?.id)
156
+ throw new MedicineWheelClientError('wheel returned no node', 502, res.url);
157
+ return body.node;
158
+ },
159
+ async patch(id, patch) {
160
+ const res = await call(`/api/nodes/${encodeURIComponent(id)}`, { method: 'PATCH', body: JSON.stringify(patch) });
161
+ const body = await json(res, 'refused the node patch');
162
+ if (!body?.node?.id)
163
+ throw new MedicineWheelClientError('wheel returned no node', 502, res.url);
164
+ return body.node;
165
+ },
166
+ },
167
+ edges: {
168
+ async list(o = {}) {
169
+ const res = await call(`/api/edges${query({ from: o.from, to: o.to, limit: limitParam(o.limit) })}`);
170
+ return pageFrom(await json(res, 'refused the edge list'), 'edges');
171
+ },
172
+ async create(input) {
173
+ const res = await call('/api/edges', { method: 'POST', body: JSON.stringify(input) });
174
+ const body = await json(res, 'refused the edge');
175
+ if (!body?.edge)
176
+ throw new MedicineWheelClientError('wheel returned no edge', 502, res.url);
177
+ return body.edge;
178
+ },
179
+ async remove(from_id, to_id) {
180
+ const res = await call(`/api/edges${query({ from: from_id, to: to_id })}`, { method: 'DELETE' });
181
+ if (!res.ok && res.status !== 404)
182
+ await refused(res, 'refused the edge removal');
183
+ },
184
+ },
185
+ ceremonies: {
186
+ async list(o = {}) {
187
+ const res = await call(`/api/ceremonies${query({ direction: o.direction, type: o.type, episode_path: o.episode_path, circle_id: o.circle_id, closes: o.closes, limit: limitParam(o.limit) })}`);
188
+ return pageFrom(await json(res, 'refused the ceremony list'), 'ceremonies');
189
+ },
190
+ async get(id) {
191
+ return getOrNull(`/api/ceremonies/${encodeURIComponent(id)}`, 'ceremony', 'refused the ceremony read');
192
+ },
193
+ async create(input) {
194
+ const res = await call('/api/ceremonies', { method: 'POST', body: JSON.stringify(input) });
195
+ const body = await json(res, 'refused the ceremony');
196
+ if (!body?.ceremony?.id)
197
+ throw new MedicineWheelClientError('wheel returned no ceremony', 502, res.url);
198
+ return body.ceremony;
199
+ },
200
+ },
201
+ beats: {
202
+ async list(o = {}) {
203
+ // The beats door returns the whole collection as a bare array and takes no query.
204
+ const res = await call('/api/narrative/beats');
205
+ const all = pageFrom(await json(res, 'refused the beat list'), 'beats');
206
+ let items = all.items;
207
+ if (o.direction)
208
+ items = items.filter((b) => b.direction === o.direction);
209
+ if (o.ceremony)
210
+ items = items.filter((b) => Array.isArray(b.ceremonies) && b.ceremonies.includes(o.ceremony));
211
+ const matched = items.length;
212
+ if (typeof o.limit === 'number' && items.length > o.limit)
213
+ items = items.slice(0, o.limit);
214
+ return { items, count: items.length, total: all.items.length, matched, truncated: items.length < matched, ...(all.provider ? { provider: all.provider } : {}) };
215
+ },
216
+ async get(id) {
217
+ const res = await call(`/api/narrative/beats/${encodeURIComponent(id)}`);
218
+ if (res.status === 404)
219
+ return null;
220
+ return json(res, 'refused the beat read');
221
+ },
222
+ async create(input) {
223
+ const res = await call('/api/narrative/beats', { method: 'POST', body: JSON.stringify(input) });
224
+ const beat = await json(res, 'refused the beat');
225
+ if (!beat?.id)
226
+ throw new MedicineWheelClientError('wheel returned no beat', 502, res.url);
227
+ return beat;
228
+ },
229
+ async witness(id, patch) {
230
+ const res = await call(`/api/narrative/beats/${encodeURIComponent(id)}`, { method: 'PATCH', body: JSON.stringify(patch) });
231
+ const beat = await json(res, 'refused the witnessing');
232
+ if (!beat?.id)
233
+ throw new MedicineWheelClientError('wheel returned no beat', 502, res.url);
234
+ return beat;
235
+ },
236
+ },
237
+ diary: {
238
+ async list(o = {}) {
239
+ const params = {
240
+ participant: o.participant,
241
+ phase: o.phase,
242
+ entryType: o.entryType,
243
+ chronicle: o.chronicle,
244
+ ceremony_id: o.ceremony_id,
245
+ limit: limitParam(o.limit),
246
+ };
247
+ let q = query(params);
248
+ for (const tag of o.tags ?? [])
249
+ q += `${q ? '&' : '?'}tag=${encodeURIComponent(tag)}`;
250
+ const res = await call(`/api/diary${q}`);
251
+ return pageFrom(await json(res, 'refused the diary list'), 'entries');
252
+ },
253
+ async get(id) {
254
+ return getOrNull(`/api/diary/${encodeURIComponent(id)}`, 'entry', 'refused the diary read');
255
+ },
256
+ async create(input) {
257
+ const res = await call('/api/diary', { method: 'POST', body: JSON.stringify(input) });
258
+ const body = await json(res, 'refused the diary entry');
259
+ if (!body?.entry?.id)
260
+ throw new MedicineWheelClientError('wheel returned no entry', 502, res.url);
261
+ return body.entry;
262
+ },
263
+ async remove(id) {
264
+ const res = await call(`/api/diary/${encodeURIComponent(id)}`, { method: 'DELETE' });
265
+ if (!res.ok && res.status !== 404)
266
+ await refused(res, 'refused the diary removal');
267
+ },
268
+ },
269
+ };
270
+ }
271
+ // ── readers every consumer needs ────────────────────────────────────────────
272
+ /** The episode a ceremony is bound to: the typed field first (0.14.0), then the legacy JSON string in `research_context`. */
273
+ export function episodeOf(ceremony) {
274
+ if (typeof ceremony.episode_path === 'string' && ceremony.episode_path) {
275
+ return {
276
+ episode_path: ceremony.episode_path,
277
+ ...(typeof ceremony.episode_number === 'number' ? { episode_number: ceremony.episode_number } : {}),
278
+ ...(typeof ceremony.source === 'string' ? { source: ceremony.source } : {}),
279
+ };
280
+ }
281
+ if (typeof ceremony.research_context !== 'string')
282
+ return null;
283
+ try {
284
+ const parsed = JSON.parse(ceremony.research_context);
285
+ const path = parsed?.episode_path ?? parsed?.episodePath;
286
+ if (typeof path !== 'string' || !path)
287
+ return null;
288
+ return {
289
+ episode_path: path,
290
+ ...(typeof parsed?.episode_number === 'number' ? { episode_number: parsed.episode_number } : {}),
291
+ ...(typeof parsed?.source === 'string' ? { source: parsed.source } : {}),
292
+ };
293
+ }
294
+ catch {
295
+ return null;
296
+ }
297
+ }
298
+ /** The opening a closing closes: the typed field first (0.14.0), then the MCP's convention of naming it in `research_context`. */
299
+ export function closingOf(ceremony) {
300
+ if (ceremony.type !== 'closing')
301
+ return null;
302
+ if (typeof ceremony.closes === 'string' && ceremony.closes)
303
+ return ceremony.closes;
304
+ const rc = ceremony.research_context;
305
+ return typeof rc === 'string' && /^ceremony:\d+:[a-z0-9]+$/.test(rc.trim()) ? rc.trim() : null;
306
+ }
307
+ /** Read the wheel URL the way every Miadi tool does: `MIADI_CHRONICLE_MW_URL` first, then `MW_API_URL`. */
308
+ export function wheelUrlFromEnv(env = process.env) {
309
+ const raw = env.MIADI_CHRONICLE_MW_URL ?? env.MW_API_URL ?? '';
310
+ const trimmed = trimBase(raw);
311
+ return trimmed || null;
312
+ }
313
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@medicine-wheel/client",
3
+ "version": "0.14.0",
4
+ "type": "module",
5
+ "description": "Typed HTTP client for a Medicine Wheel — nodes, edges, ceremonies, beats and the ceremonial diary — with the wheel's paging honesty carried through (count, total, truncated) and fail-fast errors that name the status.",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.js",
13
+ "default": "./dist/index.js"
14
+ }
15
+ },
16
+ "sideEffects": false,
17
+ "files": [
18
+ "dist",
19
+ "README.md"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsc",
23
+ "dev": "tsc --watch",
24
+ "lint": "tsc --noEmit",
25
+ "clean": "rm -rf dist",
26
+ "prepublishOnly": "npm run clean && npm run build"
27
+ },
28
+ "keywords": [
29
+ "medicine-wheel",
30
+ "client",
31
+ "http",
32
+ "ceremony",
33
+ "talking-circle",
34
+ "relational-accountability"
35
+ ],
36
+ "author": "IAIP Collaborative - Shawinigan, QC",
37
+ "license": "MIT",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/jgwill/medicine-wheel.git",
41
+ "directory": "src/client"
42
+ },
43
+ "dependencies": {
44
+ "@medicine-wheel/ontology-core": "^0.14.0",
45
+ "@medicine-wheel/storage-provider": "^0.14.0"
46
+ },
47
+ "devDependencies": {
48
+ "@types/node": "^20.10.0",
49
+ "typescript": "^5.3.0"
50
+ }
51
+ }