vibeostheog 0.24.24 → 0.24.25
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 +100 -63
- 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;
|
|
@@ -6147,32 +6156,35 @@ function _refreshModel(directory3) {
|
|
|
6147
6156
|
}
|
|
6148
6157
|
if (!(_modelLocked || sel.slot_locked === true)) {
|
|
6149
6158
|
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
|
-
|
|
6159
|
+
const currentSlotModel = activeIsManual ? "" : slotOcModel;
|
|
6160
|
+
if (!currentSlotModel) {
|
|
6161
|
+
const cfgModel = readConfig(directory3) || readConfig(getOpenCodeHome()) || "";
|
|
6162
|
+
if (cfgModel && cfgModel.includes("/") && cfgModel !== currentModel) {
|
|
6163
|
+
const oldModel = currentModel;
|
|
6164
|
+
const oldTier = currentTier;
|
|
6165
|
+
setCurrentModel(cfgModel);
|
|
6166
|
+
setCurrentTier(classify(cfgModel));
|
|
6167
|
+
if (DEBUG_INTERNALS)
|
|
6168
|
+
console.error(`[vibeOS] model refresh (config fallback): ${oldModel}(${oldTier}) \u2192 ${currentModel}(${currentTier})`);
|
|
6169
|
+
try {
|
|
6170
|
+
if (existsSync6(TIERS_FILE3)) {
|
|
6171
|
+
withFileLock2(TIERS_FILE3, () => {
|
|
6172
|
+
const t = safeJsonParse3(readFileSync5(TIERS_FILE3, "utf-8"));
|
|
6173
|
+
for (const s of getTrinitySlotOrder(t)) {
|
|
6174
|
+
if (t?.trinity?.[s]?.oc === cfgModel) {
|
|
6175
|
+
t.selection.active_slot = s;
|
|
6176
|
+
const _tmp = TIERS_FILE3 + ".tmp." + Date.now() + "." + Math.random().toString(36).slice(2, 8);
|
|
6177
|
+
writeFileSync5(_tmp, JSON.stringify(t, null, 2) + "\n", "utf-8");
|
|
6178
|
+
renameSync4(_tmp, TIERS_FILE3);
|
|
6179
|
+
if (DEBUG_INTERNALS)
|
|
6180
|
+
console.error(`[vibeOS] model refresh (config fallback): synced active_slot \u2192 ${s}`);
|
|
6181
|
+
break;
|
|
6182
|
+
}
|
|
6171
6183
|
}
|
|
6172
|
-
}
|
|
6173
|
-
}
|
|
6184
|
+
});
|
|
6185
|
+
}
|
|
6186
|
+
} catch {
|
|
6174
6187
|
}
|
|
6175
|
-
} catch {
|
|
6176
6188
|
}
|
|
6177
6189
|
}
|
|
6178
6190
|
}
|
|
@@ -7283,15 +7295,33 @@ function recoverOptimizationModeFromSelection(sel) {
|
|
|
7283
7295
|
return "budget";
|
|
7284
7296
|
return "budget";
|
|
7285
7297
|
}
|
|
7298
|
+
function recoverOptimizationModeFromLiveState(sel) {
|
|
7299
|
+
const liveTier = String(currentTier || "").toLowerCase();
|
|
7300
|
+
if (liveTier === "high")
|
|
7301
|
+
return "quality";
|
|
7302
|
+
if (liveTier === "mid")
|
|
7303
|
+
return "vibemax";
|
|
7304
|
+
if (liveTier === "cheap" || liveTier === "budget")
|
|
7305
|
+
return "budget";
|
|
7306
|
+
return recoverOptimizationModeFromSelection(sel);
|
|
7307
|
+
}
|
|
7286
7308
|
function loadOptimizationMode() {
|
|
7287
7309
|
try {
|
|
7288
7310
|
const sel = loadSelection();
|
|
7289
7311
|
const persistedMode = sel.optimization_mode || null;
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7312
|
+
const prevKey = `${_OC_SID}_prev_opt`;
|
|
7313
|
+
const sessionMode = loadSessionOptMode(_OC_SID);
|
|
7314
|
+
const globalMode = loadGlobalOptMode();
|
|
7315
|
+
const liveRecovery = recoverOptimizationModeFromLiveState(sel);
|
|
7316
|
+
const storedModes = [
|
|
7317
|
+
persistedMode,
|
|
7318
|
+
sel.previous_optimization_mode,
|
|
7319
|
+
loadSessionOptMode(prevKey),
|
|
7320
|
+
sessionMode,
|
|
7321
|
+
globalMode
|
|
7322
|
+
].map((mode) => String(mode || "").toLowerCase());
|
|
7323
|
+
if (storedModes.includes("vibelitex")) {
|
|
7324
|
+
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
7325
|
if (recoveryMode && recoveryMode !== "vibelitex") {
|
|
7296
7326
|
try {
|
|
7297
7327
|
writeSelection("optimization_mode", recoveryMode);
|
|
@@ -7312,12 +7342,10 @@ function loadOptimizationMode() {
|
|
|
7312
7342
|
return recoveryMode;
|
|
7313
7343
|
}
|
|
7314
7344
|
}
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
if (global && global !== "auto")
|
|
7320
|
-
return global;
|
|
7345
|
+
if (sessionMode && sessionMode !== "auto")
|
|
7346
|
+
return sessionMode;
|
|
7347
|
+
if (globalMode && globalMode !== "auto")
|
|
7348
|
+
return globalMode;
|
|
7321
7349
|
return DFLT_OPTIMIZATION_MODE;
|
|
7322
7350
|
} catch {
|
|
7323
7351
|
return DFLT_OPTIMIZATION_MODE;
|
|
@@ -8263,6 +8291,13 @@ function createTrinityTool(deps) {
|
|
|
8263
8291
|
slot = action;
|
|
8264
8292
|
action = "set";
|
|
8265
8293
|
}
|
|
8294
|
+
const keepExistingTrinitySlot = (existingSlot, nextModel) => {
|
|
8295
|
+
const currentOc = String(existingSlot?.oc || "").trim();
|
|
8296
|
+
if (currentOc && !/placeholder/i.test(currentOc) && !/^[^/]+\/[a-z-]+-model$/i.test(currentOc)) {
|
|
8297
|
+
return { ...existingSlot, cc: existingSlot?.cc || deps.modelToCcAlias(currentOc) };
|
|
8298
|
+
}
|
|
8299
|
+
return { oc: nextModel, cc: deps.modelToCcAlias(nextModel) };
|
|
8300
|
+
};
|
|
8266
8301
|
const _brandedModeIds = ["vibeultrax", "vibeqmax", "vibemax", "vibelitex"];
|
|
8267
8302
|
const _builtInModeIds = ["budget", "quality", "speed", "longrun", "auto", "balanced", "audit", "forensic"];
|
|
8268
8303
|
if (!action || action === "status") {
|
|
@@ -8300,7 +8335,7 @@ function createTrinityTool(deps) {
|
|
|
8300
8335
|
const fallbackModelGuard = currentProvider === "opencode" && selectedProvider !== "opencode";
|
|
8301
8336
|
if (deps.currentModel && sel.selected_model && deps.currentModel !== sel.selected_model && !apiFallbackActive && !fallbackModelGuard) {
|
|
8302
8337
|
try {
|
|
8303
|
-
const providers = deps._loadOpenCodeProviders();
|
|
8338
|
+
const providers = typeof deps._loadOpenCodeProviders === "function" ? deps._loadOpenCodeProviders(deps.directory) : {};
|
|
8304
8339
|
const auth = deps._readAuth();
|
|
8305
8340
|
const models = await deps.discoverAvailableModels(providers, auth);
|
|
8306
8341
|
const trinity = buildDeterministicTrinity(models, { selectedModelId: deps.currentModel });
|
|
@@ -8318,13 +8353,7 @@ function createTrinityTool(deps) {
|
|
|
8318
8353
|
const slots = ["brain", "medium", "cheap"];
|
|
8319
8354
|
for (const s of slots) {
|
|
8320
8355
|
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
|
-
}
|
|
8356
|
+
tiersData.trinity[s] = keepExistingTrinitySlot(oldTiers[s], autoModel);
|
|
8328
8357
|
}
|
|
8329
8358
|
tiersData.selection ??= {};
|
|
8330
8359
|
tiersData.selection.selected_provider = trinity.provider || resolveExecutionIdentity(deps.currentModel, deps.directory)?.provider || "";
|
|
@@ -8672,7 +8701,7 @@ Lock is per-session (resets on restart).`;
|
|
|
8672
8701
|
if (action === "setup") {
|
|
8673
8702
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
8674
8703
|
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() : {};
|
|
8704
|
+
const providers = typeof deps._loadOpenCodeProviders === "function" ? deps._loadOpenCodeProviders(deps.directory) : {};
|
|
8676
8705
|
const auth = typeof deps._readAuth === "function" ? deps._readAuth() : {};
|
|
8677
8706
|
let discovered = [];
|
|
8678
8707
|
try {
|
|
@@ -8706,12 +8735,12 @@ Lock is per-session (resets on restart).`;
|
|
|
8706
8735
|
tiers.selection.executed_provider = tiers.selection.selected_provider;
|
|
8707
8736
|
tiers.selection.executed_quality_tier = tiers.selection.selected_quality_tier;
|
|
8708
8737
|
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 =
|
|
8738
|
+
if (brain)
|
|
8739
|
+
tiers.trinity.brain = keepExistingTrinitySlot(existing?.trinity?.brain, brain);
|
|
8740
|
+
if (medium)
|
|
8741
|
+
tiers.trinity.medium = keepExistingTrinitySlot(existing?.trinity?.medium, medium);
|
|
8742
|
+
if (cheap)
|
|
8743
|
+
tiers.trinity.cheap = keepExistingTrinitySlot(existing?.trinity?.cheap, cheap);
|
|
8715
8744
|
deps.mkdirSync(dirname9(deps.TIERS_FILE), { recursive: true });
|
|
8716
8745
|
deps.writeFileSync(deps.TIERS_FILE, JSON.stringify(tiers, null, 2) + "\n");
|
|
8717
8746
|
if (typeof deps._refreshModel === "function")
|
|
@@ -9063,7 +9092,7 @@ ${L.repeat(40)}`);
|
|
|
9063
9092
|
return "[vibeOS] Alpha bootstrap token saved. Remote API will retry the exchange on the next call.";
|
|
9064
9093
|
}
|
|
9065
9094
|
if (action === "rebuild") {
|
|
9066
|
-
const providers = deps._loadOpenCodeProviders();
|
|
9095
|
+
const providers = typeof deps._loadOpenCodeProviders === "function" ? deps._loadOpenCodeProviders(deps.directory) : {};
|
|
9067
9096
|
const auth = deps._readAuth();
|
|
9068
9097
|
const models = await deps.discoverAvailableModels(providers, auth);
|
|
9069
9098
|
const selectedModel = deps.currentModel || deps.loadSelection?.().selected_model || deps.loadSelection?.().executed_model || "";
|
|
@@ -9092,9 +9121,9 @@ ${L.repeat(40)}`);
|
|
|
9092
9121
|
const tiers = deps.safeJsonParse(deps.readFileSync(deps.TIERS_FILE, "utf-8"));
|
|
9093
9122
|
const existing = tiers.trinity || {};
|
|
9094
9123
|
tiers.trinity = {
|
|
9095
|
-
brain: existing.brain
|
|
9096
|
-
medium: existing.medium
|
|
9097
|
-
cheap: existing.cheap
|
|
9124
|
+
brain: keepExistingTrinitySlot(existing.brain, probed.brain.id),
|
|
9125
|
+
medium: keepExistingTrinitySlot(existing.medium, probed.medium.id),
|
|
9126
|
+
cheap: keepExistingTrinitySlot(existing.cheap, probed.cheap.id)
|
|
9098
9127
|
};
|
|
9099
9128
|
tiers.selection ??= {};
|
|
9100
9129
|
tiers.selection.selected_provider = trinity.provider || resolveExecutionIdentity(selectedModel, deps.directory)?.provider || "";
|
|
@@ -9178,7 +9207,7 @@ ${L.repeat(40)}`);
|
|
|
9178
9207
|
} else if (deps.currentModel || !deps.existsSync(deps.TIERS_FILE)) {
|
|
9179
9208
|
try {
|
|
9180
9209
|
const auth = deps._readAuth();
|
|
9181
|
-
const ok = await deps.probeModel(deps.currentModel, auth, deps._loadOpenCodeProviders());
|
|
9210
|
+
const ok = await deps.probeModel(deps.currentModel, auth, typeof deps._loadOpenCodeProviders === "function" ? deps._loadOpenCodeProviders(deps.directory) : {});
|
|
9182
9211
|
results.push({
|
|
9183
9212
|
ok,
|
|
9184
9213
|
okLabel: ok ? "\u2705" : "\u274C",
|
|
@@ -10826,9 +10855,10 @@ function syncControlSettings(cv, options = {}) {
|
|
|
10826
10855
|
const restoreMode = sessionPreviousOptMode || previousOptMode2 || inferredRecoveryMode;
|
|
10827
10856
|
const canRestorePrevious = !!restoreMode && cv.optimization_mode !== "vibelitex" && (previousOptMode2 !== null || sessionPreviousOptMode !== null);
|
|
10828
10857
|
if (fallbackPinned) {
|
|
10829
|
-
|
|
10830
|
-
|
|
10831
|
-
|
|
10858
|
+
const snapshotMode = currentSel.optimization_mode && currentSel.optimization_mode !== "vibelitex" ? currentSel.optimization_mode : previousOptMode2 || sessionPreviousOptMode || inferredRecoveryMode;
|
|
10859
|
+
if (snapshotMode && snapshotMode !== "vibelitex") {
|
|
10860
|
+
writeIf("previous_optimization_mode", snapshotMode);
|
|
10861
|
+
writeSessionOptMode(prevSessionKey2, snapshotMode);
|
|
10832
10862
|
}
|
|
10833
10863
|
} else if (canRestorePrevious) {
|
|
10834
10864
|
writeIf("optimization_mode", restoreMode);
|
|
@@ -14418,10 +14448,17 @@ async function _seedOrRepairModelTiers(directory3) {
|
|
|
14418
14448
|
}
|
|
14419
14449
|
const existingSelection = existing?.selection && typeof existing.selection === "object" ? existing.selection : {};
|
|
14420
14450
|
const existingTrinity = existing?.trinity && typeof existing.trinity === "object" ? existing.trinity : {};
|
|
14451
|
+
const keepExistingSlot = (slotRow, fallbackModel) => {
|
|
14452
|
+
const currentOc = String(slotRow?.oc || "").trim();
|
|
14453
|
+
if (currentOc && !PLACEHOLDER_RE.test(currentOc) && !/placeholder/i.test(currentOc)) {
|
|
14454
|
+
return { ...slotRow, cc: slotRow?.cc || modelToCcAlias(currentOc) };
|
|
14455
|
+
}
|
|
14456
|
+
return { oc: fallbackModel, cc: modelToCcAlias(fallbackModel) };
|
|
14457
|
+
};
|
|
14421
14458
|
const nextTrinity = {
|
|
14422
|
-
brain:
|
|
14423
|
-
medium:
|
|
14424
|
-
cheap:
|
|
14459
|
+
brain: keepExistingSlot(existingTrinity.brain, brain),
|
|
14460
|
+
medium: keepExistingSlot(existingTrinity.medium, medium),
|
|
14461
|
+
cheap: keepExistingSlot(existingTrinity.cheap, cheap)
|
|
14425
14462
|
};
|
|
14426
14463
|
const activeSlot = ["brain", "medium", "cheap"].includes(String(existingSelection.active_slot || "").trim()) ? String(existingSelection.active_slot) : "brain";
|
|
14427
14464
|
const tiers = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeostheog",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.25",
|
|
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",
|