vibeostheog 0.20.4 → 0.20.7

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,21 @@
1
+ ## 0.20.7
2
+ - fix: ship compiled OpenCode plugin bundle
3
+ - fix: always show model label in tool.execute.after footer, even with zero savings
4
+ - fix: always show model label in tool.execute.after footer, even with zero savings
5
+ - fix: restore release tarball pack step
6
+ Merge pull request #74 from DrunkkToys/codex/release-live-bundle
7
+ Merge pull request #72 from DrunkkToys/codex/alpha-token-install-validation
8
+
9
+
10
+ ## 0.20.6
11
+ - fix: quiet delegation warnings in CLI stderr
12
+ - fix: keep delegation note in the chat transcript only
13
+
14
+ ## 0.20.5
15
+ - fix: validate embedded alpha token on install
16
+ - fix: keep alpha token embedded for seamless onboarding
17
+ - fix: only show footer flash after live backend success
18
+
1
19
  ## 0.20.4
2
20
  - fix: add alpha token invalidate switch
3
21
  - fix: prefer valid api tokens over placeholder env
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeostheog",
3
- "version": "0.20.4",
3
+ "version": "0.20.7",
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",
@@ -12,7 +12,7 @@
12
12
  "deploy": "node scripts/deploy.mjs",
13
13
  "typecheck": "tsc -p tsconfig.json --noEmit",
14
14
  "checkpoint:validate": "node scripts/checkpoint-validate.mjs",
15
- "test:scripts": "node --test scripts/tests/checkpoint-validate.test.mjs",
15
+ "test:scripts": "node --test scripts/tests/checkpoint-validate.test.mjs tests/release-pack.test.mjs",
16
16
  "ts:audit": "node scripts/ts-audit.mjs",
17
17
  "test": "VIBEOS_MCP_PORT=0 node --test --test-timeout=240000 tests/deep_integration.test.mjs tests/production_regressions.test.mjs tests/release_hardening_tigerteam.test.mjs tests/test_api_migration.neutral.test.mjs tests/test_const_assignment_regression.test.mjs tests/test_delegation_enforcer.test.mjs tests/test_diagnose_cmd.test.mjs tests/test_install_and_recovery.test.mjs tests/test_internals_stress_patterns_offtopic.test.mjs tests/test_saveos_e2e_cleanup.test.mjs tests/test_tdd_enforcer.test.mjs src/tests/*.test.js src/utils/tests/*.test.mjs \"src/vibeOS-lib/tests/!(test_blackbox*).test.mjs\"",
18
18
  "test:ci": "VIBEOS_MCP_PORT=0 node --test --test-timeout=30000 tests/production_regressions.test.mjs tests/release_hardening_tigerteam.test.mjs tests/test_const_assignment_regression.test.mjs tests/test_diagnose_cmd.test.mjs tests/test_install_and_recovery.test.mjs tests/test_saveos_e2e_cleanup.test.mjs tests/test_tdd_enforcer.test.mjs src/tests/*.test.js src/utils/tests/*.test.mjs \"src/vibeOS-lib/tests/!(test_blackbox*).test.mjs\"",
@@ -85,5 +85,8 @@
85
85
  "eslint": "^10.4.0",
86
86
  "express": "^5.2.1",
87
87
  "typescript": "^5.9.3"
88
+ },
89
+ "dependencies": {
90
+ "vibeoscore": "file:vibeoscore-1.0.2.tgz"
88
91
  }
89
92
  }
@@ -9,9 +9,13 @@ const __dirname = dirname(fileURLToPath(import.meta.url))
9
9
  const ROOT = join(__dirname, "..")
10
10
 
11
11
  const srcPath = join(ROOT, "src", "index.js")
12
+ const srcLibPath = join(ROOT, "src", "lib")
13
+ const srcUtilsPath = join(ROOT, "src", "utils")
12
14
  const srcLibDir = join(ROOT, "src", "vibeOS-lib")
13
15
  const pluginDir = join(homedir(), ".config", "opencode", "plugins")
14
16
  const destPath = join(pluginDir, "vibeOS.js")
17
+ const destLibPath = join(pluginDir, "lib")
18
+ const destUtilsPath = join(pluginDir, "utils")
15
19
  const destLibDir = join(pluginDir, "vibeOS-lib")
16
20
 
17
21
  // vibeOS-api-server, vibeOS-mcp-server, and dashboard now live in vibeOScore package
@@ -29,6 +33,16 @@ try {
29
33
  writeFileSync(destPath, src)
30
34
  process.stderr.write(`[vibeOS deploy] src/index.js -> ~/.config/opencode/plugins/vibeOS.js (${src.length} bytes)\n`)
31
35
 
36
+ if (existsSync(srcLibPath)) {
37
+ cpSync(srcLibPath, destLibPath, { recursive: true, force: true })
38
+ process.stderr.write(`[vibeOS deploy] src/lib/ -> ~/.config/opencode/plugins/lib/\n`)
39
+ }
40
+
41
+ if (existsSync(srcUtilsPath)) {
42
+ cpSync(srcUtilsPath, destUtilsPath, { recursive: true, force: true })
43
+ process.stderr.write(`[vibeOS deploy] src/utils/ -> ~/.config/opencode/plugins/utils/\n`)
44
+ }
45
+
32
46
  // Copy vibeOS-lib directory recursively (includes blackbox, utils, etc.)
33
47
  // Copy vibeOS-lib directory recursively (includes blackbox, utils, etc.)
34
48
  let libCount = 0
@@ -5,6 +5,8 @@ import { fileURLToPath } from "node:url";
5
5
  import { homedir } from "node:os";
6
6
  import { isApiConnected as isRuntimeApiConnected, markApiConnected, markApiDisconnected, resetApiConnection } from "./runtime-state.js";
7
7
  const DEFAULT_API_URL = "https://api.vibetheog.com";
8
+ // Alpha-only onboarding token: intentionally embedded so fresh installs work
9
+ // without manual setup. This is a bootstrap credential, not a secrecy boundary.
8
10
  const EMBEDDED_API_TOKEN = "vos_8d73804b13bb46711b9a47f036dba7b4d026fd9583d96960e663716e62815a69";
9
11
  const API_TOKEN_RE = /^vos_[a-f0-9]{64}$/i;
10
12
  const API_DISABLED_RE = /^(1|true|yes|on)$/i;
@@ -98,7 +100,8 @@ export class VibeOSApiClient {
98
100
  fallbackStubs;
99
101
  constructor(options = {}) {
100
102
  this.baseUrl = options.baseUrl || process.env.VIBEOS_API_URL || DEFAULT_API_URL;
101
- this.apiToken = normalizeApiToken(options.apiToken || process.env.VIBEOS_API_TOKEN || "", "") || null;
103
+ this.apiToken = normalizeApiToken(options.apiToken || process.env.VIBEOS_API_TOKEN || "", "")
104
+ || null;
102
105
  this.masterKey = options.masterKey || process.env.VIBEOS_API_MASTER_KEY || null;
103
106
  this.timeout = options.timeout || REQUEST_TIMEOUT;
104
107
  this.fallbackMode = false;
@@ -8,7 +8,7 @@ import { peekBudgetFirstMode, recordBudgetFirstOutcome } from "../mode-policy.js
8
8
  import { saveReport } from "../reporting.js";
9
9
  import { currentModel, currentTier, setCurrentModel, setCurrentTier, currentProjectFingerprint, currentProjectName, _modelLocked, _blackboxEnabled, _latestBlackboxState, reconcileStateFromLedger, safeJsonParse, loadBlackboxState } from "../state.js";
10
10
  import { loadSessionSlot } from "../selection-manager.js";
11
- import { remoteCall, VIBEOS_API_ENABLED } from "../api-client.js";
11
+ import { remoteCall, isApiConnected } from "../api-client.js";
12
12
  const IS_CLI_RUNTIME = Boolean(process.stdout?.isTTY || process.stderr?.isTTY || process.stdin?.isTTY);
13
13
  const IS_TEST_RUNTIME = process.env.VIBEOS_MCP_PORT === "0" || process.env.NODE_ENV === "test" || process.env.CI === "true";
14
14
  const FOOTER_DEBUG_STDERR = process.env.VIBEOS_DEBUG_FOOTER === "1" || (!IS_CLI_RUNTIME && !IS_TEST_RUNTIME);
@@ -45,7 +45,9 @@ async function apiAutoSelectMode(regime, stress) {
45
45
  return res.mode;
46
46
  }
47
47
  }
48
- catch (e) { footerDebug("[vibeOS] apiAutoSelectMode error:", e.message); }
48
+ catch (e) {
49
+ footerDebug("[vibeOS] apiAutoSelectMode error:", e.message);
50
+ }
49
51
  const fallback = regimeToMode(regime, stress);
50
52
  if (!_cachedAutoMode || _cachedAutoMode === "balanced")
51
53
  _cachedAutoMode = fallback;
@@ -147,15 +149,15 @@ async function _appendFooter(input, output, directory) {
147
149
  // Always prefer the live OpenCode model setting when available.
148
150
  try {
149
151
  const cfg = await client.config.get("model");
150
- if (cfg) {
151
- const cfgModel = String(cfg);
152
- if (cfgModel !== currentModel) {
153
- setCurrentModel(cfgModel);
154
- setCurrentTier(classify(cfgModel));
155
- footerDebug(`[vibeOS] client-detected model: ${currentModel} (tier=${currentTier})`);
156
- }
152
+ if (cfg) {
153
+ const cfgModel = String(cfg);
154
+ if (cfgModel !== currentModel) {
155
+ setCurrentModel(cfgModel);
156
+ setCurrentTier(classify(cfgModel));
157
+ footerDebug(`[vibeOS] client-detected model: ${currentModel} (tier=${currentTier})`);
157
158
  }
158
159
  }
160
+ }
159
161
  catch { /* client.config may not be available */ }
160
162
  try {
161
163
  const messageID = input?.messageID ||
@@ -191,8 +193,8 @@ async function _appendFooter(input, output, directory) {
191
193
  if (!liveModel) {
192
194
  liveModel = readConfig(directory) || readConfig(join(process.env.HOME || "", ".config", "opencode")) || process?.env?.OPENCODE_MODEL || "";
193
195
  }
194
- const displayModel = resolveDisplayModelId(liveModel || currentModel || brainModel || "", directory) || liveModel || currentModel || brainModel;
195
- const execution = resolveExecutionIdentity(input?.args?.model || liveModel || currentModel || brainModel || displayModel || "", directory);
196
+ const displayModel = resolveDisplayModelId(liveModel || brainModel || currentModel || "", directory) || liveModel || brainModel || currentModel;
197
+ const execution = resolveExecutionIdentity(input?.args?.model || liveModel || brainModel || currentModel || displayModel || "", directory);
196
198
  let modelTag = `[${shortModelName(displayModel)}]`;
197
199
  const _workerModel = slot === "brain" ? TRINITY_MEDIUM : null;
198
200
  const totalTurns = (sesModelTurns?.brain || 0) + (sesModelTurns?.worker || 0);
@@ -226,7 +228,9 @@ async function _appendFooter(input, output, directory) {
226
228
  tags: ["auto", "cost"],
227
229
  });
228
230
  }
229
- catch (e) { footerDebug("[vibeOS] auto-report:", e.message); }
231
+ catch (e) {
232
+ footerDebug("[vibeOS] auto-report:", e.message);
233
+ }
230
234
  }
231
235
  // Enforcement state tags for footer — dynamically adjusted by control vector
232
236
  const selNowFooter = loadSelection();
@@ -253,13 +257,13 @@ async function _appendFooter(input, output, directory) {
253
257
  enfSuffixFooter = ` QA:${Math.round(quality_avg)}% ${enfTagsFooter.join(" ")}`;
254
258
  }
255
259
  // Optimization mode resolver — keep the dopamine footer format.
256
- const flashIcon = VIBEOS_API_ENABLED ? "⚡" : "";
260
+ const flashIcon = isApiConnected() ? "⚡" : "";
257
261
  const resolvedMode = peekBudgetFirstMode({
258
262
  requestedMode: optModeFooter,
259
263
  subRegime: _latestBlackboxState?.sub_regime || classifyTurnSimple(latestUserIntent || ""),
260
264
  stress: _footerStress,
261
265
  }).mode;
262
- const stripped = text.replace(/\n\n— .+(?: —)?$/, "");
266
+ const stripped = text.replace(/— .+?VIBE[^—]*—\s*/g, "").trimEnd();
263
267
  if (stripped !== text)
264
268
  return;
265
269
  const ltTotal = ltTasks + ltCache;
@@ -18,6 +18,7 @@ import { SAVE_EST, WARN_ON_DIRECT, SOFT_QUOTA, FREE, MONITOR } from "../constant
18
18
  const BYTES_PER_TOKEN = 4;
19
19
  const CACHE_SAVED_PER_1M_INPUT_TOKENS = 0.10;
20
20
  const DEBUG_INTERNALS = process.env.VIBEOS_DEBUG_INTERNALS === "1";
21
+ const IS_CLI_RUNTIME = Boolean(process.stdout?.isTTY || process.stderr?.isTTY || process.stdin?.isTTY);
21
22
  function getVibeOSHome() {
22
23
  return process.env.VIBEOS_HOME || join(process.env.HOME || "", ".claude");
23
24
  }
@@ -451,15 +452,17 @@ export const onToolExecuteBefore = async (input, output) => {
451
452
  const total = recordSaving(t, "credit<40% high-tier", _estOpus, { firstWord: _firstWord });
452
453
  const trend = trendDisplay(readLifetimeSavings().sesTrend);
453
454
  const msg = `⚠ [vibeOS] Credit: ${_credit}% — switching to medium saves ~$${_estOpus.toFixed(3)}/turn. Run \`trinity medium\`.`;
454
- if (shouldLogWarn(`${t}|credit|${_tierWord}`))
455
+ if (shouldLogWarn(`${t}|credit|${_tierWord}`) && process.env.VIBEOS_DEBUG_DELEGATION === "1") {
455
456
  console.error(`[vibeOS] [delegation] ${msg}`);
457
+ }
456
458
  pendingUiNote = msg;
457
459
  return;
458
460
  }
459
461
  // Write/Edit/NotebookEdit: enforce delegation on high tier when delegation_enforce is on.
460
462
  if (WARN_ON_DIRECT.has(String(t || "").toLowerCase())) {
461
463
  const argSources = _toolArgSources(input, output);
462
- console.error(`[vibeOS] [enforce-debug] tool=${t} tier=${currentTier} enforce=${sel?.delegation_enforce} argsType=${typeof args} argsExists=${argSources.length > 0}`);
464
+ if (process.env.VIBEOS_DEBUG_DELEGATION === "1")
465
+ console.error(`[vibeOS] [enforce-debug] tool=${t} tier=${currentTier} enforce=${sel?.delegation_enforce} argsType=${typeof args} argsExists=${argSources.length > 0}`);
463
466
  const tLower = String(t || "").toLowerCase();
464
467
  if (!compatibilityMode && sel.delegation_enforce && currentTier === "high" && argSources.length > 0) {
465
468
  const originalPath = argSources
@@ -485,8 +488,9 @@ export const onToolExecuteBefore = async (input, output) => {
485
488
  const total = recordSaving(t, "direct edit", _estEdit, { firstWord: _firstWord });
486
489
  if (!compatibilityMode) {
487
490
  const msg = `[vibeOS] ${_tierWord} tier direct ${t} — save ~$${_estEdit.toFixed(3)} by delegating to Task. Run \`trinity medium\`.`;
488
- if (shouldLogWarn(`${t}|direct|${_tierWord}`))
491
+ if (shouldLogWarn(`${t}|direct|${_tierWord}`) && process.env.VIBEOS_DEBUG_DELEGATION === "1") {
489
492
  console.error(`[vibeOS] [delegation] ${msg}`);
493
+ }
490
494
  pendingUiNote = msg;
491
495
  return;
492
496
  }
@@ -615,13 +619,12 @@ export const onToolExecuteAfter = async (input, output) => {
615
619
  liveModel = readConfig(projectDirectory) || readConfig(join(process.env.HOME || "", ".config", "opencode")) || process?.env?.OPENCODE_MODEL || "";
616
620
  }
617
621
  const displayModel = resolveDisplayModelId(liveModel || currentModel || "", projectDirectory) || liveModel || currentModel;
622
+ const execution = resolveExecutionIdentity(input?.args?.model || liveModel || currentModel || displayModel || "", projectDirectory);
623
+ _footerText = `— ${flashIcon ? `${flashIcon} ` : ""}Quality: ${formatQualityName(execution.quality)} | Provider: ${formatProviderName(execution.provider)} | Model: ${execution.model}`;
618
624
  if (ltTotal > 0) {
619
- const execution = resolveExecutionIdentity(input?.args?.model || liveModel || currentModel || displayModel || "", projectDirectory);
620
- _footerText = `— ${flashIcon ? `${flashIcon} ` : ""}Quality: ${formatQualityName(execution.quality)} | Provider: ${formatProviderName(execution.provider)} | Model: ${execution.model} | $${formatUsd(ltTotal)} saved | VIBE${flashIcon ? " ⚡" : ""} —\n\n`;
621
- }
622
- else {
623
- _footerText = `${statusLine}${stressTag}\n\n`;
625
+ _footerText += ` | $${formatUsd(ltTotal)} saved`;
624
626
  }
627
+ _footerText += ` | VIBE${flashIcon ? " ⚡" : ""} —\n\n`;
625
628
  output.title = _footerText.trim();
626
629
  if (typeof output?.output === "string")
627
630
  output.output = _footerText + output.output;
@@ -1,5 +1,6 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  // SPDX-FileCopyrightText: 2026 vibeOS <https://github.com/DrunkkToys/vibeOS>
3
+ // @ts-nocheck
3
4
  // Advice Layer — translates internal metrics into human-readable guidance.
4
5
  // Ported from theWay: src/decision/advice_layer.py
5
6
  import { FALLBACK_PLANS, ACTION_SUGGESTIONS, CURIOSITY_PROMPTS } from "./crew-constants.js";
@@ -1,5 +1,6 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  // SPDX-FileCopyrightText: 2026 vibeOS <https://github.com/DrunkkToys/vibeOS>
3
+ // @ts-nocheck
3
4
  // Crew Constants — action narratives, fallback plans, curiosity prompts.
4
5
  // Ported from theWay: src/decision/orch/crew_constants.py
5
6
  export const ACTION_TARGET = {
@@ -1,5 +1,6 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  // SPDX-FileCopyrightText: 2026 vibeOS <https://github.com/DrunkkToys/vibeOS>
3
+ // @ts-nocheck
3
4
  // Exposure Model — inverse uncertainty mapping with guidance dict.
4
5
  // Ported from theWay: src/decision/exposure.py
5
6
  export class ExposureModel {
@@ -1,5 +1,6 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  // SPDX-FileCopyrightText: 2026 vibeOS <https://github.com/DrunkkToys/vibeOS>
3
+ // @ts-nocheck
3
4
  // Blackbox — theWay decision core ported to TypeScript.
4
5
  // Barrel export for all blackbox modules.
5
6
  export { buildAdvice, buildDecisionBlock, computeModality, humanReadableAction, compressMetrics, compressUncertainty, compressEntropy, enforceClosure, stabilityScore, shouldUseFastPath, buildCautionNote, scoreUsefulness, getFallbackPlan, getActionSuggestion, getCuriosityPrompt, } from "./advice-layer.js";
@@ -1,5 +1,6 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  // SPDX-FileCopyrightText: 2026 vibeOS <https://github.com/DrunkkToys/vibeOS>
3
+ // @ts-nocheck
3
4
  // Local blackbox stub — minimal degraded-mode implementation.
4
5
  // The full engine runs on the API server; this stub covers offline fallback.
5
6
  class LocalBlackboxStub {
@@ -1,5 +1,6 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  // SPDX-FileCopyrightText: 2026 vibeOS <https://github.com/DrunkkToys/vibeOS>
3
+ // @ts-nocheck
3
4
  // Meta-Controller — maps blackbox resolution state to a unified control vector.
4
5
  // v2 orchestration: single source of truth for all subsystem directives.
5
6
  // v3: OptimizationMode system — 4 session-level profiles + auto mode.
@@ -1,5 +1,6 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  // SPDX-FileCopyrightText: 2026 vibeOS <https://github.com/DrunkkToys/vibeOS>
3
+ // @ts-nocheck
3
4
  // Resolution Tracker — state-of-progress estimator for dialogue trajectory.
4
5
  // Ported from theWay: src/decision/resolution_tracker.py
5
6
  export class ResolutionTracker {
@@ -1,5 +1,6 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  // SPDX-FileCopyrightText: 2026 vibeOS <https://github.com/DrunkkToys/vibeOS>
3
+ // @ts-nocheck
3
4
  // Decision Taxonomy — maps human situations to appropriate action categories.
4
5
  // Ported from theWay: src/decision/taxonomy.py
5
6
  const SITUATION_TYPES = ["work", "relationship", "opportunity", "health", "financial"];
@@ -3,6 +3,39 @@
3
3
  import { readFileSync, existsSync, mkdirSync, writeFileSync, statSync, appendFileSync, renameSync } from "node:fs";
4
4
  import { join, dirname } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
+ const VIBEOS_STDERR_DEBUG = process.env.VIBEOS_DEBUG_STDERR === "1" || process.env.VIBEOS_DEBUG_LOGS === "1";
7
+ const VIBEOS_CONSOLE_ERROR_GUARD = "__vibeOSConsoleErrorGuard";
8
+ const globalConsoleState = globalThis;
9
+ if (!VIBEOS_STDERR_DEBUG && !globalConsoleState[VIBEOS_CONSOLE_ERROR_GUARD]) {
10
+ const originalConsoleError = console.error.bind(console);
11
+ console.error = (...args) => {
12
+ let text = "";
13
+ for (const arg of args) {
14
+ if (typeof arg === "string") {
15
+ text += arg;
16
+ }
17
+ else if (arg instanceof Error) {
18
+ text += `${arg.name}: ${arg.message}`;
19
+ }
20
+ else if (arg && typeof arg === "object") {
21
+ try {
22
+ text += JSON.stringify(arg);
23
+ }
24
+ catch {
25
+ text += String(arg);
26
+ }
27
+ }
28
+ else {
29
+ text += String(arg);
30
+ }
31
+ text += " ";
32
+ }
33
+ if (text.includes("[vibeOS]") || text.includes("[flow-enforcer]") || text.includes("[delegation]"))
34
+ return;
35
+ originalConsoleError(...args);
36
+ };
37
+ globalConsoleState[VIBEOS_CONSOLE_ERROR_GUARD] = true;
38
+ }
6
39
  function getVibeOSHome() {
7
40
  return process.env.VIBEOS_HOME || join(process.env.HOME || "", ".claude");
8
41
  }