@sixb/sqlite 0.1.1 → 0.1.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 (108) hide show
  1. package/README.md +18 -13
  2. package/dist/action-run-storage.d.ts +5 -2
  3. package/dist/action-run-storage.d.ts.map +1 -1
  4. package/dist/agents/agent-storage.d.ts +4 -2
  5. package/dist/agents/agent-storage.d.ts.map +1 -1
  6. package/dist/agents/rows.d.ts +3 -10
  7. package/dist/agents/rows.d.ts.map +1 -1
  8. package/dist/agents/runs.d.ts +3 -2
  9. package/dist/agents/runs.d.ts.map +1 -1
  10. package/dist/ai-usage-storage.d.ts +22 -0
  11. package/dist/ai-usage-storage.d.ts.map +1 -0
  12. package/dist/auth-storage/service-accounts.d.ts.map +1 -1
  13. package/dist/auth-storage/shared.d.ts +1 -10
  14. package/dist/auth-storage/shared.d.ts.map +1 -1
  15. package/dist/connector-connection-storage.d.ts +9 -0
  16. package/dist/connector-connection-storage.d.ts.map +1 -0
  17. package/dist/execution-storage.d.ts +14 -0
  18. package/dist/execution-storage.d.ts.map +1 -0
  19. package/dist/index.d.ts +13 -9
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +3862 -1042
  22. package/dist/index.js.map +30 -27
  23. package/dist/latest-run-query.d.ts.map +1 -1
  24. package/dist/migrations.d.ts +0 -1
  25. package/dist/migrations.d.ts.map +1 -1
  26. package/dist/ontology-storage/materialization-session.d.ts +50 -8
  27. package/dist/ontology-storage/materialization-session.d.ts.map +1 -1
  28. package/dist/ontology-storage/materialization-state.d.ts +4 -5
  29. package/dist/ontology-storage/materialization-state.d.ts.map +1 -1
  30. package/dist/ontology-storage/materialization-writer.d.ts.map +1 -1
  31. package/dist/ontology-storage/materializations.d.ts +0 -2
  32. package/dist/ontology-storage/materializations.d.ts.map +1 -1
  33. package/dist/ontology-storage/outbox.d.ts.map +1 -1
  34. package/dist/ontology-storage/shared.d.ts +3 -3
  35. package/dist/ontology-storage/shared.d.ts.map +1 -1
  36. package/dist/ontology-storage/sources.d.ts.map +1 -1
  37. package/dist/pipeline-run-storage.d.ts +7 -2
  38. package/dist/pipeline-run-storage.d.ts.map +1 -1
  39. package/dist/projection-run-storage.d.ts +9 -2
  40. package/dist/projection-run-storage.d.ts.map +1 -1
  41. package/dist/run-list-query.d.ts +1 -1
  42. package/dist/run-list-query.d.ts.map +1 -1
  43. package/dist/sync-run-storage.d.ts +7 -2
  44. package/dist/sync-run-storage.d.ts.map +1 -1
  45. package/dist/testing.d.ts +6 -0
  46. package/dist/testing.d.ts.map +1 -0
  47. package/dist/transactions.d.ts +3 -0
  48. package/dist/transactions.d.ts.map +1 -1
  49. package/dist/webhook-run-storage.d.ts +9 -2
  50. package/dist/webhook-run-storage.d.ts.map +1 -1
  51. package/dist/workflow-run-storage.d.ts +7 -3
  52. package/dist/workflow-run-storage.d.ts.map +1 -1
  53. package/package.json +3 -3
  54. package/src/action-run-storage.ts +51 -74
  55. package/src/agents/agent-storage.ts +5 -3
  56. package/src/agents/rows.ts +8 -40
  57. package/src/agents/runs.ts +27 -21
  58. package/src/ai-usage-storage.ts +324 -0
  59. package/src/auth-storage/service-accounts.ts +14 -21
  60. package/src/auth-storage/shared.ts +0 -22
  61. package/src/connector-connection-storage.ts +784 -0
  62. package/src/execution-storage.ts +158 -0
  63. package/src/index.ts +63 -22
  64. package/src/latest-run-query.ts +7 -1
  65. package/src/migrations/004-executions.sql +142 -0
  66. package/src/migrations/005-workflow-executions.sql +7 -0
  67. package/src/migrations/006-narrow-ontology-source-root-index.sql +4 -0
  68. package/src/migrations/007-split-overrides.sql +154 -0
  69. package/src/migrations/008-action-executions.sql +4 -0
  70. package/src/migrations/009-agent-executions.sql +115 -0
  71. package/src/migrations/010-ai-usage-accounting-foundation.sql +74 -0
  72. package/src/migrations/011-sync-failure-record.sql +22 -0
  73. package/src/migrations/012-pipeline-failure-record.sql +45 -0
  74. package/src/migrations/013-workflow-failure-record.sql +45 -0
  75. package/src/migrations/014-agent-failure-record.sql +59 -0
  76. package/src/migrations/015-projection-failure-record.sql +20 -0
  77. package/src/migrations/016-webhook-run-failure-record.sql +19 -0
  78. package/src/migrations/017-action-failure-record.sql +65 -0
  79. package/src/migrations/018-ontology-outbox-failure-record.sql +80 -0
  80. package/src/migrations/019-webhook-delivery-failure-record.sql +62 -0
  81. package/src/migrations/020-drop-run-usage-projections.sql +7 -0
  82. package/src/migrations/021-sync-pipeline-executions.sql +101 -0
  83. package/src/migrations/022-projection-executions.sql +244 -0
  84. package/src/migrations/023-webhook-executions.sql +51 -0
  85. package/src/migrations/024-ontology-commit-executions.sql +58 -0
  86. package/src/migrations/025-connector-connections.sql +257 -0
  87. package/src/migrations.ts +119 -4
  88. package/src/ontology-storage/materialization-session.ts +317 -143
  89. package/src/ontology-storage/materialization-state.ts +321 -112
  90. package/src/ontology-storage/materialization-writer.ts +142 -67
  91. package/src/ontology-storage/materializations.ts +67 -141
  92. package/src/ontology-storage/outbox.ts +10 -3
  93. package/src/ontology-storage/shared.ts +10 -4
  94. package/src/ontology-storage/sources.ts +4 -1
  95. package/src/pipeline-run-storage.ts +128 -43
  96. package/src/projection-run-storage.ts +209 -97
  97. package/src/run-list-query.ts +9 -4
  98. package/src/sync-run-storage.ts +118 -32
  99. package/src/testing.ts +20 -0
  100. package/src/transactions.ts +10 -3
  101. package/src/webhook-run-storage.ts +118 -74
  102. package/src/workflow-run-storage.ts +117 -131
  103. package/dist/validation.d.ts +0 -5
  104. package/dist/validation.d.ts.map +0 -1
  105. package/dist/webhook-delivery-storage.d.ts +0 -27
  106. package/dist/webhook-delivery-storage.d.ts.map +0 -1
  107. package/src/validation.ts +0 -30
  108. package/src/webhook-delivery-storage.ts +0 -272
@@ -0,0 +1,154 @@
1
+ CREATE TABLE ontology_object_overrides (
2
+ project_id TEXT NOT NULL,
3
+ object_type_id TEXT NOT NULL,
4
+ primary_id TEXT NOT NULL,
5
+ value TEXT NOT NULL CHECK (json_valid(value) AND json_type(value) = 'object'),
6
+ last_commit_id TEXT NOT NULL,
7
+ updated_at TEXT NOT NULL,
8
+ PRIMARY KEY (project_id, object_type_id, primary_id),
9
+ CHECK (COALESCE(json_extract(value, '$.kind') IN ('create', 'patch', 'delete'), 0))
10
+ );
11
+
12
+ CREATE TABLE ontology_link_overrides (
13
+ project_id TEXT NOT NULL,
14
+ identity_kind TEXT NOT NULL CHECK (identity_kind IN ('edge', 'slot')),
15
+ identity_key TEXT NOT NULL CHECK (json_valid(identity_key)),
16
+ source_type_id TEXT NOT NULL,
17
+ source_primary_id TEXT NOT NULL,
18
+ link_id TEXT NOT NULL,
19
+ target_type_id TEXT NOT NULL,
20
+ target_primary_id TEXT NOT NULL,
21
+ value TEXT NOT NULL CHECK (json_valid(value) AND json_type(value) = 'object'),
22
+ last_commit_id TEXT NOT NULL,
23
+ updated_at TEXT NOT NULL,
24
+ PRIMARY KEY (project_id, identity_kind, identity_key),
25
+ CHECK (
26
+ identity_key = CASE identity_kind
27
+ WHEN 'edge' THEN json_array(
28
+ source_type_id, source_primary_id, link_id, target_type_id, target_primary_id
29
+ )
30
+ WHEN 'slot' THEN json_array(source_type_id, source_primary_id, link_id)
31
+ END
32
+ ),
33
+ CHECK (
34
+ (identity_kind = 'edge'
35
+ AND COALESCE(json_extract(value, '$.kind') IN ('upsert', 'delete'), 0))
36
+ OR
37
+ (identity_kind = 'slot'
38
+ AND COALESCE(json_extract(value, '$.kind') IN ('set', 'clear', 'legacy-conflict'), 0)
39
+ AND (
40
+ json_extract(value, '$.kind') = 'legacy-conflict'
41
+ OR (
42
+ target_type_id = json_extract(value, '$.target.objectTypeId')
43
+ AND target_primary_id = json_extract(value, '$.target.primaryId')
44
+ )
45
+ ))
46
+ )
47
+ );
48
+
49
+ CREATE INDEX idx_ontology_link_overrides_source
50
+ ON ontology_link_overrides(
51
+ project_id, identity_kind, source_type_id, source_primary_id, link_id,
52
+ target_type_id, target_primary_id
53
+ );
54
+
55
+ CREATE INDEX idx_ontology_link_overrides_target
56
+ ON ontology_link_overrides(project_id, target_type_id, target_primary_id);
57
+
58
+ INSERT INTO ontology_object_overrides (
59
+ project_id, object_type_id, primary_id, value, last_commit_id, updated_at
60
+ )
61
+ SELECT project_id, object_type_id, primary_id, value, last_commit_id, updated_at
62
+ FROM ontology_overrides
63
+ WHERE entity_kind = 'object';
64
+
65
+ INSERT INTO ontology_link_overrides (
66
+ project_id, identity_kind, identity_key,
67
+ source_type_id, source_primary_id, link_id, target_type_id, target_primary_id,
68
+ value, last_commit_id, updated_at
69
+ )
70
+ SELECT project_id, 'edge', entity_key,
71
+ source_type_id, source_primary_id, link_id, target_type_id, target_primary_id,
72
+ value, last_commit_id, updated_at
73
+ FROM ontology_overrides
74
+ WHERE entity_kind = 'link';
75
+
76
+ -- Storage migrations do not have access to the ontology cardinality. Derive a slot candidate for
77
+ -- every legacy link scope; the runtime selects edge or slot authority from the registered ontology.
78
+ -- A single upsert is an unambiguous set and a delete-only scope is an unambiguous clear. Multiple
79
+ -- upserts are preserved as an explicit conflict instead of selecting a target arbitrarily.
80
+ WITH scopes AS (
81
+ SELECT project_id, source_type_id, source_primary_id, link_id,
82
+ SUM(CASE WHEN json_extract(value, '$.kind') = 'upsert' THEN 1 ELSE 0 END) AS upsert_count
83
+ FROM ontology_overrides
84
+ WHERE entity_kind = 'link'
85
+ GROUP BY project_id, source_type_id, source_primary_id, link_id
86
+ ), selected AS (
87
+ SELECT scopes.*,
88
+ COALESCE(
89
+ (
90
+ SELECT entity_key FROM ontology_overrides AS candidate
91
+ WHERE candidate.project_id = scopes.project_id
92
+ AND candidate.entity_kind = 'link'
93
+ AND candidate.source_type_id = scopes.source_type_id
94
+ AND candidate.source_primary_id = scopes.source_primary_id
95
+ AND candidate.link_id = scopes.link_id
96
+ AND json_extract(candidate.value, '$.kind') = 'upsert'
97
+ ORDER BY candidate.updated_at DESC, candidate.entity_sort_key DESC
98
+ LIMIT 1
99
+ ),
100
+ (
101
+ SELECT entity_key FROM ontology_overrides AS candidate
102
+ WHERE candidate.project_id = scopes.project_id
103
+ AND candidate.entity_kind = 'link'
104
+ AND candidate.source_type_id = scopes.source_type_id
105
+ AND candidate.source_primary_id = scopes.source_primary_id
106
+ AND candidate.link_id = scopes.link_id
107
+ ORDER BY candidate.updated_at DESC, candidate.entity_sort_key DESC
108
+ LIMIT 1
109
+ )
110
+ ) AS selected_key
111
+ FROM scopes
112
+ )
113
+ INSERT INTO ontology_link_overrides (
114
+ project_id, identity_kind, identity_key,
115
+ source_type_id, source_primary_id, link_id, target_type_id, target_primary_id,
116
+ value, last_commit_id, updated_at
117
+ )
118
+ SELECT selected.project_id, 'slot',
119
+ json_array(selected.source_type_id, selected.source_primary_id, selected.link_id),
120
+ selected.source_type_id, selected.source_primary_id, selected.link_id,
121
+ overrides.target_type_id, overrides.target_primary_id,
122
+ CASE
123
+ WHEN selected.upsert_count > 1 THEN json_object('kind', 'legacy-conflict')
124
+ WHEN selected.upsert_count = 1 THEN json_patch(
125
+ json_object(
126
+ 'kind', 'set',
127
+ 'target', json_object(
128
+ 'objectTypeId', overrides.target_type_id,
129
+ 'primaryId', overrides.target_primary_id
130
+ )
131
+ ),
132
+ CASE
133
+ WHEN json_type(overrides.value, '$.properties') IS NOT NULL
134
+ THEN json_object('properties', json_extract(overrides.value, '$.properties'))
135
+ ELSE json('{}')
136
+ END
137
+ )
138
+ ELSE json_object(
139
+ 'kind', 'clear',
140
+ 'target', json_object(
141
+ 'objectTypeId', overrides.target_type_id,
142
+ 'primaryId', overrides.target_primary_id
143
+ )
144
+ )
145
+ END,
146
+ overrides.last_commit_id,
147
+ overrides.updated_at
148
+ FROM selected
149
+ JOIN ontology_overrides AS overrides
150
+ ON overrides.project_id = selected.project_id
151
+ AND overrides.entity_kind = 'link'
152
+ AND overrides.entity_key = selected.selected_key;
153
+
154
+ DROP TABLE ontology_overrides;
@@ -0,0 +1,4 @@
1
+ ALTER TABLE action_runs ADD COLUMN execution_id TEXT NOT NULL;
2
+
3
+ CREATE UNIQUE INDEX idx_action_runs_project_execution
4
+ ON action_runs(project_id, execution_id);
@@ -0,0 +1,115 @@
1
+ -- Existing rows cannot be assigned an honest authority retroactively. These NOT NULL additions
2
+ -- intentionally fail on non-empty legacy tables instead of inventing execution provenance.
3
+ ALTER TABLE agent_runs ADD COLUMN execution_id TEXT NOT NULL;
4
+ ALTER TABLE workflow_agent_node_runs ADD COLUMN execution_id TEXT NOT NULL;
5
+
6
+ CREATE TABLE agent_runs_v2 (
7
+ project_id TEXT NOT NULL,
8
+ id TEXT NOT NULL,
9
+ execution_id TEXT NOT NULL,
10
+ thread_id TEXT NOT NULL,
11
+ agent_id TEXT NOT NULL,
12
+ trigger_message_id TEXT NOT NULL,
13
+ status TEXT NOT NULL CHECK (
14
+ status IN ('queued', 'running', 'succeeded', 'failed', 'cancelled')
15
+ ),
16
+ model_id TEXT,
17
+ finish_reason TEXT,
18
+ usage_input_tokens INTEGER CHECK (usage_input_tokens IS NULL OR usage_input_tokens >= 0),
19
+ usage_output_tokens INTEGER CHECK (usage_output_tokens IS NULL OR usage_output_tokens >= 0),
20
+ usage_total_tokens INTEGER CHECK (usage_total_tokens IS NULL OR usage_total_tokens >= 0),
21
+ usage_reasoning_tokens INTEGER CHECK (
22
+ usage_reasoning_tokens IS NULL OR usage_reasoning_tokens >= 0
23
+ ),
24
+ usage_cached_input_tokens INTEGER CHECK (
25
+ usage_cached_input_tokens IS NULL OR usage_cached_input_tokens >= 0
26
+ ),
27
+ error TEXT,
28
+ diagnostics TEXT,
29
+ attempt INTEGER NOT NULL DEFAULT 0 CHECK (attempt >= 0),
30
+ execution_token TEXT,
31
+ execution_queue_lease_expires_at TEXT,
32
+ created_at TEXT NOT NULL,
33
+ started_at TEXT,
34
+ completed_at TEXT,
35
+ PRIMARY KEY (project_id, id),
36
+ UNIQUE (project_id, execution_id),
37
+ FOREIGN KEY (project_id, execution_id)
38
+ REFERENCES executions (project_id, id)
39
+ ON DELETE RESTRICT,
40
+ CHECK ((execution_token IS NULL) = (execution_queue_lease_expires_at IS NULL))
41
+ );
42
+
43
+ INSERT INTO agent_runs_v2 (
44
+ project_id, id, execution_id, thread_id, agent_id, trigger_message_id, status, model_id,
45
+ finish_reason, usage_input_tokens, usage_output_tokens, usage_total_tokens,
46
+ usage_reasoning_tokens, usage_cached_input_tokens, error, diagnostics, attempt, execution_token,
47
+ execution_queue_lease_expires_at, created_at, started_at, completed_at
48
+ )
49
+ SELECT
50
+ project_id, id, execution_id, thread_id, agent_id, trigger_message_id, status, model_id,
51
+ finish_reason, usage_input_tokens, usage_output_tokens, usage_total_tokens,
52
+ usage_reasoning_tokens, usage_cached_input_tokens, error, diagnostics, attempt, execution_token,
53
+ execution_queue_lease_expires_at, created_at, started_at, completed_at
54
+ FROM agent_runs;
55
+
56
+ DROP TABLE agent_runs;
57
+ ALTER TABLE agent_runs_v2 RENAME TO agent_runs;
58
+
59
+ CREATE INDEX idx_agent_runs_project_started
60
+ ON agent_runs(project_id, COALESCE(started_at, created_at) DESC);
61
+ CREATE INDEX idx_agent_runs_project_thread_started
62
+ ON agent_runs(project_id, thread_id, COALESCE(started_at, created_at) DESC);
63
+ CREATE INDEX idx_agent_runs_project_agent_started
64
+ ON agent_runs(project_id, agent_id, COALESCE(started_at, created_at) DESC);
65
+ CREATE INDEX idx_agent_runs_project_status_started
66
+ ON agent_runs(project_id, status, COALESCE(started_at, created_at) DESC);
67
+
68
+ CREATE TABLE workflow_agent_node_runs_v2 (
69
+ project_id TEXT NOT NULL,
70
+ node_run_id TEXT NOT NULL,
71
+ execution_id TEXT NOT NULL,
72
+ agent_id TEXT NOT NULL,
73
+ status TEXT NOT NULL CHECK (status IN ('queued', 'running', 'succeeded', 'failed', 'cancelled')),
74
+ prompt TEXT NOT NULL,
75
+ model_id TEXT,
76
+ finish_reason TEXT,
77
+ usage TEXT,
78
+ trace TEXT,
79
+ diagnostics TEXT,
80
+ error TEXT,
81
+ attempt INTEGER NOT NULL DEFAULT 0 CHECK (attempt >= 0),
82
+ execution_token TEXT,
83
+ execution_queue_lease_expires_at TEXT,
84
+ created_at TEXT NOT NULL,
85
+ started_at TEXT,
86
+ completed_at TEXT,
87
+ PRIMARY KEY (project_id, node_run_id),
88
+ UNIQUE (project_id, execution_id),
89
+ FOREIGN KEY (project_id, node_run_id)
90
+ REFERENCES workflow_node_runs (project_id, id)
91
+ ON DELETE CASCADE,
92
+ FOREIGN KEY (project_id, execution_id)
93
+ REFERENCES executions (project_id, id)
94
+ ON DELETE RESTRICT,
95
+ CHECK ((execution_token IS NULL) = (execution_queue_lease_expires_at IS NULL))
96
+ );
97
+
98
+ INSERT INTO workflow_agent_node_runs_v2 (
99
+ project_id, node_run_id, execution_id, agent_id, status, prompt, model_id, finish_reason, usage,
100
+ trace, diagnostics, error, attempt, execution_token, execution_queue_lease_expires_at, created_at,
101
+ started_at, completed_at
102
+ )
103
+ SELECT
104
+ project_id, node_run_id, execution_id, agent_id, status, prompt, model_id, finish_reason, usage,
105
+ trace, diagnostics, error, attempt, execution_token, execution_queue_lease_expires_at, created_at,
106
+ started_at, completed_at
107
+ FROM workflow_agent_node_runs;
108
+
109
+ DROP TABLE workflow_agent_node_runs;
110
+ ALTER TABLE workflow_agent_node_runs_v2 RENAME TO workflow_agent_node_runs;
111
+
112
+ CREATE INDEX idx_workflow_agent_node_runs_project_agent_created
113
+ ON workflow_agent_node_runs(project_id, agent_id, created_at DESC);
114
+ CREATE INDEX idx_workflow_agent_node_runs_project_status_created
115
+ ON workflow_agent_node_runs(project_id, status, created_at DESC);
@@ -0,0 +1,74 @@
1
+ ALTER TABLE agent_runs
2
+ ADD COLUMN requester_group_ids TEXT NOT NULL DEFAULT '[]'
3
+ CHECK (json_valid(requester_group_ids) AND json_type(requester_group_ids) = 'array');
4
+
5
+ ALTER TABLE workflow_runs
6
+ ADD COLUMN requester_group_ids TEXT NOT NULL DEFAULT '[]'
7
+ CHECK (json_valid(requester_group_ids) AND json_type(requester_group_ids) = 'array');
8
+
9
+ CREATE TABLE ai_model_call_usage (
10
+ project_id TEXT NOT NULL CHECK (length(trim(project_id)) > 0),
11
+ id TEXT NOT NULL CHECK (length(trim(id)) > 0),
12
+ execution_id TEXT NOT NULL CHECK (length(trim(execution_id)) > 0),
13
+ attempt INTEGER NOT NULL CHECK (attempt >= 1),
14
+ call_id TEXT NOT NULL CHECK (length(trim(call_id)) > 0),
15
+ provider_id TEXT NOT NULL CHECK (length(trim(provider_id)) > 0),
16
+ requested_model_id TEXT NOT NULL CHECK (length(trim(requested_model_id)) > 0),
17
+ response_model_id TEXT CHECK (
18
+ response_model_id IS NULL OR length(trim(response_model_id)) > 0
19
+ ),
20
+ response_id TEXT NOT NULL CHECK (length(trim(response_id)) > 0),
21
+ input_tokens INTEGER CHECK (input_tokens IS NULL OR input_tokens >= 0),
22
+ output_tokens INTEGER CHECK (output_tokens IS NULL OR output_tokens >= 0),
23
+ total_tokens INTEGER CHECK (total_tokens IS NULL OR total_tokens >= 0),
24
+ uncached_input_tokens INTEGER CHECK (
25
+ uncached_input_tokens IS NULL OR uncached_input_tokens >= 0
26
+ ),
27
+ cache_read_input_tokens INTEGER CHECK (
28
+ cache_read_input_tokens IS NULL OR cache_read_input_tokens >= 0
29
+ ),
30
+ cache_write_input_tokens INTEGER CHECK (
31
+ cache_write_input_tokens IS NULL OR cache_write_input_tokens >= 0
32
+ ),
33
+ text_output_tokens INTEGER CHECK (
34
+ text_output_tokens IS NULL OR text_output_tokens >= 0
35
+ ),
36
+ reasoning_output_tokens INTEGER CHECK (
37
+ reasoning_output_tokens IS NULL OR reasoning_output_tokens >= 0
38
+ ),
39
+ reporting_status TEXT NOT NULL CHECK (
40
+ reporting_status IN ('complete', 'partial', 'unavailable')
41
+ ),
42
+ raw_usage TEXT CHECK (
43
+ raw_usage IS NULL OR (json_valid(raw_usage) AND json_type(raw_usage) = 'object')
44
+ ),
45
+ occurred_at TEXT NOT NULL,
46
+ recorded_at TEXT NOT NULL,
47
+ PRIMARY KEY (project_id, id),
48
+ FOREIGN KEY (project_id, execution_id)
49
+ REFERENCES executions(project_id, id)
50
+ ON DELETE RESTRICT
51
+ );
52
+
53
+ CREATE UNIQUE INDEX idx_ai_model_call_usage_idempotency
54
+ ON ai_model_call_usage (project_id, execution_id, attempt, call_id, response_id);
55
+ CREATE INDEX idx_ai_model_call_usage_execution
56
+ ON ai_model_call_usage (project_id, execution_id, occurred_at, id);
57
+ CREATE INDEX idx_ai_model_call_usage_project_time
58
+ ON ai_model_call_usage (project_id, occurred_at, id);
59
+ CREATE INDEX idx_ai_model_call_usage_provider_response
60
+ ON ai_model_call_usage (project_id, provider_id, response_id);
61
+
62
+ CREATE TABLE ai_model_call_usage_groups (
63
+ project_id TEXT NOT NULL,
64
+ usage_record_id TEXT NOT NULL,
65
+ group_id TEXT NOT NULL,
66
+ occurred_at TEXT NOT NULL,
67
+ PRIMARY KEY (project_id, usage_record_id, group_id),
68
+ FOREIGN KEY (project_id, usage_record_id)
69
+ REFERENCES ai_model_call_usage(project_id, id)
70
+ ON DELETE CASCADE
71
+ );
72
+
73
+ CREATE INDEX idx_ai_model_call_usage_groups_group_time
74
+ ON ai_model_call_usage_groups (project_id, group_id, occurred_at, usage_record_id);
@@ -0,0 +1,22 @@
1
+ ALTER TABLE sync_runs ADD COLUMN error TEXT CHECK (error IS NULL OR json_valid(error));
2
+
3
+ UPDATE sync_runs
4
+ SET error = json_object(
5
+ 'code', CASE WHEN status = 'cancelled' THEN 'runtime.cancelled' ELSE 'internal.unexpected' END,
6
+ 'message', CASE
7
+ WHEN status = 'cancelled' THEN 'Execution was cancelled.'
8
+ ELSE 'An unexpected internal error occurred.'
9
+ END,
10
+ 'retryable', json('false'),
11
+ 'at', COALESCE(finished_at, started_at),
12
+ 'details', json_object(
13
+ 'syncId', sync_id,
14
+ 'runId', id,
15
+ 'datasetId', dataset_id,
16
+ 'migratedFromLegacyError', json('true')
17
+ )
18
+ )
19
+ WHERE error_name IS NOT NULL OR error_message IS NOT NULL;
20
+
21
+ ALTER TABLE sync_runs DROP COLUMN error_name;
22
+ ALTER TABLE sync_runs DROP COLUMN error_message;
@@ -0,0 +1,45 @@
1
+ ALTER TABLE pipeline_runs ADD COLUMN error TEXT CHECK (error IS NULL OR json_valid(error));
2
+
3
+ UPDATE pipeline_runs
4
+ SET error = json_object(
5
+ 'code', CASE WHEN status = 'cancelled' THEN 'runtime.cancelled' ELSE 'internal.unexpected' END,
6
+ 'message', CASE
7
+ WHEN status = 'cancelled' THEN 'Execution was cancelled.'
8
+ ELSE 'An unexpected internal error occurred.'
9
+ END,
10
+ 'retryable', json('false'),
11
+ 'at', COALESCE(finished_at, started_at),
12
+ 'details', json_object(
13
+ 'pipelineId', pipeline_id,
14
+ 'runId', id,
15
+ 'migratedFromLegacyError', json('true')
16
+ )
17
+ )
18
+ WHERE error_name IS NOT NULL OR error_message IS NOT NULL;
19
+
20
+ ALTER TABLE pipeline_runs DROP COLUMN error_name;
21
+ ALTER TABLE pipeline_runs DROP COLUMN error_message;
22
+
23
+ ALTER TABLE pipeline_step_runs ADD COLUMN error TEXT CHECK (error IS NULL OR json_valid(error));
24
+
25
+ UPDATE pipeline_step_runs
26
+ SET error = json_object(
27
+ 'code', CASE WHEN status = 'cancelled' THEN 'runtime.cancelled' ELSE 'internal.unexpected' END,
28
+ 'message', CASE
29
+ WHEN status = 'cancelled' THEN 'Execution was cancelled.'
30
+ ELSE 'An unexpected internal error occurred.'
31
+ END,
32
+ 'retryable', json('false'),
33
+ 'at', COALESCE(finished_at, started_at),
34
+ 'details', json_object(
35
+ 'pipelineId', pipeline_id,
36
+ 'pipelineRunId', pipeline_run_id,
37
+ 'stepId', step_id,
38
+ 'stepRunId', id,
39
+ 'migratedFromLegacyError', json('true')
40
+ )
41
+ )
42
+ WHERE error_name IS NOT NULL OR error_message IS NOT NULL;
43
+
44
+ ALTER TABLE pipeline_step_runs DROP COLUMN error_name;
45
+ ALTER TABLE pipeline_step_runs DROP COLUMN error_message;
@@ -0,0 +1,45 @@
1
+ ALTER TABLE workflow_runs RENAME COLUMN error TO legacy_error;
2
+ ALTER TABLE workflow_runs ADD COLUMN error TEXT CHECK (error IS NULL OR json_valid(error));
3
+
4
+ UPDATE workflow_runs
5
+ SET error = json_object(
6
+ 'code', CASE WHEN status = 'cancelled' THEN 'runtime.cancelled' ELSE 'internal.unexpected' END,
7
+ 'message', CASE
8
+ WHEN status = 'cancelled' THEN 'Execution was cancelled.'
9
+ ELSE 'An unexpected internal error occurred.'
10
+ END,
11
+ 'retryable', json('false'),
12
+ 'at', COALESCE(finished_at, started_at),
13
+ 'details', json_object(
14
+ 'workflowId', workflow_id,
15
+ 'workflowRunId', id,
16
+ 'migratedFromLegacyError', json('true')
17
+ )
18
+ )
19
+ WHERE legacy_error IS NOT NULL;
20
+
21
+ ALTER TABLE workflow_runs DROP COLUMN legacy_error;
22
+
23
+ ALTER TABLE workflow_node_runs RENAME COLUMN error TO legacy_error;
24
+ ALTER TABLE workflow_node_runs ADD COLUMN error TEXT CHECK (error IS NULL OR json_valid(error));
25
+
26
+ UPDATE workflow_node_runs
27
+ SET error = json_object(
28
+ 'code', CASE WHEN status = 'cancelled' THEN 'runtime.cancelled' ELSE 'internal.unexpected' END,
29
+ 'message', CASE
30
+ WHEN status = 'cancelled' THEN 'Execution was cancelled.'
31
+ ELSE 'An unexpected internal error occurred.'
32
+ END,
33
+ 'retryable', json('false'),
34
+ 'at', COALESCE(finished_at, started_at),
35
+ 'details', json_object(
36
+ 'workflowId', workflow_id,
37
+ 'workflowRunId', workflow_run_id,
38
+ 'nodeId', node_id,
39
+ 'nodeRunId', id,
40
+ 'migratedFromLegacyError', json('true')
41
+ )
42
+ )
43
+ WHERE legacy_error IS NOT NULL;
44
+
45
+ ALTER TABLE workflow_node_runs DROP COLUMN legacy_error;
@@ -0,0 +1,59 @@
1
+ ALTER TABLE agent_runs RENAME COLUMN error TO legacy_error;
2
+ ALTER TABLE agent_runs ADD COLUMN error TEXT CHECK (error IS NULL OR json_valid(error));
3
+
4
+ UPDATE agent_runs
5
+ SET error = json_object(
6
+ 'code', CASE WHEN status = 'cancelled' THEN 'runtime.cancelled' ELSE 'internal.unexpected' END,
7
+ 'message', CASE
8
+ WHEN status = 'cancelled' THEN 'Execution was cancelled.'
9
+ ELSE 'An unexpected internal error occurred.'
10
+ END,
11
+ 'retryable', json('false'),
12
+ 'at', COALESCE(completed_at, started_at, created_at),
13
+ 'details', json_object(
14
+ 'agentId', agent_id,
15
+ 'runId', id,
16
+ 'threadId', thread_id,
17
+ 'migratedFromLegacyError', json('true')
18
+ )
19
+ )
20
+ WHERE legacy_error IS NOT NULL;
21
+
22
+ ALTER TABLE agent_runs DROP COLUMN legacy_error;
23
+
24
+ ALTER TABLE workflow_agent_node_runs RENAME COLUMN error TO legacy_error;
25
+ ALTER TABLE workflow_agent_node_runs ADD COLUMN error TEXT CHECK (error IS NULL OR json_valid(error));
26
+
27
+ UPDATE workflow_agent_node_runs
28
+ SET error = json_object(
29
+ 'code', CASE WHEN status = 'cancelled' THEN 'runtime.cancelled' ELSE 'internal.unexpected' END,
30
+ 'message', CASE
31
+ WHEN status = 'cancelled' THEN 'Execution was cancelled.'
32
+ ELSE 'An unexpected internal error occurred.'
33
+ END,
34
+ 'retryable', json('false'),
35
+ 'at', COALESCE(completed_at, started_at, created_at),
36
+ 'details', json_object(
37
+ 'agentId', agent_id,
38
+ 'workflowId', (
39
+ SELECT workflow_id FROM workflow_node_runs AS node
40
+ WHERE node.project_id = workflow_agent_node_runs.project_id
41
+ AND node.id = workflow_agent_node_runs.node_run_id
42
+ ),
43
+ 'workflowRunId', (
44
+ SELECT workflow_run_id FROM workflow_node_runs AS node
45
+ WHERE node.project_id = workflow_agent_node_runs.project_id
46
+ AND node.id = workflow_agent_node_runs.node_run_id
47
+ ),
48
+ 'nodeId', (
49
+ SELECT node_id FROM workflow_node_runs AS node
50
+ WHERE node.project_id = workflow_agent_node_runs.project_id
51
+ AND node.id = workflow_agent_node_runs.node_run_id
52
+ ),
53
+ 'nodeRunId', node_run_id,
54
+ 'migratedFromLegacyError', json('true')
55
+ )
56
+ )
57
+ WHERE legacy_error IS NOT NULL;
58
+
59
+ ALTER TABLE workflow_agent_node_runs DROP COLUMN legacy_error;
@@ -0,0 +1,20 @@
1
+ ALTER TABLE projection_runs ADD COLUMN error TEXT CHECK (error IS NULL OR json_valid(error));
2
+
3
+ UPDATE projection_runs
4
+ SET error = json_object(
5
+ 'code', CASE WHEN status = 'cancelled' THEN 'runtime.cancelled' ELSE 'internal.unexpected' END,
6
+ 'message', CASE
7
+ WHEN status = 'cancelled' THEN 'Execution was cancelled.'
8
+ ELSE 'An unexpected internal error occurred.'
9
+ END,
10
+ 'retryable', json('false'),
11
+ 'at', COALESCE(finished_at, started_at),
12
+ 'details', json_object(
13
+ 'projectionId', projection_id,
14
+ 'runId', id,
15
+ 'migratedFromLegacyError', json('true')
16
+ )
17
+ )
18
+ WHERE error_message IS NOT NULL;
19
+
20
+ ALTER TABLE projection_runs DROP COLUMN error_message;
@@ -0,0 +1,19 @@
1
+ ALTER TABLE webhook_runs RENAME COLUMN error TO legacy_error;
2
+ ALTER TABLE webhook_runs ADD COLUMN error TEXT CHECK (error IS NULL OR json_valid(error));
3
+
4
+ UPDATE webhook_runs
5
+ SET error = json_object(
6
+ 'code', 'internal.unexpected',
7
+ 'message', 'An unexpected internal error occurred.',
8
+ 'retryable', json('false'),
9
+ 'at', COALESCE(finished_at, started_at),
10
+ 'details', json_object(
11
+ 'connectorId', connector_id,
12
+ 'webhookId', webhook_id,
13
+ 'runId', id,
14
+ 'migratedFromLegacyError', json('true')
15
+ )
16
+ )
17
+ WHERE legacy_error IS NOT NULL;
18
+
19
+ ALTER TABLE webhook_runs DROP COLUMN legacy_error;
@@ -0,0 +1,65 @@
1
+ ALTER TABLE action_runs ADD COLUMN writeback_error TEXT
2
+ CHECK (writeback_error IS NULL OR json_valid(writeback_error));
3
+ ALTER TABLE action_runs ADD COLUMN effects_error TEXT
4
+ CHECK (effects_error IS NULL OR json_valid(effects_error));
5
+ ALTER TABLE action_runs ADD COLUMN error TEXT CHECK (error IS NULL OR json_valid(error));
6
+
7
+ UPDATE action_runs
8
+ SET writeback_error = json_object(
9
+ 'code', 'internal.unexpected',
10
+ 'message', 'An unexpected internal error occurred.',
11
+ 'retryable', json('false'),
12
+ 'at', COALESCE(writeback_completed_at, finished_at, queued_at),
13
+ 'details', json_object(
14
+ 'actionId', action_id,
15
+ 'runId', id,
16
+ 'phase', 'writeback'
17
+ )
18
+ )
19
+ WHERE writeback_error_name IS NOT NULL OR writeback_error_message IS NOT NULL;
20
+
21
+ UPDATE action_runs
22
+ SET effects_error = json_object(
23
+ 'code', 'internal.unexpected',
24
+ 'message', 'An unexpected internal error occurred.',
25
+ 'retryable', json('false'),
26
+ 'at', COALESCE(effects_completed_at, finished_at, queued_at),
27
+ 'details', json_object(
28
+ 'actionId', action_id,
29
+ 'runId', id,
30
+ 'phase', 'effects'
31
+ )
32
+ )
33
+ WHERE effects_error_name IS NOT NULL OR effects_error_message IS NOT NULL;
34
+
35
+ UPDATE action_runs
36
+ SET error = json_object(
37
+ 'code', CASE
38
+ WHEN error_phase = 'enqueue' THEN 'queue.enqueue_failed'
39
+ WHEN error_phase = 'cancelled' OR status = 'cancelled' THEN 'runtime.cancelled'
40
+ ELSE 'internal.unexpected'
41
+ END,
42
+ 'message', CASE
43
+ WHEN error_phase = 'enqueue' THEN 'The job could not be enqueued.'
44
+ WHEN error_phase = 'cancelled' OR status = 'cancelled' THEN 'Execution was cancelled.'
45
+ ELSE 'An unexpected internal error occurred.'
46
+ END,
47
+ 'retryable', json(CASE WHEN error_phase = 'enqueue' THEN 'true' ELSE 'false' END),
48
+ 'at', COALESCE(finished_at, queued_at),
49
+ 'details', json_object(
50
+ 'actionId', action_id,
51
+ 'runId', id,
52
+ 'phase', COALESCE(error_phase, phase, 'request')
53
+ )
54
+ )
55
+ WHERE error_name IS NOT NULL OR error_message IS NOT NULL;
56
+
57
+ ALTER TABLE action_runs DROP COLUMN writeback_error_name;
58
+ ALTER TABLE action_runs DROP COLUMN writeback_error_message;
59
+ ALTER TABLE action_runs DROP COLUMN writeback_error_phase;
60
+ ALTER TABLE action_runs DROP COLUMN effects_error_name;
61
+ ALTER TABLE action_runs DROP COLUMN effects_error_message;
62
+ ALTER TABLE action_runs DROP COLUMN effects_error_phase;
63
+ ALTER TABLE action_runs DROP COLUMN error_name;
64
+ ALTER TABLE action_runs DROP COLUMN error_message;
65
+ ALTER TABLE action_runs DROP COLUMN error_phase;