@crewx/sdk 0.9.0-rc.11 → 0.9.0-rc.110

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 (246) hide show
  1. package/README.md +1 -1
  2. package/dist/account/auth-client.d.ts +61 -0
  3. package/dist/account/auth-json-v2.d.ts +1 -0
  4. package/dist/account/auth-json.d.ts +30 -0
  5. package/dist/account/config.d.ts +37 -0
  6. package/dist/account/env-bootstrap.d.ts +5 -0
  7. package/dist/account/errors.d.ts +24 -0
  8. package/dist/account/index.d.ts +12 -0
  9. package/dist/account/index.js +2 -0
  10. package/dist/account/session-manager.d.ts +47 -0
  11. package/dist/activity-log/builder.d.ts +56 -6
  12. package/dist/agent/agent-list-view.d.ts +19 -0
  13. package/dist/boxing/box.types.d.ts +4 -0
  14. package/dist/config/canonicalize-agent-options.d.ts +17 -0
  15. package/dist/config/default-agent-models.d.ts +11 -0
  16. package/dist/config/global-settings.d.ts +33 -0
  17. package/dist/config/migrate-grok-mode.d.ts +6 -0
  18. package/dist/config/model-compat.d.ts +31 -0
  19. package/dist/config/models.generated.d.ts +37 -0
  20. package/dist/config/models.remote.d.ts +1 -0
  21. package/dist/config/overdrive.d.ts +7 -0
  22. package/dist/config/pricing.d.ts +7 -3
  23. package/dist/config/pricing.generated.d.ts +4 -0
  24. package/dist/config/pricing.types.d.ts +4 -10
  25. package/dist/config/timeout.config.d.ts +4 -0
  26. package/dist/config/wi-boards.d.ts +19 -0
  27. package/dist/context-budget/continuity.d.ts +61 -0
  28. package/dist/context-budget/index.d.ts +141 -0
  29. package/dist/conversation/index.d.ts +1 -1
  30. package/dist/conversation/sqlite-provider.d.ts +6 -2
  31. package/dist/conversation/to-template-messages.d.ts +9 -0
  32. package/dist/conversation/types.d.ts +47 -1
  33. package/dist/desktop/command-runner.d.ts +4 -0
  34. package/dist/desktop/default-adapters.d.ts +4 -0
  35. package/dist/desktop/global-install.d.ts +19 -0
  36. package/dist/desktop/index.d.ts +3 -0
  37. package/dist/desktop/index.js +3 -0
  38. package/dist/desktop/install.d.ts +5 -0
  39. package/dist/desktop/lnk.d.ts +22 -0
  40. package/dist/desktop/manifest.d.ts +21 -0
  41. package/dist/desktop/types.d.ts +67 -0
  42. package/dist/desktop/version.d.ts +1 -0
  43. package/dist/desktop/windows-paths.d.ts +21 -0
  44. package/dist/desktop/wrapper.d.ts +18 -0
  45. package/dist/esm/account/index.js +2 -0
  46. package/dist/esm/desktop/index.js +3 -0
  47. package/dist/esm/index.js +700 -183
  48. package/dist/esm/plugins/index.js +302 -180
  49. package/dist/esm/process/index.js +1 -0
  50. package/dist/esm/publish/index.js +2 -0
  51. package/dist/esm/repository/index.js +370 -170
  52. package/dist/esm/skills/index.js +1 -0
  53. package/dist/esm/testing/index.js +1 -1
  54. package/dist/events/types.d.ts +9 -0
  55. package/dist/facade/Crewx.d.ts +54 -4
  56. package/dist/highlight/thread-highlight-prompt.d.ts +2 -0
  57. package/dist/highlight/thread-highlighter.d.ts +326 -0
  58. package/dist/index.browser.d.ts +14 -1
  59. package/dist/index.browser.js +6 -2
  60. package/dist/index.d.ts +106 -15
  61. package/dist/index.js +700 -183
  62. package/dist/internal/console-decoder.d.ts +38 -0
  63. package/dist/internal/windows-spawn.d.ts +10 -0
  64. package/dist/layout/types.d.ts +18 -1
  65. package/dist/lifecycle/task-heartbeat.d.ts +41 -0
  66. package/dist/lifecycle/task-stop.d.ts +82 -0
  67. package/dist/lifecycle/update-admission.d.ts +44 -0
  68. package/dist/local-server/base-url.d.ts +18 -0
  69. package/dist/local-server/index.d.ts +8 -0
  70. package/dist/local-server/opencode.d.ts +8 -0
  71. package/dist/local-server/probe.d.ts +3 -0
  72. package/dist/local-server/runtime.d.ts +26 -0
  73. package/dist/local-server/types.d.ts +43 -0
  74. package/dist/mcp-app/apps-context.d.ts +5 -0
  75. package/dist/mcp-app/catalog.d.ts +7 -0
  76. package/dist/mcp-app/discovery.d.ts +105 -0
  77. package/dist/mcp-app/errors.d.ts +7 -0
  78. package/dist/mcp-app/index.d.ts +18 -0
  79. package/dist/mcp-app/installed-app-ref.d.ts +25 -0
  80. package/dist/mcp-app/node-app-discovery-fs.d.ts +20 -0
  81. package/dist/mcp-app/projection.d.ts +13 -0
  82. package/dist/mcp-app/registry.d.ts +19 -0
  83. package/dist/mcp-app/state-set.d.ts +9 -0
  84. package/dist/mcp-app/types.d.ts +362 -0
  85. package/dist/mcp-app/workspace-snapshot.d.ts +53 -0
  86. package/dist/migrations/0008_careful_black_bird.sql +17 -0
  87. package/dist/migrations/0009_hot_dark_phoenix.sql +1 -0
  88. package/dist/migrations/0010_analyze_stats.sql +6 -0
  89. package/dist/migrations/0011_far_black_tarantula.sql +1 -0
  90. package/dist/migrations/0012_blue_turbo.sql +23 -0
  91. package/dist/migrations/0013_hesitant_adam_destine.sql +15 -0
  92. package/dist/migrations/0014_organic_mongu.sql +73 -0
  93. package/dist/migrations/0015_panoramic_gorilla_man.sql +71 -0
  94. package/dist/migrations/0016_fuzzy_hemingway.sql +14 -0
  95. package/dist/migrations/0017_project_stage_sdk_migration.sql +29 -0
  96. package/dist/migrations/0018_bored_jackal.sql +33 -0
  97. package/dist/migrations/0019_backfill_task_thread_ids.sql +74 -0
  98. package/dist/migrations/0020_useful_iron_lad.sql +55 -0
  99. package/dist/migrations/0021_dashing_peter_quill.sql +51 -0
  100. package/dist/migrations/0022_wandering_bucky.sql +1 -0
  101. package/dist/migrations/0023_red_payback.sql +1 -0
  102. package/dist/migrations/0024_storage_metadata.sql +262 -0
  103. package/dist/migrations/0025_task_heartbeat.sql +8 -0
  104. package/dist/migrations/0025_thread_app_instance_ledger.sql +2 -0
  105. package/dist/migrations/0026_mcp_action_source.sql +47 -0
  106. package/dist/migrations/0027_task_stop_scope_cleanup.sql +5 -0
  107. package/dist/migrations/0027_ui_instance_active_unique.sql +2 -0
  108. package/dist/migrations/0029_nice_rhino.sql +1 -0
  109. package/dist/migrations/0031_petite_arclight.sql +6 -0
  110. package/dist/migrations/meta/0008_snapshot.json +1327 -0
  111. package/dist/migrations/meta/0009_snapshot.json +1335 -0
  112. package/dist/migrations/meta/0010_snapshot.json +1335 -0
  113. package/dist/migrations/meta/0011_snapshot.json +1342 -0
  114. package/dist/migrations/meta/0012_snapshot.json +1494 -0
  115. package/dist/migrations/meta/0013_snapshot.json +1592 -0
  116. package/dist/migrations/meta/0014_snapshot.json +1975 -0
  117. package/dist/migrations/meta/0015_snapshot.json +2315 -0
  118. package/dist/migrations/meta/0016_snapshot.json +2419 -0
  119. package/dist/migrations/meta/0017_snapshot.json +2419 -0
  120. package/dist/migrations/meta/0018_snapshot.json +2570 -0
  121. package/dist/migrations/meta/0020_snapshot.json +2895 -0
  122. package/dist/migrations/meta/0021_snapshot.json +3031 -0
  123. package/dist/migrations/meta/0022_snapshot.json +3039 -0
  124. package/dist/migrations/meta/0023_snapshot.json +3047 -0
  125. package/dist/migrations/meta/0029_snapshot.json +3206 -0
  126. package/dist/migrations/meta/0031_snapshot.json +3251 -0
  127. package/dist/migrations/meta/_journal.json +168 -0
  128. package/dist/paths.d.ts +1 -0
  129. package/dist/plugin/types.d.ts +1 -0
  130. package/dist/plugins/index.d.ts +1 -1
  131. package/dist/plugins/index.js +302 -180
  132. package/dist/plugins/sqlite-tracing.d.ts +46 -0
  133. package/dist/process/index.d.ts +2 -0
  134. package/dist/process/index.js +1 -0
  135. package/dist/process/process-control.d.ts +41 -0
  136. package/dist/prompt/tag-names.d.ts +20 -0
  137. package/dist/provider/acp/connection.d.ts +6 -0
  138. package/dist/provider/acp/meta.d.ts +11 -0
  139. package/dist/provider/bridge.d.ts +7 -1
  140. package/dist/provider/classify-task-error.d.ts +2 -0
  141. package/dist/provider/cli/adapter.types.d.ts +9 -1
  142. package/dist/provider/cli/adapters/agent-call.util.d.ts +1 -1
  143. package/dist/provider/cli/adapters/cli-knob.util.d.ts +7 -0
  144. package/dist/provider/cli/adapters/event-timestamp.util.d.ts +1 -0
  145. package/dist/provider/cli/adapters/grok.d.ts +2 -0
  146. package/dist/provider/cli/adapters/index.d.ts +1 -0
  147. package/dist/provider/cli/index.d.ts +1 -1
  148. package/dist/provider/cli/meta.d.ts +5 -0
  149. package/dist/provider/cli/protocol-envelope.d.ts +2 -0
  150. package/dist/provider/errors.d.ts +5 -1
  151. package/dist/provider/idle-watchdog.d.ts +19 -0
  152. package/dist/provider/models.d.ts +17 -12
  153. package/dist/provider/order.d.ts +1 -1
  154. package/dist/provider/parse-usage.d.ts +6 -0
  155. package/dist/provider/provider-selection.d.ts +8 -0
  156. package/dist/provider/redact-technical-message.d.ts +1 -0
  157. package/dist/provider/task-error.types.d.ts +17 -0
  158. package/dist/publish/constants.d.ts +6 -0
  159. package/dist/publish/errors.d.ts +7 -0
  160. package/dist/publish/index.d.ts +50 -0
  161. package/dist/publish/index.js +2 -0
  162. package/dist/publish/manifest.d.ts +47 -0
  163. package/dist/publish/marketplace-api.constants.d.ts +1 -0
  164. package/dist/publish/pack.d.ts +6 -0
  165. package/dist/publish/scan.d.ts +9 -0
  166. package/dist/publish/secrets.d.ts +6 -0
  167. package/dist/publish/upload.d.ts +19 -0
  168. package/dist/remote/execution-profile.d.ts +9 -0
  169. package/dist/remote/index.d.ts +1 -0
  170. package/dist/remote/types.d.ts +28 -0
  171. package/dist/repository/agent-suggestion.repository.d.ts +34 -0
  172. package/dist/repository/base-sqlite-repository.d.ts +1 -0
  173. package/dist/repository/common-code.repository.d.ts +45 -0
  174. package/dist/repository/db.d.ts +12 -1
  175. package/dist/repository/index.d.ts +38 -5
  176. package/dist/repository/index.js +370 -170
  177. package/dist/repository/notification.repository.d.ts +58 -0
  178. package/dist/repository/project.repository.d.ts +90 -0
  179. package/dist/repository/request-log.repository.d.ts +1 -0
  180. package/dist/repository/storage-metadata.repository.d.ts +64 -0
  181. package/dist/repository/task-log-migration.d.ts +74 -0
  182. package/dist/repository/task-log.repository.d.ts +44 -0
  183. package/dist/repository/task-status.d.ts +14 -0
  184. package/dist/repository/task.repository.d.ts +246 -7
  185. package/dist/repository/thread-history.repository.d.ts +193 -0
  186. package/dist/repository/thread-title.types.d.ts +29 -0
  187. package/dist/repository/thread.repository.d.ts +47 -5
  188. package/dist/repository/usage-backfill.d.ts +62 -0
  189. package/dist/repository/usage-from-logs.d.ts +21 -0
  190. package/dist/repository/usage-report.repository.d.ts +27 -0
  191. package/dist/repository/workspace.repository.d.ts +3 -0
  192. package/dist/schema/agent-suggestions.d.ts +199 -0
  193. package/dist/schema/common-codes.d.ts +216 -0
  194. package/dist/schema/index.d.ts +10 -0
  195. package/dist/schema/notifications.d.ts +303 -0
  196. package/dist/schema/projects.d.ts +610 -0
  197. package/dist/schema/storage-metadata.d.ts +181 -0
  198. package/dist/schema/task-log-events.d.ts +119 -0
  199. package/dist/schema/tasks.d.ts +165 -0
  200. package/dist/schema/thread-history.d.ts +734 -0
  201. package/dist/schema/threads.d.ts +59 -0
  202. package/dist/schema/ui-action-receipts.d.ts +303 -0
  203. package/dist/schema/ui-instances.d.ts +286 -0
  204. package/dist/schema/usage-reports.d.ts +252 -0
  205. package/dist/schema/workspaces.d.ts +17 -0
  206. package/dist/skills/index.d.ts +7 -0
  207. package/dist/skills/index.js +1 -0
  208. package/dist/skills/types.d.ts +18 -0
  209. package/dist/task-log/anchor-child-tasks.d.ts +7 -0
  210. package/dist/task-log/delegation-trailer.d.ts +34 -0
  211. package/dist/template/engine.d.ts +2 -2
  212. package/dist/template/helpers/exec.browser.d.ts +4 -3
  213. package/dist/template/helpers/exec.d.ts +4 -3
  214. package/dist/template/types.d.ts +20 -0
  215. package/dist/testing/index.js +1 -1
  216. package/dist/types/index.d.ts +1569 -3
  217. package/dist/types/task-log.types.d.ts +2 -0
  218. package/dist/ui-card/index.d.ts +2 -0
  219. package/dist/ui-card/legacy-card-parser.d.ts +11 -0
  220. package/dist/ui-instance/definition.d.ts +6 -0
  221. package/dist/ui-instance/errors.d.ts +17 -0
  222. package/dist/ui-instance/index.d.ts +9 -0
  223. package/dist/ui-instance/json.d.ts +5 -0
  224. package/dist/ui-instance/runtime.d.ts +18 -0
  225. package/dist/ui-instance/store.d.ts +99 -0
  226. package/dist/ui-instance/types.d.ts +213 -0
  227. package/dist/ui-plugin/index.d.ts +4 -0
  228. package/dist/ui-plugin/limits.d.ts +27 -0
  229. package/dist/ui-plugin/manifest.d.ts +3 -0
  230. package/dist/ui-plugin/types.d.ts +174 -0
  231. package/dist/ui-plugin/validator.d.ts +15 -0
  232. package/dist/utils/crewx-executable.d.ts +54 -0
  233. package/dist/utils/crewx-home.d.ts +1 -0
  234. package/dist/utils/env-defaults.d.ts +2 -0
  235. package/dist/utils/id.d.ts +1 -1
  236. package/dist/utils/runner-env.d.ts +3 -0
  237. package/dist/utils/timestamp.d.ts +1 -0
  238. package/dist/utils/workspace.d.ts +1 -0
  239. package/dist/wi/create.d.ts +48 -0
  240. package/dist/wi/select.d.ts +20 -0
  241. package/package.json +40 -2
  242. package/templates/agents/default.yaml +269 -127
  243. package/templates/documents/crewx-manual.md +138 -138
  244. package/templates/documents/crewx-quick-guide.md +1 -1
  245. package/templates/workflows/wi-default-flow.yaml +65 -0
  246. package/templates/workflows/wi-plan-flow.yaml +140 -0
@@ -0,0 +1,29 @@
1
+ -- Normalize the exact historical default without carrying translated labels
2
+ -- into the SDK-owned persistence contract.
3
+ UPDATE projects
4
+ SET stages_json = '[{"key":"outcome_plan","labelOverride":null},{"key":"contract_check","labelOverride":null},{"key":"feature_link","labelOverride":null},{"key":"use_verify","labelOverride":null},{"key":"result_review","labelOverride":null}]'
5
+ WHERE json(stages_json) = json('[{"key":"outcome_plan","label":"결과·계획"},{"key":"contract_check","label":"계약 확인"},{"key":"feature_link","label":"기능 연결"},{"key":"use_verify","label":"사용 검증"},{"key":"result_review","label":"결과 확인"}]');
6
+ --> statement-breakpoint
7
+ -- Custom and mixed arrays retain their label text under the new property name.
8
+ UPDATE projects
9
+ SET stages_json = (
10
+ SELECT json_group_array(
11
+ CASE
12
+ WHEN json_type(value, '$.label') IS NULL THEN json(value)
13
+ ELSE json_set(
14
+ json_remove(json(value), '$.label'),
15
+ '$.labelOverride',
16
+ json(json_quote(json_extract(value, '$.label')))
17
+ )
18
+ END
19
+ )
20
+ FROM json_each(projects.stages_json)
21
+ )
22
+ WHERE json_valid(stages_json)
23
+ AND json_type(stages_json) = 'array'
24
+ AND json(stages_json) <> json('[{"key":"outcome_plan","label":"결과·계획"},{"key":"contract_check","label":"계약 확인"},{"key":"feature_link","label":"기능 연결"},{"key":"use_verify","label":"사용 검증"},{"key":"result_review","label":"결과 확인"}]')
25
+ AND EXISTS (
26
+ SELECT 1
27
+ FROM json_each(projects.stages_json)
28
+ WHERE json_type(value, '$.label') IS NOT NULL
29
+ );
@@ -0,0 +1,33 @@
1
+ CREATE TABLE IF NOT EXISTS `common_codes` (
2
+ `code_group` text NOT NULL,
3
+ `code` text NOT NULL,
4
+ `code_name` text,
5
+ `color` text DEFAULT 'gray' NOT NULL,
6
+ `sort_order` integer NOT NULL,
7
+ `workspace_id` text,
8
+ `is_builtin` integer DEFAULT 0 NOT NULL,
9
+ `is_archived` integer DEFAULT 0 NOT NULL,
10
+ `metadata` text,
11
+ `created_at` text NOT NULL,
12
+ `updated_at` text NOT NULL,
13
+ PRIMARY KEY(`code_group`, `code`),
14
+ CONSTRAINT "common_codes_metadata_ck" CHECK("common_codes"."metadata" IS NULL OR (json_valid("common_codes"."metadata") AND json_type("common_codes"."metadata") = 'object')),
15
+ CONSTRAINT "common_codes_builtin_ck" CHECK("common_codes"."is_builtin" IN (0, 1)),
16
+ CONSTRAINT "common_codes_archived_ck" CHECK("common_codes"."is_archived" IN (0, 1))
17
+ );
18
+ --> statement-breakpoint
19
+ CREATE INDEX IF NOT EXISTS `idx_common_codes_group_archived_order` ON `common_codes` (`code_group`,`is_archived`,`sort_order`);--> statement-breakpoint
20
+ INSERT OR IGNORE INTO `common_codes`
21
+ (`code_group`, `code`, `code_name`, `color`, `sort_order`, `workspace_id`, `is_builtin`, `is_archived`, `metadata`, `created_at`, `updated_at`)
22
+ VALUES
23
+ ('THREAD_PRIORITY', 'urgent', NULL, 'red', 0, NULL, 1, 0, NULL, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
24
+ ('THREAD_PRIORITY', 'high', NULL, 'orange', 1, NULL, 1, 0, NULL, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
25
+ ('THREAD_PRIORITY', 'medium', NULL, 'blue', 2, NULL, 1, 0, NULL, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
26
+ ('THREAD_PRIORITY', 'low', NULL, 'gray', 3, NULL, 1, 0, NULL, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
27
+ ('THREAD_STATE', 'investigating', NULL, 'violet', 0, NULL, 1, 0, NULL, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
28
+ ('THREAD_STATE', 'in-progress', NULL, 'blue', 1, NULL, 1, 0, NULL, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
29
+ ('THREAD_STATE', 'in-review', NULL, 'amber', 2, NULL, 1, 0, NULL, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
30
+ ('THREAD_STATE', 'on-hold', NULL, 'gray', 3, NULL, 1, 0, NULL, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
31
+ ('THREAD_STATE', 'done', NULL, 'green', 4, NULL, 1, 0, NULL, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), strftime('%Y-%m-%dT%H:%M:%fZ', 'now'));--> statement-breakpoint
32
+ CREATE INDEX IF NOT EXISTS `idx_threads_workspace_thread_state` ON `threads` (`workspace_id`, json_extract(metadata, '$.threadTitle.state'));--> statement-breakpoint
33
+ CREATE INDEX IF NOT EXISTS `idx_threads_workspace_thread_priority` ON `threads` (`workspace_id`, json_extract(metadata, '$.threadTitle.priority'));
@@ -0,0 +1,74 @@
1
+ -- Backfill the indexed thread_id before command-based legacy lookups are removed.
2
+ -- The command format stores a thread id as the next whitespace-delimited value
3
+ -- after --thread=. Quoted values are normalized because some older launchers
4
+ -- persisted argv strings with quotes. A prompt can also contain a documented
5
+ -- --thread= example, so the final marker is the actual CLI option appended by
6
+ -- the launcher.
7
+ WITH RECURSIVE thread_markers(id, command, marker_pos) AS (
8
+ SELECT
9
+ id,
10
+ command,
11
+ instr(command, '--thread=') AS marker_pos
12
+ FROM tasks
13
+ WHERE thread_id IS NULL
14
+ AND command IS NOT NULL
15
+ AND instr(command, '--thread=') > 0
16
+
17
+ UNION ALL
18
+
19
+ SELECT
20
+ id,
21
+ command,
22
+ marker_pos
23
+ + length('--thread=')
24
+ - 1
25
+ + instr(substr(command, marker_pos + length('--thread=')), '--thread=')
26
+ FROM thread_markers
27
+ WHERE instr(substr(command, marker_pos + length('--thread=')), '--thread=') > 0
28
+ ), last_markers AS (
29
+ SELECT id, command, MAX(marker_pos) AS marker_pos
30
+ FROM thread_markers
31
+ GROUP BY id, command
32
+ ), legacy_threads AS (
33
+ SELECT
34
+ id,
35
+ substr(command, marker_pos + length('--thread=')) AS tail
36
+ FROM last_markers
37
+ ), extracted AS (
38
+ SELECT
39
+ id,
40
+ trim(
41
+ CASE
42
+ WHEN instr(replace(replace(replace(tail, char(9), ' '), char(10), ' '), char(13), ' '), ' ') > 0
43
+ THEN substr(
44
+ replace(replace(replace(tail, char(9), ' '), char(10), ' '), char(13), ' '),
45
+ 1,
46
+ instr(replace(replace(replace(tail, char(9), ' '), char(10), ' '), char(13), ' '), ' ') - 1
47
+ )
48
+ ELSE replace(replace(replace(tail, char(9), ' '), char(10), ' '), char(13), ' ')
49
+ END
50
+ ) AS raw_thread_id
51
+ FROM legacy_threads
52
+ ), normalized AS (
53
+ SELECT
54
+ id,
55
+ CASE
56
+ WHEN substr(raw_thread_id, 1, 1) IN ('"', char(39))
57
+ AND substr(raw_thread_id, -1, 1) = substr(raw_thread_id, 1, 1)
58
+ THEN substr(raw_thread_id, 2, length(raw_thread_id) - 2)
59
+ ELSE raw_thread_id
60
+ END AS thread_id
61
+ FROM extracted
62
+ )
63
+ UPDATE tasks
64
+ SET thread_id = (
65
+ SELECT normalized.thread_id
66
+ FROM normalized
67
+ WHERE normalized.id = tasks.id
68
+ )
69
+ WHERE tasks.thread_id IS NULL
70
+ AND tasks.id IN (
71
+ SELECT id
72
+ FROM normalized
73
+ WHERE length(thread_id) > 0
74
+ );
@@ -0,0 +1,55 @@
1
+ CREATE TABLE IF NOT EXISTS `thread_events` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `thread_id` text NOT NULL,
4
+ `seq` integer NOT NULL,
5
+ `type` text NOT NULL,
6
+ `actor_type` text NOT NULL,
7
+ `payload_json` text NOT NULL,
8
+ `created_at` text NOT NULL,
9
+ `actor_id` text,
10
+ `task_id` text,
11
+ `highlight_id` text,
12
+ FOREIGN KEY (`thread_id`) REFERENCES `threads`(`id`) ON UPDATE no action ON DELETE cascade,
13
+ CONSTRAINT "thread_events_type_ck" CHECK("thread_events"."type" IN ('thread.snapshot.imported', 'thread.title.changed', 'thread.priority.changed', 'thread.state.changed', 'thread.highlight.created', 'thread.highlight.updated', 'thread.highlight.deleted')),
14
+ CONSTRAINT "thread_events_actor_type_ck" CHECK("thread_events"."actor_type" IN ('user', 'agent', 'system')),
15
+ CONSTRAINT "thread_events_payload_json_ck" CHECK(json_valid("thread_events"."payload_json") AND json_type("thread_events"."payload_json") = 'object')
16
+ );
17
+ --> statement-breakpoint
18
+ CREATE INDEX IF NOT EXISTS `idx_thread_events_thread_seq` ON `thread_events` (`thread_id`,`seq`);--> statement-breakpoint
19
+ CREATE INDEX IF NOT EXISTS `idx_thread_events_thread_created` ON `thread_events` (`thread_id`,`created_at`);--> statement-breakpoint
20
+ CREATE UNIQUE INDEX IF NOT EXISTS `thread_events_thread_seq_uq` ON `thread_events` (`thread_id`,`seq`);--> statement-breakpoint
21
+ CREATE TABLE IF NOT EXISTS `thread_highlights` (
22
+ `id` text PRIMARY KEY NOT NULL,
23
+ `thread_id` text NOT NULL,
24
+ `source` text NOT NULL,
25
+ `kind` text NOT NULL,
26
+ `status` text DEFAULT 'active' NOT NULL,
27
+ `text` text,
28
+ `covers_from_task_id` text NOT NULL,
29
+ `covers_to_task_id` text NOT NULL,
30
+ `revision` integer DEFAULT 0 NOT NULL,
31
+ `created_at` text NOT NULL,
32
+ `updated_at` text NOT NULL,
33
+ `agent_id` text,
34
+ `source_task_id` text,
35
+ `detector_version` text,
36
+ `content_fingerprint` text,
37
+ `dismissed_at` text,
38
+ FOREIGN KEY (`thread_id`) REFERENCES `threads`(`id`) ON UPDATE no action ON DELETE cascade,
39
+ CONSTRAINT "thread_highlights_source_ck" CHECK("thread_highlights"."source" IN ('auto', 'manual')),
40
+ CONSTRAINT "thread_highlights_kind_ck" CHECK("thread_highlights"."kind" IN ('decision', 'judgment', 'issue', 'result', 'pivot')),
41
+ CONSTRAINT "thread_highlights_status_ck" CHECK("thread_highlights"."status" IN ('active', 'dismissed')),
42
+ CONSTRAINT "thread_highlights_active_text_ck" CHECK("thread_highlights"."status" = 'dismissed' OR ("thread_highlights"."text" IS NOT NULL AND length("thread_highlights"."text") > 0)),
43
+ CONSTRAINT "thread_highlights_covers_ck" CHECK(length("thread_highlights"."covers_from_task_id") > 0 AND length("thread_highlights"."covers_to_task_id") > 0),
44
+ CONSTRAINT "thread_highlights_auto_key_ck" CHECK("thread_highlights"."source" = 'manual' OR ("thread_highlights"."source" = 'auto' AND "thread_highlights"."source_task_id" IS NOT NULL AND "thread_highlights"."detector_version" IS NOT NULL AND "thread_highlights"."content_fingerprint" IS NOT NULL AND length("thread_highlights"."source_task_id") > 0 AND length("thread_highlights"."detector_version") > 0 AND length("thread_highlights"."content_fingerprint") > 0))
45
+ );
46
+ --> statement-breakpoint
47
+ CREATE INDEX IF NOT EXISTS `idx_thread_highlights_thread_status_created` ON `thread_highlights` (`thread_id`,`status`,`created_at`);--> statement-breakpoint
48
+ CREATE INDEX IF NOT EXISTS `idx_thread_highlights_thread_covers` ON `thread_highlights` (`thread_id`,`covers_from_task_id`,`covers_to_task_id`);--> statement-breakpoint
49
+ CREATE UNIQUE INDEX IF NOT EXISTS `thread_highlights_auto_idempotency_uq` ON `thread_highlights` (`thread_id`,`source_task_id`,`detector_version`,`content_fingerprint`) WHERE "thread_highlights"."source" = 'auto';
50
+ --> statement-breakpoint
51
+ CREATE TRIGGER IF NOT EXISTS thread_events_no_update
52
+ BEFORE UPDATE ON thread_events
53
+ BEGIN
54
+ SELECT RAISE(ABORT, 'thread_events is append-only');
55
+ END;
@@ -0,0 +1,51 @@
1
+ CREATE TABLE IF NOT EXISTS `thread_highlight_runs` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `thread_id` text NOT NULL,
4
+ `request_id` text NOT NULL,
5
+ `status` text NOT NULL,
6
+ `detector_version` text NOT NULL,
7
+ `requested_at` text NOT NULL,
8
+ `started_at` text,
9
+ `completed_at` text,
10
+ `error_code` text,
11
+ `previous_auto_count` integer,
12
+ `new_auto_count` integer,
13
+ FOREIGN KEY (`thread_id`) REFERENCES `threads`(`id`) ON UPDATE no action ON DELETE cascade,
14
+ CONSTRAINT "thread_highlight_runs_status_ck" CHECK("thread_highlight_runs"."status" IN ('queued', 'running', 'completed', 'failed')),
15
+ CONSTRAINT "thread_highlight_runs_counts_ck" CHECK(("thread_highlight_runs"."previous_auto_count" IS NULL OR "thread_highlight_runs"."previous_auto_count" >= 0) AND ("thread_highlight_runs"."new_auto_count" IS NULL OR "thread_highlight_runs"."new_auto_count" >= 0))
16
+ );
17
+ --> statement-breakpoint
18
+ CREATE UNIQUE INDEX IF NOT EXISTS `thread_highlight_runs_thread_request_uq` ON `thread_highlight_runs` (`thread_id`,`request_id`);--> statement-breakpoint
19
+ CREATE UNIQUE INDEX IF NOT EXISTS `thread_highlight_runs_in_progress_thread_uq` ON `thread_highlight_runs` (`thread_id`) WHERE "thread_highlight_runs"."status" IN ('queued', 'running');--> statement-breakpoint
20
+ CREATE INDEX IF NOT EXISTS `idx_thread_highlight_runs_thread_status_requested` ON `thread_highlight_runs` (`thread_id`,`status`,`requested_at`);--> statement-breakpoint
21
+ PRAGMA foreign_keys=OFF;--> statement-breakpoint
22
+ CREATE TABLE IF NOT EXISTS `__new_thread_events` (
23
+ `id` text PRIMARY KEY NOT NULL,
24
+ `thread_id` text NOT NULL,
25
+ `seq` integer NOT NULL,
26
+ `type` text NOT NULL,
27
+ `actor_type` text NOT NULL,
28
+ `payload_json` text NOT NULL,
29
+ `created_at` text NOT NULL,
30
+ `actor_id` text,
31
+ `task_id` text,
32
+ `highlight_id` text,
33
+ FOREIGN KEY (`thread_id`) REFERENCES `threads`(`id`) ON UPDATE no action ON DELETE cascade,
34
+ CONSTRAINT "thread_events_type_ck" CHECK("__new_thread_events"."type" IN ('thread.snapshot.imported', 'thread.title.changed', 'thread.priority.changed', 'thread.state.changed', 'thread.highlight.created', 'thread.highlight.updated', 'thread.highlight.deleted', 'thread.highlights.regenerated')),
35
+ CONSTRAINT "thread_events_actor_type_ck" CHECK("__new_thread_events"."actor_type" IN ('user', 'agent', 'system')),
36
+ CONSTRAINT "thread_events_payload_json_ck" CHECK(json_valid("__new_thread_events"."payload_json") AND json_type("__new_thread_events"."payload_json") = 'object')
37
+ );
38
+ --> statement-breakpoint
39
+ INSERT INTO `__new_thread_events`("id", "thread_id", "seq", "type", "actor_type", "payload_json", "created_at", "actor_id", "task_id", "highlight_id") SELECT "id", "thread_id", "seq", "type", "actor_type", "payload_json", "created_at", "actor_id", "task_id", "highlight_id" FROM `thread_events`;--> statement-breakpoint
40
+ DROP TABLE `thread_events`;--> statement-breakpoint
41
+ ALTER TABLE `__new_thread_events` RENAME TO `thread_events`;--> statement-breakpoint
42
+ PRAGMA foreign_keys=ON;--> statement-breakpoint
43
+ CREATE INDEX IF NOT EXISTS `idx_thread_events_thread_seq` ON `thread_events` (`thread_id`,`seq`);--> statement-breakpoint
44
+ CREATE INDEX IF NOT EXISTS `idx_thread_events_thread_created` ON `thread_events` (`thread_id`,`created_at`);--> statement-breakpoint
45
+ CREATE UNIQUE INDEX IF NOT EXISTS `thread_events_thread_seq_uq` ON `thread_events` (`thread_id`,`seq`);
46
+ --> statement-breakpoint
47
+ CREATE TRIGGER IF NOT EXISTS thread_events_no_update
48
+ BEFORE UPDATE ON thread_events
49
+ BEGIN
50
+ SELECT RAISE(ABORT, 'thread_events is append-only');
51
+ END;
@@ -0,0 +1 @@
1
+ CREATE INDEX IF NOT EXISTS `task_log_events_timestamp_id_idx` ON `task_log_events` (`timestamp`,`id`);
@@ -0,0 +1 @@
1
+ ALTER TABLE `workspaces` ADD `starred` integer DEFAULT 0 NOT NULL;
@@ -0,0 +1,262 @@
1
+ CREATE TABLE IF NOT EXISTS `storage_metadata` (
2
+ `source_kind` text NOT NULL,
3
+ `source_id` text NOT NULL,
4
+ `utc_ts` text,
5
+ `bytes` integer NOT NULL,
6
+ PRIMARY KEY (`source_kind`, `source_id`)
7
+ ) WITHOUT ROWID;
8
+ --> statement-breakpoint
9
+ CREATE INDEX IF NOT EXISTS `idx_storage_metadata_kind_ts_bytes`
10
+ ON `storage_metadata` (`source_kind`, `utc_ts`, `bytes`);
11
+ --> statement-breakpoint
12
+ CREATE TABLE IF NOT EXISTS `storage_metadata_state` (
13
+ `unit` text PRIMARY KEY NOT NULL,
14
+ `cursor_rowid` integer DEFAULT 0 NOT NULL,
15
+ `end_rowid` integer,
16
+ `complete` integer DEFAULT 0 NOT NULL,
17
+ `updated_at` text NOT NULL
18
+ ) WITHOUT ROWID;
19
+ --> statement-breakpoint
20
+ CREATE TRIGGER IF NOT EXISTS `trg_storage_meta_tle_ins`
21
+ AFTER INSERT ON `task_log_events`
22
+ BEGIN
23
+ INSERT INTO `storage_metadata` (`source_kind`, `source_id`, `utc_ts`, `bytes`)
24
+ VALUES (
25
+ 'taskLogs',
26
+ CAST(NEW.`id` AS TEXT),
27
+ datetime(NEW.`timestamp`),
28
+ COALESCE(length(CAST(NEW.`message` AS BLOB)), 0)
29
+ + COALESCE(length(CAST(NEW.`task_id` AS BLOB)), 0)
30
+ + COALESCE(length(CAST(NEW.`timestamp` AS BLOB)), 0)
31
+ + COALESCE(length(CAST(NEW.`level` AS BLOB)), 0)
32
+ )
33
+ ON CONFLICT (`source_kind`, `source_id`) DO UPDATE SET
34
+ `utc_ts` = excluded.`utc_ts`,
35
+ `bytes` = excluded.`bytes`;
36
+ END;
37
+ --> statement-breakpoint
38
+ CREATE TRIGGER IF NOT EXISTS `trg_storage_meta_tle_upd`
39
+ AFTER UPDATE OF `id`, `timestamp`, `task_id`, `level`, `message` ON `task_log_events`
40
+ BEGIN
41
+ DELETE FROM `storage_metadata`
42
+ WHERE `source_kind` = 'taskLogs'
43
+ AND `source_id` = CAST(OLD.`id` AS TEXT)
44
+ AND OLD.`id` IS NOT NEW.`id`;
45
+ INSERT INTO `storage_metadata` (`source_kind`, `source_id`, `utc_ts`, `bytes`)
46
+ VALUES (
47
+ 'taskLogs',
48
+ CAST(NEW.`id` AS TEXT),
49
+ datetime(NEW.`timestamp`),
50
+ COALESCE(length(CAST(NEW.`message` AS BLOB)), 0)
51
+ + COALESCE(length(CAST(NEW.`task_id` AS BLOB)), 0)
52
+ + COALESCE(length(CAST(NEW.`timestamp` AS BLOB)), 0)
53
+ + COALESCE(length(CAST(NEW.`level` AS BLOB)), 0)
54
+ )
55
+ ON CONFLICT (`source_kind`, `source_id`) DO UPDATE SET
56
+ `utc_ts` = excluded.`utc_ts`,
57
+ `bytes` = excluded.`bytes`;
58
+ END;
59
+ --> statement-breakpoint
60
+ CREATE TRIGGER IF NOT EXISTS `trg_storage_meta_tle_del`
61
+ AFTER DELETE ON `task_log_events`
62
+ BEGIN
63
+ DELETE FROM `storage_metadata`
64
+ WHERE `source_kind` = 'taskLogs'
65
+ AND `source_id` = CAST(OLD.`id` AS TEXT);
66
+ END;
67
+ --> statement-breakpoint
68
+ CREATE TRIGGER IF NOT EXISTS `trg_storage_meta_request_logs_ins`
69
+ AFTER INSERT ON `request_logs`
70
+ BEGIN
71
+ INSERT INTO `storage_metadata` (`source_kind`, `source_id`, `utc_ts`, `bytes`)
72
+ VALUES (
73
+ 'requestLogs',
74
+ CAST(NEW.`id` AS TEXT),
75
+ datetime(NEW.`timestamp`),
76
+ COALESCE(length(CAST(NEW.`path` AS BLOB)), 0)
77
+ + COALESCE(length(CAST(NEW.`method` AS BLOB)), 0)
78
+ + COALESCE(length(CAST(NEW.`request_body` AS BLOB)), 0)
79
+ + COALESCE(length(CAST(NEW.`response_body` AS BLOB)), 0)
80
+ + COALESCE(length(CAST(NEW.`request_headers` AS BLOB)), 0)
81
+ + COALESCE(length(CAST(NEW.`response_headers` AS BLOB)), 0)
82
+ + COALESCE(length(CAST(NEW.`query` AS BLOB)), 0)
83
+ + COALESCE(length(CAST(NEW.`metadata` AS BLOB)), 0)
84
+ )
85
+ ON CONFLICT (`source_kind`, `source_id`) DO UPDATE SET
86
+ `utc_ts` = excluded.`utc_ts`,
87
+ `bytes` = excluded.`bytes`;
88
+ END;
89
+ --> statement-breakpoint
90
+ CREATE TRIGGER IF NOT EXISTS `trg_storage_meta_request_logs_upd`
91
+ AFTER UPDATE OF `id`, `timestamp`, `path`, `method`, `request_body`, `response_body`, `request_headers`, `response_headers`, `query`, `metadata` ON `request_logs`
92
+ BEGIN
93
+ DELETE FROM `storage_metadata`
94
+ WHERE `source_kind` = 'requestLogs'
95
+ AND `source_id` = CAST(OLD.`id` AS TEXT)
96
+ AND OLD.`id` IS NOT NEW.`id`;
97
+ INSERT INTO `storage_metadata` (`source_kind`, `source_id`, `utc_ts`, `bytes`)
98
+ VALUES (
99
+ 'requestLogs',
100
+ CAST(NEW.`id` AS TEXT),
101
+ datetime(NEW.`timestamp`),
102
+ COALESCE(length(CAST(NEW.`path` AS BLOB)), 0)
103
+ + COALESCE(length(CAST(NEW.`method` AS BLOB)), 0)
104
+ + COALESCE(length(CAST(NEW.`request_body` AS BLOB)), 0)
105
+ + COALESCE(length(CAST(NEW.`response_body` AS BLOB)), 0)
106
+ + COALESCE(length(CAST(NEW.`request_headers` AS BLOB)), 0)
107
+ + COALESCE(length(CAST(NEW.`response_headers` AS BLOB)), 0)
108
+ + COALESCE(length(CAST(NEW.`query` AS BLOB)), 0)
109
+ + COALESCE(length(CAST(NEW.`metadata` AS BLOB)), 0)
110
+ )
111
+ ON CONFLICT (`source_kind`, `source_id`) DO UPDATE SET
112
+ `utc_ts` = excluded.`utc_ts`,
113
+ `bytes` = excluded.`bytes`;
114
+ END;
115
+ --> statement-breakpoint
116
+ CREATE TRIGGER IF NOT EXISTS `trg_storage_meta_request_logs_del`
117
+ AFTER DELETE ON `request_logs`
118
+ BEGIN
119
+ DELETE FROM `storage_metadata`
120
+ WHERE `source_kind` = 'requestLogs'
121
+ AND `source_id` = CAST(OLD.`id` AS TEXT);
122
+ END;
123
+ --> statement-breakpoint
124
+ CREATE TRIGGER IF NOT EXISTS `trg_storage_meta_tasks_ins`
125
+ AFTER INSERT ON `tasks`
126
+ BEGIN
127
+ INSERT INTO `storage_metadata` (`source_kind`, `source_id`, `utc_ts`, `bytes`)
128
+ VALUES (
129
+ 'prompts',
130
+ CAST(NEW.`id` AS TEXT),
131
+ datetime(NEW.`started_at`),
132
+ COALESCE(length(CAST(NEW.`prompt` AS BLOB)), 0)
133
+ + COALESCE(length(CAST(NEW.`rendered_prompt` AS BLOB)), 0)
134
+ + COALESCE(length(CAST(NEW.`result` AS BLOB)), 0)
135
+ )
136
+ ON CONFLICT (`source_kind`, `source_id`) DO UPDATE SET
137
+ `utc_ts` = excluded.`utc_ts`,
138
+ `bytes` = excluded.`bytes`;
139
+ INSERT INTO `storage_metadata` (`source_kind`, `source_id`, `utc_ts`, `bytes`)
140
+ VALUES (
141
+ 'tasksLedger',
142
+ CAST(NEW.`id` AS TEXT),
143
+ datetime(NEW.`started_at`),
144
+ COALESCE(length(CAST(NEW.`id` AS BLOB)), 0)
145
+ + COALESCE(length(CAST(NEW.`agent_id` AS BLOB)), 0)
146
+ + COALESCE(length(CAST(NEW.`status` AS BLOB)), 0)
147
+ + COALESCE(length(CAST(NEW.`started_at` AS BLOB)), 0)
148
+ + COALESCE(length(CAST(NEW.`input_tokens` AS TEXT)), 0)
149
+ + COALESCE(length(CAST(NEW.`output_tokens` AS TEXT)), 0)
150
+ + COALESCE(length(CAST(NEW.`cost_usd` AS TEXT)), 0)
151
+ )
152
+ ON CONFLICT (`source_kind`, `source_id`) DO UPDATE SET
153
+ `utc_ts` = excluded.`utc_ts`,
154
+ `bytes` = excluded.`bytes`;
155
+ END;
156
+ --> statement-breakpoint
157
+ CREATE TRIGGER IF NOT EXISTS `trg_storage_meta_tasks_upd`
158
+ AFTER UPDATE OF `id`, `prompt`, `rendered_prompt`, `result`, `started_at` ON `tasks`
159
+ BEGIN
160
+ DELETE FROM `storage_metadata`
161
+ WHERE `source_kind` = 'prompts'
162
+ AND `source_id` = CAST(OLD.`id` AS TEXT)
163
+ AND OLD.`id` IS NOT NEW.`id`;
164
+ INSERT INTO `storage_metadata` (`source_kind`, `source_id`, `utc_ts`, `bytes`)
165
+ VALUES (
166
+ 'prompts',
167
+ CAST(NEW.`id` AS TEXT),
168
+ datetime(NEW.`started_at`),
169
+ COALESCE(length(CAST(NEW.`prompt` AS BLOB)), 0)
170
+ + COALESCE(length(CAST(NEW.`rendered_prompt` AS BLOB)), 0)
171
+ + COALESCE(length(CAST(NEW.`result` AS BLOB)), 0)
172
+ )
173
+ ON CONFLICT (`source_kind`, `source_id`) DO UPDATE SET
174
+ `utc_ts` = excluded.`utc_ts`,
175
+ `bytes` = excluded.`bytes`;
176
+ END;
177
+ --> statement-breakpoint
178
+ CREATE TRIGGER IF NOT EXISTS `trg_storage_meta_tasks_upd_ledger`
179
+ AFTER UPDATE OF `id`, `agent_id`, `status`, `started_at`, `input_tokens`, `output_tokens`, `cost_usd` ON `tasks`
180
+ BEGIN
181
+ DELETE FROM `storage_metadata`
182
+ WHERE `source_kind` = 'tasksLedger'
183
+ AND `source_id` = CAST(OLD.`id` AS TEXT)
184
+ AND OLD.`id` IS NOT NEW.`id`;
185
+ INSERT INTO `storage_metadata` (`source_kind`, `source_id`, `utc_ts`, `bytes`)
186
+ VALUES (
187
+ 'tasksLedger',
188
+ CAST(NEW.`id` AS TEXT),
189
+ datetime(NEW.`started_at`),
190
+ COALESCE(length(CAST(NEW.`id` AS BLOB)), 0)
191
+ + COALESCE(length(CAST(NEW.`agent_id` AS BLOB)), 0)
192
+ + COALESCE(length(CAST(NEW.`status` AS BLOB)), 0)
193
+ + COALESCE(length(CAST(NEW.`started_at` AS BLOB)), 0)
194
+ + COALESCE(length(CAST(NEW.`input_tokens` AS TEXT)), 0)
195
+ + COALESCE(length(CAST(NEW.`output_tokens` AS TEXT)), 0)
196
+ + COALESCE(length(CAST(NEW.`cost_usd` AS TEXT)), 0)
197
+ )
198
+ ON CONFLICT (`source_kind`, `source_id`) DO UPDATE SET
199
+ `utc_ts` = excluded.`utc_ts`,
200
+ `bytes` = excluded.`bytes`;
201
+ END;
202
+ --> statement-breakpoint
203
+ CREATE TRIGGER IF NOT EXISTS `trg_storage_meta_tasks_del`
204
+ AFTER DELETE ON `tasks`
205
+ BEGIN
206
+ DELETE FROM `storage_metadata`
207
+ WHERE `source_kind` = 'prompts'
208
+ AND `source_id` = CAST(OLD.`id` AS TEXT);
209
+ DELETE FROM `storage_metadata`
210
+ WHERE `source_kind` = 'tasksLedger'
211
+ AND `source_id` = CAST(OLD.`id` AS TEXT);
212
+ END;
213
+ --> statement-breakpoint
214
+ CREATE TRIGGER IF NOT EXISTS `trg_storage_meta_threads_ins`
215
+ AFTER INSERT ON `threads`
216
+ BEGIN
217
+ INSERT INTO `storage_metadata` (`source_kind`, `source_id`, `utc_ts`, `bytes`)
218
+ VALUES (
219
+ 'threadsLedger',
220
+ CAST(NEW.`id` AS TEXT),
221
+ datetime(COALESCE(NEW.`updated_at`, NEW.`created_at`)),
222
+ COALESCE(length(CAST(NEW.`id` AS BLOB)), 0)
223
+ + COALESCE(length(CAST(NEW.`workspace_id` AS BLOB)), 0)
224
+ + COALESCE(length(CAST(NEW.`platform` AS BLOB)), 0)
225
+ + COALESCE(length(CAST(NEW.`created_at` AS BLOB)), 0)
226
+ + COALESCE(length(CAST(NEW.`updated_at` AS BLOB)), 0)
227
+ )
228
+ ON CONFLICT (`source_kind`, `source_id`) DO UPDATE SET
229
+ `utc_ts` = excluded.`utc_ts`,
230
+ `bytes` = excluded.`bytes`;
231
+ END;
232
+ --> statement-breakpoint
233
+ CREATE TRIGGER IF NOT EXISTS `trg_storage_meta_threads_upd`
234
+ AFTER UPDATE OF `id`, `workspace_id`, `platform`, `created_at`, `updated_at` ON `threads`
235
+ BEGIN
236
+ DELETE FROM `storage_metadata`
237
+ WHERE `source_kind` = 'threadsLedger'
238
+ AND `source_id` = CAST(OLD.`id` AS TEXT)
239
+ AND OLD.`id` IS NOT NEW.`id`;
240
+ INSERT INTO `storage_metadata` (`source_kind`, `source_id`, `utc_ts`, `bytes`)
241
+ VALUES (
242
+ 'threadsLedger',
243
+ CAST(NEW.`id` AS TEXT),
244
+ datetime(COALESCE(NEW.`updated_at`, NEW.`created_at`)),
245
+ COALESCE(length(CAST(NEW.`id` AS BLOB)), 0)
246
+ + COALESCE(length(CAST(NEW.`workspace_id` AS BLOB)), 0)
247
+ + COALESCE(length(CAST(NEW.`platform` AS BLOB)), 0)
248
+ + COALESCE(length(CAST(NEW.`created_at` AS BLOB)), 0)
249
+ + COALESCE(length(CAST(NEW.`updated_at` AS BLOB)), 0)
250
+ )
251
+ ON CONFLICT (`source_kind`, `source_id`) DO UPDATE SET
252
+ `utc_ts` = excluded.`utc_ts`,
253
+ `bytes` = excluded.`bytes`;
254
+ END;
255
+ --> statement-breakpoint
256
+ CREATE TRIGGER IF NOT EXISTS `trg_storage_meta_threads_del`
257
+ AFTER DELETE ON `threads`
258
+ BEGIN
259
+ DELETE FROM `storage_metadata`
260
+ WHERE `source_kind` = 'threadsLedger'
261
+ AND `source_id` = CAST(OLD.`id` AS TEXT);
262
+ END;
@@ -0,0 +1,8 @@
1
+ ALTER TABLE `tasks` ADD `heartbeat_at` text;
2
+ --> statement-breakpoint
3
+ ALTER TABLE `tasks` ADD `stop_requested_at` text;
4
+ --> statement-breakpoint
5
+ ALTER TABLE `tasks` ADD `stop_requested_epoch` integer;
6
+ --> statement-breakpoint
7
+ CREATE INDEX IF NOT EXISTS `idx_tasks_status_heartbeat`
8
+ ON `tasks` (`status`, `heartbeat_at`);
@@ -0,0 +1,2 @@
1
+ ALTER TABLE `ui_instances` ADD `app_id` text CONSTRAINT "ui_instances_app_id_ck" CHECK("ui_instances"."app_id" IS NULL OR length("ui_instances"."app_id") BETWEEN 1 AND 128);--> statement-breakpoint
2
+ CREATE UNIQUE INDEX IF NOT EXISTS `ui_instances_workspace_thread_app_uq` ON `ui_instances` (`workspace_id`,`thread_id`,`app_id`);
@@ -0,0 +1,47 @@
1
+ PRAGMA foreign_keys=OFF;--> statement-breakpoint
2
+ CREATE TABLE `__new_ui_action_receipts` (
3
+ `id` text PRIMARY KEY NOT NULL,
4
+ `instance_id` text NOT NULL,
5
+ `request_id` text NOT NULL,
6
+ `action_id` text NOT NULL,
7
+ `actor_json` text NOT NULL,
8
+ `source` text NOT NULL,
9
+ `expected_revision` integer NOT NULL,
10
+ `before_revision` integer NOT NULL,
11
+ `after_revision` integer,
12
+ `status` text NOT NULL,
13
+ `outcome` text,
14
+ `input_json` text NOT NULL,
15
+ `result_json` text,
16
+ `error_code` text,
17
+ `requested_at` integer NOT NULL,
18
+ `settled_at` integer,
19
+ CONSTRAINT "ui_action_receipts_id_ck" CHECK(length("__new_ui_action_receipts"."id") BETWEEN 5 AND 128),
20
+ CONSTRAINT "ui_action_receipts_instance_id_ck" CHECK(length("__new_ui_action_receipts"."instance_id") BETWEEN 1 AND 128),
21
+ CONSTRAINT "ui_action_receipts_request_id_ck" CHECK(length("__new_ui_action_receipts"."request_id") BETWEEN 1 AND 128),
22
+ CONSTRAINT "ui_action_receipts_action_id_ck" CHECK(length("__new_ui_action_receipts"."action_id") BETWEEN 1 AND 128),
23
+ CONSTRAINT "ui_action_receipts_actor_json_ck" CHECK(json_valid("__new_ui_action_receipts"."actor_json") AND json_type("__new_ui_action_receipts"."actor_json") = 'object'),
24
+ CONSTRAINT "ui_action_receipts_source_ck" CHECK("__new_ui_action_receipts"."source" IN ('ui_host', 'cli', 'system', 'mcp')),
25
+ CONSTRAINT "ui_action_receipts_expected_revision_ck" CHECK("__new_ui_action_receipts"."expected_revision" >= 0),
26
+ CONSTRAINT "ui_action_receipts_before_revision_ck" CHECK("__new_ui_action_receipts"."before_revision" >= 0),
27
+ CONSTRAINT "ui_action_receipts_after_revision_ck" CHECK("__new_ui_action_receipts"."after_revision" IS NULL OR "__new_ui_action_receipts"."after_revision" >= 0),
28
+ CONSTRAINT "ui_action_receipts_status_ck" CHECK("__new_ui_action_receipts"."status" IN ('requested', 'settled')),
29
+ CONSTRAINT "ui_action_receipts_outcome_ck" CHECK("__new_ui_action_receipts"."outcome" IS NULL OR "__new_ui_action_receipts"."outcome" IN ('succeeded', 'rejected', 'failed', 'conflicted', 'expired')),
30
+ CONSTRAINT "ui_action_receipts_input_json_ck" CHECK(json_valid("__new_ui_action_receipts"."input_json") AND json_type("__new_ui_action_receipts"."input_json") = 'object'),
31
+ CONSTRAINT "ui_action_receipts_result_json_ck" CHECK("__new_ui_action_receipts"."result_json" IS NULL OR (json_valid("__new_ui_action_receipts"."result_json") AND json_type("__new_ui_action_receipts"."result_json") = 'object')),
32
+ CONSTRAINT "ui_action_receipts_requested_at_ck" CHECK("__new_ui_action_receipts"."requested_at" >= 0),
33
+ CONSTRAINT "ui_action_receipts_settled_at_ck" CHECK("__new_ui_action_receipts"."settled_at" IS NULL OR "__new_ui_action_receipts"."settled_at" >= "__new_ui_action_receipts"."requested_at"),
34
+ CONSTRAINT "ui_action_receipts_status_transition_ck" CHECK((
35
+ ("__new_ui_action_receipts"."status" = 'requested' AND "__new_ui_action_receipts"."after_revision" IS NULL AND "__new_ui_action_receipts"."outcome" IS NULL AND "__new_ui_action_receipts"."settled_at" IS NULL)
36
+ OR
37
+ ("__new_ui_action_receipts"."status" = 'settled' AND "__new_ui_action_receipts"."after_revision" IS NOT NULL AND "__new_ui_action_receipts"."outcome" IS NOT NULL AND "__new_ui_action_receipts"."settled_at" IS NOT NULL)
38
+ ))
39
+ );
40
+ --> statement-breakpoint
41
+ INSERT INTO `__new_ui_action_receipts`("id", "instance_id", "request_id", "action_id", "actor_json", "source", "expected_revision", "before_revision", "after_revision", "status", "outcome", "input_json", "result_json", "error_code", "requested_at", "settled_at") SELECT "id", "instance_id", "request_id", "action_id", "actor_json", "source", "expected_revision", "before_revision", "after_revision", "status", "outcome", "input_json", "result_json", "error_code", "requested_at", "settled_at" FROM `ui_action_receipts`;--> statement-breakpoint
42
+ DROP TABLE `ui_action_receipts`;--> statement-breakpoint
43
+ ALTER TABLE `__new_ui_action_receipts` RENAME TO `ui_action_receipts`;--> statement-breakpoint
44
+ PRAGMA foreign_keys=ON;--> statement-breakpoint
45
+ CREATE UNIQUE INDEX `ui_action_receipts_instance_request_uq` ON `ui_action_receipts` (`instance_id`,`request_id`);--> statement-breakpoint
46
+ CREATE INDEX `ui_action_receipts_instance_id_idx` ON `ui_action_receipts` (`instance_id`);--> statement-breakpoint
47
+ CREATE INDEX `ui_action_receipts_requested_at_idx` ON `ui_action_receipts` (`requested_at`);
@@ -0,0 +1,5 @@
1
+ UPDATE `tasks`
2
+ SET `stop_requested_at` = NULL,
3
+ `stop_requested_epoch` = NULL
4
+ WHERE `status` IN ('success', 'failed')
5
+ AND (`stop_requested_at` IS NOT NULL OR `stop_requested_epoch` IS NOT NULL);
@@ -0,0 +1,2 @@
1
+ DROP INDEX IF EXISTS `ui_instances_workspace_thread_app_uq`;--> statement-breakpoint
2
+ CREATE UNIQUE INDEX IF NOT EXISTS `ui_instances_workspace_thread_app_uq` ON `ui_instances` (`workspace_id`,`thread_id`,`app_id`) WHERE "status" = 'active';
@@ -0,0 +1 @@
1
+ ALTER TABLE `tasks` ADD `cwd` text;
@@ -0,0 +1,6 @@
1
+ ALTER TABLE `tasks` ADD `actor_kind` text;--> statement-breakpoint
2
+ ALTER TABLE `tasks` ADD `actor_id` text;--> statement-breakpoint
3
+ ALTER TABLE `threads` ADD `created_by_kind` text;--> statement-breakpoint
4
+ ALTER TABLE `threads` ADD `created_by_id` text;--> statement-breakpoint
5
+ ALTER TABLE `threads` ADD `created_by_task_id` text;--> statement-breakpoint
6
+ CREATE INDEX IF NOT EXISTS `idx_threads_workspace_created_by_kind_updated_at` ON `threads` (`workspace_id`,`created_by_kind`,`updated_at`);