Entities.vala 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. using InvercargillSql.Orm;
  2. namespace ClankerSaddle.Data {
  3. /**
  4. * A software project worked on by saddle agents, stored in the
  5. * `projects` table.
  6. */
  7. public class Project : Object {
  8. public int64 id { get; set; }
  9. public string name { get; set; default = ""; }
  10. public string git_url { get; set; default = ""; }
  11. public string default_branch { get; set; default = "main"; }
  12. public string? summary { get; set; default = null; }
  13. public DateTime? created_at { get; set; default = null; }
  14. public static void entity_mapping(EntityMapperBuilder<Project> cfg) {
  15. cfg.table("projects")
  16. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  17. .column<string>("name", o => o.name, (o, v) => o.name = v)
  18. .column<string>("git_url", o => o.git_url, (o, v) => o.git_url = v)
  19. .column<string>("default_branch", o => o.default_branch, (o, v) => o.default_branch = v)
  20. .column<string>("summary", o => o.summary, (o, v) => o.summary = v)
  21. .column<DateTime?>("created_at", o => o.created_at, (o, v) => o.created_at = v);
  22. }
  23. }
  24. /**
  25. * A directed relationship between two projects ('co-developed' or
  26. * 'reference'), stored in the `project_links` table.
  27. */
  28. public class ProjectLink : Object {
  29. public int64 id { get; set; }
  30. public int64 parent_project_id { get; set; }
  31. public int64 linked_project_id { get; set; }
  32. public string relationship { get; set; default = "reference"; }
  33. public static void entity_mapping(EntityMapperBuilder<ProjectLink> cfg) {
  34. cfg.table("project_links")
  35. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  36. .column<int64?>("parent_project_id", o => o.parent_project_id, (o, v) => o.parent_project_id = v)
  37. .column<int64?>("linked_project_id", o => o.linked_project_id, (o, v) => o.linked_project_id = v)
  38. .column<string>("relationship", o => o.relationship, (o, v) => o.relationship = v);
  39. }
  40. }
  41. /**
  42. * A unit of work for a saddle agent: queued, dispatched to a saddle,
  43. * worked, possibly blocked on questions, and eventually done or failed.
  44. * Stored in the `tasks` table; child tasks reference their parent via
  45. * {@link parent_task_id}. Named `TaskEntity` (not `Task`) to stay
  46. * clear of `GLib.Task` in files that import Gio transitively.
  47. */
  48. public class TaskEntity : Object {
  49. public int64 id { get; set; }
  50. public int64 parent_task_id { get; set; default = 0; }
  51. public int64 project_id { get; set; }
  52. public string title { get; set; default = ""; }
  53. public string? description { get; set; default = null; }
  54. public string status { get; set; default = "queued"; }
  55. public int64 priority { get; set; default = 5; }
  56. public bool is_design_task { get; set; default = false; }
  57. public string? working_branch { get; set; default = null; }
  58. public string? summary { get; set; default = null; }
  59. public string? plan { get; set; default = null; }
  60. public string? task_branch { get; set; default = null; }
  61. public string? branch_from { get; set; default = null; }
  62. public DateTime? created_at { get; set; default = null; }
  63. public DateTime? started_at { get; set; default = null; }
  64. public DateTime? completed_at { get; set; default = null; }
  65. public DateTime? suspended_at { get; set; default = null; }
  66. public static void entity_mapping(EntityMapperBuilder<TaskEntity> cfg) {
  67. cfg.table("tasks")
  68. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  69. .column<int64?>("parent_task_id", o => o.parent_task_id, (o, v) => o.parent_task_id = v)
  70. .column<int64?>("project_id", o => o.project_id, (o, v) => o.project_id = v)
  71. .column<string>("title", o => o.title, (o, v) => o.title = v)
  72. .column<string>("description", o => o.description, (o, v) => o.description = v)
  73. .column<string>("status", o => o.status, (o, v) => o.status = v)
  74. .column<int64?>("priority", o => o.priority, (o, v) => o.priority = v)
  75. .column<bool>("is_design_task", o => o.is_design_task, (o, v) => o.is_design_task = v)
  76. .column<string>("working_branch", o => o.working_branch, (o, v) => o.working_branch = v)
  77. .column<string>("summary", o => o.summary, (o, v) => o.summary = v)
  78. .column<string>("plan", o => o.plan, (o, v) => o.plan = v)
  79. .column<string>("task_branch", o => o.task_branch, (o, v) => o.task_branch = v)
  80. .column<string>("branch_from", o => o.branch_from, (o, v) => o.branch_from = v)
  81. .column<DateTime?>("created_at", o => o.created_at, (o, v) => o.created_at = v)
  82. .column<DateTime?>("started_at", o => o.started_at, (o, v) => o.started_at = v)
  83. .column<DateTime?>("completed_at", o => o.completed_at, (o, v) => o.completed_at = v)
  84. .column<DateTime?>("suspended_at", o => o.suspended_at, (o, v) => o.suspended_at = v);
  85. }
  86. }
  87. /**
  88. * One LLM-reported progress line on a task (`saddle progress-update`),
  89. * stored in the `task_progress` table.
  90. */
  91. public class TaskProgress : Object {
  92. public int64 id { get; set; }
  93. public int64 task_id { get; set; }
  94. public string summary { get; set; default = ""; }
  95. public DateTime? created_at { get; set; default = null; }
  96. public static void entity_mapping(EntityMapperBuilder<TaskProgress> cfg) {
  97. cfg.table("task_progress")
  98. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  99. .column<int64?>("task_id", o => o.task_id, (o, v) => o.task_id = v)
  100. .column<string>("summary", o => o.summary, (o, v) => o.summary = v)
  101. .column<DateTime?>("created_at", o => o.created_at, (o, v) => o.created_at = v);
  102. }
  103. }
  104. /** An edge saying one task must finish before another may start. */
  105. public class TaskDependency : Object {
  106. public int64 id { get; set; }
  107. public int64 task_id { get; set; }
  108. public int64 depends_on_task_id { get; set; }
  109. public static void entity_mapping(EntityMapperBuilder<TaskDependency> cfg) {
  110. cfg.table("task_dependencies")
  111. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  112. .column<int64?>("task_id", o => o.task_id, (o, v) => o.task_id = v)
  113. .column<int64?>("depends_on_task_id", o => o.depends_on_task_id, (o, v) => o.depends_on_task_id = v);
  114. }
  115. }
  116. /** A remark on a task, authored either by a human or by the agent ('bot'). */
  117. public class TaskComment : Object {
  118. public int64 id { get; set; }
  119. public int64 task_id { get; set; }
  120. public string author { get; set; default = "bot"; }
  121. public string body { get; set; default = ""; }
  122. public string? quote { get; set; default = null; }
  123. public DateTime? created_at { get; set; default = null; }
  124. public static void entity_mapping(EntityMapperBuilder<TaskComment> cfg) {
  125. cfg.table("task_comments")
  126. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  127. .column<int64?>("task_id", o => o.task_id, (o, v) => o.task_id = v)
  128. .column<string>("author", o => o.author, (o, v) => o.author = v)
  129. .column<string>("body", o => o.body, (o, v) => o.body = v)
  130. .column<string>("quote", o => o.quote, (o, v) => o.quote = v)
  131. .column<DateTime?>("created_at", o => o.created_at, (o, v) => o.created_at = v);
  132. }
  133. }
  134. /**
  135. * A blocking prompt raised by an agent mid-task — a multiple-choice
  136. * {@link block_type} question, a request for comment or a review
  137. * request — answered by a human in the web UI; the answer is collected
  138. * by the saddle on its next
  139. * {@link ClankerSaddle.Api.SaddlePollEndpoint} poll.
  140. */
  141. public class TaskBlock : Object {
  142. public int64 id { get; set; }
  143. public int64 task_id { get; set; }
  144. public string question { get; set; default = ""; }
  145. public string? answer { get; set; default = null; }
  146. public string block_type { get; set; default = "question"; }
  147. public string? options { get; set; default = null; }
  148. public string? body { get; set; default = null; }
  149. public DateTime? answered_at { get; set; default = null; }
  150. public DateTime? created_at { get; set; default = null; }
  151. public static void entity_mapping(EntityMapperBuilder<TaskBlock> cfg) {
  152. cfg.table("task_blocks")
  153. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  154. .column<int64?>("task_id", o => o.task_id, (o, v) => o.task_id = v)
  155. .column<string>("question", o => o.question, (o, v) => o.question = v)
  156. .column<string>("answer", o => o.answer, (o, v) => o.answer = v)
  157. .column<string>("type", o => o.block_type, (o, v) => o.block_type = v)
  158. .column<string>("options", o => o.options, (o, v) => o.options = v)
  159. .column<string>("body", o => o.body, (o, v) => o.body = v)
  160. .column<DateTime?>("answered_at", o => o.answered_at, (o, v) => o.answered_at = v)
  161. .column<DateTime?>("created_at", o => o.created_at, (o, v) => o.created_at = v);
  162. }
  163. }
  164. /**
  165. * A saddle container registered with this app: one daemon managing one
  166. * bash session at a time, controlled over HTTP at {@link host}.
  167. */
  168. public class Saddle : Object {
  169. public int64 id { get; set; }
  170. public string name { get; set; default = ""; }
  171. public string? container_id { get; set; default = null; }
  172. public string host { get; set; default = ""; }
  173. public string status { get; set; default = "offline"; }
  174. public int64 current_task_id { get; set; default = 0; }
  175. public DateTime? allocated_at { get; set; default = null; }
  176. public static void entity_mapping(EntityMapperBuilder<Saddle> cfg) {
  177. cfg.table("saddles")
  178. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  179. .column<string>("name", o => o.name, (o, v) => o.name = v)
  180. .column<string>("container_id", o => o.container_id, (o, v) => o.container_id = v)
  181. .column<string>("host", o => o.host, (o, v) => o.host = v)
  182. .column<string>("status", o => o.status, (o, v) => o.status = v)
  183. .column<int64?>("current_task_id", o => o.current_task_id, (o, v) => o.current_task_id = v)
  184. .column<DateTime?>("allocated_at", o => o.allocated_at, (o, v) => o.allocated_at = v);
  185. }
  186. }
  187. /**
  188. * One run of a task on a saddle: opened when the dispatcher assigns
  189. * the task, closed with an outcome when the session ends.
  190. */
  191. public class Session : Object {
  192. public int64 id { get; set; }
  193. public int64 task_id { get; set; }
  194. public int64 saddle_id { get; set; }
  195. public DateTime? started_at { get; set; default = null; }
  196. public DateTime? ended_at { get; set; default = null; }
  197. public string? outcome { get; set; default = null; }
  198. public static void entity_mapping(EntityMapperBuilder<Session> cfg) {
  199. cfg.table("sessions")
  200. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  201. .column<int64?>("task_id", o => o.task_id, (o, v) => o.task_id = v)
  202. .column<int64?>("saddle_id", o => o.saddle_id, (o, v) => o.saddle_id = v)
  203. .column<DateTime?>("started_at", o => o.started_at, (o, v) => o.started_at = v)
  204. .column<DateTime?>("ended_at", o => o.ended_at, (o, v) => o.ended_at = v)
  205. .column<string>("outcome", o => o.outcome, (o, v) => o.outcome = v);
  206. }
  207. }
  208. /**
  209. * A numbered entry captured during a {@link Session} — a bash
  210. * command/output pair or a conversation-level event (comment, block,
  211. * progress, review, plan, user-comment) — stored as the saddle daemon
  212. * reports it.
  213. */
  214. public class SessionCommand : Object {
  215. public int64 id { get; set; }
  216. public int64 session_id { get; set; }
  217. public string command_text { get; set; default = ""; }
  218. public string? output_text { get; set; default = null; }
  219. public int64 exit_code { get; set; default = 0; }
  220. public string entry_type { get; set; default = "command"; }
  221. public string? piped_input { get; set; default = null; }
  222. public DateTime? started_at { get; set; default = null; }
  223. public DateTime? completed_at { get; set; default = null; }
  224. public int64 duration_ms { get; set; default = 0; }
  225. public static void entity_mapping(EntityMapperBuilder<SessionCommand> cfg) {
  226. cfg.table("session_commands")
  227. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  228. .column<int64?>("session_id", o => o.session_id, (o, v) => o.session_id = v)
  229. .column<string>("command_text", o => o.command_text, (o, v) => o.command_text = v)
  230. .column<string>("output_text", o => o.output_text, (o, v) => o.output_text = v)
  231. .column<int64?>("exit_code", o => o.exit_code, (o, v) => o.exit_code = v)
  232. .column<string>("type", o => o.entry_type, (o, v) => o.entry_type = v)
  233. .column<string>("piped_input", o => o.piped_input, (o, v) => o.piped_input = v)
  234. .column<DateTime?>("started_at", o => o.started_at, (o, v) => o.started_at = v)
  235. .column<DateTime?>("completed_at", o => o.completed_at, (o, v) => o.completed_at = v)
  236. .column<int64?>("duration_ms", o => o.duration_ms, (o, v) => o.duration_ms = v);
  237. }
  238. }
  239. /**
  240. * A reusable instruction the dispatched agent must follow, stored in
  241. * the `rules` table and attached to projects and/or tasks.
  242. */
  243. public class Rule : Object {
  244. public int64 id { get; set; }
  245. public string name { get; set; default = ""; }
  246. public string body { get; set; default = ""; }
  247. public DateTime? created_at { get; set; default = null; }
  248. public static void entity_mapping(EntityMapperBuilder<Rule> cfg) {
  249. cfg.table("rules")
  250. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  251. .column<string>("name", o => o.name, (o, v) => o.name = v)
  252. .column<string>("body", o => o.body, (o, v) => o.body = v)
  253. .column<DateTime?>("created_at", o => o.created_at, (o, v) => o.created_at = v);
  254. }
  255. }
  256. /** An attachment of a rule to a project (`rule_projects`). */
  257. public class RuleProject : Object {
  258. public int64 id { get; set; }
  259. public int64 rule_id { get; set; }
  260. public int64 project_id { get; set; }
  261. public static void entity_mapping(EntityMapperBuilder<RuleProject> cfg) {
  262. cfg.table("rule_projects")
  263. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  264. .column<int64?>("rule_id", o => o.rule_id, (o, v) => o.rule_id = v)
  265. .column<int64?>("project_id", o => o.project_id, (o, v) => o.project_id = v);
  266. }
  267. }
  268. /** An attachment of a rule to a task (`task_rules`). */
  269. public class TaskRule : Object {
  270. public int64 id { get; set; }
  271. public int64 rule_id { get; set; }
  272. public int64 task_id { get; set; }
  273. public static void entity_mapping(EntityMapperBuilder<TaskRule> cfg) {
  274. cfg.table("task_rules")
  275. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  276. .column<int64?>("rule_id", o => o.rule_id, (o, v) => o.rule_id = v)
  277. .column<int64?>("task_id", o => o.task_id, (o, v) => o.task_id = v);
  278. }
  279. }
  280. /**
  281. * An LLM-authored remark about a project (`saddle note` via the
  282. * callback endpoint), curated from the project page. The source task
  283. * is null for notes without one.
  284. */
  285. public class ProjectNote : Object {
  286. public int64 id { get; set; }
  287. public int64 project_id { get; set; }
  288. public int64 source_task_id { get; set; default = 0; }
  289. public string body { get; set; default = ""; }
  290. public DateTime? created_at { get; set; default = null; }
  291. public static void entity_mapping(EntityMapperBuilder<ProjectNote> cfg) {
  292. cfg.table("project_notes")
  293. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  294. .column<int64?>("project_id", o => o.project_id, (o, v) => o.project_id = v)
  295. .column<int64?>("source_task_id", o => o.source_task_id, (o, v) => o.source_task_id = v ?? 0)
  296. .column<string>("body", o => o.body, (o, v) => o.body = v)
  297. .column<DateTime?>("created_at", o => o.created_at, (o, v) => o.created_at = v);
  298. }
  299. }
  300. /**
  301. * One raw PTY output chunk of a {@link Session}, pulled from the
  302. * daemon's `GET /log` ring buffer while the session is active
  303. * (`session_raw_log`); `seq` is the daemon's monotonic chunk
  304. * sequence number.
  305. */
  306. public class SessionRawLog : Object {
  307. public int64 id { get; set; }
  308. public int64 session_id { get; set; }
  309. public int64 seq { get; set; }
  310. public string chunk { get; set; default = ""; }
  311. public static void entity_mapping(EntityMapperBuilder<SessionRawLog> cfg) {
  312. cfg.table("session_raw_log")
  313. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  314. .column<int64?>("session_id", o => o.session_id, (o, v) => o.session_id = v)
  315. .column<int64?>("seq", o => o.seq, (o, v) => o.seq = v)
  316. .column<string>("chunk", o => o.chunk, (o, v) => o.chunk = v);
  317. }
  318. }
  319. /**
  320. * A named tag used for dispatch routing (`capabilities`): saddles
  321. * declare the tags they carry, tasks the tags they require.
  322. */
  323. public class Capability : Object {
  324. public int64 id { get; set; }
  325. public string name { get; set; default = ""; }
  326. public DateTime? created_at { get; set; default = null; }
  327. public static void entity_mapping(EntityMapperBuilder<Capability> cfg) {
  328. cfg.table("capabilities")
  329. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  330. .column<string>("name", o => o.name, (o, v) => o.name = v)
  331. .column<DateTime?>("created_at", o => o.created_at, (o, v) => o.created_at = v);
  332. }
  333. }
  334. /** A tag declaration on a saddle (`saddle_capabilities`). */
  335. public class SaddleCapability : Object {
  336. public int64 id { get; set; }
  337. public int64 capability_id { get; set; }
  338. public int64 saddle_id { get; set; }
  339. public static void entity_mapping(EntityMapperBuilder<SaddleCapability> cfg) {
  340. cfg.table("saddle_capabilities")
  341. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  342. .column<int64?>("capability_id", o => o.capability_id, (o, v) => o.capability_id = v)
  343. .column<int64?>("saddle_id", o => o.saddle_id, (o, v) => o.saddle_id = v);
  344. }
  345. }
  346. /** A required tag on a task (`task_capabilities`). */
  347. public class TaskCapability : Object {
  348. public int64 id { get; set; }
  349. public int64 capability_id { get; set; }
  350. public int64 task_id { get; set; }
  351. public static void entity_mapping(EntityMapperBuilder<TaskCapability> cfg) {
  352. cfg.table("task_capabilities")
  353. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  354. .column<int64?>("capability_id", o => o.capability_id, (o, v) => o.capability_id = v)
  355. .column<int64?>("task_id", o => o.task_id, (o, v) => o.task_id = v);
  356. }
  357. }
  358. /**
  359. * A bearer token authorising one saddle daemon's calls against the
  360. * `/api/saddle/*` endpoints, generated at registration.
  361. */
  362. public class ApiToken : Object {
  363. public int64 id { get; set; }
  364. public int64 saddle_id { get; set; }
  365. public string token { get; set; default = ""; }
  366. public DateTime? created_at { get; set; default = null; }
  367. public static void entity_mapping(EntityMapperBuilder<ApiToken> cfg) {
  368. cfg.table("api_tokens")
  369. .column<int64?>("id", o => o.id, (o, v) => o.id = v)
  370. .column<int64?>("saddle_id", o => o.saddle_id, (o, v) => o.saddle_id = v)
  371. .column<string>("token", o => o.token, (o, v) => o.token = v)
  372. .column<DateTime?>("created_at", o => o.created_at, (o, v) => o.created_at = v);
  373. }
  374. }
  375. }