@posthog/agent 2.3.363 → 2.3.370

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/dist/agent.js CHANGED
@@ -63,11 +63,11 @@ var require_tree_sitter = __commonJS({
63
63
  throw toThrow;
64
64
  };
65
65
  var scriptDirectory = "";
66
- function locateFile(path14) {
66
+ function locateFile(path15) {
67
67
  if (Module["locateFile"]) {
68
- return Module["locateFile"](path14, scriptDirectory);
68
+ return Module["locateFile"](path15, scriptDirectory);
69
69
  }
70
- return scriptDirectory + path14;
70
+ return scriptDirectory + path15;
71
71
  }
72
72
  var readAsync, readBinary;
73
73
  if (ENVIRONMENT_IS_NODE) {
@@ -81,10 +81,10 @@ var require_tree_sitter = __commonJS({
81
81
  };
82
82
  readAsync = (filename, binary2 = true) => {
83
83
  filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename);
84
- return new Promise((resolve4, reject) => {
84
+ return new Promise((resolve6, reject) => {
85
85
  fs.readFile(filename, binary2 ? void 0 : "utf8", (err2, data) => {
86
86
  if (err2) reject(err2);
87
- else resolve4(binary2 ? data.buffer : data);
87
+ else resolve6(binary2 ? data.buffer : data);
88
88
  });
89
89
  });
90
90
  };
@@ -125,13 +125,13 @@ var require_tree_sitter = __commonJS({
125
125
  }
126
126
  readAsync = (url) => {
127
127
  if (isFileURI(url)) {
128
- return new Promise((reject, resolve4) => {
128
+ return new Promise((reject, resolve6) => {
129
129
  var xhr = new XMLHttpRequest();
130
130
  xhr.open("GET", url, true);
131
131
  xhr.responseType = "arraybuffer";
132
132
  xhr.onload = () => {
133
133
  if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
134
- resolve4(xhr.response);
134
+ resolve6(xhr.response);
135
135
  }
136
136
  reject(xhr.status);
137
137
  };
@@ -1091,8 +1091,8 @@ var require_tree_sitter = __commonJS({
1091
1091
  }
1092
1092
  var libFile = locateFile(libName2);
1093
1093
  if (flags2.loadAsync) {
1094
- return new Promise(function(resolve4, reject) {
1095
- asyncLoad(libFile, resolve4, reject);
1094
+ return new Promise(function(resolve6, reject) {
1095
+ asyncLoad(libFile, resolve6, reject);
1096
1096
  });
1097
1097
  }
1098
1098
  if (!readBinary) {
@@ -3696,15 +3696,15 @@ var require_src2 = __commonJS({
3696
3696
  var fs_1 = __require("fs");
3697
3697
  var debug_1 = __importDefault(require_src());
3698
3698
  var log = debug_1.default("@kwsites/file-exists");
3699
- function check(path14, isFile, isDirectory) {
3700
- log(`checking %s`, path14);
3699
+ function check(path15, isFile2, isDirectory) {
3700
+ log(`checking %s`, path15);
3701
3701
  try {
3702
- const stat = fs_1.statSync(path14);
3703
- if (stat.isFile() && isFile) {
3702
+ const stat2 = fs_1.statSync(path15);
3703
+ if (stat2.isFile() && isFile2) {
3704
3704
  log(`[OK] path represents a file`);
3705
3705
  return true;
3706
3706
  }
3707
- if (stat.isDirectory() && isDirectory) {
3707
+ if (stat2.isDirectory() && isDirectory) {
3708
3708
  log(`[OK] path represents a directory`);
3709
3709
  return true;
3710
3710
  }
@@ -3719,8 +3719,8 @@ var require_src2 = __commonJS({
3719
3719
  throw e;
3720
3720
  }
3721
3721
  }
3722
- function exists2(path14, type = exports2.READABLE) {
3723
- return check(path14, (type & exports2.FILE) > 0, (type & exports2.FOLDER) > 0);
3722
+ function exists2(path15, type = exports2.READABLE) {
3723
+ return check(path15, (type & exports2.FILE) > 0, (type & exports2.FOLDER) > 0);
3724
3724
  }
3725
3725
  exports2.exists = exists2;
3726
3726
  exports2.FILE = 1;
@@ -3846,17 +3846,17 @@ var Pushable = class {
3846
3846
  resolvers = [];
3847
3847
  done = false;
3848
3848
  push(item) {
3849
- const resolve4 = this.resolvers.shift();
3850
- if (resolve4) {
3851
- resolve4({ value: item, done: false });
3849
+ const resolve6 = this.resolvers.shift();
3850
+ if (resolve6) {
3851
+ resolve6({ value: item, done: false });
3852
3852
  } else {
3853
3853
  this.queue.push(item);
3854
3854
  }
3855
3855
  }
3856
3856
  end() {
3857
3857
  this.done = true;
3858
- for (const resolve4 of this.resolvers) {
3859
- resolve4({ value: void 0, done: true });
3858
+ for (const resolve6 of this.resolvers) {
3859
+ resolve6({ value: void 0, done: true });
3860
3860
  }
3861
3861
  this.resolvers = [];
3862
3862
  }
@@ -3873,8 +3873,8 @@ var Pushable = class {
3873
3873
  done: true
3874
3874
  });
3875
3875
  }
3876
- return new Promise((resolve4) => {
3877
- this.resolvers.push(resolve4);
3876
+ return new Promise((resolve6) => {
3877
+ this.resolvers.push(resolve6);
3878
3878
  });
3879
3879
  }
3880
3880
  };
@@ -3988,20 +3988,20 @@ function nodeReadableToWebReadable(nodeStream) {
3988
3988
  function nodeWritableToWebWritable(nodeStream) {
3989
3989
  return new WritableStream({
3990
3990
  write(chunk) {
3991
- return new Promise((resolve4, reject) => {
3991
+ return new Promise((resolve6, reject) => {
3992
3992
  const ok = nodeStream.write(Buffer.from(chunk), (err2) => {
3993
3993
  if (err2) reject(err2);
3994
3994
  });
3995
3995
  if (ok) {
3996
- resolve4();
3996
+ resolve6();
3997
3997
  } else {
3998
- nodeStream.once("drain", resolve4);
3998
+ nodeStream.once("drain", resolve6);
3999
3999
  }
4000
4000
  });
4001
4001
  },
4002
4002
  close() {
4003
- return new Promise((resolve4) => {
4004
- nodeStream.end(resolve4);
4003
+ return new Promise((resolve6) => {
4004
+ nodeStream.end(resolve6);
4005
4005
  });
4006
4006
  },
4007
4007
  abort(reason) {
@@ -4016,7 +4016,7 @@ function nodeWritableToWebWritable(nodeStream) {
4016
4016
  import { randomUUID } from "crypto";
4017
4017
  import * as fs8 from "fs";
4018
4018
  import * as os4 from "os";
4019
- import * as path11 from "path";
4019
+ import * as path12 from "path";
4020
4020
  import {
4021
4021
  RequestError as RequestError2
4022
4022
  } from "@agentclientprotocol/sdk";
@@ -4030,7 +4030,7 @@ import { v7 as uuidv7 } from "uuid";
4030
4030
  // package.json
4031
4031
  var package_default = {
4032
4032
  name: "@posthog/agent",
4033
- version: "2.3.363",
4033
+ version: "2.3.370",
4034
4034
  repository: "https://github.com/PostHog/code",
4035
4035
  description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
4036
4036
  exports: {
@@ -4220,15 +4220,17 @@ function isMethod(method, expected) {
4220
4220
  }
4221
4221
 
4222
4222
  // src/enrichment/file-enricher.ts
4223
- import * as path3 from "path";
4223
+ import * as path4 from "path";
4224
4224
 
4225
4225
  // ../enricher/dist/index.js
4226
4226
  var import_web_tree_sitter = __toESM(require_tree_sitter(), 1);
4227
- import { existsSync } from "fs";
4227
+ import { statSync } from "fs";
4228
4228
  import * as path from "path";
4229
+ import { existsSync } from "fs";
4230
+ import * as path2 from "path";
4229
4231
  import { fileURLToPath } from "url";
4230
4232
  import * as fs2 from "fs/promises";
4231
- import * as path2 from "path";
4233
+ import * as path3 from "path";
4232
4234
  function getCapture(captures, name2) {
4233
4235
  const found = captures.find((c) => c.name === name2);
4234
4236
  return found ? found.node : null;
@@ -4343,6 +4345,22 @@ function walkNodes(root, type, callback) {
4343
4345
  };
4344
4346
  visit(root);
4345
4347
  }
4348
+ var JSX_NODE_TYPES = /* @__PURE__ */ new Set([
4349
+ "jsx_element",
4350
+ "jsx_fragment",
4351
+ "jsx_self_closing_element",
4352
+ "jsx_opening_element",
4353
+ "jsx_closing_element",
4354
+ "jsx_attribute"
4355
+ ]);
4356
+ function isInsideJsx(node) {
4357
+ let cur = node.parent;
4358
+ while (cur) {
4359
+ if (JSX_NODE_TYPES.has(cur.type)) return true;
4360
+ cur = cur.parent;
4361
+ }
4362
+ return false;
4363
+ }
4346
4364
  var JS_CAPTURE_METHODS = /* @__PURE__ */ new Set(["capture"]);
4347
4365
  var JS_FLAG_METHODS = /* @__PURE__ */ new Set([
4348
4366
  "getFeatureFlag",
@@ -4528,6 +4546,33 @@ var JS_QUERIES = {
4528
4546
  object: (_) @client
4529
4547
  property: (property_identifier) @method)
4530
4548
  arguments: (arguments . (_) @first_arg)) @call
4549
+ `,
4550
+ imports: `
4551
+ (import_statement
4552
+ (import_clause
4553
+ (identifier) @default_name)
4554
+ source: (string (string_fragment) @source)) @stmt
4555
+
4556
+ (import_statement
4557
+ (import_clause
4558
+ (named_imports
4559
+ (import_specifier
4560
+ name: (identifier) @imported_name) @spec))
4561
+ source: (string (string_fragment) @source)) @stmt
4562
+
4563
+ (import_statement
4564
+ (import_clause
4565
+ (named_imports
4566
+ (import_specifier
4567
+ name: (identifier) @imported_name
4568
+ alias: (identifier) @local_name) @spec))
4569
+ source: (string (string_fragment) @source)) @stmt
4570
+
4571
+ (import_statement
4572
+ (import_clause
4573
+ (namespace_import
4574
+ (identifier) @namespace_name))
4575
+ source: (string (string_fragment) @source)) @stmt
4531
4576
  `
4532
4577
  };
4533
4578
  var PY_QUERIES = {
@@ -4604,6 +4649,31 @@ var PY_QUERIES = {
4604
4649
  object: (_) @client
4605
4650
  attribute: (identifier) @method)
4606
4651
  arguments: (argument_list . (_) @first_arg)) @call
4652
+ `,
4653
+ imports: `
4654
+ (import_from_statement
4655
+ module_name: (dotted_name) @source
4656
+ name: (dotted_name) @imported_name) @stmt
4657
+
4658
+ (import_from_statement
4659
+ module_name: (dotted_name) @source
4660
+ name: (aliased_import
4661
+ name: (dotted_name) @imported_name
4662
+ alias: (identifier) @local_name)) @stmt
4663
+
4664
+ (import_from_statement
4665
+ module_name: (relative_import
4666
+ (import_prefix) @relative_prefix
4667
+ (dotted_name)? @relative_name)
4668
+ name: (dotted_name) @imported_name) @stmt
4669
+
4670
+ (import_from_statement
4671
+ module_name: (relative_import
4672
+ (import_prefix) @relative_prefix
4673
+ (dotted_name)? @relative_name)
4674
+ name: (aliased_import
4675
+ name: (dotted_name) @imported_name
4676
+ alias: (identifier) @local_name)) @stmt
4607
4677
  `
4608
4678
  };
4609
4679
  var GO_QUERIES = {
@@ -4995,7 +5065,7 @@ function buildConstantMap(pm, lang, tree) {
4995
5065
  }
4996
5066
  var POSTHOG_CLASS_NAMES2 = /* @__PURE__ */ new Set(["PostHog", "Posthog"]);
4997
5067
  var GO_CONSTRUCTOR_NAMES2 = /* @__PURE__ */ new Set(["New", "NewWithConfig"]);
4998
- async function findPostHogCalls(pm, source, languageId) {
5068
+ async function findPostHogCalls(pm, source, languageId, context) {
4999
5069
  const ready = await pm.ensureReady(languageId);
5000
5070
  if (!ready) {
5001
5071
  return [];
@@ -5024,6 +5094,7 @@ async function findPostHogCalls(pm, source, languageId) {
5024
5094
  const clientNode = getCapture(match.captures, "client");
5025
5095
  const methodNode = getCapture(match.captures, "method");
5026
5096
  const keyNode = getCapture(match.captures, "key");
5097
+ const callNode = getCapture(match.captures, "call");
5027
5098
  if (!clientNode || !methodNode || !keyNode) {
5028
5099
  continue;
5029
5100
  }
@@ -5049,7 +5120,8 @@ async function findPostHogCalls(pm, source, languageId) {
5049
5120
  key: cleanStringValue(keyNode.text),
5050
5121
  line: keyNode.startPosition.row,
5051
5122
  keyStartCol: keyNode.startPosition.column,
5052
- keyEndCol: keyNode.endPosition.column
5123
+ keyEndCol: keyNode.endPosition.column,
5124
+ inJsx: callNode ? isInsideJsx(callNode) : void 0
5053
5125
  });
5054
5126
  }
5055
5127
  }
@@ -5104,6 +5176,7 @@ async function findPostHogCalls(pm, source, languageId) {
5104
5176
  const methodNode = getCapture(match.captures, "method");
5105
5177
  const propNameNode = getCapture(match.captures, "prop_name");
5106
5178
  const keyNode = getCapture(match.captures, "key");
5179
+ const callNode = getCapture(match.captures, "call");
5107
5180
  if (!clientNode || !methodNode || !propNameNode || !keyNode) {
5108
5181
  continue;
5109
5182
  }
@@ -5126,7 +5199,8 @@ async function findPostHogCalls(pm, source, languageId) {
5126
5199
  key: cleanStringValue(keyNode.text),
5127
5200
  line: keyNode.startPosition.row,
5128
5201
  keyStartCol: keyNode.startPosition.column,
5129
- keyEndCol: keyNode.endPosition.column
5202
+ keyEndCol: keyNode.endPosition.column,
5203
+ inJsx: callNode ? isInsideJsx(callNode) : void 0
5130
5204
  });
5131
5205
  }
5132
5206
  }
@@ -5223,6 +5297,7 @@ async function findPostHogCalls(pm, source, languageId) {
5223
5297
  for (const match of matches) {
5224
5298
  const funcNode = getCapture(match.captures, "func_name");
5225
5299
  const keyNode = getCapture(match.captures, "key");
5300
+ const callNode = getCapture(match.captures, "call");
5226
5301
  if (!funcNode || !keyNode) {
5227
5302
  continue;
5228
5303
  }
@@ -5233,7 +5308,8 @@ async function findPostHogCalls(pm, source, languageId) {
5233
5308
  key: cleanStringValue(keyNode.text),
5234
5309
  line: keyNode.startPosition.row,
5235
5310
  keyStartCol: keyNode.startPosition.column,
5236
- keyEndCol: keyNode.endPosition.column
5311
+ keyEndCol: keyNode.endPosition.column,
5312
+ inJsx: callNode ? isInsideJsx(callNode) : void 0
5237
5313
  });
5238
5314
  }
5239
5315
  }
@@ -5247,6 +5323,7 @@ async function findPostHogCalls(pm, source, languageId) {
5247
5323
  for (const match of matches) {
5248
5324
  const funcNode = getCapture(match.captures, "func_name");
5249
5325
  const keyNode = getCapture(match.captures, "key");
5326
+ const callNode = getCapture(match.captures, "call");
5250
5327
  if (!funcNode || !keyNode) {
5251
5328
  continue;
5252
5329
  }
@@ -5256,7 +5333,8 @@ async function findPostHogCalls(pm, source, languageId) {
5256
5333
  key: cleanStringValue(keyNode.text),
5257
5334
  line: keyNode.startPosition.row,
5258
5335
  keyStartCol: keyNode.startPosition.column,
5259
- keyEndCol: keyNode.endPosition.column
5336
+ keyEndCol: keyNode.endPosition.column,
5337
+ inJsx: callNode ? isInsideJsx(callNode) : void 0
5260
5338
  });
5261
5339
  }
5262
5340
  }
@@ -5271,6 +5349,7 @@ async function findPostHogCalls(pm, source, languageId) {
5271
5349
  const clientNode = getCapture(match.captures, "client");
5272
5350
  const methodNode = getCapture(match.captures, "method");
5273
5351
  const argNode = getCapture(match.captures, "arg_id");
5352
+ const callNode = getCapture(match.captures, "call");
5274
5353
  if (!clientNode || !methodNode || !argNode) {
5275
5354
  continue;
5276
5355
  }
@@ -5300,7 +5379,8 @@ async function findPostHogCalls(pm, source, languageId) {
5300
5379
  key: resolved,
5301
5380
  line,
5302
5381
  keyStartCol: argNode.startPosition.column,
5303
- keyEndCol: argNode.endPosition.column
5382
+ keyEndCol: argNode.endPosition.column,
5383
+ inJsx: callNode ? isInsideJsx(callNode) : void 0
5304
5384
  });
5305
5385
  }
5306
5386
  }
@@ -5313,6 +5393,7 @@ async function findPostHogCalls(pm, source, languageId) {
5313
5393
  const clientNode = getCapture(match.captures, "client");
5314
5394
  const methodNode = getCapture(match.captures, "method");
5315
5395
  const firstArgNode = getCapture(match.captures, "first_arg");
5396
+ const callNode = getCapture(match.captures, "call");
5316
5397
  if (!clientNode || !methodNode || !firstArgNode) {
5317
5398
  continue;
5318
5399
  }
@@ -5337,13 +5418,167 @@ async function findPostHogCalls(pm, source, languageId) {
5337
5418
  line,
5338
5419
  keyStartCol: firstArgNode.startPosition.column,
5339
5420
  keyEndCol: firstArgNode.endPosition.column,
5340
- dynamic: true
5421
+ dynamic: true,
5422
+ inJsx: callNode ? isInsideJsx(callNode) : void 0
5341
5423
  });
5342
5424
  matchedLines.add(line);
5343
5425
  }
5344
5426
  }
5427
+ if (context?.wrappersByLocalName?.size) {
5428
+ synthesizeBareWrapperCalls(
5429
+ pm,
5430
+ lang,
5431
+ tree,
5432
+ languageId,
5433
+ context.wrappersByLocalName,
5434
+ constantMap,
5435
+ calls,
5436
+ matchedLines
5437
+ );
5438
+ }
5439
+ if (context?.namespaceWrappers?.size) {
5440
+ synthesizeNamespaceWrapperCalls(
5441
+ pm,
5442
+ lang,
5443
+ tree,
5444
+ languageId,
5445
+ context.namespaceWrappers,
5446
+ constantMap,
5447
+ calls,
5448
+ matchedLines
5449
+ );
5450
+ }
5345
5451
  return calls;
5346
5452
  }
5453
+ var WRAPPER_BARE_CALL_QUERIES = {
5454
+ javascript: `(call_expression function: (identifier) @func_name arguments: (arguments) @args) @call`,
5455
+ javascriptreact: `(call_expression function: (identifier) @func_name arguments: (arguments) @args) @call`,
5456
+ typescript: `(call_expression function: (identifier) @func_name arguments: (arguments) @args) @call`,
5457
+ typescriptreact: `(call_expression function: (identifier) @func_name arguments: (arguments) @args) @call`,
5458
+ python: `(call function: (identifier) @func_name arguments: (argument_list) @args) @call`
5459
+ };
5460
+ var WRAPPER_NAMESPACE_CALL_QUERIES = {
5461
+ javascript: `(call_expression function: (member_expression object: (identifier) @ns property: (property_identifier) @method) arguments: (arguments) @args) @call`,
5462
+ javascriptreact: `(call_expression function: (member_expression object: (identifier) @ns property: (property_identifier) @method) arguments: (arguments) @args) @call`,
5463
+ typescript: `(call_expression function: (member_expression object: (identifier) @ns property: (property_identifier) @method) arguments: (arguments) @args) @call`,
5464
+ typescriptreact: `(call_expression function: (member_expression object: (identifier) @ns property: (property_identifier) @method) arguments: (arguments) @args) @call`,
5465
+ python: `(call function: (attribute object: (identifier) @ns attribute: (identifier) @method) arguments: (argument_list) @args) @call`
5466
+ };
5467
+ function synthesizeBareWrapperCalls(pm, lang, tree, languageId, wrappers, constantMap, calls, matchedLines) {
5468
+ const queryStr = WRAPPER_BARE_CALL_QUERIES[languageId];
5469
+ if (!queryStr) return;
5470
+ const query2 = pm.getQuery(lang, queryStr);
5471
+ if (!query2) return;
5472
+ for (const match of query2.matches(tree.rootNode)) {
5473
+ const funcNode = getCapture(match.captures, "func_name");
5474
+ const argsNode = getCapture(match.captures, "args");
5475
+ const callNode = getCapture(match.captures, "call");
5476
+ if (!funcNode || !argsNode) continue;
5477
+ const wrapper = wrappers.get(funcNode.text);
5478
+ if (!wrapper) continue;
5479
+ pushWrapperCall(
5480
+ wrapper,
5481
+ funcNode,
5482
+ argsNode,
5483
+ callNode,
5484
+ constantMap,
5485
+ calls,
5486
+ matchedLines
5487
+ );
5488
+ }
5489
+ }
5490
+ function synthesizeNamespaceWrapperCalls(pm, lang, tree, languageId, namespaceWrappers, constantMap, calls, matchedLines) {
5491
+ const queryStr = WRAPPER_NAMESPACE_CALL_QUERIES[languageId];
5492
+ if (!queryStr) return;
5493
+ const query2 = pm.getQuery(lang, queryStr);
5494
+ if (!query2) return;
5495
+ for (const match of query2.matches(tree.rootNode)) {
5496
+ const nsNode = getCapture(match.captures, "ns");
5497
+ const methodNode = getCapture(match.captures, "method");
5498
+ const argsNode = getCapture(match.captures, "args");
5499
+ const callNode = getCapture(match.captures, "call");
5500
+ if (!nsNode || !methodNode || !argsNode) continue;
5501
+ const nsWrappers = namespaceWrappers.get(nsNode.text);
5502
+ if (!nsWrappers) continue;
5503
+ const wrapper = nsWrappers.get(methodNode.text);
5504
+ if (!wrapper) continue;
5505
+ pushWrapperCall(
5506
+ wrapper,
5507
+ methodNode,
5508
+ argsNode,
5509
+ callNode,
5510
+ constantMap,
5511
+ calls,
5512
+ matchedLines
5513
+ );
5514
+ }
5515
+ }
5516
+ function pushWrapperCall(wrapper, callerNode, argsNode, callNode, constantMap, calls, matchedLines) {
5517
+ let line = callerNode.startPosition.row;
5518
+ let keyStartCol = callerNode.startPosition.column;
5519
+ let keyEndCol = callerNode.endPosition.column;
5520
+ let key = "";
5521
+ let dynamic = false;
5522
+ if (wrapper.classification.kind === "fixed-key") {
5523
+ key = wrapper.classification.key;
5524
+ } else {
5525
+ const positional = argsNode.namedChildren.filter(
5526
+ (c) => c.type !== "comment" && c.type !== "keyword_argument"
5527
+ );
5528
+ const arg = positional[wrapper.classification.paramIndex];
5529
+ if (!arg) return;
5530
+ line = arg.startPosition.row;
5531
+ keyStartCol = arg.startPosition.column;
5532
+ keyEndCol = arg.endPosition.column;
5533
+ if (arg.type === "string") {
5534
+ const fragment = arg.namedChildren.find(
5535
+ (c) => c.type === "string_fragment" || c.type === "string_content"
5536
+ );
5537
+ if (fragment) {
5538
+ key = fragment.text;
5539
+ } else {
5540
+ dynamic = true;
5541
+ }
5542
+ } else if (arg.type === "template_string") {
5543
+ const fragments = arg.namedChildren.filter(
5544
+ (c) => c.type === "string_fragment"
5545
+ );
5546
+ const hasInterp = arg.namedChildren.some(
5547
+ (c) => c.type === "template_substitution"
5548
+ );
5549
+ if (!hasInterp && fragments.length === 1) {
5550
+ key = fragments[0].text;
5551
+ } else {
5552
+ dynamic = true;
5553
+ }
5554
+ } else if (arg.type === "interpreted_string_literal") {
5555
+ key = arg.text.slice(1, -1);
5556
+ } else if (arg.type === "identifier") {
5557
+ const resolved = constantMap.get(arg.text);
5558
+ if (resolved) {
5559
+ key = resolved;
5560
+ } else {
5561
+ dynamic = true;
5562
+ }
5563
+ } else {
5564
+ dynamic = true;
5565
+ }
5566
+ }
5567
+ if (matchedLines.has(line) && dynamic) {
5568
+ return;
5569
+ }
5570
+ calls.push({
5571
+ method: wrapper.posthogMethod,
5572
+ key,
5573
+ line,
5574
+ keyStartCol,
5575
+ keyEndCol,
5576
+ dynamic: dynamic ? true : void 0,
5577
+ viaWrapper: wrapper.name,
5578
+ inJsx: callNode ? isInsideJsx(callNode) : void 0
5579
+ });
5580
+ matchedLines.add(line);
5581
+ }
5347
5582
  async function findInitCalls(pm, source, languageId) {
5348
5583
  const ready = await pm.ensureReady(languageId);
5349
5584
  if (!ready) {
@@ -5756,6 +5991,7 @@ async function findFunctions(pm, source, languageId) {
5756
5991
  }
5757
5992
  const params = singleParamNode ? [singleParamNode.text] : paramsNode ? extractParams(paramsNode.text) : [];
5758
5993
  const bodyLine = bodyNode.startPosition.row;
5994
+ const bodyEndLine = bodyNode.endPosition.row;
5759
5995
  const nextLineIdx = bodyLine + 1;
5760
5996
  const lines = text2.split("\n");
5761
5997
  const nextLine = nextLineIdx < lines.length ? lines[nextLineIdx] : "";
@@ -5765,6 +6001,7 @@ async function findFunctions(pm, source, languageId) {
5765
6001
  params,
5766
6002
  isComponent: /^[A-Z]/.test(name2),
5767
6003
  bodyLine,
6004
+ bodyEndLine,
5768
6005
  bodyIndent
5769
6006
  });
5770
6007
  }
@@ -5822,6 +6059,157 @@ async function findFlagAssignments(pm, source, languageId) {
5822
6059
  }
5823
6060
  return assignments;
5824
6061
  }
6062
+ var JS_EXTENSION_PROBES = [
6063
+ ".ts",
6064
+ ".tsx",
6065
+ ".mts",
6066
+ ".cts",
6067
+ ".js",
6068
+ ".jsx",
6069
+ ".mjs",
6070
+ ".cjs"
6071
+ ];
6072
+ var PY_EXTENSION_PROBES = [".py"];
6073
+ function isRelativeSpecifier(spec) {
6074
+ return spec.startsWith("./") || spec.startsWith("../") || spec === ".";
6075
+ }
6076
+ function resolveJsPath(callerAbsPath, specifier) {
6077
+ if (!isRelativeSpecifier(specifier)) return null;
6078
+ const dir = path.dirname(callerAbsPath);
6079
+ const base = path.resolve(dir, specifier);
6080
+ if (JS_EXTENSION_PROBES.includes(path.extname(specifier))) {
6081
+ return isFile(base) ? base : null;
6082
+ }
6083
+ if (isFile(base)) return base;
6084
+ for (const ext of JS_EXTENSION_PROBES) {
6085
+ const candidate = base + ext;
6086
+ if (isFile(candidate)) return candidate;
6087
+ }
6088
+ for (const ext of JS_EXTENSION_PROBES) {
6089
+ const candidate = path.join(base, `index${ext}`);
6090
+ if (isFile(candidate)) return candidate;
6091
+ }
6092
+ return null;
6093
+ }
6094
+ function isFile(p) {
6095
+ try {
6096
+ return statSync(p).isFile();
6097
+ } catch {
6098
+ return false;
6099
+ }
6100
+ }
6101
+ function resolvePythonModule(callerAbsPath, relativePrefix, moduleName) {
6102
+ if (!relativePrefix) return null;
6103
+ const dots = relativePrefix.length;
6104
+ const levelsUp = dots - 1;
6105
+ let baseDir = path.dirname(callerAbsPath);
6106
+ for (let i2 = 0; i2 < levelsUp; i2++) {
6107
+ baseDir = path.dirname(baseDir);
6108
+ }
6109
+ if (!moduleName) {
6110
+ const init2 = path.join(baseDir, "__init__.py");
6111
+ return isFile(init2) ? init2 : null;
6112
+ }
6113
+ const parts2 = moduleName.split(".");
6114
+ const joined = path.join(baseDir, ...parts2);
6115
+ for (const ext of PY_EXTENSION_PROBES) {
6116
+ const candidate = joined + ext;
6117
+ if (isFile(candidate)) return candidate;
6118
+ }
6119
+ const pkgInit = path.join(joined, "__init__.py");
6120
+ if (isFile(pkgInit)) return pkgInit;
6121
+ return null;
6122
+ }
6123
+ async function findImports(pm, source, languageId, callerAbsPath) {
6124
+ const ready = await pm.ensureReady(languageId);
6125
+ if (!ready) return [];
6126
+ const { lang, family } = ready;
6127
+ if (!family.queries.imports) return [];
6128
+ const tree = pm.parse(source, lang);
6129
+ if (!tree) return [];
6130
+ const query2 = pm.getQuery(lang, family.queries.imports);
6131
+ if (!query2) return [];
6132
+ const edges = [];
6133
+ const isPython = languageId === "python";
6134
+ for (const match of query2.matches(tree.rootNode)) {
6135
+ if (isPython) {
6136
+ pushPythonEdge(match.captures, callerAbsPath, edges);
6137
+ } else {
6138
+ pushJsEdge(match.captures, callerAbsPath, edges);
6139
+ }
6140
+ }
6141
+ return dedupe(edges);
6142
+ }
6143
+ function pushJsEdge(captures, callerAbsPath, out2) {
6144
+ const sourceNode = getCapture(captures, "source");
6145
+ if (!sourceNode) return;
6146
+ const specifier = sourceNode.text;
6147
+ if (!isRelativeSpecifier(specifier)) return;
6148
+ const resolvedAbsPath = resolveJsPath(callerAbsPath, specifier);
6149
+ const defaultNode = getCapture(captures, "default_name");
6150
+ if (defaultNode) {
6151
+ out2.push({
6152
+ localName: defaultNode.text,
6153
+ importedName: "default",
6154
+ isDefault: true,
6155
+ resolvedAbsPath
6156
+ });
6157
+ return;
6158
+ }
6159
+ const namespaceNode = getCapture(captures, "namespace_name");
6160
+ if (namespaceNode) {
6161
+ out2.push({
6162
+ localName: namespaceNode.text,
6163
+ importedName: "*",
6164
+ isNamespace: true,
6165
+ resolvedAbsPath
6166
+ });
6167
+ return;
6168
+ }
6169
+ const importedNode = getCapture(captures, "imported_name");
6170
+ if (importedNode) {
6171
+ const localNode = getCapture(captures, "local_name");
6172
+ out2.push({
6173
+ localName: (localNode ?? importedNode).text,
6174
+ importedName: importedNode.text,
6175
+ resolvedAbsPath
6176
+ });
6177
+ }
6178
+ }
6179
+ function pushPythonEdge(captures, callerAbsPath, out2) {
6180
+ const importedNode = getCapture(captures, "imported_name");
6181
+ if (!importedNode) return;
6182
+ const relativePrefix = getCapture(captures, "relative_prefix");
6183
+ const relativeName = getCapture(captures, "relative_name");
6184
+ const sourceNode = getCapture(captures, "source");
6185
+ let resolvedAbsPath = null;
6186
+ if (relativePrefix) {
6187
+ resolvedAbsPath = resolvePythonModule(
6188
+ callerAbsPath,
6189
+ relativePrefix.text,
6190
+ relativeName ? relativeName.text : null
6191
+ );
6192
+ } else if (sourceNode) {
6193
+ resolvedAbsPath = resolvePythonModule(callerAbsPath, ".", sourceNode.text);
6194
+ }
6195
+ const localNode = getCapture(captures, "local_name");
6196
+ out2.push({
6197
+ localName: (localNode ?? importedNode).text,
6198
+ importedName: importedNode.text,
6199
+ resolvedAbsPath
6200
+ });
6201
+ }
6202
+ function dedupe(edges) {
6203
+ const seen = /* @__PURE__ */ new Set();
6204
+ const out2 = [];
6205
+ for (const e of edges) {
6206
+ const key = `${e.localName}|${e.importedName}|${e.resolvedAbsPath ?? ""}|${e.isDefault ? "d" : ""}|${e.isNamespace ? "n" : ""}`;
6207
+ if (seen.has(key)) continue;
6208
+ seen.add(key);
6209
+ out2.push(e);
6210
+ }
6211
+ return out2;
6212
+ }
5825
6213
  var noop = {
5826
6214
  warn() {
5827
6215
  }
@@ -5837,17 +6225,18 @@ var DEFAULT_CONFIG = {
5837
6225
  };
5838
6226
  function resolveGrammarsDir() {
5839
6227
  const thisFile = fileURLToPath(import.meta.url);
5840
- const dir = path.dirname(thisFile);
6228
+ const dir = path2.dirname(thisFile);
5841
6229
  const candidates = [
5842
- path.join(dir, "..", "grammars"),
5843
- path.join(dir, "grammars"),
5844
- path.join(dir, "..", "..", "grammars")
6230
+ path2.join(dir, "..", "grammars"),
6231
+ path2.join(dir, "grammars"),
6232
+ path2.join(dir, "..", "..", "grammars")
5845
6233
  ];
5846
6234
  return candidates.find((p) => existsSync(p)) ?? candidates[0];
5847
6235
  }
5848
6236
  var ParserManager = class {
5849
6237
  parser = null;
5850
6238
  languages = /* @__PURE__ */ new Map();
6239
+ languageKeys = /* @__PURE__ */ new WeakMap();
5851
6240
  queryCache = /* @__PURE__ */ new Map();
5852
6241
  maxCacheSize = 256;
5853
6242
  initPromise = null;
@@ -5866,7 +6255,7 @@ var ParserManager = class {
5866
6255
  async doInit() {
5867
6256
  try {
5868
6257
  await import_web_tree_sitter.default.init({
5869
- locateFile: (scriptName) => path.join(this.wasmDir, scriptName)
6258
+ locateFile: (scriptName) => path2.join(this.wasmDir, scriptName)
5870
6259
  });
5871
6260
  this.parser = new import_web_tree_sitter.default();
5872
6261
  } catch (err2) {
@@ -5893,9 +6282,10 @@ var ParserManager = class {
5893
6282
  let lang = this.languages.get(family.wasm);
5894
6283
  if (!lang) {
5895
6284
  try {
5896
- const wasmPath = path.join(this.wasmDir, family.wasm);
6285
+ const wasmPath = path2.join(this.wasmDir, family.wasm);
5897
6286
  lang = await import_web_tree_sitter.default.Language.load(wasmPath);
5898
6287
  this.languages.set(family.wasm, lang);
6288
+ this.languageKeys.set(lang, family.wasm);
5899
6289
  } catch (err2) {
5900
6290
  warn(`Failed to load grammar ${family.wasm}`, err2);
5901
6291
  return null;
@@ -5914,7 +6304,8 @@ var ParserManager = class {
5914
6304
  if (!queryStr.trim()) {
5915
6305
  return null;
5916
6306
  }
5917
- const cacheKey = `${lang.toString()}:${queryStr}`;
6307
+ const langKey = this.languageKeys.get(lang) ?? lang.toString();
6308
+ const cacheKey = `${langKey}:${queryStr}`;
5918
6309
  let query2 = this.queryCache.get(cacheKey);
5919
6310
  if (query2) {
5920
6311
  this.queryCache.delete(cacheKey);
@@ -5941,6 +6332,7 @@ var ParserManager = class {
5941
6332
  this.parser = null;
5942
6333
  this.initPromise = null;
5943
6334
  this.languages.clear();
6335
+ this.languageKeys = /* @__PURE__ */ new WeakMap();
5944
6336
  this.queryCache.clear();
5945
6337
  }
5946
6338
  };
@@ -6755,6 +7147,260 @@ function isTruthinessCheckForVar(conditionNode, varName) {
6755
7147
  }
6756
7148
  return false;
6757
7149
  }
7150
+ var CONTROL_FLOW_KEYWORDS = /* @__PURE__ */ new Set([
7151
+ "if",
7152
+ "for",
7153
+ "while",
7154
+ "switch",
7155
+ "catch",
7156
+ "else"
7157
+ ]);
7158
+ function getKeyArgLocator(method, family, languageId) {
7159
+ if (languageId === "python") {
7160
+ if (family.captureMethods.has(method)) {
7161
+ return { positionalIndex: 1, kwargName: "event" };
7162
+ }
7163
+ if (family.flagMethods.has(method)) {
7164
+ return { positionalIndex: 0, kwargName: "key" };
7165
+ }
7166
+ return null;
7167
+ }
7168
+ if (family.allMethods.has(method)) {
7169
+ return { positionalIndex: 0 };
7170
+ }
7171
+ return null;
7172
+ }
7173
+ function extractRawParams(paramsNode, singleParamNode, languageId) {
7174
+ if (singleParamNode) {
7175
+ return [singleParamNode.text];
7176
+ }
7177
+ if (!paramsNode) {
7178
+ return [];
7179
+ }
7180
+ const names = [];
7181
+ for (const child of paramsNode.namedChildren) {
7182
+ const n = extractParamName(child, languageId);
7183
+ if (n) {
7184
+ names.push(n);
7185
+ } else {
7186
+ names.push("");
7187
+ }
7188
+ }
7189
+ return names;
7190
+ }
7191
+ function extractParamName(node, languageId) {
7192
+ switch (node.type) {
7193
+ case "identifier":
7194
+ return node.text;
7195
+ case "required_parameter":
7196
+ case "optional_parameter": {
7197
+ const pat = node.childForFieldName("pattern");
7198
+ if (pat) return extractParamName(pat, languageId);
7199
+ const name2 = node.childForFieldName("name");
7200
+ if (name2) return extractParamName(name2, languageId);
7201
+ const id = node.namedChildren.find((c) => c.type === "identifier");
7202
+ return id?.text ?? null;
7203
+ }
7204
+ case "assignment_pattern": {
7205
+ const left = node.childForFieldName("left");
7206
+ return left ? extractParamName(left, languageId) : null;
7207
+ }
7208
+ case "typed_parameter":
7209
+ case "default_parameter":
7210
+ case "typed_default_parameter": {
7211
+ const name2 = node.childForFieldName("name");
7212
+ if (name2) return extractParamName(name2, languageId);
7213
+ const id = node.namedChildren.find((c) => c.type === "identifier");
7214
+ return id?.text ?? null;
7215
+ }
7216
+ case "parameter": {
7217
+ const id = node.namedChildren.find(
7218
+ (c) => c.type === "identifier" || c.type === "field_identifier"
7219
+ );
7220
+ return id?.text ?? null;
7221
+ }
7222
+ default: {
7223
+ const id = node.namedChildren.find((c) => c.type === "identifier");
7224
+ return id?.text ?? null;
7225
+ }
7226
+ }
7227
+ }
7228
+ function findPostHogCallInBody(body2, allClients, family, languageId, detectNested) {
7229
+ let found = null;
7230
+ const visit = (node) => {
7231
+ if (found) return;
7232
+ const call = matchPostHogCall(
7233
+ node,
7234
+ allClients,
7235
+ family,
7236
+ languageId,
7237
+ detectNested
7238
+ );
7239
+ if (call) {
7240
+ found = call;
7241
+ return;
7242
+ }
7243
+ for (const child of node.namedChildren) {
7244
+ if (found) return;
7245
+ visit(child);
7246
+ }
7247
+ };
7248
+ visit(body2);
7249
+ return found;
7250
+ }
7251
+ function matchPostHogCall(node, allClients, family, languageId, detectNested) {
7252
+ if (node.type !== "call_expression" && node.type !== "call") return null;
7253
+ const funcNode = node.childForFieldName("function");
7254
+ if (!funcNode) return null;
7255
+ let method = null;
7256
+ if (funcNode.type === "member_expression" || funcNode.type === "attribute") {
7257
+ const objNode = funcNode.childForFieldName("object") || funcNode.childForFieldName("operand");
7258
+ const propNode = funcNode.childForFieldName("property") || funcNode.childForFieldName("attribute");
7259
+ if (!objNode || !propNode) return null;
7260
+ const clientName = extractClientName(objNode, detectNested);
7261
+ if (!clientName || !allClients.has(clientName)) return null;
7262
+ method = propNode.text;
7263
+ } else if (funcNode.type === "selector_expression") {
7264
+ const opNode = funcNode.childForFieldName("operand");
7265
+ const fieldNode = funcNode.childForFieldName("field");
7266
+ if (!opNode || !fieldNode) return null;
7267
+ const clientName = extractClientName(opNode, detectNested);
7268
+ if (!clientName || !allClients.has(clientName)) return null;
7269
+ method = fieldNode.text;
7270
+ } else {
7271
+ return null;
7272
+ }
7273
+ if (!method || !family.allMethods.has(method)) return null;
7274
+ const locator = getKeyArgLocator(method, family, languageId);
7275
+ if (!locator) return null;
7276
+ const argsNode = node.childForFieldName("arguments") || node.namedChildren.find(
7277
+ (c) => c.type === "arguments" || c.type === "argument_list"
7278
+ ) || null;
7279
+ if (!argsNode) return null;
7280
+ const { keyNode, kwargName } = pickKeyArg(argsNode, locator);
7281
+ return {
7282
+ method,
7283
+ keyArgNode: keyNode,
7284
+ kwargName
7285
+ };
7286
+ }
7287
+ function pickKeyArg(argsNode, locator) {
7288
+ const positional = [];
7289
+ let kwargHit = null;
7290
+ let kwargName = null;
7291
+ for (const child of argsNode.namedChildren) {
7292
+ if (child.type === "keyword_argument") {
7293
+ const nameNode = child.childForFieldName("name");
7294
+ const valueNode = child.childForFieldName("value");
7295
+ if (nameNode && valueNode && locator.kwargName && nameNode.text === locator.kwargName) {
7296
+ kwargHit = valueNode;
7297
+ kwargName = nameNode.text;
7298
+ }
7299
+ continue;
7300
+ }
7301
+ positional.push(child);
7302
+ }
7303
+ if (kwargHit) {
7304
+ return { keyNode: kwargHit, kwargName };
7305
+ }
7306
+ const positionalHit = positional[locator.positionalIndex] ?? null;
7307
+ return { keyNode: positionalHit, kwargName: null };
7308
+ }
7309
+ function classifyKeyArg(keyArgNode, params) {
7310
+ if (!keyArgNode) return null;
7311
+ if (keyArgNode.type === "string" || keyArgNode.type === "interpreted_string_literal") {
7312
+ const key = extractStringFromNode(keyArgNode);
7313
+ return key !== null ? { kind: "fixed-key", key } : null;
7314
+ }
7315
+ if (keyArgNode.type === "template_string") {
7316
+ const hasInterpolation = keyArgNode.namedChildren.some(
7317
+ (c) => c.type === "template_substitution"
7318
+ );
7319
+ if (hasInterpolation) return null;
7320
+ const key = extractStringFromNode(keyArgNode);
7321
+ return key !== null ? { kind: "fixed-key", key } : null;
7322
+ }
7323
+ if (keyArgNode.type === "identifier") {
7324
+ const idx = params.indexOf(keyArgNode.text);
7325
+ if (idx >= 0) return { kind: "pass-through", paramIndex: idx };
7326
+ return null;
7327
+ }
7328
+ return null;
7329
+ }
7330
+ function getExportStatus(nameNode, languageId) {
7331
+ const defNode = nameNode.parent;
7332
+ if (!defNode) return { isDefaultExport: false, isNamedExport: false };
7333
+ if (languageId === "python") {
7334
+ let cur2 = defNode.parent;
7335
+ while (cur2) {
7336
+ if (cur2.type === "module") {
7337
+ return { isDefaultExport: false, isNamedExport: true };
7338
+ }
7339
+ if (cur2.type === "function_definition" || cur2.type === "class_definition") {
7340
+ return { isDefaultExport: false, isNamedExport: false };
7341
+ }
7342
+ cur2 = cur2.parent;
7343
+ }
7344
+ return { isDefaultExport: false, isNamedExport: false };
7345
+ }
7346
+ let cur = defNode.parent;
7347
+ while (cur) {
7348
+ if (cur.type === "export_statement") {
7349
+ const hasDefault = cur.children.some((c) => c.type === "default");
7350
+ return { isDefaultExport: hasDefault, isNamedExport: !hasDefault };
7351
+ }
7352
+ if (cur.type === "program" || cur.type === "module") break;
7353
+ cur = cur.parent;
7354
+ }
7355
+ return { isDefaultExport: false, isNamedExport: false };
7356
+ }
7357
+ async function findWrappers(pm, source, languageId) {
7358
+ const ready = await pm.ensureReady(languageId);
7359
+ if (!ready) return [];
7360
+ const { lang, family } = ready;
7361
+ const tree = pm.parse(source, lang);
7362
+ if (!tree) return [];
7363
+ const functionQuery = pm.getQuery(lang, family.queries.functions);
7364
+ if (!functionQuery) return [];
7365
+ const allClients = getEffectiveClients(pm.config);
7366
+ const { clientAliases } = findAliases(pm, lang, tree, family);
7367
+ for (const a of clientAliases) allClients.add(a);
7368
+ const wrappers = [];
7369
+ const seen = /* @__PURE__ */ new Set();
7370
+ for (const match of functionQuery.matches(tree.rootNode)) {
7371
+ const nameNode = getCapture(match.captures, "func_name");
7372
+ const paramsNode = getCapture(match.captures, "func_params");
7373
+ const singleParamNode = getCapture(match.captures, "func_single_param");
7374
+ const bodyNode = getCapture(match.captures, "func_body");
7375
+ if (!nameNode || !bodyNode) continue;
7376
+ const name2 = nameNode.text;
7377
+ if (CONTROL_FLOW_KEYWORDS.has(name2)) continue;
7378
+ if (seen.has(name2)) continue;
7379
+ const params = extractRawParams(paramsNode, singleParamNode, languageId);
7380
+ const call = findPostHogCallInBody(
7381
+ bodyNode,
7382
+ allClients,
7383
+ family,
7384
+ languageId,
7385
+ pm.config.detectNestedClients
7386
+ );
7387
+ if (!call) continue;
7388
+ const classification = classifyKeyArg(call.keyArgNode, params);
7389
+ if (!classification) continue;
7390
+ const methodKind = family.captureMethods.has(call.method) ? "capture" : "flag";
7391
+ const posthogMethod = call.method === "Enqueue" ? "capture" : call.method;
7392
+ const exportStatus = getExportStatus(nameNode, languageId);
7393
+ seen.add(name2);
7394
+ wrappers.push({
7395
+ name: name2,
7396
+ methodKind,
7397
+ posthogMethod,
7398
+ classification,
7399
+ ...exportStatus
7400
+ });
7401
+ }
7402
+ return wrappers;
7403
+ }
6758
7404
  var PostHogDetector = class {
6759
7405
  pm = new ParserManager();
6760
7406
  updateConfig(config) {
@@ -6766,8 +7412,8 @@ var PostHogDetector = class {
6766
7412
  get supportedLanguages() {
6767
7413
  return this.pm.supportedLanguages;
6768
7414
  }
6769
- async findPostHogCalls(source, languageId) {
6770
- return findPostHogCalls(this.pm, source, languageId);
7415
+ async findPostHogCalls(source, languageId, context) {
7416
+ return findPostHogCalls(this.pm, source, languageId, context);
6771
7417
  }
6772
7418
  async findInitCalls(source, languageId) {
6773
7419
  return findInitCalls(this.pm, source, languageId);
@@ -6781,6 +7427,12 @@ var PostHogDetector = class {
6781
7427
  async findFlagAssignments(source, languageId) {
6782
7428
  return findFlagAssignments(this.pm, source, languageId);
6783
7429
  }
7430
+ async findWrappers(source, languageId) {
7431
+ return findWrappers(this.pm, source, languageId);
7432
+ }
7433
+ async findImports(source, languageId, callerAbsPath) {
7434
+ return findImports(this.pm, source, languageId, callerAbsPath);
7435
+ }
6784
7436
  dispose() {
6785
7437
  this.pm.dispose();
6786
7438
  }
@@ -6885,18 +7537,32 @@ function commentPrefix(languageId) {
6885
7537
  }
6886
7538
  function formatFlagComment(flag) {
6887
7539
  const parts2 = [`Flag: "${flag.flagKey}"`];
6888
- if (flag.flag) {
6889
- parts2.push(flag.flagType);
6890
- if (flag.rollout !== null) {
6891
- parts2.push(`${flag.rollout}% rolled out`);
6892
- }
6893
- if (flag.experiment) {
6894
- const status = flag.experiment.end_date ? "complete" : "running";
6895
- parts2.push(`Experiment: "${flag.experiment.name}" (${status})`);
6896
- }
6897
- if (flag.staleness) {
6898
- parts2.push(`STALE (${flag.staleness})`);
6899
- }
7540
+ if (!flag.flag) {
7541
+ parts2.push("not in PostHog");
7542
+ return parts2.join(" \u2014 ");
7543
+ }
7544
+ parts2.push(flag.flagType);
7545
+ parts2.push(flag.flag.active ? "active" : "inactive");
7546
+ if (flag.rollout !== null) {
7547
+ parts2.push(`${flag.rollout}% rolled out`);
7548
+ }
7549
+ if (flag.evaluationStats) {
7550
+ const evals = flag.evaluationStats.evaluations.toLocaleString();
7551
+ const users = flag.evaluationStats.uniqueUsers.toLocaleString();
7552
+ const days = flag.evaluationStats.windowDays;
7553
+ parts2.push(`${evals} evals / ${users} users (${days}d)`);
7554
+ } else if (flag.evaluationStatsError) {
7555
+ parts2.push("eval stats unavailable");
7556
+ }
7557
+ if (flag.experiment) {
7558
+ const status = flag.experiment.end_date ? "complete" : "running";
7559
+ parts2.push(`Experiment: "${flag.experiment.name}" (${status})`);
7560
+ }
7561
+ if (flag.staleness) {
7562
+ parts2.push(`STALE (${flag.staleness})`);
7563
+ }
7564
+ if (flag.url) {
7565
+ parts2.push(flag.url);
6900
7566
  }
6901
7567
  return parts2.join(" \u2014 ");
6902
7568
  }
@@ -6917,21 +7583,25 @@ function formatEventComment(event) {
6917
7583
  return parts2.join(" \u2014 ");
6918
7584
  }
6919
7585
  function buildCommentBody(item, enrichedFlags, enrichedEvents) {
7586
+ let body2 = null;
6920
7587
  if (item.type === "flag") {
6921
7588
  const flag = enrichedFlags.get(item.name);
6922
- if (flag) return formatFlagComment(flag);
6923
- return null;
6924
- }
6925
- if (item.type === "event") {
7589
+ body2 = flag ? formatFlagComment(flag) : null;
7590
+ } else if (item.type === "event") {
6926
7591
  const event = enrichedEvents.get(item.name);
6927
- if (event) return formatEventComment(event);
6928
- if (item.detail) return `Event: ${item.detail}`;
6929
- return null;
7592
+ if (event) {
7593
+ body2 = formatEventComment(event);
7594
+ } else if (item.detail) {
7595
+ body2 = `Event: ${item.detail}`;
7596
+ }
7597
+ } else if (item.type === "init") {
7598
+ body2 = `Init: token "${item.name}"`;
6930
7599
  }
6931
- if (item.type === "init") {
6932
- return `Init: token "${item.name}"`;
7600
+ if (!body2) return null;
7601
+ if (item.viaWrapper) {
7602
+ body2 = `${body2} (via ${item.viaWrapper})`;
6933
7603
  }
6934
- return null;
7604
+ return body2;
6935
7605
  }
6936
7606
  function formatComments(source, languageId, items, enrichedFlags, enrichedEvents) {
6937
7607
  const prefix = commentPrefix(languageId);
@@ -6942,7 +7612,7 @@ function formatComments(source, languageId, items, enrichedFlags, enrichedEvents
6942
7612
  const targetLine = item.line + offset;
6943
7613
  const body2 = buildCommentBody(item, enrichedFlags, enrichedEvents);
6944
7614
  if (!body2) continue;
6945
- const comment = `${prefix} [PostHog] ${body2}`;
7615
+ const comment = item.inJsx ? `{/* [PostHog] ${body2} */}` : `${prefix} [PostHog] ${body2}`;
6946
7616
  const indent = lines[targetLine]?.match(/^(\s*)/)?.[1] ?? "";
6947
7617
  lines.splice(targetLine, 0, `${indent}${comment}`);
6948
7618
  offset++;
@@ -6956,15 +7626,32 @@ function formatInlineComments(source, languageId, items, enrichedFlags, enriched
6956
7626
  for (const item of items) {
6957
7627
  const body2 = buildCommentBody(item, enrichedFlags, enrichedEvents);
6958
7628
  if (!body2) continue;
6959
- const arr = byLine.get(item.line) ?? [];
6960
- arr.push(body2);
6961
- byLine.set(item.line, arr);
7629
+ const entry = byLine.get(item.line) ?? { jsxBodies: [], nonJsxBodies: [] };
7630
+ (item.inJsx ? entry.jsxBodies : entry.nonJsxBodies).push(body2);
7631
+ byLine.set(item.line, entry);
6962
7632
  }
6963
- for (const [lineIdx, bodies] of byLine) {
7633
+ const leadingInserts = [];
7634
+ for (const [lineIdx, { jsxBodies, nonJsxBodies }] of byLine) {
6964
7635
  if (lineIdx < 0 || lineIdx >= lines.length) continue;
6965
- const suffix = ` ${prefix} [PostHog] ${bodies.join(" | ")}`;
7636
+ if (jsxBodies.length > 0 && nonJsxBodies.length > 0) {
7637
+ const joined2 = [...nonJsxBodies, ...jsxBodies].join(" | ");
7638
+ const indent = lines[lineIdx]?.match(/^(\s*)/)?.[1] ?? "";
7639
+ leadingInserts.push({
7640
+ atLine: lineIdx,
7641
+ text: `${indent}{/* [PostHog] ${joined2} */}`
7642
+ });
7643
+ continue;
7644
+ }
7645
+ const isJsx = jsxBodies.length > 0;
7646
+ const bodies = isJsx ? jsxBodies : nonJsxBodies;
7647
+ const joined = bodies.join(" | ");
7648
+ const suffix = isJsx ? ` {/* [PostHog] ${joined} */}` : ` ${prefix} [PostHog] ${joined}`;
6966
7649
  lines[lineIdx] = `${lines[lineIdx]}${suffix}`;
6967
7650
  }
7651
+ leadingInserts.sort((a, b) => b.atLine - a.atLine);
7652
+ for (const { atLine, text: text2 } of leadingInserts) {
7653
+ lines.splice(atLine, 0, text2);
7654
+ }
6968
7655
  return lines.join("\n");
6969
7656
  }
6970
7657
  var EnrichedResult = class {
@@ -6987,6 +7674,7 @@ var EnrichedResult = class {
6987
7674
  let entry = flagMap.get(check.flagKey);
6988
7675
  if (!entry) {
6989
7676
  const flag = this.context.flags?.get(check.flagKey);
7677
+ const url = this.context.flagUrls?.get(check.flagKey) ?? null;
6990
7678
  entry = {
6991
7679
  flagKey: check.flagKey,
6992
7680
  occurrences: [],
@@ -7002,7 +7690,10 @@ var EnrichedResult = class {
7002
7690
  variants: flag ? extractVariants(flag) : [],
7003
7691
  experiment: experiments.find(
7004
7692
  (e) => e.feature_flag_key === check.flagKey
7005
- )
7693
+ ),
7694
+ url,
7695
+ evaluationStats: this.context.flagEvaluationStats?.get(check.flagKey),
7696
+ evaluationStatsError: this.context.flagEvaluationStatsError ?? false
7006
7697
  };
7007
7698
  flagMap.set(check.flagKey, entry);
7008
7699
  }
@@ -7060,6 +7751,10 @@ var EnrichedResult = class {
7060
7751
  enriched.flagType = flag.flagType;
7061
7752
  enriched.staleness = flag.staleness;
7062
7753
  enriched.rollout = flag.rollout;
7754
+ enriched.active = flag.flag?.active;
7755
+ enriched.url = flag.url;
7756
+ enriched.evaluations = flag.evaluationStats?.evaluations;
7757
+ enriched.evaluationUsers = flag.evaluationStats?.uniqueUsers;
7063
7758
  if (flag.experiment) {
7064
7759
  enriched.experimentName = flag.experiment.name;
7065
7760
  enriched.experimentStatus = flag.experiment.end_date ? "complete" : "running";
@@ -7126,8 +7821,8 @@ var PostHogApi = class {
7126
7821
  get signal() {
7127
7822
  return AbortSignal.timeout(this.config.timeoutMs ?? 1e4);
7128
7823
  }
7129
- async get(path32) {
7130
- const res = await fetch(`${this.baseUrl}${path32}`, {
7824
+ async get(path42) {
7825
+ const res = await fetch(`${this.baseUrl}${path42}`, {
7131
7826
  headers: {
7132
7827
  Authorization: `Bearer ${this.config.apiKey}`,
7133
7828
  "Content-Type": "application/json"
@@ -7136,13 +7831,13 @@ var PostHogApi = class {
7136
7831
  });
7137
7832
  if (!res.ok) {
7138
7833
  throw new Error(
7139
- `PostHog API error: ${res.status} ${res.statusText} on GET ${path32}`
7834
+ `PostHog API error: ${res.status} ${res.statusText} on GET ${path42}`
7140
7835
  );
7141
7836
  }
7142
7837
  return res.json();
7143
7838
  }
7144
- async post(path32, body2) {
7145
- const res = await fetch(`${this.baseUrl}${path32}`, {
7839
+ async post(path42, body2) {
7840
+ const res = await fetch(`${this.baseUrl}${path42}`, {
7146
7841
  method: "POST",
7147
7842
  headers: {
7148
7843
  Authorization: `Bearer ${this.config.apiKey}`,
@@ -7153,7 +7848,7 @@ var PostHogApi = class {
7153
7848
  });
7154
7849
  if (!res.ok) {
7155
7850
  throw new Error(
7156
- `PostHog API error: ${res.status} ${res.statusText} on POST ${path32}`
7851
+ `PostHog API error: ${res.status} ${res.statusText} on POST ${path42}`
7157
7852
  );
7158
7853
  }
7159
7854
  return res.json();
@@ -7171,11 +7866,11 @@ var PostHogApi = class {
7171
7866
  return data.results;
7172
7867
  }
7173
7868
  async getEventDefinitions(names) {
7174
- let path32 = "/event_definitions/?limit=500";
7869
+ let path42 = "/event_definitions/?limit=500";
7175
7870
  if (names && names.length > 0) {
7176
- path32 += `&search=${encodeURIComponent(names.join(","))}`;
7871
+ path42 += `&search=${encodeURIComponent(names.join(","))}`;
7177
7872
  }
7178
- const data = await this.get(path32);
7873
+ const data = await this.get(path42);
7179
7874
  return data.results;
7180
7875
  }
7181
7876
  async getEventStats(eventNames, daysBack = 30) {
@@ -7211,6 +7906,35 @@ var PostHogApi = class {
7211
7906
  }
7212
7907
  return stats;
7213
7908
  }
7909
+ async getFlagEvaluationStats(flagKeys, daysBack = 7) {
7910
+ if (flagKeys.length === 0) {
7911
+ return /* @__PURE__ */ new Map();
7912
+ }
7913
+ const days = Math.max(1, Math.min(365, Math.floor(daysBack)));
7914
+ const query2 = `
7915
+ SELECT
7916
+ properties.$feature_flag AS flag_key,
7917
+ count() AS evaluations,
7918
+ count(DISTINCT person_id) AS unique_users
7919
+ FROM events
7920
+ WHERE event = '$feature_flag_called'
7921
+ AND properties.$feature_flag IN {flagKeys}
7922
+ AND timestamp >= now() - INTERVAL ${days} DAY
7923
+ GROUP BY flag_key
7924
+ `;
7925
+ const data = await this.post("/query/", {
7926
+ query: {
7927
+ kind: "HogQLQuery",
7928
+ query: query2,
7929
+ values: { flagKeys }
7930
+ }
7931
+ });
7932
+ const stats = /* @__PURE__ */ new Map();
7933
+ for (const [flagKey, evaluations, uniqueUsers] of data.results) {
7934
+ stats.set(flagKey, { evaluations, uniqueUsers, windowDays: days });
7935
+ }
7936
+ return stats;
7937
+ }
7214
7938
  };
7215
7939
  var CAPTURE_METHODS = /* @__PURE__ */ new Set(["capture", "Enqueue"]);
7216
7940
  var ParseResult = class {
@@ -7234,14 +7958,18 @@ var ParseResult = class {
7234
7958
  return this.calls.filter((c) => CAPTURE_METHODS.has(c.method)).map((c) => ({
7235
7959
  name: c.key,
7236
7960
  line: c.line,
7237
- dynamic: c.dynamic ?? false
7961
+ dynamic: c.dynamic ?? false,
7962
+ viaWrapper: c.viaWrapper,
7963
+ inJsx: c.inJsx
7238
7964
  }));
7239
7965
  }
7240
7966
  get flagChecks() {
7241
7967
  return this.calls.filter((c) => !CAPTURE_METHODS.has(c.method)).map((c) => ({
7242
7968
  method: c.method,
7243
7969
  flagKey: c.key,
7244
- line: c.line
7970
+ line: c.line,
7971
+ viaWrapper: c.viaWrapper,
7972
+ inJsx: c.inJsx
7245
7973
  }));
7246
7974
  }
7247
7975
  get flagKeys() {
@@ -7269,7 +7997,9 @@ var ParseResult = class {
7269
7997
  line: call.line,
7270
7998
  name: call.key,
7271
7999
  method: call.method,
7272
- detail: call.dynamic ? "dynamic event name" : void 0
8000
+ detail: call.dynamic ? "dynamic event name" : void 0,
8001
+ viaWrapper: call.viaWrapper,
8002
+ inJsx: call.inJsx
7273
8003
  });
7274
8004
  }
7275
8005
  return items.sort((a, b) => a.line - b.line);
@@ -7282,14 +8012,22 @@ var ParseResult = class {
7282
8012
  flagKeys.length > 0 ? api.getFeatureFlags() : Promise.resolve([]),
7283
8013
  flagKeys.length > 0 ? api.getExperiments() : Promise.resolve([]),
7284
8014
  eventNames.length > 0 ? api.getEventDefinitions(eventNames) : Promise.resolve([]),
7285
- eventNames.length > 0 ? api.getEventStats(eventNames) : Promise.resolve(/* @__PURE__ */ new Map())
8015
+ eventNames.length > 0 ? api.getEventStats(eventNames) : Promise.resolve(/* @__PURE__ */ new Map()),
8016
+ flagKeys.length > 0 ? api.getFlagEvaluationStats(flagKeys, 7) : Promise.resolve(/* @__PURE__ */ new Map())
7286
8017
  ]);
7287
- const [flagsResult, experimentsResult, eventDefsResult, eventStatsResult] = settled;
8018
+ const [
8019
+ flagsResult,
8020
+ experimentsResult,
8021
+ eventDefsResult,
8022
+ eventStatsResult,
8023
+ flagEvalStatsResult
8024
+ ] = settled;
7288
8025
  const labels = [
7289
8026
  "getFeatureFlags",
7290
8027
  "getExperiments",
7291
8028
  "getEventDefinitions",
7292
- "getEventStats"
8029
+ "getEventStats",
8030
+ "getFlagEvaluationStats"
7293
8031
  ];
7294
8032
  settled.forEach((r, i2) => {
7295
8033
  if (r.status === "rejected") {
@@ -7300,6 +8038,8 @@ var ParseResult = class {
7300
8038
  const allExperiments = experimentsResult.status === "fulfilled" ? experimentsResult.value : [];
7301
8039
  const allEventDefs = eventDefsResult.status === "fulfilled" ? eventDefsResult.value : [];
7302
8040
  const eventStats = eventStatsResult.status === "fulfilled" ? eventStatsResult.value : /* @__PURE__ */ new Map();
8041
+ const flagEvaluationStats = flagEvalStatsResult.status === "fulfilled" ? flagEvalStatsResult.value : /* @__PURE__ */ new Map();
8042
+ const flagEvaluationStatsError = flagEvalStatsResult.status === "rejected";
7303
8043
  const flagKeySet = new Set(flagKeys);
7304
8044
  const flags2 = new Map(
7305
8045
  allFlags.filter((f) => flagKeySet.has(f.key)).map((f) => [f.key, f])
@@ -7310,18 +8050,34 @@ var ParseResult = class {
7310
8050
  const eventDefinitions = new Map(
7311
8051
  allEventDefs.filter((d) => eventNames.includes(d.name)).map((d) => [d.name, d])
7312
8052
  );
8053
+ const host = config.host.replace(/\/$/, "");
8054
+ const flagUrls = /* @__PURE__ */ new Map();
8055
+ for (const [key, flag] of flags2) {
8056
+ flagUrls.set(
8057
+ key,
8058
+ `${host}/project/${config.projectId}/feature_flags/${flag.id}`
8059
+ );
8060
+ }
7313
8061
  return new EnrichedResult(this, {
7314
8062
  flags: flags2,
7315
8063
  experiments,
7316
8064
  eventDefinitions,
7317
- eventStats
8065
+ eventStats,
8066
+ flagEvaluationStats,
8067
+ flagEvaluationStatsError,
8068
+ flagUrls
7318
8069
  });
7319
8070
  }
7320
8071
  };
8072
+ var MAX_WRAPPER_SOURCE_BYTES = 1e6;
8073
+ var WRAPPER_CACHE_MAX = 1024;
8074
+ var POSTHOG_LITERAL_REGEX = /posthog/i;
7321
8075
  var PostHogEnricher = class {
7322
8076
  detector = new PostHogDetector();
8077
+ wrapperCache = /* @__PURE__ */ new Map();
7323
8078
  updateConfig(config) {
7324
8079
  this.detector.updateConfig(config);
8080
+ this.wrapperCache.clear();
7325
8081
  }
7326
8082
  isSupported(langId) {
7327
8083
  return this.detector.isSupported(langId);
@@ -7329,9 +8085,9 @@ var PostHogEnricher = class {
7329
8085
  get supportedLanguages() {
7330
8086
  return this.detector.supportedLanguages;
7331
8087
  }
7332
- async parse(source, languageId) {
8088
+ async parse(source, languageId, context) {
7333
8089
  const results = await Promise.allSettled([
7334
- this.detector.findPostHogCalls(source, languageId),
8090
+ this.detector.findPostHogCalls(source, languageId, context),
7335
8091
  this.detector.findInitCalls(source, languageId),
7336
8092
  this.detector.findFlagAssignments(source, languageId),
7337
8093
  this.detector.findVariantBranches(source, languageId),
@@ -7362,7 +8118,7 @@ var PostHogEnricher = class {
7362
8118
  );
7363
8119
  }
7364
8120
  async parseFile(filePath) {
7365
- const ext = path2.extname(filePath).toLowerCase();
8121
+ const ext = path3.extname(filePath).toLowerCase();
7366
8122
  const languageId = EXT_TO_LANG_ID[ext];
7367
8123
  if (!languageId) {
7368
8124
  throw new Error(`Unsupported file extension: ${ext}`);
@@ -7370,8 +8126,70 @@ var PostHogEnricher = class {
7370
8126
  const source = await fs2.readFile(filePath, "utf-8");
7371
8127
  return this.parse(source, languageId);
7372
8128
  }
8129
+ /**
8130
+ * Parse a file for wrapper definitions (functions that directly call PostHog SDK methods).
8131
+ * Results are cached per absolute path + mtime so subsequent calls within the same session
8132
+ * are cheap. Returns [] for unsupported extensions, unreadable files, or files larger than
8133
+ * `MAX_WRAPPER_SOURCE_BYTES`.
8134
+ */
8135
+ async getWrappersForFile(absPath) {
8136
+ const ext = path3.extname(absPath).toLowerCase();
8137
+ const languageId = EXT_TO_LANG_ID[ext];
8138
+ if (!languageId || !this.isSupported(languageId)) {
8139
+ return this.setWrapperCache(absPath, 0, []);
8140
+ }
8141
+ let mtimeMs = 0;
8142
+ try {
8143
+ const stat2 = await fs2.stat(absPath);
8144
+ mtimeMs = stat2.mtimeMs;
8145
+ if (stat2.size > MAX_WRAPPER_SOURCE_BYTES) {
8146
+ return this.setWrapperCache(absPath, mtimeMs, []);
8147
+ }
8148
+ } catch {
8149
+ return this.setWrapperCache(absPath, 0, []);
8150
+ }
8151
+ const cached = this.wrapperCache.get(absPath);
8152
+ if (cached && cached.mtimeMs === mtimeMs) {
8153
+ this.touchCache(absPath);
8154
+ return cached.wrappers;
8155
+ }
8156
+ let source;
8157
+ try {
8158
+ source = await fs2.readFile(absPath, "utf-8");
8159
+ } catch {
8160
+ return this.setWrapperCache(absPath, mtimeMs, []);
8161
+ }
8162
+ if (!POSTHOG_LITERAL_REGEX.test(source)) {
8163
+ return this.setWrapperCache(absPath, mtimeMs, []);
8164
+ }
8165
+ const wrappers = await this.detector.findWrappers(source, languageId);
8166
+ return this.setWrapperCache(absPath, mtimeMs, wrappers);
8167
+ }
8168
+ async findImportsInSource(source, languageId, callerAbsPath) {
8169
+ return this.detector.findImports(source, languageId, callerAbsPath);
8170
+ }
8171
+ clearWrapperCache() {
8172
+ this.wrapperCache.clear();
8173
+ }
7373
8174
  dispose() {
7374
8175
  this.detector.dispose();
8176
+ this.wrapperCache.clear();
8177
+ }
8178
+ setWrapperCache(absPath, mtimeMs, wrappers) {
8179
+ if (this.wrapperCache.size >= WRAPPER_CACHE_MAX) {
8180
+ const oldest = this.wrapperCache.keys().next().value;
8181
+ if (oldest !== void 0) {
8182
+ this.wrapperCache.delete(oldest);
8183
+ }
8184
+ }
8185
+ this.wrapperCache.set(absPath, { mtimeMs, wrappers });
8186
+ return wrappers;
8187
+ }
8188
+ touchCache(absPath) {
8189
+ const entry = this.wrapperCache.get(absPath);
8190
+ if (!entry) return;
8191
+ this.wrapperCache.delete(absPath);
8192
+ this.wrapperCache.set(absPath, entry);
7375
8193
  }
7376
8194
  };
7377
8195
 
@@ -7385,14 +8203,25 @@ function createEnrichment(apiConfig, logger) {
7385
8203
  };
7386
8204
  }
7387
8205
  var MAX_ENRICHMENT_BYTES = 1e6;
8206
+ var MAX_RELATIVE_IMPORTS = 64;
8207
+ var RELATIVE_IMPORT_REGEX = /(?:^|\n)\s*(?:import\b[^\n]*['"]\.{1,2}\/|from\s+\.)/;
8208
+ var POSTHOG_LITERAL_REGEX2 = /posthog/i;
7388
8209
  async function enrichFileForAgent(deps, filePath, content) {
7389
8210
  if (!content || content.length > MAX_ENRICHMENT_BYTES) return null;
7390
- if (!/posthog/i.test(content)) return null;
7391
- const ext = path3.extname(filePath).toLowerCase();
8211
+ const ext = path4.extname(filePath).toLowerCase();
7392
8212
  const langId = EXT_TO_LANG_ID[ext];
7393
8213
  if (!langId || !deps.enricher.isSupported(langId)) return null;
8214
+ const hasPostHogLiteral = POSTHOG_LITERAL_REGEX2.test(content);
8215
+ const hasRelativeImport = RELATIVE_IMPORT_REGEX.test(content);
8216
+ let parseContext;
8217
+ if (hasRelativeImport) {
8218
+ const absPath = path4.resolve(filePath);
8219
+ const ctx = await buildWrapperContext(deps, content, langId, absPath);
8220
+ if (ctx) parseContext = ctx;
8221
+ }
8222
+ if (!hasPostHogLiteral && !parseContext) return null;
7394
8223
  try {
7395
- const parsed = await deps.enricher.parse(content, langId);
8224
+ const parsed = await deps.enricher.parse(content, langId, parseContext);
7396
8225
  if (parsed.calls.length === 0 && parsed.initCalls.length === 0) {
7397
8226
  return null;
7398
8227
  }
@@ -7414,7 +8243,8 @@ async function enrichFileForAgent(deps, filePath, content) {
7414
8243
  }
7415
8244
  deps.logger?.debug("File enriched", {
7416
8245
  filePath,
7417
- calls: parsed.calls.length
8246
+ calls: parsed.calls.length,
8247
+ viaWrappers: parsed.calls.filter((c) => c.viaWrapper).length
7418
8248
  });
7419
8249
  return annotated;
7420
8250
  } catch (err2) {
@@ -7423,11 +8253,62 @@ async function enrichFileForAgent(deps, filePath, content) {
7423
8253
  return null;
7424
8254
  }
7425
8255
  }
8256
+ async function buildWrapperContext(deps, content, langId, absPath) {
8257
+ let edges;
8258
+ try {
8259
+ edges = await deps.enricher.findImportsInSource(content, langId, absPath);
8260
+ } catch (err2) {
8261
+ deps.logger?.debug("Import resolution failed", {
8262
+ absPath,
8263
+ err: err2 instanceof Error ? err2.message : String(err2)
8264
+ });
8265
+ return null;
8266
+ }
8267
+ if (!edges.length) return null;
8268
+ const bounded = edges.slice(0, MAX_RELATIVE_IMPORTS);
8269
+ const wrappersByLocalName = /* @__PURE__ */ new Map();
8270
+ const namespaceWrappers = /* @__PURE__ */ new Map();
8271
+ const resolutions = await Promise.all(
8272
+ bounded.map(async (edge) => {
8273
+ if (!edge.resolvedAbsPath) return null;
8274
+ const wrappers = await deps.enricher.getWrappersForFile(
8275
+ edge.resolvedAbsPath
8276
+ );
8277
+ if (!wrappers.length) return null;
8278
+ return { edge, wrappers };
8279
+ })
8280
+ );
8281
+ for (const entry of resolutions) {
8282
+ if (!entry) continue;
8283
+ const { edge, wrappers } = entry;
8284
+ if (edge.isNamespace) {
8285
+ const nsMap = /* @__PURE__ */ new Map();
8286
+ for (const w of wrappers) {
8287
+ if (w.isNamedExport || w.isDefaultExport) {
8288
+ nsMap.set(w.name, w);
8289
+ }
8290
+ }
8291
+ if (nsMap.size) namespaceWrappers.set(edge.localName, nsMap);
8292
+ continue;
8293
+ }
8294
+ if (edge.isDefault) {
8295
+ const target2 = wrappers.find((w) => w.isDefaultExport);
8296
+ if (target2) wrappersByLocalName.set(edge.localName, target2);
8297
+ continue;
8298
+ }
8299
+ const target = wrappers.find(
8300
+ (w) => w.name === edge.importedName && w.isNamedExport
8301
+ );
8302
+ if (target) wrappersByLocalName.set(edge.localName, target);
8303
+ }
8304
+ if (!wrappersByLocalName.size && !namespaceWrappers.size) return null;
8305
+ return { wrappersByLocalName, namespaceWrappers };
8306
+ }
7426
8307
 
7427
8308
  // src/utils/common.ts
7428
8309
  async function withTimeout(operation, timeoutMs) {
7429
8310
  const timeoutPromise = new Promise(
7430
- (resolve4) => setTimeout(() => resolve4({ result: "timeout" }), timeoutMs)
8311
+ (resolve6) => setTimeout(() => resolve6({ result: "timeout" }), timeoutMs)
7431
8312
  );
7432
8313
  const operationPromise = operation.then((value) => ({
7433
8314
  result: "success",
@@ -7627,7 +8508,7 @@ var BaseAcpAgent = class {
7627
8508
  };
7628
8509
 
7629
8510
  // src/adapters/claude/conversion/acp-to-sdk.ts
7630
- import * as path4 from "path";
8511
+ import * as path5 from "path";
7631
8512
  import { fileURLToPath as fileURLToPath2 } from "url";
7632
8513
  function sdkText(value) {
7633
8514
  return { type: "text", text: value };
@@ -7635,7 +8516,7 @@ function sdkText(value) {
7635
8516
  function formatUriAsLink(uri) {
7636
8517
  try {
7637
8518
  if (uri.startsWith("zed://")) {
7638
- const name2 = path4.basename(uri) || uri;
8519
+ const name2 = path5.basename(uri) || uri;
7639
8520
  return `[@${name2}](${uri})`;
7640
8521
  }
7641
8522
  return uri;
@@ -7646,7 +8527,7 @@ function formatUriAsLink(uri) {
7646
8527
  function formatFileAttachment(uri) {
7647
8528
  try {
7648
8529
  const filePath = fileURLToPath2(uri);
7649
- const name2 = path4.basename(filePath) || filePath;
8530
+ const name2 = path5.basename(filePath) || filePath;
7650
8531
  return [
7651
8532
  "Attached file available in the workspace:",
7652
8533
  `- name: ${name2}`,
@@ -7758,8 +8639,8 @@ var ToolContentBuilder = class {
7758
8639
  this.items.push({ type: "content", content: image(data, mimeType, uri) });
7759
8640
  return this;
7760
8641
  }
7761
- diff(path14, oldText, newText) {
7762
- this.items.push({ type: "diff", path: path14, oldText, newText });
8642
+ diff(path15, oldText, newText) {
8643
+ this.items.push({ type: "diff", path: path15, oldText, newText });
7763
8644
  return this;
7764
8645
  }
7765
8646
  build() {
@@ -7936,7 +8817,7 @@ var createPreToolUseHook = (settingsManager, logger) => async (input, _toolUseID
7936
8817
 
7937
8818
  // src/adapters/claude/conversion/tool-use-to-acp.ts
7938
8819
  import fs3 from "fs";
7939
- import path5 from "path";
8820
+ import path6 from "path";
7940
8821
 
7941
8822
  // src/adapters/claude/mcp/tool-metadata.ts
7942
8823
  var mcpToolMetadataCache = /* @__PURE__ */ new Map();
@@ -7946,7 +8827,7 @@ function buildToolKey(serverName, toolName) {
7946
8827
  return `mcp__${serverName}__${toolName}`;
7947
8828
  }
7948
8829
  function delay(ms) {
7949
- return new Promise((resolve4) => setTimeout(resolve4, ms));
8830
+ return new Promise((resolve6) => setTimeout(resolve6, ms));
7950
8831
  }
7951
8832
  async function fetchMcpToolMetadata(q, logger = new Logger({ debug: false, prefix: "[McpToolMetadata]" })) {
7952
8833
  let retries = 0;
@@ -8022,10 +8903,10 @@ function stripSystemReminders(value) {
8022
8903
  }
8023
8904
  function toDisplayPath(filePath, cwd) {
8024
8905
  if (!cwd) return filePath;
8025
- const resolvedCwd = path5.resolve(cwd);
8026
- const resolvedFile = path5.resolve(filePath);
8027
- if (resolvedFile.startsWith(resolvedCwd + path5.sep) || resolvedFile === resolvedCwd) {
8028
- return path5.relative(resolvedCwd, resolvedFile);
8906
+ const resolvedCwd = path6.resolve(cwd);
8907
+ const resolvedFile = path6.resolve(filePath);
8908
+ if (resolvedFile.startsWith(resolvedCwd + path6.sep) || resolvedFile === resolvedCwd) {
8909
+ return path6.relative(resolvedCwd, resolvedFile);
8029
8910
  }
8030
8911
  return filePath;
8031
8912
  }
@@ -9165,18 +10046,18 @@ async function handleUserAssistantMessage(message, context) {
9165
10046
 
9166
10047
  // src/adapters/claude/plan/utils.ts
9167
10048
  import * as os from "os";
9168
- import * as path6 from "path";
10049
+ import * as path7 from "path";
9169
10050
  function getClaudeConfigDir() {
9170
- return process.env.CLAUDE_CONFIG_DIR || path6.join(os.homedir(), ".claude");
10051
+ return process.env.CLAUDE_CONFIG_DIR || path7.join(os.homedir(), ".claude");
9171
10052
  }
9172
10053
  function getClaudePlansDir() {
9173
- return path6.join(getClaudeConfigDir(), "plans");
10054
+ return path7.join(getClaudeConfigDir(), "plans");
9174
10055
  }
9175
10056
  function isClaudePlanFilePath(filePath) {
9176
10057
  if (!filePath) return false;
9177
- const resolved = path6.resolve(filePath);
9178
- const plansDir = path6.resolve(getClaudePlansDir());
9179
- return resolved === plansDir || resolved.startsWith(plansDir + path6.sep);
10058
+ const resolved = path7.resolve(filePath);
10059
+ const plansDir = path7.resolve(getClaudePlansDir());
10060
+ return resolved === plansDir || resolved.startsWith(plansDir + path7.sep);
9180
10061
  }
9181
10062
  function isPlanReady(plan) {
9182
10063
  if (!plan) return false;
@@ -9972,7 +10853,7 @@ function resolveModelPreference(preference, options) {
9972
10853
  import { spawn } from "child_process";
9973
10854
  import * as fs4 from "fs";
9974
10855
  import * as os2 from "os";
9975
- import * as path7 from "path";
10856
+ import * as path8 from "path";
9976
10857
 
9977
10858
  // src/adapters/claude/session/instructions.ts
9978
10859
  var BRANCH_NAMING = `
@@ -10164,8 +11045,8 @@ function buildSpawnWrapper(sessionId, onProcessSpawned, onProcessExited, logger)
10164
11045
  };
10165
11046
  }
10166
11047
  function ensureLocalSettings(cwd) {
10167
- const claudeDir = path7.join(cwd, ".claude");
10168
- const localSettingsPath = path7.join(claudeDir, "settings.local.json");
11048
+ const claudeDir = path8.join(cwd, ".claude");
11049
+ const localSettingsPath = path8.join(claudeDir, "settings.local.json");
10169
11050
  try {
10170
11051
  if (!fs4.existsSync(localSettingsPath)) {
10171
11052
  fs4.mkdirSync(claudeDir, { recursive: true });
@@ -10244,8 +11125,8 @@ function buildSessionOptions(params) {
10244
11125
  return options;
10245
11126
  }
10246
11127
  function clearStatsigCache() {
10247
- const statsigPath = path7.join(
10248
- process.env.CLAUDE_CONFIG_DIR || path7.join(os2.homedir(), ".claude"),
11128
+ const statsigPath = path8.join(
11129
+ process.env.CLAUDE_CONFIG_DIR || path8.join(os2.homedir(), ".claude"),
10249
11130
  "statsig"
10250
11131
  );
10251
11132
  fs4.rm(statsigPath, { recursive: true, force: true }, () => {
@@ -10255,7 +11136,7 @@ function clearStatsigCache() {
10255
11136
  // src/adapters/claude/session/settings.ts
10256
11137
  import * as fs7 from "fs";
10257
11138
  import * as os3 from "os";
10258
- import * as path10 from "path";
11139
+ import * as path11 from "path";
10259
11140
  import { minimatch } from "minimatch";
10260
11141
 
10261
11142
  // src/utils/async-mutex.ts
@@ -10267,8 +11148,8 @@ var AsyncMutex = class {
10267
11148
  this.locked = true;
10268
11149
  return;
10269
11150
  }
10270
- return new Promise((resolve4) => {
10271
- this.queue.push(resolve4);
11151
+ return new Promise((resolve6) => {
11152
+ this.queue.push(resolve6);
10272
11153
  });
10273
11154
  }
10274
11155
  release() {
@@ -10289,7 +11170,7 @@ var AsyncMutex = class {
10289
11170
 
10290
11171
  // ../git/dist/queries.js
10291
11172
  import * as fs6 from "fs/promises";
10292
- import * as path9 from "path";
11173
+ import * as path10 from "path";
10293
11174
 
10294
11175
  // ../../node_modules/simple-git/dist/esm/index.js
10295
11176
  var import_file_exists = __toESM(require_dist(), 1);
@@ -10328,8 +11209,8 @@ function pathspec(...paths) {
10328
11209
  cache.set(key, paths);
10329
11210
  return key;
10330
11211
  }
10331
- function isPathSpec(path14) {
10332
- return path14 instanceof String && cache.has(path14);
11212
+ function isPathSpec(path15) {
11213
+ return path15 instanceof String && cache.has(path15);
10333
11214
  }
10334
11215
  function toPaths(pathSpec) {
10335
11216
  return cache.get(pathSpec) || [];
@@ -10418,8 +11299,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
10418
11299
  function forEachLineWithContent(input, callback) {
10419
11300
  return toLinesWithContent(input, true).map((line) => callback(line));
10420
11301
  }
10421
- function folderExists(path14) {
10422
- return (0, import_file_exists.exists)(path14, import_file_exists.FOLDER);
11302
+ function folderExists(path15) {
11303
+ return (0, import_file_exists.exists)(path15, import_file_exists.FOLDER);
10423
11304
  }
10424
11305
  function append(target, item) {
10425
11306
  if (Array.isArray(target)) {
@@ -10823,8 +11704,8 @@ function checkIsRepoRootTask() {
10823
11704
  commands,
10824
11705
  format: "utf-8",
10825
11706
  onError,
10826
- parser(path14) {
10827
- return /^\.(git)?$/.test(path14.trim());
11707
+ parser(path15) {
11708
+ return /^\.(git)?$/.test(path15.trim());
10828
11709
  }
10829
11710
  };
10830
11711
  }
@@ -11258,11 +12139,11 @@ function parseGrep(grep) {
11258
12139
  const paths = /* @__PURE__ */ new Set();
11259
12140
  const results = {};
11260
12141
  forEachLineWithContent(grep, (input) => {
11261
- const [path14, line, preview] = input.split(NULL);
11262
- paths.add(path14);
11263
- (results[path14] = results[path14] || []).push({
12142
+ const [path15, line, preview] = input.split(NULL);
12143
+ paths.add(path15);
12144
+ (results[path15] = results[path15] || []).push({
11264
12145
  line: asNumber(line),
11265
- path: path14,
12146
+ path: path15,
11266
12147
  preview
11267
12148
  });
11268
12149
  });
@@ -12027,14 +12908,14 @@ var init_hash_object = __esm({
12027
12908
  init_task();
12028
12909
  }
12029
12910
  });
12030
- function parseInit(bare, path14, text2) {
12911
+ function parseInit(bare, path15, text2) {
12031
12912
  const response = String(text2).trim();
12032
12913
  let result;
12033
12914
  if (result = initResponseRegex.exec(response)) {
12034
- return new InitSummary(bare, path14, false, result[1]);
12915
+ return new InitSummary(bare, path15, false, result[1]);
12035
12916
  }
12036
12917
  if (result = reInitResponseRegex.exec(response)) {
12037
- return new InitSummary(bare, path14, true, result[1]);
12918
+ return new InitSummary(bare, path15, true, result[1]);
12038
12919
  }
12039
12920
  let gitDir = "";
12040
12921
  const tokens = response.split(" ");
@@ -12045,7 +12926,7 @@ function parseInit(bare, path14, text2) {
12045
12926
  break;
12046
12927
  }
12047
12928
  }
12048
- return new InitSummary(bare, path14, /^re/i.test(response), gitDir);
12929
+ return new InitSummary(bare, path15, /^re/i.test(response), gitDir);
12049
12930
  }
12050
12931
  var InitSummary;
12051
12932
  var initResponseRegex;
@@ -12054,9 +12935,9 @@ var init_InitSummary = __esm({
12054
12935
  "src/lib/responses/InitSummary.ts"() {
12055
12936
  "use strict";
12056
12937
  InitSummary = class {
12057
- constructor(bare, path14, existing, gitDir) {
12938
+ constructor(bare, path15, existing, gitDir) {
12058
12939
  this.bare = bare;
12059
- this.path = path14;
12940
+ this.path = path15;
12060
12941
  this.existing = existing;
12061
12942
  this.gitDir = gitDir;
12062
12943
  }
@@ -12068,7 +12949,7 @@ var init_InitSummary = __esm({
12068
12949
  function hasBareCommand(command) {
12069
12950
  return command.includes(bareCommand);
12070
12951
  }
12071
- function initTask(bare = false, path14, customArgs) {
12952
+ function initTask(bare = false, path15, customArgs) {
12072
12953
  const commands = ["init", ...customArgs];
12073
12954
  if (bare && !hasBareCommand(commands)) {
12074
12955
  commands.splice(1, 0, bareCommand);
@@ -12077,7 +12958,7 @@ function initTask(bare = false, path14, customArgs) {
12077
12958
  commands,
12078
12959
  format: "utf-8",
12079
12960
  parser(text2) {
12080
- return parseInit(commands.includes("--bare"), path14, text2);
12961
+ return parseInit(commands.includes("--bare"), path15, text2);
12081
12962
  }
12082
12963
  };
12083
12964
  }
@@ -12893,12 +13774,12 @@ var init_FileStatusSummary = __esm({
12893
13774
  "use strict";
12894
13775
  fromPathRegex = /^(.+)\0(.+)$/;
12895
13776
  FileStatusSummary = class {
12896
- constructor(path14, index, working_dir) {
12897
- this.path = path14;
13777
+ constructor(path15, index, working_dir) {
13778
+ this.path = path15;
12898
13779
  this.index = index;
12899
13780
  this.working_dir = working_dir;
12900
13781
  if (index === "R" || working_dir === "R") {
12901
- const detail = fromPathRegex.exec(path14) || [null, path14, path14];
13782
+ const detail = fromPathRegex.exec(path15) || [null, path15, path15];
12902
13783
  this.from = detail[2] || "";
12903
13784
  this.path = detail[1] || "";
12904
13785
  }
@@ -12929,14 +13810,14 @@ function splitLine(result, lineStr) {
12929
13810
  default:
12930
13811
  return;
12931
13812
  }
12932
- function data(index, workingDir, path14) {
13813
+ function data(index, workingDir, path15) {
12933
13814
  const raw = `${index}${workingDir}`;
12934
13815
  const handler = parsers6.get(raw);
12935
13816
  if (handler) {
12936
- handler(result, path14);
13817
+ handler(result, path15);
12937
13818
  }
12938
13819
  if (raw !== "##" && raw !== "!!") {
12939
- result.files.push(new FileStatusSummary(path14, index, workingDir));
13820
+ result.files.push(new FileStatusSummary(path15, index, workingDir));
12940
13821
  }
12941
13822
  }
12942
13823
  }
@@ -13249,9 +14130,9 @@ var init_simple_git_api = __esm({
13249
14130
  next
13250
14131
  );
13251
14132
  }
13252
- hashObject(path14, write) {
14133
+ hashObject(path15, write) {
13253
14134
  return this._runTask(
13254
- hashObjectTask(path14, write === true),
14135
+ hashObjectTask(path15, write === true),
13255
14136
  trailingFunctionArgument(arguments)
13256
14137
  );
13257
14138
  }
@@ -13604,8 +14485,8 @@ var init_branch = __esm({
13604
14485
  }
13605
14486
  });
13606
14487
  function toPath(input) {
13607
- const path14 = input.trim().replace(/^["']|["']$/g, "");
13608
- return path14 && normalize(path14);
14488
+ const path15 = input.trim().replace(/^["']|["']$/g, "");
14489
+ return path15 && normalize(path15);
13609
14490
  }
13610
14491
  var parseCheckIgnore;
13611
14492
  var init_CheckIgnore = __esm({
@@ -13919,8 +14800,8 @@ __export(sub_module_exports, {
13919
14800
  subModuleTask: () => subModuleTask,
13920
14801
  updateSubModuleTask: () => updateSubModuleTask
13921
14802
  });
13922
- function addSubModuleTask(repo, path14) {
13923
- return subModuleTask(["add", repo, path14]);
14803
+ function addSubModuleTask(repo, path15) {
14804
+ return subModuleTask(["add", repo, path15]);
13924
14805
  }
13925
14806
  function initSubModuleTask(customArgs) {
13926
14807
  return subModuleTask(["init", ...customArgs]);
@@ -14250,8 +15131,8 @@ var require_git = __commonJS2({
14250
15131
  }
14251
15132
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
14252
15133
  };
14253
- Git2.prototype.submoduleAdd = function(repo, path14, then) {
14254
- return this._runTask(addSubModuleTask2(repo, path14), trailingFunctionArgument2(arguments));
15134
+ Git2.prototype.submoduleAdd = function(repo, path15, then) {
15135
+ return this._runTask(addSubModuleTask2(repo, path15), trailingFunctionArgument2(arguments));
14255
15136
  };
14256
15137
  Git2.prototype.submoduleUpdate = function(args2, then) {
14257
15138
  return this._runTask(
@@ -14853,24 +15734,24 @@ function createGitClient(baseDir, options) {
14853
15734
  // ../git/dist/lock-detector.js
14854
15735
  import { execFile } from "child_process";
14855
15736
  import fs5 from "fs/promises";
14856
- import path8 from "path";
15737
+ import path9 from "path";
14857
15738
  import { promisify } from "util";
14858
15739
  var execFileAsync = promisify(execFile);
14859
15740
  async function getIndexLockPath(repoPath) {
14860
15741
  try {
14861
15742
  const { stdout } = await execFileAsync("git", ["rev-parse", "--git-path", "index.lock"], { cwd: repoPath });
14862
- return path8.resolve(repoPath, stdout.trim());
15743
+ return path9.resolve(repoPath, stdout.trim());
14863
15744
  } catch {
14864
- return path8.join(repoPath, ".git", "index.lock");
15745
+ return path9.join(repoPath, ".git", "index.lock");
14865
15746
  }
14866
15747
  }
14867
15748
  async function getLockInfo(repoPath) {
14868
15749
  const lockPath = await getIndexLockPath(repoPath);
14869
15750
  try {
14870
- const stat = await fs5.stat(lockPath);
15751
+ const stat2 = await fs5.stat(lockPath);
14871
15752
  return {
14872
15753
  path: lockPath,
14873
- ageMs: Date.now() - stat.mtimeMs
15754
+ ageMs: Date.now() - stat2.mtimeMs
14874
15755
  };
14875
15756
  } catch {
14876
15757
  return null;
@@ -14905,10 +15786,10 @@ var AsyncReaderWriterLock = class {
14905
15786
  this.readers++;
14906
15787
  return;
14907
15788
  }
14908
- return new Promise((resolve4) => {
15789
+ return new Promise((resolve6) => {
14909
15790
  this.readQueue.push(() => {
14910
15791
  this.readers++;
14911
- resolve4();
15792
+ resolve6();
14912
15793
  });
14913
15794
  });
14914
15795
  }
@@ -14922,11 +15803,11 @@ var AsyncReaderWriterLock = class {
14922
15803
  return;
14923
15804
  }
14924
15805
  this.writerWaiting = true;
14925
- return new Promise((resolve4) => {
15806
+ return new Promise((resolve6) => {
14926
15807
  this.writeQueue.push(() => {
14927
15808
  this.writerWaiting = this.writeQueue.length > 0;
14928
15809
  this.writer = true;
14929
- resolve4();
15810
+ resolve6();
14930
15811
  });
14931
15812
  });
14932
15813
  }
@@ -15127,13 +16008,13 @@ function parseRule(rule) {
15127
16008
  function normalizePath(filePath, cwd) {
15128
16009
  let resolved = filePath;
15129
16010
  if (resolved.startsWith("~/")) {
15130
- resolved = path10.join(os3.homedir(), resolved.slice(2));
16011
+ resolved = path11.join(os3.homedir(), resolved.slice(2));
15131
16012
  } else if (resolved.startsWith("./")) {
15132
- resolved = path10.join(cwd, resolved.slice(2));
15133
- } else if (!path10.isAbsolute(resolved)) {
15134
- resolved = path10.join(cwd, resolved);
16013
+ resolved = path11.join(cwd, resolved.slice(2));
16014
+ } else if (!path11.isAbsolute(resolved)) {
16015
+ resolved = path11.join(cwd, resolved);
15135
16016
  }
15136
- return path10.normalize(resolved).replace(/\\/g, "/");
16017
+ return path11.normalize(resolved).replace(/\\/g, "/");
15137
16018
  }
15138
16019
  function matchesGlob(pattern, filePath, cwd) {
15139
16020
  const normalizedPattern = normalizePath(pattern, cwd);
@@ -15254,11 +16135,11 @@ var SettingsManager = class {
15254
16135
  return this.initPromise;
15255
16136
  }
15256
16137
  getUserSettingsPath() {
15257
- const configDir = process.env.CLAUDE_CONFIG_DIR || path10.join(os3.homedir(), ".claude");
15258
- return path10.join(configDir, "settings.json");
16138
+ const configDir = process.env.CLAUDE_CONFIG_DIR || path11.join(os3.homedir(), ".claude");
16139
+ return path11.join(configDir, "settings.json");
15259
16140
  }
15260
16141
  getProjectSettingsPath() {
15261
- return path10.join(this.cwd, ".claude", "settings.json");
16142
+ return path11.join(this.cwd, ".claude", "settings.json");
15262
16143
  }
15263
16144
  /**
15264
16145
  * Local settings are anchored to the primary worktree so every worktree of
@@ -15266,7 +16147,7 @@ var SettingsManager = class {
15266
16147
  * avoids re-prompting for the same permission in every worktree.
15267
16148
  */
15268
16149
  getLocalSettingsPath() {
15269
- return path10.join(this.repoRoot, ".claude", "settings.local.json");
16150
+ return path11.join(this.repoRoot, ".claude", "settings.local.json");
15270
16151
  }
15271
16152
  async loadAllSettings() {
15272
16153
  this.repoRoot = await resolveMainRepoPath(this.cwd);
@@ -15384,7 +16265,7 @@ var SettingsManager = class {
15384
16265
  }
15385
16266
  permissions.allow = Array.from(current2);
15386
16267
  const next = { ...existing, permissions };
15387
- await fs7.promises.mkdir(path10.dirname(filePath), { recursive: true });
16268
+ await fs7.promises.mkdir(path11.dirname(filePath), { recursive: true });
15388
16269
  await writeFileAtomic(filePath, `${JSON.stringify(next, null, 2)}
15389
16270
  `);
15390
16271
  this.localSettings = next;
@@ -15488,7 +16369,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
15488
16369
  };
15489
16370
  }
15490
16371
  async newSession(params) {
15491
- if (fs8.existsSync(path11.resolve(os4.homedir(), ".claude.json.backup")) && !fs8.existsSync(path11.resolve(os4.homedir(), ".claude.json"))) {
16372
+ if (fs8.existsSync(path12.resolve(os4.homedir(), ".claude.json.backup")) && !fs8.existsSync(path12.resolve(os4.homedir(), ".claude.json"))) {
15492
16373
  throw RequestError2.authRequired();
15493
16374
  }
15494
16375
  const response = await this.createSession(params, {
@@ -15594,8 +16475,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
15594
16475
  if (this.session.promptRunning) {
15595
16476
  this.session.input.push(userMessage);
15596
16477
  const order = this.session.nextPendingOrder++;
15597
- const cancelled = await new Promise((resolve4) => {
15598
- this.session.pendingMessages.set(promptUuid, { resolve: resolve4, order });
16478
+ const cancelled = await new Promise((resolve6) => {
16479
+ this.session.pendingMessages.set(promptUuid, { resolve: resolve6, order });
15599
16480
  });
15600
16481
  if (cancelled) {
15601
16482
  return { stopReason: "cancelled" };
@@ -16466,7 +17347,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
16466
17347
  */
16467
17348
  deferBackgroundFetches(q) {
16468
17349
  Promise.all([
16469
- new Promise((resolve4) => setTimeout(resolve4, 10)).then(
17350
+ new Promise((resolve6) => setTimeout(resolve6, 10)).then(
16470
17351
  () => this.sendAvailableCommandsUpdate()
16471
17352
  ),
16472
17353
  fetchMcpToolMetadata(q, this.logger).then(() => {
@@ -16674,7 +17555,7 @@ function resetUsage(state) {
16674
17555
  // src/adapters/codex/settings.ts
16675
17556
  import * as fs9 from "fs";
16676
17557
  import * as os5 from "os";
16677
- import * as path12 from "path";
17558
+ import * as path13 from "path";
16678
17559
  var CodexSettingsManager = class {
16679
17560
  cwd;
16680
17561
  settings = { mcpServerNames: [] };
@@ -16685,7 +17566,7 @@ var CodexSettingsManager = class {
16685
17566
  async initialize() {
16686
17567
  }
16687
17568
  getConfigPath() {
16688
- return path12.join(os5.homedir(), ".codex", "config.toml");
17569
+ return path13.join(os5.homedir(), ".codex", "config.toml");
16689
17570
  }
16690
17571
  loadSettings() {
16691
17572
  const configPath = this.getConfigPath();
@@ -16748,7 +17629,7 @@ function parseCodexToml(content, cwd) {
16748
17629
  // src/adapters/codex/spawn.ts
16749
17630
  import { spawn as spawn3 } from "child_process";
16750
17631
  import { existsSync as existsSync4 } from "fs";
16751
- import { delimiter, dirname as dirname4 } from "path";
17632
+ import { delimiter, dirname as dirname5 } from "path";
16752
17633
  function buildConfigArgs(options) {
16753
17634
  const args2 = [];
16754
17635
  args2.push("-c", `features.remote_models=false`);
@@ -16799,7 +17680,7 @@ function spawnCodexProcess(options) {
16799
17680
  }
16800
17681
  const { command, args: args2 } = findCodexBinary(options);
16801
17682
  if (options.binaryPath && existsSync4(options.binaryPath)) {
16802
- const binDir = dirname4(options.binaryPath);
17683
+ const binDir = dirname5(options.binaryPath);
16803
17684
  env.PATH = `${binDir}${delimiter}${env.PATH ?? ""}`;
16804
17685
  }
16805
17686
  logger.info("Spawning codex-acp process", {
@@ -17638,7 +18519,7 @@ var PostHogAPIClient = class {
17638
18519
  // src/session-log-writer.ts
17639
18520
  import fs10 from "fs";
17640
18521
  import fsp from "fs/promises";
17641
- import path13 from "path";
18522
+ import path14 from "path";
17642
18523
  var SessionLogWriter = class _SessionLogWriter {
17643
18524
  static FLUSH_DEBOUNCE_MS = 500;
17644
18525
  static FLUSH_MAX_INTERVAL_MS = 5e3;
@@ -17674,7 +18555,7 @@ var SessionLogWriter = class _SessionLogWriter {
17674
18555
  this.sessions.set(sessionId, { context, currentTurnMessages: [] });
17675
18556
  this.lastFlushAttemptTime.set(sessionId, Date.now());
17676
18557
  if (this.localCachePath) {
17677
- const sessionDir = path13.join(
18558
+ const sessionDir = path14.join(
17678
18559
  this.localCachePath,
17679
18560
  "sessions",
17680
18561
  context.runId
@@ -17932,7 +18813,7 @@ var SessionLogWriter = class _SessionLogWriter {
17932
18813
  if (!this.localCachePath) return;
17933
18814
  const session = this.sessions.get(sessionId);
17934
18815
  if (!session) return;
17935
- const logPath = path13.join(
18816
+ const logPath = path14.join(
17936
18817
  this.localCachePath,
17937
18818
  "sessions",
17938
18819
  session.context.runId,
@@ -17951,13 +18832,13 @@ var SessionLogWriter = class _SessionLogWriter {
17951
18832
  }
17952
18833
  }
17953
18834
  static async cleanupOldSessions(localCachePath) {
17954
- const sessionsDir = path13.join(localCachePath, "sessions");
18835
+ const sessionsDir = path14.join(localCachePath, "sessions");
17955
18836
  let deleted = 0;
17956
18837
  try {
17957
18838
  const entries = await fsp.readdir(sessionsDir);
17958
18839
  const now = Date.now();
17959
18840
  for (const entry of entries) {
17960
- const entryPath = path13.join(sessionsDir, entry);
18841
+ const entryPath = path14.join(sessionsDir, entry);
17961
18842
  try {
17962
18843
  const stats = await fsp.stat(entryPath);
17963
18844
  if (stats.isDirectory() && now - stats.birthtimeMs > _SessionLogWriter.SESSIONS_MAX_AGE_MS) {