squads-cli 0.2.0 → 0.4.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.
@@ -0,0 +1,399 @@
1
+ -- Squads Local Database Initialization
2
+ -- Creates additional schemas/tables beyond what Langfuse creates
3
+
4
+ -- Schema for squads-specific data (separate from Langfuse)
5
+ CREATE SCHEMA IF NOT EXISTS squads;
6
+
7
+ -- GitHub metrics table - tracks git activity over time
8
+ CREATE TABLE IF NOT EXISTS squads.github_metrics (
9
+ id SERIAL PRIMARY KEY,
10
+ org VARCHAR(255) NOT NULL,
11
+ repo VARCHAR(255) NOT NULL,
12
+ metric_date DATE NOT NULL,
13
+
14
+ -- Activity counts
15
+ commits INTEGER DEFAULT 0,
16
+ prs_opened INTEGER DEFAULT 0,
17
+ prs_merged INTEGER DEFAULT 0,
18
+ prs_closed INTEGER DEFAULT 0,
19
+ issues_opened INTEGER DEFAULT 0,
20
+ issues_closed INTEGER DEFAULT 0,
21
+ reviews INTEGER DEFAULT 0,
22
+
23
+ -- Code metrics
24
+ additions INTEGER DEFAULT 0,
25
+ deletions INTEGER DEFAULT 0,
26
+
27
+ -- Quality signals
28
+ avg_pr_cycle_hours NUMERIC(10,2),
29
+ review_pass_rate NUMERIC(5,2),
30
+
31
+ -- Metadata
32
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
33
+
34
+ UNIQUE(org, repo, metric_date)
35
+ );
36
+
37
+ -- Agent execution metrics - links to Langfuse traces
38
+ CREATE TABLE IF NOT EXISTS squads.agent_executions (
39
+ id SERIAL PRIMARY KEY,
40
+ squad VARCHAR(100) NOT NULL,
41
+ agent VARCHAR(100) NOT NULL,
42
+ execution_id VARCHAR(255), -- Links to Langfuse trace_id
43
+
44
+ -- Timing
45
+ started_at TIMESTAMP WITH TIME ZONE NOT NULL,
46
+ completed_at TIMESTAMP WITH TIME ZONE,
47
+ duration_ms INTEGER,
48
+
49
+ -- Results
50
+ status VARCHAR(50) DEFAULT 'running', -- running, completed, failed
51
+ output_type VARCHAR(50), -- commit, pr, issue, file, etc
52
+ output_ref VARCHAR(255), -- PR URL, commit SHA, etc
53
+
54
+ -- Cost tracking (backup to Langfuse)
55
+ input_tokens INTEGER DEFAULT 0,
56
+ output_tokens INTEGER DEFAULT 0,
57
+ cost_usd NUMERIC(10,6) DEFAULT 0,
58
+
59
+ -- Metadata
60
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
61
+ );
62
+
63
+ -- Baseline snapshots - for before/after comparison
64
+ CREATE TABLE IF NOT EXISTS squads.baselines (
65
+ id SERIAL PRIMARY KEY,
66
+ org VARCHAR(255) NOT NULL,
67
+ name VARCHAR(100) NOT NULL,
68
+ captured_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
69
+
70
+ -- 30-day metrics at capture time
71
+ commits_30d INTEGER DEFAULT 0,
72
+ prs_30d INTEGER DEFAULT 0,
73
+ issues_30d INTEGER DEFAULT 0,
74
+ avg_pr_cycle_hours NUMERIC(10,2),
75
+
76
+ -- Metadata
77
+ notes TEXT,
78
+
79
+ UNIQUE(org, name)
80
+ );
81
+
82
+ -- Create indexes for common queries
83
+ CREATE INDEX IF NOT EXISTS idx_github_metrics_date ON squads.github_metrics(metric_date DESC);
84
+ CREATE INDEX IF NOT EXISTS idx_github_metrics_repo ON squads.github_metrics(org, repo);
85
+ CREATE INDEX IF NOT EXISTS idx_agent_executions_squad ON squads.agent_executions(squad, agent);
86
+ CREATE INDEX IF NOT EXISTS idx_agent_executions_status ON squads.agent_executions(status);
87
+
88
+ -- Dashboard snapshots - full dashboard state over time
89
+ CREATE TABLE IF NOT EXISTS squads.dashboard_snapshots (
90
+ id SERIAL PRIMARY KEY,
91
+ captured_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
92
+
93
+ -- Top-level metrics
94
+ total_squads INTEGER DEFAULT 0,
95
+ total_commits INTEGER DEFAULT 0,
96
+ total_prs_merged INTEGER DEFAULT 0,
97
+ total_issues_closed INTEGER DEFAULT 0,
98
+ total_issues_open INTEGER DEFAULT 0,
99
+ goal_progress_pct INTEGER DEFAULT 0,
100
+
101
+ -- Cost metrics (from Langfuse)
102
+ cost_usd NUMERIC(10,4) DEFAULT 0,
103
+ daily_budget_usd NUMERIC(10,2) DEFAULT 50,
104
+ input_tokens INTEGER DEFAULT 0,
105
+ output_tokens INTEGER DEFAULT 0,
106
+
107
+ -- Git activity
108
+ commits_30d INTEGER DEFAULT 0,
109
+ avg_commits_per_day NUMERIC(5,1) DEFAULT 0,
110
+ active_days INTEGER DEFAULT 0,
111
+ peak_commits INTEGER DEFAULT 0,
112
+ peak_date DATE,
113
+
114
+ -- Squad breakdown (JSONB for flexibility)
115
+ squads_data JSONB DEFAULT '[]'::jsonb,
116
+ -- Format: [{ name, commits, prs, issues_closed, issues_open, goals_active, goals_total, progress }]
117
+
118
+ -- Authors breakdown
119
+ authors_data JSONB DEFAULT '[]'::jsonb,
120
+ -- Format: [{ name, commits }]
121
+
122
+ -- Repos breakdown
123
+ repos_data JSONB DEFAULT '[]'::jsonb
124
+ -- Format: [{ name, commits }]
125
+ );
126
+
127
+ -- Index for time-series queries
128
+ CREATE INDEX IF NOT EXISTS idx_dashboard_snapshots_date ON squads.dashboard_snapshots(captured_at DESC);
129
+
130
+ -- =============================================================================
131
+ -- Telemetry Tables - Primary data store (Langfuse is optional forwarding)
132
+ -- =============================================================================
133
+
134
+ -- LLM generations - every API call to Claude/OpenAI
135
+ CREATE TABLE IF NOT EXISTS squads.llm_generations (
136
+ id SERIAL PRIMARY KEY,
137
+ session_id VARCHAR(255) NOT NULL,
138
+ trace_id VARCHAR(255),
139
+
140
+ -- Context
141
+ squad VARCHAR(100) DEFAULT 'hq',
142
+ agent VARCHAR(100) DEFAULT 'coo',
143
+ user_id VARCHAR(255),
144
+
145
+ -- Model info
146
+ model VARCHAR(100) NOT NULL,
147
+
148
+ -- Token counts
149
+ input_tokens INTEGER DEFAULT 0,
150
+ output_tokens INTEGER DEFAULT 0,
151
+ cache_read_tokens INTEGER DEFAULT 0,
152
+ cache_creation_tokens INTEGER DEFAULT 0,
153
+
154
+ -- Cost
155
+ cost_usd NUMERIC(10,6) DEFAULT 0,
156
+
157
+ -- Timing
158
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
159
+ duration_ms INTEGER,
160
+
161
+ -- Metadata (prompt summary, response summary, etc)
162
+ metadata JSONB DEFAULT '{}'::jsonb
163
+ );
164
+
165
+ -- Tool executions - every tool call
166
+ CREATE TABLE IF NOT EXISTS squads.tool_executions (
167
+ id SERIAL PRIMARY KEY,
168
+ session_id VARCHAR(255) NOT NULL,
169
+ trace_id VARCHAR(255),
170
+
171
+ -- Context
172
+ squad VARCHAR(100) DEFAULT 'hq',
173
+ agent VARCHAR(100) DEFAULT 'coo',
174
+
175
+ -- Tool info
176
+ tool_name VARCHAR(255) NOT NULL,
177
+ success BOOLEAN DEFAULT true,
178
+
179
+ -- Timing
180
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
181
+ duration_ms INTEGER,
182
+
183
+ -- Metadata (parameters, result summary)
184
+ metadata JSONB DEFAULT '{}'::jsonb
185
+ );
186
+
187
+ -- Sessions - groups related generations/tools
188
+ CREATE TABLE IF NOT EXISTS squads.sessions (
189
+ id VARCHAR(255) PRIMARY KEY,
190
+ squad VARCHAR(100) DEFAULT 'hq',
191
+ agent VARCHAR(100) DEFAULT 'coo',
192
+ user_id VARCHAR(255),
193
+
194
+ -- Aggregated metrics (updated on each event)
195
+ total_input_tokens INTEGER DEFAULT 0,
196
+ total_output_tokens INTEGER DEFAULT 0,
197
+ total_cost_usd NUMERIC(10,6) DEFAULT 0,
198
+ generation_count INTEGER DEFAULT 0,
199
+ tool_count INTEGER DEFAULT 0,
200
+
201
+ -- Timing
202
+ started_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
203
+ last_activity_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
204
+
205
+ -- Status
206
+ status VARCHAR(50) DEFAULT 'active' -- active, completed, failed
207
+ );
208
+
209
+ -- Indexes for telemetry queries
210
+ CREATE INDEX IF NOT EXISTS idx_llm_generations_session ON squads.llm_generations(session_id);
211
+ CREATE INDEX IF NOT EXISTS idx_llm_generations_squad ON squads.llm_generations(squad, agent);
212
+ CREATE INDEX IF NOT EXISTS idx_llm_generations_created ON squads.llm_generations(created_at DESC);
213
+ CREATE INDEX IF NOT EXISTS idx_tool_executions_session ON squads.tool_executions(session_id);
214
+ CREATE INDEX IF NOT EXISTS idx_tool_executions_tool ON squads.tool_executions(tool_name);
215
+ CREATE INDEX IF NOT EXISTS idx_sessions_squad ON squads.sessions(squad, agent);
216
+ CREATE INDEX IF NOT EXISTS idx_sessions_status ON squads.sessions(status);
217
+
218
+ -- =============================================================================
219
+ -- Conversations - Captured from Claude Code sessions (engram hook)
220
+ -- =============================================================================
221
+
222
+ -- Conversations/memories from Claude Code sessions
223
+ CREATE TABLE IF NOT EXISTS squads.conversations (
224
+ id SERIAL PRIMARY KEY,
225
+ session_id VARCHAR(255),
226
+ user_id VARCHAR(255) DEFAULT 'local',
227
+
228
+ -- Content
229
+ role VARCHAR(50) NOT NULL, -- user, assistant, thinking
230
+ content TEXT NOT NULL,
231
+
232
+ -- Classification
233
+ message_type VARCHAR(50) DEFAULT 'message', -- message, thinking, decision, learning
234
+ importance VARCHAR(20) DEFAULT 'normal', -- low, normal, high
235
+
236
+ -- Context
237
+ squad VARCHAR(100),
238
+ agent VARCHAR(100),
239
+ working_dir VARCHAR(500),
240
+
241
+ -- Timing
242
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
243
+
244
+ -- Metadata (hook info, extracted entities, etc)
245
+ metadata JSONB DEFAULT '{}'::jsonb
246
+ );
247
+
248
+ -- Full-text search on content
249
+ CREATE INDEX IF NOT EXISTS idx_conversations_content_search
250
+ ON squads.conversations USING gin(to_tsvector('english', content));
251
+ CREATE INDEX IF NOT EXISTS idx_conversations_session ON squads.conversations(session_id);
252
+ CREATE INDEX IF NOT EXISTS idx_conversations_user ON squads.conversations(user_id);
253
+ CREATE INDEX IF NOT EXISTS idx_conversations_created ON squads.conversations(created_at DESC);
254
+ CREATE INDEX IF NOT EXISTS idx_conversations_type ON squads.conversations(message_type);
255
+ CREATE INDEX IF NOT EXISTS idx_conversations_importance ON squads.conversations(importance);
256
+
257
+ -- =============================================================================
258
+ -- CLI Events - Anonymous telemetry from squads-cli
259
+ -- =============================================================================
260
+
261
+ CREATE TABLE IF NOT EXISTS squads.cli_events (
262
+ id SERIAL PRIMARY KEY,
263
+ received_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
264
+
265
+ -- Anonymous identification
266
+ anonymous_id VARCHAR(100),
267
+
268
+ -- Event data
269
+ event_name VARCHAR(100) NOT NULL,
270
+ cli_version VARCHAR(20),
271
+
272
+ -- Properties (flexible JSON)
273
+ properties JSONB DEFAULT '{}'::jsonb
274
+ );
275
+
276
+ -- Indexes for analytics queries
277
+ CREATE INDEX IF NOT EXISTS idx_cli_events_name ON squads.cli_events(event_name);
278
+ CREATE INDEX IF NOT EXISTS idx_cli_events_received ON squads.cli_events(received_at DESC);
279
+ CREATE INDEX IF NOT EXISTS idx_cli_events_anonymous ON squads.cli_events(anonymous_id);
280
+
281
+ -- =============================================================================
282
+ -- Task Tracking - Track task completion, retries, and quality
283
+ -- =============================================================================
284
+
285
+ -- Tasks - track goal/task completion
286
+ CREATE TABLE IF NOT EXISTS squads.tasks (
287
+ id SERIAL PRIMARY KEY,
288
+ task_id VARCHAR(255) UNIQUE NOT NULL, -- External ID for deduplication
289
+ session_id VARCHAR(255),
290
+
291
+ -- Context
292
+ squad VARCHAR(100) NOT NULL,
293
+ agent VARCHAR(100),
294
+
295
+ -- Task info
296
+ task_type VARCHAR(50) DEFAULT 'goal', -- goal, issue, pr, command
297
+ description TEXT,
298
+
299
+ -- Completion tracking
300
+ status VARCHAR(50) DEFAULT 'started', -- started, completed, failed, cancelled
301
+ success BOOLEAN,
302
+ retry_count INTEGER DEFAULT 0,
303
+
304
+ -- Output
305
+ output_type VARCHAR(50), -- commit, pr, issue, file, none
306
+ output_ref VARCHAR(500), -- URL or reference
307
+
308
+ -- Cost
309
+ total_tokens INTEGER DEFAULT 0,
310
+ total_cost_usd NUMERIC(10,6) DEFAULT 0,
311
+
312
+ -- Context window
313
+ peak_context_tokens INTEGER DEFAULT 0, -- Max context size during task
314
+ context_utilization_pct NUMERIC(5,2), -- Peak % of context window used
315
+
316
+ -- Timing
317
+ started_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
318
+ completed_at TIMESTAMP WITH TIME ZONE,
319
+ duration_ms INTEGER,
320
+
321
+ -- Metadata
322
+ metadata JSONB DEFAULT '{}'::jsonb
323
+ );
324
+
325
+ -- User feedback on task quality
326
+ CREATE TABLE IF NOT EXISTS squads.task_feedback (
327
+ id SERIAL PRIMARY KEY,
328
+ task_id VARCHAR(255) REFERENCES squads.tasks(task_id),
329
+
330
+ -- Rating
331
+ quality_score INTEGER CHECK (quality_score >= 1 AND quality_score <= 5), -- 1-5 stars
332
+
333
+ -- Detailed feedback
334
+ was_helpful BOOLEAN,
335
+ required_fixes BOOLEAN DEFAULT false,
336
+ fix_description TEXT,
337
+
338
+ -- Tags
339
+ tags VARCHAR(50)[], -- ['accurate', 'fast', 'needed-revision', etc]
340
+
341
+ -- Timing
342
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
343
+
344
+ -- Free-form notes
345
+ notes TEXT
346
+ );
347
+
348
+ -- Aggregated insights per squad/agent (materialized for fast queries)
349
+ CREATE TABLE IF NOT EXISTS squads.agent_insights (
350
+ id SERIAL PRIMARY KEY,
351
+ captured_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
352
+ period VARCHAR(20) NOT NULL, -- 'day', 'week', 'month'
353
+ period_start DATE NOT NULL,
354
+
355
+ -- Context
356
+ squad VARCHAR(100) NOT NULL,
357
+ agent VARCHAR(100),
358
+
359
+ -- Task metrics
360
+ tasks_started INTEGER DEFAULT 0,
361
+ tasks_completed INTEGER DEFAULT 0,
362
+ tasks_failed INTEGER DEFAULT 0,
363
+ success_rate NUMERIC(5,2), -- percentage
364
+
365
+ -- Retry metrics
366
+ total_retries INTEGER DEFAULT 0,
367
+ avg_retries_per_task NUMERIC(5,2),
368
+ tasks_with_retries INTEGER DEFAULT 0,
369
+
370
+ -- Quality metrics (from feedback)
371
+ avg_quality_score NUMERIC(3,2),
372
+ feedback_count INTEGER DEFAULT 0,
373
+ helpful_pct NUMERIC(5,2),
374
+ fix_required_pct NUMERIC(5,2),
375
+
376
+ -- Efficiency metrics
377
+ avg_duration_ms INTEGER,
378
+ avg_tokens_per_task INTEGER,
379
+ avg_cost_per_task NUMERIC(10,6),
380
+ avg_context_utilization NUMERIC(5,2),
381
+
382
+ -- Tool usage
383
+ top_tools JSONB DEFAULT '[]'::jsonb, -- [{name, count, success_rate}]
384
+ tool_failure_rate NUMERIC(5,2),
385
+
386
+ UNIQUE(period, period_start, squad, agent)
387
+ );
388
+
389
+ -- Indexes for insights queries
390
+ CREATE INDEX IF NOT EXISTS idx_tasks_squad ON squads.tasks(squad, agent);
391
+ CREATE INDEX IF NOT EXISTS idx_tasks_status ON squads.tasks(status);
392
+ CREATE INDEX IF NOT EXISTS idx_tasks_created ON squads.tasks(started_at DESC);
393
+ CREATE INDEX IF NOT EXISTS idx_task_feedback_task ON squads.task_feedback(task_id);
394
+ CREATE INDEX IF NOT EXISTS idx_agent_insights_lookup ON squads.agent_insights(squad, period, period_start DESC);
395
+
396
+ -- Grant permissions
397
+ GRANT ALL PRIVILEGES ON SCHEMA squads TO squads;
398
+ GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA squads TO squads;
399
+ GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA squads TO squads;
@@ -0,0 +1,148 @@
1
+ -- =============================================================================
2
+ -- Engram Database Initialization
3
+ -- =============================================================================
4
+ -- Creates the engram database with pgvector extension for memory storage
5
+ -- This script runs after init-db.sql (squads schema)
6
+
7
+ -- Create engram database
8
+ SELECT 'CREATE DATABASE engram'
9
+ WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'engram')\gexec
10
+
11
+ -- Connect to engram database and set up extensions
12
+ \c engram
13
+
14
+ -- Enable pgvector for vector similarity search
15
+ CREATE EXTENSION IF NOT EXISTS vector;
16
+
17
+ -- Enable pg_trgm for fuzzy text search
18
+ CREATE EXTENSION IF NOT EXISTS pg_trgm;
19
+
20
+ -- Create engram schema
21
+ CREATE SCHEMA IF NOT EXISTS engram;
22
+
23
+ -- =============================================================================
24
+ -- Auth Tables - Token-based authentication for MCP server
25
+ -- =============================================================================
26
+
27
+ -- Users table
28
+ CREATE TABLE IF NOT EXISTS engram.users (
29
+ id SERIAL PRIMARY KEY,
30
+ email VARCHAR(255) UNIQUE NOT NULL,
31
+ name VARCHAR(255),
32
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
33
+ updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
34
+ );
35
+
36
+ -- API tokens table
37
+ CREATE TABLE IF NOT EXISTS engram.tokens (
38
+ id SERIAL PRIMARY KEY,
39
+ user_id INTEGER REFERENCES engram.users(id) ON DELETE CASCADE,
40
+ token_hash VARCHAR(255) NOT NULL,
41
+ name VARCHAR(255),
42
+ last_used_at TIMESTAMP WITH TIME ZONE,
43
+ expires_at TIMESTAMP WITH TIME ZONE,
44
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
45
+ revoked_at TIMESTAMP WITH TIME ZONE
46
+ );
47
+
48
+ -- Token usage audit log
49
+ CREATE TABLE IF NOT EXISTS engram.token_usage (
50
+ id SERIAL PRIMARY KEY,
51
+ token_id INTEGER REFERENCES engram.tokens(id) ON DELETE SET NULL,
52
+ user_id INTEGER REFERENCES engram.users(id) ON DELETE SET NULL,
53
+ endpoint VARCHAR(255),
54
+ ip_address INET,
55
+ user_agent TEXT,
56
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
57
+ );
58
+
59
+ -- =============================================================================
60
+ -- Memory Tables - Core memory storage
61
+ -- =============================================================================
62
+
63
+ -- Note: mem0 creates its own tables for memory storage
64
+ -- These are additional tables for Engram-specific features
65
+
66
+ -- Memory metadata (extends mem0 memories)
67
+ CREATE TABLE IF NOT EXISTS engram.memory_metadata (
68
+ id SERIAL PRIMARY KEY,
69
+ memory_id VARCHAR(255) UNIQUE NOT NULL, -- Links to mem0 memory
70
+ user_id INTEGER REFERENCES engram.users(id),
71
+ project_id VARCHAR(255),
72
+ importance FLOAT DEFAULT 0.5,
73
+ access_count INTEGER DEFAULT 0,
74
+ last_accessed_at TIMESTAMP WITH TIME ZONE,
75
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
76
+ metadata JSONB DEFAULT '{}'::jsonb
77
+ );
78
+
79
+ -- Memory chunks (for large text chunking)
80
+ CREATE TABLE IF NOT EXISTS engram.memory_chunks (
81
+ id SERIAL PRIMARY KEY,
82
+ parent_memory_id VARCHAR(255) NOT NULL,
83
+ chunk_index INTEGER NOT NULL,
84
+ total_chunks INTEGER NOT NULL,
85
+ chunk_size INTEGER NOT NULL,
86
+ has_overlap BOOLEAN DEFAULT false,
87
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
88
+ UNIQUE(parent_memory_id, chunk_index)
89
+ );
90
+
91
+ -- =============================================================================
92
+ -- Graph Sync Tables - Tracks Neo4j synchronization
93
+ -- =============================================================================
94
+
95
+ CREATE TABLE IF NOT EXISTS engram.graph_sync_log (
96
+ id SERIAL PRIMARY KEY,
97
+ memory_id VARCHAR(255) NOT NULL,
98
+ sync_type VARCHAR(50) NOT NULL, -- 'create', 'update', 'delete', 'link'
99
+ status VARCHAR(50) NOT NULL, -- 'pending', 'synced', 'failed'
100
+ error_message TEXT,
101
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
102
+ synced_at TIMESTAMP WITH TIME ZONE
103
+ );
104
+
105
+ -- =============================================================================
106
+ -- Indexes
107
+ -- =============================================================================
108
+
109
+ -- Auth indexes
110
+ CREATE INDEX IF NOT EXISTS idx_tokens_user ON engram.tokens(user_id);
111
+ CREATE INDEX IF NOT EXISTS idx_tokens_hash ON engram.tokens(token_hash);
112
+ CREATE INDEX IF NOT EXISTS idx_token_usage_token ON engram.token_usage(token_id);
113
+ CREATE INDEX IF NOT EXISTS idx_token_usage_created ON engram.token_usage(created_at DESC);
114
+
115
+ -- Memory indexes
116
+ CREATE INDEX IF NOT EXISTS idx_memory_metadata_user ON engram.memory_metadata(user_id);
117
+ CREATE INDEX IF NOT EXISTS idx_memory_metadata_project ON engram.memory_metadata(project_id);
118
+ CREATE INDEX IF NOT EXISTS idx_memory_metadata_importance ON engram.memory_metadata(importance DESC);
119
+ CREATE INDEX IF NOT EXISTS idx_memory_chunks_parent ON engram.memory_chunks(parent_memory_id);
120
+
121
+ -- Graph sync indexes
122
+ CREATE INDEX IF NOT EXISTS idx_graph_sync_memory ON engram.graph_sync_log(memory_id);
123
+ CREATE INDEX IF NOT EXISTS idx_graph_sync_status ON engram.graph_sync_log(status);
124
+ CREATE INDEX IF NOT EXISTS idx_graph_sync_pending ON engram.graph_sync_log(status) WHERE status = 'pending';
125
+
126
+ -- =============================================================================
127
+ -- Default User (for local development)
128
+ -- =============================================================================
129
+
130
+ INSERT INTO engram.users (email, name)
131
+ VALUES ('local@squads.dev', 'Local Development User')
132
+ ON CONFLICT (email) DO NOTHING;
133
+
134
+ -- Grant permissions
135
+ GRANT ALL PRIVILEGES ON SCHEMA engram TO squads;
136
+ GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA engram TO squads;
137
+ GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA engram TO squads;
138
+
139
+ -- =============================================================================
140
+ -- Verify setup
141
+ -- =============================================================================
142
+
143
+ DO $$
144
+ BEGIN
145
+ RAISE NOTICE 'Engram database initialized successfully';
146
+ RAISE NOTICE 'Extensions: vector, pg_trgm';
147
+ RAISE NOTICE 'Schema: engram';
148
+ END $$;
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+ # Create separate database for Langfuse to avoid schema conflicts
3
+ set -e
4
+
5
+ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
6
+ CREATE DATABASE langfuse;
7
+ GRANT ALL PRIVILEGES ON DATABASE langfuse TO squads;
8
+ EOSQL
9
+
10
+ echo "Created langfuse database"
@@ -0,0 +1,34 @@
1
+ receivers:
2
+ otlp:
3
+ protocols:
4
+ http:
5
+ endpoint: 0.0.0.0:4318
6
+
7
+ processors:
8
+ batch:
9
+ timeout: 5s
10
+ send_batch_size: 100
11
+
12
+ exporters:
13
+ # Forward to Squads bridge (postgres primary, Langfuse optional)
14
+ otlphttp:
15
+ endpoint: http://squads-bridge:8080
16
+ encoding: json
17
+ headers: {}
18
+ tls:
19
+ insecure: true
20
+
21
+ # Debug logging
22
+ debug:
23
+ verbosity: detailed
24
+
25
+ service:
26
+ pipelines:
27
+ metrics:
28
+ receivers: [otlp]
29
+ processors: [batch]
30
+ exporters: [otlphttp, debug]
31
+ logs:
32
+ receivers: [otlp]
33
+ processors: [batch]
34
+ exporters: [otlphttp, debug]
@@ -0,0 +1,14 @@
1
+ FROM python:3.11-slim
2
+
3
+ ENV PYTHONUNBUFFERED=1
4
+
5
+ WORKDIR /app
6
+
7
+ COPY requirements.txt .
8
+ RUN pip install --no-cache-dir -r requirements.txt
9
+
10
+ COPY squads_bridge.py .
11
+
12
+ EXPOSE 8080
13
+
14
+ CMD ["python", "squads_bridge.py"]
@@ -0,0 +1,14 @@
1
+ FROM python:3.11-slim
2
+
3
+ ENV PYTHONUNBUFFERED=1
4
+
5
+ WORKDIR /app
6
+
7
+ COPY requirements.txt .
8
+ RUN pip install --no-cache-dir -r requirements.txt
9
+
10
+ COPY anthropic_proxy.py .
11
+
12
+ EXPOSE 8089
13
+
14
+ CMD ["python", "anthropic_proxy.py"]