codeusage-cli 0.1.10 → 0.1.11

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.cjs +775 -57
  3. package/package.json +4 -2
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # CodeUsage CLI
1
+ # Codeusage CLI
2
2
 
3
3
  Track your team's AI coding tool usage with zero friction.
4
4
 
package/dist/index.cjs CHANGED
@@ -21374,10 +21374,12 @@ var toolUsageSchema = exports_external.object({
21374
21374
  name: exports_external.string().min(1),
21375
21375
  count: exports_external.number().int().min(0)
21376
21376
  });
21377
+ var fileChangeTypeSchema = exports_external.enum(["created", "modified", "deleted"]);
21377
21378
  var fileChangeDetailSchema = exports_external.object({
21378
21379
  path: exports_external.string().min(1),
21379
21380
  additions: exports_external.number().int().min(0),
21380
- deletions: exports_external.number().int().min(0)
21381
+ deletions: exports_external.number().int().min(0),
21382
+ change_type: fileChangeTypeSchema
21381
21383
  });
21382
21384
  var toolSourceSchema = exports_external.enum(["claude_code", "codex"]);
21383
21385
  var hookScopeSchema = exports_external.enum(["global", "project"]);
@@ -21391,6 +21393,9 @@ var telemetryPayloadSchema = exports_external.object({
21391
21393
  cache_tokens: exports_external.number().int().min(0),
21392
21394
  cost_usd: exports_external.number().min(0).max(50),
21393
21395
  files_changed: exports_external.number().int().min(0),
21396
+ files_created: exports_external.number().int().min(0),
21397
+ files_modified: exports_external.number().int().min(0),
21398
+ files_deleted: exports_external.number().int().min(0),
21394
21399
  files_changed_details: exports_external.array(fileChangeDetailSchema).default([]),
21395
21400
  tools_used: exports_external.array(toolUsageSchema),
21396
21401
  task_duration_sec: exports_external.number().int().min(0),
@@ -21650,7 +21655,10 @@ async function validateApiKey(apiKey) {
21650
21655
  return { valid: false, error: "Invalid API key" };
21651
21656
  }
21652
21657
  const errorBody = await response.text().catch(() => "");
21653
- return { valid: false, error: `Unexpected response ${response.status} from ${apiUrl}: ${errorBody}` };
21658
+ return {
21659
+ valid: false,
21660
+ error: `Unexpected response ${response.status} from ${apiUrl}: ${errorBody}`
21661
+ };
21654
21662
  } catch (err) {
21655
21663
  const error = err;
21656
21664
  const cause = error.cause ? ` (cause: ${JSON.stringify(error.cause)})` : "";
@@ -28207,21 +28215,21 @@ var claudeCodeConfig = {
28207
28215
  const s = settings || {};
28208
28216
  s.hooks = s.hooks || {};
28209
28217
  const stopHooks = s.hooks.Stop || [];
28210
- const hasStopCodeUsage = stopHooks.some((entry) => entry.hooks?.some((h2) => h2.command.startsWith("codeusage")));
28211
- if (!hasStopCodeUsage) {
28218
+ const hasStopCodeusage = stopHooks.some((entry) => entry.hooks?.some((h2) => h2.command.startsWith("codeusage")));
28219
+ if (!hasStopCodeusage) {
28212
28220
  s.hooks.Stop = [...stopHooks, createClaudeHookEntry("codeusage hook stop --provider claude_code")];
28213
28221
  }
28214
28222
  const postToolHooks = s.hooks.PostToolUse || [];
28215
- const hasPostToolCodeUsage = postToolHooks.some((entry) => entry.hooks?.some((h2) => h2.command.startsWith("codeusage")));
28216
- if (!hasPostToolCodeUsage) {
28223
+ const hasPostToolCodeusage = postToolHooks.some((entry) => entry.hooks?.some((h2) => h2.command.startsWith("codeusage")));
28224
+ if (!hasPostToolCodeusage) {
28217
28225
  s.hooks.PostToolUse = [
28218
28226
  ...postToolHooks,
28219
28227
  createClaudeHookEntry("codeusage hook post-tool-use --provider claude_code")
28220
28228
  ];
28221
28229
  }
28222
28230
  const notifHooks = s.hooks.Notification || [];
28223
- const hasNotifCodeUsage = notifHooks.some((entry) => entry.hooks?.some((h2) => h2.command.startsWith("codeusage")));
28224
- if (!hasNotifCodeUsage) {
28231
+ const hasNotifCodeusage = notifHooks.some((entry) => entry.hooks?.some((h2) => h2.command.startsWith("codeusage")));
28232
+ if (!hasNotifCodeusage) {
28225
28233
  s.hooks.Notification = [
28226
28234
  ...notifHooks,
28227
28235
  createClaudeHookEntry("codeusage hook notification --provider claude_code")
@@ -28244,7 +28252,7 @@ var claudeCodeConfig = {
28244
28252
  }
28245
28253
  return s;
28246
28254
  },
28247
- hasCodeUsage: (settings) => {
28255
+ hasCodeusage: (settings) => {
28248
28256
  const s = settings;
28249
28257
  if (!s?.hooks?.Stop)
28250
28258
  return false;
@@ -28262,11 +28270,11 @@ var codexConfig = {
28262
28270
  const s = settings || {};
28263
28271
  s.hooks = s.hooks || {};
28264
28272
  const stopHooks = s.hooks.Stop || [];
28265
- const hasStopCodeUsage = stopHooks.some((h2) => h2.command.startsWith("codeusage"));
28266
- if (!hasStopCodeUsage) {
28273
+ const hasStopCodeusage = stopHooks.some((h2) => h2.command.startsWith("codeusage"));
28274
+ if (!hasStopCodeusage) {
28267
28275
  s.hooks.Stop = [
28268
28276
  ...stopHooks,
28269
- createCodexHookCommand("codeusage hook stop --provider codex", "Syncing to CodeUsage...")
28277
+ createCodexHookCommand("codeusage hook stop --provider codex", "Syncing to Codeusage...")
28270
28278
  ];
28271
28279
  }
28272
28280
  return s;
@@ -28280,7 +28288,7 @@ var codexConfig = {
28280
28288
  }
28281
28289
  return s;
28282
28290
  },
28283
- hasCodeUsage: (settings) => {
28291
+ hasCodeusage: (settings) => {
28284
28292
  const s = settings;
28285
28293
  if (!s?.hooks?.Stop)
28286
28294
  return false;
@@ -28342,15 +28350,15 @@ async function areHooksRegistered(scope, cwd, providerId = DEFAULT_PROVIDER) {
28342
28350
  try {
28343
28351
  const content = await import_promises12.default.readFile(filePath, "utf-8");
28344
28352
  const settings = JSON.parse(content);
28345
- return config2.hasCodeUsage(settings);
28353
+ return config2.hasCodeusage(settings);
28346
28354
  } catch {}
28347
28355
  return false;
28348
28356
  }
28349
28357
 
28350
28358
  // src/commands/init.ts
28351
- var initCommand = new Command("init").description("Initialize CodeUsage CLI and connect to your workspace").option("--force", "Reinitialize even if already configured").action(async (options) => {
28359
+ var initCommand = new Command("init").description("Initialize Codeusage CLI and connect to your workspace").option("--force", "Reinitialize even if already configured").action(async (options) => {
28352
28360
  console.log(source_default.bold(`
28353
- \uD83D\uDCCA CodeUsage CLI Setup
28361
+ \uD83D\uDCCA Codeusage CLI Setup
28354
28362
  `));
28355
28363
  if (isConfigured() && !options.force) {
28356
28364
  const config2 = getConfig();
@@ -28385,7 +28393,7 @@ Selected provider is not available yet.
28385
28393
  Using ${providerInfo.displayName}
28386
28394
  `));
28387
28395
  console.log(source_default.dim(`
28388
- Get your workspace key from the CodeUsage dashboard Settings page.
28396
+ Get your workspace key from the Codeusage dashboard Settings page.
28389
28397
  `));
28390
28398
  const workspaceKey = await dist_default5({
28391
28399
  message: "Workspace API key:",
@@ -28451,7 +28459,7 @@ ${err.message}
28451
28459
  project_overrides: {}
28452
28460
  });
28453
28461
  console.log(source_default.green(`
28454
- CodeUsage is ready!
28462
+ Codeusage is ready!
28455
28463
  `));
28456
28464
  console.log(source_default.dim(`Your ${providerInfo.displayName} sessions will now be tracked.`));
28457
28465
  console.log(source_default.dim(`View your dashboard at: https://codeusage.dev
@@ -28526,9 +28534,9 @@ async function clearBuffer() {
28526
28534
  }
28527
28535
 
28528
28536
  // src/commands/status.ts
28529
- var statusCommand = new Command("status").description("Show current CodeUsage configuration and connection status").action(async () => {
28537
+ var statusCommand = new Command("status").description("Show current Codeusage configuration and connection status").action(async () => {
28530
28538
  console.log(source_default.bold(`
28531
- \uD83D\uDCCA CodeUsage Status
28539
+ \uD83D\uDCCA Codeusage Status
28532
28540
  `));
28533
28541
  if (!isConfigured()) {
28534
28542
  console.log(source_default.yellow(`Not configured. Run: codeusage init
@@ -28739,7 +28747,7 @@ ${newProvider.displayName} is coming soon!`));
28739
28747
  console.log(source_default.green(`
28740
28748
  ✓ ${newProvider.displayName} hooks registered!
28741
28749
  `));
28742
- console.log(source_default.dim(`Both providers are now active. Tasks from either tool will sync to CodeUsage.
28750
+ console.log(source_default.dim(`Both providers are now active. Tasks from either tool will sync to Codeusage.
28743
28751
  `));
28744
28752
  } catch (err) {
28745
28753
  console.log(source_default.red(`
@@ -28836,7 +28844,7 @@ Syncing ${bufferCount} buffered task(s)...
28836
28844
  });
28837
28845
 
28838
28846
  // src/commands/config.ts
28839
- var configCommand = new Command("config").description("View or modify CodeUsage configuration");
28847
+ var configCommand = new Command("config").description("View or modify Codeusage configuration");
28840
28848
  configCommand.command("show").description("Show current configuration").action(async () => {
28841
28849
  if (!isConfigured()) {
28842
28850
  console.log(source_default.yellow(`
@@ -28847,7 +28855,7 @@ Not configured. Run: codeusage init
28847
28855
  const config2 = getConfig();
28848
28856
  const enabledProviders = getProviders();
28849
28857
  console.log(source_default.bold(`
28850
- CodeUsage Configuration:
28858
+ Codeusage Configuration:
28851
28859
  `));
28852
28860
  const maskedKey = config2.workspace_key.slice(0, 10) + "••••••••••••";
28853
28861
  console.log(` Workspace Key: ${source_default.dim(maskedKey)}`);
@@ -29071,7 +29079,7 @@ function confirm(question) {
29071
29079
  });
29072
29080
  });
29073
29081
  }
29074
- var logoutCommand = new Command("logout").description("Disconnect from CodeUsage and remove local configuration").option("-f, --force", "Skip confirmation prompt").action(async (options) => {
29082
+ var logoutCommand = new Command("logout").description("Disconnect from Codeusage and remove local configuration").option("-f, --force", "Skip confirmation prompt").action(async (options) => {
29075
29083
  if (!isConfigured()) {
29076
29084
  console.log(source_default.dim(`
29077
29085
  Not configured. Nothing to logout from.
@@ -29113,6 +29121,664 @@ Cleaning up...`));
29113
29121
  var import_promises14 = __toESM(require("fs/promises"));
29114
29122
  var import_path4 = __toESM(require("path"));
29115
29123
  var import_os3 = __toESM(require("os"));
29124
+
29125
+ // ../../node_modules/.bun/diff@8.0.4/node_modules/diff/libesm/diff/base.js
29126
+ class Diff {
29127
+ diff(oldStr, newStr, options = {}) {
29128
+ let callback;
29129
+ if (typeof options === "function") {
29130
+ callback = options;
29131
+ options = {};
29132
+ } else if ("callback" in options) {
29133
+ callback = options.callback;
29134
+ }
29135
+ const oldString = this.castInput(oldStr, options);
29136
+ const newString = this.castInput(newStr, options);
29137
+ const oldTokens = this.removeEmpty(this.tokenize(oldString, options));
29138
+ const newTokens = this.removeEmpty(this.tokenize(newString, options));
29139
+ return this.diffWithOptionsObj(oldTokens, newTokens, options, callback);
29140
+ }
29141
+ diffWithOptionsObj(oldTokens, newTokens, options, callback) {
29142
+ var _a;
29143
+ const done = (value) => {
29144
+ value = this.postProcess(value, options);
29145
+ if (callback) {
29146
+ setTimeout(function() {
29147
+ callback(value);
29148
+ }, 0);
29149
+ return;
29150
+ } else {
29151
+ return value;
29152
+ }
29153
+ };
29154
+ const newLen = newTokens.length, oldLen = oldTokens.length;
29155
+ let editLength = 1;
29156
+ let maxEditLength = newLen + oldLen;
29157
+ if (options.maxEditLength != null) {
29158
+ maxEditLength = Math.min(maxEditLength, options.maxEditLength);
29159
+ }
29160
+ const maxExecutionTime = (_a = options.timeout) !== null && _a !== undefined ? _a : Infinity;
29161
+ const abortAfterTimestamp = Date.now() + maxExecutionTime;
29162
+ const bestPath = [{ oldPos: -1, lastComponent: undefined }];
29163
+ let newPos = this.extractCommon(bestPath[0], newTokens, oldTokens, 0, options);
29164
+ if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
29165
+ return done(this.buildValues(bestPath[0].lastComponent, newTokens, oldTokens));
29166
+ }
29167
+ let minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
29168
+ const execEditLength = () => {
29169
+ for (let diagonalPath = Math.max(minDiagonalToConsider, -editLength);diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
29170
+ let basePath;
29171
+ const removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
29172
+ if (removePath) {
29173
+ bestPath[diagonalPath - 1] = undefined;
29174
+ }
29175
+ let canAdd = false;
29176
+ if (addPath) {
29177
+ const addPathNewPos = addPath.oldPos - diagonalPath;
29178
+ canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
29179
+ }
29180
+ const canRemove = removePath && removePath.oldPos + 1 < oldLen;
29181
+ if (!canAdd && !canRemove) {
29182
+ bestPath[diagonalPath] = undefined;
29183
+ continue;
29184
+ }
29185
+ if (!canRemove || canAdd && removePath.oldPos < addPath.oldPos) {
29186
+ basePath = this.addToPath(addPath, true, false, 0, options);
29187
+ } else {
29188
+ basePath = this.addToPath(removePath, false, true, 1, options);
29189
+ }
29190
+ newPos = this.extractCommon(basePath, newTokens, oldTokens, diagonalPath, options);
29191
+ if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
29192
+ return done(this.buildValues(basePath.lastComponent, newTokens, oldTokens)) || true;
29193
+ } else {
29194
+ bestPath[diagonalPath] = basePath;
29195
+ if (basePath.oldPos + 1 >= oldLen) {
29196
+ maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
29197
+ }
29198
+ if (newPos + 1 >= newLen) {
29199
+ minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
29200
+ }
29201
+ }
29202
+ }
29203
+ editLength++;
29204
+ };
29205
+ if (callback) {
29206
+ (function exec() {
29207
+ setTimeout(function() {
29208
+ if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
29209
+ return callback(undefined);
29210
+ }
29211
+ if (!execEditLength()) {
29212
+ exec();
29213
+ }
29214
+ }, 0);
29215
+ })();
29216
+ } else {
29217
+ while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
29218
+ const ret = execEditLength();
29219
+ if (ret) {
29220
+ return ret;
29221
+ }
29222
+ }
29223
+ }
29224
+ }
29225
+ addToPath(path13, added, removed, oldPosInc, options) {
29226
+ const last = path13.lastComponent;
29227
+ if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
29228
+ return {
29229
+ oldPos: path13.oldPos + oldPosInc,
29230
+ lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
29231
+ };
29232
+ } else {
29233
+ return {
29234
+ oldPos: path13.oldPos + oldPosInc,
29235
+ lastComponent: { count: 1, added, removed, previousComponent: last }
29236
+ };
29237
+ }
29238
+ }
29239
+ extractCommon(basePath, newTokens, oldTokens, diagonalPath, options) {
29240
+ const newLen = newTokens.length, oldLen = oldTokens.length;
29241
+ let oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
29242
+ while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldTokens[oldPos + 1], newTokens[newPos + 1], options)) {
29243
+ newPos++;
29244
+ oldPos++;
29245
+ commonCount++;
29246
+ if (options.oneChangePerToken) {
29247
+ basePath.lastComponent = { count: 1, previousComponent: basePath.lastComponent, added: false, removed: false };
29248
+ }
29249
+ }
29250
+ if (commonCount && !options.oneChangePerToken) {
29251
+ basePath.lastComponent = { count: commonCount, previousComponent: basePath.lastComponent, added: false, removed: false };
29252
+ }
29253
+ basePath.oldPos = oldPos;
29254
+ return newPos;
29255
+ }
29256
+ equals(left, right, options) {
29257
+ if (options.comparator) {
29258
+ return options.comparator(left, right);
29259
+ } else {
29260
+ return left === right || !!options.ignoreCase && left.toLowerCase() === right.toLowerCase();
29261
+ }
29262
+ }
29263
+ removeEmpty(array) {
29264
+ const ret = [];
29265
+ for (let i2 = 0;i2 < array.length; i2++) {
29266
+ if (array[i2]) {
29267
+ ret.push(array[i2]);
29268
+ }
29269
+ }
29270
+ return ret;
29271
+ }
29272
+ castInput(value, options) {
29273
+ return value;
29274
+ }
29275
+ tokenize(value, options) {
29276
+ return Array.from(value);
29277
+ }
29278
+ join(chars) {
29279
+ return chars.join("");
29280
+ }
29281
+ postProcess(changeObjects, options) {
29282
+ return changeObjects;
29283
+ }
29284
+ get useLongestToken() {
29285
+ return false;
29286
+ }
29287
+ buildValues(lastComponent, newTokens, oldTokens) {
29288
+ const components = [];
29289
+ let nextComponent;
29290
+ while (lastComponent) {
29291
+ components.push(lastComponent);
29292
+ nextComponent = lastComponent.previousComponent;
29293
+ delete lastComponent.previousComponent;
29294
+ lastComponent = nextComponent;
29295
+ }
29296
+ components.reverse();
29297
+ const componentLen = components.length;
29298
+ let componentPos = 0, newPos = 0, oldPos = 0;
29299
+ for (;componentPos < componentLen; componentPos++) {
29300
+ const component = components[componentPos];
29301
+ if (!component.removed) {
29302
+ if (!component.added && this.useLongestToken) {
29303
+ let value = newTokens.slice(newPos, newPos + component.count);
29304
+ value = value.map(function(value2, i2) {
29305
+ const oldValue = oldTokens[oldPos + i2];
29306
+ return oldValue.length > value2.length ? oldValue : value2;
29307
+ });
29308
+ component.value = this.join(value);
29309
+ } else {
29310
+ component.value = this.join(newTokens.slice(newPos, newPos + component.count));
29311
+ }
29312
+ newPos += component.count;
29313
+ if (!component.added) {
29314
+ oldPos += component.count;
29315
+ }
29316
+ } else {
29317
+ component.value = this.join(oldTokens.slice(oldPos, oldPos + component.count));
29318
+ oldPos += component.count;
29319
+ }
29320
+ }
29321
+ return components;
29322
+ }
29323
+ }
29324
+
29325
+ // ../../node_modules/.bun/diff@8.0.4/node_modules/diff/libesm/diff/character.js
29326
+ class CharacterDiff extends Diff {
29327
+ }
29328
+ var characterDiff = new CharacterDiff;
29329
+
29330
+ // ../../node_modules/.bun/diff@8.0.4/node_modules/diff/libesm/util/string.js
29331
+ function longestCommonPrefix(str1, str2) {
29332
+ let i2;
29333
+ for (i2 = 0;i2 < str1.length && i2 < str2.length; i2++) {
29334
+ if (str1[i2] != str2[i2]) {
29335
+ return str1.slice(0, i2);
29336
+ }
29337
+ }
29338
+ return str1.slice(0, i2);
29339
+ }
29340
+ function longestCommonSuffix(str1, str2) {
29341
+ let i2;
29342
+ if (!str1 || !str2 || str1[str1.length - 1] != str2[str2.length - 1]) {
29343
+ return "";
29344
+ }
29345
+ for (i2 = 0;i2 < str1.length && i2 < str2.length; i2++) {
29346
+ if (str1[str1.length - (i2 + 1)] != str2[str2.length - (i2 + 1)]) {
29347
+ return str1.slice(-i2);
29348
+ }
29349
+ }
29350
+ return str1.slice(-i2);
29351
+ }
29352
+ function replacePrefix(string, oldPrefix, newPrefix) {
29353
+ if (string.slice(0, oldPrefix.length) != oldPrefix) {
29354
+ throw Error(`string ${JSON.stringify(string)} doesn't start with prefix ${JSON.stringify(oldPrefix)}; this is a bug`);
29355
+ }
29356
+ return newPrefix + string.slice(oldPrefix.length);
29357
+ }
29358
+ function replaceSuffix(string, oldSuffix, newSuffix) {
29359
+ if (!oldSuffix) {
29360
+ return string + newSuffix;
29361
+ }
29362
+ if (string.slice(-oldSuffix.length) != oldSuffix) {
29363
+ throw Error(`string ${JSON.stringify(string)} doesn't end with suffix ${JSON.stringify(oldSuffix)}; this is a bug`);
29364
+ }
29365
+ return string.slice(0, -oldSuffix.length) + newSuffix;
29366
+ }
29367
+ function removePrefix(string, oldPrefix) {
29368
+ return replacePrefix(string, oldPrefix, "");
29369
+ }
29370
+ function removeSuffix(string, oldSuffix) {
29371
+ return replaceSuffix(string, oldSuffix, "");
29372
+ }
29373
+ function maximumOverlap(string1, string2) {
29374
+ return string2.slice(0, overlapCount(string1, string2));
29375
+ }
29376
+ function overlapCount(a2, b) {
29377
+ let startA = 0;
29378
+ if (a2.length > b.length) {
29379
+ startA = a2.length - b.length;
29380
+ }
29381
+ let endB = b.length;
29382
+ if (a2.length < b.length) {
29383
+ endB = a2.length;
29384
+ }
29385
+ const map = Array(endB);
29386
+ let k = 0;
29387
+ map[0] = 0;
29388
+ for (let j = 1;j < endB; j++) {
29389
+ if (b[j] == b[k]) {
29390
+ map[j] = map[k];
29391
+ } else {
29392
+ map[j] = k;
29393
+ }
29394
+ while (k > 0 && b[j] != b[k]) {
29395
+ k = map[k];
29396
+ }
29397
+ if (b[j] == b[k]) {
29398
+ k++;
29399
+ }
29400
+ }
29401
+ k = 0;
29402
+ for (let i2 = startA;i2 < a2.length; i2++) {
29403
+ while (k > 0 && a2[i2] != b[k]) {
29404
+ k = map[k];
29405
+ }
29406
+ if (a2[i2] == b[k]) {
29407
+ k++;
29408
+ }
29409
+ }
29410
+ return k;
29411
+ }
29412
+ function segment(string, segmenter2) {
29413
+ const parts = [];
29414
+ for (const segmentObj of Array.from(segmenter2.segment(string))) {
29415
+ const segment2 = segmentObj.segment;
29416
+ if (parts.length && /\s/.test(parts[parts.length - 1]) && /\s/.test(segment2)) {
29417
+ parts[parts.length - 1] += segment2;
29418
+ } else {
29419
+ parts.push(segment2);
29420
+ }
29421
+ }
29422
+ return parts;
29423
+ }
29424
+ function trailingWs(string, segmenter2) {
29425
+ if (segmenter2) {
29426
+ return leadingAndTrailingWs(string, segmenter2)[1];
29427
+ }
29428
+ let i2;
29429
+ for (i2 = string.length - 1;i2 >= 0; i2--) {
29430
+ if (!string[i2].match(/\s/)) {
29431
+ break;
29432
+ }
29433
+ }
29434
+ return string.substring(i2 + 1);
29435
+ }
29436
+ function leadingWs(string, segmenter2) {
29437
+ if (segmenter2) {
29438
+ return leadingAndTrailingWs(string, segmenter2)[0];
29439
+ }
29440
+ const match = string.match(/^\s*/);
29441
+ return match ? match[0] : "";
29442
+ }
29443
+ function leadingAndTrailingWs(string, segmenter2) {
29444
+ if (!segmenter2) {
29445
+ return [leadingWs(string), trailingWs(string)];
29446
+ }
29447
+ if (segmenter2.resolvedOptions().granularity != "word") {
29448
+ throw new Error('The segmenter passed must have a granularity of "word"');
29449
+ }
29450
+ const segments = segment(string, segmenter2);
29451
+ const firstSeg = segments[0];
29452
+ const lastSeg = segments[segments.length - 1];
29453
+ const head = /\s/.test(firstSeg) ? firstSeg : "";
29454
+ const tail = /\s/.test(lastSeg) ? lastSeg : "";
29455
+ return [head, tail];
29456
+ }
29457
+
29458
+ // ../../node_modules/.bun/diff@8.0.4/node_modules/diff/libesm/diff/word.js
29459
+ var extendedWordChars = "a-zA-Z0-9_\\u{AD}\\u{C0}-\\u{D6}\\u{D8}-\\u{F6}\\u{F8}-\\u{2C6}\\u{2C8}-\\u{2D7}\\u{2DE}-\\u{2FF}\\u{1E00}-\\u{1EFF}";
29460
+ var tokenizeIncludingWhitespace = new RegExp(`[${extendedWordChars}]+|\\s+|[^${extendedWordChars}]`, "ug");
29461
+
29462
+ class WordDiff extends Diff {
29463
+ equals(left, right, options) {
29464
+ if (options.ignoreCase) {
29465
+ left = left.toLowerCase();
29466
+ right = right.toLowerCase();
29467
+ }
29468
+ return left.trim() === right.trim();
29469
+ }
29470
+ tokenize(value, options = {}) {
29471
+ let parts;
29472
+ if (options.intlSegmenter) {
29473
+ const segmenter2 = options.intlSegmenter;
29474
+ if (segmenter2.resolvedOptions().granularity != "word") {
29475
+ throw new Error('The segmenter passed must have a granularity of "word"');
29476
+ }
29477
+ parts = segment(value, segmenter2);
29478
+ } else {
29479
+ parts = value.match(tokenizeIncludingWhitespace) || [];
29480
+ }
29481
+ const tokens = [];
29482
+ let prevPart = null;
29483
+ parts.forEach((part) => {
29484
+ if (/\s/.test(part)) {
29485
+ if (prevPart == null) {
29486
+ tokens.push(part);
29487
+ } else {
29488
+ tokens.push(tokens.pop() + part);
29489
+ }
29490
+ } else if (prevPart != null && /\s/.test(prevPart)) {
29491
+ if (tokens[tokens.length - 1] == prevPart) {
29492
+ tokens.push(tokens.pop() + part);
29493
+ } else {
29494
+ tokens.push(prevPart + part);
29495
+ }
29496
+ } else {
29497
+ tokens.push(part);
29498
+ }
29499
+ prevPart = part;
29500
+ });
29501
+ return tokens;
29502
+ }
29503
+ join(tokens) {
29504
+ return tokens.map((token, i2) => {
29505
+ if (i2 == 0) {
29506
+ return token;
29507
+ } else {
29508
+ return token.replace(/^\s+/, "");
29509
+ }
29510
+ }).join("");
29511
+ }
29512
+ postProcess(changes, options) {
29513
+ if (!changes || options.oneChangePerToken) {
29514
+ return changes;
29515
+ }
29516
+ let lastKeep = null;
29517
+ let insertion = null;
29518
+ let deletion = null;
29519
+ changes.forEach((change) => {
29520
+ if (change.added) {
29521
+ insertion = change;
29522
+ } else if (change.removed) {
29523
+ deletion = change;
29524
+ } else {
29525
+ if (insertion || deletion) {
29526
+ dedupeWhitespaceInChangeObjects(lastKeep, deletion, insertion, change, options.intlSegmenter);
29527
+ }
29528
+ lastKeep = change;
29529
+ insertion = null;
29530
+ deletion = null;
29531
+ }
29532
+ });
29533
+ if (insertion || deletion) {
29534
+ dedupeWhitespaceInChangeObjects(lastKeep, deletion, insertion, null, options.intlSegmenter);
29535
+ }
29536
+ return changes;
29537
+ }
29538
+ }
29539
+ var wordDiff = new WordDiff;
29540
+ function dedupeWhitespaceInChangeObjects(startKeep, deletion, insertion, endKeep, segmenter2) {
29541
+ if (deletion && insertion) {
29542
+ const [oldWsPrefix, oldWsSuffix] = leadingAndTrailingWs(deletion.value, segmenter2);
29543
+ const [newWsPrefix, newWsSuffix] = leadingAndTrailingWs(insertion.value, segmenter2);
29544
+ if (startKeep) {
29545
+ const commonWsPrefix = longestCommonPrefix(oldWsPrefix, newWsPrefix);
29546
+ startKeep.value = replaceSuffix(startKeep.value, newWsPrefix, commonWsPrefix);
29547
+ deletion.value = removePrefix(deletion.value, commonWsPrefix);
29548
+ insertion.value = removePrefix(insertion.value, commonWsPrefix);
29549
+ }
29550
+ if (endKeep) {
29551
+ const commonWsSuffix = longestCommonSuffix(oldWsSuffix, newWsSuffix);
29552
+ endKeep.value = replacePrefix(endKeep.value, newWsSuffix, commonWsSuffix);
29553
+ deletion.value = removeSuffix(deletion.value, commonWsSuffix);
29554
+ insertion.value = removeSuffix(insertion.value, commonWsSuffix);
29555
+ }
29556
+ } else if (insertion) {
29557
+ if (startKeep) {
29558
+ const ws = leadingWs(insertion.value, segmenter2);
29559
+ insertion.value = insertion.value.substring(ws.length);
29560
+ }
29561
+ if (endKeep) {
29562
+ const ws = leadingWs(endKeep.value, segmenter2);
29563
+ endKeep.value = endKeep.value.substring(ws.length);
29564
+ }
29565
+ } else if (startKeep && endKeep) {
29566
+ const newWsFull = leadingWs(endKeep.value, segmenter2), [delWsStart, delWsEnd] = leadingAndTrailingWs(deletion.value, segmenter2);
29567
+ const newWsStart = longestCommonPrefix(newWsFull, delWsStart);
29568
+ deletion.value = removePrefix(deletion.value, newWsStart);
29569
+ const newWsEnd = longestCommonSuffix(removePrefix(newWsFull, newWsStart), delWsEnd);
29570
+ deletion.value = removeSuffix(deletion.value, newWsEnd);
29571
+ endKeep.value = replacePrefix(endKeep.value, newWsFull, newWsEnd);
29572
+ startKeep.value = replaceSuffix(startKeep.value, newWsFull, newWsFull.slice(0, newWsFull.length - newWsEnd.length));
29573
+ } else if (endKeep) {
29574
+ const endKeepWsPrefix = leadingWs(endKeep.value, segmenter2);
29575
+ const deletionWsSuffix = trailingWs(deletion.value, segmenter2);
29576
+ const overlap = maximumOverlap(deletionWsSuffix, endKeepWsPrefix);
29577
+ deletion.value = removeSuffix(deletion.value, overlap);
29578
+ } else if (startKeep) {
29579
+ const startKeepWsSuffix = trailingWs(startKeep.value, segmenter2);
29580
+ const deletionWsPrefix = leadingWs(deletion.value, segmenter2);
29581
+ const overlap = maximumOverlap(startKeepWsSuffix, deletionWsPrefix);
29582
+ deletion.value = removePrefix(deletion.value, overlap);
29583
+ }
29584
+ }
29585
+
29586
+ class WordsWithSpaceDiff extends Diff {
29587
+ tokenize(value) {
29588
+ const regex2 = new RegExp(`(\\r?\\n)|[${extendedWordChars}]+|[^\\S\\n\\r]+|[^${extendedWordChars}]`, "ug");
29589
+ return value.match(regex2) || [];
29590
+ }
29591
+ }
29592
+ var wordsWithSpaceDiff = new WordsWithSpaceDiff;
29593
+
29594
+ // ../../node_modules/.bun/diff@8.0.4/node_modules/diff/libesm/diff/line.js
29595
+ class LineDiff extends Diff {
29596
+ constructor() {
29597
+ super(...arguments);
29598
+ this.tokenize = tokenize;
29599
+ }
29600
+ equals(left, right, options) {
29601
+ if (options.ignoreWhitespace) {
29602
+ if (!options.newlineIsToken || !left.includes(`
29603
+ `)) {
29604
+ left = left.trim();
29605
+ }
29606
+ if (!options.newlineIsToken || !right.includes(`
29607
+ `)) {
29608
+ right = right.trim();
29609
+ }
29610
+ } else if (options.ignoreNewlineAtEof && !options.newlineIsToken) {
29611
+ if (left.endsWith(`
29612
+ `)) {
29613
+ left = left.slice(0, -1);
29614
+ }
29615
+ if (right.endsWith(`
29616
+ `)) {
29617
+ right = right.slice(0, -1);
29618
+ }
29619
+ }
29620
+ return super.equals(left, right, options);
29621
+ }
29622
+ }
29623
+ var lineDiff = new LineDiff;
29624
+ function diffLines(oldStr, newStr, options) {
29625
+ return lineDiff.diff(oldStr, newStr, options);
29626
+ }
29627
+ function tokenize(value, options) {
29628
+ if (options.stripTrailingCr) {
29629
+ value = value.replace(/\r\n/g, `
29630
+ `);
29631
+ }
29632
+ const retLines = [], linesAndNewlines = value.split(/(\n|\r\n)/);
29633
+ if (!linesAndNewlines[linesAndNewlines.length - 1]) {
29634
+ linesAndNewlines.pop();
29635
+ }
29636
+ for (let i2 = 0;i2 < linesAndNewlines.length; i2++) {
29637
+ const line = linesAndNewlines[i2];
29638
+ if (i2 % 2 && !options.newlineIsToken) {
29639
+ retLines[retLines.length - 1] += line;
29640
+ } else {
29641
+ retLines.push(line);
29642
+ }
29643
+ }
29644
+ return retLines;
29645
+ }
29646
+
29647
+ // ../../node_modules/.bun/diff@8.0.4/node_modules/diff/libesm/diff/sentence.js
29648
+ function isSentenceEndPunct(char) {
29649
+ return char == "." || char == "!" || char == "?";
29650
+ }
29651
+
29652
+ class SentenceDiff extends Diff {
29653
+ tokenize(value) {
29654
+ var _a;
29655
+ const result = [];
29656
+ let tokenStartI = 0;
29657
+ for (let i2 = 0;i2 < value.length; i2++) {
29658
+ if (i2 == value.length - 1) {
29659
+ result.push(value.slice(tokenStartI));
29660
+ break;
29661
+ }
29662
+ if (isSentenceEndPunct(value[i2]) && value[i2 + 1].match(/\s/)) {
29663
+ result.push(value.slice(tokenStartI, i2 + 1));
29664
+ i2 = tokenStartI = i2 + 1;
29665
+ while ((_a = value[i2 + 1]) === null || _a === undefined ? undefined : _a.match(/\s/)) {
29666
+ i2++;
29667
+ }
29668
+ result.push(value.slice(tokenStartI, i2 + 1));
29669
+ tokenStartI = i2 + 1;
29670
+ }
29671
+ }
29672
+ return result;
29673
+ }
29674
+ }
29675
+ var sentenceDiff = new SentenceDiff;
29676
+
29677
+ // ../../node_modules/.bun/diff@8.0.4/node_modules/diff/libesm/diff/css.js
29678
+ class CssDiff extends Diff {
29679
+ tokenize(value) {
29680
+ return value.split(/([{}:;,]|\s+)/);
29681
+ }
29682
+ }
29683
+ var cssDiff = new CssDiff;
29684
+
29685
+ // ../../node_modules/.bun/diff@8.0.4/node_modules/diff/libesm/diff/json.js
29686
+ class JsonDiff extends Diff {
29687
+ constructor() {
29688
+ super(...arguments);
29689
+ this.tokenize = tokenize;
29690
+ }
29691
+ get useLongestToken() {
29692
+ return true;
29693
+ }
29694
+ castInput(value, options) {
29695
+ const { undefinedReplacement, stringifyReplacer = (k, v) => typeof v === "undefined" ? undefinedReplacement : v } = options;
29696
+ return typeof value === "string" ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), null, " ");
29697
+ }
29698
+ equals(left, right, options) {
29699
+ return super.equals(left.replace(/,([\r\n])/g, "$1"), right.replace(/,([\r\n])/g, "$1"), options);
29700
+ }
29701
+ }
29702
+ var jsonDiff = new JsonDiff;
29703
+ function canonicalize(obj, stack, replacementStack, replacer, key) {
29704
+ stack = stack || [];
29705
+ replacementStack = replacementStack || [];
29706
+ if (replacer) {
29707
+ obj = replacer(key === undefined ? "" : key, obj);
29708
+ }
29709
+ let i2;
29710
+ for (i2 = 0;i2 < stack.length; i2 += 1) {
29711
+ if (stack[i2] === obj) {
29712
+ return replacementStack[i2];
29713
+ }
29714
+ }
29715
+ let canonicalizedObj;
29716
+ if (Object.prototype.toString.call(obj) === "[object Array]") {
29717
+ stack.push(obj);
29718
+ canonicalizedObj = new Array(obj.length);
29719
+ replacementStack.push(canonicalizedObj);
29720
+ for (i2 = 0;i2 < obj.length; i2 += 1) {
29721
+ canonicalizedObj[i2] = canonicalize(obj[i2], stack, replacementStack, replacer, String(i2));
29722
+ }
29723
+ stack.pop();
29724
+ replacementStack.pop();
29725
+ return canonicalizedObj;
29726
+ }
29727
+ if (obj && obj.toJSON) {
29728
+ obj = obj.toJSON();
29729
+ }
29730
+ if (typeof obj === "object" && obj !== null) {
29731
+ stack.push(obj);
29732
+ canonicalizedObj = {};
29733
+ replacementStack.push(canonicalizedObj);
29734
+ const sortedKeys = [];
29735
+ let key2;
29736
+ for (key2 in obj) {
29737
+ if (Object.prototype.hasOwnProperty.call(obj, key2)) {
29738
+ sortedKeys.push(key2);
29739
+ }
29740
+ }
29741
+ sortedKeys.sort();
29742
+ for (i2 = 0;i2 < sortedKeys.length; i2 += 1) {
29743
+ key2 = sortedKeys[i2];
29744
+ canonicalizedObj[key2] = canonicalize(obj[key2], stack, replacementStack, replacer, key2);
29745
+ }
29746
+ stack.pop();
29747
+ replacementStack.pop();
29748
+ } else {
29749
+ canonicalizedObj = obj;
29750
+ }
29751
+ return canonicalizedObj;
29752
+ }
29753
+
29754
+ // ../../node_modules/.bun/diff@8.0.4/node_modules/diff/libesm/diff/array.js
29755
+ class ArrayDiff extends Diff {
29756
+ tokenize(value) {
29757
+ return value.slice();
29758
+ }
29759
+ join(value) {
29760
+ return value;
29761
+ }
29762
+ removeEmpty(value) {
29763
+ return value;
29764
+ }
29765
+ }
29766
+ var arrayDiff = new ArrayDiff;
29767
+
29768
+ // src/lib/session-log.ts
29769
+ function calculateLineDiff(oldString, newString) {
29770
+ const changes = diffLines(oldString, newString);
29771
+ let additions = 0;
29772
+ let deletions = 0;
29773
+ for (const change of changes) {
29774
+ if (change.added) {
29775
+ additions += change.count ?? 0;
29776
+ } else if (change.removed) {
29777
+ deletions += change.count ?? 0;
29778
+ }
29779
+ }
29780
+ return { additions, deletions };
29781
+ }
29116
29782
  async function getGitRoot(cwd) {
29117
29783
  try {
29118
29784
  const { stdout } = await execa("git", ["rev-parse", "--show-toplevel"], {
@@ -29207,14 +29873,12 @@ async function parseClaudeCodeSession(cwd) {
29207
29873
  if (filePath && typeof filePath === "string") {
29208
29874
  const oldString = block.input?.old_string || "";
29209
29875
  const newString = block.input?.new_string || "";
29210
- const deletions = oldString.split(`
29211
- `).length;
29212
- const additions = newString.split(`
29213
- `).length;
29214
- const existing = fileChanges.get(filePath) || { additions: 0, deletions: 0 };
29876
+ const { additions, deletions } = calculateLineDiff(oldString, newString);
29877
+ const existing = fileChanges.get(filePath) || { additions: 0, deletions: 0, change_type: "modified" };
29215
29878
  fileChanges.set(filePath, {
29216
29879
  additions: existing.additions + additions,
29217
- deletions: existing.deletions + deletions
29880
+ deletions: existing.deletions + deletions,
29881
+ change_type: existing.change_type
29218
29882
  });
29219
29883
  }
29220
29884
  } else if (block.name === "Write") {
@@ -29223,11 +29887,20 @@ async function parseClaudeCodeSession(cwd) {
29223
29887
  const content2 = block.input?.content || "";
29224
29888
  const additions = content2.split(`
29225
29889
  `).length;
29226
- const existing = fileChanges.get(filePath) || { additions: 0, deletions: 0 };
29227
- fileChanges.set(filePath, {
29228
- additions: existing.additions + additions,
29229
- deletions: existing.deletions
29230
- });
29890
+ const existing = fileChanges.get(filePath);
29891
+ if (existing) {
29892
+ fileChanges.set(filePath, {
29893
+ additions: existing.additions + additions,
29894
+ deletions: existing.deletions,
29895
+ change_type: existing.change_type
29896
+ });
29897
+ } else {
29898
+ fileChanges.set(filePath, {
29899
+ additions,
29900
+ deletions: 0,
29901
+ change_type: "created"
29902
+ });
29903
+ }
29231
29904
  }
29232
29905
  }
29233
29906
  }
@@ -29241,11 +29914,15 @@ async function parseClaudeCodeSession(cwd) {
29241
29914
  count: count2
29242
29915
  }));
29243
29916
  const duration_sec = startTime && endTime ? Math.round((endTime - startTime) / 1000) : 0;
29244
- const files_changed_details = Array.from(fileChanges.entries()).map(([path14, stats]) => ({
29245
- path: path14,
29917
+ const files_changed_details = Array.from(fileChanges.entries()).map(([filePath, stats]) => ({
29918
+ path: filePath,
29246
29919
  additions: stats.additions,
29247
- deletions: stats.deletions
29920
+ deletions: stats.deletions,
29921
+ change_type: stats.change_type
29248
29922
  }));
29923
+ const files_created = files_changed_details.filter((f) => f.change_type === "created").length;
29924
+ const files_modified = files_changed_details.filter((f) => f.change_type === "modified").length;
29925
+ const files_deleted = files_changed_details.filter((f) => f.change_type === "deleted").length;
29249
29926
  return {
29250
29927
  session_id: sessionId,
29251
29928
  input_tokens: inputTokens,
@@ -29255,6 +29932,9 @@ async function parseClaudeCodeSession(cwd) {
29255
29932
  tools_used,
29256
29933
  tool_counts: toolCounts,
29257
29934
  files_changed: fileChanges.size,
29935
+ files_created,
29936
+ files_modified,
29937
+ files_deleted,
29258
29938
  files_changed_details,
29259
29939
  duration_sec,
29260
29940
  start_time: startTime,
@@ -29306,16 +29986,10 @@ async function findLatestCodexSession() {
29306
29986
  }
29307
29987
  return null;
29308
29988
  }
29309
- function extractCodexSessionId(filename) {
29310
- const basename = import_path4.default.basename(filename, ".jsonl");
29311
- const match = basename.match(/rollout-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-(.+)/);
29312
- return match ? match[1] : basename;
29313
- }
29314
- async function parseCodexSession(cwd) {
29989
+ async function parseCodexSession(_cwd) {
29315
29990
  const sessionFile = await findLatestCodexSession();
29316
29991
  if (!sessionFile)
29317
29992
  return null;
29318
- const sessionId = extractCodexSessionId(sessionFile);
29319
29993
  try {
29320
29994
  const content = await import_promises14.default.readFile(sessionFile, "utf-8");
29321
29995
  const lines = content.trim().split(`
@@ -29343,7 +30017,7 @@ async function parseCodexSession(cwd) {
29343
30017
  startIndex: i2,
29344
30018
  startTime: new Date(entry.timestamp).getTime()
29345
30019
  };
29346
- } else if (payload.type === "task_complete" && payload.turn_id && currentTurn) {
30020
+ } else if (payload.type === "task_complete" && payload.turn_id && currentTurn && currentTurn.turnId) {
29347
30021
  if (currentTurn.turnId === payload.turn_id) {
29348
30022
  turns.push({
29349
30023
  turnId: currentTurn.turnId,
@@ -29411,12 +30085,13 @@ async function parseCodexSession(cwd) {
29411
30085
  const updateMatches = patchContent.matchAll(/\*\*\* Update File: ([^\n]+)/g);
29412
30086
  for (const match of updateMatches) {
29413
30087
  const filePath = match[1].trim();
29414
- const existing = fileChanges.get(filePath) || { additions: 0, deletions: 0 };
30088
+ const existing = fileChanges.get(filePath) || { additions: 0, deletions: 0, change_type: "modified" };
29415
30089
  const additions = (patchContent.match(/^\+[^+]/gm) || []).length;
29416
30090
  const deletions = (patchContent.match(/^-[^-]/gm) || []).length;
29417
30091
  fileChanges.set(filePath, {
29418
30092
  additions: existing.additions + additions,
29419
- deletions: existing.deletions + deletions
30093
+ deletions: existing.deletions + deletions,
30094
+ change_type: existing.change_type
29420
30095
  });
29421
30096
  }
29422
30097
  const addMatches = patchContent.matchAll(/\*\*\* Add File: ([^\n]+)/g);
@@ -29424,7 +30099,14 @@ async function parseCodexSession(cwd) {
29424
30099
  const filePath = match[1].trim();
29425
30100
  const additions = patchContent.split(`
29426
30101
  `).length || 1;
29427
- fileChanges.set(filePath, { additions, deletions: 0 });
30102
+ fileChanges.set(filePath, { additions, deletions: 0, change_type: "created" });
30103
+ }
30104
+ const deleteMatches = patchContent.matchAll(/\*\*\* Delete File: ([^\n]+)/g);
30105
+ for (const match of deleteMatches) {
30106
+ const filePath = match[1].trim();
30107
+ const existing = fileChanges.get(filePath);
30108
+ const deletions = existing?.additions || 0;
30109
+ fileChanges.set(filePath, { additions: 0, deletions, change_type: "deleted" });
29428
30110
  }
29429
30111
  }
29430
30112
  }
@@ -29448,8 +30130,12 @@ async function parseCodexSession(cwd) {
29448
30130
  const files_changed_details = Array.from(fileChanges.entries()).map(([filePath, stats]) => ({
29449
30131
  path: filePath,
29450
30132
  additions: stats.additions,
29451
- deletions: stats.deletions
30133
+ deletions: stats.deletions,
30134
+ change_type: stats.change_type
29452
30135
  }));
30136
+ const files_created = files_changed_details.filter((f) => f.change_type === "created").length;
30137
+ const files_modified = files_changed_details.filter((f) => f.change_type === "modified").length;
30138
+ const files_deleted = files_changed_details.filter((f) => f.change_type === "deleted").length;
29453
30139
  return {
29454
30140
  session_id: lastTurn.turnId,
29455
30141
  input_tokens: inputTokens,
@@ -29459,6 +30145,9 @@ async function parseCodexSession(cwd) {
29459
30145
  tools_used,
29460
30146
  tool_counts: toolCounts,
29461
30147
  files_changed: fileChanges.size,
30148
+ files_created,
30149
+ files_modified,
30150
+ files_deleted,
29462
30151
  files_changed_details,
29463
30152
  duration_sec,
29464
30153
  start_time: lastTurn.startTime,
@@ -29525,6 +30214,9 @@ function calculateDelta(current, previous) {
29525
30214
  output_tokens: current.output_tokens,
29526
30215
  cache_tokens: current.cache_tokens,
29527
30216
  files_changed: current.files_changed,
30217
+ files_created: current.files_created,
30218
+ files_modified: current.files_modified,
30219
+ files_deleted: current.files_deleted,
29528
30220
  files_changed_details: current.files_changed_details,
29529
30221
  tools_used: Object.entries(current.tool_counts).map(([name, count2]) => ({
29530
30222
  name,
@@ -29553,17 +30245,23 @@ function calculateDelta(current, previous) {
29553
30245
  deltaFileDetails.push({
29554
30246
  path: file.path,
29555
30247
  additions: deltaAdditions,
29556
- deletions: deltaDeletions
30248
+ deletions: deltaDeletions,
30249
+ change_type: file.change_type
29557
30250
  });
29558
30251
  }
29559
30252
  }
29560
30253
  }
29561
- const filesChangedDelta = deltaFileDetails.length;
30254
+ const filesCreatedDelta = deltaFileDetails.filter((f) => f.change_type === "created").length;
30255
+ const filesModifiedDelta = deltaFileDetails.filter((f) => f.change_type === "modified").length;
30256
+ const filesDeletedDelta = deltaFileDetails.filter((f) => f.change_type === "deleted").length;
29562
30257
  return {
29563
30258
  input_tokens: Math.max(0, current.input_tokens - previous.input_tokens),
29564
30259
  output_tokens: Math.max(0, current.output_tokens - previous.output_tokens),
29565
30260
  cache_tokens: Math.max(0, current.cache_tokens - previous.cache_tokens),
29566
- files_changed: filesChangedDelta,
30261
+ files_changed: deltaFileDetails.length,
30262
+ files_created: filesCreatedDelta,
30263
+ files_modified: filesModifiedDelta,
30264
+ files_deleted: filesDeletedDelta,
29567
30265
  files_changed_details: deltaFileDetails,
29568
30266
  tools_used: Object.entries(deltaToolCounts).map(([name, count2]) => ({
29569
30267
  name,
@@ -29611,6 +30309,9 @@ var hookStopCommand = new Command("stop").description("Handle AI coding tool sto
29611
30309
  output_tokens: session.output_tokens,
29612
30310
  cache_tokens: session.cache_tokens,
29613
30311
  files_changed: session.files_changed,
30312
+ files_created: session.files_created,
30313
+ files_modified: session.files_modified,
30314
+ files_deleted: session.files_deleted,
29614
30315
  files_changed_details: session.files_changed_details,
29615
30316
  tool_counts: session.tool_counts
29616
30317
  }, previousState);
@@ -29635,6 +30336,9 @@ var hookStopCommand = new Command("stop").description("Handle AI coding tool sto
29635
30336
  cache_tokens: delta.cache_tokens,
29636
30337
  cost_usd: cost,
29637
30338
  files_changed: delta.files_changed,
30339
+ files_created: delta.files_created,
30340
+ files_modified: delta.files_modified,
30341
+ files_deleted: delta.files_deleted,
29638
30342
  files_changed_details: delta.files_changed_details,
29639
30343
  tools_used: delta.tools_used,
29640
30344
  task_duration_sec: taskDuration,
@@ -29654,7 +30358,7 @@ var hookStopCommand = new Command("stop").description("Handle AI coding tool sto
29654
30358
  console.log(`Cache: ${source_default.green(payload.cache_tokens.toLocaleString())} tokens`);
29655
30359
  }
29656
30360
  console.log(`Cost: ${source_default.green(`~$${payload.cost_usd.toFixed(4)}`)}`);
29657
- console.log(`Files changed: ${source_default.yellow(payload.files_changed)}`);
30361
+ console.log(`Files: ${source_default.yellow(payload.files_changed)} changed (${source_default.green(`+${payload.files_created}`)} created, ${source_default.blue(`~${payload.files_modified}`)} modified, ${source_default.red(`-${payload.files_deleted}`)} deleted)`);
29658
30362
  console.log(`Duration: ${source_default.yellow(payload.task_duration_sec)}s`);
29659
30363
  if (payload.tools_used.length > 0) {
29660
30364
  console.log(`Tools: ${payload.tools_used.map((t) => `${t.name}(${t.count})`).join(", ")}`);
@@ -29676,7 +30380,11 @@ var hookStopCommand = new Command("stop").description("Handle AI coding tool sto
29676
30380
  console.log(source_default.green("✓ Task synced"));
29677
30381
  const file_stats = {};
29678
30382
  for (const file of session.files_changed_details) {
29679
- file_stats[file.path] = { additions: file.additions, deletions: file.deletions };
30383
+ file_stats[file.path] = {
30384
+ additions: file.additions,
30385
+ deletions: file.deletions,
30386
+ change_type: file.change_type
30387
+ };
29680
30388
  }
29681
30389
  const newState = {
29682
30390
  session_id: session.session_id,
@@ -29684,6 +30392,9 @@ var hookStopCommand = new Command("stop").description("Handle AI coding tool sto
29684
30392
  output_tokens: session.output_tokens,
29685
30393
  cache_tokens: session.cache_tokens,
29686
30394
  files_changed: session.files_changed,
30395
+ files_created: session.files_created,
30396
+ files_modified: session.files_modified,
30397
+ files_deleted: session.files_deleted,
29687
30398
  file_stats,
29688
30399
  tool_counts: session.tool_counts,
29689
30400
  last_timestamp: session.end_time || Date.now(),
@@ -29698,7 +30409,11 @@ var hookStopCommand = new Command("stop").description("Handle AI coding tool sto
29698
30409
  await bufferTask(payload);
29699
30410
  const bufferedFileStats = {};
29700
30411
  for (const file of session.files_changed_details) {
29701
- bufferedFileStats[file.path] = { additions: file.additions, deletions: file.deletions };
30412
+ bufferedFileStats[file.path] = {
30413
+ additions: file.additions,
30414
+ deletions: file.deletions,
30415
+ change_type: file.change_type
30416
+ };
29702
30417
  }
29703
30418
  const newState = {
29704
30419
  session_id: session.session_id,
@@ -29706,6 +30421,9 @@ var hookStopCommand = new Command("stop").description("Handle AI coding tool sto
29706
30421
  output_tokens: session.output_tokens,
29707
30422
  cache_tokens: session.cache_tokens,
29708
30423
  files_changed: session.files_changed,
30424
+ files_created: session.files_created,
30425
+ files_modified: session.files_modified,
30426
+ files_deleted: session.files_deleted,
29709
30427
  file_stats: bufferedFileStats,
29710
30428
  tool_counts: session.tool_counts,
29711
30429
  last_timestamp: session.end_time || Date.now(),
@@ -29723,7 +30441,7 @@ var hookNotificationCommand = new Command("notification").description("Handle Cl
29723
30441
 
29724
30442
  // src/index.ts
29725
30443
  var program2 = new Command;
29726
- program2.name("codeusage").description("CLI for CodeUsage - AI coding tool intelligence platform").version("0.1.8");
30444
+ program2.name("codeusage").description("CLI for Codeusage - AI coding tool intelligence platform").version("0.1.8");
29727
30445
  program2.addCommand(initCommand);
29728
30446
  program2.addCommand(statusCommand);
29729
30447
  program2.addCommand(projectCommand);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "codeusage-cli",
3
- "version": "0.1.10",
4
- "description": "CLI for CodeUsage - AI coding tool intelligence platform",
3
+ "version": "0.1.11",
4
+ "description": "CLI for Codeusage - AI coding tool intelligence platform",
5
5
  "author": "Hashim",
6
6
  "license": "MIT",
7
7
  "type": "module",
@@ -25,12 +25,14 @@
25
25
  "chalk": "^5.4.1",
26
26
  "commander": "^13.1.0",
27
27
  "conf": "^13.1.0",
28
+ "diff": "^8.0.4",
28
29
  "execa": "^9.5.2",
29
30
  "ora": "^8.2.0",
30
31
  "zod": "^3.25.76"
31
32
  },
32
33
  "devDependencies": {
33
34
  "@codeusage/shared": "workspace:*",
35
+ "@types/diff": "^8.0.0",
34
36
  "@types/node": "^20.19.0",
35
37
  "tsup": "^8.5.0",
36
38
  "tsx": "^4.19.0",