feat: open source multi-user AI notebook with observability
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Annotated
|
||||
|
||||
from pydantic import (
|
||||
BaseModel,
|
||||
Field,
|
||||
StringConstraints,
|
||||
field_validator,
|
||||
model_validator,
|
||||
)
|
||||
|
||||
|
||||
Content = Annotated[str, StringConstraints(strip_whitespace=True, min_length=1)]
|
||||
|
||||
|
||||
class LoginRequest(BaseModel):
|
||||
access_key: str = Field(min_length=1, max_length=512)
|
||||
|
||||
|
||||
class FragmentCreate(BaseModel):
|
||||
content: Content = Field(max_length=20_000)
|
||||
|
||||
|
||||
class IdeaOverride(BaseModel):
|
||||
maturity: float | None = Field(default=None, ge=0, le=100)
|
||||
|
||||
|
||||
class DebugSharingUpdate(BaseModel):
|
||||
enabled: bool
|
||||
|
||||
|
||||
class IdeaAssessment(BaseModel):
|
||||
idea_id: str | None = Field(
|
||||
description="Existing idea id, or null only when a genuinely new idea is needed."
|
||||
)
|
||||
title: str = Field(min_length=1, max_length=80)
|
||||
summary: str = Field(min_length=1, max_length=280)
|
||||
maturity: float = Field(ge=0, le=100)
|
||||
confidence: float = Field(ge=0, le=1)
|
||||
motion: str = Field(min_length=1, max_length=24)
|
||||
position: str = Field(min_length=1, max_length=120)
|
||||
tension: str = Field(min_length=1, max_length=240)
|
||||
trajectory: str = Field(min_length=1, max_length=280)
|
||||
possible_moves: list[str] = Field(min_length=1, max_length=4)
|
||||
relevance: float = Field(default=1, ge=0, le=1)
|
||||
|
||||
@field_validator("possible_moves")
|
||||
@classmethod
|
||||
def moves_are_brief(cls, moves: list[str]) -> list[str]:
|
||||
return [move.strip()[:100] for move in moves if move.strip()][:4]
|
||||
|
||||
|
||||
class CuratorDecision(BaseModel):
|
||||
standalone: bool = Field(
|
||||
description="True when the fragment should remain only in the raw stream for now."
|
||||
)
|
||||
reasoning_note: str = Field(
|
||||
max_length=200,
|
||||
description="Brief audit note for the system, never shown in the capture stream.",
|
||||
)
|
||||
assessments: list[IdeaAssessment] = Field(default_factory=list, max_length=2)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def decision_is_coherent(self) -> "CuratorDecision":
|
||||
if self.standalone and self.assessments:
|
||||
raise ValueError("standalone decisions cannot contain assessments")
|
||||
if not self.standalone and not self.assessments:
|
||||
raise ValueError("non-standalone decisions require an assessment")
|
||||
return self
|
||||
Reference in New Issue
Block a user