osdy-pi 1.2.0 → 1.3.0
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 +160 -30
- package/bin/osdy-pi.mjs +29 -6
- package/bin/osdy.mjs +43 -0
- package/extensions/osdy-pi/account-profiles.test.ts +111 -97
- package/extensions/osdy-pi/account-profiles.ts +91 -162
- package/extensions/osdy-pi/animation.test.ts +84 -0
- package/extensions/osdy-pi/animation.ts +17 -8
- package/extensions/osdy-pi/codex-usage-ui.test.ts +1145 -0
- package/extensions/osdy-pi/codex-usage-ui.ts +728 -0
- package/extensions/osdy-pi/codex-usage.test.ts +276 -0
- package/extensions/osdy-pi/codex-usage.ts +276 -0
- package/extensions/osdy-pi/constants.ts +134 -34
- package/extensions/osdy-pi/context-usage-ui.test.ts +168 -0
- package/extensions/osdy-pi/context-usage-ui.ts +60 -0
- package/extensions/osdy-pi/editor-settings.test.ts +121 -23
- package/extensions/osdy-pi/editor-settings.ts +39 -3
- package/extensions/osdy-pi/metrics.test.ts +95 -0
- package/extensions/osdy-pi/metrics.ts +39 -1
- package/extensions/osdy-pi/profile-label.ts +2 -2
- package/extensions/osdy-pi/runtime-helpers.test.ts +220 -1
- package/extensions/osdy-pi/runtime-helpers.ts +42 -19
- package/extensions/osdy-pi/runtime.test.ts +355 -7
- package/extensions/osdy-pi/runtime.ts +344 -66
- package/extensions/osdy-pi/types.ts +26 -1
- package/extensions/osdy-pi/ui.test.ts +128 -0
- package/extensions/osdy-pi/ui.ts +57 -40
- package/package.json +5 -2
- package/scripts/osdy-pi-account-profiles.mjs +521 -76
- package/scripts/osdy-pi-gentle-coexistence.mjs +200 -0
- package/scripts/osdy-pi-profile-setup.mjs +175 -0
- package/themes/osdy-pi-catppuccin-frappe.json +6 -2
- package/themes/osdy-pi-catppuccin-latte.json +6 -2
- package/themes/osdy-pi-catppuccin-macchiato.json +6 -2
- package/themes/osdy-pi-catppuccin-mocha.json +6 -2
- package/themes/osdy-pi-dark.json +6 -2
- package/themes/osdy-pi-dracula.json +6 -2
- package/themes/osdy-pi-kanagawa-dragon.json +6 -2
- package/themes/osdy-pi-kanagawa-lotus.json +6 -2
- package/themes/osdy-pi-kanagawa-wave.json +6 -2
- package/themes/osdy-pi-lucent-orange.json +6 -2
- package/themes/osdy-pi-matrix.json +6 -2
- package/themes/osdy-pi-new.json +6 -2
- package/themes/osdy-pi-sexy.json +6 -2
- package/themes/osdy-pi-tokyo-night.json +6 -2
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { registerHooks } from "node:module";
|
|
3
|
+
import test from "node:test";
|
|
4
|
+
// @ts-expect-error Node's native TypeScript runner resolves test-only TypeScript source imports.
|
|
5
|
+
import { HEADER_VARIANTS } from "./constants.ts";
|
|
6
|
+
import type { SimpleTheme } from "./types.js";
|
|
7
|
+
|
|
8
|
+
registerHooks({
|
|
9
|
+
resolve(specifier, context, nextResolve) {
|
|
10
|
+
if (
|
|
11
|
+
context.parentURL?.includes("/extensions/osdy-pi/") &&
|
|
12
|
+
specifier.startsWith("./") &&
|
|
13
|
+
specifier.endsWith(".js")
|
|
14
|
+
) {
|
|
15
|
+
return nextResolve(`${specifier.slice(0, -3)}.ts`, context);
|
|
16
|
+
}
|
|
17
|
+
return nextResolve(specifier, context);
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// @ts-expect-error Node's native TypeScript runner resolves test-only TypeScript source imports.
|
|
22
|
+
const { colorAsciiCharacter } = await import("./animation.ts");
|
|
23
|
+
|
|
24
|
+
class RecordingTheme implements SimpleTheme {
|
|
25
|
+
readonly calls: Array<{ name: string; text: string }> = [];
|
|
26
|
+
|
|
27
|
+
fg(name: string, text: string): string {
|
|
28
|
+
this.calls.push({ name, text });
|
|
29
|
+
return `<${name}:${text}>`;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function neonPalette() {
|
|
34
|
+
const palette = HEADER_VARIANTS.neon.headerTonePalette;
|
|
35
|
+
assert.ok(palette);
|
|
36
|
+
return palette;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
void test("Neon renders fixed white and near-black as foreground RGB", () => {
|
|
40
|
+
const palette = neonPalette();
|
|
41
|
+
const theme = new RecordingTheme();
|
|
42
|
+
|
|
43
|
+
assert.equal(
|
|
44
|
+
colorAsciiCharacter(theme, palette.c, "W"),
|
|
45
|
+
"\u001B[38;2;255;255;255mW\u001B[39m",
|
|
46
|
+
);
|
|
47
|
+
assert.equal(
|
|
48
|
+
colorAsciiCharacter(theme, palette.d, "B"),
|
|
49
|
+
"\u001B[38;2;18;1;27mB\u001B[39m",
|
|
50
|
+
);
|
|
51
|
+
assert.deepEqual(theme.calls, []);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
void test("Neon renders main and dark pink through bounded accent styling", () => {
|
|
55
|
+
const palette = neonPalette();
|
|
56
|
+
const theme = new RecordingTheme();
|
|
57
|
+
|
|
58
|
+
const main = colorAsciiCharacter(theme, palette.h, "H");
|
|
59
|
+
const dark = [palette.l, palette.m, palette.p].map((color, index) =>
|
|
60
|
+
colorAsciiCharacter(theme, color, `D${index}`),
|
|
61
|
+
);
|
|
62
|
+
assert.equal(main, "<accent:H>");
|
|
63
|
+
assert.deepEqual(dark, [
|
|
64
|
+
"\u001B[2m<accent:D0>\u001B[22m",
|
|
65
|
+
"\u001B[2m<accent:D1>\u001B[22m",
|
|
66
|
+
"\u001B[2m<accent:D2>\u001B[22m",
|
|
67
|
+
]);
|
|
68
|
+
assert.deepEqual(theme.calls, [
|
|
69
|
+
{ name: "accent", text: "H" },
|
|
70
|
+
{ name: "accent", text: "D0" },
|
|
71
|
+
{ name: "accent", text: "D1" },
|
|
72
|
+
{ name: "accent", text: "D2" },
|
|
73
|
+
]);
|
|
74
|
+
assert.equal(`${main}${dark.join("")}`.includes("\u001B[48;"), false);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
void test("Neon never maps a tone to mdHeading or mdLink", () => {
|
|
78
|
+
for (const color of Object.values(neonPalette())) {
|
|
79
|
+
if (typeof color === "string") {
|
|
80
|
+
assert.notEqual(color, "mdHeading");
|
|
81
|
+
assert.notEqual(color, "mdLink");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { ANIMATION_ENABLED } from "./constants.js";
|
|
2
2
|
import type { AnimationMode, SimpleTheme } from "./types.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
MascotTonePalette,
|
|
5
|
+
ThemeForegroundColor,
|
|
6
|
+
} from "./constants.js";
|
|
4
7
|
import { positiveModulo } from "./utils.js";
|
|
5
8
|
|
|
6
9
|
export type AsciiAnimationStyle = "static" | "animated";
|
|
@@ -25,12 +28,12 @@ export function asciiAnimationMode(): AnimationMode {
|
|
|
25
28
|
return getAnimationOverrideMode(process.env.OSDY_PI_ANIMATION) ?? "intro";
|
|
26
29
|
}
|
|
27
30
|
|
|
28
|
-
function getAnimatedAsciiColor(
|
|
31
|
+
function getAnimatedAsciiColor<Color>(
|
|
29
32
|
wave: number,
|
|
30
|
-
baseColor:
|
|
31
|
-
highlightColor:
|
|
32
|
-
trailColor:
|
|
33
|
-
):
|
|
33
|
+
baseColor: Color,
|
|
34
|
+
highlightColor: Color,
|
|
35
|
+
trailColor: Color,
|
|
36
|
+
): Color {
|
|
34
37
|
if (wave <= 3) return highlightColor;
|
|
35
38
|
if (wave <= 8) return trailColor;
|
|
36
39
|
return baseColor;
|
|
@@ -50,11 +53,17 @@ const GLOW_TRAIL_TONES = {
|
|
|
50
53
|
v: "c",
|
|
51
54
|
} as const;
|
|
52
55
|
|
|
53
|
-
function colorAsciiCharacter(
|
|
56
|
+
export function colorAsciiCharacter(
|
|
54
57
|
theme: SimpleTheme,
|
|
55
|
-
color: string,
|
|
58
|
+
color: string | ThemeForegroundColor,
|
|
56
59
|
character: string,
|
|
57
60
|
): string {
|
|
61
|
+
if (typeof color !== "string") {
|
|
62
|
+
const themedCharacter = theme.fg(color.token, character);
|
|
63
|
+
return color.dimmed
|
|
64
|
+
? `\u001B[2m${themedCharacter}\u001B[22m`
|
|
65
|
+
: themedCharacter;
|
|
66
|
+
}
|
|
58
67
|
const hexMatch = RAW_HEX_COLOR.exec(color);
|
|
59
68
|
if (!hexMatch) return theme.fg(color, character);
|
|
60
69
|
const red = Number.parseInt(hexMatch[1] ?? "", 16);
|