osdy-pi 0.1.4 → 0.1.5
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 +36 -5
- package/extensions/osdy-pi/animation.ts +40 -0
- package/extensions/osdy-pi/constants.ts +294 -31
- package/extensions/osdy-pi/runtime-helpers.ts +1 -1
- package/extensions/osdy-pi/runtime.ts +57 -10
- package/extensions/osdy-pi/types.ts +3 -0
- package/extensions/osdy-pi/ui.ts +69 -20
- package/extensions/osdy-pi/utils.ts +10 -10
- package/package.json +3 -2
- package/themes/osdy-pi-dark.json +6 -0
- package/themes/osdy-pi-light.json +6 -0
- package/themes/osdy-pi-simple.json +83 -0
package/README.md
CHANGED
|
@@ -10,15 +10,23 @@ Visit the Osdy landing page: [landing-osdy.vercel.app](https://landing-osdy.verc
|
|
|
10
10
|
|
|
11
11
|
- **Dark theme:** `osdy-pi-dark`, enabled by default when the package starts.
|
|
12
12
|
- **Light theme:** `osdy-pi-light`, with the same Osdy palette adapted for light terminals.
|
|
13
|
-
- **
|
|
13
|
+
- **Simple theme:** `osdy-pi-simple`, a blue/red/slate console theme for the full Pi interface.
|
|
14
|
+
- **Custom header:** two selectable header styles with responsive status metadata: `osdy-theme` (default) and `classic`.
|
|
14
15
|
- **Custom editor:** full-width framed input area with model, thinking, token, cost, and context status.
|
|
15
|
-
- **
|
|
16
|
+
- **Custom working indicator:** a dedicated working widget/spinner appears above the text box, outside the editor frame.
|
|
17
|
+
- **Clean layout:** the built-in working row is hidden while Osdy Pi is enabled to avoid duplicated UI.
|
|
16
18
|
|
|
17
19
|
<img width="1280" height="433" alt="image" src="https://github.com/user-attachments/assets/20c7624d-9ad8-4494-97fb-6b6d81aaf328" />
|
|
18
20
|
|
|
19
21
|
## Install in Pi
|
|
20
22
|
|
|
21
|
-
Install the package
|
|
23
|
+
Install the published package from npm:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pi install npm:osdy-pi
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
You can also install it directly from GitHub:
|
|
22
30
|
|
|
23
31
|
```bash
|
|
24
32
|
pi install git:github.com/OsdyOrtiz/Osdy-Pi
|
|
@@ -45,6 +53,7 @@ Then select one of these theme names:
|
|
|
45
53
|
```text
|
|
46
54
|
osdy-pi-dark
|
|
47
55
|
osdy-pi-light
|
|
56
|
+
osdy-pi-simple
|
|
48
57
|
```
|
|
49
58
|
|
|
50
59
|
You can also set it in your Pi `settings.json`:
|
|
@@ -55,7 +64,7 @@ You can also set it in your Pi `settings.json`:
|
|
|
55
64
|
}
|
|
56
65
|
```
|
|
57
66
|
|
|
58
|
-
Use `osdy-pi-light`
|
|
67
|
+
Use `osdy-pi-light` if you prefer the light version, or `osdy-pi-simple` if you want the blue/red/slate palette across the whole console.
|
|
59
68
|
|
|
60
69
|
## Commands
|
|
61
70
|
|
|
@@ -65,11 +74,20 @@ Osdy Pi includes a small command group:
|
|
|
65
74
|
/osdy-pi enable
|
|
66
75
|
/osdy-pi disable
|
|
67
76
|
/osdy-pi status
|
|
77
|
+
/osdy-pi osdy-theme
|
|
78
|
+
/osdy-pi classic
|
|
79
|
+
/osdy-pi-osdy-theme
|
|
80
|
+
/osdy-pi-classic
|
|
68
81
|
```
|
|
69
82
|
|
|
70
83
|
- `enable` applies the dark Osdy theme, custom header, custom editor, and clean layout.
|
|
71
84
|
- `disable` restores Pi's built-in header, editor, footer, and working visibility, then switches back to the previous theme or `dark`.
|
|
72
|
-
- `status` shows whether the Osdy Pi UI is currently enabled.
|
|
85
|
+
- `status` shows whether the Osdy Pi UI is currently enabled, including the active style.
|
|
86
|
+
- `osdy-theme` is the default OsdyTheme header with pink, cyan, and purple styling, plus the mascot glow on the right edge.
|
|
87
|
+
- `classic` keeps the previous classic header shape with the shared mascot.
|
|
88
|
+
- `/osdy-pi-osdy-theme` and `/osdy-pi-classic` are direct aliases.
|
|
89
|
+
|
|
90
|
+
After changing a local extension, run `/reload` or restart Pi so the updated commands are registered.
|
|
73
91
|
|
|
74
92
|
## Local install
|
|
75
93
|
|
|
@@ -92,11 +110,24 @@ pi install /absolute/path/to/Osdy-Pi
|
|
|
92
110
|
```text
|
|
93
111
|
themes/osdy-pi-dark.json
|
|
94
112
|
themes/osdy-pi-light.json
|
|
113
|
+
themes/osdy-pi-simple.json
|
|
95
114
|
extensions/osdy-pi.ts
|
|
115
|
+
extensions/osdy-pi/
|
|
96
116
|
```
|
|
97
117
|
|
|
118
|
+
`extensions/osdy-pi.ts` is the package entrypoint. The implementation lives in the modular `extensions/osdy-pi/` folder (runtime, UI, metrics, working controller, animation, border, and formatting helpers).
|
|
119
|
+
|
|
98
120
|
The Pi manifest is declared in `package.json` through `pi.themes` and `pi.extensions`, so Pi can discover the themes and extension after installation.
|
|
99
121
|
|
|
122
|
+
## Development
|
|
123
|
+
|
|
124
|
+
If you are working on the package locally, you can run:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
npm run typecheck
|
|
128
|
+
npm run lint
|
|
129
|
+
```
|
|
130
|
+
|
|
100
131
|
## Uninstall or turn off
|
|
101
132
|
|
|
102
133
|
To temporarily turn off the custom UI inside Pi:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ANIMATION_ENABLED } from "./constants.js";
|
|
2
2
|
import type { AnimationMode, SimpleTheme } from "./types.js";
|
|
3
|
+
import type { MascotTonePalette } from "./constants.js";
|
|
3
4
|
import { positiveModulo } from "./utils.js";
|
|
4
5
|
|
|
5
6
|
export type AsciiAnimationStyle = "static" | "animated";
|
|
@@ -57,3 +58,42 @@ export function animateAsciiLine(
|
|
|
57
58
|
})
|
|
58
59
|
.join("");
|
|
59
60
|
}
|
|
61
|
+
|
|
62
|
+
export function animateAsciiLineWithToneMap(
|
|
63
|
+
line: string,
|
|
64
|
+
toneMap: string,
|
|
65
|
+
lineIndex: number,
|
|
66
|
+
frame: number,
|
|
67
|
+
theme: SimpleTheme,
|
|
68
|
+
palette: MascotTonePalette,
|
|
69
|
+
style: AsciiAnimationStyle,
|
|
70
|
+
): string {
|
|
71
|
+
return Array.from(line)
|
|
72
|
+
.map((char, charIndex) => {
|
|
73
|
+
if (char === " ") return char;
|
|
74
|
+
const tone = toneMap[charIndex];
|
|
75
|
+
if (
|
|
76
|
+
tone !== "b" &&
|
|
77
|
+
tone !== "h" &&
|
|
78
|
+
tone !== "l" &&
|
|
79
|
+
tone !== "m" &&
|
|
80
|
+
tone !== "d" &&
|
|
81
|
+
tone !== "p" &&
|
|
82
|
+
tone !== "c" &&
|
|
83
|
+
tone !== "v"
|
|
84
|
+
) {
|
|
85
|
+
return char;
|
|
86
|
+
}
|
|
87
|
+
const baseColor = palette[tone];
|
|
88
|
+
if (style === "static") return theme.fg(baseColor, char);
|
|
89
|
+
const wave = positiveModulo(charIndex + lineIndex * 2 - frame * 5, 44);
|
|
90
|
+
const highlightColor =
|
|
91
|
+
tone === "b" || tone === "h" || tone === "p" ? palette.h : palette.l;
|
|
92
|
+
const trailColor = tone === "d" ? palette.m : palette.b;
|
|
93
|
+
return theme.fg(
|
|
94
|
+
getAnimatedAsciiColor(wave, baseColor, highlightColor, trailColor),
|
|
95
|
+
char,
|
|
96
|
+
);
|
|
97
|
+
})
|
|
98
|
+
.join("");
|
|
99
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { visibleWidth } from "@earendil-works/pi-tui";
|
|
2
|
+
import type { HeaderVariant } from "./types.js";
|
|
2
3
|
|
|
3
4
|
export const THEME_NAME = "osdy-pi-dark";
|
|
4
5
|
export const ANIMATION_ENABLED = true;
|
|
@@ -20,37 +21,83 @@ export const WORKING_WIDGET_KEY = "osdy-pi-working";
|
|
|
20
21
|
export const MASCOT_MIN_ROWS = 34;
|
|
21
22
|
export const MASCOT_GAP = 0;
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
24
|
+
const HTML_MASCOT = [
|
|
25
|
+
" ▓▓▓▓▒ ",
|
|
26
|
+
" ░ ▓▓▓ ▒▓ ",
|
|
27
|
+
" ░░░▓▓▓ ▓▓ ",
|
|
28
|
+
" ▒ ▒ ▒▒ ▒ ░░ ▓▓▓▓ ░▒▓▓ ",
|
|
29
|
+
"▓▓▓▓▓▓▓▓░░░░░ ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒ ░░▒▓ ",
|
|
30
|
+
"▓▓ ▓▓▓▓▓░░░ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░ ░░▒▒ ",
|
|
31
|
+
"▓▓░ ▒▓▓▓▒░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒░░ ░▒▒ ",
|
|
32
|
+
" ▓▒░░ ▒░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓█▓▓█▓▓▓▓▓▒▒▒░▒▒░ ",
|
|
33
|
+
" ▓▒░░ ░▒▒▒▒▒▓▓▓▓▓▒█▒▒▒▒▒▓▓▓▓ ░░░ ▓▓▓▓▒▒▒░░ ",
|
|
34
|
+
" ▒▒░░ ░▒▒▒▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▓▓ ░ ▓ ▒▒░░ ",
|
|
35
|
+
" ▒▒▒▒░▒▒▓▓▓▓░ ░▓▒▒▒▒▒ ░▒▒█▓ ▒▓▓▓░▒ ",
|
|
36
|
+
" ░ ░▒▒▓▓▒ ▓░░ ░░ ░ ▓▓▓▒ ",
|
|
37
|
+
" ░░▒▓░ ░▒░▓▓ ░░ ░▓▓▒ ",
|
|
38
|
+
" ░▒ ▒ ░▒▒▒ ▒▒▒▒ ░ ▒▒▒ ",
|
|
39
|
+
" ░▒▓▓░ ▓▓░░░ █▓ ▒ ░▒▒▒ ",
|
|
40
|
+
" ▒▓▓▓░ ▓▓ ▓▓▓▓▓▓▓▓▓ ░░▒ ",
|
|
41
|
+
" ▓▓▓░ ░ ▓▓▓▓▓▓▒▓▓▓▓ ▓▓▓▓▓▓▓▒░░░░ ░ ",
|
|
42
|
+
" ▒▒▒▒ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░░ ",
|
|
43
|
+
" ▓▒▒░░ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒░░ ▓ ",
|
|
44
|
+
" ░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒ ░░░ ",
|
|
45
|
+
" ░ ░░░░░░░░░░░▒▒░░ ░ ░ ░ ▓ ",
|
|
46
|
+
" ░░░░░▒▒▒▒░░▒░ ▒▒▒▒▒░░ ░░▒▒▒░░░░░░░░ ",
|
|
47
|
+
" ▒▒▒▒▒░░░▒▒▒▒▒▒▒▒▒▒▒▒░░░ ▒░░▒▒▒▒▓▓▓▓░░░░ ",
|
|
48
|
+
" ░▒▒▒▒▒░ ░░▒▒▒▒▒▒▒▒░░░ ░░▒▓▓▓▓▒▒░░ ",
|
|
49
|
+
" ▓░░░░░░ ░ ░░░░░░░░░░░ ░░░░░░▓▒▒▒▒ ░",
|
|
50
|
+
" ░░░▒▒▓▓▓▓▓▒░░░░░░░░░░ ░░▒▒▒▒░░░░░░░▒▒░░ ",
|
|
51
|
+
" ░▒▒▒▓▓▓▓▓▓▓▓▓▓▒▒▒▒░░░ ░▒▒▒▓▓▒░░░ ░░░▒ ",
|
|
52
|
+
" ▒░▒▒▒▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒░░░ ░▒▒▓▓▒░ ░ ",
|
|
53
|
+
" ░░▒▒▒▒▒▒▓▓▓▓▓▓▒▒▒▒▒▒░░░░ ░▒▒▒▒▒ ░ ",
|
|
54
|
+
" ▒░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░ ▒▒░▒ ",
|
|
55
|
+
" ░░░░░░░░░░▒░░▒░▒▒░░░░ ░ ░░░░ ",
|
|
56
|
+
" ░░░░ ░░░░░░░░░░░ ░░░░ ",
|
|
57
|
+
" ░ ░░░░░░ ▓ ",
|
|
58
|
+
" ░░░░░ ░░░░░░ ",
|
|
59
|
+
" ░ ░ ",
|
|
46
60
|
] as const;
|
|
47
61
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
const HTML_MASCOT_MAP = [
|
|
63
|
+
" hhhhl ",
|
|
64
|
+
" dmmhhhmmlhm ",
|
|
65
|
+
" dmmmhhhdmmmmhh ",
|
|
66
|
+
" ldldllddmdldmmmmhhlhddmmmlhh ",
|
|
67
|
+
"hhhhhhhhmmmlm llllllllllllllllllmlldddmmmll ",
|
|
68
|
+
"hhmmmmlhhhhmmmdllllllllllllllllllllllllmddmmmll ",
|
|
69
|
+
"hhmmmddlhhhlmlllllllllllllllllllhlllllllllmmlld ",
|
|
70
|
+
" llmmmdddlmllllllllllllllllllhbhhbhhhhhllllllm ",
|
|
71
|
+
" dllmmmddllllllhhhhhlblllllhhhhmmmmmmhhhhlllmm ",
|
|
72
|
+
" dllmmmlllllhhhhhhhhhhllllhhmmmmmmmmmddddhdlllm ",
|
|
73
|
+
" lllllllhhhhmmmmmmmhllllldmdlllbhmmmmddddlhhhlldd ",
|
|
74
|
+
" mdlllhhlmmdhmmmddmmdmmddmmmmdldddddddddmmmhhhl ",
|
|
75
|
+
" lllhmddmlmhhmmmmmddmmmddddddddddddddddmmdmmmhhl ",
|
|
76
|
+
" mlldldddmlllddddddddlllldmddddddddddddmmmddmlll ",
|
|
77
|
+
" llhhmddddmmdddddddddhhmmmdbhdldddddddddmmddmlll ",
|
|
78
|
+
" llhhmmmdddddddddddddhhddddmhhhhhhhhhmmdddddlml ",
|
|
79
|
+
" hhhmmmmmddddddddldhhhhhhlhhhhmhhhhhhhlmmmmmm ",
|
|
80
|
+
" llllmddmddddddddhhhhhhhhhhlhhhhhhhlllmmmm ",
|
|
81
|
+
" hllllmddddddmhhhhhhhhhhhhhllllllmmmh ",
|
|
82
|
+
" dmmmmmmmmlllllllllllllmdmmm ",
|
|
83
|
+
" mmmmmmmmmmmmmmmlllmm ",
|
|
84
|
+
" dlmmmmllllmmlmmllllllm dmllllmmmmmmmm ",
|
|
85
|
+
" lllllmmlllllllllllllmmm lmllllllllhlmmmmm ",
|
|
86
|
+
" mlllllmdmlllllllllmmmd mddmmmmlhhhlllmmmmm ",
|
|
87
|
+
" hmmmmmmdmdmmmmmmmmmmm dddmmmmmmmmlllllmmdmm",
|
|
88
|
+
" mmmlllllhllllmmmmmmmm dmmllllmmmmmmmlllmdm ",
|
|
89
|
+
" mlllhhhhhhhhlllllllmmdddmlllhllmmmmmmlmml ",
|
|
90
|
+
" llllllhhhhhhhllllllllmmdddmmlllllmmmmdmmd ",
|
|
91
|
+
" mllllllllhhllllllllllmmmddmmmlllllmdddmm ",
|
|
92
|
+
" lmllmlllllllllllllllmmmmmddmmmllllmdddd ",
|
|
93
|
+
" lmmmmmmllllmllllllmmmdmdddddmmmmmddmd ",
|
|
94
|
+
" dmmmmmmd dmmmmmmmmmmmmddddmmmmmdd ",
|
|
95
|
+
" dmmmmmd dmmmmmmd h ",
|
|
96
|
+
" mmmmmmmm dmmmmmmm ",
|
|
97
|
+
" dmmmmmm ",
|
|
98
|
+
] as const;
|
|
52
99
|
|
|
53
|
-
|
|
100
|
+
const HEADER_CLASSIC = [
|
|
54
101
|
"░█████╗░░██████╗██████╗░██╗░░░██╗░░░░░░██████╗░██╗",
|
|
55
102
|
"██╔══██╗██╔════╝██╔══██╗╚██╗░██╔╝░░░░░░██╔══██╗ ║",
|
|
56
103
|
"██║░░██║╚█████╗░██║░░██║░╚████╔╝░█████╗██████╔╝██║",
|
|
@@ -64,11 +111,227 @@ export const HEADER = [
|
|
|
64
111
|
" ╱╱╱╱╱╱╱╰╯ </>",
|
|
65
112
|
] as const;
|
|
66
113
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
114
|
+
const HEADER_SIMPLE = [
|
|
115
|
+
" ███████ █████ ███████████ ███ ",
|
|
116
|
+
" ███░░░░░███ ░░███ ░░███░░░░░███ ░░░ ",
|
|
117
|
+
" ███ ░░███ █████ ███████ █████ ████ ░███ ░███ ████ ",
|
|
118
|
+
"░███ ░███ ███░░ ███░░███ ░░███ ░███ ██████████ ░██████████ ░░███ ",
|
|
119
|
+
"░███ ░███░░█████ ░███ ░███ ░███ ░███ ░░░░░░░░░░ ░███░░░░░░ ░███ ",
|
|
120
|
+
"░░███ ███ ░░░░███░███ ░███ ░███ ░███ ░███ ░███ ",
|
|
121
|
+
" ░░░███████░ ██████ ░░████████ ░░███████ █████ █████",
|
|
122
|
+
" ░░░░░░░ ░░░░░░ ░░░░░░░░ ░░░░░███ ░░░░░ ░░░░░ ",
|
|
123
|
+
" ███ ░███",
|
|
124
|
+
" ░░██████",
|
|
125
|
+
" ░░░░░░ </>",
|
|
126
|
+
] as const;
|
|
127
|
+
|
|
128
|
+
type HeaderPalette = {
|
|
129
|
+
baseColor: string;
|
|
130
|
+
highlightColor: string;
|
|
131
|
+
trailColor: string;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export type MascotToneKey = "b" | "h" | "l" | "m" | "d" | "p" | "c" | "v";
|
|
135
|
+
|
|
136
|
+
export type MascotTonePalette = Record<MascotToneKey, string>;
|
|
137
|
+
|
|
138
|
+
type HeaderVariantConfig = {
|
|
139
|
+
label: string;
|
|
140
|
+
header: readonly string[];
|
|
141
|
+
headerMap?: readonly string[];
|
|
142
|
+
headerTonePalette?: MascotTonePalette;
|
|
143
|
+
minRowsForFull?: number;
|
|
144
|
+
fallbackHeader?: readonly string[];
|
|
145
|
+
fallbackLinePalette?: (lineIndex: number) => HeaderPalette;
|
|
146
|
+
mascot?: readonly string[];
|
|
147
|
+
mascotMap?: readonly string[];
|
|
148
|
+
linePalette: (lineIndex: number) => HeaderPalette;
|
|
149
|
+
mascotPalette: HeaderPalette;
|
|
150
|
+
mascotTonePalette?: MascotTonePalette;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const CLASSIC_PALETTE: HeaderPalette = {
|
|
154
|
+
baseColor: "accent",
|
|
155
|
+
highlightColor: "mdHeading",
|
|
156
|
+
trailColor: "mdLink",
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const CLASSIC_LINK_PALETTE: HeaderPalette = {
|
|
160
|
+
baseColor: "mdLink",
|
|
161
|
+
highlightColor: "mdHeading",
|
|
162
|
+
trailColor: "mdLink",
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const OSDY_THEME_PINK_PALETTE: HeaderPalette = {
|
|
166
|
+
baseColor: "accent",
|
|
167
|
+
highlightColor: "mdHeading",
|
|
168
|
+
trailColor: "mdLink",
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const OSDY_THEME_CYAN_PALETTE: HeaderPalette = {
|
|
172
|
+
baseColor: "mdLink",
|
|
173
|
+
highlightColor: "accent",
|
|
174
|
+
trailColor: "mdHeading",
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const OSDY_THEME_PURPLE_PALETTE: HeaderPalette = {
|
|
178
|
+
baseColor: "mdHeading",
|
|
179
|
+
highlightColor: "mdLink",
|
|
180
|
+
trailColor: "accent",
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const OSDY_THEME_MASCOT_PALETTE: HeaderPalette = {
|
|
184
|
+
baseColor: "mdLink",
|
|
185
|
+
highlightColor: "accent",
|
|
186
|
+
trailColor: "mdHeading",
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const HTML_MASCOT_TONES: MascotTonePalette = {
|
|
190
|
+
b: "mascotBg",
|
|
191
|
+
h: "mascotBright",
|
|
192
|
+
l: "mascotLight",
|
|
193
|
+
m: "mascotMid",
|
|
194
|
+
d: "mascotDark",
|
|
195
|
+
p: "htmlPink",
|
|
196
|
+
c: "mdLink",
|
|
197
|
+
v: "mdHeading",
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
type MascotArt = {
|
|
201
|
+
mascot: readonly string[];
|
|
202
|
+
toneMap: readonly string[];
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
function sampleIndex(
|
|
206
|
+
outputIndex: number,
|
|
207
|
+
outputCount: number,
|
|
208
|
+
inputCount: number,
|
|
209
|
+
): number {
|
|
210
|
+
if (outputCount <= 1) return 0;
|
|
211
|
+
return Math.min(
|
|
212
|
+
inputCount - 1,
|
|
213
|
+
Math.round((outputIndex * (inputCount - 1)) / (outputCount - 1)),
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function sampleLine(
|
|
218
|
+
line: string,
|
|
219
|
+
outputWidth: number,
|
|
220
|
+
inputWidth: number,
|
|
221
|
+
): string {
|
|
222
|
+
const chars = Array.from(line.padEnd(inputWidth, " "));
|
|
223
|
+
return Array.from({ length: outputWidth }, (_value, outputIndex) => {
|
|
224
|
+
const inputIndex = sampleIndex(outputIndex, outputWidth, inputWidth);
|
|
225
|
+
return chars[inputIndex] ?? " ";
|
|
226
|
+
}).join("");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function scaleMascotArt(
|
|
230
|
+
mascot: readonly string[],
|
|
231
|
+
toneMap: readonly string[],
|
|
232
|
+
scale: number,
|
|
233
|
+
): MascotArt {
|
|
234
|
+
const inputRows = Math.min(mascot.length, toneMap.length);
|
|
235
|
+
const inputWidth = Math.max(
|
|
236
|
+
...mascot.slice(0, inputRows).map((line) => Array.from(line).length),
|
|
237
|
+
...toneMap.slice(0, inputRows).map((line) => Array.from(line).length),
|
|
238
|
+
);
|
|
239
|
+
const outputRows = Math.max(1, Math.round(inputRows * scale));
|
|
240
|
+
const outputWidth = Math.max(1, Math.round(inputWidth * scale));
|
|
241
|
+
|
|
242
|
+
return Array.from({ length: outputRows }, (_value, outputIndex) => {
|
|
243
|
+
const inputIndex = sampleIndex(outputIndex, outputRows, inputRows);
|
|
244
|
+
return {
|
|
245
|
+
mascot: sampleLine(mascot[inputIndex] ?? "", outputWidth, inputWidth),
|
|
246
|
+
toneMap: sampleLine(toneMap[inputIndex] ?? "", outputWidth, inputWidth),
|
|
247
|
+
};
|
|
248
|
+
}).reduce<MascotArt>(
|
|
249
|
+
(accumulator, line) => ({
|
|
250
|
+
mascot: [...accumulator.mascot, line.mascot],
|
|
251
|
+
toneMap: [...accumulator.toneMap, line.toneMap],
|
|
252
|
+
}),
|
|
253
|
+
{ mascot: [], toneMap: [] },
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function addRightEdgeGlow(
|
|
258
|
+
mascot: readonly string[],
|
|
259
|
+
toneMap: readonly string[],
|
|
260
|
+
): readonly string[] {
|
|
261
|
+
return toneMap.map((lineMap, lineIndex) => {
|
|
262
|
+
const chars = Array.from(lineMap);
|
|
263
|
+
const mascotLine = mascot[lineIndex] ?? "";
|
|
264
|
+
const rightEdgeIndex = Math.max(
|
|
265
|
+
...Array.from(mascotLine).map((char, index) =>
|
|
266
|
+
char === " " ? -1 : index,
|
|
267
|
+
),
|
|
268
|
+
);
|
|
269
|
+
if (rightEdgeIndex < 0) return lineMap;
|
|
270
|
+
const glowTones = ["p", "c", "v"] as const;
|
|
271
|
+
for (let offset = 0; offset < glowTones.length; offset += 1) {
|
|
272
|
+
const glowTone = glowTones[offset];
|
|
273
|
+
const index = rightEdgeIndex - offset;
|
|
274
|
+
if (
|
|
275
|
+
glowTone &&
|
|
276
|
+
index >= 0 &&
|
|
277
|
+
index < chars.length &&
|
|
278
|
+
chars[index] !== " "
|
|
279
|
+
) {
|
|
280
|
+
chars[index] = glowTone;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return chars.join("");
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const OSDY_THEME_MASCOT_ART = scaleMascotArt(HTML_MASCOT, HTML_MASCOT_MAP, 0.9);
|
|
288
|
+
const OSDY_THEME_MASCOT_MAP = addRightEdgeGlow(
|
|
289
|
+
OSDY_THEME_MASCOT_ART.mascot,
|
|
290
|
+
OSDY_THEME_MASCOT_ART.toneMap,
|
|
70
291
|
);
|
|
71
292
|
|
|
293
|
+
function osdyThemePalette(lineIndex: number): HeaderPalette {
|
|
294
|
+
if (lineIndex < 4) return OSDY_THEME_PINK_PALETTE;
|
|
295
|
+
if (lineIndex < 8) return OSDY_THEME_CYAN_PALETTE;
|
|
296
|
+
return OSDY_THEME_PURPLE_PALETTE;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export const HEADER_VARIANTS: Record<HeaderVariant, HeaderVariantConfig> = {
|
|
300
|
+
"osdy-theme": {
|
|
301
|
+
label: "OsdyTheme",
|
|
302
|
+
header: HEADER_SIMPLE,
|
|
303
|
+
mascot: OSDY_THEME_MASCOT_ART.mascot,
|
|
304
|
+
mascotMap: OSDY_THEME_MASCOT_MAP,
|
|
305
|
+
linePalette: osdyThemePalette,
|
|
306
|
+
mascotPalette: OSDY_THEME_MASCOT_PALETTE,
|
|
307
|
+
mascotTonePalette: HTML_MASCOT_TONES,
|
|
308
|
+
},
|
|
309
|
+
classic: {
|
|
310
|
+
label: "Classic",
|
|
311
|
+
header: HEADER_CLASSIC,
|
|
312
|
+
mascot: HTML_MASCOT,
|
|
313
|
+
mascotMap: HTML_MASCOT_MAP,
|
|
314
|
+
linePalette: (lineIndex) =>
|
|
315
|
+
lineIndex >= 6 ? CLASSIC_LINK_PALETTE : CLASSIC_PALETTE,
|
|
316
|
+
mascotPalette: OSDY_THEME_MASCOT_PALETTE,
|
|
317
|
+
mascotTonePalette: HTML_MASCOT_TONES,
|
|
318
|
+
},
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
export function headerWidth(variant: HeaderVariant): number {
|
|
322
|
+
return HEADER_VARIANTS[variant].header.reduce(
|
|
323
|
+
(maxWidth, line) => Math.max(maxWidth, visibleWidth(line)),
|
|
324
|
+
0,
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export function mascotWidth(variant: HeaderVariant): number {
|
|
329
|
+
return (HEADER_VARIANTS[variant].mascot ?? []).reduce(
|
|
330
|
+
(maxWidth, line) => Math.max(maxWidth, visibleWidth(line)),
|
|
331
|
+
0,
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
72
335
|
export const HEADER_FALLBACK = [
|
|
73
336
|
"OSDY - PI",
|
|
74
337
|
"</> Compilador de ideas",
|
|
@@ -95,7 +95,7 @@ export function disableOsdyPi(ctx: ExtensionContext, state: OsdyState): void {
|
|
|
95
95
|
|
|
96
96
|
export function notifyStatus(ctx: ExtensionContext, state: OsdyState): void {
|
|
97
97
|
ctx.ui.notify(
|
|
98
|
-
`osdy-pi ${state.enabled ? "enabled" : "disabled"} · theme ${ctx.ui.theme.name ?? "unknown"} · animation ${asciiAnimationMode()} · ${modelLabel(ctx)} · ${usageLabel(ctx).trim()}`,
|
|
98
|
+
`osdy-pi ${state.enabled ? "enabled" : "disabled"} · theme ${ctx.ui.theme.name ?? "unknown"} · style ${state.headerVariant} · animation ${asciiAnimationMode()} · ${modelLabel(ctx)} · ${usageLabel(ctx).trim()}`,
|
|
99
99
|
"info",
|
|
100
100
|
);
|
|
101
101
|
}
|
|
@@ -3,7 +3,7 @@ import type {
|
|
|
3
3
|
ExtensionContext,
|
|
4
4
|
} from "@earendil-works/pi-coding-agent";
|
|
5
5
|
import { applyOsdyPi, disableOsdyPi, notifyStatus } from "./runtime-helpers.js";
|
|
6
|
-
import type { OsdyState, WorkingWidgetState } from "./types.js";
|
|
6
|
+
import type { HeaderVariant, OsdyState, WorkingWidgetState } from "./types.js";
|
|
7
7
|
import {
|
|
8
8
|
createWorkingController,
|
|
9
9
|
type WorkingController,
|
|
@@ -61,8 +61,14 @@ function loadSessionMetadata(
|
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
function
|
|
65
|
-
return args.trim().split(/\s
|
|
64
|
+
function parseCommandArgs(args: string): string[] {
|
|
65
|
+
return args.trim().split(/\s+/).filter(Boolean);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const HEADER_VARIANTS = ["osdy-theme", "classic"] as const;
|
|
69
|
+
|
|
70
|
+
function isHeaderVariant(value: string): value is HeaderVariant {
|
|
71
|
+
return HEADER_VARIANTS.includes(value as HeaderVariant);
|
|
66
72
|
}
|
|
67
73
|
|
|
68
74
|
function enableOsdyPi(
|
|
@@ -87,6 +93,18 @@ function disableOsdyPiCommand(
|
|
|
87
93
|
disableOsdyPi(ctx, state);
|
|
88
94
|
}
|
|
89
95
|
|
|
96
|
+
function setHeaderVariant(
|
|
97
|
+
pi: ExtensionAPI,
|
|
98
|
+
ctx: ExtensionContext,
|
|
99
|
+
state: OsdyState,
|
|
100
|
+
workingState: WorkingWidgetState,
|
|
101
|
+
variant: HeaderVariant,
|
|
102
|
+
): void {
|
|
103
|
+
state.headerVariant = variant;
|
|
104
|
+
if (state.enabled) applyOsdyPi(pi, ctx, state, workingState);
|
|
105
|
+
ctx.ui.notify(`osdy-pi style: ${variant}`, "info");
|
|
106
|
+
}
|
|
107
|
+
|
|
90
108
|
function registerCommand(
|
|
91
109
|
pi: ExtensionAPI,
|
|
92
110
|
state: OsdyState,
|
|
@@ -94,14 +112,21 @@ function registerCommand(
|
|
|
94
112
|
controller: WorkingController,
|
|
95
113
|
): void {
|
|
96
114
|
pi.registerCommand("osdy-pi", {
|
|
97
|
-
description:
|
|
115
|
+
description:
|
|
116
|
+
"Manage the Osdy Pi experience: enable, disable, status, or style.",
|
|
98
117
|
getArgumentCompletions(prefix: string) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
118
|
+
const trimmed = prefix.trim();
|
|
119
|
+
const parts = parseCommandArgs(trimmed);
|
|
120
|
+
if (parts.length <= 1) {
|
|
121
|
+
const valuePrefix = parts[0] ?? "";
|
|
122
|
+
return ["enable", "disable", "status", ...HEADER_VARIANTS]
|
|
123
|
+
.filter((value) => value.startsWith(valuePrefix))
|
|
124
|
+
.map((value) => ({ value, label: value }));
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
102
127
|
},
|
|
103
128
|
handler: (args, ctx) => {
|
|
104
|
-
const action =
|
|
129
|
+
const [action = "status"] = parseCommandArgs(args);
|
|
105
130
|
if (action === "enable") {
|
|
106
131
|
enableOsdyPi(pi, ctx, state, workingState, controller);
|
|
107
132
|
return Promise.resolve();
|
|
@@ -114,14 +139,36 @@ function registerCommand(
|
|
|
114
139
|
notifyStatus(ctx, state);
|
|
115
140
|
return Promise.resolve();
|
|
116
141
|
}
|
|
117
|
-
|
|
142
|
+
if (isHeaderVariant(action)) {
|
|
143
|
+
setHeaderVariant(pi, ctx, state, workingState, action);
|
|
144
|
+
return Promise.resolve();
|
|
145
|
+
}
|
|
146
|
+
ctx.ui.notify(
|
|
147
|
+
"Usage: /osdy-pi enable | disable | status | osdy-theme | classic",
|
|
148
|
+
"warning",
|
|
149
|
+
);
|
|
118
150
|
return Promise.resolve();
|
|
119
151
|
},
|
|
120
152
|
});
|
|
153
|
+
|
|
154
|
+
for (const variant of HEADER_VARIANTS) {
|
|
155
|
+
pi.registerCommand(`osdy-pi-${variant}`, {
|
|
156
|
+
description: `Switch Osdy Pi header to ${variant}.`,
|
|
157
|
+
handler: (_args, ctx) => {
|
|
158
|
+
setHeaderVariant(pi, ctx, state, workingState, variant);
|
|
159
|
+
return Promise.resolve();
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
}
|
|
121
163
|
}
|
|
122
164
|
|
|
123
165
|
export function registerOsdyPi(pi: ExtensionAPI): void {
|
|
124
|
-
const state: OsdyState = {
|
|
166
|
+
const state: OsdyState = {
|
|
167
|
+
enabled: true,
|
|
168
|
+
headerVariant: "osdy-theme",
|
|
169
|
+
gitLabel: "-",
|
|
170
|
+
agentsLabel: "-",
|
|
171
|
+
};
|
|
125
172
|
const workingState: WorkingWidgetState = {
|
|
126
173
|
active: false,
|
|
127
174
|
label: "Working...",
|
|
@@ -2,8 +2,11 @@ import type { TUI } from "@earendil-works/pi-tui";
|
|
|
2
2
|
|
|
3
3
|
export type AnimationMode = "off" | "intro" | "continuous";
|
|
4
4
|
|
|
5
|
+
export type HeaderVariant = "osdy-theme" | "classic";
|
|
6
|
+
|
|
5
7
|
export type OsdyState = {
|
|
6
8
|
enabled: boolean;
|
|
9
|
+
headerVariant: HeaderVariant;
|
|
7
10
|
previousThemeName?: string;
|
|
8
11
|
gitLabel: string;
|
|
9
12
|
agentsLabel: string;
|
package/extensions/osdy-pi/ui.ts
CHANGED
|
@@ -12,18 +12,21 @@ import {
|
|
|
12
12
|
truncateToWidth,
|
|
13
13
|
visibleWidth,
|
|
14
14
|
} from "@earendil-works/pi-tui";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
animateAsciiLine,
|
|
17
|
+
animateAsciiLineWithToneMap,
|
|
18
|
+
asciiAnimationMode,
|
|
19
|
+
} from "./animation.js";
|
|
16
20
|
import { fitBorder } from "./border.js";
|
|
17
21
|
import {
|
|
18
22
|
ANIMATION_INTERVAL_MS,
|
|
19
|
-
|
|
23
|
+
headerWidth,
|
|
20
24
|
HEADER_FALLBACK,
|
|
21
|
-
|
|
25
|
+
HEADER_VARIANTS,
|
|
22
26
|
INTRO_ANIMATION_FRAMES,
|
|
23
|
-
MASCOT,
|
|
24
27
|
MASCOT_GAP,
|
|
25
28
|
MASCOT_MIN_ROWS,
|
|
26
|
-
|
|
29
|
+
mascotWidth,
|
|
27
30
|
WORKING_SPINNER_FRAMES,
|
|
28
31
|
} from "./constants.js";
|
|
29
32
|
import { formatPath } from "./format.js";
|
|
@@ -130,39 +133,85 @@ export function createHeaderComponent(
|
|
|
130
133
|
render(width: number): string[] {
|
|
131
134
|
const animationStyle =
|
|
132
135
|
animateAscii && !animationComplete ? "animated" : "static";
|
|
136
|
+
const variant = HEADER_VARIANTS[state.headerVariant];
|
|
137
|
+
const fullHeaderWidth = headerWidth(state.headerVariant);
|
|
138
|
+
const canUseFullHeader =
|
|
139
|
+
width >= fullHeaderWidth &&
|
|
140
|
+
(variant.minRowsForFull === undefined ||
|
|
141
|
+
_tui.terminal.rows >= variant.minRowsForFull);
|
|
142
|
+
const mascotLinesSource = variant.mascot ?? [];
|
|
143
|
+
const mascotToneMap = variant.mascotMap ?? [];
|
|
144
|
+
const fullMascotWidth = mascotWidth(state.headerVariant);
|
|
133
145
|
const showMascot =
|
|
146
|
+
canUseFullHeader &&
|
|
147
|
+
mascotLinesSource.length > 0 &&
|
|
134
148
|
_tui.terminal.rows >= MASCOT_MIN_ROWS &&
|
|
135
|
-
width >=
|
|
136
|
-
const
|
|
137
|
-
|
|
149
|
+
width >= fullMascotWidth + MASCOT_GAP + fullHeaderWidth;
|
|
150
|
+
const headerLines = canUseFullHeader
|
|
151
|
+
? [...variant.header]
|
|
152
|
+
: [...(variant.fallbackHeader ?? HEADER_FALLBACK)];
|
|
153
|
+
const headerToneMap = canUseFullHeader ? (variant.headerMap ?? []) : [];
|
|
138
154
|
const metadataRows = renderHeaderMetadata(pi, ctx, state, width);
|
|
139
155
|
const logoLines = headerLines.map((line, index) => {
|
|
140
|
-
const
|
|
156
|
+
const toneLine = headerToneMap[index];
|
|
157
|
+
if (toneLine && variant.headerTonePalette) {
|
|
158
|
+
return animateAsciiLineWithToneMap(
|
|
159
|
+
line,
|
|
160
|
+
toneLine,
|
|
161
|
+
index,
|
|
162
|
+
frame,
|
|
163
|
+
theme,
|
|
164
|
+
variant.headerTonePalette,
|
|
165
|
+
animationStyle,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
const palette = canUseFullHeader
|
|
169
|
+
? variant.linePalette(index)
|
|
170
|
+
: (variant.fallbackLinePalette?.(index) ??
|
|
171
|
+
variant.linePalette(index));
|
|
141
172
|
return animateAsciiLine(
|
|
142
173
|
line,
|
|
143
174
|
index,
|
|
144
175
|
frame,
|
|
145
176
|
theme,
|
|
146
|
-
baseColor,
|
|
147
|
-
|
|
148
|
-
|
|
177
|
+
palette.baseColor,
|
|
178
|
+
palette.highlightColor,
|
|
179
|
+
palette.trailColor,
|
|
149
180
|
animationStyle,
|
|
150
181
|
);
|
|
151
182
|
});
|
|
152
|
-
const mascotLines =
|
|
153
|
-
|
|
183
|
+
const mascotLines = mascotLinesSource.map((line, index) => {
|
|
184
|
+
const toneLine = mascotToneMap[index];
|
|
185
|
+
if (toneLine && variant.mascotTonePalette) {
|
|
186
|
+
return animateAsciiLineWithToneMap(
|
|
187
|
+
line,
|
|
188
|
+
toneLine,
|
|
189
|
+
index,
|
|
190
|
+
frame,
|
|
191
|
+
theme,
|
|
192
|
+
variant.mascotTonePalette,
|
|
193
|
+
animationStyle,
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
return animateAsciiLine(
|
|
154
197
|
line,
|
|
155
198
|
index,
|
|
156
199
|
frame,
|
|
157
200
|
theme,
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
201
|
+
variant.mascotPalette.baseColor,
|
|
202
|
+
variant.mascotPalette.highlightColor,
|
|
203
|
+
variant.mascotPalette.trailColor,
|
|
161
204
|
animationStyle,
|
|
162
|
-
)
|
|
163
|
-
);
|
|
205
|
+
);
|
|
206
|
+
});
|
|
164
207
|
const headerBlock = showMascot
|
|
165
|
-
? composeSideBySide(
|
|
208
|
+
? composeSideBySide(
|
|
209
|
+
mascotLines,
|
|
210
|
+
fullMascotWidth,
|
|
211
|
+
logoLines,
|
|
212
|
+
width,
|
|
213
|
+
fullHeaderWidth,
|
|
214
|
+
)
|
|
166
215
|
: logoLines.map((line) => fitCenterVisible(line, width));
|
|
167
216
|
return [
|
|
168
217
|
"",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TUI } from "@earendil-works/pi-tui";
|
|
2
2
|
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
3
|
-
import {
|
|
3
|
+
import { MASCOT_GAP } from "./constants.js";
|
|
4
4
|
|
|
5
5
|
export function sanitizeStatusText(text: string): string {
|
|
6
6
|
return text
|
|
@@ -26,27 +26,27 @@ export function padVisibleRight(line: string, width: number): string {
|
|
|
26
26
|
return `${line}${" ".repeat(Math.max(0, width - visibleWidth(line)))}`;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
function getCombinedHeaderWidth(): number {
|
|
30
|
-
return MASCOT_WIDTH + MASCOT_GAP + HEADER_WIDTH;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
29
|
export function composeSideBySide(
|
|
34
30
|
leftLines: string[],
|
|
31
|
+
leftWidth: number,
|
|
35
32
|
rightLines: string[],
|
|
36
33
|
width: number,
|
|
34
|
+
rightWidth: number,
|
|
37
35
|
): string[] {
|
|
38
|
-
const combinedWidth =
|
|
36
|
+
const combinedWidth = leftWidth + MASCOT_GAP + rightWidth;
|
|
39
37
|
if (width < combinedWidth) return rightLines;
|
|
40
38
|
const leftPad = " ".repeat(
|
|
41
39
|
Math.max(0, Math.floor((width - combinedWidth) / 2)),
|
|
42
40
|
);
|
|
43
41
|
const rows = Math.max(leftLines.length, rightLines.length);
|
|
44
42
|
const topOffset = Math.max(0, Math.floor((rows - rightLines.length) / 2));
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
const composedRows: string[] = [];
|
|
44
|
+
for (let index = 0; index < rows; index += 1) {
|
|
45
|
+
const left = padVisibleRight(leftLines[index] ?? "", leftWidth);
|
|
47
46
|
const right = rightLines[index - topOffset] ?? "";
|
|
48
|
-
|
|
49
|
-
}
|
|
47
|
+
composedRows.push(`${leftPad}${left}${" ".repeat(MASCOT_GAP)}${right}`);
|
|
48
|
+
}
|
|
49
|
+
return composedRows;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
export function internalLineTarget(tui: TUI): number {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "osdy-pi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Osdy Pi package: themes, header, and custom editor for Pi.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"pi": {
|
|
25
25
|
"themes": [
|
|
26
26
|
"./themes/osdy-pi-dark.json",
|
|
27
|
-
"./themes/osdy-pi-light.json"
|
|
27
|
+
"./themes/osdy-pi-light.json",
|
|
28
|
+
"./themes/osdy-pi-simple.json"
|
|
28
29
|
],
|
|
29
30
|
"extensions": [
|
|
30
31
|
"./extensions/osdy-pi.ts"
|
package/themes/osdy-pi-dark.json
CHANGED
|
@@ -62,6 +62,12 @@
|
|
|
62
62
|
"syntaxType": "violet",
|
|
63
63
|
"syntaxOperator": "hotPink",
|
|
64
64
|
"syntaxPunctuation": "lavenderGray",
|
|
65
|
+
"mascotBg": "#F9F7F2",
|
|
66
|
+
"mascotBright": "#F0E5D7",
|
|
67
|
+
"mascotLight": "#C7B4A1",
|
|
68
|
+
"mascotMid": "#7D6F67",
|
|
69
|
+
"mascotDark": "#2A2321",
|
|
70
|
+
"htmlPink": "#FF2E8C",
|
|
65
71
|
"thinkingOff": "#3A2852",
|
|
66
72
|
"thinkingMinimal": "lavenderGray",
|
|
67
73
|
"thinkingLow": "purple",
|
|
@@ -62,6 +62,12 @@
|
|
|
62
62
|
"syntaxType": "violet",
|
|
63
63
|
"syntaxOperator": "hotPink",
|
|
64
64
|
"syntaxPunctuation": "lavenderGray",
|
|
65
|
+
"mascotBg": "#8F7E73",
|
|
66
|
+
"mascotBright": "#E8DACB",
|
|
67
|
+
"mascotLight": "#B79F8E",
|
|
68
|
+
"mascotMid": "#74665F",
|
|
69
|
+
"mascotDark": "#2E2725",
|
|
70
|
+
"htmlPink": "#FF2E8C",
|
|
65
71
|
"thinkingOff": "dimPurple",
|
|
66
72
|
"thinkingMinimal": "lavenderGray",
|
|
67
73
|
"thinkingLow": "purple",
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/earendil-works/pi-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
|
3
|
+
"name": "osdy-pi-simple",
|
|
4
|
+
"vars": {
|
|
5
|
+
"slate900": "#0B1220",
|
|
6
|
+
"slate800": "#111827",
|
|
7
|
+
"slate700": "#1F2937",
|
|
8
|
+
"slate600": "#475569",
|
|
9
|
+
"steel": "#94A3B8",
|
|
10
|
+
"mist": "#CBD5E1",
|
|
11
|
+
"ice": "#E2E8F0",
|
|
12
|
+
"deepBlue": "#0A66FF",
|
|
13
|
+
"royalBlue": "#2563EB",
|
|
14
|
+
"cyanBlue": "#38BDF8",
|
|
15
|
+
"ferrari": "#FF2800",
|
|
16
|
+
"ember": "#FF5A36",
|
|
17
|
+
"roseRed": "#E11D48"
|
|
18
|
+
},
|
|
19
|
+
"colors": {
|
|
20
|
+
"accent": "ferrari",
|
|
21
|
+
"border": "royalBlue",
|
|
22
|
+
"borderAccent": "deepBlue",
|
|
23
|
+
"borderMuted": "slate600",
|
|
24
|
+
"success": "cyanBlue",
|
|
25
|
+
"error": "ember",
|
|
26
|
+
"warning": "ferrari",
|
|
27
|
+
"muted": "steel",
|
|
28
|
+
"dim": "slate600",
|
|
29
|
+
"text": "ice",
|
|
30
|
+
"thinkingText": "steel",
|
|
31
|
+
"selectedBg": "slate700",
|
|
32
|
+
"userMessageBg": "slate800",
|
|
33
|
+
"userMessageText": "ice",
|
|
34
|
+
"customMessageBg": "slate700",
|
|
35
|
+
"customMessageText": "ice",
|
|
36
|
+
"customMessageLabel": "deepBlue",
|
|
37
|
+
"toolPendingBg": "slate800",
|
|
38
|
+
"toolSuccessBg": "#10263A",
|
|
39
|
+
"toolErrorBg": "#3B1417",
|
|
40
|
+
"toolTitle": "deepBlue",
|
|
41
|
+
"toolOutput": "ice",
|
|
42
|
+
"mdHeading": "royalBlue",
|
|
43
|
+
"mdLink": "cyanBlue",
|
|
44
|
+
"mdLinkUrl": "mist",
|
|
45
|
+
"mdCode": "deepBlue",
|
|
46
|
+
"mdCodeBlock": "ice",
|
|
47
|
+
"mdCodeBlockBorder": "royalBlue",
|
|
48
|
+
"mdQuote": "steel",
|
|
49
|
+
"mdQuoteBorder": "slate600",
|
|
50
|
+
"mdHr": "slate600",
|
|
51
|
+
"mdListBullet": "ferrari",
|
|
52
|
+
"toolDiffAdded": "cyanBlue",
|
|
53
|
+
"toolDiffRemoved": "ember",
|
|
54
|
+
"toolDiffContext": "steel",
|
|
55
|
+
"syntaxComment": "slate600",
|
|
56
|
+
"syntaxKeyword": "ferrari",
|
|
57
|
+
"syntaxFunction": "cyanBlue",
|
|
58
|
+
"syntaxVariable": "ice",
|
|
59
|
+
"syntaxString": "mist",
|
|
60
|
+
"syntaxNumber": "royalBlue",
|
|
61
|
+
"syntaxType": "royalBlue",
|
|
62
|
+
"syntaxOperator": "ember",
|
|
63
|
+
"syntaxPunctuation": "steel",
|
|
64
|
+
"mascotBg": "#F4EEE5",
|
|
65
|
+
"mascotBright": "#E6D8C8",
|
|
66
|
+
"mascotLight": "#BFA998",
|
|
67
|
+
"mascotMid": "#7A6B63",
|
|
68
|
+
"mascotDark": "#241F1D",
|
|
69
|
+
"htmlPink": "#FF2E8C",
|
|
70
|
+
"thinkingOff": "slate600",
|
|
71
|
+
"thinkingMinimal": "steel",
|
|
72
|
+
"thinkingLow": "royalBlue",
|
|
73
|
+
"thinkingMedium": "deepBlue",
|
|
74
|
+
"thinkingHigh": "cyanBlue",
|
|
75
|
+
"thinkingXhigh": "ember",
|
|
76
|
+
"bashMode": "royalBlue"
|
|
77
|
+
},
|
|
78
|
+
"export": {
|
|
79
|
+
"pageBg": "slate900",
|
|
80
|
+
"cardBg": "slate800",
|
|
81
|
+
"infoBg": "slate700"
|
|
82
|
+
}
|
|
83
|
+
}
|