codex-wakatime 1.0.0 → 1.1.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/README.md +10 -4
- package/dist/index.cjs +101 -17
- package/package.json +15 -5
package/README.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# codex-wakatime
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/codex-wakatime)
|
|
4
|
+
[](https://www.npmjs.com/package/codex-wakatime)
|
|
5
|
+
[](https://github.com/angristan/codex-wakatime/actions/workflows/workflow.yml)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
WakaTime integration for [OpenAI Codex CLI](https://github.com/openai/codex). Track AI coding activity and time spent.
|
|
9
|
+
|
|
10
|
+
> [!TIP]
|
|
11
|
+
> Also check out [opencode-wakatime](https://github.com/angristan/opencode-wakatime) for OpenCode!
|
|
4
12
|
|
|
5
13
|
## Features
|
|
6
14
|
|
|
@@ -114,7 +122,7 @@ Logs are written to `~/.wakatime/codex.log`.
|
|
|
114
122
|
|
|
115
123
|
```bash
|
|
116
124
|
# Clone the repository
|
|
117
|
-
git clone https://github.com/
|
|
125
|
+
git clone https://github.com/angristan/codex-wakatime
|
|
118
126
|
cd codex-wakatime
|
|
119
127
|
|
|
120
128
|
# Install dependencies
|
|
@@ -148,8 +156,6 @@ codex-wakatime/
|
|
|
148
156
|
│ ├── options.ts # Config parsing
|
|
149
157
|
│ ├── types.ts # TypeScript interfaces
|
|
150
158
|
│ └── __tests__/ # Test files
|
|
151
|
-
├── scripts/
|
|
152
|
-
│ └── generate-version.js
|
|
153
159
|
├── package.json
|
|
154
160
|
├── tsconfig.json
|
|
155
161
|
└── biome.json
|
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: Created/Modified/Updated/Wrote/Edited/Deleted file.ts
|
|
288
|
-
/(?:Created|Modified|Updated|Wrote|Edited|Deleted|Reading|Writing)\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
|
|
@@ -427,7 +441,9 @@ function normalizeNotifyValue(value) {
|
|
|
427
441
|
return [];
|
|
428
442
|
}
|
|
429
443
|
function hasNotifyEntry(entries, command) {
|
|
430
|
-
return entries.some(
|
|
444
|
+
return entries.some(
|
|
445
|
+
(entry) => typeof entry === "string" && entry === command
|
|
446
|
+
);
|
|
431
447
|
}
|
|
432
448
|
function removeNotifyEntry(entries, command) {
|
|
433
449
|
return entries.filter(
|
|
@@ -641,6 +657,73 @@ function updateLastHeartbeat() {
|
|
|
641
657
|
var import_node_child_process = require("node:child_process");
|
|
642
658
|
var os6 = __toESM(require("node:os"), 1);
|
|
643
659
|
|
|
660
|
+
// package.json
|
|
661
|
+
var package_default = {
|
|
662
|
+
$schema: "https://json.schemastore.org/package.json",
|
|
663
|
+
name: "codex-wakatime",
|
|
664
|
+
version: "1.1.0",
|
|
665
|
+
description: "WakaTime plugin for OpenAI Codex CLI - Track AI coding activity and time spent",
|
|
666
|
+
repository: {
|
|
667
|
+
type: "git",
|
|
668
|
+
url: "https://github.com/angristan/codex-wakatime.git"
|
|
669
|
+
},
|
|
670
|
+
type: "module",
|
|
671
|
+
main: "dist/index.cjs",
|
|
672
|
+
types: "dist/index.d.ts",
|
|
673
|
+
bin: {
|
|
674
|
+
"codex-wakatime": "dist/index.cjs"
|
|
675
|
+
},
|
|
676
|
+
files: [
|
|
677
|
+
"dist"
|
|
678
|
+
],
|
|
679
|
+
scripts: {
|
|
680
|
+
build: 'esbuild src/index.ts --bundle --platform=node --format=cjs --outfile=dist/index.cjs --banner:js="#!/usr/bin/env node"',
|
|
681
|
+
typecheck: "tsc --noEmit",
|
|
682
|
+
lint: "biome lint .",
|
|
683
|
+
format: "biome format --write .",
|
|
684
|
+
check: "biome check .",
|
|
685
|
+
test: "vitest",
|
|
686
|
+
"test:run": "vitest run",
|
|
687
|
+
"test:coverage": "vitest run --coverage",
|
|
688
|
+
prepublishOnly: "npm run build",
|
|
689
|
+
prepare: "husky"
|
|
690
|
+
},
|
|
691
|
+
keywords: [
|
|
692
|
+
"codex",
|
|
693
|
+
"openai",
|
|
694
|
+
"wakatime",
|
|
695
|
+
"time-tracking",
|
|
696
|
+
"ai",
|
|
697
|
+
"coding",
|
|
698
|
+
"productivity"
|
|
699
|
+
],
|
|
700
|
+
author: "WakaTime",
|
|
701
|
+
license: "MIT",
|
|
702
|
+
devDependencies: {
|
|
703
|
+
"@biomejs/biome": "^2.3.10",
|
|
704
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
705
|
+
"@semantic-release/git": "^10.0.1",
|
|
706
|
+
"@types/node": "^22.0.0",
|
|
707
|
+
"@types/which": "^3.0.0",
|
|
708
|
+
"@vitest/coverage-v8": "^4.0.16",
|
|
709
|
+
esbuild: "^0.25.0",
|
|
710
|
+
husky: "^9.1.7",
|
|
711
|
+
"lint-staged": "^16.2.7",
|
|
712
|
+
"semantic-release": "^25.0.2",
|
|
713
|
+
typescript: "^5.0.0",
|
|
714
|
+
vitest: "^4.0.16"
|
|
715
|
+
},
|
|
716
|
+
dependencies: {
|
|
717
|
+
"@iarna/toml": "^3.0.0",
|
|
718
|
+
which: "^4.0.0"
|
|
719
|
+
},
|
|
720
|
+
"lint-staged": {
|
|
721
|
+
"*.{ts,js,json}": [
|
|
722
|
+
"biome check --write"
|
|
723
|
+
]
|
|
724
|
+
}
|
|
725
|
+
};
|
|
726
|
+
|
|
644
727
|
// src/dependencies.ts
|
|
645
728
|
var fs5 = __toESM(require("node:fs"), 1);
|
|
646
729
|
var import_node_fs = require("node:fs");
|
|
@@ -913,10 +996,8 @@ var Dependencies = class {
|
|
|
913
996
|
};
|
|
914
997
|
var dependencies = new Dependencies();
|
|
915
998
|
|
|
916
|
-
// src/version.ts
|
|
917
|
-
var VERSION = "1.0.0";
|
|
918
|
-
|
|
919
999
|
// src/wakatime.ts
|
|
1000
|
+
var VERSION = package_default.version;
|
|
920
1001
|
function isWindows() {
|
|
921
1002
|
return os6.platform() === "win32";
|
|
922
1003
|
}
|
|
@@ -1040,16 +1121,19 @@ async function main() {
|
|
|
1040
1121
|
}
|
|
1041
1122
|
const assistantMessage = notification["last-assistant-message"] ?? "";
|
|
1042
1123
|
const cwd = notification.cwd;
|
|
1043
|
-
const files =
|
|
1124
|
+
const files = extractFiles(assistantMessage, cwd);
|
|
1044
1125
|
logger.debug(`Extracted ${files.length} files from message`);
|
|
1045
1126
|
if (files.length > 0) {
|
|
1046
1127
|
for (const file of files) {
|
|
1047
|
-
logger.debug(
|
|
1128
|
+
logger.debug(
|
|
1129
|
+
`Sending heartbeat for file: ${file.path} (isWrite: ${file.isWrite})`
|
|
1130
|
+
);
|
|
1048
1131
|
sendHeartbeat({
|
|
1049
|
-
entity: file,
|
|
1132
|
+
entity: file.path,
|
|
1050
1133
|
entityType: "file",
|
|
1051
1134
|
category: "ai coding",
|
|
1052
|
-
projectFolder: cwd
|
|
1135
|
+
projectFolder: cwd,
|
|
1136
|
+
isWrite: file.isWrite
|
|
1053
1137
|
});
|
|
1054
1138
|
}
|
|
1055
1139
|
} else {
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "codex-wakatime",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.1.0",
|
|
5
5
|
"description": "WakaTime plugin for OpenAI Codex CLI - Track AI coding activity and time spent",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "https://github.com/
|
|
8
|
+
"url": "https://github.com/angristan/codex-wakatime.git"
|
|
9
9
|
},
|
|
10
10
|
"type": "module",
|
|
11
11
|
"main": "dist/index.cjs",
|
|
@@ -17,8 +17,7 @@
|
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
|
-
"
|
|
21
|
-
"build": "npm run prebuild && esbuild src/index.ts --bundle --platform=node --format=cjs --outfile=dist/index.cjs --banner:js=\"#!/usr/bin/env node\"",
|
|
20
|
+
"build": "esbuild src/index.ts --bundle --platform=node --format=cjs --outfile=dist/index.cjs --banner:js=\"#!/usr/bin/env node\"",
|
|
22
21
|
"typecheck": "tsc --noEmit",
|
|
23
22
|
"lint": "biome lint .",
|
|
24
23
|
"format": "biome format --write .",
|
|
@@ -26,7 +25,8 @@
|
|
|
26
25
|
"test": "vitest",
|
|
27
26
|
"test:run": "vitest run",
|
|
28
27
|
"test:coverage": "vitest run --coverage",
|
|
29
|
-
"prepublishOnly": "npm run build"
|
|
28
|
+
"prepublishOnly": "npm run build",
|
|
29
|
+
"prepare": "husky"
|
|
30
30
|
},
|
|
31
31
|
"keywords": [
|
|
32
32
|
"codex",
|
|
@@ -41,15 +41,25 @@
|
|
|
41
41
|
"license": "MIT",
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@biomejs/biome": "^2.3.10",
|
|
44
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
45
|
+
"@semantic-release/git": "^10.0.1",
|
|
44
46
|
"@types/node": "^22.0.0",
|
|
45
47
|
"@types/which": "^3.0.0",
|
|
46
48
|
"@vitest/coverage-v8": "^4.0.16",
|
|
47
49
|
"esbuild": "^0.25.0",
|
|
50
|
+
"husky": "^9.1.7",
|
|
51
|
+
"lint-staged": "^16.2.7",
|
|
52
|
+
"semantic-release": "^25.0.2",
|
|
48
53
|
"typescript": "^5.0.0",
|
|
49
54
|
"vitest": "^4.0.16"
|
|
50
55
|
},
|
|
51
56
|
"dependencies": {
|
|
52
57
|
"@iarna/toml": "^3.0.0",
|
|
53
58
|
"which": "^4.0.0"
|
|
59
|
+
},
|
|
60
|
+
"lint-staged": {
|
|
61
|
+
"*.{ts,js,json}": [
|
|
62
|
+
"biome check --write"
|
|
63
|
+
]
|
|
54
64
|
}
|
|
55
65
|
}
|