feat(console): add initial console for Cursor BYOK with provider management and LLM call tracking

This commit is contained in:
leookun
2026-08-17 10:14:10 +08:00
parent 4db2061611
commit c96cb0a110
220 changed files with 29466 additions and 10769 deletions
+99 -65
View File
@@ -1,38 +1,121 @@
PRAGMA foreign_keys = ON;
CREATE TABLE IF NOT EXISTS conversations (
CREATE TABLE conversations (
conversation_id TEXT PRIMARY KEY,
revision INTEGER NOT NULL DEFAULT 0,
head_blob_id BLOB,
current_revision_id INTEGER,
active_run_id TEXT,
updated_at_ms INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS messages (
CREATE TABLE messages (
conversation_id TEXT NOT NULL,
message_seq INTEGER NOT NULL,
message_id TEXT NOT NULL,
role TEXT NOT NULL,
origin TEXT NOT NULL,
payload_json TEXT NOT NULL,
runtime_event_id TEXT,
created_at_ms INTEGER NOT NULL,
PRIMARY KEY (conversation_id, message_seq),
UNIQUE (conversation_id, message_id),
UNIQUE (conversation_id, runtime_event_id),
PRIMARY KEY (conversation_id, message_id),
FOREIGN KEY (conversation_id) REFERENCES conversations(conversation_id)
);
CREATE INDEX IF NOT EXISTS messages_conversation_seq
ON messages(conversation_id, message_seq);
CREATE UNIQUE INDEX messages_runtime_event
ON messages(conversation_id, runtime_event_id)
WHERE runtime_event_id IS NOT NULL;
CREATE TABLE IF NOT EXISTS blobs (
blob_id BLOB PRIMARY KEY CHECK(length(blob_id) = 32),
data BLOB NOT NULL,
CREATE TABLE conversation_revisions (
revision_id INTEGER PRIMARY KEY AUTOINCREMENT,
conversation_id TEXT NOT NULL,
parent_revision_id INTEGER,
state_digest BLOB NOT NULL CHECK(length(state_digest) = 32),
created_at_ms INTEGER NOT NULL,
CHECK(length(data) >= 0)
UNIQUE (conversation_id, state_digest),
FOREIGN KEY (conversation_id) REFERENCES conversations(conversation_id),
FOREIGN KEY (parent_revision_id) REFERENCES conversation_revisions(revision_id)
);
CREATE TABLE IF NOT EXISTS blob_edges (
CREATE INDEX conversation_revisions_parent
ON conversation_revisions(conversation_id, parent_revision_id);
CREATE TABLE revision_messages (
revision_id INTEGER NOT NULL,
ordinal INTEGER NOT NULL,
conversation_id TEXT NOT NULL,
message_id TEXT NOT NULL,
PRIMARY KEY (revision_id, ordinal),
UNIQUE (revision_id, message_id),
FOREIGN KEY (revision_id) REFERENCES conversation_revisions(revision_id),
FOREIGN KEY (conversation_id, message_id) REFERENCES messages(conversation_id, message_id)
);
CREATE TABLE runs (
run_id TEXT PRIMARY KEY,
conversation_id TEXT NOT NULL,
base_revision_id INTEGER NOT NULL,
head_revision_id INTEGER NOT NULL,
parent_run_id TEXT,
parent_tool_call_id TEXT,
run_kind TEXT NOT NULL,
subagent_kind TEXT,
status TEXT NOT NULL,
provider_call_index INTEGER NOT NULL DEFAULT -1,
turn_usage_json TEXT NOT NULL DEFAULT 'null',
failure_category TEXT,
failure_summary TEXT,
created_at_ms INTEGER NOT NULL,
updated_at_ms INTEGER NOT NULL,
FOREIGN KEY (conversation_id) REFERENCES conversations(conversation_id),
FOREIGN KEY (base_revision_id) REFERENCES conversation_revisions(revision_id),
FOREIGN KEY (head_revision_id) REFERENCES conversation_revisions(revision_id)
);
CREATE INDEX runs_conversation_status
ON runs(conversation_id, status);
CREATE TABLE tool_rounds (
round_id TEXT PRIMARY KEY,
run_id TEXT NOT NULL,
base_revision_id INTEGER NOT NULL,
assistant_json TEXT NOT NULL,
status TEXT NOT NULL,
version INTEGER NOT NULL DEFAULT 0,
next_completion_seq INTEGER NOT NULL DEFAULT 0,
created_at_ms INTEGER NOT NULL,
updated_at_ms INTEGER NOT NULL,
FOREIGN KEY (run_id) REFERENCES runs(run_id),
FOREIGN KEY (base_revision_id) REFERENCES conversation_revisions(revision_id)
);
CREATE INDEX tool_rounds_run_status
ON tool_rounds(run_id, status);
CREATE TABLE tool_round_calls (
round_id TEXT NOT NULL,
call_index INTEGER NOT NULL,
call_id TEXT NOT NULL,
model_call_id TEXT NOT NULL,
name TEXT NOT NULL,
arguments_json TEXT NOT NULL,
status TEXT NOT NULL,
completion_seq INTEGER,
result_content TEXT,
result_is_error INTEGER,
committed_revision_id INTEGER,
completed_at_ms INTEGER,
PRIMARY KEY (round_id, call_index),
UNIQUE (round_id, call_id),
UNIQUE (round_id, completion_seq),
FOREIGN KEY (round_id) REFERENCES tool_rounds(round_id),
FOREIGN KEY (committed_revision_id) REFERENCES conversation_revisions(revision_id)
);
CREATE TABLE blobs (
blob_id BLOB PRIMARY KEY CHECK(length(blob_id) = 32),
data BLOB NOT NULL,
created_at_ms INTEGER NOT NULL
);
CREATE TABLE blob_edges (
parent_blob_id BLOB NOT NULL,
child_blob_id BLOB NOT NULL,
field_name TEXT NOT NULL,
@@ -41,53 +124,4 @@ CREATE TABLE IF NOT EXISTS blob_edges (
FOREIGN KEY (child_blob_id) REFERENCES blobs(blob_id)
);
CREATE INDEX IF NOT EXISTS blob_edges_child ON blob_edges(child_blob_id);
CREATE TABLE IF NOT EXISTS runs (
request_id TEXT PRIMARY KEY,
run_id TEXT,
conversation_id TEXT,
revision INTEGER,
append_seqno INTEGER NOT NULL DEFAULT -1,
status TEXT NOT NULL,
provider_call_index INTEGER NOT NULL DEFAULT 0,
turn_usage_json TEXT NOT NULL DEFAULT '{}',
created_at_ms INTEGER NOT NULL,
updated_at_ms INTEGER NOT NULL,
FOREIGN KEY (conversation_id) REFERENCES conversations(conversation_id)
);
CREATE INDEX IF NOT EXISTS runs_conversation_status
ON runs(conversation_id, status);
CREATE TABLE IF NOT EXISTS run_tool_results (
request_id TEXT NOT NULL,
batch_index INTEGER NOT NULL,
call_index INTEGER NOT NULL,
completion_seq INTEGER NOT NULL,
call_id TEXT NOT NULL,
output_json TEXT NOT NULL,
is_error INTEGER NOT NULL,
completed_at_ms INTEGER NOT NULL,
PRIMARY KEY (request_id, batch_index, call_index),
UNIQUE (request_id, call_id),
FOREIGN KEY (request_id) REFERENCES runs(request_id)
);
CREATE TABLE IF NOT EXISTS outbox (
outbox_id INTEGER PRIMARY KEY AUTOINCREMENT,
request_id TEXT NOT NULL,
operation_key TEXT NOT NULL,
operation_kind TEXT NOT NULL,
payload BLOB NOT NULL,
dependency_blob_ids_json TEXT NOT NULL DEFAULT '[]',
attempts INTEGER NOT NULL DEFAULT 0,
acked_at_ms INTEGER,
created_at_ms INTEGER NOT NULL,
updated_at_ms INTEGER NOT NULL,
UNIQUE(request_id, operation_key),
FOREIGN KEY (request_id) REFERENCES runs(request_id)
);
CREATE INDEX IF NOT EXISTS outbox_pending
ON outbox(request_id, acked_at_ms, outbox_id);
CREATE INDEX blob_edges_child ON blob_edges(child_blob_id);
@@ -0,0 +1,9 @@
CREATE TABLE input_anchors (
conversation_id TEXT NOT NULL,
input_id TEXT NOT NULL,
base_revision_id INTEGER NOT NULL,
created_at_ms INTEGER NOT NULL,
PRIMARY KEY (conversation_id, input_id),
FOREIGN KEY (conversation_id) REFERENCES conversations(conversation_id),
FOREIGN KEY (base_revision_id) REFERENCES conversation_revisions(revision_id)
);
@@ -0,0 +1,103 @@
CREATE TABLE provider_endpoints (
provider_id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
provider_type TEXT NOT NULL,
base_url TEXT NOT NULL,
api_key TEXT NOT NULL,
custom_headers_json TEXT NOT NULL DEFAULT '{}',
created_at_ms INTEGER NOT NULL,
updated_at_ms INTEGER NOT NULL
);
CREATE TABLE provider_models (
model_hash TEXT PRIMARY KEY CHECK(length(model_hash) = 8),
provider_id INTEGER NOT NULL,
model_id TEXT NOT NULL,
display_name TEXT NOT NULL,
enabled INTEGER NOT NULL DEFAULT 1,
sort_order INTEGER NOT NULL DEFAULT 0,
context_window_tokens INTEGER,
max_output_tokens INTEGER,
reasoning_enabled INTEGER NOT NULL DEFAULT 0,
reasoning_effort TEXT,
extra_params_json TEXT NOT NULL DEFAULT '{}',
created_at_ms INTEGER NOT NULL,
updated_at_ms INTEGER NOT NULL,
UNIQUE(provider_id, model_id),
FOREIGN KEY(provider_id) REFERENCES provider_endpoints(provider_id) ON DELETE CASCADE
);
CREATE INDEX provider_models_enabled_sort
ON provider_models(enabled, sort_order, display_name);
CREATE TABLE service_settings (
setting_key TEXT PRIMARY KEY,
value_json TEXT NOT NULL,
updated_at_ms INTEGER NOT NULL
);
INSERT INTO service_settings(setting_key, value_json, updated_at_ms)
VALUES ('llm_detailed_logging', 'false', unixepoch('subsec') * 1000);
CREATE TABLE llm_calls (
call_id TEXT PRIMARY KEY,
run_id TEXT NOT NULL,
conversation_id TEXT NOT NULL,
provider_call_index INTEGER NOT NULL,
model_hash TEXT,
provider_type TEXT NOT NULL,
provider_url TEXT NOT NULL,
model_id TEXT NOT NULL,
display_name TEXT NOT NULL,
status TEXT NOT NULL,
finish_reason TEXT,
created_at_ms INTEGER NOT NULL,
request_started_at_ms INTEGER,
response_headers_at_ms INTEGER,
first_event_at_ms INTEGER,
first_text_at_ms INTEGER,
finished_at_ms INTEGER,
queue_ms INTEGER,
ttfb_ms INTEGER,
ttft_ms INTEGER,
duration_ms INTEGER,
input_tokens INTEGER,
output_tokens INTEGER,
total_tokens INTEGER,
cache_read_tokens INTEGER,
cache_write_tokens INTEGER,
reasoning_tokens INTEGER,
usage_json TEXT,
message_count INTEGER NOT NULL,
tool_count INTEGER NOT NULL,
request_bytes INTEGER,
response_bytes INTEGER NOT NULL DEFAULT 0,
stream_event_count INTEGER NOT NULL DEFAULT 0,
http_status INTEGER,
error_kind TEXT,
error_message TEXT,
detailed INTEGER NOT NULL,
FOREIGN KEY(model_hash) REFERENCES provider_models(model_hash)
);
CREATE INDEX llm_calls_created ON llm_calls(created_at_ms DESC);
CREATE INDEX llm_calls_run ON llm_calls(run_id, provider_call_index);
CREATE INDEX llm_calls_model ON llm_calls(model_hash, created_at_ms DESC);
CREATE TABLE llm_call_requests (
call_id TEXT PRIMARY KEY,
headers_json TEXT NOT NULL,
body_json TEXT NOT NULL,
byte_count INTEGER NOT NULL,
FOREIGN KEY(call_id) REFERENCES llm_calls(call_id) ON DELETE CASCADE
);
CREATE TABLE llm_call_response_chunks (
call_id TEXT NOT NULL,
seq INTEGER NOT NULL,
received_offset_ms INTEGER NOT NULL,
data BLOB NOT NULL,
byte_count INTEGER NOT NULL,
PRIMARY KEY(call_id, seq),
FOREIGN KEY(call_id) REFERENCES llm_calls(call_id) ON DELETE CASCADE
);