@osfactory/har 0.64.0 → 0.64.1

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 +44 -40
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -32313,6 +32313,8 @@ function extractClaudeUsageFromRecords(records) {
32313
32313
  let tokensCacheCreation = 0;
32314
32314
  let costUsd = null;
32315
32315
  const modelBreakdown = {};
32316
+ const billed = /* @__PURE__ */ new Map();
32317
+ const unkeyed = [];
32316
32318
  for (const record2 of records) {
32317
32319
  if (!record2 || typeof record2 !== "object") continue;
32318
32320
  const payload = record2;
@@ -32327,29 +32329,34 @@ function extractClaudeUsageFromRecords(records) {
32327
32329
  const message = payload.message;
32328
32330
  const nestedUsage = payload.usage ?? message?.usage;
32329
32331
  if (nestedUsage && payload.type !== "result") {
32330
- const i = Number(nestedUsage.input_tokens ?? 0);
32331
- const o = Number(nestedUsage.output_tokens ?? 0);
32332
- const cr = Number(nestedUsage.cache_read_input_tokens ?? 0);
32333
- const cc = Number(nestedUsage.cache_creation_input_tokens ?? 0);
32334
- tokensInput += i;
32335
- tokensOutput += o;
32336
- tokensCacheRead += cr;
32337
- tokensCacheCreation += cc;
32338
32332
  const model = typeof message?.model === "string" ? message.model : void 0;
32339
- if (model && model !== "<synthetic>") {
32340
- const totals = modelBreakdown[model] ??= {
32341
- tokensInput: 0,
32342
- tokensOutput: 0,
32343
- tokensCacheRead: 0,
32344
- tokensCacheCreation: 0,
32345
- tokensTotal: 0
32346
- };
32347
- totals.tokensInput += i;
32348
- totals.tokensOutput += o;
32349
- totals.tokensCacheRead += cr;
32350
- totals.tokensCacheCreation += cc;
32351
- totals.tokensTotal += i + o + cr + cc;
32352
- }
32333
+ const entry = { usage: nestedUsage, model };
32334
+ if (typeof message?.id === "string" && message.id) billed.set(message.id, entry);
32335
+ else unkeyed.push(entry);
32336
+ }
32337
+ }
32338
+ for (const { usage: usage2, model } of [...billed.values(), ...unkeyed]) {
32339
+ const i = Number(usage2.input_tokens ?? 0);
32340
+ const o = Number(usage2.output_tokens ?? 0);
32341
+ const cr = Number(usage2.cache_read_input_tokens ?? 0);
32342
+ const cc = Number(usage2.cache_creation_input_tokens ?? 0);
32343
+ tokensInput += i;
32344
+ tokensOutput += o;
32345
+ tokensCacheRead += cr;
32346
+ tokensCacheCreation += cc;
32347
+ if (model && model !== "<synthetic>") {
32348
+ const totals = modelBreakdown[model] ??= {
32349
+ tokensInput: 0,
32350
+ tokensOutput: 0,
32351
+ tokensCacheRead: 0,
32352
+ tokensCacheCreation: 0,
32353
+ tokensTotal: 0
32354
+ };
32355
+ totals.tokensInput += i;
32356
+ totals.tokensOutput += o;
32357
+ totals.tokensCacheRead += cr;
32358
+ totals.tokensCacheCreation += cc;
32359
+ totals.tokensTotal += i + o + cr + cc;
32353
32360
  }
32354
32361
  }
32355
32362
  return { tokensInput, tokensOutput, tokensCacheRead, tokensCacheCreation, costUsd, modelBreakdown };
@@ -32388,8 +32395,9 @@ function findMatchingClaudeTranscripts(slot) {
32388
32395
  }
32389
32396
  }
32390
32397
  }
32391
- if (primaryHit) primary.push({ filePath, records, mtimeMs: stat.mtimeMs });
32392
- else if (fallbackHit) fallback.push({ filePath, records, mtimeMs: stat.mtimeMs });
32398
+ if (primaryHit) primary.push({ filePath, records, mtimeMs: stat.mtimeMs, primary: true });
32399
+ else if (fallbackHit)
32400
+ fallback.push({ filePath, records, mtimeMs: stat.mtimeMs, primary: false });
32393
32401
  }
32394
32402
  }
32395
32403
  primary.sort((a, b2) => b2.mtimeMs - a.mtimeMs);
@@ -32446,18 +32454,14 @@ function harvestClaudeUsage(slot) {
32446
32454
  suffix: slot.suffix,
32447
32455
  createdAt: slot.sessionCreatedAt
32448
32456
  });
32449
- let best = null;
32450
- for (const match of matches) {
32451
- const usage2 = extractClaudeUsageFromRecords(match.records);
32452
- if (usage2.tokensInput + usage2.tokensOutput + usage2.tokensCacheRead === 0 && (usage2.costUsd == null || usage2.costUsd === 0)) {
32453
- continue;
32454
- }
32455
- best = usage2;
32456
- break;
32457
+ const own = matches.filter((match) => match.primary);
32458
+ const usable = own.length > 0 ? own : matches;
32459
+ const usage2 = extractClaudeUsageFromRecords(usable.flatMap((match) => match.records));
32460
+ if (usage2.tokensInput + usage2.tokensOutput + usage2.tokensCacheRead === 0 && (usage2.costUsd == null || usage2.costUsd === 0)) {
32461
+ return null;
32457
32462
  }
32458
- if (!best) return null;
32459
32463
  const now = (/* @__PURE__ */ new Date()).toISOString();
32460
- const tokensTotal = best.tokensInput + best.tokensOutput + best.tokensCacheRead + best.tokensCacheCreation;
32464
+ const tokensTotal = usage2.tokensInput + usage2.tokensOutput + usage2.tokensCacheRead + usage2.tokensCacheCreation;
32461
32465
  return {
32462
32466
  sessionKey,
32463
32467
  agentId: slot.agentId,
@@ -32465,13 +32469,13 @@ function harvestClaudeUsage(slot) {
32465
32469
  workDir: slot.workDir,
32466
32470
  branch: slot.branch,
32467
32471
  suffix: slot.suffix,
32468
- tokensInput: best.tokensInput,
32469
- tokensOutput: best.tokensOutput,
32470
- tokensCacheRead: best.tokensCacheRead,
32471
- tokensCacheCreation: best.tokensCacheCreation,
32472
+ tokensInput: usage2.tokensInput,
32473
+ tokensOutput: usage2.tokensOutput,
32474
+ tokensCacheRead: usage2.tokensCacheRead,
32475
+ tokensCacheCreation: usage2.tokensCacheCreation,
32472
32476
  tokensTotal,
32473
- costUsd: best.costUsd,
32474
- ...Object.keys(best.modelBreakdown).length > 0 ? { modelBreakdown: best.modelBreakdown } : {},
32477
+ costUsd: usage2.costUsd,
32478
+ ...Object.keys(usage2.modelBreakdown).length > 0 ? { modelBreakdown: usage2.modelBreakdown } : {},
32475
32479
  sources: ["harvest"],
32476
32480
  firstSeenAt: slot.sessionCreatedAt ?? now,
32477
32481
  lastSeenAt: now
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osfactory/har",
3
- "version": "0.64.0",
3
+ "version": "0.64.1",
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",