toolroll 0.9.53 → 0.9.55

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 (254) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +5 -4
  3. package/dist/agent-onboard.js +4 -1
  4. package/dist/approval-rules-ui.d.ts +3 -2
  5. package/dist/approval-rules-ui.js +15 -20
  6. package/dist/assignment-ui.d.ts +3 -2
  7. package/dist/assignment-ui.js +4 -11
  8. package/dist/backup-ui.d.ts +2 -1
  9. package/dist/backup-ui.js +16 -27
  10. package/dist/brand-mark.d.ts +3 -2
  11. package/dist/brand-mark.js +4 -4
  12. package/dist/browser/workspace.css +1 -1
  13. package/dist/browser/workspace.js +25 -25
  14. package/dist/browser-shell.d.ts +2 -1
  15. package/dist/browser-shell.js +9 -9
  16. package/dist/browser-workspace.d.ts +2 -3
  17. package/dist/browser-workspace.js +0 -3
  18. package/dist/chat-ask.js +8 -8
  19. package/dist/chat-core.d.ts +171 -0
  20. package/dist/chat-core.js +288 -0
  21. package/dist/chat-decide.d.ts +10 -8
  22. package/dist/chat-decide.js +26 -21
  23. package/dist/chat-delivery-state.d.ts +51 -75
  24. package/dist/chat-delivery-state.js +140 -170
  25. package/dist/chat-delivery.d.ts +21 -2
  26. package/dist/chat-delivery.js +313 -194
  27. package/dist/chat-flow.d.ts +29 -1
  28. package/dist/chat-flow.js +24 -50
  29. package/dist/chat-messages.d.ts +319 -0
  30. package/dist/chat-messages.js +841 -0
  31. package/dist/chat-migration.d.ts +30 -0
  32. package/dist/chat-migration.js +802 -0
  33. package/dist/chat-polish.d.ts +5 -4
  34. package/dist/chat-polish.js +9 -10
  35. package/dist/chat-quiet.d.ts +3 -0
  36. package/dist/chat-quiet.js +5 -0
  37. package/dist/check-levels-ui.d.ts +2 -1
  38. package/dist/check-levels-ui.js +26 -53
  39. package/dist/cli.d.ts +3 -1
  40. package/dist/cli.js +9 -3
  41. package/dist/coding-shipping-ui.d.ts +2 -1
  42. package/dist/coding-shipping-ui.js +6 -6
  43. package/dist/coding-ui.d.ts +3 -1
  44. package/dist/coding-ui.js +30 -29
  45. package/dist/contracts/chat-content.d.ts +71 -2
  46. package/dist/contracts/chat-content.js +22 -3
  47. package/dist/contracts/chat-tables.d.ts +11 -4
  48. package/dist/contracts/chat-tables.js +165 -87
  49. package/dist/contracts/cli.d.ts +1 -3
  50. package/dist/contracts/console-api.d.ts +1 -1
  51. package/dist/contracts/console-api.js +6 -5
  52. package/dist/contracts/discord-callback.js +2 -1
  53. package/dist/contracts/health.d.ts +1 -3
  54. package/dist/contracts/slack-callback.js +3 -2
  55. package/dist/contracts/store-json.d.ts +1 -5
  56. package/dist/contracts/store-json.js +1 -4
  57. package/dist/contracts/teams-callback.js +2 -1
  58. package/dist/control-ui.d.ts +5 -4
  59. package/dist/control-ui.js +9 -34
  60. package/dist/credentials-ui.d.ts +5 -4
  61. package/dist/credentials-ui.js +23 -24
  62. package/dist/demo-chat.d.ts +3 -3
  63. package/dist/demo-chat.js +29 -76
  64. package/dist/discord-chat.js +19 -38
  65. package/dist/discord-settings.d.ts +3 -2
  66. package/dist/discord-settings.js +21 -55
  67. package/dist/discord.js +4 -14
  68. package/dist/envelope.js +10 -0
  69. package/dist/evidence-pack.d.ts +2 -1
  70. package/dist/evidence-pack.js +45 -49
  71. package/dist/export-ui.d.ts +7 -2
  72. package/dist/export-ui.js +4 -10
  73. package/dist/export.js +4 -4
  74. package/dist/flow-gallery-ui.d.ts +4 -3
  75. package/dist/flow-gallery-ui.js +28 -43
  76. package/dist/flow-starters-ui.d.ts +2 -1
  77. package/dist/flow-starters-ui.js +12 -15
  78. package/dist/flow-triggers.d.ts +1 -0
  79. package/dist/flow-triggers.js +16 -14
  80. package/dist/flows-ui.d.ts +4 -3
  81. package/dist/flows-ui.js +19 -30
  82. package/dist/flows.js +2 -1
  83. package/dist/guides.js +108 -3
  84. package/dist/html.d.ts +76 -0
  85. package/dist/html.js +173 -0
  86. package/dist/integrations-ui.d.ts +2 -1
  87. package/dist/integrations-ui.js +19 -23
  88. package/dist/kits-ui.d.ts +5 -4
  89. package/dist/kits-ui.js +18 -20
  90. package/dist/knowledge-ui.d.ts +6 -5
  91. package/dist/knowledge-ui.js +26 -25
  92. package/dist/lead-context.d.ts +11 -1
  93. package/dist/lead-context.js +6 -8
  94. package/dist/ledger-view.d.ts +2 -1
  95. package/dist/ledger-view.js +27 -29
  96. package/dist/limits-ui.d.ts +2 -1
  97. package/dist/limits-ui.js +7 -7
  98. package/dist/live-bus.d.ts +50 -8
  99. package/dist/live-bus.js +133 -50
  100. package/dist/mate-tools.js +3 -2
  101. package/dist/mcp-oauth.js +35 -36
  102. package/dist/models-ui.d.ts +2 -1
  103. package/dist/models-ui.js +25 -35
  104. package/dist/modes.d.ts +13 -1
  105. package/dist/modes.js +17 -1
  106. package/dist/monitoring-ui.d.ts +4 -3
  107. package/dist/monitoring-ui.js +13 -26
  108. package/dist/notification-rows.d.ts +30 -0
  109. package/dist/notification-rows.js +102 -0
  110. package/dist/openrouter-models.d.ts +2 -1
  111. package/dist/openrouter-models.js +5 -9
  112. package/dist/operate.js +16 -9
  113. package/dist/people-audit-ui.d.ts +2 -1
  114. package/dist/people-audit-ui.js +13 -13
  115. package/dist/plane-review.js +5 -11
  116. package/dist/policy-ui.d.ts +3 -2
  117. package/dist/policy-ui.js +17 -23
  118. package/dist/project-delete-ui.d.ts +4 -3
  119. package/dist/project-delete-ui.js +15 -27
  120. package/dist/project-delete.js +21 -26
  121. package/dist/pull-request-ui.d.ts +2 -1
  122. package/dist/pull-request-ui.js +17 -32
  123. package/dist/recipe-ui.d.ts +8 -7
  124. package/dist/recipe-ui.js +39 -32
  125. package/dist/release-adapters.d.ts +60 -0
  126. package/dist/release-adapters.js +435 -0
  127. package/dist/release-cli.d.ts +24 -0
  128. package/dist/release-cli.js +181 -0
  129. package/dist/release-gate.d.ts +80 -0
  130. package/dist/release-gate.js +150 -0
  131. package/dist/release-links.d.ts +29 -0
  132. package/dist/release-links.js +102 -0
  133. package/dist/release.d.ts +331 -0
  134. package/dist/release.js +550 -0
  135. package/dist/reply-shape.d.ts +2 -1
  136. package/dist/reply-shape.js +5 -5
  137. package/dist/repository-context-ui.d.ts +2 -1
  138. package/dist/repository-context-ui.js +2 -7
  139. package/dist/request-budget-ui.d.ts +2 -1
  140. package/dist/request-budget-ui.js +16 -16
  141. package/dist/result-review.d.ts +2 -3
  142. package/dist/result-review.js +3 -9
  143. package/dist/result-shots.js +2 -2
  144. package/dist/retention-ui.d.ts +7 -1
  145. package/dist/retention-ui.js +7 -11
  146. package/dist/retention.js +1 -1
  147. package/dist/serve.d.ts +11 -2
  148. package/dist/serve.js +69 -58
  149. package/dist/server/chat.d.ts +3 -6
  150. package/dist/server/chat.js +969 -1006
  151. package/dist/server/chrome.d.ts +291 -0
  152. package/dist/server/chrome.js +747 -0
  153. package/dist/server/console.css +2819 -0
  154. package/dist/server/flows.d.ts +2 -6
  155. package/dist/server/flows.js +840 -766
  156. package/dist/server/guards.d.ts +1 -1
  157. package/dist/server/guards.js +5 -2
  158. package/dist/server/handler-context.d.ts +1 -1
  159. package/dist/server/handler-context.js +1 -1
  160. package/dist/server/handler-registry.d.ts +8 -6
  161. package/dist/server/handler-registry.js +14 -2
  162. package/dist/server/http.d.ts +274 -0
  163. package/dist/server/http.js +239 -0
  164. package/dist/server/live.d.ts +34 -0
  165. package/dist/server/live.js +309 -0
  166. package/dist/server/pages.d.ts +2 -6
  167. package/dist/server/pages.js +808 -789
  168. package/dist/server/people-tokens.d.ts +1 -6
  169. package/dist/server/people-tokens.js +580 -572
  170. package/dist/server/remote.d.ts +4 -7
  171. package/dist/server/remote.js +37 -70
  172. package/dist/server/render-chat.d.ts +402 -0
  173. package/dist/server/render-chat.js +927 -0
  174. package/dist/server/render-pages.d.ts +535 -0
  175. package/dist/server/render-pages.js +1277 -0
  176. package/dist/server/render-people.d.ts +32 -0
  177. package/dist/server/render-people.js +121 -0
  178. package/dist/server/render-results.d.ts +744 -0
  179. package/dist/server/render-results.js +2237 -0
  180. package/dist/server/render-settings.d.ts +147 -0
  181. package/dist/server/render-settings.js +577 -0
  182. package/dist/server/render-tasks.d.ts +632 -0
  183. package/dist/server/render-tasks.js +2345 -0
  184. package/dist/server/request-context.d.ts +46 -0
  185. package/dist/server/request-context.js +17 -0
  186. package/dist/server/route-table.d.ts +25 -3
  187. package/dist/server/route-table.js +163 -75
  188. package/dist/server/runtime.d.ts +15 -7
  189. package/dist/server/runtime.js +7 -1
  190. package/dist/server/session.d.ts +138 -0
  191. package/dist/server/session.js +94 -0
  192. package/dist/server/settings.d.ts +1 -5
  193. package/dist/server/settings.js +2182 -2117
  194. package/dist/server/task-views.d.ts +11 -4
  195. package/dist/server/task-views.js +26 -22
  196. package/dist/server/tasks.d.ts +9 -9
  197. package/dist/server/tasks.js +1486 -1418
  198. package/dist/server-telemetry.d.ts +4 -3
  199. package/dist/server-telemetry.js +4 -8
  200. package/dist/skills-ui.d.ts +4 -3
  201. package/dist/skills-ui.js +14 -17
  202. package/dist/skills.d.ts +1 -1
  203. package/dist/skills.js +2 -1
  204. package/dist/slack-api.d.ts +5 -1
  205. package/dist/slack-api.js +2 -2
  206. package/dist/slack-chat.d.ts +9 -4
  207. package/dist/slack-chat.js +29 -52
  208. package/dist/slack-settings.d.ts +3 -2
  209. package/dist/slack-settings.js +23 -57
  210. package/dist/slack.js +6 -16
  211. package/dist/spend-ui.d.ts +2 -1
  212. package/dist/spend-ui.js +9 -32
  213. package/dist/sso-ui.d.ts +3 -2
  214. package/dist/sso-ui.js +26 -27
  215. package/dist/storage-ui.d.ts +2 -1
  216. package/dist/storage-ui.js +14 -33
  217. package/dist/store.d.ts +97 -364
  218. package/dist/store.js +207 -1531
  219. package/dist/surface.js +14 -3
  220. package/dist/task-composer.d.ts +2 -1
  221. package/dist/task-composer.js +7 -7
  222. package/dist/task-status.d.ts +4 -3
  223. package/dist/task-status.js +15 -16
  224. package/dist/team-http.d.ts +5 -9
  225. package/dist/team-http.js +5 -63
  226. package/dist/team-ui.d.ts +2 -1
  227. package/dist/team-ui.js +2 -5
  228. package/dist/teammate-question.js +12 -12
  229. package/dist/teammates-ui.d.ts +5 -4
  230. package/dist/teammates-ui.js +61 -90
  231. package/dist/teams-chat.js +12 -9
  232. package/dist/teams-settings.d.ts +3 -2
  233. package/dist/teams-settings.js +22 -33
  234. package/dist/teams.js +4 -5
  235. package/dist/telegram-flow.js +5 -5
  236. package/dist/telegram-settings.d.ts +3 -2
  237. package/dist/telegram-settings.js +14 -25
  238. package/dist/telegram.js +4 -4
  239. package/dist/toolroll-update-ui.d.ts +3 -2
  240. package/dist/toolroll-update-ui.js +35 -39
  241. package/dist/toolroll-update.d.ts +10 -0
  242. package/dist/toolroll-update.js +50 -3
  243. package/dist/tools-ui.d.ts +5 -2
  244. package/dist/tools-ui.js +31 -31
  245. package/dist/when-html.d.ts +11 -3
  246. package/dist/when-html.js +5 -6
  247. package/dist/workspace-revision.js +3 -1
  248. package/dist/workspace-ui.d.ts +4 -2
  249. package/dist/workspace-ui.js +10 -10
  250. package/package.json +1 -1
  251. package/dist/server/shared.d.ts +0 -3151
  252. package/dist/server/shared.js +0 -12001
  253. package/dist/slack-state.d.ts +0 -13
  254. package/dist/slack-state.js +0 -10
@@ -0,0 +1,30 @@
1
+ import type { Database } from "./store.js";
2
+ export type LegacyChatApp = "slack" | "discord" | "teams";
3
+ export declare const LEGACY_CHAT_APPS: readonly LegacyChatApp[];
4
+ /** One app's old tables, as an older database has (or should have had) them. */
5
+ export declare const legacyAppSchema: (app: LegacyChatApp) => string;
6
+ /** One app's 16 old tables, parents first. */
7
+ export declare const legacyAppTables: (app: LegacyChatApp) => string[];
8
+ /** Telegram's own tables (v1-v114) and the bridge's lease, kept verbatim. */
9
+ export declare const LEGACY_TELEGRAM_SCHEMA = "\nCREATE TABLE IF NOT EXISTS telegram_flow_choice (\n token TEXT PRIMARY KEY,\n binding INTEGER NOT NULL REFERENCES telegram_binding(id) ON DELETE RESTRICT,\n card INTEGER NOT NULL REFERENCES flow_card(id),\n entry INTEGER NOT NULL,\n choice INTEGER NOT NULL,\n label TEXT NOT NULL,\n chat_id TEXT NOT NULL,\n message_id TEXT,\n created_at TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n consumed_at TEXT\n);\nCREATE INDEX IF NOT EXISTS telegram_flow_choice_visit ON telegram_flow_choice (card, entry);\n\n-- v79: a Telegram message that showed one task (a /task status, a task\n-- picked from /tasks): a reply to it is about that task. Like chat_focus,\n-- a pointer and never an authority \u2014 the turn re-proves the task.\nCREATE TABLE IF NOT EXISTS telegram_task_message (\n binding INTEGER NOT NULL,\n chat_id TEXT NOT NULL,\n message_id TEXT NOT NULL,\n task_id TEXT NOT NULL,\n source_run INTEGER,\n created_at TEXT NOT NULL,\n PRIMARY KEY (binding, chat_id, message_id)\n);\n\n\n-- Away mode (v34, mate arc \u00A710): the Telegram bridge's digest cadence.\n-- One row. every_ms NULL = off (every fact pages as it lands); set, the\n-- bridge holds ROUTINE rows unclaimed until the window elapses and sends\n-- them as one message \u2014 decisions and attention-class facts still page\n-- singly. last_sent_at anchors the window; it never deletes a row.\nCREATE TABLE IF NOT EXISTS telegram_digest (\n id INTEGER PRIMARY KEY CHECK (id = 1),\n every_ms INTEGER,\n set_by TEXT,\n set_at TEXT,\n last_sent_at TEXT\n);\nINSERT OR IGNORE INTO telegram_digest (id, every_ms) VALUES (1, NULL);\n\n\n-- One Telegram chat speaking as one approver. Bindings are never deleted:\n-- revocation is a stamp, because \"who could answer as whom, when\" is an\n-- audit question a DELETE cannot answer. The partial unique index (v72) is\n-- the rule that one Telegram user has one live binding per bot: several\n-- teammates pair their own private chats with the same bot.\nCREATE TABLE IF NOT EXISTS telegram_binding (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n bot_id TEXT NOT NULL,\n chat_id TEXT NOT NULL,\n user_id TEXT NOT NULL,\n approver TEXT NOT NULL REFERENCES approver(name) ON DELETE RESTRICT,\n approver_generation INTEGER NOT NULL,\n paired_at TEXT NOT NULL,\n paired_by TEXT NOT NULL,\n pair_update_id INTEGER,\n revoked_at TEXT,\n revoked_by TEXT\n);\nCREATE UNIQUE INDEX IF NOT EXISTS telegram_binding_live_user\n ON telegram_binding (bot_id, user_id) WHERE revoked_at IS NULL;\n\n-- v72: a Telegram chat's place in the shared team conversations. A group\n-- follows exactly one team conversation (and a conversation has at most one\n-- group); a private chat may select one conversation to talk in instead of\n-- its personal assistant. The cursor is the last conversation message this\n-- chat received. Rows are revoked, never deleted.\nCREATE TABLE IF NOT EXISTS telegram_team_chat (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n bot_id TEXT NOT NULL,\n chat_id TEXT NOT NULL,\n binding INTEGER NOT NULL REFERENCES telegram_binding(id) ON DELETE RESTRICT,\n kind TEXT NOT NULL CHECK (kind IN ('group','private')),\n conversation TEXT NOT NULL REFERENCES team_conversation(id) ON DELETE RESTRICT,\n bound_by TEXT NOT NULL,\n bound_at TEXT NOT NULL,\n cursor INTEGER NOT NULL DEFAULT 0,\n revoked_at TEXT,\n revoked_by TEXT\n);\nCREATE UNIQUE INDEX IF NOT EXISTS telegram_team_chat_live\n ON telegram_team_chat (bot_id, chat_id) WHERE revoked_at IS NULL;\nCREATE UNIQUE INDEX IF NOT EXISTS telegram_team_chat_group\n ON telegram_team_chat (conversation) WHERE revoked_at IS NULL AND kind = 'group';\n\n\nCREATE TABLE IF NOT EXISTS telegram_outbound_message (\n binding INTEGER NOT NULL REFERENCES telegram_binding(id) ON DELETE RESTRICT,\n bot_id TEXT NOT NULL,\n chat_id TEXT NOT NULL,\n message_id TEXT NOT NULL,\n notification INTEGER NOT NULL REFERENCES notification(id) ON DELETE RESTRICT,\n destination TEXT NOT NULL,\n project TEXT,\n task_ref INTEGER REFERENCES task_ref(id),\n task_id TEXT,\n source_run INTEGER REFERENCES run(id),\n created_at TEXT NOT NULL,\n PRIMARY KEY (binding, chat_id, message_id, notification)\n);\nCREATE TABLE IF NOT EXISTS telegram_retry (\n bot_id TEXT PRIMARY KEY,\n next_attempt_at TEXT NOT NULL\n);\n\n-- One-time pairing codes, hashed like every other credential, consumed in\n-- one transaction with the binding they create.\nCREATE TABLE IF NOT EXISTS telegram_pairing (\n code_hash TEXT PRIMARY KEY,\n approver TEXT NOT NULL REFERENCES approver(name) ON DELETE RESTRICT,\n approver_generation INTEGER NOT NULL,\n created_at TEXT NOT NULL,\n created_by TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n consumed_at TEXT,\n consumed_chat TEXT,\n consumed_user TEXT,\n consumed_update INTEGER\n);\n\n-- Every Telegram update this installation has applied, exactly once. The\n-- PRIMARY KEY is the idempotency: a replayed batch re-applies nothing.\nCREATE TABLE IF NOT EXISTS telegram_update (\n update_id INTEGER PRIMARY KEY,\n applied_at TEXT NOT NULL,\n result TEXT NOT NULL\n);\n\n-- Opaque one-tap actions. callback_data carries only the random token; what\n-- the tap MEANS \u2014 which binding, decision, option, and phase \u2014 lives here,\n-- where a stolen bot token cannot read or forge it. Confirm challenges are\n-- short-lived rows in the same table, consumed exactly once.\nCREATE TABLE IF NOT EXISTS telegram_action (\n token TEXT PRIMARY KEY,\n binding INTEGER NOT NULL REFERENCES telegram_binding(id) ON DELETE RESTRICT,\n decision INTEGER NOT NULL REFERENCES decision(id) ON DELETE CASCADE,\n option_id TEXT NOT NULL,\n phase TEXT NOT NULL CHECK (phase IN ('choose','confirm','cancel')),\n chat_id TEXT NOT NULL,\n message_id TEXT,\n created_at TEXT NOT NULL,\n expires_at TEXT,\n consumed_at TEXT\n);\nCREATE INDEX IF NOT EXISTS telegram_action_by_decision ON telegram_action (decision);\n\n-- v86: a flow card waiting at a \"Person decides\" zone reaches the decider on\n-- Telegram with Approve / Edit / Send back. Each button is one opaque token\n-- for one visit of one card (card, entry), placed on the message it rides so\n-- a tap on any other message proves itself stale. Edit and Send back ask\n-- for a reply to a prompt: telegram_flow_prompt names which prompt means\n-- what, so the reply becomes the new draft or the note.\nCREATE TABLE IF NOT EXISTS telegram_flow_action (\n token TEXT PRIMARY KEY,\n binding INTEGER NOT NULL REFERENCES telegram_binding(id) ON DELETE RESTRICT,\n card INTEGER NOT NULL REFERENCES flow_card(id),\n entry INTEGER NOT NULL,\n action TEXT NOT NULL CHECK (action IN ('approve','edit','send-back')),\n chat_id TEXT NOT NULL,\n message_id TEXT,\n created_at TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n consumed_at TEXT\n);\nCREATE INDEX IF NOT EXISTS telegram_flow_action_visit ON telegram_flow_action (card, entry);\n-- v93: a teammate's question on Telegram. One button per option (choice)\n-- and one to reply in words (choice NULL), placed on the message it rides;\n-- a reply to the prompt the Reply button sends is the answer.\nCREATE TABLE IF NOT EXISTS telegram_question_action (\n token TEXT PRIMARY KEY,\n binding INTEGER NOT NULL REFERENCES telegram_binding(id) ON DELETE RESTRICT,\n question INTEGER NOT NULL REFERENCES teammate_question(id),\n choice TEXT,\n chat_id TEXT NOT NULL,\n message_id TEXT,\n created_at TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n consumed_at TEXT\n);\nCREATE TABLE IF NOT EXISTS telegram_question_prompt (\n chat_id TEXT NOT NULL,\n message_id TEXT NOT NULL,\n binding INTEGER NOT NULL REFERENCES telegram_binding(id) ON DELETE RESTRICT,\n question INTEGER NOT NULL REFERENCES teammate_question(id),\n created_at TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n consumed_at TEXT,\n PRIMARY KEY (chat_id, message_id)\n);\nCREATE TABLE IF NOT EXISTS telegram_flow_prompt (\n chat_id TEXT NOT NULL,\n message_id TEXT NOT NULL,\n binding INTEGER NOT NULL REFERENCES telegram_binding(id) ON DELETE RESTRICT,\n card INTEGER NOT NULL REFERENCES flow_card(id),\n entry INTEGER NOT NULL,\n mode TEXT NOT NULL CHECK (mode IN ('edit','send-back')),\n created_at TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n consumed_at TEXT,\n PRIMARY KEY (chat_id, message_id)\n);\n\n-- Which outbound Telegram message carries which decision (v10). A free-text\n-- reply is routed through the EXACT message it replies to \u2014 never \"the\n-- latest decision\", never \"the only open one\" (Codex free-text review,\n-- finding 1). Losing the send/record race fails closed: an unrecorded\n-- message routes nothing.\nCREATE TABLE IF NOT EXISTS telegram_decision_message (\n binding INTEGER NOT NULL REFERENCES telegram_binding(id) ON DELETE CASCADE,\n chat_id TEXT NOT NULL,\n message_id TEXT NOT NULL,\n decision INTEGER NOT NULL REFERENCES decision(id) ON DELETE CASCADE,\n created_at TEXT NOT NULL,\n PRIMARY KEY (binding, chat_id, message_id)\n);\n\n-- The free-text draft (v10): an operator's note, held immutable and\n-- expiring until a TAP commits it with the choice. One live draft per\n-- (binding, decision); a newer valid reply SUPERSEDES, never edits.\nCREATE TABLE IF NOT EXISTS telegram_note_draft (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n binding INTEGER NOT NULL REFERENCES telegram_binding(id) ON DELETE CASCADE,\n decision INTEGER NOT NULL REFERENCES decision(id) ON DELETE CASCADE,\n update_id INTEGER NOT NULL,\n message_id TEXT NOT NULL,\n reply_to TEXT NOT NULL,\n note TEXT NOT NULL,\n state TEXT NOT NULL DEFAULT 'pending' CHECK (state IN ('pending','armed','superseded','consumed','discarded')),\n created_at TEXT NOT NULL,\n expires_at TEXT NOT NULL\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS telegram_note_draft_live\n ON telegram_note_draft (binding, decision) WHERE state IN ('pending','armed');\n\n-- v62: the durable inbound conversation queue. An ordinary paired message\n-- becomes a row in the SAME transaction that marks its update applied, so\n-- the poll cursor never moves past text nobody holds. The row carries the\n-- exact binding, sender, update, message and the request identity the\n-- shared mate engine receipts it under; the async model turn runs OUTSIDE\n-- any transaction under a short claim, and a replay or restart finds the\n-- receipt instead of dispatching the provider again.\nCREATE TABLE IF NOT EXISTS telegram_conversation (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n binding INTEGER NOT NULL REFERENCES telegram_binding(id) ON DELETE RESTRICT,\n bot_id TEXT NOT NULL,\n chat_id TEXT NOT NULL,\n user_id TEXT NOT NULL,\n approver TEXT NOT NULL,\n approver_generation INTEGER NOT NULL,\n update_id INTEGER NOT NULL UNIQUE,\n message_id TEXT NOT NULL,\n reply_to TEXT,\n request TEXT NOT NULL UNIQUE,\n text TEXT NOT NULL,\n context TEXT,\n task_id TEXT,\n source_run INTEGER,\n state TEXT NOT NULL CHECK (state IN ('queued','running','done','failed')),\n claim_owner TEXT,\n claim_expires_at TEXT,\n attempts INTEGER NOT NULL DEFAULT 0,\n next_attempt_at TEXT,\n session INTEGER,\n turn INTEGER,\n outcome TEXT,\n reply_message_id TEXT,\n created_at TEXT NOT NULL,\n started_at TEXT,\n finished_at TEXT\n);\nCREATE INDEX IF NOT EXISTS telegram_conversation_queue ON telegram_conversation (bot_id, state, id);\n\n-- v62: opaque one-tap tokens for the mate's proposal cards, the same shape\n-- as telegram_action for decisions: callback_data carries only the token,\n-- and what a tap MEANS (which binding, which proposal, which phase) lives\n-- here. Consumed exactly once; an irreversible answer arms a yes/cancel\n-- pair first, exactly as a decision button does.\nCREATE TABLE IF NOT EXISTS telegram_proposal_action (\n token TEXT PRIMARY KEY,\n binding INTEGER NOT NULL REFERENCES telegram_binding(id) ON DELETE RESTRICT,\n proposal INTEGER NOT NULL REFERENCES mate_proposal(id) ON DELETE CASCADE,\n phase TEXT NOT NULL CHECK (phase IN ('confirm','dismiss','yes','cancel')),\n chat_id TEXT NOT NULL,\n message_id TEXT,\n created_at TEXT NOT NULL,\n expires_at TEXT,\n consumed_at TEXT\n);\nCREATE INDEX IF NOT EXISTS telegram_proposal_action_by_proposal ON telegram_proposal_action (proposal);\n\n-- v63: the outbound half of a conversation, durable BEFORE any send. Once\n-- the engine's turn is answered (or recovered from its receipt), the exact\n-- reply text, split into Telegram-sized parts, and one card per pending\n-- proposal are written here in one transaction; the bridge then sends\n-- them in order under the row's claim, marking a part sent only when\n-- Telegram confirmed a message id. A crash, an outage, a rate limit or a\n-- restart resumes from the first unsent part \u2014 never another model call,\n-- proposal, task or revision. A card's buttons are minted with the part,\n-- so a resend carries the same tokens. A part whose network answer was\n-- lost is counted as uncertain: a resend may duplicate it, and the row\n-- says so instead of claiming an exactly-once Telegram cannot provide.\n-- v64: an 'image' part is one verified screenshot of one exact result,\n-- named by typed columns \u2014 task, run, artifact and the hash its record\n-- carried when the part was planned \u2014 never by JSON inside text or a\n-- keyboard, and never by bytes: every send re-reads the artifact from the\n-- evidence root and re-verifies it against these columns first. Its text\n-- is the short caption. A confirmed image message binds replies to that\n-- exact task and run, exactly as an outbox fact's message does.\nCREATE TABLE IF NOT EXISTS telegram_conversation_part (\n conversation INTEGER NOT NULL REFERENCES telegram_conversation(id) ON DELETE CASCADE,\n ordinal INTEGER NOT NULL,\n kind TEXT NOT NULL CHECK (kind IN ('reply','card','image')),\n text TEXT NOT NULL,\n reply_to TEXT,\n proposal INTEGER REFERENCES mate_proposal(id) ON DELETE SET NULL,\n keyboard_json TEXT,\n state TEXT NOT NULL CHECK (state IN ('pending','sent','dropped')),\n message_id TEXT,\n attempts INTEGER NOT NULL DEFAULT 0,\n uncertain INTEGER NOT NULL DEFAULT 0,\n next_attempt_at TEXT,\n last_error TEXT,\n created_at TEXT NOT NULL,\n sent_at TEXT,\n task_id TEXT,\n source_run INTEGER REFERENCES run(id),\n artifact INTEGER,\n sha256 TEXT,\n PRIMARY KEY (conversation, ordinal),\n CHECK ((state = 'sent') = (message_id IS NOT NULL)),\n CHECK ((state = 'sent') = (sent_at IS NOT NULL)),\n CHECK ((kind = 'image') = (task_id IS NOT NULL AND source_run IS NOT NULL AND artifact IS NOT NULL AND sha256 IS NOT NULL))\n);\n\n\n-- The bridge's poll lease and cursor, per bot. One live poller at a time;\n-- the cursor only ever moves forward, and only under a live generation.\nCREATE TABLE IF NOT EXISTS bridge_lease (\n bot_id TEXT PRIMARY KEY,\n owner TEXT NOT NULL,\n generation INTEGER NOT NULL,\n cursor INTEGER NOT NULL DEFAULT 0,\n expires_at TEXT NOT NULL,\n heartbeat_at TEXT NOT NULL,\n push_url TEXT,\n push_at TEXT,\n push_problem TEXT\n);\n-- v98: updates Telegram pushed to /hooks/telegram, kept until the bridge\n-- applies them (in update order, through the same door as polled ones).\nCREATE TABLE IF NOT EXISTS telegram_inbox (\n update_id INTEGER PRIMARY KEY,\n bot_id TEXT NOT NULL,\n payload TEXT NOT NULL,\n received_at TEXT NOT NULL\n);\n\n\nCREATE TABLE IF NOT EXISTS telegram_flow_confirm (\n token TEXT PRIMARY KEY,\n binding INTEGER NOT NULL,\n chat_id TEXT NOT NULL,\n message_id TEXT NOT NULL,\n card INTEGER NOT NULL,\n entry INTEGER NOT NULL,\n phase TEXT NOT NULL CHECK (phase IN ('yes','cancel')),\n created_at TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n consumed_at TEXT\n);\nCREATE INDEX IF NOT EXISTS telegram_flow_confirm_visit ON telegram_flow_confirm (card, entry);\n";
10
+ /** Telegram's 21 old tables and the bridge's lease, children first. */
11
+ export declare const LEGACY_TELEGRAM_TABLES: readonly ["telegram_note_draft", "telegram_decision_message", "telegram_task_message", "telegram_outbound_message", "telegram_action", "telegram_proposal_action", "telegram_flow_action", "telegram_flow_confirm", "telegram_flow_choice", "telegram_flow_prompt", "telegram_question_action", "telegram_question_prompt", "telegram_conversation_part", "telegram_conversation", "telegram_team_chat", "telegram_pairing", "telegram_update", "telegram_inbox", "telegram_retry", "telegram_digest", "telegram_binding", "bridge_lease"];
12
+ /** Whether this database already keeps its chats in the shared tables (v116 ran, or it was made at v116 or later). */
13
+ export declare function chatTablesShared(db: Database): boolean;
14
+ /** Whether any of the old per-app tables is still here. */
15
+ export declare function legacyChatTablesPresent(db: Database): boolean;
16
+ /**
17
+ * What is wrong with the old chat tables this database still has, before anything is changed: one that lacks a column
18
+ * its every shape has had is not a table this build knows how to carry. Null when they are fine (or already gone).
19
+ */
20
+ export declare function legacyChatProblem(db: Database): string | null;
21
+ /**
22
+ * v116: every old chat table's rows into the shared ones, in one transaction. Each copy is one INSERT ... SELECT (no
23
+ * row passes through this process), then every count is checked against its source, every Telegram message's words
24
+ * against the person its binding names, and every foreign key; only then are the old tables dropped. Anything that
25
+ * doesn't add up rolls the whole move back and the open fails, with the old tables as they were. Run again (a resumed
26
+ * upgrade) it finds no old tables and does nothing.
27
+ */
28
+ export declare function convertChatTables(db: Database): {
29
+ copied: number;
30
+ };