wdyt 0.1.0 → 0.1.2
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/package.json +4 -4
- package/src/commands/chat.ts +85 -34
- package/src/commands/init.ts +3 -3
- package/src/state.ts +5 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wdyt",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Code review context builder for LLMs - what do you think?",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
],
|
|
17
17
|
"repository": {
|
|
18
18
|
"type": "git",
|
|
19
|
-
"url": "git+https://github.com/Bewinxed/
|
|
19
|
+
"url": "git+https://github.com/Bewinxed/wdyt.git"
|
|
20
20
|
},
|
|
21
21
|
"bugs": {
|
|
22
|
-
"url": "https://github.com/Bewinxed/
|
|
22
|
+
"url": "https://github.com/Bewinxed/wdyt/issues"
|
|
23
23
|
},
|
|
24
|
-
"homepage": "https://github.com/Bewinxed/
|
|
24
|
+
"homepage": "https://github.com/Bewinxed/wdyt#readme",
|
|
25
25
|
"keywords": [
|
|
26
26
|
"code-review",
|
|
27
27
|
"llm",
|
package/src/commands/chat.ts
CHANGED
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
* }
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import {
|
|
21
|
+
import { mkdirSync } from "fs";
|
|
22
22
|
import { join, dirname, basename } from "path";
|
|
23
23
|
import { homedir } from "os";
|
|
24
|
+
import { $ } from "bun";
|
|
24
25
|
import { getTab, getWindow } from "../state";
|
|
25
26
|
|
|
26
27
|
/**
|
|
@@ -74,14 +75,79 @@ function generateUUID(): string {
|
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
/**
|
|
77
|
-
*
|
|
78
|
+
* Check if claude CLI is available
|
|
78
79
|
*/
|
|
79
|
-
function
|
|
80
|
+
async function claudeCliAvailable(): Promise<boolean> {
|
|
80
81
|
try {
|
|
81
|
-
|
|
82
|
+
await $`which claude`.quiet();
|
|
83
|
+
return true;
|
|
84
|
+
} catch {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Run a review using Claude CLI
|
|
91
|
+
* Returns the review output including verdict
|
|
92
|
+
*/
|
|
93
|
+
async function runClaudeReview(contextPath: string, prompt: string): Promise<string> {
|
|
94
|
+
// Read the context file content first
|
|
95
|
+
const contextFile = Bun.file(contextPath);
|
|
96
|
+
const contextContent = await contextFile.text();
|
|
97
|
+
|
|
98
|
+
const reviewPrompt = `You are reviewing code changes. Analyze the following context and provide a thorough review.
|
|
99
|
+
|
|
100
|
+
Review instructions:
|
|
101
|
+
${prompt}
|
|
102
|
+
|
|
103
|
+
<context>
|
|
104
|
+
${contextContent}
|
|
105
|
+
</context>
|
|
106
|
+
|
|
107
|
+
Analyze the code for:
|
|
108
|
+
- Correctness - Logic errors, bugs, spec compliance
|
|
109
|
+
- Security - Injection risks, auth gaps, data exposure
|
|
110
|
+
- Simplicity - Over-engineering, unnecessary complexity
|
|
111
|
+
- Edge cases - Failure modes, boundary conditions
|
|
112
|
+
|
|
113
|
+
Provide findings organized by severity (Critical > Major > Minor).
|
|
114
|
+
|
|
115
|
+
REQUIRED: End your review with exactly one verdict tag:
|
|
116
|
+
<verdict>SHIP</verdict> - Code is production-ready
|
|
117
|
+
<verdict>NEEDS_WORK</verdict> - Issues must be fixed first
|
|
118
|
+
<verdict>MAJOR_RETHINK</verdict> - Fundamental problems require redesign`;
|
|
119
|
+
|
|
120
|
+
// Write prompt to temp file to avoid shell escaping issues
|
|
121
|
+
const tempPromptPath = join(getChatsDir(), `review-prompt-${Date.now()}.txt`);
|
|
122
|
+
await Bun.write(tempPromptPath, reviewPrompt);
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
// Run claude CLI in print mode, reading from temp file
|
|
126
|
+
const result = await $`cat ${tempPromptPath} | claude -p`.text();
|
|
127
|
+
|
|
128
|
+
// Clean up temp file
|
|
129
|
+
await $`rm ${tempPromptPath}`.quiet();
|
|
130
|
+
|
|
131
|
+
return result.trim();
|
|
132
|
+
} catch (error) {
|
|
133
|
+
// Clean up temp file on error too
|
|
134
|
+
await $`rm ${tempPromptPath}`.quiet();
|
|
135
|
+
|
|
136
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
137
|
+
throw new Error(`Claude CLI review failed: ${message}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Read file content safely using Bun's file API
|
|
143
|
+
*/
|
|
144
|
+
async function readFileSafe(path: string): Promise<{ success: boolean; content?: string; error?: string }> {
|
|
145
|
+
try {
|
|
146
|
+
const file = Bun.file(path);
|
|
147
|
+
if (!(await file.exists())) {
|
|
82
148
|
return { success: false, error: `File not found: ${path}` };
|
|
83
149
|
}
|
|
84
|
-
const content =
|
|
150
|
+
const content = await file.text();
|
|
85
151
|
return { success: true, content };
|
|
86
152
|
} catch (error) {
|
|
87
153
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -218,7 +284,7 @@ export async function chatSendCommand(
|
|
|
218
284
|
const errors: string[] = [];
|
|
219
285
|
|
|
220
286
|
for (const filePath of filePaths) {
|
|
221
|
-
const result = readFileSafe(filePath);
|
|
287
|
+
const result = await readFileSafe(filePath);
|
|
222
288
|
if (result.success && result.content !== undefined) {
|
|
223
289
|
files.push({ path: filePath, content: result.content });
|
|
224
290
|
} else {
|
|
@@ -252,41 +318,26 @@ export async function chatSendCommand(
|
|
|
252
318
|
const chatPath = join(chatsDir, `${chatId}.xml`);
|
|
253
319
|
await Bun.write(chatPath, xmlContent);
|
|
254
320
|
|
|
255
|
-
// Check if this is a review request - if so,
|
|
321
|
+
// Check if this is a review request - if so, run Claude CLI to do the review
|
|
256
322
|
const isReviewMode = payload.mode === "review";
|
|
257
323
|
|
|
258
324
|
if (isReviewMode) {
|
|
259
|
-
//
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
Task(subagent_type="flow-next:quality-auditor", prompt="""
|
|
268
|
-
Review the code changes in this context file: ${chatPath}
|
|
269
|
-
|
|
270
|
-
Read the file, analyze the code for:
|
|
271
|
-
- Correctness - Logic errors, bugs
|
|
272
|
-
- Security - Injection, auth gaps
|
|
273
|
-
- Simplicity - Over-engineering
|
|
274
|
-
- Edge cases - Failure modes
|
|
275
|
-
|
|
276
|
-
Provide findings by severity (Critical > Major > Minor).
|
|
277
|
-
|
|
278
|
-
REQUIRED: End with exactly one verdict tag:
|
|
279
|
-
<verdict>SHIP</verdict> - Code is production-ready
|
|
280
|
-
<verdict>NEEDS_WORK</verdict> - Issues must be fixed first
|
|
281
|
-
""")
|
|
325
|
+
// Check if claude CLI is available
|
|
326
|
+
if (!(await claudeCliAvailable())) {
|
|
327
|
+
return {
|
|
328
|
+
success: false,
|
|
329
|
+
error: "Review mode requires Claude CLI (claude) to be installed and in PATH",
|
|
330
|
+
};
|
|
331
|
+
}
|
|
282
332
|
|
|
283
|
-
|
|
284
|
-
|
|
333
|
+
// Run the review using Claude CLI
|
|
334
|
+
console.error("Running review with Claude CLI...");
|
|
335
|
+
const reviewOutput = await runClaudeReview(chatPath, prompt);
|
|
285
336
|
|
|
286
337
|
return {
|
|
287
338
|
success: true,
|
|
288
|
-
data: { id: chatId, path: chatPath },
|
|
289
|
-
output: reviewOutput
|
|
339
|
+
data: { id: chatId, path: chatPath, review: reviewOutput },
|
|
340
|
+
output: `Chat: \`${chatId}\`\n\n${reviewOutput}`,
|
|
290
341
|
};
|
|
291
342
|
}
|
|
292
343
|
|
package/src/commands/init.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* bunx wdyt init --global # Install globally
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { mkdirSync,
|
|
11
|
+
import { mkdirSync, symlinkSync, unlinkSync } from "fs";
|
|
12
12
|
import { join } from "path";
|
|
13
13
|
import { homedir } from "os";
|
|
14
14
|
import { $ } from "bun";
|
|
@@ -169,12 +169,12 @@ export async function initCommand(options: InitOptions): Promise<{
|
|
|
169
169
|
mkdirSync(binDir, { recursive: true });
|
|
170
170
|
|
|
171
171
|
// Remove existing symlink if present
|
|
172
|
-
if (
|
|
172
|
+
if (await Bun.file(rpCliPath).exists()) {
|
|
173
173
|
unlinkSync(rpCliPath);
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
// Check if wdyt binary exists
|
|
177
|
-
if (
|
|
177
|
+
if (await Bun.file(secondOpinionPath).exists()) {
|
|
178
178
|
symlinkSync(secondOpinionPath, rpCliPath);
|
|
179
179
|
lines.push(` ✓ Created symlink: rp-cli -> wdyt`);
|
|
180
180
|
} else {
|
package/src/state.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { join } from "path";
|
|
9
9
|
import { homedir } from "os";
|
|
10
|
-
import { mkdirSync,
|
|
10
|
+
import { mkdirSync, renameSync } from "fs";
|
|
11
11
|
import type { StateFile, Window, Tab, TabUpdate } from "./types";
|
|
12
12
|
|
|
13
13
|
const STATE_VERSION = 1;
|
|
@@ -60,14 +60,14 @@ function generateUUID(): string {
|
|
|
60
60
|
export async function loadState(): Promise<StateFile> {
|
|
61
61
|
const statePath = getStatePath();
|
|
62
62
|
|
|
63
|
-
// Check if file exists first
|
|
64
|
-
|
|
63
|
+
// Check if file exists first using Bun's file API
|
|
64
|
+
const stateFile = Bun.file(statePath);
|
|
65
|
+
if (!(await stateFile.exists())) {
|
|
65
66
|
return createDefaultState();
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
try {
|
|
69
|
-
const
|
|
70
|
-
const content = await file.text();
|
|
70
|
+
const content = await stateFile.text();
|
|
71
71
|
const state = JSON.parse(content) as StateFile;
|
|
72
72
|
|
|
73
73
|
// Validate basic structure
|