vibora 1.9.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.html CHANGED
@@ -6,8 +6,8 @@
6
6
  <link rel="icon" type="image/png" sizes="512x512" href="/vibora-icon.png" />
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
8
  <title>Vibora</title>
9
- <script type="module" crossorigin src="/assets/index-CCtJOkVu.js"></script>
10
- <link rel="stylesheet" crossorigin href="/assets/index-BxbgLbxS.css">
9
+ <script type="module" crossorigin src="/assets/index-DptSra7n.js"></script>
10
+ <link rel="stylesheet" crossorigin href="/assets/index-D5T2n3lt.css">
11
11
  </head>
12
12
  <body>
13
13
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibora",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "description": "The Vibe Engineer's Cockpit",
5
5
  "license": "PolyForm-Shield-1.0.0",
6
6
  "repository": {
package/server/index.js CHANGED
@@ -3512,7 +3512,8 @@ var DEFAULT_SETTINGS = {
3512
3512
  basicAuthUsername: null,
3513
3513
  basicAuthPassword: null,
3514
3514
  linearApiKey: null,
3515
- githubPat: null
3515
+ githubPat: null,
3516
+ language: null
3516
3517
  };
3517
3518
  function expandPath(p) {
3518
3519
  if (p.startsWith("~/")) {
@@ -3586,7 +3587,8 @@ function getSettings() {
3586
3587
  basicAuthUsername: parsed.basicAuthUsername ?? null,
3587
3588
  basicAuthPassword: parsed.basicAuthPassword ?? null,
3588
3589
  linearApiKey: parsed.linearApiKey ?? null,
3589
- githubPat: parsed.githubPat ?? null
3590
+ githubPat: parsed.githubPat ?? null,
3591
+ language: parsed.language ?? null
3590
3592
  };
3591
3593
  if (hasMissingKeys) {
3592
3594
  fs.writeFileSync(settingsPath, JSON.stringify(fileSettings, null, 2), "utf-8");
@@ -3602,7 +3604,8 @@ function getSettings() {
3602
3604
  basicAuthUsername: process.env.VIBORA_BASIC_AUTH_USERNAME ?? fileSettings.basicAuthUsername,
3603
3605
  basicAuthPassword: process.env.VIBORA_BASIC_AUTH_PASSWORD ?? fileSettings.basicAuthPassword,
3604
3606
  linearApiKey: process.env.LINEAR_API_KEY ?? fileSettings.linearApiKey,
3605
- githubPat: process.env.GITHUB_PAT ?? fileSettings.githubPat
3607
+ githubPat: process.env.GITHUB_PAT ?? fileSettings.githubPat,
3608
+ language: fileSettings.language
3606
3609
  };
3607
3610
  }
3608
3611
  function getSetting(key) {
@@ -3679,6 +3682,80 @@ function updateNotificationSettings(updates) {
3679
3682
  fs.writeFileSync(settingsPath, JSON.stringify(parsed, null, 2), "utf-8");
3680
3683
  return updated;
3681
3684
  }
3685
+ function getClaudeSettingsPath() {
3686
+ return path.join(os.homedir(), ".claude", "settings.json");
3687
+ }
3688
+ function getClaudeSettings() {
3689
+ const settingsPath = getClaudeSettingsPath();
3690
+ if (!fs.existsSync(settingsPath))
3691
+ return {};
3692
+ try {
3693
+ return JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
3694
+ } catch {
3695
+ return {};
3696
+ }
3697
+ }
3698
+ function updateClaudeSettings(updates) {
3699
+ const settingsPath = getClaudeSettingsPath();
3700
+ const dir = path.dirname(settingsPath);
3701
+ if (!fs.existsSync(dir))
3702
+ fs.mkdirSync(dir, { recursive: true });
3703
+ const current = getClaudeSettings();
3704
+ const merged = { ...current, ...updates };
3705
+ fs.writeFileSync(settingsPath, JSON.stringify(merged, null, 2), "utf-8");
3706
+ }
3707
+ var DEFAULT_ZAI_SETTINGS = {
3708
+ enabled: false,
3709
+ apiKey: null,
3710
+ haikuModel: "glm-4.5-air",
3711
+ sonnetModel: "glm-4.7",
3712
+ opusModel: "glm-4.7"
3713
+ };
3714
+ function getZAiSettings() {
3715
+ ensureViboraDir();
3716
+ const settingsPath = getSettingsPath();
3717
+ if (!fs.existsSync(settingsPath)) {
3718
+ return DEFAULT_ZAI_SETTINGS;
3719
+ }
3720
+ try {
3721
+ const content = fs.readFileSync(settingsPath, "utf-8");
3722
+ const parsed = JSON.parse(content);
3723
+ const zai = parsed.zai;
3724
+ if (!zai) {
3725
+ return DEFAULT_ZAI_SETTINGS;
3726
+ }
3727
+ return {
3728
+ enabled: zai.enabled ?? false,
3729
+ apiKey: zai.apiKey ?? null,
3730
+ haikuModel: zai.haikuModel ?? DEFAULT_ZAI_SETTINGS.haikuModel,
3731
+ sonnetModel: zai.sonnetModel ?? DEFAULT_ZAI_SETTINGS.sonnetModel,
3732
+ opusModel: zai.opusModel ?? DEFAULT_ZAI_SETTINGS.opusModel
3733
+ };
3734
+ } catch {
3735
+ return DEFAULT_ZAI_SETTINGS;
3736
+ }
3737
+ }
3738
+ function updateZAiSettings(updates) {
3739
+ ensureViboraDir();
3740
+ const settingsPath = getSettingsPath();
3741
+ let parsed = {};
3742
+ if (fs.existsSync(settingsPath)) {
3743
+ try {
3744
+ parsed = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
3745
+ } catch {}
3746
+ }
3747
+ const current = getZAiSettings();
3748
+ const updated = {
3749
+ enabled: updates.enabled ?? current.enabled,
3750
+ apiKey: updates.apiKey !== undefined ? updates.apiKey : current.apiKey,
3751
+ haikuModel: updates.haikuModel ?? current.haikuModel,
3752
+ sonnetModel: updates.sonnetModel ?? current.sonnetModel,
3753
+ opusModel: updates.opusModel ?? current.opusModel
3754
+ };
3755
+ parsed.zai = updated;
3756
+ fs.writeFileSync(settingsPath, JSON.stringify(parsed, null, 2), "utf-8");
3757
+ return updated;
3758
+ }
3682
3759
 
3683
3760
  // server/middleware/auth.ts
3684
3761
  var SESSION_COOKIE_NAME = "vibora_session";
@@ -13320,7 +13397,7 @@ glob.glob = glob;
13320
13397
  // node_modules/bun-pty/dist/index.js
13321
13398
  import { dlopen, FFIType, ptr } from "bun:ffi";
13322
13399
  import { Buffer as Buffer2 } from "buffer";
13323
- import { join as join3, dirname, basename } from "path";
13400
+ import { join as join3, dirname as dirname2, basename } from "path";
13324
13401
  import { existsSync as existsSync2 } from "fs";
13325
13402
 
13326
13403
  class EventEmitter2 {
@@ -13359,9 +13436,9 @@ function resolveLibPath() {
13359
13436
  const arch = process.arch;
13360
13437
  const filenames = platform === "darwin" ? arch === "arm64" ? ["librust_pty_arm64.dylib", "librust_pty.dylib"] : ["librust_pty.dylib"] : platform === "win32" ? ["rust_pty.dll"] : arch === "arm64" ? ["librust_pty_arm64.so", "librust_pty.so"] : ["librust_pty.so"];
13361
13438
  const base = Bun.fileURLToPath(import.meta.url);
13362
- const fileDir = dirname(base);
13439
+ const fileDir = dirname2(base);
13363
13440
  const dirName = basename(fileDir);
13364
- const here = dirName === "src" || dirName === "dist" ? dirname(fileDir) : fileDir;
13441
+ const here = dirName === "src" || dirName === "dist" ? dirname2(fileDir) : fileDir;
13365
13442
  const basePaths = [
13366
13443
  join3(here, "rust-pty", "target", "release"),
13367
13444
  join3(here, "..", "bun-pty", "rust-pty", "target", "release"),
@@ -138993,7 +139070,8 @@ var CONFIG_KEYS = {
138993
139070
  HOSTNAME: "hostname",
138994
139071
  SSH_PORT: "sshPort",
138995
139072
  LINEAR_API_KEY: "linearApiKey",
138996
- GITHUB_PAT: "githubPat"
139073
+ GITHUB_PAT: "githubPat",
139074
+ LANGUAGE: "language"
138997
139075
  };
138998
139076
  var app5 = new Hono2;
138999
139077
  app5.get("/notifications", (c) => {
@@ -139018,6 +139096,46 @@ app5.post("/notifications/test/:channel", async (c) => {
139018
139096
  const result = await testNotificationChannel(channel);
139019
139097
  return c.json(result);
139020
139098
  });
139099
+ app5.get("/z-ai", (c) => {
139100
+ const settings = getZAiSettings();
139101
+ return c.json(settings);
139102
+ });
139103
+ app5.put("/z-ai", async (c) => {
139104
+ try {
139105
+ const body = await c.req.json();
139106
+ const updated = updateZAiSettings(body);
139107
+ if (updated.enabled && updated.apiKey) {
139108
+ const claudeSettings = getClaudeSettings();
139109
+ const currentEnv = claudeSettings.env || {};
139110
+ updateClaudeSettings({
139111
+ env: {
139112
+ ...currentEnv,
139113
+ ANTHROPIC_AUTH_TOKEN: updated.apiKey,
139114
+ ANTHROPIC_BASE_URL: "https://api.z.ai/api/anthropic",
139115
+ API_TIMEOUT_MS: "3000000",
139116
+ ANTHROPIC_DEFAULT_HAIKU_MODEL: updated.haikuModel,
139117
+ ANTHROPIC_DEFAULT_SONNET_MODEL: updated.sonnetModel,
139118
+ ANTHROPIC_DEFAULT_OPUS_MODEL: updated.opusModel
139119
+ }
139120
+ });
139121
+ } else {
139122
+ const claudeSettings = getClaudeSettings();
139123
+ if (claudeSettings.env) {
139124
+ const env = { ...claudeSettings.env };
139125
+ delete env.ANTHROPIC_AUTH_TOKEN;
139126
+ delete env.ANTHROPIC_BASE_URL;
139127
+ delete env.API_TIMEOUT_MS;
139128
+ delete env.ANTHROPIC_DEFAULT_HAIKU_MODEL;
139129
+ delete env.ANTHROPIC_DEFAULT_SONNET_MODEL;
139130
+ delete env.ANTHROPIC_DEFAULT_OPUS_MODEL;
139131
+ updateClaudeSettings({ env: Object.keys(env).length > 0 ? env : undefined });
139132
+ }
139133
+ }
139134
+ return c.json(updated);
139135
+ } catch (err) {
139136
+ return c.json({ error: err instanceof Error ? err.message : "Failed to update z.ai settings" }, 400);
139137
+ }
139138
+ });
139021
139139
  app5.get("/:key", (c) => {
139022
139140
  const key = c.req.param("key");
139023
139141
  const settings = getSettings();
@@ -139036,6 +139154,8 @@ app5.get("/:key", (c) => {
139036
139154
  value = settings.linearApiKey;
139037
139155
  } else if (key === "github_pat" || key === CONFIG_KEYS.GITHUB_PAT) {
139038
139156
  value = settings.githubPat;
139157
+ } else if (key === "language" || key === CONFIG_KEYS.LANGUAGE) {
139158
+ return c.json({ key, value: settings.language, isDefault: settings.language === null });
139039
139159
  } else if (key === "worktree_base_path") {
139040
139160
  return c.json({ key, value: getWorktreeBasePath(), isDefault: true });
139041
139161
  }
@@ -139092,6 +139212,13 @@ app5.put("/:key", async (c) => {
139092
139212
  }
139093
139213
  updateSettings({ githubPat: body.value || null });
139094
139214
  return c.json({ key, value: body.value });
139215
+ } else if (key === "language" || key === CONFIG_KEYS.LANGUAGE) {
139216
+ const langValue = body.value === "" || body.value === null ? null : body.value;
139217
+ if (langValue !== null && langValue !== "en" && langValue !== "zh") {
139218
+ return c.json({ error: 'Language must be "en", "zh", or null' }, 400);
139219
+ }
139220
+ updateSettings({ language: langValue });
139221
+ return c.json({ key, value: langValue });
139095
139222
  } else {
139096
139223
  return c.json({ error: `Unknown or read-only config key: ${key}` }, 400);
139097
139224
  }
@@ -139117,6 +139244,8 @@ app5.delete("/:key", (c) => {
139117
139244
  defaultValue = defaults2.linearApiKey;
139118
139245
  } else if (key === "github_pat" || key === CONFIG_KEYS.GITHUB_PAT) {
139119
139246
  defaultValue = defaults2.githubPat;
139247
+ } else if (key === "language" || key === CONFIG_KEYS.LANGUAGE) {
139248
+ defaultValue = defaults2.language;
139120
139249
  }
139121
139250
  return c.json({ key, value: defaultValue, isDefault: true });
139122
139251
  });