@uvl000/claude-trace 3.0.13-workflowexp.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 +477 -0
- package/README.zh-CN.md +477 -0
- package/dist/adapt/api-format.d.ts +41 -0
- package/dist/adapt/api-format.d.ts.map +1 -0
- package/dist/adapt/api-format.js +132 -0
- package/dist/adapt/api-format.js.map +1 -0
- package/dist/adapt/openai-adapter.d.ts +123 -0
- package/dist/adapt/openai-adapter.d.ts.map +1 -0
- package/dist/adapt/openai-adapter.js +628 -0
- package/dist/adapt/openai-adapter.js.map +1 -0
- package/dist/cli/cli-common.d.ts +73 -0
- package/dist/cli/cli-common.d.ts.map +1 -0
- package/dist/cli/cli-common.js +189 -0
- package/dist/cli/cli-common.js.map +1 -0
- package/dist/cli/cli.d.ts +23 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +175 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/codex-cli.d.ts +24 -0
- package/dist/cli/codex-cli.d.ts.map +1 -0
- package/dist/cli/codex-cli.js +146 -0
- package/dist/cli/codex-cli.js.map +1 -0
- package/dist/cli/opencode-cli.d.ts +23 -0
- package/dist/cli/opencode-cli.d.ts.map +1 -0
- package/dist/cli/opencode-cli.js +156 -0
- package/dist/cli/opencode-cli.js.map +1 -0
- package/dist/cli/trace-runner.d.ts +21 -0
- package/dist/cli/trace-runner.d.ts.map +1 -0
- package/dist/cli/trace-runner.js +282 -0
- package/dist/cli/trace-runner.js.map +1 -0
- package/dist/cli/validate-trace.d.ts +30 -0
- package/dist/cli/validate-trace.d.ts.map +1 -0
- package/dist/cli/validate-trace.js +230 -0
- package/dist/cli/validate-trace.js.map +1 -0
- package/dist/cli/verify-offline-bundle.d.ts +13 -0
- package/dist/cli/verify-offline-bundle.d.ts.map +1 -0
- package/dist/cli/verify-offline-bundle.js +89 -0
- package/dist/cli/verify-offline-bundle.js.map +1 -0
- package/dist/cli/vibe-coding-proxy-cli.d.ts +12 -0
- package/dist/cli/vibe-coding-proxy-cli.d.ts.map +1 -0
- package/dist/cli/vibe-coding-proxy-cli.js +218 -0
- package/dist/cli/vibe-coding-proxy-cli.js.map +1 -0
- package/dist/config/claude-config-overlay.d.ts +69 -0
- package/dist/config/claude-config-overlay.d.ts.map +1 -0
- package/dist/config/claude-config-overlay.js +229 -0
- package/dist/config/claude-config-overlay.js.map +1 -0
- package/dist/config/codex-config-overlay.d.ts +122 -0
- package/dist/config/codex-config-overlay.d.ts.map +1 -0
- package/dist/config/codex-config-overlay.js +352 -0
- package/dist/config/codex-config-overlay.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/intercept/forward-proxy.d.ts +77 -0
- package/dist/intercept/forward-proxy.d.ts.map +1 -0
- package/dist/intercept/forward-proxy.js +368 -0
- package/dist/intercept/forward-proxy.js.map +1 -0
- package/dist/intercept/header-redaction.d.ts +7 -0
- package/dist/intercept/header-redaction.d.ts.map +1 -0
- package/dist/intercept/header-redaction.js +28 -0
- package/dist/intercept/header-redaction.js.map +1 -0
- package/dist/intercept/interceptor-loader.js +26 -0
- package/dist/intercept/interceptor.d.ts +164 -0
- package/dist/intercept/interceptor.d.ts.map +1 -0
- package/dist/intercept/interceptor.js +496 -0
- package/dist/intercept/interceptor.js.map +1 -0
- package/dist/intercept/mitm-cert.d.ts +53 -0
- package/dist/intercept/mitm-cert.d.ts.map +1 -0
- package/dist/intercept/mitm-cert.js +259 -0
- package/dist/intercept/mitm-cert.js.map +1 -0
- package/dist/intercept/proxy-log-writer.d.ts +77 -0
- package/dist/intercept/proxy-log-writer.d.ts.map +1 -0
- package/dist/intercept/proxy-log-writer.js +323 -0
- package/dist/intercept/proxy-log-writer.js.map +1 -0
- package/dist/intercept/proxy-targets.d.ts +69 -0
- package/dist/intercept/proxy-targets.d.ts.map +1 -0
- package/dist/intercept/proxy-targets.js +129 -0
- package/dist/intercept/proxy-targets.js.map +1 -0
- package/dist/intercept/reverse-proxy.d.ts +191 -0
- package/dist/intercept/reverse-proxy.d.ts.map +1 -0
- package/dist/intercept/reverse-proxy.js +807 -0
- package/dist/intercept/reverse-proxy.js.map +1 -0
- package/dist/intercept/token-extractor.js +28 -0
- package/dist/report/html-generator.d.ts +96 -0
- package/dist/report/html-generator.d.ts.map +1 -0
- package/dist/report/html-generator.js +225 -0
- package/dist/report/html-generator.js.map +1 -0
- package/dist/report/index-generator.d.ts +89 -0
- package/dist/report/index-generator.d.ts.map +1 -0
- package/dist/report/index-generator.js +319 -0
- package/dist/report/index-generator.js.map +1 -0
- package/dist/report/shared-conversation-processor.d.ts +200 -0
- package/dist/report/shared-conversation-processor.d.ts.map +1 -0
- package/dist/report/shared-conversation-processor.js +720 -0
- package/dist/report/shared-conversation-processor.js.map +1 -0
- package/dist/routing/codex-routing.d.ts +40 -0
- package/dist/routing/codex-routing.d.ts.map +1 -0
- package/dist/routing/codex-routing.js +96 -0
- package/dist/routing/codex-routing.js.map +1 -0
- package/dist/routing/proxy-routing.d.ts +48 -0
- package/dist/routing/proxy-routing.d.ts.map +1 -0
- package/dist/routing/proxy-routing.js +113 -0
- package/dist/routing/proxy-routing.js.map +1 -0
- package/dist/tools/binary-utils.d.ts +29 -0
- package/dist/tools/binary-utils.d.ts.map +1 -0
- package/dist/tools/binary-utils.js +134 -0
- package/dist/tools/binary-utils.js.map +1 -0
- package/dist/tools/claude.d.ts +61 -0
- package/dist/tools/claude.d.ts.map +1 -0
- package/dist/tools/claude.js +449 -0
- package/dist/tools/claude.js.map +1 -0
- package/dist/tools/codex.d.ts +70 -0
- package/dist/tools/codex.d.ts.map +1 -0
- package/dist/tools/codex.js +492 -0
- package/dist/tools/codex.js.map +1 -0
- package/dist/tools/opencode.d.ts +85 -0
- package/dist/tools/opencode.d.ts.map +1 -0
- package/dist/tools/opencode.js +401 -0
- package/dist/tools/opencode.js.map +1 -0
- package/dist/tools/types.d.ts +91 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +11 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/types.d.ts +158 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/frontend/dist/index.global.js +1551 -0
- package/frontend/dist/styles.css +1027 -0
- package/frontend/template.html +19 -0
- package/node_modules/agent-base/LICENSE +22 -0
- package/node_modules/agent-base/README.md +69 -0
- package/node_modules/agent-base/dist/helpers.d.ts +15 -0
- package/node_modules/agent-base/dist/helpers.d.ts.map +1 -0
- package/node_modules/agent-base/dist/helpers.js +66 -0
- package/node_modules/agent-base/dist/helpers.js.map +1 -0
- package/node_modules/agent-base/dist/index.d.ts +41 -0
- package/node_modules/agent-base/dist/index.d.ts.map +1 -0
- package/node_modules/agent-base/dist/index.js +178 -0
- package/node_modules/agent-base/dist/index.js.map +1 -0
- package/node_modules/agent-base/package.json +46 -0
- package/node_modules/debug/LICENSE +20 -0
- package/node_modules/debug/README.md +481 -0
- package/node_modules/debug/package.json +64 -0
- package/node_modules/debug/src/browser.js +272 -0
- package/node_modules/debug/src/common.js +292 -0
- package/node_modules/debug/src/index.js +10 -0
- package/node_modules/debug/src/node.js +263 -0
- package/node_modules/http-proxy-agent/LICENSE +22 -0
- package/node_modules/http-proxy-agent/README.md +44 -0
- package/node_modules/http-proxy-agent/dist/index.d.ts +44 -0
- package/node_modules/http-proxy-agent/dist/index.d.ts.map +1 -0
- package/node_modules/http-proxy-agent/dist/index.js +148 -0
- package/node_modules/http-proxy-agent/dist/index.js.map +1 -0
- package/node_modules/http-proxy-agent/package.json +47 -0
- package/node_modules/https-proxy-agent/LICENSE +22 -0
- package/node_modules/https-proxy-agent/README.md +70 -0
- package/node_modules/https-proxy-agent/dist/index.d.ts +47 -0
- package/node_modules/https-proxy-agent/dist/index.d.ts.map +1 -0
- package/node_modules/https-proxy-agent/dist/index.js +180 -0
- package/node_modules/https-proxy-agent/dist/index.js.map +1 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts +15 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts.map +1 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.js +101 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.js.map +1 -0
- package/node_modules/https-proxy-agent/package.json +50 -0
- package/node_modules/ms/index.js +162 -0
- package/node_modules/ms/license.md +21 -0
- package/node_modules/ms/package.json +38 -0
- package/node_modules/ms/readme.md +59 -0
- package/node_modules/node-forge/LICENSE +331 -0
- package/node_modules/node-forge/README.md +2071 -0
- package/node_modules/node-forge/dist/forge.all.min.js +2 -0
- package/node_modules/node-forge/dist/forge.all.min.js.map +1 -0
- package/node_modules/node-forge/dist/forge.min.js +2 -0
- package/node_modules/node-forge/dist/forge.min.js.map +1 -0
- package/node_modules/node-forge/dist/prime.worker.min.js +2 -0
- package/node_modules/node-forge/dist/prime.worker.min.js.map +1 -0
- package/node_modules/node-forge/flash/swf/SocketPool.swf +0 -0
- package/node_modules/node-forge/lib/aes.js +1091 -0
- package/node_modules/node-forge/lib/aesCipherSuites.js +282 -0
- package/node_modules/node-forge/lib/asn1-validator.js +91 -0
- package/node_modules/node-forge/lib/asn1.js +1503 -0
- package/node_modules/node-forge/lib/baseN.js +186 -0
- package/node_modules/node-forge/lib/cipher.js +230 -0
- package/node_modules/node-forge/lib/cipherModes.js +999 -0
- package/node_modules/node-forge/lib/des.js +496 -0
- package/node_modules/node-forge/lib/ed25519.js +1091 -0
- package/node_modules/node-forge/lib/forge.js +13 -0
- package/node_modules/node-forge/lib/form.js +149 -0
- package/node_modules/node-forge/lib/hmac.js +146 -0
- package/node_modules/node-forge/lib/http.js +1346 -0
- package/node_modules/node-forge/lib/index.all.js +16 -0
- package/node_modules/node-forge/lib/index.js +33 -0
- package/node_modules/node-forge/lib/jsbn.js +1294 -0
- package/node_modules/node-forge/lib/kem.js +168 -0
- package/node_modules/node-forge/lib/log.js +319 -0
- package/node_modules/node-forge/lib/md.all.js +13 -0
- package/node_modules/node-forge/lib/md.js +11 -0
- package/node_modules/node-forge/lib/md5.js +289 -0
- package/node_modules/node-forge/lib/mgf.js +12 -0
- package/node_modules/node-forge/lib/mgf1.js +57 -0
- package/node_modules/node-forge/lib/oids.js +180 -0
- package/node_modules/node-forge/lib/pbe.js +1023 -0
- package/node_modules/node-forge/lib/pbkdf2.js +211 -0
- package/node_modules/node-forge/lib/pem.js +237 -0
- package/node_modules/node-forge/lib/pkcs1.js +276 -0
- package/node_modules/node-forge/lib/pkcs12.js +1078 -0
- package/node_modules/node-forge/lib/pkcs7.js +1260 -0
- package/node_modules/node-forge/lib/pkcs7asn1.js +410 -0
- package/node_modules/node-forge/lib/pki.js +102 -0
- package/node_modules/node-forge/lib/prime.js +297 -0
- package/node_modules/node-forge/lib/prime.worker.js +168 -0
- package/node_modules/node-forge/lib/prng.js +419 -0
- package/node_modules/node-forge/lib/pss.js +241 -0
- package/node_modules/node-forge/lib/random.js +191 -0
- package/node_modules/node-forge/lib/rc2.js +410 -0
- package/node_modules/node-forge/lib/rsa.js +1968 -0
- package/node_modules/node-forge/lib/sha1.js +319 -0
- package/node_modules/node-forge/lib/sha256.js +327 -0
- package/node_modules/node-forge/lib/sha512.js +561 -0
- package/node_modules/node-forge/lib/socket.js +287 -0
- package/node_modules/node-forge/lib/ssh.js +236 -0
- package/node_modules/node-forge/lib/tls.js +4282 -0
- package/node_modules/node-forge/lib/tlssocket.js +249 -0
- package/node_modules/node-forge/lib/util.js +2652 -0
- package/node_modules/node-forge/lib/x509.js +3251 -0
- package/node_modules/node-forge/lib/xhr.js +738 -0
- package/node_modules/node-forge/package.json +123 -0
- package/node_modules/smol-toml/LICENSE +24 -0
- package/node_modules/smol-toml/README.md +239 -0
- package/node_modules/smol-toml/dist/date.d.ts +41 -0
- package/node_modules/smol-toml/dist/date.js +127 -0
- package/node_modules/smol-toml/dist/error.d.ts +38 -0
- package/node_modules/smol-toml/dist/error.js +63 -0
- package/node_modules/smol-toml/dist/extract.d.ts +30 -0
- package/node_modules/smol-toml/dist/extract.js +100 -0
- package/node_modules/smol-toml/dist/index.cjs +897 -0
- package/node_modules/smol-toml/dist/index.d.ts +43 -0
- package/node_modules/smol-toml/dist/index.js +33 -0
- package/node_modules/smol-toml/dist/parse.d.ts +37 -0
- package/node_modules/smol-toml/dist/parse.js +148 -0
- package/node_modules/smol-toml/dist/primitive.d.ts +31 -0
- package/node_modules/smol-toml/dist/primitive.js +179 -0
- package/node_modules/smol-toml/dist/stringify.d.ts +31 -0
- package/node_modules/smol-toml/dist/stringify.js +167 -0
- package/node_modules/smol-toml/dist/struct.d.ts +32 -0
- package/node_modules/smol-toml/dist/struct.js +184 -0
- package/node_modules/smol-toml/dist/util.d.ts +42 -0
- package/node_modules/smol-toml/dist/util.js +111 -0
- package/node_modules/smol-toml/package.json +54 -0
- package/offline/bin/claude-trace +6 -0
- package/offline/bin/claude-wrapper +13 -0
- package/offline/bin/install-agent +14 -0
- package/offline/bin/validate-trace +6 -0
- package/offline/bin/verify-bundle +7 -0
- package/package.json +103 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file Conversation index generator for trace log directories.
|
|
4
|
+
*
|
|
5
|
+
* Scans JSONL session logs, optionally regenerates per-log HTML reports and
|
|
6
|
+
* AI-generated conversation summaries via the Claude CLI, then writes a
|
|
7
|
+
* browsable `index.html` listing all sessions and their summaries.
|
|
8
|
+
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.IndexGenerator = void 0;
|
|
14
|
+
const fs_1 = __importDefault(require("fs"));
|
|
15
|
+
const path_1 = __importDefault(require("path"));
|
|
16
|
+
const child_process_1 = require("child_process");
|
|
17
|
+
const html_generator_1 = require("./html-generator");
|
|
18
|
+
const shared_conversation_processor_1 = require("./shared-conversation-processor");
|
|
19
|
+
/**
|
|
20
|
+
* Builds and maintains `index.html` plus per-log `summary-*.json` sidecars.
|
|
21
|
+
*
|
|
22
|
+
* Summaries are regenerated when missing or older than the source JSONL file.
|
|
23
|
+
*/
|
|
24
|
+
class IndexGenerator {
|
|
25
|
+
/**
|
|
26
|
+
* @param traceDir - Trace output directory (e.g. `.claude-trace`).
|
|
27
|
+
*/
|
|
28
|
+
constructor(traceDir = ".claude-trace") {
|
|
29
|
+
this.traceDir = traceDir;
|
|
30
|
+
this.htmlGenerator = new html_generator_1.HTMLGenerator();
|
|
31
|
+
this.conversationProcessor = new shared_conversation_processor_1.SharedConversationProcessor();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Main entry point: process all logs in `traceDir` and write `index.html`.
|
|
35
|
+
* Exits the process with code 1 when the directory or logs are missing.
|
|
36
|
+
*/
|
|
37
|
+
async generateIndex() {
|
|
38
|
+
console.log("Generating conversation index...");
|
|
39
|
+
console.log(`Looking in: ${this.traceDir}/`);
|
|
40
|
+
if (!fs_1.default.existsSync(this.traceDir)) {
|
|
41
|
+
console.log(`Directory ${this.traceDir} not found`);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
// Find all log files
|
|
45
|
+
const logFiles = this.findLogFiles();
|
|
46
|
+
console.log(`Found ${logFiles.length} log files`);
|
|
47
|
+
if (logFiles.length === 0) {
|
|
48
|
+
console.log("No log files found");
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
// Process each log file
|
|
52
|
+
const allSummaries = [];
|
|
53
|
+
for (const logFile of logFiles) {
|
|
54
|
+
console.log(`\nProcessing ${logFile}...`);
|
|
55
|
+
const summary = await this.processLogFile(logFile);
|
|
56
|
+
if (summary) {
|
|
57
|
+
allSummaries.push(summary);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Generate index.html
|
|
61
|
+
await this.generateIndexHTML(allSummaries);
|
|
62
|
+
console.log(`\nIndex generated: ${this.traceDir}/index.html`);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Lists session JSONL files matching `log-YYYY-MM-DD-HH-MM-SS.jsonl`,
|
|
66
|
+
* newest first.
|
|
67
|
+
*
|
|
68
|
+
* @returns Filenames only (not full paths), sorted descending by timestamp.
|
|
69
|
+
*/
|
|
70
|
+
findLogFiles() {
|
|
71
|
+
const files = fs_1.default.readdirSync(this.traceDir);
|
|
72
|
+
return files
|
|
73
|
+
.filter((file) => file.match(/^log-\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2}\.jsonl$/))
|
|
74
|
+
.sort((a, b) => b.localeCompare(a)); // newest first
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Ensures a summary sidecar exists for one log, regenerating when stale.
|
|
78
|
+
* Also generates the per-log HTML report if missing.
|
|
79
|
+
*/
|
|
80
|
+
async processLogFile(logFile) {
|
|
81
|
+
const logPath = path_1.default.join(this.traceDir, logFile);
|
|
82
|
+
const timestamp = logFile.match(/log-(\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2})\.jsonl$/)?.[1];
|
|
83
|
+
if (!timestamp)
|
|
84
|
+
return null;
|
|
85
|
+
const summaryFile = `summary-${timestamp}.json`;
|
|
86
|
+
const summaryPath = path_1.default.join(this.traceDir, summaryFile);
|
|
87
|
+
const htmlFile = `log-${timestamp}.html`;
|
|
88
|
+
const htmlPath = path_1.default.join(this.traceDir, htmlFile);
|
|
89
|
+
// Check if summary needs regeneration
|
|
90
|
+
const logStat = fs_1.default.statSync(logPath);
|
|
91
|
+
let needsRegeneration = !fs_1.default.existsSync(summaryPath);
|
|
92
|
+
if (!needsRegeneration) {
|
|
93
|
+
const summaryStat = fs_1.default.statSync(summaryPath);
|
|
94
|
+
needsRegeneration = summaryStat.mtime < logStat.mtime;
|
|
95
|
+
}
|
|
96
|
+
if (needsRegeneration) {
|
|
97
|
+
console.log(` Generating summary (${needsRegeneration ? "missing or outdated" : "up to date"})...`);
|
|
98
|
+
// Ensure HTML file exists
|
|
99
|
+
if (!fs_1.default.existsSync(htmlPath)) {
|
|
100
|
+
console.log(` Generating HTML file...`);
|
|
101
|
+
await this.htmlGenerator.generateHTMLFromJSONL(logPath, htmlPath);
|
|
102
|
+
}
|
|
103
|
+
// Process conversations
|
|
104
|
+
const conversations = await this.extractConversations(logPath);
|
|
105
|
+
const summaries = [];
|
|
106
|
+
// Summarize non-compacted conversations with more than 2 messages
|
|
107
|
+
const nonCompactedConversations = conversations.filter((conv) => !conv.compacted && conv.messages.length > 2);
|
|
108
|
+
console.log(` Found ${nonCompactedConversations.length} non-compacted conversations (>2 messages)`);
|
|
109
|
+
for (const conversation of nonCompactedConversations) {
|
|
110
|
+
console.log(` Summarizing conversation ${conversation.id}...`);
|
|
111
|
+
const summary = await this.summarizeConversation(conversation);
|
|
112
|
+
if (summary) {
|
|
113
|
+
summaries.push(summary);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Save summary file
|
|
117
|
+
const logSummary = {
|
|
118
|
+
logFile,
|
|
119
|
+
htmlFile,
|
|
120
|
+
generated: new Date().toISOString(),
|
|
121
|
+
conversations: summaries,
|
|
122
|
+
};
|
|
123
|
+
fs_1.default.writeFileSync(summaryPath, JSON.stringify(logSummary, null, 2));
|
|
124
|
+
console.log(` Summary saved: ${summaryFile}`);
|
|
125
|
+
return logSummary;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
console.log(` Using existing summary`);
|
|
129
|
+
return JSON.parse(fs_1.default.readFileSync(summaryPath, "utf-8"));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/** Parses a JSONL log into merged {@link SimpleConversation} objects. */
|
|
133
|
+
async extractConversations(logPath) {
|
|
134
|
+
// Read and parse JSONL file
|
|
135
|
+
const content = fs_1.default.readFileSync(logPath, "utf-8");
|
|
136
|
+
const lines = content
|
|
137
|
+
.trim()
|
|
138
|
+
.split("\n")
|
|
139
|
+
.filter((line) => line.trim());
|
|
140
|
+
const rawPairs = lines.map((line) => JSON.parse(line));
|
|
141
|
+
// Process pairs using shared implementation
|
|
142
|
+
const processedPairs = this.conversationProcessor.processRawPairs(rawPairs);
|
|
143
|
+
// Extract conversations
|
|
144
|
+
return this.conversationProcessor.mergeConversations(processedPairs);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Calls the Claude CLI to produce a title and summary for one conversation.
|
|
148
|
+
* Returns null when parsing fails or the CLI is unavailable.
|
|
149
|
+
*/
|
|
150
|
+
async summarizeConversation(conversation) {
|
|
151
|
+
try {
|
|
152
|
+
// Convert conversation to text for summarization
|
|
153
|
+
const conversationText = this.conversationToText(conversation);
|
|
154
|
+
// Prepare prompt for Claude
|
|
155
|
+
const prompt = `Please analyze this conversation and provide:
|
|
156
|
+
1. A concise title (max 10 words)
|
|
157
|
+
2. A summary in 1-3 paragraphs describing what was accomplished
|
|
158
|
+
|
|
159
|
+
Conversation:
|
|
160
|
+
${conversationText}
|
|
161
|
+
|
|
162
|
+
Format your response as:
|
|
163
|
+
TITLE: [title]
|
|
164
|
+
SUMMARY: [summary]`;
|
|
165
|
+
// Call Claude CLI
|
|
166
|
+
const claudeResponse = await this.callClaude(prompt);
|
|
167
|
+
// Parse response
|
|
168
|
+
const titleMatch = claudeResponse.match(/TITLE:\s*(.+)/);
|
|
169
|
+
const summaryMatch = claudeResponse.match(/SUMMARY:\s*([\s\S]+)/);
|
|
170
|
+
if (!titleMatch || !summaryMatch) {
|
|
171
|
+
console.log(` Failed to parse Claude response for conversation ${conversation.id}`);
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
id: conversation.id,
|
|
176
|
+
title: titleMatch[1].trim(),
|
|
177
|
+
summary: summaryMatch[1].trim(),
|
|
178
|
+
startTime: conversation.metadata.startTime,
|
|
179
|
+
messageCount: conversation.messages.length,
|
|
180
|
+
models: Array.from(conversation.models),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
console.log(` Failed to summarize conversation ${conversation.id}: ${error}`);
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Flattens a conversation to plain text for the summarization prompt.
|
|
190
|
+
* Truncates long blocks to keep token usage reasonable.
|
|
191
|
+
*/
|
|
192
|
+
conversationToText(conversation) {
|
|
193
|
+
let text = "";
|
|
194
|
+
// Add system prompt (stripped)
|
|
195
|
+
if (conversation.system) {
|
|
196
|
+
const systemText = typeof conversation.system === "string"
|
|
197
|
+
? conversation.system
|
|
198
|
+
: conversation.system.map((block) => (block.type === "text" ? block.text : "[non-text]")).join(" ");
|
|
199
|
+
text += `SYSTEM: ${systemText.substring(0, 500)}...\n\n`;
|
|
200
|
+
}
|
|
201
|
+
// Add messages (without tool results for brevity)
|
|
202
|
+
for (const message of conversation.messages) {
|
|
203
|
+
if (message.hide)
|
|
204
|
+
continue;
|
|
205
|
+
text += `${message.role.toUpperCase()}: `;
|
|
206
|
+
if (typeof message.content === "string") {
|
|
207
|
+
text += message.content.substring(0, 1000);
|
|
208
|
+
}
|
|
209
|
+
else if (Array.isArray(message.content)) {
|
|
210
|
+
const textBlocks = message.content
|
|
211
|
+
.filter((block) => block.type === "text")
|
|
212
|
+
.map((block) => block.text)
|
|
213
|
+
.join(" ");
|
|
214
|
+
text += textBlocks.substring(0, 1000);
|
|
215
|
+
}
|
|
216
|
+
text += "\n\n";
|
|
217
|
+
}
|
|
218
|
+
return text;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Spawns `claude -p <prompt>` and returns stdout.
|
|
222
|
+
* @throws When the CLI exits non-zero or cannot be spawned.
|
|
223
|
+
*/
|
|
224
|
+
async callClaude(prompt) {
|
|
225
|
+
return new Promise((resolve, reject) => {
|
|
226
|
+
console.log(" Calling Claude CLI for summarization...");
|
|
227
|
+
console.log(" This will incur additional token usage");
|
|
228
|
+
const child = (0, child_process_1.spawn)("claude", ["-p", prompt], {
|
|
229
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
230
|
+
});
|
|
231
|
+
let stdout = "";
|
|
232
|
+
let stderr = "";
|
|
233
|
+
child.stdout.on("data", (data) => {
|
|
234
|
+
stdout += data.toString();
|
|
235
|
+
});
|
|
236
|
+
child.stderr.on("data", (data) => {
|
|
237
|
+
stderr += data.toString();
|
|
238
|
+
});
|
|
239
|
+
child.on("close", (code) => {
|
|
240
|
+
if (code === 0) {
|
|
241
|
+
resolve(stdout.trim());
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
reject(new Error(`Claude CLI exited with code ${code}: ${stderr}`));
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
child.on("error", (error) => {
|
|
248
|
+
reject(new Error(`Failed to spawn claude CLI: ${error.message}`));
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Writes a static HTML index page linking to per-log reports and summaries.
|
|
254
|
+
*
|
|
255
|
+
* Uses inline CSS only — no frontend bundle — so the index opens instantly
|
|
256
|
+
* without rebuilding the Lit viewer.
|
|
257
|
+
*/
|
|
258
|
+
async generateIndexHTML(summaries) {
|
|
259
|
+
// Static template; a future version may reuse the lazy-loading frontend bundle
|
|
260
|
+
const indexPath = path_1.default.join(this.traceDir, "index.html");
|
|
261
|
+
let html = `<!DOCTYPE html>
|
|
262
|
+
<html lang="en">
|
|
263
|
+
<head>
|
|
264
|
+
<meta charset="UTF-8">
|
|
265
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
266
|
+
<title>Claude Trace - Conversation Index</title>
|
|
267
|
+
<style>
|
|
268
|
+
body { font-family: system-ui, sans-serif; max-width: 1200px; margin: 0 auto; padding: 20px; }
|
|
269
|
+
.header { border-bottom: 1px solid #ddd; padding-bottom: 20px; margin-bottom: 30px; }
|
|
270
|
+
.log-section { margin-bottom: 40px; }
|
|
271
|
+
.log-header { background: #f5f5f5; padding: 15px; border-radius: 8px; margin-bottom: 20px; }
|
|
272
|
+
.conversation { border: 1px solid #e0e0e0; border-radius: 8px; padding: 20px; margin-bottom: 15px; }
|
|
273
|
+
.conversation h3 { margin-top: 0; color: #2563eb; }
|
|
274
|
+
.conversation-meta { color: #666; font-size: 14px; margin-bottom: 10px; }
|
|
275
|
+
.models { display: flex; gap: 8px; margin-top: 10px; }
|
|
276
|
+
.model-tag { background: #e5f3ff; color: #0066cc; padding: 2px 8px; border-radius: 4px; font-size: 12px; }
|
|
277
|
+
a { color: #2563eb; text-decoration: none; }
|
|
278
|
+
a:hover { text-decoration: underline; }
|
|
279
|
+
</style>
|
|
280
|
+
</head>
|
|
281
|
+
<body>
|
|
282
|
+
<div class="header">
|
|
283
|
+
<h1>Claude Trace - Conversation Index</h1>
|
|
284
|
+
<p>Generated: ${new Date().toISOString().replace("T", " ").slice(0, -5)}</p>
|
|
285
|
+
<p>Total logs: ${summaries.length}</p>
|
|
286
|
+
</div>
|
|
287
|
+
`;
|
|
288
|
+
for (const summary of summaries) {
|
|
289
|
+
html += `
|
|
290
|
+
<div class="log-section">
|
|
291
|
+
<div class="log-header">
|
|
292
|
+
<h2><a href="${summary.htmlFile}">${summary.logFile}</a></h2>
|
|
293
|
+
<p>Generated: ${summary.generated.replace("T", " ").slice(0, -5)} | Conversations: ${summary.conversations.length}</p>
|
|
294
|
+
</div>
|
|
295
|
+
`;
|
|
296
|
+
for (const conv of summary.conversations) {
|
|
297
|
+
html += `
|
|
298
|
+
<div class="conversation">
|
|
299
|
+
<h3>${conv.title}</h3>
|
|
300
|
+
<div class="conversation-meta">
|
|
301
|
+
${conv.startTime.replace("T", " ").slice(0, -5)} | ${conv.messageCount} messages
|
|
302
|
+
</div>
|
|
303
|
+
<p>${conv.summary}</p>
|
|
304
|
+
<div class="models">
|
|
305
|
+
${conv.models.map((model) => `<span class="model-tag">${model}</span>`).join("")}
|
|
306
|
+
</div>
|
|
307
|
+
</div>
|
|
308
|
+
`;
|
|
309
|
+
}
|
|
310
|
+
html += ` </div>`;
|
|
311
|
+
}
|
|
312
|
+
html += `
|
|
313
|
+
</body>
|
|
314
|
+
</html>`;
|
|
315
|
+
fs_1.default.writeFileSync(indexPath, html);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
exports.IndexGenerator = IndexGenerator;
|
|
319
|
+
//# sourceMappingURL=index-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-generator.js","sourceRoot":"","sources":["../../src/report/index-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Shared conversation parsing for frontend and backend.
|
|
3
|
+
*
|
|
4
|
+
* Converts raw JSONL request/response pairs into normalized Anthropic-shaped
|
|
5
|
+
* messages, groups them into conversation threads, pairs tool_use with
|
|
6
|
+
* tool_result blocks, and detects compacted (summarized) conversations.
|
|
7
|
+
*
|
|
8
|
+
* Used by both the Lit HTML viewer and the CLI index generator so parsing
|
|
9
|
+
* behavior stays identical across surfaces.
|
|
10
|
+
*/
|
|
11
|
+
import type { Message, MessageCreateParams, MessageParam, TextBlockParam, ToolResultBlockParam } from "@anthropic-ai/sdk/resources/messages";
|
|
12
|
+
import type { ApiFormat } from "../tools/types";
|
|
13
|
+
import type { RawPair } from "../types";
|
|
14
|
+
/** A single logged API round-trip normalized for display and grouping. */
|
|
15
|
+
export interface ProcessedPair {
|
|
16
|
+
id: string;
|
|
17
|
+
timestamp: string;
|
|
18
|
+
request: MessageCreateParams;
|
|
19
|
+
response: Message;
|
|
20
|
+
model: string;
|
|
21
|
+
isStreaming: boolean;
|
|
22
|
+
/** Raw SSE or Bedrock event-stream body preserved for debug views. */
|
|
23
|
+
rawStreamData?: string;
|
|
24
|
+
/** Whether streaming data used Anthropic SSE or AWS Bedrock binary format. */
|
|
25
|
+
streamFormat?: "standard" | "bedrock" | null;
|
|
26
|
+
/** Detected upstream API format when known at log or parse time. */
|
|
27
|
+
apiFormat?: ApiFormat;
|
|
28
|
+
}
|
|
29
|
+
/** Message with paired tool results attached and optional UI hide flag. */
|
|
30
|
+
export interface EnhancedMessageParam extends MessageParam {
|
|
31
|
+
/** Tool results keyed by `tool_use_id`, hoisted onto the assistant turn. */
|
|
32
|
+
toolResults?: Record<string, ToolResultBlockParam>;
|
|
33
|
+
/** When true, the message is tool-result-only and hidden in the UI. */
|
|
34
|
+
hide?: boolean;
|
|
35
|
+
}
|
|
36
|
+
/** Token usage fields aggregated from API pairs in a conversation thread. */
|
|
37
|
+
export interface ConversationUsageMetadata {
|
|
38
|
+
/** Last request context size; alias of {@link lastTurnInputTokens}. */
|
|
39
|
+
inputTokens: number;
|
|
40
|
+
/** Sum of output tokens across all pairs; alias of {@link sessionOutputTokens}. */
|
|
41
|
+
outputTokens: number;
|
|
42
|
+
/** Alias of {@link sessionOutputTokens} (not input + output). */
|
|
43
|
+
totalTokens: number;
|
|
44
|
+
/** Context token count from the chronologically last API response. */
|
|
45
|
+
lastTurnInputTokens: number;
|
|
46
|
+
/** Output token count from the chronologically last API response. */
|
|
47
|
+
lastTurnOutputTokens: number;
|
|
48
|
+
/** Sum of `output_tokens` across every pair in the thread. */
|
|
49
|
+
sessionOutputTokens: number;
|
|
50
|
+
/** Prompt cache hits on the last turn, when reported by the API. */
|
|
51
|
+
cacheReadTokens?: number | null;
|
|
52
|
+
/** Prompt cache writes on the last turn, when reported by the API. */
|
|
53
|
+
cacheCreationTokens?: number | null;
|
|
54
|
+
}
|
|
55
|
+
/** One logical conversation thread merged from multiple API pairs. */
|
|
56
|
+
export interface SimpleConversation {
|
|
57
|
+
id: string;
|
|
58
|
+
models: Set<string>;
|
|
59
|
+
system?: string | TextBlockParam[];
|
|
60
|
+
messages: EnhancedMessageParam[];
|
|
61
|
+
response: Message;
|
|
62
|
+
/** All API pairs that belong to this thread, sorted by time. */
|
|
63
|
+
allPairs: ProcessedPair[];
|
|
64
|
+
/** The pair with the longest message list — treated as the thread snapshot. */
|
|
65
|
+
finalPair: ProcessedPair;
|
|
66
|
+
/** True when this thread was detected as a post-compaction summary. */
|
|
67
|
+
compacted?: boolean;
|
|
68
|
+
/** Human-readable API format label, e.g. "OpenAI Chat". */
|
|
69
|
+
apiFormatDisplay?: string;
|
|
70
|
+
metadata: {
|
|
71
|
+
startTime: string;
|
|
72
|
+
endTime: string;
|
|
73
|
+
totalPairs: number;
|
|
74
|
+
} & ConversationUsageMetadata;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Aggregates token usage from chronologically ordered API pairs.
|
|
78
|
+
*
|
|
79
|
+
* Input tokens reflect the last turn's context snapshot (not summed across turns).
|
|
80
|
+
* Output tokens are summed across all pairs as the session generation cost.
|
|
81
|
+
*
|
|
82
|
+
* @param pairs - Processed pairs belonging to one conversation thread.
|
|
83
|
+
*/
|
|
84
|
+
export declare function aggregateUsageFromPairs(pairs: ProcessedPair[]): ConversationUsageMetadata;
|
|
85
|
+
/**
|
|
86
|
+
* Parses raw trace pairs and merges them into viewer-ready conversations.
|
|
87
|
+
* Used by both the Lit frontend and the CLI index generator.
|
|
88
|
+
*/
|
|
89
|
+
export declare class SharedConversationProcessor {
|
|
90
|
+
/**
|
|
91
|
+
* Converts each {@link RawPair} into a {@link ProcessedPair}.
|
|
92
|
+
*
|
|
93
|
+
* Handles Anthropic JSON, Anthropic/Bedrock SSE, and OpenAI Chat/Responses
|
|
94
|
+
* formats. Pairs missing request/response or failing parse are skipped with
|
|
95
|
+
* a console warning.
|
|
96
|
+
*
|
|
97
|
+
* @param rawPairs - Lines parsed from a session JSONL log.
|
|
98
|
+
* @returns Normalized pairs ready for merging or JSON debug display.
|
|
99
|
+
*/
|
|
100
|
+
processRawPairs(rawPairs: RawPair[]): ProcessedPair[];
|
|
101
|
+
/**
|
|
102
|
+
* Detects AWS Bedrock binary event-stream responses by their leading NUL bytes.
|
|
103
|
+
*
|
|
104
|
+
* @param bodyRaw - Raw response body string from the proxy log.
|
|
105
|
+
*/
|
|
106
|
+
private isBedrockResponse;
|
|
107
|
+
/**
|
|
108
|
+
* Parses Bedrock binary event stream into a synthetic Anthropic {@link Message}.
|
|
109
|
+
*
|
|
110
|
+
* Extracts base64-wrapped JSON events from `event{"bytes":...}` frames and
|
|
111
|
+
* merges Bedrock invocation metrics into usage when present.
|
|
112
|
+
*/
|
|
113
|
+
private parseBedrockStreamingResponse;
|
|
114
|
+
/**
|
|
115
|
+
* Decodes base64 to UTF-8 in both browser (atob) and Node.js (Buffer).
|
|
116
|
+
*
|
|
117
|
+
* @throws When neither API is available (unlikely in this project's targets).
|
|
118
|
+
*/
|
|
119
|
+
private decodeBase64ToUtf8;
|
|
120
|
+
/**
|
|
121
|
+
* Scans raw Bedrock event-stream text for `event{"bytes":{...}}` JSON wrappers.
|
|
122
|
+
*
|
|
123
|
+
* Uses brace counting rather than regex to handle nested JSON objects safely.
|
|
124
|
+
*/
|
|
125
|
+
private extractJsonChunksFromEventStream;
|
|
126
|
+
/**
|
|
127
|
+
* Best-effort extraction of Bedrock token metrics embedded in the raw stream.
|
|
128
|
+
*/
|
|
129
|
+
private extractBedrockMetrics;
|
|
130
|
+
/**
|
|
131
|
+
* Dispatches streaming body parsing to Bedrock or standard Anthropic SSE.
|
|
132
|
+
*
|
|
133
|
+
* @param bodyRaw - Raw `body_raw` field from a logged response.
|
|
134
|
+
* @returns Reconstructed assistant {@link Message}.
|
|
135
|
+
*/
|
|
136
|
+
parseStreamingResponse(bodyRaw: string): Message;
|
|
137
|
+
/**
|
|
138
|
+
* Parses Anthropic-style `data: {...}` SSE lines into a {@link Message}.
|
|
139
|
+
*/
|
|
140
|
+
private parseStandardStreamingResponse;
|
|
141
|
+
/**
|
|
142
|
+
* Replays streaming events into a complete {@link Message}, accumulating
|
|
143
|
+
* text, thinking, and tool_use deltas and parsing tool JSON at block stop.
|
|
144
|
+
*
|
|
145
|
+
* @param events - Ordered stream events from SSE or Bedrock decode.
|
|
146
|
+
* @param bedrockMetrics - Optional Bedrock token counts overriding usage.
|
|
147
|
+
*/
|
|
148
|
+
private buildMessageFromEvents;
|
|
149
|
+
/**
|
|
150
|
+
* Resolves a display model id from Bedrock URL, request body, or response body.
|
|
151
|
+
*/
|
|
152
|
+
private extractModel;
|
|
153
|
+
/**
|
|
154
|
+
* Strips Bedrock inference-profile prefixes for shorter display names.
|
|
155
|
+
*/
|
|
156
|
+
private normalizeModelName;
|
|
157
|
+
/**
|
|
158
|
+
* Groups {@link ProcessedPair} rows into {@link SimpleConversation} threads.
|
|
159
|
+
*
|
|
160
|
+
* Threading heuristic: same system prompt + model, then bucket by normalized
|
|
161
|
+
* first user message. Within each bucket the pair with the most messages
|
|
162
|
+
* becomes the thread snapshot. Compacted conversations are merged when detected.
|
|
163
|
+
*
|
|
164
|
+
* @param pairs - Normalized pairs from {@link processRawPairs}.
|
|
165
|
+
* @param options.includeShortConversations - Include threads with ≤2 messages.
|
|
166
|
+
* @returns Conversations sorted by start time.
|
|
167
|
+
*/
|
|
168
|
+
mergeConversations(pairs: ProcessedPair[], options?: {
|
|
169
|
+
includeShortConversations?: boolean;
|
|
170
|
+
}): SimpleConversation[];
|
|
171
|
+
/**
|
|
172
|
+
* Attaches tool_result blocks to their tool_use messages and hides
|
|
173
|
+
* user turns that contain only orphaned tool results.
|
|
174
|
+
*/
|
|
175
|
+
private processToolResults;
|
|
176
|
+
/**
|
|
177
|
+
* Detects Claude Code compaction: a single-pair conversation whose message
|
|
178
|
+
* list is two longer than an earlier thread with matching tail messages.
|
|
179
|
+
*/
|
|
180
|
+
private detectAndMergeCompactConversations;
|
|
181
|
+
/**
|
|
182
|
+
* Combines pre- and post-compaction threads, restoring the original first
|
|
183
|
+
* user message while keeping the compacted response and pair list.
|
|
184
|
+
*/
|
|
185
|
+
private mergeCompactConversation;
|
|
186
|
+
/**
|
|
187
|
+
* Loose equality check for compaction pairing — compares role and content shape only.
|
|
188
|
+
*/
|
|
189
|
+
private messagesRoughlyEqual;
|
|
190
|
+
/**
|
|
191
|
+
* Strips volatile substrings from the first message so threading keys stay
|
|
192
|
+
* stable across retries (timestamps, IDE open events, system reminders).
|
|
193
|
+
*/
|
|
194
|
+
private normalizeMessageForGrouping;
|
|
195
|
+
/**
|
|
196
|
+
* Simple string hash for conversation grouping keys (not cryptographic).
|
|
197
|
+
*/
|
|
198
|
+
private hashString;
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=shared-conversation-processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-conversation-processor.d.ts","sourceRoot":"","sources":["../../src/report/shared-conversation-processor.ts"],"names":[],"mappings":"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"}
|