@athanlab/mcp 0.0.0-stage → 0.1.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/dist/batch.js ADDED
@@ -0,0 +1,394 @@
1
+ /**
2
+ * POST /speech/batch — used by athanlab_speak_script only when the live
3
+ * OpenAPI document has the path (src/api/features.ts).
4
+ *
5
+ * The endpoint is Phase B of the API (docs/API_AGENT_READINESS_DESIGN.md
6
+ * §4.6) and NOT live yet, so everything here reads the design's shapes
7
+ * defensively, and any sign that the API does not take batches after all
8
+ * (404, 405, batches_not_enabled) falls back to one job per line.
9
+ *
10
+ * A batch only replaces the "create" step: each line becomes an ordinary job
11
+ * whose id appears in the batch's `lines[].job_id` once admitted, and from
12
+ * there the script follows and downloads it exactly like a single job. The
13
+ * batch retries a failed line itself, so its followers never resubmit.
14
+ *
15
+ * An earlier run's batch outlives that run: its lines are durable rows the
16
+ * API keeps admitting — and charging — for up to 24 hours, and a batch
17
+ * blocked on the balance resumes by itself after a top-up. So before
18
+ * anything new is posted, an unfinished earlier batch is settled:
19
+ *
20
+ * - known id → read it. If every line it may still admit is one this run
21
+ * still wants unchanged, re-attach and follow it to the end of admission;
22
+ * if it would admit a line that is gone or changed, cancel it and wait
23
+ * until it has settled. Lines it admitted are followed, not re-created.
24
+ * - unknown id (its creation was never confirmed) → post with its key
25
+ * again: the API replays it, names it in an idempotency_conflict, or —
26
+ * when it never landed — creates this batch under the unused key.
27
+ *
28
+ * Only the lines no earlier batch will admit go into a new batch.
29
+ */
30
+ import { AthanLabError, isRecord, toAthanLabError } from './api/errors.js';
31
+ import { buildRequestBody } from './speech.js';
32
+ const FALLBACK_CODES = new Set(['not_found', 'batches_not_enabled', 'http_404', 'http_405', 'endpoint_removed']);
33
+ /** A batch line in one of these will cost nothing more and admits nothing more. */
34
+ const LINE_DONE_STATES = new Set(['succeeded', 'failed', 'cancelled', 'skipped']);
35
+ /** A batch line that ended without a job to follow. */
36
+ const NO_JOB_OUTCOMES = new Set(['failed', 'cancelled', 'skipped']);
37
+ const BATCH_ID_PATTERN = /^[A-Za-z0-9_-]{1,80}$/;
38
+ const JOB_ID_PATTERN = /^[0-9a-f]{32}$/;
39
+ const MAX_POLL_SECONDS = 15;
40
+ const REATTACH_POLL_SECONDS = 5;
41
+ /** The design's line id rule: ^[A-Za-z0-9][A-Za-z0-9_.:-]{0,63}$ — anything else is left out. */
42
+ function batchLineId(entry) {
43
+ const id = entry.id;
44
+ return id && /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,63}$/.test(id) ? id : undefined;
45
+ }
46
+ function batchBody(ctx, lines, format, numberMode) {
47
+ return {
48
+ lines: lines.map(({ entry, input }) => {
49
+ const body = buildRequestBody({ ...input, metadata: undefined }, ctx.features);
50
+ return {
51
+ ...(batchLineId(entry) ? { id: batchLineId(entry) } : {}),
52
+ text: body.text,
53
+ ...(body.voice_id ? { voice_id: body.voice_id } : {}),
54
+ };
55
+ }),
56
+ output_format: format,
57
+ ...(numberMode ? { defaults: { number_mode: numberMode } } : {}),
58
+ };
59
+ }
60
+ function num(value) {
61
+ return typeof value === 'number' && Number.isFinite(value) ? value : null;
62
+ }
63
+ /** A dry-run quote for every line in one request; null → quote line by line instead. */
64
+ export async function quoteBatch(ctx, lines, format, numberMode, signal) {
65
+ try {
66
+ const res = await ctx.client.json('/speech/batch', {
67
+ method: 'POST',
68
+ body: { ...batchBody(ctx, lines, format, numberMode), dry_run: true },
69
+ ...(signal ? { signal } : {}),
70
+ });
71
+ const data = isRecord(res.data) ? res.data : {};
72
+ const quoteLines = Array.isArray(data.lines) ? data.lines.filter(isRecord) : [];
73
+ const characters = num(data.characters)
74
+ ?? (quoteLines.length > 0
75
+ ? quoteLines.reduce((sum, l) => sum + (num(l.characters) ?? 0), 0)
76
+ : lines.reduce((sum, l) => sum + l.entry.characters, 0));
77
+ const dispatches = num(data.dispatches) ?? quoteLines.reduce((sum, l) => sum + (num(l.dispatches) ?? 0), 0);
78
+ const spendable = num(data.spendable);
79
+ const sufficient = typeof data.sufficient === 'boolean' ? data.sufficient : spendable === null ? null : spendable >= characters;
80
+ return { characters, lines: lines.length, dispatches, spendable, sufficient };
81
+ }
82
+ catch (err) {
83
+ const e = toAthanLabError(err);
84
+ if (FALLBACK_CODES.has(e.code)) {
85
+ ctx.logger.warn('POST /speech/batch is documented but refused; quoting line by line', { code: e.code });
86
+ return null;
87
+ }
88
+ const lineErrors = e.details?.line_errors;
89
+ if (Array.isArray(lineErrors) && lineErrors.length > 0) {
90
+ throw AthanLabError.client('invalid_lines', `${lineErrors.length} line(s) would be refused, so nothing was created or charged: ${e.message}`, {
91
+ details: { line_errors: lineErrors.map((le) => remapLineError(le, lines)) },
92
+ });
93
+ }
94
+ throw e;
95
+ }
96
+ }
97
+ /** A batch line error's index is its position in the batch; report the script's line index. */
98
+ function remapLineError(raw, lines) {
99
+ if (!isRecord(raw))
100
+ return raw;
101
+ const position = num(raw.index) ?? num(raw.line_index);
102
+ const entry = position !== null ? lines[position]?.entry : undefined;
103
+ return entry ? { ...raw, index: entry.index } : raw;
104
+ }
105
+ function readLines(batch, scriptIndexes, byIndex) {
106
+ const raw = Array.isArray(batch.lines) ? batch.lines.filter(isRecord) : [];
107
+ return raw.map((l, position) => {
108
+ const scriptIndex = scriptIndexes[num(l.index) ?? position];
109
+ return {
110
+ scriptIndex,
111
+ line: scriptIndex === undefined ? undefined : byIndex.get(scriptIndex),
112
+ jobId: typeof l.job_id === 'string' && JOB_ID_PATTERN.test(l.job_id) ? l.job_id : null,
113
+ state: typeof l.status === 'string' ? l.status : 'queued',
114
+ error: isRecord(l.error) ? l.error : {},
115
+ };
116
+ });
117
+ }
118
+ function batchStatus(batch) {
119
+ return typeof batch.status === 'string' ? batch.status : 'processing';
120
+ }
121
+ class BatchRunner {
122
+ ctx;
123
+ opts;
124
+ byIndex;
125
+ followed = new Set();
126
+ followers = [];
127
+ constructor(ctx, opts) {
128
+ this.ctx = ctx;
129
+ this.opts = opts;
130
+ this.byIndex = new Map(opts.lines.map(l => [l.entry.index, l]));
131
+ }
132
+ /** Wait for every followed line, then hand back `value`. */
133
+ async finish(value) {
134
+ await Promise.all(this.followers);
135
+ return value;
136
+ }
137
+ follow(line, jobId, charged) {
138
+ if (this.followed.has(jobId))
139
+ return;
140
+ this.followed.add(jobId);
141
+ line.entry.job_id = jobId;
142
+ line.entry.status = 'processing';
143
+ line.entry.error = null;
144
+ this.followers.push(this.opts.followLine(line, charged));
145
+ }
146
+ requestOpts() {
147
+ return { deadline: this.opts.deadline, ...(this.opts.signal ? { signal: this.opts.signal } : {}) };
148
+ }
149
+ async getBatch(id) {
150
+ const res = await this.ctx.client.json(`/speech/batch/${encodeURIComponent(id)}`, this.requestOpts());
151
+ return isRecord(res.data) ? res.data : {};
152
+ }
153
+ async markFinished(id, key, scriptIndexes) {
154
+ this.opts.manifest.batch = { id, idempotency_key: key, line_indexes: scriptIndexes, finished: true };
155
+ await this.opts.save();
156
+ }
157
+ /** Follow the jobs a settled batch admitted for unchanged lines; returns their indexes. */
158
+ adoptAdmitted(lines) {
159
+ const covered = new Set();
160
+ for (const l of lines) {
161
+ if (l.jobId && l.line?.carried && l.scriptIndex !== undefined) {
162
+ covered.add(l.scriptIndex);
163
+ this.follow(l.line, l.jobId, false);
164
+ }
165
+ }
166
+ return covered;
167
+ }
168
+ /**
169
+ * Settle an unfinished earlier batch (see the top of this file). Returns the
170
+ * script indexes it covers — admitted, or still to be admitted by it — or
171
+ * null when this run must not create anything: the batch is blocked, could
172
+ * not be read, or did not settle in time.
173
+ */
174
+ async settleEarlier(id, key, scriptIndexes) {
175
+ let batch;
176
+ try {
177
+ batch = await this.getBatch(id);
178
+ }
179
+ catch (err) {
180
+ const e = toAthanLabError(err);
181
+ if (e.code === 'not_found') {
182
+ await this.markFinished(id, key, scriptIndexes);
183
+ return new Set();
184
+ }
185
+ // Unknown state: creating now could admit lines twice.
186
+ this.opts.onStop(e);
187
+ return null;
188
+ }
189
+ let lines = readLines(batch, scriptIndexes, this.byIndex);
190
+ if (batchStatus(batch) !== 'processing') {
191
+ await this.markFinished(id, key, scriptIndexes);
192
+ return this.adoptAdmitted(lines);
193
+ }
194
+ // Lines it has yet to admit — and charge — that this run no longer wants as they were. (A line
195
+ // it already admitted is paid either way; one for a position now skipped or resumed is that line's own job.)
196
+ const unwanted = lines.filter(l => !l.jobId && !LINE_DONE_STATES.has(l.state) && !l.line?.carried);
197
+ if (unwanted.length === 0) {
198
+ const covered = new Set();
199
+ for (const l of lines) {
200
+ if (l.scriptIndex !== undefined && l.line?.carried && (l.jobId || !LINE_DONE_STATES.has(l.state)))
201
+ covered.add(l.scriptIndex);
202
+ }
203
+ this.ctx.logger.info('re-attaching to an unfinished speech batch', { batch_id: id, lines: covered.size });
204
+ const outcome = await this.watch({ id, key, scriptIndexes, batch, delay: REATTACH_POLL_SECONDS, chargedOnFirstLook: false, covered });
205
+ return outcome === 'finished' ? covered : null;
206
+ }
207
+ this.ctx.logger.warn('cancelling an earlier speech batch whose lines changed', { batch_id: id, unwanted: unwanted.length });
208
+ try {
209
+ await this.ctx.client.json(`/speech/batch/${encodeURIComponent(id)}/cancel`, { method: 'POST', ...this.requestOpts() });
210
+ }
211
+ catch (err) {
212
+ const e = toAthanLabError(err);
213
+ if (e.code !== 'batch_finished') {
214
+ this.opts.onStop(e);
215
+ return null;
216
+ }
217
+ }
218
+ // Wait until it admits nothing more, then take over what it did admit.
219
+ let delay = 2;
220
+ while (batchStatus(batch) === 'processing') {
221
+ if (this.ctx.clock.now() + delay * 1000 > this.opts.deadline) {
222
+ this.opts.onTimeout();
223
+ return null;
224
+ }
225
+ await this.ctx.clock.sleep(delay * 1000, this.opts.signal);
226
+ delay = Math.min(delay * 1.5, MAX_POLL_SECONDS);
227
+ batch = await this.getBatch(id);
228
+ }
229
+ lines = readLines(batch, scriptIndexes, this.byIndex);
230
+ await this.markFinished(id, key, scriptIndexes);
231
+ return this.adoptAdmitted(lines);
232
+ }
233
+ /**
234
+ * Follow a batch until every line has a job or an outcome. For an earlier
235
+ * batch only the `covered` lines are this run's; a fresh one is all ours.
236
+ */
237
+ async watch(w) {
238
+ let { batch, delay } = w;
239
+ let first = true;
240
+ this.opts.manifest.batch = { id: w.id, idempotency_key: w.key, line_indexes: w.scriptIndexes, finished: false };
241
+ for (;;) {
242
+ let open = 0;
243
+ for (const l of readLines(batch, w.scriptIndexes, this.byIndex)) {
244
+ if (!l.jobId && !LINE_DONE_STATES.has(l.state))
245
+ open++;
246
+ if (!l.line || l.scriptIndex === undefined || (w.covered && !w.covered.has(l.scriptIndex)))
247
+ continue;
248
+ if (l.jobId) {
249
+ this.follow(l.line, l.jobId, first ? w.chargedOnFirstLook : true);
250
+ }
251
+ else if (NO_JOB_OUTCOMES.has(l.state) && !l.line.entry.job_id) {
252
+ l.line.entry.status = l.state === 'cancelled' ? 'cancelled' : 'failed';
253
+ l.line.entry.error = {
254
+ code: typeof l.error.code === 'string' ? l.error.code : l.state,
255
+ message: typeof l.error.message === 'string' ? l.error.message : `The batch marked this line ${l.state}.`,
256
+ };
257
+ }
258
+ }
259
+ await this.opts.save();
260
+ const blocked = isRecord(batch.blocked) ? batch.blocked : null;
261
+ if (blocked && typeof blocked.code === 'string') {
262
+ // It resumes by itself after a top-up; a later run re-attaches to it.
263
+ this.opts.onStop(new AthanLabError({
264
+ code: blocked.code,
265
+ message: typeof blocked.message === 'string' ? blocked.message : 'The batch is waiting.',
266
+ source: 'api',
267
+ details: { batch_id: w.id },
268
+ }));
269
+ return 'blocked';
270
+ }
271
+ if (open === 0 || batchStatus(batch) !== 'processing') {
272
+ // Every line has a job or an outcome: a later run must never replay or re-attach to it.
273
+ await this.markFinished(w.id, w.key, w.scriptIndexes);
274
+ return 'finished';
275
+ }
276
+ if (this.ctx.clock.now() + delay * 1000 > this.opts.deadline) {
277
+ this.opts.onTimeout();
278
+ return 'timed_out';
279
+ }
280
+ await this.ctx.clock.sleep(delay * 1000, this.opts.signal);
281
+ delay = Math.min(delay * 1.5, MAX_POLL_SECONDS);
282
+ batch = await this.getBatch(w.id);
283
+ first = false;
284
+ }
285
+ }
286
+ /** Create a batch for `lines` (with an unconfirmed earlier batch's key, when there is one) and follow it. */
287
+ async create(lines, reuseKey) {
288
+ const { manifest } = this.opts;
289
+ const earlierIndexes = manifest.batch?.line_indexes ?? [];
290
+ let toSubmit = lines;
291
+ let key = reuseKey ?? this.ctx.newIdempotencyKey();
292
+ let scriptIndexes = toSubmit.map(l => l.entry.index);
293
+ // An earlier batch's key keeps its own line positions until the API tells us what it is.
294
+ manifest.batch = { id: null, idempotency_key: key, line_indexes: reuseKey ? earlierIndexes : scriptIndexes, finished: false };
295
+ await this.opts.save();
296
+ let created;
297
+ for (let attempt = 1;; attempt++) {
298
+ try {
299
+ created = await this.ctx.client.json('/speech/batch', {
300
+ method: 'POST',
301
+ body: batchBody(this.ctx, toSubmit, this.opts.format, this.opts.numberMode),
302
+ idempotencyKey: key,
303
+ ...this.requestOpts(),
304
+ });
305
+ break;
306
+ }
307
+ catch (err) {
308
+ const e = toAthanLabError(err);
309
+ if (FALLBACK_CODES.has(e.code)) {
310
+ this.ctx.logger.warn('POST /speech/batch refused; running one job per line', { code: e.code });
311
+ manifest.batch = null;
312
+ await this.opts.save();
313
+ return false;
314
+ }
315
+ if (e.code === 'idempotency_conflict' && attempt === 1 && reuseKey) {
316
+ // The key's earlier batch exists, with a different body: settle it before anything new.
317
+ const named = [e.details?.batch_id, e.details?.id].find((v) => typeof v === 'string' && BATCH_ID_PATTERN.test(v));
318
+ if (!named) {
319
+ this.opts.onStop(new AthanLabError({
320
+ code: 'batch_unresolved',
321
+ message: 'An earlier batch for this script may still be admitting lines, but the API did not say which one, so no second batch was created (it could charge lines twice).',
322
+ source: 'client',
323
+ requestId: e.requestId,
324
+ }));
325
+ return true;
326
+ }
327
+ const covered = await this.settleEarlier(named, key, earlierIndexes);
328
+ if (!covered)
329
+ return true;
330
+ toSubmit = toSubmit.filter(l => !covered.has(l.entry.index));
331
+ if (toSubmit.length === 0)
332
+ return true;
333
+ key = this.ctx.newIdempotencyKey();
334
+ scriptIndexes = toSubmit.map(l => l.entry.index);
335
+ manifest.batch = { id: null, idempotency_key: key, line_indexes: scriptIndexes, finished: false };
336
+ await this.opts.save();
337
+ continue;
338
+ }
339
+ this.opts.onStop(e);
340
+ return true;
341
+ }
342
+ }
343
+ const replayed = created.headers.get('idempotent-replayed') === 'true';
344
+ const batch = isRecord(created.data) ? created.data : {};
345
+ const batchId = typeof batch.id === 'string' ? batch.id : null;
346
+ if (!batchId || !BATCH_ID_PATTERN.test(batchId)) {
347
+ this.opts.onStop(new AthanLabError({ code: 'invalid_response', message: 'POST /speech/batch answered without a usable batch id.', source: 'api', requestId: created.requestId }));
348
+ return true;
349
+ }
350
+ // A replay is the earlier batch itself, on its own line positions.
351
+ if (replayed && reuseKey)
352
+ scriptIndexes = earlierIndexes;
353
+ manifest.batch = { id: batchId, idempotency_key: key, line_indexes: scriptIndexes, finished: false };
354
+ await this.opts.save();
355
+ this.ctx.logger.info('speech batch created', { batch_id: batchId, lines: toSubmit.length, replayed });
356
+ await this.watch({
357
+ id: batchId,
358
+ key,
359
+ scriptIndexes,
360
+ batch,
361
+ delay: created.retryAfterSeconds ?? 5,
362
+ chargedOnFirstLook: !replayed,
363
+ covered: null,
364
+ });
365
+ return true;
366
+ }
367
+ }
368
+ /**
369
+ * Settle any unfinished earlier batch, then create one for the lines no
370
+ * batch covers and follow it. Returns false when the API turns out not to
371
+ * take batches — the caller then runs one job per line for every line that
372
+ * has no job yet.
373
+ */
374
+ export async function runBatch(ctx, opts) {
375
+ const runner = new BatchRunner(ctx, opts);
376
+ let toSubmit = opts.lines;
377
+ let reuseKey = null;
378
+ const previous = opts.manifest.batch;
379
+ if (previous && previous.finished !== true) {
380
+ if (previous.id) {
381
+ const covered = await runner.settleEarlier(previous.id, previous.idempotency_key, previous.line_indexes);
382
+ if (!covered)
383
+ return runner.finish(true);
384
+ toSubmit = toSubmit.filter(l => !covered.has(l.entry.index));
385
+ }
386
+ else {
387
+ reuseKey = previous.idempotency_key;
388
+ }
389
+ }
390
+ if (toSubmit.length === 0)
391
+ return runner.finish(true);
392
+ return runner.finish(await runner.create(toSubmit, reuseKey));
393
+ }
394
+ //# sourceMappingURL=batch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch.js","sourceRoot":"","sources":["../src/batch.ts"],"names":[],"mappings":"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"}
package/dist/clock.js ADDED
@@ -0,0 +1,31 @@
1
+ function abortError(signal) {
2
+ const reason = signal.reason;
3
+ if (reason instanceof Error)
4
+ return reason;
5
+ const err = new Error('The operation was aborted.');
6
+ err.name = 'AbortError';
7
+ return err;
8
+ }
9
+ export const systemClock = {
10
+ now: () => Date.now(),
11
+ sleep: (ms, signal) => new Promise((resolve, reject) => {
12
+ if (signal?.aborted) {
13
+ reject(abortError(signal));
14
+ return;
15
+ }
16
+ const timer = setTimeout(() => {
17
+ signal?.removeEventListener('abort', onAbort);
18
+ resolve();
19
+ }, Math.max(0, ms));
20
+ const onAbort = () => {
21
+ clearTimeout(timer);
22
+ reject(abortError(signal));
23
+ };
24
+ signal?.addEventListener('abort', onAbort, { once: true });
25
+ }),
26
+ };
27
+ export function throwIfAborted(signal) {
28
+ if (signal?.aborted)
29
+ throw abortError(signal);
30
+ }
31
+ //# sourceMappingURL=clock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clock.js","sourceRoot":"","sources":["../src/clock.ts"],"names":[],"mappings":"AAMA,SAAS,UAAU,CAAC,MAAmB;IACrC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;IAC5B,IAAI,MAAM,YAAY,KAAK;QAAE,OAAO,MAAM,CAAA;IAC1C,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAA;IACnD,GAAG,CAAC,IAAI,GAAG,YAAY,CAAA;IACvB,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAU;IAChC,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;IACrB,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC3D,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAA;YAC1B,OAAM;QACR,CAAC;QACD,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;YAC7C,OAAO,EAAE,CAAA;QACX,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;QACnB,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,YAAY,CAAC,KAAK,CAAC,CAAA;YACnB,MAAM,CAAC,UAAU,CAAC,MAAqB,CAAC,CAAC,CAAA;QAC3C,CAAC,CAAA;QACD,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;IAC5D,CAAC,CAAC;CACH,CAAA;AAED,MAAM,UAAU,cAAc,CAAC,MAA+B;IAC5D,IAAI,MAAM,EAAE,OAAO;QAAE,MAAM,UAAU,CAAC,MAAM,CAAC,CAAA;AAC/C,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Configuration from the environment.
3
+ *
4
+ * ATHANLAB_API_KEY required. ak_live_ + 32 hex. Checked HERE, before any
5
+ * request: a typo must never reach the API, where 20
6
+ * failed key checks in 5 minutes block the whole network
7
+ * for 10 minutes.
8
+ * ATHANLAB_API_BASE default https://api.athanlab.com/api/v1. Plain http is
9
+ * accepted only for localhost / 127.0.0.1 / ::1 (dev).
10
+ * ATHANLAB_OUTPUT_DIR default ./athanlab-audio, resolved to an absolute path
11
+ * against the working directory; created on demand.
12
+ * ATHANLAB_MAX_CHARS_PER_CALL optional safety cap: a speak/script call whose
13
+ * characters exceed it is refused before any POST.
14
+ *
15
+ * A missing or malformed key does NOT stop the server: it starts, the writing guide
16
+ * still works, and every API tool answers with what to fix. A bad base URL or cap is
17
+ * fatal — those would send the key somewhere unexpected or silently remove a guard.
18
+ *
19
+ * The key's value is never put into an error message or a log line.
20
+ */
21
+ import path from 'node:path';
22
+ export const DEFAULT_API_BASE = 'https://api.athanlab.com/api/v1';
23
+ export const DEFAULT_OUTPUT_DIR = 'athanlab-audio';
24
+ export const API_KEY_PATTERN = /^ak_live_[0-9a-f]{32}$/;
25
+ const LOCAL_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]', '::1']);
26
+ export class ConfigError extends Error {
27
+ constructor(message) {
28
+ super(message);
29
+ this.name = 'ConfigError';
30
+ }
31
+ }
32
+ /** A value an MCP client left as its literal placeholder (e.g. `${ATHANLAB_API_KEY}`
33
+ * when the variable was not exported) means "not set", not "malformed". */
34
+ function unexpanded(value) {
35
+ return !!value && /^\$\{[^}]*\}$/.test(value.trim());
36
+ }
37
+ export function checkApiKey(raw) {
38
+ const value = unexpanded(raw) ? '' : raw?.trim() ?? '';
39
+ if (!value) {
40
+ return {
41
+ ok: false,
42
+ code: 'missing_api_key',
43
+ message: 'ATHANLAB_API_KEY is not set. Add your AthanLab API key (ak_live_ followed by 32 hex characters) to this MCP server\'s environment.',
44
+ };
45
+ }
46
+ if (!API_KEY_PATTERN.test(value)) {
47
+ // Never echo the value: it may be a real key with a typo, or another secret.
48
+ return {
49
+ ok: false,
50
+ code: 'invalid_api_key_format',
51
+ message: 'ATHANLAB_API_KEY is malformed: an AthanLab key is ak_live_ followed by exactly 32 lowercase hex characters. Copy it again from the Developer API page. It was not sent to the API.',
52
+ };
53
+ }
54
+ return { ok: true, key: value };
55
+ }
56
+ export function parseApiBase(raw) {
57
+ const value = raw?.trim() || DEFAULT_API_BASE;
58
+ let url;
59
+ try {
60
+ url = new URL(value);
61
+ }
62
+ catch {
63
+ throw new ConfigError('ATHANLAB_API_BASE is not a valid URL.');
64
+ }
65
+ if (url.username || url.password) {
66
+ throw new ConfigError('ATHANLAB_API_BASE must not contain credentials.');
67
+ }
68
+ if (url.search || url.hash) {
69
+ throw new ConfigError('ATHANLAB_API_BASE must not contain a query string or fragment.');
70
+ }
71
+ if (url.protocol === 'http:') {
72
+ if (!LOCAL_HOSTS.has(url.hostname)) {
73
+ throw new ConfigError('ATHANLAB_API_BASE must use https (plain http is allowed only for localhost and 127.0.0.1).');
74
+ }
75
+ }
76
+ else if (url.protocol !== 'https:') {
77
+ throw new ConfigError('ATHANLAB_API_BASE must be an https URL.');
78
+ }
79
+ return url.toString().replace(/\/+$/, '');
80
+ }
81
+ export function parseMaxChars(raw) {
82
+ const value = raw?.trim();
83
+ if (!value)
84
+ return null;
85
+ if (!/^\d+$/.test(value) || Number(value) < 1 || !Number.isSafeInteger(Number(value))) {
86
+ throw new ConfigError('ATHANLAB_MAX_CHARS_PER_CALL must be a positive whole number of characters.');
87
+ }
88
+ return Number(value);
89
+ }
90
+ export function loadConfig(env = process.env, cwd = process.cwd()) {
91
+ return {
92
+ apiKey: checkApiKey(env.ATHANLAB_API_KEY),
93
+ apiBase: parseApiBase(unexpanded(env.ATHANLAB_API_BASE) ? undefined : env.ATHANLAB_API_BASE),
94
+ // Claude Code sets CLAUDE_PROJECT_DIR for every stdio server, and a user-scope
95
+ // server's working directory is not guaranteed to be the project.
96
+ outputDir: path.resolve(cwd, (!unexpanded(env.ATHANLAB_OUTPUT_DIR) && env.ATHANLAB_OUTPUT_DIR?.trim())
97
+ || (env.CLAUDE_PROJECT_DIR?.trim() ? path.join(env.CLAUDE_PROJECT_DIR.trim(), DEFAULT_OUTPUT_DIR) : DEFAULT_OUTPUT_DIR)),
98
+ maxCharsPerCall: parseMaxChars(env.ATHANLAB_MAX_CHARS_PER_CALL),
99
+ };
100
+ }
101
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}