vibeostheog 0.25.33 → 0.25.34

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,20 @@
1
+ ## 0.25.34
2
+ - fix: remove hardcoded model names from fallback
3
+ - fix: restore apiRoute gate for cascade (#239)
4
+ - fix: cascade triggered only by ML_ENABLED, not apiRoute (#238)
5
+ - fix: cascade router must run regardless of remote API route (#237)
6
+ - fix: cascade fallback only when ML API route is unavailable
7
+ - fix: race condition in token refresh with concurrent session renewal (#235)
8
+ - fix: cascade applySlot fires for all tools regardless of delegation_enforce
9
+ - fix: rename pipeline tier 'local' to 'cheap' (#232)
10
+ - docs: add TDD template + branch-first workflow to AGENTS.md
11
+ - build: strip sync-ts-build from pipeline, esbuild-only bundle (#242)
12
+ Reapply "fix: remove hardcoded model names from fallback" (#244)
13
+ Revert "fix: remove hardcoded model names from fallback"
14
+ Fix fail-open delegation and remove hardcoded fallback (#243)
15
+ Remove hardcoded task fallback model (#241)
16
+
17
+
1
18
  ## 0.25.31
2
19
  - feat: anti-loop cost guard with per-turn memoization
3
20
  - feat: remove auto-lock on slot/mode change, README/skills use vibe, lock regression tests
@@ -1 +1 @@
1
- window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:57270";
1
+ window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:42977";
package/dist/vibeOS.js CHANGED
@@ -4200,16 +4200,16 @@ function learnedRouteFromGraph(text) {
4200
4200
  }
4201
4201
  function profileFromCascade(decision, learned = null) {
4202
4202
  if (learned?.learnedTier === "cheap")
4203
- return { profile: "direct", cascade_depth: 1, pipeline_root: ["local"], tier_bias: "cheap" };
4203
+ return { profile: "direct", cascade_depth: 1, pipeline_root: ["cheap"], tier_bias: "cheap" };
4204
4204
  if (learned?.learnedTier === "medium")
4205
4205
  return { profile: "standard", cascade_depth: 2, pipeline_root: ["medium", "brain"], tier_bias: "medium" };
4206
4206
  if (learned?.learnedTier === "brain")
4207
- return { profile: "deep", cascade_depth: 3, pipeline_root: ["local", "medium", "brain"], tier_bias: "brain" };
4207
+ return { profile: "deep", cascade_depth: 3, pipeline_root: ["cheap", "medium", "brain"], tier_bias: "brain" };
4208
4208
  if (decision.useCheap && decision.escalate)
4209
- return { profile: "deep", cascade_depth: 3, pipeline_root: ["local", "medium", "brain"], tier_bias: "brain" };
4209
+ return { profile: "deep", cascade_depth: 3, pipeline_root: ["cheap", "medium", "brain"], tier_bias: "brain" };
4210
4210
  if (decision.escalate)
4211
4211
  return { profile: "standard", cascade_depth: 2, pipeline_root: ["medium", "brain"], tier_bias: "brain" };
4212
- return { profile: "direct", cascade_depth: 1, pipeline_root: ["local"], tier_bias: "cheap" };
4212
+ return { profile: "direct", cascade_depth: 1, pipeline_root: ["cheap"], tier_bias: "cheap" };
4213
4213
  }
4214
4214
  function getPivotCache2() {
4215
4215
  if (!globalThis.__vibeultraxPivotCache)
@@ -5378,7 +5378,8 @@ function setApiToken(newToken) {
5378
5378
  VIBEOS_API_TOKEN = normalizeDirectApiToken(newToken);
5379
5379
  VIBEOS_API_BOOTSTRAP_TOKEN = readBootstrapTokenFromDisk() || VIBEOS_API_BOOTSTRAP_TOKEN;
5380
5380
  syncApiEnabledState(process.env.VIBEOS_API_ENABLED !== "false" && (!!VIBEOS_API_TOKEN || !!VIBEOS_API_BOOTSTRAP_TOKEN));
5381
- _apiClient = null;
5381
+ _apiClientGen++;
5382
+ _apiClientHolder = { client: null, gen: _apiClientGen, tokenSnapshot: VIBEOS_API_TOKEN };
5382
5383
  _apiFallbackMode = false;
5383
5384
  _apiFallbackSince = null;
5384
5385
  persistPrimaryApiEnvState({ token: VIBEOS_API_TOKEN, disabled: false });
@@ -5396,7 +5397,8 @@ function invalidateApiToken() {
5396
5397
  VIBEOS_API_TOKEN = "";
5397
5398
  VIBEOS_API_BOOTSTRAP_TOKEN = "";
5398
5399
  syncApiEnabledState(false);
5399
- _apiClient = null;
5400
+ _apiClientGen++;
5401
+ _apiClientHolder = { client: null, gen: _apiClientGen, tokenSnapshot: "" };
5400
5402
  _apiFallbackMode = false;
5401
5403
  _apiFallbackSince = null;
5402
5404
  if (_anomalyDetector)
@@ -5422,7 +5424,8 @@ function setApiBootstrapToken(newToken) {
5422
5424
  console.error("[vibeOS] Failed to update alpha bootstrap token:", e.message);
5423
5425
  }
5424
5426
  }
5425
- var _apiClient = null;
5427
+ var _apiClientHolder = { client: null, gen: 0, tokenSnapshot: "" };
5428
+ var _apiClientGen = 0;
5426
5429
  var _apiFallbackMode = false;
5427
5430
  var _apiFallbackSince = null;
5428
5431
  var _bootstrapExchangeInFlight = null;
@@ -5499,7 +5502,8 @@ function syncApiTokenFromDisk() {
5499
5502
  VIBEOS_API_TOKEN = "";
5500
5503
  VIBEOS_API_BOOTSTRAP_TOKEN = "";
5501
5504
  syncApiEnabledState(false);
5502
- _apiClient = null;
5505
+ _apiClientGen++;
5506
+ _apiClientHolder = { client: null, gen: _apiClientGen, tokenSnapshot: "" };
5503
5507
  _apiFallbackMode = false;
5504
5508
  _apiFallbackSince = null;
5505
5509
  resetApiConnection();
@@ -5511,7 +5515,8 @@ function syncApiTokenFromDisk() {
5511
5515
  VIBEOS_API_DISABLED = false;
5512
5516
  VIBEOS_API_TOKEN = diskToken;
5513
5517
  syncApiEnabledState(process.env.VIBEOS_API_ENABLED !== "false" && (!!VIBEOS_API_TOKEN || !!VIBEOS_API_BOOTSTRAP_TOKEN));
5514
- _apiClient = null;
5518
+ _apiClientGen++;
5519
+ _apiClientHolder = { client: null, gen: _apiClientGen, tokenSnapshot: VIBEOS_API_TOKEN };
5515
5520
  _apiFallbackMode = false;
5516
5521
  _apiFallbackSince = null;
5517
5522
  markApiConnected();
@@ -5547,14 +5552,21 @@ function syncApiTokenFromDisk() {
5547
5552
  }
5548
5553
  function getApiClient2() {
5549
5554
  syncApiTokenFromDisk();
5550
- if (!_apiClient && isApiEnabled() && VIBEOS_API_TOKEN) {
5551
- _apiClient = new VibeOSApiClient({
5555
+ if (_apiClientHolder.client && _apiClientHolder.gen === _apiClientGen) {
5556
+ return _apiClientHolder.client;
5557
+ }
5558
+ if (isApiEnabled() && VIBEOS_API_TOKEN) {
5559
+ _apiClientHolder.client = new VibeOSApiClient({
5552
5560
  baseUrl: VIBEOS_API_URL,
5553
5561
  apiToken: VIBEOS_API_TOKEN,
5554
5562
  timeout: 5e3
5555
5563
  });
5564
+ _apiClientHolder.gen = _apiClientGen;
5565
+ _apiClientHolder.tokenSnapshot = VIBEOS_API_TOKEN;
5566
+ } else {
5567
+ _apiClientHolder.client = null;
5556
5568
  }
5557
- return _apiClient;
5569
+ return _apiClientHolder.client;
5558
5570
  }
5559
5571
  function isApiFallback() {
5560
5572
  return _apiFallbackMode || isApiFallbackMode() || !isApiEnabled();
@@ -5570,7 +5582,6 @@ async function remoteCall(method, args, fallbackFn) {
5570
5582
  syncApiTokenFromDisk();
5571
5583
  if (!VIBEOS_API_TOKEN && VIBEOS_API_BOOTSTRAP_TOKEN) {
5572
5584
  await ensureBootstrapExchange();
5573
- syncApiTokenFromDisk();
5574
5585
  }
5575
5586
  if (tryResetFallbackCooldown()) {
5576
5587
  if (process.env.VIBEOS_DEBUG)
@@ -9273,14 +9284,14 @@ var BRANDED_MODES = [
9273
9284
  index: 1,
9274
9285
  name: "VibeUltraX",
9275
9286
  icon: "\u{1F3C6}",
9276
- pipeline: ["local", "medium", "brain"],
9287
+ pipeline: ["cheap", "medium", "brain"],
9277
9288
  thinking: "full",
9278
9289
  tdd: "quality",
9279
9290
  enforcement: "strict",
9280
9291
  flow: "strict",
9281
9292
  qualityVsBrain: 107,
9282
9293
  costVsBrain: 58,
9283
- desc: "3-model debate: local proposes, medium reviews, brain refines."
9294
+ desc: "3-model debate: cheap proposes, medium reviews, brain refines."
9284
9295
  },
9285
9296
  {
9286
9297
  id: "vibeqmax",
@@ -12206,7 +12217,7 @@ function syncControlSettings(cv, options = {}) {
12206
12217
  if (cv?.pipeline_root && Array.isArray(cv.pipeline_root)) {
12207
12218
  writeIf("active_pipeline", JSON.stringify(cv.pipeline_root));
12208
12219
  } else if (cv?.cascade_depth && cv.cascade_depth >= 3) {
12209
- writeIf("active_pipeline", JSON.stringify(["local", "medium", "brain"]));
12220
+ writeIf("active_pipeline", JSON.stringify(["cheap", "medium", "brain"]));
12210
12221
  }
12211
12222
  writeIf("enabled", true);
12212
12223
  const compatibilityMode = currentSel.onboarding_mode === "assist";
@@ -12587,8 +12598,7 @@ function orchestratorDirective(cv, sel) {
12587
12598
  const mediumModel = TRINITY_MEDIUM || "the medium model";
12588
12599
  const targetModel = tierBias === "cheap" ? cheapModel : tierBias === "medium" ? mediumModel : tierBias === "brain" ? brainModel : `${cheapModel} or ${mediumModel}`;
12589
12600
  const compatibilityMode = sel?.onboarding_mode === "assist";
12590
- const cheapSlot = TRINITY_CHEAP || "deepseek/deepseek-chat";
12591
- const mediumSlot = TRINITY_MEDIUM || "deepseek/deepseek-v4-flash";
12601
+ const cheapSlot = TRINITY_CHEAP || cheapModel;
12592
12602
  return `[AI ORCHESTRATOR AGENT] You are an AI orchestrator agent. Delegate heavy work to Task subagents (runs on ${targetModel}). Your role is to verify, fill gaps, and synthesize cleanly. ` + (compatibilityMode ? "Compatibility mode is active, so direct Write/Edit stays available until strict guardrails are enabled." : "Brain-tier focuses on orchestration \u2014 hand file writes and edits to Task subagents (cheaper, same quality). Use medium directly with `trinity medium` if the task is simple enough.") + ` [delegation guide] When a write/edit is blocked, use the \`task\` tool with: subagent_type="general" model="${cheapSlot}" prompt="write <path> with: <content>". The task subagent runs on the cheap tier and handles file operations transparently. Parallel task calls are encouraged for independent file changes. Always display the vibeOS cost footer.` + (tierBias !== "auto" ? ` [tier routing] This turn is biased toward ${tierBias} tier.` : "");
12593
12603
  }
12594
12604
  function flowTodosDirective() {
@@ -15301,13 +15311,13 @@ ${argsJson}
15301
15311
  }
15302
15312
  }
15303
15313
  const activePipeline = loadSelection().active_pipeline;
15304
- if (activePipeline && Array.isArray(activePipeline) && activePipeline.length > 1 && TRINITY_CHEAP && TRINITY_MEDIUM) {
15314
+ if (!apiRoute?.target && activePipeline && Array.isArray(activePipeline) && activePipeline.length > 1 && TRINITY_CHEAP && TRINITY_MEDIUM) {
15305
15315
  try {
15306
15316
  const cheapCost = 1e-3;
15307
15317
  const mediumCost = 5e-3;
15308
15318
  const brainCost = 0.02;
15309
15319
  const cascadeResult = cascadeDecide(_prompt, cheapCost, mediumCost, brainCost, 0.85);
15310
- const tierMap = { cheap: TRINITY_CHEAP, medium: TRINITY_MEDIUM, brain: TRINITY_BRAIN, local: TRINITY_CHEAP };
15320
+ const tierMap = { cheap: TRINITY_CHEAP, medium: TRINITY_MEDIUM, brain: TRINITY_BRAIN };
15311
15321
  const pipelineModels = activePipeline.map((t2) => tierMap[t2] || TRINITY_CHEAP);
15312
15322
  if (cascadeResult.escalate && pipelineModels.length > 1) {
15313
15323
  if (pipelineModels.length > 2 && cascadeResult.confidence >= 0.8) {
@@ -15350,7 +15360,7 @@ ${argsJson}
15350
15360
  try {
15351
15361
  const selNow = loadSelection();
15352
15362
  const desiredSlot = _target === TRINITY_CHEAP ? "cheap" : _target === TRINITY_MEDIUM ? "medium" : _target === TRINITY_BRAIN ? "brain" : null;
15353
- if (selNow.delegation_enforce && currentTier === "high" && desiredSlot && selNow.active_slot !== desiredSlot) {
15363
+ if (desiredSlot && selNow.active_slot !== desiredSlot) {
15354
15364
  taskSlotRestore = selNow.active_slot || "brain";
15355
15365
  const switched = applySlot(desiredSlot);
15356
15366
  if (switched?.ok) {
@@ -15445,8 +15455,8 @@ ${argsJson}
15445
15455
  const originalPath = argSources.flatMap((src) => [src?.filePath, src?.file_path, src?.path]).find((v) => typeof v === "string" && v.trim()) || "";
15446
15456
  const basename6 = originalPath.split("/").pop() || "blocked";
15447
15457
  const apiResult = await remoteCall("delegateCheck", [tLower, currentTier, currentModel, _prompt], () => ({
15448
- blocked: true,
15449
- savings: _estEdit,
15458
+ blocked: false,
15459
+ savings: 0,
15450
15460
  _fallback: true
15451
15461
  }));
15452
15462
  const remoteSavings = Number(apiResult?.savings);
@@ -15461,7 +15471,7 @@ ${argsJson}
15461
15471
  projectName: currentProjectName || "",
15462
15472
  sessionId: getCurrentSessionId()
15463
15473
  });
15464
- const taskModel = TRINITY_CHEAP || "deepseek/deepseek-chat";
15474
+ const taskModel = TRINITY_CHEAP || TRINITY_MEDIUM || currentModel || TRINITY_BRAIN || "";
15465
15475
  pendingUiNote = `[delegation] ${t} blocked on brain tier. Use a task subagent instead: \`task subagent_type="general" model="${taskModel}" prompt="${t} <file> with the intended content"\`. Keeps brain focused on orchestration.`;
15466
15476
  enforcementBlocked = true;
15467
15477
  _mutateBlockedToolArgs(t, argSources, originalPath, output);
@@ -16201,10 +16211,10 @@ async function _seedOrRepairModelTiers(directory3) {
16201
16211
  let medium = trinity?.medium || brain;
16202
16212
  let cheap = trinity?.cheap || medium || brain;
16203
16213
  if (!brain) {
16204
- brain = "deepseek/deepseek-v4-pro";
16205
- medium = "deepseek/deepseek-v4-flash";
16206
- cheap = "deepseek/deepseek-chat";
16207
- console.error("[vibeOS] no providers detected \u2014 using default model tiers (brain=v4-pro, medium=v4-flash, cheap=v4-chat)");
16214
+ brain = "generic/brain";
16215
+ medium = "generic/medium";
16216
+ cheap = "generic/cheap";
16217
+ console.error('[vibeOS] no providers or trinity config found \u2014 run "vibe rebuild" to set model tiers');
16208
16218
  }
16209
16219
  const existingSelection = existing?.selection && typeof existing.selection === "object" ? existing.selection : {};
16210
16220
  const existingTrinity = existing?.trinity && typeof existing.trinity === "object" ? existing.trinity : {};
package/package.json CHANGED
@@ -1,22 +1,22 @@
1
1
  {
2
2
  "name": "vibeostheog",
3
- "version": "0.25.33",
3
+ "version": "0.25.34",
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",
7
7
  "release:patch": "node scripts/release.mjs patch --yes",
8
8
  "release:minor": "node scripts/release.mjs minor --yes",
9
9
  "release:major": "node scripts/release.mjs major --yes",
10
- "build": "npm run build:bundle && node scripts/deploy.mjs",
11
- "build:bundle": "tsc -p tsconfig.json && node scripts/sync-ts-build.mjs && node scripts/build-bundle.mjs",
10
+ "build": "npm run typecheck && npm run build:bundle && node scripts/deploy.mjs",
11
+ "build:bundle": "node scripts/build-bundle.mjs",
12
12
  "build:single": "node scripts/build-bundle.mjs",
13
13
  "deploy": "node scripts/deploy.mjs",
14
14
  "typecheck": "tsc -p tsconfig.json --noEmit",
15
15
  "checkpoint:validate": "node scripts/checkpoint-validate.mjs",
16
16
  "test:scripts": "node scripts/run-test-suite.mjs scripts",
17
17
  "ts:audit": "node scripts/ts-audit.mjs",
18
- "test": "npm run build:bundle && node scripts/run-test-suite.mjs full",
19
- "test:ci": "npm run build:bundle && node scripts/run-test-suite.mjs ci",
18
+ "test": "tsc -p tsconfig.json && node scripts/build-bundle.mjs && node scripts/run-test-suite.mjs full",
19
+ "test:ci": "tsc -p tsconfig.json && node scripts/build-bundle.mjs && node scripts/run-test-suite.mjs ci",
20
20
  "guard": "bash plugins/vibetheog-guard/scripts/run-guard.sh",
21
21
  "guard:full": "VIBETHEOG_GUARD_FULL=1 bash plugins/vibetheog-guard/scripts/run-guard.sh",
22
22
  "hook:precommit": "bash plugins/vibetheog-guard/hooks/pre-commit.sh",