@askexenow/exe-os 0.9.268 → 0.9.270
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/deploy/compose/.env.customer.example +2 -0
- package/deploy/compose/.env.default +1 -0
- package/deploy/compose/.env.example +2 -0
- package/deploy/compose/docker-compose.yml +14 -6
- package/deploy/compose/generate-env.ts +5 -0
- package/deploy/compose/init-db.sql +236 -56
- package/dist/bin/cli.js +1 -1
- package/dist/bin/exe-forget.js +1 -1
- package/dist/bin/exe-new-employee.js +1 -1
- package/dist/bin/exe-search.js +1 -1
- package/dist/bin/exe-start.sh +28 -1
- package/dist/bin/install.js +1 -1
- package/dist/bin/setup.js +1 -1
- package/dist/bin/stack-update.js +2 -2
- package/dist/bin/vps-health-gate.js +1 -1
- package/dist/catchup-brief-7G3HIQT3.js +151 -0
- package/dist/catchup-brief-IA2K5RYM.js +151 -0
- package/dist/catchup-brief-KABFKY7U.js +151 -0
- package/dist/chunk-4GJHWD4H.js +1148 -0
- package/dist/chunk-6H7PZOYD.js +58 -0
- package/dist/chunk-AHVGHSWX.js +230 -0
- package/dist/chunk-AQU2CVD4.js +1148 -0
- package/dist/chunk-AX6EKVRZ.js +13696 -0
- package/dist/chunk-DFI2IZXM.js +1395 -0
- package/dist/chunk-EM4EYF3P.js +149 -0
- package/dist/chunk-F7RM3Z4R.js +230 -0
- package/dist/chunk-LMYSCMSQ.js +1148 -0
- package/dist/chunk-RJVFHGFD.js +13696 -0
- package/dist/chunk-U2O2UXVQ.js +13696 -0
- package/dist/chunk-UHKKI5MD.js +1391 -0
- package/dist/chunk-X56OLWQS.js +58 -0
- package/dist/chunk-YYO5RQRT.js +1021 -0
- package/dist/chunk-ZFHXFDWX.js +58 -0
- package/dist/hooks/error-recall.js +1 -1
- package/dist/hooks/manifest.json +4 -4
- package/dist/hooks/prompt-submit.js +1 -1
- package/dist/hooks/session-start.js +1 -1
- package/dist/lib/exe-daemon.js +49 -3
- package/dist/lib/hybrid-search.js +1 -1
- package/dist/lib/session-wrappers.js +1 -1
- package/dist/mcp/register-tools.js +3 -3
- package/dist/mcp/server.js +3 -3
- package/dist/reranker-7GCUQ6LC.js +19 -0
- package/dist/reranker-NLH3VBTN.js +19 -0
- package/dist/reranker-RUOD4YHZ.js +19 -0
- package/dist/setup-wizard-M7A7MXH4.js +12 -0
- package/dist/stack-update-MYPMZQEI.js +52 -0
- package/dist/stack-update-YJ433OLM.js +52 -0
- package/dist/task-enforcement-CJKWU43B.js +364 -0
- package/dist/task-enforcement-FYDLTS3R.js +391 -0
- package/dist/task-enforcement-YXKZYS5L.js +369 -0
- package/package.json +1 -1
- package/release-notes.json +57 -21
- package/stack.release.json +48 -48
|
@@ -72,6 +72,8 @@ API_ROUTER_KEY=exe_rk_CHANGEME_API_ROUTER_KEY
|
|
|
72
72
|
# ANTHROPIC_API_KEY=CHANGEME_ANTHROPIC_API_KEY
|
|
73
73
|
GATEWAY_HTTP_HOST_PORT=3100
|
|
74
74
|
GATEWAY_WS_HOST_PORT=3101
|
|
75
|
+
# CRM bridge: exe-gateway reaches exe-crm through Docker service DNS.
|
|
76
|
+
CRM_GRAPHQL_URL=http://exe-crm:3000/graphql
|
|
75
77
|
|
|
76
78
|
# --- Monitoring hub (PocketBase — local per-customer instance) ---
|
|
77
79
|
MONITOR_HUB_IMAGE_TAG=update.askexe.com/askexe/exe-monitor-hub:v0.9.4
|
|
@@ -69,5 +69,6 @@ EXE_GATEWAY_WHATSAPP_VERIFY_TOKEN=CHANGEME_EXE_GATEWAY_WHATSAPP_VERIFY_TOKEN
|
|
|
69
69
|
WHATSAPP_ACCESS_TOKEN=
|
|
70
70
|
API_ROUTER_URL=https://gateway.askexe.com
|
|
71
71
|
API_ROUTER_KEY=exe_rk_CHANGEME_API_ROUTER_KEY
|
|
72
|
+
CRM_GRAPHQL_URL=http://exe-crm:3000/graphql
|
|
72
73
|
GATEWAY_HTTP_HOST_PORT=3100
|
|
73
74
|
GATEWAY_WS_HOST_PORT=3101
|
|
@@ -66,6 +66,8 @@ GATEWAY_HTTP_HOST_PORT=3100
|
|
|
66
66
|
GATEWAY_WS_HOST_PORT=3101
|
|
67
67
|
# GoTrue SSO — enable for unified auth across all services
|
|
68
68
|
GATEWAY_GOTRUE_URL=http://gotrue:9999
|
|
69
|
+
# CRM bridge: exe-gateway reaches exe-crm through Docker service DNS.
|
|
70
|
+
CRM_GRAPHQL_URL=http://exe-crm:3000/graphql
|
|
69
71
|
# Error forwarding to exe-monitor-hub (strongly recommended for production)
|
|
70
72
|
ERROR_REPORTING_ENABLED=true
|
|
71
73
|
MONITOR_ERROR_URL=http://exe-monitor-hub:8090/api/exe-monitor/errors
|
|
@@ -418,6 +418,7 @@ services:
|
|
|
418
418
|
API_ROUTER_KEY: ${API_ROUTER_KEY:-}
|
|
419
419
|
EXED_MCP_URL: http://exe-os:48739/mcp
|
|
420
420
|
EXED_MCP_TOKEN: ${EXED_MCP_TOKEN:?EXED_MCP_TOKEN is required}
|
|
421
|
+
CRM_GRAPHQL_URL: ${CRM_GRAPHQL_URL:-http://exe-crm:3000/graphql}
|
|
421
422
|
ERROR_REPORTING_ENABLED: "true"
|
|
422
423
|
MONITOR_ERROR_URL: http://exe-monitor-hub:8090/api/exe-monitor/errors
|
|
423
424
|
EXE_DAEMON_TOKEN: ${EXED_MCP_TOKEN:?EXED_MCP_TOKEN is required}
|
|
@@ -543,8 +544,11 @@ services:
|
|
|
543
544
|
restart: unless-stopped
|
|
544
545
|
# Token mode: `tunnel run --token <TOKEN>` — no local credentials file needed.
|
|
545
546
|
# The token embeds the tunnel ID + credentials; routes are managed in the CF dashboard.
|
|
547
|
+
# --metrics exposes a local HTTP endpoint used by the healthcheck.
|
|
546
548
|
command: >
|
|
547
|
-
tunnel
|
|
549
|
+
tunnel
|
|
550
|
+
--metrics localhost:2000
|
|
551
|
+
run
|
|
548
552
|
--token ${CLOUDFLARE_TUNNEL_TOKEN}
|
|
549
553
|
depends_on:
|
|
550
554
|
exe-crm:
|
|
@@ -560,11 +564,15 @@ services:
|
|
|
560
564
|
ipv4_address: 10.42.0.31
|
|
561
565
|
frontend:
|
|
562
566
|
ipv4_address: 10.43.0.31
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
567
|
+
healthcheck:
|
|
568
|
+
# `tunnel info` requires API credentials unavailable in token mode.
|
|
569
|
+
# The command above exposes cloudflared's local metrics endpoint; use it
|
|
570
|
+
# for container liveness without hitting the Cloudflare control plane.
|
|
571
|
+
test: ["CMD-SHELL", "pgrep -x cloudflared && wget -q --spider http://localhost:2000/ready || exit 1"]
|
|
572
|
+
interval: 30s
|
|
573
|
+
timeout: 5s
|
|
574
|
+
start_period: 30s
|
|
575
|
+
retries: 5
|
|
568
576
|
logging:
|
|
569
577
|
driver: json-file
|
|
570
578
|
options: { max-size: "10m", max-file: "3" }
|
|
@@ -35,6 +35,7 @@ const LICENSE_KEY_COMMENT = "# injected by deploy_client";
|
|
|
35
35
|
const MANUAL_VALUE_COMMENT = "# SET_MANUALLY";
|
|
36
36
|
const EXAMPLE_LICENSE_KEY = "CHANGEME_EXE_LICENSE_KEY";
|
|
37
37
|
const DEFAULT_API_ROUTER_URL = "https://gateway.askexe.com";
|
|
38
|
+
const DEFAULT_CRM_GRAPHQL_URL = "http://exe-crm:3000/graphql";
|
|
38
39
|
const DEFAULT_MONITOR_HUB_URL = "http://exe-monitor-hub:8090";
|
|
39
40
|
const DEFAULT_MONITOR_AGENT_LISTEN = ":45876";
|
|
40
41
|
const DEFAULT_EXE_MCP_HOST_BIND = "127.0.0.1";
|
|
@@ -115,6 +116,8 @@ export function generateEnv(options: GenerateEnvOptions): string {
|
|
|
115
116
|
`GATEWAY_WS_HOST_PORT=${GATEWAY_WS_HOST_PORT}`,
|
|
116
117
|
"# GoTrue SSO — enable for unified auth across all services",
|
|
117
118
|
"GATEWAY_GOTRUE_URL=http://gotrue:9999",
|
|
119
|
+
"# CRM bridge: exe-gateway reaches exe-crm through Docker service DNS.",
|
|
120
|
+
`CRM_GRAPHQL_URL=${DEFAULT_CRM_GRAPHQL_URL}`,
|
|
118
121
|
"# Error forwarding to exe-monitor-hub (strongly recommended for production)",
|
|
119
122
|
"ERROR_REPORTING_ENABLED=true",
|
|
120
123
|
"MONITOR_ERROR_URL=http://exe-monitor-hub:8090/api/exe-monitor/errors",
|
|
@@ -234,6 +237,8 @@ export function generateExampleEnv(): string {
|
|
|
234
237
|
`GATEWAY_WS_HOST_PORT=${GATEWAY_WS_HOST_PORT}`,
|
|
235
238
|
"# GoTrue SSO — enable for unified auth across all services",
|
|
236
239
|
"GATEWAY_GOTRUE_URL=http://gotrue:9999",
|
|
240
|
+
"# CRM bridge: exe-gateway reaches exe-crm through Docker service DNS.",
|
|
241
|
+
`CRM_GRAPHQL_URL=${DEFAULT_CRM_GRAPHQL_URL}`,
|
|
237
242
|
"# Error forwarding to exe-monitor-hub (strongly recommended for production)",
|
|
238
243
|
"ERROR_REPORTING_ENABLED=true",
|
|
239
244
|
"MONITOR_ERROR_URL=http://exe-monitor-hub:8090/api/exe-monitor/errors",
|
|
@@ -49,6 +49,75 @@ CREATE SCHEMA IF NOT EXISTS auth;
|
|
|
49
49
|
CREATE SCHEMA IF NOT EXISTS billing;
|
|
50
50
|
CREATE SCHEMA IF NOT EXISTS erp;
|
|
51
51
|
|
|
52
|
+
-- Helpers for upgrading existing customer volumes. CREATE TABLE IF NOT EXISTS
|
|
53
|
+
-- does not add columns to tables created by older init-db.sql versions, and
|
|
54
|
+
-- CREATE INDEX IF NOT EXISTS still fails if the target column is missing.
|
|
55
|
+
CREATE OR REPLACE FUNCTION pg_temp.exe_add_column_if_missing(
|
|
56
|
+
p_schema_name TEXT,
|
|
57
|
+
p_table_name TEXT,
|
|
58
|
+
p_column_name TEXT,
|
|
59
|
+
p_column_sql TEXT
|
|
60
|
+
) RETURNS VOID LANGUAGE plpgsql AS $$
|
|
61
|
+
BEGIN
|
|
62
|
+
IF to_regclass(format('%I.%I', p_schema_name, p_table_name)) IS NULL THEN
|
|
63
|
+
RETURN;
|
|
64
|
+
END IF;
|
|
65
|
+
|
|
66
|
+
IF NOT EXISTS (
|
|
67
|
+
SELECT 1
|
|
68
|
+
FROM information_schema.columns
|
|
69
|
+
WHERE table_schema = p_schema_name
|
|
70
|
+
AND table_name = p_table_name
|
|
71
|
+
AND column_name = p_column_name
|
|
72
|
+
) THEN
|
|
73
|
+
EXECUTE format('ALTER TABLE %I.%I ADD COLUMN %s', p_schema_name, p_table_name, p_column_sql);
|
|
74
|
+
END IF;
|
|
75
|
+
END $$;
|
|
76
|
+
|
|
77
|
+
CREATE OR REPLACE FUNCTION pg_temp.exe_create_index_if_columns_exist(
|
|
78
|
+
p_index_name TEXT,
|
|
79
|
+
p_schema_name TEXT,
|
|
80
|
+
p_table_name TEXT,
|
|
81
|
+
p_column_names TEXT[],
|
|
82
|
+
p_create_sql TEXT
|
|
83
|
+
) RETURNS VOID LANGUAGE plpgsql AS $$
|
|
84
|
+
DECLARE
|
|
85
|
+
missing_column TEXT;
|
|
86
|
+
BEGIN
|
|
87
|
+
IF to_regclass(format('%I.%I', p_schema_name, p_table_name)) IS NULL THEN
|
|
88
|
+
RETURN;
|
|
89
|
+
END IF;
|
|
90
|
+
|
|
91
|
+
SELECT c INTO missing_column
|
|
92
|
+
FROM unnest(p_column_names) AS c
|
|
93
|
+
WHERE NOT EXISTS (
|
|
94
|
+
SELECT 1
|
|
95
|
+
FROM information_schema.columns
|
|
96
|
+
WHERE table_schema = p_schema_name
|
|
97
|
+
AND table_name = p_table_name
|
|
98
|
+
AND column_name = c
|
|
99
|
+
)
|
|
100
|
+
LIMIT 1;
|
|
101
|
+
|
|
102
|
+
IF missing_column IS NOT NULL THEN
|
|
103
|
+
RAISE NOTICE 'Skipping index %.% because %.% is missing column %',
|
|
104
|
+
p_schema_name, p_index_name, p_schema_name, p_table_name, missing_column;
|
|
105
|
+
RETURN;
|
|
106
|
+
END IF;
|
|
107
|
+
|
|
108
|
+
IF to_regclass(format('%I.%I', p_schema_name, p_index_name)) IS NOT NULL THEN
|
|
109
|
+
RETURN;
|
|
110
|
+
END IF;
|
|
111
|
+
|
|
112
|
+
BEGIN
|
|
113
|
+
EXECUTE p_create_sql;
|
|
114
|
+
EXCEPTION
|
|
115
|
+
WHEN unique_violation THEN
|
|
116
|
+
RAISE NOTICE 'Skipping unique index %.% because existing rows are not unique',
|
|
117
|
+
p_schema_name, p_index_name;
|
|
118
|
+
END;
|
|
119
|
+
END $$;
|
|
120
|
+
|
|
52
121
|
-- Grant exe full access to all schemas
|
|
53
122
|
DO $$ DECLARE s text; BEGIN
|
|
54
123
|
FOR s IN SELECT schema_name FROM information_schema.schemata
|
|
@@ -79,9 +148,9 @@ CREATE TABLE IF NOT EXISTS raw.raw_events (
|
|
|
79
148
|
projections JSONB DEFAULT '{}'::jsonb
|
|
80
149
|
);
|
|
81
150
|
|
|
82
|
-
CREATE INDEX IF NOT EXISTS idx_raw_events_unprocessed ON raw.raw_events (created_at) WHERE processed_at IS NULL;
|
|
83
|
-
CREATE INDEX IF NOT EXISTS idx_raw_events_retryable ON raw.raw_events (failed_at) WHERE processed_at IS NULL AND failed_at IS NOT NULL AND retry_count < 5;
|
|
84
|
-
CREATE UNIQUE INDEX IF NOT EXISTS uq_raw_events_dedup ON raw.raw_events (source, source_id, event_type);
|
|
151
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_raw_events_unprocessed', 'raw', 'raw_events', ARRAY['created_at', 'processed_at'], 'CREATE INDEX IF NOT EXISTS idx_raw_events_unprocessed ON raw.raw_events (created_at) WHERE processed_at IS NULL');
|
|
152
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_raw_events_retryable', 'raw', 'raw_events', ARRAY['failed_at', 'processed_at', 'retry_count'], 'CREATE INDEX IF NOT EXISTS idx_raw_events_retryable ON raw.raw_events (failed_at) WHERE processed_at IS NULL AND failed_at IS NOT NULL AND retry_count < 5');
|
|
153
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('uq_raw_events_dedup', 'raw', 'raw_events', ARRAY['source', 'source_id', 'event_type'], 'CREATE UNIQUE INDEX IF NOT EXISTS uq_raw_events_dedup ON raw.raw_events (source, source_id, event_type)');
|
|
85
154
|
|
|
86
155
|
-- ---------------------------------------------------------------------------
|
|
87
156
|
-- Graph schema — Company Brain memory + GraphRAG projection targets.
|
|
@@ -114,10 +183,33 @@ CREATE TABLE IF NOT EXISTS graph.memory_records (
|
|
|
114
183
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
115
184
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
116
185
|
);
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
186
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'id', 'id UUID DEFAULT gen_random_uuid()');
|
|
187
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'agent_id', 'agent_id TEXT NOT NULL DEFAULT ''system''');
|
|
188
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'agent_role', 'agent_role TEXT NOT NULL DEFAULT ''ingest''');
|
|
189
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'session_id', 'session_id TEXT NOT NULL DEFAULT ''projection-worker''');
|
|
190
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'timestamp', 'timestamp TIMESTAMPTZ NOT NULL DEFAULT now()');
|
|
191
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'tool_name', 'tool_name TEXT NOT NULL DEFAULT ''projection_worker''');
|
|
192
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'project_name', 'project_name TEXT NOT NULL DEFAULT ''exe-os''');
|
|
193
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'has_error', 'has_error BOOLEAN NOT NULL DEFAULT false');
|
|
194
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'raw_text', 'raw_text TEXT NOT NULL DEFAULT ''''');
|
|
195
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'vector', 'vector vector(1024)');
|
|
196
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'version', 'version INTEGER NOT NULL DEFAULT 0');
|
|
197
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'task_id', 'task_id TEXT');
|
|
198
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'intent', 'intent TEXT');
|
|
199
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'outcome', 'outcome TEXT');
|
|
200
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'domain', 'domain TEXT');
|
|
201
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'trajectory', 'trajectory TEXT');
|
|
202
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'memory_type', 'memory_type TEXT NOT NULL DEFAULT ''raw''');
|
|
203
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'source_type', 'source_type TEXT NOT NULL DEFAULT ''unknown''');
|
|
204
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'importance', 'importance INTEGER NOT NULL DEFAULT 5');
|
|
205
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'status', 'status TEXT NOT NULL DEFAULT ''active''');
|
|
206
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'metadata', 'metadata JSONB NOT NULL DEFAULT ''{}''::jsonb');
|
|
207
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'created_at', 'created_at TIMESTAMPTZ NOT NULL DEFAULT now()');
|
|
208
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'memory_records', 'updated_at', 'updated_at TIMESTAMPTZ NOT NULL DEFAULT now()');
|
|
209
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_graph_memory_records_agent', 'graph', 'memory_records', ARRAY['agent_id'], 'CREATE INDEX IF NOT EXISTS idx_graph_memory_records_agent ON graph.memory_records(agent_id)');
|
|
210
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_graph_memory_records_project_time', 'graph', 'memory_records', ARRAY['project_name', 'timestamp'], 'CREATE INDEX IF NOT EXISTS idx_graph_memory_records_project_time ON graph.memory_records(project_name, timestamp DESC)');
|
|
211
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_graph_memory_records_status', 'graph', 'memory_records', ARRAY['status'], 'CREATE INDEX IF NOT EXISTS idx_graph_memory_records_status ON graph.memory_records(status)');
|
|
212
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_graph_memory_records_source_type', 'graph', 'memory_records', ARRAY['source_type'], 'CREATE INDEX IF NOT EXISTS idx_graph_memory_records_source_type ON graph.memory_records(source_type)');
|
|
121
213
|
|
|
122
214
|
CREATE TABLE IF NOT EXISTS graph.entities (
|
|
123
215
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
@@ -128,8 +220,14 @@ CREATE TABLE IF NOT EXISTS graph.entities (
|
|
|
128
220
|
properties JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
129
221
|
UNIQUE(name, type)
|
|
130
222
|
);
|
|
131
|
-
|
|
132
|
-
|
|
223
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'entities', 'id', 'id UUID DEFAULT gen_random_uuid()');
|
|
224
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'entities', 'name', 'name TEXT NOT NULL DEFAULT ''''');
|
|
225
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'entities', 'type', 'type TEXT NOT NULL DEFAULT ''unknown''');
|
|
226
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'entities', 'first_seen', 'first_seen TIMESTAMPTZ NOT NULL DEFAULT now()');
|
|
227
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'entities', 'last_seen', 'last_seen TIMESTAMPTZ NOT NULL DEFAULT now()');
|
|
228
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'entities', 'properties', 'properties JSONB NOT NULL DEFAULT ''{}''::jsonb');
|
|
229
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_graph_entities_type', 'graph', 'entities', ARRAY['type'], 'CREATE INDEX IF NOT EXISTS idx_graph_entities_type ON graph.entities(type)');
|
|
230
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_graph_entities_last_seen', 'graph', 'entities', ARRAY['last_seen'], 'CREATE INDEX IF NOT EXISTS idx_graph_entities_last_seen ON graph.entities(last_seen DESC)');
|
|
133
231
|
|
|
134
232
|
CREATE TABLE IF NOT EXISTS graph.relationships (
|
|
135
233
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
@@ -143,16 +241,26 @@ CREATE TABLE IF NOT EXISTS graph.relationships (
|
|
|
143
241
|
properties JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
144
242
|
UNIQUE(source_entity_id, target_entity_id, type)
|
|
145
243
|
);
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
244
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'relationships', 'source_entity_id', 'source_entity_id UUID');
|
|
245
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'relationships', 'target_entity_id', 'target_entity_id UUID');
|
|
246
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'relationships', 'type', 'type TEXT NOT NULL DEFAULT ''related_to''');
|
|
247
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'relationships', 'weight', 'weight DOUBLE PRECISION NOT NULL DEFAULT 1.0');
|
|
248
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'relationships', 'confidence', 'confidence DOUBLE PRECISION NOT NULL DEFAULT 0.8');
|
|
249
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'relationships', 'confidence_label', 'confidence_label TEXT');
|
|
250
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'relationships', 'timestamp', 'timestamp TIMESTAMPTZ NOT NULL DEFAULT now()');
|
|
251
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'relationships', 'properties', 'properties JSONB NOT NULL DEFAULT ''{}''::jsonb');
|
|
252
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_graph_relationships_source', 'graph', 'relationships', ARRAY['source_entity_id'], 'CREATE INDEX IF NOT EXISTS idx_graph_relationships_source ON graph.relationships(source_entity_id)');
|
|
253
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_graph_relationships_target', 'graph', 'relationships', ARRAY['target_entity_id'], 'CREATE INDEX IF NOT EXISTS idx_graph_relationships_target ON graph.relationships(target_entity_id)');
|
|
254
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_graph_relationships_type', 'graph', 'relationships', ARRAY['type'], 'CREATE INDEX IF NOT EXISTS idx_graph_relationships_type ON graph.relationships(type)');
|
|
149
255
|
|
|
150
256
|
CREATE TABLE IF NOT EXISTS graph.entity_memories (
|
|
151
257
|
entity_id UUID NOT NULL REFERENCES graph.entities(id) ON DELETE CASCADE,
|
|
152
258
|
memory_id UUID NOT NULL REFERENCES graph.memory_records(id) ON DELETE CASCADE,
|
|
153
259
|
PRIMARY KEY(entity_id, memory_id)
|
|
154
260
|
);
|
|
155
|
-
|
|
261
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'entity_memories', 'entity_id', 'entity_id UUID');
|
|
262
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'entity_memories', 'memory_id', 'memory_id UUID');
|
|
263
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_graph_entity_memories_memory', 'graph', 'entity_memories', ARRAY['memory_id'], 'CREATE INDEX IF NOT EXISTS idx_graph_entity_memories_memory ON graph.entity_memories(memory_id)');
|
|
156
264
|
|
|
157
265
|
CREATE TABLE IF NOT EXISTS graph.agent_sessions (
|
|
158
266
|
id TEXT PRIMARY KEY,
|
|
@@ -163,7 +271,13 @@ CREATE TABLE IF NOT EXISTS graph.agent_sessions (
|
|
|
163
271
|
event_count INTEGER NOT NULL DEFAULT 0,
|
|
164
272
|
properties JSONB NOT NULL DEFAULT '{}'::jsonb
|
|
165
273
|
);
|
|
166
|
-
|
|
274
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_sessions', 'agent_id', 'agent_id TEXT NOT NULL DEFAULT ''system''');
|
|
275
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_sessions', 'project_name', 'project_name TEXT');
|
|
276
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_sessions', 'started_at', 'started_at TIMESTAMP(3) NOT NULL DEFAULT now()');
|
|
277
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_sessions', 'last_event_at', 'last_event_at TIMESTAMP(3) NOT NULL DEFAULT now()');
|
|
278
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_sessions', 'event_count', 'event_count INTEGER NOT NULL DEFAULT 0');
|
|
279
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_sessions', 'properties', 'properties JSONB NOT NULL DEFAULT ''{}''::jsonb');
|
|
280
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_agent_sessions_agent_time', 'graph', 'agent_sessions', ARRAY['agent_id', 'started_at'], 'CREATE INDEX IF NOT EXISTS idx_agent_sessions_agent_time ON graph.agent_sessions(agent_id, started_at)');
|
|
167
281
|
|
|
168
282
|
CREATE TABLE IF NOT EXISTS graph.agent_goals (
|
|
169
283
|
id TEXT PRIMARY KEY,
|
|
@@ -181,7 +295,20 @@ CREATE TABLE IF NOT EXISTS graph.agent_goals (
|
|
|
181
295
|
updated_at TIMESTAMP(3) NOT NULL,
|
|
182
296
|
source_memory_id TEXT
|
|
183
297
|
);
|
|
184
|
-
|
|
298
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goals', 'statement', 'statement TEXT NOT NULL DEFAULT ''''');
|
|
299
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goals', 'owner_agent_id', 'owner_agent_id TEXT');
|
|
300
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goals', 'project_name', 'project_name TEXT');
|
|
301
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goals', 'status', 'status TEXT NOT NULL DEFAULT ''open''');
|
|
302
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goals', 'priority', 'priority INTEGER NOT NULL DEFAULT 5');
|
|
303
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goals', 'success_criteria', 'success_criteria TEXT');
|
|
304
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goals', 'parent_goal_id', 'parent_goal_id TEXT');
|
|
305
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goals', 'due_at', 'due_at TIMESTAMP(3)');
|
|
306
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goals', 'achieved_at', 'achieved_at TIMESTAMP(3)');
|
|
307
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goals', 'supersedes_id', 'supersedes_id TEXT');
|
|
308
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goals', 'created_at', 'created_at TIMESTAMP(3) NOT NULL DEFAULT now()');
|
|
309
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goals', 'updated_at', 'updated_at TIMESTAMP(3) NOT NULL DEFAULT now()');
|
|
310
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goals', 'source_memory_id', 'source_memory_id TEXT');
|
|
311
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_agent_goals_project_status', 'graph', 'agent_goals', ARRAY['project_name', 'status', 'priority'], 'CREATE INDEX IF NOT EXISTS idx_agent_goals_project_status ON graph.agent_goals(project_name, status, priority)');
|
|
185
312
|
|
|
186
313
|
CREATE TABLE IF NOT EXISTS graph.agent_events (
|
|
187
314
|
id TEXT PRIMARY KEY,
|
|
@@ -202,10 +329,26 @@ CREATE TABLE IF NOT EXISTS graph.agent_events (
|
|
|
202
329
|
payload JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
203
330
|
created_at TIMESTAMP(3) NOT NULL
|
|
204
331
|
);
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
332
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'event_type', 'event_type TEXT NOT NULL DEFAULT ''event''');
|
|
333
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'occurred_at', 'occurred_at TIMESTAMP(3) NOT NULL DEFAULT now()');
|
|
334
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'sequence_index', 'sequence_index INTEGER NOT NULL DEFAULT 0');
|
|
335
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'actor_agent_id', 'actor_agent_id TEXT');
|
|
336
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'agent_role', 'agent_role TEXT');
|
|
337
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'project_name', 'project_name TEXT');
|
|
338
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'session_id', 'session_id TEXT');
|
|
339
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'task_id', 'task_id TEXT');
|
|
340
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'goal_id', 'goal_id TEXT');
|
|
341
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'parent_event_id', 'parent_event_id TEXT');
|
|
342
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'intention', 'intention TEXT');
|
|
343
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'outcome', 'outcome TEXT');
|
|
344
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'evidence_memory_id', 'evidence_memory_id TEXT');
|
|
345
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'impact', 'impact TEXT');
|
|
346
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'payload', 'payload JSONB NOT NULL DEFAULT ''{}''::jsonb');
|
|
347
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_events', 'created_at', 'created_at TIMESTAMP(3) NOT NULL DEFAULT now()');
|
|
348
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_agent_events_time', 'graph', 'agent_events', ARRAY['occurred_at', 'sequence_index'], 'CREATE INDEX IF NOT EXISTS idx_agent_events_time ON graph.agent_events(occurred_at, sequence_index)');
|
|
349
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_agent_events_session_seq', 'graph', 'agent_events', ARRAY['session_id', 'sequence_index'], 'CREATE INDEX IF NOT EXISTS idx_agent_events_session_seq ON graph.agent_events(session_id, sequence_index)');
|
|
350
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_agent_events_goal_time', 'graph', 'agent_events', ARRAY['goal_id', 'occurred_at'], 'CREATE INDEX IF NOT EXISTS idx_agent_events_goal_time ON graph.agent_events(goal_id, occurred_at)');
|
|
351
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_agent_events_memory', 'graph', 'agent_events', ARRAY['evidence_memory_id'], 'CREATE INDEX IF NOT EXISTS idx_agent_events_memory ON graph.agent_events(evidence_memory_id)');
|
|
209
352
|
|
|
210
353
|
CREATE TABLE IF NOT EXISTS graph.agent_goal_links (
|
|
211
354
|
id TEXT PRIMARY KEY,
|
|
@@ -215,7 +358,12 @@ CREATE TABLE IF NOT EXISTS graph.agent_goal_links (
|
|
|
215
358
|
target_type TEXT NOT NULL,
|
|
216
359
|
created_at TIMESTAMP(3) NOT NULL
|
|
217
360
|
);
|
|
218
|
-
|
|
361
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goal_links', 'goal_id', 'goal_id TEXT NOT NULL DEFAULT ''''');
|
|
362
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goal_links', 'link_type', 'link_type TEXT NOT NULL DEFAULT ''related''');
|
|
363
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goal_links', 'target_id', 'target_id TEXT NOT NULL DEFAULT ''''');
|
|
364
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goal_links', 'target_type', 'target_type TEXT NOT NULL DEFAULT ''unknown''');
|
|
365
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_goal_links', 'created_at', 'created_at TIMESTAMP(3) NOT NULL DEFAULT now()');
|
|
366
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_agent_goal_links_goal', 'graph', 'agent_goal_links', ARRAY['goal_id', 'target_type'], 'CREATE INDEX IF NOT EXISTS idx_agent_goal_links_goal ON graph.agent_goal_links(goal_id, target_type)');
|
|
219
367
|
|
|
220
368
|
CREATE TABLE IF NOT EXISTS graph.agent_semantic_labels (
|
|
221
369
|
id TEXT PRIMARY KEY,
|
|
@@ -228,8 +376,16 @@ CREATE TABLE IF NOT EXISTS graph.agent_semantic_labels (
|
|
|
228
376
|
created_at TIMESTAMP(3) NOT NULL,
|
|
229
377
|
updated_at TIMESTAMP(3) NOT NULL
|
|
230
378
|
);
|
|
231
|
-
|
|
232
|
-
|
|
379
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_semantic_labels', 'source_memory_id', 'source_memory_id TEXT NOT NULL DEFAULT ''''');
|
|
380
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_semantic_labels', 'event_id', 'event_id TEXT');
|
|
381
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_semantic_labels', 'labeler', 'labeler TEXT NOT NULL DEFAULT ''system''');
|
|
382
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_semantic_labels', 'schema_version', 'schema_version INTEGER NOT NULL DEFAULT 1');
|
|
383
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_semantic_labels', 'confidence', 'confidence DOUBLE PRECISION NOT NULL DEFAULT 0');
|
|
384
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_semantic_labels', 'labels', 'labels JSONB NOT NULL DEFAULT ''[]''::jsonb');
|
|
385
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_semantic_labels', 'created_at', 'created_at TIMESTAMP(3) NOT NULL DEFAULT now()');
|
|
386
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_semantic_labels', 'updated_at', 'updated_at TIMESTAMP(3) NOT NULL DEFAULT now()');
|
|
387
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_agent_semantic_labels_memory', 'graph', 'agent_semantic_labels', ARRAY['source_memory_id', 'labeler'], 'CREATE INDEX IF NOT EXISTS idx_agent_semantic_labels_memory ON graph.agent_semantic_labels(source_memory_id, labeler)');
|
|
388
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_agent_semantic_labels_event', 'graph', 'agent_semantic_labels', ARRAY['event_id'], 'CREATE INDEX IF NOT EXISTS idx_agent_semantic_labels_event ON graph.agent_semantic_labels(event_id)');
|
|
233
389
|
|
|
234
390
|
CREATE TABLE IF NOT EXISTS graph.agent_reflection_checkpoints (
|
|
235
391
|
id TEXT PRIMARY KEY,
|
|
@@ -249,8 +405,23 @@ CREATE TABLE IF NOT EXISTS graph.agent_reflection_checkpoints (
|
|
|
249
405
|
confidence DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
250
406
|
created_at TIMESTAMP(3) NOT NULL
|
|
251
407
|
);
|
|
252
|
-
|
|
253
|
-
|
|
408
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_reflection_checkpoints', 'project_name', 'project_name TEXT');
|
|
409
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_reflection_checkpoints', 'session_id', 'session_id TEXT');
|
|
410
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_reflection_checkpoints', 'window_start_at', 'window_start_at TIMESTAMP(3) NOT NULL DEFAULT now()');
|
|
411
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_reflection_checkpoints', 'window_end_at', 'window_end_at TIMESTAMP(3) NOT NULL DEFAULT now()');
|
|
412
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_reflection_checkpoints', 'event_count', 'event_count INTEGER NOT NULL DEFAULT 0');
|
|
413
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_reflection_checkpoints', 'goal_count', 'goal_count INTEGER NOT NULL DEFAULT 0');
|
|
414
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_reflection_checkpoints', 'success_count', 'success_count INTEGER NOT NULL DEFAULT 0');
|
|
415
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_reflection_checkpoints', 'failure_count', 'failure_count INTEGER NOT NULL DEFAULT 0');
|
|
416
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_reflection_checkpoints', 'risk_count', 'risk_count INTEGER NOT NULL DEFAULT 0');
|
|
417
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_reflection_checkpoints', 'summary', 'summary TEXT NOT NULL DEFAULT ''''');
|
|
418
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_reflection_checkpoints', 'learnings', 'learnings JSONB NOT NULL DEFAULT ''[]''::jsonb');
|
|
419
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_reflection_checkpoints', 'next_actions', 'next_actions JSONB NOT NULL DEFAULT ''[]''::jsonb');
|
|
420
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_reflection_checkpoints', 'evidence_event_ids', 'evidence_event_ids JSONB NOT NULL DEFAULT ''[]''::jsonb');
|
|
421
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_reflection_checkpoints', 'confidence', 'confidence DOUBLE PRECISION NOT NULL DEFAULT 0');
|
|
422
|
+
SELECT pg_temp.exe_add_column_if_missing('graph', 'agent_reflection_checkpoints', 'created_at', 'created_at TIMESTAMP(3) NOT NULL DEFAULT now()');
|
|
423
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_agent_reflection_project_time', 'graph', 'agent_reflection_checkpoints', ARRAY['project_name', 'window_end_at'], 'CREATE INDEX IF NOT EXISTS idx_agent_reflection_project_time ON graph.agent_reflection_checkpoints(project_name, window_end_at)');
|
|
424
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_agent_reflection_session_time', 'graph', 'agent_reflection_checkpoints', ARRAY['session_id', 'window_end_at'], 'CREATE INDEX IF NOT EXISTS idx_agent_reflection_session_time ON graph.agent_reflection_checkpoints(session_id, window_end_at)');
|
|
254
425
|
|
|
255
426
|
-- Minimal wiki projection tables used by projection-worker.ts before the
|
|
256
427
|
-- full exe-wiki service has accepted API-ingested documents.
|
|
@@ -262,6 +433,7 @@ CREATE TABLE IF NOT EXISTS wiki.workspaces (
|
|
|
262
433
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
263
434
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
264
435
|
);
|
|
436
|
+
SELECT pg_temp.exe_add_column_if_missing('wiki', 'workspaces', 'id', 'id INTEGER GENERATED BY DEFAULT AS IDENTITY');
|
|
265
437
|
|
|
266
438
|
CREATE TABLE IF NOT EXISTS wiki.workspace_documents (
|
|
267
439
|
id BIGSERIAL PRIMARY KEY,
|
|
@@ -274,8 +446,10 @@ CREATE TABLE IF NOT EXISTS wiki.workspace_documents (
|
|
|
274
446
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
275
447
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
276
448
|
);
|
|
277
|
-
|
|
278
|
-
|
|
449
|
+
SELECT pg_temp.exe_add_column_if_missing('wiki', 'workspace_documents', 'workspace_id', 'workspace_id INTEGER');
|
|
450
|
+
SELECT pg_temp.exe_add_column_if_missing('wiki', 'workspace_documents', 'docpath', 'docpath TEXT NOT NULL DEFAULT ''''');
|
|
451
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_wiki_workspace_documents_workspace', 'wiki', 'workspace_documents', ARRAY['workspace_id'], 'CREATE INDEX IF NOT EXISTS idx_wiki_workspace_documents_workspace ON wiki.workspace_documents(workspace_id)');
|
|
452
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_wiki_workspace_documents_docpath', 'wiki', 'workspace_documents', ARRAY['docpath'], 'CREATE INDEX IF NOT EXISTS idx_wiki_workspace_documents_docpath ON wiki.workspace_documents(docpath)');
|
|
279
453
|
|
|
280
454
|
-- Filtered schema — curated, deduplicated, entity-resolved data.
|
|
281
455
|
-- Projected from raw.raw_events by daemon workers.
|
|
@@ -295,9 +469,10 @@ CREATE TABLE IF NOT EXISTS filtered.contacts (
|
|
|
295
469
|
last_seen TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
296
470
|
UNIQUE(platform, platform_id)
|
|
297
471
|
);
|
|
472
|
+
SELECT pg_temp.exe_add_column_if_missing('filtered', 'contacts', 'id', 'id UUID DEFAULT gen_random_uuid()');
|
|
298
473
|
|
|
299
|
-
CREATE INDEX IF NOT EXISTS idx_filtered_contacts_phone ON filtered.contacts (phone);
|
|
300
|
-
CREATE INDEX IF NOT EXISTS idx_filtered_contacts_platform ON filtered.contacts (platform);
|
|
474
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_filtered_contacts_phone', 'filtered', 'contacts', ARRAY['phone'], 'CREATE INDEX IF NOT EXISTS idx_filtered_contacts_phone ON filtered.contacts (phone)');
|
|
475
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_filtered_contacts_platform', 'filtered', 'contacts', ARRAY['platform'], 'CREATE INDEX IF NOT EXISTS idx_filtered_contacts_platform ON filtered.contacts (platform)');
|
|
301
476
|
|
|
302
477
|
-- Normalized chat threads across platforms
|
|
303
478
|
-- Column names match projection-worker.ts ensureFilteredSchema (source of truth)
|
|
@@ -315,9 +490,9 @@ CREATE TABLE IF NOT EXISTS filtered.conversations (
|
|
|
315
490
|
UNIQUE(platform, source_ref)
|
|
316
491
|
);
|
|
317
492
|
|
|
318
|
-
CREATE INDEX IF NOT EXISTS idx_filtered_conversations_contact ON filtered.conversations (contact_id, sent_at DESC);
|
|
319
|
-
CREATE INDEX IF NOT EXISTS idx_filtered_conversations_ts ON filtered.conversations (sent_at DESC);
|
|
320
|
-
CREATE INDEX IF NOT EXISTS idx_filtered_conversations_thread_sent ON filtered.conversations (platform, thread_id, sent_at);
|
|
493
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_filtered_conversations_contact', 'filtered', 'conversations', ARRAY['contact_id', 'sent_at'], 'CREATE INDEX IF NOT EXISTS idx_filtered_conversations_contact ON filtered.conversations (contact_id, sent_at DESC)');
|
|
494
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_filtered_conversations_ts', 'filtered', 'conversations', ARRAY['sent_at'], 'CREATE INDEX IF NOT EXISTS idx_filtered_conversations_ts ON filtered.conversations (sent_at DESC)');
|
|
495
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_filtered_conversations_thread_sent', 'filtered', 'conversations', ARRAY['platform', 'thread_id', 'sent_at'], 'CREATE INDEX IF NOT EXISTS idx_filtered_conversations_thread_sent ON filtered.conversations (platform, thread_id, sent_at)');
|
|
321
496
|
|
|
322
497
|
-- Knowledge documents for wiki ingestion
|
|
323
498
|
-- Column names match projection-worker.ts ensureFilteredSchema (source of truth)
|
|
@@ -333,7 +508,7 @@ CREATE TABLE IF NOT EXISTS filtered.documents (
|
|
|
333
508
|
UNIQUE(source, source_id)
|
|
334
509
|
);
|
|
335
510
|
|
|
336
|
-
CREATE INDEX IF NOT EXISTS idx_filtered_documents_type ON filtered.documents (doc_type);
|
|
511
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_filtered_documents_type', 'filtered', 'documents', ARRAY['doc_type'], 'CREATE INDEX IF NOT EXISTS idx_filtered_documents_type ON filtered.documents (doc_type)');
|
|
337
512
|
|
|
338
513
|
-- Business events (meetings, orders, milestones)
|
|
339
514
|
CREATE TABLE IF NOT EXISTS filtered.events (
|
|
@@ -348,8 +523,8 @@ CREATE TABLE IF NOT EXISTS filtered.events (
|
|
|
348
523
|
created_at TIMESTAMPTZ DEFAULT now()
|
|
349
524
|
);
|
|
350
525
|
|
|
351
|
-
CREATE INDEX IF NOT EXISTS idx_filtered_events_type ON filtered.events (event_type, occurred_at DESC);
|
|
352
|
-
CREATE INDEX IF NOT EXISTS idx_filtered_events_contact ON filtered.events (contact_id);
|
|
526
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_filtered_events_type', 'filtered', 'events', ARRAY['event_type', 'occurred_at'], 'CREATE INDEX IF NOT EXISTS idx_filtered_events_type ON filtered.events (event_type, occurred_at DESC)');
|
|
527
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_filtered_events_contact', 'filtered', 'events', ARRAY['contact_id'], 'CREATE INDEX IF NOT EXISTS idx_filtered_events_contact ON filtered.events (contact_id)');
|
|
353
528
|
|
|
354
529
|
-- ---------------------------------------------------------------------------
|
|
355
530
|
-- Gateway schema — WhatsApp/messaging accounts, contacts, threads, messages.
|
|
@@ -364,6 +539,7 @@ CREATE TABLE IF NOT EXISTS gateway.accounts (
|
|
|
364
539
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
365
540
|
UNIQUE(platform, account_name)
|
|
366
541
|
);
|
|
542
|
+
SELECT pg_temp.exe_add_column_if_missing('gateway', 'accounts', 'id', 'id INTEGER GENERATED BY DEFAULT AS IDENTITY');
|
|
367
543
|
|
|
368
544
|
CREATE TABLE IF NOT EXISTS gateway.contacts (
|
|
369
545
|
id SERIAL PRIMARY KEY,
|
|
@@ -386,10 +562,11 @@ CREATE TABLE IF NOT EXISTS gateway.contacts (
|
|
|
386
562
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
387
563
|
UNIQUE(platform, platform_jid)
|
|
388
564
|
);
|
|
389
|
-
|
|
390
|
-
CREATE INDEX IF NOT EXISTS
|
|
391
|
-
CREATE INDEX IF NOT EXISTS
|
|
392
|
-
CREATE INDEX IF NOT EXISTS
|
|
565
|
+
SELECT pg_temp.exe_add_column_if_missing('gateway', 'contacts', 'id', 'id INTEGER GENERATED BY DEFAULT AS IDENTITY');
|
|
566
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_gw_contacts_phone', 'gateway', 'contacts', ARRAY['phone'], 'CREATE INDEX IF NOT EXISTS idx_gw_contacts_phone ON gateway.contacts(phone)');
|
|
567
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_gw_contacts_phone_jid', 'gateway', 'contacts', ARRAY['phone_jid'], 'CREATE INDEX IF NOT EXISTS idx_gw_contacts_phone_jid ON gateway.contacts(phone_jid)');
|
|
568
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_gw_contacts_lid_jid', 'gateway', 'contacts', ARRAY['lid_jid'], 'CREATE INDEX IF NOT EXISTS idx_gw_contacts_lid_jid ON gateway.contacts(lid_jid)');
|
|
569
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_gw_contacts_crm_person', 'gateway', 'contacts', ARRAY['crm_person_id'], 'CREATE INDEX IF NOT EXISTS idx_gw_contacts_crm_person ON gateway.contacts(crm_person_id)');
|
|
393
570
|
|
|
394
571
|
CREATE TABLE IF NOT EXISTS gateway.contact_identities (
|
|
395
572
|
id SERIAL PRIMARY KEY,
|
|
@@ -403,8 +580,8 @@ CREATE TABLE IF NOT EXISTS gateway.contact_identities (
|
|
|
403
580
|
last_seen TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
404
581
|
UNIQUE(platform, identity_type, identity_value)
|
|
405
582
|
);
|
|
406
|
-
CREATE INDEX IF NOT EXISTS idx_gw_ci_contact ON gateway.contact_identities(contact_id);
|
|
407
|
-
CREATE INDEX IF NOT EXISTS idx_gw_ci_value ON gateway.contact_identities(identity_value);
|
|
583
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_gw_ci_contact', 'gateway', 'contact_identities', ARRAY['contact_id'], 'CREATE INDEX IF NOT EXISTS idx_gw_ci_contact ON gateway.contact_identities(contact_id)');
|
|
584
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_gw_ci_value', 'gateway', 'contact_identities', ARRAY['identity_value'], 'CREATE INDEX IF NOT EXISTS idx_gw_ci_value ON gateway.contact_identities(identity_value)');
|
|
408
585
|
|
|
409
586
|
CREATE TABLE IF NOT EXISTS gateway.threads (
|
|
410
587
|
id SERIAL PRIMARY KEY,
|
|
@@ -440,8 +617,8 @@ CREATE TABLE IF NOT EXISTS gateway.messages (
|
|
|
440
617
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
441
618
|
UNIQUE(account_id, message_id)
|
|
442
619
|
);
|
|
443
|
-
CREATE INDEX IF NOT EXISTS idx_gw_msg_thread_ts ON gateway.messages(thread_id, timestamp);
|
|
444
|
-
CREATE INDEX IF NOT EXISTS idx_gw_msg_account ON gateway.messages(account_id, message_id);
|
|
620
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_gw_msg_thread_ts', 'gateway', 'messages', ARRAY['thread_id', 'timestamp'], 'CREATE INDEX IF NOT EXISTS idx_gw_msg_thread_ts ON gateway.messages(thread_id, timestamp)');
|
|
621
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_gw_msg_account', 'gateway', 'messages', ARRAY['account_id', 'message_id'], 'CREATE INDEX IF NOT EXISTS idx_gw_msg_account ON gateway.messages(account_id, message_id)');
|
|
445
622
|
|
|
446
623
|
CREATE TABLE IF NOT EXISTS gateway.groups (
|
|
447
624
|
id SERIAL PRIMARY KEY,
|
|
@@ -456,6 +633,7 @@ CREATE TABLE IF NOT EXISTS gateway.groups (
|
|
|
456
633
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
457
634
|
UNIQUE(platform, group_jid)
|
|
458
635
|
);
|
|
636
|
+
SELECT pg_temp.exe_add_column_if_missing('gateway', 'groups', 'id', 'id INTEGER GENERATED BY DEFAULT AS IDENTITY');
|
|
459
637
|
|
|
460
638
|
CREATE TABLE IF NOT EXISTS gateway.group_members (
|
|
461
639
|
id SERIAL PRIMARY KEY,
|
|
@@ -469,8 +647,8 @@ CREATE TABLE IF NOT EXISTS gateway.group_members (
|
|
|
469
647
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
470
648
|
UNIQUE(group_id, member_jid)
|
|
471
649
|
);
|
|
472
|
-
CREATE INDEX IF NOT EXISTS idx_gw_gm_member ON gateway.group_members(member_jid);
|
|
473
|
-
CREATE INDEX IF NOT EXISTS idx_gw_gm_phone ON gateway.group_members(phone_jid);
|
|
650
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_gw_gm_member', 'gateway', 'group_members', ARRAY['member_jid'], 'CREATE INDEX IF NOT EXISTS idx_gw_gm_member ON gateway.group_members(member_jid)');
|
|
651
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_gw_gm_phone', 'gateway', 'group_members', ARRAY['phone_jid'], 'CREATE INDEX IF NOT EXISTS idx_gw_gm_phone ON gateway.group_members(phone_jid)');
|
|
474
652
|
|
|
475
653
|
CREATE TABLE IF NOT EXISTS gateway.provider_keys (
|
|
476
654
|
id SERIAL PRIMARY KEY,
|
|
@@ -488,6 +666,7 @@ CREATE TABLE IF NOT EXISTS gateway.customers (
|
|
|
488
666
|
last_seen_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
489
667
|
interaction_count INT NOT NULL DEFAULT 0
|
|
490
668
|
);
|
|
669
|
+
SELECT pg_temp.exe_add_column_if_missing('gateway', 'customers', 'id', 'id UUID DEFAULT gen_random_uuid()');
|
|
491
670
|
|
|
492
671
|
CREATE TABLE IF NOT EXISTS gateway.customer_identities (
|
|
493
672
|
id SERIAL PRIMARY KEY,
|
|
@@ -510,8 +689,8 @@ CREATE TABLE IF NOT EXISTS gateway.sessions (
|
|
|
510
689
|
total_output_tokens INT NOT NULL DEFAULT 0,
|
|
511
690
|
status TEXT NOT NULL DEFAULT 'active'
|
|
512
691
|
);
|
|
513
|
-
CREATE INDEX IF NOT EXISTS idx_gw_sess_cust ON gateway.sessions(customer_id, bot_id);
|
|
514
|
-
CREATE INDEX IF NOT EXISTS idx_gw_sess_status ON gateway.sessions(status);
|
|
692
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_gw_sess_cust', 'gateway', 'sessions', ARRAY['customer_id', 'bot_id'], 'CREATE INDEX IF NOT EXISTS idx_gw_sess_cust ON gateway.sessions(customer_id, bot_id)');
|
|
693
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_gw_sess_status', 'gateway', 'sessions', ARRAY['status'], 'CREATE INDEX IF NOT EXISTS idx_gw_sess_status ON gateway.sessions(status)');
|
|
515
694
|
|
|
516
695
|
-- ---------------------------------------------------------------------------
|
|
517
696
|
-- Billing schema — licenses, stack releases, entitlements, deploy audits.
|
|
@@ -533,10 +712,11 @@ CREATE TABLE IF NOT EXISTS billing.licenses (
|
|
|
533
712
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
534
713
|
created_by TEXT NOT NULL DEFAULT 'system'
|
|
535
714
|
);
|
|
715
|
+
SELECT pg_temp.exe_add_column_if_missing('billing', 'licenses', 'key', 'key TEXT');
|
|
536
716
|
|
|
537
|
-
CREATE INDEX IF NOT EXISTS idx_billing_licenses_key ON billing.licenses (key);
|
|
538
|
-
CREATE INDEX IF NOT EXISTS idx_billing_licenses_status ON billing.licenses (status);
|
|
539
|
-
CREATE INDEX IF NOT EXISTS idx_billing_licenses_email ON billing.licenses (email);
|
|
717
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_billing_licenses_key', 'billing', 'licenses', ARRAY['key'], 'CREATE INDEX IF NOT EXISTS idx_billing_licenses_key ON billing.licenses (key)');
|
|
718
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_billing_licenses_status', 'billing', 'licenses', ARRAY['status'], 'CREATE INDEX IF NOT EXISTS idx_billing_licenses_status ON billing.licenses (status)');
|
|
719
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_billing_licenses_email', 'billing', 'licenses', ARRAY['email'], 'CREATE INDEX IF NOT EXISTS idx_billing_licenses_email ON billing.licenses (email)');
|
|
540
720
|
|
|
541
721
|
CREATE TABLE IF NOT EXISTS billing.stack_releases (
|
|
542
722
|
id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
|
|
@@ -550,8 +730,8 @@ CREATE TABLE IF NOT EXISTS billing.stack_releases (
|
|
|
550
730
|
created_by TEXT NOT NULL DEFAULT 'system'
|
|
551
731
|
);
|
|
552
732
|
|
|
553
|
-
CREATE INDEX IF NOT EXISTS idx_billing_stack_releases_status ON billing.stack_releases (status);
|
|
554
|
-
CREATE INDEX IF NOT EXISTS idx_billing_stack_releases_version ON billing.stack_releases (version);
|
|
733
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_billing_stack_releases_status', 'billing', 'stack_releases', ARRAY['status'], 'CREATE INDEX IF NOT EXISTS idx_billing_stack_releases_status ON billing.stack_releases (status)');
|
|
734
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_billing_stack_releases_version', 'billing', 'stack_releases', ARRAY['version'], 'CREATE INDEX IF NOT EXISTS idx_billing_stack_releases_version ON billing.stack_releases (version)');
|
|
555
735
|
|
|
556
736
|
CREATE TABLE IF NOT EXISTS billing.stack_entitlements (
|
|
557
737
|
id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
|
|
@@ -567,8 +747,8 @@ CREATE TABLE IF NOT EXISTS billing.stack_entitlements (
|
|
|
567
747
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
568
748
|
);
|
|
569
749
|
|
|
570
|
-
CREATE INDEX IF NOT EXISTS idx_billing_entitlements_token ON billing.stack_entitlements (token_hash);
|
|
571
|
-
CREATE INDEX IF NOT EXISTS idx_billing_entitlements_status ON billing.stack_entitlements (status);
|
|
750
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_billing_entitlements_token', 'billing', 'stack_entitlements', ARRAY['token_hash'], 'CREATE INDEX IF NOT EXISTS idx_billing_entitlements_token ON billing.stack_entitlements (token_hash)');
|
|
751
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_billing_entitlements_status', 'billing', 'stack_entitlements', ARRAY['status'], 'CREATE INDEX IF NOT EXISTS idx_billing_entitlements_status ON billing.stack_entitlements (status)');
|
|
572
752
|
|
|
573
753
|
CREATE TABLE IF NOT EXISTS billing.stack_deploy_audits (
|
|
574
754
|
id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
|
|
@@ -584,6 +764,6 @@ CREATE TABLE IF NOT EXISTS billing.stack_deploy_audits (
|
|
|
584
764
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
585
765
|
);
|
|
586
766
|
|
|
587
|
-
CREATE INDEX IF NOT EXISTS idx_billing_deploy_audits_license ON billing.stack_deploy_audits (license_key);
|
|
588
|
-
CREATE INDEX IF NOT EXISTS idx_billing_deploy_audits_status ON billing.stack_deploy_audits (status);
|
|
589
|
-
CREATE INDEX IF NOT EXISTS idx_billing_deploy_audits_started ON billing.stack_deploy_audits (started_at DESC NULLS LAST);
|
|
767
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_billing_deploy_audits_license', 'billing', 'stack_deploy_audits', ARRAY['license_key'], 'CREATE INDEX IF NOT EXISTS idx_billing_deploy_audits_license ON billing.stack_deploy_audits (license_key)');
|
|
768
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_billing_deploy_audits_status', 'billing', 'stack_deploy_audits', ARRAY['status'], 'CREATE INDEX IF NOT EXISTS idx_billing_deploy_audits_status ON billing.stack_deploy_audits (status)');
|
|
769
|
+
SELECT pg_temp.exe_create_index_if_columns_exist('idx_billing_deploy_audits_started', 'billing', 'stack_deploy_audits', ARRAY['started_at'], 'CREATE INDEX IF NOT EXISTS idx_billing_deploy_audits_started ON billing.stack_deploy_audits (started_at DESC NULLS LAST)');
|