qodewk 0.7.0 → 0.9.0
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.
- package/dist/index.cjs +501 -208
- 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
|
|
1157
|
-
var
|
|
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 (
|
|
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 =
|
|
2157
|
-
if (
|
|
2158
|
-
if (sourceExt.includes(
|
|
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) =>
|
|
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 =
|
|
2172
|
+
resolvedScriptPath = fs12.realpathSync(this._scriptPath);
|
|
2173
2173
|
} catch {
|
|
2174
2174
|
resolvedScriptPath = this._scriptPath;
|
|
2175
2175
|
}
|
|
2176
|
-
executableDir =
|
|
2177
|
-
|
|
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 =
|
|
2184
|
+
const legacyName = path13.basename(
|
|
2185
2185
|
this._scriptPath,
|
|
2186
|
-
|
|
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(
|
|
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 =
|
|
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(
|
|
3059
|
-
if (
|
|
3060
|
-
this._executableDir =
|
|
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(
|
|
4071
|
-
log(`checking %s`,
|
|
4070
|
+
function check(path13, isFile, isDirectory) {
|
|
4071
|
+
log(`checking %s`, path13);
|
|
4072
4072
|
try {
|
|
4073
|
-
const stat = fs_1.statSync(
|
|
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(
|
|
4094
|
-
return check(
|
|
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
|
|
4159
|
-
var
|
|
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:
|
|
4663
|
-
const fullPath = [...
|
|
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,
|
|
4779
|
+
constructor(parent, value, path13, key) {
|
|
4780
4780
|
this._cachedPath = [];
|
|
4781
4781
|
this.parent = parent;
|
|
4782
4782
|
this.data = value;
|
|
4783
|
-
this._path =
|
|
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(
|
|
8896
|
-
return (0, import_file_exists.exists)(
|
|
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(
|
|
9299
|
-
return /^\.(git)?$/.test(
|
|
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 [
|
|
9734
|
-
paths.add(
|
|
9735
|
-
(results[
|
|
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:
|
|
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,
|
|
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,
|
|
10505
|
+
return new InitSummary(bare, path13, false, result[1]);
|
|
10506
10506
|
}
|
|
10507
10507
|
if (result = reInitResponseRegex.exec(response)) {
|
|
10508
|
-
return new InitSummary(bare,
|
|
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, path11, text) {
|
|
|
10516
10516
|
break;
|
|
10517
10517
|
}
|
|
10518
10518
|
}
|
|
10519
|
-
return new InitSummary(bare,
|
|
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,
|
|
10528
|
+
constructor(bare, path13, existing, gitDir) {
|
|
10529
10529
|
this.bare = bare;
|
|
10530
|
-
this.path =
|
|
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,
|
|
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, path11, customArgs) {
|
|
|
10548
10548
|
commands,
|
|
10549
10549
|
format: "utf-8",
|
|
10550
10550
|
parser(text) {
|
|
10551
|
-
return parseInit(commands.includes("--bare"),
|
|
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(
|
|
11367
|
-
this.path =
|
|
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(
|
|
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,
|
|
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,
|
|
11406
|
+
handler(result, path13);
|
|
11407
11407
|
}
|
|
11408
11408
|
if (raw !== "##" && raw !== "!!") {
|
|
11409
|
-
result.files.push(new FileStatusSummary(
|
|
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(
|
|
11760
|
+
hashObject(path13, write) {
|
|
11761
11761
|
return this._runTask(
|
|
11762
|
-
hashObjectTask(
|
|
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
|
|
12117
|
-
return
|
|
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,
|
|
12403
|
-
return subModuleTask(["add", repo,
|
|
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,
|
|
12718
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
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(
|
|
@@ -13280,6 +13280,9 @@ function parseSinceOption(since) {
|
|
|
13280
13280
|
if (s === "today") {
|
|
13281
13281
|
return new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
13282
13282
|
}
|
|
13283
|
+
if (s === "yesterday") {
|
|
13284
|
+
return new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
|
|
13285
|
+
}
|
|
13283
13286
|
const hoursMatch = s.match(/^(\d+)\s*h(?:ours?)?$/);
|
|
13284
13287
|
if (hoursMatch && hoursMatch[1]) {
|
|
13285
13288
|
const hours = parseInt(hoursMatch[1], 10);
|
|
@@ -13849,15 +13852,29 @@ var MODEL_ALIASES = {
|
|
|
13849
13852
|
"deepseek-reasoner": "deepseek-r1",
|
|
13850
13853
|
"deepseek/deepseek-r1": "deepseek-r1"
|
|
13851
13854
|
};
|
|
13855
|
+
var DYNAMIC_RATE_CARDS = {};
|
|
13856
|
+
var DYNAMIC_ALIASES = {};
|
|
13857
|
+
function updatePricingRegistry(newCards, newAliases) {
|
|
13858
|
+
DYNAMIC_RATE_CARDS = { ...DYNAMIC_RATE_CARDS, ...newCards };
|
|
13859
|
+
if (newAliases) {
|
|
13860
|
+
DYNAMIC_ALIASES = { ...DYNAMIC_ALIASES, ...newAliases };
|
|
13861
|
+
}
|
|
13862
|
+
}
|
|
13852
13863
|
function getRateCard(modelId) {
|
|
13853
13864
|
if (!modelId)
|
|
13854
|
-
return RATE_CARDS["default"];
|
|
13865
|
+
return DYNAMIC_RATE_CARDS["default"] ?? RATE_CARDS["default"];
|
|
13855
13866
|
let key = modelId.toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
13856
|
-
|
|
13857
|
-
|
|
13858
|
-
|
|
13859
|
-
|
|
13867
|
+
const aliasMatch = DYNAMIC_ALIASES[modelId.toLowerCase()] ?? MODEL_ALIASES[modelId.toLowerCase()];
|
|
13868
|
+
if (aliasMatch) {
|
|
13869
|
+
key = aliasMatch;
|
|
13870
|
+
} else {
|
|
13871
|
+
const fallbackAliasMatch = DYNAMIC_ALIASES[key] ?? MODEL_ALIASES[key];
|
|
13872
|
+
if (fallbackAliasMatch) {
|
|
13873
|
+
key = fallbackAliasMatch;
|
|
13874
|
+
}
|
|
13860
13875
|
}
|
|
13876
|
+
if (DYNAMIC_RATE_CARDS[key])
|
|
13877
|
+
return DYNAMIC_RATE_CARDS[key];
|
|
13861
13878
|
if (RATE_CARDS[key])
|
|
13862
13879
|
return RATE_CARDS[key];
|
|
13863
13880
|
if (key.includes("opus")) {
|
|
@@ -14189,8 +14206,8 @@ function harvestAntigravityFootprints(repoPath, sinceDate) {
|
|
|
14189
14206
|
const DatabaseSync2 = getSqliteDatabase();
|
|
14190
14207
|
if (!DatabaseSync2)
|
|
14191
14208
|
return footprints;
|
|
14192
|
-
const
|
|
14193
|
-
const antigravityDir = process.env.ANTIGRAVITY_APP_DATA_DIR || path3.join(
|
|
14209
|
+
const homedir8 = os2.homedir();
|
|
14210
|
+
const antigravityDir = process.env.ANTIGRAVITY_APP_DATA_DIR || path3.join(homedir8, ".gemini", "antigravity");
|
|
14194
14211
|
const dbPath = path3.join(antigravityDir, "conversation_summaries.db");
|
|
14195
14212
|
if (!fs2.existsSync(dbPath)) {
|
|
14196
14213
|
return footprints;
|
|
@@ -14230,7 +14247,7 @@ function harvestAntigravityFootprints(repoPath, sinceDate) {
|
|
|
14230
14247
|
continue;
|
|
14231
14248
|
if (line.includes("Model Selection")) {
|
|
14232
14249
|
const match = line.match(/Model Selection` from .*?to ([^\.\(\n\r]+)/);
|
|
14233
|
-
if (match && match[1]) {
|
|
14250
|
+
if (match && match[1] && match[1].length < 30) {
|
|
14234
14251
|
const rawModel = match[1].trim();
|
|
14235
14252
|
if (rawModel.toLowerCase().includes("opus"))
|
|
14236
14253
|
detectedModel = "claude-opus-4-6-thinking";
|
|
@@ -14286,8 +14303,8 @@ function harvestAntigravityFootprints(repoPath, sinceDate) {
|
|
|
14286
14303
|
cached: estimatedCached
|
|
14287
14304
|
},
|
|
14288
14305
|
cost,
|
|
14289
|
-
mode: "
|
|
14290
|
-
confidence: 0.
|
|
14306
|
+
mode: "estimated",
|
|
14307
|
+
confidence: 0.65,
|
|
14291
14308
|
rawTranscriptPath: transcriptPath
|
|
14292
14309
|
});
|
|
14293
14310
|
}
|
|
@@ -14302,8 +14319,8 @@ var path4 = __toESM(require("path"), 1);
|
|
|
14302
14319
|
var os3 = __toESM(require("os"), 1);
|
|
14303
14320
|
function harvestClaudeFootprints(repoPath, projectAlias, sinceDate) {
|
|
14304
14321
|
const footprints = [];
|
|
14305
|
-
const
|
|
14306
|
-
const claudeProjectsDir = path4.join(
|
|
14322
|
+
const homedir8 = os3.homedir();
|
|
14323
|
+
const claudeProjectsDir = path4.join(homedir8, ".claude", "projects");
|
|
14307
14324
|
if (!fs3.existsSync(claudeProjectsDir)) {
|
|
14308
14325
|
return footprints;
|
|
14309
14326
|
}
|
|
@@ -15060,6 +15077,10 @@ function parseSinceOption2(since) {
|
|
|
15060
15077
|
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
15061
15078
|
return today;
|
|
15062
15079
|
}
|
|
15080
|
+
if (s === "yesterday") {
|
|
15081
|
+
const yesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
|
|
15082
|
+
return yesterday;
|
|
15083
|
+
}
|
|
15063
15084
|
const hoursMatch = s.match(/^(\d+)\s*h(?:ours?)?$/);
|
|
15064
15085
|
if (hoursMatch && hoursMatch[1]) {
|
|
15065
15086
|
const hours = parseInt(hoursMatch[1], 10);
|
|
@@ -15105,7 +15126,7 @@ async function harvestUniversalFootprints(options) {
|
|
|
15105
15126
|
allFootprints.push(...trailerFps);
|
|
15106
15127
|
}
|
|
15107
15128
|
const { primary, rankedFootprints } = selectPrimaryFootprint(allFootprints, options.gitContext);
|
|
15108
|
-
allFootprints = rankedFootprints;
|
|
15129
|
+
allFootprints = rankedFootprints.filter((fp) => fp.attributionScore === void 0 || fp.attributionScore >= 0.1);
|
|
15109
15130
|
try {
|
|
15110
15131
|
const db = new LocalStateDB();
|
|
15111
15132
|
for (const fp of allFootprints) {
|
|
@@ -15224,6 +15245,49 @@ function estimateCost(options) {
|
|
|
15224
15245
|
};
|
|
15225
15246
|
}
|
|
15226
15247
|
|
|
15248
|
+
// ../core/dist/pricing-sync.js
|
|
15249
|
+
var fs8 = __toESM(require("fs"), 1);
|
|
15250
|
+
var path9 = __toESM(require("path"), 1);
|
|
15251
|
+
var os7 = __toESM(require("os"), 1);
|
|
15252
|
+
async function syncDynamicPricing(options) {
|
|
15253
|
+
try {
|
|
15254
|
+
const qodewkDir = path9.join(os7.homedir(), ".qodewk");
|
|
15255
|
+
if (!fs8.existsSync(qodewkDir)) {
|
|
15256
|
+
fs8.mkdirSync(qodewkDir, { recursive: true });
|
|
15257
|
+
}
|
|
15258
|
+
const cacheFile = path9.join(qodewkDir, "pricing_registry_cache.json");
|
|
15259
|
+
const TTL_MS = 24 * 60 * 60 * 1e3;
|
|
15260
|
+
const now = Date.now();
|
|
15261
|
+
if (!options?.force && fs8.existsSync(cacheFile)) {
|
|
15262
|
+
try {
|
|
15263
|
+
const stats = fs8.statSync(cacheFile);
|
|
15264
|
+
if (now - stats.mtimeMs < TTL_MS) {
|
|
15265
|
+
const cachedData = JSON.parse(fs8.readFileSync(cacheFile, "utf-8"));
|
|
15266
|
+
if (cachedData.rates) {
|
|
15267
|
+
updatePricingRegistry(cachedData.rates, cachedData.aliases);
|
|
15268
|
+
}
|
|
15269
|
+
return;
|
|
15270
|
+
}
|
|
15271
|
+
} catch {
|
|
15272
|
+
}
|
|
15273
|
+
}
|
|
15274
|
+
const REMOTE_URL = process.env.QODEWK_PRICING_URL || "https://raw.githubusercontent.com/abushaidislam/Qodewk/master/registry/pricing.json";
|
|
15275
|
+
const controller = new AbortController();
|
|
15276
|
+
const timeout = setTimeout(() => controller.abort(), options?.timeoutMs || 2500);
|
|
15277
|
+
const response = await fetch(REMOTE_URL, { signal: controller.signal });
|
|
15278
|
+
clearTimeout(timeout);
|
|
15279
|
+
if (response.ok) {
|
|
15280
|
+
const data = await response.json();
|
|
15281
|
+
if (data && typeof data === "object" && data.rates) {
|
|
15282
|
+
updatePricingRegistry(data.rates, data.aliases);
|
|
15283
|
+
fs8.promises.writeFile(cacheFile, JSON.stringify(data, null, 2), "utf-8").catch(() => {
|
|
15284
|
+
});
|
|
15285
|
+
}
|
|
15286
|
+
}
|
|
15287
|
+
} catch (error) {
|
|
15288
|
+
}
|
|
15289
|
+
}
|
|
15290
|
+
|
|
15227
15291
|
// ../core/dist/format.js
|
|
15228
15292
|
function formatMarkdownReceipt(receipt, publicUrl) {
|
|
15229
15293
|
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || process.env.QODEWK_APP_URL || "https://qodewk.flinkeo.online";
|
|
@@ -15283,6 +15347,7 @@ function sanitizeReceiptForShare(receipt) {
|
|
|
15283
15347
|
};
|
|
15284
15348
|
}
|
|
15285
15349
|
async function generateReceipt(options = {}) {
|
|
15350
|
+
await syncDynamicPricing({ timeoutMs: 1500 });
|
|
15286
15351
|
const metrics = await extractGitMetrics({
|
|
15287
15352
|
repoPath: options.repoPath || process.cwd(),
|
|
15288
15353
|
baseSha: options.baseSha,
|
|
@@ -15388,7 +15453,7 @@ async function generateReceipt(options = {}) {
|
|
|
15388
15453
|
}
|
|
15389
15454
|
|
|
15390
15455
|
// src/receipt-view.ts
|
|
15391
|
-
var
|
|
15456
|
+
var fs9 = __toESM(require("fs"), 1);
|
|
15392
15457
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
15393
15458
|
|
|
15394
15459
|
// src/barcode.ts
|
|
@@ -15618,9 +15683,17 @@ var ansiHex = (hexColor) => {
|
|
|
15618
15683
|
const b2 = num & 255;
|
|
15619
15684
|
return (text) => `\x1B[38;2;${r2};${g};${b2}m${text}\x1B[39m`;
|
|
15620
15685
|
};
|
|
15686
|
+
var bgAnsiHex = (hexColor) => {
|
|
15687
|
+
const num = parseInt(hexColor.replace("#", ""), 16);
|
|
15688
|
+
const r2 = num >> 16 & 255;
|
|
15689
|
+
const g = num >> 8 & 255;
|
|
15690
|
+
const b2 = num & 255;
|
|
15691
|
+
return (text) => `\x1B[48;2;${r2};${g};${b2}m${text}\x1B[49m`;
|
|
15692
|
+
};
|
|
15621
15693
|
var colors = {
|
|
15622
15694
|
coral: ansiHex(THEME.primary),
|
|
15623
15695
|
coralActive: ansiHex(THEME.primaryActive),
|
|
15696
|
+
ink: ansiHex(THEME.ink),
|
|
15624
15697
|
muted: ansiHex(THEME.muted),
|
|
15625
15698
|
mutedSoft: ansiHex(THEME.mutedSoft),
|
|
15626
15699
|
teal: ansiHex(THEME.teal),
|
|
@@ -15630,6 +15703,20 @@ var colors = {
|
|
|
15630
15703
|
hairline: ansiHex(THEME.hairline),
|
|
15631
15704
|
canvas: ansiHex(THEME.canvas)
|
|
15632
15705
|
};
|
|
15706
|
+
var bg = {
|
|
15707
|
+
coral: bgAnsiHex(THEME.primary),
|
|
15708
|
+
teal: bgAnsiHex(THEME.teal),
|
|
15709
|
+
dark: bgAnsiHex(THEME.surfaceDark),
|
|
15710
|
+
card: bgAnsiHex(THEME.surfaceCard)
|
|
15711
|
+
};
|
|
15712
|
+
var bannerGradient = [
|
|
15713
|
+
ansiHex("#e6dfd8"),
|
|
15714
|
+
ansiHex("#b3aca4"),
|
|
15715
|
+
ansiHex("#8e8b82"),
|
|
15716
|
+
ansiHex("#6c6a64"),
|
|
15717
|
+
ansiHex("#454440"),
|
|
15718
|
+
ansiHex("#454440")
|
|
15719
|
+
];
|
|
15633
15720
|
var stripAnsi = (str) => {
|
|
15634
15721
|
return str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "").replace(/\x1B\([B0]/g, "");
|
|
15635
15722
|
};
|
|
@@ -15644,27 +15731,27 @@ function buildTerminalReceipt(receipt, publicUrl) {
|
|
|
15644
15731
|
const green = colors.green;
|
|
15645
15732
|
const red = colors.red;
|
|
15646
15733
|
const teal = colors.teal;
|
|
15647
|
-
const
|
|
15734
|
+
const INNER_WIDTH = 52;
|
|
15648
15735
|
const push = (line) => lines.push(line);
|
|
15649
|
-
const printRow = (content, width =
|
|
15736
|
+
const printRow = (content, width = INNER_WIDTH) => {
|
|
15650
15737
|
const visLen = visibleWidth(content);
|
|
15651
15738
|
const pad = Math.max(0, width - visLen);
|
|
15652
15739
|
push(` | ${content}${" ".repeat(pad)} |`);
|
|
15653
15740
|
};
|
|
15654
|
-
const printRowSplit = (left, right, width =
|
|
15741
|
+
const printRowSplit = (left, right, width = INNER_WIDTH) => {
|
|
15655
15742
|
const leftVis = visibleWidth(left);
|
|
15656
15743
|
const rightVis = visibleWidth(right);
|
|
15657
15744
|
const pad = Math.max(1, width - leftVis - rightVis);
|
|
15658
15745
|
push(` | ${left}${" ".repeat(pad)}${right} |`);
|
|
15659
15746
|
};
|
|
15660
|
-
const printCenteredRow = (content, width =
|
|
15747
|
+
const printCenteredRow = (content, width = INNER_WIDTH) => {
|
|
15661
15748
|
const visLen = visibleWidth(content);
|
|
15662
15749
|
const totalPad = Math.max(0, width - visLen);
|
|
15663
15750
|
const leftPad = Math.floor(totalPad / 2);
|
|
15664
15751
|
const rightPad = totalPad - leftPad;
|
|
15665
15752
|
push(` | ${" ".repeat(leftPad)}${content}${" ".repeat(rightPad)} |`);
|
|
15666
15753
|
};
|
|
15667
|
-
const printDivider = (char = "=", width =
|
|
15754
|
+
const printDivider = (char = "=", width = INNER_WIDTH) => {
|
|
15668
15755
|
push(` | ${char.repeat(width)} |`);
|
|
15669
15756
|
};
|
|
15670
15757
|
const totalTokens = (receipt.ai.tokens.input + receipt.ai.tokens.output).toLocaleString();
|
|
@@ -15713,7 +15800,7 @@ function buildTerminalReceipt(receipt, publicUrl) {
|
|
|
15713
15800
|
}
|
|
15714
15801
|
if (receipt.ai.aiWrittenRatio !== void 0) {
|
|
15715
15802
|
const aiPct = Math.round(receipt.ai.aiWrittenRatio * 100);
|
|
15716
|
-
printRowSplit("AI
|
|
15803
|
+
printRowSplit("AI Touched Files", `${aiPct}% (Human: ${100 - aiPct}%)`);
|
|
15717
15804
|
}
|
|
15718
15805
|
const tokenDetail = `${inputK} in (${Math.round(receipt.ai.tokens.cached / 1e3)}k cached) / ${outputK} out`;
|
|
15719
15806
|
const cleanTokens = tokenDetail.length > 40 ? tokenDetail.slice(0, 39) + "\u2026" : tokenDetail;
|
|
@@ -15735,7 +15822,7 @@ function buildTerminalReceipt(receipt, publicUrl) {
|
|
|
15735
15822
|
maxChars: 28
|
|
15736
15823
|
});
|
|
15737
15824
|
const barcodeRows = renderTerminalBarcode(barcodePayload, {
|
|
15738
|
-
maxWidth:
|
|
15825
|
+
maxWidth: INNER_WIDTH,
|
|
15739
15826
|
height: 3,
|
|
15740
15827
|
quietZone: 8
|
|
15741
15828
|
});
|
|
@@ -15780,7 +15867,7 @@ async function outputReceipt(receipt, options, publicUrl) {
|
|
|
15780
15867
|
}
|
|
15781
15868
|
if (options.out) {
|
|
15782
15869
|
const fileContent = format === "terminal" ? stripAnsi(content) : content;
|
|
15783
|
-
|
|
15870
|
+
fs9.writeFileSync(options.out, fileContent.endsWith("\n") ? fileContent : fileContent + "\n", "utf-8");
|
|
15784
15871
|
console.log(import_picocolors.default.green(`\u2713 Receipt written to ${options.out}`));
|
|
15785
15872
|
}
|
|
15786
15873
|
if (!options.out) {
|
|
@@ -15793,8 +15880,8 @@ async function outputReceipt(receipt, options, publicUrl) {
|
|
|
15793
15880
|
}
|
|
15794
15881
|
|
|
15795
15882
|
// src/hooks.ts
|
|
15796
|
-
var
|
|
15797
|
-
var
|
|
15883
|
+
var fs10 = __toESM(require("fs"), 1);
|
|
15884
|
+
var path10 = __toESM(require("path"), 1);
|
|
15798
15885
|
var HOOK_MARKER_BEGIN = "# --- BEGIN QODEWK HOOK ---";
|
|
15799
15886
|
var HOOK_MARKER_END = "# --- END QODEWK HOOK ---";
|
|
15800
15887
|
var HOOK_SNIPPET = `
|
|
@@ -15806,37 +15893,37 @@ fi
|
|
|
15806
15893
|
${HOOK_MARKER_END}
|
|
15807
15894
|
`;
|
|
15808
15895
|
function resolveGitHooksDir(cwd = process.cwd()) {
|
|
15809
|
-
const gitPath =
|
|
15810
|
-
if (!
|
|
15896
|
+
const gitPath = path10.join(cwd, ".git");
|
|
15897
|
+
if (!fs10.existsSync(gitPath)) return null;
|
|
15811
15898
|
let gitCommonDir;
|
|
15812
|
-
const stat =
|
|
15899
|
+
const stat = fs10.statSync(gitPath);
|
|
15813
15900
|
if (stat.isDirectory()) {
|
|
15814
15901
|
gitCommonDir = gitPath;
|
|
15815
15902
|
} else {
|
|
15816
|
-
const content =
|
|
15903
|
+
const content = fs10.readFileSync(gitPath, "utf-8");
|
|
15817
15904
|
const match = content.match(/gitdir:\s*(.+)/i);
|
|
15818
15905
|
if (!match?.[1]) return null;
|
|
15819
15906
|
let gitDir = match[1].trim();
|
|
15820
|
-
if (!
|
|
15821
|
-
gitDir =
|
|
15907
|
+
if (!path10.isAbsolute(gitDir)) {
|
|
15908
|
+
gitDir = path10.resolve(cwd, gitDir);
|
|
15822
15909
|
}
|
|
15823
|
-
const commonFile =
|
|
15824
|
-
if (
|
|
15825
|
-
let common =
|
|
15826
|
-
if (!
|
|
15827
|
-
common =
|
|
15910
|
+
const commonFile = path10.join(gitDir, "commondir");
|
|
15911
|
+
if (fs10.existsSync(commonFile)) {
|
|
15912
|
+
let common = fs10.readFileSync(commonFile, "utf-8").trim();
|
|
15913
|
+
if (!path10.isAbsolute(common)) {
|
|
15914
|
+
common = path10.resolve(gitDir, common);
|
|
15828
15915
|
}
|
|
15829
15916
|
gitCommonDir = common;
|
|
15830
|
-
} else if (
|
|
15831
|
-
gitCommonDir =
|
|
15917
|
+
} else if (path10.basename(path10.dirname(gitDir)) === "worktrees") {
|
|
15918
|
+
gitCommonDir = path10.dirname(path10.dirname(gitDir));
|
|
15832
15919
|
} else {
|
|
15833
15920
|
gitCommonDir = gitDir;
|
|
15834
15921
|
}
|
|
15835
15922
|
}
|
|
15836
|
-
return
|
|
15923
|
+
return path10.join(gitCommonDir, "hooks");
|
|
15837
15924
|
}
|
|
15838
15925
|
function checkHookStatus(hooksDir) {
|
|
15839
|
-
if (!hooksDir || !
|
|
15926
|
+
if (!hooksDir || !fs10.existsSync(hooksDir)) {
|
|
15840
15927
|
return {
|
|
15841
15928
|
isGit: Boolean(hooksDir),
|
|
15842
15929
|
hooksDir,
|
|
@@ -15844,12 +15931,12 @@ function checkHookStatus(hooksDir) {
|
|
|
15844
15931
|
postRewriteInstalled: false
|
|
15845
15932
|
};
|
|
15846
15933
|
}
|
|
15847
|
-
const postCommit =
|
|
15848
|
-
const postRewrite =
|
|
15934
|
+
const postCommit = path10.join(hooksDir, "post-commit");
|
|
15935
|
+
const postRewrite = path10.join(hooksDir, "post-rewrite");
|
|
15849
15936
|
const hasHook = (p2) => {
|
|
15850
|
-
if (!
|
|
15937
|
+
if (!fs10.existsSync(p2)) return false;
|
|
15851
15938
|
try {
|
|
15852
|
-
const content =
|
|
15939
|
+
const content = fs10.readFileSync(p2, "utf-8");
|
|
15853
15940
|
return content.includes(HOOK_MARKER_BEGIN);
|
|
15854
15941
|
} catch {
|
|
15855
15942
|
return false;
|
|
@@ -15864,32 +15951,40 @@ function checkHookStatus(hooksDir) {
|
|
|
15864
15951
|
}
|
|
15865
15952
|
function installHookFile(hookFile) {
|
|
15866
15953
|
let content = "";
|
|
15867
|
-
if (
|
|
15868
|
-
content =
|
|
15954
|
+
if (fs10.existsSync(hookFile)) {
|
|
15955
|
+
content = fs10.readFileSync(hookFile, "utf-8");
|
|
15869
15956
|
} else {
|
|
15870
15957
|
content = "#!/bin/sh\n";
|
|
15871
15958
|
}
|
|
15872
15959
|
if (content.includes(HOOK_MARKER_BEGIN)) {
|
|
15873
15960
|
return "exists";
|
|
15874
15961
|
}
|
|
15875
|
-
|
|
15962
|
+
fs10.writeFileSync(hookFile, content + HOOK_SNIPPET, { mode: 493 });
|
|
15876
15963
|
return "installed";
|
|
15877
15964
|
}
|
|
15878
15965
|
function uninstallHookFile(hookFile) {
|
|
15879
|
-
if (!
|
|
15880
|
-
const content =
|
|
15966
|
+
if (!fs10.existsSync(hookFile)) return "absent";
|
|
15967
|
+
const content = fs10.readFileSync(hookFile, "utf-8");
|
|
15881
15968
|
if (!content.includes(HOOK_MARKER_BEGIN)) return "missing";
|
|
15882
15969
|
const regex = new RegExp(`\\n?${HOOK_MARKER_BEGIN}[\\s\\S]*?${HOOK_MARKER_END}\\n?`, "g");
|
|
15883
15970
|
const updated = content.replace(regex, "");
|
|
15884
|
-
|
|
15971
|
+
fs10.writeFileSync(hookFile, updated, { mode: 493 });
|
|
15885
15972
|
return "removed";
|
|
15886
15973
|
}
|
|
15887
15974
|
|
|
15888
15975
|
// src/menu.ts
|
|
15889
15976
|
var readline = __toESM(require("readline"), 1);
|
|
15977
|
+
var path11 = __toESM(require("path"), 1);
|
|
15890
15978
|
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
15891
|
-
var INNER_WIDTH = 58;
|
|
15892
15979
|
var SHARE_PAYLOAD_MAX_BYTES = 5e4;
|
|
15980
|
+
var BANNER_LINES = [
|
|
15981
|
+
" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557",
|
|
15982
|
+
" \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2554\u255D",
|
|
15983
|
+
" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2554\u255D ",
|
|
15984
|
+
" \u2588\u2588\u2551\u2584\u2584 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2588\u2588\u2557 ",
|
|
15985
|
+
" \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2554\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2557",
|
|
15986
|
+
" \u255A\u2550\u2550\u2580\u2580\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u255D\u255A\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D"
|
|
15987
|
+
];
|
|
15893
15988
|
var MENU_ITEMS = [
|
|
15894
15989
|
{
|
|
15895
15990
|
id: "receipt",
|
|
@@ -15913,7 +16008,7 @@ var MENU_ITEMS = [
|
|
|
15913
16008
|
id: "hooks",
|
|
15914
16009
|
key: "4",
|
|
15915
16010
|
label: "Configure Git Hooks",
|
|
15916
|
-
description: "Non-blocking background telemetry recording"
|
|
16011
|
+
description: "Non-blocking background telemetry recording (< 5ms)"
|
|
15917
16012
|
},
|
|
15918
16013
|
{
|
|
15919
16014
|
id: "storage",
|
|
@@ -15921,6 +16016,12 @@ var MENU_ITEMS = [
|
|
|
15921
16016
|
label: "Database & Storage Status",
|
|
15922
16017
|
description: "Inspect local SQLite (~/.qodewk/state.db) records"
|
|
15923
16018
|
},
|
|
16019
|
+
{
|
|
16020
|
+
id: "notes",
|
|
16021
|
+
key: "6",
|
|
16022
|
+
label: "Git Notes Management",
|
|
16023
|
+
description: "Inspect & attach receipts to refs/notes/qodewk"
|
|
16024
|
+
},
|
|
15924
16025
|
{
|
|
15925
16026
|
id: "exit",
|
|
15926
16027
|
key: "0",
|
|
@@ -15928,79 +16029,95 @@ var MENU_ITEMS = [
|
|
|
15928
16029
|
description: "Return to shell"
|
|
15929
16030
|
}
|
|
15930
16031
|
];
|
|
15931
|
-
|
|
16032
|
+
var RECEIPT_HORIZON_ITEMS = [
|
|
16033
|
+
{
|
|
16034
|
+
id: "latest",
|
|
16035
|
+
key: "1",
|
|
16036
|
+
label: "Latest Changes (Default)",
|
|
16037
|
+
description: "Current git working tree or latest commit"
|
|
16038
|
+
},
|
|
16039
|
+
{
|
|
16040
|
+
id: "today",
|
|
16041
|
+
key: "2",
|
|
16042
|
+
label: "Today's Work Session",
|
|
16043
|
+
description: "Commits & agent activity since midnight (--today)"
|
|
16044
|
+
},
|
|
16045
|
+
{
|
|
16046
|
+
id: "yesterday",
|
|
16047
|
+
key: "3",
|
|
16048
|
+
label: "Yesterday's Work",
|
|
16049
|
+
description: "Activity from yesterday to now (--since yesterday)"
|
|
16050
|
+
},
|
|
16051
|
+
{
|
|
16052
|
+
id: "week",
|
|
16053
|
+
key: "4",
|
|
16054
|
+
label: "Past 7 Days (Sprint)",
|
|
16055
|
+
description: "Weekly sprint telemetry across all agents (--since 7d)"
|
|
16056
|
+
},
|
|
16057
|
+
{
|
|
16058
|
+
id: "custom",
|
|
16059
|
+
key: "5",
|
|
16060
|
+
label: "Custom Duration",
|
|
16061
|
+
description: "Specify hours (e.g. 12h) or days (e.g. 3d, 14d)"
|
|
16062
|
+
},
|
|
16063
|
+
{
|
|
16064
|
+
id: "back",
|
|
16065
|
+
key: "0",
|
|
16066
|
+
label: "Back to Main Menu",
|
|
16067
|
+
description: "Return to previous screen"
|
|
16068
|
+
}
|
|
16069
|
+
];
|
|
16070
|
+
function buildMenuFrame(selectedIndex, items = MENU_ITEMS, title = "Telemetry Control Panel", subtitle = "\u2191\u2193 move \xB7 enter select \xB7 0-6 quick jump \xB7 q quit", options = {}) {
|
|
15932
16071
|
const lines = [];
|
|
15933
|
-
const coral = colors.coral;
|
|
15934
|
-
const mutedSoft = colors.mutedSoft;
|
|
15935
|
-
const amber = colors.amber;
|
|
15936
|
-
const border = colors.mutedSoft;
|
|
15937
16072
|
const push = (line) => lines.push(line);
|
|
15938
|
-
|
|
15939
|
-
|
|
15940
|
-
|
|
15941
|
-
|
|
15942
|
-
|
|
15943
|
-
const printCenteredRow = (content, width = INNER_WIDTH) => {
|
|
15944
|
-
const visLen = visibleWidth(content);
|
|
15945
|
-
const totalPad = Math.max(0, width - visLen);
|
|
15946
|
-
const leftPad = Math.floor(totalPad / 2);
|
|
15947
|
-
const rightPad = totalPad - leftPad;
|
|
15948
|
-
push(` ${border("\u2502")} ${" ".repeat(leftPad)}${content}${" ".repeat(rightPad)} ${border("\u2502")}`);
|
|
15949
|
-
};
|
|
15950
|
-
const printDivider = (width = INNER_WIDTH) => {
|
|
15951
|
-
push(` ${border("\u251C" + "\u2500".repeat(width + 2) + "\u2524")}`);
|
|
15952
|
-
};
|
|
15953
|
-
push("");
|
|
15954
|
-
push(` ${border("\u250C" + "\u2500".repeat(INNER_WIDTH + 2) + "\u2510")}`);
|
|
15955
|
-
printCenteredRow(import_picocolors2.default.bold(import_picocolors2.default.white("Q O D E W K")));
|
|
15956
|
-
printCenteredRow(coral("Telemetry Control Panel"));
|
|
15957
|
-
printDivider();
|
|
15958
|
-
printCenteredRow(mutedSoft("Use \u2191 / \u2193 to navigate \xB7 Enter to select \xB7 q to quit"));
|
|
15959
|
-
printDivider();
|
|
15960
|
-
printRow("");
|
|
15961
|
-
const mainItems = items.filter((item) => item.id !== "exit");
|
|
15962
|
-
const exitItem = items.find((item) => item.id === "exit");
|
|
15963
|
-
for (let i2 = 0; i2 < mainItems.length; i2++) {
|
|
15964
|
-
const item = mainItems[i2];
|
|
15965
|
-
const itemIndex = items.indexOf(item);
|
|
15966
|
-
const isSelected = itemIndex === selectedIndex;
|
|
15967
|
-
if (isSelected) {
|
|
15968
|
-
const pointer = import_picocolors2.default.bold(coral("\u203A"));
|
|
15969
|
-
const keyTag = import_picocolors2.default.bold(coral(`[${item.key}]`));
|
|
15970
|
-
const label = import_picocolors2.default.bold(import_picocolors2.default.white(item.label));
|
|
15971
|
-
printRow(` ${pointer} ${keyTag} ${label}`);
|
|
15972
|
-
printRow(` ${amber(item.description)}`);
|
|
15973
|
-
} else {
|
|
15974
|
-
const keyTag = mutedSoft(`[${item.key}]`);
|
|
15975
|
-
const label = import_picocolors2.default.dim(import_picocolors2.default.white(item.label));
|
|
15976
|
-
printRow(` ${keyTag} ${label}`);
|
|
15977
|
-
printRow(` ${import_picocolors2.default.dim(item.description)}`);
|
|
15978
|
-
}
|
|
15979
|
-
if (i2 < mainItems.length - 1) {
|
|
15980
|
-
printRow("");
|
|
16073
|
+
if (options.showBanner ?? true) {
|
|
16074
|
+
push("");
|
|
16075
|
+
for (let i2 = 0; i2 < BANNER_LINES.length; i2++) {
|
|
16076
|
+
const gradFn = bannerGradient[i2] || bannerGradient[bannerGradient.length - 1];
|
|
16077
|
+
push(gradFn(BANNER_LINES[i2]));
|
|
15981
16078
|
}
|
|
15982
16079
|
}
|
|
15983
|
-
|
|
15984
|
-
|
|
15985
|
-
|
|
15986
|
-
|
|
15987
|
-
|
|
16080
|
+
push("");
|
|
16081
|
+
const badge = bg.teal(import_picocolors2.default.bold(colors.ink(" qodewk ")));
|
|
16082
|
+
push(` ${colors.mutedSoft("\u250C")} ${badge} ${import_picocolors2.default.dim("v0.9.0")}`);
|
|
16083
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16084
|
+
if (options.actionContext) {
|
|
16085
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors2.default.dim("Action:")} ${import_picocolors2.default.white(options.actionContext)}`);
|
|
16086
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16087
|
+
} else {
|
|
16088
|
+
const repo = options.repoContext?.alias || "Qodewk";
|
|
16089
|
+
const branch = options.repoContext?.branch ? `(${options.repoContext.branch})` : "";
|
|
16090
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors2.default.dim("Repository:")} ${import_picocolors2.default.white(repo)} ${import_picocolors2.default.dim(branch)}`);
|
|
16091
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16092
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors2.default.dim("Telemetry:")} ${import_picocolors2.default.white("Claude Warm Editorial Rate Cards")}`);
|
|
16093
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16094
|
+
}
|
|
16095
|
+
push(` ${colors.coral("\u25C6")} ${import_picocolors2.default.bold(import_picocolors2.default.white(title))}`);
|
|
16096
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16097
|
+
const selectedItem = items[selectedIndex] || items[0];
|
|
16098
|
+
for (let i2 = 0; i2 < items.length; i2++) {
|
|
16099
|
+
const item = items[i2];
|
|
16100
|
+
const isSelected = i2 === selectedIndex;
|
|
15988
16101
|
if (isSelected) {
|
|
15989
|
-
|
|
15990
|
-
|
|
15991
|
-
|
|
15992
|
-
printRow(` ${pointer} ${keyTag} ${label}`);
|
|
15993
|
-
printRow(` ${amber(exitItem.description)}`);
|
|
16102
|
+
push(
|
|
16103
|
+
` ${colors.mutedSoft("\u2502")} ${import_picocolors2.default.bold(colors.coral("\u203A"))} ${import_picocolors2.default.bold(colors.coral(item.key))} ${import_picocolors2.default.bold(import_picocolors2.default.white(item.label))}`
|
|
16104
|
+
);
|
|
15994
16105
|
} else {
|
|
15995
|
-
|
|
15996
|
-
|
|
15997
|
-
|
|
15998
|
-
printRow(` ${import_picocolors2.default.dim(exitItem.description)}`);
|
|
16106
|
+
push(
|
|
16107
|
+
` ${colors.mutedSoft("\u2502")} ${import_picocolors2.default.dim(item.key)} ${import_picocolors2.default.dim(import_picocolors2.default.white(item.label))}`
|
|
16108
|
+
);
|
|
15999
16109
|
}
|
|
16000
16110
|
}
|
|
16001
|
-
|
|
16002
|
-
|
|
16003
|
-
push(` ${
|
|
16111
|
+
const divider = colors.mutedSoft("\u2500".repeat(58));
|
|
16112
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16113
|
+
push(` ${colors.mutedSoft("\u2502")} ${divider}`);
|
|
16114
|
+
push(` ${colors.mutedSoft("\u2502")} ${import_picocolors2.default.bold(import_picocolors2.default.dim("Description"))}`);
|
|
16115
|
+
push(` ${colors.mutedSoft("\u2502")} ${colors.amber(selectedItem.description)}`);
|
|
16116
|
+
push(` ${colors.mutedSoft("\u2502")} ${divider}`);
|
|
16117
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16118
|
+
push(` ${colors.mutedSoft("\u2502")} ${import_picocolors2.default.dim(subtitle)}`);
|
|
16119
|
+
push(` ${colors.mutedSoft("\u2502")} ${colors.green("[\u2713]")} ${import_picocolors2.default.dim("Source code was never uploaded to Qodewk")}`);
|
|
16120
|
+
push(` ${colors.mutedSoft("\u2514")}`);
|
|
16004
16121
|
push("");
|
|
16005
16122
|
return lines.join("\n");
|
|
16006
16123
|
}
|
|
@@ -16034,17 +16151,50 @@ function waitForKeyToReturn() {
|
|
|
16034
16151
|
process.stdin.once("data", onKey);
|
|
16035
16152
|
});
|
|
16036
16153
|
}
|
|
16154
|
+
var cachedRepoContext = null;
|
|
16155
|
+
async function getRepoContext() {
|
|
16156
|
+
if (cachedRepoContext) return cachedRepoContext;
|
|
16157
|
+
try {
|
|
16158
|
+
const { simpleGit: simpleGit2 } = await import("simple-git");
|
|
16159
|
+
const git = simpleGit2(process.cwd());
|
|
16160
|
+
const isRepo = await git.checkIsRepo();
|
|
16161
|
+
if (!isRepo) {
|
|
16162
|
+
cachedRepoContext = { alias: "Workspace", branch: "detached" };
|
|
16163
|
+
return cachedRepoContext;
|
|
16164
|
+
}
|
|
16165
|
+
const branchSummary = await git.branch();
|
|
16166
|
+
const branch = branchSummary.current || "HEAD";
|
|
16167
|
+
const alias = path11.basename(process.cwd());
|
|
16168
|
+
cachedRepoContext = { alias, branch };
|
|
16169
|
+
return cachedRepoContext;
|
|
16170
|
+
} catch {
|
|
16171
|
+
cachedRepoContext = { alias: "Workspace", branch: "detached" };
|
|
16172
|
+
return cachedRepoContext;
|
|
16173
|
+
}
|
|
16174
|
+
}
|
|
16037
16175
|
async function runInteractiveMenu() {
|
|
16038
16176
|
if (!process.stdin.isTTY) {
|
|
16039
16177
|
console.log(buildMenuFrame(0));
|
|
16040
16178
|
console.log(import_picocolors2.default.yellow("Interactive menu requires a TTY terminal. Use `qodewk --help` for commands."));
|
|
16041
16179
|
return;
|
|
16042
16180
|
}
|
|
16181
|
+
const repoContext = await getRepoContext();
|
|
16182
|
+
let currentScreen = "main";
|
|
16043
16183
|
let selectedIndex = 0;
|
|
16044
16184
|
let active = true;
|
|
16045
16185
|
let lastRenderedLinesCount = 0;
|
|
16186
|
+
const getActiveItems = () => currentScreen === "main" ? MENU_ITEMS : RECEIPT_HORIZON_ITEMS;
|
|
16046
16187
|
const render = () => {
|
|
16047
|
-
const
|
|
16188
|
+
const items = getActiveItems();
|
|
16189
|
+
const title = currentScreen === "main" ? "Telemetry Control Panel" : "Generate Local Receipt";
|
|
16190
|
+
const subtitle = currentScreen === "main" ? "\u2191\u2193 move \xB7 enter select \xB7 0-6 quick jump \xB7 q quit" : "\u2191\u2193 move \xB7 enter select \xB7 0-5 quick jump \xB7 esc / 0 back";
|
|
16191
|
+
const actionContext = currentScreen === "receipt_horizon" ? "Generate Local Receipt" : void 0;
|
|
16192
|
+
const showBanner = currentScreen === "main";
|
|
16193
|
+
const frame = buildMenuFrame(selectedIndex, items, title, subtitle, {
|
|
16194
|
+
repoContext,
|
|
16195
|
+
actionContext,
|
|
16196
|
+
showBanner
|
|
16197
|
+
});
|
|
16048
16198
|
const lineCount = frame.split("\n").length;
|
|
16049
16199
|
if (lastRenderedLinesCount > 0) {
|
|
16050
16200
|
readline.cursorTo(process.stdout, 0);
|
|
@@ -16062,28 +16212,52 @@ async function runInteractiveMenu() {
|
|
|
16062
16212
|
process.stdout.write("\x1B[?25h");
|
|
16063
16213
|
};
|
|
16064
16214
|
process.on("exit", cleanup);
|
|
16215
|
+
const executeReceiptHorizon = async (item) => {
|
|
16216
|
+
cleanup();
|
|
16217
|
+
console.log("");
|
|
16218
|
+
lastRenderedLinesCount = 0;
|
|
16219
|
+
let since = void 0;
|
|
16220
|
+
let label = "latest git diff";
|
|
16221
|
+
if (item.id === "today") {
|
|
16222
|
+
since = "today";
|
|
16223
|
+
label = "today's work session (--today)";
|
|
16224
|
+
} else if (item.id === "yesterday") {
|
|
16225
|
+
since = "yesterday";
|
|
16226
|
+
label = "yesterday's work (--since yesterday)";
|
|
16227
|
+
} else if (item.id === "week") {
|
|
16228
|
+
since = "7d";
|
|
16229
|
+
label = "past 7 days weekly sprint (--since 7d)";
|
|
16230
|
+
} else if (item.id === "custom") {
|
|
16231
|
+
console.log(import_picocolors2.default.bold(import_picocolors2.default.white(" Custom Telemetry Horizon")));
|
|
16232
|
+
console.log(import_picocolors2.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
16233
|
+
const input = await askLine(" \u203A Enter duration or date (e.g. 12h, 3d, 2026-10-01): ");
|
|
16234
|
+
if (input) {
|
|
16235
|
+
since = input;
|
|
16236
|
+
label = `custom range: ${input}`;
|
|
16237
|
+
}
|
|
16238
|
+
}
|
|
16239
|
+
console.log(import_picocolors2.default.dim(` [\xB7] Generating local receipt for ${label}...`));
|
|
16240
|
+
try {
|
|
16241
|
+
const receipt = await generateReceipt({ since, isPublic: false });
|
|
16242
|
+
const db = new LocalStateDB();
|
|
16243
|
+
db.saveReceipt(receipt);
|
|
16244
|
+
db.close();
|
|
16245
|
+
await renderTerminalReceipt(receipt);
|
|
16246
|
+
} catch (err) {
|
|
16247
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
16248
|
+
console.error(import_picocolors2.default.red(`
|
|
16249
|
+
Failed to generate receipt: ${message}`));
|
|
16250
|
+
}
|
|
16251
|
+
await waitForKeyToReturn();
|
|
16252
|
+
currentScreen = "main";
|
|
16253
|
+
selectedIndex = 0;
|
|
16254
|
+
};
|
|
16065
16255
|
const executeSelectedAction = async () => {
|
|
16066
16256
|
cleanup();
|
|
16067
16257
|
console.log("");
|
|
16068
16258
|
lastRenderedLinesCount = 0;
|
|
16069
16259
|
const selectedItem = MENU_ITEMS[selectedIndex];
|
|
16070
16260
|
switch (selectedItem.id) {
|
|
16071
|
-
case "receipt": {
|
|
16072
|
-
console.log(import_picocolors2.default.dim(" [\xB7] Generating local receipt from git diff..."));
|
|
16073
|
-
try {
|
|
16074
|
-
const receipt = await generateReceipt({ isPublic: false });
|
|
16075
|
-
const db = new LocalStateDB();
|
|
16076
|
-
db.saveReceipt(receipt);
|
|
16077
|
-
db.close();
|
|
16078
|
-
await renderTerminalReceipt(receipt);
|
|
16079
|
-
} catch (err) {
|
|
16080
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
16081
|
-
console.error(import_picocolors2.default.red(`
|
|
16082
|
-
Failed to generate receipt: ${message}`));
|
|
16083
|
-
}
|
|
16084
|
-
await waitForKeyToReturn();
|
|
16085
|
-
break;
|
|
16086
|
-
}
|
|
16087
16261
|
case "audit": {
|
|
16088
16262
|
console.log(import_picocolors2.default.bold(import_picocolors2.default.white("\n Audit Branch or Revision Diff")));
|
|
16089
16263
|
console.log(import_picocolors2.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
@@ -16148,6 +16322,16 @@ async function runInteractiveMenu() {
|
|
|
16148
16322
|
});
|
|
16149
16323
|
if (!response.ok) {
|
|
16150
16324
|
const errText = await response.text().catch(() => "");
|
|
16325
|
+
if (response.status === 503) {
|
|
16326
|
+
console.log(import_picocolors2.default.yellow("\n Notice: Remote server requires durable storage (Supabase or PostgreSQL) in production"));
|
|
16327
|
+
console.log(import_picocolors2.default.dim(" to protect receipts from serverless cold-start data loss."));
|
|
16328
|
+
console.log(import_picocolors2.default.dim(` Endpoint: ${endpoint}`));
|
|
16329
|
+
console.log(colors.green("\n [\u2713] Your receipt is safely saved locally in: ~/.qodewk/state.db"));
|
|
16330
|
+
console.log(import_picocolors2.default.dim(" You can also save it as a local Git note: qodewk --notes\n"));
|
|
16331
|
+
await renderTerminalReceipt(sanitized);
|
|
16332
|
+
await waitForKeyToReturn();
|
|
16333
|
+
break;
|
|
16334
|
+
}
|
|
16151
16335
|
throw new Error(`API responded with ${response.status}${errText ? `: ${errText.slice(0, 100)}` : ""}`);
|
|
16152
16336
|
}
|
|
16153
16337
|
const data = await response.json();
|
|
@@ -16176,6 +16360,10 @@ async function runInteractiveMenu() {
|
|
|
16176
16360
|
await showStorageStatus();
|
|
16177
16361
|
break;
|
|
16178
16362
|
}
|
|
16363
|
+
case "notes": {
|
|
16364
|
+
await manageGitNotesSubmenu();
|
|
16365
|
+
break;
|
|
16366
|
+
}
|
|
16179
16367
|
case "exit": {
|
|
16180
16368
|
active = false;
|
|
16181
16369
|
cleanup();
|
|
@@ -16210,7 +16398,6 @@ async function runInteractiveMenu() {
|
|
|
16210
16398
|
const choice = await askLine(" \u203A Select option [0-2]: ");
|
|
16211
16399
|
if (choice === "1") {
|
|
16212
16400
|
if (status.hooksDir) {
|
|
16213
|
-
const path11 = await import("path");
|
|
16214
16401
|
const targets = ["post-commit", "post-rewrite"];
|
|
16215
16402
|
for (const t2 of targets) {
|
|
16216
16403
|
installHookFile(path11.join(status.hooksDir, t2));
|
|
@@ -16219,7 +16406,6 @@ async function runInteractiveMenu() {
|
|
|
16219
16406
|
}
|
|
16220
16407
|
} else if (choice === "2") {
|
|
16221
16408
|
if (status.hooksDir) {
|
|
16222
|
-
const path11 = await import("path");
|
|
16223
16409
|
const targets = ["post-commit", "post-rewrite"];
|
|
16224
16410
|
for (const t2 of targets) {
|
|
16225
16411
|
uninstallHookFile(path11.join(status.hooksDir, t2));
|
|
@@ -16229,6 +16415,66 @@ async function runInteractiveMenu() {
|
|
|
16229
16415
|
}
|
|
16230
16416
|
await waitForKeyToReturn();
|
|
16231
16417
|
};
|
|
16418
|
+
const manageGitNotesSubmenu = async () => {
|
|
16419
|
+
console.log(import_picocolors2.default.bold(import_picocolors2.default.white("\n Qodewk Git Notes Management (refs/notes/qodewk)")));
|
|
16420
|
+
console.log(import_picocolors2.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
16421
|
+
console.log(" [1] List commits with attached Qodewk notes");
|
|
16422
|
+
console.log(" [2] Show receipt note on a commit (default: HEAD)");
|
|
16423
|
+
console.log(" [3] Attach receipt note to a Git commit (default: HEAD)");
|
|
16424
|
+
console.log(" [0] Back to main menu");
|
|
16425
|
+
console.log("");
|
|
16426
|
+
const choice = await askLine(" \u203A Select option [0-3]: ");
|
|
16427
|
+
if (choice === "1") {
|
|
16428
|
+
try {
|
|
16429
|
+
const shas = await listGitReceiptNotes();
|
|
16430
|
+
if (shas.length === 0) {
|
|
16431
|
+
console.log(import_picocolors2.default.yellow("\n No Qodewk Git notes found in repository."));
|
|
16432
|
+
} else {
|
|
16433
|
+
console.log(import_picocolors2.default.bold(`
|
|
16434
|
+
Found ${shas.length} commit note(s) in refs/notes/qodewk:`));
|
|
16435
|
+
for (const sha of shas) {
|
|
16436
|
+
console.log(` ${import_picocolors2.default.cyan(sha.slice(0, 10))} ${import_picocolors2.default.dim(sha)}`);
|
|
16437
|
+
}
|
|
16438
|
+
}
|
|
16439
|
+
} catch (err) {
|
|
16440
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
16441
|
+
console.error(import_picocolors2.default.red(`
|
|
16442
|
+
Error listing Git notes: ${message}`));
|
|
16443
|
+
}
|
|
16444
|
+
} else if (choice === "2") {
|
|
16445
|
+
const commit = await askLine(" \u203A Commit SHA or ref [default: HEAD]: ") || "HEAD";
|
|
16446
|
+
try {
|
|
16447
|
+
const receipt = await readGitReceiptNote(commit);
|
|
16448
|
+
if (!receipt) {
|
|
16449
|
+
console.log(import_picocolors2.default.yellow(`
|
|
16450
|
+
No Qodewk receipt note found on commit '${commit}'.`));
|
|
16451
|
+
} else {
|
|
16452
|
+
await renderTerminalReceipt(receipt);
|
|
16453
|
+
}
|
|
16454
|
+
} catch (err) {
|
|
16455
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
16456
|
+
console.error(import_picocolors2.default.red(`
|
|
16457
|
+
Error reading Git note: ${message}`));
|
|
16458
|
+
}
|
|
16459
|
+
} else if (choice === "3") {
|
|
16460
|
+
const commit = await askLine(" \u203A Commit SHA to attach note [default: HEAD]: ") || "HEAD";
|
|
16461
|
+
try {
|
|
16462
|
+
console.log(import_picocolors2.default.dim(`
|
|
16463
|
+
[\xB7] Generating receipt for ${commit}...`));
|
|
16464
|
+
const receipt = await generateReceipt({ headSha: commit });
|
|
16465
|
+
await writeGitReceiptNote(receipt.repository.headSha, receipt);
|
|
16466
|
+
console.log(
|
|
16467
|
+
colors.green(`
|
|
16468
|
+
[\u2713] Attached receipt note to ${receipt.repository.headSha.slice(0, 7)} (refs/notes/qodewk)`)
|
|
16469
|
+
);
|
|
16470
|
+
} catch (err) {
|
|
16471
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
16472
|
+
console.error(import_picocolors2.default.red(`
|
|
16473
|
+
Error writing Git note: ${message}`));
|
|
16474
|
+
}
|
|
16475
|
+
}
|
|
16476
|
+
await waitForKeyToReturn();
|
|
16477
|
+
};
|
|
16232
16478
|
const showStorageStatus = async () => {
|
|
16233
16479
|
console.log(import_picocolors2.default.bold(import_picocolors2.default.white("\n Qodewk Local Database & Storage Status")));
|
|
16234
16480
|
console.log(import_picocolors2.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
@@ -16271,31 +16517,55 @@ async function runInteractiveMenu() {
|
|
|
16271
16517
|
render();
|
|
16272
16518
|
const onKeypress = async (_str, key) => {
|
|
16273
16519
|
if (!active) return;
|
|
16520
|
+
const items = getActiveItems();
|
|
16274
16521
|
if (key.ctrl && key.name === "c") {
|
|
16275
16522
|
cleanup();
|
|
16276
16523
|
process.exit(0);
|
|
16277
16524
|
}
|
|
16278
16525
|
if (key.name === "q" || key.name === "escape") {
|
|
16526
|
+
if (currentScreen !== "main") {
|
|
16527
|
+
currentScreen = "main";
|
|
16528
|
+
selectedIndex = 0;
|
|
16529
|
+
render();
|
|
16530
|
+
return;
|
|
16531
|
+
}
|
|
16279
16532
|
cleanup();
|
|
16280
16533
|
console.log(import_picocolors2.default.dim("\n Exited Qodewk.\n"));
|
|
16281
16534
|
process.exit(0);
|
|
16282
16535
|
}
|
|
16283
16536
|
if (key.name === "up" || key.name === "k") {
|
|
16284
|
-
selectedIndex = (selectedIndex - 1 +
|
|
16537
|
+
selectedIndex = (selectedIndex - 1 + items.length) % items.length;
|
|
16285
16538
|
render();
|
|
16286
16539
|
return;
|
|
16287
16540
|
}
|
|
16288
16541
|
if (key.name === "down" || key.name === "j") {
|
|
16289
|
-
selectedIndex = (selectedIndex + 1) %
|
|
16542
|
+
selectedIndex = (selectedIndex + 1) % items.length;
|
|
16290
16543
|
render();
|
|
16291
16544
|
return;
|
|
16292
16545
|
}
|
|
16293
|
-
const itemByKey =
|
|
16546
|
+
const itemByKey = items.findIndex((item) => item.key === key.name || item.key === _str);
|
|
16294
16547
|
if (itemByKey !== -1) {
|
|
16295
16548
|
selectedIndex = itemByKey;
|
|
16296
16549
|
render();
|
|
16297
16550
|
process.stdin.removeListener("keypress", onKeypress);
|
|
16298
|
-
|
|
16551
|
+
const selected = items[selectedIndex];
|
|
16552
|
+
if (currentScreen === "main") {
|
|
16553
|
+
if (selected.id === "receipt") {
|
|
16554
|
+
currentScreen = "receipt_horizon";
|
|
16555
|
+
selectedIndex = 0;
|
|
16556
|
+
if (active) startLoop();
|
|
16557
|
+
return;
|
|
16558
|
+
}
|
|
16559
|
+
await executeSelectedAction();
|
|
16560
|
+
} else {
|
|
16561
|
+
if (selected.id === "back") {
|
|
16562
|
+
currentScreen = "main";
|
|
16563
|
+
selectedIndex = 0;
|
|
16564
|
+
if (active) startLoop();
|
|
16565
|
+
return;
|
|
16566
|
+
}
|
|
16567
|
+
await executeReceiptHorizon(selected);
|
|
16568
|
+
}
|
|
16299
16569
|
if (active) {
|
|
16300
16570
|
startLoop();
|
|
16301
16571
|
}
|
|
@@ -16303,7 +16573,24 @@ async function runInteractiveMenu() {
|
|
|
16303
16573
|
}
|
|
16304
16574
|
if (key.name === "return" || key.name === "enter") {
|
|
16305
16575
|
process.stdin.removeListener("keypress", onKeypress);
|
|
16306
|
-
|
|
16576
|
+
const selected = items[selectedIndex];
|
|
16577
|
+
if (currentScreen === "main") {
|
|
16578
|
+
if (selected.id === "receipt") {
|
|
16579
|
+
currentScreen = "receipt_horizon";
|
|
16580
|
+
selectedIndex = 0;
|
|
16581
|
+
if (active) startLoop();
|
|
16582
|
+
return;
|
|
16583
|
+
}
|
|
16584
|
+
await executeSelectedAction();
|
|
16585
|
+
} else {
|
|
16586
|
+
if (selected.id === "back") {
|
|
16587
|
+
currentScreen = "main";
|
|
16588
|
+
selectedIndex = 0;
|
|
16589
|
+
if (active) startLoop();
|
|
16590
|
+
return;
|
|
16591
|
+
}
|
|
16592
|
+
await executeReceiptHorizon(selected);
|
|
16593
|
+
}
|
|
16307
16594
|
if (active) {
|
|
16308
16595
|
startLoop();
|
|
16309
16596
|
}
|
|
@@ -16319,19 +16606,19 @@ async function runInteractiveMenu() {
|
|
|
16319
16606
|
var SHARE_PAYLOAD_MAX_BYTES2 = 5e4;
|
|
16320
16607
|
function resolveCliVersion() {
|
|
16321
16608
|
try {
|
|
16322
|
-
const argv1 = process.argv[1] ?
|
|
16609
|
+
const argv1 = process.argv[1] ? path12.dirname(path12.resolve(process.argv[1])) : process.cwd();
|
|
16323
16610
|
const candidates = [
|
|
16324
|
-
|
|
16325
|
-
|
|
16611
|
+
path12.join(argv1, "..", "package.json"),
|
|
16612
|
+
path12.join(argv1, "package.json")
|
|
16326
16613
|
];
|
|
16327
16614
|
for (const candidate of candidates) {
|
|
16328
|
-
if (!
|
|
16329
|
-
const pkg = JSON.parse(
|
|
16615
|
+
if (!fs11.existsSync(candidate)) continue;
|
|
16616
|
+
const pkg = JSON.parse(fs11.readFileSync(candidate, "utf-8"));
|
|
16330
16617
|
if (pkg.name === "qodewk" && pkg.version) return pkg.version;
|
|
16331
16618
|
}
|
|
16332
16619
|
} catch {
|
|
16333
16620
|
}
|
|
16334
|
-
return "0.
|
|
16621
|
+
return "0.9.0";
|
|
16335
16622
|
}
|
|
16336
16623
|
function resolveSince(options) {
|
|
16337
16624
|
return options.today ? "today" : options.since;
|
|
@@ -16350,6 +16637,12 @@ program2.name("qodewk").description("Universal telemetry and digital receipt gen
|
|
|
16350
16637
|
await runInteractiveMenu();
|
|
16351
16638
|
return;
|
|
16352
16639
|
}
|
|
16640
|
+
const hasExplicitOption = options.json || options.out || options.provider || options.model || options.since || options.today || options.platform || options.anon || options.local || options.notes || options.format && options.format !== "terminal";
|
|
16641
|
+
const isInteractiveTerminal = Boolean(process.stdin.isTTY && !process.env.CI);
|
|
16642
|
+
if (!hasExplicitOption && isInteractiveTerminal) {
|
|
16643
|
+
await runInteractiveMenu();
|
|
16644
|
+
return;
|
|
16645
|
+
}
|
|
16353
16646
|
try {
|
|
16354
16647
|
const receipt = await generateReceipt({
|
|
16355
16648
|
provider: options.provider,
|
|
@@ -16492,14 +16785,14 @@ hookCommand.command("install").description("Install non-blocking post-commit and
|
|
|
16492
16785
|
console.error(import_picocolors3.default.red("Error: Current directory is not a Git repository (.git not found)."));
|
|
16493
16786
|
process.exit(1);
|
|
16494
16787
|
}
|
|
16495
|
-
if (!
|
|
16496
|
-
|
|
16788
|
+
if (!fs11.existsSync(hooksDir)) {
|
|
16789
|
+
fs11.mkdirSync(hooksDir, { recursive: true });
|
|
16497
16790
|
}
|
|
16498
16791
|
const targets = ["post-commit", "post-rewrite"];
|
|
16499
16792
|
let installed = 0;
|
|
16500
16793
|
let existing = 0;
|
|
16501
16794
|
for (const name of targets) {
|
|
16502
|
-
const result = installHookFile(
|
|
16795
|
+
const result = installHookFile(path12.join(hooksDir, name));
|
|
16503
16796
|
if (result === "installed") installed++;
|
|
16504
16797
|
else existing++;
|
|
16505
16798
|
}
|
|
@@ -16531,7 +16824,7 @@ hookCommand.command("uninstall").description("Remove Qodewk post-commit and post
|
|
|
16531
16824
|
const targets = ["post-commit", "post-rewrite"];
|
|
16532
16825
|
let removed = 0;
|
|
16533
16826
|
for (const name of targets) {
|
|
16534
|
-
const result = uninstallHookFile(
|
|
16827
|
+
const result = uninstallHookFile(path12.join(hooksDir, name));
|
|
16535
16828
|
if (result === "removed") removed++;
|
|
16536
16829
|
}
|
|
16537
16830
|
if (removed === 0) {
|