webtape 1.7.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.
- package/README.md +99 -0
- package/dist/analyzer.d.ts +27 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzer.js +128 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/config.d.ts +36 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +158 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +4 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +276 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +326 -0
- package/dist/index.js.map +1 -0
- package/dist/install.d.ts +17 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +235 -0
- package/dist/install.js.map +1 -0
- package/dist/native-host.d.ts +15 -0
- package/dist/native-host.d.ts.map +1 -0
- package/dist/native-host.js +129 -0
- package/dist/native-host.js.map +1 -0
- package/dist/rules.d.ts +59 -0
- package/dist/rules.d.ts.map +1 -0
- package/dist/rules.js +115 -0
- package/dist/rules.js.map +1 -0
- package/dist/server.d.ts +32 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +122 -0
- package/dist/server.js.map +1 -0
- package/dist/storage.d.ts +48 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +271 -0
- package/dist/storage.js.map +1 -0
- package/dist/templates/context.md.ejs +79 -0
- package/dist/types.d.ts +103 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/workspace.d.ts +15 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +128 -0
- package/dist/workspace.js.map +1 -0
- package/dist/workspace.zip +0 -0
- package/package.json +52 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* webtape install — registers the Native Messaging host with Chrome/Edge/Brave
|
|
3
|
+
* and opens the Chrome Web Store page for the extension.
|
|
4
|
+
*
|
|
5
|
+
* The host manifest is written to the OS-specific NativeMessagingHosts directory.
|
|
6
|
+
* After installation, Chrome will spawn the webtape binary on-demand whenever
|
|
7
|
+
* the extension calls chrome.runtime.connectNative('com.webtape.receiver').
|
|
8
|
+
*/
|
|
9
|
+
export declare const HOST_NAME = "com.webtape.receiver";
|
|
10
|
+
/** Chrome Web Store extension URL — update when published */
|
|
11
|
+
export declare const CWS_URL = "https://chrome.google.com/webstore/detail/webtape/pending";
|
|
12
|
+
export interface InstallOptions {
|
|
13
|
+
extensionId?: string;
|
|
14
|
+
openStore?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare function runInstall(opts?: InstallOptions): Promise<void>;
|
|
17
|
+
//# sourceMappingURL=install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAcH,eAAO,MAAM,SAAS,yBAAyB,CAAC;AAEhD,6DAA6D;AAC7D,eAAO,MAAM,OAAO,8DACyC,CAAC;AAuK9D,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAsB,UAAU,CAAC,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmEzE"}
|
package/dist/install.js
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* webtape install — registers the Native Messaging host with Chrome/Edge/Brave
|
|
3
|
+
* and opens the Chrome Web Store page for the extension.
|
|
4
|
+
*
|
|
5
|
+
* The host manifest is written to the OS-specific NativeMessagingHosts directory.
|
|
6
|
+
* After installation, Chrome will spawn the webtape binary on-demand whenever
|
|
7
|
+
* the extension calls chrome.runtime.connectNative('com.webtape.receiver').
|
|
8
|
+
*/
|
|
9
|
+
import { writeFileSync, mkdirSync, existsSync, chmodSync, readFileSync, } from 'node:fs';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
import { homedir, platform } from 'node:os';
|
|
12
|
+
import { execSync, execFile } from 'node:child_process';
|
|
13
|
+
import chalk from 'chalk';
|
|
14
|
+
export const HOST_NAME = 'com.webtape.receiver';
|
|
15
|
+
/** Chrome Web Store extension URL — update when published */
|
|
16
|
+
export const CWS_URL = 'https://chrome.google.com/webstore/detail/webtape/pending';
|
|
17
|
+
/**
|
|
18
|
+
* Paths where Chrome (and Chromium-family browsers) look for NativeMessagingHosts
|
|
19
|
+
* on each OS.
|
|
20
|
+
*/
|
|
21
|
+
function getNativeMessagingDirs() {
|
|
22
|
+
const os = platform();
|
|
23
|
+
const home = homedir();
|
|
24
|
+
if (os === 'darwin') {
|
|
25
|
+
return [
|
|
26
|
+
{
|
|
27
|
+
label: 'Chrome',
|
|
28
|
+
path: join(home, 'Library', 'Application Support', 'Google', 'Chrome', 'NativeMessagingHosts'),
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
label: 'Chromium',
|
|
32
|
+
path: join(home, 'Library', 'Application Support', 'Chromium', 'NativeMessagingHosts'),
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
label: 'Brave',
|
|
36
|
+
path: join(home, 'Library', 'Application Support', 'BraveSoftware', 'Brave-Browser', 'NativeMessagingHosts'),
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
label: 'Edge',
|
|
40
|
+
path: join(home, 'Library', 'Application Support', 'Microsoft Edge', 'NativeMessagingHosts'),
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
if (os === 'linux') {
|
|
45
|
+
return [
|
|
46
|
+
{
|
|
47
|
+
label: 'Chrome',
|
|
48
|
+
path: join(home, '.config', 'google-chrome', 'NativeMessagingHosts'),
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
label: 'Chromium',
|
|
52
|
+
path: join(home, '.config', 'chromium', 'NativeMessagingHosts'),
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
label: 'Brave',
|
|
56
|
+
path: join(home, '.config', 'BraveSoftware', 'Brave-Browser', 'NativeMessagingHosts'),
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
label: 'Edge',
|
|
60
|
+
path: join(home, '.config', 'microsoft-edge', 'NativeMessagingHosts'),
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
}
|
|
64
|
+
if (os === 'win32') {
|
|
65
|
+
// On Windows, registration goes to the registry; we write a helper manifest
|
|
66
|
+
// to APPDATA and then set the registry key.
|
|
67
|
+
return [
|
|
68
|
+
{
|
|
69
|
+
label: 'Windows (APPDATA)',
|
|
70
|
+
path: join(process.env.APPDATA ?? join(home, 'AppData', 'Roaming'), 'WebTape', 'NativeMessagingHosts'),
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Resolve the absolute path to the webtape executable (i.e. this process).
|
|
78
|
+
*/
|
|
79
|
+
function resolveExecutablePath() {
|
|
80
|
+
// When installed via npm -g, `process.execPath` is node and argv[1] is the script.
|
|
81
|
+
// We want the wrapper script (the `bin` entry), not node itself.
|
|
82
|
+
// The npm bin wrapper lives adjacent to node or in npm's bin dir.
|
|
83
|
+
try {
|
|
84
|
+
const result = execSync('which webtape', { encoding: 'utf-8' }).trim();
|
|
85
|
+
if (result && existsSync(result))
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// fall through
|
|
90
|
+
}
|
|
91
|
+
// Fallback: use node + the current script as the host command
|
|
92
|
+
return process.argv[1];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Build the Native Messaging host manifest JSON.
|
|
96
|
+
*/
|
|
97
|
+
function buildManifest(executablePath, extensionId) {
|
|
98
|
+
const os = platform();
|
|
99
|
+
if (os === 'win32') {
|
|
100
|
+
return {
|
|
101
|
+
name: HOST_NAME,
|
|
102
|
+
description: 'WebTape Native Messaging Host',
|
|
103
|
+
path: executablePath,
|
|
104
|
+
type: 'stdio',
|
|
105
|
+
allowed_origins: [`chrome-extension://${extensionId}/`],
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
name: HOST_NAME,
|
|
110
|
+
description: 'WebTape Native Messaging Host',
|
|
111
|
+
path: executablePath,
|
|
112
|
+
type: 'stdio',
|
|
113
|
+
allowed_origins: [`chrome-extension://${extensionId}/`],
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function writeWindowsRegistry(manifestPath) {
|
|
117
|
+
try {
|
|
118
|
+
execSync(`reg add "HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\${HOST_NAME}" /ve /d "${manifestPath}" /f`, { stdio: 'ignore' });
|
|
119
|
+
console.log(chalk.green(' ✓ Chrome (Registry)'));
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
console.log(chalk.yellow(' ⚠ 无法写入 Chrome 注册表,请手动添加'));
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
execSync(`reg add "HKCU\\Software\\Microsoft\\Edge\\NativeMessagingHosts\\${HOST_NAME}" /ve /d "${manifestPath}" /f`, { stdio: 'ignore' });
|
|
126
|
+
console.log(chalk.green(' ✓ Edge (Registry)'));
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// Edge is optional
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function openUrl(url) {
|
|
133
|
+
const os = platform();
|
|
134
|
+
try {
|
|
135
|
+
if (os === 'darwin')
|
|
136
|
+
execFile('open', [url]);
|
|
137
|
+
else if (os === 'win32')
|
|
138
|
+
execFile('cmd', ['/c', 'start', '', url]);
|
|
139
|
+
else
|
|
140
|
+
execFile('xdg-open', [url]);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// Best effort
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Read the extension ID from the built manifest file (if available in the
|
|
148
|
+
* package root — used for development). In production the user provides it
|
|
149
|
+
* or it defaults to the published ID.
|
|
150
|
+
*/
|
|
151
|
+
function readExtensionIdFromManifest() {
|
|
152
|
+
// Walk up from __dirname to find the root manifest.json
|
|
153
|
+
let dir = new URL('..', import.meta.url).pathname;
|
|
154
|
+
for (let i = 0; i < 5; i++) {
|
|
155
|
+
const candidate = join(dir, 'manifest.json');
|
|
156
|
+
if (existsSync(candidate)) {
|
|
157
|
+
try {
|
|
158
|
+
const json = JSON.parse(readFileSync(candidate, 'utf-8'));
|
|
159
|
+
if (json.key) {
|
|
160
|
+
// CRX key → ID derivation is non-trivial; skip for now
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
// ignore
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
dir = join(dir, '..');
|
|
169
|
+
}
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
export async function runInstall(opts = {}) {
|
|
173
|
+
console.log('');
|
|
174
|
+
console.log(chalk.bold.cyan(' 🔧 WebTape — 安装 Native Messaging Host'));
|
|
175
|
+
console.log(chalk.gray(' ─────────────────────────────────────────'));
|
|
176
|
+
console.log('');
|
|
177
|
+
const extensionId = opts.extensionId ?? readExtensionIdFromManifest() ?? 'PENDING_EXTENSION_ID';
|
|
178
|
+
const executablePath = resolveExecutablePath();
|
|
179
|
+
const manifest = buildManifest(executablePath, extensionId);
|
|
180
|
+
const manifestJson = JSON.stringify(manifest, null, 2);
|
|
181
|
+
const os = platform();
|
|
182
|
+
console.log(` ${chalk.green('可执行文件')} ${executablePath}`);
|
|
183
|
+
console.log(` ${chalk.green('扩展 ID')} ${extensionId}`);
|
|
184
|
+
console.log('');
|
|
185
|
+
const dirs = getNativeMessagingDirs();
|
|
186
|
+
if (os === 'win32') {
|
|
187
|
+
// On Windows: write a single manifest file and register in the registry
|
|
188
|
+
const winDir = dirs[0].path;
|
|
189
|
+
mkdirSync(winDir, { recursive: true });
|
|
190
|
+
const manifestPath = join(winDir, `${HOST_NAME}.json`);
|
|
191
|
+
writeFileSync(manifestPath, manifestJson, 'utf-8');
|
|
192
|
+
console.log(chalk.green(` ✓ 已写入 manifest → ${manifestPath}`));
|
|
193
|
+
console.log('');
|
|
194
|
+
console.log(' 正在写入 Windows 注册表…');
|
|
195
|
+
writeWindowsRegistry(manifestPath);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
console.log(' 正在写入 NativeMessagingHosts manifest…');
|
|
199
|
+
console.log('');
|
|
200
|
+
for (const dir of dirs) {
|
|
201
|
+
try {
|
|
202
|
+
mkdirSync(dir.path, { recursive: true });
|
|
203
|
+
const manifestPath = join(dir.path, `${HOST_NAME}.json`);
|
|
204
|
+
writeFileSync(manifestPath, manifestJson, 'utf-8');
|
|
205
|
+
console.log(chalk.green(` ✓ ${dir.label}: ${manifestPath}`));
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
console.log(chalk.gray(` - ${dir.label}: 跳过 (${err.message})`));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Ensure the executable is executable
|
|
212
|
+
try {
|
|
213
|
+
chmodSync(executablePath, 0o755);
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// ignore
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
console.log('');
|
|
220
|
+
console.log(chalk.green(' ✅ Native Messaging Host 注册完成'));
|
|
221
|
+
console.log('');
|
|
222
|
+
if (opts.openStore !== false) {
|
|
223
|
+
console.log(chalk.cyan(' 正在打开 Chrome 插件安装页…'));
|
|
224
|
+
openUrl(CWS_URL);
|
|
225
|
+
console.log(chalk.gray(' 请在浏览器中点击"添加到 Chrome"完成插件安装。'));
|
|
226
|
+
console.log('');
|
|
227
|
+
console.log(chalk.gray(' 提示:如果浏览器没有自动打开,请手动访问:'));
|
|
228
|
+
console.log(chalk.cyan(` ${CWS_URL}`));
|
|
229
|
+
}
|
|
230
|
+
console.log('');
|
|
231
|
+
console.log(chalk.bold(' 安装完成!'));
|
|
232
|
+
console.log(chalk.gray(' 录制时直接点击插件图标,无需任何额外操作。'));
|
|
233
|
+
console.log('');
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Messaging host entry point.
|
|
3
|
+
*
|
|
4
|
+
* Chrome spawns this process on-demand when the extension calls
|
|
5
|
+
* chrome.runtime.connectNative('com.webtape.receiver').
|
|
6
|
+
*
|
|
7
|
+
* Protocol: each message is prefixed with a 4-byte little-endian length (uint32).
|
|
8
|
+
* Chrome manages the process lifecycle; we exit after handling the message.
|
|
9
|
+
*/
|
|
10
|
+
export declare function runNativeHost(): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Run analysis for a session directory (called from the detached subprocess).
|
|
13
|
+
*/
|
|
14
|
+
export declare function runDetachedAnalysis(sessionDir: string, backend: string, model?: string): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=native-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-host.d.ts","sourceRoot":"","sources":["../src/native-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2DH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CA0DnD;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAmBf"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Messaging host entry point.
|
|
3
|
+
*
|
|
4
|
+
* Chrome spawns this process on-demand when the extension calls
|
|
5
|
+
* chrome.runtime.connectNative('com.webtape.receiver').
|
|
6
|
+
*
|
|
7
|
+
* Protocol: each message is prefixed with a 4-byte little-endian length (uint32).
|
|
8
|
+
* Chrome manages the process lifecycle; we exit after handling the message.
|
|
9
|
+
*/
|
|
10
|
+
import { resolveWorkspaceRoot, ensureWorkspace } from './workspace.js';
|
|
11
|
+
import { saveRecording } from './storage.js';
|
|
12
|
+
import { analyzeRecording } from './analyzer.js';
|
|
13
|
+
import { loadConfig } from './config.js';
|
|
14
|
+
import { spawn } from 'node:child_process';
|
|
15
|
+
import { existsSync } from 'node:fs';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
const VERSION = '1.7.0';
|
|
18
|
+
function readNativeMessage() {
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
const chunks = [];
|
|
21
|
+
let headerBuf = Buffer.alloc(0);
|
|
22
|
+
let expectedLen = null;
|
|
23
|
+
let body = Buffer.alloc(0);
|
|
24
|
+
process.stdin.on('data', (chunk) => {
|
|
25
|
+
if (expectedLen === null) {
|
|
26
|
+
headerBuf = Buffer.concat([headerBuf, chunk]);
|
|
27
|
+
if (headerBuf.length >= 4) {
|
|
28
|
+
expectedLen = headerBuf.readUInt32LE(0);
|
|
29
|
+
body = headerBuf.slice(4);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
body = Buffer.concat([body, chunk]);
|
|
34
|
+
}
|
|
35
|
+
if (expectedLen !== null && body.length >= expectedLen) {
|
|
36
|
+
resolve(body.slice(0, expectedLen));
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
process.stdin.on('error', reject);
|
|
40
|
+
process.stdin.on('end', () => {
|
|
41
|
+
if (expectedLen === null || body.length < expectedLen) {
|
|
42
|
+
reject(new Error('stdin closed before full message received'));
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function writeNativeMessage(obj) {
|
|
48
|
+
const json = JSON.stringify(obj);
|
|
49
|
+
const buf = Buffer.from(json, 'utf-8');
|
|
50
|
+
const header = Buffer.alloc(4);
|
|
51
|
+
header.writeUInt32LE(buf.length, 0);
|
|
52
|
+
process.stdout.write(Buffer.concat([header, buf]));
|
|
53
|
+
}
|
|
54
|
+
function getHostScriptPath() {
|
|
55
|
+
return fileURLToPath(import.meta.url);
|
|
56
|
+
}
|
|
57
|
+
export async function runNativeHost() {
|
|
58
|
+
let payload;
|
|
59
|
+
try {
|
|
60
|
+
const raw = await readNativeMessage();
|
|
61
|
+
const msg = JSON.parse(raw.toString('utf-8'));
|
|
62
|
+
if (msg.type === 'ping') {
|
|
63
|
+
writeNativeMessage({ type: 'pong', version: VERSION });
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
if (msg.type !== 'recording') {
|
|
67
|
+
writeNativeMessage({ type: 'error', error: `Unknown message type: ${msg.type}` });
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
payload = msg.payload;
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
writeNativeMessage({ type: 'error', error: String(err) });
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
let sessionDir;
|
|
77
|
+
try {
|
|
78
|
+
const workspaceRoot = resolveWorkspaceRoot();
|
|
79
|
+
const workspace = ensureWorkspace(workspaceRoot, VERSION);
|
|
80
|
+
sessionDir = saveRecording(workspace, payload);
|
|
81
|
+
writeNativeMessage({ type: 'received', session: sessionDir });
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
writeNativeMessage({ type: 'error', error: String(err) });
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
// Spawn a detached child process to run AI analysis so the native host
|
|
88
|
+
// can exit immediately (Chrome does not need to keep it alive).
|
|
89
|
+
const config = loadConfig();
|
|
90
|
+
const backend = config.aiBackend ?? 'cursor';
|
|
91
|
+
if (backend !== 'none') {
|
|
92
|
+
try {
|
|
93
|
+
const hostScript = getHostScriptPath();
|
|
94
|
+
const child = spawn(process.execPath, [hostScript, '--analyze', sessionDir, '--backend', backend, ...(config.aiModel ? ['--model', config.aiModel] : [])], {
|
|
95
|
+
detached: true,
|
|
96
|
+
stdio: 'ignore',
|
|
97
|
+
env: process.env,
|
|
98
|
+
});
|
|
99
|
+
child.unref();
|
|
100
|
+
}
|
|
101
|
+
catch (_err) {
|
|
102
|
+
// Analysis spawn failure is non-fatal; data is already saved
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
process.exit(0);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Run analysis for a session directory (called from the detached subprocess).
|
|
109
|
+
*/
|
|
110
|
+
export async function runDetachedAnalysis(sessionDir, backend, model) {
|
|
111
|
+
const workspaceRoot = resolveWorkspaceRoot();
|
|
112
|
+
const workspace = ensureWorkspace(workspaceRoot, VERSION);
|
|
113
|
+
if (!existsSync(sessionDir)) {
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
await analyzeRecording({
|
|
118
|
+
backend: backend,
|
|
119
|
+
workspace,
|
|
120
|
+
sessionDir,
|
|
121
|
+
model,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
catch (_err) {
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
process.exit(0);
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=native-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-host.js","sourceRoot":"","sources":["../src/native-host.ts"],"names":[],"mappings":"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"}
|
package/dist/rules.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* webtape-receiver 接收/呈现层规则 — 集中管理
|
|
3
|
+
*
|
|
4
|
+
* ┌─────────────────────────────────────────────────────────────────────┐
|
|
5
|
+
* │ 边界说明 │
|
|
6
|
+
* │ │
|
|
7
|
+
* │ 插件层(根目录 rules.js) → 控制「采集什么」 │
|
|
8
|
+
* │ 哪些网络请求要录制、哪些用户操作要捕获、时间窗口参数、 │
|
|
9
|
+
* │ A11y 树过滤等。 │
|
|
10
|
+
* │ │
|
|
11
|
+
* │ 接收层(本文件) → 控制「如何呈现」 │
|
|
12
|
+
* │ 导出 JSON / _context.md 综述时的头噪音过滤、body 截断阈值、 │
|
|
13
|
+
* │ 协议过滤(只在 context 中展示 HTTPS/WSS)、时间线加工规则 │
|
|
14
|
+
* │ (如移除首个误捕获 CLICK)、cookie 脱敏等。 │
|
|
15
|
+
* └─────────────────────────────────────────────────────────────────────┘
|
|
16
|
+
*/
|
|
17
|
+
/** 精确匹配的噪音 header 名(全部小写)— 请求+响应均适用 */
|
|
18
|
+
export declare const NOISE_HEADERS: Set<string>;
|
|
19
|
+
/** 仅请求:浏览器几乎总会带的头,context 中不展示 */
|
|
20
|
+
export declare const NOISE_HEADERS_REQUEST_ONLY: Set<string>;
|
|
21
|
+
/** 仅响应:CDN/网关追踪、耗时类,对业务链综述价值低 */
|
|
22
|
+
export declare const NOISE_HEADERS_RESPONSE_ONLY: Set<string>;
|
|
23
|
+
/** 前缀匹配的噪音 header 名(全部小写) */
|
|
24
|
+
export declare const NOISE_HEADER_PREFIXES: string[];
|
|
25
|
+
/**
|
|
26
|
+
* 判断一个 header 是否为噪音(应在 context 综述中过滤掉)。
|
|
27
|
+
* @param role 传入 `request` / `response` 时可应用按侧过滤(如 UA、content-type、eo-*)。
|
|
28
|
+
*/
|
|
29
|
+
export declare function isNoiseHeader(name: string, role?: 'request' | 'response'): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* 需要脱敏渲染的 header 名 → 处理策略。
|
|
32
|
+
* - 'cookie' → 只显示 cookie 名称列表,不显示值
|
|
33
|
+
* - 'set-cookie' → 只提示存在
|
|
34
|
+
*/
|
|
35
|
+
export declare const SENSITIVE_HEADER_RULES: Record<string, 'cookie_names' | 'presence_only'>;
|
|
36
|
+
/** header 值的最大显示长度,超出截断 */
|
|
37
|
+
export declare const HEADER_VALUE_MAX_LENGTH = 300;
|
|
38
|
+
/** body 全文展示阈值(JS 字符串 .length),不超过则完整写入 context */
|
|
39
|
+
export declare const BODY_FULL_LIMIT = 1000;
|
|
40
|
+
/** 超过 BODY_FULL_LIMIT 时,依据 UTF-8 字节数选择提示语气 */
|
|
41
|
+
export declare const BODY_OVERSIZE_HINT_LT_LARGE: number;
|
|
42
|
+
export declare const BODY_OVERSIZE_HINT_LT_HUGE: number;
|
|
43
|
+
/**
|
|
44
|
+
* 不允许出现在 context 综述中的协议。
|
|
45
|
+
* 即:纯 http / ws 的请求会被过滤掉(只保留 https / wss 等)。
|
|
46
|
+
*/
|
|
47
|
+
export declare const DISALLOWED_PROTOCOLS: Set<string>;
|
|
48
|
+
/**
|
|
49
|
+
* 判断 URL 对应的协议是否允许出现在 context 综述中。
|
|
50
|
+
* 返回 true 表示允许(即非 http/ws)。
|
|
51
|
+
*/
|
|
52
|
+
export declare function isAllowedProtocol(url: string): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* 是否移除时间线中第一个 CLICK 操作。
|
|
55
|
+
* 录制启动时用户点击"开始录制"按钮通常会被 content script 捕获为第一个 CLICK,
|
|
56
|
+
* 属于误捕获,应在呈现时剔除。
|
|
57
|
+
*/
|
|
58
|
+
export declare const STRIP_FIRST_CLICK = true;
|
|
59
|
+
//# sourceMappingURL=rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,uCAAuC;AACvC,eAAO,MAAM,aAAa,aAOxB,CAAC;AAEH,kCAAkC;AAClC,eAAO,MAAM,0BAA0B,aAErC,CAAC;AAEH,iCAAiC;AACjC,eAAO,MAAM,2BAA2B,aAEtC,CAAC;AAEH,6BAA6B;AAC7B,eAAO,MAAM,qBAAqB,UAIjC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,SAAS,GAAG,UAAU,GAC5B,OAAO,CAUT;AAMD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,eAAe,CAGnF,CAAC;AAEF,2BAA2B;AAC3B,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAM3C,mDAAmD;AACnD,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC,8CAA8C;AAC9C,eAAO,MAAM,2BAA2B,QAAY,CAAC;AACrD,eAAO,MAAM,0BAA0B,QAAa,CAAC;AAMrD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,aAA4B,CAAC;AAE9D;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOtD;AAMD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC"}
|
package/dist/rules.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* webtape-receiver 接收/呈现层规则 — 集中管理
|
|
3
|
+
*
|
|
4
|
+
* ┌─────────────────────────────────────────────────────────────────────┐
|
|
5
|
+
* │ 边界说明 │
|
|
6
|
+
* │ │
|
|
7
|
+
* │ 插件层(根目录 rules.js) → 控制「采集什么」 │
|
|
8
|
+
* │ 哪些网络请求要录制、哪些用户操作要捕获、时间窗口参数、 │
|
|
9
|
+
* │ A11y 树过滤等。 │
|
|
10
|
+
* │ │
|
|
11
|
+
* │ 接收层(本文件) → 控制「如何呈现」 │
|
|
12
|
+
* │ 导出 JSON / _context.md 综述时的头噪音过滤、body 截断阈值、 │
|
|
13
|
+
* │ 协议过滤(只在 context 中展示 HTTPS/WSS)、时间线加工规则 │
|
|
14
|
+
* │ (如移除首个误捕获 CLICK)、cookie 脱敏等。 │
|
|
15
|
+
* └─────────────────────────────────────────────────────────────────────┘
|
|
16
|
+
*/
|
|
17
|
+
// =========================================================================
|
|
18
|
+
// 1. Header Noise Filtering — context 综述中过滤掉的无关请求/响应头
|
|
19
|
+
// =========================================================================
|
|
20
|
+
/** 精确匹配的噪音 header 名(全部小写)— 请求+响应均适用 */
|
|
21
|
+
export const NOISE_HEADERS = new Set([
|
|
22
|
+
'accept-encoding', 'accept-language', 'cache-control', 'connection',
|
|
23
|
+
'content-length', 'content-type', 'dnt', 'etag', 'if-modified-since',
|
|
24
|
+
'if-none-match', 'keep-alive', 'pragma', 'server', 'vary', 'date', 'age',
|
|
25
|
+
'expires', 'last-modified', 'transfer-encoding', 'x-powered-by',
|
|
26
|
+
'x-request-id', 'x-frame-options', 'x-content-type-options',
|
|
27
|
+
'x-xss-protection',
|
|
28
|
+
]);
|
|
29
|
+
/** 仅请求:浏览器几乎总会带的头,context 中不展示 */
|
|
30
|
+
export const NOISE_HEADERS_REQUEST_ONLY = new Set([
|
|
31
|
+
'accept', 'origin', 'referer', 'user-agent', 'x-requested-with',
|
|
32
|
+
]);
|
|
33
|
+
/** 仅响应:CDN/网关追踪、耗时类,对业务链综述价值低 */
|
|
34
|
+
export const NOISE_HEADERS_RESPONSE_ONLY = new Set([
|
|
35
|
+
'server-timing', 'x-req-id', 'x-server-cost',
|
|
36
|
+
]);
|
|
37
|
+
/** 前缀匹配的噪音 header 名(全部小写) */
|
|
38
|
+
export const NOISE_HEADER_PREFIXES = [
|
|
39
|
+
'sec-', 'content-security-policy', 'strict-transport-security',
|
|
40
|
+
'access-control-', 'permissions-policy', 'cross-origin-',
|
|
41
|
+
'report-to', 'nel', ':',
|
|
42
|
+
];
|
|
43
|
+
/**
|
|
44
|
+
* 判断一个 header 是否为噪音(应在 context 综述中过滤掉)。
|
|
45
|
+
* @param role 传入 `request` / `response` 时可应用按侧过滤(如 UA、content-type、eo-*)。
|
|
46
|
+
*/
|
|
47
|
+
export function isNoiseHeader(name, role) {
|
|
48
|
+
const lower = name.toLowerCase();
|
|
49
|
+
if (NOISE_HEADERS.has(lower))
|
|
50
|
+
return true;
|
|
51
|
+
if (NOISE_HEADER_PREFIXES.some((p) => lower.startsWith(p)))
|
|
52
|
+
return true;
|
|
53
|
+
if (role === 'request' && NOISE_HEADERS_REQUEST_ONLY.has(lower))
|
|
54
|
+
return true;
|
|
55
|
+
if (role === 'response') {
|
|
56
|
+
if (NOISE_HEADERS_RESPONSE_ONLY.has(lower))
|
|
57
|
+
return true;
|
|
58
|
+
if (lower.startsWith('eo-'))
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
// =========================================================================
|
|
64
|
+
// 2. Cookie / Sensitive Header Rendering — 脱敏规则
|
|
65
|
+
// =========================================================================
|
|
66
|
+
/**
|
|
67
|
+
* 需要脱敏渲染的 header 名 → 处理策略。
|
|
68
|
+
* - 'cookie' → 只显示 cookie 名称列表,不显示值
|
|
69
|
+
* - 'set-cookie' → 只提示存在
|
|
70
|
+
*/
|
|
71
|
+
export const SENSITIVE_HEADER_RULES = {
|
|
72
|
+
cookie: 'cookie_names',
|
|
73
|
+
'set-cookie': 'presence_only',
|
|
74
|
+
};
|
|
75
|
+
/** header 值的最大显示长度,超出截断 */
|
|
76
|
+
export const HEADER_VALUE_MAX_LENGTH = 300;
|
|
77
|
+
// =========================================================================
|
|
78
|
+
// 3. Body Rendering — context 中的 body 长度阈值与超大提示档位(按字节)
|
|
79
|
+
// =========================================================================
|
|
80
|
+
/** body 全文展示阈值(JS 字符串 .length),不超过则完整写入 context */
|
|
81
|
+
export const BODY_FULL_LIMIT = 1000;
|
|
82
|
+
/** 超过 BODY_FULL_LIMIT 时,依据 UTF-8 字节数选择提示语气 */
|
|
83
|
+
export const BODY_OVERSIZE_HINT_LT_LARGE = 20 * 1024;
|
|
84
|
+
export const BODY_OVERSIZE_HINT_LT_HUGE = 500 * 1024;
|
|
85
|
+
// =========================================================================
|
|
86
|
+
// 4. Protocol Filtering — context 综述中只展示安全协议的请求
|
|
87
|
+
// =========================================================================
|
|
88
|
+
/**
|
|
89
|
+
* 不允许出现在 context 综述中的协议。
|
|
90
|
+
* 即:纯 http / ws 的请求会被过滤掉(只保留 https / wss 等)。
|
|
91
|
+
*/
|
|
92
|
+
export const DISALLOWED_PROTOCOLS = new Set(['http:', 'ws:']);
|
|
93
|
+
/**
|
|
94
|
+
* 判断 URL 对应的协议是否允许出现在 context 综述中。
|
|
95
|
+
* 返回 true 表示允许(即非 http/ws)。
|
|
96
|
+
*/
|
|
97
|
+
export function isAllowedProtocol(url) {
|
|
98
|
+
try {
|
|
99
|
+
const protocol = new URL(url).protocol.toLowerCase();
|
|
100
|
+
return !DISALLOWED_PROTOCOLS.has(protocol);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// =========================================================================
|
|
107
|
+
// 5. Timeline Processing — 时间线加工规则
|
|
108
|
+
// =========================================================================
|
|
109
|
+
/**
|
|
110
|
+
* 是否移除时间线中第一个 CLICK 操作。
|
|
111
|
+
* 录制启动时用户点击"开始录制"按钮通常会被 content script 捕获为第一个 CLICK,
|
|
112
|
+
* 属于误捕获,应在呈现时剔除。
|
|
113
|
+
*/
|
|
114
|
+
export const STRIP_FIRST_CLICK = true;
|
|
115
|
+
//# sourceMappingURL=rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type IncomingMessage, type ServerResponse } from 'node:http';
|
|
2
|
+
import type { WorkspacePaths } from './workspace.js';
|
|
3
|
+
import type { WebTapePayload } from './types.js';
|
|
4
|
+
import { type AnalyzerBackend, type AnalyzeResult } from './analyzer.js';
|
|
5
|
+
/** 单次 webhook 收包后、启动 AI 之前的处理耗时(接收/解析 + 落盘与生成 _context.md) */
|
|
6
|
+
export interface ReceivePersistMetrics {
|
|
7
|
+
/** 读取 HTTP 正文 */
|
|
8
|
+
readBodyMs: number;
|
|
9
|
+
/** JSON.parse 与 meta/content 校验 */
|
|
10
|
+
parseValidateMs: number;
|
|
11
|
+
/** saveRecording:写 requests/responses/snapshots/index.json 与 _context.md */
|
|
12
|
+
persistMs: number;
|
|
13
|
+
/** 以上三项之和,即非 AI 链路总耗时 */
|
|
14
|
+
totalNonAiMs: number;
|
|
15
|
+
}
|
|
16
|
+
export interface ServerOptions {
|
|
17
|
+
port: number;
|
|
18
|
+
workspace: WorkspacePaths;
|
|
19
|
+
autoAnalyze: boolean;
|
|
20
|
+
analyzerBackend: AnalyzerBackend;
|
|
21
|
+
analyzerModel?: string;
|
|
22
|
+
onReceive?: (sessionDir: string, payload: WebTapePayload, metrics: ReceivePersistMetrics) => void;
|
|
23
|
+
onAnalyzeLog?: (line: string) => void;
|
|
24
|
+
onAnalyzeDone?: (result: AnalyzeResult) => void;
|
|
25
|
+
onError?: (err: Error) => void;
|
|
26
|
+
}
|
|
27
|
+
export declare function createWebhookServer(opts: ServerOptions): {
|
|
28
|
+
start: () => Promise<void>;
|
|
29
|
+
stop: () => Promise<void>;
|
|
30
|
+
server: import("http").Server<typeof IncomingMessage, typeof ServerResponse>;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +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;AAGpF,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,8DAA8D;AAC9D,MAAM,WAAW,qBAAqB;IACpC,iBAAiB;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,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,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAClG,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,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;;;;EA6FtD"}
|