@butlerw/vellum 0.2.0 → 0.2.2
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/dist/index.mjs +201 -33
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -195908,7 +195908,7 @@ init_esm_shims();
|
|
|
195908
195908
|
|
|
195909
195909
|
// src/version.ts
|
|
195910
195910
|
init_esm_shims();
|
|
195911
|
-
var version = "0.2.
|
|
195911
|
+
var version = "0.2.2" ;
|
|
195912
195912
|
|
|
195913
195913
|
// src/tui/components/Banner/ShimmerText.tsx
|
|
195914
195914
|
init_esm_shims();
|
|
@@ -195950,16 +195950,13 @@ function useShimmer(config = {}) {
|
|
|
195950
195950
|
const cycleCountRef = useRef(0);
|
|
195951
195951
|
const lastTickRef = useRef(null);
|
|
195952
195952
|
const lastDebugRef = useRef(0);
|
|
195953
|
+
const hasAnimationTickRef = useRef(false);
|
|
195954
|
+
const { timestamp: timestamp2, isPaused } = useAnimation();
|
|
195953
195955
|
const onCompleteRef = useRef(onComplete);
|
|
195954
195956
|
onCompleteRef.current = onComplete;
|
|
195955
|
-
|
|
195956
|
-
|
|
195957
|
-
|
|
195958
|
-
const timer = setInterval(() => {
|
|
195959
|
-
const now = Date.now();
|
|
195960
|
-
const lastTick = lastTickRef.current ?? now;
|
|
195961
|
-
lastTickRef.current = now;
|
|
195962
|
-
const deltaMs = now - lastTick;
|
|
195957
|
+
const advancePosition = useCallback(
|
|
195958
|
+
(deltaMs, nowMs) => {
|
|
195959
|
+
if (deltaMs <= 0) return;
|
|
195963
195960
|
const step = deltaMs / cycleDuration;
|
|
195964
195961
|
let nextPosition = positionRef.current + step;
|
|
195965
195962
|
if (nextPosition >= 1) {
|
|
@@ -195968,7 +195965,6 @@ function useShimmer(config = {}) {
|
|
|
195968
195965
|
cycleCountRef.current = updatedCycleCount;
|
|
195969
195966
|
setCycleCount(updatedCycleCount);
|
|
195970
195967
|
if (maxCycles !== void 0 && updatedCycleCount >= maxCycles) {
|
|
195971
|
-
clearInterval(timer);
|
|
195972
195968
|
setIsActive(false);
|
|
195973
195969
|
setIsComplete(true);
|
|
195974
195970
|
positionRef.current = 0.618;
|
|
@@ -195982,16 +195978,44 @@ function useShimmer(config = {}) {
|
|
|
195982
195978
|
setPosition(nextPosition);
|
|
195983
195979
|
if (SHIMMER_DEBUG_ENABLED) {
|
|
195984
195980
|
const lastDebug = lastDebugRef.current;
|
|
195985
|
-
if (
|
|
195986
|
-
lastDebugRef.current =
|
|
195981
|
+
if (nowMs - lastDebug >= 1e3) {
|
|
195982
|
+
lastDebugRef.current = nowMs;
|
|
195987
195983
|
debugShimmer(
|
|
195988
195984
|
`deltaMs=${deltaMs.toFixed(1)} position=${nextPosition.toFixed(3)} cycle=${cycleCountRef.current}`
|
|
195989
195985
|
);
|
|
195990
195986
|
}
|
|
195991
195987
|
}
|
|
195988
|
+
},
|
|
195989
|
+
[cycleDuration, maxCycles]
|
|
195990
|
+
);
|
|
195991
|
+
useEffect(() => {
|
|
195992
|
+
if (timestamp2 !== 0) {
|
|
195993
|
+
hasAnimationTickRef.current = true;
|
|
195994
|
+
}
|
|
195995
|
+
}, [timestamp2]);
|
|
195996
|
+
const useGlobalClock = hasAnimationTickRef.current && !isPaused;
|
|
195997
|
+
useEffect(() => {
|
|
195998
|
+
lastTickRef.current = null;
|
|
195999
|
+
}, []);
|
|
196000
|
+
useEffect(() => {
|
|
196001
|
+
if (!useGlobalClock || !isActive || isComplete) return;
|
|
196002
|
+
const lastTick = lastTickRef.current ?? timestamp2;
|
|
196003
|
+
lastTickRef.current = timestamp2;
|
|
196004
|
+
const deltaMs = timestamp2 - lastTick;
|
|
196005
|
+
advancePosition(deltaMs, timestamp2);
|
|
196006
|
+
}, [useGlobalClock, isActive, isComplete, timestamp2, advancePosition]);
|
|
196007
|
+
useEffect(() => {
|
|
196008
|
+
if (useGlobalClock || !isActive || isComplete) return;
|
|
196009
|
+
lastTickRef.current = Date.now();
|
|
196010
|
+
const timer = setInterval(() => {
|
|
196011
|
+
const now = Date.now();
|
|
196012
|
+
const lastTick = lastTickRef.current ?? now;
|
|
196013
|
+
lastTickRef.current = now;
|
|
196014
|
+
const deltaMs = now - lastTick;
|
|
196015
|
+
advancePosition(deltaMs, now);
|
|
195992
196016
|
}, updateInterval);
|
|
195993
196017
|
return () => clearInterval(timer);
|
|
195994
|
-
}, [isActive,
|
|
196018
|
+
}, [useGlobalClock, isActive, isComplete, updateInterval, advancePosition]);
|
|
195995
196019
|
useEffect(() => {
|
|
195996
196020
|
if (enabled && !isComplete) {
|
|
195997
196021
|
setIsActive(true);
|
|
@@ -196026,22 +196050,144 @@ function calculateShimmerIntensity(charIndex, totalChars, shimmerPosition, shimm
|
|
|
196026
196050
|
const intensity = Math.cos(normalizedDistance * Math.PI * 0.5);
|
|
196027
196051
|
return Math.max(0, intensity);
|
|
196028
196052
|
}
|
|
196029
|
-
|
|
196030
|
-
|
|
196031
|
-
|
|
196032
|
-
|
|
196033
|
-
|
|
196034
|
-
|
|
196035
|
-
|
|
196036
|
-
|
|
196053
|
+
var NAMED_COLORS = {
|
|
196054
|
+
black: "#000000",
|
|
196055
|
+
red: "#FF0000",
|
|
196056
|
+
green: "#008000",
|
|
196057
|
+
yellow: "#FFFF00",
|
|
196058
|
+
blue: "#0000FF",
|
|
196059
|
+
magenta: "#FF00FF",
|
|
196060
|
+
cyan: "#00FFFF",
|
|
196061
|
+
white: "#FFFFFF",
|
|
196062
|
+
gray: "#808080",
|
|
196063
|
+
grey: "#808080",
|
|
196064
|
+
orange: "#FFA500",
|
|
196065
|
+
pink: "#FFC0CB",
|
|
196066
|
+
purple: "#800080",
|
|
196067
|
+
brown: "#A52A2A",
|
|
196068
|
+
lime: "#00FF00",
|
|
196069
|
+
navy: "#000080",
|
|
196070
|
+
teal: "#008080",
|
|
196071
|
+
olive: "#808000",
|
|
196072
|
+
maroon: "#800000",
|
|
196073
|
+
aqua: "#00FFFF",
|
|
196074
|
+
fuchsia: "#FF00FF",
|
|
196075
|
+
silver: "#C0C0C0"
|
|
196076
|
+
};
|
|
196077
|
+
function clampRgb(value) {
|
|
196078
|
+
return Math.max(0, Math.min(255, Math.round(value)));
|
|
196079
|
+
}
|
|
196080
|
+
function parseHexColor(hex) {
|
|
196081
|
+
const cleaned = hex.replace("#", "").trim();
|
|
196082
|
+
if (cleaned.length === 3) {
|
|
196083
|
+
const rChar = cleaned[0];
|
|
196084
|
+
const gChar = cleaned[1];
|
|
196085
|
+
const bChar = cleaned[2];
|
|
196086
|
+
if (!rChar || !gChar || !bChar) return null;
|
|
196087
|
+
const r = parseInt(rChar + rChar, 16);
|
|
196088
|
+
const g = parseInt(gChar + gChar, 16);
|
|
196089
|
+
const b = parseInt(bChar + bChar, 16);
|
|
196090
|
+
if ([r, g, b].some((value) => Number.isNaN(value))) return null;
|
|
196091
|
+
return { r, g, b };
|
|
196092
|
+
}
|
|
196093
|
+
if (cleaned.length === 6) {
|
|
196094
|
+
const bigint = parseInt(cleaned, 16);
|
|
196095
|
+
if (Number.isNaN(bigint)) return null;
|
|
196096
|
+
return {
|
|
196097
|
+
r: bigint >> 16 & 255,
|
|
196098
|
+
g: bigint >> 8 & 255,
|
|
196099
|
+
b: bigint & 255
|
|
196100
|
+
};
|
|
196101
|
+
}
|
|
196102
|
+
return null;
|
|
196103
|
+
}
|
|
196104
|
+
function ansi256ToRgb(code) {
|
|
196105
|
+
if (!Number.isFinite(code)) return null;
|
|
196106
|
+
if (code < 0 || code > 255) return null;
|
|
196107
|
+
const ansi16 = [
|
|
196108
|
+
{ r: 0, g: 0, b: 0 },
|
|
196109
|
+
// 0 black
|
|
196110
|
+
{ r: 128, g: 0, b: 0 },
|
|
196111
|
+
// 1 red
|
|
196112
|
+
{ r: 0, g: 128, b: 0 },
|
|
196113
|
+
// 2 green
|
|
196114
|
+
{ r: 128, g: 128, b: 0 },
|
|
196115
|
+
// 3 yellow
|
|
196116
|
+
{ r: 0, g: 0, b: 128 },
|
|
196117
|
+
// 4 blue
|
|
196118
|
+
{ r: 128, g: 0, b: 128 },
|
|
196119
|
+
// 5 magenta
|
|
196120
|
+
{ r: 0, g: 128, b: 128 },
|
|
196121
|
+
// 6 cyan
|
|
196122
|
+
{ r: 192, g: 192, b: 192 },
|
|
196123
|
+
// 7 white (light gray)
|
|
196124
|
+
{ r: 128, g: 128, b: 128 },
|
|
196125
|
+
// 8 bright black (dark gray)
|
|
196126
|
+
{ r: 255, g: 0, b: 0 },
|
|
196127
|
+
// 9 bright red
|
|
196128
|
+
{ r: 0, g: 255, b: 0 },
|
|
196129
|
+
// 10 bright green
|
|
196130
|
+
{ r: 255, g: 255, b: 0 },
|
|
196131
|
+
// 11 bright yellow
|
|
196132
|
+
{ r: 0, g: 0, b: 255 },
|
|
196133
|
+
// 12 bright blue
|
|
196134
|
+
{ r: 255, g: 0, b: 255 },
|
|
196135
|
+
// 13 bright magenta
|
|
196136
|
+
{ r: 0, g: 255, b: 255 },
|
|
196137
|
+
// 14 bright cyan
|
|
196138
|
+
{ r: 255, g: 255, b: 255 }
|
|
196139
|
+
// 15 bright white
|
|
196140
|
+
];
|
|
196141
|
+
if (code < 16) {
|
|
196142
|
+
return ansi16[code] ?? null;
|
|
196143
|
+
}
|
|
196144
|
+
if (code >= 232) {
|
|
196145
|
+
const gray = (code - 232) * 10 + 8;
|
|
196146
|
+
return { r: gray, g: gray, b: gray };
|
|
196147
|
+
}
|
|
196148
|
+
const index = code - 16;
|
|
196149
|
+
const r = Math.floor(index / 36);
|
|
196150
|
+
const g = Math.floor(index % 36 / 6);
|
|
196151
|
+
const b = index % 6;
|
|
196152
|
+
const toChannel = (value) => value === 0 ? 0 : value * 40 + 55;
|
|
196153
|
+
return { r: toChannel(r), g: toChannel(g), b: toChannel(b) };
|
|
196154
|
+
}
|
|
196155
|
+
function parseColorToRgb(color) {
|
|
196156
|
+
const trimmed2 = color.trim().toLowerCase();
|
|
196157
|
+
if (!trimmed2) {
|
|
196158
|
+
return { r: 128, g: 128, b: 128 };
|
|
196159
|
+
}
|
|
196160
|
+
const named = NAMED_COLORS[trimmed2];
|
|
196161
|
+
if (named) {
|
|
196162
|
+
return parseHexColor(named) ?? { r: 128, g: 128, b: 128 };
|
|
196163
|
+
}
|
|
196164
|
+
const hexMatch = trimmed2.match(/^#?[0-9a-f]{3}$|^#?[0-9a-f]{6}$/i);
|
|
196165
|
+
if (hexMatch) {
|
|
196166
|
+
return parseHexColor(trimmed2) ?? { r: 128, g: 128, b: 128 };
|
|
196167
|
+
}
|
|
196168
|
+
const rgbMatch = trimmed2.match(
|
|
196169
|
+
/^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*([\d.]+))?\s*\)$/
|
|
196170
|
+
);
|
|
196171
|
+
if (rgbMatch) {
|
|
196172
|
+
const r = clampRgb(Number.parseInt(rgbMatch[1] ?? "0", 10));
|
|
196173
|
+
const g = clampRgb(Number.parseInt(rgbMatch[2] ?? "0", 10));
|
|
196174
|
+
const b = clampRgb(Number.parseInt(rgbMatch[3] ?? "0", 10));
|
|
196175
|
+
return { r, g, b };
|
|
196176
|
+
}
|
|
196177
|
+
const ansiMatch = trimmed2.match(/^ansi256\(\s*(\d{1,3})\s*\)$/i);
|
|
196178
|
+
if (ansiMatch) {
|
|
196179
|
+
const code = Number.parseInt(ansiMatch[1] ?? "", 10);
|
|
196180
|
+
return ansi256ToRgb(code) ?? { r: 128, g: 128, b: 128 };
|
|
196181
|
+
}
|
|
196182
|
+
return { r: 128, g: 128, b: 128 };
|
|
196037
196183
|
}
|
|
196038
196184
|
function rgbToHex(r, g, b) {
|
|
196039
196185
|
const toHex = (n) => Math.round(n).toString(16).padStart(2, "0");
|
|
196040
196186
|
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
196041
196187
|
}
|
|
196042
196188
|
function interpolateColor(baseColor, highlightColor, intensity) {
|
|
196043
|
-
const base =
|
|
196044
|
-
const highlight =
|
|
196189
|
+
const base = parseColorToRgb(baseColor);
|
|
196190
|
+
const highlight = parseColorToRgb(highlightColor);
|
|
196045
196191
|
const r = base.r + (highlight.r - base.r) * intensity;
|
|
196046
196192
|
const g = base.g + (highlight.g - base.g) * intensity;
|
|
196047
196193
|
const b = base.b + (highlight.b - base.b) * intensity;
|
|
@@ -199969,6 +200115,27 @@ function StreamingIndicatorImpl({
|
|
|
199969
200115
|
}
|
|
199970
200116
|
};
|
|
199971
200117
|
const phaseColor = getPhaseColor();
|
|
200118
|
+
const highlightColor = theme.brand.highlight ?? "#FFD700";
|
|
200119
|
+
const shouldShimmerLabel = phase === "thinking" || phase === "generating" || phase === "tool_call" || phase === "tool_executing";
|
|
200120
|
+
const renderLabel = () => {
|
|
200121
|
+
if (!shouldShimmerLabel) {
|
|
200122
|
+
return /* @__PURE__ */ jsxs(Text, { color: phaseColor, children: [
|
|
200123
|
+
" ",
|
|
200124
|
+
displayLabel
|
|
200125
|
+
] });
|
|
200126
|
+
}
|
|
200127
|
+
return /* @__PURE__ */ jsx(
|
|
200128
|
+
BannerShimmerText,
|
|
200129
|
+
{
|
|
200130
|
+
baseColor: phaseColor,
|
|
200131
|
+
highlightColor,
|
|
200132
|
+
shimmerConfig: { cycleDuration: 2e3 },
|
|
200133
|
+
shimmerWidth: 0.2,
|
|
200134
|
+
bold: true,
|
|
200135
|
+
children: ` ${displayLabel}`
|
|
200136
|
+
}
|
|
200137
|
+
);
|
|
200138
|
+
};
|
|
199972
200139
|
if (narrow) {
|
|
199973
200140
|
const icon = PHASE_ICONS[phase];
|
|
199974
200141
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
@@ -199978,10 +200145,7 @@ function StreamingIndicatorImpl({
|
|
|
199978
200145
|
" ",
|
|
199979
200146
|
icon
|
|
199980
200147
|
] }),
|
|
199981
|
-
|
|
199982
|
-
" ",
|
|
199983
|
-
displayLabel
|
|
199984
|
-
] })
|
|
200148
|
+
renderLabel()
|
|
199985
200149
|
] }),
|
|
199986
200150
|
meta && /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: meta }) }),
|
|
199987
200151
|
rightContent && /* @__PURE__ */ jsx(Box, { children: rightContent })
|
|
@@ -199989,10 +200153,7 @@ function StreamingIndicatorImpl({
|
|
|
199989
200153
|
}
|
|
199990
200154
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "center", children: [
|
|
199991
200155
|
/* @__PURE__ */ jsx(Spinner, { color: phaseColor, frames: spinnerFrames }),
|
|
199992
|
-
|
|
199993
|
-
" ",
|
|
199994
|
-
displayLabel
|
|
199995
|
-
] }),
|
|
200156
|
+
renderLabel(),
|
|
199996
200157
|
meta && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
199997
200158
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
199998
200159
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: meta })
|
|
@@ -229095,7 +229256,8 @@ Respond in JSON: { "score": 0.X, "reasoning": "..." }`;
|
|
|
229095
229256
|
try {
|
|
229096
229257
|
const fullPath = join(env2.workingDir, file);
|
|
229097
229258
|
const content = await readFile(fullPath, "utf-8");
|
|
229098
|
-
const truncated = content.length > MAX_FILE_SIZE2 ? content.slice(0, MAX_FILE_SIZE2)
|
|
229259
|
+
const truncated = content.length > MAX_FILE_SIZE2 ? `${content.slice(0, MAX_FILE_SIZE2)}
|
|
229260
|
+
... (truncated)` : content;
|
|
229099
229261
|
contents.push(`### ${file}
|
|
229100
229262
|
\`\`\`
|
|
229101
229263
|
${truncated}
|
|
@@ -229313,7 +229475,9 @@ var TaskLoader = class {
|
|
|
229313
229475
|
*/
|
|
229314
229476
|
async loadTask(taskId) {
|
|
229315
229477
|
if (this.cache.has(taskId)) {
|
|
229316
|
-
|
|
229478
|
+
const cached = this.cache.get(taskId);
|
|
229479
|
+
if (cached)
|
|
229480
|
+
return cached;
|
|
229317
229481
|
}
|
|
229318
229482
|
const taskPath = await this.findTaskFile(taskId);
|
|
229319
229483
|
if (!taskPath) {
|
|
@@ -229648,6 +229812,10 @@ ${"-".repeat(60)}`);
|
|
|
229648
229812
|
console.log(`\u26A0\uFE0F REGRESSION DETECTED in ${report.regression.regressedTasks.length} task(s):`);
|
|
229649
229813
|
for (const taskId of report.regression.regressedTasks) {
|
|
229650
229814
|
const comp = report.regression.comparisons.find((c) => c.taskId === taskId);
|
|
229815
|
+
if (!comp) {
|
|
229816
|
+
console.log(` - ${taskId}: regression details unavailable`);
|
|
229817
|
+
continue;
|
|
229818
|
+
}
|
|
229651
229819
|
console.log(` - ${taskId}: ${comp.regressionReason}`);
|
|
229652
229820
|
}
|
|
229653
229821
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@butlerw/vellum",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Next-generation AI coding assistant CLI",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -57,13 +57,13 @@
|
|
|
57
57
|
"tsx": "^4.21.0",
|
|
58
58
|
"typescript": "^5.9.3",
|
|
59
59
|
"@vellum/core": "0.1.15",
|
|
60
|
+
"@vellum/eval": "0.1.0",
|
|
60
61
|
"@vellum/lsp": "0.1.0",
|
|
61
62
|
"@vellum/mcp": "0.1.3",
|
|
62
|
-
"@vellum/eval": "0.1.0",
|
|
63
63
|
"@vellum/plugin": "0.1.3",
|
|
64
|
+
"@vellum/provider": "0.2.0",
|
|
64
65
|
"@vellum/sandbox": "0.1.0",
|
|
65
|
-
"@vellum/shared": "0.1.0"
|
|
66
|
-
"@vellum/provider": "0.2.0"
|
|
66
|
+
"@vellum/shared": "0.1.0"
|
|
67
67
|
},
|
|
68
68
|
"scripts": {
|
|
69
69
|
"build": "tsup",
|