Skip to content

Conversation

@Scra3
Copy link
Member

@Scra3 Scra3 commented Jan 26, 2026

Summary

  • Add AiProxyClient class with a clean, UX-friendly API to interact with ai-proxy from frontend or agent-client
  • Lightweight client: Import from @forestadmin/ai-proxy/client - zero dependencies

⚠️ Breaking Change

Langchain packages are now optional peer dependencies. Users of the server-side features (Router, ProviderDispatcher) must install them manually:

npm install @langchain/core @langchain/openai @langchain/community @langchain/mcp-adapters

Users who only use the client don't need to install anything extra.

API

// Lightweight import - no dependencies
import { createAiProxyClient } from '@forestadmin/ai-proxy/client';

const client = createAiProxyClient({
  baseUrl: 'https://my-agent.com/forest',
  apiKey: 'sk-...',
});

// Simple - just a message
const response = await client.chat('Hello');

// Advanced - with options
const response = await client.chat({
  messages: [{ role: 'user', content: 'Hello' }],
  tools: [...],
  toolChoice: 'auto',
  aiName: 'gpt-4',
});

// List available tools
const tools = await client.getTools();

// Call a tool
const result = await client.callTool('brave_search', [
  { role: 'user', content: 'cats' }
]);

Package Structure

Import Use case Dependencies
@forestadmin/ai-proxy Server-side routing Requires langchain (peer)
@forestadmin/ai-proxy/client Frontend HTTP client None

Test plan

  • All existing tests pass
  • New tests for client methods (16 tests)
  • Build passes
  • Lint passes

🤖 Generated with Claude Code

@qltysh
Copy link

qltysh bot commented Jan 26, 2026

2 new issues

Tool Category Rule Count
qlty Structure Function with high complexity (count = 26): request 1
qlty Structure Function with many parameters (count = 4): constructor 1

@Scra3 Scra3 force-pushed the feat/ai-proxy-client branch from 657874e to 87fbd66 Compare January 26, 2026 10:44
@qltysh
Copy link

qltysh bot commented Jan 26, 2026

Qlty

Coverage Impact

This PR will not change total coverage.

🚦 See full report on Qlty Cloud »

🛟 Help
  • Diff Coverage: Coverage for added or modified lines of code (excludes deleted files). Learn more.

  • Total Coverage: Coverage for the whole repository, calculated as the sum of all File Coverage. Learn more.

  • File Coverage: Covered Lines divided by Covered Lines plus Missed Lines. (Excludes non-executable lines including blank lines and comments.)

    • Indirect Changes: Changes to File Coverage for files that were not modified in this PR. Learn more.

@Scra3 Scra3 force-pushed the feat/ai-proxy-client branch 5 times, most recently from c3a1199 to 544d9ee Compare January 26, 2026 11:03
Add AiProxyClient class with a clean, UX-friendly API:
- chat(input): accepts a simple string or ChatInput object
- getTools(): list available remote tools
- callTool(name, inputs): execute a specific tool

API improvements:
- Simplified chat() that accepts just a string for common use cases
- Consistent camelCase naming (toolChoice, aiName)
- Renamed apiKey (more generic than openAiApiKey)
- Clear method names: chat(), getTools(), callTool()

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@Scra3 Scra3 force-pushed the feat/ai-proxy-client branch from 544d9ee to ba3bcac Compare January 26, 2026 11:06
alban bertolini and others added 13 commits January 26, 2026 12:27
Create a single source of truth for API types by introducing routes.ts.
This file defines types for all routes (ai-query, invoke-remote-tool,
remote-tools) and is imported by both server and client code.

- Add src/routes.ts with shared OpenAI and route types
- Update router.ts to use AiQueryRequest and InvokeToolRequest
- Update provider-dispatcher.ts to import from routes.ts
- Update remote-tools.ts to use RemoteToolDefinition
- Update client/types.ts to re-export from routes.ts
- Maintain backwards compatibility with legacy type aliases

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The dependency is only used for type imports (Logger type), so it
doesn't need to be installed by consumers at runtime.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove legacy type exports (DispatchBody, ChatCompletionResponse, etc.)
since there are no external consumers yet.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Object.setPrototypeOf for proper Error subclass behavior
- Add cause property to preserve original error stack traces
- Add error categorization helpers (isNetworkError, isClientError, isServerError)
- Fail fast when auth required but no apiKey configured
- Handle JSON parse errors on successful responses properly
- Add request context (method, path) to all error messages
- Add tests for edge cases: both json/text fail, non-Error exceptions,
  invalid JSON on success, error cause preservation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Not needed since Node 18+ is the minimum supported version.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Better reflects that this file contains type definitions, not routing logic.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Authentication is handled at a different layer.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
AiProxyClientConfig now uses a union type where fetch and baseUrl are
mutually exclusive:
- Custom fetch mode: { fetch, timeout? }
- Simple mode: { baseUrl, headers?, timeout? }

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Document mutually exclusive config modes (baseUrl vs fetch)
- Remove outdated apiKey references
- Add complex tool example with nested objects, arrays, and enums
- Document error categorization helpers

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Quick Start section at the top
- Remove redundant API Reference and TypeScript sections
- Simplify error handling documentation
- Focus on time-to-first-success

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use toBeInstanceOf(AiProxyClientError) instead of toMatchObject
- Add return value assertions to all tests
- Add tests for default timeout (30s)
- Add tests for empty aiName
- Add tests for URL encoding special characters in aiName/toolName
- Add tests for custom headers overriding Content-Type
- Add tests for concurrent requests with independent abort signals
- Replace expect.anything() with specific assertions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants