diff --git a/apps/e2e/bin/deploy-fixtures.ts b/apps/e2e/bin/deploy-fixtures.ts index ee700c76..816473e2 100644 --- a/apps/e2e/bin/deploy-fixtures.ts +++ b/apps/e2e/bin/deploy-fixtures.ts @@ -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( diff --git a/packages/fixtures/valid/everything-openapi/agentic.config.ts b/packages/fixtures/valid/everything-openapi/agentic.config.ts index 691524cc..237b0df5 100644 --- a/packages/fixtures/valid/everything-openapi/agentic.config.ts +++ b/packages/fixtures/valid/everything-openapi/agentic.config.ts @@ -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 } ] diff --git a/packages/fixtures/valid/everything-openapi/src/routes/no-cache-cache-control-tool.ts b/packages/fixtures/valid/everything-openapi/src/routes/no-cache-cache-control-tool.ts new file mode 100644 index 00000000..6aad71a2 --- /dev/null +++ b/packages/fixtures/valid/everything-openapi/src/routes/no-cache-cache-control-tool.ts @@ -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')) + }) +} diff --git a/packages/fixtures/valid/everything-openapi/src/routes/unpure-marked-pure.ts b/packages/fixtures/valid/everything-openapi/src/routes/unpure-marked-pure.ts new file mode 100644 index 00000000..1262de33 --- /dev/null +++ b/packages/fixtures/valid/everything-openapi/src/routes/unpure-marked-pure.ts @@ -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 + }) +} diff --git a/packages/fixtures/valid/everything-openapi/src/server.ts b/packages/fixtures/valid/everything-openapi/src/server.ts index f57aee6b..9ded7cf2 100644 --- a/packages/fixtures/valid/everything-openapi/src/server.ts +++ b/packages/fixtures/valid/everything-openapi/src/server.ts @@ -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 diff --git a/packages/hono/src/error-handler.ts b/packages/hono/src/error-handler.ts index 803164eb..a4cea0a2 100644 --- a/packages/hono/src/error-handler.ts +++ b/packages/hono/src/error-handler.ts @@ -71,7 +71,7 @@ export function errorHandler( } } } else { - logger.warn(status, message, err) + logger.warn(status, err) } if (isJsonRpcRequest) { diff --git a/packages/openapi-utils/src/__snapshots__/get-tools-from-openapi-spec.test.ts.snap b/packages/openapi-utils/src/__snapshots__/get-tools-from-openapi-spec.test.ts.snap index d7fdcbbc..567fa4f5 100644 --- a/packages/openapi-utils/src/__snapshots__/get-tools-from-openapi-spec.test.ts.snap +++ b/packages/openapi-utils/src/__snapshots__/get-tools-from-openapi-spec.test.ts.snap @@ -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": { diff --git a/packages/openapi-utils/src/__snapshots__/validate-openapi-spec.test.ts.snap b/packages/openapi-utils/src/__snapshots__/validate-openapi-spec.test.ts.snap index 67b9892a..5c160d17 100644 --- a/packages/openapi-utils/src/__snapshots__/validate-openapi-spec.test.ts.snap +++ b/packages/openapi-utils/src/__snapshots__/validate-openapi-spec.test.ts.snap @@ -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": { diff --git a/packages/openapi-utils/src/get-tools-from-openapi-spec.test.ts b/packages/openapi-utils/src/get-tools-from-openapi-spec.test.ts index b472aec0..80972353 100644 --- a/packages/openapi-utils/src/get-tools-from-openapi-spec.test.ts +++ b/packages/openapi-utils/src/get-tools-from-openapi-spec.test.ts @@ -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, diff --git a/packages/openapi-utils/src/validate-openapi-spec.test.ts b/packages/openapi-utils/src/validate-openapi-spec.test.ts index a2a1c153..de138dd1 100644 --- a/packages/openapi-utils/src/validate-openapi-spec.test.ts +++ b/packages/openapi-utils/src/validate-openapi-spec.test.ts @@ -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)`, diff --git a/packages/openapi-utils/src/validate-openapi-spec.ts b/packages/openapi-utils/src/validate-openapi-spec.ts index 8f2f4cbe..8769f94e 100644 --- a/packages/openapi-utils/src/validate-openapi-spec.ts +++ b/packages/openapi-utils/src/validate-openapi-spec.ts @@ -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 = diff --git a/packages/platform/src/__snapshots__/load-agentic-config.test.ts.snap b/packages/platform/src/__snapshots__/load-agentic-config.test.ts.snap index 34f52356..0ba666ab 100644 --- a/packages/platform/src/__snapshots__/load-agentic-config.test.ts.snap +++ b/packages/platform/src/__snapshots__/load-agentic-config.test.ts.snap @@ -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"]`;