updates on the ai and agent and all thse things awith onboarding
This commit is contained in:
123
models/ai_registry.go
Normal file
123
models/ai_registry.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// The AI agent registry: the one source of truth for which agents exist, which
|
||||
// skills they run and which tools those skills may call. The console's Agent
|
||||
// Studio reads it (and edits the few operator-owned columns); the AI_engine
|
||||
// will read it too. Plan: krow_talent_app/docs/agent-platform-plan.md.
|
||||
//
|
||||
// Agents, tools and seeded skills are DEFINED IN CODE (internal/ai/registry)
|
||||
// and upserted on every boot. Only the columns marked "operator-owned" below
|
||||
// change at runtime, only by roleid 1, and every change writes an
|
||||
// AIRegistryAudit row in the same transaction. A tool can never be invented
|
||||
// from the console: a tool with no implementation behind it is a lie on screen.
|
||||
//
|
||||
// JSON documents are stored as jsonb in string fields, the same way
|
||||
// AgentDecision stores its context — the controllers re-emit them as raw JSON.
|
||||
|
||||
// AIAgent is one agent, in AI_engine or in the console.
|
||||
type AIAgent struct {
|
||||
Agentid string `json:"agentid" gorm:"primaryKey;column:agentid;size:64"`
|
||||
Name string `json:"name" gorm:"column:name;not null"`
|
||||
Runtime string `json:"runtime" gorm:"column:runtime;size:20;not null"` // engine, console
|
||||
Classref string `json:"classref" gorm:"column:classref"` // where it is implemented, file:line
|
||||
Purpose string `json:"purpose" gorm:"column:purpose"`
|
||||
// Wakeon is what makes the agent run: a NATS subject, a direct task, an
|
||||
// operator prompt. Free text for people, not parsed.
|
||||
Wakeon string `json:"wakeon" gorm:"column:wakeon"`
|
||||
// Status is what the code does today, not what the docs claim:
|
||||
// live, partial, simulation, broken, unmerged, retired.
|
||||
Status string `json:"status" gorm:"column:status;size:20;not null"`
|
||||
// Llmdecision names the model call the agent makes, empty when it makes none.
|
||||
Llmdecision string `json:"llmdecision" gorm:"column:llmdecision"`
|
||||
// Hasautonomygate is true for the agents whose writes are behind an
|
||||
// autonomy switch in AI_engine (Dispatch, Exception, Express). Autonomy can
|
||||
// only be set on these.
|
||||
Hasautonomygate bool `json:"hasautonomygate" gorm:"column:hasautonomygate;default:false"`
|
||||
Sortorder int `json:"sortorder" gorm:"column:sortorder;default:0"`
|
||||
|
||||
// Operator-owned.
|
||||
Autonomous bool `json:"autonomous" gorm:"column:autonomous;default:false"`
|
||||
Model string `json:"model" gorm:"column:model;size:64"` // empty = the engine's own default
|
||||
|
||||
Updatedby *int `json:"updatedby" gorm:"column:updatedby"`
|
||||
Createdat time.Time `json:"createdat" gorm:"column:createdat;default:CURRENT_TIMESTAMP"`
|
||||
Updatedat time.Time `json:"updatedat" gorm:"column:updatedat;default:CURRENT_TIMESTAMP"`
|
||||
}
|
||||
|
||||
func (AIAgent) TableName() string { return "aiagents" }
|
||||
|
||||
// AITool is one capability a skill may call. Entirely code-defined.
|
||||
type AITool struct {
|
||||
Toolname string `json:"toolname" gorm:"primaryKey;column:toolname;size:64"`
|
||||
Description string `json:"description" gorm:"column:description;not null"`
|
||||
// Kind is read, write or notify. A write or notify tool always requires
|
||||
// confirmation unless its agent is autonomous.
|
||||
Kind string `json:"kind" gorm:"column:kind;size:10;not null"`
|
||||
Target string `json:"target" gorm:"column:target"` // the system it touches
|
||||
Implementedat string `json:"implementedat" gorm:"column:implementedat"` // file:line today
|
||||
Inputschema string `json:"-" gorm:"column:inputschema;type:jsonb"`
|
||||
Requiresconfirmation bool `json:"requiresconfirmation" gorm:"column:requiresconfirmation;default:false"`
|
||||
Createdat time.Time `json:"createdat" gorm:"column:createdat;default:CURRENT_TIMESTAMP"`
|
||||
Updatedat time.Time `json:"updatedat" gorm:"column:updatedat;default:CURRENT_TIMESTAMP"`
|
||||
}
|
||||
|
||||
func (AITool) TableName() string { return "aitools" }
|
||||
|
||||
// AISkill is a named behaviour of one agent, using one or more tools.
|
||||
type AISkill struct {
|
||||
Skillid string `json:"skillid" gorm:"primaryKey;column:skillid;size:64"`
|
||||
Agentid string `json:"agentid" gorm:"column:agentid;size:64;not null;index"`
|
||||
Title string `json:"title" gorm:"column:title;not null"`
|
||||
Category string `json:"category" gorm:"column:category;size:40"`
|
||||
Description string `json:"description" gorm:"column:description"`
|
||||
Sampleprompt string `json:"sampleprompt" gorm:"column:sampleprompt"`
|
||||
// Source is engine, console (the ops-layer skills), or custom (created in
|
||||
// Agent Studio). Custom skills are never touched by the seed.
|
||||
Source string `json:"source" gorm:"column:source;size:20;not null"`
|
||||
Thresholdsschema string `json:"-" gorm:"column:thresholdsschema;type:jsonb"`
|
||||
|
||||
// Operator-owned.
|
||||
// No gorm default on purpose: with `default:true` gorm omits a false value
|
||||
// from the INSERT and the database default wins, so a skill seeded OFF came
|
||||
// up ON (caught by TestPGSkillSeededOffStaysOff). Every insert sets it.
|
||||
Enabled bool `json:"enabled" gorm:"column:enabled;not null"`
|
||||
Thresholds string `json:"-" gorm:"column:thresholds;type:jsonb"`
|
||||
|
||||
// Version increases on every operator change, so a consumer holding a copy
|
||||
// can tell it is stale.
|
||||
Version int `json:"version" gorm:"column:version;default:1"`
|
||||
Updatedby *int `json:"updatedby" gorm:"column:updatedby"`
|
||||
Createdat time.Time `json:"createdat" gorm:"column:createdat;default:CURRENT_TIMESTAMP"`
|
||||
Updatedat time.Time `json:"updatedat" gorm:"column:updatedat;default:CURRENT_TIMESTAMP"`
|
||||
}
|
||||
|
||||
func (AISkill) TableName() string { return "aiskills" }
|
||||
|
||||
// AISkillTool links a skill to a tool it may call.
|
||||
type AISkillTool struct {
|
||||
Skillid string `json:"skillid" gorm:"primaryKey;column:skillid;size:64"`
|
||||
Toolname string `json:"toolname" gorm:"primaryKey;column:toolname;size:64"`
|
||||
}
|
||||
|
||||
func (AISkillTool) TableName() string { return "aiskilltools" }
|
||||
|
||||
// AIRegistryAudit is one operator change to the registry. Written in the same
|
||||
// transaction as the change, so a change without its audit row cannot exist.
|
||||
type AIRegistryAudit struct {
|
||||
Auditid int64 `json:"auditid" gorm:"primaryKey;column:auditid;autoIncrement"`
|
||||
Entity string `json:"entity" gorm:"column:entity;size:20;not null;index:idx_airegistryaudit_entity"` // agent, skill
|
||||
Entityid string `json:"entityid" gorm:"column:entityid;size:64;not null;index:idx_airegistryaudit_entity"`
|
||||
Field string `json:"field" gorm:"column:field;size:40;not null"`
|
||||
Oldvalue string `json:"-" gorm:"column:oldvalue;type:jsonb"`
|
||||
Newvalue string `json:"-" gorm:"column:newvalue;type:jsonb"`
|
||||
Changedby int `json:"changedby" gorm:"column:changedby;not null"`
|
||||
// Changedbyemail is the login's email from its token. Recorded alongside
|
||||
// the id because an admin login with no appusers row carries user id 0 —
|
||||
// found in the Phase 2 end-to-end run, where every audit row said "0".
|
||||
Changedbyemail string `json:"changedbyemail" gorm:"column:changedbyemail;size:255"`
|
||||
Changedat time.Time `json:"changedat" gorm:"column:changedat;default:CURRENT_TIMESTAMP;index"`
|
||||
}
|
||||
|
||||
func (AIRegistryAudit) TableName() string { return "airegistryaudit" }
|
||||
35
models/ai_runs.go
Normal file
35
models/ai_runs.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// AIAgentRun is one task an AI_engine agent finished, recorded from its
|
||||
// `telemetry.task` event (internal/ai/telemetry). Phase 4 of
|
||||
// krow_talent_app/docs/agent-platform-plan.md: before this, a run existed only
|
||||
// as a log line and an ephemeral NATS message, so nothing could say how often
|
||||
// an agent ran or how often it failed.
|
||||
//
|
||||
// Append-only, and pruned after 30 days. Live agent STATE (the 5-second
|
||||
// `telemetry.agent` heartbeat) is deliberately not stored here — it is
|
||||
// ephemeral and lives in Redis.
|
||||
type AIAgentRun struct {
|
||||
Runid int64 `json:"runid" gorm:"primaryKey;column:runid;autoIncrement"`
|
||||
Agentid string `json:"agentid" gorm:"column:agentid;size:64;not null;index:idx_aiagentruns_agent_received,priority:1;uniqueIndex:uq_aiagentruns_agent_task,priority:1"`
|
||||
// Taskid is the engine's task id. Null when the event carried none; the
|
||||
// unique index then does not apply (Postgres treats NULLs as distinct), so
|
||||
// a redelivered event with an id is stored once and one without is not lost.
|
||||
Taskid *string `json:"taskid" gorm:"column:taskid;size:64;uniqueIndex:uq_aiagentruns_agent_task,priority:2"`
|
||||
Tasktype string `json:"tasktype" gorm:"column:tasktype;size:64"`
|
||||
Status string `json:"status" gorm:"column:status;size:20;not null"` // completed, failed
|
||||
Error string `json:"error" gorm:"column:error;type:text"`
|
||||
// Durationms is how long the task ran, as the engine measured it.
|
||||
Durationms int `json:"durationms" gorm:"column:durationms"`
|
||||
// Occurredat is the engine's own timestamp, kept for display only: it is a
|
||||
// naive local time from whatever clock and zone the engine host runs.
|
||||
// Windows and ordering use Receivedat, which is this backend's clock as a
|
||||
// true instant (time.Now) — the column is timestamptz, so utils.DBNow's
|
||||
// IST-digits-labelled-UTC value would be 5h30m off here.
|
||||
Occurredat *time.Time `json:"occurredat" gorm:"column:occurredat"`
|
||||
Receivedat time.Time `json:"receivedat" gorm:"column:receivedat;not null;index:idx_aiagentruns_agent_received,priority:2;index:idx_aiagentruns_received"`
|
||||
}
|
||||
|
||||
func (AIAgentRun) TableName() string { return "aiagentruns" }
|
||||
Reference in New Issue
Block a user