@leo-alvarenga/pi-zen-frame 0.12.1 → 0.13.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 +10 -4
- package/extensions/components/agent-mode.ts +8 -7
- package/extensions/components/cwd.ts +6 -9
- package/extensions/components/frame.ts +58 -63
- package/extensions/components/header.ts +3 -3
- package/extensions/components/model.ts +3 -6
- package/extensions/components/reasoning.ts +5 -4
- package/extensions/components/registry.ts +2 -2
- package/extensions/components/token-count.ts +7 -9
- package/extensions/components/types.ts +12 -18
- package/extensions/config/constants/contracts.ts +12 -0
- package/extensions/config/constants/defaults.ts +46 -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/extensions/config/settings.ts +9 -22
- package/extensions/config/types.ts +22 -28
- package/extensions/editor/{frame-editor.ts → blocky-editor.ts} +58 -54
- package/extensions/index.ts +20 -9
- package/extensions/renderers/registry.ts +41 -0
- package/extensions/renderers/types.ts +57 -0
- package/package.json +1 -1
- package/extensions/config/constants.ts +0 -279
package/README.md
CHANGED
|
@@ -45,8 +45,13 @@ Configuration is loaded from `~/.pi/agent/pi-zen-frame.json`. All properties are
|
|
|
45
45
|
// Master mute: renders all segments in muted tones except agent-mode
|
|
46
46
|
"zenMode": true,
|
|
47
47
|
|
|
48
|
+
// Editor-frame renderer by registered name (built-in: "blocky")
|
|
49
|
+
"editorFrame": "blocky",
|
|
50
|
+
|
|
48
51
|
"header": {
|
|
49
52
|
"enable": true,
|
|
53
|
+
// Header renderer by registered name (built-in: "basic")
|
|
54
|
+
"type": "basic",
|
|
50
55
|
"logo": ["█████████ ", "███ ███ ", "██████ ", "███ ███"],
|
|
51
56
|
"heading": "Welcome back!",
|
|
52
57
|
"subheading": "Ready for your next session? Terminal warm, context clean, tools ready to execute",
|
|
@@ -63,7 +68,7 @@ Configuration is loaded from `~/.pi/agent/pi-zen-frame.json`. All properties are
|
|
|
63
68
|
// Padding inside the frame
|
|
64
69
|
"paddingTop": 1,
|
|
65
70
|
"paddingBottom": 1,
|
|
66
|
-
"paddingX":
|
|
71
|
+
"paddingX": 2,
|
|
67
72
|
|
|
68
73
|
// Outer margin around the frame
|
|
69
74
|
"marginTop": 0,
|
|
@@ -81,7 +86,7 @@ Configuration is loaded from `~/.pi/agent/pi-zen-frame.json`. All properties are
|
|
|
81
86
|
"borderColor": "border",
|
|
82
87
|
|
|
83
88
|
// Input prompt prefix glyph and color settings
|
|
84
|
-
"prefix": "
|
|
89
|
+
"prefix": "┃",
|
|
85
90
|
"prefixColor": "muted", // Options: "agentMode", "frameBorder", or any ThemeColor
|
|
86
91
|
|
|
87
92
|
// Override default Nerd-Font glyphs
|
|
@@ -149,8 +154,9 @@ Run `/reload` after modifying your keybindings.
|
|
|
149
154
|
extensions/
|
|
150
155
|
├── index.ts # Extension entry point: config initialization and events
|
|
151
156
|
├── config/ # Types, defaults, and settings normalization
|
|
152
|
-
├── components/ # Header, frame border, and status segment modules
|
|
153
|
-
├── editor/ #
|
|
157
|
+
├── components/ # Header (BasicHeader), frame border, and status segment modules
|
|
158
|
+
├── editor/ # BlockyEditor editor-frame renderer
|
|
159
|
+
├── renderers/ # Renderer registry + swap-in API (blocky / basic)
|
|
154
160
|
└── utils/ # Helpers for Git status, paths, and agent modes
|
|
155
161
|
|
|
156
162
|
```
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { capitalize } from "../utils";
|
|
2
|
+
|
|
2
3
|
import type { SegmentDef } from "./types";
|
|
3
4
|
|
|
4
|
-
/**
|
|
5
|
-
* Rendered as a pill using the agent's own color/icon. */
|
|
5
|
+
/** Pseudo-footer (left): the current Agent Mode from pi-agent-manager
|
|
6
|
+
* (when installed). Rendered as a pill using the agent's own color/icon. */
|
|
6
7
|
export const agentModeSegment: SegmentDef = {
|
|
7
8
|
id: "agent-mode",
|
|
8
|
-
slot: "
|
|
9
|
+
slot: "topLeft",
|
|
9
10
|
enabled: (_d, cfg) => cfg.showAgentMode !== false,
|
|
10
11
|
|
|
11
|
-
render: (d, { theme
|
|
12
|
+
render: (d, { theme }) => {
|
|
12
13
|
const m = d.agentMode;
|
|
13
14
|
if (!m) return "";
|
|
14
15
|
|
|
15
|
-
// Agent's own color wins;
|
|
16
|
-
const color = m.color ??
|
|
17
|
-
const label =
|
|
16
|
+
// Agent's own color wins; accent fills in. Zen never mutes the agent.
|
|
17
|
+
const color = m.color ?? d.accentColor;
|
|
18
|
+
const label = ` ${capitalize(m.name)} `;
|
|
18
19
|
|
|
19
20
|
try {
|
|
20
21
|
return theme.fg(color, label);
|
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
import type { SegmentDef } from "./types";
|
|
2
2
|
import { getShortCwd } from "../utils";
|
|
3
3
|
|
|
4
|
-
/**
|
|
4
|
+
/** Pseudo-footer (right): working directory + git branch (with dirty count). */
|
|
5
5
|
export const cwdSegment: SegmentDef = {
|
|
6
6
|
id: "cwd",
|
|
7
|
-
slot: "
|
|
7
|
+
slot: "bottomLeft",
|
|
8
8
|
enabled: (_d, cfg) => cfg.showCwd !== false,
|
|
9
|
-
render: (d, { theme, icons
|
|
9
|
+
render: (d, { theme, icons }) => {
|
|
10
10
|
const folder = getShortCwd(d.cwd);
|
|
11
11
|
|
|
12
|
-
let text = theme.fg(
|
|
13
|
-
segColor("cwd", "muted"),
|
|
14
|
-
`${icons.folder} ${folder}`,
|
|
15
|
-
);
|
|
12
|
+
let text = theme.fg("muted", `${icons.folder} ${folder}`);
|
|
16
13
|
|
|
17
14
|
if (d.gitBranch) {
|
|
18
15
|
let git = ` ${icons.gitBranch} ${d.gitBranch}`;
|
|
19
|
-
text += theme.fg(
|
|
16
|
+
text += theme.fg(d.zenMode ? "muted" : d.accentColor, git);
|
|
20
17
|
|
|
21
18
|
if (d.gitDirty > 0) {
|
|
22
19
|
text += theme.fg(
|
|
23
|
-
|
|
20
|
+
d.zenMode ? "muted" : "error",
|
|
24
21
|
` ${icons.gitDirty} ${d.gitDirty}`,
|
|
25
22
|
);
|
|
26
23
|
}
|
|
@@ -1,23 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* corner glyphs, embeds the segment text into the top/bottom border, and
|
|
4
|
-
* inserts the configurable blank padding lines inside the box.
|
|
2
|
+
* Row layout for the borderless band editor.
|
|
5
3
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* `width` columns
|
|
4
|
+
* composeBand assembles the bg-filled band: padding rows, content (prefix on
|
|
5
|
+
* the first row), autocomplete, one blank row, then the box-bottom segments.
|
|
6
|
+
* Every output row is exactly `width` columns. fitFrameRow/fitInfoRow lay out
|
|
7
|
+
* the header and status rows.
|
|
9
8
|
*/
|
|
10
9
|
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
11
10
|
|
|
12
|
-
export interface FrameOptions {
|
|
13
|
-
width: number;
|
|
14
|
-
prefix?: string;
|
|
15
|
-
paddingX: number;
|
|
16
|
-
paddingTop: number;
|
|
17
|
-
paddingBottom: number;
|
|
18
|
-
border: (str: string) => string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
11
|
const SGR_RE = /\x1b\[[0-9;]*m/g;
|
|
22
12
|
const CURSOR_MARKER_RE = /\x1b_pi:c\x07/g;
|
|
23
13
|
|
|
@@ -26,7 +16,7 @@ function plain(row: string): string {
|
|
|
26
16
|
}
|
|
27
17
|
|
|
28
18
|
/** A border row is all `─`, or a `─── ↑/↓ N more ───` scroll indicator. */
|
|
29
|
-
function isBorderRow(row: string): boolean {
|
|
19
|
+
export function isBorderRow(row: string): boolean {
|
|
30
20
|
const t = plain(row).trim();
|
|
31
21
|
|
|
32
22
|
if (t === "") return true;
|
|
@@ -35,6 +25,58 @@ function isBorderRow(row: string): boolean {
|
|
|
35
25
|
return /^─── [↑↓] \d+ more ─*$/.test(t);
|
|
36
26
|
}
|
|
37
27
|
|
|
28
|
+
export interface BandOptions {
|
|
29
|
+
padX: number;
|
|
30
|
+
width: number;
|
|
31
|
+
prefix: string;
|
|
32
|
+
marginX: number;
|
|
33
|
+
boxBottom: string;
|
|
34
|
+
paddingTop: number;
|
|
35
|
+
paddingBottom: number;
|
|
36
|
+
paint: (row: string) => string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Borderless bg band: padding, content (prefix on first row), autocomplete,
|
|
40
|
+
* blank row, box-bottom segments. Every row is exactly `width` columns. */
|
|
41
|
+
export function composeBand(
|
|
42
|
+
content: string[],
|
|
43
|
+
autocomplete: string[],
|
|
44
|
+
opts: BandOptions,
|
|
45
|
+
): string[] {
|
|
46
|
+
const {
|
|
47
|
+
padX,
|
|
48
|
+
paint,
|
|
49
|
+
width,
|
|
50
|
+
prefix,
|
|
51
|
+
marginX,
|
|
52
|
+
boxBottom,
|
|
53
|
+
paddingTop,
|
|
54
|
+
paddingBottom,
|
|
55
|
+
} = opts;
|
|
56
|
+
|
|
57
|
+
const lead = Math.max(0, padX - visibleWidth(prefix));
|
|
58
|
+
|
|
59
|
+
const inset = (row: string) =>
|
|
60
|
+
paint(prefix + " ".repeat(lead) + row + " ".repeat(padX));
|
|
61
|
+
|
|
62
|
+
const fill = () => inset(paint(" ".repeat(Math.max(0, width - 2 * padX))));
|
|
63
|
+
|
|
64
|
+
const rows: string[] = [];
|
|
65
|
+
for (let i = 0; i < paddingTop; i++) rows.push(fill());
|
|
66
|
+
|
|
67
|
+
content.forEach((row) => {
|
|
68
|
+
rows.push(inset(row));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
autocomplete.forEach((row) => rows.push(inset(row)));
|
|
72
|
+
|
|
73
|
+
rows.push(fill());
|
|
74
|
+
rows.push(inset(boxBottom));
|
|
75
|
+
|
|
76
|
+
for (let i = 0; i < paddingBottom; i++) rows.push(fill());
|
|
77
|
+
return rows;
|
|
78
|
+
}
|
|
79
|
+
|
|
38
80
|
/** Lay one border row: cap + leftText + ─fill + rightText + cap, always
|
|
39
81
|
* exactly `width` columns. Right text truncates first, then left text. */
|
|
40
82
|
export function fitFrameRow(
|
|
@@ -91,50 +133,3 @@ export function fitInfoRow(
|
|
|
91
133
|
);
|
|
92
134
|
return leftText2 + " ".repeat(fill) + rightText2;
|
|
93
135
|
}
|
|
94
|
-
|
|
95
|
-
function wrapContent(row: string, paddingX: number): string {
|
|
96
|
-
if (paddingX <= 0) return row;
|
|
97
|
-
|
|
98
|
-
return " ".repeat(paddingX) + row + " ".repeat(paddingX);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export function renderFrame(inner: string[], opts: FrameOptions): string[] {
|
|
102
|
-
const { border, width, paddingX, prefix } = opts;
|
|
103
|
-
if (inner.length === 0) return inner;
|
|
104
|
-
|
|
105
|
-
// The real bottom border is the last border-like row (autocomplete rows
|
|
106
|
-
// are appended *after* it, so the last row is NOT necessarily the bottom).
|
|
107
|
-
let bottomIdx = inner.length - 1;
|
|
108
|
-
|
|
109
|
-
for (let i = inner.length - 1; i >= 0; i--) {
|
|
110
|
-
if (isBorderRow(inner[i]!)) {
|
|
111
|
-
bottomIdx = i;
|
|
112
|
-
break;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const result: string[] = [];
|
|
117
|
-
const padRow = " ".repeat(Math.max(0, width));
|
|
118
|
-
const fullBorder = border("─".repeat(width));
|
|
119
|
-
|
|
120
|
-
result.push(fullBorder);
|
|
121
|
-
|
|
122
|
-
for (let i = 0; i < opts.paddingTop; i++) result.push(padRow);
|
|
123
|
-
|
|
124
|
-
for (let i = 1; i < bottomIdx; i++) {
|
|
125
|
-
const decorator = i === 1 ? (prefix ?? "") : "";
|
|
126
|
-
const content = decorator + inner[i]!;
|
|
127
|
-
|
|
128
|
-
result.push(wrapContent(content, paddingX - visibleWidth(decorator)));
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
for (let i = 0; i < opts.paddingBottom; i++) result.push(padRow);
|
|
132
|
-
|
|
133
|
-
result.push(fullBorder);
|
|
134
|
-
|
|
135
|
-
for (let i = bottomIdx + 1; i < inner.length; i++) {
|
|
136
|
-
result.push(wrapContent(inner[i]!, paddingX));
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return result;
|
|
140
|
-
}
|
|
@@ -143,7 +143,7 @@ export function createHeader(
|
|
|
143
143
|
|
|
144
144
|
const rightW = inner - leftW - 1;
|
|
145
145
|
|
|
146
|
-
const rightLines = infoRows(env, rightW);
|
|
146
|
+
const rightLines = infoRows(env, rightW - 2);
|
|
147
147
|
const leftLines = [
|
|
148
148
|
...logo.lines.map((l) => theme.fg(logo.color, l)),
|
|
149
149
|
|
|
@@ -152,7 +152,7 @@ export function createHeader(
|
|
|
152
152
|
|
|
153
153
|
...wrapLines(
|
|
154
154
|
[settings.header?.heading ?? DEFAULT_SETTINGS.header?.heading ?? ""],
|
|
155
|
-
leftW,
|
|
155
|
+
leftW - 2,
|
|
156
156
|
).map((line) => theme.bold(theme.fg("muted", line))),
|
|
157
157
|
|
|
158
158
|
"",
|
|
@@ -163,7 +163,7 @@ export function createHeader(
|
|
|
163
163
|
DEFAULT_SETTINGS.header?.subheading ??
|
|
164
164
|
"",
|
|
165
165
|
],
|
|
166
|
-
leftW,
|
|
166
|
+
leftW - 2,
|
|
167
167
|
).map((line) => theme.italic(theme.fg("muted", line))),
|
|
168
168
|
];
|
|
169
169
|
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import type { SegmentDef } from "./types";
|
|
2
2
|
|
|
3
|
-
/**
|
|
3
|
+
/** Box bottom (left): the active model name. */
|
|
4
4
|
export const modelSegment: SegmentDef = {
|
|
5
5
|
id: "model",
|
|
6
6
|
slot: "topLeft",
|
|
7
7
|
enabled: (_d, cfg) => cfg.showModel !== false,
|
|
8
|
-
render: (d, { theme
|
|
8
|
+
render: (d, { theme }) => {
|
|
9
9
|
if (!d.modelName) return "";
|
|
10
10
|
|
|
11
|
-
return theme.fg(
|
|
12
|
-
segColor("model", d.accentColor),
|
|
13
|
-
` ${icons.model} ${d.modelName} `,
|
|
14
|
-
);
|
|
11
|
+
return ` ${theme.fg("text", d.modelName)} ${theme.fg("muted", `(${d.modelProvider})`)} `;
|
|
15
12
|
},
|
|
16
13
|
};
|
|
@@ -3,19 +3,20 @@ import type { ThemeColor } from "@earendil-works/pi-coding-agent";
|
|
|
3
3
|
import type { SegmentDef } from "./types";
|
|
4
4
|
import { THINKING_TOKEN } from "../config/constants";
|
|
5
5
|
|
|
6
|
-
/**
|
|
7
|
-
*
|
|
6
|
+
/** Box bottom (left): current thinking level, tinted with its own theme
|
|
7
|
+
* token — the same color pi applies to the border at that level. */
|
|
8
8
|
export const reasoningSegment: SegmentDef = {
|
|
9
9
|
id: "reasoning",
|
|
10
10
|
slot: "topLeft",
|
|
11
11
|
enabled: (_d, cfg) => cfg.showThinking !== false,
|
|
12
|
-
render: (d, { theme, icons
|
|
12
|
+
render: (d, { theme, icons }) => {
|
|
13
13
|
if (!d.thinkingLevel) return "";
|
|
14
|
+
|
|
14
15
|
const token = (THINKING_TOKEN[d.thinkingLevel] ??
|
|
15
16
|
"thinkingText") as ThemeColor;
|
|
16
17
|
|
|
17
18
|
return theme.fg(
|
|
18
|
-
|
|
19
|
+
d.zenMode ? "muted" : token,
|
|
19
20
|
` ${icons.thinking} ${d.thinkingLevel} `,
|
|
20
21
|
);
|
|
21
22
|
},
|
|
@@ -13,11 +13,11 @@ import { agentModeSegment } from "./agent-mode";
|
|
|
13
13
|
import type { FrameData, SegmentContext, SegmentDef, Slot } from "./types";
|
|
14
14
|
|
|
15
15
|
export const segments: SegmentDef[] = [
|
|
16
|
+
agentModeSegment,
|
|
16
17
|
modelSegment,
|
|
17
18
|
reasoningSegment,
|
|
18
19
|
spinnerSegment,
|
|
19
20
|
tokenCountSegment,
|
|
20
|
-
agentModeSegment,
|
|
21
21
|
cwdSegment,
|
|
22
22
|
];
|
|
23
23
|
|
|
@@ -38,5 +38,5 @@ export function segmentsFor(
|
|
|
38
38
|
return active
|
|
39
39
|
.map((s) => s.render(d, ctx))
|
|
40
40
|
.filter((t) => t !== "")
|
|
41
|
-
.join(ctx.
|
|
41
|
+
.join(ctx.theme.fg("dim", "·"));
|
|
42
42
|
}
|
|
@@ -19,12 +19,12 @@ function formatWindow(n: number): string {
|
|
|
19
19
|
return `${(n / 1_000).toFixed(0)}k`;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
/**
|
|
22
|
+
/** Box bottom (right): context window usage (percent + used/window tokens). */
|
|
23
23
|
export const tokenCountSegment: SegmentDef = {
|
|
24
24
|
id: "token-count",
|
|
25
|
-
slot: "
|
|
25
|
+
slot: "bottomRight",
|
|
26
26
|
enabled: (_d, cfg) => cfg.showContext !== false,
|
|
27
|
-
render: (d, {
|
|
27
|
+
render: (d, { theme, icons }) => {
|
|
28
28
|
const c = d.context;
|
|
29
29
|
if (!c) return "";
|
|
30
30
|
|
|
@@ -41,15 +41,13 @@ export const tokenCountSegment: SegmentDef = {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
const color2 = d.zenMode ? "muted" : color;
|
|
44
45
|
const used = c.tokens === null ? "?" : formatTokens(c.tokens);
|
|
45
46
|
|
|
46
47
|
return (
|
|
47
|
-
theme.fg(
|
|
48
|
-
|
|
49
|
-
theme.fg(
|
|
50
|
-
segColor("context", color),
|
|
51
|
-
` ${used}/${formatWindow(c.window)} `,
|
|
52
|
-
)
|
|
48
|
+
theme.fg(color2, ` ${icons.context} ctx ${pct} `) +
|
|
49
|
+
theme.fg("dim", "·") +
|
|
50
|
+
theme.fg(color2, ` ${used}/${formatWindow(c.window)} `)
|
|
53
51
|
);
|
|
54
52
|
},
|
|
55
53
|
};
|
|
@@ -10,14 +10,11 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { Theme, ThemeColor } from "@earendil-works/pi-coding-agent";
|
|
12
12
|
|
|
13
|
-
import type {
|
|
14
|
-
FrameColors,
|
|
15
|
-
FrameIcons,
|
|
16
|
-
FrameSettings,
|
|
17
|
-
SpinnerPhase,
|
|
18
|
-
} from "../config/types";
|
|
13
|
+
import type { FrameIcons, FrameSettings, SpinnerPhase } from "../config/types";
|
|
19
14
|
|
|
20
|
-
/** Where
|
|
15
|
+
/** Where a segment renders. "top*" → the box-bottom row inside the band,
|
|
16
|
+
* "bottom*" → the pseudo-footer row below it (names kept from the old
|
|
17
|
+
* border layout). */
|
|
21
18
|
export type Slot = "topLeft" | "topRight" | "bottomLeft" | "bottomRight";
|
|
22
19
|
|
|
23
20
|
export type AgentConfig = {
|
|
@@ -47,6 +44,7 @@ export interface FrameData {
|
|
|
47
44
|
accentColor: ThemeColor;
|
|
48
45
|
gitBranch: string | undefined;
|
|
49
46
|
modelName: string | undefined;
|
|
47
|
+
modelProvider: string | undefined;
|
|
50
48
|
spinnerPhase: SpinnerPhase | null;
|
|
51
49
|
thinkingLevel: string | undefined;
|
|
52
50
|
|
|
@@ -68,11 +66,6 @@ export interface SegmentContext {
|
|
|
68
66
|
theme: Theme;
|
|
69
67
|
icons: FrameIcons;
|
|
70
68
|
cfg: FrameSettings;
|
|
71
|
-
border: (str: string) => string;
|
|
72
|
-
|
|
73
|
-
/** Resolve a segment's fg: zen-mode mutes everything except agentMode;
|
|
74
|
-
* else `frame.colors.<key>` supersedes the segment default. */
|
|
75
|
-
segColor: (key: keyof FrameColors, fallback: ThemeColor) => ThemeColor;
|
|
76
69
|
}
|
|
77
70
|
|
|
78
71
|
/** A segment renders an already-ANSI-styled string, or "" to render nothing. */
|
|
@@ -93,14 +86,15 @@ export interface SegmentDef {
|
|
|
93
86
|
* this with its own live state (mode / count / spinner frame) in render().
|
|
94
87
|
*/
|
|
95
88
|
export interface ExternalData {
|
|
96
|
-
modelName: string | undefined;
|
|
97
|
-
thinkingLevel: string | undefined;
|
|
98
|
-
spinnerPhase: SpinnerPhase | null;
|
|
99
|
-
context: FrameData["context"];
|
|
100
89
|
cwd: string;
|
|
101
|
-
gitBranch: string | undefined;
|
|
102
90
|
gitDirty: number;
|
|
91
|
+
zenMode: boolean;
|
|
103
92
|
agentMode: AgentMode;
|
|
104
93
|
theme: Theme | undefined;
|
|
105
|
-
|
|
94
|
+
gitBranch: string | undefined;
|
|
95
|
+
modelName: string | undefined;
|
|
96
|
+
context: FrameData["context"];
|
|
97
|
+
modelProvider: string | undefined;
|
|
98
|
+
thinkingLevel: string | undefined;
|
|
99
|
+
spinnerPhase: SpinnerPhase | null;
|
|
106
100
|
}
|
|
@@ -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,46 @@
|
|
|
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
|
+
editorFrame: "blocky",
|
|
7
|
+
|
|
8
|
+
header: {
|
|
9
|
+
enable: false,
|
|
10
|
+
type: "basic",
|
|
11
|
+
logoColor: "text",
|
|
12
|
+
accentColor: "accent",
|
|
13
|
+
|
|
14
|
+
heading: "Welcome back!",
|
|
15
|
+
subheading:
|
|
16
|
+
"Ready for your next session? Terminal warm, context clean, tools ready to execute",
|
|
17
|
+
|
|
18
|
+
logo: ["█████████ ", "███ ███ ", "██████ ", "███ ███"],
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
workingMessage: {
|
|
22
|
+
enable: true,
|
|
23
|
+
intervalMs: 3000,
|
|
24
|
+
messages: WORKING_MESSAGES,
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
frame: {
|
|
28
|
+
icons: {},
|
|
29
|
+
marginX: 1,
|
|
30
|
+
paddingX: 2,
|
|
31
|
+
prefix: "┃",
|
|
32
|
+
enable: true,
|
|
33
|
+
minWidth: 20,
|
|
34
|
+
marginTop: 0,
|
|
35
|
+
showCwd: true,
|
|
36
|
+
paddingTop: 1,
|
|
37
|
+
marginBottom: 0,
|
|
38
|
+
showModel: true,
|
|
39
|
+
paddingBottom: 1,
|
|
40
|
+
showSpinner: false,
|
|
41
|
+
showContext: true,
|
|
42
|
+
showThinking: true,
|
|
43
|
+
showAgentMode: true,
|
|
44
|
+
prefixColor: "agentMode",
|
|
45
|
+
},
|
|
46
|
+
};
|
|
@@ -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";
|