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.
- package/lib/agent-api.js +530 -0
- package/lib/auth.js +127 -0
- package/lib/config.js +53 -0
- package/lib/database.js +762 -0
- package/lib/device-flow.js +257 -0
- package/lib/email.js +420 -0
- package/lib/encryption.js +112 -0
- package/lib/github.js +339 -0
- package/lib/history.js +143 -0
- package/lib/pwa.js +107 -0
- package/lib/redis-logs.js +226 -0
- package/lib/routes.js +680 -0
- package/migrations/000_create_database.sql +33 -0
- package/migrations/001_create_agentdev_schema.sql +135 -0
- package/migrations/001_create_agentdev_schema.sql.old +100 -0
- package/migrations/001_create_agentdev_schema_fixed.sql +135 -0
- package/migrations/002_add_github_token.sql +17 -0
- package/migrations/003_add_agent_logs_table.sql +23 -0
- package/migrations/004_remove_oauth_columns.sql +11 -0
- package/migrations/005_add_projects.sql +44 -0
- package/migrations/006_project_github_token.sql +7 -0
- package/migrations/007_project_repositories.sql +12 -0
- package/migrations/008_add_notifications.sql +20 -0
- package/migrations/009_unified_oauth.sql +153 -0
- package/migrations/README.md +97 -0
- package/package.json +37 -0
- package/public/css/styles.css +1140 -0
- package/public/device.html +384 -0
- package/public/docs.html +862 -0
- package/public/docs.md +697 -0
- package/public/favicon.svg +5 -0
- package/public/index.html +271 -0
- package/public/js/app.js +2379 -0
- package/public/login.html +224 -0
- package/public/profile.html +394 -0
- package/public/register.html +392 -0
- package/public/reset-password.html +349 -0
- package/public/verify-email.html +177 -0
- package/server.js +1450 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
-- Migration 009: Unified OAuth Provider Tables
|
|
2
|
+
-- Follows the data-tamer-dashboard pattern for OAuth provider configuration and user connections.
|
|
3
|
+
-- Creates two tables:
|
|
4
|
+
-- 1. agentdev_oauth_provider_configs - Provider definitions (auth URLs, scopes, token exchange settings)
|
|
5
|
+
-- 2. agentdev_oauth_providers - Per-user OAuth connections with encrypted tokens
|
|
6
|
+
-- Then migrates existing github_token_encrypted and project github_token data.
|
|
7
|
+
|
|
8
|
+
-- Enable UUID generation if not already available
|
|
9
|
+
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
|
10
|
+
|
|
11
|
+
-- ============================================================================
|
|
12
|
+
-- Table: agentdev_oauth_provider_configs
|
|
13
|
+
-- Platform-level OAuth provider definitions (GitHub, Google, etc.)
|
|
14
|
+
-- ============================================================================
|
|
15
|
+
CREATE TABLE IF NOT EXISTS agentdev_oauth_provider_configs (
|
|
16
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
17
|
+
provider_key VARCHAR(50) UNIQUE NOT NULL,
|
|
18
|
+
name VARCHAR(100) NOT NULL,
|
|
19
|
+
client_id TEXT, -- Encrypted client ID (null for PAT-only providers)
|
|
20
|
+
client_secret TEXT, -- Encrypted client secret (null for PAT-only providers)
|
|
21
|
+
authorize_payload JSONB NOT NULL DEFAULT '{}',
|
|
22
|
+
callback_payload JSONB NOT NULL DEFAULT '{}',
|
|
23
|
+
is_active BOOLEAN DEFAULT true,
|
|
24
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
25
|
+
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
-- ============================================================================
|
|
29
|
+
-- Table: agentdev_oauth_providers
|
|
30
|
+
-- User-specific OAuth connections with encrypted tokens
|
|
31
|
+
-- ============================================================================
|
|
32
|
+
CREATE TABLE IF NOT EXISTS agentdev_oauth_providers (
|
|
33
|
+
id SERIAL PRIMARY KEY,
|
|
34
|
+
user_id INT NOT NULL REFERENCES agentdev_users(id) ON DELETE CASCADE,
|
|
35
|
+
config_id UUID NOT NULL REFERENCES agentdev_oauth_provider_configs(id) ON DELETE CASCADE,
|
|
36
|
+
provider_key VARCHAR(50) NOT NULL,
|
|
37
|
+
access_token TEXT, -- Encrypted access token
|
|
38
|
+
refresh_token TEXT, -- Encrypted refresh token (nullable)
|
|
39
|
+
token_expires_at TIMESTAMPTZ,
|
|
40
|
+
scopes TEXT[] DEFAULT '{}',
|
|
41
|
+
status VARCHAR(20) DEFAULT 'active',
|
|
42
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
43
|
+
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
44
|
+
UNIQUE(user_id, provider_key)
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
-- Index for quick lookups
|
|
48
|
+
CREATE INDEX IF NOT EXISTS idx_oauth_providers_user_id ON agentdev_oauth_providers(user_id);
|
|
49
|
+
CREATE INDEX IF NOT EXISTS idx_oauth_providers_provider_key ON agentdev_oauth_providers(provider_key);
|
|
50
|
+
|
|
51
|
+
-- ============================================================================
|
|
52
|
+
-- Seed: GitHub provider config
|
|
53
|
+
-- ============================================================================
|
|
54
|
+
INSERT INTO agentdev_oauth_provider_configs (
|
|
55
|
+
provider_key,
|
|
56
|
+
name,
|
|
57
|
+
client_id,
|
|
58
|
+
client_secret,
|
|
59
|
+
authorize_payload,
|
|
60
|
+
callback_payload,
|
|
61
|
+
is_active
|
|
62
|
+
) VALUES (
|
|
63
|
+
'github',
|
|
64
|
+
'GitHub',
|
|
65
|
+
NULL, -- PAT-based, no OAuth app client ID needed yet
|
|
66
|
+
NULL, -- PAT-based, no OAuth app client secret needed yet
|
|
67
|
+
'{
|
|
68
|
+
"name": "GitHub",
|
|
69
|
+
"authUrl": "https://github.com/login/oauth/authorize",
|
|
70
|
+
"scope": ["user:email", "read:user", "repo", "read:org", "project"],
|
|
71
|
+
"redirectUriPath": "/api/oauth/callback",
|
|
72
|
+
"additionalParams": {
|
|
73
|
+
"allow_signup": "true"
|
|
74
|
+
}
|
|
75
|
+
}'::jsonb,
|
|
76
|
+
'{
|
|
77
|
+
"settings": {},
|
|
78
|
+
"oauth_provider": {
|
|
79
|
+
"name": "GitHub",
|
|
80
|
+
"tokenUrl": "https://github.com/login/oauth/access_token",
|
|
81
|
+
"headers": {
|
|
82
|
+
"Accept": "application/json",
|
|
83
|
+
"Content-Type": "application/json"
|
|
84
|
+
},
|
|
85
|
+
"bodyFormat": "json",
|
|
86
|
+
"redirectPath": "/api/oauth/callback",
|
|
87
|
+
"successParam": "github_connected",
|
|
88
|
+
"defaultExpiration": 31536000000,
|
|
89
|
+
"supportsRefreshToken": false,
|
|
90
|
+
"useBasicAuth": false
|
|
91
|
+
}
|
|
92
|
+
}'::jsonb,
|
|
93
|
+
true
|
|
94
|
+
) ON CONFLICT (provider_key) DO NOTHING;
|
|
95
|
+
|
|
96
|
+
-- LinkedIn provider config
|
|
97
|
+
INSERT INTO agentdev_oauth_provider_configs (
|
|
98
|
+
provider_key,
|
|
99
|
+
name,
|
|
100
|
+
client_id,
|
|
101
|
+
client_secret,
|
|
102
|
+
authorize_payload,
|
|
103
|
+
callback_payload,
|
|
104
|
+
is_active
|
|
105
|
+
) VALUES (
|
|
106
|
+
'linkedin',
|
|
107
|
+
'LinkedIn',
|
|
108
|
+
NULL,
|
|
109
|
+
NULL,
|
|
110
|
+
'{
|
|
111
|
+
"name": "LinkedIn",
|
|
112
|
+
"authUrl": "https://www.linkedin.com/oauth/v2/authorization",
|
|
113
|
+
"scope": ["openid", "profile", "email", "w_member_social"],
|
|
114
|
+
"redirectUriPath": "/api/oauth/callback"
|
|
115
|
+
}'::jsonb,
|
|
116
|
+
'{
|
|
117
|
+
"settings": {},
|
|
118
|
+
"oauth_provider": {
|
|
119
|
+
"name": "LinkedIn",
|
|
120
|
+
"tokenUrl": "https://www.linkedin.com/oauth/v2/accessToken",
|
|
121
|
+
"headers": {
|
|
122
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
123
|
+
},
|
|
124
|
+
"bodyFormat": "form",
|
|
125
|
+
"redirectPath": "/api/oauth/callback",
|
|
126
|
+
"successParam": "linkedin_connected",
|
|
127
|
+
"supportsRefreshToken": true,
|
|
128
|
+
"useBasicAuth": false
|
|
129
|
+
}
|
|
130
|
+
}'::jsonb,
|
|
131
|
+
true
|
|
132
|
+
) ON CONFLICT (provider_key) DO NOTHING;
|
|
133
|
+
|
|
134
|
+
-- ============================================================================
|
|
135
|
+
-- Data Migration: Move existing LinkedIn tokens to new table (if they exist)
|
|
136
|
+
-- ============================================================================
|
|
137
|
+
INSERT INTO agentdev_oauth_providers (user_id, config_id, provider_key, access_token, refresh_token, token_expires_at, scopes, status)
|
|
138
|
+
SELECT
|
|
139
|
+
u.id,
|
|
140
|
+
(SELECT id FROM agentdev_oauth_provider_configs WHERE provider_key = 'linkedin'),
|
|
141
|
+
'linkedin',
|
|
142
|
+
u.linkedin_token_encrypted,
|
|
143
|
+
u.linkedin_refresh_token_encrypted,
|
|
144
|
+
u.linkedin_token_expires_at,
|
|
145
|
+
ARRAY['openid', 'profile', 'email', 'w_member_social'],
|
|
146
|
+
'active'
|
|
147
|
+
FROM agentdev_users u
|
|
148
|
+
WHERE u.linkedin_token_encrypted IS NOT NULL
|
|
149
|
+
ON CONFLICT (user_id, provider_key) DO NOTHING;
|
|
150
|
+
|
|
151
|
+
-- Note: github_token_encrypted column does not exist in production schema.
|
|
152
|
+
-- GitHub tokens are saved to the new unified table via the application code
|
|
153
|
+
-- when users save their token through the profile page.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Database Migrations
|
|
2
|
+
|
|
3
|
+
## Setup
|
|
4
|
+
|
|
5
|
+
The AgentDev distributed system uses a **dedicated PostgreSQL database** for isolation and better management.
|
|
6
|
+
|
|
7
|
+
## Running Migrations
|
|
8
|
+
|
|
9
|
+
### Step 1: Create Database and User
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Get PostgreSQL password from secret
|
|
13
|
+
export POSTGRES_PASSWORD=$(kubectl get secret postgresql -n datatamer -o jsonpath='{.data.postgresql-password}' | base64 -d)
|
|
14
|
+
|
|
15
|
+
# Port forward to PostgreSQL
|
|
16
|
+
kubectl port-forward svc/pgbouncer -n datatamer 6432:6432 &
|
|
17
|
+
|
|
18
|
+
# Create database and user
|
|
19
|
+
PGPASSWORD=$POSTGRES_PASSWORD psql -h localhost -p 6432 -U postgres -f migrations/000_create_database.sql
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
This creates:
|
|
23
|
+
- Database: `agentdev`
|
|
24
|
+
- User: `agentdev` with password `agentdev_secure_password_change_me`
|
|
25
|
+
- Extensions: `uuid-ossp`
|
|
26
|
+
|
|
27
|
+
### Step 2: Run Schema Migration
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Run schema migration
|
|
31
|
+
PGPASSWORD=agentdev_secure_password_change_me psql -h localhost -p 6432 -U agentdev -d agentdev -f migrations/001_create_agentdev_schema.sql
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Step 3: Verify Tables Created
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
PGPASSWORD=agentdev_secure_password_change_me psql -h localhost -p 6432 -U agentdev -d agentdev -c "\dt"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Expected output:
|
|
41
|
+
```
|
|
42
|
+
List of relations
|
|
43
|
+
Schema | Name | Type | Owner
|
|
44
|
+
--------+---------------------------+-------+----------
|
|
45
|
+
public | agentdev_agents | table | agentdev
|
|
46
|
+
public | agentdev_device_codes | table | agentdev
|
|
47
|
+
public | agentdev_logs | table | agentdev
|
|
48
|
+
public | agentdev_tickets | table | agentdev
|
|
49
|
+
public | agentdev_users | table | agentdev
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Production Deployment
|
|
53
|
+
|
|
54
|
+
For production, update the Helm chart with a **sealed secret** for the database password:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Generate sealed secret for production
|
|
58
|
+
kubectl create secret generic agentdev-db-password \
|
|
59
|
+
--from-literal=password='<strong-random-password>' \
|
|
60
|
+
--dry-run=client -o yaml | \
|
|
61
|
+
kubeseal -o yaml > production-secrets.yaml
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Then update Helm values to reference the secret:
|
|
65
|
+
|
|
66
|
+
```yaml
|
|
67
|
+
config:
|
|
68
|
+
DATABASE_URL: "postgresql://agentdev:$(AGENTDEV_DB_PASSWORD)@pgbouncer.datatamer.svc.cluster.local:6432/agentdev"
|
|
69
|
+
|
|
70
|
+
envFrom:
|
|
71
|
+
- secretRef:
|
|
72
|
+
name: agentdev-db-password
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Schema Overview
|
|
76
|
+
|
|
77
|
+
| Table | Purpose |
|
|
78
|
+
|-------|---------|
|
|
79
|
+
| `agentdev_users` | User accounts with OAuth configuration |
|
|
80
|
+
| `agentdev_agents` | Registered agents with status tracking |
|
|
81
|
+
| `agentdev_tickets` | GitHub tickets being processed |
|
|
82
|
+
| `agentdev_logs` | Persistent agent logs |
|
|
83
|
+
| `agentdev_device_codes` | OAuth device flow authorization |
|
|
84
|
+
|
|
85
|
+
## Indexes
|
|
86
|
+
|
|
87
|
+
Optimized for:
|
|
88
|
+
- Agent lookup by user and status
|
|
89
|
+
- Ticket assignment and priority queries
|
|
90
|
+
- Log retrieval by agent and timestamp
|
|
91
|
+
- Device code validation
|
|
92
|
+
|
|
93
|
+
## Constraints
|
|
94
|
+
|
|
95
|
+
- Foreign keys with CASCADE delete for cleanup
|
|
96
|
+
- Status enums for data integrity
|
|
97
|
+
- Unique constraints on email, user_code, and ticket identifiers
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agentdev-webui",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Multi-agent workflow dashboard for auto-ticket processing",
|
|
5
|
+
"main": "server.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"agentdev-webui": "server.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"server.js",
|
|
11
|
+
"lib/",
|
|
12
|
+
"public/",
|
|
13
|
+
"migrations/"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"start": "node server.js",
|
|
17
|
+
"dev": "nodemon --watch server.js --watch lib --watch public --ext js,html,css,json --delay 500ms server.js",
|
|
18
|
+
"test": "echo \"No tests yet\" && exit 0"
|
|
19
|
+
},
|
|
20
|
+
"keywords": ["agent", "workflow", "dashboard", "pwa"],
|
|
21
|
+
"author": "DataTamer",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/data-tamer/agentdev-webui.git"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"playwright": "^1.58.1",
|
|
29
|
+
"ioredis": "^5.3.2",
|
|
30
|
+
"pg": "^8.11.3",
|
|
31
|
+
"jsonwebtoken": "^9.0.2",
|
|
32
|
+
"nodemailer": "^6.9.8"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"nodemon": "^3.1.11"
|
|
36
|
+
}
|
|
37
|
+
}
|