Official
files
Built-in files UI (JavaScript UI plugin).
The app opens the listing; nothing installs until an agent in your Plugins workspace has read the files and you enable the plugin. In a terminal: cvg install convergence/files@0.2.0
Permissions in 0.2.0
Files
panel.ts1.6 KB
// File panel state, filtering and folder-first tree construction.
// Paths and selection remain workspace-relative, matching the kernel tree ids.
import * as z from "zod";
import type { EffectClient } from "convergence/effect";
import type * as Fiber from "effect/Fiber";
import type { AppState } from "convergence";
import type { Tabs } from "../tabs/contract.ts";
export interface FilesState {
workspaceId: string | null;
paths: readonly string[];
loaded: boolean;
query: string;
// The convergence/tabs client while its provider runs, the open file it
// last announced, and the fiber following it; selection stays empty
// without it.
tabs: EffectClient<typeof Tabs> | undefined;
activePath: string | null;
follow: Fiber.Fiber<void> | undefined;
}
export const initialState = (): FilesState => ({
workspaceId: null,
paths: [],
loaded: false,
query: "",
tabs: undefined,
activePath: null,
follow: undefined,
});
export function visiblePaths(paths: readonly string[], query: string): readonly string[] {
const q = query.trim().toLowerCase();
return q ? paths.filter((path) => path.toLowerCase().includes(q)).slice(0, 500) : paths;
}
export function isOpen(app: AppState): boolean {
return app.shared?.rightPanel === "files" || app.shared?.rightPanelPreview === "files";
}
export function selectedPath(activePath: string | null): string | null {
return typeof activePath === "string" ? activePath : null;
}
const finished = z.object({ event: z.literal("run_finished") });
export const runFinished = (kind: unknown): boolean => finished.safeParse(kind).success;Versions
| Version | Published | Plugin API | Size | Permissions | Status |
|---|---|---|---|---|---|
| 0.2.0latest | Oct 5, 2026 | >=2 <3 | 6.4 KB | 3 permissions | Listed |
No comments yet.