vibeostheog 0.24.5 → 0.24.6
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/README.md +1 -1
- package/dist/vibeOS.js +297 -153
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -175,7 +175,7 @@ Local dev checkout:
|
|
|
175
175
|
| Command | Effect |
|
|
176
176
|
|---------|--------|
|
|
177
177
|
| `trinity status` | Tier, enforcement, savings, stress, lock state |
|
|
178
|
-
| `trinity set brain\|medium\|cheap` | Switch active model tier |
|
|
178
|
+
| `trinity set brain\|medium\|cheap [model=<model_id>]` | Switch active model tier or override the slot model |
|
|
179
179
|
| `trinity brain\|medium\|cheap` | Shorthand tier switch |
|
|
180
180
|
| `trinity enable\|disable` | Toggle plugin on/off |
|
|
181
181
|
| `trinity mode budget\|quality\|speed\|longrun\|auto` | Set optimization mode |
|
package/dist/vibeOS.js
CHANGED
|
@@ -1532,7 +1532,7 @@ import { dirname as dirname3 } from "node:path";
|
|
|
1532
1532
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
1533
1533
|
import { homedir } from "node:os";
|
|
1534
1534
|
|
|
1535
|
-
// src/lib/runtime-state.
|
|
1535
|
+
// src/lib/runtime-state.js
|
|
1536
1536
|
var RUNTIME_KEY = "__vibeOSRuntimeState";
|
|
1537
1537
|
function getRuntimeState() {
|
|
1538
1538
|
const g = globalThis;
|
|
@@ -1559,7 +1559,8 @@ function markApiDisconnected() {
|
|
|
1559
1559
|
const state = getRuntimeState();
|
|
1560
1560
|
state.apiConnected = false;
|
|
1561
1561
|
state.apiFallbackMode = true;
|
|
1562
|
-
if (!state.apiFallbackSince)
|
|
1562
|
+
if (!state.apiFallbackSince)
|
|
1563
|
+
state.apiFallbackSince = (/* @__PURE__ */ new Date()).toISOString();
|
|
1563
1564
|
}
|
|
1564
1565
|
function resetApiConnection() {
|
|
1565
1566
|
const state = getRuntimeState();
|
|
@@ -2424,42 +2425,56 @@ function writeSessionOptMode(sid, mode) {
|
|
|
2424
2425
|
}
|
|
2425
2426
|
}
|
|
2426
2427
|
|
|
2427
|
-
// src/lib/pattern-helpers.
|
|
2428
|
+
// src/lib/pattern-helpers.js
|
|
2428
2429
|
import { relative, basename as basename2 } from "node:path";
|
|
2429
2430
|
function normalizeObservedPath(filePath, directory3) {
|
|
2430
|
-
if (!filePath || typeof filePath !== "string")
|
|
2431
|
+
if (!filePath || typeof filePath !== "string")
|
|
2432
|
+
return "unknown";
|
|
2431
2433
|
let p = filePath;
|
|
2432
2434
|
try {
|
|
2433
2435
|
if (directory3 && p.startsWith("/")) {
|
|
2434
2436
|
const rel = relative(directory3, p);
|
|
2435
|
-
if (rel && !rel.startsWith("..") && !rel.startsWith("/"))
|
|
2437
|
+
if (rel && !rel.startsWith("..") && !rel.startsWith("/"))
|
|
2438
|
+
p = rel;
|
|
2436
2439
|
}
|
|
2437
2440
|
} catch {
|
|
2438
2441
|
}
|
|
2439
2442
|
p = p.replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
2440
|
-
if (/^(src\/index\.js|package\.json|README\.md|CHANGELOG\.md|tsconfig\.json)$/i.test(p))
|
|
2443
|
+
if (/^(src\/index\.js|package\.json|README\.md|CHANGELOG\.md|tsconfig\.json)$/i.test(p))
|
|
2444
|
+
return p;
|
|
2441
2445
|
const m = p.match(/\.([a-z0-9]+)$/i);
|
|
2442
|
-
if (p.startsWith("src/") && m)
|
|
2443
|
-
|
|
2446
|
+
if (p.startsWith("src/") && m)
|
|
2447
|
+
return `src/*.${m[1].toLowerCase()}`;
|
|
2448
|
+
if (p.startsWith("tests/") && m)
|
|
2449
|
+
return `tests/*.${m[1].toLowerCase()}`;
|
|
2444
2450
|
return basename2(p) || "unknown";
|
|
2445
2451
|
}
|
|
2446
2452
|
function commandFamily(command) {
|
|
2447
2453
|
const c = String(command || "").trim().toLowerCase();
|
|
2448
|
-
if (!c)
|
|
2449
|
-
|
|
2450
|
-
if (/\
|
|
2451
|
-
|
|
2452
|
-
if (/\bnpm\s+run\s+
|
|
2453
|
-
|
|
2454
|
-
if (/\
|
|
2454
|
+
if (!c)
|
|
2455
|
+
return "unknown";
|
|
2456
|
+
if (/\bnode\s+--check\b/.test(c))
|
|
2457
|
+
return "syntax-check";
|
|
2458
|
+
if (/\bnpm\s+run\s+typecheck\b|\btsc\b.*--noemit/.test(c))
|
|
2459
|
+
return "typecheck";
|
|
2460
|
+
if (/\bnpm\s+test\b|\bnode\s+--test\b|\bvitest\b|\bjest\b|\bpytest\b/.test(c))
|
|
2461
|
+
return "test";
|
|
2462
|
+
if (/\bnpm\s+run\s+build\b|\btsc\s+-p\b/.test(c))
|
|
2463
|
+
return "build";
|
|
2464
|
+
if (/\bgit\s+status\b/.test(c))
|
|
2465
|
+
return "git-status";
|
|
2466
|
+
if (/\bgit\s+commit\b/.test(c))
|
|
2467
|
+
return "git-commit";
|
|
2455
2468
|
const first = c.replace(/^[a-z_][a-z0-9_]*=\S+\s+/g, "").split(/\s+/)[0];
|
|
2456
2469
|
return /^[a-z0-9._/-]{1,30}$/.test(first) ? first : "command";
|
|
2457
2470
|
}
|
|
2458
2471
|
function commandFailed(output) {
|
|
2459
2472
|
const code = output?.exitCode ?? output?.statusCode ?? output?.code;
|
|
2460
|
-
if (Number.isFinite(Number(code)) && Number(code) !== 0)
|
|
2473
|
+
if (Number.isFinite(Number(code)) && Number(code) !== 0)
|
|
2474
|
+
return true;
|
|
2461
2475
|
const raw = output?.result ?? output?.text ?? output?.content ?? output?.data ?? "";
|
|
2462
|
-
if (typeof raw !== "string")
|
|
2476
|
+
if (typeof raw !== "string")
|
|
2477
|
+
return false;
|
|
2463
2478
|
return /\b(exit code|exited with code)\s*[:=]?\s*[1-9]\b|\b(assertionerror|syntaxerror|typeerror|referenceerror)\b|\b(failed|error:|err!)\b/i.test(raw);
|
|
2464
2479
|
}
|
|
2465
2480
|
function mergeProjectBucket(dst, src) {
|
|
@@ -2476,7 +2491,8 @@ function mergeProjectBucket(dst, src) {
|
|
|
2476
2491
|
row.sessions = [.../* @__PURE__ */ new Set([...row.sessions || [], ...v?.sessions || []])].slice(-10);
|
|
2477
2492
|
row.lastSeen = [row.lastSeen, v?.lastSeen].filter(Boolean).sort().slice(-1)[0] || null;
|
|
2478
2493
|
row.summary = row.summary || v?.summary || "";
|
|
2479
|
-
if (v?.kind)
|
|
2494
|
+
if (v?.kind)
|
|
2495
|
+
row.kind = v.kind;
|
|
2480
2496
|
out[key] = row;
|
|
2481
2497
|
}
|
|
2482
2498
|
}
|
|
@@ -2495,9 +2511,11 @@ function mergeProjectBucket(dst, src) {
|
|
|
2495
2511
|
};
|
|
2496
2512
|
}
|
|
2497
2513
|
function _pruneOldSessions(state) {
|
|
2498
|
-
if (!state?.sessions)
|
|
2514
|
+
if (!state?.sessions)
|
|
2515
|
+
return;
|
|
2499
2516
|
const entries = Object.entries(state.sessions);
|
|
2500
|
-
if (entries.length <= 30)
|
|
2517
|
+
if (entries.length <= 30)
|
|
2518
|
+
return;
|
|
2501
2519
|
entries.sort((a, b) => {
|
|
2502
2520
|
const da = a[1]?.started || a[1]?.last_costed || "";
|
|
2503
2521
|
const db = b[1]?.started || b[1]?.last_costed || "";
|
|
@@ -5574,7 +5592,7 @@ function applySlot2(slot, projectDir = "") {
|
|
|
5574
5592
|
writeFileSync5(ocConfig, JSON.stringify(oc, null, 2) + "\n");
|
|
5575
5593
|
}
|
|
5576
5594
|
clearWorkspaceFollowupPauseForSession(getCurrentSessionId());
|
|
5577
|
-
_refreshModel(
|
|
5595
|
+
_refreshModel(dir);
|
|
5578
5596
|
return { ok: true, ocModel };
|
|
5579
5597
|
} catch (err) {
|
|
5580
5598
|
return { ok: false, reason: err.message };
|
|
@@ -7480,6 +7498,15 @@ function createTrinityTool(deps) {
|
|
|
7480
7498
|
const _brandedModeIds = ["vibeultrax", "vibeqmax", "vibemax", "vibelitex"];
|
|
7481
7499
|
const _builtInModeIds = ["budget", "quality", "speed", "longrun", "auto", "balanced", "audit", "forensic"];
|
|
7482
7500
|
if (!action || action === "status") {
|
|
7501
|
+
if (slot && (_brandedModeIds.includes(slot) || _builtInModeIds.includes(slot))) {
|
|
7502
|
+
action = "mode";
|
|
7503
|
+
} else if (["brain", "medium", "cheap"].includes(slot)) {
|
|
7504
|
+
action = "set";
|
|
7505
|
+
} else if (["full", "brief", "off"].includes(slot)) {
|
|
7506
|
+
action = "thinking";
|
|
7507
|
+
level = slot;
|
|
7508
|
+
slot = void 0;
|
|
7509
|
+
}
|
|
7483
7510
|
} else if (_brandedModeIds.includes(action) || _builtInModeIds.includes(action)) {
|
|
7484
7511
|
slot = action;
|
|
7485
7512
|
action = "mode";
|
|
@@ -7664,10 +7691,10 @@ function createTrinityTool(deps) {
|
|
|
7664
7691
|
console.error("[vibeOS] WARN: probe error for " + targetModel + ": " + e.message + " - switching anyway");
|
|
7665
7692
|
}
|
|
7666
7693
|
deps.writeSessionSlot(deps._OC_SID, slot);
|
|
7667
|
-
const result = deps.applySlot(slot);
|
|
7694
|
+
const result = deps.applySlot(slot, deps.directory);
|
|
7668
7695
|
if (!result.ok) return `\u274C Failed to set slot: ${result.reason}`;
|
|
7669
7696
|
try {
|
|
7670
|
-
const selected =
|
|
7697
|
+
const selected = resolveExecutionIdentity(result.ocModel, deps.directory);
|
|
7671
7698
|
if (selected) {
|
|
7672
7699
|
deps.writeSelection("selected_provider", selected.provider || "");
|
|
7673
7700
|
deps.writeSelection("selected_quality_tier", selected.quality || slot);
|
|
@@ -8922,7 +8949,7 @@ import { readFileSync as readFileSync13, writeFileSync as writeFileSync13, appen
|
|
|
8922
8949
|
import { join as join14, dirname as dirname11, basename as basename7 } from "node:path";
|
|
8923
8950
|
import { createHash as createHash3 } from "node:crypto";
|
|
8924
8951
|
|
|
8925
|
-
// src/lib/mode-policy.
|
|
8952
|
+
// src/lib/mode-policy.js
|
|
8926
8953
|
var STRESS_QUALITY_THRESHOLD = 1.5;
|
|
8927
8954
|
var BASELINE_MODE = "budget";
|
|
8928
8955
|
var LOOP_REGIMES = /* @__PURE__ */ new Set(["LOOPING", "DIVERGENT"]);
|
|
@@ -8930,7 +8957,8 @@ var QUALITY_REGIMES = /* @__PURE__ */ new Set(["CONVERGING", "CLOSED"]);
|
|
|
8930
8957
|
var MANUAL_MODES = /* @__PURE__ */ new Set(["balanced", "quality", "speed", "longrun", "vibemax", "vibeqmax", "vibeultrax"]);
|
|
8931
8958
|
function normalizeMode(mode) {
|
|
8932
8959
|
const normalized = String(mode || BASELINE_MODE).toLowerCase();
|
|
8933
|
-
if (normalized === "auto" || normalized === "")
|
|
8960
|
+
if (normalized === "auto" || normalized === "")
|
|
8961
|
+
return BASELINE_MODE;
|
|
8934
8962
|
if (normalized === "budget" || normalized === "quality" || normalized === "speed" || normalized === "longrun" || normalized === "balanced" || normalized === "vibemax" || normalized === "vibeqmax" || normalized === "vibeultrax") {
|
|
8935
8963
|
return normalized;
|
|
8936
8964
|
}
|
|
@@ -8943,9 +8971,12 @@ function isManualOverride(mode) {
|
|
|
8943
8971
|
return MANUAL_MODES.has(normalizeMode(mode));
|
|
8944
8972
|
}
|
|
8945
8973
|
function chooseEpisodeMode(regime, suggestedMode, stress) {
|
|
8946
|
-
if (suggestedMode === "vibeultrax" || suggestedMode === "vibeqmax" || suggestedMode === "vibemax")
|
|
8947
|
-
|
|
8948
|
-
if (
|
|
8974
|
+
if (suggestedMode === "vibeultrax" || suggestedMode === "vibeqmax" || suggestedMode === "vibemax")
|
|
8975
|
+
return suggestedMode;
|
|
8976
|
+
if (LOOP_REGIMES.has(regime) || suggestedMode === "speed")
|
|
8977
|
+
return "speed";
|
|
8978
|
+
if (QUALITY_REGIMES.has(regime) || suggestedMode === "quality")
|
|
8979
|
+
return "quality";
|
|
8949
8980
|
return stress > STRESS_QUALITY_THRESHOLD ? "quality" : "budget";
|
|
8950
8981
|
}
|
|
8951
8982
|
function defaultPolicy() {
|
|
@@ -8966,15 +8997,19 @@ function defaultPolicy() {
|
|
|
8966
8997
|
}
|
|
8967
8998
|
function modeToSlot(mode) {
|
|
8968
8999
|
const normalized = normalizeMode(mode);
|
|
8969
|
-
if (normalized === "speed")
|
|
8970
|
-
|
|
9000
|
+
if (normalized === "speed")
|
|
9001
|
+
return "medium";
|
|
9002
|
+
if (normalized === "quality" || normalized === "longrun" || normalized === "vibeultrax" || normalized === "vibeqmax")
|
|
9003
|
+
return "brain";
|
|
8971
9004
|
return "cheap";
|
|
8972
9005
|
}
|
|
8973
9006
|
function loadSessionPolicy() {
|
|
8974
9007
|
const state = loadBlackboxState();
|
|
8975
|
-
if (!state.sessions || typeof state.sessions !== "object")
|
|
9008
|
+
if (!state.sessions || typeof state.sessions !== "object")
|
|
9009
|
+
state.sessions = {};
|
|
8976
9010
|
const sid = _OC_SID;
|
|
8977
|
-
if (!state.sessions[sid] || typeof state.sessions[sid] !== "object")
|
|
9011
|
+
if (!state.sessions[sid] || typeof state.sessions[sid] !== "object")
|
|
9012
|
+
state.sessions[sid] = {};
|
|
8978
9013
|
const session = state.sessions[sid];
|
|
8979
9014
|
if (!session.mode_policy || typeof session.mode_policy !== "object") {
|
|
8980
9015
|
session.mode_policy = defaultPolicy();
|
|
@@ -9102,7 +9137,7 @@ function recordBudgetFirstOutcome(input = {}) {
|
|
|
9102
9137
|
import { join as join13 } from "node:path";
|
|
9103
9138
|
import { writeFileSync as writeFileSync12 } from "node:fs";
|
|
9104
9139
|
|
|
9105
|
-
// src/lib/text-compress.
|
|
9140
|
+
// src/lib/text-compress.js
|
|
9106
9141
|
var VERBOSE_LINE_RE = [
|
|
9107
9142
|
/^[\s#*/\\\-_=+|~:;'"`@\$%^&<>{}\[\]()!?.,0-9]+$/,
|
|
9108
9143
|
/^(Filed|Created|Modified|Deleted|Updated|Renamed|Copied|Moved|Changed):/,
|
|
@@ -9119,12 +9154,15 @@ function extractBulletLines(lines, targetChars, minLines) {
|
|
|
9119
9154
|
const keyLines = [];
|
|
9120
9155
|
const otherLines = [];
|
|
9121
9156
|
for (const line of lines) {
|
|
9122
|
-
if (BULLET_PATTERNS.some((re) => re.test(line)))
|
|
9123
|
-
|
|
9157
|
+
if (BULLET_PATTERNS.some((re) => re.test(line)))
|
|
9158
|
+
keyLines.push(line);
|
|
9159
|
+
else
|
|
9160
|
+
otherLines.push(line);
|
|
9124
9161
|
}
|
|
9125
9162
|
const selected = [...keyLines];
|
|
9126
9163
|
for (const line of otherLines) {
|
|
9127
|
-
if (selected.length >= minLines && selected.join("\n").length >= targetChars)
|
|
9164
|
+
if (selected.length >= minLines && selected.join("\n").length >= targetChars)
|
|
9165
|
+
break;
|
|
9128
9166
|
selected.push(line);
|
|
9129
9167
|
}
|
|
9130
9168
|
while (selected.length > minLines && selected.join("\n").length > targetChars * 2) {
|
|
@@ -9133,7 +9171,8 @@ function extractBulletLines(lines, targetChars, minLines) {
|
|
|
9133
9171
|
return selected;
|
|
9134
9172
|
}
|
|
9135
9173
|
function compressText(text) {
|
|
9136
|
-
if (!text || typeof text !== "string")
|
|
9174
|
+
if (!text || typeof text !== "string")
|
|
9175
|
+
return text;
|
|
9137
9176
|
let lines = text.split("\n");
|
|
9138
9177
|
let removed = 0;
|
|
9139
9178
|
const out = [];
|
|
@@ -9146,14 +9185,16 @@ function compressText(text) {
|
|
|
9146
9185
|
break;
|
|
9147
9186
|
}
|
|
9148
9187
|
}
|
|
9149
|
-
if (!skip)
|
|
9188
|
+
if (!skip)
|
|
9189
|
+
out.push(line);
|
|
9150
9190
|
}
|
|
9151
9191
|
const collapsed = [];
|
|
9152
9192
|
let blanks = 0;
|
|
9153
9193
|
for (const line of out) {
|
|
9154
9194
|
if (line.trim() === "") {
|
|
9155
9195
|
blanks++;
|
|
9156
|
-
if (blanks <= 2)
|
|
9196
|
+
if (blanks <= 2)
|
|
9197
|
+
collapsed.push(line);
|
|
9157
9198
|
} else {
|
|
9158
9199
|
blanks = 0;
|
|
9159
9200
|
collapsed.push(line);
|
|
@@ -9161,10 +9202,7 @@ function compressText(text) {
|
|
|
9161
9202
|
}
|
|
9162
9203
|
let result = collapsed.join("\n").trim();
|
|
9163
9204
|
if (result.length > COMPRESS_THRESHOLD) {
|
|
9164
|
-
const targetChars = Math.max(
|
|
9165
|
-
Math.round(result.length * COMPRESS_RATIO),
|
|
9166
|
-
COMPRESS_THRESHOLD
|
|
9167
|
-
);
|
|
9205
|
+
const targetChars = Math.max(Math.round(result.length * COMPRESS_RATIO), COMPRESS_THRESHOLD);
|
|
9168
9206
|
const minLines = Math.max(1, Math.round(collapsed.length * MIN_KEPT_LINES_RATIO));
|
|
9169
9207
|
const bulletLines = extractBulletLines(collapsed, targetChars, minLines);
|
|
9170
9208
|
result = bulletLines.join("\n").trim();
|
|
@@ -9463,7 +9501,7 @@ function recordSaving(tool2, reason, saveEst, meta = {}) {
|
|
|
9463
9501
|
}
|
|
9464
9502
|
}
|
|
9465
9503
|
|
|
9466
|
-
// src/lib/constants.
|
|
9504
|
+
// src/lib/constants.js
|
|
9467
9505
|
var SAVE_EST = {
|
|
9468
9506
|
// Realistic: v4-pro (0.00057) - v4-flash (0.000182) = 0.000388/turn
|
|
9469
9507
|
WRITE_EDIT: 4e-4,
|
|
@@ -9481,7 +9519,7 @@ var COMPRESS_MARKER = "[ctx-compressed-v1]";
|
|
|
9481
9519
|
var PROTOCOL_MARKER = "[wbp-v1]";
|
|
9482
9520
|
var PROTOCOL_TEXT = PROTOCOL_MARKER + " [Worker-to-Brain Report Protocol] When synthesizing the preceding Task output: 1) EXTRACT core findings/data. 2) REFORMAT into bullet points. 3) VERIFY against the original ask. 4) SYNTHESIZE into final response.";
|
|
9483
9521
|
|
|
9484
|
-
// src/lib/templates.
|
|
9522
|
+
// src/lib/templates.js
|
|
9485
9523
|
var TEMPLATES = {
|
|
9486
9524
|
save: {
|
|
9487
9525
|
tier_bias: "cheap",
|
|
@@ -9520,7 +9558,8 @@ var TEMPLATES = {
|
|
|
9520
9558
|
var DEFAULT_TEMPLATE = "save";
|
|
9521
9559
|
var SEC_KEYWORDS = /\b(security|vuln|exploit|injection|xss|csrf|secret|credential|token leak|auth bypass|privacy|breach|backdoor|sql injection|cve)\b/i;
|
|
9522
9560
|
function detectSecuritySignal(text) {
|
|
9523
|
-
if (!text || typeof text !== "string")
|
|
9561
|
+
if (!text || typeof text !== "string")
|
|
9562
|
+
return false;
|
|
9524
9563
|
return SEC_KEYWORDS.test(text);
|
|
9525
9564
|
}
|
|
9526
9565
|
function detectBudgetSignal(creditPercent) {
|
|
@@ -9533,16 +9572,21 @@ function detectStressSpike(stressScore) {
|
|
|
9533
9572
|
return delta > 0.3 && stressScore > 0.5;
|
|
9534
9573
|
}
|
|
9535
9574
|
function resolveTemplate(prevTemplate, stressScore, userText, creditPercent) {
|
|
9536
|
-
if (detectSecuritySignal(userText))
|
|
9537
|
-
|
|
9538
|
-
if (
|
|
9575
|
+
if (detectSecuritySignal(userText))
|
|
9576
|
+
return "security";
|
|
9577
|
+
if (detectBudgetSignal(creditPercent))
|
|
9578
|
+
return "save";
|
|
9579
|
+
if (detectStressSpike(stressScore))
|
|
9580
|
+
return "quality";
|
|
9539
9581
|
return prevTemplate || DEFAULT_TEMPLATE;
|
|
9540
9582
|
}
|
|
9541
9583
|
var _turnCount = 0;
|
|
9542
9584
|
function shouldInjectTemplate(template, prevTemplate) {
|
|
9543
9585
|
_turnCount++;
|
|
9544
|
-
if (template !== prevTemplate)
|
|
9545
|
-
|
|
9586
|
+
if (template !== prevTemplate)
|
|
9587
|
+
return true;
|
|
9588
|
+
if (_turnCount % 10 === 0)
|
|
9589
|
+
return true;
|
|
9546
9590
|
return false;
|
|
9547
9591
|
}
|
|
9548
9592
|
|
|
@@ -10649,7 +10693,7 @@ import { writeFileSync as writeFileSync16, appendFileSync as appendFileSync9, ex
|
|
|
10649
10693
|
import { join as join17, dirname as dirname14, basename as basename9 } from "node:path";
|
|
10650
10694
|
import { createHash as createHash5 } from "node:crypto";
|
|
10651
10695
|
|
|
10652
|
-
// src/lib/cost-anomaly.
|
|
10696
|
+
// src/lib/cost-anomaly.js
|
|
10653
10697
|
var COST_WINDOW_SIZE = 20;
|
|
10654
10698
|
var COST_ANOMALY_THRESHOLD = 3;
|
|
10655
10699
|
var COST_WARMUP_SAMPLES = 5;
|
|
@@ -10660,21 +10704,26 @@ var CostAnomalyDetector = class {
|
|
|
10660
10704
|
currentAnomalyCost = 0;
|
|
10661
10705
|
currentAnomalyMean = 0;
|
|
10662
10706
|
record(cost) {
|
|
10663
|
-
if (this.disabled)
|
|
10707
|
+
if (this.disabled)
|
|
10708
|
+
return;
|
|
10664
10709
|
this.costHistory.push(cost);
|
|
10665
10710
|
if (this.costHistory.length > COST_WINDOW_SIZE) {
|
|
10666
10711
|
this.costHistory.shift();
|
|
10667
10712
|
}
|
|
10668
10713
|
}
|
|
10669
10714
|
get mean() {
|
|
10670
|
-
if (this.costHistory.length === 0)
|
|
10715
|
+
if (this.costHistory.length === 0)
|
|
10716
|
+
return 0;
|
|
10671
10717
|
return this.costHistory.reduce((a, b) => a + b, 0) / this.costHistory.length;
|
|
10672
10718
|
}
|
|
10673
10719
|
checkAnomaly(model, cost) {
|
|
10674
|
-
if (this.disabled)
|
|
10675
|
-
|
|
10720
|
+
if (this.disabled)
|
|
10721
|
+
return false;
|
|
10722
|
+
if (this.costHistory.length < COST_WARMUP_SAMPLES)
|
|
10723
|
+
return false;
|
|
10676
10724
|
const avg = this.mean;
|
|
10677
|
-
if (avg <= 0 || cost <= avg)
|
|
10725
|
+
if (avg <= 0 || cost <= avg)
|
|
10726
|
+
return false;
|
|
10678
10727
|
const ratio = cost / avg;
|
|
10679
10728
|
if (ratio > COST_ANOMALY_THRESHOLD) {
|
|
10680
10729
|
this.currentAnomalyModel = model;
|
|
@@ -10696,7 +10745,8 @@ var CostAnomalyDetector = class {
|
|
|
10696
10745
|
};
|
|
10697
10746
|
var _costDetector = null;
|
|
10698
10747
|
function getCostAnomalyDetector() {
|
|
10699
|
-
if (!_costDetector)
|
|
10748
|
+
if (!_costDetector)
|
|
10749
|
+
_costDetector = new CostAnomalyDetector();
|
|
10700
10750
|
return _costDetector;
|
|
10701
10751
|
}
|
|
10702
10752
|
|
|
@@ -10708,9 +10758,10 @@ import { readFileSync as readFileSync15, writeFileSync as writeFileSync15, appen
|
|
|
10708
10758
|
import { join as join16, dirname as dirname13 } from "node:path";
|
|
10709
10759
|
import { createHash as createHash4 } from "node:crypto";
|
|
10710
10760
|
|
|
10711
|
-
// src/utils/tdd-helpers.
|
|
10761
|
+
// src/utils/tdd-helpers.js
|
|
10712
10762
|
function extractExports(sourceContent, ext) {
|
|
10713
|
-
if (!sourceContent || typeof sourceContent !== "string")
|
|
10763
|
+
if (!sourceContent || typeof sourceContent !== "string")
|
|
10764
|
+
return [];
|
|
10714
10765
|
const exports = [];
|
|
10715
10766
|
const seen = /* @__PURE__ */ new Set();
|
|
10716
10767
|
const add = (name, type = "function") => {
|
|
@@ -10721,51 +10772,69 @@ function extractExports(sourceContent, ext) {
|
|
|
10721
10772
|
};
|
|
10722
10773
|
switch (ext) {
|
|
10723
10774
|
case "py": {
|
|
10724
|
-
for (const m of sourceContent.matchAll(/^def\s+([a-zA-Z]\w*)\s*\(/gm))
|
|
10725
|
-
|
|
10775
|
+
for (const m of sourceContent.matchAll(/^def\s+([a-zA-Z]\w*)\s*\(/gm))
|
|
10776
|
+
add(m[1]);
|
|
10777
|
+
for (const m of sourceContent.matchAll(/^class\s+([a-zA-Z_]\w*)\s*[\(:]/gm))
|
|
10778
|
+
add(m[1], "class");
|
|
10726
10779
|
break;
|
|
10727
10780
|
}
|
|
10728
10781
|
case "js":
|
|
10729
10782
|
case "mjs":
|
|
10730
10783
|
case "jsx": {
|
|
10731
|
-
for (const m of sourceContent.matchAll(/export\s+(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
10732
|
-
|
|
10784
|
+
for (const m of sourceContent.matchAll(/export\s+(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
10785
|
+
add(m[1]);
|
|
10786
|
+
for (const m of sourceContent.matchAll(/export\s+const\s+([a-zA-Z_$]\w*)\s*=/g))
|
|
10787
|
+
add(m[1]);
|
|
10733
10788
|
if (exports.length === 0) {
|
|
10734
|
-
for (const m of sourceContent.matchAll(/^(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/gm))
|
|
10789
|
+
for (const m of sourceContent.matchAll(/^(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/gm))
|
|
10790
|
+
add(m[1]);
|
|
10735
10791
|
}
|
|
10736
10792
|
break;
|
|
10737
10793
|
}
|
|
10738
10794
|
case "ts":
|
|
10739
10795
|
case "tsx": {
|
|
10740
|
-
for (const m of sourceContent.matchAll(/export\s+(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
10741
|
-
|
|
10742
|
-
for (const m of sourceContent.matchAll(/export\s+
|
|
10796
|
+
for (const m of sourceContent.matchAll(/export\s+(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
10797
|
+
add(m[1]);
|
|
10798
|
+
for (const m of sourceContent.matchAll(/export\s+const\s+([a-zA-Z_$]\w*)\s*[:=]/g))
|
|
10799
|
+
add(m[1]);
|
|
10800
|
+
for (const m of sourceContent.matchAll(/export\s+class\s+([a-zA-Z_$]\w*)/g))
|
|
10801
|
+
add(m[1], "class");
|
|
10743
10802
|
break;
|
|
10744
10803
|
}
|
|
10745
10804
|
case "go": {
|
|
10746
|
-
for (const m of sourceContent.matchAll(/func\s+(?:\([^)]+\)\s+)?([A-Z]\w*)\s*\(/g))
|
|
10805
|
+
for (const m of sourceContent.matchAll(/func\s+(?:\([^)]+\)\s+)?([A-Z]\w*)\s*\(/g))
|
|
10806
|
+
add(m[1]);
|
|
10747
10807
|
break;
|
|
10748
10808
|
}
|
|
10749
10809
|
case "rs": {
|
|
10750
|
-
for (const m of sourceContent.matchAll(/pub\s+fn\s+([a-zA-Z_]\w*)\s*</g))
|
|
10751
|
-
|
|
10752
|
-
for (const m of sourceContent.matchAll(/pub\s+
|
|
10810
|
+
for (const m of sourceContent.matchAll(/pub\s+fn\s+([a-zA-Z_]\w*)\s*</g))
|
|
10811
|
+
add(m[1]);
|
|
10812
|
+
for (const m of sourceContent.matchAll(/pub\s+fn\s+([a-zA-Z_]\w*)\s*\(/g))
|
|
10813
|
+
add(m[1]);
|
|
10814
|
+
for (const m of sourceContent.matchAll(/pub\s+struct\s+([a-zA-Z_]\w*)/g))
|
|
10815
|
+
add(m[1], "struct");
|
|
10753
10816
|
break;
|
|
10754
10817
|
}
|
|
10755
10818
|
case "rb": {
|
|
10756
|
-
for (const m of sourceContent.matchAll(/def\s+(?:self\.)?([a-zA-Z_]\w*[?!=]?)/g))
|
|
10757
|
-
|
|
10819
|
+
for (const m of sourceContent.matchAll(/def\s+(?:self\.)?([a-zA-Z_]\w*[?!=]?)/g))
|
|
10820
|
+
add(m[1]);
|
|
10821
|
+
for (const m of sourceContent.matchAll(/class\s+([A-Z]\w*)/g))
|
|
10822
|
+
add(m[1], "class");
|
|
10758
10823
|
break;
|
|
10759
10824
|
}
|
|
10760
10825
|
case "java":
|
|
10761
10826
|
case "kt": {
|
|
10762
|
-
for (const m of sourceContent.matchAll(/(?:public|protected)\s+(?:static\s+)?(?:final\s+)?\S+\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
10763
|
-
|
|
10827
|
+
for (const m of sourceContent.matchAll(/(?:public|protected)\s+(?:static\s+)?(?:final\s+)?\S+\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
10828
|
+
add(m[1]);
|
|
10829
|
+
for (const m of sourceContent.matchAll(/fun\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
10830
|
+
add(m[1]);
|
|
10764
10831
|
break;
|
|
10765
10832
|
}
|
|
10766
10833
|
case "sh": {
|
|
10767
|
-
for (const m of sourceContent.matchAll(/^(?:function\s+)?([a-zA-Z_]\w*)\s*\(\)\s*\{/gm))
|
|
10768
|
-
|
|
10834
|
+
for (const m of sourceContent.matchAll(/^(?:function\s+)?([a-zA-Z_]\w*)\s*\(\)\s*\{/gm))
|
|
10835
|
+
add(m[1]);
|
|
10836
|
+
for (const m of sourceContent.matchAll(/^function\s+([a-zA-Z_]\w*)/gm))
|
|
10837
|
+
add(m[1]);
|
|
10769
10838
|
break;
|
|
10770
10839
|
}
|
|
10771
10840
|
}
|
|
@@ -10787,7 +10856,8 @@ function generateTestCaseNames(funcName, _type, quality = false) {
|
|
|
10787
10856
|
];
|
|
10788
10857
|
}
|
|
10789
10858
|
function inferFunctionParams(sourceContent, funcName) {
|
|
10790
|
-
if (!sourceContent || !funcName)
|
|
10859
|
+
if (!sourceContent || !funcName)
|
|
10860
|
+
return [];
|
|
10791
10861
|
const patterns = [
|
|
10792
10862
|
new RegExp(`(?:export\\s+)?(?:async\\s+)?function\\s+${funcName}\\s*\\(([^)]*)\\)`, "m"),
|
|
10793
10863
|
new RegExp(`(?:export\\s+)?const\\s+${funcName}\\s*[:=]\\s*(?:async\\s+)?\\(([^)]*)\\)`, "m"),
|
|
@@ -10800,7 +10870,8 @@ function inferFunctionParams(sourceContent, funcName) {
|
|
|
10800
10870
|
if (m) {
|
|
10801
10871
|
return m[1].split(",").map((s) => {
|
|
10802
10872
|
const trimmed = s.trim();
|
|
10803
|
-
if (!trimmed)
|
|
10873
|
+
if (!trimmed)
|
|
10874
|
+
return null;
|
|
10804
10875
|
const nameMatch = trimmed.match(/^\s*((?:public|protected)|static|final|val|var|let|const)?\s*(?:readonly\s+)?(?:[_$a-zA-Z][_$a-zA-Z0-9]*)\s*(?::|(?=\s*=)|(?=\s*[,)]))/);
|
|
10805
10876
|
const rawName = trimmed.replace(/^[^a-zA-Z_$]*/, "").replace(/[=:].*$/, "").replace(/\s+.*$/, "").trim();
|
|
10806
10877
|
const defaultMatch = trimmed.match(/=\s*(.+)$/);
|
|
@@ -10816,22 +10887,35 @@ function inferFunctionParams(sourceContent, funcName) {
|
|
|
10816
10887
|
return [];
|
|
10817
10888
|
}
|
|
10818
10889
|
function inferTypeFromName(paramName, defaultValue) {
|
|
10819
|
-
if (!paramName)
|
|
10890
|
+
if (!paramName)
|
|
10891
|
+
return "any";
|
|
10820
10892
|
const name = paramName.toLowerCase();
|
|
10821
10893
|
if (defaultValue !== null && defaultValue !== void 0) {
|
|
10822
|
-
if (/^["']/.test(defaultValue))
|
|
10823
|
-
|
|
10824
|
-
if (
|
|
10825
|
-
|
|
10826
|
-
if (
|
|
10827
|
-
|
|
10828
|
-
|
|
10829
|
-
|
|
10830
|
-
|
|
10831
|
-
|
|
10832
|
-
|
|
10833
|
-
|
|
10834
|
-
|
|
10894
|
+
if (/^["']/.test(defaultValue))
|
|
10895
|
+
return "string";
|
|
10896
|
+
if (/^\d+\.?\d*$/.test(defaultValue))
|
|
10897
|
+
return "number";
|
|
10898
|
+
if (/^(true|false)$/i.test(defaultValue))
|
|
10899
|
+
return "boolean";
|
|
10900
|
+
if (/^\[/.test(defaultValue))
|
|
10901
|
+
return "array";
|
|
10902
|
+
if (/^\{/.test(defaultValue))
|
|
10903
|
+
return "object";
|
|
10904
|
+
if (/^null$/i.test(defaultValue))
|
|
10905
|
+
return "null";
|
|
10906
|
+
}
|
|
10907
|
+
if (/^(is|has|can|should|will|did|was|are|contains?_|[A-Z])/.test(name))
|
|
10908
|
+
return "boolean";
|
|
10909
|
+
if (/^(count|index|limit|offset|max|min|size|length|total|num|age)_?/.test(name))
|
|
10910
|
+
return "number";
|
|
10911
|
+
if (/^(name|title|label|msg|message|text|str|prefix|suffix|path|url|email|id)_?/.test(name))
|
|
10912
|
+
return "string";
|
|
10913
|
+
if (/^(items|list|arr|entries|data|values|args)_?/.test(name))
|
|
10914
|
+
return "array";
|
|
10915
|
+
if (/^(obj|config|opts|options|settings|params|props)_?/.test(name))
|
|
10916
|
+
return "object";
|
|
10917
|
+
if (/^(fn|cb|callback|handler|on[A-Z])/.test(name))
|
|
10918
|
+
return "function";
|
|
10835
10919
|
return "any";
|
|
10836
10920
|
}
|
|
10837
10921
|
function _langComment(lang) {
|
|
@@ -10844,14 +10928,22 @@ function buildQualityAssertionsForFunc(funcName, params, lang, indent) {
|
|
|
10844
10928
|
let block = "";
|
|
10845
10929
|
const testValues = params.map((p) => {
|
|
10846
10930
|
const t = p.type || inferTypeFromName(p.name, p.defaultValue);
|
|
10847
|
-
if (t === "string" || t === "String")
|
|
10848
|
-
|
|
10849
|
-
if (t === "
|
|
10850
|
-
|
|
10851
|
-
if (t === "
|
|
10852
|
-
|
|
10853
|
-
if (t === "
|
|
10854
|
-
|
|
10931
|
+
if (t === "string" || t === "String")
|
|
10932
|
+
return '"sample_input"';
|
|
10933
|
+
if (t === "number" || t === "int" || t === "float" || t === "Number")
|
|
10934
|
+
return "42";
|
|
10935
|
+
if (t === "boolean" || t === "bool" || t === "Boolean")
|
|
10936
|
+
return "true";
|
|
10937
|
+
if (t === "array" || t === "Array" || t === "list" || t === "List")
|
|
10938
|
+
return "[]";
|
|
10939
|
+
if (t === "object" || t === "Object" || t === "dict" || t === "Dict")
|
|
10940
|
+
return "{}";
|
|
10941
|
+
if (t === "function" || t === "Function")
|
|
10942
|
+
return "() => {}";
|
|
10943
|
+
if (t === "any")
|
|
10944
|
+
return '"test"';
|
|
10945
|
+
if (t === "null")
|
|
10946
|
+
return "null";
|
|
10855
10947
|
return '"test"';
|
|
10856
10948
|
});
|
|
10857
10949
|
const args = testValues.join(", ");
|
|
@@ -10881,8 +10973,10 @@ function buildQualityAssertionsForFunc(funcName, params, lang, indent) {
|
|
|
10881
10973
|
`;
|
|
10882
10974
|
const ecArgs = params.map((p) => {
|
|
10883
10975
|
const t = p.type || inferTypeFromName(p.name, p.defaultValue);
|
|
10884
|
-
if (t === "string")
|
|
10885
|
-
|
|
10976
|
+
if (t === "string")
|
|
10977
|
+
return '""';
|
|
10978
|
+
if (t === "number" || t === "int" || t === "float")
|
|
10979
|
+
return "0";
|
|
10886
10980
|
return '"edge"';
|
|
10887
10981
|
}).join(", ");
|
|
10888
10982
|
block += `${indent} result = ${funcName}(${ecArgs})
|
|
@@ -10920,11 +11014,16 @@ function buildQualityAssertionsForFunc(funcName, params, lang, indent) {
|
|
|
10920
11014
|
`;
|
|
10921
11015
|
const ecArgsJS = params.map((p) => {
|
|
10922
11016
|
const t = p.type || inferTypeFromName(p.name, p.defaultValue);
|
|
10923
|
-
if (t === "string")
|
|
10924
|
-
|
|
10925
|
-
if (t === "
|
|
10926
|
-
|
|
10927
|
-
if (t === "
|
|
11017
|
+
if (t === "string")
|
|
11018
|
+
return '""';
|
|
11019
|
+
if (t === "number" || t === "int" || t === "float")
|
|
11020
|
+
return "0";
|
|
11021
|
+
if (t === "boolean")
|
|
11022
|
+
return "false";
|
|
11023
|
+
if (t === "array")
|
|
11024
|
+
return "[]";
|
|
11025
|
+
if (t === "object")
|
|
11026
|
+
return "{}";
|
|
10928
11027
|
return "undefined";
|
|
10929
11028
|
}).join(", ");
|
|
10930
11029
|
block += `${indent} const result = mod.${funcName}(${ecArgsJS});
|
|
@@ -10957,14 +11056,15 @@ function buildQualityAssertionsForFunc(funcName, params, lang, indent) {
|
|
|
10957
11056
|
return block;
|
|
10958
11057
|
}
|
|
10959
11058
|
function isSkeletonUseless(content) {
|
|
10960
|
-
if (!content)
|
|
11059
|
+
if (!content)
|
|
11060
|
+
return true;
|
|
10961
11061
|
const lines = content.split("\n").filter((l) => l.trim() && !l.trim().startsWith("//") && !l.trim().startsWith("#") && !l.trim().startsWith("/*") && !l.trim().startsWith("*"));
|
|
10962
11062
|
const todoLines = content.split("\n").filter((l) => /TODO|placeholder|smoke|is exported|module loads/.test(l));
|
|
10963
11063
|
const meaningfulLines = lines.filter((l) => !/TODO|placeholder|smoke|is exported|module loads|throw new Error|raise AssertionError|pytest\.skip|assert.*true/.test(l));
|
|
10964
11064
|
return meaningfulLines.length < 2;
|
|
10965
11065
|
}
|
|
10966
11066
|
|
|
10967
|
-
// src/lib/test-skeletons.
|
|
11067
|
+
// src/lib/test-skeletons.js
|
|
10968
11068
|
var TEST_SKELETONS = {
|
|
10969
11069
|
py: (name, exports = [], depth = "full", strict = true, quality = true, sourceContent = "") => {
|
|
10970
11070
|
const moduleImport = name.replace(/-/g, "_");
|
|
@@ -10992,7 +11092,8 @@ var TEST_SKELETONS = {
|
|
|
10992
11092
|
|
|
10993
11093
|
`;
|
|
10994
11094
|
for (const exp of exports) {
|
|
10995
|
-
if (exp.type === "class")
|
|
11095
|
+
if (exp.type === "class")
|
|
11096
|
+
continue;
|
|
10996
11097
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
10997
11098
|
content += `# TODO: implement tests for ${exp.name}
|
|
10998
11099
|
`;
|
|
@@ -11000,10 +11101,12 @@ var TEST_SKELETONS = {
|
|
|
11000
11101
|
const caseFunc = caseName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
11001
11102
|
content += `def test_${caseFunc}():
|
|
11002
11103
|
`;
|
|
11003
|
-
if (strict)
|
|
11104
|
+
if (strict)
|
|
11105
|
+
content += ` raise AssertionError("TODO: implement ${caseName}")
|
|
11004
11106
|
|
|
11005
11107
|
`;
|
|
11006
|
-
else
|
|
11108
|
+
else
|
|
11109
|
+
content += ` pytest.skip("TODO: implement ${caseName}")
|
|
11007
11110
|
|
|
11008
11111
|
`;
|
|
11009
11112
|
}
|
|
@@ -11015,10 +11118,12 @@ var TEST_SKELETONS = {
|
|
|
11015
11118
|
if (exports.length === 0) {
|
|
11016
11119
|
content += `def test_${name}_placeholder():
|
|
11017
11120
|
`;
|
|
11018
|
-
if (strict)
|
|
11121
|
+
if (strict)
|
|
11122
|
+
content += ` raise AssertionError("TODO: implement tests for ${name}")
|
|
11019
11123
|
|
|
11020
11124
|
`;
|
|
11021
|
-
else
|
|
11125
|
+
else
|
|
11126
|
+
content += ` pytest.skip("TODO: implement tests for ${name}")
|
|
11022
11127
|
|
|
11023
11128
|
`;
|
|
11024
11129
|
}
|
|
@@ -11052,7 +11157,8 @@ var TEST_SKELETONS = {
|
|
|
11052
11157
|
|
|
11053
11158
|
`;
|
|
11054
11159
|
for (const exp of exports) {
|
|
11055
|
-
if (exp.type === "class")
|
|
11160
|
+
if (exp.type === "class")
|
|
11161
|
+
continue;
|
|
11056
11162
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11057
11163
|
content += ` // TODO: implement tests for ${exp.name}
|
|
11058
11164
|
`;
|
|
@@ -11068,9 +11174,11 @@ var TEST_SKELETONS = {
|
|
|
11068
11174
|
`;
|
|
11069
11175
|
content += ` // TODO: implement ${caseName}
|
|
11070
11176
|
`;
|
|
11071
|
-
if (strict)
|
|
11177
|
+
if (strict)
|
|
11178
|
+
content += ` throw new Error('TODO: implement ${caseName}');
|
|
11072
11179
|
`;
|
|
11073
|
-
else
|
|
11180
|
+
else
|
|
11181
|
+
content += ` expect(true).toBe(true);
|
|
11074
11182
|
`;
|
|
11075
11183
|
content += ` });
|
|
11076
11184
|
|
|
@@ -11123,7 +11231,8 @@ var TEST_SKELETONS = {
|
|
|
11123
11231
|
|
|
11124
11232
|
`;
|
|
11125
11233
|
for (const exp of exports) {
|
|
11126
|
-
if (exp.type === "class")
|
|
11234
|
+
if (exp.type === "class")
|
|
11235
|
+
continue;
|
|
11127
11236
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11128
11237
|
content += ` // TODO: implement tests for ${exp.name}
|
|
11129
11238
|
`;
|
|
@@ -11139,9 +11248,11 @@ var TEST_SKELETONS = {
|
|
|
11139
11248
|
`;
|
|
11140
11249
|
content += ` // TODO: implement ${caseName}
|
|
11141
11250
|
`;
|
|
11142
|
-
if (strict)
|
|
11251
|
+
if (strict)
|
|
11252
|
+
content += ` throw new Error('TODO: implement ${caseName}');
|
|
11143
11253
|
`;
|
|
11144
|
-
else
|
|
11254
|
+
else
|
|
11255
|
+
content += ` expect(true).toBe(true);
|
|
11145
11256
|
`;
|
|
11146
11257
|
content += ` });
|
|
11147
11258
|
|
|
@@ -11194,7 +11305,8 @@ var TEST_SKELETONS = {
|
|
|
11194
11305
|
|
|
11195
11306
|
`;
|
|
11196
11307
|
for (const exp of exports) {
|
|
11197
|
-
if (exp.type === "class")
|
|
11308
|
+
if (exp.type === "class")
|
|
11309
|
+
continue;
|
|
11198
11310
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11199
11311
|
content += ` // TODO: implement tests for ${exp.name}
|
|
11200
11312
|
`;
|
|
@@ -11210,9 +11322,11 @@ var TEST_SKELETONS = {
|
|
|
11210
11322
|
`;
|
|
11211
11323
|
content += ` // TODO: implement ${caseName}
|
|
11212
11324
|
`;
|
|
11213
|
-
if (strict)
|
|
11325
|
+
if (strict)
|
|
11326
|
+
content += ` throw new Error('TODO: implement ${caseName}');
|
|
11214
11327
|
`;
|
|
11215
|
-
else
|
|
11328
|
+
else
|
|
11329
|
+
content += ` expect(true).toBe(true);
|
|
11216
11330
|
`;
|
|
11217
11331
|
content += ` });
|
|
11218
11332
|
|
|
@@ -11272,7 +11386,8 @@ var TEST_SKELETONS = {
|
|
|
11272
11386
|
|
|
11273
11387
|
`;
|
|
11274
11388
|
for (const exp of exports) {
|
|
11275
|
-
if (exp.type === "class")
|
|
11389
|
+
if (exp.type === "class")
|
|
11390
|
+
continue;
|
|
11276
11391
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11277
11392
|
const expCap = exp.name.charAt(0).toUpperCase() + exp.name.slice(1);
|
|
11278
11393
|
content += `// TODO: implement tests for ${exp.name}
|
|
@@ -11281,9 +11396,11 @@ var TEST_SKELETONS = {
|
|
|
11281
11396
|
const caseFunc = caseName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
11282
11397
|
content += `func Test${cap}_${caseFunc}(t *testing.T) {
|
|
11283
11398
|
`;
|
|
11284
|
-
if (strict)
|
|
11399
|
+
if (strict)
|
|
11400
|
+
content += ` t.Error("TODO: implement ${caseName}")
|
|
11285
11401
|
`;
|
|
11286
|
-
else
|
|
11402
|
+
else
|
|
11403
|
+
content += ` t.Skip("TODO: implement ${caseName}")
|
|
11287
11404
|
`;
|
|
11288
11405
|
content += `}
|
|
11289
11406
|
|
|
@@ -11303,9 +11420,11 @@ var TEST_SKELETONS = {
|
|
|
11303
11420
|
if (exports.length === 0) {
|
|
11304
11421
|
content += `func Test${cap}_Placeholder(t *testing.T) {
|
|
11305
11422
|
`;
|
|
11306
|
-
if (strict)
|
|
11423
|
+
if (strict)
|
|
11424
|
+
content += ` t.Error("TODO: implement tests for ${name}")
|
|
11307
11425
|
`;
|
|
11308
|
-
else
|
|
11426
|
+
else
|
|
11427
|
+
content += ` t.Skip("TODO: implement tests for ${name}")
|
|
11309
11428
|
`;
|
|
11310
11429
|
content += `}
|
|
11311
11430
|
`;
|
|
@@ -11338,9 +11457,11 @@ var TEST_SKELETONS = {
|
|
|
11338
11457
|
`;
|
|
11339
11458
|
content += ` echo "TODO: implement ${caseName}"
|
|
11340
11459
|
`;
|
|
11341
|
-
if (strict)
|
|
11460
|
+
if (strict)
|
|
11461
|
+
content += ` exit 1
|
|
11342
11462
|
`;
|
|
11343
|
-
else
|
|
11463
|
+
else
|
|
11464
|
+
content += ` echo "SKIP: ${caseName}"
|
|
11344
11465
|
`;
|
|
11345
11466
|
content += `}
|
|
11346
11467
|
|
|
@@ -11354,9 +11475,11 @@ var TEST_SKELETONS = {
|
|
|
11354
11475
|
if (exports.length === 0) {
|
|
11355
11476
|
content += `function test_smoke {
|
|
11356
11477
|
`;
|
|
11357
|
-
if (strict)
|
|
11478
|
+
if (strict)
|
|
11479
|
+
content += ` echo "TODO: implement tests for ${name}" && exit 1
|
|
11358
11480
|
`;
|
|
11359
|
-
else
|
|
11481
|
+
else
|
|
11482
|
+
content += ` echo "TODO: implement tests for ${name}"
|
|
11360
11483
|
`;
|
|
11361
11484
|
content += `}
|
|
11362
11485
|
`;
|
|
@@ -11396,7 +11519,8 @@ mod tests {
|
|
|
11396
11519
|
|
|
11397
11520
|
`;
|
|
11398
11521
|
for (const exp of exports) {
|
|
11399
|
-
if (exp.type === "class")
|
|
11522
|
+
if (exp.type === "class")
|
|
11523
|
+
continue;
|
|
11400
11524
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11401
11525
|
content += ` // TODO: implement tests for ${exp.name}
|
|
11402
11526
|
`;
|
|
@@ -11405,9 +11529,11 @@ mod tests {
|
|
|
11405
11529
|
content += ` #[test]
|
|
11406
11530
|
fn test_${caseFunc}() {
|
|
11407
11531
|
`;
|
|
11408
|
-
if (strict)
|
|
11532
|
+
if (strict)
|
|
11533
|
+
content += ` panic!("TODO: implement ${caseName}");
|
|
11409
11534
|
`;
|
|
11410
|
-
else
|
|
11535
|
+
else
|
|
11536
|
+
content += ` // TODO: implement ${caseName}
|
|
11411
11537
|
`;
|
|
11412
11538
|
content += ` }
|
|
11413
11539
|
|
|
@@ -11422,9 +11548,11 @@ mod tests {
|
|
|
11422
11548
|
content += ` #[test]
|
|
11423
11549
|
fn ${name}_placeholder() {
|
|
11424
11550
|
`;
|
|
11425
|
-
if (strict)
|
|
11551
|
+
if (strict)
|
|
11552
|
+
content += ` panic!("TODO: implement tests for ${name}");
|
|
11426
11553
|
`;
|
|
11427
|
-
else
|
|
11554
|
+
else
|
|
11555
|
+
content += ` // TODO: implement tests for ${name}
|
|
11428
11556
|
`;
|
|
11429
11557
|
content += ` }
|
|
11430
11558
|
`;
|
|
@@ -11464,7 +11592,8 @@ mod tests {
|
|
|
11464
11592
|
|
|
11465
11593
|
`;
|
|
11466
11594
|
for (const exp of exports) {
|
|
11467
|
-
if (exp.type === "class")
|
|
11595
|
+
if (exp.type === "class")
|
|
11596
|
+
continue;
|
|
11468
11597
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11469
11598
|
content += ` # TODO: implement tests for ${exp.name}
|
|
11470
11599
|
`;
|
|
@@ -11472,9 +11601,11 @@ mod tests {
|
|
|
11472
11601
|
const caseFunc = caseName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
11473
11602
|
content += ` def test_${caseFunc}
|
|
11474
11603
|
`;
|
|
11475
|
-
if (strict)
|
|
11604
|
+
if (strict)
|
|
11605
|
+
content += ` flunk "TODO: implement ${caseName}"
|
|
11476
11606
|
`;
|
|
11477
|
-
else
|
|
11607
|
+
else
|
|
11608
|
+
content += ` # TODO: implement ${caseName}
|
|
11478
11609
|
`;
|
|
11479
11610
|
content += ` end
|
|
11480
11611
|
|
|
@@ -11488,9 +11619,11 @@ mod tests {
|
|
|
11488
11619
|
if (exports.length === 0) {
|
|
11489
11620
|
content += ` def test_placeholder
|
|
11490
11621
|
`;
|
|
11491
|
-
if (strict)
|
|
11622
|
+
if (strict)
|
|
11623
|
+
content += ` flunk "TODO: implement tests for ${name}"
|
|
11492
11624
|
`;
|
|
11493
|
-
else
|
|
11625
|
+
else
|
|
11626
|
+
content += ` # TODO: implement tests for ${name}
|
|
11494
11627
|
`;
|
|
11495
11628
|
content += ` end
|
|
11496
11629
|
`;
|
|
@@ -11536,15 +11669,18 @@ mod tests {
|
|
|
11536
11669
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11537
11670
|
for (const caseName of cases) {
|
|
11538
11671
|
const testFunc = caseName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
11539
|
-
if (!strict)
|
|
11672
|
+
if (!strict)
|
|
11673
|
+
content += ` // @Disabled("TODO")
|
|
11540
11674
|
`;
|
|
11541
11675
|
content += ` @Test
|
|
11542
11676
|
`;
|
|
11543
11677
|
content += ` void test${testFunc.charAt(0).toUpperCase() + testFunc.slice(1)}() {
|
|
11544
11678
|
`;
|
|
11545
|
-
if (strict)
|
|
11679
|
+
if (strict)
|
|
11680
|
+
content += ` fail("TODO: implement ${caseName}");
|
|
11546
11681
|
`;
|
|
11547
|
-
else
|
|
11682
|
+
else
|
|
11683
|
+
content += ` assertTrue(true); // TODO: implement ${caseName}
|
|
11548
11684
|
`;
|
|
11549
11685
|
content += ` }
|
|
11550
11686
|
|
|
@@ -11606,15 +11742,18 @@ mod tests {
|
|
|
11606
11742
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11607
11743
|
for (const caseName of cases) {
|
|
11608
11744
|
const testFunc = caseName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
11609
|
-
if (!strict)
|
|
11745
|
+
if (!strict)
|
|
11746
|
+
content += ` // @Disabled("TODO")
|
|
11610
11747
|
`;
|
|
11611
11748
|
content += ` @Test
|
|
11612
11749
|
`;
|
|
11613
11750
|
content += ` fun test${testFunc.charAt(0).toUpperCase() + testFunc.slice(1)}() {
|
|
11614
11751
|
`;
|
|
11615
|
-
if (strict)
|
|
11752
|
+
if (strict)
|
|
11753
|
+
content += ` fail("TODO: implement ${caseName}")
|
|
11616
11754
|
`;
|
|
11617
|
-
else
|
|
11755
|
+
else
|
|
11756
|
+
content += ` assertTrue(true) // TODO: implement ${caseName}
|
|
11618
11757
|
`;
|
|
11619
11758
|
content += ` }
|
|
11620
11759
|
|
|
@@ -12492,7 +12631,10 @@ var onToolExecuteAfter = async (input, output) => {
|
|
|
12492
12631
|
const optModeFooter = loadSessionOptMode(currentSid + "_opt") || loadOptimizationMode() || "budget";
|
|
12493
12632
|
const activeSlot = selNow.active_slot || (execution.quality === "brain" ? "brain" : execution.quality === "medium" ? "medium" : "cheap");
|
|
12494
12633
|
const vibeBrand = resolveBrand(optModeFooter, activeSlot);
|
|
12495
|
-
const
|
|
12634
|
+
const sessionSlot = loadSessionSlot(currentSid);
|
|
12635
|
+
const displayMode = selNow.optimization_mode || optModeFooter || "auto";
|
|
12636
|
+
const currentSubRegime = loadBlackboxState()?.sessions?.[currentSid]?.sub_regime || classifyTurnSimple2(latestUserIntent || "");
|
|
12637
|
+
const flashIcon = isApiConnected2() ? " \u26A1" : "";
|
|
12496
12638
|
_footerText = buildFooterLine({
|
|
12497
12639
|
activeSlot,
|
|
12498
12640
|
providerLabel: execution.provider_label,
|
|
@@ -12500,10 +12642,12 @@ var onToolExecuteAfter = async (input, output) => {
|
|
|
12500
12642
|
ltTotal,
|
|
12501
12643
|
ltTrend: sesTrend || "",
|
|
12502
12644
|
vibeBrand,
|
|
12503
|
-
optMode:
|
|
12645
|
+
optMode: displayMode,
|
|
12504
12646
|
flashIcon,
|
|
12505
12647
|
enfTags,
|
|
12506
|
-
|
|
12648
|
+
sessionSlot,
|
|
12649
|
+
vectorChangedSlot: selNow.vector_changed_slot,
|
|
12650
|
+
subRegime: currentSubRegime
|
|
12507
12651
|
}) + "\n\n";
|
|
12508
12652
|
const footerTarget = _payload(output);
|
|
12509
12653
|
output.title = _footerText.trim();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeostheog",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.6",
|
|
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",
|