vibeostheog 0.25.28 → 0.25.30

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.
@@ -40,6 +40,8 @@ type StatusResponse = {
40
40
  model_locked?: boolean
41
41
  locked_slot?: string | null
42
42
  locked_model?: string | null
43
+ optimization_mode?: string | null
44
+ tiers?: Record<string, { oc?: string }> | null
43
45
  }
44
46
 
45
47
  type SavingsResponse = {
@@ -270,18 +272,31 @@ const plugin: TuiPlugin = async (api, _options, _meta) => {
270
272
  </Slot>
271
273
  <Slot name="sidebar_content" session_id={props.session_id}>
272
274
  <box flexDirection="column" padding={1}>
273
- <text dim bold>MODEL STATUS</text>
275
+ <text dim bold>MODE TIERS CONNECTED</text>
274
276
  <newline />
275
277
  <box>
276
- <text bold={activeSlot === "brain"} color={activeSlot === "brain" ? "green" : undefined}>
277
- {shortModel}
278
- </text>
279
- {activeSlot === "brain" && <text color="green"> active</text>}
278
+ <text>brain </text>
279
+ <text color={activeSlot === "brain" ? "green" : "dim"}>{s?.tiers?.brain?.oc ?? "-"}</text>
280
+ {activeSlot === "brain" && <text color="green" bold> active</text>}
280
281
  </box>
281
282
  <newline />
282
283
  <box>
283
- <text>Backend </text>
284
- <text color={backendConnected ? "green" : "red"} bold>{backendConnected ? "ON" : "OFF"}</text>
284
+ <text>medium </text>
285
+ <text color={activeSlot === "medium" ? "green" : "dim"}>{s?.tiers?.medium?.oc ?? "-"}</text>
286
+ {activeSlot === "medium" && <text color="green" bold> active</text>}
287
+ </box>
288
+ <newline />
289
+ <box>
290
+ <text>cheap </text>
291
+ <text color={activeSlot === "cheap" ? "green" : "dim"}>{s?.tiers?.cheap?.oc ?? "-"}</text>
292
+ {activeSlot === "cheap" && <text color="green" bold> active</text>}
293
+ </box>
294
+ <newline />
295
+ <text dim>---</text>
296
+ <newline />
297
+ <box>
298
+ <text>Session </text>
299
+ <text color="green" bold>{s?.active_slot ?? "?"}</text>
285
300
  </box>
286
301
  <newline />
287
302
  <box>
package/README.md CHANGED
@@ -30,7 +30,7 @@ vibeOS is not a collection of static rules. It is a learning system that pattern
30
30
 
31
31
  The flagship routing strategy. Every turn passes through a three-stage cascade:
32
32
 
33
- 1. **Local proposal** — MagicCoder:7b (Ollama) generates an initial response at zero cost.
33
+ 1. **Cheap proposal** — Your configured cheap slot generates an initial response (e.g., a local Ollama model via `trinity set cheap magiccoder:7b`, or any API model).
34
34
  2. **Flash review** — DeepSeek v4 Flash critiques and refines the proposal.
35
35
  3. **Pro polish** — DeepSeek v4 Pro applies final quality pass on complex sections.
36
36
 
@@ -88,13 +88,13 @@ DeepSeek Chat costs $0/turn when routed through the Direct DeepSeek provider (no
88
88
 
89
89
  | Policy | Quality vs Brain | Cost vs Brain | Savings | Method |
90
90
  |--------|-----------------|--------------|---------|--------|
91
- | VibeUltraX | 107% | 0.58x | 42% | local -> Flash -> Pro cascade |
91
+ | VibeUltraX | 107% | 0.58x | 42% | cheap -> medium -> brain cascade |
92
92
  | VibeQMaX | ~100% | 0.50x | 50% | same model, framework optimizations |
93
93
  | Raw Brain | 100% | 1.00x | - | baseline |
94
94
  | VibeMaX | ~75% | 0.18x | 82% | trained cascade (conservative escalate) |
95
95
  | Budget | ~40% | 0.00x | 100% | direct routing |
96
96
 
97
- **VibeUltraX** — Local Ollama proposes, v4 Flash reviews, v4 Pro refines. 107% quality at 58% cost.
97
+ **VibeUltraX** — Cheap slot proposes, medium reviews, brain refines. 107% quality at 58% cost.
98
98
 
99
99
  **VibeQMaX** — Routes strategic turns through v4 Pro with full thinking, strict enforcement, strict flow checks, and quality TDD. Write/edit delegated per enforcement rules. Blended cost ~$0.00029/turn (50% of brain baseline).
100
100
 
@@ -108,7 +108,7 @@ DeepSeek Chat costs $0/turn when routed through the Direct DeepSeek provider (no
108
108
  |------|-------|----------|-------------|------|-----|
109
109
  | Raw Brain | v4 Pro | full | - | - | - |
110
110
  | VibeQMaX | v4 Pro | full | strict | strict | quality |
111
- | VibeUltraX | cascade (local->Flash->Pro) | auto | auto | auto | auto |
111
+ | VibeUltraX | cascade (cheap->medium->brain) | auto | auto | auto | auto |
112
112
  | VibeMaX | v4 Flash (auto-escalate) | auto | auto | auto | auto |
113
113
  | Speed | v4 Flash | off | relaxed | audit | lazy |
114
114
  | Budget | DeepSeek Chat | off | relaxed | audit | lazy |
@@ -119,9 +119,9 @@ When auto-mode is active, the VibeBoX control vector is the authority. `syncCont
119
119
 
120
120
  | Regime | Mode | Enforce | Flow | TDD | Tier | Think |
121
121
  |--------|------|---------|------|-----|------|-------|
122
- | INIT / DIVERGENT / EXPLORING / REFINING | VibeMaX | relaxed | audit | lazy | cheap | off |
122
+ | INIT / DIVERGENT / EXPLORING / REFINING | vibelitex | relaxed | audit | lazy | cheap | off |
123
123
  | CONVERGING / CLOSED | quality | strict | strict | quality | brain | full |
124
- | LOOPING | speed | relaxed | audit | lazy | medium | off |
124
+ | LOOPING | quality | relaxed | audit | lazy | brain | full |
125
125
 
126
126
  Stress > 1.5 escalates any regime to quality mode regardless of the above mapping.
127
127
 
@@ -1 +1 @@
1
- window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:56848";
1
+ window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:64544";
package/dist/vibeOS.js CHANGED
@@ -5542,7 +5542,7 @@ function getApiClient2() {
5542
5542
  }
5543
5543
  return _apiClient;
5544
5544
  }
5545
- function isApiFallback2() {
5545
+ function isApiFallback() {
5546
5546
  return _apiFallbackMode || isApiFallbackMode() || !isApiEnabled();
5547
5547
  }
5548
5548
  function isApiConnected() {
@@ -5559,7 +5559,8 @@ async function remoteCall(method, args, fallbackFn) {
5559
5559
  syncApiTokenFromDisk();
5560
5560
  }
5561
5561
  if (tryResetFallbackCooldown()) {
5562
- console.debug("[vibeOS] API fallback cooldown expired \u2014 retrying API");
5562
+ if (process.env.VIBEOS_DEBUG)
5563
+ console.warn("[vibeOS] API fallback cooldown expired \u2014 retrying API");
5563
5564
  }
5564
5565
  if (!isApiEnabled() || _apiFallbackMode) {
5565
5566
  if (fallbackFn)
@@ -5586,7 +5587,8 @@ async function remoteCall(method, args, fallbackFn) {
5586
5587
  if (_apiFallbackMode) {
5587
5588
  _apiFallbackMode = false;
5588
5589
  _apiFallbackSince = null;
5589
- console.debug(`[vibeOS] API reconnected \u2014 ${method} OK`);
5590
+ if (process.env.VIBEOS_DEBUG)
5591
+ console.warn(`[vibeOS] API reconnected \u2014 ${method} OK`);
5590
5592
  }
5591
5593
  _apiFallbackMode = false;
5592
5594
  _apiFallbackSince = null;
@@ -7752,7 +7754,7 @@ function classifyTurnSimple2(userText) {
7752
7754
  async function classifyTurnRemote(text) {
7753
7755
  try {
7754
7756
  const client2 = getApiClient2();
7755
- if (!client2 || isApiFallback2()) {
7757
+ if (!client2 || isApiFallback()) {
7756
7758
  _lastClassifiedByApi = false;
7757
7759
  return classifyTurnSimple(text);
7758
7760
  }
@@ -7802,7 +7804,7 @@ function resolveOptimizationMode(subRegime, stressMultiplier, optimizationMode)
7802
7804
  const normalized = String(optimizationMode || "auto").toLowerCase();
7803
7805
  if (normalized === "auto" || normalized === "")
7804
7806
  return autoSelectMode2(subRegime || "INIT", stressMultiplier);
7805
- if (isApiFallback2())
7807
+ if (isApiFallback())
7806
7808
  return "vibelitex";
7807
7809
  if (normalized === "balanced" || normalized === "budget" || normalized === "quality" || normalized === "speed" || normalized === "longrun" || normalized === "audit" || normalized === "forensic" || normalized === "vibeultrax" || normalized === "vibeqmax" || normalized === "vibemax" || normalized === "vibelitex") {
7808
7810
  return normalized;
@@ -7814,7 +7816,7 @@ async function selectOptimizationModeRemote(subRegime, stressMultiplier, fallbac
7814
7816
  const fallback2 = resolveOptimizationMode(subRegime, stressMultiplier, fallbackMode);
7815
7817
  if (normalizedRequestedMode !== "auto" && normalizedRequestedMode !== "")
7816
7818
  return fallback2;
7817
- if (isApiFallback2())
7819
+ if (isApiFallback())
7818
7820
  return fallback2;
7819
7821
  try {
7820
7822
  const client2 = getApiClient2();
@@ -8188,7 +8190,7 @@ function resolveEnforcementMode() {
8188
8190
  async function syncOutcomeToApi(outcome) {
8189
8191
  try {
8190
8192
  const client2 = getApiClient2();
8191
- if (!client2 || isApiFallback2())
8193
+ if (!client2 || isApiFallback())
8192
8194
  return;
8193
8195
  await client2.blackboxOutcome(_OC_SID, outcome);
8194
8196
  } catch {
@@ -8197,7 +8199,7 @@ async function syncOutcomeToApi(outcome) {
8197
8199
  async function fetchBlackboxEnrichment(sessionId, localState) {
8198
8200
  try {
8199
8201
  const client2 = getApiClient2();
8200
- if (!client2 || isApiFallback2())
8202
+ if (!client2 || isApiFallback())
8201
8203
  return null;
8202
8204
  const result = await client2.blackboxAnalyze(sessionId, {
8203
8205
  userText: "",
@@ -8584,7 +8586,7 @@ function researchAudit({ hours = 24, session: sessionFilter } = {}) {
8584
8586
  function normalizeTrend(trend) {
8585
8587
  return trend === "up" || trend === "down" ? trend : "flat";
8586
8588
  }
8587
- function buildStatusPayload({ selection, tiersData, currentModel: currentModel3, creditPercent, version, todos, backendConnected, backendHealthUrl, backendVersion, apiFallbackMode, apiFallbackSince, modelLocked, lockedSlot, lockedModel }) {
8589
+ function buildStatusPayload({ selection, tiersData, currentModel: currentModel3, creditPercent, version, todos, backendConnected, backendHealthUrl, backendVersion, apiFallbackMode, apiFallbackSince, modelLocked, lockedSlot, lockedModel, fallbackThinking, optimizationMode, tiers }) {
8588
8590
  const activeSlot = selection?.active_slot || "brain";
8589
8591
  const todoList = Array.isArray(todos) ? todos : [];
8590
8592
  const pendingTodos = todoList.filter((t) => t?.status === "pending").length;
@@ -8617,6 +8619,8 @@ function buildStatusPayload({ selection, tiersData, currentModel: currentModel3,
8617
8619
  model_locked: lockActive,
8618
8620
  locked_slot: resolvedLockedSlot,
8619
8621
  locked_model: resolvedLockedModel,
8622
+ optimization_mode: selection?.optimization_mode || optimizationMode || null,
8623
+ tiers: tiers?.trinity || null,
8620
8624
  label_modes: [...LABEL_MODES]
8621
8625
  };
8622
8626
  }
@@ -11493,7 +11497,8 @@ function observeToolPattern(toolName, input, output, directory3) {
11493
11497
  } catch {
11494
11498
  }
11495
11499
  }
11496
- if (repeat === 0 && _patternFiredKeys.size > 0) {
11500
+ if (repeat === 0 && _patternFiredKeys.size > 0 && !_trustedCountFired) {
11501
+ _trustedCountFired = true;
11497
11502
  try {
11498
11503
  updateGlobalLearning((gl) => {
11499
11504
  gl.patternQuality ??= { ignoredCount: 0, trustedCount: 0 };
@@ -12637,7 +12642,7 @@ var onSystemTransform = async (_input, output) => {
12637
12642
  pushSystem(output, "[vibeOS dashboard display] When the trinity tool returns output starting with '[vibeOS-dashboard]', use the question tool to display that data in a clean, human-readable format. Use the question field (not the header) to show the dashboard data. Format it with clear sections separated by blank lines, aligned columns with spaces, and plain text only. The header should be 'vibeOS Dashboard'. Include only one option in options: {label: 'Dismiss', description: ''}. Strip the '[vibeOS-dashboard]' marker line before displaying.");
12638
12643
  }
12639
12644
  if (!oneShot("vibeos_dopamine_style_" + fp2)) {
12640
- pushSystem(output, regimeAwareToolStyleDirective(currentSubRegime, displayMode, stressScore));
12645
+ pushSystem(output, regimeAwareToolStyleDirective(_latestBlackboxState3?.sub_regime || classifiedRegime, _currentTemplate, stressScore));
12641
12646
  }
12642
12647
  } catch (err) {
12643
12648
  console.error(`[vibeOS] system.transform failed: ${err.message}`);
@@ -12802,6 +12807,9 @@ function buildFooterLine(input) {
12802
12807
  if (enforcementPulse) {
12803
12808
  line += ` | ${enforcementPulse}`;
12804
12809
  }
12810
+ if (input.stressGauge) {
12811
+ line += ` | ${input.stressGauge}`;
12812
+ }
12805
12813
  if (sessionSlot && sessionSlot !== activeSlot) {
12806
12814
  line += ` | session:${sessionSlot}`;
12807
12815
  }
@@ -13036,7 +13044,7 @@ async function _appendFooter(input, output, directory3) {
13036
13044
  }
13037
13045
  const selNowFooter = loadSelection3();
13038
13046
  const normalizedIntent = classifyTurnSimple2(latestUserIntent || "");
13039
- const currentSubRegime2 = _latestBlackboxState?.sub_regime || normalizedIntent;
13047
+ const currentSubRegime = _latestBlackboxState?.sub_regime || normalizedIntent;
13040
13048
  const bbMode = resolveEnforcementMode();
13041
13049
  const enfTags = buildEnforcementTags({
13042
13050
  delegationEnforce: selNowFooter.delegation_enforce,
@@ -13054,8 +13062,8 @@ async function _appendFooter(input, output, directory3) {
13054
13062
  const ltTotal = ltTasks + ltCache;
13055
13063
  const activeSlot = selNowFooter.active_slot || "brain";
13056
13064
  const flashIcon = isApiConnected() ? " \u26A1" : "";
13057
- const displayMode2 = autoSelectMode2(currentSubRegime2, _footerStress);
13058
- const vibeBrand = resolveBrand(loadOptimizationMode() || displayMode2, activeSlot);
13065
+ const displayMode = autoSelectMode2(currentSubRegime, _footerStress);
13066
+ const vibeBrand = resolveBrand(loadOptimizationMode() || displayMode, activeSlot);
13059
13067
  const vibeLine = buildFooterLine({
13060
13068
  activeSlot,
13061
13069
  providerLabel: execution.provider_label,
@@ -13063,12 +13071,13 @@ async function _appendFooter(input, output, directory3) {
13063
13071
  ltTotal,
13064
13072
  ltTrend: sesTrend,
13065
13073
  vibeBrand,
13066
- optMode: displayMode2,
13074
+ optMode: displayMode,
13067
13075
  flashIcon,
13068
13076
  enfTags,
13069
13077
  sessionSlot,
13070
13078
  vectorChangedSlot: selNowFooter?.vector_changed_slot,
13071
- subRegime: currentSubRegime2
13079
+ subRegime: currentSubRegime,
13080
+ stressGauge: _footerStress > 0.85 ? "\u2588" : _footerStress > 0.7 ? "\u2586" : _footerStress > 0.5 ? "\u2585" : _footerStress > 0.3 ? "\u2583" : _footerStress > 0.1 ? "\u2582" : "\u2581"
13072
13081
  });
13073
13082
  const footerText = stripped + `
13074
13083
 
@@ -15165,7 +15174,7 @@ var onToolExecuteAfter = async (input, output) => {
15165
15174
  }
15166
15175
  const execution = resolveExecutionIdentity(displayModel || resolvedModel || "", projectDirectory);
15167
15176
  const currentSid = _OC_SID;
15168
- const currentSubRegime2 = loadBlackboxState()?.sessions?.[currentSid]?.sub_regime || classifyTurnSimple2(latestUserIntent || "");
15177
+ const currentSubRegime = loadBlackboxState()?.sessions?.[currentSid]?.sub_regime || classifyTurnSimple2(latestUserIntent || "");
15169
15178
  const bbMode = resolveEnforcementMode();
15170
15179
  const enfTags = buildEnforcementTags({
15171
15180
  delegationEnforce: selNow.delegation_enforce,
@@ -15176,8 +15185,8 @@ var onToolExecuteAfter = async (input, output) => {
15176
15185
  quietIntent: isGreetingLike2(latestUserIntent || "")
15177
15186
  });
15178
15187
  const activeSlot = selNow.active_slot || (execution.quality === "brain" ? "brain" : execution.quality === "medium" ? "medium" : "cheap");
15179
- const displayMode2 = autoSelectMode2(currentSubRegime2, latestUserIntent ? scoreStress(latestUserIntent) : 0);
15180
- const vibeBrand = resolveBrand(displayMode2, activeSlot);
15188
+ const displayMode = autoSelectMode2(currentSubRegime, latestUserIntent ? scoreStress(latestUserIntent) : 0);
15189
+ const vibeBrand = resolveBrand(displayMode, activeSlot);
15181
15190
  const sessionSlot = loadSessionSlot(currentSid);
15182
15191
  const flashIcon = isApiConnected() ? " \u26A1" : "";
15183
15192
  _footerText = buildFooterLine({
@@ -15187,12 +15196,12 @@ var onToolExecuteAfter = async (input, output) => {
15187
15196
  ltTotal,
15188
15197
  ltTrend: sesTrend || "",
15189
15198
  vibeBrand,
15190
- optMode: displayMode2,
15199
+ optMode: displayMode,
15191
15200
  flashIcon,
15192
15201
  enfTags,
15193
15202
  sessionSlot,
15194
15203
  vectorChangedSlot: selNow.vector_changed_slot,
15195
- subRegime: currentSubRegime2
15204
+ subRegime: currentSubRegime
15196
15205
  }) + "\n\n";
15197
15206
  const footerTarget = _payload(output);
15198
15207
  output.title = _footerText.trim();
@@ -15932,7 +15941,15 @@ async function ensureMcpServerRunning() {
15932
15941
  backendConnected: isApiConnected(),
15933
15942
  backendHealthUrl: `${VIBEOS_API_URL}/health`,
15934
15943
  backendVersion: getBackendVersion(),
15935
- apiFallbackMode: isApiFallback2(),
15944
+ optimizationMode: loadSelection()?.optimization_mode || null,
15945
+ tiers: (() => {
15946
+ try {
15947
+ return safeJsonParse2(readFileSync17(getTiersFile(), "utf-8"))?.trinity;
15948
+ } catch {
15949
+ return null;
15950
+ }
15951
+ })(),
15952
+ apiFallbackMode: isApiFallback(),
15936
15953
  apiFallbackSince: getApiFallbackSince(),
15937
15954
  modelLocked: _modelLocked,
15938
15955
  lockedSlot: _lockedSlot,
@@ -16318,7 +16335,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
16318
16335
  setBlackboxEnabled,
16319
16336
  loadBlackboxState,
16320
16337
  saveBlackboxState,
16321
- isApiFallback: () => isApiFallback2(),
16338
+ isApiFallback: () => isApiFallback(),
16322
16339
  get _apiFallbackSince() {
16323
16340
  return getApiFallbackSince();
16324
16341
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeostheog",
3
- "version": "0.25.28",
3
+ "version": "0.25.30",
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",