Download apps/vscode/src/managers/file.manager.ts from SaylorTwift/kimi-code: direct link, hf CLI and curl.
- Browser
- Download file 4.69 kB
-
https://huggingface.co/SaylorTwift/kimi-code/resolve/main/apps/vscode/src/managers/file.manager.ts
- Command line
-
hf download hf://SaylorTwift/kimi-code/apps/vscode/src/managers/file.manager.ts
-
curl -L -o file.manager.ts https://huggingface.co/SaylorTwift/kimi-code/resolve/main/apps/vscode/src/managers/file.manager.ts
4.69 kB
| import * as vscode from "vscode"; | |
| import * as path from "node:path"; | |
| import { BaselineManager, type BaselineSession } from "./baseline.manager"; | |
| import { Events } from "../../shared/bridge"; | |
| import type { ProjectFile } from "../../shared/types"; | |
| import { buildCaseInsensitiveGlobLiteral } from "../utils/string"; | |
| import { | |
| isWorkspacePathContained, | |
| relativeWorkspacePath, | |
| } from "../utils/workspace-path"; | |
| export type BroadcastFn = (event: string, data: unknown, webviewId?: string) => void; | |
| const IGNORE_DIRS = new Set([ | |
| "node_modules", | |
| ".git", | |
| ".svn", | |
| ".hg", | |
| "dist", | |
| "build", | |
| "out", | |
| ".next", | |
| ".nuxt", | |
| "__pycache__", | |
| ".cache", | |
| ".venv", | |
| "venv", | |
| ".gradle", | |
| ".idea", | |
| ".DS_Store", | |
| "Thumbs.db", | |
| "coverage", | |
| ".nyc_output", | |
| ".pytest_cache", | |
| ".mypy_cache", | |
| ".tox", | |
| ".eggs", | |
| ".sass-cache", | |
| ".parcel-cache", | |
| "bower_components", | |
| "jspm_packages", | |
| ".turbo", | |
| ]); | |
| const SEARCH_EXCLUDE = `{${[...IGNORE_DIRS].map((d) => `**/${d}`).join(",")}}`; | |
| interface ViewState { | |
| session: BaselineSession | null; | |
| trackedFiles: Set<string>; | |
| } | |
| export class FileManager { | |
| private viewStates = new Map<string, ViewState>(); | |
| private disposables: vscode.Disposable[] = []; | |
| constructor( | |
| private readonly baselineManager: BaselineManager, | |
| private broadcast: BroadcastFn, | |
| ) { | |
| // Watch for file changes | |
| const watcher = vscode.workspace.createFileSystemWatcher("**/*"); | |
| const refresh = (uri: vscode.Uri) => { | |
| void this.onFileChange(uri).catch((error) => { | |
| console.error("[kimi-vscode] Unable to refresh file changes", error); | |
| }); | |
| }; | |
| watcher.onDidChange(refresh); | |
| watcher.onDidCreate(refresh); | |
| watcher.onDidDelete(refresh); | |
| this.disposables.push(watcher); | |
| } | |
| private getViewState(webviewId: string): ViewState { | |
| let state = this.viewStates.get(webviewId); | |
| if (!state) { | |
| state = { session: null, trackedFiles: new Set() }; | |
| this.viewStates.set(webviewId, state); | |
| } | |
| return state; | |
| } | |
| setSession(webviewId: string, session: BaselineSession): void { | |
| this.getViewState(webviewId).session = session; | |
| } | |
| clearSession(webviewId: string): void { | |
| const state = this.getViewState(webviewId); | |
| state.session = null; | |
| state.trackedFiles.clear(); | |
| } | |
| getSessionId(webviewId: string): string | null { | |
| return this.getViewState(webviewId).session?.id ?? null; | |
| } | |
| getSession(webviewId: string): BaselineSession | null { | |
| return this.getViewState(webviewId).session; | |
| } | |
| trackFile(webviewId: string, absolutePath: string): void { | |
| this.getViewState(webviewId).trackedFiles.add(absolutePath); | |
| } | |
| getTracked(webviewId: string): Set<string> { | |
| return this.getViewState(webviewId).trackedFiles; | |
| } | |
| clearTracked(webviewId: string): void { | |
| this.getViewState(webviewId).trackedFiles.clear(); | |
| } | |
| disposeView(webviewId: string): void { | |
| this.viewStates.delete(webviewId); | |
| } | |
| private async onFileChange(uri: vscode.Uri): Promise<void> { | |
| const absolutePath = uri.fsPath; | |
| for (const [webviewId, state] of this.viewStates) { | |
| if (!state.session || !state.trackedFiles.has(absolutePath)) { | |
| continue; | |
| } | |
| await this.refreshChanges(webviewId); | |
| } | |
| } | |
| async refreshChanges(webviewId: string): Promise<void> { | |
| const state = this.getViewState(webviewId); | |
| if (state.session === null) { | |
| this.broadcast(Events.FileChangesUpdated, [], webviewId); | |
| return; | |
| } | |
| const changes = await this.baselineManager.getChanges(state.session); | |
| this.broadcast(Events.FileChangesUpdated, changes, webviewId); | |
| } | |
| async searchFiles(workDirUri: vscode.Uri, query?: string): Promise<ProjectFile[]> { | |
| query = query ? buildCaseInsensitiveGlobLiteral(query) : ""; | |
| const pattern = query ? `**/*${query}*` : "**/*"; | |
| const files = await vscode.workspace.findFiles( | |
| new vscode.RelativePattern(workDirUri, pattern), | |
| new vscode.RelativePattern(workDirUri, SEARCH_EXCLUDE), | |
| 200, | |
| ); | |
| const results = await Promise.all( | |
| files.map(async (uri): Promise<ProjectFile | undefined> => { | |
| const relativePath = relativeWorkspacePath(workDirUri, uri); | |
| if (relativePath === undefined || !(await isWorkspacePathContained(workDirUri, uri))) return undefined; | |
| return { | |
| path: relativePath, | |
| name: path.posix.basename(relativePath), | |
| isDirectory: false, | |
| }; | |
| }), | |
| ); | |
| return results.filter((result): result is ProjectFile => result !== undefined); | |
| } | |
| dispose(): void { | |
| for (const d of this.disposables) { | |
| d.dispose(); | |
| } | |
| this.disposables = []; | |
| this.viewStates.clear(); | |
| } | |
| } | |