Add runtime provider controls and searchable AI routing
CI / verify (push) Has been cancelled
CI / publish (push) Has been cancelled

Manage provider keys at runtime, route current-information questions through server-side search with safe fallback, and scope OOBE usage claims to grants.
This commit is contained in:
Rocky
2026-08-22 16:33:17 +08:00
parent f8fa93dc48
commit 9fb947aa7d
43 changed files with 2079 additions and 80 deletions
+85 -5
View File
@@ -387,7 +387,9 @@ paths:
summary: Create a short-lived anonymous OOBE gateway grant
description: |
Verifies an App Attest assertion bound to the installation and returns
credentials limited to the four one-time onboarding AI features.
credentials limited to the four onboarding AI pages. Each feature can
succeed once within this short-lived grant; a later OOBE run receives
a new grant so the guided experience remains repeatable.
requestBody:
required: true
content:
@@ -477,11 +479,16 @@ paths:
The server deterministically selects model, thinking, search, tools, retry,
and output-budget policy from `capability` plus optional `taskKind`. It
never infers task type from `input` or `context`, and clients cannot
supply provider parameters. Search and tools are currently disabled.
supply provider parameters. Ordinary AI questions allow model-selected
server-side web search; current-information questions require it. Other
tools remain disabled. Search has no separate credit fee; settlement
uses the provider-reported LLM input and output Token counts, including
any search context charged by the provider.
For account grants, `oobe` is accepted only for dictation polish and the
first successful request per account is complimentary. Anonymous OOBE
grants require a matching `oobeFeature` and allow one successful request
per feature. Later attempts fail without falling through to paid billing.
per feature within that grant. A new OOBE grant starts a fresh guided
session; repeated calls within one page still fail without paid fallback.
parameters:
- $ref: "#/components/parameters/RequestId"
- name: capability
@@ -914,6 +921,63 @@ paths:
responses:
"204": { description: Session revoked }
"401": { description: Session is invalid }
/v1/admin/providers:
get:
security:
- adminMtls: []
adminSession: []
summary: List effective provider credential status without returning secrets
responses:
"200":
description: Provider credential status
content:
application/json:
schema:
type: array
minItems: 2
maxItems: 2
items: { $ref: "#/components/schemas/ProviderCredentialStatus" }
"403": { description: SUPER_ADMIN role is required }
/v1/admin/providers/{providerId}/api-key:
put:
security:
- adminMtls: []
adminSession: []
summary: Replace the runtime provider API key for new upstream requests
parameters:
- name: providerId
in: path
required: true
schema: { type: string, enum: [deepseek, volcengine] }
- $ref: "#/components/parameters/AdminCsrf"
- name: X-Request-ID
in: header
required: false
schema: { type: string, pattern: "^[A-Za-z0-9_-]{8,64}$" }
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
required: [apiKey]
properties:
apiKey:
type: string
minLength: 1
maxLength: 4096
pattern: "^[^\\r\\n]+$"
writeOnly: true
responses:
"200":
description: Runtime override saved, encrypted, and audited
content:
application/json:
schema: { $ref: "#/components/schemas/ProviderCredentialStatus" }
"400": { description: API key is blank, multiline, oversized, or malformed }
"403": { description: SUPER_ADMIN role and valid CSRF are required }
"404": { description: Provider is not supported }
/v1/admin/overview:
get:
security:
@@ -1293,6 +1357,7 @@ paths:
- CONTENT_HINT_PACK_SAVED
- CONTENT_HINT_FEED_SETTINGS_UPDATED
- CONTENT_HINT_FEED_GENERATED
- PROVIDER_API_KEY_UPDATED
- name: result
in: query
schema: { type: string, enum: [success, rejected] }
@@ -1812,6 +1877,19 @@ components:
type: ["string", "null"]
enum: [SUPER_ADMIN, SUPPORT, ANALYST, null]
description: CSRF material is intentionally not reconstructed or returned by session checks.
ProviderCredentialStatus:
type: object
additionalProperties: false
required: [providerId, configured, source]
properties:
providerId: { type: string, enum: [deepseek, volcengine] }
configured: { type: boolean }
source: { type: string, enum: [ENVIRONMENT, RUNTIME_OVERRIDE] }
updatedAt:
type: ["string", "null"]
format: date-time
description: Present only for a runtime override.
description: API key material is never returned.
AdminLoginResponse:
type: object
additionalProperties: false
@@ -2648,6 +2726,7 @@ components:
- translation
- edit_last_input
- ai_question
- current_information_question
- clipboard_transform
- custom_skill
- agent_planning
@@ -2655,7 +2734,8 @@ components:
description: |
Optional deterministic task selector. Allowed combinations are:
`polish` with `dictation_polish`, `translation`, or `edit_last_input`;
`ai` with `ai_question`, `clipboard_transform`, or `custom_skill`;
`ai` with `ai_question`, `current_information_question`,
`clipboard_transform`, or `custom_skill`;
and `agent` with `agent_planning`. Omission defaults respectively to
`dictation_polish`, `ai_question`, and `agent_planning`. A mismatch
returns `400 invalid_request`.
@@ -2676,7 +2756,7 @@ components:
description: |
Required for anonymous OOBE grants. The server validates that the
feature matches the requested capability and task kind, and allows
each feature to succeed only once per installation-bound subject.
each feature to succeed only once per short-lived OOBE grant.
CreateOobeGrantRequest:
type: object
additionalProperties: false