vibeostheog 0.24.23 → 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 CHANGED
@@ -1,3 +1,13 @@
1
+ ## 0.24.25
2
+ - fix: heal stale vibelitex recovery across cascade
3
+
4
+
5
+ ## 0.24.24
6
+ - fix: restore persisted slot lock on reload (#151)
7
+ - chore: v0.24.23 (#150)
8
+ Merge remote-tracking branch 'origin/master'
9
+
10
+
1
11
  ## 0.24.23
2
12
  - fix: heal stale vibelitex reconnect state
3
13
 
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: ${err.message}`);
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.message}`);
2375
+ console.error(`[vibeOS] fallback also failed: ${fe?.message || fe}`);
2367
2376
  }
2368
2377
  }
2369
2378
  return null;
@@ -3395,6 +3404,15 @@ var _latestBlackboxPivotMsg = null;
3395
3404
  var _modelLocked = false;
3396
3405
  var _lockedSlot = null;
3397
3406
  var _lockedModel = null;
3407
+ function setModelLocked(val) {
3408
+ _modelLocked = !!val;
3409
+ }
3410
+ function setLockedSlot(val) {
3411
+ _lockedSlot = val ? String(val) : null;
3412
+ }
3413
+ function setLockedModel(val) {
3414
+ _lockedModel = val ? String(val) : null;
3415
+ }
3398
3416
  var _patternFiredKeys = /* @__PURE__ */ new Set();
3399
3417
  var _sessionCleanupRegistered = false;
3400
3418
  var _sessionCacheCleaned = false;
@@ -6136,34 +6154,37 @@ function _refreshModel(directory3) {
6136
6154
  console.error(`[vibeOS] auto-detected model: ${currentModel} (tier=${currentTier})`);
6137
6155
  }
6138
6156
  }
6139
- if (!_modelLocked) {
6157
+ if (!(_modelLocked || sel.slot_locked === true)) {
6140
6158
  const activeIsManual = tiersData?.trinity?.[activeSlot]?.manual === true;
6141
- const cfgModel = activeIsManual ? "" : readConfig(directory3) || readConfig(getOpenCodeHome()) || "";
6142
- if (cfgModel && cfgModel.includes("/") && cfgModel !== currentModel) {
6143
- const oldModel = currentModel;
6144
- const oldTier = currentTier;
6145
- setCurrentModel(cfgModel);
6146
- setCurrentTier(classify(cfgModel));
6147
- if (DEBUG_INTERNALS)
6148
- console.error(`[vibeOS] model refresh (config): ${oldModel}(${oldTier}) \u2192 ${currentModel}(${currentTier})`);
6149
- try {
6150
- if (existsSync6(TIERS_FILE3)) {
6151
- withFileLock2(TIERS_FILE3, () => {
6152
- const t = safeJsonParse3(readFileSync5(TIERS_FILE3, "utf-8"));
6153
- for (const s of getTrinitySlotOrder(t)) {
6154
- if (t?.trinity?.[s]?.oc === cfgModel) {
6155
- t.selection.active_slot = s;
6156
- const _tmp = TIERS_FILE3 + ".tmp." + Date.now() + "." + Math.random().toString(36).slice(2, 8);
6157
- writeFileSync5(_tmp, JSON.stringify(t, null, 2) + "\n", "utf-8");
6158
- renameSync4(_tmp, TIERS_FILE3);
6159
- if (DEBUG_INTERNALS)
6160
- console.error(`[vibeOS] model refresh (config): synced active_slot \u2192 ${s}`);
6161
- break;
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
+ }
6162
6183
  }
6163
- }
6164
- });
6184
+ });
6185
+ }
6186
+ } catch {
6165
6187
  }
6166
- } catch {
6167
6188
  }
6168
6189
  }
6169
6190
  }
@@ -7274,15 +7295,33 @@ function recoverOptimizationModeFromSelection(sel) {
7274
7295
  return "budget";
7275
7296
  return "budget";
7276
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
+ }
7277
7308
  function loadOptimizationMode() {
7278
7309
  try {
7279
7310
  const sel = loadSelection();
7280
7311
  const persistedMode = sel.optimization_mode || null;
7281
- if (persistedMode === "vibelitex") {
7282
- const prevKey = `${_OC_SID}_prev_opt`;
7283
- const sessionMode = loadSessionOptMode(_OC_SID);
7284
- const globalMode = loadGlobalOptMode();
7285
- const recoveryMode = sel.previous_optimization_mode || loadSessionOptMode(prevKey) || (sessionMode && sessionMode !== "vibelitex" ? sessionMode : "") || (globalMode && globalMode !== "vibelitex" ? globalMode : "") || recoverOptimizationModeFromSelection(sel);
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;
7286
7325
  if (recoveryMode && recoveryMode !== "vibelitex") {
7287
7326
  try {
7288
7327
  writeSelection("optimization_mode", recoveryMode);
@@ -7303,12 +7342,10 @@ function loadOptimizationMode() {
7303
7342
  return recoveryMode;
7304
7343
  }
7305
7344
  }
7306
- const mode = loadSessionOptMode(_OC_SID);
7307
- if (mode && mode !== "auto")
7308
- return mode;
7309
- const global = loadGlobalOptMode();
7310
- if (global && global !== "auto")
7311
- return global;
7345
+ if (sessionMode && sessionMode !== "auto")
7346
+ return sessionMode;
7347
+ if (globalMode && globalMode !== "auto")
7348
+ return globalMode;
7312
7349
  return DFLT_OPTIMIZATION_MODE;
7313
7350
  } catch {
7314
7351
  return DFLT_OPTIMIZATION_MODE;
@@ -8254,6 +8291,13 @@ function createTrinityTool(deps) {
8254
8291
  slot = action;
8255
8292
  action = "set";
8256
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
+ };
8257
8301
  const _brandedModeIds = ["vibeultrax", "vibeqmax", "vibemax", "vibelitex"];
8258
8302
  const _builtInModeIds = ["budget", "quality", "speed", "longrun", "auto", "balanced", "audit", "forensic"];
8259
8303
  if (!action || action === "status") {
@@ -8291,7 +8335,7 @@ function createTrinityTool(deps) {
8291
8335
  const fallbackModelGuard = currentProvider === "opencode" && selectedProvider !== "opencode";
8292
8336
  if (deps.currentModel && sel.selected_model && deps.currentModel !== sel.selected_model && !apiFallbackActive && !fallbackModelGuard) {
8293
8337
  try {
8294
- const providers = deps._loadOpenCodeProviders();
8338
+ const providers = typeof deps._loadOpenCodeProviders === "function" ? deps._loadOpenCodeProviders(deps.directory) : {};
8295
8339
  const auth = deps._readAuth();
8296
8340
  const models = await deps.discoverAvailableModels(providers, auth);
8297
8341
  const trinity = buildDeterministicTrinity(models, { selectedModelId: deps.currentModel });
@@ -8309,13 +8353,7 @@ function createTrinityTool(deps) {
8309
8353
  const slots = ["brain", "medium", "cheap"];
8310
8354
  for (const s of slots) {
8311
8355
  const autoModel = probed[s].id;
8312
- const oldModel = oldTiers[s]?.oc || "";
8313
- const oldModelProvider = oldModel.includes("/") ? oldModel.split("/")[0] : "";
8314
- if (oldModelProvider && oldModelProvider !== oldProvider && oldModelProvider !== newProvider) {
8315
- tiersData.trinity[s] = oldTiers[s];
8316
- } else {
8317
- tiersData.trinity[s] = { oc: autoModel, cc: deps.modelToCcAlias(autoModel) };
8318
- }
8356
+ tiersData.trinity[s] = keepExistingTrinitySlot(oldTiers[s], autoModel);
8319
8357
  }
8320
8358
  tiersData.selection ??= {};
8321
8359
  tiersData.selection.selected_provider = trinity.provider || resolveExecutionIdentity(deps.currentModel, deps.directory)?.provider || "";
@@ -8663,7 +8701,7 @@ Lock is per-session (resets on restart).`;
8663
8701
  if (action === "setup") {
8664
8702
  const now = (/* @__PURE__ */ new Date()).toISOString();
8665
8703
  const existing = deps.existsSync(deps.TIERS_FILE) ? deps.safeJsonParse(deps.readFileSync(deps.TIERS_FILE, "utf-8")) || {} : {};
8666
- const providers = typeof deps._loadOpenCodeProviders === "function" ? deps._loadOpenCodeProviders() : {};
8704
+ const providers = typeof deps._loadOpenCodeProviders === "function" ? deps._loadOpenCodeProviders(deps.directory) : {};
8667
8705
  const auth = typeof deps._readAuth === "function" ? deps._readAuth() : {};
8668
8706
  let discovered = [];
8669
8707
  try {
@@ -8697,12 +8735,12 @@ Lock is per-session (resets on restart).`;
8697
8735
  tiers.selection.executed_provider = tiers.selection.selected_provider;
8698
8736
  tiers.selection.executed_quality_tier = tiers.selection.selected_quality_tier;
8699
8737
  tiers.selection.executed_model = tiers.selection.selected_model;
8700
- if (brain && existing?.trinity?.brain?.manual !== true)
8701
- tiers.trinity.brain = { oc: brain, cc: deps.modelToCcAlias(brain) };
8702
- if (medium && existing?.trinity?.medium?.manual !== true)
8703
- tiers.trinity.medium = { oc: medium, cc: deps.modelToCcAlias(medium) };
8704
- if (cheap && existing?.trinity?.cheap?.manual !== true)
8705
- tiers.trinity.cheap = { oc: cheap, cc: deps.modelToCcAlias(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);
8706
8744
  deps.mkdirSync(dirname9(deps.TIERS_FILE), { recursive: true });
8707
8745
  deps.writeFileSync(deps.TIERS_FILE, JSON.stringify(tiers, null, 2) + "\n");
8708
8746
  if (typeof deps._refreshModel === "function")
@@ -9054,7 +9092,7 @@ ${L.repeat(40)}`);
9054
9092
  return "[vibeOS] Alpha bootstrap token saved. Remote API will retry the exchange on the next call.";
9055
9093
  }
9056
9094
  if (action === "rebuild") {
9057
- const providers = deps._loadOpenCodeProviders();
9095
+ const providers = typeof deps._loadOpenCodeProviders === "function" ? deps._loadOpenCodeProviders(deps.directory) : {};
9058
9096
  const auth = deps._readAuth();
9059
9097
  const models = await deps.discoverAvailableModels(providers, auth);
9060
9098
  const selectedModel = deps.currentModel || deps.loadSelection?.().selected_model || deps.loadSelection?.().executed_model || "";
@@ -9083,9 +9121,9 @@ ${L.repeat(40)}`);
9083
9121
  const tiers = deps.safeJsonParse(deps.readFileSync(deps.TIERS_FILE, "utf-8"));
9084
9122
  const existing = tiers.trinity || {};
9085
9123
  tiers.trinity = {
9086
- brain: existing.brain?.manual === true ? { ...existing.brain } : { oc: probed.brain.id, cc: deps.modelToCcAlias(probed.brain.id) },
9087
- medium: existing.medium?.manual === true ? { ...existing.medium } : { oc: probed.medium.id, cc: deps.modelToCcAlias(probed.medium.id) },
9088
- cheap: existing.cheap?.manual === true ? { ...existing.cheap } : { oc: probed.cheap.id, cc: deps.modelToCcAlias(probed.cheap.id) }
9124
+ brain: keepExistingTrinitySlot(existing.brain, probed.brain.id),
9125
+ medium: keepExistingTrinitySlot(existing.medium, probed.medium.id),
9126
+ cheap: keepExistingTrinitySlot(existing.cheap, probed.cheap.id)
9089
9127
  };
9090
9128
  tiers.selection ??= {};
9091
9129
  tiers.selection.selected_provider = trinity.provider || resolveExecutionIdentity(selectedModel, deps.directory)?.provider || "";
@@ -9169,7 +9207,7 @@ ${L.repeat(40)}`);
9169
9207
  } else if (deps.currentModel || !deps.existsSync(deps.TIERS_FILE)) {
9170
9208
  try {
9171
9209
  const auth = deps._readAuth();
9172
- 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) : {});
9173
9211
  results.push({
9174
9212
  ok,
9175
9213
  okLabel: ok ? "\u2705" : "\u274C",
@@ -10817,9 +10855,10 @@ function syncControlSettings(cv, options = {}) {
10817
10855
  const restoreMode = sessionPreviousOptMode || previousOptMode2 || inferredRecoveryMode;
10818
10856
  const canRestorePrevious = !!restoreMode && cv.optimization_mode !== "vibelitex" && (previousOptMode2 !== null || sessionPreviousOptMode !== null);
10819
10857
  if (fallbackPinned) {
10820
- if (currentSel.optimization_mode !== "vibelitex") {
10821
- writeIf("previous_optimization_mode", currentSel.optimization_mode);
10822
- writeSessionOptMode(prevSessionKey2, currentSel.optimization_mode || "");
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);
10823
10862
  }
10824
10863
  } else if (canRestorePrevious) {
10825
10864
  writeIf("optimization_mode", restoreMode);
@@ -14409,10 +14448,17 @@ async function _seedOrRepairModelTiers(directory3) {
14409
14448
  }
14410
14449
  const existingSelection = existing?.selection && typeof existing.selection === "object" ? existing.selection : {};
14411
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
+ };
14412
14458
  const nextTrinity = {
14413
- brain: existingTrinity.brain?.manual === true && String(existingTrinity.brain?.oc || "").trim() && !PLACEHOLDER_RE.test(String(existingTrinity.brain?.oc || "")) ? { ...existingTrinity.brain, cc: existingTrinity.brain?.cc || modelToCcAlias(String(existingTrinity.brain?.oc || "")) } : { oc: brain, cc: modelToCcAlias(brain) },
14414
- medium: existingTrinity.medium?.manual === true && String(existingTrinity.medium?.oc || "").trim() && !PLACEHOLDER_RE.test(String(existingTrinity.medium?.oc || "")) ? { ...existingTrinity.medium, cc: existingTrinity.medium?.cc || modelToCcAlias(String(existingTrinity.medium?.oc || "")) } : { oc: medium, cc: modelToCcAlias(medium) },
14415
- cheap: existingTrinity.cheap?.manual === true && String(existingTrinity.cheap?.oc || "").trim() && !PLACEHOLDER_RE.test(String(existingTrinity.cheap?.oc || "")) ? { ...existingTrinity.cheap, cc: existingTrinity.cheap?.cc || modelToCcAlias(String(existingTrinity.cheap?.oc || "")) } : { oc: cheap, cc: modelToCcAlias(cheap) }
14459
+ brain: keepExistingSlot(existingTrinity.brain, brain),
14460
+ medium: keepExistingSlot(existingTrinity.medium, medium),
14461
+ cheap: keepExistingSlot(existingTrinity.cheap, cheap)
14416
14462
  };
14417
14463
  const activeSlot = ["brain", "medium", "cheap"].includes(String(existingSelection.active_slot || "").trim()) ? String(existingSelection.active_slot) : "brain";
14418
14464
  const tiers = {
@@ -14558,6 +14604,27 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
14558
14604
  } else {
14559
14605
  console.error("[vibeOS] NO MODEL \u2014 enforcement disabled, will auto-detect on first hook");
14560
14606
  }
14607
+ try {
14608
+ const startupSelection = loadSelection();
14609
+ if (startupSelection?.slot_locked === true) {
14610
+ const lockedSlot = ["brain", "medium", "cheap"].includes(String(startupSelection.active_slot || "").trim()) ? String(startupSelection.active_slot) : "brain";
14611
+ let lockedModel = currentModel || null;
14612
+ try {
14613
+ const tiers = safeJsonParse3(readFileSync17(getTiersFile(), "utf-8"));
14614
+ lockedModel = tiers?.trinity?.[lockedSlot]?.oc || lockedModel || null;
14615
+ } catch {
14616
+ }
14617
+ setModelLocked(true);
14618
+ setLockedSlot(lockedSlot);
14619
+ setLockedModel(lockedModel);
14620
+ console.error(`[vibeOS] startup lock restored \u2192 ${lockedSlot}${lockedModel ? ` (${lockedModel})` : ""}`);
14621
+ } else {
14622
+ setModelLocked(false);
14623
+ setLockedSlot(null);
14624
+ setLockedModel(null);
14625
+ }
14626
+ } catch {
14627
+ }
14561
14628
  console.error(`[vibeOS] auto-config guard: currentModel=${currentModel ? "SET" : "NONE"}, TIERS_FILE=${getTiersFile()}, exists=${existsSync18(getTiersFile())}`);
14562
14629
  try {
14563
14630
  if (!existsSync18(getTiersFile())) {
@@ -14648,7 +14715,6 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
14648
14715
  _loadOpenCodeProviders,
14649
14716
  _modelCost: _modelCost2,
14650
14717
  _modelTier: _modelTier2,
14651
- _modelLocked,
14652
14718
  _latestBlackboxState,
14653
14719
  currentModel,
14654
14720
  currentTier,
@@ -14747,6 +14813,24 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
14747
14813
  },
14748
14814
  set _blackboxEnabled(v) {
14749
14815
  setBlackboxEnabled(v);
14816
+ },
14817
+ get _modelLocked() {
14818
+ return _modelLocked;
14819
+ },
14820
+ set _modelLocked(v) {
14821
+ setModelLocked(v);
14822
+ },
14823
+ get _lockedSlot() {
14824
+ return _lockedSlot;
14825
+ },
14826
+ set _lockedSlot(v) {
14827
+ setLockedSlot(v);
14828
+ },
14829
+ get _lockedModel() {
14830
+ return _lockedModel;
14831
+ },
14832
+ set _lockedModel(v) {
14833
+ setLockedModel(v);
14750
14834
  }
14751
14835
  };
14752
14836
  const pluginHooks = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeostheog",
3
- "version": "0.24.23",
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",