mobbdev 1.2.59 → 1.2.62
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.
|
@@ -56,22 +56,32 @@ declare const PromptItemZ: z.ZodObject<{
|
|
|
56
56
|
name: string;
|
|
57
57
|
parameters: string;
|
|
58
58
|
result: string;
|
|
59
|
-
rawArguments?: string | undefined;
|
|
60
59
|
accepted?: boolean | undefined;
|
|
60
|
+
rawArguments?: string | undefined;
|
|
61
61
|
mcpServer?: string | undefined;
|
|
62
62
|
mcpToolName?: string | undefined;
|
|
63
63
|
}, {
|
|
64
64
|
name: string;
|
|
65
65
|
parameters: string;
|
|
66
66
|
result: string;
|
|
67
|
-
rawArguments?: string | undefined;
|
|
68
67
|
accepted?: boolean | undefined;
|
|
68
|
+
rawArguments?: string | undefined;
|
|
69
69
|
mcpServer?: string | undefined;
|
|
70
70
|
mcpToolName?: string | undefined;
|
|
71
71
|
}>>;
|
|
72
72
|
}, "strip", z.ZodTypeAny, {
|
|
73
73
|
type: "USER_PROMPT" | "AI_RESPONSE" | "TOOL_EXECUTION" | "AI_THINKING" | "MCP_TOOL_CALL";
|
|
74
|
+
tool?: {
|
|
75
|
+
name: string;
|
|
76
|
+
parameters: string;
|
|
77
|
+
result: string;
|
|
78
|
+
accepted?: boolean | undefined;
|
|
79
|
+
rawArguments?: string | undefined;
|
|
80
|
+
mcpServer?: string | undefined;
|
|
81
|
+
mcpToolName?: string | undefined;
|
|
82
|
+
} | undefined;
|
|
74
83
|
date?: Date | undefined;
|
|
84
|
+
text?: string | undefined;
|
|
75
85
|
attachedFiles?: {
|
|
76
86
|
relativePath: string;
|
|
77
87
|
startLine?: number | undefined;
|
|
@@ -80,19 +90,19 @@ declare const PromptItemZ: z.ZodObject<{
|
|
|
80
90
|
inputCount: number;
|
|
81
91
|
outputCount: number;
|
|
82
92
|
} | undefined;
|
|
83
|
-
|
|
93
|
+
}, {
|
|
94
|
+
type: "USER_PROMPT" | "AI_RESPONSE" | "TOOL_EXECUTION" | "AI_THINKING" | "MCP_TOOL_CALL";
|
|
84
95
|
tool?: {
|
|
85
96
|
name: string;
|
|
86
97
|
parameters: string;
|
|
87
98
|
result: string;
|
|
88
|
-
rawArguments?: string | undefined;
|
|
89
99
|
accepted?: boolean | undefined;
|
|
100
|
+
rawArguments?: string | undefined;
|
|
90
101
|
mcpServer?: string | undefined;
|
|
91
102
|
mcpToolName?: string | undefined;
|
|
92
103
|
} | undefined;
|
|
93
|
-
}, {
|
|
94
|
-
type: "USER_PROMPT" | "AI_RESPONSE" | "TOOL_EXECUTION" | "AI_THINKING" | "MCP_TOOL_CALL";
|
|
95
104
|
date?: Date | undefined;
|
|
105
|
+
text?: string | undefined;
|
|
96
106
|
attachedFiles?: {
|
|
97
107
|
relativePath: string;
|
|
98
108
|
startLine?: number | undefined;
|
|
@@ -101,16 +111,6 @@ declare const PromptItemZ: z.ZodObject<{
|
|
|
101
111
|
inputCount: number;
|
|
102
112
|
outputCount: number;
|
|
103
113
|
} | undefined;
|
|
104
|
-
text?: string | undefined;
|
|
105
|
-
tool?: {
|
|
106
|
-
name: string;
|
|
107
|
-
parameters: string;
|
|
108
|
-
result: string;
|
|
109
|
-
rawArguments?: string | undefined;
|
|
110
|
-
accepted?: boolean | undefined;
|
|
111
|
-
mcpServer?: string | undefined;
|
|
112
|
-
mcpToolName?: string | undefined;
|
|
113
|
-
} | undefined;
|
|
114
114
|
}>;
|
|
115
115
|
type PromptItem = z.infer<typeof PromptItemZ>;
|
|
116
116
|
declare const PromptItemArrayZ: z.ZodArray<z.ZodObject<{
|
|
@@ -149,22 +149,32 @@ declare const PromptItemArrayZ: z.ZodArray<z.ZodObject<{
|
|
|
149
149
|
name: string;
|
|
150
150
|
parameters: string;
|
|
151
151
|
result: string;
|
|
152
|
-
rawArguments?: string | undefined;
|
|
153
152
|
accepted?: boolean | undefined;
|
|
153
|
+
rawArguments?: string | undefined;
|
|
154
154
|
mcpServer?: string | undefined;
|
|
155
155
|
mcpToolName?: string | undefined;
|
|
156
156
|
}, {
|
|
157
157
|
name: string;
|
|
158
158
|
parameters: string;
|
|
159
159
|
result: string;
|
|
160
|
-
rawArguments?: string | undefined;
|
|
161
160
|
accepted?: boolean | undefined;
|
|
161
|
+
rawArguments?: string | undefined;
|
|
162
162
|
mcpServer?: string | undefined;
|
|
163
163
|
mcpToolName?: string | undefined;
|
|
164
164
|
}>>;
|
|
165
165
|
}, "strip", z.ZodTypeAny, {
|
|
166
166
|
type: "USER_PROMPT" | "AI_RESPONSE" | "TOOL_EXECUTION" | "AI_THINKING" | "MCP_TOOL_CALL";
|
|
167
|
+
tool?: {
|
|
168
|
+
name: string;
|
|
169
|
+
parameters: string;
|
|
170
|
+
result: string;
|
|
171
|
+
accepted?: boolean | undefined;
|
|
172
|
+
rawArguments?: string | undefined;
|
|
173
|
+
mcpServer?: string | undefined;
|
|
174
|
+
mcpToolName?: string | undefined;
|
|
175
|
+
} | undefined;
|
|
167
176
|
date?: Date | undefined;
|
|
177
|
+
text?: string | undefined;
|
|
168
178
|
attachedFiles?: {
|
|
169
179
|
relativePath: string;
|
|
170
180
|
startLine?: number | undefined;
|
|
@@ -173,19 +183,19 @@ declare const PromptItemArrayZ: z.ZodArray<z.ZodObject<{
|
|
|
173
183
|
inputCount: number;
|
|
174
184
|
outputCount: number;
|
|
175
185
|
} | undefined;
|
|
176
|
-
|
|
186
|
+
}, {
|
|
187
|
+
type: "USER_PROMPT" | "AI_RESPONSE" | "TOOL_EXECUTION" | "AI_THINKING" | "MCP_TOOL_CALL";
|
|
177
188
|
tool?: {
|
|
178
189
|
name: string;
|
|
179
190
|
parameters: string;
|
|
180
191
|
result: string;
|
|
181
|
-
rawArguments?: string | undefined;
|
|
182
192
|
accepted?: boolean | undefined;
|
|
193
|
+
rawArguments?: string | undefined;
|
|
183
194
|
mcpServer?: string | undefined;
|
|
184
195
|
mcpToolName?: string | undefined;
|
|
185
196
|
} | undefined;
|
|
186
|
-
}, {
|
|
187
|
-
type: "USER_PROMPT" | "AI_RESPONSE" | "TOOL_EXECUTION" | "AI_THINKING" | "MCP_TOOL_CALL";
|
|
188
197
|
date?: Date | undefined;
|
|
198
|
+
text?: string | undefined;
|
|
189
199
|
attachedFiles?: {
|
|
190
200
|
relativePath: string;
|
|
191
201
|
startLine?: number | undefined;
|
|
@@ -194,16 +204,6 @@ declare const PromptItemArrayZ: z.ZodArray<z.ZodObject<{
|
|
|
194
204
|
inputCount: number;
|
|
195
205
|
outputCount: number;
|
|
196
206
|
} | undefined;
|
|
197
|
-
text?: string | undefined;
|
|
198
|
-
tool?: {
|
|
199
|
-
name: string;
|
|
200
|
-
parameters: string;
|
|
201
|
-
result: string;
|
|
202
|
-
rawArguments?: string | undefined;
|
|
203
|
-
accepted?: boolean | undefined;
|
|
204
|
-
mcpServer?: string | undefined;
|
|
205
|
-
mcpToolName?: string | undefined;
|
|
206
|
-
} | undefined;
|
|
207
207
|
}>, "many">;
|
|
208
208
|
type PromptItemArray = z.infer<typeof PromptItemArrayZ>;
|
|
209
209
|
/**
|
|
@@ -7209,7 +7209,17 @@ import Debug8 from "debug";
|
|
|
7209
7209
|
|
|
7210
7210
|
// src/utils/sanitize-sensitive-data.ts
|
|
7211
7211
|
import { OpenRedaction } from "@openredaction/openredaction";
|
|
7212
|
+
var ADO_PAT_PATTERN = {
|
|
7213
|
+
type: "AZURE_DEVOPS_PAT",
|
|
7214
|
+
regex: /\b[a-zA-Z0-9]{20,}JQQJ99[a-zA-Z0-9]{10,52}\b/g,
|
|
7215
|
+
priority: 95,
|
|
7216
|
+
placeholder: "[ADO_PAT_{n}]",
|
|
7217
|
+
description: "Azure DevOps Personal Access Token",
|
|
7218
|
+
severity: "high",
|
|
7219
|
+
validator: (match) => match.length >= 52 && match.length <= 100
|
|
7220
|
+
};
|
|
7212
7221
|
var openRedaction = new OpenRedaction({
|
|
7222
|
+
customPatterns: [ADO_PAT_PATTERN],
|
|
7213
7223
|
patterns: [
|
|
7214
7224
|
// Core Personal Data
|
|
7215
7225
|
// Removed EMAIL - causes false positives in code/test snippets (e.g. --author="Eve Author <eve@example.com>")
|
|
@@ -7280,7 +7290,9 @@ var openRedaction = new OpenRedaction({
|
|
|
7280
7290
|
"STRIPE_API_KEY",
|
|
7281
7291
|
"GOOGLE_API_KEY",
|
|
7282
7292
|
"FIREBASE_API_KEY",
|
|
7283
|
-
|
|
7293
|
+
// Removed HEROKU_API_KEY - its regex matches ALL UUIDs ([a-f0-9]{8}-[a-f0-9]{4}-...)
|
|
7294
|
+
// and the validator triggers on "auth" anywhere in context (e.g. "oauth2" in user IDs).
|
|
7295
|
+
// This causes false positives on every UUID when OAuth-related strings are nearby.
|
|
7284
7296
|
"MAILGUN_API_KEY",
|
|
7285
7297
|
"SENDGRID_API_KEY",
|
|
7286
7298
|
"TWILIO_API_KEY",
|
|
@@ -7305,7 +7317,11 @@ async function sanitizeDataWithCounts(obj) {
|
|
|
7305
7317
|
const counts = {
|
|
7306
7318
|
detections: { total: 0, high: 0, medium: 0, low: 0 }
|
|
7307
7319
|
};
|
|
7320
|
+
const MAX_SCAN_LENGTH = 1e5;
|
|
7308
7321
|
const sanitizeString = async (str) => {
|
|
7322
|
+
if (str.length > MAX_SCAN_LENGTH) {
|
|
7323
|
+
return str;
|
|
7324
|
+
}
|
|
7309
7325
|
let result = str;
|
|
7310
7326
|
const piiDetections = openRedaction.scan(str);
|
|
7311
7327
|
if (piiDetections && piiDetections.total > 0) {
|
package/dist/index.mjs
CHANGED
|
@@ -6468,27 +6468,6 @@ function getCommitUrl(params) {
|
|
|
6468
6468
|
analysisId
|
|
6469
6469
|
})}/commit?${searchParams.toString()}`;
|
|
6470
6470
|
}
|
|
6471
|
-
function getCommitIssueUrl(params) {
|
|
6472
|
-
const {
|
|
6473
|
-
issueId,
|
|
6474
|
-
projectId,
|
|
6475
|
-
organizationId,
|
|
6476
|
-
analysisId,
|
|
6477
|
-
redirectUrl,
|
|
6478
|
-
appBaseUrl,
|
|
6479
|
-
commentId
|
|
6480
|
-
} = params;
|
|
6481
|
-
const searchParams = new URLSearchParams();
|
|
6482
|
-
searchParams.append("redirect_url", redirectUrl);
|
|
6483
|
-
searchParams.append("comment_id", commentId.toString());
|
|
6484
|
-
return `${getIssueUrl({
|
|
6485
|
-
appBaseUrl,
|
|
6486
|
-
issueId,
|
|
6487
|
-
projectId,
|
|
6488
|
-
organizationId,
|
|
6489
|
-
analysisId
|
|
6490
|
-
})}/commit?${searchParams.toString()}`;
|
|
6491
|
-
}
|
|
6492
6471
|
function extractLinearTicketsFromBody(body, seen) {
|
|
6493
6472
|
const tickets = [];
|
|
6494
6473
|
const htmlPattern = /<a href="(https:\/\/linear\.app\/[^"]+)">([A-Z]+-\d+)<\/a>/g;
|
|
@@ -13207,7 +13186,17 @@ function getStableComputerName() {
|
|
|
13207
13186
|
|
|
13208
13187
|
// src/utils/sanitize-sensitive-data.ts
|
|
13209
13188
|
import { OpenRedaction } from "@openredaction/openredaction";
|
|
13189
|
+
var ADO_PAT_PATTERN = {
|
|
13190
|
+
type: "AZURE_DEVOPS_PAT",
|
|
13191
|
+
regex: /\b[a-zA-Z0-9]{20,}JQQJ99[a-zA-Z0-9]{10,52}\b/g,
|
|
13192
|
+
priority: 95,
|
|
13193
|
+
placeholder: "[ADO_PAT_{n}]",
|
|
13194
|
+
description: "Azure DevOps Personal Access Token",
|
|
13195
|
+
severity: "high",
|
|
13196
|
+
validator: (match) => match.length >= 52 && match.length <= 100
|
|
13197
|
+
};
|
|
13210
13198
|
var openRedaction = new OpenRedaction({
|
|
13199
|
+
customPatterns: [ADO_PAT_PATTERN],
|
|
13211
13200
|
patterns: [
|
|
13212
13201
|
// Core Personal Data
|
|
13213
13202
|
// Removed EMAIL - causes false positives in code/test snippets (e.g. --author="Eve Author <eve@example.com>")
|
|
@@ -13278,7 +13267,9 @@ var openRedaction = new OpenRedaction({
|
|
|
13278
13267
|
"STRIPE_API_KEY",
|
|
13279
13268
|
"GOOGLE_API_KEY",
|
|
13280
13269
|
"FIREBASE_API_KEY",
|
|
13281
|
-
|
|
13270
|
+
// Removed HEROKU_API_KEY - its regex matches ALL UUIDs ([a-f0-9]{8}-[a-f0-9]{4}-...)
|
|
13271
|
+
// and the validator triggers on "auth" anywhere in context (e.g. "oauth2" in user IDs).
|
|
13272
|
+
// This causes false positives on every UUID when OAuth-related strings are nearby.
|
|
13282
13273
|
"MAILGUN_API_KEY",
|
|
13283
13274
|
"SENDGRID_API_KEY",
|
|
13284
13275
|
"TWILIO_API_KEY",
|
|
@@ -13303,7 +13294,11 @@ async function sanitizeDataWithCounts(obj) {
|
|
|
13303
13294
|
const counts = {
|
|
13304
13295
|
detections: { total: 0, high: 0, medium: 0, low: 0 }
|
|
13305
13296
|
};
|
|
13297
|
+
const MAX_SCAN_LENGTH = 1e5;
|
|
13306
13298
|
const sanitizeString = async (str) => {
|
|
13299
|
+
if (str.length > MAX_SCAN_LENGTH) {
|
|
13300
|
+
return str;
|
|
13301
|
+
}
|
|
13307
13302
|
let result = str;
|
|
13308
13303
|
const piiDetections = openRedaction.scan(str);
|
|
13309
13304
|
if (piiDetections && piiDetections.total > 0) {
|
|
@@ -14263,15 +14258,7 @@ function buildFixCommentBody({
|
|
|
14263
14258
|
irrelevantIssueWithTags
|
|
14264
14259
|
}) {
|
|
14265
14260
|
const isIrrelevantIssueWithTags = irrelevantIssueWithTags?.[0]?.tag;
|
|
14266
|
-
const commitUrl =
|
|
14267
|
-
appBaseUrl: WEB_APP_URL,
|
|
14268
|
-
issueId,
|
|
14269
|
-
projectId,
|
|
14270
|
-
analysisId,
|
|
14271
|
-
organizationId,
|
|
14272
|
-
redirectUrl: commentUrl,
|
|
14273
|
-
commentId
|
|
14274
|
-
}) : getCommitUrl({
|
|
14261
|
+
const commitUrl = getCommitUrl({
|
|
14275
14262
|
appBaseUrl: WEB_APP_URL,
|
|
14276
14263
|
fixId,
|
|
14277
14264
|
projectId,
|
|
@@ -16423,9 +16410,11 @@ async function analyzeHandler(args) {
|
|
|
16423
16410
|
}
|
|
16424
16411
|
|
|
16425
16412
|
// src/features/claude_code/data_collector.ts
|
|
16413
|
+
import { execFile } from "child_process";
|
|
16426
16414
|
import { createHash as createHash2 } from "crypto";
|
|
16427
16415
|
import { access, open as open4, readdir, readFile, unlink } from "fs/promises";
|
|
16428
16416
|
import path14 from "path";
|
|
16417
|
+
import { promisify } from "util";
|
|
16429
16418
|
import { z as z33 } from "zod";
|
|
16430
16419
|
init_client_generates();
|
|
16431
16420
|
|
|
@@ -16581,7 +16570,10 @@ function createDdBatch(config2) {
|
|
|
16581
16570
|
}
|
|
16582
16571
|
});
|
|
16583
16572
|
}
|
|
16584
|
-
|
|
16573
|
+
function updateDdTags(ddtags) {
|
|
16574
|
+
config2.ddtags = ddtags;
|
|
16575
|
+
}
|
|
16576
|
+
return { enqueue, flush, flushAsync, dispose, createPinoStream, updateDdTags };
|
|
16585
16577
|
}
|
|
16586
16578
|
|
|
16587
16579
|
// src/utils/shared-logger/hostname.ts
|
|
@@ -16694,6 +16686,11 @@ function createLogger(config2) {
|
|
|
16694
16686
|
ddBatch.dispose();
|
|
16695
16687
|
}
|
|
16696
16688
|
}
|
|
16689
|
+
function updateDdTags(newDdTags) {
|
|
16690
|
+
if (ddBatch) {
|
|
16691
|
+
ddBatch.updateDdTags(newDdTags);
|
|
16692
|
+
}
|
|
16693
|
+
}
|
|
16697
16694
|
return {
|
|
16698
16695
|
info,
|
|
16699
16696
|
warn,
|
|
@@ -16704,14 +16701,23 @@ function createLogger(config2) {
|
|
|
16704
16701
|
flushLogs: flushLogs2,
|
|
16705
16702
|
flushDdAsync,
|
|
16706
16703
|
disposeDd,
|
|
16707
|
-
setScopePath: csStream.setScopePath
|
|
16704
|
+
setScopePath: csStream.setScopePath,
|
|
16705
|
+
updateDdTags
|
|
16708
16706
|
};
|
|
16709
16707
|
}
|
|
16710
16708
|
|
|
16711
16709
|
// src/features/claude_code/hook_logger.ts
|
|
16712
16710
|
var DD_RUM_TOKEN = true ? "pubf59c0182545bfb4c299175119f1abf9b" : "";
|
|
16713
|
-
var CLI_VERSION = true ? "1.2.
|
|
16711
|
+
var CLI_VERSION = true ? "1.2.62" : "unknown";
|
|
16714
16712
|
var NAMESPACE = "mobbdev-claude-code-hook-logs";
|
|
16713
|
+
var claudeCodeVersion;
|
|
16714
|
+
function buildDdTags() {
|
|
16715
|
+
const tags = [`version:${CLI_VERSION}`];
|
|
16716
|
+
if (claudeCodeVersion) {
|
|
16717
|
+
tags.push(`cc_version:${claudeCodeVersion}`);
|
|
16718
|
+
}
|
|
16719
|
+
return tags.join(",");
|
|
16720
|
+
}
|
|
16715
16721
|
function createHookLogger(scopePath) {
|
|
16716
16722
|
return createLogger({
|
|
16717
16723
|
namespace: NAMESPACE,
|
|
@@ -16720,7 +16726,7 @@ function createHookLogger(scopePath) {
|
|
|
16720
16726
|
apiKey: DD_RUM_TOKEN,
|
|
16721
16727
|
ddsource: "mobbdev-cli",
|
|
16722
16728
|
service: "mobbdev-cli-hook",
|
|
16723
|
-
ddtags:
|
|
16729
|
+
ddtags: buildDdTags(),
|
|
16724
16730
|
hostnameMode: "hashed",
|
|
16725
16731
|
unrefTimer: true
|
|
16726
16732
|
}
|
|
@@ -16729,6 +16735,13 @@ function createHookLogger(scopePath) {
|
|
|
16729
16735
|
var logger = createHookLogger();
|
|
16730
16736
|
var activeScopedLoggers = [];
|
|
16731
16737
|
var hookLog = logger;
|
|
16738
|
+
function setClaudeCodeVersion(version) {
|
|
16739
|
+
claudeCodeVersion = version;
|
|
16740
|
+
logger.updateDdTags(buildDdTags());
|
|
16741
|
+
}
|
|
16742
|
+
function getClaudeCodeVersion() {
|
|
16743
|
+
return claudeCodeVersion;
|
|
16744
|
+
}
|
|
16732
16745
|
function flushLogs() {
|
|
16733
16746
|
logger.flushLogs();
|
|
16734
16747
|
for (const scoped of activeScopedLoggers) {
|
|
@@ -16754,8 +16767,7 @@ import os5 from "os";
|
|
|
16754
16767
|
import path13 from "path";
|
|
16755
16768
|
import chalk11 from "chalk";
|
|
16756
16769
|
var CLAUDE_SETTINGS_PATH = path13.join(os5.homedir(), ".claude", "settings.json");
|
|
16757
|
-
var RECOMMENDED_MATCHER = "
|
|
16758
|
-
var STALE_MATCHERS = /* @__PURE__ */ new Set(["", "*", "Edit|Write"]);
|
|
16770
|
+
var RECOMMENDED_MATCHER = "Write|Edit";
|
|
16759
16771
|
async function claudeSettingsExists() {
|
|
16760
16772
|
try {
|
|
16761
16773
|
await fsPromises4.access(CLAUDE_SETTINGS_PATH);
|
|
@@ -16787,12 +16799,19 @@ async function autoUpgradeMatcherIfStale() {
|
|
|
16787
16799
|
let upgraded = false;
|
|
16788
16800
|
for (const hook of hooks) {
|
|
16789
16801
|
const isMobbHook = hook.hooks.some(
|
|
16790
|
-
(h) => h.command?.includes("claude-code-process-hook")
|
|
16802
|
+
(h) => h.command?.includes("claude-code-process-hook")
|
|
16791
16803
|
);
|
|
16792
|
-
if (isMobbHook
|
|
16804
|
+
if (!isMobbHook) continue;
|
|
16805
|
+
if (hook.matcher !== RECOMMENDED_MATCHER) {
|
|
16793
16806
|
hook.matcher = RECOMMENDED_MATCHER;
|
|
16794
16807
|
upgraded = true;
|
|
16795
16808
|
}
|
|
16809
|
+
for (const h of hook.hooks) {
|
|
16810
|
+
if (!h.async) {
|
|
16811
|
+
h.async = true;
|
|
16812
|
+
upgraded = true;
|
|
16813
|
+
}
|
|
16814
|
+
}
|
|
16796
16815
|
}
|
|
16797
16816
|
if (upgraded) {
|
|
16798
16817
|
await writeClaudeSettings(settings);
|
|
@@ -16846,7 +16865,8 @@ async function installMobbHooks(options = {}) {
|
|
|
16846
16865
|
hooks: [
|
|
16847
16866
|
{
|
|
16848
16867
|
type: "command",
|
|
16849
|
-
command
|
|
16868
|
+
command,
|
|
16869
|
+
async: true
|
|
16850
16870
|
}
|
|
16851
16871
|
]
|
|
16852
16872
|
};
|
|
@@ -16871,6 +16891,8 @@ async function installMobbHooks(options = {}) {
|
|
|
16871
16891
|
}
|
|
16872
16892
|
|
|
16873
16893
|
// src/features/claude_code/data_collector.ts
|
|
16894
|
+
var CC_VERSION_CACHE_KEY = "claudeCode.detectedCCVersion";
|
|
16895
|
+
var CC_VERSION_CLI_KEY = "claudeCode.detectedCCVersionCli";
|
|
16874
16896
|
var GLOBAL_COOLDOWN_MS = 5e3;
|
|
16875
16897
|
var HOOK_COOLDOWN_MS = 15e3;
|
|
16876
16898
|
var ACTIVE_LOCK_TTL_MS = 6e4;
|
|
@@ -16881,14 +16903,35 @@ var MAX_ENTRIES_PER_INVOCATION = 50;
|
|
|
16881
16903
|
var COOLDOWN_KEY = "lastHookRunAt";
|
|
16882
16904
|
var ACTIVE_KEY = "hookActiveAt";
|
|
16883
16905
|
var HookDataSchema = z33.object({
|
|
16884
|
-
session_id: z33.string(),
|
|
16885
|
-
transcript_path: z33.string(),
|
|
16886
|
-
cwd: z33.string(),
|
|
16906
|
+
session_id: z33.string().nullish(),
|
|
16907
|
+
transcript_path: z33.string().nullish(),
|
|
16908
|
+
cwd: z33.string().nullish(),
|
|
16887
16909
|
hook_event_name: z33.string(),
|
|
16888
16910
|
tool_name: z33.string(),
|
|
16889
16911
|
tool_input: z33.unknown(),
|
|
16890
16912
|
tool_response: z33.unknown()
|
|
16891
16913
|
});
|
|
16914
|
+
var execFileAsync = promisify(execFile);
|
|
16915
|
+
async function detectClaudeCodeVersion() {
|
|
16916
|
+
const cachedCliVersion = configStore.get(CC_VERSION_CLI_KEY);
|
|
16917
|
+
if (cachedCliVersion === packageJson.version) {
|
|
16918
|
+
return configStore.get(CC_VERSION_CACHE_KEY);
|
|
16919
|
+
}
|
|
16920
|
+
try {
|
|
16921
|
+
const { stdout: stdout2 } = await execFileAsync("claude", ["--version"], {
|
|
16922
|
+
timeout: 3e3,
|
|
16923
|
+
encoding: "utf-8"
|
|
16924
|
+
});
|
|
16925
|
+
const version = stdout2.trim().split(/\s/)[0] || stdout2.trim();
|
|
16926
|
+
configStore.set(CC_VERSION_CACHE_KEY, version);
|
|
16927
|
+
configStore.set(CC_VERSION_CLI_KEY, packageJson.version);
|
|
16928
|
+
return version;
|
|
16929
|
+
} catch {
|
|
16930
|
+
configStore.set(CC_VERSION_CACHE_KEY, void 0);
|
|
16931
|
+
configStore.set(CC_VERSION_CLI_KEY, packageJson.version);
|
|
16932
|
+
return void 0;
|
|
16933
|
+
}
|
|
16934
|
+
}
|
|
16892
16935
|
var STDIN_TIMEOUT_MS = 1e4;
|
|
16893
16936
|
async function readStdinData() {
|
|
16894
16937
|
hookLog.debug("Reading stdin data");
|
|
@@ -16940,6 +16983,24 @@ async function readStdinData() {
|
|
|
16940
16983
|
function validateHookData(data) {
|
|
16941
16984
|
return HookDataSchema.parse(data);
|
|
16942
16985
|
}
|
|
16986
|
+
async function extractSessionIdFromTranscript(transcriptPath) {
|
|
16987
|
+
try {
|
|
16988
|
+
const fh = await open4(transcriptPath, "r");
|
|
16989
|
+
try {
|
|
16990
|
+
const buf = Buffer.alloc(4096);
|
|
16991
|
+
const { bytesRead } = await fh.read(buf, 0, 4096, 0);
|
|
16992
|
+
const chunk = buf.toString("utf-8", 0, bytesRead);
|
|
16993
|
+
const firstLine = chunk.split("\n").find((l) => l.trim().length > 0);
|
|
16994
|
+
if (!firstLine) return null;
|
|
16995
|
+
const entry = JSON.parse(firstLine);
|
|
16996
|
+
return entry.sessionId ?? null;
|
|
16997
|
+
} finally {
|
|
16998
|
+
await fh.close();
|
|
16999
|
+
}
|
|
17000
|
+
} catch {
|
|
17001
|
+
return null;
|
|
17002
|
+
}
|
|
17003
|
+
}
|
|
16943
17004
|
function generateSyntheticId(sessionId, timestamp, type2, lineIndex) {
|
|
16944
17005
|
const input = `${sessionId ?? ""}:${timestamp ?? ""}:${type2 ?? ""}:${lineIndex}`;
|
|
16945
17006
|
const hash = createHash2("sha256").update(input).digest("hex").slice(0, 16);
|
|
@@ -17230,9 +17291,94 @@ async function processAndUploadTranscriptEntries() {
|
|
|
17230
17291
|
hookLog.info("Auto-upgraded hook matcher to reduce CPU usage");
|
|
17231
17292
|
}
|
|
17232
17293
|
}
|
|
17294
|
+
try {
|
|
17295
|
+
const ccVersion = await detectClaudeCodeVersion();
|
|
17296
|
+
setClaudeCodeVersion(ccVersion);
|
|
17297
|
+
} catch {
|
|
17298
|
+
}
|
|
17233
17299
|
const rawData = await readStdinData();
|
|
17234
|
-
const
|
|
17235
|
-
const
|
|
17300
|
+
const rawObj = rawData;
|
|
17301
|
+
const hookData = (() => {
|
|
17302
|
+
try {
|
|
17303
|
+
return validateHookData(rawData);
|
|
17304
|
+
} catch (err) {
|
|
17305
|
+
hookLog.error(
|
|
17306
|
+
{
|
|
17307
|
+
data: {
|
|
17308
|
+
hook_event_name: rawObj?.["hook_event_name"],
|
|
17309
|
+
tool_name: rawObj?.["tool_name"],
|
|
17310
|
+
session_id: rawObj?.["session_id"],
|
|
17311
|
+
cwd: rawObj?.["cwd"],
|
|
17312
|
+
keys: rawObj ? Object.keys(rawObj) : []
|
|
17313
|
+
}
|
|
17314
|
+
},
|
|
17315
|
+
`Hook validation failed: ${err.message?.slice(0, 200)}`
|
|
17316
|
+
);
|
|
17317
|
+
throw err;
|
|
17318
|
+
}
|
|
17319
|
+
})();
|
|
17320
|
+
if (!hookData.transcript_path) {
|
|
17321
|
+
hookLog.warn(
|
|
17322
|
+
{
|
|
17323
|
+
data: {
|
|
17324
|
+
hook_event_name: hookData.hook_event_name,
|
|
17325
|
+
tool_name: hookData.tool_name,
|
|
17326
|
+
session_id: hookData.session_id,
|
|
17327
|
+
cwd: hookData.cwd
|
|
17328
|
+
}
|
|
17329
|
+
},
|
|
17330
|
+
"Missing transcript_path \u2014 cannot process hook"
|
|
17331
|
+
);
|
|
17332
|
+
return { entriesUploaded: 0, entriesSkipped: 0, errors: 0 };
|
|
17333
|
+
}
|
|
17334
|
+
let sessionId = hookData.session_id;
|
|
17335
|
+
if (!sessionId) {
|
|
17336
|
+
sessionId = await extractSessionIdFromTranscript(hookData.transcript_path);
|
|
17337
|
+
if (sessionId) {
|
|
17338
|
+
hookLog.warn(
|
|
17339
|
+
{
|
|
17340
|
+
data: {
|
|
17341
|
+
hook_event_name: hookData.hook_event_name,
|
|
17342
|
+
tool_name: hookData.tool_name,
|
|
17343
|
+
cwd: hookData.cwd,
|
|
17344
|
+
extractedSessionId: sessionId
|
|
17345
|
+
}
|
|
17346
|
+
},
|
|
17347
|
+
"Missing session_id in hook data \u2014 extracted from transcript"
|
|
17348
|
+
);
|
|
17349
|
+
} else {
|
|
17350
|
+
hookLog.warn(
|
|
17351
|
+
{
|
|
17352
|
+
data: {
|
|
17353
|
+
hook_event_name: hookData.hook_event_name,
|
|
17354
|
+
tool_name: hookData.tool_name,
|
|
17355
|
+
transcript_path: hookData.transcript_path
|
|
17356
|
+
}
|
|
17357
|
+
},
|
|
17358
|
+
"Missing session_id and could not extract from transcript \u2014 cannot process hook"
|
|
17359
|
+
);
|
|
17360
|
+
return { entriesUploaded: 0, entriesSkipped: 0, errors: 0 };
|
|
17361
|
+
}
|
|
17362
|
+
}
|
|
17363
|
+
if (!hookData.cwd) {
|
|
17364
|
+
hookLog.warn(
|
|
17365
|
+
{
|
|
17366
|
+
data: {
|
|
17367
|
+
hook_event_name: hookData.hook_event_name,
|
|
17368
|
+
tool_name: hookData.tool_name,
|
|
17369
|
+
session_id: sessionId
|
|
17370
|
+
}
|
|
17371
|
+
},
|
|
17372
|
+
"Missing cwd in hook data \u2014 scoped logging and repo URL detection disabled"
|
|
17373
|
+
);
|
|
17374
|
+
}
|
|
17375
|
+
const resolvedHookData = {
|
|
17376
|
+
...hookData,
|
|
17377
|
+
session_id: sessionId,
|
|
17378
|
+
transcript_path: hookData.transcript_path,
|
|
17379
|
+
cwd: hookData.cwd ?? void 0
|
|
17380
|
+
};
|
|
17381
|
+
const sessionStore = createSessionConfigStore(resolvedHookData.session_id);
|
|
17236
17382
|
await cleanupStaleSessions(sessionStore);
|
|
17237
17383
|
const now = Date.now();
|
|
17238
17384
|
const lastRunAt = sessionStore.get(COOLDOWN_KEY);
|
|
@@ -17247,7 +17393,7 @@ async function processAndUploadTranscriptEntries() {
|
|
|
17247
17393
|
{
|
|
17248
17394
|
data: {
|
|
17249
17395
|
activeDurationMs: activeDuration,
|
|
17250
|
-
sessionId:
|
|
17396
|
+
sessionId: resolvedHookData.session_id
|
|
17251
17397
|
}
|
|
17252
17398
|
},
|
|
17253
17399
|
"Hook still active \u2014 possible slow upload or hung process"
|
|
@@ -17257,20 +17403,21 @@ async function processAndUploadTranscriptEntries() {
|
|
|
17257
17403
|
}
|
|
17258
17404
|
sessionStore.set(ACTIVE_KEY, now);
|
|
17259
17405
|
sessionStore.set(COOLDOWN_KEY, now);
|
|
17260
|
-
const log2 = createScopedHookLog(
|
|
17406
|
+
const log2 = createScopedHookLog(resolvedHookData.cwd ?? process.cwd());
|
|
17261
17407
|
log2.info(
|
|
17262
17408
|
{
|
|
17263
17409
|
data: {
|
|
17264
|
-
sessionId:
|
|
17265
|
-
toolName:
|
|
17266
|
-
hookEvent:
|
|
17267
|
-
cwd:
|
|
17410
|
+
sessionId: resolvedHookData.session_id,
|
|
17411
|
+
toolName: resolvedHookData.tool_name,
|
|
17412
|
+
hookEvent: resolvedHookData.hook_event_name,
|
|
17413
|
+
cwd: resolvedHookData.cwd,
|
|
17414
|
+
claudeCodeVersion: getClaudeCodeVersion()
|
|
17268
17415
|
}
|
|
17269
17416
|
},
|
|
17270
17417
|
"Hook data validated"
|
|
17271
17418
|
);
|
|
17272
17419
|
try {
|
|
17273
|
-
return await processTranscript(
|
|
17420
|
+
return await processTranscript(resolvedHookData, sessionStore, log2);
|
|
17274
17421
|
} finally {
|
|
17275
17422
|
sessionStore.delete(ACTIVE_KEY);
|
|
17276
17423
|
log2.flushLogs();
|
|
@@ -17359,6 +17506,9 @@ async function processTranscript(hookData, sessionStore, log2) {
|
|
|
17359
17506
|
rawEntry["message"] = { model: lastSeenModel };
|
|
17360
17507
|
}
|
|
17361
17508
|
}
|
|
17509
|
+
if (!rawEntry["sessionId"]) {
|
|
17510
|
+
rawEntry["sessionId"] = hookData.session_id;
|
|
17511
|
+
}
|
|
17362
17512
|
return {
|
|
17363
17513
|
platform: "CLAUDE_CODE" /* ClaudeCode */,
|
|
17364
17514
|
recordId: _recordId,
|
|
@@ -17400,7 +17550,8 @@ async function processTranscript(hookData, sessionStore, log2) {
|
|
|
17400
17550
|
sessionStore.set(cursorKey, cursor);
|
|
17401
17551
|
log2.heartbeat("Upload ok", {
|
|
17402
17552
|
entriesUploaded: entries.length,
|
|
17403
|
-
entriesSkipped: filteredOut
|
|
17553
|
+
entriesSkipped: filteredOut,
|
|
17554
|
+
claudeCodeVersion: getClaudeCodeVersion()
|
|
17404
17555
|
});
|
|
17405
17556
|
return {
|
|
17406
17557
|
entriesUploaded: entries.length,
|