Skip to content
Open
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
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ dist
.env
.env.*
!.env.example
!.env.schema
data
artifacts
RESEARCH.md
Expand Down
46 changes: 39 additions & 7 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,20 +1,52 @@
# OpenDots template: the UI opens in setup state until these fields are configured.
# Varlock validates .env.schema. Run `npm run env:check` before starting.
HOST=127.0.0.1
PORT=4310
DATABASE_PATH=data/opendots.sqlite
# Keep OWNER_ID stable: it owns the persistent Intelligence conversations.
OWNER_ID=opendots-owner
# npm run dev allows http://127.0.0.1:5173; override for a different exact origin.
# npm run dev allows http://127.0.0.1:5173. Override for a different exact origin.
# APP_ORIGIN=http://127.0.0.1:5173
# Required for an external HOST binding (24+ characters); enables local login too.
# Required for an external HOST binding (24+ characters). Enables local login too.
# OWNER_TOKEN=

INTELLIGENCE_API_KEY=
# INTELLIGENCE_API_URL=
# INTELLIGENCE_WS_URL=

# Model provider. Configure one slot and set MODEL_PROVIDER.
# openai = OPENAI_* | anthropic = ANTHROPIC_* | cline-pass = CLINE_*
# claude-code = Claude subscription via `claude auth login` (local development)
# codex = ChatGPT subscription via `codex login` (local development)
# custom = any OpenAI-compatible endpoint via OPENAI_BASE_URL
MODEL_PROVIDER=openai
OPENAI_API_KEY=
OPENAI_BASE_URL=https://api.openai.com/v1
OPENAI_MODEL=
# Set the model ID accepted by your selected provider and account.

# Anthropic pay-per-token (console.anthropic.com).
# ANTHROPIC_API_KEY=
# ANTHROPIC_MODEL=
# ANTHROPIC_BASE_URL=https://api.anthropic.com/v1

# Cline Pass: key from app.cline.bot > Settings > API Keys.
# CLINE_API_KEY=
# CLINE_MODEL=
# CLINE_BASE_URL=https://api.cline.bot/api/v1

# Claude subscription: install Claude Code and run `claude auth login` first.
# The CLI owns authentication. Use npm run dev on this machine.
# Production and container startup refuse subscription providers.
# CLAUDE_AUTH_MODE=host
# CLAUDE_MODEL=
# CLAUDE_CWD=
# CLAUDE_PERMISSION_MODE=acceptEdits

# ChatGPT subscription harness: run `codex login` on this machine first.
# CODEX_AUTH_MODE=host
# CODEX_MODEL=
# CODEX_CWD=

# Optional isolated read-only public-page browser for WEB_SEARCH_PROVIDER=browser.
BROWSER_URL=http://127.0.0.1:4311
Expand All @@ -24,14 +56,14 @@ BROWSER_PORT=4311
# Use the same random 24+ character secret in app/browser. All redirects are blocked.
# Supply canonical public URLs. Use the separate browser container for isolation.

# Optional realtime speech; compute uses the same configured Intelligence thread.
# Optional realtime speech. Compute uses the same configured Intelligence thread.
VOICE_API_KEY=
VOICE_MODEL=
VOICE_NAME=marin

# Optional managed Slack channel; see docs/SETUP.md#slack.
# Optional managed Slack channel. See docs/SETUP.md#slack.
# Match the managed declaration name, not a Slack #conversation name.
# OpenTag calls this INTELLIGENCE_CHANNEL_NAME; OpenDots uses SLACK_CHANNEL_NAME.
# OpenTag calls this INTELLIGENCE_CHANNEL_NAME. OpenDots uses SLACK_CHANNEL_NAME.
# Allowlist both the Slack workspace and explicit Slack user IDs.
SLACK_CHANNEL_NAME=
SLACK_TEAM_ID=
Expand All @@ -50,7 +82,7 @@ COMPUTER_NAMESPACE=opendots
# ENGINE_SOCKET=/var/run/docker.sock

# Public-web provider. parallel (default), browser (URL-only), or disabled.
# Queries and selected URLs are sent to Parallel; sample mode makes no provider calls.
# Queries and selected URLs go to Parallel. Sample mode makes no provider calls.
WEB_SEARCH_PROVIDER=parallel
# Optional Bearer key for production/higher limits; anonymous MCP supports light use.
# Optional Bearer key for authenticated Parallel requests.
PARALLEL_API_KEY=
92 changes: 92 additions & 0 deletions .env.schema
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# OpenDots environment schema. Optional services can stay unconfigured.
# Runtime provider selection checks the selected slot's credentials and model.
# @defaultRequired=false
# @defaultSensitive=false
# @redactLogs=true
# @preventLeaks=true
# ---

# @type=enum(development,production,test)
NODE_ENV=production
# @type=boolean
OPENDOTS_CONTAINER=false
HOST=127.0.0.1
# @type=port
PORT=4310
DATABASE_PATH=data/opendots.sqlite
OWNER_ID=opendots-owner
# @type=url
APP_ORIGIN=
# Required by the server for non-loopback HOST bindings.
# @sensitive
OWNER_TOKEN=

# @sensitive
INTELLIGENCE_API_KEY=
# @type=url
INTELLIGENCE_API_URL=
# @type=url
INTELLIGENCE_WS_URL=

# Select one slot. Empty keys and models leave the app in setup state.
# @type=enum(openai,anthropic,cline-pass,claude-code,codex,custom,clinepass,cline_pass,claude_code,claude,claude-subscription,codex-subscription,chatgpt,openai-codex)
MODEL_PROVIDER=openai
# @sensitive
OPENAI_API_KEY=
# @type=url
OPENAI_BASE_URL=https://api.openai.com/v1
OPENAI_MODEL=
# @sensitive
ANTHROPIC_API_KEY=
ANTHROPIC_MODEL=
# @type=url
ANTHROPIC_BASE_URL=https://api.anthropic.com/v1
# @sensitive
CLINE_API_KEY=
CLINE_MODEL=
# @type=url
CLINE_BASE_URL=https://api.cline.bot/api/v1

# Subscription CLIs keep their own authentication. Local development only.
# @type=enum(host)
CLAUDE_AUTH_MODE=host
CLAUDE_MODEL=
CLAUDE_CWD=
# @type=enum(default,acceptEdits,plan,bypassPermissions)
CLAUDE_PERMISSION_MODE=acceptEdits
# @type=enum(host)
CODEX_AUTH_MODE=host
CODEX_MODEL=
CODEX_CWD=

# @type=url
BROWSER_URL=http://127.0.0.1:4311
# @sensitive
BROWSER_SECRET=
BROWSER_HOST=127.0.0.1
# @type=port
BROWSER_PORT=4311
# @sensitive
VOICE_API_KEY=
VOICE_MODEL=
VOICE_NAME=marin
SLACK_CHANNEL_NAME=
SLACK_TEAM_ID=
SLACK_USER_IDS=
SLACK_DOT_ID=
# @type=url
COMPUTER_SUPERVISOR_URL=
# @sensitive
COMPUTER_SUPERVISOR_TOKEN=
# @sensitive
COMPUTER_TOKEN=
COMPUTER_NAMESPACE=opendots
# Deployment settings used by compose.computers.yml.
# @type=number(min=1,isInt=true)
COMPUTER_MEMORY_BYTES=2147483648
COMPUTER_RUNTIME=
ENGINE_SOCKET=/var/run/docker.sock
# @type=enum(parallel,browser,disabled)
WEB_SEARCH_PROVIDER=parallel
# @sensitive
PARALLEL_API_KEY=
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ jobs:
node-version: '24'
cache: npm
- run: npm ci
- run: npm run env:check
- run: npm run check-format
- run: npm run lint
- run: npm run typecheck
- run: npm test
- run: npm run build
- run: npx playwright install --with-deps chromium
- run: npm run verify:themes
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ dist/
.env
.env.*
!.env.example
!.env.schema
.opendots/
artifacts/
playwright-report/
Expand Down
12 changes: 8 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,25 @@ COPY . .
RUN npm run build

FROM node:24-bookworm-slim AS app
ENV NODE_ENV=production HOST=0.0.0.0 PORT=4310 DATABASE_PATH=/data/opendots.sqlite
ENV NODE_ENV=production OPENDOTS_CONTAINER=true HOST=0.0.0.0 PORT=4310 DATABASE_PATH=/data/opendots.sqlite
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev && mkdir -p /data && chown node:node /data
COPY --from=build /app/dist ./dist
COPY .env.schema ./
COPY scripts/varlock.mjs ./scripts/varlock.mjs
USER node
EXPOSE 4310
CMD ["node", "dist/server/server/index.js"]
CMD ["npm", "start"]

FROM node:24-bookworm-slim AS browser
ENV NODE_ENV=production BROWSER_HOST=0.0.0.0 BROWSER_PORT=4311 PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
ENV NODE_ENV=production OPENDOTS_CONTAINER=true BROWSER_HOST=0.0.0.0 BROWSER_PORT=4311 PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev && npx playwright install --with-deps chromium && chmod -R a+rX /ms-playwright
COPY --from=build /app/dist/server ./dist/server
COPY .env.schema ./
COPY scripts/varlock.mjs ./scripts/varlock.mjs
USER node
EXPOSE 4311
CMD ["node", "dist/server/browser/index.js"]
CMD ["npm", "run", "browser:start"]
13 changes: 13 additions & 0 deletions compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ services:
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
OPENAI_BASE_URL: ${OPENAI_BASE_URL:-https://api.openai.com/v1}
OPENAI_MODEL: ${OPENAI_MODEL:-}
MODEL_PROVIDER: ${MODEL_PROVIDER:-openai}
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
ANTHROPIC_MODEL: ${ANTHROPIC_MODEL:-}
ANTHROPIC_BASE_URL: ${ANTHROPIC_BASE_URL:-https://api.anthropic.com/v1}
CLINE_API_KEY: ${CLINE_API_KEY:-}
CLINE_MODEL: ${CLINE_MODEL:-}
CLINE_BASE_URL: ${CLINE_BASE_URL:-https://api.cline.bot/api/v1}
# Subscription harnesses are local-dev only: run `claude auth login` /
# `codex login` on the host and use npm run dev, never Docker.
CLAUDE_AUTH_MODE: ${CLAUDE_AUTH_MODE:-host}
CLAUDE_MODEL: ${CLAUDE_MODEL:-}
CODEX_AUTH_MODE: ${CODEX_AUTH_MODE:-host}
CODEX_MODEL: ${CODEX_MODEL:-}
WEB_SEARCH_PROVIDER: ${WEB_SEARCH_PROVIDER:-parallel}
PARALLEL_API_KEY: ${PARALLEL_API_KEY:-}
BROWSER_URL: http://browser:4311
Expand Down
Loading