1+ import { Client , createClient , createConfig } from "../api-clients/pint/client" ;
2+ import {
3+ IAgentClientFS ,
4+ PickRawFsResult ,
5+ } from "../agent-client-interface" ;
6+ import {
7+ createFile ,
8+ readFile ,
9+ performFileAction ,
10+ listDirectory ,
11+ createDirectory ,
12+ deleteDirectory ,
13+ getFileStat ,
14+ } from "../api-clients/pint" ;
15+ export class PintFsClient implements IAgentClientFS {
16+ constructor ( private apiClient : Client ) { }
17+
18+ async readFile ( path : string ) : Promise < PickRawFsResult < "fs/readFile" > > {
19+ try {
20+ const response = await readFile ( {
21+ client : this . apiClient ,
22+ path : {
23+ path : path ,
24+ } ,
25+ } ) ;
26+
27+ if ( response . data ) {
28+ // Convert string content to Uint8Array to match FSReadFileResult type
29+ const encoder = new TextEncoder ( ) ;
30+ const content = encoder . encode ( response . data . content ) ;
31+
32+ return {
33+ type : "ok" ,
34+ result : {
35+ content : content ,
36+ } ,
37+ } ;
38+ } else {
39+ return {
40+ type : "error" ,
41+ error : response . error ?. message || "Failed to read file" ,
42+ errno : null ,
43+ } ;
44+ }
45+ } catch ( error ) {
46+ return {
47+ type : "error" ,
48+ error : error instanceof Error ? error . message : "Unknown error" ,
49+ errno : null ,
50+ } ;
51+ }
52+ }
53+
54+ async readdir ( path : string ) : Promise < PickRawFsResult < "fs/readdir" > > {
55+ try {
56+ const response = await listDirectory ( {
57+ client : this . apiClient ,
58+ path : {
59+ path : path ,
60+ } ,
61+ } ) ;
62+
63+ if ( response . data ) {
64+ const entries = response . data . files . map ( ( fileInfo ) => ( {
65+ name : fileInfo . name ,
66+ type : fileInfo . isDir ? ( 1 as const ) : ( 0 as const ) , // 1 = directory, 0 = file
67+ isSymlink : false , // API doesn't provide symlink info, defaulting to false
68+ } ) ) ;
69+
70+ return {
71+ type : "ok" ,
72+ result : {
73+ entries : entries ,
74+ } ,
75+ } ;
76+ } else {
77+ return {
78+ type : "error" ,
79+ error : response . error ?. message || "Failed to read directory" ,
80+ errno : null ,
81+ } ;
82+ }
83+ } catch ( error ) {
84+ return {
85+ type : "error" ,
86+ error : error instanceof Error ? error . message : "Unknown error" ,
87+ errno : null ,
88+ } ;
89+ }
90+ }
91+
92+ async writeFile (
93+ path : string ,
94+ content : Uint8Array ,
95+ create ?: boolean ,
96+ overwrite ?: boolean
97+ ) : Promise < PickRawFsResult < "fs/writeFile" > > {
98+ try {
99+ // Convert Uint8Array content to string for the API
100+ const decoder = new TextDecoder ( ) ;
101+ const contentString = decoder . decode ( content ) ;
102+
103+ const response = await createFile ( {
104+ client : this . apiClient ,
105+ path : {
106+ path : path ,
107+ } ,
108+ body : {
109+ content : contentString ,
110+ } ,
111+ } ) ;
112+
113+ if ( response . data ) {
114+ // FSWriteFileResult is an empty object (Record<string, never>)
115+ return {
116+ type : "ok" ,
117+ result : { } ,
118+ } ;
119+ } else {
120+ return {
121+ type : "error" ,
122+ error : response . error ?. message || "Failed to write file" ,
123+ errno : null ,
124+ } ;
125+ }
126+ } catch ( error ) {
127+ return {
128+ type : "error" ,
129+ error : error instanceof Error ? error . message : "Unknown error" ,
130+ errno : null ,
131+ } ;
132+ }
133+ }
134+
135+ async remove (
136+ path : string ,
137+ recursive ?: boolean
138+ ) : Promise < PickRawFsResult < "fs/remove" > > {
139+ try {
140+ const response = await deleteDirectory ( {
141+ client : this . apiClient ,
142+ path : {
143+ path : path ,
144+ } ,
145+ } ) ;
146+
147+ if ( response . data ) {
148+ // FSRemoveResult is an empty object (Record<string, never>)
149+ return {
150+ type : "ok" ,
151+ result : { } ,
152+ } ;
153+ } else {
154+ return {
155+ type : "error" ,
156+ error : response . error ?. message || "Failed to remove directory" ,
157+ errno : null ,
158+ } ;
159+ }
160+ } catch ( error ) {
161+ return {
162+ type : "error" ,
163+ error : error instanceof Error ? error . message : "Unknown error" ,
164+ errno : null ,
165+ } ;
166+ }
167+ }
168+
169+ async mkdir (
170+ path : string ,
171+ recursive ?: boolean
172+ ) : Promise < PickRawFsResult < "fs/mkdir" > > {
173+ try {
174+ const response = await createDirectory ( {
175+ client : this . apiClient ,
176+ path : {
177+ path : path ,
178+ } ,
179+ } ) ;
180+
181+ if ( response . data ) {
182+ // FSMkdirResult is an empty object (Record<string, never>)
183+ return {
184+ type : "ok" ,
185+ result : { } ,
186+ } ;
187+ } else {
188+ return {
189+ type : "error" ,
190+ error : response . error ?. message || "Failed to create directory" ,
191+ errno : null ,
192+ } ;
193+ }
194+ } catch ( error ) {
195+ return {
196+ type : "error" ,
197+ error : error instanceof Error ? error . message : "Unknown error" ,
198+ errno : null ,
199+ } ;
200+ }
201+ }
202+
203+ async stat ( path : string ) : Promise < PickRawFsResult < "fs/stat" > > {
204+ try {
205+ const response = await getFileStat ( {
206+ client : this . apiClient ,
207+ path : {
208+ path : path ,
209+ } ,
210+ } ) ;
211+
212+ if ( response . data ) {
213+ // Parse modTime string to timestamp (assuming ISO string format)
214+ const modTimeMs = new Date ( response . data . modTime ) . getTime ( ) ;
215+
216+ return {
217+ type : "ok" ,
218+ result : {
219+ type : response . data . isDir ? 1 : 0 , // 1 = directory, 0 = file
220+ isSymlink : false , // API doesn't provide symlink info, defaulting to false
221+ size : response . data . size ,
222+ mtime : modTimeMs ,
223+ ctime : modTimeMs , // Using modTime as fallback since API doesn't provide ctime
224+ atime : modTimeMs , // Using modTime as fallback since API doesn't provide atime
225+ } ,
226+ } ;
227+ } else {
228+ return {
229+ type : "error" ,
230+ error : response . error ?. message || "Failed to get file stat" ,
231+ errno : null ,
232+ } ;
233+ }
234+ } catch ( error ) {
235+ return {
236+ type : "error" ,
237+ error : error instanceof Error ? error . message : "Unknown error" ,
238+ errno : null ,
239+ } ;
240+ }
241+ }
242+
243+ async copy (
244+ from : string ,
245+ to : string ,
246+ recursive ?: boolean ,
247+ overwrite ?: boolean
248+ ) : Promise < PickRawFsResult < "fs/copy" > > {
249+ try {
250+ const response = await performFileAction ( {
251+ client : this . apiClient ,
252+ path : {
253+ path : from ,
254+ } ,
255+ body : {
256+ action : 'copy' ,
257+ destination : to ,
258+ } ,
259+ } ) ;
260+
261+ if ( response . data ) {
262+ // FSCopyResult is an empty object (Record<string, never>)
263+ return {
264+ type : "ok" ,
265+ result : { } ,
266+ } ;
267+ } else {
268+ return {
269+ type : "error" ,
270+ error : response . error ?. message || "Failed to copy file" ,
271+ errno : null ,
272+ } ;
273+ }
274+ } catch ( error ) {
275+ return {
276+ type : "error" ,
277+ error : error instanceof Error ? error . message : "Unknown error" ,
278+ errno : null ,
279+ } ;
280+ }
281+ }
282+
283+ async rename (
284+ from : string ,
285+ to : string ,
286+ overwrite ?: boolean
287+ ) : Promise < PickRawFsResult < "fs/rename" > > {
288+ try {
289+ const response = await performFileAction ( {
290+ client : this . apiClient ,
291+ path : {
292+ path : from ,
293+ } ,
294+ body : {
295+ action : 'move' ,
296+ destination : to ,
297+ } ,
298+ } ) ;
299+
300+ if ( response . data ) {
301+ // FSRenameResult is an empty object (Record<string, never>)
302+ return {
303+ type : "ok" ,
304+ result : { } ,
305+ } ;
306+ } else {
307+ return {
308+ type : "error" ,
309+ error : response . error ?. message || "Failed to rename/move file" ,
310+ errno : null ,
311+ } ;
312+ }
313+ } catch ( error ) {
314+ return {
315+ type : "error" ,
316+ error : error instanceof Error ? error . message : "Unknown error" ,
317+ errno : null ,
318+ } ;
319+ }
320+ }
321+
322+ async watch (
323+ path : string ,
324+ options : {
325+ readonly recursive ?: boolean ;
326+ readonly excludes ?: readonly string [ ] ;
327+ } ,
328+ onEvent : ( watchEvent : any ) => void
329+ ) : Promise <
330+ | ( PickRawFsResult < "fs/watch" > & { type : "error" } )
331+ | { type : "success" ; dispose ( ) : void }
332+ > {
333+ throw new Error ( "Not implemented" ) ;
334+ }
335+
336+ async download ( path ?: string ) : Promise < { downloadUrl : string } > {
337+ throw new Error ( "Not implemented" ) ;
338+ }
339+ }
0 commit comments