Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions src/__tests__/api-clients.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,66 @@ describe('Auxiliary API clients', () => {
);
});

it('FileClient forwards includeHidden to the home and search_subdirs endpoints', async () => {
global.fetch = jest
.fn()
.mockResolvedValueOnce(
new Response(JSON.stringify({ home: '/workspace' }), {
status: 200,
headers: { 'content-type': 'application/json' },
})
)
.mockResolvedValueOnce(
new Response(JSON.stringify({ items: [], next_page_id: null }), {
status: 200,
headers: { 'content-type': 'application/json' },
})
);

const client = new FileClient({ host: 'http://example.com' });
await expect(client.getHome({ includeHidden: true })).resolves.toEqual({
home: '/workspace',
});
await client.searchSubdirectories('/workspace', { includeHidden: true });

expect(global.fetch).toHaveBeenNthCalledWith(
1,
'http://example.com/api/file/home?include_hidden=true',
expect.objectContaining({ method: 'GET' })
);
expect(global.fetch).toHaveBeenNthCalledWith(
2,
'http://example.com/api/file/search_subdirs?path=%2Fworkspace&include_hidden=true',
expect.objectContaining({ method: 'GET' })
);
});

it('FileClient omits include_hidden when includeHidden is not set', async () => {
global.fetch = jest
.fn()
.mockResolvedValueOnce(
new Response(JSON.stringify({ home: '/workspace' }), {
status: 200,
headers: { 'content-type': 'application/json' },
})
)
.mockResolvedValueOnce(
new Response(JSON.stringify({ items: [], next_page_id: null }), {
status: 200,
headers: { 'content-type': 'application/json' },
})
);

const client = new FileClient({ host: 'http://example.com' });
await client.getHome();
await client.searchSubdirectories('/workspace');

expect((global.fetch as jest.Mock).mock.calls[0][0]).toBe('http://example.com/api/file/home');
expect((global.fetch as jest.Mock).mock.calls[1][0]).toBe(
'http://example.com/api/file/search_subdirs?path=%2Fworkspace'
);
});

it('ConversationClient wraps agent-canvas conversation endpoints', async () => {
global.fetch = jest.fn().mockImplementation(() =>
Promise.resolve(
Expand Down
10 changes: 8 additions & 2 deletions src/client/file-client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { HttpClient } from './http-client';
import type {
FileHomeOptions,
FileHomeResponse,
FileSearchSubdirsOptions,
FileSubdirectoryPage,
Expand Down Expand Up @@ -38,13 +39,18 @@ export class FileClient {
path,
page_id: options.pageId,
limit: options.limit,
include_hidden: options.includeHidden || undefined,
},
});
return response.data;
}

async getHome(): Promise<FileHomeResponse> {
const response = await this.client.get<FileHomeResponse>('/api/file/home');
async getHome(options: FileHomeOptions = {}): Promise<FileHomeResponse> {
const response = await this.client.get<FileHomeResponse>('/api/file/home', {
params: {
include_hidden: options.includeHidden || undefined,
},
});
return response.data;
}

Expand Down
14 changes: 14 additions & 0 deletions src/models/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,13 +289,27 @@ export interface FileSubdirectoryPage {
next_page_id: string | null;
}

export interface FileBrowserEntry {
label: string;
path: string;
}

export interface FileHomeResponse {
home: string;
favorites?: FileBrowserEntry[];
locations?: FileBrowserEntry[];
}

export interface FileHomeOptions {
/** Include hidden top-level directories in the response's `favorites`. */
includeHidden?: boolean;
}

export interface FileSearchSubdirsOptions {
pageId?: string | null;
limit?: number;
/** Include hidden subdirectories (names starting with '.'). */
includeHidden?: boolean;
}

export interface CloudProxyRequest {
Expand Down
Loading