Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
81 changes: 0 additions & 81 deletions .github/workflows/content.yml

This file was deleted.

4 changes: 0 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ RUN apk add --no-cache ca-certificates tini util-linux git openssh-client \
&& mkdir -p /data

COPY --chown=65532:65532 dist ./dist
COPY --chown=65532:65532 templates ./templates
COPY --chown=65532:65532 docs ./docs
COPY --chown=65532:65532 docker-entrypoint.sh ./docker-entrypoint.sh

RUN chmod 0755 /app/docker-entrypoint.sh \
Expand All @@ -30,5 +28,3 @@ CMD ["manager"]
FROM agent-runtime AS agent-runner
ENV TREESEED_PROVIDER_ROLE=runner
CMD ["runner"]

FROM agent-runner AS railway-runtime
138 changes: 32 additions & 106 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,132 +1,58 @@
# @treeseed/agent

`@treeseed/agent` runs Treeseed capacity providers. It provides the provider manager, provider runner, AgentKernel execution, mode scheduling, provider-local capacity enforcement, package-owned Docker/Compose assets, and deployment templates.
`@treeseed/agent` is the outbound-only capacity-provider and assignment-execution package for TreeSeed.

Use this package when your organization needs to run or maintain capacity that executes Treeseed work. Ordinary hosted projects can consume assigned capacity without owning a provider runtime.
The API owns scheduling, workdays, capacity plans, assignments, leases, authorization, and settlement. The SDK owns portable wire contracts and the catalog-driven remote client. Agent owns only provider identity/custody, availability publication, provider-local admission, trusted execution, recovery, usage, and terminal evidence.

## What You Can Run With Agent
## Runtime roles

- provider manager and provider runner roles
- AgentKernel planning/acting mode execution
- local provider diagnostics
- provider containers and compose workflows
- runtime tests for capacity scheduling and provider lifecycle
- provider manager reconciles repository-governed connections and publishes observed capacity;
- provider runner accepts an API-issued lease and invokes one trusted executor.

## Install
The package does not host a control-plane API, persist control-plane resources, synthesize project work, expose a public Agent CLI, or construct raw API paths.

```bash
npm install @treeseed/agent @treeseed/sdk
```

For package development:
## Development

```bash
npm install
npm run build
npm test
npm run verify:local
npm ci
npm run build:dist
npm run test:modern
npm run release:verify
```

## Operate A Capacity Provider
Only focused tests for the current provider boundary are retained. Tests for the removed embedded API, local Agent SDK, content runtime, and legacy provider implementations were deleted with those implementations.

Use the CLI for provider lifecycle:
## Provider profile

```bash
trsd capacity build
trsd capacity up
trsd capacity status
trsd capacity logs
trsd capacity down
trsd capacity test-local
```
Provider connections declare `serverProfile`, `controlPlaneUrl`, and `controlPlaneAudience`. Local Compose uses:

The package-owned role images are:

```text
treeseed/agent-manager
treeseed/agent-runner
```
- `TREESEED_SERVER_PROFILE_LOCAL_URL`;
- `TREESEED_SERVER_PROFILE_LOCAL_AUDIENCE`;
- `TREESEED_CAPACITY_PROVIDER_MANIFEST`;
- `TREESEED_PROVIDER_DATA_DIR`.

Production release images are published for `linux/amd64` and `linux/arm64`. Staging builds the provider services from source at an exact commit. The images start:

```bash
node ./dist/provider/lifecycle/entrypoint.js manager
node ./dist/provider/lifecycle/entrypoint.js runner
node ./dist/provider/lifecycle/entrypoint.js doctor
```

Use the qualified role names provider manager and provider runner in architecture and implementation docs. The provider manager supervises one provider's local runtime; API-side assignment selection lives in `@treeseed/api`.

Store provider credentials through `trsd config` or host secret managers. Do not create plaintext provider `.env` files.

Advanced launch configuration can be declared in `treeseed.capacity-provider.yaml` and passed to `trsd capacity up --config treeseed.capacity-provider.yaml`. The manifest can select official role images or derived images built from `treeseed/agent-manager` and `treeseed/agent-runner`. Secrets belong in encrypted Treeseed config or host secret managers, not in the manifest.

See [Capacity Provider Runtime](./docs/capacity-provider-runtime.md) for the provider check-in, assignment lease, TreeDX proxy, and mode-run protocol.

## How Agent Fits With Other Packages

- `@treeseed/admin` may display and manage capacity-provider configuration, status, and diagnostics.
- `@treeseed/ui` owns reusable capacity/status components.
- `@treeseed/api` owns backend control-plane routes, operation state, provider-authenticated API behavior, provider availability sessions, assignment leases, mode-run persistence, and capacity ledger settlement.
- `@treeseed/sdk` owns shared provider contracts, portable capacity/assignment types, config, and reconciliation primitives.
- `@treeseed/cli` owns the operator command surface for provider lifecycle.
- root market hosts the admin UI and future marketplace/business overlays.

Agent runtime must stay external to the root web app and API process.

## Common Commands

Source entrypoints:

```bash
node --import tsx ./src/provider/lifecycle/entrypoint.ts doctor --json
node --import tsx ./src/provider/lifecycle/entrypoint.ts manager --once --json
node --import tsx ./src/provider/lifecycle/entrypoint.ts runner --once --json
```

Built entrypoints:
Model/runtime implementation is injected through a trusted `TREESEED_AGENT_EXECUTOR_MODULE`. If it is absent or unhealthy, the manager advertises no executable capacity and the runner does not request assignments.

```bash
node ./dist/provider/lifecycle/entrypoint.js doctor --json
node ./dist/provider/lifecycle/entrypoint.js manager --once --json
node ./dist/provider/lifecycle/entrypoint.js runner --once --json
node ./dist/provider/lifecycle/entrypoint.js manager --plan --json
node ./dist/provider/lifecycle/entrypoint.js runner --plan --json
```

Verification:

```bash
npm run build:dist
npm run test:unit
npm run test:smoke
npm run release:verify
npm run verify:local
```

CI runs `.github/workflows/verify.yml`. Capacity-provider image publication uses `.github/workflows/publish.yml` for tagged production releases; staging deployments build from source through Railway reconciliation.

## Environment Registry

`src/env.yaml` is the package-owned provider/runtime environment registry. It contains provider manager, provider runner, capacity-provider, and provider-launch entries. Workday budgets and scheduling policy are durable API control-plane records governed by active team allocation sets, not provider-runtime environment variables.

Provider-neutral shared entries belong in `@treeseed/sdk`. Web/forms/Astro entries belong in `@treeseed/core`. Admin UI expectations belong in `@treeseed/admin`. Backend control-plane entries belong in `@treeseed/api`.

## Public Surfaces
See [Capacity Provider Runtime](./docs/capacity-provider-runtime.md) for the lifecycle and recovery contract.

Exports include runtime APIs, service helpers, contracts, and binaries needed by provider deployments and package tests. Prefer SDK-owned contracts for shared model types so root market and admin code do not import agent runtime internals.
## Public package surface

Published binaries:
- `@treeseed/agent`: executor contracts and the catalog-driven assignment runner;
- `@treeseed/agent/provider-governance`: provider identity, connection, manifest, and secret-reference governance.

- `treeseed-agents`
Container entrypoints are private runtime surfaces. The package installs no executable.

## What Agent Does Not Own
## Non-ownership

- root market web app
- admin routes or UI pages
- reusable UI components
- backend PostgreSQL adapter, API routes, migrations, or operations runner
- SDK reconciliation engine
- CLI command parsing
- TreeDX repository service internals
- ecommerce, billing, licensing, or marketplace policy
Agent does not own:

See the root [Package Ownership](../../docs/package-ownership.md) guide for cross-package boundaries.
- REST, OAuth, OpenAPI, MCP, persistence, or policy;
- CLI command parsing or repository integration workflow;
- TreeDX service semantics or content persistence;
- GitHub, billing, commerce, deployment, or marketplace policy.
98 changes: 11 additions & 87 deletions compose.capacity-provider.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,55 +7,23 @@ services:
target: agent-manager
command: ["manager"]
restart: unless-stopped
ulimits:
core:
soft: 0
hard: 0
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
TREESEED_PROVIDER_ROLE: manager
TREESEED_PROVIDER_STARTUP_MODE: ${TREESEED_PROVIDER_STARTUP_MODE:-live}
extra_hosts: ["host.docker.internal:host-gateway"]
environment: &provider-environment
TREESEED_CAPACITY_PROVIDER_MANIFEST: /config/treeseed.capacity-provider.yaml
TREESEED_PROVIDER_DATA_DIR: /data
TREESEED_PROVIDER_CHOWN_DATA: ${TREESEED_PROVIDER_CHOWN_DATA:-1}
TREESEED_PROVIDER_UID: ${TREESEED_PROVIDER_CONTAINER_UID:-65532}
TREESEED_PROVIDER_GID: ${TREESEED_PROVIDER_CONTAINER_GID:-65532}
TREESEED_PROVIDER_ENVIRONMENT: ${TREESEED_PROVIDER_ENVIRONMENT:-local}
TREESEED_PROVIDER_CLASS: ${TREESEED_PROVIDER_CLASS:-agent}
TREESEED_PROVIDER_SOURCE_CLOSURE_DIGEST: ${TREESEED_PROVIDER_SOURCE_CLOSURE_DIGEST:-}
TREESEED_MARKET_PROFILE_LOCAL_URL: ${TREESEED_MARKET_PROFILE_LOCAL_URL:-http://host.docker.internal:3000}
TREESEED_MARKET_PROFILE_LOCAL_AUDIENCE: ${TREESEED_MARKET_PROFILE_LOCAL_AUDIENCE:-http://127.0.0.1:3000}
TREESEED_PROVIDER_CAPABILITIES_FILE: ${TREESEED_PROVIDER_CAPABILITIES_FILE:-}
TREESEED_PROVIDER_BUDGET_FILE: ${TREESEED_PROVIDER_BUDGET_FILE:-}
TREESEED_PROVIDER_MAX_CONCURRENT_WORKDAYS: ${TREESEED_PROVIDER_MAX_CONCURRENT_WORKDAYS:-}
TREESEED_PROVIDER_MAX_CONCURRENT_RUNNERS: ${TREESEED_PROVIDER_MAX_CONCURRENT_RUNNERS:-}
TREESEED_SERVER_PROFILE_LOCAL_URL: ${TREESEED_SERVER_PROFILE_LOCAL_URL:-http://host.docker.internal:3002}
TREESEED_SERVER_PROFILE_LOCAL_AUDIENCE: ${TREESEED_SERVER_PROFILE_LOCAL_AUDIENCE:-http://127.0.0.1:3002}
TREESEED_AGENT_EXECUTOR_MODULE: ${TREESEED_AGENT_EXECUTOR_MODULE:-}
TREESEED_PROVIDER_MAX_CONCURRENT_WORKDAYS: ${TREESEED_PROVIDER_MAX_CONCURRENT_WORKDAYS:-1}
TREESEED_PROVIDER_MAX_CONCURRENT_RUNNERS: ${TREESEED_PROVIDER_MAX_CONCURRENT_RUNNERS:-1}
TREESEED_PROVIDER_DAILY_AGENT_SECONDS_LIMIT: ${TREESEED_PROVIDER_DAILY_AGENT_SECONDS_LIMIT:-}
TREESEED_PROVIDER_MONTHLY_AGENT_SECONDS_LIMIT: ${TREESEED_PROVIDER_MONTHLY_AGENT_SECONDS_LIMIT:-}
TREESEED_MIN_FREE_DISK_BYTES: ${TREESEED_MIN_FREE_DISK_BYTES:-}
TREESEED_PROVIDER_MIN_FREE_DISK_BYTES: ${TREESEED_PROVIDER_MIN_FREE_DISK_BYTES:-}
TREESEED_PROVIDER_ASSIGNMENT_DISK_HEADROOM_BYTES: ${TREESEED_PROVIDER_ASSIGNMENT_DISK_HEADROOM_BYTES:-}
TREESEED_CODEX_AUTH_FILE: ${TREESEED_CODEX_AUTH_FILE:-}
TREESEED_CODEX_API_KEY: ${TREESEED_CODEX_API_KEY:-}
TREESEED_AI_GATEWAY_TOKEN: ${TREESEED_AI_GATEWAY_TOKEN:-}
TREESEED_CODEX_AUTH_JSON_B64: ${TREESEED_CODEX_AUTH_JSON_B64:-}
TREESEED_CODEX_AUTH_OVERWRITE: ${TREESEED_CODEX_AUTH_OVERWRITE:-}
TREESEED_CODEX_TIMEOUT_MS: ${TREESEED_CODEX_TIMEOUT_MS:-900000}
TREESEED_OPENCODE_SERVER_URL: ${TREESEED_OPENCODE_SERVER_URL:-}
TREESEED_OPENCODE_AUTH_FILE: ${TREESEED_OPENCODE_AUTH_FILE:-}
TREESEED_OPENCODE_SERVER_USERNAME: ${TREESEED_OPENCODE_SERVER_USERNAME:-}
TREESEED_OPENCODE_SERVER_PASSWORD: ${TREESEED_OPENCODE_SERVER_PASSWORD:-}
TREESEED_OPENROUTER_API_KEY: ${TREESEED_OPENROUTER_API_KEY:-}
TREESEED_GITHUB_COPILOT_TOKEN: ${TREESEED_GITHUB_COPILOT_TOKEN:-}
TREESEED_CLOUDFLARE_API_TOKEN: ${TREESEED_CLOUDFLARE_API_TOKEN:-}
TREESEED_CLOUDFLARE_ACCOUNT_ID: ${TREESEED_CLOUDFLARE_ACCOUNT_ID:-}
TREESEED_CONTENT_BUCKET_NAME: ${TREESEED_CONTENT_BUCKET_NAME:-}
TREESEED_GITHUB_TOKEN: ${TREESEED_GITHUB_TOKEN:-}
volumes:
volumes: &provider-volumes
- "${TREESEED_PROVIDER_HOST_DATA_DIR:-.treeseed/local-capacity-providers/agent-standalone}:/data"
- "${TREESEED_CAPACITY_PROVIDER_MANIFEST:-./treeseed.capacity-provider.yaml}:/config/treeseed.capacity-provider.yaml:ro"
- "${TREESEED_HOST_CODEX_AUTH_FILE:-/dev/null}:/run/treeseed-secrets/codex-auth.json:ro"

runner:
image: ${TREESEED_AGENT_RUNNER_IMAGE:-treeseed/agent-runner:${TREESEED_AGENT_IMAGE_TAG:-local}}
build:
Expand All @@ -64,51 +32,7 @@ services:
target: agent-runner
command: ["runner"]
restart: unless-stopped
ulimits:
core:
soft: 0
hard: 0
extra_hosts:
- "host.docker.internal:host-gateway"
extra_hosts: ["host.docker.internal:host-gateway"]
environment:
TREESEED_PROVIDER_ROLE: runner
TREESEED_PROVIDER_STARTUP_MODE: ${TREESEED_PROVIDER_STARTUP_MODE:-live}
TREESEED_CAPACITY_PROVIDER_MANIFEST: /config/treeseed.capacity-provider.yaml
TREESEED_PROVIDER_DATA_DIR: /data
TREESEED_PROVIDER_CHOWN_DATA: ${TREESEED_PROVIDER_CHOWN_DATA:-1}
TREESEED_PROVIDER_UID: ${TREESEED_PROVIDER_CONTAINER_UID:-65532}
TREESEED_PROVIDER_GID: ${TREESEED_PROVIDER_CONTAINER_GID:-65532}
TREESEED_PROVIDER_ENVIRONMENT: ${TREESEED_PROVIDER_ENVIRONMENT:-local}
TREESEED_PROVIDER_CLASS: ${TREESEED_PROVIDER_CLASS:-agent}
TREESEED_PROVIDER_SOURCE_CLOSURE_DIGEST: ${TREESEED_PROVIDER_SOURCE_CLOSURE_DIGEST:-}
TREESEED_MARKET_PROFILE_LOCAL_URL: ${TREESEED_MARKET_PROFILE_LOCAL_URL:-http://host.docker.internal:3000}
TREESEED_MARKET_PROFILE_LOCAL_AUDIENCE: ${TREESEED_MARKET_PROFILE_LOCAL_AUDIENCE:-http://127.0.0.1:3000}
TREESEED_PROVIDER_CAPABILITIES_FILE: ${TREESEED_PROVIDER_CAPABILITIES_FILE:-}
TREESEED_PROVIDER_BUDGET_FILE: ${TREESEED_PROVIDER_BUDGET_FILE:-}
TREESEED_PROVIDER_MAX_CONCURRENT_WORKDAYS: ${TREESEED_PROVIDER_MAX_CONCURRENT_WORKDAYS:-}
TREESEED_PROVIDER_MAX_CONCURRENT_RUNNERS: ${TREESEED_PROVIDER_MAX_CONCURRENT_RUNNERS:-}
TREESEED_PROVIDER_DAILY_AGENT_SECONDS_LIMIT: ${TREESEED_PROVIDER_DAILY_AGENT_SECONDS_LIMIT:-}
TREESEED_PROVIDER_MONTHLY_AGENT_SECONDS_LIMIT: ${TREESEED_PROVIDER_MONTHLY_AGENT_SECONDS_LIMIT:-}
TREESEED_MIN_FREE_DISK_BYTES: ${TREESEED_MIN_FREE_DISK_BYTES:-}
TREESEED_PROVIDER_MIN_FREE_DISK_BYTES: ${TREESEED_PROVIDER_MIN_FREE_DISK_BYTES:-}
TREESEED_PROVIDER_ASSIGNMENT_DISK_HEADROOM_BYTES: ${TREESEED_PROVIDER_ASSIGNMENT_DISK_HEADROOM_BYTES:-}
TREESEED_CODEX_AUTH_FILE: ${TREESEED_CODEX_AUTH_FILE:-}
TREESEED_CODEX_API_KEY: ${TREESEED_CODEX_API_KEY:-}
TREESEED_AI_GATEWAY_TOKEN: ${TREESEED_AI_GATEWAY_TOKEN:-}
TREESEED_CODEX_AUTH_JSON_B64: ${TREESEED_CODEX_AUTH_JSON_B64:-}
TREESEED_CODEX_AUTH_OVERWRITE: ${TREESEED_CODEX_AUTH_OVERWRITE:-}
TREESEED_CODEX_TIMEOUT_MS: ${TREESEED_CODEX_TIMEOUT_MS:-900000}
TREESEED_OPENCODE_SERVER_URL: ${TREESEED_OPENCODE_SERVER_URL:-}
TREESEED_OPENCODE_AUTH_FILE: ${TREESEED_OPENCODE_AUTH_FILE:-}
TREESEED_OPENCODE_SERVER_USERNAME: ${TREESEED_OPENCODE_SERVER_USERNAME:-}
TREESEED_OPENCODE_SERVER_PASSWORD: ${TREESEED_OPENCODE_SERVER_PASSWORD:-}
TREESEED_OPENROUTER_API_KEY: ${TREESEED_OPENROUTER_API_KEY:-}
TREESEED_GITHUB_COPILOT_TOKEN: ${TREESEED_GITHUB_COPILOT_TOKEN:-}
TREESEED_CLOUDFLARE_API_TOKEN: ${TREESEED_CLOUDFLARE_API_TOKEN:-}
TREESEED_CLOUDFLARE_ACCOUNT_ID: ${TREESEED_CLOUDFLARE_ACCOUNT_ID:-}
TREESEED_CONTENT_BUCKET_NAME: ${TREESEED_CONTENT_BUCKET_NAME:-}
TREESEED_GITHUB_TOKEN: ${TREESEED_GITHUB_TOKEN:-}
volumes:
- "${TREESEED_PROVIDER_HOST_DATA_DIR:-.treeseed/local-capacity-providers/agent-standalone}:/data"
- "${TREESEED_CAPACITY_PROVIDER_MANIFEST:-./treeseed.capacity-provider.yaml}:/config/treeseed.capacity-provider.yaml:ro"
- "${TREESEED_HOST_CODEX_AUTH_FILE:-/dev/null}:/run/treeseed-secrets/codex-auth.json:ro"
<<: *provider-environment
volumes: *provider-volumes
Loading
Loading