@polka-codes/cli-shared 0.9.91 → 0.9.93

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 +105 -5
  2. package/package.json +4 -3
package/dist/index.js CHANGED
@@ -50959,12 +50959,12 @@ var toolConfigSchema = exports_external.union([
50959
50959
  var memoryConfigSchema = exports_external.object({
50960
50960
  enabled: exports_external.boolean().optional().default(true),
50961
50961
  type: exports_external.enum(["sqlite", "memory"]).optional().default("sqlite"),
50962
- path: exports_external.string().optional().default("~/.config/polka-codes/memory.sqlite")
50962
+ path: exports_external.string().optional().default("~/.config/polkacodes/memory/memory.sqlite")
50963
50963
  }).strict().optional();
50964
50964
  var DEFAULT_MEMORY_CONFIG = {
50965
50965
  enabled: true,
50966
50966
  type: "sqlite",
50967
- path: "~/.config/polka-codes/memory.sqlite"
50967
+ path: "~/.config/polkacodes/memory/memory.sqlite"
50968
50968
  };
50969
50969
  function resolveHomePath(path) {
50970
50970
  if (path.startsWith("~")) {
@@ -52333,6 +52333,7 @@ var writeToFile_default = {
52333
52333
  // ../core/src/UsageMeter.ts
52334
52334
  class UsageMeter {
52335
52335
  #totals = { input: 0, output: 0, cachedRead: 0, cost: 0, messageCount: 0 };
52336
+ #providerMetadataEntries = [];
52336
52337
  #modelInfos;
52337
52338
  #maxMessages;
52338
52339
  #maxCost;
@@ -52414,8 +52415,17 @@ class UsageMeter {
52414
52415
  this.#totals.cachedRead += result.cachedRead || 0;
52415
52416
  this.#totals.cost += result.cost || 0;
52416
52417
  this.#totals.messageCount += 1;
52418
+ if (resp.providerMetadata && Object.keys(resp.providerMetadata).length > 0) {
52419
+ const providerKey = Object.keys(resp.providerMetadata)[0];
52420
+ this.#providerMetadataEntries.push({
52421
+ provider: providerKey || llm.provider,
52422
+ model: llm.modelId,
52423
+ metadata: resp.providerMetadata[providerKey] || resp.providerMetadata,
52424
+ timestamp: Date.now()
52425
+ });
52426
+ }
52417
52427
  }
52418
- setUsage(newUsage) {
52428
+ setUsage(newUsage, options = {}) {
52419
52429
  if (newUsage.input != null)
52420
52430
  this.#totals.input = newUsage.input;
52421
52431
  if (newUsage.output != null)
@@ -52426,12 +52436,16 @@ class UsageMeter {
52426
52436
  this.#totals.cost = newUsage.cost;
52427
52437
  if (newUsage.messageCount != null)
52428
52438
  this.#totals.messageCount = newUsage.messageCount;
52439
+ if (options.clearMetadata) {
52440
+ this.#providerMetadataEntries = [];
52441
+ }
52429
52442
  }
52430
52443
  incrementMessageCount(n = 1) {
52431
52444
  this.#totals.messageCount += n;
52432
52445
  }
52433
52446
  resetUsage() {
52434
52447
  this.#totals = { input: 0, output: 0, cachedRead: 0, cost: 0, messageCount: 0 };
52448
+ this.#providerMetadataEntries = [];
52435
52449
  }
52436
52450
  isLimitExceeded() {
52437
52451
  const messageCount = this.#maxMessages > 0 && this.#totals.messageCount >= this.#maxMessages;
@@ -52453,6 +52467,37 @@ class UsageMeter {
52453
52467
  get usage() {
52454
52468
  return { ...this.#totals };
52455
52469
  }
52470
+ get providerMetadata() {
52471
+ return [...this.#providerMetadataEntries];
52472
+ }
52473
+ get cacheStats() {
52474
+ const entries = this.#providerMetadataEntries;
52475
+ const totalRequests = entries.length;
52476
+ let totalCachedTokens = 0;
52477
+ let requestsWithCache = 0;
52478
+ for (const entry of entries) {
52479
+ const metadata = entry.metadata;
52480
+ if (typeof metadata !== "object" || metadata === null) {
52481
+ continue;
52482
+ }
52483
+ const cachedTokens = metadata.cachedPromptTokens ?? metadata.cacheReadTokens ?? metadata.prompt_cache_hit_tokens ?? 0;
52484
+ if (cachedTokens > 0) {
52485
+ totalCachedTokens += cachedTokens;
52486
+ requestsWithCache++;
52487
+ }
52488
+ }
52489
+ const cacheHitRate = totalRequests > 0 ? requestsWithCache / totalRequests : 0;
52490
+ return {
52491
+ totalCachedTokens,
52492
+ totalRequests,
52493
+ requestsWithCache,
52494
+ cacheHitRate,
52495
+ entries: [...this.#providerMetadataEntries]
52496
+ };
52497
+ }
52498
+ clearProviderMetadata() {
52499
+ this.#providerMetadataEntries = [];
52500
+ }
52456
52501
  merge(other) {
52457
52502
  const otherUsage = other.usage;
52458
52503
  this.#totals.input += otherUsage.input;
@@ -52460,6 +52505,7 @@ class UsageMeter {
52460
52505
  this.#totals.cachedRead += otherUsage.cachedRead;
52461
52506
  this.#totals.cost += otherUsage.cost;
52462
52507
  this.#totals.messageCount += otherUsage.messageCount;
52508
+ this.#providerMetadataEntries.push(...other.providerMetadata);
52463
52509
  }
52464
52510
  getUsageText() {
52465
52511
  const u = this.usage;
@@ -67431,17 +67477,65 @@ ${content}`;
67431
67477
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
67432
67478
  import { randomUUID } from "node:crypto";
67433
67479
  import { existsSync as existsSync3 } from "node:fs";
67434
- import { mkdir as mkdir2, readFile as readFile3, rename as rename2, writeFile as writeFile2 } from "node:fs/promises";
67435
- import { dirname as dirname3, resolve as resolve5 } from "node:path";
67480
+ import { mkdir as mkdir2, readdir, readFile as readFile3, rename as rename2, unlink as unlink2, writeFile as writeFile2 } from "node:fs/promises";
67481
+ import { basename as basename2, dirname as dirname3, resolve as resolve5 } from "node:path";
67436
67482
  import { fileURLToPath } from "node:url";
67437
67483
  var import_sql = __toESM(require_sql_wasm(), 1);
67438
67484
 
67439
67485
  class FileLock {
67440
67486
  lockfilePath;
67441
67487
  static LOCK_TIMEOUT = 30000;
67488
+ static CLEANUP_AGE = 600000;
67489
+ static lastCleanupTime = 0;
67490
+ static CLEANUP_THROTTLE = 60000;
67442
67491
  constructor(dbPath) {
67443
67492
  this.lockfilePath = `${dbPath}.lock`;
67444
67493
  }
67494
+ static resetCleanupThrottle() {
67495
+ FileLock.lastCleanupTime = 0;
67496
+ }
67497
+ static async cleanupOldLockFiles(dbPath, maxAge = FileLock.CLEANUP_AGE, force = false) {
67498
+ const now = Date.now();
67499
+ if (!force && now - FileLock.lastCleanupTime < FileLock.CLEANUP_THROTTLE) {
67500
+ return;
67501
+ }
67502
+ FileLock.lastCleanupTime = now;
67503
+ try {
67504
+ const lockDir = dirname3(dbPath);
67505
+ const dbBaseName = basename2(dbPath);
67506
+ const files = await readdir(lockDir);
67507
+ const now2 = Date.now();
67508
+ let cleanedCount = 0;
67509
+ for (const file2 of files) {
67510
+ if (!file2.startsWith(`${dbBaseName}.lock.`)) {
67511
+ continue;
67512
+ }
67513
+ const match = file2.match(/\.lock\.(released|stale|invalid|corrupt)\.(\d+)$/);
67514
+ if (!match) {
67515
+ continue;
67516
+ }
67517
+ const filePath = resolve5(lockDir, file2);
67518
+ const timestamp = Number.parseInt(match[2], 10);
67519
+ const age = now2 - timestamp;
67520
+ if (age > maxAge) {
67521
+ try {
67522
+ await unlink2(filePath);
67523
+ cleanedCount++;
67524
+ } catch (error48) {
67525
+ const errorCode = error48?.code;
67526
+ if (errorCode !== "ENOENT") {
67527
+ console.warn(`[FileLock] Failed to delete old lock file ${file2}: ${error48 instanceof Error ? error48.message : String(error48)}`);
67528
+ }
67529
+ }
67530
+ }
67531
+ }
67532
+ if (cleanedCount > 0) {
67533
+ console.log(`[FileLock] Cleaned up ${cleanedCount} old lock file(s) (older than ${maxAge}ms)`);
67534
+ }
67535
+ } catch (error48) {
67536
+ console.debug(`[FileLock] Cleanup encountered an error: ${error48 instanceof Error ? error48.message : String(error48)}`);
67537
+ }
67538
+ }
67445
67539
  async acquire(retries = 10, delay2 = 100) {
67446
67540
  for (let i2 = 0;i2 < retries; i2++) {
67447
67541
  try {
@@ -67492,6 +67586,8 @@ class FileLock {
67492
67586
  async release() {
67493
67587
  try {
67494
67588
  await rename2(this.lockfilePath, `${this.lockfilePath}.released.${Date.now()}`);
67589
+ const dbPath = this.lockfilePath.slice(0, -5);
67590
+ FileLock.cleanupOldLockFiles(dbPath).catch(() => {});
67495
67591
  } catch (error48) {
67496
67592
  const errorCode = error48.code;
67497
67593
  if (errorCode !== "ENOENT") {
@@ -67574,6 +67670,9 @@ class SQLiteMemoryStore {
67574
67670
  inTransaction = false;
67575
67671
  transactionMutex = new ReentrantMutex;
67576
67672
  fileLock;
67673
+ static resetCleanupThrottle() {
67674
+ FileLock.resetCleanupThrottle();
67675
+ }
67577
67676
  getDbPath() {
67578
67677
  return this.config.path || DEFAULT_MEMORY_CONFIG.path;
67579
67678
  }
@@ -67610,6 +67709,7 @@ class SQLiteMemoryStore {
67610
67709
  if (!existsSync3(dir)) {
67611
67710
  await mkdir2(dir, { recursive: true, mode: 448 });
67612
67711
  }
67712
+ FileLock.cleanupOldLockFiles(dbPath).catch(() => {});
67613
67713
  let dbData;
67614
67714
  if (existsSync3(dbPath)) {
67615
67715
  const lock = this.getFileLock();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polka-codes/cli-shared",
3
- "version": "0.9.91",
3
+ "version": "0.9.93",
4
4
  "license": "AGPL-3.0",
5
5
  "author": "github@polka.codes",
6
6
  "type": "module",
@@ -21,7 +21,7 @@
21
21
  "@ai-sdk/provider": "^2.0.1",
22
22
  "@ai-sdk/provider-utils": "^3.0.20",
23
23
  "@inquirer/prompts": "^8.1.0",
24
- "@polka-codes/core": "0.9.89",
24
+ "@polka-codes/core": "0.9.91",
25
25
  "ai": "^5.0.117",
26
26
  "chalk": "^5.6.2",
27
27
  "ignore": "^7.0.5",
@@ -33,6 +33,7 @@
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/lodash-es": "^4.17.12",
36
- "@types/mime-types": "^3.0.1"
36
+ "@types/mime-types": "^3.0.1",
37
+ "@types/sql.js": "^1.4.9"
37
38
  }
38
39
  }