codex-wakatime 1.0.1 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.cjs +62 -40
- package/package.json +12 -2
package/README.md
CHANGED
|
@@ -39,6 +39,8 @@ codex-wakatime --install
|
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
This adds `notify = ["codex-wakatime"]` to your `~/.codex/config.toml`.
|
|
42
|
+
If you already have a `notify` command configured, codex-wakatime replaces it
|
|
43
|
+
because Codex supports a single notify command.
|
|
42
44
|
|
|
43
45
|
## How It Works
|
|
44
46
|
|
package/dist/index.cjs
CHANGED
|
@@ -279,16 +279,17 @@ var path7 = __toESM(require("node:path"), 1);
|
|
|
279
279
|
|
|
280
280
|
// src/extractor.ts
|
|
281
281
|
var path = __toESM(require("node:path"), 1);
|
|
282
|
-
var
|
|
282
|
+
var READ_PATTERNS = [
|
|
283
283
|
// Code block headers: ```typescript:src/index.ts or ```ts:src/index.ts
|
|
284
284
|
/```\w*:([^\n`]+)/g,
|
|
285
285
|
// Backtick paths with extension: `src/foo/bar.ts`
|
|
286
286
|
/`([^`\s]+\.\w{1,6})`/g,
|
|
287
|
-
// Action patterns: Read/List/Created/Modified/Updated/Wrote/Edited/Deleted file.ts
|
|
288
|
-
/(?:Read|List|Create|Created|Modify|Modified|Update|Updated|Write|Wrote|Edit|Edited|Delete|Deleted)\s+`?([^\s`\n]+\.\w{1,6})`?/gi,
|
|
289
287
|
// File path in quotes: "src/file.ts" or 'src/file.ts'
|
|
290
|
-
/["']([^"'\s]+\.\w{1,6})["']/g
|
|
288
|
+
/["']([^"'\s]+\.\w{1,6})["']/g,
|
|
289
|
+
// Read action patterns: Read/List file.ts
|
|
290
|
+
/(?:Read|List)\s+`?([^\s`\n]+\.\w{1,6})`?/gi
|
|
291
291
|
];
|
|
292
|
+
var WRITE_PATTERN = /(?:Create|Created|Modify|Modified|Update|Updated|Write|Wrote|Edit|Edited|Delete|Deleted)\s+`?([^\s`\n]+\.\w{1,6})`?/gi;
|
|
292
293
|
function isValidFilePath(p) {
|
|
293
294
|
if (!p || p.length === 0) return false;
|
|
294
295
|
if (p.startsWith("http://") || p.startsWith("https://") || p.includes("://"))
|
|
@@ -306,22 +307,35 @@ function normalizePath(filePath, cwd) {
|
|
|
306
307
|
}
|
|
307
308
|
return path.normalize(path.join(cwd, cleaned));
|
|
308
309
|
}
|
|
309
|
-
function
|
|
310
|
+
function extractFiles(message, cwd) {
|
|
310
311
|
if (!message || message.length === 0) {
|
|
311
312
|
return [];
|
|
312
313
|
}
|
|
313
|
-
const
|
|
314
|
-
|
|
314
|
+
const fileMap = /* @__PURE__ */ new Map();
|
|
315
|
+
WRITE_PATTERN.lastIndex = 0;
|
|
316
|
+
for (const match of message.matchAll(WRITE_PATTERN)) {
|
|
317
|
+
const filePath = match[1];
|
|
318
|
+
if (filePath && isValidFilePath(filePath)) {
|
|
319
|
+
const normalized = normalizePath(filePath, cwd);
|
|
320
|
+
fileMap.set(normalized, true);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
for (const pattern of READ_PATTERNS) {
|
|
315
324
|
pattern.lastIndex = 0;
|
|
316
325
|
for (const match of message.matchAll(pattern)) {
|
|
317
326
|
const filePath = match[1];
|
|
318
327
|
if (filePath && isValidFilePath(filePath)) {
|
|
319
328
|
const normalized = normalizePath(filePath, cwd);
|
|
320
|
-
|
|
329
|
+
if (!fileMap.has(normalized)) {
|
|
330
|
+
fileMap.set(normalized, false);
|
|
331
|
+
}
|
|
321
332
|
}
|
|
322
333
|
}
|
|
323
334
|
}
|
|
324
|
-
return Array.from(
|
|
335
|
+
return Array.from(fileMap.entries()).map(([filePath, isWrite]) => ({
|
|
336
|
+
path: filePath,
|
|
337
|
+
isWrite
|
|
338
|
+
}));
|
|
325
339
|
}
|
|
326
340
|
|
|
327
341
|
// src/install.ts
|
|
@@ -421,20 +435,15 @@ function formatTomlValue(value) {
|
|
|
421
435
|
}
|
|
422
436
|
return String(value);
|
|
423
437
|
}
|
|
424
|
-
function
|
|
425
|
-
if (Array.isArray(value))
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
}
|
|
434
|
-
function removeNotifyEntry(entries, command) {
|
|
435
|
-
return entries.filter(
|
|
436
|
-
(entry) => !(typeof entry === "string" && entry === command)
|
|
437
|
-
);
|
|
438
|
+
function normalizeNotifyCommand(value) {
|
|
439
|
+
if (Array.isArray(value)) {
|
|
440
|
+
const entries = value.filter(
|
|
441
|
+
(entry) => typeof entry === "string" && entry.length > 0
|
|
442
|
+
);
|
|
443
|
+
return entries.length > 0 ? entries : void 0;
|
|
444
|
+
}
|
|
445
|
+
if (typeof value === "string" && value.length > 0) return [value];
|
|
446
|
+
return void 0;
|
|
438
447
|
}
|
|
439
448
|
function getPluginCommand() {
|
|
440
449
|
return ["codex-wakatime"];
|
|
@@ -457,12 +466,17 @@ function installHook() {
|
|
|
457
466
|
}
|
|
458
467
|
}
|
|
459
468
|
const pluginCommand = getPluginCommand()[0];
|
|
460
|
-
const existingNotify =
|
|
461
|
-
if (
|
|
469
|
+
const existingNotify = normalizeNotifyCommand(config.notify);
|
|
470
|
+
if (existingNotify?.[0] === pluginCommand) {
|
|
462
471
|
console.log("codex-wakatime is already configured");
|
|
463
472
|
return;
|
|
464
473
|
}
|
|
465
|
-
|
|
474
|
+
if (existingNotify && existingNotify.length > 0) {
|
|
475
|
+
console.warn(
|
|
476
|
+
"Existing Codex notify command found; replacing with codex-wakatime"
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
config.notify = [pluginCommand];
|
|
466
480
|
const newContent = stringifyToml(config);
|
|
467
481
|
fs.writeFileSync(CODEX_CONFIG_PATH, newContent);
|
|
468
482
|
console.log(`Updated ${CODEX_CONFIG_PATH}`);
|
|
@@ -482,17 +496,12 @@ function uninstallHook() {
|
|
|
482
496
|
const content = fs.readFileSync(CODEX_CONFIG_PATH, "utf-8");
|
|
483
497
|
const config = parseToml(content);
|
|
484
498
|
const pluginCommand = getPluginCommand()[0];
|
|
485
|
-
const existingNotify =
|
|
486
|
-
if (!
|
|
499
|
+
const existingNotify = normalizeNotifyCommand(config.notify);
|
|
500
|
+
if (!existingNotify || existingNotify[0] !== pluginCommand) {
|
|
487
501
|
console.log("codex-wakatime was not configured");
|
|
488
502
|
return;
|
|
489
503
|
}
|
|
490
|
-
|
|
491
|
-
if (updatedNotify.length === 0) {
|
|
492
|
-
delete config.notify;
|
|
493
|
-
} else {
|
|
494
|
-
config.notify = updatedNotify;
|
|
495
|
-
}
|
|
504
|
+
delete config.notify;
|
|
496
505
|
const newContent = stringifyToml(config);
|
|
497
506
|
fs.writeFileSync(CODEX_CONFIG_PATH, newContent);
|
|
498
507
|
console.log("codex-wakatime notification hook removed");
|
|
@@ -647,7 +656,7 @@ var os6 = __toESM(require("node:os"), 1);
|
|
|
647
656
|
var package_default = {
|
|
648
657
|
$schema: "https://json.schemastore.org/package.json",
|
|
649
658
|
name: "codex-wakatime",
|
|
650
|
-
version: "1.
|
|
659
|
+
version: "1.1.1",
|
|
651
660
|
description: "WakaTime plugin for OpenAI Codex CLI - Track AI coding activity and time spent",
|
|
652
661
|
repository: {
|
|
653
662
|
type: "git",
|
|
@@ -671,7 +680,8 @@ var package_default = {
|
|
|
671
680
|
test: "vitest",
|
|
672
681
|
"test:run": "vitest run",
|
|
673
682
|
"test:coverage": "vitest run --coverage",
|
|
674
|
-
prepublishOnly: "npm run build"
|
|
683
|
+
prepublishOnly: "npm run build",
|
|
684
|
+
prepare: "husky"
|
|
675
685
|
},
|
|
676
686
|
keywords: [
|
|
677
687
|
"codex",
|
|
@@ -686,12 +696,16 @@ var package_default = {
|
|
|
686
696
|
license: "MIT",
|
|
687
697
|
devDependencies: {
|
|
688
698
|
"@biomejs/biome": "^2.3.10",
|
|
699
|
+
"@commitlint/cli": "^20.2.0",
|
|
700
|
+
"@commitlint/config-conventional": "^20.2.0",
|
|
689
701
|
"@semantic-release/changelog": "^6.0.3",
|
|
690
702
|
"@semantic-release/git": "^10.0.1",
|
|
691
703
|
"@types/node": "^22.0.0",
|
|
692
704
|
"@types/which": "^3.0.0",
|
|
693
705
|
"@vitest/coverage-v8": "^4.0.16",
|
|
694
706
|
esbuild: "^0.25.0",
|
|
707
|
+
husky: "^9.1.7",
|
|
708
|
+
"lint-staged": "^16.2.7",
|
|
695
709
|
"semantic-release": "^25.0.2",
|
|
696
710
|
typescript: "^5.0.0",
|
|
697
711
|
vitest: "^4.0.16"
|
|
@@ -699,6 +713,11 @@ var package_default = {
|
|
|
699
713
|
dependencies: {
|
|
700
714
|
"@iarna/toml": "^3.0.0",
|
|
701
715
|
which: "^4.0.0"
|
|
716
|
+
},
|
|
717
|
+
"lint-staged": {
|
|
718
|
+
"*.{ts,js,json}": [
|
|
719
|
+
"biome check --write"
|
|
720
|
+
]
|
|
702
721
|
}
|
|
703
722
|
};
|
|
704
723
|
|
|
@@ -1099,16 +1118,19 @@ async function main() {
|
|
|
1099
1118
|
}
|
|
1100
1119
|
const assistantMessage = notification["last-assistant-message"] ?? "";
|
|
1101
1120
|
const cwd = notification.cwd;
|
|
1102
|
-
const files =
|
|
1121
|
+
const files = extractFiles(assistantMessage, cwd);
|
|
1103
1122
|
logger.debug(`Extracted ${files.length} files from message`);
|
|
1104
1123
|
if (files.length > 0) {
|
|
1105
1124
|
for (const file of files) {
|
|
1106
|
-
logger.debug(
|
|
1125
|
+
logger.debug(
|
|
1126
|
+
`Sending heartbeat for file: ${file.path} (isWrite: ${file.isWrite})`
|
|
1127
|
+
);
|
|
1107
1128
|
sendHeartbeat({
|
|
1108
|
-
entity: file,
|
|
1129
|
+
entity: file.path,
|
|
1109
1130
|
entityType: "file",
|
|
1110
1131
|
category: "ai coding",
|
|
1111
|
-
projectFolder: cwd
|
|
1132
|
+
projectFolder: cwd,
|
|
1133
|
+
isWrite: file.isWrite
|
|
1112
1134
|
});
|
|
1113
1135
|
}
|
|
1114
1136
|
} else {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "codex-wakatime",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.1.1",
|
|
5
5
|
"description": "WakaTime plugin for OpenAI Codex CLI - Track AI coding activity and time spent",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"test": "vitest",
|
|
26
26
|
"test:run": "vitest run",
|
|
27
27
|
"test:coverage": "vitest run --coverage",
|
|
28
|
-
"prepublishOnly": "npm run build"
|
|
28
|
+
"prepublishOnly": "npm run build",
|
|
29
|
+
"prepare": "husky"
|
|
29
30
|
},
|
|
30
31
|
"keywords": [
|
|
31
32
|
"codex",
|
|
@@ -40,12 +41,16 @@
|
|
|
40
41
|
"license": "MIT",
|
|
41
42
|
"devDependencies": {
|
|
42
43
|
"@biomejs/biome": "^2.3.10",
|
|
44
|
+
"@commitlint/cli": "^20.2.0",
|
|
45
|
+
"@commitlint/config-conventional": "^20.2.0",
|
|
43
46
|
"@semantic-release/changelog": "^6.0.3",
|
|
44
47
|
"@semantic-release/git": "^10.0.1",
|
|
45
48
|
"@types/node": "^22.0.0",
|
|
46
49
|
"@types/which": "^3.0.0",
|
|
47
50
|
"@vitest/coverage-v8": "^4.0.16",
|
|
48
51
|
"esbuild": "^0.25.0",
|
|
52
|
+
"husky": "^9.1.7",
|
|
53
|
+
"lint-staged": "^16.2.7",
|
|
49
54
|
"semantic-release": "^25.0.2",
|
|
50
55
|
"typescript": "^5.0.0",
|
|
51
56
|
"vitest": "^4.0.16"
|
|
@@ -53,5 +58,10 @@
|
|
|
53
58
|
"dependencies": {
|
|
54
59
|
"@iarna/toml": "^3.0.0",
|
|
55
60
|
"which": "^4.0.0"
|
|
61
|
+
},
|
|
62
|
+
"lint-staged": {
|
|
63
|
+
"*.{ts,js,json}": [
|
|
64
|
+
"biome check --write"
|
|
65
|
+
]
|
|
56
66
|
}
|
|
57
67
|
}
|