diff --git a/.cargo/config.toml b/.cargo/config.toml index dc7058400..e267a7636 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -7,3 +7,6 @@ t = "test -- --format terse" # pays ~900ms of system-proxy lookup overhead per process, which pushes tests # past the 3s nextest kill threshold under parallel load. FABRO_HTTP_PROXY_POLICY = "disabled" + +[net] +git-fetch-with-cli = true diff --git a/.config/nextest.toml b/.config/nextest.toml index aaec8ca9c..39f1c5520 100644 --- a/.config/nextest.toml +++ b/.config/nextest.toml @@ -15,6 +15,12 @@ leak-timeout = "500ms" filter = "package(fabro-workflow)" slow-timeout = { period = "2s", terminate-after = 3 } + # fabro-petri's adapter tests run whole workflows on the host sandbox + # through the sandbox-driver plugin, and one of them calls the twin. + [[profile.default.overrides]] + filter = "package(fabro-petri)" + slow-timeout = { period = "5s", terminate-after = 4 } + # Real descendant regressions include bounded reaping and process probes. # Leave room for their own watchdogs to run fail-safe fixture cleanup. [[profile.default.overrides]] @@ -59,3 +65,7 @@ leak-timeout = "2s" filter = "package(fabro-workflow)" slow-timeout = { period = "30s", terminate-after = 4 } + [[profile.ci.overrides]] + filter = "package(fabro-petri)" + slow-timeout = { period = "30s", terminate-after = 4 } + diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 8f3423e7e..758603179 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -91,6 +91,26 @@ jobs: fi - run: cargo +nightly-2026-04-14 clippy --locked --workspace --all-targets -- -D warnings + rustdoc: + name: Rustdoc + runs-on: ubuntu-24.04-x86-32-cores + permissions: + contents: read + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + with: + toolchain: 1.97.1 + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2 + with: + cache-on-failure: true + # Broken intra-doc links and the other rustdoc lints fail the build. + - run: cargo doc --locked --workspace --no-deps + env: + RUSTDOCFLAGS: -D warnings + generated-docs: name: Generated Docs runs-on: ubuntu-24.04-x86-32-cores @@ -124,6 +144,43 @@ jobs: with: cache-on-failure: true - uses: taiki-e/install-action@773334c0e05d7e699e4d78234494308223f3a2cf # nextest + # Every Petri run takes its scope through a sandbox-driver plugin + # executable that Petri finds on PATH: `sandbox-driver-host` for the + # `local` provider, `sandbox-driver-docker` for `docker`. Installed + # at the rev the workspace pins, so the plugins and the in-process + # driver are one build; a from-source build, so the two executables + # are cached by OS and rev and only rebuilt when the pin moves. + - name: Read the sandbox-driver rev the workspace pins + id: sandbox-driver + run: | + rev="$(sed -n 's/^sandbox-driver = { git = "[^"]*", rev = "\([0-9a-f]*\)" }$/\1/p' Cargo.toml)" + test -n "$rev" + echo "rev=$rev" >> "$GITHUB_OUTPUT" + - name: Restore the sandbox-driver plugin executables + id: sandbox-driver-cache + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: | + ~/.cargo/bin/sandbox-driver-host + ~/.cargo/bin/sandbox-driver-docker + key: sandbox-driver-plugins-${{ runner.os }}-${{ steps.sandbox-driver.outputs.rev }} + - name: Install the sandbox-driver plugin executables + if: steps.sandbox-driver-cache.outputs.cache-hit != 'true' + run: cargo install --locked --git https://github.com/lithoscomputer/sandbox-driver --rev "${{ steps.sandbox-driver.outputs.rev }}" sandbox-driver-host sandbox-driver-docker + # The images the suite's Docker tests run. The plugin pulls a missing + # image on first use, but a 1 GiB pull inside a run's wait is a flake, + # so pull them here, where a registry problem reads as one. Most tests + # leave the image to Petri, whose Docker scope runs on its default + # runner image at the pin the checked-out Petri names; the + # fabro-server catalog scenarios name CATALOG_IMAGE in + # lib/apps/fabro-server/tests/it/scenario/petri.rs. + - name: Pull the images the Docker tests run + run: | + backend="$(dirname "$(cargo metadata --locked --format-version 1 | jq -r '.packages[] | select(.name == "petri-executor-sandbox") | .manifest_path')")/src/backend.rs" + pin="$(sed -n 's/^const RUNNER_PIN: &str = "\([0-9a-f]*\)";$/\1/p' "$backend")" + test -n "$pin" + docker pull "ghcr.io/lithoscomputer/ubuntu-24.04:slim-$pin" + docker pull ghcr.io/lithoscomputer/ubuntu-22.04:slim - run: cargo nextest run --locked --workspace --status-level slow --profile ci # The twin-mode ignored suites this job once ran belonged to fabro-agent, # which pebble's coding agent replaced; the agent loop's workflow-level @@ -131,14 +188,14 @@ jobs: # Re-add a `--run-ignored only -E 'package(...)'` step here when a # package has ignored suites that are fully green in twin mode. - sandbox-plugins: - name: Sandbox plugins (stdio) + sandbox-docker: + name: Sandbox providers (Docker) runs-on: ubuntu-24.04-x86-32-cores permissions: contents: read env: - # The plugin scenarios skip when an executable or daemon is missing; - # in CI a skip is a failure. + # The Docker scenarios skip when the executable, the daemon or the + # image is missing; in CI a skip is a failure. FABRO_REQUIRE_SANDBOX_PLUGINS: "1" steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -151,25 +208,45 @@ jobs: with: cache-on-failure: true - uses: taiki-e/install-action@773334c0e05d7e699e4d78234494308223f3a2cf # nextest + # The image the Docker scenarios' environment names, and Petri's + # default runner image, which the fabro-petri Docker test runs. - run: docker pull buildpack-deps:noble - # The driver's own Host and Docker executables, installed at the rev the - # workspace pins so the plugins and the in-process providers are one - # build; the CLI scenarios find them on PATH and launch them over stdio. - - name: Install the sandbox-driver plugin executables + - name: Pull Petri's default runner image + run: | + backend="$(dirname "$(cargo metadata --locked --format-version 1 | jq -r '.packages[] | select(.name == "petri-executor-sandbox") | .manifest_path')")/src/backend.rs" + pin="$(sed -n 's/^const RUNNER_PIN: &str = "\([0-9a-f]*\)";$/\1/p' "$backend")" + test -n "$pin" + docker pull "ghcr.io/lithoscomputer/ubuntu-24.04:slim-$pin" + # Every Petri run takes its scope through a sandbox-driver plugin + # executable that Petri finds on PATH: `sandbox-driver-host` for the + # `local` provider, `sandbox-driver-docker` for `docker`. Installed + # at the rev the workspace pins, so the plugins and the in-process + # driver are one build; a from-source build, so the two executables + # are cached by OS and rev and only rebuilt when the pin moves. + - name: Read the sandbox-driver rev the workspace pins + id: sandbox-driver run: | rev="$(sed -n 's/^sandbox-driver = { git = "[^"]*", rev = "\([0-9a-f]*\)" }$/\1/p' Cargo.toml)" test -n "$rev" - cargo install --locked --git https://github.com/lithoscomputer/sandbox-driver --rev "$rev" sandbox-driver-host sandbox-driver-docker - # Host and Docker served as plugins through the workflow scenarios. The - # scenarios are e2e tests (ignored by default); the key-free ones run - # here, the LLM-backed ones self-skip without credentials. - - run: cargo nextest run --locked --profile ci --status-level slow --run-ignored only -p fabro-cli --test it -E 'test(/host_plugin_|docker_plugin_/)' - # The stdio plugin proof (not ignored: it skips without the executable, - # which the environment above forbids) and the driver-backed Docker - # integration tests. - - run: cargo nextest run --locked --profile ci --status-level slow -p fabro-sandbox --test plugin_provider - - run: cargo nextest run --locked --profile ci --status-level slow --run-ignored only -p fabro-sandbox --test docker_streaming - - run: cargo nextest run --locked --profile ci --status-level slow --run-ignored only -p fabro-workflow --test it -E 'test(asset_collection_docker_sandbox)' + echo "rev=$rev" >> "$GITHUB_OUTPUT" + - name: Restore the sandbox-driver plugin executables + id: sandbox-driver-cache + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: | + ~/.cargo/bin/sandbox-driver-host + ~/.cargo/bin/sandbox-driver-docker + key: sandbox-driver-plugins-${{ runner.os }}-${{ steps.sandbox-driver.outputs.rev }} + - name: Install the sandbox-driver plugin executables + if: steps.sandbox-driver-cache.outputs.cache-hit != 'true' + run: cargo install --locked --git https://github.com/lithoscomputer/sandbox-driver --rev "${{ steps.sandbox-driver.outputs.rev }}" sandbox-driver-host sandbox-driver-docker + # The workflow scenarios on the Docker provider. The scenarios are e2e + # tests (ignored by default); the key-free ones run here, the + # LLM-backed ones self-skip without credentials. + - run: cargo nextest run --locked --profile ci --status-level slow --run-ignored only -p fabro-cli --test it -E 'test(/::docker_/)' + # The Petri runs (not ignored: they skip without the host plugin, which + # the environment above forbids). + - run: cargo nextest run --locked --profile ci --status-level slow -p fabro-petri test-macos: name: Test (macOS) @@ -188,4 +265,28 @@ jobs: with: cache-on-failure: true - uses: taiki-e/install-action@773334c0e05d7e699e4d78234494308223f3a2cf # nextest + # Every Petri run takes its scope through a sandbox-driver plugin + # executable that Petri finds on PATH: `sandbox-driver-host` for the + # `local` provider, `sandbox-driver-docker` for `docker`. Installed + # at the rev the workspace pins, so the plugins and the in-process + # driver are one build; a from-source build, so the two executables + # are cached by OS and rev and only rebuilt when the pin moves. + - name: Read the sandbox-driver rev the workspace pins + id: sandbox-driver + run: | + rev="$(sed -n 's/^sandbox-driver = { git = "[^"]*", rev = "\([0-9a-f]*\)" }$/\1/p' Cargo.toml)" + test -n "$rev" + echo "rev=$rev" >> "$GITHUB_OUTPUT" + - name: Restore the sandbox-driver plugin executables + id: sandbox-driver-cache + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: | + ~/.cargo/bin/sandbox-driver-host + ~/.cargo/bin/sandbox-driver-docker + key: sandbox-driver-plugins-${{ runner.os }}-${{ steps.sandbox-driver.outputs.rev }} + - name: Install the sandbox-driver plugin executables + if: steps.sandbox-driver-cache.outputs.cache-hit != 'true' + run: cargo install --locked --git https://github.com/lithoscomputer/sandbox-driver --rev "${{ steps.sandbox-driver.outputs.rev }}" sandbox-driver-host sandbox-driver-docker + # No Docker daemon on the macOS runner: the Docker tests skip there. - run: cargo nextest run --locked --workspace --status-level slow --profile ci diff --git a/AGENTS.md b/AGENTS.md index 05ca4f0ad..382eb86d6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -30,21 +30,12 @@ macOS note: if `cargo nextest run` fails with `Too many open files (os error 24) ### Docker sandbox provider - Docker is the default runtime sandbox provider from `defaults.toml`. The Fabro process must have a working Docker client environment (`DOCKER_HOST`, socket access, Docker Desktop behavior, TLS settings, groups/permissions, and any remote daemon policy are operator responsibilities). - The packaged compose service mounts `/var/run/docker.sock` so the server can create sibling run containers on the host daemon. This is host-root-equivalent under Docker's security model; only use it in the trusted, single-tenant deployment model described by the sandbox code/docs. -- Docker and Daytona are clone-based providers. When a run manifest has a GitHub origin, they clone it into the provider workspace. Present non-GitHub origins fail unless the provider has `skip_clone = true`; absent origins or `skip_clone = true` create an empty workspace without repository files. For an exact commit, the submitted branch names the working branch and the syntactically valid SHA is requested directly. No layer proves branch/SHA ancestry: a fetchable commit is checked out, an unavailable commit fails setup, and branch HEAD is never substituted. -- The sandbox layer also accepts an optional exact commit for future admitted - runs. An exact commit always requires a non-empty branch. The sandbox driver - performs the pin the same way on every provider: it initializes an empty - repository, fetches the SHA directly at the requested depth, and attaches - the admitted branch to it, so the workspace reports the admitted branch - name. Daytona's native toolbox clone serves plain branch clones only; its - commit pin checks the branch head out first, so the driver does not use - it. A successful clone has the pin checked out; the driver's - conformance suite verifies that on every provider, and fabro does not - re-verify HEAD. Never fall back to a newer branch HEAD, and do not wire - this capability directly from legacy `GitContext.sha`. The sandbox layer - does not verify that the commit is reachable from the branch; admission - owns that check. Current production callers remain branch-only until the - RunIntent admission cutover supplies a validated branch/SHA pair. +- Fabro no longer clones a repository into a sandbox: the engine prepares + every run's checkout. `CloneRequest` still travels beside the sandbox spec + so the run record names the origin and branch; fabro validates it (a pin + needs a branch, a non-GitHub origin needs `skip_clone`) and refuses a + request that asks for a clone. Preflight and `fabro exec` initialize + sandboxes with `CloneRequest::none()`, which creates an empty workspace. ### Release automation - `cargo dev release` — creates the next stable release tag. Use `cargo dev release --nightly` for a nightly prerelease. Use `--dry-run` to print planned commands without mutating git or running Cargo, `--skip-tests` only after running the release-mode smoke yourself, and `--release-date YYYY-MM-DD` or `FABRO_RELEASE_DATE` for deterministic version computation. @@ -119,17 +110,132 @@ Before merging changes that add or move shared test helpers, verify: ## Architecture -Fabro is an AI-powered workflow orchestration platform. Workflows are defined as Graphviz graphs, where each node is a stage (agent, prompt, command, conditional, human, parallel, etc.) executed by the workflow engine. +Fabro is an AI-powered workflow orchestration platform. Workflows are defined as Graphviz graphs, where each node is a stage (agent, prompt, command, conditional, human, parallel, etc.). Petri, the workflow engine, admits a workflow at create and executes every run. Two crates import it: `fabro-petri` (the engine adapters) and `fabro-dot` (Petri's DOT parser, for reading a graph's shape and file references). ### Rust crates (`lib/apps/`, `lib/components/`, and `lib/foundation/`) - **fabro-cli** — CLI entry point. Commands: `run`, `exec`, `serve`, `validate`, `parse`, `cp`, `model`, `doctor`, `install`, `ps`, `system prune` -- **fabro-workflow** — Core workflow engine. Parses Graphviz graphs, runs stages, manages checkpoints/resume, hooks, and human-in-the-loop interactions -- **fabro-sandbox** — Local, Docker, and Daytona sandbox providers. `RunSandbox` is also the `Environment` pebble's coding agent runs its tools through; agent stages, Ask Fabro, hook evaluators, and `fabro exec` all run on the `pebble-coding-agent` crate (pinned by rev in the workspace `Cargo.toml`). `RunSandbox` is also the `Environment` pebble's coding agent runs its tools through; agent stages, Ask Fabro, hook evaluators, and `fabro exec` all run on the `pebble-coding-agent` crate (pinned by rev in the workspace `Cargo.toml`). Docker is the default runtime provider and creates clone-based `/workspace` containers through the operator's Docker daemon; Daytona uses the same GitHub-only clone-source contract. Docker daemon access is host-root-equivalent and assumes trusted callers/payloads. +- **fabro-workflow** — Fabro's platform half of a run: creates a run around Petri's admission (the run's display graph is read off the admitted graph), archives, forks and retries runs, and holds the run tools and the pull request pipeline. Compilation and execution are Petri's, through `fabro-petri` +- **fabro-dot** — The workflow graph as written, read through Petri's DOT parser: its name, goal, node and edge counts, and the files it references (`import`, `stack.child_workflow`, `@file` prompts, the goal). The bundler and the workflow-version store walk references through it; `fabro-graphviz` re-emits Fabro DOT for Graphviz through it +- **fabro-graphviz** — SVG rendering of workflow graphs through the vendored Graphviz (`graphviz-sys`) +- **fabro-pebble-sandbox** — A `sandbox-driver` handle as the `Environment` pebble's coding agent runs its tools through (`PebbleSandbox`), with Fabro's exec policy, port routes, and secret redactor. Petri creates and owns every run sandbox through the sandbox driver; Fabro attaches to one for Ask Fabro, and `fabro exec` creates a host sandbox of its own. Agent stages, Ask Fabro, hook evaluators, and `fabro exec` all run on the `pebble-coding-agent` crate (pinned by rev in the workspace `Cargo.toml`). Docker is the default runtime provider and runs the operator's Docker daemon; daemon access is host-root-equivalent and assumes trusted callers/payloads. +- **fabro-petri** — Fabro's adapters over Petri, the workflow engine: the one crate that imports the Petri packages (pinned by rev in the workspace `Cargo.toml`), holding the run store over SQLite and the platform adapters - **fabro-server** — Axum HTTP server. Routes for runs, sessions, models, completions, usage. SSE event streaming. Demo mode via header - **fabro-llm** — Unified LLM client with providers: Anthropic, OpenAI, Gemini, OpenAI-compatible, plus retry/middleware/streaming - **fabro-api** — Auto-generated Rust types and reqwest HTTP client from OpenAPI spec (build.rs + progenitor) - **fabro-github** — GitHub App auth (JWT signing, installation tokens, PR creation) -- **fabro-mcp** — Model Context Protocol client/server +- **fabro-mcp-server** — Fabro's own MCP server (`fabro mcp`): the run tools for external agents +- **fabro-slack** — Slack integration (socket mode, blocks API) +- **fabro-checkpoint** — Git checkpoint author identity and commit trailers +- **fabro-telemetry** — CLI analytics (Segment) and crash reporting (Sentry), with anonymous IDs, command sanitization, and detached subprocess delivery +- **fabro-util** — Shared utilities (redaction, terminal formatting) + +### TypeScript (fabro-web) +- `cd apps/fabro-web && bun run dev` — rebuild web assets on change for the Rust server; refresh the browser manually +- `cd apps/fabro-web && bun test` — run tests +- `cd apps/fabro-web && bun run typecheck` — type check +- `cd apps/fabro-web && bun run build` — production build (writes to `apps/fabro-web/dist/` only; does NOT update the bundled SPA that ships in the Rust binary) +- `cargo dev build [-- ]` — refreshes the embedded SPA assets from the production build, verifies SPA asset budgets, and then runs `cargo build` with forwarded args. The embedded assets are gitignored except for `.gitkeep`; use this when building a Rust binary that should include a populated SPA bundle. `bun run dev` for local development is unchanged because debug builds prefer `apps/fabro-web/dist/` on disk via the server fallback. + +### Docker image +- `cargo dev docker-build` — builds the local Docker image from the current tree using the release pipeline's cargo-zigbuild approach. Honors `--arch amd64|arm64`, `--tag ` (default `fabro-sh/fabro`), `--compile-only` (stages `tmp/docker-context//fabro` without `docker build`), and `--dry-run` (prints the Docker commands without running them). Prefer this over writing a throwaway Dockerfile; the release pipeline, `Dockerfile`, and this command share the same binary layout. + +### Docker sandbox provider +- Docker is the default runtime sandbox provider from `defaults.toml`. The Fabro process must have a working Docker client environment (`DOCKER_HOST`, socket access, Docker Desktop behavior, TLS settings, groups/permissions, and any remote daemon policy are operator responsibilities). +- The packaged compose service mounts `/var/run/docker.sock` so the server can create sibling run containers on the host daemon. This is host-root-equivalent under Docker's security model; only use it in the trusted, single-tenant deployment model described by the sandbox code/docs. +- Fabro no longer clones a repository into a sandbox: the engine prepares + every run's checkout. `CloneRequest` still travels beside the sandbox spec + so the run record names the origin and branch; fabro validates it (a pin + needs a branch, a non-GitHub origin needs `skip_clone`) and refuses a + request that asks for a clone. Preflight and `fabro exec` initialize + sandboxes with `CloneRequest::none()`, which creates an empty workspace. + +### Release automation +- `cargo dev release` — creates the next stable release tag. Use `cargo dev release --nightly` for a nightly prerelease. Use `--dry-run` to print planned commands without mutating git or running Cargo, `--skip-tests` only after running the release-mode smoke yourself, and `--release-date YYYY-MM-DD` or `FABRO_RELEASE_DATE` for deterministic version computation. + +### Marketing site (apps/marketing) +- `cd apps/marketing && bun run dev` — start Astro dev server +- `cd apps/marketing && bun run build` — production build +- `cd apps/marketing && bunx vercel --prod` — deploy to Vercel (project: website, domain: fabro.sh) + +### Dev servers +1. `fabro server start` — starts the Rust API server (demo mode is per-request via `X-Fabro-Demo: 1` header) +2. `cd apps/fabro-web && bun run dev` — rebuilds web assets on change; refresh the browser manually +3. Mintlify docs dev server (requires Docker — `mintlify dev` needs Node LTS which may not match the host): + ``` + docker run --rm -d -p 3333:3333 -v $(pwd)/docs/public:/docs -w /docs --name mintlify-dev node:22-slim \ + bash -c "npx mintlify dev --host 0.0.0.0 --port 3333" + ``` + Then open http://localhost:3333. Stop with `docker stop mintlify-dev`. + +## API workflow + +The OpenAPI spec at `docs/public/api-reference/fabro-api.yaml` is the source of truth for the fabro-api HTTP interface. + +1. Edit `docs/public/api-reference/fabro-api.yaml` +2. `cargo build -p fabro-api` — build.rs regenerates Rust types and client via progenitor +3. Write/update handler in `lib/apps/fabro-server/src/server.rs`, add route to `build_router()` +4. `cargo nextest run -p fabro-server` — conformance test catches spec/router drift +5. `cd lib/packages/fabro-api-client && bun run generate` — regenerates TypeScript Axios client + +### API type ownership + +- Treat OpenAPI as the source of truth for the wire contract, not as the automatic owner of Rust types. +- Before adding or keeping a generated schema type, search the workspace for an existing hand-written Rust type with the same product meaning. +- If the schema and an existing Rust type have the same semantics and serde shape, reuse the existing type via `lib/foundation/fabro-api/build.rs` `with_replacement(...)` instead of generating a parallel API type. +- If two types are close but not identical, prefer proposing changes that align them into one canonical type rather than accepting small drift. It is usually better to iterate the API now than to create permanently split Rust/API types. +- Keep a separate API DTO only when the API is intentionally a projection, summary, or presentation-specific view of internal state. In that case, give it a distinct API-facing name instead of reusing the internal concept name. +- Treat `ApiFoo` aliases and `foo_to_api` / `foo_from_api` adapters as a smell unless they represent a real semantic boundary. They should not exist only to bridge accidental duplicate types. +- If a type is shared across crates and is part of the core product vocabulary, move it to a shared crate first, then make `fabro-api` reuse it. +- For every new `with_replacement(...)`, add a `fabro-api` test that proves type identity and JSON parity with the OpenAPI schema. + +## Test support boundaries + +Test-only helpers, fixture constructors, fake credentials, in-memory stores, panic-heavy setup code, and test environment shims must not be exposed from production modules or linked into normal builds. + +Put shared test helpers in a dedicated `test_support` module gated behind tests or an explicit feature: + +```rust +#[cfg(any(test, feature = "test-support"))] +pub mod test_support; +``` + +If another crate's tests need those helpers, enable the feature only through a dev-dependency using Cargo's dual-listing pattern: + +```toml +[dependencies] +fabro-server = { path = "../fabro-server" } + +[dev-dependencies] +fabro-server = { path = "../fabro-server", features = ["test-support"] } +``` + +Do not enable `test-support` in default features, production dependencies, release builds, or binaries. + +Use names that make the boundary obvious: `test_app_state`, `test_store_bundle`, `test_auth_mode`, and similar. Avoid production-looking names such as `create_app_state` for test fixtures. `#[doc(hidden)]` is not a substitute for feature-gating; hidden public APIs still compile, link, and can be used accidentally. + +Before merging changes that add or move shared test helpers, verify: + +- `cargo build --workspace` succeeds without `test-support` +- relevant tests compile and run with `test-support` +- `rg -n "create_app_state|test-only-name"` does not show production call sites +- release/debug artifacts do not contain fake secrets, fixture tokens, or test helper symbols when built without `test-support` + +## Architecture + +Fabro is an AI-powered workflow orchestration platform. Workflows are defined as Graphviz graphs, where each node is a stage (agent, prompt, command, conditional, human, parallel, etc.). Petri, the workflow engine, admits a workflow at create and executes every run. Two crates import it: `fabro-petri` (the engine adapters) and `fabro-dot` (Petri's DOT parser, for reading a graph's shape and file references). + +### Rust crates (`lib/apps/`, `lib/components/`, and `lib/foundation/`) +- **fabro-cli** — CLI entry point. Commands: `run`, `exec`, `serve`, `validate`, `parse`, `cp`, `model`, `doctor`, `install`, `ps`, `system prune` +- **fabro-workflow** — Fabro's platform half of a run: creates a run around Petri's admission (the run's display graph is read off the admitted graph), archives, forks and retries runs, and holds the run tools and the pull request pipeline. Compilation and execution are Petri's, through `fabro-petri` +- **fabro-dot** — The workflow graph as written, read through Petri's DOT parser: its name, goal, node and edge counts, and the files it references (`import`, `stack.child_workflow`, `@file` prompts, the goal). The bundler and the workflow-version store walk references through it; `fabro-graphviz` re-emits Fabro DOT for Graphviz through it +- **fabro-graphviz** — SVG rendering of workflow graphs through the vendored Graphviz (`graphviz-sys`) +- **fabro-pebble-sandbox** — A `sandbox-driver` handle as the `Environment` pebble's coding agent runs its tools through (`PebbleSandbox`), with Fabro's exec policy, port routes, and secret redactor. Petri creates and owns every run sandbox through the sandbox driver; Fabro attaches to one for Ask Fabro, and `fabro exec` creates a host sandbox of its own. Agent stages, Ask Fabro, hook evaluators, and `fabro exec` all run on the `pebble-coding-agent` crate (pinned by rev in the workspace `Cargo.toml`). Docker is the default runtime provider and runs the operator's Docker daemon; daemon access is host-root-equivalent and assumes trusted callers/payloads. +- **fabro-petri** — Fabro's adapters over Petri, the workflow engine: the one crate that imports the Petri packages (pinned by rev in the workspace `Cargo.toml`), holding the run store over SQLite and the platform adapters +- **fabro-server** — Axum HTTP server. Routes for runs, sessions, models, completions, usage. SSE event streaming. Demo mode via header +- **fabro-llm** — Unified LLM client with providers: Anthropic, OpenAI, Gemini, OpenAI-compatible, plus retry/middleware/streaming +- **fabro-api** — Auto-generated Rust types and reqwest HTTP client from OpenAPI spec (build.rs + progenitor) +- **fabro-github** — GitHub App auth (JWT signing, installation tokens, PR creation) +- **fabro-mcp-server** — Fabro's own MCP server (`fabro mcp`): the run tools for external agents - **fabro-slack** — Slack integration (socket mode, blocks API) - **fabro-checkpoint** — Git checkpoint author identity and commit trailers - **fabro-telemetry** — CLI analytics (Segment) and crash reporting (Sentry), with anonymous IDs, command sanitization, and detached subprocess delivery @@ -140,7 +246,7 @@ Fabro is an AI-powered workflow orchestration platform. Workflows are defined as - **lib/packages/fabro-api-client** — Auto-generated TypeScript Axios client from OpenAPI spec ### Key design patterns -- **RunSandbox** — One concrete sandbox type for local, Docker, and Daytona execution environments, over the `sandbox-driver` facets (exec, filesystem, search, git). There is no fabro-side sandbox trait; tests use `fabro_sandbox::test_support::MockSandbox` over the driver's scripted doubles. Clone-based providers use run-spec GitHub origin metadata rather than worker process cwd detection. +- **Direct sandbox access** — Petri creates every run sandbox through the sandbox driver and records its provider, id and working directory on the run (`RunSandboxInstance`); every Docker and Daytona sandbox carries the `petri.run` label. The server reaches a run's sandbox (the sandbox tab, Run Files, terminal, SSH, preview URLs, VNC, `fabro cp`, Ask Fabro) through `fabro-server/src/sandbox_access.rs`: it connects the record's provider itself, keys ownership on `petri.run`, and works on the driver's `Arc` facets (exec, filesystem, search, git, pty). Deleting a run deletes its sandboxes through Petri's lease ledger (`fabro_petri::prune`, what `petri sandbox prune` does), not through a provider call of Fabro's own. There is no fabro-side sandbox trait; tests use `fabro_pebble_sandbox::test_support::MockSandbox` over the driver's scripted doubles. - **Graphviz graph workflows** — Stages and transitions defined as Graphviz graph attributes - **OpenAPI-first** — `fabro-api.yaml` drives Rust type + client generation (progenitor) and TypeScript client generation (openapi-generator) - **Checkpoint/resume** — Workflows can be paused, checkpointed, and resumed @@ -151,7 +257,7 @@ When working in an area covered by a strategy doc, read the relevant document **before** making changes: - **`docs/internal/logging-strategy.md`** — read when adding `tracing` calls (`info!`, `debug!`, `warn!`, `error!`), working on error handling paths, or adding new operations that should be observable -- **`docs/internal/events-strategy.md`** — read when adding or modifying `Event` variants, touching `Emitter`/`emit()`, changing `progress.jsonl` output, or adding new workflow stage types +- **`docs/internal/events-strategy.md`** — read when adding a platform record kind, changing the projection fold or the run stream, or writing a consumer that matches on stream items - **`docs/internal/testing-strategy.md`** — read when adding or reorganizing tests, choosing between unit vs `tests/it`, deciding whether a test belongs in `cmd` vs `workflow` vs `scenario`, or deciding how to structure snapshots and fixtures - **`docs/internal/server-secrets-strategy.md`** — read when adding or changing server-level secrets, startup validation, install-time secret persistence, or subprocess env inheritance/scrubbing - **`docs/internal/migrations-strategy.md`** — read when adding or changing temporary compatibility migrations, startup/file rewrites, migration runners, backups, or removal deadlines diff --git a/Cargo.lock b/Cargo.lock index c2e2e482f..8e29324a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,72 +58,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "agent-client-protocol" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af62fb84df2af0f933d8f5fd78b843fa5eb0ec5a48fa1b528c41951d0bbe36c" -dependencies = [ - "agent-client-protocol-derive", - "agent-client-protocol-schema", - "anyhow", - "futures", - "futures-concurrency", - "jsonrpcmsg", - "rmcp", - "rustc-hash", - "schemars 1.2.1", - "serde", - "serde_json", - "thiserror 2.0.18", - "tokio", - "tokio-util", - "tracing", - "uuid", -] - -[[package]] -name = "agent-client-protocol-derive" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce42c2d3c048c12897eef2e577dfff1e3355c632c9f1625cc953b9df48b44631" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "agent-client-protocol-schema" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49bae57dad1c28a362fbdcf7bab0583316a02b45a70792109fced55780a3b63c" -dependencies = [ - "anyhow", - "derive_more", - "schemars 1.2.1", - "serde", - "serde_json", - "serde_with", - "strum 0.28.0", - "tracing", -] - -[[package]] -name = "agent-client-protocol-tokio" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1572b219f22c4b3be0f20f934c8b6f1d1457126ce72923c4f6608f96153b65" -dependencies = [ - "agent-client-protocol", - "futures", - "serde", - "serde_json", - "shell-words", - "tokio", - "tokio-util", -] - [[package]] name = "ahash" version = "0.8.12" @@ -147,12 +81,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "aliasable" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" - [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -249,49 +177,10 @@ dependencies = [ ] [[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "asn1-rs" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" -dependencies = [ - "asn1-rs-derive", - "asn1-rs-impl", - "displaydoc", - "nom", - "num-traits", - "rusticata-macros", - "thiserror 1.0.69", - "time", -] - -[[package]] -name = "asn1-rs-derive" +name = "arraydeque" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", - "synstructure", -] - -[[package]] -name = "asn1-rs-impl" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" [[package]] name = "assert-json-diff" @@ -318,18 +207,6 @@ dependencies = [ "wait-timeout", ] -[[package]] -name = "async-channel" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - [[package]] name = "async-compression" version = "0.4.42" @@ -383,15 +260,9 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - [[package]] name = "async-trait" version = "0.1.89" @@ -400,7 +271,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -427,33 +298,12 @@ dependencies = [ "num-traits", ] -[[package]] -name = "atomic" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" -dependencies = [ - "bytemuck", -] - [[package]] name = "atomic-waker" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "auto_enums" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65398a2893f41bce5c9259f6e1a4f03fbae40637c1bdc755b4f387f48c613b03" -dependencies = [ - "derive_utils", - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "autocfg" version = "1.5.0" @@ -787,7 +637,7 @@ checksum = "8d7396fd9500589e62e460e987ecb671bad374934e55ec3b5f498cc7a8a8a7b7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -938,18 +788,7 @@ checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", -] - -[[package]] -name = "backon" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" -dependencies = [ - "fastrand", - "gloo-timers", - "tokio", + "syn", ] [[package]] @@ -992,15 +831,6 @@ dependencies = [ "vsimd", ] -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - [[package]] name = "bit-set" version = "0.8.0" @@ -1102,6 +932,16 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc0b364ead1874514c8c2855ab558056ebfeb775653e7ae45ff72f28f8f3166c" +[[package]] +name = "borsh" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "553c5d846a6ba5150c65e3b1b8ec073bcf1abc20f9b7220de384a4443ea4e20a" +dependencies = [ + "bytes", + "cfg_aliases", +] + [[package]] name = "brotli" version = "8.0.1" @@ -1155,12 +995,6 @@ version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" -[[package]] -name = "bytemuck" -version = "1.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" - [[package]] name = "byteorder" version = "1.5.0" @@ -1270,7 +1104,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.1", + "strsim", ] [[package]] @@ -1288,10 +1122,10 @@ version = "4.5.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -1325,12 +1159,6 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" -[[package]] -name = "cmsketch" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ee2cfacbd29706479902b06d75ad8f1362900836aa32799eabc7e004bfd854" - [[package]] name = "colorchoice" version = "1.0.4" @@ -1560,7 +1388,7 @@ dependencies = [ "proc-macro2", "quote", "strict", - "syn 2.0.117", + "syn", ] [[package]] @@ -1624,16 +1452,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "crossbeam-skiplist" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df29de440c58ca2cc6e587ec3d22347551a32435fbde9d2bff64e78a9ffa151b" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -1726,16 +1544,6 @@ dependencies = [ "cmov", ] -[[package]] -name = "darling" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" -dependencies = [ - "darling_core 0.14.4", - "darling_macro 0.14.4", -] - [[package]] name = "darling" version = "0.20.11" @@ -1756,20 +1564,6 @@ dependencies = [ "darling_macro 0.23.0", ] -[[package]] -name = "darling_core" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.10.0", - "syn 1.0.109", -] - [[package]] name = "darling_core" version = "0.20.11" @@ -1780,8 +1574,8 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.11.1", - "syn 2.0.117", + "strsim", + "syn", ] [[package]] @@ -1793,19 +1587,8 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.11.1", - "syn 2.0.117", -] - -[[package]] -name = "darling_macro" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" -dependencies = [ - "darling_core 0.14.4", - "quote", - "syn 1.0.109", + "strsim", + "syn", ] [[package]] @@ -1816,7 +1599,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -1827,7 +1610,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core 0.23.0", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -1915,20 +1698,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "der-parser" -version = "9.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" -dependencies = [ - "asn1-rs", - "displaydoc", - "nom", - "num-bigint", - "num-traits", - "rusticata-macros", -] - [[package]] name = "deranged" version = "0.5.8" @@ -1957,7 +1726,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -1967,7 +1736,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.117", + "syn", ] [[package]] @@ -1989,19 +1758,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.117", - "unicode-xid", -] - -[[package]] -name = "derive_utils" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "362f47930db19fe7735f527e6595e4900316b893ebf6d48ad3d31be928d57dd6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -2063,7 +1820,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2084,9 +1841,15 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] +[[package]] +name = "doc-comment" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "780955b8b195a21ab8e4ac6b60dd1dbdcec1dc6c51c0617964b08c81785e12c9" + [[package]] name = "document-features" version = "0.2.12" @@ -2102,31 +1865,12 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" -[[package]] -name = "downcast-rs" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" - [[package]] name = "dunce" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" -[[package]] -name = "duration-str" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f88959de2d447fd3eddcf1909d1f19fe084e27a056a6904203dc5d8b9e771c1e" -dependencies = [ - "rust_decimal", - "serde", - "thiserror 2.0.18", - "time", - "winnow 0.6.26", -] - [[package]] name = "dyn-clone" version = "1.0.20" @@ -2190,7 +1934,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2244,26 +1988,6 @@ dependencies = [ "libc", ] -[[package]] -name = "fabro-acp" -version = "0.362.0-nightly.0" -dependencies = [ - "agent-client-protocol", - "agent-client-protocol-tokio", - "fabro-sandbox", - "fabro-types", - "fabro-util", - "futures", - "pebble-coding-agent", - "serde_json", - "shlex", - "tempfile", - "thiserror 2.0.18", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "fabro-api" version = "0.362.0-nightly.0" @@ -2286,7 +2010,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "syn 2.0.117", + "syn", "uuid", ] @@ -2366,44 +2090,38 @@ dependencies = [ "core-foundation 0.9.4", "dialoguer", "dirs", - "dotenvy", - "fabro-acp", "fabro-api", "fabro-auth", "fabro-build-support", - "fabro-checkpoint", "fabro-client", "fabro-config", + "fabro-db", "fabro-dump", "fabro-environment", "fabro-github", "fabro-graphviz", - "fabro-hooks", "fabro-http", "fabro-install", "fabro-interview", "fabro-llm", "fabro-macros", "fabro-manifest", - "fabro-mcp", "fabro-mcp-server", "fabro-oauth", + "fabro-pebble-sandbox", + "fabro-petri", "fabro-proc", "fabro-redact", - "fabro-sandbox", "fabro-server", "fabro-static", "fabro-store", "fabro-telemetry", - "fabro-template", "fabro-test", "fabro-tool", "fabro-types", "fabro-util", - "fabro-validate", "fabro-vault", "fabro-workflow", - "fs2", "futures", "git2", "hkdf 0.12.4", @@ -2418,17 +2136,17 @@ dependencies = [ "object_store", "openssl", "paste", - "pebble-agent", "pebble-cli-core", "pebble-coding-agent", "predicates", - "progenitor-client", "rand 0.9.4", "regex", "reqwest 0.13.4", "ring", + "rmcp", "rustls", "sandbox-driver", + "sandbox-driver-host", "scopeguard", "semver", "serde", @@ -2449,7 +2167,6 @@ dependencies = [ "tracing-subscriber", "ulid", "walkdir", - "x509-parser", ] [[package]] @@ -2498,7 +2215,7 @@ dependencies = [ "ipnet", "serde", "serde_json", - "strsim 0.11.1", + "strsim", "strum 0.28.0", "temp-env", "tempfile", @@ -2510,22 +2227,6 @@ dependencies = [ "ulid", ] -[[package]] -name = "fabro-core" -version = "0.362.0-nightly.0" -dependencies = [ - "async-trait", - "fabro-types", - "fabro-util", - "serde", - "serde_json", - "strum 0.28.0", - "thiserror 2.0.18", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "fabro-db" version = "0.362.0-nightly.0" @@ -2558,6 +2259,18 @@ dependencies = [ "walkdir", ] +[[package]] +name = "fabro-dot" +version = "0.362.0-nightly.0" +dependencies = [ + "fabro-template", + "fabro-types", + "insta", + "petri-frontend-attractor", + "thiserror 2.0.18", + "walkdir", +] + [[package]] name = "fabro-dump" version = "0.362.0-nightly.0" @@ -2624,39 +2337,9 @@ name = "fabro-graphviz" version = "0.362.0-nightly.0" dependencies = [ "anyhow", - "fabro-types", + "fabro-dot", "graphviz-sys", - "nom", "regex", - "serde", - "serde_json", - "strum 0.28.0", - "thiserror 2.0.18", -] - -[[package]] -name = "fabro-hooks" -version = "0.362.0-nightly.0" -dependencies = [ - "async-trait", - "fabro-auth", - "fabro-http", - "fabro-llm", - "fabro-redact", - "fabro-sandbox", - "fabro-types", - "fabro-util", - "httpmock", - "lithos-llm", - "pebble-agent", - "pebble-coding-agent", - "regex", - "serde", - "serde_json", - "tokio", - "tokio-util", - "toml 0.8.23", - "tracing", ] [[package]] @@ -2674,7 +2357,6 @@ name = "fabro-install" version = "0.362.0-nightly.0" dependencies = [ "anyhow", - "base64", "fabro-config", "fabro-db", "fabro-environment", @@ -2682,7 +2364,6 @@ dependencies = [ "fabro-types", "fabro-util", "fabro-vault", - "ring", "tempfile", "tokio", "toml 0.8.23", @@ -2693,12 +2374,9 @@ name = "fabro-interview" version = "0.362.0-nightly.0" dependencies = [ "async-trait", - "dialoguer", "fabro-types", - "fabro-util", "serde", "serde_json", - "tempfile", "tokio", "tracing", ] @@ -2707,7 +2385,6 @@ dependencies = [ name = "fabro-llm" version = "0.362.0-nightly.0" dependencies = [ - "anyhow", "async-trait", "bytes", "fabro-auth", @@ -2715,7 +2392,6 @@ dependencies = [ "fabro-http", "fabro-llm", "fabro-macros", - "fabro-redact", "fabro-static", "fabro-test", "fabro-types", @@ -2727,9 +2403,7 @@ dependencies = [ "strum 0.28.0", "thiserror 2.0.18", "tokio", - "tokio-util", "toml 0.8.23", - "tracing", ] [[package]] @@ -2740,7 +2414,7 @@ dependencies = [ "fabro-options-metadata", "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -2751,8 +2425,8 @@ dependencies = [ "async-trait", "fabro-api", "fabro-config", + "fabro-dot", "fabro-github", - "fabro-graphviz", "fabro-template", "fabro-test", "fabro-tool", @@ -2772,43 +2446,23 @@ dependencies = [ "tracing-subscriber", ] -[[package]] -name = "fabro-mcp" -version = "0.362.0-nightly.0" -dependencies = [ - "anyhow", - "fabro-types", - "pebble-coding-agent", - "rmcp", - "serde_json", - "tokio", - "tracing", -] - [[package]] name = "fabro-mcp-server" version = "0.362.0-nightly.0" dependencies = [ "anyhow", - "chrono", - "fabro-api", "fabro-client", - "fabro-config", "fabro-manifest", - "fabro-server", "fabro-tool", "fabro-types", "fabro-util", - "futures", "httpmock", "rmcp", "schemars 1.2.1", "serde", "serde_json", - "strum 0.28.0", "tempfile", "tokio", - "toml 0.8.23", "tracing", ] @@ -2860,6 +2514,70 @@ dependencies = [ "serde_json", ] +[[package]] +name = "fabro-pebble-sandbox" +version = "0.362.0-nightly.0" +dependencies = [ + "async-trait", + "fabro-redact", + "fabro-types", + "fabro-util", + "pebble-coding-agent", + "sandbox-driver", + "sandbox-driver-host", + "sandbox-driver-testing", + "serde_json", + "tempfile", + "thiserror 2.0.18", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "fabro-petri" +version = "0.362.0-nightly.0" +dependencies = [ + "anyhow", + "async-trait", + "bytes", + "chrono", + "fabro-api", + "fabro-auth", + "fabro-checkpoint", + "fabro-client", + "fabro-db", + "fabro-http", + "fabro-interview", + "fabro-llm", + "fabro-petri", + "fabro-store", + "fabro-test", + "fabro-tool", + "fabro-types", + "fabro-util", + "fabro-vault", + "fabro-workflow", + "httpmock", + "lithos-llm", + "pebble-coding-agent", + "petri-attractor-steps", + "petri-execution", + "petri-frontend-attractor", + "petri-frontend-fabro", + "petri-runtime", + "petri-store", + "petri-testkit", + "serde", + "serde_json", + "sqlx", + "tempfile", + "thiserror 2.0.18", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "fabro-proc" version = "0.362.0-nightly.0" @@ -2889,44 +2607,6 @@ dependencies = [ "url", ] -[[package]] -name = "fabro-sandbox" -version = "0.362.0-nightly.0" -dependencies = [ - "anyhow", - "async-trait", - "base64", - "chrono", - "fabro-github", - "fabro-proc", - "fabro-redact", - "fabro-static", - "fabro-test", - "fabro-types", - "fabro-util", - "futures", - "pebble-coding-agent", - "reqwest 0.13.4", - "sandbox-driver", - "sandbox-driver-daytona", - "sandbox-driver-daytona-config", - "sandbox-driver-docker", - "sandbox-driver-docker-config", - "sandbox-driver-host", - "sandbox-driver-protocol", - "sandbox-driver-testing", - "serde", - "serde_json", - "strum 0.28.0", - "tempfile", - "thiserror 2.0.18", - "tokio", - "tokio-util", - "toml 0.8.23", - "tracing", - "uuid", -] - [[package]] name = "fabro-server" version = "0.362.0-nightly.0" @@ -2942,7 +2622,6 @@ dependencies = [ "clap", "cookie", "croner", - "dirs", "fabro-api", "fabro-auth", "fabro-automation", @@ -2950,10 +2629,10 @@ dependencies = [ "fabro-client", "fabro-config", "fabro-db", + "fabro-dot", "fabro-environment", "fabro-github", "fabro-graphviz", - "fabro-hooks", "fabro-http", "fabro-install", "fabro-interview", @@ -2961,9 +2640,10 @@ dependencies = [ "fabro-macros", "fabro-manifest", "fabro-mcp-store", + "fabro-pebble-sandbox", + "fabro-petri", "fabro-proc", "fabro-redact", - "fabro-sandbox", "fabro-slack", "fabro-spa", "fabro-static", @@ -2973,7 +2653,6 @@ dependencies = [ "fabro-tool", "fabro-types", "fabro-util", - "fabro-validate", "fabro-variable", "fabro-vault", "fabro-workflow", @@ -2989,16 +2668,18 @@ dependencies = [ "jsonwebtoken", "lithos-llm", "mime_guess", - "multer", "object_store", "pebble-agent", "pebble-coding-agent", "percent-encoding", "rand 0.9.4", - "regex", "reqwest 0.12.28", "sandbox-driver", - "semver", + "sandbox-driver-daytona", + "sandbox-driver-docker", + "sandbox-driver-host", + "sandbox-driver-protocol", + "sandbox-driver-testing", "serde", "serde_json", "serde_yaml", @@ -3013,7 +2694,6 @@ dependencies = [ "tokio-tungstenite 0.26.2", "tokio-util", "toml 0.8.23", - "toml_edit", "tower", "tower-http", "tracing", @@ -3033,7 +2713,6 @@ dependencies = [ "fabro-interview", "fabro-static", "fabro-types", - "fabro-workflow", "futures-util", "rustls", "serde", @@ -3062,13 +2741,11 @@ version = "0.362.0-nightly.0" name = "fabro-store" version = "0.362.0-nightly.0" dependencies = [ - "async-trait", "bytes", "chrono", "dashmap", "fabro-db", "fabro-types", - "fabro-util", "futures", "hex", "insta", @@ -3079,14 +2756,11 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.9", - "slatedb", "sqlx", "strum 0.28.0", "tempfile", "thiserror 2.0.18", "tokio", - "tokio-stream", - "tracing", "ulid", "uuid", ] @@ -3244,19 +2918,6 @@ dependencies = [ "tracing-subscriber", ] -[[package]] -name = "fabro-validate" -version = "0.362.0-nightly.0" -dependencies = [ - "fabro-acp", - "fabro-graphviz", - "fabro-llm", - "fabro-types", - "serde", - "thiserror 2.0.18", - "toml 0.8.23", -] - [[package]] name = "fabro-variable" version = "0.362.0-nightly.0" @@ -3298,73 +2959,45 @@ name = "fabro-workflow" version = "0.362.0-nightly.0" dependencies = [ "anyhow", - "assert_cmd", "async-trait", - "base64", "bytes", "chrono", "dirs", - "fabro-acp", - "fabro-api", "fabro-auth", - "fabro-checkpoint", "fabro-client", "fabro-config", - "fabro-core", "fabro-dump", "fabro-environment", "fabro-github", - "fabro-graphviz", - "fabro-hooks", "fabro-http", - "fabro-interview", "fabro-llm", "fabro-macros", - "fabro-mcp", + "fabro-pebble-sandbox", "fabro-redact", - "fabro-sandbox", - "fabro-static", "fabro-store", - "fabro-template", "fabro-test", "fabro-tool", "fabro-types", "fabro-util", - "fabro-validate", "fabro-vault", "fabro-workflow", "fabro-workflow-version", - "futures", "git2", "hex", "httpmock", - "jsonschema", "lithos-llm", - "md5", - "miette", - "mime_guess", - "object_store", - "pebble-agent", "pebble-coding-agent", - "predicates", - "rand 0.9.4", - "regex", "sandbox-driver", + "sandbox-driver-host", "scopeguard", "serde", "serde_json", - "sha2 0.10.9", - "shlex", - "strum 0.28.0", "tempfile", "thiserror 2.0.18", "tokio", - "tokio-util", "toml 0.8.23", "tracing", "ulid", - "uuid", - "walkdir", ] [[package]] @@ -3372,7 +3005,7 @@ name = "fabro-workflow-version" version = "0.362.0-nightly.0" dependencies = [ "fabro-config", - "fabro-graphviz", + "fabro-dot", "fabro-store", "fabro-template", "fabro-types", @@ -3383,17 +3016,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "fail-parallel" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5666e8ca4ec174d896fb742789c29b1bea9319dcfd623c41bececc0a60c4939d" -dependencies = [ - "log", - "once_cell", - "rand 0.8.6", -] - [[package]] name = "fancy-regex" version = "0.17.0" @@ -3411,22 +3033,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" -[[package]] -name = "figment" -version = "0.10.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" -dependencies = [ - "atomic", - "pear", - "serde", - "serde_json", - "serde_yaml", - "toml 0.8.23", - "uncased", - "version_check", -] - [[package]] name = "filetime" version = "0.2.27" @@ -3444,22 +3050,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" -[[package]] -name = "fixedbitset" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" - -[[package]] -name = "flatbuffers" -version = "25.12.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35f6839d7b3b98adde531effaf34f0c2badc6f4735d26fe74709d8e513a96ef3" -dependencies = [ - "bitflags", - "rustc_version", -] - [[package]] name = "flate2" version = "1.1.9" @@ -3490,18 +3080,6 @@ dependencies = [ "serde", ] -[[package]] -name = "flume" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" -dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "spin", -] - [[package]] name = "flume" version = "0.12.0" @@ -3564,112 +3142,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "foyer" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642093b1a72c4a0ef89862484d669a353e732974781bb9c49a979526d1e30edc" -dependencies = [ - "equivalent", - "foyer-common", - "foyer-memory", - "foyer-storage", - "madsim-tokio", - "mixtrics", - "pin-project", - "serde", - "thiserror 2.0.18", - "tokio", - "tracing", -] - -[[package]] -name = "foyer-common" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9db9c0e4648b13e9216d785b308d43751ca975301aeb83e607ec630b6f956944" -dependencies = [ - "bincode", - "bytes", - "cfg-if", - "itertools", - "madsim-tokio", - "mixtrics", - "parking_lot", - "pin-project", - "serde", - "thiserror 2.0.18", - "tokio", - "twox-hash", -] - -[[package]] -name = "foyer-intrusive-collections" -version = "0.10.0-dev" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4fee46bea69e0596130e3210e65d3424e0ac1e6df3bde6636304bdf1ca4a3b" -dependencies = [ - "memoffset", -] - -[[package]] -name = "foyer-memory" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "040dc38acbfca8f1def26bbbd9e9199090884aabb15de99f7bf4060be66ff608" -dependencies = [ - "arc-swap", - "bitflags", - "cmsketch", - "equivalent", - "foyer-common", - "foyer-intrusive-collections", - "hashbrown 0.15.5", - "itertools", - "madsim-tokio", - "mixtrics", - "parking_lot", - "pin-project", - "serde", - "thiserror 2.0.18", - "tokio", - "tracing", -] - -[[package]] -name = "foyer-storage" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a77ed888da490e997da6d6d62fcbce3f202ccf28be098c4ea595ca046fc4a9" -dependencies = [ - "allocator-api2", - "anyhow", - "auto_enums", - "bytes", - "equivalent", - "flume 0.11.1", - "foyer-common", - "foyer-memory", - "fs4", - "futures-core", - "futures-util", - "itertools", - "libc", - "lz4", - "madsim-tokio", - "ordered_hash_map", - "parking_lot", - "paste", - "pin-project", - "rand 0.9.4", - "serde", - "thiserror 2.0.18", - "tokio", - "tracing", - "twox-hash", - "zstd", -] - [[package]] name = "fraction" version = "0.15.3" @@ -3690,16 +3162,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "fs4" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8640e34b88f7652208ce9e88b1a37a2ae95227d84abec377ccd3c5cfeb141ed4" -dependencies = [ - "rustix", - "windows-sys 0.59.0", -] - [[package]] name = "fs_extra" version = "1.3.0" @@ -3731,19 +3193,6 @@ dependencies = [ "futures-sink", ] -[[package]] -name = "futures-concurrency" -version = "7.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175cd8cca9e1d45b87f18ffa75088f2099e3c4fe5e2f83e42de112560bea8ea6" -dependencies = [ - "fixedbitset", - "futures-core", - "futures-lite", - "pin-project", - "smallvec", -] - [[package]] name = "futures-core" version = "0.3.32" @@ -3799,7 +3248,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -3938,18 +3387,6 @@ dependencies = [ "regex-syntax", ] -[[package]] -name = "gloo-timers" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - [[package]] name = "graphviz-sys" version = "0.1.0" @@ -3983,15 +3420,6 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash", -] - [[package]] name = "hashbrown" version = "0.14.5" @@ -4004,8 +3432,6 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "allocator-api2", - "equivalent", "foldhash 0.1.5", ] @@ -4020,6 +3446,15 @@ dependencies = [ "foldhash 0.2.0", ] +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.5", +] + [[package]] name = "hashlink" version = "0.11.1" @@ -4053,12 +3488,6 @@ dependencies = [ "http 1.4.0", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -4358,7 +3787,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.2", + "windows-core 0.61.2", ] [[package]] @@ -4504,7 +3933,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -4553,12 +3982,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "inlinable_string" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" - [[package]] name = "inout" version = "0.1.4" @@ -4684,7 +4107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" dependencies = [ "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -4707,16 +4130,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "jsonrpcmsg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d833a15225c779251e13929203518c2ff26e2fe0f322d584b213f4f4dad37bd" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "jsonschema" version = "0.42.2" @@ -4781,7 +4194,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.117", + "syn", ] [[package]] @@ -4939,25 +4352,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" -[[package]] -name = "lz4" -version = "1.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20b523e860d03443e98350ceaac5e71c6ba89aea7d960769ec3ce37f4de5af4" -dependencies = [ - "lz4-sys", -] - -[[package]] -name = "lz4-sys" -version = "1.11.1+lz4-1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "mac_address" version = "1.1.8" @@ -4969,58 +4363,14 @@ dependencies = [ ] [[package]] -name = "madsim" -version = "0.2.34" +name = "marked-yaml" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18351aac4194337d6ea9ffbd25b3d1540ecc0754142af1bff5ba7392d1f6f771" +checksum = "3a76cf4e66a8ffccfce983161b0faafe61a5ef03fe875ef2e3deb897e4e915fa" dependencies = [ - "ahash", - "async-channel", - "async-stream", - "async-task", - "bincode", - "bytes", - "downcast-rs", - "errno 0.3.14", - "futures-util", - "lazy_static", - "libc", - "madsim-macros", - "naive-timer", - "panic-message", - "rand 0.8.6", - "rand_xoshiro 0.6.0", - "rustversion", - "serde", - "spin", - "tokio", - "tokio-util", - "toml 0.9.12+spec-1.1.0", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "madsim-macros" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d248e97b1a48826a12c3828d921e8548e714394bf17274dd0a93910dc946e1" -dependencies = [ - "darling 0.14.4", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "madsim-tokio" -version = "0.2.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d3eb2acc57c82d21d699119b859e2df70a91dbdb84734885a1e72be83bdecb5" -dependencies = [ - "madsim", - "spin", - "tokio", + "doc-comment", + "hashlink 0.10.0", + "yaml-rust2", ] [[package]] @@ -5112,7 +4462,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -5150,12 +4500,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.8.9" @@ -5178,48 +4522,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "mixtrics" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb252c728b9d77c6ef9103f0c81524fa0a3d3b161d0a936295d7fbeff6e04c11" -dependencies = [ - "itertools", - "parking_lot", -] - -[[package]] -name = "multer" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" -dependencies = [ - "bytes", - "encoding_rs", - "futures-util", - "http 1.4.0", - "httparse", - "memchr", - "mime", - "spin", - "version_check", -] - -[[package]] -name = "naive-timer" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034a0ad7deebf0c2abcf2435950a6666c3c15ea9d8fad0c0f48efa8a7f843fed" - -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom 0.2.17", -] - [[package]] name = "native-tls" version = "0.2.18" @@ -5274,16 +4576,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "normalize-line-endings" version = "0.3.0" @@ -5305,7 +4597,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5607,15 +4899,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "oid-registry" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" -dependencies = [ - "asn1-rs", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -5678,7 +4961,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -5721,15 +5004,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "ordered_hash_map" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab0e5f22bf6dd04abd854a8874247813a8fa2c8c1260eba6fbb150270ce7c176" -dependencies = [ - "hashbrown 0.13.2", -] - [[package]] name = "os_info" version = "3.14.0" @@ -5746,30 +5020,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "ouroboros" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59" -dependencies = [ - "aliasable", - "ouroboros_macro", - "static_assertions", -] - -[[package]] -name = "ouroboros_macro" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.117", -] - [[package]] name = "outref" version = "0.5.2" @@ -5782,12 +5032,6 @@ version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" -[[package]] -name = "panic-message" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384e52fd8fbd4cbe3c317e8216260c21a0f9134de108cea8a4dd4e7e152c472d" - [[package]] name = "parking" version = "2.2.1" @@ -5844,29 +5088,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" -[[package]] -name = "pear" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467" -dependencies = [ - "inlinable_string", - "pear_codegen", - "yansi", -] - -[[package]] -name = "pear_codegen" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" -dependencies = [ - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.117", -] - [[package]] name = "pebble-agent" version = "0.1.0" @@ -5953,6 +5174,273 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "petri-attractor-steps" +version = "0.1.0" +source = "git+https://github.com/lithoscomputer/petri.git?rev=9d5171558115d94e867af01ec6d1938e0f636e12#9d5171558115d94e867af01ec6d1938e0f636e12" +dependencies = [ + "async-trait", + "globset", + "jsonschema", + "lithos-llm", + "pebble-agent", + "pebble-coding-agent", + "petri-execution", + "petri-executor", + "petri-frontend", + "petri-frontend-attractor", + "petri-ir", + "petri-runtime", + "petri-steps", + "regex", + "reqwest 0.13.4", + "serde", + "serde_json", + "shlex", + "smol_str", + "tar", + "thiserror 2.0.18", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "petri-driver" +version = "0.1.0" +source = "git+https://github.com/lithoscomputer/petri.git?rev=9d5171558115d94e867af01ec6d1938e0f636e12#9d5171558115d94e867af01ec6d1938e0f636e12" +dependencies = [ + "async-trait", + "getrandom 0.3.4", + "petri-engine", + "petri-executor", + "petri-ir", + "petri-steps", + "petri-store", + "serde", + "serde_json", + "smol_str", + "thiserror 2.0.18", + "tokio", + "tracing", +] + +[[package]] +name = "petri-engine" +version = "0.1.0" +source = "git+https://github.com/lithoscomputer/petri.git?rev=9d5171558115d94e867af01ec6d1938e0f636e12#9d5171558115d94e867af01ec6d1938e0f636e12" +dependencies = [ + "petri-ir", + "serde", + "serde_json", + "smol_str", + "thiserror 2.0.18", +] + +[[package]] +name = "petri-execution" +version = "0.1.0" +source = "git+https://github.com/lithoscomputer/petri.git?rev=9d5171558115d94e867af01ec6d1938e0f636e12#9d5171558115d94e867af01ec6d1938e0f636e12" +dependencies = [ + "async-trait", + "petri-driver", + "petri-engine", + "petri-executor", + "petri-executor-sandbox", + "petri-ir", + "petri-runtime", + "petri-steps", + "petri-store", + "regex", + "serde", + "serde_json", + "smol_str", + "thiserror 2.0.18", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "petri-executor" +version = "0.1.0" +source = "git+https://github.com/lithoscomputer/petri.git?rev=9d5171558115d94e867af01ec6d1938e0f636e12#9d5171558115d94e867af01ec6d1938e0f636e12" +dependencies = [ + "async-trait", + "libc", + "petri-ir", + "serde", + "serde_json", + "smol_str", + "thiserror 2.0.18", + "tokio", +] + +[[package]] +name = "petri-executor-sandbox" +version = "0.1.0" +source = "git+https://github.com/lithoscomputer/petri.git?rev=9d5171558115d94e867af01ec6d1938e0f636e12#9d5171558115d94e867af01ec6d1938e0f636e12" +dependencies = [ + "async-trait", + "petri-executor", + "petri-ir", + "sandbox-driver", + "sandbox-driver-daytona-config", + "sandbox-driver-docker-config", + "sandbox-driver-protocol", + "serde", + "serde_json", + "sha2 0.10.9", + "smol_str", + "thiserror 2.0.18", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "petri-frontend" +version = "0.1.0" +source = "git+https://github.com/lithoscomputer/petri.git?rev=9d5171558115d94e867af01ec6d1938e0f636e12#9d5171558115d94e867af01ec6d1938e0f636e12" +dependencies = [ + "marked-yaml", + "petri-ir", + "serde", + "serde_json", + "smol_str", + "thiserror 2.0.18", + "yaml-rust2", +] + +[[package]] +name = "petri-frontend-attractor" +version = "0.1.0" +source = "git+https://github.com/lithoscomputer/petri.git?rev=9d5171558115d94e867af01ec6d1938e0f636e12#9d5171558115d94e867af01ec6d1938e0f636e12" +dependencies = [ + "minijinja", + "petri-frontend", + "petri-ir", + "regex", + "serde", + "serde_json", + "shlex", + "smol_str", + "thiserror 2.0.18", + "toml 0.9.12+spec-1.1.0", +] + +[[package]] +name = "petri-frontend-fabro" +version = "0.1.0" +source = "git+https://github.com/lithoscomputer/petri.git?rev=9d5171558115d94e867af01ec6d1938e0f636e12#9d5171558115d94e867af01ec6d1938e0f636e12" +dependencies = [ + "petri-frontend", + "petri-frontend-attractor", + "petri-ir", + "regex", + "serde", + "serde_json", + "shlex", + "smol_str", + "toml 0.9.12+spec-1.1.0", +] + +[[package]] +name = "petri-frontend-native" +version = "0.1.0" +source = "git+https://github.com/lithoscomputer/petri.git?rev=9d5171558115d94e867af01ec6d1938e0f636e12#9d5171558115d94e867af01ec6d1938e0f636e12" +dependencies = [ + "petri-frontend", + "petri-ir", + "serde_json", + "smol_str", +] + +[[package]] +name = "petri-ir" +version = "0.1.0" +source = "git+https://github.com/lithoscomputer/petri.git?rev=9d5171558115d94e867af01ec6d1938e0f636e12#9d5171558115d94e867af01ec6d1938e0f636e12" +dependencies = [ + "regex", + "serde", + "serde_json", + "sha2 0.10.9", + "smol_str", + "thiserror 2.0.18", +] + +[[package]] +name = "petri-runtime" +version = "0.1.0" +source = "git+https://github.com/lithoscomputer/petri.git?rev=9d5171558115d94e867af01ec6d1938e0f636e12#9d5171558115d94e867af01ec6d1938e0f636e12" +dependencies = [ + "async-trait", + "petri-driver", + "petri-engine", + "petri-executor", + "petri-executor-sandbox", + "petri-frontend", + "petri-frontend-native", + "petri-ir", + "petri-steps", + "petri-store", + "serde_json", + "smol_str", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "petri-steps" +version = "0.1.0" +source = "git+https://github.com/lithoscomputer/petri.git?rev=9d5171558115d94e867af01ec6d1938e0f636e12#9d5171558115d94e867af01ec6d1938e0f636e12" +dependencies = [ + "async-trait", + "petri-executor", + "petri-ir", + "serde", + "serde_json", + "smol_str", + "thiserror 2.0.18", + "tokio", + "tracing", +] + +[[package]] +name = "petri-store" +version = "0.1.0" +source = "git+https://github.com/lithoscomputer/petri.git?rev=9d5171558115d94e867af01ec6d1938e0f636e12#9d5171558115d94e867af01ec6d1938e0f636e12" +dependencies = [ + "async-trait", + "getrandom 0.3.4", + "petri-ir", + "serde", + "serde_json", + "smol_str", + "thiserror 2.0.18", + "tokio", +] + +[[package]] +name = "petri-testkit" +version = "0.1.0" +source = "git+https://github.com/lithoscomputer/petri.git?rev=9d5171558115d94e867af01ec6d1938e0f636e12#9d5171558115d94e867af01ec6d1938e0f636e12" +dependencies = [ + "async-trait", + "petri-driver", + "petri-engine", + "petri-executor", + "petri-executor-sandbox", + "petri-ir", + "petri-steps", + "petri-store", + "sandbox-driver", + "serde", + "serde_json", + "smol_str", + "tokio", +] + [[package]] name = "pin-project" version = "1.1.11" @@ -5970,7 +5458,7 @@ checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -6070,7 +5558,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.117", + "syn", ] [[package]] @@ -6092,7 +5580,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -6104,19 +5592,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "proc-macro2-diagnostics" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", - "version_check", - "yansi", -] - [[package]] name = "process-wrap" version = "9.0.3" @@ -6163,7 +5638,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de362a0477182f45accdbad4d43cd89a95a1db0a518a7c1ddf3e525e6896f0f0" dependencies = [ - "heck 0.5.0", + "heck", "http 1.4.0", "indexmap 2.13.0", "openapiv3", @@ -6173,7 +5648,7 @@ dependencies = [ "schemars 0.8.22", "serde", "serde_json", - "syn 2.0.117", + "syn", "thiserror 2.0.18", "typify", "unicode-ident", @@ -6194,7 +5669,7 @@ dependencies = [ "serde_json", "serde_tokenstream", "serde_yaml", - "syn 2.0.117", + "syn", ] [[package]] @@ -6285,7 +5760,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -6379,24 +5854,6 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" -[[package]] -name = "rand_xoshiro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" -dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "rand_xoshiro" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" -dependencies = [ - "rand_core 0.9.5", -] - [[package]] name = "redox_syscall" version = "0.5.18" @@ -6443,7 +5900,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -6643,7 +6100,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0810a9f717d9828f475fe1f629f4c305c8464b7f496c3a854b58d29e65f4058e" dependencies = [ "async-trait", - "base64", "chrono", "futures", "http 1.4.0", @@ -6673,7 +6129,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.117", + "syn", ] [[package]] @@ -6697,7 +6153,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.117", + "syn", "walkdir", ] @@ -6712,16 +6168,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "rust_decimal" -version = "1.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ce901f9a19d251159075a4c37af514c3b8ef99c22e02dd8c19161cf397ee94a" -dependencies = [ - "arrayvec", - "num-traits", -] - [[package]] name = "rustc-demangle" version = "0.1.27" @@ -6743,15 +6189,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rusticata-macros" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" -dependencies = [ - "nom", -] - [[package]] name = "rustix" version = "1.1.4" @@ -6762,7 +6199,7 @@ dependencies = [ "errno 0.3.14", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -6821,7 +6258,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -7050,7 +6487,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.117", + "syn", ] [[package]] @@ -7062,7 +6499,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.117", + "syn", ] [[package]] @@ -7216,7 +6653,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -7227,7 +6664,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -7286,7 +6723,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -7316,7 +6753,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.117", + "syn", ] [[package]] @@ -7360,7 +6797,7 @@ dependencies = [ "darling 0.23.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -7468,7 +6905,7 @@ version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ - "errno 0.3.14", + "errno 0.2.8", "libc", ] @@ -7505,92 +6942,12 @@ dependencies = [ "time", ] -[[package]] -name = "siphasher" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" - [[package]] name = "slab" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" -[[package]] -name = "slatedb" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d945c6cd6f239873e640c5b7bb204f5638ed5681b02145cdcc2e80b2d3882b8a" -dependencies = [ - "anyhow", - "async-trait", - "atomic", - "backon", - "bitflags", - "bytemuck", - "bytes", - "chrono", - "crc32fast", - "crossbeam-skiplist", - "dotenvy", - "duration-str", - "fail-parallel", - "figment", - "flatbuffers", - "foyer", - "futures", - "log", - "object_store", - "once_cell", - "ouroboros", - "parking_lot", - "rand 0.9.4", - "rand_xoshiro 0.7.0", - "serde", - "serde_json", - "siphasher", - "slatedb-common", - "slatedb-txn-obj", - "sysinfo", - "thiserror 1.0.69", - "thread_local", - "tokio", - "tokio-util", - "tracing", - "ulid", - "url", - "uuid", - "walkdir", - "zstd", -] - -[[package]] -name = "slatedb-common" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2893ff22bb9a1013af0fb5e85380307ccd9d0a4fa8a111e187a48750e14b9a47" -dependencies = [ - "chrono", - "tokio", -] - -[[package]] -name = "slatedb-txn-obj" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c33d5597404e23b9706aa32a1723399f022f0513a289d1059df8810a282dcc4" -dependencies = [ - "async-trait", - "bytes", - "chrono", - "futures", - "log", - "object_store", - "slatedb-common", - "thiserror 1.0.69", -] - [[package]] name = "smallvec" version = "1.15.1" @@ -7600,6 +6957,16 @@ dependencies = [ "serde", ] +[[package]] +name = "smol_str" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aaa7368fcf4852a4c2dd92df0cace6a71f2091ca0a23391ce7f3a31833f1523" +dependencies = [ + "borsh", + "serde_core", +] + [[package]] name = "socket2" version = "0.6.2" @@ -7650,7 +7017,7 @@ dependencies = [ "futures-io", "futures-util", "hashbrown 0.16.1", - "hashlink", + "hashlink 0.11.1", "indexmap 2.13.0", "log", "memchr", @@ -7676,7 +7043,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.117", + "syn", ] [[package]] @@ -7688,7 +7055,7 @@ dependencies = [ "cfg-if", "dotenvy", "either", - "heck 0.5.0", + "heck", "hex", "proc-macro2", "quote", @@ -7697,7 +7064,7 @@ dependencies = [ "sha2 0.10.9", "sqlx-core", "sqlx-sqlite", - "syn 2.0.117", + "syn", "thiserror 2.0.18", "tokio", "url", @@ -7771,7 +7138,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "488e99c397a62007e4229aec669a179816339afc6d2620ca6fa420dbee2e982c" dependencies = [ "atoi", - "flume 0.12.0", + "flume", "form_urlencoded", "futures-channel", "futures-core", @@ -7836,12 +7203,6 @@ dependencies = [ "unicode-properties", ] -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strsim" version = "0.11.1" @@ -7872,10 +7233,10 @@ version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -7884,10 +7245,10 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -7917,17 +7278,6 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.117" @@ -7956,7 +7306,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -8033,7 +7383,7 @@ dependencies = [ "getrandom 0.4.1", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -8068,7 +7418,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -8113,7 +7463,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -8124,7 +7474,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -8217,7 +7567,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -8291,7 +7641,6 @@ dependencies = [ "futures-io", "futures-sink", "futures-util", - "hashbrown 0.15.5", "libc", "pin-project-lite", "tokio", @@ -8321,7 +7670,7 @@ dependencies = [ "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", - "winnow 0.7.14", + "winnow", ] [[package]] @@ -8353,7 +7702,7 @@ dependencies = [ "serde_spanned 0.6.9", "toml_datetime 0.6.11", "toml_write", - "winnow 0.7.14", + "winnow", ] [[package]] @@ -8362,7 +7711,7 @@ version = "1.0.9+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" dependencies = [ - "winnow 0.7.14", + "winnow", ] [[package]] @@ -8460,7 +7809,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -8597,15 +7946,6 @@ dependencies = [ "twin-core", ] -[[package]] -name = "twox-hash" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" -dependencies = [ - "rand 0.9.4", -] - [[package]] name = "typenum" version = "1.19.0" @@ -8628,7 +7968,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2fd0d27608a466d063d23b97cf2d26c25d838f01b4f7d5ff406a7446f16b6e3" dependencies = [ - "heck 0.5.0", + "heck", "log", "proc-macro2", "quote", @@ -8637,7 +7977,7 @@ dependencies = [ "semver", "serde", "serde_json", - "syn 2.0.117", + "syn", "thiserror 2.0.18", "unicode-ident", ] @@ -8655,7 +7995,7 @@ dependencies = [ "serde", "serde_json", "serde_tokenstream", - "syn 2.0.117", + "syn", "typify-impl", ] @@ -8666,7 +8006,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "470dbf6591da1b39d43c14523b2b469c86879a53e8b758c8e090a470fe7b1fbe" dependencies = [ "rand 0.9.4", - "serde", "web-time", ] @@ -8679,15 +8018,6 @@ dependencies = [ "libc", ] -[[package]] -name = "uncased" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" -dependencies = [ - "version_check", -] - [[package]] name = "unicase" version = "2.9.0" @@ -8987,7 +8317,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn", "wasm-bindgen-shared", ] @@ -9135,7 +8465,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -9243,7 +8573,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -9254,7 +8584,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -9585,15 +8915,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" -[[package]] -name = "winnow" -version = "0.6.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e90edd2ac1aa278a5c4599b1d89cf03074b610800f866d4026dc199d7929a28" -dependencies = [ - "memchr", -] - [[package]] name = "winnow" version = "0.7.14" @@ -9619,7 +8940,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" dependencies = [ "anyhow", - "heck 0.5.0", + "heck", "wit-parser", ] @@ -9630,10 +8951,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", - "heck 0.5.0", + "heck", "indexmap 2.13.0", "prettyplease", - "syn 2.0.117", + "syn", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -9649,7 +8970,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.117", + "syn", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -9697,23 +9018,6 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" -[[package]] -name = "x509-parser" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" -dependencies = [ - "asn1-rs", - "data-encoding", - "der-parser", - "lazy_static", - "nom", - "oid-registry", - "rusticata-macros", - "thiserror 1.0.69", - "time", -] - [[package]] name = "xattr" version = "1.6.1" @@ -9731,10 +9035,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" [[package]] -name = "yansi" -version = "1.0.1" +name = "yaml-rust2" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" +checksum = "2462ea039c445496d8793d052e13787f2b90e750b833afee748e601c17621ed9" +dependencies = [ + "arraydeque", + "encoding_rs", + "hashlink 0.10.0", +] [[package]] name = "yoke" @@ -9755,7 +9064,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", "synstructure", ] @@ -9776,7 +9085,7 @@ checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -9796,7 +9105,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", "synstructure", ] @@ -9836,7 +9145,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1dcbaff8a..75a53d55c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,8 +14,6 @@ version = "0.362.0-nightly.0" license = "MIT" [workspace.dependencies] -agent-client-protocol = { version = "0.11.1", features = ["unstable_session_usage"] } -agent-client-protocol-tokio = "0.11.1" anyhow = "1" axum = { version = "0.8" } axum-extra = { version = "0.10", features = ["cookie-private", "query"] } @@ -39,22 +37,6 @@ fs2 = "0.4" base64 = "0.22" bytes = "1" tokio-util = "0.7" -# AWS building blocks for the native Bedrock adapter. Lean stack: request -# signing + credential chain + event-stream decode only. Transport for the -# actual Bedrock inference calls stays on fabro-http; the full -# aws-sdk-bedrockruntime (and its parallel hyper stack) is not pulled in. -# aws-config keeps its DEFAULT features on purpose: `rt-tokio` supplies the -# TokioSleep impl the credential chain's retry requires (without it, -# resolving the default chain panics with "an async sleep implementation is -# required"), and `sso`/`credentials-process` make from_default_chain's -# documented SSO/credential-process support real. `rustls` pins the TLS -# backend for credential-resolution HTTP. -aws-config = { version = "1", features = ["behavior-version-latest", "rustls"] } -aws-credential-types = { version = "1", features = ["hardcoded-credentials"] } -aws-sigv4 = "1" -aws-smithy-eventstream = "0.60" -aws-smithy-runtime-api = "1" -aws-smithy-types = "1" clap = { version = "4", features = ["derive", "env"] } clap_complete = "4" jsonschema = { version = "0.42", default-features = false } @@ -130,10 +112,22 @@ sandbox-driver-testing = { git = "https://github.com/lithoscomputer/sandbox-driv pebble-agent = { git = "https://github.com/lithoscomputer/pebble", rev = "67c9f486dd28f15c04e8d590a91e6f5563f7605d" } pebble-coding-agent = { git = "https://github.com/lithoscomputer/pebble", rev = "67c9f486dd28f15c04e8d590a91e6f5563f7605d", features = ["mcp", "search-providers"] } pebble-cli-core = { git = "https://github.com/lithoscomputer/pebble", rev = "67c9f486dd28f15c04e8d590a91e6f5563f7605d" } +# petri: the workflow engine Fabro runs its workflows on. Pinned by rev, the +# same way pebble and sandbox-driver are. Petri pins the same pebble, +# lithos-llm and sandbox-driver revisions as this file, so the workspace links +# one copy of each. Only `fabro-petri` and `fabro-dot` (the DOT parser alone) +# may depend on these packages; the keys carry the `petri_` prefix so the crate +# names say where they come from. +petri_runtime = { git = "https://github.com/lithoscomputer/petri.git", rev = "9d5171558115d94e867af01ec6d1938e0f636e12", package = "petri-runtime" } +petri_execution = { git = "https://github.com/lithoscomputer/petri.git", rev = "9d5171558115d94e867af01ec6d1938e0f636e12", package = "petri-execution" } +petri_store = { git = "https://github.com/lithoscomputer/petri.git", rev = "9d5171558115d94e867af01ec6d1938e0f636e12", package = "petri-store" } +petri_attractor_steps = { git = "https://github.com/lithoscomputer/petri.git", rev = "9d5171558115d94e867af01ec6d1938e0f636e12", package = "petri-attractor-steps" } +petri_frontend_attractor = { git = "https://github.com/lithoscomputer/petri.git", rev = "9d5171558115d94e867af01ec6d1938e0f636e12", package = "petri-frontend-attractor" } +petri_frontend_fabro = { git = "https://github.com/lithoscomputer/petri.git", rev = "9d5171558115d94e867af01ec6d1938e0f636e12", package = "petri-frontend-fabro" } +petri_testkit = { git = "https://github.com/lithoscomputer/petri.git", rev = "9d5171558115d94e867af01ec6d1938e0f636e12", package = "petri-testkit" } sentry = { version = "0.35", default-features = false, features = ["backtrace", "contexts", "ureq", "rustls"] } fork = "0.2" exec = "0.3" -slatedb = { version = "0.11.2", features = ["zstd"] } object_store = { version = "0.12.5", features = ["aws"] } rust-embed = "8" percent-encoding = "2" diff --git a/apps/fabro-web/app/components/event-debug-helpers.tsx b/apps/fabro-web/app/components/event-debug-helpers.tsx index 1a55035bd..c32fc1d61 100644 --- a/apps/fabro-web/app/components/event-debug-helpers.tsx +++ b/apps/fabro-web/app/components/event-debug-helpers.tsx @@ -5,7 +5,9 @@ export type DebugCategory = | "command" | "lifecycle" | "human" - | "system"; + | "system" + | "petri" + | "platform"; export const DEBUG_CATEGORIES: readonly DebugCategory[] = [ "agent", @@ -13,6 +15,8 @@ export const DEBUG_CATEGORIES: readonly DebugCategory[] = [ "lifecycle", "human", "system", + "petri", + "platform", ] as const; const PREFIX_TO_CATEGORY: Record = { @@ -34,6 +38,8 @@ const CATEGORY_LABEL: Record = { lifecycle: "Lifecycle", human: "Human", system: "System", + petri: "Petri", + platform: "Platform", }; const CATEGORY_TONE: Record = { @@ -42,6 +48,8 @@ const CATEGORY_TONE: Record = { lifecycle: "bg-amber/15 text-amber", human: "bg-coral/15 text-coral", system: "bg-overlay-strong text-fg-3", + petri: "bg-teal-500/15 text-teal-500", + platform: "bg-amber/15 text-amber", }; const CATEGORY_COLOR: Record = { @@ -50,6 +58,8 @@ const CATEGORY_COLOR: Record = { lifecycle: "var(--color-amber)", human: "var(--color-coral)", system: "var(--color-ice-300)", + petri: "var(--color-teal-500)", + platform: "var(--color-amber)", }; export function debugCategory(eventName: string | null | undefined): DebugCategory { diff --git a/apps/fabro-web/app/components/event-debug.tsx b/apps/fabro-web/app/components/event-debug.tsx index b50ced2f9..d563bb1c2 100644 --- a/apps/fabro-web/app/components/event-debug.tsx +++ b/apps/fabro-web/app/components/event-debug.tsx @@ -12,12 +12,10 @@ import { FunnelIcon, MagnifyingGlassIcon, } from "@heroicons/react/16/solid"; -import type { EventEnvelope } from "@qltysh/fabro-api-client"; import { Tooltip } from "./ui"; import { formatAbsoluteTs } from "../lib/format"; import { - debugCategory, debugCategoryColor, debugCategoryLabel, debugCategoryTone, @@ -28,19 +26,35 @@ import { import { FloatingTooltip } from "./floating-tooltip"; import { useWindowEvent } from "../hooks/effects"; +/** + * What a debug row needs of a run stream item, as `debugRowsFromStream` + * shapes it: the `stream_seq`, the item's name, when it was recorded, and + * its category (`petri` or `platform`). + */ +export interface DebugRowLike { + seq: number; + event?: string | null; + ts: string; + category: DebugCategory; +} + +export function debugRowCategory(row: DebugRowLike): DebugCategory { + return row.category; +} + export function DebugEventRow({ event, runStart, selected, onSelect, }: { - event: EventEnvelope; + event: DebugRowLike; runStart: string | undefined; selected: boolean; onSelect: () => void; }) { const eventName = event.event ?? ""; - const category = debugCategory(eventName); + const category = debugRowCategory(event); return ( )} - {showRetry && ( - - - - )} {showArchive && (