@sixb/sqlite 0.1.6 → 0.1.7
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.
- package/dist/agents/rows.d.ts +7 -4
- package/dist/agents/rows.d.ts.map +1 -1
- package/dist/agents/runs.d.ts +3 -2
- package/dist/agents/runs.d.ts.map +1 -1
- package/dist/agents/threads.d.ts.map +1 -1
- package/dist/ai-cost-groups.d.ts +5 -0
- package/dist/ai-cost-groups.d.ts.map +1 -0
- package/dist/ai-cost-storage.d.ts +2 -1
- package/dist/ai-cost-storage.d.ts.map +1 -1
- package/dist/ai-limit-storage.d.ts +35 -0
- package/dist/ai-limit-storage.d.ts.map +1 -0
- package/dist/ai-usage-storage.d.ts +1 -0
- package/dist/ai-usage-storage.d.ts.map +1 -1
- package/dist/auth-storage/access-tokens.d.ts +1 -1
- package/dist/auth-storage/access-tokens.d.ts.map +1 -1
- package/dist/auth-storage/auth-storage.d.ts +4 -1
- package/dist/auth-storage/auth-storage.d.ts.map +1 -1
- package/dist/auth-storage/device-authorizations.d.ts +29 -0
- package/dist/auth-storage/device-authorizations.d.ts.map +1 -0
- package/dist/auth-storage/rows.d.ts +19 -1
- package/dist/auth-storage/rows.d.ts.map +1 -1
- package/dist/auth-storage/shared.d.ts +1 -1
- package/dist/auth-storage/shared.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1898 -356
- package/dist/index.js.map +18 -15
- package/dist/migrations.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/agents/rows.ts +36 -9
- package/src/agents/runs.ts +152 -13
- package/src/agents/threads.ts +2 -17
- package/src/ai-cost-groups.ts +100 -0
- package/src/ai-cost-storage.ts +67 -25
- package/src/ai-limit-storage.ts +981 -0
- package/src/ai-usage-storage.ts +24 -1
- package/src/auth-storage/access-tokens.ts +77 -68
- package/src/auth-storage/auth-storage.ts +80 -1
- package/src/auth-storage/device-authorizations.ts +153 -0
- package/src/auth-storage/rows.ts +41 -0
- package/src/auth-storage/shared.ts +1 -0
- package/src/index.ts +6 -0
- package/src/migrations/029-model-accounting.sql +79 -0
- package/src/migrations/030-ai-usage-limits.sql +100 -0
- package/src/migrations/031-subagent-runs.sql +231 -0
- package/src/migrations/032-conversation-run-spec.sql +78 -0
- package/src/migrations/033-retire-agent-definitions.sql +89 -0
- package/src/migrations/034-device-authorizations.sql +22 -0
- package/src/migrations.ts +18 -0
- package/src/workflow-run-storage.ts +8 -8
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
-- Call-time model configuration and provider identity. Historical identity remains unknown.
|
|
2
|
+
ALTER TABLE ai_model_call_usage
|
|
3
|
+
ADD COLUMN requested_reasoning TEXT
|
|
4
|
+
CHECK (
|
|
5
|
+
requested_reasoning IS NULL OR (
|
|
6
|
+
json_valid(requested_reasoning) AND
|
|
7
|
+
json_type(requested_reasoning) IN ('text', 'object')
|
|
8
|
+
)
|
|
9
|
+
);
|
|
10
|
+
ALTER TABLE ai_model_call_usage ADD COLUMN provider_ids TEXT
|
|
11
|
+
CHECK (provider_ids IS NULL OR json_valid(provider_ids));
|
|
12
|
+
|
|
13
|
+
-- Upgrade the shipped valuation reason while retaining the selected-cost projection.
|
|
14
|
+
CREATE TABLE ai_model_call_valuations_next (
|
|
15
|
+
project_id TEXT NOT NULL CHECK (length(trim(project_id)) > 0),
|
|
16
|
+
usage_record_id TEXT NOT NULL CHECK (length(trim(usage_record_id)) > 0),
|
|
17
|
+
status TEXT NOT NULL CHECK (status IN ('rated', 'unpriceable')),
|
|
18
|
+
provider_id TEXT CHECK (provider_id IS NULL OR length(trim(provider_id)) > 0),
|
|
19
|
+
model_id TEXT CHECK (model_id IS NULL OR length(trim(model_id)) > 0),
|
|
20
|
+
currency TEXT CHECK (
|
|
21
|
+
currency IS NULL OR (length(currency) = 3 AND currency GLOB '[A-Z][A-Z][A-Z]')
|
|
22
|
+
),
|
|
23
|
+
amount_nanos INTEGER CHECK (
|
|
24
|
+
amount_nanos IS NULL OR (typeof(amount_nanos) = 'integer' AND amount_nanos >= 0)
|
|
25
|
+
),
|
|
26
|
+
reason TEXT CHECK (
|
|
27
|
+
reason IS NULL OR reason IN (
|
|
28
|
+
'missingBillingIdentity',
|
|
29
|
+
'missingRateCard',
|
|
30
|
+
'missingUsageMeter',
|
|
31
|
+
'unsupportedPricingDimension',
|
|
32
|
+
'invalidUsageForFormula'
|
|
33
|
+
)
|
|
34
|
+
),
|
|
35
|
+
details TEXT NOT NULL CHECK (json_valid(details) AND json_type(details) = 'object'),
|
|
36
|
+
rated_at TEXT NOT NULL CHECK (length(trim(rated_at)) > 0),
|
|
37
|
+
PRIMARY KEY (project_id, usage_record_id),
|
|
38
|
+
FOREIGN KEY (project_id, usage_record_id)
|
|
39
|
+
REFERENCES ai_model_call_usage(project_id, id)
|
|
40
|
+
ON DELETE RESTRICT,
|
|
41
|
+
CHECK (
|
|
42
|
+
(
|
|
43
|
+
status = 'rated'
|
|
44
|
+
AND provider_id IS NOT NULL
|
|
45
|
+
AND model_id IS NOT NULL
|
|
46
|
+
AND currency IS NOT NULL
|
|
47
|
+
AND amount_nanos IS NOT NULL
|
|
48
|
+
AND reason IS NULL
|
|
49
|
+
)
|
|
50
|
+
OR
|
|
51
|
+
(
|
|
52
|
+
status = 'unpriceable'
|
|
53
|
+
AND currency IS NULL
|
|
54
|
+
AND amount_nanos IS NULL
|
|
55
|
+
AND reason IS NOT NULL
|
|
56
|
+
AND (
|
|
57
|
+
(reason = 'missingBillingIdentity' AND provider_id IS NULL AND model_id IS NULL)
|
|
58
|
+
OR
|
|
59
|
+
(reason <> 'missingBillingIdentity' AND provider_id IS NOT NULL AND model_id IS NOT NULL)
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
INSERT INTO ai_model_call_valuations_next (
|
|
66
|
+
project_id, usage_record_id, status, provider_id, model_id,
|
|
67
|
+
currency, amount_nanos, reason, details, rated_at
|
|
68
|
+
)
|
|
69
|
+
SELECT project_id, usage_record_id, status, provider_id, model_id,
|
|
70
|
+
currency, amount_nanos,
|
|
71
|
+
CASE WHEN reason = 'missingCatalogEntry' THEN 'missingRateCard' ELSE reason END,
|
|
72
|
+
details, rated_at
|
|
73
|
+
FROM ai_model_call_valuations;
|
|
74
|
+
|
|
75
|
+
DROP TABLE ai_model_call_valuations;
|
|
76
|
+
ALTER TABLE ai_model_call_valuations_next RENAME TO ai_model_call_valuations;
|
|
77
|
+
|
|
78
|
+
CREATE INDEX idx_ai_model_call_valuations_summary
|
|
79
|
+
ON ai_model_call_valuations (project_id, status, currency, usage_record_id);
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
CREATE TABLE ai_usage_limits (
|
|
2
|
+
project_id TEXT NOT NULL CHECK (length(trim(project_id)) > 0),
|
|
3
|
+
id TEXT NOT NULL CHECK (length(trim(id)) > 0),
|
|
4
|
+
subject_type TEXT NOT NULL CHECK (
|
|
5
|
+
subject_type IN ('project', 'group', 'user', 'serviceAccount')
|
|
6
|
+
),
|
|
7
|
+
subject_id TEXT NOT NULL CHECK (
|
|
8
|
+
(subject_type = 'project' AND subject_id = '')
|
|
9
|
+
OR (subject_type <> 'project' AND length(trim(subject_id)) > 0)
|
|
10
|
+
),
|
|
11
|
+
meter TEXT NOT NULL CHECK (meter IN ('tokens.total', 'cost.catalogEstimated')),
|
|
12
|
+
currency TEXT NOT NULL CHECK (
|
|
13
|
+
(meter = 'tokens.total' AND currency = '')
|
|
14
|
+
OR (meter = 'cost.catalogEstimated' AND currency = 'USD')
|
|
15
|
+
),
|
|
16
|
+
limit_amount TEXT NOT NULL CHECK (
|
|
17
|
+
limit_amount = '0'
|
|
18
|
+
OR (
|
|
19
|
+
limit_amount NOT GLOB '*[^0-9]*'
|
|
20
|
+
AND substr(limit_amount, 1, 1) BETWEEN '1' AND '9'
|
|
21
|
+
)
|
|
22
|
+
),
|
|
23
|
+
period_kind TEXT NOT NULL CHECK (period_kind = 'calendarMonth'),
|
|
24
|
+
enabled INTEGER NOT NULL CHECK (enabled IN (0, 1)),
|
|
25
|
+
created_at TEXT NOT NULL,
|
|
26
|
+
updated_at TEXT NOT NULL,
|
|
27
|
+
PRIMARY KEY (project_id, id),
|
|
28
|
+
UNIQUE (project_id, subject_type, subject_id, meter, currency)
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
CREATE INDEX idx_ai_usage_limits_project_enabled
|
|
32
|
+
ON ai_usage_limits (project_id, enabled, subject_type, subject_id, meter, currency);
|
|
33
|
+
|
|
34
|
+
CREATE TABLE ai_usage_limit_periods (
|
|
35
|
+
project_id TEXT NOT NULL CHECK (length(trim(project_id)) > 0),
|
|
36
|
+
subject_type TEXT NOT NULL CHECK (
|
|
37
|
+
subject_type IN ('project', 'group', 'user', 'serviceAccount')
|
|
38
|
+
),
|
|
39
|
+
subject_id TEXT NOT NULL CHECK (
|
|
40
|
+
(subject_type = 'project' AND subject_id = '')
|
|
41
|
+
OR (subject_type <> 'project' AND length(trim(subject_id)) > 0)
|
|
42
|
+
),
|
|
43
|
+
meter TEXT NOT NULL CHECK (meter IN ('tokens.total', 'cost.catalogEstimated')),
|
|
44
|
+
currency TEXT NOT NULL CHECK (
|
|
45
|
+
(meter = 'tokens.total' AND currency = '')
|
|
46
|
+
OR (meter = 'cost.catalogEstimated' AND currency = 'USD')
|
|
47
|
+
),
|
|
48
|
+
period_start TEXT NOT NULL,
|
|
49
|
+
period_end TEXT NOT NULL,
|
|
50
|
+
actual_amount TEXT NOT NULL DEFAULT '0',
|
|
51
|
+
reserved_amount TEXT NOT NULL DEFAULT '0',
|
|
52
|
+
unknown_amount TEXT NOT NULL DEFAULT '0',
|
|
53
|
+
accounting_status TEXT NOT NULL DEFAULT 'complete' CHECK (
|
|
54
|
+
accounting_status IN ('complete', 'unavailable')
|
|
55
|
+
),
|
|
56
|
+
updated_at TEXT NOT NULL,
|
|
57
|
+
PRIMARY KEY (
|
|
58
|
+
project_id, subject_type, subject_id, meter, currency, period_start
|
|
59
|
+
)
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
CREATE INDEX idx_ai_usage_limit_periods_subject_period
|
|
63
|
+
ON ai_usage_limit_periods (
|
|
64
|
+
project_id, subject_type, subject_id, period_start, period_end, meter, currency
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
CREATE TABLE ai_model_call_reservations (
|
|
68
|
+
project_id TEXT NOT NULL CHECK (length(trim(project_id)) > 0),
|
|
69
|
+
execution_id TEXT NOT NULL CHECK (length(trim(execution_id)) > 0),
|
|
70
|
+
attempt INTEGER NOT NULL CHECK (attempt >= 1),
|
|
71
|
+
call_id TEXT NOT NULL CHECK (length(trim(call_id)) > 0),
|
|
72
|
+
buckets TEXT NOT NULL CHECK (json_valid(buckets) AND json_type(buckets) = 'array'),
|
|
73
|
+
request_key TEXT NOT NULL,
|
|
74
|
+
period_start TEXT NOT NULL,
|
|
75
|
+
period_end TEXT NOT NULL,
|
|
76
|
+
state TEXT NOT NULL CHECK (state IN ('active', 'reconciled', 'unknown')),
|
|
77
|
+
usage_record_id TEXT,
|
|
78
|
+
reserved_at TEXT NOT NULL,
|
|
79
|
+
updated_at TEXT NOT NULL,
|
|
80
|
+
PRIMARY KEY (project_id, execution_id, attempt, call_id),
|
|
81
|
+
FOREIGN KEY (project_id, execution_id)
|
|
82
|
+
REFERENCES executions(project_id, id)
|
|
83
|
+
ON DELETE RESTRICT,
|
|
84
|
+
FOREIGN KEY (project_id, usage_record_id)
|
|
85
|
+
REFERENCES ai_model_call_usage(project_id, id)
|
|
86
|
+
ON DELETE RESTRICT,
|
|
87
|
+
CHECK (
|
|
88
|
+
(
|
|
89
|
+
state = 'reconciled'
|
|
90
|
+
AND usage_record_id IS NOT NULL
|
|
91
|
+
)
|
|
92
|
+
OR (
|
|
93
|
+
state <> 'reconciled'
|
|
94
|
+
AND usage_record_id IS NULL
|
|
95
|
+
)
|
|
96
|
+
)
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
CREATE INDEX idx_ai_model_call_reservations_active
|
|
100
|
+
ON ai_model_call_reservations (project_id, state, period_end, execution_id, attempt, call_id);
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
-- SQLite cannot alter a CHECK constraint in place. Rebuild the execution table to align SQL with
|
|
2
|
+
-- the durable Agent authority model: managed service account or exact inherited user/disabled.
|
|
3
|
+
CREATE TABLE executions_v3 (
|
|
4
|
+
project_id TEXT NOT NULL CHECK (length(trim(project_id)) > 0),
|
|
5
|
+
id TEXT NOT NULL CHECK (length(trim(id)) > 0),
|
|
6
|
+
executor_kind TEXT NOT NULL CHECK (
|
|
7
|
+
executor_kind IN (
|
|
8
|
+
'request', 'action', 'pipeline', 'projection', 'rule', 'sync', 'webhook', 'workflow',
|
|
9
|
+
'agent', 'kernel'
|
|
10
|
+
)
|
|
11
|
+
),
|
|
12
|
+
executor_id TEXT NOT NULL CHECK (length(trim(executor_id)) > 0),
|
|
13
|
+
source_kind TEXT NOT NULL CHECK (
|
|
14
|
+
source_kind IN ('http', 'webhook', 'schedule', 'event', 'datasetVersion', 'execution')
|
|
15
|
+
),
|
|
16
|
+
source_id TEXT NOT NULL CHECK (length(trim(source_id)) > 0),
|
|
17
|
+
requested_by_user_id TEXT,
|
|
18
|
+
requested_by_service_account_id TEXT,
|
|
19
|
+
correlation_id TEXT NOT NULL CHECK (length(trim(correlation_id)) > 0),
|
|
20
|
+
parent_execution_id TEXT,
|
|
21
|
+
authority_kind TEXT NOT NULL CHECK (
|
|
22
|
+
authority_kind IN ('principal', 'trustedPrimitive', 'kernel', 'disabled')
|
|
23
|
+
),
|
|
24
|
+
authority_user_id TEXT,
|
|
25
|
+
authority_service_account_id TEXT,
|
|
26
|
+
authority_session_id TEXT,
|
|
27
|
+
authority_access_token_id TEXT,
|
|
28
|
+
authority_primitive_kind TEXT CHECK (
|
|
29
|
+
authority_primitive_kind IS NULL
|
|
30
|
+
OR authority_primitive_kind IN (
|
|
31
|
+
'action', 'pipeline', 'projection', 'rule', 'sync', 'webhook', 'workflow'
|
|
32
|
+
)
|
|
33
|
+
),
|
|
34
|
+
authority_primitive_id TEXT,
|
|
35
|
+
authority_kernel_operation TEXT CHECK (
|
|
36
|
+
authority_kernel_operation IS NULL OR authority_kernel_operation = 'ontology.recover'
|
|
37
|
+
),
|
|
38
|
+
created_at TEXT NOT NULL,
|
|
39
|
+
PRIMARY KEY (project_id, id),
|
|
40
|
+
FOREIGN KEY (project_id, parent_execution_id) REFERENCES executions (project_id, id),
|
|
41
|
+
FOREIGN KEY (project_id, requested_by_user_id) REFERENCES auth_users (project_id, id),
|
|
42
|
+
FOREIGN KEY (project_id, requested_by_service_account_id)
|
|
43
|
+
REFERENCES auth_service_accounts (project_id, id),
|
|
44
|
+
FOREIGN KEY (project_id, authority_user_id) REFERENCES auth_users (project_id, id),
|
|
45
|
+
FOREIGN KEY (project_id, authority_service_account_id)
|
|
46
|
+
REFERENCES auth_service_accounts (project_id, id),
|
|
47
|
+
FOREIGN KEY (project_id, authority_session_id) REFERENCES auth_sessions (project_id, id),
|
|
48
|
+
FOREIGN KEY (project_id, authority_access_token_id)
|
|
49
|
+
REFERENCES auth_access_tokens (project_id, id),
|
|
50
|
+
CHECK ((requested_by_user_id IS NOT NULL) + (requested_by_service_account_id IS NOT NULL) <= 1),
|
|
51
|
+
CHECK (
|
|
52
|
+
(source_kind = 'execution' AND parent_execution_id = source_id)
|
|
53
|
+
OR (source_kind <> 'execution' AND parent_execution_id IS NULL)
|
|
54
|
+
),
|
|
55
|
+
CHECK (
|
|
56
|
+
(
|
|
57
|
+
authority_kind = 'principal'
|
|
58
|
+
AND (authority_user_id IS NOT NULL) + (authority_service_account_id IS NOT NULL) = 1
|
|
59
|
+
AND (authority_session_id IS NOT NULL) + (authority_access_token_id IS NOT NULL) <= 1
|
|
60
|
+
AND (authority_session_id IS NULL OR authority_user_id IS NOT NULL)
|
|
61
|
+
AND authority_primitive_kind IS NULL
|
|
62
|
+
AND authority_primitive_id IS NULL
|
|
63
|
+
AND authority_kernel_operation IS NULL
|
|
64
|
+
)
|
|
65
|
+
OR (
|
|
66
|
+
authority_kind = 'trustedPrimitive'
|
|
67
|
+
AND authority_user_id IS NULL
|
|
68
|
+
AND authority_service_account_id IS NULL
|
|
69
|
+
AND authority_session_id IS NULL
|
|
70
|
+
AND authority_access_token_id IS NULL
|
|
71
|
+
AND authority_primitive_kind IS NOT NULL
|
|
72
|
+
AND authority_primitive_id IS NOT NULL
|
|
73
|
+
AND length(trim(authority_primitive_id)) > 0
|
|
74
|
+
AND authority_kernel_operation IS NULL
|
|
75
|
+
)
|
|
76
|
+
OR (
|
|
77
|
+
authority_kind = 'kernel'
|
|
78
|
+
AND authority_user_id IS NULL
|
|
79
|
+
AND authority_service_account_id IS NULL
|
|
80
|
+
AND authority_session_id IS NULL
|
|
81
|
+
AND authority_access_token_id IS NULL
|
|
82
|
+
AND authority_primitive_kind IS NULL
|
|
83
|
+
AND authority_primitive_id IS NULL
|
|
84
|
+
AND authority_kernel_operation IS NOT NULL
|
|
85
|
+
)
|
|
86
|
+
OR (
|
|
87
|
+
authority_kind = 'disabled'
|
|
88
|
+
AND authority_user_id IS NULL
|
|
89
|
+
AND authority_service_account_id IS NULL
|
|
90
|
+
AND authority_session_id IS NULL
|
|
91
|
+
AND authority_access_token_id IS NULL
|
|
92
|
+
AND authority_primitive_kind IS NULL
|
|
93
|
+
AND authority_primitive_id IS NULL
|
|
94
|
+
AND authority_kernel_operation IS NULL
|
|
95
|
+
)
|
|
96
|
+
),
|
|
97
|
+
CHECK (
|
|
98
|
+
(
|
|
99
|
+
executor_kind = 'request'
|
|
100
|
+
AND source_kind = 'http'
|
|
101
|
+
AND executor_id = source_id
|
|
102
|
+
AND (
|
|
103
|
+
(
|
|
104
|
+
authority_kind = 'principal'
|
|
105
|
+
AND requested_by_user_id IS authority_user_id
|
|
106
|
+
AND requested_by_service_account_id IS authority_service_account_id
|
|
107
|
+
)
|
|
108
|
+
OR (
|
|
109
|
+
authority_kind = 'disabled'
|
|
110
|
+
AND requested_by_user_id IS NULL
|
|
111
|
+
AND requested_by_service_account_id IS NULL
|
|
112
|
+
)
|
|
113
|
+
)
|
|
114
|
+
)
|
|
115
|
+
OR (
|
|
116
|
+
executor_kind IN ('action', 'pipeline', 'projection', 'rule', 'sync', 'webhook', 'workflow')
|
|
117
|
+
AND authority_kind = 'trustedPrimitive'
|
|
118
|
+
AND executor_kind = authority_primitive_kind
|
|
119
|
+
)
|
|
120
|
+
OR (
|
|
121
|
+
executor_kind = 'agent'
|
|
122
|
+
AND source_kind = 'execution'
|
|
123
|
+
AND (
|
|
124
|
+
(
|
|
125
|
+
authority_kind = 'principal'
|
|
126
|
+
AND authority_service_account_id IS NOT NULL
|
|
127
|
+
AND authority_session_id IS NULL
|
|
128
|
+
AND authority_access_token_id IS NULL
|
|
129
|
+
)
|
|
130
|
+
OR (
|
|
131
|
+
authority_kind = 'principal'
|
|
132
|
+
AND authority_user_id IS NOT NULL
|
|
133
|
+
AND (authority_session_id IS NOT NULL) + (authority_access_token_id IS NOT NULL) = 1
|
|
134
|
+
)
|
|
135
|
+
OR authority_kind = 'disabled'
|
|
136
|
+
)
|
|
137
|
+
)
|
|
138
|
+
OR (executor_kind = 'kernel' AND authority_kind = 'kernel')
|
|
139
|
+
)
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
INSERT INTO executions_v3 SELECT * FROM executions;
|
|
143
|
+
DROP TABLE executions;
|
|
144
|
+
ALTER TABLE executions_v3 RENAME TO executions;
|
|
145
|
+
|
|
146
|
+
CREATE TABLE agent_runs_v3 (
|
|
147
|
+
project_id TEXT NOT NULL,
|
|
148
|
+
id TEXT NOT NULL,
|
|
149
|
+
execution_id TEXT NOT NULL,
|
|
150
|
+
kind TEXT NOT NULL DEFAULT 'conversation' CHECK (kind IN ('conversation', 'subagent')),
|
|
151
|
+
thread_id TEXT,
|
|
152
|
+
agent_id TEXT,
|
|
153
|
+
trigger_message_id TEXT,
|
|
154
|
+
parent_run_id TEXT,
|
|
155
|
+
spawn_key TEXT,
|
|
156
|
+
spec TEXT CHECK (spec IS NULL OR json_valid(spec)),
|
|
157
|
+
result TEXT CHECK (result IS NULL OR json_valid(result)),
|
|
158
|
+
requester_group_ids TEXT NOT NULL DEFAULT '[]'
|
|
159
|
+
CHECK (json_valid(requester_group_ids) AND json_type(requester_group_ids) = 'array'),
|
|
160
|
+
status TEXT NOT NULL CHECK (
|
|
161
|
+
status IN ('queued', 'running', 'succeeded', 'failed', 'cancelled')
|
|
162
|
+
),
|
|
163
|
+
model_id TEXT,
|
|
164
|
+
finish_reason TEXT,
|
|
165
|
+
error TEXT CHECK (error IS NULL OR json_valid(error)),
|
|
166
|
+
diagnostics TEXT,
|
|
167
|
+
attempt INTEGER NOT NULL DEFAULT 0 CHECK (attempt >= 0),
|
|
168
|
+
execution_token TEXT,
|
|
169
|
+
execution_queue_lease_expires_at TEXT,
|
|
170
|
+
created_at TEXT NOT NULL,
|
|
171
|
+
started_at TEXT,
|
|
172
|
+
completed_at TEXT,
|
|
173
|
+
PRIMARY KEY (project_id, id),
|
|
174
|
+
UNIQUE (project_id, execution_id),
|
|
175
|
+
UNIQUE (project_id, parent_run_id, spawn_key),
|
|
176
|
+
FOREIGN KEY (project_id, execution_id)
|
|
177
|
+
REFERENCES executions (project_id, id)
|
|
178
|
+
ON DELETE RESTRICT,
|
|
179
|
+
FOREIGN KEY (project_id, parent_run_id)
|
|
180
|
+
REFERENCES agent_runs_v3 (project_id, id)
|
|
181
|
+
ON DELETE RESTRICT,
|
|
182
|
+
CHECK ((execution_token IS NULL) = (execution_queue_lease_expires_at IS NULL)),
|
|
183
|
+
CHECK (
|
|
184
|
+
(
|
|
185
|
+
kind = 'conversation'
|
|
186
|
+
AND thread_id IS NOT NULL
|
|
187
|
+
AND agent_id IS NOT NULL
|
|
188
|
+
AND trigger_message_id IS NOT NULL
|
|
189
|
+
AND parent_run_id IS NULL
|
|
190
|
+
AND spawn_key IS NULL
|
|
191
|
+
AND spec IS NULL
|
|
192
|
+
AND result IS NULL
|
|
193
|
+
)
|
|
194
|
+
OR
|
|
195
|
+
(
|
|
196
|
+
kind = 'subagent'
|
|
197
|
+
AND thread_id IS NULL
|
|
198
|
+
AND agent_id IS NULL
|
|
199
|
+
AND trigger_message_id IS NULL
|
|
200
|
+
AND parent_run_id IS NOT NULL
|
|
201
|
+
AND spawn_key IS NOT NULL
|
|
202
|
+
AND spec IS NOT NULL
|
|
203
|
+
)
|
|
204
|
+
),
|
|
205
|
+
CHECK (kind <> 'subagent' OR status <> 'succeeded' OR result IS NOT NULL)
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
INSERT INTO agent_runs_v3 (
|
|
209
|
+
project_id, id, execution_id, kind, thread_id, agent_id, trigger_message_id,
|
|
210
|
+
requester_group_ids, status, model_id, finish_reason, error, diagnostics, attempt,
|
|
211
|
+
execution_token, execution_queue_lease_expires_at, created_at, started_at, completed_at
|
|
212
|
+
)
|
|
213
|
+
SELECT
|
|
214
|
+
project_id, id, execution_id, 'conversation', thread_id, agent_id, trigger_message_id,
|
|
215
|
+
requester_group_ids, status, model_id, finish_reason, error, diagnostics, attempt,
|
|
216
|
+
execution_token, execution_queue_lease_expires_at, created_at, started_at, completed_at
|
|
217
|
+
FROM agent_runs;
|
|
218
|
+
|
|
219
|
+
DROP TABLE agent_runs;
|
|
220
|
+
ALTER TABLE agent_runs_v3 RENAME TO agent_runs;
|
|
221
|
+
|
|
222
|
+
CREATE INDEX idx_agent_runs_project_started
|
|
223
|
+
ON agent_runs(project_id, COALESCE(started_at, created_at) DESC);
|
|
224
|
+
CREATE INDEX idx_agent_runs_project_thread_started
|
|
225
|
+
ON agent_runs(project_id, thread_id, COALESCE(started_at, created_at) DESC);
|
|
226
|
+
CREATE INDEX idx_agent_runs_project_agent_started
|
|
227
|
+
ON agent_runs(project_id, agent_id, COALESCE(started_at, created_at) DESC);
|
|
228
|
+
CREATE INDEX idx_agent_runs_project_status_started
|
|
229
|
+
ON agent_runs(project_id, status, COALESCE(started_at, created_at) DESC);
|
|
230
|
+
CREATE INDEX idx_agent_runs_project_parent_started
|
|
231
|
+
ON agent_runs(project_id, parent_run_id, status, COALESCE(started_at, created_at) DESC);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
CREATE TABLE agent_runs_v4 (
|
|
2
|
+
project_id TEXT NOT NULL,
|
|
3
|
+
id TEXT NOT NULL,
|
|
4
|
+
execution_id TEXT NOT NULL,
|
|
5
|
+
kind TEXT NOT NULL DEFAULT 'conversation' CHECK (kind IN ('conversation', 'subagent')),
|
|
6
|
+
thread_id TEXT,
|
|
7
|
+
agent_id TEXT,
|
|
8
|
+
trigger_message_id TEXT,
|
|
9
|
+
parent_run_id TEXT,
|
|
10
|
+
spawn_key TEXT,
|
|
11
|
+
spec TEXT CHECK (spec IS NULL OR json_valid(spec)),
|
|
12
|
+
result TEXT CHECK (result IS NULL OR json_valid(result)),
|
|
13
|
+
requester_group_ids TEXT NOT NULL DEFAULT '[]'
|
|
14
|
+
CHECK (json_valid(requester_group_ids) AND json_type(requester_group_ids) = 'array'),
|
|
15
|
+
status TEXT NOT NULL CHECK (
|
|
16
|
+
status IN ('queued', 'running', 'succeeded', 'failed', 'cancelled')
|
|
17
|
+
),
|
|
18
|
+
model_id TEXT,
|
|
19
|
+
finish_reason TEXT,
|
|
20
|
+
error TEXT CHECK (error IS NULL OR json_valid(error)),
|
|
21
|
+
diagnostics TEXT,
|
|
22
|
+
attempt INTEGER NOT NULL DEFAULT 0 CHECK (attempt >= 0),
|
|
23
|
+
execution_token TEXT,
|
|
24
|
+
execution_queue_lease_expires_at TEXT,
|
|
25
|
+
created_at TEXT NOT NULL,
|
|
26
|
+
started_at TEXT,
|
|
27
|
+
completed_at TEXT,
|
|
28
|
+
PRIMARY KEY (project_id, id),
|
|
29
|
+
UNIQUE (project_id, execution_id),
|
|
30
|
+
UNIQUE (project_id, parent_run_id, spawn_key),
|
|
31
|
+
FOREIGN KEY (project_id, execution_id)
|
|
32
|
+
REFERENCES executions (project_id, id)
|
|
33
|
+
ON DELETE RESTRICT,
|
|
34
|
+
FOREIGN KEY (project_id, parent_run_id)
|
|
35
|
+
-- Use the final name: Bun's legacy ALTER mode preserves references when foreign keys are off.
|
|
36
|
+
REFERENCES agent_runs (project_id, id)
|
|
37
|
+
ON DELETE RESTRICT,
|
|
38
|
+
CHECK ((execution_token IS NULL) = (execution_queue_lease_expires_at IS NULL)),
|
|
39
|
+
CHECK (
|
|
40
|
+
(
|
|
41
|
+
kind = 'conversation'
|
|
42
|
+
AND thread_id IS NOT NULL
|
|
43
|
+
AND agent_id IS NOT NULL
|
|
44
|
+
AND trigger_message_id IS NOT NULL
|
|
45
|
+
AND parent_run_id IS NULL
|
|
46
|
+
AND spawn_key IS NULL
|
|
47
|
+
AND result IS NULL
|
|
48
|
+
)
|
|
49
|
+
OR
|
|
50
|
+
(
|
|
51
|
+
kind = 'subagent'
|
|
52
|
+
AND thread_id IS NULL
|
|
53
|
+
AND agent_id IS NULL
|
|
54
|
+
AND trigger_message_id IS NULL
|
|
55
|
+
AND parent_run_id IS NOT NULL
|
|
56
|
+
AND spawn_key IS NOT NULL
|
|
57
|
+
AND spec IS NOT NULL
|
|
58
|
+
)
|
|
59
|
+
),
|
|
60
|
+
CHECK (kind <> 'subagent' OR status <> 'succeeded' OR result IS NOT NULL)
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
INSERT INTO agent_runs_v4 SELECT * FROM agent_runs;
|
|
64
|
+
DROP TABLE agent_runs;
|
|
65
|
+
ALTER TABLE agent_runs_v4 RENAME TO agent_runs;
|
|
66
|
+
|
|
67
|
+
CREATE INDEX idx_agent_runs_project_thread_started
|
|
68
|
+
ON agent_runs (project_id, thread_id, COALESCE(started_at, created_at) DESC, id DESC);
|
|
69
|
+
CREATE INDEX idx_agent_runs_project_status_created
|
|
70
|
+
ON agent_runs (project_id, status, created_at, id);
|
|
71
|
+
CREATE INDEX idx_agent_runs_project_parent_started
|
|
72
|
+
ON agent_runs (
|
|
73
|
+
project_id,
|
|
74
|
+
parent_run_id,
|
|
75
|
+
status,
|
|
76
|
+
COALESCE(started_at, created_at) DESC,
|
|
77
|
+
id DESC
|
|
78
|
+
);
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
DROP INDEX idx_agent_threads_project_agent_activity;
|
|
2
|
+
ALTER TABLE workflow_agent_node_runs RENAME COLUMN agent_id TO actor_id;
|
|
3
|
+
ALTER TABLE agent_threads DROP COLUMN agent_id;
|
|
4
|
+
|
|
5
|
+
CREATE TABLE agent_runs_v5 (
|
|
6
|
+
project_id TEXT NOT NULL,
|
|
7
|
+
id TEXT NOT NULL,
|
|
8
|
+
execution_id TEXT NOT NULL,
|
|
9
|
+
kind TEXT NOT NULL DEFAULT 'conversation' CHECK (kind IN ('conversation', 'subagent')),
|
|
10
|
+
thread_id TEXT,
|
|
11
|
+
trigger_message_id TEXT,
|
|
12
|
+
parent_run_id TEXT,
|
|
13
|
+
spawn_key TEXT,
|
|
14
|
+
spec TEXT CHECK (spec IS NULL OR json_valid(spec)),
|
|
15
|
+
result TEXT CHECK (result IS NULL OR json_valid(result)),
|
|
16
|
+
requester_group_ids TEXT NOT NULL DEFAULT '[]'
|
|
17
|
+
CHECK (json_valid(requester_group_ids) AND json_type(requester_group_ids) = 'array'),
|
|
18
|
+
status TEXT NOT NULL CHECK (
|
|
19
|
+
status IN ('queued', 'running', 'succeeded', 'failed', 'cancelled')
|
|
20
|
+
),
|
|
21
|
+
model_id TEXT,
|
|
22
|
+
finish_reason TEXT,
|
|
23
|
+
error TEXT CHECK (error IS NULL OR json_valid(error)),
|
|
24
|
+
diagnostics TEXT,
|
|
25
|
+
attempt INTEGER NOT NULL DEFAULT 0 CHECK (attempt >= 0),
|
|
26
|
+
execution_token TEXT,
|
|
27
|
+
execution_queue_lease_expires_at TEXT,
|
|
28
|
+
created_at TEXT NOT NULL,
|
|
29
|
+
started_at TEXT,
|
|
30
|
+
completed_at TEXT,
|
|
31
|
+
PRIMARY KEY (project_id, id),
|
|
32
|
+
UNIQUE (project_id, execution_id),
|
|
33
|
+
UNIQUE (project_id, parent_run_id, spawn_key),
|
|
34
|
+
FOREIGN KEY (project_id, execution_id)
|
|
35
|
+
REFERENCES executions (project_id, id)
|
|
36
|
+
ON DELETE RESTRICT,
|
|
37
|
+
FOREIGN KEY (project_id, parent_run_id)
|
|
38
|
+
-- Use the final name: Bun's legacy ALTER mode preserves references when foreign keys are off.
|
|
39
|
+
REFERENCES agent_runs (project_id, id)
|
|
40
|
+
ON DELETE RESTRICT,
|
|
41
|
+
CHECK ((execution_token IS NULL) = (execution_queue_lease_expires_at IS NULL)),
|
|
42
|
+
CHECK (
|
|
43
|
+
(
|
|
44
|
+
kind = 'conversation'
|
|
45
|
+
AND thread_id IS NOT NULL
|
|
46
|
+
AND trigger_message_id IS NOT NULL
|
|
47
|
+
AND parent_run_id IS NULL
|
|
48
|
+
AND spawn_key IS NULL
|
|
49
|
+
AND result IS NULL
|
|
50
|
+
)
|
|
51
|
+
OR
|
|
52
|
+
(
|
|
53
|
+
kind = 'subagent'
|
|
54
|
+
AND thread_id IS NULL
|
|
55
|
+
AND trigger_message_id IS NULL
|
|
56
|
+
AND parent_run_id IS NOT NULL
|
|
57
|
+
AND spawn_key IS NOT NULL
|
|
58
|
+
AND spec IS NOT NULL
|
|
59
|
+
)
|
|
60
|
+
),
|
|
61
|
+
CHECK (kind <> 'subagent' OR status <> 'succeeded' OR result IS NOT NULL)
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
INSERT INTO agent_runs_v5 (
|
|
65
|
+
project_id, id, execution_id, kind, thread_id, trigger_message_id, parent_run_id, spawn_key,
|
|
66
|
+
spec, result, requester_group_ids, status, model_id, finish_reason, error, diagnostics, attempt,
|
|
67
|
+
execution_token, execution_queue_lease_expires_at, created_at, started_at, completed_at
|
|
68
|
+
)
|
|
69
|
+
SELECT
|
|
70
|
+
project_id, id, execution_id, kind, thread_id, trigger_message_id, parent_run_id, spawn_key,
|
|
71
|
+
spec, result, requester_group_ids, status, model_id, finish_reason, error, diagnostics, attempt,
|
|
72
|
+
execution_token, execution_queue_lease_expires_at, created_at, started_at, completed_at
|
|
73
|
+
FROM agent_runs;
|
|
74
|
+
|
|
75
|
+
DROP TABLE agent_runs;
|
|
76
|
+
ALTER TABLE agent_runs_v5 RENAME TO agent_runs;
|
|
77
|
+
|
|
78
|
+
CREATE INDEX idx_agent_runs_project_thread_started
|
|
79
|
+
ON agent_runs (project_id, thread_id, COALESCE(started_at, created_at) DESC, id DESC);
|
|
80
|
+
CREATE INDEX idx_agent_runs_project_status_created
|
|
81
|
+
ON agent_runs (project_id, status, created_at, id);
|
|
82
|
+
CREATE INDEX idx_agent_runs_project_parent_started
|
|
83
|
+
ON agent_runs (
|
|
84
|
+
project_id,
|
|
85
|
+
parent_run_id,
|
|
86
|
+
status,
|
|
87
|
+
COALESCE(started_at, created_at) DESC,
|
|
88
|
+
id DESC
|
|
89
|
+
);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
CREATE TABLE auth_device_authorizations (
|
|
2
|
+
project_id TEXT NOT NULL,
|
|
3
|
+
id TEXT NOT NULL,
|
|
4
|
+
device_code_hash TEXT NOT NULL,
|
|
5
|
+
user_code TEXT NOT NULL,
|
|
6
|
+
client_name TEXT NOT NULL,
|
|
7
|
+
token_name TEXT NOT NULL,
|
|
8
|
+
token_expires_at TEXT NOT NULL,
|
|
9
|
+
status TEXT NOT NULL CHECK (status IN ('pending', 'approved', 'denied', 'consumed')),
|
|
10
|
+
approved_user_id TEXT,
|
|
11
|
+
approved_session_id TEXT,
|
|
12
|
+
created_at TEXT NOT NULL,
|
|
13
|
+
expires_at TEXT NOT NULL,
|
|
14
|
+
approved_at TEXT,
|
|
15
|
+
denied_at TEXT,
|
|
16
|
+
consumed_at TEXT,
|
|
17
|
+
PRIMARY KEY (project_id, id),
|
|
18
|
+
UNIQUE (project_id, user_code)
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
CREATE INDEX idx_auth_device_authorizations_pending
|
|
22
|
+
ON auth_device_authorizations(project_id, status, expires_at);
|
package/src/migrations.ts
CHANGED
|
@@ -76,6 +76,18 @@ import agentContextCheckpointsSql from "./migrations/027-agent-context-checkpoin
|
|
|
76
76
|
import objectOverrideEditTimesSql from "./migrations/028-object-override-edit-times.sql" with {
|
|
77
77
|
type: "text",
|
|
78
78
|
}
|
|
79
|
+
import modelAccountingSql from "./migrations/029-model-accounting.sql" with { type: "text" }
|
|
80
|
+
import aiUsageLimitsSql from "./migrations/030-ai-usage-limits.sql" with { type: "text" }
|
|
81
|
+
import subagentRunsSql from "./migrations/031-subagent-runs.sql" with { type: "text" }
|
|
82
|
+
import conversationRunSpecSql from "./migrations/032-conversation-run-spec.sql" with {
|
|
83
|
+
type: "text",
|
|
84
|
+
}
|
|
85
|
+
import retireAgentDefinitionsSql from "./migrations/033-retire-agent-definitions.sql" with {
|
|
86
|
+
type: "text",
|
|
87
|
+
}
|
|
88
|
+
import deviceAuthorizationsSql from "./migrations/034-device-authorizations.sql" with {
|
|
89
|
+
type: "text",
|
|
90
|
+
}
|
|
79
91
|
|
|
80
92
|
const MIGRATIONS_TABLE_SQL = `
|
|
81
93
|
CREATE TABLE IF NOT EXISTS sixb_migrations (
|
|
@@ -159,6 +171,12 @@ export const sqliteStorageMigrations = defineMigrations({
|
|
|
159
171
|
sqliteSql("026-ai-cost-accounting", aiCostAccountingSql),
|
|
160
172
|
sqliteSql("027-agent-context-checkpoints", agentContextCheckpointsSql),
|
|
161
173
|
sqliteSql("028-object-override-edit-times", objectOverrideEditTimesSql),
|
|
174
|
+
sqliteSql("029-model-accounting", modelAccountingSql),
|
|
175
|
+
sqliteSql("030-ai-usage-limits", aiUsageLimitsSql),
|
|
176
|
+
sqliteSql("031-subagent-runs", subagentRunsSql),
|
|
177
|
+
sqliteSql("032-conversation-run-spec", conversationRunSpecSql),
|
|
178
|
+
sqliteSql("033-retire-agent-definitions", retireAgentDefinitionsSql),
|
|
179
|
+
sqliteSql("034-device-authorizations", deviceAuthorizationsSql),
|
|
162
180
|
],
|
|
163
181
|
})
|
|
164
182
|
|
|
@@ -491,7 +491,7 @@ export class SqliteWorkflowAgentNodeRunStorage implements WorkflowAgentNodeRunSt
|
|
|
491
491
|
projectId: input.projectId,
|
|
492
492
|
executionId: input.executionId,
|
|
493
493
|
nodeRunId: input.nodeRunId,
|
|
494
|
-
|
|
494
|
+
actorId: input.actorId,
|
|
495
495
|
workflowExecutionId: parent.execution_id,
|
|
496
496
|
})
|
|
497
497
|
|
|
@@ -499,14 +499,14 @@ export class SqliteWorkflowAgentNodeRunStorage implements WorkflowAgentNodeRunSt
|
|
|
499
499
|
this.db
|
|
500
500
|
.query(`
|
|
501
501
|
INSERT INTO workflow_agent_node_runs (
|
|
502
|
-
project_id, node_run_id, execution_id,
|
|
502
|
+
project_id, node_run_id, execution_id, actor_id, status, prompt, attempt, created_at
|
|
503
503
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
504
504
|
`)
|
|
505
505
|
.run(
|
|
506
506
|
input.projectId,
|
|
507
507
|
input.nodeRunId,
|
|
508
508
|
input.executionId,
|
|
509
|
-
input.
|
|
509
|
+
input.actorId,
|
|
510
510
|
"queued",
|
|
511
511
|
input.prompt,
|
|
512
512
|
0,
|
|
@@ -659,9 +659,9 @@ export class SqliteWorkflowAgentNodeRunStorage implements WorkflowAgentNodeRunSt
|
|
|
659
659
|
if (hasEmptyStatuses(input)) return { runs: [], total: 0, hasMore: false }
|
|
660
660
|
const whereClauses = ["project_id = ?"]
|
|
661
661
|
const args: SqliteValue[] = [input.projectId]
|
|
662
|
-
if (input.
|
|
663
|
-
whereClauses.push("
|
|
664
|
-
args.push(input.
|
|
662
|
+
if (input.actorId) {
|
|
663
|
+
whereClauses.push("actor_id = ?")
|
|
664
|
+
args.push(input.actorId)
|
|
665
665
|
}
|
|
666
666
|
appendRunListFilters(whereClauses, args, input)
|
|
667
667
|
const result = queryRunList<WorkflowAgentNodeRunDatabaseRow>({
|
|
@@ -1073,7 +1073,7 @@ interface WorkflowAgentNodeRunDatabaseRow {
|
|
|
1073
1073
|
project_id: string
|
|
1074
1074
|
node_run_id: string
|
|
1075
1075
|
execution_id: string
|
|
1076
|
-
|
|
1076
|
+
actor_id: string
|
|
1077
1077
|
status: WorkflowAgentNodeRunRecord["status"]
|
|
1078
1078
|
prompt: string
|
|
1079
1079
|
model_id: string | null
|
|
@@ -1107,7 +1107,7 @@ function rowToWorkflowAgentNodeRunRecord(
|
|
|
1107
1107
|
projectId: row.project_id,
|
|
1108
1108
|
nodeRunId: row.node_run_id,
|
|
1109
1109
|
executionId: row.execution_id,
|
|
1110
|
-
|
|
1110
|
+
actorId: row.actor_id,
|
|
1111
1111
|
status: row.status,
|
|
1112
1112
|
prompt: row.prompt,
|
|
1113
1113
|
...(row.model_id ? { modelId: row.model_id } : {}),
|