pull/715/head
Travis Fischer 2025-06-11 11:31:16 +07:00
rodzic fc40a5ac30
commit eb2932b799
12 zmienionych plików z 818 dodań i 14 usunięć

Wyświetl plik

@ -8,6 +8,7 @@ import pMap from 'p-map'
import { client } from '../src'
const fixtures = [
// TODO: re-add these
// 'basic-raw-free-ts',
// 'basic-raw-free-json',
// 'pricing-freemium',
@ -15,8 +16,9 @@ const fixtures = [
// 'pricing-3-plans',
// 'pricing-monthly-annual',
// 'pricing-custom-0',
'basic-openapi',
'basic-mcp'
// 'basic-openapi',
// 'basic-mcp',
'everything-openapi'
]
const fixturesDir = path.join(

Wyświetl plik

@ -9,7 +9,7 @@ export default defineConfig({
},
toolConfigs: [
{
name: 'getUser',
name: 'get_user',
enabled: true,
pure: true,
// cacheControl: 'no-cache',
@ -23,11 +23,11 @@ export default defineConfig({
}
},
{
name: 'disabledTool',
name: 'disabled_tool',
enabled: false
},
{
name: 'disabledForFreePlanTool',
name: 'disabled_for_free_plan_tool',
pricingPlanOverridesMap: {
free: {
enabled: false
@ -35,35 +35,35 @@ export default defineConfig({
}
},
{
name: 'pureTool',
name: 'pure',
pure: true
},
{
name: 'unpureToolMarkedPure',
name: 'unpure_marked_pure',
pure: true
},
{
name: 'customCacheControlTool',
name: 'custom_cache_control_tool',
cacheControl:
'public, max-age=7200, s-maxage=7200, stale-while-revalidate=3600'
},
{
name: 'noCacheCacheControlTool',
name: 'no_cache_cache_control_tool',
cacheControl: 'no-cache'
},
{
name: 'noStoreCacheControlTool',
name: 'no_store_cache_control_tool',
cacheControl: 'no-store'
},
{
name: 'customRateLimitTool',
name: 'custom_rate_limit_tool',
rateLimit: {
interval: '30s',
maxPerInterval: 10
}
},
{
name: 'disabledRateLimitTool',
name: 'disabled_rate_limit_tool',
rateLimit: null
}
]

Wyświetl plik

@ -0,0 +1,33 @@
import { createRoute, type OpenAPIHono, z } from '@hono/zod-openapi'
const route = createRoute({
description: 'No cache cache control tool',
operationId: 'noCacheCacheControlTool',
method: 'post',
path: '/no-cache-cache-control-tool',
request: {
body: {
content: {
'application/json': {
schema: z.object({}).passthrough()
}
}
}
},
responses: {
200: {
description: 'Echoed request body',
content: {
'application/json': {
schema: z.object({}).passthrough()
}
}
}
}
})
export function registerNoCacheCacheControlTool(app: OpenAPIHono) {
return app.openapi(route, async (c) => {
return c.json(c.req.valid('json'))
})
}

Wyświetl plik

@ -0,0 +1,41 @@
import { createRoute, type OpenAPIHono, z } from '@hono/zod-openapi'
const route = createRoute({
description: 'Unpure tool marked pure',
operationId: 'unpure_marked_pure',
method: 'post',
path: '/unpure-marked-pure',
request: {
body: {
content: {
'application/json': {
schema: z.object({}).passthrough()
}
}
}
},
responses: {
200: {
description: 'Echoed request body with current timestamp to not be pure',
content: {
'application/json': {
schema: z
.object({
now: z.number()
})
.passthrough()
}
}
}
}
})
export function registerUnpureMarkedPure(app: OpenAPIHono) {
return app.openapi(route, async (c) => {
const now = Date.now()
return c.json({
now,
...c.req.valid('json')
}) as any
})
}

Wyświetl plik

@ -11,8 +11,10 @@ import { registerDisabledTool } from './routes/disabled-tool'
import { registerEcho } from './routes/echo'
import { registerGetUser } from './routes/get-user'
import { registerHealthCheck } from './routes/health-check'
import { registerNoCacheCacheControlTool } from './routes/no-cache-cache-control-tool'
import { registerNoStoreCacheControlTool } from './routes/no-store-cache-control-tool'
import { registerPure } from './routes/pure'
import { registerUnpureMarkedPure } from './routes/unpure-marked-pure'
export const app = new OpenAPIHono()
@ -24,14 +26,21 @@ registerDisabledTool(app)
registerDisabledForFreePlanTool(app)
registerEcho(app)
registerPure(app)
registerUnpureMarkedPure(app)
registerCustomCacheControlTool(app)
registerNoStoreCacheControlTool(app)
registerNoCacheCacheControlTool(app)
registerCustomRateLimitTool(app)
registerDisabledRateLimitTool(app)
app.doc31('/docs', {
openapi: '3.1.0',
info: { title: 'OpenAPI server to test everything', version: '0.1.0' }
info: {
title: 'OpenAPI server everything',
description:
"OpenAPI kitchen sink server meant for testing Agentic's origin OpenAPI adapter and ToolConfig features.",
version: '0.1.0'
}
})
const port = process.env.PORT ? Number.parseInt(process.env.PORT) : 3081

Wyświetl plik

@ -71,7 +71,7 @@ export function errorHandler(
}
}
} else {
logger.warn(status, message, err)
logger.warn(status, err)
}
if (isJsonRpcRequest) {

Wyświetl plik

@ -1609,6 +1609,262 @@ Sed tempus felis lobortis leo pulvinar rutrum. Nam mattis velit nisl, eu condime
}
`;
exports[`getToolsFromOpenAPISpec > remote spec https://agentic-platform-fixtures-everything.onrender.com/docs 1`] = `
{
"toolToOperationMap": {
"custom_cache_control_tool": {
"method": "post",
"operationId": "customCacheControlTool",
"parameterSources": {},
"path": "/custom-cache-control-tool",
"tags": undefined,
},
"custom_rate_limit_tool": {
"method": "post",
"operationId": "customRateLimitTool",
"parameterSources": {},
"path": "/custom-rate-limit-tool",
"tags": undefined,
},
"disabled_for_free_plan_tool": {
"method": "get",
"operationId": "disabledForFreePlanTool",
"parameterSources": {},
"path": "/disabled-for-free-plan-tool",
"tags": undefined,
},
"disabled_rate_limit_tool": {
"method": "post",
"operationId": "disabledRateLimitTool",
"parameterSources": {},
"path": "/disabled-rate-limit-tool",
"tags": undefined,
},
"disabled_tool": {
"method": "get",
"operationId": "disabledTool",
"parameterSources": {},
"path": "/disabled-tool",
"tags": undefined,
},
"echo": {
"method": "post",
"operationId": "echo",
"parameterSources": {},
"path": "/echo",
"tags": undefined,
},
"get_user": {
"method": "get",
"operationId": "getUser",
"parameterSources": {
"userId": "path",
},
"path": "/users/{userId}",
"tags": [
"users",
],
},
"health_check": {
"method": "get",
"operationId": "healthCheck",
"parameterSources": {},
"path": "/health",
"tags": undefined,
},
"no_store_cache_control_tool": {
"method": "post",
"operationId": "noStoreCacheControlTool",
"parameterSources": {},
"path": "/no-store-cache-control-tool",
"tags": undefined,
},
"pure": {
"method": "post",
"operationId": "pure",
"parameterSources": {},
"path": "/pure",
"tags": undefined,
},
},
"tools": [
{
"description": "Check if the server is healthy",
"inputSchema": {
"properties": {},
"required": [],
"type": "object",
},
"name": "health_check",
"outputSchema": {
"properties": {
"status": {
"type": "string",
},
},
"required": [
"status",
],
"type": "object",
},
},
{
"description": "Gets a user",
"inputSchema": {
"properties": {
"userId": {
"description": "User ID",
"type": "string",
},
},
"required": [
"userId",
],
"type": "object",
},
"name": "get_user",
"outputSchema": {
"properties": {
"email": {
"type": "string",
},
"id": {
"type": "string",
},
"name": {
"type": "string",
},
},
"required": [
"id",
"name",
"email",
],
"type": "object",
},
},
{
"description": "Disabled tool",
"inputSchema": {
"properties": {},
"required": [],
"type": "object",
},
"name": "disabled_tool",
"outputSchema": {
"properties": {
"status": {
"type": "string",
},
},
"required": [
"status",
],
"type": "object",
},
},
{
"description": "Disabled for free plan tool",
"inputSchema": {
"properties": {},
"required": [],
"type": "object",
},
"name": "disabled_for_free_plan_tool",
"outputSchema": {
"properties": {
"status": {
"type": "string",
},
},
"required": [
"status",
],
"type": "object",
},
},
{
"description": "Echoes the request body",
"inputSchema": {
"properties": {},
"required": [],
"type": "object",
},
"name": "echo",
"outputSchema": {
"properties": {},
"type": "object",
},
},
{
"description": "Pure tool",
"inputSchema": {
"properties": {},
"required": [],
"type": "object",
},
"name": "pure",
"outputSchema": {
"properties": {},
"type": "object",
},
},
{
"description": "Custom cache control tool",
"inputSchema": {
"properties": {},
"required": [],
"type": "object",
},
"name": "custom_cache_control_tool",
"outputSchema": {
"properties": {},
"type": "object",
},
},
{
"description": "No store cache control tool",
"inputSchema": {
"properties": {},
"required": [],
"type": "object",
},
"name": "no_store_cache_control_tool",
"outputSchema": {
"properties": {},
"type": "object",
},
},
{
"description": "Custom rate limit tool",
"inputSchema": {
"properties": {},
"required": [],
"type": "object",
},
"name": "custom_rate_limit_tool",
"outputSchema": {
"properties": {},
"type": "object",
},
},
{
"description": "Disabled rate limit tool",
"inputSchema": {
"properties": {},
"required": [],
"type": "object",
},
"name": "disabled_rate_limit_tool",
"outputSchema": {
"properties": {},
"type": "object",
},
},
],
}
`;
exports[`getToolsFromOpenAPISpec > security.json 1`] = `
{
"toolToOperationMap": {

Wyświetl plik

@ -22506,6 +22506,327 @@ Sed tempus felis lobortis leo pulvinar rutrum. Nam mattis velit nisl, eu condime
}
`;
exports[`validateOpenAPISpec > remote spec https://agentic-platform-fixtures-everything.onrender.com/docs 1`] = `
{
"components": {
"parameters": {},
"schemas": {
"User": {
"properties": {
"email": {
"type": "string",
},
"id": {
"type": "string",
},
"name": {
"type": "string",
},
},
"required": [
"id",
"name",
"email",
],
"type": "object",
},
},
},
"info": {
"title": "OpenAPI server to test everything",
"version": "0.1.0",
},
"openapi": "3.1.0",
"paths": {
"/custom-cache-control-tool": {
"post": {
"description": "Custom cache control tool",
"operationId": "customCacheControlTool",
"requestBody": {
"content": {
"application/json": {
"schema": {
"properties": {},
"type": "object",
},
},
},
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {},
"type": "object",
},
},
},
"description": "Echoed request body",
},
},
},
},
"/custom-rate-limit-tool": {
"post": {
"description": "Custom rate limit tool",
"operationId": "customRateLimitTool",
"requestBody": {
"content": {
"application/json": {
"schema": {
"properties": {},
"type": "object",
},
},
},
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {},
"type": "object",
},
},
},
"description": "Echoed request body",
},
},
},
},
"/disabled-for-free-plan-tool": {
"get": {
"description": "Disabled for free plan tool",
"operationId": "disabledForFreePlanTool",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {
"status": {
"type": "string",
},
},
"required": [
"status",
],
"type": "object",
},
},
},
"description": "OK",
},
},
},
},
"/disabled-rate-limit-tool": {
"post": {
"description": "Disabled rate limit tool",
"operationId": "disabledRateLimitTool",
"requestBody": {
"content": {
"application/json": {
"schema": {
"properties": {},
"type": "object",
},
},
},
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {},
"type": "object",
},
},
},
"description": "Echoed request body",
},
},
},
},
"/disabled-tool": {
"get": {
"description": "Disabled tool",
"operationId": "disabledTool",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {
"status": {
"type": "string",
},
},
"required": [
"status",
],
"type": "object",
},
},
},
"description": "OK",
},
},
},
},
"/echo": {
"post": {
"description": "Echoes the request body",
"operationId": "echo",
"requestBody": {
"content": {
"application/json": {
"schema": {
"properties": {},
"type": "object",
},
},
},
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {},
"type": "object",
},
},
},
"description": "Echoed request body",
},
},
},
},
"/health": {
"get": {
"description": "Check if the server is healthy",
"operationId": "healthCheck",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {
"status": {
"type": "string",
},
},
"required": [
"status",
],
"type": "object",
},
},
},
"description": "OK",
},
},
},
},
"/no-store-cache-control-tool": {
"post": {
"description": "No store cache control tool",
"operationId": "noStoreCacheControlTool",
"requestBody": {
"content": {
"application/json": {
"schema": {
"properties": {},
"type": "object",
},
},
},
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {},
"type": "object",
},
},
},
"description": "Echoed request body",
},
},
},
},
"/pure": {
"post": {
"description": "Pure tool",
"operationId": "pure",
"requestBody": {
"content": {
"application/json": {
"schema": {
"properties": {},
"type": "object",
},
},
},
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {},
"type": "object",
},
},
},
"description": "Echoed request body",
},
},
},
},
"/users/{userId}": {
"get": {
"description": "Gets a user",
"operationId": "getUser",
"parameters": [
{
"description": "User ID",
"in": "path",
"name": "userId",
"required": true,
"schema": {
"type": "string",
},
},
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User",
},
},
},
"description": "A user object",
},
},
"tags": [
"users",
],
},
},
},
"webhooks": {},
}
`;
exports[`validateOpenAPISpec > security.json (file url) 1`] = `
{
"components": {

Wyświetl plik

@ -28,6 +28,16 @@ const fixturesDir = path.join(
)
describe('getToolsFromOpenAPISpec', () => {
test('remote spec https://agentic-platform-fixtures-everything.onrender.com/docs', async () => {
const source =
'https://agentic-platform-fixtures-everything.onrender.com/docs'
const spec = await validateOpenAPISpec(source, {
dereference: true
})
const result = await getToolsFromOpenAPISpec(spec)
expect(result).toMatchSnapshot()
})
for (const fixture of validFixtures) {
test(
fixture,

Wyświetl plik

@ -67,6 +67,13 @@ afterAll(async () => {
})
describe('validateOpenAPISpec', () => {
test('remote spec https://agentic-platform-fixtures-everything.onrender.com/docs', async () => {
const source =
'https://agentic-platform-fixtures-everything.onrender.com/docs'
const result = await validateOpenAPISpec(source)
expect(result).toMatchSnapshot()
})
for (const fixture of fixtures) {
test(
`${fixture} (string)`,

Wyświetl plik

@ -53,6 +53,19 @@ export async function validateOpenAPISpec<
redoclyConfig = await getDefaultRedoclyConfig()
}
if (
typeof source === 'string' &&
(source.startsWith('https://') ||
source.startsWith('http://') ||
source.startsWith('//'))
) {
try {
source = new URL(source)
} catch {
// Not a URL, continue
}
}
let absoluteRef: string
if (source instanceof URL) {
absoluteRef =

Wyświetl plik

@ -130,6 +130,118 @@ exports[`loadAgenticConfig > basic-raw-free-ts 1`] = `
}
`;
exports[`loadAgenticConfig > everything-openapi 1`] = `
{
"name": "test-everything-openapi",
"originAdapter": {
"location": "external",
"spec": "{"openapi":"3.1.0","info":{"title":"OpenAPI server to test everything","version":"0.1.0"},"components":{"schemas":{"User":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"}},"required":["id","name","email"]}},"parameters":{}},"paths":{"/health":{"get":{"description":"Check if the server is healthy","operationId":"healthCheck","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"}},"required":["status"]}}}}}}},"/users/{userId}":{"get":{"description":"Gets a user","tags":["users"],"operationId":"getUser","parameters":[{"schema":{"type":"string"},"required":true,"description":"User ID","name":"userId","in":"path"}],"responses":{"200":{"description":"A user object","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}}}}},"/disabled-tool":{"get":{"description":"Disabled tool","operationId":"disabledTool","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"}},"required":["status"]}}}}}}},"/disabled-for-free-plan-tool":{"get":{"description":"Disabled for free plan tool","operationId":"disabledForFreePlanTool","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"}},"required":["status"]}}}}}}},"/echo":{"post":{"description":"Echoes the request body","operationId":"echo","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"Echoed request body","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/pure":{"post":{"description":"Pure tool","operationId":"pure","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"Echoed request body","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/custom-cache-control-tool":{"post":{"description":"Custom cache control tool","operationId":"customCacheControlTool","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"Echoed request body","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/no-store-cache-control-tool":{"post":{"description":"No store cache control tool","operationId":"noStoreCacheControlTool","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"Echoed request body","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/custom-rate-limit-tool":{"post":{"description":"Custom rate limit tool","operationId":"customRateLimitTool","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"Echoed request body","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/disabled-rate-limit-tool":{"post":{"description":"Disabled rate limit tool","operationId":"disabledRateLimitTool","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"Echoed request body","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}}},"webhooks":{}}",
"type": "openapi",
},
"originUrl": "https://agentic-platform-fixtures-everything.onrender.com",
"pricingIntervals": [
"month",
],
"pricingPlans": [
{
"lineItems": [
{
"amount": 0,
"slug": "base",
"usageType": "licensed",
},
],
"name": "Free",
"slug": "free",
},
],
"toolConfigs": [
{
"enabled": true,
"name": "getUser",
"pricingPlanOverridesMap": {
"free": {
"enabled": true,
"reportUsage": true,
},
},
"pure": true,
"rateLimit": null,
"reportUsage": true,
},
{
"enabled": false,
"name": "disabledTool",
"pure": false,
"reportUsage": true,
},
{
"enabled": true,
"name": "disabledForFreePlanTool",
"pricingPlanOverridesMap": {
"free": {
"enabled": false,
},
},
"pure": false,
"reportUsage": true,
},
{
"enabled": true,
"name": "pureTool",
"pure": true,
"reportUsage": true,
},
{
"enabled": true,
"name": "unpureToolMarkedPure",
"pure": true,
"reportUsage": true,
},
{
"cacheControl": "public, max-age=7200, s-maxage=7200, stale-while-revalidate=3600",
"enabled": true,
"name": "customCacheControlTool",
"pure": false,
"reportUsage": true,
},
{
"cacheControl": "no-cache",
"enabled": true,
"name": "noCacheCacheControlTool",
"pure": false,
"reportUsage": true,
},
{
"cacheControl": "no-store",
"enabled": true,
"name": "noStoreCacheControlTool",
"pure": false,
"reportUsage": true,
},
{
"enabled": true,
"name": "customRateLimitTool",
"pure": false,
"rateLimit": {
"async": true,
"interval": 30,
"maxPerInterval": 10,
},
"reportUsage": true,
},
{
"enabled": true,
"name": "disabledRateLimitTool",
"pure": false,
"rateLimit": null,
"reportUsage": true,
},
],
"version": undefined,
}
`;
exports[`loadAgenticConfig > invalid: invalid-name-0 1`] = `[Error: Invalid project name "Test Invalid Name 0". Must be ascii-only lower kebab-case with no spaces between 1 and 256 characters. For example: "my-project" or "linkedin-resolver-23"]`;
exports[`loadAgenticConfig > invalid: invalid-name-1 1`] = `[Error: Invalid project name "Test-Invalid-Name-1". Must be ascii-only lower kebab-case with no spaces between 1 and 256 characters. For example: "my-project" or "linkedin-resolver-23"]`;