codekanban 0.19.0 → 0.20.0

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,99 @@
1
+ import path from 'node:path';
2
+
3
+ import { CodeKanbanConfigError, CodeKanbanValidationError } from './errors.js';
4
+
5
+ export function normalizeBaseUrl(baseURL) {
6
+ const value = String(baseURL || '').trim();
7
+ if (!value) {
8
+ throw new CodeKanbanConfigError('baseURL is required');
9
+ }
10
+ const normalized = value.endsWith('/') ? value : `${value}/`;
11
+ let url;
12
+ try {
13
+ url = new URL(normalized);
14
+ } catch (error) {
15
+ throw new CodeKanbanConfigError(`invalid baseURL: ${value}`, { cause: error });
16
+ }
17
+ if (!['http:', 'https:'].includes(url.protocol)) {
18
+ throw new CodeKanbanConfigError(`unsupported baseURL protocol: ${url.protocol}`);
19
+ }
20
+ return url;
21
+ }
22
+
23
+ export function ensureString(value, fieldName) {
24
+ const normalized = typeof value === 'string' ? value.trim() : '';
25
+ if (!normalized) {
26
+ throw new CodeKanbanValidationError(`${fieldName} is required`);
27
+ }
28
+ return normalized;
29
+ }
30
+
31
+ export function ensureOptionalString(value) {
32
+ return typeof value === 'string' ? value.trim() : '';
33
+ }
34
+
35
+ export function ensureArrayOfStrings(value, fieldName) {
36
+ if (value == null) {
37
+ return [];
38
+ }
39
+ if (!Array.isArray(value)) {
40
+ throw new CodeKanbanValidationError(`${fieldName} must be an array of strings`);
41
+ }
42
+ return value
43
+ .map(item => (typeof item === 'string' ? item.trim() : ''))
44
+ .filter(Boolean);
45
+ }
46
+
47
+ export function normalizeFsPath(inputPath) {
48
+ const value = ensureString(inputPath, 'path');
49
+ const resolved = path.resolve(value);
50
+ const normalized = path.normalize(resolved);
51
+ return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
52
+ }
53
+
54
+ export function pathBasename(inputPath) {
55
+ const resolved = path.resolve(String(inputPath || ''));
56
+ const base = path.basename(resolved);
57
+ return base || 'project';
58
+ }
59
+
60
+ export function sleep(ms) {
61
+ return new Promise(resolve => setTimeout(resolve, ms));
62
+ }
63
+
64
+ export function toWsUrl(baseURL, wsPath) {
65
+ const base = normalizeBaseUrl(baseURL);
66
+ const wsBase = new URL(base.toString());
67
+ wsBase.protocol = base.protocol === 'https:' ? 'wss:' : 'ws:';
68
+ return new URL(wsPath, wsBase).toString();
69
+ }
70
+
71
+ export function normalizeTerminalEnter(value) {
72
+ const trimmed = String(value || '').replace(/\s+$/, '');
73
+ if (!trimmed) {
74
+ return '';
75
+ }
76
+ if (trimmed.endsWith('\n') || trimmed.endsWith('\r')) {
77
+ return trimmed;
78
+ }
79
+ return `${trimmed}\r`;
80
+ }
81
+
82
+ export function shellQuote(arg) {
83
+ const value = String(arg ?? '');
84
+ if (!value) {
85
+ return '""';
86
+ }
87
+ if (/^[A-Za-z0-9_./:\\=-]+$/.test(value)) {
88
+ return value;
89
+ }
90
+ return `"${value.replace(/"/g, '\\"')}"`;
91
+ }
92
+
93
+ export function toCommandString(argv) {
94
+ return argv.map(shellQuote).join(' ');
95
+ }
96
+
97
+ export function createJsonOutput(value) {
98
+ return `${JSON.stringify(value, null, 2)}\n`;
99
+ }
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "CodeKanban Project Session"
3
+ short_description: "Start AI workflows and inspect project sessions"
4
+ default_prompt: "Use the CodeKanban project session workflow to start Codex or Claude in a project path, including plan or yolo startup profiles, or inspect terminal and AI sessions for that project."
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { runCli } from '../../../packages/node-sdk/src/cli.js';
3
+
4
+ const exitCode = await runCli(process.argv.slice(2));
5
+ if (typeof exitCode === 'number') {
6
+ process.exitCode = exitCode;
7
+ }
@@ -0,0 +1,162 @@
1
+ # Claude Code Terminal Analyzer
2
+
3
+ 一个专门用于分析 Claude Code 终端调试信息的工具,可以:
4
+ - 使用虚拟终端模拟器重放终端输出
5
+ - 检测 AI 助手状态的转换
6
+ - 生成详细的 JSON 和 HTML 分析报告
7
+
8
+ ## 功能特性
9
+
10
+ - ✅ 支持从 URL 或本地文件加载调试数据
11
+ - ✅ 使用虚拟终端(vt10x)精确模拟终端行为
12
+ - ✅ 复用项目 `ai_assistant` 包的检测逻辑,确保一致性
13
+ - ✅ 自动检测 Claude Code 的状态:
14
+ - `thinking` - AI 正在思考
15
+ - `executing` - AI 正在执行任务
16
+ - `waiting_approval` - 等待审批
17
+ - `replying` - AI 正在回复
18
+ - `waiting_input` - 等待用户输入
19
+ - ✅ 记录每次状态转换时的终端完整显示
20
+ - ✅ 生成美观的 HTML 可视化报告
21
+ - ✅ 输出详细的 JSON 数据报告
22
+ - ✅ 统计各阶段耗时
23
+
24
+ ## 安装
25
+
26
+ ```bash
27
+ # 编译
28
+ go build -o claude-terminal-analyzer.exe
29
+
30
+ # 或使用提供的脚本
31
+ build.bat # Windows
32
+ ./build.sh # Linux/Mac
33
+ ```
34
+
35
+ ## 使用方法
36
+
37
+ ### 基本用法
38
+
39
+ ```bash
40
+ # 从本地文件分析
41
+ ./claude-terminal-analyzer -source debug.json
42
+
43
+ # 从 API URL 分析
44
+ ./claude-terminal-analyzer -source http://localhost:3007/api/v1/terminals/xxxxx/debug
45
+
46
+ # 指定输出文件
47
+ ./claude-terminal-analyzer -source debug.json -json report.json
48
+ ```
49
+
50
+ ### 命令行参数
51
+
52
+ - `-source` - **必需**,数据源(文件路径或 URL)
53
+ - `-json` - JSON 报告输出路径(默认: analysis.json)
54
+ - `-type` - AI 类型(默认: claude,可选: claude / codex)
55
+ - `-sync2026` - 是否启用 CSI `?2026` 同步输出缓冲(默认: true)
56
+ - `-codex-filter` - 是否启用 Codex diff 渲染误判过滤(默认: true)
57
+
58
+ ## 输出示例
59
+
60
+ ### 控制台输出
61
+
62
+ ```
63
+ ============================================================
64
+ 📊 ANALYSIS SUMMARY
65
+ ============================================================
66
+ Session ID: jlBr0XXAJoUJng9N
67
+ Total Chunks: 261
68
+ State Changes: 15
69
+ Unique States: [thinking executing completed waiting]
70
+ Current State: waiting_input
71
+ State Updated: 2025-11-23 17:14:59
72
+ Thinking Time: 2.71s
73
+ Executing Time: 0.00s
74
+ Waiting Time: 16.76s
75
+ ============================================================
76
+
77
+ 🔄 STATE TRANSITIONS:
78
+ 1. [Chunk #0] THINKING
79
+ 2. [Chunk #15] EXECUTING - 测试所有功能
80
+ 3. [Chunk #89] THINKING
81
+ 4. [Chunk #102] EXECUTING - 测试所有功能
82
+ ...
83
+ ```
84
+
85
+ ### HTML 报告
86
+
87
+ 生成的 HTML 报告包含:
88
+ - 📊 统计卡片:显示各项指标
89
+ - 🎯 时间轴:展示状态变化
90
+ - 💬 消息详情:显示每个状态的具体内容
91
+ - 📝 原始数据:可展开查看原始终端输出
92
+
93
+ ### JSON 报告
94
+
95
+ ```json
96
+ {
97
+ "summary": {
98
+ "totalChunks": 261,
99
+ "stateChanges": 15,
100
+ "uniqueStates": ["thinking", "executing", "waiting"],
101
+ "sessionId": "jlBr0XXAJoUJng9N",
102
+ "currentState": "waiting_input",
103
+ "totalThinkingMs": 2706,
104
+ "totalExecutingMs": 0,
105
+ "totalWaitingMs": 16763
106
+ },
107
+ "stateChanges": [
108
+ {
109
+ "index": 0,
110
+ "state": "thinking",
111
+ "indicator": "∴ Thought for 4s",
112
+ "message": "",
113
+ "cleanedText": "..."
114
+ }
115
+ ]
116
+ }
117
+ ```
118
+
119
+ ## 工作原理
120
+
121
+ 工具模拟真实的终端行为:
122
+
123
+ 1. **创建虚拟终端**:使用 `vt10x` 包创建终端模拟器
124
+ 2. **逐块喂入数据**:将每个 scrollback chunk 依次写入虚拟终端
125
+ 3. **读取终端显示**:从虚拟终端读取当前的可见内容
126
+ 4. **状态检测**:使用项目的 `ai_assistant` 包检测状态
127
+ 5. **记录转换**:当状态变化时,记录终端快照
128
+
129
+ 这种方式确保:
130
+ - ✅ 完全模拟真实终端的渲染行为
131
+ - ✅ 检测逻辑与主项目完全一致
132
+ - ✅ 结果稳定可重复
133
+
134
+ ## 典型应用场景
135
+
136
+ 1. **性能分析**:了解 AI 在各个阶段的耗时
137
+ 2. **状态追踪**:查看 AI 的工作流程
138
+ 3. **问题诊断**:分析卡顿或异常的原因
139
+ 4. **使用统计**:统计 AI 的使用模式
140
+ 5. **行为验证**:验证状态检测逻辑是否正确
141
+
142
+ ## 技术实现
143
+
144
+ - **虚拟终端模拟**:使用 `github.com/hinshun/vt10x` 包
145
+ - **状态检测**:复用 `code-kanban/utils/ai_assistant2` 包的检测逻辑
146
+ - **报告生成**:
147
+ - JSON:使用 Go 标准库的 `encoding/json`
148
+ - HTML:使用内嵌模板生成美观的可视化报告
149
+
150
+ ## 开发
151
+
152
+ ```bash
153
+ # 运行测试
154
+ go test ./...
155
+
156
+ # 格式化代码
157
+ go fmt ./...
158
+ ```
159
+
160
+ ## 许可证
161
+
162
+ MIT License
@@ -0,0 +1,9 @@
1
+ @echo off
2
+ echo Building Claude Terminal Analyzer...
3
+ go build -o claude-terminal-analyzer.exe -ldflags="-s -w" .
4
+ if %errorlevel% == 0 (
5
+ echo Build successful! Executable: claude-terminal-analyzer.exe
6
+ ) else (
7
+ echo Build failed!
8
+ exit /b 1
9
+ )