vibeostheog 0.15.7 → 0.15.9
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/CHANGELOG.md +8 -0
- package/package.json +1 -1
- package/src/index.js +148 -122
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## 0.15.9
|
|
2
|
+
- fix: VIBEOS_API_TOKEN lookup from __dirname, ~/.claude/, ~/, cwd/
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
## 0.15.8
|
|
6
|
+
- fix: load VIBEOS_API_TOKEN from .env.production if env var not set
|
|
7
|
+
|
|
8
|
+
|
|
1
9
|
## 0.15.7
|
|
2
10
|
- fix: auto mode now actually applies optimization mode from API response
|
|
3
11
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeostheog",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.9",
|
|
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
|
@@ -344,8 +344,8 @@ var init_flow_enforcer = __esm({
|
|
|
344
344
|
|
|
345
345
|
// src/index.ts
|
|
346
346
|
init_flow_enforcer();
|
|
347
|
-
import { readFileSync as
|
|
348
|
-
import { join as
|
|
347
|
+
import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, existsSync as existsSync15, mkdirSync as mkdirSync10, copyFileSync as copyFileSync6, renameSync as renameSync6 } from "node:fs";
|
|
348
|
+
import { join as join17, dirname as dirname8, basename as basename9 } from "node:path";
|
|
349
349
|
|
|
350
350
|
// src/vibeOS-lib/session-metrics.js
|
|
351
351
|
function formatDuration(totalSeconds) {
|
|
@@ -3230,9 +3230,9 @@ function applySlot2(slot) {
|
|
|
3230
3230
|
}
|
|
3231
3231
|
|
|
3232
3232
|
// src/lib/turn-classify.js
|
|
3233
|
-
import { readFileSync as
|
|
3234
|
-
import { join as
|
|
3235
|
-
import { homedir as
|
|
3233
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, appendFileSync as appendFileSync5, existsSync as existsSync6, mkdirSync as mkdirSync5, statSync as statSync6, copyFileSync as copyFileSync4, renameSync as renameSync5, openSync as openSync3, closeSync as closeSync3, rmSync as rmSync3 } from "node:fs";
|
|
3234
|
+
import { join as join7, dirname as dirname5, basename as basename5 } from "node:path";
|
|
3235
|
+
import { homedir as homedir6, tmpdir as tmpdir4 } from "node:os";
|
|
3236
3236
|
import { createHash as createHash3 } from "node:crypto";
|
|
3237
3237
|
|
|
3238
3238
|
// ../vibeOScore/client.js
|
|
@@ -3491,8 +3491,34 @@ var VibeOSNetworkError = class extends Error {
|
|
|
3491
3491
|
};
|
|
3492
3492
|
|
|
3493
3493
|
// src/lib/api-client.js
|
|
3494
|
+
import { readFileSync as readFileSync5 } from "node:fs";
|
|
3495
|
+
import { join as join6 } from "node:path";
|
|
3496
|
+
import { homedir as homedir5 } from "node:os";
|
|
3494
3497
|
var VIBEOS_API_URL = process.env.VIBEOS_API_URL || "https://api.vibetheog.com";
|
|
3495
|
-
var
|
|
3498
|
+
var _envToken2 = "";
|
|
3499
|
+
try {
|
|
3500
|
+
const env = readFileSync5(join6(process.cwd(), ".env.production"), "utf8");
|
|
3501
|
+
const m = env.match(/^VIBEOS_API_TOKEN=(.+)$/m);
|
|
3502
|
+
if (m) _envToken2 = m[1].trim();
|
|
3503
|
+
} catch {
|
|
3504
|
+
}
|
|
3505
|
+
if (!_envToken2) {
|
|
3506
|
+
try {
|
|
3507
|
+
const env = readFileSync5(join6(homedir5(), ".env.production"), "utf8");
|
|
3508
|
+
const m = env.match(/^VIBEOS_API_TOKEN=(.+)$/m);
|
|
3509
|
+
if (m) _envToken2 = m[1].trim();
|
|
3510
|
+
} catch {
|
|
3511
|
+
}
|
|
3512
|
+
}
|
|
3513
|
+
if (!_envToken2) {
|
|
3514
|
+
try {
|
|
3515
|
+
const env = readFileSync5(join6(homedir5(), ".claude", ".env.production"), "utf8");
|
|
3516
|
+
const m = env.match(/^VIBEOS_API_TOKEN=(.+)$/m);
|
|
3517
|
+
if (m) _envToken2 = m[1].trim();
|
|
3518
|
+
} catch {
|
|
3519
|
+
}
|
|
3520
|
+
}
|
|
3521
|
+
var VIBEOS_API_TOKEN = process.env.VIBEOS_API_TOKEN || _envToken2 || "";
|
|
3496
3522
|
var VIBEOS_API_ENABLED = process.env.VIBEOS_API_ENABLED !== "false" && !!VIBEOS_API_TOKEN;
|
|
3497
3523
|
var _apiClient = null;
|
|
3498
3524
|
var _apiFallbackMode = false;
|
|
@@ -3744,16 +3770,16 @@ var _BlackboxStub = class __BlackboxStub {
|
|
|
3744
3770
|
};
|
|
3745
3771
|
var USER_HOME4 = (() => {
|
|
3746
3772
|
try {
|
|
3747
|
-
return
|
|
3773
|
+
return homedir6();
|
|
3748
3774
|
} catch {
|
|
3749
3775
|
return tmpdir4();
|
|
3750
3776
|
}
|
|
3751
3777
|
})();
|
|
3752
|
-
var FILE_LOCK_DIR3 =
|
|
3753
|
-
var BLACKBOX_STATE_FILE2 =
|
|
3754
|
-
var GLOBAL_LEARNING_FILE2 =
|
|
3755
|
-
var STATE_FILE3 =
|
|
3756
|
-
var PROJECT_STATE_FILE2 =
|
|
3778
|
+
var FILE_LOCK_DIR3 = join7(USER_HOME4, ".claude/.vibeOS-locks");
|
|
3779
|
+
var BLACKBOX_STATE_FILE2 = join7(USER_HOME4, ".claude/blackbox-state.json");
|
|
3780
|
+
var GLOBAL_LEARNING_FILE2 = join7(USER_HOME4, ".claude/global-learning.json");
|
|
3781
|
+
var STATE_FILE3 = join7(USER_HOME4, ".claude/delegation-state.json");
|
|
3782
|
+
var PROJECT_STATE_FILE2 = join7(USER_HOME4, ".claude/project-states.json");
|
|
3757
3783
|
var DFLT_GL2 = { exploratory_words: {}, task_first_words: {}, updatedAt: null };
|
|
3758
3784
|
var _blackboxTracker = null;
|
|
3759
3785
|
var _OC_SID2 = "opencode-" + (process.pid || "x") + "-" + Date.now();
|
|
@@ -3768,14 +3794,14 @@ var WARN_MAX_PER_SESSION = 3;
|
|
|
3768
3794
|
var WARN_COALESCE_THRESHOLD = 10;
|
|
3769
3795
|
var warnCoalesceCounters = /* @__PURE__ */ new Map();
|
|
3770
3796
|
function _handleStateCorruption4(path) {
|
|
3771
|
-
const backupDir =
|
|
3797
|
+
const backupDir = join7(USER_HOME4, ".claude", ".backups");
|
|
3772
3798
|
mkdirSync5(backupDir, { recursive: true });
|
|
3773
|
-
const backupPath =
|
|
3799
|
+
const backupPath = join7(backupDir, basename5(path) + ".corrupted." + Date.now());
|
|
3774
3800
|
try {
|
|
3775
3801
|
copyFileSync4(path, backupPath);
|
|
3776
3802
|
} catch {
|
|
3777
3803
|
}
|
|
3778
|
-
const logPath =
|
|
3804
|
+
const logPath = join7(USER_HOME4, ".claude", ".state-corruption-log.jsonl");
|
|
3779
3805
|
try {
|
|
3780
3806
|
appendFileSync5(logPath, JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), path, backup: backupPath }) + "\n");
|
|
3781
3807
|
} catch {
|
|
@@ -3783,7 +3809,7 @@ function _handleStateCorruption4(path) {
|
|
|
3783
3809
|
}
|
|
3784
3810
|
function _lockPathFor3(filePath) {
|
|
3785
3811
|
const hash = createHash3("sha1").update(String(filePath || "")).digest("hex");
|
|
3786
|
-
return
|
|
3812
|
+
return join7(FILE_LOCK_DIR3, `${hash}.lock`);
|
|
3787
3813
|
}
|
|
3788
3814
|
function withFileLock3(filePath, fn, opts = {}) {
|
|
3789
3815
|
const staleMs = Number(opts.staleMs || 3e4);
|
|
@@ -3838,7 +3864,7 @@ function readJsonOrEmpty2(filePath) {
|
|
|
3838
3864
|
_handleStateCorruption4(filePath);
|
|
3839
3865
|
return {};
|
|
3840
3866
|
}
|
|
3841
|
-
return safeJsonParse3(
|
|
3867
|
+
return safeJsonParse3(readFileSync6(filePath, "utf-8"));
|
|
3842
3868
|
} catch {
|
|
3843
3869
|
_handleStateCorruption4(filePath);
|
|
3844
3870
|
return {};
|
|
@@ -3846,10 +3872,10 @@ function readJsonOrEmpty2(filePath) {
|
|
|
3846
3872
|
}
|
|
3847
3873
|
function loadTrinityModels() {
|
|
3848
3874
|
try {
|
|
3849
|
-
const p =
|
|
3875
|
+
const p = join7(USER_HOME4, ".claude/model-tiers.json");
|
|
3850
3876
|
if (!existsSync6(p))
|
|
3851
3877
|
return { brain: "", cheap: "", medium: "" };
|
|
3852
|
-
const j = safeJsonParse3(
|
|
3878
|
+
const j = safeJsonParse3(readFileSync6(p, "utf-8"));
|
|
3853
3879
|
return {
|
|
3854
3880
|
brain: j?.trinity?.brain?.oc || j?.trinity?.brain || "",
|
|
3855
3881
|
cheap: j?.trinity?.cheap?.oc || j?.trinity?.cheap || "",
|
|
@@ -3871,7 +3897,7 @@ function loadBlackboxState() {
|
|
|
3871
3897
|
_handleStateCorruption4(BLACKBOX_STATE_FILE2);
|
|
3872
3898
|
return { enabled: false, sessions: {} };
|
|
3873
3899
|
}
|
|
3874
|
-
return safeJsonParse3(
|
|
3900
|
+
return safeJsonParse3(readFileSync6(BLACKBOX_STATE_FILE2, "utf-8")) || { enabled: false, sessions: {} };
|
|
3875
3901
|
} catch {
|
|
3876
3902
|
_handleStateCorruption4(BLACKBOX_STATE_FILE2);
|
|
3877
3903
|
return { enabled: false, sessions: {} };
|
|
@@ -4024,7 +4050,7 @@ function loadGlobalLearning2() {
|
|
|
4024
4050
|
_handleStateCorruption4(GLOBAL_LEARNING_FILE2);
|
|
4025
4051
|
return DFLT_GL2;
|
|
4026
4052
|
}
|
|
4027
|
-
const j = safeJsonParse3(
|
|
4053
|
+
const j = safeJsonParse3(readFileSync6(GLOBAL_LEARNING_FILE2, "utf-8"));
|
|
4028
4054
|
if (!j || typeof j !== "object")
|
|
4029
4055
|
return DFLT_GL2;
|
|
4030
4056
|
j.exploratory_words ??= {};
|
|
@@ -4090,9 +4116,9 @@ function saveProjectState2(state) {
|
|
|
4090
4116
|
function detectTechStack2(dir) {
|
|
4091
4117
|
const stacks = [];
|
|
4092
4118
|
try {
|
|
4093
|
-
const pkg = safeJsonParse3(
|
|
4119
|
+
const pkg = safeJsonParse3(readFileSync6(join7(dir, "package.json"), "utf-8"));
|
|
4094
4120
|
if (pkg) {
|
|
4095
|
-
if (pkg.devDependencies?.typescript || pkg.dependencies?.typescript || existsSync6(
|
|
4121
|
+
if (pkg.devDependencies?.typescript || pkg.dependencies?.typescript || existsSync6(join7(dir, "tsconfig.json")))
|
|
4096
4122
|
stacks.push("typescript");
|
|
4097
4123
|
if (pkg.dependencies?.react || pkg.devDependencies?.react)
|
|
4098
4124
|
stacks.push("react");
|
|
@@ -4101,21 +4127,21 @@ function detectTechStack2(dir) {
|
|
|
4101
4127
|
} catch {
|
|
4102
4128
|
}
|
|
4103
4129
|
try {
|
|
4104
|
-
if (existsSync6(
|
|
4130
|
+
if (existsSync6(join7(dir, "Cargo.toml")))
|
|
4105
4131
|
stacks.push("rust");
|
|
4106
4132
|
} catch {
|
|
4107
4133
|
}
|
|
4108
4134
|
try {
|
|
4109
|
-
if (existsSync6(
|
|
4135
|
+
if (existsSync6(join7(dir, "go.mod")))
|
|
4110
4136
|
stacks.push("go");
|
|
4111
4137
|
} catch {
|
|
4112
4138
|
}
|
|
4113
4139
|
try {
|
|
4114
|
-
if (existsSync6(
|
|
4140
|
+
if (existsSync6(join7(dir, "requirements.txt")))
|
|
4115
4141
|
stacks.push("python");
|
|
4116
|
-
if (existsSync6(
|
|
4142
|
+
if (existsSync6(join7(dir, "setup.py")))
|
|
4117
4143
|
stacks.push("python");
|
|
4118
|
-
if (existsSync6(
|
|
4144
|
+
if (existsSync6(join7(dir, "pyproject.toml")))
|
|
4119
4145
|
stacks.push("python");
|
|
4120
4146
|
} catch {
|
|
4121
4147
|
}
|
|
@@ -4223,30 +4249,30 @@ function saveOptimizationMode(mode) {
|
|
|
4223
4249
|
}
|
|
4224
4250
|
|
|
4225
4251
|
// src/lib/research-audit.js
|
|
4226
|
-
import { readFileSync as
|
|
4227
|
-
import { join as
|
|
4228
|
-
import { homedir as
|
|
4252
|
+
import { readFileSync as readFileSync7, existsSync as existsSync7 } from "node:fs";
|
|
4253
|
+
import { join as join8 } from "node:path";
|
|
4254
|
+
import { homedir as homedir7, tmpdir as tmpdir5 } from "node:os";
|
|
4229
4255
|
var USER_HOME5 = (() => {
|
|
4230
4256
|
try {
|
|
4231
|
-
return
|
|
4257
|
+
return homedir7();
|
|
4232
4258
|
} catch {
|
|
4233
4259
|
return tmpdir5();
|
|
4234
4260
|
}
|
|
4235
4261
|
})();
|
|
4236
4262
|
var _OC_SID3 = "opencode-" + (process.pid || "x") + "-" + Date.now();
|
|
4237
|
-
var SCRATCHPAD_ROOT2 =
|
|
4238
|
-
var SCRATCHPAD_GLOBAL_DIR2 =
|
|
4239
|
-
var SCRATCHPAD_SESSIONS_DIR2 =
|
|
4240
|
-
var STATE_FILE4 =
|
|
4263
|
+
var SCRATCHPAD_ROOT2 = join8(USER_HOME5, ".claude/scratch");
|
|
4264
|
+
var SCRATCHPAD_GLOBAL_DIR2 = join8(SCRATCHPAD_ROOT2, "by-hash");
|
|
4265
|
+
var SCRATCHPAD_SESSIONS_DIR2 = join8(SCRATCHPAD_ROOT2, "sessions");
|
|
4266
|
+
var STATE_FILE4 = join8(USER_HOME5, ".claude/delegation-state.json");
|
|
4241
4267
|
var currentModel2 = null;
|
|
4242
4268
|
function getSessionRoot2() {
|
|
4243
|
-
return
|
|
4269
|
+
return join8(SCRATCHPAD_SESSIONS_DIR2, _OC_SID3);
|
|
4244
4270
|
}
|
|
4245
4271
|
function getSessionScratchpadDir2() {
|
|
4246
|
-
return
|
|
4272
|
+
return join8(getSessionRoot2(), "by-hash");
|
|
4247
4273
|
}
|
|
4248
4274
|
function getGlobalIndexPath2() {
|
|
4249
|
-
return
|
|
4275
|
+
return join8(SCRATCHPAD_ROOT2, "index.jsonl");
|
|
4250
4276
|
}
|
|
4251
4277
|
var FETCH_TOOLS = /* @__PURE__ */ new Set(["WebFetch", "WebSearch", "webfetch", "websearch"]);
|
|
4252
4278
|
function researchAudit({ hours = 24, session: sessionFilter } = {}) {
|
|
@@ -4255,7 +4281,7 @@ function researchAudit({ hours = 24, session: sessionFilter } = {}) {
|
|
|
4255
4281
|
try {
|
|
4256
4282
|
const indexPath = getGlobalIndexPath2();
|
|
4257
4283
|
if (existsSync7(indexPath)) {
|
|
4258
|
-
const lines =
|
|
4284
|
+
const lines = readFileSync7(indexPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
4259
4285
|
const domainCache = {};
|
|
4260
4286
|
for (const line of lines) {
|
|
4261
4287
|
const e = JSON.parse(line);
|
|
@@ -4269,11 +4295,11 @@ function researchAudit({ hours = 24, session: sessionFilter } = {}) {
|
|
|
4269
4295
|
report.totalFetches++;
|
|
4270
4296
|
report.totalBytes += e.size || 0;
|
|
4271
4297
|
const hash = e.hash;
|
|
4272
|
-
const summaryPathSession =
|
|
4273
|
-
const summaryPathGlobal =
|
|
4298
|
+
const summaryPathSession = join8(getSessionScratchpadDir2(), hash + ".summary.txt");
|
|
4299
|
+
const summaryPathGlobal = join8(SCRATCHPAD_GLOBAL_DIR2, hash + ".summary.txt");
|
|
4274
4300
|
const summaryPath = existsSync7(summaryPathSession) ? summaryPathSession : summaryPathGlobal;
|
|
4275
4301
|
if (existsSync7(summaryPath)) {
|
|
4276
|
-
const summary =
|
|
4302
|
+
const summary = readFileSync7(summaryPath, "utf-8").slice(0, 200);
|
|
4277
4303
|
const urlMatch = summary.match(/https?:\/\/([^\/\s\)]+)/i);
|
|
4278
4304
|
const queryMatch = summary.match(/"query":"([^"]+)"/);
|
|
4279
4305
|
let domain;
|
|
@@ -4320,7 +4346,7 @@ function researchAudit({ hours = 24, session: sessionFilter } = {}) {
|
|
|
4320
4346
|
}
|
|
4321
4347
|
try {
|
|
4322
4348
|
if (existsSync7(STATE_FILE4)) {
|
|
4323
|
-
const state = safeJsonParse3(
|
|
4349
|
+
const state = safeJsonParse3(readFileSync7(STATE_FILE4, "utf-8"));
|
|
4324
4350
|
for (const [sid, s] of Object.entries(state.sessions || {})) {
|
|
4325
4351
|
if (sessionFilter && sid !== sessionFilter)
|
|
4326
4352
|
continue;
|
|
@@ -4343,25 +4369,25 @@ function researchAudit({ hours = 24, session: sessionFilter } = {}) {
|
|
|
4343
4369
|
}
|
|
4344
4370
|
|
|
4345
4371
|
// src/lib/reporting.js
|
|
4346
|
-
import { readFileSync as
|
|
4347
|
-
import { join as
|
|
4348
|
-
import { homedir as
|
|
4372
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync8, mkdirSync as mkdirSync6, statSync as statSync7, copyFileSync as copyFileSync5, rmSync as rmSync4 } from "node:fs";
|
|
4373
|
+
import { join as join9, basename as basename6 } from "node:path";
|
|
4374
|
+
import { homedir as homedir8, tmpdir as tmpdir6 } from "node:os";
|
|
4349
4375
|
var USER_HOME6 = (() => {
|
|
4350
4376
|
try {
|
|
4351
|
-
return
|
|
4377
|
+
return homedir8();
|
|
4352
4378
|
} catch {
|
|
4353
4379
|
return tmpdir6();
|
|
4354
4380
|
}
|
|
4355
4381
|
})();
|
|
4356
|
-
var REPORTS_DIR2 =
|
|
4357
|
-
var REPORTS_INDEX =
|
|
4382
|
+
var REPORTS_DIR2 = join9(USER_HOME6, ".claude/reports");
|
|
4383
|
+
var REPORTS_INDEX = join9(REPORTS_DIR2, "index.json");
|
|
4358
4384
|
var _OC_SID4 = "opencode-" + (process.pid || "x") + "-" + Date.now();
|
|
4359
4385
|
var currentProjectFingerprint3 = "";
|
|
4360
4386
|
var currentProjectName2 = "";
|
|
4361
4387
|
function _handleStateCorruption5(path) {
|
|
4362
|
-
const backupDir =
|
|
4388
|
+
const backupDir = join9(USER_HOME6, ".claude", ".backups");
|
|
4363
4389
|
mkdirSync6(backupDir, { recursive: true });
|
|
4364
|
-
const backupPath =
|
|
4390
|
+
const backupPath = join9(backupDir, basename6(path) + ".corrupted." + Date.now());
|
|
4365
4391
|
try {
|
|
4366
4392
|
copyFileSync5(path, backupPath);
|
|
4367
4393
|
} catch {
|
|
@@ -4376,7 +4402,7 @@ function readJsonOrEmpty3(filePath) {
|
|
|
4376
4402
|
_handleStateCorruption5(filePath);
|
|
4377
4403
|
return {};
|
|
4378
4404
|
}
|
|
4379
|
-
return safeJsonParse3(
|
|
4405
|
+
return safeJsonParse3(readFileSync8(filePath, "utf-8"));
|
|
4380
4406
|
} catch {
|
|
4381
4407
|
_handleStateCorruption5(filePath);
|
|
4382
4408
|
return {};
|
|
@@ -4431,7 +4457,7 @@ function _pruneReports() {
|
|
|
4431
4457
|
continue;
|
|
4432
4458
|
if (now - created > 90 * 24 * 3600 * 1e3) {
|
|
4433
4459
|
try {
|
|
4434
|
-
rmSync4(
|
|
4460
|
+
rmSync4(join9(REPORTS_DIR2, `${r.id}.json`));
|
|
4435
4461
|
} catch {
|
|
4436
4462
|
}
|
|
4437
4463
|
continue;
|
|
@@ -4502,7 +4528,7 @@ function saveReport({ type = "manual", summary = "", findings = null, metrics =
|
|
|
4502
4528
|
try {
|
|
4503
4529
|
withFileLock(REPORTS_INDEX, () => {
|
|
4504
4530
|
mkdirSync6(REPORTS_DIR2, { recursive: true });
|
|
4505
|
-
writeFileSync6(
|
|
4531
|
+
writeFileSync6(join9(REPORTS_DIR2, `${id2}.json`), JSON.stringify(report, null, 2) + "\n");
|
|
4506
4532
|
const idx = reportsIndex();
|
|
4507
4533
|
const _sum = (summary || "").slice(0, 80);
|
|
4508
4534
|
idx.reports.push({ id: id2, type, project: report.meta.project, fingerprint: fp3, created: report.meta.created, summary: _sum });
|
|
@@ -4536,19 +4562,19 @@ function readReport(id2) {
|
|
|
4536
4562
|
return null;
|
|
4537
4563
|
if (!/^[\w-]+$/.test(String(id2)))
|
|
4538
4564
|
return null;
|
|
4539
|
-
const path =
|
|
4565
|
+
const path = join9(REPORTS_DIR2, `${id2}.json`);
|
|
4540
4566
|
try {
|
|
4541
4567
|
if (!existsSync8(path))
|
|
4542
4568
|
return null;
|
|
4543
|
-
return safeJsonParse3(
|
|
4569
|
+
return safeJsonParse3(readFileSync8(path, "utf-8"));
|
|
4544
4570
|
} catch {
|
|
4545
4571
|
return null;
|
|
4546
4572
|
}
|
|
4547
4573
|
}
|
|
4548
4574
|
|
|
4549
4575
|
// src/lib/credit-api.js
|
|
4550
|
-
import { readFileSync as
|
|
4551
|
-
import { join as
|
|
4576
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync7, existsSync as existsSync9 } from "node:fs";
|
|
4577
|
+
import { join as join10 } from "node:path";
|
|
4552
4578
|
function safeJsonParse4(raw) {
|
|
4553
4579
|
try {
|
|
4554
4580
|
return JSON.parse(raw);
|
|
@@ -4579,7 +4605,7 @@ var BALANCE_APIS = {
|
|
|
4579
4605
|
var _creditTimer = null;
|
|
4580
4606
|
function _readAuth() {
|
|
4581
4607
|
try {
|
|
4582
|
-
return existsSync9(AUTH_F) ? safeJsonParse4(
|
|
4608
|
+
return existsSync9(AUTH_F) ? safeJsonParse4(readFileSync9(AUTH_F, "utf-8")) : {};
|
|
4583
4609
|
} catch {
|
|
4584
4610
|
return {};
|
|
4585
4611
|
}
|
|
@@ -4622,14 +4648,14 @@ function _cachedPct() {
|
|
|
4622
4648
|
try {
|
|
4623
4649
|
if (!existsSync9(CREDIT_CACHE_F))
|
|
4624
4650
|
return null;
|
|
4625
|
-
const s = safeJsonParse4(
|
|
4651
|
+
const s = safeJsonParse4(readFileSync9(CREDIT_CACHE_F, "utf-8"));
|
|
4626
4652
|
if (s?.total == null || !s.ts)
|
|
4627
4653
|
return null;
|
|
4628
4654
|
let budget = 50;
|
|
4629
4655
|
try {
|
|
4630
|
-
const p =
|
|
4656
|
+
const p = join10(USER_HOME2, ".claude/model-tiers.json");
|
|
4631
4657
|
if (existsSync9(p)) {
|
|
4632
|
-
const j = safeJsonParse4(
|
|
4658
|
+
const j = safeJsonParse4(readFileSync9(p, "utf-8"));
|
|
4633
4659
|
if (j?.selection?.monthly_budget_usd)
|
|
4634
4660
|
budget = j.selection.monthly_budget_usd;
|
|
4635
4661
|
}
|
|
@@ -4660,9 +4686,9 @@ function loadCredit() {
|
|
|
4660
4686
|
return n;
|
|
4661
4687
|
}
|
|
4662
4688
|
try {
|
|
4663
|
-
const f =
|
|
4689
|
+
const f = join10(USER_HOME2, ".claude/credit-percent");
|
|
4664
4690
|
if (existsSync9(f)) {
|
|
4665
|
-
const n = parseInt(
|
|
4691
|
+
const n = parseInt(readFileSync9(f, "utf-8").trim(), 10);
|
|
4666
4692
|
if (!isNaN(n))
|
|
4667
4693
|
return n;
|
|
4668
4694
|
}
|
|
@@ -4679,7 +4705,7 @@ function thinkingLevel(credit) {
|
|
|
4679
4705
|
}
|
|
4680
4706
|
|
|
4681
4707
|
// src/lib/trinity-tool.js
|
|
4682
|
-
import { join as
|
|
4708
|
+
import { join as join11 } from "node:path";
|
|
4683
4709
|
function createTrinityTool(deps) {
|
|
4684
4710
|
return {
|
|
4685
4711
|
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'.",
|
|
@@ -4934,7 +4960,7 @@ Lock is per-session (resets on restart).`;
|
|
|
4934
4960
|
const ok = deps.writeSelection("tdd_enforce", slot === "on");
|
|
4935
4961
|
return ok ? `\u2705 TDD enforcement ${slot === "on" ? "ENABLED (auto-create skeletons)" : "DISABLED (nudge only)"}` : `\u274C Failed to write model-tiers.json`;
|
|
4936
4962
|
}
|
|
4937
|
-
const stateFile =
|
|
4963
|
+
const stateFile = join11(deps.USER_HOME, ".claude/delegation-state.json");
|
|
4938
4964
|
let enforced = 0;
|
|
4939
4965
|
try {
|
|
4940
4966
|
if (deps.existsSync(stateFile)) {
|
|
@@ -5314,7 +5340,7 @@ ${L.repeat(40)}`);
|
|
|
5314
5340
|
}
|
|
5315
5341
|
if (action === "diagnose") {
|
|
5316
5342
|
const results = [];
|
|
5317
|
-
const ocConfig =
|
|
5343
|
+
const ocConfig = join11(deps.USER_HOME, ".config/opencode/opencode.json");
|
|
5318
5344
|
const checks = [
|
|
5319
5345
|
{ path: deps.TIERS_FILE, label: "model-tiers.json" },
|
|
5320
5346
|
{ path: ocConfig, label: "opencode.json" },
|
|
@@ -5486,7 +5512,7 @@ ${L.repeat(40)}`);
|
|
|
5486
5512
|
for (const r of idx.reports || []) {
|
|
5487
5513
|
if (r.project !== name || r.fingerprint !== dstFp)
|
|
5488
5514
|
continue;
|
|
5489
|
-
const rf =
|
|
5515
|
+
const rf = join11(deps.REPORTS_DIR, `${r.id}.json`);
|
|
5490
5516
|
try {
|
|
5491
5517
|
if (!deps.existsSync(rf))
|
|
5492
5518
|
continue;
|
|
@@ -5605,8 +5631,8 @@ ${L.repeat(40)}`);
|
|
|
5605
5631
|
}
|
|
5606
5632
|
|
|
5607
5633
|
// src/lib/trinity-rebuild.js
|
|
5608
|
-
import { readFileSync as
|
|
5609
|
-
import { join as
|
|
5634
|
+
import { readFileSync as readFileSync10, existsSync as existsSync10 } from "node:fs";
|
|
5635
|
+
import { join as join12 } from "node:path";
|
|
5610
5636
|
var MODEL_RANK = { high: 3, mid: 2, budget: 1 };
|
|
5611
5637
|
var OPENCODE_GO_CATALOG = [
|
|
5612
5638
|
"deepseek/deepseek-v4-flash",
|
|
@@ -5809,17 +5835,17 @@ async function probeModel(modelId, auth) {
|
|
|
5809
5835
|
}
|
|
5810
5836
|
|
|
5811
5837
|
// src/lib/hooks/footer.js
|
|
5812
|
-
import { readFileSync as
|
|
5813
|
-
import { join as
|
|
5814
|
-
import { homedir as
|
|
5838
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
5839
|
+
import { join as join15 } from "node:path";
|
|
5840
|
+
import { homedir as homedir9, tmpdir as tmpdir7 } from "node:os";
|
|
5815
5841
|
|
|
5816
5842
|
// src/lib/hooks/chat-transform.js
|
|
5817
|
-
import { readFileSync as
|
|
5818
|
-
import { join as
|
|
5843
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync9, existsSync as existsSync11, mkdirSync as mkdirSync7 } from "node:fs";
|
|
5844
|
+
import { join as join14, basename as basename7 } from "node:path";
|
|
5819
5845
|
import { createHash as createHash4 } from "node:crypto";
|
|
5820
5846
|
|
|
5821
5847
|
// src/lib/index-helpers.js
|
|
5822
|
-
import { join as
|
|
5848
|
+
import { join as join13 } from "node:path";
|
|
5823
5849
|
import { writeFileSync as writeFileSync8 } from "node:fs";
|
|
5824
5850
|
|
|
5825
5851
|
// src/lib/text-compress.js
|
|
@@ -6154,7 +6180,7 @@ function recordSaving(tool2, reason, saveEst, meta = {}) {
|
|
|
6154
6180
|
try {
|
|
6155
6181
|
const sd = getSessionScratchpadDir();
|
|
6156
6182
|
if (sd) {
|
|
6157
|
-
const sp =
|
|
6183
|
+
const sp = join13(sd, "delegation-state-hint.txt");
|
|
6158
6184
|
try {
|
|
6159
6185
|
writeFileSync8(sp, JSON.stringify({ sid, total_savings: s.lifetime.total_savings_usd, last_reason: reason }), "utf8");
|
|
6160
6186
|
} catch {
|
|
@@ -6283,10 +6309,10 @@ function buildProjectBriefing(directory3) {
|
|
|
6283
6309
|
return `[project memory] Active project: ${label}. Stay focused on the current repository and prefer the existing workflow.`;
|
|
6284
6310
|
}
|
|
6285
6311
|
function ensureProjectSkill(dir, fp3) {
|
|
6286
|
-
const skillsDir =
|
|
6312
|
+
const skillsDir = join14(dir, ".opencode", "skills");
|
|
6287
6313
|
const projectName = basename7(dir);
|
|
6288
|
-
const skillDir =
|
|
6289
|
-
const skillPath =
|
|
6314
|
+
const skillDir = join14(skillsDir, projectName);
|
|
6315
|
+
const skillPath = join14(skillDir, "SKILL.md");
|
|
6290
6316
|
if (existsSync11(skillPath)) {
|
|
6291
6317
|
return { created: false, skipped: true, path: skillPath };
|
|
6292
6318
|
}
|
|
@@ -6443,7 +6469,7 @@ var onMessagesTransform = async (_input, output) => {
|
|
|
6443
6469
|
const hash = createHash4("sha256").update(`tool_result
|
|
6444
6470
|
${raw}
|
|
6445
6471
|
`).digest("hex").slice(0, 16);
|
|
6446
|
-
const fullPath =
|
|
6472
|
+
const fullPath = join14(getSessionScratchpadDir(), `${hash}.txt`);
|
|
6447
6473
|
try {
|
|
6448
6474
|
ensureSessionScratchpadDirs();
|
|
6449
6475
|
if (!existsSync11(fullPath)) {
|
|
@@ -6617,7 +6643,7 @@ var onSystemTransform = async (_input, output) => {
|
|
|
6617
6643
|
const mediumModel = TRINITY_MEDIUM || "the medium model";
|
|
6618
6644
|
let brainModel = "(brain)";
|
|
6619
6645
|
try {
|
|
6620
|
-
brainModel = safeJsonParse3(
|
|
6646
|
+
brainModel = safeJsonParse3(readFileSync11(TIERS_FILE2, "utf-8")).trinity?.brain?.oc || brainModel;
|
|
6621
6647
|
} catch {
|
|
6622
6648
|
}
|
|
6623
6649
|
const targetModel = tierBias === "cheap" ? cheapModel : tierBias === "medium" ? mediumModel : tierBias === "brain" ? brainModel : `${cheapModel} or ${mediumModel}`;
|
|
@@ -6668,7 +6694,7 @@ var onSystemTransform = async (_input, output) => {
|
|
|
6668
6694
|
const sel2 = loadSelection();
|
|
6669
6695
|
let tiers = {};
|
|
6670
6696
|
try {
|
|
6671
|
-
tiers = safeJsonParse3(
|
|
6697
|
+
tiers = safeJsonParse3(readFileSync11(TIERS_FILE2, "utf-8")).trinity || {};
|
|
6672
6698
|
} catch {
|
|
6673
6699
|
}
|
|
6674
6700
|
const active = sel2.active_slot || "medium";
|
|
@@ -6710,19 +6736,19 @@ async function apiAutoSelectMode(regime, stress) {
|
|
|
6710
6736
|
}
|
|
6711
6737
|
var USER_HOME7 = (() => {
|
|
6712
6738
|
try {
|
|
6713
|
-
return
|
|
6739
|
+
return homedir9();
|
|
6714
6740
|
} catch {
|
|
6715
6741
|
return tmpdir7();
|
|
6716
6742
|
}
|
|
6717
6743
|
})();
|
|
6718
|
-
var STATE_FILE5 =
|
|
6719
|
-
var SAVINGS_LEDGER_FILE2 =
|
|
6744
|
+
var STATE_FILE5 = join15(USER_HOME7, ".claude/delegation-state.json");
|
|
6745
|
+
var SAVINGS_LEDGER_FILE2 = join15(USER_HOME7, ".claude/savings-ledger.jsonl");
|
|
6720
6746
|
var _prevOutputText = "";
|
|
6721
6747
|
var _autoReportCount = 0;
|
|
6722
6748
|
var textCompletePainted = /* @__PURE__ */ new Set();
|
|
6723
6749
|
function loadSelection3() {
|
|
6724
6750
|
try {
|
|
6725
|
-
const raw =
|
|
6751
|
+
const raw = readFileSync12(join15(USER_HOME7, ".claude/model-tiers.json"), "utf-8");
|
|
6726
6752
|
return safeJsonParse3(raw)?.selection || { active_slot: "medium", enabled: true, delegation_enforce: false, flow_enabled: false, flow_enforce: false, tdd_enforce: false, tdd_strict: false };
|
|
6727
6753
|
} catch {
|
|
6728
6754
|
return { active_slot: "medium", enabled: true, delegation_enforce: false, flow_enabled: false, flow_enforce: false, tdd_enforce: false, tdd_strict: false };
|
|
@@ -6731,7 +6757,7 @@ function loadSelection3() {
|
|
|
6731
6757
|
function readLifetimeSavings2() {
|
|
6732
6758
|
try {
|
|
6733
6759
|
reconcileStateFromLedger();
|
|
6734
|
-
const raw =
|
|
6760
|
+
const raw = readFileSync12(STATE_FILE5, "utf-8");
|
|
6735
6761
|
const state = safeJsonParse3(raw);
|
|
6736
6762
|
const ses = state?.sessions?.[typeof _OC_SID6 !== "undefined" ? _OC_SID6 : ""] || {};
|
|
6737
6763
|
return {
|
|
@@ -6961,8 +6987,8 @@ import { dirname as dirname7, basename as basename8 } from "node:path";
|
|
|
6961
6987
|
init_flow_enforcer();
|
|
6962
6988
|
|
|
6963
6989
|
// src/lib/tdd-enforcer.js
|
|
6964
|
-
import { readFileSync as
|
|
6965
|
-
import { join as
|
|
6990
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, appendFileSync as appendFileSync6, existsSync as existsSync12, mkdirSync as mkdirSync8, statSync as statSync8, readdirSync as readdirSync2, rmSync as rmSync5, openSync as openSync4 } from "node:fs";
|
|
6991
|
+
import { join as join16, dirname as dirname6 } from "node:path";
|
|
6966
6992
|
import { createHash as createHash5 } from "node:crypto";
|
|
6967
6993
|
|
|
6968
6994
|
// src/utils/tdd-helpers.js
|
|
@@ -8001,9 +8027,9 @@ function _detectTestFramework() {
|
|
|
8001
8027
|
let testExt = null;
|
|
8002
8028
|
try {
|
|
8003
8029
|
const root = directory || process.cwd();
|
|
8004
|
-
const pkgPath =
|
|
8030
|
+
const pkgPath = join16(root, "package.json");
|
|
8005
8031
|
if (existsSync12(pkgPath)) {
|
|
8006
|
-
const pkg = JSON.parse(
|
|
8032
|
+
const pkg = JSON.parse(readFileSync13(pkgPath, "utf-8"));
|
|
8007
8033
|
const testScript = String(pkg?.scripts?.test || "");
|
|
8008
8034
|
const deps = { ...pkg?.devDependencies, ...pkg?.dependencies };
|
|
8009
8035
|
if (testScript.includes("vitest") || deps["vitest"]) {
|
|
@@ -8023,12 +8049,12 @@ function _detectTestFramework() {
|
|
|
8023
8049
|
if (!framework) {
|
|
8024
8050
|
const testDirs = ["src/tests", "tests", "test", "__tests__"];
|
|
8025
8051
|
for (const td of testDirs) {
|
|
8026
|
-
const dirPath =
|
|
8052
|
+
const dirPath = join16(root, td);
|
|
8027
8053
|
if (!existsSync12(dirPath))
|
|
8028
8054
|
continue;
|
|
8029
8055
|
const files = readdirSync2(dirPath).filter((f) => /\.test\./.test(f) || /\.spec\./.test(f));
|
|
8030
8056
|
if (files.length > 0) {
|
|
8031
|
-
const content =
|
|
8057
|
+
const content = readFileSync13(join16(dirPath, files[0]), "utf-8");
|
|
8032
8058
|
if (/from\s+['"]node:test['"]/.test(content)) {
|
|
8033
8059
|
framework = "node-test";
|
|
8034
8060
|
testExt = files[0].split(".").pop();
|
|
@@ -8054,16 +8080,16 @@ function _detectTestFramework() {
|
|
|
8054
8080
|
console.error(`[vibeOS] [tdd] detected test framework: ${framework || "default"} (ext: ${testExt || "match source"})`);
|
|
8055
8081
|
return _detectedFramework;
|
|
8056
8082
|
}
|
|
8057
|
-
var ENFORCEMENT_LOCK_DIR =
|
|
8083
|
+
var ENFORCEMENT_LOCK_DIR = join16(USER_HOME2, ".claude/.enforcement-lock");
|
|
8058
8084
|
var LOCK_EXPIRE_MS = 3e4;
|
|
8059
|
-
var ENFORCEMENT_COOLDOWN_FILE2 =
|
|
8085
|
+
var ENFORCEMENT_COOLDOWN_FILE2 = join16(USER_HOME2, ".claude/.enforcement-cooldown.jsonl");
|
|
8060
8086
|
var COOLDOWN_MS = 6e4;
|
|
8061
8087
|
var _enforcementCooldown = /* @__PURE__ */ new Set();
|
|
8062
8088
|
function _acquireLock(testPath) {
|
|
8063
8089
|
try {
|
|
8064
8090
|
mkdirSync8(ENFORCEMENT_LOCK_DIR, { recursive: true });
|
|
8065
8091
|
const hash = createHash5("sha256").update(testPath).digest("hex").slice(0, 16);
|
|
8066
|
-
const lockPath =
|
|
8092
|
+
const lockPath = join16(ENFORCEMENT_LOCK_DIR, `${hash}.lock`);
|
|
8067
8093
|
try {
|
|
8068
8094
|
openSync4(lockPath, "wx");
|
|
8069
8095
|
return true;
|
|
@@ -8091,7 +8117,7 @@ function _acquireLock(testPath) {
|
|
|
8091
8117
|
function _releaseLock(testPath) {
|
|
8092
8118
|
try {
|
|
8093
8119
|
const hash = createHash5("sha256").update(testPath).digest("hex").slice(0, 16);
|
|
8094
|
-
const lockPath =
|
|
8120
|
+
const lockPath = join16(ENFORCEMENT_LOCK_DIR, `${hash}.lock`);
|
|
8095
8121
|
rmSync5(lockPath);
|
|
8096
8122
|
} catch {
|
|
8097
8123
|
}
|
|
@@ -8101,7 +8127,7 @@ function _isInCooldown(testPath) {
|
|
|
8101
8127
|
if (!existsSync12(ENFORCEMENT_COOLDOWN_FILE2))
|
|
8102
8128
|
return false;
|
|
8103
8129
|
const hash = createHash5("sha256").update(testPath).digest("hex").slice(0, 16);
|
|
8104
|
-
const lines =
|
|
8130
|
+
const lines = readFileSync13(ENFORCEMENT_COOLDOWN_FILE2, "utf-8").trim().split("\n").filter(Boolean);
|
|
8105
8131
|
const now = Date.now();
|
|
8106
8132
|
for (const line of lines) {
|
|
8107
8133
|
try {
|
|
@@ -8122,7 +8148,7 @@ function _recordCooldown(testPath) {
|
|
|
8122
8148
|
const hash = createHash5("sha256").update(testPath).digest("hex").slice(0, 16);
|
|
8123
8149
|
const entry = JSON.stringify({ h: hash, ts: Date.now() }) + "\n";
|
|
8124
8150
|
appendFileSync6(ENFORCEMENT_COOLDOWN_FILE2, entry);
|
|
8125
|
-
const lines =
|
|
8151
|
+
const lines = readFileSync13(ENFORCEMENT_COOLDOWN_FILE2, "utf-8").trim().split("\n").filter(Boolean);
|
|
8126
8152
|
if (lines.length > 500) {
|
|
8127
8153
|
writeFileSync10(ENFORCEMENT_COOLDOWN_FILE2, lines.slice(-200).join("\n") + "\n");
|
|
8128
8154
|
}
|
|
@@ -8193,7 +8219,7 @@ function enforceTestFile(filePath) {
|
|
|
8193
8219
|
let sourceContent = "";
|
|
8194
8220
|
try {
|
|
8195
8221
|
if (existsSync12(filePath)) {
|
|
8196
|
-
sourceContent =
|
|
8222
|
+
sourceContent = readFileSync13(filePath, "utf-8");
|
|
8197
8223
|
}
|
|
8198
8224
|
} catch {
|
|
8199
8225
|
}
|
|
@@ -8814,7 +8840,7 @@ ${pendingUiNote}`;
|
|
|
8814
8840
|
};
|
|
8815
8841
|
|
|
8816
8842
|
// src/lib/hooks/session-compact.js
|
|
8817
|
-
import { readFileSync as
|
|
8843
|
+
import { readFileSync as readFileSync14, existsSync as existsSync14 } from "node:fs";
|
|
8818
8844
|
var onSessionCompacting = async (_input, output) => {
|
|
8819
8845
|
if (!loadSelection().enabled)
|
|
8820
8846
|
return;
|
|
@@ -8823,7 +8849,7 @@ var onSessionCompacting = async (_input, output) => {
|
|
|
8823
8849
|
let recent = "";
|
|
8824
8850
|
if (existsSync14(indexPath)) {
|
|
8825
8851
|
try {
|
|
8826
|
-
const lines =
|
|
8852
|
+
const lines = readFileSync14(indexPath, "utf-8").trim().split("\n").slice(-30);
|
|
8827
8853
|
recent = lines.map((l) => {
|
|
8828
8854
|
try {
|
|
8829
8855
|
return JSON.parse(l);
|
|
@@ -8877,17 +8903,17 @@ var _mcpServerRuntime = null;
|
|
|
8877
8903
|
var _mcpServerHooked = false;
|
|
8878
8904
|
function _loadOpenCodeProviders() {
|
|
8879
8905
|
try {
|
|
8880
|
-
const cfg = _readOpenCodeConfigObject(
|
|
8906
|
+
const cfg = _readOpenCodeConfigObject(join17(USER_HOME2, ".config", "opencode"));
|
|
8881
8907
|
return cfg?.provider || {};
|
|
8882
8908
|
} catch {
|
|
8883
8909
|
return {};
|
|
8884
8910
|
}
|
|
8885
8911
|
}
|
|
8886
8912
|
function _readOpenCodeConfigObject(dir) {
|
|
8887
|
-
const jsonPath =
|
|
8888
|
-
const jsoncPath =
|
|
8889
|
-
if (existsSync15(jsonPath)) return safeJsonParse3(
|
|
8890
|
-
if (existsSync15(jsoncPath)) return _parseJsonc(
|
|
8913
|
+
const jsonPath = join17(dir, "opencode.json");
|
|
8914
|
+
const jsoncPath = join17(dir, "opencode.jsonc");
|
|
8915
|
+
if (existsSync15(jsonPath)) return safeJsonParse3(readFileSync15(jsonPath, "utf-8"));
|
|
8916
|
+
if (existsSync15(jsoncPath)) return _parseJsonc(readFileSync15(jsoncPath, "utf-8"));
|
|
8891
8917
|
return {};
|
|
8892
8918
|
}
|
|
8893
8919
|
function _parseJsonc(raw) {
|
|
@@ -8913,9 +8939,9 @@ function _modelTier2(id2) {
|
|
|
8913
8939
|
function backupFile(path, label) {
|
|
8914
8940
|
try {
|
|
8915
8941
|
if (!existsSync15(path)) return null;
|
|
8916
|
-
const bkDir =
|
|
8942
|
+
const bkDir = join17(USER_HOME2, ".claude", ".backups");
|
|
8917
8943
|
mkdirSync10(bkDir, { recursive: true });
|
|
8918
|
-
const bk =
|
|
8944
|
+
const bk = join17(bkDir, `${basename9(path)}.${label}.${Date.now()}.bak`);
|
|
8919
8945
|
copyFileSync6(path, bk);
|
|
8920
8946
|
return bk;
|
|
8921
8947
|
} catch {
|
|
@@ -8924,7 +8950,7 @@ function backupFile(path, label) {
|
|
|
8924
8950
|
}
|
|
8925
8951
|
function readPackageVersion() {
|
|
8926
8952
|
try {
|
|
8927
|
-
const pkg = safeJsonParse3(
|
|
8953
|
+
const pkg = safeJsonParse3(readFileSync15(join17(process.cwd(), "package.json"), "utf-8"));
|
|
8928
8954
|
return String(pkg?.version || "");
|
|
8929
8955
|
} catch {
|
|
8930
8956
|
return "";
|
|
@@ -8939,7 +8965,7 @@ function loadMcpPort() {
|
|
|
8939
8965
|
}
|
|
8940
8966
|
try {
|
|
8941
8967
|
if (existsSync15(TIERS_FILE2)) {
|
|
8942
|
-
const tiers = safeJsonParse3(
|
|
8968
|
+
const tiers = safeJsonParse3(readFileSync15(TIERS_FILE2, "utf-8"));
|
|
8943
8969
|
const cfg = tiers?.selection?.mcp_port ?? tiers?.mcp_port;
|
|
8944
8970
|
if (cfg === false || cfg === "disabled" || cfg === 0) return 0;
|
|
8945
8971
|
const n = Number(cfg);
|
|
@@ -8952,7 +8978,7 @@ function loadMcpPort() {
|
|
|
8952
8978
|
function persistMcpPort(port) {
|
|
8953
8979
|
try {
|
|
8954
8980
|
if (!existsSync15(TIERS_FILE2)) return;
|
|
8955
|
-
const tiers = safeJsonParse3(
|
|
8981
|
+
const tiers = safeJsonParse3(readFileSync15(TIERS_FILE2, "utf-8"));
|
|
8956
8982
|
tiers.selection ??= {};
|
|
8957
8983
|
if (Number(tiers.selection.mcp_port) === Number(port)) return;
|
|
8958
8984
|
tiers.selection.mcp_port = port;
|
|
@@ -8967,7 +8993,7 @@ function computeStatusPayload() {
|
|
|
8967
8993
|
const sel = loadSelection();
|
|
8968
8994
|
let tiersData = {};
|
|
8969
8995
|
try {
|
|
8970
|
-
tiersData = safeJsonParse3(
|
|
8996
|
+
tiersData = safeJsonParse3(readFileSync15(TIERS_FILE2, "utf-8"));
|
|
8971
8997
|
} catch {
|
|
8972
8998
|
}
|
|
8973
8999
|
const credit = loadCredit();
|
|
@@ -9120,13 +9146,13 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
9120
9146
|
setCurrentModel(readConfig(directory3));
|
|
9121
9147
|
if (!currentModel) {
|
|
9122
9148
|
const home = process.env.HOME || "";
|
|
9123
|
-
if (home) setCurrentModel(readConfig(
|
|
9149
|
+
if (home) setCurrentModel(readConfig(join17(home, ".config/opencode")));
|
|
9124
9150
|
}
|
|
9125
9151
|
if (!currentModel) setCurrentModel(process?.env?.OPENCODE_MODEL || "");
|
|
9126
9152
|
if (currentModel) {
|
|
9127
9153
|
setCurrentTier(classify(currentModel));
|
|
9128
9154
|
try {
|
|
9129
|
-
const _tiersData2 = safeJsonParse3(
|
|
9155
|
+
const _tiersData2 = safeJsonParse3(readFileSync15(TIERS_FILE2, "utf-8"));
|
|
9130
9156
|
const _activeSlot = _tiersData2?.selection?.active_slot || "brain";
|
|
9131
9157
|
if (_activeSlot === "brain") {
|
|
9132
9158
|
const _brainOcModel = _tiersData2?.trinity?.brain?.oc || "";
|
|
@@ -9151,7 +9177,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
9151
9177
|
let _wasCorrupted = false;
|
|
9152
9178
|
if (existsSync15(TIERS_FILE2)) {
|
|
9153
9179
|
try {
|
|
9154
|
-
_tiersData2 = safeJsonParse3(
|
|
9180
|
+
_tiersData2 = safeJsonParse3(readFileSync15(TIERS_FILE2, "utf-8"));
|
|
9155
9181
|
} catch {
|
|
9156
9182
|
_tiersData2 = { selection: { enabled: true, active_slot: "brain", delegation_enforce: true, tdd_strict: true }, trinity: {} };
|
|
9157
9183
|
_wasCorrupted = true;
|
|
@@ -9227,7 +9253,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
9227
9253
|
writeFileSync12(_tmp, JSON.stringify(_tiersData2, null, 2) + "\n", "utf-8");
|
|
9228
9254
|
renameSync6(_tmp, TIERS_FILE2);
|
|
9229
9255
|
console.error(`[vibeOS] auto-synced model-tiers.json: brain=${_brain.id} medium=${_tiersData2.trinity?.medium?.oc || ""} cheap=${_tiersData2.trinity?.cheap?.oc || ""}`);
|
|
9230
|
-
const _tiersCfg = safeJsonParse3(
|
|
9256
|
+
const _tiersCfg = safeJsonParse3(readFileSync15(TIERS_FILE2, "utf-8"));
|
|
9231
9257
|
const _b = _tiersCfg?.trinity?.brain?.oc;
|
|
9232
9258
|
const _m = _tiersCfg?.trinity?.medium?.oc;
|
|
9233
9259
|
const _c = _tiersCfg?.trinity?.cheap?.oc;
|
|
@@ -9244,7 +9270,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
9244
9270
|
}
|
|
9245
9271
|
}
|
|
9246
9272
|
try {
|
|
9247
|
-
const _mt = safeJsonParse3(
|
|
9273
|
+
const _mt = safeJsonParse3(readFileSync15(TIERS_FILE2, "utf-8"));
|
|
9248
9274
|
if (_mt.selection && (_mt.selection.mcp_port === void 0 || _mt.selection.mcp_port === null)) {
|
|
9249
9275
|
_mt.selection.mcp_port = 9578;
|
|
9250
9276
|
const _tmp = TIERS_FILE2 + ".tmp." + Date.now();
|
|
@@ -9282,7 +9308,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
9282
9308
|
}
|
|
9283
9309
|
const _tiersData = (() => {
|
|
9284
9310
|
try {
|
|
9285
|
-
return safeJsonParse3(
|
|
9311
|
+
return safeJsonParse3(readFileSync15(TIERS_FILE2, "utf-8"));
|
|
9286
9312
|
} catch {
|
|
9287
9313
|
return {};
|
|
9288
9314
|
}
|
|
@@ -9305,7 +9331,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
9305
9331
|
latestUserIntent,
|
|
9306
9332
|
directory: directory3,
|
|
9307
9333
|
safeJsonParse: safeJsonParse3,
|
|
9308
|
-
readFileSync:
|
|
9334
|
+
readFileSync: readFileSync15,
|
|
9309
9335
|
writeFileSync: writeFileSync12,
|
|
9310
9336
|
existsSync: existsSync15,
|
|
9311
9337
|
renameSync: renameSync6,
|