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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wdyt",
3
- "version": "0.1.0",
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/reepoproompt.git"
19
+ "url": "git+https://github.com/Bewinxed/wdyt.git"
20
20
  },
21
21
  "bugs": {
22
- "url": "https://github.com/Bewinxed/reepoproompt/issues"
22
+ "url": "https://github.com/Bewinxed/wdyt/issues"
23
23
  },
24
- "homepage": "https://github.com/Bewinxed/reepoproompt#readme",
24
+ "homepage": "https://github.com/Bewinxed/wdyt#readme",
25
25
  "keywords": [
26
26
  "code-review",
27
27
  "llm",
@@ -18,9 +18,10 @@
18
18
  * }
19
19
  */
20
20
 
21
- import { existsSync, readFileSync, mkdirSync } from "fs";
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
- * Read file content safely
78
+ * Check if claude CLI is available
78
79
  */
79
- function readFileSafe(path: string): { success: boolean; content?: string; error?: string } {
80
+ async function claudeCliAvailable(): Promise<boolean> {
80
81
  try {
81
- if (!existsSync(path)) {
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 = readFileSync(path, "utf-8");
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, output subagent spawn instruction
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
- // Build the review output that instructs Claude Code to spawn quality-auditor
260
- const reviewOutput = `Chat: \`${chatId}\`
261
-
262
- [CLAUDE_CODE_REVIEW_REQUEST]
263
- The context has been exported to: ${chatPath}
264
-
265
- To complete this review, spawn a quality-auditor subagent with the Task tool:
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
- The subagent will return the review findings and verdict.
284
- [/CLAUDE_CODE_REVIEW_REQUEST]`;
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
 
@@ -8,7 +8,7 @@
8
8
  * bunx wdyt init --global # Install globally
9
9
  */
10
10
 
11
- import { mkdirSync, existsSync, symlinkSync, unlinkSync } from "fs";
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 (existsSync(rpCliPath)) {
172
+ if (await Bun.file(rpCliPath).exists()) {
173
173
  unlinkSync(rpCliPath);
174
174
  }
175
175
 
176
176
  // Check if wdyt binary exists
177
- if (existsSync(secondOpinionPath)) {
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, existsSync, renameSync } from "fs";
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
- if (!existsSync(statePath)) {
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 file = Bun.file(statePath);
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