qodewk 0.8.0 → 0.9.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.cjs +221 -135
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -1153,8 +1153,8 @@ var require_command = __commonJS({
1153
1153
  "use strict";
1154
1154
  var EventEmitter2 = require("events").EventEmitter;
1155
1155
  var childProcess = require("child_process");
1156
- var path12 = require("path");
1157
- var fs11 = require("fs");
1156
+ var path13 = require("path");
1157
+ var fs12 = require("fs");
1158
1158
  var process2 = require("process");
1159
1159
  var { Argument: Argument2, humanReadableArgName } = require_argument();
1160
1160
  var { CommanderError: CommanderError2 } = require_error();
@@ -2135,7 +2135,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2135
2135
  * @param {string} subcommandName
2136
2136
  */
2137
2137
  _checkForMissingExecutable(executableFile, executableDir, subcommandName) {
2138
- if (fs11.existsSync(executableFile)) return;
2138
+ if (fs12.existsSync(executableFile)) return;
2139
2139
  const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
2140
2140
  const executableMissing = `'${executableFile}' does not exist
2141
2141
  - if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
@@ -2153,11 +2153,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
2153
2153
  let launchWithNode = false;
2154
2154
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
2155
2155
  function findFile(baseDir, baseName) {
2156
- const localBin = path12.resolve(baseDir, baseName);
2157
- if (fs11.existsSync(localBin)) return localBin;
2158
- if (sourceExt.includes(path12.extname(baseName))) return void 0;
2156
+ const localBin = path13.resolve(baseDir, baseName);
2157
+ if (fs12.existsSync(localBin)) return localBin;
2158
+ if (sourceExt.includes(path13.extname(baseName))) return void 0;
2159
2159
  const foundExt = sourceExt.find(
2160
- (ext) => fs11.existsSync(`${localBin}${ext}`)
2160
+ (ext) => fs12.existsSync(`${localBin}${ext}`)
2161
2161
  );
2162
2162
  if (foundExt) return `${localBin}${foundExt}`;
2163
2163
  return void 0;
@@ -2169,21 +2169,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
2169
2169
  if (this._scriptPath) {
2170
2170
  let resolvedScriptPath;
2171
2171
  try {
2172
- resolvedScriptPath = fs11.realpathSync(this._scriptPath);
2172
+ resolvedScriptPath = fs12.realpathSync(this._scriptPath);
2173
2173
  } catch {
2174
2174
  resolvedScriptPath = this._scriptPath;
2175
2175
  }
2176
- executableDir = path12.resolve(
2177
- path12.dirname(resolvedScriptPath),
2176
+ executableDir = path13.resolve(
2177
+ path13.dirname(resolvedScriptPath),
2178
2178
  executableDir
2179
2179
  );
2180
2180
  }
2181
2181
  if (executableDir) {
2182
2182
  let localFile = findFile(executableDir, executableFile);
2183
2183
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
2184
- const legacyName = path12.basename(
2184
+ const legacyName = path13.basename(
2185
2185
  this._scriptPath,
2186
- path12.extname(this._scriptPath)
2186
+ path13.extname(this._scriptPath)
2187
2187
  );
2188
2188
  if (legacyName !== this._name) {
2189
2189
  localFile = findFile(
@@ -2194,7 +2194,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2194
2194
  }
2195
2195
  executableFile = localFile || executableFile;
2196
2196
  }
2197
- launchWithNode = sourceExt.includes(path12.extname(executableFile));
2197
+ launchWithNode = sourceExt.includes(path13.extname(executableFile));
2198
2198
  let proc;
2199
2199
  if (process2.platform !== "win32") {
2200
2200
  if (launchWithNode) {
@@ -3041,7 +3041,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
3041
3041
  * @return {Command}
3042
3042
  */
3043
3043
  nameFromFilename(filename) {
3044
- this._name = path12.basename(filename, path12.extname(filename));
3044
+ this._name = path13.basename(filename, path13.extname(filename));
3045
3045
  return this;
3046
3046
  }
3047
3047
  /**
@@ -3055,9 +3055,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
3055
3055
  * @param {string} [path]
3056
3056
  * @return {(string|null|Command)}
3057
3057
  */
3058
- executableDir(path13) {
3059
- if (path13 === void 0) return this._executableDir;
3060
- this._executableDir = path13;
3058
+ executableDir(path14) {
3059
+ if (path14 === void 0) return this._executableDir;
3060
+ this._executableDir = path14;
3061
3061
  return this;
3062
3062
  }
3063
3063
  /**
@@ -4067,10 +4067,10 @@ var require_src2 = __commonJS({
4067
4067
  var fs_1 = require("fs");
4068
4068
  var debug_1 = __importDefault(require_src());
4069
4069
  var log = debug_1.default("@kwsites/file-exists");
4070
- function check(path12, isFile, isDirectory) {
4071
- log(`checking %s`, path12);
4070
+ function check(path13, isFile, isDirectory) {
4071
+ log(`checking %s`, path13);
4072
4072
  try {
4073
- const stat = fs_1.statSync(path12);
4073
+ const stat = fs_1.statSync(path13);
4074
4074
  if (stat.isFile() && isFile) {
4075
4075
  log(`[OK] path represents a file`);
4076
4076
  return true;
@@ -4090,8 +4090,8 @@ var require_src2 = __commonJS({
4090
4090
  throw e;
4091
4091
  }
4092
4092
  }
4093
- function exists2(path12, type = exports2.READABLE) {
4094
- return check(path12, (type & exports2.FILE) > 0, (type & exports2.FOLDER) > 0);
4093
+ function exists2(path13, type = exports2.READABLE) {
4094
+ return check(path13, (type & exports2.FILE) > 0, (type & exports2.FOLDER) > 0);
4095
4095
  }
4096
4096
  exports2.exists = exists2;
4097
4097
  exports2.FILE = 1;
@@ -4155,8 +4155,8 @@ var require_dist2 = __commonJS({
4155
4155
  });
4156
4156
 
4157
4157
  // src/index.ts
4158
- var fs10 = __toESM(require("fs"), 1);
4159
- var path11 = __toESM(require("path"), 1);
4158
+ var fs11 = __toESM(require("fs"), 1);
4159
+ var path12 = __toESM(require("path"), 1);
4160
4160
 
4161
4161
  // ../../node_modules/.pnpm/commander@13.1.0/node_modules/commander/esm.mjs
4162
4162
  var import_index = __toESM(require_commander(), 1);
@@ -4659,8 +4659,8 @@ function getErrorMap() {
4659
4659
 
4660
4660
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
4661
4661
  var makeIssue = (params) => {
4662
- const { data, path: path12, errorMaps, issueData } = params;
4663
- const fullPath = [...path12, ...issueData.path || []];
4662
+ const { data, path: path13, errorMaps, issueData } = params;
4663
+ const fullPath = [...path13, ...issueData.path || []];
4664
4664
  const fullIssue = {
4665
4665
  ...issueData,
4666
4666
  path: fullPath
@@ -4776,11 +4776,11 @@ var errorUtil;
4776
4776
 
4777
4777
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
4778
4778
  var ParseInputLazyPath = class {
4779
- constructor(parent, value, path12, key) {
4779
+ constructor(parent, value, path13, key) {
4780
4780
  this._cachedPath = [];
4781
4781
  this.parent = parent;
4782
4782
  this.data = value;
4783
- this._path = path12;
4783
+ this._path = path13;
4784
4784
  this._key = key;
4785
4785
  }
4786
4786
  get path() {
@@ -8892,8 +8892,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
8892
8892
  function forEachLineWithContent(input, callback) {
8893
8893
  return toLinesWithContent(input, true).map((line) => callback(line));
8894
8894
  }
8895
- function folderExists(path12) {
8896
- return (0, import_file_exists.exists)(path12, import_file_exists.FOLDER);
8895
+ function folderExists(path13) {
8896
+ return (0, import_file_exists.exists)(path13, import_file_exists.FOLDER);
8897
8897
  }
8898
8898
  function append(target, item) {
8899
8899
  if (Array.isArray(target)) {
@@ -9295,8 +9295,8 @@ function checkIsRepoRootTask() {
9295
9295
  commands,
9296
9296
  format: "utf-8",
9297
9297
  onError,
9298
- parser(path12) {
9299
- return /^\.(git)?$/.test(path12.trim());
9298
+ parser(path13) {
9299
+ return /^\.(git)?$/.test(path13.trim());
9300
9300
  }
9301
9301
  };
9302
9302
  }
@@ -9730,11 +9730,11 @@ function parseGrep(grep) {
9730
9730
  const paths = /* @__PURE__ */ new Set();
9731
9731
  const results = {};
9732
9732
  forEachLineWithContent(grep, (input) => {
9733
- const [path12, line, preview] = input.split(NULL);
9734
- paths.add(path12);
9735
- (results[path12] = results[path12] || []).push({
9733
+ const [path13, line, preview] = input.split(NULL);
9734
+ paths.add(path13);
9735
+ (results[path13] = results[path13] || []).push({
9736
9736
  line: asNumber(line),
9737
- path: path12,
9737
+ path: path13,
9738
9738
  preview
9739
9739
  });
9740
9740
  });
@@ -10498,14 +10498,14 @@ var init_hash_object = __esm({
10498
10498
  init_task();
10499
10499
  }
10500
10500
  });
10501
- function parseInit(bare, path12, text) {
10501
+ function parseInit(bare, path13, text) {
10502
10502
  const response = String(text).trim();
10503
10503
  let result;
10504
10504
  if (result = initResponseRegex.exec(response)) {
10505
- return new InitSummary(bare, path12, false, result[1]);
10505
+ return new InitSummary(bare, path13, false, result[1]);
10506
10506
  }
10507
10507
  if (result = reInitResponseRegex.exec(response)) {
10508
- return new InitSummary(bare, path12, true, result[1]);
10508
+ return new InitSummary(bare, path13, true, result[1]);
10509
10509
  }
10510
10510
  let gitDir = "";
10511
10511
  const tokens = response.split(" ");
@@ -10516,7 +10516,7 @@ function parseInit(bare, path12, text) {
10516
10516
  break;
10517
10517
  }
10518
10518
  }
10519
- return new InitSummary(bare, path12, /^re/i.test(response), gitDir);
10519
+ return new InitSummary(bare, path13, /^re/i.test(response), gitDir);
10520
10520
  }
10521
10521
  var InitSummary;
10522
10522
  var initResponseRegex;
@@ -10525,9 +10525,9 @@ var init_InitSummary = __esm({
10525
10525
  "src/lib/responses/InitSummary.ts"() {
10526
10526
  "use strict";
10527
10527
  InitSummary = class {
10528
- constructor(bare, path12, existing, gitDir) {
10528
+ constructor(bare, path13, existing, gitDir) {
10529
10529
  this.bare = bare;
10530
- this.path = path12;
10530
+ this.path = path13;
10531
10531
  this.existing = existing;
10532
10532
  this.gitDir = gitDir;
10533
10533
  }
@@ -10539,7 +10539,7 @@ var init_InitSummary = __esm({
10539
10539
  function hasBareCommand(command) {
10540
10540
  return command.includes(bareCommand);
10541
10541
  }
10542
- function initTask(bare = false, path12, customArgs) {
10542
+ function initTask(bare = false, path13, customArgs) {
10543
10543
  const commands = ["init", ...customArgs];
10544
10544
  if (bare && !hasBareCommand(commands)) {
10545
10545
  commands.splice(1, 0, bareCommand);
@@ -10548,7 +10548,7 @@ function initTask(bare = false, path12, customArgs) {
10548
10548
  commands,
10549
10549
  format: "utf-8",
10550
10550
  parser(text) {
10551
- return parseInit(commands.includes("--bare"), path12, text);
10551
+ return parseInit(commands.includes("--bare"), path13, text);
10552
10552
  }
10553
10553
  };
10554
10554
  }
@@ -11363,12 +11363,12 @@ var init_FileStatusSummary = __esm({
11363
11363
  "use strict";
11364
11364
  fromPathRegex = /^(.+)\0(.+)$/;
11365
11365
  FileStatusSummary = class {
11366
- constructor(path12, index, working_dir) {
11367
- this.path = path12;
11366
+ constructor(path13, index, working_dir) {
11367
+ this.path = path13;
11368
11368
  this.index = index;
11369
11369
  this.working_dir = working_dir;
11370
11370
  if (index === "R" || working_dir === "R") {
11371
- const detail = fromPathRegex.exec(path12) || [null, path12, path12];
11371
+ const detail = fromPathRegex.exec(path13) || [null, path13, path13];
11372
11372
  this.from = detail[2] || "";
11373
11373
  this.path = detail[1] || "";
11374
11374
  }
@@ -11399,14 +11399,14 @@ function splitLine(result, lineStr) {
11399
11399
  default:
11400
11400
  return;
11401
11401
  }
11402
- function data(index, workingDir, path12) {
11402
+ function data(index, workingDir, path13) {
11403
11403
  const raw = `${index}${workingDir}`;
11404
11404
  const handler = parsers6.get(raw);
11405
11405
  if (handler) {
11406
- handler(result, path12);
11406
+ handler(result, path13);
11407
11407
  }
11408
11408
  if (raw !== "##" && raw !== "!!") {
11409
- result.files.push(new FileStatusSummary(path12, index, workingDir));
11409
+ result.files.push(new FileStatusSummary(path13, index, workingDir));
11410
11410
  }
11411
11411
  }
11412
11412
  }
@@ -11757,9 +11757,9 @@ var init_simple_git_api = __esm({
11757
11757
  next
11758
11758
  );
11759
11759
  }
11760
- hashObject(path12, write) {
11760
+ hashObject(path13, write) {
11761
11761
  return this._runTask(
11762
- hashObjectTask(path12, write === true),
11762
+ hashObjectTask(path13, write === true),
11763
11763
  trailingFunctionArgument(arguments)
11764
11764
  );
11765
11765
  }
@@ -12113,8 +12113,8 @@ var init_branch = __esm({
12113
12113
  }
12114
12114
  });
12115
12115
  function toPath(input) {
12116
- const path12 = input.trim().replace(/^["']|["']$/g, "");
12117
- return path12 && (0, import_node_path.normalize)(path12);
12116
+ const path13 = input.trim().replace(/^["']|["']$/g, "");
12117
+ return path13 && (0, import_node_path.normalize)(path13);
12118
12118
  }
12119
12119
  var parseCheckIgnore;
12120
12120
  var init_CheckIgnore = __esm({
@@ -12399,8 +12399,8 @@ __export2(sub_module_exports, {
12399
12399
  subModuleTask: () => subModuleTask,
12400
12400
  updateSubModuleTask: () => updateSubModuleTask
12401
12401
  });
12402
- function addSubModuleTask(repo, path12) {
12403
- return subModuleTask(["add", repo, path12]);
12402
+ function addSubModuleTask(repo, path13) {
12403
+ return subModuleTask(["add", repo, path13]);
12404
12404
  }
12405
12405
  function initSubModuleTask(customArgs) {
12406
12406
  return subModuleTask(["init", ...customArgs]);
@@ -12714,8 +12714,8 @@ var require_git = __commonJS2({
12714
12714
  }
12715
12715
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
12716
12716
  };
12717
- Git2.prototype.submoduleAdd = function(repo, path12, then) {
12718
- return this._runTask(addSubModuleTask2(repo, path12), trailingFunctionArgument2(arguments));
12717
+ Git2.prototype.submoduleAdd = function(repo, path13, then) {
12718
+ return this._runTask(addSubModuleTask2(repo, path13), trailingFunctionArgument2(arguments));
12719
12719
  };
12720
12720
  Git2.prototype.submoduleUpdate = function(args, then) {
12721
12721
  return this._runTask(
@@ -13842,6 +13842,9 @@ var MODEL_ALIASES = {
13842
13842
  "gemini-3": "gemini-3-8-flash",
13843
13843
  "gemini-flash": "gemini-3-8-flash",
13844
13844
  "gemini-pro": "gemini-2-5-pro",
13845
+ "gemini-3-1-pro": "gemini-2-5-pro",
13846
+ "gemini-3-pro": "gemini-2-5-pro",
13847
+ "gemini-3-1-flash": "gemini-3-8-flash",
13845
13848
  "gemini-2.0-flash": "gemini-2-0-flash",
13846
13849
  "gemini-1.5-pro": "gemini-1-5-pro",
13847
13850
  "gemini-1.5-flash": "gemini-2-0-flash",
@@ -13852,33 +13855,82 @@ var MODEL_ALIASES = {
13852
13855
  "deepseek-reasoner": "deepseek-r1",
13853
13856
  "deepseek/deepseek-r1": "deepseek-r1"
13854
13857
  };
13858
+ var DYNAMIC_RATE_CARDS = {};
13859
+ var DYNAMIC_ALIASES = {};
13860
+ var PROVIDERS = /* @__PURE__ */ new Set(["anthropic", "openai", "google", "deepseek", "generic"]);
13861
+ function isPrice(v) {
13862
+ return typeof v === "number" && Number.isFinite(v) && v >= 0 && v <= 1e3;
13863
+ }
13864
+ function sanitizeRateCards(raw) {
13865
+ const out = {};
13866
+ if (!raw || typeof raw !== "object")
13867
+ return out;
13868
+ for (const [key, value] of Object.entries(raw)) {
13869
+ const c3 = value;
13870
+ if (!c3 || typeof c3 !== "object")
13871
+ continue;
13872
+ if (isPrice(c3.inputPerMTok) && isPrice(c3.outputPerMTok) && isPrice(c3.cacheReadPerMTok) && isPrice(c3.cacheWritePerMTok)) {
13873
+ out[key] = {
13874
+ id: typeof c3.id === "string" ? c3.id : key,
13875
+ provider: PROVIDERS.has(c3.provider) ? c3.provider : "generic",
13876
+ name: typeof c3.name === "string" ? c3.name : key,
13877
+ inputPerMTok: c3.inputPerMTok,
13878
+ outputPerMTok: c3.outputPerMTok,
13879
+ cacheReadPerMTok: c3.cacheReadPerMTok,
13880
+ cacheWritePerMTok: c3.cacheWritePerMTok,
13881
+ contextWindow: typeof c3.contextWindow === "number" && c3.contextWindow > 0 ? c3.contextWindow : 128e3
13882
+ };
13883
+ }
13884
+ }
13885
+ return out;
13886
+ }
13887
+ function sanitizeAliases(raw) {
13888
+ const out = {};
13889
+ if (!raw || typeof raw !== "object")
13890
+ return out;
13891
+ for (const [k2, v] of Object.entries(raw)) {
13892
+ if (typeof v === "string" && v.length > 0)
13893
+ out[k2.toLowerCase()] = v;
13894
+ }
13895
+ return out;
13896
+ }
13897
+ function updatePricingRegistry(newCards, newAliases) {
13898
+ DYNAMIC_RATE_CARDS = { ...DYNAMIC_RATE_CARDS, ...sanitizeRateCards(newCards) };
13899
+ if (newAliases) {
13900
+ DYNAMIC_ALIASES = { ...DYNAMIC_ALIASES, ...sanitizeAliases(newAliases) };
13901
+ }
13902
+ }
13855
13903
  function getRateCard(modelId) {
13856
13904
  if (!modelId)
13857
- return RATE_CARDS["default"];
13905
+ return DYNAMIC_RATE_CARDS["default"] ?? RATE_CARDS["default"];
13858
13906
  let key = modelId.toLowerCase().replace(/[^a-z0-9-]/g, "-");
13859
- if (MODEL_ALIASES[modelId.toLowerCase()]) {
13860
- key = MODEL_ALIASES[modelId.toLowerCase()];
13861
- } else if (MODEL_ALIASES[key]) {
13862
- key = MODEL_ALIASES[key];
13907
+ const aliasMatch = DYNAMIC_ALIASES[modelId.toLowerCase()] ?? MODEL_ALIASES[modelId.toLowerCase()];
13908
+ if (aliasMatch) {
13909
+ key = aliasMatch;
13910
+ } else {
13911
+ const fallbackAliasMatch = DYNAMIC_ALIASES[key] ?? MODEL_ALIASES[key];
13912
+ if (fallbackAliasMatch) {
13913
+ key = fallbackAliasMatch;
13914
+ }
13863
13915
  }
13916
+ if (DYNAMIC_RATE_CARDS[key])
13917
+ return DYNAMIC_RATE_CARDS[key];
13864
13918
  if (RATE_CARDS[key])
13865
13919
  return RATE_CARDS[key];
13866
13920
  if (key.includes("opus")) {
13867
13921
  return RATE_CARDS["claude-opus-4-6-thinking"] ?? RATE_CARDS["claude-opus-4"];
13868
13922
  }
13869
13923
  if (key.includes("sonnet")) {
13870
- if (key.includes("4-6") || key.includes("thinking")) {
13871
- return RATE_CARDS["claude-sonnet-4-6-thinking"];
13872
- }
13873
13924
  if (key.includes("3-7") || key.includes("sonnet-3-7")) {
13874
13925
  return RATE_CARDS["claude-3-7-sonnet"];
13875
13926
  }
13876
13927
  if (key.includes("3-5") || key.includes("sonnet-3-5")) {
13877
13928
  return RATE_CARDS["claude-3-5-sonnet"];
13878
13929
  }
13879
- if (key.includes("sonnet-4") || key.includes("claude-4") || key.includes("sonnet-v4")) {
13880
- return RATE_CARDS["claude-sonnet-4"] ?? RATE_CARDS["claude-sonnet-4-6-thinking"];
13881
- }
13930
+ return RATE_CARDS["claude-sonnet-4-6-thinking"];
13931
+ }
13932
+ if (key.includes("haiku")) {
13933
+ return RATE_CARDS["claude-3-5-haiku"];
13882
13934
  }
13883
13935
  if (key.includes("o1-mini") || key.includes("o3-mini")) {
13884
13936
  return RATE_CARDS["o3-mini"];
@@ -14192,8 +14244,8 @@ function harvestAntigravityFootprints(repoPath, sinceDate) {
14192
14244
  const DatabaseSync2 = getSqliteDatabase();
14193
14245
  if (!DatabaseSync2)
14194
14246
  return footprints;
14195
- const homedir7 = os2.homedir();
14196
- const antigravityDir = process.env.ANTIGRAVITY_APP_DATA_DIR || path3.join(homedir7, ".gemini", "antigravity");
14247
+ const homedir8 = os2.homedir();
14248
+ const antigravityDir = process.env.ANTIGRAVITY_APP_DATA_DIR || path3.join(homedir8, ".gemini", "antigravity");
14197
14249
  const dbPath = path3.join(antigravityDir, "conversation_summaries.db");
14198
14250
  if (!fs2.existsSync(dbPath)) {
14199
14251
  return footprints;
@@ -14233,18 +14285,8 @@ function harvestAntigravityFootprints(repoPath, sinceDate) {
14233
14285
  continue;
14234
14286
  if (line.includes("Model Selection")) {
14235
14287
  const match = line.match(/Model Selection` from .*?to ([^\.\(\n\r]+)/);
14236
- if (match && match[1]) {
14237
- const rawModel = match[1].trim();
14238
- if (rawModel.toLowerCase().includes("opus"))
14239
- detectedModel = "claude-opus-4-6-thinking";
14240
- else if (rawModel.toLowerCase().includes("sonnet"))
14241
- detectedModel = "claude-sonnet-4-6-thinking";
14242
- else if (rawModel.toLowerCase().includes("flash"))
14243
- detectedModel = "gemini-3-8-flash";
14244
- else if (rawModel.toLowerCase().includes("pro"))
14245
- detectedModel = "gemini-2-5-pro";
14246
- else
14247
- detectedModel = rawModel.toLowerCase().replace(/\s+/g, "-");
14288
+ if (match && match[1] && match[1].length < 30) {
14289
+ detectedModel = match[1].toLowerCase().replace(/\(.*?\)/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
14248
14290
  }
14249
14291
  }
14250
14292
  if (line.includes('"replace_file_content"') || line.includes('"write_to_file"')) {
@@ -14289,8 +14331,8 @@ function harvestAntigravityFootprints(repoPath, sinceDate) {
14289
14331
  cached: estimatedCached
14290
14332
  },
14291
14333
  cost,
14292
- mode: "verified",
14293
- confidence: 0.95,
14334
+ mode: "estimated",
14335
+ confidence: 0.65,
14294
14336
  rawTranscriptPath: transcriptPath
14295
14337
  });
14296
14338
  }
@@ -14305,8 +14347,8 @@ var path4 = __toESM(require("path"), 1);
14305
14347
  var os3 = __toESM(require("os"), 1);
14306
14348
  function harvestClaudeFootprints(repoPath, projectAlias, sinceDate) {
14307
14349
  const footprints = [];
14308
- const homedir7 = os3.homedir();
14309
- const claudeProjectsDir = path4.join(homedir7, ".claude", "projects");
14350
+ const homedir8 = os3.homedir();
14351
+ const claudeProjectsDir = path4.join(homedir8, ".claude", "projects");
14310
14352
  if (!fs3.existsSync(claudeProjectsDir)) {
14311
14353
  return footprints;
14312
14354
  }
@@ -14575,8 +14617,8 @@ function harvestCursorFootprints(repoPath, sinceDate) {
14575
14617
  cached: estCached
14576
14618
  },
14577
14619
  cost,
14578
- mode: "verified",
14579
- confidence: 0.95,
14620
+ mode: "estimated",
14621
+ confidence: 0.55,
14580
14622
  rawTranscriptPath: dbFile
14581
14623
  });
14582
14624
  }
@@ -15112,7 +15154,7 @@ async function harvestUniversalFootprints(options) {
15112
15154
  allFootprints.push(...trailerFps);
15113
15155
  }
15114
15156
  const { primary, rankedFootprints } = selectPrimaryFootprint(allFootprints, options.gitContext);
15115
- allFootprints = rankedFootprints;
15157
+ allFootprints = rankedFootprints.filter((fp) => fp.attributionScore === void 0 || fp.attributionScore >= 0.1);
15116
15158
  try {
15117
15159
  const db = new LocalStateDB();
15118
15160
  for (const fp of allFootprints) {
@@ -15231,6 +15273,49 @@ function estimateCost(options) {
15231
15273
  };
15232
15274
  }
15233
15275
 
15276
+ // ../core/dist/pricing-sync.js
15277
+ var fs8 = __toESM(require("fs"), 1);
15278
+ var path9 = __toESM(require("path"), 1);
15279
+ var os7 = __toESM(require("os"), 1);
15280
+ async function syncDynamicPricing(options) {
15281
+ try {
15282
+ const qodewkDir = path9.join(os7.homedir(), ".qodewk");
15283
+ if (!fs8.existsSync(qodewkDir)) {
15284
+ fs8.mkdirSync(qodewkDir, { recursive: true });
15285
+ }
15286
+ const cacheFile = path9.join(qodewkDir, "pricing_registry_cache.json");
15287
+ const TTL_MS = 24 * 60 * 60 * 1e3;
15288
+ const now = Date.now();
15289
+ if (!options?.force && fs8.existsSync(cacheFile)) {
15290
+ try {
15291
+ const stats = fs8.statSync(cacheFile);
15292
+ if (now - stats.mtimeMs < TTL_MS) {
15293
+ const cachedData = JSON.parse(fs8.readFileSync(cacheFile, "utf-8"));
15294
+ if (cachedData.rates) {
15295
+ updatePricingRegistry(cachedData.rates, cachedData.aliases);
15296
+ }
15297
+ return;
15298
+ }
15299
+ } catch {
15300
+ }
15301
+ }
15302
+ const REMOTE_URL = process.env.QODEWK_PRICING_URL || "https://raw.githubusercontent.com/abushaidislam/Qodewk/master/registry/pricing.json";
15303
+ const controller = new AbortController();
15304
+ const timeout = setTimeout(() => controller.abort(), options?.timeoutMs || 2500);
15305
+ const response = await fetch(REMOTE_URL, { signal: controller.signal });
15306
+ clearTimeout(timeout);
15307
+ if (response.ok) {
15308
+ const data = await response.json();
15309
+ if (data && typeof data === "object" && data.rates) {
15310
+ updatePricingRegistry(data.rates, data.aliases);
15311
+ fs8.promises.writeFile(cacheFile, JSON.stringify(data, null, 2), "utf-8").catch(() => {
15312
+ });
15313
+ }
15314
+ }
15315
+ } catch (error) {
15316
+ }
15317
+ }
15318
+
15234
15319
  // ../core/dist/format.js
15235
15320
  function formatMarkdownReceipt(receipt, publicUrl) {
15236
15321
  const baseUrl = process.env.NEXT_PUBLIC_APP_URL || process.env.QODEWK_APP_URL || "https://qodewk.flinkeo.online";
@@ -15290,6 +15375,7 @@ function sanitizeReceiptForShare(receipt) {
15290
15375
  };
15291
15376
  }
15292
15377
  async function generateReceipt(options = {}) {
15378
+ await syncDynamicPricing({ timeoutMs: 1500 });
15293
15379
  const metrics = await extractGitMetrics({
15294
15380
  repoPath: options.repoPath || process.cwd(),
15295
15381
  baseSha: options.baseSha,
@@ -15395,7 +15481,7 @@ async function generateReceipt(options = {}) {
15395
15481
  }
15396
15482
 
15397
15483
  // src/receipt-view.ts
15398
- var fs8 = __toESM(require("fs"), 1);
15484
+ var fs9 = __toESM(require("fs"), 1);
15399
15485
  var import_picocolors = __toESM(require_picocolors(), 1);
15400
15486
 
15401
15487
  // src/barcode.ts
@@ -15742,7 +15828,7 @@ function buildTerminalReceipt(receipt, publicUrl) {
15742
15828
  }
15743
15829
  if (receipt.ai.aiWrittenRatio !== void 0) {
15744
15830
  const aiPct = Math.round(receipt.ai.aiWrittenRatio * 100);
15745
- printRowSplit("AI Written Code", `${aiPct}% (Human: ${100 - aiPct}%)`);
15831
+ printRowSplit("AI Touched Files", `${aiPct}% (Human: ${100 - aiPct}%)`);
15746
15832
  }
15747
15833
  const tokenDetail = `${inputK} in (${Math.round(receipt.ai.tokens.cached / 1e3)}k cached) / ${outputK} out`;
15748
15834
  const cleanTokens = tokenDetail.length > 40 ? tokenDetail.slice(0, 39) + "\u2026" : tokenDetail;
@@ -15809,7 +15895,7 @@ async function outputReceipt(receipt, options, publicUrl) {
15809
15895
  }
15810
15896
  if (options.out) {
15811
15897
  const fileContent = format === "terminal" ? stripAnsi(content) : content;
15812
- fs8.writeFileSync(options.out, fileContent.endsWith("\n") ? fileContent : fileContent + "\n", "utf-8");
15898
+ fs9.writeFileSync(options.out, fileContent.endsWith("\n") ? fileContent : fileContent + "\n", "utf-8");
15813
15899
  console.log(import_picocolors.default.green(`\u2713 Receipt written to ${options.out}`));
15814
15900
  }
15815
15901
  if (!options.out) {
@@ -15822,8 +15908,8 @@ async function outputReceipt(receipt, options, publicUrl) {
15822
15908
  }
15823
15909
 
15824
15910
  // src/hooks.ts
15825
- var fs9 = __toESM(require("fs"), 1);
15826
- var path9 = __toESM(require("path"), 1);
15911
+ var fs10 = __toESM(require("fs"), 1);
15912
+ var path10 = __toESM(require("path"), 1);
15827
15913
  var HOOK_MARKER_BEGIN = "# --- BEGIN QODEWK HOOK ---";
15828
15914
  var HOOK_MARKER_END = "# --- END QODEWK HOOK ---";
15829
15915
  var HOOK_SNIPPET = `
@@ -15835,37 +15921,37 @@ fi
15835
15921
  ${HOOK_MARKER_END}
15836
15922
  `;
15837
15923
  function resolveGitHooksDir(cwd = process.cwd()) {
15838
- const gitPath = path9.join(cwd, ".git");
15839
- if (!fs9.existsSync(gitPath)) return null;
15924
+ const gitPath = path10.join(cwd, ".git");
15925
+ if (!fs10.existsSync(gitPath)) return null;
15840
15926
  let gitCommonDir;
15841
- const stat = fs9.statSync(gitPath);
15927
+ const stat = fs10.statSync(gitPath);
15842
15928
  if (stat.isDirectory()) {
15843
15929
  gitCommonDir = gitPath;
15844
15930
  } else {
15845
- const content = fs9.readFileSync(gitPath, "utf-8");
15931
+ const content = fs10.readFileSync(gitPath, "utf-8");
15846
15932
  const match = content.match(/gitdir:\s*(.+)/i);
15847
15933
  if (!match?.[1]) return null;
15848
15934
  let gitDir = match[1].trim();
15849
- if (!path9.isAbsolute(gitDir)) {
15850
- gitDir = path9.resolve(cwd, gitDir);
15935
+ if (!path10.isAbsolute(gitDir)) {
15936
+ gitDir = path10.resolve(cwd, gitDir);
15851
15937
  }
15852
- const commonFile = path9.join(gitDir, "commondir");
15853
- if (fs9.existsSync(commonFile)) {
15854
- let common = fs9.readFileSync(commonFile, "utf-8").trim();
15855
- if (!path9.isAbsolute(common)) {
15856
- common = path9.resolve(gitDir, common);
15938
+ const commonFile = path10.join(gitDir, "commondir");
15939
+ if (fs10.existsSync(commonFile)) {
15940
+ let common = fs10.readFileSync(commonFile, "utf-8").trim();
15941
+ if (!path10.isAbsolute(common)) {
15942
+ common = path10.resolve(gitDir, common);
15857
15943
  }
15858
15944
  gitCommonDir = common;
15859
- } else if (path9.basename(path9.dirname(gitDir)) === "worktrees") {
15860
- gitCommonDir = path9.dirname(path9.dirname(gitDir));
15945
+ } else if (path10.basename(path10.dirname(gitDir)) === "worktrees") {
15946
+ gitCommonDir = path10.dirname(path10.dirname(gitDir));
15861
15947
  } else {
15862
15948
  gitCommonDir = gitDir;
15863
15949
  }
15864
15950
  }
15865
- return path9.join(gitCommonDir, "hooks");
15951
+ return path10.join(gitCommonDir, "hooks");
15866
15952
  }
15867
15953
  function checkHookStatus(hooksDir) {
15868
- if (!hooksDir || !fs9.existsSync(hooksDir)) {
15954
+ if (!hooksDir || !fs10.existsSync(hooksDir)) {
15869
15955
  return {
15870
15956
  isGit: Boolean(hooksDir),
15871
15957
  hooksDir,
@@ -15873,12 +15959,12 @@ function checkHookStatus(hooksDir) {
15873
15959
  postRewriteInstalled: false
15874
15960
  };
15875
15961
  }
15876
- const postCommit = path9.join(hooksDir, "post-commit");
15877
- const postRewrite = path9.join(hooksDir, "post-rewrite");
15962
+ const postCommit = path10.join(hooksDir, "post-commit");
15963
+ const postRewrite = path10.join(hooksDir, "post-rewrite");
15878
15964
  const hasHook = (p2) => {
15879
- if (!fs9.existsSync(p2)) return false;
15965
+ if (!fs10.existsSync(p2)) return false;
15880
15966
  try {
15881
- const content = fs9.readFileSync(p2, "utf-8");
15967
+ const content = fs10.readFileSync(p2, "utf-8");
15882
15968
  return content.includes(HOOK_MARKER_BEGIN);
15883
15969
  } catch {
15884
15970
  return false;
@@ -15893,30 +15979,30 @@ function checkHookStatus(hooksDir) {
15893
15979
  }
15894
15980
  function installHookFile(hookFile) {
15895
15981
  let content = "";
15896
- if (fs9.existsSync(hookFile)) {
15897
- content = fs9.readFileSync(hookFile, "utf-8");
15982
+ if (fs10.existsSync(hookFile)) {
15983
+ content = fs10.readFileSync(hookFile, "utf-8");
15898
15984
  } else {
15899
15985
  content = "#!/bin/sh\n";
15900
15986
  }
15901
15987
  if (content.includes(HOOK_MARKER_BEGIN)) {
15902
15988
  return "exists";
15903
15989
  }
15904
- fs9.writeFileSync(hookFile, content + HOOK_SNIPPET, { mode: 493 });
15990
+ fs10.writeFileSync(hookFile, content + HOOK_SNIPPET, { mode: 493 });
15905
15991
  return "installed";
15906
15992
  }
15907
15993
  function uninstallHookFile(hookFile) {
15908
- if (!fs9.existsSync(hookFile)) return "absent";
15909
- const content = fs9.readFileSync(hookFile, "utf-8");
15994
+ if (!fs10.existsSync(hookFile)) return "absent";
15995
+ const content = fs10.readFileSync(hookFile, "utf-8");
15910
15996
  if (!content.includes(HOOK_MARKER_BEGIN)) return "missing";
15911
15997
  const regex = new RegExp(`\\n?${HOOK_MARKER_BEGIN}[\\s\\S]*?${HOOK_MARKER_END}\\n?`, "g");
15912
15998
  const updated = content.replace(regex, "");
15913
- fs9.writeFileSync(hookFile, updated, { mode: 493 });
15999
+ fs10.writeFileSync(hookFile, updated, { mode: 493 });
15914
16000
  return "removed";
15915
16001
  }
15916
16002
 
15917
16003
  // src/menu.ts
15918
16004
  var readline = __toESM(require("readline"), 1);
15919
- var path10 = __toESM(require("path"), 1);
16005
+ var path11 = __toESM(require("path"), 1);
15920
16006
  var import_picocolors2 = __toESM(require_picocolors(), 1);
15921
16007
  var SHARE_PAYLOAD_MAX_BYTES = 5e4;
15922
16008
  var BANNER_LINES = [
@@ -16021,7 +16107,7 @@ function buildMenuFrame(selectedIndex, items = MENU_ITEMS, title = "Telemetry Co
16021
16107
  }
16022
16108
  push("");
16023
16109
  const badge = bg.teal(import_picocolors2.default.bold(colors.ink(" qodewk ")));
16024
- push(` ${colors.mutedSoft("\u250C")} ${badge} ${import_picocolors2.default.dim("v0.8.0")}`);
16110
+ push(` ${colors.mutedSoft("\u250C")} ${badge} ${import_picocolors2.default.dim("v0.9.1")}`);
16025
16111
  push(` ${colors.mutedSoft("\u2502")}`);
16026
16112
  if (options.actionContext) {
16027
16113
  push(` ${colors.teal("\u25C7")} ${import_picocolors2.default.dim("Action:")} ${import_picocolors2.default.white(options.actionContext)}`);
@@ -16106,7 +16192,7 @@ async function getRepoContext() {
16106
16192
  }
16107
16193
  const branchSummary = await git.branch();
16108
16194
  const branch = branchSummary.current || "HEAD";
16109
- const alias = path10.basename(process.cwd());
16195
+ const alias = path11.basename(process.cwd());
16110
16196
  cachedRepoContext = { alias, branch };
16111
16197
  return cachedRepoContext;
16112
16198
  } catch {
@@ -16342,7 +16428,7 @@ async function runInteractiveMenu() {
16342
16428
  if (status.hooksDir) {
16343
16429
  const targets = ["post-commit", "post-rewrite"];
16344
16430
  for (const t2 of targets) {
16345
- installHookFile(path10.join(status.hooksDir, t2));
16431
+ installHookFile(path11.join(status.hooksDir, t2));
16346
16432
  }
16347
16433
  console.log(colors.green("\n [\u2713] Non-blocking hooks installed successfully."));
16348
16434
  }
@@ -16350,7 +16436,7 @@ async function runInteractiveMenu() {
16350
16436
  if (status.hooksDir) {
16351
16437
  const targets = ["post-commit", "post-rewrite"];
16352
16438
  for (const t2 of targets) {
16353
- uninstallHookFile(path10.join(status.hooksDir, t2));
16439
+ uninstallHookFile(path11.join(status.hooksDir, t2));
16354
16440
  }
16355
16441
  console.log(colors.green("\n [\u2713] Qodewk hooks removed."));
16356
16442
  }
@@ -16548,19 +16634,19 @@ async function runInteractiveMenu() {
16548
16634
  var SHARE_PAYLOAD_MAX_BYTES2 = 5e4;
16549
16635
  function resolveCliVersion() {
16550
16636
  try {
16551
- const argv1 = process.argv[1] ? path11.dirname(path11.resolve(process.argv[1])) : process.cwd();
16637
+ const argv1 = process.argv[1] ? path12.dirname(path12.resolve(process.argv[1])) : process.cwd();
16552
16638
  const candidates = [
16553
- path11.join(argv1, "..", "package.json"),
16554
- path11.join(argv1, "package.json")
16639
+ path12.join(argv1, "..", "package.json"),
16640
+ path12.join(argv1, "package.json")
16555
16641
  ];
16556
16642
  for (const candidate of candidates) {
16557
- if (!fs10.existsSync(candidate)) continue;
16558
- const pkg = JSON.parse(fs10.readFileSync(candidate, "utf-8"));
16643
+ if (!fs11.existsSync(candidate)) continue;
16644
+ const pkg = JSON.parse(fs11.readFileSync(candidate, "utf-8"));
16559
16645
  if (pkg.name === "qodewk" && pkg.version) return pkg.version;
16560
16646
  }
16561
16647
  } catch {
16562
16648
  }
16563
- return "0.8.0";
16649
+ return "0.9.1";
16564
16650
  }
16565
16651
  function resolveSince(options) {
16566
16652
  return options.today ? "today" : options.since;
@@ -16727,14 +16813,14 @@ hookCommand.command("install").description("Install non-blocking post-commit and
16727
16813
  console.error(import_picocolors3.default.red("Error: Current directory is not a Git repository (.git not found)."));
16728
16814
  process.exit(1);
16729
16815
  }
16730
- if (!fs10.existsSync(hooksDir)) {
16731
- fs10.mkdirSync(hooksDir, { recursive: true });
16816
+ if (!fs11.existsSync(hooksDir)) {
16817
+ fs11.mkdirSync(hooksDir, { recursive: true });
16732
16818
  }
16733
16819
  const targets = ["post-commit", "post-rewrite"];
16734
16820
  let installed = 0;
16735
16821
  let existing = 0;
16736
16822
  for (const name of targets) {
16737
- const result = installHookFile(path11.join(hooksDir, name));
16823
+ const result = installHookFile(path12.join(hooksDir, name));
16738
16824
  if (result === "installed") installed++;
16739
16825
  else existing++;
16740
16826
  }
@@ -16766,7 +16852,7 @@ hookCommand.command("uninstall").description("Remove Qodewk post-commit and post
16766
16852
  const targets = ["post-commit", "post-rewrite"];
16767
16853
  let removed = 0;
16768
16854
  for (const name of targets) {
16769
- const result = uninstallHookFile(path11.join(hooksDir, name));
16855
+ const result = uninstallHookFile(path12.join(hooksDir, name));
16770
16856
  if (result === "removed") removed++;
16771
16857
  }
16772
16858
  if (removed === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qodewk",
3
- "version": "0.8.0",
3
+ "version": "0.9.1",
4
4
  "description": "Universal telemetry and digital receipt generator for the AI coding agent era",
5
5
  "type": "module",
6
6
  "bin": {