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
- text?: string | undefined;
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
- text?: string | undefined;
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
- "HEROKU_API_KEY",
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
- "HEROKU_API_KEY",
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 = isIrrelevantIssueWithTags ? getCommitIssueUrl({
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
- return { enqueue, flush, flushAsync, dispose, createPinoStream };
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.59" : "unknown";
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: `version:${CLI_VERSION}`,
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 = "Bash|Write|Edit|Agent|Read";
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") && (h.command?.includes("mobbdev") || h.command?.includes("mobbdev@"))
16802
+ (h) => h.command?.includes("claude-code-process-hook")
16791
16803
  );
16792
- if (isMobbHook && STALE_MATCHERS.has(hook.matcher)) {
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 hookData = validateHookData(rawData);
17235
- const sessionStore = createSessionConfigStore(hookData.session_id);
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: hookData.session_id
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(hookData.cwd);
17406
+ const log2 = createScopedHookLog(resolvedHookData.cwd ?? process.cwd());
17261
17407
  log2.info(
17262
17408
  {
17263
17409
  data: {
17264
- sessionId: hookData.session_id,
17265
- toolName: hookData.tool_name,
17266
- hookEvent: hookData.hook_event_name,
17267
- cwd: hookData.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(hookData, sessionStore, log2);
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,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobbdev",
3
- "version": "1.2.59",
3
+ "version": "1.2.62",
4
4
  "description": "Automated secure code remediation tool",
5
5
  "repository": "git+https://github.com/mobb-dev/bugsy.git",
6
6
  "main": "dist/index.mjs",