@zuplo/runtime 7.8.0 → 7.8.2

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.
@@ -22,5 +22,5 @@
22
22
  * DEALINGS IN THE SOFTWARE.
23
23
  *--------------------------------------------------------------------------------------------*/
24
24
 
25
- import{E as p,J as c,M as u}from"../chunk-BB77BBJC.js";import"../chunk-B5DKYXCI.js";import{a as d}from"../chunk-QGAJTUPE.js";import"../chunk-A3QGJZO7.js";import"../chunk-GCOWKKQW.js";import{$ as i}from"../chunk-HWNKBEMX.js";import{a as o}from"../chunk-TYV53J3B.js";function w(l={request:new Request("https://api.example.com")}){let e=[];function t(s){e.push(Promise.resolve(s))}return o(t,"waitUntil"),{context:new a({event:{waitUntil:t},route:l.route,originalRequest:l.request}),invokeResponse:o(async()=>{await Promise.all(e)},"invokeResponse")}}o(w,"createMockContext");var g={path:"/",methods:["GET"],handler:{module:{},export:"default"},raw:o(()=>({}),"raw")},a=class extends EventTarget{static{o(this,"MockZuploContext")}#e;#t;contextId;requestId;log;route;custom;incomingRequestProperties;parentContext;analyticsContext;constructor({event:e,route:t=g,parentContext:n,originalRequest:r}){super(),this.requestId=crypto.randomUUID(),this.contextId=crypto.randomUUID(),this.log={info:i.console.info,log:i.console.log,debug:i.console.debug,warn:i.console.warn,error:i.console.error,setLogProperties:o(()=>{},"setLogProperties")},this.custom={},this.route=t,this.incomingRequestProperties={ip:"203.0.113.7",asn:1234,asOrganization:"ORGANIZATION",city:"Seattle",region:"Washington",regionCode:"WA",colo:"SEA",continent:"NA",country:"US",postalCode:"98004",metroCode:"SEA",latitude:void 0,longitude:void 0,timezone:void 0,httpProtocol:void 0,clientCert:void 0,clientMtlsVerificationStatus:void 0,clientMtlsVerificationReason:void 0,clientCertFingerprintSha256:void 0,clientCertNotBefore:void 0,clientCertNotAfter:void 0,clientCertIssuerDn:void 0,clientCertSubjectDn:void 0},this.parentContext=n,this.#e=e,this.#t=r,this.analyticsContext=new c(this.requestId)}waitUntil(e){this.#e.waitUntil(e)}invokeInboundPolicy(e,t){throw new Error("Not implemented")}invokeOutboundPolicy(e,t,n){throw new Error("Not implemented")}invokeRoute(e,t){throw new Error("Not implemented")}addResponseSendingHook(e){throw new Error("Not implemented")}addResponseSendingFinalHook(e){throw new Error("Not implemented")}addPreRequestHandler(e,t){let n;try{n=u.getContextExtensions(this)}catch{n=u.initialize(this,new d(this.#t??new Request("https://api.example.com")))}n.preRequestPhase??="active",p(this,n,e,t)}get preRequestHandlers(){let e;try{e=u.getContextExtensions(this)}catch{return[]}return(e.preRequestState?.entries??[]).map(t=>({policyName:t.policyName,name:t.name}))}addEventListener(e,t,n){let r=o(s=>{try{typeof t=="function"?t(s):t.handleEvent(s)}catch(m){throw this.log.error(`Error invoking event ${e}. See following logs for details.`),m}},"wrapped");super.addEventListener(e,r,n)}};export{a as MockZuploContext,w as createMockContext};
25
+ import{E as p,J as c,M as u}from"../chunk-7O65Y44U.js";import"../chunk-B5DKYXCI.js";import{a as d}from"../chunk-QGAJTUPE.js";import"../chunk-A3QGJZO7.js";import"../chunk-GCOWKKQW.js";import{$ as i}from"../chunk-HWNKBEMX.js";import{a as o}from"../chunk-TYV53J3B.js";function w(l={request:new Request("https://api.example.com")}){let e=[];function t(s){e.push(Promise.resolve(s))}return o(t,"waitUntil"),{context:new a({event:{waitUntil:t},route:l.route,originalRequest:l.request}),invokeResponse:o(async()=>{await Promise.all(e)},"invokeResponse")}}o(w,"createMockContext");var g={path:"/",methods:["GET"],handler:{module:{},export:"default"},raw:o(()=>({}),"raw")},a=class extends EventTarget{static{o(this,"MockZuploContext")}#e;#t;contextId;requestId;log;route;custom;incomingRequestProperties;parentContext;analyticsContext;constructor({event:e,route:t=g,parentContext:n,originalRequest:r}){super(),this.requestId=crypto.randomUUID(),this.contextId=crypto.randomUUID(),this.log={info:i.console.info,log:i.console.log,debug:i.console.debug,warn:i.console.warn,error:i.console.error,setLogProperties:o(()=>{},"setLogProperties")},this.custom={},this.route=t,this.incomingRequestProperties={ip:"203.0.113.7",asn:1234,asOrganization:"ORGANIZATION",city:"Seattle",region:"Washington",regionCode:"WA",colo:"SEA",continent:"NA",country:"US",postalCode:"98004",metroCode:"SEA",latitude:void 0,longitude:void 0,timezone:void 0,httpProtocol:void 0,clientCert:void 0,clientMtlsVerificationStatus:void 0,clientMtlsVerificationReason:void 0,clientCertFingerprintSha256:void 0,clientCertNotBefore:void 0,clientCertNotAfter:void 0,clientCertIssuerDn:void 0,clientCertSubjectDn:void 0},this.parentContext=n,this.#e=e,this.#t=r,this.analyticsContext=new c(this.requestId)}waitUntil(e){this.#e.waitUntil(e)}invokeInboundPolicy(e,t){throw new Error("Not implemented")}invokeOutboundPolicy(e,t,n){throw new Error("Not implemented")}invokeRoute(e,t){throw new Error("Not implemented")}addResponseSendingHook(e){throw new Error("Not implemented")}addResponseSendingFinalHook(e){throw new Error("Not implemented")}addPreRequestHandler(e,t){let n;try{n=u.getContextExtensions(this)}catch{n=u.initialize(this,new d(this.#t??new Request("https://api.example.com")))}n.preRequestPhase??="active",p(this,n,e,t)}get preRequestHandlers(){let e;try{e=u.getContextExtensions(this)}catch{return[]}return(e.preRequestState?.entries??[]).map(t=>({policyName:t.policyName,name:t.name}))}addEventListener(e,t,n){let r=o(s=>{try{typeof t=="function"?t(s):t.handleEvent(s)}catch(m){throw this.log.error(`Error invoking event ${e}. See following logs for details.`),m}},"wrapped");super.addEventListener(e,r,n)}};export{a as MockZuploContext,w as createMockContext};
26
26
  //# sourceMappingURL=index.js.map
@@ -505,6 +505,61 @@ export declare function aiGatewayHandlerV2(
505
505
  context: ZuploContext
506
506
  ): Promise<Response>;
507
507
 
508
+ /**
509
+ * Accepts only requests that this gateway made itself with
510
+ * `context.invokeRoute`, and rejects every request that arrived over the
511
+ * network with `403 Forbidden`.
512
+ *
513
+ * Use it in place of AI Gateway Authentication on an application that is only
514
+ * ever called by other routes and policies on the same gateway, such as the
515
+ * classifier application behind the Smart Router or Prompt Injection
516
+ * Protection policies. Those calls never leave the gateway, so an API key on
517
+ * them protects nothing. This policy asserts the one thing that matters: the
518
+ * request originated inside the deployment.
519
+ *
520
+ * The check reads `context.parentContext`, which the runtime sets only on the
521
+ * child context that `context.invokeRoute` creates. A client cannot supply it
522
+ * through a header, the URL, or the body. The policy has no options, makes no
523
+ * network calls, reads no body, and leaves `request.user` unset.
524
+ *
525
+ * @title Ensure Gateway Internal Invocation Only
526
+ * @product ai-gateway
527
+ * @requiresAI
528
+ * @public
529
+ *
530
+ * @param request - The incoming ZuploRequest
531
+ * @param context - The ZuploContext
532
+ * @param _options - The policy options set in policies.json (this policy has none)
533
+ * @param policyName - The name of the policy as set in policies.json
534
+ * @returns The request when the gateway made it with `context.invokeRoute`, otherwise a 403 response
535
+ *
536
+ * @example
537
+ * ```json
538
+ * // policies.json - Declare the policy so an application chain can select it
539
+ * {
540
+ * "name": "ai-gateway-internal-only-inbound",
541
+ * "policyType": "ai-gateway-internal-only",
542
+ * "handler": {
543
+ * "export": "AIGatewayInternalOnlyInboundPolicy",
544
+ * "module": "$import(@zuplo/runtime)",
545
+ * "options": {}
546
+ * }
547
+ * }
548
+ * ```
549
+ */
550
+ export declare function AIGatewayInternalOnlyInboundPolicy(
551
+ request: ZuploRequest,
552
+ context: ZuploContext,
553
+ _options: AIGatewayInternalOnlyInboundPolicyOptions,
554
+ policyName: string
555
+ ): Promise<ZuploRequest | Response>;
556
+
557
+ /**
558
+ * The options for this policy. It has none.
559
+ * @public
560
+ */
561
+ export declare interface AIGatewayInternalOnlyInboundPolicyOptions {}
562
+
508
563
  /* Excluded from this release type: AIGatewayMeterIncrements */
509
564
 
510
565
  /**
@@ -884,6 +939,93 @@ export declare const AIGatewayOpenAIToAnthropicOutboundPolicy: OutboundPolicyHan
884
939
  */
885
940
  export declare interface AIGatewayOpenAIToAnthropicOutboundPolicyOptions {}
886
941
 
942
+ /**
943
+ * Prompt Injection Protection Policy
944
+ * @title Prompt Injection Protection
945
+ * @product ai-gateway
946
+ * @requiresAI
947
+ *
948
+ * Uses a small tool-calling LLM to detect prompt injection attempts in AI
949
+ * Gateway requests and blocks them before they reach the upstream model. The
950
+ * classifier runs on any OpenAI-compatible API and is forced (via
951
+ * `tool_choice`) to answer through a single SAFE/UNSAFE function call, so one
952
+ * bounded, non-streaming completion at temperature 0 yields a deterministic
953
+ * verdict. Requests whose inspected messages carry no text skip the classifier
954
+ * entirely.
955
+ *
956
+ * This policy inspects the request only, so it adds no time-to-first-token
957
+ * cost on responses and works with streaming untouched.
958
+ *
959
+ * By default only the newest message of the conversation is inspected
960
+ * (`recentMessageCount: 1`): earlier turns were screened when they were the
961
+ * newest, so a chat session pays for one classification per turn rather than
962
+ * for its whole transcript on every turn. System and developer messages,
963
+ * Anthropic's top-level `system` and the Responses `instructions` field are
964
+ * never inspected — they are the application's own instructions, not where an
965
+ * injection arrives — while tool results are, because retrieved documents and
966
+ * tool output are the main indirect-injection vector. `classifierPrompt`
967
+ * replaces the built-in system prompt; the inspected text always travels as a
968
+ * separate user message and the verdict always comes back through the fixed
969
+ * SAFE/UNSAFE tool call, so a custom prompt changes what is flagged, never how
970
+ * the verdict is read.
971
+ *
972
+ * With `appId`, the classifier runs on another AI Gateway app instead of an
973
+ * external API. The gateway invokes that app in-process through
974
+ * `context.invokeRoute`, so there is no outbound HTTP hop and the
975
+ * classification inherits that app's provider credentials, model routing,
976
+ * fallbacks and quotas. The target app must not run this policy itself: being
977
+ * asked to classify a classification request is rejected as a configuration
978
+ * error rather than silently skipped, so a guardrail never looks configured
979
+ * while inspecting nothing.
980
+ *
981
+ * With `execution: "parallel"`, the classifier is registered as a pre-request
982
+ * handler and runs concurrently with the remaining inbound policies instead of
983
+ * blocking the chain. The runtime enforces the verdict before the request is
984
+ * dispatched upstream, so a prompt is never forwarded unchecked; what changes
985
+ * is that a safe prompt no longer pays for the classifier serially. A verdict
986
+ * that stops mattering (another response is already being served) aborts the
987
+ * in-flight classifier call and is neither logged as a failure nor counted.
988
+ * Omitting `execution` means `"sequential"`, while the generated example sets
989
+ * `"parallel"` — an existing configuration never changes behaviour under it.
990
+ *
991
+ * Options are validated at request time and invalid options fail closed with a
992
+ * ConfigurationError.
993
+ * Classifier-call failures (invalid credentials, rate limits, timeouts,
994
+ * outages) also fail closed by default, returning a 502 in the route's native
995
+ * error format; set `onError: "allow"` to fail open and prioritize
996
+ * availability over inspection.
997
+ *
998
+ * @param request - The ZuploRequest
999
+ * @param context - The ZuploContext
1000
+ * @param options - The policy options set in policies.json
1001
+ * @param policyName - The name of the policy as set in policies.json
1002
+ * @returns A Request or a Response
1003
+ */
1004
+ export declare function AIGatewayPromptInjectionPolicy(
1005
+ request: ZuploRequest,
1006
+ context: ZuploContext,
1007
+ unparsedOptions: unknown,
1008
+ policyName: string
1009
+ ): Promise<ZuploRequest | Response>;
1010
+
1011
+ /**
1012
+ * The options for the Prompt Injection Protection policy.
1013
+ * @public
1014
+ */
1015
+ export declare interface AIGatewayPromptInjectionPolicyOptions {
1016
+ apiKey?: APIKey;
1017
+ appId?: ClassifierAppID;
1018
+ execution?: Execution;
1019
+ recentMessageCount?: RecentMessageCount;
1020
+ model?: ClassifierModel;
1021
+ classifierPrompt?: ClassifierPrompt;
1022
+ baseUrl?: BaseURL;
1023
+ timeoutMs?: ClassifierTimeoutMs;
1024
+ endpoints?: ApplicableEndpoints_2;
1025
+ onUnknownShape?: OnUnknownShape_2;
1026
+ onError?: OnClassifierError;
1027
+ }
1028
+
887
1029
  /**
888
1030
  * Public metadata for an AI Gateway provider name and its models.
889
1031
  *
@@ -1069,10 +1211,10 @@ export declare interface AIGatewaySemanticCacheV2InboundPolicyOptions {
1069
1211
  semanticTolerance?: SemanticTolerance;
1070
1212
  expirationSecondsTtl?: CacheTTLSeconds;
1071
1213
  namespace?: CacheNamespace;
1072
- recentMessageCount?: RecentMessageCount;
1214
+ recentMessageCount?: RecentMessageCount_2;
1073
1215
  maxConversationLength?: MaxConversationLength;
1074
- endpoints?: ApplicableEndpoints_2;
1075
- onUnknownShape?: OnUnknownShape_2;
1216
+ endpoints?: ApplicableEndpoints_3;
1217
+ onUnknownShape?: OnUnknownShape_3;
1076
1218
  }
1077
1219
 
1078
1220
  /**
@@ -1135,15 +1277,15 @@ export declare function AIGatewaySmartRouterInboundPolicy(
1135
1277
  * @public
1136
1278
  */
1137
1279
  export declare interface AIGatewaySmartRouterInboundPolicyOptions {
1138
- classifierAppID: ClassifierAppID;
1139
- classifierAppApiKey: ClassifierAppAPIKey;
1140
- classifierModel: ClassifierModel;
1280
+ classifierAppID: ClassifierAppID_2;
1281
+ classifierAppApiKey?: ClassifierAppAPIKey;
1282
+ classifierModel: ClassifierModel_2;
1141
1283
  smartRoutingEnabled?: SmartRoutingEnabled;
1142
1284
  modelsByComplexity: ModelsByComplexity;
1143
1285
  intents?: Intents;
1144
- classifierPrompt?: ClassifierPrompt;
1286
+ classifierPrompt?: ClassifierPrompt_2;
1145
1287
  minConfidenceForRouting?: MinimumConfidenceForRouting;
1146
- classifierTimeoutMs?: ClassifierTimeoutMs;
1288
+ classifierTimeoutMs?: ClassifierTimeoutMs_2;
1147
1289
  maxPromptChars?: MaxPromptCharacters;
1148
1290
  }
1149
1291
 
@@ -1407,7 +1549,7 @@ export declare function AkamaiAIFirewallInboundPolicy(
1407
1549
  */
1408
1550
  export declare interface AkamaiAIFirewallPolicyOptions {
1409
1551
  configurationId: ConfigurationID;
1410
- "api-key": APIKey;
1552
+ "api-key": APIKey_2;
1411
1553
  applicationId?: ApplicationID;
1412
1554
  streamingAccumulation?: StreamingAccumulationSettings;
1413
1555
  onError?: OnFirewallError;
@@ -1452,11 +1594,11 @@ export declare function AkamaiAIFirewallV2InboundPolicy(
1452
1594
  */
1453
1595
  export declare interface AkamaiAIFirewallV2PolicyOptions {
1454
1596
  configurationId: ConfigurationID_2;
1455
- "api-key": APIKey_2;
1597
+ "api-key": APIKey_3;
1456
1598
  applicationId?: ApplicationID_2;
1457
1599
  streamingAccumulation?: StreamingAccumulationSettings_2;
1458
- endpoints?: ApplicableEndpoints_3;
1459
- onUnknownShape?: OnUnknownShape_3;
1600
+ endpoints?: ApplicableEndpoints_4;
1601
+ onUnknownShape?: OnUnknownShape_4;
1460
1602
  onError?: OnFirewallError_2;
1461
1603
  }
1462
1604
 
@@ -1839,7 +1981,7 @@ export declare interface ApiAuthKeyInboundPolicyOptions {
1839
1981
  }
1840
1982
 
1841
1983
  /**
1842
- * The API key for the AI Firewall.
1984
+ * Credential used to run the classifier. Without `appId` this is the API key for the OpenAI-compatible service at `baseUrl`, and it is required. With `appId` it is optional: omit it when the classifier app runs the Ensure Gateway Internal Invocation Only policy, which authorizes the in-process invocation itself, and set it only when that app authenticates callers with API keys, in which case it is sent as `Authorization: Bearer`.
1843
1985
  * @public
1844
1986
  */
1845
1987
  declare type APIKey = string;
@@ -1850,6 +1992,12 @@ declare type APIKey = string;
1850
1992
  */
1851
1993
  declare type APIKey_2 = string;
1852
1994
 
1995
+ /**
1996
+ * The API key for the AI Firewall.
1997
+ * @public
1998
+ */
1999
+ declare type APIKey_3 = string;
2000
+
1853
2001
  /**
1854
2002
  * Represents a consumer in the API Key service.
1855
2003
  * @public
@@ -2087,11 +2235,22 @@ declare type ApplicableEndpoints = (
2087
2235
  | "anthropic-messages"
2088
2236
  )[];
2089
2237
 
2238
+ /**
2239
+ * The endpoint shapes this policy applies to. Omit to apply to all (openai-chat, openai-responses, anthropic-messages).
2240
+ *
2241
+ * @minItems 1
2242
+ * @public
2243
+ */
2244
+ declare type ApplicableEndpoints_2 = [
2245
+ "openai-chat" | "openai-responses" | "anthropic-messages",
2246
+ ...("openai-chat" | "openai-responses" | "anthropic-messages")[],
2247
+ ];
2248
+
2090
2249
  /**
2091
2250
  * The endpoint shapes to cache. Defaults to all shapes: ['openai-chat', 'anthropic-messages', 'openai-responses'].
2092
2251
  * @public
2093
2252
  */
2094
- declare type ApplicableEndpoints_2 = (
2253
+ declare type ApplicableEndpoints_3 = (
2095
2254
  | "openai-chat"
2096
2255
  | "openai-responses"
2097
2256
  | "anthropic-messages"
@@ -2101,7 +2260,7 @@ declare type ApplicableEndpoints_2 = (
2101
2260
  * The endpoint shapes this policy applies to. Omit to apply to all (openai-chat, openai-responses, anthropic-messages).
2102
2261
  * @public
2103
2262
  */
2104
- declare type ApplicableEndpoints_3 = (
2263
+ declare type ApplicableEndpoints_4 = (
2105
2264
  | "openai-chat"
2106
2265
  | "openai-responses"
2107
2266
  | "anthropic-messages"
@@ -2111,7 +2270,7 @@ declare type ApplicableEndpoints_3 = (
2111
2270
  * The endpoint shapes this policy applies to. Omit to apply to all (openai-chat, openai-responses, anthropic-messages).
2112
2271
  * @public
2113
2272
  */
2114
- declare type ApplicableEndpoints_4 = (
2273
+ declare type ApplicableEndpoints_5 = (
2115
2274
  | "openai-chat"
2116
2275
  | "openai-responses"
2117
2276
  | "anthropic-messages"
@@ -2121,7 +2280,7 @@ declare type ApplicableEndpoints_4 = (
2121
2280
  * The endpoint shapes this policy applies to. Omit to apply to all (openai-chat, openai-responses, anthropic-messages).
2122
2281
  * @public
2123
2282
  */
2124
- declare type ApplicableEndpoints_5 = (
2283
+ declare type ApplicableEndpoints_6 = (
2125
2284
  | "openai-chat"
2126
2285
  | "openai-responses"
2127
2286
  | "anthropic-messages"
@@ -3150,6 +3309,12 @@ declare class BaseOpenFGAAuthZInboundPolicy extends InboundPolicy<OpenFGAAuthZIn
3150
3309
  private getAuthorizer;
3151
3310
  }
3152
3311
 
3312
+ /**
3313
+ * Base URL of the OpenAI-compatible API that runs the classifier model. Mutually exclusive with `appId`, which routes the classifier through an AI Gateway app instead.
3314
+ * @public
3315
+ */
3316
+ declare type BaseURL = string;
3317
+
3153
3318
  /**
3154
3319
  * An account object.
3155
3320
  * @public
@@ -3795,35 +3960,59 @@ declare type Claim = string;
3795
3960
  declare type ClaimCheck = EqualsRule | InRule | StartsWithRule;
3796
3961
 
3797
3962
  /**
3798
- * API key sent as `Authorization: Bearer` when invoking the classifier app.
3963
+ * API key sent as `Authorization: Bearer` when invoking the classifier app. Omit it when the classifier app runs the Ensure Gateway Internal Invocation Only policy: the classifier call never leaves the gateway, so that policy accepts it and rejects everything arriving over the network, and no credential is sent. Set it only when the classifier app authenticates callers with API keys.
3799
3964
  * @public
3800
3965
  */
3801
3966
  declare type ClassifierAppAPIKey = string;
3802
3967
 
3803
3968
  /**
3804
- * The AI Gateway application id used to run the classifier prompt and evaluate the user's request.
3969
+ * Run the classifier on another AI Gateway app instead of calling an external API directly. The gateway invokes that app in-process — no outbound HTTP hop — so the classifier inherits its provider credentials, model routing, fallbacks and quotas, and provider keys stay on one app. Give that app the Ensure Gateway Internal Invocation Only policy and `apiKey` is not needed at all. When set, `model` must name a routed model as `provider/model` and `baseUrl` must not be set. The target app must not itself run this policy: it would be asked to classify its own classification request, which is rejected as a configuration error rather than silently skipped. Omit to call `baseUrl` directly.
3805
3970
  * @public
3806
3971
  */
3807
3972
  declare type ClassifierAppID = string;
3808
3973
 
3809
3974
  /**
3810
- * The model (`providerName/model`) the classifier uses to evaluate the user's request. E.g. `openai/gpt-4o-mini`.
3975
+ * The AI Gateway application id used to run the classifier prompt and evaluate the user's request.
3976
+ * @public
3977
+ */
3978
+ declare type ClassifierAppID_2 = string;
3979
+
3980
+ /**
3981
+ * Tool-calling capable model used to classify prompts. Prefer a small, fast model; the classification runs before every inspected request reaches the upstream model. With `appId` set this must name a model the classifier app routes, written as `provider/model` (for example `openai/gpt-4o-mini`), and has no default.
3811
3982
  * @public
3812
3983
  */
3813
3984
  declare type ClassifierModel = string;
3814
3985
 
3815
3986
  /**
3816
- * Prompt used to analyze and classify the user message. Omit to use the built-in classifier prompt.
3987
+ * The model (`providerName/model`) the classifier uses to evaluate the user's request. E.g. `openai/gpt-4o-mini`.
3988
+ * @public
3989
+ */
3990
+ declare type ClassifierModel_2 = string;
3991
+
3992
+ /**
3993
+ * Replaces the built-in system prompt that tells the classifier what counts as a prompt injection. A string, or an array of lines joined with newlines. The inspected text is always sent as a separate user message and the verdict always comes back through the fixed SAFE/UNSAFE tool call, so a custom prompt changes what is flagged, never how the verdict is read. Omit to use the built-in prompt, which the policy documentation shows in full.
3817
3994
  * @public
3818
3995
  */
3819
3996
  declare type ClassifierPrompt = string | [string, ...string[]];
3820
3997
 
3821
3998
  /**
3822
- * Timeout configured for the classifier task. When exceeded, the request is forwarded without classification to the original model.
3999
+ * Prompt used to analyze and classify the user message. Omit to use the built-in classifier prompt.
4000
+ * @public
4001
+ */
4002
+ declare type ClassifierPrompt_2 = string | [string, ...string[]];
4003
+
4004
+ /**
4005
+ * Maximum time in milliseconds to wait for the classifier before applying the onError action.
3823
4006
  * @public
3824
4007
  */
3825
4008
  declare type ClassifierTimeoutMs = number;
3826
4009
 
4010
+ /**
4011
+ * Timeout configured for the classifier task. When exceeded, the request is forwarded without classification to the original model.
4012
+ * @public
4013
+ */
4014
+ declare type ClassifierTimeoutMs_2 = number;
4015
+
3827
4016
  /**
3828
4017
  * Removes all headers from the incoming request except for those in the exclude list.
3829
4018
  *
@@ -4092,8 +4281,8 @@ export declare interface CometOpikTracingV2PolicyOptions {
4092
4281
  * The base URL for the Comet Opik API (optional, defaults to https://www.comet.com/opik/api).
4093
4282
  */
4094
4283
  baseUrl?: string;
4095
- endpoints?: ApplicableEndpoints_4;
4096
- onUnknownShape?: OnUnknownShape_4;
4284
+ endpoints?: ApplicableEndpoints_5;
4285
+ onUnknownShape?: OnUnknownShape_5;
4097
4286
  }
4098
4287
 
4099
4288
  /**
@@ -5409,12 +5598,23 @@ declare const EventType: {
5409
5598
 
5410
5599
  declare type EventType = (typeof EventType)[keyof typeof EventType];
5411
5600
 
5601
+ /**
5602
+ * How the classifier runs relative to the rest of the inbound policy chain. 'sequential' classifies inline, so later policies wait for the verdict; this is the behaviour when the option is omitted. 'parallel' classifies while the remaining inbound policies run — the verdict is still enforced before the request reaches the model, so no prompt is forwarded unchecked, but on a safe prompt the classifier's latency overlaps the rest of the chain instead of adding to it.
5603
+ * @public
5604
+ */
5605
+ declare type Execution = "sequential" | "parallel";
5606
+
5412
5607
  /**
5413
5608
  * Best-effort flatten of ALL human/assistant text in a request OR response body,
5414
5609
  * across every shape — the one sanctioned cross-shape helper. Intended for
5415
5610
  * guardrails that just need "all the text to scan/moderate"; it is deliberately
5416
5611
  * lossy (drops roles, structure, tool calls). Everything else should read the
5417
5612
  * typed body via {@link getRequestBody} / {@link getResponseBody}.
5613
+ *
5614
+ * For "the most recent messages" rather than all of the text, use
5615
+ * `conversation-window.ts` (`getConversationItems` + `selectRecentTurns`):
5616
+ * the one definition of a message window that the semantic cache and the
5617
+ * prompt injection guardrail share.
5418
5618
  * @public
5419
5619
  */
5420
5620
  export declare function extractAllText(body: unknown): string;
@@ -5678,8 +5878,8 @@ export declare interface GalileoTracingV2PolicyOptions {
5678
5878
  * The base URL for the Galileo API (optional, defaults to https://api.galileo.ai).
5679
5879
  */
5680
5880
  baseUrl?: string;
5681
- endpoints?: ApplicableEndpoints_5;
5682
- onUnknownShape?: OnUnknownShape_5;
5881
+ endpoints?: ApplicableEndpoints_6;
5882
+ onUnknownShape?: OnUnknownShape_6;
5683
5883
  }
5684
5884
 
5685
5885
  /**
@@ -11196,6 +11396,12 @@ export declare interface OktaJwtInboundPolicyOptions {
11196
11396
  oAuthResourceMetadataEnabled?: boolean;
11197
11397
  }
11198
11398
 
11399
+ /**
11400
+ * What to do when the classifier call itself fails (invalid API key, rate limit, timeout, outage). 'block' (the default) fails closed and returns a 502 so unverified prompts are never forwarded; 'allow' fails open and lets the request through without inspection.
11401
+ * @public
11402
+ */
11403
+ declare type OnClassifierError = "block" | "allow";
11404
+
11199
11405
  /**
11200
11406
  * What to do if the scanner itself throws. The engine is a local in-gateway scanner, so this is effectively unreachable outside of a runtime defect — but a guardrail must declare its failure posture. `block` (the default) fails closed with a 500 in the route's native error format; `allow` fails open and serves the content uninspected.
11201
11407
  * @public
@@ -11266,19 +11472,19 @@ declare interface OnSendingAwsLambdaEventHook {
11266
11472
  declare type OnUnknownShape = "deny" | "skip";
11267
11473
 
11268
11474
  /**
11269
- * Unused by the cache (a cache miss is never unsafe, so it always fails open). Present for interface consistency.
11475
+ * What to do when the request shape cannot be inspected. As a guardrail, this policy defaults to 'deny' (fail closed) so uninspectable content is never forwarded.
11270
11476
  * @public
11271
11477
  */
11272
11478
  declare type OnUnknownShape_2 = "deny" | "skip";
11273
11479
 
11274
11480
  /**
11275
- * What to do when the request shape cannot be inspected. As a guardrail, this policy defaults to 'deny' (fail closed) so uninspectable content is never served.
11481
+ * Unused by the cache (a cache miss is never unsafe, so it always fails open). Present for interface consistency.
11276
11482
  * @public
11277
11483
  */
11278
11484
  declare type OnUnknownShape_3 = "deny" | "skip";
11279
11485
 
11280
11486
  /**
11281
- * What to do on a shape the policy cannot read. As an observer this defaults to 'skip' (fail open — pass through untraced).
11487
+ * What to do when the request shape cannot be inspected. As a guardrail, this policy defaults to 'deny' (fail closed) so uninspectable content is never served.
11282
11488
  * @public
11283
11489
  */
11284
11490
  declare type OnUnknownShape_4 = "deny" | "skip";
@@ -11289,6 +11495,12 @@ declare type OnUnknownShape_4 = "deny" | "skip";
11289
11495
  */
11290
11496
  declare type OnUnknownShape_5 = "deny" | "skip";
11291
11497
 
11498
+ /**
11499
+ * What to do on a shape the policy cannot read. As an observer this defaults to 'skip' (fail open — pass through untraced).
11500
+ * @public
11501
+ */
11502
+ declare type OnUnknownShape_6 = "deny" | "skip";
11503
+
11292
11504
  /**
11293
11505
  * Handler that serves OpenAPI specification files.
11294
11506
  * Use this to expose your API documentation in a standard format that can be
@@ -13018,11 +13230,17 @@ export declare function ReadmeMetricsInboundPolicy(
13018
13230
  ): Promise<ZuploRequest<RequestGeneric>>;
13019
13231
 
13020
13232
  /**
13021
- * How many of the conversation's most recent messages (input items on the Responses endpoint) form the cache key, both when storing a response and when matching later requests. Earlier messages are ignored, so a multi-turn conversation can hit an entry cached from a shorter one; system messages are always included. Requests whose keyed window contains no user message (for example a conversation ending in an assistant prefill) are not cached. Defaults to 1 (match on the newest message only).
13233
+ * How many of the conversation's most recent messages the classifier inspects (input items on the Responses endpoint). Earlier messages are not re-inspected: each was screened when it was the newest, so a chat session pays for one classification per turn instead of one per transcript. System and developer messages, Anthropic's top-level `system` and the Responses `instructions` field never count and are never inspected — they are your application's own instructions, not where an injection arrives. Tool results count as messages and are inspected. Raise this when clients send conversation history that was assembled outside the gateway. Defaults to 1 (the newest message only).
13022
13234
  * @public
13023
13235
  */
13024
13236
  declare type RecentMessageCount = number;
13025
13237
 
13238
+ /**
13239
+ * How many of the conversation's most recent messages (input items on the Responses endpoint) form the cache key, both when storing a response and when matching later requests. Earlier messages are ignored, so a multi-turn conversation can hit an entry cached from a shorter one; system messages are always included. Requests whose keyed window contains no user message (for example a conversation ending in an assistant prefill) are not cached. Defaults to 1 (match on the newest message only).
13240
+ * @public
13241
+ */
13242
+ declare type RecentMessageCount_2 = number;
13243
+
13026
13244
  /**
13027
13245
  * Record the GraphQL response-cache outcome for the in-flight operation so
13028
13246
  * the analytics middleware can emit it as the `cacheState` dimension on the
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zuplo/runtime",
3
3
  "type": "module",
4
- "version": "7.8.0",
4
+ "version": "7.8.2",
5
5
  "repository": "https://github.com/zuplo/zuplo",
6
6
  "author": "Zuplo, Inc.",
7
7
  "exports": {