@zuplo/cli 7.9.12 → 7.9.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/integration/source-upgrade.integration.test.d.ts +2 -0
- package/dist/__tests__/integration/source-upgrade.integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration/source-upgrade.integration.test.js +100 -0
- package/dist/__tests__/integration/source-upgrade.integration.test.js.map +1 -0
- package/dist/cmds/source/upgrade.d.ts.map +1 -1
- package/dist/cmds/source/upgrade.js +45 -2
- package/dist/cmds/source/upgrade.js.map +1 -1
- package/dist/source/ai-gateway/catalog.json +411 -0
- package/dist/source/ai-gateway/files.d.ts +16 -0
- package/dist/source/ai-gateway/files.d.ts.map +1 -0
- package/dist/source/ai-gateway/files.js +174 -0
- package/dist/source/ai-gateway/files.js.map +1 -0
- package/dist/source/ai-gateway/files.test.d.ts +2 -0
- package/dist/source/ai-gateway/files.test.d.ts.map +1 -0
- package/dist/source/ai-gateway/files.test.js +135 -0
- package/dist/source/ai-gateway/files.test.js.map +1 -0
- package/dist/source/ai-gateway/handler.d.ts +31 -0
- package/dist/source/ai-gateway/handler.d.ts.map +1 -0
- package/dist/source/ai-gateway/handler.js +140 -0
- package/dist/source/ai-gateway/handler.js.map +1 -0
- package/dist/source/ai-gateway/handler.test.d.ts +2 -0
- package/dist/source/ai-gateway/handler.test.d.ts.map +1 -0
- package/dist/source/ai-gateway/handler.test.js +113 -0
- package/dist/source/ai-gateway/handler.test.js.map +1 -0
- package/dist/source/ai-gateway/package.test.d.ts +2 -0
- package/dist/source/ai-gateway/package.test.d.ts.map +1 -0
- package/dist/source/ai-gateway/package.test.js +30 -0
- package/dist/source/ai-gateway/package.test.js.map +1 -0
- package/dist/source/ai-gateway/planner.d.ts +132 -0
- package/dist/source/ai-gateway/planner.d.ts.map +1 -0
- package/dist/source/ai-gateway/planner.js +365 -0
- package/dist/source/ai-gateway/planner.js.map +1 -0
- package/dist/source/ai-gateway/planner.test.d.ts +2 -0
- package/dist/source/ai-gateway/planner.test.d.ts.map +1 -0
- package/dist/source/ai-gateway/planner.test.js +282 -0
- package/dist/source/ai-gateway/planner.test.js.map +1 -0
- package/dist/source/ai-gateway/release.d.ts +19 -0
- package/dist/source/ai-gateway/release.d.ts.map +1 -0
- package/dist/source/ai-gateway/release.js +75 -0
- package/dist/source/ai-gateway/release.js.map +1 -0
- package/dist/source/ai-gateway/release.test.d.ts +2 -0
- package/dist/source/ai-gateway/release.test.d.ts.map +1 -0
- package/dist/source/ai-gateway/release.test.js +62 -0
- package/dist/source/ai-gateway/release.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/node_modules/@zuplo/core/package.json +1 -1
- package/node_modules/@zuplo/graphql/package.json +1 -1
- package/node_modules/@zuplo/openapi-tools/package.json +1 -1
- package/node_modules/@zuplo/otel/package.json +1 -1
- package/node_modules/@zuplo/runtime/package.json +1 -1
- package/package.json +11 -11
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
{
|
|
2
|
+
"formatVersion": 1,
|
|
3
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
4
|
+
"snapshots": [
|
|
5
|
+
{
|
|
6
|
+
"revision": "f9f94ab6646b82abc66a167c95669a50b3e20a7dea224cac0d3893d4ddde6620",
|
|
7
|
+
"sourceCommit": "3fa357e4ada23887c79964dda62dad06032f418f",
|
|
8
|
+
"files": {
|
|
9
|
+
"README-template.md": "# AI Gateway\n\nThis project is a Zuplo AI Gateway. It exposes the canonical AI Gateway\noperations (`/v1/chat/completions`, `/v1/messages`, `/v1/responses`, and\n`/v1/embeddings`) through `aiGatewayHandlerV2` under `/{app_id}/*`. Only paths\nwhose suffix is a supported `/v1/...` operation succeed; other paths under\n`/{app_id}` return 404.\n\nEach route invokes `ai-gateway-configuration-loader-v2-inbound`, which loads\nthe application's configuration from the `app_id` path segment, then\n`ai-gateway-configuration-executor-v2-inbound`, which runs its\n`inboundPolicyChain`. Applications may select only from the policies\npre-declared in `config/policies.json`. To require application API keys for a\nspecific app, add `ai-gateway-auth-v2-inbound` to that application's\n`inboundPolicyChain`. Adding it on the route before the loader requires a key\nfor every application on the route.\n\n## Customizing the gateway\n\n- Declare additional selectable policies (including custom code policies) in\n `config/policies.json`.\n- Pushes to your default branch deploy the gateway to production.\n",
|
|
10
|
+
"config/ai.oas.json": "{\n \"openapi\": \"3.1.0\",\n \"info\": {\n \"version\": \"1.0.0\",\n \"title\": \"AI Gateway API\",\n \"description\": \"A unified API gateway for multiple AI providers. OpenAI-compatible ops are served under /{app_id}/v1/*; other paths under /{app_id} are rejected.\"\n },\n \"paths\": {\n \"/:app_id/(.*)\": {\n \"x-zuplo-path\": {\n \"pathMode\": \"url-pattern\"\n },\n \"get,post,delete\": {\n \"summary\": \"AI Gateway catch-all\",\n \"description\": \"Routes AI requests under /{app_id}/* to the AI Gateway handler. The configuration loader loads the application configuration from the app_id path segment; the configuration executor then runs the application's inboundPolicyChain. Only paths whose suffix is a supported /v1/... operation succeed (/v1/chat/completions, /v1/embeddings, /v1/messages, /v1/responses and its sub-resources); anything else under /{app_id} returns 404.\",\n \"operationId\": \"aiGatewayCatchAll\",\n \"responses\": {\n \"200\": {\n \"description\": \"Successful AI Gateway response\"\n },\n \"400\": {\n \"description\": \"Bad request\"\n },\n \"401\": {\n \"description\": \"Unauthorized — returned only when the application's inboundPolicyChain includes ai-gateway-auth-v2-inbound, or authentication runs before the configuration loader\"\n },\n \"403\": {\n \"description\": \"Forbidden — returned by per-app policies, such as an API key issued for a different app_id or a model the app does not allow\"\n },\n \"404\": {\n \"description\": \"Unsupported AI Gateway endpoint\"\n },\n \"500\": {\n \"description\": \"Internal server error\"\n }\n },\n \"x-zuplo-route\": {\n \"corsPolicy\": \"none\",\n \"handler\": {\n \"export\": \"aiGatewayHandlerV2\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"policies\": {\n \"inbound\": [\n \"ai-gateway-configuration-loader-v2-inbound\",\n \"ai-gateway-configuration-executor-v2-inbound\"\n ]\n }\n }\n }\n }\n }\n}\n",
|
|
11
|
+
"config/policies.json": "{\n \"policies\": [\n {\n \"handler\": {\n \"export\": \"AIGatewayAuthV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-auth-v2-inbound\",\n \"policyType\": \"ai-gateway-auth-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayConfigurationLoaderV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-configuration-loader-v2-inbound\",\n \"policyType\": \"ai-gateway-configuration-loader-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayConfigurationExecutorV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-configuration-executor-v2-inbound\",\n \"policyType\": \"ai-gateway-configuration-executor-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayMeteringV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-metering-v2-inbound\",\n \"policyType\": \"ai-gateway-metering-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayModelFilteringV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"models\": {\n \"completions\": {\n \"allowList\": [\"openai/gpt-4o-mini\"]\n }\n }\n }\n },\n \"name\": \"ai-gateway-model-filtering-v2-inbound\",\n \"policyType\": \"ai-gateway-model-filtering-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayFallbackModelV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"models\": {\n \"completions\": {\n \"fallback\": \"openai/gpt-4o-mini\"\n }\n },\n \"fallbackTimeoutSeconds\": 60\n }\n },\n \"name\": \"ai-gateway-fallback-model-v2-inbound\",\n \"policyType\": \"ai-gateway-fallback-model-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewaySemanticCacheV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"semanticTolerance\": 0.4,\n \"expirationSecondsTtl\": 3600\n }\n },\n \"name\": \"ai-gateway-semantic-cache-v2-inbound\",\n \"policyType\": \"ai-gateway-semantic-cache-v2-inbound\"\n },\n {\n \"handler\": {\n \"export\": \"AkamaiAIFirewallV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"configurationId\": \"\",\n \"api-key\": \"\"\n }\n },\n \"name\": \"akamai-ai-firewall-v2-inbound\",\n \"policyType\": \"akamai-ai-firewall-v2-inbound\"\n },\n {\n \"handler\": {\n \"export\": \"CometOpikTracingV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"apiKey\": \"\",\n \"projectName\": \"\",\n \"workspace\": \"\"\n }\n },\n \"name\": \"comet-opik-tracing-v2-inbound\",\n \"policyType\": \"comet-opik-tracing-v2-inbound\"\n },\n {\n \"handler\": {\n \"export\": \"GalileoTracingV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"apiKey\": \"\",\n \"projectId\": \"\",\n \"logStreamId\": \"\"\n }\n },\n \"name\": \"galileo-tracing-v2-inbound\",\n \"policyType\": \"galileo-tracing-v2-inbound\"\n }\n ]\n}\n",
|
|
12
|
+
"env.example": "# Optional credentials for the pre-declared AI Gateway policies in\n# config/policies.json. Only required when an application's policy chain\n# selects the matching policy. Configure these as environment variables on\n# your Zuplo project (Settings -> Environment Variables) for deployed\n# environments.\n\n",
|
|
13
|
+
"gitignore": ".zuplo/\n.cache/\ndist/\nnode_modules/\n\n# OS Stuff\n\n.DS_Store\n",
|
|
14
|
+
"tsconfig.json": "{\n \"include\": [\"modules/**/*\", \".zuplo/**/*\"],\n \"exclude\": [\"./node_modules\", \"./dist\", \"./docs\", \"./examples\"],\n \"compilerOptions\": {\n \"module\": \"ESNext\",\n \"target\": \"ES2022\",\n \"lib\": [\"ESNext\", \"WebWorker\", \"Webworker.Iterable\"],\n \"preserveConstEnums\": true,\n \"moduleResolution\": \"Bundler\",\n \"useUnknownInCatchVariables\": false,\n \"forceConsistentCasingInFileNames\": true,\n \"importHelpers\": true,\n \"removeComments\": true,\n \"esModuleInterop\": true,\n \"noEmit\": true,\n \"skipLibCheck\": true,\n \"strictNullChecks\": true,\n \"experimentalDecorators\": true\n }\n}\n",
|
|
15
|
+
"zuplo.jsonc": "{\n \"version\": 1,\n \"compatibilityDate\": \"2026-03-01\"\n}\n"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"revision": "e291749bef80347f9b04b6b48b15c0060d9f46c929fdff584c65e21dd2a1617b",
|
|
20
|
+
"sourceCommit": "4bb1d5adf9be0eebda1a5742d37ea871d012c8e4",
|
|
21
|
+
"files": {
|
|
22
|
+
"README-template.md": "# AI Gateway\n\nThis project is a Zuplo AI Gateway. It exposes the canonical AI Gateway\noperations (`/v1/chat/completions`, `/v1/messages`, `/v1/responses`, and\n`/v1/embeddings`) through `aiGatewayHandlerV2` under `/{app_id}/*`. Only paths\nwhose suffix is a supported `/v1/...` operation succeed; other paths under\n`/{app_id}` return 404.\n\nEach route invokes `ai-gateway-configuration-loader-v2-inbound`, which loads\nthe application's configuration from the `app_id` path segment, then\n`ai-gateway-configuration-executor-v2-inbound`, which runs its\n`inboundPolicyChain`. Applications may select only from the policies\npre-declared in `config/policies.json`. To require application API keys for a\nspecific app, add `ai-gateway-auth-v2-inbound` to that application's\n`inboundPolicyChain`. Adding it on the route before the loader requires a key\nfor every application on the route.\n\n## Customizing the gateway\n\n- Declare additional selectable policies (including custom code policies) in\n `config/policies.json`.\n- Pushes to your default branch deploy the gateway to production.\n",
|
|
23
|
+
"config/ai.oas.json": "{\n \"openapi\": \"3.1.0\",\n \"info\": {\n \"version\": \"1.0.0\",\n \"title\": \"AI Gateway API\",\n \"description\": \"A unified API gateway for multiple AI providers. OpenAI-compatible ops are served under /{app_id}/v1/*; other paths under /{app_id} are rejected.\"\n },\n \"paths\": {\n \"/:app_id/(.*)\": {\n \"x-zuplo-path\": {\n \"pathMode\": \"url-pattern\"\n },\n \"get,post,delete\": {\n \"summary\": \"AI Gateway catch-all\",\n \"description\": \"Routes AI requests under /{app_id}/* to the AI Gateway handler. The configuration loader loads the application configuration from the app_id path segment; the configuration executor then runs the application's inboundPolicyChain. Only paths whose suffix is a supported /v1/... operation succeed (/v1/chat/completions, /v1/embeddings, /v1/messages, /v1/responses and its sub-resources); anything else under /{app_id} returns 404.\",\n \"operationId\": \"aiGatewayCatchAll\",\n \"responses\": {\n \"200\": {\n \"description\": \"Successful AI Gateway response\"\n },\n \"400\": {\n \"description\": \"Bad request\"\n },\n \"401\": {\n \"description\": \"Unauthorized — returned only when the application's inboundPolicyChain includes ai-gateway-auth-v2-inbound, or authentication runs before the configuration loader\"\n },\n \"403\": {\n \"description\": \"Forbidden — returned by per-app policies, such as an API key issued for a different app_id or a model the app does not allow\"\n },\n \"404\": {\n \"description\": \"Unsupported AI Gateway endpoint\"\n },\n \"500\": {\n \"description\": \"Internal server error\"\n }\n },\n \"x-zuplo-route\": {\n \"corsPolicy\": \"none\",\n \"handler\": {\n \"export\": \"aiGatewayHandlerV2\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"policies\": {\n \"inbound\": [\n \"ai-gateway-configuration-loader-v2-inbound\",\n \"ai-gateway-configuration-executor-v2-inbound\"\n ]\n }\n }\n }\n }\n }\n}\n",
|
|
24
|
+
"config/policies.json": "{\n \"policies\": [\n {\n \"handler\": {\n \"export\": \"AIGatewayAuthV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-auth-v2-inbound\",\n \"policyType\": \"ai-gateway-auth-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayConfigurationLoaderV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"cacheTtlSeconds\": 5\n }\n },\n \"name\": \"ai-gateway-configuration-loader-v2-inbound\",\n \"policyType\": \"ai-gateway-configuration-loader-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayConfigurationExecutorV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-configuration-executor-v2-inbound\",\n \"policyType\": \"ai-gateway-configuration-executor-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayMeteringV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-metering-v2-inbound\",\n \"policyType\": \"ai-gateway-metering-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayModelFilteringV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"models\": {\n \"completions\": {\n \"allowList\": [\"openai/gpt-4o-mini\"]\n }\n }\n }\n },\n \"name\": \"ai-gateway-model-filtering-v2-inbound\",\n \"policyType\": \"ai-gateway-model-filtering-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayFallbackModelV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"models\": {\n \"completions\": {\n \"fallback\": \"openai/gpt-4o-mini\"\n }\n },\n \"fallbackTimeoutSeconds\": 60\n }\n },\n \"name\": \"ai-gateway-fallback-model-v2-inbound\",\n \"policyType\": \"ai-gateway-fallback-model-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewaySemanticCacheV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"semanticTolerance\": 0.4,\n \"expirationSecondsTtl\": 3600\n }\n },\n \"name\": \"ai-gateway-semantic-cache-v2-inbound\",\n \"policyType\": \"ai-gateway-semantic-cache-v2-inbound\"\n },\n {\n \"handler\": {\n \"export\": \"AkamaiAIFirewallV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"configurationId\": \"\",\n \"api-key\": \"\"\n }\n },\n \"name\": \"akamai-ai-firewall-v2-inbound\",\n \"policyType\": \"akamai-ai-firewall-v2-inbound\"\n },\n {\n \"handler\": {\n \"export\": \"CometOpikTracingV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"apiKey\": \"\",\n \"projectName\": \"\",\n \"workspace\": \"\"\n }\n },\n \"name\": \"comet-opik-tracing-v2-inbound\",\n \"policyType\": \"comet-opik-tracing-v2-inbound\"\n },\n {\n \"handler\": {\n \"export\": \"GalileoTracingV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"apiKey\": \"\",\n \"projectId\": \"\",\n \"logStreamId\": \"\"\n }\n },\n \"name\": \"galileo-tracing-v2-inbound\",\n \"policyType\": \"galileo-tracing-v2-inbound\"\n }\n ]\n}\n",
|
|
25
|
+
"env.example": "# Optional credentials for the pre-declared AI Gateway policies in\n# config/policies.json. Only required when an application's policy chain\n# selects the matching policy. Configure these as environment variables on\n# your Zuplo project (Settings -> Environment Variables) for deployed\n# environments.\n\n",
|
|
26
|
+
"gitignore": ".zuplo/\n.cache/\ndist/\nnode_modules/\n\n# OS Stuff\n\n.DS_Store\n",
|
|
27
|
+
"tsconfig.json": "{\n \"include\": [\"modules/**/*\", \".zuplo/**/*\"],\n \"exclude\": [\"./node_modules\", \"./dist\", \"./docs\", \"./examples\"],\n \"compilerOptions\": {\n \"module\": \"ESNext\",\n \"target\": \"ES2022\",\n \"lib\": [\"ESNext\", \"WebWorker\", \"Webworker.Iterable\"],\n \"preserveConstEnums\": true,\n \"moduleResolution\": \"Bundler\",\n \"useUnknownInCatchVariables\": false,\n \"forceConsistentCasingInFileNames\": true,\n \"importHelpers\": true,\n \"removeComments\": true,\n \"esModuleInterop\": true,\n \"noEmit\": true,\n \"skipLibCheck\": true,\n \"strictNullChecks\": true,\n \"experimentalDecorators\": true\n }\n}\n",
|
|
28
|
+
"zuplo.jsonc": "{\n \"version\": 1,\n \"compatibilityDate\": \"2026-03-01\"\n}\n"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"revision": "ccce9317ba85ee5807a35073652af29b80c0c97a4cbdc39b16c2b40ed4ce0351",
|
|
33
|
+
"sourceCommit": "ee4e306a854ed7b20316edc68a23d66e950dd9a2",
|
|
34
|
+
"files": {
|
|
35
|
+
"README-template.md": "# AI Gateway\n\nThis project is a Zuplo AI Gateway. It exposes the canonical AI Gateway\noperations (`/v1/chat/completions`, `/v1/messages`, `/v1/responses`, and\n`/v1/embeddings`) through `aiGatewayHandlerV2` under `/{app_id}/*`. Only paths\nwhose suffix is a supported `/v1/...` operation succeed; other paths under\n`/{app_id}` return 404.\n\nEach route invokes `ai-gateway-configuration-loader-v2-inbound`, which loads the\napplication's configuration from the `app_id` path segment, then\n`ai-gateway-configuration-executor-v2-inbound`, which runs its\n`inboundPolicyChain`. Applications may select only from the policies\npre-declared in `config/policies.json`. To require application API keys for a\nspecific app, add `ai-gateway-auth-v2-inbound` to that application's\n`inboundPolicyChain`. Adding it on the route before the loader requires a key\nfor every application on the route.\n\n## Customizing the gateway\n\n- Declare additional selectable policies (including custom code policies) in\n `config/policies.json`.\n- Pushes to your default branch deploy the gateway to production.\n",
|
|
36
|
+
"config/ai.oas.json": "{\n \"openapi\": \"3.1.0\",\n \"info\": {\n \"version\": \"1.0.0\",\n \"title\": \"AI Gateway API\",\n \"description\": \"A unified API gateway for multiple AI providers. OpenAI-compatible ops are served under /{app_id}/v1/*, AWS Bedrock Runtime ops under /{app_id}/model/{modelId}/{operation}; other paths under /{app_id} are rejected.\"\n },\n \"paths\": {\n \"/:app_id/(.*)\": {\n \"x-zuplo-path\": {\n \"pathMode\": \"url-pattern\"\n },\n \"get,post,put,patch,delete,head\": {\n \"summary\": \"AI Gateway catch-all\",\n \"description\": \"Routes AI requests under /{app_id}/* to the AI Gateway handler. The configuration loader loads the application configuration from the app_id path segment; the configuration executor then runs the application's inboundPolicyChain. Two path shapes succeed: a supported /v1/... operation (see resolveBasePath in packages/runtime/src/llm-translation/index.ts for the current set) and a Bedrock Runtime operation addressed AWS's way as /model/{modelId}/{operation} (see matchBedrockRuntimeRoute in packages/runtime/src/ai-gateway/bedrock-runtime-route.ts). Anything else under /{app_id} returns 404.\",\n \"operationId\": \"aiGatewayCatchAll\",\n \"responses\": {\n \"200\": {\n \"description\": \"Successful AI Gateway response\"\n },\n \"400\": {\n \"description\": \"Bad request\"\n },\n \"401\": {\n \"description\": \"Unauthorized — returned only when the application's inboundPolicyChain includes ai-gateway-auth-v2-inbound, or authentication runs before the configuration loader\"\n },\n \"403\": {\n \"description\": \"Forbidden — returned by per-app policies, such as an API key issued for a different app_id or a model the app does not allow\"\n },\n \"404\": {\n \"description\": \"Unsupported AI Gateway endpoint\"\n },\n \"500\": {\n \"description\": \"Internal server error\"\n }\n },\n \"x-zuplo-route\": {\n \"corsPolicy\": \"none\",\n \"handler\": {\n \"export\": \"aiGatewayHandlerV2\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"policies\": {\n \"inbound\": [\n \"ai-gateway-configuration-loader-v2-inbound\",\n \"ai-gateway-configuration-executor-v2-inbound\"\n ]\n }\n }\n }\n }\n }\n}\n",
|
|
37
|
+
"config/policies.json": "{\n \"policies\": [\n {\n \"handler\": {\n \"export\": \"AIGatewayAuthV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-auth-v2-inbound\",\n \"policyType\": \"ai-gateway-auth-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayInternalOnlyInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-internal-only-inbound\",\n \"policyType\": \"ai-gateway-internal-only\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayConfigurationLoaderV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"cacheTtlSeconds\": 5\n }\n },\n \"name\": \"ai-gateway-configuration-loader-v2-inbound\",\n \"policyType\": \"ai-gateway-configuration-loader-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayConfigurationExecutorV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-configuration-executor-v2-inbound\",\n \"policyType\": \"ai-gateway-configuration-executor-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayMeteringV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-metering-v2-inbound\",\n \"policyType\": \"ai-gateway-metering-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayModelFilteringV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"models\": {\n \"completions\": {\n \"allowList\": [\"openai/gpt-4o-mini\"]\n }\n }\n }\n },\n \"name\": \"ai-gateway-model-filtering-v2-inbound\",\n \"policyType\": \"ai-gateway-model-filtering-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayFallbackModelV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"models\": {\n \"completions\": {\n \"fallback\": \"openai/gpt-4o-mini\"\n }\n },\n \"fallbackTimeoutSeconds\": 60\n }\n },\n \"name\": \"ai-gateway-fallback-model-v2-inbound\",\n \"policyType\": \"ai-gateway-fallback-model-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewaySemanticCacheV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"semanticTolerance\": 0.4,\n \"expirationSecondsTtl\": 3600\n }\n },\n \"name\": \"ai-gateway-semantic-cache-v2-inbound\",\n \"policyType\": \"ai-gateway-semantic-cache-v2-inbound\"\n },\n {\n \"handler\": {\n \"export\": \"AkamaiAIFirewallV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"configurationId\": \"\",\n \"api-key\": \"\"\n }\n },\n \"name\": \"akamai-ai-firewall-v2-inbound\",\n \"policyType\": \"akamai-ai-firewall-v2-inbound\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayPromptInjectionPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"execution\": \"parallel\"\n }\n },\n \"name\": \"ai-gateway-prompt-injection\",\n \"policyType\": \"ai-gateway-prompt-injection\"\n },\n {\n \"handler\": {\n \"export\": \"CometOpikTracingV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"apiKey\": \"\",\n \"projectName\": \"\",\n \"workspace\": \"\"\n }\n },\n \"name\": \"comet-opik-tracing-v2-inbound\",\n \"policyType\": \"comet-opik-tracing-v2-inbound\"\n },\n {\n \"handler\": {\n \"export\": \"GalileoTracingV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"apiKey\": \"\",\n \"projectId\": \"\",\n \"logStreamId\": \"\"\n }\n },\n \"name\": \"galileo-tracing-v2-inbound\",\n \"policyType\": \"galileo-tracing-v2-inbound\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayDlpInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"rules\": {\n \"inbound\": {\n \"pii\": {\n \"action\": \"mask\"\n },\n \"contact-email\": {\n \"action\": \"off\"\n },\n \"finance-credit-card\": {\n \"action\": \"mask\"\n },\n \"finance-iban\": {\n \"action\": \"mask\"\n }\n },\n \"outbound\": {\n \"pii\": {\n \"action\": \"mask\"\n },\n \"contact-email\": {\n \"action\": \"off\"\n },\n \"finance-credit-card\": {\n \"action\": \"mask\"\n },\n \"finance-iban\": {\n \"action\": \"mask\"\n }\n }\n }\n }\n },\n \"name\": \"ai-gateway-dlp-inbound\",\n \"policyType\": \"ai-gateway-dlp\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewaySmartRouterInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"classifierAppID\": \"\",\n \"classifierModel\": \"openai/gpt-4o-mini\",\n \"smartRoutingEnabled\": false,\n \"modelsByComplexity\": {\n \"low\": \"openai/gpt-4o-mini\",\n \"medium\": \"openai/gpt-4o\",\n \"high\": \"openai/gpt-5\"\n }\n }\n },\n \"name\": \"ai-gateway-smart-router-inbound\",\n \"policyType\": \"ai-gateway-smart-router\"\n }\n ]\n}\n",
|
|
38
|
+
"env.example": "# Optional credentials for the pre-declared AI Gateway policies in\n# config/policies.json. Only required when an application's policy chain\n# selects the matching policy. Configure these as environment variables on\n# your Zuplo project (Settings -> Environment Variables) for deployed\n# environments.\n\n",
|
|
39
|
+
"gitignore": ".zuplo/\n.cache/\ndist/\nnode_modules/\n\n# OS Stuff\n\n.DS_Store\n",
|
|
40
|
+
"tsconfig.json": "{\n \"include\": [\"modules/**/*\", \".zuplo/**/*\"],\n \"exclude\": [\"./node_modules\", \"./dist\", \"./docs\", \"./examples\"],\n \"compilerOptions\": {\n \"module\": \"ESNext\",\n \"target\": \"ES2022\",\n \"lib\": [\"ESNext\", \"WebWorker\", \"Webworker.Iterable\"],\n \"preserveConstEnums\": true,\n \"moduleResolution\": \"Bundler\",\n \"useUnknownInCatchVariables\": false,\n \"forceConsistentCasingInFileNames\": true,\n \"importHelpers\": true,\n \"removeComments\": true,\n \"esModuleInterop\": true,\n \"noEmit\": true,\n \"skipLibCheck\": true,\n \"strictNullChecks\": true,\n \"experimentalDecorators\": true\n }\n}\n",
|
|
41
|
+
"zuplo.jsonc": "{\n \"version\": 1,\n \"compatibilityDate\": \"2026-03-01\"\n}\n"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"revision": "5a36ec349bb12f720f8e4e70c9799a5c35c62cc08106bd7f17b319c348d2a483",
|
|
46
|
+
"sourceCommit": "28e3ec39391f174b51a63fe03c2f389480507798",
|
|
47
|
+
"files": {
|
|
48
|
+
"README-template.md": "## Zuplo AI Gateway\n\nThis is a Zuplo AI Gateway that was created with\n[`create-zuplo-api`](https://zuplo.com/docs). It gives your applications one\nOpenAI-compatible API in front of many AI providers, with per-app keys, model\ncontrols, budgets, caching, and guardrails.\n\n## Getting Started\n\nThe gateway loads each app's configuration (providers, models, and policies)\nfrom your Zuplo account at request time, so the project must be linked to a\nZuplo project before it can serve requests.\n\n1. Link the project. This writes your project's settings to `.env.zuplo`, which\n is gitignored:\n\n ```bash\n npx zuplo link\n ```\n\n2. In the [Zuplo Portal](https://portal.zuplo.com), add a provider and create an\n app. Each app gets its own API URL and API key. See\n [Apps](https://zuplo.com/docs/ai-gateway/apps).\n\n3. Start the development server:\n\n ```bash\n npm run dev\n # or\n yarn dev\n # or\n pnpm dev\n ```\n\n4. Send a request to the local gateway. Replace `<app_id>` with the ID from your\n app's API URL and set `ZUPLO_APP_API_KEY` to the app's API key:\n\n ```bash\n curl http://localhost:9000/<app_id>/v1/chat/completions \\\n -H \"Authorization: Bearer $ZUPLO_APP_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"openai/gpt-4o-mini\",\n \"messages\": [{ \"role\": \"user\", \"content\": \"Say hi\" }]\n }'\n ```\n\n## Endpoints\n\nEvery request is scoped to an app by the first path segment, `/{app_id}`. For\nthe supported endpoints and which providers serve each one, see the\n[AI Gateway documentation](https://zuplo.com/docs/ai-gateway/overview).\n\n## Project Structure\n\n| Path | What it does |\n| -------------------------- | ---------------------------------------------------------------------- |\n| `config/ai.oas.json` | The catch-all route that sends `/{app_id}/*` to the AI Gateway handler |\n| `config/policies.json` | The policies an app can select for its policy chain |\n| `modules/zuplo.runtime.ts` | Runtime plugins, such as tracing and logging |\n| `.env.example` | Sample environment variables. Copy it to `.env` for local development |\n\nAn app runs only the policies listed in its policy chain, and it can select only\npolicies declared in `config/policies.json`. To add your own policy, write it in\n`modules/` and declare it in `config/policies.json`.\n\n## Debugging\n\nIn VS Code, open **Run and Debug**, select **Launch & Attach Zuplo**, and click\nthe green play button.\n\nFor other editors and more details, see the\n[debugging guide](https://zuplo.com/docs/articles/local-development-debugging).\n\n## Deploying\n\nConnect the project to source control in the Zuplo Portal. Pushes to your\ndefault branch deploy the gateway to production.\n\n## Learn More\n\nTo learn more about the AI Gateway, visit the\n[AI Gateway documentation](https://zuplo.com/docs/ai-gateway/overview).\n\nTo connect with the community join [Discord](https://discord.zuplo.com).\n",
|
|
49
|
+
"config/ai.oas.json": "{\n \"openapi\": \"3.1.0\",\n \"info\": {\n \"version\": \"1.0.0\",\n \"title\": \"AI Gateway API\",\n \"description\": \"A unified API gateway for multiple AI providers. OpenAI-compatible ops are served under /{app_id}/v1/*, AWS Bedrock Runtime ops under /{app_id}/model/{modelId}/{operation}; other paths under /{app_id} are rejected.\"\n },\n \"paths\": {\n \"/u/:app_id/(.*)\": {\n \"x-zuplo-path\": {\n \"pathMode\": \"url-pattern\"\n },\n \"get,post,put,patch,delete,head\": {\n \"summary\": \"AI Gateway User App catch-all\",\n \"description\": \"Routes User App requests under /u/{app_id}/* to the AI Gateway handler. The configuration kind must be ai-user-app.\",\n \"operationId\": \"aiGatewayUserAppCatchAll\",\n \"responses\": {\n \"200\": {\n \"description\": \"Successful AI Gateway response\"\n },\n \"400\": {\n \"description\": \"Bad request\"\n },\n \"403\": {\n \"description\": \"Forbidden \\u2014 public User App routes require trusted internal access; application API keys cannot authenticate trusted User App calls\"\n },\n \"404\": {\n \"description\": \"Unsupported AI Gateway endpoint\"\n },\n \"500\": {\n \"description\": \"Internal server error\"\n }\n },\n \"x-zuplo-route\": {\n \"corsPolicy\": \"none\",\n \"handler\": {\n \"export\": \"aiGatewayHandlerV2\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"policies\": {\n \"inbound\": [\n \"ai-gateway-configuration-loader-v2-inbound\",\n \"ai-gateway-configuration-executor-v2-inbound\"\n ]\n }\n }\n }\n },\n \"/a/:app_id/(.*)\": {\n \"x-zuplo-path\": {\n \"pathMode\": \"url-pattern\"\n },\n \"get,post,put,patch,delete,head\": {\n \"summary\": \"AI Gateway AI App catch-all\",\n \"description\": \"Routes AI App requests under /a/{app_id}/* to the AI Gateway handler. The configuration kind must be ai-app.\",\n \"operationId\": \"aiGatewayAIAppCatchAll\",\n \"responses\": {\n \"200\": {\n \"description\": \"Successful AI Gateway response\"\n },\n \"400\": {\n \"description\": \"Bad request\"\n },\n \"401\": {\n \"description\": \"Unauthorized \\u2014 returned only when the application's inboundPolicyChain includes ai-gateway-auth-v2-inbound, or authentication runs before the configuration loader\"\n },\n \"403\": {\n \"description\": \"Forbidden \\u2014 returned by per-app policies, such as an API key issued for a different app_id or a model the app does not allow\"\n },\n \"404\": {\n \"description\": \"Unsupported AI Gateway endpoint\"\n },\n \"500\": {\n \"description\": \"Internal server error\"\n }\n },\n \"x-zuplo-route\": {\n \"corsPolicy\": \"none\",\n \"handler\": {\n \"export\": \"aiGatewayHandlerV2\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"policies\": {\n \"inbound\": [\n \"ai-gateway-configuration-loader-v2-inbound\",\n \"ai-gateway-configuration-executor-v2-inbound\"\n ]\n }\n }\n }\n },\n \"/:app_id/(.*)\": {\n \"x-zuplo-path\": {\n \"pathMode\": \"url-pattern\"\n },\n \"get,post,put,patch,delete,head\": {\n \"summary\": \"AI Gateway catch-all\",\n \"description\": \"Routes AI requests under /{app_id}/* to the AI Gateway handler. The configuration loader loads the application configuration from the app_id path segment; the configuration executor then runs the application's inboundPolicyChain. Two path shapes succeed: a supported /v1/... operation (see resolveBasePath in packages/runtime/src/llm-translation/index.ts for the current set) and a Bedrock Runtime operation addressed AWS's way as /model/{modelId}/{operation} (see matchBedrockRuntimeRoute in packages/runtime/src/ai-gateway/bedrock-runtime-route.ts). Anything else under /{app_id} returns 404.\",\n \"operationId\": \"aiGatewayCatchAll\",\n \"responses\": {\n \"200\": {\n \"description\": \"Successful AI Gateway response\"\n },\n \"400\": {\n \"description\": \"Bad request\"\n },\n \"401\": {\n \"description\": \"Unauthorized \\u2014 returned only when the application's inboundPolicyChain includes ai-gateway-auth-v2-inbound, or authentication runs before the configuration loader\"\n },\n \"403\": {\n \"description\": \"Forbidden \\u2014 returned by per-app policies, such as an API key issued for a different app_id or a model the app does not allow\"\n },\n \"404\": {\n \"description\": \"Unsupported AI Gateway endpoint\"\n },\n \"500\": {\n \"description\": \"Internal server error\"\n }\n },\n \"x-zuplo-route\": {\n \"corsPolicy\": \"none\",\n \"handler\": {\n \"export\": \"aiGatewayHandlerV2\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"policies\": {\n \"inbound\": [\n \"ai-gateway-configuration-loader-v2-inbound\",\n \"ai-gateway-configuration-executor-v2-inbound\"\n ]\n }\n }\n }\n }\n }\n}\n",
|
|
50
|
+
"config/policies.json": "{\n \"policies\": [\n {\n \"handler\": {\n \"export\": \"AIGatewayAuthV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-auth-v2-inbound\",\n \"policyType\": \"ai-gateway-auth-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayInternalOnlyInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-internal-only-inbound\",\n \"policyType\": \"ai-gateway-internal-only\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayConfigurationLoaderV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"cacheTtlSeconds\": 5\n }\n },\n \"name\": \"ai-gateway-configuration-loader-v2-inbound\",\n \"policyType\": \"ai-gateway-configuration-loader-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayConfigurationExecutorV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-configuration-executor-v2-inbound\",\n \"policyType\": \"ai-gateway-configuration-executor-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayMeteringV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-metering-v2-inbound\",\n \"policyType\": \"ai-gateway-metering-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayModelFilteringV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"models\": {\n \"completions\": {\n \"allowList\": [\"openai/gpt-4o-mini\"]\n }\n }\n }\n },\n \"name\": \"ai-gateway-model-filtering-v2-inbound\",\n \"policyType\": \"ai-gateway-model-filtering-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayFallbackModelV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"models\": {\n \"completions\": {\n \"fallback\": \"openai/gpt-4o-mini\"\n }\n },\n \"fallbackTimeoutSeconds\": 60\n }\n },\n \"name\": \"ai-gateway-fallback-model-v2-inbound\",\n \"policyType\": \"ai-gateway-fallback-model-v2\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewaySemanticCacheV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"semanticTolerance\": 0.4,\n \"expirationSecondsTtl\": 3600\n }\n },\n \"name\": \"ai-gateway-semantic-cache-v2-inbound\",\n \"policyType\": \"ai-gateway-semantic-cache-v2-inbound\"\n },\n {\n \"handler\": {\n \"export\": \"AkamaiAIFirewallV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"configurationId\": \"\",\n \"api-key\": \"\"\n }\n },\n \"name\": \"akamai-ai-firewall-v2-inbound\",\n \"policyType\": \"akamai-ai-firewall-v2-inbound\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayPromptInjectionPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"execution\": \"parallel\"\n }\n },\n \"name\": \"ai-gateway-prompt-injection\",\n \"policyType\": \"ai-gateway-prompt-injection\"\n },\n {\n \"handler\": {\n \"export\": \"CometOpikTracingV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"apiKey\": \"\",\n \"projectName\": \"\",\n \"workspace\": \"\"\n }\n },\n \"name\": \"comet-opik-tracing-v2-inbound\",\n \"policyType\": \"comet-opik-tracing-v2-inbound\"\n },\n {\n \"handler\": {\n \"export\": \"GalileoTracingV2InboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"apiKey\": \"\",\n \"projectId\": \"\",\n \"logStreamId\": \"\"\n }\n },\n \"name\": \"galileo-tracing-v2-inbound\",\n \"policyType\": \"galileo-tracing-v2-inbound\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayDlpInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"rules\": {\n \"inbound\": {\n \"pii\": {\n \"action\": \"mask\"\n },\n \"contact-email\": {\n \"action\": \"off\"\n },\n \"finance-credit-card\": {\n \"action\": \"mask\"\n },\n \"finance-iban\": {\n \"action\": \"mask\"\n }\n },\n \"outbound\": {\n \"pii\": {\n \"action\": \"mask\"\n },\n \"contact-email\": {\n \"action\": \"off\"\n },\n \"finance-credit-card\": {\n \"action\": \"mask\"\n },\n \"finance-iban\": {\n \"action\": \"mask\"\n }\n }\n }\n }\n },\n \"name\": \"ai-gateway-dlp-inbound\",\n \"policyType\": \"ai-gateway-dlp\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewaySmartRouterInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"classifierAppID\": \"\",\n \"classifierModel\": \"openai/gpt-4o-mini\",\n \"smartRoutingEnabled\": false,\n \"modelsByComplexity\": {\n \"low\": \"openai/gpt-4o-mini\",\n \"medium\": \"openai/gpt-4o\",\n \"high\": \"openai/gpt-5\"\n }\n }\n },\n \"name\": \"ai-gateway-smart-router-inbound\",\n \"policyType\": \"ai-gateway-smart-router\"\n }\n ]\n}\n",
|
|
51
|
+
"modules/zuplo.runtime.ts": "import type { RuntimeExtensions } from \"@zuplo/runtime\";\n\n/**\n * `runtimeInit` runs once when your gateway boots. Use it to register plugins\n * and lifecycle hooks. Docs:\n * https://zuplo.com/docs/programmable-api/runtime-extensions\n */\nexport function runtimeInit(runtime: RuntimeExtensions) {\n // `runtime` is unused until you enable a plugin below. This reference keeps\n // linters from flagging it; delete it once you call `runtime.addPlugin`.\n void runtime;\n\n // --- OpenTelemetry tracing (optional) ------------------------------------\n // Send traces to Zuplo's built-in tracing. This can also be configured to\n // send traces to a third-party service such as Honeycomb, Grafana, and\n // others. Docs: https://zuplo.com/docs/articles/opentelemetry\n //\n // To enable, run `npm install @zuplo/otel`, then import `OpenTelemetryPlugin`\n // from \"@zuplo/otel\" and `environment` from \"@zuplo/runtime\":\n // const isWorkingCopy =\n // environment.ZUPLO_ENVIRONMENT_STAGE === \"working-copy\";\n // runtime.addPlugin(\n // new OpenTelemetryPlugin({\n // sampling: {\n // headSampler: { ratio: isWorkingCopy ? 1 : 0.1 },\n // },\n // }),\n // );\n // --- Logging (optional) --------------------------------------------------\n // Ship request logs to Datadog. Other log integrations (New Relic, Splunk,\n // Loki, Dynatrace, and others) follow the same pattern — see the logging\n // overview at https://zuplo.com/docs/articles/logging.\n // Docs: https://zuplo.com/docs/articles/log-plugin-datadog\n //\n // To enable, import the plugin and `environment` from \"@zuplo/runtime\":\n // runtime.addPlugin(\n // new DataDogLoggingPlugin({\n // apiKey: environment.DATADOG_API_KEY,\n // source: \"my-ai-gateway\",\n // }),\n // );\n}\n",
|
|
52
|
+
"tsconfig.json": "{\n \"include\": [\"modules/**/*\", \".zuplo/**/*\"],\n \"exclude\": [\"./node_modules\", \"./dist\", \"./docs\", \"./examples\"],\n \"compilerOptions\": {\n \"module\": \"ESNext\",\n \"target\": \"ES2022\",\n \"lib\": [\"ESNext\", \"WebWorker\", \"Webworker.Iterable\"],\n \"preserveConstEnums\": true,\n \"moduleResolution\": \"Bundler\",\n \"useUnknownInCatchVariables\": false,\n \"forceConsistentCasingInFileNames\": true,\n \"importHelpers\": true,\n \"removeComments\": true,\n \"esModuleInterop\": true,\n \"noEmit\": true,\n \"skipLibCheck\": true,\n \"strictNullChecks\": true,\n \"experimentalDecorators\": true\n }\n}\n",
|
|
53
|
+
"zuplo.jsonc": "{\n \"version\": 1,\n \"compatibilityDate\": \"2026-03-01\"\n}\n"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"revision": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
58
|
+
"sourceCommit": "305f4ccb60af80b580ce8271b9e100554aadc61a",
|
|
59
|
+
"files": {
|
|
60
|
+
"README-template.md": "## Zuplo AI Gateway\n\nThis is a Zuplo AI Gateway that was created with\n[`create-zuplo-api`](https://zuplo.com/docs). It gives your applications one\nOpenAI-compatible API in front of many AI providers, with per-app keys, model\ncontrols, budgets, caching, and guardrails.\n\n## Getting Started\n\nThe gateway loads each app's configuration (providers, models, and policies)\nfrom your Zuplo account at request time, so the project must be linked to a\nZuplo project before it can serve requests.\n\n1. Link the project. This writes your project's settings to `.env.zuplo`, which\n is gitignored:\n\n ```bash\n npx zuplo link\n ```\n\n2. In the [Zuplo Portal](https://portal.zuplo.com), add a provider and create an\n app. Each app gets its own API URL and API key. See\n [Apps](https://zuplo.com/docs/ai-gateway/apps).\n\n3. Start the development server:\n\n ```bash\n npm run dev\n # or\n yarn dev\n # or\n pnpm dev\n ```\n\n4. Send a request to the local gateway. Replace `<app_id>` with the ID from your\n app's API URL and set `ZUPLO_APP_API_KEY` to the app's API key:\n\n ```bash\n curl http://localhost:9000/<app_id>/v1/chat/completions \\\n -H \"Authorization: Bearer $ZUPLO_APP_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"openai/gpt-4o-mini\",\n \"messages\": [{ \"role\": \"user\", \"content\": \"Say hi\" }]\n }'\n ```\n\n## Endpoints\n\nEvery request is scoped to an app by the first path segment, `/{app_id}`. For\nthe supported endpoints and which providers serve each one, see the\n[AI Gateway documentation](https://zuplo.com/docs/ai-gateway/overview).\n\n## Project Structure\n\n| Path | What it does |\n| -------------------------- | ---------------------------------------------------------------------- |\n| `config/ai.oas.json` | The catch-all route that sends `/{app_id}/*` to the AI Gateway handler |\n| `config/policies.json` | The policies an app can select for its policy chain |\n| `modules/zuplo.runtime.ts` | Runtime plugins, such as tracing and logging |\n| `.env.example` | Sample environment variables. Copy it to `.env` for local development |\n\nAn app runs only the policies listed in its policy chain, and it can select only\npolicies declared in `config/policies.json`. To add your own policy, write it in\n`modules/` and declare it in `config/policies.json`.\n\n## Debugging\n\nIn VS Code, open **Run and Debug**, select **Launch & Attach Zuplo**, and click\nthe green play button.\n\nFor other editors and more details, see the\n[debugging guide](https://zuplo.com/docs/articles/local-development-debugging).\n\n## Deploying\n\nConnect the project to source control in the Zuplo Portal. Pushes to your\ndefault branch deploy the gateway to production.\n\n## Learn More\n\nTo learn more about the AI Gateway, visit the\n[AI Gateway documentation](https://zuplo.com/docs/ai-gateway/overview).\n\nTo connect with the community join [Discord](https://discord.zuplo.com).\n",
|
|
61
|
+
"config/ai.oas.json": "{\n \"openapi\": \"3.1.0\",\n \"info\": {\n \"version\": \"1.0.0\",\n \"title\": \"AI Gateway API\",\n \"description\": \"A unified API gateway for multiple AI providers. OpenAI-compatible ops are served under /{app_id}/v1/*, AWS Bedrock Runtime ops under /{app_id}/model/{modelId}/{operation}; other paths under /{app_id} are rejected.\"\n },\n \"paths\": {\n \"/u/:app_id/(.*)\": {\n \"x-zuplo-path\": {\n \"pathMode\": \"url-pattern\"\n },\n \"get,post,put,patch,delete,head\": {\n \"summary\": \"AI Gateway User App catch-all\",\n \"description\": \"Routes User App requests under /u/{app_id}/* to the AI Gateway handler. The configuration kind must be ai-user-app.\",\n \"operationId\": \"aiGatewayUserAppCatchAll\",\n \"responses\": {\n \"200\": {\n \"description\": \"Successful AI Gateway response\"\n },\n \"400\": {\n \"description\": \"Bad request\"\n },\n \"403\": {\n \"description\": \"Forbidden \\u2014 User App routes require a personal API key issued for this User App; application API keys cannot authenticate them\"\n },\n \"404\": {\n \"description\": \"Unsupported AI Gateway endpoint\"\n },\n \"500\": {\n \"description\": \"Internal server error\"\n }\n },\n \"x-zuplo-route\": {\n \"corsPolicy\": \"none\",\n \"handler\": {\n \"export\": \"aiGatewayHandlerV2\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"policies\": {\n \"inbound\": [\n \"ai-gateway-configuration-loader-inbound\",\n \"ai-gateway-configuration-executor-inbound\"\n ]\n }\n }\n }\n },\n \"/a/:app_id/(.*)\": {\n \"x-zuplo-path\": {\n \"pathMode\": \"url-pattern\"\n },\n \"get,post,put,patch,delete,head\": {\n \"summary\": \"AI Gateway AI App catch-all\",\n \"description\": \"Routes AI App requests under /a/{app_id}/* to the AI Gateway handler. The configuration kind must be ai-app.\",\n \"operationId\": \"aiGatewayAIAppCatchAll\",\n \"responses\": {\n \"200\": {\n \"description\": \"Successful AI Gateway response\"\n },\n \"400\": {\n \"description\": \"Bad request\"\n },\n \"401\": {\n \"description\": \"Unauthorized \\u2014 returned only when the application's inboundPolicyChain includes ai-gateway-auth-inbound, or authentication runs before the configuration loader\"\n },\n \"403\": {\n \"description\": \"Forbidden \\u2014 returned by per-app policies, such as an API key issued for a different app_id or a model the app does not allow\"\n },\n \"404\": {\n \"description\": \"Unsupported AI Gateway endpoint\"\n },\n \"500\": {\n \"description\": \"Internal server error\"\n }\n },\n \"x-zuplo-route\": {\n \"corsPolicy\": \"none\",\n \"handler\": {\n \"export\": \"aiGatewayHandlerV2\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"policies\": {\n \"inbound\": [\n \"ai-gateway-configuration-loader-inbound\",\n \"ai-gateway-configuration-executor-inbound\"\n ]\n }\n }\n }\n },\n \"/:app_id/(.*)\": {\n \"x-zuplo-path\": {\n \"pathMode\": \"url-pattern\"\n },\n \"get,post,put,patch,delete,head\": {\n \"summary\": \"AI Gateway catch-all\",\n \"description\": \"Routes AI requests under /{app_id}/* to the AI Gateway handler. The configuration loader loads the application configuration from the app_id path segment; the configuration executor then runs the application's inboundPolicyChain. Two path shapes succeed: a supported /v1/... operation (see resolveBasePath in packages/runtime/src/llm-translation/index.ts for the current set) and a Bedrock Runtime operation addressed AWS's way as /model/{modelId}/{operation} (see matchBedrockRuntimeRoute in packages/runtime/src/ai-gateway/bedrock-runtime-route.ts). Anything else under /{app_id} returns 404.\",\n \"operationId\": \"aiGatewayCatchAll\",\n \"responses\": {\n \"200\": {\n \"description\": \"Successful AI Gateway response\"\n },\n \"400\": {\n \"description\": \"Bad request\"\n },\n \"401\": {\n \"description\": \"Unauthorized \\u2014 returned only when the application's inboundPolicyChain includes ai-gateway-auth-inbound, or authentication runs before the configuration loader\"\n },\n \"403\": {\n \"description\": \"Forbidden \\u2014 returned by per-app policies, such as an API key issued for a different app_id or a model the app does not allow\"\n },\n \"404\": {\n \"description\": \"Unsupported AI Gateway endpoint\"\n },\n \"500\": {\n \"description\": \"Internal server error\"\n }\n },\n \"x-zuplo-route\": {\n \"corsPolicy\": \"none\",\n \"handler\": {\n \"export\": \"aiGatewayHandlerV2\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"policies\": {\n \"inbound\": [\n \"ai-gateway-configuration-loader-inbound\",\n \"ai-gateway-configuration-executor-inbound\"\n ]\n }\n }\n }\n }\n }\n}\n",
|
|
62
|
+
"config/policies.json": "{\n \"policies\": [\n {\n \"handler\": {\n \"export\": \"AIGatewayAuthInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-auth-inbound\",\n \"policyType\": \"ai-gateway-auth\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayInternalOnlyInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-internal-only-inbound\",\n \"policyType\": \"ai-gateway-internal-only\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayConfigurationLoaderInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"cacheTtlSeconds\": 5\n }\n },\n \"name\": \"ai-gateway-configuration-loader-inbound\",\n \"policyType\": \"ai-gateway-configuration-loader\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayConfigurationExecutorInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-configuration-executor-inbound\",\n \"policyType\": \"ai-gateway-configuration-executor\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayMeteringInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-metering-inbound\",\n \"policyType\": \"ai-gateway-metering\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayModelOverrideInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"models\": {\n \"completions\": {\n \"default\": \"openai/gpt-4o-mini\"\n }\n }\n }\n },\n \"name\": \"ai-gateway-model-override-inbound\",\n \"policyType\": \"ai-gateway-model-override\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayModelFilteringInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"models\": {\n \"completions\": {\n \"allowList\": [\"openai/gpt-4o-mini\"]\n }\n }\n }\n },\n \"name\": \"ai-gateway-model-filtering-inbound\",\n \"policyType\": \"ai-gateway-model-filtering\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayFallbackModelInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"models\": {\n \"completions\": {\n \"fallback\": \"openai/gpt-4o-mini\"\n }\n },\n \"fallbackTimeoutSeconds\": 60\n }\n },\n \"name\": \"ai-gateway-fallback-model-inbound\",\n \"policyType\": \"ai-gateway-fallback-model\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewaySemanticCacheInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"semanticTolerance\": 0.4,\n \"expirationSecondsTtl\": 3600\n }\n },\n \"name\": \"ai-gateway-semantic-cache-inbound\",\n \"policyType\": \"ai-gateway-semantic-cache\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayAkamaiFirewallInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"configurationId\": \"\",\n \"api-key\": \"\"\n }\n },\n \"name\": \"ai-gateway-akamai-firewall-inbound\",\n \"policyType\": \"ai-gateway-akamai-firewall\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayPromptInjectionPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"execution\": \"parallel\"\n }\n },\n \"name\": \"ai-gateway-prompt-injection\",\n \"policyType\": \"ai-gateway-prompt-injection\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayOpikTracingInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"apiKey\": \"\",\n \"projectName\": \"\",\n \"workspace\": \"\"\n }\n },\n \"name\": \"ai-gateway-opik-tracing-inbound\",\n \"policyType\": \"ai-gateway-opik-tracing\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayGalileoTracingInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"apiKey\": \"\",\n \"projectId\": \"\",\n \"logStreamId\": \"\"\n }\n },\n \"name\": \"ai-gateway-galileo-tracing-inbound\",\n \"policyType\": \"ai-gateway-galileo-tracing\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayDlpInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"rules\": {\n \"inbound\": {\n \"pii\": {\n \"action\": \"mask\"\n },\n \"contact-email\": {\n \"action\": \"off\"\n },\n \"finance-credit-card\": {\n \"action\": \"mask\"\n },\n \"finance-iban\": {\n \"action\": \"mask\"\n }\n },\n \"outbound\": {\n \"pii\": {\n \"action\": \"mask\"\n },\n \"contact-email\": {\n \"action\": \"off\"\n },\n \"finance-credit-card\": {\n \"action\": \"mask\"\n },\n \"finance-iban\": {\n \"action\": \"mask\"\n }\n }\n }\n }\n },\n \"name\": \"ai-gateway-dlp-inbound\",\n \"policyType\": \"ai-gateway-dlp\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewaySmartRouterInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"classifier\": {\n \"app\": {\n \"appId\": \"\",\n \"model\": \"openai/gpt-4o-mini\"\n }\n },\n \"modelsByComplexity\": {\n \"low\": \"openai/gpt-4o-mini\",\n \"medium\": \"openai/gpt-4o\",\n \"high\": \"openai/gpt-5\"\n }\n }\n },\n \"name\": \"ai-gateway-smart-router-inbound\",\n \"policyType\": \"ai-gateway-smart-router\"\n }\n ]\n}\n",
|
|
63
|
+
"modules/zuplo.runtime.ts": "import type { RuntimeExtensions } from \"@zuplo/runtime\";\n\n/**\n * `runtimeInit` runs once when your gateway boots. Use it to register plugins\n * and lifecycle hooks. Docs:\n * https://zuplo.com/docs/programmable-api/runtime-extensions\n */\nexport function runtimeInit(runtime: RuntimeExtensions) {\n // `runtime` is unused until you enable a plugin below. This reference keeps\n // linters from flagging it; delete it once you call `runtime.addPlugin`.\n void runtime;\n\n // --- OpenTelemetry tracing (optional) ------------------------------------\n // Send traces to Zuplo's built-in tracing. This can also be configured to\n // send traces to a third-party service such as Honeycomb, Grafana, and\n // others. Docs: https://zuplo.com/docs/articles/opentelemetry\n //\n // To enable, run `npm install @zuplo/otel`, then import `OpenTelemetryPlugin`\n // from \"@zuplo/otel\" and `environment` from \"@zuplo/runtime\":\n // const isWorkingCopy =\n // environment.ZUPLO_ENVIRONMENT_STAGE === \"working-copy\";\n // runtime.addPlugin(\n // new OpenTelemetryPlugin({\n // sampling: {\n // headSampler: { ratio: isWorkingCopy ? 1 : 0.1 },\n // },\n // }),\n // );\n // --- Logging (optional) --------------------------------------------------\n // Ship request logs to Datadog. Other log integrations (New Relic, Splunk,\n // Loki, Dynatrace, and others) follow the same pattern — see the logging\n // overview at https://zuplo.com/docs/articles/logging.\n // Docs: https://zuplo.com/docs/articles/log-plugin-datadog\n //\n // To enable, import the plugin and `environment` from \"@zuplo/runtime\":\n // runtime.addPlugin(\n // new DataDogLoggingPlugin({\n // apiKey: environment.DATADOG_API_KEY,\n // source: \"my-ai-gateway\",\n // }),\n // );\n}\n",
|
|
64
|
+
"tsconfig.json": "{\n \"include\": [\"modules/**/*\", \".zuplo/**/*\"],\n \"exclude\": [\"./node_modules\", \"./dist\", \"./docs\", \"./examples\"],\n \"compilerOptions\": {\n \"module\": \"ESNext\",\n \"target\": \"ES2022\",\n \"lib\": [\"ESNext\", \"WebWorker\", \"Webworker.Iterable\"],\n \"preserveConstEnums\": true,\n \"moduleResolution\": \"Bundler\",\n \"useUnknownInCatchVariables\": false,\n \"forceConsistentCasingInFileNames\": true,\n \"importHelpers\": true,\n \"removeComments\": true,\n \"esModuleInterop\": true,\n \"noEmit\": true,\n \"skipLibCheck\": true,\n \"strictNullChecks\": true,\n \"experimentalDecorators\": true\n }\n}\n",
|
|
65
|
+
"zuplo.jsonc": "{\n \"version\": 1,\n \"compatibilityDate\": \"2026-03-01\"\n}\n"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"revision": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
70
|
+
"sourceCommit": "5c44f3afdbe710e6bd0e727a7e6cd9d2e99666cd",
|
|
71
|
+
"files": {
|
|
72
|
+
"README-template.md": "## Zuplo AI Gateway\n\nThis is a Zuplo AI Gateway that was created with\n[`create-zuplo-api`](https://zuplo.com/docs). It gives your applications one\nOpenAI-compatible API in front of many AI providers, with per-app keys, model\ncontrols, budgets, caching, and guardrails.\n\n## Getting Started\n\nThe gateway loads each app's configuration (providers, models, and policies)\nfrom your Zuplo account at request time, so the project must be linked to a\nZuplo project before it can serve requests.\n\n1. Link the project. This writes your project's settings to `.env.zuplo`, which\n is gitignored:\n\n ```bash\n npx zuplo link\n ```\n\n2. In the [Zuplo Portal](https://portal.zuplo.com), add a provider and create an\n app. Each app gets its own API URL and API key. See\n [Apps](https://zuplo.com/docs/ai-gateway/apps).\n\n3. Start the development server:\n\n ```bash\n npm run dev\n # or\n yarn dev\n # or\n pnpm dev\n ```\n\n4. Send a request to the local gateway. Replace `<app_id>` with the ID from your\n app's API URL and set `ZUPLO_APP_API_KEY` to the app's API key:\n\n ```bash\n curl http://localhost:9000/<app_id>/v1/chat/completions \\\n -H \"Authorization: Bearer $ZUPLO_APP_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"openai/gpt-4o-mini\",\n \"messages\": [{ \"role\": \"user\", \"content\": \"Say hi\" }]\n }'\n ```\n\n## Endpoints\n\nEvery request is scoped to an app by the first path segment, `/{app_id}`. For\nthe supported endpoints and which providers serve each one, see the\n[AI Gateway documentation](https://zuplo.com/docs/ai-gateway/overview).\n\n## Project Structure\n\n| Path | What it does |\n| -------------------------- | ---------------------------------------------------------------------- |\n| `config/ai.oas.json` | The catch-all route that sends `/{app_id}/*` to the AI Gateway handler |\n| `config/policies.json` | The policies an app can select for its policy chain |\n| `modules/zuplo.runtime.ts` | Runtime plugins, such as tracing and logging |\n| `.env.example` | Sample environment variables. Copy it to `.env` for local development |\n\nAn app runs only the policies listed in its policy chain, and it can select only\npolicies declared in `config/policies.json`. To add your own policy, write it in\n`modules/` and declare it in `config/policies.json`.\n\n## Debugging\n\nIn VS Code, open **Run and Debug**, select **Launch & Attach Zuplo**, and click\nthe green play button.\n\nFor other editors and more details, see the\n[debugging guide](https://zuplo.com/docs/articles/local-development-debugging).\n\n## Deploying\n\nConnect the project to source control in the Zuplo Portal. Pushes to your\ndefault branch deploy the gateway to production.\n\n## Learn More\n\nTo learn more about the AI Gateway, visit the\n[AI Gateway documentation](https://zuplo.com/docs/ai-gateway/overview).\n\nTo connect with the community join [Discord](https://discord.zuplo.com).\n",
|
|
73
|
+
"config/ai.oas.json": "{\n \"openapi\": \"3.1.0\",\n \"info\": {\n \"version\": \"1.0.0\",\n \"title\": \"AI Gateway API\",\n \"description\": \"A unified API gateway for multiple AI providers. OpenAI-compatible ops are served under /{app_id}/v1/*, AWS Bedrock Runtime ops under /{app_id}/model/{modelId}/{operation}; other paths under /{app_id} are rejected.\"\n },\n \"paths\": {\n \"/u/:app_id/(.*)\": {\n \"x-zuplo-path\": {\n \"pathMode\": \"url-pattern\"\n },\n \"get,post,put,patch,delete,head\": {\n \"summary\": \"AI Gateway User App catch-all\",\n \"description\": \"Routes User App requests under /u/{app_id}/* to the AI Gateway handler. The configuration kind must be ai-user-app.\",\n \"operationId\": \"aiGatewayUserAppCatchAll\",\n \"responses\": {\n \"200\": {\n \"description\": \"Successful AI Gateway response\"\n },\n \"400\": {\n \"description\": \"Bad request\"\n },\n \"403\": {\n \"description\": \"Forbidden \\u2014 User App routes require a personal API key issued for this User App; application API keys cannot authenticate them\"\n },\n \"404\": {\n \"description\": \"Unsupported AI Gateway endpoint\"\n },\n \"500\": {\n \"description\": \"Internal server error\"\n }\n },\n \"x-zuplo-route\": {\n \"corsPolicy\": \"none\",\n \"handler\": {\n \"export\": \"aiGatewayHandlerV2\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"policies\": {\n \"inbound\": [\n \"ai-gateway-configuration-loader-inbound\",\n \"ai-gateway-configuration-executor-inbound\"\n ]\n }\n }\n }\n },\n \"/a/:app_id/(.*)\": {\n \"x-zuplo-path\": {\n \"pathMode\": \"url-pattern\"\n },\n \"get,post,put,patch,delete,head\": {\n \"summary\": \"AI Gateway AI App catch-all\",\n \"description\": \"Routes AI App requests under /a/{app_id}/* to the AI Gateway handler. The configuration kind must be ai-app.\",\n \"operationId\": \"aiGatewayAIAppCatchAll\",\n \"responses\": {\n \"200\": {\n \"description\": \"Successful AI Gateway response\"\n },\n \"400\": {\n \"description\": \"Bad request\"\n },\n \"401\": {\n \"description\": \"Unauthorized \\u2014 returned only when the application's inboundPolicyChain includes ai-gateway-auth-inbound, or authentication runs before the configuration loader\"\n },\n \"403\": {\n \"description\": \"Forbidden \\u2014 returned by per-app policies, such as an API key issued for a different app_id or a model the app does not allow\"\n },\n \"404\": {\n \"description\": \"Unsupported AI Gateway endpoint\"\n },\n \"500\": {\n \"description\": \"Internal server error\"\n }\n },\n \"x-zuplo-route\": {\n \"corsPolicy\": \"none\",\n \"handler\": {\n \"export\": \"aiGatewayHandlerV2\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"policies\": {\n \"inbound\": [\n \"ai-gateway-configuration-loader-inbound\",\n \"ai-gateway-configuration-executor-inbound\"\n ]\n }\n }\n }\n },\n \"/:app_id/(.*)\": {\n \"x-zuplo-path\": {\n \"pathMode\": \"url-pattern\"\n },\n \"get,post,put,patch,delete,head\": {\n \"summary\": \"AI Gateway catch-all\",\n \"description\": \"Routes AI requests under /{app_id}/* to the AI Gateway handler. The configuration loader loads the application configuration from the app_id path segment; the configuration executor then runs the application's inboundPolicyChain. Two path shapes succeed: a supported /v1/... operation (see resolveBasePath in packages/runtime/src/llm-translation/index.ts for the current set) and a Bedrock Runtime operation addressed AWS's way as /model/{modelId}/{operation} (see matchBedrockRuntimeRoute in packages/runtime/src/ai-gateway/bedrock-runtime-route.ts). Anything else under /{app_id} returns 404.\",\n \"operationId\": \"aiGatewayCatchAll\",\n \"responses\": {\n \"200\": {\n \"description\": \"Successful AI Gateway response\"\n },\n \"400\": {\n \"description\": \"Bad request\"\n },\n \"401\": {\n \"description\": \"Unauthorized \\u2014 returned only when the application's inboundPolicyChain includes ai-gateway-auth-inbound, or authentication runs before the configuration loader\"\n },\n \"403\": {\n \"description\": \"Forbidden \\u2014 returned by per-app policies, such as an API key issued for a different app_id or a model the app does not allow\"\n },\n \"404\": {\n \"description\": \"Unsupported AI Gateway endpoint\"\n },\n \"500\": {\n \"description\": \"Internal server error\"\n }\n },\n \"x-zuplo-route\": {\n \"corsPolicy\": \"none\",\n \"handler\": {\n \"export\": \"aiGatewayHandlerV2\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"policies\": {\n \"inbound\": [\n \"ai-gateway-configuration-loader-inbound\",\n \"ai-gateway-configuration-executor-inbound\"\n ]\n }\n }\n }\n }\n }\n}\n",
|
|
74
|
+
"config/policies.json": "{\n \"policies\": [\n {\n \"handler\": {\n \"export\": \"AIGatewayAuthInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-auth-inbound\",\n \"policyType\": \"ai-gateway-auth\"\n },\n {\n \"handler\": {\n \"export\": \"InternalOnlyInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"internal-only-inbound\",\n \"policyType\": \"internal-only\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayConfigurationLoaderInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"cacheTtlSeconds\": 5\n }\n },\n \"name\": \"ai-gateway-configuration-loader-inbound\",\n \"policyType\": \"ai-gateway-configuration-loader\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayConfigurationExecutorInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-configuration-executor-inbound\",\n \"policyType\": \"ai-gateway-configuration-executor\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayMeteringInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {}\n },\n \"name\": \"ai-gateway-metering-inbound\",\n \"policyType\": \"ai-gateway-metering\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayModelOverrideInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"models\": {\n \"completions\": {\n \"default\": \"openai/gpt-4o-mini\"\n }\n }\n }\n },\n \"name\": \"ai-gateway-model-override-inbound\",\n \"policyType\": \"ai-gateway-model-override\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayModelFilteringInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"models\": {\n \"completions\": {\n \"allowList\": [\"openai/gpt-4o-mini\"]\n }\n }\n }\n },\n \"name\": \"ai-gateway-model-filtering-inbound\",\n \"policyType\": \"ai-gateway-model-filtering\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayFallbackModelInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"models\": {\n \"completions\": {\n \"fallback\": \"openai/gpt-4o-mini\"\n }\n },\n \"fallbackTimeoutSeconds\": 60\n }\n },\n \"name\": \"ai-gateway-fallback-model-inbound\",\n \"policyType\": \"ai-gateway-fallback-model\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewaySemanticCacheInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"semanticTolerance\": 0.4,\n \"expirationSecondsTtl\": 3600\n }\n },\n \"name\": \"ai-gateway-semantic-cache-inbound\",\n \"policyType\": \"ai-gateway-semantic-cache\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayAkamaiFirewallInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"configurationId\": \"\",\n \"api-key\": \"\"\n }\n },\n \"name\": \"ai-gateway-akamai-firewall-inbound\",\n \"policyType\": \"ai-gateway-akamai-firewall\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayPromptInjectionPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"execution\": \"parallel\"\n }\n },\n \"name\": \"ai-gateway-prompt-injection\",\n \"policyType\": \"ai-gateway-prompt-injection\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayOpikTracingInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"apiKey\": \"\",\n \"projectName\": \"\",\n \"workspace\": \"\"\n }\n },\n \"name\": \"ai-gateway-opik-tracing-inbound\",\n \"policyType\": \"ai-gateway-opik-tracing\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayGalileoTracingInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"apiKey\": \"\",\n \"projectId\": \"\",\n \"logStreamId\": \"\"\n }\n },\n \"name\": \"ai-gateway-galileo-tracing-inbound\",\n \"policyType\": \"ai-gateway-galileo-tracing\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewayDlpInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"rules\": {\n \"inbound\": {\n \"pii\": {\n \"action\": \"mask\"\n },\n \"contact-email\": {\n \"action\": \"off\"\n },\n \"finance-credit-card\": {\n \"action\": \"mask\"\n },\n \"finance-iban\": {\n \"action\": \"mask\"\n }\n },\n \"outbound\": {\n \"pii\": {\n \"action\": \"mask\"\n },\n \"contact-email\": {\n \"action\": \"off\"\n },\n \"finance-credit-card\": {\n \"action\": \"mask\"\n },\n \"finance-iban\": {\n \"action\": \"mask\"\n }\n }\n }\n }\n },\n \"name\": \"ai-gateway-dlp-inbound\",\n \"policyType\": \"ai-gateway-dlp\"\n },\n {\n \"handler\": {\n \"export\": \"AIGatewaySmartRouterInboundPolicy\",\n \"module\": \"$import(@zuplo/runtime)\",\n \"options\": {\n \"classifier\": {\n \"app\": {\n \"appId\": \"\",\n \"model\": \"openai/gpt-4o-mini\"\n }\n },\n \"modelsByComplexity\": {\n \"low\": \"openai/gpt-4o-mini\",\n \"medium\": \"openai/gpt-4o\",\n \"high\": \"openai/gpt-5\"\n }\n }\n },\n \"name\": \"ai-gateway-smart-router-inbound\",\n \"policyType\": \"ai-gateway-smart-router\"\n }\n ]\n}\n",
|
|
75
|
+
"modules/zuplo.runtime.ts": "import type { RuntimeExtensions } from \"@zuplo/runtime\";\n\n/**\n * `runtimeInit` runs once when your gateway boots. Use it to register plugins\n * and lifecycle hooks. Docs:\n * https://zuplo.com/docs/programmable-api/runtime-extensions\n */\nexport function runtimeInit(runtime: RuntimeExtensions) {\n // `runtime` is unused until you enable a plugin below. This reference keeps\n // linters from flagging it; delete it once you call `runtime.addPlugin`.\n void runtime;\n\n // --- OpenTelemetry tracing (optional) ------------------------------------\n // Send traces to Zuplo's built-in tracing. This can also be configured to\n // send traces to a third-party service such as Honeycomb, Grafana, and\n // others. Docs: https://zuplo.com/docs/articles/opentelemetry\n //\n // To enable, run `npm install @zuplo/otel`, then import `OpenTelemetryPlugin`\n // from \"@zuplo/otel\" and `environment` from \"@zuplo/runtime\":\n // const isWorkingCopy =\n // environment.ZUPLO_ENVIRONMENT_STAGE === \"working-copy\";\n // runtime.addPlugin(\n // new OpenTelemetryPlugin({\n // sampling: {\n // headSampler: { ratio: isWorkingCopy ? 1 : 0.1 },\n // },\n // }),\n // );\n // --- Logging (optional) --------------------------------------------------\n // Ship request logs to Datadog. Other log integrations (New Relic, Splunk,\n // Loki, Dynatrace, and others) follow the same pattern — see the logging\n // overview at https://zuplo.com/docs/articles/logging.\n // Docs: https://zuplo.com/docs/articles/log-plugin-datadog\n //\n // To enable, import the plugin and `environment` from \"@zuplo/runtime\":\n // runtime.addPlugin(\n // new DataDogLoggingPlugin({\n // apiKey: environment.DATADOG_API_KEY,\n // source: \"my-ai-gateway\",\n // }),\n // );\n}\n",
|
|
76
|
+
"tsconfig.json": "{\n \"include\": [\"modules/**/*\", \".zuplo/**/*\"],\n \"exclude\": [\"./node_modules\", \"./dist\", \"./docs\", \"./examples\"],\n \"compilerOptions\": {\n \"module\": \"ESNext\",\n \"target\": \"ES2022\",\n \"lib\": [\"ESNext\", \"WebWorker\", \"Webworker.Iterable\"],\n \"preserveConstEnums\": true,\n \"moduleResolution\": \"Bundler\",\n \"useUnknownInCatchVariables\": false,\n \"forceConsistentCasingInFileNames\": true,\n \"importHelpers\": true,\n \"removeComments\": true,\n \"esModuleInterop\": true,\n \"noEmit\": true,\n \"skipLibCheck\": true,\n \"strictNullChecks\": true,\n \"experimentalDecorators\": true\n }\n}\n",
|
|
77
|
+
"zuplo.jsonc": "{\n \"version\": 1,\n \"compatibilityDate\": \"2026-03-01\"\n}\n"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
"aliases": {
|
|
82
|
+
"ai-gateway-auth-v2": "ai-gateway-auth-inbound",
|
|
83
|
+
"ai-gateway-auth-v2-inbound": "ai-gateway-auth-inbound",
|
|
84
|
+
"ai-gateway-metering-v2": "ai-gateway-metering-inbound",
|
|
85
|
+
"ai-gateway-metering-v2-inbound": "ai-gateway-metering-inbound",
|
|
86
|
+
"ai-gateway-semantic-cache-v2": "ai-gateway-semantic-cache-inbound",
|
|
87
|
+
"ai-gateway-semantic-cache-v2-inbound": "ai-gateway-semantic-cache-inbound",
|
|
88
|
+
"ai-gateway-semantic-cache-inbound-v2": "ai-gateway-semantic-cache-inbound",
|
|
89
|
+
"ai-gateway-model-filtering-v2": "ai-gateway-model-filtering-inbound",
|
|
90
|
+
"ai-gateway-model-filtering-v2-inbound": "ai-gateway-model-filtering-inbound",
|
|
91
|
+
"ai-gateway-fallback-model-v2": "ai-gateway-fallback-model-inbound",
|
|
92
|
+
"ai-gateway-fallback-model-v2-inbound": "ai-gateway-fallback-model-inbound",
|
|
93
|
+
"ai-gateway-configuration-loader-v2": "ai-gateway-configuration-loader-inbound",
|
|
94
|
+
"ai-gateway-configuration-loader-v2-inbound": "ai-gateway-configuration-loader-inbound",
|
|
95
|
+
"ai-gateway-configuration-executor-v2": "ai-gateway-configuration-executor-inbound",
|
|
96
|
+
"ai-gateway-configuration-executor-v2-inbound": "ai-gateway-configuration-executor-inbound",
|
|
97
|
+
"akamai-ai-firewall-v2": "ai-gateway-akamai-firewall-inbound",
|
|
98
|
+
"akamai-ai-firewall-v2-inbound": "ai-gateway-akamai-firewall-inbound",
|
|
99
|
+
"akamai-ai-firewall-inbound-v2": "ai-gateway-akamai-firewall-inbound",
|
|
100
|
+
"comet-opik-tracing-v2": "ai-gateway-opik-tracing-inbound",
|
|
101
|
+
"comet-opik-tracing-v2-inbound": "ai-gateway-opik-tracing-inbound",
|
|
102
|
+
"comet-opik-tracing-inbound-v2": "ai-gateway-opik-tracing-inbound",
|
|
103
|
+
"galileo-tracing-v2": "ai-gateway-galileo-tracing-inbound",
|
|
104
|
+
"galileo-tracing-v2-inbound": "ai-gateway-galileo-tracing-inbound",
|
|
105
|
+
"galileo-tracing-inbound-v2": "ai-gateway-galileo-tracing-inbound",
|
|
106
|
+
"ai-gateway-internal-only": "internal-only-inbound",
|
|
107
|
+
"ai-gateway-internal-only-inbound": "internal-only-inbound"
|
|
108
|
+
},
|
|
109
|
+
"steps": [
|
|
110
|
+
{
|
|
111
|
+
"id": "route:/u/:app_id/(.*)",
|
|
112
|
+
"kind": "route",
|
|
113
|
+
"key": "/u/:app_id/(.*)",
|
|
114
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
115
|
+
"runtime": "release",
|
|
116
|
+
"instructions": "Insert before /:app_id/(.*), with the displayed inbound policy order."
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"id": "route:/a/:app_id/(.*)",
|
|
120
|
+
"kind": "route",
|
|
121
|
+
"key": "/a/:app_id/(.*)",
|
|
122
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
123
|
+
"runtime": "release",
|
|
124
|
+
"instructions": "Insert before /:app_id/(.*), with the displayed inbound policy order."
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"id": "route:/:app_id/(.*)",
|
|
128
|
+
"kind": "route",
|
|
129
|
+
"key": "/:app_id/(.*)",
|
|
130
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
131
|
+
"runtime": "release",
|
|
132
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"id": "policy:ai-gateway-auth-inbound",
|
|
136
|
+
"kind": "policy",
|
|
137
|
+
"key": "ai-gateway-auth-inbound",
|
|
138
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
139
|
+
"runtime": "release",
|
|
140
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"id": "policy:ai-gateway-internal-only-inbound",
|
|
144
|
+
"kind": "policy",
|
|
145
|
+
"key": "ai-gateway-internal-only-inbound",
|
|
146
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
147
|
+
"runtime": "release",
|
|
148
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"id": "policy:ai-gateway-configuration-loader-inbound",
|
|
152
|
+
"kind": "policy",
|
|
153
|
+
"key": "ai-gateway-configuration-loader-inbound",
|
|
154
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
155
|
+
"runtime": "release",
|
|
156
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"id": "policy:ai-gateway-configuration-executor-inbound",
|
|
160
|
+
"kind": "policy",
|
|
161
|
+
"key": "ai-gateway-configuration-executor-inbound",
|
|
162
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
163
|
+
"runtime": "release",
|
|
164
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"id": "policy:ai-gateway-metering-inbound",
|
|
168
|
+
"kind": "policy",
|
|
169
|
+
"key": "ai-gateway-metering-inbound",
|
|
170
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
171
|
+
"runtime": "release",
|
|
172
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"id": "policy:ai-gateway-model-override-inbound",
|
|
176
|
+
"kind": "policy",
|
|
177
|
+
"key": "ai-gateway-model-override-inbound",
|
|
178
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
179
|
+
"runtime": "release",
|
|
180
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"id": "policy:ai-gateway-model-filtering-inbound",
|
|
184
|
+
"kind": "policy",
|
|
185
|
+
"key": "ai-gateway-model-filtering-inbound",
|
|
186
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
187
|
+
"runtime": "release",
|
|
188
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
"id": "policy:ai-gateway-fallback-model-inbound",
|
|
192
|
+
"kind": "policy",
|
|
193
|
+
"key": "ai-gateway-fallback-model-inbound",
|
|
194
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
195
|
+
"runtime": "release",
|
|
196
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"id": "policy:ai-gateway-semantic-cache-inbound",
|
|
200
|
+
"kind": "policy",
|
|
201
|
+
"key": "ai-gateway-semantic-cache-inbound",
|
|
202
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
203
|
+
"runtime": "release",
|
|
204
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"id": "policy:ai-gateway-akamai-firewall-inbound",
|
|
208
|
+
"kind": "policy",
|
|
209
|
+
"key": "ai-gateway-akamai-firewall-inbound",
|
|
210
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
211
|
+
"runtime": "release",
|
|
212
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"id": "policy:ai-gateway-prompt-injection",
|
|
216
|
+
"kind": "policy",
|
|
217
|
+
"key": "ai-gateway-prompt-injection",
|
|
218
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
219
|
+
"runtime": "release",
|
|
220
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"id": "policy:ai-gateway-opik-tracing-inbound",
|
|
224
|
+
"kind": "policy",
|
|
225
|
+
"key": "ai-gateway-opik-tracing-inbound",
|
|
226
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
227
|
+
"runtime": "release",
|
|
228
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
"id": "policy:ai-gateway-galileo-tracing-inbound",
|
|
232
|
+
"kind": "policy",
|
|
233
|
+
"key": "ai-gateway-galileo-tracing-inbound",
|
|
234
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
235
|
+
"runtime": "release",
|
|
236
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"id": "policy:ai-gateway-dlp-inbound",
|
|
240
|
+
"kind": "policy",
|
|
241
|
+
"key": "ai-gateway-dlp-inbound",
|
|
242
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
243
|
+
"runtime": "release",
|
|
244
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"id": "policy:ai-gateway-smart-router-inbound",
|
|
248
|
+
"kind": "policy",
|
|
249
|
+
"key": "ai-gateway-smart-router-inbound",
|
|
250
|
+
"target": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
251
|
+
"runtime": "release",
|
|
252
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:route:/u/:app_id/(.*)",
|
|
256
|
+
"kind": "route",
|
|
257
|
+
"key": "/u/:app_id/(.*)",
|
|
258
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
259
|
+
"runtime": "release",
|
|
260
|
+
"instructions": "Insert before /:app_id/(.*), with the displayed inbound policy order."
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:route:/a/:app_id/(.*)",
|
|
264
|
+
"kind": "route",
|
|
265
|
+
"key": "/a/:app_id/(.*)",
|
|
266
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
267
|
+
"runtime": "release",
|
|
268
|
+
"instructions": "Insert before /:app_id/(.*), with the displayed inbound policy order."
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:route:/:app_id/(.*)",
|
|
272
|
+
"kind": "route",
|
|
273
|
+
"key": "/:app_id/(.*)",
|
|
274
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
275
|
+
"runtime": "release",
|
|
276
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:policy:ai-gateway-auth-inbound",
|
|
280
|
+
"kind": "policy",
|
|
281
|
+
"key": "ai-gateway-auth-inbound",
|
|
282
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
283
|
+
"runtime": "release",
|
|
284
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:policy:ai-gateway-internal-only-inbound",
|
|
288
|
+
"kind": "policy",
|
|
289
|
+
"key": "internal-only-inbound",
|
|
290
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
291
|
+
"runtime": "release",
|
|
292
|
+
"instructions": "Add only if neither internal-only-inbound nor its historical AI Gateway alias is declared. Preserve existing declarations and application chain references."
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:policy:ai-gateway-configuration-loader-inbound",
|
|
296
|
+
"kind": "policy",
|
|
297
|
+
"key": "ai-gateway-configuration-loader-inbound",
|
|
298
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
299
|
+
"runtime": "release",
|
|
300
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:policy:ai-gateway-configuration-executor-inbound",
|
|
304
|
+
"kind": "policy",
|
|
305
|
+
"key": "ai-gateway-configuration-executor-inbound",
|
|
306
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
307
|
+
"runtime": "release",
|
|
308
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:policy:ai-gateway-metering-inbound",
|
|
312
|
+
"kind": "policy",
|
|
313
|
+
"key": "ai-gateway-metering-inbound",
|
|
314
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
315
|
+
"runtime": "release",
|
|
316
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:policy:ai-gateway-model-override-inbound",
|
|
320
|
+
"kind": "policy",
|
|
321
|
+
"key": "ai-gateway-model-override-inbound",
|
|
322
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
323
|
+
"runtime": "release",
|
|
324
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:policy:ai-gateway-model-filtering-inbound",
|
|
328
|
+
"kind": "policy",
|
|
329
|
+
"key": "ai-gateway-model-filtering-inbound",
|
|
330
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
331
|
+
"runtime": "release",
|
|
332
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:policy:ai-gateway-fallback-model-inbound",
|
|
336
|
+
"kind": "policy",
|
|
337
|
+
"key": "ai-gateway-fallback-model-inbound",
|
|
338
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
339
|
+
"runtime": "release",
|
|
340
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:policy:ai-gateway-semantic-cache-inbound",
|
|
344
|
+
"kind": "policy",
|
|
345
|
+
"key": "ai-gateway-semantic-cache-inbound",
|
|
346
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
347
|
+
"runtime": "release",
|
|
348
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:policy:ai-gateway-akamai-firewall-inbound",
|
|
352
|
+
"kind": "policy",
|
|
353
|
+
"key": "ai-gateway-akamai-firewall-inbound",
|
|
354
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
355
|
+
"runtime": "release",
|
|
356
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:policy:ai-gateway-prompt-injection",
|
|
360
|
+
"kind": "policy",
|
|
361
|
+
"key": "ai-gateway-prompt-injection",
|
|
362
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
363
|
+
"runtime": "release",
|
|
364
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:policy:ai-gateway-opik-tracing-inbound",
|
|
368
|
+
"kind": "policy",
|
|
369
|
+
"key": "ai-gateway-opik-tracing-inbound",
|
|
370
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
371
|
+
"runtime": "release",
|
|
372
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:policy:ai-gateway-galileo-tracing-inbound",
|
|
376
|
+
"kind": "policy",
|
|
377
|
+
"key": "ai-gateway-galileo-tracing-inbound",
|
|
378
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
379
|
+
"runtime": "release",
|
|
380
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:policy:ai-gateway-dlp-inbound",
|
|
384
|
+
"kind": "policy",
|
|
385
|
+
"key": "ai-gateway-dlp-inbound",
|
|
386
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
387
|
+
"runtime": "release",
|
|
388
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
"id": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4:policy:ai-gateway-smart-router-inbound",
|
|
392
|
+
"kind": "policy",
|
|
393
|
+
"key": "ai-gateway-smart-router-inbound",
|
|
394
|
+
"target": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
395
|
+
"runtime": "release",
|
|
396
|
+
"instructions": "Review the definition and application policy chains before adding it."
|
|
397
|
+
}
|
|
398
|
+
],
|
|
399
|
+
"assessments": [
|
|
400
|
+
{
|
|
401
|
+
"revision": "d86ffae8998e43d71f8f543b1269a5f1e9b4bf78c45f22c7022a7feb7f4fa766",
|
|
402
|
+
"classification": "additions",
|
|
403
|
+
"instructions": "Only missing routes and policy declarations are eligible. Existing definitions, including changed defaults and historical aliases, remain customer-owned. Existing policy changes require manual review."
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
"revision": "256d7e12d04fba5317a0a6277edf7eb7f1e798385af6f75aed34426aa5b771f4",
|
|
407
|
+
"classification": "additions",
|
|
408
|
+
"instructions": "The Internal Only policy now uses internal-only-inbound, InternalOnlyInboundPolicy, and policyType internal-only. Existing AI Gateway names remain supported runtime aliases and are preserved; do not add a duplicate declaration or automatically rename existing configuration. Missing declarations use the new name. Other existing policy options and defaults still require separate review."
|
|
409
|
+
}
|
|
410
|
+
]
|
|
411
|
+
}
|