Skip to content

Commit 91d2a18

Browse files
committed
switch sdk fs to use promises only
1 parent 5b6f9b5 commit 91d2a18

24 files changed

+283
-307
lines changed

common/src/project-file-tree.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import type { DirectoryNode, FileTreeNode } from './util/file'
1111

1212
export const DEFAULT_MAX_FILES = 10_000
1313

14-
export function getProjectFileTree(params: {
14+
export async function getProjectFileTree(params: {
1515
projectRoot: string
1616
maxFiles?: number
1717
fs: CodebuffFileSystem
18-
}): FileTreeNode[] {
18+
}): Promise<FileTreeNode[]> {
1919
const withDefaults = { maxFiles: DEFAULT_MAX_FILES, ...params }
2020
const { projectRoot, fs } = withDefaults
2121
let { maxFiles } = withDefaults
@@ -55,10 +55,10 @@ export function getProjectFileTree(params: {
5555
const mergedIgnore = ignore
5656
.default()
5757
.add(currentIgnore)
58-
.add(parseGitignore({ fullDirPath: fullPath, projectRoot, fs }))
58+
.add(await parseGitignore({ fullDirPath: fullPath, projectRoot, fs }))
5959

6060
try {
61-
const files = fs.readdirSync(fullPath)
61+
const files = await fs.readdir(fullPath)
6262
for (const file of files) {
6363
if (totalFiles >= maxFiles) break
6464

@@ -68,7 +68,7 @@ export function getProjectFileTree(params: {
6868
if (mergedIgnore.ignores(relativeFilePath)) continue
6969

7070
try {
71-
const stats = fs.statSync(filePath)
71+
const stats = await fs.stat(filePath)
7272
if (stats.isDirectory()) {
7373
const childNode: DirectoryNode = {
7474
name: file,
@@ -151,11 +151,11 @@ function rebaseGitignorePattern(
151151
return isNegated ? `!${rebased}` : rebased
152152
}
153153

154-
export function parseGitignore(params: {
154+
export async function parseGitignore(params: {
155155
fullDirPath: string
156156
projectRoot: string
157157
fs: CodebuffFileSystem
158-
}): ignore.Ignore {
158+
}): Promise<ignore.Ignore> {
159159
const { fullDirPath, projectRoot, fs } = params
160160

161161
const ig = ignore.default()
@@ -167,9 +167,9 @@ export function parseGitignore(params: {
167167
]
168168

169169
for (const ignoreFilePath of ignoreFiles) {
170-
if (!fs.existsSync(ignoreFilePath)) continue
170+
if (!(await fs.exists(ignoreFilePath))) continue
171171

172-
const ignoreContent = fs.readFileSync(ignoreFilePath, 'utf8')
172+
const ignoreContent = await fs.readFile(ignoreFilePath, 'utf8')
173173
const lines = ignoreContent.split('\n')
174174
for (let line of lines) {
175175
line = line.trim()
@@ -218,11 +218,11 @@ export function getLastReadFilePaths(
218218
.map((node) => node.filePath)
219219
}
220220

221-
export function isFileIgnored(params: {
221+
export async function isFileIgnored(params: {
222222
filePath: string
223223
projectRoot: string
224224
fs: CodebuffFileSystem
225-
}): boolean {
225+
}): Promise<boolean> {
226226
const { filePath, projectRoot, fs } = params
227227

228228
const defaultIgnore = ignore.default()
@@ -241,7 +241,7 @@ export function isFileIgnored(params: {
241241
let currentDir = dirPath
242242
while (currentDir.startsWith(projectRoot)) {
243243
mergedIgnore.add(
244-
parseGitignore({ fullDirPath: currentDir, projectRoot, fs }),
244+
await parseGitignore({ fullDirPath: currentDir, projectRoot, fs }),
245245
)
246246
currentDir = path.dirname(currentDir)
247247
}

common/src/types/filesystem.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,9 @@ import type fs from 'fs'
22

33
/** File system used for Codebuff SDK.
44
*
5-
* Compatible with the `'fs'` module
5+
* Compatible with `fs.promises` from the `'fs'` module.
66
*/
77
export type CodebuffFileSystem = Pick<
8-
typeof fs,
9-
| 'existsSync'
10-
| 'mkdirSync'
11-
| 'readdirSync'
12-
| 'readFileSync'
13-
| 'statSync'
14-
| 'writeFileSync'
15-
> & { promises: Pick<typeof fs.promises, 'readdir'> }
8+
typeof fs.promises,
9+
'exists' | 'mkdir' | 'readdir' | 'readFile' | 'stat' | 'writeFile'
10+
>

common/src/types/util.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export type Prettify<T> = {
2+
[K in keyof T]: T[K]
3+
} & {}

common/src/util/file.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,14 +215,14 @@ export const ensureEndsWithNewline = (
215215
return contents + '\n'
216216
}
217217

218-
export const ensureDirectoryExists = (params: {
218+
export const ensureDirectoryExists = async (params: {
219219
baseDir: string
220220
fs: CodebuffFileSystem
221221
}) => {
222222
const { baseDir, fs } = params
223223

224-
if (!fs.existsSync(baseDir)) {
225-
fs.mkdirSync(baseDir, { recursive: true })
224+
if (!(await fs.exists(baseDir))) {
225+
await fs.mkdir(baseDir, { recursive: true })
226226
}
227227
}
228228

@@ -249,14 +249,14 @@ export function isValidFilePath(path: string) {
249249
return true
250250
}
251251

252-
export function isDir(params: {
252+
export async function isDir(params: {
253253
path: string
254254
fs: CodebuffFileSystem
255-
}): boolean {
255+
}): Promise<boolean> {
256256
const { path, fs } = params
257257

258258
try {
259-
return fs.statSync(path).isDirectory()
259+
return (await fs.stat(path)).isDirectory()
260260
} catch {
261261
return false
262262
}

common/src/util/git.ts

Lines changed: 0 additions & 64 deletions
This file was deleted.

evals/scaffolding.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,10 @@ export async function createFileReadingMock(projectRoot: string) {
137137
export async function getProjectFileContext(
138138
projectPath: string,
139139
): Promise<ProjectFileContext> {
140-
const fileTree = getProjectFileTree({ projectRoot: projectPath, fs })
140+
const fileTree = await getProjectFileTree({
141+
projectRoot: projectPath,
142+
fs: fs.promises,
143+
})
141144
const allFilePaths = getAllFilePaths(fileTree)
142145
const knowledgeFilePaths = allFilePaths.filter((filePath) =>
143146
filePath.endsWith('knowledge.md'),

npm-app/src/browser-runner.ts

Lines changed: 0 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1-
import * as fs from 'fs'
2-
import * as path from 'path'
3-
41
import { BROWSER_DEFAULTS } from '@codebuff/common/browser-actions'
5-
import { ensureDirectoryExists } from '@codebuff/common/util/file'
62
import { sleep } from '@codebuff/common/util/promise'
73
import { ensureUrlProtocol } from '@codebuff/common/util/string'
84
import puppeteer from 'puppeteer-core'
95

10-
import { getCurrentChatDir } from './project-files'
116
import { logger } from './utils/logger'
127

138
import type {
@@ -466,94 +461,6 @@ export class BrowserRunner {
466461
}
467462
}
468463

469-
private async takeScreenshot(
470-
action: Extract<BrowserAction, { type: 'screenshot' }>,
471-
page: Page,
472-
): Promise<{
473-
data: string
474-
logs: BrowserResponse['logs']
475-
}> {
476-
// Take a screenshot with aggressive compression settings
477-
const screenshot = await page.screenshot({
478-
fullPage: BROWSER_DEFAULTS.fullPage,
479-
type: 'jpeg',
480-
quality:
481-
action.screenshotCompressionQuality ??
482-
BROWSER_DEFAULTS.screenshotCompressionQuality,
483-
encoding: 'base64',
484-
})
485-
486-
// Log screenshot capture and size
487-
const sizeInKB = Math.round((screenshot.length * 3) / 4 / 1024)
488-
this.logs.push({
489-
type: 'info',
490-
message: `Captured screenshot (${sizeInKB}KB)`,
491-
timestamp: Date.now(),
492-
category: 'screenshot',
493-
source: 'tool',
494-
})
495-
496-
// If debug mode is enabled, save the screenshot
497-
if (action.debug) {
498-
console.debug({
499-
message: 'Saving screenshot to disk...',
500-
timestamp: Date.now(),
501-
source: 'tool',
502-
})
503-
504-
try {
505-
const chatDir = getCurrentChatDir()
506-
const screenshotsDir = path.join(chatDir, 'screenshots')
507-
ensureDirectoryExists({ baseDir: screenshotsDir, fs })
508-
509-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
510-
const filename = `screenshot-${timestamp}.jpg`
511-
const filepath = path.join(screenshotsDir, filename)
512-
513-
fs.writeFileSync(filepath, Buffer.from(screenshot, 'base64'))
514-
console.debug({
515-
type: 'debug',
516-
message: `Saved screenshot to ${filepath}`,
517-
timestamp: Date.now(),
518-
source: 'tool',
519-
})
520-
521-
// Save metadata
522-
const metadataPath = path.join(
523-
screenshotsDir,
524-
`${timestamp}-metadata.json`,
525-
)
526-
const metadata = {
527-
timestamp,
528-
format: 'jpeg',
529-
quality: 25,
530-
fullPage: action.fullPage ?? BROWSER_DEFAULTS.fullPage,
531-
metrics: await this.collectMetrics(),
532-
}
533-
fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2))
534-
} catch (error) {
535-
console.error({
536-
message: `Failed to save screenshot: ${(error as Error).message}`,
537-
timestamp: Date.now(),
538-
source: 'tool',
539-
})
540-
logger.error(
541-
{
542-
errorMessage:
543-
error instanceof Error ? error.message : String(error),
544-
errorStack: error instanceof Error ? error.stack : undefined,
545-
},
546-
'Failed to save screenshot',
547-
)
548-
}
549-
}
550-
551-
return {
552-
data: screenshot,
553-
logs: this.logs,
554-
}
555-
}
556-
557464
private attachPageListeners() {
558465
if (!this.page) return
559466

npm-app/src/chat-storage.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import * as path from 'path'
33

44
import { transformJsonInString } from '@codebuff/common/util/string'
55

6-
import { getCurrentChatDir, getCurrentChatId } from './project-files'
6+
import { getCurrentChatDirSync, getCurrentChatId } from './project-files'
77
import { logger } from './utils/logger'
88

99
import type { Log } from '@codebuff/common/browser-actions'
1010
import type { Message } from '@codebuff/common/types/messages/codebuff-message'
1111

12-
export function setMessages(messages: Message[]) {
12+
export function setMessagesSync(messages: Message[]) {
1313
// Clean up any screenshots and logs in previous messages
1414
// Skip the last message as it may not have been processed by the backend yet
1515
const lastIndex = messages.length - 1
@@ -76,7 +76,7 @@ export function setMessages(messages: Message[]) {
7676

7777
// Save messages to chat directory
7878
try {
79-
const chatDir = getCurrentChatDir()
79+
const chatDir = getCurrentChatDirSync()
8080
const messagesPath = path.join(chatDir, 'messages.json')
8181

8282
const messagesData = {

npm-app/src/cli.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
getAllAgents,
1111
getAgentDisplayName,
1212
} from '@codebuff/common/util/agent-name-resolver'
13-
import { isDir } from '@codebuff/common/util/file'
1413
import { pluralize } from '@codebuff/common/util/string'
1514
import { uniq } from 'lodash'
1615
import {
@@ -601,17 +600,21 @@ export class CLI {
601600
const partial = input.endsWith(directorySuffix) ? '' : basename(input)
602601

603602
let baseDir = isAbsolute(dir) ? dir : path.join(getWorkingDirectory(), dir)
603+
function isDirSync(path: string): boolean {
604+
try {
605+
return fs.statSync(path).isDirectory()
606+
} catch {
607+
return false
608+
}
609+
}
604610

605611
try {
606612
const files = readdirSync(baseDir)
607613
const fsMatches = files
608614
.filter((file) => file.startsWith(partial))
609615
.map(
610616
(file) =>
611-
file +
612-
(isDir({ path: path.join(baseDir, file), fs })
613-
? directorySuffix
614-
: ''),
617+
file + (isDirSync(path.join(baseDir, file)) ? directorySuffix : ''),
615618
)
616619
return [fsMatches, partial]
617620
} catch {

0 commit comments

Comments
 (0)