qodewk 0.4.0 → 0.6.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 +649 -169
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1153,8 +1153,8 @@ var require_command = __commonJS({
|
|
|
1153
1153
|
"use strict";
|
|
1154
1154
|
var EventEmitter2 = require("events").EventEmitter;
|
|
1155
1155
|
var childProcess = require("child_process");
|
|
1156
|
-
var
|
|
1157
|
-
var
|
|
1156
|
+
var path11 = require("path");
|
|
1157
|
+
var fs11 = require("fs");
|
|
1158
1158
|
var process2 = require("process");
|
|
1159
1159
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
1160
1160
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -2135,7 +2135,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2135
2135
|
* @param {string} subcommandName
|
|
2136
2136
|
*/
|
|
2137
2137
|
_checkForMissingExecutable(executableFile, executableDir, subcommandName) {
|
|
2138
|
-
if (
|
|
2138
|
+
if (fs11.existsSync(executableFile)) return;
|
|
2139
2139
|
const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
|
|
2140
2140
|
const executableMissing = `'${executableFile}' does not exist
|
|
2141
2141
|
- if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
@@ -2153,11 +2153,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2153
2153
|
let launchWithNode = false;
|
|
2154
2154
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
2155
2155
|
function findFile(baseDir, baseName) {
|
|
2156
|
-
const localBin =
|
|
2157
|
-
if (
|
|
2158
|
-
if (sourceExt.includes(
|
|
2156
|
+
const localBin = path11.resolve(baseDir, baseName);
|
|
2157
|
+
if (fs11.existsSync(localBin)) return localBin;
|
|
2158
|
+
if (sourceExt.includes(path11.extname(baseName))) return void 0;
|
|
2159
2159
|
const foundExt = sourceExt.find(
|
|
2160
|
-
(ext) =>
|
|
2160
|
+
(ext) => fs11.existsSync(`${localBin}${ext}`)
|
|
2161
2161
|
);
|
|
2162
2162
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
2163
2163
|
return void 0;
|
|
@@ -2169,21 +2169,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2169
2169
|
if (this._scriptPath) {
|
|
2170
2170
|
let resolvedScriptPath;
|
|
2171
2171
|
try {
|
|
2172
|
-
resolvedScriptPath =
|
|
2172
|
+
resolvedScriptPath = fs11.realpathSync(this._scriptPath);
|
|
2173
2173
|
} catch {
|
|
2174
2174
|
resolvedScriptPath = this._scriptPath;
|
|
2175
2175
|
}
|
|
2176
|
-
executableDir =
|
|
2177
|
-
|
|
2176
|
+
executableDir = path11.resolve(
|
|
2177
|
+
path11.dirname(resolvedScriptPath),
|
|
2178
2178
|
executableDir
|
|
2179
2179
|
);
|
|
2180
2180
|
}
|
|
2181
2181
|
if (executableDir) {
|
|
2182
2182
|
let localFile = findFile(executableDir, executableFile);
|
|
2183
2183
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
2184
|
-
const legacyName =
|
|
2184
|
+
const legacyName = path11.basename(
|
|
2185
2185
|
this._scriptPath,
|
|
2186
|
-
|
|
2186
|
+
path11.extname(this._scriptPath)
|
|
2187
2187
|
);
|
|
2188
2188
|
if (legacyName !== this._name) {
|
|
2189
2189
|
localFile = findFile(
|
|
@@ -2194,7 +2194,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2194
2194
|
}
|
|
2195
2195
|
executableFile = localFile || executableFile;
|
|
2196
2196
|
}
|
|
2197
|
-
launchWithNode = sourceExt.includes(
|
|
2197
|
+
launchWithNode = sourceExt.includes(path11.extname(executableFile));
|
|
2198
2198
|
let proc;
|
|
2199
2199
|
if (process2.platform !== "win32") {
|
|
2200
2200
|
if (launchWithNode) {
|
|
@@ -3041,7 +3041,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3041
3041
|
* @return {Command}
|
|
3042
3042
|
*/
|
|
3043
3043
|
nameFromFilename(filename) {
|
|
3044
|
-
this._name =
|
|
3044
|
+
this._name = path11.basename(filename, path11.extname(filename));
|
|
3045
3045
|
return this;
|
|
3046
3046
|
}
|
|
3047
3047
|
/**
|
|
@@ -3055,9 +3055,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3055
3055
|
* @param {string} [path]
|
|
3056
3056
|
* @return {(string|null|Command)}
|
|
3057
3057
|
*/
|
|
3058
|
-
executableDir(
|
|
3059
|
-
if (
|
|
3060
|
-
this._executableDir =
|
|
3058
|
+
executableDir(path12) {
|
|
3059
|
+
if (path12 === void 0) return this._executableDir;
|
|
3060
|
+
this._executableDir = path12;
|
|
3061
3061
|
return this;
|
|
3062
3062
|
}
|
|
3063
3063
|
/**
|
|
@@ -4067,10 +4067,10 @@ var require_src2 = __commonJS({
|
|
|
4067
4067
|
var fs_1 = require("fs");
|
|
4068
4068
|
var debug_1 = __importDefault(require_src());
|
|
4069
4069
|
var log = debug_1.default("@kwsites/file-exists");
|
|
4070
|
-
function check(
|
|
4071
|
-
log(`checking %s`,
|
|
4070
|
+
function check(path11, isFile, isDirectory) {
|
|
4071
|
+
log(`checking %s`, path11);
|
|
4072
4072
|
try {
|
|
4073
|
-
const stat = fs_1.statSync(
|
|
4073
|
+
const stat = fs_1.statSync(path11);
|
|
4074
4074
|
if (stat.isFile() && isFile) {
|
|
4075
4075
|
log(`[OK] path represents a file`);
|
|
4076
4076
|
return true;
|
|
@@ -4090,8 +4090,8 @@ var require_src2 = __commonJS({
|
|
|
4090
4090
|
throw e;
|
|
4091
4091
|
}
|
|
4092
4092
|
}
|
|
4093
|
-
function exists2(
|
|
4094
|
-
return check(
|
|
4093
|
+
function exists2(path11, type = exports2.READABLE) {
|
|
4094
|
+
return check(path11, (type & exports2.FILE) > 0, (type & exports2.FOLDER) > 0);
|
|
4095
4095
|
}
|
|
4096
4096
|
exports2.exists = exists2;
|
|
4097
4097
|
exports2.FILE = 1;
|
|
@@ -4155,8 +4155,8 @@ var require_dist2 = __commonJS({
|
|
|
4155
4155
|
});
|
|
4156
4156
|
|
|
4157
4157
|
// src/index.ts
|
|
4158
|
-
var
|
|
4159
|
-
var
|
|
4158
|
+
var fs10 = __toESM(require("fs"), 1);
|
|
4159
|
+
var path10 = __toESM(require("path"), 1);
|
|
4160
4160
|
|
|
4161
4161
|
// ../../node_modules/.pnpm/commander@13.1.0/node_modules/commander/esm.mjs
|
|
4162
4162
|
var import_index = __toESM(require_commander(), 1);
|
|
@@ -4659,8 +4659,8 @@ function getErrorMap() {
|
|
|
4659
4659
|
|
|
4660
4660
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
4661
4661
|
var makeIssue = (params) => {
|
|
4662
|
-
const { data, path:
|
|
4663
|
-
const fullPath = [...
|
|
4662
|
+
const { data, path: path11, errorMaps, issueData } = params;
|
|
4663
|
+
const fullPath = [...path11, ...issueData.path || []];
|
|
4664
4664
|
const fullIssue = {
|
|
4665
4665
|
...issueData,
|
|
4666
4666
|
path: fullPath
|
|
@@ -4776,11 +4776,11 @@ var errorUtil;
|
|
|
4776
4776
|
|
|
4777
4777
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
4778
4778
|
var ParseInputLazyPath = class {
|
|
4779
|
-
constructor(parent, value,
|
|
4779
|
+
constructor(parent, value, path11, key) {
|
|
4780
4780
|
this._cachedPath = [];
|
|
4781
4781
|
this.parent = parent;
|
|
4782
4782
|
this.data = value;
|
|
4783
|
-
this._path =
|
|
4783
|
+
this._path = path11;
|
|
4784
4784
|
this._key = key;
|
|
4785
4785
|
}
|
|
4786
4786
|
get path() {
|
|
@@ -8892,8 +8892,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
8892
8892
|
function forEachLineWithContent(input, callback) {
|
|
8893
8893
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
8894
8894
|
}
|
|
8895
|
-
function folderExists(
|
|
8896
|
-
return (0, import_file_exists.exists)(
|
|
8895
|
+
function folderExists(path11) {
|
|
8896
|
+
return (0, import_file_exists.exists)(path11, import_file_exists.FOLDER);
|
|
8897
8897
|
}
|
|
8898
8898
|
function append(target, item) {
|
|
8899
8899
|
if (Array.isArray(target)) {
|
|
@@ -9295,8 +9295,8 @@ function checkIsRepoRootTask() {
|
|
|
9295
9295
|
commands,
|
|
9296
9296
|
format: "utf-8",
|
|
9297
9297
|
onError,
|
|
9298
|
-
parser(
|
|
9299
|
-
return /^\.(git)?$/.test(
|
|
9298
|
+
parser(path11) {
|
|
9299
|
+
return /^\.(git)?$/.test(path11.trim());
|
|
9300
9300
|
}
|
|
9301
9301
|
};
|
|
9302
9302
|
}
|
|
@@ -9730,11 +9730,11 @@ function parseGrep(grep) {
|
|
|
9730
9730
|
const paths = /* @__PURE__ */ new Set();
|
|
9731
9731
|
const results = {};
|
|
9732
9732
|
forEachLineWithContent(grep, (input) => {
|
|
9733
|
-
const [
|
|
9734
|
-
paths.add(
|
|
9735
|
-
(results[
|
|
9733
|
+
const [path11, line, preview] = input.split(NULL);
|
|
9734
|
+
paths.add(path11);
|
|
9735
|
+
(results[path11] = results[path11] || []).push({
|
|
9736
9736
|
line: asNumber(line),
|
|
9737
|
-
path:
|
|
9737
|
+
path: path11,
|
|
9738
9738
|
preview
|
|
9739
9739
|
});
|
|
9740
9740
|
});
|
|
@@ -10498,14 +10498,14 @@ var init_hash_object = __esm({
|
|
|
10498
10498
|
init_task();
|
|
10499
10499
|
}
|
|
10500
10500
|
});
|
|
10501
|
-
function parseInit(bare,
|
|
10501
|
+
function parseInit(bare, path11, text) {
|
|
10502
10502
|
const response = String(text).trim();
|
|
10503
10503
|
let result;
|
|
10504
10504
|
if (result = initResponseRegex.exec(response)) {
|
|
10505
|
-
return new InitSummary(bare,
|
|
10505
|
+
return new InitSummary(bare, path11, false, result[1]);
|
|
10506
10506
|
}
|
|
10507
10507
|
if (result = reInitResponseRegex.exec(response)) {
|
|
10508
|
-
return new InitSummary(bare,
|
|
10508
|
+
return new InitSummary(bare, path11, true, result[1]);
|
|
10509
10509
|
}
|
|
10510
10510
|
let gitDir = "";
|
|
10511
10511
|
const tokens = response.split(" ");
|
|
@@ -10516,7 +10516,7 @@ function parseInit(bare, path9, text) {
|
|
|
10516
10516
|
break;
|
|
10517
10517
|
}
|
|
10518
10518
|
}
|
|
10519
|
-
return new InitSummary(bare,
|
|
10519
|
+
return new InitSummary(bare, path11, /^re/i.test(response), gitDir);
|
|
10520
10520
|
}
|
|
10521
10521
|
var InitSummary;
|
|
10522
10522
|
var initResponseRegex;
|
|
@@ -10525,9 +10525,9 @@ var init_InitSummary = __esm({
|
|
|
10525
10525
|
"src/lib/responses/InitSummary.ts"() {
|
|
10526
10526
|
"use strict";
|
|
10527
10527
|
InitSummary = class {
|
|
10528
|
-
constructor(bare,
|
|
10528
|
+
constructor(bare, path11, existing, gitDir) {
|
|
10529
10529
|
this.bare = bare;
|
|
10530
|
-
this.path =
|
|
10530
|
+
this.path = path11;
|
|
10531
10531
|
this.existing = existing;
|
|
10532
10532
|
this.gitDir = gitDir;
|
|
10533
10533
|
}
|
|
@@ -10539,7 +10539,7 @@ var init_InitSummary = __esm({
|
|
|
10539
10539
|
function hasBareCommand(command) {
|
|
10540
10540
|
return command.includes(bareCommand);
|
|
10541
10541
|
}
|
|
10542
|
-
function initTask(bare = false,
|
|
10542
|
+
function initTask(bare = false, path11, customArgs) {
|
|
10543
10543
|
const commands = ["init", ...customArgs];
|
|
10544
10544
|
if (bare && !hasBareCommand(commands)) {
|
|
10545
10545
|
commands.splice(1, 0, bareCommand);
|
|
@@ -10548,7 +10548,7 @@ function initTask(bare = false, path9, customArgs) {
|
|
|
10548
10548
|
commands,
|
|
10549
10549
|
format: "utf-8",
|
|
10550
10550
|
parser(text) {
|
|
10551
|
-
return parseInit(commands.includes("--bare"),
|
|
10551
|
+
return parseInit(commands.includes("--bare"), path11, text);
|
|
10552
10552
|
}
|
|
10553
10553
|
};
|
|
10554
10554
|
}
|
|
@@ -11363,12 +11363,12 @@ var init_FileStatusSummary = __esm({
|
|
|
11363
11363
|
"use strict";
|
|
11364
11364
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
11365
11365
|
FileStatusSummary = class {
|
|
11366
|
-
constructor(
|
|
11367
|
-
this.path =
|
|
11366
|
+
constructor(path11, index, working_dir) {
|
|
11367
|
+
this.path = path11;
|
|
11368
11368
|
this.index = index;
|
|
11369
11369
|
this.working_dir = working_dir;
|
|
11370
11370
|
if (index === "R" || working_dir === "R") {
|
|
11371
|
-
const detail = fromPathRegex.exec(
|
|
11371
|
+
const detail = fromPathRegex.exec(path11) || [null, path11, path11];
|
|
11372
11372
|
this.from = detail[2] || "";
|
|
11373
11373
|
this.path = detail[1] || "";
|
|
11374
11374
|
}
|
|
@@ -11399,14 +11399,14 @@ function splitLine(result, lineStr) {
|
|
|
11399
11399
|
default:
|
|
11400
11400
|
return;
|
|
11401
11401
|
}
|
|
11402
|
-
function data(index, workingDir,
|
|
11402
|
+
function data(index, workingDir, path11) {
|
|
11403
11403
|
const raw = `${index}${workingDir}`;
|
|
11404
11404
|
const handler = parsers6.get(raw);
|
|
11405
11405
|
if (handler) {
|
|
11406
|
-
handler(result,
|
|
11406
|
+
handler(result, path11);
|
|
11407
11407
|
}
|
|
11408
11408
|
if (raw !== "##" && raw !== "!!") {
|
|
11409
|
-
result.files.push(new FileStatusSummary(
|
|
11409
|
+
result.files.push(new FileStatusSummary(path11, index, workingDir));
|
|
11410
11410
|
}
|
|
11411
11411
|
}
|
|
11412
11412
|
}
|
|
@@ -11757,9 +11757,9 @@ var init_simple_git_api = __esm({
|
|
|
11757
11757
|
next
|
|
11758
11758
|
);
|
|
11759
11759
|
}
|
|
11760
|
-
hashObject(
|
|
11760
|
+
hashObject(path11, write) {
|
|
11761
11761
|
return this._runTask(
|
|
11762
|
-
hashObjectTask(
|
|
11762
|
+
hashObjectTask(path11, write === true),
|
|
11763
11763
|
trailingFunctionArgument(arguments)
|
|
11764
11764
|
);
|
|
11765
11765
|
}
|
|
@@ -12113,8 +12113,8 @@ var init_branch = __esm({
|
|
|
12113
12113
|
}
|
|
12114
12114
|
});
|
|
12115
12115
|
function toPath(input) {
|
|
12116
|
-
const
|
|
12117
|
-
return
|
|
12116
|
+
const path11 = input.trim().replace(/^["']|["']$/g, "");
|
|
12117
|
+
return path11 && (0, import_node_path.normalize)(path11);
|
|
12118
12118
|
}
|
|
12119
12119
|
var parseCheckIgnore;
|
|
12120
12120
|
var init_CheckIgnore = __esm({
|
|
@@ -12399,8 +12399,8 @@ __export2(sub_module_exports, {
|
|
|
12399
12399
|
subModuleTask: () => subModuleTask,
|
|
12400
12400
|
updateSubModuleTask: () => updateSubModuleTask
|
|
12401
12401
|
});
|
|
12402
|
-
function addSubModuleTask(repo,
|
|
12403
|
-
return subModuleTask(["add", repo,
|
|
12402
|
+
function addSubModuleTask(repo, path11) {
|
|
12403
|
+
return subModuleTask(["add", repo, path11]);
|
|
12404
12404
|
}
|
|
12405
12405
|
function initSubModuleTask(customArgs) {
|
|
12406
12406
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -12714,8 +12714,8 @@ var require_git = __commonJS2({
|
|
|
12714
12714
|
}
|
|
12715
12715
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
12716
12716
|
};
|
|
12717
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
12718
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
12717
|
+
Git2.prototype.submoduleAdd = function(repo, path11, then) {
|
|
12718
|
+
return this._runTask(addSubModuleTask2(repo, path11), trailingFunctionArgument2(arguments));
|
|
12719
12719
|
};
|
|
12720
12720
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
12721
12721
|
return this._runTask(
|
|
@@ -13334,7 +13334,8 @@ async function resolveGitSha(git, ref) {
|
|
|
13334
13334
|
}
|
|
13335
13335
|
throw new Error(`Unable to resolve git reference '${ref}' to a valid commit SHA.`);
|
|
13336
13336
|
}
|
|
13337
|
-
async function detectDefaultBaseBranch(
|
|
13337
|
+
async function detectDefaultBaseBranch(repoPathOrGit = process.cwd()) {
|
|
13338
|
+
const git = typeof repoPathOrGit === "string" ? simpleGit(repoPathOrGit) : repoPathOrGit;
|
|
13338
13339
|
const candidates = ["origin/main", "main", "origin/master", "master"];
|
|
13339
13340
|
for (const c3 of candidates) {
|
|
13340
13341
|
try {
|
|
@@ -13568,63 +13569,62 @@ function mapExtensionToLanguage(ext) {
|
|
|
13568
13569
|
};
|
|
13569
13570
|
return map[ext] || (ext ? ext.toUpperCase() : null);
|
|
13570
13571
|
}
|
|
13571
|
-
|
|
13572
|
-
|
|
13573
|
-
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
|
|
13577
|
-
|
|
13578
|
-
|
|
13579
|
-
|
|
13580
|
-
if (msg.includes("claude") || msg.includes("anthropic")) {
|
|
13581
|
-
return {
|
|
13582
|
-
provider: "anthropic",
|
|
13583
|
-
model: "claude-3-7-sonnet",
|
|
13584
|
-
confidence: 0.85,
|
|
13585
|
-
mode: "observed"
|
|
13586
|
-
};
|
|
13587
|
-
}
|
|
13588
|
-
if (msg.includes("antigravity")) {
|
|
13589
|
-
return {
|
|
13590
|
-
provider: "antigravity",
|
|
13591
|
-
model: "claude-sonnet-4-6-thinking",
|
|
13592
|
-
confidence: 0.85,
|
|
13593
|
-
mode: "observed"
|
|
13594
|
-
};
|
|
13595
|
-
}
|
|
13596
|
-
if (msg.includes("gemini")) {
|
|
13597
|
-
return {
|
|
13598
|
-
provider: "google",
|
|
13599
|
-
model: "gemini-3-8-flash",
|
|
13600
|
-
confidence: 0.85,
|
|
13601
|
-
mode: "observed"
|
|
13602
|
-
};
|
|
13572
|
+
var QODEWK_GIT_NOTES_REF = "refs/notes/qodewk";
|
|
13573
|
+
async function writeGitReceiptNote(commitSha, receipt, options = {}) {
|
|
13574
|
+
const repoPath = options.repoPath || process.cwd();
|
|
13575
|
+
const git = simpleGit(repoPath);
|
|
13576
|
+
const cleanSha = commitSha.trim();
|
|
13577
|
+
const notePayload = JSON.stringify(receipt, null, 2);
|
|
13578
|
+
const args = ["notes", `--ref=${QODEWK_GIT_NOTES_REF}`, "add"];
|
|
13579
|
+
if (options.force !== false) {
|
|
13580
|
+
args.push("-f");
|
|
13603
13581
|
}
|
|
13604
|
-
|
|
13605
|
-
|
|
13606
|
-
|
|
13607
|
-
|
|
13608
|
-
|
|
13609
|
-
|
|
13610
|
-
|
|
13582
|
+
args.push("-m", notePayload, cleanSha);
|
|
13583
|
+
await git.raw(args);
|
|
13584
|
+
}
|
|
13585
|
+
async function readGitReceiptNote(commitSha, options = {}) {
|
|
13586
|
+
const repoPath = options.repoPath || process.cwd();
|
|
13587
|
+
const git = simpleGit(repoPath);
|
|
13588
|
+
const cleanSha = commitSha.trim();
|
|
13589
|
+
try {
|
|
13590
|
+
const rawNote = await git.raw(["notes", `--ref=${QODEWK_GIT_NOTES_REF}`, "show", cleanSha]);
|
|
13591
|
+
if (!rawNote || !rawNote.trim())
|
|
13592
|
+
return null;
|
|
13593
|
+
const parsed = JSON.parse(rawNote.trim());
|
|
13594
|
+
const valid = ReceiptV1Schema.safeParse(parsed);
|
|
13595
|
+
if (valid.success) {
|
|
13596
|
+
return valid.data;
|
|
13597
|
+
}
|
|
13598
|
+
return null;
|
|
13599
|
+
} catch {
|
|
13600
|
+
return null;
|
|
13611
13601
|
}
|
|
13612
|
-
|
|
13613
|
-
|
|
13614
|
-
|
|
13615
|
-
|
|
13616
|
-
|
|
13617
|
-
|
|
13618
|
-
|
|
13602
|
+
}
|
|
13603
|
+
async function listGitReceiptNotes(options = {}) {
|
|
13604
|
+
const repoPath = options.repoPath || process.cwd();
|
|
13605
|
+
const git = simpleGit(repoPath);
|
|
13606
|
+
try {
|
|
13607
|
+
const output = await git.raw(["notes", `--ref=${QODEWK_GIT_NOTES_REF}`, "list"]);
|
|
13608
|
+
if (!output || !output.trim())
|
|
13609
|
+
return [];
|
|
13610
|
+
const lines = output.trim().split("\n");
|
|
13611
|
+
const commitShas = [];
|
|
13612
|
+
for (const line of lines) {
|
|
13613
|
+
const parts = line.trim().split(/\s+/);
|
|
13614
|
+
if (parts.length >= 2 && parts[1]) {
|
|
13615
|
+
commitShas.push(parts[1]);
|
|
13616
|
+
}
|
|
13617
|
+
}
|
|
13618
|
+
return commitShas;
|
|
13619
|
+
} catch {
|
|
13620
|
+
return [];
|
|
13619
13621
|
}
|
|
13620
|
-
return null;
|
|
13621
13622
|
}
|
|
13622
13623
|
|
|
13623
|
-
// ../core/dist/
|
|
13624
|
-
var
|
|
13625
|
-
var
|
|
13626
|
-
var
|
|
13627
|
-
var import_node_module = require("module");
|
|
13624
|
+
// ../core/dist/discovery.js
|
|
13625
|
+
var fs = __toESM(require("fs"), 1);
|
|
13626
|
+
var path2 = __toESM(require("path"), 1);
|
|
13627
|
+
var os = __toESM(require("os"), 1);
|
|
13628
13628
|
|
|
13629
13629
|
// ../pricing/dist/index.js
|
|
13630
13630
|
var RATE_CARDS = {
|
|
@@ -13814,10 +13814,50 @@ var RATE_CARDS = {
|
|
|
13814
13814
|
contextWindow: 128e3
|
|
13815
13815
|
}
|
|
13816
13816
|
};
|
|
13817
|
+
var MODEL_ALIASES = {
|
|
13818
|
+
// Anthropic aliases
|
|
13819
|
+
"claude-3-7-sonnet-latest": "claude-3-7-sonnet",
|
|
13820
|
+
"claude-3-7-sonnet-20250219": "claude-3-7-sonnet",
|
|
13821
|
+
"claude-3-5-sonnet-latest": "claude-3-5-sonnet",
|
|
13822
|
+
"claude-3-5-sonnet-20241022": "claude-3-5-sonnet",
|
|
13823
|
+
"claude-3-5-sonnet-20240620": "claude-3-5-sonnet",
|
|
13824
|
+
"claude-3-5-haiku-latest": "claude-3-5-haiku",
|
|
13825
|
+
"claude-3-5-haiku-20241022": "claude-3-5-haiku",
|
|
13826
|
+
"claude-3-opus-20240229": "claude-opus-4",
|
|
13827
|
+
"claude-code": "claude-3-7-sonnet",
|
|
13828
|
+
"cursor-fast": "claude-3-5-sonnet",
|
|
13829
|
+
"cursor-small": "claude-3-5-haiku",
|
|
13830
|
+
// OpenAI aliases
|
|
13831
|
+
"chatgpt-4o-latest": "gpt-4o",
|
|
13832
|
+
"gpt-4o-2024-08-06": "gpt-4o",
|
|
13833
|
+
"gpt-4o-2024-11-20": "gpt-4o",
|
|
13834
|
+
"gpt-4o-mini-2024-07-18": "gpt-4o-mini",
|
|
13835
|
+
"o1-preview": "o1",
|
|
13836
|
+
"o1-2024-12-17": "o1",
|
|
13837
|
+
"o3": "o3-mini",
|
|
13838
|
+
// Google aliases
|
|
13839
|
+
"gemini-3": "gemini-3-8-flash",
|
|
13840
|
+
"gemini-flash": "gemini-3-8-flash",
|
|
13841
|
+
"gemini-pro": "gemini-2-5-pro",
|
|
13842
|
+
"gemini-2.0-flash": "gemini-2-0-flash",
|
|
13843
|
+
"gemini-1.5-pro": "gemini-1-5-pro",
|
|
13844
|
+
"gemini-1.5-flash": "gemini-2-0-flash",
|
|
13845
|
+
// DeepSeek aliases
|
|
13846
|
+
"deepseek-chat": "deepseek-v3",
|
|
13847
|
+
"deepseek-coder": "deepseek-v3",
|
|
13848
|
+
"deepseek/deepseek-chat": "deepseek-v3",
|
|
13849
|
+
"deepseek-reasoner": "deepseek-r1",
|
|
13850
|
+
"deepseek/deepseek-r1": "deepseek-r1"
|
|
13851
|
+
};
|
|
13817
13852
|
function getRateCard(modelId) {
|
|
13818
13853
|
if (!modelId)
|
|
13819
13854
|
return RATE_CARDS["default"];
|
|
13820
|
-
|
|
13855
|
+
let key = modelId.toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
13856
|
+
if (MODEL_ALIASES[modelId.toLowerCase()]) {
|
|
13857
|
+
key = MODEL_ALIASES[modelId.toLowerCase()];
|
|
13858
|
+
} else if (MODEL_ALIASES[key]) {
|
|
13859
|
+
key = MODEL_ALIASES[key];
|
|
13860
|
+
}
|
|
13821
13861
|
if (RATE_CARDS[key])
|
|
13822
13862
|
return RATE_CARDS[key];
|
|
13823
13863
|
if (key.includes("opus")) {
|
|
@@ -13866,6 +13906,152 @@ function computeCost(inputTokens, outputTokens, cachedTokens, card, cacheWriteTo
|
|
|
13866
13906
|
return Number((freshCost + cacheReadCost + cacheWriteCost + outCost).toFixed(4));
|
|
13867
13907
|
}
|
|
13868
13908
|
|
|
13909
|
+
// ../core/dist/discovery.js
|
|
13910
|
+
function parseGitTrailers(commitMessage) {
|
|
13911
|
+
if (!commitMessage)
|
|
13912
|
+
return [];
|
|
13913
|
+
const trailers = [];
|
|
13914
|
+
const lines = commitMessage.split("\n");
|
|
13915
|
+
for (const line of lines) {
|
|
13916
|
+
const trimmed2 = line.trim();
|
|
13917
|
+
const match = trimmed2.match(/^([A-Za-z\-]+):\s*(.+)$/i);
|
|
13918
|
+
if (!match || !match[1] || !match[2])
|
|
13919
|
+
continue;
|
|
13920
|
+
const token = match[1].toLowerCase();
|
|
13921
|
+
const value = match[2];
|
|
13922
|
+
const valLower = value.toLowerCase();
|
|
13923
|
+
if (token === "co-authored-by" || token === "generated-by" || token === "assisted-by" || token === "signed-off-by") {
|
|
13924
|
+
if (valLower.includes("copilot") || valLower.includes("github-actions")) {
|
|
13925
|
+
trailers.push({ token, value, provider: "copilot", model: "gpt-4o" });
|
|
13926
|
+
} else if (valLower.includes("claude") || valLower.includes("anthropic")) {
|
|
13927
|
+
trailers.push({ token, value, provider: "claude", model: "claude-3-7-sonnet" });
|
|
13928
|
+
} else if (valLower.includes("cursor") || valLower.includes("anysphere")) {
|
|
13929
|
+
trailers.push({ token, value, provider: "cursor", model: "claude-3-5-sonnet" });
|
|
13930
|
+
} else if (valLower.includes("aider")) {
|
|
13931
|
+
trailers.push({ token, value, provider: "aider", model: "claude-3-5-sonnet" });
|
|
13932
|
+
} else if (valLower.includes("windsurf") || valLower.includes("codeium")) {
|
|
13933
|
+
trailers.push({ token, value, provider: "windsurf", model: "claude-3-5-sonnet" });
|
|
13934
|
+
} else if (valLower.includes("antigravity") || valLower.includes("gemini")) {
|
|
13935
|
+
trailers.push({ token, value, provider: "antigravity", model: "claude-sonnet-4-6-thinking" });
|
|
13936
|
+
}
|
|
13937
|
+
}
|
|
13938
|
+
}
|
|
13939
|
+
return trailers;
|
|
13940
|
+
}
|
|
13941
|
+
function detectProviderFromCommit(commitMessage) {
|
|
13942
|
+
if (!commitMessage)
|
|
13943
|
+
return null;
|
|
13944
|
+
const trailers = parseGitTrailers(commitMessage);
|
|
13945
|
+
if (trailers.length > 0) {
|
|
13946
|
+
const primary = trailers[0];
|
|
13947
|
+
return {
|
|
13948
|
+
provider: primary.provider === "claude" ? "anthropic" : primary.provider,
|
|
13949
|
+
model: primary.model,
|
|
13950
|
+
confidence: 0.9,
|
|
13951
|
+
mode: "observed"
|
|
13952
|
+
};
|
|
13953
|
+
}
|
|
13954
|
+
const msg = commitMessage.toLowerCase();
|
|
13955
|
+
if (msg.includes("claude") || msg.includes("anthropic")) {
|
|
13956
|
+
return {
|
|
13957
|
+
provider: "anthropic",
|
|
13958
|
+
model: "claude-3-7-sonnet",
|
|
13959
|
+
confidence: 0.8,
|
|
13960
|
+
mode: "observed"
|
|
13961
|
+
};
|
|
13962
|
+
}
|
|
13963
|
+
if (msg.includes("antigravity")) {
|
|
13964
|
+
return {
|
|
13965
|
+
provider: "antigravity",
|
|
13966
|
+
model: "claude-sonnet-4-6-thinking",
|
|
13967
|
+
confidence: 0.8,
|
|
13968
|
+
mode: "observed"
|
|
13969
|
+
};
|
|
13970
|
+
}
|
|
13971
|
+
if (msg.includes("gemini")) {
|
|
13972
|
+
return {
|
|
13973
|
+
provider: "google",
|
|
13974
|
+
model: "gemini-3-8-flash",
|
|
13975
|
+
confidence: 0.8,
|
|
13976
|
+
mode: "observed"
|
|
13977
|
+
};
|
|
13978
|
+
}
|
|
13979
|
+
if (msg.includes("cursor")) {
|
|
13980
|
+
return {
|
|
13981
|
+
provider: "cursor",
|
|
13982
|
+
model: "claude-3-5-sonnet",
|
|
13983
|
+
confidence: 0.8,
|
|
13984
|
+
mode: "observed"
|
|
13985
|
+
};
|
|
13986
|
+
}
|
|
13987
|
+
if (msg.includes("aider")) {
|
|
13988
|
+
return {
|
|
13989
|
+
provider: "aider",
|
|
13990
|
+
model: "claude-3-5-sonnet",
|
|
13991
|
+
confidence: 0.8,
|
|
13992
|
+
mode: "observed"
|
|
13993
|
+
};
|
|
13994
|
+
}
|
|
13995
|
+
if (msg.includes("windsurf")) {
|
|
13996
|
+
return {
|
|
13997
|
+
provider: "windsurf",
|
|
13998
|
+
model: "claude-3-5-sonnet",
|
|
13999
|
+
confidence: 0.8,
|
|
14000
|
+
mode: "observed"
|
|
14001
|
+
};
|
|
14002
|
+
}
|
|
14003
|
+
if (msg.includes("copilot") || msg.includes("github-actions")) {
|
|
14004
|
+
return {
|
|
14005
|
+
provider: "copilot",
|
|
14006
|
+
model: "gpt-4o",
|
|
14007
|
+
confidence: 0.8,
|
|
14008
|
+
mode: "observed"
|
|
14009
|
+
};
|
|
14010
|
+
}
|
|
14011
|
+
return null;
|
|
14012
|
+
}
|
|
14013
|
+
function harvestTrailerFootprints(repoPath, commitMessage, headSha, commitDate) {
|
|
14014
|
+
if (!commitMessage)
|
|
14015
|
+
return [];
|
|
14016
|
+
const trailers = parseGitTrailers(commitMessage);
|
|
14017
|
+
const footprints = [];
|
|
14018
|
+
const dateIso = commitDate ? commitDate instanceof Date ? commitDate.toISOString() : new Date(commitDate).toISOString() : (/* @__PURE__ */ new Date()).toISOString();
|
|
14019
|
+
for (const t2 of trailers) {
|
|
14020
|
+
const rateCard = getRateCard(t2.model);
|
|
14021
|
+
const estInput = 5e3;
|
|
14022
|
+
const estCached = 2500;
|
|
14023
|
+
const estOutput = 600;
|
|
14024
|
+
const cost = computeCost(estInput, estOutput, estCached, rateCard);
|
|
14025
|
+
footprints.push({
|
|
14026
|
+
id: `trailer_${t2.provider}_${(headSha || "head").slice(0, 8)}`,
|
|
14027
|
+
platform: t2.provider,
|
|
14028
|
+
sessionId: `commit_trailer_${t2.provider}`,
|
|
14029
|
+
repoPath,
|
|
14030
|
+
taskTitle: `Commit Trailer (${t2.token}: ${t2.value.slice(0, 30)})`,
|
|
14031
|
+
model: t2.model,
|
|
14032
|
+
stepsCount: 1,
|
|
14033
|
+
filesEdited: [],
|
|
14034
|
+
timestamp: dateIso,
|
|
14035
|
+
boundCommitSha: headSha,
|
|
14036
|
+
tokens: {
|
|
14037
|
+
input: estInput,
|
|
14038
|
+
output: estOutput,
|
|
14039
|
+
cached: estCached
|
|
14040
|
+
},
|
|
14041
|
+
cost,
|
|
14042
|
+
mode: "observed",
|
|
14043
|
+
confidence: 0.9
|
|
14044
|
+
});
|
|
14045
|
+
}
|
|
14046
|
+
return footprints;
|
|
14047
|
+
}
|
|
14048
|
+
|
|
14049
|
+
// ../core/dist/harvester/antigravity.js
|
|
14050
|
+
var fs2 = __toESM(require("fs"), 1);
|
|
14051
|
+
var path3 = __toESM(require("path"), 1);
|
|
14052
|
+
var os2 = __toESM(require("os"), 1);
|
|
14053
|
+
var import_node_module = require("module");
|
|
14054
|
+
|
|
13869
14055
|
// ../core/dist/harvester/scoring.js
|
|
13870
14056
|
function normalizeFilePath(filePath, repoPath) {
|
|
13871
14057
|
let p2 = filePath.replace(/\\/g, "/").trim();
|
|
@@ -14003,8 +14189,8 @@ function harvestAntigravityFootprints(repoPath, sinceDate) {
|
|
|
14003
14189
|
const DatabaseSync2 = getSqliteDatabase();
|
|
14004
14190
|
if (!DatabaseSync2)
|
|
14005
14191
|
return footprints;
|
|
14006
|
-
const
|
|
14007
|
-
const antigravityDir = process.env.ANTIGRAVITY_APP_DATA_DIR || path3.join(
|
|
14192
|
+
const homedir7 = os2.homedir();
|
|
14193
|
+
const antigravityDir = process.env.ANTIGRAVITY_APP_DATA_DIR || path3.join(homedir7, ".gemini", "antigravity");
|
|
14008
14194
|
const dbPath = path3.join(antigravityDir, "conversation_summaries.db");
|
|
14009
14195
|
if (!fs2.existsSync(dbPath)) {
|
|
14010
14196
|
return footprints;
|
|
@@ -14116,8 +14302,8 @@ var path4 = __toESM(require("path"), 1);
|
|
|
14116
14302
|
var os3 = __toESM(require("os"), 1);
|
|
14117
14303
|
function harvestClaudeFootprints(repoPath, projectAlias, sinceDate) {
|
|
14118
14304
|
const footprints = [];
|
|
14119
|
-
const
|
|
14120
|
-
const claudeProjectsDir = path4.join(
|
|
14305
|
+
const homedir7 = os3.homedir();
|
|
14306
|
+
const claudeProjectsDir = path4.join(homedir7, ".claude", "projects");
|
|
14121
14307
|
if (!fs3.existsSync(claudeProjectsDir)) {
|
|
14122
14308
|
return footprints;
|
|
14123
14309
|
}
|
|
@@ -14452,13 +14638,116 @@ function harvestCursorFootprints(repoPath, sinceDate) {
|
|
|
14452
14638
|
return footprints;
|
|
14453
14639
|
}
|
|
14454
14640
|
|
|
14455
|
-
// ../core/dist/
|
|
14456
|
-
var import_node_module3 = require("module");
|
|
14457
|
-
var path6 = __toESM(require("path"), 1);
|
|
14641
|
+
// ../core/dist/harvester/aider.js
|
|
14458
14642
|
var fs5 = __toESM(require("fs"), 1);
|
|
14643
|
+
var path6 = __toESM(require("path"), 1);
|
|
14644
|
+
function harvestAiderFootprints(repoPath, sinceDate) {
|
|
14645
|
+
const footprints = [];
|
|
14646
|
+
const historyPath = path6.join(repoPath, ".aider.chat.history.md");
|
|
14647
|
+
if (!fs5.existsSync(historyPath)) {
|
|
14648
|
+
return footprints;
|
|
14649
|
+
}
|
|
14650
|
+
try {
|
|
14651
|
+
const stat = fs5.statSync(historyPath);
|
|
14652
|
+
if (sinceDate && stat.mtime < sinceDate) {
|
|
14653
|
+
return footprints;
|
|
14654
|
+
}
|
|
14655
|
+
const content = fs5.readFileSync(historyPath, "utf-8");
|
|
14656
|
+
const sessionChunks = content.split(/^#\s+aider chat started at\s+/m);
|
|
14657
|
+
for (let i2 = 1; i2 < sessionChunks.length; i2++) {
|
|
14658
|
+
const chunk = sessionChunks[i2];
|
|
14659
|
+
const firstNewline = chunk.indexOf("\n");
|
|
14660
|
+
const dateStr = firstNewline !== -1 ? chunk.slice(0, firstNewline).trim() : chunk.slice(0, 30).trim();
|
|
14661
|
+
const sessionDate = new Date(dateStr);
|
|
14662
|
+
if (sinceDate && !isNaN(sessionDate.getTime()) && sessionDate < sinceDate) {
|
|
14663
|
+
continue;
|
|
14664
|
+
}
|
|
14665
|
+
const timestamp = !isNaN(sessionDate.getTime()) ? sessionDate.toISOString() : stat.mtime.toISOString();
|
|
14666
|
+
const lines = chunk.split("\n");
|
|
14667
|
+
let taskTitle = "";
|
|
14668
|
+
let model = "claude-3-5-sonnet";
|
|
14669
|
+
let boundCommitSha;
|
|
14670
|
+
const filesEdited = /* @__PURE__ */ new Set();
|
|
14671
|
+
let stepCount = 0;
|
|
14672
|
+
let reportedInputTokens = 0;
|
|
14673
|
+
let reportedOutputTokens = 0;
|
|
14674
|
+
let reportedCost = 0;
|
|
14675
|
+
for (const line of lines) {
|
|
14676
|
+
const trimmed2 = line.trim();
|
|
14677
|
+
const modelMatch = trimmed2.match(/^(?:Main\s+)?model:\s*([^\s,]+)/i);
|
|
14678
|
+
if (modelMatch && modelMatch[1]) {
|
|
14679
|
+
model = modelMatch[1].replace(/[`"']/g, "").trim();
|
|
14680
|
+
}
|
|
14681
|
+
if (!taskTitle && trimmed2.startsWith("#### ")) {
|
|
14682
|
+
const query = trimmed2.replace(/^####\s+/, "").trim();
|
|
14683
|
+
if (query && !query.startsWith("/") && !query.startsWith("add ") && !query.startsWith("drop ")) {
|
|
14684
|
+
taskTitle = query.slice(0, 60);
|
|
14685
|
+
}
|
|
14686
|
+
}
|
|
14687
|
+
if (trimmed2.startsWith("#### ") || trimmed2.startsWith("> Applied edit to") || trimmed2.startsWith("> Commit ")) {
|
|
14688
|
+
stepCount++;
|
|
14689
|
+
}
|
|
14690
|
+
const editMatch = trimmed2.match(/^>\s*(?:Applied edit to|Wrote|Updated)\s+([^\s]+)/i);
|
|
14691
|
+
if (editMatch && editMatch[1]) {
|
|
14692
|
+
filesEdited.add(normalizeFilePath(editMatch[1], repoPath));
|
|
14693
|
+
}
|
|
14694
|
+
const commitMatch = trimmed2.match(/^>\s*Commit\s+([a-f0-9]{7,40})/i);
|
|
14695
|
+
if (commitMatch && commitMatch[1]) {
|
|
14696
|
+
boundCommitSha = commitMatch[1];
|
|
14697
|
+
}
|
|
14698
|
+
const tokenMatch = trimmed2.match(/Tokens:\s*([0-9\.]+)k?\s*sent,\s*([0-9\.]+)k?\s*received/i);
|
|
14699
|
+
if (tokenMatch && tokenMatch[1] && tokenMatch[2]) {
|
|
14700
|
+
const sentMult = trimmed2.includes(tokenMatch[1] + "k") ? 1e3 : 1;
|
|
14701
|
+
const recvMult = trimmed2.includes(tokenMatch[2] + "k") ? 1e3 : 1;
|
|
14702
|
+
reportedInputTokens += Math.round(parseFloat(tokenMatch[1]) * sentMult);
|
|
14703
|
+
reportedOutputTokens += Math.round(parseFloat(tokenMatch[2]) * recvMult);
|
|
14704
|
+
}
|
|
14705
|
+
const costMatch = trimmed2.match(/Cost:\s*\$([0-9\.]+)\s*(?:message|session)/i);
|
|
14706
|
+
if (costMatch && costMatch[1]) {
|
|
14707
|
+
reportedCost = Math.max(reportedCost, parseFloat(costMatch[1]));
|
|
14708
|
+
}
|
|
14709
|
+
}
|
|
14710
|
+
if (stepCount > 0 || filesEdited.size > 0) {
|
|
14711
|
+
const rateCard = getRateCard(model);
|
|
14712
|
+
const estInput = reportedInputTokens > 0 ? reportedInputTokens : Math.max(stepCount * 2500, 3e3);
|
|
14713
|
+
const estCached = Math.round(estInput * 0.5);
|
|
14714
|
+
const estOutput = reportedOutputTokens > 0 ? reportedOutputTokens : Math.max(stepCount * 350, 400);
|
|
14715
|
+
const cost = reportedCost > 0 ? reportedCost : computeCost(estInput, estOutput, estCached, rateCard);
|
|
14716
|
+
footprints.push({
|
|
14717
|
+
id: `aider_${i2}_${timestamp.slice(0, 10)}`,
|
|
14718
|
+
platform: "aider",
|
|
14719
|
+
sessionId: `aider_session_${i2}`,
|
|
14720
|
+
repoPath,
|
|
14721
|
+
taskTitle: taskTitle || "Aider Pairing Session",
|
|
14722
|
+
model,
|
|
14723
|
+
stepsCount: Math.max(stepCount, 1),
|
|
14724
|
+
filesEdited: Array.from(filesEdited),
|
|
14725
|
+
timestamp,
|
|
14726
|
+
boundCommitSha,
|
|
14727
|
+
tokens: {
|
|
14728
|
+
input: estInput,
|
|
14729
|
+
output: estOutput,
|
|
14730
|
+
cached: estCached
|
|
14731
|
+
},
|
|
14732
|
+
cost,
|
|
14733
|
+
mode: reportedInputTokens > 0 ? "verified" : "imported",
|
|
14734
|
+
confidence: boundCommitSha ? 0.95 : 0.85,
|
|
14735
|
+
rawTranscriptPath: historyPath
|
|
14736
|
+
});
|
|
14737
|
+
}
|
|
14738
|
+
}
|
|
14739
|
+
} catch {
|
|
14740
|
+
}
|
|
14741
|
+
return footprints;
|
|
14742
|
+
}
|
|
14743
|
+
|
|
14744
|
+
// ../core/dist/harvester/windsurf.js
|
|
14745
|
+
var fs6 = __toESM(require("fs"), 1);
|
|
14746
|
+
var path7 = __toESM(require("path"), 1);
|
|
14459
14747
|
var os5 = __toESM(require("os"), 1);
|
|
14748
|
+
var import_node_module3 = require("module");
|
|
14460
14749
|
var import_meta3 = {};
|
|
14461
|
-
function
|
|
14750
|
+
function getSqliteDatabase3() {
|
|
14462
14751
|
try {
|
|
14463
14752
|
const mod = "node:sqlite";
|
|
14464
14753
|
if (typeof require !== "undefined") {
|
|
@@ -14474,6 +14763,128 @@ function getDatabaseSyncClass() {
|
|
|
14474
14763
|
return null;
|
|
14475
14764
|
}
|
|
14476
14765
|
}
|
|
14766
|
+
function harvestWindsurfFootprints(repoPath, sinceDate) {
|
|
14767
|
+
const footprints = [];
|
|
14768
|
+
const DatabaseSync2 = getSqliteDatabase3();
|
|
14769
|
+
if (!DatabaseSync2)
|
|
14770
|
+
return footprints;
|
|
14771
|
+
const normTarget = repoPath.toLowerCase().replace(/\\/g, "/").replace(/\/$/, "");
|
|
14772
|
+
const targetBasename = path7.basename(repoPath).toLowerCase();
|
|
14773
|
+
let storageDir = "";
|
|
14774
|
+
if (process.platform === "win32") {
|
|
14775
|
+
storageDir = path7.join(process.env.APPDATA || path7.join(os5.homedir(), "AppData", "Roaming"), "Windsurf", "User", "workspaceStorage");
|
|
14776
|
+
} else if (process.platform === "darwin") {
|
|
14777
|
+
storageDir = path7.join(os5.homedir(), "Library", "Application Support", "Windsurf", "User", "workspaceStorage");
|
|
14778
|
+
} else {
|
|
14779
|
+
storageDir = path7.join(os5.homedir(), ".config", "Windsurf", "User", "workspaceStorage");
|
|
14780
|
+
}
|
|
14781
|
+
if (!fs6.existsSync(storageDir))
|
|
14782
|
+
return footprints;
|
|
14783
|
+
try {
|
|
14784
|
+
const wsDirs = fs6.readdirSync(storageDir);
|
|
14785
|
+
for (const ws of wsDirs) {
|
|
14786
|
+
const wsPath = path7.join(storageDir, ws);
|
|
14787
|
+
const wsJsonPath = path7.join(wsPath, "workspace.json");
|
|
14788
|
+
if (!fs6.existsSync(wsJsonPath))
|
|
14789
|
+
continue;
|
|
14790
|
+
try {
|
|
14791
|
+
const wsJson = JSON.parse(fs6.readFileSync(wsJsonPath, "utf-8"));
|
|
14792
|
+
let folderUri = wsJson.folder || wsJson.workspace || "";
|
|
14793
|
+
try {
|
|
14794
|
+
folderUri = decodeURIComponent(folderUri.replace(/^file:\/\/\/?/, ""));
|
|
14795
|
+
} catch {
|
|
14796
|
+
}
|
|
14797
|
+
const folder = folderUri.toLowerCase().replace(/\\/g, "/");
|
|
14798
|
+
if (!folder.includes(normTarget) && !normTarget.includes(folder) && !folder.endsWith(targetBasename)) {
|
|
14799
|
+
continue;
|
|
14800
|
+
}
|
|
14801
|
+
const dbFile = path7.join(wsPath, "state.vscdb");
|
|
14802
|
+
if (!fs6.existsSync(dbFile))
|
|
14803
|
+
continue;
|
|
14804
|
+
const dbStat = fs6.statSync(dbFile);
|
|
14805
|
+
if (sinceDate && dbStat.mtime < sinceDate)
|
|
14806
|
+
continue;
|
|
14807
|
+
const db = new DatabaseSync2(dbFile, { readOnly: true });
|
|
14808
|
+
const rows = db.prepare("SELECT key, value FROM ItemTable WHERE key LIKE '%cascade%' OR key LIKE '%codeium%' LIMIT 5").all();
|
|
14809
|
+
if (rows && rows.length > 0) {
|
|
14810
|
+
let stepCount = 0;
|
|
14811
|
+
let taskTitle = "";
|
|
14812
|
+
let model = "claude-3-5-sonnet";
|
|
14813
|
+
const filesEditedSet = /* @__PURE__ */ new Set();
|
|
14814
|
+
for (const row of rows) {
|
|
14815
|
+
try {
|
|
14816
|
+
const parsed = JSON.parse(row.value);
|
|
14817
|
+
if (Array.isArray(parsed)) {
|
|
14818
|
+
stepCount += parsed.length;
|
|
14819
|
+
} else if (parsed && typeof parsed === "object") {
|
|
14820
|
+
if (parsed.steps || parsed.messages) {
|
|
14821
|
+
stepCount += (parsed.steps || parsed.messages).length;
|
|
14822
|
+
}
|
|
14823
|
+
if (parsed.title)
|
|
14824
|
+
taskTitle = String(parsed.title);
|
|
14825
|
+
if (parsed.model)
|
|
14826
|
+
model = String(parsed.model);
|
|
14827
|
+
}
|
|
14828
|
+
} catch {
|
|
14829
|
+
}
|
|
14830
|
+
}
|
|
14831
|
+
const count = Math.max(stepCount, 1);
|
|
14832
|
+
const rateCard = getRateCard(model);
|
|
14833
|
+
const estInput = count * 2500;
|
|
14834
|
+
const estCached = Math.round(estInput * 0.6);
|
|
14835
|
+
const estOutput = count * 300;
|
|
14836
|
+
const cost = computeCost(estInput, estOutput, estCached, rateCard);
|
|
14837
|
+
footprints.push({
|
|
14838
|
+
id: `windsurf_${ws}`,
|
|
14839
|
+
platform: "windsurf",
|
|
14840
|
+
sessionId: ws,
|
|
14841
|
+
repoPath,
|
|
14842
|
+
taskTitle: taskTitle || "Windsurf Cascade Session",
|
|
14843
|
+
model,
|
|
14844
|
+
stepsCount: count,
|
|
14845
|
+
filesEdited: Array.from(filesEditedSet),
|
|
14846
|
+
timestamp: dbStat.mtime.toISOString(),
|
|
14847
|
+
tokens: {
|
|
14848
|
+
input: estInput,
|
|
14849
|
+
output: estOutput,
|
|
14850
|
+
cached: estCached
|
|
14851
|
+
},
|
|
14852
|
+
cost,
|
|
14853
|
+
mode: "imported",
|
|
14854
|
+
confidence: 0.85,
|
|
14855
|
+
rawTranscriptPath: dbFile
|
|
14856
|
+
});
|
|
14857
|
+
}
|
|
14858
|
+
} catch {
|
|
14859
|
+
}
|
|
14860
|
+
}
|
|
14861
|
+
} catch {
|
|
14862
|
+
}
|
|
14863
|
+
return footprints;
|
|
14864
|
+
}
|
|
14865
|
+
|
|
14866
|
+
// ../core/dist/db.js
|
|
14867
|
+
var import_node_module4 = require("module");
|
|
14868
|
+
var path8 = __toESM(require("path"), 1);
|
|
14869
|
+
var fs7 = __toESM(require("fs"), 1);
|
|
14870
|
+
var os6 = __toESM(require("os"), 1);
|
|
14871
|
+
var import_meta4 = {};
|
|
14872
|
+
function getDatabaseSyncClass() {
|
|
14873
|
+
try {
|
|
14874
|
+
const mod = "node:sqlite";
|
|
14875
|
+
if (typeof require !== "undefined") {
|
|
14876
|
+
return require(mod).DatabaseSync;
|
|
14877
|
+
}
|
|
14878
|
+
} catch {
|
|
14879
|
+
}
|
|
14880
|
+
try {
|
|
14881
|
+
const mod = "node:sqlite";
|
|
14882
|
+
const req = (0, import_node_module4.createRequire)(import_meta4.url);
|
|
14883
|
+
return req(mod).DatabaseSync;
|
|
14884
|
+
} catch {
|
|
14885
|
+
return null;
|
|
14886
|
+
}
|
|
14887
|
+
}
|
|
14477
14888
|
var DatabaseSync = getDatabaseSyncClass();
|
|
14478
14889
|
var LocalStateDB = class {
|
|
14479
14890
|
db;
|
|
@@ -14485,11 +14896,11 @@ var LocalStateDB = class {
|
|
|
14485
14896
|
if (inMemory || process.env.CI === "true" || process.env.QODEWK_NO_DB === "true") {
|
|
14486
14897
|
this.db = new DatabaseSync(":memory:");
|
|
14487
14898
|
} else {
|
|
14488
|
-
const qodewkDir =
|
|
14489
|
-
if (!
|
|
14490
|
-
|
|
14899
|
+
const qodewkDir = path8.join(os6.homedir(), ".qodewk");
|
|
14900
|
+
if (!fs7.existsSync(qodewkDir)) {
|
|
14901
|
+
fs7.mkdirSync(qodewkDir, { recursive: true });
|
|
14491
14902
|
}
|
|
14492
|
-
const dbPath =
|
|
14903
|
+
const dbPath = path8.join(qodewkDir, "state.db");
|
|
14493
14904
|
this.db = new DatabaseSync(dbPath);
|
|
14494
14905
|
}
|
|
14495
14906
|
this.migrate();
|
|
@@ -14681,6 +15092,18 @@ async function harvestUniversalFootprints(options) {
|
|
|
14681
15092
|
const cursorFootprints = harvestCursorFootprints(options.repoPath, sinceDate);
|
|
14682
15093
|
allFootprints.push(...cursorFootprints);
|
|
14683
15094
|
}
|
|
15095
|
+
if (!options.platform || options.platform === "all" || options.platform === "aider") {
|
|
15096
|
+
const aiderFootprints = harvestAiderFootprints(options.repoPath, sinceDate);
|
|
15097
|
+
allFootprints.push(...aiderFootprints);
|
|
15098
|
+
}
|
|
15099
|
+
if (!options.platform || options.platform === "all" || options.platform === "windsurf") {
|
|
15100
|
+
const windsurfFootprints = harvestWindsurfFootprints(options.repoPath, sinceDate);
|
|
15101
|
+
allFootprints.push(...windsurfFootprints);
|
|
15102
|
+
}
|
|
15103
|
+
if (options.gitContext?.commitMessage) {
|
|
15104
|
+
const trailerFps = harvestTrailerFootprints(options.repoPath, options.gitContext.commitMessage, options.gitContext.headSha, options.gitContext.commitDate);
|
|
15105
|
+
allFootprints.push(...trailerFps);
|
|
15106
|
+
}
|
|
14684
15107
|
const { primary, rankedFootprints } = selectPrimaryFootprint(allFootprints, options.gitContext);
|
|
14685
15108
|
allFootprints = rankedFootprints;
|
|
14686
15109
|
try {
|
|
@@ -14875,6 +15298,7 @@ async function generateReceipt(options = {}) {
|
|
|
14875
15298
|
gitContext: {
|
|
14876
15299
|
headSha: metrics.headSha,
|
|
14877
15300
|
commitDate: metrics.commitDate,
|
|
15301
|
+
commitMessage: metrics.commitMessage,
|
|
14878
15302
|
changedFiles: metrics.changedFiles,
|
|
14879
15303
|
branch: metrics.branch
|
|
14880
15304
|
}
|
|
@@ -14964,7 +15388,7 @@ async function generateReceipt(options = {}) {
|
|
|
14964
15388
|
}
|
|
14965
15389
|
|
|
14966
15390
|
// src/receipt-view.ts
|
|
14967
|
-
var
|
|
15391
|
+
var fs8 = __toESM(require("fs"), 1);
|
|
14968
15392
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
14969
15393
|
|
|
14970
15394
|
// src/barcode.ts
|
|
@@ -15356,7 +15780,7 @@ async function outputReceipt(receipt, options, publicUrl) {
|
|
|
15356
15780
|
}
|
|
15357
15781
|
if (options.out) {
|
|
15358
15782
|
const fileContent = format === "terminal" ? stripAnsi(content) : content;
|
|
15359
|
-
|
|
15783
|
+
fs8.writeFileSync(options.out, fileContent.endsWith("\n") ? fileContent : fileContent + "\n", "utf-8");
|
|
15360
15784
|
console.log(import_picocolors.default.green(`\u2713 Receipt written to ${options.out}`));
|
|
15361
15785
|
}
|
|
15362
15786
|
if (!options.out) {
|
|
@@ -15369,8 +15793,8 @@ async function outputReceipt(receipt, options, publicUrl) {
|
|
|
15369
15793
|
}
|
|
15370
15794
|
|
|
15371
15795
|
// src/hooks.ts
|
|
15372
|
-
var
|
|
15373
|
-
var
|
|
15796
|
+
var fs9 = __toESM(require("fs"), 1);
|
|
15797
|
+
var path9 = __toESM(require("path"), 1);
|
|
15374
15798
|
var HOOK_MARKER_BEGIN = "# --- BEGIN QODEWK HOOK ---";
|
|
15375
15799
|
var HOOK_MARKER_END = "# --- END QODEWK HOOK ---";
|
|
15376
15800
|
var HOOK_SNIPPET = `
|
|
@@ -15382,37 +15806,37 @@ fi
|
|
|
15382
15806
|
${HOOK_MARKER_END}
|
|
15383
15807
|
`;
|
|
15384
15808
|
function resolveGitHooksDir(cwd = process.cwd()) {
|
|
15385
|
-
const gitPath =
|
|
15386
|
-
if (!
|
|
15809
|
+
const gitPath = path9.join(cwd, ".git");
|
|
15810
|
+
if (!fs9.existsSync(gitPath)) return null;
|
|
15387
15811
|
let gitCommonDir;
|
|
15388
|
-
const stat =
|
|
15812
|
+
const stat = fs9.statSync(gitPath);
|
|
15389
15813
|
if (stat.isDirectory()) {
|
|
15390
15814
|
gitCommonDir = gitPath;
|
|
15391
15815
|
} else {
|
|
15392
|
-
const content =
|
|
15816
|
+
const content = fs9.readFileSync(gitPath, "utf-8");
|
|
15393
15817
|
const match = content.match(/gitdir:\s*(.+)/i);
|
|
15394
15818
|
if (!match?.[1]) return null;
|
|
15395
15819
|
let gitDir = match[1].trim();
|
|
15396
|
-
if (!
|
|
15397
|
-
gitDir =
|
|
15820
|
+
if (!path9.isAbsolute(gitDir)) {
|
|
15821
|
+
gitDir = path9.resolve(cwd, gitDir);
|
|
15398
15822
|
}
|
|
15399
|
-
const commonFile =
|
|
15400
|
-
if (
|
|
15401
|
-
let common =
|
|
15402
|
-
if (!
|
|
15403
|
-
common =
|
|
15823
|
+
const commonFile = path9.join(gitDir, "commondir");
|
|
15824
|
+
if (fs9.existsSync(commonFile)) {
|
|
15825
|
+
let common = fs9.readFileSync(commonFile, "utf-8").trim();
|
|
15826
|
+
if (!path9.isAbsolute(common)) {
|
|
15827
|
+
common = path9.resolve(gitDir, common);
|
|
15404
15828
|
}
|
|
15405
15829
|
gitCommonDir = common;
|
|
15406
|
-
} else if (
|
|
15407
|
-
gitCommonDir =
|
|
15830
|
+
} else if (path9.basename(path9.dirname(gitDir)) === "worktrees") {
|
|
15831
|
+
gitCommonDir = path9.dirname(path9.dirname(gitDir));
|
|
15408
15832
|
} else {
|
|
15409
15833
|
gitCommonDir = gitDir;
|
|
15410
15834
|
}
|
|
15411
15835
|
}
|
|
15412
|
-
return
|
|
15836
|
+
return path9.join(gitCommonDir, "hooks");
|
|
15413
15837
|
}
|
|
15414
15838
|
function checkHookStatus(hooksDir) {
|
|
15415
|
-
if (!hooksDir || !
|
|
15839
|
+
if (!hooksDir || !fs9.existsSync(hooksDir)) {
|
|
15416
15840
|
return {
|
|
15417
15841
|
isGit: Boolean(hooksDir),
|
|
15418
15842
|
hooksDir,
|
|
@@ -15420,12 +15844,12 @@ function checkHookStatus(hooksDir) {
|
|
|
15420
15844
|
postRewriteInstalled: false
|
|
15421
15845
|
};
|
|
15422
15846
|
}
|
|
15423
|
-
const postCommit =
|
|
15424
|
-
const postRewrite =
|
|
15847
|
+
const postCommit = path9.join(hooksDir, "post-commit");
|
|
15848
|
+
const postRewrite = path9.join(hooksDir, "post-rewrite");
|
|
15425
15849
|
const hasHook = (p2) => {
|
|
15426
|
-
if (!
|
|
15850
|
+
if (!fs9.existsSync(p2)) return false;
|
|
15427
15851
|
try {
|
|
15428
|
-
const content =
|
|
15852
|
+
const content = fs9.readFileSync(p2, "utf-8");
|
|
15429
15853
|
return content.includes(HOOK_MARKER_BEGIN);
|
|
15430
15854
|
} catch {
|
|
15431
15855
|
return false;
|
|
@@ -15440,24 +15864,24 @@ function checkHookStatus(hooksDir) {
|
|
|
15440
15864
|
}
|
|
15441
15865
|
function installHookFile(hookFile) {
|
|
15442
15866
|
let content = "";
|
|
15443
|
-
if (
|
|
15444
|
-
content =
|
|
15867
|
+
if (fs9.existsSync(hookFile)) {
|
|
15868
|
+
content = fs9.readFileSync(hookFile, "utf-8");
|
|
15445
15869
|
} else {
|
|
15446
15870
|
content = "#!/bin/sh\n";
|
|
15447
15871
|
}
|
|
15448
15872
|
if (content.includes(HOOK_MARKER_BEGIN)) {
|
|
15449
15873
|
return "exists";
|
|
15450
15874
|
}
|
|
15451
|
-
|
|
15875
|
+
fs9.writeFileSync(hookFile, content + HOOK_SNIPPET, { mode: 493 });
|
|
15452
15876
|
return "installed";
|
|
15453
15877
|
}
|
|
15454
15878
|
function uninstallHookFile(hookFile) {
|
|
15455
|
-
if (!
|
|
15456
|
-
const content =
|
|
15879
|
+
if (!fs9.existsSync(hookFile)) return "absent";
|
|
15880
|
+
const content = fs9.readFileSync(hookFile, "utf-8");
|
|
15457
15881
|
if (!content.includes(HOOK_MARKER_BEGIN)) return "missing";
|
|
15458
15882
|
const regex = new RegExp(`\\n?${HOOK_MARKER_BEGIN}[\\s\\S]*?${HOOK_MARKER_END}\\n?`, "g");
|
|
15459
15883
|
const updated = content.replace(regex, "");
|
|
15460
|
-
|
|
15884
|
+
fs9.writeFileSync(hookFile, updated, { mode: 493 });
|
|
15461
15885
|
return "removed";
|
|
15462
15886
|
}
|
|
15463
15887
|
|
|
@@ -15665,8 +16089,7 @@ async function runInteractiveMenu() {
|
|
|
15665
16089
|
console.log(import_picocolors2.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
15666
16090
|
let defaultBase = "origin/main";
|
|
15667
16091
|
try {
|
|
15668
|
-
|
|
15669
|
-
defaultBase = await detectDefaultBaseBranch(simpleGit2(process.cwd()));
|
|
16092
|
+
defaultBase = await detectDefaultBaseBranch(process.cwd());
|
|
15670
16093
|
} catch {
|
|
15671
16094
|
}
|
|
15672
16095
|
const base = await askLine(
|
|
@@ -15787,19 +16210,19 @@ async function runInteractiveMenu() {
|
|
|
15787
16210
|
const choice = await askLine(" \u203A Select option [0-2]: ");
|
|
15788
16211
|
if (choice === "1") {
|
|
15789
16212
|
if (status.hooksDir) {
|
|
15790
|
-
const
|
|
16213
|
+
const path11 = await import("path");
|
|
15791
16214
|
const targets = ["post-commit", "post-rewrite"];
|
|
15792
16215
|
for (const t2 of targets) {
|
|
15793
|
-
installHookFile(
|
|
16216
|
+
installHookFile(path11.join(status.hooksDir, t2));
|
|
15794
16217
|
}
|
|
15795
16218
|
console.log(colors.green("\n [\u2713] Non-blocking hooks installed successfully."));
|
|
15796
16219
|
}
|
|
15797
16220
|
} else if (choice === "2") {
|
|
15798
16221
|
if (status.hooksDir) {
|
|
15799
|
-
const
|
|
16222
|
+
const path11 = await import("path");
|
|
15800
16223
|
const targets = ["post-commit", "post-rewrite"];
|
|
15801
16224
|
for (const t2 of targets) {
|
|
15802
|
-
uninstallHookFile(
|
|
16225
|
+
uninstallHookFile(path11.join(status.hooksDir, t2));
|
|
15803
16226
|
}
|
|
15804
16227
|
console.log(colors.green("\n [\u2713] Qodewk hooks removed."));
|
|
15805
16228
|
}
|
|
@@ -15896,14 +16319,14 @@ async function runInteractiveMenu() {
|
|
|
15896
16319
|
var SHARE_PAYLOAD_MAX_BYTES2 = 5e4;
|
|
15897
16320
|
function resolveCliVersion() {
|
|
15898
16321
|
try {
|
|
15899
|
-
const argv1 = process.argv[1] ?
|
|
16322
|
+
const argv1 = process.argv[1] ? path10.dirname(path10.resolve(process.argv[1])) : process.cwd();
|
|
15900
16323
|
const candidates = [
|
|
15901
|
-
|
|
15902
|
-
|
|
16324
|
+
path10.join(argv1, "..", "package.json"),
|
|
16325
|
+
path10.join(argv1, "package.json")
|
|
15903
16326
|
];
|
|
15904
16327
|
for (const candidate of candidates) {
|
|
15905
|
-
if (!
|
|
15906
|
-
const pkg = JSON.parse(
|
|
16328
|
+
if (!fs10.existsSync(candidate)) continue;
|
|
16329
|
+
const pkg = JSON.parse(fs10.readFileSync(candidate, "utf-8"));
|
|
15907
16330
|
if (pkg.name === "qodewk" && pkg.version) return pkg.version;
|
|
15908
16331
|
}
|
|
15909
16332
|
} catch {
|
|
@@ -15922,7 +16345,7 @@ function persistReceipt(receipt, claimToken) {
|
|
|
15922
16345
|
}
|
|
15923
16346
|
}
|
|
15924
16347
|
var program2 = new Command();
|
|
15925
|
-
program2.name("qodewk").description("Universal telemetry and digital receipt generator for the AI coding agent era").version(resolveCliVersion()).option("-i, --interactive", "Launch interactive terminal control panel").option("--menu", "Launch interactive terminal control panel").option("-j, --json", "Output receipt in machine-readable JSON format").option("-f, --format <format>", "Output format (terminal, json, markdown)", "terminal").option("-o, --out <path>", "Write receipt output to specified file path").option("-p, --provider <provider>", "Specify AI provider (antigravity, claude, cursor, etc.)").option("-m, --model <model>", "Specify AI model identifier").option("-s, --since <duration>", "Harvest agent footprints since duration (e.g. today, 24h, 7d)").option("--today", "Harvest agent footprints for today").option("--platform <platform>", "Filter agent platform (antigravity, claude, cursor, all)").option("--anon", "Anonymize branch name in output").option("--local", "Force local-only mode (never open network sockets)").option("--barcode", "Render classic 1D thermal barcode (always on; kept for compatibility)").action(async (options) => {
|
|
16348
|
+
program2.name("qodewk").description("Universal telemetry and digital receipt generator for the AI coding agent era").version(resolveCliVersion()).option("-i, --interactive", "Launch interactive terminal control panel").option("--menu", "Launch interactive terminal control panel").option("-j, --json", "Output receipt in machine-readable JSON format").option("-f, --format <format>", "Output format (terminal, json, markdown)", "terminal").option("-o, --out <path>", "Write receipt output to specified file path").option("-p, --provider <provider>", "Specify AI provider (antigravity, claude, cursor, etc.)").option("-m, --model <model>", "Specify AI model identifier").option("-s, --since <duration>", "Harvest agent footprints since duration (e.g. today, 24h, 7d)").option("--today", "Harvest agent footprints for today").option("--platform <platform>", "Filter agent platform (antigravity, claude, cursor, all)").option("--anon", "Anonymize branch name in output").option("--local", "Force local-only mode (never open network sockets)").option("--barcode", "Render classic 1D thermal barcode (always on; kept for compatibility)").option("--notes", "Persist receipt into local Git note (refs/notes/qodewk)").action(async (options) => {
|
|
15926
16349
|
if (options.interactive || options.menu) {
|
|
15927
16350
|
await runInteractiveMenu();
|
|
15928
16351
|
return;
|
|
@@ -15937,6 +16360,14 @@ program2.name("qodewk").description("Universal telemetry and digital receipt gen
|
|
|
15937
16360
|
isPublic: false
|
|
15938
16361
|
});
|
|
15939
16362
|
persistReceipt(receipt);
|
|
16363
|
+
if (options.notes) {
|
|
16364
|
+
try {
|
|
16365
|
+
await writeGitReceiptNote(receipt.repository.headSha, receipt);
|
|
16366
|
+
console.log(import_picocolors3.default.green(`\u2713 Attached receipt note to ${receipt.repository.headSha.slice(0, 7)} (refs/notes/qodewk)`));
|
|
16367
|
+
} catch (noteErr) {
|
|
16368
|
+
console.warn(import_picocolors3.default.yellow(`Warning: Could not write Git note: ${noteErr.message}`));
|
|
16369
|
+
}
|
|
16370
|
+
}
|
|
15940
16371
|
await outputReceipt(receipt, options);
|
|
15941
16372
|
} catch (err) {
|
|
15942
16373
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -16061,14 +16492,14 @@ hookCommand.command("install").description("Install non-blocking post-commit and
|
|
|
16061
16492
|
console.error(import_picocolors3.default.red("Error: Current directory is not a Git repository (.git not found)."));
|
|
16062
16493
|
process.exit(1);
|
|
16063
16494
|
}
|
|
16064
|
-
if (!
|
|
16065
|
-
|
|
16495
|
+
if (!fs10.existsSync(hooksDir)) {
|
|
16496
|
+
fs10.mkdirSync(hooksDir, { recursive: true });
|
|
16066
16497
|
}
|
|
16067
16498
|
const targets = ["post-commit", "post-rewrite"];
|
|
16068
16499
|
let installed = 0;
|
|
16069
16500
|
let existing = 0;
|
|
16070
16501
|
for (const name of targets) {
|
|
16071
|
-
const result = installHookFile(
|
|
16502
|
+
const result = installHookFile(path10.join(hooksDir, name));
|
|
16072
16503
|
if (result === "installed") installed++;
|
|
16073
16504
|
else existing++;
|
|
16074
16505
|
}
|
|
@@ -16100,7 +16531,7 @@ hookCommand.command("uninstall").description("Remove Qodewk post-commit and post
|
|
|
16100
16531
|
const targets = ["post-commit", "post-rewrite"];
|
|
16101
16532
|
let removed = 0;
|
|
16102
16533
|
for (const name of targets) {
|
|
16103
|
-
const result = uninstallHookFile(
|
|
16534
|
+
const result = uninstallHookFile(path10.join(hooksDir, name));
|
|
16104
16535
|
if (result === "removed") removed++;
|
|
16105
16536
|
}
|
|
16106
16537
|
if (removed === 0) {
|
|
@@ -16114,4 +16545,53 @@ hookCommand.command("uninstall").description("Remove Qodewk post-commit and post
|
|
|
16114
16545
|
process.exit(1);
|
|
16115
16546
|
}
|
|
16116
16547
|
});
|
|
16548
|
+
var notesCmd = program2.command("notes").description("Manage local Git notes receipts (refs/notes/qodewk)");
|
|
16549
|
+
notesCmd.command("show [commit]").description("Display Qodewk receipt attached to a Git commit note").option("-j, --json", "Output receipt as JSON").action(async (commit = "HEAD", opts) => {
|
|
16550
|
+
try {
|
|
16551
|
+
const receipt = await readGitReceiptNote(commit);
|
|
16552
|
+
if (!receipt) {
|
|
16553
|
+
console.log(import_picocolors3.default.yellow(`No Qodewk receipt note found on commit '${commit}'.`));
|
|
16554
|
+
return;
|
|
16555
|
+
}
|
|
16556
|
+
if (opts.json) {
|
|
16557
|
+
console.log(JSON.stringify(receipt, null, 2));
|
|
16558
|
+
} else {
|
|
16559
|
+
await outputReceipt(receipt, { format: "terminal" });
|
|
16560
|
+
}
|
|
16561
|
+
} catch (err) {
|
|
16562
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
16563
|
+
console.error(import_picocolors3.default.red(`Error reading Git note: ${message}`));
|
|
16564
|
+
process.exit(1);
|
|
16565
|
+
}
|
|
16566
|
+
});
|
|
16567
|
+
notesCmd.command("write [commit]").description("Generate and attach receipt to a Git commit note").action(async (commit = "HEAD") => {
|
|
16568
|
+
try {
|
|
16569
|
+
const receipt = await generateReceipt({ headSha: commit });
|
|
16570
|
+
await writeGitReceiptNote(receipt.repository.headSha, receipt);
|
|
16571
|
+
console.log(
|
|
16572
|
+
import_picocolors3.default.green(`\u2713 Attached receipt note to ${receipt.repository.headSha.slice(0, 7)} (refs/notes/qodewk)`)
|
|
16573
|
+
);
|
|
16574
|
+
} catch (err) {
|
|
16575
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
16576
|
+
console.error(import_picocolors3.default.red(`Error writing Git note: ${message}`));
|
|
16577
|
+
process.exit(1);
|
|
16578
|
+
}
|
|
16579
|
+
});
|
|
16580
|
+
notesCmd.command("list").description("List all commits with attached Qodewk receipts").action(async () => {
|
|
16581
|
+
try {
|
|
16582
|
+
const shas = await listGitReceiptNotes();
|
|
16583
|
+
if (shas.length === 0) {
|
|
16584
|
+
console.log(import_picocolors3.default.yellow("No Qodewk Git notes found in repository."));
|
|
16585
|
+
return;
|
|
16586
|
+
}
|
|
16587
|
+
console.log(import_picocolors3.default.bold(`Found ${shas.length} commit note(s) in refs/notes/qodewk:`));
|
|
16588
|
+
for (const sha of shas) {
|
|
16589
|
+
console.log(` ${import_picocolors3.default.cyan(sha.slice(0, 10))} ${import_picocolors3.default.dim(sha)}`);
|
|
16590
|
+
}
|
|
16591
|
+
} catch (err) {
|
|
16592
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
16593
|
+
console.error(import_picocolors3.default.red(`Error listing Git notes: ${message}`));
|
|
16594
|
+
process.exit(1);
|
|
16595
|
+
}
|
|
16596
|
+
});
|
|
16117
16597
|
program2.parse(process.argv);
|