@polka-codes/cli 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 +117 -12
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -16534,12 +16534,12 @@ var init_memory = __esm(() => {
16534
16534
  memoryConfigSchema = exports_external.object({
16535
16535
  enabled: exports_external.boolean().optional().default(true),
16536
16536
  type: exports_external.enum(["sqlite", "memory"]).optional().default("sqlite"),
16537
- path: exports_external.string().optional().default("~/.config/polka-codes/memory.sqlite")
16537
+ path: exports_external.string().optional().default("~/.config/polkacodes/memory/memory.sqlite")
16538
16538
  }).strict().optional();
16539
16539
  DEFAULT_MEMORY_CONFIG = {
16540
16540
  enabled: true,
16541
16541
  type: "sqlite",
16542
- path: "~/.config/polka-codes/memory.sqlite"
16542
+ path: "~/.config/polkacodes/memory/memory.sqlite"
16543
16543
  };
16544
16544
  });
16545
16545
 
@@ -25517,6 +25517,7 @@ var init_tools2 = __esm(() => {
25517
25517
  // ../core/src/UsageMeter.ts
25518
25518
  class UsageMeter {
25519
25519
  #totals = { input: 0, output: 0, cachedRead: 0, cost: 0, messageCount: 0 };
25520
+ #providerMetadataEntries = [];
25520
25521
  #modelInfos;
25521
25522
  #maxMessages;
25522
25523
  #maxCost;
@@ -25598,8 +25599,17 @@ class UsageMeter {
25598
25599
  this.#totals.cachedRead += result.cachedRead || 0;
25599
25600
  this.#totals.cost += result.cost || 0;
25600
25601
  this.#totals.messageCount += 1;
25602
+ if (resp.providerMetadata && Object.keys(resp.providerMetadata).length > 0) {
25603
+ const providerKey = Object.keys(resp.providerMetadata)[0];
25604
+ this.#providerMetadataEntries.push({
25605
+ provider: providerKey || llm.provider,
25606
+ model: llm.modelId,
25607
+ metadata: resp.providerMetadata[providerKey] || resp.providerMetadata,
25608
+ timestamp: Date.now()
25609
+ });
25610
+ }
25601
25611
  }
25602
- setUsage(newUsage) {
25612
+ setUsage(newUsage, options = {}) {
25603
25613
  if (newUsage.input != null)
25604
25614
  this.#totals.input = newUsage.input;
25605
25615
  if (newUsage.output != null)
@@ -25610,12 +25620,16 @@ class UsageMeter {
25610
25620
  this.#totals.cost = newUsage.cost;
25611
25621
  if (newUsage.messageCount != null)
25612
25622
  this.#totals.messageCount = newUsage.messageCount;
25623
+ if (options.clearMetadata) {
25624
+ this.#providerMetadataEntries = [];
25625
+ }
25613
25626
  }
25614
25627
  incrementMessageCount(n = 1) {
25615
25628
  this.#totals.messageCount += n;
25616
25629
  }
25617
25630
  resetUsage() {
25618
25631
  this.#totals = { input: 0, output: 0, cachedRead: 0, cost: 0, messageCount: 0 };
25632
+ this.#providerMetadataEntries = [];
25619
25633
  }
25620
25634
  isLimitExceeded() {
25621
25635
  const messageCount = this.#maxMessages > 0 && this.#totals.messageCount >= this.#maxMessages;
@@ -25637,6 +25651,37 @@ class UsageMeter {
25637
25651
  get usage() {
25638
25652
  return { ...this.#totals };
25639
25653
  }
25654
+ get providerMetadata() {
25655
+ return [...this.#providerMetadataEntries];
25656
+ }
25657
+ get cacheStats() {
25658
+ const entries = this.#providerMetadataEntries;
25659
+ const totalRequests = entries.length;
25660
+ let totalCachedTokens = 0;
25661
+ let requestsWithCache = 0;
25662
+ for (const entry of entries) {
25663
+ const metadata = entry.metadata;
25664
+ if (typeof metadata !== "object" || metadata === null) {
25665
+ continue;
25666
+ }
25667
+ const cachedTokens = metadata.cachedPromptTokens ?? metadata.cacheReadTokens ?? metadata.prompt_cache_hit_tokens ?? 0;
25668
+ if (cachedTokens > 0) {
25669
+ totalCachedTokens += cachedTokens;
25670
+ requestsWithCache++;
25671
+ }
25672
+ }
25673
+ const cacheHitRate = totalRequests > 0 ? requestsWithCache / totalRequests : 0;
25674
+ return {
25675
+ totalCachedTokens,
25676
+ totalRequests,
25677
+ requestsWithCache,
25678
+ cacheHitRate,
25679
+ entries: [...this.#providerMetadataEntries]
25680
+ };
25681
+ }
25682
+ clearProviderMetadata() {
25683
+ this.#providerMetadataEntries = [];
25684
+ }
25640
25685
  merge(other) {
25641
25686
  const otherUsage = other.usage;
25642
25687
  this.#totals.input += otherUsage.input;
@@ -25644,6 +25689,7 @@ class UsageMeter {
25644
25689
  this.#totals.cachedRead += otherUsage.cachedRead;
25645
25690
  this.#totals.cost += otherUsage.cost;
25646
25691
  this.#totals.messageCount += otherUsage.messageCount;
25692
+ this.#providerMetadataEntries.push(...other.providerMetadata);
25647
25693
  }
25648
25694
  getUsageText() {
25649
25695
  const u = this.usage;
@@ -75767,16 +75813,64 @@ var require_sql_wasm = __commonJS((exports, module) => {
75767
75813
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
75768
75814
  import { randomUUID } from "node:crypto";
75769
75815
  import { existsSync as existsSync4 } from "node:fs";
75770
- import { mkdir as mkdir2, readFile as readFile4, rename as rename2, writeFile as writeFile2 } from "node:fs/promises";
75771
- import { dirname as dirname3, resolve as resolve5 } from "node:path";
75816
+ import { mkdir as mkdir2, readdir as readdir2, readFile as readFile4, rename as rename2, unlink as unlink2, writeFile as writeFile2 } from "node:fs/promises";
75817
+ import { basename as basename2, dirname as dirname3, resolve as resolve5 } from "node:path";
75772
75818
  import { fileURLToPath } from "node:url";
75773
75819
 
75774
75820
  class FileLock {
75775
75821
  lockfilePath;
75776
75822
  static LOCK_TIMEOUT = 30000;
75823
+ static CLEANUP_AGE = 600000;
75824
+ static lastCleanupTime = 0;
75825
+ static CLEANUP_THROTTLE = 60000;
75777
75826
  constructor(dbPath) {
75778
75827
  this.lockfilePath = `${dbPath}.lock`;
75779
75828
  }
75829
+ static resetCleanupThrottle() {
75830
+ FileLock.lastCleanupTime = 0;
75831
+ }
75832
+ static async cleanupOldLockFiles(dbPath, maxAge = FileLock.CLEANUP_AGE, force = false) {
75833
+ const now2 = Date.now();
75834
+ if (!force && now2 - FileLock.lastCleanupTime < FileLock.CLEANUP_THROTTLE) {
75835
+ return;
75836
+ }
75837
+ FileLock.lastCleanupTime = now2;
75838
+ try {
75839
+ const lockDir = dirname3(dbPath);
75840
+ const dbBaseName = basename2(dbPath);
75841
+ const files = await readdir2(lockDir);
75842
+ const now3 = Date.now();
75843
+ let cleanedCount = 0;
75844
+ for (const file2 of files) {
75845
+ if (!file2.startsWith(`${dbBaseName}.lock.`)) {
75846
+ continue;
75847
+ }
75848
+ const match = file2.match(/\.lock\.(released|stale|invalid|corrupt)\.(\d+)$/);
75849
+ if (!match) {
75850
+ continue;
75851
+ }
75852
+ const filePath = resolve5(lockDir, file2);
75853
+ const timestamp = Number.parseInt(match[2], 10);
75854
+ const age = now3 - timestamp;
75855
+ if (age > maxAge) {
75856
+ try {
75857
+ await unlink2(filePath);
75858
+ cleanedCount++;
75859
+ } catch (error48) {
75860
+ const errorCode = error48?.code;
75861
+ if (errorCode !== "ENOENT") {
75862
+ console.warn(`[FileLock] Failed to delete old lock file ${file2}: ${error48 instanceof Error ? error48.message : String(error48)}`);
75863
+ }
75864
+ }
75865
+ }
75866
+ }
75867
+ if (cleanedCount > 0) {
75868
+ console.log(`[FileLock] Cleaned up ${cleanedCount} old lock file(s) (older than ${maxAge}ms)`);
75869
+ }
75870
+ } catch (error48) {
75871
+ console.debug(`[FileLock] Cleanup encountered an error: ${error48 instanceof Error ? error48.message : String(error48)}`);
75872
+ }
75873
+ }
75780
75874
  async acquire(retries = 10, delay2 = 100) {
75781
75875
  for (let i2 = 0;i2 < retries; i2++) {
75782
75876
  try {
@@ -75827,6 +75921,8 @@ class FileLock {
75827
75921
  async release() {
75828
75922
  try {
75829
75923
  await rename2(this.lockfilePath, `${this.lockfilePath}.released.${Date.now()}`);
75924
+ const dbPath = this.lockfilePath.slice(0, -5);
75925
+ FileLock.cleanupOldLockFiles(dbPath).catch(() => {});
75830
75926
  } catch (error48) {
75831
75927
  const errorCode = error48.code;
75832
75928
  if (errorCode !== "ENOENT") {
@@ -75910,6 +76006,9 @@ var init_sqlite_memory_store = __esm(() => {
75910
76006
  inTransaction = false;
75911
76007
  transactionMutex = new ReentrantMutex;
75912
76008
  fileLock;
76009
+ static resetCleanupThrottle() {
76010
+ FileLock.resetCleanupThrottle();
76011
+ }
75913
76012
  getDbPath() {
75914
76013
  return this.config.path || DEFAULT_MEMORY_CONFIG.path;
75915
76014
  }
@@ -75946,6 +76045,7 @@ var init_sqlite_memory_store = __esm(() => {
75946
76045
  if (!existsSync4(dir)) {
75947
76046
  await mkdir2(dir, { recursive: true, mode: 448 });
75948
76047
  }
76048
+ FileLock.cleanupOldLockFiles(dbPath).catch(() => {});
75949
76049
  let dbData;
75950
76050
  if (existsSync4(dbPath)) {
75951
76051
  const lock = this.getFileLock();
@@ -94025,9 +94125,11 @@ function createGitReadBinaryFile(commit2) {
94025
94125
  }
94026
94126
  };
94027
94127
  }
94028
- const result = await provider3.executeCommand(`git show ${quotedCommit}:${quotedUrl}`, false);
94128
+ const isWindows2 = process.platform === "win32";
94129
+ const command = isWindows2 ? `cmd /c "git show ${quotedCommit}:${quotedUrl} | base64 -w 0 2>&1"` : `sh -c "git show ${quotedCommit}:${quotedUrl} | base64 2>&1"`;
94130
+ const result = await provider3.executeCommand(command, false);
94029
94131
  if (result.exitCode === 0) {
94030
- const base64Data = Buffer.from(result.stdout, "binary").toString("base64");
94132
+ const base64Data = result.stdout.replace(/\n/g, "");
94031
94133
  return {
94032
94134
  success: true,
94033
94135
  message: {
@@ -94043,11 +94145,13 @@ function createGitReadBinaryFile(commit2) {
94043
94145
  }
94044
94146
  };
94045
94147
  } else {
94148
+ const isBase64Error = result.stderr.includes("not recognized") || result.stderr.includes("command not found") || result.stderr.includes("base64");
94149
+ const errorMessage = isBase64Error ? `Failed to read binary file: base64 command not found. On Windows, ensure Git Bash or Unix tools are installed and in PATH.` : `Failed to read binary file: ${result.stderr}`;
94046
94150
  return {
94047
94151
  success: false,
94048
94152
  message: {
94049
94153
  type: "error-text",
94050
- value: `Failed to read binary file: ${result.stderr}`
94154
+ value: errorMessage
94051
94155
  }
94052
94156
  };
94053
94157
  }
@@ -94441,7 +94545,7 @@ var reviewWorkflow = async (input, context) => {
94441
94545
  return { overview: "No changes to review.", specificReviews: [] };
94442
94546
  }
94443
94547
  const targetCommit = extractTargetCommit(range, pr2);
94444
- const isRange = range && range.includes("..");
94548
+ const isRange = range?.includes("..");
94445
94549
  const finalChangeInfo = targetCommit && !isRange ? { ...changeInfo, targetCommit } : changeInfo;
94446
94550
  const fileTools = targetCommit && !isRange ? createGitAwareTools(targetCommit) : { readFile: readFile_default, listFiles: listFiles_default, readBinaryFile: readBinaryFile_default };
94447
94551
  const reviewTools = targetCommit && !isRange ? [fileTools.readFile, fileTools.readBinaryFile, fileTools.listFiles, createGitAwareDiff(targetCommit)] : [readFile_default, readBinaryFile_default, searchFiles_default, listFiles_default, gitDiff_default];
@@ -112236,7 +112340,7 @@ var {
112236
112340
  Help
112237
112341
  } = import__.default;
112238
112342
  // package.json
112239
- var version = "0.9.91";
112343
+ var version = "0.9.93";
112240
112344
 
112241
112345
  // src/commands/agent.ts
112242
112346
  init_src();
@@ -120933,8 +121037,8 @@ async function memoryStatus() {
120933
121037
  const stats = await store.getStats();
120934
121038
  const globalConfigPath = getGlobalConfigPath();
120935
121039
  const config4 = await loadConfigAtPath(globalConfigPath);
120936
- const memoryConfig = config4?.memory || { path: "~/.config/polka-codes/memory.sqlite" };
120937
- const dbPath = resolveHomePath(memoryConfig.path || "~/.config/polka-codes/memory.sqlite");
121040
+ const memoryConfig = config4?.memory || { path: "~/.config/polkacodes/memory/memory.sqlite" };
121041
+ const dbPath = resolveHomePath(memoryConfig.path || "~/.config/polkacodes/memory/memory.sqlite");
120938
121042
  console.log(`
120939
121043
  Memory Store Status:`);
120940
121044
  console.log("─".repeat(80));
@@ -121353,6 +121457,7 @@ var reviewCommand = new Command("review").description("Review a GitHub pull requ
121353
121457
  const workflowOpts = getBaseWorkflowOptions(command);
121354
121458
  if (json2) {
121355
121459
  workflowOpts.interactive = false;
121460
+ workflowOpts.silent = true;
121356
121461
  }
121357
121462
  const { verbose } = workflowOpts;
121358
121463
  const logger = createLogger({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polka-codes/cli",
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",
@@ -29,8 +29,8 @@
29
29
  "@inquirer/prompts": "^8.1.0",
30
30
  "@modelcontextprotocol/sdk": "^1.25.1",
31
31
  "@openrouter/ai-sdk-provider": "^1.5.4",
32
- "@polka-codes/cli-shared": "0.9.89",
33
- "@polka-codes/core": "0.9.89",
32
+ "@polka-codes/cli-shared": "0.9.91",
33
+ "@polka-codes/core": "0.9.91",
34
34
  "ai": "^5.0.117",
35
35
  "chalk": "^5.6.2",
36
36
  "commander": "^14.0.2",