agentdev-webui 1.0.0

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 (39) hide show
  1. package/lib/agent-api.js +530 -0
  2. package/lib/auth.js +127 -0
  3. package/lib/config.js +53 -0
  4. package/lib/database.js +762 -0
  5. package/lib/device-flow.js +257 -0
  6. package/lib/email.js +420 -0
  7. package/lib/encryption.js +112 -0
  8. package/lib/github.js +339 -0
  9. package/lib/history.js +143 -0
  10. package/lib/pwa.js +107 -0
  11. package/lib/redis-logs.js +226 -0
  12. package/lib/routes.js +680 -0
  13. package/migrations/000_create_database.sql +33 -0
  14. package/migrations/001_create_agentdev_schema.sql +135 -0
  15. package/migrations/001_create_agentdev_schema.sql.old +100 -0
  16. package/migrations/001_create_agentdev_schema_fixed.sql +135 -0
  17. package/migrations/002_add_github_token.sql +17 -0
  18. package/migrations/003_add_agent_logs_table.sql +23 -0
  19. package/migrations/004_remove_oauth_columns.sql +11 -0
  20. package/migrations/005_add_projects.sql +44 -0
  21. package/migrations/006_project_github_token.sql +7 -0
  22. package/migrations/007_project_repositories.sql +12 -0
  23. package/migrations/008_add_notifications.sql +20 -0
  24. package/migrations/009_unified_oauth.sql +153 -0
  25. package/migrations/README.md +97 -0
  26. package/package.json +37 -0
  27. package/public/css/styles.css +1140 -0
  28. package/public/device.html +384 -0
  29. package/public/docs.html +862 -0
  30. package/public/docs.md +697 -0
  31. package/public/favicon.svg +5 -0
  32. package/public/index.html +271 -0
  33. package/public/js/app.js +2379 -0
  34. package/public/login.html +224 -0
  35. package/public/profile.html +394 -0
  36. package/public/register.html +392 -0
  37. package/public/reset-password.html +349 -0
  38. package/public/verify-email.html +177 -0
  39. package/server.js +1450 -0
@@ -0,0 +1,33 @@
1
+ -- Create separate AgentDev database
2
+ -- Run with: psql -h localhost -p 6432 -U postgres -f migrations/000_create_database.sql
3
+
4
+ -- Create database
5
+ CREATE DATABASE agentdev OWNER postgres;
6
+
7
+ -- Create dedicated user
8
+ CREATE USER agentdev WITH PASSWORD 'agentdev_secure_password_change_me';
9
+
10
+ -- Grant privileges
11
+ GRANT CONNECT ON DATABASE agentdev TO agentdev;
12
+ GRANT ALL PRIVILEGES ON DATABASE agentdev TO agentdev;
13
+
14
+ \c agentdev
15
+
16
+ -- Grant schema privileges
17
+ GRANT ALL PRIVILEGES ON SCHEMA public TO agentdev;
18
+ GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO agentdev;
19
+ GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO agentdev;
20
+
21
+ -- Set default privileges for future tables
22
+ ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO agentdev;
23
+ ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO agentdev;
24
+
25
+ -- Create uuid extension (useful for future)
26
+ CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
27
+
28
+ -- Success message
29
+ \echo '✓ Database agentdev created successfully'
30
+ \echo '✓ User agentdev created with full privileges'
31
+ \echo ''
32
+ \echo 'Next step: Run migrations/001_create_agentdev_schema.sql'
33
+ \echo ' psql -h localhost -p 6432 -U agentdev -d agentdev -f migrations/001_create_agentdev_schema.sql'
@@ -0,0 +1,135 @@
1
+ -- AgentDev Distributed System Database Schema
2
+ -- Fixed version without circular foreign key dependencies
3
+
4
+ BEGIN;
5
+
6
+ -- Users table (extends existing authentication)
7
+ CREATE TABLE IF NOT EXISTS agentdev_users (
8
+ id SERIAL PRIMARY KEY,
9
+ email VARCHAR(255) UNIQUE NOT NULL,
10
+ password_hash VARCHAR(255) NOT NULL,
11
+ github_oauth_client_id TEXT,
12
+ github_oauth_client_secret_encrypted TEXT,
13
+ github_oauth_scopes TEXT[] DEFAULT ARRAY['repo', 'read:org', 'project'],
14
+ max_agents INT DEFAULT 3,
15
+ created_at TIMESTAMPTZ DEFAULT NOW(),
16
+ updated_at TIMESTAMPTZ DEFAULT NOW()
17
+ );
18
+
19
+ CREATE INDEX IF NOT EXISTS idx_agentdev_users_email ON agentdev_users(email);
20
+
21
+ -- Agents table (without current_ticket_id FK first)
22
+ CREATE TABLE IF NOT EXISTS agentdev_agents (
23
+ id VARCHAR(64) PRIMARY KEY,
24
+ user_id INT NOT NULL REFERENCES agentdev_users(id) ON DELETE CASCADE,
25
+ name VARCHAR(100) NOT NULL,
26
+ hostname VARCHAR(128),
27
+ status VARCHAR(20) DEFAULT 'offline' CHECK (status IN ('offline', 'idle', 'busy')),
28
+ current_ticket_id INT, -- FK will be added later
29
+ last_heartbeat TIMESTAMPTZ,
30
+ registered_at TIMESTAMPTZ DEFAULT NOW(),
31
+ capabilities JSONB DEFAULT '{}'::jsonb,
32
+ access_token_hash VARCHAR(255)
33
+ );
34
+
35
+ CREATE INDEX IF NOT EXISTS idx_agentdev_agents_user ON agentdev_agents(user_id);
36
+ CREATE INDEX IF NOT EXISTS idx_agentdev_agents_status ON agentdev_agents(status);
37
+ CREATE INDEX IF NOT EXISTS idx_agentdev_agents_heartbeat ON agentdev_agents(last_heartbeat);
38
+
39
+ -- Tickets table (without assigned_agent_id FK first)
40
+ CREATE TABLE IF NOT EXISTS agentdev_tickets (
41
+ id SERIAL PRIMARY KEY,
42
+ github_issue_number INT NOT NULL,
43
+ github_repo VARCHAR(100) NOT NULL,
44
+ github_project_item_id VARCHAR(100),
45
+ status VARCHAR(20) DEFAULT 'todo' CHECK (status IN ('todo', 'assigned', 'in_progress', 'completed', 'failed')),
46
+ assigned_agent_id VARCHAR(64), -- FK will be added later
47
+ assigned_at TIMESTAMPTZ,
48
+ priority INT DEFAULT 5,
49
+ created_at TIMESTAMPTZ DEFAULT NOW(),
50
+ completed_at TIMESTAMPTZ,
51
+ error_message TEXT,
52
+ UNIQUE(github_repo, github_issue_number)
53
+ );
54
+
55
+ CREATE INDEX IF NOT EXISTS idx_agentdev_tickets_status ON agentdev_tickets(status);
56
+ CREATE INDEX IF NOT EXISTS idx_agentdev_tickets_assigned ON agentdev_tickets(assigned_agent_id);
57
+ CREATE INDEX IF NOT EXISTS idx_agentdev_tickets_priority ON agentdev_tickets(priority DESC);
58
+
59
+ -- Now add the circular foreign keys
60
+ DO $$
61
+ BEGIN
62
+ -- Add FK from agents to tickets
63
+ IF NOT EXISTS (
64
+ SELECT 1 FROM information_schema.table_constraints
65
+ WHERE constraint_name = 'fk_current_ticket'
66
+ AND table_name = 'agentdev_agents'
67
+ ) THEN
68
+ ALTER TABLE agentdev_agents
69
+ ADD CONSTRAINT fk_current_ticket
70
+ FOREIGN KEY (current_ticket_id)
71
+ REFERENCES agentdev_tickets(id)
72
+ ON DELETE SET NULL
73
+ DEFERRABLE INITIALLY DEFERRED;
74
+ END IF;
75
+
76
+ -- Add FK from tickets to agents
77
+ IF NOT EXISTS (
78
+ SELECT 1 FROM information_schema.table_constraints
79
+ WHERE constraint_name = 'fk_assigned_agent'
80
+ AND table_name = 'agentdev_tickets'
81
+ ) THEN
82
+ ALTER TABLE agentdev_tickets
83
+ ADD CONSTRAINT fk_assigned_agent
84
+ FOREIGN KEY (assigned_agent_id)
85
+ REFERENCES agentdev_agents(id)
86
+ ON DELETE SET NULL;
87
+ END IF;
88
+ END $$;
89
+
90
+ -- Agent logs table (optional - for persistent storage beyond Redis)
91
+ CREATE TABLE IF NOT EXISTS agentdev_logs (
92
+ id BIGSERIAL PRIMARY KEY,
93
+ agent_id VARCHAR(64) NOT NULL REFERENCES agentdev_agents(id) ON DELETE CASCADE,
94
+ ticket_id INT REFERENCES agentdev_tickets(id) ON DELETE CASCADE,
95
+ timestamp TIMESTAMPTZ DEFAULT NOW(),
96
+ level VARCHAR(10) DEFAULT 'INFO' CHECK (level IN ('DEBUG', 'INFO', 'WARN', 'ERROR')),
97
+ content TEXT NOT NULL
98
+ );
99
+
100
+ CREATE INDEX IF NOT EXISTS idx_agentdev_logs_agent_time ON agentdev_logs(agent_id, timestamp DESC);
101
+ CREATE INDEX IF NOT EXISTS idx_agentdev_logs_ticket ON agentdev_logs(ticket_id);
102
+
103
+ -- Device authorization table (for OAuth device flow)
104
+ CREATE TABLE IF NOT EXISTS agentdev_device_codes (
105
+ device_code VARCHAR(64) PRIMARY KEY,
106
+ user_code VARCHAR(16) UNIQUE NOT NULL,
107
+ user_id INT REFERENCES agentdev_users(id) ON DELETE CASCADE,
108
+ status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'denied', 'expired')),
109
+ agent_name VARCHAR(100),
110
+ agent_capabilities JSONB,
111
+ created_at TIMESTAMPTZ DEFAULT NOW(),
112
+ expires_at TIMESTAMPTZ NOT NULL
113
+ );
114
+
115
+ CREATE INDEX IF NOT EXISTS idx_agentdev_device_codes_user_code ON agentdev_device_codes(user_code);
116
+ CREATE INDEX IF NOT EXISTS idx_agentdev_device_codes_expires ON agentdev_device_codes(expires_at);
117
+
118
+ -- Auto-update updated_at timestamp
119
+ CREATE OR REPLACE FUNCTION update_updated_at_column()
120
+ RETURNS TRIGGER AS $$
121
+ BEGIN
122
+ NEW.updated_at = NOW();
123
+ RETURN NEW;
124
+ END;
125
+ $$ language 'plpgsql';
126
+
127
+ DROP TRIGGER IF EXISTS update_agentdev_users_updated_at ON agentdev_users;
128
+ CREATE TRIGGER update_agentdev_users_updated_at BEFORE UPDATE ON agentdev_users
129
+ FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
130
+
131
+ -- Grant permissions
132
+ GRANT ALL ON ALL TABLES IN SCHEMA public TO agentdev;
133
+ GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO agentdev;
134
+
135
+ COMMIT;
@@ -0,0 +1,100 @@
1
+ -- AgentDev Distributed System Database Schema
2
+ -- Run with: psql -U agentdev -d datatamer -f migrations/001_create_agentdev_schema.sql
3
+
4
+ BEGIN;
5
+
6
+ -- Users table (extends existing authentication)
7
+ CREATE TABLE IF NOT EXISTS agentdev_users (
8
+ id SERIAL PRIMARY KEY,
9
+ email VARCHAR(255) UNIQUE NOT NULL,
10
+ password_hash VARCHAR(255) NOT NULL,
11
+ github_oauth_client_id TEXT,
12
+ github_oauth_client_secret_encrypted TEXT,
13
+ github_oauth_scopes TEXT[] DEFAULT ARRAY['repo', 'read:org', 'project'],
14
+ max_agents INT DEFAULT 3,
15
+ created_at TIMESTAMPTZ DEFAULT NOW(),
16
+ updated_at TIMESTAMPTZ DEFAULT NOW()
17
+ );
18
+
19
+ CREATE INDEX idx_agentdev_users_email ON agentdev_users(email);
20
+
21
+ -- Agents table
22
+ CREATE TABLE IF NOT EXISTS agentdev_agents (
23
+ id VARCHAR(64) PRIMARY KEY,
24
+ user_id INT NOT NULL REFERENCES agentdev_users(id) ON DELETE CASCADE,
25
+ name VARCHAR(100) NOT NULL,
26
+ hostname VARCHAR(128),
27
+ status VARCHAR(20) DEFAULT 'offline' CHECK (status IN ('offline', 'idle', 'busy')),
28
+ current_ticket_id INT,
29
+ last_heartbeat TIMESTAMPTZ,
30
+ registered_at TIMESTAMPTZ DEFAULT NOW(),
31
+ capabilities JSONB DEFAULT '{}'::jsonb,
32
+ access_token_hash VARCHAR(255),
33
+ CONSTRAINT fk_current_ticket FOREIGN KEY (current_ticket_id) REFERENCES agentdev_tickets(id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED
34
+ );
35
+
36
+ CREATE INDEX idx_agentdev_agents_user ON agentdev_agents(user_id);
37
+ CREATE INDEX idx_agentdev_agents_status ON agentdev_agents(status);
38
+ CREATE INDEX idx_agentdev_agents_heartbeat ON agentdev_agents(last_heartbeat);
39
+
40
+ -- Tickets table
41
+ CREATE TABLE IF NOT EXISTS agentdev_tickets (
42
+ id SERIAL PRIMARY KEY,
43
+ github_issue_number INT NOT NULL,
44
+ github_repo VARCHAR(100) NOT NULL,
45
+ github_project_item_id VARCHAR(100),
46
+ status VARCHAR(20) DEFAULT 'todo' CHECK (status IN ('todo', 'assigned', 'in_progress', 'completed', 'failed')),
47
+ assigned_agent_id VARCHAR(64) REFERENCES agentdev_agents(id) ON DELETE SET NULL,
48
+ assigned_at TIMESTAMPTZ,
49
+ priority INT DEFAULT 5,
50
+ created_at TIMESTAMPTZ DEFAULT NOW(),
51
+ completed_at TIMESTAMPTZ,
52
+ error_message TEXT,
53
+ UNIQUE(github_repo, github_issue_number)
54
+ );
55
+
56
+ CREATE INDEX idx_agentdev_tickets_status ON agentdev_tickets(status);
57
+ CREATE INDEX idx_agentdev_tickets_assigned ON agentdev_tickets(assigned_agent_id);
58
+ CREATE INDEX idx_agentdev_tickets_priority ON agentdev_tickets(priority DESC);
59
+
60
+ -- Agent logs table (optional - for persistent storage beyond Redis)
61
+ CREATE TABLE IF NOT EXISTS agentdev_logs (
62
+ id BIGSERIAL PRIMARY KEY,
63
+ agent_id VARCHAR(64) NOT NULL REFERENCES agentdev_agents(id) ON DELETE CASCADE,
64
+ ticket_id INT REFERENCES agentdev_tickets(id) ON DELETE CASCADE,
65
+ timestamp TIMESTAMPTZ DEFAULT NOW(),
66
+ level VARCHAR(10) DEFAULT 'INFO' CHECK (level IN ('DEBUG', 'INFO', 'WARN', 'ERROR')),
67
+ content TEXT NOT NULL
68
+ );
69
+
70
+ CREATE INDEX idx_agentdev_logs_agent_time ON agentdev_logs(agent_id, timestamp DESC);
71
+ CREATE INDEX idx_agentdev_logs_ticket ON agentdev_logs(ticket_id);
72
+
73
+ -- Device authorization table (for OAuth device flow)
74
+ CREATE TABLE IF NOT EXISTS agentdev_device_codes (
75
+ device_code VARCHAR(64) PRIMARY KEY,
76
+ user_code VARCHAR(16) UNIQUE NOT NULL,
77
+ user_id INT REFERENCES agentdev_users(id) ON DELETE CASCADE,
78
+ status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'denied', 'expired')),
79
+ agent_name VARCHAR(100),
80
+ agent_capabilities JSONB,
81
+ created_at TIMESTAMPTZ DEFAULT NOW(),
82
+ expires_at TIMESTAMPTZ NOT NULL
83
+ );
84
+
85
+ CREATE INDEX idx_agentdev_device_codes_user_code ON agentdev_device_codes(user_code);
86
+ CREATE INDEX idx_agentdev_device_codes_expires ON agentdev_device_codes(expires_at);
87
+
88
+ -- Auto-update updated_at timestamp
89
+ CREATE OR REPLACE FUNCTION update_updated_at_column()
90
+ RETURNS TRIGGER AS $$
91
+ BEGIN
92
+ NEW.updated_at = NOW();
93
+ RETURN NEW;
94
+ END;
95
+ $$ language 'plpgsql';
96
+
97
+ CREATE TRIGGER update_agentdev_users_updated_at BEFORE UPDATE ON agentdev_users
98
+ FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
99
+
100
+ COMMIT;
@@ -0,0 +1,135 @@
1
+ -- AgentDev Distributed System Database Schema
2
+ -- Fixed version without circular foreign key dependencies
3
+
4
+ BEGIN;
5
+
6
+ -- Users table (extends existing authentication)
7
+ CREATE TABLE IF NOT EXISTS agentdev_users (
8
+ id SERIAL PRIMARY KEY,
9
+ email VARCHAR(255) UNIQUE NOT NULL,
10
+ password_hash VARCHAR(255) NOT NULL,
11
+ github_oauth_client_id TEXT,
12
+ github_oauth_client_secret_encrypted TEXT,
13
+ github_oauth_scopes TEXT[] DEFAULT ARRAY['repo', 'read:org', 'project'],
14
+ max_agents INT DEFAULT 3,
15
+ created_at TIMESTAMPTZ DEFAULT NOW(),
16
+ updated_at TIMESTAMPTZ DEFAULT NOW()
17
+ );
18
+
19
+ CREATE INDEX IF NOT EXISTS idx_agentdev_users_email ON agentdev_users(email);
20
+
21
+ -- Agents table (without current_ticket_id FK first)
22
+ CREATE TABLE IF NOT EXISTS agentdev_agents (
23
+ id VARCHAR(64) PRIMARY KEY,
24
+ user_id INT NOT NULL REFERENCES agentdev_users(id) ON DELETE CASCADE,
25
+ name VARCHAR(100) NOT NULL,
26
+ hostname VARCHAR(128),
27
+ status VARCHAR(20) DEFAULT 'offline' CHECK (status IN ('offline', 'idle', 'busy')),
28
+ current_ticket_id INT, -- FK will be added later
29
+ last_heartbeat TIMESTAMPTZ,
30
+ registered_at TIMESTAMPTZ DEFAULT NOW(),
31
+ capabilities JSONB DEFAULT '{}'::jsonb,
32
+ access_token_hash VARCHAR(255)
33
+ );
34
+
35
+ CREATE INDEX IF NOT EXISTS idx_agentdev_agents_user ON agentdev_agents(user_id);
36
+ CREATE INDEX IF NOT EXISTS idx_agentdev_agents_status ON agentdev_agents(status);
37
+ CREATE INDEX IF NOT EXISTS idx_agentdev_agents_heartbeat ON agentdev_agents(last_heartbeat);
38
+
39
+ -- Tickets table (without assigned_agent_id FK first)
40
+ CREATE TABLE IF NOT EXISTS agentdev_tickets (
41
+ id SERIAL PRIMARY KEY,
42
+ github_issue_number INT NOT NULL,
43
+ github_repo VARCHAR(100) NOT NULL,
44
+ github_project_item_id VARCHAR(100),
45
+ status VARCHAR(20) DEFAULT 'todo' CHECK (status IN ('todo', 'assigned', 'in_progress', 'completed', 'failed')),
46
+ assigned_agent_id VARCHAR(64), -- FK will be added later
47
+ assigned_at TIMESTAMPTZ,
48
+ priority INT DEFAULT 5,
49
+ created_at TIMESTAMPTZ DEFAULT NOW(),
50
+ completed_at TIMESTAMPTZ,
51
+ error_message TEXT,
52
+ UNIQUE(github_repo, github_issue_number)
53
+ );
54
+
55
+ CREATE INDEX IF NOT EXISTS idx_agentdev_tickets_status ON agentdev_tickets(status);
56
+ CREATE INDEX IF NOT EXISTS idx_agentdev_tickets_assigned ON agentdev_tickets(assigned_agent_id);
57
+ CREATE INDEX IF NOT EXISTS idx_agentdev_tickets_priority ON agentdev_tickets(priority DESC);
58
+
59
+ -- Now add the circular foreign keys
60
+ DO $$
61
+ BEGIN
62
+ -- Add FK from agents to tickets
63
+ IF NOT EXISTS (
64
+ SELECT 1 FROM information_schema.table_constraints
65
+ WHERE constraint_name = 'fk_current_ticket'
66
+ AND table_name = 'agentdev_agents'
67
+ ) THEN
68
+ ALTER TABLE agentdev_agents
69
+ ADD CONSTRAINT fk_current_ticket
70
+ FOREIGN KEY (current_ticket_id)
71
+ REFERENCES agentdev_tickets(id)
72
+ ON DELETE SET NULL
73
+ DEFERRABLE INITIALLY DEFERRED;
74
+ END IF;
75
+
76
+ -- Add FK from tickets to agents
77
+ IF NOT EXISTS (
78
+ SELECT 1 FROM information_schema.table_constraints
79
+ WHERE constraint_name = 'fk_assigned_agent'
80
+ AND table_name = 'agentdev_tickets'
81
+ ) THEN
82
+ ALTER TABLE agentdev_tickets
83
+ ADD CONSTRAINT fk_assigned_agent
84
+ FOREIGN KEY (assigned_agent_id)
85
+ REFERENCES agentdev_agents(id)
86
+ ON DELETE SET NULL;
87
+ END IF;
88
+ END $$;
89
+
90
+ -- Agent logs table (optional - for persistent storage beyond Redis)
91
+ CREATE TABLE IF NOT EXISTS agentdev_logs (
92
+ id BIGSERIAL PRIMARY KEY,
93
+ agent_id VARCHAR(64) NOT NULL REFERENCES agentdev_agents(id) ON DELETE CASCADE,
94
+ ticket_id INT REFERENCES agentdev_tickets(id) ON DELETE CASCADE,
95
+ timestamp TIMESTAMPTZ DEFAULT NOW(),
96
+ level VARCHAR(10) DEFAULT 'INFO' CHECK (level IN ('DEBUG', 'INFO', 'WARN', 'ERROR')),
97
+ content TEXT NOT NULL
98
+ );
99
+
100
+ CREATE INDEX IF NOT EXISTS idx_agentdev_logs_agent_time ON agentdev_logs(agent_id, timestamp DESC);
101
+ CREATE INDEX IF NOT EXISTS idx_agentdev_logs_ticket ON agentdev_logs(ticket_id);
102
+
103
+ -- Device authorization table (for OAuth device flow)
104
+ CREATE TABLE IF NOT EXISTS agentdev_device_codes (
105
+ device_code VARCHAR(64) PRIMARY KEY,
106
+ user_code VARCHAR(16) UNIQUE NOT NULL,
107
+ user_id INT REFERENCES agentdev_users(id) ON DELETE CASCADE,
108
+ status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'denied', 'expired')),
109
+ agent_name VARCHAR(100),
110
+ agent_capabilities JSONB,
111
+ created_at TIMESTAMPTZ DEFAULT NOW(),
112
+ expires_at TIMESTAMPTZ NOT NULL
113
+ );
114
+
115
+ CREATE INDEX IF NOT EXISTS idx_agentdev_device_codes_user_code ON agentdev_device_codes(user_code);
116
+ CREATE INDEX IF NOT EXISTS idx_agentdev_device_codes_expires ON agentdev_device_codes(expires_at);
117
+
118
+ -- Auto-update updated_at timestamp
119
+ CREATE OR REPLACE FUNCTION update_updated_at_column()
120
+ RETURNS TRIGGER AS $$
121
+ BEGIN
122
+ NEW.updated_at = NOW();
123
+ RETURN NEW;
124
+ END;
125
+ $$ language 'plpgsql';
126
+
127
+ DROP TRIGGER IF EXISTS update_agentdev_users_updated_at ON agentdev_users;
128
+ CREATE TRIGGER update_agentdev_users_updated_at BEFORE UPDATE ON agentdev_users
129
+ FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
130
+
131
+ -- Grant permissions
132
+ GRANT ALL ON ALL TABLES IN SCHEMA public TO agentdev;
133
+ GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO agentdev;
134
+
135
+ COMMIT;
@@ -0,0 +1,17 @@
1
+ -- Migration: Add GitHub token column to users table
2
+ -- Date: 2026-02-07
3
+
4
+ -- Add github_token_encrypted column to agentdev_users table
5
+ ALTER TABLE agentdev_users
6
+ ADD COLUMN IF NOT EXISTS github_token_encrypted TEXT;
7
+
8
+ -- Add index for faster lookups (optional but recommended)
9
+ CREATE INDEX IF NOT EXISTS idx_users_github_token
10
+ ON agentdev_users(id)
11
+ WHERE github_token_encrypted IS NOT NULL;
12
+
13
+ -- Verify column was added
14
+ SELECT column_name, data_type, is_nullable
15
+ FROM information_schema.columns
16
+ WHERE table_name = 'agentdev_users'
17
+ AND column_name = 'github_token_encrypted';
@@ -0,0 +1,23 @@
1
+ -- Migration: Add agent logs table
2
+ -- Date: 2026-02-07
3
+
4
+ CREATE TABLE IF NOT EXISTS agentdev_agent_logs (
5
+ id BIGSERIAL PRIMARY KEY,
6
+ agent_id VARCHAR(64) NOT NULL,
7
+ ticket_number INT,
8
+ timestamp TIMESTAMPTZ DEFAULT NOW(),
9
+ level VARCHAR(10) DEFAULT 'INFO',
10
+ content TEXT NOT NULL
11
+ );
12
+
13
+ CREATE INDEX IF NOT EXISTS idx_agent_logs_agent_time
14
+ ON agentdev_agent_logs(agent_id, timestamp DESC);
15
+
16
+ CREATE INDEX IF NOT EXISTS idx_agent_logs_timestamp
17
+ ON agentdev_agent_logs(timestamp DESC);
18
+
19
+ -- Verify table was created
20
+ SELECT table_name, column_name, data_type
21
+ FROM information_schema.columns
22
+ WHERE table_name = 'agentdev_agent_logs'
23
+ ORDER BY ordinal_position;
@@ -0,0 +1,11 @@
1
+ -- Remove OAuth client ID/secret columns from agentdev_users
2
+ -- Users only need a GitHub Personal Access Token (github_token_encrypted)
3
+
4
+ BEGIN;
5
+
6
+ ALTER TABLE agentdev_users
7
+ DROP COLUMN IF EXISTS github_oauth_client_id,
8
+ DROP COLUMN IF EXISTS github_oauth_client_secret_encrypted,
9
+ DROP COLUMN IF EXISTS github_oauth_scopes;
10
+
11
+ COMMIT;
@@ -0,0 +1,44 @@
1
+ BEGIN;
2
+
3
+ CREATE TABLE IF NOT EXISTS agentdev_projects (
4
+ id SERIAL PRIMARY KEY,
5
+ name VARCHAR(100) NOT NULL,
6
+ github_org VARCHAR(100) NOT NULL,
7
+ project_number INT NOT NULL,
8
+ github_project_id VARCHAR(100) NOT NULL,
9
+ status_field_id VARCHAR(100) NOT NULL,
10
+ status_options JSONB NOT NULL DEFAULT '{}',
11
+ created_by INT REFERENCES agentdev_users(id),
12
+ created_at TIMESTAMPTZ DEFAULT NOW(),
13
+ UNIQUE(github_org, project_number)
14
+ );
15
+
16
+ -- Seed the existing hardcoded project
17
+ INSERT INTO agentdev_projects (name, github_org, project_number, github_project_id, status_field_id, status_options)
18
+ VALUES (
19
+ 'DataTamer',
20
+ 'data-tamer',
21
+ 1,
22
+ 'PVT_kwDOCJIWbs4AnuSZ',
23
+ 'PVTSSF_lADOCJIWbs4AnuSZzgfaWGs',
24
+ '{"TODO":"f75ad846","IN_PROGRESS":"47fc9ee4","TEST":"c48bc058","DONE":"98236657"}'
25
+ ) ON CONFLICT DO NOTHING;
26
+
27
+ -- Add project_id to agents (nullable for backwards compat, then backfill)
28
+ ALTER TABLE agentdev_agents ADD COLUMN IF NOT EXISTS project_id INT REFERENCES agentdev_projects(id) ON DELETE SET NULL;
29
+
30
+ -- Add project_id to tickets
31
+ ALTER TABLE agentdev_tickets ADD COLUMN IF NOT EXISTS project_id INT REFERENCES agentdev_projects(id) ON DELETE SET NULL;
32
+
33
+ -- Backfill existing rows to project 1
34
+ UPDATE agentdev_agents SET project_id = 1 WHERE project_id IS NULL;
35
+ UPDATE agentdev_tickets SET project_id = 1 WHERE project_id IS NULL;
36
+
37
+ -- Indexes
38
+ CREATE INDEX IF NOT EXISTS idx_agentdev_agents_project ON agentdev_agents(project_id);
39
+ CREATE INDEX IF NOT EXISTS idx_agentdev_tickets_project ON agentdev_tickets(project_id);
40
+
41
+ GRANT ALL ON ALL TABLES IN SCHEMA public TO agentdev;
42
+ GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO agentdev;
43
+
44
+ COMMIT;
@@ -0,0 +1,7 @@
1
+ BEGIN;
2
+
3
+ ALTER TABLE agentdev_projects ADD COLUMN IF NOT EXISTS github_token TEXT DEFAULT NULL;
4
+
5
+ GRANT ALL ON ALL TABLES IN SCHEMA public TO agentdev;
6
+
7
+ COMMIT;
@@ -0,0 +1,12 @@
1
+ BEGIN;
2
+
3
+ ALTER TABLE agentdev_projects ADD COLUMN IF NOT EXISTS repositories JSONB NOT NULL DEFAULT '[]';
4
+
5
+ -- Seed existing DataTamer project with current repo list
6
+ UPDATE agentdev_projects
7
+ SET repositories = '["data-tamer-dashboard","tamer_service","datatamer.ai","super_agent","consumer_service","agent_service","agentdev-webui","data-tamer-mobile","production_k3s","local_k3s"]'
8
+ WHERE github_org = 'data-tamer' AND project_number = 1;
9
+
10
+ GRANT ALL ON ALL TABLES IN SCHEMA public TO agentdev;
11
+
12
+ COMMIT;
@@ -0,0 +1,20 @@
1
+ BEGIN;
2
+
3
+ CREATE TABLE IF NOT EXISTS agentdev_notifications (
4
+ id BIGSERIAL PRIMARY KEY,
5
+ user_id INT NOT NULL REFERENCES agentdev_users(id) ON DELETE CASCADE,
6
+ type VARCHAR(50) NOT NULL DEFAULT 'ticket-completed',
7
+ title VARCHAR(255) NOT NULL,
8
+ message TEXT,
9
+ metadata JSONB DEFAULT '{}',
10
+ read BOOLEAN NOT NULL DEFAULT FALSE,
11
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
12
+ );
13
+
14
+ CREATE INDEX IF NOT EXISTS idx_agentdev_notifications_user_unread
15
+ ON agentdev_notifications (user_id, read, created_at DESC);
16
+
17
+ GRANT ALL ON agentdev_notifications TO agentdev;
18
+ GRANT ALL ON agentdev_notifications_id_seq TO agentdev;
19
+
20
+ COMMIT;