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.
Files changed (101) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +106 -0
  3. package/extensions/app/config/renderer.ts +452 -0
  4. package/extensions/app/config/shell.ts +2484 -0
  5. package/extensions/app/ownership.ts +18 -0
  6. package/extensions/app/panel.ts +533 -0
  7. package/extensions/app/presets.ts +36 -0
  8. package/extensions/features/agent-summary/core.ts +194 -0
  9. package/extensions/features/agent-summary/index.ts +37 -0
  10. package/extensions/features/compact-thinking.ts +1262 -0
  11. package/extensions/features/context.ts +857 -0
  12. package/extensions/features/reference/index.ts +643 -0
  13. package/extensions/features/reference/session.ts +278 -0
  14. package/extensions/features/reference/subagent.ts +218 -0
  15. package/extensions/features/shell/aliases.ts +28 -0
  16. package/extensions/features/shell/flush-docked-bash.ts +39 -0
  17. package/extensions/features/shell/startup-header.ts +357 -0
  18. package/extensions/features/shell/working-message.ts +226 -0
  19. package/extensions/index.ts +52 -0
  20. package/extensions/shell/accent-rail-editor.ts +112 -0
  21. package/extensions/shell/accent-rail-layout-patch.ts +530 -0
  22. package/extensions/shell/completion-menu.ts +186 -0
  23. package/extensions/shell/editor-metadata-format.ts +287 -0
  24. package/extensions/shell/editor-transfer.ts +73 -0
  25. package/extensions/shell/extension-status.ts +102 -0
  26. package/extensions/shell/footer-format.ts +388 -0
  27. package/extensions/shell/footer-layout.ts +144 -0
  28. package/extensions/shell/footer.ts +1035 -0
  29. package/extensions/shell/format.ts +577 -0
  30. package/extensions/shell/git.ts +434 -0
  31. package/extensions/shell/icons.ts +261 -0
  32. package/extensions/shell/index.ts +1659 -0
  33. package/extensions/shell/interaction-summary.ts +1194 -0
  34. package/extensions/shell/live-context.ts +82 -0
  35. package/extensions/shell/minimalist-editor.ts +548 -0
  36. package/extensions/shell/package-version.ts +675 -0
  37. package/extensions/shell/project-refresh.ts +130 -0
  38. package/extensions/shell/project-state.ts +60 -0
  39. package/extensions/shell/prototype-patch-registry.ts +183 -0
  40. package/extensions/shell/runtime.ts +915 -0
  41. package/extensions/shell/selector-border.ts +109 -0
  42. package/extensions/shell/session-lifecycle.ts +60 -0
  43. package/extensions/shell/settings-command.ts +2144 -0
  44. package/extensions/shell/settings-previews.ts +137 -0
  45. package/extensions/shell/state.ts +83 -0
  46. package/extensions/shell/style.ts +480 -0
  47. package/extensions/shell/telemetry.ts +90 -0
  48. package/extensions/shell/ui.ts +1326 -0
  49. package/extensions/shell/user-message-osc.ts +279 -0
  50. package/extensions/shell/user-message-styles.ts +266 -0
  51. package/extensions/shell/user-message.ts +226 -0
  52. package/extensions/shell/working-line-messages.ts +24 -0
  53. package/extensions/shell/working-line-spinners.ts +54 -0
  54. package/extensions/shell/working-line.ts +1603 -0
  55. package/extensions/tools/ansi-color.ts +44 -0
  56. package/extensions/tools/ansi-text.ts +52 -0
  57. package/extensions/tools/component-tree.ts +37 -0
  58. package/extensions/tools/format.ts +28 -0
  59. package/extensions/tools/fullscreen-detect.ts +11 -0
  60. package/extensions/tools/patch-keys.ts +158 -0
  61. package/extensions/tools/sgr-mouse.ts +59 -0
  62. package/extensions/tools/tool-loading-icon.ts +20 -0
  63. package/extensions/tools/tool-result-sanitize.ts +27 -0
  64. package/extensions/transcript/index.ts +65 -0
  65. package/extensions/transcript/renderer/compact-mode.ts +1443 -0
  66. package/extensions/transcript/renderer/default-mode.ts +735 -0
  67. package/extensions/transcript/renderer/index.ts +286 -0
  68. package/extensions/transcript/renderer/markdown-enhance.ts +325 -0
  69. package/extensions/transcript/renderer/mouse/hover.ts +175 -0
  70. package/extensions/transcript/renderer/mouse/interaction.ts +1016 -0
  71. package/extensions/transcript/renderer/mouse/layout.ts +207 -0
  72. package/extensions/transcript/renderer/mouse/packets.ts +96 -0
  73. package/extensions/transcript/renderer/mouse/scroll.ts +211 -0
  74. package/extensions/transcript/renderer/tool/diff/ATTRIBUTION.md +28 -0
  75. package/extensions/transcript/renderer/tool/diff/ansi-utils.ts +128 -0
  76. package/extensions/transcript/renderer/tool/diff/diff-component.ts +112 -0
  77. package/extensions/transcript/renderer/tool/diff/diff-edit-render.ts +255 -0
  78. package/extensions/transcript/renderer/tool/diff/diff-header.ts +184 -0
  79. package/extensions/transcript/renderer/tool/diff/diff-highlight.ts +131 -0
  80. package/extensions/transcript/renderer/tool/diff/diff-inline.ts +350 -0
  81. package/extensions/transcript/renderer/tool/diff/diff-layout.ts +870 -0
  82. package/extensions/transcript/renderer/tool/diff/diff-limits.ts +189 -0
  83. package/extensions/transcript/renderer/tool/diff/diff-palette.ts +436 -0
  84. package/extensions/transcript/renderer/tool/diff/diff-parse.ts +536 -0
  85. package/extensions/transcript/renderer/tool/diff/diff-presentation.ts +79 -0
  86. package/extensions/transcript/renderer/tool/diff/diff-renderer.ts +29 -0
  87. package/extensions/transcript/renderer/tool/diff/diff-text.ts +57 -0
  88. package/extensions/transcript/renderer/tool/diff/diff-write-render.ts +629 -0
  89. package/extensions/transcript/renderer/tool/diff/index.ts +147 -0
  90. package/extensions/transcript/renderer/tool/diff/line-width-safety.ts +100 -0
  91. package/extensions/transcript/renderer/tool/diff/shiki-highlight.ts +104 -0
  92. package/extensions/transcript/renderer/tool/diff/write-execution.ts +124 -0
  93. package/extensions/transcript/renderer/tool/grouping.ts +619 -0
  94. package/extensions/transcript/renderer/tool/message-display.ts +183 -0
  95. package/extensions/transcript/renderer/tool/names.ts +195 -0
  96. package/extensions/transcript/renderer/tool/result.ts +842 -0
  97. package/extensions/transcript/renderer/tool/show-more-hint.ts +42 -0
  98. package/extensions/transcript/renderer/transcript-refresh.ts +79 -0
  99. package/package.json +58 -0
  100. package/themes/cc-dark.json +91 -0
  101. package/themes/cc-light.json +91 -0
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Agent 回合摘要:统计一次 agent 运行的工具使用并格式化成摘要文本。
3
+ *
4
+ * 分类:bash / read / edit / write / other(精确工具名;MCP 风格名归 other)。
5
+ * 计数:bash/powershell 按调用次数;read/edit/write 按非空 path/file_path 去重;other 按调用次数。
6
+ * 失败单独累计;另记回合耗时。
7
+ *
8
+ * 呈现:`summaryLine` 纯文本,`summaryMarkdown` Markdown(可 box 引用块)。
9
+ */
10
+
11
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
12
+ import { formatDuration } from "../../tools/format.ts";
13
+ export { formatDuration };
14
+
15
+ /** 工具分类。 */
16
+ export type AgentToolCategory = "bash" | "read" | "edit" | "write" | "other";
17
+
18
+ /** 一次 agent 回合的统计快照。 */
19
+ export type AgentSummaryData = {
20
+ commands: number;
21
+ reads: number;
22
+ edits: number;
23
+ writes: number;
24
+ others: number;
25
+ failed: number;
26
+ durationMs: number;
27
+ };
28
+
29
+ export function classifyTool(toolName: string): AgentToolCategory {
30
+ const base = toolName.split(".").pop() ?? toolName;
31
+ if (base === "bash" || base === "powershell") return "bash";
32
+ if (base === "read") return "read";
33
+ if (base === "edit") return "edit";
34
+ if (base === "write") return "write";
35
+ return "other";
36
+ }
37
+
38
+ function nonEmptyString(value: unknown): value is string {
39
+ return typeof value === "string" && value.length > 0;
40
+ }
41
+
42
+ function toolPath(args?: Record<string, unknown> | null): string | undefined {
43
+ const path = args?.path ?? args?.file_path;
44
+ return nonEmptyString(path) ? path : undefined;
45
+ }
46
+
47
+ /** 累积一次 agent 回合的工具统计;agent_start 时新建实例。 */
48
+ export class AgentRunSummary {
49
+ toolCount = 0;
50
+ commandCount = 0;
51
+ readFiles = new Set<string>();
52
+ editFiles = new Set<string>();
53
+ writeFiles = new Set<string>();
54
+ otherCount = 0;
55
+ failedCount = 0;
56
+
57
+ readonly startedAt: number;
58
+
59
+ constructor(startedAt = Date.now()) {
60
+ this.startedAt = startedAt;
61
+ }
62
+
63
+ /** tool_execution_start 时调用。 */
64
+ recordToolStart(
65
+ toolName: string,
66
+ args?: Record<string, unknown> | null,
67
+ ): void {
68
+ this.toolCount++;
69
+ const path = toolPath(args);
70
+ switch (classifyTool(toolName)) {
71
+ case "bash":
72
+ this.commandCount++;
73
+ break;
74
+ case "read":
75
+ if (path) this.readFiles.add(path);
76
+ break;
77
+ case "edit":
78
+ if (path) this.editFiles.add(path);
79
+ break;
80
+ case "write":
81
+ if (path) this.writeFiles.add(path);
82
+ break;
83
+ default:
84
+ this.otherCount++;
85
+ }
86
+ }
87
+
88
+ /** tool_execution_end 时调用;isError 为 true 计入失败。 */
89
+ recordToolResult(isError: boolean): void {
90
+ if (isError) this.failedCount++;
91
+ }
92
+
93
+ snapshot(now = Date.now()): AgentSummaryData {
94
+ return {
95
+ commands: this.commandCount,
96
+ reads: this.readFiles.size,
97
+ edits: this.editFiles.size,
98
+ writes: this.writeFiles.size,
99
+ others: this.otherCount,
100
+ failed: this.failedCount,
101
+ durationMs: now - this.startedAt,
102
+ };
103
+ }
104
+ }
105
+
106
+ const plural = (count: number) => (count === 1 ? "" : "s");
107
+
108
+ /** 输出顺序:bash → read → edit → write → other → failed。 */
109
+ function summaryParts(data: AgentSummaryData): string[] {
110
+ const parts: string[] = [];
111
+ if (data.commands)
112
+ parts.push(`ran ${data.commands} command${plural(data.commands)}`);
113
+ if (data.reads) parts.push(`read ${data.reads} file${plural(data.reads)}`);
114
+ if (data.edits) parts.push(`edited ${data.edits} file${plural(data.edits)}`);
115
+ if (data.writes)
116
+ parts.push(`wrote ${data.writes} file${plural(data.writes)}`);
117
+ if (data.others)
118
+ parts.push(`${data.others} other tool${plural(data.others)}`);
119
+ if (data.failed) parts.push(`${data.failed} failed`);
120
+ return parts;
121
+ }
122
+
123
+ /** 纯文本摘要行:句首大写 + 可选耗时。 */
124
+ export function summaryLine(data: AgentSummaryData): string {
125
+ const parts = summaryParts(data);
126
+ if (parts.length === 0) return "";
127
+ const text = parts.join(", ");
128
+ const capitalized = text[0].toUpperCase() + text.slice(1);
129
+ const duration = formatDuration(data.durationMs);
130
+ return duration ? `${capitalized} · ${duration}` : capitalized;
131
+ }
132
+
133
+ /**
134
+ * Markdown 摘要行。
135
+ * `box` 为 true:引用块 `> *斜体*`;false:整体加粗。
136
+ * `colors`:仅数字染色(success / failed)。
137
+ */
138
+ export function summaryMarkdown(
139
+ data: AgentSummaryData,
140
+ box = false,
141
+ colors: { success: string; failed: string } = { success: "", failed: "" },
142
+ ): string {
143
+ const parts = summaryParts(data);
144
+ if (parts.length === 0) return "";
145
+ const capitalizeFirst = (part: string, first: boolean) => {
146
+ const verb = part.match(/^[a-z]+/)?.[0] ?? "";
147
+ return first && verb
148
+ ? verb[0].toUpperCase() + verb.slice(1) + part.slice(verb.length)
149
+ : part;
150
+ };
151
+ const paintNumber = (code: string, part: string) =>
152
+ code ? part.replace(/(\d+)/, `${code}$1\x1b[0m`) : part;
153
+ const text = parts
154
+ .map((part, index) => capitalizeFirst(part, index === 0))
155
+ .map((part) =>
156
+ paintNumber(
157
+ part.endsWith("failed") ? colors.failed : colors.success,
158
+ part,
159
+ ),
160
+ )
161
+ .join(", ");
162
+ const duration = formatDuration(data.durationMs);
163
+ const line = duration ? `${text} · ${duration}` : text;
164
+ return box ? `> *${line}*` : `**${line}**`;
165
+ }
166
+
167
+ /**
168
+ * 绑定 pi 事件到摘要统计:
169
+ * - agent_start 重置
170
+ * - tool_execution_start / end 累计
171
+ * - agent_end 回调(toolCount < minToolCount 跳过)
172
+ */
173
+ export function bindAgentSummary(
174
+ pi: ExtensionAPI,
175
+ onSummary: (data: AgentSummaryData) => void,
176
+ minToolCount = 2,
177
+ ): () => void {
178
+ let summary = new AgentRunSummary();
179
+ pi.on("agent_start", async () => {
180
+ summary = new AgentRunSummary();
181
+ });
182
+ pi.on("tool_execution_start", async (event) => {
183
+ summary.recordToolStart(event.toolName, event.args);
184
+ });
185
+ pi.on("tool_execution_end", async (event) => {
186
+ summary.recordToolResult(event.isError === true);
187
+ });
188
+ pi.on("agent_end", async () => {
189
+ if (summary.toolCount >= minToolCount) onSummary(summary.snapshot());
190
+ });
191
+ return () => {
192
+ summary = new AgentRunSummary();
193
+ };
194
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Agent 回合摘要展示:agent_end 时把本回合工具统计写入会话条目,
3
+ * 由 entry renderer 渲染为 markdown 引用块 `> [!TIP] *斜体内容*`。
4
+ *
5
+ * 统计复用 ./core.ts(bash|powershell/read/edit/write/other)。
6
+ * appendEntry 不进 LLM 上下文,只显示在聊天区。
7
+ * 引用块文字色取主题 mdQuote(cc 主题下为 muted 灰),内容用 *斜体* 语法。
8
+ */
9
+
10
+ import { Markdown } from "@earendil-works/pi-tui";
11
+ import { getMarkdownTheme } from "@earendil-works/pi-coding-agent";
12
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
13
+ import {
14
+ bindAgentSummary,
15
+ summaryMarkdown,
16
+ type AgentSummaryData,
17
+ } from "./core.ts";
18
+
19
+ export const AGENT_SUMMARY_ENTRY_TYPE = "agent-summary";
20
+
21
+ export default function (pi: ExtensionAPI): void {
22
+ pi.registerEntryRenderer(
23
+ AGENT_SUMMARY_ENTRY_TYPE,
24
+ (entry, _options, theme) => {
25
+ const line = summaryMarkdown(entry.data as AgentSummaryData, true, {
26
+ success: theme.getFgAnsi("success"),
27
+ failed: theme.getFgAnsi("error"),
28
+ });
29
+ if (!line) return undefined;
30
+ return new Markdown(line, 1, 0, getMarkdownTheme());
31
+ },
32
+ );
33
+
34
+ bindAgentSummary(pi, (data) => {
35
+ pi.appendEntry(AGENT_SUMMARY_ENTRY_TYPE, data);
36
+ });
37
+ }