pi-one-ui 0.1.1
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/LICENSE +21 -0
- package/README.md +106 -0
- package/extensions/app/config/renderer.ts +452 -0
- package/extensions/app/config/shell.ts +2484 -0
- package/extensions/app/ownership.ts +18 -0
- package/extensions/app/panel.ts +533 -0
- package/extensions/app/presets.ts +36 -0
- package/extensions/features/agent-summary/core.ts +194 -0
- package/extensions/features/agent-summary/index.ts +37 -0
- package/extensions/features/compact-thinking.ts +1262 -0
- package/extensions/features/context.ts +857 -0
- package/extensions/features/reference/index.ts +643 -0
- package/extensions/features/reference/session.ts +278 -0
- package/extensions/features/reference/subagent.ts +218 -0
- package/extensions/features/shell/aliases.ts +28 -0
- package/extensions/features/shell/flush-docked-bash.ts +39 -0
- package/extensions/features/shell/startup-header.ts +357 -0
- package/extensions/features/shell/working-message.ts +226 -0
- package/extensions/index.ts +52 -0
- package/extensions/shell/accent-rail-editor.ts +112 -0
- package/extensions/shell/accent-rail-layout-patch.ts +530 -0
- package/extensions/shell/completion-menu.ts +186 -0
- package/extensions/shell/editor-metadata-format.ts +287 -0
- package/extensions/shell/editor-transfer.ts +73 -0
- package/extensions/shell/extension-status.ts +102 -0
- package/extensions/shell/footer-format.ts +388 -0
- package/extensions/shell/footer-layout.ts +144 -0
- package/extensions/shell/footer.ts +1035 -0
- package/extensions/shell/format.ts +577 -0
- package/extensions/shell/git.ts +434 -0
- package/extensions/shell/icons.ts +261 -0
- package/extensions/shell/index.ts +1659 -0
- package/extensions/shell/interaction-summary.ts +1194 -0
- package/extensions/shell/live-context.ts +82 -0
- package/extensions/shell/minimalist-editor.ts +548 -0
- package/extensions/shell/package-version.ts +675 -0
- package/extensions/shell/project-refresh.ts +130 -0
- package/extensions/shell/project-state.ts +60 -0
- package/extensions/shell/prototype-patch-registry.ts +183 -0
- package/extensions/shell/runtime.ts +915 -0
- package/extensions/shell/selector-border.ts +109 -0
- package/extensions/shell/session-lifecycle.ts +60 -0
- package/extensions/shell/settings-command.ts +2144 -0
- package/extensions/shell/settings-previews.ts +137 -0
- package/extensions/shell/state.ts +83 -0
- package/extensions/shell/style.ts +480 -0
- package/extensions/shell/telemetry.ts +90 -0
- package/extensions/shell/ui.ts +1326 -0
- package/extensions/shell/user-message-osc.ts +279 -0
- package/extensions/shell/user-message-styles.ts +266 -0
- package/extensions/shell/user-message.ts +226 -0
- package/extensions/shell/working-line-messages.ts +24 -0
- package/extensions/shell/working-line-spinners.ts +54 -0
- package/extensions/shell/working-line.ts +1603 -0
- package/extensions/tools/ansi-color.ts +44 -0
- package/extensions/tools/ansi-text.ts +52 -0
- package/extensions/tools/component-tree.ts +37 -0
- package/extensions/tools/format.ts +28 -0
- package/extensions/tools/fullscreen-detect.ts +11 -0
- package/extensions/tools/patch-keys.ts +158 -0
- package/extensions/tools/sgr-mouse.ts +59 -0
- package/extensions/tools/tool-loading-icon.ts +20 -0
- package/extensions/tools/tool-result-sanitize.ts +27 -0
- package/extensions/transcript/index.ts +65 -0
- package/extensions/transcript/renderer/compact-mode.ts +1443 -0
- package/extensions/transcript/renderer/default-mode.ts +735 -0
- package/extensions/transcript/renderer/index.ts +286 -0
- package/extensions/transcript/renderer/markdown-enhance.ts +325 -0
- package/extensions/transcript/renderer/mouse/hover.ts +175 -0
- package/extensions/transcript/renderer/mouse/interaction.ts +1016 -0
- package/extensions/transcript/renderer/mouse/layout.ts +207 -0
- package/extensions/transcript/renderer/mouse/packets.ts +96 -0
- package/extensions/transcript/renderer/mouse/scroll.ts +211 -0
- package/extensions/transcript/renderer/tool/diff/ATTRIBUTION.md +28 -0
- package/extensions/transcript/renderer/tool/diff/ansi-utils.ts +128 -0
- package/extensions/transcript/renderer/tool/diff/diff-component.ts +112 -0
- package/extensions/transcript/renderer/tool/diff/diff-edit-render.ts +255 -0
- package/extensions/transcript/renderer/tool/diff/diff-header.ts +184 -0
- package/extensions/transcript/renderer/tool/diff/diff-highlight.ts +131 -0
- package/extensions/transcript/renderer/tool/diff/diff-inline.ts +350 -0
- package/extensions/transcript/renderer/tool/diff/diff-layout.ts +870 -0
- package/extensions/transcript/renderer/tool/diff/diff-limits.ts +189 -0
- package/extensions/transcript/renderer/tool/diff/diff-palette.ts +436 -0
- package/extensions/transcript/renderer/tool/diff/diff-parse.ts +536 -0
- package/extensions/transcript/renderer/tool/diff/diff-presentation.ts +79 -0
- package/extensions/transcript/renderer/tool/diff/diff-renderer.ts +29 -0
- package/extensions/transcript/renderer/tool/diff/diff-text.ts +57 -0
- package/extensions/transcript/renderer/tool/diff/diff-write-render.ts +629 -0
- package/extensions/transcript/renderer/tool/diff/index.ts +147 -0
- package/extensions/transcript/renderer/tool/diff/line-width-safety.ts +100 -0
- package/extensions/transcript/renderer/tool/diff/shiki-highlight.ts +104 -0
- package/extensions/transcript/renderer/tool/diff/write-execution.ts +124 -0
- package/extensions/transcript/renderer/tool/grouping.ts +619 -0
- package/extensions/transcript/renderer/tool/message-display.ts +183 -0
- package/extensions/transcript/renderer/tool/names.ts +195 -0
- package/extensions/transcript/renderer/tool/result.ts +842 -0
- package/extensions/transcript/renderer/tool/show-more-hint.ts +42 -0
- package/extensions/transcript/renderer/transcript-refresh.ts +79 -0
- package/package.json +58 -0
- package/themes/cc-dark.json +91 -0
- package/themes/cc-light.json +91 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Theme,
|
|
3
|
+
UserMessageComponent,
|
|
4
|
+
} from "@earendil-works/pi-coding-agent";
|
|
5
|
+
import { wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
6
|
+
import type { ZentuiConfig } from "../app/config/shell.ts";
|
|
7
|
+
import {
|
|
8
|
+
installPrototypePatch,
|
|
9
|
+
removePrototypePatch,
|
|
10
|
+
} from "./prototype-patch-registry.ts";
|
|
11
|
+
import {
|
|
12
|
+
sanitizeRenderedUserMessageLines,
|
|
13
|
+
sanitizeRenderedUserMessageText,
|
|
14
|
+
sanitizeUserMessageSourceText,
|
|
15
|
+
} from "./user-message-osc.ts";
|
|
16
|
+
import {
|
|
17
|
+
renderUserMessageStyle,
|
|
18
|
+
userMessageStyleCacheKey,
|
|
19
|
+
} from "./user-message-styles.ts";
|
|
20
|
+
|
|
21
|
+
const OSC133_ZONE_START = "\x1b]133;A\x07";
|
|
22
|
+
const OSC133_ZONE_END = "\x1b]133;B\x07";
|
|
23
|
+
const OSC133_ZONE_FINAL = "\x1b]133;C\x07";
|
|
24
|
+
|
|
25
|
+
type PatchableUserMessagePrototype = {
|
|
26
|
+
children?: unknown[];
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type Cleanup = () => void;
|
|
30
|
+
|
|
31
|
+
type UserMessageRenderCache = {
|
|
32
|
+
hasMarkdownText: boolean;
|
|
33
|
+
text?: string;
|
|
34
|
+
width?: number;
|
|
35
|
+
theme?: Theme;
|
|
36
|
+
configKey?: string;
|
|
37
|
+
renderedLines?: string[];
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const userMessageRenderCache = new WeakMap<object, UserMessageRenderCache>();
|
|
41
|
+
|
|
42
|
+
function isObject(value: unknown): value is object {
|
|
43
|
+
return (
|
|
44
|
+
(typeof value === "object" && value !== null) || typeof value === "function"
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
49
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function findMarkdownText(value: unknown): string | undefined {
|
|
53
|
+
if (!isRecord(value)) return undefined;
|
|
54
|
+
if (typeof value.text === "string") return value.text;
|
|
55
|
+
|
|
56
|
+
const children = value.children;
|
|
57
|
+
if (!Array.isArray(children)) return undefined;
|
|
58
|
+
|
|
59
|
+
for (const child of children) {
|
|
60
|
+
const text = findMarkdownText(child);
|
|
61
|
+
if (text !== undefined) return text;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function getCachedMarkdownText(instance: object): string | undefined {
|
|
68
|
+
const cached = userMessageRenderCache.get(instance);
|
|
69
|
+
if (cached?.hasMarkdownText) return cached.text;
|
|
70
|
+
|
|
71
|
+
const text = findMarkdownText(instance);
|
|
72
|
+
if (text !== undefined) {
|
|
73
|
+
userMessageRenderCache.set(instance, {
|
|
74
|
+
...cached,
|
|
75
|
+
hasMarkdownText: true,
|
|
76
|
+
text,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return text;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function renderZentuiUserMessage(
|
|
83
|
+
instance: PatchableUserMessagePrototype,
|
|
84
|
+
width: number,
|
|
85
|
+
theme: Theme | undefined,
|
|
86
|
+
config: ZentuiConfig,
|
|
87
|
+
): string[] | undefined {
|
|
88
|
+
if (!isRecord(instance)) return undefined;
|
|
89
|
+
|
|
90
|
+
const text = getCachedMarkdownText(instance);
|
|
91
|
+
if (text === undefined) return undefined;
|
|
92
|
+
const configKey = userMessageStyleCacheKey(config);
|
|
93
|
+
const cached = userMessageRenderCache.get(instance);
|
|
94
|
+
if (
|
|
95
|
+
cached?.hasMarkdownText &&
|
|
96
|
+
cached.width === width &&
|
|
97
|
+
cached.theme === theme &&
|
|
98
|
+
cached.configKey === configKey &&
|
|
99
|
+
cached.renderedLines
|
|
100
|
+
) {
|
|
101
|
+
return cached.renderedLines;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const lines = renderUserMessageStyle({
|
|
105
|
+
text,
|
|
106
|
+
width,
|
|
107
|
+
theme,
|
|
108
|
+
config,
|
|
109
|
+
});
|
|
110
|
+
userMessageRenderCache.set(instance, {
|
|
111
|
+
hasMarkdownText: true,
|
|
112
|
+
text,
|
|
113
|
+
width,
|
|
114
|
+
theme,
|
|
115
|
+
configKey,
|
|
116
|
+
renderedLines: lines,
|
|
117
|
+
});
|
|
118
|
+
return lines;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function withPromptZoneMarkers(lines: string[]): string[] {
|
|
122
|
+
if (lines.length === 1) {
|
|
123
|
+
return [
|
|
124
|
+
`${OSC133_ZONE_START}${lines[0]}${OSC133_ZONE_END}${OSC133_ZONE_FINAL}`,
|
|
125
|
+
];
|
|
126
|
+
}
|
|
127
|
+
const markedLines = [...lines];
|
|
128
|
+
markedLines[0] = OSC133_ZONE_START + markedLines[0];
|
|
129
|
+
markedLines[markedLines.length - 1] =
|
|
130
|
+
OSC133_ZONE_END + OSC133_ZONE_FINAL + markedLines[markedLines.length - 1];
|
|
131
|
+
return markedLines;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function sanitizePredecessorRender(result: unknown): unknown {
|
|
135
|
+
if (typeof result === "string")
|
|
136
|
+
return sanitizeRenderedUserMessageText(result);
|
|
137
|
+
if (!Array.isArray(result)) return result;
|
|
138
|
+
const stringRows = result.every(
|
|
139
|
+
(line): line is string => typeof line === "string",
|
|
140
|
+
);
|
|
141
|
+
if (stringRows) return sanitizeRenderedUserMessageLines(result);
|
|
142
|
+
return result.map((line) =>
|
|
143
|
+
typeof line === "string" ? sanitizeRenderedUserMessageText(line) : line,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function renderSafeSourceFallback(
|
|
148
|
+
instance: PatchableUserMessagePrototype,
|
|
149
|
+
width: number,
|
|
150
|
+
): string[] | undefined {
|
|
151
|
+
let text: string | undefined;
|
|
152
|
+
try {
|
|
153
|
+
text = isRecord(instance) ? getCachedMarkdownText(instance) : undefined;
|
|
154
|
+
} catch {
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
if (text === undefined) return undefined;
|
|
158
|
+
const stripped = sanitizeUserMessageSourceText(text);
|
|
159
|
+
if (stripped === text) return undefined;
|
|
160
|
+
const lines = (width > 0 ? wrapTextWithAnsi(stripped, width) : [""]).map(
|
|
161
|
+
sanitizeRenderedUserMessageText,
|
|
162
|
+
);
|
|
163
|
+
return withPromptZoneMarkers(lines.length > 0 ? lines : [""]);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function removeUserMessageStyle(): void {
|
|
167
|
+
const prototype = UserMessageComponent.prototype;
|
|
168
|
+
removePrototypePatch(prototype, "render", "user-message-render");
|
|
169
|
+
removePrototypePatch(prototype, "invalidate", "user-message-invalidate");
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function installUserMessageStyle(
|
|
173
|
+
getTheme: () => Theme | undefined,
|
|
174
|
+
getConfig: () => ZentuiConfig,
|
|
175
|
+
): Cleanup {
|
|
176
|
+
const prototype = UserMessageComponent.prototype;
|
|
177
|
+
const cleanupInvalidate = installPrototypePatch(
|
|
178
|
+
prototype,
|
|
179
|
+
"invalidate",
|
|
180
|
+
"user-message-invalidate",
|
|
181
|
+
({ predecessor, receiver, args }) => {
|
|
182
|
+
if (isObject(receiver)) userMessageRenderCache.delete(receiver);
|
|
183
|
+
return Reflect.apply(predecessor, receiver, args);
|
|
184
|
+
},
|
|
185
|
+
);
|
|
186
|
+
let cleanupRender: Cleanup;
|
|
187
|
+
try {
|
|
188
|
+
cleanupRender = installPrototypePatch(
|
|
189
|
+
prototype,
|
|
190
|
+
"render",
|
|
191
|
+
"user-message-render",
|
|
192
|
+
({ predecessor, receiver, args }) => {
|
|
193
|
+
const renderPredecessor = () =>
|
|
194
|
+
sanitizePredecessorRender(Reflect.apply(predecessor, receiver, args));
|
|
195
|
+
const width = args[0];
|
|
196
|
+
if (typeof width !== "number") return renderPredecessor();
|
|
197
|
+
try {
|
|
198
|
+
const lines = renderZentuiUserMessage(
|
|
199
|
+
receiver as PatchableUserMessagePrototype,
|
|
200
|
+
width,
|
|
201
|
+
getTheme(),
|
|
202
|
+
getConfig(),
|
|
203
|
+
);
|
|
204
|
+
if (!lines) return renderPredecessor();
|
|
205
|
+
return lines.length ? withPromptZoneMarkers(lines) : lines;
|
|
206
|
+
} catch {
|
|
207
|
+
const safeFallback = renderSafeSourceFallback(
|
|
208
|
+
receiver as PatchableUserMessagePrototype,
|
|
209
|
+
width,
|
|
210
|
+
);
|
|
211
|
+
return safeFallback ?? renderPredecessor();
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
);
|
|
215
|
+
} catch (error) {
|
|
216
|
+
cleanupInvalidate();
|
|
217
|
+
throw error;
|
|
218
|
+
}
|
|
219
|
+
let cleaned = false;
|
|
220
|
+
return () => {
|
|
221
|
+
if (cleaned) return;
|
|
222
|
+
cleaned = true;
|
|
223
|
+
cleanupRender();
|
|
224
|
+
cleanupInvalidate();
|
|
225
|
+
};
|
|
226
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** The built-in Working-line verb catalog, in display order. */
|
|
2
|
+
export const PI_WORKING_LINE_DEFAULT_PHRASES = [
|
|
3
|
+
"Sautéing",
|
|
4
|
+
"Cooking",
|
|
5
|
+
"Ionizing",
|
|
6
|
+
"Zigzagging",
|
|
7
|
+
"Razzle-dazzling",
|
|
8
|
+
"Photosynthesizing",
|
|
9
|
+
"Nucleating",
|
|
10
|
+
"Brewing",
|
|
11
|
+
"Combobulating",
|
|
12
|
+
"Boogieing",
|
|
13
|
+
"Befuddling",
|
|
14
|
+
"Alchemizing",
|
|
15
|
+
"Conjuring",
|
|
16
|
+
"Baking",
|
|
17
|
+
"Simmering",
|
|
18
|
+
"Blanching",
|
|
19
|
+
] as const;
|
|
20
|
+
|
|
21
|
+
/** Complete visible messages derived consistently from the built-in verb catalog. */
|
|
22
|
+
export const PI_WORKING_LINE_MESSAGES = PI_WORKING_LINE_DEFAULT_PHRASES.map(
|
|
23
|
+
(phrase) => `${phrase}…`,
|
|
24
|
+
);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { WorkingLineSpinner } from "../app/config/shell.ts";
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Pulse frames adapted from Funky UI's animations.ts:
|
|
5
|
+
* https://github.com/pi-zza/funky-ui/blob/e9aed319a4de61c2b2a5e99009821efa7b67b178/packages/funky-ui/extensions/funky-ui/animations.ts
|
|
6
|
+
* Frozen imported source revision:
|
|
7
|
+
* https://github.com/lmilojevicc/pi-zza/blob/37d82d565c1f5a9aa9b31d4b1711fa5604eb04a1/packages/funky-ui/extensions/funky-ui/animations.ts
|
|
8
|
+
*
|
|
9
|
+
* Funky UI's NOTICE states that the package combines Marko Nakic's Funky UI
|
|
10
|
+
* source with code derived from FammasMaz/pi-cc-tools, published as
|
|
11
|
+
* pi-claude-style-tools.
|
|
12
|
+
*
|
|
13
|
+
* MIT License
|
|
14
|
+
*
|
|
15
|
+
* Copyright (c) FammasMaz/pi-cc-tools contributors
|
|
16
|
+
* Copyright (c) 2026 Marko Nakic
|
|
17
|
+
*
|
|
18
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
19
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
20
|
+
* in the Software without restriction, including without limitation the rights
|
|
21
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
22
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
23
|
+
* furnished to do so, subject to the following conditions:
|
|
24
|
+
*
|
|
25
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
26
|
+
* copies or substantial portions of the Software.
|
|
27
|
+
*
|
|
28
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
29
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
30
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
31
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
32
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
33
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
34
|
+
* SOFTWARE.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/** Spinner definitions contain frames only; spinnerIntervalMs remains user-controlled. */
|
|
38
|
+
export const WORKING_LINE_SPINNERS = {
|
|
39
|
+
braille: {
|
|
40
|
+
frames: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
|
|
41
|
+
},
|
|
42
|
+
"star-bloom": {
|
|
43
|
+
frames: ["·", "✦", "✧", "✶", "✧", "✦"],
|
|
44
|
+
},
|
|
45
|
+
pinwheel: {
|
|
46
|
+
frames: ["-", "\\", "|", "/"],
|
|
47
|
+
},
|
|
48
|
+
"claude-inspired": {
|
|
49
|
+
frames: ["·", "✢", "✳", "✶", "✻", "✽"],
|
|
50
|
+
},
|
|
51
|
+
pulse: {
|
|
52
|
+
frames: ["⠀⠶⠀", "⠰⣿⠆", "⢾⣉⡷", "⣏⠀⣹", "⡁⠀⢈"],
|
|
53
|
+
},
|
|
54
|
+
} as const satisfies Record<WorkingLineSpinner, { frames: readonly string[] }>;
|