@theoremjs/agents 0.0.0-stage → 0.3.1
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/LICENSE +21 -0
- package/README.md +545 -2
- package/esm/_dnt.polyfills.d.ts +66 -0
- package/esm/_dnt.polyfills.js +51 -0
- package/esm/mod.d.ts +79 -0
- package/esm/mod.js +49 -0
- package/esm/package.json +3 -0
- package/esm/src/cli/bin.d.ts +7 -0
- package/esm/src/cli/bin.js +9 -0
- package/esm/src/cli/commands/bench.d.ts +6 -0
- package/esm/src/cli/commands/bench.js +480 -0
- package/esm/src/cli/commands/detect-compile.d.ts +17 -0
- package/esm/src/cli/commands/detect-compile.js +22 -0
- package/esm/src/cli/commands/eval.d.ts +37 -0
- package/esm/src/cli/commands/eval.js +190 -0
- package/esm/src/cli/commands/fuzz-canary.d.ts +15 -0
- package/esm/src/cli/commands/fuzz-canary.js +241 -0
- package/esm/src/cli/commands/fuzz-guardrails.d.ts +2 -0
- package/esm/src/cli/commands/fuzz-guardrails.js +5 -0
- package/esm/src/cli/commands/profile.d.ts +2 -0
- package/esm/src/cli/commands/profile.js +80 -0
- package/esm/src/cli/commands/run.d.ts +13 -0
- package/esm/src/cli/commands/run.js +45 -0
- package/esm/src/cli/commands/test.d.ts +26 -0
- package/esm/src/cli/commands/test.js +143 -0
- package/esm/src/cli/event-log.d.ts +15 -0
- package/esm/src/cli/event-log.js +136 -0
- package/esm/src/cli/index.d.ts +10 -0
- package/esm/src/cli/index.js +267 -0
- package/esm/src/cli/matrix/fixtures.d.ts +10 -0
- package/esm/src/cli/matrix/fixtures.js +67 -0
- package/esm/src/cli/matrix/synthesizer.d.ts +18 -0
- package/esm/src/cli/matrix/synthesizer.js +103 -0
- package/esm/src/evals/attachments.d.ts +5 -0
- package/esm/src/evals/attachments.js +55 -0
- package/esm/src/evals/breakdown.d.ts +30 -0
- package/esm/src/evals/breakdown.js +69 -0
- package/esm/src/evals/graders/answer.d.ts +16 -0
- package/esm/src/evals/graders/answer.js +134 -0
- package/esm/src/evals/graders/code.d.ts +40 -0
- package/esm/src/evals/graders/code.js +184 -0
- package/esm/src/evals/graders/judge.d.ts +24 -0
- package/esm/src/evals/graders/judge.js +367 -0
- package/esm/src/evals/graders/latency.d.ts +6 -0
- package/esm/src/evals/graders/latency.js +82 -0
- package/esm/src/evals/graders/live.d.ts +14 -0
- package/esm/src/evals/graders/live.js +42 -0
- package/esm/src/evals/graders/media.d.ts +18 -0
- package/esm/src/evals/graders/media.js +91 -0
- package/esm/src/evals/graders/shared.d.ts +11 -0
- package/esm/src/evals/graders/shared.js +62 -0
- package/esm/src/evals/graders/transcript.d.ts +19 -0
- package/esm/src/evals/graders/transcript.js +202 -0
- package/esm/src/evals/mod.d.ts +34 -0
- package/esm/src/evals/mod.js +22 -0
- package/esm/src/evals/record.d.ts +41 -0
- package/esm/src/evals/record.js +107 -0
- package/esm/src/evals/rubrics/catalog.d.ts +148 -0
- package/esm/src/evals/rubrics/catalog.js +846 -0
- package/esm/src/evals/rubrics/mod.d.ts +24 -0
- package/esm/src/evals/rubrics/mod.js +55 -0
- package/esm/src/evals/rubrics/mustache.d.ts +23 -0
- package/esm/src/evals/rubrics/mustache.js +154 -0
- package/esm/src/evals/rubrics/types.d.ts +54 -0
- package/esm/src/evals/rubrics/types.js +74 -0
- package/esm/src/evals/run.d.ts +75 -0
- package/esm/src/evals/run.js +418 -0
- package/esm/src/evals/suite.d.ts +28 -0
- package/esm/src/evals/suite.js +97 -0
- package/esm/src/evals/summary.d.ts +35 -0
- package/esm/src/evals/summary.js +31 -0
- package/esm/src/evals/trial.d.ts +14 -0
- package/esm/src/evals/trial.js +135 -0
- package/esm/src/evals/types.d.ts +169 -0
- package/esm/src/evals/types.js +113 -0
- package/esm/src/evals/verdict.d.ts +23 -0
- package/esm/src/evals/verdict.js +48 -0
- package/esm/src/guardrails/boundaries.d.ts +41 -0
- package/esm/src/guardrails/boundaries.js +103 -0
- package/esm/src/guardrails/canary-gate.d.ts +22 -0
- package/esm/src/guardrails/canary-gate.js +40 -0
- package/esm/src/guardrails/canary.d.ts +146 -0
- package/esm/src/guardrails/canary.js +974 -0
- package/esm/src/guardrails/compile-egress.d.ts +12 -0
- package/esm/src/guardrails/compile-egress.js +12 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +24 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.js +305 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.d.ts +5 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.js +199 -0
- package/esm/src/guardrails/corpus/inbound-payloads.d.ts +5 -0
- package/esm/src/guardrails/corpus/inbound-payloads.js +120 -0
- package/esm/src/guardrails/corpus/live-attacks.d.ts +15 -0
- package/esm/src/guardrails/corpus/live-attacks.js +229 -0
- package/esm/src/guardrails/corpus/mod.d.ts +7 -0
- package/esm/src/guardrails/corpus/mod.js +4 -0
- package/esm/src/guardrails/corpus/secrets.d.ts +12 -0
- package/esm/src/guardrails/corpus/secrets.js +16 -0
- package/esm/src/guardrails/corpus/strings.d.ts +23 -0
- package/esm/src/guardrails/corpus/strings.js +29 -0
- package/esm/src/guardrails/corpus/types.d.ts +36 -0
- package/esm/src/guardrails/corpus/types.js +1 -0
- package/esm/src/guardrails/credential-rules.d.ts +36 -0
- package/esm/src/guardrails/credential-rules.js +3001 -0
- package/esm/src/guardrails/credential-scan.d.ts +45 -0
- package/esm/src/guardrails/credential-scan.js +172 -0
- package/esm/src/guardrails/destinations.d.ts +45 -0
- package/esm/src/guardrails/destinations.js +234 -0
- package/esm/src/guardrails/detect-at.d.ts +107 -0
- package/esm/src/guardrails/detect-at.js +434 -0
- package/esm/src/guardrails/detect-reply.d.ts +61 -0
- package/esm/src/guardrails/detect-reply.js +95 -0
- package/esm/src/guardrails/detect-stream.d.ts +33 -0
- package/esm/src/guardrails/detect-stream.js +77 -0
- package/esm/src/guardrails/detectors.d.ts +216 -0
- package/esm/src/guardrails/detectors.js +503 -0
- package/esm/src/guardrails/egress-automata.d.ts +12 -0
- package/esm/src/guardrails/egress-automata.js +25582 -0
- package/esm/src/guardrails/egress-compiler.d.ts +55 -0
- package/esm/src/guardrails/egress-compiler.js +431 -0
- package/esm/src/guardrails/egress-patterns.d.ts +26 -0
- package/esm/src/guardrails/egress-patterns.js +36 -0
- package/esm/src/guardrails/egress-stream.d.ts +123 -0
- package/esm/src/guardrails/egress-stream.js +774 -0
- package/esm/src/guardrails/egress-urls.d.ts +86 -0
- package/esm/src/guardrails/egress-urls.js +909 -0
- package/esm/src/guardrails/egress.d.ts +46 -0
- package/esm/src/guardrails/egress.js +124 -0
- package/esm/src/guardrails/error.d.ts +31 -0
- package/esm/src/guardrails/error.js +96 -0
- package/esm/src/guardrails/event-schemas.d.ts +100 -0
- package/esm/src/guardrails/event-schemas.js +48 -0
- package/esm/src/guardrails/events.d.ts +13 -0
- package/esm/src/guardrails/events.js +45 -0
- package/esm/src/guardrails/hints.d.ts +14 -0
- package/esm/src/guardrails/hints.js +57 -0
- package/esm/src/guardrails/hits.d.ts +14 -0
- package/esm/src/guardrails/hits.js +30 -0
- package/esm/src/guardrails/host-patterns.d.ts +85 -0
- package/esm/src/guardrails/host-patterns.js +173 -0
- package/esm/src/guardrails/injection-patterns.d.ts +20 -0
- package/esm/src/guardrails/injection-patterns.js +126 -0
- package/esm/src/guardrails/injection-reversed.d.ts +9 -0
- package/esm/src/guardrails/injection-reversed.js +49 -0
- package/esm/src/guardrails/injection.d.ts +30 -0
- package/esm/src/guardrails/injection.js +460 -0
- package/esm/src/guardrails/labels.d.ts +40 -0
- package/esm/src/guardrails/labels.js +874 -0
- package/esm/src/guardrails/live-outbound-gate.d.ts +55 -0
- package/esm/src/guardrails/live-outbound-gate.js +298 -0
- package/esm/src/guardrails/mod.d.ts +54 -0
- package/esm/src/guardrails/mod.js +34 -0
- package/esm/src/guardrails/network.d.ts +46 -0
- package/esm/src/guardrails/network.js +330 -0
- package/esm/src/guardrails/normalize.d.ts +20 -0
- package/esm/src/guardrails/normalize.js +165 -0
- package/esm/src/guardrails/policy.d.ts +4 -0
- package/esm/src/guardrails/policy.js +21 -0
- package/esm/src/guardrails/progressive-yield.d.ts +110 -0
- package/esm/src/guardrails/progressive-yield.js +281 -0
- package/esm/src/guardrails/prompt-echo.d.ts +40 -0
- package/esm/src/guardrails/prompt-echo.js +306 -0
- package/esm/src/guardrails/quota.d.ts +21 -0
- package/esm/src/guardrails/quota.js +80 -0
- package/esm/src/guardrails/rules.d.ts +47 -0
- package/esm/src/guardrails/rules.js +47 -0
- package/esm/src/guardrails/sanitize.d.ts +40 -0
- package/esm/src/guardrails/sanitize.js +160 -0
- package/esm/src/guardrails/sensitive-groups.d.ts +21 -0
- package/esm/src/guardrails/sensitive-groups.js +12 -0
- package/esm/src/guardrails/sensitive.d.ts +22 -0
- package/esm/src/guardrails/sensitive.js +234 -0
- package/esm/src/guardrails/serialize.d.ts +15 -0
- package/esm/src/guardrails/serialize.js +37 -0
- package/esm/src/guardrails/testing.d.ts +11 -0
- package/esm/src/guardrails/testing.js +10 -0
- package/esm/src/guardrails/theorem-error.d.ts +21 -0
- package/esm/src/guardrails/theorem-error.js +54 -0
- package/esm/src/guardrails/thought-guard.d.ts +76 -0
- package/esm/src/guardrails/thought-guard.js +664 -0
- package/esm/src/guardrails/tool-directives.d.ts +38 -0
- package/esm/src/guardrails/tool-directives.js +195 -0
- package/esm/src/guardrails/tool-leak.d.ts +26 -0
- package/esm/src/guardrails/tool-leak.js +45 -0
- package/esm/src/guardrails/tool-result.d.ts +92 -0
- package/esm/src/guardrails/tool-result.js +272 -0
- package/esm/src/guardrails/types.d.ts +250 -0
- package/esm/src/guardrails/types.js +58 -0
- package/esm/src/host/client-turn.d.ts +36 -0
- package/esm/src/host/client-turn.js +80 -0
- package/esm/src/host/mint-trace.d.ts +29 -0
- package/esm/src/host/mint-trace.js +60 -0
- package/esm/src/host/mod.d.ts +13 -0
- package/esm/src/host/mod.js +11 -0
- package/esm/src/host/readStreamingJsonStringField.d.ts +2 -0
- package/esm/src/host/readStreamingJsonStringField.js +27 -0
- package/esm/src/host/reply.d.ts +13 -0
- package/esm/src/host/reply.js +41 -0
- package/esm/src/interface/blocks.d.ts +11 -0
- package/esm/src/interface/blocks.js +283 -0
- package/esm/src/interface/composer-actions.d.ts +24 -0
- package/esm/src/interface/composer-actions.js +33 -0
- package/esm/src/interface/draft.d.ts +20 -0
- package/esm/src/interface/draft.js +39 -0
- package/esm/src/interface/from-profile.d.ts +24 -0
- package/esm/src/interface/from-profile.js +179 -0
- package/esm/src/interface/history.d.ts +46 -0
- package/esm/src/interface/history.js +278 -0
- package/esm/src/interface/inputs.d.ts +11 -0
- package/esm/src/interface/inputs.js +67 -0
- package/esm/src/interface/mod.d.ts +33 -0
- package/esm/src/interface/mod.js +22 -0
- package/esm/src/interface/models.d.ts +26 -0
- package/esm/src/interface/models.js +50 -0
- package/esm/src/interface/pending.d.ts +57 -0
- package/esm/src/interface/pending.js +152 -0
- package/esm/src/interface/profile-interface.d.ts +4 -0
- package/esm/src/interface/profile-interface.js +237 -0
- package/esm/src/interface/session.d.ts +71 -0
- package/esm/src/interface/session.js +128 -0
- package/esm/src/interface/stop.d.ts +13 -0
- package/esm/src/interface/stop.js +28 -0
- package/esm/src/interface/tool-calls.d.ts +32 -0
- package/esm/src/interface/tool-calls.js +127 -0
- package/esm/src/interface/tool-invoke.d.ts +6 -0
- package/esm/src/interface/tool-invoke.js +22 -0
- package/esm/src/interface/tool-media.d.ts +11 -0
- package/esm/src/interface/tool-media.js +113 -0
- package/esm/src/interface/types.d.ts +278 -0
- package/esm/src/interface/types.js +5 -0
- package/esm/src/kernel/api-catalog.d.ts +85 -0
- package/esm/src/kernel/api-catalog.js +229 -0
- package/esm/src/kernel/auth/credential-source.d.ts +23 -0
- package/esm/src/kernel/auth/credential-source.js +11 -0
- package/esm/src/kernel/auth/crypto.d.ts +56 -0
- package/esm/src/kernel/auth/crypto.js +163 -0
- package/esm/src/kernel/auth/mod.d.ts +5 -0
- package/esm/src/kernel/auth/mod.js +5 -0
- package/esm/src/kernel/auth/oauth.d.ts +18 -0
- package/esm/src/kernel/auth/oauth.js +439 -0
- package/esm/src/kernel/auth/scope-refusal.d.ts +9 -0
- package/esm/src/kernel/auth/scope-refusal.js +8 -0
- package/esm/src/kernel/auth/typed-secret.d.ts +13 -0
- package/esm/src/kernel/auth/typed-secret.js +23 -0
- package/esm/src/kernel/auth/types.d.ts +152 -0
- package/esm/src/kernel/auth/types.js +1 -0
- package/esm/src/kernel/checkpoint.d.ts +43 -0
- package/esm/src/kernel/checkpoint.js +58 -0
- package/esm/src/kernel/default-scope.d.ts +72 -0
- package/esm/src/kernel/default-scope.js +121 -0
- package/esm/src/kernel/engine/call-trace.d.ts +19 -0
- package/esm/src/kernel/engine/call-trace.js +29 -0
- package/esm/src/kernel/engine/compaction.d.ts +71 -0
- package/esm/src/kernel/engine/compaction.js +203 -0
- package/esm/src/kernel/engine/decision.d.ts +43 -0
- package/esm/src/kernel/engine/decision.js +439 -0
- package/esm/src/kernel/engine/embedding.d.ts +8 -0
- package/esm/src/kernel/engine/embedding.js +118 -0
- package/esm/src/kernel/engine/hash.d.ts +6 -0
- package/esm/src/kernel/engine/hash.js +22 -0
- package/esm/src/kernel/engine/live-inbound.d.ts +19 -0
- package/esm/src/kernel/engine/live-inbound.js +44 -0
- package/esm/src/kernel/engine/live-ingress.d.ts +15 -0
- package/esm/src/kernel/engine/live-ingress.js +42 -0
- package/esm/src/kernel/engine/record.d.ts +3 -0
- package/esm/src/kernel/engine/record.js +11 -0
- package/esm/src/kernel/engine/repair.d.ts +7 -0
- package/esm/src/kernel/engine/repair.js +36 -0
- package/esm/src/kernel/engine/runner/gates.d.ts +5 -0
- package/esm/src/kernel/engine/runner/gates.js +508 -0
- package/esm/src/kernel/engine/runner/mod.d.ts +29 -0
- package/esm/src/kernel/engine/runner/mod.js +625 -0
- package/esm/src/kernel/engine/runner/nested.d.ts +32 -0
- package/esm/src/kernel/engine/runner/nested.js +134 -0
- package/esm/src/kernel/engine/runner/schema-validation.d.ts +35 -0
- package/esm/src/kernel/engine/runner/schema-validation.js +179 -0
- package/esm/src/kernel/engine/runner/stages.d.ts +28 -0
- package/esm/src/kernel/engine/runner/stages.js +41 -0
- package/esm/src/kernel/engine/runner/state.d.ts +97 -0
- package/esm/src/kernel/engine/runner/state.js +50 -0
- package/esm/src/kernel/engine/runner/step-order.d.ts +27 -0
- package/esm/src/kernel/engine/runner/step-order.js +165 -0
- package/esm/src/kernel/engine/runner/steps.d.ts +14 -0
- package/esm/src/kernel/engine/runner/steps.js +519 -0
- package/esm/src/kernel/engine/runner/stream.d.ts +71 -0
- package/esm/src/kernel/engine/runner/stream.js +376 -0
- package/esm/src/kernel/engine/runner/usage.d.ts +45 -0
- package/esm/src/kernel/engine/runner/usage.js +148 -0
- package/esm/src/kernel/engine/session/mod.d.ts +33 -0
- package/esm/src/kernel/engine/session/mod.js +1182 -0
- package/esm/src/kernel/engine/session/session-trace.d.ts +115 -0
- package/esm/src/kernel/engine/session/session-trace.js +500 -0
- package/esm/src/kernel/engine/token-estimate.d.ts +23 -0
- package/esm/src/kernel/engine/token-estimate.js +38 -0
- package/esm/src/kernel/engine/tool-trace.d.ts +58 -0
- package/esm/src/kernel/engine/tool-trace.js +132 -0
- package/esm/src/kernel/engine/tree.d.ts +2 -0
- package/esm/src/kernel/engine/tree.js +17 -0
- package/esm/src/kernel/engine/turn-trace.d.ts +119 -0
- package/esm/src/kernel/engine/turn-trace.js +855 -0
- package/esm/src/kernel/engine/usage.d.ts +36 -0
- package/esm/src/kernel/engine/usage.js +151 -0
- package/esm/src/kernel/interaction-parts.d.ts +13 -0
- package/esm/src/kernel/interaction-parts.js +40 -0
- package/esm/src/kernel/json.d.ts +10 -0
- package/esm/src/kernel/json.js +3 -0
- package/esm/src/kernel/mod.d.ts +74 -0
- package/esm/src/kernel/mod.js +45 -0
- package/esm/src/kernel/profile-graph.d.ts +145 -0
- package/esm/src/kernel/profile-graph.js +158 -0
- package/esm/src/kernel/profile-presence.d.ts +18 -0
- package/esm/src/kernel/profile-presence.js +158 -0
- package/esm/src/kernel/profile-scope.d.ts +40 -0
- package/esm/src/kernel/profile-scope.js +274 -0
- package/esm/src/kernel/protocols/binding.d.ts +65 -0
- package/esm/src/kernel/protocols/binding.js +125 -0
- package/esm/src/kernel/protocols/limits.d.ts +15 -0
- package/esm/src/kernel/protocols/limits.js +28 -0
- package/esm/src/kernel/protocols/mod.d.ts +5 -0
- package/esm/src/kernel/protocols/mod.js +5 -0
- package/esm/src/kernel/protocols/prices.d.ts +36 -0
- package/esm/src/kernel/protocols/prices.js +37 -0
- package/esm/src/kernel/protocols/protocol.d.ts +253 -0
- package/esm/src/kernel/protocols/protocol.js +253 -0
- package/esm/src/kernel/protocols/provider.d.ts +108 -0
- package/esm/src/kernel/protocols/provider.js +143 -0
- package/esm/src/kernel/protocols/runtime.d.ts +55 -0
- package/esm/src/kernel/protocols/runtime.js +534 -0
- package/esm/src/kernel/provider-budget.d.ts +32 -0
- package/esm/src/kernel/provider-budget.js +262 -0
- package/esm/src/kernel/provider-dispatch.d.ts +13 -0
- package/esm/src/kernel/provider-dispatch.js +36 -0
- package/esm/src/kernel/provider-live.d.ts +7 -0
- package/esm/src/kernel/provider-live.js +189 -0
- package/esm/src/kernel/provider-runtime.d.ts +57 -0
- package/esm/src/kernel/provider-runtime.js +524 -0
- package/esm/src/kernel/registry/attachments.d.ts +46 -0
- package/esm/src/kernel/registry/attachments.js +220 -0
- package/esm/src/kernel/registry/catalog.d.ts +25 -0
- package/esm/src/kernel/registry/catalog.js +85 -0
- package/esm/src/kernel/registry/embedding-rules.d.ts +28 -0
- package/esm/src/kernel/registry/embedding-rules.js +66 -0
- package/esm/src/kernel/registry/ingress.d.ts +12 -0
- package/esm/src/kernel/registry/ingress.js +179 -0
- package/esm/src/kernel/registry/kernel-registry.d.ts +15 -0
- package/esm/src/kernel/registry/kernel-registry.js +15 -0
- package/esm/src/kernel/registry/profile-outputs.d.ts +3 -0
- package/esm/src/kernel/registry/profile-outputs.js +10 -0
- package/esm/src/kernel/registry/profiles.d.ts +116 -0
- package/esm/src/kernel/registry/profiles.js +773 -0
- package/esm/src/kernel/registry/provider-request.d.ts +6 -0
- package/esm/src/kernel/registry/provider-request.js +34 -0
- package/esm/src/kernel/registry/resolve.d.ts +17 -0
- package/esm/src/kernel/registry/resolve.js +238 -0
- package/esm/src/kernel/registry/schemas.d.ts +12 -0
- package/esm/src/kernel/registry/schemas.js +27 -0
- package/esm/src/kernel/registry/slot-fill.d.ts +7 -0
- package/esm/src/kernel/registry/slot-fill.js +22 -0
- package/esm/src/kernel/registry/sole-model.d.ts +2 -0
- package/esm/src/kernel/registry/sole-model.js +4 -0
- package/esm/src/kernel/registry/system-prompt.d.ts +8 -0
- package/esm/src/kernel/registry/system-prompt.js +32 -0
- package/esm/src/kernel/registry/system-role.d.ts +3 -0
- package/esm/src/kernel/registry/system-role.js +9 -0
- package/esm/src/kernel/registry/vault.d.ts +14 -0
- package/esm/src/kernel/registry/vault.js +1 -0
- package/esm/src/kernel/schema.d.ts +226 -0
- package/esm/src/kernel/schema.js +895 -0
- package/esm/src/kernel/scope.d.ts +29 -0
- package/esm/src/kernel/scope.js +45 -0
- package/esm/src/kernel/stages.d.ts +176 -0
- package/esm/src/kernel/stages.js +431 -0
- package/esm/src/kernel/stop.d.ts +116 -0
- package/esm/src/kernel/stop.js +137 -0
- package/esm/src/kernel/system-parts.d.ts +26 -0
- package/esm/src/kernel/system-parts.js +98 -0
- package/esm/src/kernel/tools/activity-label.d.ts +22 -0
- package/esm/src/kernel/tools/activity-label.js +435 -0
- package/esm/src/kernel/tools/agent.d.ts +66 -0
- package/esm/src/kernel/tools/agent.js +212 -0
- package/esm/src/kernel/tools/coordinate.d.ts +4 -0
- package/esm/src/kernel/tools/coordinate.js +165 -0
- package/esm/src/kernel/tools/events.d.ts +66 -0
- package/esm/src/kernel/tools/events.js +184 -0
- package/esm/src/kernel/tools/execute.d.ts +100 -0
- package/esm/src/kernel/tools/execute.js +1173 -0
- package/esm/src/kernel/tools/gate-answer.d.ts +60 -0
- package/esm/src/kernel/tools/gate-answer.js +65 -0
- package/esm/src/kernel/tools/handler-events.d.ts +45 -0
- package/esm/src/kernel/tools/handler-events.js +106 -0
- package/esm/src/kernel/tools/harness.d.ts +17 -0
- package/esm/src/kernel/tools/harness.js +43 -0
- package/esm/src/kernel/tools/http-limit.d.ts +27 -0
- package/esm/src/kernel/tools/http-limit.js +85 -0
- package/esm/src/kernel/tools/invoke.d.ts +32 -0
- package/esm/src/kernel/tools/invoke.js +282 -0
- package/esm/src/kernel/tools/mcp-sessions.d.ts +23 -0
- package/esm/src/kernel/tools/mcp-sessions.js +69 -0
- package/esm/src/kernel/tools/mod.d.ts +10 -0
- package/esm/src/kernel/tools/mod.js +7 -0
- package/esm/src/kernel/tools/model-text.d.ts +16 -0
- package/esm/src/kernel/tools/model-text.js +31 -0
- package/esm/src/kernel/tools/operation.d.ts +76 -0
- package/esm/src/kernel/tools/operation.js +100 -0
- package/esm/src/kernel/tools/page-answer.d.ts +8 -0
- package/esm/src/kernel/tools/page-answer.js +19 -0
- package/esm/src/kernel/tools/permission.d.ts +15 -0
- package/esm/src/kernel/tools/permission.js +38 -0
- package/esm/src/kernel/tools/project.d.ts +11 -0
- package/esm/src/kernel/tools/project.js +55 -0
- package/esm/src/kernel/tools/registry.d.ts +27 -0
- package/esm/src/kernel/tools/registry.js +143 -0
- package/esm/src/kernel/tools/remote.d.ts +144 -0
- package/esm/src/kernel/tools/remote.js +1125 -0
- package/esm/src/kernel/tools/resolve.d.ts +31 -0
- package/esm/src/kernel/tools/resolve.js +267 -0
- package/esm/src/kernel/tools/run.d.ts +28 -0
- package/esm/src/kernel/tools/run.js +86 -0
- package/esm/src/kernel/tools/schema.d.ts +10 -0
- package/esm/src/kernel/tools/schema.js +95 -0
- package/esm/src/kernel/tools/signed-in-fetch.d.ts +19 -0
- package/esm/src/kernel/tools/signed-in-fetch.js +45 -0
- package/esm/src/kernel/tools/stage-run.d.ts +116 -0
- package/esm/src/kernel/tools/stage-run.js +198 -0
- package/esm/src/kernel/tools/types.d.ts +497 -0
- package/esm/src/kernel/tools/types.js +1 -0
- package/esm/src/kernel/tools/unchecked-output.d.ts +14 -0
- package/esm/src/kernel/tools/unchecked-output.js +18 -0
- package/esm/src/kernel/turn-events.d.ts +776 -0
- package/esm/src/kernel/turn-events.js +543 -0
- package/esm/src/kernel/types.d.ts +1025 -0
- package/esm/src/kernel/types.js +1 -0
- package/esm/src/kernel/util/base64.d.ts +4 -0
- package/esm/src/kernel/util/base64.js +15 -0
- package/esm/src/kernel/util/exact-type.d.ts +31 -0
- package/esm/src/kernel/util/exact-type.js +1 -0
- package/esm/src/kernel/util/find-last.d.ts +3 -0
- package/esm/src/kernel/util/find-last.js +9 -0
- package/esm/src/kernel/util/mime.d.ts +2 -0
- package/esm/src/kernel/util/mime.js +4 -0
- package/esm/src/kernel/util/partial-json.d.ts +23 -0
- package/esm/src/kernel/util/partial-json.js +128 -0
- package/esm/src/kernel/util/record.d.ts +2 -0
- package/esm/src/kernel/util/record.js +4 -0
- package/esm/src/observability/destinations.d.ts +14 -0
- package/esm/src/observability/destinations.js +43 -0
- package/esm/src/observability/jsonl.d.ts +18 -0
- package/esm/src/observability/jsonl.js +110 -0
- package/esm/src/observability/mod.d.ts +22 -0
- package/esm/src/observability/mod.js +16 -0
- package/esm/src/observability/openinference.d.ts +11 -0
- package/esm/src/observability/openinference.js +205 -0
- package/esm/src/observability/otlp.d.ts +71 -0
- package/esm/src/observability/otlp.js +98 -0
- package/esm/src/observability/phoenix.d.ts +30 -0
- package/esm/src/observability/phoenix.js +71 -0
- package/esm/src/observability/policy.d.ts +17 -0
- package/esm/src/observability/policy.js +73 -0
- package/esm/src/observability/resolve-policy.d.ts +8 -0
- package/esm/src/observability/resolve-policy.js +64 -0
- package/esm/src/observability/spans.d.ts +22 -0
- package/esm/src/observability/spans.js +72 -0
- package/esm/src/observability/trace-catalog.d.ts +128 -0
- package/esm/src/observability/trace-catalog.js +906 -0
- package/esm/src/observability/trace-record.d.ts +23 -0
- package/esm/src/observability/trace-record.js +228 -0
- package/esm/src/observability/trace-schema.d.ts +57 -0
- package/esm/src/observability/trace-schema.js +59 -0
- package/esm/src/observability/trace-sink.d.ts +14 -0
- package/esm/src/observability/trace-sink.js +3 -0
- package/esm/src/observability/trace-span.d.ts +98 -0
- package/esm/src/observability/trace-span.js +201 -0
- package/esm/src/observability/trace.d.ts +13 -0
- package/esm/src/observability/trace.js +37 -0
- package/esm/src/observability/types.d.ts +109 -0
- package/esm/src/observability/types.js +3 -0
- package/esm/src/presets/google/speech-voices.d.ts +9 -0
- package/esm/src/presets/google/speech-voices.js +38 -0
- package/esm/src/presets/google-limits.d.ts +13 -0
- package/esm/src/presets/google-limits.js +18 -0
- package/esm/src/presets/google.d.ts +119 -0
- package/esm/src/presets/google.js +197 -0
- package/esm/src/presets/local.d.ts +26 -0
- package/esm/src/presets/local.js +30 -0
- package/esm/src/presets/mod.d.ts +11 -0
- package/esm/src/presets/mod.js +9 -0
- package/esm/src/presets/openrouter.d.ts +26 -0
- package/esm/src/presets/openrouter.js +31 -0
- package/esm/src/providers/embedding-limits.d.ts +7 -0
- package/esm/src/providers/embedding-limits.js +12 -0
- package/esm/src/providers/gemini/embedding-protocol.d.ts +8 -0
- package/esm/src/providers/gemini/embedding-protocol.js +125 -0
- package/esm/src/providers/gemini/interactions-protocol.d.ts +8 -0
- package/esm/src/providers/gemini/interactions-protocol.js +105 -0
- package/esm/src/providers/gemini/live-protocol.d.ts +3 -0
- package/esm/src/providers/gemini/live-protocol.js +191 -0
- package/esm/src/providers/gemini/prices.d.ts +3 -0
- package/esm/src/providers/gemini/prices.js +63 -0
- package/esm/src/providers/gemini/provider.d.ts +7 -0
- package/esm/src/providers/gemini/provider.js +39 -0
- package/esm/src/providers/google/api-error.d.ts +8 -0
- package/esm/src/providers/google/api-error.js +123 -0
- package/esm/src/providers/google/builtins.d.ts +14 -0
- package/esm/src/providers/google/builtins.js +57 -0
- package/esm/src/providers/google/grounding.d.ts +5 -0
- package/esm/src/providers/google/grounding.js +226 -0
- package/esm/src/providers/google/interactions/framing.d.ts +27 -0
- package/esm/src/providers/google/interactions/framing.js +304 -0
- package/esm/src/providers/google/interactions/steps.d.ts +12 -0
- package/esm/src/providers/google/interactions/steps.js +200 -0
- package/esm/src/providers/google/interactions/stream.d.ts +23 -0
- package/esm/src/providers/google/interactions/stream.js +230 -0
- package/esm/src/providers/google/live/framing.d.ts +61 -0
- package/esm/src/providers/google/live/framing.js +597 -0
- package/esm/src/providers/google/live/stream.d.ts +13 -0
- package/esm/src/providers/google/live/stream.js +57 -0
- package/esm/src/providers/google/thinking.d.ts +3 -0
- package/esm/src/providers/google/thinking.js +8 -0
- package/esm/src/providers/google/urls.d.ts +4 -0
- package/esm/src/providers/google/urls.js +4 -0
- package/esm/src/providers/google/usage.d.ts +7 -0
- package/esm/src/providers/google/usage.js +49 -0
- package/esm/src/providers/live.d.ts +6 -0
- package/esm/src/providers/live.js +6 -0
- package/esm/src/providers/local/embedding-protocol.d.ts +7 -0
- package/esm/src/providers/local/embedding-protocol.js +60 -0
- package/esm/src/providers/local/provider.d.ts +7 -0
- package/esm/src/providers/local/provider.js +28 -0
- package/esm/src/providers/mod.d.ts +32 -0
- package/esm/src/providers/mod.js +23 -0
- package/esm/src/providers/open-ai/protocol.d.ts +3 -0
- package/esm/src/providers/open-ai/protocol.js +189 -0
- package/esm/src/providers/openrouter/embedding-protocol.d.ts +6 -0
- package/esm/src/providers/openrouter/embedding-protocol.js +86 -0
- package/esm/src/providers/openrouter/image.d.ts +15 -0
- package/esm/src/providers/openrouter/image.js +34 -0
- package/esm/src/providers/openrouter/images-protocol.d.ts +3 -0
- package/esm/src/providers/openrouter/images-protocol.js +82 -0
- package/esm/src/providers/openrouter/openai/compat.d.ts +19 -0
- package/esm/src/providers/openrouter/openai/compat.js +162 -0
- package/esm/src/providers/openrouter/openai/image-payload.d.ts +9 -0
- package/esm/src/providers/openrouter/openai/image-payload.js +115 -0
- package/esm/src/providers/openrouter/openai/reasoning-state.d.ts +2 -0
- package/esm/src/providers/openrouter/openai/reasoning-state.js +31 -0
- package/esm/src/providers/openrouter/openai/usage.d.ts +8 -0
- package/esm/src/providers/openrouter/openai/usage.js +56 -0
- package/esm/src/providers/openrouter/protocol.d.ts +8 -0
- package/esm/src/providers/openrouter/protocol.js +171 -0
- package/esm/src/providers/openrouter/provider.d.ts +10 -0
- package/esm/src/providers/openrouter/provider.js +50 -0
- package/esm/src/providers/shared/carried-tool-files.d.ts +7 -0
- package/esm/src/providers/shared/carried-tool-files.js +43 -0
- package/esm/src/providers/shared/pcm.d.ts +14 -0
- package/esm/src/providers/shared/pcm.js +78 -0
- package/esm/src/providers/shared/protocol-events.d.ts +8 -0
- package/esm/src/providers/shared/protocol-events.js +20 -0
- package/esm/src/providers/shared/response-identity.d.ts +11 -0
- package/esm/src/providers/shared/response-identity.js +12 -0
- package/esm/src/providers/shared/retry.d.ts +17 -0
- package/esm/src/providers/shared/retry.js +90 -0
- package/esm/src/providers/shared/sse.d.ts +6 -0
- package/esm/src/providers/shared/sse.js +93 -0
- package/esm/src/providers/shared/structured-output.d.ts +4 -0
- package/esm/src/providers/shared/structured-output.js +11 -0
- package/esm/src/providers/shared/tool-args.d.ts +24 -0
- package/esm/src/providers/shared/tool-args.js +88 -0
- package/esm/src/providers/shared/tool-draft.d.ts +16 -0
- package/esm/src/providers/shared/tool-draft.js +14 -0
- package/esm/src/providers/shared/upstream-tap.d.ts +8 -0
- package/esm/src/providers/shared/upstream-tap.js +85 -0
- package/esm/src/providers/shared/upstream-tape.d.ts +6 -0
- package/esm/src/providers/shared/upstream-tape.js +88 -0
- package/esm/src/providers/system-one/protocol.d.ts +8 -0
- package/esm/src/providers/system-one/protocol.js +93 -0
- package/esm/src/providers/types.d.ts +51 -0
- package/esm/src/providers/types.js +2 -0
- package/esm/src/providers/typesafe/provider.d.ts +7 -0
- package/esm/src/providers/typesafe/provider.js +24 -0
- package/esm/src/surface/formats.d.ts +46 -0
- package/esm/src/surface/formats.js +178 -0
- package/esm/src/surface/mod.d.ts +16 -0
- package/esm/src/surface/mod.js +12 -0
- package/esm/src/surface/runtime.d.ts +44 -0
- package/esm/src/surface/runtime.js +441 -0
- package/esm/src/surface/tools.d.ts +9 -0
- package/esm/src/surface/tools.js +62 -0
- package/esm/src/surface/types.d.ts +110 -0
- package/esm/src/surface/types.js +4 -0
- package/package.json +100 -4
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { canaryOpeningFrom, createCanaryScanner, promptLeakCarry, RELEASED_LOOKBACK, } from './canary.js';
|
|
2
|
+
import { detectReads, scopeOf } from './detect-at.js';
|
|
3
|
+
import { createDetectStream } from './detect-stream.js';
|
|
4
|
+
import { promptEchoHits } from './egress.js';
|
|
5
|
+
import { loadEgressAutomata } from './egress-stream.js';
|
|
6
|
+
import { CANARY_HIT } from './hits.js';
|
|
7
|
+
import { promptEchoHoldFrom, promptEchoScanFrom } from './prompt-echo.js';
|
|
8
|
+
/** Call `flush` when the stream ends to release the held tail. */
|
|
9
|
+
async function createProgressiveYieldGate(options) {
|
|
10
|
+
if (options.detect)
|
|
11
|
+
await loadEgressAutomata();
|
|
12
|
+
return progressiveYieldGate(options);
|
|
13
|
+
}
|
|
14
|
+
/** `createProgressiveYieldGate`, once the automata are loaded: a Live cycle opens its next gate mid-stream. */
|
|
15
|
+
function progressiveYieldGate(options) {
|
|
16
|
+
const { context } = options;
|
|
17
|
+
const reads = options.detect;
|
|
18
|
+
const detecting = reads
|
|
19
|
+
? createDetectStream(reads.boundary, reads.matrix, reads.scope)
|
|
20
|
+
: undefined;
|
|
21
|
+
/** What a match of one of ours does at this gate's boundary. A gate given no matrix stops on it. */
|
|
22
|
+
const ours = (detector) => reads ? reads.matrix[detector][reads.boundary] : 'block';
|
|
23
|
+
const canaryAction = ours('canary_leak');
|
|
24
|
+
const promptAction = ours('prompt_leak');
|
|
25
|
+
/** The canary a reply must not repeat: none when it was given (`canaryGiven`), or not read here. */
|
|
26
|
+
const token = context.canaryGiven || canaryAction === 'ignore' ? undefined : context.canary;
|
|
27
|
+
/** The private system instruction a reply must not repeat: none when not read here. */
|
|
28
|
+
const privateSystem = promptAction === 'ignore' ? undefined : context.privateSystem;
|
|
29
|
+
const guarded = token !== undefined || privateSystem !== undefined;
|
|
30
|
+
const carry = guarded ? (options.carry ?? '') : '';
|
|
31
|
+
/** The leaks set to `flag` found since the last release, and the rules already reported. */
|
|
32
|
+
let noted = [];
|
|
33
|
+
const reported = new Set();
|
|
34
|
+
let accumulated = '';
|
|
35
|
+
let emitted = 0;
|
|
36
|
+
/** The window from `emitted` on. Each piece of the reply is kept apart, so no step rereads the whole. */
|
|
37
|
+
let held = '';
|
|
38
|
+
/** The carry and the released window, as far back as the canary hold rereads. */
|
|
39
|
+
let released = carry.slice(-RELEASED_LOOKBACK);
|
|
40
|
+
/** The carry and window from where the next prompt echo scan may reach back to. */
|
|
41
|
+
let echoed = carry;
|
|
42
|
+
/** Where `echoed` starts in the carry and window. */
|
|
43
|
+
let echoedFrom = 0;
|
|
44
|
+
/**
|
|
45
|
+
* The carry and window from `openingBase` on, for the canary hold. No
|
|
46
|
+
* opening of a leak starts before `openingFrom`: a point further back than
|
|
47
|
+
* `RELEASED_LOOKBACK` that does not open one by now never will. So each
|
|
48
|
+
* step reads from there, not the whole held text.
|
|
49
|
+
*/
|
|
50
|
+
let opening = carry;
|
|
51
|
+
let openingBase = 0;
|
|
52
|
+
let openingFrom = 0;
|
|
53
|
+
/** Reads the carry, then the window as it grows. */
|
|
54
|
+
const scanner = token ? createCanaryScanner(token) : undefined;
|
|
55
|
+
scanner?.push(carry);
|
|
56
|
+
/**
|
|
57
|
+
* The leaks of what is ours (canary, prompt echo) in the carry and this
|
|
58
|
+
* window that stop the reply. One set to `flag` is noted for the next
|
|
59
|
+
* release instead, once. The canary scan reads each character once
|
|
60
|
+
* (`createCanaryScanner`) and the echo check rereads only its own short
|
|
61
|
+
* lookback (`promptEchoScanFrom`), so a long reply costs time in proportion
|
|
62
|
+
* to its length, not its square.
|
|
63
|
+
*/
|
|
64
|
+
function leakStops(fresh) {
|
|
65
|
+
const found = [];
|
|
66
|
+
if (scanner?.push(fresh))
|
|
67
|
+
found.push([canaryAction, CANARY_HIT]);
|
|
68
|
+
if (privateSystem) {
|
|
69
|
+
const scanned = echoed.length;
|
|
70
|
+
echoed += fresh;
|
|
71
|
+
const from = promptEchoScanFrom(echoed, scanned);
|
|
72
|
+
echoed = echoed.slice(from);
|
|
73
|
+
echoedFrom += from;
|
|
74
|
+
const [hit] = promptEchoHits(echoed, privateSystem, context.canary);
|
|
75
|
+
if (hit)
|
|
76
|
+
found.push([promptAction, hit]);
|
|
77
|
+
}
|
|
78
|
+
for (const [action, hit] of found) {
|
|
79
|
+
if (action !== 'flag' || reported.has(hit.rule))
|
|
80
|
+
continue;
|
|
81
|
+
reported.add(hit.rule);
|
|
82
|
+
noted.push(hit);
|
|
83
|
+
}
|
|
84
|
+
return found.filter(([action]) => action !== 'flag').map(([, hit]) => hit);
|
|
85
|
+
}
|
|
86
|
+
/** What stops the reply at this step: a leak of ours, read at the gate's boundary. */
|
|
87
|
+
function scan(fragment) {
|
|
88
|
+
const leaks = guarded ? leakStops(fragment ?? '') : [];
|
|
89
|
+
if (fragment)
|
|
90
|
+
detecting?.push(fragment);
|
|
91
|
+
if (leaks.length === 0)
|
|
92
|
+
return null;
|
|
93
|
+
return { hits: leaks, ...(reads ? { boundary: reads.boundary } : {}) };
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Where the leak checks hold from: a canary opening, or words a prompt echo
|
|
97
|
+
* could grow from. A leak set to `flag` holds nothing: it is shown.
|
|
98
|
+
*/
|
|
99
|
+
function leakHoldFrom() {
|
|
100
|
+
const canary = token && canaryAction !== 'flag' ? canaryFrom(token) : held.length;
|
|
101
|
+
const echo = privateSystem && promptAction !== 'flag'
|
|
102
|
+
? echoHoldFrom(privateSystem, context.canary)
|
|
103
|
+
: held.length;
|
|
104
|
+
return emitted + Math.min(canary, echo);
|
|
105
|
+
}
|
|
106
|
+
/** `result` with the leaks noted since the last release reported in it. */
|
|
107
|
+
function withNoted(result) {
|
|
108
|
+
if (noted.length === 0)
|
|
109
|
+
return result;
|
|
110
|
+
const hits = [...noted, ...(result.found?.hits ?? [])];
|
|
111
|
+
noted = [];
|
|
112
|
+
return { ...result, found: { action: result.found?.action ?? 'flag', hits } };
|
|
113
|
+
}
|
|
114
|
+
/** `canaryHoldFrom` on the held text, read from where an opening could start. */
|
|
115
|
+
function canaryFrom(canary) {
|
|
116
|
+
const shownTo = carry.length + emitted;
|
|
117
|
+
const from = Math.max(shownTo, openingFrom);
|
|
118
|
+
const lead = Math.max(openingBase, from - RELEASED_LOOKBACK);
|
|
119
|
+
let at = lead + canaryOpeningFrom(opening.slice(lead - openingBase), canary);
|
|
120
|
+
if (at < from && from > shownTo) {
|
|
121
|
+
// why: An opening the bound rules out: read the held text whole, and from there on.
|
|
122
|
+
opening = released + held;
|
|
123
|
+
openingBase = shownTo - released.length;
|
|
124
|
+
at = openingBase + canaryOpeningFrom(opening, canary);
|
|
125
|
+
}
|
|
126
|
+
openingFrom = Math.min(at, carry.length + accumulated.length - RELEASED_LOOKBACK);
|
|
127
|
+
const base = Math.max(openingBase, Math.max(shownTo, openingFrom) - RELEASED_LOOKBACK);
|
|
128
|
+
opening = opening.slice(base - openingBase);
|
|
129
|
+
openingBase = base;
|
|
130
|
+
return Math.max(0, at - shownTo);
|
|
131
|
+
}
|
|
132
|
+
/** `promptEchoHoldFrom` on the held text, read from its last few words. */
|
|
133
|
+
function echoHoldFrom(privateSystem, canary) {
|
|
134
|
+
// why: Until this window releases anything, its opening may continue the carry.
|
|
135
|
+
const lead = emitted === 0 ? carry : '';
|
|
136
|
+
const leadFrom = carry.length + emitted - lead.length;
|
|
137
|
+
const [text, from] = echoedFrom >= leadFrom ? [echoed, echoedFrom] : [lead + held, leadFrom];
|
|
138
|
+
return Math.max(0, from + promptEchoHoldFrom(text, privateSystem, canary) - carry.length - emitted);
|
|
139
|
+
}
|
|
140
|
+
function release(fragment) {
|
|
141
|
+
const stop = scan(fragment);
|
|
142
|
+
if (stop) {
|
|
143
|
+
return { blocked: true, ...stop };
|
|
144
|
+
}
|
|
145
|
+
const ended = fragment === undefined;
|
|
146
|
+
const end = ended
|
|
147
|
+
? accumulated.length
|
|
148
|
+
: Math.min(leakHoldFrom(), detecting?.holdFrom() ?? accumulated.length);
|
|
149
|
+
const length = Math.max(0, end - emitted);
|
|
150
|
+
if (!(reads && detecting)) {
|
|
151
|
+
return withNoted({ blocked: false, emit: take(length) });
|
|
152
|
+
}
|
|
153
|
+
const read = detecting.take(emitted, emitted + length, ended);
|
|
154
|
+
if (read.action === 'block' || (read.action === 'redact' && !reads.rewrite)) {
|
|
155
|
+
return { blocked: true, hits: read.hits, boundary: reads.boundary };
|
|
156
|
+
}
|
|
157
|
+
take(read.taken);
|
|
158
|
+
return withNoted({
|
|
159
|
+
blocked: false,
|
|
160
|
+
emit: read.text ?? '',
|
|
161
|
+
...(read.action === 'allow' ? {} : { found: { action: read.action, hits: read.hits } }),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/** Release the first `length` characters held, as written. */
|
|
165
|
+
function take(length) {
|
|
166
|
+
const emit = held.slice(0, length);
|
|
167
|
+
held = held.slice(length);
|
|
168
|
+
emitted += emit.length;
|
|
169
|
+
if (guarded)
|
|
170
|
+
released = (released + emit).slice(-RELEASED_LOOKBACK);
|
|
171
|
+
return emit;
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
process(fragment) {
|
|
175
|
+
if (!fragment) {
|
|
176
|
+
return { blocked: false, emit: '' };
|
|
177
|
+
}
|
|
178
|
+
accumulated += fragment;
|
|
179
|
+
held += fragment;
|
|
180
|
+
if (guarded)
|
|
181
|
+
opening += fragment;
|
|
182
|
+
return release(fragment);
|
|
183
|
+
},
|
|
184
|
+
flush: () => release(),
|
|
185
|
+
accumulated: () => accumulated,
|
|
186
|
+
unreleased: () => held,
|
|
187
|
+
drainUnreleased: () => take(held.length),
|
|
188
|
+
carryOut: () => (guarded ? promptLeakCarry(carry + accumulated, token, privateSystem) : ''),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Whether a reply read at `boundaries` gets a verdict once it has ended: a
|
|
193
|
+
* detector reads one of them. A gate that stops such a reply withholds it for
|
|
194
|
+
* that verdict.
|
|
195
|
+
*/
|
|
196
|
+
function replyIsJudged(policy, boundaries, scope) {
|
|
197
|
+
return detectReads(boundaries, policy.detect, scope);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Shared constructor for runTurn + Live: a gate when a detector reads
|
|
201
|
+
* `boundary`. `context.canary` is set only while `canary_leak` is above
|
|
202
|
+
* `ignore` somewhere, and `context.privateSystem` while `prompt_leak` is.
|
|
203
|
+
*/
|
|
204
|
+
async function createOutboundProgressiveGate(policy, context, boundary, carry) {
|
|
205
|
+
if (!replyIsJudged(policy, [boundary], context))
|
|
206
|
+
return null;
|
|
207
|
+
await loadEgressAutomata();
|
|
208
|
+
return outboundProgressiveGate(policy, context, boundary, carry);
|
|
209
|
+
}
|
|
210
|
+
/** `createOutboundProgressiveGate`, once the automata are loaded. */
|
|
211
|
+
function outboundProgressiveGate(policy, context, boundary, carry) {
|
|
212
|
+
if (!replyIsJudged(policy, [boundary], context)) {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
return progressiveYieldGate({
|
|
216
|
+
context,
|
|
217
|
+
detect: {
|
|
218
|
+
matrix: policy.detect,
|
|
219
|
+
boundary,
|
|
220
|
+
rewrite: boundary === 'reply',
|
|
221
|
+
scope: scopeOf(policy, context),
|
|
222
|
+
},
|
|
223
|
+
...(carry ? { carry } : {}),
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* A gate for a draft read at `boundary`, where the whole it previews is read before the host sees
|
|
228
|
+
* it: a tool call the model is still writing, a tool's output as the tool writes it, or a
|
|
229
|
+
* structured reply's JSON as the model writes it. It never
|
|
230
|
+
* rewrites: a match the whole's check would replace or stop stops the draft instead, because the
|
|
231
|
+
* host gets the whole only as that check leaves it. `scope` is what that check reads against;
|
|
232
|
+
* left out, the turn's (`scopeOf`).
|
|
233
|
+
*/
|
|
234
|
+
async function createDraftGate(policy, context, boundary, scope) {
|
|
235
|
+
if (!replyIsJudged(policy, [boundary], scope ?? context))
|
|
236
|
+
return null;
|
|
237
|
+
await loadEgressAutomata();
|
|
238
|
+
return progressiveYieldGate({
|
|
239
|
+
context,
|
|
240
|
+
detect: {
|
|
241
|
+
matrix: policy.detect,
|
|
242
|
+
boundary,
|
|
243
|
+
rewrite: false,
|
|
244
|
+
scope: scope ?? scopeOf(policy, context),
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* One stream of drafts read through one draft gate, opened on the first draft. A match stops
|
|
250
|
+
* the rest of the stream; with no gate (nothing is judged there), every draft passes as is.
|
|
251
|
+
*/
|
|
252
|
+
class DraftReader {
|
|
253
|
+
open;
|
|
254
|
+
gate;
|
|
255
|
+
constructor(open) {
|
|
256
|
+
this.open = open;
|
|
257
|
+
}
|
|
258
|
+
/** What of `text` may be shown now: empty while the gate holds it, or once a match stopped the stream. */
|
|
259
|
+
async read(text) {
|
|
260
|
+
if (this.gate === undefined)
|
|
261
|
+
this.gate = await this.open();
|
|
262
|
+
if (this.gate === 'stopped')
|
|
263
|
+
return '';
|
|
264
|
+
if (!this.gate)
|
|
265
|
+
return text;
|
|
266
|
+
const result = this.gate.process(text);
|
|
267
|
+
if (result.blocked) {
|
|
268
|
+
this.gate = 'stopped';
|
|
269
|
+
return '';
|
|
270
|
+
}
|
|
271
|
+
return result.emit;
|
|
272
|
+
}
|
|
273
|
+
/** The tail the gate still holds, once the stream has ended. */
|
|
274
|
+
end() {
|
|
275
|
+
if (!this.gate || this.gate === 'stopped')
|
|
276
|
+
return '';
|
|
277
|
+
const result = this.gate.flush();
|
|
278
|
+
return result.blocked ? '' : result.emit;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
export { createDraftGate, createOutboundProgressiveGate, createProgressiveYieldGate, DraftReader, outboundProgressiveGate, replyIsJudged, };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System-prompt echo — the leak the canary cannot see.
|
|
3
|
+
*
|
|
4
|
+
* The canary proves the token leaked; a reply that restates the system prompt
|
|
5
|
+
* while leaving the token out trips nothing. This check reads the reply for a
|
|
6
|
+
* run of `PROMPT_ECHO_WORDS` consecutive words of one private stretch of the
|
|
7
|
+
* system prompt (`BoundSystem.private`); text the host marked shareable is
|
|
8
|
+
* not read, and no run reaches across it. Words are
|
|
9
|
+
* compared case-folded after Unicode compatibility folding, punctuation and
|
|
10
|
+
* markup between them ignored, and bare numbers skipped, so reformatting a
|
|
11
|
+
* dump as a numbered or bulleted list does not hide it. Nor does encoding it:
|
|
12
|
+
* the prompt is also read backwards and in rot13, and both it and the reply
|
|
13
|
+
* with leetspeak decoded. Where the prompt has
|
|
14
|
+
* the canary, any one word, or none continues a run: a model told to hide the
|
|
15
|
+
* canary echoes the prompt around a stand-in for it. A streamed reply holds
|
|
16
|
+
* the words an echo could still grow from (`promptEchoHoldFrom`), so none of
|
|
17
|
+
* an echo reaches the host.
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
/** Consecutive system-prompt words that make a reply an echo of it. */
|
|
22
|
+
declare const PROMPT_ECHO_WORDS = 12;
|
|
23
|
+
/**
|
|
24
|
+
* Where an echo still being written could start: the first word of the
|
|
25
|
+
* longest run of words ending `text` that the system prompt also has, or the
|
|
26
|
+
* word still being written when that is earlier and could become a prompt
|
|
27
|
+
* word. Any echo that completes later starts there or after.
|
|
28
|
+
*/
|
|
29
|
+
declare function promptEchoHoldFrom(text: string, stretches: readonly string[], canary?: string): number;
|
|
30
|
+
/** Offsets `[start, end)` of `text` that repeat a private stretch, ordered by start. */
|
|
31
|
+
declare function promptEchoRanges(text: string, stretches: readonly string[], canary?: string): Array<[number, number]>;
|
|
32
|
+
/** Whether `text` repeats `PROMPT_ECHO_WORDS` consecutive words of a private stretch. */
|
|
33
|
+
declare function scanTextForPromptEcho(text: string, stretches: readonly string[], canary?: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Where a scan of `text` must start when everything before `from` was
|
|
36
|
+
* already scanned clean: at the word an echo run ending past `from` could
|
|
37
|
+
* start in.
|
|
38
|
+
*/
|
|
39
|
+
declare function promptEchoScanFrom(text: string, from: number): number;
|
|
40
|
+
export { PROMPT_ECHO_WORDS, promptEchoHoldFrom, promptEchoRanges, promptEchoScanFrom, scanTextForPromptEcho, };
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System-prompt echo — the leak the canary cannot see.
|
|
3
|
+
*
|
|
4
|
+
* The canary proves the token leaked; a reply that restates the system prompt
|
|
5
|
+
* while leaving the token out trips nothing. This check reads the reply for a
|
|
6
|
+
* run of `PROMPT_ECHO_WORDS` consecutive words of one private stretch of the
|
|
7
|
+
* system prompt (`BoundSystem.private`); text the host marked shareable is
|
|
8
|
+
* not read, and no run reaches across it. Words are
|
|
9
|
+
* compared case-folded after Unicode compatibility folding, punctuation and
|
|
10
|
+
* markup between them ignored, and bare numbers skipped, so reformatting a
|
|
11
|
+
* dump as a numbered or bulleted list does not hide it. Nor does encoding it:
|
|
12
|
+
* the prompt is also read backwards and in rot13, and both it and the reply
|
|
13
|
+
* with leetspeak decoded. Where the prompt has
|
|
14
|
+
* the canary, any one word, or none continues a run: a model told to hide the
|
|
15
|
+
* canary echoes the prompt around a stand-in for it. A streamed reply holds
|
|
16
|
+
* the words an echo could still grow from (`promptEchoHoldFrom`), so none of
|
|
17
|
+
* an echo reaches the host.
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
import { LEET_MAP, tryRot13 } from './injection.js';
|
|
22
|
+
/** Consecutive system-prompt words that make a reply an echo of it. */
|
|
23
|
+
const PROMPT_ECHO_WORDS = 12;
|
|
24
|
+
/** Words a scan rereads before new text: an echo run ending in it starts no earlier. */
|
|
25
|
+
const ECHO_LOOKBACK_WORDS = PROMPT_ECHO_WORDS;
|
|
26
|
+
const WORD = /[\p{L}\p{N}]+/gu;
|
|
27
|
+
const WORD_CHAR = /[\p{L}\p{N}]/u;
|
|
28
|
+
const NUMBER = /^\p{N}+$/u;
|
|
29
|
+
const ASCII = /^\p{ASCII}*$/u;
|
|
30
|
+
/** Most letters compatibility folding joins into one (a Hangul syllable from its jamo). */
|
|
31
|
+
const MAX_FOLD = 3;
|
|
32
|
+
/** The words a text is compared by, with the offsets each came from. */
|
|
33
|
+
function echoWords(text) {
|
|
34
|
+
const words = [];
|
|
35
|
+
for (const match of text.matchAll(WORD)) {
|
|
36
|
+
const word = match[0].normalize('NFKC').toLowerCase();
|
|
37
|
+
if (!NUMBER.test(word)) {
|
|
38
|
+
words.push({ word, at: match.index, to: match.index + match[0].length });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return words;
|
|
42
|
+
}
|
|
43
|
+
/** Where the canary stood in the prompt's words: any one word or none matches it. */
|
|
44
|
+
const SLOT = '\u0000';
|
|
45
|
+
/**
|
|
46
|
+
* The prompt as a reply can encode it: written backwards, by code point, in
|
|
47
|
+
* rot13, or as the decoded leetspeak reply reads it.
|
|
48
|
+
*/
|
|
49
|
+
const PROMPT_VIEWS = [
|
|
50
|
+
(text) => text,
|
|
51
|
+
(text) => [...text].reverse().join(''),
|
|
52
|
+
tryRot13,
|
|
53
|
+
decodeLeet,
|
|
54
|
+
];
|
|
55
|
+
/**
|
|
56
|
+
* The private stretches' words as a run can repeat them, in each of
|
|
57
|
+
* `PROMPT_VIEWS`: as written, with the canary left out, and with the canary
|
|
58
|
+
* as `SLOT`.
|
|
59
|
+
*/
|
|
60
|
+
function promptReadings(stretches, canary) {
|
|
61
|
+
const readings = { plain: [], slotted: [] };
|
|
62
|
+
for (const view of PROMPT_VIEWS) {
|
|
63
|
+
const read = viewReadings(stretches.map(view), canary === undefined ? undefined : view(canary));
|
|
64
|
+
readings.plain.push(...read.plain);
|
|
65
|
+
readings.slotted.push(...read.slotted);
|
|
66
|
+
}
|
|
67
|
+
return readings;
|
|
68
|
+
}
|
|
69
|
+
function viewReadings(stretches, canary) {
|
|
70
|
+
const token = canary ? echoWords(canary).map((entry) => entry.word) : [];
|
|
71
|
+
const readings = { plain: [], slotted: [] };
|
|
72
|
+
for (const stretch of stretches) {
|
|
73
|
+
const words = echoWords(stretch).map((entry) => entry.word);
|
|
74
|
+
readings.plain.push(words);
|
|
75
|
+
if (token.length === 0)
|
|
76
|
+
continue;
|
|
77
|
+
const slotted = [];
|
|
78
|
+
for (let at = 0; at < words.length;) {
|
|
79
|
+
if (token.every((word, k) => words[at + k] === word)) {
|
|
80
|
+
slotted.push(SLOT);
|
|
81
|
+
at += token.length;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
slotted.push(words[at]);
|
|
85
|
+
at++;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (!slotted.includes(SLOT))
|
|
89
|
+
continue;
|
|
90
|
+
readings.plain.push(slotted.filter((word) => word !== SLOT));
|
|
91
|
+
readings.slotted.push(slotted);
|
|
92
|
+
}
|
|
93
|
+
return readings;
|
|
94
|
+
}
|
|
95
|
+
/** A run with a slot, keyed by where the slot is and the words around it. */
|
|
96
|
+
function slotKey(run, slot) {
|
|
97
|
+
// why: Bare numbers are never words here, so the slot's index leads unambiguously.
|
|
98
|
+
return [slot, ...run.filter((_, k) => k !== slot)].join(' ');
|
|
99
|
+
}
|
|
100
|
+
/** A run may not start on the canary's place unless `leading`: a stand-in for it is not prompt text. */
|
|
101
|
+
function addRuns(set, readings, lengths, leading) {
|
|
102
|
+
for (const words of readings.plain) {
|
|
103
|
+
for (const length of lengths) {
|
|
104
|
+
for (let from = 0; from + length <= words.length; from++) {
|
|
105
|
+
set.plain.add(words.slice(from, from + length).join(' '));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
for (const slotted of readings.slotted) {
|
|
110
|
+
for (const length of lengths) {
|
|
111
|
+
for (let from = 0; from + length <= slotted.length; from++) {
|
|
112
|
+
const run = slotted.slice(from, from + length);
|
|
113
|
+
const slot = run.indexOf(SLOT);
|
|
114
|
+
if (slot === -1 || (slot === 0 && !leading))
|
|
115
|
+
continue;
|
|
116
|
+
set.slotted.add(slotKey(run, slot));
|
|
117
|
+
set.slots.add(slot);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/** Where in `run` the canary's place fell when `set` has it: -1 for nowhere, undefined when not a run. */
|
|
123
|
+
function matchRun(set, run) {
|
|
124
|
+
if (set.plain.has(run.join(' ')))
|
|
125
|
+
return -1;
|
|
126
|
+
for (const slot of set.slots) {
|
|
127
|
+
if (slot < run.length && set.slotted.has(slotKey(run, slot)))
|
|
128
|
+
return slot;
|
|
129
|
+
}
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
function sameStretches(a, b) {
|
|
133
|
+
return a === b || (a.length === b.length && a.every((stretch, k) => stretch === b[k]));
|
|
134
|
+
}
|
|
135
|
+
let gramsCache;
|
|
136
|
+
/** Every run of `PROMPT_ECHO_WORDS` words in a private stretch. */
|
|
137
|
+
function promptGrams(stretches, canary) {
|
|
138
|
+
if (gramsCache &&
|
|
139
|
+
gramsCache.canary === canary &&
|
|
140
|
+
sameStretches(gramsCache.stretches, stretches)) {
|
|
141
|
+
return gramsCache.grams;
|
|
142
|
+
}
|
|
143
|
+
const grams = { plain: new Set(), slotted: new Set(), slots: new Set() };
|
|
144
|
+
addRuns(grams, promptReadings(stretches, canary), [PROMPT_ECHO_WORDS], true);
|
|
145
|
+
gramsCache = { stretches, canary, grams };
|
|
146
|
+
return grams;
|
|
147
|
+
}
|
|
148
|
+
let shapeCache;
|
|
149
|
+
function promptShape(stretches, canary) {
|
|
150
|
+
if (shapeCache &&
|
|
151
|
+
shapeCache.canary === canary &&
|
|
152
|
+
sameStretches(shapeCache.stretches, stretches)) {
|
|
153
|
+
return shapeCache.shape;
|
|
154
|
+
}
|
|
155
|
+
const readings = promptReadings(stretches, canary);
|
|
156
|
+
const shape = {
|
|
157
|
+
runs: { plain: new Set(), slotted: new Set(), slots: new Set() },
|
|
158
|
+
prefixes: new Set(),
|
|
159
|
+
longest: 0,
|
|
160
|
+
};
|
|
161
|
+
for (const word of readings.plain.flat()) {
|
|
162
|
+
shape.longest = Math.max(shape.longest, word.length);
|
|
163
|
+
for (let end = 1; end <= word.length && ASCII.test(word.charAt(end - 1)); end++) {
|
|
164
|
+
shape.prefixes.add(word.slice(0, end));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
addRuns(shape.runs, readings, Array.from({ length: PROMPT_ECHO_WORDS - 1 }, (_, k) => k + 1), false);
|
|
168
|
+
shapeCache = { stretches, canary, shape };
|
|
169
|
+
return shape;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Whether a word still being written could end as a word of the system
|
|
173
|
+
* prompt. ASCII folds letter by letter, so it must start one; other
|
|
174
|
+
* scripts can fold several letters into one (Hangul jamo, up to three), so
|
|
175
|
+
* only a word too long to fold down to any of them is ruled out.
|
|
176
|
+
*/
|
|
177
|
+
function mayBecomePromptWord(partial, shape) {
|
|
178
|
+
if (ASCII.test(partial)) {
|
|
179
|
+
return shape.prefixes.has(partial.toLowerCase());
|
|
180
|
+
}
|
|
181
|
+
return partial.length <= MAX_FOLD * shape.longest;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Where an echo still being written could start: the first word of the
|
|
185
|
+
* longest run of words ending `text` that the system prompt also has, or the
|
|
186
|
+
* word still being written when that is earlier and could become a prompt
|
|
187
|
+
* word. Any echo that completes later starts there or after.
|
|
188
|
+
*/
|
|
189
|
+
function promptEchoHoldFrom(text, stretches, canary) {
|
|
190
|
+
for (let reach = TAIL_REACH;; reach *= 2) {
|
|
191
|
+
const start = decodableFrom(text, text.length - reach);
|
|
192
|
+
const holds = replyViews(text.slice(start)).map((view) => holdFrom(view, stretches, canary));
|
|
193
|
+
if (start === 0 || holds.every(({ tail }) => tail > 0)) {
|
|
194
|
+
return start + Math.min(...holds.map(({ hold }) => hold));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/** The hold in `text`, and where the words it was read from start: at 0, `text` may be too short a tail. */
|
|
199
|
+
function holdFrom(text, stretches, canary) {
|
|
200
|
+
const tail = promptEchoScanFrom(text, text.length);
|
|
201
|
+
return { hold: holdIn(text, tail, stretches, canary), tail };
|
|
202
|
+
}
|
|
203
|
+
function holdIn(text, tail, stretches, canary) {
|
|
204
|
+
const words = echoWords(text.slice(tail));
|
|
205
|
+
let writing = text.length;
|
|
206
|
+
while (writing > 0 && WORD_CHAR.test(text.charAt(writing - 1)))
|
|
207
|
+
writing--;
|
|
208
|
+
const complete = words.filter((entry) => tail + entry.to < text.length || writing === text.length);
|
|
209
|
+
const shape = promptShape(stretches, canary);
|
|
210
|
+
const hold = mayBecomePromptWord(text.slice(writing), shape) ? writing : text.length;
|
|
211
|
+
for (let from = Math.max(0, complete.length - (PROMPT_ECHO_WORDS - 1)); from < complete.length; from++) {
|
|
212
|
+
const run = complete.slice(from).map((entry) => entry.word);
|
|
213
|
+
if (matchRun(shape.runs, run) !== undefined) {
|
|
214
|
+
return Math.min(hold, tail + complete[from].at);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return hold;
|
|
218
|
+
}
|
|
219
|
+
/** A leetspeak letter, or a list number that stays one; `!` only before a word goes on. */
|
|
220
|
+
const LEET = /(?<=^|\n)[ \t]*\p{N}+[.)]|[0-9@]|!(?=[\p{L}\p{N}@])/gu;
|
|
221
|
+
/** How far back a tail is first read from; a tail with too few words in it is doubled. */
|
|
222
|
+
const TAIL_REACH = 512;
|
|
223
|
+
const LIST_NUMBER_CHAR = /[ \t\p{N}]/u;
|
|
224
|
+
const NUMBER_CHAR = /\p{N}/u;
|
|
225
|
+
/**
|
|
226
|
+
* A start at or before `at` from which `text` decodes as it does whole: a
|
|
227
|
+
* list number is one from its line's start, so the start is no later than the
|
|
228
|
+
* character before the blanks and digits leading up to `at`.
|
|
229
|
+
*/
|
|
230
|
+
function decodableFrom(text, at) {
|
|
231
|
+
let start = Math.max(0, at);
|
|
232
|
+
while (start > 0 && LIST_NUMBER_CHAR.test(text.charAt(start - 1)))
|
|
233
|
+
start--;
|
|
234
|
+
return Math.max(0, start - 1);
|
|
235
|
+
}
|
|
236
|
+
/** `text` with its leetspeak decoded, letter for letter, so offsets keep. */
|
|
237
|
+
function decodeLeet(text) {
|
|
238
|
+
return text.replace(LEET, (match) => (match.length === 1 ? (LEET_MAP[match] ?? match) : match));
|
|
239
|
+
}
|
|
240
|
+
/** The reply as written and with its leetspeak decoded. */
|
|
241
|
+
function replyViews(text) {
|
|
242
|
+
const decoded = decodeLeet(text);
|
|
243
|
+
return decoded === text ? [text] : [text, decoded];
|
|
244
|
+
}
|
|
245
|
+
/** Offsets `[start, end)` of `text` that repeat a private stretch, ordered by start. */
|
|
246
|
+
function promptEchoRanges(text, stretches, canary) {
|
|
247
|
+
return replyViews(text)
|
|
248
|
+
.flatMap((view) => echoRanges(view, stretches, canary))
|
|
249
|
+
.sort((a, b) => a[0] - b[0]);
|
|
250
|
+
}
|
|
251
|
+
function echoRanges(text, stretches, canary) {
|
|
252
|
+
const grams = promptGrams(stretches, canary);
|
|
253
|
+
if (!text || grams.plain.size === 0) {
|
|
254
|
+
return [];
|
|
255
|
+
}
|
|
256
|
+
const words = echoWords(text);
|
|
257
|
+
const ranges = [];
|
|
258
|
+
for (let from = 0; from + PROMPT_ECHO_WORDS <= words.length; from++) {
|
|
259
|
+
const run = words.slice(from, from + PROMPT_ECHO_WORDS).map((entry) => entry.word);
|
|
260
|
+
const slot = matchRun(grams, run);
|
|
261
|
+
if (slot === undefined)
|
|
262
|
+
continue;
|
|
263
|
+
// why: A stand-in for the canary at either end is the model's, not the prompt's.
|
|
264
|
+
const first = slot === 0 ? from + 1 : from;
|
|
265
|
+
const last = slot === PROMPT_ECHO_WORDS - 1 ? from + slot - 1 : from + PROMPT_ECHO_WORDS - 1;
|
|
266
|
+
ranges.push([words[first]?.at ?? 0, words[last]?.to ?? 0]);
|
|
267
|
+
}
|
|
268
|
+
return ranges;
|
|
269
|
+
}
|
|
270
|
+
/** Whether `text` repeats `PROMPT_ECHO_WORDS` consecutive words of a private stretch. */
|
|
271
|
+
function scanTextForPromptEcho(text, stretches, canary) {
|
|
272
|
+
return promptEchoRanges(text, stretches, canary).length > 0;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Where a scan of `text` must start when everything before `from` was
|
|
276
|
+
* already scanned clean: at the word an echo run ending past `from` could
|
|
277
|
+
* start in.
|
|
278
|
+
*/
|
|
279
|
+
function promptEchoScanFrom(text, from) {
|
|
280
|
+
const end = Math.min(from, text.length);
|
|
281
|
+
for (let reach = TAIL_REACH;; reach *= 2) {
|
|
282
|
+
const start = decodableFrom(text, end - reach);
|
|
283
|
+
// why: What follows `end` decides how the tail's last characters read: a `!` by the next one, digits by the list number they may be.
|
|
284
|
+
let stop = end;
|
|
285
|
+
while (stop < text.length && NUMBER_CHAR.test(text.charAt(stop)))
|
|
286
|
+
stop++;
|
|
287
|
+
const tail = text.slice(start, stop + 1);
|
|
288
|
+
const at = Math.min(...replyViews(tail).map((view) => scanFrom(view, end - start)));
|
|
289
|
+
if (start === 0 || at > 0)
|
|
290
|
+
return start + at;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function scanFrom(text, from) {
|
|
294
|
+
let at = Math.min(from, text.length);
|
|
295
|
+
for (let counted = 0; counted < ECHO_LOOKBACK_WORDS && at > 0;) {
|
|
296
|
+
while (at > 0 && !WORD_CHAR.test(text.charAt(at - 1)))
|
|
297
|
+
at--;
|
|
298
|
+
const end = at;
|
|
299
|
+
while (at > 0 && WORD_CHAR.test(text.charAt(at - 1)))
|
|
300
|
+
at--;
|
|
301
|
+
if (end > at && !NUMBER.test(text.slice(at, end)))
|
|
302
|
+
counted++;
|
|
303
|
+
}
|
|
304
|
+
return at;
|
|
305
|
+
}
|
|
306
|
+
export { PROMPT_ECHO_WORDS, promptEchoHoldFrom, promptEchoRanges, promptEchoScanFrom, scanTextForPromptEcho, };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Profile } from '../kernel/types.js';
|
|
2
|
+
import { TheoremError } from './theorem-error.js';
|
|
3
|
+
/** What taking a quota slot returned: `ok` (reserved), `busy` (a turn already holds the slot), `quota` (the day's limit is used) or `not_configured` (the profile sets no quota). */
|
|
4
|
+
type QuotaSlotStatus = 'ok' | 'busy' | 'quota' | 'not_configured';
|
|
5
|
+
/** Returns whether a local request lacks the proxy header needed for quota identity. */
|
|
6
|
+
declare function skipQuota(peer: string, req: Request): boolean;
|
|
7
|
+
/** Resolves the client identity, preferring Cloudflare's header for local peers. */
|
|
8
|
+
declare function clientIp(peer: string, req: Request): string;
|
|
9
|
+
/**
|
|
10
|
+
* Reserves one profile-and-client daily quota slot. The reservation stays busy
|
|
11
|
+
* until `releaseSlot` is called, preventing concurrent turns from overspending.
|
|
12
|
+
*/
|
|
13
|
+
declare function takeSlot(profile: Profile, ip: string, now: number): QuotaSlotStatus;
|
|
14
|
+
/** Releases an active quota reservation without decrementing its daily count. */
|
|
15
|
+
declare function releaseSlot(profile: Profile, ip: string): void;
|
|
16
|
+
/** `undefined` when the profile has no quota configured. */
|
|
17
|
+
declare function quotaExhausted(profile: Profile): TheoremError | undefined;
|
|
18
|
+
/** Clears all process-local quota counters; intended for tests or host resets. */
|
|
19
|
+
declare function resetSlots(): void;
|
|
20
|
+
export type { QuotaSlotStatus };
|
|
21
|
+
export { clientIp, quotaExhausted, releaseSlot, resetSlots, skipQuota, takeSlot };
|