pull/715/head
Travis Fischer 2025-05-21 01:20:00 +07:00
rodzic 584d692ed7
commit b4dab71399
2 zmienionych plików z 81 dodań i 17 usunięć

Wyświetl plik

@ -2,7 +2,7 @@ import type { Simplify } from 'type-fest'
import defaultKy, { type KyInstance } from 'ky'
import type { operations } from './openapi'
import { getEnv } from './utils'
import { getEnv, sanitizeSearchParams } from './utils'
export class AgenticApiClient {
static readonly DEFAULT_API_BASE_URL = 'https://api.agentic.so'
@ -121,7 +121,9 @@ export class AgenticApiClient {
}: OperationParameters<'listProjects'>): Promise<
OperationResponse<'listProjects'>
> {
return this.ky.get('v1/projects', { searchParams }).json()
return this.ky
.get('v1/projects', { searchParams: sanitizeSearchParams(searchParams) })
.json()
}
async createProject(
@ -137,7 +139,11 @@ export class AgenticApiClient {
}: OperationParameters<'getProject'>): Promise<
OperationResponse<'getProject'>
> {
return this.ky.get(`v1/projects/${projectId}`, { searchParams }).json()
return this.ky
.get(`v1/projects/${projectId}`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
async updateProject(
@ -155,7 +161,11 @@ export class AgenticApiClient {
}: OperationParameters<'getConsumer'>): Promise<
OperationResponse<'getConsumer'>
> {
return this.ky.get(`v1/consumers/${consumerId}`, { searchParams }).json()
return this.ky
.get(`v1/consumers/${consumerId}`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
async updateConsumer(
@ -192,7 +202,9 @@ export class AgenticApiClient {
OperationResponse<'listConsumers'>
> {
return this.ky
.get(`v1/projects/${projectId}/consumers`, { searchParams })
.get(`v1/projects/${projectId}/consumers`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
@ -203,7 +215,9 @@ export class AgenticApiClient {
OperationResponse<'getDeployment'>
> {
return this.ky
.get(`v1/deployments/${deploymentId}`, { searchParams })
.get(`v1/deployments/${deploymentId}`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
@ -219,12 +233,14 @@ export class AgenticApiClient {
.json()
}
async listDeployments({
...searchParams
}: OperationParameters<'listDeployments'>): Promise<
OperationResponse<'listDeployments'>
> {
return this.ky.get('v1/deployments', { searchParams }).json()
async listDeployments(
searchParams: OperationParameters<'listDeployments'>
): Promise<OperationResponse<'listDeployments'>> {
return this.ky
.get('v1/deployments', {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
async createDeployment(
@ -255,18 +271,19 @@ export class AgenticApiClient {
OperationResponse<'adminGetConsumerByToken'>
> {
return this.ky
.get(`v1/admin/consumers/tokens/${token}`, { searchParams })
.get(`v1/admin/consumers/tokens/${token}`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
}
type OperationParameters<
T extends keyof operations,
Q extends object | undefined = operations[T]['parameters']['query'],
P extends object | undefined = operations[T]['parameters']['path']
Q = NonNullable<operations[T]['parameters']['query']>,
P = NonNullable<operations[T]['parameters']['path']>
> = Simplify<
(Q extends never | undefined ? unknown : Q) &
(P extends never | undefined ? unknown : P)
([Q] extends [never] ? unknown : Q) & ([P] extends [never] ? unknown : P)
>
type OperationResponse<T extends keyof operations> =

Wyświetl plik

@ -8,3 +8,50 @@ export function getEnv(name: string): string | undefined {
return undefined
}
}
/**
* Creates a new `URLSearchParams` object with all values coerced to strings
* that correctly handles arrays of values as repeated keys (or CSV) and
* correctly removes `undefined` keys and values.
*/
export function sanitizeSearchParams(
searchParams:
| Record<
string,
string | number | boolean | string[] | number[] | boolean[] | undefined
>
| object,
{
csv = false
}: {
/**
* Whether to use comma-separated-values for arrays or multiple entries.
*
* Defaults to `false` and will use multiple entries.
*/
csv?: boolean
} = {}
): URLSearchParams {
const entries = Object.entries(searchParams).flatMap(([key, value]) => {
if (key === undefined || value === undefined) {
return []
}
if (Array.isArray(value)) {
return value.map((v) => [key, String(v)])
}
return [[key, String(value)]]
}) as [string, string][]
if (!csv) {
return new URLSearchParams(entries)
}
const csvEntries: Record<string, string> = {}
for (const [key, value] of entries) {
csvEntries[key] = csvEntries[key] ? `${csvEntries[key]},${value}` : value
}
return new URLSearchParams(csvEntries)
}