claude-code-wakatime 3.0.4 → 3.1.0

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.
@@ -11,7 +11,7 @@
11
11
  "name": "claude-code-wakatime",
12
12
  "source": "./",
13
13
  "description": "WakaTime plugin for Claude Code - Track your AI usage, lines of code generated, and time spent prompting AI",
14
- "version": "3.0.0",
14
+ "version": "3.1.0",
15
15
  "homepage": "https://github.com/wakatime/claude-code-wakatime",
16
16
  "repository": "https://github.com/wakatime/claude-code-wakatime",
17
17
  "license": "BSD-3-Clause",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "claude-code-wakatime",
3
3
  "description": "WakaTime plugin for Claude Code - Track your AI usage, lines of code generated, and time spent prompting AI",
4
- "version": "3.0.0",
4
+ "version": "3.1.0",
5
5
  "author": {
6
6
  "name": "WakaTime"
7
7
  },
package/README.md CHANGED
@@ -18,15 +18,9 @@ Track your AI usage, lines of code generated, time spent prompting AI, etc. usin
18
18
  api_key = waka_123
19
19
  ```
20
20
 
21
- ### NPM Installation (Legacy)
21
+ ## Upgrading
22
22
 
23
- 1. `npm install -g claude-code-wakatime`
24
-
25
- 2. Add your [API key][api-key] to `~/.wakatime.cfg`:
26
- ```
27
- [settings]
28
- api_key = waka_123
29
- ```
23
+ claude plugin marketplace update
30
24
 
31
25
  ## Usage
32
26
 
package/dist/index.js CHANGED
@@ -336,7 +336,7 @@ var require_utils = __commonJS({
336
336
  module2.exports = Utils;
337
337
  Utils.prototype.makeDir = function(folder) {
338
338
  const self2 = this;
339
- function mkdirSync3(fpath) {
339
+ function mkdirSync2(fpath) {
340
340
  let resolvedPath = fpath.split(self2.sep)[0];
341
341
  fpath.split(self2.sep).forEach(function(name) {
342
342
  if (!name || name.substr(-1, 1) === ":") return;
@@ -350,27 +350,27 @@ var require_utils = __commonJS({
350
350
  if (stat && stat.isFile()) throw Errors.FILE_IN_THE_WAY(`"${resolvedPath}"`);
351
351
  });
352
352
  }
353
- mkdirSync3(folder);
353
+ mkdirSync2(folder);
354
354
  };
355
- Utils.prototype.writeFileTo = function(path5, content, overwrite, attr) {
355
+ Utils.prototype.writeFileTo = function(path4, content, overwrite, attr) {
356
356
  const self2 = this;
357
- if (self2.fs.existsSync(path5)) {
357
+ if (self2.fs.existsSync(path4)) {
358
358
  if (!overwrite) return false;
359
- var stat = self2.fs.statSync(path5);
359
+ var stat = self2.fs.statSync(path4);
360
360
  if (stat.isDirectory()) {
361
361
  return false;
362
362
  }
363
363
  }
364
- var folder = pth.dirname(path5);
364
+ var folder = pth.dirname(path4);
365
365
  if (!self2.fs.existsSync(folder)) {
366
366
  self2.makeDir(folder);
367
367
  }
368
368
  var fd;
369
369
  try {
370
- fd = self2.fs.openSync(path5, "w", 438);
370
+ fd = self2.fs.openSync(path4, "w", 438);
371
371
  } catch (e) {
372
- self2.fs.chmodSync(path5, 438);
373
- fd = self2.fs.openSync(path5, "w", 438);
372
+ self2.fs.chmodSync(path4, 438);
373
+ fd = self2.fs.openSync(path4, "w", 438);
374
374
  }
375
375
  if (fd) {
376
376
  try {
@@ -379,31 +379,31 @@ var require_utils = __commonJS({
379
379
  self2.fs.closeSync(fd);
380
380
  }
381
381
  }
382
- self2.fs.chmodSync(path5, attr || 438);
382
+ self2.fs.chmodSync(path4, attr || 438);
383
383
  return true;
384
384
  };
385
- Utils.prototype.writeFileToAsync = function(path5, content, overwrite, attr, callback) {
385
+ Utils.prototype.writeFileToAsync = function(path4, content, overwrite, attr, callback) {
386
386
  if (typeof attr === "function") {
387
387
  callback = attr;
388
388
  attr = void 0;
389
389
  }
390
390
  const self2 = this;
391
- self2.fs.exists(path5, function(exist) {
391
+ self2.fs.exists(path4, function(exist) {
392
392
  if (exist && !overwrite) return callback(false);
393
- self2.fs.stat(path5, function(err, stat) {
393
+ self2.fs.stat(path4, function(err, stat) {
394
394
  if (exist && stat.isDirectory()) {
395
395
  return callback(false);
396
396
  }
397
- var folder = pth.dirname(path5);
397
+ var folder = pth.dirname(path4);
398
398
  self2.fs.exists(folder, function(exists) {
399
399
  if (!exists) self2.makeDir(folder);
400
- self2.fs.open(path5, "w", 438, function(err2, fd) {
400
+ self2.fs.open(path4, "w", 438, function(err2, fd) {
401
401
  if (err2) {
402
- self2.fs.chmod(path5, 438, function() {
403
- self2.fs.open(path5, "w", 438, function(err3, fd2) {
402
+ self2.fs.chmod(path4, 438, function() {
403
+ self2.fs.open(path4, "w", 438, function(err3, fd2) {
404
404
  self2.fs.write(fd2, content, 0, content.length, 0, function() {
405
405
  self2.fs.close(fd2, function() {
406
- self2.fs.chmod(path5, attr || 438, function() {
406
+ self2.fs.chmod(path4, attr || 438, function() {
407
407
  callback(true);
408
408
  });
409
409
  });
@@ -413,13 +413,13 @@ var require_utils = __commonJS({
413
413
  } else if (fd) {
414
414
  self2.fs.write(fd, content, 0, content.length, 0, function() {
415
415
  self2.fs.close(fd, function() {
416
- self2.fs.chmod(path5, attr || 438, function() {
416
+ self2.fs.chmod(path4, attr || 438, function() {
417
417
  callback(true);
418
418
  });
419
419
  });
420
420
  });
421
421
  } else {
422
- self2.fs.chmod(path5, attr || 438, function() {
422
+ self2.fs.chmod(path4, attr || 438, function() {
423
423
  callback(true);
424
424
  });
425
425
  }
@@ -428,7 +428,7 @@ var require_utils = __commonJS({
428
428
  });
429
429
  });
430
430
  };
431
- Utils.prototype.findFiles = function(path5) {
431
+ Utils.prototype.findFiles = function(path4) {
432
432
  const self2 = this;
433
433
  function findSync(dir, pattern, recursive) {
434
434
  if (typeof pattern === "boolean") {
@@ -437,16 +437,16 @@ var require_utils = __commonJS({
437
437
  }
438
438
  let files = [];
439
439
  self2.fs.readdirSync(dir).forEach(function(file) {
440
- const path6 = pth.join(dir, file);
441
- const stat = self2.fs.statSync(path6);
442
- if (!pattern || pattern.test(path6)) {
443
- files.push(pth.normalize(path6) + (stat.isDirectory() ? self2.sep : ""));
440
+ const path5 = pth.join(dir, file);
441
+ const stat = self2.fs.statSync(path5);
442
+ if (!pattern || pattern.test(path5)) {
443
+ files.push(pth.normalize(path5) + (stat.isDirectory() ? self2.sep : ""));
444
444
  }
445
- if (stat.isDirectory() && recursive) files = files.concat(findSync(path6, pattern, recursive));
445
+ if (stat.isDirectory() && recursive) files = files.concat(findSync(path5, pattern, recursive));
446
446
  });
447
447
  return files;
448
448
  }
449
- return findSync(path5, void 0, true);
449
+ return findSync(path4, void 0, true);
450
450
  };
451
451
  Utils.prototype.findFilesAsync = function(dir, cb) {
452
452
  const self2 = this;
@@ -501,14 +501,14 @@ var require_utils = __commonJS({
501
501
  return "UNSUPPORTED (" + method + ")";
502
502
  }
503
503
  };
504
- Utils.canonical = function(path5) {
505
- if (!path5) return "";
506
- const safeSuffix = pth.posix.normalize("/" + path5.split("\\").join("/"));
504
+ Utils.canonical = function(path4) {
505
+ if (!path4) return "";
506
+ const safeSuffix = pth.posix.normalize("/" + path4.split("\\").join("/"));
507
507
  return pth.join(".", safeSuffix);
508
508
  };
509
- Utils.zipnamefix = function(path5) {
510
- if (!path5) return "";
511
- const safeSuffix = pth.posix.normalize("/" + path5.split("\\").join("/"));
509
+ Utils.zipnamefix = function(path4) {
510
+ if (!path4) return "";
511
+ const safeSuffix = pth.posix.normalize("/" + path4.split("\\").join("/"));
512
512
  return pth.posix.join(".", safeSuffix);
513
513
  };
514
514
  Utils.findLast = function(arr, callback) {
@@ -525,9 +525,9 @@ var require_utils = __commonJS({
525
525
  prefix = pth.resolve(pth.normalize(prefix));
526
526
  var parts = name.split("/");
527
527
  for (var i = 0, l = parts.length; i < l; i++) {
528
- var path5 = pth.normalize(pth.join(prefix, parts.slice(i, l).join(pth.sep)));
529
- if (path5.indexOf(prefix) === 0) {
530
- return path5;
528
+ var path4 = pth.normalize(pth.join(prefix, parts.slice(i, l).join(pth.sep)));
529
+ if (path4.indexOf(prefix) === 0) {
530
+ return path4;
531
531
  }
532
532
  }
533
533
  return pth.normalize(pth.join(prefix, pth.basename(name)));
@@ -567,8 +567,8 @@ var require_utils = __commonJS({
567
567
  var require_fattr = __commonJS({
568
568
  "node_modules/adm-zip/util/fattr.js"(exports2, module2) {
569
569
  var pth = require("path");
570
- module2.exports = function(path5, { fs: fs5 }) {
571
- var _path = path5 || "", _obj = newAttr(), _stat = null;
570
+ module2.exports = function(path4, { fs: fs5 }) {
571
+ var _path = path4 || "", _obj = newAttr(), _stat = null;
572
572
  function newAttr() {
573
573
  return {
574
574
  directory: false,
@@ -2960,10 +2960,10 @@ var require_store = __commonJS({
2960
2960
  }
2961
2961
  exports2.Store = Store;
2962
2962
  Store.prototype.synchronous = false;
2963
- Store.prototype.findCookie = function(domain, path5, key, cb) {
2963
+ Store.prototype.findCookie = function(domain, path4, key, cb) {
2964
2964
  throw new Error("findCookie is not implemented");
2965
2965
  };
2966
- Store.prototype.findCookies = function(domain, path5, cb) {
2966
+ Store.prototype.findCookies = function(domain, path4, cb) {
2967
2967
  throw new Error("findCookies is not implemented");
2968
2968
  };
2969
2969
  Store.prototype.putCookie = function(cookie, cb) {
@@ -2972,10 +2972,10 @@ var require_store = __commonJS({
2972
2972
  Store.prototype.updateCookie = function(oldCookie, newCookie, cb) {
2973
2973
  throw new Error("updateCookie is not implemented");
2974
2974
  };
2975
- Store.prototype.removeCookie = function(domain, path5, key, cb) {
2975
+ Store.prototype.removeCookie = function(domain, path4, key, cb) {
2976
2976
  throw new Error("removeCookie is not implemented");
2977
2977
  };
2978
- Store.prototype.removeCookies = function(domain, path5, cb) {
2978
+ Store.prototype.removeCookies = function(domain, path4, cb) {
2979
2979
  throw new Error("removeCookies is not implemented");
2980
2980
  };
2981
2981
  Store.prototype.removeAllCookies = function(cb) {
@@ -3059,22 +3059,22 @@ var require_memstore = __commonJS({
3059
3059
  if (util.inspect.custom) {
3060
3060
  MemoryCookieStore.prototype[util.inspect.custom] = MemoryCookieStore.prototype.inspect;
3061
3061
  }
3062
- MemoryCookieStore.prototype.findCookie = function(domain, path5, key, cb) {
3062
+ MemoryCookieStore.prototype.findCookie = function(domain, path4, key, cb) {
3063
3063
  if (!this.idx[domain]) {
3064
3064
  return cb(null, void 0);
3065
3065
  }
3066
- if (!this.idx[domain][path5]) {
3066
+ if (!this.idx[domain][path4]) {
3067
3067
  return cb(null, void 0);
3068
3068
  }
3069
- return cb(null, this.idx[domain][path5][key] || null);
3069
+ return cb(null, this.idx[domain][path4][key] || null);
3070
3070
  };
3071
- MemoryCookieStore.prototype.findCookies = function(domain, path5, cb) {
3071
+ MemoryCookieStore.prototype.findCookies = function(domain, path4, cb) {
3072
3072
  var results = [];
3073
3073
  if (!domain) {
3074
3074
  return cb(null, []);
3075
3075
  }
3076
3076
  var pathMatcher;
3077
- if (!path5) {
3077
+ if (!path4) {
3078
3078
  pathMatcher = function matchAll(domainIndex) {
3079
3079
  for (var curPath in domainIndex) {
3080
3080
  var pathIndex = domainIndex[curPath];
@@ -3086,7 +3086,7 @@ var require_memstore = __commonJS({
3086
3086
  } else {
3087
3087
  pathMatcher = function matchRFC(domainIndex) {
3088
3088
  Object.keys(domainIndex).forEach(function(cookiePath) {
3089
- if (pathMatch(path5, cookiePath)) {
3089
+ if (pathMatch(path4, cookiePath)) {
3090
3090
  var pathIndex = domainIndex[cookiePath];
3091
3091
  for (var key in pathIndex) {
3092
3092
  results.push(pathIndex[key]);
@@ -3119,16 +3119,16 @@ var require_memstore = __commonJS({
3119
3119
  MemoryCookieStore.prototype.updateCookie = function(oldCookie, newCookie, cb) {
3120
3120
  this.putCookie(newCookie, cb);
3121
3121
  };
3122
- MemoryCookieStore.prototype.removeCookie = function(domain, path5, key, cb) {
3123
- if (this.idx[domain] && this.idx[domain][path5] && this.idx[domain][path5][key]) {
3124
- delete this.idx[domain][path5][key];
3122
+ MemoryCookieStore.prototype.removeCookie = function(domain, path4, key, cb) {
3123
+ if (this.idx[domain] && this.idx[domain][path4] && this.idx[domain][path4][key]) {
3124
+ delete this.idx[domain][path4][key];
3125
3125
  }
3126
3126
  cb(null);
3127
3127
  };
3128
- MemoryCookieStore.prototype.removeCookies = function(domain, path5, cb) {
3128
+ MemoryCookieStore.prototype.removeCookies = function(domain, path4, cb) {
3129
3129
  if (this.idx[domain]) {
3130
- if (path5) {
3131
- delete this.idx[domain][path5];
3130
+ if (path4) {
3131
+ delete this.idx[domain][path4];
3132
3132
  } else {
3133
3133
  delete this.idx[domain];
3134
3134
  }
@@ -3145,11 +3145,11 @@ var require_memstore = __commonJS({
3145
3145
  var domains = Object.keys(idx);
3146
3146
  domains.forEach(function(domain) {
3147
3147
  var paths = Object.keys(idx[domain]);
3148
- paths.forEach(function(path5) {
3149
- var keys = Object.keys(idx[domain][path5]);
3148
+ paths.forEach(function(path4) {
3149
+ var keys = Object.keys(idx[domain][path4]);
3150
3150
  keys.forEach(function(key) {
3151
3151
  if (key !== null) {
3152
- cookies.push(idx[domain][path5][key]);
3152
+ cookies.push(idx[domain][path4][key]);
3153
3153
  }
3154
3154
  });
3155
3155
  });
@@ -3376,18 +3376,18 @@ var require_cookie = __commonJS({
3376
3376
  }
3377
3377
  return true;
3378
3378
  }
3379
- function defaultPath(path5) {
3380
- if (!path5 || path5.substr(0, 1) !== "/") {
3379
+ function defaultPath(path4) {
3380
+ if (!path4 || path4.substr(0, 1) !== "/") {
3381
3381
  return "/";
3382
3382
  }
3383
- if (path5 === "/") {
3384
- return path5;
3383
+ if (path4 === "/") {
3384
+ return path4;
3385
3385
  }
3386
- var rightSlash = path5.lastIndexOf("/");
3386
+ var rightSlash = path4.lastIndexOf("/");
3387
3387
  if (rightSlash === 0) {
3388
3388
  return "/";
3389
3389
  }
3390
- return path5.slice(0, rightSlash);
3390
+ return path4.slice(0, rightSlash);
3391
3391
  }
3392
3392
  function trimTerminator(str) {
3393
3393
  for (var t = 0; t < TERMINATORS.length; t++) {
@@ -3563,21 +3563,21 @@ var require_cookie = __commonJS({
3563
3563
  cmp = a.creationIndex - b.creationIndex;
3564
3564
  return cmp;
3565
3565
  }
3566
- function permutePath(path5) {
3567
- if (path5 === "/") {
3566
+ function permutePath(path4) {
3567
+ if (path4 === "/") {
3568
3568
  return ["/"];
3569
3569
  }
3570
- if (path5.lastIndexOf("/") === path5.length - 1) {
3571
- path5 = path5.substr(0, path5.length - 1);
3570
+ if (path4.lastIndexOf("/") === path4.length - 1) {
3571
+ path4 = path4.substr(0, path4.length - 1);
3572
3572
  }
3573
- var permutations = [path5];
3574
- while (path5.length > 1) {
3575
- var lindex = path5.lastIndexOf("/");
3573
+ var permutations = [path4];
3574
+ while (path4.length > 1) {
3575
+ var lindex = path4.lastIndexOf("/");
3576
3576
  if (lindex === 0) {
3577
3577
  break;
3578
3578
  }
3579
- path5 = path5.substr(0, lindex);
3580
- permutations.push(path5);
3579
+ path4 = path4.substr(0, lindex);
3580
+ permutations.push(path4);
3581
3581
  }
3582
3582
  permutations.push("/");
3583
3583
  return permutations;
@@ -3908,7 +3908,7 @@ var require_cookie = __commonJS({
3908
3908
  options2 = {};
3909
3909
  }
3910
3910
  var host = canonicalDomain(context.hostname);
3911
- var path5 = context.pathname || "/";
3911
+ var path4 = context.pathname || "/";
3912
3912
  var secure = options2.secure;
3913
3913
  if (secure == null && context.protocol && (context.protocol == "https:" || context.protocol == "wss:")) {
3914
3914
  secure = true;
@@ -3931,7 +3931,7 @@ var require_cookie = __commonJS({
3931
3931
  return false;
3932
3932
  }
3933
3933
  }
3934
- if (!allPaths && !pathMatch(path5, c.path)) {
3934
+ if (!allPaths && !pathMatch(path4, c.path)) {
3935
3935
  return false;
3936
3936
  }
3937
3937
  if (c.secure && !secure) {
@@ -3947,7 +3947,7 @@ var require_cookie = __commonJS({
3947
3947
  }
3948
3948
  return true;
3949
3949
  }
3950
- store.findCookies(host, allPaths ? null : path5, function(err, cookies) {
3950
+ store.findCookies(host, allPaths ? null : path4, function(err, cookies) {
3951
3951
  if (err) {
3952
3952
  return cb(err);
3953
3953
  }
@@ -4425,13 +4425,13 @@ var require_aws_sign2 = __commonJS({
4425
4425
  }
4426
4426
  module2.exports.canonicalizeHeaders = canonicalizeHeaders;
4427
4427
  function canonicalizeResource(resource) {
4428
- var url = parse(resource, true), path5 = url.pathname, buf = [];
4428
+ var url = parse(resource, true), path4 = url.pathname, buf = [];
4429
4429
  Object.keys(url.query).forEach(function(key) {
4430
4430
  if (!~keys.indexOf(key)) return;
4431
4431
  var val = "" == url.query[key] ? "" : "=" + encodeURIComponent(url.query[key]);
4432
4432
  buf.push(key + val);
4433
4433
  });
4434
- return path5 + (buf.length ? "?" + buf.sort().join("&") : "");
4434
+ return path4 + (buf.length ? "?" + buf.sort().join("&") : "");
4435
4435
  }
4436
4436
  module2.exports.canonicalizeResource = canonicalizeResource;
4437
4437
  }
@@ -4717,14 +4717,14 @@ var require_aws4 = __commonJS({
4717
4717
  }
4718
4718
  if (pathStr !== "/") {
4719
4719
  if (normalizePath) pathStr = pathStr.replace(/\/{2,}/g, "/");
4720
- pathStr = pathStr.split("/").reduce(function(path5, piece) {
4720
+ pathStr = pathStr.split("/").reduce(function(path4, piece) {
4721
4721
  if (normalizePath && piece === "..") {
4722
- path5.pop();
4722
+ path4.pop();
4723
4723
  } else if (!normalizePath || piece !== ".") {
4724
4724
  if (decodePath) piece = decodeURIComponent(piece.replace(/\+/g, " "));
4725
- path5.push(encodeRfc3986Full(piece));
4725
+ path4.push(encodeRfc3986Full(piece));
4726
4726
  }
4727
- return path5;
4727
+ return path4;
4728
4728
  }, []).join("/");
4729
4729
  if (pathStr[0] !== "/") pathStr = "/" + pathStr;
4730
4730
  if (decodeSlashesInPath) pathStr = pathStr.replace(/%2F/g, "/");
@@ -4777,25 +4777,25 @@ var require_aws4 = __commonJS({
4777
4777
  };
4778
4778
  };
4779
4779
  RequestSigner.prototype.parsePath = function() {
4780
- var path5 = this.request.path || "/";
4781
- if (/[^0-9A-Za-z;,/?:@&=+$\-_.!~*'()#%]/.test(path5)) {
4782
- path5 = encodeURI(decodeURI(path5));
4780
+ var path4 = this.request.path || "/";
4781
+ if (/[^0-9A-Za-z;,/?:@&=+$\-_.!~*'()#%]/.test(path4)) {
4782
+ path4 = encodeURI(decodeURI(path4));
4783
4783
  }
4784
- var queryIx = path5.indexOf("?"), query = null;
4784
+ var queryIx = path4.indexOf("?"), query = null;
4785
4785
  if (queryIx >= 0) {
4786
- query = querystring.parse(path5.slice(queryIx + 1));
4787
- path5 = path5.slice(0, queryIx);
4786
+ query = querystring.parse(path4.slice(queryIx + 1));
4787
+ path4 = path4.slice(0, queryIx);
4788
4788
  }
4789
4789
  this.parsedPath = {
4790
- path: path5,
4790
+ path: path4,
4791
4791
  query
4792
4792
  };
4793
4793
  };
4794
4794
  RequestSigner.prototype.formatPath = function() {
4795
- var path5 = this.parsedPath.path, query = this.parsedPath.query;
4796
- if (!query) return path5;
4795
+ var path4 = this.parsedPath.path, query = this.parsedPath.query;
4796
+ if (!query) return path4;
4797
4797
  if (query[""] != null) delete query[""];
4798
- return path5 + "?" + encodeRfc3986(querystring.stringify(query));
4798
+ return path4 + "?" + encodeRfc3986(querystring.stringify(query));
4799
4799
  };
4800
4800
  aws4.RequestSigner = RequestSigner;
4801
4801
  aws4.sign = function(request2, credentials) {
@@ -17488,13 +17488,13 @@ var require_validate = __commonJS({
17488
17488
  return schema2.type || primitiveConstructors[schema2.name] == schema2 && schema2.name.toLowerCase();
17489
17489
  }
17490
17490
  var errors = [];
17491
- function checkProp(value, schema2, path5, i) {
17491
+ function checkProp(value, schema2, path4, i) {
17492
17492
  var l;
17493
- path5 += path5 ? typeof i == "number" ? "[" + i + "]" : typeof i == "undefined" ? "" : "." + i : i;
17493
+ path4 += path4 ? typeof i == "number" ? "[" + i + "]" : typeof i == "undefined" ? "" : "." + i : i;
17494
17494
  function addError(message) {
17495
- errors.push({ property: path5, message });
17495
+ errors.push({ property: path4, message });
17496
17496
  }
17497
- if ((typeof schema2 != "object" || schema2 instanceof Array) && (path5 || typeof schema2 != "function") && !(schema2 && getType(schema2))) {
17497
+ if ((typeof schema2 != "object" || schema2 instanceof Array) && (path4 || typeof schema2 != "function") && !(schema2 && getType(schema2))) {
17498
17498
  if (typeof schema2 == "function") {
17499
17499
  if (!(value instanceof schema2)) {
17500
17500
  addError("is not an instance of the class/constructor " + schema2.name);
@@ -17508,12 +17508,12 @@ var require_validate = __commonJS({
17508
17508
  addError("is a readonly field, it can not be changed");
17509
17509
  }
17510
17510
  if (schema2["extends"]) {
17511
- checkProp(value, schema2["extends"], path5, i);
17511
+ checkProp(value, schema2["extends"], path4, i);
17512
17512
  }
17513
17513
  function checkType(type, value2) {
17514
17514
  if (type) {
17515
17515
  if (typeof type == "string" && type != "any" && (type == "null" ? value2 !== null : typeof value2 != type) && !(value2 instanceof Array && type == "array") && !(value2 instanceof Date && type == "date") && !(type == "integer" && value2 % 1 === 0)) {
17516
- return [{ property: path5, message: value2 + " - " + typeof value2 + " value found, but a " + type + " is required" }];
17516
+ return [{ property: path4, message: value2 + " - " + typeof value2 + " value found, but a " + type + " is required" }];
17517
17517
  }
17518
17518
  if (type instanceof Array) {
17519
17519
  var unionErrors = [];
@@ -17528,7 +17528,7 @@ var require_validate = __commonJS({
17528
17528
  } else if (typeof type == "object") {
17529
17529
  var priorErrors = errors;
17530
17530
  errors = [];
17531
- checkProp(value2, type, path5);
17531
+ checkProp(value2, type, path4);
17532
17532
  var theseErrors = errors;
17533
17533
  errors = priorErrors;
17534
17534
  return theseErrors;
@@ -17555,7 +17555,7 @@ var require_validate = __commonJS({
17555
17555
  propDef = schema2.items[i];
17556
17556
  if (options2.coerce)
17557
17557
  value[i] = options2.coerce(value[i], propDef);
17558
- errors.concat(checkProp(value[i], propDef, path5, i));
17558
+ errors.concat(checkProp(value[i], propDef, path4, i));
17559
17559
  }
17560
17560
  }
17561
17561
  if (schema2.minItems && value.length < schema2.minItems) {
@@ -17565,7 +17565,7 @@ var require_validate = __commonJS({
17565
17565
  addError("There must be a maximum of " + schema2.maxItems + " in the array");
17566
17566
  }
17567
17567
  } else if (schema2.properties || schema2.additionalProperties) {
17568
- errors.concat(checkObj(value, schema2.properties, path5, schema2.additionalProperties));
17568
+ errors.concat(checkObj(value, schema2.properties, path4, schema2.additionalProperties));
17569
17569
  }
17570
17570
  if (schema2.pattern && typeof value == "string" && !value.match(schema2.pattern)) {
17571
17571
  addError("does not match the regex pattern " + schema2.pattern);
@@ -17603,10 +17603,10 @@ var require_validate = __commonJS({
17603
17603
  }
17604
17604
  return null;
17605
17605
  }
17606
- function checkObj(instance2, objTypeDef, path5, additionalProp) {
17606
+ function checkObj(instance2, objTypeDef, path4, additionalProp) {
17607
17607
  if (typeof objTypeDef == "object") {
17608
17608
  if (typeof instance2 != "object" || instance2 instanceof Array) {
17609
- errors.push({ property: path5, message: "an object is required" });
17609
+ errors.push({ property: path4, message: "an object is required" });
17610
17610
  }
17611
17611
  for (var i in objTypeDef) {
17612
17612
  if (objTypeDef.hasOwnProperty(i) && i != "__proto__" && i != "constructor") {
@@ -17619,7 +17619,7 @@ var require_validate = __commonJS({
17619
17619
  if (options2.coerce && i in instance2) {
17620
17620
  value = instance2[i] = options2.coerce(value, propDef);
17621
17621
  }
17622
- checkProp(value, propDef, path5, i);
17622
+ checkProp(value, propDef, path4, i);
17623
17623
  }
17624
17624
  }
17625
17625
  }
@@ -17629,22 +17629,22 @@ var require_validate = __commonJS({
17629
17629
  delete instance2[i];
17630
17630
  continue;
17631
17631
  } else {
17632
- errors.push({ property: path5, message: "The property " + i + " is not defined in the schema and the schema does not allow additional properties" });
17632
+ errors.push({ property: path4, message: "The property " + i + " is not defined in the schema and the schema does not allow additional properties" });
17633
17633
  }
17634
17634
  }
17635
17635
  var requires = objTypeDef && objTypeDef[i] && objTypeDef[i].requires;
17636
17636
  if (requires && !(requires in instance2)) {
17637
- errors.push({ property: path5, message: "the presence of the property " + i + " requires that " + requires + " also be present" });
17637
+ errors.push({ property: path4, message: "the presence of the property " + i + " requires that " + requires + " also be present" });
17638
17638
  }
17639
17639
  value = instance2[i];
17640
17640
  if (additionalProp && (!(objTypeDef && typeof objTypeDef == "object") || !(i in objTypeDef))) {
17641
17641
  if (options2.coerce) {
17642
17642
  value = instance2[i] = options2.coerce(value, additionalProp);
17643
17643
  }
17644
- checkProp(value, additionalProp, path5, i);
17644
+ checkProp(value, additionalProp, path4, i);
17645
17645
  }
17646
17646
  if (!_changing && value && value.$schema) {
17647
- errors = errors.concat(checkProp(value, value.$schema, path5, i));
17647
+ errors = errors.concat(checkProp(value, value.$schema, path4, i));
17648
17648
  }
17649
17649
  }
17650
17650
  return errors;
@@ -18251,11 +18251,11 @@ var require_signer = __commonJS({
18251
18251
  RequestSigner.prototype.writeDateHeader = function() {
18252
18252
  return this.writeHeader("date", jsprim.rfc1123(/* @__PURE__ */ new Date()));
18253
18253
  };
18254
- RequestSigner.prototype.writeTarget = function(method, path5) {
18254
+ RequestSigner.prototype.writeTarget = function(method, path4) {
18255
18255
  assert.string(method, "method");
18256
- assert.string(path5, "path");
18256
+ assert.string(path4, "path");
18257
18257
  method = method.toLowerCase();
18258
- this.writeHeader("(request-target)", method + " " + path5);
18258
+ this.writeHeader("(request-target)", method + " " + path4);
18259
18259
  };
18260
18260
  RequestSigner.prototype.sign = function(cb) {
18261
18261
  assert.func(cb, "callback");
@@ -27139,11 +27139,11 @@ var require_mime_types = __commonJS({
27139
27139
  }
27140
27140
  return exts[0];
27141
27141
  }
27142
- function lookup(path5) {
27143
- if (!path5 || typeof path5 !== "string") {
27142
+ function lookup(path4) {
27143
+ if (!path4 || typeof path4 !== "string") {
27144
27144
  return false;
27145
27145
  }
27146
- var extension2 = extname("x." + path5).toLowerCase().substr(1);
27146
+ var extension2 = extname("x." + path4).toLowerCase().substr(1);
27147
27147
  if (!extension2) {
27148
27148
  return false;
27149
27149
  }
@@ -27846,7 +27846,7 @@ var require_form_data = __commonJS({
27846
27846
  "node_modules/request/node_modules/form-data/lib/form_data.js"(exports2, module2) {
27847
27847
  var CombinedStream = require_combined_stream();
27848
27848
  var util = require("util");
27849
- var path5 = require("path");
27849
+ var path4 = require("path");
27850
27850
  var http = require("http");
27851
27851
  var https = require("https");
27852
27852
  var parseUrl = require("url").parse;
@@ -27971,11 +27971,11 @@ var require_form_data = __commonJS({
27971
27971
  FormData.prototype._getContentDisposition = function(value, options2) {
27972
27972
  var filename, contentDisposition;
27973
27973
  if (typeof options2.filepath === "string") {
27974
- filename = path5.normalize(options2.filepath).replace(/\\/g, "/");
27974
+ filename = path4.normalize(options2.filepath).replace(/\\/g, "/");
27975
27975
  } else if (options2.filename || value.name || value.path) {
27976
- filename = path5.basename(options2.filename || value.name || value.path);
27976
+ filename = path4.basename(options2.filename || value.name || value.path);
27977
27977
  } else if (value.readable && value.hasOwnProperty("httpVersion")) {
27978
- filename = path5.basename(value.client._httpMessage.path);
27978
+ filename = path4.basename(value.client._httpMessage.path);
27979
27979
  }
27980
27980
  if (filename) {
27981
27981
  contentDisposition = 'filename="' + filename + '"';
@@ -29613,8 +29613,8 @@ var require_uri_all = __commonJS({
29613
29613
  wsComponents.secure = void 0;
29614
29614
  }
29615
29615
  if (wsComponents.resourceName) {
29616
- var _wsComponents$resourc = wsComponents.resourceName.split("?"), _wsComponents$resourc2 = slicedToArray(_wsComponents$resourc, 2), path5 = _wsComponents$resourc2[0], query = _wsComponents$resourc2[1];
29617
- wsComponents.path = path5 && path5 !== "/" ? path5 : void 0;
29616
+ var _wsComponents$resourc = wsComponents.resourceName.split("?"), _wsComponents$resourc2 = slicedToArray(_wsComponents$resourc, 2), path4 = _wsComponents$resourc2[0], query = _wsComponents$resourc2[1];
29617
+ wsComponents.path = path4 && path4 !== "/" ? path4 : void 0;
29618
29618
  wsComponents.query = query;
29619
29619
  wsComponents.resourceName = void 0;
29620
29620
  }
@@ -29987,12 +29987,12 @@ var require_util3 = __commonJS({
29987
29987
  return "'" + escapeQuotes(str) + "'";
29988
29988
  }
29989
29989
  function getPathExpr(currentPath, expr, jsonPointers, isNumber) {
29990
- var path5 = jsonPointers ? "'/' + " + expr + (isNumber ? "" : ".replace(/~/g, '~0').replace(/\\//g, '~1')") : isNumber ? "'[' + " + expr + " + ']'" : "'[\\'' + " + expr + " + '\\']'";
29991
- return joinPaths(currentPath, path5);
29990
+ var path4 = jsonPointers ? "'/' + " + expr + (isNumber ? "" : ".replace(/~/g, '~0').replace(/\\//g, '~1')") : isNumber ? "'[' + " + expr + " + ']'" : "'[\\'' + " + expr + " + '\\']'";
29991
+ return joinPaths(currentPath, path4);
29992
29992
  }
29993
29993
  function getPath(currentPath, prop, jsonPointers) {
29994
- var path5 = jsonPointers ? toQuotedString("/" + escapeJsonPointer(prop)) : toQuotedString(getProperty(prop));
29995
- return joinPaths(currentPath, path5);
29994
+ var path4 = jsonPointers ? toQuotedString("/" + escapeJsonPointer(prop)) : toQuotedString(getProperty(prop));
29995
+ return joinPaths(currentPath, path4);
29996
29996
  }
29997
29997
  var JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/;
29998
29998
  var RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
@@ -36256,7 +36256,7 @@ var require_auth = __commonJS({
36256
36256
  return authHeader;
36257
36257
  }
36258
36258
  };
36259
- Auth.prototype.digest = function(method, path5, authHeader) {
36259
+ Auth.prototype.digest = function(method, path4, authHeader) {
36260
36260
  var self2 = this;
36261
36261
  var challenge = {};
36262
36262
  var re = /([a-z0-9_-]+)=(?:"([^"]+)"|([a-z0-9_-]+))/gi;
@@ -36279,13 +36279,13 @@ var require_auth = __commonJS({
36279
36279
  var nc = qop && "00000001";
36280
36280
  var cnonce = qop && uuid().replace(/-/g, "");
36281
36281
  var ha1 = ha1Compute(challenge.algorithm, self2.user, challenge.realm, self2.pass, challenge.nonce, cnonce);
36282
- var ha2 = md5(method + ":" + path5);
36282
+ var ha2 = md5(method + ":" + path4);
36283
36283
  var digestResponse = qop ? md5(ha1 + ":" + challenge.nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + ha2) : md5(ha1 + ":" + challenge.nonce + ":" + ha2);
36284
36284
  var authValues = {
36285
36285
  username: self2.user,
36286
36286
  realm: challenge.realm,
36287
36287
  nonce: challenge.nonce,
36288
- uri: path5,
36288
+ uri: path4,
36289
36289
  qop,
36290
36290
  response: digestResponse,
36291
36291
  nc,
@@ -38304,10 +38304,10 @@ var require_request2 = __commonJS({
38304
38304
  Request.prototype.enableUnixSocket = function() {
38305
38305
  var unixParts = this.uri.path.split(":");
38306
38306
  var host = unixParts[0];
38307
- var path5 = unixParts[1];
38307
+ var path4 = unixParts[1];
38308
38308
  this.socketPath = host;
38309
- this.uri.pathname = path5;
38310
- this.uri.path = path5;
38309
+ this.uri.pathname = path4;
38310
+ this.uri.path = path4;
38311
38311
  this.uri.host = host;
38312
38312
  this.uri.hostname = host;
38313
38313
  this.uri.isUnix = true;
@@ -38356,14 +38356,14 @@ var require_request2 = __commonJS({
38356
38356
  md5: self2.getHeader("content-md5") || "",
38357
38357
  amazonHeaders: aws2.canonicalizeHeaders(self2.headers)
38358
38358
  };
38359
- var path5 = self2.uri.path;
38360
- if (opts.bucket && path5) {
38361
- auth.resource = "/" + opts.bucket + path5;
38362
- } else if (opts.bucket && !path5) {
38359
+ var path4 = self2.uri.path;
38360
+ if (opts.bucket && path4) {
38361
+ auth.resource = "/" + opts.bucket + path4;
38362
+ } else if (opts.bucket && !path4) {
38363
38363
  auth.resource = "/" + opts.bucket;
38364
- } else if (!opts.bucket && path5) {
38365
- auth.resource = path5;
38366
- } else if (!opts.bucket && !path5) {
38364
+ } else if (!opts.bucket && path4) {
38365
+ auth.resource = path4;
38366
+ } else if (!opts.bucket && !path4) {
38367
38367
  auth.resource = "/";
38368
38368
  }
38369
38369
  auth.resource = aws2.canonicalizeResource(auth.resource);
@@ -40533,10 +40533,10 @@ var require_posix = __commonJS({
40533
40533
  exports2.sync = exports2.isexe = void 0;
40534
40534
  var fs_1 = require("fs");
40535
40535
  var promises_1 = require("fs/promises");
40536
- var isexe = async (path5, options2 = {}) => {
40536
+ var isexe = async (path4, options2 = {}) => {
40537
40537
  const { ignoreErrors = false } = options2;
40538
40538
  try {
40539
- return checkStat(await (0, promises_1.stat)(path5), options2);
40539
+ return checkStat(await (0, promises_1.stat)(path4), options2);
40540
40540
  } catch (e) {
40541
40541
  const er = e;
40542
40542
  if (ignoreErrors || er.code === "EACCES")
@@ -40545,10 +40545,10 @@ var require_posix = __commonJS({
40545
40545
  }
40546
40546
  };
40547
40547
  exports2.isexe = isexe;
40548
- var sync2 = (path5, options2 = {}) => {
40548
+ var sync2 = (path4, options2 = {}) => {
40549
40549
  const { ignoreErrors = false } = options2;
40550
40550
  try {
40551
- return checkStat((0, fs_1.statSync)(path5), options2);
40551
+ return checkStat((0, fs_1.statSync)(path4), options2);
40552
40552
  } catch (e) {
40553
40553
  const er = e;
40554
40554
  if (ignoreErrors || er.code === "EACCES")
@@ -40586,10 +40586,10 @@ var require_win32 = __commonJS({
40586
40586
  exports2.sync = exports2.isexe = void 0;
40587
40587
  var fs_1 = require("fs");
40588
40588
  var promises_1 = require("fs/promises");
40589
- var isexe = async (path5, options2 = {}) => {
40589
+ var isexe = async (path4, options2 = {}) => {
40590
40590
  const { ignoreErrors = false } = options2;
40591
40591
  try {
40592
- return checkStat(await (0, promises_1.stat)(path5), path5, options2);
40592
+ return checkStat(await (0, promises_1.stat)(path4), path4, options2);
40593
40593
  } catch (e) {
40594
40594
  const er = e;
40595
40595
  if (ignoreErrors || er.code === "EACCES")
@@ -40598,10 +40598,10 @@ var require_win32 = __commonJS({
40598
40598
  }
40599
40599
  };
40600
40600
  exports2.isexe = isexe;
40601
- var sync2 = (path5, options2 = {}) => {
40601
+ var sync2 = (path4, options2 = {}) => {
40602
40602
  const { ignoreErrors = false } = options2;
40603
40603
  try {
40604
- return checkStat((0, fs_1.statSync)(path5), path5, options2);
40604
+ return checkStat((0, fs_1.statSync)(path4), path4, options2);
40605
40605
  } catch (e) {
40606
40606
  const er = e;
40607
40607
  if (ignoreErrors || er.code === "EACCES")
@@ -40610,7 +40610,7 @@ var require_win32 = __commonJS({
40610
40610
  }
40611
40611
  };
40612
40612
  exports2.sync = sync2;
40613
- var checkPathExt = (path5, options2) => {
40613
+ var checkPathExt = (path4, options2) => {
40614
40614
  const { pathExt = process.env.PATHEXT || "" } = options2;
40615
40615
  const peSplit = pathExt.split(";");
40616
40616
  if (peSplit.indexOf("") !== -1) {
@@ -40618,14 +40618,14 @@ var require_win32 = __commonJS({
40618
40618
  }
40619
40619
  for (let i = 0; i < peSplit.length; i++) {
40620
40620
  const p = peSplit[i].toLowerCase();
40621
- const ext = path5.substring(path5.length - p.length).toLowerCase();
40621
+ const ext = path4.substring(path4.length - p.length).toLowerCase();
40622
40622
  if (p && ext === p) {
40623
40623
  return true;
40624
40624
  }
40625
40625
  }
40626
40626
  return false;
40627
40627
  };
40628
- var checkStat = (stat, path5, options2) => stat.isFile() && checkPathExt(path5, options2);
40628
+ var checkStat = (stat, path4, options2) => stat.isFile() && checkPathExt(path4, options2);
40629
40629
  }
40630
40630
  });
40631
40631
 
@@ -40778,12 +40778,11 @@ var import_child_process = require("child_process");
40778
40778
 
40779
40779
  // src/options.ts
40780
40780
  var fs3 = __toESM(require("fs"));
40781
- var path3 = __toESM(require("path"));
40781
+ var path2 = __toESM(require("path"));
40782
40782
 
40783
40783
  // src/utils.ts
40784
40784
  var fs2 = __toESM(require("fs"));
40785
40785
  var os2 = __toESM(require("os"));
40786
- var import_path2 = __toESM(require("path"));
40787
40786
 
40788
40787
  // src/logger.ts
40789
40788
  var import_fs = __toESM(require("fs"));
@@ -40855,7 +40854,6 @@ var logger = global.logger ?? new Logger();
40855
40854
  global.logger = logger;
40856
40855
 
40857
40856
  // src/utils.ts
40858
- var STATE_FILE = import_path2.default.join(os2.homedir(), ".wakatime", "claude-code.json");
40859
40857
  function parseInput() {
40860
40858
  try {
40861
40859
  const stdinData = fs2.readFileSync(0, "utf-8");
@@ -40868,29 +40866,34 @@ function parseInput() {
40868
40866
  }
40869
40867
  return void 0;
40870
40868
  }
40869
+ function getStateFile(inp) {
40870
+ return `${inp.transcript_path}.wakatime`;
40871
+ }
40871
40872
  function shouldSendHeartbeat(inp) {
40872
40873
  if (inp?.hook_event_name === "Stop") {
40873
40874
  return true;
40874
40875
  }
40876
+ if (!inp) return false;
40875
40877
  try {
40876
- const last = JSON.parse(fs2.readFileSync(STATE_FILE, "utf-8")).lastHeartbeatAt ?? timestamp();
40878
+ const last = JSON.parse(fs2.readFileSync(getStateFile(inp), "utf-8")).lastHeartbeatAt ?? timestamp();
40877
40879
  return timestamp() - last >= 60;
40878
40880
  } catch {
40879
40881
  return true;
40880
40882
  }
40881
40883
  }
40882
- function updateState() {
40883
- fs2.mkdirSync(import_path2.default.dirname(STATE_FILE), { recursive: true });
40884
- fs2.writeFileSync(STATE_FILE, JSON.stringify({ lastHeartbeatAt: timestamp() }, null, 2));
40884
+ async function updateState(inp) {
40885
+ if (!inp) return;
40886
+ const file = getStateFile(inp);
40887
+ await fs2.promises.writeFile(file, JSON.stringify({ lastHeartbeatAt: timestamp() }, null, 2));
40885
40888
  }
40886
- function getEntityFiles(inp) {
40889
+ async function getEntityFiles(inp) {
40887
40890
  const entities = /* @__PURE__ */ new Map();
40888
40891
  let claudeVersion = "";
40889
40892
  const transcriptPath = inp?.transcript_path;
40890
40893
  if (!transcriptPath || !fs2.existsSync(transcriptPath)) {
40891
40894
  return { entities, claudeVersion };
40892
40895
  }
40893
- const lastHeartbeatAt = getLastHeartbeat();
40896
+ const lastHeartbeatAt = await getLastHeartbeat(inp);
40894
40897
  const content = fs2.readFileSync(transcriptPath, "utf-8");
40895
40898
  for (const logLine of content.split("\n")) {
40896
40899
  if (!logLine.trim()) continue;
@@ -40905,11 +40908,15 @@ function getEntityFiles(inp) {
40905
40908
  const patches = log.toolUseResult?.structuredPatch;
40906
40909
  if (!patches) continue;
40907
40910
  const lineChanges = patches.map((patch) => patch.newLines - patch.oldLines).reduce((p, c) => p + c, 0);
40908
- entities.set(filePath, (entities.get(filePath) ?? 0) + lineChanges);
40911
+ const prevLineChanges = (entities.get(filePath) ?? { lineChanges: 0 }).lineChanges;
40912
+ entities.set(filePath, { lineChanges: prevLineChanges + lineChanges, type: "file" });
40909
40913
  } catch (err) {
40910
40914
  logger.warnException(err);
40911
40915
  }
40912
40916
  }
40917
+ if (inp.hook_event_name == "UserPromptSubmit" && entities.size === 0) {
40918
+ entities.set(inp.cwd, { lineChanges: 0, type: "app" });
40919
+ }
40913
40920
  return { entities, claudeVersion };
40914
40921
  }
40915
40922
  function formatArguments(binary, args) {
@@ -40944,9 +40951,9 @@ function buildOptions(stdin) {
40944
40951
  }
40945
40952
  return options2;
40946
40953
  }
40947
- function getLastHeartbeat() {
40954
+ async function getLastHeartbeat(inp) {
40948
40955
  try {
40949
- const stateData = JSON.parse(fs2.readFileSync(STATE_FILE, "utf-8"));
40956
+ const stateData = JSON.parse(await fs2.promises.readFile(getStateFile(inp), "utf-8"));
40950
40957
  return stateData.lastHeartbeatAt ?? 0;
40951
40958
  } catch {
40952
40959
  return 0;
@@ -40972,7 +40979,7 @@ function obfuscateKey(key) {
40972
40979
  var Options = class {
40973
40980
  constructor() {
40974
40981
  const home = getHomeDirectory();
40975
- const wakaFolder = path3.join(home, ".wakatime");
40982
+ const wakaFolder = path2.join(home, ".wakatime");
40976
40983
  try {
40977
40984
  if (!fs3.existsSync(wakaFolder)) {
40978
40985
  fs3.mkdirSync(wakaFolder, { recursive: true });
@@ -40982,9 +40989,9 @@ var Options = class {
40982
40989
  console.error(e);
40983
40990
  throw e;
40984
40991
  }
40985
- this.configFile = path3.join(home, ".wakatime.cfg");
40986
- this.internalConfigFile = path3.join(this.resourcesLocation, "wakatime-internal.cfg");
40987
- this.logFile = path3.join(this.resourcesLocation, "wakatime.log");
40992
+ this.configFile = path2.join(home, ".wakatime.cfg");
40993
+ this.internalConfigFile = path2.join(this.resourcesLocation, "wakatime-internal.cfg");
40994
+ this.logFile = path2.join(this.resourcesLocation, "wakatime.log");
40988
40995
  }
40989
40996
  getSetting(section, key, internal) {
40990
40997
  try {
@@ -41127,14 +41134,14 @@ var Options = class {
41127
41134
  };
41128
41135
 
41129
41136
  // src/version.ts
41130
- var VERSION = "3.0.3";
41137
+ var VERSION = "3.1.0";
41131
41138
 
41132
41139
  // src/dependencies.ts
41133
41140
  var import_adm_zip = __toESM(require_adm_zip());
41134
41141
  var child_process = __toESM(require("child_process"));
41135
41142
  var fs4 = __toESM(require("fs"));
41136
41143
  var os3 = __toESM(require("os"));
41137
- var path4 = __toESM(require("path"));
41144
+ var path3 = __toESM(require("path"));
41138
41145
  var request = __toESM(require_request3());
41139
41146
  var semver = __toESM(require_semver2());
41140
41147
  var which = __toESM(require_lib6());
@@ -41160,16 +41167,16 @@ var Dependencies = class {
41160
41167
  const arch2 = this.architecture();
41161
41168
  const ext = isWindows() ? ".exe" : "";
41162
41169
  const binary = `wakatime-cli-${osname}-${arch2}${ext}`;
41163
- this.cliLocation = path4.join(this.resourcesLocation, binary);
41170
+ this.cliLocation = path3.join(this.resourcesLocation, binary);
41164
41171
  return this.cliLocation;
41165
41172
  }
41166
41173
  getCliLocationGlobal() {
41167
41174
  if (this.cliLocationGlobal) return this.cliLocationGlobal;
41168
41175
  const binaryName = `wakatime-cli${isWindows() ? ".exe" : ""}`;
41169
- const path5 = which.sync(binaryName, { nothrow: true });
41170
- if (path5) {
41171
- this.cliLocationGlobal = path5;
41172
- this.logger.debug(`Using global wakatime-cli location: ${path5}`);
41176
+ const path4 = which.sync(binaryName, { nothrow: true });
41177
+ if (path4) {
41178
+ this.cliLocationGlobal = path4;
41179
+ this.logger.debug(`Using global wakatime-cli location: ${path4}`);
41173
41180
  }
41174
41181
  return this.cliLocationGlobal;
41175
41182
  }
@@ -41285,7 +41292,7 @@ var Dependencies = class {
41285
41292
  installCli(callback) {
41286
41293
  this.logger.debug(`Downloading wakatime-cli from GitHub...`);
41287
41294
  const url = this.cliDownloadUrl();
41288
- let zipFile = path4.join(this.resourcesLocation, "wakatime-cli" + this.randStr() + ".zip");
41295
+ let zipFile = path3.join(this.resourcesLocation, "wakatime-cli" + this.randStr() + ".zip");
41289
41296
  this.downloadFile(
41290
41297
  url,
41291
41298
  zipFile,
@@ -41318,7 +41325,7 @@ var Dependencies = class {
41318
41325
  this.logger.warnException(e);
41319
41326
  }
41320
41327
  const ext = isWindows() ? ".exe" : "";
41321
- const link = path4.join(this.resourcesLocation, `wakatime-cli${ext}`);
41328
+ const link = path3.join(this.resourcesLocation, `wakatime-cli${ext}`);
41322
41329
  if (!this.isSymlink(link)) {
41323
41330
  try {
41324
41331
  this.logger.debug(`Create symlink from wakatime-cli to ${cli}`);
@@ -41479,18 +41486,18 @@ var Dependencies = class {
41479
41486
  // src/index.ts
41480
41487
  var options = new Options();
41481
41488
  var deps = new Dependencies(options, logger);
41482
- function sendHeartbeat(inp) {
41489
+ async function sendHeartbeat(inp) {
41483
41490
  const projectFolder = inp?.cwd;
41484
- const { entities, claudeVersion } = getEntityFiles(inp);
41491
+ const { entities, claudeVersion } = await getEntityFiles(inp);
41485
41492
  if (entities.size === 0) return false;
41486
41493
  const wakatime_cli = deps.getCliLocation();
41487
- for (const [entity, lineChanges] of entities.entries()) {
41488
- logger.debug(`Entity: ${entity}`);
41494
+ for (const [entityFile, entityData] of entities.entries()) {
41495
+ logger.debug(`Entity: ${entityFile}`);
41489
41496
  const args = [
41490
41497
  "--entity",
41491
- entity,
41498
+ entityFile,
41492
41499
  "--entity-type",
41493
- "file",
41500
+ entityData.type,
41494
41501
  "--category",
41495
41502
  "ai coding",
41496
41503
  "--plugin",
@@ -41500,9 +41507,9 @@ function sendHeartbeat(inp) {
41500
41507
  args.push("--project-folder");
41501
41508
  args.push(projectFolder);
41502
41509
  }
41503
- if (lineChanges) {
41510
+ if (entityData.lineChanges) {
41504
41511
  args.push("--ai-line-changes");
41505
- args.push(lineChanges.toString());
41512
+ args.push(entityData.lineChanges.toString());
41506
41513
  }
41507
41514
  logger.debug(`Sending heartbeat: ${formatArguments(wakatime_cli, args)}`);
41508
41515
  const execOptions = buildOptions();
@@ -41514,7 +41521,7 @@ function sendHeartbeat(inp) {
41514
41521
  }
41515
41522
  return true;
41516
41523
  }
41517
- function main() {
41524
+ async function main() {
41518
41525
  const inp = parseInput();
41519
41526
  const debug = options.getSetting("settings", "debug");
41520
41527
  logger.setLevel(debug === "true" ? 0 /* DEBUG */ : 1 /* INFO */);
@@ -41522,8 +41529,8 @@ function main() {
41522
41529
  if (inp) logger.debug(JSON.stringify(inp, null, 2));
41523
41530
  deps.checkAndInstallCli();
41524
41531
  if (shouldSendHeartbeat(inp)) {
41525
- if (sendHeartbeat(inp)) {
41526
- updateState();
41532
+ if (await sendHeartbeat(inp)) {
41533
+ await updateState(inp);
41527
41534
  }
41528
41535
  }
41529
41536
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-wakatime",
3
- "version": "3.0.4",
3
+ "version": "3.1.0",
4
4
  "description": "WakaTime plugin for Claude Code",
5
5
  "bin": {
6
6
  "claude-code-wakatime": "dist/index.js"
@@ -11,9 +11,9 @@
11
11
  "build:legacy": "esbuild src/install-hooks.ts --bundle --platform=node --outfile=dist/install-hooks.js",
12
12
  "build": "npm run build:legacy && esbuild src/index.ts --bundle --platform=node --outfile=dist/index.js",
13
13
  "watch": "npm run prebuild && tsc --watch",
14
- "release:major": "npm run build && npm version major && npm publish && git push && git push --tags",
15
- "release:minor": "npm run build && npm version minor && npm publish && git push && git push --tags",
16
- "release:patch": "npm run build && npm version patch && npm publish && git push && git push --tags"
14
+ "release:major": "npm version major && npm run build && npm publish && git push && git push --tags",
15
+ "release:minor": "npm version minor && npm run build && npm publish && git push && git push --tags",
16
+ "release:patch": "npm version patch && npm run build && npm publish && git push && git push --tags"
17
17
  },
18
18
  "repository": {
19
19
  "type": "git",
package/src/index.ts CHANGED
@@ -4,27 +4,27 @@ import { execFile } from 'child_process';
4
4
  import { Options } from './options';
5
5
  import { VERSION } from './version';
6
6
  import { Dependencies } from './dependencies';
7
- import { logger, Logger, LogLevel } from './logger';
7
+ import { logger, LogLevel } from './logger';
8
8
  import { Input } from './types';
9
9
  import { buildOptions, formatArguments, getEntityFiles, parseInput, shouldSendHeartbeat, updateState } from './utils';
10
10
 
11
11
  const options = new Options();
12
12
  const deps = new Dependencies(options, logger);
13
13
 
14
- function sendHeartbeat(inp: Input | undefined): boolean {
14
+ async function sendHeartbeat(inp: Input | undefined): Promise<boolean> {
15
15
  const projectFolder = inp?.cwd;
16
- const { entities, claudeVersion } = getEntityFiles(inp);
16
+ const { entities, claudeVersion } = await getEntityFiles(inp);
17
17
  if (entities.size === 0) return false;
18
18
 
19
19
  const wakatime_cli = deps.getCliLocation();
20
20
 
21
- for (const [entity, lineChanges] of entities.entries()) {
22
- logger.debug(`Entity: ${entity}`);
21
+ for (const [entityFile, entityData] of entities.entries()) {
22
+ logger.debug(`Entity: ${entityFile}`);
23
23
  const args: string[] = [
24
24
  '--entity',
25
- entity,
25
+ entityFile,
26
26
  '--entity-type',
27
- 'file',
27
+ entityData.type,
28
28
  '--category',
29
29
  'ai coding',
30
30
  '--plugin',
@@ -35,9 +35,9 @@ function sendHeartbeat(inp: Input | undefined): boolean {
35
35
  args.push(projectFolder);
36
36
  }
37
37
 
38
- if (lineChanges) {
38
+ if (entityData.lineChanges) {
39
39
  args.push('--ai-line-changes');
40
- args.push(lineChanges.toString());
40
+ args.push(entityData.lineChanges.toString());
41
41
  }
42
42
 
43
43
  logger.debug(`Sending heartbeat: ${formatArguments(wakatime_cli, args)}`);
@@ -53,7 +53,7 @@ function sendHeartbeat(inp: Input | undefined): boolean {
53
53
  return true;
54
54
  }
55
55
 
56
- function main() {
56
+ async function main() {
57
57
  const inp = parseInput();
58
58
 
59
59
  const debug = options.getSetting('settings', 'debug');
@@ -65,8 +65,8 @@ function main() {
65
65
  deps.checkAndInstallCli();
66
66
 
67
67
  if (shouldSendHeartbeat(inp)) {
68
- if (sendHeartbeat(inp)) {
69
- updateState();
68
+ if (await sendHeartbeat(inp)) {
69
+ await updateState(inp);
70
70
  }
71
71
  }
72
72
  } catch (err) {
package/src/types.ts CHANGED
@@ -2,11 +2,23 @@ export type State = {
2
2
  lastHeartbeatAt?: number;
3
3
  };
4
4
 
5
+ export type HookEvent =
6
+ | 'PreToolUse'
7
+ | 'PermissionRequest'
8
+ | 'PostToolUse'
9
+ | 'Notification'
10
+ | 'UserPromptSubmit'
11
+ | 'Stop'
12
+ | 'SubagentStop'
13
+ | 'PreCompact'
14
+ | 'SessionStart'
15
+ | 'SessionEnd';
16
+
5
17
  export type Input = {
6
18
  session_id: string;
7
19
  transcript_path: string;
8
20
  cwd: string;
9
- hook_event_name: string;
21
+ hook_event_name: HookEvent;
10
22
  };
11
23
 
12
24
  export type TranscriptLog = {
@@ -48,3 +60,10 @@ export type TranscriptLog = {
48
60
  replaceAll?: string;
49
61
  };
50
62
  };
63
+
64
+ export type Entity = {
65
+ type: 'file' | 'app';
66
+ lineChanges: number;
67
+ };
68
+
69
+ export type EntityMap = Map<string, Entity>;
package/src/utils.ts CHANGED
@@ -2,12 +2,9 @@ import * as fs from 'fs';
2
2
  import * as os from 'os';
3
3
  import * as child_process from 'child_process';
4
4
  import { StdioOptions } from 'child_process';
5
- import { Input, State, TranscriptLog } from './types';
6
- import path from 'path';
5
+ import { Entity, EntityMap, Input, State, TranscriptLog } from './types';
7
6
  import { logger } from './logger';
8
7
 
9
- const STATE_FILE = path.join(os.homedir(), '.wakatime', 'claude-code.json');
10
-
11
8
  export function parseInput() {
12
9
  try {
13
10
  const stdinData = fs.readFileSync(0, 'utf-8');
@@ -21,26 +18,33 @@ export function parseInput() {
21
18
  return undefined;
22
19
  }
23
20
 
21
+ function getStateFile(inp: Input): string {
22
+ return `${inp.transcript_path}.wakatime`;
23
+ }
24
+
24
25
  export function shouldSendHeartbeat(inp?: Input): boolean {
25
26
  if (inp?.hook_event_name === 'Stop') {
26
27
  return true;
27
28
  }
28
29
 
30
+ if (!inp) return false;
31
+
29
32
  try {
30
- const last = (JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8')) as State).lastHeartbeatAt ?? timestamp();
33
+ const last = (JSON.parse(fs.readFileSync(getStateFile(inp), 'utf-8')) as State).lastHeartbeatAt ?? timestamp();
31
34
  return timestamp() - last >= 60;
32
35
  } catch {
33
36
  return true;
34
37
  }
35
38
  }
36
39
 
37
- export function updateState() {
38
- fs.mkdirSync(path.dirname(STATE_FILE), { recursive: true });
39
- fs.writeFileSync(STATE_FILE, JSON.stringify({ lastHeartbeatAt: timestamp() } as State, null, 2));
40
+ export async function updateState(inp?: Input) {
41
+ if (!inp) return;
42
+ const file = getStateFile(inp);
43
+ await fs.promises.writeFile(file, JSON.stringify({ lastHeartbeatAt: timestamp() } as State, null, 2));
40
44
  }
41
45
 
42
- export function getEntityFiles(inp: Input | undefined): { entities: Map<string, number>; claudeVersion: string } {
43
- const entities = new Map<string, number>();
46
+ export async function getEntityFiles(inp: Input | undefined): Promise<{ entities: EntityMap; claudeVersion: string }> {
47
+ const entities = new Map<string, Entity>() as EntityMap;
44
48
  let claudeVersion = '';
45
49
 
46
50
  const transcriptPath = inp?.transcript_path;
@@ -48,7 +52,7 @@ export function getEntityFiles(inp: Input | undefined): { entities: Map<string,
48
52
  return { entities, claudeVersion };
49
53
  }
50
54
 
51
- const lastHeartbeatAt = getLastHeartbeat();
55
+ const lastHeartbeatAt = await getLastHeartbeat(inp);
52
56
 
53
57
  const content = fs.readFileSync(transcriptPath, 'utf-8');
54
58
  for (const logLine of content.split('\n')) {
@@ -71,12 +75,17 @@ export function getEntityFiles(inp: Input | undefined): { entities: Map<string,
71
75
 
72
76
  const lineChanges = patches.map((patch) => patch.newLines - patch.oldLines).reduce((p, c) => p + c, 0);
73
77
 
74
- entities.set(filePath, (entities.get(filePath) ?? 0) + lineChanges);
78
+ const prevLineChanges = (entities.get(filePath) ?? ({ lineChanges: 0 } as Entity)).lineChanges;
79
+ entities.set(filePath, { lineChanges: prevLineChanges + lineChanges, type: 'file' });
75
80
  } catch (err) {
76
81
  logger.warnException(err);
77
82
  }
78
83
  }
79
84
 
85
+ if (inp.hook_event_name == 'UserPromptSubmit' && entities.size === 0) {
86
+ entities.set(inp.cwd, { lineChanges: 0, type: 'app' });
87
+ }
88
+
80
89
  return { entities, claudeVersion };
81
90
  }
82
91
 
@@ -116,9 +125,9 @@ export function buildOptions(stdin?: boolean): Object {
116
125
  return options;
117
126
  }
118
127
 
119
- function getLastHeartbeat() {
128
+ async function getLastHeartbeat(inp: Input) {
120
129
  try {
121
- const stateData = JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8')) as State;
130
+ const stateData = JSON.parse(await fs.promises.readFile(getStateFile(inp), 'utf-8')) as State;
122
131
  return stateData.lastHeartbeatAt ?? 0;
123
132
  } catch {
124
133
  return 0;