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.
- package/README.md +470 -75
- package/dist/chunk-7OCVIDC7.js +12 -0
- package/dist/chunk-7OCVIDC7.js.map +1 -0
- package/dist/chunk-FUHBEL3L.js +203 -0
- package/dist/chunk-FUHBEL3L.js.map +1 -0
- package/dist/chunk-G63RBKDH.js +980 -0
- package/dist/chunk-G63RBKDH.js.map +1 -0
- package/dist/cli.js +4174 -1962
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -4
- package/dist/index.js +1 -11
- package/dist/index.js.map +1 -1
- package/dist/memory-4PVUKIDK.js +19 -0
- package/dist/memory-4PVUKIDK.js.map +1 -0
- package/dist/sessions-JCQ34BEU.js +15 -0
- package/dist/sessions-JCQ34BEU.js.map +1 -0
- package/docker/.env.example +17 -0
- package/docker/README.md +92 -0
- package/docker/docker-compose.engram.yml +289 -0
- package/docker/docker-compose.yml +194 -0
- package/docker/init-db.sql +399 -0
- package/docker/init-engram-db.sql +148 -0
- package/docker/init-langfuse-db.sh +10 -0
- package/docker/otel-collector.yaml +34 -0
- package/docker/squads-bridge/Dockerfile +14 -0
- package/docker/squads-bridge/Dockerfile.proxy +14 -0
- package/docker/squads-bridge/anthropic_proxy.py +313 -0
- package/docker/squads-bridge/requirements.txt +7 -0
- package/docker/squads-bridge/squads_bridge.py +1610 -0
- package/docker/telemetry-ping/Dockerfile +10 -0
- package/docker/telemetry-ping/deploy.sh +69 -0
- package/docker/telemetry-ping/main.py +136 -0
- package/docker/telemetry-ping/requirements.txt +3 -0
- package/package.json +15 -2
|
@@ -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]
|