Per-tree AI model policy (owner-only admin view)
The operator decides which model providers exist (env / registry — Anthropic,
OpenAI, x.AI, Ollama, several at once). The *tree owner* decides who uses which:
- Members' assistant -> one configured provider (or none)
- Recommender (association/connection finder) -> one configured provider (or none)
- Owner -> may use any configured provider
Backend: two nullable columns on `trees` (ai_member_provider,
ai_recommender_provider) + migration; `configured_llm_providers()` exposes the
registry as {name, model} with no secrets; owner-gated GET/PATCH
/trees/{id}/ai validate names against the configured set. Frontend: owner-only
"AI models" page with a dropdown per role, graceful 403 for non-owners, and a
sidebar link.
Per-model-within-a-provider selection is a follow-up; today each provider maps
to its single configured model.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Justin Paul <justin@jpaul.me>
This commit is contained in:
+186
-1
@@ -4093,6 +4093,100 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/trees/{tree_id}/ai": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"ai"
|
||||
],
|
||||
"summary": "Get Ai Policy",
|
||||
"operationId": "get_ai_policy_api_v1_trees__tree_id__ai_get",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tree_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"title": "Tree Id"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TreeAiPolicyRead"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"patch": {
|
||||
"tags": [
|
||||
"ai"
|
||||
],
|
||||
"summary": "Update Ai Policy",
|
||||
"operationId": "update_ai_policy_api_v1_trees__tree_id__ai_patch",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tree_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"title": "Tree Id"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TreeAiPolicyUpdate"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TreeAiPolicyRead"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
@@ -4683,6 +4777,24 @@
|
||||
],
|
||||
"title": "CleanupResult"
|
||||
},
|
||||
"ConfiguredProvider": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"title": "Name"
|
||||
},
|
||||
"model": {
|
||||
"type": "string",
|
||||
"title": "Model"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"model"
|
||||
],
|
||||
"title": "ConfiguredProvider"
|
||||
},
|
||||
"DeceasedApply": {
|
||||
"properties": {
|
||||
"person_ids": {
|
||||
@@ -6812,6 +6924,79 @@
|
||||
],
|
||||
"title": "TokenRequest"
|
||||
},
|
||||
"TreeAiPolicyRead": {
|
||||
"properties": {
|
||||
"member_provider": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Member Provider"
|
||||
},
|
||||
"recommender_provider": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recommender Provider"
|
||||
},
|
||||
"configured_providers": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ConfiguredProvider"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Configured Providers"
|
||||
},
|
||||
"default_provider": {
|
||||
"type": "string",
|
||||
"title": "Default Provider"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"member_provider",
|
||||
"recommender_provider",
|
||||
"configured_providers",
|
||||
"default_provider"
|
||||
],
|
||||
"title": "TreeAiPolicyRead"
|
||||
},
|
||||
"TreeAiPolicyUpdate": {
|
||||
"properties": {
|
||||
"member_provider": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Member Provider"
|
||||
},
|
||||
"recommender_provider": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recommender Provider"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"title": "TreeAiPolicyUpdate"
|
||||
},
|
||||
"TreeCreate": {
|
||||
"properties": {
|
||||
"name": {
|
||||
@@ -7081,4 +7266,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user