mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-18 04:04:24 +00:00
Rename Factory to Foundry
This commit is contained in:
parent
0a8fda040b
commit
324de36577
256 changed files with 605 additions and 603 deletions
|
|
@ -17,7 +17,7 @@ coverage/
|
||||||
# Environment
|
# Environment
|
||||||
.env
|
.env
|
||||||
.env.*
|
.env.*
|
||||||
.sandbox-agent-factory/
|
.sandbox-agent-foundry/
|
||||||
|
|
||||||
# IDE
|
# IDE
|
||||||
.idea/
|
.idea/
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
APP_URL=http://localhost:4173
|
APP_URL=http://localhost:4173
|
||||||
BETTER_AUTH_URL=http://localhost:4173
|
BETTER_AUTH_URL=http://localhost:4173
|
||||||
BETTER_AUTH_SECRET=sandbox-agent-factory-development-only-change-me
|
BETTER_AUTH_SECRET=sandbox-agent-foundry-development-only-change-me
|
||||||
GITHUB_REDIRECT_URI=http://localhost:4173/api/rivet/app/auth/github/callback
|
GITHUB_REDIRECT_URI=http://localhost:4173/api/rivet/app/auth/github/callback
|
||||||
|
|
||||||
# Fill these in when enabling live GitHub OAuth.
|
# Fill these in when enabling live GitHub OAuth.
|
||||||
|
|
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -49,12 +49,14 @@ Cargo.lock
|
||||||
.claude/
|
.claude/
|
||||||
.opencode/
|
.opencode/
|
||||||
.context/
|
.context/
|
||||||
factory/.context/
|
foundry/.context/
|
||||||
|
**/.sandbox-agent-factory/
|
||||||
|
**/.sandbox-agent-foundry/
|
||||||
|
|
||||||
# Example temp files
|
# Example temp files
|
||||||
.tmp-upload/
|
.tmp-upload/
|
||||||
*.db
|
*.db
|
||||||
.sandbox-agent-factory/
|
.sandbox-agent-foundry/
|
||||||
.openhandoff/
|
.openhandoff/
|
||||||
|
|
||||||
# CLI binaries (downloaded during npm publish)
|
# CLI binaries (downloaded during npm publish)
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@
|
||||||
- `research/acp/todo.md`
|
- `research/acp/todo.md`
|
||||||
- `research/friction/rivetkit.md`
|
- `research/friction/rivetkit.md`
|
||||||
- `research/friction/sandbox-agent-sdk.md`
|
- `research/friction/sandbox-agent-sdk.md`
|
||||||
- `research/friction/factory.md`
|
- `research/friction/foundry.md`
|
||||||
|
|
||||||
## Change Tracking
|
## Change Tracking
|
||||||
|
|
||||||
|
|
@ -114,7 +114,7 @@
|
||||||
- `research/acp/friction.md` — ACP protocol, migration, and spec issues.
|
- `research/acp/friction.md` — ACP protocol, migration, and spec issues.
|
||||||
- `research/friction/rivetkit.md` — RivetKit runtime, actor model, queues, keys, workflows.
|
- `research/friction/rivetkit.md` — RivetKit runtime, actor model, queues, keys, workflows.
|
||||||
- `research/friction/sandbox-agent-sdk.md` — Sandbox Agent SDK/API, TypeScript clients, ACP HTTP client.
|
- `research/friction/sandbox-agent-sdk.md` — Sandbox Agent SDK/API, TypeScript clients, ACP HTTP client.
|
||||||
- `research/friction/factory.md` — Factory product development, frontend, backend, client.
|
- `research/friction/foundry.md` — Foundry product development, frontend, backend, client.
|
||||||
- Friction log entry format (all logs use the same template):
|
- Friction log entry format (all logs use the same template):
|
||||||
```
|
```
|
||||||
- Date:
|
- Date:
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ sandbox-agent server --no-token --host 127.0.0.1 --port 2468
|
||||||
|
|
||||||
[Quickstart](https://sandboxagent.dev/docs/quickstart) — [Deployment guides](https://sandboxagent.dev/docs/deploy)
|
[Quickstart](https://sandboxagent.dev/docs/quickstart) — [Deployment guides](https://sandboxagent.dev/docs/deploy)
|
||||||
|
|
||||||
Factory self-hosting setup for auth, GitHub, and billing: [docs/deploy/factory-self-hosting.mdx](docs/deploy/factory-self-hosting.mdx)
|
Foundry self-hosting setup for auth, GitHub, and billing: [docs/deploy/foundry-self-hosting.mdx](docs/deploy/foundry-self-hosting.mdx)
|
||||||
|
|
||||||
### CLI
|
### CLI
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
---
|
---
|
||||||
title: "Factory Self-Hosting"
|
title: "Foundry Self-Hosting"
|
||||||
description: "Environment, credentials, and deployment setup for Sandbox Agent Factory auth, GitHub, and billing."
|
description: "Environment, credentials, and deployment setup for Sandbox Agent Foundry auth, GitHub, and billing."
|
||||||
---
|
---
|
||||||
|
|
||||||
This guide documents the deployment contract for the Factory product surface: app auth, GitHub onboarding, repository import, and billing.
|
This guide documents the deployment contract for the Foundry product surface: app auth, GitHub onboarding, repository import, and billing.
|
||||||
|
|
||||||
It also covers the local-development bootstrap that uses `.env.development` only when `NODE_ENV=development`.
|
It also covers the local-development bootstrap that uses `.env.development` only when `NODE_ENV=development`.
|
||||||
|
|
||||||
## Local Development
|
## Local Development
|
||||||
|
|
||||||
For backend local development, the Factory backend now supports a development-only dotenv bootstrap:
|
For backend local development, the Foundry backend now supports a development-only dotenv bootstrap:
|
||||||
|
|
||||||
- It loads `.env.development.local` and `.env.development`
|
- It loads `.env.development.local` and `.env.development`
|
||||||
- It does this **only** when `NODE_ENV=development`
|
- It does this **only** when `NODE_ENV=development`
|
||||||
|
|
@ -26,7 +26,7 @@ cp .env.development.example .env.development
|
||||||
Run the backend with:
|
Run the backend with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
just factory-backend-start
|
just foundry-backend-start
|
||||||
```
|
```
|
||||||
|
|
||||||
That recipe sets `NODE_ENV=development`, which enables the dotenv loader.
|
That recipe sets `NODE_ENV=development`, which enables the dotenv loader.
|
||||||
|
|
@ -37,7 +37,7 @@ These values can be safely defaulted for local development:
|
||||||
|
|
||||||
- `APP_URL=http://localhost:4173`
|
- `APP_URL=http://localhost:4173`
|
||||||
- `BETTER_AUTH_URL=http://localhost:4173`
|
- `BETTER_AUTH_URL=http://localhost:4173`
|
||||||
- `BETTER_AUTH_SECRET=sandbox-agent-factory-development-only-change-me`
|
- `BETTER_AUTH_SECRET=sandbox-agent-foundry-development-only-change-me`
|
||||||
- `GITHUB_REDIRECT_URI=http://localhost:4173/api/rivet/app/auth/github/callback`
|
- `GITHUB_REDIRECT_URI=http://localhost:4173/api/rivet/app/auth/github/callback`
|
||||||
|
|
||||||
These should be treated as development-only values.
|
These should be treated as development-only values.
|
||||||
|
|
@ -71,7 +71,7 @@ Use GitHub OAuth for:
|
||||||
|
|
||||||
## GitHub App
|
## GitHub App
|
||||||
|
|
||||||
If your Factory deployment uses GitHub App-backed organization install and repo import, also configure:
|
If your Foundry deployment uses GitHub App-backed organization install and repo import, also configure:
|
||||||
|
|
||||||
| Variable | Required | Notes |
|
| Variable | Required | Notes |
|
||||||
|---|---:|---|
|
|---|---:|---|
|
||||||
|
|
@ -139,7 +139,7 @@ Stripe should own:
|
||||||
|
|
||||||
## Mock Invariant
|
## Mock Invariant
|
||||||
|
|
||||||
Factory’s mock client path should continue to work end to end even when the real auth/GitHub/Stripe path exists.
|
Foundry’s mock client path should continue to work end to end even when the real auth/GitHub/Stripe path exists.
|
||||||
|
|
||||||
That includes:
|
That includes:
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@
|
||||||
"icon": "server",
|
"icon": "server",
|
||||||
"pages": [
|
"pages": [
|
||||||
"deploy/local",
|
"deploy/local",
|
||||||
"deploy/factory-self-hosting",
|
"deploy/foundry-self-hosting",
|
||||||
"deploy/computesdk",
|
"deploy/computesdk",
|
||||||
"deploy/e2b",
|
"deploy/e2b",
|
||||||
"deploy/daytona",
|
"deploy/daytona",
|
||||||
|
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
name: sandbox-agent-factory-mock
|
|
||||||
|
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
build:
|
|
||||||
context: ..
|
|
||||||
dockerfile: factory/docker/frontend.dev.Dockerfile
|
|
||||||
working_dir: /app
|
|
||||||
environment:
|
|
||||||
HOME: "/tmp"
|
|
||||||
FACTORY_FRONTEND_CLIENT_MODE: "mock"
|
|
||||||
ports:
|
|
||||||
- "4174:4173"
|
|
||||||
volumes:
|
|
||||||
- "..:/app"
|
|
||||||
- "./.sandbox-agent-factory:/app/factory/.sandbox-agent-factory"
|
|
||||||
# Use Linux-native workspace dependencies inside the container instead of host node_modules.
|
|
||||||
- "sandbox-agent-factory-mock_node_modules:/app/node_modules"
|
|
||||||
- "sandbox-agent-factory-mock_client_node_modules:/app/factory/packages/client/node_modules"
|
|
||||||
- "sandbox-agent-factory-mock_frontend_errors_node_modules:/app/factory/packages/frontend-errors/node_modules"
|
|
||||||
- "sandbox-agent-factory-mock_frontend_node_modules:/app/factory/packages/frontend/node_modules"
|
|
||||||
- "sandbox-agent-factory-mock_shared_node_modules:/app/factory/packages/shared/node_modules"
|
|
||||||
- "sandbox-agent-factory-mock_pnpm_store:/tmp/.local/share/pnpm/store"
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
sandbox-agent-factory-mock_node_modules: {}
|
|
||||||
sandbox-agent-factory-mock_client_node_modules: {}
|
|
||||||
sandbox-agent-factory-mock_frontend_errors_node_modules: {}
|
|
||||||
sandbox-agent-factory-mock_frontend_node_modules: {}
|
|
||||||
sandbox-agent-factory-mock_shared_node_modules: {}
|
|
||||||
sandbox-agent-factory-mock_pnpm_store: {}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
declare module "@sandbox-agent/factory-client/view-model" {
|
|
||||||
export {
|
|
||||||
HANDOFF_STATUS_GROUPS,
|
|
||||||
groupTaskStatus,
|
|
||||||
} from "@sandbox-agent/factory-client";
|
|
||||||
export type { TaskStatusGroup } from "@sandbox-agent/factory-client";
|
|
||||||
}
|
|
||||||
|
|
@ -30,19 +30,19 @@ Use `pnpm` workspaces and Turborepo.
|
||||||
|
|
||||||
**Always use Docker Compose to run dev servers.** Do not start the backend, frontend, or any other long-running service directly via `bun`, `pnpm dev`, Vite, or tmux. All dev services must run through the Compose stack so that networking, environment variables, and service dependencies are consistent.
|
**Always use Docker Compose to run dev servers.** Do not start the backend, frontend, or any other long-running service directly via `bun`, `pnpm dev`, Vite, or tmux. All dev services must run through the Compose stack so that networking, environment variables, and service dependencies are consistent.
|
||||||
|
|
||||||
- Start the full dev stack (real backend): `just factory-dev`
|
- Start the full dev stack (real backend): `just foundry-dev`
|
||||||
- Stop the dev stack: `just factory-dev-down`
|
- Stop the dev stack: `just foundry-dev-down`
|
||||||
- Tail dev logs: `just factory-dev-logs`
|
- Tail dev logs: `just foundry-dev-logs`
|
||||||
- Start the mock dev stack (frontend-only, no backend): `just factory-dev-mock`
|
- Start the mock dev stack (frontend-only, no backend): `just foundry-dev-mock`
|
||||||
- Stop the mock stack: `just factory-dev-mock-down`
|
- Stop the mock stack: `just foundry-dev-mock-down`
|
||||||
- Tail mock logs: `just factory-dev-mock-logs`
|
- Tail mock logs: `just foundry-dev-mock-logs`
|
||||||
- Start the production-build preview stack: `just factory-preview`
|
- Start the production-build preview stack: `just foundry-preview`
|
||||||
- Stop the preview stack: `just factory-preview-down`
|
- Stop the preview stack: `just foundry-preview-down`
|
||||||
- Tail preview logs: `just factory-preview-logs`
|
- Tail preview logs: `just foundry-preview-logs`
|
||||||
|
|
||||||
The real dev server runs on port 4173 (frontend) + 7741 (backend). The mock dev server runs on port 4174 (frontend only). Both can run simultaneously.
|
The real dev server runs on port 4173 (frontend) + 7741 (backend). The mock dev server runs on port 4174 (frontend only). Both can run simultaneously.
|
||||||
|
|
||||||
When making code changes, restart or recreate the relevant Compose services so the running app reflects the latest code (e.g. `docker compose -f factory/compose.dev.yaml up -d --build backend`).
|
When making code changes, restart or recreate the relevant Compose services so the running app reflects the latest code (e.g. `docker compose -f foundry/compose.dev.yaml up -d --build backend`).
|
||||||
|
|
||||||
## Mock vs Real Backend — UI Change Policy
|
## Mock vs Real Backend — UI Change Policy
|
||||||
|
|
||||||
|
|
@ -60,7 +60,7 @@ When making code changes, restart or recreate the relevant Compose services so t
|
||||||
|
|
||||||
- Install deps: `pnpm install`
|
- Install deps: `pnpm install`
|
||||||
- Full active-workspace validation: `pnpm -w typecheck`, `pnpm -w build`, `pnpm -w test`
|
- Full active-workspace validation: `pnpm -w typecheck`, `pnpm -w build`, `pnpm -w test`
|
||||||
- Start the frontend against the mock workbench client (no backend needed): `FACTORY_FRONTEND_CLIENT_MODE=mock pnpm --filter @sandbox-agent/factory-frontend dev`
|
- Start the frontend against the mock workbench client (no backend needed): `FOUNDRY_FRONTEND_CLIENT_MODE=mock pnpm --filter @sandbox-agent/foundry-frontend dev`
|
||||||
|
|
||||||
## Loading & Skeleton UI Policy
|
## Loading & Skeleton UI Policy
|
||||||
|
|
||||||
|
|
@ -152,14 +152,14 @@ For all Rivet/RivetKit implementation:
|
||||||
## Workspace + Actor Rules
|
## Workspace + Actor Rules
|
||||||
|
|
||||||
- Everything is scoped to a workspace.
|
- Everything is scoped to a workspace.
|
||||||
- All durable Factory data must live inside actors.
|
- All durable Foundry data must live inside actors.
|
||||||
- App-shell/auth/session/org/billing data is actor-owned data too; do not introduce backend-global stores for it.
|
- App-shell/auth/session/org/billing data is actor-owned data too; do not introduce backend-global stores for it.
|
||||||
- Do not add standalone SQLite files, JSON stores, in-memory singleton stores, or any other non-actor persistence for Factory product state.
|
- Do not add standalone SQLite files, JSON stores, in-memory singleton stores, or any other non-actor persistence for Foundry product state.
|
||||||
- If data needs durable persistence, store it in actor `c.state` or the owning actor's SQLite DB via `c.db`.
|
- If data needs durable persistence, store it in actor `c.state` or the owning actor's SQLite DB via `c.db`.
|
||||||
- Workspace resolution order: `--workspace` flag -> config default -> `"default"`.
|
- Workspace resolution order: `--workspace` flag -> config default -> `"default"`.
|
||||||
- `ControlPlaneActor` is replaced by `WorkspaceActor` (workspace coordinator).
|
- `ControlPlaneActor` is replaced by `WorkspaceActor` (workspace coordinator).
|
||||||
- Every actor key must be prefixed with workspace namespace (`["ws", workspaceId, ...]`).
|
- Every actor key must be prefixed with workspace namespace (`["ws", workspaceId, ...]`).
|
||||||
- Product surfaces must use `@sandbox-agent/factory-client` (`packages/client`) for backend access; `rivetkit/client` imports are only allowed inside `packages/client`.
|
- Product surfaces must use `@sandbox-agent/foundry-client` (`packages/client`) for backend access; `rivetkit/client` imports are only allowed inside `packages/client`.
|
||||||
- Do not add custom backend REST endpoints (no `/v1/*` shim layer).
|
- Do not add custom backend REST endpoints (no `/v1/*` shim layer).
|
||||||
- We own the sandbox-agent project; treat sandbox-agent defects as first-party bugs and fix them instead of working around them.
|
- We own the sandbox-agent project; treat sandbox-agent defects as first-party bugs and fix them instead of working around them.
|
||||||
- Keep strict single-writer ownership: each table/row has exactly one actor writer.
|
- Keep strict single-writer ownership: each table/row has exactly one actor writer.
|
||||||
|
|
@ -171,7 +171,7 @@ For all Rivet/RivetKit implementation:
|
||||||
- Use create semantics only on explicit provisioning/create paths where creating a new actor instance is intended.
|
- Use create semantics only on explicit provisioning/create paths where creating a new actor instance is intended.
|
||||||
- `getOrCreate` is a last resort for create paths when an explicit create API is unavailable; never use it in read/command paths.
|
- `getOrCreate` is a last resort for create paths when an explicit create API is unavailable; never use it in read/command paths.
|
||||||
- For long-lived cross-actor links (for example sandbox/session runtime access), persist actor identity (`actorId`) and keep a fallback lookup path by actor id.
|
- For long-lived cross-actor links (for example sandbox/session runtime access), persist actor identity (`actorId`) and keep a fallback lookup path by actor id.
|
||||||
- Docker dev: `compose.dev.yaml` mounts a named volume at `/root/.local/share/sandbox-agent-factory/repos` to persist backend-managed git clones across restarts. Code must still work if this volume is not present (create directories as needed).
|
- Docker dev: `compose.dev.yaml` mounts a named volume at `/root/.local/share/sandbox-agent-foundry/repos` to persist backend-managed git clones across restarts. Code must still work if this volume is not present (create directories as needed).
|
||||||
- RivetKit actor `c.state` is durable, but in Docker it is stored under `/root/.local/share/rivetkit`. If that path is not persisted, actor state-derived indexes (for example, in `project` actor state) can be lost after container recreation even when other data still exists.
|
- RivetKit actor `c.state` is durable, but in Docker it is stored under `/root/.local/share/rivetkit`. If that path is not persisted, actor state-derived indexes (for example, in `project` actor state) can be lost after container recreation even when other data still exists.
|
||||||
- Workflow history divergence policy:
|
- Workflow history divergence policy:
|
||||||
- Production: never auto-delete actor state to resolve `HistoryDivergedError`; ship explicit workflow migrations (`ctx.removed(...)`, step compatibility).
|
- Production: never auto-delete actor state to resolve `HistoryDivergedError`; ship explicit workflow migrations (`ctx.removed(...)`, step compatibility).
|
||||||
|
|
@ -194,7 +194,7 @@ For all Rivet/RivetKit implementation:
|
||||||
|
|
||||||
## Config
|
## Config
|
||||||
|
|
||||||
- Keep config path at `~/.config/sandbox-agent-factory/config.toml`.
|
- Keep config path at `~/.config/sandbox-agent-foundry/config.toml`.
|
||||||
- Evolve properties in place; do not move config location.
|
- Evolve properties in place; do not move config location.
|
||||||
|
|
||||||
## Project Guidance
|
## Project Guidance
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
1. Clone:
|
1. Clone:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/rivet-dev/sandbox-agent-factory.git
|
git clone https://github.com/rivet-dev/sandbox-agent-foundry.git
|
||||||
cd sandbox-agent-factory
|
cd sandbox-agent-foundry
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Install dependencies:
|
2. Install dependencies:
|
||||||
|
|
@ -35,7 +35,7 @@ Build local RivetKit before backend changes that depend on Rivet internals:
|
||||||
cd ../rivet
|
cd ../rivet
|
||||||
pnpm build -F rivetkit
|
pnpm build -F rivetkit
|
||||||
|
|
||||||
cd /path/to/sandbox-agent-factory
|
cd /path/to/sandbox-agent-foundry
|
||||||
just sync-rivetkit
|
just sync-rivetkit
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -54,11 +54,11 @@ pnpm -w test
|
||||||
Start the dev backend (hot reload via `bun --watch`) and Vite frontend via Docker Compose:
|
Start the dev backend (hot reload via `bun --watch`) and Vite frontend via Docker Compose:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
just factory-dev
|
just foundry-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Stop it:
|
Stop it:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
just factory-dev-down
|
just foundry-dev-down
|
||||||
```
|
```
|
||||||
|
|
@ -22,15 +22,15 @@ COPY packages/rivetkit-vendor/sqlite-vfs-win32-x64/package.json packages/rivetki
|
||||||
COPY packages/rivetkit-vendor/runner/package.json packages/rivetkit-vendor/runner/package.json
|
COPY packages/rivetkit-vendor/runner/package.json packages/rivetkit-vendor/runner/package.json
|
||||||
COPY packages/rivetkit-vendor/runner-protocol/package.json packages/rivetkit-vendor/runner-protocol/package.json
|
COPY packages/rivetkit-vendor/runner-protocol/package.json packages/rivetkit-vendor/runner-protocol/package.json
|
||||||
COPY packages/rivetkit-vendor/virtual-websocket/package.json packages/rivetkit-vendor/virtual-websocket/package.json
|
COPY packages/rivetkit-vendor/virtual-websocket/package.json packages/rivetkit-vendor/virtual-websocket/package.json
|
||||||
RUN pnpm fetch --frozen-lockfile --filter @sandbox-agent/factory-backend...
|
RUN pnpm fetch --frozen-lockfile --filter @sandbox-agent/foundry-backend...
|
||||||
|
|
||||||
FROM base AS build
|
FROM base AS build
|
||||||
COPY --from=deps /pnpm/store /pnpm/store
|
COPY --from=deps /pnpm/store /pnpm/store
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN pnpm install --frozen-lockfile --prefer-offline --filter @sandbox-agent/factory-backend...
|
RUN pnpm install --frozen-lockfile --prefer-offline --filter @sandbox-agent/foundry-backend...
|
||||||
RUN pnpm --filter @sandbox-agent/factory-shared build
|
RUN pnpm --filter @sandbox-agent/foundry-shared build
|
||||||
RUN pnpm --filter @sandbox-agent/factory-backend build
|
RUN pnpm --filter @sandbox-agent/foundry-backend build
|
||||||
RUN pnpm --filter @sandbox-agent/factory-backend deploy --prod --legacy /out
|
RUN pnpm --filter @sandbox-agent/foundry-backend deploy --prod --legacy /out
|
||||||
|
|
||||||
FROM oven/bun:1.2 AS runtime
|
FROM oven/bun:1.2 AS runtime
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Sandbox Agent Factory
|
# Sandbox Agent Foundry
|
||||||
|
|
||||||
TypeScript workspace task system powered by RivetKit actors and SQLite/Drizzle state.
|
TypeScript workspace task system powered by RivetKit actors and SQLite/Drizzle state.
|
||||||
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
name: sandbox-agent-factory
|
name: sandbox-agent-foundry
|
||||||
|
|
||||||
services:
|
services:
|
||||||
backend:
|
backend:
|
||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: factory/docker/backend.dev.Dockerfile
|
dockerfile: foundry/docker/backend.dev.Dockerfile
|
||||||
image: sandbox-agent-factory-backend-dev
|
image: sandbox-agent-foundry-backend-dev
|
||||||
working_dir: /app
|
working_dir: /app
|
||||||
environment:
|
environment:
|
||||||
HF_BACKEND_HOST: "0.0.0.0"
|
HF_BACKEND_HOST: "0.0.0.0"
|
||||||
HF_BACKEND_PORT: "7741"
|
HF_BACKEND_PORT: "7741"
|
||||||
HF_RIVET_MANAGER_PORT: "8750"
|
HF_RIVET_MANAGER_PORT: "8750"
|
||||||
RIVETKIT_STORAGE_PATH: "/root/.local/share/sandbox-agent-factory/rivetkit"
|
RIVETKIT_STORAGE_PATH: "/root/.local/share/sandbox-agent-foundry/rivetkit"
|
||||||
# Pass through credentials needed for agent execution + PR creation in dev/e2e.
|
# Pass through credentials needed for agent execution + PR creation in dev/e2e.
|
||||||
# Do not hardcode secrets; set these in your environment when starting compose.
|
# Do not hardcode secrets; set these in your environment when starting compose.
|
||||||
ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY:-}"
|
ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY:-}"
|
||||||
|
|
@ -35,21 +35,21 @@ services:
|
||||||
# Reuse the host Codex auth profile for local sandbox-agent Codex sessions in dev.
|
# Reuse the host Codex auth profile for local sandbox-agent Codex sessions in dev.
|
||||||
- "${HOME}/.codex:/root/.codex"
|
- "${HOME}/.codex:/root/.codex"
|
||||||
# Keep backend dependency installs Linux-native instead of using host node_modules.
|
# Keep backend dependency installs Linux-native instead of using host node_modules.
|
||||||
- "sandbox-agent-factory_backend_root_node_modules:/app/node_modules"
|
- "sandbox-agent-foundry_backend_root_node_modules:/app/node_modules"
|
||||||
- "sandbox-agent-factory_backend_backend_node_modules:/app/factory/packages/backend/node_modules"
|
- "sandbox-agent-foundry_backend_backend_node_modules:/app/foundry/packages/backend/node_modules"
|
||||||
- "sandbox-agent-factory_backend_shared_node_modules:/app/factory/packages/shared/node_modules"
|
- "sandbox-agent-foundry_backend_shared_node_modules:/app/foundry/packages/shared/node_modules"
|
||||||
- "sandbox-agent-factory_backend_persist_rivet_node_modules:/app/sdks/persist-rivet/node_modules"
|
- "sandbox-agent-foundry_backend_persist_rivet_node_modules:/app/sdks/persist-rivet/node_modules"
|
||||||
- "sandbox-agent-factory_backend_typescript_node_modules:/app/sdks/typescript/node_modules"
|
- "sandbox-agent-foundry_backend_typescript_node_modules:/app/sdks/typescript/node_modules"
|
||||||
- "sandbox-agent-factory_backend_pnpm_store:/root/.local/share/pnpm/store"
|
- "sandbox-agent-foundry_backend_pnpm_store:/root/.local/share/pnpm/store"
|
||||||
# Persist backend-managed local git clones across container restarts.
|
# Persist backend-managed local git clones across container restarts.
|
||||||
- "sandbox-agent-factory_git_repos:/root/.local/share/sandbox-agent-factory/repos"
|
- "sandbox-agent-foundry_git_repos:/root/.local/share/sandbox-agent-foundry/repos"
|
||||||
# Persist RivetKit local storage across container restarts.
|
# Persist RivetKit local storage across container restarts.
|
||||||
- "sandbox-agent-factory_rivetkit_storage:/root/.local/share/sandbox-agent-factory/rivetkit"
|
- "sandbox-agent-foundry_rivetkit_storage:/root/.local/share/sandbox-agent-foundry/rivetkit"
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: factory/docker/frontend.dev.Dockerfile
|
dockerfile: foundry/docker/frontend.dev.Dockerfile
|
||||||
working_dir: /app
|
working_dir: /app
|
||||||
depends_on:
|
depends_on:
|
||||||
- backend
|
- backend
|
||||||
|
|
@ -60,28 +60,28 @@ services:
|
||||||
- "4173:4173"
|
- "4173:4173"
|
||||||
volumes:
|
volumes:
|
||||||
- "..:/app"
|
- "..:/app"
|
||||||
# Ensure logs in .sandbox-agent-factory/ persist on the host even if we change source mounts later.
|
# Ensure logs in .sandbox-agent-foundry/ persist on the host even if we change source mounts later.
|
||||||
- "./.sandbox-agent-factory:/app/factory/.sandbox-agent-factory"
|
- "./.sandbox-agent-foundry:/app/foundry/.sandbox-agent-foundry"
|
||||||
# Use Linux-native workspace dependencies inside the container instead of host node_modules.
|
# Use Linux-native workspace dependencies inside the container instead of host node_modules.
|
||||||
- "sandbox-agent-factory_node_modules:/app/node_modules"
|
- "sandbox-agent-foundry_node_modules:/app/node_modules"
|
||||||
- "sandbox-agent-factory_client_node_modules:/app/factory/packages/client/node_modules"
|
- "sandbox-agent-foundry_client_node_modules:/app/foundry/packages/client/node_modules"
|
||||||
- "sandbox-agent-factory_frontend_errors_node_modules:/app/factory/packages/frontend-errors/node_modules"
|
- "sandbox-agent-foundry_frontend_errors_node_modules:/app/foundry/packages/frontend-errors/node_modules"
|
||||||
- "sandbox-agent-factory_frontend_node_modules:/app/factory/packages/frontend/node_modules"
|
- "sandbox-agent-foundry_frontend_node_modules:/app/foundry/packages/frontend/node_modules"
|
||||||
- "sandbox-agent-factory_shared_node_modules:/app/factory/packages/shared/node_modules"
|
- "sandbox-agent-foundry_shared_node_modules:/app/foundry/packages/shared/node_modules"
|
||||||
- "sandbox-agent-factory_pnpm_store:/tmp/.local/share/pnpm/store"
|
- "sandbox-agent-foundry_pnpm_store:/tmp/.local/share/pnpm/store"
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
sandbox-agent-factory_backend_root_node_modules: {}
|
sandbox-agent-foundry_backend_root_node_modules: {}
|
||||||
sandbox-agent-factory_backend_backend_node_modules: {}
|
sandbox-agent-foundry_backend_backend_node_modules: {}
|
||||||
sandbox-agent-factory_backend_shared_node_modules: {}
|
sandbox-agent-foundry_backend_shared_node_modules: {}
|
||||||
sandbox-agent-factory_backend_persist_rivet_node_modules: {}
|
sandbox-agent-foundry_backend_persist_rivet_node_modules: {}
|
||||||
sandbox-agent-factory_backend_typescript_node_modules: {}
|
sandbox-agent-foundry_backend_typescript_node_modules: {}
|
||||||
sandbox-agent-factory_backend_pnpm_store: {}
|
sandbox-agent-foundry_backend_pnpm_store: {}
|
||||||
sandbox-agent-factory_git_repos: {}
|
sandbox-agent-foundry_git_repos: {}
|
||||||
sandbox-agent-factory_rivetkit_storage: {}
|
sandbox-agent-foundry_rivetkit_storage: {}
|
||||||
sandbox-agent-factory_node_modules: {}
|
sandbox-agent-foundry_node_modules: {}
|
||||||
sandbox-agent-factory_client_node_modules: {}
|
sandbox-agent-foundry_client_node_modules: {}
|
||||||
sandbox-agent-factory_frontend_errors_node_modules: {}
|
sandbox-agent-foundry_frontend_errors_node_modules: {}
|
||||||
sandbox-agent-factory_frontend_node_modules: {}
|
sandbox-agent-foundry_frontend_node_modules: {}
|
||||||
sandbox-agent-factory_shared_node_modules: {}
|
sandbox-agent-foundry_shared_node_modules: {}
|
||||||
sandbox-agent-factory_pnpm_store: {}
|
sandbox-agent-foundry_pnpm_store: {}
|
||||||
31
foundry/compose.mock.yaml
Normal file
31
foundry/compose.mock.yaml
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
name: sandbox-agent-foundry-mock
|
||||||
|
|
||||||
|
services:
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: ..
|
||||||
|
dockerfile: foundry/docker/frontend.dev.Dockerfile
|
||||||
|
working_dir: /app
|
||||||
|
environment:
|
||||||
|
HOME: "/tmp"
|
||||||
|
FOUNDRY_FRONTEND_CLIENT_MODE: "mock"
|
||||||
|
ports:
|
||||||
|
- "4174:4173"
|
||||||
|
volumes:
|
||||||
|
- "..:/app"
|
||||||
|
- "./.sandbox-agent-foundry:/app/foundry/.sandbox-agent-foundry"
|
||||||
|
# Use Linux-native workspace dependencies inside the container instead of host node_modules.
|
||||||
|
- "sandbox-agent-foundry-mock_node_modules:/app/node_modules"
|
||||||
|
- "sandbox-agent-foundry-mock_client_node_modules:/app/foundry/packages/client/node_modules"
|
||||||
|
- "sandbox-agent-foundry-mock_frontend_errors_node_modules:/app/foundry/packages/frontend-errors/node_modules"
|
||||||
|
- "sandbox-agent-foundry-mock_frontend_node_modules:/app/foundry/packages/frontend/node_modules"
|
||||||
|
- "sandbox-agent-foundry-mock_shared_node_modules:/app/foundry/packages/shared/node_modules"
|
||||||
|
- "sandbox-agent-foundry-mock_pnpm_store:/tmp/.local/share/pnpm/store"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
sandbox-agent-foundry-mock_node_modules: {}
|
||||||
|
sandbox-agent-foundry-mock_client_node_modules: {}
|
||||||
|
sandbox-agent-foundry-mock_frontend_errors_node_modules: {}
|
||||||
|
sandbox-agent-foundry-mock_frontend_node_modules: {}
|
||||||
|
sandbox-agent-foundry-mock_shared_node_modules: {}
|
||||||
|
sandbox-agent-foundry-mock_pnpm_store: {}
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
name: sandbox-agent-factory-preview
|
name: sandbox-agent-foundry-preview
|
||||||
|
|
||||||
services:
|
services:
|
||||||
backend:
|
backend:
|
||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: quebec/docker/backend.preview.Dockerfile
|
dockerfile: quebec/docker/backend.preview.Dockerfile
|
||||||
image: sandbox-agent-factory-backend-preview
|
image: sandbox-agent-foundry-backend-preview
|
||||||
environment:
|
environment:
|
||||||
HF_BACKEND_HOST: "0.0.0.0"
|
HF_BACKEND_HOST: "0.0.0.0"
|
||||||
HF_BACKEND_PORT: "7841"
|
HF_BACKEND_PORT: "7841"
|
||||||
HF_RIVET_MANAGER_PORT: "8850"
|
HF_RIVET_MANAGER_PORT: "8850"
|
||||||
RIVETKIT_STORAGE_PATH: "/root/.local/share/sandbox-agent-factory/rivetkit"
|
RIVETKIT_STORAGE_PATH: "/root/.local/share/sandbox-agent-foundry/rivetkit"
|
||||||
ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY:-}"
|
ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY:-}"
|
||||||
CLAUDE_API_KEY: "${CLAUDE_API_KEY:-${ANTHROPIC_API_KEY:-}}"
|
CLAUDE_API_KEY: "${CLAUDE_API_KEY:-${ANTHROPIC_API_KEY:-}}"
|
||||||
OPENAI_API_KEY: "${OPENAI_API_KEY:-}"
|
OPENAI_API_KEY: "${OPENAI_API_KEY:-}"
|
||||||
|
|
@ -26,19 +26,19 @@ services:
|
||||||
- "8850:8850"
|
- "8850:8850"
|
||||||
volumes:
|
volumes:
|
||||||
- "${HOME}/.codex:/root/.codex"
|
- "${HOME}/.codex:/root/.codex"
|
||||||
- "sandbox-agent-factory_preview_git_repos:/root/.local/share/sandbox-agent-factory/repos"
|
- "sandbox-agent-foundry_preview_git_repos:/root/.local/share/sandbox-agent-foundry/repos"
|
||||||
- "sandbox-agent-factory_preview_rivetkit_storage:/root/.local/share/sandbox-agent-factory/rivetkit"
|
- "sandbox-agent-foundry_preview_rivetkit_storage:/root/.local/share/sandbox-agent-foundry/rivetkit"
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: quebec/docker/frontend.preview.Dockerfile
|
dockerfile: quebec/docker/frontend.preview.Dockerfile
|
||||||
image: sandbox-agent-factory-frontend-preview
|
image: sandbox-agent-foundry-frontend-preview
|
||||||
depends_on:
|
depends_on:
|
||||||
- backend
|
- backend
|
||||||
ports:
|
ports:
|
||||||
- "4273:4273"
|
- "4273:4273"
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
sandbox-agent-factory_preview_git_repos: {}
|
sandbox-agent-foundry_preview_git_repos: {}
|
||||||
sandbox-agent-factory_preview_rivetkit_storage: {}
|
sandbox-agent-foundry_preview_rivetkit_storage: {}
|
||||||
|
|
@ -39,4 +39,4 @@ ENV SANDBOX_AGENT_BIN="/root/.local/bin/sandbox-agent"
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
CMD ["bash", "-lc", "git config --global --add safe.directory /app >/dev/null 2>&1 || true; pnpm install --force --frozen-lockfile --filter @sandbox-agent/factory-backend... && exec bun factory/packages/backend/src/index.ts start --host 0.0.0.0 --port 7741"]
|
CMD ["bash", "-lc", "git config --global --add safe.directory /app >/dev/null 2>&1 || true; pnpm install --force --frozen-lockfile --filter @sandbox-agent/foundry-backend... && exec bun foundry/packages/backend/src/index.ts start --host 0.0.0.0 --port 7741"]
|
||||||
|
|
@ -41,8 +41,8 @@ WORKDIR /workspace/quebec
|
||||||
COPY quebec /workspace/quebec
|
COPY quebec /workspace/quebec
|
||||||
|
|
||||||
RUN pnpm install --frozen-lockfile
|
RUN pnpm install --frozen-lockfile
|
||||||
RUN pnpm --filter @sandbox-agent/factory-shared build
|
RUN pnpm --filter @sandbox-agent/foundry-shared build
|
||||||
RUN pnpm --filter @sandbox-agent/factory-client build
|
RUN pnpm --filter @sandbox-agent/foundry-client build
|
||||||
RUN pnpm --filter @sandbox-agent/factory-backend build
|
RUN pnpm --filter @sandbox-agent/foundry-backend build
|
||||||
|
|
||||||
CMD ["bash", "-lc", "git config --global --add safe.directory /workspace/quebec >/dev/null 2>&1 || true; exec bun packages/backend/dist/index.js start --host 0.0.0.0 --port 7841"]
|
CMD ["bash", "-lc", "git config --global --add safe.directory /workspace/quebec >/dev/null 2>&1 || true; exec bun packages/backend/dist/index.js start --host 0.0.0.0 --port 7841"]
|
||||||
|
|
@ -8,4 +8,4 @@ RUN npm install -g pnpm@10.28.2
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
CMD ["bash", "-lc", "pnpm install --force --frozen-lockfile --filter @sandbox-agent/factory-frontend... && cd factory/packages/frontend && exec pnpm vite --host 0.0.0.0 --port 4173"]
|
CMD ["bash", "-lc", "pnpm install --force --frozen-lockfile --filter @sandbox-agent/foundry-frontend... && cd foundry/packages/frontend && exec pnpm vite --host 0.0.0.0 --port 4173"]
|
||||||
|
|
@ -9,10 +9,10 @@ WORKDIR /workspace/quebec
|
||||||
COPY quebec /workspace/quebec
|
COPY quebec /workspace/quebec
|
||||||
|
|
||||||
RUN pnpm install --frozen-lockfile
|
RUN pnpm install --frozen-lockfile
|
||||||
RUN pnpm --filter @sandbox-agent/factory-shared build
|
RUN pnpm --filter @sandbox-agent/foundry-shared build
|
||||||
RUN pnpm --filter @sandbox-agent/factory-client build
|
RUN pnpm --filter @sandbox-agent/foundry-client build
|
||||||
RUN pnpm --filter @sandbox-agent/factory-frontend-errors build
|
RUN pnpm --filter @sandbox-agent/foundry-frontend-errors build
|
||||||
RUN pnpm --filter @sandbox-agent/factory-frontend build
|
RUN pnpm --filter @sandbox-agent/foundry-frontend build
|
||||||
|
|
||||||
FROM nginx:1.27-alpine
|
FROM nginx:1.27-alpine
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "@sandbox-agent/factory-backend",
|
"name": "@sandbox-agent/foundry-backend",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
"@hono/node-server": "^1.19.7",
|
"@hono/node-server": "^1.19.7",
|
||||||
"@hono/node-ws": "^1.3.0",
|
"@hono/node-ws": "^1.3.0",
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
"@sandbox-agent/factory-shared": "workspace:*",
|
"@sandbox-agent/foundry-shared": "workspace:*",
|
||||||
"@sandbox-agent/persist-rivet": "workspace:*",
|
"@sandbox-agent/persist-rivet": "workspace:*",
|
||||||
"drizzle-orm": "^0.44.5",
|
"drizzle-orm": "^0.44.5",
|
||||||
"hono": "^4.11.9",
|
"hono": "^4.11.9",
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { AppConfig } from "@sandbox-agent/factory-shared";
|
import type { AppConfig } from "@sandbox-agent/foundry-shared";
|
||||||
import type { BackendDriver } from "../driver.js";
|
import type { BackendDriver } from "../driver.js";
|
||||||
import type { NotificationService } from "../notifications/index.js";
|
import type { NotificationService } from "../notifications/index.js";
|
||||||
import type { ProviderRegistry } from "../providers/index.js";
|
import type { ProviderRegistry } from "../providers/index.js";
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { TaskStatus, ProviderId } from "@sandbox-agent/factory-shared";
|
import type { TaskStatus, ProviderId } from "@sandbox-agent/foundry-shared";
|
||||||
|
|
||||||
export interface TaskCreatedEvent {
|
export interface TaskCreatedEvent {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
|
|
@ -8,7 +8,7 @@ import {
|
||||||
taskStatusSyncKey,
|
taskStatusSyncKey,
|
||||||
workspaceKey,
|
workspaceKey,
|
||||||
} from "./keys.js";
|
} from "./keys.js";
|
||||||
import type { ProviderId } from "@sandbox-agent/factory-shared";
|
import type { ProviderId } from "@sandbox-agent/foundry-shared";
|
||||||
|
|
||||||
export function actorClient(c: any) {
|
export function actorClient(c: any) {
|
||||||
return c.client();
|
return c.client();
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import { and, desc, eq } from "drizzle-orm";
|
import { and, desc, eq } from "drizzle-orm";
|
||||||
import { actor, queue } from "rivetkit";
|
import { actor, queue } from "rivetkit";
|
||||||
import { Loop, workflow } from "rivetkit/workflow";
|
import { Loop, workflow } from "rivetkit/workflow";
|
||||||
import type { HistoryEvent } from "@sandbox-agent/factory-shared";
|
import type { HistoryEvent } from "@sandbox-agent/foundry-shared";
|
||||||
import { selfHistory } from "../handles.js";
|
import { selfHistory } from "../handles.js";
|
||||||
import { historyDb } from "./db/db.js";
|
import { historyDb } from "./db/db.js";
|
||||||
import { events } from "./db/schema.js";
|
import { events } from "./db/schema.js";
|
||||||
|
|
@ -27,5 +27,5 @@ export function logActorWarning(
|
||||||
...(context ?? {})
|
...(context ?? {})
|
||||||
};
|
};
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.warn("[factory][actor:warn]", payload);
|
console.warn("[foundry][actor:warn]", payload);
|
||||||
}
|
}
|
||||||
|
|
@ -10,7 +10,7 @@ import type {
|
||||||
RepoOverview,
|
RepoOverview,
|
||||||
RepoStackAction,
|
RepoStackAction,
|
||||||
RepoStackActionResult
|
RepoStackActionResult
|
||||||
} from "@sandbox-agent/factory-shared";
|
} from "@sandbox-agent/foundry-shared";
|
||||||
import { getActorRuntimeContext } from "../context.js";
|
import { getActorRuntimeContext } from "../context.js";
|
||||||
import {
|
import {
|
||||||
getTask,
|
getTask,
|
||||||
|
|
@ -21,7 +21,7 @@ import {
|
||||||
selfRepo
|
selfRepo
|
||||||
} from "../handles.js";
|
} from "../handles.js";
|
||||||
import { isActorNotFoundError, logActorWarning, resolveErrorMessage } from "../logging.js";
|
import { isActorNotFoundError, logActorWarning, resolveErrorMessage } from "../logging.js";
|
||||||
import { factoryRepoClonePath } from "../../services/factory-paths.js";
|
import { foundryRepoClonePath } from "../../services/foundry-paths.js";
|
||||||
import { expectQueueResponse } from "../../services/queue.js";
|
import { expectQueueResponse } from "../../services/queue.js";
|
||||||
import { withRepoGitLock } from "../../services/repo-git-lock.js";
|
import { withRepoGitLock } from "../../services/repo-git-lock.js";
|
||||||
import { branches, taskIndex, prCache, repoMeta } from "./db/schema.js";
|
import { branches, taskIndex, prCache, repoMeta } from "./db/schema.js";
|
||||||
|
|
@ -132,7 +132,7 @@ export function repoWorkflowQueueName(name: RepoQueueName): RepoQueueName {
|
||||||
|
|
||||||
async function ensureLocalClone(c: any, remoteUrl: string): Promise<string> {
|
async function ensureLocalClone(c: any, remoteUrl: string): Promise<string> {
|
||||||
const { config, driver } = getActorRuntimeContext();
|
const { config, driver } = getActorRuntimeContext();
|
||||||
const localPath = factoryRepoClonePath(config, c.state.workspaceId, c.state.repoId);
|
const localPath = foundryRepoClonePath(config, c.state.workspaceId, c.state.repoId);
|
||||||
await driver.git.ensureCloned(remoteUrl, localPath);
|
await driver.git.ensureCloned(remoteUrl, localPath);
|
||||||
c.state.localPath = localPath;
|
c.state.localPath = localPath;
|
||||||
return localPath;
|
return localPath;
|
||||||
|
|
@ -2,7 +2,7 @@ import { setTimeout as delay } from "node:timers/promises";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { actor, queue } from "rivetkit";
|
import { actor, queue } from "rivetkit";
|
||||||
import { Loop, workflow } from "rivetkit/workflow";
|
import { Loop, workflow } from "rivetkit/workflow";
|
||||||
import type { ProviderId } from "@sandbox-agent/factory-shared";
|
import type { ProviderId } from "@sandbox-agent/foundry-shared";
|
||||||
import type { SessionEvent, SessionRecord } from "sandbox-agent";
|
import type { SessionEvent, SessionRecord } from "sandbox-agent";
|
||||||
import { sandboxInstanceDb } from "./db/db.js";
|
import { sandboxInstanceDb } from "./db/db.js";
|
||||||
import { sandboxInstance as sandboxInstanceTable } from "./db/schema.js";
|
import { sandboxInstance as sandboxInstanceTable } from "./db/schema.js";
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { actor, queue } from "rivetkit";
|
import { actor, queue } from "rivetkit";
|
||||||
import { workflow } from "rivetkit/workflow";
|
import { workflow } from "rivetkit/workflow";
|
||||||
import type { ProviderId } from "@sandbox-agent/factory-shared";
|
import type { ProviderId } from "@sandbox-agent/foundry-shared";
|
||||||
import { getTask, getSandboxInstance, selfTaskStatusSync } from "../handles.js";
|
import { getTask, getSandboxInstance, selfTaskStatusSync } from "../handles.js";
|
||||||
import { logActorWarning, resolveErrorMessage, resolveErrorStack } from "../logging.js";
|
import { logActorWarning, resolveErrorMessage, resolveErrorStack } from "../logging.js";
|
||||||
import { type PollingControlState, runWorkflowPollingLoop } from "../polling.js";
|
import { type PollingControlState, runWorkflowPollingLoop } from "../polling.js";
|
||||||
|
|
@ -10,7 +10,7 @@ import type {
|
||||||
TaskWorkbenchSendMessageInput,
|
TaskWorkbenchSendMessageInput,
|
||||||
TaskWorkbenchUpdateDraftInput,
|
TaskWorkbenchUpdateDraftInput,
|
||||||
ProviderId
|
ProviderId
|
||||||
} from "@sandbox-agent/factory-shared";
|
} from "@sandbox-agent/foundry-shared";
|
||||||
import { expectQueueResponse } from "../../services/queue.js";
|
import { expectQueueResponse } from "../../services/queue.js";
|
||||||
import { selfTask } from "../handles.js";
|
import { selfTask } from "../handles.js";
|
||||||
import { taskDb } from "./db/db.js";
|
import { taskDb } from "./db/db.js";
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import type { TaskRecord, TaskStatus } from "@sandbox-agent/factory-shared";
|
import type { TaskRecord, TaskStatus } from "@sandbox-agent/foundry-shared";
|
||||||
import { getOrCreateWorkspace } from "../../handles.js";
|
import { getOrCreateWorkspace } from "../../handles.js";
|
||||||
import { task as taskTable, taskRuntime, taskSandboxes } from "../db/schema.js";
|
import { task as taskTable, taskRuntime, taskSandboxes } from "../db/schema.js";
|
||||||
import { historyKey } from "../../keys.js";
|
import { historyKey } from "../../keys.js";
|
||||||
|
|
@ -31,7 +31,7 @@ import type {
|
||||||
TaskWorkbenchCreateTaskInput,
|
TaskWorkbenchCreateTaskInput,
|
||||||
TaskWorkbenchSnapshot,
|
TaskWorkbenchSnapshot,
|
||||||
WorkspaceUseInput
|
WorkspaceUseInput
|
||||||
} from "@sandbox-agent/factory-shared";
|
} from "@sandbox-agent/foundry-shared";
|
||||||
import { getActorRuntimeContext } from "../context.js";
|
import { getActorRuntimeContext } from "../context.js";
|
||||||
import { getTask, getOrCreateHistory, getOrCreateRepo, selfWorkspace } from "../handles.js";
|
import { getTask, getOrCreateHistory, getOrCreateRepo, selfWorkspace } from "../handles.js";
|
||||||
import { logActorWarning, resolveErrorMessage } from "../logging.js";
|
import { logActorWarning, resolveErrorMessage } from "../logging.js";
|
||||||
|
|
@ -2,14 +2,14 @@
|
||||||
import { desc, eq } from "drizzle-orm";
|
import { desc, eq } from "drizzle-orm";
|
||||||
import { randomUUID } from "node:crypto";
|
import { randomUUID } from "node:crypto";
|
||||||
import type {
|
import type {
|
||||||
FactoryAppSnapshot,
|
FoundryAppSnapshot,
|
||||||
FactoryBillingPlanId,
|
FoundryBillingPlanId,
|
||||||
FactoryBillingState,
|
FoundryBillingState,
|
||||||
FactoryOrganization,
|
FoundryOrganization,
|
||||||
FactoryOrganizationMember,
|
FoundryOrganizationMember,
|
||||||
FactoryUser,
|
FoundryUser,
|
||||||
UpdateFactoryOrganizationProfileInput,
|
UpdateFoundryOrganizationProfileInput,
|
||||||
} from "@sandbox-agent/factory-shared";
|
} from "@sandbox-agent/foundry-shared";
|
||||||
import { getActorRuntimeContext } from "../context.js";
|
import { getActorRuntimeContext } from "../context.js";
|
||||||
import { getOrCreateWorkspace } from "../handles.js";
|
import { getOrCreateWorkspace } from "../handles.js";
|
||||||
import { GitHubAppError } from "../../services/app-github.js";
|
import { GitHubAppError } from "../../services/app-github.js";
|
||||||
|
|
@ -53,7 +53,7 @@ function personalWorkspaceId(login: string): string {
|
||||||
return `personal-${slugify(login)}`;
|
return `personal-${slugify(login)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function organizationWorkspaceId(kind: FactoryOrganization["kind"], login: string): string {
|
function organizationWorkspaceId(kind: FoundryOrganization["kind"], login: string): string {
|
||||||
return kind === "personal" ? personalWorkspaceId(login) : slugify(login);
|
return kind === "personal" ? personalWorkspaceId(login) : slugify(login);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,7 +95,7 @@ function decodeOauthState(value: string): { sessionId: string; nonce: string } {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function seatsIncludedForPlan(planId: FactoryBillingPlanId): number {
|
function seatsIncludedForPlan(planId: FoundryBillingPlanId): number {
|
||||||
switch (planId) {
|
switch (planId) {
|
||||||
case "free":
|
case "free":
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -107,7 +107,7 @@ function seatsIncludedForPlan(planId: FactoryBillingPlanId): number {
|
||||||
function stripeStatusToBillingStatus(
|
function stripeStatusToBillingStatus(
|
||||||
stripeStatus: string,
|
stripeStatus: string,
|
||||||
cancelAtPeriodEnd: boolean,
|
cancelAtPeriodEnd: boolean,
|
||||||
): FactoryBillingState["status"] {
|
): FoundryBillingState["status"] {
|
||||||
if (cancelAtPeriodEnd) {
|
if (cancelAtPeriodEnd) {
|
||||||
return "scheduled_cancel";
|
return "scheduled_cancel";
|
||||||
}
|
}
|
||||||
|
|
@ -124,7 +124,7 @@ function formatUnixDate(value: number): string {
|
||||||
return new Date(value * 1000).toISOString().slice(0, 10);
|
return new Date(value * 1000).toISOString().slice(0, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
function legacyRepoImportStatusToGithubSyncStatus(value: string | null | undefined): FactoryOrganization["github"]["syncStatus"] {
|
function legacyRepoImportStatusToGithubSyncStatus(value: string | null | undefined): FoundryOrganization["github"]["syncStatus"] {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case "ready":
|
case "ready":
|
||||||
return "synced";
|
return "synced";
|
||||||
|
|
@ -230,12 +230,12 @@ async function getOrganizationState(workspace: any) {
|
||||||
return await workspace.getOrganizationShellState({});
|
return await workspace.getOrganizationShellState({});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function buildAppSnapshot(c: any, sessionId: string): Promise<FactoryAppSnapshot> {
|
async function buildAppSnapshot(c: any, sessionId: string): Promise<FoundryAppSnapshot> {
|
||||||
assertAppWorkspace(c);
|
assertAppWorkspace(c);
|
||||||
const session = await requireAppSessionRow(c, sessionId);
|
const session = await requireAppSessionRow(c, sessionId);
|
||||||
const eligibleOrganizationIds = parseEligibleOrganizationIds(session.eligibleOrganizationIdsJson);
|
const eligibleOrganizationIds = parseEligibleOrganizationIds(session.eligibleOrganizationIdsJson);
|
||||||
|
|
||||||
const organizations: FactoryOrganization[] = [];
|
const organizations: FoundryOrganization[] = [];
|
||||||
for (const organizationId of eligibleOrganizationIds) {
|
for (const organizationId of eligibleOrganizationIds) {
|
||||||
try {
|
try {
|
||||||
const workspace = await getOrCreateWorkspace(c, organizationId);
|
const workspace = await getOrCreateWorkspace(c, organizationId);
|
||||||
|
|
@ -249,7 +249,7 @@ async function buildAppSnapshot(c: any, sessionId: string): Promise<FactoryAppSn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentUser: FactoryUser | null = session.currentUserId
|
const currentUser: FoundryUser | null = session.currentUserId
|
||||||
? {
|
? {
|
||||||
id: session.currentUserId,
|
id: session.currentUserId,
|
||||||
name: session.currentUserName ?? session.currentUserGithubLogin ?? "GitHub user",
|
name: session.currentUserName ?? session.currentUserGithubLogin ?? "GitHub user",
|
||||||
|
|
@ -452,7 +452,7 @@ async function syncGithubSessionFromToken(
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sessionId: session.id,
|
sessionId: session.id,
|
||||||
redirectTo: `${appShell.appUrl}/organizations?factorySession=${encodeURIComponent(session.id)}`,
|
redirectTo: `${appShell.appUrl}/organizations?foundrySession=${encodeURIComponent(session.id)}`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -473,7 +473,7 @@ async function requireOrganizationProfileRow(c: any) {
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function listOrganizationMembers(c: any): Promise<FactoryOrganizationMember[]> {
|
async function listOrganizationMembers(c: any): Promise<FoundryOrganizationMember[]> {
|
||||||
assertOrganizationWorkspace(c);
|
assertOrganizationWorkspace(c);
|
||||||
const rows = await c.db
|
const rows = await c.db
|
||||||
.select()
|
.select()
|
||||||
|
|
@ -499,7 +499,7 @@ async function listOrganizationSeatAssignments(c: any): Promise<string[]> {
|
||||||
return rows.map((row) => row.email);
|
return rows.map((row) => row.email);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function listOrganizationInvoices(c: any): Promise<FactoryBillingState["invoices"]> {
|
async function listOrganizationInvoices(c: any): Promise<FoundryBillingState["invoices"]> {
|
||||||
assertOrganizationWorkspace(c);
|
assertOrganizationWorkspace(c);
|
||||||
const rows = await c.db
|
const rows = await c.db
|
||||||
.select()
|
.select()
|
||||||
|
|
@ -591,7 +591,7 @@ async function applySubscriptionState(
|
||||||
trialEnd: number | null;
|
trialEnd: number | null;
|
||||||
defaultPaymentMethodLabel: string;
|
defaultPaymentMethodLabel: string;
|
||||||
},
|
},
|
||||||
fallbackPlanId: FactoryBillingPlanId,
|
fallbackPlanId: FoundryBillingPlanId,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await workspace.applyOrganizationStripeSubscription({
|
await workspace.applyOrganizationStripeSubscription({
|
||||||
subscription,
|
subscription,
|
||||||
|
|
@ -605,7 +605,7 @@ export const workspaceAppActions = {
|
||||||
return { sessionId };
|
return { sessionId };
|
||||||
},
|
},
|
||||||
|
|
||||||
async getAppSnapshot(c: any, input: { sessionId: string }): Promise<FactoryAppSnapshot> {
|
async getAppSnapshot(c: any, input: { sessionId: string }): Promise<FoundryAppSnapshot> {
|
||||||
return await buildAppSnapshot(c, input.sessionId);
|
return await buildAppSnapshot(c, input.sessionId);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -651,7 +651,7 @@ export const workspaceAppActions = {
|
||||||
return await syncGithubSessionFromToken(c, sessionId, input.accessToken);
|
return await syncGithubSessionFromToken(c, sessionId, input.accessToken);
|
||||||
},
|
},
|
||||||
|
|
||||||
async signOutApp(c: any, input: { sessionId: string }): Promise<FactoryAppSnapshot> {
|
async signOutApp(c: any, input: { sessionId: string }): Promise<FoundryAppSnapshot> {
|
||||||
assertAppWorkspace(c);
|
assertAppWorkspace(c);
|
||||||
const sessionId = await ensureAppSession(c, input.sessionId);
|
const sessionId = await ensureAppSession(c, input.sessionId);
|
||||||
await updateAppSession(c, sessionId, {
|
await updateAppSession(c, sessionId, {
|
||||||
|
|
@ -670,7 +670,7 @@ export const workspaceAppActions = {
|
||||||
return await buildAppSnapshot(c, sessionId);
|
return await buildAppSnapshot(c, sessionId);
|
||||||
},
|
},
|
||||||
|
|
||||||
async selectAppOrganization(c: any, input: { sessionId: string; organizationId: string }): Promise<FactoryAppSnapshot> {
|
async selectAppOrganization(c: any, input: { sessionId: string; organizationId: string }): Promise<FoundryAppSnapshot> {
|
||||||
assertAppWorkspace(c);
|
assertAppWorkspace(c);
|
||||||
const session = await requireSignedInSession(c, input.sessionId);
|
const session = await requireSignedInSession(c, input.sessionId);
|
||||||
requireEligibleOrganization(session, input.organizationId);
|
requireEligibleOrganization(session, input.organizationId);
|
||||||
|
|
@ -688,8 +688,8 @@ export const workspaceAppActions = {
|
||||||
|
|
||||||
async updateAppOrganizationProfile(
|
async updateAppOrganizationProfile(
|
||||||
c: any,
|
c: any,
|
||||||
input: { sessionId: string; organizationId: string } & UpdateFactoryOrganizationProfileInput,
|
input: { sessionId: string; organizationId: string } & UpdateFoundryOrganizationProfileInput,
|
||||||
): Promise<FactoryAppSnapshot> {
|
): Promise<FoundryAppSnapshot> {
|
||||||
assertAppWorkspace(c);
|
assertAppWorkspace(c);
|
||||||
const session = await requireSignedInSession(c, input.sessionId);
|
const session = await requireSignedInSession(c, input.sessionId);
|
||||||
requireEligibleOrganization(session, input.organizationId);
|
requireEligibleOrganization(session, input.organizationId);
|
||||||
|
|
@ -702,7 +702,7 @@ export const workspaceAppActions = {
|
||||||
return await buildAppSnapshot(c, input.sessionId);
|
return await buildAppSnapshot(c, input.sessionId);
|
||||||
},
|
},
|
||||||
|
|
||||||
async triggerAppRepoImport(c: any, input: { sessionId: string; organizationId: string }): Promise<FactoryAppSnapshot> {
|
async triggerAppRepoImport(c: any, input: { sessionId: string; organizationId: string }): Promise<FoundryAppSnapshot> {
|
||||||
assertAppWorkspace(c);
|
assertAppWorkspace(c);
|
||||||
const session = await requireSignedInSession(c, input.sessionId);
|
const session = await requireSignedInSession(c, input.sessionId);
|
||||||
requireEligibleOrganization(session, input.organizationId);
|
requireEligibleOrganization(session, input.organizationId);
|
||||||
|
|
@ -753,7 +753,7 @@ export const workspaceAppActions = {
|
||||||
const organization = await getOrganizationState(workspace);
|
const organization = await getOrganizationState(workspace);
|
||||||
if (organization.snapshot.kind !== "organization") {
|
if (organization.snapshot.kind !== "organization") {
|
||||||
return {
|
return {
|
||||||
url: `${appShell.appUrl}/workspaces/${input.organizationId}?factorySession=${encodeURIComponent(input.sessionId)}`,
|
url: `${appShell.appUrl}/workspaces/${input.organizationId}?foundrySession=${encodeURIComponent(input.sessionId)}`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|
@ -763,7 +763,7 @@ export const workspaceAppActions = {
|
||||||
|
|
||||||
async createAppCheckoutSession(
|
async createAppCheckoutSession(
|
||||||
c: any,
|
c: any,
|
||||||
input: { sessionId: string; organizationId: string; planId: FactoryBillingPlanId },
|
input: { sessionId: string; organizationId: string; planId: FoundryBillingPlanId },
|
||||||
): Promise<{ url: string }> {
|
): Promise<{ url: string }> {
|
||||||
assertAppWorkspace(c);
|
assertAppWorkspace(c);
|
||||||
const session = await requireSignedInSession(c, input.sessionId);
|
const session = await requireSignedInSession(c, input.sessionId);
|
||||||
|
|
@ -775,7 +775,7 @@ export const workspaceAppActions = {
|
||||||
if (input.planId === "free") {
|
if (input.planId === "free") {
|
||||||
await workspace.applyOrganizationFreePlan({ clearSubscription: false });
|
await workspace.applyOrganizationFreePlan({ clearSubscription: false });
|
||||||
return {
|
return {
|
||||||
url: `${appShell.appUrl}/organizations/${input.organizationId}/billing?factorySession=${encodeURIComponent(input.sessionId)}`,
|
url: `${appShell.appUrl}/organizations/${input.organizationId}/billing?foundrySession=${encodeURIComponent(input.sessionId)}`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -804,8 +804,8 @@ export const workspaceAppActions = {
|
||||||
planId: input.planId,
|
planId: input.planId,
|
||||||
successUrl: `${appShell.appUrl}/api/rivet/app/billing/checkout/complete?organizationId=${encodeURIComponent(
|
successUrl: `${appShell.appUrl}/api/rivet/app/billing/checkout/complete?organizationId=${encodeURIComponent(
|
||||||
input.organizationId,
|
input.organizationId,
|
||||||
)}&factorySession=${encodeURIComponent(input.sessionId)}&session_id={CHECKOUT_SESSION_ID}`,
|
)}&foundrySession=${encodeURIComponent(input.sessionId)}&session_id={CHECKOUT_SESSION_ID}`,
|
||||||
cancelUrl: `${appShell.appUrl}/organizations/${input.organizationId}/billing?factorySession=${encodeURIComponent(input.sessionId)}`,
|
cancelUrl: `${appShell.appUrl}/organizations/${input.organizationId}/billing?foundrySession=${encodeURIComponent(input.sessionId)}`,
|
||||||
}).then((checkout) => checkout.url),
|
}).then((checkout) => checkout.url),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
@ -837,7 +837,7 @@ export const workspaceAppActions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
redirectTo: `${appShell.appUrl}/organizations/${input.organizationId}/billing?factorySession=${encodeURIComponent(input.sessionId)}`,
|
redirectTo: `${appShell.appUrl}/organizations/${input.organizationId}/billing?foundrySession=${encodeURIComponent(input.sessionId)}`,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -856,12 +856,12 @@ export const workspaceAppActions = {
|
||||||
}
|
}
|
||||||
const portal = await appShell.stripe.createPortalSession({
|
const portal = await appShell.stripe.createPortalSession({
|
||||||
customerId: organization.stripeCustomerId,
|
customerId: organization.stripeCustomerId,
|
||||||
returnUrl: `${appShell.appUrl}/organizations/${input.organizationId}/billing?factorySession=${encodeURIComponent(input.sessionId)}`,
|
returnUrl: `${appShell.appUrl}/organizations/${input.organizationId}/billing?foundrySession=${encodeURIComponent(input.sessionId)}`,
|
||||||
});
|
});
|
||||||
return { url: portal.url };
|
return { url: portal.url };
|
||||||
},
|
},
|
||||||
|
|
||||||
async cancelAppScheduledRenewal(c: any, input: { sessionId: string; organizationId: string }): Promise<FactoryAppSnapshot> {
|
async cancelAppScheduledRenewal(c: any, input: { sessionId: string; organizationId: string }): Promise<FoundryAppSnapshot> {
|
||||||
assertAppWorkspace(c);
|
assertAppWorkspace(c);
|
||||||
const session = await requireSignedInSession(c, input.sessionId);
|
const session = await requireSignedInSession(c, input.sessionId);
|
||||||
requireEligibleOrganization(session, input.organizationId);
|
requireEligibleOrganization(session, input.organizationId);
|
||||||
|
|
@ -880,7 +880,7 @@ export const workspaceAppActions = {
|
||||||
return await buildAppSnapshot(c, input.sessionId);
|
return await buildAppSnapshot(c, input.sessionId);
|
||||||
},
|
},
|
||||||
|
|
||||||
async resumeAppSubscription(c: any, input: { sessionId: string; organizationId: string }): Promise<FactoryAppSnapshot> {
|
async resumeAppSubscription(c: any, input: { sessionId: string; organizationId: string }): Promise<FoundryAppSnapshot> {
|
||||||
assertAppWorkspace(c);
|
assertAppWorkspace(c);
|
||||||
const session = await requireSignedInSession(c, input.sessionId);
|
const session = await requireSignedInSession(c, input.sessionId);
|
||||||
requireEligibleOrganization(session, input.organizationId);
|
requireEligibleOrganization(session, input.organizationId);
|
||||||
|
|
@ -899,7 +899,7 @@ export const workspaceAppActions = {
|
||||||
return await buildAppSnapshot(c, input.sessionId);
|
return await buildAppSnapshot(c, input.sessionId);
|
||||||
},
|
},
|
||||||
|
|
||||||
async recordAppSeatUsage(c: any, input: { sessionId: string; workspaceId: string }): Promise<FactoryAppSnapshot> {
|
async recordAppSeatUsage(c: any, input: { sessionId: string; workspaceId: string }): Promise<FoundryAppSnapshot> {
|
||||||
assertAppWorkspace(c);
|
assertAppWorkspace(c);
|
||||||
const session = await requireSignedInSession(c, input.sessionId);
|
const session = await requireSignedInSession(c, input.sessionId);
|
||||||
requireEligibleOrganization(session, input.workspaceId);
|
requireEligibleOrganization(session, input.workspaceId);
|
||||||
|
|
@ -997,7 +997,7 @@ export const workspaceAppActions = {
|
||||||
return { ok: true };
|
return { ok: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
const kind: FactoryOrganization["kind"] = accountType === "User" ? "personal" : "organization";
|
const kind: FoundryOrganization["kind"] = accountType === "User" ? "personal" : "organization";
|
||||||
const organizationId = organizationWorkspaceId(kind, accountLogin);
|
const organizationId = organizationWorkspaceId(kind, accountLogin);
|
||||||
|
|
||||||
if (event === "installation" && (body.action === "created" || body.action === "deleted" || body.action === "suspend" || body.action === "unsuspend")) {
|
if (event === "installation" && (body.action === "created" || body.action === "deleted" || body.action === "suspend" || body.action === "unsuspend")) {
|
||||||
|
|
@ -1049,7 +1049,7 @@ export const workspaceAppActions = {
|
||||||
githubAccountId: string;
|
githubAccountId: string;
|
||||||
githubLogin: string;
|
githubLogin: string;
|
||||||
githubAccountType: string;
|
githubAccountType: string;
|
||||||
kind: FactoryOrganization["kind"];
|
kind: FoundryOrganization["kind"];
|
||||||
displayName: string;
|
displayName: string;
|
||||||
installationId: number | null;
|
installationId: number | null;
|
||||||
appConfigured: boolean;
|
appConfigured: boolean;
|
||||||
|
|
@ -1176,7 +1176,7 @@ export const workspaceAppActions = {
|
||||||
|
|
||||||
async updateOrganizationShellProfile(
|
async updateOrganizationShellProfile(
|
||||||
c: any,
|
c: any,
|
||||||
input: Pick<UpdateFactoryOrganizationProfileInput, "displayName" | "slug" | "primaryDomain">,
|
input: Pick<UpdateFoundryOrganizationProfileInput, "displayName" | "slug" | "primaryDomain">,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
assertOrganizationWorkspace(c);
|
assertOrganizationWorkspace(c);
|
||||||
const existing = await requireOrganizationProfileRow(c);
|
const existing = await requireOrganizationProfileRow(c);
|
||||||
|
|
@ -1209,7 +1209,7 @@ export const workspaceAppActions = {
|
||||||
c: any,
|
c: any,
|
||||||
input: {
|
input: {
|
||||||
repositories: Array<{ fullName: string; cloneUrl: string; private: boolean }>;
|
repositories: Array<{ fullName: string; cloneUrl: string; private: boolean }>;
|
||||||
installationStatus: FactoryOrganization["github"]["installationStatus"];
|
installationStatus: FoundryOrganization["github"]["installationStatus"];
|
||||||
lastSyncLabel: string;
|
lastSyncLabel: string;
|
||||||
},
|
},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
|
@ -1249,7 +1249,7 @@ export const workspaceAppActions = {
|
||||||
|
|
||||||
async markOrganizationSyncFailed(
|
async markOrganizationSyncFailed(
|
||||||
c: any,
|
c: any,
|
||||||
input: { message: string; installationStatus: FactoryOrganization["github"]["installationStatus"] },
|
input: { message: string; installationStatus: FoundryOrganization["github"]["installationStatus"] },
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
assertOrganizationWorkspace(c);
|
assertOrganizationWorkspace(c);
|
||||||
await c.db
|
await c.db
|
||||||
|
|
@ -1289,7 +1289,7 @@ export const workspaceAppActions = {
|
||||||
trialEnd: number | null;
|
trialEnd: number | null;
|
||||||
defaultPaymentMethodLabel: string;
|
defaultPaymentMethodLabel: string;
|
||||||
};
|
};
|
||||||
fallbackPlanId: FactoryBillingPlanId;
|
fallbackPlanId: FoundryBillingPlanId;
|
||||||
},
|
},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
assertOrganizationWorkspace(c);
|
assertOrganizationWorkspace(c);
|
||||||
|
|
@ -1347,7 +1347,7 @@ export const workspaceAppActions = {
|
||||||
.run();
|
.run();
|
||||||
},
|
},
|
||||||
|
|
||||||
async setOrganizationBillingStatus(c: any, input: { status: FactoryBillingState["status"] }): Promise<void> {
|
async setOrganizationBillingStatus(c: any, input: { status: FoundryBillingState["status"] }): Promise<void> {
|
||||||
assertOrganizationWorkspace(c);
|
assertOrganizationWorkspace(c);
|
||||||
await c.db
|
await c.db
|
||||||
.update(organizationProfile)
|
.update(organizationProfile)
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue