Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,6 @@ internal/contentviewer/dist/*

# Claude Code session files
.claude/

# Resolved dev ports written by dev/start.sh (auto-relocation)
dev/.dev-ports.env
8 changes: 5 additions & 3 deletions dev/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ services:
# connects via localhost, and an all-interfaces 0.0.0.0 bind both exposes
# the DB on the LAN and collides with any other specific-address :5432
# listener (e.g. a kubefwd-forwarded cluster Postgres on a 127.x alias).
- "127.0.0.1:5432:5432"
# Host port is auto-relocated by dev/start.sh (DEV_PG_PORT) when 5432 is
# held by another stack; container port stays 5432. Defaults to 5432.
- "127.0.0.1:${DEV_PG_PORT:-5432}:5432"
volumes:
- acme_postgres_data:/var/lib/postgresql/data
# Init script creates the mcp_test and apitest databases used by the
Expand Down Expand Up @@ -123,7 +125,7 @@ services:
command: 'server -s3 -s3.port=8333 -s3.config=/etc/seaweedfs/s3.json -dir=/data -volume.max=5'
ports:
# Loopback only, matching the other dev services (see postgres above).
- "127.0.0.1:9000:8333"
- "127.0.0.1:${DEV_S3_PORT:-9000}:8333"
volumes:
- acme_seaweed_data:/data
- ./seaweedfs-s3.json:/etc/seaweedfs/s3.json:ro
Expand Down Expand Up @@ -170,7 +172,7 @@ services:
image: ollama/ollama:0.30.6@sha256:fbaaecc6c632a73c2b4ca25ef52dbee0b68d07783fcb850f916404c004040f90
container_name: acme-dev-ollama
ports:
- "127.0.0.1:11434:11434"
- "127.0.0.1:${DEV_OLLAMA_PORT:-11434}:11434"
volumes:
- acme_ollama_data:/root/.ollama
healthcheck:
Expand Down
15 changes: 13 additions & 2 deletions dev/info.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@
# of truth is dev/platform.yaml (api_keys) and the dev Keycloak realm.
set -euo pipefail

# Load the ports resolved by the last `make dev`. start.sh auto-relocates the
# Go API and Ollama (among others) when their defaults are held by another
# stack; without these the banner below would print stale URLs. Falls back to
# the defaults when the file is absent (dev never started this session).
DEV_API_PORT=8080
DEV_OLLAMA_PORT=11434
if [ -f dev/.dev-ports.env ]; then
# shellcheck disable=SC1091
source dev/.dev-ports.env
fi

# Colors only when stdout is a terminal, so `make dev-info | pbcopy` and
# log redirects stay clean.
if [ -t 1 ]; then
Expand All @@ -18,12 +29,12 @@ fi
echo -e "${BOLD}${GREEN}Local dev login${NC}"
echo ""
echo -e " Portal UI: ${CYAN}http://localhost:5173/portal/${NC}"
echo -e " Go API: ${CYAN}http://localhost:8080${NC}"
echo -e " Go API: ${CYAN}http://localhost:${DEV_API_PORT}${NC}"
echo -e " API key: ${CYAN}acme-dev-key-2024${NC} (send as ${BOLD}X-API-Key${NC} header)"
echo ""
echo -e " ${BOLD}Portal sign-in (Keycloak OIDC)${NC}"
echo -e " ${CYAN}admin@example.com${NC} / ${CYAN}admin-password${NC} (dp_admin)"
echo -e " ${CYAN}analyst@example.com${NC} / ${CYAN}analyst-password${NC} (dp_analyst)"
echo -e " Keycloak admin console: ${CYAN}http://localhost:9090/admin${NC} (admin / admin)"
echo -e " Ollama embedder: ${CYAN}http://localhost:11434${NC} (model: nomic-embed-text — powers semantic indexing)"
echo -e " Ollama embedder: ${CYAN}http://localhost:${DEV_OLLAMA_PORT}${NC} (model: nomic-embed-text — powers semantic indexing)"
echo ""
12 changes: 7 additions & 5 deletions dev/platform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ apiVersion: v1
server:
name: acme-data-platform
transport: http
address: ":8080"
# DEV_API_PORT is auto-relocated by dev/start.sh when :8080 is held by
# another stack (e.g. a running DataHub). Defaults to 8080 when free.
address: ":${DEV_API_PORT:-8080}"
description: |
ACME Corp's unified data platform providing governed access to the enterprise
data warehouse (Trino/Iceberg), data catalog (DataHub), and object storage (S3).
Expand Down Expand Up @@ -99,7 +101,7 @@ oauth:
enabled: false

database:
dsn: "postgres://platform:platform_secret@localhost:5432/mcp_platform?sslmode=disable"
dsn: "postgres://platform:platform_secret@localhost:${DEV_PG_PORT:-5432}/mcp_platform?sslmode=disable"
max_open_conns: 10

# Six ACME personas
Expand Down Expand Up @@ -283,7 +285,7 @@ toolkits:
instances:
dev-s3:
enabled: true
endpoint: "http://localhost:9000"
endpoint: "http://localhost:${DEV_S3_PORT:-9000}"
region: "us-east-1"
access_key_id: "dev-access-key"
secret_access_key: "dev-secret-key"
Expand Down Expand Up @@ -317,15 +319,15 @@ tuning:

portal:
enabled: true
public_base_url: "http://localhost:8080"
public_base_url: "http://localhost:${DEV_API_PORT:-8080}"
s3_connection: dev-s3
s3_bucket: portal-assets

memory:
embedding:
provider: ollama
ollama:
url: "http://localhost:11434"
url: "http://localhost:${DEV_OLLAMA_PORT:-11434}"
model: "nomic-embed-text"

knowledge:
Expand Down
23 changes: 22 additions & 1 deletion dev/seed-s3.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
# This prevents clearing generated thumbnails on every dev restart.
set -euo pipefail

API="http://localhost:8080"
# DEV_API_PORT is exported by dev/start.sh (auto-relocated when 8080 is busy).
API="http://localhost:${DEV_API_PORT:-8080}"
API_KEY="acme-dev-key-2024"
CONTENT_DIR="dev/seed-content"

Expand All @@ -33,3 +34,23 @@ upload "asset-003" "$CONTENT_DIR/asset-003.jsx"
upload "asset-004" "$CONTENT_DIR/asset-004.md"
upload "asset-005" "$CONTENT_DIR/asset-005.svg"
upload "asset-006" "$CONTENT_DIR/asset-006.html"

# Content for the 120 generated demo assets (seed-0001..0120 from seed.sql).
# Reuse the five content files, cycled by the same (n % 5) index used in the
# SQL so each generated asset's bytes match its content_type. Uploaded in
# parallel batches so this stays a few seconds, not a minute of serial curls.
# The GET-404 skip in upload() makes reruns a no-op (preserves thumbnails).
GENERATED_CONTENT=(
"$CONTENT_DIR/asset-001.html" # n % 5 == 0 -> text/html
"$CONTENT_DIR/asset-002.csv" # n % 5 == 1 -> text/csv
"$CONTENT_DIR/asset-003.jsx" # n % 5 == 2 -> text/jsx
"$CONTENT_DIR/asset-004.md" # n % 5 == 3 -> text/markdown
"$CONTENT_DIR/asset-005.svg" # n % 5 == 4 -> image/svg+xml
)
for n in $(seq 1 120); do
id=$(printf 'seed-%04d' "$n")
upload "$id" "${GENERATED_CONTENT[$((n % 5))]}" &
# Cap concurrency so we do not open 120 sockets at once.
if [ "$((n % 16))" -eq 0 ]; then wait; fi
done
wait
33 changes: 32 additions & 1 deletion dev/seed.sql
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
-- 50 fresh audit events within the last hour (new each restart)
-- 8 knowledge insights in various states
-- 2 knowledge changesets (1 applied, 1 rolled back)
-- 6 portal assets with versions and shares
-- 6 curated portal assets (with versions and shares) + 120 generated demo
-- assets so the library exercises pagination (126 total under "Mine")
-- 3 portal collections with sections, items, and a public share

-- ============================================================================
Expand Down Expand Up @@ -561,6 +562,36 @@ ON CONFLICT (id) DO UPDATE SET
content_type = EXCLUDED.content_type,
tags = EXCLUDED.tags;

-- Bulk demo assets (120) so the portal library has enough volume to exercise
-- pagination / "Load more" out of the box — six assets never surfaced the
-- 50-per-page behaviour. All owned by apikey:admin (the acme-dev-key-2024 API
-- key, so they show under "Mine"), content type cycled through the five kinds,
-- created_at staggered by the hour so created_at DESC ordering is stable.
-- Content is uploaded per asset by seed-s3.sh (reusing the five content files),
-- so the placeholder s3_key here is replaced by a real versioned key on upload.
INSERT INTO portal_assets (
id, owner_id, owner_email, name, description, content_type,
s3_bucket, s3_key, size_bytes, tags, provenance, session_id,
current_version, created_at, updated_at
)
SELECT
'seed-' || lpad(n::text, 4, '0'),
'apikey:admin', 'admin@apikey.local',
(ARRAY['Sales Dashboard','Inventory Export','Store Comparison','Pipeline Notes','Regional Heatmap'])[(n % 5) + 1]
|| ' ' || lpad(n::text, 4, '0'),
'Generated demo asset #' || n || ' — seeded so the portal library exercises pagination.',
(ARRAY['text/html','text/csv','text/jsx','text/markdown','image/svg+xml'])[(n % 5) + 1],
'portal-assets',
'portal/apikey:admin/seed-' || lpad(n::text, 4, '0') || '/v1/content'
|| (ARRAY['.html','.csv','.jsx','.md','.svg'])[(n % 5) + 1],
(ARRAY[4280, 15720, 6340, 2890, 8150])[(n % 5) + 1],
jsonb_build_array('demo', (ARRAY['sales','inventory','stores','pipeline','regional'])[(n % 5) + 1]),
'{"tool": "save_artifact", "session_id": "sess-demo"}'::jsonb,
'sess-demo-' || n, 1,
NOW() - (n || ' hours')::interval, NOW() - (n || ' hours')::interval
FROM generate_series(1, 120) AS n
ON CONFLICT (id) DO NOTHING;

-- Asset versions (one per asset, matching the current_version=1)
INSERT INTO portal_asset_versions (
id, asset_id, version, s3_key, s3_bucket, content_type, size_bytes,
Expand Down
Loading
Loading