qodewk 0.10.1 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +617 -353
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1157,8 +1157,8 @@ var require_command = __commonJS({
|
|
|
1157
1157
|
"use strict";
|
|
1158
1158
|
var EventEmitter2 = require("events").EventEmitter;
|
|
1159
1159
|
var childProcess = require("child_process");
|
|
1160
|
-
var
|
|
1161
|
-
var
|
|
1160
|
+
var path18 = require("path");
|
|
1161
|
+
var fs17 = require("fs");
|
|
1162
1162
|
var process3 = require("process");
|
|
1163
1163
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
1164
1164
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -2139,7 +2139,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2139
2139
|
* @param {string} subcommandName
|
|
2140
2140
|
*/
|
|
2141
2141
|
_checkForMissingExecutable(executableFile, executableDir, subcommandName) {
|
|
2142
|
-
if (
|
|
2142
|
+
if (fs17.existsSync(executableFile)) return;
|
|
2143
2143
|
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";
|
|
2144
2144
|
const executableMissing = `'${executableFile}' does not exist
|
|
2145
2145
|
- if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
@@ -2157,11 +2157,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2157
2157
|
let launchWithNode = false;
|
|
2158
2158
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
2159
2159
|
function findFile(baseDir, baseName) {
|
|
2160
|
-
const localBin =
|
|
2161
|
-
if (
|
|
2162
|
-
if (sourceExt.includes(
|
|
2160
|
+
const localBin = path18.resolve(baseDir, baseName);
|
|
2161
|
+
if (fs17.existsSync(localBin)) return localBin;
|
|
2162
|
+
if (sourceExt.includes(path18.extname(baseName))) return void 0;
|
|
2163
2163
|
const foundExt = sourceExt.find(
|
|
2164
|
-
(ext) =>
|
|
2164
|
+
(ext) => fs17.existsSync(`${localBin}${ext}`)
|
|
2165
2165
|
);
|
|
2166
2166
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
2167
2167
|
return void 0;
|
|
@@ -2173,21 +2173,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2173
2173
|
if (this._scriptPath) {
|
|
2174
2174
|
let resolvedScriptPath;
|
|
2175
2175
|
try {
|
|
2176
|
-
resolvedScriptPath =
|
|
2176
|
+
resolvedScriptPath = fs17.realpathSync(this._scriptPath);
|
|
2177
2177
|
} catch {
|
|
2178
2178
|
resolvedScriptPath = this._scriptPath;
|
|
2179
2179
|
}
|
|
2180
|
-
executableDir =
|
|
2181
|
-
|
|
2180
|
+
executableDir = path18.resolve(
|
|
2181
|
+
path18.dirname(resolvedScriptPath),
|
|
2182
2182
|
executableDir
|
|
2183
2183
|
);
|
|
2184
2184
|
}
|
|
2185
2185
|
if (executableDir) {
|
|
2186
2186
|
let localFile = findFile(executableDir, executableFile);
|
|
2187
2187
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
2188
|
-
const legacyName =
|
|
2188
|
+
const legacyName = path18.basename(
|
|
2189
2189
|
this._scriptPath,
|
|
2190
|
-
|
|
2190
|
+
path18.extname(this._scriptPath)
|
|
2191
2191
|
);
|
|
2192
2192
|
if (legacyName !== this._name) {
|
|
2193
2193
|
localFile = findFile(
|
|
@@ -2198,7 +2198,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2198
2198
|
}
|
|
2199
2199
|
executableFile = localFile || executableFile;
|
|
2200
2200
|
}
|
|
2201
|
-
launchWithNode = sourceExt.includes(
|
|
2201
|
+
launchWithNode = sourceExt.includes(path18.extname(executableFile));
|
|
2202
2202
|
let proc;
|
|
2203
2203
|
if (process3.platform !== "win32") {
|
|
2204
2204
|
if (launchWithNode) {
|
|
@@ -3045,7 +3045,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3045
3045
|
* @return {Command}
|
|
3046
3046
|
*/
|
|
3047
3047
|
nameFromFilename(filename) {
|
|
3048
|
-
this._name =
|
|
3048
|
+
this._name = path18.basename(filename, path18.extname(filename));
|
|
3049
3049
|
return this;
|
|
3050
3050
|
}
|
|
3051
3051
|
/**
|
|
@@ -3059,9 +3059,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3059
3059
|
* @param {string} [path]
|
|
3060
3060
|
* @return {(string|null|Command)}
|
|
3061
3061
|
*/
|
|
3062
|
-
executableDir(
|
|
3063
|
-
if (
|
|
3064
|
-
this._executableDir =
|
|
3062
|
+
executableDir(path19) {
|
|
3063
|
+
if (path19 === void 0) return this._executableDir;
|
|
3064
|
+
this._executableDir = path19;
|
|
3065
3065
|
return this;
|
|
3066
3066
|
}
|
|
3067
3067
|
/**
|
|
@@ -4207,10 +4207,10 @@ var require_src2 = __commonJS({
|
|
|
4207
4207
|
var fs_1 = require("fs");
|
|
4208
4208
|
var debug_1 = __importDefault(require_src());
|
|
4209
4209
|
var log = debug_1.default("@kwsites/file-exists");
|
|
4210
|
-
function check(
|
|
4211
|
-
log(`checking %s`,
|
|
4210
|
+
function check(path18, isFile, isDirectory) {
|
|
4211
|
+
log(`checking %s`, path18);
|
|
4212
4212
|
try {
|
|
4213
|
-
const stat = fs_1.statSync(
|
|
4213
|
+
const stat = fs_1.statSync(path18);
|
|
4214
4214
|
if (stat.isFile() && isFile) {
|
|
4215
4215
|
log(`[OK] path represents a file`);
|
|
4216
4216
|
return true;
|
|
@@ -4230,8 +4230,8 @@ var require_src2 = __commonJS({
|
|
|
4230
4230
|
throw e;
|
|
4231
4231
|
}
|
|
4232
4232
|
}
|
|
4233
|
-
function exists2(
|
|
4234
|
-
return check(
|
|
4233
|
+
function exists2(path18, type = exports2.READABLE) {
|
|
4234
|
+
return check(path18, (type & exports2.FILE) > 0, (type & exports2.FOLDER) > 0);
|
|
4235
4235
|
}
|
|
4236
4236
|
exports2.exists = exists2;
|
|
4237
4237
|
exports2.FILE = 1;
|
|
@@ -4842,8 +4842,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
4842
4842
|
function forEachLineWithContent(input, callback) {
|
|
4843
4843
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
4844
4844
|
}
|
|
4845
|
-
function folderExists(
|
|
4846
|
-
return (0, import_file_exists.exists)(
|
|
4845
|
+
function folderExists(path18) {
|
|
4846
|
+
return (0, import_file_exists.exists)(path18, import_file_exists.FOLDER);
|
|
4847
4847
|
}
|
|
4848
4848
|
function append(target, item) {
|
|
4849
4849
|
if (Array.isArray(target)) {
|
|
@@ -5034,8 +5034,8 @@ function checkIsRepoRootTask() {
|
|
|
5034
5034
|
commands,
|
|
5035
5035
|
format: "utf-8",
|
|
5036
5036
|
onError,
|
|
5037
|
-
parser(
|
|
5038
|
-
return /^\.(git)?$/.test(
|
|
5037
|
+
parser(path18) {
|
|
5038
|
+
return /^\.(git)?$/.test(path18.trim());
|
|
5039
5039
|
}
|
|
5040
5040
|
};
|
|
5041
5041
|
}
|
|
@@ -5291,11 +5291,11 @@ function parseGrep(grep) {
|
|
|
5291
5291
|
const paths = /* @__PURE__ */ new Set();
|
|
5292
5292
|
const results = {};
|
|
5293
5293
|
forEachLineWithContent(grep, (input) => {
|
|
5294
|
-
const [
|
|
5295
|
-
paths.add(
|
|
5296
|
-
(results[
|
|
5294
|
+
const [path18, line, preview] = input.split(NULL);
|
|
5295
|
+
paths.add(path18);
|
|
5296
|
+
(results[path18] = results[path18] || []).push({
|
|
5297
5297
|
line: asNumber(line),
|
|
5298
|
-
path:
|
|
5298
|
+
path: path18,
|
|
5299
5299
|
preview
|
|
5300
5300
|
});
|
|
5301
5301
|
});
|
|
@@ -5592,14 +5592,14 @@ function hashObjectTask(filePath, write) {
|
|
|
5592
5592
|
}
|
|
5593
5593
|
return straightThroughStringTask(commands, true);
|
|
5594
5594
|
}
|
|
5595
|
-
function parseInit(bare,
|
|
5595
|
+
function parseInit(bare, path18, text) {
|
|
5596
5596
|
const response = String(text).trim();
|
|
5597
5597
|
let result;
|
|
5598
5598
|
if (result = initResponseRegex.exec(response)) {
|
|
5599
|
-
return new InitSummary(bare,
|
|
5599
|
+
return new InitSummary(bare, path18, false, result[1]);
|
|
5600
5600
|
}
|
|
5601
5601
|
if (result = reInitResponseRegex.exec(response)) {
|
|
5602
|
-
return new InitSummary(bare,
|
|
5602
|
+
return new InitSummary(bare, path18, true, result[1]);
|
|
5603
5603
|
}
|
|
5604
5604
|
let gitDir = "";
|
|
5605
5605
|
const tokens = response.split(" ");
|
|
@@ -5610,12 +5610,12 @@ function parseInit(bare, path17, text) {
|
|
|
5610
5610
|
break;
|
|
5611
5611
|
}
|
|
5612
5612
|
}
|
|
5613
|
-
return new InitSummary(bare,
|
|
5613
|
+
return new InitSummary(bare, path18, /^re/i.test(response), gitDir);
|
|
5614
5614
|
}
|
|
5615
5615
|
function hasBareCommand(command) {
|
|
5616
5616
|
return command.includes(bareCommand);
|
|
5617
5617
|
}
|
|
5618
|
-
function initTask(bare = false,
|
|
5618
|
+
function initTask(bare = false, path18, customArgs) {
|
|
5619
5619
|
const commands = ["init", ...customArgs];
|
|
5620
5620
|
if (bare && !hasBareCommand(commands)) {
|
|
5621
5621
|
commands.splice(1, 0, bareCommand);
|
|
@@ -5624,7 +5624,7 @@ function initTask(bare = false, path17, customArgs) {
|
|
|
5624
5624
|
commands,
|
|
5625
5625
|
format: "utf-8",
|
|
5626
5626
|
parser(text) {
|
|
5627
|
-
return parseInit(commands.includes("--bare"),
|
|
5627
|
+
return parseInit(commands.includes("--bare"), path18, text);
|
|
5628
5628
|
}
|
|
5629
5629
|
};
|
|
5630
5630
|
}
|
|
@@ -5903,14 +5903,14 @@ function splitLine(result, lineStr) {
|
|
|
5903
5903
|
default:
|
|
5904
5904
|
return;
|
|
5905
5905
|
}
|
|
5906
|
-
function data(index, workingDir,
|
|
5906
|
+
function data(index, workingDir, path18) {
|
|
5907
5907
|
const raw = `${index}${workingDir}`;
|
|
5908
5908
|
const handler = parsers6.get(raw);
|
|
5909
5909
|
if (handler) {
|
|
5910
|
-
handler(result,
|
|
5910
|
+
handler(result, path18);
|
|
5911
5911
|
}
|
|
5912
5912
|
if (raw !== "##" && raw !== "!!") {
|
|
5913
|
-
result.files.push(new FileStatusSummary(
|
|
5913
|
+
result.files.push(new FileStatusSummary(path18, index, workingDir));
|
|
5914
5914
|
}
|
|
5915
5915
|
}
|
|
5916
5916
|
}
|
|
@@ -6097,8 +6097,8 @@ function deleteBranchTask(branch, forceDelete = false) {
|
|
|
6097
6097
|
return task;
|
|
6098
6098
|
}
|
|
6099
6099
|
function toPath(input) {
|
|
6100
|
-
const
|
|
6101
|
-
return
|
|
6100
|
+
const path18 = input.trim().replace(/^["']|["']$/g, "");
|
|
6101
|
+
return path18 && (0, import_node_path.normalize)(path18);
|
|
6102
6102
|
}
|
|
6103
6103
|
function checkIgnoreTask(paths) {
|
|
6104
6104
|
return {
|
|
@@ -6237,8 +6237,8 @@ function stashListTask(opt = {}, customArgs) {
|
|
|
6237
6237
|
parser: parser4
|
|
6238
6238
|
};
|
|
6239
6239
|
}
|
|
6240
|
-
function addSubModuleTask(repo,
|
|
6241
|
-
return subModuleTask(["add", repo,
|
|
6240
|
+
function addSubModuleTask(repo, path18) {
|
|
6241
|
+
return subModuleTask(["add", repo, path18]);
|
|
6242
6242
|
}
|
|
6243
6243
|
function initSubModuleTask(customArgs) {
|
|
6244
6244
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -6646,12 +6646,12 @@ function gitP(...args) {
|
|
|
6646
6646
|
);
|
|
6647
6647
|
}
|
|
6648
6648
|
return chain.then(function() {
|
|
6649
|
-
return new Promise(function(
|
|
6649
|
+
return new Promise(function(resolve8, reject) {
|
|
6650
6650
|
const callback = (err, result) => {
|
|
6651
6651
|
if (err) {
|
|
6652
6652
|
return reject(toError(err));
|
|
6653
6653
|
}
|
|
6654
|
-
|
|
6654
|
+
resolve8(result);
|
|
6655
6655
|
};
|
|
6656
6656
|
args2.push(callback);
|
|
6657
6657
|
git2[fn].apply(git2, args2);
|
|
@@ -7570,9 +7570,9 @@ var init_esm = __esm({
|
|
|
7570
7570
|
"src/lib/responses/InitSummary.ts"() {
|
|
7571
7571
|
"use strict";
|
|
7572
7572
|
InitSummary = class {
|
|
7573
|
-
constructor(bare,
|
|
7573
|
+
constructor(bare, path18, existing, gitDir) {
|
|
7574
7574
|
this.bare = bare;
|
|
7575
|
-
this.path =
|
|
7575
|
+
this.path = path18;
|
|
7576
7576
|
this.existing = existing;
|
|
7577
7577
|
this.gitDir = gitDir;
|
|
7578
7578
|
}
|
|
@@ -8105,12 +8105,12 @@ var init_esm = __esm({
|
|
|
8105
8105
|
"use strict";
|
|
8106
8106
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
8107
8107
|
FileStatusSummary = class {
|
|
8108
|
-
constructor(
|
|
8109
|
-
this.path =
|
|
8108
|
+
constructor(path18, index, working_dir) {
|
|
8109
|
+
this.path = path18;
|
|
8110
8110
|
this.index = index;
|
|
8111
8111
|
this.working_dir = working_dir;
|
|
8112
8112
|
if (index === "R" || working_dir === "R") {
|
|
8113
|
-
const detail = fromPathRegex.exec(
|
|
8113
|
+
const detail = fromPathRegex.exec(path18) || [null, path18, path18];
|
|
8114
8114
|
this.from = detail[2] || "";
|
|
8115
8115
|
this.path = detail[1] || "";
|
|
8116
8116
|
}
|
|
@@ -8372,9 +8372,9 @@ var init_esm = __esm({
|
|
|
8372
8372
|
next
|
|
8373
8373
|
);
|
|
8374
8374
|
}
|
|
8375
|
-
hashObject(
|
|
8375
|
+
hashObject(path18, write) {
|
|
8376
8376
|
return this._runTask(
|
|
8377
|
-
hashObjectTask(
|
|
8377
|
+
hashObjectTask(path18, write === true),
|
|
8378
8378
|
trailingFunctionArgument(arguments)
|
|
8379
8379
|
);
|
|
8380
8380
|
}
|
|
@@ -9011,8 +9011,8 @@ var init_esm = __esm({
|
|
|
9011
9011
|
}
|
|
9012
9012
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
9013
9013
|
};
|
|
9014
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
9015
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
9014
|
+
Git2.prototype.submoduleAdd = function(repo, path18, then) {
|
|
9015
|
+
return this._runTask(addSubModuleTask2(repo, path18), trailingFunctionArgument2(arguments));
|
|
9016
9016
|
};
|
|
9017
9017
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
9018
9018
|
return this._runTask(
|
|
@@ -9318,8 +9318,8 @@ var init_esm = __esm({
|
|
|
9318
9318
|
});
|
|
9319
9319
|
|
|
9320
9320
|
// src/index.ts
|
|
9321
|
-
var
|
|
9322
|
-
var
|
|
9321
|
+
var fs16 = __toESM(require("fs"), 1);
|
|
9322
|
+
var path17 = __toESM(require("path"), 1);
|
|
9323
9323
|
|
|
9324
9324
|
// ../../node_modules/.pnpm/commander@13.1.0/node_modules/commander/esm.mjs
|
|
9325
9325
|
var import_index = __toESM(require_commander(), 1);
|
|
@@ -9339,7 +9339,7 @@ var {
|
|
|
9339
9339
|
} = import_index.default;
|
|
9340
9340
|
|
|
9341
9341
|
// src/index.ts
|
|
9342
|
-
var
|
|
9342
|
+
var import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
9343
9343
|
|
|
9344
9344
|
// ../core/dist/index.js
|
|
9345
9345
|
var crypto2 = __toESM(require("crypto"), 1);
|
|
@@ -9822,8 +9822,8 @@ function getErrorMap() {
|
|
|
9822
9822
|
|
|
9823
9823
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
9824
9824
|
var makeIssue = (params) => {
|
|
9825
|
-
const { data, path:
|
|
9826
|
-
const fullPath = [...
|
|
9825
|
+
const { data, path: path18, errorMaps, issueData } = params;
|
|
9826
|
+
const fullPath = [...path18, ...issueData.path || []];
|
|
9827
9827
|
const fullIssue = {
|
|
9828
9828
|
...issueData,
|
|
9829
9829
|
path: fullPath
|
|
@@ -9939,11 +9939,11 @@ var errorUtil;
|
|
|
9939
9939
|
|
|
9940
9940
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
9941
9941
|
var ParseInputLazyPath = class {
|
|
9942
|
-
constructor(parent, value,
|
|
9942
|
+
constructor(parent, value, path18, key) {
|
|
9943
9943
|
this._cachedPath = [];
|
|
9944
9944
|
this.parent = parent;
|
|
9945
9945
|
this.data = value;
|
|
9946
|
-
this._path =
|
|
9946
|
+
this._path = path18;
|
|
9947
9947
|
this._key = key;
|
|
9948
9948
|
}
|
|
9949
9949
|
get path() {
|
|
@@ -13394,11 +13394,13 @@ var AttributionModeSchema = external_exports.enum([
|
|
|
13394
13394
|
"unknown"
|
|
13395
13395
|
]);
|
|
13396
13396
|
var ProviderSessionSchema = external_exports.object({
|
|
13397
|
+
sessionId: external_exports.string().optional(),
|
|
13397
13398
|
provider: external_exports.string(),
|
|
13398
13399
|
// e.g. "anthropic", "openai", "cursor", "copilot", "gemini", "antigravity"
|
|
13399
13400
|
model: external_exports.string().optional(),
|
|
13400
13401
|
task: external_exports.string().optional(),
|
|
13401
13402
|
filesTouched: external_exports.array(external_exports.string()).optional(),
|
|
13403
|
+
turnsCount: external_exports.number().int().nonnegative().optional(),
|
|
13402
13404
|
tokens: external_exports.object({
|
|
13403
13405
|
input: external_exports.number().int().nonnegative().default(0),
|
|
13404
13406
|
output: external_exports.number().int().nonnegative().default(0),
|
|
@@ -13406,7 +13408,8 @@ var ProviderSessionSchema = external_exports.object({
|
|
|
13406
13408
|
}),
|
|
13407
13409
|
cost: external_exports.number().nonnegative(),
|
|
13408
13410
|
confidence: external_exports.number().min(0).max(1),
|
|
13409
|
-
mode: AttributionModeSchema
|
|
13411
|
+
mode: AttributionModeSchema,
|
|
13412
|
+
createdAt: external_exports.string().optional()
|
|
13410
13413
|
});
|
|
13411
13414
|
var ReceiptV1Schema = external_exports.object({
|
|
13412
13415
|
version: external_exports.literal("1.0"),
|
|
@@ -13957,6 +13960,16 @@ var RATE_CARDS = {
|
|
|
13957
13960
|
cacheWritePerMTok: 0.1,
|
|
13958
13961
|
contextWindow: 1e6
|
|
13959
13962
|
},
|
|
13963
|
+
"gemini-3-6-flash": {
|
|
13964
|
+
id: "gemini-3-6-flash",
|
|
13965
|
+
provider: "google",
|
|
13966
|
+
name: "Gemini 3.6 Flash",
|
|
13967
|
+
inputPerMTok: 0.1,
|
|
13968
|
+
outputPerMTok: 0.4,
|
|
13969
|
+
cacheReadPerMTok: 0.025,
|
|
13970
|
+
cacheWritePerMTok: 0.1,
|
|
13971
|
+
contextWindow: 1e6
|
|
13972
|
+
},
|
|
13960
13973
|
"gemini-2-5-pro": {
|
|
13961
13974
|
id: "gemini-2-5-pro",
|
|
13962
13975
|
provider: "google",
|
|
@@ -14065,9 +14078,14 @@ var MODEL_ALIASES = {
|
|
|
14065
14078
|
"gemini-3-1-pro": "gemini-2-5-pro",
|
|
14066
14079
|
"gemini-3-pro": "gemini-2-5-pro",
|
|
14067
14080
|
"gemini-3-1-flash": "gemini-3-8-flash",
|
|
14081
|
+
"gemini-3.8-flash": "gemini-3-8-flash",
|
|
14082
|
+
"gemini-3.6-flash": "gemini-3-6-flash",
|
|
14083
|
+
"gemini-3-6": "gemini-3-6-flash",
|
|
14068
14084
|
"gemini-2.0-flash": "gemini-2-0-flash",
|
|
14069
14085
|
"gemini-1.5-pro": "gemini-1-5-pro",
|
|
14070
14086
|
"gemini-1.5-flash": "gemini-2-0-flash",
|
|
14087
|
+
"google/gemini-3.8-flash": "gemini-3-8-flash",
|
|
14088
|
+
"google/gemini-3.6-flash": "gemini-3-6-flash",
|
|
14071
14089
|
// DeepSeek aliases
|
|
14072
14090
|
"deepseek-chat": "deepseek-v3",
|
|
14073
14091
|
"deepseek-coder": "deepseek-v3",
|
|
@@ -14375,6 +14393,9 @@ function discoverAntigravityEnvironment() {
|
|
|
14375
14393
|
return null;
|
|
14376
14394
|
}
|
|
14377
14395
|
|
|
14396
|
+
// ../core/dist/harvester/index.js
|
|
14397
|
+
var path11 = __toESM(require("path"), 1);
|
|
14398
|
+
|
|
14378
14399
|
// ../core/dist/harvester/antigravity.js
|
|
14379
14400
|
var fs2 = __toESM(require("fs"), 1);
|
|
14380
14401
|
var path3 = __toESM(require("path"), 1);
|
|
@@ -14383,7 +14404,8 @@ var import_node_module = require("module");
|
|
|
14383
14404
|
|
|
14384
14405
|
// ../core/dist/harvester/scoring.js
|
|
14385
14406
|
function normalizeFilePath(filePath, repoPath) {
|
|
14386
|
-
let p2 = filePath.replace(
|
|
14407
|
+
let p2 = filePath.trim().replace(/^["']|["']$/g, "").replace(/\\/g, "/");
|
|
14408
|
+
p2 = p2.replace(/\/+/g, "/");
|
|
14387
14409
|
p2 = p2.replace(/^file:\/\/\/?/, "");
|
|
14388
14410
|
if (repoPath) {
|
|
14389
14411
|
const normRepo = repoPath.replace(/\\/g, "/").replace(/\/$/, "");
|
|
@@ -15799,39 +15821,86 @@ function parseSinceOption2(since) {
|
|
|
15799
15821
|
}
|
|
15800
15822
|
return void 0;
|
|
15801
15823
|
}
|
|
15802
|
-
|
|
15803
|
-
const
|
|
15804
|
-
|
|
15805
|
-
|
|
15806
|
-
let allFootprints = [];
|
|
15807
|
-
if (!options.platform || options.platform === "all" || options.platform === "antigravity") {
|
|
15808
|
-
const agFootprints = harvestAntigravityFootprints(options.repoPath, sinceDate);
|
|
15824
|
+
function harvestRawPlatformFootprints(repoPath, alias, sinceDate, platform) {
|
|
15825
|
+
const allFootprints = [];
|
|
15826
|
+
if (!platform || platform === "all" || platform === "antigravity") {
|
|
15827
|
+
const agFootprints = harvestAntigravityFootprints(repoPath, sinceDate);
|
|
15809
15828
|
allFootprints.push(...agFootprints);
|
|
15810
15829
|
}
|
|
15811
|
-
if (!
|
|
15812
|
-
const claudeFootprints = harvestClaudeFootprints(
|
|
15830
|
+
if (!platform || platform === "all" || platform === "claude") {
|
|
15831
|
+
const claudeFootprints = harvestClaudeFootprints(repoPath, alias, sinceDate);
|
|
15813
15832
|
allFootprints.push(...claudeFootprints);
|
|
15814
15833
|
}
|
|
15815
|
-
if (!
|
|
15816
|
-
const cursorFootprints = harvestCursorFootprints(
|
|
15834
|
+
if (!platform || platform === "all" || platform === "cursor") {
|
|
15835
|
+
const cursorFootprints = harvestCursorFootprints(repoPath, sinceDate);
|
|
15817
15836
|
allFootprints.push(...cursorFootprints);
|
|
15818
15837
|
}
|
|
15819
|
-
if (!
|
|
15820
|
-
const aiderFootprints = harvestAiderFootprints(
|
|
15838
|
+
if (!platform || platform === "all" || platform === "aider") {
|
|
15839
|
+
const aiderFootprints = harvestAiderFootprints(repoPath, sinceDate);
|
|
15821
15840
|
allFootprints.push(...aiderFootprints);
|
|
15822
15841
|
}
|
|
15823
|
-
if (!
|
|
15824
|
-
const windsurfFootprints = harvestWindsurfFootprints(
|
|
15842
|
+
if (!platform || platform === "all" || platform === "windsurf") {
|
|
15843
|
+
const windsurfFootprints = harvestWindsurfFootprints(repoPath, sinceDate);
|
|
15825
15844
|
allFootprints.push(...windsurfFootprints);
|
|
15826
15845
|
}
|
|
15827
|
-
if (!
|
|
15828
|
-
const clineFootprints = harvestClineFootprints(
|
|
15846
|
+
if (!platform || platform === "all" || platform === "cline") {
|
|
15847
|
+
const clineFootprints = harvestClineFootprints(repoPath, sinceDate);
|
|
15829
15848
|
allFootprints.push(...clineFootprints);
|
|
15830
15849
|
}
|
|
15831
|
-
if (!
|
|
15832
|
-
const opencodeFootprints = harvestOpenCodeFootprints(
|
|
15850
|
+
if (!platform || platform === "all" || platform === "opencode") {
|
|
15851
|
+
const opencodeFootprints = harvestOpenCodeFootprints(repoPath, sinceDate);
|
|
15833
15852
|
allFootprints.push(...opencodeFootprints);
|
|
15834
15853
|
}
|
|
15854
|
+
return allFootprints;
|
|
15855
|
+
}
|
|
15856
|
+
async function listProjectChats(options = {}) {
|
|
15857
|
+
const repoPath = options.repoPath || process.cwd();
|
|
15858
|
+
const alias = options.projectAlias || path11.basename(path11.resolve(repoPath)) || "project";
|
|
15859
|
+
let sinceDate;
|
|
15860
|
+
let windowDescription = "All-time";
|
|
15861
|
+
if (!options.all) {
|
|
15862
|
+
if (options.since) {
|
|
15863
|
+
sinceDate = parseSinceOption2(options.since);
|
|
15864
|
+
windowDescription = typeof options.since === "string" ? `Since ${options.since}` : `Since ${options.since.toISOString().slice(0, 10)}`;
|
|
15865
|
+
} else {
|
|
15866
|
+
sinceDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
|
|
15867
|
+
windowDescription = "Last 30 Days";
|
|
15868
|
+
}
|
|
15869
|
+
}
|
|
15870
|
+
const allFootprints = harvestRawPlatformFootprints(repoPath, alias, sinceDate, options.platform);
|
|
15871
|
+
allFootprints.sort((a, b2) => new Date(b2.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
15872
|
+
let totalInput = 0;
|
|
15873
|
+
let totalOutput = 0;
|
|
15874
|
+
let totalCached = 0;
|
|
15875
|
+
let totalCost = 0;
|
|
15876
|
+
let totalSteps = 0;
|
|
15877
|
+
for (const fp of allFootprints) {
|
|
15878
|
+
totalInput += fp.tokens.input;
|
|
15879
|
+
totalOutput += fp.tokens.output;
|
|
15880
|
+
totalCached += fp.tokens.cached;
|
|
15881
|
+
totalCost += fp.cost;
|
|
15882
|
+
totalSteps += fp.stepsCount || 0;
|
|
15883
|
+
}
|
|
15884
|
+
return {
|
|
15885
|
+
repoPath,
|
|
15886
|
+
projectAlias: alias,
|
|
15887
|
+
windowDescription,
|
|
15888
|
+
totalCost: Number(totalCost.toFixed(4)),
|
|
15889
|
+
totalTokens: {
|
|
15890
|
+
input: totalInput,
|
|
15891
|
+
output: totalOutput,
|
|
15892
|
+
cached: totalCached
|
|
15893
|
+
},
|
|
15894
|
+
totalSteps,
|
|
15895
|
+
sessionsCount: allFootprints.length,
|
|
15896
|
+
chats: allFootprints
|
|
15897
|
+
};
|
|
15898
|
+
}
|
|
15899
|
+
async function harvestUniversalFootprints(options) {
|
|
15900
|
+
const parsedSince = parseSinceOption2(options.since);
|
|
15901
|
+
const sinceDate = parsedSince ? new Date(parsedSince.getTime() - 24 * 60 * 60 * 1e3) : void 0;
|
|
15902
|
+
const alias = options.projectAlias || "";
|
|
15903
|
+
let allFootprints = harvestRawPlatformFootprints(options.repoPath, alias, sinceDate, options.platform);
|
|
15835
15904
|
if (options.gitContext?.commitMessage) {
|
|
15836
15905
|
const trailerFps = harvestTrailerFootprints(options.repoPath, options.gitContext.commitMessage, options.gitContext.headSha, options.gitContext.commitDate);
|
|
15837
15906
|
allFootprints.push(...trailerFps);
|
|
@@ -15958,15 +16027,15 @@ function estimateCost(options) {
|
|
|
15958
16027
|
|
|
15959
16028
|
// ../core/dist/pricing-sync.js
|
|
15960
16029
|
var fs10 = __toESM(require("fs"), 1);
|
|
15961
|
-
var
|
|
16030
|
+
var path12 = __toESM(require("path"), 1);
|
|
15962
16031
|
var os10 = __toESM(require("os"), 1);
|
|
15963
16032
|
async function syncDynamicPricing(options) {
|
|
15964
16033
|
try {
|
|
15965
|
-
const qodewkDir =
|
|
16034
|
+
const qodewkDir = path12.join(os10.homedir(), ".qodewk");
|
|
15966
16035
|
if (!fs10.existsSync(qodewkDir)) {
|
|
15967
16036
|
fs10.mkdirSync(qodewkDir, { recursive: true });
|
|
15968
16037
|
}
|
|
15969
|
-
const cacheFile =
|
|
16038
|
+
const cacheFile = path12.join(qodewkDir, "pricing_registry_cache.json");
|
|
15970
16039
|
const TTL_MS = 24 * 60 * 60 * 1e3;
|
|
15971
16040
|
const now = Date.now();
|
|
15972
16041
|
if (!options?.force && fs10.existsSync(cacheFile)) {
|
|
@@ -16001,7 +16070,7 @@ async function syncDynamicPricing(options) {
|
|
|
16001
16070
|
|
|
16002
16071
|
// ../core/dist/env.js
|
|
16003
16072
|
var fs11 = __toESM(require("fs"), 1);
|
|
16004
|
-
var
|
|
16073
|
+
var path13 = __toESM(require("path"), 1);
|
|
16005
16074
|
var os11 = __toESM(require("os"), 1);
|
|
16006
16075
|
var isEnvLoaded = false;
|
|
16007
16076
|
function loadQodewkEnv(startDir = process.cwd()) {
|
|
@@ -16009,11 +16078,11 @@ function loadQodewkEnv(startDir = process.cwd()) {
|
|
|
16009
16078
|
return;
|
|
16010
16079
|
isEnvLoaded = true;
|
|
16011
16080
|
const candidates = [
|
|
16012
|
-
|
|
16013
|
-
|
|
16014
|
-
|
|
16015
|
-
|
|
16016
|
-
|
|
16081
|
+
path13.join(startDir, ".env.local"),
|
|
16082
|
+
path13.join(startDir, ".env"),
|
|
16083
|
+
path13.join(startDir, "apps", "web", ".env.local"),
|
|
16084
|
+
path13.join(startDir, "apps", "web", ".env"),
|
|
16085
|
+
path13.join(os11.homedir(), ".qodewk", "config.env")
|
|
16017
16086
|
];
|
|
16018
16087
|
for (const envPath of candidates) {
|
|
16019
16088
|
if (!fs11.existsSync(envPath))
|
|
@@ -16089,7 +16158,7 @@ function formatMarkdownReceipt(receipt, publicUrl) {
|
|
|
16089
16158
|
|
|
16090
16159
|
// ../core/dist/doctor.js
|
|
16091
16160
|
var fs12 = __toESM(require("fs"), 1);
|
|
16092
|
-
var
|
|
16161
|
+
var path14 = __toESM(require("path"), 1);
|
|
16093
16162
|
var os12 = __toESM(require("os"), 1);
|
|
16094
16163
|
var import_node_child_process = require("child_process");
|
|
16095
16164
|
var HOOK_MARKER_BEGIN = "# --- BEGIN QODEWK HOOK ---";
|
|
@@ -16097,7 +16166,7 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16097
16166
|
const homedir12 = os12.homedir();
|
|
16098
16167
|
const results = [];
|
|
16099
16168
|
const agEnv = process.env.ANTIGRAVITY_APP_DATA_DIR;
|
|
16100
|
-
const agHome =
|
|
16169
|
+
const agHome = path14.join(homedir12, ".gemini", "antigravity");
|
|
16101
16170
|
const agPath = agEnv && fs12.existsSync(agEnv) ? agEnv : fs12.existsSync(agHome) ? agHome : void 0;
|
|
16102
16171
|
results.push({
|
|
16103
16172
|
id: "antigravity",
|
|
@@ -16106,7 +16175,7 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16106
16175
|
path: agPath,
|
|
16107
16176
|
details: agPath ? "Antigravity brain telemetry detected" : "No active session brain found"
|
|
16108
16177
|
});
|
|
16109
|
-
const claudeProjects =
|
|
16178
|
+
const claudeProjects = path14.join(homedir12, ".claude", "projects");
|
|
16110
16179
|
const claudeExists = fs12.existsSync(claudeProjects);
|
|
16111
16180
|
results.push({
|
|
16112
16181
|
id: "claude",
|
|
@@ -16117,15 +16186,15 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16117
16186
|
});
|
|
16118
16187
|
let cursorPath;
|
|
16119
16188
|
if (process.platform === "win32") {
|
|
16120
|
-
const c3 =
|
|
16189
|
+
const c3 = path14.join(process.env.APPDATA || path14.join(homedir12, "AppData", "Roaming"), "Cursor", "User", "workspaceStorage");
|
|
16121
16190
|
if (fs12.existsSync(c3))
|
|
16122
16191
|
cursorPath = c3;
|
|
16123
16192
|
} else if (process.platform === "darwin") {
|
|
16124
|
-
const c3 =
|
|
16193
|
+
const c3 = path14.join(homedir12, "Library", "Application Support", "Cursor", "User", "workspaceStorage");
|
|
16125
16194
|
if (fs12.existsSync(c3))
|
|
16126
16195
|
cursorPath = c3;
|
|
16127
16196
|
} else {
|
|
16128
|
-
const c3 =
|
|
16197
|
+
const c3 = path14.join(homedir12, ".config", "Cursor", "User", "workspaceStorage");
|
|
16129
16198
|
if (fs12.existsSync(c3))
|
|
16130
16199
|
cursorPath = c3;
|
|
16131
16200
|
}
|
|
@@ -16138,15 +16207,15 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16138
16207
|
});
|
|
16139
16208
|
let windsurfPath;
|
|
16140
16209
|
if (process.platform === "win32") {
|
|
16141
|
-
const w =
|
|
16210
|
+
const w = path14.join(process.env.APPDATA || path14.join(homedir12, "AppData", "Roaming"), "Windsurf", "User", "workspaceStorage");
|
|
16142
16211
|
if (fs12.existsSync(w))
|
|
16143
16212
|
windsurfPath = w;
|
|
16144
16213
|
} else if (process.platform === "darwin") {
|
|
16145
|
-
const w =
|
|
16214
|
+
const w = path14.join(homedir12, "Library", "Application Support", "Windsurf", "User", "workspaceStorage");
|
|
16146
16215
|
if (fs12.existsSync(w))
|
|
16147
16216
|
windsurfPath = w;
|
|
16148
16217
|
} else {
|
|
16149
|
-
const w =
|
|
16218
|
+
const w = path14.join(homedir12, ".config", "Windsurf", "User", "workspaceStorage");
|
|
16150
16219
|
if (fs12.existsSync(w))
|
|
16151
16220
|
windsurfPath = w;
|
|
16152
16221
|
}
|
|
@@ -16158,16 +16227,16 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16158
16227
|
details: windsurfPath ? "Cascade session workspace storage detected" : "Windsurf IDE storage not detected"
|
|
16159
16228
|
});
|
|
16160
16229
|
let clinePath;
|
|
16161
|
-
const localCline =
|
|
16162
|
-
const localRoo =
|
|
16230
|
+
const localCline = path14.join(repoPath, ".cline");
|
|
16231
|
+
const localRoo = path14.join(repoPath, ".roo");
|
|
16163
16232
|
if (fs12.existsSync(localCline)) {
|
|
16164
16233
|
clinePath = localCline;
|
|
16165
16234
|
} else if (fs12.existsSync(localRoo)) {
|
|
16166
16235
|
clinePath = localRoo;
|
|
16167
16236
|
} else {
|
|
16168
|
-
const appData = process.platform === "win32" ? process.env.APPDATA ||
|
|
16169
|
-
const clineExt =
|
|
16170
|
-
const rooExt =
|
|
16237
|
+
const appData = process.platform === "win32" ? process.env.APPDATA || path14.join(homedir12, "AppData", "Roaming") : process.platform === "darwin" ? path14.join(homedir12, "Library", "Application Support") : path14.join(homedir12, ".config");
|
|
16238
|
+
const clineExt = path14.join(appData, "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "tasks");
|
|
16239
|
+
const rooExt = path14.join(appData, "Code", "User", "globalStorage", "rooveterinaryinc.roo-cline", "tasks");
|
|
16171
16240
|
if (fs12.existsSync(clineExt))
|
|
16172
16241
|
clinePath = clineExt;
|
|
16173
16242
|
else if (fs12.existsSync(rooExt))
|
|
@@ -16180,7 +16249,7 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16180
16249
|
path: clinePath,
|
|
16181
16250
|
details: clinePath ? "VS Code autonomous agent task storage detected" : "No active Cline or Roo Code tasks found"
|
|
16182
16251
|
});
|
|
16183
|
-
const aiderPath =
|
|
16252
|
+
const aiderPath = path14.join(repoPath, ".aider.chat.history.md");
|
|
16184
16253
|
const aiderExists = fs12.existsSync(aiderPath);
|
|
16185
16254
|
results.push({
|
|
16186
16255
|
id: "aider",
|
|
@@ -16189,8 +16258,8 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16189
16258
|
path: aiderExists ? aiderPath : void 0,
|
|
16190
16259
|
details: aiderExists ? "Repository pairing transcript found" : "No repo-local .aider.chat.history.md found"
|
|
16191
16260
|
});
|
|
16192
|
-
const localOpenCode =
|
|
16193
|
-
const homeOpenCode =
|
|
16261
|
+
const localOpenCode = path14.join(repoPath, ".opencode");
|
|
16262
|
+
const homeOpenCode = path14.join(homedir12, ".opencode", "sessions");
|
|
16194
16263
|
const opencodePath = fs12.existsSync(localOpenCode) ? localOpenCode : fs12.existsSync(homeOpenCode) ? homeOpenCode : void 0;
|
|
16195
16264
|
results.push({
|
|
16196
16265
|
id: "opencode",
|
|
@@ -16202,32 +16271,38 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16202
16271
|
return results;
|
|
16203
16272
|
}
|
|
16204
16273
|
function resolveHooksDir(cwd = process.cwd()) {
|
|
16205
|
-
|
|
16206
|
-
|
|
16207
|
-
|
|
16274
|
+
let curr = path14.resolve(cwd);
|
|
16275
|
+
let gitPath = path14.join(curr, ".git");
|
|
16276
|
+
while (!fs12.existsSync(gitPath)) {
|
|
16277
|
+
const parent = path14.dirname(curr);
|
|
16278
|
+
if (parent === curr)
|
|
16279
|
+
return null;
|
|
16280
|
+
curr = parent;
|
|
16281
|
+
gitPath = path14.join(curr, ".git");
|
|
16282
|
+
}
|
|
16208
16283
|
try {
|
|
16209
16284
|
const stat = fs12.statSync(gitPath);
|
|
16210
16285
|
if (stat.isDirectory()) {
|
|
16211
|
-
return
|
|
16286
|
+
return path14.join(gitPath, "hooks");
|
|
16212
16287
|
}
|
|
16213
16288
|
const content = fs12.readFileSync(gitPath, "utf-8");
|
|
16214
16289
|
const match = content.match(/gitdir:\s*(.+)/i);
|
|
16215
16290
|
if (!match?.[1])
|
|
16216
16291
|
return null;
|
|
16217
16292
|
let gitDir = match[1].trim();
|
|
16218
|
-
if (!
|
|
16219
|
-
gitDir =
|
|
16293
|
+
if (!path14.isAbsolute(gitDir)) {
|
|
16294
|
+
gitDir = path14.resolve(curr, gitDir);
|
|
16220
16295
|
}
|
|
16221
|
-
const commonFile =
|
|
16296
|
+
const commonFile = path14.join(gitDir, "commondir");
|
|
16222
16297
|
if (fs12.existsSync(commonFile)) {
|
|
16223
16298
|
let common = fs12.readFileSync(commonFile, "utf-8").trim();
|
|
16224
|
-
if (!
|
|
16225
|
-
common =
|
|
16226
|
-
return
|
|
16227
|
-
} else if (
|
|
16228
|
-
return
|
|
16299
|
+
if (!path14.isAbsolute(common))
|
|
16300
|
+
common = path14.resolve(gitDir, common);
|
|
16301
|
+
return path14.join(common, "hooks");
|
|
16302
|
+
} else if (path14.basename(path14.dirname(gitDir)) === "worktrees") {
|
|
16303
|
+
return path14.join(path14.dirname(path14.dirname(gitDir)), "hooks");
|
|
16229
16304
|
}
|
|
16230
|
-
return
|
|
16305
|
+
return path14.join(gitDir, "hooks");
|
|
16231
16306
|
} catch {
|
|
16232
16307
|
return null;
|
|
16233
16308
|
}
|
|
@@ -16243,8 +16318,8 @@ function auditGitHooks(repoPath = process.cwd()) {
|
|
|
16243
16318
|
markerFound: false
|
|
16244
16319
|
};
|
|
16245
16320
|
}
|
|
16246
|
-
const postCommit =
|
|
16247
|
-
const postRewrite =
|
|
16321
|
+
const postCommit = path14.join(hooksDir, "post-commit");
|
|
16322
|
+
const postRewrite = path14.join(hooksDir, "post-rewrite");
|
|
16248
16323
|
const hasMarker = (filePath) => {
|
|
16249
16324
|
if (!fs12.existsSync(filePath))
|
|
16250
16325
|
return false;
|
|
@@ -16308,7 +16383,7 @@ async function benchmarkHookLatency(trials = 3) {
|
|
|
16308
16383
|
}
|
|
16309
16384
|
}
|
|
16310
16385
|
function auditStorageHealth() {
|
|
16311
|
-
const dbPath =
|
|
16386
|
+
const dbPath = path14.join(os12.homedir(), ".qodewk", "state.db");
|
|
16312
16387
|
try {
|
|
16313
16388
|
const db = new LocalStateDB();
|
|
16314
16389
|
const stats = db.getStats();
|
|
@@ -16335,7 +16410,7 @@ function auditStorageHealth() {
|
|
|
16335
16410
|
}
|
|
16336
16411
|
function auditPricingSync() {
|
|
16337
16412
|
const modelsCount = Object.keys(RATE_CARDS).length;
|
|
16338
|
-
const cachedJson =
|
|
16413
|
+
const cachedJson = path14.join(os12.homedir(), ".qodewk", "pricing.json");
|
|
16339
16414
|
const hasCached = fs12.existsSync(cachedJson);
|
|
16340
16415
|
return {
|
|
16341
16416
|
modelsLoaded: modelsCount,
|
|
@@ -16359,7 +16434,7 @@ async function runDiagnostics(options = {}) {
|
|
|
16359
16434
|
}
|
|
16360
16435
|
return {
|
|
16361
16436
|
overallStatus,
|
|
16362
|
-
version: "0.
|
|
16437
|
+
version: "0.11.1",
|
|
16363
16438
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16364
16439
|
repoPath,
|
|
16365
16440
|
agents,
|
|
@@ -16422,14 +16497,17 @@ async function generateReceipt(options = {}) {
|
|
|
16422
16497
|
const model = options.model || primaryFp?.model || detected?.model;
|
|
16423
16498
|
const task = options.task || primaryFp?.taskTitle || (harvestResult.tasks.length > 0 ? harvestResult.tasks[0] : void 0);
|
|
16424
16499
|
const sessions = harvestResult.footprints.map((fp) => ({
|
|
16500
|
+
sessionId: fp.sessionId,
|
|
16425
16501
|
provider: fp.platform,
|
|
16426
16502
|
model: fp.model,
|
|
16427
16503
|
task: fp.taskTitle,
|
|
16428
16504
|
filesTouched: fp.filesEdited,
|
|
16505
|
+
turnsCount: fp.stepsCount,
|
|
16429
16506
|
tokens: fp.tokens,
|
|
16430
16507
|
cost: fp.cost,
|
|
16431
16508
|
confidence: fp.confidence,
|
|
16432
|
-
mode: fp.mode
|
|
16509
|
+
mode: fp.mode,
|
|
16510
|
+
createdAt: fp.timestamp
|
|
16433
16511
|
}));
|
|
16434
16512
|
const aiWrittenRatio = computeAiWrittenRatio(metrics.changedFiles, harvestResult.filesEdited);
|
|
16435
16513
|
const costResult = estimateCost({
|
|
@@ -16840,11 +16918,20 @@ function buildTerminalReceipt(receipt, publicUrl) {
|
|
|
16840
16918
|
const provString = receipt.ai.provider + " \xB7 " + (receipt.ai.model || "Unknown");
|
|
16841
16919
|
const cleanProv = provString.length > 40 ? provString.slice(0, 39) + "\u2026" : provString;
|
|
16842
16920
|
printRow(`Provider: ${cleanProv}`);
|
|
16843
|
-
if (receipt.ai.sessions && receipt.ai.sessions.length >
|
|
16844
|
-
|
|
16845
|
-
|
|
16846
|
-
|
|
16921
|
+
if (receipt.ai.sessions && receipt.ai.sessions.length > 0) {
|
|
16922
|
+
printDivider("-");
|
|
16923
|
+
printRow(`ITEMIZED SESSIONS (${receipt.ai.sessions.length}):`);
|
|
16924
|
+
for (const s of receipt.ai.sessions.slice(0, 5)) {
|
|
16925
|
+
const taskLabel = s.task ? s.task.length > 18 ? s.task.slice(0, 17) + "\u2026" : s.task : s.sessionId ? "#" + s.sessionId.slice(0, 8) : s.provider;
|
|
16926
|
+
const cleanMod = (s.model || s.provider).replace(/^(claude-|gemini-|gpt-)/, "");
|
|
16927
|
+
const modelLabel = ` (${cleanMod.length > 11 ? cleanMod.slice(0, 10) + "\u2026" : cleanMod})`;
|
|
16928
|
+
const sCost = s.mode === "verified" ? `$${s.cost.toFixed(2)}` : `~$${s.cost.toFixed(2)}`;
|
|
16929
|
+
printRowSplit(`\u2022 ${taskLabel}${import_picocolors.default.dim(modelLabel)}`, teal(sCost));
|
|
16847
16930
|
}
|
|
16931
|
+
if (receipt.ai.sessions.length > 5) {
|
|
16932
|
+
printRow(import_picocolors.default.dim(` ... and ${receipt.ai.sessions.length - 5} more sessions`));
|
|
16933
|
+
}
|
|
16934
|
+
printDivider("-");
|
|
16848
16935
|
}
|
|
16849
16936
|
if (receipt.ai.aiWrittenRatio !== void 0) {
|
|
16850
16937
|
const aiPct = Math.round(receipt.ai.aiWrittenRatio * 100);
|
|
@@ -16929,7 +17016,7 @@ async function outputReceipt(receipt, options, publicUrl) {
|
|
|
16929
17016
|
|
|
16930
17017
|
// src/hooks.ts
|
|
16931
17018
|
var fs14 = __toESM(require("fs"), 1);
|
|
16932
|
-
var
|
|
17019
|
+
var path15 = __toESM(require("path"), 1);
|
|
16933
17020
|
var HOOK_MARKER_BEGIN2 = "# --- BEGIN QODEWK HOOK ---";
|
|
16934
17021
|
var HOOK_MARKER_END = "# --- END QODEWK HOOK ---";
|
|
16935
17022
|
var HOOK_SNIPPET = `
|
|
@@ -16941,7 +17028,7 @@ fi
|
|
|
16941
17028
|
${HOOK_MARKER_END}
|
|
16942
17029
|
`;
|
|
16943
17030
|
function resolveGitHooksDir(cwd = process.cwd()) {
|
|
16944
|
-
const gitPath =
|
|
17031
|
+
const gitPath = path15.join(cwd, ".git");
|
|
16945
17032
|
if (!fs14.existsSync(gitPath)) return null;
|
|
16946
17033
|
let gitCommonDir;
|
|
16947
17034
|
const stat = fs14.statSync(gitPath);
|
|
@@ -16952,23 +17039,23 @@ function resolveGitHooksDir(cwd = process.cwd()) {
|
|
|
16952
17039
|
const match = content.match(/gitdir:\s*(.+)/i);
|
|
16953
17040
|
if (!match?.[1]) return null;
|
|
16954
17041
|
let gitDir = match[1].trim();
|
|
16955
|
-
if (!
|
|
16956
|
-
gitDir =
|
|
17042
|
+
if (!path15.isAbsolute(gitDir)) {
|
|
17043
|
+
gitDir = path15.resolve(cwd, gitDir);
|
|
16957
17044
|
}
|
|
16958
|
-
const commonFile =
|
|
17045
|
+
const commonFile = path15.join(gitDir, "commondir");
|
|
16959
17046
|
if (fs14.existsSync(commonFile)) {
|
|
16960
17047
|
let common = fs14.readFileSync(commonFile, "utf-8").trim();
|
|
16961
|
-
if (!
|
|
16962
|
-
common =
|
|
17048
|
+
if (!path15.isAbsolute(common)) {
|
|
17049
|
+
common = path15.resolve(gitDir, common);
|
|
16963
17050
|
}
|
|
16964
17051
|
gitCommonDir = common;
|
|
16965
|
-
} else if (
|
|
16966
|
-
gitCommonDir =
|
|
17052
|
+
} else if (path15.basename(path15.dirname(gitDir)) === "worktrees") {
|
|
17053
|
+
gitCommonDir = path15.dirname(path15.dirname(gitDir));
|
|
16967
17054
|
} else {
|
|
16968
17055
|
gitCommonDir = gitDir;
|
|
16969
17056
|
}
|
|
16970
17057
|
}
|
|
16971
|
-
return
|
|
17058
|
+
return path15.join(gitCommonDir, "hooks");
|
|
16972
17059
|
}
|
|
16973
17060
|
function checkHookStatus(hooksDir) {
|
|
16974
17061
|
if (!hooksDir || !fs14.existsSync(hooksDir)) {
|
|
@@ -16979,8 +17066,8 @@ function checkHookStatus(hooksDir) {
|
|
|
16979
17066
|
postRewriteInstalled: false
|
|
16980
17067
|
};
|
|
16981
17068
|
}
|
|
16982
|
-
const postCommit =
|
|
16983
|
-
const postRewrite =
|
|
17069
|
+
const postCommit = path15.join(hooksDir, "post-commit");
|
|
17070
|
+
const postRewrite = path15.join(hooksDir, "post-rewrite");
|
|
16984
17071
|
const hasHook = (p2) => {
|
|
16985
17072
|
if (!fs14.existsSync(p2)) return false;
|
|
16986
17073
|
try {
|
|
@@ -17022,8 +17109,9 @@ function uninstallHookFile(hookFile) {
|
|
|
17022
17109
|
|
|
17023
17110
|
// src/menu.ts
|
|
17024
17111
|
var readline = __toESM(require("readline"), 1);
|
|
17025
|
-
var
|
|
17026
|
-
var
|
|
17112
|
+
var path16 = __toESM(require("path"), 1);
|
|
17113
|
+
var fs15 = __toESM(require("fs"), 1);
|
|
17114
|
+
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
17027
17115
|
|
|
17028
17116
|
// src/doctor-view.ts
|
|
17029
17117
|
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
@@ -17110,6 +17198,98 @@ function formatHookTestReport(hooks, benchmark) {
|
|
|
17110
17198
|
return lines.join("\n");
|
|
17111
17199
|
}
|
|
17112
17200
|
|
|
17201
|
+
// src/chat-view.ts
|
|
17202
|
+
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
17203
|
+
function buildTerminalChatLedger(report) {
|
|
17204
|
+
const lines = [];
|
|
17205
|
+
const coral = colors.coral;
|
|
17206
|
+
const teal = colors.teal;
|
|
17207
|
+
const green = colors.green;
|
|
17208
|
+
const INNER_WIDTH = 68;
|
|
17209
|
+
const push = (line) => lines.push(line);
|
|
17210
|
+
const printRow = (content, width = INNER_WIDTH) => {
|
|
17211
|
+
const visLen = visibleWidth(content);
|
|
17212
|
+
const pad = Math.max(0, width - visLen);
|
|
17213
|
+
push(` | ${content}${" ".repeat(pad)} |`);
|
|
17214
|
+
};
|
|
17215
|
+
const printRowSplit = (left, right, width = INNER_WIDTH) => {
|
|
17216
|
+
const leftVis = visibleWidth(left);
|
|
17217
|
+
const rightVis = visibleWidth(right);
|
|
17218
|
+
const pad = Math.max(1, width - leftVis - rightVis);
|
|
17219
|
+
push(` | ${left}${" ".repeat(pad)}${right} |`);
|
|
17220
|
+
};
|
|
17221
|
+
const printCenteredRow = (content, width = INNER_WIDTH) => {
|
|
17222
|
+
const visLen = visibleWidth(content);
|
|
17223
|
+
const totalPad = Math.max(0, width - visLen);
|
|
17224
|
+
const leftPad = Math.floor(totalPad / 2);
|
|
17225
|
+
const rightPad = totalPad - leftPad;
|
|
17226
|
+
push(` | ${" ".repeat(leftPad)}${content}${" ".repeat(rightPad)} |`);
|
|
17227
|
+
};
|
|
17228
|
+
const printDivider = (char = "=", width = INNER_WIDTH) => {
|
|
17229
|
+
push(` | ${char.repeat(width)} |`);
|
|
17230
|
+
};
|
|
17231
|
+
push("");
|
|
17232
|
+
push(" " + import_picocolors3.default.bold(coral("/\\".repeat(36))));
|
|
17233
|
+
printCenteredRow(import_picocolors3.default.bold(import_picocolors3.default.white("Q O D E W K")));
|
|
17234
|
+
printCenteredRow(coral("*** WORKSPACE CHAT TELEMETRY LEDGER ***"));
|
|
17235
|
+
printRow("");
|
|
17236
|
+
printRowSplit(
|
|
17237
|
+
`REPO: ${report.projectAlias.slice(0, 24)}`,
|
|
17238
|
+
`WINDOW: ${report.windowDescription}`
|
|
17239
|
+
);
|
|
17240
|
+
printRowSplit(
|
|
17241
|
+
`CHATS: ${report.sessionsCount} sessions`,
|
|
17242
|
+
`STEPS: ${report.totalSteps.toLocaleString()} steps`
|
|
17243
|
+
);
|
|
17244
|
+
printDivider("=");
|
|
17245
|
+
if (report.chats.length === 0) {
|
|
17246
|
+
printCenteredRow(import_picocolors3.default.dim("No agent chat sessions found in this workspace window."));
|
|
17247
|
+
printRow("");
|
|
17248
|
+
} else {
|
|
17249
|
+
const colTask = "CHAT / TASK".padEnd(28);
|
|
17250
|
+
const colModel = "MODEL".padEnd(18);
|
|
17251
|
+
const colTok = "TOKENS".padStart(8);
|
|
17252
|
+
const colCost = "COST".padStart(10);
|
|
17253
|
+
printRow(`${colTask} ${colModel} ${colTok} ${colCost}`);
|
|
17254
|
+
printDivider("-");
|
|
17255
|
+
for (const chat of report.chats) {
|
|
17256
|
+
const cleanTitle = (chat.taskTitle || chat.sessionId || "Untitled Session").replace(/\n/g, " ").trim();
|
|
17257
|
+
const taskDisplay = (cleanTitle.length > 27 ? cleanTitle.slice(0, 26) + "\u2026" : cleanTitle).padEnd(28);
|
|
17258
|
+
const cleanModel = (chat.model || chat.platform || "default").replace(/^(claude-|gemini-|gpt-)/, "").slice(0, 17);
|
|
17259
|
+
const modelDisplay = cleanModel.padEnd(18);
|
|
17260
|
+
const tokK = `${Math.round((chat.tokens.input + chat.tokens.output) / 1e3)}k`.padStart(8);
|
|
17261
|
+
const costStr = (chat.mode === "verified" ? `$${chat.cost.toFixed(2)}` : `~$${chat.cost.toFixed(2)}`).padStart(10);
|
|
17262
|
+
printRow(`${taskDisplay} ${import_picocolors3.default.dim(modelDisplay)} ${teal(tokK)} ${coral(costStr)}`);
|
|
17263
|
+
}
|
|
17264
|
+
}
|
|
17265
|
+
printDivider("=");
|
|
17266
|
+
const totalTokK = `${Math.round((report.totalTokens.input + report.totalTokens.output) / 1e3)}k tokens`;
|
|
17267
|
+
printRowSplit("TOTAL ESTIMATED TOKENS:", green(totalTokK));
|
|
17268
|
+
printRowSplit("TOTAL ESTIMATED SPEND:", import_picocolors3.default.bold(coral(`~$${report.totalCost.toFixed(2)}`)));
|
|
17269
|
+
printDivider("=");
|
|
17270
|
+
printCenteredRow(import_picocolors3.default.dim("[\u2713] Zero code exfiltration \xB7 Telemetry calculated locally"));
|
|
17271
|
+
push(" " + import_picocolors3.default.bold(coral("\\/".repeat(36))));
|
|
17272
|
+
push("");
|
|
17273
|
+
return lines.join("\n");
|
|
17274
|
+
}
|
|
17275
|
+
function buildMarkdownChatLedger(report) {
|
|
17276
|
+
const lines = [];
|
|
17277
|
+
lines.push(`### \u{1F916} Qodewk Workspace Chat Telemetry Ledger`);
|
|
17278
|
+
lines.push(`**Repository:** \`${report.projectAlias}\` | **Window:** ${report.windowDescription} | **Total Spend:** \`~$${report.totalCost.toFixed(2)}\``);
|
|
17279
|
+
lines.push("");
|
|
17280
|
+
lines.push("| Chat / Task | Platform | Model | Steps | Tokens | Cost |");
|
|
17281
|
+
lines.push("| :--- | :--- | :--- | :--- | :--- | :--- |");
|
|
17282
|
+
for (const chat of report.chats) {
|
|
17283
|
+
const title = (chat.taskTitle || chat.sessionId).replace(/\|/g, "\\|").trim();
|
|
17284
|
+
const tokensK = `${Math.round((chat.tokens.input + chat.tokens.output) / 1e3)}k`;
|
|
17285
|
+
const cost = chat.mode === "verified" ? `$${chat.cost.toFixed(2)}` : `~$${chat.cost.toFixed(2)}`;
|
|
17286
|
+
lines.push(`| ${title} | \`${chat.platform}\` | \`${chat.model}\` | ${chat.stepsCount} | ${tokensK} | ${cost} |`);
|
|
17287
|
+
}
|
|
17288
|
+
lines.push("");
|
|
17289
|
+
lines.push(`*Total Sessions: ${report.sessionsCount} \xB7 Total Steps: ${report.totalSteps.toLocaleString()}*`);
|
|
17290
|
+
return lines.join("\n");
|
|
17291
|
+
}
|
|
17292
|
+
|
|
17113
17293
|
// src/menu.ts
|
|
17114
17294
|
var SHARE_PAYLOAD_MAX_BYTES = 5e4;
|
|
17115
17295
|
var BANNER_LINES = [
|
|
@@ -17163,6 +17343,12 @@ var MENU_ITEMS = [
|
|
|
17163
17343
|
label: "System Health & Diagnostics",
|
|
17164
17344
|
description: "Audit AI agents, Git hooks, SQLite & pricing registry (doctor)"
|
|
17165
17345
|
},
|
|
17346
|
+
{
|
|
17347
|
+
id: "chats",
|
|
17348
|
+
key: "8",
|
|
17349
|
+
label: "Workspace Chats & Cost Ledger",
|
|
17350
|
+
description: "Inspect all agent conversation sessions and model costs (chats)"
|
|
17351
|
+
},
|
|
17166
17352
|
{
|
|
17167
17353
|
id: "exit",
|
|
17168
17354
|
key: "0",
|
|
@@ -17246,9 +17432,36 @@ var SHARE_HORIZON_ITEMS = [
|
|
|
17246
17432
|
description: "Return to previous screen"
|
|
17247
17433
|
}
|
|
17248
17434
|
];
|
|
17249
|
-
function
|
|
17435
|
+
function resolveMenuCliVersion() {
|
|
17436
|
+
try {
|
|
17437
|
+
const argv1 = process.argv[1] ? path16.dirname(path16.resolve(process.argv[1])) : process.cwd();
|
|
17438
|
+
const candidates = [
|
|
17439
|
+
path16.join(argv1, "..", "package.json"),
|
|
17440
|
+
path16.join(argv1, "package.json")
|
|
17441
|
+
];
|
|
17442
|
+
for (const candidate of candidates) {
|
|
17443
|
+
if (!fs15.existsSync(candidate)) continue;
|
|
17444
|
+
const pkg = JSON.parse(fs15.readFileSync(candidate, "utf-8"));
|
|
17445
|
+
if (pkg.name === "qodewk" && pkg.version) return pkg.version;
|
|
17446
|
+
}
|
|
17447
|
+
} catch {
|
|
17448
|
+
}
|
|
17449
|
+
return "0.11.1";
|
|
17450
|
+
}
|
|
17451
|
+
function computeMenuSubtitle(items, isSubmenu = false) {
|
|
17452
|
+
const numericKeys = items.map((item) => parseInt(item.key, 10)).filter((n) => !isNaN(n) && n > 0);
|
|
17453
|
+
const hasZero = items.some((item) => item.key === "0");
|
|
17454
|
+
const maxKey = numericKeys.length > 0 ? Math.max(...numericKeys) : 0;
|
|
17455
|
+
const jumpText = hasZero && maxKey > 0 ? `0-${maxKey} quick jump` : maxKey > 0 ? `1-${maxKey} quick jump` : "enter select";
|
|
17456
|
+
if (isSubmenu) {
|
|
17457
|
+
return `\u2191\u2193 move \xB7 enter select \xB7 ${jumpText} \xB7 esc / 0 back`;
|
|
17458
|
+
}
|
|
17459
|
+
return `\u2191\u2193 move \xB7 enter select \xB7 ${jumpText} \xB7 q quit`;
|
|
17460
|
+
}
|
|
17461
|
+
function buildMenuFrame(selectedIndex, items = MENU_ITEMS, title = "Telemetry Control Panel", subtitle, options = {}) {
|
|
17250
17462
|
const lines = [];
|
|
17251
17463
|
const push = (line) => lines.push(line);
|
|
17464
|
+
const effectiveSubtitle = subtitle ?? computeMenuSubtitle(items, items !== MENU_ITEMS);
|
|
17252
17465
|
if (options.showBanner ?? true) {
|
|
17253
17466
|
push("");
|
|
17254
17467
|
for (let i2 = 0; i2 < BANNER_LINES.length; i2++) {
|
|
@@ -17257,16 +17470,17 @@ function buildMenuFrame(selectedIndex, items = MENU_ITEMS, title = "Telemetry Co
|
|
|
17257
17470
|
}
|
|
17258
17471
|
}
|
|
17259
17472
|
push("");
|
|
17260
|
-
const badge = bg.teal(
|
|
17261
|
-
|
|
17473
|
+
const badge = bg.teal(import_picocolors4.default.bold(colors.ink(" qodewk ")));
|
|
17474
|
+
const cliVer = resolveMenuCliVersion();
|
|
17475
|
+
push(` ${colors.mutedSoft("\u250C")} ${badge} ${import_picocolors4.default.dim(`v${cliVer}`)}`);
|
|
17262
17476
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17263
17477
|
if (options.actionContext) {
|
|
17264
|
-
push(` ${colors.teal("\u25C7")} ${
|
|
17478
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors4.default.dim("Action:")} ${import_picocolors4.default.white(options.actionContext)}`);
|
|
17265
17479
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17266
17480
|
} else {
|
|
17267
17481
|
const repo = options.repoContext?.alias || "Qodewk";
|
|
17268
17482
|
const branch = options.repoContext?.branch ? `(${options.repoContext.branch})` : "";
|
|
17269
|
-
push(` ${colors.teal("\u25C7")} ${
|
|
17483
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors4.default.dim("Repository:")} ${import_picocolors4.default.white(repo)} ${import_picocolors4.default.dim(branch)}`);
|
|
17270
17484
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17271
17485
|
let telemetryLabel = "Multi-Model Rate Cards (Active)";
|
|
17272
17486
|
try {
|
|
@@ -17278,10 +17492,10 @@ function buildMenuFrame(selectedIndex, items = MENU_ITEMS, title = "Telemetry Co
|
|
|
17278
17492
|
}
|
|
17279
17493
|
} catch {
|
|
17280
17494
|
}
|
|
17281
|
-
push(` ${colors.teal("\u25C7")} ${
|
|
17495
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors4.default.dim("Telemetry:")} ${import_picocolors4.default.white(telemetryLabel)}`);
|
|
17282
17496
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17283
17497
|
}
|
|
17284
|
-
push(` ${colors.coral("\u25C6")} ${
|
|
17498
|
+
push(` ${colors.coral("\u25C6")} ${import_picocolors4.default.bold(import_picocolors4.default.white(title))}`);
|
|
17285
17499
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17286
17500
|
const selectedItem = items[selectedIndex] || items[0];
|
|
17287
17501
|
for (let i2 = 0; i2 < items.length; i2++) {
|
|
@@ -17289,62 +17503,67 @@ function buildMenuFrame(selectedIndex, items = MENU_ITEMS, title = "Telemetry Co
|
|
|
17289
17503
|
const isSelected = i2 === selectedIndex;
|
|
17290
17504
|
if (isSelected) {
|
|
17291
17505
|
push(
|
|
17292
|
-
` ${colors.mutedSoft("\u2502")} ${
|
|
17506
|
+
` ${colors.mutedSoft("\u2502")} ${import_picocolors4.default.bold(colors.coral("\u203A"))} ${import_picocolors4.default.bold(colors.coral(item.key))} ${import_picocolors4.default.bold(import_picocolors4.default.white(item.label))}`
|
|
17293
17507
|
);
|
|
17294
17508
|
} else {
|
|
17295
17509
|
push(
|
|
17296
|
-
` ${colors.mutedSoft("\u2502")} ${
|
|
17510
|
+
` ${colors.mutedSoft("\u2502")} ${import_picocolors4.default.dim(item.key)} ${import_picocolors4.default.dim(import_picocolors4.default.white(item.label))}`
|
|
17297
17511
|
);
|
|
17298
17512
|
}
|
|
17299
17513
|
}
|
|
17300
17514
|
const divider = colors.mutedSoft("\u2500".repeat(58));
|
|
17301
17515
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17302
17516
|
push(` ${colors.mutedSoft("\u2502")} ${divider}`);
|
|
17303
|
-
push(` ${colors.mutedSoft("\u2502")} ${
|
|
17517
|
+
push(` ${colors.mutedSoft("\u2502")} ${import_picocolors4.default.bold(import_picocolors4.default.dim("Description"))}`);
|
|
17304
17518
|
push(` ${colors.mutedSoft("\u2502")} ${colors.amber(selectedItem.description)}`);
|
|
17305
17519
|
push(` ${colors.mutedSoft("\u2502")} ${divider}`);
|
|
17306
17520
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17307
|
-
push(` ${colors.mutedSoft("\u2502")} ${
|
|
17308
|
-
push(` ${colors.mutedSoft("\u2502")} ${colors.green("[\u2713]")} ${
|
|
17521
|
+
push(` ${colors.mutedSoft("\u2502")} ${import_picocolors4.default.dim(effectiveSubtitle)}`);
|
|
17522
|
+
push(` ${colors.mutedSoft("\u2502")} ${colors.green("[\u2713]")} ${import_picocolors4.default.dim("Source code was never uploaded to Qodewk")}`);
|
|
17309
17523
|
push(` ${colors.mutedSoft("\u2514")}`);
|
|
17310
17524
|
push("");
|
|
17311
17525
|
return lines.join("\n");
|
|
17312
17526
|
}
|
|
17313
17527
|
function askLine(promptText) {
|
|
17314
|
-
return new Promise((
|
|
17528
|
+
return new Promise((resolve8) => {
|
|
17315
17529
|
const rl = readline.createInterface({
|
|
17316
17530
|
input: process.stdin,
|
|
17317
17531
|
output: process.stdout
|
|
17318
17532
|
});
|
|
17319
17533
|
rl.question(promptText, (answer) => {
|
|
17320
17534
|
rl.close();
|
|
17321
|
-
|
|
17535
|
+
resolve8(answer.trim());
|
|
17322
17536
|
});
|
|
17323
17537
|
});
|
|
17324
17538
|
}
|
|
17325
17539
|
function waitForKeyToReturn() {
|
|
17326
|
-
return new Promise((
|
|
17327
|
-
console.log(
|
|
17540
|
+
return new Promise((resolve8) => {
|
|
17541
|
+
console.log(import_picocolors4.default.dim("\n Press any key or Enter to return to menu..."));
|
|
17328
17542
|
if (!process.stdin.isTTY) {
|
|
17329
|
-
|
|
17543
|
+
resolve8();
|
|
17330
17544
|
return;
|
|
17331
17545
|
}
|
|
17332
17546
|
const wasRaw = process.stdin.isRaw;
|
|
17333
17547
|
process.stdin.setRawMode(true);
|
|
17334
17548
|
process.stdin.resume();
|
|
17335
|
-
const onKey = () => {
|
|
17549
|
+
const onKey = (data) => {
|
|
17336
17550
|
process.stdin.removeListener("data", onKey);
|
|
17337
17551
|
if (wasRaw !== void 0) process.stdin.setRawMode(wasRaw);
|
|
17338
|
-
|
|
17552
|
+
if (data && (data[0] === 3 || data.toString() === "")) {
|
|
17553
|
+
process.stdout.write("\x1B[?25h");
|
|
17554
|
+
console.log(import_picocolors4.default.dim("\n Exited Qodewk.\n"));
|
|
17555
|
+
process.exit(0);
|
|
17556
|
+
}
|
|
17557
|
+
resolve8();
|
|
17339
17558
|
};
|
|
17340
17559
|
process.stdin.once("data", onKey);
|
|
17341
17560
|
});
|
|
17342
17561
|
}
|
|
17343
17562
|
function waitForKeyOrAction(promptText) {
|
|
17344
|
-
return new Promise((
|
|
17563
|
+
return new Promise((resolve8) => {
|
|
17345
17564
|
console.log(promptText);
|
|
17346
17565
|
if (!process.stdin.isTTY) {
|
|
17347
|
-
|
|
17566
|
+
resolve8("");
|
|
17348
17567
|
return;
|
|
17349
17568
|
}
|
|
17350
17569
|
const wasRaw = process.stdin.isRaw;
|
|
@@ -17354,14 +17573,19 @@ function waitForKeyOrAction(promptText) {
|
|
|
17354
17573
|
process.stdin.removeListener("data", onKey);
|
|
17355
17574
|
if (wasRaw !== void 0) process.stdin.setRawMode(wasRaw);
|
|
17356
17575
|
const str = data.toString();
|
|
17357
|
-
|
|
17576
|
+
if (data[0] === 3 || str === "") {
|
|
17577
|
+
process.stdout.write("\x1B[?25h");
|
|
17578
|
+
console.log(import_picocolors4.default.dim("\n Exited Qodewk.\n"));
|
|
17579
|
+
process.exit(0);
|
|
17580
|
+
}
|
|
17581
|
+
resolve8(str);
|
|
17358
17582
|
};
|
|
17359
17583
|
process.stdin.once("data", onKey);
|
|
17360
17584
|
});
|
|
17361
17585
|
}
|
|
17362
17586
|
async function publishReceiptToCloud(receipt) {
|
|
17363
17587
|
if (process.env.QODEWK_TELEMETRY === "off") {
|
|
17364
|
-
console.log(
|
|
17588
|
+
console.log(import_picocolors4.default.yellow("\n Cloud publishing is disabled by QODEWK_TELEMETRY=off."));
|
|
17365
17589
|
return null;
|
|
17366
17590
|
}
|
|
17367
17591
|
const sanitized = sanitizeReceiptForShare(receipt);
|
|
@@ -17374,11 +17598,11 @@ async function publishReceiptToCloud(receipt) {
|
|
|
17374
17598
|
body = JSON.stringify(trimmed2);
|
|
17375
17599
|
}
|
|
17376
17600
|
if (Buffer.byteLength(body, "utf-8") > SHARE_PAYLOAD_MAX_BYTES) {
|
|
17377
|
-
console.error(
|
|
17601
|
+
console.error(import_picocolors4.default.red(" Sanitized receipt still exceeds the 50 KB cloud payload limit."));
|
|
17378
17602
|
return null;
|
|
17379
17603
|
}
|
|
17380
17604
|
const endpoint = resolveApiUrl();
|
|
17381
|
-
console.log(
|
|
17605
|
+
console.log(import_picocolors4.default.dim(`
|
|
17382
17606
|
[\xB7] Publishing receipt to ${endpoint}...`));
|
|
17383
17607
|
try {
|
|
17384
17608
|
const response = await fetch(endpoint, {
|
|
@@ -17392,11 +17616,11 @@ async function publishReceiptToCloud(receipt) {
|
|
|
17392
17616
|
if (!response.ok) {
|
|
17393
17617
|
const errText = await response.text().catch(() => "");
|
|
17394
17618
|
if (response.status === 503) {
|
|
17395
|
-
console.log(
|
|
17396
|
-
console.log(
|
|
17397
|
-
console.log(
|
|
17619
|
+
console.log(import_picocolors4.default.yellow("\n Notice: Remote server requires durable storage (Supabase or PostgreSQL) in production"));
|
|
17620
|
+
console.log(import_picocolors4.default.dim(" to protect receipts from serverless cold-start data loss."));
|
|
17621
|
+
console.log(import_picocolors4.default.dim(` Endpoint: ${endpoint}`));
|
|
17398
17622
|
console.log(colors.green("\n [\u2713] Your receipt is safely saved locally in: ~/.qodewk/state.db"));
|
|
17399
|
-
console.log(
|
|
17623
|
+
console.log(import_picocolors4.default.dim(" You can also save it as a local Git note: qodewk --notes\n"));
|
|
17400
17624
|
return null;
|
|
17401
17625
|
}
|
|
17402
17626
|
throw new Error(`API responded with ${response.status}: ${errText.slice(0, 100)}`);
|
|
@@ -17407,14 +17631,14 @@ async function publishReceiptToCloud(receipt) {
|
|
|
17407
17631
|
db.close();
|
|
17408
17632
|
console.log("");
|
|
17409
17633
|
console.log(colors.green(" [\u2713] Published successfully."));
|
|
17410
|
-
console.log(` ${
|
|
17411
|
-
console.log(` ${
|
|
17412
|
-
console.log(
|
|
17634
|
+
console.log(` ${import_picocolors4.default.dim("Public URL:")} ${import_picocolors4.default.underline(import_picocolors4.default.cyan(data.url))}`);
|
|
17635
|
+
console.log(` ${import_picocolors4.default.bold(colors.amber("Claim token:"))} ${colors.amber(data.claimToken)}`);
|
|
17636
|
+
console.log(import_picocolors4.default.dim(" (Saved to ~/.qodewk/state.db for future authorship proofs)\n"));
|
|
17413
17637
|
await renderTerminalReceipt(sanitized, data.url);
|
|
17414
17638
|
return data;
|
|
17415
17639
|
} catch (err) {
|
|
17416
17640
|
const message = err instanceof Error ? err.message : String(err);
|
|
17417
|
-
console.error(
|
|
17641
|
+
console.error(import_picocolors4.default.red(`
|
|
17418
17642
|
Share failed: ${message}`));
|
|
17419
17643
|
return null;
|
|
17420
17644
|
}
|
|
@@ -17432,7 +17656,7 @@ async function getRepoContext() {
|
|
|
17432
17656
|
}
|
|
17433
17657
|
const branchSummary = await git.branch();
|
|
17434
17658
|
const branch = branchSummary.current || "HEAD";
|
|
17435
|
-
const alias =
|
|
17659
|
+
const alias = path16.basename(process.cwd());
|
|
17436
17660
|
cachedRepoContext = { alias, branch };
|
|
17437
17661
|
return cachedRepoContext;
|
|
17438
17662
|
} catch {
|
|
@@ -17443,12 +17667,13 @@ async function getRepoContext() {
|
|
|
17443
17667
|
async function runInteractiveMenu() {
|
|
17444
17668
|
if (!process.stdin.isTTY) {
|
|
17445
17669
|
console.log(buildMenuFrame(0));
|
|
17446
|
-
console.log(
|
|
17670
|
+
console.log(import_picocolors4.default.yellow("Interactive menu requires a TTY terminal. Use `qodewk --help` for commands."));
|
|
17447
17671
|
return;
|
|
17448
17672
|
}
|
|
17449
17673
|
const repoContext = await getRepoContext();
|
|
17450
17674
|
let currentScreen = "main";
|
|
17451
17675
|
let selectedIndex = 0;
|
|
17676
|
+
let savedMainIndex = 0;
|
|
17452
17677
|
let active = true;
|
|
17453
17678
|
let lastRenderedLinesCount = 0;
|
|
17454
17679
|
const getActiveItems = () => {
|
|
@@ -17459,7 +17684,7 @@ async function runInteractiveMenu() {
|
|
|
17459
17684
|
const render = () => {
|
|
17460
17685
|
const items = getActiveItems();
|
|
17461
17686
|
const title = currentScreen === "main" ? "Telemetry Control Panel" : currentScreen === "receipt_horizon" ? "Generate Local Receipt" : "Publish Receipt to Cloud";
|
|
17462
|
-
const subtitle = currentScreen
|
|
17687
|
+
const subtitle = computeMenuSubtitle(items, currentScreen !== "main");
|
|
17463
17688
|
const actionContext = currentScreen === "receipt_horizon" ? "Generate Local Receipt" : currentScreen === "share_horizon" ? "Publish Receipt to Cloud" : void 0;
|
|
17464
17689
|
const showBanner = currentScreen === "main";
|
|
17465
17690
|
const frame = buildMenuFrame(selectedIndex, items, title, subtitle, {
|
|
@@ -17500,15 +17725,15 @@ async function runInteractiveMenu() {
|
|
|
17500
17725
|
since = "7d";
|
|
17501
17726
|
label = "past 7 days weekly sprint (--since 7d)";
|
|
17502
17727
|
} else if (item.id === "custom") {
|
|
17503
|
-
console.log(
|
|
17504
|
-
console.log(
|
|
17728
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white(" Custom Telemetry Horizon")));
|
|
17729
|
+
console.log(import_picocolors4.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"));
|
|
17505
17730
|
const input = await askLine(" \u203A Enter duration or date (e.g. 12h, 3d, 2026-10-01): ");
|
|
17506
17731
|
if (input) {
|
|
17507
17732
|
since = input;
|
|
17508
17733
|
label = `custom range: ${input}`;
|
|
17509
17734
|
}
|
|
17510
17735
|
}
|
|
17511
|
-
console.log(
|
|
17736
|
+
console.log(import_picocolors4.default.dim(` [\xB7] Generating local receipt for ${label}...`));
|
|
17512
17737
|
try {
|
|
17513
17738
|
const receipt = await generateReceipt({ since, isPublic: false });
|
|
17514
17739
|
const db = new LocalStateDB();
|
|
@@ -17517,7 +17742,7 @@ async function runInteractiveMenu() {
|
|
|
17517
17742
|
await renderTerminalReceipt(receipt);
|
|
17518
17743
|
console.log("");
|
|
17519
17744
|
const actionKey = await waitForKeyOrAction(
|
|
17520
|
-
` ${colors.coral("[s]")} ${
|
|
17745
|
+
` ${colors.coral("[s]")} ${import_picocolors4.default.white("Publish this receipt to cloud")} \xB7 ${import_picocolors4.default.dim("[any other key] Return to menu")}`
|
|
17521
17746
|
);
|
|
17522
17747
|
if (actionKey.trim().toLowerCase() === "s") {
|
|
17523
17748
|
await publishReceiptToCloud(receipt);
|
|
@@ -17525,12 +17750,12 @@ async function runInteractiveMenu() {
|
|
|
17525
17750
|
}
|
|
17526
17751
|
} catch (err) {
|
|
17527
17752
|
const message = err instanceof Error ? err.message : String(err);
|
|
17528
|
-
console.error(
|
|
17753
|
+
console.error(import_picocolors4.default.red(`
|
|
17529
17754
|
Failed to generate receipt: ${message}`));
|
|
17530
17755
|
await waitForKeyToReturn();
|
|
17531
17756
|
}
|
|
17532
17757
|
currentScreen = "main";
|
|
17533
|
-
selectedIndex =
|
|
17758
|
+
selectedIndex = savedMainIndex;
|
|
17534
17759
|
};
|
|
17535
17760
|
const executeShareHorizon = async (item) => {
|
|
17536
17761
|
cleanup();
|
|
@@ -17548,26 +17773,26 @@ async function runInteractiveMenu() {
|
|
|
17548
17773
|
since = "7d";
|
|
17549
17774
|
label = "past 7 days weekly sprint (--since 7d)";
|
|
17550
17775
|
} else if (item.id === "custom") {
|
|
17551
|
-
console.log(
|
|
17552
|
-
console.log(
|
|
17776
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white(" Custom Telemetry Horizon for Cloud Publish")));
|
|
17777
|
+
console.log(import_picocolors4.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"));
|
|
17553
17778
|
const input = await askLine(" \u203A Enter duration or date (e.g. 12h, 3d, 2026-10-01): ");
|
|
17554
17779
|
if (input) {
|
|
17555
17780
|
since = input;
|
|
17556
17781
|
label = `custom range: ${input}`;
|
|
17557
17782
|
}
|
|
17558
17783
|
}
|
|
17559
|
-
console.log(
|
|
17784
|
+
console.log(import_picocolors4.default.dim(` [\xB7] Generating and publishing receipt for ${label}...`));
|
|
17560
17785
|
try {
|
|
17561
17786
|
const receipt = await generateReceipt({ since, isPublic: false });
|
|
17562
17787
|
await publishReceiptToCloud(receipt);
|
|
17563
17788
|
} catch (err) {
|
|
17564
17789
|
const message = err instanceof Error ? err.message : String(err);
|
|
17565
|
-
console.error(
|
|
17790
|
+
console.error(import_picocolors4.default.red(`
|
|
17566
17791
|
Share failed: ${message}`));
|
|
17567
17792
|
}
|
|
17568
17793
|
await waitForKeyToReturn();
|
|
17569
17794
|
currentScreen = "main";
|
|
17570
|
-
selectedIndex =
|
|
17795
|
+
selectedIndex = savedMainIndex;
|
|
17571
17796
|
};
|
|
17572
17797
|
const executeSelectedAction = async () => {
|
|
17573
17798
|
cleanup();
|
|
@@ -17576,8 +17801,8 @@ async function runInteractiveMenu() {
|
|
|
17576
17801
|
const selectedItem = MENU_ITEMS[selectedIndex];
|
|
17577
17802
|
switch (selectedItem.id) {
|
|
17578
17803
|
case "audit": {
|
|
17579
|
-
console.log(
|
|
17580
|
-
console.log(
|
|
17804
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white("\n Audit Branch or Revision Diff")));
|
|
17805
|
+
console.log(import_picocolors4.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"));
|
|
17581
17806
|
let defaultBase = "origin/main";
|
|
17582
17807
|
try {
|
|
17583
17808
|
defaultBase = await detectDefaultBaseBranch(process.cwd());
|
|
@@ -17589,7 +17814,7 @@ async function runInteractiveMenu() {
|
|
|
17589
17814
|
const head = await askLine(
|
|
17590
17815
|
` \u203A Head git ref or commit SHA [default: HEAD]: `
|
|
17591
17816
|
);
|
|
17592
|
-
console.log(
|
|
17817
|
+
console.log(import_picocolors4.default.dim("\n [\xB7] Auditing git revision range..."));
|
|
17593
17818
|
try {
|
|
17594
17819
|
const receipt = await generateReceipt({
|
|
17595
17820
|
baseSha: base || defaultBase,
|
|
@@ -17602,7 +17827,7 @@ async function runInteractiveMenu() {
|
|
|
17602
17827
|
await renderTerminalReceipt(receipt);
|
|
17603
17828
|
} catch (err) {
|
|
17604
17829
|
const message = err instanceof Error ? err.message : String(err);
|
|
17605
|
-
console.error(
|
|
17830
|
+
console.error(import_picocolors4.default.red(`
|
|
17606
17831
|
Audit failed: ${message}`));
|
|
17607
17832
|
}
|
|
17608
17833
|
await waitForKeyToReturn();
|
|
@@ -17629,10 +17854,14 @@ async function runInteractiveMenu() {
|
|
|
17629
17854
|
await runDoctorDiagnosticsAction();
|
|
17630
17855
|
break;
|
|
17631
17856
|
}
|
|
17857
|
+
case "chats": {
|
|
17858
|
+
await showChatsAction();
|
|
17859
|
+
break;
|
|
17860
|
+
}
|
|
17632
17861
|
case "exit": {
|
|
17633
17862
|
active = false;
|
|
17634
17863
|
cleanup();
|
|
17635
|
-
console.log(
|
|
17864
|
+
console.log(import_picocolors4.default.dim(" Exited Qodewk.\n"));
|
|
17636
17865
|
process.exit(0);
|
|
17637
17866
|
return;
|
|
17638
17867
|
}
|
|
@@ -17641,19 +17870,19 @@ async function runInteractiveMenu() {
|
|
|
17641
17870
|
const manageHooksSubmenu = async () => {
|
|
17642
17871
|
const hooksDir = resolveGitHooksDir();
|
|
17643
17872
|
const status = checkHookStatus(hooksDir);
|
|
17644
|
-
console.log(
|
|
17645
|
-
console.log(
|
|
17873
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white("\n Qodewk Git Hooks Management")));
|
|
17874
|
+
console.log(import_picocolors4.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"));
|
|
17646
17875
|
if (!status.isGit) {
|
|
17647
|
-
console.log(
|
|
17876
|
+
console.log(import_picocolors4.default.yellow(" Not inside a Git repository. Hooks cannot be configured."));
|
|
17648
17877
|
await waitForKeyToReturn();
|
|
17649
17878
|
return;
|
|
17650
17879
|
}
|
|
17651
|
-
console.log(` Hooks directory: ${
|
|
17880
|
+
console.log(` Hooks directory: ${import_picocolors4.default.dim(status.hooksDir || "None")}`);
|
|
17652
17881
|
console.log(
|
|
17653
|
-
` post-commit: ${status.postCommitInstalled ? colors.green("[\u2713 Installed]") :
|
|
17882
|
+
` post-commit: ${status.postCommitInstalled ? colors.green("[\u2713 Installed]") : import_picocolors4.default.dim("[\xB7 Not installed]")}`
|
|
17654
17883
|
);
|
|
17655
17884
|
console.log(
|
|
17656
|
-
` post-rewrite: ${status.postRewriteInstalled ? colors.green("[\u2713 Installed]") :
|
|
17885
|
+
` post-rewrite: ${status.postRewriteInstalled ? colors.green("[\u2713 Installed]") : import_picocolors4.default.dim("[\xB7 Not installed]")}`
|
|
17657
17886
|
);
|
|
17658
17887
|
console.log("");
|
|
17659
17888
|
console.log(" [1] Install non-blocking hooks (< 5ms background recorder)");
|
|
@@ -17662,74 +17891,86 @@ async function runInteractiveMenu() {
|
|
|
17662
17891
|
console.log(" [0] Back to main menu");
|
|
17663
17892
|
console.log("");
|
|
17664
17893
|
const choice = await askLine(" \u203A Select option [0-3]: ");
|
|
17665
|
-
if (choice === "
|
|
17894
|
+
if (choice === "0" || !choice) {
|
|
17895
|
+
return;
|
|
17896
|
+
} else if (choice === "1") {
|
|
17666
17897
|
if (status.hooksDir) {
|
|
17667
17898
|
const targets = ["post-commit", "post-rewrite"];
|
|
17668
17899
|
for (const t2 of targets) {
|
|
17669
|
-
installHookFile(
|
|
17900
|
+
installHookFile(path16.join(status.hooksDir, t2));
|
|
17670
17901
|
}
|
|
17671
17902
|
console.log(colors.green("\n [\u2713] Non-blocking hooks installed successfully."));
|
|
17672
17903
|
}
|
|
17904
|
+
await waitForKeyToReturn();
|
|
17673
17905
|
} else if (choice === "2") {
|
|
17674
17906
|
if (status.hooksDir) {
|
|
17675
17907
|
const targets = ["post-commit", "post-rewrite"];
|
|
17676
17908
|
for (const t2 of targets) {
|
|
17677
|
-
uninstallHookFile(
|
|
17909
|
+
uninstallHookFile(path16.join(status.hooksDir, t2));
|
|
17678
17910
|
}
|
|
17679
17911
|
console.log(colors.green("\n [\u2713] Qodewk hooks removed."));
|
|
17680
17912
|
}
|
|
17913
|
+
await waitForKeyToReturn();
|
|
17681
17914
|
} else if (choice === "3") {
|
|
17682
17915
|
const hooks = auditGitHooks();
|
|
17683
17916
|
const bench = await benchmarkHookLatency();
|
|
17684
17917
|
console.log(formatHookTestReport(hooks, bench));
|
|
17918
|
+
await waitForKeyToReturn();
|
|
17919
|
+
} else {
|
|
17920
|
+
console.log(import_picocolors4.default.yellow(`
|
|
17921
|
+
Option '${choice}' is not recognized.`));
|
|
17922
|
+
await waitForKeyToReturn();
|
|
17685
17923
|
}
|
|
17686
|
-
await waitForKeyToReturn();
|
|
17687
17924
|
};
|
|
17688
17925
|
const manageGitNotesSubmenu = async () => {
|
|
17689
|
-
console.log(
|
|
17690
|
-
console.log(
|
|
17926
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white("\n Qodewk Git Notes Management (refs/notes/qodewk)")));
|
|
17927
|
+
console.log(import_picocolors4.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"));
|
|
17691
17928
|
console.log(" [1] List commits with attached Qodewk notes");
|
|
17692
17929
|
console.log(" [2] Show receipt note on a commit (default: HEAD)");
|
|
17693
17930
|
console.log(" [3] Attach receipt note to a Git commit (default: HEAD)");
|
|
17694
17931
|
console.log(" [0] Back to main menu");
|
|
17695
17932
|
console.log("");
|
|
17696
17933
|
const choice = await askLine(" \u203A Select option [0-3]: ");
|
|
17697
|
-
if (choice === "
|
|
17934
|
+
if (choice === "0" || !choice) {
|
|
17935
|
+
return;
|
|
17936
|
+
} else if (choice === "1") {
|
|
17698
17937
|
try {
|
|
17699
17938
|
const shas = await listGitReceiptNotes();
|
|
17700
17939
|
if (shas.length === 0) {
|
|
17701
|
-
console.log(
|
|
17940
|
+
console.log(import_picocolors4.default.yellow("\n No Qodewk Git notes found in repository."));
|
|
17702
17941
|
} else {
|
|
17703
|
-
console.log(
|
|
17942
|
+
console.log(import_picocolors4.default.bold(`
|
|
17704
17943
|
Found ${shas.length} commit note(s) in refs/notes/qodewk:`));
|
|
17705
17944
|
for (const sha of shas) {
|
|
17706
|
-
console.log(` ${
|
|
17945
|
+
console.log(` ${import_picocolors4.default.cyan(sha.slice(0, 10))} ${import_picocolors4.default.dim(sha)}`);
|
|
17707
17946
|
}
|
|
17708
17947
|
}
|
|
17709
17948
|
} catch (err) {
|
|
17710
17949
|
const message = err instanceof Error ? err.message : String(err);
|
|
17711
|
-
console.error(
|
|
17950
|
+
console.error(import_picocolors4.default.red(`
|
|
17712
17951
|
Error listing Git notes: ${message}`));
|
|
17713
17952
|
}
|
|
17953
|
+
await waitForKeyToReturn();
|
|
17714
17954
|
} else if (choice === "2") {
|
|
17715
17955
|
const commit = await askLine(" \u203A Commit SHA or ref [default: HEAD]: ") || "HEAD";
|
|
17716
17956
|
try {
|
|
17717
17957
|
const receipt = await readGitReceiptNote(commit);
|
|
17718
17958
|
if (!receipt) {
|
|
17719
|
-
console.log(
|
|
17959
|
+
console.log(import_picocolors4.default.yellow(`
|
|
17720
17960
|
No Qodewk receipt note found on commit '${commit}'.`));
|
|
17721
17961
|
} else {
|
|
17722
17962
|
await renderTerminalReceipt(receipt);
|
|
17723
17963
|
}
|
|
17724
17964
|
} catch (err) {
|
|
17725
17965
|
const message = err instanceof Error ? err.message : String(err);
|
|
17726
|
-
console.error(
|
|
17966
|
+
console.error(import_picocolors4.default.red(`
|
|
17727
17967
|
Error reading Git note: ${message}`));
|
|
17728
17968
|
}
|
|
17969
|
+
await waitForKeyToReturn();
|
|
17729
17970
|
} else if (choice === "3") {
|
|
17730
17971
|
const commit = await askLine(" \u203A Commit SHA to attach note [default: HEAD]: ") || "HEAD";
|
|
17731
17972
|
try {
|
|
17732
|
-
console.log(
|
|
17973
|
+
console.log(import_picocolors4.default.dim(`
|
|
17733
17974
|
[\xB7] Generating receipt for ${commit}...`));
|
|
17734
17975
|
const receipt = await generateReceipt({ headSha: commit });
|
|
17735
17976
|
await writeGitReceiptNote(receipt.repository.headSha, receipt);
|
|
@@ -17739,30 +17980,38 @@ async function runInteractiveMenu() {
|
|
|
17739
17980
|
);
|
|
17740
17981
|
} catch (err) {
|
|
17741
17982
|
const message = err instanceof Error ? err.message : String(err);
|
|
17742
|
-
console.error(
|
|
17983
|
+
console.error(import_picocolors4.default.red(`
|
|
17743
17984
|
Error writing Git note: ${message}`));
|
|
17744
17985
|
}
|
|
17986
|
+
await waitForKeyToReturn();
|
|
17987
|
+
} else {
|
|
17988
|
+
console.log(import_picocolors4.default.yellow(`
|
|
17989
|
+
Option '${choice}' is not recognized.`));
|
|
17990
|
+
await waitForKeyToReturn();
|
|
17745
17991
|
}
|
|
17746
|
-
await waitForKeyToReturn();
|
|
17747
17992
|
};
|
|
17748
17993
|
const showStorageStatus = async () => {
|
|
17749
|
-
console.log(
|
|
17750
|
-
console.log(
|
|
17994
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white("\n Qodewk Local Database & Storage Status")));
|
|
17995
|
+
console.log(import_picocolors4.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"));
|
|
17751
17996
|
try {
|
|
17752
17997
|
const db = new LocalStateDB();
|
|
17753
17998
|
const stats = db.getStats();
|
|
17754
17999
|
const recent = db.getRecentReceipts(5);
|
|
17755
18000
|
db.close();
|
|
17756
|
-
console.log(` Database path: ${
|
|
17757
|
-
console.log(` Total saved receipts: ${
|
|
17758
|
-
console.log(` Total agent footprints: ${
|
|
18001
|
+
console.log(` Database path: ${import_picocolors4.default.dim("~/.qodewk/state.db")}`);
|
|
18002
|
+
console.log(` Total saved receipts: ${import_picocolors4.default.bold(import_picocolors4.default.white(String(stats.totalReceipts)))}`);
|
|
18003
|
+
console.log(` Total agent footprints: ${import_picocolors4.default.bold(import_picocolors4.default.white(String(stats.totalFootprints)))}`);
|
|
17759
18004
|
console.log("");
|
|
17760
18005
|
if (recent.length === 0) {
|
|
17761
|
-
console.log(
|
|
18006
|
+
console.log(import_picocolors4.default.dim(" No stored receipts yet. Run 'Generate Local Receipt' to record your first."));
|
|
18007
|
+
console.log("");
|
|
18008
|
+
console.log(` ${colors.green("[\u2713]")} ${import_picocolors4.default.dim("Privacy guarantee: raw source code is never stored in SQLite")}`);
|
|
18009
|
+
await waitForKeyToReturn();
|
|
18010
|
+
return;
|
|
17762
18011
|
} else {
|
|
17763
|
-
console.log(
|
|
17764
|
-
console.log(
|
|
17765
|
-
console.log(
|
|
18012
|
+
console.log(import_picocolors4.default.dim(" Recent Receipts:"));
|
|
18013
|
+
console.log(import_picocolors4.default.dim(" " + "ID".padEnd(26) + "DATE".padEnd(12) + "BRANCH".padEnd(18) + "COST"));
|
|
18014
|
+
console.log(import_picocolors4.default.dim(" " + "\u2500".repeat(60)));
|
|
17766
18015
|
for (const item of recent) {
|
|
17767
18016
|
const id = item.receipt.receipt.id.slice(0, 24).padEnd(26);
|
|
17768
18017
|
const date = item.receipt.receipt.createdAt.slice(0, 10).padEnd(12);
|
|
@@ -17772,7 +18021,7 @@ async function runInteractiveMenu() {
|
|
|
17772
18021
|
}
|
|
17773
18022
|
}
|
|
17774
18023
|
console.log("");
|
|
17775
|
-
console.log(` ${colors.green("[\u2713]")} ${
|
|
18024
|
+
console.log(` ${colors.green("[\u2713]")} ${import_picocolors4.default.dim("Privacy guarantee: raw source code is never stored in SQLite")}`);
|
|
17776
18025
|
if (recent.length > 0) {
|
|
17777
18026
|
console.log("");
|
|
17778
18027
|
const ans = await askLine(" \u203A Enter receipt ID prefix to publish to cloud [Enter to return]: ");
|
|
@@ -17783,26 +18032,45 @@ async function runInteractiveMenu() {
|
|
|
17783
18032
|
await waitForKeyToReturn();
|
|
17784
18033
|
return;
|
|
17785
18034
|
} else {
|
|
17786
|
-
console.log(
|
|
18035
|
+
console.log(import_picocolors4.default.yellow(` No stored receipt matching '${ans}' found.`));
|
|
18036
|
+
await waitForKeyToReturn();
|
|
18037
|
+
return;
|
|
17787
18038
|
}
|
|
18039
|
+
} else {
|
|
18040
|
+
return;
|
|
17788
18041
|
}
|
|
17789
18042
|
}
|
|
17790
18043
|
} catch (err) {
|
|
17791
18044
|
const message = err instanceof Error ? err.message : String(err);
|
|
17792
|
-
console.error(
|
|
18045
|
+
console.error(import_picocolors4.default.red(` Failed to inspect storage: ${message}`));
|
|
18046
|
+
await waitForKeyToReturn();
|
|
17793
18047
|
}
|
|
17794
|
-
await waitForKeyToReturn();
|
|
17795
18048
|
};
|
|
17796
18049
|
const runDoctorDiagnosticsAction = async () => {
|
|
17797
|
-
console.log(
|
|
17798
|
-
console.log(
|
|
17799
|
-
console.log(
|
|
18050
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white("\n Qodewk System Health & Diagnostics (Doctor)")));
|
|
18051
|
+
console.log(import_picocolors4.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"));
|
|
18052
|
+
console.log(import_picocolors4.default.dim(" [\xB7] Running diagnostic audit across agents, hooks, storage, and pricing...\n"));
|
|
17800
18053
|
try {
|
|
17801
18054
|
const report = await runDiagnostics();
|
|
17802
18055
|
console.log(formatDoctorReport(report));
|
|
17803
18056
|
} catch (err) {
|
|
17804
18057
|
const message = err instanceof Error ? err.message : String(err);
|
|
17805
|
-
console.error(
|
|
18058
|
+
console.error(import_picocolors4.default.red(` Diagnostic check failed: ${message}`));
|
|
18059
|
+
}
|
|
18060
|
+
await waitForKeyToReturn();
|
|
18061
|
+
};
|
|
18062
|
+
const showChatsAction = async () => {
|
|
18063
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white("\n Qodewk Workspace Chat Telemetry & Cost Ledger")));
|
|
18064
|
+
console.log(import_picocolors4.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"));
|
|
18065
|
+
console.log(import_picocolors4.default.dim(" [\xB7] Scanning local IDE transcripts (Antigravity, Cursor, Claude, Windsurf, Cline)...\n"));
|
|
18066
|
+
try {
|
|
18067
|
+
const report = await listProjectChats({
|
|
18068
|
+
repoPath: process.cwd()
|
|
18069
|
+
});
|
|
18070
|
+
console.log(buildTerminalChatLedger(report));
|
|
18071
|
+
} catch (err) {
|
|
18072
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
18073
|
+
console.error(import_picocolors4.default.red(` Failed to inspect workspace chats: ${message}`));
|
|
17806
18074
|
}
|
|
17807
18075
|
await waitForKeyToReturn();
|
|
17808
18076
|
};
|
|
@@ -17812,22 +18080,61 @@ async function runInteractiveMenu() {
|
|
|
17812
18080
|
process.stdin.setRawMode(true);
|
|
17813
18081
|
process.stdin.resume();
|
|
17814
18082
|
render();
|
|
18083
|
+
const executeItem = async (selected) => {
|
|
18084
|
+
if (currentScreen === "main") {
|
|
18085
|
+
if (selected.id === "receipt") {
|
|
18086
|
+
savedMainIndex = selectedIndex;
|
|
18087
|
+
currentScreen = "receipt_horizon";
|
|
18088
|
+
selectedIndex = 0;
|
|
18089
|
+
if (active) startLoop();
|
|
18090
|
+
return;
|
|
18091
|
+
}
|
|
18092
|
+
if (selected.id === "share") {
|
|
18093
|
+
savedMainIndex = selectedIndex;
|
|
18094
|
+
currentScreen = "share_horizon";
|
|
18095
|
+
selectedIndex = 0;
|
|
18096
|
+
if (active) startLoop();
|
|
18097
|
+
return;
|
|
18098
|
+
}
|
|
18099
|
+
await executeSelectedAction();
|
|
18100
|
+
} else if (currentScreen === "receipt_horizon") {
|
|
18101
|
+
if (selected.id === "back") {
|
|
18102
|
+
currentScreen = "main";
|
|
18103
|
+
selectedIndex = savedMainIndex;
|
|
18104
|
+
if (active) startLoop();
|
|
18105
|
+
return;
|
|
18106
|
+
}
|
|
18107
|
+
await executeReceiptHorizon(selected);
|
|
18108
|
+
} else if (currentScreen === "share_horizon") {
|
|
18109
|
+
if (selected.id === "back") {
|
|
18110
|
+
currentScreen = "main";
|
|
18111
|
+
selectedIndex = savedMainIndex;
|
|
18112
|
+
if (active) startLoop();
|
|
18113
|
+
return;
|
|
18114
|
+
}
|
|
18115
|
+
await executeShareHorizon(selected);
|
|
18116
|
+
}
|
|
18117
|
+
if (active) {
|
|
18118
|
+
startLoop();
|
|
18119
|
+
}
|
|
18120
|
+
};
|
|
17815
18121
|
const onKeypress = async (_str, key) => {
|
|
17816
18122
|
if (!active) return;
|
|
17817
18123
|
const items = getActiveItems();
|
|
17818
18124
|
if (key.ctrl && key.name === "c") {
|
|
17819
18125
|
cleanup();
|
|
18126
|
+
console.log(import_picocolors4.default.dim("\n Exited Qodewk.\n"));
|
|
17820
18127
|
process.exit(0);
|
|
17821
18128
|
}
|
|
17822
18129
|
if (key.name === "q" || key.name === "escape") {
|
|
17823
18130
|
if (currentScreen !== "main") {
|
|
17824
18131
|
currentScreen = "main";
|
|
17825
|
-
selectedIndex =
|
|
18132
|
+
selectedIndex = savedMainIndex;
|
|
17826
18133
|
render();
|
|
17827
18134
|
return;
|
|
17828
18135
|
}
|
|
17829
18136
|
cleanup();
|
|
17830
|
-
console.log(
|
|
18137
|
+
console.log(import_picocolors4.default.dim("\n Exited Qodewk.\n"));
|
|
17831
18138
|
process.exit(0);
|
|
17832
18139
|
}
|
|
17833
18140
|
if (key.name === "up" || key.name === "k") {
|
|
@@ -17840,85 +18147,19 @@ async function runInteractiveMenu() {
|
|
|
17840
18147
|
render();
|
|
17841
18148
|
return;
|
|
17842
18149
|
}
|
|
17843
|
-
const itemByKey = items.findIndex(
|
|
18150
|
+
const itemByKey = items.findIndex(
|
|
18151
|
+
(item) => item.key === key.name || item.key === _str
|
|
18152
|
+
);
|
|
17844
18153
|
if (itemByKey !== -1) {
|
|
17845
18154
|
selectedIndex = itemByKey;
|
|
17846
18155
|
render();
|
|
17847
18156
|
process.stdin.removeListener("keypress", onKeypress);
|
|
17848
|
-
|
|
17849
|
-
if (currentScreen === "main") {
|
|
17850
|
-
if (selected.id === "receipt") {
|
|
17851
|
-
currentScreen = "receipt_horizon";
|
|
17852
|
-
selectedIndex = 0;
|
|
17853
|
-
if (active) startLoop();
|
|
17854
|
-
return;
|
|
17855
|
-
}
|
|
17856
|
-
if (selected.id === "share") {
|
|
17857
|
-
currentScreen = "share_horizon";
|
|
17858
|
-
selectedIndex = 0;
|
|
17859
|
-
if (active) startLoop();
|
|
17860
|
-
return;
|
|
17861
|
-
}
|
|
17862
|
-
await executeSelectedAction();
|
|
17863
|
-
} else if (currentScreen === "receipt_horizon") {
|
|
17864
|
-
if (selected.id === "back") {
|
|
17865
|
-
currentScreen = "main";
|
|
17866
|
-
selectedIndex = 0;
|
|
17867
|
-
if (active) startLoop();
|
|
17868
|
-
return;
|
|
17869
|
-
}
|
|
17870
|
-
await executeReceiptHorizon(selected);
|
|
17871
|
-
} else if (currentScreen === "share_horizon") {
|
|
17872
|
-
if (selected.id === "back") {
|
|
17873
|
-
currentScreen = "main";
|
|
17874
|
-
selectedIndex = 0;
|
|
17875
|
-
if (active) startLoop();
|
|
17876
|
-
return;
|
|
17877
|
-
}
|
|
17878
|
-
await executeShareHorizon(selected);
|
|
17879
|
-
}
|
|
17880
|
-
if (active) {
|
|
17881
|
-
startLoop();
|
|
17882
|
-
}
|
|
18157
|
+
await executeItem(items[selectedIndex]);
|
|
17883
18158
|
return;
|
|
17884
18159
|
}
|
|
17885
18160
|
if (key.name === "return" || key.name === "enter") {
|
|
17886
18161
|
process.stdin.removeListener("keypress", onKeypress);
|
|
17887
|
-
|
|
17888
|
-
if (currentScreen === "main") {
|
|
17889
|
-
if (selected.id === "receipt") {
|
|
17890
|
-
currentScreen = "receipt_horizon";
|
|
17891
|
-
selectedIndex = 0;
|
|
17892
|
-
if (active) startLoop();
|
|
17893
|
-
return;
|
|
17894
|
-
}
|
|
17895
|
-
if (selected.id === "share") {
|
|
17896
|
-
currentScreen = "share_horizon";
|
|
17897
|
-
selectedIndex = 0;
|
|
17898
|
-
if (active) startLoop();
|
|
17899
|
-
return;
|
|
17900
|
-
}
|
|
17901
|
-
await executeSelectedAction();
|
|
17902
|
-
} else if (currentScreen === "receipt_horizon") {
|
|
17903
|
-
if (selected.id === "back") {
|
|
17904
|
-
currentScreen = "main";
|
|
17905
|
-
selectedIndex = 0;
|
|
17906
|
-
if (active) startLoop();
|
|
17907
|
-
return;
|
|
17908
|
-
}
|
|
17909
|
-
await executeReceiptHorizon(selected);
|
|
17910
|
-
} else if (currentScreen === "share_horizon") {
|
|
17911
|
-
if (selected.id === "back") {
|
|
17912
|
-
currentScreen = "main";
|
|
17913
|
-
selectedIndex = 0;
|
|
17914
|
-
if (active) startLoop();
|
|
17915
|
-
return;
|
|
17916
|
-
}
|
|
17917
|
-
await executeShareHorizon(selected);
|
|
17918
|
-
}
|
|
17919
|
-
if (active) {
|
|
17920
|
-
startLoop();
|
|
17921
|
-
}
|
|
18162
|
+
await executeItem(items[selectedIndex]);
|
|
17922
18163
|
return;
|
|
17923
18164
|
}
|
|
17924
18165
|
};
|
|
@@ -17932,19 +18173,19 @@ loadQodewkEnv();
|
|
|
17932
18173
|
var SHARE_PAYLOAD_MAX_BYTES2 = 5e4;
|
|
17933
18174
|
function resolveCliVersion() {
|
|
17934
18175
|
try {
|
|
17935
|
-
const argv1 = process.argv[1] ?
|
|
18176
|
+
const argv1 = process.argv[1] ? path17.dirname(path17.resolve(process.argv[1])) : process.cwd();
|
|
17936
18177
|
const candidates = [
|
|
17937
|
-
|
|
17938
|
-
|
|
18178
|
+
path17.join(argv1, "..", "package.json"),
|
|
18179
|
+
path17.join(argv1, "package.json")
|
|
17939
18180
|
];
|
|
17940
18181
|
for (const candidate of candidates) {
|
|
17941
|
-
if (!
|
|
17942
|
-
const pkg = JSON.parse(
|
|
18182
|
+
if (!fs16.existsSync(candidate)) continue;
|
|
18183
|
+
const pkg = JSON.parse(fs16.readFileSync(candidate, "utf-8"));
|
|
17943
18184
|
if (pkg.name === "qodewk" && pkg.version) return pkg.version;
|
|
17944
18185
|
}
|
|
17945
18186
|
} catch {
|
|
17946
18187
|
}
|
|
17947
|
-
return "0.
|
|
18188
|
+
return "0.11.1";
|
|
17948
18189
|
}
|
|
17949
18190
|
function resolveSince(options) {
|
|
17950
18191
|
return options.today ? "today" : options.since;
|
|
@@ -17982,21 +18223,44 @@ program2.name("qodewk").description("Universal telemetry and digital receipt gen
|
|
|
17982
18223
|
if (options.notes) {
|
|
17983
18224
|
try {
|
|
17984
18225
|
await writeGitReceiptNote(receipt.repository.headSha, receipt);
|
|
17985
|
-
console.log(
|
|
18226
|
+
console.log(import_picocolors5.default.green(`\u2713 Attached receipt note to ${receipt.repository.headSha.slice(0, 7)} (refs/notes/qodewk)`));
|
|
17986
18227
|
} catch (noteErr) {
|
|
17987
|
-
console.warn(
|
|
18228
|
+
console.warn(import_picocolors5.default.yellow(`Warning: Could not write Git note: ${noteErr.message}`));
|
|
17988
18229
|
}
|
|
17989
18230
|
}
|
|
17990
18231
|
await outputReceipt(receipt, options);
|
|
17991
18232
|
} catch (err) {
|
|
17992
18233
|
const message = err instanceof Error ? err.message : String(err);
|
|
17993
|
-
console.error(
|
|
18234
|
+
console.error(import_picocolors5.default.red(`Error generating receipt: ${message}`));
|
|
17994
18235
|
process.exit(1);
|
|
17995
18236
|
}
|
|
17996
18237
|
});
|
|
17997
18238
|
program2.command("menu").description("Launch interactive terminal control panel").action(async () => {
|
|
17998
18239
|
await runInteractiveMenu();
|
|
17999
18240
|
});
|
|
18241
|
+
program2.command("chats").description("Inspect AI chat sessions and model cost ledger for current workspace").option("-s, --since <duration>", "Filter chats since duration (e.g. today, 24h, 7d, 30d)").option("--today", "Filter chats for today").option("--all", "Show all-time workspace chats (bypass 30-day default window)").option("-p, --platform <platform>", "Filter agent platform (antigravity, claude, cursor, etc.)").option("-j, --json", "Output chat telemetry report in machine-readable JSON format").option("-f, --format <format>", "Output format (terminal, json, markdown)", "terminal").action(async (options) => {
|
|
18242
|
+
try {
|
|
18243
|
+
const since = options.today ? "today" : options.since;
|
|
18244
|
+
const report = await listProjectChats({
|
|
18245
|
+
repoPath: process.cwd(),
|
|
18246
|
+
since,
|
|
18247
|
+
platform: options.platform,
|
|
18248
|
+
all: options.all
|
|
18249
|
+
});
|
|
18250
|
+
const isJson = Boolean(options.json || program2.opts().json || options.format === "json");
|
|
18251
|
+
if (isJson) {
|
|
18252
|
+
console.log(JSON.stringify(report, null, 2));
|
|
18253
|
+
} else if (options.format === "markdown") {
|
|
18254
|
+
console.log(buildMarkdownChatLedger(report));
|
|
18255
|
+
} else {
|
|
18256
|
+
console.log(buildTerminalChatLedger(report));
|
|
18257
|
+
}
|
|
18258
|
+
} catch (err) {
|
|
18259
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
18260
|
+
console.error(import_picocolors5.default.red(`Error listing workspace chats: ${message}`));
|
|
18261
|
+
process.exit(1);
|
|
18262
|
+
}
|
|
18263
|
+
});
|
|
18000
18264
|
program2.command("doctor").description("Run complete diagnostic health check of AI agents, git hooks, and local telemetry").option("-j, --json", "Output diagnostic report in machine-readable JSON format").action(async (options) => {
|
|
18001
18265
|
try {
|
|
18002
18266
|
const isJson = Boolean(options.json || program2.opts().json);
|
|
@@ -18011,7 +18275,7 @@ program2.command("doctor").description("Run complete diagnostic health check of
|
|
|
18011
18275
|
}
|
|
18012
18276
|
} catch (err) {
|
|
18013
18277
|
const message = err instanceof Error ? err.message : String(err);
|
|
18014
|
-
console.error(
|
|
18278
|
+
console.error(import_picocolors5.default.red(`Error running diagnostics: ${message}`));
|
|
18015
18279
|
process.exit(1);
|
|
18016
18280
|
}
|
|
18017
18281
|
});
|
|
@@ -18031,7 +18295,7 @@ program2.command("audit").description("Audit PR or branch diff against a target
|
|
|
18031
18295
|
await outputReceipt(receipt, options);
|
|
18032
18296
|
} catch (err) {
|
|
18033
18297
|
const message = err instanceof Error ? err.message : String(err);
|
|
18034
|
-
console.error(
|
|
18298
|
+
console.error(import_picocolors5.default.red(`Error auditing git range: ${message}`));
|
|
18035
18299
|
process.exit(1);
|
|
18036
18300
|
}
|
|
18037
18301
|
});
|
|
@@ -18048,12 +18312,12 @@ program2.command("share").description("Publish privacy-safe receipt to Qodewk cl
|
|
|
18048
18312
|
const localFlag = program2.opts().local === true;
|
|
18049
18313
|
if (process.env.QODEWK_TELEMETRY === "off" || localFlag) {
|
|
18050
18314
|
console.log(
|
|
18051
|
-
|
|
18315
|
+
import_picocolors5.default.yellow(
|
|
18052
18316
|
`
|
|
18053
18317
|
Cloud publishing is disabled (${localFlag ? "--local" : "QODEWK_TELEMETRY=off"}).`
|
|
18054
18318
|
)
|
|
18055
18319
|
);
|
|
18056
|
-
console.log(
|
|
18320
|
+
console.log(import_picocolors5.default.dim("Telemetry remains strictly stored in local SQLite (~/.qodewk/state.db).\n"));
|
|
18057
18321
|
persistReceipt(receipt);
|
|
18058
18322
|
await renderTerminalReceipt(receipt);
|
|
18059
18323
|
return;
|
|
@@ -18068,11 +18332,11 @@ Cloud publishing is disabled (${localFlag ? "--local" : "QODEWK_TELEMETRY=off"})
|
|
|
18068
18332
|
body = JSON.stringify(trimmed2);
|
|
18069
18333
|
}
|
|
18070
18334
|
if (Buffer.byteLength(body, "utf-8") > SHARE_PAYLOAD_MAX_BYTES2) {
|
|
18071
|
-
console.error(
|
|
18335
|
+
console.error(import_picocolors5.default.red("Sanitized receipt still exceeds the 50 KB cloud payload limit."));
|
|
18072
18336
|
process.exit(1);
|
|
18073
18337
|
}
|
|
18074
18338
|
const endpoint = resolveApiUrl();
|
|
18075
|
-
console.log(
|
|
18339
|
+
console.log(import_picocolors5.default.dim(`Publishing receipt ${sanitized.receipt.id} to ${endpoint}...`));
|
|
18076
18340
|
try {
|
|
18077
18341
|
const response = await fetch(endpoint, {
|
|
18078
18342
|
method: "POST",
|
|
@@ -18089,11 +18353,11 @@ Cloud publishing is disabled (${localFlag ? "--local" : "QODEWK_TELEMETRY=off"})
|
|
|
18089
18353
|
const data = await response.json();
|
|
18090
18354
|
persistReceipt(sanitized, data.claimToken);
|
|
18091
18355
|
console.log("");
|
|
18092
|
-
console.log(
|
|
18093
|
-
console.log(` ${
|
|
18094
|
-
console.log(` ${
|
|
18095
|
-
console.log(` ${
|
|
18096
|
-
console.log(
|
|
18356
|
+
console.log(import_picocolors5.default.green(" Published successfully."));
|
|
18357
|
+
console.log(` ${import_picocolors5.default.dim("Public URL:")} ${import_picocolors5.default.underline(import_picocolors5.default.cyan(data.url))}`);
|
|
18358
|
+
console.log(` ${import_picocolors5.default.bold(import_picocolors5.default.yellow(" Claim token (store securely \u2014 shown once):"))}`);
|
|
18359
|
+
console.log(` ${import_picocolors5.default.yellow(data.claimToken)}`);
|
|
18360
|
+
console.log(import_picocolors5.default.dim(" Saved to ~/.qodewk/state.db \u2014 required to prove authorship later."));
|
|
18097
18361
|
console.log("");
|
|
18098
18362
|
await renderTerminalReceipt(sanitized, data.url);
|
|
18099
18363
|
if (options.json) {
|
|
@@ -18101,14 +18365,14 @@ Cloud publishing is disabled (${localFlag ? "--local" : "QODEWK_TELEMETRY=off"})
|
|
|
18101
18365
|
}
|
|
18102
18366
|
} catch (networkErr) {
|
|
18103
18367
|
const message = networkErr instanceof Error ? networkErr.message : String(networkErr);
|
|
18104
|
-
console.log(
|
|
18368
|
+
console.log(import_picocolors5.default.yellow(`
|
|
18105
18369
|
Could not reach cloud API (${message}). Rendered locally:`));
|
|
18106
18370
|
persistReceipt(receipt);
|
|
18107
18371
|
await renderTerminalReceipt(receipt);
|
|
18108
18372
|
}
|
|
18109
18373
|
} catch (err) {
|
|
18110
18374
|
const message = err instanceof Error ? err.message : String(err);
|
|
18111
|
-
console.error(
|
|
18375
|
+
console.error(import_picocolors5.default.red(`Error sharing receipt: ${message}`));
|
|
18112
18376
|
process.exit(1);
|
|
18113
18377
|
}
|
|
18114
18378
|
});
|
|
@@ -18126,35 +18390,35 @@ hookCommand.command("install").description("Install non-blocking post-commit and
|
|
|
18126
18390
|
try {
|
|
18127
18391
|
const hooksDir = resolveGitHooksDir();
|
|
18128
18392
|
if (!hooksDir) {
|
|
18129
|
-
console.error(
|
|
18393
|
+
console.error(import_picocolors5.default.red("Error: Current directory is not a Git repository (.git not found)."));
|
|
18130
18394
|
process.exit(1);
|
|
18131
18395
|
}
|
|
18132
|
-
if (!
|
|
18133
|
-
|
|
18396
|
+
if (!fs16.existsSync(hooksDir)) {
|
|
18397
|
+
fs16.mkdirSync(hooksDir, { recursive: true });
|
|
18134
18398
|
}
|
|
18135
18399
|
const targets = ["post-commit", "post-rewrite"];
|
|
18136
18400
|
let installed = 0;
|
|
18137
18401
|
let existing = 0;
|
|
18138
18402
|
for (const name of targets) {
|
|
18139
|
-
const result = installHookFile(
|
|
18403
|
+
const result = installHookFile(path17.join(hooksDir, name));
|
|
18140
18404
|
if (result === "installed") installed++;
|
|
18141
18405
|
else existing++;
|
|
18142
18406
|
}
|
|
18143
18407
|
if (installed === 0 && existing > 0) {
|
|
18144
|
-
console.log(
|
|
18408
|
+
console.log(import_picocolors5.default.yellow("Qodewk Git hooks are already installed (post-commit, post-rewrite)."));
|
|
18145
18409
|
return;
|
|
18146
18410
|
}
|
|
18147
18411
|
console.log(
|
|
18148
|
-
|
|
18412
|
+
import_picocolors5.default.green(
|
|
18149
18413
|
`\u2713 Non-blocking Qodewk hooks installed in ${hooksDir} (post-commit${installed > 1 || existing > 0 ? ", post-rewrite" : installed === 1 && targets.length === 2 ? " + post-rewrite" : ""})`
|
|
18150
18414
|
)
|
|
18151
18415
|
);
|
|
18152
18416
|
if (existing > 0) {
|
|
18153
|
-
console.log(
|
|
18417
|
+
console.log(import_picocolors5.default.dim(` (${existing} hook file(s) already contained the Qodewk marker)`));
|
|
18154
18418
|
}
|
|
18155
18419
|
} catch (err) {
|
|
18156
18420
|
const message = err instanceof Error ? err.message : String(err);
|
|
18157
|
-
console.error(
|
|
18421
|
+
console.error(import_picocolors5.default.red(`Failed to install Git hook: ${message}`));
|
|
18158
18422
|
process.exit(1);
|
|
18159
18423
|
}
|
|
18160
18424
|
});
|
|
@@ -18162,23 +18426,23 @@ hookCommand.command("uninstall").description("Remove Qodewk post-commit and post
|
|
|
18162
18426
|
try {
|
|
18163
18427
|
const hooksDir = resolveGitHooksDir();
|
|
18164
18428
|
if (!hooksDir) {
|
|
18165
|
-
console.log(
|
|
18429
|
+
console.log(import_picocolors5.default.yellow("No Git repository found."));
|
|
18166
18430
|
return;
|
|
18167
18431
|
}
|
|
18168
18432
|
const targets = ["post-commit", "post-rewrite"];
|
|
18169
18433
|
let removed = 0;
|
|
18170
18434
|
for (const name of targets) {
|
|
18171
|
-
const result = uninstallHookFile(
|
|
18435
|
+
const result = uninstallHookFile(path17.join(hooksDir, name));
|
|
18172
18436
|
if (result === "removed") removed++;
|
|
18173
18437
|
}
|
|
18174
18438
|
if (removed === 0) {
|
|
18175
|
-
console.log(
|
|
18439
|
+
console.log(import_picocolors5.default.yellow("Qodewk hooks are not installed."));
|
|
18176
18440
|
return;
|
|
18177
18441
|
}
|
|
18178
|
-
console.log(
|
|
18442
|
+
console.log(import_picocolors5.default.green(`\u2713 Qodewk hook markers removed from ${removed} file(s).`));
|
|
18179
18443
|
} catch (err) {
|
|
18180
18444
|
const message = err instanceof Error ? err.message : String(err);
|
|
18181
|
-
console.error(
|
|
18445
|
+
console.error(import_picocolors5.default.red(`Failed to uninstall hook: ${message}`));
|
|
18182
18446
|
process.exit(1);
|
|
18183
18447
|
}
|
|
18184
18448
|
});
|
|
@@ -18197,7 +18461,7 @@ hookCommand.command("test").aliases(["verify", "check"]).description("Verify non
|
|
|
18197
18461
|
}
|
|
18198
18462
|
} catch (err) {
|
|
18199
18463
|
const message = err instanceof Error ? err.message : String(err);
|
|
18200
|
-
console.error(
|
|
18464
|
+
console.error(import_picocolors5.default.red(`Error testing hooks: ${message}`));
|
|
18201
18465
|
process.exit(1);
|
|
18202
18466
|
}
|
|
18203
18467
|
});
|
|
@@ -18206,7 +18470,7 @@ notesCmd.command("show [commit]").description("Display Qodewk receipt attached t
|
|
|
18206
18470
|
try {
|
|
18207
18471
|
const receipt = await readGitReceiptNote(commit);
|
|
18208
18472
|
if (!receipt) {
|
|
18209
|
-
console.log(
|
|
18473
|
+
console.log(import_picocolors5.default.yellow(`No Qodewk receipt note found on commit '${commit}'.`));
|
|
18210
18474
|
return;
|
|
18211
18475
|
}
|
|
18212
18476
|
if (opts.json) {
|
|
@@ -18216,7 +18480,7 @@ notesCmd.command("show [commit]").description("Display Qodewk receipt attached t
|
|
|
18216
18480
|
}
|
|
18217
18481
|
} catch (err) {
|
|
18218
18482
|
const message = err instanceof Error ? err.message : String(err);
|
|
18219
|
-
console.error(
|
|
18483
|
+
console.error(import_picocolors5.default.red(`Error reading Git note: ${message}`));
|
|
18220
18484
|
process.exit(1);
|
|
18221
18485
|
}
|
|
18222
18486
|
});
|
|
@@ -18225,11 +18489,11 @@ notesCmd.command("write [commit]").description("Generate and attach receipt to a
|
|
|
18225
18489
|
const receipt = await generateReceipt({ headSha: commit });
|
|
18226
18490
|
await writeGitReceiptNote(receipt.repository.headSha, receipt);
|
|
18227
18491
|
console.log(
|
|
18228
|
-
|
|
18492
|
+
import_picocolors5.default.green(`\u2713 Attached receipt note to ${receipt.repository.headSha.slice(0, 7)} (refs/notes/qodewk)`)
|
|
18229
18493
|
);
|
|
18230
18494
|
} catch (err) {
|
|
18231
18495
|
const message = err instanceof Error ? err.message : String(err);
|
|
18232
|
-
console.error(
|
|
18496
|
+
console.error(import_picocolors5.default.red(`Error writing Git note: ${message}`));
|
|
18233
18497
|
process.exit(1);
|
|
18234
18498
|
}
|
|
18235
18499
|
});
|
|
@@ -18237,16 +18501,16 @@ notesCmd.command("list").description("List all commits with attached Qodewk rece
|
|
|
18237
18501
|
try {
|
|
18238
18502
|
const shas = await listGitReceiptNotes();
|
|
18239
18503
|
if (shas.length === 0) {
|
|
18240
|
-
console.log(
|
|
18504
|
+
console.log(import_picocolors5.default.yellow("No Qodewk Git notes found in repository."));
|
|
18241
18505
|
return;
|
|
18242
18506
|
}
|
|
18243
|
-
console.log(
|
|
18507
|
+
console.log(import_picocolors5.default.bold(`Found ${shas.length} commit note(s) in refs/notes/qodewk:`));
|
|
18244
18508
|
for (const sha of shas) {
|
|
18245
|
-
console.log(` ${
|
|
18509
|
+
console.log(` ${import_picocolors5.default.cyan(sha.slice(0, 10))} ${import_picocolors5.default.dim(sha)}`);
|
|
18246
18510
|
}
|
|
18247
18511
|
} catch (err) {
|
|
18248
18512
|
const message = err instanceof Error ? err.message : String(err);
|
|
18249
|
-
console.error(
|
|
18513
|
+
console.error(import_picocolors5.default.red(`Error listing Git notes: ${message}`));
|
|
18250
18514
|
process.exit(1);
|
|
18251
18515
|
}
|
|
18252
18516
|
});
|