@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,439 @@
|
|
|
1
|
+
import { fetchGuarded } from '../../guardrails/network.js';
|
|
2
|
+
import { isRecord } from '../util/record.js';
|
|
3
|
+
import { computeCodeChallenge, generateCodeVerifier, sealStatePayload, toBase64Url, unsealStatePayload, } from './crypto.js';
|
|
4
|
+
const HTTP_NOT_FOUND = 404;
|
|
5
|
+
/** Never follows a redirect: it would carry codes and refresh tokens somewhere nobody vetted. */
|
|
6
|
+
function oauthFetch(url, init, transport) {
|
|
7
|
+
return fetchGuarded(url, init, {
|
|
8
|
+
policy: transport.network,
|
|
9
|
+
followRedirects: false,
|
|
10
|
+
resolveHost: transport.resolveHost,
|
|
11
|
+
...(transport.fetchFn ? { fetchFn: transport.fetchFn } : {}),
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
/** RFC 8414 §2, RFC 9728 §1.2, OAuth 2.1 §1.5: an absolute `https` URL without a fragment. */
|
|
15
|
+
function httpsUrl(value, what) {
|
|
16
|
+
if (typeof value !== 'string') {
|
|
17
|
+
throw new Error(`OAuth ${what} is missing`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
18
|
+
}
|
|
19
|
+
let url;
|
|
20
|
+
try {
|
|
21
|
+
url = new URL(value);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
throw new Error(`OAuth ${what} "${value}" is not a URL`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
25
|
+
}
|
|
26
|
+
if (url.protocol !== 'https:' || url.hash) {
|
|
27
|
+
throw new Error(`OAuth ${what} "${value}" must be an https URL without a fragment`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
28
|
+
}
|
|
29
|
+
return url;
|
|
30
|
+
}
|
|
31
|
+
/** RFC 8252 §7.3: the loopback hosts an `http` redirect may name. */
|
|
32
|
+
const LOOPBACK_HOSTS = new Set(['127.0.0.1', '[::1]', 'localhost']);
|
|
33
|
+
/**
|
|
34
|
+
* RFC 6749 §3.1.2: no fragment; `https`, `http` on loopback (RFC 8252 §7.3), or a
|
|
35
|
+
* reverse-domain private-use scheme for a native app (RFC 8252 §7.1).
|
|
36
|
+
*/
|
|
37
|
+
function assertRedirectUri(value) {
|
|
38
|
+
let url;
|
|
39
|
+
try {
|
|
40
|
+
url = new URL(value);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
throw new Error(`OAuth redirect_uri "${value}" is not an absolute URI`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
44
|
+
}
|
|
45
|
+
const scheme = url.protocol.slice(0, -1);
|
|
46
|
+
const allowed = scheme === 'https' ||
|
|
47
|
+
(scheme === 'http' && LOOPBACK_HOSTS.has(url.hostname)) ||
|
|
48
|
+
(scheme !== 'http' && scheme.includes('.'));
|
|
49
|
+
if (!allowed || value.includes('#')) {
|
|
50
|
+
throw new Error(`OAuth redirect_uri "${value}" must be https, http on loopback, or a reverse-domain app scheme, without a fragment`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** RFC 6749 §3.3: a scope token is one or more printable ASCII characters other than space, `"`, and `\`. */
|
|
54
|
+
const SCOPE_TOKEN = /^[\x21\x23-\x5B\x5D-\x7E]+$/;
|
|
55
|
+
function assertScopeTokens(scopes) {
|
|
56
|
+
for (const scope of scopes) {
|
|
57
|
+
if (!SCOPE_TOKEN.test(scope)) {
|
|
58
|
+
throw new Error(`OAuth scope "${scope}" is not a single RFC 6749 scope token`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** Names the flow sets itself; a provider's own parameters may not replace them. */
|
|
63
|
+
const FLOW_PARAMS = new Set([
|
|
64
|
+
'response_type',
|
|
65
|
+
'client_id',
|
|
66
|
+
'redirect_uri',
|
|
67
|
+
'code_challenge',
|
|
68
|
+
'code_challenge_method',
|
|
69
|
+
'state',
|
|
70
|
+
'resource',
|
|
71
|
+
'scope',
|
|
72
|
+
]);
|
|
73
|
+
function assertAuthorizationParams(params) {
|
|
74
|
+
for (const name of Object.keys(params)) {
|
|
75
|
+
if (FLOW_PARAMS.has(name)) {
|
|
76
|
+
throw new Error(`OAuth authorization parameter "${name}" is set by the flow and cannot be passed`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/** A client id that is a URL is a Client ID Metadata Document, which is served over https. */
|
|
81
|
+
function assertClientId(clientId) {
|
|
82
|
+
if (clientId.length === 0) {
|
|
83
|
+
throw new Error('OAuth client_id is missing'); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
84
|
+
}
|
|
85
|
+
if (/^https?:/i.test(clientId))
|
|
86
|
+
httpsUrl(clientId, 'client_id');
|
|
87
|
+
}
|
|
88
|
+
/** RFC 8414 §3.1, RFC 9728 §3.1: `/.well-known/<suffix>` goes between the host and the path. */
|
|
89
|
+
function wellKnownUrl(identifier, suffix) {
|
|
90
|
+
const path = identifier.pathname.replace(/\/$/, '');
|
|
91
|
+
return `${identifier.origin}/.well-known/${suffix}${path}${identifier.search}`;
|
|
92
|
+
}
|
|
93
|
+
function stringList(data, field) {
|
|
94
|
+
const value = data[field];
|
|
95
|
+
if (value === undefined)
|
|
96
|
+
return undefined;
|
|
97
|
+
if (!Array.isArray(value) || !value.every((entry) => typeof entry === 'string')) {
|
|
98
|
+
throw new Error(`OAuth metadata "${field}" must be a list of strings`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
99
|
+
}
|
|
100
|
+
return value;
|
|
101
|
+
}
|
|
102
|
+
async function metadataObject(response, url) {
|
|
103
|
+
const data = await response.json();
|
|
104
|
+
if (!isRecord(data)) {
|
|
105
|
+
throw new Error(`OAuth metadata at ${url} is not a JSON object`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
106
|
+
}
|
|
107
|
+
return data;
|
|
108
|
+
}
|
|
109
|
+
/** `undefined` on HTTP 404. RFC 9728 §3.3: a `resource` not identical to `resourceUrl` is refused. */
|
|
110
|
+
export async function discoverResourceMetadata(resourceUrl, transport = {}) {
|
|
111
|
+
const metadataUrl = wellKnownUrl(httpsUrl(resourceUrl, 'resource'), 'oauth-protected-resource');
|
|
112
|
+
const response = await oauthFetch(metadataUrl, { headers: { Accept: 'application/json' } }, transport);
|
|
113
|
+
if (response.status === HTTP_NOT_FOUND) {
|
|
114
|
+
await response.body?.cancel();
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
if (!response.ok) {
|
|
118
|
+
await response.body?.cancel();
|
|
119
|
+
throw new Error(`Failed to discover protected resource metadata at ${metadataUrl} (HTTP ${response.status})`);
|
|
120
|
+
}
|
|
121
|
+
const data = await metadataObject(response, metadataUrl);
|
|
122
|
+
if (data.resource !== resourceUrl) {
|
|
123
|
+
throw new Error(`Protected resource metadata at ${metadataUrl} is for "${String(data.resource)}", not "${resourceUrl}"`);
|
|
124
|
+
}
|
|
125
|
+
const authServers = stringList(data, 'authorization_servers') ?? [];
|
|
126
|
+
if (authServers.length === 0) {
|
|
127
|
+
throw new Error(`Protected resource metadata at ${metadataUrl} did not declare any authorization_servers`);
|
|
128
|
+
}
|
|
129
|
+
for (const server of authServers)
|
|
130
|
+
httpsUrl(server, 'authorization server');
|
|
131
|
+
return {
|
|
132
|
+
resource: resourceUrl,
|
|
133
|
+
authorization_servers: authServers,
|
|
134
|
+
scopes_supported: stringList(data, 'scopes_supported'),
|
|
135
|
+
bearer_methods_supported: stringList(data, 'bearer_methods_supported'),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/** RFC 8414 §3.3: the `issuer` must be identical to the one it was fetched for. */
|
|
139
|
+
function parseAuthServerMetadata(data, issuer, url) {
|
|
140
|
+
if (data.issuer !== issuer) {
|
|
141
|
+
throw new Error(`Authorization server metadata at ${url} names issuer "${String(data.issuer)}", not "${issuer}"`);
|
|
142
|
+
}
|
|
143
|
+
const authorizationEndpoint = httpsUrl(data.authorization_endpoint, 'authorization_endpoint');
|
|
144
|
+
const tokenEndpoint = httpsUrl(data.token_endpoint, 'token_endpoint');
|
|
145
|
+
const registrationEndpoint = data.registration_endpoint === undefined
|
|
146
|
+
? undefined
|
|
147
|
+
: httpsUrl(data.registration_endpoint, 'registration_endpoint');
|
|
148
|
+
return {
|
|
149
|
+
issuer,
|
|
150
|
+
authorization_endpoint: authorizationEndpoint.href,
|
|
151
|
+
token_endpoint: tokenEndpoint.href,
|
|
152
|
+
registration_endpoint: registrationEndpoint?.href,
|
|
153
|
+
scopes_supported: stringList(data, 'scopes_supported'),
|
|
154
|
+
response_types_supported: stringList(data, 'response_types_supported'),
|
|
155
|
+
grant_types_supported: stringList(data, 'grant_types_supported'),
|
|
156
|
+
code_challenge_methods_supported: stringList(data, 'code_challenge_methods_supported'),
|
|
157
|
+
authorization_response_iss_parameter_supported: data.authorization_response_iss_parameter_supported === true,
|
|
158
|
+
client_id_metadata_document_supported: data.client_id_metadata_document_supported === true,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
/** In order: RFC 8414, then OIDC Discovery with the well-known inserted, then appended for a path. */
|
|
162
|
+
function authServerMetadataUrls(issuer) {
|
|
163
|
+
const urls = [
|
|
164
|
+
wellKnownUrl(issuer, 'oauth-authorization-server'),
|
|
165
|
+
wellKnownUrl(issuer, 'openid-configuration'),
|
|
166
|
+
];
|
|
167
|
+
const path = issuer.pathname.replace(/\/$/, '');
|
|
168
|
+
if (path)
|
|
169
|
+
urls.push(`${issuer.origin}${path}/.well-known/openid-configuration`);
|
|
170
|
+
return urls;
|
|
171
|
+
}
|
|
172
|
+
/** A non-OK URL moves on to the next; metadata that answers but fails validation is refused outright. */
|
|
173
|
+
export async function discoverAuthServerMetadata(issuer, transport = {}) {
|
|
174
|
+
const issuerUrl = httpsUrl(issuer, 'issuer');
|
|
175
|
+
if (issuerUrl.search) {
|
|
176
|
+
throw new Error(`OAuth issuer "${issuer}" must not have a query`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
177
|
+
}
|
|
178
|
+
for (const url of authServerMetadataUrls(issuerUrl)) {
|
|
179
|
+
const response = await oauthFetch(url, { headers: { Accept: 'application/json' } }, transport);
|
|
180
|
+
if (!response.ok) {
|
|
181
|
+
await response.body?.cancel();
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
return parseAuthServerMetadata(await metadataObject(response, url), issuer, url);
|
|
185
|
+
}
|
|
186
|
+
throw new Error(`Failed to discover authorization server metadata for "${issuer}"`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
187
|
+
}
|
|
188
|
+
/** A resource that publishes no metadata is its own authorization server. */
|
|
189
|
+
async function discoverEndpoints(resourceServerUrl, transport) {
|
|
190
|
+
const resourceMeta = await discoverResourceMetadata(resourceServerUrl, transport);
|
|
191
|
+
const issuer = resourceMeta?.authorization_servers[0] ?? resourceServerUrl;
|
|
192
|
+
const asMeta = await discoverAuthServerMetadata(issuer, transport);
|
|
193
|
+
if (!asMeta.code_challenge_methods_supported?.includes('S256')) {
|
|
194
|
+
throw new Error(`Authorization server "${issuer}" does not advertise S256 PKCE (code_challenge_methods_supported)`);
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
issuer: asMeta.issuer,
|
|
198
|
+
authorizationEndpoint: asMeta.authorization_endpoint,
|
|
199
|
+
tokenEndpoint: asMeta.token_endpoint,
|
|
200
|
+
issParameterSupported: asMeta.authorization_response_iss_parameter_supported === true,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
/** Stateless: the verifier, expected issuer, token endpoint, and resource are sealed into `state`. */
|
|
204
|
+
export async function createOAuthPkceFlow(options) {
|
|
205
|
+
const endpoints = options.preResolved ?? (await discoverEndpoints(options.resourceServerUrl, options));
|
|
206
|
+
httpsUrl(endpoints.issuer, 'issuer');
|
|
207
|
+
const authUrl = httpsUrl(endpoints.authorizationEndpoint, 'authorization_endpoint');
|
|
208
|
+
const tokenEndpoint = httpsUrl(endpoints.tokenEndpoint, 'token_endpoint').href;
|
|
209
|
+
const { issuer } = endpoints;
|
|
210
|
+
// why: RFC 8707 audience: always the resource the flow is for; discovery required its metadata to match.
|
|
211
|
+
httpsUrl(options.resourceServerUrl, 'resource');
|
|
212
|
+
const resource = options.resourceServerUrl;
|
|
213
|
+
assertClientId(options.clientId);
|
|
214
|
+
assertRedirectUri(options.redirectUri);
|
|
215
|
+
if (options.scopes)
|
|
216
|
+
assertScopeTokens(options.scopes);
|
|
217
|
+
if (options.authorizationParams)
|
|
218
|
+
assertAuthorizationParams(options.authorizationParams);
|
|
219
|
+
const ttl = options.stateTtlMs ?? 10 * 60 * 1000;
|
|
220
|
+
if (!Number.isFinite(ttl) || ttl <= 0) {
|
|
221
|
+
throw new RangeError(`OAuth stateTtlMs must be a positive number of milliseconds; got ${ttl}`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
222
|
+
}
|
|
223
|
+
const sessionBinding = await sessionBindingDigest(options.sessionBinding);
|
|
224
|
+
const codeVerifier = generateCodeVerifier();
|
|
225
|
+
const codeChallenge = await computeCodeChallenge(codeVerifier);
|
|
226
|
+
const state = await sealStatePayload({
|
|
227
|
+
codeVerifier,
|
|
228
|
+
expectedIssuer: issuer,
|
|
229
|
+
issRequired: endpoints.issParameterSupported === true,
|
|
230
|
+
tokenEndpoint,
|
|
231
|
+
resource,
|
|
232
|
+
redirectUri: options.redirectUri,
|
|
233
|
+
expiresAt: Date.now() + ttl,
|
|
234
|
+
clientId: options.clientId,
|
|
235
|
+
sessionBinding,
|
|
236
|
+
scopes: options.scopes ? [...options.scopes] : [],
|
|
237
|
+
}, options.signingSecret);
|
|
238
|
+
for (const [name, value] of Object.entries(options.authorizationParams ?? {})) {
|
|
239
|
+
authUrl.searchParams.set(name, value);
|
|
240
|
+
}
|
|
241
|
+
authUrl.searchParams.set('response_type', 'code');
|
|
242
|
+
authUrl.searchParams.set('client_id', options.clientId);
|
|
243
|
+
authUrl.searchParams.set('redirect_uri', options.redirectUri);
|
|
244
|
+
authUrl.searchParams.set('code_challenge', codeChallenge);
|
|
245
|
+
authUrl.searchParams.set('code_challenge_method', 'S256');
|
|
246
|
+
authUrl.searchParams.set('state', state);
|
|
247
|
+
authUrl.searchParams.set('resource', resource);
|
|
248
|
+
if (options.scopes && options.scopes.length > 0) {
|
|
249
|
+
authUrl.searchParams.set('scope', options.scopes.join(' '));
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
authorizationUrl: authUrl.toString(),
|
|
253
|
+
state,
|
|
254
|
+
codeChallenge,
|
|
255
|
+
issuer,
|
|
256
|
+
resource,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
/** SHA-256 of the host's session binding, so the raw value never enters the state. */
|
|
260
|
+
async function sessionBindingDigest(binding) {
|
|
261
|
+
if (binding.length === 0) {
|
|
262
|
+
throw new Error('OAuth sessionBinding must be a non-empty value tied to the user session'); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
263
|
+
}
|
|
264
|
+
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(binding));
|
|
265
|
+
return toBase64Url(new Uint8Array(digest));
|
|
266
|
+
}
|
|
267
|
+
/** Compare two digests without an early exit, so timing says nothing about where they differ. */
|
|
268
|
+
function sameDigest(a, b) {
|
|
269
|
+
if (a.length !== b.length)
|
|
270
|
+
return false;
|
|
271
|
+
let diff = 0;
|
|
272
|
+
for (let i = 0; i < a.length; i++)
|
|
273
|
+
diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
274
|
+
return diff === 0;
|
|
275
|
+
}
|
|
276
|
+
/** RFC 9207 §2.4: `iss` is required when the server advertises it, and byte-exact (no URL normalization). */
|
|
277
|
+
export function validateIssuer(expectedIssuer, receivedIss, issRequired) {
|
|
278
|
+
if (receivedIss === undefined) {
|
|
279
|
+
if (issRequired) {
|
|
280
|
+
throw new Error(`RFC 9207: authorization server "${expectedIssuer}" sends "iss", but the response has none (potential mix-up attack)`);
|
|
281
|
+
}
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (expectedIssuer !== receivedIss) {
|
|
285
|
+
throw new Error(`RFC 9207 Issuer mismatch detected (potential mix-up attack): expected "${expectedIssuer}", received "${receivedIss}"`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/** RFC 6749 §5.2: `error_description` is printable ASCII without `"` or `\`. */
|
|
289
|
+
const ERROR_DESCRIPTION = /^[\x20\x21\x23-\x5B\x5D-\x7E]*$/;
|
|
290
|
+
/** RFC 6749 §5.2 shape only; any other body is not repeated into the error. */
|
|
291
|
+
async function tokenErrorText(response) {
|
|
292
|
+
let data;
|
|
293
|
+
try {
|
|
294
|
+
data = await response.json();
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
return '';
|
|
298
|
+
}
|
|
299
|
+
if (!isRecord(data))
|
|
300
|
+
return '';
|
|
301
|
+
const { error, error_description: description } = data;
|
|
302
|
+
if (typeof error !== 'string' || !ERROR_DESCRIPTION.test(error))
|
|
303
|
+
return '';
|
|
304
|
+
const told = typeof description === 'string' && ERROR_DESCRIPTION.test(description);
|
|
305
|
+
return told ? `: ${error} (${description})` : `: ${error}`;
|
|
306
|
+
}
|
|
307
|
+
function parseTokenResponse(data, tokenEndpoint) {
|
|
308
|
+
const fail = (why) => {
|
|
309
|
+
throw new Error(`Token response from ${tokenEndpoint} ${why}`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
310
|
+
};
|
|
311
|
+
if (!isRecord(data)) {
|
|
312
|
+
return fail('is not a JSON object'); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
313
|
+
}
|
|
314
|
+
const tokens = data;
|
|
315
|
+
if (typeof tokens.access_token !== 'string' || tokens.access_token.length === 0) {
|
|
316
|
+
fail('has no access_token'); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
317
|
+
}
|
|
318
|
+
if (typeof tokens.token_type !== 'string' || tokens.token_type.toLowerCase() !== 'bearer') {
|
|
319
|
+
fail(`has token_type "${String(tokens.token_type)}", not Bearer`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
320
|
+
}
|
|
321
|
+
const expiresIn = tokens.expires_in;
|
|
322
|
+
if (expiresIn !== undefined &&
|
|
323
|
+
(typeof expiresIn !== 'number' || !Number.isFinite(expiresIn) || expiresIn < 0)) {
|
|
324
|
+
fail('has an expires_in that is not a number of seconds'); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
325
|
+
}
|
|
326
|
+
for (const field of ['refresh_token', 'scope']) {
|
|
327
|
+
if (tokens[field] !== undefined && typeof tokens[field] !== 'string') {
|
|
328
|
+
fail(`has a ${field} that is not a string`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return tokens;
|
|
332
|
+
}
|
|
333
|
+
/** RFC 6749 §3.3: a scope is a list of space-delimited tokens. */
|
|
334
|
+
function scopeTokens(scope) {
|
|
335
|
+
return scope === undefined ? [] : scope.split(' ').filter((token) => token.length > 0);
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* The scopes asked for are the most a grant may hold: a token carrying any other is refused
|
|
339
|
+
* before it is stored. An empty request asked for the server's default, so it sets no ceiling;
|
|
340
|
+
* a response without `scope` granted exactly what was asked (RFC 6749 §5.1).
|
|
341
|
+
*/
|
|
342
|
+
function assertGrantWithin(granted, requested, tokenEndpoint) {
|
|
343
|
+
if (requested.length === 0)
|
|
344
|
+
return;
|
|
345
|
+
const beyond = scopeTokens(granted).filter((scope) => !requested.includes(scope));
|
|
346
|
+
if (beyond.length > 0) {
|
|
347
|
+
throw new Error(`Token response from ${tokenEndpoint} grants scopes that were not asked for: ${beyond.join(', ')}`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* `requested` is the ceiling the grant is held to. A refresh passes `previous`, whose refresh
|
|
352
|
+
* token and scope stay when the server sends no new ones.
|
|
353
|
+
*/
|
|
354
|
+
async function requestToken(transport, grant, params, requested, previous) {
|
|
355
|
+
const { clientSecret, ...issued } = grant;
|
|
356
|
+
const body = new URLSearchParams({
|
|
357
|
+
...params,
|
|
358
|
+
client_id: grant.clientId,
|
|
359
|
+
...(clientSecret === undefined ? {} : { client_secret: clientSecret }),
|
|
360
|
+
resource: grant.resource,
|
|
361
|
+
});
|
|
362
|
+
const response = await oauthFetch(grant.tokenEndpoint, {
|
|
363
|
+
method: 'POST',
|
|
364
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded', Accept: 'application/json' },
|
|
365
|
+
body: body.toString(),
|
|
366
|
+
}, transport);
|
|
367
|
+
if (!response.ok) {
|
|
368
|
+
const failed = previous ? 'Token refresh failed' : 'Token exchange failed'; // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
369
|
+
throw new Error(`${failed} at ${grant.tokenEndpoint} (HTTP ${response.status})${await tokenErrorText(response)}`);
|
|
370
|
+
}
|
|
371
|
+
const tokens = parseTokenResponse(await response.json(), grant.tokenEndpoint);
|
|
372
|
+
assertGrantWithin(tokens.scope, requested, grant.tokenEndpoint);
|
|
373
|
+
const credential = {
|
|
374
|
+
type: 'oauth2',
|
|
375
|
+
...issued,
|
|
376
|
+
accessToken: tokens.access_token,
|
|
377
|
+
refreshToken: tokens.refresh_token ?? previous?.refreshToken,
|
|
378
|
+
expiresAt: tokens.expires_in === undefined ? undefined : Date.now() + tokens.expires_in * 1000,
|
|
379
|
+
scope: tokens.scope ?? previous?.scope ?? (requested.length > 0 ? requested.join(' ') : undefined),
|
|
380
|
+
};
|
|
381
|
+
return { tokens, credential };
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Requires the session that began the flow (RFC 6749 §10.12), the same `redirect_uri` (§4.1.3)
|
|
385
|
+
* and a valid `iss` (RFC 9207); posts to the token endpoint sealed in `state`, never a caller's.
|
|
386
|
+
*/
|
|
387
|
+
export async function exchangeOAuthPkce(options) {
|
|
388
|
+
const state = await unsealStatePayload(options.state, options.signingSecret);
|
|
389
|
+
const presented = await sessionBindingDigest(options.sessionBinding);
|
|
390
|
+
if (!sameDigest(presented, state.sessionBinding)) {
|
|
391
|
+
throw new Error('OAuth state belongs to another session: the callback did not come from the session that began the flow');
|
|
392
|
+
}
|
|
393
|
+
if (options.redirectUri !== state.redirectUri) {
|
|
394
|
+
throw new Error(`Redirect URI mismatch: expected "${state.redirectUri}", received "${options.redirectUri}"`);
|
|
395
|
+
}
|
|
396
|
+
validateIssuer(state.expectedIssuer, options.iss, state.issRequired);
|
|
397
|
+
return requestToken(options, {
|
|
398
|
+
issuer: state.expectedIssuer,
|
|
399
|
+
resource: state.resource,
|
|
400
|
+
tokenEndpoint: state.tokenEndpoint,
|
|
401
|
+
clientId: state.clientId,
|
|
402
|
+
...(options.clientSecret === undefined ? {} : { clientSecret: options.clientSecret }),
|
|
403
|
+
}, {
|
|
404
|
+
grant_type: 'authorization_code',
|
|
405
|
+
code: options.code,
|
|
406
|
+
redirect_uri: state.redirectUri,
|
|
407
|
+
code_verifier: state.codeVerifier,
|
|
408
|
+
}, state.scopes);
|
|
409
|
+
}
|
|
410
|
+
/** Exchanges a refresh token for new tokens at the token endpoint; both the endpoint and the resource must be https URLs. */
|
|
411
|
+
export function refreshOAuthToken(options) {
|
|
412
|
+
httpsUrl(options.tokenEndpoint, 'token_endpoint');
|
|
413
|
+
httpsUrl(options.resource, 'resource');
|
|
414
|
+
return requestToken(options, {
|
|
415
|
+
issuer: options.issuer,
|
|
416
|
+
resource: options.resource,
|
|
417
|
+
tokenEndpoint: options.tokenEndpoint,
|
|
418
|
+
clientId: options.clientId,
|
|
419
|
+
...(options.clientSecret === undefined ? {} : { clientSecret: options.clientSecret }),
|
|
420
|
+
}, {
|
|
421
|
+
grant_type: 'refresh_token',
|
|
422
|
+
refresh_token: options.refreshToken,
|
|
423
|
+
...(options.scope ? { scope: options.scope } : {}),
|
|
424
|
+
}, scopeTokens(options.scope), { refreshToken: options.refreshToken, scope: options.scope });
|
|
425
|
+
}
|
|
426
|
+
/** RFC 8707: the same origin, and the resource's path or below it. */
|
|
427
|
+
export function tokenAudienceCovers(resource, url) {
|
|
428
|
+
let audience;
|
|
429
|
+
try {
|
|
430
|
+
audience = new URL(resource);
|
|
431
|
+
}
|
|
432
|
+
catch {
|
|
433
|
+
return false;
|
|
434
|
+
}
|
|
435
|
+
if (audience.origin !== url.origin)
|
|
436
|
+
return false;
|
|
437
|
+
const base = audience.pathname.replace(/\/$/, '');
|
|
438
|
+
return url.pathname === base || url.pathname.startsWith(`${base}/`) || base === '';
|
|
439
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** What a refusal outside the declared scopes streams as `progress`, for the host and the trace. */
|
|
3
|
+
export declare const authScopeRefusedSchema: z.ZodObject<{
|
|
4
|
+
kind: z.ZodLiteral<"auth_scope_refused">;
|
|
5
|
+
slot: z.ZodString;
|
|
6
|
+
requested: z.ZodArray<z.ZodString>;
|
|
7
|
+
declared: z.ZodArray<z.ZodString>;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
export type AuthScopeRefused = z.infer<typeof authScopeRefusedSchema>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** What a refusal outside the declared scopes streams as `progress`, for the host and the trace. */
|
|
3
|
+
export const authScopeRefusedSchema = z.object({
|
|
4
|
+
kind: z.literal('auth_scope_refused'),
|
|
5
|
+
slot: z.string(),
|
|
6
|
+
requested: z.array(z.string()),
|
|
7
|
+
declared: z.array(z.string()),
|
|
8
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ToolAuthType } from '../schema.js';
|
|
2
|
+
import type { ToolGateAuth } from '../tools/gate-answer.js';
|
|
3
|
+
import type { ApiKeyCredential, BearerCredential } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* The server builds the credential, so the browser cannot pick its kind or header. An OAuth
|
|
6
|
+
* gate takes no typed secret: its token comes from the host's callback route.
|
|
7
|
+
*/
|
|
8
|
+
export declare function credentialFromTypedSecret(authType: ToolAuthType, secret: unknown): BearerCredential | ApiKeyCredential;
|
|
9
|
+
/** `auth` is absent on any gate other than sign-in, which takes no key. */
|
|
10
|
+
export declare function credentialForSignInGate(auth: Pick<ToolGateAuth, 'slot' | 'authType'> | undefined, secret: unknown): {
|
|
11
|
+
slot: string;
|
|
12
|
+
credential: BearerCredential | ApiKeyCredential;
|
|
13
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { TheoremError } from '../../guardrails/error.js';
|
|
2
|
+
/**
|
|
3
|
+
* The server builds the credential, so the browser cannot pick its kind or header. An OAuth
|
|
4
|
+
* gate takes no typed secret: its token comes from the host's callback route.
|
|
5
|
+
*/
|
|
6
|
+
export function credentialFromTypedSecret(authType, secret) {
|
|
7
|
+
const value = typeof secret === 'string' ? secret.trim() : '';
|
|
8
|
+
if (!value) {
|
|
9
|
+
throw new TheoremError('request', 'A typed credential must be a non-empty string'); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
10
|
+
}
|
|
11
|
+
if (authType === 'bearer')
|
|
12
|
+
return { type: 'bearer', token: value };
|
|
13
|
+
if (authType === 'api_key')
|
|
14
|
+
return { type: 'api_key', key: value };
|
|
15
|
+
throw new TheoremError('request', `A '${authType}' sign-in takes no typed credential; the host's callback saves it`);
|
|
16
|
+
}
|
|
17
|
+
/** `auth` is absent on any gate other than sign-in, which takes no key. */
|
|
18
|
+
export function credentialForSignInGate(auth, secret) {
|
|
19
|
+
if (!auth) {
|
|
20
|
+
throw new TheoremError('request', 'a typed credential answers only a sign-in gate'); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
21
|
+
}
|
|
22
|
+
return { slot: auth.slot, credential: credentialFromTypedSecret(auth.authType, secret) };
|
|
23
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { ResolveHost } from '../../guardrails/network.js';
|
|
2
|
+
import type { NetworkGuardrailSpec } from '../../guardrails/types.js';
|
|
3
|
+
/** RFC 9728. */
|
|
4
|
+
export interface ProtectedResourceMetadata {
|
|
5
|
+
resource: string;
|
|
6
|
+
authorization_servers: string[];
|
|
7
|
+
scopes_supported?: string[];
|
|
8
|
+
bearer_methods_supported?: string[];
|
|
9
|
+
resource_documentation?: string;
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
/** RFC 8414 / OpenID Connect Discovery. */
|
|
13
|
+
export interface AuthorizationServerMetadata {
|
|
14
|
+
issuer: string;
|
|
15
|
+
authorization_endpoint: string;
|
|
16
|
+
token_endpoint: string;
|
|
17
|
+
registration_endpoint?: string;
|
|
18
|
+
scopes_supported?: string[];
|
|
19
|
+
response_types_supported?: string[];
|
|
20
|
+
grant_types_supported?: string[];
|
|
21
|
+
code_challenge_methods_supported?: string[];
|
|
22
|
+
authorization_response_iss_parameter_supported?: boolean;
|
|
23
|
+
client_id_metadata_document_supported?: boolean;
|
|
24
|
+
[key: string]: unknown;
|
|
25
|
+
}
|
|
26
|
+
/** The tokens an OAuth server returns. */
|
|
27
|
+
export interface OAuthTokens {
|
|
28
|
+
access_token: string;
|
|
29
|
+
token_type?: string;
|
|
30
|
+
expires_in?: number;
|
|
31
|
+
refresh_token?: string;
|
|
32
|
+
scope?: string;
|
|
33
|
+
[key: string]: unknown;
|
|
34
|
+
}
|
|
35
|
+
/** An OAuth sign-in a tool authenticates with. */
|
|
36
|
+
export interface OAuth2Credential {
|
|
37
|
+
type: 'oauth2';
|
|
38
|
+
issuer: string;
|
|
39
|
+
/** RFC 8707: the token is sent nowhere else. */
|
|
40
|
+
resource: string;
|
|
41
|
+
accessToken: string;
|
|
42
|
+
refreshToken?: string;
|
|
43
|
+
/** Epoch milliseconds. */
|
|
44
|
+
expiresAt?: number;
|
|
45
|
+
tokenEndpoint: string;
|
|
46
|
+
clientId: string;
|
|
47
|
+
scope?: string;
|
|
48
|
+
}
|
|
49
|
+
/** A bearer token a tool authenticates with. */
|
|
50
|
+
export interface BearerCredential {
|
|
51
|
+
type: 'bearer';
|
|
52
|
+
token: string;
|
|
53
|
+
}
|
|
54
|
+
/** An API key a tool authenticates with. */
|
|
55
|
+
export interface ApiKeyCredential {
|
|
56
|
+
type: 'api_key';
|
|
57
|
+
key: string;
|
|
58
|
+
/** The header the key goes in; a tool whose `auth.queryParam` puts it in the URL ignores it. */
|
|
59
|
+
headerName?: string;
|
|
60
|
+
/** Text put before the key in the header; ignored as `headerName` is. */
|
|
61
|
+
headerPrefix?: string;
|
|
62
|
+
}
|
|
63
|
+
/** Any credential a tool can authenticate with. */
|
|
64
|
+
export type ToolCredential = OAuth2Credential | BearerCredential | ApiKeyCredential;
|
|
65
|
+
/** Every discovery and token request clears the network policy and never follows a redirect. */
|
|
66
|
+
export interface OAuthTransportOptions {
|
|
67
|
+
/** Default: https to public hosts. */
|
|
68
|
+
network?: NetworkGuardrailSpec;
|
|
69
|
+
/** A host that resolves to a private address is refused. */
|
|
70
|
+
resolveHost?: ResolveHost;
|
|
71
|
+
fetchFn?: typeof fetch;
|
|
72
|
+
}
|
|
73
|
+
/** The endpoints of an OAuth authorization server. */
|
|
74
|
+
export interface OAuthEndpoints {
|
|
75
|
+
issuer: string;
|
|
76
|
+
authorizationEndpoint: string;
|
|
77
|
+
tokenEndpoint: string;
|
|
78
|
+
/** RFC 9207: authorization responses without `iss` are then refused. */
|
|
79
|
+
issParameterSupported?: boolean;
|
|
80
|
+
}
|
|
81
|
+
/** Options for starting a PKCE authorization. */
|
|
82
|
+
export interface CreatePkceFlowOptions extends OAuthTransportOptions {
|
|
83
|
+
/**
|
|
84
|
+
* An https URL (e.g. the MCP server) and the token's audience (RFC 8707). Without
|
|
85
|
+
* RFC 9728 metadata of its own it is its own authorization server.
|
|
86
|
+
*/
|
|
87
|
+
resourceServerUrl: string;
|
|
88
|
+
/** Or the https URL of its Client ID Metadata Document. */
|
|
89
|
+
clientId: string;
|
|
90
|
+
/** No fragment: https, http on loopback (RFC 8252 §7.3), or a reverse-domain app scheme (§7.1). */
|
|
91
|
+
redirectUri: string;
|
|
92
|
+
/** Each a single RFC 6749 §3.3 scope token. */
|
|
93
|
+
scopes?: string[];
|
|
94
|
+
/**
|
|
95
|
+
* Encrypts the state envelope: at least 32 bytes and 256 bits of entropy (32 CSPRNG bytes,
|
|
96
|
+
* base64-encoded), so a quantum search still faces 128-bit work.
|
|
97
|
+
*/
|
|
98
|
+
signingSecret: string;
|
|
99
|
+
/**
|
|
100
|
+
* Bound to the user's session and neither knowable nor settable by an attacker (a session id,
|
|
101
|
+
* an HttpOnly cookie value). The callback must present it (RFC 6749 §10.12); only its SHA-256 is sealed.
|
|
102
|
+
*/
|
|
103
|
+
sessionBinding: string;
|
|
104
|
+
/** Milliseconds; default 10 minutes. */
|
|
105
|
+
stateTtlMs?: number;
|
|
106
|
+
/** Skips discovery. */
|
|
107
|
+
preResolved?: OAuthEndpoints;
|
|
108
|
+
/**
|
|
109
|
+
* Parameters a provider reads beyond the standard ones (e.g. Google's
|
|
110
|
+
* `access_type: 'offline'`, without which it issues no refresh token). A name the
|
|
111
|
+
* flow sets itself is refused.
|
|
112
|
+
*/
|
|
113
|
+
authorizationParams?: Readonly<Record<string, string>>;
|
|
114
|
+
}
|
|
115
|
+
/** A started PKCE authorization: the URL to send the user to and the values to keep. */
|
|
116
|
+
export interface PkceFlowResult {
|
|
117
|
+
authorizationUrl: string;
|
|
118
|
+
state: string;
|
|
119
|
+
codeChallenge: string;
|
|
120
|
+
issuer: string;
|
|
121
|
+
resource: string;
|
|
122
|
+
}
|
|
123
|
+
/** Options for trading an authorization code for tokens. */
|
|
124
|
+
export interface ExchangePkceCodeOptions extends OAuthTransportOptions {
|
|
125
|
+
code: string;
|
|
126
|
+
state: string;
|
|
127
|
+
/** From the authorization response query (RFC 9207). */
|
|
128
|
+
iss?: string;
|
|
129
|
+
/** Must match the authorization request. */
|
|
130
|
+
redirectUri: string;
|
|
131
|
+
signingSecret: string;
|
|
132
|
+
/** Read from the session handling the callback. */
|
|
133
|
+
sessionBinding: string;
|
|
134
|
+
/** A confidential client's secret, sent in the token request body (RFC 6749 §2.3.1); never stored. */
|
|
135
|
+
clientSecret?: string;
|
|
136
|
+
}
|
|
137
|
+
/** The tokens and credential a PKCE exchange yields. */
|
|
138
|
+
export interface ExchangePkceCodeResult {
|
|
139
|
+
tokens: OAuthTokens;
|
|
140
|
+
credential: OAuth2Credential;
|
|
141
|
+
}
|
|
142
|
+
/** Options for refreshing an OAuth access token. */
|
|
143
|
+
export interface RefreshOAuthTokenOptions extends OAuthTransportOptions {
|
|
144
|
+
refreshToken: string;
|
|
145
|
+
tokenEndpoint: string;
|
|
146
|
+
clientId: string;
|
|
147
|
+
resource: string;
|
|
148
|
+
scope?: string;
|
|
149
|
+
issuer: string;
|
|
150
|
+
/** A confidential client's secret, sent in the token request body (RFC 6749 §2.3.1); never stored. */
|
|
151
|
+
clientSecret?: string;
|
|
152
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|