@theoremjs/agents 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +277 -995
- package/esm/mod.d.ts +34 -20
- package/esm/mod.js +19 -12
- package/esm/src/cli/commands/bench.js +36 -14
- 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 +3 -3
- package/esm/src/cli/commands/fuzz-canary.js +55 -16
- package/esm/src/cli/commands/profile.js +4 -4
- package/esm/src/cli/commands/run.d.ts +2 -2
- package/esm/src/cli/commands/run.js +1 -1
- package/esm/src/cli/commands/test.d.ts +4 -3
- package/esm/src/cli/commands/test.js +2 -2
- package/esm/src/cli/index.js +9 -9
- package/esm/src/cli/matrix/fixtures.js +25 -30
- package/esm/src/evals/attachments.d.ts +1 -0
- package/esm/src/evals/attachments.js +4 -2
- package/esm/src/evals/breakdown.d.ts +2 -0
- package/esm/src/evals/breakdown.js +1 -0
- package/esm/src/evals/graders/answer.d.ts +3 -0
- package/esm/src/evals/graders/answer.js +1 -0
- package/esm/src/evals/graders/code.d.ts +7 -31
- package/esm/src/evals/graders/code.js +4 -25
- package/esm/src/evals/graders/judge.d.ts +4 -0
- package/esm/src/evals/graders/judge.js +7 -5
- package/esm/src/evals/graders/latency.d.ts +1 -0
- package/esm/src/evals/graders/latency.js +3 -2
- package/esm/src/evals/graders/live.d.ts +3 -0
- package/esm/src/evals/graders/live.js +2 -0
- package/esm/src/evals/graders/media.js +1 -2
- package/esm/src/evals/graders/shared.js +1 -1
- package/esm/src/evals/graders/transcript.d.ts +2 -0
- package/esm/src/evals/graders/transcript.js +5 -3
- package/esm/src/evals/mod.d.ts +1 -9
- package/esm/src/evals/mod.js +1 -9
- package/esm/src/evals/record.d.ts +6 -0
- package/esm/src/evals/record.js +4 -2
- package/esm/src/evals/rubrics/mod.d.ts +1 -1
- package/esm/src/evals/rubrics/mod.js +1 -1
- package/esm/src/evals/rubrics/mustache.js +1 -1
- package/esm/src/evals/rubrics/types.js +1 -1
- package/esm/src/evals/run.d.ts +9 -52
- package/esm/src/evals/run.js +12 -46
- package/esm/src/evals/suite.d.ts +12 -3
- package/esm/src/evals/suite.js +9 -4
- package/esm/src/evals/summary.d.ts +3 -0
- package/esm/src/evals/summary.js +1 -0
- package/esm/src/evals/trial.d.ts +3 -16
- package/esm/src/evals/trial.js +7 -30
- package/esm/src/evals/types.d.ts +30 -121
- package/esm/src/evals/types.js +3 -16
- package/esm/src/evals/verdict.d.ts +5 -0
- package/esm/src/evals/verdict.js +4 -1
- 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 +1 -0
- package/esm/src/guardrails/canary.d.ts +49 -15
- package/esm/src/guardrails/canary.js +103 -30
- package/esm/src/guardrails/compile-egress.d.ts +6 -5
- package/esm/src/guardrails/compile-egress.js +6 -5
- package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +3 -1
- package/esm/src/guardrails/corpus/canary-egress-attacks.js +4 -2
- package/esm/src/guardrails/corpus/fuzz-inbound.js +14 -17
- package/esm/src/guardrails/corpus/inbound-payloads.d.ts +2 -0
- package/esm/src/guardrails/corpus/inbound-payloads.js +4 -2
- package/esm/src/guardrails/corpus/live-attacks.d.ts +2 -0
- package/esm/src/guardrails/corpus/live-attacks.js +6 -1
- package/esm/src/guardrails/corpus/mod.d.ts +1 -1
- package/esm/src/guardrails/corpus/secrets.d.ts +3 -3
- package/esm/src/guardrails/corpus/secrets.js +2 -2
- package/esm/src/guardrails/corpus/strings.d.ts +1 -1
- package/esm/src/guardrails/corpus/strings.js +1 -1
- package/esm/src/guardrails/corpus/types.d.ts +5 -1
- 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 +4 -6
- package/esm/src/guardrails/egress-automata.js +24095 -4572
- package/esm/src/guardrails/egress-compiler.d.ts +38 -16
- package/esm/src/guardrails/egress-compiler.js +254 -60
- package/esm/src/guardrails/egress-patterns.d.ts +4 -2
- package/esm/src/guardrails/egress-patterns.js +6 -2
- package/esm/src/guardrails/egress-stream.d.ts +54 -36
- package/esm/src/guardrails/egress-stream.js +253 -124
- package/esm/src/guardrails/egress-urls.d.ts +6 -3
- package/esm/src/guardrails/egress-urls.js +14 -22
- package/esm/src/guardrails/egress.d.ts +26 -86
- package/esm/src/guardrails/egress.js +59 -309
- package/esm/src/guardrails/error.d.ts +13 -8
- package/esm/src/guardrails/error.js +25 -18
- package/esm/src/guardrails/event-schemas.d.ts +46 -3
- package/esm/src/guardrails/event-schemas.js +12 -5
- package/esm/src/guardrails/events.d.ts +5 -1
- package/esm/src/guardrails/events.js +4 -1
- package/esm/src/guardrails/hints.d.ts +14 -0
- package/esm/src/guardrails/hints.js +57 -0
- package/esm/src/guardrails/hits.d.ts +7 -1
- package/esm/src/guardrails/hits.js +12 -1
- 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 +6 -1
- package/esm/src/guardrails/injection-patterns.js +33 -1
- 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 +17 -1
- package/esm/src/guardrails/injection.js +259 -36
- package/esm/src/guardrails/labels.d.ts +40 -0
- package/esm/src/guardrails/labels.js +881 -0
- package/esm/src/guardrails/live-outbound-gate.d.ts +9 -8
- package/esm/src/guardrails/live-outbound-gate.js +100 -107
- package/esm/src/guardrails/mod.d.ts +30 -22
- package/esm/src/guardrails/mod.js +19 -14
- package/esm/src/guardrails/network.d.ts +4 -0
- package/esm/src/guardrails/network.js +21 -19
- package/esm/src/guardrails/normalize.d.ts +15 -1
- package/esm/src/guardrails/normalize.js +34 -1
- package/esm/src/guardrails/policy.d.ts +2 -17
- package/esm/src/guardrails/policy.js +12 -41
- package/esm/src/guardrails/progressive-yield.d.ts +65 -24
- package/esm/src/guardrails/progressive-yield.js +191 -147
- package/esm/src/guardrails/prompt-echo.d.ts +4 -2
- package/esm/src/guardrails/prompt-echo.js +87 -6
- package/esm/src/guardrails/quota.d.ts +4 -1
- package/esm/src/guardrails/quota.js +7 -2
- package/esm/src/guardrails/rules.d.ts +20 -29
- package/esm/src/guardrails/rules.js +23 -30
- package/esm/src/guardrails/sanitize.d.ts +32 -15
- package/esm/src/guardrails/sanitize.js +100 -124
- 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 +16 -23
- package/esm/src/guardrails/sensitive.js +168 -47
- package/esm/src/guardrails/serialize.d.ts +1 -0
- package/esm/src/guardrails/testing.d.ts +4 -2
- package/esm/src/guardrails/testing.js +4 -2
- package/esm/src/guardrails/theorem-error.d.ts +5 -2
- package/esm/src/guardrails/theorem-error.js +6 -3
- package/esm/src/guardrails/thought-guard.d.ts +34 -13
- package/esm/src/guardrails/thought-guard.js +264 -64
- package/esm/src/guardrails/tool-directives.d.ts +29 -10
- package/esm/src/guardrails/tool-directives.js +133 -47
- 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 +45 -14
- package/esm/src/guardrails/tool-result.js +94 -70
- package/esm/src/guardrails/types.d.ts +79 -71
- package/esm/src/guardrails/types.js +11 -7
- package/esm/src/host/client-turn.d.ts +29 -2
- package/esm/src/host/client-turn.js +46 -4
- package/esm/src/host/mint-trace.d.ts +1 -0
- package/esm/src/host/mint-trace.js +3 -2
- package/esm/src/host/mod.d.ts +2 -2
- package/esm/src/host/mod.js +1 -1
- package/esm/src/host/readStreamingJsonStringField.js +2 -43
- package/esm/src/host/reply.d.ts +6 -0
- package/esm/src/host/reply.js +8 -1
- package/esm/src/interface/blocks.d.ts +3 -0
- package/esm/src/interface/blocks.js +84 -14
- package/esm/src/interface/composer-actions.d.ts +4 -0
- package/esm/src/interface/composer-actions.js +5 -3
- package/esm/src/interface/draft.d.ts +6 -0
- package/esm/src/interface/draft.js +22 -11
- package/esm/src/interface/from-profile.d.ts +13 -1
- package/esm/src/interface/from-profile.js +66 -31
- package/esm/src/interface/history.d.ts +9 -3
- package/esm/src/interface/history.js +33 -24
- package/esm/src/interface/inputs.d.ts +1 -0
- package/esm/src/interface/inputs.js +3 -0
- package/esm/src/interface/mod.d.ts +4 -2
- package/esm/src/interface/mod.js +3 -2
- package/esm/src/interface/models.d.ts +7 -0
- package/esm/src/interface/models.js +5 -0
- package/esm/src/interface/pending.d.ts +9 -0
- package/esm/src/interface/pending.js +9 -3
- package/esm/src/interface/profile-interface.js +54 -40
- package/esm/src/interface/session.d.ts +12 -5
- package/esm/src/interface/session.js +17 -10
- 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 +14 -2
- package/esm/src/interface/tool-calls.js +64 -10
- package/esm/src/interface/tool-invoke.d.ts +2 -0
- package/esm/src/interface/tool-invoke.js +3 -1
- package/esm/src/interface/tool-media.d.ts +2 -0
- package/esm/src/interface/tool-media.js +2 -1
- package/esm/src/interface/types.d.ts +105 -40
- package/esm/src/interface/types.js +1 -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/crypto.d.ts +7 -2
- package/esm/src/kernel/auth/crypto.js +12 -10
- package/esm/src/kernel/auth/oauth.d.ts +2 -1
- package/esm/src/kernel/auth/oauth.js +23 -22
- package/esm/src/kernel/auth/typed-secret.js +2 -2
- package/esm/src/kernel/auth/types.d.ts +13 -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 +43 -5
- package/esm/src/kernel/default-scope.js +54 -5
- 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 +6 -5
- package/esm/src/kernel/engine/compaction.js +12 -11
- package/esm/src/kernel/engine/decision.d.ts +10 -8
- package/esm/src/kernel/engine/decision.js +174 -146
- package/esm/src/kernel/engine/embedding.d.ts +8 -0
- package/esm/src/kernel/engine/embedding.js +118 -0
- package/esm/src/kernel/engine/live-inbound.d.ts +14 -4
- package/esm/src/kernel/engine/live-inbound.js +36 -11
- package/esm/src/kernel/engine/live-ingress.d.ts +6 -0
- package/esm/src/kernel/engine/live-ingress.js +6 -1
- package/esm/src/kernel/engine/repair.js +12 -12
- package/esm/src/kernel/engine/runner/gates.d.ts +2 -2
- package/esm/src/kernel/engine/runner/gates.js +287 -101
- package/esm/src/kernel/engine/runner/mod.d.ts +19 -5
- package/esm/src/kernel/engine/runner/mod.js +107 -56
- 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 +24 -3
- package/esm/src/kernel/engine/runner/schema-validation.js +78 -4
- package/esm/src/kernel/engine/runner/stages.d.ts +1 -1
- package/esm/src/kernel/engine/runner/stages.js +1 -8
- package/esm/src/kernel/engine/runner/state.d.ts +33 -12
- package/esm/src/kernel/engine/runner/state.js +11 -1
- 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 +2 -2
- package/esm/src/kernel/engine/runner/steps.js +329 -169
- package/esm/src/kernel/engine/runner/stream.d.ts +42 -11
- package/esm/src/kernel/engine/runner/stream.js +197 -46
- package/esm/src/kernel/engine/runner/usage.d.ts +5 -5
- package/esm/src/kernel/engine/runner/usage.js +12 -14
- package/esm/src/kernel/engine/session/mod.d.ts +8 -6
- package/esm/src/kernel/engine/session/mod.js +360 -129
- package/esm/src/kernel/engine/session/session-trace.d.ts +10 -10
- package/esm/src/kernel/engine/session/session-trace.js +41 -30
- package/esm/src/kernel/engine/token-estimate.d.ts +10 -64
- package/esm/src/kernel/engine/token-estimate.js +14 -194
- package/esm/src/kernel/engine/tool-trace.d.ts +3 -3
- package/esm/src/kernel/engine/tool-trace.js +2 -1
- package/esm/src/kernel/engine/turn-trace.d.ts +8 -7
- package/esm/src/kernel/engine/turn-trace.js +28 -36
- package/esm/src/kernel/engine/usage.d.ts +6 -0
- package/esm/src/kernel/engine/usage.js +17 -0
- package/esm/src/kernel/interaction-parts.d.ts +3 -0
- package/esm/src/kernel/interaction-parts.js +18 -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 +38 -11
- package/esm/src/kernel/mod.js +22 -7
- package/esm/src/kernel/profile-graph.d.ts +11 -6
- package/esm/src/kernel/profile-graph.js +14 -7
- package/esm/src/kernel/profile-presence.d.ts +10 -1
- package/esm/src/kernel/profile-presence.js +90 -75
- package/esm/src/kernel/profile-scope.d.ts +7 -3
- package/esm/src/kernel/profile-scope.js +67 -55
- 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 +15 -4
- package/esm/src/kernel/registry/attachments.js +31 -22
- package/esm/src/kernel/registry/catalog.d.ts +6 -0
- package/esm/src/kernel/registry/catalog.js +9 -2
- 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 +6 -2
- package/esm/src/kernel/registry/ingress.js +55 -10
- package/esm/src/kernel/registry/kernel-registry.d.ts +3 -0
- package/esm/src/kernel/registry/kernel-registry.js +9 -2
- package/esm/src/kernel/registry/profile-outputs.js +4 -1
- package/esm/src/kernel/registry/profiles.d.ts +38 -14
- package/esm/src/kernel/registry/profiles.js +280 -205
- package/esm/src/kernel/registry/provider-request.d.ts +3 -3
- package/esm/src/kernel/registry/provider-request.js +5 -13
- package/esm/src/kernel/registry/resolve.d.ts +4 -1
- package/esm/src/kernel/registry/resolve.js +59 -58
- package/esm/src/kernel/registry/schemas.d.ts +3 -0
- package/esm/src/kernel/registry/schemas.js +3 -1
- 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/system-prompt.js +7 -8
- package/esm/src/kernel/registry/vault.d.ts +14 -13
- package/esm/src/kernel/registry/vault.js +1 -14
- package/esm/src/kernel/schema.d.ts +100 -46
- package/esm/src/kernel/schema.js +499 -257
- package/esm/src/kernel/scope.d.ts +12 -5
- package/esm/src/kernel/scope.js +23 -3
- package/esm/src/kernel/stages.d.ts +38 -3
- package/esm/src/kernel/stages.js +82 -39
- package/esm/src/kernel/stop.d.ts +29 -6
- package/esm/src/kernel/stop.js +16 -4
- package/esm/src/kernel/system-parts.js +6 -6
- package/esm/src/kernel/tools/activity-label.d.ts +12 -6
- package/esm/src/kernel/tools/activity-label.js +258 -32
- 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 +21 -6
- package/esm/src/kernel/tools/events.js +53 -18
- package/esm/src/kernel/tools/execute.d.ts +47 -11
- package/esm/src/kernel/tools/execute.js +508 -136
- package/esm/src/kernel/tools/gate-answer.d.ts +12 -2
- package/esm/src/kernel/tools/gate-answer.js +17 -6
- 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 +1 -0
- package/esm/src/kernel/tools/harness.js +2 -1
- 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 +27 -5
- package/esm/src/kernel/tools/invoke.js +223 -70
- package/esm/src/kernel/tools/mcp-sessions.d.ts +4 -1
- package/esm/src/kernel/tools/mcp-sessions.js +13 -8
- package/esm/src/kernel/tools/mod.d.ts +4 -3
- package/esm/src/kernel/tools/mod.js +3 -2
- package/esm/src/kernel/tools/model-text.d.ts +10 -5
- package/esm/src/kernel/tools/model-text.js +18 -12
- 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 +11 -2
- package/esm/src/kernel/tools/permission.js +12 -12
- package/esm/src/kernel/tools/project.d.ts +4 -1
- package/esm/src/kernel/tools/project.js +32 -2
- package/esm/src/kernel/tools/registry.d.ts +9 -2
- package/esm/src/kernel/tools/registry.js +69 -10
- package/esm/src/kernel/tools/remote.d.ts +40 -6
- package/esm/src/kernel/tools/remote.js +219 -92
- package/esm/src/kernel/tools/resolve.d.ts +3 -0
- package/esm/src/kernel/tools/resolve.js +12 -4
- 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 +3 -3
- package/esm/src/kernel/tools/schema.js +21 -100
- package/esm/src/kernel/tools/signed-in-fetch.d.ts +2 -1
- package/esm/src/kernel/tools/signed-in-fetch.js +3 -3
- package/esm/src/kernel/tools/stage-run.d.ts +27 -4
- package/esm/src/kernel/tools/stage-run.js +75 -17
- package/esm/src/kernel/tools/types.d.ts +235 -25
- 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 +208 -31
- package/esm/src/kernel/turn-events.js +127 -9
- package/esm/src/kernel/types.d.ts +302 -161
- package/esm/src/kernel/util/base64.d.ts +2 -0
- package/esm/src/kernel/util/base64.js +2 -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 +1 -0
- package/esm/src/kernel/util/record.js +1 -0
- package/esm/src/observability/destinations.d.ts +5 -0
- package/esm/src/observability/destinations.js +7 -2
- package/esm/src/observability/jsonl.d.ts +2 -2
- package/esm/src/observability/jsonl.js +15 -22
- package/esm/src/observability/mod.d.ts +3 -3
- package/esm/src/observability/mod.js +2 -2
- package/esm/src/observability/openinference.d.ts +1 -1
- package/esm/src/observability/openinference.js +3 -3
- package/esm/src/observability/otlp.d.ts +3 -0
- package/esm/src/observability/otlp.js +3 -3
- package/esm/src/observability/phoenix.d.ts +1 -0
- package/esm/src/observability/policy.d.ts +3 -0
- package/esm/src/observability/policy.js +5 -1
- package/esm/src/observability/resolve-policy.js +11 -5
- package/esm/src/observability/spans.d.ts +8 -2
- package/esm/src/observability/spans.js +21 -5
- package/esm/src/observability/trace-catalog.d.ts +19 -2
- package/esm/src/observability/trace-catalog.js +130 -88
- package/esm/src/observability/trace-record.js +22 -17
- package/esm/src/observability/trace-schema.d.ts +3 -0
- package/esm/src/observability/trace-schema.js +1 -1
- package/esm/src/observability/trace-sink.d.ts +1 -0
- package/esm/src/observability/trace-sink.js +1 -1
- package/esm/src/observability/trace-span.d.ts +7 -1
- package/esm/src/observability/trace-span.js +3 -1
- package/esm/src/observability/trace.d.ts +2 -0
- package/esm/src/observability/trace.js +4 -2
- package/esm/src/observability/types.d.ts +35 -11
- package/esm/src/observability/types.js +1 -1
- package/esm/src/presets/google/speech-voices.d.ts +1 -0
- package/esm/src/presets/google-limits.d.ts +1 -0
- package/esm/src/presets/google.d.ts +27 -12
- package/esm/src/presets/google.js +34 -25
- package/esm/src/presets/local.d.ts +26 -0
- package/esm/src/presets/local.js +30 -0
- package/esm/src/presets/mod.d.ts +5 -4
- package/esm/src/presets/mod.js +4 -4
- package/esm/src/presets/openrouter.d.ts +14 -1
- package/esm/src/presets/openrouter.js +19 -1
- 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 +102 -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 +2 -0
- package/esm/src/providers/google/api-error.js +26 -18
- 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 +4 -4
- package/esm/src/providers/google/interactions/framing.d.ts +20 -8
- package/esm/src/providers/google/interactions/framing.js +85 -44
- package/esm/src/providers/google/interactions/steps.d.ts +5 -5
- package/esm/src/providers/google/interactions/steps.js +4 -4
- package/esm/src/providers/google/interactions/stream.d.ts +10 -11
- package/esm/src/providers/google/interactions/stream.js +33 -100
- package/esm/src/providers/google/live/framing.d.ts +15 -5
- package/esm/src/providers/google/live/framing.js +25 -25
- package/esm/src/providers/google/live/stream.d.ts +6 -44
- package/esm/src/providers/google/live/stream.js +4 -210
- package/esm/src/providers/google/urls.d.ts +1 -3
- package/esm/src/providers/google/urls.js +1 -3
- package/esm/src/providers/google/usage.js +2 -2
- 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 +28 -7
- package/esm/src/providers/mod.js +19 -3
- 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 +0 -9
- package/esm/src/providers/openrouter/image.js +0 -153
- 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 +2 -2
- package/esm/src/providers/openrouter/openai/compat.js +6 -6
- package/esm/src/providers/openrouter/openai/image-payload.d.ts +2 -2
- 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/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.js +2 -2
- 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 +2 -2
- package/esm/src/providers/shared/retry.d.ts +18 -0
- package/esm/src/providers/shared/retry.js +89 -0
- package/esm/src/providers/shared/sse.d.ts +0 -4
- package/esm/src/providers/shared/sse.js +50 -36
- package/esm/src/providers/shared/tool-args.d.ts +6 -7
- package/esm/src/providers/shared/tool-args.js +10 -6
- 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 +2 -2
- package/esm/src/providers/shared/upstream-tape.js +1 -1
- 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 +48 -16
- package/esm/src/providers/types.js +2 -1
- 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 +19 -1
- package/esm/src/surface/formats.js +68 -29
- package/esm/src/surface/mod.d.ts +4 -2
- package/esm/src/surface/mod.js +4 -2
- package/esm/src/surface/runtime.d.ts +4 -0
- package/esm/src/surface/runtime.js +2 -0
- package/esm/src/surface/tools.d.ts +2 -8
- package/esm/src/surface/tools.js +4 -22
- package/esm/src/surface/types.d.ts +6 -0
- package/package.json +5 -13
- package/esm/src/cli/commands/egress-compile.d.ts +0 -17
- package/esm/src/cli/commands/egress-compile.js +0 -25
- package/esm/src/guardrails/egress-policy.d.ts +0 -27
- package/esm/src/guardrails/egress-policy.js +0 -76
- package/esm/src/guardrails/egress-rules.d.ts +0 -54
- package/esm/src/guardrails/egress-rules.js +0 -49
- package/esm/src/guardrails/lexicon.d.ts +0 -30
- package/esm/src/guardrails/lexicon.js +0 -478
- package/esm/src/kernel/engine/media-probe/audio.d.ts +0 -7
- package/esm/src/kernel/engine/media-probe/audio.js +0 -342
- package/esm/src/kernel/engine/media-probe/bytes.d.ts +0 -6
- package/esm/src/kernel/engine/media-probe/bytes.js +0 -26
- package/esm/src/kernel/engine/media-probe/image.d.ts +0 -5
- package/esm/src/kernel/engine/media-probe/image.js +0 -171
- package/esm/src/kernel/engine/media-probe/iso-bmff.d.ts +0 -19
- package/esm/src/kernel/engine/media-probe/iso-bmff.js +0 -48
- package/esm/src/kernel/engine/media-probe/matroska.d.ts +0 -35
- package/esm/src/kernel/engine/media-probe/matroska.js +0 -226
- package/esm/src/kernel/engine/media-probe/mp4.d.ts +0 -22
- package/esm/src/kernel/engine/media-probe/mp4.js +0 -279
- package/esm/src/kernel/engine/media-probe/opus.d.ts +0 -4
- package/esm/src/kernel/engine/media-probe/opus.js +0 -23
- package/esm/src/kernel/engine/media-probe/pdf.d.ts +0 -5
- package/esm/src/kernel/engine/media-probe/pdf.js +0 -117
- package/esm/src/kernel/engine/media-probe/video.d.ts +0 -15
- package/esm/src/kernel/engine/media-probe/video.js +0 -49
- package/esm/src/presets/typesafe.d.ts +0 -2
- package/esm/src/presets/typesafe.js +0 -2
- package/esm/src/providers/create-provider.d.ts +0 -21
- package/esm/src/providers/create-provider.js +0 -90
- package/esm/src/providers/decision/usage.d.ts +0 -3
- package/esm/src/providers/decision/usage.js +0 -25
- package/esm/src/providers/google/interactions/mod.d.ts +0 -2
- package/esm/src/providers/google/interactions/mod.js +0 -2
- package/esm/src/providers/google/keys.d.ts +0 -20
- package/esm/src/providers/google/keys.js +0 -87
- package/esm/src/providers/google/live/mod.d.ts +0 -7
- package/esm/src/providers/google/live/mod.js +0 -7
- package/esm/src/providers/google/live/openapi-schema.d.ts +0 -1
- package/esm/src/providers/google/live/openapi-schema.js +0 -42
- package/esm/src/providers/google/live/session.d.ts +0 -14
- package/esm/src/providers/google/live/session.js +0 -150
- package/esm/src/providers/local/local.d.ts +0 -12
- package/esm/src/providers/local/local.js +0 -186
- package/esm/src/providers/local/mod.d.ts +0 -8
- package/esm/src/providers/local/mod.js +0 -8
- package/esm/src/providers/openrouter/cache-control.d.ts +0 -5
- package/esm/src/providers/openrouter/cache-control.js +0 -4
- package/esm/src/providers/openrouter/chat.d.ts +0 -64
- package/esm/src/providers/openrouter/chat.js +0 -490
- package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +0 -10
- package/esm/src/providers/openrouter/openai/sdk-messages.js +0 -99
- package/esm/src/providers/openrouter/resolve-api-key.d.ts +0 -3
- package/esm/src/providers/openrouter/resolve-api-key.js +0 -8
- package/esm/src/providers/openrouter/speech.d.ts +0 -18
- package/esm/src/providers/openrouter/speech.js +0 -109
- package/esm/src/providers/probe.d.ts +0 -5
- package/esm/src/providers/probe.js +0 -15
- package/esm/src/providers/shared/builtin-wire.d.ts +0 -4
- package/esm/src/providers/shared/builtin-wire.js +0 -9
- package/esm/src/providers/shared/vault.d.ts +0 -13
- package/esm/src/providers/shared/vault.js +0 -41
package/esm/src/kernel/schema.js
CHANGED
|
@@ -3,15 +3,27 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
|
-
/**
|
|
6
|
+
/** labels-exempt-file: authoring field-meta / closed unions — not runtime user or model copy (P2) */
|
|
7
7
|
import "../../_dnt.polyfills.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { BOUNDARIES, BOUNDARY_META, recordOf } from '../guardrails/boundaries.js';
|
|
9
|
+
import { DETECT_ACTION_META, DETECT_ACTIONS, DETECT_DEFAULTS, DETECTOR_BOUNDARIES, DETECTOR_META, DETECTORS, } from '../guardrails/detectors.js';
|
|
10
|
+
import { LABEL_NOTES } from '../guardrails/labels.js';
|
|
11
|
+
import { BLOCKED_REPLY_ON_BLOCK, DESTINATION_GATES, TAINT_GATES, } from '../guardrails/types.js';
|
|
10
12
|
import { GOOGLE_SPEECH_VOICES } from '../presets/google/speech-voices.js';
|
|
11
13
|
import { PROFILE_FIELD_PRESENCE } from './profile-presence.js';
|
|
12
|
-
import { profileFieldScope } from './profile-scope.js';
|
|
13
|
-
export {
|
|
14
|
-
|
|
14
|
+
import { isProfileRootField, profileFieldScope } from './profile-scope.js';
|
|
15
|
+
export { BLOCKED_REPLY_ON_BLOCK };
|
|
16
|
+
/** The kinds of profile: each fixes which fields and models a profile may use. */
|
|
17
|
+
export const PROFILE_TYPES = [
|
|
18
|
+
'text',
|
|
19
|
+
'image',
|
|
20
|
+
'speech',
|
|
21
|
+
'live',
|
|
22
|
+
'decision',
|
|
23
|
+
'embedding',
|
|
24
|
+
'host',
|
|
25
|
+
];
|
|
26
|
+
/** Reasoning effort levels, lowest to highest; a model accepts only the levels its catalog row lists. */
|
|
15
27
|
export const THINKING_LEVELS = [
|
|
16
28
|
'none',
|
|
17
29
|
'minimal',
|
|
@@ -21,45 +33,40 @@ export const THINKING_LEVELS = [
|
|
|
21
33
|
'xhigh',
|
|
22
34
|
'max',
|
|
23
35
|
];
|
|
24
|
-
|
|
25
|
-
export const
|
|
26
|
-
/**
|
|
27
|
-
export const
|
|
28
|
-
|
|
29
|
-
geminiLive: ['google'],
|
|
30
|
-
openAi: ['openrouter', 'local'],
|
|
31
|
-
decision: ['typesafe', 'openrouter'],
|
|
32
|
-
};
|
|
33
|
-
export const PROFILE_TYPE_PROTOCOLS = {
|
|
34
|
-
text: ['geminiInteractions', 'openAi'],
|
|
35
|
-
image: ['geminiInteractions', 'openAi'],
|
|
36
|
-
speech: ['geminiInteractions', 'openAi'],
|
|
37
|
-
live: ['geminiLive'],
|
|
38
|
-
decision: ['decision'],
|
|
39
|
-
host: [],
|
|
40
|
-
};
|
|
41
|
-
export function protocolsForProfileType(type) {
|
|
42
|
-
return PROFILE_TYPE_PROTOCOLS[type];
|
|
43
|
-
}
|
|
44
|
-
export function isValidProfileProtocol(type, protocol) {
|
|
45
|
-
return PROFILE_TYPE_PROTOCOLS[type].includes(protocol);
|
|
46
|
-
}
|
|
47
|
-
/** Letters, digits, `-` and `_`, up to 32 characters, starting with a letter or digit. */
|
|
36
|
+
/** The longest a profile's `id` may be, in characters: room for a dotted or generated one. */
|
|
37
|
+
export const PROFILE_ID_MAX_CHARS = 64;
|
|
38
|
+
/** The longest a profile's `identity.handle` may be, in characters: it is a name people read. */
|
|
39
|
+
export const PROFILE_HANDLE_MAX_CHARS = 32;
|
|
40
|
+
/** Letters, digits, `-`, and `_`, up to 32 characters, starting with a letter or digit. */
|
|
48
41
|
export const KEY_SLOT_NAME = /^[A-Za-z0-9][A-Za-z0-9_-]{0,31}$/;
|
|
42
|
+
/** True when the value is a legal key slot name. */
|
|
49
43
|
export function isKeySlotName(value) {
|
|
50
44
|
return typeof value === 'string' && KEY_SLOT_NAME.test(value);
|
|
51
45
|
}
|
|
46
|
+
/** The kinds of media a model can take as input. */
|
|
52
47
|
export const MEDIA_INPUT_KIND_VALUES = ['image', 'audio', 'video', 'document'];
|
|
48
|
+
/** Whether thought summaries are asked for (`auto`) or not (`none`). */
|
|
53
49
|
export const SUMMARY_MODES = ['auto', 'none'];
|
|
50
|
+
/** Whether the provider call streams (`sse`) or is one buffered call. */
|
|
54
51
|
export const STREAM_MODES = ['sse', 'buffered'];
|
|
52
|
+
/** Audio encodings a speech profile can return. */
|
|
55
53
|
export const SPEECH_AUDIO_FORMATS = ['pcm', 'mp3'];
|
|
54
|
+
/** Who can send a turn its context: the browser, or the host's own code. */
|
|
55
|
+
/** How long a caller is away, in milliseconds, before `live.resumed.prompt` is sent, when the profile sets no `afterMs`. */
|
|
56
|
+
export const DEFAULT_RESUMED_AFTER_MS = 3000;
|
|
57
|
+
export const CONTEXT_SENDERS = ['client', 'server'];
|
|
58
|
+
/** What the user starting to speak does to a live model that is mid-reply. */
|
|
56
59
|
export const LIVE_ACTIVITY_HANDLINGS = ['START_OF_ACTIVITY_INTERRUPTS', 'NO_INTERRUPTION'];
|
|
60
|
+
/** How readily live voice detection decides the user has started speaking. */
|
|
57
61
|
export const LIVE_START_SENSITIVITIES = [
|
|
58
62
|
'START_SENSITIVITY_LOW',
|
|
59
63
|
'START_SENSITIVITY_HIGH',
|
|
60
64
|
];
|
|
65
|
+
/** How readily live voice detection decides the user has stopped speaking. */
|
|
61
66
|
export const LIVE_END_SENSITIVITIES = ['END_SENSITIVITY_LOW', 'END_SENSITIVITY_HIGH'];
|
|
67
|
+
/** What compaction counts against its token limit: the stored history or the next request's input. */
|
|
62
68
|
export const COMPACTION_METERS = ['history', 'input'];
|
|
69
|
+
/** Whether compaction runs before or after a turn. */
|
|
63
70
|
export const COMPACTION_TIMINGS = ['before', 'after'];
|
|
64
71
|
/**
|
|
65
72
|
* - `compacted`: a summary replaced the compacted messages.
|
|
@@ -67,8 +74,11 @@ export const COMPACTION_TIMINGS = ['before', 'after'];
|
|
|
67
74
|
* - `dropped`: the compactor failed over `maxTokens`, so the compacted messages were dropped.
|
|
68
75
|
*/
|
|
69
76
|
export const COMPACTION_OUTCOMES = ['compacted', 'deferred', 'dropped'];
|
|
77
|
+
/** Which part of the prompt is cached: the whole request (`automatic`) or the system instruction only (`system`). */
|
|
70
78
|
export const CACHE_MODES = ['automatic', 'system'];
|
|
79
|
+
/** How long a provider keeps a cached prompt. */
|
|
71
80
|
export const CACHE_TTLS = ['5m', '1h'];
|
|
81
|
+
/** Why a turn stopped, as `done.stop.kind` reports it. */
|
|
72
82
|
export const TURN_STOP_KINDS = [
|
|
73
83
|
'completed',
|
|
74
84
|
'length',
|
|
@@ -80,12 +90,19 @@ export const TURN_STOP_KINDS = [
|
|
|
80
90
|
'provider_error',
|
|
81
91
|
'cancelled',
|
|
82
92
|
'stream_incomplete',
|
|
93
|
+
/** The turn made its last allowed model call and that call asked for tools: there is no answer. */
|
|
94
|
+
'step_limit',
|
|
83
95
|
'interrupted',
|
|
84
96
|
/** Live: model finished generating audio/text for this utterance; turn may still be open. */
|
|
85
97
|
'generation_complete',
|
|
86
98
|
];
|
|
99
|
+
/** What a text turn's last allowed model call may do, as `turnBehaviour.atStepLimit` sets it. */
|
|
100
|
+
export const STEP_LIMIT_MODES = ['stop', 'answer'];
|
|
101
|
+
/** What happens to a list item its check refuses, as `outputs.validation.items.*.onFail` sets it. */
|
|
102
|
+
export const ITEM_FAIL_ACTIONS = ['drop', 'fix'];
|
|
87
103
|
/** Every other stop resumes by another host path, or not at all. */
|
|
88
104
|
export const CONTINUE_STOP_KINDS = ['length', 'stream_incomplete', 'provider_error'];
|
|
105
|
+
/** The points in a turn where a stage handler runs. */
|
|
89
106
|
export const TURN_STAGES = [
|
|
90
107
|
'pre_turn',
|
|
91
108
|
'pre_tool',
|
|
@@ -94,24 +111,29 @@ export const TURN_STAGES = [
|
|
|
94
111
|
'post_turn',
|
|
95
112
|
];
|
|
96
113
|
const TURN_STAGE_SET = new Set(TURN_STAGES);
|
|
114
|
+
/** True when the value names a turn stage. */
|
|
97
115
|
export function isTurnStage(value) {
|
|
98
116
|
return typeof value === 'string' && TURN_STAGE_SET.has(value);
|
|
99
117
|
}
|
|
100
118
|
/** Stages where an inject can land; the inject gate still applies. */
|
|
101
119
|
export const TURN_INJECT_STAGES = ['pre_turn', 'post_tool', 'before_end'];
|
|
102
120
|
const TURN_INJECT_STAGE_SET = new Set(TURN_INJECT_STAGES);
|
|
121
|
+
/** True when the value names a stage an inject can land in. */
|
|
103
122
|
export function isTurnInjectStage(value) {
|
|
104
123
|
return typeof value === 'string' && TURN_INJECT_STAGE_SET.has(value);
|
|
105
124
|
}
|
|
106
|
-
/** `pre_tool` gates; not `awaiting_user_input`. */
|
|
107
|
-
export const TOOL_GATE_KINDS = ['confirmation', 'permission', 'auth'];
|
|
125
|
+
/** `pre_tool` gates; not `awaiting_user_input`. `page` holds a call for the page that answers it. */
|
|
126
|
+
export const TOOL_GATE_KINDS = ['confirmation', 'permission', 'auth', 'page'];
|
|
108
127
|
/** Why a refused gate settles: the user said no, walked away, or let it run out. */
|
|
109
128
|
export const TOOL_RESUME_CAUSES = ['declined', 'abandoned', 'expired'];
|
|
110
129
|
const TOOL_GATE_KIND_SET = new Set(TOOL_GATE_KINDS);
|
|
130
|
+
/** True when the value names a tool gate kind. */
|
|
111
131
|
export function isToolGateKind(value) {
|
|
112
132
|
return typeof value === 'string' && TOOL_GATE_KIND_SET.has(value);
|
|
113
133
|
}
|
|
134
|
+
/** The questions a turn can pause to ask the user. */
|
|
114
135
|
export const AWAITING_USER_INPUT_KINDS = ['confirm', 'choice', 'text'];
|
|
136
|
+
/** Why a stage handler's result was partly or wholly ignored. */
|
|
115
137
|
export const STAGE_APPLY_WARNING_CODES = [
|
|
116
138
|
'affordance_not_allowed',
|
|
117
139
|
'inject_not_allowed',
|
|
@@ -121,22 +143,30 @@ export const STAGE_APPLY_WARNING_CODES = [
|
|
|
121
143
|
'deny_invalid',
|
|
122
144
|
'confirm_invalid',
|
|
123
145
|
'mutate_invalid',
|
|
146
|
+
'label_failed_invalid',
|
|
124
147
|
'abort_invalid',
|
|
148
|
+
'wait_for_invalid',
|
|
125
149
|
'unknown_field',
|
|
126
150
|
'result_invalid',
|
|
127
151
|
];
|
|
152
|
+
/** The `status` of a tool output that asks the user a question. */
|
|
128
153
|
export const AWAITING_USER_INPUT_STATUS = 'awaiting_user_input';
|
|
129
154
|
/** Enforced by the kernel at resolve time. */
|
|
130
|
-
export const TOOL_LOAD_TIERS = ['T0', '
|
|
155
|
+
export const TOOL_LOAD_TIERS = ['T0', 'T2'];
|
|
156
|
+
/** The HTTP methods an `http` tool may use. */
|
|
131
157
|
export const HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
|
|
132
158
|
/** When remote tool auth is missing or expired. */
|
|
133
|
-
export const AUTH_UNAUTHENTICATED_POLICIES = ['gate', 'report_to_model'];
|
|
134
|
-
|
|
159
|
+
export const AUTH_UNAUTHENTICATED_POLICIES = ['gate', 'report_to_model', 'fail'];
|
|
160
|
+
/** The kinds of tool a profile can list. */
|
|
161
|
+
export const TOOL_TYPES = ['builtin', 'function', 'http', 'mcp', 'agent'];
|
|
162
|
+
/** How much a tool can change: nothing, data, or irreversibly. */
|
|
135
163
|
export const TOOL_ACCESS = ['read-only', 'read-write', 'destructive'];
|
|
164
|
+
/** When the user must approve a tool call: never, once per session, or every call. */
|
|
136
165
|
export const TOOL_PERMISSION = ['auto', 'session_consent', 'always_confirm'];
|
|
166
|
+
/** The credential shapes a remote tool can authenticate with. */
|
|
137
167
|
export const TOOL_AUTH_TYPES = ['bearer', 'api_key', 'oauth2'];
|
|
138
168
|
/** Adds UI-only `none`, which omits auth at compile time. */
|
|
139
|
-
export const
|
|
169
|
+
export const STUDIO_AUTH_TYPES = ['none', ...TOOL_AUTH_TYPES];
|
|
140
170
|
/**
|
|
141
171
|
* The package's complete media-input vocabulary: `assertMediaMime` refuses any MIME not
|
|
142
172
|
* here, so hosts keep no second table. Rows follow Google Interactions / Live's documented
|
|
@@ -200,6 +230,7 @@ export const MEDIA_WILDCARDS = ['image/*', 'audio/*', 'video/*'];
|
|
|
200
230
|
function mimesOf(kind) {
|
|
201
231
|
return Object.keys(MEDIA_INPUT_KINDS).filter((mime) => MEDIA_INPUT_KINDS[mime] === kind);
|
|
202
232
|
}
|
|
233
|
+
/** The MIME types a text profile's `accept` entries may list. */
|
|
203
234
|
export const ATTACHMENT_ACCEPT_MIMES = [
|
|
204
235
|
'image/*',
|
|
205
236
|
'video/*',
|
|
@@ -219,35 +250,8 @@ export const IMAGE_ATTACHMENT_ACCEPT_MIMES = [
|
|
|
219
250
|
...mimesOf('video'),
|
|
220
251
|
'application/pdf',
|
|
221
252
|
];
|
|
253
|
+
/** The MIME types a voice profile's `accept` entries may list. */
|
|
222
254
|
export const VOICE_ACCEPT_MIMES = ['audio/*', ...mimesOf('audio')];
|
|
223
|
-
export function providersFor(protocol) {
|
|
224
|
-
return PROTOCOL_PROVIDERS[protocol];
|
|
225
|
-
}
|
|
226
|
-
export function protocolsFor(provider) {
|
|
227
|
-
const found = [];
|
|
228
|
-
for (const protocol of PROTOCOLS) {
|
|
229
|
-
if (PROTOCOL_PROVIDERS[protocol].includes(provider)) {
|
|
230
|
-
found.push(protocol);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
return found;
|
|
234
|
-
}
|
|
235
|
-
/** True when `createProvider` will accept this pair. */
|
|
236
|
-
export function isValidPair(protocol, provider) {
|
|
237
|
-
return PROTOCOL_PROVIDERS[protocol].includes(provider);
|
|
238
|
-
}
|
|
239
|
-
/** When protocol changes, snap provider to a valid partner. */
|
|
240
|
-
export function coerceProvider(protocol, provider) {
|
|
241
|
-
const allowed = providersFor(protocol);
|
|
242
|
-
const [first] = allowed;
|
|
243
|
-
return allowed.includes(provider) ? provider : first;
|
|
244
|
-
}
|
|
245
|
-
/** When provider changes, snap protocol to a valid partner. */
|
|
246
|
-
export function coerceProtocol(protocol, provider) {
|
|
247
|
-
const allowed = protocolsFor(provider);
|
|
248
|
-
const [first] = allowed;
|
|
249
|
-
return allowed.includes(protocol) ? protocol : first;
|
|
250
|
-
}
|
|
251
255
|
function unionType(values) {
|
|
252
256
|
return values.map((value) => `'${value}'`).join(' | ');
|
|
253
257
|
}
|
|
@@ -273,12 +277,17 @@ export const DYNAMIC_FIELD_PARENTS = new Set([
|
|
|
273
277
|
'models',
|
|
274
278
|
'models.*.efforts',
|
|
275
279
|
'identity.systemByRole',
|
|
276
|
-
'
|
|
280
|
+
'labels',
|
|
277
281
|
'inputs.slots',
|
|
278
282
|
'inputs.limitsByMime',
|
|
279
283
|
'outputs.validation.fields',
|
|
284
|
+
'outputs.validation.items',
|
|
280
285
|
]);
|
|
286
|
+
/** Turns a key path into its catalog path, replacing host-chosen map keys with `*`. */
|
|
281
287
|
export function catalogPathFor(keys) {
|
|
288
|
+
const [first] = keys;
|
|
289
|
+
if (keys.length === 1 && first !== undefined && isProfileRootField(first))
|
|
290
|
+
return `profile.${first}`;
|
|
282
291
|
const resolved = [];
|
|
283
292
|
for (const key of keys) {
|
|
284
293
|
const prefix = resolved.join('.');
|
|
@@ -291,6 +300,181 @@ export function catalogPathFor(keys) {
|
|
|
291
300
|
}
|
|
292
301
|
return resolved.join('.');
|
|
293
302
|
}
|
|
303
|
+
const DETECT_ACTION_DOCS = recordOf(DETECT_ACTIONS, (action) => DETECT_ACTION_META[action].doc);
|
|
304
|
+
/** The `allow` rows of a detector: the URLs it lets through, or for `tool_leak` the names. */
|
|
305
|
+
function allowFields(path, detector) {
|
|
306
|
+
if (DETECTOR_META[detector].allow === 'names') {
|
|
307
|
+
return [
|
|
308
|
+
[`${path}.allow`, field('NameAllow', 'The names that are innocent in a reply.')],
|
|
309
|
+
[
|
|
310
|
+
`${path}.allow.names`,
|
|
311
|
+
{
|
|
312
|
+
...field('string[]', 'Names of tools or parameters that are not read for, such as a tool called search.'),
|
|
313
|
+
unset: 'None',
|
|
314
|
+
},
|
|
315
|
+
],
|
|
316
|
+
];
|
|
317
|
+
}
|
|
318
|
+
const hosts = detector === 'ungiven_links'
|
|
319
|
+
? 'Hostnames whose links pass whatever their URL; the hosts ungiven_images allows pass too.'
|
|
320
|
+
: 'Hostnames whose images load whatever their URL, such as your own CDN.';
|
|
321
|
+
return [
|
|
322
|
+
[
|
|
323
|
+
`${path}.allow`,
|
|
324
|
+
field('UrlAllow', 'What passes besides the URLs the model was given this turn.'),
|
|
325
|
+
],
|
|
326
|
+
[`${path}.allow.hosts`, { ...field('string[]', hosts), unset: 'None' }],
|
|
327
|
+
[
|
|
328
|
+
`${path}.allow.fromTools`,
|
|
329
|
+
{
|
|
330
|
+
...field('boolean', 'Whether a URL a tool returned counts as given. Off keeps only what the system prompt, the user, and history gave.'),
|
|
331
|
+
unset: 'On',
|
|
332
|
+
},
|
|
333
|
+
],
|
|
334
|
+
];
|
|
335
|
+
}
|
|
336
|
+
const COMPILED_DOC = 'The table your patterns compile to, from compileDetect or `agents detect-compile`. Needed whenever patterns is set.';
|
|
337
|
+
/** The rows of one pattern in a detector's `patterns`. */
|
|
338
|
+
function patternRows(path) {
|
|
339
|
+
const each = `${path}.patterns.*`;
|
|
340
|
+
return [
|
|
341
|
+
[`${each}.name`, field('string', 'What a match is called in the trace.')],
|
|
342
|
+
[
|
|
343
|
+
`${each}.pattern`,
|
|
344
|
+
field('string', 'The source of a regular expression. A pattern takes this or words.'),
|
|
345
|
+
],
|
|
346
|
+
[
|
|
347
|
+
`${each}.flags`,
|
|
348
|
+
{
|
|
349
|
+
...field('string', 'Regular-expression flags, each a letter: i ignores case, m matches ^ and $ at each line, s lets . match a line break, u reads Unicode. Not g or y: every match is always found.'),
|
|
350
|
+
unset: 'None',
|
|
351
|
+
},
|
|
352
|
+
],
|
|
353
|
+
[
|
|
354
|
+
`${each}.words`,
|
|
355
|
+
field('string[]', 'Words to match whole, whatever their case. A space in one matches any run of whitespace.'),
|
|
356
|
+
],
|
|
357
|
+
];
|
|
358
|
+
}
|
|
359
|
+
/** The rows of a detector of the host's own, under a key with a dot. */
|
|
360
|
+
function hostDetectorFields(path) {
|
|
361
|
+
const action = (doc) => field('DetectAction', doc, DETECT_ACTIONS, DETECT_ACTION_DOCS);
|
|
362
|
+
return [
|
|
363
|
+
[
|
|
364
|
+
path,
|
|
365
|
+
field('HostDetectorConfig', 'Your own detector, keyed with a dot: acme.codenames. No default action.'),
|
|
366
|
+
],
|
|
367
|
+
[`${path}.label`, field('string', 'What an editor and the trace call it.')],
|
|
368
|
+
[
|
|
369
|
+
`${path}.action`,
|
|
370
|
+
{
|
|
371
|
+
...action('What a match does, at every boundary.'),
|
|
372
|
+
unset: 'Only the boundaries at names are read',
|
|
373
|
+
},
|
|
374
|
+
],
|
|
375
|
+
[`${path}.at`, field('{ [boundary]: DetectAction }', 'An action per boundary, over action.')],
|
|
376
|
+
...BOUNDARIES.map((boundary) => [
|
|
377
|
+
`${path}.at.${boundary}`,
|
|
378
|
+
{ ...action(BOUNDARY_META[boundary].doc), unset: DETECT_ACTION_META.ignore.label },
|
|
379
|
+
]),
|
|
380
|
+
[
|
|
381
|
+
`${path}.patterns`,
|
|
382
|
+
{
|
|
383
|
+
...field('HostPattern[]', 'Its patterns, each a name and a regular expression or a list of words, read on the text as written.'),
|
|
384
|
+
unset: 'None',
|
|
385
|
+
},
|
|
386
|
+
],
|
|
387
|
+
...patternRows(path),
|
|
388
|
+
[`${path}.compiled`, field('CompiledPatterns', COMPILED_DOC)],
|
|
389
|
+
[
|
|
390
|
+
`${path}.hint`,
|
|
391
|
+
{
|
|
392
|
+
...field('string', 'One line telling the model what to leave out, sent when this detector blocks a reply that is then retried.'),
|
|
393
|
+
unset: 'The labels’s detect.hint.own, which names the label',
|
|
394
|
+
},
|
|
395
|
+
],
|
|
396
|
+
[
|
|
397
|
+
`${path}.find`,
|
|
398
|
+
field('HostFind', 'Its own reading, for what patterns cannot say: a function that returns where the matches start and end. It runs on every text crossing a boundary the detector reads, so it returns at once.'),
|
|
399
|
+
],
|
|
400
|
+
];
|
|
401
|
+
}
|
|
402
|
+
/** The rows of a detector that reads with patterns: whose it reads with. */
|
|
403
|
+
function patternFields(path) {
|
|
404
|
+
return [
|
|
405
|
+
[
|
|
406
|
+
`${path}.theorem`,
|
|
407
|
+
{
|
|
408
|
+
...field('boolean', 'Whether Theorem’s own patterns run. Off with no patterns of your own turns the detector off.'),
|
|
409
|
+
unset: 'On',
|
|
410
|
+
},
|
|
411
|
+
],
|
|
412
|
+
[
|
|
413
|
+
`${path}.patterns`,
|
|
414
|
+
{
|
|
415
|
+
...field('HostPattern[]', 'Your own patterns, each a name and a regular expression or a list of words. A match takes this detector’s action.'),
|
|
416
|
+
unset: 'None',
|
|
417
|
+
},
|
|
418
|
+
],
|
|
419
|
+
...patternRows(path),
|
|
420
|
+
[`${path}.compiled`, field('CompiledPatterns', COMPILED_DOC)],
|
|
421
|
+
[
|
|
422
|
+
`${path}.hint`,
|
|
423
|
+
{
|
|
424
|
+
...field('string', 'One line telling the model what to leave out, sent when this detector blocks a reply that is then retried. Set it beside patterns of your own.'),
|
|
425
|
+
unset: `The labels’s detect.hint line for this detector`,
|
|
426
|
+
},
|
|
427
|
+
],
|
|
428
|
+
];
|
|
429
|
+
}
|
|
430
|
+
/** The settings a detector's full form takes, as a sentence lists them. */
|
|
431
|
+
function settingsOf(detector) {
|
|
432
|
+
const { allow, patterns } = DETECTOR_META[detector];
|
|
433
|
+
if (allow && patterns)
|
|
434
|
+
return 'action, at, allow, theorem, patterns, and hint';
|
|
435
|
+
if (allow)
|
|
436
|
+
return 'action, at, and allow';
|
|
437
|
+
return patterns ? 'action, at, theorem, patterns, and hint' : 'action and at';
|
|
438
|
+
}
|
|
439
|
+
/** The `guardrails.detect` rows: one for the setting, one per detector, and one per detector and boundary. */
|
|
440
|
+
function detectFields() {
|
|
441
|
+
const action = (type, doc) => field(type, doc, DETECT_ACTIONS, DETECT_ACTION_DOCS);
|
|
442
|
+
const rows = [
|
|
443
|
+
[
|
|
444
|
+
'guardrails.detect',
|
|
445
|
+
action('DetectAction | { [detector]: DetectorRule }', 'What a guardrail does when a detector matches. One action covers every detector; an object sets each detector (or one of your own) apart. Absent: each detector keeps its default action.'),
|
|
446
|
+
],
|
|
447
|
+
];
|
|
448
|
+
for (const detector of DETECTORS) {
|
|
449
|
+
const path = `guardrails.detect.${detector}`;
|
|
450
|
+
rows.push([
|
|
451
|
+
path,
|
|
452
|
+
action('DetectAction | DetectorConfig', `${DETECTOR_META[detector].doc} Set one action, or ${settingsOf(detector)}.`),
|
|
453
|
+
]);
|
|
454
|
+
if (DETECTOR_META[detector].allow)
|
|
455
|
+
rows.push(...allowFields(path, detector));
|
|
456
|
+
if (DETECTOR_META[detector].patterns)
|
|
457
|
+
rows.push(...patternFields(path));
|
|
458
|
+
rows.push([
|
|
459
|
+
`${path}.action`,
|
|
460
|
+
{
|
|
461
|
+
...action('DetectAction', 'What a match of this detector does at every boundary it reads, unless `at` names that boundary.'),
|
|
462
|
+
unset: 'Each boundary keeps its default',
|
|
463
|
+
},
|
|
464
|
+
]);
|
|
465
|
+
rows.push([
|
|
466
|
+
`${path}.at`,
|
|
467
|
+
field('{ [boundary]: DetectAction }', 'An action per boundary, over action or the default.'),
|
|
468
|
+
]);
|
|
469
|
+
for (const boundary of DETECTOR_BOUNDARIES[detector]) {
|
|
470
|
+
const unset = DETECT_ACTION_META[DETECT_DEFAULTS[detector][boundary]].label;
|
|
471
|
+
const meta = action('DetectAction', BOUNDARY_META[boundary].doc);
|
|
472
|
+
rows.push([`${path}.at.${boundary}`, { ...meta, unset }]);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
rows.push(...hostDetectorFields('guardrails.detect.*'));
|
|
476
|
+
return Object.fromEntries(rows);
|
|
477
|
+
}
|
|
294
478
|
function withScopeAndPresence(fields) {
|
|
295
479
|
return Object.fromEntries(Object.entries(fields).map(([path, meta]) => {
|
|
296
480
|
const scope = profileFieldScope(path);
|
|
@@ -309,61 +493,59 @@ function withScopeAndPresence(fields) {
|
|
|
309
493
|
* take it, and record it in `PROFILE_FIELD_PRESENCE` if it is required or its absence matters.
|
|
310
494
|
*/
|
|
311
495
|
export const PROFILE_FIELDS = withScopeAndPresence({
|
|
312
|
-
id: field('string', 'The name this profile is registered and looked up by; registering the same id again replaces it.'),
|
|
313
|
-
type: field("'text' | 'image' | 'speech' | 'live' | 'decision' | 'host'", 'What kind of agent this is, and so what each call gives back: text, image, speech, live, decision or host.', PROFILE_TYPES, {
|
|
496
|
+
'profile.id': field('string', 'The name this profile is registered and looked up by, at most 64 characters; registering the same id again replaces it.'),
|
|
497
|
+
'profile.type': field("'text' | 'image' | 'speech' | 'live' | 'decision' | 'embedding' | 'host'", 'What kind of agent this is, and so what each call gives back: text, image, speech, live, decision, embedding, or host.', PROFILE_TYPES, {
|
|
314
498
|
text: 'A chat or task agent. Each turn the model answers in text, or in JSON when outputs ask for a structured reply, and can call tools on the way.',
|
|
315
|
-
image: 'Makes pictures from a prompt, in the shape, size and format the image block sets.',
|
|
499
|
+
image: 'Makes pictures from a prompt, in the shape, size, and format the image block sets.',
|
|
316
500
|
speech: 'Gives your app a voice. Each turn reads text aloud in the voice the speech block names.',
|
|
317
|
-
live: 'For talking in real time. One continuous voice and video session
|
|
318
|
-
decision: 'For when your app needs a judgement, not a reply. It answers questions about a JSON state, each with a choice, a score or a number.',
|
|
319
|
-
|
|
501
|
+
live: 'For talking in real time. One continuous voice and video session, rather than separate turns.',
|
|
502
|
+
decision: 'For when your app needs a judgement, not a reply. It answers questions about a JSON state, each with a choice, a score, or a number.',
|
|
503
|
+
embedding: 'For when your app needs vectors from text or provider-supported media.',
|
|
504
|
+
host: 'A governed passthrough to your tool registry, with no model. It calls MCP, HTTP, and in-app function tools under the same permissions and traces as any agent, guarded by detect and network.',
|
|
320
505
|
}),
|
|
321
506
|
identity: field('{ handle, system?, systemByRole? }', "The agent's display name and the system instruction it is given."),
|
|
322
|
-
'identity.handle': field('string',
|
|
323
|
-
'identity.system': field('string | Array<string | { private: string }>', 'The instruction the model gets on every turn unless a systemByRole entry replaces it;
|
|
507
|
+
'identity.handle': field('string', 'The name hosts and users see for this agent, at most 32 characters; the model never sees it. It is also the role a turn gets when it names none, so identity.systemByRole may hold an entry under it.'),
|
|
508
|
+
'identity.system': field('string | Array<string | { private: string }>', 'The instruction the model gets on every turn unless a systemByRole entry replaces it; some providers send it for an image profile only with includeText on. Mark what must not leak as { private: text }; only that is guarded. With none, the whole prompt is.'),
|
|
324
509
|
'identity.systemByRole': field('Record<string, string | Array<string | { private: string }>>', 'Other system instructions, picked by the role a turn names.'),
|
|
325
510
|
'identity.systemByRole.*': field('string | Array<string | { private: string }>', 'The instruction that replaces identity.system when a turn names this role.'),
|
|
326
|
-
models: field('Record<ModelId, ModelBinding | DecisionModelBinding>', 'The
|
|
511
|
+
models: field('Record<ModelId, ModelBinding | DecisionModelBinding>', 'The trained AI systems that turn input into results. Each entry binds a local name to an upstream model and its call settings.'),
|
|
327
512
|
'models.*': field('ModelBinding | DecisionModelBinding', 'One model: how to reach it and the settings sent with it.'),
|
|
328
|
-
'models.*.protocol': field(
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
'
|
|
335
|
-
|
|
336
|
-
openrouter: 'OpenRouter, which routes to many model vendors.',
|
|
337
|
-
local: "A server you run (Ollama, llama.cpp, vLLM); it can't serve image profiles.",
|
|
338
|
-
typesafe: 'TypeSafe, serving its native decision models.',
|
|
339
|
-
}),
|
|
340
|
-
'models.*.apiId': field('string', "The model's name at the provider."),
|
|
513
|
+
'models.*.protocol': field('string', 'The API shape this model is spoken to in.'),
|
|
514
|
+
'models.*.provider': field('string', 'The service that runs the model or routes requests to one, such as Gemini or OpenRouter. Its registration supplies the endpoint and authentication.'),
|
|
515
|
+
'models.*.keySlot': field('KeySlot', "The key slot this model's calls are signed with, instead of the provider's. Use it to bill one model to a different key. Absent: the provider's primary slot."),
|
|
516
|
+
'models.*.fallbackKeySlot': field('KeySlot', "The key slot tried once after a rate limit or a busy model on the primary slot, instead of the provider's fallback. Must differ from the primary slot. Absent: the provider's fallback slot, if it has one."),
|
|
517
|
+
'models.*.options': field('JsonObject', "Settings only this model's protocol has, such as a task type or vector size. Each is checked when the profile loads. Any left out keep the provider's default."),
|
|
518
|
+
providerContinuation: field('ProviderContinuationPolicy', 'Who holds the conversation a saved provider state continues.'),
|
|
519
|
+
'providerContinuation.history': field("'host' | 'stateless' | 'provider'", 'Who holds the conversation a checkpoint continues: the host passes history back, the provider keeps it and the checkpoint travels alone, or the profile is stateless and every request stands alone.', ['host', 'stateless', 'provider']),
|
|
520
|
+
'models.*.apiId': field('string', "The model's id as the provider lists it, such as gemini-2.5-flash; sent on every call. The name this model has in the profile is its key in models."),
|
|
341
521
|
'models.*.timeoutMs': field('number', 'How long a decision waits for its provider, in milliseconds. Omit for no timeout.'),
|
|
342
522
|
decision: field('{ contract: DecisionContractId }', 'Names the host decision this profile makes.'),
|
|
343
|
-
'decision.contract': field('string',
|
|
344
|
-
'models.*.efforts': field('Record<string, ThinkingLevel>', 'Named thinking levels
|
|
523
|
+
'decision.contract': field('string', 'Your name for this decision, on its traces. Not sent to the model. Not checked against the questions.'),
|
|
524
|
+
'models.*.efforts': field('Record<string, ThinkingLevel>', 'Named thinking levels. A turn picks one when allowEffortSelect is on. A provider refuses a level its model does not take. Speech ignores them, and so may an image profile without includeText.'),
|
|
345
525
|
'models.*.efforts.*': field(unionType(THINKING_LEVELS), 'The thinking level sent to the provider for this name.', THINKING_LEVELS, {
|
|
346
|
-
none: 'No thinking
|
|
526
|
+
none: 'No thinking, where the provider has that level.',
|
|
347
527
|
minimal: 'The least thinking.',
|
|
348
528
|
low: 'Light thinking.',
|
|
349
529
|
medium: 'Moderate thinking.',
|
|
350
530
|
high: 'Heavy thinking.',
|
|
351
|
-
xhigh: 'Heavier thinking
|
|
352
|
-
max: 'The most thinking the model supports
|
|
531
|
+
xhigh: 'Heavier thinking, where the provider has that level.',
|
|
532
|
+
max: 'The most thinking the model supports, where the provider has that level.',
|
|
353
533
|
}),
|
|
354
534
|
'models.*.defaultEffort': field('string', "The effort a turn gets when it doesn't pick one."),
|
|
355
535
|
'models.*.allowEffortSelect': field('boolean', 'Lets a turn pick an effort; needs two or more efforts.'),
|
|
356
|
-
'models.*.summaries': field('boolean', 'Asks
|
|
357
|
-
'models.*.maxOutputTokens': field('number', 'The
|
|
358
|
-
'models.*.temperature': field('number', "How varied the model's wording is; higher is more random."),
|
|
359
|
-
'models.*.builtInTools': field('BuiltinToolId[]', "The provider's own tools, such as Google Search, this model may use; each must be registered as a builtin tool."),
|
|
360
|
-
'models.*.
|
|
361
|
-
'models.*.fallbackKey': field('KeySlot', "The key slot this model's calls retry on when its key is refused for quota, ahead of the profile's fallbackKey."),
|
|
362
|
-
'models.*.compaction': field('CompactionSpec', 'Summarises older history once it grows past a threshold; the agent writes the summary unless profile names another.'),
|
|
536
|
+
'models.*.summaries': field('boolean', 'Asks the model for summaries of its thinking, which not every model sends; with some providers, off only hides thoughts, and others ignore it.'),
|
|
537
|
+
'models.*.maxOutputTokens': field('number', 'The token limit for one reply. Some providers never send it for speech, or for image without includeText.'),
|
|
538
|
+
'models.*.temperature': field('number', "How varied the model's wording is; higher is more random. Some providers never send it for speech, or for image without includeText."),
|
|
539
|
+
'models.*.builtInTools': field('BuiltinToolId[]', "The provider's own tools, such as Google Search, this model may use; each must be registered as a builtin tool and declared by the provider's adapter."),
|
|
540
|
+
'models.*.compaction': field('CompactionSpec', 'Summarises history past a threshold. A text agent can write the summary. Other types name a compaction profile.'),
|
|
363
541
|
'models.*.compaction.maxTokens': field('number', 'The token budget compactAt is a fraction of.'),
|
|
364
|
-
'models.*.compaction.
|
|
365
|
-
'models.*.compaction.
|
|
366
|
-
'models.*.compaction.
|
|
542
|
+
'models.*.compaction.trigger': field('(ctx: CompactionTriggerContext) => boolean | Promise<boolean>', 'Your function that decides when to compact, in place of compactAt and maxTokens.'),
|
|
543
|
+
'models.*.compaction.compactAt': field('number', 'The fraction of maxTokens, between 0 and 1, at which compaction starts, unless trigger decides.'),
|
|
544
|
+
'models.*.compaction.previousExchanges': field('number', 'How much recent history compaction keeps: a number of exchanges (1 or more), a fraction of maxTokens below compactAt, or 0 to compact it all.'),
|
|
545
|
+
'models.*.compaction.profile': {
|
|
546
|
+
...field('ProfileId', 'The text profile that writes the summary; register it before this one. Leave it out and a text agent summarises its own history, with its own instructions and model and no tools. Its registered model binding selects the provider independently of the calling agent.'),
|
|
547
|
+
unset: 'The agent itself',
|
|
548
|
+
},
|
|
367
549
|
'models.*.compaction.timing': field(unionType(COMPACTION_TIMINGS), 'Whether the kernel compacts before the turn or tells the host to compact after it.', COMPACTION_TIMINGS, {
|
|
368
550
|
before: 'The kernel compacts before the turn runs.',
|
|
369
551
|
after: "The turn's done event says compaction is due, and the host runs it.",
|
|
@@ -372,67 +554,62 @@ export const PROFILE_FIELDS = withScopeAndPresence({
|
|
|
372
554
|
history: 'Tokens in the earlier conversation.',
|
|
373
555
|
input: 'The prompt tokens the provider reported for the last call, or the count the host passes in.',
|
|
374
556
|
}),
|
|
375
|
-
'
|
|
376
|
-
'
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
}),
|
|
380
|
-
'models.*.cache.ttl': field(unionType(CACHE_TTLS), 'How long a cached prompt lasts.', CACHE_TTLS, {
|
|
381
|
-
'5m': 'Five minutes.',
|
|
382
|
-
'1h': 'One hour; writing the cache costs more, which pays off in long sessions.',
|
|
383
|
-
}),
|
|
384
|
-
'models.*.store': field('boolean', 'Whether Google stores the interaction (Gemini Interactions only); a turn can override it.'),
|
|
385
|
-
'models.*.persistViaInteractionId': field('boolean', 'Whether Google builds the context from its stored interaction (true) or every call sends the history the host passes plus the steps of this turn (false); Gemini Interactions only, and true needs storing on.'),
|
|
386
|
-
'models.*.server': field('string', "Which local server runs the model (ollama, vllm, …), recorded on traces; it doesn't change where requests go."),
|
|
387
|
-
defaultModel: field('ModelId', "The model a turn gets when it doesn't pick one."),
|
|
388
|
-
allowModelSelect: field('boolean', 'Lets a turn pick a model; needs two or more models.'),
|
|
389
|
-
maxSteps: field('number', 'The most model calls one turn may make while using tools, where 1 runs the tools asked for but never sends their results back; live sessions ignore it.'),
|
|
390
|
-
key: field('KeySlot', 'The key slot used when a model has no key of its own.'),
|
|
391
|
-
fallbackKey: field('KeySlot', 'The key slot a call retries on once when its key is refused for quota. Off unless set.'),
|
|
392
|
-
tools: field('{ allow: ToolId[]; t1Policy?; t2Loader? }', 'Which of your registered tools this profile may use, and how they load; built-in tools are turned on per model.'),
|
|
557
|
+
'profile.defaultModel': field('ModelId', "The model a turn gets when it doesn't pick one."),
|
|
558
|
+
'profile.allowModelSelect': field('boolean', 'Lets a turn name the model it runs on; a name the profile does not declare is refused.'),
|
|
559
|
+
'profile.maxSteps': field('number', 'The most model calls one turn may make while using tools, counted afresh for each rewrite; 1 runs the tools asked for but never sends their results back. Live sessions ignore it.'),
|
|
560
|
+
tools: field('{ allow: ToolId[]; t1Policy?; t2Loader?; parallel? }', 'The registered tools this profile may use, and how they load. Built-in tools are set per model.'),
|
|
393
561
|
'tools.allow': field('ToolId[]', "Your registered tools this agent may use; the provider's own tools go on the model's builtInTools instead."),
|
|
394
|
-
'tools.t1Policy': field('(ctx) => ToolId[] | Promise<ToolId[]>', 'Your function that picks, at the start of each turn, which
|
|
395
|
-
'tools.t2Loader': field('ToolId',
|
|
562
|
+
'tools.t1Policy': field('(ctx) => ToolId[] | Promise<ToolId[]>', 'Your function that picks, at the start of each turn, which T2 tools to load up front; the rest wait for tools.t2Loader.'),
|
|
563
|
+
'tools.t2Loader': field('ToolId', "The function tool that loads T2 tools. It must be in allow and return { loaded: ToolId[] }. One forbidden id fails the load. Ids off the turn path are skipped. The tools it loads can be called from the next step: a step's calls see the tools as they stood when the step began."),
|
|
564
|
+
'tools.parallel': field('boolean', 'true: the calls of one step run side by side, and a call whose pre_tool answers waitFor starts its body once those calls settle. Left out or false: they run one at a time, in the order the model made them. A step is the calls the model makes together in a turn, or the calls a host runs through invokeToolStep.'),
|
|
396
565
|
inputs: field('ProfileInputsSpec | DecisionInputsSpec', 'What a turn may send (text, files, voice, choices), or on a decision, the state it reads.'),
|
|
397
566
|
'inputs.state': field("'json'", 'A decision reads JSON state, passed on each call.', ['json']),
|
|
398
567
|
'inputs.maxStateBytes': field('number', 'The largest state, in bytes, a decision call may send; larger state is refused before it leaves your process.'),
|
|
399
568
|
'inputs.text': field('boolean', 'Whether a turn may send text.'),
|
|
400
569
|
'inputs.attachments': field('{ accept: string[] }', 'Lets turns send files.'),
|
|
401
|
-
'inputs.attachments.accept': field('string[]', 'The file types a turn may send, where type/* matches a whole family; image profiles take only images, video and PDF.', ATTACHMENT_ACCEPT_MIMES, "Types the kernel knows; a listed type it doesn't know is refused when a turn sends it."),
|
|
570
|
+
'inputs.attachments.accept': field('string[]', 'The file types a turn may send, where type/* matches a whole family; image profiles take only images, video, and PDF.', ATTACHMENT_ACCEPT_MIMES, "Types the kernel knows; a listed type it doesn't know is refused when a turn sends it."),
|
|
402
571
|
'inputs.voice': field('{ accept: string[] }', 'Lets turns send voice clips.'),
|
|
403
572
|
'inputs.voice.accept': field('string[]', 'The audio types a voice clip may be; audio/* matches them all.', VOICE_ACCEPT_MIMES, 'Audio types the kernel knows.'),
|
|
404
|
-
'inputs.maxFiles': field('number', 'The most files and voice clips one turn may send, counted together.'),
|
|
405
|
-
'inputs.maxBytes': field('number', 'The largest file or clip, in bytes, a turn may send inline.'),
|
|
406
|
-
'inputs.maxTurnBytes': field('number', 'The most bytes one turn may send inline across all its files and clips.'),
|
|
573
|
+
'inputs.maxFiles': field('number', 'The most files and voice clips one turn or embedding request may send, counted together.'),
|
|
574
|
+
'inputs.maxBytes': field('number', 'The largest file or clip, in bytes, a turn or embedding request may send inline.'),
|
|
575
|
+
'inputs.maxTurnBytes': field('number', 'The most bytes one turn or embedding request may send inline across all its files and clips.'),
|
|
407
576
|
'inputs.limitsByMime': field('Record<string, number>', 'Size limits by file type that replace maxBytes for those types.'),
|
|
408
|
-
'inputs.limitsByMime.*': field('number', 'The largest file of this type (or type/* family), in bytes, a turn may send inline.'),
|
|
409
|
-
'inputs.slots': field('Record<string, string[]>', 'Named choices a turn can make, such as language, each with its allowed values.'),
|
|
577
|
+
'inputs.limitsByMime.*': field('number', 'The largest file of this type (or type/* family), in bytes, a turn or embedding request may send inline.'),
|
|
578
|
+
'inputs.slots': field('Record<string, string[]>', 'Named choices a turn or a call can make, such as language, each with its allowed values. {name} in a prompt becomes the chosen value.'),
|
|
410
579
|
'inputs.slots.*': field('string[]', 'The values a turn may choose for this slot; any other is refused.'),
|
|
580
|
+
'inputs.context': field('{ from: ContextSender[]; maxChars: number }', 'Lets the page or the host send the agent one package of things to know, read at the context boundary.'),
|
|
581
|
+
'inputs.context.from': field("Array<'client' | 'server'>", 'Who may send context; context from anyone else is refused.', CONTEXT_SENDERS, {
|
|
582
|
+
client: 'The browser. A visitor can change it, so it is untrusted.',
|
|
583
|
+
server: "The host's own code. It is assembled, like turn system text.",
|
|
584
|
+
}),
|
|
585
|
+
'inputs.context.maxChars': field('number', 'The longest package, in characters of its JSON, each sender may send.'),
|
|
411
586
|
outputs: field('ProfileOutputsSpec', 'The shape of the reply, how it is checked, and how it streams.'),
|
|
412
|
-
'outputs.structured': field('StructuredSchemaId | StructuredBySlot | null', 'The registered JSON schema the reply must follow, which can vary by slot.'),
|
|
413
|
-
image: field('ProfileImageSpec', '
|
|
587
|
+
'outputs.structured': field('StructuredSchemaId | StructuredBySlot | null', 'The registered JSON schema the reply must follow, which can vary by slot; register it before the profile.'),
|
|
588
|
+
image: field('ProfileImageSpec', 'How the images this profile generates are shaped and made: size, format, quality and references. Each setting is sent only where the provider has it; one it lacks is refused or ignored, as that setting says.'),
|
|
414
589
|
'image.aspectRatio': field('string', 'The shape of generated images, such as 16:9.'),
|
|
415
590
|
'image.resolution': field('string', 'How detailed generated images are, such as 1K, 2K or 4K.'),
|
|
416
|
-
'image.mimeType': field('string', 'The file type of generated images;
|
|
417
|
-
'image.quality': field('string', 'How much effort the model spends on each image
|
|
418
|
-
'image.background': field('string', 'The background of generated images
|
|
419
|
-
'image.n': field('number', 'How many images one request makes
|
|
420
|
-
'image.seed': field('number', 'A seed for repeatable images
|
|
421
|
-
'image.outputCompression': field('number', 'Compression from 0 to 100 for jpeg and webp images
|
|
422
|
-
'image.references': field('Array<TurnBlob | TurnMediaRef>',
|
|
423
|
-
'image.includeText': field('boolean', 'Whether the model may write text alongside its images;
|
|
424
|
-
speech: field('ProfileSpeechSpec', '
|
|
425
|
-
'speech.voice': field('string',
|
|
426
|
-
'speech.
|
|
591
|
+
'image.mimeType': field('string', 'The file type of generated images; a provider that takes a fixed set of types may use png for any other.'),
|
|
592
|
+
'image.quality': field('string', 'How much effort the model spends on each image: auto, low, medium, or high. A provider that has no such setting refuses it.'),
|
|
593
|
+
'image.background': field('string', 'The background of generated images: auto, transparent, or opaque. A provider that has no such setting refuses it.'),
|
|
594
|
+
'image.n': field('number', 'How many images one request makes, where the provider takes a count.'),
|
|
595
|
+
'image.seed': field('number', 'A seed for repeatable images, where the provider and the model honour it.'),
|
|
596
|
+
'image.outputCompression': field('number', 'Compression from 0 to 100 for jpeg and webp images, where the provider takes it.'),
|
|
597
|
+
'image.references': field('Array<TurnBlob | TurnMediaRef>', "Images sent with every turn, before the user's. Each is bytes (`data`) or a link (`uri`). Some providers take http(s) links only, and none with includeText."),
|
|
598
|
+
'image.includeText': field('boolean', 'Whether the model may write text alongside its images; with some providers this also sends the system instruction and history.'),
|
|
599
|
+
speech: field('ProfileSpeechSpec', "How the profile's speech sounds and is delivered: voice, style, speed and audio format. A turn may replace voice, style and speed for that turn."),
|
|
600
|
+
'speech.voice': field('string', "The voice the speech is read in, by the provider's own name for it; a turn's speech.voice replaces it."),
|
|
601
|
+
'speech.style': field('string', "How the script is delivered, in plain words (pace, mood, accent); it is never read aloud, and a turn's speech.style replaces it. A model that takes no direction ignores it."),
|
|
602
|
+
'speech.speed': field('number', "The speaking rate, where 1 is the voice's own pace; a turn's speech.speed replaces it. A provider that has no rate refuses it or ignores it."),
|
|
603
|
+
'speech.format': field(unionType(SPEECH_AUDIO_FORMATS), "The audio encoding each turn's speech comes back in, and so what the host plays or stores.", SPEECH_AUDIO_FORMATS, {
|
|
427
604
|
pcm: 'Uncompressed audio, delivered as WAV.',
|
|
428
|
-
mp3: 'Compressed audio;
|
|
605
|
+
mp3: 'Compressed audio; a provider that cannot make it refuses the turn.',
|
|
429
606
|
}),
|
|
430
|
-
live: field('ProfileLiveSpec', '
|
|
607
|
+
live: field('ProfileLiveSpec', 'How a realtime voice and video session runs: what it accepts from the user, the voice it answers in, when it hears the user start and stop, and how it resumes and trims its context.'),
|
|
431
608
|
'live.ingress': field('LiveIngressSpec', 'Which channels the session accepts from the user.'),
|
|
432
609
|
'live.ingress.audio': field('boolean', 'Whether the session accepts microphone audio.'),
|
|
433
610
|
'live.ingress.video': field('boolean', 'Whether the session accepts camera frames.'),
|
|
434
611
|
'live.ingress.text': field('boolean', 'Whether the session accepts typed text.'),
|
|
435
|
-
'live.voice': field('string', 'The voice the model speaks in.', GOOGLE_SPEECH_VOICES,
|
|
612
|
+
'live.voice': field('string', 'The voice the model speaks in.', GOOGLE_SPEECH_VOICES, 'Voice names to pick from; any other name is sent as written.'),
|
|
436
613
|
'live.vad': field('LiveVadSpec', 'How the session detects when the user starts and stops speaking.'),
|
|
437
614
|
'live.vad.activityHandling': field(unionType(LIVE_ACTIVITY_HANDLINGS), "Whether the user speaking interrupts the model's reply.", LIVE_ACTIVITY_HANDLINGS, {
|
|
438
615
|
START_OF_ACTIVITY_INTERRUPTS: 'The user speaking cuts the reply off.',
|
|
@@ -448,22 +625,30 @@ export const PROFILE_FIELDS = withScopeAndPresence({
|
|
|
448
625
|
}),
|
|
449
626
|
'live.vad.prefixPaddingMs': field('number', 'How long speech must last, in milliseconds, before it counts as the user starting to speak.'),
|
|
450
627
|
'live.vad.silenceDurationMs': field('number', "How long a silence, in milliseconds, ends the user's speech."),
|
|
451
|
-
'live.sessionResumption': field('boolean', 'Whether
|
|
628
|
+
'live.sessionResumption': field('boolean', 'Whether the provider sends resume handles, which the host can pass to a new session to carry this one on.'),
|
|
629
|
+
'live.greeting': field('string', 'A prompt the call sends itself when it opens new, so the agent speaks first. The visitor does not see it. It may use {slot}.'),
|
|
630
|
+
'live.resumed': field('{ prompt: string; afterMs?: number }', 'What happens when a call comes back after a drop. It needs live.sessionResumption.'),
|
|
631
|
+
'live.resumed.prompt': field('string', 'A prompt the call sends itself when it resumes, so the agent says it is back. The visitor does not see it. It may use {slot}.'),
|
|
632
|
+
'live.resumed.afterMs': field('number', 'The shortest time away, in milliseconds, that earns the prompt; a shorter drop resumes silently.'),
|
|
452
633
|
'live.contextCompression': field('LiveContextCompressionSpec', "Trims the session's context once it grows past the trigger."),
|
|
453
634
|
'live.contextCompression.triggerTokens': field('number', 'The context size, in tokens, that starts trimming.'),
|
|
454
635
|
'live.contextCompression.slidingWindow': field('LiveSlidingWindowSpec', 'Trims by dropping the oldest turns; the system instruction stays.'),
|
|
455
636
|
'live.contextCompression.slidingWindow.targetTokens': field('number', 'The context size, in tokens, to trim down to; below the trigger.'),
|
|
456
637
|
'live.transcription': field('LiveTranscriptionSpec', "Text transcripts of the session's speech."),
|
|
457
638
|
'live.transcription.input': field('boolean', "Whether the user's speech is transcribed."),
|
|
458
|
-
'live.transcription.output': field('boolean', "Whether the model's speech is transcribed."),
|
|
639
|
+
'live.transcription.output': field('boolean', "Whether the model's speech is transcribed; always on while a detector reads live_reply, since it reads the transcript."),
|
|
459
640
|
'outputs.validation': field('ProfileValidationSpec', 'Your checks on a structured reply, and how many rewrites a failure gets.'),
|
|
460
|
-
'outputs.validation.fields': field('Record<string, ProfileValidator>', 'Your checks, each keyed by a dotted path into the structured reply, such as diagram.mermaid.'),
|
|
461
|
-
'outputs.validation.fields.*': field('(candidate: unknown, slots?: Record<string, string>) => ValidationResult | Promise<ValidationResult>', 'Your check on this part of the reply; a failure sends its error back to the model to rewrite.'),
|
|
462
|
-
'outputs.validation.
|
|
641
|
+
'outputs.validation.fields': field('Record<string, ProfileValidator>', 'Your checks, each keyed by a dotted path into the structured reply, such as diagram.mermaid; a path no structured schema reaches is refused when the profile registers.'),
|
|
642
|
+
'outputs.validation.fields.*': field('(candidate: unknown, slots?: Record<string, string>) => ValidationResult | Promise<ValidationResult>', 'Your check on this part of the reply, reached through object properties only; a failure sends its error back to the model to rewrite while retries remain.'),
|
|
643
|
+
'outputs.validation.items': field('Record<string, ProfileItemRule>', 'Your checks on the items of a list, each keyed by the dotted path of that list in the structured reply, such as claims; a path no structured schema reaches as a list is refused when the profile registers.'),
|
|
644
|
+
'outputs.validation.items.*': field('ProfileItemRule', 'Your check on each item of this list. A refused item never fails the reply and the rest of the reply is kept.'),
|
|
645
|
+
'outputs.validation.items.*.check': field('(item: unknown, turn: ItemCheckTurn) => ValidationResult | Promise<ValidationResult>', 'Your check on one item, given what the tools of the turn returned (turn.toolResults); its error is the reason the model reads on a rewrite and the host reads on the removed item.'),
|
|
646
|
+
'outputs.validation.items.*.onFail': field("'drop' | 'fix'", 'drop removes a refused item. fix first asks the model to rewrite the refused items alone, once and while retries remain, then removes any refused again. Removed items leave on the structured event as removed.', ITEM_FAIL_ACTIONS),
|
|
647
|
+
'outputs.validation.maxRetries': field('number', "How many times the model may rewrite a reply that fails your checks or the schema's required keys before it goes out as it is; under sse, an attempt that gets rewritten has already streamed. A rewrite of a blocked reply (guardrails.blockedReply) counts against this too."),
|
|
463
648
|
'outputs.streaming': field('ProfileStreamingSpec', 'How the reply reaches the host, and whether its thinking does.'),
|
|
464
|
-
'outputs.streaming.mode': field(unionType(STREAM_MODES), 'Whether the
|
|
465
|
-
sse: 'Events arrive as the model writes.',
|
|
466
|
-
buffered: 'One non-streaming call
|
|
649
|
+
'outputs.streaming.mode': field(unionType(STREAM_MODES), 'Whether the reply reaches the host as the model writes it, or whole.', STREAM_MODES, {
|
|
650
|
+
sse: 'Events arrive as the model writes, so a reply that fails outputs.validation has already streamed when it is rewritten; some providers always answer image and speech in one piece.',
|
|
651
|
+
buffered: 'One non-streaming call, whose events arrive together; under outputs.validation, only once the reply passes or retries run out. Thinking still streams.',
|
|
467
652
|
}),
|
|
468
653
|
'outputs.streaming.streamThoughts': field('boolean', "Whether the model's thinking reaches the host."),
|
|
469
654
|
turnBehaviour: field('ProfileTurnBehaviourSpec', 'Whether a reply that stopped early can be continued, and whether a running turn can be steered.'),
|
|
@@ -473,181 +658,238 @@ export const PROFILE_FIELDS = withScopeAndPresence({
|
|
|
473
658
|
stream_incomplete: 'The connection dropped mid-reply.',
|
|
474
659
|
provider_error: 'The provider returned an error or timed out.',
|
|
475
660
|
}),
|
|
476
|
-
'turnBehaviour.resumption.autoContinue': field('ContinueStopKind[]', 'Which early stops
|
|
661
|
+
'turnBehaviour.resumption.autoContinue': field('ContinueStopKind[]', 'Which early stops are continued without asking, whether or not allowContinue offers a Continue for them. When set, a text turn sends a listed failed model call that gave no reply again itself; the host continues the rest.', CONTINUE_STOP_KINDS, {
|
|
477
662
|
length: 'The reply hit the output token limit.',
|
|
478
663
|
stream_incomplete: 'The connection dropped mid-reply.',
|
|
479
664
|
provider_error: 'The provider returned an error or timed out.',
|
|
480
665
|
}),
|
|
481
|
-
'turnBehaviour.resumption.maxContinues': field('number', 'How many times one reply may be continued; once set, each continue must say which one it is.'),
|
|
482
|
-
'turnBehaviour.allowSteering': field('boolean', '
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
'guardrails.
|
|
489
|
-
'guardrails.
|
|
490
|
-
|
|
491
|
-
'guardrails.
|
|
492
|
-
'guardrails.
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
'guardrails.egress.enforce': field('EgressEnforcer', 'Your own check on the reply, run as it streams and when it ends. Return allow, flag (log only), redact (swap in your text) or block (see onBlock); a block or redact holds the rest of the stream, and a throw counts as a block. Set this or checks, not both.'),
|
|
496
|
-
'guardrails.egress.checks': field('boolean | EgressChecks', 'The bundled checks on the reply, blocking on what they find. true runs each at its default, false none but the system-prompt leak checks, and an object switches the ones it names. Set this or enforce, not both.'),
|
|
497
|
-
'guardrails.egress.checks.sensitive': field('boolean | SensitiveSwitches', 'Credentials and personal data in the reply, by group. Every group but network by default: an address in a reply is not a secret.'),
|
|
498
|
-
'guardrails.egress.checks.sensitive.ids': field('boolean', 'US SSN, ITIN and EIN numbers.'),
|
|
499
|
-
'guardrails.egress.checks.sensitive.financial': field('boolean', 'IBANs and card numbers.'),
|
|
500
|
-
'guardrails.egress.checks.sensitive.network': field('boolean', 'IPv4 and IPv6 addresses.'),
|
|
501
|
-
'guardrails.egress.checks.sensitive.credentials': field('boolean', 'API keys, access tokens, bearer tokens and private keys.'),
|
|
502
|
-
'guardrails.egress.checks.boundary': field('boolean', 'The markers the kernel puts around user data, and the canary note, repeated in the reply.'),
|
|
503
|
-
'guardrails.egress.checks.injection': field('boolean', 'Prompt-injection phrasing in the reply, as written or disguised.'),
|
|
504
|
-
'guardrails.egress.checks.images': field('boolean | UrlCheck', 'Images in the reply that load a URL the model was not given, which would send data off the device with no click.'),
|
|
505
|
-
'guardrails.egress.checks.images.hosts': field('string[]', 'Hostnames whose images load whatever their URL, such as your own CDN.'),
|
|
506
|
-
'guardrails.egress.checks.images.fromTools': field('boolean', 'Whether a URL a tool returned counts as given. Off keeps only what the system prompt, the user and history gave.'),
|
|
507
|
-
'guardrails.egress.checks.links': field('boolean | UrlCheck', 'Links in the reply to a URL the model was not given. Turn it on when your app unfurls links into previews.'),
|
|
508
|
-
'guardrails.egress.checks.links.hosts': field('string[]', 'Hostnames whose links pass whatever their URL; the images hosts pass too.'),
|
|
509
|
-
'guardrails.egress.checks.links.fromTools': field('boolean', 'Whether a URL a tool returned counts as given. Off keeps only what the system prompt, the user and history gave.'),
|
|
510
|
-
'guardrails.egress.onBlock': field(unionType(EGRESS_ON_BLOCK), 'What happens when enforce blocks the reply.', EGRESS_ON_BLOCK, {
|
|
511
|
-
reject_to_agent: 'The model reads why and rewrites the reply, up to maxRetries times; once retries run out, the reply is withheld and the turn ends with a safety error.',
|
|
512
|
-
refuse_to_user: 'The user sees the egress.refusal wording in place of the reply, and the turn ends.',
|
|
666
|
+
'turnBehaviour.resumption.maxContinues': field('number', 'How many times one reply may be continued; once set, each continue must say which one it is. Also how many failed model calls one text turn sends again itself (one when unset).'),
|
|
667
|
+
'turnBehaviour.allowSteering': field('boolean', 'Lets your onStage hook add messages to a running turn. Text profiles also let the user steer.'),
|
|
668
|
+
'turnBehaviour.atStepLimit': field("'stop' | 'answer'", 'What happens when a turn reaches maxSteps while the model still wants tools: the turn stops with no answer, or the last call is made without tools so it answers.', STEP_LIMIT_MODES, {
|
|
669
|
+
stop: 'It may still call tools; if it does, they run and the turn stops as step_limit with no answer.',
|
|
670
|
+
answer: 'It is sent without tools, so it writes the answer from what the turn has gathered.',
|
|
671
|
+
}),
|
|
672
|
+
guardrails: field('ProfileGuardrailsSpec', 'Theorem checks what enters or leaves an agent’s context and generation against built-in or custom rules at each configured boundary.'),
|
|
673
|
+
'guardrails.quota': field('QuotaGuardrailSpec', 'A daily turn limit. Your server enforces it with takeSlot.'),
|
|
674
|
+
'guardrails.quota.perDay': field('number', 'Turns each client IP may run on this profile per UTC day, one at a time; counts live in the process, and a loopback caller is not counted.'),
|
|
675
|
+
...detectFields(),
|
|
676
|
+
'guardrails.blockedReply': field('BlockedReplySpec', 'How a reply a guardrail blocked is handled: the model rewrites it, or the user gets a refusal, and how many rewrites it gets.'),
|
|
677
|
+
'guardrails.blockedReply.onBlock': field(unionType(BLOCKED_REPLY_ON_BLOCK), 'Whether the model gets to rewrite a reply a guardrail blocked, or the user gets a refusal in its place.', BLOCKED_REPLY_ON_BLOCK, {
|
|
678
|
+
retry: 'The model reads why and rewrites the reply, up to maxRetries times; once retries run out, the reply is withheld and the turn ends with a safety error. Live never rewrites: it withholds at once.',
|
|
679
|
+
refuse: 'The user sees the egress.refusal wording in place of the reply, and the turn ends.',
|
|
513
680
|
}),
|
|
514
|
-
'guardrails.
|
|
515
|
-
'guardrails.
|
|
516
|
-
'guardrails.network': field('NetworkGuardrailSpec', 'Which addresses your HTTP and MCP tools may reach.'),
|
|
681
|
+
'guardrails.blockedReply.maxRetries': field('number', 'How many times the model may rewrite a blocked reply. Live ignores it.'),
|
|
682
|
+
'guardrails.network': field('NetworkGuardrailSpec', 'Addresses HTTP and MCP tools may reach.'),
|
|
517
683
|
'guardrails.network.allowPrivateNetworks': field('boolean', 'Lets tools reach localhost and private network addresses, for local development.'),
|
|
518
|
-
'guardrails.network.allowedHosts': field('string[]', "Hostnames tools may reach even when they resolve to a private address; public hosts don't need listing."),
|
|
684
|
+
'guardrails.network.allowedHosts': field('string[]', "Hostnames tools may reach even when they resolve to a private address; public hosts don't need listing. Names are resolved only when the host passes resolveHost."),
|
|
519
685
|
'guardrails.network.allowedSchemes': field('string[]', 'The URL schemes tools may use.'),
|
|
520
|
-
'guardrails.taint': field('TaintGuardrailSpec',
|
|
686
|
+
'guardrails.taint': field('TaintGuardrailSpec', 'Tool limits after a remote read.'),
|
|
521
687
|
'guardrails.taint.afterRemoteRead': field(unionType(TAINT_GATES), "Which tool calls are refused, by each tool's access, once the turn has read a remote tool's result.", TAINT_GATES, {
|
|
522
688
|
off: 'None; risky calls are only logged.',
|
|
523
689
|
destructive: 'Destructive calls.',
|
|
524
690
|
write: 'Read-write and destructive calls.',
|
|
525
691
|
}),
|
|
692
|
+
'guardrails.taint.remoteDestination': field(unionType(DESTINATION_GATES), "What happens to a tool call, read-only ones too, that sends to an email address, a link's host or a bank account number (IBAN) that only the running text of a remote tool's result named. One the user, the system prompt, or a local tool gave passes, and so does one that is a whole field of the result.", DESTINATION_GATES, {
|
|
693
|
+
off: 'The call runs; it is only logged.',
|
|
694
|
+
confirm: 'The call waits for the user to approve it; an approval runs it.',
|
|
695
|
+
block: 'The call is refused, and the model is told why.',
|
|
696
|
+
}),
|
|
526
697
|
'guardrails.disclosure': field('{ enforce: DecisionDisclosureEnforcer }', 'Your check on the state before a decision sends it to the model.'),
|
|
527
698
|
'guardrails.disclosure.enforce': field('(state, context) => DecisionDisclosureVerdict | Promise<DecisionDisclosureVerdict>', 'Your function that allows or blocks the state before it is sent.'),
|
|
528
|
-
|
|
529
|
-
'
|
|
699
|
+
labels: field('LabelOverrides', "This profile's own wording for error lines, notices, and notes to the model, by labels key."),
|
|
700
|
+
'labels.*': field('string', 'The wording for this labels key; canary.bind_note must keep its {canary} placeholder.'),
|
|
530
701
|
observability: field('ProfileObservabilitySpec', "Where this profile's traces go and what they keep."),
|
|
531
|
-
'observability.writeTo': field('false | string | TraceSink', 'Where traces
|
|
532
|
-
'observability.sampleRate': field('number', 'The share of traces kept, from 0 to 1, each kept or dropped whole.'),
|
|
702
|
+
'observability.writeTo': field('false | string | TraceSink', 'Where traces go: a registered destination id, your own writer, or false. An unregistered id fails the turn at the start. A sink passed to runTurn replaces it.'),
|
|
703
|
+
'observability.sampleRate': field('number', 'The share of traces kept, from 0 to 1, each kept or dropped whole; a sink passed straight to runTurn keeps every trace.'),
|
|
533
704
|
'observability.include': field('TraceIncludeSpec', 'Which optional parts of a trace are kept.'),
|
|
534
|
-
'observability.include.upstreamLog': field('boolean', 'Keeps each row the provider sent back, scrubbed, as it arrived.'),
|
|
705
|
+
'observability.include.upstreamLog': field('boolean', 'Keeps each row the provider sent back, scrubbed, as it arrived, with media bytes replaced by their sha256.'),
|
|
535
706
|
'observability.include.outboundWire': field('boolean', 'Keeps each request body sent to the provider, scrubbed.'),
|
|
536
|
-
'observability.include.evidenceRaw': field('boolean', "Keeps the provider's raw payload on grounding results such as search citations."),
|
|
537
|
-
'observability.include.usage': field('boolean', 'Keeps token counts and other usage figures.'),
|
|
707
|
+
'observability.include.evidenceRaw': field('boolean', "Keeps the provider's raw payload on grounding results such as search citations; upstreamLog rows keep their own copy."),
|
|
708
|
+
'observability.include.usage': field('boolean', 'Keeps token counts and other usage figures on spans; upstreamLog rows keep their own.'),
|
|
538
709
|
'observability.include.guardrailDecisions': field('boolean', 'Keeps each guardrail decision.'),
|
|
539
|
-
'observability.include.guardrailMatchPreview': field('boolean', "Keeps the exact text each guardrail matched, on the trace and the host's event stream; for debugging only."),
|
|
710
|
+
'observability.include.guardrailMatchPreview': field('boolean', "Keeps the exact text each guardrail matched, unscrubbed, on the trace and the host's event stream; for debugging only."),
|
|
540
711
|
'observability.resource': field('Record<string, TraceAttributeValue>', 'Attributes stamped on every trace, such as service.name.'),
|
|
541
712
|
'observability.scrub': field('TraceScrubSpec', "What is removed from stored traces, separately from the turn's guardrails."),
|
|
542
|
-
'observability.scrub.sensitive': field('
|
|
543
|
-
'observability.scrub.injection': field('
|
|
544
|
-
'observability.scrub.canary': field('
|
|
545
|
-
'observability.retainForDays': field('number', '
|
|
713
|
+
'observability.scrub.sensitive': field('ScrubSwitch', "Removes what the data detectors (IDs, Financial, Network, Credentials) and your own detectors find from stored traces. On, it cleans with the patterns each reads the turn with; { theorem, host } picks Theorem's patterns, yours, or both for the trace alone."),
|
|
714
|
+
'observability.scrub.injection': field('ScrubSwitch', "Removes what Injection and Tool instructions find from stored traces. On, it cleans with the patterns each reads the turn with; { theorem, host } picks Theorem's patterns, yours, or both for the trace alone."),
|
|
715
|
+
'observability.scrub.canary': field('ScrubSwitch', "Removes the canary token from stored traces. The canary is Theorem's, so { theorem: false } keeps it."),
|
|
716
|
+
'observability.retainForDays': field('number', 'Days a trace file is kept, by its UTC day. The next write removes old files. 0 or less keeps all.'),
|
|
546
717
|
'observability.rotateAfterMiB': field('number', 'File size in MiB at which a file-based destination starts a new file, handed to every destination with the record. Default 32.'),
|
|
547
|
-
'observability.onWriteError': field('(err: unknown) => void', "Your function called when a trace can't be built or written; the turn carries on, and a destination's own error handler takes priority."),
|
|
718
|
+
'observability.onWriteError': field('(err: unknown) => void', "Your function called when a trace can't be built or written; the turn carries on, and a destination's own error handler takes priority. An unregistered writeTo id is a config error instead."),
|
|
548
719
|
});
|
|
549
720
|
const TOOL_TYPE_FIELD = field(unionType(TOOL_TYPES), 'How the tool runs.', TOOL_TYPES, {
|
|
550
721
|
builtin: "The provider's own tool, such as Google Search, run by the provider.",
|
|
551
722
|
function: 'Your handler runs it.',
|
|
552
723
|
http: 'The kernel calls your HTTP endpoint.',
|
|
553
724
|
mcp: 'The kernel calls a tool on a remote MCP server.',
|
|
725
|
+
agent: 'The kernel runs one turn of another registered agent and returns its reply.',
|
|
554
726
|
});
|
|
555
727
|
const CREDENTIAL_KINDS = {
|
|
556
728
|
bearer: 'A token; a secret typed in at the prompt becomes a bearer token.',
|
|
557
729
|
['api_' + 'key']: 'An API key; a secret typed in at the prompt becomes an API key.',
|
|
558
730
|
oauth2: 'An OAuth sign-in; the host supplies the token.',
|
|
559
731
|
};
|
|
732
|
+
/**
|
|
733
|
+
* The catalog of the fields `registerTool` takes, keyed `registerTool.<field>`. The `studio.` and
|
|
734
|
+
* `local.` rows are the studio's own; a builder never sets them.
|
|
735
|
+
*/
|
|
560
736
|
export const EXTRA_FIELDS = {
|
|
561
|
-
|
|
737
|
+
'done.stop.kind': field('TurnStopKind', 'Why the turn ended, on the done event: its stop.kind.', TURN_STOP_KINDS, {
|
|
738
|
+
completed: 'The model finished its reply.',
|
|
739
|
+
length: 'The model reached its token limit.',
|
|
740
|
+
tool: 'The model called tools and the turn hands them to the host, in done.tools.',
|
|
741
|
+
gate: 'A pre_tool stage held a tool call. The host resumes it with invokeTool, not continueFrom.',
|
|
742
|
+
filtered: 'The provider filtered the reply, or the egress guardrail withheld it.',
|
|
743
|
+
provider_error: 'The provider failed or reported an error.',
|
|
744
|
+
cancelled: 'The turn was cancelled, by the user or by a stage that aborted it.',
|
|
745
|
+
stream_incomplete: 'The stream ended without the provider reporting a final status.',
|
|
746
|
+
step_limit: 'The last model call maxSteps allows asked for tools, so the turn ended with no answer.',
|
|
747
|
+
interrupted: 'A live utterance was cut off by an interruption.',
|
|
748
|
+
generation_complete: 'Live: the model finished generating audio or text for this utterance. The turn may still be open.',
|
|
749
|
+
}),
|
|
562
750
|
'registerTool.type': TOOL_TYPE_FIELD,
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
751
|
+
/** Studio-only rows: the editor's local-model connection, and a decision's questions and images. */
|
|
752
|
+
'local.baseUrl': field('string', 'Where your local model server listens, such as Ollama, llama.cpp or vLLM. The browser calls it directly.'),
|
|
753
|
+
'studio.remoteTools': {
|
|
754
|
+
...field('boolean', 'Whether tools that reach other hosts (HTTP and MCP) may run while a local model is in use. Off, a run with a local model reaches no host.'),
|
|
755
|
+
unset: 'Off',
|
|
756
|
+
},
|
|
757
|
+
'decision.questions.id': field('string', "The question's name. Its answer comes back under it."),
|
|
758
|
+
'decision.questions.type': field("'choice' | 'score' | 'noul' | 'box'", 'The kind of answer the question takes.', ['choice', 'score', 'noul', 'box'], {
|
|
759
|
+
choice: 'One of the named options, with a confidence and a probability for each option.',
|
|
760
|
+
score: 'A level on an ordered scale, with a confidence.',
|
|
761
|
+
noul: 'One number, which may weigh named criteria.',
|
|
762
|
+
box: 'Where something is in an image: its top, bottom, left and right edges, with a confidence.',
|
|
763
|
+
}),
|
|
764
|
+
'decision.questions.instructions': field('DecisionEntry', "What to ask about the state. Name a state field in backticks, such as `photo`, and one of the decision's images by its reference, such as <ginger>. A box looks in its In image, else in the image of the first field it names."),
|
|
765
|
+
'decision.questions.image': {
|
|
766
|
+
...field('string', "The image a box is in: one of the decision's images, such as <ghs02>, or a state field its instructions name, such as `photo`. The model is told it in the instructions."),
|
|
767
|
+
unset: 'The image the instructions name',
|
|
768
|
+
},
|
|
769
|
+
'decision.images': field('Record<string, DecisionAsset>', 'Pictures sent with every decision, beside the state. A question names one by its reference, such as <ghs02>. A PNG or JPEG.'),
|
|
770
|
+
'decision.images.name': field('string', 'The reference a question writes, without its angle brackets: ghs02 is written <ghs02>. Lowercase letters, digits and _.'),
|
|
771
|
+
'registerTool.name': field('string', "The tool's id, which profiles list in tools.allow (or a model's builtInTools) and the model calls a custom tool by."),
|
|
772
|
+
'registerTool.description': field('string', 'Tells the model what the tool does (custom tools only).'),
|
|
773
|
+
'registerTool.input': field('ZodSchema', "The Zod schema for the tool's arguments, sent to the model and checked on every call."),
|
|
774
|
+
'registerTool.output': field('ZodSchema', "The Zod schema every result the tool returns must match; the kernel's own not-signed-in note is not checked."),
|
|
775
|
+
'registerTool.handler': field('ToolHandler', 'Your function that runs the tool; it can also yield progress as it goes.'),
|
|
776
|
+
'registerTool.endpoint': field('string', 'The URL the tool calls, with {name} placeholders for mapping.pathParams; the scheme and host must be written out.'),
|
|
777
|
+
'registerTool.method': field(unionType(HTTP_METHODS), 'The HTTP method; every method but GET sends a JSON body.', HTTP_METHODS),
|
|
778
|
+
'registerTool.headers': field('Record<string, string>', "Headers sent with every request to the tool's own origin, never once a redirect leaves it."),
|
|
779
|
+
'registerTool.mapping': field('{ pathParams?, queryParams?, bodyParam? }', 'Where each argument goes in the request.'),
|
|
780
|
+
'registerTool.mapping.pathParams': field('string[]', 'Arguments that fill the {name} placeholders in the endpoint.'),
|
|
781
|
+
'registerTool.mapping.queryParams': field('string[]', 'Arguments added to the query string.'),
|
|
782
|
+
'registerTool.mapping.bodyParam': field('string', 'The one argument sent as the whole JSON body; without it, a method other than GET sends every argument the path and query leave unused.'),
|
|
783
|
+
'registerTool.serverUrl': field('string', "The MCP server's URL."),
|
|
784
|
+
'registerTool.mcpToolName': field('string', "The tool's name on the MCP server."),
|
|
785
|
+
'registerTool.profile': field('ProfileId', 'The profile this agent tool runs: text, image, or speech. Register it first. Nothing it calls may stop on a gate.'),
|
|
786
|
+
'registerTool.answeredBy': {
|
|
787
|
+
...field("'page'", 'Who answers a call to a function tool. With page, the page the agent is on returns the output, and the tool has no handler.', ['page']),
|
|
788
|
+
unset: 'Its handler',
|
|
789
|
+
},
|
|
790
|
+
'registerTool.maxCallsPerTurn': {
|
|
791
|
+
...field('number', 'How many times one turn of the calling agent may run this tool.'),
|
|
792
|
+
unset: 'As many as its steps allow',
|
|
793
|
+
},
|
|
794
|
+
'registerTool.fieldText': {
|
|
795
|
+
...field('Partial<Record<keyof AgentToolInput, string>>', 'What the calling model reads on a field of an agent tool input, such as text. A field the profile does not take is refused when the tool registers.'),
|
|
796
|
+
unset: 'The fields carry no text',
|
|
797
|
+
},
|
|
798
|
+
'registerTool.hostFields': {
|
|
799
|
+
...field('Record<string, ZodType>', 'Fields the calling model fills on an agent tool that only the host reads. onAgentCall gets them as hostInput and turns them into what the agent is sent; the agent never sees them. A name the input already has is refused when the tool registers.'),
|
|
800
|
+
unset: 'The input is only what the profile takes',
|
|
801
|
+
},
|
|
802
|
+
'registerTool.hostOnly': {
|
|
803
|
+
...field("Array<'attachments' | 'voice' | 'slots'>", 'Channels the called profile takes that the calling model cannot fill on an agent tool; only onAgentCall sends them. A channel the profile does not take is refused when the tool registers.'),
|
|
804
|
+
unset: 'The model can fill every channel the profile takes',
|
|
805
|
+
},
|
|
806
|
+
'registerTool.auth': {
|
|
578
807
|
...field('ToolAuthConfig', 'How the tool gets its credential.'),
|
|
579
808
|
unset: 'No credential',
|
|
580
809
|
},
|
|
581
|
-
'auth.type': field(unionType(TOOL_AUTH_TYPES),
|
|
582
|
-
'auth.slot': field('string', 'Which of the credentials the turn passes in this tool uses.'),
|
|
583
|
-
'auth.service': field('string', 'The service the person signs in to, as they know it, named when a turn stops to ask for a credential.'),
|
|
584
|
-
'auth.headerName': {
|
|
585
|
-
...field('string',
|
|
810
|
+
'registerTool.auth.type': field(unionType(TOOL_AUTH_TYPES), "The kind of credential the tool expects, shown when a turn stops to ask for one; the header follows the stored credential's own kind.", TOOL_AUTH_TYPES, CREDENTIAL_KINDS),
|
|
811
|
+
'registerTool.auth.slot': field('string', 'Which of the credentials the turn passes in this tool uses.'),
|
|
812
|
+
'registerTool.auth.service': field('string', 'The service the person signs in to, as they know it, named when a turn stops to ask for a credential.'),
|
|
813
|
+
'registerTool.auth.headerName': {
|
|
814
|
+
...field('string', "The header the credential goes in; an API key's own headerName comes first."),
|
|
586
815
|
unset: 'Authorization',
|
|
587
816
|
},
|
|
588
|
-
'auth.headerPrefix': {
|
|
589
|
-
...field('string',
|
|
817
|
+
'registerTool.auth.headerPrefix': {
|
|
818
|
+
...field('string', "Text put before the credential in the header; an API key's own headerPrefix comes first."),
|
|
590
819
|
unset: '"Bearer " for tokens, nothing for API keys',
|
|
591
820
|
},
|
|
592
|
-
'auth.
|
|
593
|
-
...field(
|
|
821
|
+
'registerTool.auth.queryParam': {
|
|
822
|
+
...field('string', 'For a service that takes its API key in the URL: the query parameter the key goes in, in place of a header.'),
|
|
823
|
+
unset: 'The key goes in a header',
|
|
824
|
+
},
|
|
825
|
+
'registerTool.auth.onUnauthenticated': {
|
|
826
|
+
...field(unionType(AUTH_UNAUTHENTICATED_POLICIES), "What happens when the credential is missing, expired, can't be refreshed or is refused by the service.", AUTH_UNAUTHENTICATED_POLICIES, {
|
|
594
827
|
gate: 'The turn stops and asks the host for a credential.',
|
|
595
828
|
report_to_model: "The model is told the tool isn't signed in, and the turn goes on.",
|
|
829
|
+
fail: 'The call fails as not signed in, for a key the host holds that no person can sign in to replace.',
|
|
596
830
|
}),
|
|
597
831
|
unset: 'gate',
|
|
598
832
|
},
|
|
599
|
-
'auth.scopes': field('string[]', 'The OAuth scopes the tool needs, shown when a turn stops to ask for a credential.'),
|
|
600
|
-
'auth.clientId': field('string', "Your OAuth client id, kept for the host's sign-in flow; the kernel doesn't read it."),
|
|
601
|
-
'auth.redirectUri': field('string', "Your OAuth redirect URI, kept for the host's sign-in flow; the kernel doesn't read it."),
|
|
602
|
-
'
|
|
603
|
-
'
|
|
604
|
-
'
|
|
605
|
-
...field('Record<string, unknown>', '
|
|
833
|
+
'registerTool.auth.scopes': field('string[]', 'The OAuth scopes the tool needs, shown when a turn stops to ask for a credential. A service asking for any other scope fails the call, with no new sign-in.'),
|
|
834
|
+
'registerTool.auth.clientId': field('string', "Your OAuth client id, kept for the host's sign-in flow; the kernel doesn't read it."),
|
|
835
|
+
'registerTool.auth.redirectUri': field('string', "Your OAuth redirect URI, kept for the host's sign-in flow; the kernel doesn't read it."),
|
|
836
|
+
'studio.authType': field(unionType(STUDIO_AUTH_TYPES), 'The kind of credential the tool expects, or none.', STUDIO_AUTH_TYPES, { none: 'The tool sends no credential.', ...CREDENTIAL_KINDS }),
|
|
837
|
+
'studio.testCredential': field('string', "A credential for this tool's connection tests, kept in the tab and never saved."),
|
|
838
|
+
'studio.stubOutput': {
|
|
839
|
+
...field('Record<string, unknown>', 'What a function tool returns in the studio, unless a demo handler has its name.'),
|
|
606
840
|
unset: 'A stand-in built from the output schema',
|
|
607
841
|
},
|
|
608
|
-
'
|
|
609
|
-
'
|
|
610
|
-
'
|
|
842
|
+
'studio.sampleInput': field('Record<string, unknown>', 'Arguments for the connection test, never saved.'),
|
|
843
|
+
'registerTool.inputSchema': field('Record<string, unknown>', "The tool's arguments as a JSON Schema, sent to the model."),
|
|
844
|
+
'registerTool.outputSchema': field('Record<string, unknown>', "The tool's result as a JSON Schema, which a function tool's stand-in result is built from."),
|
|
611
845
|
'registerStructured.jsonSchema': field('Record<string, unknown>', 'The JSON Schema a structured reply must follow, sent to the model as its response format.'),
|
|
612
|
-
access: field(unionType(TOOL_ACCESS), "What the tool can change, which taint.afterRemoteRead refuses calls by after a turn reads a remote tool's result.", TOOL_ACCESS, {
|
|
846
|
+
'registerTool.access': field(unionType(TOOL_ACCESS), "What the tool can change, which taint.afterRemoteRead refuses calls by after a turn reads a remote tool's result.", TOOL_ACCESS, {
|
|
613
847
|
'read-only': 'Only reads.',
|
|
614
848
|
'read-write': 'Creates or updates things.',
|
|
615
849
|
destructive: 'Deletes, charges, or does something else hard to undo.',
|
|
616
850
|
}),
|
|
617
|
-
loadTier: field(unionType(TOOL_LOAD_TIERS), 'When the tool becomes available to the model; live and host profiles load every allowed tool at the start.', TOOL_LOAD_TIERS, {
|
|
851
|
+
'registerTool.loadTier': field(unionType(TOOL_LOAD_TIERS), 'When the tool becomes available to the model; live and host profiles load every allowed tool at the start.', TOOL_LOAD_TIERS, {
|
|
618
852
|
T0: 'At the start of every turn.',
|
|
619
|
-
|
|
620
|
-
T2: 'When the tools.t2Loader tool loads it mid-turn (custom tools only).',
|
|
853
|
+
T2: 'On demand: when tools.t1Policy picks it at the start of a turn, or when the tools.t2Loader tool loads it mid-turn (custom tools only).',
|
|
621
854
|
}),
|
|
622
|
-
permission: field(unionType(TOOL_PERMISSION), "Whether the host must approve a call before it runs; the provider's own tools never ask.", TOOL_PERMISSION, {
|
|
855
|
+
'registerTool.permission': field(unionType(TOOL_PERMISSION), "Whether the host must approve a call before it runs; the provider's own tools never ask.", TOOL_PERMISSION, {
|
|
623
856
|
auto: 'Runs without asking.',
|
|
624
857
|
session_consent: 'Asks once; the approval lasts as long as the host keeps passing it back.',
|
|
625
858
|
always_confirm: 'Asks every time.',
|
|
626
859
|
}),
|
|
627
|
-
category: field('string', 'A label for grouping tools; nothing reads it yet.'),
|
|
628
|
-
labels: field('ToolLabels', "
|
|
629
|
-
'labels.activity': {
|
|
630
|
-
...field('string', "
|
|
860
|
+
'registerTool.category': field('string', 'A label for grouping tools; nothing reads it yet.'),
|
|
861
|
+
'registerTool.labels': field('ToolLabels', "Transcript text for a call. {path} reads a value from the call. {results.0.name} reads a list item. {path|text} shows the text when the value is unusable. With no fallback, the label is dropped. A label is one line, or a list read top to bottom: the first line that fits is shown. A line fits when each {path} has a value and its condition holds, as in 'when status is archived: archiving {title}'. Neighbouring lines that open with '+ ' show together, joined in words. The last line of a list must always fit."),
|
|
862
|
+
'registerTool.labels.activity': {
|
|
863
|
+
...field('string | string[]', "Transcript text while a call runs, e.g. 'Saving {title} to your collection'. {path} reads the call's input."),
|
|
864
|
+
unset: 'The tool name, in words',
|
|
865
|
+
},
|
|
866
|
+
'registerTool.labels.activityPast': {
|
|
867
|
+
...field('string | string[]', "What the transcript says once a call completes, e.g. 'Found {results.0.name}'. Each {path} is filled from the call's input, then its output."),
|
|
631
868
|
unset: 'The tool name, in words',
|
|
632
869
|
},
|
|
633
|
-
'labels.
|
|
634
|
-
...field('string', "What the transcript says
|
|
870
|
+
'registerTool.labels.activityFailed': {
|
|
871
|
+
...field('string | string[]', "What the transcript says when a call fails or the host labels it failed, e.g. 'Couldn't save {title}'. Each {path} is filled from the call's input."),
|
|
872
|
+
unset: "Couldn't complete, then the tool name in words",
|
|
873
|
+
},
|
|
874
|
+
'registerTool.labels.request': {
|
|
875
|
+
...field('string | string[]', "What the approval card says the agent wants to do, e.g. 'check the weather in {city}'. Each {path} is filled from the call's input."),
|
|
635
876
|
unset: 'The tool name, in words',
|
|
636
877
|
},
|
|
637
|
-
paths: {
|
|
638
|
-
...field('string[]', 'The turn paths this tool is offered on, where * means every path; a turn with no path gets only * tools.'),
|
|
878
|
+
'registerTool.paths': {
|
|
879
|
+
...field('string[]', 'The turn paths this tool is offered on, where * means every path; a turn with no path gets only * tools. Host profiles ignore it.'),
|
|
639
880
|
unset: 'Every path',
|
|
640
881
|
},
|
|
641
882
|
};
|
|
642
|
-
/** `
|
|
883
|
+
/** `labels.<key>` resolves to `labels.*` with that key's own note. */
|
|
643
884
|
export function fieldMeta(path) {
|
|
644
885
|
const meta = PROFILE_FIELDS[path] ?? EXTRA_FIELDS[path];
|
|
645
|
-
if (meta || !path.startsWith('
|
|
886
|
+
if (meta || !path.startsWith('labels.'))
|
|
646
887
|
return meta;
|
|
647
|
-
const key = path.slice('
|
|
648
|
-
const wildcard = PROFILE_FIELDS['
|
|
649
|
-
if (!wildcard || !Object.hasOwn(
|
|
888
|
+
const key = path.slice('labels.'.length);
|
|
889
|
+
const wildcard = PROFILE_FIELDS['labels.*'];
|
|
890
|
+
if (!wildcard || !Object.hasOwn(LABEL_NOTES, key))
|
|
650
891
|
return undefined;
|
|
651
|
-
return { ...wildcard, doc:
|
|
892
|
+
return { ...wildcard, doc: LABEL_NOTES[key] };
|
|
652
893
|
}
|
|
894
|
+
export { API_EXPORTS, REQUEST_FIELDS } from './api-catalog.js';
|
|
653
895
|
export { PROFILE_GRAPH, profileGraphFacet, spineFacetsForProfileType } from './profile-graph.js';
|