Skip to content
Closed
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
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
"import": "./dist/clients.js",
"default": "./dist/clients.js"
},
"./agent-server-api": {
"types": "./dist/generated/agent-server-api.d.ts",
"import": "./dist/generated/agent-server-api.js",
"default": "./dist/generated/agent-server-api.js"
},
"./client/http-client": {
"types": "./dist/client/http-client.d.ts",
"import": "./dist/client/http-client.js",
Expand All @@ -40,6 +45,7 @@
},
"scripts": {
"build": "tsc && node ./scripts/rewrite-relative-imports.mjs",
"generate:openapi-types": "npx --yes openapi-typescript@7.13.0 swagger-doc.json --export-type --default-non-nullable false --root-types --root-types-no-schema-prefix -o src/generated/agent-server-api.ts",
"lint": "eslint src/**/*.ts",
"lint:fix": "eslint src/**/*.ts --fix",
"format": "prettier --write \"src/**/*.ts\" \"examples/**/*.ts\" \"scripts/**/*.mjs\"",
Expand Down
71 changes: 71 additions & 0 deletions src/__tests__/openapi-types.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { ConversationClient } from '../clients';
import type { CreateConversationPayload } from '../clients';
import type {
AgentServerConversationInfo,
SettingsResponse,
SettingsUpdateRequest,
StartConversationRequest,
} from '../index';
import type { StartConversationRequest as SubpathStartConversationRequest } from '../generated/agent-server-api';

const originalFetch = global.fetch;

describe('generated Agent Server OpenAPI types', () => {
afterEach(() => {
global.fetch = originalFetch;
jest.restoreAllMocks();
});

it('types ConversationClient.createConversation with StartConversationRequest', async () => {
const payload: StartConversationRequest = {
workspace: { kind: 'LocalWorkspace', working_dir: '/workspace/project' },
agent_settings: {
agent_kind: 'openhands',
llm: { model: 'anthropic/claude-sonnet-4-5-20250929' },
},
max_iterations: 500,
stuck_detection: true,
};
const clientPayload: CreateConversationPayload = payload;
const subpathPayload: SubpathStartConversationRequest = payload;

const responseBody: Pick<AgentServerConversationInfo, 'id'> = {
id: '11111111-1111-1111-1111-111111111111',
};

global.fetch = jest.fn().mockResolvedValue(
new Response(JSON.stringify(responseBody), {
status: 200,
headers: { 'content-type': 'application/json' },
})
) as typeof fetch;

const client = new ConversationClient({ host: 'http://example.com' });
const conversation = await client.createConversation(clientPayload);

expect(subpathPayload.agent_settings).toEqual(payload.agent_settings);
expect(conversation.id).toBe('11111111-1111-1111-1111-111111111111');
expect(global.fetch).toHaveBeenCalledWith(
'http://example.com/api/conversations',
expect.objectContaining({
method: 'POST',
body: JSON.stringify(payload),
})
);
});

it('exports generated settings request and response shapes', () => {
const update: SettingsUpdateRequest = {
agent_settings_diff: { llm: { model: 'openai/gpt-4o' } },
conversation_settings_diff: { max_iterations: 200 },
};
const response: SettingsResponse = {
agent_settings: { llm: { model: 'openai/gpt-4o' } },
conversation_settings: { max_iterations: 200 },
llm_api_key_is_set: false,
};

expect(update.agent_settings_diff?.llm).toEqual({ model: 'openai/gpt-4o' });
expect(response.llm_api_key_is_set).toBe(false);
});
});
8 changes: 6 additions & 2 deletions src/client/conversation-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@ import type {
ConversationSearchResponse,
UpdateConversationRequest,
} from '../models/conversation';
import type {
ConversationInfo as AgentServerConversationInfo,
StartConversationRequest,
} from '../generated/agent-server-api';

export interface ConversationClientOptions {
host: string;
apiKey?: string;
timeout?: number;
}

export type CreateConversationPayload = Record<string, unknown>;
export type CreateConversationPayload = StartConversationRequest;

export interface SendConversationEventOptions {
run?: boolean;
Expand All @@ -36,7 +40,7 @@ export class ConversationClient {
});
}

async createConversation<TConversation = ConversationInfo>(
async createConversation<TConversation = AgentServerConversationInfo>(
payload: CreateConversationPayload
): Promise<TConversation> {
const response = await this.client.post<TConversation>('/api/conversations', payload);
Expand Down
14 changes: 14 additions & 0 deletions src/clients.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@ export { ApiKeysClient } from './client/api-keys-client';
export { SessionClient } from './client/session-client';
export { SharedClient } from './client/shared-client';

export type {
paths as AgentServerPaths,
components as AgentServerComponents,
operations as AgentServerOperations,
StartConversationRequest,
StartAcpConversationRequest as StartACPConversationRequest,
ConversationInfo as AgentServerConversationInfo,
ConversationPage,
SettingsResponse,
SettingsUpdateRequest,
LocalWorkspaceInput,
AgentBaseInput,
} from './generated/agent-server-api';

export type { ServerClientOptions } from './client/server-client';
export type { BashClientOptions } from './client/bash-client';
export type {
Expand Down
Loading
Loading