kodevu 0.1.22 → 0.1.24

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 gyt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -76,7 +76,7 @@ npx kodevu /path/to/your/repo --config ./config.current.json
76
76
  ## Config
77
77
 
78
78
  - `target`: required repository target; can be provided by config or as the CLI positional argument
79
- - `reviewer`: `codex`, `gemini`, or `auto`; default `auto`
79
+ - `reviewer`: `codex`, `gemini`, `copilot`, or `auto`; default `auto`
80
80
  - `prompt`: saved into the report as review context
81
81
  - `outputDir`: report output directory; default `~/.kodevu`
82
82
  - `outputFormats`: report formats to generate; supports `markdown` and `json`; default `["markdown"]`
@@ -100,7 +100,8 @@ Internal defaults:
100
100
 
101
101
  - `reviewer: "codex"` uses `codex exec` with the diff embedded in the prompt.
102
102
  - `reviewer: "gemini"` uses `gemini -p` in non-interactive mode.
103
- - `reviewer: "auto"` probes `codex` and `gemini` in `PATH`, then randomly chooses one of the available CLIs for this run.
103
+ - `reviewer: "copilot"` uses `copilot -p` in non-interactive mode.
104
+ - `reviewer: "auto"` probes `codex`, `gemini`, and `copilot` in `PATH`, then randomly chooses one of the available CLIs for this run.
104
105
  - Large diffs are truncated before being sent to the reviewer or written into the report once they exceed the configured line or character limits.
105
106
  - For Git targets and local SVN working copies, the reviewer command runs from the repository workspace so it can inspect related files beyond the diff when needed.
106
107
  - For remote SVN URLs without a local working copy, the review still relies on the diff and change metadata only.
@@ -110,3 +111,7 @@ Internal defaults:
110
111
  - `~/.kodevu/state.json` stores per-project checkpoints keyed by repository identity; only the v2 multi-project structure is supported.
111
112
  - If the reviewer command exits non-zero or times out, the report is still written, but the state is not advanced so the change can be retried later.
112
113
  - Each report includes a `Token Usage` section recording token consumption for the review task. When the reviewer CLI outputs token statistics (via stderr), those are used directly (`source: "reviewer"`). Otherwise tokens are estimated at ~4 characters per token (`source: "estimate"`). The JSON report contains a `tokenUsage` object with `inputTokens`, `outputTokens`, `totalTokens`, and `source`.
114
+
115
+ ## License
116
+
117
+ MIT
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "kodevu",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
+ "license": "MIT",
4
5
  "type": "module",
5
6
  "description": "Poll SVN revisions or Git commits, send each change diff to a reviewer CLI, and write configurable review reports.",
6
7
  "bin": {
package/src/config.js CHANGED
@@ -4,7 +4,7 @@ import path from "node:path";
4
4
  import { findCommandOnPath } from "./shell.js";
5
5
 
6
6
  const defaultStorageDir = path.join(os.homedir(), ".kodevu");
7
- const SUPPORTED_REVIEWERS = ["codex", "gemini"];
7
+ const SUPPORTED_REVIEWERS = ["codex", "gemini", "copilot"];
8
8
 
9
9
  const defaultConfig = {
10
10
  reviewer: "auto",
@@ -223,7 +223,7 @@ export async function loadConfig(configPath, cliArgs = {}) {
223
223
  config.reviewerWasAutoSelected = true;
224
224
  } else if (!SUPPORTED_REVIEWERS.includes(config.reviewer)) {
225
225
  throw new Error(
226
- `"reviewer" must be one of "codex", "gemini", or "auto"${loadedConfigPath ? ` in ${loadedConfigPath}` : ""}`
226
+ `"reviewer" must be one of "codex", "gemini", "copilot", or "auto"${loadedConfigPath ? ` in ${loadedConfigPath}` : ""}`
227
227
  );
228
228
  }
229
229
 
@@ -259,13 +259,13 @@ Usage:
259
259
 
260
260
  Options:
261
261
  --config, -c Optional config json path. If omitted, ./config.json is loaded only when present
262
- --reviewer, -r Override reviewer (codex | gemini | auto)
262
+ --reviewer, -r Override reviewer (codex | gemini | copilot | auto)
263
263
  --prompt, -p Override prompt
264
264
  --debug, -d Print extra debug information to the console
265
265
  --help, -h Show help
266
266
 
267
267
  Config highlights:
268
- reviewer codex | gemini | auto
268
+ reviewer codex | gemini | copilot | auto
269
269
  target Repository target path (Git) or SVN working copy / URL; CLI positional target overrides config
270
270
  outputFormats ["markdown"] by default; set to include "json" when needed
271
271
  `);
@@ -83,8 +83,40 @@ function parseCodexTokenUsage(stderr) {
83
83
  return { inputTokens, outputTokens, totalTokens };
84
84
  }
85
85
 
86
+ function parseCopilotTokenUsage(stderr) {
87
+ if (!stderr) {
88
+ return null;
89
+ }
90
+
91
+ const patterns = [
92
+ /input[_ ]tokens?\s*[:=]\s*(\d+)/i,
93
+ /output[_ ]tokens?\s*[:=]\s*(\d+)/i,
94
+ /total[_ ]tokens?\s*[:=]\s*(\d+)/i
95
+ ];
96
+
97
+ const inputMatch = stderr.match(patterns[0]);
98
+ const outputMatch = stderr.match(patterns[1]);
99
+ const totalMatch = stderr.match(patterns[2]);
100
+
101
+ if (!inputMatch && !outputMatch && !totalMatch) {
102
+ return null;
103
+ }
104
+
105
+ const inputTokens = inputMatch ? Number(inputMatch[1]) : 0;
106
+ const outputTokens = outputMatch ? Number(outputMatch[1]) : 0;
107
+ const totalTokens = totalMatch ? Number(totalMatch[1]) : inputTokens + outputTokens;
108
+
109
+ return { inputTokens, outputTokens, totalTokens };
110
+ }
111
+
112
+ const TOKEN_PARSERS = {
113
+ gemini: parseGeminiTokenUsage,
114
+ codex: parseCodexTokenUsage,
115
+ copilot: parseCopilotTokenUsage
116
+ };
117
+
86
118
  function resolveTokenUsage(reviewerName, stderr, promptText, diffText, responseText) {
87
- const parseFn = reviewerName === "gemini" ? parseGeminiTokenUsage : parseCodexTokenUsage;
119
+ const parseFn = TOKEN_PARSERS[reviewerName] || parseCopilotTokenUsage;
88
120
  const parsed = parseFn(stderr);
89
121
 
90
122
  if (parsed && parsed.totalTokens > 0) {
@@ -161,6 +193,25 @@ const REVIEWERS = {
161
193
  debug: config.debug
162
194
  });
163
195
 
196
+ return {
197
+ ...execResult,
198
+ message: execResult.stdout
199
+ };
200
+ }
201
+ },
202
+ copilot: {
203
+ displayName: "Copilot",
204
+ responseSectionTitle: "Copilot Response",
205
+ emptyResponseText: "_No final response returned from copilot._",
206
+ async run(config, workingDir, promptText, diffText) {
207
+ const execResult = await runCommand("copilot", ["-p", promptText], {
208
+ cwd: workingDir,
209
+ input: ["Unified diff:", diffText].join("\n\n"),
210
+ allowFailure: true,
211
+ timeoutMs: config.commandTimeoutMs,
212
+ debug: config.debug
213
+ });
214
+
164
215
  return {
165
216
  ...execResult,
166
217
  message: execResult.stdout