diff --git a/packages/cli/examples/xquik-api.yaml b/packages/cli/examples/xquik-api.yaml new file mode 100644 index 0000000..17de8bd --- /dev/null +++ b/packages/cli/examples/xquik-api.yaml @@ -0,0 +1,60 @@ +openapi: 3.1.0 +info: + title: Xquik API + version: 1.0.0 +servers: + - url: https://xquik.com +security: + - xApiKey: [] +paths: + /api/v1/x/tweets/search: + get: + summary: Search X posts + operationId: searchTweets + parameters: + - name: q + in: query + required: true + description: Search query + schema: + type: string + - name: limit + in: query + required: false + description: Maximum number of posts to return + schema: + type: integer + minimum: 1 + maximum: 100 + responses: + "200": + description: Search results + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + type: object + required: + - id + - text + properties: + id: + type: string + text: + type: string + authorUsername: + type: string + nextCursor: + type: string +components: + securitySchemes: + xApiKey: + type: apiKey + in: header + name: x-api-key diff --git a/packages/sdk/src/lib.test.ts b/packages/sdk/src/lib.test.ts index 47434d1..19b35be 100644 --- a/packages/sdk/src/lib.test.ts +++ b/packages/sdk/src/lib.test.ts @@ -5,6 +5,7 @@ import { fileURLToPath } from 'url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const SAMPLE_SPEC = path.resolve(__dirname, '../../cli/examples/sample-api.yaml'); +const XQUIK_SPEC = path.resolve(__dirname, '../../cli/examples/xquik-api.yaml'); describe('createTools', () => { it('returns a ToolSet with one tool per operation', async () => { @@ -59,6 +60,22 @@ describe('createTools', () => { expect(result.length).toBeLessThanOrEqual(2); }); + it('can load an OpenAPI 3.1 spec with API key auth in code mode', async () => { + const tools = await createTools({ spec: XQUIK_SPEC, codeMode: true }); + expect(Object.keys(tools).sort()).toEqual(['execute', 'search']); + + const searchTool = tools['search']; + const exec = 'execute' in searchTool ? searchTool.execute : undefined; + + const result = await exec!( + { query: 'tweets' }, + { toolCallId: 'x', messages: [], abortSignal: new AbortController().signal } + ) as string; + + expect(result).toContain('searchTweets'); + expect(result).toContain('Search X posts'); + }); + describe('codeMode', () => { it('returns exactly 2 tools when codeMode is true', async () => { const tools = await createTools({ spec: SAMPLE_SPEC, codeMode: true });