clawmux 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,15 +14,22 @@ Smart model routing + context compression proxy for OpenClaw.
14
14
 
15
15
  ## Installation
16
16
 
17
- Fetch the installation guide and follow it:
17
+ Copy and paste this into your OpenClaw agent:
18
18
 
19
19
  ```bash
20
+ Install and configure oh-my-opencode by following the instructions here:
20
21
  curl -s https://raw.githubusercontent.com/HyeokjaeLee/ClawMux/refs/heads/main/docs/guide/installation.md
21
22
  ```
22
23
 
23
24
  ## Configuration
24
25
 
25
- Copy `clawmux.example.json` to `clawmux.json` and adjust as needed:
26
+ ClawMux stores its config at `~/.openclaw/clawmux.json` (next to `openclaw.json`). `clawmux init` creates it automatically. You can also copy `clawmux.example.json` as a starting point:
27
+
28
+ ```bash
29
+ cp clawmux.example.json ~/.openclaw/clawmux.json
30
+ ```
31
+
32
+ Adjust as needed:
26
33
 
27
34
  ```jsonc
28
35
  {
@@ -46,7 +53,7 @@ Copy `clawmux.example.json` to `clawmux.json` and adjust as needed:
46
53
  }
47
54
  ```
48
55
 
49
- Config is watched for changes. Edit `clawmux.json` while the proxy is running and it reloads automatically.
56
+ Config is watched for changes. Edit `~/.openclaw/clawmux.json` while the proxy is running and it reloads automatically. Override the path with `CLAWMUX_CONFIG=/path/to/clawmux.json`.
50
57
 
51
58
  ### Cross-Provider Routing
52
59
 
@@ -99,7 +106,7 @@ OpenClaw → ClawMux Proxy (localhost:3456) → Upstream Provider(s)
99
106
 
100
107
  ClawMux resolves each model's context window using this priority chain:
101
108
 
102
- 1. **clawmux.json** `routing.contextWindows` — explicit per-model override
109
+ 1. **~/.openclaw/clawmux.json** `routing.contextWindows` — explicit per-model override
103
110
  2. **openclaw.json** `models.providers[provider].models[].contextWindow` — user config
104
111
  3. **OpenClaw built-in catalog** — pi-ai model database (812+ models)
105
112
  4. **Default: 200,000 tokens**
package/dist/cli.cjs CHANGED
@@ -80,7 +80,7 @@ async function writeWebResponse(res, response) {
80
80
 
81
81
  // src/cli.ts
82
82
  var import_promises6 = require("node:fs/promises");
83
- var import_node_path6 = require("node:path");
83
+ var import_node_path5 = require("node:path");
84
84
  var import_node_child_process = require("node:child_process");
85
85
  var import_node_os = require("node:os");
86
86
 
@@ -424,12 +424,17 @@ function validateConfig(raw) {
424
424
  }
425
425
 
426
426
  // src/config/loader.ts
427
- function findConfigPath() {
427
+ function getHomeDir() {
428
+ return process.env.HOME ?? "/root";
429
+ }
430
+ function getClawmuxConfigPath() {
428
431
  const envPath = process.env.CLAWMUX_CONFIG;
429
- if (envPath) {
432
+ if (envPath)
430
433
  return import_node_path.resolve(envPath);
431
- }
432
- return import_node_path.resolve(process.cwd(), "clawmux.json");
434
+ return import_node_path.join(getHomeDir(), ".openclaw", "clawmux.json");
435
+ }
436
+ function findConfigPath() {
437
+ return getClawmuxConfigPath();
433
438
  }
434
439
  async function loadConfig(configPath) {
435
440
  const filePath = configPath ?? findConfigPath();
@@ -553,7 +558,7 @@ function resolveEnvVar(value) {
553
558
  }
554
559
  return value;
555
560
  }
556
- function getHomeDir() {
561
+ function getHomeDir2() {
557
562
  return process.env.HOME ?? "/root";
558
563
  }
559
564
  function getConfigPath(override) {
@@ -561,7 +566,7 @@ function getConfigPath(override) {
561
566
  return override;
562
567
  if (process.env.OPENCLAW_CONFIG_PATH)
563
568
  return process.env.OPENCLAW_CONFIG_PATH;
564
- return import_node_path2.join(getHomeDir(), ".openclaw", "openclaw.json");
569
+ return import_node_path2.join(getHomeDir2(), ".openclaw", "openclaw.json");
565
570
  }
566
571
  async function readOpenClawConfig(configPath) {
567
572
  const path = getConfigPath(configPath);
@@ -584,7 +589,7 @@ async function readOpenClawConfig(configPath) {
584
589
  }
585
590
  function getAuthProfilesPath(agentId) {
586
591
  const id = agentId ?? "main";
587
- return import_node_path2.join(getHomeDir(), ".openclaw", "agents", id, "agent", "auth-profiles.json");
592
+ return import_node_path2.join(getHomeDir2(), ".openclaw", "agents", id, "agent", "auth-profiles.json");
588
593
  }
589
594
  function parseAuthProfilesFile(text) {
590
595
  try {
@@ -618,7 +623,7 @@ function parseAuthProfilesFile(text) {
618
623
  }
619
624
  }
620
625
  async function readAuthProfiles(_agentId, _profilesPath, agentsDirOverride) {
621
- const agentsDir = agentsDirOverride ?? import_node_path2.join(getHomeDir(), ".openclaw", "agents");
626
+ const agentsDir = agentsDirOverride ?? import_node_path2.join(getHomeDir2(), ".openclaw", "agents");
622
627
  let agentDirs;
623
628
  try {
624
629
  agentDirs = (await import_promises4.readdir(agentsDir, { withFileTypes: true })).filter((d) => d.isDirectory()).map((d) => d.name).sort();
@@ -3833,9 +3838,8 @@ function setupPipelineRoutes(config, openclawConfig, authProfiles, compressionMi
3833
3838
  }
3834
3839
 
3835
3840
  // src/index.ts
3836
- var import_node_path4 = require("node:path");
3837
3841
  async function bootstrap(portOverride) {
3838
- const configPath = process.env.CLAWMUX_CONFIG ? import_node_path4.resolve(process.env.CLAWMUX_CONFIG) : import_node_path4.resolve(process.cwd(), "clawmux.json");
3842
+ const configPath = getClawmuxConfigPath();
3839
3843
  const result = await loadConfig(configPath);
3840
3844
  if (!result.valid) {
3841
3845
  console.error("[clawmux] Config errors:");
@@ -3870,8 +3874,8 @@ if (typeof Bun !== "undefined" && Bun.main === "/home/runner/work/ClawMux/ClawMu
3870
3874
 
3871
3875
  // src/utils/logger.ts
3872
3876
  var import_node_fs2 = require("node:fs");
3873
- var import_node_path5 = require("node:path");
3874
- var LOG_DIR = import_node_path5.join(process.env.HOME ?? "/root", ".openclaw", "clawmux");
3877
+ var import_node_path4 = require("node:path");
3878
+ var LOG_DIR = import_node_path4.join(process.env.HOME ?? "/root", ".openclaw", "clawmux");
3875
3879
  var MAX_DAYS = 7;
3876
3880
  var fileStream = null;
3877
3881
  var currentDate = "";
@@ -3880,7 +3884,7 @@ function todayString() {
3880
3884
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
3881
3885
  }
3882
3886
  function logPath(date) {
3883
- return import_node_path5.join(LOG_DIR, `${date}.log`);
3887
+ return import_node_path4.join(LOG_DIR, `${date}.log`);
3884
3888
  }
3885
3889
  function rotateIfNeeded() {
3886
3890
  const today = todayString();
@@ -3898,7 +3902,7 @@ function purgeOldLogs() {
3898
3902
  const files = import_node_fs2.readdirSync(LOG_DIR).filter((f) => f.endsWith(".log")).sort();
3899
3903
  while (files.length > MAX_DAYS) {
3900
3904
  const oldest = files.shift();
3901
- import_node_fs2.unlinkSync(import_node_path5.join(LOG_DIR, oldest));
3905
+ import_node_fs2.unlinkSync(import_node_path4.join(LOG_DIR, oldest));
3902
3906
  }
3903
3907
  } catch (_) {}
3904
3908
  }
@@ -3938,7 +3942,7 @@ function getLogDir() {
3938
3942
  }
3939
3943
 
3940
3944
  // src/cli.ts
3941
- var VERSION2 = process.env.npm_package_version ?? "0.3.2";
3945
+ var VERSION2 = process.env.npm_package_version ?? "0.3.3";
3942
3946
  var SERVICE_NAME = "clawmux";
3943
3947
  var HELP = `Usage: clawmux <command>
3944
3948
 
@@ -3998,13 +4002,13 @@ function resolveClawmuxBin() {
3998
4002
  return detectPackageManager() === "bunx" ? "bunx clawmux" : "npx clawmux";
3999
4003
  }
4000
4004
  }
4001
- function getHomeDir2() {
4005
+ function getHomeDir3() {
4002
4006
  return process.env.HOME ?? "/root";
4003
4007
  }
4004
- var SYSTEMD_DIR = import_node_path6.join(getHomeDir2(), ".config", "systemd", "user");
4005
- var SYSTEMD_PATH = import_node_path6.join(SYSTEMD_DIR, `${SERVICE_NAME}.service`);
4006
- var LAUNCHD_DIR = import_node_path6.join(getHomeDir2(), "Library", "LaunchAgents");
4007
- var LAUNCHD_PATH = import_node_path6.join(LAUNCHD_DIR, `com.${SERVICE_NAME}.plist`);
4008
+ var SYSTEMD_DIR = import_node_path5.join(getHomeDir3(), ".config", "systemd", "user");
4009
+ var SYSTEMD_PATH = import_node_path5.join(SYSTEMD_DIR, `${SERVICE_NAME}.service`);
4010
+ var LAUNCHD_DIR = import_node_path5.join(getHomeDir3(), "Library", "LaunchAgents");
4011
+ var LAUNCHD_PATH = import_node_path5.join(LAUNCHD_DIR, `com.${SERVICE_NAME}.plist`);
4008
4012
  function buildSystemdUnit(bin, port, workDir) {
4009
4013
  return `[Unit]
4010
4014
  Description=ClawMux - Smart model routing proxy
@@ -4023,7 +4027,7 @@ WantedBy=default.target
4023
4027
  `;
4024
4028
  }
4025
4029
  function buildLaunchdPlist(bin, port, workDir) {
4026
- const logDir = import_node_path6.join(getHomeDir2(), ".openclaw", "clawmux");
4030
+ const logDir = import_node_path5.join(getHomeDir3(), ".openclaw", "clawmux");
4027
4031
  return `<?xml version="1.0" encoding="UTF-8"?>
4028
4032
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
4029
4033
  <plist version="1.0">
@@ -4078,7 +4082,7 @@ async function installService(port, workDir) {
4078
4082
  }
4079
4083
  } else if (os === "darwin") {
4080
4084
  await import_promises6.mkdir(LAUNCHD_DIR, { recursive: true });
4081
- const logDir = import_node_path6.join(getHomeDir2(), ".openclaw", "clawmux");
4085
+ const logDir = import_node_path5.join(getHomeDir3(), ".openclaw", "clawmux");
4082
4086
  await import_promises6.mkdir(logDir, { recursive: true });
4083
4087
  await import_promises6.writeFile(LAUNCHD_PATH, buildLaunchdPlist(bin, port, workDir));
4084
4088
  try {
@@ -4227,8 +4231,8 @@ async function update() {
4227
4231
  async function init() {
4228
4232
  const args = process.argv.slice(2);
4229
4233
  const noService = args.includes("--no-service");
4230
- const homeDir = getHomeDir2();
4231
- const openclawConfigPath = process.env.OPENCLAW_CONFIG_PATH ?? import_node_path6.join(homeDir, ".openclaw", "openclaw.json");
4234
+ const homeDir = getHomeDir3();
4235
+ const openclawConfigPath = process.env.OPENCLAW_CONFIG_PATH ?? import_node_path5.join(homeDir, ".openclaw", "openclaw.json");
4232
4236
  if (!await fileExistsLocal(openclawConfigPath)) {
4233
4237
  console.error(`[error] OpenClaw config not found at ${openclawConfigPath}`);
4234
4238
  console.error("Set OPENCLAW_CONFIG_PATH or ensure ~/.openclaw/openclaw.json exists");
@@ -4238,8 +4242,9 @@ async function init() {
4238
4242
  const backupPath = `${openclawConfigPath}.bak.${Date.now()}`;
4239
4243
  await import_promises6.copyFile(openclawConfigPath, backupPath);
4240
4244
  console.log(`[info] Backup created: ${backupPath}`);
4241
- const clawmuxJsonPath = import_node_path6.join(process.cwd(), "clawmux.json");
4242
- const examplePath = import_node_path6.join(process.cwd(), "clawmux.example.json");
4245
+ const clawmuxJsonPath = getClawmuxConfigPath();
4246
+ const examplePath = import_node_path5.join(process.cwd(), "clawmux.example.json");
4247
+ console.log(`[info] Using ClawMux config: ${clawmuxJsonPath}`);
4243
4248
  if (!await fileExistsLocal(clawmuxJsonPath)) {
4244
4249
  if (await fileExistsLocal(examplePath)) {
4245
4250
  await import_promises6.copyFile(examplePath, clawmuxJsonPath);
@@ -4307,7 +4312,7 @@ async function init() {
4307
4312
  [info] ClawMux setup complete!`);
4308
4313
  console.log(`
4309
4314
  Next steps:`);
4310
- console.log(" 1. Edit clawmux.json to configure your models");
4315
+ console.log(` 1. Edit ${clawmuxJsonPath} to configure your models`);
4311
4316
  if (noService) {
4312
4317
  console.log(" 2. Run: clawmux start");
4313
4318
  } else {
@@ -4331,8 +4336,8 @@ async function start() {
4331
4336
  }
4332
4337
  async function uninstall() {
4333
4338
  await removeService();
4334
- const homeDir = getHomeDir2();
4335
- const openclawConfigPath = process.env.OPENCLAW_CONFIG_PATH ?? import_node_path6.join(homeDir, ".openclaw", "openclaw.json");
4339
+ const homeDir = getHomeDir3();
4340
+ const openclawConfigPath = process.env.OPENCLAW_CONFIG_PATH ?? import_node_path5.join(homeDir, ".openclaw", "openclaw.json");
4336
4341
  if (await fileExistsLocal(openclawConfigPath)) {
4337
4342
  const backupPath = `${openclawConfigPath}.bak.${Date.now()}`;
4338
4343
  await import_promises6.copyFile(openclawConfigPath, backupPath);
package/dist/index.cjs CHANGED
@@ -447,12 +447,17 @@ function validateConfig(raw) {
447
447
  }
448
448
 
449
449
  // src/config/loader.ts
450
- function findConfigPath() {
450
+ function getHomeDir() {
451
+ return process.env.HOME ?? "/root";
452
+ }
453
+ function getClawmuxConfigPath() {
451
454
  const envPath = process.env.CLAWMUX_CONFIG;
452
- if (envPath) {
455
+ if (envPath)
453
456
  return import_node_path.resolve(envPath);
454
- }
455
- return import_node_path.resolve(process.cwd(), "clawmux.json");
457
+ return import_node_path.join(getHomeDir(), ".openclaw", "clawmux.json");
458
+ }
459
+ function findConfigPath() {
460
+ return getClawmuxConfigPath();
456
461
  }
457
462
  async function loadConfig(configPath) {
458
463
  const filePath = configPath ?? findConfigPath();
@@ -576,7 +581,7 @@ function resolveEnvVar(value) {
576
581
  }
577
582
  return value;
578
583
  }
579
- function getHomeDir() {
584
+ function getHomeDir2() {
580
585
  return process.env.HOME ?? "/root";
581
586
  }
582
587
  function getConfigPath(override) {
@@ -584,7 +589,7 @@ function getConfigPath(override) {
584
589
  return override;
585
590
  if (process.env.OPENCLAW_CONFIG_PATH)
586
591
  return process.env.OPENCLAW_CONFIG_PATH;
587
- return import_node_path2.join(getHomeDir(), ".openclaw", "openclaw.json");
592
+ return import_node_path2.join(getHomeDir2(), ".openclaw", "openclaw.json");
588
593
  }
589
594
  async function readOpenClawConfig(configPath) {
590
595
  const path = getConfigPath(configPath);
@@ -607,7 +612,7 @@ async function readOpenClawConfig(configPath) {
607
612
  }
608
613
  function getAuthProfilesPath(agentId) {
609
614
  const id = agentId ?? "main";
610
- return import_node_path2.join(getHomeDir(), ".openclaw", "agents", id, "agent", "auth-profiles.json");
615
+ return import_node_path2.join(getHomeDir2(), ".openclaw", "agents", id, "agent", "auth-profiles.json");
611
616
  }
612
617
  function parseAuthProfilesFile(text) {
613
618
  try {
@@ -641,7 +646,7 @@ function parseAuthProfilesFile(text) {
641
646
  }
642
647
  }
643
648
  async function readAuthProfiles(_agentId, _profilesPath, agentsDirOverride) {
644
- const agentsDir = agentsDirOverride ?? import_node_path2.join(getHomeDir(), ".openclaw", "agents");
649
+ const agentsDir = agentsDirOverride ?? import_node_path2.join(getHomeDir2(), ".openclaw", "agents");
645
650
  let agentDirs;
646
651
  try {
647
652
  agentDirs = (await import_promises4.readdir(agentsDir, { withFileTypes: true })).filter((d) => d.isDirectory()).map((d) => d.name).sort();
@@ -3856,9 +3861,8 @@ function setupPipelineRoutes(config, openclawConfig, authProfiles, compressionMi
3856
3861
  }
3857
3862
 
3858
3863
  // src/index.ts
3859
- var import_node_path4 = require("node:path");
3860
3864
  async function bootstrap(portOverride) {
3861
- const configPath = process.env.CLAWMUX_CONFIG ? import_node_path4.resolve(process.env.CLAWMUX_CONFIG) : import_node_path4.resolve(process.cwd(), "clawmux.json");
3865
+ const configPath = getClawmuxConfigPath();
3862
3866
  const result = await loadConfig(configPath);
3863
3867
  if (!result.valid) {
3864
3868
  console.error("[clawmux] Config errors:");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmux",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Smart model routing + context compression proxy for OpenClaw",
5
5
  "type": "module",
6
6
  "bin": {