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:
Vendored
+109
@@ -1031,6 +1031,24 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/trees/{tree_id}/ai": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
/** Get Ai Policy */
|
||||
get: operations["get_ai_policy_api_v1_trees__tree_id__ai_get"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
/** Update Ai Policy */
|
||||
patch: operations["update_ai_policy_api_v1_trees__tree_id__ai_patch"];
|
||||
trace?: never;
|
||||
};
|
||||
}
|
||||
export type webhooks = Record<string, never>;
|
||||
export interface components {
|
||||
@@ -1215,6 +1233,13 @@ export interface components {
|
||||
/** Updated */
|
||||
updated: number;
|
||||
};
|
||||
/** ConfiguredProvider */
|
||||
ConfiguredProvider: {
|
||||
/** Name */
|
||||
name: string;
|
||||
/** Model */
|
||||
model: string;
|
||||
};
|
||||
/** DeceasedApply */
|
||||
DeceasedApply: {
|
||||
/** Person Ids */
|
||||
@@ -1886,6 +1911,24 @@ export interface components {
|
||||
/** Token */
|
||||
token: string;
|
||||
};
|
||||
/** TreeAiPolicyRead */
|
||||
TreeAiPolicyRead: {
|
||||
/** Member Provider */
|
||||
member_provider: string | null;
|
||||
/** Recommender Provider */
|
||||
recommender_provider: string | null;
|
||||
/** Configured Providers */
|
||||
configured_providers: components["schemas"]["ConfiguredProvider"][];
|
||||
/** Default Provider */
|
||||
default_provider: string;
|
||||
};
|
||||
/** TreeAiPolicyUpdate */
|
||||
TreeAiPolicyUpdate: {
|
||||
/** Member Provider */
|
||||
member_provider?: string | null;
|
||||
/** Recommender Provider */
|
||||
recommender_provider?: string | null;
|
||||
};
|
||||
/** TreeCreate */
|
||||
TreeCreate: {
|
||||
/** Name */
|
||||
@@ -4651,4 +4694,70 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
get_ai_policy_api_v1_trees__tree_id__ai_get: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
tree_id: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Successful Response */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["TreeAiPolicyRead"];
|
||||
};
|
||||
};
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
update_ai_policy_api_v1_trees__tree_id__ai_patch: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
tree_id: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["TreeAiPolicyUpdate"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Successful Response */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["TreeAiPolicyRead"];
|
||||
};
|
||||
};
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user