vibeostheog 0.24.8 → 0.24.10
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 +8 -0
- package/dist/vibeOS.js +169 -290
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dist/vibeOS.js
CHANGED
|
@@ -1596,7 +1596,7 @@ import { dirname as dirname3 } from "node:path";
|
|
|
1596
1596
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
1597
1597
|
import { homedir } from "node:os";
|
|
1598
1598
|
|
|
1599
|
-
// src/lib/runtime-state.
|
|
1599
|
+
// src/lib/runtime-state.ts
|
|
1600
1600
|
var RUNTIME_KEY = "__vibeOSRuntimeState";
|
|
1601
1601
|
function getRuntimeState() {
|
|
1602
1602
|
const g = globalThis;
|
|
@@ -1623,8 +1623,7 @@ function markApiDisconnected() {
|
|
|
1623
1623
|
const state = getRuntimeState();
|
|
1624
1624
|
state.apiConnected = false;
|
|
1625
1625
|
state.apiFallbackMode = true;
|
|
1626
|
-
if (!state.apiFallbackSince)
|
|
1627
|
-
state.apiFallbackSince = (/* @__PURE__ */ new Date()).toISOString();
|
|
1626
|
+
if (!state.apiFallbackSince) state.apiFallbackSince = (/* @__PURE__ */ new Date()).toISOString();
|
|
1628
1627
|
}
|
|
1629
1628
|
function resetApiConnection() {
|
|
1630
1629
|
const state = getRuntimeState();
|
|
@@ -2529,56 +2528,42 @@ function writeSessionOptMode(sid, mode) {
|
|
|
2529
2528
|
}
|
|
2530
2529
|
}
|
|
2531
2530
|
|
|
2532
|
-
// src/lib/pattern-helpers.
|
|
2531
|
+
// src/lib/pattern-helpers.ts
|
|
2533
2532
|
import { relative, basename as basename2 } from "node:path";
|
|
2534
2533
|
function normalizeObservedPath(filePath, directory3) {
|
|
2535
|
-
if (!filePath || typeof filePath !== "string")
|
|
2536
|
-
return "unknown";
|
|
2534
|
+
if (!filePath || typeof filePath !== "string") return "unknown";
|
|
2537
2535
|
let p = filePath;
|
|
2538
2536
|
try {
|
|
2539
2537
|
if (directory3 && p.startsWith("/")) {
|
|
2540
2538
|
const rel = relative(directory3, p);
|
|
2541
|
-
if (rel && !rel.startsWith("..") && !rel.startsWith("/"))
|
|
2542
|
-
p = rel;
|
|
2539
|
+
if (rel && !rel.startsWith("..") && !rel.startsWith("/")) p = rel;
|
|
2543
2540
|
}
|
|
2544
2541
|
} catch {
|
|
2545
2542
|
}
|
|
2546
2543
|
p = p.replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
2547
|
-
if (/^(src\/index\.js|package\.json|README\.md|CHANGELOG\.md|tsconfig\.json)$/i.test(p))
|
|
2548
|
-
return p;
|
|
2544
|
+
if (/^(src\/index\.js|package\.json|README\.md|CHANGELOG\.md|tsconfig\.json)$/i.test(p)) return p;
|
|
2549
2545
|
const m = p.match(/\.([a-z0-9]+)$/i);
|
|
2550
|
-
if (p.startsWith("src/") && m)
|
|
2551
|
-
|
|
2552
|
-
if (p.startsWith("tests/") && m)
|
|
2553
|
-
return `tests/*.${m[1].toLowerCase()}`;
|
|
2546
|
+
if (p.startsWith("src/") && m) return `src/*.${m[1].toLowerCase()}`;
|
|
2547
|
+
if (p.startsWith("tests/") && m) return `tests/*.${m[1].toLowerCase()}`;
|
|
2554
2548
|
return basename2(p) || "unknown";
|
|
2555
2549
|
}
|
|
2556
2550
|
function commandFamily(command) {
|
|
2557
2551
|
const c = String(command || "").trim().toLowerCase();
|
|
2558
|
-
if (!c)
|
|
2559
|
-
|
|
2560
|
-
if (/\
|
|
2561
|
-
|
|
2562
|
-
if (/\bnpm\s+run\s+
|
|
2563
|
-
|
|
2564
|
-
if (/\
|
|
2565
|
-
return "test";
|
|
2566
|
-
if (/\bnpm\s+run\s+build\b|\btsc\s+-p\b/.test(c))
|
|
2567
|
-
return "build";
|
|
2568
|
-
if (/\bgit\s+status\b/.test(c))
|
|
2569
|
-
return "git-status";
|
|
2570
|
-
if (/\bgit\s+commit\b/.test(c))
|
|
2571
|
-
return "git-commit";
|
|
2552
|
+
if (!c) return "unknown";
|
|
2553
|
+
if (/\bnode\s+--check\b/.test(c)) return "syntax-check";
|
|
2554
|
+
if (/\bnpm\s+run\s+typecheck\b|\btsc\b.*--noemit/.test(c)) return "typecheck";
|
|
2555
|
+
if (/\bnpm\s+test\b|\bnode\s+--test\b|\bvitest\b|\bjest\b|\bpytest\b/.test(c)) return "test";
|
|
2556
|
+
if (/\bnpm\s+run\s+build\b|\btsc\s+-p\b/.test(c)) return "build";
|
|
2557
|
+
if (/\bgit\s+status\b/.test(c)) return "git-status";
|
|
2558
|
+
if (/\bgit\s+commit\b/.test(c)) return "git-commit";
|
|
2572
2559
|
const first = c.replace(/^[a-z_][a-z0-9_]*=\S+\s+/g, "").split(/\s+/)[0];
|
|
2573
2560
|
return /^[a-z0-9._/-]{1,30}$/.test(first) ? first : "command";
|
|
2574
2561
|
}
|
|
2575
2562
|
function commandFailed(output) {
|
|
2576
2563
|
const code = output?.exitCode ?? output?.statusCode ?? output?.code;
|
|
2577
|
-
if (Number.isFinite(Number(code)) && Number(code) !== 0)
|
|
2578
|
-
return true;
|
|
2564
|
+
if (Number.isFinite(Number(code)) && Number(code) !== 0) return true;
|
|
2579
2565
|
const raw = output?.result ?? output?.text ?? output?.content ?? output?.data ?? "";
|
|
2580
|
-
if (typeof raw !== "string")
|
|
2581
|
-
return false;
|
|
2566
|
+
if (typeof raw !== "string") return false;
|
|
2582
2567
|
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);
|
|
2583
2568
|
}
|
|
2584
2569
|
function mergeProjectBucket(dst, src) {
|
|
@@ -2595,8 +2580,7 @@ function mergeProjectBucket(dst, src) {
|
|
|
2595
2580
|
row.sessions = [.../* @__PURE__ */ new Set([...row.sessions || [], ...v?.sessions || []])].slice(-10);
|
|
2596
2581
|
row.lastSeen = [row.lastSeen, v?.lastSeen].filter(Boolean).sort().slice(-1)[0] || null;
|
|
2597
2582
|
row.summary = row.summary || v?.summary || "";
|
|
2598
|
-
if (v?.kind)
|
|
2599
|
-
row.kind = v.kind;
|
|
2583
|
+
if (v?.kind) row.kind = v.kind;
|
|
2600
2584
|
out[key] = row;
|
|
2601
2585
|
}
|
|
2602
2586
|
}
|
|
@@ -2615,11 +2599,9 @@ function mergeProjectBucket(dst, src) {
|
|
|
2615
2599
|
};
|
|
2616
2600
|
}
|
|
2617
2601
|
function _pruneOldSessions(state) {
|
|
2618
|
-
if (!state?.sessions)
|
|
2619
|
-
return;
|
|
2602
|
+
if (!state?.sessions) return;
|
|
2620
2603
|
const entries = Object.entries(state.sessions);
|
|
2621
|
-
if (entries.length <= 30)
|
|
2622
|
-
return;
|
|
2604
|
+
if (entries.length <= 30) return;
|
|
2623
2605
|
entries.sort((a, b) => {
|
|
2624
2606
|
const da = a[1]?.started || a[1]?.last_costed || "";
|
|
2625
2607
|
const db = b[1]?.started || b[1]?.last_costed || "";
|
|
@@ -7350,7 +7332,6 @@ function getReportsIndexPath() {
|
|
|
7350
7332
|
}
|
|
7351
7333
|
var REPORTS_DIR2 = getReportsDir();
|
|
7352
7334
|
var REPORTS_INDEX = getReportsIndexPath();
|
|
7353
|
-
var _OC_SID3 = "opencode-" + (process.pid || "x") + "-" + Date.now();
|
|
7354
7335
|
var currentProjectFingerprint2 = "";
|
|
7355
7336
|
var currentProjectName2 = "";
|
|
7356
7337
|
function _handleStateCorruption4(path) {
|
|
@@ -7483,12 +7464,22 @@ function _parseMetrics(v) {
|
|
|
7483
7464
|
function saveReport({ type = "manual", summary = "", findings = null, metrics = null, narrative = "", tags = [], fingerprint = null, status = "pending", task_description = "", outcome_verified = false } = {}) {
|
|
7484
7465
|
const parsedFindings = _parseFindings(findings);
|
|
7485
7466
|
const parsedMetrics = _parseMetrics(metrics);
|
|
7467
|
+
const metricsObject = parsedMetrics && typeof parsedMetrics === "object" && !Array.isArray(parsedMetrics) ? parsedMetrics : {};
|
|
7468
|
+
const metricsSessionId = typeof metricsObject.sessionId === "string" && metricsObject.sessionId.trim() ? metricsObject.sessionId.trim() : "";
|
|
7469
|
+
const metricsProjectName = typeof metricsObject.projectName === "string" && metricsObject.projectName.trim() ? metricsObject.projectName.trim() : "";
|
|
7470
|
+
const metricsProjectFingerprint = typeof metricsObject.projectFingerprint === "string" && metricsObject.projectFingerprint.trim() ? metricsObject.projectFingerprint.trim() : "";
|
|
7486
7471
|
if (_wouldBeDuplicate(type, summary))
|
|
7487
7472
|
return null;
|
|
7488
|
-
|
|
7473
|
+
if (!currentProjectFingerprint2 && metricsProjectFingerprint)
|
|
7474
|
+
currentProjectFingerprint2 = metricsProjectFingerprint;
|
|
7475
|
+
if (!currentProjectName2 && metricsProjectName)
|
|
7476
|
+
currentProjectName2 = metricsProjectName;
|
|
7477
|
+
const fp2 = fingerprint || metricsProjectFingerprint || currentProjectFingerprint2 || "unknown";
|
|
7478
|
+
const sessionId = metricsSessionId || getOcSessionId();
|
|
7479
|
+
const projectName = metricsProjectName || currentProjectName2 || "unknown";
|
|
7489
7480
|
const id2 = generateReportId(type, fp2);
|
|
7490
7481
|
const report = {
|
|
7491
|
-
meta: { id: id2, project:
|
|
7482
|
+
meta: { id: id2, project: projectName, fingerprint: fp2, type, created: (/* @__PURE__ */ new Date()).toISOString(), sessionId },
|
|
7492
7483
|
summary,
|
|
7493
7484
|
findings: parsedFindings,
|
|
7494
7485
|
metrics: parsedMetrics,
|
|
@@ -9456,7 +9447,7 @@ import { readFileSync as readFileSync13, writeFileSync as writeFileSync12, appen
|
|
|
9456
9447
|
import { join as join14, dirname as dirname10, basename as basename6 } from "node:path";
|
|
9457
9448
|
import { createHash as createHash3 } from "node:crypto";
|
|
9458
9449
|
|
|
9459
|
-
// src/lib/mode-policy.
|
|
9450
|
+
// src/lib/mode-policy.ts
|
|
9460
9451
|
var STRESS_QUALITY_THRESHOLD = 1.5;
|
|
9461
9452
|
var BASELINE_MODE = "budget";
|
|
9462
9453
|
var LOOP_REGIMES = /* @__PURE__ */ new Set(["LOOPING", "DIVERGENT"]);
|
|
@@ -9464,8 +9455,7 @@ var QUALITY_REGIMES = /* @__PURE__ */ new Set(["CONVERGING", "CLOSED"]);
|
|
|
9464
9455
|
var MANUAL_MODES = /* @__PURE__ */ new Set(["balanced", "quality", "speed", "longrun", "vibemax", "vibeqmax", "vibeultrax"]);
|
|
9465
9456
|
function normalizeMode(mode) {
|
|
9466
9457
|
const normalized = String(mode || BASELINE_MODE).toLowerCase();
|
|
9467
|
-
if (normalized === "auto" || normalized === "")
|
|
9468
|
-
return BASELINE_MODE;
|
|
9458
|
+
if (normalized === "auto" || normalized === "") return BASELINE_MODE;
|
|
9469
9459
|
if (normalized === "budget" || normalized === "quality" || normalized === "speed" || normalized === "longrun" || normalized === "balanced" || normalized === "vibemax" || normalized === "vibeqmax" || normalized === "vibeultrax") {
|
|
9470
9460
|
return normalized;
|
|
9471
9461
|
}
|
|
@@ -9478,12 +9468,9 @@ function isManualOverride(mode) {
|
|
|
9478
9468
|
return MANUAL_MODES.has(normalizeMode(mode));
|
|
9479
9469
|
}
|
|
9480
9470
|
function chooseEpisodeMode(regime, suggestedMode, stress) {
|
|
9481
|
-
if (suggestedMode === "vibeultrax" || suggestedMode === "vibeqmax" || suggestedMode === "vibemax")
|
|
9482
|
-
|
|
9483
|
-
if (
|
|
9484
|
-
return "speed";
|
|
9485
|
-
if (QUALITY_REGIMES.has(regime) || suggestedMode === "quality")
|
|
9486
|
-
return "quality";
|
|
9471
|
+
if (suggestedMode === "vibeultrax" || suggestedMode === "vibeqmax" || suggestedMode === "vibemax") return suggestedMode;
|
|
9472
|
+
if (LOOP_REGIMES.has(regime) || suggestedMode === "speed") return "speed";
|
|
9473
|
+
if (QUALITY_REGIMES.has(regime) || suggestedMode === "quality") return "quality";
|
|
9487
9474
|
return stress > STRESS_QUALITY_THRESHOLD ? "quality" : "budget";
|
|
9488
9475
|
}
|
|
9489
9476
|
function defaultPolicy() {
|
|
@@ -9504,19 +9491,15 @@ function defaultPolicy() {
|
|
|
9504
9491
|
}
|
|
9505
9492
|
function modeToSlot(mode) {
|
|
9506
9493
|
const normalized = normalizeMode(mode);
|
|
9507
|
-
if (normalized === "speed")
|
|
9508
|
-
|
|
9509
|
-
if (normalized === "quality" || normalized === "longrun" || normalized === "vibeultrax" || normalized === "vibeqmax")
|
|
9510
|
-
return "brain";
|
|
9494
|
+
if (normalized === "speed") return "medium";
|
|
9495
|
+
if (normalized === "quality" || normalized === "longrun" || normalized === "vibeultrax" || normalized === "vibeqmax") return "brain";
|
|
9511
9496
|
return "cheap";
|
|
9512
9497
|
}
|
|
9513
9498
|
function loadSessionPolicy() {
|
|
9514
9499
|
const state = loadBlackboxState();
|
|
9515
|
-
if (!state.sessions || typeof state.sessions !== "object")
|
|
9516
|
-
state.sessions = {};
|
|
9500
|
+
if (!state.sessions || typeof state.sessions !== "object") state.sessions = {};
|
|
9517
9501
|
const sid = _OC_SID;
|
|
9518
|
-
if (!state.sessions[sid] || typeof state.sessions[sid] !== "object")
|
|
9519
|
-
state.sessions[sid] = {};
|
|
9502
|
+
if (!state.sessions[sid] || typeof state.sessions[sid] !== "object") state.sessions[sid] = {};
|
|
9520
9503
|
const session = state.sessions[sid];
|
|
9521
9504
|
if (!session.mode_policy || typeof session.mode_policy !== "object") {
|
|
9522
9505
|
session.mode_policy = defaultPolicy();
|
|
@@ -9644,7 +9627,7 @@ function recordBudgetFirstOutcome(input = {}) {
|
|
|
9644
9627
|
import { join as join13 } from "node:path";
|
|
9645
9628
|
import { writeFileSync as writeFileSync11 } from "node:fs";
|
|
9646
9629
|
|
|
9647
|
-
// src/lib/text-compress.
|
|
9630
|
+
// src/lib/text-compress.ts
|
|
9648
9631
|
var VERBOSE_LINE_RE = [
|
|
9649
9632
|
/^[\s#*/\\\-_=+|~:;'"`@\$%^&<>{}\[\]()!?.,0-9]+$/,
|
|
9650
9633
|
/^(Filed|Created|Modified|Deleted|Updated|Renamed|Copied|Moved|Changed):/,
|
|
@@ -9661,15 +9644,12 @@ function extractBulletLines(lines, targetChars, minLines) {
|
|
|
9661
9644
|
const keyLines = [];
|
|
9662
9645
|
const otherLines = [];
|
|
9663
9646
|
for (const line of lines) {
|
|
9664
|
-
if (BULLET_PATTERNS.some((re) => re.test(line)))
|
|
9665
|
-
|
|
9666
|
-
else
|
|
9667
|
-
otherLines.push(line);
|
|
9647
|
+
if (BULLET_PATTERNS.some((re) => re.test(line))) keyLines.push(line);
|
|
9648
|
+
else otherLines.push(line);
|
|
9668
9649
|
}
|
|
9669
9650
|
const selected = [...keyLines];
|
|
9670
9651
|
for (const line of otherLines) {
|
|
9671
|
-
if (selected.length >= minLines && selected.join("\n").length >= targetChars)
|
|
9672
|
-
break;
|
|
9652
|
+
if (selected.length >= minLines && selected.join("\n").length >= targetChars) break;
|
|
9673
9653
|
selected.push(line);
|
|
9674
9654
|
}
|
|
9675
9655
|
while (selected.length > minLines && selected.join("\n").length > targetChars * 2) {
|
|
@@ -9678,8 +9658,7 @@ function extractBulletLines(lines, targetChars, minLines) {
|
|
|
9678
9658
|
return selected;
|
|
9679
9659
|
}
|
|
9680
9660
|
function compressText(text) {
|
|
9681
|
-
if (!text || typeof text !== "string")
|
|
9682
|
-
return text;
|
|
9661
|
+
if (!text || typeof text !== "string") return text;
|
|
9683
9662
|
let lines = text.split("\n");
|
|
9684
9663
|
let removed = 0;
|
|
9685
9664
|
const out = [];
|
|
@@ -9692,16 +9671,14 @@ function compressText(text) {
|
|
|
9692
9671
|
break;
|
|
9693
9672
|
}
|
|
9694
9673
|
}
|
|
9695
|
-
if (!skip)
|
|
9696
|
-
out.push(line);
|
|
9674
|
+
if (!skip) out.push(line);
|
|
9697
9675
|
}
|
|
9698
9676
|
const collapsed = [];
|
|
9699
9677
|
let blanks = 0;
|
|
9700
9678
|
for (const line of out) {
|
|
9701
9679
|
if (line.trim() === "") {
|
|
9702
9680
|
blanks++;
|
|
9703
|
-
if (blanks <= 2)
|
|
9704
|
-
collapsed.push(line);
|
|
9681
|
+
if (blanks <= 2) collapsed.push(line);
|
|
9705
9682
|
} else {
|
|
9706
9683
|
blanks = 0;
|
|
9707
9684
|
collapsed.push(line);
|
|
@@ -9709,7 +9686,10 @@ function compressText(text) {
|
|
|
9709
9686
|
}
|
|
9710
9687
|
let result = collapsed.join("\n").trim();
|
|
9711
9688
|
if (result.length > COMPRESS_THRESHOLD) {
|
|
9712
|
-
const targetChars = Math.max(
|
|
9689
|
+
const targetChars = Math.max(
|
|
9690
|
+
Math.round(result.length * COMPRESS_RATIO),
|
|
9691
|
+
COMPRESS_THRESHOLD
|
|
9692
|
+
);
|
|
9713
9693
|
const minLines = Math.max(1, Math.round(collapsed.length * MIN_KEPT_LINES_RATIO));
|
|
9714
9694
|
const bulletLines = extractBulletLines(collapsed, targetChars, minLines);
|
|
9715
9695
|
result = bulletLines.join("\n").trim();
|
|
@@ -10024,7 +10004,7 @@ function recordSaving(tool2, reason, saveEst, meta = {}) {
|
|
|
10024
10004
|
}
|
|
10025
10005
|
}
|
|
10026
10006
|
|
|
10027
|
-
// src/lib/constants.
|
|
10007
|
+
// src/lib/constants.ts
|
|
10028
10008
|
var SAVE_EST = {
|
|
10029
10009
|
// Realistic: v4-pro (0.00057) - v4-flash (0.000182) = 0.000388/turn
|
|
10030
10010
|
WRITE_EDIT: 4e-4,
|
|
@@ -10042,7 +10022,7 @@ var COMPRESS_MARKER = "[ctx-compressed-v1]";
|
|
|
10042
10022
|
var PROTOCOL_MARKER = "[wbp-v1]";
|
|
10043
10023
|
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.";
|
|
10044
10024
|
|
|
10045
|
-
// src/lib/templates.
|
|
10025
|
+
// src/lib/templates.ts
|
|
10046
10026
|
var TEMPLATES = {
|
|
10047
10027
|
save: {
|
|
10048
10028
|
tier_bias: "cheap",
|
|
@@ -10092,8 +10072,7 @@ var TEMPLATES = {
|
|
|
10092
10072
|
var DEFAULT_TEMPLATE = "save";
|
|
10093
10073
|
var SEC_KEYWORDS = /\b(security|vuln|exploit|injection|xss|csrf|secret|credential|token leak|auth bypass|privacy|breach|backdoor|sql injection|cve)\b/i;
|
|
10094
10074
|
function detectSecuritySignal(text) {
|
|
10095
|
-
if (!text || typeof text !== "string")
|
|
10096
|
-
return false;
|
|
10075
|
+
if (!text || typeof text !== "string") return false;
|
|
10097
10076
|
return SEC_KEYWORDS.test(text);
|
|
10098
10077
|
}
|
|
10099
10078
|
function detectBudgetSignal(creditPercent) {
|
|
@@ -10106,25 +10085,20 @@ function detectStressSpike(stressScore) {
|
|
|
10106
10085
|
return delta > 0.3 && stressScore > 0.5;
|
|
10107
10086
|
}
|
|
10108
10087
|
function resolveTemplate(prevTemplate, stressScore, userText, creditPercent, subRegime) {
|
|
10109
|
-
if (detectSecuritySignal(userText))
|
|
10110
|
-
return "security";
|
|
10088
|
+
if (detectSecuritySignal(userText)) return "security";
|
|
10111
10089
|
if (detectBudgetSignal(creditPercent)) {
|
|
10112
10090
|
const regime = String(subRegime || "").toUpperCase();
|
|
10113
|
-
if (regime === "LOOPING" || regime === "DIVERGENT")
|
|
10114
|
-
return "speed";
|
|
10091
|
+
if (regime === "LOOPING" || regime === "DIVERGENT") return "speed";
|
|
10115
10092
|
return "save";
|
|
10116
10093
|
}
|
|
10117
|
-
if (detectStressSpike(stressScore))
|
|
10118
|
-
return "quality";
|
|
10094
|
+
if (detectStressSpike(stressScore)) return "quality";
|
|
10119
10095
|
return prevTemplate || DEFAULT_TEMPLATE;
|
|
10120
10096
|
}
|
|
10121
10097
|
var _turnCount = 0;
|
|
10122
10098
|
function shouldInjectTemplate(template, prevTemplate) {
|
|
10123
10099
|
_turnCount++;
|
|
10124
|
-
if (template !== prevTemplate)
|
|
10125
|
-
|
|
10126
|
-
if (_turnCount % 10 === 0)
|
|
10127
|
-
return true;
|
|
10100
|
+
if (template !== prevTemplate) return true;
|
|
10101
|
+
if (_turnCount % 10 === 0) return true;
|
|
10128
10102
|
return false;
|
|
10129
10103
|
}
|
|
10130
10104
|
|
|
@@ -10171,7 +10145,7 @@ function ensureProjectContext(hookDirectory) {
|
|
|
10171
10145
|
return resolved;
|
|
10172
10146
|
}
|
|
10173
10147
|
var latestUserIntent = null;
|
|
10174
|
-
var
|
|
10148
|
+
var _OC_SID3 = "opencode-" + (process.pid || "x") + "-" + Date.now();
|
|
10175
10149
|
var _latestBlackboxState3 = null;
|
|
10176
10150
|
var _latestBlackboxLoopMsg3 = null;
|
|
10177
10151
|
var _latestBlackboxPivotMsg3 = null;
|
|
@@ -10313,7 +10287,7 @@ function syncControlSettings(cv, options = {}) {
|
|
|
10313
10287
|
if (!cv)
|
|
10314
10288
|
return;
|
|
10315
10289
|
try {
|
|
10316
|
-
const sid =
|
|
10290
|
+
const sid = _OC_SID3;
|
|
10317
10291
|
if (!cv.agent_mode) {
|
|
10318
10292
|
try {
|
|
10319
10293
|
clearWorkspaceFollowupPauseForSession(sid);
|
|
@@ -10533,7 +10507,7 @@ async function trackBlackbox(messages) {
|
|
|
10533
10507
|
const tracker = getBlackboxTracker();
|
|
10534
10508
|
const localState = tracker.update(latestUserIntent);
|
|
10535
10509
|
const state = loadBlackboxState();
|
|
10536
|
-
const sid =
|
|
10510
|
+
const sid = _OC_SID3;
|
|
10537
10511
|
ensureProjectContext(process.cwd() || "");
|
|
10538
10512
|
const serialized = tracker.serialize();
|
|
10539
10513
|
const existingSession = state.sessions[sid] || {};
|
|
@@ -10861,7 +10835,7 @@ var onSystemTransform = async (_input, output) => {
|
|
|
10861
10835
|
const regime2 = _latestBlackboxState3?.sub_regime || classifyTurnSimple2(latestUserIntent || "");
|
|
10862
10836
|
const calRecord = JSON.stringify({
|
|
10863
10837
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10864
|
-
sid:
|
|
10838
|
+
sid: _OC_SID3,
|
|
10865
10839
|
mode: _currentTemplate,
|
|
10866
10840
|
regime: regime2,
|
|
10867
10841
|
stress: stressScore,
|
|
@@ -11028,7 +11002,7 @@ function readLifetimeSavings2() {
|
|
|
11028
11002
|
reconcileStateFromLedger();
|
|
11029
11003
|
const raw = readFileSync14(STATE_FILE2, "utf-8");
|
|
11030
11004
|
const state = safeJsonParse3(raw);
|
|
11031
|
-
const ses = state?.sessions?.[typeof
|
|
11005
|
+
const ses = state?.sessions?.[typeof _OC_SID4 !== "undefined" ? _OC_SID4 : ""] || {};
|
|
11032
11006
|
return {
|
|
11033
11007
|
ltTasks: roundUsd2(state?.lifetime?.total_savings_usd || 0),
|
|
11034
11008
|
ltCache: roundUsd2(state?.lifetime?.cache_savings_usd || 0),
|
|
@@ -11056,7 +11030,7 @@ function readLifetimeSavings2() {
|
|
|
11056
11030
|
return { ltTasks: 0, ltCache: 0, ltCost: 0, count: 0, sesTasks: 0, sesCache: 0, sesTaskDelegations: 0, sesDuration: 0, sesRatePerHour: 0, sesTrend: "", sesToolBreakdown: {}, sesModelTurns: {}, quality_avg: 0 };
|
|
11057
11031
|
}
|
|
11058
11032
|
}
|
|
11059
|
-
var
|
|
11033
|
+
var _OC_SID4 = "opencode-" + (process.pid || "x") + "-" + Date.now();
|
|
11060
11034
|
function scoreTaskQuality(outputText, promptText) {
|
|
11061
11035
|
if (typeof outputText !== "string" || outputText.length === 0)
|
|
11062
11036
|
return 0;
|
|
@@ -11083,7 +11057,7 @@ function scoreTaskQuality(outputText, promptText) {
|
|
|
11083
11057
|
function readRewardSignals() {
|
|
11084
11058
|
try {
|
|
11085
11059
|
const state = loadBlackboxState();
|
|
11086
|
-
const session = state?.sessions?.[
|
|
11060
|
+
const session = state?.sessions?.[_OC_SID4] || {};
|
|
11087
11061
|
const policy = session?.mode_policy || {};
|
|
11088
11062
|
return {
|
|
11089
11063
|
stableStreak: Math.max(0, Number(policy.stable_streak || 0)),
|
|
@@ -11160,7 +11134,7 @@ async function _appendFooter(input, output, directory3) {
|
|
|
11160
11134
|
return;
|
|
11161
11135
|
const { ltTasks, ltCache, ltCost, count, sesTasks, sesEdit, sesCredit, sesC7, sesQuota, sesCache, sesTaskDelegations, sesDuration, sesRatePerHour, sesTrend, sesToolBreakdown, sesModelTurns, quality_avg } = readLifetimeSavings2();
|
|
11162
11136
|
const { stableStreak, problemStreak } = readRewardSignals();
|
|
11163
|
-
const sessionSlot = loadBlackboxState()?.sessions?.[
|
|
11137
|
+
const sessionSlot = loadBlackboxState()?.sessions?.[_OC_SID4]?.active_slot || loadSessionSlot(_OC_SID4);
|
|
11164
11138
|
const slot = sessionSlot || loadSelection3().active_slot || "brain";
|
|
11165
11139
|
const brainModel = slot === "brain" ? TRINITY_BRAIN || currentModel : slot === "medium" ? TRINITY_MEDIUM || currentModel : TRINITY_CHEAP || currentModel || "";
|
|
11166
11140
|
let liveModel = "";
|
|
@@ -11194,7 +11168,7 @@ async function _appendFooter(input, output, directory3) {
|
|
|
11194
11168
|
type: "session",
|
|
11195
11169
|
summary: "Session cost: $" + formatUsd(ltCost) + " | cache saved: $" + formatUsd(ltCache) + " | delegation saved: $" + formatUsd(Number(sesTasks || 0)) + " | task delegations: " + Number(sesTaskDelegations || 0),
|
|
11196
11170
|
metrics: {
|
|
11197
|
-
sessionId:
|
|
11171
|
+
sessionId: _OC_SID4,
|
|
11198
11172
|
projectFingerprint: currentProjectFingerprint || "unknown",
|
|
11199
11173
|
projectName: currentProjectName || "unknown",
|
|
11200
11174
|
sessionCost: ltCost,
|
|
@@ -11283,7 +11257,7 @@ ${vibeLine}`;
|
|
|
11283
11257
|
syncOutcomeToApi(finalOutcome);
|
|
11284
11258
|
try {
|
|
11285
11259
|
mkdirSync11(getVibeOSHome10(), { recursive: true });
|
|
11286
|
-
appendFileSync6(join15(getVibeOSHome10(), "calibration-data.jsonl"), JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), event: "outcome", sid:
|
|
11260
|
+
appendFileSync6(join15(getVibeOSHome10(), "calibration-data.jsonl"), JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), event: "outcome", sid: _OC_SID4, outcome: finalOutcome }) + "\n");
|
|
11287
11261
|
} catch {
|
|
11288
11262
|
}
|
|
11289
11263
|
}
|
|
@@ -11313,7 +11287,7 @@ import { writeFileSync as writeFileSync14, appendFileSync as appendFileSync8, ex
|
|
|
11313
11287
|
import { join as join17, dirname as dirname12, basename as basename7 } from "node:path";
|
|
11314
11288
|
import { createHash as createHash5 } from "node:crypto";
|
|
11315
11289
|
|
|
11316
|
-
// src/lib/cost-anomaly.
|
|
11290
|
+
// src/lib/cost-anomaly.ts
|
|
11317
11291
|
var COST_WINDOW_SIZE = 20;
|
|
11318
11292
|
var COST_ANOMALY_THRESHOLD = 3;
|
|
11319
11293
|
var COST_WARMUP_SAMPLES = 5;
|
|
@@ -11324,26 +11298,21 @@ var CostAnomalyDetector = class {
|
|
|
11324
11298
|
currentAnomalyCost = 0;
|
|
11325
11299
|
currentAnomalyMean = 0;
|
|
11326
11300
|
record(cost) {
|
|
11327
|
-
if (this.disabled)
|
|
11328
|
-
return;
|
|
11301
|
+
if (this.disabled) return;
|
|
11329
11302
|
this.costHistory.push(cost);
|
|
11330
11303
|
if (this.costHistory.length > COST_WINDOW_SIZE) {
|
|
11331
11304
|
this.costHistory.shift();
|
|
11332
11305
|
}
|
|
11333
11306
|
}
|
|
11334
11307
|
get mean() {
|
|
11335
|
-
if (this.costHistory.length === 0)
|
|
11336
|
-
return 0;
|
|
11308
|
+
if (this.costHistory.length === 0) return 0;
|
|
11337
11309
|
return this.costHistory.reduce((a, b) => a + b, 0) / this.costHistory.length;
|
|
11338
11310
|
}
|
|
11339
11311
|
checkAnomaly(model, cost) {
|
|
11340
|
-
if (this.disabled)
|
|
11341
|
-
|
|
11342
|
-
if (this.costHistory.length < COST_WARMUP_SAMPLES)
|
|
11343
|
-
return false;
|
|
11312
|
+
if (this.disabled) return false;
|
|
11313
|
+
if (this.costHistory.length < COST_WARMUP_SAMPLES) return false;
|
|
11344
11314
|
const avg = this.mean;
|
|
11345
|
-
if (avg <= 0 || cost <= avg)
|
|
11346
|
-
return false;
|
|
11315
|
+
if (avg <= 0 || cost <= avg) return false;
|
|
11347
11316
|
const ratio = cost / avg;
|
|
11348
11317
|
if (ratio > COST_ANOMALY_THRESHOLD) {
|
|
11349
11318
|
this.currentAnomalyModel = model;
|
|
@@ -11365,8 +11334,7 @@ var CostAnomalyDetector = class {
|
|
|
11365
11334
|
};
|
|
11366
11335
|
var _costDetector = null;
|
|
11367
11336
|
function getCostAnomalyDetector() {
|
|
11368
|
-
if (!_costDetector)
|
|
11369
|
-
_costDetector = new CostAnomalyDetector();
|
|
11337
|
+
if (!_costDetector) _costDetector = new CostAnomalyDetector();
|
|
11370
11338
|
return _costDetector;
|
|
11371
11339
|
}
|
|
11372
11340
|
|
|
@@ -11378,10 +11346,9 @@ import { readFileSync as readFileSync15, writeFileSync as writeFileSync13, appen
|
|
|
11378
11346
|
import { join as join16, dirname as dirname11 } from "node:path";
|
|
11379
11347
|
import { createHash as createHash4 } from "node:crypto";
|
|
11380
11348
|
|
|
11381
|
-
// src/utils/tdd-helpers.
|
|
11349
|
+
// src/utils/tdd-helpers.ts
|
|
11382
11350
|
function extractExports(sourceContent, ext) {
|
|
11383
|
-
if (!sourceContent || typeof sourceContent !== "string")
|
|
11384
|
-
return [];
|
|
11351
|
+
if (!sourceContent || typeof sourceContent !== "string") return [];
|
|
11385
11352
|
const exports = [];
|
|
11386
11353
|
const seen = /* @__PURE__ */ new Set();
|
|
11387
11354
|
const add = (name, type = "function") => {
|
|
@@ -11392,69 +11359,51 @@ function extractExports(sourceContent, ext) {
|
|
|
11392
11359
|
};
|
|
11393
11360
|
switch (ext) {
|
|
11394
11361
|
case "py": {
|
|
11395
|
-
for (const m of sourceContent.matchAll(/^def\s+([a-zA-Z]\w*)\s*\(/gm))
|
|
11396
|
-
|
|
11397
|
-
for (const m of sourceContent.matchAll(/^class\s+([a-zA-Z_]\w*)\s*[\(:]/gm))
|
|
11398
|
-
add(m[1], "class");
|
|
11362
|
+
for (const m of sourceContent.matchAll(/^def\s+([a-zA-Z]\w*)\s*\(/gm)) add(m[1]);
|
|
11363
|
+
for (const m of sourceContent.matchAll(/^class\s+([a-zA-Z_]\w*)\s*[\(:]/gm)) add(m[1], "class");
|
|
11399
11364
|
break;
|
|
11400
11365
|
}
|
|
11401
11366
|
case "js":
|
|
11402
11367
|
case "mjs":
|
|
11403
11368
|
case "jsx": {
|
|
11404
|
-
for (const m of sourceContent.matchAll(/export\s+(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
11405
|
-
|
|
11406
|
-
for (const m of sourceContent.matchAll(/export\s+const\s+([a-zA-Z_$]\w*)\s*=/g))
|
|
11407
|
-
add(m[1]);
|
|
11369
|
+
for (const m of sourceContent.matchAll(/export\s+(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/g)) add(m[1]);
|
|
11370
|
+
for (const m of sourceContent.matchAll(/export\s+const\s+([a-zA-Z_$]\w*)\s*=/g)) add(m[1]);
|
|
11408
11371
|
if (exports.length === 0) {
|
|
11409
|
-
for (const m of sourceContent.matchAll(/^(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/gm))
|
|
11410
|
-
add(m[1]);
|
|
11372
|
+
for (const m of sourceContent.matchAll(/^(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/gm)) add(m[1]);
|
|
11411
11373
|
}
|
|
11412
11374
|
break;
|
|
11413
11375
|
}
|
|
11414
11376
|
case "ts":
|
|
11415
11377
|
case "tsx": {
|
|
11416
|
-
for (const m of sourceContent.matchAll(/export\s+(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
11417
|
-
|
|
11418
|
-
for (const m of sourceContent.matchAll(/export\s+
|
|
11419
|
-
add(m[1]);
|
|
11420
|
-
for (const m of sourceContent.matchAll(/export\s+class\s+([a-zA-Z_$]\w*)/g))
|
|
11421
|
-
add(m[1], "class");
|
|
11378
|
+
for (const m of sourceContent.matchAll(/export\s+(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/g)) add(m[1]);
|
|
11379
|
+
for (const m of sourceContent.matchAll(/export\s+const\s+([a-zA-Z_$]\w*)\s*[:=]/g)) add(m[1]);
|
|
11380
|
+
for (const m of sourceContent.matchAll(/export\s+class\s+([a-zA-Z_$]\w*)/g)) add(m[1], "class");
|
|
11422
11381
|
break;
|
|
11423
11382
|
}
|
|
11424
11383
|
case "go": {
|
|
11425
|
-
for (const m of sourceContent.matchAll(/func\s+(?:\([^)]+\)\s+)?([A-Z]\w*)\s*\(/g))
|
|
11426
|
-
add(m[1]);
|
|
11384
|
+
for (const m of sourceContent.matchAll(/func\s+(?:\([^)]+\)\s+)?([A-Z]\w*)\s*\(/g)) add(m[1]);
|
|
11427
11385
|
break;
|
|
11428
11386
|
}
|
|
11429
11387
|
case "rs": {
|
|
11430
|
-
for (const m of sourceContent.matchAll(/pub\s+fn\s+([a-zA-Z_]\w*)\s*</g))
|
|
11431
|
-
|
|
11432
|
-
for (const m of sourceContent.matchAll(/pub\s+
|
|
11433
|
-
add(m[1]);
|
|
11434
|
-
for (const m of sourceContent.matchAll(/pub\s+struct\s+([a-zA-Z_]\w*)/g))
|
|
11435
|
-
add(m[1], "struct");
|
|
11388
|
+
for (const m of sourceContent.matchAll(/pub\s+fn\s+([a-zA-Z_]\w*)\s*</g)) add(m[1]);
|
|
11389
|
+
for (const m of sourceContent.matchAll(/pub\s+fn\s+([a-zA-Z_]\w*)\s*\(/g)) add(m[1]);
|
|
11390
|
+
for (const m of sourceContent.matchAll(/pub\s+struct\s+([a-zA-Z_]\w*)/g)) add(m[1], "struct");
|
|
11436
11391
|
break;
|
|
11437
11392
|
}
|
|
11438
11393
|
case "rb": {
|
|
11439
|
-
for (const m of sourceContent.matchAll(/def\s+(?:self\.)?([a-zA-Z_]\w*[?!=]?)/g))
|
|
11440
|
-
|
|
11441
|
-
for (const m of sourceContent.matchAll(/class\s+([A-Z]\w*)/g))
|
|
11442
|
-
add(m[1], "class");
|
|
11394
|
+
for (const m of sourceContent.matchAll(/def\s+(?:self\.)?([a-zA-Z_]\w*[?!=]?)/g)) add(m[1]);
|
|
11395
|
+
for (const m of sourceContent.matchAll(/class\s+([A-Z]\w*)/g)) add(m[1], "class");
|
|
11443
11396
|
break;
|
|
11444
11397
|
}
|
|
11445
11398
|
case "java":
|
|
11446
11399
|
case "kt": {
|
|
11447
|
-
for (const m of sourceContent.matchAll(/(?:public|protected)\s+(?:static\s+)?(?:final\s+)?\S+\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
11448
|
-
|
|
11449
|
-
for (const m of sourceContent.matchAll(/fun\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
11450
|
-
add(m[1]);
|
|
11400
|
+
for (const m of sourceContent.matchAll(/(?:public|protected)\s+(?:static\s+)?(?:final\s+)?\S+\s+([a-zA-Z_$]\w*)\s*\(/g)) add(m[1]);
|
|
11401
|
+
for (const m of sourceContent.matchAll(/fun\s+([a-zA-Z_$]\w*)\s*\(/g)) add(m[1]);
|
|
11451
11402
|
break;
|
|
11452
11403
|
}
|
|
11453
11404
|
case "sh": {
|
|
11454
|
-
for (const m of sourceContent.matchAll(/^(?:function\s+)?([a-zA-Z_]\w*)\s*\(\)\s*\{/gm))
|
|
11455
|
-
|
|
11456
|
-
for (const m of sourceContent.matchAll(/^function\s+([a-zA-Z_]\w*)/gm))
|
|
11457
|
-
add(m[1]);
|
|
11405
|
+
for (const m of sourceContent.matchAll(/^(?:function\s+)?([a-zA-Z_]\w*)\s*\(\)\s*\{/gm)) add(m[1]);
|
|
11406
|
+
for (const m of sourceContent.matchAll(/^function\s+([a-zA-Z_]\w*)/gm)) add(m[1]);
|
|
11458
11407
|
break;
|
|
11459
11408
|
}
|
|
11460
11409
|
}
|
|
@@ -11476,8 +11425,7 @@ function generateTestCaseNames(funcName, _type, quality = false) {
|
|
|
11476
11425
|
];
|
|
11477
11426
|
}
|
|
11478
11427
|
function inferFunctionParams(sourceContent, funcName) {
|
|
11479
|
-
if (!sourceContent || !funcName)
|
|
11480
|
-
return [];
|
|
11428
|
+
if (!sourceContent || !funcName) return [];
|
|
11481
11429
|
const patterns = [
|
|
11482
11430
|
new RegExp(`(?:export\\s+)?(?:async\\s+)?function\\s+${funcName}\\s*\\(([^)]*)\\)`, "m"),
|
|
11483
11431
|
new RegExp(`(?:export\\s+)?const\\s+${funcName}\\s*[:=]\\s*(?:async\\s+)?\\(([^)]*)\\)`, "m"),
|
|
@@ -11490,8 +11438,7 @@ function inferFunctionParams(sourceContent, funcName) {
|
|
|
11490
11438
|
if (m) {
|
|
11491
11439
|
return m[1].split(",").map((s) => {
|
|
11492
11440
|
const trimmed = s.trim();
|
|
11493
|
-
if (!trimmed)
|
|
11494
|
-
return null;
|
|
11441
|
+
if (!trimmed) return null;
|
|
11495
11442
|
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*[,)]))/);
|
|
11496
11443
|
const rawName = trimmed.replace(/^[^a-zA-Z_$]*/, "").replace(/[=:].*$/, "").replace(/\s+.*$/, "").trim();
|
|
11497
11444
|
const defaultMatch = trimmed.match(/=\s*(.+)$/);
|
|
@@ -11507,35 +11454,22 @@ function inferFunctionParams(sourceContent, funcName) {
|
|
|
11507
11454
|
return [];
|
|
11508
11455
|
}
|
|
11509
11456
|
function inferTypeFromName(paramName, defaultValue) {
|
|
11510
|
-
if (!paramName)
|
|
11511
|
-
return "any";
|
|
11457
|
+
if (!paramName) return "any";
|
|
11512
11458
|
const name = paramName.toLowerCase();
|
|
11513
11459
|
if (defaultValue !== null && defaultValue !== void 0) {
|
|
11514
|
-
if (/^["']/.test(defaultValue))
|
|
11515
|
-
|
|
11516
|
-
if (
|
|
11517
|
-
|
|
11518
|
-
if (
|
|
11519
|
-
|
|
11520
|
-
|
|
11521
|
-
|
|
11522
|
-
|
|
11523
|
-
|
|
11524
|
-
|
|
11525
|
-
|
|
11526
|
-
|
|
11527
|
-
if (/^(is|has|can|should|will|did|was|are|contains?_|[A-Z])/.test(name))
|
|
11528
|
-
return "boolean";
|
|
11529
|
-
if (/^(count|index|limit|offset|max|min|size|length|total|num|age)_?/.test(name))
|
|
11530
|
-
return "number";
|
|
11531
|
-
if (/^(name|title|label|msg|message|text|str|prefix|suffix|path|url|email|id)_?/.test(name))
|
|
11532
|
-
return "string";
|
|
11533
|
-
if (/^(items|list|arr|entries|data|values|args)_?/.test(name))
|
|
11534
|
-
return "array";
|
|
11535
|
-
if (/^(obj|config|opts|options|settings|params|props)_?/.test(name))
|
|
11536
|
-
return "object";
|
|
11537
|
-
if (/^(fn|cb|callback|handler|on[A-Z])/.test(name))
|
|
11538
|
-
return "function";
|
|
11460
|
+
if (/^["']/.test(defaultValue)) return "string";
|
|
11461
|
+
if (/^\d+\.?\d*$/.test(defaultValue)) return "number";
|
|
11462
|
+
if (/^(true|false)$/i.test(defaultValue)) return "boolean";
|
|
11463
|
+
if (/^\[/.test(defaultValue)) return "array";
|
|
11464
|
+
if (/^\{/.test(defaultValue)) return "object";
|
|
11465
|
+
if (/^null$/i.test(defaultValue)) return "null";
|
|
11466
|
+
}
|
|
11467
|
+
if (/^(is|has|can|should|will|did|was|are|contains?_|[A-Z])/.test(name)) return "boolean";
|
|
11468
|
+
if (/^(count|index|limit|offset|max|min|size|length|total|num|age)_?/.test(name)) return "number";
|
|
11469
|
+
if (/^(name|title|label|msg|message|text|str|prefix|suffix|path|url|email|id)_?/.test(name)) return "string";
|
|
11470
|
+
if (/^(items|list|arr|entries|data|values|args)_?/.test(name)) return "array";
|
|
11471
|
+
if (/^(obj|config|opts|options|settings|params|props)_?/.test(name)) return "object";
|
|
11472
|
+
if (/^(fn|cb|callback|handler|on[A-Z])/.test(name)) return "function";
|
|
11539
11473
|
return "any";
|
|
11540
11474
|
}
|
|
11541
11475
|
function _langComment(lang) {
|
|
@@ -11548,22 +11482,14 @@ function buildQualityAssertionsForFunc(funcName, params, lang, indent) {
|
|
|
11548
11482
|
let block = "";
|
|
11549
11483
|
const testValues = params.map((p) => {
|
|
11550
11484
|
const t = p.type || inferTypeFromName(p.name, p.defaultValue);
|
|
11551
|
-
if (t === "string" || t === "String")
|
|
11552
|
-
|
|
11553
|
-
if (t === "
|
|
11554
|
-
|
|
11555
|
-
if (t === "
|
|
11556
|
-
|
|
11557
|
-
if (t === "
|
|
11558
|
-
|
|
11559
|
-
if (t === "object" || t === "Object" || t === "dict" || t === "Dict")
|
|
11560
|
-
return "{}";
|
|
11561
|
-
if (t === "function" || t === "Function")
|
|
11562
|
-
return "() => {}";
|
|
11563
|
-
if (t === "any")
|
|
11564
|
-
return '"test"';
|
|
11565
|
-
if (t === "null")
|
|
11566
|
-
return "null";
|
|
11485
|
+
if (t === "string" || t === "String") return '"sample_input"';
|
|
11486
|
+
if (t === "number" || t === "int" || t === "float" || t === "Number") return "42";
|
|
11487
|
+
if (t === "boolean" || t === "bool" || t === "Boolean") return "true";
|
|
11488
|
+
if (t === "array" || t === "Array" || t === "list" || t === "List") return "[]";
|
|
11489
|
+
if (t === "object" || t === "Object" || t === "dict" || t === "Dict") return "{}";
|
|
11490
|
+
if (t === "function" || t === "Function") return "() => {}";
|
|
11491
|
+
if (t === "any") return '"test"';
|
|
11492
|
+
if (t === "null") return "null";
|
|
11567
11493
|
return '"test"';
|
|
11568
11494
|
});
|
|
11569
11495
|
const args = testValues.join(", ");
|
|
@@ -11593,10 +11519,8 @@ function buildQualityAssertionsForFunc(funcName, params, lang, indent) {
|
|
|
11593
11519
|
`;
|
|
11594
11520
|
const ecArgs = params.map((p) => {
|
|
11595
11521
|
const t = p.type || inferTypeFromName(p.name, p.defaultValue);
|
|
11596
|
-
if (t === "string")
|
|
11597
|
-
|
|
11598
|
-
if (t === "number" || t === "int" || t === "float")
|
|
11599
|
-
return "0";
|
|
11522
|
+
if (t === "string") return '""';
|
|
11523
|
+
if (t === "number" || t === "int" || t === "float") return "0";
|
|
11600
11524
|
return '"edge"';
|
|
11601
11525
|
}).join(", ");
|
|
11602
11526
|
block += `${indent} result = ${funcName}(${ecArgs})
|
|
@@ -11634,16 +11558,11 @@ function buildQualityAssertionsForFunc(funcName, params, lang, indent) {
|
|
|
11634
11558
|
`;
|
|
11635
11559
|
const ecArgsJS = params.map((p) => {
|
|
11636
11560
|
const t = p.type || inferTypeFromName(p.name, p.defaultValue);
|
|
11637
|
-
if (t === "string")
|
|
11638
|
-
|
|
11639
|
-
if (t === "
|
|
11640
|
-
|
|
11641
|
-
if (t === "
|
|
11642
|
-
return "false";
|
|
11643
|
-
if (t === "array")
|
|
11644
|
-
return "[]";
|
|
11645
|
-
if (t === "object")
|
|
11646
|
-
return "{}";
|
|
11561
|
+
if (t === "string") return '""';
|
|
11562
|
+
if (t === "number" || t === "int" || t === "float") return "0";
|
|
11563
|
+
if (t === "boolean") return "false";
|
|
11564
|
+
if (t === "array") return "[]";
|
|
11565
|
+
if (t === "object") return "{}";
|
|
11647
11566
|
return "undefined";
|
|
11648
11567
|
}).join(", ");
|
|
11649
11568
|
block += `${indent} const result = mod.${funcName}(${ecArgsJS});
|
|
@@ -11676,15 +11595,14 @@ function buildQualityAssertionsForFunc(funcName, params, lang, indent) {
|
|
|
11676
11595
|
return block;
|
|
11677
11596
|
}
|
|
11678
11597
|
function isSkeletonUseless(content) {
|
|
11679
|
-
if (!content)
|
|
11680
|
-
return true;
|
|
11598
|
+
if (!content) return true;
|
|
11681
11599
|
const lines = content.split("\n").filter((l) => l.trim() && !l.trim().startsWith("//") && !l.trim().startsWith("#") && !l.trim().startsWith("/*") && !l.trim().startsWith("*"));
|
|
11682
11600
|
const todoLines = content.split("\n").filter((l) => /TODO|placeholder|smoke|is exported|module loads/.test(l));
|
|
11683
11601
|
const meaningfulLines = lines.filter((l) => !/TODO|placeholder|smoke|is exported|module loads|throw new Error|raise AssertionError|pytest\.skip|assert.*true/.test(l));
|
|
11684
11602
|
return meaningfulLines.length < 2;
|
|
11685
11603
|
}
|
|
11686
11604
|
|
|
11687
|
-
// src/lib/test-skeletons.
|
|
11605
|
+
// src/lib/test-skeletons.ts
|
|
11688
11606
|
var TEST_SKELETONS = {
|
|
11689
11607
|
py: (name, exports = [], depth = "full", strict = true, quality = true, sourceContent = "") => {
|
|
11690
11608
|
const moduleImport = name.replace(/-/g, "_");
|
|
@@ -11712,8 +11630,7 @@ var TEST_SKELETONS = {
|
|
|
11712
11630
|
|
|
11713
11631
|
`;
|
|
11714
11632
|
for (const exp of exports) {
|
|
11715
|
-
if (exp.type === "class")
|
|
11716
|
-
continue;
|
|
11633
|
+
if (exp.type === "class") continue;
|
|
11717
11634
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11718
11635
|
content += `# TODO: implement tests for ${exp.name}
|
|
11719
11636
|
`;
|
|
@@ -11721,12 +11638,10 @@ var TEST_SKELETONS = {
|
|
|
11721
11638
|
const caseFunc = caseName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
11722
11639
|
content += `def test_${caseFunc}():
|
|
11723
11640
|
`;
|
|
11724
|
-
if (strict)
|
|
11725
|
-
content += ` raise AssertionError("TODO: implement ${caseName}")
|
|
11641
|
+
if (strict) content += ` raise AssertionError("TODO: implement ${caseName}")
|
|
11726
11642
|
|
|
11727
11643
|
`;
|
|
11728
|
-
else
|
|
11729
|
-
content += ` pytest.skip("TODO: implement ${caseName}")
|
|
11644
|
+
else content += ` pytest.skip("TODO: implement ${caseName}")
|
|
11730
11645
|
|
|
11731
11646
|
`;
|
|
11732
11647
|
}
|
|
@@ -11738,12 +11653,10 @@ var TEST_SKELETONS = {
|
|
|
11738
11653
|
if (exports.length === 0) {
|
|
11739
11654
|
content += `def test_${name}_placeholder():
|
|
11740
11655
|
`;
|
|
11741
|
-
if (strict)
|
|
11742
|
-
content += ` raise AssertionError("TODO: implement tests for ${name}")
|
|
11656
|
+
if (strict) content += ` raise AssertionError("TODO: implement tests for ${name}")
|
|
11743
11657
|
|
|
11744
11658
|
`;
|
|
11745
|
-
else
|
|
11746
|
-
content += ` pytest.skip("TODO: implement tests for ${name}")
|
|
11659
|
+
else content += ` pytest.skip("TODO: implement tests for ${name}")
|
|
11747
11660
|
|
|
11748
11661
|
`;
|
|
11749
11662
|
}
|
|
@@ -11777,8 +11690,7 @@ var TEST_SKELETONS = {
|
|
|
11777
11690
|
|
|
11778
11691
|
`;
|
|
11779
11692
|
for (const exp of exports) {
|
|
11780
|
-
if (exp.type === "class")
|
|
11781
|
-
continue;
|
|
11693
|
+
if (exp.type === "class") continue;
|
|
11782
11694
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11783
11695
|
content += ` // TODO: implement tests for ${exp.name}
|
|
11784
11696
|
`;
|
|
@@ -11794,11 +11706,9 @@ var TEST_SKELETONS = {
|
|
|
11794
11706
|
`;
|
|
11795
11707
|
content += ` // TODO: implement ${caseName}
|
|
11796
11708
|
`;
|
|
11797
|
-
if (strict)
|
|
11798
|
-
content += ` throw new Error('TODO: implement ${caseName}');
|
|
11709
|
+
if (strict) content += ` throw new Error('TODO: implement ${caseName}');
|
|
11799
11710
|
`;
|
|
11800
|
-
else
|
|
11801
|
-
content += ` expect(true).toBe(true);
|
|
11711
|
+
else content += ` expect(true).toBe(true);
|
|
11802
11712
|
`;
|
|
11803
11713
|
content += ` });
|
|
11804
11714
|
|
|
@@ -11851,8 +11761,7 @@ var TEST_SKELETONS = {
|
|
|
11851
11761
|
|
|
11852
11762
|
`;
|
|
11853
11763
|
for (const exp of exports) {
|
|
11854
|
-
if (exp.type === "class")
|
|
11855
|
-
continue;
|
|
11764
|
+
if (exp.type === "class") continue;
|
|
11856
11765
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11857
11766
|
content += ` // TODO: implement tests for ${exp.name}
|
|
11858
11767
|
`;
|
|
@@ -11868,11 +11777,9 @@ var TEST_SKELETONS = {
|
|
|
11868
11777
|
`;
|
|
11869
11778
|
content += ` // TODO: implement ${caseName}
|
|
11870
11779
|
`;
|
|
11871
|
-
if (strict)
|
|
11872
|
-
content += ` throw new Error('TODO: implement ${caseName}');
|
|
11780
|
+
if (strict) content += ` throw new Error('TODO: implement ${caseName}');
|
|
11873
11781
|
`;
|
|
11874
|
-
else
|
|
11875
|
-
content += ` expect(true).toBe(true);
|
|
11782
|
+
else content += ` expect(true).toBe(true);
|
|
11876
11783
|
`;
|
|
11877
11784
|
content += ` });
|
|
11878
11785
|
|
|
@@ -11925,8 +11832,7 @@ var TEST_SKELETONS = {
|
|
|
11925
11832
|
|
|
11926
11833
|
`;
|
|
11927
11834
|
for (const exp of exports) {
|
|
11928
|
-
if (exp.type === "class")
|
|
11929
|
-
continue;
|
|
11835
|
+
if (exp.type === "class") continue;
|
|
11930
11836
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11931
11837
|
content += ` // TODO: implement tests for ${exp.name}
|
|
11932
11838
|
`;
|
|
@@ -11942,11 +11848,9 @@ var TEST_SKELETONS = {
|
|
|
11942
11848
|
`;
|
|
11943
11849
|
content += ` // TODO: implement ${caseName}
|
|
11944
11850
|
`;
|
|
11945
|
-
if (strict)
|
|
11946
|
-
content += ` throw new Error('TODO: implement ${caseName}');
|
|
11851
|
+
if (strict) content += ` throw new Error('TODO: implement ${caseName}');
|
|
11947
11852
|
`;
|
|
11948
|
-
else
|
|
11949
|
-
content += ` expect(true).toBe(true);
|
|
11853
|
+
else content += ` expect(true).toBe(true);
|
|
11950
11854
|
`;
|
|
11951
11855
|
content += ` });
|
|
11952
11856
|
|
|
@@ -12006,8 +11910,7 @@ var TEST_SKELETONS = {
|
|
|
12006
11910
|
|
|
12007
11911
|
`;
|
|
12008
11912
|
for (const exp of exports) {
|
|
12009
|
-
if (exp.type === "class")
|
|
12010
|
-
continue;
|
|
11913
|
+
if (exp.type === "class") continue;
|
|
12011
11914
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
12012
11915
|
const expCap = exp.name.charAt(0).toUpperCase() + exp.name.slice(1);
|
|
12013
11916
|
content += `// TODO: implement tests for ${exp.name}
|
|
@@ -12016,11 +11919,9 @@ var TEST_SKELETONS = {
|
|
|
12016
11919
|
const caseFunc = caseName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
12017
11920
|
content += `func Test${cap}_${caseFunc}(t *testing.T) {
|
|
12018
11921
|
`;
|
|
12019
|
-
if (strict)
|
|
12020
|
-
content += ` t.Error("TODO: implement ${caseName}")
|
|
11922
|
+
if (strict) content += ` t.Error("TODO: implement ${caseName}")
|
|
12021
11923
|
`;
|
|
12022
|
-
else
|
|
12023
|
-
content += ` t.Skip("TODO: implement ${caseName}")
|
|
11924
|
+
else content += ` t.Skip("TODO: implement ${caseName}")
|
|
12024
11925
|
`;
|
|
12025
11926
|
content += `}
|
|
12026
11927
|
|
|
@@ -12040,11 +11941,9 @@ var TEST_SKELETONS = {
|
|
|
12040
11941
|
if (exports.length === 0) {
|
|
12041
11942
|
content += `func Test${cap}_Placeholder(t *testing.T) {
|
|
12042
11943
|
`;
|
|
12043
|
-
if (strict)
|
|
12044
|
-
content += ` t.Error("TODO: implement tests for ${name}")
|
|
11944
|
+
if (strict) content += ` t.Error("TODO: implement tests for ${name}")
|
|
12045
11945
|
`;
|
|
12046
|
-
else
|
|
12047
|
-
content += ` t.Skip("TODO: implement tests for ${name}")
|
|
11946
|
+
else content += ` t.Skip("TODO: implement tests for ${name}")
|
|
12048
11947
|
`;
|
|
12049
11948
|
content += `}
|
|
12050
11949
|
`;
|
|
@@ -12077,11 +11976,9 @@ var TEST_SKELETONS = {
|
|
|
12077
11976
|
`;
|
|
12078
11977
|
content += ` echo "TODO: implement ${caseName}"
|
|
12079
11978
|
`;
|
|
12080
|
-
if (strict)
|
|
12081
|
-
content += ` exit 1
|
|
11979
|
+
if (strict) content += ` exit 1
|
|
12082
11980
|
`;
|
|
12083
|
-
else
|
|
12084
|
-
content += ` echo "SKIP: ${caseName}"
|
|
11981
|
+
else content += ` echo "SKIP: ${caseName}"
|
|
12085
11982
|
`;
|
|
12086
11983
|
content += `}
|
|
12087
11984
|
|
|
@@ -12095,11 +11992,9 @@ var TEST_SKELETONS = {
|
|
|
12095
11992
|
if (exports.length === 0) {
|
|
12096
11993
|
content += `function test_smoke {
|
|
12097
11994
|
`;
|
|
12098
|
-
if (strict)
|
|
12099
|
-
content += ` echo "TODO: implement tests for ${name}" && exit 1
|
|
11995
|
+
if (strict) content += ` echo "TODO: implement tests for ${name}" && exit 1
|
|
12100
11996
|
`;
|
|
12101
|
-
else
|
|
12102
|
-
content += ` echo "TODO: implement tests for ${name}"
|
|
11997
|
+
else content += ` echo "TODO: implement tests for ${name}"
|
|
12103
11998
|
`;
|
|
12104
11999
|
content += `}
|
|
12105
12000
|
`;
|
|
@@ -12139,8 +12034,7 @@ mod tests {
|
|
|
12139
12034
|
|
|
12140
12035
|
`;
|
|
12141
12036
|
for (const exp of exports) {
|
|
12142
|
-
if (exp.type === "class")
|
|
12143
|
-
continue;
|
|
12037
|
+
if (exp.type === "class") continue;
|
|
12144
12038
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
12145
12039
|
content += ` // TODO: implement tests for ${exp.name}
|
|
12146
12040
|
`;
|
|
@@ -12149,11 +12043,9 @@ mod tests {
|
|
|
12149
12043
|
content += ` #[test]
|
|
12150
12044
|
fn test_${caseFunc}() {
|
|
12151
12045
|
`;
|
|
12152
|
-
if (strict)
|
|
12153
|
-
content += ` panic!("TODO: implement ${caseName}");
|
|
12046
|
+
if (strict) content += ` panic!("TODO: implement ${caseName}");
|
|
12154
12047
|
`;
|
|
12155
|
-
else
|
|
12156
|
-
content += ` // TODO: implement ${caseName}
|
|
12048
|
+
else content += ` // TODO: implement ${caseName}
|
|
12157
12049
|
`;
|
|
12158
12050
|
content += ` }
|
|
12159
12051
|
|
|
@@ -12168,11 +12060,9 @@ mod tests {
|
|
|
12168
12060
|
content += ` #[test]
|
|
12169
12061
|
fn ${name}_placeholder() {
|
|
12170
12062
|
`;
|
|
12171
|
-
if (strict)
|
|
12172
|
-
content += ` panic!("TODO: implement tests for ${name}");
|
|
12063
|
+
if (strict) content += ` panic!("TODO: implement tests for ${name}");
|
|
12173
12064
|
`;
|
|
12174
|
-
else
|
|
12175
|
-
content += ` // TODO: implement tests for ${name}
|
|
12065
|
+
else content += ` // TODO: implement tests for ${name}
|
|
12176
12066
|
`;
|
|
12177
12067
|
content += ` }
|
|
12178
12068
|
`;
|
|
@@ -12212,8 +12102,7 @@ mod tests {
|
|
|
12212
12102
|
|
|
12213
12103
|
`;
|
|
12214
12104
|
for (const exp of exports) {
|
|
12215
|
-
if (exp.type === "class")
|
|
12216
|
-
continue;
|
|
12105
|
+
if (exp.type === "class") continue;
|
|
12217
12106
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
12218
12107
|
content += ` # TODO: implement tests for ${exp.name}
|
|
12219
12108
|
`;
|
|
@@ -12221,11 +12110,9 @@ mod tests {
|
|
|
12221
12110
|
const caseFunc = caseName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
12222
12111
|
content += ` def test_${caseFunc}
|
|
12223
12112
|
`;
|
|
12224
|
-
if (strict)
|
|
12225
|
-
content += ` flunk "TODO: implement ${caseName}"
|
|
12113
|
+
if (strict) content += ` flunk "TODO: implement ${caseName}"
|
|
12226
12114
|
`;
|
|
12227
|
-
else
|
|
12228
|
-
content += ` # TODO: implement ${caseName}
|
|
12115
|
+
else content += ` # TODO: implement ${caseName}
|
|
12229
12116
|
`;
|
|
12230
12117
|
content += ` end
|
|
12231
12118
|
|
|
@@ -12239,11 +12126,9 @@ mod tests {
|
|
|
12239
12126
|
if (exports.length === 0) {
|
|
12240
12127
|
content += ` def test_placeholder
|
|
12241
12128
|
`;
|
|
12242
|
-
if (strict)
|
|
12243
|
-
content += ` flunk "TODO: implement tests for ${name}"
|
|
12129
|
+
if (strict) content += ` flunk "TODO: implement tests for ${name}"
|
|
12244
12130
|
`;
|
|
12245
|
-
else
|
|
12246
|
-
content += ` # TODO: implement tests for ${name}
|
|
12131
|
+
else content += ` # TODO: implement tests for ${name}
|
|
12247
12132
|
`;
|
|
12248
12133
|
content += ` end
|
|
12249
12134
|
`;
|
|
@@ -12289,18 +12174,15 @@ mod tests {
|
|
|
12289
12174
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
12290
12175
|
for (const caseName of cases) {
|
|
12291
12176
|
const testFunc = caseName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
12292
|
-
if (!strict)
|
|
12293
|
-
content += ` // @Disabled("TODO")
|
|
12177
|
+
if (!strict) content += ` // @Disabled("TODO")
|
|
12294
12178
|
`;
|
|
12295
12179
|
content += ` @Test
|
|
12296
12180
|
`;
|
|
12297
12181
|
content += ` void test${testFunc.charAt(0).toUpperCase() + testFunc.slice(1)}() {
|
|
12298
12182
|
`;
|
|
12299
|
-
if (strict)
|
|
12300
|
-
content += ` fail("TODO: implement ${caseName}");
|
|
12183
|
+
if (strict) content += ` fail("TODO: implement ${caseName}");
|
|
12301
12184
|
`;
|
|
12302
|
-
else
|
|
12303
|
-
content += ` assertTrue(true); // TODO: implement ${caseName}
|
|
12185
|
+
else content += ` assertTrue(true); // TODO: implement ${caseName}
|
|
12304
12186
|
`;
|
|
12305
12187
|
content += ` }
|
|
12306
12188
|
|
|
@@ -12362,18 +12244,15 @@ mod tests {
|
|
|
12362
12244
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
12363
12245
|
for (const caseName of cases) {
|
|
12364
12246
|
const testFunc = caseName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
12365
|
-
if (!strict)
|
|
12366
|
-
content += ` // @Disabled("TODO")
|
|
12247
|
+
if (!strict) content += ` // @Disabled("TODO")
|
|
12367
12248
|
`;
|
|
12368
12249
|
content += ` @Test
|
|
12369
12250
|
`;
|
|
12370
12251
|
content += ` fun test${testFunc.charAt(0).toUpperCase() + testFunc.slice(1)}() {
|
|
12371
12252
|
`;
|
|
12372
|
-
if (strict)
|
|
12373
|
-
content += ` fail("TODO: implement ${caseName}")
|
|
12253
|
+
if (strict) content += ` fail("TODO: implement ${caseName}")
|
|
12374
12254
|
`;
|
|
12375
|
-
else
|
|
12376
|
-
content += ` assertTrue(true) // TODO: implement ${caseName}
|
|
12255
|
+
else content += ` assertTrue(true) // TODO: implement ${caseName}
|
|
12377
12256
|
`;
|
|
12378
12257
|
content += ` }
|
|
12379
12258
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeostheog",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.10",
|
|
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",
|