@ia-ccun/code-agent-cli 0.0.3 → 0.0.4-8.beta.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/README.md +92 -11
- package/bin/cli.js +212 -59
- package/config/agent/APPEND_SYSTEM.md +46 -5
- package/config/agent/bin/fd +0 -0
- package/config/agent/bin/rg +0 -0
- package/config/agent/dangerous-patterns.json +106 -0
- package/config/agent/extensions/aicode-tips.ts +191 -0
- package/config/agent/extensions/bash-check.ts +227 -0
- package/config/agent/extensions/context-monitor.ts +275 -0
- package/config/agent/extensions/context.ts +1 -0
- package/config/agent/extensions/custom-footer.ts +33 -2
- package/config/agent/extensions/custom.ts +24 -91
- package/config/agent/extensions/error-monitor.ts +142 -0
- package/config/agent/extensions/msg-debug.ts +185 -0
- package/config/agent/extensions/review.ts +4 -0
- package/config/agent/extensions/working-msg.ts +39 -20
- package/config/agent/mcp.json +4 -0
- package/config/agent/models.json +16 -43
- package/config/agent/prompts/code-simplifier.md +51 -0
- package/config/agent/prompts/feat.md +2 -2
- package/config/agent/prompts/git-commit.md +9 -15
- package/config/agent/prompts/init-project.md +2 -1
- package/config/agent/prompts/workflow.md +3 -2
- package/config/agent/settings.json +17 -5
- package/config/agent/skills/brainstorming/SKILL.md +167 -0
- package/config/agent/skills/brainstorming/scripts/frame-template.html +214 -0
- package/config/agent/skills/brainstorming/scripts/helper.js +88 -0
- package/config/agent/skills/brainstorming/scripts/server.cjs +338 -0
- package/config/agent/skills/brainstorming/scripts/start-server.sh +153 -0
- package/config/agent/skills/brainstorming/scripts/stop-server.sh +55 -0
- package/config/agent/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
- package/config/agent/skills/brainstorming/visual-companion.md +286 -0
- package/config/agent/skills/code-review/SKILL.md +4 -2
- package/config/agent/skills/commit/SKILL.md +10 -5
- package/config/agent/skills/csv-data-summarizer/SKILL.md +2 -1
- package/config/agent/skills/design-md/README.md +34 -0
- package/config/agent/skills/design-md/SKILL.md +172 -0
- package/config/agent/skills/design-md/examples/DESIGN.md +154 -0
- package/config/agent/skills/dispatching-parallel-agents/SKILL.md +185 -0
- package/config/agent/skills/executing-plans/SKILL.md +73 -0
- package/config/agent/skills/find-skills/SKILL.md +5 -1
- package/config/agent/skills/finishing-a-development-branch/SKILL.md +204 -0
- package/config/agent/skills/fireworks-tech-graph/LICENSE +21 -0
- package/config/agent/skills/fireworks-tech-graph/README.md +528 -0
- package/config/agent/skills/fireworks-tech-graph/README.zh.md +499 -0
- package/config/agent/skills/fireworks-tech-graph/SKILL.md +537 -0
- package/config/agent/skills/fireworks-tech-graph/agentloop-core.svg +101 -0
- package/config/agent/skills/fireworks-tech-graph/agents/openai.yaml +4 -0
- package/config/agent/skills/fireworks-tech-graph/assets/samples/sample-style1-flat.png +0 -0
- package/config/agent/skills/fireworks-tech-graph/assets/samples/sample-style2-dark.png +0 -0
- package/config/agent/skills/fireworks-tech-graph/assets/samples/sample-style3-blueprint.png +0 -0
- package/config/agent/skills/fireworks-tech-graph/assets/samples/sample-style4-notion.png +0 -0
- package/config/agent/skills/fireworks-tech-graph/assets/samples/sample-style5-glass.png +0 -0
- package/config/agent/skills/fireworks-tech-graph/assets/samples/sample-style6-claude.png +0 -0
- package/config/agent/skills/fireworks-tech-graph/assets/samples/sample-style7-openai.png +0 -0
- package/config/agent/skills/fireworks-tech-graph/fixtures/agent-memory-types-style4.json +181 -0
- package/config/agent/skills/fireworks-tech-graph/fixtures/api-flow-style7.json +40 -0
- package/config/agent/skills/fireworks-tech-graph/fixtures/mem0-style1.json +297 -0
- package/config/agent/skills/fireworks-tech-graph/fixtures/microservices-style3.json +64 -0
- package/config/agent/skills/fireworks-tech-graph/fixtures/multi-agent-style5.json +45 -0
- package/config/agent/skills/fireworks-tech-graph/fixtures/system-architecture-style6.json +48 -0
- package/config/agent/skills/fireworks-tech-graph/fixtures/tool-call-style2.json +182 -0
- package/config/agent/skills/fireworks-tech-graph/package.json +42 -0
- package/config/agent/skills/fireworks-tech-graph/references/icons.md +406 -0
- package/config/agent/skills/fireworks-tech-graph/references/style-1-flat-icon.md +108 -0
- package/config/agent/skills/fireworks-tech-graph/references/style-2-dark-terminal.md +107 -0
- package/config/agent/skills/fireworks-tech-graph/references/style-3-blueprint.md +113 -0
- package/config/agent/skills/fireworks-tech-graph/references/style-4-notion-clean.md +94 -0
- package/config/agent/skills/fireworks-tech-graph/references/style-5-glassmorphism.md +125 -0
- package/config/agent/skills/fireworks-tech-graph/references/style-6-claude-official.md +209 -0
- package/config/agent/skills/fireworks-tech-graph/references/style-7-openai.md +215 -0
- package/config/agent/skills/fireworks-tech-graph/references/style-diagram-matrix.md +135 -0
- package/config/agent/skills/fireworks-tech-graph/references/svg-layout-best-practices.md +100 -0
- package/config/agent/skills/fireworks-tech-graph/scripts/README.md +244 -0
- package/config/agent/skills/fireworks-tech-graph/scripts/generate-diagram.sh +157 -0
- package/config/agent/skills/fireworks-tech-graph/scripts/generate-from-template.py +1556 -0
- package/config/agent/skills/fireworks-tech-graph/scripts/test-all-styles.sh +135 -0
- package/config/agent/skills/fireworks-tech-graph/scripts/validate-svg.sh +292 -0
- package/config/agent/skills/fireworks-tech-graph/templates/agent-architecture.svg +28 -0
- package/config/agent/skills/fireworks-tech-graph/templates/architecture.svg +23 -0
- package/config/agent/skills/fireworks-tech-graph/templates/comparison-matrix.svg +14 -0
- package/config/agent/skills/fireworks-tech-graph/templates/data-flow.svg +28 -0
- package/config/agent/skills/fireworks-tech-graph/templates/er-diagram.svg +21 -0
- package/config/agent/skills/fireworks-tech-graph/templates/flowchart.svg +21 -0
- package/config/agent/skills/fireworks-tech-graph/templates/sequence.svg +20 -0
- package/config/agent/skills/fireworks-tech-graph/templates/state-machine.svg +20 -0
- package/config/agent/skills/fireworks-tech-graph/templates/timeline.svg +19 -0
- package/config/agent/skills/fireworks-tech-graph/templates/use-case.svg +21 -0
- package/config/agent/skills/frontend-design/SKILL.md +4 -1
- package/config/agent/skills/hello/SKILL.md +5 -2
- package/config/agent/skills/impeccable/adapt/SKILL.md +204 -0
- package/config/agent/skills/impeccable/animate/SKILL.md +177 -0
- package/config/agent/skills/impeccable/arrange/SKILL.md +127 -0
- package/config/agent/skills/impeccable/audit/SKILL.md +128 -0
- package/config/agent/skills/impeccable/bolder/SKILL.md +119 -0
- package/config/agent/skills/impeccable/clarify/SKILL.md +185 -0
- package/config/agent/skills/impeccable/colorize/SKILL.md +145 -0
- package/config/agent/skills/impeccable/critique/SKILL.md +122 -0
- package/config/agent/skills/impeccable/delight/SKILL.md +306 -0
- package/config/agent/skills/impeccable/distill/SKILL.md +124 -0
- package/config/agent/skills/impeccable/extract/SKILL.md +94 -0
- package/config/agent/skills/impeccable/frontend-design/reference/color-and-contrast.md +132 -0
- package/config/agent/skills/impeccable/frontend-design/reference/interaction-design.md +123 -0
- package/config/agent/skills/impeccable/frontend-design/reference/motion-design.md +99 -0
- package/config/agent/skills/impeccable/frontend-design/reference/responsive-design.md +114 -0
- package/config/agent/skills/impeccable/frontend-design/reference/spatial-design.md +100 -0
- package/config/agent/skills/impeccable/frontend-design/reference/typography.md +133 -0
- package/config/agent/skills/impeccable/frontend-design/reference/ux-writing.md +107 -0
- package/config/agent/skills/impeccable/harden/SKILL.md +357 -0
- package/config/agent/skills/impeccable/normalize/SKILL.md +73 -0
- package/config/agent/skills/impeccable/onboard/SKILL.md +248 -0
- package/config/agent/skills/impeccable/optimize/SKILL.md +268 -0
- package/config/agent/skills/impeccable/overdrive/SKILL.md +144 -0
- package/config/agent/skills/impeccable/polish/SKILL.md +205 -0
- package/config/agent/skills/impeccable/quieter/SKILL.md +105 -0
- package/config/agent/skills/impeccable/teach-impeccable/SKILL.md +71 -0
- package/config/agent/skills/impeccable/typeset/SKILL.md +118 -0
- package/config/agent/skills/librarian/SKILL.md +5 -1
- package/config/agent/skills/markdown-to-html/SKILL.md +5 -2
- package/config/agent/skills/owasp-security/SKILL.md +539 -0
- package/config/agent/skills/pr/SKILL.md +5 -2
- package/config/agent/skills/receiving-code-review/SKILL.md +216 -0
- package/config/agent/skills/refactor/SKILL.md +5 -2
- package/config/agent/skills/requesting-code-review/SKILL.md +108 -0
- package/config/agent/skills/requesting-code-review/code-reviewer.md +146 -0
- package/config/agent/skills/session-learning/SKILL.md +185 -0
- package/config/agent/skills/skill-creator/SKILL.md +339 -213
- package/config/agent/skills/skill-creator/agents/analyzer.md +274 -0
- package/config/agent/skills/skill-creator/agents/comparator.md +202 -0
- package/config/agent/skills/skill-creator/agents/grader.md +223 -0
- package/config/agent/skills/skill-creator/assets/eval_review.html +146 -0
- package/config/agent/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/config/agent/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/config/agent/skills/skill-creator/references/schemas.md +430 -0
- package/config/agent/skills/skill-creator/scripts/__init__.py +0 -0
- package/config/agent/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/config/agent/skills/skill-creator/scripts/generate_report.py +326 -0
- package/config/agent/skills/skill-creator/scripts/improve_description.py +248 -0
- package/config/agent/skills/skill-creator/scripts/package_skill.py +33 -7
- package/config/agent/skills/skill-creator/scripts/quick_validate.py +11 -3
- package/config/agent/skills/skill-creator/scripts/run_eval.py +310 -0
- package/config/agent/skills/skill-creator/scripts/run_loop.py +332 -0
- package/config/agent/skills/skill-creator/scripts/utils.py +47 -0
- package/config/agent/skills/subagent-driven-development/SKILL.md +280 -0
- package/config/agent/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
- package/config/agent/skills/subagent-driven-development/implementer-prompt.md +113 -0
- package/config/agent/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/config/agent/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/config/agent/skills/systematic-debugging/SKILL.md +300 -0
- package/config/agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/config/agent/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/config/agent/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/config/agent/skills/systematic-debugging/find-polluter.sh +63 -0
- package/config/agent/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/config/agent/skills/systematic-debugging/test-academic.md +14 -0
- package/config/agent/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/config/agent/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/config/agent/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/config/agent/skills/test-driven-development/SKILL.md +375 -0
- package/config/agent/skills/test-driven-development/testing-anti-patterns.md +299 -0
- package/config/agent/skills/ui-ux-pro-max/SKILL.md +4 -1
- package/config/agent/skills/unit-test/SKILL.md +4 -2
- package/config/agent/skills/using-git-worktrees/SKILL.md +222 -0
- package/config/agent/skills/using-superpowers/SKILL.md +118 -0
- package/config/agent/skills/using-superpowers/references/codex-tools.md +25 -0
- package/config/agent/skills/using-superpowers/references/gemini-tools.md +33 -0
- package/config/agent/skills/verification-before-completion/SKILL.md +142 -0
- package/config/agent/skills/writing-plans/SKILL.md +148 -0
- package/config/agent/skills/writing-plans/plan-document-reviewer-prompt.md +49 -0
- package/config/agent/skills/writing-skills/SKILL.md +669 -0
- package/config/agent/skills/writing-skills/anthropic-best-practices.md +1150 -0
- package/config/agent/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/config/agent/skills/writing-skills/graphviz-conventions.dot +172 -0
- package/config/agent/skills/writing-skills/persuasion-principles.md +187 -0
- package/config/agent/skills/writing-skills/render-graphs.js +168 -0
- package/config/agent/skills/writing-skills/testing-skills-with-subagents.md +384 -0
- package/config.json +23 -2
- package/dist/banner.js +3 -3
- package/dist/banner.js.map +1 -1
- package/package.json +21 -16
- package/scripts/banner.txt +4 -3
- package/scripts/postinstall.js +203 -11
- package/config/agent/prompts/git-rollback.md +0 -91
- package/config/agent/prompts/git-worktree.md +0 -277
- package/config/agent/prompts/help.md +0 -10
- package/config/agent/skills/github/SKILL.md +0 -47
- package/config/agent/skills/skill-creator/references/output-patterns.md +0 -82
- package/config/agent/skills/skill-creator/references/workflows.md +0 -28
- package/config/agent/skills/skill-creator/scripts/init_skill.py +0 -303
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* @author: xujianjiang
|
|
2
3
|
* Custom Footer Extension — Single-line compact powerline style
|
|
3
4
|
*
|
|
4
5
|
* ~/path (branch) │ ↑in ↓out $cost │ 42%/200k │ ⚡ model • thinking
|
|
@@ -16,11 +17,35 @@ function fmtTokens(n: number): string {
|
|
|
16
17
|
return `${(n / 1000000).toFixed(1)}M`;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
//
|
|
20
|
-
const gold = (s: string) => `\x1b[38;2;
|
|
20
|
+
// #49bccf
|
|
21
|
+
const gold = (s: string) => `\x1b[38;2;73;188;207m${s}\x1b[0m`;
|
|
22
|
+
|
|
23
|
+
// 获取本地版本号
|
|
24
|
+
function getVersion() {
|
|
25
|
+
return process.env.AICODE_CLI_VERSION || null;
|
|
26
|
+
}
|
|
21
27
|
|
|
22
28
|
export default function (pi: ExtensionAPI) {
|
|
23
29
|
pi.on("session_start", async (_event, ctx) => {
|
|
30
|
+
// 检查版本更新并显示通知
|
|
31
|
+
const cachePath = process.env.AICODE_CLI_VERSION_CACHE;
|
|
32
|
+
if (cachePath) {
|
|
33
|
+
try {
|
|
34
|
+
const { existsSync, readFileSync } = await import("fs");
|
|
35
|
+
if (existsSync(cachePath)) {
|
|
36
|
+
const cache = JSON.parse(readFileSync(cachePath, 'utf-8'));
|
|
37
|
+
// 缓存有效期 1 小时
|
|
38
|
+
if (cache.needsUpdate && Date.now() - cache.timestamp < 3600000) {
|
|
39
|
+
// 在输入框上方显示版本更新提示
|
|
40
|
+
const msg = `\x1b[38;2;243;139;168m⚠️ 发现新版本 v${cache.localVersion} → v${cache.latestVersion}\x1b[0m \x1b[36mnpm install -g @ia-ccun/code-agent-cli\x1b[0m`;
|
|
41
|
+
ctx.ui.setWidget("version-update", [msg], { placement: "aboveEditor" });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
} catch (e) {
|
|
45
|
+
// 忽略
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
24
49
|
ctx.ui.setFooter((tui, theme, footerData) => {
|
|
25
50
|
const unsub = footerData.onBranchChange(() => tui.requestRender());
|
|
26
51
|
|
|
@@ -161,6 +186,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
161
186
|
segments.push(modelColored);
|
|
162
187
|
segments.push(theme.fg("muted", quote));
|
|
163
188
|
|
|
189
|
+
// ── Version segment (rightmost) ─────────────────────────
|
|
190
|
+
const version = getVersion();
|
|
191
|
+
if (version) {
|
|
192
|
+
segments.push(theme.fg("muted", `v${version}`));
|
|
193
|
+
}
|
|
194
|
+
|
|
164
195
|
const joined = segments.join(sep);
|
|
165
196
|
return [truncateToWidth(joined, width)];
|
|
166
197
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* @author: xujianjiang
|
|
2
3
|
* 自定义扩展示例
|
|
3
4
|
*
|
|
4
5
|
* 放置位置: config/agent/extensions/
|
|
@@ -35,9 +36,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
35
36
|
timeStr = `${mins}m ${secs}s`;
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
//
|
|
39
|
+
// 格式化完整时间
|
|
39
40
|
const now = new Date();
|
|
40
|
-
const timeStr2 = `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`;
|
|
41
|
+
const timeStr2 = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`;
|
|
41
42
|
|
|
42
43
|
// agent_end 表示一轮对话结束,显示完成提示
|
|
43
44
|
ctx.ui.notify(`${timeStr2} | ✨ 消息处理完成 (${timeStr})`, "info");
|
|
@@ -57,51 +58,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
57
58
|
await ctx.ui.notify("⚠️ logout 功能已禁用", "warning");
|
|
58
59
|
return { block: true, reason: "logout 功能已禁用" };
|
|
59
60
|
}
|
|
60
|
-
|
|
61
|
-
// 拦截其他工具
|
|
62
|
-
if (event.toolName === "bash") {
|
|
63
|
-
const command = event.input.command;
|
|
64
|
-
if (command.includes("rm -rf")) {
|
|
65
|
-
// 解析要删除的路径
|
|
66
|
-
const match = command.match(/rm\s+-rf\s+('[^']+'|"[^"]+"|\S+)/g);
|
|
67
|
-
if (match) {
|
|
68
|
-
const paths = match.map(m => m.replace(/^rm\s+-rf\s+/, '').replace(/^['"]|['"]$/g, ''));
|
|
69
|
-
|
|
70
|
-
// 尝试列出文件
|
|
71
|
-
const { readdirSync, statSync, existsSync } = await import("fs");
|
|
72
|
-
let fileList: string[] = [];
|
|
73
|
-
for (const p of paths) {
|
|
74
|
-
try {
|
|
75
|
-
if (existsSync(p)) {
|
|
76
|
-
const stat = statSync(p);
|
|
77
|
-
if (stat.isDirectory()) {
|
|
78
|
-
const files = readdirSync(p);
|
|
79
|
-
fileList.push(`📁 ${p}/ (${files.length} 个文件)`);
|
|
80
|
-
} else {
|
|
81
|
-
fileList.push(`📄 ${p}`);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
} catch (e) { /* 忽略读取错误 */ }
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const msg = fileList.length > 0
|
|
88
|
-
? `将删除以下文件/目录:\n${fileList.join('\n')}`
|
|
89
|
-
: '确定要执行此删除命令吗?';
|
|
90
|
-
|
|
91
|
-
// 第一次确认
|
|
92
|
-
const firstConfirm = await ctx.ui.confirm("🔴 危险操作 - rm -rf", msg);
|
|
93
|
-
if (!firstConfirm) {
|
|
94
|
-
return { block: true, reason: "被用户拒绝" };
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// 二次确认
|
|
98
|
-
const secondConfirm = await ctx.ui.confirm("🔴 二次确认 - 不可恢复", "确定要继续删除吗?此操作不可恢复!");
|
|
99
|
-
if (!secondConfirm) {
|
|
100
|
-
return { block: true, reason: "被用户二次拒绝" };
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
61
|
});
|
|
106
62
|
|
|
107
63
|
// === 注册自定义命令 ===
|
|
@@ -179,52 +135,24 @@ export default function (pi: ExtensionAPI) {
|
|
|
179
135
|
// === 注册 /update 命令 ===
|
|
180
136
|
|
|
181
137
|
pi.registerCommand("update", {
|
|
182
|
-
description: "更新
|
|
138
|
+
description: "更新 aicode-cli 工具",
|
|
183
139
|
usage: "/update",
|
|
184
140
|
handler: async (_args, ctx) => {
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
"更新依赖 agent",
|
|
188
|
-
];
|
|
189
|
-
|
|
190
|
-
// 让用户选择
|
|
191
|
-
const selected = await ctx.ui.select("选择更新内容", options);
|
|
192
|
-
if (!selected) {
|
|
141
|
+
const ok = await ctx.ui.confirm("更新确认", "确定要更新 aicode-cli 吗?");
|
|
142
|
+
if (!ok) {
|
|
193
143
|
ctx.ui.notify("已取消", "info");
|
|
194
144
|
return;
|
|
195
145
|
}
|
|
196
146
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const { exec } = await import("child_process");
|
|
205
|
-
exec("npm install -g @ia-ccun/aicode-cli", (error, stdout, stderr) => {
|
|
206
|
-
if (error) {
|
|
207
|
-
ctx.ui.notify(`❌ 更新失败: ${error.message},请重试`, "error");
|
|
208
|
-
} else {
|
|
209
|
-
ctx.ui.notify("✅ aicode-cli 更新成功!", "success");
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
} else if (selected.includes("agent")) {
|
|
213
|
-
const ok = await ctx.ui.confirm("更新确认", "确定要更新依赖的agent 吗?");
|
|
214
|
-
if (!ok) {
|
|
215
|
-
ctx.ui.notify("已取消", "info");
|
|
216
|
-
return;
|
|
147
|
+
ctx.ui.notify("🔄 正在更新 aicode-cli...", "info");
|
|
148
|
+
const { exec } = await import("child_process");
|
|
149
|
+
exec("npm install -g @ia-ccun/code-agent-cli", (error, stdout, stderr) => {
|
|
150
|
+
if (error) {
|
|
151
|
+
ctx.ui.notify(`❌ 更新失败: ${error.message},请重试`, "error");
|
|
152
|
+
} else {
|
|
153
|
+
ctx.ui.notify("✅ aicode-cli 更新成功!请重启 CLI", "success");
|
|
217
154
|
}
|
|
218
|
-
|
|
219
|
-
const { exec } = await import("child_process");
|
|
220
|
-
exec("npm install -g @mariozechner/pi-coding-agent", (error, stdout, stderr) => {
|
|
221
|
-
if (error) {
|
|
222
|
-
ctx.ui.notify(`❌ 更新失败: ${error.message},请重试`, "error");
|
|
223
|
-
} else {
|
|
224
|
-
ctx.ui.notify("✅ 依赖的 agent 更新成功!", "success");
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
}
|
|
155
|
+
});
|
|
228
156
|
},
|
|
229
157
|
});
|
|
230
158
|
|
|
@@ -240,14 +168,19 @@ export default function (pi: ExtensionAPI) {
|
|
|
240
168
|
usage: "/version",
|
|
241
169
|
handler: async (_args, ctx) => {
|
|
242
170
|
const { execSync } = await import("child_process");
|
|
243
|
-
const
|
|
244
|
-
const { readFileSync } = await import("fs");
|
|
171
|
+
const { readFileSync, existsSync } = await import("fs");
|
|
245
172
|
|
|
246
|
-
//
|
|
173
|
+
// 读取全局安装的 aicode-cli 版本
|
|
247
174
|
let localVersion = "未知";
|
|
248
175
|
try {
|
|
249
|
-
|
|
250
|
-
|
|
176
|
+
// 获取全局 npm 包路径
|
|
177
|
+
const globalPath = execSync("npm root -g", { encoding: "utf8" }).trim();
|
|
178
|
+
const pkgPath = `${globalPath}/@ia-ccun/code-agent-cli/package.json`;
|
|
179
|
+
|
|
180
|
+
if (existsSync(pkgPath)) {
|
|
181
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
182
|
+
localVersion = pkg.version;
|
|
183
|
+
}
|
|
251
184
|
} catch (e) {
|
|
252
185
|
// 忽略
|
|
253
186
|
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Monitor Extension
|
|
3
|
+
*
|
|
4
|
+
* @author: xujianjiang
|
|
5
|
+
*
|
|
6
|
+
* Logs errors to ./.aicode-cli/debug-logs/aicode-error-YYYY-MM-DD.log
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
10
|
+
import fs from "fs";
|
|
11
|
+
import path from "path";
|
|
12
|
+
|
|
13
|
+
// Error log file configuration
|
|
14
|
+
const ERROR_LOG_DIR = path.resolve(process.cwd(), "./.aicode-cli/debug-logs");
|
|
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
|
+
}
|
|
53
|
+
|
|
54
|
+
// Ensure log directory exists
|
|
55
|
+
function ensureLogDir(): void {
|
|
56
|
+
if (!fs.existsSync(ERROR_LOG_DIR)) {
|
|
57
|
+
fs.mkdirSync(ERROR_LOG_DIR, { recursive: true });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @author: xujianjiang
|
|
63
|
+
* Append error message to log file
|
|
64
|
+
*/
|
|
65
|
+
function appendToErrorLog(message: string, context?: Record<string, unknown>): void {
|
|
66
|
+
ensureLogDir();
|
|
67
|
+
cleanOldLogs(); // 每次写日志时清理过期文件
|
|
68
|
+
const timestamp = formatBeijingTime();
|
|
69
|
+
const logFile = path.join(ERROR_LOG_DIR, getLogFileName());
|
|
70
|
+
let logEntry = `[${timestamp}] ${message}`;
|
|
71
|
+
if (context && Object.keys(context).length > 0) {
|
|
72
|
+
logEntry += `\nContext: ${JSON.stringify(context, null, 2)}`;
|
|
73
|
+
}
|
|
74
|
+
logEntry += "\n---\n";
|
|
75
|
+
fs.appendFileSync(logFile, logEntry);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default function (pi: ExtensionAPI) {
|
|
79
|
+
// Counter for error tracking
|
|
80
|
+
let toolErrorCount = 0;
|
|
81
|
+
let bashErrorCount = 0;
|
|
82
|
+
const startTime = Date.now();
|
|
83
|
+
|
|
84
|
+
// Monitor tool execution end for errors
|
|
85
|
+
pi.on("tool_execution_end", (event) => {
|
|
86
|
+
const { toolCallId, toolName, result, isError } = event;
|
|
87
|
+
|
|
88
|
+
if (isError) {
|
|
89
|
+
toolErrorCount++;
|
|
90
|
+
const errorMsg = typeof result === "string" ? result : JSON.stringify(result);
|
|
91
|
+
|
|
92
|
+
// Append to error log file
|
|
93
|
+
appendToErrorLog(
|
|
94
|
+
`Tool Execution Failed: ${toolName}`,
|
|
95
|
+
{
|
|
96
|
+
toolCallId,
|
|
97
|
+
toolName,
|
|
98
|
+
errorMessage: errorMsg?.substring(0, 500),
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Monitor user bash events for command failures
|
|
105
|
+
pi.on("user_bash", (event) => {
|
|
106
|
+
const { command, result } = event;
|
|
107
|
+
|
|
108
|
+
if (result?.exitCode !== 0) {
|
|
109
|
+
bashErrorCount++;
|
|
110
|
+
|
|
111
|
+
// Append to error log file
|
|
112
|
+
appendToErrorLog(
|
|
113
|
+
`Bash Command Failed: ${command} - exit code ${result?.exitCode}`,
|
|
114
|
+
{
|
|
115
|
+
command,
|
|
116
|
+
exitCode: result?.exitCode,
|
|
117
|
+
stderr: result?.stderr?.substring(0, 500),
|
|
118
|
+
stdout: result?.stdout?.substring(0, 500),
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Summary on session shutdown
|
|
125
|
+
pi.on("session_shutdown", () => {
|
|
126
|
+
const uptime = Math.round((Date.now() - startTime) / 1000);
|
|
127
|
+
const totalErrors = toolErrorCount + bashErrorCount;
|
|
128
|
+
|
|
129
|
+
if (totalErrors > 0) {
|
|
130
|
+
console.log(`
|
|
131
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
132
|
+
📊 Error Monitor 会话统计
|
|
133
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
134
|
+
总错误数: ${totalErrors}
|
|
135
|
+
工具错误数: ${toolErrorCount}
|
|
136
|
+
Bash 错误数: ${bashErrorCount}
|
|
137
|
+
运行时长: ${uptime}秒
|
|
138
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
139
|
+
`);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author: xujianjiang
|
|
3
|
+
* Msg Debug Extension - Log LLM request/response messages to file
|
|
4
|
+
*
|
|
5
|
+
* This extension logs all requests and responses sent to/from the LLM provider
|
|
6
|
+
* for debugging purposes. Logs are saved to ./.aicode-cli/debug-logs/
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Logs before_provider_request: messages, parameters, raw payload
|
|
10
|
+
* - Logs after_provider_response: usage stats, response content, stop reason
|
|
11
|
+
* - Logs errors with context
|
|
12
|
+
* - Console output removed (logs to file only)
|
|
13
|
+
* - Session-based log files (one file per session)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { appendFileSync, existsSync, mkdirSync } from "node:fs";
|
|
17
|
+
import { join } from "node:path";
|
|
18
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
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
|
+
|
|
34
|
+
export default function (pi: ExtensionAPI) {
|
|
35
|
+
// Create log directory in project root: ./.aicode-cli/debug-logs
|
|
36
|
+
const logDir = join(process.cwd(), ".aicode-cli", "debug-logs");
|
|
37
|
+
if (!existsSync(logDir)) {
|
|
38
|
+
mkdirSync(logDir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Format date as YYYY-MM-DD for daily log files
|
|
42
|
+
const dateStr = formatDateStr();
|
|
43
|
+
const logFile = join(logDir, `llm-requests-${dateStr}.log`);
|
|
44
|
+
|
|
45
|
+
// Filter to only log user and assistant messages
|
|
46
|
+
const ALLOWED_ROLES = ["user", "assistant"];
|
|
47
|
+
|
|
48
|
+
function formatMessage(message: any): string {
|
|
49
|
+
if (!message) return "undefined";
|
|
50
|
+
|
|
51
|
+
const role = message.role || "unknown";
|
|
52
|
+
let content = "";
|
|
53
|
+
|
|
54
|
+
if (typeof message.content === "string") {
|
|
55
|
+
content = message.content;
|
|
56
|
+
} else if (Array.isArray(message.content)) {
|
|
57
|
+
content = message.content.map((item: any) => {
|
|
58
|
+
if (item.type === "text") {
|
|
59
|
+
return item.text || "";
|
|
60
|
+
} else if (item.type === "image") {
|
|
61
|
+
return `[image: ${item.source?.type || "unknown"}]`;
|
|
62
|
+
} else if (item.type === "tool_use") {
|
|
63
|
+
return `[tool_use: ${item.name || "unknown"}]`;
|
|
64
|
+
} else if (item.type === "tool_result") {
|
|
65
|
+
return `[tool_result: ${item.tool_use_id || ""}]`;
|
|
66
|
+
}
|
|
67
|
+
return JSON.stringify(item);
|
|
68
|
+
}).join("\n");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return `[${role}]: ${content}`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Filter messages to only include user and assistant
|
|
75
|
+
function filterMessages(messages: any[]): any[] {
|
|
76
|
+
if (!Array.isArray(messages)) return [];
|
|
77
|
+
return messages.filter((msg) => ALLOWED_ROLES.includes(msg.role));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Log before request is sent
|
|
81
|
+
pi.on("before_provider_request", (event) => {
|
|
82
|
+
const timestamp = formatBeijingTime();
|
|
83
|
+
const { provider, model, payload } = event;
|
|
84
|
+
|
|
85
|
+
// Filter messages to only user and assistant
|
|
86
|
+
const filteredMessages = filterMessages(payload.messages);
|
|
87
|
+
const originalCount = payload.messages?.length || 0;
|
|
88
|
+
|
|
89
|
+
const logEntry = `
|
|
90
|
+
================================================================================
|
|
91
|
+
[${timestamp}] BEFORE PROVIDER REQUEST
|
|
92
|
+
================================================================================
|
|
93
|
+
Provider: ${provider || "unknown"}
|
|
94
|
+
Model: ${model || "unknown"}
|
|
95
|
+
Messages: ${filteredMessages.length} (filtered from ${originalCount}, showing user/assistant only)
|
|
96
|
+
|
|
97
|
+
--- Messages ---
|
|
98
|
+
${filteredMessages.map((msg: any, i: number) =>
|
|
99
|
+
`[${i}] ${formatMessage(msg)}`
|
|
100
|
+
).join("\n\n") || "No messages"}
|
|
101
|
+
|
|
102
|
+
--- Request Parameters ---
|
|
103
|
+
${JSON.stringify({
|
|
104
|
+
maxTokens: payload.max_tokens,
|
|
105
|
+
temperature: payload.temperature,
|
|
106
|
+
topP: payload.top_p,
|
|
107
|
+
topK: payload.top_k,
|
|
108
|
+
stopSequences: payload.stop_sequences,
|
|
109
|
+
thinking: payload.thinking ? "enabled" : "disabled",
|
|
110
|
+
budgetTokens: payload.budget_tokens
|
|
111
|
+
}, null, 2)}
|
|
112
|
+
|
|
113
|
+
--- Raw Payload (filtered) ---
|
|
114
|
+
${JSON.stringify({ ...payload, messages: filteredMessages }, null, 2)}
|
|
115
|
+
|
|
116
|
+
================================================================================
|
|
117
|
+
`;
|
|
118
|
+
|
|
119
|
+
// Save to file
|
|
120
|
+
appendFileSync(logFile, logEntry, "utf8");
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Log after response is received
|
|
124
|
+
pi.on("after_provider_response", (event) => {
|
|
125
|
+
const timestamp = formatBeijingTime();
|
|
126
|
+
const { response, usage, cached } = event;
|
|
127
|
+
|
|
128
|
+
const logEntry = `
|
|
129
|
+
================================================================================
|
|
130
|
+
[${timestamp}] AFTER PROVIDER RESPONSE
|
|
131
|
+
================================================================================
|
|
132
|
+
Cached: ${cached ? "YES" : "NO"}
|
|
133
|
+
|
|
134
|
+
--- Usage Stats ---
|
|
135
|
+
${JSON.stringify(usage, null, 2)}
|
|
136
|
+
|
|
137
|
+
--- Response Content ---
|
|
138
|
+
${response.content?.map((c: any, i: number) => {
|
|
139
|
+
if (c.type === "text") {
|
|
140
|
+
return `[${i}] text: ${c.text}`;
|
|
141
|
+
} else if (c.type === "tool_use") {
|
|
142
|
+
return `[${i}] tool_use: ${c.name}(${JSON.stringify(c.input)})`;
|
|
143
|
+
}
|
|
144
|
+
return `[${i}] ${c.type}: ${JSON.stringify(c)}`;
|
|
145
|
+
}).join("\n") || "No content"}
|
|
146
|
+
|
|
147
|
+
--- Stop Reason ---
|
|
148
|
+
${response.stopReason || "unknown"}
|
|
149
|
+
|
|
150
|
+
--- Raw Response ---
|
|
151
|
+
${JSON.stringify(response, null, 2)}
|
|
152
|
+
|
|
153
|
+
================================================================================
|
|
154
|
+
|
|
155
|
+
`;
|
|
156
|
+
|
|
157
|
+
// Save to file
|
|
158
|
+
appendFileSync(logFile, logEntry, "utf8");
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Log request errors
|
|
162
|
+
pi.on("error", (event) => {
|
|
163
|
+
const timestamp = formatBeijingTime();
|
|
164
|
+
const { error, context } = event;
|
|
165
|
+
|
|
166
|
+
const logEntry = `
|
|
167
|
+
################################################################################
|
|
168
|
+
[${timestamp}] ERROR
|
|
169
|
+
################################################################################
|
|
170
|
+
Error: ${error.message || String(error)}
|
|
171
|
+
Stack: ${error.stack || "No stack trace"}
|
|
172
|
+
|
|
173
|
+
Context:
|
|
174
|
+
${JSON.stringify(context, null, 2)}
|
|
175
|
+
|
|
176
|
+
################################################################################
|
|
177
|
+
|
|
178
|
+
`;
|
|
179
|
+
|
|
180
|
+
// Save to file
|
|
181
|
+
appendFileSync(logFile, logEntry, "utf8");
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Extension enabled silently (logs to file only, no console output)
|
|
185
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* @author: xujianjiang
|
|
2
3
|
* Code Review Extension (inspired by Codex's review feature)
|
|
3
4
|
*
|
|
4
5
|
* Provides a `/review` command that prompts the agent to review code changes.
|
|
@@ -916,6 +917,9 @@ export default function reviewExtension(pi: ExtensionAPI) {
|
|
|
916
917
|
fullPrompt += `\n\nThis project has additional instructions for code reviews:\n\n${projectGuidelines}`;
|
|
917
918
|
}
|
|
918
919
|
|
|
920
|
+
// 要求 AI 使用中文输出
|
|
921
|
+
fullPrompt += `\n\n---\n\n**重要:请使用中文撰写审查反馈。**`;
|
|
922
|
+
|
|
919
923
|
const modeHint = useFreshSession ? " (fresh session)" : "";
|
|
920
924
|
ctx.ui.notify(`Starting review: ${hint}${modeHint}`, "info");
|
|
921
925
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* @author: xujianjiang
|
|
2
3
|
* working-message
|
|
3
4
|
*
|
|
4
5
|
* 自定义工作消息,格式类似 Claude Code: ✶ xxx… (时间 · tokens)
|
|
@@ -11,33 +12,52 @@ import type { AssistantMessage } from "@mariozechner/pi-ai";
|
|
|
11
12
|
const accentColor = "\x1b[38;2;73;188;207m";
|
|
12
13
|
const reset = "\x1b[0m";
|
|
13
14
|
|
|
14
|
-
// 随机消息列表
|
|
15
|
+
// 随机消息列表 - 金融/支付/科技术语
|
|
15
16
|
const workingMessages = [
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
17
|
+
// 金融支付类
|
|
18
|
+
"备付金", "网银支付", "快捷支付", "代付", "代收", "清算", "结算", "对账",
|
|
19
|
+
"交易路由", "风控", "反欺诈", "欺诈检测", "洗钱防控", "合规审查", "反洗钱",
|
|
20
|
+
"支付通道", "渠道商", "商户", "收款", "退款", "拒付", "冲正", "挂账",
|
|
21
|
+
"资金池", "沉淀资金", "T+1结算", "实时结算", "分账", "分润", "抽成",
|
|
22
|
+
"银行卡", "信用卡", "借记卡", "IC卡", "磁条卡", "虚拟卡", "预付费卡",
|
|
23
|
+
"二维码支付", "NFC支付", "刷脸支付", "指纹支付", "声纹支付",
|
|
24
|
+
"跨境支付", "外汇结算", "汇率", "国际清算", "SWIFT", "CIPS",
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
// 区块链/网络安全类
|
|
27
|
+
"区块链", "智能合约", "共识机制", "PoW", "PoS", "DPoS", "Gas费",
|
|
28
|
+
"加密货币", "比特币", "以太坊", "稳定币", "DeFi", "NFT", "Web3",
|
|
29
|
+
"数字签名", "哈希", "非对称加密", "对称加密", "公钥", "私钥", "证书",
|
|
30
|
+
"数字证书", "PKI体系", "CA中心", "SSL/TLS", "HTTPS", "国密算法",
|
|
31
|
+
"防火墙", "入侵检测", "DDoS防护", "WAF", "漏洞扫描", "渗透测试",
|
|
25
32
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
// 生产变更/运维类
|
|
34
|
+
"变更管理", "发布", "回滚", "灰度发布", "蓝绿部署", "金丝雀发布",
|
|
35
|
+
"熔断", "限流", "降级", "切流", "流量切换", "流量调度",
|
|
36
|
+
"监控", "告警", "日志", "链路追踪", "APM", "性能监控", "可用性",
|
|
37
|
+
|
|
38
|
+
// 技术通用类
|
|
39
|
+
"Proofing", "Thinking", "Analyzing", "Reading", "Writing", "Searching",
|
|
40
|
+
"Generating", "Compiling", "Running", "Optimizing", "Debugging", "Learning",
|
|
41
|
+
"Processing", "Reasoning", "Summarizing", "Planning", "Executing", "Fetching",
|
|
42
|
+
"Parsing", "Validating", "Building", "Testing", "Deploying", "Refactoring",
|
|
43
|
+
"Documenting", "Researching", "Evaluating", "Comparing", "Calculating",
|
|
44
|
+
"Algorithm", "Architecture", "Database", "Cache", "Queue", "Microservice",
|
|
45
|
+
];
|
|
31
46
|
|
|
32
47
|
let intervalId: ReturnType<typeof setInterval> | null = null;
|
|
33
48
|
let startTime = 0;
|
|
34
49
|
let totalTokens = 0;
|
|
35
50
|
|
|
51
|
+
function getNextMessage(): string {
|
|
52
|
+
const randomIndex = Math.floor(Math.random() * workingMessages.length);
|
|
53
|
+
return workingMessages[randomIndex];
|
|
54
|
+
}
|
|
55
|
+
|
|
36
56
|
function formatTime(seconds: number): string {
|
|
37
|
-
if (seconds < 60) return `${seconds}s`;
|
|
57
|
+
if (seconds < 60) return `${seconds} s`;
|
|
38
58
|
const mins = Math.floor(seconds / 60);
|
|
39
59
|
const secs = seconds % 60;
|
|
40
|
-
return `${mins}m ${secs}s`;
|
|
60
|
+
return `${mins} m ${secs} s`;
|
|
41
61
|
}
|
|
42
62
|
|
|
43
63
|
function formatTokens(tokens: number): string {
|
|
@@ -53,7 +73,6 @@ export default function workingMessageExtension(pi: ExtensionAPI) {
|
|
|
53
73
|
// 记录开始时间
|
|
54
74
|
startTime = Date.now();
|
|
55
75
|
totalTokens = 0;
|
|
56
|
-
currentIndex = 0;
|
|
57
76
|
|
|
58
77
|
// 立即设置第一条
|
|
59
78
|
const updateMessage = () => {
|
|
@@ -61,7 +80,7 @@ export default function workingMessageExtension(pi: ExtensionAPI) {
|
|
|
61
80
|
const timeStr = formatTime(elapsed);
|
|
62
81
|
const tokensStr = formatTokens(totalTokens);
|
|
63
82
|
// ✶ 和单词显示为主题色
|
|
64
|
-
const msg = `${accentColor}
|
|
83
|
+
const msg = `${accentColor} ✶ ${getNextMessage()}…${reset} (${timeStr} · ↓ ${tokensStr} tokens)`;
|
|
65
84
|
ctx.ui?.setWorkingMessage(msg);
|
|
66
85
|
};
|
|
67
86
|
|
|
@@ -74,8 +93,8 @@ export default function workingMessageExtension(pi: ExtensionAPI) {
|
|
|
74
93
|
for (const entry of ctx.sessionManager.getBranch()) {
|
|
75
94
|
if (entry.type === "message" && (entry as any).message?.role === "assistant") {
|
|
76
95
|
const msg = (entry as any).message as AssistantMessage;
|
|
77
|
-
if (msg.usage?.
|
|
78
|
-
totalTokens = msg.usage.
|
|
96
|
+
if (msg.usage?.output) {
|
|
97
|
+
totalTokens = msg.usage.output;
|
|
79
98
|
}
|
|
80
99
|
}
|
|
81
100
|
}
|