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 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`
@@ -102,11 +102,20 @@ function extractHookContext(payload) {
102
102
  return null;
103
103
  }
104
104
  const hookEventName = payload.hook_event_name || payload.hookEventName || '';
105
- return {
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);
@@ -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: resolveSystemUsername(),
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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ronds_ai",
3
- "version": "0.1.23",
3
+ "version": "0.1.24",
4
4
  "description": "CLI for reporting AI code edit events.",
5
5
  "bin": {
6
6
  "ronds_ai": "bin/ronds_ai.js"