Spaces:
Running
Running
File size: 4,803 Bytes
4dc70fb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | -- OpenCode Tables for Supabase
-- Run this in Supabase SQL Editor
-- Sessions table
CREATE TABLE IF NOT EXISTS opencode_sessions (
id TEXT PRIMARY KEY,
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
title TEXT NOT NULL,
agent_id TEXT DEFAULT 'build',
provider_id TEXT,
model_id TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_opencode_sessions_user_id ON opencode_sessions(user_id);
CREATE INDEX IF NOT EXISTS idx_opencode_sessions_updated_at ON opencode_sessions(updated_at DESC);
-- Messages table
CREATE TABLE IF NOT EXISTS opencode_messages (
id TEXT PRIMARY KEY,
session_id TEXT NOT NULL REFERENCES opencode_sessions(id) ON DELETE CASCADE,
role TEXT NOT NULL CHECK (role IN ('user', 'assistant')),
content TEXT,
provider_id TEXT,
model_id TEXT,
input_tokens INTEGER,
output_tokens INTEGER,
error TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_opencode_messages_session_id ON opencode_messages(session_id);
CREATE INDEX IF NOT EXISTS idx_opencode_messages_created_at ON opencode_messages(session_id, created_at);
-- Message parts (text, tool_call, tool_result)
CREATE TABLE IF NOT EXISTS opencode_message_parts (
id TEXT PRIMARY KEY,
message_id TEXT NOT NULL REFERENCES opencode_messages(id) ON DELETE CASCADE,
type TEXT NOT NULL CHECK (type IN ('text', 'tool_call', 'tool_result')),
content TEXT,
tool_call_id TEXT,
tool_name TEXT,
tool_args JSONB,
tool_output TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_opencode_message_parts_message_id ON opencode_message_parts(message_id);
-- Usage tracking (replaces sandbox_usage)
CREATE TABLE IF NOT EXISTS opencode_usage (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
usage_date DATE NOT NULL DEFAULT CURRENT_DATE,
input_tokens INTEGER DEFAULT 0,
output_tokens INTEGER DEFAULT 0,
request_count INTEGER DEFAULT 0,
UNIQUE(user_id, usage_date)
);
CREATE INDEX IF NOT EXISTS idx_opencode_usage_user_date ON opencode_usage(user_id, usage_date);
-- Row Level Security
ALTER TABLE opencode_sessions ENABLE ROW LEVEL SECURITY;
ALTER TABLE opencode_messages ENABLE ROW LEVEL SECURITY;
ALTER TABLE opencode_message_parts ENABLE ROW LEVEL SECURITY;
ALTER TABLE opencode_usage ENABLE ROW LEVEL SECURITY;
-- RLS Policies: Users can only access their own data
CREATE POLICY "Users can CRUD their own sessions"
ON opencode_sessions FOR ALL
USING (auth.uid() = user_id);
CREATE POLICY "Users can CRUD messages in their sessions"
ON opencode_messages FOR ALL
USING (
EXISTS (
SELECT 1 FROM opencode_sessions
WHERE opencode_sessions.id = opencode_messages.session_id
AND opencode_sessions.user_id = auth.uid()
)
);
CREATE POLICY "Users can CRUD parts in their messages"
ON opencode_message_parts FOR ALL
USING (
EXISTS (
SELECT 1 FROM opencode_messages
JOIN opencode_sessions ON opencode_sessions.id = opencode_messages.session_id
WHERE opencode_messages.id = opencode_message_parts.message_id
AND opencode_sessions.user_id = auth.uid()
)
);
CREATE POLICY "Users can access their own usage"
ON opencode_usage FOR ALL
USING (auth.uid() = user_id);
-- Function to increment usage (atomic)
CREATE OR REPLACE FUNCTION increment_opencode_usage(
p_user_id UUID,
p_input_tokens INTEGER DEFAULT 0,
p_output_tokens INTEGER DEFAULT 0
)
RETURNS void AS $$
BEGIN
INSERT INTO opencode_usage (user_id, usage_date, input_tokens, output_tokens, request_count)
VALUES (p_user_id, CURRENT_DATE, p_input_tokens, p_output_tokens, 1)
ON CONFLICT (user_id, usage_date)
DO UPDATE SET
input_tokens = opencode_usage.input_tokens + EXCLUDED.input_tokens,
output_tokens = opencode_usage.output_tokens + EXCLUDED.output_tokens,
request_count = opencode_usage.request_count + 1;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Function to get daily usage
CREATE OR REPLACE FUNCTION get_opencode_usage(p_user_id UUID)
RETURNS TABLE(input_tokens INTEGER, output_tokens INTEGER, request_count INTEGER) AS $$
BEGIN
RETURN QUERY
SELECT
COALESCE(u.input_tokens, 0)::INTEGER,
COALESCE(u.output_tokens, 0)::INTEGER,
COALESCE(u.request_count, 0)::INTEGER
FROM opencode_usage u
WHERE u.user_id = p_user_id AND u.usage_date = CURRENT_DATE;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Update timestamp trigger
CREATE OR REPLACE FUNCTION update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER opencode_sessions_updated_at
BEFORE UPDATE ON opencode_sessions
FOR EACH ROW EXECUTE FUNCTION update_updated_at();
|