qodewk 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +721 -306
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1157,7 +1157,7 @@ var require_command = __commonJS({
|
|
|
1157
1157
|
"use strict";
|
|
1158
1158
|
var EventEmitter2 = require("events").EventEmitter;
|
|
1159
1159
|
var childProcess = require("child_process");
|
|
1160
|
-
var
|
|
1160
|
+
var path18 = require("path");
|
|
1161
1161
|
var fs16 = require("fs");
|
|
1162
1162
|
var process3 = require("process");
|
|
1163
1163
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
@@ -2157,9 +2157,9 @@ 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 =
|
|
2160
|
+
const localBin = path18.resolve(baseDir, baseName);
|
|
2161
2161
|
if (fs16.existsSync(localBin)) return localBin;
|
|
2162
|
-
if (sourceExt.includes(
|
|
2162
|
+
if (sourceExt.includes(path18.extname(baseName))) return void 0;
|
|
2163
2163
|
const foundExt = sourceExt.find(
|
|
2164
2164
|
(ext) => fs16.existsSync(`${localBin}${ext}`)
|
|
2165
2165
|
);
|
|
@@ -2177,17 +2177,17 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
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(resolve7, reject) {
|
|
6650
6650
|
const callback = (err, result) => {
|
|
6651
6651
|
if (err) {
|
|
6652
6652
|
return reject(toError(err));
|
|
6653
6653
|
}
|
|
6654
|
-
|
|
6654
|
+
resolve7(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(
|
|
@@ -9319,7 +9319,7 @@ var init_esm = __esm({
|
|
|
9319
9319
|
|
|
9320
9320
|
// src/index.ts
|
|
9321
9321
|
var fs15 = __toESM(require("fs"), 1);
|
|
9322
|
-
var
|
|
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",
|
|
@@ -14352,6 +14370,31 @@ function harvestTrailerFootprints(repoPath, commitMessage, headSha, commitDate)
|
|
|
14352
14370
|
}
|
|
14353
14371
|
return footprints;
|
|
14354
14372
|
}
|
|
14373
|
+
function discoverAntigravityEnvironment() {
|
|
14374
|
+
const isAgent = process.env.ANTIGRAVITY_AGENT === "1" || Boolean(process.env.ANTIGRAVITY_CONVERSATION_ID);
|
|
14375
|
+
const homedir12 = os2.homedir();
|
|
14376
|
+
const antigravityDir = process.env.ANTIGRAVITY_APP_DATA_DIR || path2.join(homedir12, ".gemini", "antigravity");
|
|
14377
|
+
if (isAgent) {
|
|
14378
|
+
return {
|
|
14379
|
+
provider: "antigravity",
|
|
14380
|
+
model: "claude-sonnet-4-6-thinking",
|
|
14381
|
+
confidence: 0.85,
|
|
14382
|
+
mode: "observed"
|
|
14383
|
+
};
|
|
14384
|
+
}
|
|
14385
|
+
if (fs.existsSync(antigravityDir)) {
|
|
14386
|
+
return {
|
|
14387
|
+
provider: "antigravity",
|
|
14388
|
+
model: "claude-sonnet-4-6-thinking",
|
|
14389
|
+
confidence: 0.65,
|
|
14390
|
+
mode: "estimated"
|
|
14391
|
+
};
|
|
14392
|
+
}
|
|
14393
|
+
return null;
|
|
14394
|
+
}
|
|
14395
|
+
|
|
14396
|
+
// ../core/dist/harvester/index.js
|
|
14397
|
+
var path11 = __toESM(require("path"), 1);
|
|
14355
14398
|
|
|
14356
14399
|
// ../core/dist/harvester/antigravity.js
|
|
14357
14400
|
var fs2 = __toESM(require("fs"), 1);
|
|
@@ -14361,7 +14404,8 @@ var import_node_module = require("module");
|
|
|
14361
14404
|
|
|
14362
14405
|
// ../core/dist/harvester/scoring.js
|
|
14363
14406
|
function normalizeFilePath(filePath, repoPath) {
|
|
14364
|
-
let p2 = filePath.replace(
|
|
14407
|
+
let p2 = filePath.trim().replace(/^["']|["']$/g, "").replace(/\\/g, "/");
|
|
14408
|
+
p2 = p2.replace(/\/+/g, "/");
|
|
14365
14409
|
p2 = p2.replace(/^file:\/\/\/?/, "");
|
|
14366
14410
|
if (repoPath) {
|
|
14367
14411
|
const normRepo = repoPath.replace(/\\/g, "/").replace(/\/$/, "");
|
|
@@ -14396,7 +14440,8 @@ function scoreFootprint(fp, gitCtx) {
|
|
|
14396
14440
|
if (found)
|
|
14397
14441
|
matches++;
|
|
14398
14442
|
}
|
|
14399
|
-
const
|
|
14443
|
+
const maxPossibleMatches = Math.min(normChanged.length, normEdited.length);
|
|
14444
|
+
const ratio = maxPossibleMatches > 0 ? matches / maxPossibleMatches : 0;
|
|
14400
14445
|
if (matches > 0) {
|
|
14401
14446
|
score += ratio * 0.4;
|
|
14402
14447
|
} else {
|
|
@@ -15776,38 +15821,86 @@ function parseSinceOption2(since) {
|
|
|
15776
15821
|
}
|
|
15777
15822
|
return void 0;
|
|
15778
15823
|
}
|
|
15779
|
-
|
|
15780
|
-
const
|
|
15781
|
-
|
|
15782
|
-
|
|
15783
|
-
if (!options.platform || options.platform === "all" || options.platform === "antigravity") {
|
|
15784
|
-
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);
|
|
15785
15828
|
allFootprints.push(...agFootprints);
|
|
15786
15829
|
}
|
|
15787
|
-
if (!
|
|
15788
|
-
const claudeFootprints = harvestClaudeFootprints(
|
|
15830
|
+
if (!platform || platform === "all" || platform === "claude") {
|
|
15831
|
+
const claudeFootprints = harvestClaudeFootprints(repoPath, alias, sinceDate);
|
|
15789
15832
|
allFootprints.push(...claudeFootprints);
|
|
15790
15833
|
}
|
|
15791
|
-
if (!
|
|
15792
|
-
const cursorFootprints = harvestCursorFootprints(
|
|
15834
|
+
if (!platform || platform === "all" || platform === "cursor") {
|
|
15835
|
+
const cursorFootprints = harvestCursorFootprints(repoPath, sinceDate);
|
|
15793
15836
|
allFootprints.push(...cursorFootprints);
|
|
15794
15837
|
}
|
|
15795
|
-
if (!
|
|
15796
|
-
const aiderFootprints = harvestAiderFootprints(
|
|
15838
|
+
if (!platform || platform === "all" || platform === "aider") {
|
|
15839
|
+
const aiderFootprints = harvestAiderFootprints(repoPath, sinceDate);
|
|
15797
15840
|
allFootprints.push(...aiderFootprints);
|
|
15798
15841
|
}
|
|
15799
|
-
if (!
|
|
15800
|
-
const windsurfFootprints = harvestWindsurfFootprints(
|
|
15842
|
+
if (!platform || platform === "all" || platform === "windsurf") {
|
|
15843
|
+
const windsurfFootprints = harvestWindsurfFootprints(repoPath, sinceDate);
|
|
15801
15844
|
allFootprints.push(...windsurfFootprints);
|
|
15802
15845
|
}
|
|
15803
|
-
if (!
|
|
15804
|
-
const clineFootprints = harvestClineFootprints(
|
|
15846
|
+
if (!platform || platform === "all" || platform === "cline") {
|
|
15847
|
+
const clineFootprints = harvestClineFootprints(repoPath, sinceDate);
|
|
15805
15848
|
allFootprints.push(...clineFootprints);
|
|
15806
15849
|
}
|
|
15807
|
-
if (!
|
|
15808
|
-
const opencodeFootprints = harvestOpenCodeFootprints(
|
|
15850
|
+
if (!platform || platform === "all" || platform === "opencode") {
|
|
15851
|
+
const opencodeFootprints = harvestOpenCodeFootprints(repoPath, sinceDate);
|
|
15809
15852
|
allFootprints.push(...opencodeFootprints);
|
|
15810
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);
|
|
15811
15904
|
if (options.gitContext?.commitMessage) {
|
|
15812
15905
|
const trailerFps = harvestTrailerFootprints(options.repoPath, options.gitContext.commitMessage, options.gitContext.headSha, options.gitContext.commitDate);
|
|
15813
15906
|
allFootprints.push(...trailerFps);
|
|
@@ -15934,15 +16027,15 @@ function estimateCost(options) {
|
|
|
15934
16027
|
|
|
15935
16028
|
// ../core/dist/pricing-sync.js
|
|
15936
16029
|
var fs10 = __toESM(require("fs"), 1);
|
|
15937
|
-
var
|
|
16030
|
+
var path12 = __toESM(require("path"), 1);
|
|
15938
16031
|
var os10 = __toESM(require("os"), 1);
|
|
15939
16032
|
async function syncDynamicPricing(options) {
|
|
15940
16033
|
try {
|
|
15941
|
-
const qodewkDir =
|
|
16034
|
+
const qodewkDir = path12.join(os10.homedir(), ".qodewk");
|
|
15942
16035
|
if (!fs10.existsSync(qodewkDir)) {
|
|
15943
16036
|
fs10.mkdirSync(qodewkDir, { recursive: true });
|
|
15944
16037
|
}
|
|
15945
|
-
const cacheFile =
|
|
16038
|
+
const cacheFile = path12.join(qodewkDir, "pricing_registry_cache.json");
|
|
15946
16039
|
const TTL_MS = 24 * 60 * 60 * 1e3;
|
|
15947
16040
|
const now = Date.now();
|
|
15948
16041
|
if (!options?.force && fs10.existsSync(cacheFile)) {
|
|
@@ -15977,7 +16070,7 @@ async function syncDynamicPricing(options) {
|
|
|
15977
16070
|
|
|
15978
16071
|
// ../core/dist/env.js
|
|
15979
16072
|
var fs11 = __toESM(require("fs"), 1);
|
|
15980
|
-
var
|
|
16073
|
+
var path13 = __toESM(require("path"), 1);
|
|
15981
16074
|
var os11 = __toESM(require("os"), 1);
|
|
15982
16075
|
var isEnvLoaded = false;
|
|
15983
16076
|
function loadQodewkEnv(startDir = process.cwd()) {
|
|
@@ -15985,11 +16078,11 @@ function loadQodewkEnv(startDir = process.cwd()) {
|
|
|
15985
16078
|
return;
|
|
15986
16079
|
isEnvLoaded = true;
|
|
15987
16080
|
const candidates = [
|
|
15988
|
-
|
|
15989
|
-
|
|
15990
|
-
|
|
15991
|
-
|
|
15992
|
-
|
|
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")
|
|
15993
16086
|
];
|
|
15994
16087
|
for (const envPath of candidates) {
|
|
15995
16088
|
if (!fs11.existsSync(envPath))
|
|
@@ -16065,7 +16158,7 @@ function formatMarkdownReceipt(receipt, publicUrl) {
|
|
|
16065
16158
|
|
|
16066
16159
|
// ../core/dist/doctor.js
|
|
16067
16160
|
var fs12 = __toESM(require("fs"), 1);
|
|
16068
|
-
var
|
|
16161
|
+
var path14 = __toESM(require("path"), 1);
|
|
16069
16162
|
var os12 = __toESM(require("os"), 1);
|
|
16070
16163
|
var import_node_child_process = require("child_process");
|
|
16071
16164
|
var HOOK_MARKER_BEGIN = "# --- BEGIN QODEWK HOOK ---";
|
|
@@ -16073,7 +16166,7 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16073
16166
|
const homedir12 = os12.homedir();
|
|
16074
16167
|
const results = [];
|
|
16075
16168
|
const agEnv = process.env.ANTIGRAVITY_APP_DATA_DIR;
|
|
16076
|
-
const agHome =
|
|
16169
|
+
const agHome = path14.join(homedir12, ".gemini", "antigravity");
|
|
16077
16170
|
const agPath = agEnv && fs12.existsSync(agEnv) ? agEnv : fs12.existsSync(agHome) ? agHome : void 0;
|
|
16078
16171
|
results.push({
|
|
16079
16172
|
id: "antigravity",
|
|
@@ -16082,7 +16175,7 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16082
16175
|
path: agPath,
|
|
16083
16176
|
details: agPath ? "Antigravity brain telemetry detected" : "No active session brain found"
|
|
16084
16177
|
});
|
|
16085
|
-
const claudeProjects =
|
|
16178
|
+
const claudeProjects = path14.join(homedir12, ".claude", "projects");
|
|
16086
16179
|
const claudeExists = fs12.existsSync(claudeProjects);
|
|
16087
16180
|
results.push({
|
|
16088
16181
|
id: "claude",
|
|
@@ -16093,15 +16186,15 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16093
16186
|
});
|
|
16094
16187
|
let cursorPath;
|
|
16095
16188
|
if (process.platform === "win32") {
|
|
16096
|
-
const c3 =
|
|
16189
|
+
const c3 = path14.join(process.env.APPDATA || path14.join(homedir12, "AppData", "Roaming"), "Cursor", "User", "workspaceStorage");
|
|
16097
16190
|
if (fs12.existsSync(c3))
|
|
16098
16191
|
cursorPath = c3;
|
|
16099
16192
|
} else if (process.platform === "darwin") {
|
|
16100
|
-
const c3 =
|
|
16193
|
+
const c3 = path14.join(homedir12, "Library", "Application Support", "Cursor", "User", "workspaceStorage");
|
|
16101
16194
|
if (fs12.existsSync(c3))
|
|
16102
16195
|
cursorPath = c3;
|
|
16103
16196
|
} else {
|
|
16104
|
-
const c3 =
|
|
16197
|
+
const c3 = path14.join(homedir12, ".config", "Cursor", "User", "workspaceStorage");
|
|
16105
16198
|
if (fs12.existsSync(c3))
|
|
16106
16199
|
cursorPath = c3;
|
|
16107
16200
|
}
|
|
@@ -16114,15 +16207,15 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16114
16207
|
});
|
|
16115
16208
|
let windsurfPath;
|
|
16116
16209
|
if (process.platform === "win32") {
|
|
16117
|
-
const w =
|
|
16210
|
+
const w = path14.join(process.env.APPDATA || path14.join(homedir12, "AppData", "Roaming"), "Windsurf", "User", "workspaceStorage");
|
|
16118
16211
|
if (fs12.existsSync(w))
|
|
16119
16212
|
windsurfPath = w;
|
|
16120
16213
|
} else if (process.platform === "darwin") {
|
|
16121
|
-
const w =
|
|
16214
|
+
const w = path14.join(homedir12, "Library", "Application Support", "Windsurf", "User", "workspaceStorage");
|
|
16122
16215
|
if (fs12.existsSync(w))
|
|
16123
16216
|
windsurfPath = w;
|
|
16124
16217
|
} else {
|
|
16125
|
-
const w =
|
|
16218
|
+
const w = path14.join(homedir12, ".config", "Windsurf", "User", "workspaceStorage");
|
|
16126
16219
|
if (fs12.existsSync(w))
|
|
16127
16220
|
windsurfPath = w;
|
|
16128
16221
|
}
|
|
@@ -16134,16 +16227,16 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16134
16227
|
details: windsurfPath ? "Cascade session workspace storage detected" : "Windsurf IDE storage not detected"
|
|
16135
16228
|
});
|
|
16136
16229
|
let clinePath;
|
|
16137
|
-
const localCline =
|
|
16138
|
-
const localRoo =
|
|
16230
|
+
const localCline = path14.join(repoPath, ".cline");
|
|
16231
|
+
const localRoo = path14.join(repoPath, ".roo");
|
|
16139
16232
|
if (fs12.existsSync(localCline)) {
|
|
16140
16233
|
clinePath = localCline;
|
|
16141
16234
|
} else if (fs12.existsSync(localRoo)) {
|
|
16142
16235
|
clinePath = localRoo;
|
|
16143
16236
|
} else {
|
|
16144
|
-
const appData = process.platform === "win32" ? process.env.APPDATA ||
|
|
16145
|
-
const clineExt =
|
|
16146
|
-
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");
|
|
16147
16240
|
if (fs12.existsSync(clineExt))
|
|
16148
16241
|
clinePath = clineExt;
|
|
16149
16242
|
else if (fs12.existsSync(rooExt))
|
|
@@ -16156,7 +16249,7 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16156
16249
|
path: clinePath,
|
|
16157
16250
|
details: clinePath ? "VS Code autonomous agent task storage detected" : "No active Cline or Roo Code tasks found"
|
|
16158
16251
|
});
|
|
16159
|
-
const aiderPath =
|
|
16252
|
+
const aiderPath = path14.join(repoPath, ".aider.chat.history.md");
|
|
16160
16253
|
const aiderExists = fs12.existsSync(aiderPath);
|
|
16161
16254
|
results.push({
|
|
16162
16255
|
id: "aider",
|
|
@@ -16165,8 +16258,8 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16165
16258
|
path: aiderExists ? aiderPath : void 0,
|
|
16166
16259
|
details: aiderExists ? "Repository pairing transcript found" : "No repo-local .aider.chat.history.md found"
|
|
16167
16260
|
});
|
|
16168
|
-
const localOpenCode =
|
|
16169
|
-
const homeOpenCode =
|
|
16261
|
+
const localOpenCode = path14.join(repoPath, ".opencode");
|
|
16262
|
+
const homeOpenCode = path14.join(homedir12, ".opencode", "sessions");
|
|
16170
16263
|
const opencodePath = fs12.existsSync(localOpenCode) ? localOpenCode : fs12.existsSync(homeOpenCode) ? homeOpenCode : void 0;
|
|
16171
16264
|
results.push({
|
|
16172
16265
|
id: "opencode",
|
|
@@ -16178,32 +16271,38 @@ function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
|
16178
16271
|
return results;
|
|
16179
16272
|
}
|
|
16180
16273
|
function resolveHooksDir(cwd = process.cwd()) {
|
|
16181
|
-
|
|
16182
|
-
|
|
16183
|
-
|
|
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
|
+
}
|
|
16184
16283
|
try {
|
|
16185
16284
|
const stat = fs12.statSync(gitPath);
|
|
16186
16285
|
if (stat.isDirectory()) {
|
|
16187
|
-
return
|
|
16286
|
+
return path14.join(gitPath, "hooks");
|
|
16188
16287
|
}
|
|
16189
16288
|
const content = fs12.readFileSync(gitPath, "utf-8");
|
|
16190
16289
|
const match = content.match(/gitdir:\s*(.+)/i);
|
|
16191
16290
|
if (!match?.[1])
|
|
16192
16291
|
return null;
|
|
16193
16292
|
let gitDir = match[1].trim();
|
|
16194
|
-
if (!
|
|
16195
|
-
gitDir =
|
|
16293
|
+
if (!path14.isAbsolute(gitDir)) {
|
|
16294
|
+
gitDir = path14.resolve(curr, gitDir);
|
|
16196
16295
|
}
|
|
16197
|
-
const commonFile =
|
|
16296
|
+
const commonFile = path14.join(gitDir, "commondir");
|
|
16198
16297
|
if (fs12.existsSync(commonFile)) {
|
|
16199
16298
|
let common = fs12.readFileSync(commonFile, "utf-8").trim();
|
|
16200
|
-
if (!
|
|
16201
|
-
common =
|
|
16202
|
-
return
|
|
16203
|
-
} else if (
|
|
16204
|
-
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");
|
|
16205
16304
|
}
|
|
16206
|
-
return
|
|
16305
|
+
return path14.join(gitDir, "hooks");
|
|
16207
16306
|
} catch {
|
|
16208
16307
|
return null;
|
|
16209
16308
|
}
|
|
@@ -16219,8 +16318,8 @@ function auditGitHooks(repoPath = process.cwd()) {
|
|
|
16219
16318
|
markerFound: false
|
|
16220
16319
|
};
|
|
16221
16320
|
}
|
|
16222
|
-
const postCommit =
|
|
16223
|
-
const postRewrite =
|
|
16321
|
+
const postCommit = path14.join(hooksDir, "post-commit");
|
|
16322
|
+
const postRewrite = path14.join(hooksDir, "post-rewrite");
|
|
16224
16323
|
const hasMarker = (filePath) => {
|
|
16225
16324
|
if (!fs12.existsSync(filePath))
|
|
16226
16325
|
return false;
|
|
@@ -16284,7 +16383,7 @@ async function benchmarkHookLatency(trials = 3) {
|
|
|
16284
16383
|
}
|
|
16285
16384
|
}
|
|
16286
16385
|
function auditStorageHealth() {
|
|
16287
|
-
const dbPath =
|
|
16386
|
+
const dbPath = path14.join(os12.homedir(), ".qodewk", "state.db");
|
|
16288
16387
|
try {
|
|
16289
16388
|
const db = new LocalStateDB();
|
|
16290
16389
|
const stats = db.getStats();
|
|
@@ -16311,7 +16410,7 @@ function auditStorageHealth() {
|
|
|
16311
16410
|
}
|
|
16312
16411
|
function auditPricingSync() {
|
|
16313
16412
|
const modelsCount = Object.keys(RATE_CARDS).length;
|
|
16314
|
-
const cachedJson =
|
|
16413
|
+
const cachedJson = path14.join(os12.homedir(), ".qodewk", "pricing.json");
|
|
16315
16414
|
const hasCached = fs12.existsSync(cachedJson);
|
|
16316
16415
|
return {
|
|
16317
16416
|
modelsLoaded: modelsCount,
|
|
@@ -16335,7 +16434,7 @@ async function runDiagnostics(options = {}) {
|
|
|
16335
16434
|
}
|
|
16336
16435
|
return {
|
|
16337
16436
|
overallStatus,
|
|
16338
|
-
version: "0.
|
|
16437
|
+
version: "0.11.0",
|
|
16339
16438
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16340
16439
|
repoPath,
|
|
16341
16440
|
agents,
|
|
@@ -16398,14 +16497,17 @@ async function generateReceipt(options = {}) {
|
|
|
16398
16497
|
const model = options.model || primaryFp?.model || detected?.model;
|
|
16399
16498
|
const task = options.task || primaryFp?.taskTitle || (harvestResult.tasks.length > 0 ? harvestResult.tasks[0] : void 0);
|
|
16400
16499
|
const sessions = harvestResult.footprints.map((fp) => ({
|
|
16500
|
+
sessionId: fp.sessionId,
|
|
16401
16501
|
provider: fp.platform,
|
|
16402
16502
|
model: fp.model,
|
|
16403
16503
|
task: fp.taskTitle,
|
|
16404
16504
|
filesTouched: fp.filesEdited,
|
|
16505
|
+
turnsCount: fp.stepsCount,
|
|
16405
16506
|
tokens: fp.tokens,
|
|
16406
16507
|
cost: fp.cost,
|
|
16407
16508
|
confidence: fp.confidence,
|
|
16408
|
-
mode: fp.mode
|
|
16509
|
+
mode: fp.mode,
|
|
16510
|
+
createdAt: fp.timestamp
|
|
16409
16511
|
}));
|
|
16410
16512
|
const aiWrittenRatio = computeAiWrittenRatio(metrics.changedFiles, harvestResult.filesEdited);
|
|
16411
16513
|
const costResult = estimateCost({
|
|
@@ -16816,11 +16918,20 @@ function buildTerminalReceipt(receipt, publicUrl) {
|
|
|
16816
16918
|
const provString = receipt.ai.provider + " \xB7 " + (receipt.ai.model || "Unknown");
|
|
16817
16919
|
const cleanProv = provString.length > 40 ? provString.slice(0, 39) + "\u2026" : provString;
|
|
16818
16920
|
printRow(`Provider: ${cleanProv}`);
|
|
16819
|
-
if (receipt.ai.sessions && receipt.ai.sessions.length >
|
|
16820
|
-
|
|
16821
|
-
|
|
16822
|
-
|
|
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));
|
|
16930
|
+
}
|
|
16931
|
+
if (receipt.ai.sessions.length > 5) {
|
|
16932
|
+
printRow(import_picocolors.default.dim(` ... and ${receipt.ai.sessions.length - 5} more sessions`));
|
|
16823
16933
|
}
|
|
16934
|
+
printDivider("-");
|
|
16824
16935
|
}
|
|
16825
16936
|
if (receipt.ai.aiWrittenRatio !== void 0) {
|
|
16826
16937
|
const aiPct = Math.round(receipt.ai.aiWrittenRatio * 100);
|
|
@@ -16905,7 +17016,7 @@ async function outputReceipt(receipt, options, publicUrl) {
|
|
|
16905
17016
|
|
|
16906
17017
|
// src/hooks.ts
|
|
16907
17018
|
var fs14 = __toESM(require("fs"), 1);
|
|
16908
|
-
var
|
|
17019
|
+
var path15 = __toESM(require("path"), 1);
|
|
16909
17020
|
var HOOK_MARKER_BEGIN2 = "# --- BEGIN QODEWK HOOK ---";
|
|
16910
17021
|
var HOOK_MARKER_END = "# --- END QODEWK HOOK ---";
|
|
16911
17022
|
var HOOK_SNIPPET = `
|
|
@@ -16917,7 +17028,7 @@ fi
|
|
|
16917
17028
|
${HOOK_MARKER_END}
|
|
16918
17029
|
`;
|
|
16919
17030
|
function resolveGitHooksDir(cwd = process.cwd()) {
|
|
16920
|
-
const gitPath =
|
|
17031
|
+
const gitPath = path15.join(cwd, ".git");
|
|
16921
17032
|
if (!fs14.existsSync(gitPath)) return null;
|
|
16922
17033
|
let gitCommonDir;
|
|
16923
17034
|
const stat = fs14.statSync(gitPath);
|
|
@@ -16928,23 +17039,23 @@ function resolveGitHooksDir(cwd = process.cwd()) {
|
|
|
16928
17039
|
const match = content.match(/gitdir:\s*(.+)/i);
|
|
16929
17040
|
if (!match?.[1]) return null;
|
|
16930
17041
|
let gitDir = match[1].trim();
|
|
16931
|
-
if (!
|
|
16932
|
-
gitDir =
|
|
17042
|
+
if (!path15.isAbsolute(gitDir)) {
|
|
17043
|
+
gitDir = path15.resolve(cwd, gitDir);
|
|
16933
17044
|
}
|
|
16934
|
-
const commonFile =
|
|
17045
|
+
const commonFile = path15.join(gitDir, "commondir");
|
|
16935
17046
|
if (fs14.existsSync(commonFile)) {
|
|
16936
17047
|
let common = fs14.readFileSync(commonFile, "utf-8").trim();
|
|
16937
|
-
if (!
|
|
16938
|
-
common =
|
|
17048
|
+
if (!path15.isAbsolute(common)) {
|
|
17049
|
+
common = path15.resolve(gitDir, common);
|
|
16939
17050
|
}
|
|
16940
17051
|
gitCommonDir = common;
|
|
16941
|
-
} else if (
|
|
16942
|
-
gitCommonDir =
|
|
17052
|
+
} else if (path15.basename(path15.dirname(gitDir)) === "worktrees") {
|
|
17053
|
+
gitCommonDir = path15.dirname(path15.dirname(gitDir));
|
|
16943
17054
|
} else {
|
|
16944
17055
|
gitCommonDir = gitDir;
|
|
16945
17056
|
}
|
|
16946
17057
|
}
|
|
16947
|
-
return
|
|
17058
|
+
return path15.join(gitCommonDir, "hooks");
|
|
16948
17059
|
}
|
|
16949
17060
|
function checkHookStatus(hooksDir) {
|
|
16950
17061
|
if (!hooksDir || !fs14.existsSync(hooksDir)) {
|
|
@@ -16955,8 +17066,8 @@ function checkHookStatus(hooksDir) {
|
|
|
16955
17066
|
postRewriteInstalled: false
|
|
16956
17067
|
};
|
|
16957
17068
|
}
|
|
16958
|
-
const postCommit =
|
|
16959
|
-
const postRewrite =
|
|
17069
|
+
const postCommit = path15.join(hooksDir, "post-commit");
|
|
17070
|
+
const postRewrite = path15.join(hooksDir, "post-rewrite");
|
|
16960
17071
|
const hasHook = (p2) => {
|
|
16961
17072
|
if (!fs14.existsSync(p2)) return false;
|
|
16962
17073
|
try {
|
|
@@ -16998,8 +17109,8 @@ function uninstallHookFile(hookFile) {
|
|
|
16998
17109
|
|
|
16999
17110
|
// src/menu.ts
|
|
17000
17111
|
var readline = __toESM(require("readline"), 1);
|
|
17001
|
-
var
|
|
17002
|
-
var
|
|
17112
|
+
var path16 = __toESM(require("path"), 1);
|
|
17113
|
+
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
17003
17114
|
|
|
17004
17115
|
// src/doctor-view.ts
|
|
17005
17116
|
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
@@ -17086,6 +17197,98 @@ function formatHookTestReport(hooks, benchmark) {
|
|
|
17086
17197
|
return lines.join("\n");
|
|
17087
17198
|
}
|
|
17088
17199
|
|
|
17200
|
+
// src/chat-view.ts
|
|
17201
|
+
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
17202
|
+
function buildTerminalChatLedger(report) {
|
|
17203
|
+
const lines = [];
|
|
17204
|
+
const coral = colors.coral;
|
|
17205
|
+
const teal = colors.teal;
|
|
17206
|
+
const green = colors.green;
|
|
17207
|
+
const INNER_WIDTH = 68;
|
|
17208
|
+
const push = (line) => lines.push(line);
|
|
17209
|
+
const printRow = (content, width = INNER_WIDTH) => {
|
|
17210
|
+
const visLen = visibleWidth(content);
|
|
17211
|
+
const pad = Math.max(0, width - visLen);
|
|
17212
|
+
push(` | ${content}${" ".repeat(pad)} |`);
|
|
17213
|
+
};
|
|
17214
|
+
const printRowSplit = (left, right, width = INNER_WIDTH) => {
|
|
17215
|
+
const leftVis = visibleWidth(left);
|
|
17216
|
+
const rightVis = visibleWidth(right);
|
|
17217
|
+
const pad = Math.max(1, width - leftVis - rightVis);
|
|
17218
|
+
push(` | ${left}${" ".repeat(pad)}${right} |`);
|
|
17219
|
+
};
|
|
17220
|
+
const printCenteredRow = (content, width = INNER_WIDTH) => {
|
|
17221
|
+
const visLen = visibleWidth(content);
|
|
17222
|
+
const totalPad = Math.max(0, width - visLen);
|
|
17223
|
+
const leftPad = Math.floor(totalPad / 2);
|
|
17224
|
+
const rightPad = totalPad - leftPad;
|
|
17225
|
+
push(` | ${" ".repeat(leftPad)}${content}${" ".repeat(rightPad)} |`);
|
|
17226
|
+
};
|
|
17227
|
+
const printDivider = (char = "=", width = INNER_WIDTH) => {
|
|
17228
|
+
push(` | ${char.repeat(width)} |`);
|
|
17229
|
+
};
|
|
17230
|
+
push("");
|
|
17231
|
+
push(" " + import_picocolors3.default.bold(coral("/\\".repeat(36))));
|
|
17232
|
+
printCenteredRow(import_picocolors3.default.bold(import_picocolors3.default.white("Q O D E W K")));
|
|
17233
|
+
printCenteredRow(coral("*** WORKSPACE CHAT TELEMETRY LEDGER ***"));
|
|
17234
|
+
printRow("");
|
|
17235
|
+
printRowSplit(
|
|
17236
|
+
`REPO: ${report.projectAlias.slice(0, 24)}`,
|
|
17237
|
+
`WINDOW: ${report.windowDescription}`
|
|
17238
|
+
);
|
|
17239
|
+
printRowSplit(
|
|
17240
|
+
`CHATS: ${report.sessionsCount} sessions`,
|
|
17241
|
+
`STEPS: ${report.totalSteps.toLocaleString()} steps`
|
|
17242
|
+
);
|
|
17243
|
+
printDivider("=");
|
|
17244
|
+
if (report.chats.length === 0) {
|
|
17245
|
+
printCenteredRow(import_picocolors3.default.dim("No agent chat sessions found in this workspace window."));
|
|
17246
|
+
printRow("");
|
|
17247
|
+
} else {
|
|
17248
|
+
const colTask = "CHAT / TASK".padEnd(28);
|
|
17249
|
+
const colModel = "MODEL".padEnd(18);
|
|
17250
|
+
const colTok = "TOKENS".padStart(8);
|
|
17251
|
+
const colCost = "COST".padStart(10);
|
|
17252
|
+
printRow(`${colTask} ${colModel} ${colTok} ${colCost}`);
|
|
17253
|
+
printDivider("-");
|
|
17254
|
+
for (const chat of report.chats) {
|
|
17255
|
+
const cleanTitle = (chat.taskTitle || chat.sessionId || "Untitled Session").replace(/\n/g, " ").trim();
|
|
17256
|
+
const taskDisplay = (cleanTitle.length > 27 ? cleanTitle.slice(0, 26) + "\u2026" : cleanTitle).padEnd(28);
|
|
17257
|
+
const cleanModel = (chat.model || chat.platform || "default").replace(/^(claude-|gemini-|gpt-)/, "").slice(0, 17);
|
|
17258
|
+
const modelDisplay = cleanModel.padEnd(18);
|
|
17259
|
+
const tokK = `${Math.round((chat.tokens.input + chat.tokens.output) / 1e3)}k`.padStart(8);
|
|
17260
|
+
const costStr = (chat.mode === "verified" ? `$${chat.cost.toFixed(2)}` : `~$${chat.cost.toFixed(2)}`).padStart(10);
|
|
17261
|
+
printRow(`${taskDisplay} ${import_picocolors3.default.dim(modelDisplay)} ${teal(tokK)} ${coral(costStr)}`);
|
|
17262
|
+
}
|
|
17263
|
+
}
|
|
17264
|
+
printDivider("=");
|
|
17265
|
+
const totalTokK = `${Math.round((report.totalTokens.input + report.totalTokens.output) / 1e3)}k tokens`;
|
|
17266
|
+
printRowSplit("TOTAL ESTIMATED TOKENS:", green(totalTokK));
|
|
17267
|
+
printRowSplit("TOTAL ESTIMATED SPEND:", import_picocolors3.default.bold(coral(`~$${report.totalCost.toFixed(2)}`)));
|
|
17268
|
+
printDivider("=");
|
|
17269
|
+
printCenteredRow(import_picocolors3.default.dim("[\u2713] Zero code exfiltration \xB7 Telemetry calculated locally"));
|
|
17270
|
+
push(" " + import_picocolors3.default.bold(coral("\\/".repeat(36))));
|
|
17271
|
+
push("");
|
|
17272
|
+
return lines.join("\n");
|
|
17273
|
+
}
|
|
17274
|
+
function buildMarkdownChatLedger(report) {
|
|
17275
|
+
const lines = [];
|
|
17276
|
+
lines.push(`### \u{1F916} Qodewk Workspace Chat Telemetry Ledger`);
|
|
17277
|
+
lines.push(`**Repository:** \`${report.projectAlias}\` | **Window:** ${report.windowDescription} | **Total Spend:** \`~$${report.totalCost.toFixed(2)}\``);
|
|
17278
|
+
lines.push("");
|
|
17279
|
+
lines.push("| Chat / Task | Platform | Model | Steps | Tokens | Cost |");
|
|
17280
|
+
lines.push("| :--- | :--- | :--- | :--- | :--- | :--- |");
|
|
17281
|
+
for (const chat of report.chats) {
|
|
17282
|
+
const title = (chat.taskTitle || chat.sessionId).replace(/\|/g, "\\|").trim();
|
|
17283
|
+
const tokensK = `${Math.round((chat.tokens.input + chat.tokens.output) / 1e3)}k`;
|
|
17284
|
+
const cost = chat.mode === "verified" ? `$${chat.cost.toFixed(2)}` : `~$${chat.cost.toFixed(2)}`;
|
|
17285
|
+
lines.push(`| ${title} | \`${chat.platform}\` | \`${chat.model}\` | ${chat.stepsCount} | ${tokensK} | ${cost} |`);
|
|
17286
|
+
}
|
|
17287
|
+
lines.push("");
|
|
17288
|
+
lines.push(`*Total Sessions: ${report.sessionsCount} \xB7 Total Steps: ${report.totalSteps.toLocaleString()}*`);
|
|
17289
|
+
return lines.join("\n");
|
|
17290
|
+
}
|
|
17291
|
+
|
|
17089
17292
|
// src/menu.ts
|
|
17090
17293
|
var SHARE_PAYLOAD_MAX_BYTES = 5e4;
|
|
17091
17294
|
var BANNER_LINES = [
|
|
@@ -17139,6 +17342,12 @@ var MENU_ITEMS = [
|
|
|
17139
17342
|
label: "System Health & Diagnostics",
|
|
17140
17343
|
description: "Audit AI agents, Git hooks, SQLite & pricing registry (doctor)"
|
|
17141
17344
|
},
|
|
17345
|
+
{
|
|
17346
|
+
id: "chats",
|
|
17347
|
+
key: "8",
|
|
17348
|
+
label: "Workspace Chats & Cost Ledger",
|
|
17349
|
+
description: "Inspect all agent conversation sessions and model costs (chats)"
|
|
17350
|
+
},
|
|
17142
17351
|
{
|
|
17143
17352
|
id: "exit",
|
|
17144
17353
|
key: "0",
|
|
@@ -17184,7 +17393,45 @@ var RECEIPT_HORIZON_ITEMS = [
|
|
|
17184
17393
|
description: "Return to previous screen"
|
|
17185
17394
|
}
|
|
17186
17395
|
];
|
|
17187
|
-
|
|
17396
|
+
var SHARE_HORIZON_ITEMS = [
|
|
17397
|
+
{
|
|
17398
|
+
id: "latest",
|
|
17399
|
+
key: "1",
|
|
17400
|
+
label: "Latest Changes (Default)",
|
|
17401
|
+
description: "Publish git working tree or latest commit to cloud"
|
|
17402
|
+
},
|
|
17403
|
+
{
|
|
17404
|
+
id: "today",
|
|
17405
|
+
key: "2",
|
|
17406
|
+
label: "Today's Work Session",
|
|
17407
|
+
description: "Publish commits & agent activity since midnight (--today)"
|
|
17408
|
+
},
|
|
17409
|
+
{
|
|
17410
|
+
id: "yesterday",
|
|
17411
|
+
key: "3",
|
|
17412
|
+
label: "Yesterday's Work",
|
|
17413
|
+
description: "Publish activity from yesterday to now (--since yesterday)"
|
|
17414
|
+
},
|
|
17415
|
+
{
|
|
17416
|
+
id: "week",
|
|
17417
|
+
key: "4",
|
|
17418
|
+
label: "Past 7 Days (Sprint)",
|
|
17419
|
+
description: "Publish weekly sprint telemetry across all agents (--since 7d)"
|
|
17420
|
+
},
|
|
17421
|
+
{
|
|
17422
|
+
id: "custom",
|
|
17423
|
+
key: "5",
|
|
17424
|
+
label: "Custom Duration",
|
|
17425
|
+
description: "Specify hours (e.g. 12h) or days (e.g. 3d, 14d) to publish"
|
|
17426
|
+
},
|
|
17427
|
+
{
|
|
17428
|
+
id: "back",
|
|
17429
|
+
key: "0",
|
|
17430
|
+
label: "Back to Main Menu",
|
|
17431
|
+
description: "Return to previous screen"
|
|
17432
|
+
}
|
|
17433
|
+
];
|
|
17434
|
+
function buildMenuFrame(selectedIndex, items = MENU_ITEMS, title = "Telemetry Control Panel", subtitle = "\u2191\u2193 move \xB7 enter select \xB7 0-8 quick jump \xB7 q quit", options = {}) {
|
|
17188
17435
|
const lines = [];
|
|
17189
17436
|
const push = (line) => lines.push(line);
|
|
17190
17437
|
if (options.showBanner ?? true) {
|
|
@@ -17195,21 +17442,31 @@ function buildMenuFrame(selectedIndex, items = MENU_ITEMS, title = "Telemetry Co
|
|
|
17195
17442
|
}
|
|
17196
17443
|
}
|
|
17197
17444
|
push("");
|
|
17198
|
-
const badge = bg.teal(
|
|
17199
|
-
push(` ${colors.mutedSoft("\u250C")} ${badge} ${
|
|
17445
|
+
const badge = bg.teal(import_picocolors4.default.bold(colors.ink(" qodewk ")));
|
|
17446
|
+
push(` ${colors.mutedSoft("\u250C")} ${badge} ${import_picocolors4.default.dim("v0.11.0")}`);
|
|
17200
17447
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17201
17448
|
if (options.actionContext) {
|
|
17202
|
-
push(` ${colors.teal("\u25C7")} ${
|
|
17449
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors4.default.dim("Action:")} ${import_picocolors4.default.white(options.actionContext)}`);
|
|
17203
17450
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17204
17451
|
} else {
|
|
17205
17452
|
const repo = options.repoContext?.alias || "Qodewk";
|
|
17206
17453
|
const branch = options.repoContext?.branch ? `(${options.repoContext.branch})` : "";
|
|
17207
|
-
push(` ${colors.teal("\u25C7")} ${
|
|
17454
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors4.default.dim("Repository:")} ${import_picocolors4.default.white(repo)} ${import_picocolors4.default.dim(branch)}`);
|
|
17208
17455
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17209
|
-
|
|
17456
|
+
let telemetryLabel = "Multi-Model Rate Cards (Active)";
|
|
17457
|
+
try {
|
|
17458
|
+
const agEnv = discoverAntigravityEnvironment();
|
|
17459
|
+
if (agEnv && agEnv.mode === "observed") {
|
|
17460
|
+
telemetryLabel = "Google Antigravity (Active)";
|
|
17461
|
+
} else if (agEnv) {
|
|
17462
|
+
telemetryLabel = "Google Antigravity Detected";
|
|
17463
|
+
}
|
|
17464
|
+
} catch {
|
|
17465
|
+
}
|
|
17466
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors4.default.dim("Telemetry:")} ${import_picocolors4.default.white(telemetryLabel)}`);
|
|
17210
17467
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17211
17468
|
}
|
|
17212
|
-
push(` ${colors.coral("\u25C6")} ${
|
|
17469
|
+
push(` ${colors.coral("\u25C6")} ${import_picocolors4.default.bold(import_picocolors4.default.white(title))}`);
|
|
17213
17470
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17214
17471
|
const selectedItem = items[selectedIndex] || items[0];
|
|
17215
17472
|
for (let i2 = 0; i2 < items.length; i2++) {
|
|
@@ -17217,44 +17474,44 @@ function buildMenuFrame(selectedIndex, items = MENU_ITEMS, title = "Telemetry Co
|
|
|
17217
17474
|
const isSelected = i2 === selectedIndex;
|
|
17218
17475
|
if (isSelected) {
|
|
17219
17476
|
push(
|
|
17220
|
-
` ${colors.mutedSoft("\u2502")} ${
|
|
17477
|
+
` ${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))}`
|
|
17221
17478
|
);
|
|
17222
17479
|
} else {
|
|
17223
17480
|
push(
|
|
17224
|
-
` ${colors.mutedSoft("\u2502")} ${
|
|
17481
|
+
` ${colors.mutedSoft("\u2502")} ${import_picocolors4.default.dim(item.key)} ${import_picocolors4.default.dim(import_picocolors4.default.white(item.label))}`
|
|
17225
17482
|
);
|
|
17226
17483
|
}
|
|
17227
17484
|
}
|
|
17228
17485
|
const divider = colors.mutedSoft("\u2500".repeat(58));
|
|
17229
17486
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17230
17487
|
push(` ${colors.mutedSoft("\u2502")} ${divider}`);
|
|
17231
|
-
push(` ${colors.mutedSoft("\u2502")} ${
|
|
17488
|
+
push(` ${colors.mutedSoft("\u2502")} ${import_picocolors4.default.bold(import_picocolors4.default.dim("Description"))}`);
|
|
17232
17489
|
push(` ${colors.mutedSoft("\u2502")} ${colors.amber(selectedItem.description)}`);
|
|
17233
17490
|
push(` ${colors.mutedSoft("\u2502")} ${divider}`);
|
|
17234
17491
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17235
|
-
push(` ${colors.mutedSoft("\u2502")} ${
|
|
17236
|
-
push(` ${colors.mutedSoft("\u2502")} ${colors.green("[\u2713]")} ${
|
|
17492
|
+
push(` ${colors.mutedSoft("\u2502")} ${import_picocolors4.default.dim(subtitle)}`);
|
|
17493
|
+
push(` ${colors.mutedSoft("\u2502")} ${colors.green("[\u2713]")} ${import_picocolors4.default.dim("Source code was never uploaded to Qodewk")}`);
|
|
17237
17494
|
push(` ${colors.mutedSoft("\u2514")}`);
|
|
17238
17495
|
push("");
|
|
17239
17496
|
return lines.join("\n");
|
|
17240
17497
|
}
|
|
17241
17498
|
function askLine(promptText) {
|
|
17242
|
-
return new Promise((
|
|
17499
|
+
return new Promise((resolve7) => {
|
|
17243
17500
|
const rl = readline.createInterface({
|
|
17244
17501
|
input: process.stdin,
|
|
17245
17502
|
output: process.stdout
|
|
17246
17503
|
});
|
|
17247
17504
|
rl.question(promptText, (answer) => {
|
|
17248
17505
|
rl.close();
|
|
17249
|
-
|
|
17506
|
+
resolve7(answer.trim());
|
|
17250
17507
|
});
|
|
17251
17508
|
});
|
|
17252
17509
|
}
|
|
17253
17510
|
function waitForKeyToReturn() {
|
|
17254
|
-
return new Promise((
|
|
17255
|
-
console.log(
|
|
17511
|
+
return new Promise((resolve7) => {
|
|
17512
|
+
console.log(import_picocolors4.default.dim("\n Press any key or Enter to return to menu..."));
|
|
17256
17513
|
if (!process.stdin.isTTY) {
|
|
17257
|
-
|
|
17514
|
+
resolve7();
|
|
17258
17515
|
return;
|
|
17259
17516
|
}
|
|
17260
17517
|
const wasRaw = process.stdin.isRaw;
|
|
@@ -17263,11 +17520,90 @@ function waitForKeyToReturn() {
|
|
|
17263
17520
|
const onKey = () => {
|
|
17264
17521
|
process.stdin.removeListener("data", onKey);
|
|
17265
17522
|
if (wasRaw !== void 0) process.stdin.setRawMode(wasRaw);
|
|
17266
|
-
|
|
17523
|
+
resolve7();
|
|
17524
|
+
};
|
|
17525
|
+
process.stdin.once("data", onKey);
|
|
17526
|
+
});
|
|
17527
|
+
}
|
|
17528
|
+
function waitForKeyOrAction(promptText) {
|
|
17529
|
+
return new Promise((resolve7) => {
|
|
17530
|
+
console.log(promptText);
|
|
17531
|
+
if (!process.stdin.isTTY) {
|
|
17532
|
+
resolve7("");
|
|
17533
|
+
return;
|
|
17534
|
+
}
|
|
17535
|
+
const wasRaw = process.stdin.isRaw;
|
|
17536
|
+
process.stdin.setRawMode(true);
|
|
17537
|
+
process.stdin.resume();
|
|
17538
|
+
const onKey = (data) => {
|
|
17539
|
+
process.stdin.removeListener("data", onKey);
|
|
17540
|
+
if (wasRaw !== void 0) process.stdin.setRawMode(wasRaw);
|
|
17541
|
+
const str = data.toString();
|
|
17542
|
+
resolve7(str);
|
|
17267
17543
|
};
|
|
17268
17544
|
process.stdin.once("data", onKey);
|
|
17269
17545
|
});
|
|
17270
17546
|
}
|
|
17547
|
+
async function publishReceiptToCloud(receipt) {
|
|
17548
|
+
if (process.env.QODEWK_TELEMETRY === "off") {
|
|
17549
|
+
console.log(import_picocolors4.default.yellow("\n Cloud publishing is disabled by QODEWK_TELEMETRY=off."));
|
|
17550
|
+
return null;
|
|
17551
|
+
}
|
|
17552
|
+
const sanitized = sanitizeReceiptForShare(receipt);
|
|
17553
|
+
let body = JSON.stringify(sanitized);
|
|
17554
|
+
if (Buffer.byteLength(body, "utf-8") > SHARE_PAYLOAD_MAX_BYTES && sanitized.ai.sessions) {
|
|
17555
|
+
const trimmed2 = {
|
|
17556
|
+
...sanitized,
|
|
17557
|
+
ai: { ...sanitized.ai, sessions: void 0 }
|
|
17558
|
+
};
|
|
17559
|
+
body = JSON.stringify(trimmed2);
|
|
17560
|
+
}
|
|
17561
|
+
if (Buffer.byteLength(body, "utf-8") > SHARE_PAYLOAD_MAX_BYTES) {
|
|
17562
|
+
console.error(import_picocolors4.default.red(" Sanitized receipt still exceeds the 50 KB cloud payload limit."));
|
|
17563
|
+
return null;
|
|
17564
|
+
}
|
|
17565
|
+
const endpoint = resolveApiUrl();
|
|
17566
|
+
console.log(import_picocolors4.default.dim(`
|
|
17567
|
+
[\xB7] Publishing receipt to ${endpoint}...`));
|
|
17568
|
+
try {
|
|
17569
|
+
const response = await fetch(endpoint, {
|
|
17570
|
+
method: "POST",
|
|
17571
|
+
headers: {
|
|
17572
|
+
"Content-Type": "application/json",
|
|
17573
|
+
"Content-Length": String(Buffer.byteLength(body, "utf-8"))
|
|
17574
|
+
},
|
|
17575
|
+
body
|
|
17576
|
+
});
|
|
17577
|
+
if (!response.ok) {
|
|
17578
|
+
const errText = await response.text().catch(() => "");
|
|
17579
|
+
if (response.status === 503) {
|
|
17580
|
+
console.log(import_picocolors4.default.yellow("\n Notice: Remote server requires durable storage (Supabase or PostgreSQL) in production"));
|
|
17581
|
+
console.log(import_picocolors4.default.dim(" to protect receipts from serverless cold-start data loss."));
|
|
17582
|
+
console.log(import_picocolors4.default.dim(` Endpoint: ${endpoint}`));
|
|
17583
|
+
console.log(colors.green("\n [\u2713] Your receipt is safely saved locally in: ~/.qodewk/state.db"));
|
|
17584
|
+
console.log(import_picocolors4.default.dim(" You can also save it as a local Git note: qodewk --notes\n"));
|
|
17585
|
+
return null;
|
|
17586
|
+
}
|
|
17587
|
+
throw new Error(`API responded with ${response.status}: ${errText.slice(0, 100)}`);
|
|
17588
|
+
}
|
|
17589
|
+
const data = await response.json();
|
|
17590
|
+
const db = new LocalStateDB();
|
|
17591
|
+
db.saveReceipt(sanitized, data.claimToken);
|
|
17592
|
+
db.close();
|
|
17593
|
+
console.log("");
|
|
17594
|
+
console.log(colors.green(" [\u2713] Published successfully."));
|
|
17595
|
+
console.log(` ${import_picocolors4.default.dim("Public URL:")} ${import_picocolors4.default.underline(import_picocolors4.default.cyan(data.url))}`);
|
|
17596
|
+
console.log(` ${import_picocolors4.default.bold(colors.amber("Claim token:"))} ${colors.amber(data.claimToken)}`);
|
|
17597
|
+
console.log(import_picocolors4.default.dim(" (Saved to ~/.qodewk/state.db for future authorship proofs)\n"));
|
|
17598
|
+
await renderTerminalReceipt(sanitized, data.url);
|
|
17599
|
+
return data;
|
|
17600
|
+
} catch (err) {
|
|
17601
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
17602
|
+
console.error(import_picocolors4.default.red(`
|
|
17603
|
+
Share failed: ${message}`));
|
|
17604
|
+
return null;
|
|
17605
|
+
}
|
|
17606
|
+
}
|
|
17271
17607
|
var cachedRepoContext = null;
|
|
17272
17608
|
async function getRepoContext() {
|
|
17273
17609
|
if (cachedRepoContext) return cachedRepoContext;
|
|
@@ -17281,7 +17617,7 @@ async function getRepoContext() {
|
|
|
17281
17617
|
}
|
|
17282
17618
|
const branchSummary = await git.branch();
|
|
17283
17619
|
const branch = branchSummary.current || "HEAD";
|
|
17284
|
-
const alias =
|
|
17620
|
+
const alias = path16.basename(process.cwd());
|
|
17285
17621
|
cachedRepoContext = { alias, branch };
|
|
17286
17622
|
return cachedRepoContext;
|
|
17287
17623
|
} catch {
|
|
@@ -17292,7 +17628,7 @@ async function getRepoContext() {
|
|
|
17292
17628
|
async function runInteractiveMenu() {
|
|
17293
17629
|
if (!process.stdin.isTTY) {
|
|
17294
17630
|
console.log(buildMenuFrame(0));
|
|
17295
|
-
console.log(
|
|
17631
|
+
console.log(import_picocolors4.default.yellow("Interactive menu requires a TTY terminal. Use `qodewk --help` for commands."));
|
|
17296
17632
|
return;
|
|
17297
17633
|
}
|
|
17298
17634
|
const repoContext = await getRepoContext();
|
|
@@ -17300,12 +17636,16 @@ async function runInteractiveMenu() {
|
|
|
17300
17636
|
let selectedIndex = 0;
|
|
17301
17637
|
let active = true;
|
|
17302
17638
|
let lastRenderedLinesCount = 0;
|
|
17303
|
-
const getActiveItems = () =>
|
|
17639
|
+
const getActiveItems = () => {
|
|
17640
|
+
if (currentScreen === "receipt_horizon") return RECEIPT_HORIZON_ITEMS;
|
|
17641
|
+
if (currentScreen === "share_horizon") return SHARE_HORIZON_ITEMS;
|
|
17642
|
+
return MENU_ITEMS;
|
|
17643
|
+
};
|
|
17304
17644
|
const render = () => {
|
|
17305
17645
|
const items = getActiveItems();
|
|
17306
|
-
const title = currentScreen === "main" ? "Telemetry Control Panel" : "Generate Local Receipt";
|
|
17646
|
+
const title = currentScreen === "main" ? "Telemetry Control Panel" : currentScreen === "receipt_horizon" ? "Generate Local Receipt" : "Publish Receipt to Cloud";
|
|
17307
17647
|
const subtitle = currentScreen === "main" ? "\u2191\u2193 move \xB7 enter select \xB7 0-7 quick jump \xB7 q quit" : "\u2191\u2193 move \xB7 enter select \xB7 0-5 quick jump \xB7 esc / 0 back";
|
|
17308
|
-
const actionContext = currentScreen === "receipt_horizon" ? "Generate Local Receipt" : void 0;
|
|
17648
|
+
const actionContext = currentScreen === "receipt_horizon" ? "Generate Local Receipt" : currentScreen === "share_horizon" ? "Publish Receipt to Cloud" : void 0;
|
|
17309
17649
|
const showBanner = currentScreen === "main";
|
|
17310
17650
|
const frame = buildMenuFrame(selectedIndex, items, title, subtitle, {
|
|
17311
17651
|
repoContext,
|
|
@@ -17345,25 +17685,70 @@ async function runInteractiveMenu() {
|
|
|
17345
17685
|
since = "7d";
|
|
17346
17686
|
label = "past 7 days weekly sprint (--since 7d)";
|
|
17347
17687
|
} else if (item.id === "custom") {
|
|
17348
|
-
console.log(
|
|
17349
|
-
console.log(
|
|
17688
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white(" Custom Telemetry Horizon")));
|
|
17689
|
+
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"));
|
|
17350
17690
|
const input = await askLine(" \u203A Enter duration or date (e.g. 12h, 3d, 2026-10-01): ");
|
|
17351
17691
|
if (input) {
|
|
17352
17692
|
since = input;
|
|
17353
17693
|
label = `custom range: ${input}`;
|
|
17354
17694
|
}
|
|
17355
17695
|
}
|
|
17356
|
-
console.log(
|
|
17696
|
+
console.log(import_picocolors4.default.dim(` [\xB7] Generating local receipt for ${label}...`));
|
|
17357
17697
|
try {
|
|
17358
17698
|
const receipt = await generateReceipt({ since, isPublic: false });
|
|
17359
17699
|
const db = new LocalStateDB();
|
|
17360
17700
|
db.saveReceipt(receipt);
|
|
17361
17701
|
db.close();
|
|
17362
17702
|
await renderTerminalReceipt(receipt);
|
|
17703
|
+
console.log("");
|
|
17704
|
+
const actionKey = await waitForKeyOrAction(
|
|
17705
|
+
` ${colors.coral("[s]")} ${import_picocolors4.default.white("Publish this receipt to cloud")} \xB7 ${import_picocolors4.default.dim("[any other key] Return to menu")}`
|
|
17706
|
+
);
|
|
17707
|
+
if (actionKey.trim().toLowerCase() === "s") {
|
|
17708
|
+
await publishReceiptToCloud(receipt);
|
|
17709
|
+
await waitForKeyToReturn();
|
|
17710
|
+
}
|
|
17363
17711
|
} catch (err) {
|
|
17364
17712
|
const message = err instanceof Error ? err.message : String(err);
|
|
17365
|
-
console.error(
|
|
17713
|
+
console.error(import_picocolors4.default.red(`
|
|
17366
17714
|
Failed to generate receipt: ${message}`));
|
|
17715
|
+
await waitForKeyToReturn();
|
|
17716
|
+
}
|
|
17717
|
+
currentScreen = "main";
|
|
17718
|
+
selectedIndex = 0;
|
|
17719
|
+
};
|
|
17720
|
+
const executeShareHorizon = async (item) => {
|
|
17721
|
+
cleanup();
|
|
17722
|
+
console.log("");
|
|
17723
|
+
lastRenderedLinesCount = 0;
|
|
17724
|
+
let since = void 0;
|
|
17725
|
+
let label = "latest git diff";
|
|
17726
|
+
if (item.id === "today") {
|
|
17727
|
+
since = "today";
|
|
17728
|
+
label = "today's work session (--today)";
|
|
17729
|
+
} else if (item.id === "yesterday") {
|
|
17730
|
+
since = "yesterday";
|
|
17731
|
+
label = "yesterday's work (--since yesterday)";
|
|
17732
|
+
} else if (item.id === "week") {
|
|
17733
|
+
since = "7d";
|
|
17734
|
+
label = "past 7 days weekly sprint (--since 7d)";
|
|
17735
|
+
} else if (item.id === "custom") {
|
|
17736
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white(" Custom Telemetry Horizon for Cloud Publish")));
|
|
17737
|
+
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"));
|
|
17738
|
+
const input = await askLine(" \u203A Enter duration or date (e.g. 12h, 3d, 2026-10-01): ");
|
|
17739
|
+
if (input) {
|
|
17740
|
+
since = input;
|
|
17741
|
+
label = `custom range: ${input}`;
|
|
17742
|
+
}
|
|
17743
|
+
}
|
|
17744
|
+
console.log(import_picocolors4.default.dim(` [\xB7] Generating and publishing receipt for ${label}...`));
|
|
17745
|
+
try {
|
|
17746
|
+
const receipt = await generateReceipt({ since, isPublic: false });
|
|
17747
|
+
await publishReceiptToCloud(receipt);
|
|
17748
|
+
} catch (err) {
|
|
17749
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
17750
|
+
console.error(import_picocolors4.default.red(`
|
|
17751
|
+
Share failed: ${message}`));
|
|
17367
17752
|
}
|
|
17368
17753
|
await waitForKeyToReturn();
|
|
17369
17754
|
currentScreen = "main";
|
|
@@ -17376,8 +17761,8 @@ async function runInteractiveMenu() {
|
|
|
17376
17761
|
const selectedItem = MENU_ITEMS[selectedIndex];
|
|
17377
17762
|
switch (selectedItem.id) {
|
|
17378
17763
|
case "audit": {
|
|
17379
|
-
console.log(
|
|
17380
|
-
console.log(
|
|
17764
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white("\n Audit Branch or Revision Diff")));
|
|
17765
|
+
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"));
|
|
17381
17766
|
let defaultBase = "origin/main";
|
|
17382
17767
|
try {
|
|
17383
17768
|
defaultBase = await detectDefaultBaseBranch(process.cwd());
|
|
@@ -17389,7 +17774,7 @@ async function runInteractiveMenu() {
|
|
|
17389
17774
|
const head = await askLine(
|
|
17390
17775
|
` \u203A Head git ref or commit SHA [default: HEAD]: `
|
|
17391
17776
|
);
|
|
17392
|
-
console.log(
|
|
17777
|
+
console.log(import_picocolors4.default.dim("\n [\xB7] Auditing git revision range..."));
|
|
17393
17778
|
try {
|
|
17394
17779
|
const receipt = await generateReceipt({
|
|
17395
17780
|
baseSha: base || defaultBase,
|
|
@@ -17402,71 +17787,15 @@ async function runInteractiveMenu() {
|
|
|
17402
17787
|
await renderTerminalReceipt(receipt);
|
|
17403
17788
|
} catch (err) {
|
|
17404
17789
|
const message = err instanceof Error ? err.message : String(err);
|
|
17405
|
-
console.error(
|
|
17790
|
+
console.error(import_picocolors4.default.red(`
|
|
17406
17791
|
Audit failed: ${message}`));
|
|
17407
17792
|
}
|
|
17408
17793
|
await waitForKeyToReturn();
|
|
17409
17794
|
break;
|
|
17410
17795
|
}
|
|
17411
17796
|
case "share": {
|
|
17412
|
-
|
|
17413
|
-
|
|
17414
|
-
const receipt = await generateReceipt({ isPublic: false });
|
|
17415
|
-
if (process.env.QODEWK_TELEMETRY === "off") {
|
|
17416
|
-
console.log(import_picocolors3.default.yellow("\n Cloud publishing is disabled by QODEWK_TELEMETRY=off."));
|
|
17417
|
-
await renderTerminalReceipt(receipt);
|
|
17418
|
-
await waitForKeyToReturn();
|
|
17419
|
-
break;
|
|
17420
|
-
}
|
|
17421
|
-
const sanitized = sanitizeReceiptForShare(receipt);
|
|
17422
|
-
let body = JSON.stringify(sanitized);
|
|
17423
|
-
if (Buffer.byteLength(body, "utf-8") > SHARE_PAYLOAD_MAX_BYTES && sanitized.ai.sessions) {
|
|
17424
|
-
const trimmed2 = {
|
|
17425
|
-
...sanitized,
|
|
17426
|
-
ai: { ...sanitized.ai, sessions: void 0 }
|
|
17427
|
-
};
|
|
17428
|
-
body = JSON.stringify(trimmed2);
|
|
17429
|
-
}
|
|
17430
|
-
const endpoint = resolveApiUrl();
|
|
17431
|
-
console.log(import_picocolors3.default.dim(` [\xB7] Uploading metadata to ${endpoint}...`));
|
|
17432
|
-
const response = await fetch(endpoint, {
|
|
17433
|
-
method: "POST",
|
|
17434
|
-
headers: {
|
|
17435
|
-
"Content-Type": "application/json",
|
|
17436
|
-
"Content-Length": String(Buffer.byteLength(body, "utf-8"))
|
|
17437
|
-
},
|
|
17438
|
-
body
|
|
17439
|
-
});
|
|
17440
|
-
if (!response.ok) {
|
|
17441
|
-
const errText = await response.text().catch(() => "");
|
|
17442
|
-
if (response.status === 503) {
|
|
17443
|
-
console.log(import_picocolors3.default.yellow("\n Notice: Remote server requires durable storage (Supabase or PostgreSQL) in production"));
|
|
17444
|
-
console.log(import_picocolors3.default.dim(" to protect receipts from serverless cold-start data loss."));
|
|
17445
|
-
console.log(import_picocolors3.default.dim(` Endpoint: ${endpoint}`));
|
|
17446
|
-
console.log(colors.green("\n [\u2713] Your receipt is safely saved locally in: ~/.qodewk/state.db"));
|
|
17447
|
-
console.log(import_picocolors3.default.dim(" You can also save it as a local Git note: qodewk --notes\n"));
|
|
17448
|
-
await renderTerminalReceipt(sanitized);
|
|
17449
|
-
await waitForKeyToReturn();
|
|
17450
|
-
break;
|
|
17451
|
-
}
|
|
17452
|
-
throw new Error(`API responded with ${response.status}${errText ? `: ${errText.slice(0, 100)}` : ""}`);
|
|
17453
|
-
}
|
|
17454
|
-
const data = await response.json();
|
|
17455
|
-
const db = new LocalStateDB();
|
|
17456
|
-
db.saveReceipt(sanitized, data.claimToken);
|
|
17457
|
-
db.close();
|
|
17458
|
-
console.log("");
|
|
17459
|
-
console.log(colors.green(" [\u2713] Published successfully."));
|
|
17460
|
-
console.log(` ${import_picocolors3.default.dim("Public URL:")} ${import_picocolors3.default.underline(import_picocolors3.default.cyan(data.url))}`);
|
|
17461
|
-
console.log(` ${import_picocolors3.default.bold(colors.amber("Claim token:"))} ${colors.amber(data.claimToken)}`);
|
|
17462
|
-
console.log(import_picocolors3.default.dim(" (Saved to ~/.qodewk/state.db for future authorship proofs)\n"));
|
|
17463
|
-
await renderTerminalReceipt(sanitized, data.url);
|
|
17464
|
-
} catch (err) {
|
|
17465
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
17466
|
-
console.error(import_picocolors3.default.red(`
|
|
17467
|
-
Share failed: ${message}`));
|
|
17468
|
-
}
|
|
17469
|
-
await waitForKeyToReturn();
|
|
17797
|
+
currentScreen = "share_horizon";
|
|
17798
|
+
selectedIndex = 0;
|
|
17470
17799
|
break;
|
|
17471
17800
|
}
|
|
17472
17801
|
case "hooks": {
|
|
@@ -17485,10 +17814,14 @@ async function runInteractiveMenu() {
|
|
|
17485
17814
|
await runDoctorDiagnosticsAction();
|
|
17486
17815
|
break;
|
|
17487
17816
|
}
|
|
17817
|
+
case "chats": {
|
|
17818
|
+
await showChatsAction();
|
|
17819
|
+
break;
|
|
17820
|
+
}
|
|
17488
17821
|
case "exit": {
|
|
17489
17822
|
active = false;
|
|
17490
17823
|
cleanup();
|
|
17491
|
-
console.log(
|
|
17824
|
+
console.log(import_picocolors4.default.dim(" Exited Qodewk.\n"));
|
|
17492
17825
|
process.exit(0);
|
|
17493
17826
|
return;
|
|
17494
17827
|
}
|
|
@@ -17497,19 +17830,19 @@ async function runInteractiveMenu() {
|
|
|
17497
17830
|
const manageHooksSubmenu = async () => {
|
|
17498
17831
|
const hooksDir = resolveGitHooksDir();
|
|
17499
17832
|
const status = checkHookStatus(hooksDir);
|
|
17500
|
-
console.log(
|
|
17501
|
-
console.log(
|
|
17833
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white("\n Qodewk Git Hooks Management")));
|
|
17834
|
+
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"));
|
|
17502
17835
|
if (!status.isGit) {
|
|
17503
|
-
console.log(
|
|
17836
|
+
console.log(import_picocolors4.default.yellow(" Not inside a Git repository. Hooks cannot be configured."));
|
|
17504
17837
|
await waitForKeyToReturn();
|
|
17505
17838
|
return;
|
|
17506
17839
|
}
|
|
17507
|
-
console.log(` Hooks directory: ${
|
|
17840
|
+
console.log(` Hooks directory: ${import_picocolors4.default.dim(status.hooksDir || "None")}`);
|
|
17508
17841
|
console.log(
|
|
17509
|
-
` post-commit: ${status.postCommitInstalled ? colors.green("[\u2713 Installed]") :
|
|
17842
|
+
` post-commit: ${status.postCommitInstalled ? colors.green("[\u2713 Installed]") : import_picocolors4.default.dim("[\xB7 Not installed]")}`
|
|
17510
17843
|
);
|
|
17511
17844
|
console.log(
|
|
17512
|
-
` post-rewrite: ${status.postRewriteInstalled ? colors.green("[\u2713 Installed]") :
|
|
17845
|
+
` post-rewrite: ${status.postRewriteInstalled ? colors.green("[\u2713 Installed]") : import_picocolors4.default.dim("[\xB7 Not installed]")}`
|
|
17513
17846
|
);
|
|
17514
17847
|
console.log("");
|
|
17515
17848
|
console.log(" [1] Install non-blocking hooks (< 5ms background recorder)");
|
|
@@ -17522,7 +17855,7 @@ async function runInteractiveMenu() {
|
|
|
17522
17855
|
if (status.hooksDir) {
|
|
17523
17856
|
const targets = ["post-commit", "post-rewrite"];
|
|
17524
17857
|
for (const t2 of targets) {
|
|
17525
|
-
installHookFile(
|
|
17858
|
+
installHookFile(path16.join(status.hooksDir, t2));
|
|
17526
17859
|
}
|
|
17527
17860
|
console.log(colors.green("\n [\u2713] Non-blocking hooks installed successfully."));
|
|
17528
17861
|
}
|
|
@@ -17530,7 +17863,7 @@ async function runInteractiveMenu() {
|
|
|
17530
17863
|
if (status.hooksDir) {
|
|
17531
17864
|
const targets = ["post-commit", "post-rewrite"];
|
|
17532
17865
|
for (const t2 of targets) {
|
|
17533
|
-
uninstallHookFile(
|
|
17866
|
+
uninstallHookFile(path16.join(status.hooksDir, t2));
|
|
17534
17867
|
}
|
|
17535
17868
|
console.log(colors.green("\n [\u2713] Qodewk hooks removed."));
|
|
17536
17869
|
}
|
|
@@ -17542,8 +17875,8 @@ async function runInteractiveMenu() {
|
|
|
17542
17875
|
await waitForKeyToReturn();
|
|
17543
17876
|
};
|
|
17544
17877
|
const manageGitNotesSubmenu = async () => {
|
|
17545
|
-
console.log(
|
|
17546
|
-
console.log(
|
|
17878
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white("\n Qodewk Git Notes Management (refs/notes/qodewk)")));
|
|
17879
|
+
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"));
|
|
17547
17880
|
console.log(" [1] List commits with attached Qodewk notes");
|
|
17548
17881
|
console.log(" [2] Show receipt note on a commit (default: HEAD)");
|
|
17549
17882
|
console.log(" [3] Attach receipt note to a Git commit (default: HEAD)");
|
|
@@ -17554,17 +17887,17 @@ async function runInteractiveMenu() {
|
|
|
17554
17887
|
try {
|
|
17555
17888
|
const shas = await listGitReceiptNotes();
|
|
17556
17889
|
if (shas.length === 0) {
|
|
17557
|
-
console.log(
|
|
17890
|
+
console.log(import_picocolors4.default.yellow("\n No Qodewk Git notes found in repository."));
|
|
17558
17891
|
} else {
|
|
17559
|
-
console.log(
|
|
17892
|
+
console.log(import_picocolors4.default.bold(`
|
|
17560
17893
|
Found ${shas.length} commit note(s) in refs/notes/qodewk:`));
|
|
17561
17894
|
for (const sha of shas) {
|
|
17562
|
-
console.log(` ${
|
|
17895
|
+
console.log(` ${import_picocolors4.default.cyan(sha.slice(0, 10))} ${import_picocolors4.default.dim(sha)}`);
|
|
17563
17896
|
}
|
|
17564
17897
|
}
|
|
17565
17898
|
} catch (err) {
|
|
17566
17899
|
const message = err instanceof Error ? err.message : String(err);
|
|
17567
|
-
console.error(
|
|
17900
|
+
console.error(import_picocolors4.default.red(`
|
|
17568
17901
|
Error listing Git notes: ${message}`));
|
|
17569
17902
|
}
|
|
17570
17903
|
} else if (choice === "2") {
|
|
@@ -17572,20 +17905,20 @@ async function runInteractiveMenu() {
|
|
|
17572
17905
|
try {
|
|
17573
17906
|
const receipt = await readGitReceiptNote(commit);
|
|
17574
17907
|
if (!receipt) {
|
|
17575
|
-
console.log(
|
|
17908
|
+
console.log(import_picocolors4.default.yellow(`
|
|
17576
17909
|
No Qodewk receipt note found on commit '${commit}'.`));
|
|
17577
17910
|
} else {
|
|
17578
17911
|
await renderTerminalReceipt(receipt);
|
|
17579
17912
|
}
|
|
17580
17913
|
} catch (err) {
|
|
17581
17914
|
const message = err instanceof Error ? err.message : String(err);
|
|
17582
|
-
console.error(
|
|
17915
|
+
console.error(import_picocolors4.default.red(`
|
|
17583
17916
|
Error reading Git note: ${message}`));
|
|
17584
17917
|
}
|
|
17585
17918
|
} else if (choice === "3") {
|
|
17586
17919
|
const commit = await askLine(" \u203A Commit SHA to attach note [default: HEAD]: ") || "HEAD";
|
|
17587
17920
|
try {
|
|
17588
|
-
console.log(
|
|
17921
|
+
console.log(import_picocolors4.default.dim(`
|
|
17589
17922
|
[\xB7] Generating receipt for ${commit}...`));
|
|
17590
17923
|
const receipt = await generateReceipt({ headSha: commit });
|
|
17591
17924
|
await writeGitReceiptNote(receipt.repository.headSha, receipt);
|
|
@@ -17595,30 +17928,30 @@ async function runInteractiveMenu() {
|
|
|
17595
17928
|
);
|
|
17596
17929
|
} catch (err) {
|
|
17597
17930
|
const message = err instanceof Error ? err.message : String(err);
|
|
17598
|
-
console.error(
|
|
17931
|
+
console.error(import_picocolors4.default.red(`
|
|
17599
17932
|
Error writing Git note: ${message}`));
|
|
17600
17933
|
}
|
|
17601
17934
|
}
|
|
17602
17935
|
await waitForKeyToReturn();
|
|
17603
17936
|
};
|
|
17604
17937
|
const showStorageStatus = async () => {
|
|
17605
|
-
console.log(
|
|
17606
|
-
console.log(
|
|
17938
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white("\n Qodewk Local Database & Storage Status")));
|
|
17939
|
+
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"));
|
|
17607
17940
|
try {
|
|
17608
17941
|
const db = new LocalStateDB();
|
|
17609
17942
|
const stats = db.getStats();
|
|
17610
17943
|
const recent = db.getRecentReceipts(5);
|
|
17611
17944
|
db.close();
|
|
17612
|
-
console.log(` Database path: ${
|
|
17613
|
-
console.log(` Total saved receipts: ${
|
|
17614
|
-
console.log(` Total agent footprints: ${
|
|
17945
|
+
console.log(` Database path: ${import_picocolors4.default.dim("~/.qodewk/state.db")}`);
|
|
17946
|
+
console.log(` Total saved receipts: ${import_picocolors4.default.bold(import_picocolors4.default.white(String(stats.totalReceipts)))}`);
|
|
17947
|
+
console.log(` Total agent footprints: ${import_picocolors4.default.bold(import_picocolors4.default.white(String(stats.totalFootprints)))}`);
|
|
17615
17948
|
console.log("");
|
|
17616
17949
|
if (recent.length === 0) {
|
|
17617
|
-
console.log(
|
|
17950
|
+
console.log(import_picocolors4.default.dim(" No stored receipts yet. Run 'Generate Local Receipt' to record your first."));
|
|
17618
17951
|
} else {
|
|
17619
|
-
console.log(
|
|
17620
|
-
console.log(
|
|
17621
|
-
console.log(
|
|
17952
|
+
console.log(import_picocolors4.default.dim(" Recent Receipts:"));
|
|
17953
|
+
console.log(import_picocolors4.default.dim(" " + "ID".padEnd(26) + "DATE".padEnd(12) + "BRANCH".padEnd(18) + "COST"));
|
|
17954
|
+
console.log(import_picocolors4.default.dim(" " + "\u2500".repeat(60)));
|
|
17622
17955
|
for (const item of recent) {
|
|
17623
17956
|
const id = item.receipt.receipt.id.slice(0, 24).padEnd(26);
|
|
17624
17957
|
const date = item.receipt.receipt.createdAt.slice(0, 10).padEnd(12);
|
|
@@ -17628,23 +17961,52 @@ async function runInteractiveMenu() {
|
|
|
17628
17961
|
}
|
|
17629
17962
|
}
|
|
17630
17963
|
console.log("");
|
|
17631
|
-
console.log(` ${colors.green("[\u2713]")} ${
|
|
17964
|
+
console.log(` ${colors.green("[\u2713]")} ${import_picocolors4.default.dim("Privacy guarantee: raw source code is never stored in SQLite")}`);
|
|
17965
|
+
if (recent.length > 0) {
|
|
17966
|
+
console.log("");
|
|
17967
|
+
const ans = await askLine(" \u203A Enter receipt ID prefix to publish to cloud [Enter to return]: ");
|
|
17968
|
+
if (ans) {
|
|
17969
|
+
const matched = recent.find((r2) => r2.receipt.receipt.id.toLowerCase().startsWith(ans.toLowerCase()));
|
|
17970
|
+
if (matched) {
|
|
17971
|
+
await publishReceiptToCloud(matched.receipt);
|
|
17972
|
+
await waitForKeyToReturn();
|
|
17973
|
+
return;
|
|
17974
|
+
} else {
|
|
17975
|
+
console.log(import_picocolors4.default.yellow(` No stored receipt matching '${ans}' found.`));
|
|
17976
|
+
}
|
|
17977
|
+
}
|
|
17978
|
+
}
|
|
17632
17979
|
} catch (err) {
|
|
17633
17980
|
const message = err instanceof Error ? err.message : String(err);
|
|
17634
|
-
console.error(
|
|
17981
|
+
console.error(import_picocolors4.default.red(` Failed to inspect storage: ${message}`));
|
|
17635
17982
|
}
|
|
17636
17983
|
await waitForKeyToReturn();
|
|
17637
17984
|
};
|
|
17638
17985
|
const runDoctorDiagnosticsAction = async () => {
|
|
17639
|
-
console.log(
|
|
17640
|
-
console.log(
|
|
17641
|
-
console.log(
|
|
17986
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white("\n Qodewk System Health & Diagnostics (Doctor)")));
|
|
17987
|
+
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"));
|
|
17988
|
+
console.log(import_picocolors4.default.dim(" [\xB7] Running diagnostic audit across agents, hooks, storage, and pricing...\n"));
|
|
17642
17989
|
try {
|
|
17643
17990
|
const report = await runDiagnostics();
|
|
17644
17991
|
console.log(formatDoctorReport(report));
|
|
17645
17992
|
} catch (err) {
|
|
17646
17993
|
const message = err instanceof Error ? err.message : String(err);
|
|
17647
|
-
console.error(
|
|
17994
|
+
console.error(import_picocolors4.default.red(` Diagnostic check failed: ${message}`));
|
|
17995
|
+
}
|
|
17996
|
+
await waitForKeyToReturn();
|
|
17997
|
+
};
|
|
17998
|
+
const showChatsAction = async () => {
|
|
17999
|
+
console.log(import_picocolors4.default.bold(import_picocolors4.default.white("\n Qodewk Workspace Chat Telemetry & Cost Ledger")));
|
|
18000
|
+
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"));
|
|
18001
|
+
console.log(import_picocolors4.default.dim(" [\xB7] Scanning local IDE transcripts (Antigravity, Cursor, Claude, Windsurf, Cline)...\n"));
|
|
18002
|
+
try {
|
|
18003
|
+
const report = await listProjectChats({
|
|
18004
|
+
repoPath: process.cwd()
|
|
18005
|
+
});
|
|
18006
|
+
console.log(buildTerminalChatLedger(report));
|
|
18007
|
+
} catch (err) {
|
|
18008
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
18009
|
+
console.error(import_picocolors4.default.red(` Failed to inspect workspace chats: ${message}`));
|
|
17648
18010
|
}
|
|
17649
18011
|
await waitForKeyToReturn();
|
|
17650
18012
|
};
|
|
@@ -17669,7 +18031,7 @@ async function runInteractiveMenu() {
|
|
|
17669
18031
|
return;
|
|
17670
18032
|
}
|
|
17671
18033
|
cleanup();
|
|
17672
|
-
console.log(
|
|
18034
|
+
console.log(import_picocolors4.default.dim("\n Exited Qodewk.\n"));
|
|
17673
18035
|
process.exit(0);
|
|
17674
18036
|
}
|
|
17675
18037
|
if (key.name === "up" || key.name === "k") {
|
|
@@ -17682,7 +18044,9 @@ async function runInteractiveMenu() {
|
|
|
17682
18044
|
render();
|
|
17683
18045
|
return;
|
|
17684
18046
|
}
|
|
17685
|
-
const itemByKey = items.findIndex(
|
|
18047
|
+
const itemByKey = items.findIndex(
|
|
18048
|
+
(item) => item.key === key.name || item.key === _str || _str && _str.toLowerCase() === "c" && item.id === "chats"
|
|
18049
|
+
);
|
|
17686
18050
|
if (itemByKey !== -1) {
|
|
17687
18051
|
selectedIndex = itemByKey;
|
|
17688
18052
|
render();
|
|
@@ -17695,8 +18059,14 @@ async function runInteractiveMenu() {
|
|
|
17695
18059
|
if (active) startLoop();
|
|
17696
18060
|
return;
|
|
17697
18061
|
}
|
|
18062
|
+
if (selected.id === "share") {
|
|
18063
|
+
currentScreen = "share_horizon";
|
|
18064
|
+
selectedIndex = 0;
|
|
18065
|
+
if (active) startLoop();
|
|
18066
|
+
return;
|
|
18067
|
+
}
|
|
17698
18068
|
await executeSelectedAction();
|
|
17699
|
-
} else {
|
|
18069
|
+
} else if (currentScreen === "receipt_horizon") {
|
|
17700
18070
|
if (selected.id === "back") {
|
|
17701
18071
|
currentScreen = "main";
|
|
17702
18072
|
selectedIndex = 0;
|
|
@@ -17704,6 +18074,14 @@ async function runInteractiveMenu() {
|
|
|
17704
18074
|
return;
|
|
17705
18075
|
}
|
|
17706
18076
|
await executeReceiptHorizon(selected);
|
|
18077
|
+
} else if (currentScreen === "share_horizon") {
|
|
18078
|
+
if (selected.id === "back") {
|
|
18079
|
+
currentScreen = "main";
|
|
18080
|
+
selectedIndex = 0;
|
|
18081
|
+
if (active) startLoop();
|
|
18082
|
+
return;
|
|
18083
|
+
}
|
|
18084
|
+
await executeShareHorizon(selected);
|
|
17707
18085
|
}
|
|
17708
18086
|
if (active) {
|
|
17709
18087
|
startLoop();
|
|
@@ -17720,8 +18098,14 @@ async function runInteractiveMenu() {
|
|
|
17720
18098
|
if (active) startLoop();
|
|
17721
18099
|
return;
|
|
17722
18100
|
}
|
|
18101
|
+
if (selected.id === "share") {
|
|
18102
|
+
currentScreen = "share_horizon";
|
|
18103
|
+
selectedIndex = 0;
|
|
18104
|
+
if (active) startLoop();
|
|
18105
|
+
return;
|
|
18106
|
+
}
|
|
17723
18107
|
await executeSelectedAction();
|
|
17724
|
-
} else {
|
|
18108
|
+
} else if (currentScreen === "receipt_horizon") {
|
|
17725
18109
|
if (selected.id === "back") {
|
|
17726
18110
|
currentScreen = "main";
|
|
17727
18111
|
selectedIndex = 0;
|
|
@@ -17729,6 +18113,14 @@ async function runInteractiveMenu() {
|
|
|
17729
18113
|
return;
|
|
17730
18114
|
}
|
|
17731
18115
|
await executeReceiptHorizon(selected);
|
|
18116
|
+
} else if (currentScreen === "share_horizon") {
|
|
18117
|
+
if (selected.id === "back") {
|
|
18118
|
+
currentScreen = "main";
|
|
18119
|
+
selectedIndex = 0;
|
|
18120
|
+
if (active) startLoop();
|
|
18121
|
+
return;
|
|
18122
|
+
}
|
|
18123
|
+
await executeShareHorizon(selected);
|
|
17732
18124
|
}
|
|
17733
18125
|
if (active) {
|
|
17734
18126
|
startLoop();
|
|
@@ -17746,10 +18138,10 @@ loadQodewkEnv();
|
|
|
17746
18138
|
var SHARE_PAYLOAD_MAX_BYTES2 = 5e4;
|
|
17747
18139
|
function resolveCliVersion() {
|
|
17748
18140
|
try {
|
|
17749
|
-
const argv1 = process.argv[1] ?
|
|
18141
|
+
const argv1 = process.argv[1] ? path17.dirname(path17.resolve(process.argv[1])) : process.cwd();
|
|
17750
18142
|
const candidates = [
|
|
17751
|
-
|
|
17752
|
-
|
|
18143
|
+
path17.join(argv1, "..", "package.json"),
|
|
18144
|
+
path17.join(argv1, "package.json")
|
|
17753
18145
|
];
|
|
17754
18146
|
for (const candidate of candidates) {
|
|
17755
18147
|
if (!fs15.existsSync(candidate)) continue;
|
|
@@ -17758,7 +18150,7 @@ function resolveCliVersion() {
|
|
|
17758
18150
|
}
|
|
17759
18151
|
} catch {
|
|
17760
18152
|
}
|
|
17761
|
-
return "0.
|
|
18153
|
+
return "0.11.0";
|
|
17762
18154
|
}
|
|
17763
18155
|
function resolveSince(options) {
|
|
17764
18156
|
return options.today ? "today" : options.since;
|
|
@@ -17796,21 +18188,44 @@ program2.name("qodewk").description("Universal telemetry and digital receipt gen
|
|
|
17796
18188
|
if (options.notes) {
|
|
17797
18189
|
try {
|
|
17798
18190
|
await writeGitReceiptNote(receipt.repository.headSha, receipt);
|
|
17799
|
-
console.log(
|
|
18191
|
+
console.log(import_picocolors5.default.green(`\u2713 Attached receipt note to ${receipt.repository.headSha.slice(0, 7)} (refs/notes/qodewk)`));
|
|
17800
18192
|
} catch (noteErr) {
|
|
17801
|
-
console.warn(
|
|
18193
|
+
console.warn(import_picocolors5.default.yellow(`Warning: Could not write Git note: ${noteErr.message}`));
|
|
17802
18194
|
}
|
|
17803
18195
|
}
|
|
17804
18196
|
await outputReceipt(receipt, options);
|
|
17805
18197
|
} catch (err) {
|
|
17806
18198
|
const message = err instanceof Error ? err.message : String(err);
|
|
17807
|
-
console.error(
|
|
18199
|
+
console.error(import_picocolors5.default.red(`Error generating receipt: ${message}`));
|
|
17808
18200
|
process.exit(1);
|
|
17809
18201
|
}
|
|
17810
18202
|
});
|
|
17811
18203
|
program2.command("menu").description("Launch interactive terminal control panel").action(async () => {
|
|
17812
18204
|
await runInteractiveMenu();
|
|
17813
18205
|
});
|
|
18206
|
+
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) => {
|
|
18207
|
+
try {
|
|
18208
|
+
const since = options.today ? "today" : options.since;
|
|
18209
|
+
const report = await listProjectChats({
|
|
18210
|
+
repoPath: process.cwd(),
|
|
18211
|
+
since,
|
|
18212
|
+
platform: options.platform,
|
|
18213
|
+
all: options.all
|
|
18214
|
+
});
|
|
18215
|
+
const isJson = Boolean(options.json || program2.opts().json || options.format === "json");
|
|
18216
|
+
if (isJson) {
|
|
18217
|
+
console.log(JSON.stringify(report, null, 2));
|
|
18218
|
+
} else if (options.format === "markdown") {
|
|
18219
|
+
console.log(buildMarkdownChatLedger(report));
|
|
18220
|
+
} else {
|
|
18221
|
+
console.log(buildTerminalChatLedger(report));
|
|
18222
|
+
}
|
|
18223
|
+
} catch (err) {
|
|
18224
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
18225
|
+
console.error(import_picocolors5.default.red(`Error listing workspace chats: ${message}`));
|
|
18226
|
+
process.exit(1);
|
|
18227
|
+
}
|
|
18228
|
+
});
|
|
17814
18229
|
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) => {
|
|
17815
18230
|
try {
|
|
17816
18231
|
const isJson = Boolean(options.json || program2.opts().json);
|
|
@@ -17825,7 +18240,7 @@ program2.command("doctor").description("Run complete diagnostic health check of
|
|
|
17825
18240
|
}
|
|
17826
18241
|
} catch (err) {
|
|
17827
18242
|
const message = err instanceof Error ? err.message : String(err);
|
|
17828
|
-
console.error(
|
|
18243
|
+
console.error(import_picocolors5.default.red(`Error running diagnostics: ${message}`));
|
|
17829
18244
|
process.exit(1);
|
|
17830
18245
|
}
|
|
17831
18246
|
});
|
|
@@ -17845,7 +18260,7 @@ program2.command("audit").description("Audit PR or branch diff against a target
|
|
|
17845
18260
|
await outputReceipt(receipt, options);
|
|
17846
18261
|
} catch (err) {
|
|
17847
18262
|
const message = err instanceof Error ? err.message : String(err);
|
|
17848
|
-
console.error(
|
|
18263
|
+
console.error(import_picocolors5.default.red(`Error auditing git range: ${message}`));
|
|
17849
18264
|
process.exit(1);
|
|
17850
18265
|
}
|
|
17851
18266
|
});
|
|
@@ -17862,12 +18277,12 @@ program2.command("share").description("Publish privacy-safe receipt to Qodewk cl
|
|
|
17862
18277
|
const localFlag = program2.opts().local === true;
|
|
17863
18278
|
if (process.env.QODEWK_TELEMETRY === "off" || localFlag) {
|
|
17864
18279
|
console.log(
|
|
17865
|
-
|
|
18280
|
+
import_picocolors5.default.yellow(
|
|
17866
18281
|
`
|
|
17867
18282
|
Cloud publishing is disabled (${localFlag ? "--local" : "QODEWK_TELEMETRY=off"}).`
|
|
17868
18283
|
)
|
|
17869
18284
|
);
|
|
17870
|
-
console.log(
|
|
18285
|
+
console.log(import_picocolors5.default.dim("Telemetry remains strictly stored in local SQLite (~/.qodewk/state.db).\n"));
|
|
17871
18286
|
persistReceipt(receipt);
|
|
17872
18287
|
await renderTerminalReceipt(receipt);
|
|
17873
18288
|
return;
|
|
@@ -17882,11 +18297,11 @@ Cloud publishing is disabled (${localFlag ? "--local" : "QODEWK_TELEMETRY=off"})
|
|
|
17882
18297
|
body = JSON.stringify(trimmed2);
|
|
17883
18298
|
}
|
|
17884
18299
|
if (Buffer.byteLength(body, "utf-8") > SHARE_PAYLOAD_MAX_BYTES2) {
|
|
17885
|
-
console.error(
|
|
18300
|
+
console.error(import_picocolors5.default.red("Sanitized receipt still exceeds the 50 KB cloud payload limit."));
|
|
17886
18301
|
process.exit(1);
|
|
17887
18302
|
}
|
|
17888
18303
|
const endpoint = resolveApiUrl();
|
|
17889
|
-
console.log(
|
|
18304
|
+
console.log(import_picocolors5.default.dim(`Publishing receipt ${sanitized.receipt.id} to ${endpoint}...`));
|
|
17890
18305
|
try {
|
|
17891
18306
|
const response = await fetch(endpoint, {
|
|
17892
18307
|
method: "POST",
|
|
@@ -17903,11 +18318,11 @@ Cloud publishing is disabled (${localFlag ? "--local" : "QODEWK_TELEMETRY=off"})
|
|
|
17903
18318
|
const data = await response.json();
|
|
17904
18319
|
persistReceipt(sanitized, data.claimToken);
|
|
17905
18320
|
console.log("");
|
|
17906
|
-
console.log(
|
|
17907
|
-
console.log(` ${
|
|
17908
|
-
console.log(` ${
|
|
17909
|
-
console.log(` ${
|
|
17910
|
-
console.log(
|
|
18321
|
+
console.log(import_picocolors5.default.green(" Published successfully."));
|
|
18322
|
+
console.log(` ${import_picocolors5.default.dim("Public URL:")} ${import_picocolors5.default.underline(import_picocolors5.default.cyan(data.url))}`);
|
|
18323
|
+
console.log(` ${import_picocolors5.default.bold(import_picocolors5.default.yellow(" Claim token (store securely \u2014 shown once):"))}`);
|
|
18324
|
+
console.log(` ${import_picocolors5.default.yellow(data.claimToken)}`);
|
|
18325
|
+
console.log(import_picocolors5.default.dim(" Saved to ~/.qodewk/state.db \u2014 required to prove authorship later."));
|
|
17911
18326
|
console.log("");
|
|
17912
18327
|
await renderTerminalReceipt(sanitized, data.url);
|
|
17913
18328
|
if (options.json) {
|
|
@@ -17915,14 +18330,14 @@ Cloud publishing is disabled (${localFlag ? "--local" : "QODEWK_TELEMETRY=off"})
|
|
|
17915
18330
|
}
|
|
17916
18331
|
} catch (networkErr) {
|
|
17917
18332
|
const message = networkErr instanceof Error ? networkErr.message : String(networkErr);
|
|
17918
|
-
console.log(
|
|
18333
|
+
console.log(import_picocolors5.default.yellow(`
|
|
17919
18334
|
Could not reach cloud API (${message}). Rendered locally:`));
|
|
17920
18335
|
persistReceipt(receipt);
|
|
17921
18336
|
await renderTerminalReceipt(receipt);
|
|
17922
18337
|
}
|
|
17923
18338
|
} catch (err) {
|
|
17924
18339
|
const message = err instanceof Error ? err.message : String(err);
|
|
17925
|
-
console.error(
|
|
18340
|
+
console.error(import_picocolors5.default.red(`Error sharing receipt: ${message}`));
|
|
17926
18341
|
process.exit(1);
|
|
17927
18342
|
}
|
|
17928
18343
|
});
|
|
@@ -17940,7 +18355,7 @@ hookCommand.command("install").description("Install non-blocking post-commit and
|
|
|
17940
18355
|
try {
|
|
17941
18356
|
const hooksDir = resolveGitHooksDir();
|
|
17942
18357
|
if (!hooksDir) {
|
|
17943
|
-
console.error(
|
|
18358
|
+
console.error(import_picocolors5.default.red("Error: Current directory is not a Git repository (.git not found)."));
|
|
17944
18359
|
process.exit(1);
|
|
17945
18360
|
}
|
|
17946
18361
|
if (!fs15.existsSync(hooksDir)) {
|
|
@@ -17950,25 +18365,25 @@ hookCommand.command("install").description("Install non-blocking post-commit and
|
|
|
17950
18365
|
let installed = 0;
|
|
17951
18366
|
let existing = 0;
|
|
17952
18367
|
for (const name of targets) {
|
|
17953
|
-
const result = installHookFile(
|
|
18368
|
+
const result = installHookFile(path17.join(hooksDir, name));
|
|
17954
18369
|
if (result === "installed") installed++;
|
|
17955
18370
|
else existing++;
|
|
17956
18371
|
}
|
|
17957
18372
|
if (installed === 0 && existing > 0) {
|
|
17958
|
-
console.log(
|
|
18373
|
+
console.log(import_picocolors5.default.yellow("Qodewk Git hooks are already installed (post-commit, post-rewrite)."));
|
|
17959
18374
|
return;
|
|
17960
18375
|
}
|
|
17961
18376
|
console.log(
|
|
17962
|
-
|
|
18377
|
+
import_picocolors5.default.green(
|
|
17963
18378
|
`\u2713 Non-blocking Qodewk hooks installed in ${hooksDir} (post-commit${installed > 1 || existing > 0 ? ", post-rewrite" : installed === 1 && targets.length === 2 ? " + post-rewrite" : ""})`
|
|
17964
18379
|
)
|
|
17965
18380
|
);
|
|
17966
18381
|
if (existing > 0) {
|
|
17967
|
-
console.log(
|
|
18382
|
+
console.log(import_picocolors5.default.dim(` (${existing} hook file(s) already contained the Qodewk marker)`));
|
|
17968
18383
|
}
|
|
17969
18384
|
} catch (err) {
|
|
17970
18385
|
const message = err instanceof Error ? err.message : String(err);
|
|
17971
|
-
console.error(
|
|
18386
|
+
console.error(import_picocolors5.default.red(`Failed to install Git hook: ${message}`));
|
|
17972
18387
|
process.exit(1);
|
|
17973
18388
|
}
|
|
17974
18389
|
});
|
|
@@ -17976,23 +18391,23 @@ hookCommand.command("uninstall").description("Remove Qodewk post-commit and post
|
|
|
17976
18391
|
try {
|
|
17977
18392
|
const hooksDir = resolveGitHooksDir();
|
|
17978
18393
|
if (!hooksDir) {
|
|
17979
|
-
console.log(
|
|
18394
|
+
console.log(import_picocolors5.default.yellow("No Git repository found."));
|
|
17980
18395
|
return;
|
|
17981
18396
|
}
|
|
17982
18397
|
const targets = ["post-commit", "post-rewrite"];
|
|
17983
18398
|
let removed = 0;
|
|
17984
18399
|
for (const name of targets) {
|
|
17985
|
-
const result = uninstallHookFile(
|
|
18400
|
+
const result = uninstallHookFile(path17.join(hooksDir, name));
|
|
17986
18401
|
if (result === "removed") removed++;
|
|
17987
18402
|
}
|
|
17988
18403
|
if (removed === 0) {
|
|
17989
|
-
console.log(
|
|
18404
|
+
console.log(import_picocolors5.default.yellow("Qodewk hooks are not installed."));
|
|
17990
18405
|
return;
|
|
17991
18406
|
}
|
|
17992
|
-
console.log(
|
|
18407
|
+
console.log(import_picocolors5.default.green(`\u2713 Qodewk hook markers removed from ${removed} file(s).`));
|
|
17993
18408
|
} catch (err) {
|
|
17994
18409
|
const message = err instanceof Error ? err.message : String(err);
|
|
17995
|
-
console.error(
|
|
18410
|
+
console.error(import_picocolors5.default.red(`Failed to uninstall hook: ${message}`));
|
|
17996
18411
|
process.exit(1);
|
|
17997
18412
|
}
|
|
17998
18413
|
});
|
|
@@ -18011,7 +18426,7 @@ hookCommand.command("test").aliases(["verify", "check"]).description("Verify non
|
|
|
18011
18426
|
}
|
|
18012
18427
|
} catch (err) {
|
|
18013
18428
|
const message = err instanceof Error ? err.message : String(err);
|
|
18014
|
-
console.error(
|
|
18429
|
+
console.error(import_picocolors5.default.red(`Error testing hooks: ${message}`));
|
|
18015
18430
|
process.exit(1);
|
|
18016
18431
|
}
|
|
18017
18432
|
});
|
|
@@ -18020,7 +18435,7 @@ notesCmd.command("show [commit]").description("Display Qodewk receipt attached t
|
|
|
18020
18435
|
try {
|
|
18021
18436
|
const receipt = await readGitReceiptNote(commit);
|
|
18022
18437
|
if (!receipt) {
|
|
18023
|
-
console.log(
|
|
18438
|
+
console.log(import_picocolors5.default.yellow(`No Qodewk receipt note found on commit '${commit}'.`));
|
|
18024
18439
|
return;
|
|
18025
18440
|
}
|
|
18026
18441
|
if (opts.json) {
|
|
@@ -18030,7 +18445,7 @@ notesCmd.command("show [commit]").description("Display Qodewk receipt attached t
|
|
|
18030
18445
|
}
|
|
18031
18446
|
} catch (err) {
|
|
18032
18447
|
const message = err instanceof Error ? err.message : String(err);
|
|
18033
|
-
console.error(
|
|
18448
|
+
console.error(import_picocolors5.default.red(`Error reading Git note: ${message}`));
|
|
18034
18449
|
process.exit(1);
|
|
18035
18450
|
}
|
|
18036
18451
|
});
|
|
@@ -18039,11 +18454,11 @@ notesCmd.command("write [commit]").description("Generate and attach receipt to a
|
|
|
18039
18454
|
const receipt = await generateReceipt({ headSha: commit });
|
|
18040
18455
|
await writeGitReceiptNote(receipt.repository.headSha, receipt);
|
|
18041
18456
|
console.log(
|
|
18042
|
-
|
|
18457
|
+
import_picocolors5.default.green(`\u2713 Attached receipt note to ${receipt.repository.headSha.slice(0, 7)} (refs/notes/qodewk)`)
|
|
18043
18458
|
);
|
|
18044
18459
|
} catch (err) {
|
|
18045
18460
|
const message = err instanceof Error ? err.message : String(err);
|
|
18046
|
-
console.error(
|
|
18461
|
+
console.error(import_picocolors5.default.red(`Error writing Git note: ${message}`));
|
|
18047
18462
|
process.exit(1);
|
|
18048
18463
|
}
|
|
18049
18464
|
});
|
|
@@ -18051,16 +18466,16 @@ notesCmd.command("list").description("List all commits with attached Qodewk rece
|
|
|
18051
18466
|
try {
|
|
18052
18467
|
const shas = await listGitReceiptNotes();
|
|
18053
18468
|
if (shas.length === 0) {
|
|
18054
|
-
console.log(
|
|
18469
|
+
console.log(import_picocolors5.default.yellow("No Qodewk Git notes found in repository."));
|
|
18055
18470
|
return;
|
|
18056
18471
|
}
|
|
18057
|
-
console.log(
|
|
18472
|
+
console.log(import_picocolors5.default.bold(`Found ${shas.length} commit note(s) in refs/notes/qodewk:`));
|
|
18058
18473
|
for (const sha of shas) {
|
|
18059
|
-
console.log(` ${
|
|
18474
|
+
console.log(` ${import_picocolors5.default.cyan(sha.slice(0, 10))} ${import_picocolors5.default.dim(sha)}`);
|
|
18060
18475
|
}
|
|
18061
18476
|
} catch (err) {
|
|
18062
18477
|
const message = err instanceof Error ? err.message : String(err);
|
|
18063
|
-
console.error(
|
|
18478
|
+
console.error(import_picocolors5.default.red(`Error listing Git notes: ${message}`));
|
|
18064
18479
|
process.exit(1);
|
|
18065
18480
|
}
|
|
18066
18481
|
});
|