qodewk 0.7.0 → 0.8.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 +392 -157
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1153,7 +1153,7 @@ var require_command = __commonJS({
|
|
|
1153
1153
|
"use strict";
|
|
1154
1154
|
var EventEmitter2 = require("events").EventEmitter;
|
|
1155
1155
|
var childProcess = require("child_process");
|
|
1156
|
-
var
|
|
1156
|
+
var path12 = require("path");
|
|
1157
1157
|
var fs11 = require("fs");
|
|
1158
1158
|
var process2 = require("process");
|
|
1159
1159
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
@@ -2153,9 +2153,9 @@ 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 =
|
|
2156
|
+
const localBin = path12.resolve(baseDir, baseName);
|
|
2157
2157
|
if (fs11.existsSync(localBin)) return localBin;
|
|
2158
|
-
if (sourceExt.includes(
|
|
2158
|
+
if (sourceExt.includes(path12.extname(baseName))) return void 0;
|
|
2159
2159
|
const foundExt = sourceExt.find(
|
|
2160
2160
|
(ext) => fs11.existsSync(`${localBin}${ext}`)
|
|
2161
2161
|
);
|
|
@@ -2173,17 +2173,17 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2173
2173
|
} catch {
|
|
2174
2174
|
resolvedScriptPath = this._scriptPath;
|
|
2175
2175
|
}
|
|
2176
|
-
executableDir =
|
|
2177
|
-
|
|
2176
|
+
executableDir = path12.resolve(
|
|
2177
|
+
path12.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 = path12.basename(
|
|
2185
2185
|
this._scriptPath,
|
|
2186
|
-
|
|
2186
|
+
path12.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(path12.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 = path12.basename(filename, path12.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(path13) {
|
|
3059
|
+
if (path13 === void 0) return this._executableDir;
|
|
3060
|
+
this._executableDir = path13;
|
|
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(path12, isFile, isDirectory) {
|
|
4071
|
+
log(`checking %s`, path12);
|
|
4072
4072
|
try {
|
|
4073
|
-
const stat = fs_1.statSync(
|
|
4073
|
+
const stat = fs_1.statSync(path12);
|
|
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(path12, type = exports2.READABLE) {
|
|
4094
|
+
return check(path12, (type & exports2.FILE) > 0, (type & exports2.FOLDER) > 0);
|
|
4095
4095
|
}
|
|
4096
4096
|
exports2.exists = exists2;
|
|
4097
4097
|
exports2.FILE = 1;
|
|
@@ -4156,7 +4156,7 @@ var require_dist2 = __commonJS({
|
|
|
4156
4156
|
|
|
4157
4157
|
// src/index.ts
|
|
4158
4158
|
var fs10 = __toESM(require("fs"), 1);
|
|
4159
|
-
var
|
|
4159
|
+
var path11 = __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: path12, errorMaps, issueData } = params;
|
|
4663
|
+
const fullPath = [...path12, ...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, path12, key) {
|
|
4780
4780
|
this._cachedPath = [];
|
|
4781
4781
|
this.parent = parent;
|
|
4782
4782
|
this.data = value;
|
|
4783
|
-
this._path =
|
|
4783
|
+
this._path = path12;
|
|
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(path12) {
|
|
8896
|
+
return (0, import_file_exists.exists)(path12, 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(path12) {
|
|
9299
|
+
return /^\.(git)?$/.test(path12.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 [path12, line, preview] = input.split(NULL);
|
|
9734
|
+
paths.add(path12);
|
|
9735
|
+
(results[path12] = results[path12] || []).push({
|
|
9736
9736
|
line: asNumber(line),
|
|
9737
|
-
path:
|
|
9737
|
+
path: path12,
|
|
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, path12, 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, path12, false, result[1]);
|
|
10506
10506
|
}
|
|
10507
10507
|
if (result = reInitResponseRegex.exec(response)) {
|
|
10508
|
-
return new InitSummary(bare,
|
|
10508
|
+
return new InitSummary(bare, path12, 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, path12, /^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, path12, existing, gitDir) {
|
|
10529
10529
|
this.bare = bare;
|
|
10530
|
-
this.path =
|
|
10530
|
+
this.path = path12;
|
|
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, path12, 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"), path12, 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(path12, index, working_dir) {
|
|
11367
|
+
this.path = path12;
|
|
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(path12) || [null, path12, path12];
|
|
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, path12) {
|
|
11403
11403
|
const raw = `${index}${workingDir}`;
|
|
11404
11404
|
const handler = parsers6.get(raw);
|
|
11405
11405
|
if (handler) {
|
|
11406
|
-
handler(result,
|
|
11406
|
+
handler(result, path12);
|
|
11407
11407
|
}
|
|
11408
11408
|
if (raw !== "##" && raw !== "!!") {
|
|
11409
|
-
result.files.push(new FileStatusSummary(
|
|
11409
|
+
result.files.push(new FileStatusSummary(path12, 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(path12, write) {
|
|
11761
11761
|
return this._runTask(
|
|
11762
|
-
hashObjectTask(
|
|
11762
|
+
hashObjectTask(path12, 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 path12 = input.trim().replace(/^["']|["']$/g, "");
|
|
12117
|
+
return path12 && (0, import_node_path.normalize)(path12);
|
|
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, path12) {
|
|
12403
|
+
return subModuleTask(["add", repo, path12]);
|
|
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, path12, then) {
|
|
12718
|
+
return this._runTask(addSubModuleTask2(repo, path12), 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);
|
|
@@ -15060,6 +15063,10 @@ function parseSinceOption2(since) {
|
|
|
15060
15063
|
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
15061
15064
|
return today;
|
|
15062
15065
|
}
|
|
15066
|
+
if (s === "yesterday") {
|
|
15067
|
+
const yesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
|
|
15068
|
+
return yesterday;
|
|
15069
|
+
}
|
|
15063
15070
|
const hoursMatch = s.match(/^(\d+)\s*h(?:ours?)?$/);
|
|
15064
15071
|
if (hoursMatch && hoursMatch[1]) {
|
|
15065
15072
|
const hours = parseInt(hoursMatch[1], 10);
|
|
@@ -15618,9 +15625,17 @@ var ansiHex = (hexColor) => {
|
|
|
15618
15625
|
const b2 = num & 255;
|
|
15619
15626
|
return (text) => `\x1B[38;2;${r2};${g};${b2}m${text}\x1B[39m`;
|
|
15620
15627
|
};
|
|
15628
|
+
var bgAnsiHex = (hexColor) => {
|
|
15629
|
+
const num = parseInt(hexColor.replace("#", ""), 16);
|
|
15630
|
+
const r2 = num >> 16 & 255;
|
|
15631
|
+
const g = num >> 8 & 255;
|
|
15632
|
+
const b2 = num & 255;
|
|
15633
|
+
return (text) => `\x1B[48;2;${r2};${g};${b2}m${text}\x1B[49m`;
|
|
15634
|
+
};
|
|
15621
15635
|
var colors = {
|
|
15622
15636
|
coral: ansiHex(THEME.primary),
|
|
15623
15637
|
coralActive: ansiHex(THEME.primaryActive),
|
|
15638
|
+
ink: ansiHex(THEME.ink),
|
|
15624
15639
|
muted: ansiHex(THEME.muted),
|
|
15625
15640
|
mutedSoft: ansiHex(THEME.mutedSoft),
|
|
15626
15641
|
teal: ansiHex(THEME.teal),
|
|
@@ -15630,6 +15645,20 @@ var colors = {
|
|
|
15630
15645
|
hairline: ansiHex(THEME.hairline),
|
|
15631
15646
|
canvas: ansiHex(THEME.canvas)
|
|
15632
15647
|
};
|
|
15648
|
+
var bg = {
|
|
15649
|
+
coral: bgAnsiHex(THEME.primary),
|
|
15650
|
+
teal: bgAnsiHex(THEME.teal),
|
|
15651
|
+
dark: bgAnsiHex(THEME.surfaceDark),
|
|
15652
|
+
card: bgAnsiHex(THEME.surfaceCard)
|
|
15653
|
+
};
|
|
15654
|
+
var bannerGradient = [
|
|
15655
|
+
ansiHex("#e6dfd8"),
|
|
15656
|
+
ansiHex("#b3aca4"),
|
|
15657
|
+
ansiHex("#8e8b82"),
|
|
15658
|
+
ansiHex("#6c6a64"),
|
|
15659
|
+
ansiHex("#454440"),
|
|
15660
|
+
ansiHex("#454440")
|
|
15661
|
+
];
|
|
15633
15662
|
var stripAnsi = (str) => {
|
|
15634
15663
|
return str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "").replace(/\x1B\([B0]/g, "");
|
|
15635
15664
|
};
|
|
@@ -15644,27 +15673,27 @@ function buildTerminalReceipt(receipt, publicUrl) {
|
|
|
15644
15673
|
const green = colors.green;
|
|
15645
15674
|
const red = colors.red;
|
|
15646
15675
|
const teal = colors.teal;
|
|
15647
|
-
const
|
|
15676
|
+
const INNER_WIDTH = 52;
|
|
15648
15677
|
const push = (line) => lines.push(line);
|
|
15649
|
-
const printRow = (content, width =
|
|
15678
|
+
const printRow = (content, width = INNER_WIDTH) => {
|
|
15650
15679
|
const visLen = visibleWidth(content);
|
|
15651
15680
|
const pad = Math.max(0, width - visLen);
|
|
15652
15681
|
push(` | ${content}${" ".repeat(pad)} |`);
|
|
15653
15682
|
};
|
|
15654
|
-
const printRowSplit = (left, right, width =
|
|
15683
|
+
const printRowSplit = (left, right, width = INNER_WIDTH) => {
|
|
15655
15684
|
const leftVis = visibleWidth(left);
|
|
15656
15685
|
const rightVis = visibleWidth(right);
|
|
15657
15686
|
const pad = Math.max(1, width - leftVis - rightVis);
|
|
15658
15687
|
push(` | ${left}${" ".repeat(pad)}${right} |`);
|
|
15659
15688
|
};
|
|
15660
|
-
const printCenteredRow = (content, width =
|
|
15689
|
+
const printCenteredRow = (content, width = INNER_WIDTH) => {
|
|
15661
15690
|
const visLen = visibleWidth(content);
|
|
15662
15691
|
const totalPad = Math.max(0, width - visLen);
|
|
15663
15692
|
const leftPad = Math.floor(totalPad / 2);
|
|
15664
15693
|
const rightPad = totalPad - leftPad;
|
|
15665
15694
|
push(` | ${" ".repeat(leftPad)}${content}${" ".repeat(rightPad)} |`);
|
|
15666
15695
|
};
|
|
15667
|
-
const printDivider = (char = "=", width =
|
|
15696
|
+
const printDivider = (char = "=", width = INNER_WIDTH) => {
|
|
15668
15697
|
push(` | ${char.repeat(width)} |`);
|
|
15669
15698
|
};
|
|
15670
15699
|
const totalTokens = (receipt.ai.tokens.input + receipt.ai.tokens.output).toLocaleString();
|
|
@@ -15735,7 +15764,7 @@ function buildTerminalReceipt(receipt, publicUrl) {
|
|
|
15735
15764
|
maxChars: 28
|
|
15736
15765
|
});
|
|
15737
15766
|
const barcodeRows = renderTerminalBarcode(barcodePayload, {
|
|
15738
|
-
maxWidth:
|
|
15767
|
+
maxWidth: INNER_WIDTH,
|
|
15739
15768
|
height: 3,
|
|
15740
15769
|
quietZone: 8
|
|
15741
15770
|
});
|
|
@@ -15887,9 +15916,17 @@ function uninstallHookFile(hookFile) {
|
|
|
15887
15916
|
|
|
15888
15917
|
// src/menu.ts
|
|
15889
15918
|
var readline = __toESM(require("readline"), 1);
|
|
15919
|
+
var path10 = __toESM(require("path"), 1);
|
|
15890
15920
|
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
15891
|
-
var INNER_WIDTH = 58;
|
|
15892
15921
|
var SHARE_PAYLOAD_MAX_BYTES = 5e4;
|
|
15922
|
+
var BANNER_LINES = [
|
|
15923
|
+
" \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",
|
|
15924
|
+
" \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",
|
|
15925
|
+
" \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 ",
|
|
15926
|
+
" \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 ",
|
|
15927
|
+
" \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",
|
|
15928
|
+
" \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"
|
|
15929
|
+
];
|
|
15893
15930
|
var MENU_ITEMS = [
|
|
15894
15931
|
{
|
|
15895
15932
|
id: "receipt",
|
|
@@ -15913,7 +15950,7 @@ var MENU_ITEMS = [
|
|
|
15913
15950
|
id: "hooks",
|
|
15914
15951
|
key: "4",
|
|
15915
15952
|
label: "Configure Git Hooks",
|
|
15916
|
-
description: "Non-blocking background telemetry recording"
|
|
15953
|
+
description: "Non-blocking background telemetry recording (< 5ms)"
|
|
15917
15954
|
},
|
|
15918
15955
|
{
|
|
15919
15956
|
id: "storage",
|
|
@@ -15921,6 +15958,12 @@ var MENU_ITEMS = [
|
|
|
15921
15958
|
label: "Database & Storage Status",
|
|
15922
15959
|
description: "Inspect local SQLite (~/.qodewk/state.db) records"
|
|
15923
15960
|
},
|
|
15961
|
+
{
|
|
15962
|
+
id: "notes",
|
|
15963
|
+
key: "6",
|
|
15964
|
+
label: "Git Notes Management",
|
|
15965
|
+
description: "Inspect & attach receipts to refs/notes/qodewk"
|
|
15966
|
+
},
|
|
15924
15967
|
{
|
|
15925
15968
|
id: "exit",
|
|
15926
15969
|
key: "0",
|
|
@@ -15928,79 +15971,95 @@ var MENU_ITEMS = [
|
|
|
15928
15971
|
description: "Return to shell"
|
|
15929
15972
|
}
|
|
15930
15973
|
];
|
|
15931
|
-
|
|
15974
|
+
var RECEIPT_HORIZON_ITEMS = [
|
|
15975
|
+
{
|
|
15976
|
+
id: "latest",
|
|
15977
|
+
key: "1",
|
|
15978
|
+
label: "Latest Changes (Default)",
|
|
15979
|
+
description: "Current git working tree or latest commit"
|
|
15980
|
+
},
|
|
15981
|
+
{
|
|
15982
|
+
id: "today",
|
|
15983
|
+
key: "2",
|
|
15984
|
+
label: "Today's Work Session",
|
|
15985
|
+
description: "Commits & agent activity since midnight (--today)"
|
|
15986
|
+
},
|
|
15987
|
+
{
|
|
15988
|
+
id: "yesterday",
|
|
15989
|
+
key: "3",
|
|
15990
|
+
label: "Yesterday's Work",
|
|
15991
|
+
description: "Activity from yesterday to now (--since yesterday)"
|
|
15992
|
+
},
|
|
15993
|
+
{
|
|
15994
|
+
id: "week",
|
|
15995
|
+
key: "4",
|
|
15996
|
+
label: "Past 7 Days (Sprint)",
|
|
15997
|
+
description: "Weekly sprint telemetry across all agents (--since 7d)"
|
|
15998
|
+
},
|
|
15999
|
+
{
|
|
16000
|
+
id: "custom",
|
|
16001
|
+
key: "5",
|
|
16002
|
+
label: "Custom Duration",
|
|
16003
|
+
description: "Specify hours (e.g. 12h) or days (e.g. 3d, 14d)"
|
|
16004
|
+
},
|
|
16005
|
+
{
|
|
16006
|
+
id: "back",
|
|
16007
|
+
key: "0",
|
|
16008
|
+
label: "Back to Main Menu",
|
|
16009
|
+
description: "Return to previous screen"
|
|
16010
|
+
}
|
|
16011
|
+
];
|
|
16012
|
+
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
16013
|
const lines = [];
|
|
15933
|
-
const coral = colors.coral;
|
|
15934
|
-
const mutedSoft = colors.mutedSoft;
|
|
15935
|
-
const amber = colors.amber;
|
|
15936
|
-
const border = colors.mutedSoft;
|
|
15937
16014
|
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("");
|
|
16015
|
+
if (options.showBanner ?? true) {
|
|
16016
|
+
push("");
|
|
16017
|
+
for (let i2 = 0; i2 < BANNER_LINES.length; i2++) {
|
|
16018
|
+
const gradFn = bannerGradient[i2] || bannerGradient[bannerGradient.length - 1];
|
|
16019
|
+
push(gradFn(BANNER_LINES[i2]));
|
|
15981
16020
|
}
|
|
15982
16021
|
}
|
|
15983
|
-
|
|
15984
|
-
|
|
15985
|
-
|
|
15986
|
-
|
|
15987
|
-
|
|
16022
|
+
push("");
|
|
16023
|
+
const badge = bg.teal(import_picocolors2.default.bold(colors.ink(" qodewk ")));
|
|
16024
|
+
push(` ${colors.mutedSoft("\u250C")} ${badge} ${import_picocolors2.default.dim("v0.8.0")}`);
|
|
16025
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16026
|
+
if (options.actionContext) {
|
|
16027
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors2.default.dim("Action:")} ${import_picocolors2.default.white(options.actionContext)}`);
|
|
16028
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16029
|
+
} else {
|
|
16030
|
+
const repo = options.repoContext?.alias || "Qodewk";
|
|
16031
|
+
const branch = options.repoContext?.branch ? `(${options.repoContext.branch})` : "";
|
|
16032
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors2.default.dim("Repository:")} ${import_picocolors2.default.white(repo)} ${import_picocolors2.default.dim(branch)}`);
|
|
16033
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16034
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors2.default.dim("Telemetry:")} ${import_picocolors2.default.white("Claude Warm Editorial Rate Cards")}`);
|
|
16035
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16036
|
+
}
|
|
16037
|
+
push(` ${colors.coral("\u25C6")} ${import_picocolors2.default.bold(import_picocolors2.default.white(title))}`);
|
|
16038
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16039
|
+
const selectedItem = items[selectedIndex] || items[0];
|
|
16040
|
+
for (let i2 = 0; i2 < items.length; i2++) {
|
|
16041
|
+
const item = items[i2];
|
|
16042
|
+
const isSelected = i2 === selectedIndex;
|
|
15988
16043
|
if (isSelected) {
|
|
15989
|
-
|
|
15990
|
-
|
|
15991
|
-
|
|
15992
|
-
printRow(` ${pointer} ${keyTag} ${label}`);
|
|
15993
|
-
printRow(` ${amber(exitItem.description)}`);
|
|
16044
|
+
push(
|
|
16045
|
+
` ${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))}`
|
|
16046
|
+
);
|
|
15994
16047
|
} else {
|
|
15995
|
-
|
|
15996
|
-
|
|
15997
|
-
|
|
15998
|
-
printRow(` ${import_picocolors2.default.dim(exitItem.description)}`);
|
|
16048
|
+
push(
|
|
16049
|
+
` ${colors.mutedSoft("\u2502")} ${import_picocolors2.default.dim(item.key)} ${import_picocolors2.default.dim(import_picocolors2.default.white(item.label))}`
|
|
16050
|
+
);
|
|
15999
16051
|
}
|
|
16000
16052
|
}
|
|
16001
|
-
|
|
16002
|
-
|
|
16003
|
-
push(` ${
|
|
16053
|
+
const divider = colors.mutedSoft("\u2500".repeat(58));
|
|
16054
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16055
|
+
push(` ${colors.mutedSoft("\u2502")} ${divider}`);
|
|
16056
|
+
push(` ${colors.mutedSoft("\u2502")} ${import_picocolors2.default.bold(import_picocolors2.default.dim("Description"))}`);
|
|
16057
|
+
push(` ${colors.mutedSoft("\u2502")} ${colors.amber(selectedItem.description)}`);
|
|
16058
|
+
push(` ${colors.mutedSoft("\u2502")} ${divider}`);
|
|
16059
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16060
|
+
push(` ${colors.mutedSoft("\u2502")} ${import_picocolors2.default.dim(subtitle)}`);
|
|
16061
|
+
push(` ${colors.mutedSoft("\u2502")} ${colors.green("[\u2713]")} ${import_picocolors2.default.dim("Source code was never uploaded to Qodewk")}`);
|
|
16062
|
+
push(` ${colors.mutedSoft("\u2514")}`);
|
|
16004
16063
|
push("");
|
|
16005
16064
|
return lines.join("\n");
|
|
16006
16065
|
}
|
|
@@ -16034,17 +16093,50 @@ function waitForKeyToReturn() {
|
|
|
16034
16093
|
process.stdin.once("data", onKey);
|
|
16035
16094
|
});
|
|
16036
16095
|
}
|
|
16096
|
+
var cachedRepoContext = null;
|
|
16097
|
+
async function getRepoContext() {
|
|
16098
|
+
if (cachedRepoContext) return cachedRepoContext;
|
|
16099
|
+
try {
|
|
16100
|
+
const { simpleGit: simpleGit2 } = await import("simple-git");
|
|
16101
|
+
const git = simpleGit2(process.cwd());
|
|
16102
|
+
const isRepo = await git.checkIsRepo();
|
|
16103
|
+
if (!isRepo) {
|
|
16104
|
+
cachedRepoContext = { alias: "Workspace", branch: "detached" };
|
|
16105
|
+
return cachedRepoContext;
|
|
16106
|
+
}
|
|
16107
|
+
const branchSummary = await git.branch();
|
|
16108
|
+
const branch = branchSummary.current || "HEAD";
|
|
16109
|
+
const alias = path10.basename(process.cwd());
|
|
16110
|
+
cachedRepoContext = { alias, branch };
|
|
16111
|
+
return cachedRepoContext;
|
|
16112
|
+
} catch {
|
|
16113
|
+
cachedRepoContext = { alias: "Workspace", branch: "detached" };
|
|
16114
|
+
return cachedRepoContext;
|
|
16115
|
+
}
|
|
16116
|
+
}
|
|
16037
16117
|
async function runInteractiveMenu() {
|
|
16038
16118
|
if (!process.stdin.isTTY) {
|
|
16039
16119
|
console.log(buildMenuFrame(0));
|
|
16040
16120
|
console.log(import_picocolors2.default.yellow("Interactive menu requires a TTY terminal. Use `qodewk --help` for commands."));
|
|
16041
16121
|
return;
|
|
16042
16122
|
}
|
|
16123
|
+
const repoContext = await getRepoContext();
|
|
16124
|
+
let currentScreen = "main";
|
|
16043
16125
|
let selectedIndex = 0;
|
|
16044
16126
|
let active = true;
|
|
16045
16127
|
let lastRenderedLinesCount = 0;
|
|
16128
|
+
const getActiveItems = () => currentScreen === "main" ? MENU_ITEMS : RECEIPT_HORIZON_ITEMS;
|
|
16046
16129
|
const render = () => {
|
|
16047
|
-
const
|
|
16130
|
+
const items = getActiveItems();
|
|
16131
|
+
const title = currentScreen === "main" ? "Telemetry Control Panel" : "Generate Local Receipt";
|
|
16132
|
+
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";
|
|
16133
|
+
const actionContext = currentScreen === "receipt_horizon" ? "Generate Local Receipt" : void 0;
|
|
16134
|
+
const showBanner = currentScreen === "main";
|
|
16135
|
+
const frame = buildMenuFrame(selectedIndex, items, title, subtitle, {
|
|
16136
|
+
repoContext,
|
|
16137
|
+
actionContext,
|
|
16138
|
+
showBanner
|
|
16139
|
+
});
|
|
16048
16140
|
const lineCount = frame.split("\n").length;
|
|
16049
16141
|
if (lastRenderedLinesCount > 0) {
|
|
16050
16142
|
readline.cursorTo(process.stdout, 0);
|
|
@@ -16062,28 +16154,52 @@ async function runInteractiveMenu() {
|
|
|
16062
16154
|
process.stdout.write("\x1B[?25h");
|
|
16063
16155
|
};
|
|
16064
16156
|
process.on("exit", cleanup);
|
|
16157
|
+
const executeReceiptHorizon = async (item) => {
|
|
16158
|
+
cleanup();
|
|
16159
|
+
console.log("");
|
|
16160
|
+
lastRenderedLinesCount = 0;
|
|
16161
|
+
let since = void 0;
|
|
16162
|
+
let label = "latest git diff";
|
|
16163
|
+
if (item.id === "today") {
|
|
16164
|
+
since = "today";
|
|
16165
|
+
label = "today's work session (--today)";
|
|
16166
|
+
} else if (item.id === "yesterday") {
|
|
16167
|
+
since = "yesterday";
|
|
16168
|
+
label = "yesterday's work (--since yesterday)";
|
|
16169
|
+
} else if (item.id === "week") {
|
|
16170
|
+
since = "7d";
|
|
16171
|
+
label = "past 7 days weekly sprint (--since 7d)";
|
|
16172
|
+
} else if (item.id === "custom") {
|
|
16173
|
+
console.log(import_picocolors2.default.bold(import_picocolors2.default.white(" Custom Telemetry Horizon")));
|
|
16174
|
+
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"));
|
|
16175
|
+
const input = await askLine(" \u203A Enter duration or date (e.g. 12h, 3d, 2026-10-01): ");
|
|
16176
|
+
if (input) {
|
|
16177
|
+
since = input;
|
|
16178
|
+
label = `custom range: ${input}`;
|
|
16179
|
+
}
|
|
16180
|
+
}
|
|
16181
|
+
console.log(import_picocolors2.default.dim(` [\xB7] Generating local receipt for ${label}...`));
|
|
16182
|
+
try {
|
|
16183
|
+
const receipt = await generateReceipt({ since, isPublic: false });
|
|
16184
|
+
const db = new LocalStateDB();
|
|
16185
|
+
db.saveReceipt(receipt);
|
|
16186
|
+
db.close();
|
|
16187
|
+
await renderTerminalReceipt(receipt);
|
|
16188
|
+
} catch (err) {
|
|
16189
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
16190
|
+
console.error(import_picocolors2.default.red(`
|
|
16191
|
+
Failed to generate receipt: ${message}`));
|
|
16192
|
+
}
|
|
16193
|
+
await waitForKeyToReturn();
|
|
16194
|
+
currentScreen = "main";
|
|
16195
|
+
selectedIndex = 0;
|
|
16196
|
+
};
|
|
16065
16197
|
const executeSelectedAction = async () => {
|
|
16066
16198
|
cleanup();
|
|
16067
16199
|
console.log("");
|
|
16068
16200
|
lastRenderedLinesCount = 0;
|
|
16069
16201
|
const selectedItem = MENU_ITEMS[selectedIndex];
|
|
16070
16202
|
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
16203
|
case "audit": {
|
|
16088
16204
|
console.log(import_picocolors2.default.bold(import_picocolors2.default.white("\n Audit Branch or Revision Diff")));
|
|
16089
16205
|
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 +16264,16 @@ async function runInteractiveMenu() {
|
|
|
16148
16264
|
});
|
|
16149
16265
|
if (!response.ok) {
|
|
16150
16266
|
const errText = await response.text().catch(() => "");
|
|
16267
|
+
if (response.status === 503) {
|
|
16268
|
+
console.log(import_picocolors2.default.yellow("\n Notice: Remote server requires durable storage (Supabase or PostgreSQL) in production"));
|
|
16269
|
+
console.log(import_picocolors2.default.dim(" to protect receipts from serverless cold-start data loss."));
|
|
16270
|
+
console.log(import_picocolors2.default.dim(` Endpoint: ${endpoint}`));
|
|
16271
|
+
console.log(colors.green("\n [\u2713] Your receipt is safely saved locally in: ~/.qodewk/state.db"));
|
|
16272
|
+
console.log(import_picocolors2.default.dim(" You can also save it as a local Git note: qodewk --notes\n"));
|
|
16273
|
+
await renderTerminalReceipt(sanitized);
|
|
16274
|
+
await waitForKeyToReturn();
|
|
16275
|
+
break;
|
|
16276
|
+
}
|
|
16151
16277
|
throw new Error(`API responded with ${response.status}${errText ? `: ${errText.slice(0, 100)}` : ""}`);
|
|
16152
16278
|
}
|
|
16153
16279
|
const data = await response.json();
|
|
@@ -16176,6 +16302,10 @@ async function runInteractiveMenu() {
|
|
|
16176
16302
|
await showStorageStatus();
|
|
16177
16303
|
break;
|
|
16178
16304
|
}
|
|
16305
|
+
case "notes": {
|
|
16306
|
+
await manageGitNotesSubmenu();
|
|
16307
|
+
break;
|
|
16308
|
+
}
|
|
16179
16309
|
case "exit": {
|
|
16180
16310
|
active = false;
|
|
16181
16311
|
cleanup();
|
|
@@ -16210,25 +16340,83 @@ async function runInteractiveMenu() {
|
|
|
16210
16340
|
const choice = await askLine(" \u203A Select option [0-2]: ");
|
|
16211
16341
|
if (choice === "1") {
|
|
16212
16342
|
if (status.hooksDir) {
|
|
16213
|
-
const path11 = await import("path");
|
|
16214
16343
|
const targets = ["post-commit", "post-rewrite"];
|
|
16215
16344
|
for (const t2 of targets) {
|
|
16216
|
-
installHookFile(
|
|
16345
|
+
installHookFile(path10.join(status.hooksDir, t2));
|
|
16217
16346
|
}
|
|
16218
16347
|
console.log(colors.green("\n [\u2713] Non-blocking hooks installed successfully."));
|
|
16219
16348
|
}
|
|
16220
16349
|
} else if (choice === "2") {
|
|
16221
16350
|
if (status.hooksDir) {
|
|
16222
|
-
const path11 = await import("path");
|
|
16223
16351
|
const targets = ["post-commit", "post-rewrite"];
|
|
16224
16352
|
for (const t2 of targets) {
|
|
16225
|
-
uninstallHookFile(
|
|
16353
|
+
uninstallHookFile(path10.join(status.hooksDir, t2));
|
|
16226
16354
|
}
|
|
16227
16355
|
console.log(colors.green("\n [\u2713] Qodewk hooks removed."));
|
|
16228
16356
|
}
|
|
16229
16357
|
}
|
|
16230
16358
|
await waitForKeyToReturn();
|
|
16231
16359
|
};
|
|
16360
|
+
const manageGitNotesSubmenu = async () => {
|
|
16361
|
+
console.log(import_picocolors2.default.bold(import_picocolors2.default.white("\n Qodewk Git Notes Management (refs/notes/qodewk)")));
|
|
16362
|
+
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"));
|
|
16363
|
+
console.log(" [1] List commits with attached Qodewk notes");
|
|
16364
|
+
console.log(" [2] Show receipt note on a commit (default: HEAD)");
|
|
16365
|
+
console.log(" [3] Attach receipt note to a Git commit (default: HEAD)");
|
|
16366
|
+
console.log(" [0] Back to main menu");
|
|
16367
|
+
console.log("");
|
|
16368
|
+
const choice = await askLine(" \u203A Select option [0-3]: ");
|
|
16369
|
+
if (choice === "1") {
|
|
16370
|
+
try {
|
|
16371
|
+
const shas = await listGitReceiptNotes();
|
|
16372
|
+
if (shas.length === 0) {
|
|
16373
|
+
console.log(import_picocolors2.default.yellow("\n No Qodewk Git notes found in repository."));
|
|
16374
|
+
} else {
|
|
16375
|
+
console.log(import_picocolors2.default.bold(`
|
|
16376
|
+
Found ${shas.length} commit note(s) in refs/notes/qodewk:`));
|
|
16377
|
+
for (const sha of shas) {
|
|
16378
|
+
console.log(` ${import_picocolors2.default.cyan(sha.slice(0, 10))} ${import_picocolors2.default.dim(sha)}`);
|
|
16379
|
+
}
|
|
16380
|
+
}
|
|
16381
|
+
} catch (err) {
|
|
16382
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
16383
|
+
console.error(import_picocolors2.default.red(`
|
|
16384
|
+
Error listing Git notes: ${message}`));
|
|
16385
|
+
}
|
|
16386
|
+
} else if (choice === "2") {
|
|
16387
|
+
const commit = await askLine(" \u203A Commit SHA or ref [default: HEAD]: ") || "HEAD";
|
|
16388
|
+
try {
|
|
16389
|
+
const receipt = await readGitReceiptNote(commit);
|
|
16390
|
+
if (!receipt) {
|
|
16391
|
+
console.log(import_picocolors2.default.yellow(`
|
|
16392
|
+
No Qodewk receipt note found on commit '${commit}'.`));
|
|
16393
|
+
} else {
|
|
16394
|
+
await renderTerminalReceipt(receipt);
|
|
16395
|
+
}
|
|
16396
|
+
} catch (err) {
|
|
16397
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
16398
|
+
console.error(import_picocolors2.default.red(`
|
|
16399
|
+
Error reading Git note: ${message}`));
|
|
16400
|
+
}
|
|
16401
|
+
} else if (choice === "3") {
|
|
16402
|
+
const commit = await askLine(" \u203A Commit SHA to attach note [default: HEAD]: ") || "HEAD";
|
|
16403
|
+
try {
|
|
16404
|
+
console.log(import_picocolors2.default.dim(`
|
|
16405
|
+
[\xB7] Generating receipt for ${commit}...`));
|
|
16406
|
+
const receipt = await generateReceipt({ headSha: commit });
|
|
16407
|
+
await writeGitReceiptNote(receipt.repository.headSha, receipt);
|
|
16408
|
+
console.log(
|
|
16409
|
+
colors.green(`
|
|
16410
|
+
[\u2713] Attached receipt note to ${receipt.repository.headSha.slice(0, 7)} (refs/notes/qodewk)`)
|
|
16411
|
+
);
|
|
16412
|
+
} catch (err) {
|
|
16413
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
16414
|
+
console.error(import_picocolors2.default.red(`
|
|
16415
|
+
Error writing Git note: ${message}`));
|
|
16416
|
+
}
|
|
16417
|
+
}
|
|
16418
|
+
await waitForKeyToReturn();
|
|
16419
|
+
};
|
|
16232
16420
|
const showStorageStatus = async () => {
|
|
16233
16421
|
console.log(import_picocolors2.default.bold(import_picocolors2.default.white("\n Qodewk Local Database & Storage Status")));
|
|
16234
16422
|
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 +16459,55 @@ async function runInteractiveMenu() {
|
|
|
16271
16459
|
render();
|
|
16272
16460
|
const onKeypress = async (_str, key) => {
|
|
16273
16461
|
if (!active) return;
|
|
16462
|
+
const items = getActiveItems();
|
|
16274
16463
|
if (key.ctrl && key.name === "c") {
|
|
16275
16464
|
cleanup();
|
|
16276
16465
|
process.exit(0);
|
|
16277
16466
|
}
|
|
16278
16467
|
if (key.name === "q" || key.name === "escape") {
|
|
16468
|
+
if (currentScreen !== "main") {
|
|
16469
|
+
currentScreen = "main";
|
|
16470
|
+
selectedIndex = 0;
|
|
16471
|
+
render();
|
|
16472
|
+
return;
|
|
16473
|
+
}
|
|
16279
16474
|
cleanup();
|
|
16280
16475
|
console.log(import_picocolors2.default.dim("\n Exited Qodewk.\n"));
|
|
16281
16476
|
process.exit(0);
|
|
16282
16477
|
}
|
|
16283
16478
|
if (key.name === "up" || key.name === "k") {
|
|
16284
|
-
selectedIndex = (selectedIndex - 1 +
|
|
16479
|
+
selectedIndex = (selectedIndex - 1 + items.length) % items.length;
|
|
16285
16480
|
render();
|
|
16286
16481
|
return;
|
|
16287
16482
|
}
|
|
16288
16483
|
if (key.name === "down" || key.name === "j") {
|
|
16289
|
-
selectedIndex = (selectedIndex + 1) %
|
|
16484
|
+
selectedIndex = (selectedIndex + 1) % items.length;
|
|
16290
16485
|
render();
|
|
16291
16486
|
return;
|
|
16292
16487
|
}
|
|
16293
|
-
const itemByKey =
|
|
16488
|
+
const itemByKey = items.findIndex((item) => item.key === key.name || item.key === _str);
|
|
16294
16489
|
if (itemByKey !== -1) {
|
|
16295
16490
|
selectedIndex = itemByKey;
|
|
16296
16491
|
render();
|
|
16297
16492
|
process.stdin.removeListener("keypress", onKeypress);
|
|
16298
|
-
|
|
16493
|
+
const selected = items[selectedIndex];
|
|
16494
|
+
if (currentScreen === "main") {
|
|
16495
|
+
if (selected.id === "receipt") {
|
|
16496
|
+
currentScreen = "receipt_horizon";
|
|
16497
|
+
selectedIndex = 0;
|
|
16498
|
+
if (active) startLoop();
|
|
16499
|
+
return;
|
|
16500
|
+
}
|
|
16501
|
+
await executeSelectedAction();
|
|
16502
|
+
} else {
|
|
16503
|
+
if (selected.id === "back") {
|
|
16504
|
+
currentScreen = "main";
|
|
16505
|
+
selectedIndex = 0;
|
|
16506
|
+
if (active) startLoop();
|
|
16507
|
+
return;
|
|
16508
|
+
}
|
|
16509
|
+
await executeReceiptHorizon(selected);
|
|
16510
|
+
}
|
|
16299
16511
|
if (active) {
|
|
16300
16512
|
startLoop();
|
|
16301
16513
|
}
|
|
@@ -16303,7 +16515,24 @@ async function runInteractiveMenu() {
|
|
|
16303
16515
|
}
|
|
16304
16516
|
if (key.name === "return" || key.name === "enter") {
|
|
16305
16517
|
process.stdin.removeListener("keypress", onKeypress);
|
|
16306
|
-
|
|
16518
|
+
const selected = items[selectedIndex];
|
|
16519
|
+
if (currentScreen === "main") {
|
|
16520
|
+
if (selected.id === "receipt") {
|
|
16521
|
+
currentScreen = "receipt_horizon";
|
|
16522
|
+
selectedIndex = 0;
|
|
16523
|
+
if (active) startLoop();
|
|
16524
|
+
return;
|
|
16525
|
+
}
|
|
16526
|
+
await executeSelectedAction();
|
|
16527
|
+
} else {
|
|
16528
|
+
if (selected.id === "back") {
|
|
16529
|
+
currentScreen = "main";
|
|
16530
|
+
selectedIndex = 0;
|
|
16531
|
+
if (active) startLoop();
|
|
16532
|
+
return;
|
|
16533
|
+
}
|
|
16534
|
+
await executeReceiptHorizon(selected);
|
|
16535
|
+
}
|
|
16307
16536
|
if (active) {
|
|
16308
16537
|
startLoop();
|
|
16309
16538
|
}
|
|
@@ -16319,10 +16548,10 @@ async function runInteractiveMenu() {
|
|
|
16319
16548
|
var SHARE_PAYLOAD_MAX_BYTES2 = 5e4;
|
|
16320
16549
|
function resolveCliVersion() {
|
|
16321
16550
|
try {
|
|
16322
|
-
const argv1 = process.argv[1] ?
|
|
16551
|
+
const argv1 = process.argv[1] ? path11.dirname(path11.resolve(process.argv[1])) : process.cwd();
|
|
16323
16552
|
const candidates = [
|
|
16324
|
-
|
|
16325
|
-
|
|
16553
|
+
path11.join(argv1, "..", "package.json"),
|
|
16554
|
+
path11.join(argv1, "package.json")
|
|
16326
16555
|
];
|
|
16327
16556
|
for (const candidate of candidates) {
|
|
16328
16557
|
if (!fs10.existsSync(candidate)) continue;
|
|
@@ -16331,7 +16560,7 @@ function resolveCliVersion() {
|
|
|
16331
16560
|
}
|
|
16332
16561
|
} catch {
|
|
16333
16562
|
}
|
|
16334
|
-
return "0.
|
|
16563
|
+
return "0.8.0";
|
|
16335
16564
|
}
|
|
16336
16565
|
function resolveSince(options) {
|
|
16337
16566
|
return options.today ? "today" : options.since;
|
|
@@ -16350,6 +16579,12 @@ program2.name("qodewk").description("Universal telemetry and digital receipt gen
|
|
|
16350
16579
|
await runInteractiveMenu();
|
|
16351
16580
|
return;
|
|
16352
16581
|
}
|
|
16582
|
+
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";
|
|
16583
|
+
const isInteractiveTerminal = Boolean(process.stdin.isTTY && !process.env.CI);
|
|
16584
|
+
if (!hasExplicitOption && isInteractiveTerminal) {
|
|
16585
|
+
await runInteractiveMenu();
|
|
16586
|
+
return;
|
|
16587
|
+
}
|
|
16353
16588
|
try {
|
|
16354
16589
|
const receipt = await generateReceipt({
|
|
16355
16590
|
provider: options.provider,
|
|
@@ -16499,7 +16734,7 @@ hookCommand.command("install").description("Install non-blocking post-commit and
|
|
|
16499
16734
|
let installed = 0;
|
|
16500
16735
|
let existing = 0;
|
|
16501
16736
|
for (const name of targets) {
|
|
16502
|
-
const result = installHookFile(
|
|
16737
|
+
const result = installHookFile(path11.join(hooksDir, name));
|
|
16503
16738
|
if (result === "installed") installed++;
|
|
16504
16739
|
else existing++;
|
|
16505
16740
|
}
|
|
@@ -16531,7 +16766,7 @@ hookCommand.command("uninstall").description("Remove Qodewk post-commit and post
|
|
|
16531
16766
|
const targets = ["post-commit", "post-rewrite"];
|
|
16532
16767
|
let removed = 0;
|
|
16533
16768
|
for (const name of targets) {
|
|
16534
|
-
const result = uninstallHookFile(
|
|
16769
|
+
const result = uninstallHookFile(path11.join(hooksDir, name));
|
|
16535
16770
|
if (result === "removed") removed++;
|
|
16536
16771
|
}
|
|
16537
16772
|
if (removed === 0) {
|