@leo-alvarenga/pi-zen-frame 0.12.0 → 0.12.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/extensions/components/header.ts +64 -50
- package/extensions/config/constants/contracts.ts +12 -0
- package/extensions/config/constants/defaults.ts +47 -0
- package/extensions/config/constants/file.ts +2 -0
- package/extensions/config/constants/index.ts +10 -0
- package/extensions/config/constants/messages.ts +176 -0
- package/extensions/config/constants/visuals.ts +84 -0
- package/package.json +1 -1
- package/extensions/config/constants.ts +0 -279
|
@@ -32,6 +32,17 @@ export interface HeaderEnv {
|
|
|
32
32
|
const RANDOM_TIP =
|
|
33
33
|
HEADER_TIPS[Math.floor(Math.random() * HEADER_TIPS.length)]?.text ?? "";
|
|
34
34
|
|
|
35
|
+
function wrapLines(
|
|
36
|
+
lines: string[],
|
|
37
|
+
maxLen: number,
|
|
38
|
+
style?: (line: string) => string,
|
|
39
|
+
): string[] {
|
|
40
|
+
const wrapped = lines.map((l) => wrapTextWithAnsi(l, maxLen)).flat();
|
|
41
|
+
if (style) return wrapped.map((l) => (l.length ? style(l) : l));
|
|
42
|
+
|
|
43
|
+
return wrapped;
|
|
44
|
+
}
|
|
45
|
+
|
|
35
46
|
export function createHeader(
|
|
36
47
|
_tui: TUI,
|
|
37
48
|
theme: Theme,
|
|
@@ -57,29 +68,6 @@ export function createHeader(
|
|
|
57
68
|
color: settings.header?.logoColor ?? DEFAULT_SETTINGS.header?.logoColor,
|
|
58
69
|
};
|
|
59
70
|
|
|
60
|
-
const leftLines = [
|
|
61
|
-
...logo.lines.map((l) => theme.fg(logo.color, l)),
|
|
62
|
-
|
|
63
|
-
"",
|
|
64
|
-
"",
|
|
65
|
-
|
|
66
|
-
theme.bold(
|
|
67
|
-
theme.fg(
|
|
68
|
-
"muted",
|
|
69
|
-
settings.header?.heading ?? DEFAULT_SETTINGS.header?.heading,
|
|
70
|
-
),
|
|
71
|
-
),
|
|
72
|
-
|
|
73
|
-
"",
|
|
74
|
-
|
|
75
|
-
theme.italic(
|
|
76
|
-
theme.fg(
|
|
77
|
-
"muted",
|
|
78
|
-
settings.header?.subheading ?? DEFAULT_SETTINGS.header?.subheading,
|
|
79
|
-
),
|
|
80
|
-
),
|
|
81
|
-
];
|
|
82
|
-
|
|
83
71
|
const border = (s: string, fg?: ThemeColor) => theme.fg(fg ?? accentColor, s);
|
|
84
72
|
|
|
85
73
|
/** Space-pad `text` so it sits horizontally centered within `inner` cols. */
|
|
@@ -106,7 +94,7 @@ export function createHeader(
|
|
|
106
94
|
}
|
|
107
95
|
|
|
108
96
|
/** Right column halves: top = model(+provider), bottom = cwd + git. */
|
|
109
|
-
function infoRows(env: HeaderEnv): string[] {
|
|
97
|
+
function infoRows(env: HeaderEnv, width: number): string[] {
|
|
110
98
|
const icons = DEFAULT_ICONS;
|
|
111
99
|
const parts: string[] = [];
|
|
112
100
|
|
|
@@ -123,46 +111,74 @@ export function createHeader(
|
|
|
123
111
|
|
|
124
112
|
return [
|
|
125
113
|
theme.bold(border("Model Info")),
|
|
126
|
-
|
|
114
|
+
|
|
115
|
+
...wrapLines(
|
|
116
|
+
[
|
|
117
|
+
env.modelName
|
|
118
|
+
? theme.fg("muted", `${icons.model} ${env.modelName}`)
|
|
119
|
+
: "",
|
|
120
|
+
],
|
|
121
|
+
width,
|
|
122
|
+
(str) => theme.fg("muted", str),
|
|
123
|
+
),
|
|
124
|
+
|
|
127
125
|
"",
|
|
126
|
+
|
|
128
127
|
theme.bold(border("Current Directory")),
|
|
129
128
|
parts.length ? parts.join(" · ") : "",
|
|
129
|
+
|
|
130
130
|
"",
|
|
131
|
+
|
|
131
132
|
theme.bold(border("Tip")),
|
|
132
|
-
theme.fg("muted",
|
|
133
|
+
...wrapLines([RANDOM_TIP], width, (str) => theme.fg("muted", str)),
|
|
133
134
|
];
|
|
134
135
|
}
|
|
135
136
|
|
|
136
137
|
return {
|
|
137
138
|
render(width: number): string[] {
|
|
138
|
-
// Too narrow for a box → fall back to a plain centered logo.
|
|
139
|
-
if (width < MIN_BOX_WIDTH) {
|
|
140
|
-
return leftLines;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
139
|
const env = getEnv(pi);
|
|
144
|
-
const rightRows = infoRows(env);
|
|
145
140
|
|
|
146
141
|
const inner = Math.max(0, width - 2);
|
|
147
142
|
const leftW = Math.floor(inner * LEFT_COL_RATIO);
|
|
148
|
-
|
|
143
|
+
|
|
144
|
+
const rightW = inner - leftW - 1;
|
|
145
|
+
|
|
146
|
+
const rightLines = infoRows(env, rightW - 2);
|
|
147
|
+
const leftLines = [
|
|
148
|
+
...logo.lines.map((l) => theme.fg(logo.color, l)),
|
|
149
|
+
|
|
150
|
+
"",
|
|
151
|
+
"",
|
|
152
|
+
|
|
153
|
+
...wrapLines(
|
|
154
|
+
[settings.header?.heading ?? DEFAULT_SETTINGS.header?.heading ?? ""],
|
|
155
|
+
leftW - 2,
|
|
156
|
+
).map((line) => theme.bold(theme.fg("muted", line))),
|
|
157
|
+
|
|
158
|
+
"",
|
|
159
|
+
|
|
160
|
+
...wrapLines(
|
|
161
|
+
[
|
|
162
|
+
settings.header?.subheading ??
|
|
163
|
+
DEFAULT_SETTINGS.header?.subheading ??
|
|
164
|
+
"",
|
|
165
|
+
],
|
|
166
|
+
leftW - 2,
|
|
167
|
+
).map((line) => theme.italic(theme.fg("muted", line))),
|
|
168
|
+
];
|
|
169
|
+
|
|
170
|
+
// Too narrow for a box → fall back to a plain centered logo.
|
|
171
|
+
if (width < MIN_BOX_WIDTH) {
|
|
172
|
+
return leftLines;
|
|
173
|
+
}
|
|
149
174
|
|
|
150
175
|
// No truncation: overflow wraps onto following lines until it all fits.
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const rightWrapped = rightRows
|
|
155
|
-
.map((r) => wrapTextWithAnsi(r, Math.max(1, rightW - 2))) // 2-col indent
|
|
156
|
-
.flat();
|
|
157
|
-
|
|
158
|
-
const height = Math.max(leftWrapped.length, rightWrapped.length);
|
|
159
|
-
const logoTop = Math.max(
|
|
160
|
-
0,
|
|
161
|
-
Math.floor((height - leftWrapped.length) / 2),
|
|
162
|
-
);
|
|
176
|
+
const height = Math.max(leftLines.length, rightLines.length);
|
|
177
|
+
const logoTop = Math.max(0, Math.floor((height - leftLines.length) / 2));
|
|
178
|
+
|
|
163
179
|
const rightTop = Math.max(
|
|
164
180
|
0,
|
|
165
|
-
Math.floor((height -
|
|
181
|
+
Math.floor((height - rightLines.length) / 2),
|
|
166
182
|
);
|
|
167
183
|
|
|
168
184
|
const lines: string[] = [""];
|
|
@@ -172,12 +188,10 @@ export function createHeader(
|
|
|
172
188
|
|
|
173
189
|
for (let i = 0; i < height; i++) {
|
|
174
190
|
const l = i - logoTop;
|
|
175
|
-
const leftLine =
|
|
176
|
-
l >= 0 && l < leftWrapped.length ? leftWrapped[l]! : "";
|
|
191
|
+
const leftLine = l >= 0 && l < leftLines.length ? leftLines[l]! : "";
|
|
177
192
|
|
|
178
193
|
const r = i - rightTop;
|
|
179
|
-
const rightLine =
|
|
180
|
-
r >= 0 && r < rightWrapped.length ? rightWrapped[r]! : "";
|
|
194
|
+
const rightLine = r >= 0 && r < rightLines.length ? rightLines[r]! : "";
|
|
181
195
|
|
|
182
196
|
lines.push(splitRow(leftW, rightW, leftLine, rightLine));
|
|
183
197
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** External contract IDs: the zen-mode keybinding and the optional
|
|
2
|
+
* pi-agent-manager integration (no hard dependency).
|
|
3
|
+
*/
|
|
4
|
+
/** pi-agent-manager integration (optional — no hard dependency). */
|
|
5
|
+
export const PI_AGENT_MANAGER_AGENT_EVENT = "pi-agent-manager:agent-changed";
|
|
6
|
+
export const PI_AGENT_MANAGER_AGENT_DATA_KEY = "pi-agent-manager-agent";
|
|
7
|
+
|
|
8
|
+
/** Keybinding id users bind in keybindings.json to toggle zen mode. */
|
|
9
|
+
export const ZEN_MODE_SHORTCUT_ID = "piZenFrame.zenMode";
|
|
10
|
+
/** Default key when the user hasn't bound one (override or disable via
|
|
11
|
+
* keybindings.json; `[]` disables the shortcut, `/zen_mode` still works). */
|
|
12
|
+
export const ZEN_MODE_DEFAULT_KEY = "ctrl+shift+z";
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Settings } from "../types";
|
|
2
|
+
import { WORKING_MESSAGES } from "./messages";
|
|
3
|
+
export const DEFAULT_SETTINGS: Settings = {
|
|
4
|
+
zenMode: false,
|
|
5
|
+
accentColor: "accent",
|
|
6
|
+
|
|
7
|
+
header: {
|
|
8
|
+
enable: false,
|
|
9
|
+
logoColor: "text",
|
|
10
|
+
accentColor: "accent",
|
|
11
|
+
|
|
12
|
+
heading: "Welcome back!",
|
|
13
|
+
subheading:
|
|
14
|
+
"Ready for your next session? Terminal warm, context clean, tools ready to execute",
|
|
15
|
+
|
|
16
|
+
logo: ["█████████ ", "███ ███ ", "██████ ", "███ ███"],
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
workingMessage: {
|
|
20
|
+
enable: true,
|
|
21
|
+
intervalMs: 3000,
|
|
22
|
+
messages: WORKING_MESSAGES,
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
frame: {
|
|
26
|
+
icons: {},
|
|
27
|
+
paddingX: 1,
|
|
28
|
+
enable: true,
|
|
29
|
+
minWidth: 20,
|
|
30
|
+
marginTop: 0,
|
|
31
|
+
showCwd: true,
|
|
32
|
+
paddingTop: 1,
|
|
33
|
+
marginBottom: 0,
|
|
34
|
+
showModel: true,
|
|
35
|
+
paddingBottom: 1,
|
|
36
|
+
showSpinner: false,
|
|
37
|
+
showContext: true,
|
|
38
|
+
showThinking: true,
|
|
39
|
+
showAgentMode: true,
|
|
40
|
+
borderColor: "text",
|
|
41
|
+
|
|
42
|
+
colors: {},
|
|
43
|
+
// ponytail: colors were dormant (nothing read them); now wired — keep
|
|
44
|
+
// defaults unset so segments keep their natural colors and zen-mode is
|
|
45
|
+
// the mute switch.
|
|
46
|
+
},
|
|
47
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants, grouped by concern and re-exported from a single barrel.
|
|
3
|
+
* Import everything with `import { ... } from "../config/constants"` —
|
|
4
|
+
* resolution keeps working now that this is a directory.
|
|
5
|
+
*/
|
|
6
|
+
export * from "./file";
|
|
7
|
+
export * from "./contracts";
|
|
8
|
+
export * from "./visuals";
|
|
9
|
+
export * from "./messages";
|
|
10
|
+
export * from "./defaults";
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import type { BannerTip } from "../types";
|
|
2
|
+
export const WORKING_MESSAGES: string[] = [
|
|
3
|
+
"Exploring",
|
|
4
|
+
"Tinkering",
|
|
5
|
+
"Searching",
|
|
6
|
+
"Polishing",
|
|
7
|
+
"Herding",
|
|
8
|
+
"Consulting",
|
|
9
|
+
"Chasing",
|
|
10
|
+
"Rearranging",
|
|
11
|
+
"Sharpening",
|
|
12
|
+
"Reticulating",
|
|
13
|
+
"Warming",
|
|
14
|
+
"Feeding",
|
|
15
|
+
"Whispering",
|
|
16
|
+
"Counting",
|
|
17
|
+
"Dusting",
|
|
18
|
+
"Tightening",
|
|
19
|
+
"Watering",
|
|
20
|
+
"Aligning",
|
|
21
|
+
"Reading",
|
|
22
|
+
"Charging",
|
|
23
|
+
"Summoning",
|
|
24
|
+
"Calibrating",
|
|
25
|
+
"Sorting",
|
|
26
|
+
"Debating",
|
|
27
|
+
"Brewing",
|
|
28
|
+
"Stargazing",
|
|
29
|
+
"Walking",
|
|
30
|
+
"Folding",
|
|
31
|
+
"Rounding",
|
|
32
|
+
"Cooking",
|
|
33
|
+
"Crunching",
|
|
34
|
+
"Cogitating",
|
|
35
|
+
"Analyzing",
|
|
36
|
+
"Architecting",
|
|
37
|
+
"Assembling",
|
|
38
|
+
"Building",
|
|
39
|
+
"Calculating",
|
|
40
|
+
"Compiling",
|
|
41
|
+
"Composing",
|
|
42
|
+
"Crafting",
|
|
43
|
+
"Decoding",
|
|
44
|
+
"Designing",
|
|
45
|
+
"Drafting",
|
|
46
|
+
"Editing",
|
|
47
|
+
"Evaluating",
|
|
48
|
+
"Experimenting",
|
|
49
|
+
"Explaining",
|
|
50
|
+
"Extracting",
|
|
51
|
+
"Generating",
|
|
52
|
+
"Integrating",
|
|
53
|
+
"Iterating",
|
|
54
|
+
"Juggling",
|
|
55
|
+
"Mapping",
|
|
56
|
+
"Measuring",
|
|
57
|
+
"Merging",
|
|
58
|
+
"Modeling",
|
|
59
|
+
"Navigating",
|
|
60
|
+
"Optimizing",
|
|
61
|
+
"Organizing",
|
|
62
|
+
"Parsing",
|
|
63
|
+
"Planning",
|
|
64
|
+
"Pondering",
|
|
65
|
+
"Processing",
|
|
66
|
+
"Refactoring",
|
|
67
|
+
"Refining",
|
|
68
|
+
"Rendering",
|
|
69
|
+
"Resolving",
|
|
70
|
+
"Reviewing",
|
|
71
|
+
"Scanning",
|
|
72
|
+
"Sifting",
|
|
73
|
+
"Simulating",
|
|
74
|
+
"Streamlining",
|
|
75
|
+
"Structuring",
|
|
76
|
+
"Synthesizing",
|
|
77
|
+
"Testing",
|
|
78
|
+
"Tracing",
|
|
79
|
+
"Translating",
|
|
80
|
+
"Triaging",
|
|
81
|
+
"Unraveling",
|
|
82
|
+
"Validating",
|
|
83
|
+
"Verifying",
|
|
84
|
+
"Wrangling",
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
export const HEADER_TIPS: BannerTip[] = [
|
|
88
|
+
{
|
|
89
|
+
type: "Tip",
|
|
90
|
+
text: "Press Ctrl + G inside Pi's input box to open your default system $EDITOR (e.g., Neovim) for writing long, complex prompts",
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
type: "Did You Know?",
|
|
94
|
+
text: "Model reasoning quality degrades as the context window fills up. Use /compact or start fresh sessions once context exceeds 50–60%",
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
type: "Workflow",
|
|
98
|
+
text: "Isolate planning from execution: use a read-only profile for architectural planning and switch to full permissions only when building",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
type: "Did You Know?",
|
|
102
|
+
text: "Modern models like Claude 3.5 and 3.7 process boundaries in XML tags (<context>, <rules>, <code_diff>) significantly better than raw Markdown dividers",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
type: "Tip",
|
|
106
|
+
text: "Always truncate or filter large log outputs before handing them to an agent — a 10,000-line stack trace will immediately saturate your token cache",
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
type: "Tip",
|
|
110
|
+
text: "Export global environment variables (like $EDITOR and $VISUAL) in ~/.bashenv (or your shell's env file) so background subshells and GUI-spawned processes inherit them cleanly",
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
type: "Did You Know?",
|
|
114
|
+
text: "Smooth 80ms Braille sequences (⠋, ⠙, ⠹, ⠸) or quadrant block meters give immediate visual feedback without consuming much screen real estate",
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
type: "Prompting",
|
|
118
|
+
text: "Tell models what TO DO instead of what NOT to do—negative constraints like 'don't use markdown' are frequently ignored compared to positive instructions",
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
type: "Workflow",
|
|
122
|
+
text: "Use fuzzy file references by typing `@` in Pi's input box to quickly anchor specific codebase files directly into the prompt context",
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
type: "Tip",
|
|
126
|
+
text: "Place heavy longform context or data files near the top of your prompt and put your actual instructions or questions at the very end for better accuracy",
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
type: "Did You Know?",
|
|
130
|
+
text: "Pi saves session history as a tree. You can use `/tree` or `/fork` to branch off a previous point in a conversation to test an alternative approach",
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
type: "Prompting",
|
|
134
|
+
text: "Define specific output formats (e.g., JSON schemas or concise bullet points) upfront to prevent models from generating unnecessary verbose prose",
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
type: "Tip",
|
|
138
|
+
text: "Paste screenshots straight into the prompt with Ctrl+V (Alt+V on Windows) — models can see error dialogs, UIs, and graphs you can't describe in words",
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
type: "Tip",
|
|
142
|
+
text: "Type `@` to anchor files into the prompt — pi inlines the real contents, so the model reads your code, not your summary of it",
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
type: "Tip",
|
|
146
|
+
text: "Swap models mid-session with `/model` or Ctrl+L instead of restarting — you keep the conversation context, just change the brain",
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
type: "Did You Know?",
|
|
150
|
+
text: "Shift+Tab cycles through your recent models without opening the picker — fastest way to A/B two models on the same prompt",
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
type: "Workflow",
|
|
154
|
+
text: "Run `/compact` before starting a big new task: the conversation is summarized and you continue with a clean, cheap context",
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
type: "Workflow",
|
|
158
|
+
text: "Assign one agent mode per task phase — read-only for planning/research, full privileges only for execution — so a misfired tool call can't touch your repo",
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: "Prompting",
|
|
162
|
+
text: "Restate the single most important requirement in the *last* line of a long prompt — instructions given early fade as context grows",
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
type: "Prompting",
|
|
166
|
+
text: "Show, don't tell: paste the exact error text plus the file:line that produced it. Vague 'it's broken' prompts get shotgun fixes",
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
type: "Tip",
|
|
170
|
+
text: "Keep messages atomic — one question or one change per message. Mega-prompts amortize badly over a long session",
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
type: "Workflow",
|
|
174
|
+
text: "For multi-file changes, ask for a plan first (files touched + order) and approve it before any edits — cheap insurance against wrong-direction refactors",
|
|
175
|
+
},
|
|
176
|
+
];
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { ThemeColor } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { FrameIcons, SpinnerPhase } from "../types";
|
|
3
|
+
/** Spinner animation frames per phase (pi-editor-shell style). */
|
|
4
|
+
export const SPINNER_FRAMES: Record<SpinnerPhase, string[]> = {
|
|
5
|
+
idle: ["⠃", "⠞", "⡵", "⠿", "⢹", "⠄"],
|
|
6
|
+
outputting: ["⠋", "⠙", "⠸", "⠴", "⠦", "⠇", "⠏"],
|
|
7
|
+
thinking: ["", "", "", "", "", "", "", ""],
|
|
8
|
+
toolcall: ["●", "●", "●", "●", "○", "○", "○", "○"],
|
|
9
|
+
exec: ["⠂", "⠅", "⠍", "⠟", "⠿", "⠽", "⠿", "⠟", "⠍", "⠅", "⠂"],
|
|
10
|
+
|
|
11
|
+
// Sample ["░", "▒", "▓", "█", "▓", "▒"],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/** Nerd Font defaults (override any subset via `frame.icons`). */
|
|
15
|
+
export const DEFAULT_ICONS: FrameIcons = {
|
|
16
|
+
model: "",
|
|
17
|
+
folder: " ",
|
|
18
|
+
context: "",
|
|
19
|
+
gitDirty: "",
|
|
20
|
+
thinking: "",
|
|
21
|
+
gitBranch: "",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/** Thinking level → theme token, mirroring pi's own border-color mapping. */
|
|
25
|
+
export const THINKING_TOKEN: Record<string, string> = {
|
|
26
|
+
off: "thinkingOff",
|
|
27
|
+
minimal: "thinkingMinimal",
|
|
28
|
+
low: "thinkingLow",
|
|
29
|
+
medium: "thinkingMedium",
|
|
30
|
+
high: "thinkingHigh",
|
|
31
|
+
xhigh: "thinkingXhigh",
|
|
32
|
+
max: "thinkingMax",
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
export const THEME_COLORS: Record<ThemeColor, true> = {
|
|
37
|
+
accent: true,
|
|
38
|
+
border: true,
|
|
39
|
+
borderAccent: true,
|
|
40
|
+
borderMuted: true,
|
|
41
|
+
success: true,
|
|
42
|
+
error: true,
|
|
43
|
+
warning: true,
|
|
44
|
+
muted: true,
|
|
45
|
+
dim: true,
|
|
46
|
+
text: true,
|
|
47
|
+
searchMatchText: true,
|
|
48
|
+
thinkingText: true,
|
|
49
|
+
userMessageText: true,
|
|
50
|
+
customMessageText: true,
|
|
51
|
+
customMessageLabel: true,
|
|
52
|
+
toolTitle: true,
|
|
53
|
+
toolOutput: true,
|
|
54
|
+
mdHeading: true,
|
|
55
|
+
mdLink: true,
|
|
56
|
+
mdLinkUrl: true,
|
|
57
|
+
mdCode: true,
|
|
58
|
+
mdCodeBlock: true,
|
|
59
|
+
mdCodeBlockBorder: true,
|
|
60
|
+
mdQuote: true,
|
|
61
|
+
mdQuoteBorder: true,
|
|
62
|
+
mdHr: true,
|
|
63
|
+
mdListBullet: true,
|
|
64
|
+
toolDiffAdded: true,
|
|
65
|
+
toolDiffRemoved: true,
|
|
66
|
+
toolDiffContext: true,
|
|
67
|
+
syntaxComment: true,
|
|
68
|
+
syntaxKeyword: true,
|
|
69
|
+
syntaxFunction: true,
|
|
70
|
+
syntaxVariable: true,
|
|
71
|
+
syntaxString: true,
|
|
72
|
+
syntaxNumber: true,
|
|
73
|
+
syntaxType: true,
|
|
74
|
+
syntaxOperator: true,
|
|
75
|
+
syntaxPunctuation: true,
|
|
76
|
+
thinkingOff: true,
|
|
77
|
+
thinkingMinimal: true,
|
|
78
|
+
thinkingLow: true,
|
|
79
|
+
thinkingMedium: true,
|
|
80
|
+
thinkingHigh: true,
|
|
81
|
+
thinkingXhigh: true,
|
|
82
|
+
thinkingMax: true,
|
|
83
|
+
bashMode: true,
|
|
84
|
+
};
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@leo-alvarenga/pi-zen-frame",
|
|
3
3
|
"description": "A pi-coding-agent extension that gives the TUI editor a simple yet polished look and feel",
|
|
4
4
|
"author": "Leonardo A. Alvarenga",
|
|
5
|
-
"version": "0.12.
|
|
5
|
+
"version": "0.12.2",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": "github.com/leo-alvarenga/pi-mono",
|
|
8
8
|
"publishConfig": {
|
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
import { ThemeColor } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import type { BannerTip, FrameIcons, Settings, SpinnerPhase } from "./types";
|
|
3
|
-
|
|
4
|
-
export const CONFIG_FILE_NAME = "pi-zen-frame.json";
|
|
5
|
-
|
|
6
|
-
/** pi-agent-manager integration (optional — no hard dependency). */
|
|
7
|
-
export const PI_AGENT_MANAGER_AGENT_EVENT = "pi-agent-manager:agent-changed";
|
|
8
|
-
export const PI_AGENT_MANAGER_AGENT_DATA_KEY = "pi-agent-manager-agent";
|
|
9
|
-
|
|
10
|
-
/** Keybinding id users bind in keybindings.json to toggle zen mode. */
|
|
11
|
-
export const ZEN_MODE_SHORTCUT_ID = "piZenFrame.zenMode";
|
|
12
|
-
/** Default key when the user hasn't bound one (override or disable via
|
|
13
|
-
* keybindings.json; `[]` disables the shortcut, `/zen_mode` still works). */
|
|
14
|
-
export const ZEN_MODE_DEFAULT_KEY = "ctrl+shift+z";
|
|
15
|
-
|
|
16
|
-
/** Spinner animation frames per phase (pi-editor-shell style). */
|
|
17
|
-
export const SPINNER_FRAMES: Record<SpinnerPhase, string[]> = {
|
|
18
|
-
idle: ["⠃", "⠞", "⡵", "⠿", "⢹", "⠄"],
|
|
19
|
-
outputting: ["⠋", "⠙", "⠸", "⠴", "⠦", "⠇", "⠏"],
|
|
20
|
-
thinking: ["", "", "", "", "", "", "", ""],
|
|
21
|
-
toolcall: ["●", "●", "●", "●", "○", "○", "○", "○"],
|
|
22
|
-
exec: ["⠂", "⠅", "⠍", "⠟", "⠿", "⠽", "⠿", "⠟", "⠍", "⠅", "⠂"],
|
|
23
|
-
|
|
24
|
-
// Sample ["░", "▒", "▓", "█", "▓", "▒"],
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
/** Nerd Font defaults (override any subset via `frame.icons`). */
|
|
28
|
-
export const DEFAULT_ICONS: FrameIcons = {
|
|
29
|
-
model: "",
|
|
30
|
-
folder: " ",
|
|
31
|
-
context: "",
|
|
32
|
-
gitDirty: "",
|
|
33
|
-
thinking: "",
|
|
34
|
-
gitBranch: "",
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
/** Thinking level → theme token, mirroring pi's own border-color mapping. */
|
|
38
|
-
export const THINKING_TOKEN: Record<string, string> = {
|
|
39
|
-
off: "thinkingOff",
|
|
40
|
-
minimal: "thinkingMinimal",
|
|
41
|
-
low: "thinkingLow",
|
|
42
|
-
medium: "thinkingMedium",
|
|
43
|
-
high: "thinkingHigh",
|
|
44
|
-
xhigh: "thinkingXhigh",
|
|
45
|
-
max: "thinkingMax",
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
/** Rotating messages for the working loader (single-word verbs; some silly, some plausible). */
|
|
49
|
-
export const WORKING_MESSAGES: string[] = [
|
|
50
|
-
"Exploring",
|
|
51
|
-
"Tinkering",
|
|
52
|
-
"Searching",
|
|
53
|
-
"Polishing",
|
|
54
|
-
"Herding",
|
|
55
|
-
"Consulting",
|
|
56
|
-
"Chasing",
|
|
57
|
-
"Rearranging",
|
|
58
|
-
"Sharpening",
|
|
59
|
-
"Reticulating",
|
|
60
|
-
"Warming",
|
|
61
|
-
"Feeding",
|
|
62
|
-
"Whispering",
|
|
63
|
-
"Counting",
|
|
64
|
-
"Dusting",
|
|
65
|
-
"Tightening",
|
|
66
|
-
"Watering",
|
|
67
|
-
"Aligning",
|
|
68
|
-
"Reading",
|
|
69
|
-
"Charging",
|
|
70
|
-
"Summoning",
|
|
71
|
-
"Calibrating",
|
|
72
|
-
"Sorting",
|
|
73
|
-
"Debating",
|
|
74
|
-
"Brewing",
|
|
75
|
-
"Stargazing",
|
|
76
|
-
"Walking",
|
|
77
|
-
"Folding",
|
|
78
|
-
"Rounding",
|
|
79
|
-
"Cooking",
|
|
80
|
-
"Crunching",
|
|
81
|
-
"Cogitating",
|
|
82
|
-
"Analyzing",
|
|
83
|
-
"Architecting",
|
|
84
|
-
"Assembling",
|
|
85
|
-
"Building",
|
|
86
|
-
"Calculating",
|
|
87
|
-
"Compiling",
|
|
88
|
-
"Composing",
|
|
89
|
-
"Crafting",
|
|
90
|
-
"Decoding",
|
|
91
|
-
"Designing",
|
|
92
|
-
"Drafting",
|
|
93
|
-
"Editing",
|
|
94
|
-
"Evaluating",
|
|
95
|
-
"Experimenting",
|
|
96
|
-
"Explaining",
|
|
97
|
-
"Extracting",
|
|
98
|
-
"Generating",
|
|
99
|
-
"Integrating",
|
|
100
|
-
"Iterating",
|
|
101
|
-
"Juggling",
|
|
102
|
-
"Mapping",
|
|
103
|
-
"Measuring",
|
|
104
|
-
"Merging",
|
|
105
|
-
"Modeling",
|
|
106
|
-
"Navigating",
|
|
107
|
-
"Optimizing",
|
|
108
|
-
"Organizing",
|
|
109
|
-
"Parsing",
|
|
110
|
-
"Planning",
|
|
111
|
-
"Pondering",
|
|
112
|
-
"Processing",
|
|
113
|
-
"Refactoring",
|
|
114
|
-
"Refining",
|
|
115
|
-
"Rendering",
|
|
116
|
-
"Resolving",
|
|
117
|
-
"Reviewing",
|
|
118
|
-
"Scanning",
|
|
119
|
-
"Sifting",
|
|
120
|
-
"Simulating",
|
|
121
|
-
"Streamlining",
|
|
122
|
-
"Structuring",
|
|
123
|
-
"Synthesizing",
|
|
124
|
-
"Testing",
|
|
125
|
-
"Tracing",
|
|
126
|
-
"Translating",
|
|
127
|
-
"Triaging",
|
|
128
|
-
"Unraveling",
|
|
129
|
-
"Validating",
|
|
130
|
-
"Verifying",
|
|
131
|
-
"Wrangling",
|
|
132
|
-
];
|
|
133
|
-
|
|
134
|
-
export const HEADER_TIPS: BannerTip[] = [
|
|
135
|
-
{
|
|
136
|
-
type: "Tip",
|
|
137
|
-
text: "Press Ctrl + G inside Pi's input box to open your default system $EDITOR (e.g., Neovim) for writing long, complex prompts",
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
type: "Did You Know?",
|
|
141
|
-
text: "Model reasoning quality degrades as the context window fills up. Use /compact or start fresh sessions once context exceeds 50–60%",
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
type: "Workflow",
|
|
145
|
-
text: "Isolate planning from execution: use a read-only profile for architectural planning and switch to full permissions only when building",
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
type: "Did You Know?",
|
|
149
|
-
text: "Modern models like Claude 3.5 and 3.7 process boundaries in XML tags (<context>, <rules>, <code_diff>) significantly better than raw Markdown dividers",
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
type: "Tip",
|
|
153
|
-
text: "Always truncate or filter large log outputs before handing them to an agent—a 10,000-line stack trace will immediately saturate your token cache",
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
type: "Tip",
|
|
157
|
-
text: "Export global environment variables (like $EDITOR and $VISUAL) in ~/.bashenv (or your shell's env file) so background subshells and GUI-spawned processes inherit them cleanly",
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
type: "Did You Know?",
|
|
161
|
-
text: "Smooth 80ms Braille sequences (⠋, ⠙, ⠹, ⠸) or quadrant block meters give immediate visual feedback without consuming much screen real estate",
|
|
162
|
-
},
|
|
163
|
-
{
|
|
164
|
-
type: "Prompting",
|
|
165
|
-
text: "Tell models what TO DO instead of what NOT to do—negative constraints like 'don't use markdown' are frequently ignored compared to positive instructions",
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
type: "Workflow",
|
|
169
|
-
text: "Use fuzzy file references by typing `@` in Pi's input box to quickly anchor specific codebase files directly into the prompt context",
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
type: "Tip",
|
|
173
|
-
text: "Place heavy longform context or data files near the top of your prompt and put your actual instructions or questions at the very end for better accuracy",
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
type: "Did You Know?",
|
|
177
|
-
text: "Pi saves session history as a tree. You can use `/tree` or `/fork` to branch off a previous point in a conversation to test an alternative approach",
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
type: "Prompting",
|
|
181
|
-
text: "Define specific output formats (e.g., JSON schemas or concise bullet points) upfront to prevent models from generating unnecessary verbose prose",
|
|
182
|
-
},
|
|
183
|
-
];
|
|
184
|
-
|
|
185
|
-
export const DEFAULT_SETTINGS: Settings = {
|
|
186
|
-
zenMode: false,
|
|
187
|
-
accentColor: "accent",
|
|
188
|
-
|
|
189
|
-
header: {
|
|
190
|
-
enable: false,
|
|
191
|
-
logoColor: "text",
|
|
192
|
-
accentColor: "accent",
|
|
193
|
-
|
|
194
|
-
heading: "Welcome back!",
|
|
195
|
-
subheading:
|
|
196
|
-
"Ready for your next session? Terminal warm, context clean, tools ready to execute",
|
|
197
|
-
|
|
198
|
-
logo: ["█████████ ", "███ ███ ", "██████ ", "███ ███"],
|
|
199
|
-
},
|
|
200
|
-
|
|
201
|
-
workingMessage: {
|
|
202
|
-
enable: true,
|
|
203
|
-
intervalMs: 3000,
|
|
204
|
-
messages: WORKING_MESSAGES,
|
|
205
|
-
},
|
|
206
|
-
|
|
207
|
-
frame: {
|
|
208
|
-
icons: {},
|
|
209
|
-
paddingX: 1,
|
|
210
|
-
enable: true,
|
|
211
|
-
minWidth: 20,
|
|
212
|
-
marginTop: 0,
|
|
213
|
-
showCwd: true,
|
|
214
|
-
paddingTop: 1,
|
|
215
|
-
marginBottom: 0,
|
|
216
|
-
showModel: true,
|
|
217
|
-
paddingBottom: 1,
|
|
218
|
-
showSpinner: false,
|
|
219
|
-
showContext: true,
|
|
220
|
-
showThinking: true,
|
|
221
|
-
showAgentMode: true,
|
|
222
|
-
borderColor: "text",
|
|
223
|
-
|
|
224
|
-
colors: {},
|
|
225
|
-
// ponytail: colors were dormant (nothing read them); now wired — keep
|
|
226
|
-
// defaults unset so segments keep their natural colors and zen-mode is
|
|
227
|
-
// the mute switch.
|
|
228
|
-
},
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
export const THEME_COLORS: Record<ThemeColor, true> = {
|
|
232
|
-
accent: true,
|
|
233
|
-
border: true,
|
|
234
|
-
borderAccent: true,
|
|
235
|
-
borderMuted: true,
|
|
236
|
-
success: true,
|
|
237
|
-
error: true,
|
|
238
|
-
warning: true,
|
|
239
|
-
muted: true,
|
|
240
|
-
dim: true,
|
|
241
|
-
text: true,
|
|
242
|
-
searchMatchText: true,
|
|
243
|
-
thinkingText: true,
|
|
244
|
-
userMessageText: true,
|
|
245
|
-
customMessageText: true,
|
|
246
|
-
customMessageLabel: true,
|
|
247
|
-
toolTitle: true,
|
|
248
|
-
toolOutput: true,
|
|
249
|
-
mdHeading: true,
|
|
250
|
-
mdLink: true,
|
|
251
|
-
mdLinkUrl: true,
|
|
252
|
-
mdCode: true,
|
|
253
|
-
mdCodeBlock: true,
|
|
254
|
-
mdCodeBlockBorder: true,
|
|
255
|
-
mdQuote: true,
|
|
256
|
-
mdQuoteBorder: true,
|
|
257
|
-
mdHr: true,
|
|
258
|
-
mdListBullet: true,
|
|
259
|
-
toolDiffAdded: true,
|
|
260
|
-
toolDiffRemoved: true,
|
|
261
|
-
toolDiffContext: true,
|
|
262
|
-
syntaxComment: true,
|
|
263
|
-
syntaxKeyword: true,
|
|
264
|
-
syntaxFunction: true,
|
|
265
|
-
syntaxVariable: true,
|
|
266
|
-
syntaxString: true,
|
|
267
|
-
syntaxNumber: true,
|
|
268
|
-
syntaxType: true,
|
|
269
|
-
syntaxOperator: true,
|
|
270
|
-
syntaxPunctuation: true,
|
|
271
|
-
thinkingOff: true,
|
|
272
|
-
thinkingMinimal: true,
|
|
273
|
-
thinkingLow: true,
|
|
274
|
-
thinkingMedium: true,
|
|
275
|
-
thinkingHigh: true,
|
|
276
|
-
thinkingXhigh: true,
|
|
277
|
-
thinkingMax: true,
|
|
278
|
-
bashMode: true,
|
|
279
|
-
};
|