@tomsun28/pizza 0.0.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.
@@ -0,0 +1,131 @@
1
+ import type { AgentEvent } from "@mariozechner/pi-agent-core";
2
+
3
+ // ANSI color helpers
4
+ const dim = (s: string) => `\x1b[2m${s}\x1b[0m`;
5
+ const bold = (s: string) => `\x1b[1m${s}\x1b[0m`;
6
+ const green = (s: string) => `\x1b[32m${s}\x1b[0m`;
7
+ const yellow = (s: string) => `\x1b[33m${s}\x1b[0m`;
8
+ const cyan = (s: string) => `\x1b[36m${s}\x1b[0m`;
9
+ const red = (s: string) => `\x1b[31m${s}\x1b[0m`;
10
+ const magenta = (s: string) => `\x1b[35m${s}\x1b[0m`;
11
+
12
+ export function createRenderer(): (event: AgentEvent) => void {
13
+ let currentToolName: string | undefined;
14
+ let isFirstTextDelta = true;
15
+
16
+ return (event: AgentEvent) => {
17
+ switch (event.type) {
18
+ case "agent_start":
19
+ isFirstTextDelta = true;
20
+ break;
21
+
22
+ case "message_update": {
23
+ const e = event.assistantMessageEvent;
24
+ if (e.type === "text_delta") {
25
+ if (isFirstTextDelta) {
26
+ process.stdout.write("\n");
27
+ isFirstTextDelta = false;
28
+ }
29
+ process.stdout.write(e.delta);
30
+ } else if (e.type === "thinking_delta") {
31
+ process.stdout.write(dim(e.delta));
32
+ }
33
+ break;
34
+ }
35
+
36
+ case "message_end": {
37
+ const msg = event.message;
38
+ if (msg.role === "assistant") {
39
+ // Check if the message had text content
40
+ const hasText = Array.isArray(msg.content)
41
+ && msg.content.some((c: any) => c.type === "text" && c.text?.trim());
42
+ if (hasText) {
43
+ process.stdout.write("\n");
44
+ }
45
+ }
46
+ break;
47
+ }
48
+
49
+ case "tool_execution_start":
50
+ currentToolName = event.toolName;
51
+ process.stdout.write(`\n${cyan(">")} ${bold(event.toolName)}`);
52
+ if (event.toolName === "bash") {
53
+ const cmd = (event.args as any)?.command;
54
+ if (cmd) process.stdout.write(` ${yellow(cmd)}`);
55
+ } else if (event.toolName === "read") {
56
+ const path = (event.args as any)?.path;
57
+ if (path) process.stdout.write(` ${magenta(path)}`);
58
+ } else if (event.toolName === "write") {
59
+ const path = (event.args as any)?.path;
60
+ if (path) process.stdout.write(` ${magenta(path)}`);
61
+ } else if (event.toolName === "edit") {
62
+ const path = (event.args as any)?.path;
63
+ if (path) process.stdout.write(` ${magenta(path)}`);
64
+ } else if (event.toolName === "ls") {
65
+ const path = (event.args as any)?.path || ".";
66
+ process.stdout.write(` ${magenta(path)}`);
67
+ } else if (event.toolName === "grep") {
68
+ const pattern = (event.args as any)?.pattern;
69
+ if (pattern) process.stdout.write(` ${yellow(pattern)}`);
70
+ }
71
+ process.stdout.write("\n");
72
+ break;
73
+
74
+ case "tool_execution_end": {
75
+ const resultText = event.result?.content
76
+ ?.filter((c: any) => c.type === "text")
77
+ .map((c: any) => c.text)
78
+ .join("\n") ?? "";
79
+
80
+ if (event.isError) {
81
+ const preview = truncatePreview(resultText, 5);
82
+ process.stdout.write(`${red(preview)}\n`);
83
+ } else {
84
+ const preview = truncatePreview(resultText, 8);
85
+ if (preview) {
86
+ process.stdout.write(`${dim(preview)}\n`);
87
+ }
88
+ }
89
+ currentToolName = undefined;
90
+ isFirstTextDelta = true;
91
+ break;
92
+ }
93
+
94
+ case "agent_end": {
95
+ // Show cost/token info if available
96
+ const messages = event.messages;
97
+ const assistantMsgs = messages.filter((m: any) => m.role === "assistant" && m.usage);
98
+ if (assistantMsgs.length > 0) {
99
+ let totalInput = 0;
100
+ let totalOutput = 0;
101
+ let totalCost = 0;
102
+ for (const m of assistantMsgs) {
103
+ const usage = (m as any).usage;
104
+ if (usage) {
105
+ totalInput += usage.input || 0;
106
+ totalOutput += usage.output || 0;
107
+ totalCost += usage.cost?.total || 0;
108
+ }
109
+ }
110
+ if (totalInput > 0 || totalOutput > 0) {
111
+ process.stdout.write(
112
+ dim(`\n[tokens: ${totalInput}→${totalOutput}` +
113
+ (totalCost > 0 ? ` | $${totalCost.toFixed(4)}` : "") +
114
+ `]\n`)
115
+ );
116
+ }
117
+ }
118
+ break;
119
+ }
120
+ }
121
+ };
122
+ }
123
+
124
+ function truncatePreview(text: string, maxLines: number): string {
125
+ if (!text) return "";
126
+ const lines = text.split("\n");
127
+ if (lines.length <= maxLines) return text;
128
+ const shown = lines.slice(0, maxLines);
129
+ const remaining = lines.length - maxLines;
130
+ return shown.join("\n") + `\n... (${remaining} more lines)`;
131
+ }
@@ -0,0 +1,55 @@
1
+ 你是一个命令行助手,运行在用户的终端环境中,帮助用户完成各类软件工程任务。
2
+
3
+ 当你需要执行命令时,使用 [CLI]命令[/CLI] 格式。你可以在一次回复中执行多个命令。执行结果会以 [RESULT]...[/RESULT] 返回。
4
+
5
+ ## 示例
6
+
7
+ 用户:项目结构是什么样的?package.json 里有哪些依赖?
8
+
9
+ 助手:看一下项目结构和依赖。
10
+
11
+ [CLI]ls -la /Users/user/project[/CLI]
12
+ [CLI]cat /Users/user/project/package.json[/CLI]
13
+
14
+ [RESULT id=1]
15
+ total 24
16
+ drwxr-xr-x 5 user staff 160 Mar 26 10:00 .
17
+ drwxr-xr-x 10 user staff 320 Mar 26 09:00 ..
18
+ drwxr-xr-x 3 user staff 96 Mar 26 10:00 src
19
+ -rw-r--r-- 1 user staff 256 Mar 26 10:00 package.json
20
+ -rw-r--r-- 1 user staff 128 Mar 26 09:30 tsconfig.json
21
+ [/RESULT]
22
+
23
+ [RESULT id=2]
24
+ {
25
+ "name": "my-app",
26
+ "dependencies": {
27
+ "express": "^4.18.0"
28
+ },
29
+ "devDependencies": {
30
+ "typescript": "^5.0.0"
31
+ }
32
+ }
33
+ [/RESULT]
34
+
35
+ 项目包含 src 目录和两个配置文件。依赖了 express 和 typescript。
36
+
37
+ 用户:构建一下项目,同时检查有没有 lint 错误
38
+
39
+ 助手:
40
+
41
+ [CLI]cd /Users/user/project && npm run build[/CLI]
42
+ [CLI]cd /Users/user/project && npm run lint[/CLI]
43
+
44
+ [RESULT id=1]
45
+ Successfully compiled 3 files.
46
+ [/RESULT]
47
+
48
+ [RESULT id=2]
49
+ /Users/user/project/src/index.ts
50
+ 12:5 warning Unexpected console statement no-console
51
+
52
+ ✖ 1 problem (0 errors, 1 warning)
53
+ [/RESULT]
54
+
55
+ 构建成功。lint 有一个警告:src/index.ts 第 12 行有个 console 语句。
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "Node16",
5
+ "moduleResolution": "Node16",
6
+ "outDir": "dist",
7
+ "rootDir": "src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "declaration": true,
12
+ "sourceMap": true
13
+ },
14
+ "include": ["src/**/*"]
15
+ }