vibeostheog 0.15.21 → 0.15.23

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/package.json +1 -1
  3. package/src/index.js +194 -166
package/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.15.23
2
+ - feat: add trinity api-token command to inject VIBEOS_API_TOKEN
3
+
4
+
5
+ ## 0.15.22
6
+ - chore: update flash pricing, add fallback indicator to footer
7
+
8
+
1
9
  ## 0.15.21
2
10
  - feat: expose all regime thresholds as calibratable weights
3
11
  - docs: add SIGNAL-REFERENCE.md with full signal pipeline documentation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeostheog",
3
- "version": "0.15.21",
3
+ "version": "0.15.23",
4
4
  "description": "Cost-aware delegation enforcer for OpenCode. Tracks model usage, routes Task subagents to cheaper tiers, surfaces cumulative savings in chat. Includes research audit, reporting framework, project memory, progressive scratchpad decadence, and trinity CLI for brain/medium/cheap slot switching.",
5
5
  "scripts": {
6
6
  "release": "node scripts/release.mjs",
package/src/index.js CHANGED
@@ -291,12 +291,12 @@ function recordFlowTodo({ filePath, content }) {
291
291
  return 0;
292
292
  }
293
293
  }
294
- var __dirname, RULES_PATH, GUARD_AGENTS_TEMPLATE, GUARD_README_TEMPLATE, STATE_FILE, FLOW_TODO_FILE, FLOW_DEDUP_FILE, MAX_FLOW_TODOS, _flowWarnsSeen, _stateWriter, _cachedRules, _rulesMtime;
294
+ var __dirname2, RULES_PATH, GUARD_AGENTS_TEMPLATE, GUARD_README_TEMPLATE, STATE_FILE, FLOW_TODO_FILE, FLOW_DEDUP_FILE, MAX_FLOW_TODOS, _flowWarnsSeen, _stateWriter, _cachedRules, _rulesMtime;
295
295
  var init_flow_enforcer = __esm({
296
296
  "src/vibeOS-lib/flow-enforcer.js"() {
297
297
  "use strict";
298
- __dirname = dirname(fileURLToPath(import.meta.url));
299
- RULES_PATH = join(__dirname, "flow-rules.json");
298
+ __dirname2 = dirname(fileURLToPath(import.meta.url));
299
+ RULES_PATH = join(__dirname2, "flow-rules.json");
300
300
  GUARD_AGENTS_TEMPLATE = [
301
301
  "# AGENTS.md",
302
302
  "",
@@ -350,7 +350,7 @@ var init_flow_enforcer = __esm({
350
350
 
351
351
  // src/index.ts
352
352
  init_flow_enforcer();
353
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, existsSync as existsSync14, mkdirSync as mkdirSync10, copyFileSync as copyFileSync6, renameSync as renameSync6 } from "node:fs";
353
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync13, existsSync as existsSync14, mkdirSync as mkdirSync10, copyFileSync as copyFileSync6, renameSync as renameSync6 } from "node:fs";
354
354
  import { join as join15, dirname as dirname7, basename as basename9 } from "node:path";
355
355
 
356
356
  // src/vibeOS-lib/session-metrics.js
@@ -496,26 +496,123 @@ function computeSessionMetrics(state, sessionId) {
496
496
  // src/index.ts
497
497
  import { createMcpServer } from "vibeOScore/mcp-server";
498
498
 
499
+ // src/lib/api-client.js
500
+ import { VibeOSApiClient, VibeOSAuthError, VibeOSTimeoutError, VibeOSNetworkError } from "vibeOScore/client";
501
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
502
+ import { homedir as homedir2 } from "node:os";
503
+ var VIBEOS_API_URL = process.env.VIBEOS_API_URL || "https://api.vibetheog.com";
504
+ var _envTk = "";
505
+ var _envPaths = [
506
+ process.cwd() + "/.env.production",
507
+ homedir2() + "/.claude/.env.production",
508
+ homedir2() + "/.env.production",
509
+ process.cwd() + "/.env.production"
510
+ ];
511
+ for (const dir of _envPaths) {
512
+ try {
513
+ const env = readFileSync2(dir + "/.env.production", "utf8");
514
+ const m = env.match(/^VIBEOS_API_TOKEN=(.+)$/m);
515
+ if (m) {
516
+ _envTk = m[1].trim();
517
+ break;
518
+ }
519
+ } catch {
520
+ }
521
+ }
522
+ var VIBEOS_API_TOKEN = process.env.VIBEOS_API_TOKEN || _envTk || "";
523
+ var VIBEOS_API_ENABLED = process.env.VIBEOS_API_ENABLED !== "false" && !!VIBEOS_API_TOKEN;
524
+ var _apiClient = null;
525
+ var _apiFallbackMode = false;
526
+ var _apiFallbackSince = null;
527
+ function setApiToken(newToken) {
528
+ VIBEOS_API_TOKEN = newToken;
529
+ VIBEOS_API_ENABLED = process.env.VIBEOS_API_ENABLED !== "false" && !!VIBEOS_API_TOKEN;
530
+ _apiClient = null;
531
+ _apiFallbackMode = false;
532
+ _apiFallbackSince = null;
533
+ const paths = [__dirname, homedir2() + "/.claude", homedir2(), process.cwd()];
534
+ for (const dir of paths) {
535
+ try {
536
+ const filePath = dir + "/.env.production";
537
+ let env = "";
538
+ try {
539
+ env = readFileSync2(filePath, "utf8");
540
+ } catch {
541
+ }
542
+ const lines = env.split("\n");
543
+ const filtered = lines.filter((l) => !l.startsWith("VIBEOS_API_TOKEN="));
544
+ filtered.push("VIBEOS_API_TOKEN=" + newToken);
545
+ writeFileSync2(filePath, filtered.join("\n") + "\n", "utf8");
546
+ } catch {
547
+ }
548
+ }
549
+ console.error("[vibeOS] API token updated via setApiToken");
550
+ }
551
+ function getApiClient() {
552
+ if (!_apiClient && VIBEOS_API_ENABLED) {
553
+ _apiClient = new VibeOSApiClient({
554
+ baseUrl: VIBEOS_API_URL,
555
+ apiToken: VIBEOS_API_TOKEN,
556
+ timeout: 5e3
557
+ });
558
+ }
559
+ return _apiClient;
560
+ }
561
+ function isApiFallback() {
562
+ return _apiFallbackMode || !VIBEOS_API_ENABLED;
563
+ }
564
+ async function remoteCall(method, args, fallbackFn) {
565
+ if (!VIBEOS_API_ENABLED || _apiFallbackMode) {
566
+ if (fallbackFn) return fallbackFn();
567
+ return null;
568
+ }
569
+ try {
570
+ const client2 = getApiClient();
571
+ if (!client2) {
572
+ if (fallbackFn) return fallbackFn();
573
+ return null;
574
+ }
575
+ const result = await client2[method](...args);
576
+ _apiFallbackMode = false;
577
+ _apiFallbackSince = null;
578
+ return result;
579
+ } catch (err) {
580
+ if (!_apiFallbackMode) {
581
+ _apiFallbackMode = true;
582
+ _apiFallbackSince = (/* @__PURE__ */ new Date()).toISOString();
583
+ console.error(`[vibeOS] API fallback activated: ${err.message}`);
584
+ }
585
+ if (fallbackFn) {
586
+ try {
587
+ return fallbackFn();
588
+ } catch (fe) {
589
+ console.error(`[vibeOS] fallback also failed: ${fe.message}`);
590
+ }
591
+ }
592
+ return null;
593
+ }
594
+ }
595
+
499
596
  // src/lib/pricing.js
500
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, appendFileSync as appendFileSync4, existsSync as existsSync4, mkdirSync as mkdirSync4, statSync as statSync4, copyFileSync as copyFileSync3, renameSync as renameSync4, openSync as openSync2, closeSync as closeSync2, rmSync as rmSync2 } from "node:fs";
597
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, appendFileSync as appendFileSync4, existsSync as existsSync4, mkdirSync as mkdirSync4, statSync as statSync4, copyFileSync as copyFileSync3, renameSync as renameSync4, openSync as openSync2, closeSync as closeSync2, rmSync as rmSync2 } from "node:fs";
501
598
  import { join as join4, dirname as dirname3, basename as basename4 } from "node:path";
502
- import { homedir as homedir4, tmpdir as tmpdir3 } from "node:os";
599
+ import { homedir as homedir5, tmpdir as tmpdir3 } from "node:os";
503
600
  import { createHash as createHash2 } from "node:crypto";
504
601
 
505
602
  // src/lib/state.js
506
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, appendFileSync as appendFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync3, statSync as statSync3, readdirSync, openSync, readSync, closeSync, rmSync, copyFileSync as copyFileSync2, renameSync as renameSync3 } from "node:fs";
603
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, appendFileSync as appendFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync3, statSync as statSync3, readdirSync, openSync, readSync, closeSync, rmSync, copyFileSync as copyFileSync2, renameSync as renameSync3 } from "node:fs";
507
604
  import { join as join3, dirname as dirname2, basename as basename3 } from "node:path";
508
605
  import { spawn } from "node:child_process";
509
- import { homedir as homedir3, tmpdir as tmpdir2 } from "node:os";
606
+ import { homedir as homedir4, tmpdir as tmpdir2 } from "node:os";
510
607
  import { createHash } from "node:crypto";
511
608
 
512
609
  // src/lib/selection-manager.js
513
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, appendFileSync as appendFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2, statSync as statSync2, copyFileSync, renameSync as renameSync2 } from "node:fs";
610
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, appendFileSync as appendFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2, statSync as statSync2, copyFileSync, renameSync as renameSync2 } from "node:fs";
514
611
  import { join as join2, basename } from "node:path";
515
- import { homedir as homedir2, tmpdir } from "node:os";
612
+ import { homedir as homedir3, tmpdir } from "node:os";
516
613
  var USER_HOME = (() => {
517
614
  try {
518
- return homedir2();
615
+ return homedir3();
519
616
  } catch {
520
617
  return tmpdir();
521
618
  }
@@ -559,7 +656,7 @@ function loadSelection() {
559
656
  _handleStateCorruption(TIERS_FILE);
560
657
  return DFLT_SEL;
561
658
  }
562
- const j = safeJsonParse2(readFileSync2(TIERS_FILE, "utf-8"));
659
+ const j = safeJsonParse2(readFileSync3(TIERS_FILE, "utf-8"));
563
660
  return {
564
661
  enabled: j?.selection?.enabled !== false,
565
662
  active_slot: j?.selection?.active_slot || null,
@@ -578,10 +675,10 @@ function loadSelection() {
578
675
  }
579
676
  function writeSelection(key, value) {
580
677
  try {
581
- const j = safeJsonParse2(readFileSync2(TIERS_FILE, "utf-8"));
678
+ const j = safeJsonParse2(readFileSync3(TIERS_FILE, "utf-8"));
582
679
  j.selection[key] = value;
583
680
  const tmp = TIERS_FILE + ".tmp";
584
- writeFileSync2(tmp, JSON.stringify(j, null, 2) + "\n");
681
+ writeFileSync3(tmp, JSON.stringify(j, null, 2) + "\n");
585
682
  renameSync2(tmp, TIERS_FILE);
586
683
  return true;
587
684
  } catch (err) {
@@ -594,7 +691,7 @@ function loadSessionSlot(sid) {
594
691
  try {
595
692
  if (!existsSync2(BLACKBOX_FILE))
596
693
  return null;
597
- const j = safeJsonParse2(readFileSync2(BLACKBOX_FILE, "utf-8"));
694
+ const j = safeJsonParse2(readFileSync3(BLACKBOX_FILE, "utf-8"));
598
695
  return j?.sessions?.[sid]?.active_slot || null;
599
696
  } catch {
600
697
  return null;
@@ -602,14 +699,14 @@ function loadSessionSlot(sid) {
602
699
  }
603
700
  function writeSessionSlot(sid, slot) {
604
701
  try {
605
- const j = existsSync2(BLACKBOX_FILE) ? safeJsonParse2(readFileSync2(BLACKBOX_FILE, "utf-8")) : {};
702
+ const j = existsSync2(BLACKBOX_FILE) ? safeJsonParse2(readFileSync3(BLACKBOX_FILE, "utf-8")) : {};
606
703
  if (!j.sessions)
607
704
  j.sessions = {};
608
705
  if (!j.sessions[sid])
609
706
  j.sessions[sid] = {};
610
707
  j.sessions[sid].active_slot = slot;
611
708
  const tmp = BLACKBOX_FILE + ".tmp";
612
- writeFileSync2(tmp, JSON.stringify(j, null, 2) + "\n");
709
+ writeFileSync3(tmp, JSON.stringify(j, null, 2) + "\n");
613
710
  renameSync2(tmp, BLACKBOX_FILE);
614
711
  return true;
615
712
  } catch (err) {
@@ -621,7 +718,7 @@ function loadSessionOptMode(sid) {
621
718
  try {
622
719
  if (!existsSync2(BLACKBOX_FILE))
623
720
  return null;
624
- const j = safeJsonParse2(readFileSync2(BLACKBOX_FILE, "utf-8"));
721
+ const j = safeJsonParse2(readFileSync3(BLACKBOX_FILE, "utf-8"));
625
722
  return j?.sessions?.[sid]?.optimization_mode || null;
626
723
  } catch {
627
724
  return null;
@@ -629,14 +726,14 @@ function loadSessionOptMode(sid) {
629
726
  }
630
727
  function writeSessionOptMode(sid, mode) {
631
728
  try {
632
- const j = existsSync2(BLACKBOX_FILE) ? safeJsonParse2(readFileSync2(BLACKBOX_FILE, "utf-8")) : {};
729
+ const j = existsSync2(BLACKBOX_FILE) ? safeJsonParse2(readFileSync3(BLACKBOX_FILE, "utf-8")) : {};
633
730
  if (!j.sessions)
634
731
  j.sessions = {};
635
732
  if (!j.sessions[sid])
636
733
  j.sessions[sid] = {};
637
734
  j.sessions[sid].optimization_mode = mode;
638
735
  const tmp = BLACKBOX_FILE + ".tmp";
639
- writeFileSync2(tmp, JSON.stringify(j, null, 2) + "\n");
736
+ writeFileSync3(tmp, JSON.stringify(j, null, 2) + "\n");
640
737
  renameSync2(tmp, BLACKBOX_FILE);
641
738
  return true;
642
739
  } catch (err) {
@@ -1310,7 +1407,7 @@ function deserializeCacheDb(raw) {
1310
1407
  // src/lib/state.js
1311
1408
  var USER_HOME2 = (() => {
1312
1409
  try {
1313
- return homedir3();
1410
+ return homedir4();
1314
1411
  } catch {
1315
1412
  return tmpdir2();
1316
1413
  }
@@ -1461,7 +1558,7 @@ function withFileLock(filePath, fn, opts = {}) {
1461
1558
  mkdirSync3(FILE_LOCK_DIR, { recursive: true });
1462
1559
  const fd = openSync(lockPath, "wx");
1463
1560
  try {
1464
- writeFileSync3(fd, `${process.pid}
1561
+ writeFileSync4(fd, `${process.pid}
1465
1562
  ${Date.now()}
1466
1563
  `);
1467
1564
  } catch {
@@ -1539,7 +1636,7 @@ function readJsonOrEmpty(filePath) {
1539
1636
  _handleStateCorruption2(filePath);
1540
1637
  return {};
1541
1638
  }
1542
- return safeJsonParse3(readFileSync3(filePath, "utf-8"));
1639
+ return safeJsonParse3(readFileSync4(filePath, "utf-8"));
1543
1640
  } catch {
1544
1641
  _handleStateCorruption2(filePath);
1545
1642
  return {};
@@ -1567,7 +1664,7 @@ function updateState(mutator) {
1567
1664
  validateState(next, DELEGATION_STATE_FILE);
1568
1665
  mkdirSync3(dirname2(DELEGATION_STATE_FILE), { recursive: true });
1569
1666
  const tmp = DELEGATION_STATE_FILE + ".tmp";
1570
- writeFileSync3(tmp, JSON.stringify(next, null, 2) + "\n");
1667
+ writeFileSync4(tmp, JSON.stringify(next, null, 2) + "\n");
1571
1668
  renameSync3(tmp, DELEGATION_STATE_FILE);
1572
1669
  return next;
1573
1670
  });
@@ -1590,7 +1687,7 @@ function readFullState() {
1590
1687
  _handleStateCorruption2(DELEGATION_STATE_FILE);
1591
1688
  return {};
1592
1689
  }
1593
- return safeJsonParse3(readFileSync3(DELEGATION_STATE_FILE, "utf-8"));
1690
+ return safeJsonParse3(readFileSync4(DELEGATION_STATE_FILE, "utf-8"));
1594
1691
  } catch {
1595
1692
  _handleStateCorruption2(DELEGATION_STATE_FILE);
1596
1693
  return {};
@@ -1616,7 +1713,7 @@ function loadTierRegexes() {
1616
1713
  const p = join3(USER_HOME2, ".claude/model-tiers.json");
1617
1714
  if (!existsSync3(p))
1618
1715
  return { high: FALLBACK_HIGH, mid: FALLBACK_MID };
1619
- const j = safeJsonParse3(readFileSync3(p, "utf-8"));
1716
+ const j = safeJsonParse3(readFileSync4(p, "utf-8"));
1620
1717
  const highRe = _safeRegex(j?.tiers?.high?.regex, FALLBACK_HIGH, "high");
1621
1718
  const midRe = _safeRegex(j?.tiers?.mid?.regex, FALLBACK_MID, "mid");
1622
1719
  return { high: highRe, mid: midRe };
@@ -1634,7 +1731,7 @@ function loadGlobalLearning() {
1634
1731
  _handleStateCorruption2(GLOBAL_LEARNING_FILE);
1635
1732
  return DFLT_GL;
1636
1733
  }
1637
- const j = safeJsonParse3(readFileSync3(GLOBAL_LEARNING_FILE, "utf-8"));
1734
+ const j = safeJsonParse3(readFileSync4(GLOBAL_LEARNING_FILE, "utf-8"));
1638
1735
  if (!j || typeof j !== "object")
1639
1736
  return DFLT_GL;
1640
1737
  j.exploratory_words ??= {};
@@ -1652,7 +1749,7 @@ function updateGlobalLearning(mutator) {
1652
1749
  next.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1653
1750
  mkdirSync3(dirname2(GLOBAL_LEARNING_FILE), { recursive: true });
1654
1751
  const tmp = GLOBAL_LEARNING_FILE + ".tmp";
1655
- writeFileSync3(tmp, JSON.stringify(next, null, 2));
1752
+ writeFileSync4(tmp, JSON.stringify(next, null, 2));
1656
1753
  renameSync3(tmp, GLOBAL_LEARNING_FILE);
1657
1754
  return next;
1658
1755
  });
@@ -1926,14 +2023,14 @@ function _pruneScratchpadDir(targetDir, opts = {}) {
1926
2023
  const summaryPath = join3(targetDir, hash + ".summary.txt");
1927
2024
  if (!existsSync3(summaryPath))
1928
2025
  try {
1929
- const content = readFileSync3(fullPath, "utf-8");
1930
- writeFileSync3(summaryPath, content.slice(0, 200).replace(/\n+/g, " ").trim() + (content.length > 200 ? "\u2026" : ""));
2026
+ const content = readFileSync4(fullPath, "utf-8");
2027
+ writeFileSync4(summaryPath, content.slice(0, 200).replace(/\n+/g, " ").trim() + (content.length > 200 ? "\u2026" : ""));
1931
2028
  } catch {
1932
2029
  }
1933
2030
  const head = _readHead(fullPath);
1934
2031
  if (!head.includes("[cold-storage]"))
1935
2032
  try {
1936
- writeFileSync3(fullPath, `[cold-storage] ${st.size}B original \u2192 ${hash}.summary.txt`);
2033
+ writeFileSync4(fullPath, `[cold-storage] ${st.size}B original \u2192 ${hash}.summary.txt`);
1937
2034
  rotated++;
1938
2035
  } catch {
1939
2036
  }
@@ -1943,14 +2040,14 @@ function _pruneScratchpadDir(targetDir, opts = {}) {
1943
2040
  const summaryPath = join3(targetDir, hash + ".summary.txt");
1944
2041
  if (!existsSync3(summaryPath))
1945
2042
  try {
1946
- const content = readFileSync3(fullPath, "utf-8");
1947
- writeFileSync3(summaryPath, content.slice(0, 500).replace(/\n+/g, " ").trim() + (content.length > 500 ? "\u2026" : ""));
2043
+ const content = readFileSync4(fullPath, "utf-8");
2044
+ writeFileSync4(summaryPath, content.slice(0, 500).replace(/\n+/g, " ").trim() + (content.length > 500 ? "\u2026" : ""));
1948
2045
  } catch {
1949
2046
  }
1950
2047
  const head = _readHead(fullPath);
1951
2048
  if (!head.includes("[warm-storage]") && !head.includes("[cold-storage]"))
1952
2049
  try {
1953
- writeFileSync3(fullPath, `[warm-storage] ${st.size}B original at ${hash}.summary.txt`);
2050
+ writeFileSync4(fullPath, `[warm-storage] ${st.size}B original at ${hash}.summary.txt`);
1954
2051
  rotated++;
1955
2052
  } catch {
1956
2053
  }
@@ -2018,7 +2115,7 @@ function loadActiveJobs() {
2018
2115
  _handleStateCorruption2(ACTIVE_JOBS_FILE);
2019
2116
  return {};
2020
2117
  }
2021
- const raw = safeJsonParse3(readFileSync3(ACTIVE_JOBS_FILE, "utf-8"));
2118
+ const raw = safeJsonParse3(readFileSync4(ACTIVE_JOBS_FILE, "utf-8"));
2022
2119
  if (!raw || typeof raw !== "object")
2023
2120
  return {};
2024
2121
  return raw;
@@ -2044,7 +2141,7 @@ function saveActiveJobForProject(job, fp3 = currentProjectFingerprint) {
2044
2141
  jobs[fp3] = job;
2045
2142
  mkdirSync3(dirname2(ACTIVE_JOBS_FILE), { recursive: true });
2046
2143
  const tmp = ACTIVE_JOBS_FILE + ".tmp";
2047
- writeFileSync3(tmp, JSON.stringify(jobs, null, 2));
2144
+ writeFileSync4(tmp, JSON.stringify(jobs, null, 2));
2048
2145
  renameSync3(tmp, ACTIVE_JOBS_FILE);
2049
2146
  } catch {
2050
2147
  }
@@ -2070,7 +2167,7 @@ function saveProjectState(state) {
2070
2167
  withFileLock(PROJECT_STATE_FILE, () => {
2071
2168
  mkdirSync3(dirname2(PROJECT_STATE_FILE), { recursive: true });
2072
2169
  const _tmp = PROJECT_STATE_FILE + ".tmp." + Date.now();
2073
- writeFileSync3(_tmp, JSON.stringify(state, null, 2) + "\n", "utf-8");
2170
+ writeFileSync4(_tmp, JSON.stringify(state, null, 2) + "\n", "utf-8");
2074
2171
  renameSync3(_tmp, PROJECT_STATE_FILE);
2075
2172
  });
2076
2173
  } catch (err) {
@@ -2093,7 +2190,7 @@ function ensureProjectBucket(state, fp3) {
2093
2190
  function detectTechStack(dir) {
2094
2191
  const stacks = [];
2095
2192
  try {
2096
- const pkg = safeJsonParse3(readFileSync3(join3(dir, "package.json"), "utf-8"));
2193
+ const pkg = safeJsonParse3(readFileSync4(join3(dir, "package.json"), "utf-8"));
2097
2194
  if (pkg) {
2098
2195
  if (pkg.devDependencies?.typescript || pkg.dependencies?.typescript || existsSync3(join3(dir, "tsconfig.json")))
2099
2196
  stacks.push("typescript");
@@ -2264,7 +2361,7 @@ function readLedgerTotals() {
2264
2361
  try {
2265
2362
  if (!existsSync3(SAVINGS_LEDGER_FILE))
2266
2363
  return empty;
2267
- const raw = readFileSync3(SAVINGS_LEDGER_FILE, "utf-8");
2364
+ const raw = readFileSync4(SAVINGS_LEDGER_FILE, "utf-8");
2268
2365
  if (!raw.trim())
2269
2366
  return empty;
2270
2367
  let delegation = 0;
@@ -2341,7 +2438,7 @@ function readLifetimeSavings() {
2341
2438
  const mtime = statSync3(DELEGATION_STATE_FILE).mtimeMs;
2342
2439
  if (_savingsCache && mtime === _savingsCacheMtime)
2343
2440
  return _savingsCache;
2344
- const s = safeJsonParse3(readFileSync3(DELEGATION_STATE_FILE, "utf-8"));
2441
+ const s = safeJsonParse3(readFileSync4(DELEGATION_STATE_FILE, "utf-8"));
2345
2442
  _savingsCache = _computeSessionMetrics(s, _OC_SID);
2346
2443
  _savingsCacheMtime = mtime;
2347
2444
  return _savingsCache;
@@ -2368,7 +2465,7 @@ function saveSessionCheckpoint() {
2368
2465
  const cpPath = join3(getSessionRoot(), "checkpoint.json");
2369
2466
  mkdirSync3(dirname2(cpPath), { recursive: true });
2370
2467
  const tmp = cpPath + ".tmp";
2371
- writeFileSync3(tmp, JSON.stringify(cp, null, 2) + "\n");
2468
+ writeFileSync4(tmp, JSON.stringify(cp, null, 2) + "\n");
2372
2469
  renameSync3(tmp, cpPath);
2373
2470
  } catch {
2374
2471
  }
@@ -2389,7 +2486,7 @@ function setTrinityCheap(v) {
2389
2486
  }
2390
2487
  var USER_HOME3 = (() => {
2391
2488
  try {
2392
- return homedir4();
2489
+ return homedir5();
2393
2490
  } catch {
2394
2491
  return tmpdir3();
2395
2492
  }
@@ -2424,7 +2521,7 @@ function withFileLock2(filePath, fn, opts = {}) {
2424
2521
  mkdirSync4(FILE_LOCK_DIR2, { recursive: true });
2425
2522
  const fd = openSync2(lockPath, "wx");
2426
2523
  try {
2427
- writeFileSync4(fd, `${process.pid}
2524
+ writeFileSync5(fd, `${process.pid}
2428
2525
  ${Date.now()}
2429
2526
  `);
2430
2527
  } catch {
@@ -2464,7 +2561,7 @@ function loadTierRegexes2() {
2464
2561
  const p = join4(USER_HOME3, ".claude/model-tiers.json");
2465
2562
  if (!existsSync4(p))
2466
2563
  return { high: FALLBACK_HIGH, mid: FALLBACK_MID };
2467
- const j = safeJsonParse3(readFileSync4(p, "utf-8"));
2564
+ const j = safeJsonParse3(readFileSync5(p, "utf-8"));
2468
2565
  const highRe = _safeRegex(j?.tiers?.high?.regex, FALLBACK_HIGH, "high");
2469
2566
  const midRe = _safeRegex(j?.tiers?.mid?.regex, FALLBACK_MID, "mid");
2470
2567
  return { high: highRe, mid: midRe };
@@ -2533,7 +2630,7 @@ var MODEL_USD_PER_TURN = {
2533
2630
  "haiku": 22e-4,
2534
2631
  // ── DeepSeek (OC platform + OpenRouter) ──────────────────
2535
2632
  "deepseek/deepseek-v4-pro": 57e-5,
2536
- "deepseek/deepseek-v4-flash": 0.000146,
2633
+ "deepseek/deepseek-v4-flash": 0.00013,
2537
2634
  "deepseek/deepseek-chat": 0,
2538
2635
  "deepseek-chat": 0,
2539
2636
  "deepseek/deepseek-v3": 0,
@@ -2570,7 +2667,7 @@ function _loadDynamicPricingCache() {
2570
2667
  _dynamicPricingCache = {};
2571
2668
  return {};
2572
2669
  }
2573
- const raw = safeJsonParse3(readFileSync4(PRICING_CACHE_FILE2, "utf-8"));
2670
+ const raw = safeJsonParse3(readFileSync5(PRICING_CACHE_FILE2, "utf-8"));
2574
2671
  const map = raw?.models && typeof raw.models === "object" ? raw.models : {};
2575
2672
  _dynamicPricingCache = map;
2576
2673
  } catch {
@@ -2612,7 +2709,7 @@ function _writeDynamicPricingCache(modelsMap) {
2612
2709
  withFileLock2(PRICING_CACHE_FILE2, () => {
2613
2710
  mkdirSync4(dirname3(PRICING_CACHE_FILE2), { recursive: true });
2614
2711
  const tmp = PRICING_CACHE_FILE2 + ".tmp";
2615
- writeFileSync4(tmp, JSON.stringify({
2712
+ writeFileSync5(tmp, JSON.stringify({
2616
2713
  ts: Date.now(),
2617
2714
  source: "openrouter-models",
2618
2715
  models: modelsMap
@@ -2682,7 +2779,7 @@ function detectContext7(files = CONTEXT7_CONFIG_FILES) {
2682
2779
  return true;
2683
2780
  for (const f of files) {
2684
2781
  try {
2685
- if (existsSync4(f) && /context7/i.test(readFileSync4(f, "utf-8")))
2782
+ if (existsSync4(f) && /context7/i.test(readFileSync5(f, "utf-8")))
2686
2783
  return true;
2687
2784
  } catch {
2688
2785
  }
@@ -2703,7 +2800,7 @@ function loadSelection2() {
2703
2800
  _handleStateCorruption3(TIERS_FILE3);
2704
2801
  return DFLT_SEL2;
2705
2802
  }
2706
- const j = safeJsonParse3(readFileSync4(TIERS_FILE3, "utf-8"));
2803
+ const j = safeJsonParse3(readFileSync5(TIERS_FILE3, "utf-8"));
2707
2804
  return {
2708
2805
  enabled: j?.selection?.enabled !== false,
2709
2806
  active_slot: j?.selection?.active_slot || null,
@@ -2739,10 +2836,10 @@ function readOpenCodeConfigObject(dir) {
2739
2836
  const jsonPath = join4(dir, "opencode.json");
2740
2837
  const jsoncPath = join4(dir, "opencode.jsonc");
2741
2838
  if (existsSync4(jsonPath)) {
2742
- return safeJsonParse3(readFileSync4(jsonPath, "utf-8"));
2839
+ return safeJsonParse3(readFileSync5(jsonPath, "utf-8"));
2743
2840
  }
2744
2841
  if (existsSync4(jsoncPath)) {
2745
- return parseJsonc(readFileSync4(jsoncPath, "utf-8"));
2842
+ return parseJsonc(readFileSync5(jsoncPath, "utf-8"));
2746
2843
  }
2747
2844
  return {};
2748
2845
  }
@@ -2752,7 +2849,7 @@ function _refreshModel(directory3) {
2752
2849
  const sel = loadSelection2();
2753
2850
  if (!sel.enabled)
2754
2851
  return;
2755
- const tiersData = safeJsonParse3(readFileSync4(TIERS_FILE3, "utf-8"));
2852
+ const tiersData = safeJsonParse3(readFileSync5(TIERS_FILE3, "utf-8"));
2756
2853
  const activeSlot = sel.active_slot || "brain";
2757
2854
  let slotOcModel = tiersData?.trinity?.[activeSlot]?.oc || "";
2758
2855
  if (slotOcModel && PLACEHOLDER_RE.test(slotOcModel)) {
@@ -2789,12 +2886,12 @@ function _refreshModel(directory3) {
2789
2886
  console.error(`[vibeOS] model refresh (config): ${oldModel}(${oldTier}) \u2192 ${currentModel}(${currentTier})`);
2790
2887
  try {
2791
2888
  if (existsSync4(TIERS_FILE3)) {
2792
- const t = safeJsonParse3(readFileSync4(TIERS_FILE3, "utf-8"));
2889
+ const t = safeJsonParse3(readFileSync5(TIERS_FILE3, "utf-8"));
2793
2890
  for (const s of ["brain", "medium", "cheap"]) {
2794
2891
  if (t?.trinity?.[s]?.oc === cfgModel) {
2795
2892
  t.selection.active_slot = s;
2796
2893
  const _tmp = TIERS_FILE3 + ".tmp." + Date.now();
2797
- writeFileSync4(_tmp, JSON.stringify(t, null, 2) + "\n", "utf-8");
2894
+ writeFileSync5(_tmp, JSON.stringify(t, null, 2) + "\n", "utf-8");
2798
2895
  renameSync4(_tmp, TIERS_FILE3);
2799
2896
  console.error(`[vibeOS] model refresh (config): synced active_slot \u2192 ${s}`);
2800
2897
  break;
@@ -2810,20 +2907,20 @@ function _refreshModel(directory3) {
2810
2907
  }
2811
2908
  function applySlot2(slot) {
2812
2909
  try {
2813
- const j = safeJsonParse3(readFileSync4(TIERS_FILE3, "utf-8"));
2910
+ const j = safeJsonParse3(readFileSync5(TIERS_FILE3, "utf-8"));
2814
2911
  const ocModel = j?.trinity?.[slot]?.oc;
2815
2912
  if (!ocModel)
2816
2913
  return { ok: false, reason: `slot '${slot}' has no oc model` };
2817
2914
  j.selection.active_slot = slot;
2818
2915
  const _tmp = TIERS_FILE3 + ".tmp." + Date.now();
2819
- writeFileSync4(_tmp, JSON.stringify(j, null, 2) + "\n", "utf-8");
2916
+ writeFileSync5(_tmp, JSON.stringify(j, null, 2) + "\n", "utf-8");
2820
2917
  renameSync4(_tmp, TIERS_FILE3);
2821
2918
  const localOcConfig = join4(process.cwd(), "opencode.json");
2822
2919
  const ocConfig = existsSync4(localOcConfig) ? localOcConfig : join4(USER_HOME3, ".config/opencode/opencode.json");
2823
2920
  if (existsSync4(ocConfig)) {
2824
- const oc = safeJsonParse3(readFileSync4(ocConfig, "utf-8"));
2921
+ const oc = safeJsonParse3(readFileSync5(ocConfig, "utf-8"));
2825
2922
  oc.model = ocModel;
2826
- writeFileSync4(ocConfig, JSON.stringify(oc, null, 2) + "\n");
2923
+ writeFileSync5(ocConfig, JSON.stringify(oc, null, 2) + "\n");
2827
2924
  }
2828
2925
  _refreshModel(process.cwd());
2829
2926
  return { ok: true, ocModel };
@@ -2833,86 +2930,11 @@ function applySlot2(slot) {
2833
2930
  }
2834
2931
 
2835
2932
  // src/lib/turn-classify.js
2836
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, appendFileSync as appendFileSync5, existsSync as existsSync5, mkdirSync as mkdirSync5, statSync as statSync5, copyFileSync as copyFileSync4, renameSync as renameSync5, openSync as openSync3, closeSync as closeSync3, rmSync as rmSync3 } from "node:fs";
2933
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, appendFileSync as appendFileSync5, existsSync as existsSync5, mkdirSync as mkdirSync5, statSync as statSync5, copyFileSync as copyFileSync4, renameSync as renameSync5, openSync as openSync3, closeSync as closeSync3, rmSync as rmSync3 } from "node:fs";
2837
2934
  import { join as join5, dirname as dirname4, basename as basename5 } from "node:path";
2838
2935
  import { homedir as homedir6, tmpdir as tmpdir4 } from "node:os";
2839
2936
  import { createHash as createHash3 } from "node:crypto";
2840
2937
 
2841
- // src/lib/api-client.js
2842
- import { VibeOSApiClient } from "vibeOScore/client";
2843
- import { readFileSync as readFileSync5 } from "node:fs";
2844
- import { homedir as homedir5 } from "node:os";
2845
- var VIBEOS_API_URL = process.env.VIBEOS_API_URL || "https://api.vibetheog.com";
2846
- var _envTk = "";
2847
- var _envPaths = [
2848
- process.cwd() + "/.env.production",
2849
- homedir5() + "/.claude/.env.production",
2850
- homedir5() + "/.env.production",
2851
- process.cwd() + "/.env.production"
2852
- ];
2853
- for (const dir of _envPaths) {
2854
- try {
2855
- const env = readFileSync5(dir + "/.env.production", "utf8");
2856
- const m = env.match(/^VIBEOS_API_TOKEN=(.+)$/m);
2857
- if (m) {
2858
- _envTk = m[1].trim();
2859
- break;
2860
- }
2861
- } catch {
2862
- }
2863
- }
2864
- var VIBEOS_API_TOKEN = process.env.VIBEOS_API_TOKEN || _envTk || "";
2865
- var VIBEOS_API_ENABLED = process.env.VIBEOS_API_ENABLED !== "false" && !!VIBEOS_API_TOKEN;
2866
- var _apiClient = null;
2867
- var _apiFallbackMode = false;
2868
- var _apiFallbackSince = null;
2869
- function getApiClient() {
2870
- if (!_apiClient && VIBEOS_API_ENABLED) {
2871
- _apiClient = new VibeOSApiClient({
2872
- baseUrl: VIBEOS_API_URL,
2873
- apiToken: VIBEOS_API_TOKEN,
2874
- timeout: 5e3
2875
- });
2876
- }
2877
- return _apiClient;
2878
- }
2879
- function isApiFallback() {
2880
- return _apiFallbackMode || !VIBEOS_API_ENABLED;
2881
- }
2882
- async function remoteCall(method, args, fallbackFn) {
2883
- if (!VIBEOS_API_ENABLED || _apiFallbackMode) {
2884
- if (fallbackFn)
2885
- return fallbackFn();
2886
- return null;
2887
- }
2888
- try {
2889
- const client2 = getApiClient();
2890
- if (!client2) {
2891
- if (fallbackFn)
2892
- return fallbackFn();
2893
- return null;
2894
- }
2895
- const result = await client2[method](...args);
2896
- _apiFallbackMode = false;
2897
- _apiFallbackSince = null;
2898
- return result;
2899
- } catch (err) {
2900
- if (!_apiFallbackMode) {
2901
- _apiFallbackMode = true;
2902
- _apiFallbackSince = (/* @__PURE__ */ new Date()).toISOString();
2903
- console.error(`[vibeOS] API fallback activated: ${err.message}`);
2904
- }
2905
- if (fallbackFn) {
2906
- try {
2907
- return fallbackFn();
2908
- } catch (fe) {
2909
- console.error(`[vibeOS] fallback also failed: ${fe.message}`);
2910
- }
2911
- }
2912
- return null;
2913
- }
2914
- }
2915
-
2916
2938
  // src/lib/classifiers.js
2917
2939
  function detectOutcomeSignal(text) {
2918
2940
  if (!text)
@@ -3164,7 +3186,7 @@ function withFileLock3(filePath, fn, opts = {}) {
3164
3186
  mkdirSync5(FILE_LOCK_DIR3, { recursive: true });
3165
3187
  const fd = openSync3(lockPath, "wx");
3166
3188
  try {
3167
- writeFileSync5(fd, `${process.pid}
3189
+ writeFileSync6(fd, `${process.pid}
3168
3190
  ${Date.now()}
3169
3191
  `);
3170
3192
  } catch {
@@ -3250,7 +3272,7 @@ function saveBlackboxState(state) {
3250
3272
  try {
3251
3273
  mkdirSync5(dirname4(BLACKBOX_STATE_FILE2), { recursive: true });
3252
3274
  const tmp = BLACKBOX_STATE_FILE2 + ".tmp";
3253
- writeFileSync5(tmp, JSON.stringify(state, null, 2) + "\n");
3275
+ writeFileSync6(tmp, JSON.stringify(state, null, 2) + "\n");
3254
3276
  renameSync5(tmp, BLACKBOX_STATE_FILE2);
3255
3277
  } catch (err) {
3256
3278
  console.error("[vibeOS] saveBlackboxState failed: " + err.message);
@@ -3411,7 +3433,7 @@ function updateGlobalLearning2(mutator) {
3411
3433
  next.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
3412
3434
  mkdirSync5(dirname4(GLOBAL_LEARNING_FILE2), { recursive: true });
3413
3435
  const tmp = GLOBAL_LEARNING_FILE2 + ".tmp";
3414
- writeFileSync5(tmp, JSON.stringify(next, null, 2));
3436
+ writeFileSync6(tmp, JSON.stringify(next, null, 2));
3415
3437
  renameSync5(tmp, GLOBAL_LEARNING_FILE2);
3416
3438
  return next;
3417
3439
  });
@@ -3449,7 +3471,7 @@ function saveProjectState2(state) {
3449
3471
  withFileLock3(PROJECT_STATE_FILE2, () => {
3450
3472
  mkdirSync5(dirname4(PROJECT_STATE_FILE2), { recursive: true });
3451
3473
  const _tmp = PROJECT_STATE_FILE2 + ".tmp." + Date.now();
3452
- writeFileSync5(_tmp, JSON.stringify(state, null, 2) + "\n", "utf-8");
3474
+ writeFileSync6(_tmp, JSON.stringify(state, null, 2) + "\n", "utf-8");
3453
3475
  renameSync5(_tmp, PROJECT_STATE_FILE2);
3454
3476
  });
3455
3477
  } catch (err) {
@@ -3712,7 +3734,7 @@ function researchAudit({ hours = 24, session: sessionFilter } = {}) {
3712
3734
  }
3713
3735
 
3714
3736
  // src/lib/reporting.js
3715
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync7, mkdirSync as mkdirSync6, statSync as statSync6, copyFileSync as copyFileSync5, rmSync as rmSync4 } from "node:fs";
3737
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, existsSync as existsSync7, mkdirSync as mkdirSync6, statSync as statSync6, copyFileSync as copyFileSync5, rmSync as rmSync4 } from "node:fs";
3716
3738
  import { join as join7, basename as basename6 } from "node:path";
3717
3739
  import { homedir as homedir8, tmpdir as tmpdir6 } from "node:os";
3718
3740
  var USER_HOME6 = (() => {
@@ -3761,7 +3783,7 @@ function saveReportsIndex(idx) {
3761
3783
  try {
3762
3784
  withFileLock(REPORTS_INDEX, () => {
3763
3785
  mkdirSync6(REPORTS_DIR2, { recursive: true });
3764
- writeFileSync6(REPORTS_INDEX, JSON.stringify(idx, null, 2) + "\n");
3786
+ writeFileSync7(REPORTS_INDEX, JSON.stringify(idx, null, 2) + "\n");
3765
3787
  });
3766
3788
  } catch (err) {
3767
3789
  console.error(`[vibeOS] reports index write failed: ${err.message}`);
@@ -3871,11 +3893,11 @@ function saveReport({ type = "manual", summary = "", findings = null, metrics =
3871
3893
  try {
3872
3894
  withFileLock(REPORTS_INDEX, () => {
3873
3895
  mkdirSync6(REPORTS_DIR2, { recursive: true });
3874
- writeFileSync6(join7(REPORTS_DIR2, `${id2}.json`), JSON.stringify(report, null, 2) + "\n");
3896
+ writeFileSync7(join7(REPORTS_DIR2, `${id2}.json`), JSON.stringify(report, null, 2) + "\n");
3875
3897
  const idx = reportsIndex();
3876
3898
  const _sum = (summary || "").slice(0, 80);
3877
3899
  idx.reports.push({ id: id2, type, project: report.meta.project, fingerprint: fp3, created: report.meta.created, summary: _sum });
3878
- writeFileSync6(REPORTS_INDEX, JSON.stringify(idx, null, 2) + "\n");
3900
+ writeFileSync7(REPORTS_INDEX, JSON.stringify(idx, null, 2) + "\n");
3879
3901
  });
3880
3902
  } catch (err) {
3881
3903
  console.error(`[vibeOS] report/index write failed: ${err.message}`);
@@ -3916,7 +3938,7 @@ function readReport(id2) {
3916
3938
  }
3917
3939
 
3918
3940
  // src/lib/credit-api.js
3919
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync7, existsSync as existsSync8 } from "node:fs";
3941
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync8, existsSync as existsSync8 } from "node:fs";
3920
3942
  import { join as join8 } from "node:path";
3921
3943
  function safeJsonParse4(raw) {
3922
3944
  try {
@@ -3983,7 +4005,7 @@ async function _snapshot() {
3983
4005
  }
3984
4006
  }
3985
4007
  try {
3986
- writeFileSync7(CREDIT_CACHE_F, JSON.stringify({ total, providers: provs, ts: Date.now() }));
4008
+ writeFileSync8(CREDIT_CACHE_F, JSON.stringify({ total, providers: provs, ts: Date.now() }));
3987
4009
  } catch {
3988
4010
  }
3989
4011
  }
@@ -4051,13 +4073,14 @@ function thinkingLevel(credit) {
4051
4073
  import { join as join9 } from "node:path";
4052
4074
  function createTrinityTool(deps) {
4053
4075
  return {
4054
- description: "Control the vibeOS plugin and active model slot. Use action='status' to see current state. Use action='enable' or 'disable' to toggle the plugin (takes effect immediately, no restart needed). Use action='set' with slot='brain'|'medium'|'cheap' to switch model tiers (writes opencode.json \u2014 active immediately). Use action='rebuild' to auto-detect available models from all configured providers and reassign brain/medium/cheap slots. Use action='flow' with slot='on'|'off' to toggle flow enforcer, or action='flow' alone for audit. Use action='flow' with slot='enforce' and level='on'|'off' to toggle auto-extract TODOs. Use action='enforce' with slot='on'|'off' to toggle delegation enforcement (blocks direct writes/edits on brain tier). Use action='tdd' with slot='on'|'off' to toggle auto-create test skeletons. Use action='tdd' with slot='strict' and level='on'|'off' to toggle strict failing TODO test templates. Use action='tdd' alone for audit. Use action='project' to show per-project analytics and optimization suggestions. Use action='patterns' to inspect learned project patterns or slot='clear' to clear them. Use action='guard' to ensure AGENTS.md and README.md exist and stay current. Call this when the user says things like 'switch to medium', 'use cheap model', 'disable plugin', 'trinity status'.",
4076
+ description: "Control the vibeOS plugin and active model slot. Use action='status' to see current state. Use action='enable' or 'disable' to toggle the plugin (takes effect immediately, no restart needed). Use action='set' with slot='brain'|'medium'|'cheap' to switch model tiers (writes opencode.json \u2014 active immediately). Use action='rebuild' to auto-detect available models from all configured providers and reassign brain/medium/cheap slots. Use action='flow' with slot='on'|'off' to toggle flow enforcer, or action='flow' alone for audit. Use action='flow' with slot='enforce' and level='on'|'off' to toggle auto-extract TODOs. Use action='enforce' with slot='on'|'off' to toggle delegation enforcement (blocks direct writes/edits on brain tier). Use action='tdd' with slot='on'|'off' to toggle auto-create test skeletons. Use action='tdd' with slot='strict' and level='on'|'off' to toggle strict failing TODO test templates. Use action='tdd' alone for audit. Use action='project' to show per-project analytics and optimization suggestions. Use action='patterns' to inspect learned project patterns or slot='clear' to clear them. Use action='guard' to ensure AGENTS.md and README.md exist and stay current. Use action='api-token' with token='<new_token>' to update the API token and re-enable remote control-vector. Call this when the user says things like 'switch to medium', 'use cheap model', 'disable plugin', 'trinity status'.",
4055
4077
  args: {
4056
- action: deps.tool.schema.enum(["status", "enable", "disable", "set", "mode", "thinking", "flow", "tdd", "project", "patterns", "rebuild", "diagnose", "help", "enforce", "repair-state", "blackbox", "report", "target", "guard"]).optional(),
4078
+ action: deps.tool.schema.enum(["status", "enable", "disable", "set", "mode", "thinking", "flow", "tdd", "project", "patterns", "rebuild", "diagnose", "help", "enforce", "repair-state", "blackbox", "report", "target", "guard", "api-token"]).optional(),
4057
4079
  slot: deps.tool.schema.enum(["brain", "medium", "cheap", "budget", "quality", "speed", "longrun", "auto", "on", "off", "enforce", "strict", "preview", "apply", "clear", "savings"]).optional(),
4058
- level: deps.tool.schema.enum(["full", "brief", "off", "on"]).optional()
4080
+ level: deps.tool.schema.enum(["full", "brief", "off", "on"]).optional(),
4081
+ token: deps.tool.schema.string().optional()
4059
4082
  },
4060
- async execute({ action, slot, level } = {}) {
4083
+ async execute({ action, slot, level, token } = {}) {
4061
4084
  if (typeof deps._lazyRefresh === "function")
4062
4085
  deps._lazyRefresh();
4063
4086
  if (!action)
@@ -4599,6 +4622,11 @@ ${L.repeat(40)}`);
4599
4622
  lines.push("README.md: auto-maintained feature documentation \u2014 keep it updated.");
4600
4623
  return lines.join("\n");
4601
4624
  }
4625
+ if (action === "api-token") {
4626
+ if (!token) return "Usage: trinity api-token <token>\nProvide a valid VIBEOS_API_TOKEN to enable remote control-vector computation.";
4627
+ deps.setApiToken(token);
4628
+ return "[vibeOS] API token updated. Remote API re-enabled.";
4629
+ }
4602
4630
  if (action === "rebuild") {
4603
4631
  const providers = deps._loadOpenCodeProviders();
4604
4632
  const auth = deps._readAuth();
@@ -4950,6 +4978,7 @@ ${L.repeat(40)}`);
4950
4978
  " trinity flow on/off Toggle flow enforcer (code quality checks)",
4951
4979
  " trinity tdd on/off Toggle auto test skeleton creation",
4952
4980
  " trinity guard Ensure AGENTS.md/README.md exist and are current",
4981
+ " trinity api-token Update VIBEOS_API_TOKEN and re-enable remote API",
4953
4982
  " trinity flow Show flow violations this session",
4954
4983
  "",
4955
4984
  "DIAGNOSTICS:",
@@ -5183,14 +5212,14 @@ import { join as join13 } from "node:path";
5183
5212
  import { homedir as homedir10, tmpdir as tmpdir7 } from "node:os";
5184
5213
 
5185
5214
  // src/lib/hooks/chat-transform.js
5186
- import { readFileSync as readFileSync11, writeFileSync as writeFileSync9, existsSync as existsSync10, mkdirSync as mkdirSync7 } from "node:fs";
5215
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync10, existsSync as existsSync10, mkdirSync as mkdirSync7 } from "node:fs";
5187
5216
  import { join as join12, basename as basename7 } from "node:path";
5188
5217
  import { homedir as homedir9 } from "node:os";
5189
5218
  import { createHash as createHash4 } from "node:crypto";
5190
5219
 
5191
5220
  // src/lib/index-helpers.js
5192
5221
  import { join as join11 } from "node:path";
5193
- import { writeFileSync as writeFileSync8 } from "node:fs";
5222
+ import { writeFileSync as writeFileSync9 } from "node:fs";
5194
5223
 
5195
5224
  // src/lib/text-compress.js
5196
5225
  var VERBOSE_LINE_RE = [
@@ -5526,7 +5555,7 @@ function recordSaving(tool2, reason, saveEst, meta = {}) {
5526
5555
  if (sd) {
5527
5556
  const sp = join11(sd, "delegation-state-hint.txt");
5528
5557
  try {
5529
- writeFileSync8(sp, JSON.stringify({ sid, total_savings: s.lifetime.total_savings_usd, last_reason: reason }), "utf8");
5558
+ writeFileSync9(sp, JSON.stringify({ sid, total_savings: s.lifetime.total_savings_usd, last_reason: reason }), "utf8");
5530
5559
  } catch {
5531
5560
  }
5532
5561
  }
@@ -5714,7 +5743,7 @@ function ensureProjectSkill(dir, fp22) {
5714
5743
  }
5715
5744
  try {
5716
5745
  mkdirSync7(skillDir, { recursive: true });
5717
- writeFileSync9(skillPath, content, "utf-8");
5746
+ writeFileSync10(skillPath, content, "utf-8");
5718
5747
  console.error(`[vibeOS] Project Guard: created .opencode/skills/${projectName}/SKILL.md`);
5719
5748
  return { created: true, path: skillPath, skipped: false };
5720
5749
  } catch (err) {
@@ -5778,7 +5807,7 @@ function syncControlSettings(cv) {
5778
5807
  const oc = safeJsonParse3(readFileSync11(OC_CONFIG, "utf-8"));
5779
5808
  if (oc.default_agent !== cv.agent_mode) {
5780
5809
  oc.default_agent = cv.agent_mode;
5781
- writeFileSync9(OC_CONFIG, JSON.stringify(oc, null, 2) + "\n");
5810
+ writeFileSync10(OC_CONFIG, JSON.stringify(oc, null, 2) + "\n");
5782
5811
  }
5783
5812
  }
5784
5813
  } catch {
@@ -5793,7 +5822,7 @@ function syncControlSettings(cv) {
5793
5822
  const oc = safeJsonParse3(readFileSync11(OC_CONFIG, "utf-8"));
5794
5823
  if (oc.default_agent === "plan") {
5795
5824
  oc.default_agent = "orchestrator";
5796
- writeFileSync9(OC_CONFIG, JSON.stringify(oc, null, 2) + "\n");
5825
+ writeFileSync10(OC_CONFIG, JSON.stringify(oc, null, 2) + "\n");
5797
5826
  }
5798
5827
  }
5799
5828
  } catch {
@@ -5828,7 +5857,7 @@ ${raw}
5828
5857
  try {
5829
5858
  ensureSessionScratchpadDirs();
5830
5859
  if (!existsSync10(fullPath)) {
5831
- writeFileSync9(fullPath, raw);
5860
+ writeFileSync10(fullPath, raw);
5832
5861
  indexAppend(hash, part.tool, raw.length);
5833
5862
  }
5834
5863
  } catch (err) {
@@ -6340,12 +6369,12 @@ async function _appendFooter(input, output, directory3) {
6340
6369
  }
6341
6370
 
6342
6371
  // src/lib/hooks/tool-execute.js
6343
- import { writeFileSync as writeFileSync11, appendFileSync as appendFileSync7, existsSync as existsSync12, mkdirSync as mkdirSync9 } from "node:fs";
6372
+ import { writeFileSync as writeFileSync12, appendFileSync as appendFileSync7, existsSync as existsSync12, mkdirSync as mkdirSync9 } from "node:fs";
6344
6373
  import { dirname as dirname6, basename as basename8 } from "node:path";
6345
6374
  init_flow_enforcer();
6346
6375
 
6347
6376
  // src/lib/tdd-enforcer.js
6348
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, appendFileSync as appendFileSync6, existsSync as existsSync11, mkdirSync as mkdirSync8, statSync as statSync7, readdirSync as readdirSync2, rmSync as rmSync5, openSync as openSync4 } from "node:fs";
6377
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync11, appendFileSync as appendFileSync6, existsSync as existsSync11, mkdirSync as mkdirSync8, statSync as statSync7, readdirSync as readdirSync2, rmSync as rmSync5, openSync as openSync4 } from "node:fs";
6349
6378
  import { join as join14, dirname as dirname5 } from "node:path";
6350
6379
  import { createHash as createHash5 } from "node:crypto";
6351
6380
 
@@ -7508,7 +7537,7 @@ function _recordCooldown(testPath) {
7508
7537
  appendFileSync6(ENFORCEMENT_COOLDOWN_FILE2, entry);
7509
7538
  const lines = readFileSync13(ENFORCEMENT_COOLDOWN_FILE2, "utf-8").trim().split("\n").filter(Boolean);
7510
7539
  if (lines.length > 500) {
7511
- writeFileSync10(ENFORCEMENT_COOLDOWN_FILE2, lines.slice(-200).join("\n") + "\n");
7540
+ writeFileSync11(ENFORCEMENT_COOLDOWN_FILE2, lines.slice(-200).join("\n") + "\n");
7512
7541
  }
7513
7542
  } catch {
7514
7543
  }
@@ -7595,7 +7624,7 @@ function enforceTestFile(filePath) {
7595
7624
  return null;
7596
7625
  try {
7597
7626
  mkdirSync8(skeleton.dir, { recursive: true });
7598
- writeFileSync10(skeleton.path, skeleton.content);
7627
+ writeFileSync11(skeleton.path, skeleton.content);
7599
7628
  _enforcementCooldown.add(skeleton.path);
7600
7629
  _recordCooldown(skeleton.path);
7601
7630
  try {
@@ -7884,7 +7913,7 @@ var onToolExecuteBefore = async (input, output) => {
7884
7913
  if (!existsSync12(CONTEXT7_INSTALL_FLAG)) {
7885
7914
  try {
7886
7915
  mkdirSync9(dirname6(CONTEXT7_INSTALL_FLAG), { recursive: true });
7887
- writeFileSync11(CONTEXT7_INSTALL_FLAG, "");
7916
+ writeFileSync12(CONTEXT7_INSTALL_FLAG, "");
7888
7917
  } catch {
7889
7918
  }
7890
7919
  console.error(`[vibeOS] \u{1F4A1} Install context7 MCP to save ~$0.06/turn on docs: \`claude mcp add context7 npx @upstash/context7-mcp\``);
@@ -8340,7 +8369,7 @@ function persistMcpPort(port) {
8340
8369
  tiers.selection.mcp_port = port;
8341
8370
  mkdirSync10(dirname7(TIERS_FILE2), { recursive: true });
8342
8371
  const tmp = TIERS_FILE2 + ".tmp." + Date.now();
8343
- writeFileSync12(tmp, JSON.stringify(tiers, null, 2) + "\n", "utf-8");
8372
+ writeFileSync13(tmp, JSON.stringify(tiers, null, 2) + "\n", "utf-8");
8344
8373
  renameSync6(tmp, TIERS_FILE2);
8345
8374
  } catch {
8346
8375
  }
@@ -8606,7 +8635,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
8606
8635
  if (_tiersData2.selection.mcp_port === void 0) _tiersData2.selection.mcp_port = 9578;
8607
8636
  mkdirSync10(dirname7(TIERS_FILE2), { recursive: true });
8608
8637
  const _tmp = TIERS_FILE2 + ".tmp." + Date.now();
8609
- writeFileSync12(_tmp, JSON.stringify(_tiersData2, null, 2) + "\n", "utf-8");
8638
+ writeFileSync13(_tmp, JSON.stringify(_tiersData2, null, 2) + "\n", "utf-8");
8610
8639
  renameSync6(_tmp, TIERS_FILE2);
8611
8640
  console.error(`[vibeOS] auto-synced model-tiers.json: brain=${_brain.id} medium=${_tiersData2.trinity?.medium?.oc || ""} cheap=${_tiersData2.trinity?.cheap?.oc || ""}`);
8612
8641
  const _tiersCfg = safeJsonParse3(readFileSync15(TIERS_FILE2, "utf-8"));
@@ -8630,7 +8659,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
8630
8659
  if (_mt.selection && (_mt.selection.mcp_port === void 0 || _mt.selection.mcp_port === null)) {
8631
8660
  _mt.selection.mcp_port = 9578;
8632
8661
  const _tmp = TIERS_FILE2 + ".tmp." + Date.now();
8633
- writeFileSync12(_tmp, JSON.stringify(_mt, null, 2) + "\n", "utf-8");
8662
+ writeFileSync13(_tmp, JSON.stringify(_mt, null, 2) + "\n", "utf-8");
8634
8663
  renameSync6(_tmp, TIERS_FILE2);
8635
8664
  }
8636
8665
  } catch {
@@ -8688,7 +8717,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
8688
8717
  directory: directory3,
8689
8718
  safeJsonParse: safeJsonParse3,
8690
8719
  readFileSync: readFileSync15,
8691
- writeFileSync: writeFileSync12,
8720
+ writeFileSync: writeFileSync13,
8692
8721
  existsSync: existsSync14,
8693
8722
  renameSync: renameSync6,
8694
8723
  TIERS_FILE: TIERS_FILE2,
@@ -8734,8 +8763,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
8734
8763
  backupFile,
8735
8764
  writeSessionSlot,
8736
8765
  _refreshModel,
8737
- writeSessionSlot,
8738
- _refreshModel,
8766
+ setApiToken,
8739
8767
  get _blackboxTracker() {
8740
8768
  return getBlackboxTracker();
8741
8769
  },