@cognisos/liminal 0.1.1 → 0.2.1

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/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/version.ts
4
- var VERSION = true ? "0.1.1" : "0.1.1";
4
+ var VERSION = true ? "0.2.1" : "0.2.1";
5
5
  var BANNER_LINES = [
6
6
  " ___ ___ _____ ______ ___ ________ ________ ___",
7
7
  "|\\ \\ |\\ \\|\\ _ \\ _ \\|\\ \\|\\ ___ \\|\\ __ \\|\\ \\",
@@ -24,6 +24,9 @@ function printBanner() {
24
24
  // src/commands/init.ts
25
25
  import { createInterface } from "readline/promises";
26
26
  import { stdin, stdout } from "process";
27
+ import { existsSync as existsSync2, readFileSync as readFileSync2, appendFileSync } from "fs";
28
+ import { join as join2 } from "path";
29
+ import { homedir as homedir2 } from "os";
27
30
  import { RSCTransport, CircuitBreaker } from "@cognisos/rsc-sdk";
28
31
 
29
32
  // src/config/loader.ts
@@ -130,125 +133,418 @@ function maskApiKey(key) {
130
133
  return key.slice(0, 8) + "..." + key.slice(-4);
131
134
  }
132
135
 
133
- // src/commands/init.ts
134
- var TOOL_MAP = {
135
- "1": "claude-code",
136
- "2": "codex",
137
- "3": "cursor",
138
- "4": "openai-compatible"
136
+ // src/ui/prompts.ts
137
+ var ANSI = {
138
+ HIDE_CURSOR: "\x1B[?25l",
139
+ SHOW_CURSOR: "\x1B[?25h",
140
+ CLEAR_LINE: "\x1B[2K",
141
+ BOLD: "\x1B[1m",
142
+ DIM: "\x1B[2m",
143
+ CYAN: "\x1B[36m",
144
+ RESET: "\x1B[0m",
145
+ moveUp: (n) => n > 0 ? `\x1B[${n}A` : ""
139
146
  };
140
- function parseToolSelection(input) {
141
- const nums = input.split(",").map((s) => s.trim()).filter(Boolean);
142
- const tools = nums.map((n) => TOOL_MAP[n]).filter((t) => !!t);
143
- return tools.length > 0 ? tools : ["claude-code"];
147
+ function parseKey(data) {
148
+ if (data.length === 0) return { type: "other" };
149
+ if (data[0] === 3) return { type: "ctrlc" };
150
+ if (data.length >= 3 && data[0] === 27 && data[1] === 91) {
151
+ if (data[2] === 65) return { type: "up" };
152
+ if (data[2] === 66) return { type: "down" };
153
+ return { type: "other" };
154
+ }
155
+ if (data.length === 1 && data[0] === 27) return { type: "escape" };
156
+ if (data[0] === 13 || data[0] === 10) return { type: "enter" };
157
+ if (data[0] === 32) return { type: "space" };
158
+ return { type: "other" };
159
+ }
160
+ function renderSelect(options, cursorIndex, message) {
161
+ const lines = [];
162
+ lines.push(` ${ANSI.BOLD}${message}${ANSI.RESET}`);
163
+ lines.push("");
164
+ const maxLabel = Math.max(...options.map((o) => o.label.length));
165
+ for (let i = 0; i < options.length; i++) {
166
+ const focused = i === cursorIndex;
167
+ const pointer = focused ? `${ANSI.CYAN}->${ANSI.RESET}` : " ";
168
+ const label = focused ? `${ANSI.BOLD}${options[i].label.padEnd(maxLabel)}${ANSI.RESET}` : `${options[i].label.padEnd(maxLabel)}`;
169
+ const desc = options[i].description ? ` ${ANSI.DIM}${options[i].description}${ANSI.RESET}` : "";
170
+ lines.push(` ${pointer} ${label}${desc}`);
171
+ }
172
+ lines.push("");
173
+ return { text: lines.join("\n"), lineCount: lines.length };
174
+ }
175
+ function renderMultiSelect(options, cursorIndex, selected, message) {
176
+ const lines = [];
177
+ lines.push(` ${ANSI.BOLD}${message}${ANSI.RESET}`);
178
+ lines.push("");
179
+ const maxLabel = Math.max(...options.map((o) => o.label.length));
180
+ for (let i = 0; i < options.length; i++) {
181
+ const focused = i === cursorIndex;
182
+ const checked = selected.has(i);
183
+ const pointer = focused ? `${ANSI.CYAN}->${ANSI.RESET}` : " ";
184
+ const box = checked ? `${ANSI.CYAN}[x]${ANSI.RESET}` : `${ANSI.DIM}[ ]${ANSI.RESET}`;
185
+ const label = focused ? `${ANSI.BOLD}${options[i].label.padEnd(maxLabel)}${ANSI.RESET}` : `${options[i].label.padEnd(maxLabel)}`;
186
+ const desc = options[i].description ? ` ${ANSI.DIM}${options[i].description}${ANSI.RESET}` : "";
187
+ lines.push(` ${pointer} ${box} ${label}${desc}`);
188
+ }
189
+ lines.push("");
190
+ lines.push(` ${ANSI.DIM}Space to toggle, Enter to confirm${ANSI.RESET}`);
191
+ lines.push("");
192
+ return { text: lines.join("\n"), lineCount: lines.length };
193
+ }
194
+ function withRawMode(streams, handler) {
195
+ const { stdin: stdin2, stdout: stdout2 } = streams;
196
+ return new Promise((resolve, reject) => {
197
+ let cleaned = false;
198
+ function cleanup() {
199
+ if (cleaned) return;
200
+ cleaned = true;
201
+ stdin2.removeListener("data", onData);
202
+ if (stdin2.setRawMode) stdin2.setRawMode(false);
203
+ if ("pause" in stdin2 && typeof stdin2.pause === "function") {
204
+ stdin2.pause();
205
+ }
206
+ stdout2.write(ANSI.SHOW_CURSOR);
207
+ process.removeListener("exit", cleanup);
208
+ }
209
+ function onData(data) {
210
+ const key = parseKey(data);
211
+ if (key.type === "ctrlc") {
212
+ cleanup();
213
+ process.exit(130);
214
+ }
215
+ keyHandler(key);
216
+ }
217
+ const keyHandler = handler((value) => {
218
+ cleanup();
219
+ resolve(value);
220
+ });
221
+ process.on("exit", cleanup);
222
+ try {
223
+ if (stdin2.setRawMode) stdin2.setRawMode(true);
224
+ stdout2.write(ANSI.HIDE_CURSOR);
225
+ stdin2.on("data", onData);
226
+ if ("resume" in stdin2 && typeof stdin2.resume === "function") {
227
+ stdin2.resume();
228
+ }
229
+ } catch (err) {
230
+ cleanup();
231
+ reject(err);
232
+ }
233
+ });
234
+ }
235
+ async function selectPrompt(config) {
236
+ const { message, options, defaultIndex = 0, _streams } = config;
237
+ const streams = _streams ?? { stdin: process.stdin, stdout: process.stdout };
238
+ let cursorIndex = defaultIndex;
239
+ let prevLineCount = 0;
240
+ function draw() {
241
+ const { text, lineCount } = renderSelect(options, cursorIndex, message);
242
+ if (prevLineCount > 0) {
243
+ streams.stdout.write(ANSI.moveUp(prevLineCount));
244
+ }
245
+ const lines = text.split("\n");
246
+ for (const line of lines) {
247
+ streams.stdout.write(ANSI.CLEAR_LINE + line + "\n");
248
+ }
249
+ prevLineCount = lineCount;
250
+ }
251
+ draw();
252
+ const result = await withRawMode(streams, (resolve) => {
253
+ return (key) => {
254
+ switch (key.type) {
255
+ case "up":
256
+ cursorIndex = (cursorIndex - 1 + options.length) % options.length;
257
+ draw();
258
+ break;
259
+ case "down":
260
+ cursorIndex = (cursorIndex + 1) % options.length;
261
+ draw();
262
+ break;
263
+ case "enter":
264
+ resolve(options[cursorIndex].value);
265
+ break;
266
+ case "escape":
267
+ resolve(null);
268
+ break;
269
+ }
270
+ };
271
+ });
272
+ if (result !== null) {
273
+ const selected = options.find((o) => o.value === result);
274
+ if (selected) {
275
+ if (prevLineCount > 0) {
276
+ streams.stdout.write(ANSI.moveUp(prevLineCount));
277
+ }
278
+ for (let i = 0; i < prevLineCount; i++) {
279
+ streams.stdout.write(ANSI.CLEAR_LINE + "\n");
280
+ }
281
+ streams.stdout.write(ANSI.moveUp(prevLineCount));
282
+ streams.stdout.write(` ${ANSI.BOLD}${message}${ANSI.RESET} ${ANSI.CYAN}${selected.label}${ANSI.RESET}
283
+ `);
284
+ }
285
+ }
286
+ return result;
144
287
  }
145
- function printToolInstructions(tool, port) {
288
+ async function multiSelectPrompt(config) {
289
+ const { message, options, _streams } = config;
290
+ const streams = _streams ?? { stdin: process.stdin, stdout: process.stdout };
291
+ let cursorIndex = 0;
292
+ const selected = /* @__PURE__ */ new Set();
293
+ let prevLineCount = 0;
294
+ for (let i = 0; i < options.length; i++) {
295
+ if (options[i].default) selected.add(i);
296
+ }
297
+ function draw() {
298
+ const { text, lineCount } = renderMultiSelect(options, cursorIndex, selected, message);
299
+ if (prevLineCount > 0) {
300
+ streams.stdout.write(ANSI.moveUp(prevLineCount));
301
+ }
302
+ const lines = text.split("\n");
303
+ for (const line of lines) {
304
+ streams.stdout.write(ANSI.CLEAR_LINE + line + "\n");
305
+ }
306
+ prevLineCount = lineCount;
307
+ }
308
+ draw();
309
+ const result = await withRawMode(streams, (resolve) => {
310
+ return (key) => {
311
+ switch (key.type) {
312
+ case "up":
313
+ cursorIndex = (cursorIndex - 1 + options.length) % options.length;
314
+ draw();
315
+ break;
316
+ case "down":
317
+ cursorIndex = (cursorIndex + 1) % options.length;
318
+ draw();
319
+ break;
320
+ case "space":
321
+ if (selected.has(cursorIndex)) {
322
+ selected.delete(cursorIndex);
323
+ } else {
324
+ selected.add(cursorIndex);
325
+ }
326
+ draw();
327
+ break;
328
+ case "enter":
329
+ if (selected.size > 0) {
330
+ const values = [...selected].sort().map((i) => options[i].value);
331
+ resolve(values);
332
+ }
333
+ break;
334
+ case "escape":
335
+ resolve(null);
336
+ break;
337
+ }
338
+ };
339
+ });
340
+ if (result !== null) {
341
+ const labels = [...selected].sort().map((i) => options[i].label);
342
+ if (prevLineCount > 0) {
343
+ streams.stdout.write(ANSI.moveUp(prevLineCount));
344
+ }
345
+ for (let i = 0; i < prevLineCount; i++) {
346
+ streams.stdout.write(ANSI.CLEAR_LINE + "\n");
347
+ }
348
+ streams.stdout.write(ANSI.moveUp(prevLineCount));
349
+ streams.stdout.write(` ${ANSI.BOLD}${message}${ANSI.RESET} ${ANSI.CYAN}${labels.join(", ")}${ANSI.RESET}
350
+ `);
351
+ }
352
+ return result;
353
+ }
354
+
355
+ // src/commands/init.ts
356
+ function detectShellProfile() {
357
+ const shell = process.env.SHELL || "";
358
+ const home = homedir2();
359
+ if (shell.endsWith("/zsh")) {
360
+ const zshrc = join2(home, ".zshrc");
361
+ return { name: "~/.zshrc", path: zshrc };
362
+ }
363
+ if (shell.endsWith("/bash")) {
364
+ const bashProfile = join2(home, ".bash_profile");
365
+ if (existsSync2(bashProfile)) {
366
+ return { name: "~/.bash_profile", path: bashProfile };
367
+ }
368
+ return { name: "~/.bashrc", path: join2(home, ".bashrc") };
369
+ }
370
+ const candidates = [
371
+ { name: "~/.zshrc", path: join2(home, ".zshrc") },
372
+ { name: "~/.bashrc", path: join2(home, ".bashrc") },
373
+ { name: "~/.profile", path: join2(home, ".profile") }
374
+ ];
375
+ for (const c of candidates) {
376
+ if (existsSync2(c.path)) return c;
377
+ }
378
+ return null;
379
+ }
380
+ function getExportLines(tools, port) {
146
381
  const base = `http://127.0.0.1:${port}`;
147
- switch (tool) {
148
- case "claude-code":
149
- console.log(" Claude Code:");
150
- console.log(` export ANTHROPIC_BASE_URL=${base}`);
151
- console.log(" (Add to your shell profile for persistence)");
152
- console.log();
153
- break;
154
- case "codex":
155
- console.log(" Codex:");
156
- console.log(` export OPENAI_BASE_URL=${base}/v1`);
157
- console.log(" (Add to your shell profile for persistence)");
158
- console.log();
159
- break;
160
- case "cursor":
161
- console.log(" Cursor:");
162
- console.log(` Settings > Models > OpenAI API Base URL: ${base}/v1`);
163
- console.log();
164
- break;
165
- case "openai-compatible":
166
- console.log(" OpenAI-compatible tools:");
167
- console.log(` Set your base URL to: ${base}/v1`);
168
- console.log();
169
- break;
382
+ const lines = [];
383
+ if (tools.includes("claude-code")) {
384
+ lines.push(`export ANTHROPIC_BASE_URL=${base}`);
385
+ }
386
+ if (tools.includes("codex") || tools.includes("openai-compatible")) {
387
+ lines.push(`export OPENAI_BASE_URL=${base}/v1`);
388
+ }
389
+ return lines;
390
+ }
391
+ function lineExistsInFile(filePath, line) {
392
+ if (!existsSync2(filePath)) return false;
393
+ try {
394
+ const content = readFileSync2(filePath, "utf-8");
395
+ return content.includes(line);
396
+ } catch {
397
+ return false;
170
398
  }
171
399
  }
400
+ function appendToShellProfile(profile, lines) {
401
+ const block = [
402
+ "",
403
+ "# Liminal \u2014 route AI tools through compression proxy",
404
+ ...lines
405
+ ].join("\n") + "\n";
406
+ appendFileSync(profile.path, block, "utf-8");
407
+ }
172
408
  async function initCommand() {
173
- const rl = createInterface({ input: stdin, output: stdout });
174
409
  printBanner();
175
410
  console.log(" Welcome to Liminal -- Your Transparency & Context Partner");
176
411
  console.log();
177
412
  console.log(" Let's start evolving.");
178
413
  console.log();
414
+ const rl = createInterface({ input: stdin, output: stdout });
415
+ let apiKey;
416
+ let port;
179
417
  try {
180
- const apiKey = await rl.question(" \x1B[1mLiminal API key\x1B[0m: ");
181
- if (!apiKey.trim()) {
418
+ const apiKeyInput = await rl.question(" \x1B[1mLiminal API key\x1B[0m: ");
419
+ if (!apiKeyInput.trim()) {
182
420
  console.error("\n Error: API key is required.");
183
421
  process.exit(1);
184
422
  }
185
- const apiBaseUrl = DEFAULTS.apiBaseUrl;
423
+ apiKey = apiKeyInput.trim();
186
424
  const portInput = await rl.question(` Proxy port [${DEFAULTS.port}]: `);
187
- const port = portInput.trim() ? parseInt(portInput.trim(), 10) : DEFAULTS.port;
425
+ port = portInput.trim() ? parseInt(portInput.trim(), 10) : DEFAULTS.port;
188
426
  if (isNaN(port) || port < 1 || port > 65535) {
189
427
  console.error("\n Error: Invalid port number.");
190
428
  process.exit(1);
191
429
  }
192
- console.log();
193
- console.log(" Which AI tools will you use with Liminal?");
194
- console.log();
195
- console.log(" 1) Claude Code");
196
- console.log(" 2) Codex");
197
- console.log(" 3) Cursor");
198
- console.log(" 4) Other / OpenAI-compatible");
199
- console.log();
200
- const toolsInput = await rl.question(" Select tools (comma-separated, e.g. 1,3) [1]: ");
201
- const tools = parseToolSelection(toolsInput.trim() || "1");
202
- const learnInput = await rl.question(" Learn from LLM responses? [Y/n]: ");
203
- const learnFromResponses = learnInput.trim().toLowerCase() !== "n";
204
- console.log();
205
- process.stdout.write(" Validating API key... ");
206
- try {
207
- const breaker = new CircuitBreaker(3, 1e4);
208
- const transport = new RSCTransport({
209
- baseUrl: apiBaseUrl,
210
- apiKey: apiKey.trim(),
211
- timeout: 1e4,
212
- maxRetries: 1,
213
- circuitBreaker: breaker
214
- });
215
- await transport.get("/health");
216
- console.log("OK");
217
- } catch (err) {
218
- const message = err instanceof Error ? err.message : String(err);
219
- console.log("FAILED");
220
- console.error(`
430
+ } finally {
431
+ rl.close();
432
+ }
433
+ console.log();
434
+ const toolsResult = await multiSelectPrompt({
435
+ message: "Which AI tools will you use with Liminal?",
436
+ options: [
437
+ { label: "Claude Code", value: "claude-code", default: true },
438
+ { label: "Codex", value: "codex" },
439
+ { label: "Cursor", value: "cursor" },
440
+ { label: "Other / OpenAI", value: "openai-compatible" }
441
+ ]
442
+ });
443
+ const tools = toolsResult ?? ["claude-code"];
444
+ console.log();
445
+ const learnResult = await selectPrompt({
446
+ message: "Learn from LLM responses?",
447
+ options: [
448
+ { label: "Yes", value: true, description: "Improve compression over time" },
449
+ { label: "No", value: false, description: "Skip response learning" }
450
+ ],
451
+ defaultIndex: 0
452
+ });
453
+ const learnFromResponses = learnResult ?? true;
454
+ console.log();
455
+ const apiBaseUrl = DEFAULTS.apiBaseUrl;
456
+ process.stdout.write(" Validating API key... ");
457
+ try {
458
+ const breaker = new CircuitBreaker(3, 1e4);
459
+ const transport = new RSCTransport({
460
+ baseUrl: apiBaseUrl,
461
+ apiKey,
462
+ timeout: 1e4,
463
+ maxRetries: 1,
464
+ circuitBreaker: breaker
465
+ });
466
+ await transport.get("/health");
467
+ console.log("OK");
468
+ } catch (err) {
469
+ const message = err instanceof Error ? err.message : String(err);
470
+ console.log("FAILED");
471
+ console.error(`
221
472
  Could not connect to Liminal API: ${message}`);
222
- console.error(" Check your API key and URL, then try again.");
223
- process.exit(1);
473
+ console.error(" Check your API key and URL, then try again.");
474
+ process.exit(1);
475
+ }
476
+ ensureDirectories();
477
+ saveConfig({
478
+ apiKey,
479
+ apiBaseUrl,
480
+ upstreamBaseUrl: DEFAULTS.upstreamBaseUrl,
481
+ anthropicUpstreamUrl: DEFAULTS.anthropicUpstreamUrl,
482
+ port,
483
+ learnFromResponses,
484
+ tools,
485
+ compressionThreshold: DEFAULTS.compressionThreshold,
486
+ compressRoles: DEFAULTS.compressRoles,
487
+ latencyBudgetMs: DEFAULTS.latencyBudgetMs,
488
+ enabled: DEFAULTS.enabled
489
+ });
490
+ console.log();
491
+ console.log(` Configuration saved to ${CONFIG_FILE}`);
492
+ console.log();
493
+ const exportLines = getExportLines(tools, port);
494
+ const hasCursor = tools.includes("cursor");
495
+ if (exportLines.length > 0) {
496
+ const profile = detectShellProfile();
497
+ if (profile) {
498
+ const allExist = exportLines.every((line) => lineExistsInFile(profile.path, line));
499
+ if (allExist) {
500
+ console.log(` Shell already configured in ${profile.name}`);
501
+ } else {
502
+ const autoResult = await selectPrompt({
503
+ message: "Configure shell automatically?",
504
+ options: [
505
+ { label: "Yes", value: true, description: `Add to ${profile.name}` },
506
+ { label: "No", value: false, description: "I'll set it up manually" }
507
+ ],
508
+ defaultIndex: 0
509
+ });
510
+ if (autoResult === true) {
511
+ const newLines = exportLines.filter((line) => !lineExistsInFile(profile.path, line));
512
+ if (newLines.length > 0) {
513
+ appendToShellProfile(profile, newLines);
514
+ }
515
+ console.log();
516
+ console.log(` Added to ${profile.name}:`);
517
+ for (const line of exportLines) {
518
+ console.log(` ${line}`);
519
+ }
520
+ console.log();
521
+ console.log(` Run \x1B[1msource ${profile.name}\x1B[0m or restart your terminal to apply.`);
522
+ } else {
523
+ console.log();
524
+ console.log(" Add these to your shell profile:");
525
+ console.log();
526
+ for (const line of exportLines) {
527
+ console.log(` ${line}`);
528
+ }
529
+ }
530
+ }
531
+ } else {
532
+ console.log(" Add these to your shell profile:");
533
+ console.log();
534
+ for (const line of exportLines) {
535
+ console.log(` ${line}`);
536
+ }
224
537
  }
225
- ensureDirectories();
226
- saveConfig({
227
- apiKey: apiKey.trim(),
228
- apiBaseUrl,
229
- upstreamBaseUrl: DEFAULTS.upstreamBaseUrl,
230
- anthropicUpstreamUrl: DEFAULTS.anthropicUpstreamUrl,
231
- port,
232
- learnFromResponses,
233
- tools,
234
- compressionThreshold: DEFAULTS.compressionThreshold,
235
- compressRoles: DEFAULTS.compressRoles,
236
- latencyBudgetMs: DEFAULTS.latencyBudgetMs,
237
- enabled: DEFAULTS.enabled
238
- });
239
- console.log();
240
- console.log(` Configuration saved to ${CONFIG_FILE}`);
241
- console.log();
242
- console.log(" Next steps:");
243
- console.log(" 1. Start the proxy: liminal start");
244
- console.log(" 2. Connect your tools:");
538
+ }
539
+ if (hasCursor) {
245
540
  console.log();
246
- for (const tool of tools) {
247
- printToolInstructions(tool, port);
248
- }
249
- } finally {
250
- rl.close();
541
+ console.log(" Cursor setup (manual):");
542
+ console.log(` Settings > Models > OpenAI API Base URL: http://127.0.0.1:${port}/v1`);
251
543
  }
544
+ console.log();
545
+ console.log(" Next step:");
546
+ console.log(" liminal start");
547
+ console.log();
252
548
  }
253
549
 
254
550
  // src/rsc/pipeline.ts
@@ -911,7 +1207,7 @@ var ProxyServer = class {
911
1207
  };
912
1208
 
913
1209
  // src/daemon/logger.ts
914
- import { appendFileSync, statSync, renameSync, mkdirSync as mkdirSync2, existsSync as existsSync2 } from "fs";
1210
+ import { appendFileSync as appendFileSync2, statSync, renameSync, mkdirSync as mkdirSync2, existsSync as existsSync3 } from "fs";
915
1211
  import { dirname as dirname2 } from "path";
916
1212
  var MAX_LOG_SIZE = 10 * 1024 * 1024;
917
1213
  var MAX_BACKUPS = 2;
@@ -922,7 +1218,7 @@ var FileLogger = class {
922
1218
  this.logFile = options?.logFile ?? LOG_FILE;
923
1219
  this.mirrorStdout = options?.mirrorStdout ?? false;
924
1220
  const logDir = dirname2(this.logFile);
925
- if (!existsSync2(logDir)) {
1221
+ if (!existsSync3(logDir)) {
926
1222
  mkdirSync2(logDir, { recursive: true });
927
1223
  }
928
1224
  }
@@ -931,7 +1227,7 @@ var FileLogger = class {
931
1227
  const line = `[${timestamp}] ${message}
932
1228
  `;
933
1229
  try {
934
- appendFileSync(this.logFile, line);
1230
+ appendFileSync2(this.logFile, line);
935
1231
  } catch {
936
1232
  process.stderr.write(`[LOG-WRITE-FAILED] ${line}`);
937
1233
  }
@@ -947,7 +1243,7 @@ var FileLogger = class {
947
1243
  for (let i = MAX_BACKUPS - 1; i >= 1; i--) {
948
1244
  const from = `${this.logFile}.${i}`;
949
1245
  const to = `${this.logFile}.${i + 1}`;
950
- if (existsSync2(from)) renameSync(from, to);
1246
+ if (existsSync3(from)) renameSync(from, to);
951
1247
  }
952
1248
  renameSync(this.logFile, `${this.logFile}.1`);
953
1249
  } catch {
@@ -959,16 +1255,16 @@ var FileLogger = class {
959
1255
  };
960
1256
 
961
1257
  // src/daemon/lifecycle.ts
962
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, unlinkSync, existsSync as existsSync3 } from "fs";
1258
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, unlinkSync, existsSync as existsSync4 } from "fs";
963
1259
  import { fork } from "child_process";
964
1260
  import { fileURLToPath } from "url";
965
1261
  function writePidFile(pid) {
966
1262
  writeFileSync2(PID_FILE, String(pid), "utf-8");
967
1263
  }
968
1264
  function readPidFile() {
969
- if (!existsSync3(PID_FILE)) return null;
1265
+ if (!existsSync4(PID_FILE)) return null;
970
1266
  try {
971
- const content = readFileSync2(PID_FILE, "utf-8").trim();
1267
+ const content = readFileSync3(PID_FILE, "utf-8").trim();
972
1268
  const pid = parseInt(content, 10);
973
1269
  return isNaN(pid) ? null : pid;
974
1270
  } catch {
@@ -977,7 +1273,7 @@ function readPidFile() {
977
1273
  }
978
1274
  function removePidFile() {
979
1275
  try {
980
- if (existsSync3(PID_FILE)) unlinkSync(PID_FILE);
1276
+ if (existsSync4(PID_FILE)) unlinkSync(PID_FILE);
981
1277
  } catch {
982
1278
  }
983
1279
  }
@@ -1358,17 +1654,17 @@ async function configCommand(flags) {
1358
1654
  }
1359
1655
 
1360
1656
  // src/commands/logs.ts
1361
- import { readFileSync as readFileSync3, existsSync as existsSync4, statSync as statSync2, createReadStream } from "fs";
1657
+ import { readFileSync as readFileSync4, existsSync as existsSync5, statSync as statSync2, createReadStream } from "fs";
1362
1658
  import { watchFile, unwatchFile } from "fs";
1363
1659
  async function logsCommand(flags) {
1364
1660
  const follow = flags.has("follow") || flags.has("f");
1365
1661
  const linesFlag = flags.get("lines") ?? flags.get("n");
1366
1662
  const lines = typeof linesFlag === "string" ? parseInt(linesFlag, 10) : 50;
1367
- if (!existsSync4(LOG_FILE)) {
1663
+ if (!existsSync5(LOG_FILE)) {
1368
1664
  console.log('No log file found. Start the daemon with "liminal start" to generate logs.');
1369
1665
  return;
1370
1666
  }
1371
- const content = readFileSync3(LOG_FILE, "utf-8");
1667
+ const content = readFileSync4(LOG_FILE, "utf-8");
1372
1668
  const allLines = content.split("\n");
1373
1669
  const tail = allLines.slice(-lines - 1);
1374
1670
  process.stdout.write(tail.join("\n"));
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts","../src/commands/init.ts","../src/config/loader.ts","../src/config/paths.ts","../src/config/schema.ts","../src/rsc/pipeline.ts","../src/proxy/completions.ts","../src/rsc/message-compressor.ts","../src/rsc/learning.ts","../src/proxy/streaming.ts","../src/proxy/messages.ts","../src/proxy/anthropic-streaming.ts","../src/proxy/handler.ts","../src/proxy/server.ts","../src/daemon/logger.ts","../src/daemon/lifecycle.ts","../src/commands/start.ts","../src/commands/stop.ts","../src/commands/status.ts","../src/commands/summary.ts","../src/commands/config.ts","../src/commands/logs.ts","../src/bin.ts"],"sourcesContent":["declare const __VERSION__: string\nexport const VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.1.1'\n\n// FIGlet-style \"LIMINAL\" banner\nconst BANNER_LINES = [\n ' ___ ___ _____ ______ ___ ________ ________ ___',\n '|\\\\ \\\\ |\\\\ \\\\|\\\\ _ \\\\ _ \\\\|\\\\ \\\\|\\\\ ___ \\\\|\\\\ __ \\\\|\\\\ \\\\',\n '\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\\\\\__\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\ \\\\ \\\\ \\\\ \\\\|\\\\ \\\\ \\\\ \\\\',\n ' \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\|__| \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\ \\\\ \\\\ \\\\ __ \\\\ \\\\ \\\\',\n ' \\\\ \\\\ \\\\____\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\____',\n ' \\\\ \\\\_______\\\\ \\\\__\\\\ \\\\__\\\\ \\\\ \\\\__\\\\ \\\\__\\\\ \\\\__\\\\\\\\ \\\\__\\\\ \\\\__\\\\ \\\\__\\\\ \\\\_______\\\\',\n ' \\\\|_______|\\\\|__|\\\\|__| \\\\|__|\\\\|__|\\\\|__| \\\\|__|\\\\|__|\\\\|__|\\\\|_______|',\n]\n\nexport function printBanner(): void {\n console.log()\n for (const line of BANNER_LINES) {\n console.log(line)\n }\n console.log()\n console.log(` v${VERSION} -- brought to you by Cognisos`)\n console.log()\n}\n","import { createInterface } from 'node:readline/promises'\nimport { stdin, stdout } from 'node:process'\nimport { RSCTransport, CircuitBreaker } from '@cognisos/rsc-sdk'\nimport { saveConfig, ensureDirectories } from '../config/loader.js'\nimport { DEFAULTS } from '../config/schema.js'\nimport { CONFIG_FILE } from '../config/paths.js'\nimport { printBanner } from '../version.js'\nimport type { Tool } from '../types.js'\n\nconst TOOL_MAP: Record<string, Tool> = {\n '1': 'claude-code',\n '2': 'codex',\n '3': 'cursor',\n '4': 'openai-compatible',\n}\n\nfunction parseToolSelection(input: string): Tool[] {\n const nums = input.split(',').map((s) => s.trim()).filter(Boolean)\n const tools = nums.map((n) => TOOL_MAP[n]).filter((t): t is Tool => !!t)\n return tools.length > 0 ? tools : ['claude-code']\n}\n\nfunction printToolInstructions(tool: Tool, port: number): void {\n const base = `http://127.0.0.1:${port}`\n switch (tool) {\n case 'claude-code':\n console.log(' Claude Code:')\n console.log(` export ANTHROPIC_BASE_URL=${base}`)\n console.log(' (Add to your shell profile for persistence)')\n console.log()\n break\n case 'codex':\n console.log(' Codex:')\n console.log(` export OPENAI_BASE_URL=${base}/v1`)\n console.log(' (Add to your shell profile for persistence)')\n console.log()\n break\n case 'cursor':\n console.log(' Cursor:')\n console.log(` Settings > Models > OpenAI API Base URL: ${base}/v1`)\n console.log()\n break\n case 'openai-compatible':\n console.log(' OpenAI-compatible tools:')\n console.log(` Set your base URL to: ${base}/v1`)\n console.log()\n break\n }\n}\n\nexport async function initCommand(): Promise<void> {\n const rl = createInterface({ input: stdin, output: stdout })\n\n printBanner()\n console.log(' Welcome to Liminal -- Your Transparency & Context Partner')\n console.log()\n console.log(\" Let's start evolving.\")\n console.log()\n\n try {\n // API key\n const apiKey = await rl.question(' \\x1b[1mLiminal API key\\x1b[0m: ')\n if (!apiKey.trim()) {\n console.error('\\n Error: API key is required.')\n process.exit(1)\n }\n\n const apiBaseUrl = DEFAULTS.apiBaseUrl\n\n // Port\n const portInput = await rl.question(` Proxy port [${DEFAULTS.port}]: `)\n const port = portInput.trim() ? parseInt(portInput.trim(), 10) : DEFAULTS.port\n if (isNaN(port) || port < 1 || port > 65535) {\n console.error('\\n Error: Invalid port number.')\n process.exit(1)\n }\n\n // Tool selection\n console.log()\n console.log(' Which AI tools will you use with Liminal?')\n console.log()\n console.log(' 1) Claude Code')\n console.log(' 2) Codex')\n console.log(' 3) Cursor')\n console.log(' 4) Other / OpenAI-compatible')\n console.log()\n const toolsInput = await rl.question(' Select tools (comma-separated, e.g. 1,3) [1]: ')\n const tools = parseToolSelection(toolsInput.trim() || '1')\n\n // Learn from responses\n const learnInput = await rl.question(' Learn from LLM responses? [Y/n]: ')\n const learnFromResponses = learnInput.trim().toLowerCase() !== 'n'\n\n console.log()\n\n // Validate API key\n process.stdout.write(' Validating API key... ')\n try {\n const breaker = new CircuitBreaker(3, 10_000)\n const transport = new RSCTransport({\n baseUrl: apiBaseUrl,\n apiKey: apiKey.trim(),\n timeout: 10_000,\n maxRetries: 1,\n circuitBreaker: breaker,\n })\n await transport.get<{ status: string }>('/health')\n console.log('OK')\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n console.log('FAILED')\n console.error(`\\n Could not connect to Liminal API: ${message}`)\n console.error(' Check your API key and URL, then try again.')\n process.exit(1)\n }\n\n // Save config\n ensureDirectories()\n saveConfig({\n apiKey: apiKey.trim(),\n apiBaseUrl,\n upstreamBaseUrl: DEFAULTS.upstreamBaseUrl,\n anthropicUpstreamUrl: DEFAULTS.anthropicUpstreamUrl,\n port,\n learnFromResponses,\n tools,\n compressionThreshold: DEFAULTS.compressionThreshold,\n compressRoles: DEFAULTS.compressRoles,\n latencyBudgetMs: DEFAULTS.latencyBudgetMs,\n enabled: DEFAULTS.enabled,\n })\n\n console.log()\n console.log(` Configuration saved to ${CONFIG_FILE}`)\n console.log()\n console.log(' Next steps:')\n console.log(' 1. Start the proxy: liminal start')\n console.log(' 2. Connect your tools:')\n console.log()\n\n for (const tool of tools) {\n printToolInstructions(tool, port)\n }\n } finally {\n rl.close()\n }\n}\n","import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { LIMINAL_DIR, CONFIG_FILE, LOG_DIR } from './paths.js'\nimport { DEFAULTS } from './schema.js'\nimport type { RSCConfig } from './schema.js'\n\n/**\n * Load config from ~/.liminal/config.json, merged with defaults and env var overrides.\n * Priority: env vars > config file > defaults\n */\nexport function loadConfig(): RSCConfig {\n let fileConfig: Partial<RSCConfig> = {}\n\n if (existsSync(CONFIG_FILE)) {\n try {\n const raw = readFileSync(CONFIG_FILE, 'utf-8')\n fileConfig = JSON.parse(raw)\n } catch {\n // Corrupted config file — fall through to defaults\n }\n }\n\n const merged: RSCConfig = {\n apiKey: fileConfig.apiKey ?? '',\n apiBaseUrl: DEFAULTS.apiBaseUrl,\n upstreamBaseUrl: DEFAULTS.upstreamBaseUrl,\n anthropicUpstreamUrl: DEFAULTS.anthropicUpstreamUrl,\n port: DEFAULTS.port,\n compressionThreshold: DEFAULTS.compressionThreshold,\n compressRoles: DEFAULTS.compressRoles,\n learnFromResponses: DEFAULTS.learnFromResponses,\n latencyBudgetMs: DEFAULTS.latencyBudgetMs,\n enabled: DEFAULTS.enabled,\n tools: DEFAULTS.tools,\n ...fileConfig,\n }\n\n // Environment variable overrides\n if (process.env.LIMINAL_API_KEY) merged.apiKey = process.env.LIMINAL_API_KEY\n if (process.env.LIMINAL_API_URL) merged.apiBaseUrl = process.env.LIMINAL_API_URL\n if (process.env.LIMINAL_UPSTREAM_URL) merged.upstreamBaseUrl = process.env.LIMINAL_UPSTREAM_URL\n if (process.env.LIMINAL_ANTHROPIC_URL) merged.anthropicUpstreamUrl = process.env.LIMINAL_ANTHROPIC_URL\n if (process.env.LIMINAL_PORT) merged.port = parseInt(process.env.LIMINAL_PORT, 10)\n\n return merged\n}\n\n/**\n * Apply CLI flag overrides on top of loaded config.\n */\nexport function applyOverrides(\n config: RSCConfig,\n overrides: Partial<Pick<RSCConfig, 'port' | 'upstreamBaseUrl'>>,\n): RSCConfig {\n return { ...config, ...overrides }\n}\n\n/**\n * Save config to ~/.liminal/config.json. Creates ~/.liminal/ and ~/.liminal/logs/ if needed.\n */\nexport function saveConfig(config: Partial<RSCConfig>): void {\n ensureDirectories()\n\n let existing: Partial<RSCConfig> = {}\n if (existsSync(CONFIG_FILE)) {\n try {\n existing = JSON.parse(readFileSync(CONFIG_FILE, 'utf-8'))\n } catch {\n // Overwrite corrupted file\n }\n }\n\n const merged = { ...existing, ...config }\n writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2) + '\\n', 'utf-8')\n}\n\n/**\n * Ensure ~/.liminal/ and ~/.liminal/logs/ directories exist.\n */\nexport function ensureDirectories(): void {\n if (!existsSync(LIMINAL_DIR)) mkdirSync(LIMINAL_DIR, { recursive: true })\n if (!existsSync(LOG_DIR)) mkdirSync(LOG_DIR, { recursive: true })\n // Ensure parent of config file exists\n const configDir = dirname(CONFIG_FILE)\n if (!existsSync(configDir)) mkdirSync(configDir, { recursive: true })\n}\n\n/**\n * Check if a valid config file exists with an API key.\n */\nexport function isConfigured(): boolean {\n try {\n const config = loadConfig()\n return config.apiKey.length > 0\n } catch {\n return false\n }\n}\n\n/**\n * Mask an API key for display: show first 8 chars + last 4.\n */\nexport function maskApiKey(key: string): string {\n if (key.length <= 12) return '****'\n return key.slice(0, 8) + '...' + key.slice(-4)\n}\n","import { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport const LIMINAL_DIR = join(homedir(), '.liminal')\nexport const CONFIG_FILE = join(LIMINAL_DIR, 'config.json')\nexport const PID_FILE = join(LIMINAL_DIR, 'liminal.pid')\nexport const LOG_DIR = join(LIMINAL_DIR, 'logs')\nexport const LOG_FILE = join(LOG_DIR, 'liminal.log')\n","export interface RSCConfig {\n apiKey: string\n apiBaseUrl: string\n upstreamBaseUrl: string\n anthropicUpstreamUrl: string\n port: number\n compressionThreshold: number\n compressRoles: string[]\n learnFromResponses: boolean\n latencyBudgetMs: number\n enabled: boolean\n tools: string[]\n}\n\nexport const DEFAULTS: Omit<RSCConfig, 'apiKey'> = {\n apiBaseUrl: 'https://rsc-platform-production.up.railway.app',\n upstreamBaseUrl: 'https://api.openai.com',\n anthropicUpstreamUrl: 'https://api.anthropic.com',\n port: 3141,\n compressionThreshold: 100,\n compressRoles: ['user'],\n learnFromResponses: true,\n latencyBudgetMs: 0,\n enabled: true,\n tools: [],\n}\n\n/** Keys that can be set via `liminal config --set` */\nexport const CONFIGURABLE_KEYS = new Set<string>([\n 'apiBaseUrl',\n 'upstreamBaseUrl',\n 'anthropicUpstreamUrl',\n 'port',\n 'compressionThreshold',\n 'compressRoles',\n 'learnFromResponses',\n 'latencyBudgetMs',\n 'enabled',\n 'tools',\n])\n","import {\n CompressionPipeline,\n RSCTransport,\n RSCEventEmitter,\n Session,\n CircuitBreaker,\n} from '@cognisos/rsc-sdk'\nimport type { SessionSummary, CircuitState } from '@cognisos/rsc-sdk'\n\nexport interface PipelineConfig {\n rscApiKey: string\n rscBaseUrl: string\n compressionThreshold: number\n learnFromResponses: boolean\n latencyBudgetMs?: number\n sessionId?: string\n}\n\nexport class RSCPipelineWrapper {\n readonly pipeline: CompressionPipeline\n readonly session: Session\n readonly events: RSCEventEmitter\n readonly transport: RSCTransport\n private readonly circuitBreaker: CircuitBreaker\n\n constructor(config: PipelineConfig) {\n this.circuitBreaker = new CircuitBreaker(5, 5 * 60 * 1000)\n\n this.transport = new RSCTransport({\n baseUrl: config.rscBaseUrl,\n apiKey: config.rscApiKey,\n timeout: 30_000,\n maxRetries: 3,\n circuitBreaker: this.circuitBreaker,\n })\n\n this.events = new RSCEventEmitter()\n this.session = new Session(config.sessionId)\n\n this.pipeline = new CompressionPipeline(\n this.transport,\n {\n threshold: config.compressionThreshold,\n learnFromResponses: config.learnFromResponses,\n latencyBudgetMs: config.latencyBudgetMs,\n sessionId: this.session.sessionId,\n },\n this.events,\n )\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n await this.transport.get<{ status: string }>('/health')\n return true\n } catch {\n return false\n }\n }\n\n getSessionSummary(): SessionSummary {\n return this.session.getSummary()\n }\n\n getCircuitState(): CircuitState {\n return this.circuitBreaker.getState()\n }\n\n isCircuitOpen(): boolean {\n return this.circuitBreaker.getState() === 'open'\n }\n\n resetCircuitBreaker(): void {\n this.circuitBreaker.reset()\n }\n}\n","import * as http from 'node:http'\nimport { RSCCircuitOpenError } from '@cognisos/rsc-sdk'\nimport { compressMessages } from '../rsc/message-compressor.js'\nimport { createStreamLearningBuffer } from '../rsc/learning.js'\nimport { pipeSSEResponse } from './streaming.js'\nimport type { RSCPipelineWrapper } from '../rsc/pipeline.js'\nimport type { ChatCompletionRequest, ResolvedConfig } from '../types.js'\nimport type { Logger } from './handler.js'\n\nfunction setCORSHeaders(res: http.ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization')\n}\n\nfunction sendJSON(res: http.ServerResponse, status: number, body: unknown): void {\n setCORSHeaders(res)\n res.writeHead(status, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify(body))\n}\n\n/**\n * Extract the bearer token from the Authorization header.\n * This is the user's LLM API key — used to forward to the upstream LLM.\n */\nfunction extractBearerToken(req: http.IncomingMessage): string | null {\n const auth = req.headers.authorization\n if (!auth || !auth.startsWith('Bearer ')) return null\n return auth.slice(7)\n}\n\nexport async function handleChatCompletions(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body: unknown,\n pipeline: RSCPipelineWrapper,\n config: ResolvedConfig,\n logger: Logger,\n): Promise<void> {\n const request = body as ChatCompletionRequest\n\n // Validate required fields\n if (!request.messages || !Array.isArray(request.messages)) {\n sendJSON(res, 400, {\n error: { message: 'messages is required and must be an array', type: 'invalid_request_error' },\n })\n return\n }\n\n // Extract LLM API key from the incoming request\n const llmApiKey = extractBearerToken(req)\n if (!llmApiKey) {\n sendJSON(res, 401, {\n error: { message: 'Authorization header with Bearer token is required', type: 'authentication_error' },\n })\n return\n }\n\n // Compress messages (or passthrough if circuit is open / disabled)\n let messages = request.messages\n let anyCompressed = false\n\n if (config.enabled && !pipeline.isCircuitOpen()) {\n try {\n const compressRoles = new Set(config.compressRoles)\n const result = await compressMessages(\n request.messages,\n pipeline.pipeline,\n pipeline.session,\n compressRoles,\n )\n messages = result.messages\n anyCompressed = result.anyCompressed\n\n if (result.totalTokensSaved > 0) {\n logger.log(`[COMPRESS] Saved ${result.totalTokensSaved} tokens`)\n }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n logger.log('[DEGRADE] Circuit breaker open — passing through directly')\n } else {\n logger.log(`[ERROR] Compression failed: ${err instanceof Error ? err.message : String(err)}`)\n }\n // Fall through with original messages\n messages = request.messages\n }\n }\n\n // Build upstream request\n const upstreamUrl = `${config.upstreamBaseUrl}/v1/chat/completions`\n const upstreamBody = { ...request, messages }\n\n const upstreamHeaders: Record<string, string> = {\n 'Authorization': `Bearer ${llmApiKey}`,\n 'Content-Type': 'application/json',\n }\n\n // Forward streaming preference\n if (request.stream) {\n upstreamHeaders['Accept'] = 'text/event-stream'\n }\n\n try {\n const upstreamResponse = await fetch(upstreamUrl, {\n method: 'POST',\n headers: upstreamHeaders,\n body: JSON.stringify(upstreamBody),\n })\n\n // Handle upstream errors\n if (!upstreamResponse.ok) {\n const errorBody = await upstreamResponse.text()\n setCORSHeaders(res)\n res.writeHead(upstreamResponse.status, {\n 'Content-Type': upstreamResponse.headers.get('Content-Type') || 'application/json',\n })\n res.end(errorBody)\n return\n }\n\n // Streaming response\n if (request.stream && upstreamResponse.body) {\n const learningBuffer = anyCompressed\n ? createStreamLearningBuffer(pipeline.pipeline)\n : null\n\n await pipeSSEResponse(\n upstreamResponse,\n res,\n (text) => learningBuffer?.append(text),\n () => learningBuffer?.flush(),\n )\n return\n }\n\n // Non-streaming response\n const responseBody = await upstreamResponse.text()\n setCORSHeaders(res)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(responseBody)\n\n // Trigger learning from response (fire-and-forget)\n if (anyCompressed) {\n try {\n const parsed = JSON.parse(responseBody)\n const content = parsed?.choices?.[0]?.message?.content\n if (typeof content === 'string' && content.length > 0) {\n pipeline.pipeline.triggerLearning(content)\n }\n } catch {\n // Ignore learning parse errors\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[ERROR] Upstream request failed: ${message}`)\n if (!res.headersSent) {\n sendJSON(res, 502, {\n error: { message: `Failed to reach upstream LLM: ${message}`, type: 'server_error' },\n })\n }\n }\n}\n","import type { CompressionPipeline, Session } from '@cognisos/rsc-sdk'\nimport { RSCCircuitOpenError } from '@cognisos/rsc-sdk'\nimport type { ChatCompletionMessage, ContentPart } from '../types.js'\n\nexport interface CompressedMessagesResult {\n messages: ChatCompletionMessage[]\n anyCompressed: boolean\n totalTokensSaved: number\n}\n\n/**\n * Walk an array of ChatCompletion messages and compress eligible ones\n * via the RSC CompressionPipeline. Non-eligible roles and non-text\n * content parts pass through unchanged.\n */\nexport async function compressMessages(\n messages: ChatCompletionMessage[],\n pipeline: CompressionPipeline,\n session: Session,\n compressRoles: Set<string>,\n): Promise<CompressedMessagesResult> {\n let anyCompressed = false\n let totalTokensSaved = 0\n\n const compressed = await Promise.all(\n messages.map(async (msg) => {\n if (!compressRoles.has(msg.role)) return msg\n\n // String content\n if (typeof msg.content === 'string') {\n return compressStringContent(msg, pipeline, session, (c, saved) => {\n anyCompressed = anyCompressed || c\n totalTokensSaved += saved\n })\n }\n\n // Array content (vision messages with text + image parts)\n if (Array.isArray(msg.content)) {\n return compressArrayContent(msg, pipeline, session, (c, saved) => {\n anyCompressed = anyCompressed || c\n totalTokensSaved += saved\n })\n }\n\n // null or other content — pass through\n return msg\n }),\n )\n\n return { messages: compressed, anyCompressed, totalTokensSaved }\n}\n\nasync function compressStringContent(\n msg: ChatCompletionMessage,\n pipeline: CompressionPipeline,\n session: Session,\n record: (compressed: boolean, saved: number) => void,\n): Promise<ChatCompletionMessage> {\n try {\n const result = await pipeline.compressForLLM(msg.content as string)\n session.recordCompression(result.metrics)\n record(!result.metrics.skipped, result.metrics.tokensSaved)\n return { ...msg, content: result.text }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n session.recordFailure()\n throw err\n }\n // Other RSC errors — return original text, don't block the request\n session.recordFailure()\n return msg\n }\n}\n\nasync function compressArrayContent(\n msg: ChatCompletionMessage,\n pipeline: CompressionPipeline,\n session: Session,\n record: (compressed: boolean, saved: number) => void,\n): Promise<ChatCompletionMessage> {\n const parts = msg.content as ContentPart[]\n\n const compressedParts = await Promise.all(\n parts.map(async (part) => {\n if (part.type === 'text' && typeof part.text === 'string') {\n try {\n const result = await pipeline.compressForLLM(part.text)\n session.recordCompression(result.metrics)\n record(!result.metrics.skipped, result.metrics.tokensSaved)\n return { ...part, text: result.text }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n session.recordFailure()\n throw err\n }\n session.recordFailure()\n return part\n }\n }\n // Pass through image_url, tool_use, etc.\n return part\n }),\n )\n\n return { ...msg, content: compressedParts }\n}\n","import type { CompressionPipeline } from '@cognisos/rsc-sdk'\n\n/**\n * Creates a buffer that accumulates streamed response text and triggers\n * background learning when the stream completes.\n */\nexport function createStreamLearningBuffer(pipeline: CompressionPipeline) {\n let buffer = ''\n\n return {\n /** Append a text delta from an SSE chunk */\n append(text: string): void {\n buffer += text\n },\n\n /** Flush the buffer — triggers fire-and-forget learning */\n flush(): void {\n if (buffer.length > 0) {\n pipeline.triggerLearning(buffer)\n buffer = ''\n }\n },\n\n /** Get current buffer contents (for testing) */\n getBuffer(): string {\n return buffer\n },\n }\n}\n","import * as http from 'node:http'\n\n/**\n * Pipe an SSE response from an upstream LLM to the client,\n * parsing content deltas for the learning buffer.\n *\n * Writes each chunk immediately — zero buffering, zero added latency.\n */\nexport async function pipeSSEResponse(\n upstreamResponse: Response,\n clientRes: http.ServerResponse,\n onContentDelta: (text: string) => void,\n onComplete: () => void,\n): Promise<void> {\n clientRes.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n })\n\n const reader = upstreamResponse.body!.getReader()\n const decoder = new TextDecoder()\n let lineBuf = ''\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n const chunk = decoder.decode(value, { stream: true })\n\n // Write immediately to client\n clientRes.write(chunk)\n\n // Parse SSE lines for learning (best-effort, never blocks the pipe)\n lineBuf += chunk\n const lines = lineBuf.split('\\n')\n lineBuf = lines.pop() || ''\n\n for (const line of lines) {\n if (line.startsWith('data: ') && line !== 'data: [DONE]') {\n try {\n const json = JSON.parse(line.slice(6))\n const content = json?.choices?.[0]?.delta?.content\n if (typeof content === 'string') {\n onContentDelta(content)\n }\n } catch {\n // Malformed SSE data — ignore for learning, chunk already piped\n }\n }\n }\n }\n } finally {\n clientRes.end()\n onComplete()\n }\n}\n","import * as http from 'node:http'\nimport { RSCCircuitOpenError } from '@cognisos/rsc-sdk'\nimport { compressMessages } from '../rsc/message-compressor.js'\nimport { createStreamLearningBuffer } from '../rsc/learning.js'\nimport { pipeAnthropicSSEResponse } from './anthropic-streaming.js'\nimport type { RSCPipelineWrapper } from '../rsc/pipeline.js'\nimport type { ChatCompletionMessage, ResolvedConfig } from '../types.js'\nimport type { AnthropicMessagesRequest, AnthropicMessage, AnthropicContentBlock } from '../types/anthropic.js'\nimport type { Logger } from './handler.js'\n\nfunction setCORSHeaders(res: http.ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-api-key, anthropic-version, anthropic-beta')\n}\n\nfunction sendAnthropicError(res: http.ServerResponse, status: number, type: string, message: string): void {\n setCORSHeaders(res)\n res.writeHead(status, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({ type: 'error', error: { type, message } }))\n}\n\nfunction extractAnthropicApiKey(req: http.IncomingMessage): string | null {\n const key = req.headers['x-api-key']\n if (typeof key === 'string' && key.length > 0) return key\n return null\n}\n\n/**\n * Convert Anthropic messages to ChatCompletionMessage[] for the compressor.\n * The structures are compatible — this is a thin adapter.\n */\nfunction convertAnthropicToCompressible(messages: AnthropicMessage[]): ChatCompletionMessage[] {\n return messages.map((msg) => ({\n role: msg.role,\n content: msg.content as string | AnthropicContentBlock[],\n }))\n}\n\n/**\n * Convert compressed ChatCompletionMessage[] back to Anthropic format.\n */\nfunction convertCompressedToAnthropic(messages: ChatCompletionMessage[]): AnthropicMessage[] {\n return messages.map((msg) => ({\n role: msg.role as 'user' | 'assistant',\n content: msg.content as string | AnthropicContentBlock[],\n }))\n}\n\nexport async function handleAnthropicMessages(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body: unknown,\n pipeline: RSCPipelineWrapper,\n config: ResolvedConfig,\n logger: Logger,\n): Promise<void> {\n const request = body as AnthropicMessagesRequest\n\n // Validate required fields\n if (!request.messages || !Array.isArray(request.messages)) {\n sendAnthropicError(res, 400, 'invalid_request_error', 'messages is required and must be an array')\n return\n }\n\n if (typeof request.max_tokens !== 'number') {\n sendAnthropicError(res, 400, 'invalid_request_error', 'max_tokens is required')\n return\n }\n\n // Extract API key from x-api-key header\n const apiKey = extractAnthropicApiKey(req)\n if (!apiKey) {\n sendAnthropicError(res, 401, 'authentication_error', 'x-api-key header is required')\n return\n }\n\n // Compress messages (reuse existing compressor via format conversion)\n let messages = request.messages\n let anyCompressed = false\n\n if (config.enabled && !pipeline.isCircuitOpen()) {\n try {\n const compressRoles = new Set(config.compressRoles)\n const compressible = convertAnthropicToCompressible(request.messages)\n const result = await compressMessages(\n compressible,\n pipeline.pipeline,\n pipeline.session,\n compressRoles,\n )\n messages = convertCompressedToAnthropic(result.messages)\n anyCompressed = result.anyCompressed\n\n if (result.totalTokensSaved > 0) {\n logger.log(`[COMPRESS] Saved ${result.totalTokensSaved} tokens`)\n }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n logger.log('[DEGRADE] Circuit breaker open -- passing through directly')\n } else {\n logger.log(`[ERROR] Compression failed: ${err instanceof Error ? err.message : String(err)}`)\n }\n messages = request.messages\n }\n }\n\n // Build upstream request\n const upstreamUrl = `${config.anthropicUpstreamUrl}/v1/messages`\n const upstreamBody = { ...request, messages }\n\n const upstreamHeaders: Record<string, string> = {\n 'x-api-key': apiKey,\n 'anthropic-version': (req.headers['anthropic-version'] as string) || '2023-06-01',\n 'Content-Type': 'application/json',\n }\n\n // Forward anthropic-beta header if present\n const betaHeader = req.headers['anthropic-beta']\n if (typeof betaHeader === 'string') {\n upstreamHeaders['anthropic-beta'] = betaHeader\n }\n\n try {\n const upstreamResponse = await fetch(upstreamUrl, {\n method: 'POST',\n headers: upstreamHeaders,\n body: JSON.stringify(upstreamBody),\n })\n\n // Handle upstream errors\n if (!upstreamResponse.ok) {\n const errorBody = await upstreamResponse.text()\n setCORSHeaders(res)\n res.writeHead(upstreamResponse.status, {\n 'Content-Type': upstreamResponse.headers.get('Content-Type') || 'application/json',\n })\n res.end(errorBody)\n return\n }\n\n // Streaming response\n if (request.stream && upstreamResponse.body) {\n const learningBuffer = anyCompressed\n ? createStreamLearningBuffer(pipeline.pipeline)\n : null\n\n await pipeAnthropicSSEResponse(\n upstreamResponse,\n res,\n (text) => learningBuffer?.append(text),\n () => learningBuffer?.flush(),\n )\n return\n }\n\n // Non-streaming response\n const responseBody = await upstreamResponse.text()\n setCORSHeaders(res)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(responseBody)\n\n // Trigger learning from response (fire-and-forget)\n if (anyCompressed) {\n try {\n const parsed = JSON.parse(responseBody)\n const textBlocks = parsed?.content?.filter(\n (b: AnthropicContentBlock) => b.type === 'text' && typeof b.text === 'string',\n )\n const content = textBlocks?.map((b: AnthropicContentBlock) => b.text).join('')\n if (typeof content === 'string' && content.length > 0) {\n pipeline.pipeline.triggerLearning(content)\n }\n } catch {\n // Ignore learning parse errors\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[ERROR] Upstream request failed: ${message}`)\n if (!res.headersSent) {\n sendAnthropicError(res, 502, 'api_error', `Failed to reach upstream: ${message}`)\n }\n }\n}\n","import * as http from 'node:http'\n\n/**\n * Pipe an Anthropic SSE response from the upstream to the client,\n * parsing content_block_delta events for the learning buffer.\n *\n * Anthropic SSE format:\n * event: content_block_delta\n * data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"Hello\"}}\n *\n * Writes each chunk immediately — zero buffering, zero added latency.\n */\nexport async function pipeAnthropicSSEResponse(\n upstreamResponse: Response,\n clientRes: http.ServerResponse,\n onContentDelta: (text: string) => void,\n onComplete: () => void,\n): Promise<void> {\n clientRes.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n })\n\n const reader = upstreamResponse.body!.getReader()\n const decoder = new TextDecoder()\n let lineBuf = ''\n let currentEvent = ''\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n const chunk = decoder.decode(value, { stream: true })\n\n // Write immediately to client\n clientRes.write(chunk)\n\n // Parse SSE lines for learning (best-effort, never blocks the pipe)\n lineBuf += chunk\n const lines = lineBuf.split('\\n')\n lineBuf = lines.pop() || ''\n\n for (const line of lines) {\n if (line.startsWith('event: ')) {\n currentEvent = line.slice(7).trim()\n } else if (line.startsWith('data: ') && currentEvent === 'content_block_delta') {\n try {\n const json = JSON.parse(line.slice(6))\n if (json?.delta?.type === 'text_delta' && typeof json.delta.text === 'string') {\n onContentDelta(json.delta.text)\n }\n } catch {\n // Malformed data — ignore for learning, chunk already piped\n }\n }\n }\n }\n } finally {\n clientRes.end()\n onComplete()\n }\n}\n","import * as http from 'node:http'\nimport { handleChatCompletions } from './completions.js'\nimport { handleAnthropicMessages } from './messages.js'\nimport type { RSCPipelineWrapper } from '../rsc/pipeline.js'\nimport type { ResolvedConfig } from '../types.js'\n\nexport interface Logger {\n log(message: string): void\n}\n\nfunction setCORSHeaders(res: http.ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-api-key, anthropic-version, anthropic-beta')\n res.setHeader('Access-Control-Max-Age', '86400')\n}\n\nfunction sendJSON(res: http.ServerResponse, status: number, body: unknown): void {\n setCORSHeaders(res)\n res.writeHead(status, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify(body))\n}\n\nfunction readBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n req.on('data', (chunk: Buffer) => chunks.push(chunk))\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')))\n req.on('error', reject)\n })\n}\n\nexport function createRequestHandler(\n pipeline: RSCPipelineWrapper,\n config: ResolvedConfig,\n logger: Logger,\n): (req: http.IncomingMessage, res: http.ServerResponse) => void {\n const startTime = Date.now()\n\n return async (req, res) => {\n try {\n const method = req.method?.toUpperCase() ?? ''\n const url = req.url ?? ''\n\n // CORS preflight\n if (method === 'OPTIONS') {\n setCORSHeaders(res)\n res.writeHead(204)\n res.end()\n return\n }\n\n // Health check (extended with session summary for `liminal status` / `liminal summary`)\n if (method === 'GET' && (url === '/health' || url === '/')) {\n const summary = pipeline.getSessionSummary()\n sendJSON(res, 200, {\n status: 'ok',\n version: config.rscApiKey ? 'connected' : 'no-api-key',\n rsc_connected: !pipeline.isCircuitOpen(),\n circuit_state: pipeline.getCircuitState(),\n session_id: summary.sessionId,\n uptime_ms: Date.now() - startTime,\n session: {\n tokens_processed: summary.tokensProcessed,\n tokens_saved: summary.tokensSaved,\n calls_total: summary.totalCalls,\n calls_compressed: summary.compressedCalls,\n calls_skipped: summary.skippedCalls,\n calls_failed: summary.failedCalls,\n patterns_learned: summary.patternsLearned,\n estimated_cost_saved_usd: summary.estimatedCostSaved,\n },\n })\n return\n }\n\n // Model listing — proxy to upstream LLM\n if (method === 'GET' && (url === '/v1/models' || url === '/models')) {\n const llmApiKey = req.headers.authorization?.slice(7)\n if (!llmApiKey) {\n sendJSON(res, 401, {\n error: { message: 'Authorization header with Bearer token is required', type: 'authentication_error' },\n })\n return\n }\n\n try {\n const upstreamRes = await fetch(`${config.upstreamBaseUrl}/v1/models`, {\n headers: { 'Authorization': `Bearer ${llmApiKey}` },\n })\n const body = await upstreamRes.text()\n setCORSHeaders(res)\n res.writeHead(upstreamRes.status, {\n 'Content-Type': upstreamRes.headers.get('Content-Type') || 'application/json',\n })\n res.end(body)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n sendJSON(res, 502, {\n error: { message: `Failed to reach upstream: ${message}`, type: 'server_error' },\n })\n }\n return\n }\n\n // Main route: chat completions\n if (method === 'POST' && (url === '/v1/chat/completions' || url === '/chat/completions')) {\n const body = await readBody(req)\n let parsed: unknown\n try {\n parsed = JSON.parse(body)\n } catch {\n sendJSON(res, 400, {\n error: { message: 'Invalid JSON body', type: 'invalid_request_error' },\n })\n return\n }\n\n await handleChatCompletions(req, res, parsed, pipeline, config, logger)\n return\n }\n\n // Anthropic Messages route\n if (method === 'POST' && (url === '/v1/messages' || url === '/messages')) {\n const body = await readBody(req)\n let parsed: unknown\n try {\n parsed = JSON.parse(body)\n } catch {\n sendJSON(res, 400, {\n type: 'error',\n error: { type: 'invalid_request_error', message: 'Invalid JSON body' },\n })\n return\n }\n\n await handleAnthropicMessages(req, res, parsed, pipeline, config, logger)\n return\n }\n\n // 404\n sendJSON(res, 404, {\n error: { message: `Not found: ${method} ${url}`, type: 'invalid_request_error' },\n })\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[ERROR] Proxy handler error: ${message}`)\n if (!res.headersSent) {\n sendJSON(res, 500, {\n error: { message: 'Internal proxy error', type: 'server_error' },\n })\n }\n }\n }\n}\n","import * as http from 'node:http'\n\nconst MAX_PORT_RETRIES = 5\n\nexport class ProxyServer {\n private server: http.Server | null = null\n private activePort: number | null = null\n private readonly requestedPort: number\n private readonly handler: (req: http.IncomingMessage, res: http.ServerResponse) => void\n\n constructor(\n port: number,\n handler: (req: http.IncomingMessage, res: http.ServerResponse) => void,\n ) {\n this.requestedPort = port\n this.handler = handler\n }\n\n async start(): Promise<number> {\n let lastError: Error | null = null\n\n for (let attempt = 0; attempt < MAX_PORT_RETRIES; attempt++) {\n const port = this.requestedPort + attempt\n try {\n await this.listen(port)\n this.activePort = port\n return port\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err))\n if ((err as NodeJS.ErrnoException).code !== 'EADDRINUSE') {\n throw lastError\n }\n }\n }\n\n throw lastError ?? new Error(`All ports ${this.requestedPort}-${this.requestedPort + MAX_PORT_RETRIES - 1} in use`)\n }\n\n private listen(port: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const server = http.createServer(this.handler)\n server.on('error', reject)\n server.listen(port, '127.0.0.1', () => {\n server.removeListener('error', reject)\n this.server = server\n resolve()\n })\n })\n }\n\n async stop(): Promise<void> {\n if (!this.server) return\n return new Promise((resolve) => {\n this.server!.close(() => {\n this.server = null\n this.activePort = null\n resolve()\n })\n })\n }\n\n isRunning(): boolean {\n return this.server !== null && this.server.listening\n }\n\n getPort(): number | null {\n return this.activePort\n }\n}\n","import { appendFileSync, statSync, renameSync, mkdirSync, existsSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { LOG_FILE, LOG_DIR } from '../config/paths.js'\nimport type { Logger } from '../proxy/handler.js'\n\nconst MAX_LOG_SIZE = 10 * 1024 * 1024 // 10 MB\nconst MAX_BACKUPS = 2\n\nexport class FileLogger implements Logger {\n private readonly logFile: string\n private readonly mirrorStdout: boolean\n\n constructor(options?: { logFile?: string; mirrorStdout?: boolean }) {\n this.logFile = options?.logFile ?? LOG_FILE\n this.mirrorStdout = options?.mirrorStdout ?? false\n\n // Ensure log directory exists\n const logDir = dirname(this.logFile)\n if (!existsSync(logDir)) {\n mkdirSync(logDir, { recursive: true })\n }\n }\n\n log(message: string): void {\n const timestamp = new Date().toISOString().slice(11, 23)\n const line = `[${timestamp}] ${message}\\n`\n\n try {\n appendFileSync(this.logFile, line)\n } catch {\n // If log write fails, try stdout as fallback\n process.stderr.write(`[LOG-WRITE-FAILED] ${line}`)\n }\n\n if (this.mirrorStdout) {\n process.stdout.write(line)\n }\n\n this.rotateIfNeeded()\n }\n\n private rotateIfNeeded(): void {\n try {\n const stats = statSync(this.logFile)\n if (stats.size <= MAX_LOG_SIZE) return\n\n // Rotate: liminal.log -> liminal.log.1 -> liminal.log.2 (drop oldest)\n for (let i = MAX_BACKUPS - 1; i >= 1; i--) {\n const from = `${this.logFile}.${i}`\n const to = `${this.logFile}.${i + 1}`\n if (existsSync(from)) renameSync(from, to)\n }\n renameSync(this.logFile, `${this.logFile}.1`)\n } catch {\n // Rotation failure is non-fatal\n }\n }\n\n getLogFile(): string {\n return this.logFile\n }\n}\n\n/**\n * A simple logger that only writes to stdout (for use during init or when log file isn't available).\n */\nexport class ConsoleLogger implements Logger {\n log(message: string): void {\n const timestamp = new Date().toISOString().slice(11, 23)\n process.stdout.write(`[${timestamp}] ${message}\\n`)\n }\n}\n","import { readFileSync, writeFileSync, unlinkSync, existsSync } from 'node:fs'\nimport { fork } from 'node:child_process'\nimport { fileURLToPath } from 'node:url'\nimport { PID_FILE } from '../config/paths.js'\nimport type { ProxyServer } from '../proxy/server.js'\nimport type { Logger } from '../proxy/handler.js'\n\n/**\n * Write the current process PID to ~/.liminal/liminal.pid.\n */\nexport function writePidFile(pid: number): void {\n writeFileSync(PID_FILE, String(pid), 'utf-8')\n}\n\n/**\n * Read PID from ~/.liminal/liminal.pid. Returns null if file doesn't exist.\n */\nexport function readPidFile(): number | null {\n if (!existsSync(PID_FILE)) return null\n try {\n const content = readFileSync(PID_FILE, 'utf-8').trim()\n const pid = parseInt(content, 10)\n return isNaN(pid) ? null : pid\n } catch {\n return null\n }\n}\n\n/**\n * Remove the PID file.\n */\nexport function removePidFile(): void {\n try {\n if (existsSync(PID_FILE)) unlinkSync(PID_FILE)\n } catch {\n // Ignore — file may already be gone\n }\n}\n\n/**\n * Check if a process with the given PID is alive.\n */\nexport function isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Check if the Liminal daemon is currently running.\n * Cleans up stale PID files automatically.\n */\nexport function isDaemonRunning(): { running: boolean; pid?: number } {\n const pid = readPidFile()\n if (pid === null) return { running: false }\n\n if (isProcessAlive(pid)) {\n return { running: true, pid }\n }\n\n // Stale PID file — process is dead\n removePidFile()\n return { running: false }\n}\n\n/**\n * Set up signal handlers for graceful shutdown.\n */\nexport function setupSignalHandlers(server: ProxyServer, logger: Logger): void {\n const shutdown = async (signal: string) => {\n logger.log(`[DAEMON] Received ${signal}, shutting down...`)\n try {\n await server.stop()\n } catch {\n // Best-effort server stop\n }\n removePidFile()\n logger.log('[DAEMON] Stopped.')\n process.exit(0)\n }\n\n process.on('SIGTERM', () => shutdown('SIGTERM'))\n process.on('SIGINT', () => shutdown('SIGINT'))\n\n process.on('uncaughtException', (err) => {\n logger.log(`[FATAL] Uncaught exception: ${err.message}`)\n removePidFile()\n process.exit(1)\n })\n\n process.on('unhandledRejection', (reason) => {\n const message = reason instanceof Error ? reason.message : String(reason)\n logger.log(`[FATAL] Unhandled rejection: ${message}`)\n removePidFile()\n process.exit(1)\n })\n}\n\n/**\n * Fork a detached child process to run the daemon in the background.\n * Returns the child PID.\n */\nexport function forkDaemon(binPath: string, extraArgs: string[] = []): number {\n const child = fork(binPath, ['start', '--_forked', ...extraArgs], {\n detached: true,\n stdio: 'ignore',\n })\n\n child.unref()\n return child.pid!\n}\n\n/**\n * Resolve the bin.ts/bin.js entry point path from import.meta.url.\n */\nexport function resolveBinPath(importMetaUrl: string): string {\n return fileURLToPath(importMetaUrl)\n}\n\n/**\n * Sleep for a given number of milliseconds.\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","import { loadConfig, applyOverrides, isConfigured } from '../config/loader.js'\nimport { RSCPipelineWrapper } from '../rsc/pipeline.js'\nimport { createRequestHandler } from '../proxy/handler.js'\nimport { ProxyServer } from '../proxy/server.js'\nimport { FileLogger } from '../daemon/logger.js'\nimport {\n isDaemonRunning,\n writePidFile,\n setupSignalHandlers,\n forkDaemon,\n resolveBinPath,\n} from '../daemon/lifecycle.js'\nimport type { ResolvedConfig, Tool } from '../types.js'\nimport { printBanner } from '../version.js'\n\nexport async function startCommand(flags: Map<string, string | true>): Promise<void> {\n const isDaemon = flags.has('d') || flags.has('daemon')\n const isForked = flags.has('_forked')\n\n // Check if already running (skip for forked processes — parent already checked)\n if (!isForked) {\n const state = isDaemonRunning()\n if (state.running) {\n console.error(`Liminal daemon is already running (PID ${state.pid}).`)\n console.error('Use \"liminal stop\" first, or \"liminal status\" to check.')\n process.exit(1)\n }\n }\n\n // Check config\n if (!isConfigured()) {\n console.error('Liminal is not configured. Run \"liminal init\" first.')\n process.exit(1)\n }\n\n // Load and apply config\n let config = loadConfig()\n const portOverride = flags.get('port')\n const upstreamOverride = flags.get('upstream')\n config = applyOverrides(config, {\n ...(typeof portOverride === 'string' ? { port: parseInt(portOverride, 10) } : {}),\n ...(typeof upstreamOverride === 'string' ? { upstreamBaseUrl: upstreamOverride } : {}),\n })\n\n // Background mode: fork and exit parent\n if (isDaemon && !isForked) {\n const extraArgs: string[] = []\n if (portOverride) extraArgs.push('--port', String(portOverride))\n if (upstreamOverride) extraArgs.push('--upstream', String(upstreamOverride))\n\n const binPath = resolveBinPath(import.meta.url)\n const childPid = forkDaemon(binPath, extraArgs)\n\n console.log(`Liminal daemon started in background (PID ${childPid})`)\n console.log(`Proxy: http://127.0.0.1:${config.port}/v1`)\n console.log('Logs: ~/.liminal/logs/liminal.log')\n process.exit(0)\n }\n\n // Foreground mode: run the server in this process\n const isForeground = !isDaemon || isForked\n const logger = new FileLogger({ mirrorStdout: isForeground && !isForked })\n\n // Build the resolved config for the proxy\n const resolvedConfig: ResolvedConfig = {\n rscApiKey: config.apiKey,\n rscBaseUrl: config.apiBaseUrl,\n proxyPort: config.port,\n compressionThreshold: config.compressionThreshold,\n compressRoles: config.compressRoles,\n learnFromResponses: config.learnFromResponses,\n latencyBudgetMs: config.latencyBudgetMs || undefined,\n upstreamBaseUrl: config.upstreamBaseUrl,\n anthropicUpstreamUrl: config.anthropicUpstreamUrl,\n enabled: config.enabled,\n tools: config.tools as Tool[],\n }\n\n // Create RSC pipeline\n const pipeline = new RSCPipelineWrapper({\n rscApiKey: config.apiKey,\n rscBaseUrl: config.apiBaseUrl,\n compressionThreshold: config.compressionThreshold,\n learnFromResponses: config.learnFromResponses,\n latencyBudgetMs: config.latencyBudgetMs || undefined,\n })\n\n // Wire up pipeline events for logging\n pipeline.events.on('compression', (event) => {\n if (event.tokensSaved > 0) {\n logger.log(`[LIMINAL] Compressed: ${event.tokensSaved} tokens saved (${event.ratio.toFixed(3)} ratio)`)\n }\n })\n pipeline.events.on('compression_skipped', (event) => {\n logger.log(`[LIMINAL] Skipped: ${event.reason}`)\n })\n pipeline.events.on('error', (event) => {\n logger.log(`[LIMINAL] Error: ${event.error.message}`)\n })\n pipeline.events.on('degradation', (event) => {\n logger.log(`[LIMINAL] Circuit ${event.circuitState}: ${event.reason}`)\n })\n\n // Create server\n const handler = createRequestHandler(pipeline, resolvedConfig, logger)\n const server = new ProxyServer(config.port, handler)\n\n // Setup graceful shutdown\n setupSignalHandlers(server, logger)\n\n // Start listening\n try {\n const actualPort = await server.start()\n writePidFile(process.pid)\n\n logger.log(`[DAEMON] Liminal proxy started on http://127.0.0.1:${actualPort}`)\n logger.log(`[DAEMON] Upstream (OpenAI): ${config.upstreamBaseUrl}`)\n logger.log(`[DAEMON] Upstream (Anthropic): ${config.anthropicUpstreamUrl}`)\n logger.log(`[DAEMON] Liminal API: ${config.apiBaseUrl}`)\n logger.log(`[DAEMON] PID: ${process.pid}`)\n\n if (isForeground && !isForked) {\n printBanner()\n console.log(` Liminal proxy running on http://127.0.0.1:${actualPort}/v1`)\n console.log(` Upstream: ${config.upstreamBaseUrl}`)\n console.log()\n console.log(' Point your AI tool\\'s base URL here. Press Ctrl+C to stop.')\n console.log()\n }\n\n // Check RSC API health on startup\n const healthy = await pipeline.healthCheck()\n if (healthy) {\n logger.log('[DAEMON] Liminal API health check: OK')\n } else {\n logger.log('[DAEMON] Liminal API health check: FAILED (will retry on first request)')\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n console.error(`Failed to start proxy: ${message}`)\n process.exit(1)\n }\n}\n","import {\n isDaemonRunning,\n readPidFile,\n removePidFile,\n isProcessAlive,\n sleep,\n} from '../daemon/lifecycle.js'\n\nexport async function stopCommand(): Promise<void> {\n const state = isDaemonRunning()\n\n if (!state.running || !state.pid) {\n console.log('Liminal daemon is not running.')\n return\n }\n\n const pid = state.pid\n console.log(`Stopping Liminal daemon (PID ${pid})...`)\n\n // Send SIGTERM for graceful shutdown\n try {\n process.kill(pid, 'SIGTERM')\n } catch {\n // Process may have already exited\n removePidFile()\n console.log('Liminal daemon stopped.')\n return\n }\n\n // Poll for up to 5 seconds\n for (let i = 0; i < 25; i++) {\n await sleep(200)\n if (!isProcessAlive(pid)) {\n removePidFile()\n console.log(`Liminal daemon stopped (PID ${pid}).`)\n return\n }\n }\n\n // Force kill after timeout\n try {\n process.kill(pid, 'SIGKILL')\n } catch {\n // Already dead\n }\n\n removePidFile()\n console.log(`Liminal daemon force-killed (PID ${pid}).`)\n}\n","import { isDaemonRunning } from '../daemon/lifecycle.js'\nimport { loadConfig, isConfigured } from '../config/loader.js'\n\nexport async function statusCommand(): Promise<void> {\n if (!isConfigured()) {\n console.log('Liminal: not configured')\n console.log('Run \"liminal init\" to set up.')\n return\n }\n\n const state = isDaemonRunning()\n\n if (!state.running || !state.pid) {\n console.log('Liminal Daemon: stopped')\n console.log('Run \"liminal start\" to start the proxy.')\n return\n }\n\n const config = loadConfig()\n const port = config.port\n\n // Try to reach the daemon's /health endpoint\n try {\n const res = await fetch(`http://127.0.0.1:${port}/health`, {\n signal: AbortSignal.timeout(3000),\n })\n const data = await res.json() as {\n status: string\n circuit_state: string\n session_id: string\n uptime_ms: number\n session?: {\n tokens_processed: number\n tokens_saved: number\n calls_total: number\n calls_compressed: number\n calls_skipped: number\n calls_failed: number\n }\n }\n\n const uptime = formatUptime(data.uptime_ms)\n\n console.log(`Liminal Daemon: running (PID ${state.pid}, port ${port})`)\n console.log(`Circuit: ${data.circuit_state}`)\n console.log(`Session: ${data.session_id}`)\n console.log(`Uptime: ${uptime}`)\n\n if (data.session) {\n const s = data.session\n const savingsPercent = s.tokens_processed > 0\n ? ((s.tokens_saved / s.tokens_processed) * 100).toFixed(1)\n : '0.0'\n console.log()\n console.log(`Tokens: ${s.tokens_processed.toLocaleString()} processed, ${s.tokens_saved.toLocaleString()} saved (${savingsPercent}%)`)\n console.log(`Calls: ${s.calls_total} total (${s.calls_compressed} compressed, ${s.calls_skipped} skipped, ${s.calls_failed} failed)`)\n }\n } catch {\n // Can't reach the daemon, but PID is alive — might still be starting\n console.log(`Liminal Daemon: running (PID ${state.pid}, port ${port})`)\n console.log('Circuit: unknown (could not reach /health)')\n }\n}\n\nfunction formatUptime(ms: number): string {\n const seconds = Math.floor(ms / 1000)\n const minutes = Math.floor(seconds / 60)\n const hours = Math.floor(minutes / 60)\n const days = Math.floor(hours / 24)\n\n if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`\n if (hours > 0) return `${hours}h ${minutes % 60}m`\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`\n return `${seconds}s`\n}\n","import { isDaemonRunning } from '../daemon/lifecycle.js'\nimport { loadConfig, isConfigured } from '../config/loader.js'\n\nexport async function summaryCommand(): Promise<void> {\n if (!isConfigured()) {\n console.log('Liminal is not configured. Run \"liminal init\" first.')\n return\n }\n\n const state = isDaemonRunning()\n\n if (!state.running || !state.pid) {\n console.log('Liminal daemon is not running. Start it with \"liminal start\".')\n return\n }\n\n const config = loadConfig()\n const port = config.port\n\n try {\n const res = await fetch(`http://127.0.0.1:${port}/health`, {\n signal: AbortSignal.timeout(3000),\n })\n const data = await res.json() as {\n circuit_state: string\n session_id: string\n uptime_ms: number\n session?: {\n tokens_processed: number\n tokens_saved: number\n calls_total: number\n calls_compressed: number\n calls_skipped: number\n calls_failed: number\n patterns_learned: number\n estimated_cost_saved_usd: number\n }\n }\n\n const uptime = formatUptime(data.uptime_ms)\n\n console.log()\n console.log(` Session: ${data.session_id}`)\n console.log(` Uptime: ${uptime}`)\n console.log()\n\n if (data.session) {\n const s = data.session\n const savingsPercent = s.tokens_processed > 0\n ? ((s.tokens_saved / s.tokens_processed) * 100).toFixed(1)\n : '0.0'\n const compressionRate = s.calls_total > 0\n ? ((s.calls_compressed / s.calls_total) * 100).toFixed(0)\n : '0'\n\n console.log(' Compression:')\n console.log(` Tokens processed: ${s.tokens_processed.toLocaleString()}`)\n console.log(` Tokens saved: ${s.tokens_saved.toLocaleString()} (${savingsPercent}%)`)\n console.log(` Compression rate: ${compressionRate}% of calls compressed`)\n console.log(` Patterns learned: ${s.patterns_learned.toLocaleString()}`)\n console.log()\n console.log(' Calls:')\n console.log(` Total: ${s.calls_total}`)\n console.log(` Compressed: ${s.calls_compressed}`)\n console.log(` Skipped: ${s.calls_skipped}`)\n console.log(` Failed: ${s.calls_failed}`)\n console.log()\n console.log(' Cost Savings:')\n console.log(` Estimated: $${s.estimated_cost_saved_usd.toFixed(4)} USD`)\n console.log()\n } else {\n console.log(' No session data available yet.')\n console.log()\n }\n\n console.log(` Circuit: ${data.circuit_state}`)\n console.log(` API: ${config.apiBaseUrl}`)\n console.log(` Upstream: ${config.upstreamBaseUrl}`)\n console.log()\n } catch {\n console.error('Could not reach the Liminal daemon. Is it running?')\n console.error(`Tried http://127.0.0.1:${port}/health`)\n process.exit(1)\n }\n}\n\nfunction formatUptime(ms: number): string {\n const seconds = Math.floor(ms / 1000)\n const minutes = Math.floor(seconds / 60)\n const hours = Math.floor(minutes / 60)\n const days = Math.floor(hours / 24)\n\n if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`\n if (hours > 0) return `${hours}h ${minutes % 60}m`\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`\n return `${seconds}s`\n}\n","import { loadConfig, saveConfig, isConfigured, maskApiKey } from '../config/loader.js'\nimport { CONFIGURABLE_KEYS } from '../config/schema.js'\nimport { CONFIG_FILE } from '../config/paths.js'\n\nexport async function configCommand(flags: Map<string, string | true>): Promise<void> {\n const getKey = flags.get('get')\n const setKv = flags.get('set')\n\n // rsc config --get <key>\n if (typeof getKey === 'string') {\n if (!isConfigured()) {\n console.error('Liminal is not configured. Run \"liminal init\" first.')\n process.exit(1)\n }\n const config = loadConfig()\n const value = (config as unknown as Record<string, unknown>)[getKey]\n if (value === undefined) {\n console.error(`Unknown config key: ${getKey}`)\n process.exit(1)\n }\n console.log(getKey === 'apiKey' ? maskApiKey(String(value)) : String(value))\n return\n }\n\n // rsc config --set <key>=<value>\n if (typeof setKv === 'string') {\n const eqIdx = setKv.indexOf('=')\n if (eqIdx === -1) {\n console.error('Usage: liminal config --set key=value')\n process.exit(1)\n }\n const key = setKv.slice(0, eqIdx)\n const rawValue = setKv.slice(eqIdx + 1)\n\n if (!CONFIGURABLE_KEYS.has(key) && key !== 'apiKey') {\n console.error(`Unknown or non-configurable key: ${key}`)\n console.error(`Configurable keys: ${[...CONFIGURABLE_KEYS].join(', ')}`)\n process.exit(1)\n }\n\n // Parse value based on key type\n let parsedValue: unknown = rawValue\n if (key === 'port' || key === 'compressionThreshold' || key === 'latencyBudgetMs') {\n parsedValue = parseInt(rawValue, 10)\n if (isNaN(parsedValue as number)) {\n console.error(`Invalid number for ${key}: ${rawValue}`)\n process.exit(1)\n }\n } else if (key === 'learnFromResponses' || key === 'enabled') {\n parsedValue = rawValue === 'true' || rawValue === '1'\n } else if (key === 'compressRoles') {\n parsedValue = rawValue.split(',').map((s) => s.trim())\n }\n\n saveConfig({ [key]: parsedValue })\n console.log(`Set ${key} = ${key === 'apiKey' ? maskApiKey(rawValue) : rawValue}`)\n return\n }\n\n // rsc config (no flags) — show all\n if (!isConfigured()) {\n console.log(`Liminal is not configured. Run \"liminal init\" first.`)\n console.log(`Config file: ${CONFIG_FILE}`)\n return\n }\n\n const config = loadConfig()\n console.log()\n console.log(` Config: ${CONFIG_FILE}`)\n console.log()\n console.log(` apiKey: ${maskApiKey(config.apiKey)}`)\n console.log(` apiBaseUrl: ${config.apiBaseUrl}`)\n console.log(` upstreamBaseUrl: ${config.upstreamBaseUrl}`)\n console.log(` anthropicUpstreamUrl: ${config.anthropicUpstreamUrl}`)\n console.log(` tools: ${config.tools.length > 0 ? config.tools.join(', ') : '(none)'}`)\n console.log(` port: ${config.port}`)\n console.log(` compressionThreshold: ${config.compressionThreshold}`)\n console.log(` compressRoles: ${config.compressRoles.join(', ')}`)\n console.log(` learnFromResponses: ${config.learnFromResponses}`)\n console.log(` latencyBudgetMs: ${config.latencyBudgetMs || 'auto'}`)\n console.log(` enabled: ${config.enabled}`)\n console.log()\n}\n","import { readFileSync, existsSync, statSync, createReadStream } from 'node:fs'\nimport { watchFile, unwatchFile } from 'node:fs'\nimport { LOG_FILE } from '../config/paths.js'\n\nexport async function logsCommand(flags: Map<string, string | true>): Promise<void> {\n const follow = flags.has('follow') || flags.has('f')\n const linesFlag = flags.get('lines') ?? flags.get('n')\n const lines = typeof linesFlag === 'string' ? parseInt(linesFlag, 10) : 50\n\n if (!existsSync(LOG_FILE)) {\n console.log('No log file found. Start the daemon with \"liminal start\" to generate logs.')\n return\n }\n\n // Read and display last N lines\n const content = readFileSync(LOG_FILE, 'utf-8')\n const allLines = content.split('\\n')\n const tail = allLines.slice(-lines - 1) // -1 to account for trailing newline\n process.stdout.write(tail.join('\\n'))\n\n if (!follow) return\n\n // Follow mode: watch for changes and stream new content\n let lastSize = statSync(LOG_FILE).size\n\n watchFile(LOG_FILE, { interval: 500 }, (curr) => {\n if (curr.size > lastSize) {\n const stream = createReadStream(LOG_FILE, { start: lastSize, encoding: 'utf-8' })\n stream.on('data', (chunk) => process.stdout.write(chunk as string))\n stream.on('end', () => { lastSize = curr.size })\n } else if (curr.size < lastSize) {\n // File was rotated — read from beginning\n lastSize = 0\n }\n })\n\n // Keep the process alive and handle Ctrl+C\n process.on('SIGINT', () => {\n unwatchFile(LOG_FILE)\n process.exit(0)\n })\n\n // Block forever\n await new Promise(() => {})\n}\n","import { VERSION } from './version.js'\nimport { initCommand } from './commands/init.js'\nimport { startCommand } from './commands/start.js'\nimport { stopCommand } from './commands/stop.js'\nimport { statusCommand } from './commands/status.js'\nimport { summaryCommand } from './commands/summary.js'\nimport { configCommand } from './commands/config.js'\nimport { logsCommand } from './commands/logs.js'\n\nconst USAGE = `\n liminal v${VERSION} — Transparent LLM context compression proxy\n\n Usage:\n liminal init Set up Liminal (API key, config)\n liminal start [-d] [--port PORT] Start the compression proxy\n liminal stop Stop the running proxy\n liminal status Show proxy health and stats\n liminal summary Detailed session metrics\n liminal config [--set k=v] [--get k] View or edit configuration\n liminal logs [--follow] [--lines N] View proxy logs\n\n Options:\n -h, --help Show this help message\n -v, --version Show version number\n\n Getting started:\n 1. liminal init # Enter your API key + select tools\n 2. liminal start # Start the proxy\n 3. Connect your AI tools:\n Claude Code: export ANTHROPIC_BASE_URL=http://localhost:3141\n Codex: export OPENAI_BASE_URL=http://localhost:3141/v1\n Cursor: Settings > Models > Base URL > http://localhost:3141/v1\n`\n\nfunction parseArgs(argv: string[]): { command: string; flags: Map<string, string | true> } {\n const command = argv[2] ?? ''\n const flags = new Map<string, string | true>()\n\n for (let i = 3; i < argv.length; i++) {\n const arg = argv[i]\n if (arg.startsWith('--')) {\n const key = arg.slice(2)\n // Check if next arg is a value (not another flag)\n if (i + 1 < argv.length && !argv[i + 1].startsWith('-')) {\n flags.set(key, argv[i + 1])\n i++\n } else {\n flags.set(key, true)\n }\n } else if (arg.startsWith('-') && arg.length === 2) {\n const key = arg.slice(1)\n if (i + 1 < argv.length && !argv[i + 1].startsWith('-')) {\n flags.set(key, argv[i + 1])\n i++\n } else {\n flags.set(key, true)\n }\n }\n }\n\n return { command, flags }\n}\n\nasync function main(): Promise<void> {\n const { command, flags } = parseArgs(process.argv)\n\n // Global flags — handle --help and --version as both commands and flags\n if (flags.has('h') || flags.has('help') || command === 'help' || command === '--help' || command === '-h') {\n console.log(USAGE)\n process.exit(0)\n }\n\n if (flags.has('v') || flags.has('version') || command === 'version' || command === '--version' || command === '-v') {\n console.log(VERSION)\n process.exit(0)\n }\n\n try {\n switch (command) {\n case 'init':\n await initCommand()\n break\n\n case 'start':\n await startCommand(flags)\n break\n\n case 'stop':\n await stopCommand()\n break\n\n case 'status':\n await statusCommand()\n break\n\n case 'summary':\n await summaryCommand()\n break\n\n case 'config':\n await configCommand(flags)\n break\n\n case 'logs':\n await logsCommand(flags)\n break\n\n case '':\n console.log(USAGE)\n process.exit(0)\n break\n\n default:\n console.error(`Unknown command: ${command}`)\n console.log(USAGE)\n process.exit(1)\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n console.error(`Error: ${message}`)\n process.exit(1)\n }\n}\n\nmain()\n"],"mappings":";;;AACO,IAAM,UAAU,OAAqC,UAAc;AAG1E,IAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,cAAoB;AAClC,UAAQ,IAAI;AACZ,aAAW,QAAQ,cAAc;AAC/B,YAAQ,IAAI,IAAI;AAAA,EAClB;AACA,UAAQ,IAAI;AACZ,UAAQ,IAAI,MAAM,OAAO,gCAAgC;AACzD,UAAQ,IAAI;AACd;;;ACtBA,SAAS,uBAAuB;AAChC,SAAS,OAAO,cAAc;AAC9B,SAAS,cAAc,sBAAsB;;;ACF7C,SAAS,cAAc,eAAe,WAAW,kBAAkB;AACnE,SAAS,eAAe;;;ACDxB,SAAS,eAAe;AACxB,SAAS,YAAY;AAEd,IAAM,cAAc,KAAK,QAAQ,GAAG,UAAU;AAC9C,IAAM,cAAc,KAAK,aAAa,aAAa;AACnD,IAAM,WAAW,KAAK,aAAa,aAAa;AAChD,IAAM,UAAU,KAAK,aAAa,MAAM;AACxC,IAAM,WAAW,KAAK,SAAS,aAAa;;;ACO5C,IAAM,WAAsC;AAAA,EACjD,YAAY;AAAA,EACZ,iBAAiB;AAAA,EACjB,sBAAsB;AAAA,EACtB,MAAM;AAAA,EACN,sBAAsB;AAAA,EACtB,eAAe,CAAC,MAAM;AAAA,EACtB,oBAAoB;AAAA,EACpB,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,OAAO,CAAC;AACV;AAGO,IAAM,oBAAoB,oBAAI,IAAY;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;;;AF7BM,SAAS,aAAwB;AACtC,MAAI,aAAiC,CAAC;AAEtC,MAAI,WAAW,WAAW,GAAG;AAC3B,QAAI;AACF,YAAM,MAAM,aAAa,aAAa,OAAO;AAC7C,mBAAa,KAAK,MAAM,GAAG;AAAA,IAC7B,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,SAAoB;AAAA,IACxB,QAAQ,WAAW,UAAU;AAAA,IAC7B,YAAY,SAAS;AAAA,IACrB,iBAAiB,SAAS;AAAA,IAC1B,sBAAsB,SAAS;AAAA,IAC/B,MAAM,SAAS;AAAA,IACf,sBAAsB,SAAS;AAAA,IAC/B,eAAe,SAAS;AAAA,IACxB,oBAAoB,SAAS;AAAA,IAC7B,iBAAiB,SAAS;AAAA,IAC1B,SAAS,SAAS;AAAA,IAClB,OAAO,SAAS;AAAA,IAChB,GAAG;AAAA,EACL;AAGA,MAAI,QAAQ,IAAI,gBAAiB,QAAO,SAAS,QAAQ,IAAI;AAC7D,MAAI,QAAQ,IAAI,gBAAiB,QAAO,aAAa,QAAQ,IAAI;AACjE,MAAI,QAAQ,IAAI,qBAAsB,QAAO,kBAAkB,QAAQ,IAAI;AAC3E,MAAI,QAAQ,IAAI,sBAAuB,QAAO,uBAAuB,QAAQ,IAAI;AACjF,MAAI,QAAQ,IAAI,aAAc,QAAO,OAAO,SAAS,QAAQ,IAAI,cAAc,EAAE;AAEjF,SAAO;AACT;AAKO,SAAS,eACd,QACA,WACW;AACX,SAAO,EAAE,GAAG,QAAQ,GAAG,UAAU;AACnC;AAKO,SAAS,WAAW,QAAkC;AAC3D,oBAAkB;AAElB,MAAI,WAA+B,CAAC;AACpC,MAAI,WAAW,WAAW,GAAG;AAC3B,QAAI;AACF,iBAAW,KAAK,MAAM,aAAa,aAAa,OAAO,CAAC;AAAA,IAC1D,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,SAAS,EAAE,GAAG,UAAU,GAAG,OAAO;AACxC,gBAAc,aAAa,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,OAAO;AAC5E;AAKO,SAAS,oBAA0B;AACxC,MAAI,CAAC,WAAW,WAAW,EAAG,WAAU,aAAa,EAAE,WAAW,KAAK,CAAC;AACxE,MAAI,CAAC,WAAW,OAAO,EAAG,WAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AAEhE,QAAM,YAAY,QAAQ,WAAW;AACrC,MAAI,CAAC,WAAW,SAAS,EAAG,WAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AACtE;AAKO,SAAS,eAAwB;AACtC,MAAI;AACF,UAAM,SAAS,WAAW;AAC1B,WAAO,OAAO,OAAO,SAAS;AAAA,EAChC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKO,SAAS,WAAW,KAAqB;AAC9C,MAAI,IAAI,UAAU,GAAI,QAAO;AAC7B,SAAO,IAAI,MAAM,GAAG,CAAC,IAAI,QAAQ,IAAI,MAAM,EAAE;AAC/C;;;ADhGA,IAAM,WAAiC;AAAA,EACrC,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AAEA,SAAS,mBAAmB,OAAuB;AACjD,QAAM,OAAO,MAAM,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AACjE,QAAM,QAAQ,KAAK,IAAI,CAAC,MAAM,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,MAAiB,CAAC,CAAC,CAAC;AACvE,SAAO,MAAM,SAAS,IAAI,QAAQ,CAAC,aAAa;AAClD;AAEA,SAAS,sBAAsB,MAAY,MAAoB;AAC7D,QAAM,OAAO,oBAAoB,IAAI;AACrC,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,cAAQ,IAAI,kBAAkB;AAC9B,cAAQ,IAAI,mCAAmC,IAAI,EAAE;AACrD,cAAQ,IAAI,mDAAmD;AAC/D,cAAQ,IAAI;AACZ;AAAA,IACF,KAAK;AACH,cAAQ,IAAI,YAAY;AACxB,cAAQ,IAAI,gCAAgC,IAAI,KAAK;AACrD,cAAQ,IAAI,mDAAmD;AAC/D,cAAQ,IAAI;AACZ;AAAA,IACF,KAAK;AACH,cAAQ,IAAI,aAAa;AACzB,cAAQ,IAAI,kDAAkD,IAAI,KAAK;AACvE,cAAQ,IAAI;AACZ;AAAA,IACF,KAAK;AACH,cAAQ,IAAI,8BAA8B;AAC1C,cAAQ,IAAI,+BAA+B,IAAI,KAAK;AACpD,cAAQ,IAAI;AACZ;AAAA,EACJ;AACF;AAEA,eAAsB,cAA6B;AACjD,QAAM,KAAK,gBAAgB,EAAE,OAAO,OAAO,QAAQ,OAAO,CAAC;AAE3D,cAAY;AACZ,UAAQ,IAAI,6DAA6D;AACzE,UAAQ,IAAI;AACZ,UAAQ,IAAI,yBAAyB;AACrC,UAAQ,IAAI;AAEZ,MAAI;AAEF,UAAM,SAAS,MAAM,GAAG,SAAS,mCAAmC;AACpE,QAAI,CAAC,OAAO,KAAK,GAAG;AAClB,cAAQ,MAAM,iCAAiC;AAC/C,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,aAAa,SAAS;AAG5B,UAAM,YAAY,MAAM,GAAG,SAAS,iBAAiB,SAAS,IAAI,KAAK;AACvE,UAAM,OAAO,UAAU,KAAK,IAAI,SAAS,UAAU,KAAK,GAAG,EAAE,IAAI,SAAS;AAC1E,QAAI,MAAM,IAAI,KAAK,OAAO,KAAK,OAAO,OAAO;AAC3C,cAAQ,MAAM,iCAAiC;AAC/C,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,YAAQ,IAAI;AACZ,YAAQ,IAAI,6CAA6C;AACzD,YAAQ,IAAI;AACZ,YAAQ,IAAI,oBAAoB;AAChC,YAAQ,IAAI,cAAc;AAC1B,YAAQ,IAAI,eAAe;AAC3B,YAAQ,IAAI,kCAAkC;AAC9C,YAAQ,IAAI;AACZ,UAAM,aAAa,MAAM,GAAG,SAAS,kDAAkD;AACvF,UAAM,QAAQ,mBAAmB,WAAW,KAAK,KAAK,GAAG;AAGzD,UAAM,aAAa,MAAM,GAAG,SAAS,qCAAqC;AAC1E,UAAM,qBAAqB,WAAW,KAAK,EAAE,YAAY,MAAM;AAE/D,YAAQ,IAAI;AAGZ,YAAQ,OAAO,MAAM,0BAA0B;AAC/C,QAAI;AACF,YAAM,UAAU,IAAI,eAAe,GAAG,GAAM;AAC5C,YAAM,YAAY,IAAI,aAAa;AAAA,QACjC,SAAS;AAAA,QACT,QAAQ,OAAO,KAAK;AAAA,QACpB,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,MAClB,CAAC;AACD,YAAM,UAAU,IAAwB,SAAS;AACjD,cAAQ,IAAI,IAAI;AAAA,IAClB,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,cAAQ,IAAI,QAAQ;AACpB,cAAQ,MAAM;AAAA,sCAAyC,OAAO,EAAE;AAChE,cAAQ,MAAM,+CAA+C;AAC7D,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,sBAAkB;AAClB,eAAW;AAAA,MACT,QAAQ,OAAO,KAAK;AAAA,MACpB;AAAA,MACA,iBAAiB,SAAS;AAAA,MAC1B,sBAAsB,SAAS;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA,sBAAsB,SAAS;AAAA,MAC/B,eAAe,SAAS;AAAA,MACxB,iBAAiB,SAAS;AAAA,MAC1B,SAAS,SAAS;AAAA,IACpB,CAAC;AAED,YAAQ,IAAI;AACZ,YAAQ,IAAI,4BAA4B,WAAW,EAAE;AACrD,YAAQ,IAAI;AACZ,YAAQ,IAAI,eAAe;AAC3B,YAAQ,IAAI,wCAAwC;AACpD,YAAQ,IAAI,4BAA4B;AACxC,YAAQ,IAAI;AAEZ,eAAW,QAAQ,OAAO;AACxB,4BAAsB,MAAM,IAAI;AAAA,IAClC;AAAA,EACF,UAAE;AACA,OAAG,MAAM;AAAA,EACX;AACF;;;AIlJA;AAAA,EACE;AAAA,EACA,gBAAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAAC;AAAA,OACK;AAYA,IAAM,qBAAN,MAAyB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACQ;AAAA,EAEjB,YAAY,QAAwB;AAClC,SAAK,iBAAiB,IAAIA,gBAAe,GAAG,IAAI,KAAK,GAAI;AAEzD,SAAK,YAAY,IAAID,cAAa;AAAA,MAChC,SAAS,OAAO;AAAA,MAChB,QAAQ,OAAO;AAAA,MACf,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,gBAAgB,KAAK;AAAA,IACvB,CAAC;AAED,SAAK,SAAS,IAAI,gBAAgB;AAClC,SAAK,UAAU,IAAI,QAAQ,OAAO,SAAS;AAE3C,SAAK,WAAW,IAAI;AAAA,MAClB,KAAK;AAAA,MACL;AAAA,QACE,WAAW,OAAO;AAAA,QAClB,oBAAoB,OAAO;AAAA,QAC3B,iBAAiB,OAAO;AAAA,QACxB,WAAW,KAAK,QAAQ;AAAA,MAC1B;AAAA,MACA,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEA,MAAM,cAAgC;AACpC,QAAI;AACF,YAAM,KAAK,UAAU,IAAwB,SAAS;AACtD,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,oBAAoC;AAClC,WAAO,KAAK,QAAQ,WAAW;AAAA,EACjC;AAAA,EAEA,kBAAgC;AAC9B,WAAO,KAAK,eAAe,SAAS;AAAA,EACtC;AAAA,EAEA,gBAAyB;AACvB,WAAO,KAAK,eAAe,SAAS,MAAM;AAAA,EAC5C;AAAA,EAEA,sBAA4B;AAC1B,SAAK,eAAe,MAAM;AAAA,EAC5B;AACF;;;AC1EA,SAAS,uBAAAE,4BAA2B;;;ACApC,SAAS,2BAA2B;AAcpC,eAAsB,iBACpB,UACA,UACA,SACA,eACmC;AACnC,MAAI,gBAAgB;AACpB,MAAI,mBAAmB;AAEvB,QAAM,aAAa,MAAM,QAAQ;AAAA,IAC/B,SAAS,IAAI,OAAO,QAAQ;AAC1B,UAAI,CAAC,cAAc,IAAI,IAAI,IAAI,EAAG,QAAO;AAGzC,UAAI,OAAO,IAAI,YAAY,UAAU;AACnC,eAAO,sBAAsB,KAAK,UAAU,SAAS,CAAC,GAAG,UAAU;AACjE,0BAAgB,iBAAiB;AACjC,8BAAoB;AAAA,QACtB,CAAC;AAAA,MACH;AAGA,UAAI,MAAM,QAAQ,IAAI,OAAO,GAAG;AAC9B,eAAO,qBAAqB,KAAK,UAAU,SAAS,CAAC,GAAG,UAAU;AAChE,0BAAgB,iBAAiB;AACjC,8BAAoB;AAAA,QACtB,CAAC;AAAA,MACH;AAGA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,UAAU,YAAY,eAAe,iBAAiB;AACjE;AAEA,eAAe,sBACb,KACA,UACA,SACA,QACgC;AAChC,MAAI;AACF,UAAM,SAAS,MAAM,SAAS,eAAe,IAAI,OAAiB;AAClE,YAAQ,kBAAkB,OAAO,OAAO;AACxC,WAAO,CAAC,OAAO,QAAQ,SAAS,OAAO,QAAQ,WAAW;AAC1D,WAAO,EAAE,GAAG,KAAK,SAAS,OAAO,KAAK;AAAA,EACxC,SAAS,KAAK;AACZ,QAAI,eAAe,qBAAqB;AACtC,cAAQ,cAAc;AACtB,YAAM;AAAA,IACR;AAEA,YAAQ,cAAc;AACtB,WAAO;AAAA,EACT;AACF;AAEA,eAAe,qBACb,KACA,UACA,SACA,QACgC;AAChC,QAAM,QAAQ,IAAI;AAElB,QAAM,kBAAkB,MAAM,QAAQ;AAAA,IACpC,MAAM,IAAI,OAAO,SAAS;AACxB,UAAI,KAAK,SAAS,UAAU,OAAO,KAAK,SAAS,UAAU;AACzD,YAAI;AACF,gBAAM,SAAS,MAAM,SAAS,eAAe,KAAK,IAAI;AACtD,kBAAQ,kBAAkB,OAAO,OAAO;AACxC,iBAAO,CAAC,OAAO,QAAQ,SAAS,OAAO,QAAQ,WAAW;AAC1D,iBAAO,EAAE,GAAG,MAAM,MAAM,OAAO,KAAK;AAAA,QACtC,SAAS,KAAK;AACZ,cAAI,eAAe,qBAAqB;AACtC,oBAAQ,cAAc;AACtB,kBAAM;AAAA,UACR;AACA,kBAAQ,cAAc;AACtB,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,GAAG,KAAK,SAAS,gBAAgB;AAC5C;;;ACnGO,SAAS,2BAA2B,UAA+B;AACxE,MAAI,SAAS;AAEb,SAAO;AAAA;AAAA,IAEL,OAAO,MAAoB;AACzB,gBAAU;AAAA,IACZ;AAAA;AAAA,IAGA,QAAc;AACZ,UAAI,OAAO,SAAS,GAAG;AACrB,iBAAS,gBAAgB,MAAM;AAC/B,iBAAS;AAAA,MACX;AAAA,IACF;AAAA;AAAA,IAGA,YAAoB;AAClB,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACpBA,eAAsB,gBACpB,kBACA,WACA,gBACA,YACe;AACf,YAAU,UAAU,KAAK;AAAA,IACvB,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,+BAA+B;AAAA,EACjC,CAAC;AAED,QAAM,SAAS,iBAAiB,KAAM,UAAU;AAChD,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,UAAU;AAEd,MAAI;AACF,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AAEV,YAAM,QAAQ,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAGpD,gBAAU,MAAM,KAAK;AAGrB,iBAAW;AACX,YAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,gBAAU,MAAM,IAAI,KAAK;AAEzB,iBAAW,QAAQ,OAAO;AACxB,YAAI,KAAK,WAAW,QAAQ,KAAK,SAAS,gBAAgB;AACxD,cAAI;AACF,kBAAM,OAAO,KAAK,MAAM,KAAK,MAAM,CAAC,CAAC;AACrC,kBAAM,UAAU,MAAM,UAAU,CAAC,GAAG,OAAO;AAC3C,gBAAI,OAAO,YAAY,UAAU;AAC/B,6BAAe,OAAO;AAAA,YACxB;AAAA,UACF,QAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,UAAE;AACA,cAAU,IAAI;AACd,eAAW;AAAA,EACb;AACF;;;AHjDA,SAAS,eAAe,KAAgC;AACtD,MAAI,UAAU,+BAA+B,GAAG;AAChD,MAAI,UAAU,gCAAgC,oBAAoB;AAClE,MAAI,UAAU,gCAAgC,6BAA6B;AAC7E;AAEA,SAAS,SAAS,KAA0B,QAAgB,MAAqB;AAC/E,iBAAe,GAAG;AAClB,MAAI,UAAU,QAAQ,EAAE,gBAAgB,mBAAmB,CAAC;AAC5D,MAAI,IAAI,KAAK,UAAU,IAAI,CAAC;AAC9B;AAMA,SAAS,mBAAmB,KAA0C;AACpE,QAAM,OAAO,IAAI,QAAQ;AACzB,MAAI,CAAC,QAAQ,CAAC,KAAK,WAAW,SAAS,EAAG,QAAO;AACjD,SAAO,KAAK,MAAM,CAAC;AACrB;AAEA,eAAsB,sBACpB,KACA,KACA,MACA,UACA,QACA,QACe;AACf,QAAM,UAAU;AAGhB,MAAI,CAAC,QAAQ,YAAY,CAAC,MAAM,QAAQ,QAAQ,QAAQ,GAAG;AACzD,aAAS,KAAK,KAAK;AAAA,MACjB,OAAO,EAAE,SAAS,6CAA6C,MAAM,wBAAwB;AAAA,IAC/F,CAAC;AACD;AAAA,EACF;AAGA,QAAM,YAAY,mBAAmB,GAAG;AACxC,MAAI,CAAC,WAAW;AACd,aAAS,KAAK,KAAK;AAAA,MACjB,OAAO,EAAE,SAAS,sDAAsD,MAAM,uBAAuB;AAAA,IACvG,CAAC;AACD;AAAA,EACF;AAGA,MAAI,WAAW,QAAQ;AACvB,MAAI,gBAAgB;AAEpB,MAAI,OAAO,WAAW,CAAC,SAAS,cAAc,GAAG;AAC/C,QAAI;AACF,YAAM,gBAAgB,IAAI,IAAI,OAAO,aAAa;AAClD,YAAM,SAAS,MAAM;AAAA,QACnB,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,SAAS;AAAA,QACT;AAAA,MACF;AACA,iBAAW,OAAO;AAClB,sBAAgB,OAAO;AAEvB,UAAI,OAAO,mBAAmB,GAAG;AAC/B,eAAO,IAAI,oBAAoB,OAAO,gBAAgB,SAAS;AAAA,MACjE;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAeC,sBAAqB;AACtC,eAAO,IAAI,gEAA2D;AAAA,MACxE,OAAO;AACL,eAAO,IAAI,+BAA+B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,MAC9F;AAEA,iBAAW,QAAQ;AAAA,IACrB;AAAA,EACF;AAGA,QAAM,cAAc,GAAG,OAAO,eAAe;AAC7C,QAAM,eAAe,EAAE,GAAG,SAAS,SAAS;AAE5C,QAAM,kBAA0C;AAAA,IAC9C,iBAAiB,UAAU,SAAS;AAAA,IACpC,gBAAgB;AAAA,EAClB;AAGA,MAAI,QAAQ,QAAQ;AAClB,oBAAgB,QAAQ,IAAI;AAAA,EAC9B;AAEA,MAAI;AACF,UAAM,mBAAmB,MAAM,MAAM,aAAa;AAAA,MAChD,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,MAAM,KAAK,UAAU,YAAY;AAAA,IACnC,CAAC;AAGD,QAAI,CAAC,iBAAiB,IAAI;AACxB,YAAM,YAAY,MAAM,iBAAiB,KAAK;AAC9C,qBAAe,GAAG;AAClB,UAAI,UAAU,iBAAiB,QAAQ;AAAA,QACrC,gBAAgB,iBAAiB,QAAQ,IAAI,cAAc,KAAK;AAAA,MAClE,CAAC;AACD,UAAI,IAAI,SAAS;AACjB;AAAA,IACF;AAGA,QAAI,QAAQ,UAAU,iBAAiB,MAAM;AAC3C,YAAM,iBAAiB,gBACnB,2BAA2B,SAAS,QAAQ,IAC5C;AAEJ,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA,CAAC,SAAS,gBAAgB,OAAO,IAAI;AAAA,QACrC,MAAM,gBAAgB,MAAM;AAAA,MAC9B;AACA;AAAA,IACF;AAGA,UAAM,eAAe,MAAM,iBAAiB,KAAK;AACjD,mBAAe,GAAG;AAClB,QAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,QAAI,IAAI,YAAY;AAGpB,QAAI,eAAe;AACjB,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,YAAY;AACtC,cAAM,UAAU,QAAQ,UAAU,CAAC,GAAG,SAAS;AAC/C,YAAI,OAAO,YAAY,YAAY,QAAQ,SAAS,GAAG;AACrD,mBAAS,SAAS,gBAAgB,OAAO;AAAA,QAC3C;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,WAAO,IAAI,oCAAoC,OAAO,EAAE;AACxD,QAAI,CAAC,IAAI,aAAa;AACpB,eAAS,KAAK,KAAK;AAAA,QACjB,OAAO,EAAE,SAAS,iCAAiC,OAAO,IAAI,MAAM,eAAe;AAAA,MACrF,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AIjKA,SAAS,uBAAAC,4BAA2B;;;ACWpC,eAAsB,yBACpB,kBACA,WACA,gBACA,YACe;AACf,YAAU,UAAU,KAAK;AAAA,IACvB,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,+BAA+B;AAAA,EACjC,CAAC;AAED,QAAM,SAAS,iBAAiB,KAAM,UAAU;AAChD,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,UAAU;AACd,MAAI,eAAe;AAEnB,MAAI;AACF,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AAEV,YAAM,QAAQ,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAGpD,gBAAU,MAAM,KAAK;AAGrB,iBAAW;AACX,YAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,gBAAU,MAAM,IAAI,KAAK;AAEzB,iBAAW,QAAQ,OAAO;AACxB,YAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,yBAAe,KAAK,MAAM,CAAC,EAAE,KAAK;AAAA,QACpC,WAAW,KAAK,WAAW,QAAQ,KAAK,iBAAiB,uBAAuB;AAC9E,cAAI;AACF,kBAAM,OAAO,KAAK,MAAM,KAAK,MAAM,CAAC,CAAC;AACrC,gBAAI,MAAM,OAAO,SAAS,gBAAgB,OAAO,KAAK,MAAM,SAAS,UAAU;AAC7E,6BAAe,KAAK,MAAM,IAAI;AAAA,YAChC;AAAA,UACF,QAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,UAAE;AACA,cAAU,IAAI;AACd,eAAW;AAAA,EACb;AACF;;;ADtDA,SAASC,gBAAe,KAAgC;AACtD,MAAI,UAAU,+BAA+B,GAAG;AAChD,MAAI,UAAU,gCAAgC,oBAAoB;AAClE,MAAI,UAAU,gCAAgC,2EAA2E;AAC3H;AAEA,SAAS,mBAAmB,KAA0B,QAAgB,MAAc,SAAuB;AACzG,EAAAA,gBAAe,GAAG;AAClB,MAAI,UAAU,QAAQ,EAAE,gBAAgB,mBAAmB,CAAC;AAC5D,MAAI,IAAI,KAAK,UAAU,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,QAAQ,EAAE,CAAC,CAAC;AACrE;AAEA,SAAS,uBAAuB,KAA0C;AACxE,QAAM,MAAM,IAAI,QAAQ,WAAW;AACnC,MAAI,OAAO,QAAQ,YAAY,IAAI,SAAS,EAAG,QAAO;AACtD,SAAO;AACT;AAMA,SAAS,+BAA+B,UAAuD;AAC7F,SAAO,SAAS,IAAI,CAAC,SAAS;AAAA,IAC5B,MAAM,IAAI;AAAA,IACV,SAAS,IAAI;AAAA,EACf,EAAE;AACJ;AAKA,SAAS,6BAA6B,UAAuD;AAC3F,SAAO,SAAS,IAAI,CAAC,SAAS;AAAA,IAC5B,MAAM,IAAI;AAAA,IACV,SAAS,IAAI;AAAA,EACf,EAAE;AACJ;AAEA,eAAsB,wBACpB,KACA,KACA,MACA,UACA,QACA,QACe;AACf,QAAM,UAAU;AAGhB,MAAI,CAAC,QAAQ,YAAY,CAAC,MAAM,QAAQ,QAAQ,QAAQ,GAAG;AACzD,uBAAmB,KAAK,KAAK,yBAAyB,2CAA2C;AACjG;AAAA,EACF;AAEA,MAAI,OAAO,QAAQ,eAAe,UAAU;AAC1C,uBAAmB,KAAK,KAAK,yBAAyB,wBAAwB;AAC9E;AAAA,EACF;AAGA,QAAM,SAAS,uBAAuB,GAAG;AACzC,MAAI,CAAC,QAAQ;AACX,uBAAmB,KAAK,KAAK,wBAAwB,8BAA8B;AACnF;AAAA,EACF;AAGA,MAAI,WAAW,QAAQ;AACvB,MAAI,gBAAgB;AAEpB,MAAI,OAAO,WAAW,CAAC,SAAS,cAAc,GAAG;AAC/C,QAAI;AACF,YAAM,gBAAgB,IAAI,IAAI,OAAO,aAAa;AAClD,YAAM,eAAe,+BAA+B,QAAQ,QAAQ;AACpE,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA,SAAS;AAAA,QACT,SAAS;AAAA,QACT;AAAA,MACF;AACA,iBAAW,6BAA6B,OAAO,QAAQ;AACvD,sBAAgB,OAAO;AAEvB,UAAI,OAAO,mBAAmB,GAAG;AAC/B,eAAO,IAAI,oBAAoB,OAAO,gBAAgB,SAAS;AAAA,MACjE;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAeC,sBAAqB;AACtC,eAAO,IAAI,4DAA4D;AAAA,MACzE,OAAO;AACL,eAAO,IAAI,+BAA+B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,MAC9F;AACA,iBAAW,QAAQ;AAAA,IACrB;AAAA,EACF;AAGA,QAAM,cAAc,GAAG,OAAO,oBAAoB;AAClD,QAAM,eAAe,EAAE,GAAG,SAAS,SAAS;AAE5C,QAAM,kBAA0C;AAAA,IAC9C,aAAa;AAAA,IACb,qBAAsB,IAAI,QAAQ,mBAAmB,KAAgB;AAAA,IACrE,gBAAgB;AAAA,EAClB;AAGA,QAAM,aAAa,IAAI,QAAQ,gBAAgB;AAC/C,MAAI,OAAO,eAAe,UAAU;AAClC,oBAAgB,gBAAgB,IAAI;AAAA,EACtC;AAEA,MAAI;AACF,UAAM,mBAAmB,MAAM,MAAM,aAAa;AAAA,MAChD,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,MAAM,KAAK,UAAU,YAAY;AAAA,IACnC,CAAC;AAGD,QAAI,CAAC,iBAAiB,IAAI;AACxB,YAAM,YAAY,MAAM,iBAAiB,KAAK;AAC9C,MAAAD,gBAAe,GAAG;AAClB,UAAI,UAAU,iBAAiB,QAAQ;AAAA,QACrC,gBAAgB,iBAAiB,QAAQ,IAAI,cAAc,KAAK;AAAA,MAClE,CAAC;AACD,UAAI,IAAI,SAAS;AACjB;AAAA,IACF;AAGA,QAAI,QAAQ,UAAU,iBAAiB,MAAM;AAC3C,YAAM,iBAAiB,gBACnB,2BAA2B,SAAS,QAAQ,IAC5C;AAEJ,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA,CAAC,SAAS,gBAAgB,OAAO,IAAI;AAAA,QACrC,MAAM,gBAAgB,MAAM;AAAA,MAC9B;AACA;AAAA,IACF;AAGA,UAAM,eAAe,MAAM,iBAAiB,KAAK;AACjD,IAAAA,gBAAe,GAAG;AAClB,QAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,QAAI,IAAI,YAAY;AAGpB,QAAI,eAAe;AACjB,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,YAAY;AACtC,cAAM,aAAa,QAAQ,SAAS;AAAA,UAClC,CAAC,MAA6B,EAAE,SAAS,UAAU,OAAO,EAAE,SAAS;AAAA,QACvE;AACA,cAAM,UAAU,YAAY,IAAI,CAAC,MAA6B,EAAE,IAAI,EAAE,KAAK,EAAE;AAC7E,YAAI,OAAO,YAAY,YAAY,QAAQ,SAAS,GAAG;AACrD,mBAAS,SAAS,gBAAgB,OAAO;AAAA,QAC3C;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,WAAO,IAAI,oCAAoC,OAAO,EAAE;AACxD,QAAI,CAAC,IAAI,aAAa;AACpB,yBAAmB,KAAK,KAAK,aAAa,6BAA6B,OAAO,EAAE;AAAA,IAClF;AAAA,EACF;AACF;;;AE9KA,SAASE,gBAAe,KAAgC;AACtD,MAAI,UAAU,+BAA+B,GAAG;AAChD,MAAI,UAAU,gCAAgC,oBAAoB;AAClE,MAAI,UAAU,gCAAgC,2EAA2E;AACzH,MAAI,UAAU,0BAA0B,OAAO;AACjD;AAEA,SAASC,UAAS,KAA0B,QAAgB,MAAqB;AAC/E,EAAAD,gBAAe,GAAG;AAClB,MAAI,UAAU,QAAQ,EAAE,gBAAgB,mBAAmB,CAAC;AAC5D,MAAI,IAAI,KAAK,UAAU,IAAI,CAAC;AAC9B;AAEA,SAAS,SAAS,KAA4C;AAC5D,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAmB,CAAC;AAC1B,QAAI,GAAG,QAAQ,CAAC,UAAkB,OAAO,KAAK,KAAK,CAAC;AACpD,QAAI,GAAG,OAAO,MAAM,QAAQ,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO,CAAC,CAAC;AACpE,QAAI,GAAG,SAAS,MAAM;AAAA,EACxB,CAAC;AACH;AAEO,SAAS,qBACd,UACA,QACA,QAC+D;AAC/D,QAAM,YAAY,KAAK,IAAI;AAE3B,SAAO,OAAO,KAAK,QAAQ;AACzB,QAAI;AACF,YAAM,SAAS,IAAI,QAAQ,YAAY,KAAK;AAC5C,YAAM,MAAM,IAAI,OAAO;AAGvB,UAAI,WAAW,WAAW;AACxB,QAAAA,gBAAe,GAAG;AAClB,YAAI,UAAU,GAAG;AACjB,YAAI,IAAI;AACR;AAAA,MACF;AAGA,UAAI,WAAW,UAAU,QAAQ,aAAa,QAAQ,MAAM;AAC1D,cAAM,UAAU,SAAS,kBAAkB;AAC3C,QAAAC,UAAS,KAAK,KAAK;AAAA,UACjB,QAAQ;AAAA,UACR,SAAS,OAAO,YAAY,cAAc;AAAA,UAC1C,eAAe,CAAC,SAAS,cAAc;AAAA,UACvC,eAAe,SAAS,gBAAgB;AAAA,UACxC,YAAY,QAAQ;AAAA,UACpB,WAAW,KAAK,IAAI,IAAI;AAAA,UACxB,SAAS;AAAA,YACP,kBAAkB,QAAQ;AAAA,YAC1B,cAAc,QAAQ;AAAA,YACtB,aAAa,QAAQ;AAAA,YACrB,kBAAkB,QAAQ;AAAA,YAC1B,eAAe,QAAQ;AAAA,YACvB,cAAc,QAAQ;AAAA,YACtB,kBAAkB,QAAQ;AAAA,YAC1B,0BAA0B,QAAQ;AAAA,UACpC;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAGA,UAAI,WAAW,UAAU,QAAQ,gBAAgB,QAAQ,YAAY;AACnE,cAAM,YAAY,IAAI,QAAQ,eAAe,MAAM,CAAC;AACpD,YAAI,CAAC,WAAW;AACd,UAAAA,UAAS,KAAK,KAAK;AAAA,YACjB,OAAO,EAAE,SAAS,sDAAsD,MAAM,uBAAuB;AAAA,UACvG,CAAC;AACD;AAAA,QACF;AAEA,YAAI;AACF,gBAAM,cAAc,MAAM,MAAM,GAAG,OAAO,eAAe,cAAc;AAAA,YACrE,SAAS,EAAE,iBAAiB,UAAU,SAAS,GAAG;AAAA,UACpD,CAAC;AACD,gBAAM,OAAO,MAAM,YAAY,KAAK;AACpC,UAAAD,gBAAe,GAAG;AAClB,cAAI,UAAU,YAAY,QAAQ;AAAA,YAChC,gBAAgB,YAAY,QAAQ,IAAI,cAAc,KAAK;AAAA,UAC7D,CAAC;AACD,cAAI,IAAI,IAAI;AAAA,QACd,SAAS,KAAK;AACZ,gBAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,UAAAC,UAAS,KAAK,KAAK;AAAA,YACjB,OAAO,EAAE,SAAS,6BAA6B,OAAO,IAAI,MAAM,eAAe;AAAA,UACjF,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAGA,UAAI,WAAW,WAAW,QAAQ,0BAA0B,QAAQ,sBAAsB;AACxF,cAAM,OAAO,MAAM,SAAS,GAAG;AAC/B,YAAI;AACJ,YAAI;AACF,mBAAS,KAAK,MAAM,IAAI;AAAA,QAC1B,QAAQ;AACN,UAAAA,UAAS,KAAK,KAAK;AAAA,YACjB,OAAO,EAAE,SAAS,qBAAqB,MAAM,wBAAwB;AAAA,UACvE,CAAC;AACD;AAAA,QACF;AAEA,cAAM,sBAAsB,KAAK,KAAK,QAAQ,UAAU,QAAQ,MAAM;AACtE;AAAA,MACF;AAGA,UAAI,WAAW,WAAW,QAAQ,kBAAkB,QAAQ,cAAc;AACxE,cAAM,OAAO,MAAM,SAAS,GAAG;AAC/B,YAAI;AACJ,YAAI;AACF,mBAAS,KAAK,MAAM,IAAI;AAAA,QAC1B,QAAQ;AACN,UAAAA,UAAS,KAAK,KAAK;AAAA,YACjB,MAAM;AAAA,YACN,OAAO,EAAE,MAAM,yBAAyB,SAAS,oBAAoB;AAAA,UACvE,CAAC;AACD;AAAA,QACF;AAEA,cAAM,wBAAwB,KAAK,KAAK,QAAQ,UAAU,QAAQ,MAAM;AACxE;AAAA,MACF;AAGA,MAAAA,UAAS,KAAK,KAAK;AAAA,QACjB,OAAO,EAAE,SAAS,cAAc,MAAM,IAAI,GAAG,IAAI,MAAM,wBAAwB;AAAA,MACjF,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,aAAO,IAAI,gCAAgC,OAAO,EAAE;AACpD,UAAI,CAAC,IAAI,aAAa;AACpB,QAAAA,UAAS,KAAK,KAAK;AAAA,UACjB,OAAO,EAAE,SAAS,wBAAwB,MAAM,eAAe;AAAA,QACjE,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;;;AC1JA,YAAY,UAAU;AAEtB,IAAM,mBAAmB;AAElB,IAAM,cAAN,MAAkB;AAAA,EACf,SAA6B;AAAA,EAC7B,aAA4B;AAAA,EACnB;AAAA,EACA;AAAA,EAEjB,YACE,MACA,SACA;AACA,SAAK,gBAAgB;AACrB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,MAAM,QAAyB;AAC7B,QAAI,YAA0B;AAE9B,aAAS,UAAU,GAAG,UAAU,kBAAkB,WAAW;AAC3D,YAAM,OAAO,KAAK,gBAAgB;AAClC,UAAI;AACF,cAAM,KAAK,OAAO,IAAI;AACtB,aAAK,aAAa;AAClB,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,oBAAY,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAC9D,YAAK,IAA8B,SAAS,cAAc;AACxD,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,aAAa,IAAI,MAAM,aAAa,KAAK,aAAa,IAAI,KAAK,gBAAgB,mBAAmB,CAAC,SAAS;AAAA,EACpH;AAAA,EAEQ,OAAO,MAA6B;AAC1C,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,SAAc,kBAAa,KAAK,OAAO;AAC7C,aAAO,GAAG,SAAS,MAAM;AACzB,aAAO,OAAO,MAAM,aAAa,MAAM;AACrC,eAAO,eAAe,SAAS,MAAM;AACrC,aAAK,SAAS;AACd,gBAAQ;AAAA,MACV,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,OAAsB;AAC1B,QAAI,CAAC,KAAK,OAAQ;AAClB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,WAAK,OAAQ,MAAM,MAAM;AACvB,aAAK,SAAS;AACd,aAAK,aAAa;AAClB,gBAAQ;AAAA,MACV,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEA,YAAqB;AACnB,WAAO,KAAK,WAAW,QAAQ,KAAK,OAAO;AAAA,EAC7C;AAAA,EAEA,UAAyB;AACvB,WAAO,KAAK;AAAA,EACd;AACF;;;ACpEA,SAAS,gBAAgB,UAAU,YAAY,aAAAC,YAAW,cAAAC,mBAAkB;AAC5E,SAAS,WAAAC,gBAAe;AAIxB,IAAM,eAAe,KAAK,OAAO;AACjC,IAAM,cAAc;AAEb,IAAM,aAAN,MAAmC;AAAA,EACvB;AAAA,EACA;AAAA,EAEjB,YAAY,SAAwD;AAClE,SAAK,UAAU,SAAS,WAAW;AACnC,SAAK,eAAe,SAAS,gBAAgB;AAG7C,UAAM,SAASC,SAAQ,KAAK,OAAO;AACnC,QAAI,CAACC,YAAW,MAAM,GAAG;AACvB,MAAAC,WAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AAAA,IACvC;AAAA,EACF;AAAA,EAEA,IAAI,SAAuB;AACzB,UAAM,aAAY,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,IAAI,EAAE;AACvD,UAAM,OAAO,IAAI,SAAS,KAAK,OAAO;AAAA;AAEtC,QAAI;AACF,qBAAe,KAAK,SAAS,IAAI;AAAA,IACnC,QAAQ;AAEN,cAAQ,OAAO,MAAM,sBAAsB,IAAI,EAAE;AAAA,IACnD;AAEA,QAAI,KAAK,cAAc;AACrB,cAAQ,OAAO,MAAM,IAAI;AAAA,IAC3B;AAEA,SAAK,eAAe;AAAA,EACtB;AAAA,EAEQ,iBAAuB;AAC7B,QAAI;AACF,YAAM,QAAQ,SAAS,KAAK,OAAO;AACnC,UAAI,MAAM,QAAQ,aAAc;AAGhC,eAAS,IAAI,cAAc,GAAG,KAAK,GAAG,KAAK;AACzC,cAAM,OAAO,GAAG,KAAK,OAAO,IAAI,CAAC;AACjC,cAAM,KAAK,GAAG,KAAK,OAAO,IAAI,IAAI,CAAC;AACnC,YAAID,YAAW,IAAI,EAAG,YAAW,MAAM,EAAE;AAAA,MAC3C;AACA,iBAAW,KAAK,SAAS,GAAG,KAAK,OAAO,IAAI;AAAA,IAC9C,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,aAAqB;AACnB,WAAO,KAAK;AAAA,EACd;AACF;;;AC7DA,SAAS,gBAAAE,eAAc,iBAAAC,gBAAe,YAAY,cAAAC,mBAAkB;AACpE,SAAS,YAAY;AACrB,SAAS,qBAAqB;AAQvB,SAAS,aAAa,KAAmB;AAC9C,EAAAC,eAAc,UAAU,OAAO,GAAG,GAAG,OAAO;AAC9C;AAKO,SAAS,cAA6B;AAC3C,MAAI,CAACC,YAAW,QAAQ,EAAG,QAAO;AAClC,MAAI;AACF,UAAM,UAAUC,cAAa,UAAU,OAAO,EAAE,KAAK;AACrD,UAAM,MAAM,SAAS,SAAS,EAAE;AAChC,WAAO,MAAM,GAAG,IAAI,OAAO;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKO,SAAS,gBAAsB;AACpC,MAAI;AACF,QAAID,YAAW,QAAQ,EAAG,YAAW,QAAQ;AAAA,EAC/C,QAAQ;AAAA,EAER;AACF;AAKO,SAAS,eAAe,KAAsB;AACnD,MAAI;AACF,YAAQ,KAAK,KAAK,CAAC;AACnB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,SAAS,kBAAsD;AACpE,QAAM,MAAM,YAAY;AACxB,MAAI,QAAQ,KAAM,QAAO,EAAE,SAAS,MAAM;AAE1C,MAAI,eAAe,GAAG,GAAG;AACvB,WAAO,EAAE,SAAS,MAAM,IAAI;AAAA,EAC9B;AAGA,gBAAc;AACd,SAAO,EAAE,SAAS,MAAM;AAC1B;AAKO,SAAS,oBAAoB,QAAqB,QAAsB;AAC7E,QAAM,WAAW,OAAO,WAAmB;AACzC,WAAO,IAAI,qBAAqB,MAAM,oBAAoB;AAC1D,QAAI;AACF,YAAM,OAAO,KAAK;AAAA,IACpB,QAAQ;AAAA,IAER;AACA,kBAAc;AACd,WAAO,IAAI,mBAAmB;AAC9B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,GAAG,WAAW,MAAM,SAAS,SAAS,CAAC;AAC/C,UAAQ,GAAG,UAAU,MAAM,SAAS,QAAQ,CAAC;AAE7C,UAAQ,GAAG,qBAAqB,CAAC,QAAQ;AACvC,WAAO,IAAI,+BAA+B,IAAI,OAAO,EAAE;AACvD,kBAAc;AACd,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAED,UAAQ,GAAG,sBAAsB,CAAC,WAAW;AAC3C,UAAM,UAAU,kBAAkB,QAAQ,OAAO,UAAU,OAAO,MAAM;AACxE,WAAO,IAAI,gCAAgC,OAAO,EAAE;AACpD,kBAAc;AACd,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;AAMO,SAAS,WAAW,SAAiB,YAAsB,CAAC,GAAW;AAC5E,QAAM,QAAQ,KAAK,SAAS,CAAC,SAAS,aAAa,GAAG,SAAS,GAAG;AAAA,IAChE,UAAU;AAAA,IACV,OAAO;AAAA,EACT,CAAC;AAED,QAAM,MAAM;AACZ,SAAO,MAAM;AACf;AAKO,SAAS,eAAe,eAA+B;AAC5D,SAAO,cAAc,aAAa;AACpC;AAKO,SAAS,MAAM,IAA2B;AAC/C,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;;;AChHA,eAAsB,aAAa,OAAkD;AACnF,QAAM,WAAW,MAAM,IAAI,GAAG,KAAK,MAAM,IAAI,QAAQ;AACrD,QAAM,WAAW,MAAM,IAAI,SAAS;AAGpC,MAAI,CAAC,UAAU;AACb,UAAM,QAAQ,gBAAgB;AAC9B,QAAI,MAAM,SAAS;AACjB,cAAQ,MAAM,0CAA0C,MAAM,GAAG,IAAI;AACrE,cAAQ,MAAM,yDAAyD;AACvE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAGA,MAAI,CAAC,aAAa,GAAG;AACnB,YAAQ,MAAM,sDAAsD;AACpE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,MAAI,SAAS,WAAW;AACxB,QAAM,eAAe,MAAM,IAAI,MAAM;AACrC,QAAM,mBAAmB,MAAM,IAAI,UAAU;AAC7C,WAAS,eAAe,QAAQ;AAAA,IAC9B,GAAI,OAAO,iBAAiB,WAAW,EAAE,MAAM,SAAS,cAAc,EAAE,EAAE,IAAI,CAAC;AAAA,IAC/E,GAAI,OAAO,qBAAqB,WAAW,EAAE,iBAAiB,iBAAiB,IAAI,CAAC;AAAA,EACtF,CAAC;AAGD,MAAI,YAAY,CAAC,UAAU;AACzB,UAAM,YAAsB,CAAC;AAC7B,QAAI,aAAc,WAAU,KAAK,UAAU,OAAO,YAAY,CAAC;AAC/D,QAAI,iBAAkB,WAAU,KAAK,cAAc,OAAO,gBAAgB,CAAC;AAE3E,UAAM,UAAU,eAAe,YAAY,GAAG;AAC9C,UAAM,WAAW,WAAW,SAAS,SAAS;AAE9C,YAAQ,IAAI,6CAA6C,QAAQ,GAAG;AACpE,YAAQ,IAAI,2BAA2B,OAAO,IAAI,KAAK;AACvD,YAAQ,IAAI,oCAAoC;AAChD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,eAAe,CAAC,YAAY;AAClC,QAAM,SAAS,IAAI,WAAW,EAAE,cAAc,gBAAgB,CAAC,SAAS,CAAC;AAGzE,QAAM,iBAAiC;AAAA,IACrC,WAAW,OAAO;AAAA,IAClB,YAAY,OAAO;AAAA,IACnB,WAAW,OAAO;AAAA,IAClB,sBAAsB,OAAO;AAAA,IAC7B,eAAe,OAAO;AAAA,IACtB,oBAAoB,OAAO;AAAA,IAC3B,iBAAiB,OAAO,mBAAmB;AAAA,IAC3C,iBAAiB,OAAO;AAAA,IACxB,sBAAsB,OAAO;AAAA,IAC7B,SAAS,OAAO;AAAA,IAChB,OAAO,OAAO;AAAA,EAChB;AAGA,QAAM,WAAW,IAAI,mBAAmB;AAAA,IACtC,WAAW,OAAO;AAAA,IAClB,YAAY,OAAO;AAAA,IACnB,sBAAsB,OAAO;AAAA,IAC7B,oBAAoB,OAAO;AAAA,IAC3B,iBAAiB,OAAO,mBAAmB;AAAA,EAC7C,CAAC;AAGD,WAAS,OAAO,GAAG,eAAe,CAAC,UAAU;AAC3C,QAAI,MAAM,cAAc,GAAG;AACzB,aAAO,IAAI,yBAAyB,MAAM,WAAW,kBAAkB,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS;AAAA,IACxG;AAAA,EACF,CAAC;AACD,WAAS,OAAO,GAAG,uBAAuB,CAAC,UAAU;AACnD,WAAO,IAAI,sBAAsB,MAAM,MAAM,EAAE;AAAA,EACjD,CAAC;AACD,WAAS,OAAO,GAAG,SAAS,CAAC,UAAU;AACrC,WAAO,IAAI,oBAAoB,MAAM,MAAM,OAAO,EAAE;AAAA,EACtD,CAAC;AACD,WAAS,OAAO,GAAG,eAAe,CAAC,UAAU;AAC3C,WAAO,IAAI,qBAAqB,MAAM,YAAY,KAAK,MAAM,MAAM,EAAE;AAAA,EACvE,CAAC;AAGD,QAAM,UAAU,qBAAqB,UAAU,gBAAgB,MAAM;AACrE,QAAM,SAAS,IAAI,YAAY,OAAO,MAAM,OAAO;AAGnD,sBAAoB,QAAQ,MAAM;AAGlC,MAAI;AACF,UAAM,aAAa,MAAM,OAAO,MAAM;AACtC,iBAAa,QAAQ,GAAG;AAExB,WAAO,IAAI,sDAAsD,UAAU,EAAE;AAC7E,WAAO,IAAI,+BAA+B,OAAO,eAAe,EAAE;AAClE,WAAO,IAAI,kCAAkC,OAAO,oBAAoB,EAAE;AAC1E,WAAO,IAAI,yBAAyB,OAAO,UAAU,EAAE;AACvD,WAAO,IAAI,iBAAiB,QAAQ,GAAG,EAAE;AAEzC,QAAI,gBAAgB,CAAC,UAAU;AAC7B,kBAAY;AACZ,cAAQ,IAAI,+CAA+C,UAAU,KAAK;AAC1E,cAAQ,IAAI,eAAe,OAAO,eAAe,EAAE;AACnD,cAAQ,IAAI;AACZ,cAAQ,IAAI,6DAA8D;AAC1E,cAAQ,IAAI;AAAA,IACd;AAGA,UAAM,UAAU,MAAM,SAAS,YAAY;AAC3C,QAAI,SAAS;AACX,aAAO,IAAI,uCAAuC;AAAA,IACpD,OAAO;AACL,aAAO,IAAI,yEAAyE;AAAA,IACtF;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,YAAQ,MAAM,0BAA0B,OAAO,EAAE;AACjD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;ACtIA,eAAsB,cAA6B;AACjD,QAAM,QAAQ,gBAAgB;AAE9B,MAAI,CAAC,MAAM,WAAW,CAAC,MAAM,KAAK;AAChC,YAAQ,IAAI,gCAAgC;AAC5C;AAAA,EACF;AAEA,QAAM,MAAM,MAAM;AAClB,UAAQ,IAAI,gCAAgC,GAAG,MAAM;AAGrD,MAAI;AACF,YAAQ,KAAK,KAAK,SAAS;AAAA,EAC7B,QAAQ;AAEN,kBAAc;AACd,YAAQ,IAAI,yBAAyB;AACrC;AAAA,EACF;AAGA,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,UAAM,MAAM,GAAG;AACf,QAAI,CAAC,eAAe,GAAG,GAAG;AACxB,oBAAc;AACd,cAAQ,IAAI,+BAA+B,GAAG,IAAI;AAClD;AAAA,IACF;AAAA,EACF;AAGA,MAAI;AACF,YAAQ,KAAK,KAAK,SAAS;AAAA,EAC7B,QAAQ;AAAA,EAER;AAEA,gBAAc;AACd,UAAQ,IAAI,oCAAoC,GAAG,IAAI;AACzD;;;AC7CA,eAAsB,gBAA+B;AACnD,MAAI,CAAC,aAAa,GAAG;AACnB,YAAQ,IAAI,yBAAyB;AACrC,YAAQ,IAAI,+BAA+B;AAC3C;AAAA,EACF;AAEA,QAAM,QAAQ,gBAAgB;AAE9B,MAAI,CAAC,MAAM,WAAW,CAAC,MAAM,KAAK;AAChC,YAAQ,IAAI,yBAAyB;AACrC,YAAQ,IAAI,yCAAyC;AACrD;AAAA,EACF;AAEA,QAAM,SAAS,WAAW;AAC1B,QAAM,OAAO,OAAO;AAGpB,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,oBAAoB,IAAI,WAAW;AAAA,MACzD,QAAQ,YAAY,QAAQ,GAAI;AAAA,IAClC,CAAC;AACD,UAAM,OAAO,MAAM,IAAI,KAAK;AAe5B,UAAM,SAAS,aAAa,KAAK,SAAS;AAE1C,YAAQ,IAAI,gCAAgC,MAAM,GAAG,UAAU,IAAI,GAAG;AACtE,YAAQ,IAAI,eAAe,KAAK,aAAa,EAAE;AAC/C,YAAQ,IAAI,eAAe,KAAK,UAAU,EAAE;AAC5C,YAAQ,IAAI,eAAe,MAAM,EAAE;AAEnC,QAAI,KAAK,SAAS;AAChB,YAAM,IAAI,KAAK;AACf,YAAM,iBAAiB,EAAE,mBAAmB,KACtC,EAAE,eAAe,EAAE,mBAAoB,KAAK,QAAQ,CAAC,IACvD;AACJ,cAAQ,IAAI;AACZ,cAAQ,IAAI,eAAe,EAAE,iBAAiB,eAAe,CAAC,eAAe,EAAE,aAAa,eAAe,CAAC,WAAW,cAAc,IAAI;AACzI,cAAQ,IAAI,eAAe,EAAE,WAAW,WAAW,EAAE,gBAAgB,gBAAgB,EAAE,aAAa,aAAa,EAAE,YAAY,UAAU;AAAA,IAC3I;AAAA,EACF,QAAQ;AAEN,YAAQ,IAAI,gCAAgC,MAAM,GAAG,UAAU,IAAI,GAAG;AACtE,YAAQ,IAAI,+CAA+C;AAAA,EAC7D;AACF;AAEA,SAAS,aAAa,IAAoB;AACxC,QAAM,UAAU,KAAK,MAAM,KAAK,GAAI;AACpC,QAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,QAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,QAAM,OAAO,KAAK,MAAM,QAAQ,EAAE;AAElC,MAAI,OAAO,EAAG,QAAO,GAAG,IAAI,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE;AAC5D,MAAI,QAAQ,EAAG,QAAO,GAAG,KAAK,KAAK,UAAU,EAAE;AAC/C,MAAI,UAAU,EAAG,QAAO,GAAG,OAAO,KAAK,UAAU,EAAE;AACnD,SAAO,GAAG,OAAO;AACnB;;;ACvEA,eAAsB,iBAAgC;AACpD,MAAI,CAAC,aAAa,GAAG;AACnB,YAAQ,IAAI,sDAAsD;AAClE;AAAA,EACF;AAEA,QAAM,QAAQ,gBAAgB;AAE9B,MAAI,CAAC,MAAM,WAAW,CAAC,MAAM,KAAK;AAChC,YAAQ,IAAI,+DAA+D;AAC3E;AAAA,EACF;AAEA,QAAM,SAAS,WAAW;AAC1B,QAAM,OAAO,OAAO;AAEpB,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,oBAAoB,IAAI,WAAW;AAAA,MACzD,QAAQ,YAAY,QAAQ,GAAI;AAAA,IAClC,CAAC;AACD,UAAM,OAAO,MAAM,IAAI,KAAK;AAgB5B,UAAM,SAASE,cAAa,KAAK,SAAS;AAE1C,YAAQ,IAAI;AACZ,YAAQ,IAAI,cAAc,KAAK,UAAU,EAAE;AAC3C,YAAQ,IAAI,cAAc,MAAM,EAAE;AAClC,YAAQ,IAAI;AAEZ,QAAI,KAAK,SAAS;AAChB,YAAM,IAAI,KAAK;AACf,YAAM,iBAAiB,EAAE,mBAAmB,KACtC,EAAE,eAAe,EAAE,mBAAoB,KAAK,QAAQ,CAAC,IACvD;AACJ,YAAM,kBAAkB,EAAE,cAAc,KAClC,EAAE,mBAAmB,EAAE,cAAe,KAAK,QAAQ,CAAC,IACtD;AAEJ,cAAQ,IAAI,gBAAgB;AAC5B,cAAQ,IAAI,0BAA0B,EAAE,iBAAiB,eAAe,CAAC,EAAE;AAC3E,cAAQ,IAAI,0BAA0B,EAAE,aAAa,eAAe,CAAC,KAAK,cAAc,IAAI;AAC5F,cAAQ,IAAI,0BAA0B,eAAe,uBAAuB;AAC5E,cAAQ,IAAI,0BAA0B,EAAE,iBAAiB,eAAe,CAAC,EAAE;AAC3E,cAAQ,IAAI;AACZ,cAAQ,IAAI,UAAU;AACtB,cAAQ,IAAI,mBAAmB,EAAE,WAAW,EAAE;AAC9C,cAAQ,IAAI,mBAAmB,EAAE,gBAAgB,EAAE;AACnD,cAAQ,IAAI,mBAAmB,EAAE,aAAa,EAAE;AAChD,cAAQ,IAAI,mBAAmB,EAAE,YAAY,EAAE;AAC/C,cAAQ,IAAI;AACZ,cAAQ,IAAI,iBAAiB;AAC7B,cAAQ,IAAI,oBAAoB,EAAE,yBAAyB,QAAQ,CAAC,CAAC,MAAM;AAC3E,cAAQ,IAAI;AAAA,IACd,OAAO;AACL,cAAQ,IAAI,kCAAkC;AAC9C,cAAQ,IAAI;AAAA,IACd;AAEA,YAAQ,IAAI,cAAc,KAAK,aAAa,EAAE;AAC9C,YAAQ,IAAI,UAAU,OAAO,UAAU,EAAE;AACzC,YAAQ,IAAI,eAAe,OAAO,eAAe,EAAE;AACnD,YAAQ,IAAI;AAAA,EACd,QAAQ;AACN,YAAQ,MAAM,oDAAoD;AAClE,YAAQ,MAAM,0BAA0B,IAAI,SAAS;AACrD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,SAASA,cAAa,IAAoB;AACxC,QAAM,UAAU,KAAK,MAAM,KAAK,GAAI;AACpC,QAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,QAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,QAAM,OAAO,KAAK,MAAM,QAAQ,EAAE;AAElC,MAAI,OAAO,EAAG,QAAO,GAAG,IAAI,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE;AAC5D,MAAI,QAAQ,EAAG,QAAO,GAAG,KAAK,KAAK,UAAU,EAAE;AAC/C,MAAI,UAAU,EAAG,QAAO,GAAG,OAAO,KAAK,UAAU,EAAE;AACnD,SAAO,GAAG,OAAO;AACnB;;;AC5FA,eAAsB,cAAc,OAAkD;AACpF,QAAM,SAAS,MAAM,IAAI,KAAK;AAC9B,QAAM,QAAQ,MAAM,IAAI,KAAK;AAG7B,MAAI,OAAO,WAAW,UAAU;AAC9B,QAAI,CAAC,aAAa,GAAG;AACnB,cAAQ,MAAM,sDAAsD;AACpE,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAMC,UAAS,WAAW;AAC1B,UAAM,QAASA,QAA8C,MAAM;AACnE,QAAI,UAAU,QAAW;AACvB,cAAQ,MAAM,uBAAuB,MAAM,EAAE;AAC7C,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,YAAQ,IAAI,WAAW,WAAW,WAAW,OAAO,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC;AAC3E;AAAA,EACF;AAGA,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,QAAQ,MAAM,QAAQ,GAAG;AAC/B,QAAI,UAAU,IAAI;AAChB,cAAQ,MAAM,uCAAuC;AACrD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK;AAChC,UAAM,WAAW,MAAM,MAAM,QAAQ,CAAC;AAEtC,QAAI,CAAC,kBAAkB,IAAI,GAAG,KAAK,QAAQ,UAAU;AACnD,cAAQ,MAAM,oCAAoC,GAAG,EAAE;AACvD,cAAQ,MAAM,sBAAsB,CAAC,GAAG,iBAAiB,EAAE,KAAK,IAAI,CAAC,EAAE;AACvE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,QAAI,cAAuB;AAC3B,QAAI,QAAQ,UAAU,QAAQ,0BAA0B,QAAQ,mBAAmB;AACjF,oBAAc,SAAS,UAAU,EAAE;AACnC,UAAI,MAAM,WAAqB,GAAG;AAChC,gBAAQ,MAAM,sBAAsB,GAAG,KAAK,QAAQ,EAAE;AACtD,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF,WAAW,QAAQ,wBAAwB,QAAQ,WAAW;AAC5D,oBAAc,aAAa,UAAU,aAAa;AAAA,IACpD,WAAW,QAAQ,iBAAiB;AAClC,oBAAc,SAAS,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAAA,IACvD;AAEA,eAAW,EAAE,CAAC,GAAG,GAAG,YAAY,CAAC;AACjC,YAAQ,IAAI,OAAO,GAAG,MAAM,QAAQ,WAAW,WAAW,QAAQ,IAAI,QAAQ,EAAE;AAChF;AAAA,EACF;AAGA,MAAI,CAAC,aAAa,GAAG;AACnB,YAAQ,IAAI,sDAAsD;AAClE,YAAQ,IAAI,gBAAgB,WAAW,EAAE;AACzC;AAAA,EACF;AAEA,QAAM,SAAS,WAAW;AAC1B,UAAQ,IAAI;AACZ,UAAQ,IAAI,aAAa,WAAW,EAAE;AACtC,UAAQ,IAAI;AACZ,UAAQ,IAAI,4BAA4B,WAAW,OAAO,MAAM,CAAC,EAAE;AACnE,UAAQ,IAAI,4BAA4B,OAAO,UAAU,EAAE;AAC3D,UAAQ,IAAI,4BAA4B,OAAO,eAAe,EAAE;AAChE,UAAQ,IAAI,4BAA4B,OAAO,oBAAoB,EAAE;AACrE,UAAQ,IAAI,4BAA4B,OAAO,MAAM,SAAS,IAAI,OAAO,MAAM,KAAK,IAAI,IAAI,QAAQ,EAAE;AACtG,UAAQ,IAAI,4BAA4B,OAAO,IAAI,EAAE;AACrD,UAAQ,IAAI,4BAA4B,OAAO,oBAAoB,EAAE;AACrE,UAAQ,IAAI,4BAA4B,OAAO,cAAc,KAAK,IAAI,CAAC,EAAE;AACzE,UAAQ,IAAI,4BAA4B,OAAO,kBAAkB,EAAE;AACnE,UAAQ,IAAI,4BAA4B,OAAO,mBAAmB,MAAM,EAAE;AAC1E,UAAQ,IAAI,4BAA4B,OAAO,OAAO,EAAE;AACxD,UAAQ,IAAI;AACd;;;AClFA,SAAS,gBAAAC,eAAc,cAAAC,aAAY,YAAAC,WAAU,wBAAwB;AACrE,SAAS,WAAW,mBAAmB;AAGvC,eAAsB,YAAY,OAAkD;AAClF,QAAM,SAAS,MAAM,IAAI,QAAQ,KAAK,MAAM,IAAI,GAAG;AACnD,QAAM,YAAY,MAAM,IAAI,OAAO,KAAK,MAAM,IAAI,GAAG;AACrD,QAAM,QAAQ,OAAO,cAAc,WAAW,SAAS,WAAW,EAAE,IAAI;AAExE,MAAI,CAACC,YAAW,QAAQ,GAAG;AACzB,YAAQ,IAAI,4EAA4E;AACxF;AAAA,EACF;AAGA,QAAM,UAAUC,cAAa,UAAU,OAAO;AAC9C,QAAM,WAAW,QAAQ,MAAM,IAAI;AACnC,QAAM,OAAO,SAAS,MAAM,CAAC,QAAQ,CAAC;AACtC,UAAQ,OAAO,MAAM,KAAK,KAAK,IAAI,CAAC;AAEpC,MAAI,CAAC,OAAQ;AAGb,MAAI,WAAWC,UAAS,QAAQ,EAAE;AAElC,YAAU,UAAU,EAAE,UAAU,IAAI,GAAG,CAAC,SAAS;AAC/C,QAAI,KAAK,OAAO,UAAU;AACxB,YAAM,SAAS,iBAAiB,UAAU,EAAE,OAAO,UAAU,UAAU,QAAQ,CAAC;AAChF,aAAO,GAAG,QAAQ,CAAC,UAAU,QAAQ,OAAO,MAAM,KAAe,CAAC;AAClE,aAAO,GAAG,OAAO,MAAM;AAAE,mBAAW,KAAK;AAAA,MAAK,CAAC;AAAA,IACjD,WAAW,KAAK,OAAO,UAAU;AAE/B,iBAAW;AAAA,IACb;AAAA,EACF,CAAC;AAGD,UAAQ,GAAG,UAAU,MAAM;AACzB,gBAAY,QAAQ;AACpB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAGD,QAAM,IAAI,QAAQ,MAAM;AAAA,EAAC,CAAC;AAC5B;;;ACnCA,IAAM,QAAQ;AAAA,aACD,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBpB,SAAS,UAAU,MAAwE;AACzF,QAAM,UAAU,KAAK,CAAC,KAAK;AAC3B,QAAM,QAAQ,oBAAI,IAA2B;AAE7C,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,IAAI,WAAW,IAAI,GAAG;AACxB,YAAM,MAAM,IAAI,MAAM,CAAC;AAEvB,UAAI,IAAI,IAAI,KAAK,UAAU,CAAC,KAAK,IAAI,CAAC,EAAE,WAAW,GAAG,GAAG;AACvD,cAAM,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC;AAC1B;AAAA,MACF,OAAO;AACL,cAAM,IAAI,KAAK,IAAI;AAAA,MACrB;AAAA,IACF,WAAW,IAAI,WAAW,GAAG,KAAK,IAAI,WAAW,GAAG;AAClD,YAAM,MAAM,IAAI,MAAM,CAAC;AACvB,UAAI,IAAI,IAAI,KAAK,UAAU,CAAC,KAAK,IAAI,CAAC,EAAE,WAAW,GAAG,GAAG;AACvD,cAAM,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC;AAC1B;AAAA,MACF,OAAO;AACL,cAAM,IAAI,KAAK,IAAI;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,MAAM;AAC1B;AAEA,eAAe,OAAsB;AACnC,QAAM,EAAE,SAAS,MAAM,IAAI,UAAU,QAAQ,IAAI;AAGjD,MAAI,MAAM,IAAI,GAAG,KAAK,MAAM,IAAI,MAAM,KAAK,YAAY,UAAU,YAAY,YAAY,YAAY,MAAM;AACzG,YAAQ,IAAI,KAAK;AACjB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,MAAM,IAAI,GAAG,KAAK,MAAM,IAAI,SAAS,KAAK,YAAY,aAAa,YAAY,eAAe,YAAY,MAAM;AAClH,YAAQ,IAAI,OAAO;AACnB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI;AACF,YAAQ,SAAS;AAAA,MACf,KAAK;AACH,cAAM,YAAY;AAClB;AAAA,MAEF,KAAK;AACH,cAAM,aAAa,KAAK;AACxB;AAAA,MAEF,KAAK;AACH,cAAM,YAAY;AAClB;AAAA,MAEF,KAAK;AACH,cAAM,cAAc;AACpB;AAAA,MAEF,KAAK;AACH,cAAM,eAAe;AACrB;AAAA,MAEF,KAAK;AACH,cAAM,cAAc,KAAK;AACzB;AAAA,MAEF,KAAK;AACH,cAAM,YAAY,KAAK;AACvB;AAAA,MAEF,KAAK;AACH,gBAAQ,IAAI,KAAK;AACjB,gBAAQ,KAAK,CAAC;AACd;AAAA,MAEF;AACE,gBAAQ,MAAM,oBAAoB,OAAO,EAAE;AAC3C,gBAAQ,IAAI,KAAK;AACjB,gBAAQ,KAAK,CAAC;AAAA,IAClB;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,YAAQ,MAAM,UAAU,OAAO,EAAE;AACjC,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,KAAK;","names":["RSCTransport","CircuitBreaker","RSCCircuitOpenError","RSCCircuitOpenError","RSCCircuitOpenError","setCORSHeaders","RSCCircuitOpenError","setCORSHeaders","sendJSON","mkdirSync","existsSync","dirname","dirname","existsSync","mkdirSync","readFileSync","writeFileSync","existsSync","writeFileSync","existsSync","readFileSync","formatUptime","config","readFileSync","existsSync","statSync","existsSync","readFileSync","statSync"]}
1
+ {"version":3,"sources":["../src/version.ts","../src/commands/init.ts","../src/config/loader.ts","../src/config/paths.ts","../src/config/schema.ts","../src/ui/prompts.ts","../src/rsc/pipeline.ts","../src/proxy/completions.ts","../src/rsc/message-compressor.ts","../src/rsc/learning.ts","../src/proxy/streaming.ts","../src/proxy/messages.ts","../src/proxy/anthropic-streaming.ts","../src/proxy/handler.ts","../src/proxy/server.ts","../src/daemon/logger.ts","../src/daemon/lifecycle.ts","../src/commands/start.ts","../src/commands/stop.ts","../src/commands/status.ts","../src/commands/summary.ts","../src/commands/config.ts","../src/commands/logs.ts","../src/bin.ts"],"sourcesContent":["declare const __VERSION__: string\nexport const VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.2.1'\n\n// FIGlet-style \"LIMINAL\" banner\nconst BANNER_LINES = [\n ' ___ ___ _____ ______ ___ ________ ________ ___',\n '|\\\\ \\\\ |\\\\ \\\\|\\\\ _ \\\\ _ \\\\|\\\\ \\\\|\\\\ ___ \\\\|\\\\ __ \\\\|\\\\ \\\\',\n '\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\\\\\__\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\ \\\\ \\\\ \\\\ \\\\|\\\\ \\\\ \\\\ \\\\',\n ' \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\|__| \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\ \\\\ \\\\ \\\\ __ \\\\ \\\\ \\\\',\n ' \\\\ \\\\ \\\\____\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\____',\n ' \\\\ \\\\_______\\\\ \\\\__\\\\ \\\\__\\\\ \\\\ \\\\__\\\\ \\\\__\\\\ \\\\__\\\\\\\\ \\\\__\\\\ \\\\__\\\\ \\\\__\\\\ \\\\_______\\\\',\n ' \\\\|_______|\\\\|__|\\\\|__| \\\\|__|\\\\|__|\\\\|__| \\\\|__|\\\\|__|\\\\|__|\\\\|_______|',\n]\n\nexport function printBanner(): void {\n console.log()\n for (const line of BANNER_LINES) {\n console.log(line)\n }\n console.log()\n console.log(` v${VERSION} -- brought to you by Cognisos`)\n console.log()\n}\n","import { createInterface } from 'node:readline/promises'\nimport { stdin, stdout } from 'node:process'\nimport { existsSync, readFileSync, appendFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { homedir } from 'node:os'\nimport { RSCTransport, CircuitBreaker } from '@cognisos/rsc-sdk'\nimport { saveConfig, ensureDirectories } from '../config/loader.js'\nimport { DEFAULTS } from '../config/schema.js'\nimport { CONFIG_FILE } from '../config/paths.js'\nimport { printBanner } from '../version.js'\nimport { multiSelectPrompt, selectPrompt } from '../ui/prompts.js'\nimport type { Tool } from '../types.js'\n\n// ─── Shell profile detection ─────────────────────────────────────────\n\ninterface ShellProfile {\n name: string\n path: string\n}\n\nfunction detectShellProfile(): ShellProfile | null {\n const shell = process.env.SHELL || ''\n const home = homedir()\n\n // Prefer the user's actual shell\n if (shell.endsWith('/zsh')) {\n const zshrc = join(home, '.zshrc')\n return { name: '~/.zshrc', path: zshrc }\n }\n\n if (shell.endsWith('/bash')) {\n // macOS uses .bash_profile, Linux uses .bashrc\n const bashProfile = join(home, '.bash_profile')\n if (existsSync(bashProfile)) {\n return { name: '~/.bash_profile', path: bashProfile }\n }\n return { name: '~/.bashrc', path: join(home, '.bashrc') }\n }\n\n // Fallback: check common files\n const candidates: ShellProfile[] = [\n { name: '~/.zshrc', path: join(home, '.zshrc') },\n { name: '~/.bashrc', path: join(home, '.bashrc') },\n { name: '~/.profile', path: join(home, '.profile') },\n ]\n\n for (const c of candidates) {\n if (existsSync(c.path)) return c\n }\n\n return null\n}\n\n/**\n * Build the export lines needed for the selected tools.\n */\nfunction getExportLines(tools: Tool[], port: number): string[] {\n const base = `http://127.0.0.1:${port}`\n const lines: string[] = []\n\n if (tools.includes('claude-code')) {\n lines.push(`export ANTHROPIC_BASE_URL=${base}`)\n }\n if (tools.includes('codex') || tools.includes('openai-compatible')) {\n lines.push(`export OPENAI_BASE_URL=${base}/v1`)\n }\n\n return lines\n}\n\n/**\n * Check if a line already exists in a file (avoids duplicate entries).\n */\nfunction lineExistsInFile(filePath: string, line: string): boolean {\n if (!existsSync(filePath)) return false\n try {\n const content = readFileSync(filePath, 'utf-8')\n return content.includes(line)\n } catch {\n return false\n }\n}\n\n/**\n * Append export lines to shell profile, with a Liminal comment header.\n */\nfunction appendToShellProfile(profile: ShellProfile, lines: string[]): void {\n const block = [\n '',\n '# Liminal — route AI tools through compression proxy',\n ...lines,\n ].join('\\n') + '\\n'\n\n appendFileSync(profile.path, block, 'utf-8')\n}\n\nexport async function initCommand(): Promise<void> {\n printBanner()\n console.log(' Welcome to Liminal -- Your Transparency & Context Partner')\n console.log()\n console.log(\" Let's start evolving.\")\n console.log()\n\n // ── Text inputs (readline) ──────────────────────────────────────\n const rl = createInterface({ input: stdin, output: stdout })\n let apiKey: string\n let port: number\n\n try {\n const apiKeyInput = await rl.question(' \\x1b[1mLiminal API key\\x1b[0m: ')\n if (!apiKeyInput.trim()) {\n console.error('\\n Error: API key is required.')\n process.exit(1)\n }\n apiKey = apiKeyInput.trim()\n\n const portInput = await rl.question(` Proxy port [${DEFAULTS.port}]: `)\n port = portInput.trim() ? parseInt(portInput.trim(), 10) : DEFAULTS.port\n if (isNaN(port) || port < 1 || port > 65535) {\n console.error('\\n Error: Invalid port number.')\n process.exit(1)\n }\n } finally {\n rl.close()\n }\n\n console.log()\n\n // ── Interactive prompts (raw mode) ──────────────────────────────\n const toolsResult = await multiSelectPrompt<Tool>({\n message: 'Which AI tools will you use with Liminal?',\n options: [\n { label: 'Claude Code', value: 'claude-code', default: true },\n { label: 'Codex', value: 'codex' },\n { label: 'Cursor', value: 'cursor' },\n { label: 'Other / OpenAI', value: 'openai-compatible' },\n ],\n })\n const tools: Tool[] = toolsResult ?? ['claude-code']\n\n console.log()\n\n const learnResult = await selectPrompt<boolean>({\n message: 'Learn from LLM responses?',\n options: [\n { label: 'Yes', value: true, description: 'Improve compression over time' },\n { label: 'No', value: false, description: 'Skip response learning' },\n ],\n defaultIndex: 0,\n })\n const learnFromResponses = learnResult ?? true\n\n console.log()\n\n // ── Validate API key ────────────────────────────────────────────\n const apiBaseUrl = DEFAULTS.apiBaseUrl\n process.stdout.write(' Validating API key... ')\n try {\n const breaker = new CircuitBreaker(3, 10_000)\n const transport = new RSCTransport({\n baseUrl: apiBaseUrl,\n apiKey,\n timeout: 10_000,\n maxRetries: 1,\n circuitBreaker: breaker,\n })\n await transport.get<{ status: string }>('/health')\n console.log('OK')\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n console.log('FAILED')\n console.error(`\\n Could not connect to Liminal API: ${message}`)\n console.error(' Check your API key and URL, then try again.')\n process.exit(1)\n }\n\n // ── Save config ─────────────────────────────────────────────────\n ensureDirectories()\n saveConfig({\n apiKey,\n apiBaseUrl,\n upstreamBaseUrl: DEFAULTS.upstreamBaseUrl,\n anthropicUpstreamUrl: DEFAULTS.anthropicUpstreamUrl,\n port,\n learnFromResponses,\n tools,\n compressionThreshold: DEFAULTS.compressionThreshold,\n compressRoles: DEFAULTS.compressRoles,\n latencyBudgetMs: DEFAULTS.latencyBudgetMs,\n enabled: DEFAULTS.enabled,\n })\n\n console.log()\n console.log(` Configuration saved to ${CONFIG_FILE}`)\n console.log()\n\n // ── Shell auto-configuration ────────────────────────────────────\n const exportLines = getExportLines(tools, port)\n const hasCursor = tools.includes('cursor')\n\n if (exportLines.length > 0) {\n const profile = detectShellProfile()\n\n if (profile) {\n // Check if already configured\n const allExist = exportLines.every((line) => lineExistsInFile(profile.path, line))\n\n if (allExist) {\n console.log(` Shell already configured in ${profile.name}`)\n } else {\n const autoResult = await selectPrompt<boolean>({\n message: 'Configure shell automatically?',\n options: [\n { label: 'Yes', value: true, description: `Add to ${profile.name}` },\n { label: 'No', value: false, description: \"I'll set it up manually\" },\n ],\n defaultIndex: 0,\n })\n\n if (autoResult === true) {\n // Only append lines that don't already exist\n const newLines = exportLines.filter((line) => !lineExistsInFile(profile.path, line))\n if (newLines.length > 0) {\n appendToShellProfile(profile, newLines)\n }\n console.log()\n console.log(` Added to ${profile.name}:`)\n for (const line of exportLines) {\n console.log(` ${line}`)\n }\n console.log()\n console.log(` Run \\x1b[1msource ${profile.name}\\x1b[0m or restart your terminal to apply.`)\n } else {\n console.log()\n console.log(' Add these to your shell profile:')\n console.log()\n for (const line of exportLines) {\n console.log(` ${line}`)\n }\n }\n }\n } else {\n // No shell profile detected — show manual instructions\n console.log(' Add these to your shell profile:')\n console.log()\n for (const line of exportLines) {\n console.log(` ${line}`)\n }\n }\n }\n\n // Cursor requires manual GUI configuration\n if (hasCursor) {\n console.log()\n console.log(' Cursor setup (manual):')\n console.log(` Settings > Models > OpenAI API Base URL: http://127.0.0.1:${port}/v1`)\n }\n\n console.log()\n console.log(' Next step:')\n console.log(' liminal start')\n console.log()\n}\n","import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { LIMINAL_DIR, CONFIG_FILE, LOG_DIR } from './paths.js'\nimport { DEFAULTS } from './schema.js'\nimport type { RSCConfig } from './schema.js'\n\n/**\n * Load config from ~/.liminal/config.json, merged with defaults and env var overrides.\n * Priority: env vars > config file > defaults\n */\nexport function loadConfig(): RSCConfig {\n let fileConfig: Partial<RSCConfig> = {}\n\n if (existsSync(CONFIG_FILE)) {\n try {\n const raw = readFileSync(CONFIG_FILE, 'utf-8')\n fileConfig = JSON.parse(raw)\n } catch {\n // Corrupted config file — fall through to defaults\n }\n }\n\n const merged: RSCConfig = {\n apiKey: fileConfig.apiKey ?? '',\n apiBaseUrl: DEFAULTS.apiBaseUrl,\n upstreamBaseUrl: DEFAULTS.upstreamBaseUrl,\n anthropicUpstreamUrl: DEFAULTS.anthropicUpstreamUrl,\n port: DEFAULTS.port,\n compressionThreshold: DEFAULTS.compressionThreshold,\n compressRoles: DEFAULTS.compressRoles,\n learnFromResponses: DEFAULTS.learnFromResponses,\n latencyBudgetMs: DEFAULTS.latencyBudgetMs,\n enabled: DEFAULTS.enabled,\n tools: DEFAULTS.tools,\n ...fileConfig,\n }\n\n // Environment variable overrides\n if (process.env.LIMINAL_API_KEY) merged.apiKey = process.env.LIMINAL_API_KEY\n if (process.env.LIMINAL_API_URL) merged.apiBaseUrl = process.env.LIMINAL_API_URL\n if (process.env.LIMINAL_UPSTREAM_URL) merged.upstreamBaseUrl = process.env.LIMINAL_UPSTREAM_URL\n if (process.env.LIMINAL_ANTHROPIC_URL) merged.anthropicUpstreamUrl = process.env.LIMINAL_ANTHROPIC_URL\n if (process.env.LIMINAL_PORT) merged.port = parseInt(process.env.LIMINAL_PORT, 10)\n\n return merged\n}\n\n/**\n * Apply CLI flag overrides on top of loaded config.\n */\nexport function applyOverrides(\n config: RSCConfig,\n overrides: Partial<Pick<RSCConfig, 'port' | 'upstreamBaseUrl'>>,\n): RSCConfig {\n return { ...config, ...overrides }\n}\n\n/**\n * Save config to ~/.liminal/config.json. Creates ~/.liminal/ and ~/.liminal/logs/ if needed.\n */\nexport function saveConfig(config: Partial<RSCConfig>): void {\n ensureDirectories()\n\n let existing: Partial<RSCConfig> = {}\n if (existsSync(CONFIG_FILE)) {\n try {\n existing = JSON.parse(readFileSync(CONFIG_FILE, 'utf-8'))\n } catch {\n // Overwrite corrupted file\n }\n }\n\n const merged = { ...existing, ...config }\n writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2) + '\\n', 'utf-8')\n}\n\n/**\n * Ensure ~/.liminal/ and ~/.liminal/logs/ directories exist.\n */\nexport function ensureDirectories(): void {\n if (!existsSync(LIMINAL_DIR)) mkdirSync(LIMINAL_DIR, { recursive: true })\n if (!existsSync(LOG_DIR)) mkdirSync(LOG_DIR, { recursive: true })\n // Ensure parent of config file exists\n const configDir = dirname(CONFIG_FILE)\n if (!existsSync(configDir)) mkdirSync(configDir, { recursive: true })\n}\n\n/**\n * Check if a valid config file exists with an API key.\n */\nexport function isConfigured(): boolean {\n try {\n const config = loadConfig()\n return config.apiKey.length > 0\n } catch {\n return false\n }\n}\n\n/**\n * Mask an API key for display: show first 8 chars + last 4.\n */\nexport function maskApiKey(key: string): string {\n if (key.length <= 12) return '****'\n return key.slice(0, 8) + '...' + key.slice(-4)\n}\n","import { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport const LIMINAL_DIR = join(homedir(), '.liminal')\nexport const CONFIG_FILE = join(LIMINAL_DIR, 'config.json')\nexport const PID_FILE = join(LIMINAL_DIR, 'liminal.pid')\nexport const LOG_DIR = join(LIMINAL_DIR, 'logs')\nexport const LOG_FILE = join(LOG_DIR, 'liminal.log')\n","export interface RSCConfig {\n apiKey: string\n apiBaseUrl: string\n upstreamBaseUrl: string\n anthropicUpstreamUrl: string\n port: number\n compressionThreshold: number\n compressRoles: string[]\n learnFromResponses: boolean\n latencyBudgetMs: number\n enabled: boolean\n tools: string[]\n}\n\nexport const DEFAULTS: Omit<RSCConfig, 'apiKey'> = {\n apiBaseUrl: 'https://rsc-platform-production.up.railway.app',\n upstreamBaseUrl: 'https://api.openai.com',\n anthropicUpstreamUrl: 'https://api.anthropic.com',\n port: 3141,\n compressionThreshold: 100,\n compressRoles: ['user'],\n learnFromResponses: true,\n latencyBudgetMs: 0,\n enabled: true,\n tools: [],\n}\n\n/** Keys that can be set via `liminal config --set` */\nexport const CONFIGURABLE_KEYS = new Set<string>([\n 'apiBaseUrl',\n 'upstreamBaseUrl',\n 'anthropicUpstreamUrl',\n 'port',\n 'compressionThreshold',\n 'compressRoles',\n 'learnFromResponses',\n 'latencyBudgetMs',\n 'enabled',\n 'tools',\n])\n","/**\n * Lightweight interactive terminal prompts — zero external dependencies.\n * Uses raw stdin mode for arrow-key navigation.\n */\n\n// ─── ANSI escape sequences ───────────────────────────────────────────\n\nconst ANSI = {\n HIDE_CURSOR: '\\x1b[?25l',\n SHOW_CURSOR: '\\x1b[?25h',\n CLEAR_LINE: '\\x1b[2K',\n BOLD: '\\x1b[1m',\n DIM: '\\x1b[2m',\n CYAN: '\\x1b[36m',\n RESET: '\\x1b[0m',\n moveUp: (n: number) => (n > 0 ? `\\x1b[${n}A` : ''),\n} as const\n\n// ─── Key parsing ─────────────────────────────────────────────────────\n\nexport type KeyPress =\n | { type: 'up' }\n | { type: 'down' }\n | { type: 'enter' }\n | { type: 'space' }\n | { type: 'escape' }\n | { type: 'ctrlc' }\n | { type: 'other' }\n\nexport function parseKey(data: Buffer): KeyPress {\n if (data.length === 0) return { type: 'other' }\n\n // Ctrl+C\n if (data[0] === 0x03) return { type: 'ctrlc' }\n\n // Arrow keys: ESC [ A/B\n if (data.length >= 3 && data[0] === 0x1b && data[1] === 0x5b) {\n if (data[2] === 0x41) return { type: 'up' }\n if (data[2] === 0x42) return { type: 'down' }\n return { type: 'other' }\n }\n\n // Standalone Escape\n if (data.length === 1 && data[0] === 0x1b) return { type: 'escape' }\n\n // Enter\n if (data[0] === 0x0d || data[0] === 0x0a) return { type: 'enter' }\n\n // Space\n if (data[0] === 0x20) return { type: 'space' }\n\n return { type: 'other' }\n}\n\n// ─── Types ───────────────────────────────────────────────────────────\n\nexport interface SelectOption<T> {\n label: string\n value: T\n description?: string\n}\n\nexport interface MultiSelectOption<T> extends SelectOption<T> {\n default?: boolean\n}\n\ninterface Streams {\n stdin: NodeJS.ReadableStream & { setRawMode?: (mode: boolean) => void; isTTY?: boolean }\n stdout: { write: (s: string) => boolean }\n}\n\ninterface SelectConfig<T> {\n message: string\n options: SelectOption<T>[]\n defaultIndex?: number\n _streams?: Streams\n}\n\ninterface MultiSelectConfig<T> {\n message: string\n options: MultiSelectOption<T>[]\n _streams?: Streams\n}\n\n// ─── Render helpers ──────────────────────────────────────────────────\n\nexport interface RenderResult {\n text: string\n lineCount: number\n}\n\nexport function renderSelect<T>(\n options: SelectOption<T>[],\n cursorIndex: number,\n message: string,\n): RenderResult {\n const lines: string[] = []\n lines.push(` ${ANSI.BOLD}${message}${ANSI.RESET}`)\n lines.push('')\n\n const maxLabel = Math.max(...options.map((o) => o.label.length))\n\n for (let i = 0; i < options.length; i++) {\n const focused = i === cursorIndex\n const pointer = focused ? `${ANSI.CYAN}->${ANSI.RESET}` : ' '\n const label = focused\n ? `${ANSI.BOLD}${options[i].label.padEnd(maxLabel)}${ANSI.RESET}`\n : `${options[i].label.padEnd(maxLabel)}`\n const desc = options[i].description\n ? ` ${ANSI.DIM}${options[i].description}${ANSI.RESET}`\n : ''\n lines.push(` ${pointer} ${label}${desc}`)\n }\n\n lines.push('')\n return { text: lines.join('\\n'), lineCount: lines.length }\n}\n\nexport function renderMultiSelect<T>(\n options: MultiSelectOption<T>[],\n cursorIndex: number,\n selected: Set<number>,\n message: string,\n): RenderResult {\n const lines: string[] = []\n lines.push(` ${ANSI.BOLD}${message}${ANSI.RESET}`)\n lines.push('')\n\n const maxLabel = Math.max(...options.map((o) => o.label.length))\n\n for (let i = 0; i < options.length; i++) {\n const focused = i === cursorIndex\n const checked = selected.has(i)\n const pointer = focused ? `${ANSI.CYAN}->${ANSI.RESET}` : ' '\n const box = checked\n ? `${ANSI.CYAN}[x]${ANSI.RESET}`\n : `${ANSI.DIM}[ ]${ANSI.RESET}`\n const label = focused\n ? `${ANSI.BOLD}${options[i].label.padEnd(maxLabel)}${ANSI.RESET}`\n : `${options[i].label.padEnd(maxLabel)}`\n const desc = options[i].description\n ? ` ${ANSI.DIM}${options[i].description}${ANSI.RESET}`\n : ''\n lines.push(` ${pointer} ${box} ${label}${desc}`)\n }\n\n lines.push('')\n lines.push(` ${ANSI.DIM}Space to toggle, Enter to confirm${ANSI.RESET}`)\n lines.push('')\n return { text: lines.join('\\n'), lineCount: lines.length }\n}\n\n// ─── Raw mode lifecycle ──────────────────────────────────────────────\n\nfunction withRawMode<T>(\n streams: Streams,\n handler: (\n resolve: (value: T) => void,\n ) => (key: KeyPress) => void,\n): Promise<T> {\n const { stdin, stdout } = streams\n\n return new Promise<T>((resolve, reject) => {\n let cleaned = false\n\n function cleanup() {\n if (cleaned) return\n cleaned = true\n stdin.removeListener('data', onData)\n if (stdin.setRawMode) stdin.setRawMode(false)\n if ('pause' in stdin && typeof (stdin as any).pause === 'function') {\n (stdin as any).pause()\n }\n stdout.write(ANSI.SHOW_CURSOR)\n process.removeListener('exit', cleanup)\n }\n\n function onData(data: Buffer) {\n const key = parseKey(data)\n if (key.type === 'ctrlc') {\n cleanup()\n process.exit(130)\n }\n keyHandler(key)\n }\n\n const keyHandler = handler((value: T) => {\n cleanup()\n resolve(value)\n })\n\n // Safety: restore terminal on unexpected exit\n process.on('exit', cleanup)\n\n try {\n if (stdin.setRawMode) stdin.setRawMode(true)\n stdout.write(ANSI.HIDE_CURSOR)\n stdin.on('data', onData)\n if ('resume' in stdin && typeof (stdin as any).resume === 'function') {\n (stdin as any).resume()\n }\n } catch (err) {\n cleanup()\n reject(err)\n }\n })\n}\n\n// ─── Public API ──────────────────────────────────────────────────────\n\nexport async function selectPrompt<T>(config: SelectConfig<T>): Promise<T | null> {\n const { message, options, defaultIndex = 0, _streams } = config\n const streams = _streams ?? { stdin: process.stdin, stdout: process.stdout }\n let cursorIndex = defaultIndex\n let prevLineCount = 0\n\n function draw() {\n const { text, lineCount } = renderSelect(options, cursorIndex, message)\n // Move up to overwrite previous render\n if (prevLineCount > 0) {\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n }\n // Clear and write each line\n const lines = text.split('\\n')\n for (const line of lines) {\n streams.stdout.write(ANSI.CLEAR_LINE + line + '\\n')\n }\n prevLineCount = lineCount\n }\n\n draw()\n\n const result = await withRawMode<T | null>(streams, (resolve) => {\n return (key: KeyPress) => {\n switch (key.type) {\n case 'up':\n cursorIndex = (cursorIndex - 1 + options.length) % options.length\n draw()\n break\n case 'down':\n cursorIndex = (cursorIndex + 1) % options.length\n draw()\n break\n case 'enter':\n resolve(options[cursorIndex].value)\n break\n case 'escape':\n resolve(null)\n break\n }\n }\n })\n\n // Show confirmed selection\n if (result !== null) {\n const selected = options.find((o) => o.value === result)\n if (selected) {\n // Overwrite prompt with confirmed value\n if (prevLineCount > 0) {\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n }\n for (let i = 0; i < prevLineCount; i++) {\n streams.stdout.write(ANSI.CLEAR_LINE + '\\n')\n }\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n streams.stdout.write(` ${ANSI.BOLD}${message}${ANSI.RESET} ${ANSI.CYAN}${selected.label}${ANSI.RESET}\\n`)\n }\n }\n\n return result\n}\n\nexport async function multiSelectPrompt<T>(config: MultiSelectConfig<T>): Promise<T[] | null> {\n const { message, options, _streams } = config\n const streams = _streams ?? { stdin: process.stdin, stdout: process.stdout }\n let cursorIndex = 0\n const selected = new Set<number>()\n let prevLineCount = 0\n\n // Pre-fill defaults\n for (let i = 0; i < options.length; i++) {\n if (options[i].default) selected.add(i)\n }\n\n function draw() {\n const { text, lineCount } = renderMultiSelect(options, cursorIndex, selected, message)\n if (prevLineCount > 0) {\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n }\n const lines = text.split('\\n')\n for (const line of lines) {\n streams.stdout.write(ANSI.CLEAR_LINE + line + '\\n')\n }\n prevLineCount = lineCount\n }\n\n draw()\n\n const result = await withRawMode<T[] | null>(streams, (resolve) => {\n return (key: KeyPress) => {\n switch (key.type) {\n case 'up':\n cursorIndex = (cursorIndex - 1 + options.length) % options.length\n draw()\n break\n case 'down':\n cursorIndex = (cursorIndex + 1) % options.length\n draw()\n break\n case 'space':\n if (selected.has(cursorIndex)) {\n selected.delete(cursorIndex)\n } else {\n selected.add(cursorIndex)\n }\n draw()\n break\n case 'enter':\n if (selected.size > 0) {\n const values = [...selected].sort().map((i) => options[i].value)\n resolve(values)\n }\n // If nothing selected, ignore Enter (must select at least 1)\n break\n case 'escape':\n resolve(null)\n break\n }\n }\n })\n\n // Show confirmed selection\n if (result !== null) {\n const labels = [...selected].sort().map((i) => options[i].label)\n if (prevLineCount > 0) {\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n }\n for (let i = 0; i < prevLineCount; i++) {\n streams.stdout.write(ANSI.CLEAR_LINE + '\\n')\n }\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n streams.stdout.write(` ${ANSI.BOLD}${message}${ANSI.RESET} ${ANSI.CYAN}${labels.join(', ')}${ANSI.RESET}\\n`)\n }\n\n return result\n}\n","import {\n CompressionPipeline,\n RSCTransport,\n RSCEventEmitter,\n Session,\n CircuitBreaker,\n} from '@cognisos/rsc-sdk'\nimport type { SessionSummary, CircuitState } from '@cognisos/rsc-sdk'\n\nexport interface PipelineConfig {\n rscApiKey: string\n rscBaseUrl: string\n compressionThreshold: number\n learnFromResponses: boolean\n latencyBudgetMs?: number\n sessionId?: string\n}\n\nexport class RSCPipelineWrapper {\n readonly pipeline: CompressionPipeline\n readonly session: Session\n readonly events: RSCEventEmitter\n readonly transport: RSCTransport\n private readonly circuitBreaker: CircuitBreaker\n\n constructor(config: PipelineConfig) {\n this.circuitBreaker = new CircuitBreaker(5, 5 * 60 * 1000)\n\n this.transport = new RSCTransport({\n baseUrl: config.rscBaseUrl,\n apiKey: config.rscApiKey,\n timeout: 30_000,\n maxRetries: 3,\n circuitBreaker: this.circuitBreaker,\n })\n\n this.events = new RSCEventEmitter()\n this.session = new Session(config.sessionId)\n\n this.pipeline = new CompressionPipeline(\n this.transport,\n {\n threshold: config.compressionThreshold,\n learnFromResponses: config.learnFromResponses,\n latencyBudgetMs: config.latencyBudgetMs,\n sessionId: this.session.sessionId,\n },\n this.events,\n )\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n await this.transport.get<{ status: string }>('/health')\n return true\n } catch {\n return false\n }\n }\n\n getSessionSummary(): SessionSummary {\n return this.session.getSummary()\n }\n\n getCircuitState(): CircuitState {\n return this.circuitBreaker.getState()\n }\n\n isCircuitOpen(): boolean {\n return this.circuitBreaker.getState() === 'open'\n }\n\n resetCircuitBreaker(): void {\n this.circuitBreaker.reset()\n }\n}\n","import * as http from 'node:http'\nimport { RSCCircuitOpenError } from '@cognisos/rsc-sdk'\nimport { compressMessages } from '../rsc/message-compressor.js'\nimport { createStreamLearningBuffer } from '../rsc/learning.js'\nimport { pipeSSEResponse } from './streaming.js'\nimport type { RSCPipelineWrapper } from '../rsc/pipeline.js'\nimport type { ChatCompletionRequest, ResolvedConfig } from '../types.js'\nimport type { Logger } from './handler.js'\n\nfunction setCORSHeaders(res: http.ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization')\n}\n\nfunction sendJSON(res: http.ServerResponse, status: number, body: unknown): void {\n setCORSHeaders(res)\n res.writeHead(status, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify(body))\n}\n\n/**\n * Extract the bearer token from the Authorization header.\n * This is the user's LLM API key — used to forward to the upstream LLM.\n */\nfunction extractBearerToken(req: http.IncomingMessage): string | null {\n const auth = req.headers.authorization\n if (!auth || !auth.startsWith('Bearer ')) return null\n return auth.slice(7)\n}\n\nexport async function handleChatCompletions(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body: unknown,\n pipeline: RSCPipelineWrapper,\n config: ResolvedConfig,\n logger: Logger,\n): Promise<void> {\n const request = body as ChatCompletionRequest\n\n // Validate required fields\n if (!request.messages || !Array.isArray(request.messages)) {\n sendJSON(res, 400, {\n error: { message: 'messages is required and must be an array', type: 'invalid_request_error' },\n })\n return\n }\n\n // Extract LLM API key from the incoming request\n const llmApiKey = extractBearerToken(req)\n if (!llmApiKey) {\n sendJSON(res, 401, {\n error: { message: 'Authorization header with Bearer token is required', type: 'authentication_error' },\n })\n return\n }\n\n // Compress messages (or passthrough if circuit is open / disabled)\n let messages = request.messages\n let anyCompressed = false\n\n if (config.enabled && !pipeline.isCircuitOpen()) {\n try {\n const compressRoles = new Set(config.compressRoles)\n const result = await compressMessages(\n request.messages,\n pipeline.pipeline,\n pipeline.session,\n compressRoles,\n )\n messages = result.messages\n anyCompressed = result.anyCompressed\n\n if (result.totalTokensSaved > 0) {\n logger.log(`[COMPRESS] Saved ${result.totalTokensSaved} tokens`)\n }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n logger.log('[DEGRADE] Circuit breaker open — passing through directly')\n } else {\n logger.log(`[ERROR] Compression failed: ${err instanceof Error ? err.message : String(err)}`)\n }\n // Fall through with original messages\n messages = request.messages\n }\n }\n\n // Build upstream request\n const upstreamUrl = `${config.upstreamBaseUrl}/v1/chat/completions`\n const upstreamBody = { ...request, messages }\n\n const upstreamHeaders: Record<string, string> = {\n 'Authorization': `Bearer ${llmApiKey}`,\n 'Content-Type': 'application/json',\n }\n\n // Forward streaming preference\n if (request.stream) {\n upstreamHeaders['Accept'] = 'text/event-stream'\n }\n\n try {\n const upstreamResponse = await fetch(upstreamUrl, {\n method: 'POST',\n headers: upstreamHeaders,\n body: JSON.stringify(upstreamBody),\n })\n\n // Handle upstream errors\n if (!upstreamResponse.ok) {\n const errorBody = await upstreamResponse.text()\n setCORSHeaders(res)\n res.writeHead(upstreamResponse.status, {\n 'Content-Type': upstreamResponse.headers.get('Content-Type') || 'application/json',\n })\n res.end(errorBody)\n return\n }\n\n // Streaming response\n if (request.stream && upstreamResponse.body) {\n const learningBuffer = anyCompressed\n ? createStreamLearningBuffer(pipeline.pipeline)\n : null\n\n await pipeSSEResponse(\n upstreamResponse,\n res,\n (text) => learningBuffer?.append(text),\n () => learningBuffer?.flush(),\n )\n return\n }\n\n // Non-streaming response\n const responseBody = await upstreamResponse.text()\n setCORSHeaders(res)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(responseBody)\n\n // Trigger learning from response (fire-and-forget)\n if (anyCompressed) {\n try {\n const parsed = JSON.parse(responseBody)\n const content = parsed?.choices?.[0]?.message?.content\n if (typeof content === 'string' && content.length > 0) {\n pipeline.pipeline.triggerLearning(content)\n }\n } catch {\n // Ignore learning parse errors\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[ERROR] Upstream request failed: ${message}`)\n if (!res.headersSent) {\n sendJSON(res, 502, {\n error: { message: `Failed to reach upstream LLM: ${message}`, type: 'server_error' },\n })\n }\n }\n}\n","import type { CompressionPipeline, Session } from '@cognisos/rsc-sdk'\nimport { RSCCircuitOpenError } from '@cognisos/rsc-sdk'\nimport type { ChatCompletionMessage, ContentPart } from '../types.js'\n\nexport interface CompressedMessagesResult {\n messages: ChatCompletionMessage[]\n anyCompressed: boolean\n totalTokensSaved: number\n}\n\n/**\n * Walk an array of ChatCompletion messages and compress eligible ones\n * via the RSC CompressionPipeline. Non-eligible roles and non-text\n * content parts pass through unchanged.\n */\nexport async function compressMessages(\n messages: ChatCompletionMessage[],\n pipeline: CompressionPipeline,\n session: Session,\n compressRoles: Set<string>,\n): Promise<CompressedMessagesResult> {\n let anyCompressed = false\n let totalTokensSaved = 0\n\n const compressed = await Promise.all(\n messages.map(async (msg) => {\n if (!compressRoles.has(msg.role)) return msg\n\n // String content\n if (typeof msg.content === 'string') {\n return compressStringContent(msg, pipeline, session, (c, saved) => {\n anyCompressed = anyCompressed || c\n totalTokensSaved += saved\n })\n }\n\n // Array content (vision messages with text + image parts)\n if (Array.isArray(msg.content)) {\n return compressArrayContent(msg, pipeline, session, (c, saved) => {\n anyCompressed = anyCompressed || c\n totalTokensSaved += saved\n })\n }\n\n // null or other content — pass through\n return msg\n }),\n )\n\n return { messages: compressed, anyCompressed, totalTokensSaved }\n}\n\nasync function compressStringContent(\n msg: ChatCompletionMessage,\n pipeline: CompressionPipeline,\n session: Session,\n record: (compressed: boolean, saved: number) => void,\n): Promise<ChatCompletionMessage> {\n try {\n const result = await pipeline.compressForLLM(msg.content as string)\n session.recordCompression(result.metrics)\n record(!result.metrics.skipped, result.metrics.tokensSaved)\n return { ...msg, content: result.text }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n session.recordFailure()\n throw err\n }\n // Other RSC errors — return original text, don't block the request\n session.recordFailure()\n return msg\n }\n}\n\nasync function compressArrayContent(\n msg: ChatCompletionMessage,\n pipeline: CompressionPipeline,\n session: Session,\n record: (compressed: boolean, saved: number) => void,\n): Promise<ChatCompletionMessage> {\n const parts = msg.content as ContentPart[]\n\n const compressedParts = await Promise.all(\n parts.map(async (part) => {\n if (part.type === 'text' && typeof part.text === 'string') {\n try {\n const result = await pipeline.compressForLLM(part.text)\n session.recordCompression(result.metrics)\n record(!result.metrics.skipped, result.metrics.tokensSaved)\n return { ...part, text: result.text }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n session.recordFailure()\n throw err\n }\n session.recordFailure()\n return part\n }\n }\n // Pass through image_url, tool_use, etc.\n return part\n }),\n )\n\n return { ...msg, content: compressedParts }\n}\n","import type { CompressionPipeline } from '@cognisos/rsc-sdk'\n\n/**\n * Creates a buffer that accumulates streamed response text and triggers\n * background learning when the stream completes.\n */\nexport function createStreamLearningBuffer(pipeline: CompressionPipeline) {\n let buffer = ''\n\n return {\n /** Append a text delta from an SSE chunk */\n append(text: string): void {\n buffer += text\n },\n\n /** Flush the buffer — triggers fire-and-forget learning */\n flush(): void {\n if (buffer.length > 0) {\n pipeline.triggerLearning(buffer)\n buffer = ''\n }\n },\n\n /** Get current buffer contents (for testing) */\n getBuffer(): string {\n return buffer\n },\n }\n}\n","import * as http from 'node:http'\n\n/**\n * Pipe an SSE response from an upstream LLM to the client,\n * parsing content deltas for the learning buffer.\n *\n * Writes each chunk immediately — zero buffering, zero added latency.\n */\nexport async function pipeSSEResponse(\n upstreamResponse: Response,\n clientRes: http.ServerResponse,\n onContentDelta: (text: string) => void,\n onComplete: () => void,\n): Promise<void> {\n clientRes.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n })\n\n const reader = upstreamResponse.body!.getReader()\n const decoder = new TextDecoder()\n let lineBuf = ''\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n const chunk = decoder.decode(value, { stream: true })\n\n // Write immediately to client\n clientRes.write(chunk)\n\n // Parse SSE lines for learning (best-effort, never blocks the pipe)\n lineBuf += chunk\n const lines = lineBuf.split('\\n')\n lineBuf = lines.pop() || ''\n\n for (const line of lines) {\n if (line.startsWith('data: ') && line !== 'data: [DONE]') {\n try {\n const json = JSON.parse(line.slice(6))\n const content = json?.choices?.[0]?.delta?.content\n if (typeof content === 'string') {\n onContentDelta(content)\n }\n } catch {\n // Malformed SSE data — ignore for learning, chunk already piped\n }\n }\n }\n }\n } finally {\n clientRes.end()\n onComplete()\n }\n}\n","import * as http from 'node:http'\nimport { RSCCircuitOpenError } from '@cognisos/rsc-sdk'\nimport { compressMessages } from '../rsc/message-compressor.js'\nimport { createStreamLearningBuffer } from '../rsc/learning.js'\nimport { pipeAnthropicSSEResponse } from './anthropic-streaming.js'\nimport type { RSCPipelineWrapper } from '../rsc/pipeline.js'\nimport type { ChatCompletionMessage, ResolvedConfig } from '../types.js'\nimport type { AnthropicMessagesRequest, AnthropicMessage, AnthropicContentBlock } from '../types/anthropic.js'\nimport type { Logger } from './handler.js'\n\nfunction setCORSHeaders(res: http.ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-api-key, anthropic-version, anthropic-beta')\n}\n\nfunction sendAnthropicError(res: http.ServerResponse, status: number, type: string, message: string): void {\n setCORSHeaders(res)\n res.writeHead(status, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({ type: 'error', error: { type, message } }))\n}\n\nfunction extractAnthropicApiKey(req: http.IncomingMessage): string | null {\n const key = req.headers['x-api-key']\n if (typeof key === 'string' && key.length > 0) return key\n return null\n}\n\n/**\n * Convert Anthropic messages to ChatCompletionMessage[] for the compressor.\n * The structures are compatible — this is a thin adapter.\n */\nfunction convertAnthropicToCompressible(messages: AnthropicMessage[]): ChatCompletionMessage[] {\n return messages.map((msg) => ({\n role: msg.role,\n content: msg.content as string | AnthropicContentBlock[],\n }))\n}\n\n/**\n * Convert compressed ChatCompletionMessage[] back to Anthropic format.\n */\nfunction convertCompressedToAnthropic(messages: ChatCompletionMessage[]): AnthropicMessage[] {\n return messages.map((msg) => ({\n role: msg.role as 'user' | 'assistant',\n content: msg.content as string | AnthropicContentBlock[],\n }))\n}\n\nexport async function handleAnthropicMessages(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body: unknown,\n pipeline: RSCPipelineWrapper,\n config: ResolvedConfig,\n logger: Logger,\n): Promise<void> {\n const request = body as AnthropicMessagesRequest\n\n // Validate required fields\n if (!request.messages || !Array.isArray(request.messages)) {\n sendAnthropicError(res, 400, 'invalid_request_error', 'messages is required and must be an array')\n return\n }\n\n if (typeof request.max_tokens !== 'number') {\n sendAnthropicError(res, 400, 'invalid_request_error', 'max_tokens is required')\n return\n }\n\n // Extract API key from x-api-key header\n const apiKey = extractAnthropicApiKey(req)\n if (!apiKey) {\n sendAnthropicError(res, 401, 'authentication_error', 'x-api-key header is required')\n return\n }\n\n // Compress messages (reuse existing compressor via format conversion)\n let messages = request.messages\n let anyCompressed = false\n\n if (config.enabled && !pipeline.isCircuitOpen()) {\n try {\n const compressRoles = new Set(config.compressRoles)\n const compressible = convertAnthropicToCompressible(request.messages)\n const result = await compressMessages(\n compressible,\n pipeline.pipeline,\n pipeline.session,\n compressRoles,\n )\n messages = convertCompressedToAnthropic(result.messages)\n anyCompressed = result.anyCompressed\n\n if (result.totalTokensSaved > 0) {\n logger.log(`[COMPRESS] Saved ${result.totalTokensSaved} tokens`)\n }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n logger.log('[DEGRADE] Circuit breaker open -- passing through directly')\n } else {\n logger.log(`[ERROR] Compression failed: ${err instanceof Error ? err.message : String(err)}`)\n }\n messages = request.messages\n }\n }\n\n // Build upstream request\n const upstreamUrl = `${config.anthropicUpstreamUrl}/v1/messages`\n const upstreamBody = { ...request, messages }\n\n const upstreamHeaders: Record<string, string> = {\n 'x-api-key': apiKey,\n 'anthropic-version': (req.headers['anthropic-version'] as string) || '2023-06-01',\n 'Content-Type': 'application/json',\n }\n\n // Forward anthropic-beta header if present\n const betaHeader = req.headers['anthropic-beta']\n if (typeof betaHeader === 'string') {\n upstreamHeaders['anthropic-beta'] = betaHeader\n }\n\n try {\n const upstreamResponse = await fetch(upstreamUrl, {\n method: 'POST',\n headers: upstreamHeaders,\n body: JSON.stringify(upstreamBody),\n })\n\n // Handle upstream errors\n if (!upstreamResponse.ok) {\n const errorBody = await upstreamResponse.text()\n setCORSHeaders(res)\n res.writeHead(upstreamResponse.status, {\n 'Content-Type': upstreamResponse.headers.get('Content-Type') || 'application/json',\n })\n res.end(errorBody)\n return\n }\n\n // Streaming response\n if (request.stream && upstreamResponse.body) {\n const learningBuffer = anyCompressed\n ? createStreamLearningBuffer(pipeline.pipeline)\n : null\n\n await pipeAnthropicSSEResponse(\n upstreamResponse,\n res,\n (text) => learningBuffer?.append(text),\n () => learningBuffer?.flush(),\n )\n return\n }\n\n // Non-streaming response\n const responseBody = await upstreamResponse.text()\n setCORSHeaders(res)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(responseBody)\n\n // Trigger learning from response (fire-and-forget)\n if (anyCompressed) {\n try {\n const parsed = JSON.parse(responseBody)\n const textBlocks = parsed?.content?.filter(\n (b: AnthropicContentBlock) => b.type === 'text' && typeof b.text === 'string',\n )\n const content = textBlocks?.map((b: AnthropicContentBlock) => b.text).join('')\n if (typeof content === 'string' && content.length > 0) {\n pipeline.pipeline.triggerLearning(content)\n }\n } catch {\n // Ignore learning parse errors\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[ERROR] Upstream request failed: ${message}`)\n if (!res.headersSent) {\n sendAnthropicError(res, 502, 'api_error', `Failed to reach upstream: ${message}`)\n }\n }\n}\n","import * as http from 'node:http'\n\n/**\n * Pipe an Anthropic SSE response from the upstream to the client,\n * parsing content_block_delta events for the learning buffer.\n *\n * Anthropic SSE format:\n * event: content_block_delta\n * data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"Hello\"}}\n *\n * Writes each chunk immediately — zero buffering, zero added latency.\n */\nexport async function pipeAnthropicSSEResponse(\n upstreamResponse: Response,\n clientRes: http.ServerResponse,\n onContentDelta: (text: string) => void,\n onComplete: () => void,\n): Promise<void> {\n clientRes.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n })\n\n const reader = upstreamResponse.body!.getReader()\n const decoder = new TextDecoder()\n let lineBuf = ''\n let currentEvent = ''\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n const chunk = decoder.decode(value, { stream: true })\n\n // Write immediately to client\n clientRes.write(chunk)\n\n // Parse SSE lines for learning (best-effort, never blocks the pipe)\n lineBuf += chunk\n const lines = lineBuf.split('\\n')\n lineBuf = lines.pop() || ''\n\n for (const line of lines) {\n if (line.startsWith('event: ')) {\n currentEvent = line.slice(7).trim()\n } else if (line.startsWith('data: ') && currentEvent === 'content_block_delta') {\n try {\n const json = JSON.parse(line.slice(6))\n if (json?.delta?.type === 'text_delta' && typeof json.delta.text === 'string') {\n onContentDelta(json.delta.text)\n }\n } catch {\n // Malformed data — ignore for learning, chunk already piped\n }\n }\n }\n }\n } finally {\n clientRes.end()\n onComplete()\n }\n}\n","import * as http from 'node:http'\nimport { handleChatCompletions } from './completions.js'\nimport { handleAnthropicMessages } from './messages.js'\nimport type { RSCPipelineWrapper } from '../rsc/pipeline.js'\nimport type { ResolvedConfig } from '../types.js'\n\nexport interface Logger {\n log(message: string): void\n}\n\nfunction setCORSHeaders(res: http.ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-api-key, anthropic-version, anthropic-beta')\n res.setHeader('Access-Control-Max-Age', '86400')\n}\n\nfunction sendJSON(res: http.ServerResponse, status: number, body: unknown): void {\n setCORSHeaders(res)\n res.writeHead(status, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify(body))\n}\n\nfunction readBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n req.on('data', (chunk: Buffer) => chunks.push(chunk))\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')))\n req.on('error', reject)\n })\n}\n\nexport function createRequestHandler(\n pipeline: RSCPipelineWrapper,\n config: ResolvedConfig,\n logger: Logger,\n): (req: http.IncomingMessage, res: http.ServerResponse) => void {\n const startTime = Date.now()\n\n return async (req, res) => {\n try {\n const method = req.method?.toUpperCase() ?? ''\n const url = req.url ?? ''\n\n // CORS preflight\n if (method === 'OPTIONS') {\n setCORSHeaders(res)\n res.writeHead(204)\n res.end()\n return\n }\n\n // Health check (extended with session summary for `liminal status` / `liminal summary`)\n if (method === 'GET' && (url === '/health' || url === '/')) {\n const summary = pipeline.getSessionSummary()\n sendJSON(res, 200, {\n status: 'ok',\n version: config.rscApiKey ? 'connected' : 'no-api-key',\n rsc_connected: !pipeline.isCircuitOpen(),\n circuit_state: pipeline.getCircuitState(),\n session_id: summary.sessionId,\n uptime_ms: Date.now() - startTime,\n session: {\n tokens_processed: summary.tokensProcessed,\n tokens_saved: summary.tokensSaved,\n calls_total: summary.totalCalls,\n calls_compressed: summary.compressedCalls,\n calls_skipped: summary.skippedCalls,\n calls_failed: summary.failedCalls,\n patterns_learned: summary.patternsLearned,\n estimated_cost_saved_usd: summary.estimatedCostSaved,\n },\n })\n return\n }\n\n // Model listing — proxy to upstream LLM\n if (method === 'GET' && (url === '/v1/models' || url === '/models')) {\n const llmApiKey = req.headers.authorization?.slice(7)\n if (!llmApiKey) {\n sendJSON(res, 401, {\n error: { message: 'Authorization header with Bearer token is required', type: 'authentication_error' },\n })\n return\n }\n\n try {\n const upstreamRes = await fetch(`${config.upstreamBaseUrl}/v1/models`, {\n headers: { 'Authorization': `Bearer ${llmApiKey}` },\n })\n const body = await upstreamRes.text()\n setCORSHeaders(res)\n res.writeHead(upstreamRes.status, {\n 'Content-Type': upstreamRes.headers.get('Content-Type') || 'application/json',\n })\n res.end(body)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n sendJSON(res, 502, {\n error: { message: `Failed to reach upstream: ${message}`, type: 'server_error' },\n })\n }\n return\n }\n\n // Main route: chat completions\n if (method === 'POST' && (url === '/v1/chat/completions' || url === '/chat/completions')) {\n const body = await readBody(req)\n let parsed: unknown\n try {\n parsed = JSON.parse(body)\n } catch {\n sendJSON(res, 400, {\n error: { message: 'Invalid JSON body', type: 'invalid_request_error' },\n })\n return\n }\n\n await handleChatCompletions(req, res, parsed, pipeline, config, logger)\n return\n }\n\n // Anthropic Messages route\n if (method === 'POST' && (url === '/v1/messages' || url === '/messages')) {\n const body = await readBody(req)\n let parsed: unknown\n try {\n parsed = JSON.parse(body)\n } catch {\n sendJSON(res, 400, {\n type: 'error',\n error: { type: 'invalid_request_error', message: 'Invalid JSON body' },\n })\n return\n }\n\n await handleAnthropicMessages(req, res, parsed, pipeline, config, logger)\n return\n }\n\n // 404\n sendJSON(res, 404, {\n error: { message: `Not found: ${method} ${url}`, type: 'invalid_request_error' },\n })\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[ERROR] Proxy handler error: ${message}`)\n if (!res.headersSent) {\n sendJSON(res, 500, {\n error: { message: 'Internal proxy error', type: 'server_error' },\n })\n }\n }\n }\n}\n","import * as http from 'node:http'\n\nconst MAX_PORT_RETRIES = 5\n\nexport class ProxyServer {\n private server: http.Server | null = null\n private activePort: number | null = null\n private readonly requestedPort: number\n private readonly handler: (req: http.IncomingMessage, res: http.ServerResponse) => void\n\n constructor(\n port: number,\n handler: (req: http.IncomingMessage, res: http.ServerResponse) => void,\n ) {\n this.requestedPort = port\n this.handler = handler\n }\n\n async start(): Promise<number> {\n let lastError: Error | null = null\n\n for (let attempt = 0; attempt < MAX_PORT_RETRIES; attempt++) {\n const port = this.requestedPort + attempt\n try {\n await this.listen(port)\n this.activePort = port\n return port\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err))\n if ((err as NodeJS.ErrnoException).code !== 'EADDRINUSE') {\n throw lastError\n }\n }\n }\n\n throw lastError ?? new Error(`All ports ${this.requestedPort}-${this.requestedPort + MAX_PORT_RETRIES - 1} in use`)\n }\n\n private listen(port: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const server = http.createServer(this.handler)\n server.on('error', reject)\n server.listen(port, '127.0.0.1', () => {\n server.removeListener('error', reject)\n this.server = server\n resolve()\n })\n })\n }\n\n async stop(): Promise<void> {\n if (!this.server) return\n return new Promise((resolve) => {\n this.server!.close(() => {\n this.server = null\n this.activePort = null\n resolve()\n })\n })\n }\n\n isRunning(): boolean {\n return this.server !== null && this.server.listening\n }\n\n getPort(): number | null {\n return this.activePort\n }\n}\n","import { appendFileSync, statSync, renameSync, mkdirSync, existsSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { LOG_FILE, LOG_DIR } from '../config/paths.js'\nimport type { Logger } from '../proxy/handler.js'\n\nconst MAX_LOG_SIZE = 10 * 1024 * 1024 // 10 MB\nconst MAX_BACKUPS = 2\n\nexport class FileLogger implements Logger {\n private readonly logFile: string\n private readonly mirrorStdout: boolean\n\n constructor(options?: { logFile?: string; mirrorStdout?: boolean }) {\n this.logFile = options?.logFile ?? LOG_FILE\n this.mirrorStdout = options?.mirrorStdout ?? false\n\n // Ensure log directory exists\n const logDir = dirname(this.logFile)\n if (!existsSync(logDir)) {\n mkdirSync(logDir, { recursive: true })\n }\n }\n\n log(message: string): void {\n const timestamp = new Date().toISOString().slice(11, 23)\n const line = `[${timestamp}] ${message}\\n`\n\n try {\n appendFileSync(this.logFile, line)\n } catch {\n // If log write fails, try stdout as fallback\n process.stderr.write(`[LOG-WRITE-FAILED] ${line}`)\n }\n\n if (this.mirrorStdout) {\n process.stdout.write(line)\n }\n\n this.rotateIfNeeded()\n }\n\n private rotateIfNeeded(): void {\n try {\n const stats = statSync(this.logFile)\n if (stats.size <= MAX_LOG_SIZE) return\n\n // Rotate: liminal.log -> liminal.log.1 -> liminal.log.2 (drop oldest)\n for (let i = MAX_BACKUPS - 1; i >= 1; i--) {\n const from = `${this.logFile}.${i}`\n const to = `${this.logFile}.${i + 1}`\n if (existsSync(from)) renameSync(from, to)\n }\n renameSync(this.logFile, `${this.logFile}.1`)\n } catch {\n // Rotation failure is non-fatal\n }\n }\n\n getLogFile(): string {\n return this.logFile\n }\n}\n\n/**\n * A simple logger that only writes to stdout (for use during init or when log file isn't available).\n */\nexport class ConsoleLogger implements Logger {\n log(message: string): void {\n const timestamp = new Date().toISOString().slice(11, 23)\n process.stdout.write(`[${timestamp}] ${message}\\n`)\n }\n}\n","import { readFileSync, writeFileSync, unlinkSync, existsSync } from 'node:fs'\nimport { fork } from 'node:child_process'\nimport { fileURLToPath } from 'node:url'\nimport { PID_FILE } from '../config/paths.js'\nimport type { ProxyServer } from '../proxy/server.js'\nimport type { Logger } from '../proxy/handler.js'\n\n/**\n * Write the current process PID to ~/.liminal/liminal.pid.\n */\nexport function writePidFile(pid: number): void {\n writeFileSync(PID_FILE, String(pid), 'utf-8')\n}\n\n/**\n * Read PID from ~/.liminal/liminal.pid. Returns null if file doesn't exist.\n */\nexport function readPidFile(): number | null {\n if (!existsSync(PID_FILE)) return null\n try {\n const content = readFileSync(PID_FILE, 'utf-8').trim()\n const pid = parseInt(content, 10)\n return isNaN(pid) ? null : pid\n } catch {\n return null\n }\n}\n\n/**\n * Remove the PID file.\n */\nexport function removePidFile(): void {\n try {\n if (existsSync(PID_FILE)) unlinkSync(PID_FILE)\n } catch {\n // Ignore — file may already be gone\n }\n}\n\n/**\n * Check if a process with the given PID is alive.\n */\nexport function isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Check if the Liminal daemon is currently running.\n * Cleans up stale PID files automatically.\n */\nexport function isDaemonRunning(): { running: boolean; pid?: number } {\n const pid = readPidFile()\n if (pid === null) return { running: false }\n\n if (isProcessAlive(pid)) {\n return { running: true, pid }\n }\n\n // Stale PID file — process is dead\n removePidFile()\n return { running: false }\n}\n\n/**\n * Set up signal handlers for graceful shutdown.\n */\nexport function setupSignalHandlers(server: ProxyServer, logger: Logger): void {\n const shutdown = async (signal: string) => {\n logger.log(`[DAEMON] Received ${signal}, shutting down...`)\n try {\n await server.stop()\n } catch {\n // Best-effort server stop\n }\n removePidFile()\n logger.log('[DAEMON] Stopped.')\n process.exit(0)\n }\n\n process.on('SIGTERM', () => shutdown('SIGTERM'))\n process.on('SIGINT', () => shutdown('SIGINT'))\n\n process.on('uncaughtException', (err) => {\n logger.log(`[FATAL] Uncaught exception: ${err.message}`)\n removePidFile()\n process.exit(1)\n })\n\n process.on('unhandledRejection', (reason) => {\n const message = reason instanceof Error ? reason.message : String(reason)\n logger.log(`[FATAL] Unhandled rejection: ${message}`)\n removePidFile()\n process.exit(1)\n })\n}\n\n/**\n * Fork a detached child process to run the daemon in the background.\n * Returns the child PID.\n */\nexport function forkDaemon(binPath: string, extraArgs: string[] = []): number {\n const child = fork(binPath, ['start', '--_forked', ...extraArgs], {\n detached: true,\n stdio: 'ignore',\n })\n\n child.unref()\n return child.pid!\n}\n\n/**\n * Resolve the bin.ts/bin.js entry point path from import.meta.url.\n */\nexport function resolveBinPath(importMetaUrl: string): string {\n return fileURLToPath(importMetaUrl)\n}\n\n/**\n * Sleep for a given number of milliseconds.\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","import { loadConfig, applyOverrides, isConfigured } from '../config/loader.js'\nimport { RSCPipelineWrapper } from '../rsc/pipeline.js'\nimport { createRequestHandler } from '../proxy/handler.js'\nimport { ProxyServer } from '../proxy/server.js'\nimport { FileLogger } from '../daemon/logger.js'\nimport {\n isDaemonRunning,\n writePidFile,\n setupSignalHandlers,\n forkDaemon,\n resolveBinPath,\n} from '../daemon/lifecycle.js'\nimport type { ResolvedConfig, Tool } from '../types.js'\nimport { printBanner } from '../version.js'\n\nexport async function startCommand(flags: Map<string, string | true>): Promise<void> {\n const isDaemon = flags.has('d') || flags.has('daemon')\n const isForked = flags.has('_forked')\n\n // Check if already running (skip for forked processes — parent already checked)\n if (!isForked) {\n const state = isDaemonRunning()\n if (state.running) {\n console.error(`Liminal daemon is already running (PID ${state.pid}).`)\n console.error('Use \"liminal stop\" first, or \"liminal status\" to check.')\n process.exit(1)\n }\n }\n\n // Check config\n if (!isConfigured()) {\n console.error('Liminal is not configured. Run \"liminal init\" first.')\n process.exit(1)\n }\n\n // Load and apply config\n let config = loadConfig()\n const portOverride = flags.get('port')\n const upstreamOverride = flags.get('upstream')\n config = applyOverrides(config, {\n ...(typeof portOverride === 'string' ? { port: parseInt(portOverride, 10) } : {}),\n ...(typeof upstreamOverride === 'string' ? { upstreamBaseUrl: upstreamOverride } : {}),\n })\n\n // Background mode: fork and exit parent\n if (isDaemon && !isForked) {\n const extraArgs: string[] = []\n if (portOverride) extraArgs.push('--port', String(portOverride))\n if (upstreamOverride) extraArgs.push('--upstream', String(upstreamOverride))\n\n const binPath = resolveBinPath(import.meta.url)\n const childPid = forkDaemon(binPath, extraArgs)\n\n console.log(`Liminal daemon started in background (PID ${childPid})`)\n console.log(`Proxy: http://127.0.0.1:${config.port}/v1`)\n console.log('Logs: ~/.liminal/logs/liminal.log')\n process.exit(0)\n }\n\n // Foreground mode: run the server in this process\n const isForeground = !isDaemon || isForked\n const logger = new FileLogger({ mirrorStdout: isForeground && !isForked })\n\n // Build the resolved config for the proxy\n const resolvedConfig: ResolvedConfig = {\n rscApiKey: config.apiKey,\n rscBaseUrl: config.apiBaseUrl,\n proxyPort: config.port,\n compressionThreshold: config.compressionThreshold,\n compressRoles: config.compressRoles,\n learnFromResponses: config.learnFromResponses,\n latencyBudgetMs: config.latencyBudgetMs || undefined,\n upstreamBaseUrl: config.upstreamBaseUrl,\n anthropicUpstreamUrl: config.anthropicUpstreamUrl,\n enabled: config.enabled,\n tools: config.tools as Tool[],\n }\n\n // Create RSC pipeline\n const pipeline = new RSCPipelineWrapper({\n rscApiKey: config.apiKey,\n rscBaseUrl: config.apiBaseUrl,\n compressionThreshold: config.compressionThreshold,\n learnFromResponses: config.learnFromResponses,\n latencyBudgetMs: config.latencyBudgetMs || undefined,\n })\n\n // Wire up pipeline events for logging\n pipeline.events.on('compression', (event) => {\n if (event.tokensSaved > 0) {\n logger.log(`[LIMINAL] Compressed: ${event.tokensSaved} tokens saved (${event.ratio.toFixed(3)} ratio)`)\n }\n })\n pipeline.events.on('compression_skipped', (event) => {\n logger.log(`[LIMINAL] Skipped: ${event.reason}`)\n })\n pipeline.events.on('error', (event) => {\n logger.log(`[LIMINAL] Error: ${event.error.message}`)\n })\n pipeline.events.on('degradation', (event) => {\n logger.log(`[LIMINAL] Circuit ${event.circuitState}: ${event.reason}`)\n })\n\n // Create server\n const handler = createRequestHandler(pipeline, resolvedConfig, logger)\n const server = new ProxyServer(config.port, handler)\n\n // Setup graceful shutdown\n setupSignalHandlers(server, logger)\n\n // Start listening\n try {\n const actualPort = await server.start()\n writePidFile(process.pid)\n\n logger.log(`[DAEMON] Liminal proxy started on http://127.0.0.1:${actualPort}`)\n logger.log(`[DAEMON] Upstream (OpenAI): ${config.upstreamBaseUrl}`)\n logger.log(`[DAEMON] Upstream (Anthropic): ${config.anthropicUpstreamUrl}`)\n logger.log(`[DAEMON] Liminal API: ${config.apiBaseUrl}`)\n logger.log(`[DAEMON] PID: ${process.pid}`)\n\n if (isForeground && !isForked) {\n printBanner()\n console.log(` Liminal proxy running on http://127.0.0.1:${actualPort}/v1`)\n console.log(` Upstream: ${config.upstreamBaseUrl}`)\n console.log()\n console.log(' Point your AI tool\\'s base URL here. Press Ctrl+C to stop.')\n console.log()\n }\n\n // Check RSC API health on startup\n const healthy = await pipeline.healthCheck()\n if (healthy) {\n logger.log('[DAEMON] Liminal API health check: OK')\n } else {\n logger.log('[DAEMON] Liminal API health check: FAILED (will retry on first request)')\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n console.error(`Failed to start proxy: ${message}`)\n process.exit(1)\n }\n}\n","import {\n isDaemonRunning,\n readPidFile,\n removePidFile,\n isProcessAlive,\n sleep,\n} from '../daemon/lifecycle.js'\n\nexport async function stopCommand(): Promise<void> {\n const state = isDaemonRunning()\n\n if (!state.running || !state.pid) {\n console.log('Liminal daemon is not running.')\n return\n }\n\n const pid = state.pid\n console.log(`Stopping Liminal daemon (PID ${pid})...`)\n\n // Send SIGTERM for graceful shutdown\n try {\n process.kill(pid, 'SIGTERM')\n } catch {\n // Process may have already exited\n removePidFile()\n console.log('Liminal daemon stopped.')\n return\n }\n\n // Poll for up to 5 seconds\n for (let i = 0; i < 25; i++) {\n await sleep(200)\n if (!isProcessAlive(pid)) {\n removePidFile()\n console.log(`Liminal daemon stopped (PID ${pid}).`)\n return\n }\n }\n\n // Force kill after timeout\n try {\n process.kill(pid, 'SIGKILL')\n } catch {\n // Already dead\n }\n\n removePidFile()\n console.log(`Liminal daemon force-killed (PID ${pid}).`)\n}\n","import { isDaemonRunning } from '../daemon/lifecycle.js'\nimport { loadConfig, isConfigured } from '../config/loader.js'\n\nexport async function statusCommand(): Promise<void> {\n if (!isConfigured()) {\n console.log('Liminal: not configured')\n console.log('Run \"liminal init\" to set up.')\n return\n }\n\n const state = isDaemonRunning()\n\n if (!state.running || !state.pid) {\n console.log('Liminal Daemon: stopped')\n console.log('Run \"liminal start\" to start the proxy.')\n return\n }\n\n const config = loadConfig()\n const port = config.port\n\n // Try to reach the daemon's /health endpoint\n try {\n const res = await fetch(`http://127.0.0.1:${port}/health`, {\n signal: AbortSignal.timeout(3000),\n })\n const data = await res.json() as {\n status: string\n circuit_state: string\n session_id: string\n uptime_ms: number\n session?: {\n tokens_processed: number\n tokens_saved: number\n calls_total: number\n calls_compressed: number\n calls_skipped: number\n calls_failed: number\n }\n }\n\n const uptime = formatUptime(data.uptime_ms)\n\n console.log(`Liminal Daemon: running (PID ${state.pid}, port ${port})`)\n console.log(`Circuit: ${data.circuit_state}`)\n console.log(`Session: ${data.session_id}`)\n console.log(`Uptime: ${uptime}`)\n\n if (data.session) {\n const s = data.session\n const savingsPercent = s.tokens_processed > 0\n ? ((s.tokens_saved / s.tokens_processed) * 100).toFixed(1)\n : '0.0'\n console.log()\n console.log(`Tokens: ${s.tokens_processed.toLocaleString()} processed, ${s.tokens_saved.toLocaleString()} saved (${savingsPercent}%)`)\n console.log(`Calls: ${s.calls_total} total (${s.calls_compressed} compressed, ${s.calls_skipped} skipped, ${s.calls_failed} failed)`)\n }\n } catch {\n // Can't reach the daemon, but PID is alive — might still be starting\n console.log(`Liminal Daemon: running (PID ${state.pid}, port ${port})`)\n console.log('Circuit: unknown (could not reach /health)')\n }\n}\n\nfunction formatUptime(ms: number): string {\n const seconds = Math.floor(ms / 1000)\n const minutes = Math.floor(seconds / 60)\n const hours = Math.floor(minutes / 60)\n const days = Math.floor(hours / 24)\n\n if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`\n if (hours > 0) return `${hours}h ${minutes % 60}m`\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`\n return `${seconds}s`\n}\n","import { isDaemonRunning } from '../daemon/lifecycle.js'\nimport { loadConfig, isConfigured } from '../config/loader.js'\n\nexport async function summaryCommand(): Promise<void> {\n if (!isConfigured()) {\n console.log('Liminal is not configured. Run \"liminal init\" first.')\n return\n }\n\n const state = isDaemonRunning()\n\n if (!state.running || !state.pid) {\n console.log('Liminal daemon is not running. Start it with \"liminal start\".')\n return\n }\n\n const config = loadConfig()\n const port = config.port\n\n try {\n const res = await fetch(`http://127.0.0.1:${port}/health`, {\n signal: AbortSignal.timeout(3000),\n })\n const data = await res.json() as {\n circuit_state: string\n session_id: string\n uptime_ms: number\n session?: {\n tokens_processed: number\n tokens_saved: number\n calls_total: number\n calls_compressed: number\n calls_skipped: number\n calls_failed: number\n patterns_learned: number\n estimated_cost_saved_usd: number\n }\n }\n\n const uptime = formatUptime(data.uptime_ms)\n\n console.log()\n console.log(` Session: ${data.session_id}`)\n console.log(` Uptime: ${uptime}`)\n console.log()\n\n if (data.session) {\n const s = data.session\n const savingsPercent = s.tokens_processed > 0\n ? ((s.tokens_saved / s.tokens_processed) * 100).toFixed(1)\n : '0.0'\n const compressionRate = s.calls_total > 0\n ? ((s.calls_compressed / s.calls_total) * 100).toFixed(0)\n : '0'\n\n console.log(' Compression:')\n console.log(` Tokens processed: ${s.tokens_processed.toLocaleString()}`)\n console.log(` Tokens saved: ${s.tokens_saved.toLocaleString()} (${savingsPercent}%)`)\n console.log(` Compression rate: ${compressionRate}% of calls compressed`)\n console.log(` Patterns learned: ${s.patterns_learned.toLocaleString()}`)\n console.log()\n console.log(' Calls:')\n console.log(` Total: ${s.calls_total}`)\n console.log(` Compressed: ${s.calls_compressed}`)\n console.log(` Skipped: ${s.calls_skipped}`)\n console.log(` Failed: ${s.calls_failed}`)\n console.log()\n console.log(' Cost Savings:')\n console.log(` Estimated: $${s.estimated_cost_saved_usd.toFixed(4)} USD`)\n console.log()\n } else {\n console.log(' No session data available yet.')\n console.log()\n }\n\n console.log(` Circuit: ${data.circuit_state}`)\n console.log(` API: ${config.apiBaseUrl}`)\n console.log(` Upstream: ${config.upstreamBaseUrl}`)\n console.log()\n } catch {\n console.error('Could not reach the Liminal daemon. Is it running?')\n console.error(`Tried http://127.0.0.1:${port}/health`)\n process.exit(1)\n }\n}\n\nfunction formatUptime(ms: number): string {\n const seconds = Math.floor(ms / 1000)\n const minutes = Math.floor(seconds / 60)\n const hours = Math.floor(minutes / 60)\n const days = Math.floor(hours / 24)\n\n if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`\n if (hours > 0) return `${hours}h ${minutes % 60}m`\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`\n return `${seconds}s`\n}\n","import { loadConfig, saveConfig, isConfigured, maskApiKey } from '../config/loader.js'\nimport { CONFIGURABLE_KEYS } from '../config/schema.js'\nimport { CONFIG_FILE } from '../config/paths.js'\n\nexport async function configCommand(flags: Map<string, string | true>): Promise<void> {\n const getKey = flags.get('get')\n const setKv = flags.get('set')\n\n // rsc config --get <key>\n if (typeof getKey === 'string') {\n if (!isConfigured()) {\n console.error('Liminal is not configured. Run \"liminal init\" first.')\n process.exit(1)\n }\n const config = loadConfig()\n const value = (config as unknown as Record<string, unknown>)[getKey]\n if (value === undefined) {\n console.error(`Unknown config key: ${getKey}`)\n process.exit(1)\n }\n console.log(getKey === 'apiKey' ? maskApiKey(String(value)) : String(value))\n return\n }\n\n // rsc config --set <key>=<value>\n if (typeof setKv === 'string') {\n const eqIdx = setKv.indexOf('=')\n if (eqIdx === -1) {\n console.error('Usage: liminal config --set key=value')\n process.exit(1)\n }\n const key = setKv.slice(0, eqIdx)\n const rawValue = setKv.slice(eqIdx + 1)\n\n if (!CONFIGURABLE_KEYS.has(key) && key !== 'apiKey') {\n console.error(`Unknown or non-configurable key: ${key}`)\n console.error(`Configurable keys: ${[...CONFIGURABLE_KEYS].join(', ')}`)\n process.exit(1)\n }\n\n // Parse value based on key type\n let parsedValue: unknown = rawValue\n if (key === 'port' || key === 'compressionThreshold' || key === 'latencyBudgetMs') {\n parsedValue = parseInt(rawValue, 10)\n if (isNaN(parsedValue as number)) {\n console.error(`Invalid number for ${key}: ${rawValue}`)\n process.exit(1)\n }\n } else if (key === 'learnFromResponses' || key === 'enabled') {\n parsedValue = rawValue === 'true' || rawValue === '1'\n } else if (key === 'compressRoles') {\n parsedValue = rawValue.split(',').map((s) => s.trim())\n }\n\n saveConfig({ [key]: parsedValue })\n console.log(`Set ${key} = ${key === 'apiKey' ? maskApiKey(rawValue) : rawValue}`)\n return\n }\n\n // rsc config (no flags) — show all\n if (!isConfigured()) {\n console.log(`Liminal is not configured. Run \"liminal init\" first.`)\n console.log(`Config file: ${CONFIG_FILE}`)\n return\n }\n\n const config = loadConfig()\n console.log()\n console.log(` Config: ${CONFIG_FILE}`)\n console.log()\n console.log(` apiKey: ${maskApiKey(config.apiKey)}`)\n console.log(` apiBaseUrl: ${config.apiBaseUrl}`)\n console.log(` upstreamBaseUrl: ${config.upstreamBaseUrl}`)\n console.log(` anthropicUpstreamUrl: ${config.anthropicUpstreamUrl}`)\n console.log(` tools: ${config.tools.length > 0 ? config.tools.join(', ') : '(none)'}`)\n console.log(` port: ${config.port}`)\n console.log(` compressionThreshold: ${config.compressionThreshold}`)\n console.log(` compressRoles: ${config.compressRoles.join(', ')}`)\n console.log(` learnFromResponses: ${config.learnFromResponses}`)\n console.log(` latencyBudgetMs: ${config.latencyBudgetMs || 'auto'}`)\n console.log(` enabled: ${config.enabled}`)\n console.log()\n}\n","import { readFileSync, existsSync, statSync, createReadStream } from 'node:fs'\nimport { watchFile, unwatchFile } from 'node:fs'\nimport { LOG_FILE } from '../config/paths.js'\n\nexport async function logsCommand(flags: Map<string, string | true>): Promise<void> {\n const follow = flags.has('follow') || flags.has('f')\n const linesFlag = flags.get('lines') ?? flags.get('n')\n const lines = typeof linesFlag === 'string' ? parseInt(linesFlag, 10) : 50\n\n if (!existsSync(LOG_FILE)) {\n console.log('No log file found. Start the daemon with \"liminal start\" to generate logs.')\n return\n }\n\n // Read and display last N lines\n const content = readFileSync(LOG_FILE, 'utf-8')\n const allLines = content.split('\\n')\n const tail = allLines.slice(-lines - 1) // -1 to account for trailing newline\n process.stdout.write(tail.join('\\n'))\n\n if (!follow) return\n\n // Follow mode: watch for changes and stream new content\n let lastSize = statSync(LOG_FILE).size\n\n watchFile(LOG_FILE, { interval: 500 }, (curr) => {\n if (curr.size > lastSize) {\n const stream = createReadStream(LOG_FILE, { start: lastSize, encoding: 'utf-8' })\n stream.on('data', (chunk) => process.stdout.write(chunk as string))\n stream.on('end', () => { lastSize = curr.size })\n } else if (curr.size < lastSize) {\n // File was rotated — read from beginning\n lastSize = 0\n }\n })\n\n // Keep the process alive and handle Ctrl+C\n process.on('SIGINT', () => {\n unwatchFile(LOG_FILE)\n process.exit(0)\n })\n\n // Block forever\n await new Promise(() => {})\n}\n","import { VERSION } from './version.js'\nimport { initCommand } from './commands/init.js'\nimport { startCommand } from './commands/start.js'\nimport { stopCommand } from './commands/stop.js'\nimport { statusCommand } from './commands/status.js'\nimport { summaryCommand } from './commands/summary.js'\nimport { configCommand } from './commands/config.js'\nimport { logsCommand } from './commands/logs.js'\n\nconst USAGE = `\n liminal v${VERSION} — Transparent LLM context compression proxy\n\n Usage:\n liminal init Set up Liminal (API key, config)\n liminal start [-d] [--port PORT] Start the compression proxy\n liminal stop Stop the running proxy\n liminal status Show proxy health and stats\n liminal summary Detailed session metrics\n liminal config [--set k=v] [--get k] View or edit configuration\n liminal logs [--follow] [--lines N] View proxy logs\n\n Options:\n -h, --help Show this help message\n -v, --version Show version number\n\n Getting started:\n 1. liminal init # Enter your API key + select tools\n 2. liminal start # Start the proxy\n 3. Connect your AI tools:\n Claude Code: export ANTHROPIC_BASE_URL=http://localhost:3141\n Codex: export OPENAI_BASE_URL=http://localhost:3141/v1\n Cursor: Settings > Models > Base URL > http://localhost:3141/v1\n`\n\nfunction parseArgs(argv: string[]): { command: string; flags: Map<string, string | true> } {\n const command = argv[2] ?? ''\n const flags = new Map<string, string | true>()\n\n for (let i = 3; i < argv.length; i++) {\n const arg = argv[i]\n if (arg.startsWith('--')) {\n const key = arg.slice(2)\n // Check if next arg is a value (not another flag)\n if (i + 1 < argv.length && !argv[i + 1].startsWith('-')) {\n flags.set(key, argv[i + 1])\n i++\n } else {\n flags.set(key, true)\n }\n } else if (arg.startsWith('-') && arg.length === 2) {\n const key = arg.slice(1)\n if (i + 1 < argv.length && !argv[i + 1].startsWith('-')) {\n flags.set(key, argv[i + 1])\n i++\n } else {\n flags.set(key, true)\n }\n }\n }\n\n return { command, flags }\n}\n\nasync function main(): Promise<void> {\n const { command, flags } = parseArgs(process.argv)\n\n // Global flags — handle --help and --version as both commands and flags\n if (flags.has('h') || flags.has('help') || command === 'help' || command === '--help' || command === '-h') {\n console.log(USAGE)\n process.exit(0)\n }\n\n if (flags.has('v') || flags.has('version') || command === 'version' || command === '--version' || command === '-v') {\n console.log(VERSION)\n process.exit(0)\n }\n\n try {\n switch (command) {\n case 'init':\n await initCommand()\n break\n\n case 'start':\n await startCommand(flags)\n break\n\n case 'stop':\n await stopCommand()\n break\n\n case 'status':\n await statusCommand()\n break\n\n case 'summary':\n await summaryCommand()\n break\n\n case 'config':\n await configCommand(flags)\n break\n\n case 'logs':\n await logsCommand(flags)\n break\n\n case '':\n console.log(USAGE)\n process.exit(0)\n break\n\n default:\n console.error(`Unknown command: ${command}`)\n console.log(USAGE)\n process.exit(1)\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n console.error(`Error: ${message}`)\n process.exit(1)\n }\n}\n\nmain()\n"],"mappings":"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","names":["existsSync","readFileSync","join","homedir","stdin","stdout","homedir","join","existsSync","readFileSync","RSCTransport","CircuitBreaker","RSCCircuitOpenError","RSCCircuitOpenError","RSCCircuitOpenError","setCORSHeaders","RSCCircuitOpenError","setCORSHeaders","sendJSON","appendFileSync","mkdirSync","existsSync","dirname","dirname","existsSync","mkdirSync","appendFileSync","readFileSync","writeFileSync","existsSync","writeFileSync","existsSync","readFileSync","formatUptime","config","readFileSync","existsSync","statSync","existsSync","readFileSync","statSync"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cognisos/liminal",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "description": "Liminal — transparent LLM context compression proxy",
5
5
  "type": "module",
6
6
  "bin": {