@ia-ccun/code-agent-cli 0.0.47-beta.6 → 0.0.47
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.
|
@@ -11,7 +11,7 @@ import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-age
|
|
|
11
11
|
const AICODE_TIPS = [
|
|
12
12
|
"@ 快速搜索项目文件",
|
|
13
13
|
"Ctrl+L 快速切换模型",
|
|
14
|
-
"Ctrl+P/Shift+Ctrl+P
|
|
14
|
+
"Ctrl+P/Shift+Ctrl+P 切换范围模型",
|
|
15
15
|
"Shift+Tab 切换思考级别",
|
|
16
16
|
"Ctrl+O 展开/折叠工具输出",
|
|
17
17
|
"Ctrl+T 展开/折叠思考块",
|
|
@@ -26,7 +26,7 @@ const AICODE_TIPS = [
|
|
|
26
26
|
"/copy 复制最后消息",
|
|
27
27
|
"/name 设置会话名称",
|
|
28
28
|
"/hotkeys 显示所有快捷键",
|
|
29
|
-
"/reload
|
|
29
|
+
"/reload 重新加载配置文件",
|
|
30
30
|
"/new 开始新会话",
|
|
31
31
|
"!cmd 执行 bash",
|
|
32
32
|
"!!cmd 执行bash但不发送给AI",
|
|
@@ -76,9 +76,17 @@ const AICODE_TIPS = [
|
|
|
76
76
|
"/btw 并行侧边对话,可在不中断主流程的情况下进行临时讨论或查询 ",
|
|
77
77
|
"/rewind 回退到任意工具执行前的状态,支持快照恢复和撤销重做 ",
|
|
78
78
|
"/mcp 连接现有的MCP服务器(如xx平台、企业微信等等),扩展AI能力支持多种外部工具和服务 ",
|
|
79
|
+
// 消息传递模式提示
|
|
80
|
+
"Enter 插话消息 - 在工具执行后立即发送,中断AI思考流程",
|
|
81
|
+
"Alt+Enter 排队消息 - 等待AI完全结束后发送,不中断AI工作",
|
|
82
|
+
"Escape 中断当前AI并恢复编辑器中的排队消息",
|
|
83
|
+
"Alt+Up 查看并编辑所有排队的消息",
|
|
84
|
+
"插话消息会打断AI正在执行的工具,等待响应",
|
|
85
|
+
"排队消息静默等待,AI空闲时自动发送",
|
|
86
|
+
"可在 /settings 中调整消息发送模式和行为偏好",
|
|
79
87
|
// 联系方式提示
|
|
80
|
-
"
|
|
81
|
-
"
|
|
88
|
+
"⚠️ 任何疑问或需求可联系 xujianjiang,支持需求对接开发、系统集成与扩展",
|
|
89
|
+
"⚠️ 内网手册参考 UniDoc《2026.03 AICode Agent CLI编码智能体使用手册》",
|
|
82
90
|
"⚠️ LLM API 4xx/5xx 错误时请确认模型配置是否正确,或在企微群咨询 jiangchi、maliang",
|
|
83
91
|
];
|
|
84
92
|
|
|
@@ -89,6 +97,16 @@ export default function (pi: ExtensionAPI) {
|
|
|
89
97
|
let currentCtx: ExtensionContext | undefined;
|
|
90
98
|
let isAutoPlaying = false;
|
|
91
99
|
|
|
100
|
+
// 基于 #49bccf (73, 188, 207) 的随机颜色生成
|
|
101
|
+
const getRandomTipColor = (): string => {
|
|
102
|
+
const baseR = 73, baseG = 188, baseB = 207;
|
|
103
|
+
const offset = 20; // 增大偏移范围,透明度降低
|
|
104
|
+
const r = Math.max(0, Math.min(255, baseR + Math.floor(Math.random() * offset * 2 - offset)));
|
|
105
|
+
const g = Math.max(0, Math.min(255, baseG + Math.floor(Math.random() * offset * 2 - offset)));
|
|
106
|
+
const b = Math.max(0, Math.min(255, baseB + Math.floor(Math.random() * offset * 2 - offset)));
|
|
107
|
+
return `\x1b[38;2;${r};${g};${b}m`;
|
|
108
|
+
};
|
|
109
|
+
|
|
92
110
|
const hideTip = () => {
|
|
93
111
|
if (!currentCtx?.hasUI) return;
|
|
94
112
|
currentCtx.ui.setWidget("aicode-tips", [], { placement: "aboveEditor" });
|
|
@@ -125,8 +143,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
125
143
|
}
|
|
126
144
|
currentTipIndex = randomIndex;
|
|
127
145
|
const tip = AICODE_TIPS[randomIndex];
|
|
128
|
-
//
|
|
129
|
-
const
|
|
146
|
+
// 使用随机颜色
|
|
147
|
+
const color = getRandomTipColor();
|
|
148
|
+
const coloredTip = `${color}tips: ${tip}\x1b[0m`;
|
|
130
149
|
currentCtx.ui.setWidget("aicode-tips", [coloredTip], { placement: "aboveEditor" });
|
|
131
150
|
|
|
132
151
|
// 自动轮播:10秒后隐藏,隐藏后3秒显示下一条
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @author: xujianjiang
|
|
5
5
|
*
|
|
6
|
-
* Logs errors to ./.aicode-cli/debug-logs/aicode-error.log
|
|
6
|
+
* Logs errors to ./.aicode-cli/debug-logs/aicode-error-YYYY-MM-DD.log
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
@@ -12,7 +12,44 @@ import path from "path";
|
|
|
12
12
|
|
|
13
13
|
// Error log file configuration
|
|
14
14
|
const ERROR_LOG_DIR = path.resolve(process.cwd(), "./.aicode-cli/debug-logs");
|
|
15
|
-
const
|
|
15
|
+
const KEEP_DAYS = 2; // 保留最近2天
|
|
16
|
+
|
|
17
|
+
// 北京时间格式化函数 (UTC+8)
|
|
18
|
+
function formatBeijingTime(date: Date = new Date()): string {
|
|
19
|
+
return date.toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 格式化为文件名日期字符串 (北京时间)
|
|
23
|
+
function getLogFileName(date: Date = new Date()): string {
|
|
24
|
+
const beijingDate = new Date(date.toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" }));
|
|
25
|
+
const year = beijingDate.getFullYear();
|
|
26
|
+
const month = String(beijingDate.getMonth() + 1).padStart(2, "0");
|
|
27
|
+
const day = String(beijingDate.getDate()).padStart(2, "0");
|
|
28
|
+
return `aicode-error-${year}-${month}-${day}.log`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 清理过期日志文件(保留最近 KEEP_DAYS 天)
|
|
32
|
+
function cleanOldLogs(): void {
|
|
33
|
+
if (!fs.existsSync(ERROR_LOG_DIR)) return;
|
|
34
|
+
|
|
35
|
+
const files = fs.readdirSync(ERROR_LOG_DIR);
|
|
36
|
+
const now = new Date(new Date().toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" }));
|
|
37
|
+
|
|
38
|
+
for (const file of files) {
|
|
39
|
+
if (!file.startsWith("aicode-error-") || !file.endsWith(".log")) continue;
|
|
40
|
+
|
|
41
|
+
// 从文件名提取日期
|
|
42
|
+
const match = file.match(/aicode-error-(\d{4})-(\d{2})-(\d{2})\.log/);
|
|
43
|
+
if (!match) continue;
|
|
44
|
+
|
|
45
|
+
const fileDate = new Date(parseInt(match[1]), parseInt(match[2]) - 1, parseInt(match[3]));
|
|
46
|
+
const diffDays = Math.floor((now.getTime() - fileDate.getTime()) / (1000 * 60 * 60 * 24));
|
|
47
|
+
|
|
48
|
+
if (diffDays > KEEP_DAYS) {
|
|
49
|
+
fs.unlinkSync(path.join(ERROR_LOG_DIR, file));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
16
53
|
|
|
17
54
|
// Ensure log directory exists
|
|
18
55
|
function ensureLogDir(): void {
|
|
@@ -27,13 +64,15 @@ function ensureLogDir(): void {
|
|
|
27
64
|
*/
|
|
28
65
|
function appendToErrorLog(message: string, context?: Record<string, unknown>): void {
|
|
29
66
|
ensureLogDir();
|
|
30
|
-
|
|
67
|
+
cleanOldLogs(); // 每次写日志时清理过期文件
|
|
68
|
+
const timestamp = formatBeijingTime();
|
|
69
|
+
const logFile = path.join(ERROR_LOG_DIR, getLogFileName());
|
|
31
70
|
let logEntry = `[${timestamp}] ${message}`;
|
|
32
71
|
if (context && Object.keys(context).length > 0) {
|
|
33
72
|
logEntry += `\nContext: ${JSON.stringify(context, null, 2)}`;
|
|
34
73
|
}
|
|
35
74
|
logEntry += "\n---\n";
|
|
36
|
-
fs.appendFileSync(
|
|
75
|
+
fs.appendFileSync(logFile, logEntry);
|
|
37
76
|
}
|
|
38
77
|
|
|
39
78
|
export default function (pi: ExtensionAPI) {
|
|
@@ -17,6 +17,20 @@ import { appendFileSync, existsSync, mkdirSync } from "node:fs";
|
|
|
17
17
|
import { join } from "node:path";
|
|
18
18
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
19
19
|
|
|
20
|
+
// 北京时间格式化函数 (UTC+8)
|
|
21
|
+
function formatBeijingTime(date: Date = new Date()): string {
|
|
22
|
+
return date.toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// 格式化为文件名日期字符串 (北京时间)
|
|
26
|
+
function formatDateStr(date: Date = new Date()): string {
|
|
27
|
+
const beijingDate = new Date(date.toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" }));
|
|
28
|
+
const year = beijingDate.getFullYear();
|
|
29
|
+
const month = String(beijingDate.getMonth() + 1).padStart(2, "0");
|
|
30
|
+
const day = String(beijingDate.getDate()).padStart(2, "0");
|
|
31
|
+
return `${year}-${month}-${day}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
20
34
|
export default function (pi: ExtensionAPI) {
|
|
21
35
|
// Create log directory in project root: ./.aicode-cli/debug-logs
|
|
22
36
|
const logDir = join(process.cwd(), ".aicode-cli", "debug-logs");
|
|
@@ -25,11 +39,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
25
39
|
}
|
|
26
40
|
|
|
27
41
|
// Format date as YYYY-MM-DD for daily log files
|
|
28
|
-
const
|
|
29
|
-
const year = today.getFullYear();
|
|
30
|
-
const month = String(today.getMonth() + 1).padStart(2, "0");
|
|
31
|
-
const day = String(today.getDate()).padStart(2, "0");
|
|
32
|
-
const dateStr = `${year}-${month}-${day}`;
|
|
42
|
+
const dateStr = formatDateStr();
|
|
33
43
|
const logFile = join(logDir, `llm-requests-${dateStr}.log`);
|
|
34
44
|
|
|
35
45
|
// Filter to only log user and assistant messages
|
|
@@ -69,7 +79,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
69
79
|
|
|
70
80
|
// Log before request is sent
|
|
71
81
|
pi.on("before_provider_request", (event) => {
|
|
72
|
-
const timestamp =
|
|
82
|
+
const timestamp = formatBeijingTime();
|
|
73
83
|
const { provider, model, payload } = event;
|
|
74
84
|
|
|
75
85
|
// Filter messages to only user and assistant
|
|
@@ -112,7 +122,7 @@ ${JSON.stringify({ ...payload, messages: filteredMessages }, null, 2)}
|
|
|
112
122
|
|
|
113
123
|
// Log after response is received
|
|
114
124
|
pi.on("after_provider_response", (event) => {
|
|
115
|
-
const timestamp =
|
|
125
|
+
const timestamp = formatBeijingTime();
|
|
116
126
|
const { response, usage, cached } = event;
|
|
117
127
|
|
|
118
128
|
const logEntry = `
|
|
@@ -150,7 +160,7 @@ ${JSON.stringify(response, null, 2)}
|
|
|
150
160
|
|
|
151
161
|
// Log request errors
|
|
152
162
|
pi.on("error", (event) => {
|
|
153
|
-
const timestamp =
|
|
163
|
+
const timestamp = formatBeijingTime();
|
|
154
164
|
const { error, context } = event;
|
|
155
165
|
|
|
156
166
|
const logEntry = `
|