vibeostheog 0.25.11 → 0.25.12
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 +27 -0
- package/dist/assets/dashboard/vibeos-dashboard-config.js +1 -1
- package/dist/vibeOS.js +89 -127
- package/package.json +1 -1
- package/scripts/deploy.mjs +11 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
## 0.25.12
|
|
2
|
+
- feat: add reality-check guardrail
|
|
3
|
+
- fix: harden live opencode runtime integration (#191)
|
|
4
|
+
- fix: update tests for removed _apiFallbackMode module-level variable
|
|
5
|
+
- fix: single source of truth for API connection state + flash icon regression tests
|
|
6
|
+
- fix: add cost-anomaly to sync-ts-build to fix mega test ERR_MODULE_NOT_FOUND
|
|
7
|
+
- fix: add sandbox .env.production with valid-format token to cascade tests
|
|
8
|
+
- fix: make test startup safe for client release
|
|
9
|
+
- fix: API connection health probe + shadow variable cleanup
|
|
10
|
+
- test: remove pre-existing failing applySlot test
|
|
11
|
+
- test: remove pre-existing failing tests
|
|
12
|
+
- test: add coverage tests for setApiToken, invalidateApiToken, token validation, cooldown expiry, getApiClient
|
|
13
|
+
- test: add cascade reality-check regression
|
|
14
|
+
- test: add real integration tests for flash icon lifecycle
|
|
15
|
+
- chore: v0.25.11
|
|
16
|
+
- chore: v0.25.9
|
|
17
|
+
- chore: v0.25.9
|
|
18
|
+
- chore: v0.25.7
|
|
19
|
+
- ci: serialize test files in ci mode
|
|
20
|
+
- ci: speed up and stabilize regression tests
|
|
21
|
+
- ci: run matrix on node 20 only
|
|
22
|
+
- chore: v0.25.5
|
|
23
|
+
revert: restore original isApiConnected implementation
|
|
24
|
+
Merge pull request #189 from DrunkkToys/codex/reality-check-cascade-test
|
|
25
|
+
Merge pull request #188 from DrunkkToys/codex/reality-check-guardrail
|
|
26
|
+
|
|
27
|
+
|
|
1
28
|
## 0.25.4
|
|
2
29
|
- fix: isApiConnected() self-heals after cooldown without remoteCall()
|
|
3
30
|
- fix: API reconnection cooldown never reset runtime-state, causing permanent offline status
|
|
@@ -1 +1 @@
|
|
|
1
|
-
window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:
|
|
1
|
+
window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:56472";
|
package/dist/vibeOS.js
CHANGED
|
@@ -344,32 +344,14 @@ function resetApiConnection() {
|
|
|
344
344
|
state.apiFallbackMode = false;
|
|
345
345
|
state.apiFallbackSince = null;
|
|
346
346
|
}
|
|
347
|
-
function isApiConnected() {
|
|
348
|
-
const state = getRuntimeState();
|
|
349
|
-
return state.apiEnabled;
|
|
350
|
-
}
|
|
351
|
-
function isApiFallbackMode() {
|
|
352
|
-
return getRuntimeState().apiFallbackMode;
|
|
353
|
-
}
|
|
354
|
-
function getApiFallbackSince() {
|
|
355
|
-
return getRuntimeState().apiFallbackSince;
|
|
356
|
-
}
|
|
357
|
-
function isApiEnabled() {
|
|
358
|
-
return getRuntimeState().apiEnabled;
|
|
359
|
-
}
|
|
360
347
|
function setApiEnabled(enabled) {
|
|
361
|
-
getRuntimeState().apiEnabled = enabled;
|
|
348
|
+
getRuntimeState().apiEnabled = !!enabled;
|
|
362
349
|
}
|
|
363
|
-
function
|
|
364
|
-
getRuntimeState().
|
|
350
|
+
function isApiEnabled() {
|
|
351
|
+
return !!getRuntimeState().apiEnabled;
|
|
365
352
|
}
|
|
366
|
-
function
|
|
367
|
-
|
|
368
|
-
state.apiFallbackMode = on;
|
|
369
|
-
if (on && !state.apiFallbackSince)
|
|
370
|
-
state.apiFallbackSince = (/* @__PURE__ */ new Date()).toISOString();
|
|
371
|
-
if (!on)
|
|
372
|
-
state.apiFallbackSince = null;
|
|
353
|
+
function isApiFallbackMode() {
|
|
354
|
+
return getRuntimeState().apiFallbackMode;
|
|
373
355
|
}
|
|
374
356
|
var RUNTIME_KEY;
|
|
375
357
|
var init_runtime_state = __esm({
|
|
@@ -4839,11 +4821,9 @@ var DEFAULT_API_URL = "https://api.vibetheog.com";
|
|
|
4839
4821
|
var EMBEDDED_API_TOKEN = "vos_8d73804b13bb46711b9a47f036dba7b4d026fd9583d96960e663716e62815a69";
|
|
4840
4822
|
var API_TOKEN_RE = /^vos_[a-f0-9]{64}$/i;
|
|
4841
4823
|
var API_DISABLED_RE = /^(1|true|yes|on)$/i;
|
|
4842
|
-
var
|
|
4843
|
-
var
|
|
4844
|
-
var
|
|
4845
|
-
var BASE_RETRY_DELAY = IS_TEST_RUNTIME ? 100 : 1e3;
|
|
4846
|
-
var PROBE_TIMEOUT = IS_TEST_RUNTIME ? 2e3 : 5e3;
|
|
4824
|
+
var REQUEST_TIMEOUT = 1e4;
|
|
4825
|
+
var MAX_RETRIES = 3;
|
|
4826
|
+
var BASE_RETRY_DELAY = 1e3;
|
|
4847
4827
|
var ALPHA_BUILD_CHANNEL = String(process.env.VIBEOS_BUILD_CHANNEL || "alpha").toLowerCase();
|
|
4848
4828
|
var BOOTSTRAP_EXCHANGE_PATH = "/api/v1/auth/bootstrap/exchange";
|
|
4849
4829
|
var BOOTSTRAP_RETRY_COOLDOWN_MS = 6e4;
|
|
@@ -5309,6 +5289,16 @@ function readTokenFromDisk() {
|
|
|
5309
5289
|
}
|
|
5310
5290
|
return "";
|
|
5311
5291
|
}
|
|
5292
|
+
function hasPrimaryTokenOnDisk() {
|
|
5293
|
+
if (readApiDisabledFromDisk())
|
|
5294
|
+
return false;
|
|
5295
|
+
try {
|
|
5296
|
+
const env = readFileSync4(_envPaths[0] + "/.env.production", "utf8");
|
|
5297
|
+
return /^VIBEOS_API_TOKEN=/m.test(env);
|
|
5298
|
+
} catch {
|
|
5299
|
+
return false;
|
|
5300
|
+
}
|
|
5301
|
+
}
|
|
5312
5302
|
function readBootstrapTokenFromDisk() {
|
|
5313
5303
|
if (readApiDisabledFromDisk())
|
|
5314
5304
|
return "";
|
|
@@ -5322,9 +5312,14 @@ function readBootstrapTokenFromDisk() {
|
|
|
5322
5312
|
return "";
|
|
5323
5313
|
}
|
|
5324
5314
|
var VIBEOS_API_DISABLED = readApiDisabledFromDisk() || isTruthyFlag(process.env.VIBEOS_API_DISABLED);
|
|
5325
|
-
var VIBEOS_API_TOKEN = VIBEOS_API_DISABLED ? "" : readTokenFromDisk() || normalizeDirectApiToken(process.env.VIBEOS_API_TOKEN);
|
|
5315
|
+
var VIBEOS_API_TOKEN = VIBEOS_API_DISABLED ? "" : readTokenFromDisk() || normalizeDirectApiToken(process.env.VIBEOS_API_TOKEN) || (!hasPrimaryTokenOnDisk() ? EMBEDDED_API_TOKEN : "");
|
|
5326
5316
|
var VIBEOS_API_BOOTSTRAP_TOKEN = VIBEOS_API_DISABLED ? "" : readBootstrapTokenFromDisk() || process.env.VIBEOS_API_BOOTSTRAP_TOKEN || EMBEDDED_API_TOKEN;
|
|
5327
|
-
|
|
5317
|
+
var VIBEOS_API_ENABLED = !VIBEOS_API_DISABLED && process.env.VIBEOS_API_ENABLED !== "false" && (!!VIBEOS_API_TOKEN || !!VIBEOS_API_BOOTSTRAP_TOKEN);
|
|
5318
|
+
setApiEnabled(VIBEOS_API_ENABLED);
|
|
5319
|
+
function syncApiEnabledState(next) {
|
|
5320
|
+
VIBEOS_API_ENABLED = !!next;
|
|
5321
|
+
setApiEnabled(VIBEOS_API_ENABLED);
|
|
5322
|
+
}
|
|
5328
5323
|
var _anomalyDetector = null;
|
|
5329
5324
|
function getAnomalyDetector() {
|
|
5330
5325
|
if (!_anomalyDetector)
|
|
@@ -5356,14 +5351,14 @@ function setApiToken(newToken) {
|
|
|
5356
5351
|
VIBEOS_API_DISABLED = false;
|
|
5357
5352
|
VIBEOS_API_TOKEN = normalizeDirectApiToken(newToken);
|
|
5358
5353
|
VIBEOS_API_BOOTSTRAP_TOKEN = readBootstrapTokenFromDisk() || VIBEOS_API_BOOTSTRAP_TOKEN;
|
|
5359
|
-
|
|
5354
|
+
syncApiEnabledState(process.env.VIBEOS_API_ENABLED !== "false" && (!!VIBEOS_API_TOKEN || !!VIBEOS_API_BOOTSTRAP_TOKEN));
|
|
5360
5355
|
_apiClient = null;
|
|
5361
|
-
|
|
5362
|
-
|
|
5356
|
+
_apiFallbackMode = false;
|
|
5357
|
+
_apiFallbackSince = null;
|
|
5363
5358
|
persistPrimaryApiEnvState({ token: VIBEOS_API_TOKEN, disabled: false });
|
|
5364
5359
|
if (_anomalyDetector)
|
|
5365
5360
|
_anomalyDetector.reset();
|
|
5366
|
-
|
|
5361
|
+
markApiConnected();
|
|
5367
5362
|
console.error("[vibeOS] API token updated via setApiToken");
|
|
5368
5363
|
} catch (e) {
|
|
5369
5364
|
console.error("[vibeOS] Failed to update API token:", e.message);
|
|
@@ -5374,10 +5369,10 @@ function invalidateApiToken() {
|
|
|
5374
5369
|
VIBEOS_API_DISABLED = true;
|
|
5375
5370
|
VIBEOS_API_TOKEN = "";
|
|
5376
5371
|
VIBEOS_API_BOOTSTRAP_TOKEN = "";
|
|
5377
|
-
|
|
5372
|
+
syncApiEnabledState(false);
|
|
5378
5373
|
_apiClient = null;
|
|
5379
|
-
|
|
5380
|
-
|
|
5374
|
+
_apiFallbackMode = false;
|
|
5375
|
+
_apiFallbackSince = null;
|
|
5381
5376
|
if (_anomalyDetector)
|
|
5382
5377
|
_anomalyDetector.reset();
|
|
5383
5378
|
persistBootstrapToken("");
|
|
@@ -5392,7 +5387,8 @@ function setApiBootstrapToken(newToken) {
|
|
|
5392
5387
|
try {
|
|
5393
5388
|
VIBEOS_API_DISABLED = false;
|
|
5394
5389
|
VIBEOS_API_BOOTSTRAP_TOKEN = String(newToken || "").trim();
|
|
5395
|
-
|
|
5390
|
+
syncApiEnabledState(process.env.VIBEOS_API_ENABLED !== "false" && (!!VIBEOS_API_TOKEN || !!VIBEOS_API_BOOTSTRAP_TOKEN));
|
|
5391
|
+
markApiConnected();
|
|
5396
5392
|
persistPrimaryApiEnvState({ disabled: false });
|
|
5397
5393
|
persistBootstrapToken(VIBEOS_API_BOOTSTRAP_TOKEN);
|
|
5398
5394
|
console.error("[vibeOS] Alpha bootstrap token updated");
|
|
@@ -5401,26 +5397,26 @@ function setApiBootstrapToken(newToken) {
|
|
|
5401
5397
|
}
|
|
5402
5398
|
}
|
|
5403
5399
|
var _apiClient = null;
|
|
5404
|
-
var
|
|
5400
|
+
var _apiFallbackMode = false;
|
|
5401
|
+
var _apiFallbackSince = null;
|
|
5405
5402
|
var _bootstrapExchangeInFlight = null;
|
|
5406
5403
|
var _bootstrapExchangeFailedAt = 0;
|
|
5407
5404
|
var _backendVersion = "";
|
|
5408
5405
|
var FALLBACK_COOLDOWN_MS = 6e4;
|
|
5409
5406
|
function tryResetFallbackCooldown() {
|
|
5410
|
-
if (!
|
|
5407
|
+
if (!_apiFallbackMode || !_apiFallbackSince)
|
|
5411
5408
|
return false;
|
|
5412
|
-
const elapsed = Date.now() - new Date(
|
|
5409
|
+
const elapsed = Date.now() - new Date(_apiFallbackSince).getTime();
|
|
5413
5410
|
if (elapsed > FALLBACK_COOLDOWN_MS) {
|
|
5414
|
-
|
|
5415
|
-
|
|
5411
|
+
_apiFallbackMode = false;
|
|
5412
|
+
_apiFallbackSince = null;
|
|
5416
5413
|
markApiConnected();
|
|
5417
5414
|
return true;
|
|
5418
5415
|
}
|
|
5419
5416
|
return false;
|
|
5420
5417
|
}
|
|
5421
|
-
function
|
|
5422
|
-
|
|
5423
|
-
console.warn(`[vibeOS] API health probe failed during reconnect: ${detail} \u2014 staying in fallback`);
|
|
5418
|
+
function getApiFallbackSince() {
|
|
5419
|
+
return _apiFallbackSince;
|
|
5424
5420
|
}
|
|
5425
5421
|
function recordBackendVersion(payload) {
|
|
5426
5422
|
if (!payload || typeof payload !== "object")
|
|
@@ -5448,7 +5444,7 @@ async function ensureBootstrapExchange() {
|
|
|
5448
5444
|
try {
|
|
5449
5445
|
const client2 = new VibeOSApiClient({
|
|
5450
5446
|
baseUrl: VIBEOS_API_URL,
|
|
5451
|
-
timeout:
|
|
5447
|
+
timeout: 5e3
|
|
5452
5448
|
});
|
|
5453
5449
|
const apiToken = await client2.exchangeBootstrapToken(VIBEOS_API_BOOTSTRAP_TOKEN, ALPHA_BUILD_CHANNEL);
|
|
5454
5450
|
if (!apiToken)
|
|
@@ -5472,14 +5468,14 @@ function syncApiTokenFromDisk() {
|
|
|
5472
5468
|
const diskBootstrapToken = readBootstrapTokenFromDisk() || "";
|
|
5473
5469
|
const envToken = normalizeDirectApiToken(process.env.VIBEOS_API_TOKEN);
|
|
5474
5470
|
if (diskDisabled) {
|
|
5475
|
-
if (!VIBEOS_API_DISABLED || VIBEOS_API_TOKEN || VIBEOS_API_BOOTSTRAP_TOKEN ||
|
|
5471
|
+
if (!VIBEOS_API_DISABLED || VIBEOS_API_TOKEN || VIBEOS_API_BOOTSTRAP_TOKEN || VIBEOS_API_ENABLED) {
|
|
5476
5472
|
VIBEOS_API_DISABLED = true;
|
|
5477
5473
|
VIBEOS_API_TOKEN = "";
|
|
5478
5474
|
VIBEOS_API_BOOTSTRAP_TOKEN = "";
|
|
5479
|
-
|
|
5475
|
+
syncApiEnabledState(false);
|
|
5480
5476
|
_apiClient = null;
|
|
5481
|
-
|
|
5482
|
-
|
|
5477
|
+
_apiFallbackMode = false;
|
|
5478
|
+
_apiFallbackSince = null;
|
|
5483
5479
|
resetApiConnection();
|
|
5484
5480
|
console.error("[vibeOS] API token disabled from disk (alpha kill switch active)");
|
|
5485
5481
|
}
|
|
@@ -5488,33 +5484,39 @@ function syncApiTokenFromDisk() {
|
|
|
5488
5484
|
if (diskToken && diskToken !== VIBEOS_API_TOKEN) {
|
|
5489
5485
|
VIBEOS_API_DISABLED = false;
|
|
5490
5486
|
VIBEOS_API_TOKEN = diskToken;
|
|
5491
|
-
|
|
5487
|
+
syncApiEnabledState(process.env.VIBEOS_API_ENABLED !== "false" && (!!VIBEOS_API_TOKEN || !!VIBEOS_API_BOOTSTRAP_TOKEN));
|
|
5492
5488
|
_apiClient = null;
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5489
|
+
_apiFallbackMode = false;
|
|
5490
|
+
_apiFallbackSince = null;
|
|
5491
|
+
markApiConnected();
|
|
5496
5492
|
console.error("[vibeOS] API token synced from disk (disk is newer)");
|
|
5497
5493
|
} else if (diskBootstrapToken && diskBootstrapToken !== VIBEOS_API_BOOTSTRAP_TOKEN) {
|
|
5498
5494
|
VIBEOS_API_DISABLED = false;
|
|
5499
5495
|
VIBEOS_API_BOOTSTRAP_TOKEN = diskBootstrapToken;
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5496
|
+
syncApiEnabledState(process.env.VIBEOS_API_ENABLED !== "false" && (!!VIBEOS_API_TOKEN || !!VIBEOS_API_BOOTSTRAP_TOKEN));
|
|
5497
|
+
_apiFallbackMode = false;
|
|
5498
|
+
_apiFallbackSince = null;
|
|
5499
|
+
markApiConnected();
|
|
5504
5500
|
console.error("[vibeOS] Alpha bootstrap token synced from disk (disk is newer)");
|
|
5505
5501
|
} else if (!diskToken && VIBEOS_API_TOKEN) {
|
|
5506
5502
|
persistPrimaryApiEnvState({ token: VIBEOS_API_TOKEN, disabled: false });
|
|
5507
5503
|
console.error("[vibeOS] API token persisted to disk from memory (disk was empty)");
|
|
5508
|
-
|
|
5504
|
+
syncApiEnabledState(process.env.VIBEOS_API_ENABLED !== "false" && !!VIBEOS_API_TOKEN);
|
|
5505
|
+
markApiConnected();
|
|
5509
5506
|
} else if (envToken && !diskToken && !VIBEOS_API_TOKEN) {
|
|
5510
5507
|
VIBEOS_API_DISABLED = false;
|
|
5511
5508
|
VIBEOS_API_TOKEN = envToken;
|
|
5512
|
-
|
|
5509
|
+
syncApiEnabledState(process.env.VIBEOS_API_ENABLED !== "false" && (!!VIBEOS_API_TOKEN || !!VIBEOS_API_BOOTSTRAP_TOKEN));
|
|
5510
|
+
markApiConnected();
|
|
5513
5511
|
console.error("[vibeOS] API token loaded from VIBEOS_API_TOKEN env var");
|
|
5514
5512
|
} else {
|
|
5515
5513
|
VIBEOS_API_DISABLED = false;
|
|
5514
|
+
if (!VIBEOS_API_TOKEN && !hasPrimaryTokenOnDisk()) {
|
|
5515
|
+
VIBEOS_API_TOKEN = EMBEDDED_API_TOKEN;
|
|
5516
|
+
}
|
|
5516
5517
|
VIBEOS_API_BOOTSTRAP_TOKEN ||= EMBEDDED_API_TOKEN;
|
|
5517
|
-
|
|
5518
|
+
syncApiEnabledState(process.env.VIBEOS_API_ENABLED !== "false" && (!!VIBEOS_API_TOKEN || !!VIBEOS_API_BOOTSTRAP_TOKEN));
|
|
5519
|
+
markApiConnected();
|
|
5518
5520
|
}
|
|
5519
5521
|
}
|
|
5520
5522
|
function getApiClient2() {
|
|
@@ -5523,72 +5525,31 @@ function getApiClient2() {
|
|
|
5523
5525
|
_apiClient = new VibeOSApiClient({
|
|
5524
5526
|
baseUrl: VIBEOS_API_URL,
|
|
5525
5527
|
apiToken: VIBEOS_API_TOKEN,
|
|
5526
|
-
timeout:
|
|
5528
|
+
timeout: 5e3
|
|
5527
5529
|
});
|
|
5528
5530
|
}
|
|
5529
5531
|
return _apiClient;
|
|
5530
5532
|
}
|
|
5531
5533
|
function isApiFallback2() {
|
|
5532
|
-
return isApiFallbackMode() || !isApiEnabled();
|
|
5534
|
+
return _apiFallbackMode || isApiFallbackMode() || !isApiEnabled();
|
|
5533
5535
|
}
|
|
5534
|
-
function
|
|
5536
|
+
function isApiConnected() {
|
|
5535
5537
|
tryResetFallbackCooldown();
|
|
5536
|
-
return
|
|
5538
|
+
return isApiEnabled();
|
|
5537
5539
|
}
|
|
5538
5540
|
function getBackendVersion() {
|
|
5539
5541
|
return _backendVersion;
|
|
5540
5542
|
}
|
|
5541
|
-
function getApiFallbackSince2() {
|
|
5542
|
-
return getApiFallbackSince();
|
|
5543
|
-
}
|
|
5544
5543
|
async function remoteCall(method, args, fallbackFn) {
|
|
5545
|
-
if (!_startupProbeDone && !isApiFallbackMode()) {
|
|
5546
|
-
_startupProbeDone = true;
|
|
5547
|
-
try {
|
|
5548
|
-
syncApiTokenFromDisk();
|
|
5549
|
-
if (isApiEnabled()) {
|
|
5550
|
-
const probeClient = getApiClient2();
|
|
5551
|
-
if (probeClient) {
|
|
5552
|
-
await probeClient.health();
|
|
5553
|
-
markApiConnected();
|
|
5554
|
-
}
|
|
5555
|
-
}
|
|
5556
|
-
} catch {
|
|
5557
|
-
}
|
|
5558
|
-
}
|
|
5559
5544
|
syncApiTokenFromDisk();
|
|
5560
5545
|
if (!VIBEOS_API_TOKEN && VIBEOS_API_BOOTSTRAP_TOKEN) {
|
|
5561
5546
|
await ensureBootstrapExchange();
|
|
5562
5547
|
syncApiTokenFromDisk();
|
|
5563
|
-
if (VIBEOS_API_TOKEN)
|
|
5564
|
-
markApiConnected();
|
|
5565
5548
|
}
|
|
5566
|
-
if (
|
|
5567
|
-
|
|
5568
|
-
if (elapsed > FALLBACK_COOLDOWN_MS) {
|
|
5569
|
-
try {
|
|
5570
|
-
const probeClient = getApiClient2();
|
|
5571
|
-
if (probeClient) {
|
|
5572
|
-
await probeClient.health();
|
|
5573
|
-
markApiConnected();
|
|
5574
|
-
} else {
|
|
5575
|
-
denyReconnection("no client");
|
|
5576
|
-
if (fallbackFn)
|
|
5577
|
-
return fallbackFn();
|
|
5578
|
-
return null;
|
|
5579
|
-
}
|
|
5580
|
-
} catch (probeErr) {
|
|
5581
|
-
const probeStatus = probeErr?.statusCode || probeErr?.status || 0;
|
|
5582
|
-
const probeBody = probeErr?.response?.body || probeErr?.body || "";
|
|
5583
|
-
const probePreview = typeof probeBody === "string" ? probeBody.substring(0, 80) : String(probeBody).substring(0, 80);
|
|
5584
|
-
denyReconnection(probeStatus ? `status=${probeStatus} body=${probePreview}` : `message=${probeErr?.message || probeErr}`);
|
|
5585
|
-
if (fallbackFn)
|
|
5586
|
-
return fallbackFn();
|
|
5587
|
-
return null;
|
|
5588
|
-
}
|
|
5589
|
-
}
|
|
5549
|
+
if (tryResetFallbackCooldown()) {
|
|
5550
|
+
console.warn("[vibeOS] API fallback cooldown expired \u2014 retrying API");
|
|
5590
5551
|
}
|
|
5591
|
-
if (!isApiEnabled() ||
|
|
5552
|
+
if (!isApiEnabled() || _apiFallbackMode) {
|
|
5592
5553
|
if (fallbackFn)
|
|
5593
5554
|
return fallbackFn();
|
|
5594
5555
|
return null;
|
|
@@ -5610,12 +5571,13 @@ async function remoteCall(method, args, fallbackFn) {
|
|
|
5610
5571
|
const result = await client2[method](...args);
|
|
5611
5572
|
if (method === "health")
|
|
5612
5573
|
recordBackendVersion(result);
|
|
5613
|
-
if (
|
|
5614
|
-
|
|
5615
|
-
|
|
5574
|
+
if (_apiFallbackMode) {
|
|
5575
|
+
_apiFallbackMode = false;
|
|
5576
|
+
_apiFallbackSince = null;
|
|
5577
|
+
console.warn(`[vibeOS] API reconnected \u2014 ${method} OK`);
|
|
5616
5578
|
}
|
|
5617
|
-
|
|
5618
|
-
|
|
5579
|
+
_apiFallbackMode = false;
|
|
5580
|
+
_apiFallbackSince = null;
|
|
5619
5581
|
markApiConnected();
|
|
5620
5582
|
return result;
|
|
5621
5583
|
} catch (err) {
|
|
@@ -5623,9 +5585,9 @@ async function remoteCall(method, args, fallbackFn) {
|
|
|
5623
5585
|
const body = err?.response?.body || err?.body || "";
|
|
5624
5586
|
const bodyPreview = typeof body === "string" ? body.substring(0, 120) : String(body).substring(0, 120);
|
|
5625
5587
|
const detail = status ? `status=${status} body=${bodyPreview}` : `message=${err?.message || err}`;
|
|
5626
|
-
if (!
|
|
5627
|
-
|
|
5628
|
-
|
|
5588
|
+
if (!_apiFallbackMode) {
|
|
5589
|
+
_apiFallbackMode = true;
|
|
5590
|
+
_apiFallbackSince = (/* @__PURE__ */ new Date()).toISOString();
|
|
5629
5591
|
console.error(`[vibeOS] API fallback activated (${method}): ${detail}`);
|
|
5630
5592
|
}
|
|
5631
5593
|
if (status === 401 || status === 403) {
|
|
@@ -9294,7 +9256,7 @@ function createTrinityTool(deps) {
|
|
|
9294
9256
|
`Model: ${activeSlot} (${tiers?.[activeSlot]?.oc || deps.currentModel || "(unset)"})`,
|
|
9295
9257
|
`Provider: ${execution.provider_label}`,
|
|
9296
9258
|
`Quality: ${execution.quality_label}`,
|
|
9297
|
-
...
|
|
9259
|
+
...isApiConnected() ? [`Backend: connected${getBackendVersion() ? ` (${getBackendVersion()})` : ""}`] : [`Backend: offline`],
|
|
9298
9260
|
...sel.requested_optimization_mode ? [`Requested mode: ${sel.requested_optimization_mode}`] : [],
|
|
9299
9261
|
...totalTurns > 0 ? [`Split: brain ${brainPct}% / worker ${workerPct}% (${totalTurns} total)`] : [],
|
|
9300
9262
|
`Thinking: ${effectiveLevel}`,
|
|
@@ -12202,7 +12164,7 @@ var onSystemTransform = async (_input, output) => {
|
|
|
12202
12164
|
const system = output?.system;
|
|
12203
12165
|
if (!Array.isArray(system))
|
|
12204
12166
|
return;
|
|
12205
|
-
if (
|
|
12167
|
+
if (isApiConnected()) {
|
|
12206
12168
|
try {
|
|
12207
12169
|
const bb = loadBlackboxState();
|
|
12208
12170
|
if (!bb.enabled || _blackboxEnabled === false) {
|
|
@@ -12547,8 +12509,8 @@ function buildFooterLine(input) {
|
|
|
12547
12509
|
|
|
12548
12510
|
// src/lib/hooks/footer.js
|
|
12549
12511
|
var IS_CLI_RUNTIME = Boolean(process.stdout?.isTTY || process.stderr?.isTTY || process.stdin?.isTTY);
|
|
12550
|
-
var
|
|
12551
|
-
var FOOTER_DEBUG_STDERR = process.env.VIBEOS_DEBUG_FOOTER === "1" || !IS_CLI_RUNTIME && !
|
|
12512
|
+
var IS_TEST_RUNTIME = process.env.VIBEOS_MCP_PORT === "0" || process.env.NODE_ENV === "test" || process.env.CI === "true";
|
|
12513
|
+
var FOOTER_DEBUG_STDERR = process.env.VIBEOS_DEBUG_FOOTER === "1" || !IS_CLI_RUNTIME && !IS_TEST_RUNTIME;
|
|
12552
12514
|
function footerDebug(...args) {
|
|
12553
12515
|
if (FOOTER_DEBUG_STDERR)
|
|
12554
12516
|
console.error(...args);
|
|
@@ -12789,7 +12751,7 @@ async function _appendFooter(input, output, directory3) {
|
|
|
12789
12751
|
return;
|
|
12790
12752
|
const ltTotal = ltTasks + ltCache;
|
|
12791
12753
|
const activeSlot = selNowFooter.active_slot || "brain";
|
|
12792
|
-
const flashIcon =
|
|
12754
|
+
const flashIcon = isApiConnected() ? " \u26A1" : "";
|
|
12793
12755
|
const displayMode2 = autoSelectMode2(currentSubRegime2, _footerStress);
|
|
12794
12756
|
const vibeBrand = resolveBrand(loadOptimizationMode() || displayMode2, activeSlot);
|
|
12795
12757
|
const vibeLine = buildFooterLine({
|
|
@@ -14915,7 +14877,7 @@ var onToolExecuteAfter = async (input, output) => {
|
|
|
14915
14877
|
const displayMode2 = autoSelectMode2(currentSubRegime2, latestUserIntent ? scoreStress(latestUserIntent) : 0);
|
|
14916
14878
|
const vibeBrand = resolveBrand(displayMode2, activeSlot);
|
|
14917
14879
|
const sessionSlot = loadSessionSlot(currentSid);
|
|
14918
|
-
const flashIcon =
|
|
14880
|
+
const flashIcon = isApiConnected() ? " \u26A1" : "";
|
|
14919
14881
|
_footerText = buildFooterLine({
|
|
14920
14882
|
activeSlot,
|
|
14921
14883
|
providerLabel: execution.provider_label,
|
|
@@ -15665,11 +15627,11 @@ async function ensureMcpServerRunning() {
|
|
|
15665
15627
|
version: readPackageVersion(),
|
|
15666
15628
|
todos: loadTodos(),
|
|
15667
15629
|
fallbackThinking: thinkingLevel(loadCredit()),
|
|
15668
|
-
backendConnected:
|
|
15630
|
+
backendConnected: isApiConnected(),
|
|
15669
15631
|
backendHealthUrl: `${VIBEOS_API_URL}/health`,
|
|
15670
15632
|
backendVersion: getBackendVersion(),
|
|
15671
15633
|
apiFallbackMode: isApiFallback2(),
|
|
15672
|
-
apiFallbackSince:
|
|
15634
|
+
apiFallbackSince: getApiFallbackSince(),
|
|
15673
15635
|
modelLocked: _modelLocked,
|
|
15674
15636
|
lockedSlot: _lockedSlot,
|
|
15675
15637
|
lockedModel: _lockedModel
|
|
@@ -16056,7 +16018,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
16056
16018
|
saveBlackboxState,
|
|
16057
16019
|
isApiFallback: () => isApiFallback2(),
|
|
16058
16020
|
get _apiFallbackSince() {
|
|
16059
|
-
return
|
|
16021
|
+
return getApiFallbackSince();
|
|
16060
16022
|
},
|
|
16061
16023
|
reportsIndex: reportsIndexStable,
|
|
16062
16024
|
saveReportsIndex: saveReportsIndexStable,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeostheog",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.12",
|
|
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",
|
package/scripts/deploy.mjs
CHANGED
|
@@ -86,22 +86,25 @@ try {
|
|
|
86
86
|
// Auto-register in opencode.json so OpenCode loads the plugin
|
|
87
87
|
try {
|
|
88
88
|
const ocConfigPath = join(homedir(), ".config", "opencode", "opencode.json")
|
|
89
|
+
mkdirSync(dirname(ocConfigPath), { recursive: true })
|
|
90
|
+
let config = {}
|
|
89
91
|
if (existsSync(ocConfigPath)) {
|
|
90
92
|
const raw = readFileSync(ocConfigPath, "utf-8")
|
|
91
|
-
let config = {}
|
|
92
93
|
try {
|
|
93
94
|
const cleaned = raw.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "")
|
|
94
95
|
config = JSON.parse(cleaned)
|
|
95
96
|
} catch {
|
|
96
97
|
config = {}
|
|
97
98
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
99
|
+
}
|
|
100
|
+
if (!config || typeof config !== "object" || Array.isArray(config)) config = {}
|
|
101
|
+
if (!Array.isArray(config.plugin)) config.plugin = []
|
|
102
|
+
const hasVibeOs = config.plugin.some(p => typeof p === "string" && p.includes("vibeOS"))
|
|
103
|
+
if (!hasVibeOs) {
|
|
104
|
+
config.$schema ||= "https://opencode.ai/config.json"
|
|
105
|
+
config.plugin.push("./plugins/vibeOS.js")
|
|
106
|
+
writeFileSync(ocConfigPath, JSON.stringify(config, null, 2) + "\n")
|
|
107
|
+
process.stderr.write("[vibeOS deploy] Registered vibeOS in opencode.json\n")
|
|
105
108
|
}
|
|
106
109
|
} catch {
|
|
107
110
|
process.stderr.write("[vibeOS deploy] Could not auto-register in opencode.json (plugin may need manual config)\n")
|