@osfactory/har 0.64.2 → 0.64.3

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 (2) hide show
  1. package/dist/index.js +66 -17
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4774,7 +4774,7 @@ var init_schema = __esm({
4774
4774
  attemptId: WorkAttemptIdSchema.optional()
4775
4775
  }).passthrough();
4776
4776
  AgentTrajectoryRecordSchema = AgentTrajectoryRecordV1Schema;
4777
- USAGE_HARVEST_VERSION = 1;
4777
+ USAGE_HARVEST_VERSION = 2;
4778
4778
  PRE_DEDUPE_HARVEST_VERSION = 0;
4779
4779
  AgentSessionUsageSchema = external_exports.object({
4780
4780
  sessionKey: external_exports.string().min(1),
@@ -28243,10 +28243,8 @@ function toGenaiPricesUsage(totals) {
28243
28243
  const rawInput = num(totals.tokensInput);
28244
28244
  const cacheRead = num(totals.tokensCacheRead);
28245
28245
  const cacheWrite = num(totals.tokensCacheCreation);
28246
- const uncached = rawInput >= cacheRead ? rawInput - cacheRead : rawInput;
28247
- const inclusiveInput = uncached + cacheRead + cacheWrite;
28248
28246
  return {
28249
- input_tokens: inclusiveInput,
28247
+ input_tokens: rawInput + cacheRead + cacheWrite,
28250
28248
  output_tokens: num(totals.tokensOutput),
28251
28249
  cache_read_tokens: cacheRead,
28252
28250
  cache_write_tokens: cacheWrite
@@ -32314,6 +32312,33 @@ var init_workspace_path_match = __esm({
32314
32312
  }
32315
32313
  });
32316
32314
 
32315
+ // src/core/usage-harvest/record-time-range.ts
32316
+ function recordTimestamp(record2) {
32317
+ if (!record2 || typeof record2 !== "object") return null;
32318
+ const payload = record2;
32319
+ const raw = typeof payload.timestamp === "string" ? payload.timestamp : payload.ts;
32320
+ if (typeof raw !== "string") return null;
32321
+ const ms = Date.parse(raw);
32322
+ return Number.isFinite(ms) ? ms : null;
32323
+ }
32324
+ function recordTimeRange(records) {
32325
+ let first = null;
32326
+ let last = null;
32327
+ for (const record2 of records) {
32328
+ const ms = recordTimestamp(record2);
32329
+ if (ms === null) continue;
32330
+ if (first === null || ms < first) first = ms;
32331
+ if (last === null || ms > last) last = ms;
32332
+ }
32333
+ if (first === null || last === null) return null;
32334
+ return { firstAt: new Date(first).toISOString(), lastAt: new Date(last).toISOString() };
32335
+ }
32336
+ var init_record_time_range = __esm({
32337
+ "src/core/usage-harvest/record-time-range.ts"() {
32338
+ "use strict";
32339
+ }
32340
+ });
32341
+
32317
32342
  // src/core/usage-harvest/claude.ts
32318
32343
  function claudeProjectsRoot() {
32319
32344
  return process.env.HAR_CLAUDE_PROJECTS_DIR ? path25.resolve(process.env.HAR_CLAUDE_PROJECTS_DIR) : path25.join(os11.homedir(), ".claude", "projects");
@@ -32340,8 +32365,12 @@ function extractClaudeUsageFromRecords(records) {
32340
32365
  let tokensOutput = 0;
32341
32366
  let tokensCacheRead = 0;
32342
32367
  let tokensCacheCreation = 0;
32343
- let costUsd = null;
32344
32368
  const modelBreakdown = {};
32369
+ let resultInput = 0;
32370
+ let resultOutput = 0;
32371
+ let resultCacheRead = 0;
32372
+ let resultCacheCreation = 0;
32373
+ let resultCostUsd = null;
32345
32374
  const billed = /* @__PURE__ */ new Map();
32346
32375
  const unkeyed = [];
32347
32376
  for (const record2 of records) {
@@ -32349,11 +32378,13 @@ function extractClaudeUsageFromRecords(records) {
32349
32378
  const payload = record2;
32350
32379
  if (payload.type === "result") {
32351
32380
  const usage2 = payload.usage ?? {};
32352
- tokensInput = Number(usage2.input_tokens ?? 0) + Number(usage2.cache_read_input_tokens ?? 0);
32353
- tokensOutput = Number(usage2.output_tokens ?? 0);
32354
- tokensCacheRead = Number(usage2.cache_read_input_tokens ?? 0);
32355
- tokensCacheCreation = Number(usage2.cache_creation_input_tokens ?? 0);
32356
- if (payload.total_cost_usd != null) costUsd = Number(payload.total_cost_usd);
32381
+ resultInput += Number(usage2.input_tokens ?? 0);
32382
+ resultOutput += Number(usage2.output_tokens ?? 0);
32383
+ resultCacheRead += Number(usage2.cache_read_input_tokens ?? 0);
32384
+ resultCacheCreation += Number(usage2.cache_creation_input_tokens ?? 0);
32385
+ if (payload.total_cost_usd != null) {
32386
+ resultCostUsd = (resultCostUsd ?? 0) + Number(payload.total_cost_usd);
32387
+ }
32357
32388
  }
32358
32389
  const message = payload.message;
32359
32390
  const nestedUsage = payload.usage ?? message?.usage;
@@ -32388,7 +32419,21 @@ function extractClaudeUsageFromRecords(records) {
32388
32419
  totals.tokensTotal += i + o + cr + cc;
32389
32420
  }
32390
32421
  }
32391
- return { tokensInput, tokensOutput, tokensCacheRead, tokensCacheCreation, costUsd, modelBreakdown };
32422
+ const resultTotal = resultInput + resultOutput + resultCacheRead + resultCacheCreation;
32423
+ if (resultTotal > 0) {
32424
+ tokensInput = resultInput;
32425
+ tokensOutput = resultOutput;
32426
+ tokensCacheRead = resultCacheRead;
32427
+ tokensCacheCreation = resultCacheCreation;
32428
+ }
32429
+ return {
32430
+ tokensInput,
32431
+ tokensOutput,
32432
+ tokensCacheRead,
32433
+ tokensCacheCreation,
32434
+ costUsd: resultCostUsd,
32435
+ modelBreakdown
32436
+ };
32392
32437
  }
32393
32438
  function findMatchingClaudeTranscripts(slot) {
32394
32439
  const primaryTargets = [slot.workDir, slot.worktreePath].filter(Boolean);
@@ -32485,11 +32530,13 @@ function harvestClaudeUsage(slot) {
32485
32530
  });
32486
32531
  const own = matches.filter((match) => match.primary);
32487
32532
  const usable = own.length > 0 ? own : matches;
32488
- const usage2 = extractClaudeUsageFromRecords(usable.flatMap((match) => match.records));
32533
+ const records = usable.flatMap((match) => match.records);
32534
+ const usage2 = extractClaudeUsageFromRecords(records);
32489
32535
  if (usage2.tokensInput + usage2.tokensOutput + usage2.tokensCacheRead === 0 && (usage2.costUsd == null || usage2.costUsd === 0)) {
32490
32536
  return null;
32491
32537
  }
32492
32538
  const now = (/* @__PURE__ */ new Date()).toISOString();
32539
+ const seen = recordTimeRange(records);
32493
32540
  const tokensTotal = usage2.tokensInput + usage2.tokensOutput + usage2.tokensCacheRead + usage2.tokensCacheCreation;
32494
32541
  return {
32495
32542
  sessionKey,
@@ -32507,8 +32554,8 @@ function harvestClaudeUsage(slot) {
32507
32554
  ...Object.keys(usage2.modelBreakdown).length > 0 ? { modelBreakdown: usage2.modelBreakdown } : {},
32508
32555
  sources: ["harvest"],
32509
32556
  harvestVersion: USAGE_HARVEST_VERSION,
32510
- firstSeenAt: slot.sessionCreatedAt ?? now,
32511
- lastSeenAt: now
32557
+ firstSeenAt: seen?.firstAt ?? slot.sessionCreatedAt ?? now,
32558
+ lastSeenAt: seen?.lastAt ?? now
32512
32559
  };
32513
32560
  }
32514
32561
  function harvestClaudeEvents(slot) {
@@ -32534,6 +32581,7 @@ var init_claude = __esm({
32534
32581
  init_telemetry_config();
32535
32582
  init_telemetry_env();
32536
32583
  init_workspace_path_match();
32584
+ init_record_time_range();
32537
32585
  }
32538
32586
  });
32539
32587
 
@@ -32594,7 +32642,7 @@ function extractCodexTokens(records) {
32594
32642
  tokensCacheRead = Math.max(tokensCacheRead, Number(payload.cached_token_count ?? 0));
32595
32643
  }
32596
32644
  }
32597
- return { tokensInput, tokensOutput, tokensCacheRead, cwd };
32645
+ return { tokensInput, tokensOutput, tokensCacheRead, cwd, seen: recordTimeRange(records) };
32598
32646
  }
32599
32647
  function harvestCodexUsage(slot) {
32600
32648
  const primaryTargets = [slot.workDir, slot.worktreePath].filter(Boolean);
@@ -32650,8 +32698,8 @@ function harvestCodexUsage(slot) {
32650
32698
  costUsd: null,
32651
32699
  sources: ["harvest"],
32652
32700
  harvestVersion: USAGE_HARVEST_VERSION,
32653
- firstSeenAt: slot.sessionCreatedAt ?? now,
32654
- lastSeenAt: now
32701
+ firstSeenAt: best.seen?.firstAt ?? slot.sessionCreatedAt ?? now,
32702
+ lastSeenAt: best.seen?.lastAt ?? now
32655
32703
  };
32656
32704
  }
32657
32705
  var fs24, os12, path26;
@@ -32664,6 +32712,7 @@ var init_codex = __esm({
32664
32712
  init_schema2();
32665
32713
  init_telemetry_env();
32666
32714
  init_workspace_path_match();
32715
+ init_record_time_range();
32667
32716
  }
32668
32717
  });
32669
32718
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osfactory/har",
3
- "version": "0.64.2",
3
+ "version": "0.64.3",
4
4
  "description": "HAR: open agent harness CLI and MCP server for coding agents, isolated worktrees, and software-factory workflows",
5
5
  "keywords": [
6
6
  "har",