ronds_ai 0.1.23 → 0.1.24
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 +1 -1
- package/lib/analyze_claude.js +19 -8
- package/lib/analyze_config.js +22 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -190,7 +190,7 @@ ronds_ai analyze claude
|
|
|
190
190
|
|
|
191
191
|
行为与 Langfuse Claude Observability Plugin 一致,只采集 transcript 中的 `text`、`tool_use` 和 `tool_result`,不上传 `thinking` block。状态和日志保存在 `~/.ronds_ai/analyze/`。
|
|
192
192
|
|
|
193
|
-
Langfuse 连接信息已内置,Trace 的 `userId`
|
|
193
|
+
Langfuse 连接信息已内置,Trace 的 `userId` 优先使用当前项目的 `git user.email`,读取不到时回退到当前操作系统用户名。可选配置:
|
|
194
194
|
|
|
195
195
|
- `CC_LANGFUSE_DEBUG=true`:启用详细日志
|
|
196
196
|
- `CC_LANGFUSE_MAX_CHARS=<正整数>`:单个文本字段的最大字符数,默认 `20000`
|
package/lib/analyze_claude.js
CHANGED
|
@@ -102,11 +102,20 @@ function extractHookContext(payload) {
|
|
|
102
102
|
return null;
|
|
103
103
|
}
|
|
104
104
|
const hookEventName = payload.hook_event_name || payload.hookEventName || '';
|
|
105
|
-
|
|
105
|
+
const context = {
|
|
106
106
|
sessionId,
|
|
107
107
|
transcriptPath: resolvedPath,
|
|
108
108
|
flushDeferredAgentTurns: hookEventName === 'SessionEnd',
|
|
109
109
|
};
|
|
110
|
+
const projectDir = [
|
|
111
|
+
payload.cwd,
|
|
112
|
+
payload.workspace && payload.workspace.current_dir,
|
|
113
|
+
payload.workspace && payload.workspace.project_dir,
|
|
114
|
+
].find((value) => typeof value === 'string' && value.trim());
|
|
115
|
+
if (projectDir) {
|
|
116
|
+
context.projectDir = path.resolve(projectDir);
|
|
117
|
+
}
|
|
118
|
+
return context;
|
|
110
119
|
}
|
|
111
120
|
|
|
112
121
|
/**
|
|
@@ -426,10 +435,7 @@ async function processHookContext(context, config, sdkModules) {
|
|
|
426
435
|
async function runClaudeAnalyze() {
|
|
427
436
|
assertAnalyzeNodeVersion();
|
|
428
437
|
const sdkModules = loadLangfuseSdk();
|
|
429
|
-
const config = getAnalyzeConfig();
|
|
430
|
-
writeAnalyzeDebug('analyze hook started', config);
|
|
431
438
|
const raw = await readStdin();
|
|
432
|
-
writeAnalyzeDebug(`stdin received ${raw.length} chars`, config);
|
|
433
439
|
if (!raw.trim()) {
|
|
434
440
|
return;
|
|
435
441
|
}
|
|
@@ -438,18 +444,23 @@ async function runClaudeAnalyze() {
|
|
|
438
444
|
try {
|
|
439
445
|
payload = JSON.parse(raw);
|
|
440
446
|
} catch (error) {
|
|
447
|
+
const config = getAnalyzeConfig();
|
|
441
448
|
writeAnalyzeLog('INFO', `invalid hook payload: ${error.message}`, config);
|
|
442
449
|
return;
|
|
443
450
|
}
|
|
444
|
-
writeAnalyzeDebug(
|
|
445
|
-
`payload top-level keys: ${Object.keys(payload).sort().join(', ')}`,
|
|
446
|
-
config,
|
|
447
|
-
);
|
|
448
451
|
const context = extractHookContext(payload);
|
|
449
452
|
if (!context) {
|
|
453
|
+
const config = getAnalyzeConfig();
|
|
450
454
|
writeAnalyzeLog('INFO', 'hook payload has no usable session or transcript', config);
|
|
451
455
|
return;
|
|
452
456
|
}
|
|
457
|
+
const config = getAnalyzeConfig(context.projectDir);
|
|
458
|
+
writeAnalyzeDebug('analyze hook started', config);
|
|
459
|
+
writeAnalyzeDebug(`stdin received ${raw.length} chars`, config);
|
|
460
|
+
writeAnalyzeDebug(
|
|
461
|
+
`payload top-level keys: ${Object.keys(payload).sort().join(', ')}`,
|
|
462
|
+
config,
|
|
463
|
+
);
|
|
453
464
|
|
|
454
465
|
try {
|
|
455
466
|
await processHookContext(context, config, sdkModules);
|
package/lib/analyze_config.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const os = require('os');
|
|
2
|
+
const { runGit } = require('./git');
|
|
2
3
|
|
|
3
4
|
// Langfuse 连接信息按产品要求从当前 Claude 配置写入源码。
|
|
4
5
|
const LANGFUSE_PUBLIC_KEY = 'pk-lf-default-001';
|
|
@@ -46,15 +47,32 @@ function resolveSystemUsername() {
|
|
|
46
47
|
return process.env.USERNAME || process.env.USER || 'unknown';
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
/**
|
|
51
|
+
* 读取当前项目的 Git 邮箱,与 record 上报的 git.user.email 保持一致。
|
|
52
|
+
*/
|
|
53
|
+
function resolveGitUserEmail(projectDir) {
|
|
54
|
+
const workingDirectory = typeof projectDir === 'string' && projectDir.trim()
|
|
55
|
+
? projectDir.trim()
|
|
56
|
+
: process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
57
|
+
return runGit(workingDirectory, ['config', 'user.email'], false).toLowerCase();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 解析 Langfuse 用户标识,优先使用 Git 邮箱并保留系统用户名兜底。
|
|
62
|
+
*/
|
|
63
|
+
function resolveAnalyzeUserId(projectDir) {
|
|
64
|
+
return resolveGitUserEmail(projectDir) || resolveSystemUsername();
|
|
65
|
+
}
|
|
66
|
+
|
|
49
67
|
/**
|
|
50
68
|
* 返回 analyze 命令使用的固定 Langfuse 配置。
|
|
51
69
|
*/
|
|
52
|
-
function getAnalyzeConfig() {
|
|
70
|
+
function getAnalyzeConfig(projectDir) {
|
|
53
71
|
return {
|
|
54
72
|
publicKey: LANGFUSE_PUBLIC_KEY,
|
|
55
73
|
secretKey: LANGFUSE_SECRET_KEY,
|
|
56
74
|
baseUrl: LANGFUSE_BASE_URL,
|
|
57
|
-
userId:
|
|
75
|
+
userId: resolveAnalyzeUserId(projectDir),
|
|
58
76
|
debug: readBooleanOption('CC_LANGFUSE_DEBUG', false),
|
|
59
77
|
maxChars: readPositiveIntegerOption('CC_LANGFUSE_MAX_CHARS', 20000),
|
|
60
78
|
skillTags: readBooleanOption('CC_LANGFUSE_SKILL_TAGS', true),
|
|
@@ -64,5 +82,7 @@ function getAnalyzeConfig() {
|
|
|
64
82
|
|
|
65
83
|
module.exports = {
|
|
66
84
|
getAnalyzeConfig,
|
|
85
|
+
resolveAnalyzeUserId,
|
|
86
|
+
resolveGitUserEmail,
|
|
67
87
|
resolveSystemUsername,
|
|
68
88
|
};
|