using InvercargillSql.Orm; namespace ClankerSaddle.Data { /** * A software project worked on by saddle agents, stored in the * `projects` table. */ public class Project : Object { public int64 id { get; set; } public string name { get; set; default = ""; } public string git_url { get; set; default = ""; } public string default_branch { get; set; default = "main"; } public string? summary { get; set; default = null; } public DateTime? created_at { get; set; default = null; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("projects") .column("id", o => o.id, (o, v) => o.id = v) .column("name", o => o.name, (o, v) => o.name = v) .column("git_url", o => o.git_url, (o, v) => o.git_url = v) .column("default_branch", o => o.default_branch, (o, v) => o.default_branch = v) .column("summary", o => o.summary, (o, v) => o.summary = v) .column("created_at", o => o.created_at, (o, v) => o.created_at = v); } } /** * A directed relationship between two projects ('co-developed' or * 'reference'), stored in the `project_links` table. */ public class ProjectLink : Object { public int64 id { get; set; } public int64 parent_project_id { get; set; } public int64 linked_project_id { get; set; } public string relationship { get; set; default = "reference"; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("project_links") .column("id", o => o.id, (o, v) => o.id = v) .column("parent_project_id", o => o.parent_project_id, (o, v) => o.parent_project_id = v) .column("linked_project_id", o => o.linked_project_id, (o, v) => o.linked_project_id = v) .column("relationship", o => o.relationship, (o, v) => o.relationship = v); } } /** * A unit of work for a saddle agent: queued, dispatched to a saddle, * worked, possibly blocked on questions, and eventually done or failed. * Stored in the `tasks` table; child tasks reference their parent via * {@link parent_task_id}. Named `TaskEntity` (not `Task`) to stay * clear of `GLib.Task` in files that import Gio transitively. */ public class TaskEntity : Object { public int64 id { get; set; } public int64 parent_task_id { get; set; default = 0; } public int64 project_id { get; set; } public string title { get; set; default = ""; } public string? description { get; set; default = null; } public string status { get; set; default = "queued"; } public int64 priority { get; set; default = 5; } public bool is_design_task { get; set; default = false; } public string? working_branch { get; set; default = null; } public string? summary { get; set; default = null; } public string? plan { get; set; default = null; } public string? task_branch { get; set; default = null; } public string? branch_from { get; set; default = null; } public DateTime? created_at { get; set; default = null; } public DateTime? started_at { get; set; default = null; } public DateTime? completed_at { get; set; default = null; } public DateTime? suspended_at { get; set; default = null; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("tasks") .column("id", o => o.id, (o, v) => o.id = v) .column("parent_task_id", o => o.parent_task_id, (o, v) => o.parent_task_id = v) .column("project_id", o => o.project_id, (o, v) => o.project_id = v) .column("title", o => o.title, (o, v) => o.title = v) .column("description", o => o.description, (o, v) => o.description = v) .column("status", o => o.status, (o, v) => o.status = v) .column("priority", o => o.priority, (o, v) => o.priority = v) .column("is_design_task", o => o.is_design_task, (o, v) => o.is_design_task = v) .column("working_branch", o => o.working_branch, (o, v) => o.working_branch = v) .column("summary", o => o.summary, (o, v) => o.summary = v) .column("plan", o => o.plan, (o, v) => o.plan = v) .column("task_branch", o => o.task_branch, (o, v) => o.task_branch = v) .column("branch_from", o => o.branch_from, (o, v) => o.branch_from = v) .column("created_at", o => o.created_at, (o, v) => o.created_at = v) .column("started_at", o => o.started_at, (o, v) => o.started_at = v) .column("completed_at", o => o.completed_at, (o, v) => o.completed_at = v) .column("suspended_at", o => o.suspended_at, (o, v) => o.suspended_at = v); } } /** * One LLM-reported progress line on a task (`saddle progress-update`), * stored in the `task_progress` table. */ public class TaskProgress : Object { public int64 id { get; set; } public int64 task_id { get; set; } public string summary { get; set; default = ""; } public DateTime? created_at { get; set; default = null; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("task_progress") .column("id", o => o.id, (o, v) => o.id = v) .column("task_id", o => o.task_id, (o, v) => o.task_id = v) .column("summary", o => o.summary, (o, v) => o.summary = v) .column("created_at", o => o.created_at, (o, v) => o.created_at = v); } } /** An edge saying one task must finish before another may start. */ public class TaskDependency : Object { public int64 id { get; set; } public int64 task_id { get; set; } public int64 depends_on_task_id { get; set; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("task_dependencies") .column("id", o => o.id, (o, v) => o.id = v) .column("task_id", o => o.task_id, (o, v) => o.task_id = v) .column("depends_on_task_id", o => o.depends_on_task_id, (o, v) => o.depends_on_task_id = v); } } /** A remark on a task, authored either by a human or by the agent ('bot'). */ public class TaskComment : Object { public int64 id { get; set; } public int64 task_id { get; set; } public string author { get; set; default = "bot"; } public string body { get; set; default = ""; } public string? quote { get; set; default = null; } public DateTime? created_at { get; set; default = null; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("task_comments") .column("id", o => o.id, (o, v) => o.id = v) .column("task_id", o => o.task_id, (o, v) => o.task_id = v) .column("author", o => o.author, (o, v) => o.author = v) .column("body", o => o.body, (o, v) => o.body = v) .column("quote", o => o.quote, (o, v) => o.quote = v) .column("created_at", o => o.created_at, (o, v) => o.created_at = v); } } /** * A blocking prompt raised by an agent mid-task — a multiple-choice * {@link block_type} question, a request for comment or a review * request — answered by a human in the web UI; the answer is collected * by the saddle on its next * {@link ClankerSaddle.Api.SaddlePollEndpoint} poll. */ public class TaskBlock : Object { public int64 id { get; set; } public int64 task_id { get; set; } public string question { get; set; default = ""; } public string? answer { get; set; default = null; } public string block_type { get; set; default = "question"; } public string? options { get; set; default = null; } public string? body { get; set; default = null; } public DateTime? answered_at { get; set; default = null; } public DateTime? created_at { get; set; default = null; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("task_blocks") .column("id", o => o.id, (o, v) => o.id = v) .column("task_id", o => o.task_id, (o, v) => o.task_id = v) .column("question", o => o.question, (o, v) => o.question = v) .column("answer", o => o.answer, (o, v) => o.answer = v) .column("type", o => o.block_type, (o, v) => o.block_type = v) .column("options", o => o.options, (o, v) => o.options = v) .column("body", o => o.body, (o, v) => o.body = v) .column("answered_at", o => o.answered_at, (o, v) => o.answered_at = v) .column("created_at", o => o.created_at, (o, v) => o.created_at = v); } } /** * A saddle container registered with this app: one daemon managing one * bash session at a time, controlled over HTTP at {@link host}. */ public class Saddle : Object { public int64 id { get; set; } public string name { get; set; default = ""; } public string? container_id { get; set; default = null; } public string host { get; set; default = ""; } public string status { get; set; default = "offline"; } public int64 current_task_id { get; set; default = 0; } public DateTime? allocated_at { get; set; default = null; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("saddles") .column("id", o => o.id, (o, v) => o.id = v) .column("name", o => o.name, (o, v) => o.name = v) .column("container_id", o => o.container_id, (o, v) => o.container_id = v) .column("host", o => o.host, (o, v) => o.host = v) .column("status", o => o.status, (o, v) => o.status = v) .column("current_task_id", o => o.current_task_id, (o, v) => o.current_task_id = v) .column("allocated_at", o => o.allocated_at, (o, v) => o.allocated_at = v); } } /** * One run of a task on a saddle: opened when the dispatcher assigns * the task, closed with an outcome when the session ends. */ public class Session : Object { public int64 id { get; set; } public int64 task_id { get; set; } public int64 saddle_id { get; set; } public DateTime? started_at { get; set; default = null; } public DateTime? ended_at { get; set; default = null; } public string? outcome { get; set; default = null; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("sessions") .column("id", o => o.id, (o, v) => o.id = v) .column("task_id", o => o.task_id, (o, v) => o.task_id = v) .column("saddle_id", o => o.saddle_id, (o, v) => o.saddle_id = v) .column("started_at", o => o.started_at, (o, v) => o.started_at = v) .column("ended_at", o => o.ended_at, (o, v) => o.ended_at = v) .column("outcome", o => o.outcome, (o, v) => o.outcome = v); } } /** * A numbered entry captured during a {@link Session} — a bash * command/output pair or a conversation-level event (comment, block, * progress, review, plan, user-comment) — stored as the saddle daemon * reports it. */ public class SessionCommand : Object { public int64 id { get; set; } public int64 session_id { get; set; } public string command_text { get; set; default = ""; } public string? output_text { get; set; default = null; } public int64 exit_code { get; set; default = 0; } public string entry_type { get; set; default = "command"; } public string? piped_input { get; set; default = null; } public DateTime? started_at { get; set; default = null; } public DateTime? completed_at { get; set; default = null; } public int64 duration_ms { get; set; default = 0; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("session_commands") .column("id", o => o.id, (o, v) => o.id = v) .column("session_id", o => o.session_id, (o, v) => o.session_id = v) .column("command_text", o => o.command_text, (o, v) => o.command_text = v) .column("output_text", o => o.output_text, (o, v) => o.output_text = v) .column("exit_code", o => o.exit_code, (o, v) => o.exit_code = v) .column("type", o => o.entry_type, (o, v) => o.entry_type = v) .column("piped_input", o => o.piped_input, (o, v) => o.piped_input = v) .column("started_at", o => o.started_at, (o, v) => o.started_at = v) .column("completed_at", o => o.completed_at, (o, v) => o.completed_at = v) .column("duration_ms", o => o.duration_ms, (o, v) => o.duration_ms = v); } } /** * A reusable instruction the dispatched agent must follow, stored in * the `rules` table and attached to projects and/or tasks. */ public class Rule : Object { public int64 id { get; set; } public string name { get; set; default = ""; } public string body { get; set; default = ""; } public DateTime? created_at { get; set; default = null; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("rules") .column("id", o => o.id, (o, v) => o.id = v) .column("name", o => o.name, (o, v) => o.name = v) .column("body", o => o.body, (o, v) => o.body = v) .column("created_at", o => o.created_at, (o, v) => o.created_at = v); } } /** An attachment of a rule to a project (`rule_projects`). */ public class RuleProject : Object { public int64 id { get; set; } public int64 rule_id { get; set; } public int64 project_id { get; set; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("rule_projects") .column("id", o => o.id, (o, v) => o.id = v) .column("rule_id", o => o.rule_id, (o, v) => o.rule_id = v) .column("project_id", o => o.project_id, (o, v) => o.project_id = v); } } /** An attachment of a rule to a task (`task_rules`). */ public class TaskRule : Object { public int64 id { get; set; } public int64 rule_id { get; set; } public int64 task_id { get; set; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("task_rules") .column("id", o => o.id, (o, v) => o.id = v) .column("rule_id", o => o.rule_id, (o, v) => o.rule_id = v) .column("task_id", o => o.task_id, (o, v) => o.task_id = v); } } /** * An LLM-authored remark about a project (`saddle note` via the * callback endpoint), curated from the project page. The source task * is null for notes without one. */ public class ProjectNote : Object { public int64 id { get; set; } public int64 project_id { get; set; } public int64 source_task_id { get; set; default = 0; } public string body { get; set; default = ""; } public DateTime? created_at { get; set; default = null; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("project_notes") .column("id", o => o.id, (o, v) => o.id = v) .column("project_id", o => o.project_id, (o, v) => o.project_id = v) .column("source_task_id", o => o.source_task_id, (o, v) => o.source_task_id = v ?? 0) .column("body", o => o.body, (o, v) => o.body = v) .column("created_at", o => o.created_at, (o, v) => o.created_at = v); } } /** * One raw PTY output chunk of a {@link Session}, pulled from the * daemon's `GET /log` ring buffer while the session is active * (`session_raw_log`); `seq` is the daemon's monotonic chunk * sequence number. */ public class SessionRawLog : Object { public int64 id { get; set; } public int64 session_id { get; set; } public int64 seq { get; set; } public string chunk { get; set; default = ""; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("session_raw_log") .column("id", o => o.id, (o, v) => o.id = v) .column("session_id", o => o.session_id, (o, v) => o.session_id = v) .column("seq", o => o.seq, (o, v) => o.seq = v) .column("chunk", o => o.chunk, (o, v) => o.chunk = v); } } /** * A named tag used for dispatch routing (`capabilities`): saddles * declare the tags they carry, tasks the tags they require. */ public class Capability : Object { public int64 id { get; set; } public string name { get; set; default = ""; } public DateTime? created_at { get; set; default = null; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("capabilities") .column("id", o => o.id, (o, v) => o.id = v) .column("name", o => o.name, (o, v) => o.name = v) .column("created_at", o => o.created_at, (o, v) => o.created_at = v); } } /** A tag declaration on a saddle (`saddle_capabilities`). */ public class SaddleCapability : Object { public int64 id { get; set; } public int64 capability_id { get; set; } public int64 saddle_id { get; set; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("saddle_capabilities") .column("id", o => o.id, (o, v) => o.id = v) .column("capability_id", o => o.capability_id, (o, v) => o.capability_id = v) .column("saddle_id", o => o.saddle_id, (o, v) => o.saddle_id = v); } } /** A required tag on a task (`task_capabilities`). */ public class TaskCapability : Object { public int64 id { get; set; } public int64 capability_id { get; set; } public int64 task_id { get; set; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("task_capabilities") .column("id", o => o.id, (o, v) => o.id = v) .column("capability_id", o => o.capability_id, (o, v) => o.capability_id = v) .column("task_id", o => o.task_id, (o, v) => o.task_id = v); } } /** * A bearer token authorising one saddle daemon's calls against the * `/api/saddle/*` endpoints, generated at registration. */ public class ApiToken : Object { public int64 id { get; set; } public int64 saddle_id { get; set; } public string token { get; set; default = ""; } public DateTime? created_at { get; set; default = null; } public static void entity_mapping(EntityMapperBuilder cfg) { cfg.table("api_tokens") .column("id", o => o.id, (o, v) => o.id = v) .column("saddle_id", o => o.saddle_id, (o, v) => o.saddle_id = v) .column("token", o => o.token, (o, v) => o.token = v) .column("created_at", o => o.created_at, (o, v) => o.created_at = v); } } }