Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ hyper = { version = "1", features = ["client", "http1"] }
hyper-util = { version = "0.1", features = ["client-legacy", "http1", "tokio"] }
parking_lot = "0.12"
rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"] }
rustscript-vm = { package = "pd-vm", git = "https://github.com/rustscript-lang/rustscript.git", rev = "d9387f98df78dd88d2d1c04eebac4415f844efaf", default-features = false, features = ["runtime", "http-client", "sqlite"] }
pd-host-function = { git = "https://github.com/rustscript-lang/rustscript.git", rev = "d9387f98df78dd88d2d1c04eebac4415f844efaf" }
rustscript-vm = { package = "pd-vm", git = "https://github.com/rustscript-lang/rustscript.git", rev = "b5066dd92fcd7c07df57e3ec2c29dbcf8c19c390", default-features = false, features = ["runtime", "http-client", "sqlite"] }
pd-host-function = { git = "https://github.com/rustscript-lang/rustscript.git", rev = "b5066dd92fcd7c07df57e3ec2c29dbcf8c19c390" }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_yaml = "0.9"
semver = "1.0.28"
yaml-rust2 = { version = "0.12", default-features = false }
# Meta-schema validation only; resolver features stay disabled.
jsonschema = { version = "0.52.1", default-features = false }
Expand All @@ -51,6 +52,8 @@ tracing-core = "0.1"
[features]
default = []
config-fixture = []
# Test-only one-shot simulated I/O faults. Unarmed production builds do not include it.
workspace-io-fault = []

# Optimize the embedded compiler while retaining development checks.
[profile.dev.package.pd-vm]
Expand Down
40 changes: 40 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,36 @@ the library's `state.db` path, but the gateway's SQLite selection remains
separate: `RUSTSCRIPT_AGENT_STATE_DB` chooses the gateway state file and an
unset value keeps gateway state in memory.

### Managed workspace (primary-only)

`RUSTSCRIPT_AGENT_MANAGED_WORKSPACE` is an OS filesystem path, read only by
`rustscript-agent-gateway` and passed to `ManagedWorkspaceConfig::for_workspace`.
It has **no deprecated alias** and is not a boolean flag. Unset means
`managed_workspace = None` (direct mode). When set, it must name an existing,
non-root directory using a non-empty absolute UTF-8 path with no NUL or
parent-directory components; invalid configuration fails startup.

Managed mode requires `RUSTSCRIPT_AGENT_STATE_DB` to name an **absolute,
persistent database**; in-memory state is rejected. The runtime derives its
private object root as `<database-parent>/.<database-filename>.effects`.
The source must not overlap the database, that object root, or the sibling
`.<database-filename>.tool-packages` directory in either direction.

The setting alone grants no workspace authority. Import and queries require a
current Native workspace grant admitting the configured source through
`workspaces.allowed_roots`. For the gateway binary, explicitly set
`RUSTSCRIPT_AGENT_HOME` to enable the workspace host, with loadable config/auth
files in a private, process-owned agent home (Unix mode `0700`). A managed run's
admitted canonical workspace must match the configured source. Embeddings
supply this authority through `with_workspace_home` or their trusted workspace
host factory.

The source is imported as a seed; managed filesystem mutations use private
working trees without writing changes back to the source. This mechanism
covers managed synchronous local filesystem effects, not OS permission
isolation or rollback of external effects. Tree quotas and retained-object
limits are described with the native field below.

### Gateway variables and deprecated aliases

Every gateway `RUSTSCRIPT_AGENT_*` variable in the table has a deprecated
Expand Down Expand Up @@ -184,6 +214,16 @@ above; every other field is set by embedding code.
| `sqlite` | `SqlitePolicy` | core defaults, `max_statements = 1024` | — |
| `approvals` | `ApprovalSettings` | `read = "allow"`, `write = "ask"`, `process = "ask"`; reviewer/model/fallback/required overrides unset (`None`) | Validated by `ApprovalSettings::validate`: `reviewer` must be `guardian` or `user` when set; `reviewer_model` must be non-empty, at most 128 characters, with no control characters or surrounding whitespace; `read = "ask"` is unsupported. |
| `fuel` | `Option<u64>` | `Some(10_000_000)` | VM fuel budget; `None` disables the fuel cap. |
| `managed_workspace` | `Option<ManagedWorkspaceConfig>` | `None` (direct mode) | Trusted native startup opt-in for persistent synchronous managed effects. `ManagedWorkspaceConfig::for_workspace(source_root)` supplies default quotas and validates the source; `AgentGatewayConfig::validate` revalidates it. Gateway construction requires an absolute persistent database, and the runtime rejects a root source or overlap with persistent state. Import and queries still require current Native workspace authority; see the primary-only environment setting above. |

`ManagedWorkspaceConfig` contains `source_root: PathBuf`, `quota: ResourceQuota`,
and `retention: ManagedRetentionLimits`. `for_workspace` defaults to at most
1 000 000 tree entries, 64 MiB per tree, and depth 32. Native embeddings may
choose smaller positive bounds through `ResourceQuota::new`; these defaults
are also its hard ceilings. Retention defaults to 128 objects and 512 MiB;
both bounds must be positive and cannot exceed those ceilings. Retained
evidence is not evicted to admit a call. These are native configuration
fields, not additional environment variables or `config.yaml` settings.

`RateLimitConfig` bounds: `enabled` (master switch), `ip_burst`, `account_burst`,
`window`, `max_buckets`. `TelegramConfig` bounds: `bot_token` (redacted in
Expand Down
6 changes: 3 additions & 3 deletions docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ treated as available.
## 1. Delivery constraint: the core dependency is not released

`rustscript-agent` depends on the RustScript VM through a **pinned Git
dependency**: `rustscript-vm = { package = "pd-vm", git = "https://github.com/rustscript-lang/rustscript.git", rev = "d9387f98df78dd88d2d1c04eebac4415f844efaf", ... }` in `Cargo.toml`.
dependency**: `rustscript-vm = { package = "pd-vm", git = "https://github.com/rustscript-lang/rustscript.git", rev = "b5066dd92fcd7c07df57e3ec2c29dbcf8c19c390", ... }` in `Cargo.toml`.
Consequences, stated plainly:

- A build fetches the exact pinned core revision from the canonical HTTPS
Expand All @@ -18,7 +18,7 @@ Consequences, stated plainly:
- `cargo build/test --locked` resolves the core source from `Cargo.lock`,
which records the canonical git source for both `pd-vm` and
`pd-host-function`:
`git+https://github.com/rustscript-lang/rustscript.git?rev=d9387f98df78dd88d2d1c04eebac4415f844efaf#d9387f98df78dd88d2d1c04eebac4415f844efaf`.
`git+https://github.com/rustscript-lang/rustscript.git?rev=b5066dd92fcd7c07df57e3ec2c29dbcf8c19c390#b5066dd92fcd7c07df57e3ec2c29dbcf8c19c390`.
A build therefore needs network access to github.com (or a pre-warmed
Cargo git cache); it never reads the state of a local core checkout.
- **There is no crates.io release of this crate, and none can be made until
Expand Down Expand Up @@ -46,7 +46,7 @@ before deploying:
```bash
# The lockfile records the exact git source for pd-vm and pd-host-function:
grep -A3 'name = "pd-vm"' Cargo.lock
# source = "git+https://github.com/rustscript-lang/rustscript.git?rev=d9387f9…#d9387f9…"
# source = "git+https://github.com/rustscript-lang/rustscript.git?rev=b5066dd…#b5066dd…"
# The resolved dependency graph shows the same source:
cargo tree --locked -p rustscript-vm
```
Expand Down
33 changes: 33 additions & 0 deletions examples/plugin_schema_sync.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//! Regenerate or check canonical JSON projections of the public YAML schemas.
//!
//! The YAML files are the contract. This tool does not invent a second schema
//! and does not fetch anything. `--check` fails if `schemas/canonical` drifted.

fn main() {
let command = std::env::args()
.nth(1)
.unwrap_or_else(|| "--check".to_string());
let dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("schemas/canonical");
match command.as_str() {
"--check" => match rustscript_agent::plugins::schema_snapshot_drift(&dir) {
Ok(()) => println!("schema snapshots match {}", dir.display()),
Err(err) => {
eprintln!("{err}");
std::process::exit(1);
}
},
"--write" => {
let docs =
rustscript_agent::plugins::canonical_schema_documents().expect("bundled schemas");
std::fs::create_dir_all(&dir).expect("canonical dir");
for (name, json) in docs {
std::fs::write(dir.join(name), json).expect(name);
}
println!("wrote {}", dir.display());
}
_ => {
eprintln!("usage: plugin_schema_sync --check|--write");
std::process::exit(2);
}
}
}
Loading
Loading