abtars 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/bundle/{_registry.generated-FNJOX7VV.js → _registry.generated-KYX63MGY.js} +3 -3
  2. package/bundle/abtars-cli.js +66 -14
  3. package/bundle/abtars-cli.js.map +3 -3
  4. package/bundle/abtars.js +109 -53
  5. package/bundle/abtars.js.map +3 -3
  6. package/bundle/{agent-registry-S2MNHQYQ.js → agent-registry-5VL5KI6U.js} +3 -3
  7. package/bundle/agent-registry-PIS5XJHX.js +19 -0
  8. package/bundle/{chunk-HCYENZAB.js → chunk-3IPMKYYH.js} +5 -5
  9. package/bundle/{chunk-WLAVZSVZ.js → chunk-4WKWPU6U.js} +70 -2
  10. package/bundle/chunk-4WKWPU6U.js.map +7 -0
  11. package/bundle/chunk-5WFIAUQC.js +672 -0
  12. package/bundle/chunk-5WFIAUQC.js.map +7 -0
  13. package/bundle/{chunk-2SWKJX64.js → chunk-7WFE2JI5.js} +3 -3
  14. package/bundle/{chunk-3X6VGRL6.js → chunk-B52YRWR6.js} +2 -1
  15. package/bundle/chunk-B52YRWR6.js.map +7 -0
  16. package/bundle/chunk-BBTQKKDO.js +258 -0
  17. package/bundle/chunk-BBTQKKDO.js.map +7 -0
  18. package/bundle/chunk-GXKJKYU4.js +1089 -0
  19. package/bundle/chunk-GXKJKYU4.js.map +7 -0
  20. package/bundle/chunk-HAS5NEK7.js +189 -0
  21. package/bundle/chunk-HAS5NEK7.js.map +7 -0
  22. package/bundle/chunk-HB54S5OY.js +4036 -0
  23. package/bundle/chunk-HB54S5OY.js.map +7 -0
  24. package/bundle/{chunk-Z4SWEFIY.js → chunk-N24ROESF.js} +4 -4
  25. package/bundle/chunk-N7UG4FID.js +4036 -0
  26. package/bundle/chunk-N7UG4FID.js.map +7 -0
  27. package/bundle/{chunk-MHK4UPM6.js → chunk-PKHYCNTT.js} +1 -1
  28. package/bundle/{chunk-QIAFGDRL.js → chunk-PUDGA4RR.js} +4 -4
  29. package/bundle/chunk-QSC6QZ44.js +183 -0
  30. package/bundle/chunk-QSC6QZ44.js.map +7 -0
  31. package/bundle/{chunk-KL5QRHHK.js → chunk-SMZQDMSZ.js} +1 -1
  32. package/bundle/{chunk-OGZXYN6E.js → chunk-VY2BUO6L.js} +64 -13
  33. package/bundle/chunk-VY2BUO6L.js.map +7 -0
  34. package/bundle/chunk-W6ELWLAR.js +143 -0
  35. package/bundle/chunk-W6ELWLAR.js.map +7 -0
  36. package/bundle/chunk-Y2XBDQP3.js +4055 -0
  37. package/bundle/chunk-Y2XBDQP3.js.map +7 -0
  38. package/bundle/chunk-YMGX6HNP.js +131 -0
  39. package/bundle/chunk-YMGX6HNP.js.map +7 -0
  40. package/bundle/{commands-AXW7L2MZ.js → commands-IGRSOSK6.js} +5 -5
  41. package/bundle/commands-LAWVNQTO.js +34 -0
  42. package/bundle/commands-RBWY7YXB.js +34 -0
  43. package/bundle/commands-XFZNMZN6.js +34 -0
  44. package/bundle/{direct-api-transport-LSAUIP5S.js → direct-api-transport-OZICXTWQ.js} +18 -2
  45. package/bundle/direct-api-transport-OZICXTWQ.js.map +7 -0
  46. package/bundle/direct-api-transport-QIWA5ES2.js +889 -0
  47. package/bundle/direct-api-transport-QIWA5ES2.js.map +7 -0
  48. package/bundle/{discord-adapter-LNWTIOUK.js → discord-adapter-JFIIVG34.js} +6 -6
  49. package/bundle/discord-adapter-U3FA5OTY.js +589 -0
  50. package/bundle/discord-adapter-U3FA5OTY.js.map +7 -0
  51. package/bundle/discord-adapter-W6L5KJ6T.js +589 -0
  52. package/bundle/discord-adapter-W6L5KJ6T.js.map +7 -0
  53. package/bundle/discord-adapter-WWM6ROTW.js +589 -0
  54. package/bundle/discord-adapter-WWM6ROTW.js.map +7 -0
  55. package/bundle/{install-FZT43PTH.js → install-I3CXVW52.js} +2 -2
  56. package/bundle/kanban-board-6Q5E5GEB.js +31 -0
  57. package/bundle/kanban-board-I52RHNHQ.js +31 -0
  58. package/bundle/kanban-board-I52RHNHQ.js.map +7 -0
  59. package/bundle/{message-pipeline-QX272U5X.js → message-pipeline-4CTBJ6K2.js} +5 -5
  60. package/bundle/message-pipeline-4CTBJ6K2.js.map +7 -0
  61. package/bundle/message-pipeline-4KL7OWUH.js +38 -0
  62. package/bundle/message-pipeline-4KL7OWUH.js.map +7 -0
  63. package/bundle/message-pipeline-GFKSHRFU.js +38 -0
  64. package/bundle/message-pipeline-GFKSHRFU.js.map +7 -0
  65. package/bundle/message-pipeline-TGI2WJJM.js +38 -0
  66. package/bundle/message-pipeline-TGI2WJJM.js.map +7 -0
  67. package/bundle/meta.json +784 -600
  68. package/bundle/{phase-transport-BSGROTHY.js → phase-transport-INFD6ELA.js} +4 -4
  69. package/bundle/phase-transport-INFD6ELA.js.map +7 -0
  70. package/bundle/phase-transport-KXFZ5BVF.js +23 -0
  71. package/bundle/phase-transport-KXFZ5BVF.js.map +7 -0
  72. package/bundle/{sleep-K7EXAFGW.js → sleep-ENFZFUJJ.js} +3 -3
  73. package/bundle/sleep-ENFZFUJJ.js.map +7 -0
  74. package/bundle/{subagent-runtime-FQAT3564.js → subagent-runtime-5AYOXOU2.js} +2 -2
  75. package/bundle/subagent-runtime-5AYOXOU2.js.map +7 -0
  76. package/bundle/subagent-runtime-VKTX6Q2M.js +13 -0
  77. package/bundle/subagent-runtime-VKTX6Q2M.js.map +7 -0
  78. package/bundle/{telegram-adapter-LXLSG4SK.js → telegram-adapter-4KI4CJPG.js} +7 -7
  79. package/bundle/telegram-adapter-76B4JRJJ.js +1080 -0
  80. package/bundle/telegram-adapter-76B4JRJJ.js.map +7 -0
  81. package/bundle/telegram-adapter-VZA74EMT.js +1080 -0
  82. package/bundle/telegram-adapter-VZA74EMT.js.map +7 -0
  83. package/bundle/telegram-adapter-ZO2CLU22.js +1080 -0
  84. package/bundle/telegram-adapter-ZO2CLU22.js.map +7 -0
  85. package/bundle/{tool-registry-5PXNSYOI.js → tool-registry-CG7GIS64.js} +3 -2
  86. package/bundle/tool-registry-CG7GIS64.js.map +7 -0
  87. package/bundle/tool-registry-TGNU5AMG.js +43 -0
  88. package/bundle/tool-registry-TGNU5AMG.js.map +7 -0
  89. package/install-manifest.json +4 -0
  90. package/package.json +2 -1
  91. package/scripts/abtars-daemon.service +3 -0
  92. package/scripts/abtars@.service +3 -0
  93. package/scripts/build-and-deploy.sh +40 -0
  94. package/bundle/chunk-3X6VGRL6.js.map +0 -7
  95. package/bundle/chunk-OGZXYN6E.js.map +0 -7
  96. package/bundle/chunk-WLAVZSVZ.js.map +0 -7
  97. package/bundle/direct-api-transport-LSAUIP5S.js.map +0 -7
  98. /package/bundle/{_registry.generated-FNJOX7VV.js.map → _registry.generated-KYX63MGY.js.map} +0 -0
  99. /package/bundle/{agent-registry-S2MNHQYQ.js.map → agent-registry-5VL5KI6U.js.map} +0 -0
  100. /package/bundle/{commands-AXW7L2MZ.js.map → agent-registry-PIS5XJHX.js.map} +0 -0
  101. /package/bundle/{chunk-HCYENZAB.js.map → chunk-3IPMKYYH.js.map} +0 -0
  102. /package/bundle/{chunk-2SWKJX64.js.map → chunk-7WFE2JI5.js.map} +0 -0
  103. /package/bundle/{chunk-Z4SWEFIY.js.map → chunk-N24ROESF.js.map} +0 -0
  104. /package/bundle/{chunk-MHK4UPM6.js.map → chunk-PKHYCNTT.js.map} +0 -0
  105. /package/bundle/{chunk-QIAFGDRL.js.map → chunk-PUDGA4RR.js.map} +0 -0
  106. /package/bundle/{chunk-KL5QRHHK.js.map → chunk-SMZQDMSZ.js.map} +0 -0
  107. /package/bundle/{install-FZT43PTH.js.map → commands-IGRSOSK6.js.map} +0 -0
  108. /package/bundle/{message-pipeline-QX272U5X.js.map → commands-LAWVNQTO.js.map} +0 -0
  109. /package/bundle/{phase-transport-BSGROTHY.js.map → commands-RBWY7YXB.js.map} +0 -0
  110. /package/bundle/{sleep-K7EXAFGW.js.map → commands-XFZNMZN6.js.map} +0 -0
  111. /package/bundle/{discord-adapter-LNWTIOUK.js.map → discord-adapter-JFIIVG34.js.map} +0 -0
  112. /package/bundle/{subagent-runtime-FQAT3564.js.map → install-I3CXVW52.js.map} +0 -0
  113. /package/bundle/{tool-registry-5PXNSYOI.js.map → kanban-board-6Q5E5GEB.js.map} +0 -0
  114. /package/bundle/{telegram-adapter-LXLSG4SK.js.map → telegram-adapter-4KI4CJPG.js.map} +0 -0
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __bundleCreateRequire } from 'node:module'; import { fileURLToPath as __bundleFileURLToPath } from 'node:url'; import { dirname as __bundleDirname } from 'node:path'; const require = __bundleCreateRequire(import.meta.url); const __chunk_filename = __bundleFileURLToPath(import.meta.url); const __chunk_dirname = __bundleDirname(__chunk_filename);
3
+ import {
4
+ abtarsHome,
5
+ init_paths
6
+ } from "./chunk-WW5F2DCO.js";
7
+ import {
8
+ __require
9
+ } from "./chunk-7K2YZTLD.js";
10
+
11
+ // src/components/tasks/kanban-board.ts
12
+ init_paths();
13
+ import { join } from "node:path";
14
+ import { mkdirSync } from "node:fs";
15
+ var _db = null;
16
+ function db() {
17
+ if (!_db) {
18
+ const dir = join(abtarsHome(), "kanban");
19
+ mkdirSync(dir, { recursive: true });
20
+ const Database = __require("better-sqlite3");
21
+ _db = new Database(join(dir, "kanban.db"));
22
+ _db.pragma("journal_mode = WAL");
23
+ _db.exec(`CREATE TABLE IF NOT EXISTS kanban_board (
24
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
25
+ title TEXT NOT NULL,
26
+ source TEXT NOT NULL,
27
+ source_id TEXT,
28
+ assignee TEXT DEFAULT 'local',
29
+ priority TEXT NOT NULL DEFAULT 'MEDIUM' CHECK(priority IN ('CRITICAL','HIGH','MEDIUM','LOW')),
30
+ status TEXT NOT NULL DEFAULT 'queued' CHECK(status IN ('queued','running','done','failed','delivering','delivered')),
31
+ type TEXT,
32
+ notes TEXT,
33
+ result_summary TEXT,
34
+ result_path TEXT,
35
+ error TEXT,
36
+ delivery_attempts INTEGER DEFAULT 0,
37
+ approval TEXT CHECK(approval IS NULL OR approval IN ('pending','approved','rejected')),
38
+ due_at TEXT,
39
+ labels TEXT,
40
+ parent_id INTEGER REFERENCES kanban_board(id),
41
+ blocked_by INTEGER REFERENCES kanban_board(id),
42
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
43
+ updated_at TEXT NOT NULL DEFAULT (datetime('now')),
44
+ completed_at TEXT,
45
+ delivered_at TEXT
46
+ )`);
47
+ }
48
+ return _db;
49
+ }
50
+ function kanbanEnqueue(title, source, sourceId, opts) {
51
+ const stmt = db().prepare(
52
+ `INSERT INTO kanban_board (title, source, source_id, priority, type, labels, due_at, parent_id, notes)
53
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
54
+ );
55
+ const result = stmt.run(title, source, sourceId ?? null, opts?.priority ?? "MEDIUM", opts?.type ?? null, opts?.labels ?? null, opts?.due_at ?? null, opts?.parent_id ?? null, opts?.notes ?? null);
56
+ return Number(result.lastInsertRowid);
57
+ }
58
+ function kanbanRunning(id) {
59
+ db().prepare(`UPDATE kanban_board SET status = 'running', updated_at = datetime('now') WHERE id = ?`).run(id);
60
+ }
61
+ function kanbanComplete(id, resultPath, summary) {
62
+ db().prepare(
63
+ `UPDATE kanban_board SET status = 'done', result_path = ?, result_summary = ?, completed_at = datetime('now'), updated_at = datetime('now') WHERE id = ?`
64
+ ).run(resultPath, summary.slice(0, 500), id);
65
+ }
66
+ function kanbanFail(id, error) {
67
+ db().prepare(
68
+ `UPDATE kanban_board SET status = 'failed', error = ?, completed_at = datetime('now'), updated_at = datetime('now') WHERE id = ?`
69
+ ).run(error.slice(0, 1e3), id);
70
+ }
71
+ function kanbanPending() {
72
+ return db().prepare(
73
+ `SELECT * FROM kanban_board WHERE status = 'done' AND delivery_attempts < 3 ORDER BY priority = 'CRITICAL' DESC, priority = 'HIGH' DESC, created_at ASC`
74
+ ).all();
75
+ }
76
+ function kanbanSetDelivering(id) {
77
+ db().prepare(`UPDATE kanban_board SET status = 'delivering', updated_at = datetime('now') WHERE id = ?`).run(id);
78
+ }
79
+ function kanbanMarkDelivered(id) {
80
+ db().prepare(
81
+ `UPDATE kanban_board SET status = 'delivered', delivered_at = datetime('now'), updated_at = datetime('now') WHERE id = ?`
82
+ ).run(id);
83
+ }
84
+ function kanbanDeliveryFailed(id) {
85
+ const card = db().prepare(`SELECT delivery_attempts FROM kanban_board WHERE id = ?`).get(id);
86
+ const attempts = (card?.delivery_attempts ?? 0) + 1;
87
+ if (attempts >= 3) {
88
+ db().prepare(`UPDATE kanban_board SET status = 'failed', error = 'delivery failed after 3 attempts', delivery_attempts = ?, updated_at = datetime('now') WHERE id = ?`).run(attempts, id);
89
+ } else {
90
+ db().prepare(`UPDATE kanban_board SET status = 'done', delivery_attempts = ?, updated_at = datetime('now') WHERE id = ?`).run(attempts, id);
91
+ }
92
+ }
93
+ function kanbanList(filter, filterKey) {
94
+ if (filter === "*") {
95
+ return db().prepare(`SELECT * FROM kanban_board ORDER BY created_at DESC LIMIT 50`).all();
96
+ }
97
+ if (filter && filterKey) {
98
+ if (filterKey === "labels") {
99
+ return db().prepare(`SELECT * FROM kanban_board WHERE labels LIKE ? ORDER BY created_at DESC LIMIT 50`).all(`%${filter}%`);
100
+ }
101
+ const allowed = /* @__PURE__ */ new Set(["status", "source", "priority", "type"]);
102
+ if (allowed.has(filterKey)) {
103
+ return db().prepare(`SELECT * FROM kanban_board WHERE ${filterKey} = ? ORDER BY created_at DESC LIMIT 50`).all(filter);
104
+ }
105
+ }
106
+ if (filter) {
107
+ return db().prepare(`SELECT * FROM kanban_board WHERE status = ? ORDER BY created_at DESC LIMIT 50`).all(filter);
108
+ }
109
+ return db().prepare(`SELECT * FROM kanban_board WHERE status NOT IN ('delivered') ORDER BY status = 'running' DESC, priority = 'CRITICAL' DESC, created_at DESC LIMIT 50`).all();
110
+ }
111
+ function kanbanUpdate(id, fields) {
112
+ const sets = ["updated_at = datetime('now')"];
113
+ const vals = [];
114
+ for (const [k, v] of Object.entries(fields)) {
115
+ if (v !== void 0) {
116
+ sets.push(`${k} = ?`);
117
+ vals.push(v);
118
+ }
119
+ }
120
+ vals.push(id);
121
+ db().prepare(`UPDATE kanban_board SET ${sets.join(", ")} WHERE id = ?`).run(...vals);
122
+ }
123
+ function kanbanCleanup(olderThanDays = 7) {
124
+ const result = db().prepare(
125
+ `DELETE FROM kanban_board WHERE status = 'delivered' AND delivered_at < datetime('now', '-' || ? || ' days')`
126
+ ).run(olderThanDays);
127
+ return result.changes;
128
+ }
129
+
130
+ export {
131
+ kanbanEnqueue,
132
+ kanbanRunning,
133
+ kanbanComplete,
134
+ kanbanFail,
135
+ kanbanPending,
136
+ kanbanSetDelivering,
137
+ kanbanMarkDelivered,
138
+ kanbanDeliveryFailed,
139
+ kanbanList,
140
+ kanbanUpdate,
141
+ kanbanCleanup
142
+ };
143
+ //# sourceMappingURL=chunk-W6ELWLAR.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/components/tasks/kanban-board.ts"],
4
+ "sourcesContent": ["/**\n * kanban-board.ts \u2014 Local Kanban board backed by SQLite.\n *\n * Workers write completion; main agent polls and delivers.\n * DB lives at ~/.abtars/kanban/kanban.db\n */\n\nimport { join } from \"node:path\";\nimport { mkdirSync } from \"node:fs\";\nimport { abtarsHome } from \"../../paths.js\";\n\n// better-sqlite3 is external (native module, available at runtime via abmind)\ntype SqliteDb = { prepare(sql: string): any; exec(sql: string): void; pragma(s: string): void };\n\nexport interface KanbanCard {\n id: number;\n title: string;\n source: string;\n source_id: string | null;\n assignee: string;\n priority: string;\n status: string;\n type: string | null;\n notes: string | null;\n result_summary: string | null;\n result_path: string | null;\n error: string | null;\n delivery_attempts: number;\n approval: string | null;\n due_at: string | null;\n labels: string | null;\n parent_id: number | null;\n blocked_by: number | null;\n created_at: string;\n updated_at: string;\n completed_at: string | null;\n delivered_at: string | null;\n}\n\nlet _db: SqliteDb | null = null;\n\nfunction db(): SqliteDb {\n if (!_db) {\n const dir = join(abtarsHome(), \"kanban\");\n mkdirSync(dir, { recursive: true });\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const Database = require(\"better-sqlite3\");\n _db = new Database(join(dir, \"kanban.db\")) as SqliteDb;\n _db.pragma(\"journal_mode = WAL\");\n _db.exec(`CREATE TABLE IF NOT EXISTS kanban_board (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n title TEXT NOT NULL,\n source TEXT NOT NULL,\n source_id TEXT,\n assignee TEXT DEFAULT 'local',\n priority TEXT NOT NULL DEFAULT 'MEDIUM' CHECK(priority IN ('CRITICAL','HIGH','MEDIUM','LOW')),\n status TEXT NOT NULL DEFAULT 'queued' CHECK(status IN ('queued','running','done','failed','delivering','delivered')),\n type TEXT,\n notes TEXT,\n result_summary TEXT,\n result_path TEXT,\n error TEXT,\n delivery_attempts INTEGER DEFAULT 0,\n approval TEXT CHECK(approval IS NULL OR approval IN ('pending','approved','rejected')),\n due_at TEXT,\n labels TEXT,\n parent_id INTEGER REFERENCES kanban_board(id),\n blocked_by INTEGER REFERENCES kanban_board(id),\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now')),\n completed_at TEXT,\n delivered_at TEXT\n )`);\n }\n return _db;\n}\n\nexport function kanbanEnqueue(title: string, source: string, sourceId?: string, opts?: { priority?: string; type?: string; labels?: string; due_at?: string; parent_id?: number; notes?: string }): number {\n const stmt = db().prepare(\n `INSERT INTO kanban_board (title, source, source_id, priority, type, labels, due_at, parent_id, notes)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`\n );\n const result = stmt.run(title, source, sourceId ?? null, opts?.priority ?? \"MEDIUM\", opts?.type ?? null, opts?.labels ?? null, opts?.due_at ?? null, opts?.parent_id ?? null, opts?.notes ?? null);\n return Number(result.lastInsertRowid);\n}\n\nexport function kanbanRunning(id: number): void {\n db().prepare(`UPDATE kanban_board SET status = 'running', updated_at = datetime('now') WHERE id = ?`).run(id);\n}\n\nexport function kanbanComplete(id: number, resultPath: string | null, summary: string): void {\n db().prepare(\n `UPDATE kanban_board SET status = 'done', result_path = ?, result_summary = ?, completed_at = datetime('now'), updated_at = datetime('now') WHERE id = ?`\n ).run(resultPath, summary.slice(0, 500), id);\n}\n\nexport function kanbanFail(id: number, error: string): void {\n db().prepare(\n `UPDATE kanban_board SET status = 'failed', error = ?, completed_at = datetime('now'), updated_at = datetime('now') WHERE id = ?`\n ).run(error.slice(0, 1000), id);\n}\n\nexport function kanbanPending(): KanbanCard[] {\n return db().prepare(\n `SELECT * FROM kanban_board WHERE status = 'done' AND delivery_attempts < 3 ORDER BY priority = 'CRITICAL' DESC, priority = 'HIGH' DESC, created_at ASC`\n ).all() as KanbanCard[];\n}\n\nexport function kanbanSetDelivering(id: number): void {\n db().prepare(`UPDATE kanban_board SET status = 'delivering', updated_at = datetime('now') WHERE id = ?`).run(id);\n}\n\nexport function kanbanMarkDelivered(id: number): void {\n db().prepare(\n `UPDATE kanban_board SET status = 'delivered', delivered_at = datetime('now'), updated_at = datetime('now') WHERE id = ?`\n ).run(id);\n}\n\nexport function kanbanDeliveryFailed(id: number): void {\n const card = db().prepare(`SELECT delivery_attempts FROM kanban_board WHERE id = ?`).get(id) as { delivery_attempts: number } | undefined;\n const attempts = (card?.delivery_attempts ?? 0) + 1;\n if (attempts >= 3) {\n db().prepare(`UPDATE kanban_board SET status = 'failed', error = 'delivery failed after 3 attempts', delivery_attempts = ?, updated_at = datetime('now') WHERE id = ?`).run(attempts, id);\n } else {\n db().prepare(`UPDATE kanban_board SET status = 'done', delivery_attempts = ?, updated_at = datetime('now') WHERE id = ?`).run(attempts, id);\n }\n}\n\nexport function kanbanList(filter?: string, filterKey?: string): KanbanCard[] {\n if (filter === \"*\") {\n return db().prepare(`SELECT * FROM kanban_board ORDER BY created_at DESC LIMIT 50`).all() as KanbanCard[];\n }\n if (filter && filterKey) {\n if (filterKey === \"labels\") {\n // LIKE match for comma-separated labels\n return db().prepare(`SELECT * FROM kanban_board WHERE labels LIKE ? ORDER BY created_at DESC LIMIT 50`).all(`%${filter}%`) as KanbanCard[];\n }\n const allowed = new Set([\"status\", \"source\", \"priority\", \"type\"]);\n if (allowed.has(filterKey)) {\n return db().prepare(`SELECT * FROM kanban_board WHERE ${filterKey} = ? ORDER BY created_at DESC LIMIT 50`).all(filter) as KanbanCard[];\n }\n }\n if (filter) {\n // Bare word = status filter\n return db().prepare(`SELECT * FROM kanban_board WHERE status = ? ORDER BY created_at DESC LIMIT 50`).all(filter) as KanbanCard[];\n }\n return db().prepare(`SELECT * FROM kanban_board WHERE status NOT IN ('delivered') ORDER BY status = 'running' DESC, priority = 'CRITICAL' DESC, created_at DESC LIMIT 50`).all() as KanbanCard[];\n}\n\nexport function kanbanUpdate(id: number, fields: Partial<Pick<KanbanCard, \"title\" | \"status\" | \"priority\" | \"type\" | \"labels\" | \"due_at\" | \"notes\" | \"parent_id\" | \"approval\">>): void {\n const sets: string[] = [\"updated_at = datetime('now')\"];\n const vals: unknown[] = [];\n for (const [k, v] of Object.entries(fields)) {\n if (v !== undefined) { sets.push(`${k} = ?`); vals.push(v); }\n }\n vals.push(id);\n db().prepare(`UPDATE kanban_board SET ${sets.join(\", \")} WHERE id = ?`).run(...vals);\n}\n\nexport function kanbanCleanup(olderThanDays = 7): number {\n const result = db().prepare(\n `DELETE FROM kanban_board WHERE status = 'delivered' AND delivered_at < datetime('now', '-' || ? || ' days')`\n ).run(olderThanDays);\n return result.changes;\n}\n"],
5
+ "mappings": ";;;;;;;;;;;AASA;AAFA,SAAS,YAAY;AACrB,SAAS,iBAAiB;AA+B1B,IAAI,MAAuB;AAE3B,SAAS,KAAe;AACtB,MAAI,CAAC,KAAK;AACR,UAAM,MAAM,KAAK,WAAW,GAAG,QAAQ;AACvC,cAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAElC,UAAM,WAAW,UAAQ,gBAAgB;AACzC,UAAM,IAAI,SAAS,KAAK,KAAK,WAAW,CAAC;AACzC,QAAI,OAAO,oBAAoB;AAC/B,QAAI,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAuBP;AAAA,EACJ;AACA,SAAO;AACT;AAEO,SAAS,cAAc,OAAe,QAAgB,UAAmB,MAA2H;AACzM,QAAM,OAAO,GAAG,EAAE;AAAA,IAChB;AAAA;AAAA,EAEF;AACA,QAAM,SAAS,KAAK,IAAI,OAAO,QAAQ,YAAY,MAAM,MAAM,YAAY,UAAU,MAAM,QAAQ,MAAM,MAAM,UAAU,MAAM,MAAM,UAAU,MAAM,MAAM,aAAa,MAAM,MAAM,SAAS,IAAI;AACjM,SAAO,OAAO,OAAO,eAAe;AACtC;AAEO,SAAS,cAAc,IAAkB;AAC9C,KAAG,EAAE,QAAQ,uFAAuF,EAAE,IAAI,EAAE;AAC9G;AAEO,SAAS,eAAe,IAAY,YAA2B,SAAuB;AAC3F,KAAG,EAAE;AAAA,IACH;AAAA,EACF,EAAE,IAAI,YAAY,QAAQ,MAAM,GAAG,GAAG,GAAG,EAAE;AAC7C;AAEO,SAAS,WAAW,IAAY,OAAqB;AAC1D,KAAG,EAAE;AAAA,IACH;AAAA,EACF,EAAE,IAAI,MAAM,MAAM,GAAG,GAAI,GAAG,EAAE;AAChC;AAEO,SAAS,gBAA8B;AAC5C,SAAO,GAAG,EAAE;AAAA,IACV;AAAA,EACF,EAAE,IAAI;AACR;AAEO,SAAS,oBAAoB,IAAkB;AACpD,KAAG,EAAE,QAAQ,0FAA0F,EAAE,IAAI,EAAE;AACjH;AAEO,SAAS,oBAAoB,IAAkB;AACpD,KAAG,EAAE;AAAA,IACH;AAAA,EACF,EAAE,IAAI,EAAE;AACV;AAEO,SAAS,qBAAqB,IAAkB;AACrD,QAAM,OAAO,GAAG,EAAE,QAAQ,yDAAyD,EAAE,IAAI,EAAE;AAC3F,QAAM,YAAY,MAAM,qBAAqB,KAAK;AAClD,MAAI,YAAY,GAAG;AACjB,OAAG,EAAE,QAAQ,yJAAyJ,EAAE,IAAI,UAAU,EAAE;AAAA,EAC1L,OAAO;AACL,OAAG,EAAE,QAAQ,2GAA2G,EAAE,IAAI,UAAU,EAAE;AAAA,EAC5I;AACF;AAEO,SAAS,WAAW,QAAiB,WAAkC;AAC5E,MAAI,WAAW,KAAK;AAClB,WAAO,GAAG,EAAE,QAAQ,8DAA8D,EAAE,IAAI;AAAA,EAC1F;AACA,MAAI,UAAU,WAAW;AACvB,QAAI,cAAc,UAAU;AAE1B,aAAO,GAAG,EAAE,QAAQ,kFAAkF,EAAE,IAAI,IAAI,MAAM,GAAG;AAAA,IAC3H;AACA,UAAM,UAAU,oBAAI,IAAI,CAAC,UAAU,UAAU,YAAY,MAAM,CAAC;AAChE,QAAI,QAAQ,IAAI,SAAS,GAAG;AAC1B,aAAO,GAAG,EAAE,QAAQ,oCAAoC,SAAS,wCAAwC,EAAE,IAAI,MAAM;AAAA,IACvH;AAAA,EACF;AACA,MAAI,QAAQ;AAEV,WAAO,GAAG,EAAE,QAAQ,+EAA+E,EAAE,IAAI,MAAM;AAAA,EACjH;AACA,SAAO,GAAG,EAAE,QAAQ,qJAAqJ,EAAE,IAAI;AACjL;AAEO,SAAS,aAAa,IAAY,QAA8I;AACrL,QAAM,OAAiB,CAAC,8BAA8B;AACtD,QAAM,OAAkB,CAAC;AACzB,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC3C,QAAI,MAAM,QAAW;AAAE,WAAK,KAAK,GAAG,CAAC,MAAM;AAAG,WAAK,KAAK,CAAC;AAAA,IAAG;AAAA,EAC9D;AACA,OAAK,KAAK,EAAE;AACZ,KAAG,EAAE,QAAQ,2BAA2B,KAAK,KAAK,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,IAAI;AACrF;AAEO,SAAS,cAAc,gBAAgB,GAAW;AACvD,QAAM,SAAS,GAAG,EAAE;AAAA,IAClB;AAAA,EACF,EAAE,IAAI,aAAa;AACnB,SAAO,OAAO;AAChB;",
6
+ "names": []
7
+ }