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
26 changes: 21 additions & 5 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,27 @@
"OPENAI_API_KEY": "sk-dev-placeholder-replace-me",
"JOBS_ENABLED": "false",
"QUEUE_ENABLED": "false",
"CORS_ALLOWED_ORIGINS": "*"
"CORS_ALLOWED_ORIGINS": "*",
"STELLAR_RPC_URL": "http://stellar:8000/soroban/rpc",
"SOROBAN_RPC_URL": "http://stellar:8000/soroban/rpc",
"STELLAR_NETWORK": "local",
"EVM_RPC_URL": "http://evm:8545"
},
"forwardPorts": [3000, 3001, 5432, 6379],
"forwardPorts": [3000, 3001, 5432, 6379, 7001, 8000, 8545, 9229],
"portsAttributes": {
"3000": { "label": "Frontend", "onAutoForward": "notify" },
"3001": { "label": "Backend API", "onAutoForward": "silent" },
"5432": { "label": "PostgreSQL", "onAutoForward": "ignore" },
"6379": { "label": "Redis", "onAutoForward": "ignore" }
"6379": { "label": "Redis", "onAutoForward": "ignore" },
"7001": { "label": "Stellar Core", "onAutoForward": "ignore" },
"8000": { "label": "Soroban RPC", "onAutoForward": "silent" },
"8545": { "label": "EVM node (Hardhat)", "onAutoForward": "silent" },
"9229": { "label": "Node debugger", "onAutoForward": "silent" }
},
"hostRequirements": {
"cpus": 4,
"memory": "8gb",
"storage": "32gb"
},
"postCreateCommand": "bash .devcontainer/post-create.sh",
"postStartCommand": "bash .devcontainer/post-start.sh",
Expand All @@ -54,13 +67,16 @@
"redhat.vscode-yaml",
"42Crunch.vscode-openapi",
"ms-azuretools.vscode-docker",
"github.vscode-github-actions"
"github.vscode-github-actions",
"vitest.explorer"
],
"settings": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"typescript.tsdk": "node_modules/typescript/lib",
"rust-analyzer.checkOnSave.command": "clippy"
"rust-analyzer.checkOnSave.command": "clippy",
"debug.javascript.autoAttachFilter": "smart",
"vitest.enable": true
}
}
},
Expand Down
116 changes: 115 additions & 1 deletion .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Devcontainer services: dev environment + Postgres + Redis.
# Devcontainer services: dev environment + Postgres + Redis + local chains.
# Used by VS Code / Cursor "Reopen in Container". Root docker-compose.yml
# provides the same Postgres/Redis stack for local (non-container) development.
#
Expand All @@ -9,6 +9,14 @@
#
# scripts/devcontainer.sh up
# # or: docker compose -f .devcontainer/docker-compose.yml --profile app up
#
# Resource allocation controls (issue #238) are env-driven so a machine under
# load can be dialled down without editing this file:
#
# DEV_POSTGRES_MEMORY=1G DEV_STELLAR_CPUS=2 docker compose ... up -d
#
# Apple Silicon: every image below publishes arm64 except the EVM node, which
# runs via Rosetta/QEMU emulation. Set DEV_EVM_PLATFORM=linux/arm64 to skip it.

services:
devcontainer:
Expand All @@ -23,9 +31,18 @@ services:
condition: service_healthy
redis:
condition: service_healthy
stellar:
condition: service_started
environment:
DATABASE_URL: postgresql://postgres:postgres@postgres:5432/agenticpay
REDIS_URL: redis://redis:6379
STELLAR_RPC_URL: http://stellar:8000/soroban/rpc
SOROBAN_RPC_URL: http://stellar:8000/soroban/rpc
deploy:
resources:
limits:
cpus: '${DEV_DEVCONTAINER_CPUS:-4.0}'
memory: ${DEV_DEVCONTAINER_MEMORY:-6G}

postgres:
image: postgres:16-alpine
Expand All @@ -41,6 +58,14 @@ services:
interval: 5s
timeout: 5s
retries: 10
deploy:
resources:
limits:
cpus: '${DEV_POSTGRES_CPUS:-1.0}'
memory: ${DEV_POSTGRES_MEMORY:-512M}
reservations:
cpus: '${DEV_POSTGRES_CPUS_RESERVED:-0.25}'
memory: ${DEV_POSTGRES_MEMORY_RESERVED:-128M}

redis:
image: redis:7-alpine
Expand All @@ -53,6 +78,76 @@ services:
interval: 5s
timeout: 3s
retries: 10
deploy:
resources:
limits:
cpus: '${DEV_REDIS_CPUS:-0.5}'
memory: ${DEV_REDIS_MEMORY:-256M}
reservations:
cpus: '${DEV_REDIS_CPUS_RESERVED:-0.1}'
memory: ${DEV_REDIS_MEMORY_RESERVED:-64M}

# Local Stellar/Soroban chain (issue #238 — "Local blockchain node").
# Mirrors the sandbox stack in docker-compose.sandbox.yml so contract
# behaviour is identical between sandbox and devcontainer workflows.
stellar:
image: stellar/stellar-quickstart:latest
restart: unless-stopped
ports:
- '${DEV_STELLAR_RPC_PORT:-8000}:8000'
- '${DEV_STELLAR_CORE_PORT:-7001}:7001'
environment:
SOROBAN_RPC_HOST: 0.0.0.0
SOROBAN_RPC_PORT: 8000
PUBNET: 'false'
TESTNET: 'false'
volumes:
# Ledger state survives `down`/`up` so deployed contracts are not lost.
- stellar-data:/opt/stellar
healthcheck:
test: ['CMD', 'curl', '--fail', 'http://localhost:8000/health']
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
deploy:
resources:
limits:
cpus: '${DEV_STELLAR_CPUS:-2.0}'
memory: ${DEV_STELLAR_MEMORY:-2G}
reservations:
cpus: '${DEV_STELLAR_CPUS_RESERVED:-0.5}'
memory: ${DEV_STELLAR_MEMORY_RESERVED:-512M}

# Local EVM chain for the Solidity contracts. Opt-in because the image is
# large and most work only needs Postgres/Redis/Soroban:
# scripts/devcontainer.sh evm
evm:
profiles: ['evm', 'app']
image: node:22-bookworm-slim
working_dir: /workspaces/agenticpay/contracts
platform: ${DEV_EVM_PLATFORM:-linux/amd64}
command: sh -c "npm install --no-audit --no-fund && npx hardhat node --hostname 0.0.0.0"
ports:
- '${DEV_EVM_PORT:-8545}:8545'
environment:
NODE_ENV: development
HARDHAT_NETWORK: localhost
volumes:
- ..:/workspaces/agenticpay:cached
- node-modules:/workspaces/agenticpay/node_modules
- hardhat-cache:/workspaces/agenticpay/contracts/.hardhat
healthcheck:
test: ['CMD', 'node', '-e', 'require("net").connect(8545).end()']
interval: 10s
timeout: 5s
retries: 10
start_period: 60s
deploy:
resources:
limits:
cpus: '${DEV_EVM_CPUS:-1.0}'
memory: ${DEV_EVM_MEMORY:-1G}

# One-time dependency install shared by the backend/frontend services.
deps:
Expand All @@ -76,6 +171,8 @@ services:
volumes:
- ..:/workspaces/agenticpay:cached
- node-modules:/workspaces/agenticpay/node_modules
# Persist the Rust/Soroban build cache between restarts.
- contract-target:/workspaces/agenticpay/contracts/target
environment:
NODE_ENV: development
PORT: '3001'
Expand All @@ -86,15 +183,24 @@ services:
QUEUE_ENABLED: 'false'
OPENAI_API_KEY: sk-dev-placeholder-replace-me
CORS_ALLOWED_ORIGINS: 'http://localhost:3000,http://localhost:3001'
STELLAR_RPC_URL: http://stellar:8000/soroban/rpc
SOROBAN_RPC_URL: http://stellar:8000/soroban/rpc
STELLAR_NETWORK: local
ports:
- '3001:3001'
- '${DEV_BACKEND_DEBUG_PORT:-9229}:9229'
depends_on:
deps:
condition: service_completed_successfully
postgres:
condition: service_healthy
redis:
condition: service_healthy
deploy:
resources:
limits:
cpus: '${DEV_BACKEND_CPUS:-2.0}'
memory: ${DEV_BACKEND_MEMORY:-2G}

frontend:
profiles: ['app']
Expand All @@ -118,8 +224,16 @@ services:
condition: service_completed_successfully
backend:
condition: service_started
deploy:
resources:
limits:
cpus: '${DEV_FRONTEND_CPUS:-2.0}'
memory: ${DEV_FRONTEND_MEMORY:-2G}

volumes:
postgres-data:
redis-data:
node-modules:
stellar-data:
hardhat-cache:
contract-target:
15 changes: 15 additions & 0 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ cd "$ROOT"

echo "==> AgenticPay devcontainer post-create"

# Debug configurations and tasks (Issue #238). `.vscode/` is gitignored, so the
# templates live in `.devcontainer/vscode/` and are copied in on create. Existing
# user files are never overwritten.
mkdir -p "$ROOT/.vscode"
for template in "$ROOT"/.devcontainer/vscode/*.json; do
[ -e "$template" ] || continue
target="$ROOT/.vscode/$(basename "$template")"
if [ -e "$target" ]; then
echo "==> Keeping existing .vscode/$(basename "$template")"
else
cp "$template" "$target"
echo "==> Installed .vscode/$(basename "$template")"
fi
done

# Rust WASM target (Soroban contracts)
if command -v rustup >/dev/null 2>&1; then
echo "==> Adding wasm32-unknown-unknown target"
Expand Down
8 changes: 6 additions & 2 deletions .devcontainer/post-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
set -euo pipefail

echo "==> Devcontainer ready"
echo " Postgres: postgresql://postgres:postgres@localhost:5432/agenticpay"
echo " Redis: redis://localhost:6379"
echo " Postgres: postgresql://postgres:postgres@localhost:5432/agenticpay"
echo " Redis: redis://localhost:6379"
echo " Soroban RPC: http://localhost:8000/soroban/rpc"
echo " Stellar Core: localhost:7001"
echo " EVM (opt-in): http://localhost:8545 (scripts/devcontainer.sh evm)"
echo " Debug: press F5 (configurations in .vscode/launch.json)"
77 changes: 77 additions & 0 deletions .devcontainer/vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
// Debug configurations for the devcontainer / local setup — Issue #238.
// Ports 3000/3001/9229 are forwarded by .devcontainer/devcontainer.json.
"version": "0.2.0",
"configurations": [
{
"name": "Backend: API (debug)",
"type": "node",
"request": "launch",
"runtimeExecutable": "npx",
"runtimeArgs": ["tsx", "watch", "--inspect=0.0.0.0:9229", "src/index.ts"],
"cwd": "${workspaceFolder}/backend",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"skipFiles": ["<node_internals>/**"]
},
{
"name": "Backend: API (no watch)",
"type": "node",
"request": "launch",
"runtimeExecutable": "npx",
"runtimeArgs": ["tsx", "--inspect=0.0.0.0:9229", "src/index.ts"],
"cwd": "${workspaceFolder}/backend",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"skipFiles": ["<node_internals>/**"]
},
{
"name": "Backend: current test file",
"type": "node",
"request": "launch",
"runtimeExecutable": "npx",
"runtimeArgs": ["vitest", "run", "${relativeFile}"],
"cwd": "${workspaceFolder}/backend",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"skipFiles": ["<node_internals>/**"]
},
{
"name": "Frontend: Next.js (debug)",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev", "--workspace=frontend"],
"cwd": "${workspaceFolder}",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"autoAttachChildProcesses": true,
"skipFiles": ["<node_internals>/**"]
},
{
"name": "Contracts: Soroban tests",
"type": "node",
"request": "launch",
"runtimeExecutable": "cargo",
"runtimeArgs": ["test", "--manifest-path", "${workspaceFolder}/contracts/Cargo.toml"],
"cwd": "${workspaceFolder}/contracts",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
},
{
"name": "Attach to backend (9229)",
"type": "node",
"request": "attach",
"port": 9229,
"restart": true,
"skipFiles": ["<node_internals>/**"]
}
],
"compounds": [
{
"name": "Full stack (backend + frontend)",
"configurations": ["Backend: API (debug)", "Frontend: Next.js (debug)"],
"stopAll": true
}
]
}
Loading
Loading