From 3ecbe0fb4cc3de7944b9dcde8a5809db2004886c Mon Sep 17 00:00:00 2001 From: Nicolas Bouliol Date: Mon, 1 Jun 2026 17:27:17 +0200 Subject: [PATCH 1/5] chore(workflow executor): config to run mutliple instances --- .dockerignore | 12 ++++ .gitignore | 1 + packages/_example/.env.executors.example | 25 +++++++++ .../assets/nginx-executor-gateway.conf | 26 +++++++++ .../_example/docker-compose.executors.yml | 56 +++++++++++++++++++ packages/_example/package.json | 3 +- packages/workflow-executor/Dockerfile | 37 ++++++++++++ 7 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 packages/_example/.env.executors.example create mode 100644 packages/_example/assets/nginx-executor-gateway.conf create mode 100644 packages/_example/docker-compose.executors.yml create mode 100644 packages/workflow-executor/Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..baac920236 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +**/node_modules +**/dist +**/coverage +**/.nx +.git +.github +**/.env +**/.env.* +!**/.env.example +**/*.log +**/*.tsbuildinfo +api-reference diff --git a/.gitignore b/.gitignore index 7f68fbc18c..2246c5657a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ lerna-debug.log # Configuration .env .env-test +.env.executors .forestadmin-schema.json # yarn diff --git a/packages/_example/.env.executors.example b/packages/_example/.env.executors.example new file mode 100644 index 0000000000..05c3a6e5dd --- /dev/null +++ b/packages/_example/.env.executors.example @@ -0,0 +1,25 @@ +# Copy to .env.executors and fill in. Used by docker-compose.executors.yml. + +# Forest Admin secrets — Settings -> Environments. FOREST_AUTH_SECRET MUST match +# the auth secret of the agent that signs forest_session_token, or every request +# proxied to the executor gets a 401. +FOREST_ENV_SECRET= +FOREST_AUTH_SECRET= + +# IMPORTANT: inside the containers, localhost/127.0.0.1 means the container +# itself, NOT your host. Anything on your machine (agent, Forest backend, +# Postgres) must be reached via host.docker.internal with its real port. + +# Your existing local Postgres run store. Both executors share it. +DATABASE_URL=postgres://user:password@host.docker.internal:5432/workflow_executor + +# Your agent, reachable from inside the containers. +AGENT_URL=http://host.docker.internal:3351 + +# The Forest orchestrator. Defaults to https://api.forestadmin.com. For a LOCAL +# backend use http(s)://host.docker.internal: (NOT localhost). Use http:// +# if it serves plaintext, else you'll hit an SSL "wrong version number" error. +# FOREST_SERVER_URL=http://host.docker.internal:3001 + +# Optional — default shown. +POLLING_INTERVAL_MS=5000 \ No newline at end of file diff --git a/packages/_example/assets/nginx-executor-gateway.conf b/packages/_example/assets/nginx-executor-gateway.conf new file mode 100644 index 0000000000..bda730dc60 --- /dev/null +++ b/packages/_example/assets/nginx-executor-gateway.conf @@ -0,0 +1,26 @@ +# Round-robin gateway in front of the two workflow-executor instances. +# Stateless: trigger re-fetches the run server-side and getRun reads the shared +# DB, so any instance serves any request — no sticky sessions needed. + +upstream executors { + server executor-1:3400; + server executor-2:3400; +} + +server { + listen 3400; + + location / { + proxy_pass http://executors; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # Authorization / Cookie are forwarded by default; AI/MCP steps can be slow. + proxy_read_timeout 600s; + proxy_send_timeout 600s; + + # Retry the other instance on connection/5xx failure. + proxy_next_upstream error timeout http_502 http_503 http_504; + } +} diff --git a/packages/_example/docker-compose.executors.yml b/packages/_example/docker-compose.executors.yml new file mode 100644 index 0000000000..c0c32fd96b --- /dev/null +++ b/packages/_example/docker-compose.executors.yml @@ -0,0 +1,56 @@ +# Two workflow-executor instances behind an nginx round-robin gateway, sharing a +# single Postgres run store (so the write-ahead idempotency log is shared across +# instances). The store is YOUR existing local Postgres, reached via DATABASE_URL. +# +# cp .env.executors.example .env.executors # fill in secrets + DATABASE_URL +# docker compose --env-file .env.executors -f docker-compose.executors.yml up --build +# +# Point your agent at the gateway: workflowExecutorUrl: "http://localhost:3400". +# Your agent must be running on the host (executors probe AGENT_URL on startup). +# +# DATABASE_URL must use host.docker.internal (NOT localhost) to reach a Postgres +# running on your host, e.g. postgres://user:pass@host.docker.internal:5432/db + +name: workflow-executor-gateway + +x-executor-env: &executor-env + FOREST_ENV_SECRET: ${FOREST_ENV_SECRET} + FOREST_AUTH_SECRET: ${FOREST_AUTH_SECRET} + AGENT_URL: ${AGENT_URL:-http://host.docker.internal:3351} + FOREST_SERVER_URL: ${FOREST_SERVER_URL:-https://api.forestadmin.com} + DATABASE_URL: ${DATABASE_URL} + POLLING_INTERVAL_MS: ${POLLING_INTERVAL_MS:-5000} + HTTP_PORT: "3400" + NODE_TLS_REJECT_UNAUTHORIZED: 0 + +x-executor-common: &executor-common + image: forest-workflow-executor:local + restart: unless-stopped + extra_hosts: + - "host.docker.internal:host-gateway" + +services: + executor-1: + <<: *executor-common + build: + context: ../.. + dockerfile: packages/workflow-executor/Dockerfile + environment: *executor-env + + executor-2: + <<: *executor-common + environment: *executor-env + depends_on: + executor-1: + condition: service_started + + gateway: + image: nginx:1.27-alpine + restart: unless-stopped + ports: + - "3400:3400" + volumes: + - ./assets/nginx-executor-gateway.conf:/etc/nginx/conf.d/default.conf:ro + depends_on: + - executor-1 + - executor-2 diff --git a/packages/_example/package.json b/packages/_example/package.json index b3cd1a6dca..8713a24d69 100644 --- a/packages/_example/package.json +++ b/packages/_example/package.json @@ -50,7 +50,8 @@ "start:with-executor:ai-error": "concurrently --kill-others --names 'agent,executor' \"yarn start\" \"bash -c 'set -a && source .env && AGENT_URL=\\$EXECUTOR_AGENT_URL && DATABASE_URL=\\$EXECUTOR_DATABASE_URL && FORCE_AI_ERROR=true && until curl -s \\$EXECUTOR_AGENT_URL >/dev/null 2>&1; do sleep 1; done && tsx watch ../workflow-executor/src/cli.ts --pretty'\"", "db:executor:up": "cd ../workflow-executor/example && docker compose up -d", "db:executor:down": "cd ../workflow-executor/example && docker compose down", - "db:executor:reset": "cd ../workflow-executor/example && docker compose down -v && docker compose up -d" + "db:executor:reset": "cd ../workflow-executor/example && docker compose down -v && docker compose up -d", + "executor:docker": "docker compose --env-file .env.executors -f docker-compose.executors.yml up" }, "devDependencies": { "@types/node": "^20.12.12", diff --git a/packages/workflow-executor/Dockerfile b/packages/workflow-executor/Dockerfile new file mode 100644 index 0000000000..751b251d5d --- /dev/null +++ b/packages/workflow-executor/Dockerfile @@ -0,0 +1,37 @@ +# syntax=docker/dockerfile:1 +# +# Local/dev image for @forestadmin/workflow-executor. +# The build context MUST be the monorepo root (yarn workspaces + yarn.lock): +# +# docker build -f packages/workflow-executor/Dockerfile -t forest-workflow-executor:local . +# +# It is NOT optimized for production (ships the full workspace node_modules). + +FROM node:22-bookworm-slim AS builder +WORKDIR /app + +# --ignore-scripts skips husky, native (node-gyp) builds and binary downloads +# we don't need here: the runtime path is Postgres and `pg` is pure JS. The only +# native dep (sqlite3) is dev-only and unused at runtime. +COPY . . +RUN yarn install --frozen-lockfile --ignore-scripts + +# Build the executor and only its workspace dependencies (6 packages), in order. +RUN node_modules/.bin/lerna run build \ + --scope @forestadmin/workflow-executor \ + --include-dependencies + +FROM node:22-bookworm-slim AS runtime +WORKDIR /app +ENV NODE_ENV=production + +# Hoisted node_modules symlink into packages/*, so the whole tree must come along +# for the @forestadmin/* workspace symlinks to resolve. +COPY --from=builder /app ./ + +USER node + +# HTTP server (GET /runs/:runId, POST /runs/:runId/trigger). Override with HTTP_PORT. +EXPOSE 3400 + +CMD ["node", "packages/workflow-executor/dist/cli.js", "--json"] From d9e7d8f3003969cb79dfaf06f09e07957e21738f Mon Sep 17 00:00:00 2001 From: Nicolas Bouliol Date: Mon, 1 Jun 2026 17:45:32 +0200 Subject: [PATCH 2/5] chore(code review): move to workflow-executor/example --- packages/_example/package.json | 2 +- .../example}/.env.executors.example | 0 .../example}/docker-compose.executors.yml | 2 +- .../example}/nginx-executor-gateway.conf | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename packages/{_example => workflow-executor/example}/.env.executors.example (100%) rename packages/{_example => workflow-executor/example}/docker-compose.executors.yml (95%) rename packages/{_example/assets => workflow-executor/example}/nginx-executor-gateway.conf (100%) diff --git a/packages/_example/package.json b/packages/_example/package.json index 8713a24d69..f13c73d853 100644 --- a/packages/_example/package.json +++ b/packages/_example/package.json @@ -51,7 +51,7 @@ "db:executor:up": "cd ../workflow-executor/example && docker compose up -d", "db:executor:down": "cd ../workflow-executor/example && docker compose down", "db:executor:reset": "cd ../workflow-executor/example && docker compose down -v && docker compose up -d", - "executor:docker": "docker compose --env-file .env.executors -f docker-compose.executors.yml up" + "executor:docker": "docker compose --env-file ../workflow-executor/example/.env.executors -f ../workflow-executor/example/docker-compose.executors.yml up" }, "devDependencies": { "@types/node": "^20.12.12", diff --git a/packages/_example/.env.executors.example b/packages/workflow-executor/example/.env.executors.example similarity index 100% rename from packages/_example/.env.executors.example rename to packages/workflow-executor/example/.env.executors.example diff --git a/packages/_example/docker-compose.executors.yml b/packages/workflow-executor/example/docker-compose.executors.yml similarity index 95% rename from packages/_example/docker-compose.executors.yml rename to packages/workflow-executor/example/docker-compose.executors.yml index c0c32fd96b..7df7b7f339 100644 --- a/packages/_example/docker-compose.executors.yml +++ b/packages/workflow-executor/example/docker-compose.executors.yml @@ -50,7 +50,7 @@ services: ports: - "3400:3400" volumes: - - ./assets/nginx-executor-gateway.conf:/etc/nginx/conf.d/default.conf:ro + - ./nginx-executor-gateway.conf:/etc/nginx/conf.d/default.conf:ro depends_on: - executor-1 - executor-2 diff --git a/packages/_example/assets/nginx-executor-gateway.conf b/packages/workflow-executor/example/nginx-executor-gateway.conf similarity index 100% rename from packages/_example/assets/nginx-executor-gateway.conf rename to packages/workflow-executor/example/nginx-executor-gateway.conf From 29051a7a27ce0fde53d6432e73655702fd85c21e Mon Sep 17 00:00:00 2001 From: Nicolas Bouliol Date: Wed, 3 Jun 2026 11:16:23 +0200 Subject: [PATCH 3/5] chore: wrap docker compose up in concurrently to run agent + executors --- packages/_example/package.json | 4 +++- packages/workflow-executor/example/.env.example | 2 +- .../example/docker-compose.executors.yml | 8 +++++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/_example/package.json b/packages/_example/package.json index f13c73d853..da0863fa71 100644 --- a/packages/_example/package.json +++ b/packages/_example/package.json @@ -48,10 +48,12 @@ "start:with-executor:with-openai": "concurrently --kill-others --names 'agent,executor' \"yarn start\" \"bash -c 'set -a && source .env && AGENT_URL=\\$EXECUTOR_AGENT_URL && DATABASE_URL=\\$EXECUTOR_DATABASE_URL && AI_PROVIDER=openai && AI_MODEL=gpt-4o && AI_API_KEY=\\$OPENAI_API_KEY && until curl -s \\$EXECUTOR_AGENT_URL >/dev/null 2>&1; do sleep 1; done && tsx watch ../workflow-executor/src/cli.ts --pretty'\"", "start:with-executor:with-anthropic": "concurrently --kill-others --names 'agent,executor' \"yarn start\" \"bash -c 'set -a && source .env && AGENT_URL=\\$EXECUTOR_AGENT_URL && DATABASE_URL=\\$EXECUTOR_DATABASE_URL && AI_PROVIDER=anthropic && AI_MODEL=claude-sonnet-4-6 && AI_API_KEY=\\$ANTHROPIC_API_KEY && until curl -s \\$EXECUTOR_AGENT_URL >/dev/null 2>&1; do sleep 1; done && tsx watch ../workflow-executor/src/cli.ts --pretty'\"", "start:with-executor:ai-error": "concurrently --kill-others --names 'agent,executor' \"yarn start\" \"bash -c 'set -a && source .env && AGENT_URL=\\$EXECUTOR_AGENT_URL && DATABASE_URL=\\$EXECUTOR_DATABASE_URL && FORCE_AI_ERROR=true && until curl -s \\$EXECUTOR_AGENT_URL >/dev/null 2>&1; do sleep 1; done && tsx watch ../workflow-executor/src/cli.ts --pretty'\"", + "start:with-executor:multiple-instances": "concurrently --kill-others --names 'agent,executors' \"yarn start\" \"bash -c 'set -a && source .env && echo \\$EXECUTOR_AGENT_URL && npx wait-on \\$EXECUTOR_AGENT_URL && yarn start:executors:docker'\"", "db:executor:up": "cd ../workflow-executor/example && docker compose up -d", "db:executor:down": "cd ../workflow-executor/example && docker compose down", "db:executor:reset": "cd ../workflow-executor/example && docker compose down -v && docker compose up -d", - "executor:docker": "docker compose --env-file ../workflow-executor/example/.env.executors -f ../workflow-executor/example/docker-compose.executors.yml up" + "start:executors:docker": "docker compose --env-file ../workflow-executor/example/.env.executors -f ../workflow-executor/example/docker-compose.executors.yml up", + "build:executors:docker": "docker compose --env-file ../workflow-executor/example/.env.executors -f ../workflow-executor/example/docker-compose.executors.yml build" }, "devDependencies": { "@types/node": "^20.12.12", diff --git a/packages/workflow-executor/example/.env.example b/packages/workflow-executor/example/.env.example index 9e25c0d372..76e7dfaeb6 100644 --- a/packages/workflow-executor/example/.env.example +++ b/packages/workflow-executor/example/.env.example @@ -10,7 +10,7 @@ DATABASE_URL=postgres://executor:password@localhost:5459/workflow_executor # Optional — defaults shown HTTP_PORT=3400 -FOREST_SERVER_URL=https://api.forestadmin.com +FOREST_SERVER_URL=https://api.development.forestadmin.com POLLING_INTERVAL_MS=5000 # Optional local AI (all-or-nothing — falls back to server AI if any is missing) diff --git a/packages/workflow-executor/example/docker-compose.executors.yml b/packages/workflow-executor/example/docker-compose.executors.yml index 7df7b7f339..013d531aed 100644 --- a/packages/workflow-executor/example/docker-compose.executors.yml +++ b/packages/workflow-executor/example/docker-compose.executors.yml @@ -28,12 +28,18 @@ x-executor-common: &executor-common restart: unless-stopped extra_hosts: - "host.docker.internal:host-gateway" + # Forest local-dev domains resolve to 127.0.0.1 via the host's /etc/hosts (the orchestrator + # runs on the host). Inside containers 127.0.0.1 is the container itself, so map them to the + # host. Inert for non-dev setups (prod api.forestadmin.com is unaffected). + - "api.development.forestadmin.com:host-gateway" + - "app.development.forestadmin.com:host-gateway" + - "static.development.forestadmin.com:host-gateway" services: executor-1: <<: *executor-common build: - context: ../.. + context: ../../.. dockerfile: packages/workflow-executor/Dockerfile environment: *executor-env From 2d683de8ac8313105b1140f0e24caebb5b79b99d Mon Sep 17 00:00:00 2001 From: Nicolas Bouliol Date: Wed, 3 Jun 2026 12:03:55 +0200 Subject: [PATCH 4/5] fix: use _example env file when running from this folder --- packages/_example/package.json | 6 +++--- packages/workflow-executor/example/.env.executors.example | 8 +++++--- .../example/docker-compose.executors.yml | 6 +++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/_example/package.json b/packages/_example/package.json index da0863fa71..028d7063de 100644 --- a/packages/_example/package.json +++ b/packages/_example/package.json @@ -48,12 +48,12 @@ "start:with-executor:with-openai": "concurrently --kill-others --names 'agent,executor' \"yarn start\" \"bash -c 'set -a && source .env && AGENT_URL=\\$EXECUTOR_AGENT_URL && DATABASE_URL=\\$EXECUTOR_DATABASE_URL && AI_PROVIDER=openai && AI_MODEL=gpt-4o && AI_API_KEY=\\$OPENAI_API_KEY && until curl -s \\$EXECUTOR_AGENT_URL >/dev/null 2>&1; do sleep 1; done && tsx watch ../workflow-executor/src/cli.ts --pretty'\"", "start:with-executor:with-anthropic": "concurrently --kill-others --names 'agent,executor' \"yarn start\" \"bash -c 'set -a && source .env && AGENT_URL=\\$EXECUTOR_AGENT_URL && DATABASE_URL=\\$EXECUTOR_DATABASE_URL && AI_PROVIDER=anthropic && AI_MODEL=claude-sonnet-4-6 && AI_API_KEY=\\$ANTHROPIC_API_KEY && until curl -s \\$EXECUTOR_AGENT_URL >/dev/null 2>&1; do sleep 1; done && tsx watch ../workflow-executor/src/cli.ts --pretty'\"", "start:with-executor:ai-error": "concurrently --kill-others --names 'agent,executor' \"yarn start\" \"bash -c 'set -a && source .env && AGENT_URL=\\$EXECUTOR_AGENT_URL && DATABASE_URL=\\$EXECUTOR_DATABASE_URL && FORCE_AI_ERROR=true && until curl -s \\$EXECUTOR_AGENT_URL >/dev/null 2>&1; do sleep 1; done && tsx watch ../workflow-executor/src/cli.ts --pretty'\"", - "start:with-executor:multiple-instances": "concurrently --kill-others --names 'agent,executors' \"yarn start\" \"bash -c 'set -a && source .env && echo \\$EXECUTOR_AGENT_URL && npx wait-on \\$EXECUTOR_AGENT_URL && yarn start:executors:docker'\"", + "start:with-executor:multiple-instances": "concurrently --kill-others --names 'agent,executors' \"yarn start\" \"bash -c 'set -a && source .env && npx wait-on \\$EXECUTOR_AGENT_URL && yarn start:executors:docker'\"", "db:executor:up": "cd ../workflow-executor/example && docker compose up -d", "db:executor:down": "cd ../workflow-executor/example && docker compose down", "db:executor:reset": "cd ../workflow-executor/example && docker compose down -v && docker compose up -d", - "start:executors:docker": "docker compose --env-file ../workflow-executor/example/.env.executors -f ../workflow-executor/example/docker-compose.executors.yml up", - "build:executors:docker": "docker compose --env-file ../workflow-executor/example/.env.executors -f ../workflow-executor/example/docker-compose.executors.yml build" + "start:executors:docker": "docker compose --env-file .env -f ../workflow-executor/example/docker-compose.executors.yml up", + "build:executors:docker": "docker compose -f ../workflow-executor/example/docker-compose.executors.yml build" }, "devDependencies": { "@types/node": "^20.12.12", diff --git a/packages/workflow-executor/example/.env.executors.example b/packages/workflow-executor/example/.env.executors.example index 05c3a6e5dd..86ee59cfbc 100644 --- a/packages/workflow-executor/example/.env.executors.example +++ b/packages/workflow-executor/example/.env.executors.example @@ -11,15 +11,17 @@ FOREST_AUTH_SECRET= # Postgres) must be reached via host.docker.internal with its real port. # Your existing local Postgres run store. Both executors share it. -DATABASE_URL=postgres://user:password@host.docker.internal:5432/workflow_executor +EXECUTOR_DATABASE_URL=postgres://user:password@host.docker.internal:5432/workflow_executor # Your agent, reachable from inside the containers. -AGENT_URL=http://host.docker.internal:3351 +EXECUTOR_AGENT_URL=http://host.docker.internal:3351 -# The Forest orchestrator. Defaults to https://api.forestadmin.com. For a LOCAL +# The Forest orchestrator. Defaults to https://api.development.forestadmin.com. For a LOCAL # backend use http(s)://host.docker.internal: (NOT localhost). Use http:// # if it serves plaintext, else you'll hit an SSL "wrong version number" error. # FOREST_SERVER_URL=http://host.docker.internal:3001 +NODE_TLS_REJECT_UNAUTHORIZED=0 + # Optional — default shown. POLLING_INTERVAL_MS=5000 \ No newline at end of file diff --git a/packages/workflow-executor/example/docker-compose.executors.yml b/packages/workflow-executor/example/docker-compose.executors.yml index 013d531aed..6433bdf16a 100644 --- a/packages/workflow-executor/example/docker-compose.executors.yml +++ b/packages/workflow-executor/example/docker-compose.executors.yml @@ -16,9 +16,9 @@ name: workflow-executor-gateway x-executor-env: &executor-env FOREST_ENV_SECRET: ${FOREST_ENV_SECRET} FOREST_AUTH_SECRET: ${FOREST_AUTH_SECRET} - AGENT_URL: ${AGENT_URL:-http://host.docker.internal:3351} - FOREST_SERVER_URL: ${FOREST_SERVER_URL:-https://api.forestadmin.com} - DATABASE_URL: ${DATABASE_URL} + AGENT_URL: ${EXECUTOR_AGENT_URL:-http://host.docker.internal:3351} + FOREST_SERVER_URL: ${FOREST_SERVER_URL:-https://api.development.forestadmin.com} + DATABASE_URL: ${EXECUTOR_DATABASE_URL} POLLING_INTERVAL_MS: ${POLLING_INTERVAL_MS:-5000} HTTP_PORT: "3400" NODE_TLS_REJECT_UNAUTHORIZED: 0 From 65142154311c6b23091c13faab5fb5c7508c924d Mon Sep 17 00:00:00 2001 From: alban bertolini Date: Wed, 3 Jun 2026 12:27:23 +0200 Subject: [PATCH 5/5] fix: command and docker --- packages/_example/.env.example | 4 ++++ packages/_example/package.json | 2 +- .../workflow-executor/example/docker-compose.executors.yml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/_example/.env.example b/packages/_example/.env.example index ee5c43ae8f..7c4ebaf6e7 100644 --- a/packages/_example/.env.example +++ b/packages/_example/.env.example @@ -21,3 +21,7 @@ FOREST_AUTH_SECRET= EXECUTOR_AGENT_URL=http://localhost:3351 WORKFLOW_EXECUTOR_URL=http://localhost:3400 EXECUTOR_DATABASE_URL=postgresql://executor:password@localhost:5459/workflow_executor +# when start:with-executor:multiple-instances command +# EXECUTOR_AGENT_URL=http://host.docker.internal:3351 +# WORKFLOW_EXECUTOR_URL=http://localhost:3400 +# EXECUTOR_DATABASE_URL=postgresql://executor:password@host.docker.internal:5459/workflow_executor diff --git a/packages/_example/package.json b/packages/_example/package.json index 028d7063de..067902287a 100644 --- a/packages/_example/package.json +++ b/packages/_example/package.json @@ -48,7 +48,7 @@ "start:with-executor:with-openai": "concurrently --kill-others --names 'agent,executor' \"yarn start\" \"bash -c 'set -a && source .env && AGENT_URL=\\$EXECUTOR_AGENT_URL && DATABASE_URL=\\$EXECUTOR_DATABASE_URL && AI_PROVIDER=openai && AI_MODEL=gpt-4o && AI_API_KEY=\\$OPENAI_API_KEY && until curl -s \\$EXECUTOR_AGENT_URL >/dev/null 2>&1; do sleep 1; done && tsx watch ../workflow-executor/src/cli.ts --pretty'\"", "start:with-executor:with-anthropic": "concurrently --kill-others --names 'agent,executor' \"yarn start\" \"bash -c 'set -a && source .env && AGENT_URL=\\$EXECUTOR_AGENT_URL && DATABASE_URL=\\$EXECUTOR_DATABASE_URL && AI_PROVIDER=anthropic && AI_MODEL=claude-sonnet-4-6 && AI_API_KEY=\\$ANTHROPIC_API_KEY && until curl -s \\$EXECUTOR_AGENT_URL >/dev/null 2>&1; do sleep 1; done && tsx watch ../workflow-executor/src/cli.ts --pretty'\"", "start:with-executor:ai-error": "concurrently --kill-others --names 'agent,executor' \"yarn start\" \"bash -c 'set -a && source .env && AGENT_URL=\\$EXECUTOR_AGENT_URL && DATABASE_URL=\\$EXECUTOR_DATABASE_URL && FORCE_AI_ERROR=true && until curl -s \\$EXECUTOR_AGENT_URL >/dev/null 2>&1; do sleep 1; done && tsx watch ../workflow-executor/src/cli.ts --pretty'\"", - "start:with-executor:multiple-instances": "concurrently --kill-others --names 'agent,executors' \"yarn start\" \"bash -c 'set -a && source .env && npx wait-on \\$EXECUTOR_AGENT_URL && yarn start:executors:docker'\"", + "start:with-executor:multiple-instances": "concurrently --kill-others --names 'agent,executors' \"yarn start\" \"bash -c 'set -a && source .env && yarn start:executors:docker'\"", "db:executor:up": "cd ../workflow-executor/example && docker compose up -d", "db:executor:down": "cd ../workflow-executor/example && docker compose down", "db:executor:reset": "cd ../workflow-executor/example && docker compose down -v && docker compose up -d", diff --git a/packages/workflow-executor/example/docker-compose.executors.yml b/packages/workflow-executor/example/docker-compose.executors.yml index 6433bdf16a..5c6b8d00f9 100644 --- a/packages/workflow-executor/example/docker-compose.executors.yml +++ b/packages/workflow-executor/example/docker-compose.executors.yml @@ -25,7 +25,7 @@ x-executor-env: &executor-env x-executor-common: &executor-common image: forest-workflow-executor:local - restart: unless-stopped + restart: always extra_hosts: - "host.docker.internal:host-gateway" # Forest local-dev domains resolve to 127.0.0.1 via the host's /etc/hosts (the orchestrator