This commit is contained in:
Timothy Jaeryang Baek
2026-03-29 21:50:54 -05:00
parent 0ad397c048
commit 6512e085c4
2 changed files with 64 additions and 46 deletions
+49 -31
View File
@@ -58,13 +58,14 @@ export const getCwd = async (baseUrl: string, apiKey: string, sessionId?: string
export const listFiles = async ( export const listFiles = async (
baseUrl: string, baseUrl: string,
apiKey: string, apiKey: string,
path: string = '/' path: string = '/',
sessionId?: string
): Promise<FileEntry[] | null> => { ): Promise<FileEntry[] | null> => {
// The endpoint uses `directory` as the query param name // The endpoint uses `directory` as the query param name
const url = `${baseUrl.replace(/\/$/, '')}/files/list?directory=${encodeURIComponent(path)}`; const url = `${baseUrl.replace(/\/$/, '')}/files/list?directory=${encodeURIComponent(path)}`;
const res = await fetch(url, { const headers: Record<string, string> = { Authorization: `Bearer ${apiKey}` };
headers: { Authorization: `Bearer ${apiKey}` } if (sessionId) headers['X-Session-Id'] = sessionId;
}) const res = await fetch(url, { headers })
.then(async (res) => { .then(async (res) => {
if (!res.ok) throw await res.json(); if (!res.ok) throw await res.json();
return res.json(); return res.json();
@@ -79,12 +80,13 @@ export const listFiles = async (
export const readFile = async ( export const readFile = async (
baseUrl: string, baseUrl: string,
apiKey: string, apiKey: string,
path: string path: string,
sessionId?: string
): Promise<string | null> => { ): Promise<string | null> => {
const url = `${baseUrl.replace(/\/$/, '')}/files/read?path=${encodeURIComponent(path)}`; const url = `${baseUrl.replace(/\/$/, '')}/files/read?path=${encodeURIComponent(path)}`;
const res = await fetch(url, { const headers: Record<string, string> = { Authorization: `Bearer ${apiKey}` };
headers: { Authorization: `Bearer ${apiKey}` } if (sessionId) headers['X-Session-Id'] = sessionId;
}).catch((err) => { const res = await fetch(url, { headers }).catch((err) => {
console.error('open-terminal readFile error:', err); console.error('open-terminal readFile error:', err);
return null; return null;
}); });
@@ -106,12 +108,13 @@ export const readFile = async (
export const downloadFileBlob = async ( export const downloadFileBlob = async (
baseUrl: string, baseUrl: string,
apiKey: string, apiKey: string,
path: string path: string,
sessionId?: string
): Promise<{ blob: Blob; filename: string } | null> => { ): Promise<{ blob: Blob; filename: string } | null> => {
const url = `${baseUrl.replace(/\/$/, '')}/files/view?path=${encodeURIComponent(path)}`; const url = `${baseUrl.replace(/\/$/, '')}/files/view?path=${encodeURIComponent(path)}`;
const res = await fetch(url, { const headers: Record<string, string> = { Authorization: `Bearer ${apiKey}` };
headers: { Authorization: `Bearer ${apiKey}` } if (sessionId) headers['X-Session-Id'] = sessionId;
}).catch(() => null); const res = await fetch(url, { headers }).catch(() => null);
if (!res || !res.ok) return null; if (!res || !res.ok) return null;
@@ -123,15 +126,18 @@ export const downloadFileBlob = async (
export const archiveFromTerminal = async ( export const archiveFromTerminal = async (
baseUrl: string, baseUrl: string,
apiKey: string, apiKey: string,
paths: string[] paths: string[],
sessionId?: string
): Promise<{ blob: Blob; filename: string } | null> => { ): Promise<{ blob: Blob; filename: string } | null> => {
const url = `${baseUrl.replace(/\/$/, '')}/files/archive`; const url = `${baseUrl.replace(/\/$/, '')}/files/archive`;
const headers: Record<string, string> = {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};
if (sessionId) headers['X-Session-Id'] = sessionId;
const res = await fetch(url, { const res = await fetch(url, {
method: 'POST', method: 'POST',
headers: { headers,
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ paths }) body: JSON.stringify({ paths })
}).catch(() => null); }).catch(() => null);
@@ -148,14 +154,17 @@ export const uploadToTerminal = async (
baseUrl: string, baseUrl: string,
apiKey: string, apiKey: string,
directory: string, directory: string,
file: File file: File,
sessionId?: string
): Promise<{ path: string; size: number } | null> => { ): Promise<{ path: string; size: number } | null> => {
const url = `${baseUrl.replace(/\/$/, '')}/files/upload?directory=${encodeURIComponent(directory)}`; const url = `${baseUrl.replace(/\/$/, '')}/files/upload?directory=${encodeURIComponent(directory)}`;
const body = new FormData(); const body = new FormData();
body.append('file', file); body.append('file', file);
const headers: Record<string, string> = { Authorization: `Bearer ${apiKey}` };
if (sessionId) headers['X-Session-Id'] = sessionId;
const res = await fetch(url, { const res = await fetch(url, {
method: 'POST', method: 'POST',
headers: { Authorization: `Bearer ${apiKey}` }, headers,
body body
}) })
.then(async (res) => { .then(async (res) => {
@@ -172,15 +181,18 @@ export const uploadToTerminal = async (
export const createDirectory = async ( export const createDirectory = async (
baseUrl: string, baseUrl: string,
apiKey: string, apiKey: string,
path: string path: string,
sessionId?: string
): Promise<{ path: string } | null> => { ): Promise<{ path: string } | null> => {
const url = `${baseUrl.replace(/\/$/, '')}/files/mkdir`; const url = `${baseUrl.replace(/\/$/, '')}/files/mkdir`;
const headers: Record<string, string> = {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};
if (sessionId) headers['X-Session-Id'] = sessionId;
const res = await fetch(url, { const res = await fetch(url, {
method: 'POST', method: 'POST',
headers: { headers,
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ path }) body: JSON.stringify({ path })
}) })
.then(async (res) => { .then(async (res) => {
@@ -197,12 +209,15 @@ export const createDirectory = async (
export const deleteEntry = async ( export const deleteEntry = async (
baseUrl: string, baseUrl: string,
apiKey: string, apiKey: string,
path: string path: string,
sessionId?: string
): Promise<{ path: string; type: string } | null> => { ): Promise<{ path: string; type: string } | null> => {
const url = `${baseUrl.replace(/\/$/, '')}/files/delete?path=${encodeURIComponent(path)}`; const url = `${baseUrl.replace(/\/$/, '')}/files/delete?path=${encodeURIComponent(path)}`;
const headers: Record<string, string> = { Authorization: `Bearer ${apiKey}` };
if (sessionId) headers['X-Session-Id'] = sessionId;
const res = await fetch(url, { const res = await fetch(url, {
method: 'DELETE', method: 'DELETE',
headers: { Authorization: `Bearer ${apiKey}` } headers
}) })
.then(async (res) => { .then(async (res) => {
if (!res.ok) throw await res.json(); if (!res.ok) throw await res.json();
@@ -247,15 +262,18 @@ export const moveEntry = async (
baseUrl: string, baseUrl: string,
apiKey: string, apiKey: string,
source: string, source: string,
destination: string destination: string,
sessionId?: string
): Promise<{ source: string; destination: string } | { error: string }> => { ): Promise<{ source: string; destination: string } | { error: string }> => {
const url = `${baseUrl.replace(/\/$/, '')}/files/move`; const url = `${baseUrl.replace(/\/$/, '')}/files/move`;
const headers: Record<string, string> = {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};
if (sessionId) headers['X-Session-Id'] = sessionId;
const res = await fetch(url, { const res = await fetch(url, {
method: 'POST', method: 'POST',
headers: { headers,
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ source, destination }) body: JSON.stringify({ source, destination })
}) })
.then(async (res) => { .then(async (res) => {
+15 -15
View File
@@ -331,7 +331,7 @@
savedPath = path; savedPath = path;
pushNavHistory(path); pushNavHistory(path);
const result = await listFiles(terminal.url, terminal.key, path); const result = await listFiles(terminal.url, terminal.key, path, chatId ?? undefined);
loading = false; loading = false;
// Set working directory on the terminal server (fire-and-forget) // Set working directory on the terminal server (fire-and-forget)
@@ -366,22 +366,22 @@
clearFilePreview(); clearFilePreview();
if (isImage(filePath)) { if (isImage(filePath)) {
const result = await downloadFileBlob(terminal.url, terminal.key, filePath); const result = await downloadFileBlob(terminal.url, terminal.key, filePath, chatId ?? undefined);
if (result) fileImageUrl = URL.createObjectURL(result.blob); if (result) fileImageUrl = URL.createObjectURL(result.blob);
} else if (isVideo(filePath)) { } else if (isVideo(filePath)) {
const result = await downloadFileBlob(terminal.url, terminal.key, filePath); const result = await downloadFileBlob(terminal.url, terminal.key, filePath, chatId ?? undefined);
if (result) fileVideoUrl = URL.createObjectURL(result.blob); if (result) fileVideoUrl = URL.createObjectURL(result.blob);
} else if (isAudio(filePath)) { } else if (isAudio(filePath)) {
const result = await downloadFileBlob(terminal.url, terminal.key, filePath); const result = await downloadFileBlob(terminal.url, terminal.key, filePath, chatId ?? undefined);
if (result) fileAudioUrl = URL.createObjectURL(result.blob); if (result) fileAudioUrl = URL.createObjectURL(result.blob);
} else if (isPdf(filePath)) { } else if (isPdf(filePath)) {
const result = await downloadFileBlob(terminal.url, terminal.key, filePath); const result = await downloadFileBlob(terminal.url, terminal.key, filePath, chatId ?? undefined);
if (result) filePdfData = await result.blob.arrayBuffer(); if (result) filePdfData = await result.blob.arrayBuffer();
} else if (isSqlite(filePath)) { } else if (isSqlite(filePath)) {
const result = await downloadFileBlob(terminal.url, terminal.key, filePath); const result = await downloadFileBlob(terminal.url, terminal.key, filePath, chatId ?? undefined);
if (result) fileSqliteData = await result.blob.arrayBuffer(); if (result) fileSqliteData = await result.blob.arrayBuffer();
} else if (isOffice(filePath)) { } else if (isOffice(filePath)) {
const result = await downloadFileBlob(terminal.url, terminal.key, filePath); const result = await downloadFileBlob(terminal.url, terminal.key, filePath, chatId ?? undefined);
if (result) { if (result) {
const ext = getFileExt(filePath); const ext = getFileExt(filePath);
const arrayBuffer = await result.blob.arrayBuffer(); const arrayBuffer = await result.blob.arrayBuffer();
@@ -414,7 +414,7 @@
} }
} }
} else { } else {
fileContent = await readFile(terminal.url, terminal.key, filePath); fileContent = await readFile(terminal.url, terminal.key, filePath, chatId ?? undefined);
} }
fileLoading = false; fileLoading = false;
}; };
@@ -427,7 +427,7 @@
const isDir = path.endsWith('/'); const isDir = path.endsWith('/');
const result = isDir const result = isDir
? await archiveFromTerminal(terminal.url, terminal.key, [path.replace(/\/$/, '')]) ? await archiveFromTerminal(terminal.url, terminal.key, [path.replace(/\/$/, '')])
: await downloadFileBlob(terminal.url, terminal.key, path); : await downloadFileBlob(terminal.url, terminal.key, path, chatId ?? undefined);
if (!result) return; if (!result) return;
const url = URL.createObjectURL(result.blob); const url = URL.createObjectURL(result.blob);
const a = document.createElement('a'); const a = document.createElement('a');
@@ -459,7 +459,7 @@
uploading = true; uploading = true;
for (const file of droppedFiles) { for (const file of droppedFiles) {
await uploadToTerminal(terminal.url, terminal.key, currentPath, file); await uploadToTerminal(terminal.url, terminal.key, currentPath, file, chatId ?? undefined);
} }
uploading = false; uploading = false;
await loadDir(currentPath); await loadDir(currentPath);
@@ -471,7 +471,7 @@
uploading = true; uploading = true;
for (const file of files) { for (const file of files) {
await uploadToTerminal(terminal.url, terminal.key, currentPath, file); await uploadToTerminal(terminal.url, terminal.key, currentPath, file, chatId ?? undefined);
} }
uploading = false; uploading = false;
await loadDir(currentPath); await loadDir(currentPath);
@@ -494,7 +494,7 @@
const terminal = selectedTerminal; const terminal = selectedTerminal;
if (!terminal) return; if (!terminal) return;
const result = await createDirectory(terminal.url, terminal.key, `${currentPath}${name}`); const result = await createDirectory(terminal.url, terminal.key, `${currentPath}${name}`, chatId ?? undefined);
toast[result ? 'success' : 'error']( toast[result ? 'success' : 'error'](
$i18n.t(result ? 'Folder created' : 'Failed to create folder') $i18n.t(result ? 'Folder created' : 'Failed to create folder')
); );
@@ -529,7 +529,7 @@
const terminal = selectedTerminal; const terminal = selectedTerminal;
if (!terminal) return; if (!terminal) return;
const result = await deleteEntry(terminal.url, terminal.key, path); const result = await deleteEntry(terminal.url, terminal.key, path, chatId ?? undefined);
toast[result ? 'success' : 'error']( toast[result ? 'success' : 'error'](
$i18n.t(result ? '{{name}} deleted' : 'Failed to delete {{name}}', { name }) $i18n.t(result ? '{{name}} deleted' : 'Failed to delete {{name}}', { name })
); );
@@ -555,7 +555,7 @@
const sourceDir = source.endsWith('/') ? source : source + '/'; const sourceDir = source.endsWith('/') ? source : source + '/';
if (destFolder.startsWith(sourceDir)) return; if (destFolder.startsWith(sourceDir)) return;
const result = await moveEntry(terminal.url, terminal.key, source, destination); const result = await moveEntry(terminal.url, terminal.key, source, destination, chatId ?? undefined);
if ('error' in result) { if ('error' in result) {
toast.error(result.error); toast.error(result.error);
} else { } else {
@@ -574,7 +574,7 @@
if (oldPath === destination) return; if (oldPath === destination) return;
const result = await moveEntry(terminal.url, terminal.key, oldPath, destination); const result = await moveEntry(terminal.url, terminal.key, oldPath, destination, chatId ?? undefined);
if ('error' in result) { if ('error' in result) {
toast.error(result.error); toast.error(result.error);
} else { } else {