package models import ( "encoding/json" "time" "github.com/google/uuid" ) // AgentSession is one dashboard-agent conversation. Sessions are per-user // (private to the member who started them) unless the org enables // assistant_shared_history, which makes every conversation workspace-shared. type AgentSession struct { ID uuid.UUID `json:"id"` OrgID uuid.UUID `json:"org_id"` UserID uuid.UUID `json:"user_id"` Title string `json:"title"` Context AgentSessionContext `json:"context"` // UserName is the owner's display name, populated only by the shared // org-wide listing so the history rail can attribute conversations. UserName string `json:"user_name,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // AgentSessionContext is the read-then-execute jsonb blob on a session: the // client's page/resource awareness, the model chosen for the run, and any tool // call paused awaiting approval. Validated at the app boundary (this struct), // never filtered in SQL. type AgentSessionContext struct { // Page / Resource mirror the presence shape the client already pushes // ({page, resource}); injected into the system prompt as context. Page string `json:"page,omitempty"` Resource string `json:"resource,omitempty"` // Model is the provider model id resolved for this session's tier. Model string `json:"model,omitempty"` // FreeModel is true when the session ran on a free/local backend // (AI_FREE): persisted so a reopened tab still shows the warning. FreeModel bool `json:"free_model,omitempty"` // Pending is the tool call awaiting the user's approve/deny when a run is // paused; nil when the session is idle or running. Pending *PendingAgentTool `json:"pending,omitempty"` } // PendingAgentTool is a write/send tool call paused for human approval. type PendingAgentTool struct { MessageID string `json:"message_id"` ToolCallID string `json:"tool_call_id"` ToolName string `json:"tool_name"` Risk string `json:"risk"` Args json.RawMessage `json:"args"` ArgsSummary string `json:"args_summary,omitempty"` } // AgentMessageRow is one persisted transcript turn. Content is the serialized // provider-agnostic message (role, text, tool_calls, tool result) so a run // resumes losslessly after an approval pause. type AgentMessageRow struct { ID uuid.UUID `json:"id"` SessionID uuid.UUID `json:"session_id"` Role string `json:"role"` Content json.RawMessage `json:"content"` Tokens int `json:"tokens"` CreatedAt time.Time `json:"created_at"` } // AIToolPolicy is a per-org "always allow this tool" decision. Only write-class // tools can have a policy; send-class tools are never auto-allowed. type AIToolPolicy struct { OrgID uuid.UUID `json:"org_id"` ToolName string `json:"tool_name"` Decision string `json:"decision"` CreatedBy *uuid.UUID `json:"created_by,omitempty"` CreatedAt time.Time `json:"created_at"` }