webtape-receiver 1.2.0 → 1.4.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/dist/analyzer.d.ts +12 -12
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +51 -70
- package/dist/analyzer.js.map +1 -1
- package/dist/config.d.ts +18 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +66 -0
- package/dist/config.js.map +1 -0
- package/dist/index.js +151 -42
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +4 -17
- package/dist/server.js.map +1 -1
- package/dist/storage.d.ts +26 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +80 -16
- package/dist/storage.js.map +1 -1
- package/dist/workspace.d.ts +6 -3
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +132 -6
- package/dist/workspace.js.map +1 -1
- package/package.json +1 -1
package/dist/analyzer.d.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import type { WorkspacePaths } from './workspace.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*/
|
|
5
|
-
export declare function buildPrompt(sessionDir: string): string;
|
|
6
|
-
export type AnalyzerBackend = 'cursor';
|
|
2
|
+
export type AnalyzerBackend = 'cursor' | 'claude';
|
|
3
|
+
export declare const VALID_BACKENDS: readonly AnalyzerBackend[];
|
|
7
4
|
export interface AnalyzeOptions {
|
|
8
5
|
backend: AnalyzerBackend;
|
|
9
6
|
workspace: WorkspacePaths;
|
|
10
7
|
sessionDir: string;
|
|
11
8
|
model?: string;
|
|
12
9
|
}
|
|
10
|
+
export interface AnalyzeResult {
|
|
11
|
+
/** Whether the analysis report was successfully created */
|
|
12
|
+
success: boolean;
|
|
13
|
+
/** Expected report path */
|
|
14
|
+
reportPath: string;
|
|
15
|
+
/** Session name */
|
|
16
|
+
sessionName: string;
|
|
17
|
+
}
|
|
13
18
|
/**
|
|
14
19
|
* Run AI analysis on a recording session.
|
|
15
|
-
* Returns
|
|
16
|
-
*/
|
|
17
|
-
export declare function analyzeRecording(opts: AnalyzeOptions): Promise<string>;
|
|
18
|
-
/**
|
|
19
|
-
* Generate (or refresh) the prompt.md file inside the session directory
|
|
20
|
-
* for manual use (e.g. paste into Cursor chat).
|
|
20
|
+
* Returns an AnalyzeResult indicating whether the report was created.
|
|
21
21
|
*/
|
|
22
|
-
export declare function
|
|
22
|
+
export declare function analyzeRecording(opts: AnalyzeOptions): Promise<AnalyzeResult>;
|
|
23
23
|
//# sourceMappingURL=analyzer.d.ts.map
|
package/dist/analyzer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAElD,eAAO,MAAM,cAAc,EAAE,SAAS,eAAe,EAAkC,CAAC;AASxF,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,cAAc,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,2DAA2D;IAC3D,OAAO,EAAE,OAAO,CAAC;IACjB,2BAA2B;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAgBnF"}
|
package/dist/analyzer.js
CHANGED
|
@@ -1,84 +1,49 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process';
|
|
2
|
-
import {
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
## 任务
|
|
7
|
-
|
|
8
|
-
1. **梳理用户操作流程**:根据 index.json 中的 action 序列,还原用户的完整操作路径。
|
|
9
|
-
2. **分析接口调用链路**:
|
|
10
|
-
- 列出每个用户操作触发的所有 API 请求
|
|
11
|
-
- 标注请求方法、URL、状态码
|
|
12
|
-
- 分析请求之间的依赖关系(例如:登录后拿到 token,后续请求携带 token)
|
|
13
|
-
3. **识别业务模块**:根据 URL 模式和请求内容,划分业务模块(如:用户认证、数据查询、表单提交等)
|
|
14
|
-
4. **生成接口文档概要**:对每个接口给出简要说明,包括用途、请求参数、响应结构
|
|
15
|
-
5. **绘制链路图**:用 Mermaid 序列图描述核心业务流程的接口调用时序
|
|
16
|
-
|
|
17
|
-
## 录制数据
|
|
18
|
-
|
|
19
|
-
以下是 WebTape 录制的 index.json 内容:
|
|
20
|
-
|
|
21
|
-
\`\`\`json
|
|
22
|
-
{{INDEX_JSON}}
|
|
23
|
-
\`\`\`
|
|
24
|
-
|
|
25
|
-
## 请求详情目录
|
|
26
|
-
|
|
27
|
-
录制的请求详情文件位于:{{SESSION_DIR}}
|
|
28
|
-
|
|
29
|
-
请详细分析并输出 Markdown 格式的报告。`;
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { join, basename } from 'node:path';
|
|
4
|
+
export const VALID_BACKENDS = ['cursor', 'claude'];
|
|
30
5
|
/**
|
|
31
|
-
* Build the analysis
|
|
6
|
+
* Build the analysis instruction for a specific recording session.
|
|
32
7
|
*/
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (!existsSync(indexPath)) {
|
|
36
|
-
throw new Error(`index.json not found in ${sessionDir}`);
|
|
37
|
-
}
|
|
38
|
-
const indexContent = readFileSync(indexPath, 'utf-8');
|
|
39
|
-
return ANALYSIS_PROMPT_TEMPLATE
|
|
40
|
-
.replace('{{INDEX_JSON}}', indexContent)
|
|
41
|
-
.replace('{{SESSION_DIR}}', sessionDir);
|
|
8
|
+
function buildInstruction(sessionName) {
|
|
9
|
+
return `请分析 recordings/${sessionName} 目录下的录制数据,按照 AGENTS.md 中的指示完成分析,并将报告文件保存到对应位置。`;
|
|
42
10
|
}
|
|
43
11
|
/**
|
|
44
12
|
* Run AI analysis on a recording session.
|
|
45
|
-
* Returns
|
|
13
|
+
* Returns an AnalyzeResult indicating whether the report was created.
|
|
46
14
|
*/
|
|
47
15
|
export async function analyzeRecording(opts) {
|
|
48
16
|
const { backend, workspace, sessionDir, model } = opts;
|
|
49
|
-
const sessionName = sessionDir
|
|
50
|
-
const reportPath = join(workspace.
|
|
51
|
-
// Ensure prompt.md exists in the session directory (backward compatibility)
|
|
52
|
-
const promptPath = join(sessionDir, 'prompt.md');
|
|
53
|
-
if (!existsSync(promptPath)) {
|
|
54
|
-
const prompt = buildPrompt(sessionDir);
|
|
55
|
-
writeFileSync(promptPath, prompt, 'utf-8');
|
|
56
|
-
}
|
|
17
|
+
const sessionName = basename(sessionDir);
|
|
18
|
+
const reportPath = join(workspace.recordings, sessionName, 'analysis_report.md');
|
|
57
19
|
if (backend === 'cursor') {
|
|
58
|
-
|
|
20
|
+
await runCursor(workspace.root, sessionName, model);
|
|
21
|
+
}
|
|
22
|
+
else if (backend === 'claude') {
|
|
23
|
+
await runClaude(workspace.root, sessionName);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
throw new Error(`Unsupported analyzer backend: ${backend}`);
|
|
59
27
|
}
|
|
60
|
-
|
|
28
|
+
const success = existsSync(reportPath);
|
|
29
|
+
return { success, reportPath, sessionName };
|
|
61
30
|
}
|
|
62
31
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* Command: cursor agent prompt "<instruction>" --model "<model>"
|
|
32
|
+
* Run analysis via `cursor agent` CLI.
|
|
33
|
+
* cwd is the workspace root so cursor reads AGENTS.md.
|
|
66
34
|
*/
|
|
67
|
-
async function
|
|
68
|
-
const instruction = '请阅读当前目录下的 prompt.md 文件,按照其中的指示完成分析任务,并将分析报告输出为 Markdown 格式。';
|
|
35
|
+
async function runCursor(workspaceRoot, sessionName, model) {
|
|
69
36
|
return new Promise((resolve, reject) => {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
'prompt', instruction,
|
|
73
|
-
];
|
|
37
|
+
const instruction = buildInstruction(sessionName);
|
|
38
|
+
const args = ['agent', instruction, '--yolo'];
|
|
74
39
|
if (model) {
|
|
75
40
|
args.push('--model', model);
|
|
76
41
|
}
|
|
77
42
|
const child = execFile('cursor', args, {
|
|
78
|
-
cwd:
|
|
43
|
+
cwd: workspaceRoot,
|
|
79
44
|
maxBuffer: 10 * 1024 * 1024,
|
|
80
45
|
timeout: 5 * 60 * 1000,
|
|
81
|
-
}, (error,
|
|
46
|
+
}, (error, _stdout, stderr) => {
|
|
82
47
|
if (error) {
|
|
83
48
|
if (stderr) {
|
|
84
49
|
console.error('[analyzer] cursor stderr:', stderr);
|
|
@@ -86,9 +51,7 @@ async function analyzeByCursor(sessionDir, reportPath, model) {
|
|
|
86
51
|
reject(new Error(`cursor agent failed: ${error.message}`));
|
|
87
52
|
return;
|
|
88
53
|
}
|
|
89
|
-
|
|
90
|
-
writeFileSync(reportPath, output, 'utf-8');
|
|
91
|
-
resolve(reportPath);
|
|
54
|
+
resolve();
|
|
92
55
|
});
|
|
93
56
|
child.on('error', (err) => {
|
|
94
57
|
reject(new Error(`Failed to launch cursor agent: ${err.message}. ` +
|
|
@@ -97,13 +60,31 @@ async function analyzeByCursor(sessionDir, reportPath, model) {
|
|
|
97
60
|
});
|
|
98
61
|
}
|
|
99
62
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
63
|
+
* Run analysis via `claude` CLI (Claude Code).
|
|
64
|
+
* cwd is the workspace root so claude reads AGENTS.md.
|
|
102
65
|
*/
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
66
|
+
async function runClaude(workspaceRoot, sessionName) {
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
const instruction = buildInstruction(sessionName);
|
|
69
|
+
const args = [instruction, '--dangerously-skip-permissions'];
|
|
70
|
+
const child = execFile('claude', args, {
|
|
71
|
+
cwd: workspaceRoot,
|
|
72
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
73
|
+
timeout: 5 * 60 * 1000,
|
|
74
|
+
}, (error, _stdout, stderr) => {
|
|
75
|
+
if (error) {
|
|
76
|
+
if (stderr) {
|
|
77
|
+
console.error('[analyzer] claude stderr:', stderr);
|
|
78
|
+
}
|
|
79
|
+
reject(new Error(`claude failed: ${error.message}`));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
resolve();
|
|
83
|
+
});
|
|
84
|
+
child.on('error', (err) => {
|
|
85
|
+
reject(new Error(`Failed to launch claude: ${err.message}. ` +
|
|
86
|
+
'Ensure Claude Code is installed and the `claude` CLI is on your PATH.'));
|
|
87
|
+
});
|
|
88
|
+
});
|
|
108
89
|
}
|
|
109
90
|
//# sourceMappingURL=analyzer.js.map
|
package/dist/analyzer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AnalyzerBackend } from './analyzer.js';
|
|
2
|
+
export interface WebtapeConfig {
|
|
3
|
+
aiBackend?: AnalyzerBackend;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Load the persisted configuration, returning an empty object if none exists.
|
|
7
|
+
*/
|
|
8
|
+
export declare function loadConfig(): WebtapeConfig;
|
|
9
|
+
/**
|
|
10
|
+
* Save the configuration to disk (merges with existing).
|
|
11
|
+
*/
|
|
12
|
+
export declare function saveConfig(partial: Partial<WebtapeConfig>): WebtapeConfig;
|
|
13
|
+
/**
|
|
14
|
+
* Interactive prompt: ask the user to choose an AI backend.
|
|
15
|
+
* Uses Node.js built-in readline so we don't add any dependencies.
|
|
16
|
+
*/
|
|
17
|
+
export declare function promptAiBackend(): Promise<AnalyzerBackend>;
|
|
18
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAKrD,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,aAAa,CAQ1C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,aAAa,CAQzE;AAED;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,eAAe,CAAC,CA6BhE"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
const CONFIG_DIR = join(homedir(), '.webtape-receiver');
|
|
5
|
+
const CONFIG_PATH = join(CONFIG_DIR, 'config.json');
|
|
6
|
+
/**
|
|
7
|
+
* Load the persisted configuration, returning an empty object if none exists.
|
|
8
|
+
*/
|
|
9
|
+
export function loadConfig() {
|
|
10
|
+
if (!existsSync(CONFIG_PATH))
|
|
11
|
+
return {};
|
|
12
|
+
try {
|
|
13
|
+
return JSON.parse(readFileSync(CONFIG_PATH, 'utf-8'));
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
console.warn('Failed to parse config file, using defaults:', err.message);
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Save the configuration to disk (merges with existing).
|
|
22
|
+
*/
|
|
23
|
+
export function saveConfig(partial) {
|
|
24
|
+
const current = loadConfig();
|
|
25
|
+
const merged = { ...current, ...partial };
|
|
26
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
27
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
writeFileSync(CONFIG_PATH, JSON.stringify(merged, null, 2), 'utf-8');
|
|
30
|
+
return merged;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Interactive prompt: ask the user to choose an AI backend.
|
|
34
|
+
* Uses Node.js built-in readline so we don't add any dependencies.
|
|
35
|
+
*/
|
|
36
|
+
export async function promptAiBackend() {
|
|
37
|
+
const { createInterface } = await import('node:readline');
|
|
38
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
39
|
+
return new Promise((resolve) => {
|
|
40
|
+
console.log('');
|
|
41
|
+
console.log(' 请选择 AI 分析后端 / Select AI analysis backend:');
|
|
42
|
+
console.log('');
|
|
43
|
+
console.log(' 1) cursor — Cursor Agent (cursor agent …)');
|
|
44
|
+
console.log(' 2) claude — Claude Code (claude … --dangerously-skip-permissions)');
|
|
45
|
+
console.log('');
|
|
46
|
+
const ask = () => {
|
|
47
|
+
rl.question(' 请输入选项 (1/2): ', (answer) => {
|
|
48
|
+
const trimmed = answer.trim();
|
|
49
|
+
if (trimmed === '1' || trimmed === 'cursor') {
|
|
50
|
+
rl.close();
|
|
51
|
+
resolve('cursor');
|
|
52
|
+
}
|
|
53
|
+
else if (trimmed === '2' || trimmed === 'claude') {
|
|
54
|
+
rl.close();
|
|
55
|
+
resolve('claude');
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
console.log(' 无效输入,请输入 1、2、cursor 或 claude');
|
|
59
|
+
ask();
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
ask();
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { join } from 'node:path';
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import ora from 'ora';
|
|
6
6
|
import { resolveWorkspaceRoot, ensureWorkspace } from './workspace.js';
|
|
7
7
|
import { createWebhookServer } from './server.js';
|
|
8
|
-
import { listRecordings } from './storage.js';
|
|
9
|
-
import { analyzeRecording,
|
|
10
|
-
|
|
8
|
+
import { listRecordings, listUnanalyzedRecordings, parseSessionName, formatTime } from './storage.js';
|
|
9
|
+
import { analyzeRecording, VALID_BACKENDS } from './analyzer.js';
|
|
10
|
+
import { loadConfig, saveConfig, promptAiBackend } from './config.js';
|
|
11
|
+
const VERSION = '1.3.0';
|
|
11
12
|
const program = new Command();
|
|
12
13
|
program
|
|
13
14
|
.name('webtape-receiver')
|
|
14
15
|
.description('接收 WebTape 插件的 webhook 数据,保存录制内容并通过 AI 分析业务接口链路')
|
|
15
16
|
.version(VERSION);
|
|
17
|
+
/**
|
|
18
|
+
* Log analysis result — success or failure hint.
|
|
19
|
+
*/
|
|
20
|
+
function logAnalyzeResult(result) {
|
|
21
|
+
if (result.success) {
|
|
22
|
+
const { domain, time } = parseSessionName(result.sessionName);
|
|
23
|
+
const formattedTime = formatTime(time);
|
|
24
|
+
console.log(chalk.green(` ✅ 已将 ${formattedTime} 录制的 ${domain} 站点 api 分析记录保存到了 ${result.reportPath}`));
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
console.log(chalk.yellow(` ⚠️ 未检测到分析报告: ${result.reportPath}`));
|
|
28
|
+
console.log(chalk.gray(' 你可以稍后使用 webtape-receiver retry 命令重新分析所有未完成的记录。'));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
16
31
|
// ─── serve ───────────────────────────────────────────────────────────────────
|
|
17
32
|
program
|
|
18
33
|
.command('serve')
|
|
@@ -20,19 +35,32 @@ program
|
|
|
20
35
|
.option('-p, --port <number>', '监听端口', '5643')
|
|
21
36
|
.option('-w, --workspace <path>', '工作区路径(默认 ~/Desktop/WebTape)')
|
|
22
37
|
.option('--no-auto-analyze', '接收数据后不自动运行 AI 分析')
|
|
23
|
-
.option('--backend <name>', 'AI 分析后端(cursor)', '
|
|
38
|
+
.option('--backend <name>', 'AI 分析后端(cursor / claude)', '')
|
|
24
39
|
.option('--model <name>', 'AI 模型名称(例如 kimi-k2.5)')
|
|
25
40
|
.action(async (opts) => {
|
|
26
41
|
const port = parseInt(opts.port, 10);
|
|
27
42
|
const workspaceRoot = resolveWorkspaceRoot(opts.workspace);
|
|
28
|
-
const workspace = ensureWorkspace(workspaceRoot);
|
|
43
|
+
const workspace = ensureWorkspace(workspaceRoot, VERSION);
|
|
44
|
+
// Resolve AI backend: CLI flag > saved config > interactive prompt
|
|
45
|
+
let backend;
|
|
46
|
+
const config = loadConfig();
|
|
47
|
+
if (opts.backend) {
|
|
48
|
+
backend = opts.backend;
|
|
49
|
+
}
|
|
50
|
+
else if (config.aiBackend) {
|
|
51
|
+
backend = config.aiBackend;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
backend = await promptAiBackend();
|
|
55
|
+
saveConfig({ aiBackend: backend });
|
|
56
|
+
}
|
|
29
57
|
console.log('');
|
|
30
|
-
console.log(chalk.bold.cyan(' 🎬 WebTape Receiver'));
|
|
58
|
+
console.log(chalk.bold.cyan(' 🎬 WebTape Receiver') + chalk.gray(` v${VERSION}`));
|
|
31
59
|
console.log(chalk.gray(' ─────────────────────────────────'));
|
|
32
60
|
console.log(` ${chalk.green('工作区')} ${workspace.root}`);
|
|
33
61
|
console.log(` ${chalk.green('端口')} ${port}`);
|
|
34
62
|
console.log(` ${chalk.green('自动分析')} ${opts.autoAnalyze ? chalk.yellow('开启') : chalk.gray('关闭')}`);
|
|
35
|
-
console.log(` ${chalk.green('AI 后端')} ${
|
|
63
|
+
console.log(` ${chalk.green('AI 后端')} ${backend}`);
|
|
36
64
|
if (opts.model) {
|
|
37
65
|
console.log(` ${chalk.green('AI 模型')} ${opts.model}`);
|
|
38
66
|
}
|
|
@@ -42,7 +70,7 @@ program
|
|
|
42
70
|
port,
|
|
43
71
|
workspace,
|
|
44
72
|
autoAnalyze: opts.autoAnalyze,
|
|
45
|
-
analyzerBackend:
|
|
73
|
+
analyzerBackend: backend,
|
|
46
74
|
analyzerModel: opts.model,
|
|
47
75
|
onReceive(sessionDir, payload) {
|
|
48
76
|
const actions = payload.content['index.json'].filter((b) => b.action).length;
|
|
@@ -57,15 +85,9 @@ program
|
|
|
57
85
|
console.log(chalk.cyan(' ⏳ 正在启动 AI 分析…'));
|
|
58
86
|
}
|
|
59
87
|
},
|
|
60
|
-
onAnalyzeDone(
|
|
61
|
-
const relativePath = relative(workspace.root, reportPath);
|
|
62
|
-
const isInsideWorkspace = !relativePath.startsWith('..');
|
|
88
|
+
onAnalyzeDone(result) {
|
|
63
89
|
console.log('');
|
|
64
|
-
|
|
65
|
-
if (isInsideWorkspace) {
|
|
66
|
-
console.log(` ${chalk.gray('产物位置')} ${relativePath}`);
|
|
67
|
-
}
|
|
68
|
-
console.log(` ${chalk.gray('完整路径')} ${reportPath}`);
|
|
90
|
+
logAnalyzeResult(result);
|
|
69
91
|
},
|
|
70
92
|
onError(err) {
|
|
71
93
|
console.error('');
|
|
@@ -104,7 +126,7 @@ program
|
|
|
104
126
|
.option('-w, --workspace <path>', '工作区路径')
|
|
105
127
|
.action((opts) => {
|
|
106
128
|
const workspaceRoot = resolveWorkspaceRoot(opts.workspace);
|
|
107
|
-
const workspace = ensureWorkspace(workspaceRoot);
|
|
129
|
+
const workspace = ensureWorkspace(workspaceRoot, VERSION);
|
|
108
130
|
const sessions = listRecordings(workspace);
|
|
109
131
|
if (sessions.length === 0) {
|
|
110
132
|
console.log(chalk.gray('暂无录制会话。'));
|
|
@@ -123,39 +145,34 @@ program
|
|
|
123
145
|
.command('analyze <session>')
|
|
124
146
|
.description('对指定的录制会话运行 AI 分析')
|
|
125
147
|
.option('-w, --workspace <path>', '工作区路径')
|
|
126
|
-
.option('--backend <name>', 'AI 分析后端(cursor)', '
|
|
148
|
+
.option('--backend <name>', 'AI 分析后端(cursor / claude)', '')
|
|
127
149
|
.option('--model <name>', 'AI 模型名称(例如 kimi-k2.5)')
|
|
128
|
-
.option('--prompt-only', '仅生成提示词文件,不执行分析', false)
|
|
129
150
|
.action(async (session, opts) => {
|
|
130
151
|
const workspaceRoot = resolveWorkspaceRoot(opts.workspace);
|
|
131
|
-
const workspace = ensureWorkspace(workspaceRoot);
|
|
132
|
-
const sessionDir =
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
console.error(err instanceof Error ? err.message : err);
|
|
145
|
-
process.exit(1);
|
|
146
|
-
}
|
|
147
|
-
return;
|
|
152
|
+
const workspace = ensureWorkspace(workspaceRoot, VERSION);
|
|
153
|
+
const sessionDir = join(workspace.recordings, session);
|
|
154
|
+
// Resolve AI backend: CLI flag > saved config > default cursor
|
|
155
|
+
let backend;
|
|
156
|
+
const config = loadConfig();
|
|
157
|
+
if (opts.backend) {
|
|
158
|
+
backend = opts.backend;
|
|
159
|
+
}
|
|
160
|
+
else if (config.aiBackend) {
|
|
161
|
+
backend = config.aiBackend;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
backend = 'cursor';
|
|
148
165
|
}
|
|
149
|
-
const spinner = ora(`正在通过 ${
|
|
166
|
+
const spinner = ora(`正在通过 ${backend} 分析会话 ${session}…`).start();
|
|
150
167
|
try {
|
|
151
|
-
const
|
|
152
|
-
backend
|
|
168
|
+
const result = await analyzeRecording({
|
|
169
|
+
backend,
|
|
153
170
|
workspace,
|
|
154
171
|
sessionDir,
|
|
155
172
|
model: opts.model,
|
|
156
173
|
});
|
|
157
|
-
spinner.
|
|
158
|
-
|
|
174
|
+
spinner.stop();
|
|
175
|
+
logAnalyzeResult(result);
|
|
159
176
|
}
|
|
160
177
|
catch (err) {
|
|
161
178
|
spinner.fail('分析失败');
|
|
@@ -163,5 +180,97 @@ program
|
|
|
163
180
|
process.exit(1);
|
|
164
181
|
}
|
|
165
182
|
});
|
|
183
|
+
// ─── retry ───────────────────────────────────────────────────────────────────
|
|
184
|
+
program
|
|
185
|
+
.command('retry')
|
|
186
|
+
.description('重新分析所有未生成报告的录制会话')
|
|
187
|
+
.option('-w, --workspace <path>', '工作区路径')
|
|
188
|
+
.option('--backend <name>', 'AI 分析后端(cursor / claude)', '')
|
|
189
|
+
.option('--model <name>', 'AI 模型名称(例如 kimi-k2.5)')
|
|
190
|
+
.action(async (opts) => {
|
|
191
|
+
const workspaceRoot = resolveWorkspaceRoot(opts.workspace);
|
|
192
|
+
const workspace = ensureWorkspace(workspaceRoot, VERSION);
|
|
193
|
+
const unanalyzed = listUnanalyzedRecordings(workspace);
|
|
194
|
+
if (unanalyzed.length === 0) {
|
|
195
|
+
console.log(chalk.green(' ✅ 所有录制会话均已完成分析。'));
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
// Resolve AI backend: CLI flag > saved config > default cursor
|
|
199
|
+
let backend;
|
|
200
|
+
const config = loadConfig();
|
|
201
|
+
if (opts.backend) {
|
|
202
|
+
backend = opts.backend;
|
|
203
|
+
}
|
|
204
|
+
else if (config.aiBackend) {
|
|
205
|
+
backend = config.aiBackend;
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
backend = 'cursor';
|
|
209
|
+
}
|
|
210
|
+
console.log('');
|
|
211
|
+
console.log(chalk.bold(`待分析会话(共 ${unanalyzed.length} 个):`));
|
|
212
|
+
for (const s of unanalyzed) {
|
|
213
|
+
console.log(` ${chalk.cyan('●')} ${s}`);
|
|
214
|
+
}
|
|
215
|
+
console.log('');
|
|
216
|
+
for (const session of unanalyzed) {
|
|
217
|
+
const sessionDir = join(workspace.recordings, session);
|
|
218
|
+
const spinner = ora(`正在通过 ${backend} 分析会话 ${session}…`).start();
|
|
219
|
+
try {
|
|
220
|
+
const result = await analyzeRecording({
|
|
221
|
+
backend,
|
|
222
|
+
workspace,
|
|
223
|
+
sessionDir,
|
|
224
|
+
model: opts.model,
|
|
225
|
+
});
|
|
226
|
+
spinner.stop();
|
|
227
|
+
logAnalyzeResult(result);
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
spinner.fail(`分析 ${session} 失败`);
|
|
231
|
+
console.error(err instanceof Error ? err.message : err);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
// ─── config ──────────────────────────────────────────────────────────────────
|
|
236
|
+
const configCmd = program
|
|
237
|
+
.command('config')
|
|
238
|
+
.description('管理 webtape-receiver 配置');
|
|
239
|
+
configCmd
|
|
240
|
+
.command('show')
|
|
241
|
+
.description('显示当前配置')
|
|
242
|
+
.action(() => {
|
|
243
|
+
const config = loadConfig();
|
|
244
|
+
console.log('');
|
|
245
|
+
console.log(chalk.bold('当前配置:'));
|
|
246
|
+
console.log('');
|
|
247
|
+
if (Object.keys(config).length === 0) {
|
|
248
|
+
console.log(chalk.gray(' (尚无配置,使用 config set 进行设置)'));
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
if (config.aiBackend) {
|
|
252
|
+
console.log(` ${chalk.green('AI 后端')} ${config.aiBackend}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
console.log('');
|
|
256
|
+
});
|
|
257
|
+
configCmd
|
|
258
|
+
.command('set <key> <value>')
|
|
259
|
+
.description('设置配置项(可用项: aiBackend)')
|
|
260
|
+
.action((key, value) => {
|
|
261
|
+
if (key === 'aiBackend') {
|
|
262
|
+
if (!VALID_BACKENDS.includes(value)) {
|
|
263
|
+
console.error(chalk.red(` 无效值: ${value},aiBackend 仅支持 ${VALID_BACKENDS.join(' 或 ')}`));
|
|
264
|
+
process.exit(1);
|
|
265
|
+
}
|
|
266
|
+
saveConfig({ aiBackend: value });
|
|
267
|
+
console.log(chalk.green(` ✓ 已设置 aiBackend = ${value}`));
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
console.error(chalk.red(` 未知配置项: ${key}`));
|
|
271
|
+
console.log(chalk.gray(' 可用配置项: aiBackend'));
|
|
272
|
+
process.exit(1);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
166
275
|
program.parse();
|
|
167
276
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type IncomingMessage, type ServerResponse } from 'node:http';
|
|
2
2
|
import type { WorkspacePaths } from './workspace.js';
|
|
3
3
|
import type { WebTapePayload } from './types.js';
|
|
4
|
-
import { type AnalyzerBackend } from './analyzer.js';
|
|
4
|
+
import { type AnalyzerBackend, type AnalyzeResult } from './analyzer.js';
|
|
5
5
|
export interface ServerOptions {
|
|
6
6
|
port: number;
|
|
7
7
|
workspace: WorkspacePaths;
|
|
@@ -9,7 +9,7 @@ export interface ServerOptions {
|
|
|
9
9
|
analyzerBackend: AnalyzerBackend;
|
|
10
10
|
analyzerModel?: string;
|
|
11
11
|
onReceive?: (sessionDir: string, payload: WebTapePayload) => void;
|
|
12
|
-
onAnalyzeDone?: (
|
|
12
|
+
onAnalyzeDone?: (result: AnalyzeResult) => void;
|
|
13
13
|
onError?: (err: Error) => void;
|
|
14
14
|
}
|
|
15
15
|
export declare function createWebhookServer(opts: ServerOptions): {
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAEpF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,OAAO,EAAoB,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAE3F,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,cAAc,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,eAAe,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IAClE,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAChD,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CAChC;AAiCD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,aAAa;;;;EA2EtD"}
|
package/dist/server.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createServer } from 'node:http';
|
|
2
|
+
import { join } from 'node:path';
|
|
2
3
|
import { saveRecording } from './storage.js';
|
|
3
|
-
import { analyzeRecording
|
|
4
|
+
import { analyzeRecording } from './analyzer.js';
|
|
4
5
|
function readBody(req) {
|
|
5
6
|
return new Promise((resolve, reject) => {
|
|
6
7
|
const chunks = [];
|
|
@@ -73,7 +74,7 @@ export function createWebhookServer(opts) {
|
|
|
73
74
|
// Trigger analysis for a specific session
|
|
74
75
|
if (req.method === 'POST' && req.url?.startsWith('/analyze/')) {
|
|
75
76
|
const sessionName = req.url.slice('/analyze/'.length);
|
|
76
|
-
const sessionDir =
|
|
77
|
+
const sessionDir = join(workspace.recordings, sessionName);
|
|
77
78
|
try {
|
|
78
79
|
runAnalysis(workspace, sessionDir, analyzerBackend, analyzerModel, onAnalyzeDone, onError);
|
|
79
80
|
json(res, 200, { status: 'analysis_started', session: sessionDir });
|
|
@@ -84,20 +85,6 @@ export function createWebhookServer(opts) {
|
|
|
84
85
|
}
|
|
85
86
|
return;
|
|
86
87
|
}
|
|
87
|
-
// Generate prompt file for manual analysis
|
|
88
|
-
if (req.method === 'POST' && req.url?.startsWith('/prompt/')) {
|
|
89
|
-
const sessionName = req.url.slice('/prompt/'.length);
|
|
90
|
-
const sessionDir = `${workspace.recordings}/${sessionName}`;
|
|
91
|
-
try {
|
|
92
|
-
const promptPath = generatePromptFile(sessionDir);
|
|
93
|
-
json(res, 200, { status: 'prompt_generated', path: promptPath });
|
|
94
|
-
}
|
|
95
|
-
catch (err) {
|
|
96
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
97
|
-
json(res, 500, { error: message });
|
|
98
|
-
}
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
88
|
json(res, 404, { error: 'Not found' });
|
|
102
89
|
});
|
|
103
90
|
return {
|
|
@@ -112,7 +99,7 @@ export function createWebhookServer(opts) {
|
|
|
112
99
|
}
|
|
113
100
|
function runAnalysis(workspace, sessionDir, backend, model, onDone, onError) {
|
|
114
101
|
analyzeRecording({ backend, workspace, sessionDir, model })
|
|
115
|
-
.then((
|
|
102
|
+
.then((result) => onDone?.(result))
|
|
116
103
|
.catch((err) => onError?.(err instanceof Error ? err : new Error(String(err))));
|
|
117
104
|
}
|
|
118
105
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA6C,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/storage.d.ts
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import type { WorkspacePaths } from './workspace.js';
|
|
2
2
|
import type { WebTapePayload } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Extract the registered domain (一级域名) from a URL string.
|
|
5
|
+
* e.g. "https://www.github.com/page" → "github.com"
|
|
6
|
+
*/
|
|
7
|
+
export declare function extractDomain(url: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Parse a session directory name back into its components.
|
|
10
|
+
* Format: ${domain}-${MMDD}-${HHmmss}
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseSessionName(name: string): {
|
|
13
|
+
domain: string;
|
|
14
|
+
date: string;
|
|
15
|
+
time: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Format a time string "HHmmss" → "HH:mm:ss".
|
|
19
|
+
*/
|
|
20
|
+
export declare function formatTime(time: string): string;
|
|
3
21
|
/**
|
|
4
22
|
* Persist a webhook payload to the workspace as structured files:
|
|
5
23
|
*
|
|
@@ -17,4 +35,12 @@ export declare function saveRecording(workspace: WorkspacePaths, payload: WebTap
|
|
|
17
35
|
* List existing recording sessions (directory names) sorted newest-first.
|
|
18
36
|
*/
|
|
19
37
|
export declare function listRecordings(workspace: WorkspacePaths): string[];
|
|
38
|
+
/**
|
|
39
|
+
* Check whether a recording session has an analysis report.
|
|
40
|
+
*/
|
|
41
|
+
export declare function hasAnalysisReport(workspace: WorkspacePaths, sessionName: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* List recordings that do NOT have an analysis report.
|
|
44
|
+
*/
|
|
45
|
+
export declare function listUnanalyzedRecordings(workspace: WorkspacePaths): string[];
|
|
20
46
|
//# sourceMappingURL=storage.d.ts.map
|
package/dist/storage.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAqBjD;AA6BD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAQ7F;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,cAAc,EACzB,OAAO,EAAE,cAAc,GACtB,MAAM,CAsCR;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,cAAc,GAAG,MAAM,EAAE,CAUlE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAEzF;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,cAAc,GAAG,MAAM,EAAE,CAE5E"}
|
package/dist/storage.js
CHANGED
|
@@ -1,22 +1,77 @@
|
|
|
1
|
-
import { mkdirSync, writeFileSync, readdirSync } from 'node:fs';
|
|
1
|
+
import { mkdirSync, writeFileSync, readdirSync, existsSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { buildPrompt } from './analyzer.js';
|
|
4
3
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Extract the registered domain (一级域名) from a URL string.
|
|
5
|
+
* e.g. "https://www.github.com/page" → "github.com"
|
|
6
|
+
*/
|
|
7
|
+
export function extractDomain(url) {
|
|
8
|
+
try {
|
|
9
|
+
const hostname = new URL(url).hostname;
|
|
10
|
+
const clean = hostname.replace(/^www\./, '');
|
|
11
|
+
// IP addresses: keep as-is
|
|
12
|
+
if (/^\d+\.\d+\.\d+\.\d+$/.test(clean)) {
|
|
13
|
+
return clean;
|
|
14
|
+
}
|
|
15
|
+
// Get registered domain
|
|
16
|
+
const parts = clean.split('.');
|
|
17
|
+
if (parts.length <= 2)
|
|
18
|
+
return clean;
|
|
19
|
+
// Common multi-part TLDs (e.g. co.uk, com.cn, co.jp, etc.)
|
|
20
|
+
const multiPartTlds = ['co.uk', 'com.cn', 'com.au', 'co.jp', 'co.kr', 'com.br', 'com.tw', 'com.hk', 'org.uk', 'net.au'];
|
|
21
|
+
const lastTwo = parts.slice(-2).join('.');
|
|
22
|
+
if (multiPartTlds.includes(lastTwo) && parts.length > 2) {
|
|
23
|
+
return parts.slice(-3).join('.');
|
|
24
|
+
}
|
|
25
|
+
return parts.slice(-2).join('.');
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return 'unknown';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Find the primary site URL from the payload's index.json timeline.
|
|
33
|
+
* Uses the first context block that has a state with a URL.
|
|
34
|
+
*/
|
|
35
|
+
function extractSiteUrl(payload) {
|
|
36
|
+
for (const block of payload.content['index.json']) {
|
|
37
|
+
if (block.state?.url)
|
|
38
|
+
return block.state.url;
|
|
39
|
+
}
|
|
40
|
+
return '';
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Build the session directory name from the payload.
|
|
44
|
+
* Format: ${domain}-${MMDD}-${HHmmss}
|
|
45
|
+
* e.g. "github.com-0305-123000"
|
|
7
46
|
*/
|
|
8
47
|
function sessionDirName(payload) {
|
|
9
48
|
const d = new Date(payload.meta.epoch);
|
|
10
49
|
const pad = (n, len = 2) => String(n).padStart(len, '0');
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
50
|
+
const domain = extractDomain(extractSiteUrl(payload)) || 'unknown';
|
|
51
|
+
const datePart = `${pad(d.getMonth() + 1)}${pad(d.getDate())}`;
|
|
52
|
+
const timePart = `${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
|
|
53
|
+
return `${domain}-${datePart}-${timePart}`;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Parse a session directory name back into its components.
|
|
57
|
+
* Format: ${domain}-${MMDD}-${HHmmss}
|
|
58
|
+
*/
|
|
59
|
+
export function parseSessionName(name) {
|
|
60
|
+
const lastDash = name.lastIndexOf('-');
|
|
61
|
+
const time = name.slice(lastDash + 1);
|
|
62
|
+
const rest = name.slice(0, lastDash);
|
|
63
|
+
const secondLastDash = rest.lastIndexOf('-');
|
|
64
|
+
const date = rest.slice(secondLastDash + 1);
|
|
65
|
+
const domain = rest.slice(0, secondLastDash);
|
|
66
|
+
return { domain, date, time };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Format a time string "HHmmss" → "HH:mm:ss".
|
|
70
|
+
*/
|
|
71
|
+
export function formatTime(time) {
|
|
72
|
+
if (time.length !== 6)
|
|
73
|
+
return time;
|
|
74
|
+
return `${time.slice(0, 2)}:${time.slice(2, 4)}:${time.slice(4, 6)}`;
|
|
20
75
|
}
|
|
21
76
|
/**
|
|
22
77
|
* Persist a webhook payload to the workspace as structured files:
|
|
@@ -45,9 +100,6 @@ export function saveRecording(workspace, payload) {
|
|
|
45
100
|
writeFileSync(join(resDir, filename), JSON.stringify(data, null, 2), 'utf-8');
|
|
46
101
|
}
|
|
47
102
|
writeFileSync(join(sessionDir, 'meta.json'), JSON.stringify(payload.meta, null, 2), 'utf-8');
|
|
48
|
-
// Build and save the analysis prompt alongside the recording data
|
|
49
|
-
const prompt = buildPrompt(sessionDir);
|
|
50
|
-
writeFileSync(join(sessionDir, 'prompt.md'), prompt, 'utf-8');
|
|
51
103
|
return sessionDir;
|
|
52
104
|
}
|
|
53
105
|
/**
|
|
@@ -65,4 +117,16 @@ export function listRecordings(workspace) {
|
|
|
65
117
|
return [];
|
|
66
118
|
}
|
|
67
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Check whether a recording session has an analysis report.
|
|
122
|
+
*/
|
|
123
|
+
export function hasAnalysisReport(workspace, sessionName) {
|
|
124
|
+
return existsSync(join(workspace.recordings, sessionName, 'analysis_report.md'));
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* List recordings that do NOT have an analysis report.
|
|
128
|
+
*/
|
|
129
|
+
export function listUnanalyzedRecordings(workspace) {
|
|
130
|
+
return listRecordings(workspace).filter((name) => !hasAnalysisReport(workspace, name));
|
|
131
|
+
}
|
|
68
132
|
//# sourceMappingURL=storage.js.map
|
package/dist/storage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
|
package/dist/workspace.d.ts
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
export interface WorkspacePaths {
|
|
2
2
|
root: string;
|
|
3
3
|
recordings: string;
|
|
4
|
-
analyses: string;
|
|
5
4
|
}
|
|
6
5
|
/**
|
|
7
6
|
* Resolve the WebTape workspace root. Priority:
|
|
8
7
|
* 1. Explicit --workspace CLI flag
|
|
9
|
-
* 2. ~/Desktop/WebTape (macOS
|
|
8
|
+
* 2. ~/Desktop/WebTape (works on macOS and Windows)
|
|
10
9
|
*/
|
|
11
10
|
export declare function resolveWorkspaceRoot(explicit?: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Content for workspace AGENTS.md — the analysis prompt template.
|
|
13
|
+
*/
|
|
14
|
+
export declare const AGENTS_MD_CONTENT = "<!-- \u26A0\uFE0F \u6B64\u6587\u4EF6\u7531 webtape-receiver \u5DE5\u5177\u81EA\u52A8\u751F\u6210\u548C\u7EF4\u62A4\uFF0C\u8BF7\u52FF\u624B\u52A8\u4FEE\u6539 -->\n\n# WebTape \u5F55\u5236\u5206\u6790 Agent\n\n\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684 Web \u524D\u7AEF\u4E1A\u52A1\u5206\u6790\u4E13\u5BB6\u3002\u8BF7\u6839\u636E\u6307\u5B9A\u7684 WebTape \u5F55\u5236\u6570\u636E\u76EE\u5F55\uFF0C\u5206\u6790\u8BE5\u7F51\u9875\u7684\u4E1A\u52A1\u903B\u8F91\u548C\u5B8C\u6574\u63A5\u53E3\u94FE\u8DEF\u3002\n\n## \u4EFB\u52A1\n\n1. **\u68B3\u7406\u7528\u6237\u64CD\u4F5C\u6D41\u7A0B**\uFF1A\n - **\u7F51\u7AD9\u6982\u51B5\u5206\u6790**\uFF1A\u9996\u5148\u68B3\u7406\u5F55\u5236\u8BB0\u5F55\u6240\u5728\u7F51\u7AD9\u7684\u57FA\u672C\u60C5\u51B5\u3002\u4F8B\u5982\uFF1A\u8FD9\u662F B \u7AD9\u67D0\u4E2A\u7528\u6237\u7684\u4E2A\u4EBA\u4E3B\u9875\uFF0C\u9875\u9762\u4E2D\u5C55\u793A\u4E86\u6295\u7A3F\u89C6\u9891\u5217\u8868\u3001\u6536\u85CF\u5939\u3001\u7C89\u4E1D\u6570\u7B49\u4FE1\u606F\uFF0C\u53EF\u4EE5\u8FDB\u884C\u70B9\u8D5E\u3001\u6295\u5E01\u3001\u6536\u85CF\u89C6\u9891\u7B49\u64CD\u4F5C\u3002\n - **\u8FD8\u539F\u64CD\u4F5C\u8DEF\u5F84**\uFF1A\u6839\u636E `index.json` \u4E2D\u7684 `action` \u5E8F\u5217\uFF0C\u7ED3\u5408\u7F51\u7AD9\u6982\u51B5\uFF0C\u8FD8\u539F\u7528\u6237\u7684\u5B8C\u6574\u64CD\u4F5C\u8DEF\u5F84\u3002\u8FD9\u4E9B\u5185\u5BB9\u5C06\u4F5C\u4E3A\u540E\u7EED\u63A5\u53E3\u4E0E\u9875\u9762\u4E1A\u52A1\u903B\u8F91\u5173\u7CFB\u68B3\u7406\u7684\u53C2\u7167\u3002\n2. **\u5206\u6790\u63A5\u53E3\u8C03\u7528\u94FE\u8DEF**\uFF1A\n - \u5217\u51FA\u6BCF\u4E2A\u7528\u6237\u64CD\u4F5C\u89E6\u53D1\u7684\u6240\u6709 API \u8BF7\u6C42\n - \u6807\u6CE8\u8BF7\u6C42\u65B9\u6CD5\u3001URL\u3001\u72B6\u6001\u7801\n - \u5206\u6790\u8BF7\u6C42\u4E4B\u95F4\u7684\u4F9D\u8D56\u5173\u7CFB\uFF08\u4F8B\u5982\uFF1A\u767B\u5F55\u540E\u62FF\u5230 token\uFF0C\u540E\u7EED\u8BF7\u6C42\u643A\u5E26 token\uFF09\n3. **\u8BC6\u522B\u4E1A\u52A1\u6A21\u5757**\uFF1A\u6839\u636E URL \u6A21\u5F0F\u548C\u8BF7\u6C42\u5185\u5BB9\uFF0C\u5212\u5206\u4E1A\u52A1\u6A21\u5757\uFF08\u5982\uFF1A\u7528\u6237\u8BA4\u8BC1\u3001\u6570\u636E\u67E5\u8BE2\u3001\u8868\u5355\u63D0\u4EA4\u7B49\uFF09\n4. **\u751F\u6210\u63A5\u53E3\u6587\u6863\u6982\u8981**\uFF1A\u5BF9\u6BCF\u4E2A\u63A5\u53E3\u7ED9\u51FA\u7B80\u8981\u8BF4\u660E\uFF0C\u5305\u62EC\u7528\u9014\u3001\u8BF7\u6C42\u53C2\u6570\u3001\u54CD\u5E94\u7ED3\u6784\n5. **\u7ED8\u5236\u94FE\u8DEF\u56FE**\uFF1A\u7528 Mermaid \u5E8F\u5217\u56FE\u63CF\u8FF0\u6838\u5FC3\u4E1A\u52A1\u6D41\u7A0B\u7684\u63A5\u53E3\u8C03\u7528\u65F6\u5E8F\n6. **\u751F\u6210\u4E1A\u52A1\u903B\u8F91\u4EE3\u7801 (request.js)**\uFF1A\n - \u4F7F\u7528 ES Module \u683C\u5F0F\u7F16\u5199\u3002\n - \u5BFC\u51FA\u82E5\u5E72\u4E1A\u52A1\u903B\u8F91\u6D41\u7A0B\u7684 JS \u51FD\u6570\u5B9E\u73B0\u3002\n - \u6BCF\u4E2A\u5BFC\u51FA\u7684\u51FD\u6570\u90FD\u5FC5\u987B\u5BF9\u5E94\u5728\u8FD9\u4E2A\u9875\u9762\u4E2D\uFF0C\u7528\u6237\u89C6\u89D2\u7684\u4E00\u4E2A\u5B8C\u6574\u4E1A\u52A1\u8FC7\u7A0B\u3002\n - **\u4EE3\u7801\u89C4\u8303\u53C2\u8003**\uFF1A\n ```javascript\n // \u5F15\u5165 chromeFetch\uFF0C\u5176\u4E0E\u539F\u751F fetch \u65E0\u5F02\uFF0C\u4F46\u662F\u4F1A\u81EA\u52A8\u4F7F\u7528\u7535\u8111\u672C\u5730 chrome \u7684 cookie\u3002\n import { chromeFetch } from '@cpu-utils/headless'\n\n /**\n * \u83B7\u53D6\u77E5\u4E4E\u6536\u85CF\u5939\u5185\u5BB9 (\u793A\u4F8B)\n * @param {Object} params - \u4E1A\u52A1\u53C2\u6570\n * @param {string} params.userId - \u7528\u6237 ID\n */\n export async function getZhiHuCollection(params) {\n // 1. \u63D0\u53D6\u4E1A\u52A1\u903B\u8F91\u5BF9\u7528\u6237\u4F7F\u7528\u89D2\u5EA6\u6240\u9700\u7684\u63A5\u53E3\u5165\u53C2\n const { userId } = params\n \n // 2. \u5982\u679C\u83B7\u53D6\u6700\u7EC8\u54CD\u5E94\u7684\u63A5\u53E3\u9700\u8981\u524D\u7F6E\u63A5\u53E3\u8FD4\u56DE\u4F5C\u4E3A\u5165\u53C2\uFF0C\u8BF7\u5728\u6B64\u5904\u4F53\u73B0\u8BE5\u8FC7\u7A0B\n \n // 3. \u8C03\u7528\u63A5\u53E3\u5E76\u8FD4\u56DE\u7ED3\u679C\n const url = 'https://www.zhihu.com/api/v4/members/' + userId + '/collections'\n const res = await chromeFetch(url, {\n method: 'GET',\n // ... \u5176\u5B83\u539F\u751F fetch \u53C2\u6570\n })\n return res\n }\n ```\n\n## \u975E\u4E1A\u52A1\u63A5\u53E3\u5904\u7406\n\n\u5BF9\u4E8E\u4EE5\u4E0B\u7C7B\u578B\u7684\u975E\u9875\u9762\u6838\u5FC3\u4E1A\u52A1\u903B\u8F91\u63A5\u53E3\uFF0C**\u4E0D\u8981\u5C55\u5F00\u8BE6\u7EC6\u5206\u6790**\uFF0C\u4EC5\u5728\u62A5\u544A\u4E2D\u7B80\u8981\u5F52\u7C7B\u63D0\u53CA\u5373\u53EF\uFF1A\n- \u57CB\u70B9\u4E0A\u62A5\uFF08tracking / analytics\uFF09\n- \u6027\u80FD\u76D1\u63A7\uFF08performance monitoring\uFF09\n- \u9519\u8BEF\u65E5\u5FD7\u4E0A\u62A5\uFF08error reporting\uFF09\n- \u5E7F\u544A\u8BF7\u6C42\uFF08ad requests\uFF09\n- \u7B2C\u4E09\u65B9\u7EDF\u8BA1 SDK \u8BF7\u6C42\uFF08\u5982 Google Analytics\u3001\u767E\u5EA6\u7EDF\u8BA1\u7B49\uFF09\n\n\u8FD9\u4E9B\u63A5\u53E3\u5728\u5206\u6790\u62A5\u544A\u4E2D\u7EDF\u4E00\u5F52\u5165\"\u975E\u4E1A\u52A1\u8F85\u52A9\u63A5\u53E3\"\u7AE0\u8282\uFF0C\u5217\u51FA\u63A5\u53E3 URL \u6A21\u5F0F\u5373\u53EF\uFF0C\u65E0\u9700\u5206\u6790\u8BF7\u6C42\u53C2\u6570\u548C\u54CD\u5E94\u7ED3\u6784\u3002\n\n## \u6570\u636E\u7ED3\u6784\n\n\u5F55\u5236\u6570\u636E\u4F4D\u4E8E `recordings/<\u8BB0\u5F55\u540D>/` \u76EE\u5F55\u4E0B\uFF0C\u5305\u542B\uFF1A\n- `index.json` \u2014 \u7528\u6237\u64CD\u4F5C\u4E0E\u7F51\u7EDC\u8BF7\u6C42\u65F6\u95F4\u7EBF\n- `meta.json` \u2014 \u5F55\u5236\u5143\u6570\u636E\n- `requests/` \u2014 \u5404\u8BF7\u6C42\u7684\u8BE6\u7EC6\u6570\u636E\uFF08\u8BF7\u6C42\u5934\u3001\u8BF7\u6C42\u4F53\u7B49\uFF09\n- `responses/` \u2014 \u5404\u54CD\u5E94\u7684\u8BE6\u7EC6\u6570\u636E\uFF08\u72B6\u6001\u7801\u3001\u54CD\u5E94\u5934\u3001\u54CD\u5E94\u4F53\u7B49\uFF09\n\n## \u8F93\u51FA\u8981\u6C42\n\n1. **\u5206\u6790\u62A5\u544A**\uFF1AMarkdown \u683C\u5F0F\uFF0C\u4FDD\u5B58\u5230 `recordings/<\u8BB0\u5F55\u540D>/analysis_report.md`\u3002\n2. **\u4E1A\u52A1\u903B\u8F91\u4EE3\u7801**\uFF1AJavaScript \u683C\u5F0F\uFF0C\u4FDD\u5B58\u5230 `recordings/<\u8BB0\u5F55\u540D>/request.js`\u3002\n";
|
|
12
15
|
/**
|
|
13
16
|
* Ensure the workspace directory tree exists and return the resolved paths.
|
|
14
17
|
*/
|
|
15
|
-
export declare function ensureWorkspace(root: string): WorkspacePaths;
|
|
18
|
+
export declare function ensureWorkspace(root: string, version: string): WorkspacePaths;
|
|
16
19
|
//# sourceMappingURL=workspace.d.ts.map
|
package/dist/workspace.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAG9D;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,4kMAuE7B,CAAC;AAwCF;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAyB7E"}
|
package/dist/workspace.js
CHANGED
|
@@ -1,27 +1,153 @@
|
|
|
1
|
-
import { mkdirSync, existsSync } from 'node:fs';
|
|
1
|
+
import { mkdirSync, existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
|
+
import chalk from 'chalk';
|
|
4
5
|
/**
|
|
5
6
|
* Resolve the WebTape workspace root. Priority:
|
|
6
7
|
* 1. Explicit --workspace CLI flag
|
|
7
|
-
* 2. ~/Desktop/WebTape (macOS
|
|
8
|
+
* 2. ~/Desktop/WebTape (works on macOS and Windows)
|
|
8
9
|
*/
|
|
9
10
|
export function resolveWorkspaceRoot(explicit) {
|
|
10
11
|
if (explicit)
|
|
11
12
|
return explicit;
|
|
12
13
|
return join(homedir(), 'Desktop', 'WebTape');
|
|
13
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Content for workspace AGENTS.md — the analysis prompt template.
|
|
17
|
+
*/
|
|
18
|
+
export const AGENTS_MD_CONTENT = `<!-- ⚠️ 此文件由 webtape-receiver 工具自动生成和维护,请勿手动修改 -->
|
|
19
|
+
|
|
20
|
+
# WebTape 录制分析 Agent
|
|
21
|
+
|
|
22
|
+
你是一个专业的 Web 前端业务分析专家。请根据指定的 WebTape 录制数据目录,分析该网页的业务逻辑和完整接口链路。
|
|
23
|
+
|
|
24
|
+
## 任务
|
|
25
|
+
|
|
26
|
+
1. **梳理用户操作流程**:
|
|
27
|
+
- **网站概况分析**:首先梳理录制记录所在网站的基本情况。例如:这是 B 站某个用户的个人主页,页面中展示了投稿视频列表、收藏夹、粉丝数等信息,可以进行点赞、投币、收藏视频等操作。
|
|
28
|
+
- **还原操作路径**:根据 \`index.json\` 中的 \`action\` 序列,结合网站概况,还原用户的完整操作路径。这些内容将作为后续接口与页面业务逻辑关系梳理的参照。
|
|
29
|
+
2. **分析接口调用链路**:
|
|
30
|
+
- 列出每个用户操作触发的所有 API 请求
|
|
31
|
+
- 标注请求方法、URL、状态码
|
|
32
|
+
- 分析请求之间的依赖关系(例如:登录后拿到 token,后续请求携带 token)
|
|
33
|
+
3. **识别业务模块**:根据 URL 模式和请求内容,划分业务模块(如:用户认证、数据查询、表单提交等)
|
|
34
|
+
4. **生成接口文档概要**:对每个接口给出简要说明,包括用途、请求参数、响应结构
|
|
35
|
+
5. **绘制链路图**:用 Mermaid 序列图描述核心业务流程的接口调用时序
|
|
36
|
+
6. **生成业务逻辑代码 (request.js)**:
|
|
37
|
+
- 使用 ES Module 格式编写。
|
|
38
|
+
- 导出若干业务逻辑流程的 JS 函数实现。
|
|
39
|
+
- 每个导出的函数都必须对应在这个页面中,用户视角的一个完整业务过程。
|
|
40
|
+
- **代码规范参考**:
|
|
41
|
+
\`\`\`javascript
|
|
42
|
+
// 引入 chromeFetch,其与原生 fetch 无异,但是会自动使用电脑本地 chrome 的 cookie。
|
|
43
|
+
import { chromeFetch } from '@cpu-utils/headless'
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 获取知乎收藏夹内容 (示例)
|
|
47
|
+
* @param {Object} params - 业务参数
|
|
48
|
+
* @param {string} params.userId - 用户 ID
|
|
49
|
+
*/
|
|
50
|
+
export async function getZhiHuCollection(params) {
|
|
51
|
+
// 1. 提取业务逻辑对用户使用角度所需的接口入参
|
|
52
|
+
const { userId } = params
|
|
53
|
+
|
|
54
|
+
// 2. 如果获取最终响应的接口需要前置接口返回作为入参,请在此处体现该过程
|
|
55
|
+
|
|
56
|
+
// 3. 调用接口并返回结果
|
|
57
|
+
const url = 'https://www.zhihu.com/api/v4/members/' + userId + '/collections'
|
|
58
|
+
const res = await chromeFetch(url, {
|
|
59
|
+
method: 'GET',
|
|
60
|
+
// ... 其它原生 fetch 参数
|
|
61
|
+
})
|
|
62
|
+
return res
|
|
63
|
+
}
|
|
64
|
+
\`\`\`
|
|
65
|
+
|
|
66
|
+
## 非业务接口处理
|
|
67
|
+
|
|
68
|
+
对于以下类型的非页面核心业务逻辑接口,**不要展开详细分析**,仅在报告中简要归类提及即可:
|
|
69
|
+
- 埋点上报(tracking / analytics)
|
|
70
|
+
- 性能监控(performance monitoring)
|
|
71
|
+
- 错误日志上报(error reporting)
|
|
72
|
+
- 广告请求(ad requests)
|
|
73
|
+
- 第三方统计 SDK 请求(如 Google Analytics、百度统计等)
|
|
74
|
+
|
|
75
|
+
这些接口在分析报告中统一归入"非业务辅助接口"章节,列出接口 URL 模式即可,无需分析请求参数和响应结构。
|
|
76
|
+
|
|
77
|
+
## 数据结构
|
|
78
|
+
|
|
79
|
+
录制数据位于 \`recordings/<记录名>/\` 目录下,包含:
|
|
80
|
+
- \`index.json\` — 用户操作与网络请求时间线
|
|
81
|
+
- \`meta.json\` — 录制元数据
|
|
82
|
+
- \`requests/\` — 各请求的详细数据(请求头、请求体等)
|
|
83
|
+
- \`responses/\` — 各响应的详细数据(状态码、响应头、响应体等)
|
|
84
|
+
|
|
85
|
+
## 输出要求
|
|
86
|
+
|
|
87
|
+
1. **分析报告**:Markdown 格式,保存到 \`recordings/<记录名>/analysis_report.md\`。
|
|
88
|
+
2. **业务逻辑代码**:JavaScript 格式,保存到 \`recordings/<记录名>/request.js\`。
|
|
89
|
+
`;
|
|
90
|
+
/**
|
|
91
|
+
* Ensure workspace template files (package.json, AGENTS.md) are up-to-date.
|
|
92
|
+
* Re-writes them whenever the CLI version changes.
|
|
93
|
+
* Returns whether the templates were written.
|
|
94
|
+
*/
|
|
95
|
+
function ensureWorkspaceTemplates(root, version) {
|
|
96
|
+
const pkgPath = join(root, 'package.json');
|
|
97
|
+
const agentsPath = join(root, 'AGENTS.md');
|
|
98
|
+
let needsUpdate = false;
|
|
99
|
+
if (!existsSync(pkgPath)) {
|
|
100
|
+
needsUpdate = true;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
try {
|
|
104
|
+
const existing = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
105
|
+
if (existing.version !== version) {
|
|
106
|
+
needsUpdate = true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
needsUpdate = true;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (needsUpdate || !existsSync(agentsPath)) {
|
|
114
|
+
const pkg = {
|
|
115
|
+
name: 'webtape-workspace',
|
|
116
|
+
version,
|
|
117
|
+
private: true,
|
|
118
|
+
description: 'WebTape 录制工作区,由 webtape-receiver CLI 维护',
|
|
119
|
+
};
|
|
120
|
+
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
|
|
121
|
+
writeFileSync(agentsPath, AGENTS_MD_CONTENT, 'utf-8');
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
14
126
|
/**
|
|
15
127
|
* Ensure the workspace directory tree exists and return the resolved paths.
|
|
16
128
|
*/
|
|
17
|
-
export function ensureWorkspace(root) {
|
|
129
|
+
export function ensureWorkspace(root, version) {
|
|
18
130
|
const recordings = join(root, 'recordings');
|
|
19
|
-
|
|
20
|
-
for (const dir of [root, recordings
|
|
131
|
+
let createdRoot = false;
|
|
132
|
+
for (const dir of [root, recordings]) {
|
|
21
133
|
if (!existsSync(dir)) {
|
|
22
134
|
mkdirSync(dir, { recursive: true });
|
|
135
|
+
if (dir === root)
|
|
136
|
+
createdRoot = true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const templatesWritten = ensureWorkspaceTemplates(root, version);
|
|
140
|
+
if (createdRoot) {
|
|
141
|
+
console.log(chalk.green(' 📁 已创建工作区目录: ' + root));
|
|
142
|
+
}
|
|
143
|
+
if (templatesWritten) {
|
|
144
|
+
if (!createdRoot) {
|
|
145
|
+
console.log(chalk.green(' 📄 已更新工作区模板文件 (v' + version + '): ' + root));
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
console.log(chalk.green(' 📄 已生成工作区模板文件 (v' + version + ')'));
|
|
23
149
|
}
|
|
24
150
|
}
|
|
25
|
-
return { root, recordings
|
|
151
|
+
return { root, recordings };
|
|
26
152
|
}
|
|
27
153
|
//# sourceMappingURL=workspace.js.map
|
package/dist/workspace.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED