vibeostheog 0.24.24 → 0.24.26
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 +4 -0
- package/dist/vibeOS.js +129 -68
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dist/vibeOS.js
CHANGED
|
@@ -2348,22 +2348,31 @@ async function remoteCall(method, args, fallbackFn) {
|
|
|
2348
2348
|
return null;
|
|
2349
2349
|
}
|
|
2350
2350
|
const result = await client2[method](...args);
|
|
2351
|
+
if (_apiFallbackMode) {
|
|
2352
|
+
_apiFallbackMode = false;
|
|
2353
|
+
_apiFallbackSince = null;
|
|
2354
|
+
console.warn(`[vibeOS] API reconnected \u2014 ${method} OK`);
|
|
2355
|
+
}
|
|
2351
2356
|
_apiFallbackMode = false;
|
|
2352
2357
|
_apiFallbackSince = null;
|
|
2353
2358
|
markApiConnected();
|
|
2354
2359
|
return result;
|
|
2355
2360
|
} catch (err) {
|
|
2361
|
+
const status = err?.statusCode || err?.status || 0;
|
|
2362
|
+
const body = err?.response?.body || err?.body || "";
|
|
2363
|
+
const bodyPreview = typeof body === "string" ? body.substring(0, 120) : String(body).substring(0, 120);
|
|
2364
|
+
const detail = status ? `status=${status} body=${bodyPreview}` : `message=${err?.message || err}`;
|
|
2356
2365
|
if (!_apiFallbackMode) {
|
|
2357
2366
|
_apiFallbackMode = true;
|
|
2358
2367
|
_apiFallbackSince = (/* @__PURE__ */ new Date()).toISOString();
|
|
2359
|
-
console.error(`[vibeOS] API fallback activated: ${
|
|
2368
|
+
console.error(`[vibeOS] API fallback activated (${method}): ${detail}`);
|
|
2360
2369
|
}
|
|
2361
2370
|
markApiDisconnected();
|
|
2362
2371
|
if (fallbackFn) {
|
|
2363
2372
|
try {
|
|
2364
2373
|
return fallbackFn();
|
|
2365
2374
|
} catch (fe) {
|
|
2366
|
-
console.error(`[vibeOS] fallback also failed: ${fe
|
|
2375
|
+
console.error(`[vibeOS] fallback also failed: ${fe?.message || fe}`);
|
|
2367
2376
|
}
|
|
2368
2377
|
}
|
|
2369
2378
|
return null;
|
|
@@ -3480,9 +3489,30 @@ function runStartupMaintenanceOnce() {
|
|
|
3480
3489
|
} catch {
|
|
3481
3490
|
}
|
|
3482
3491
|
}
|
|
3492
|
+
function _ensureVibeOSHomeDir() {
|
|
3493
|
+
try {
|
|
3494
|
+
if (!existsSync5(VIBEOS_HOME)) {
|
|
3495
|
+
mkdirSync3(VIBEOS_HOME, { recursive: true });
|
|
3496
|
+
return VIBEOS_HOME;
|
|
3497
|
+
}
|
|
3498
|
+
const st = statSync4(VIBEOS_HOME);
|
|
3499
|
+
if (!st.isDirectory()) {
|
|
3500
|
+
const backup = VIBEOS_HOME + ".backup." + Date.now();
|
|
3501
|
+
renameSync3(VIBEOS_HOME, backup);
|
|
3502
|
+
mkdirSync3(VIBEOS_HOME, { recursive: true });
|
|
3503
|
+
}
|
|
3504
|
+
return VIBEOS_HOME;
|
|
3505
|
+
} catch {
|
|
3506
|
+
return VIBEOS_HOME;
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3483
3509
|
function _handleStateCorruption2(path) {
|
|
3510
|
+
_ensureVibeOSHomeDir();
|
|
3484
3511
|
const backupDir = join4(VIBEOS_HOME, ".backups");
|
|
3485
|
-
|
|
3512
|
+
try {
|
|
3513
|
+
mkdirSync3(backupDir, { recursive: true });
|
|
3514
|
+
} catch {
|
|
3515
|
+
}
|
|
3486
3516
|
const backupPath = join4(backupDir, basename2(path) + ".corrupted." + Date.now());
|
|
3487
3517
|
try {
|
|
3488
3518
|
copyFileSync(path, backupPath);
|
|
@@ -4469,8 +4499,9 @@ function touchProjectBucket(state, fp2, meta = {}) {
|
|
|
4469
4499
|
if (!bucket.sessions.includes(meta.sessionId)) {
|
|
4470
4500
|
bucket.sessions.push(meta.sessionId);
|
|
4471
4501
|
bucket.sessions = bucket.sessions.slice(-30);
|
|
4502
|
+
bucket.totalSessions = Number(bucket.totalSessions || 0) + 1;
|
|
4472
4503
|
}
|
|
4473
|
-
bucket.totalSessions = Math.max(Number(bucket.totalSessions || 0), bucket.sessions.length);
|
|
4504
|
+
bucket.totalSessions = Math.max(Number(bucket.totalSessions || 0), bucket.sessions.length, 1);
|
|
4474
4505
|
}
|
|
4475
4506
|
if (typeof meta.reportId === "string" && meta.reportId.trim()) {
|
|
4476
4507
|
bucket.reports ??= [];
|
|
@@ -6147,32 +6178,35 @@ function _refreshModel(directory3) {
|
|
|
6147
6178
|
}
|
|
6148
6179
|
if (!(_modelLocked || sel.slot_locked === true)) {
|
|
6149
6180
|
const activeIsManual = tiersData?.trinity?.[activeSlot]?.manual === true;
|
|
6150
|
-
const
|
|
6151
|
-
if (
|
|
6152
|
-
const
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6181
|
+
const currentSlotModel = activeIsManual ? "" : slotOcModel;
|
|
6182
|
+
if (!currentSlotModel) {
|
|
6183
|
+
const cfgModel = readConfig(directory3) || readConfig(getOpenCodeHome()) || "";
|
|
6184
|
+
if (cfgModel && cfgModel.includes("/") && cfgModel !== currentModel) {
|
|
6185
|
+
const oldModel = currentModel;
|
|
6186
|
+
const oldTier = currentTier;
|
|
6187
|
+
setCurrentModel(cfgModel);
|
|
6188
|
+
setCurrentTier(classify(cfgModel));
|
|
6189
|
+
if (DEBUG_INTERNALS)
|
|
6190
|
+
console.error(`[vibeOS] model refresh (config fallback): ${oldModel}(${oldTier}) \u2192 ${currentModel}(${currentTier})`);
|
|
6191
|
+
try {
|
|
6192
|
+
if (existsSync6(TIERS_FILE3)) {
|
|
6193
|
+
withFileLock2(TIERS_FILE3, () => {
|
|
6194
|
+
const t = safeJsonParse3(readFileSync5(TIERS_FILE3, "utf-8"));
|
|
6195
|
+
for (const s of getTrinitySlotOrder(t)) {
|
|
6196
|
+
if (t?.trinity?.[s]?.oc === cfgModel) {
|
|
6197
|
+
t.selection.active_slot = s;
|
|
6198
|
+
const _tmp = TIERS_FILE3 + ".tmp." + Date.now() + "." + Math.random().toString(36).slice(2, 8);
|
|
6199
|
+
writeFileSync5(_tmp, JSON.stringify(t, null, 2) + "\n", "utf-8");
|
|
6200
|
+
renameSync4(_tmp, TIERS_FILE3);
|
|
6201
|
+
if (DEBUG_INTERNALS)
|
|
6202
|
+
console.error(`[vibeOS] model refresh (config fallback): synced active_slot \u2192 ${s}`);
|
|
6203
|
+
break;
|
|
6204
|
+
}
|
|
6171
6205
|
}
|
|
6172
|
-
}
|
|
6173
|
-
}
|
|
6206
|
+
});
|
|
6207
|
+
}
|
|
6208
|
+
} catch {
|
|
6174
6209
|
}
|
|
6175
|
-
} catch {
|
|
6176
6210
|
}
|
|
6177
6211
|
}
|
|
6178
6212
|
}
|
|
@@ -7283,15 +7317,33 @@ function recoverOptimizationModeFromSelection(sel) {
|
|
|
7283
7317
|
return "budget";
|
|
7284
7318
|
return "budget";
|
|
7285
7319
|
}
|
|
7320
|
+
function recoverOptimizationModeFromLiveState(sel) {
|
|
7321
|
+
const liveTier = String(currentTier || "").toLowerCase();
|
|
7322
|
+
if (liveTier === "high")
|
|
7323
|
+
return "quality";
|
|
7324
|
+
if (liveTier === "mid")
|
|
7325
|
+
return "vibemax";
|
|
7326
|
+
if (liveTier === "cheap" || liveTier === "budget")
|
|
7327
|
+
return "budget";
|
|
7328
|
+
return recoverOptimizationModeFromSelection(sel);
|
|
7329
|
+
}
|
|
7286
7330
|
function loadOptimizationMode() {
|
|
7287
7331
|
try {
|
|
7288
7332
|
const sel = loadSelection();
|
|
7289
7333
|
const persistedMode = sel.optimization_mode || null;
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7334
|
+
const prevKey = `${_OC_SID}_prev_opt`;
|
|
7335
|
+
const sessionMode = loadSessionOptMode(_OC_SID);
|
|
7336
|
+
const globalMode = loadGlobalOptMode();
|
|
7337
|
+
const liveRecovery = recoverOptimizationModeFromLiveState(sel);
|
|
7338
|
+
const storedModes = [
|
|
7339
|
+
persistedMode,
|
|
7340
|
+
sel.previous_optimization_mode,
|
|
7341
|
+
loadSessionOptMode(prevKey),
|
|
7342
|
+
sessionMode,
|
|
7343
|
+
globalMode
|
|
7344
|
+
].map((mode) => String(mode || "").toLowerCase());
|
|
7345
|
+
if (storedModes.includes("vibelitex")) {
|
|
7346
|
+
const recoveryMode = (sel.previous_optimization_mode && sel.previous_optimization_mode !== "vibelitex" ? sel.previous_optimization_mode : "") || loadSessionOptMode(prevKey) || (sessionMode && sessionMode !== "vibelitex" ? sessionMode : "") || (globalMode && globalMode !== "vibelitex" ? globalMode : "") || liveRecovery;
|
|
7295
7347
|
if (recoveryMode && recoveryMode !== "vibelitex") {
|
|
7296
7348
|
try {
|
|
7297
7349
|
writeSelection("optimization_mode", recoveryMode);
|
|
@@ -7312,12 +7364,10 @@ function loadOptimizationMode() {
|
|
|
7312
7364
|
return recoveryMode;
|
|
7313
7365
|
}
|
|
7314
7366
|
}
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
if (global && global !== "auto")
|
|
7320
|
-
return global;
|
|
7367
|
+
if (sessionMode && sessionMode !== "auto")
|
|
7368
|
+
return sessionMode;
|
|
7369
|
+
if (globalMode && globalMode !== "auto")
|
|
7370
|
+
return globalMode;
|
|
7321
7371
|
return DFLT_OPTIMIZATION_MODE;
|
|
7322
7372
|
} catch {
|
|
7323
7373
|
return DFLT_OPTIMIZATION_MODE;
|
|
@@ -7735,10 +7785,10 @@ function generateReportId(type, fp2) {
|
|
|
7735
7785
|
return `${ts}-${(fp2 || "unknown").slice(0, 6)}-${type}-${rnd}`;
|
|
7736
7786
|
}
|
|
7737
7787
|
var _reportDedupWindow = /* @__PURE__ */ new Map();
|
|
7738
|
-
function _wouldBeDuplicate(type, summary) {
|
|
7788
|
+
function _wouldBeDuplicate(type, summary, scope) {
|
|
7739
7789
|
if (typeof summary !== "string")
|
|
7740
7790
|
return false;
|
|
7741
|
-
const key = `${getVibeOSHome7()}::${type || ""}::${summary}`;
|
|
7791
|
+
const key = `${getVibeOSHome7()}::${type || ""}::${String(scope || "unknown")}::${summary}`;
|
|
7742
7792
|
const last = _reportDedupWindow.get(key);
|
|
7743
7793
|
if (last && Date.now() - last < 5 * 60 * 1e3)
|
|
7744
7794
|
return true;
|
|
@@ -7821,7 +7871,8 @@ function saveReport({ type = "manual", summary = "", findings = null, metrics =
|
|
|
7821
7871
|
const metricsSessionId = typeof metricsObject.sessionId === "string" && metricsObject.sessionId.trim() ? metricsObject.sessionId.trim() : "";
|
|
7822
7872
|
const metricsProjectName = typeof metricsObject.projectName === "string" && metricsObject.projectName.trim() ? metricsObject.projectName.trim() : "";
|
|
7823
7873
|
const metricsProjectFingerprint = typeof metricsObject.projectFingerprint === "string" && metricsObject.projectFingerprint.trim() ? metricsObject.projectFingerprint.trim() : "";
|
|
7824
|
-
|
|
7874
|
+
const dedupScope = fingerprint || metricsProjectFingerprint || currentProjectFingerprint || currentProjectFingerprint2 || metricsProjectName || currentProjectName || currentProjectName2 || "unknown";
|
|
7875
|
+
if (_wouldBeDuplicate(type, summary, dedupScope))
|
|
7825
7876
|
return null;
|
|
7826
7877
|
if (!currentProjectFingerprint2 && metricsProjectFingerprint)
|
|
7827
7878
|
currentProjectFingerprint2 = metricsProjectFingerprint;
|
|
@@ -8263,6 +8314,13 @@ function createTrinityTool(deps) {
|
|
|
8263
8314
|
slot = action;
|
|
8264
8315
|
action = "set";
|
|
8265
8316
|
}
|
|
8317
|
+
const keepExistingTrinitySlot = (existingSlot, nextModel) => {
|
|
8318
|
+
const currentOc = String(existingSlot?.oc || "").trim();
|
|
8319
|
+
if (currentOc && !/placeholder/i.test(currentOc) && !/^[^/]+\/[a-z-]+-model$/i.test(currentOc)) {
|
|
8320
|
+
return { ...existingSlot, cc: existingSlot?.cc || deps.modelToCcAlias(currentOc) };
|
|
8321
|
+
}
|
|
8322
|
+
return { oc: nextModel, cc: deps.modelToCcAlias(nextModel) };
|
|
8323
|
+
};
|
|
8266
8324
|
const _brandedModeIds = ["vibeultrax", "vibeqmax", "vibemax", "vibelitex"];
|
|
8267
8325
|
const _builtInModeIds = ["budget", "quality", "speed", "longrun", "auto", "balanced", "audit", "forensic"];
|
|
8268
8326
|
if (!action || action === "status") {
|
|
@@ -8300,7 +8358,7 @@ function createTrinityTool(deps) {
|
|
|
8300
8358
|
const fallbackModelGuard = currentProvider === "opencode" && selectedProvider !== "opencode";
|
|
8301
8359
|
if (deps.currentModel && sel.selected_model && deps.currentModel !== sel.selected_model && !apiFallbackActive && !fallbackModelGuard) {
|
|
8302
8360
|
try {
|
|
8303
|
-
const providers = deps._loadOpenCodeProviders();
|
|
8361
|
+
const providers = typeof deps._loadOpenCodeProviders === "function" ? deps._loadOpenCodeProviders(deps.directory) : {};
|
|
8304
8362
|
const auth = deps._readAuth();
|
|
8305
8363
|
const models = await deps.discoverAvailableModels(providers, auth);
|
|
8306
8364
|
const trinity = buildDeterministicTrinity(models, { selectedModelId: deps.currentModel });
|
|
@@ -8318,13 +8376,7 @@ function createTrinityTool(deps) {
|
|
|
8318
8376
|
const slots = ["brain", "medium", "cheap"];
|
|
8319
8377
|
for (const s of slots) {
|
|
8320
8378
|
const autoModel = probed[s].id;
|
|
8321
|
-
|
|
8322
|
-
const oldModelProvider = oldModel.includes("/") ? oldModel.split("/")[0] : "";
|
|
8323
|
-
if (oldModelProvider && oldModelProvider !== oldProvider && oldModelProvider !== newProvider) {
|
|
8324
|
-
tiersData.trinity[s] = oldTiers[s];
|
|
8325
|
-
} else {
|
|
8326
|
-
tiersData.trinity[s] = { oc: autoModel, cc: deps.modelToCcAlias(autoModel) };
|
|
8327
|
-
}
|
|
8379
|
+
tiersData.trinity[s] = keepExistingTrinitySlot(oldTiers[s], autoModel);
|
|
8328
8380
|
}
|
|
8329
8381
|
tiersData.selection ??= {};
|
|
8330
8382
|
tiersData.selection.selected_provider = trinity.provider || resolveExecutionIdentity(deps.currentModel, deps.directory)?.provider || "";
|
|
@@ -8672,7 +8724,7 @@ Lock is per-session (resets on restart).`;
|
|
|
8672
8724
|
if (action === "setup") {
|
|
8673
8725
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
8674
8726
|
const existing = deps.existsSync(deps.TIERS_FILE) ? deps.safeJsonParse(deps.readFileSync(deps.TIERS_FILE, "utf-8")) || {} : {};
|
|
8675
|
-
const providers = typeof deps._loadOpenCodeProviders === "function" ? deps._loadOpenCodeProviders() : {};
|
|
8727
|
+
const providers = typeof deps._loadOpenCodeProviders === "function" ? deps._loadOpenCodeProviders(deps.directory) : {};
|
|
8676
8728
|
const auth = typeof deps._readAuth === "function" ? deps._readAuth() : {};
|
|
8677
8729
|
let discovered = [];
|
|
8678
8730
|
try {
|
|
@@ -8706,12 +8758,12 @@ Lock is per-session (resets on restart).`;
|
|
|
8706
8758
|
tiers.selection.executed_provider = tiers.selection.selected_provider;
|
|
8707
8759
|
tiers.selection.executed_quality_tier = tiers.selection.selected_quality_tier;
|
|
8708
8760
|
tiers.selection.executed_model = tiers.selection.selected_model;
|
|
8709
|
-
if (brain
|
|
8710
|
-
tiers.trinity.brain =
|
|
8711
|
-
if (medium
|
|
8712
|
-
tiers.trinity.medium =
|
|
8713
|
-
if (cheap
|
|
8714
|
-
tiers.trinity.cheap =
|
|
8761
|
+
if (brain)
|
|
8762
|
+
tiers.trinity.brain = keepExistingTrinitySlot(existing?.trinity?.brain, brain);
|
|
8763
|
+
if (medium)
|
|
8764
|
+
tiers.trinity.medium = keepExistingTrinitySlot(existing?.trinity?.medium, medium);
|
|
8765
|
+
if (cheap)
|
|
8766
|
+
tiers.trinity.cheap = keepExistingTrinitySlot(existing?.trinity?.cheap, cheap);
|
|
8715
8767
|
deps.mkdirSync(dirname9(deps.TIERS_FILE), { recursive: true });
|
|
8716
8768
|
deps.writeFileSync(deps.TIERS_FILE, JSON.stringify(tiers, null, 2) + "\n");
|
|
8717
8769
|
if (typeof deps._refreshModel === "function")
|
|
@@ -9063,7 +9115,7 @@ ${L.repeat(40)}`);
|
|
|
9063
9115
|
return "[vibeOS] Alpha bootstrap token saved. Remote API will retry the exchange on the next call.";
|
|
9064
9116
|
}
|
|
9065
9117
|
if (action === "rebuild") {
|
|
9066
|
-
const providers = deps._loadOpenCodeProviders();
|
|
9118
|
+
const providers = typeof deps._loadOpenCodeProviders === "function" ? deps._loadOpenCodeProviders(deps.directory) : {};
|
|
9067
9119
|
const auth = deps._readAuth();
|
|
9068
9120
|
const models = await deps.discoverAvailableModels(providers, auth);
|
|
9069
9121
|
const selectedModel = deps.currentModel || deps.loadSelection?.().selected_model || deps.loadSelection?.().executed_model || "";
|
|
@@ -9092,9 +9144,9 @@ ${L.repeat(40)}`);
|
|
|
9092
9144
|
const tiers = deps.safeJsonParse(deps.readFileSync(deps.TIERS_FILE, "utf-8"));
|
|
9093
9145
|
const existing = tiers.trinity || {};
|
|
9094
9146
|
tiers.trinity = {
|
|
9095
|
-
brain: existing.brain
|
|
9096
|
-
medium: existing.medium
|
|
9097
|
-
cheap: existing.cheap
|
|
9147
|
+
brain: keepExistingTrinitySlot(existing.brain, probed.brain.id),
|
|
9148
|
+
medium: keepExistingTrinitySlot(existing.medium, probed.medium.id),
|
|
9149
|
+
cheap: keepExistingTrinitySlot(existing.cheap, probed.cheap.id)
|
|
9098
9150
|
};
|
|
9099
9151
|
tiers.selection ??= {};
|
|
9100
9152
|
tiers.selection.selected_provider = trinity.provider || resolveExecutionIdentity(selectedModel, deps.directory)?.provider || "";
|
|
@@ -9178,7 +9230,7 @@ ${L.repeat(40)}`);
|
|
|
9178
9230
|
} else if (deps.currentModel || !deps.existsSync(deps.TIERS_FILE)) {
|
|
9179
9231
|
try {
|
|
9180
9232
|
const auth = deps._readAuth();
|
|
9181
|
-
const ok = await deps.probeModel(deps.currentModel, auth, deps._loadOpenCodeProviders());
|
|
9233
|
+
const ok = await deps.probeModel(deps.currentModel, auth, typeof deps._loadOpenCodeProviders === "function" ? deps._loadOpenCodeProviders(deps.directory) : {});
|
|
9182
9234
|
results.push({
|
|
9183
9235
|
ok,
|
|
9184
9236
|
okLabel: ok ? "\u2705" : "\u274C",
|
|
@@ -10826,9 +10878,10 @@ function syncControlSettings(cv, options = {}) {
|
|
|
10826
10878
|
const restoreMode = sessionPreviousOptMode || previousOptMode2 || inferredRecoveryMode;
|
|
10827
10879
|
const canRestorePrevious = !!restoreMode && cv.optimization_mode !== "vibelitex" && (previousOptMode2 !== null || sessionPreviousOptMode !== null);
|
|
10828
10880
|
if (fallbackPinned) {
|
|
10829
|
-
|
|
10830
|
-
|
|
10831
|
-
|
|
10881
|
+
const snapshotMode = currentSel.optimization_mode && currentSel.optimization_mode !== "vibelitex" ? currentSel.optimization_mode : previousOptMode2 || sessionPreviousOptMode || inferredRecoveryMode;
|
|
10882
|
+
if (snapshotMode && snapshotMode !== "vibelitex") {
|
|
10883
|
+
writeIf("previous_optimization_mode", snapshotMode);
|
|
10884
|
+
writeSessionOptMode(prevSessionKey2, snapshotMode);
|
|
10832
10885
|
}
|
|
10833
10886
|
} else if (canRestorePrevious) {
|
|
10834
10887
|
writeIf("optimization_mode", restoreMode);
|
|
@@ -13715,6 +13768,7 @@ ${argsJson}
|
|
|
13715
13768
|
}
|
|
13716
13769
|
pendingUiNote = `[delegation] This is a good candidate for a Task subagent \u2014 ${resolveTierIcon("brain")} brain handles orchestration, let cheaper tiers do the write/edit. Switch to ${resolveTierIcon("medium")} medium with \`trinity medium\` if you'd rather do it directly.`;
|
|
13717
13770
|
enforcementBlocked = true;
|
|
13771
|
+
_mutateBlockedToolArgs(t, argSources, originalPath, output);
|
|
13718
13772
|
if (shouldLogWarn(`${t}|enforced|${_tierWord}`))
|
|
13719
13773
|
console.error(`[vibeOS] [enforcement] BLOCKED direct ${t} on high tier \u2192 delegate via Task`);
|
|
13720
13774
|
return;
|
|
@@ -14418,10 +14472,17 @@ async function _seedOrRepairModelTiers(directory3) {
|
|
|
14418
14472
|
}
|
|
14419
14473
|
const existingSelection = existing?.selection && typeof existing.selection === "object" ? existing.selection : {};
|
|
14420
14474
|
const existingTrinity = existing?.trinity && typeof existing.trinity === "object" ? existing.trinity : {};
|
|
14475
|
+
const keepExistingSlot = (slotRow, fallbackModel) => {
|
|
14476
|
+
const currentOc = String(slotRow?.oc || "").trim();
|
|
14477
|
+
if (currentOc && !PLACEHOLDER_RE.test(currentOc) && !/placeholder/i.test(currentOc)) {
|
|
14478
|
+
return { ...slotRow, cc: slotRow?.cc || modelToCcAlias(currentOc) };
|
|
14479
|
+
}
|
|
14480
|
+
return { oc: fallbackModel, cc: modelToCcAlias(fallbackModel) };
|
|
14481
|
+
};
|
|
14421
14482
|
const nextTrinity = {
|
|
14422
|
-
brain:
|
|
14423
|
-
medium:
|
|
14424
|
-
cheap:
|
|
14483
|
+
brain: keepExistingSlot(existingTrinity.brain, brain),
|
|
14484
|
+
medium: keepExistingSlot(existingTrinity.medium, medium),
|
|
14485
|
+
cheap: keepExistingSlot(existingTrinity.cheap, cheap)
|
|
14425
14486
|
};
|
|
14426
14487
|
const activeSlot = ["brain", "medium", "cheap"].includes(String(existingSelection.active_slot || "").trim()) ? String(existingSelection.active_slot) : "brain";
|
|
14427
14488
|
const tiers = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeostheog",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.26",
|
|
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",
|