mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-17 06:04:56 +00:00
feat: refresh web console theme
This commit is contained in:
parent
0fbf6272b1
commit
1fcae6ed76
34 changed files with 5037 additions and 748 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -13,6 +13,7 @@ yarn.lock
|
||||||
# Cache
|
# Cache
|
||||||
.cache/
|
.cache/
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
|
.turbo/
|
||||||
|
|
||||||
# Environment
|
# Environment
|
||||||
.env
|
.env
|
||||||
|
|
|
||||||
12
README.md
12
README.md
|
|
@ -11,5 +11,15 @@ Documentation lives in `docs/` (Mintlify). Start with:
|
||||||
Quickstart (local dev):
|
Quickstart (local dev):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sandbox-agent --token "$SANDBOX_TOKEN" --host 127.0.0.1 --port 8787
|
sandbox-agent --token "$SANDBOX_TOKEN" --host 127.0.0.1 --port 2468
|
||||||
|
```
|
||||||
|
|
||||||
|
Extract API keys from local agent configs (Claude Code, Codex, OpenCode, Amp):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Print env vars
|
||||||
|
sandbox-agent credentials extract-env
|
||||||
|
|
||||||
|
# Export to current shell
|
||||||
|
eval "$(sandbox-agent credentials extract-env --export)"
|
||||||
```
|
```
|
||||||
|
|
|
||||||
22
docs/cli.mdx
22
docs/cli.mdx
|
|
@ -8,7 +8,7 @@ The `sandbox-agent` CLI mirrors the HTTP API so you can script everything withou
|
||||||
## Server flags
|
## Server flags
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sandbox-agent --token "$SANDBOX_TOKEN" --host 127.0.0.1 --port 8787
|
sandbox-agent --token "$SANDBOX_TOKEN" --host 127.0.0.1 --port 2468
|
||||||
```
|
```
|
||||||
|
|
||||||
- `--token`: global token for all requests.
|
- `--token`: global token for all requests.
|
||||||
|
|
@ -22,7 +22,7 @@ sandbox-agent --token "$SANDBOX_TOKEN" --host 127.0.0.1 --port 8787
|
||||||
<summary><strong>agents list</strong></summary>
|
<summary><strong>agents list</strong></summary>
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sandbox-agent agents list --endpoint http://127.0.0.1:8787
|
sandbox-agent agents list --endpoint http://127.0.0.1:2468
|
||||||
```
|
```
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ sandbox-agent agents list --endpoint http://127.0.0.1:8787
|
||||||
<summary><strong>agents install</strong></summary>
|
<summary><strong>agents install</strong></summary>
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sandbox-agent agents install claude --reinstall --endpoint http://127.0.0.1:8787
|
sandbox-agent agents install claude --reinstall --endpoint http://127.0.0.1:2468
|
||||||
```
|
```
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
@ -38,7 +38,7 @@ sandbox-agent agents install claude --reinstall --endpoint http://127.0.0.1:8787
|
||||||
<summary><strong>agents modes</strong></summary>
|
<summary><strong>agents modes</strong></summary>
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sandbox-agent agents modes claude --endpoint http://127.0.0.1:8787
|
sandbox-agent agents modes claude --endpoint http://127.0.0.1:2468
|
||||||
```
|
```
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ sandbox-agent sessions create my-session \
|
||||||
--agent claude \
|
--agent claude \
|
||||||
--agent-mode build \
|
--agent-mode build \
|
||||||
--permission-mode default \
|
--permission-mode default \
|
||||||
--endpoint http://127.0.0.1:8787
|
--endpoint http://127.0.0.1:2468
|
||||||
```
|
```
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
@ -62,7 +62,7 @@ sandbox-agent sessions create my-session \
|
||||||
```bash
|
```bash
|
||||||
sandbox-agent sessions send-message my-session \
|
sandbox-agent sessions send-message my-session \
|
||||||
--message "Summarize the repository" \
|
--message "Summarize the repository" \
|
||||||
--endpoint http://127.0.0.1:8787
|
--endpoint http://127.0.0.1:2468
|
||||||
```
|
```
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
@ -70,7 +70,7 @@ sandbox-agent sessions send-message my-session \
|
||||||
<summary><strong>sessions events</strong></summary>
|
<summary><strong>sessions events</strong></summary>
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sandbox-agent sessions events my-session --offset 0 --limit 50 --endpoint http://127.0.0.1:8787
|
sandbox-agent sessions events my-session --offset 0 --limit 50 --endpoint http://127.0.0.1:2468
|
||||||
```
|
```
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
@ -78,7 +78,7 @@ sandbox-agent sessions events my-session --offset 0 --limit 50 --endpoint http:/
|
||||||
<summary><strong>sessions events-sse</strong></summary>
|
<summary><strong>sessions events-sse</strong></summary>
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sandbox-agent sessions events-sse my-session --offset 0 --endpoint http://127.0.0.1:8787
|
sandbox-agent sessions events-sse my-session --offset 0 --endpoint http://127.0.0.1:2468
|
||||||
```
|
```
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
@ -88,7 +88,7 @@ sandbox-agent sessions events-sse my-session --offset 0 --endpoint http://127.0.
|
||||||
```bash
|
```bash
|
||||||
sandbox-agent sessions reply-question my-session QUESTION_ID \
|
sandbox-agent sessions reply-question my-session QUESTION_ID \
|
||||||
--answers "yes" \
|
--answers "yes" \
|
||||||
--endpoint http://127.0.0.1:8787
|
--endpoint http://127.0.0.1:2468
|
||||||
```
|
```
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
@ -96,7 +96,7 @@ sandbox-agent sessions reply-question my-session QUESTION_ID \
|
||||||
<summary><strong>sessions reject-question</strong></summary>
|
<summary><strong>sessions reject-question</strong></summary>
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sandbox-agent sessions reject-question my-session QUESTION_ID --endpoint http://127.0.0.1:8787
|
sandbox-agent sessions reject-question my-session QUESTION_ID --endpoint http://127.0.0.1:2468
|
||||||
```
|
```
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
@ -106,6 +106,6 @@ sandbox-agent sessions reject-question my-session QUESTION_ID --endpoint http://
|
||||||
```bash
|
```bash
|
||||||
sandbox-agent sessions reply-permission my-session PERMISSION_ID \
|
sandbox-agent sessions reply-permission my-session PERMISSION_ID \
|
||||||
--reply once \
|
--reply once \
|
||||||
--endpoint http://127.0.0.1:8787
|
--endpoint http://127.0.0.1:2468
|
||||||
```
|
```
|
||||||
</details>
|
</details>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export SANDBOX_TOKEN="..."
|
||||||
cargo run -p sandbox-agent -- \
|
cargo run -p sandbox-agent -- \
|
||||||
--token "$SANDBOX_TOKEN" \
|
--token "$SANDBOX_TOKEN" \
|
||||||
--host 0.0.0.0 \
|
--host 0.0.0.0 \
|
||||||
--port 8787
|
--port 2468
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Connect your client to the sandbox endpoint.
|
4. Connect your client to the sandbox endpoint.
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ description: "Run the daemon in a Daytona workspace."
|
||||||
|
|
||||||
1. Create a Daytona workspace with Rust and curl available.
|
1. Create a Daytona workspace with Rust and curl available.
|
||||||
2. Install or build the sandbox-agent binary.
|
2. Install or build the sandbox-agent binary.
|
||||||
3. Start the daemon and expose port `8787` (or your preferred port).
|
3. Start the daemon and expose port `2468` (or your preferred port).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export SANDBOX_TOKEN="..."
|
export SANDBOX_TOKEN="..."
|
||||||
|
|
@ -15,7 +15,7 @@ export SANDBOX_TOKEN="..."
|
||||||
cargo run -p sandbox-agent -- \
|
cargo run -p sandbox-agent -- \
|
||||||
--token "$SANDBOX_TOKEN" \
|
--token "$SANDBOX_TOKEN" \
|
||||||
--host 0.0.0.0 \
|
--host 0.0.0.0 \
|
||||||
--port 8787
|
--port 2468
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Use your Daytona port forwarding to reach the daemon from your client.
|
4. Use your Daytona port forwarding to reach the daemon from your client.
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,10 @@ The binary will be written to `./artifacts/sandbox-agent-x86_64-unknown-linux-mu
|
||||||
## Run the daemon
|
## Run the daemon
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run --rm -p 8787:8787 \
|
docker run --rm -p 2468:2468 \
|
||||||
-v "$PWD/artifacts:/artifacts" \
|
-v "$PWD/artifacts:/artifacts" \
|
||||||
debian:bookworm-slim \
|
debian:bookworm-slim \
|
||||||
/artifacts/sandbox-agent-x86_64-unknown-linux-musl --token "$SANDBOX_TOKEN" --host 0.0.0.0 --port 8787
|
/artifacts/sandbox-agent-x86_64-unknown-linux-musl --token "$SANDBOX_TOKEN" --host 0.0.0.0 --port 2468
|
||||||
```
|
```
|
||||||
|
|
||||||
You can now access the API at `http://localhost:8787`.
|
You can now access the API at `http://localhost:2468`.
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ export SANDBOX_TOKEN="..."
|
||||||
cargo run -p sandbox-agent -- \
|
cargo run -p sandbox-agent -- \
|
||||||
--token "$SANDBOX_TOKEN" \
|
--token "$SANDBOX_TOKEN" \
|
||||||
--host 0.0.0.0 \
|
--host 0.0.0.0 \
|
||||||
--port 8787
|
--port 2468
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Configure your client to connect to the sandbox endpoint.
|
4. Configure your client to connect to the sandbox endpoint.
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export SANDBOX_TOKEN="..."
|
||||||
cargo run -p sandbox-agent -- \
|
cargo run -p sandbox-agent -- \
|
||||||
--token "$SANDBOX_TOKEN" \
|
--token "$SANDBOX_TOKEN" \
|
||||||
--host 0.0.0.0 \
|
--host 0.0.0.0 \
|
||||||
--port 8787
|
--port 2468
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Configure your client to use the sandbox URL.
|
4. Configure your client to use the sandbox URL.
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ pnpm --filter @sandbox-agent/web dev
|
||||||
|
|
||||||
The UI expects:
|
The UI expects:
|
||||||
|
|
||||||
- Endpoint (e.g. `http://127.0.0.1:8787`)
|
- Endpoint (e.g. `http://127.0.0.1:2468`)
|
||||||
- Optional token
|
- Optional token
|
||||||
|
|
||||||
If you see CORS errors, enable CORS on the daemon with `--cors-allow-origin` and related flags.
|
If you see CORS errors, enable CORS on the daemon with `--cors-allow-origin` and related flags.
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,18 @@ description: "Endpoint reference for the sandbox agent daemon."
|
||||||
|
|
||||||
All endpoints are under `/v1`. Authentication uses the daemon-level token via `Authorization: Bearer <token>` or `x-sandbox-token`.
|
All endpoints are under `/v1`. Authentication uses the daemon-level token via `Authorization: Bearer <token>` or `x-sandbox-token`.
|
||||||
|
|
||||||
|
## Health
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><strong>GET /v1/health</strong> - Connectivity check</summary>
|
||||||
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "status": "ok" }
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
## Sessions
|
## Sessions
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
|
|
||||||
|
|
@ -18,18 +18,18 @@ Sandbox Agent SDK is a universal API and daemon for running coding agents inside
|
||||||
Run the daemon locally:
|
Run the daemon locally:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sandbox-agent --token "$SANDBOX_TOKEN" --host 127.0.0.1 --port 8787
|
sandbox-agent --token "$SANDBOX_TOKEN" --host 127.0.0.1 --port 2468
|
||||||
```
|
```
|
||||||
|
|
||||||
Send a message:
|
Send a message:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -X POST "http://127.0.0.1:8787/v1/sessions/my-session" \
|
curl -X POST "http://127.0.0.1:2468/v1/sessions/my-session" \
|
||||||
-H "Authorization: Bearer $SANDBOX_TOKEN" \
|
-H "Authorization: Bearer $SANDBOX_TOKEN" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"agent":"claude"}'
|
-d '{"agent":"claude"}'
|
||||||
|
|
||||||
curl -X POST "http://127.0.0.1:8787/v1/sessions/my-session/messages" \
|
curl -X POST "http://127.0.0.1:2468/v1/sessions/my-session/messages" \
|
||||||
-H "Authorization: Bearer $SANDBOX_TOKEN" \
|
-H "Authorization: Bearer $SANDBOX_TOKEN" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"message":"Explain the repo structure."}'
|
-d '{"message":"Explain the repo structure."}'
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,13 @@ description: "Start the daemon and send your first message."
|
||||||
Use the installed binary, or `cargo run` in development.
|
Use the installed binary, or `cargo run` in development.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sandbox-agent --token "$SANDBOX_TOKEN" --host 127.0.0.1 --port 8787
|
sandbox-agent --token "$SANDBOX_TOKEN" --host 127.0.0.1 --port 2468
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to run without auth (local dev only):
|
If you want to run without auth (local dev only):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sandbox-agent --no-token --host 127.0.0.1 --port 8787
|
sandbox-agent --no-token --host 127.0.0.1 --port 2468
|
||||||
```
|
```
|
||||||
|
|
||||||
### CORS (frontend usage)
|
### CORS (frontend usage)
|
||||||
|
|
@ -35,7 +35,7 @@ sandbox-agent \
|
||||||
## 2. Create a session
|
## 2. Create a session
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -X POST "http://127.0.0.1:8787/v1/sessions/my-session" \
|
curl -X POST "http://127.0.0.1:2468/v1/sessions/my-session" \
|
||||||
-H "Authorization: Bearer $SANDBOX_TOKEN" \
|
-H "Authorization: Bearer $SANDBOX_TOKEN" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"agent":"claude","agentMode":"build","permissionMode":"default"}'
|
-d '{"agent":"claude","agentMode":"build","permissionMode":"default"}'
|
||||||
|
|
@ -44,7 +44,7 @@ curl -X POST "http://127.0.0.1:8787/v1/sessions/my-session" \
|
||||||
## 3. Send a message
|
## 3. Send a message
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -X POST "http://127.0.0.1:8787/v1/sessions/my-session/messages" \
|
curl -X POST "http://127.0.0.1:2468/v1/sessions/my-session/messages" \
|
||||||
-H "Authorization: Bearer $SANDBOX_TOKEN" \
|
-H "Authorization: Bearer $SANDBOX_TOKEN" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"message":"Summarize the repository and suggest next steps."}'
|
-d '{"message":"Summarize the repository and suggest next steps."}'
|
||||||
|
|
@ -53,14 +53,14 @@ curl -X POST "http://127.0.0.1:8787/v1/sessions/my-session/messages" \
|
||||||
## 4. Read events
|
## 4. Read events
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl "http://127.0.0.1:8787/v1/sessions/my-session/events?offset=0&limit=50" \
|
curl "http://127.0.0.1:2468/v1/sessions/my-session/events?offset=0&limit=50" \
|
||||||
-H "Authorization: Bearer $SANDBOX_TOKEN"
|
-H "Authorization: Bearer $SANDBOX_TOKEN"
|
||||||
```
|
```
|
||||||
|
|
||||||
For streaming output, use SSE:
|
For streaming output, use SSE:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl "http://127.0.0.1:8787/v1/sessions/my-session/events/sse?offset=0" \
|
curl "http://127.0.0.1:2468/v1/sessions/my-session/events/sse?offset=0" \
|
||||||
-H "Authorization: Bearer $SANDBOX_TOKEN"
|
-H "Authorization: Bearer $SANDBOX_TOKEN"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -69,7 +69,7 @@ curl "http://127.0.0.1:8787/v1/sessions/my-session/events/sse?offset=0" \
|
||||||
The CLI mirrors the HTTP API:
|
The CLI mirrors the HTTP API:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sandbox-agent sessions create my-session --agent claude --endpoint http://127.0.0.1:8787 --token "$SANDBOX_TOKEN"
|
sandbox-agent sessions create my-session --agent claude --endpoint http://127.0.0.1:2468 --token "$SANDBOX_TOKEN"
|
||||||
|
|
||||||
sandbox-agent sessions send-message my-session --message "Hello" --endpoint http://127.0.0.1:8787 --token "$SANDBOX_TOKEN"
|
sandbox-agent sessions send-message my-session --message "Hello" --endpoint http://127.0.0.1:2468 --token "$SANDBOX_TOKEN"
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ The TypeScript SDK is generated from the OpenAPI spec produced by the Rust serve
|
||||||
## Generate types
|
## Generate types
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm --filter @sandbox-agent/typescript-sdk generate
|
pnpm --filter sandbox-agent generate
|
||||||
```
|
```
|
||||||
|
|
||||||
This runs:
|
This runs:
|
||||||
|
|
@ -19,10 +19,10 @@ This runs:
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { SandboxDaemonClient } from "@sandbox-agent/typescript-sdk";
|
import { SandboxDaemonClient } from "sandbox-agent";
|
||||||
|
|
||||||
const client = new SandboxDaemonClient({
|
const client = new SandboxDaemonClient({
|
||||||
baseUrl: "http://127.0.0.1:8787",
|
baseUrl: "http://127.0.0.1:2468",
|
||||||
token: process.env.SANDBOX_TOKEN,
|
token: process.env.SANDBOX_TOKEN,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,9 @@ enum AgentsCommand {
|
||||||
enum CredentialsCommand {
|
enum CredentialsCommand {
|
||||||
/// Extract credentials using local discovery rules.
|
/// Extract credentials using local discovery rules.
|
||||||
Extract(CredentialsExtractArgs),
|
Extract(CredentialsExtractArgs),
|
||||||
|
/// Output credentials as environment variable assignments.
|
||||||
|
#[command(name = "extract-env")]
|
||||||
|
ExtractEnv(CredentialsExtractEnvArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
|
|
@ -239,6 +242,17 @@ struct CredentialsExtractArgs {
|
||||||
reveal: bool,
|
reveal: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Args, Debug)]
|
||||||
|
struct CredentialsExtractEnvArgs {
|
||||||
|
/// Prefix each line with "export " for shell sourcing.
|
||||||
|
#[arg(long, short = 'e')]
|
||||||
|
export: bool,
|
||||||
|
#[arg(long, short = 'd')]
|
||||||
|
home_dir: Option<PathBuf>,
|
||||||
|
#[arg(long, short = 'n')]
|
||||||
|
no_oauth: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
enum CliError {
|
enum CliError {
|
||||||
#[error("missing --token or --no-token for server mode")]
|
#[error("missing --token or --no-token for server mode")]
|
||||||
|
|
@ -455,6 +469,33 @@ fn run_credentials(command: &CredentialsCommand) -> Result<(), CliError> {
|
||||||
write_stdout_line(&pretty)?;
|
write_stdout_line(&pretty)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
CredentialsCommand::ExtractEnv(args) => {
|
||||||
|
let mut options = CredentialExtractionOptions::new();
|
||||||
|
if let Some(home_dir) = args.home_dir.clone() {
|
||||||
|
options.home_dir = Some(home_dir);
|
||||||
|
}
|
||||||
|
if args.no_oauth {
|
||||||
|
options.include_oauth = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let credentials = extract_all_credentials(&options);
|
||||||
|
let prefix = if args.export { "export " } else { "" };
|
||||||
|
|
||||||
|
if let Some(cred) = &credentials.anthropic {
|
||||||
|
write_stdout_line(&format!("{}ANTHROPIC_API_KEY={}", prefix, cred.api_key))?;
|
||||||
|
write_stdout_line(&format!("{}CLAUDE_API_KEY={}", prefix, cred.api_key))?;
|
||||||
|
}
|
||||||
|
if let Some(cred) = &credentials.openai {
|
||||||
|
write_stdout_line(&format!("{}OPENAI_API_KEY={}", prefix, cred.api_key))?;
|
||||||
|
write_stdout_line(&format!("{}CODEX_API_KEY={}", prefix, cred.api_key))?;
|
||||||
|
}
|
||||||
|
for (provider, cred) in &credentials.other {
|
||||||
|
let var_name = format!("{}_API_KEY", provider.to_uppercase().replace('-', "_"));
|
||||||
|
write_stdout_line(&format!("{}{}={}", prefix, var_name, cred.api_key))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ pub fn build_router(state: AppState) -> Router {
|
||||||
let shared = Arc::new(state);
|
let shared = Arc::new(state);
|
||||||
|
|
||||||
let mut v1_router = Router::new()
|
let mut v1_router = Router::new()
|
||||||
|
.route("/health", get(get_health))
|
||||||
.route("/agents", get(list_agents))
|
.route("/agents", get(list_agents))
|
||||||
.route("/agents/:agent/install", post(install_agent))
|
.route("/agents/:agent/install", post(install_agent))
|
||||||
.route("/agents/:agent/modes", get(get_agent_modes))
|
.route("/agents/:agent/modes", get(get_agent_modes))
|
||||||
|
|
@ -107,6 +108,7 @@ pub fn build_router(state: AppState) -> Router {
|
||||||
#[derive(OpenApi)]
|
#[derive(OpenApi)]
|
||||||
#[openapi(
|
#[openapi(
|
||||||
paths(
|
paths(
|
||||||
|
get_health,
|
||||||
install_agent,
|
install_agent,
|
||||||
get_agent_modes,
|
get_agent_modes,
|
||||||
list_agents,
|
list_agents,
|
||||||
|
|
@ -125,6 +127,7 @@ pub fn build_router(state: AppState) -> Router {
|
||||||
AgentModesResponse,
|
AgentModesResponse,
|
||||||
AgentInfo,
|
AgentInfo,
|
||||||
AgentListResponse,
|
AgentListResponse,
|
||||||
|
HealthResponse,
|
||||||
CreateSessionRequest,
|
CreateSessionRequest,
|
||||||
CreateSessionResponse,
|
CreateSessionResponse,
|
||||||
MessageRequest,
|
MessageRequest,
|
||||||
|
|
@ -153,6 +156,7 @@ pub fn build_router(state: AppState) -> Router {
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
tags(
|
tags(
|
||||||
|
(name = "meta", description = "Service metadata"),
|
||||||
(name = "agents", description = "Agent management"),
|
(name = "agents", description = "Agent management"),
|
||||||
(name = "sessions", description = "Session management")
|
(name = "sessions", description = "Session management")
|
||||||
)
|
)
|
||||||
|
|
@ -1202,12 +1206,6 @@ fn extract_token(headers: &HeaderMap) -> Option<String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(value) = headers.get("x-sandbox-token") {
|
|
||||||
if let Ok(value) = value.to_str() {
|
|
||||||
return Some(value.to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1249,6 +1247,12 @@ pub struct AgentListResponse {
|
||||||
pub agents: Vec<AgentInfo>,
|
pub agents: Vec<AgentInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct HealthResponse {
|
||||||
|
pub status: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CreateSessionRequest {
|
pub struct CreateSessionRequest {
|
||||||
|
|
@ -1390,6 +1394,18 @@ async fn get_agent_modes(
|
||||||
Ok(Json(AgentModesResponse { modes }))
|
Ok(Json(AgentModesResponse { modes }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[utoipa::path(
|
||||||
|
get,
|
||||||
|
path = "/v1/health",
|
||||||
|
responses((status = 200, body = HealthResponse)),
|
||||||
|
tag = "meta"
|
||||||
|
)]
|
||||||
|
async fn get_health() -> Json<HealthResponse> {
|
||||||
|
Json(HealthResponse {
|
||||||
|
status: "ok".to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
get,
|
get,
|
||||||
path = "/v1/agents",
|
path = "/v1/agents",
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -6,11 +6,11 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "pnpm --filter @sandbox-agent/typescript-sdk build && vite build",
|
"build": "pnpm --filter sandbox-agent build && vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sandbox-agent/typescript-sdk": "workspace:*",
|
"sandbox-agent": "workspace:*",
|
||||||
"@types/react": "^18.3.3",
|
"@types/react": "^18.3.3",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@vitejs/plugin-react": "^4.3.1",
|
"@vitejs/plugin-react": "^4.3.1",
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ const escapeSingleQuotes = (value: string) => value.replace(/'/g, `'\\''`);
|
||||||
const buildCurl = (method: string, url: string, body?: string, token?: string) => {
|
const buildCurl = (method: string, url: string, body?: string, token?: string) => {
|
||||||
const headers: string[] = [];
|
const headers: string[] = [];
|
||||||
if (token) {
|
if (token) {
|
||||||
headers.push(`-H 'x-sandbox-token: ${escapeSingleQuotes(token)}'`);
|
headers.push(`-H 'Authorization: Bearer ${escapeSingleQuotes(token)}'`);
|
||||||
}
|
}
|
||||||
if (body) {
|
if (body) {
|
||||||
headers.push(`-H 'Content-Type: application/json'`);
|
headers.push(`-H 'Content-Type: application/json'`);
|
||||||
|
|
@ -180,7 +180,7 @@ const formatTime = (value: string) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [endpoint, setEndpoint] = useState("http://localhost:8787");
|
const [endpoint, setEndpoint] = useState("http://localhost:2468");
|
||||||
const [token, setToken] = useState("");
|
const [token, setToken] = useState("");
|
||||||
const [connected, setConnected] = useState(false);
|
const [connected, setConnected] = useState(false);
|
||||||
const [connecting, setConnecting] = useState(false);
|
const [connecting, setConnecting] = useState(false);
|
||||||
|
|
@ -242,7 +242,7 @@ export default function App() {
|
||||||
headers["Content-Type"] = "application/json";
|
headers["Content-Type"] = "application/json";
|
||||||
}
|
}
|
||||||
if (token) {
|
if (token) {
|
||||||
headers["x-sandbox-token"] = token;
|
headers.Authorization = `Bearer ${token}`;
|
||||||
}
|
}
|
||||||
const curl = buildCurl(method, url, bodyText, token);
|
const curl = buildCurl(method, url, bodyText, token);
|
||||||
const logId = logIdRef.current++;
|
const logId = logIdRef.current++;
|
||||||
|
|
@ -289,13 +289,9 @@ export default function App() {
|
||||||
setConnecting(true);
|
setConnecting(true);
|
||||||
setConnectError(null);
|
setConnectError(null);
|
||||||
try {
|
try {
|
||||||
const data = await apiFetch(`${API_PREFIX}/agents`);
|
await apiFetch(`${API_PREFIX}/health`);
|
||||||
const list = (data as { agents?: AgentInfo[] })?.agents ?? [];
|
|
||||||
setAgents(list);
|
|
||||||
if (list.length > 0) {
|
|
||||||
setAgentId(list[0]?.id ?? "claude");
|
|
||||||
}
|
|
||||||
setConnected(true);
|
setConnected(true);
|
||||||
|
await refreshAgents();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const message = error instanceof Error ? error.message : "Unable to connect";
|
const message = error instanceof Error ? error.message : "Unable to connect";
|
||||||
setConnectError(message);
|
setConnectError(message);
|
||||||
|
|
@ -606,8 +602,9 @@ export default function App() {
|
||||||
one place.
|
one place.
|
||||||
</div>
|
</div>
|
||||||
<div className="callout mono">
|
<div className="callout mono">
|
||||||
sandbox-agent --host 0.0.0.0 --port 8787 --token <token> --cors-allowed-origin
|
sandbox-agent --host 0.0.0.0 --port 2468 --token <token> --cors-allow-origin
|
||||||
http://localhost:5173 --cors-allowed-methods GET,POST --cors-allowed-headers Authorization,x-sandbox-token
|
http://localhost:5173 --cors-allow-method GET --cors-allow-method POST --cors-allow-header Authorization
|
||||||
|
--cors-allow-header Content-Type
|
||||||
</div>
|
</div>
|
||||||
<div className="tag-list">
|
<div className="tag-list">
|
||||||
<span className="pill">CORS required for browser access</span>
|
<span className="pill">CORS required for browser access</span>
|
||||||
|
|
@ -630,7 +627,7 @@ export default function App() {
|
||||||
<span className="label">Endpoint</span>
|
<span className="label">Endpoint</span>
|
||||||
<input
|
<input
|
||||||
className="input"
|
className="input"
|
||||||
placeholder="http://localhost:8787"
|
placeholder="http://localhost:2468"
|
||||||
value={endpoint}
|
value={endpoint}
|
||||||
onChange={(event) => setEndpoint(event.target.value)}
|
onChange={(event) => setEndpoint(event.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
@ -639,7 +636,7 @@ export default function App() {
|
||||||
<span className="label">Token (optional)</span>
|
<span className="label">Token (optional)</span>
|
||||||
<input
|
<input
|
||||||
className="input"
|
className="input"
|
||||||
placeholder="x-sandbox-token"
|
placeholder="token"
|
||||||
value={token}
|
value={token}
|
||||||
onChange={(event) => setToken(event.target.value)}
|
onChange={(event) => setToken(event.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
2333
pnpm-lock.yaml
generated
Normal file
2333
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -4,11 +4,11 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"extract": "tsx ../../src/agents/index.ts",
|
"extract": "tsx src/index.ts",
|
||||||
"extract:opencode": "tsx ../../src/agents/index.ts --agent=opencode",
|
"extract:opencode": "tsx src/index.ts --agent=opencode",
|
||||||
"extract:claude": "tsx ../../src/agents/index.ts --agent=claude",
|
"extract:claude": "tsx src/index.ts --agent=claude",
|
||||||
"extract:codex": "tsx ../../src/agents/index.ts --agent=codex",
|
"extract:codex": "tsx src/index.ts --agent=codex",
|
||||||
"extract:amp": "tsx ../../src/agents/index.ts --agent=amp"
|
"extract:amp": "tsx src/index.ts --agent=amp"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ts-json-schema-generator": "^2.4.0",
|
"ts-json-schema-generator": "^2.4.0",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "@sandbox-agent/typescript-sdk",
|
"name": "sandbox-agent",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { components } from "./generated/openapi";
|
import type { components } from "./generated/openapi.js";
|
||||||
|
|
||||||
export type AgentInstallRequest = components["schemas"]["AgentInstallRequest"];
|
export type AgentInstallRequest = components["schemas"]["AgentInstallRequest"];
|
||||||
export type AgentModeInfo = components["schemas"]["AgentModeInfo"];
|
export type AgentModeInfo = components["schemas"]["AgentModeInfo"];
|
||||||
|
|
|
||||||
1417
sdks/typescript/src/generated/openapi.json
Normal file
1417
sdks/typescript/src/generated/openapi.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,250 +1,57 @@
|
||||||
/* eslint-disable */
|
/**
|
||||||
// This file is generated by openapi-typescript. Do not edit by hand.
|
* This file was auto-generated by openapi-typescript.
|
||||||
|
* Do not make direct changes to the file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** OneOf type helpers */
|
||||||
|
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
|
||||||
|
type XOR<T, U> = (T | U) extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U;
|
||||||
|
type OneOf<T extends any[]> = T extends [infer Only] ? Only : T extends [infer A, infer B, ...infer Rest] ? OneOf<[XOR<A, B>, ...Rest]> : never;
|
||||||
|
|
||||||
export interface paths {
|
export interface paths {
|
||||||
"/v1/agents": {
|
"/v1/agents": {
|
||||||
get: {
|
get: operations["list_agents"];
|
||||||
responses: {
|
|
||||||
200: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["AgentListResponse"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
"/v1/agents/{agent}/install": {
|
"/v1/agents/{agent}/install": {
|
||||||
post: {
|
post: operations["install_agent"];
|
||||||
parameters: {
|
|
||||||
path: {
|
|
||||||
agent: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
requestBody: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["AgentInstallRequest"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
responses: {
|
|
||||||
204: {
|
|
||||||
description: string;
|
|
||||||
};
|
|
||||||
400: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["ProblemDetails"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
404: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["ProblemDetails"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
500: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["ProblemDetails"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
"/v1/agents/{agent}/modes": {
|
"/v1/agents/{agent}/modes": {
|
||||||
get: {
|
get: operations["get_agent_modes"];
|
||||||
parameters: {
|
|
||||||
path: {
|
|
||||||
agent: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
responses: {
|
|
||||||
200: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["AgentModesResponse"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
400: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["ProblemDetails"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
"/v1/sessions/{session_id}": {
|
"/v1/sessions/{session_id}": {
|
||||||
post: {
|
post: operations["create_session"];
|
||||||
parameters: {
|
|
||||||
path: {
|
|
||||||
session_id: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
requestBody: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["CreateSessionRequest"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
responses: {
|
|
||||||
200: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["CreateSessionResponse"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
400: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["ProblemDetails"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
409: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["ProblemDetails"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"/v1/sessions/{session_id}/messages": {
|
|
||||||
post: {
|
|
||||||
parameters: {
|
|
||||||
path: {
|
|
||||||
session_id: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
requestBody: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["MessageRequest"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
responses: {
|
|
||||||
204: {
|
|
||||||
description: string;
|
|
||||||
};
|
|
||||||
404: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["ProblemDetails"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
"/v1/sessions/{session_id}/events": {
|
"/v1/sessions/{session_id}/events": {
|
||||||
get: {
|
get: operations["get_events"];
|
||||||
parameters: {
|
|
||||||
path: {
|
|
||||||
session_id: string;
|
|
||||||
};
|
|
||||||
query?: {
|
|
||||||
offset?: number | null;
|
|
||||||
limit?: number | null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
responses: {
|
|
||||||
200: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["EventsResponse"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
404: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["ProblemDetails"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
"/v1/sessions/{session_id}/events/sse": {
|
"/v1/sessions/{session_id}/events/sse": {
|
||||||
get: {
|
get: operations["get_events_sse"];
|
||||||
parameters: {
|
|
||||||
path: {
|
|
||||||
session_id: string;
|
|
||||||
};
|
|
||||||
query?: {
|
|
||||||
offset?: number | null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
responses: {
|
|
||||||
200: {
|
|
||||||
description: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
"/v1/sessions/{session_id}/questions/{question_id}/reply": {
|
"/v1/sessions/{session_id}/messages": {
|
||||||
post: {
|
post: operations["post_message"];
|
||||||
parameters: {
|
|
||||||
path: {
|
|
||||||
session_id: string;
|
|
||||||
question_id: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
requestBody: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["QuestionReplyRequest"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
responses: {
|
|
||||||
204: {
|
|
||||||
description: string;
|
|
||||||
};
|
|
||||||
404: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["ProblemDetails"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"/v1/sessions/{session_id}/questions/{question_id}/reject": {
|
|
||||||
post: {
|
|
||||||
parameters: {
|
|
||||||
path: {
|
|
||||||
session_id: string;
|
|
||||||
question_id: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
responses: {
|
|
||||||
204: {
|
|
||||||
description: string;
|
|
||||||
};
|
|
||||||
404: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["ProblemDetails"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
"/v1/sessions/{session_id}/permissions/{permission_id}/reply": {
|
"/v1/sessions/{session_id}/permissions/{permission_id}/reply": {
|
||||||
post: {
|
post: operations["reply_permission"];
|
||||||
parameters: {
|
};
|
||||||
path: {
|
"/v1/sessions/{session_id}/questions/{question_id}/reject": {
|
||||||
session_id: string;
|
post: operations["reject_question"];
|
||||||
permission_id: string;
|
};
|
||||||
};
|
"/v1/sessions/{session_id}/questions/{question_id}/reply": {
|
||||||
};
|
post: operations["reply_question"];
|
||||||
requestBody: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["PermissionReplyRequest"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
responses: {
|
|
||||||
204: {
|
|
||||||
description: string;
|
|
||||||
};
|
|
||||||
404: {
|
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["ProblemDetails"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type webhooks = Record<string, never>;
|
||||||
|
|
||||||
export interface components {
|
export interface components {
|
||||||
schemas: {
|
schemas: {
|
||||||
AgentError: {
|
AgentError: {
|
||||||
type: components["schemas"]["ErrorType"];
|
|
||||||
message: string;
|
|
||||||
agent?: string | null;
|
agent?: string | null;
|
||||||
|
details?: unknown;
|
||||||
|
message: string;
|
||||||
session_id?: string | null;
|
session_id?: string | null;
|
||||||
details?: unknown | null;
|
type: components["schemas"]["ErrorType"];
|
||||||
};
|
};
|
||||||
AgentInfo: {
|
AgentInfo: {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -259,31 +66,31 @@ export interface components {
|
||||||
agents: components["schemas"]["AgentInfo"][];
|
agents: components["schemas"]["AgentInfo"][];
|
||||||
};
|
};
|
||||||
AgentModeInfo: {
|
AgentModeInfo: {
|
||||||
|
description: string;
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
|
||||||
};
|
};
|
||||||
AgentModesResponse: {
|
AgentModesResponse: {
|
||||||
modes: components["schemas"]["AgentModeInfo"][];
|
modes: components["schemas"]["AgentModeInfo"][];
|
||||||
};
|
};
|
||||||
AttachmentSource:
|
AttachmentSource: {
|
||||||
| {
|
path: string;
|
||||||
type: "path";
|
/** @enum {string} */
|
||||||
path: string;
|
type: "path";
|
||||||
}
|
} | {
|
||||||
| {
|
/** @enum {string} */
|
||||||
type: "url";
|
type: "url";
|
||||||
url: string;
|
url: string;
|
||||||
}
|
} | ({
|
||||||
| {
|
data: string;
|
||||||
type: "data";
|
encoding?: string | null;
|
||||||
data: string;
|
/** @enum {string} */
|
||||||
encoding?: string | null;
|
type: "data";
|
||||||
};
|
});
|
||||||
CrashInfo: {
|
CrashInfo: {
|
||||||
message: string;
|
details?: unknown;
|
||||||
kind?: string | null;
|
kind?: string | null;
|
||||||
details?: unknown | null;
|
message: string;
|
||||||
};
|
};
|
||||||
CreateSessionRequest: {
|
CreateSessionRequest: {
|
||||||
agent: string;
|
agent: string;
|
||||||
|
|
@ -291,31 +98,20 @@ export interface components {
|
||||||
agentVersion?: string | null;
|
agentVersion?: string | null;
|
||||||
model?: string | null;
|
model?: string | null;
|
||||||
permissionMode?: string | null;
|
permissionMode?: string | null;
|
||||||
token?: string | null;
|
|
||||||
validateToken?: boolean | null;
|
|
||||||
variant?: string | null;
|
variant?: string | null;
|
||||||
};
|
};
|
||||||
CreateSessionResponse: {
|
CreateSessionResponse: {
|
||||||
healthy: boolean;
|
|
||||||
error?: components["schemas"]["AgentError"] | null;
|
|
||||||
agentSessionId?: string | null;
|
agentSessionId?: string | null;
|
||||||
|
error?: components["schemas"]["AgentError"] | null;
|
||||||
|
healthy: boolean;
|
||||||
};
|
};
|
||||||
ErrorType:
|
/** @enum {string} */
|
||||||
| "invalid_request"
|
ErrorType: "invalid_request" | "unsupported_agent" | "agent_not_installed" | "install_failed" | "agent_process_exited" | "token_invalid" | "permission_denied" | "session_not_found" | "session_already_exists" | "mode_not_supported" | "stream_error" | "timeout";
|
||||||
| "unsupported_agent"
|
|
||||||
| "agent_not_installed"
|
|
||||||
| "install_failed"
|
|
||||||
| "agent_process_exited"
|
|
||||||
| "token_invalid"
|
|
||||||
| "permission_denied"
|
|
||||||
| "session_not_found"
|
|
||||||
| "session_already_exists"
|
|
||||||
| "mode_not_supported"
|
|
||||||
| "stream_error"
|
|
||||||
| "timeout";
|
|
||||||
EventsQuery: {
|
EventsQuery: {
|
||||||
offset?: number | null;
|
/** Format: int64 */
|
||||||
limit?: number | null;
|
limit?: number | null;
|
||||||
|
/** Format: int64 */
|
||||||
|
offset?: number | null;
|
||||||
};
|
};
|
||||||
EventsResponse: {
|
EventsResponse: {
|
||||||
events: components["schemas"]["UniversalEvent"][];
|
events: components["schemas"]["UniversalEvent"][];
|
||||||
|
|
@ -324,141 +120,152 @@ export interface components {
|
||||||
MessageRequest: {
|
MessageRequest: {
|
||||||
message: string;
|
message: string;
|
||||||
};
|
};
|
||||||
|
/** @enum {string} */
|
||||||
PermissionReply: "once" | "always" | "reject";
|
PermissionReply: "once" | "always" | "reject";
|
||||||
PermissionReplyRequest: {
|
PermissionReplyRequest: {
|
||||||
reply: components["schemas"]["PermissionReply"];
|
reply: components["schemas"]["PermissionReply"];
|
||||||
};
|
};
|
||||||
PermissionRequest: {
|
PermissionRequest: {
|
||||||
id: string;
|
|
||||||
sessionId: string;
|
|
||||||
permission: string;
|
|
||||||
patterns: string[];
|
|
||||||
always: string[];
|
always: string[];
|
||||||
metadata?: Record<string, unknown>;
|
id: string;
|
||||||
|
metadata?: {
|
||||||
|
[key: string]: unknown;
|
||||||
|
};
|
||||||
|
patterns: string[];
|
||||||
|
permission: string;
|
||||||
|
sessionId: string;
|
||||||
tool?: components["schemas"]["PermissionToolRef"] | null;
|
tool?: components["schemas"]["PermissionToolRef"] | null;
|
||||||
};
|
};
|
||||||
PermissionToolRef: {
|
PermissionToolRef: {
|
||||||
messageId: string;
|
|
||||||
callId: string;
|
callId: string;
|
||||||
|
messageId: string;
|
||||||
};
|
};
|
||||||
ProblemDetails: {
|
ProblemDetails: {
|
||||||
type: string;
|
|
||||||
title: string;
|
|
||||||
status: number;
|
|
||||||
detail?: string | null;
|
detail?: string | null;
|
||||||
instance?: string | null;
|
instance?: string | null;
|
||||||
|
/** Format: int32 */
|
||||||
|
status: number;
|
||||||
|
title: string;
|
||||||
|
type: string;
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
};
|
};
|
||||||
QuestionInfo: {
|
QuestionInfo: {
|
||||||
question: string;
|
custom?: boolean | null;
|
||||||
options: components["schemas"]["QuestionOption"][];
|
|
||||||
header?: string | null;
|
header?: string | null;
|
||||||
multiSelect?: boolean | null;
|
multiSelect?: boolean | null;
|
||||||
custom?: boolean | null;
|
options: components["schemas"]["QuestionOption"][];
|
||||||
|
question: string;
|
||||||
};
|
};
|
||||||
QuestionOption: {
|
QuestionOption: {
|
||||||
label: string;
|
|
||||||
description?: string | null;
|
description?: string | null;
|
||||||
|
label: string;
|
||||||
};
|
};
|
||||||
QuestionReplyRequest: {
|
QuestionReplyRequest: {
|
||||||
answers: string[][];
|
answers: string[][];
|
||||||
};
|
};
|
||||||
QuestionRequest: {
|
QuestionRequest: {
|
||||||
id: string;
|
id: string;
|
||||||
sessionId: string;
|
|
||||||
questions: components["schemas"]["QuestionInfo"][];
|
questions: components["schemas"]["QuestionInfo"][];
|
||||||
|
sessionId: string;
|
||||||
tool?: components["schemas"]["QuestionToolRef"] | null;
|
tool?: components["schemas"]["QuestionToolRef"] | null;
|
||||||
};
|
};
|
||||||
QuestionToolRef: {
|
QuestionToolRef: {
|
||||||
messageId: string;
|
|
||||||
callId: string;
|
callId: string;
|
||||||
|
messageId: string;
|
||||||
};
|
};
|
||||||
Started: {
|
Started: {
|
||||||
|
details?: unknown;
|
||||||
message?: string | null;
|
message?: string | null;
|
||||||
details?: unknown | null;
|
|
||||||
};
|
};
|
||||||
UniversalEvent: {
|
UniversalEvent: {
|
||||||
id: number;
|
|
||||||
timestamp: string;
|
|
||||||
sessionId: string;
|
|
||||||
agent: string;
|
agent: string;
|
||||||
agentSessionId?: string | null;
|
agentSessionId?: string | null;
|
||||||
data: components["schemas"]["UniversalEventData"];
|
data: components["schemas"]["UniversalEventData"];
|
||||||
|
/** Format: int64 */
|
||||||
|
id: number;
|
||||||
|
sessionId: string;
|
||||||
|
timestamp: string;
|
||||||
};
|
};
|
||||||
UniversalEventData:
|
UniversalEventData: {
|
||||||
| { message: components["schemas"]["UniversalMessage"] }
|
message: components["schemas"]["UniversalMessage"];
|
||||||
| { started: components["schemas"]["Started"] }
|
} | {
|
||||||
| { error: components["schemas"]["CrashInfo"] }
|
started: components["schemas"]["Started"];
|
||||||
| { questionAsked: components["schemas"]["QuestionRequest"] }
|
} | {
|
||||||
| { permissionAsked: components["schemas"]["PermissionRequest"] }
|
error: components["schemas"]["CrashInfo"];
|
||||||
| { raw: unknown };
|
} | {
|
||||||
UniversalMessage:
|
questionAsked: components["schemas"]["QuestionRequest"];
|
||||||
| components["schemas"]["UniversalMessageParsed"]
|
} | {
|
||||||
| {
|
permissionAsked: components["schemas"]["PermissionRequest"];
|
||||||
raw: unknown;
|
} | {
|
||||||
error?: string | null;
|
raw: unknown;
|
||||||
};
|
};
|
||||||
|
UniversalMessage: OneOf<[components["schemas"]["UniversalMessageParsed"], {
|
||||||
|
error?: string | null;
|
||||||
|
raw: unknown;
|
||||||
|
}]>;
|
||||||
UniversalMessageParsed: {
|
UniversalMessageParsed: {
|
||||||
role: string;
|
|
||||||
parts: components["schemas"]["UniversalMessagePart"][];
|
|
||||||
id?: string | null;
|
id?: string | null;
|
||||||
metadata?: Record<string, unknown>;
|
metadata?: {
|
||||||
|
[key: string]: unknown;
|
||||||
|
};
|
||||||
|
parts: components["schemas"]["UniversalMessagePart"][];
|
||||||
|
role: string;
|
||||||
|
};
|
||||||
|
UniversalMessagePart: {
|
||||||
|
text: string;
|
||||||
|
/** @enum {string} */
|
||||||
|
type: "text";
|
||||||
|
} | ({
|
||||||
|
id?: string | null;
|
||||||
|
input: unknown;
|
||||||
|
name: string;
|
||||||
|
/** @enum {string} */
|
||||||
|
type: "tool_call";
|
||||||
|
}) | ({
|
||||||
|
id?: string | null;
|
||||||
|
is_error?: boolean | null;
|
||||||
|
name?: string | null;
|
||||||
|
output: unknown;
|
||||||
|
/** @enum {string} */
|
||||||
|
type: "tool_result";
|
||||||
|
}) | ({
|
||||||
|
arguments: unknown;
|
||||||
|
id?: string | null;
|
||||||
|
name?: string | null;
|
||||||
|
raw?: unknown;
|
||||||
|
/** @enum {string} */
|
||||||
|
type: "function_call";
|
||||||
|
}) | ({
|
||||||
|
id?: string | null;
|
||||||
|
is_error?: boolean | null;
|
||||||
|
name?: string | null;
|
||||||
|
raw?: unknown;
|
||||||
|
result: unknown;
|
||||||
|
/** @enum {string} */
|
||||||
|
type: "function_result";
|
||||||
|
}) | ({
|
||||||
|
filename?: string | null;
|
||||||
|
mime_type?: string | null;
|
||||||
|
raw?: unknown;
|
||||||
|
source: components["schemas"]["AttachmentSource"];
|
||||||
|
/** @enum {string} */
|
||||||
|
type: "file";
|
||||||
|
}) | ({
|
||||||
|
alt?: string | null;
|
||||||
|
mime_type?: string | null;
|
||||||
|
raw?: unknown;
|
||||||
|
source: components["schemas"]["AttachmentSource"];
|
||||||
|
/** @enum {string} */
|
||||||
|
type: "image";
|
||||||
|
}) | {
|
||||||
|
message: string;
|
||||||
|
/** @enum {string} */
|
||||||
|
type: "error";
|
||||||
|
} | {
|
||||||
|
raw: unknown;
|
||||||
|
/** @enum {string} */
|
||||||
|
type: "unknown";
|
||||||
};
|
};
|
||||||
UniversalMessagePart:
|
|
||||||
| {
|
|
||||||
type: "text";
|
|
||||||
text: string;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: "tool_call";
|
|
||||||
name: string;
|
|
||||||
input: unknown;
|
|
||||||
id?: string | null;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: "tool_result";
|
|
||||||
output: unknown;
|
|
||||||
id?: string | null;
|
|
||||||
name?: string | null;
|
|
||||||
is_error?: boolean | null;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: "function_call";
|
|
||||||
arguments: unknown;
|
|
||||||
id?: string | null;
|
|
||||||
name?: string | null;
|
|
||||||
raw?: unknown | null;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: "function_result";
|
|
||||||
result: unknown;
|
|
||||||
id?: string | null;
|
|
||||||
name?: string | null;
|
|
||||||
is_error?: boolean | null;
|
|
||||||
raw?: unknown | null;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: "file";
|
|
||||||
source: components["schemas"]["AttachmentSource"];
|
|
||||||
mime_type?: string | null;
|
|
||||||
filename?: string | null;
|
|
||||||
raw?: unknown | null;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: "image";
|
|
||||||
source: components["schemas"]["AttachmentSource"];
|
|
||||||
mime_type?: string | null;
|
|
||||||
alt?: string | null;
|
|
||||||
raw?: unknown | null;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: "error";
|
|
||||||
message: string;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: "unknown";
|
|
||||||
raw: unknown;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
responses: never;
|
responses: never;
|
||||||
parameters: never;
|
parameters: never;
|
||||||
|
|
@ -467,4 +274,244 @@ export interface components {
|
||||||
pathItems: never;
|
pathItems: never;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type webhooks = never;
|
export type $defs = Record<string, never>;
|
||||||
|
|
||||||
|
export type external = Record<string, never>;
|
||||||
|
|
||||||
|
export interface operations {
|
||||||
|
|
||||||
|
list_agents: {
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["AgentListResponse"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
install_agent: {
|
||||||
|
parameters: {
|
||||||
|
path: {
|
||||||
|
/** @description Agent id */
|
||||||
|
agent: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
requestBody: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["AgentInstallRequest"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: {
|
||||||
|
/** @description Agent installed */
|
||||||
|
204: {
|
||||||
|
content: never;
|
||||||
|
};
|
||||||
|
400: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["ProblemDetails"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
404: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["ProblemDetails"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
500: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["ProblemDetails"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
get_agent_modes: {
|
||||||
|
parameters: {
|
||||||
|
path: {
|
||||||
|
/** @description Agent id */
|
||||||
|
agent: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["AgentModesResponse"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
400: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["ProblemDetails"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
create_session: {
|
||||||
|
parameters: {
|
||||||
|
path: {
|
||||||
|
/** @description Client session id */
|
||||||
|
session_id: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
requestBody: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["CreateSessionRequest"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["CreateSessionResponse"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
400: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["ProblemDetails"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
409: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["ProblemDetails"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
get_events: {
|
||||||
|
parameters: {
|
||||||
|
query?: {
|
||||||
|
/** @description Last seen event id (exclusive) */
|
||||||
|
offset?: number | null;
|
||||||
|
/** @description Max events to return */
|
||||||
|
limit?: number | null;
|
||||||
|
};
|
||||||
|
path: {
|
||||||
|
/** @description Session id */
|
||||||
|
session_id: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["EventsResponse"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
404: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["ProblemDetails"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
get_events_sse: {
|
||||||
|
parameters: {
|
||||||
|
query?: {
|
||||||
|
/** @description Last seen event id (exclusive) */
|
||||||
|
offset?: number | null;
|
||||||
|
};
|
||||||
|
path: {
|
||||||
|
/** @description Session id */
|
||||||
|
session_id: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: {
|
||||||
|
/** @description SSE event stream */
|
||||||
|
200: {
|
||||||
|
content: never;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
post_message: {
|
||||||
|
parameters: {
|
||||||
|
path: {
|
||||||
|
/** @description Session id */
|
||||||
|
session_id: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
requestBody: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["MessageRequest"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: {
|
||||||
|
/** @description Message accepted */
|
||||||
|
204: {
|
||||||
|
content: never;
|
||||||
|
};
|
||||||
|
404: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["ProblemDetails"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
reply_permission: {
|
||||||
|
parameters: {
|
||||||
|
path: {
|
||||||
|
/** @description Session id */
|
||||||
|
session_id: string;
|
||||||
|
/** @description Permission id */
|
||||||
|
permission_id: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
requestBody: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["PermissionReplyRequest"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: {
|
||||||
|
/** @description Permission reply accepted */
|
||||||
|
204: {
|
||||||
|
content: never;
|
||||||
|
};
|
||||||
|
404: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["ProblemDetails"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
reject_question: {
|
||||||
|
parameters: {
|
||||||
|
path: {
|
||||||
|
/** @description Session id */
|
||||||
|
session_id: string;
|
||||||
|
/** @description Question id */
|
||||||
|
question_id: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: {
|
||||||
|
/** @description Question rejected */
|
||||||
|
204: {
|
||||||
|
content: never;
|
||||||
|
};
|
||||||
|
404: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["ProblemDetails"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
reply_question: {
|
||||||
|
parameters: {
|
||||||
|
path: {
|
||||||
|
/** @description Session id */
|
||||||
|
session_id: string;
|
||||||
|
/** @description Question id */
|
||||||
|
question_id: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
requestBody: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["QuestionReplyRequest"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: {
|
||||||
|
/** @description Question answered */
|
||||||
|
204: {
|
||||||
|
content: never;
|
||||||
|
};
|
||||||
|
404: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["ProblemDetails"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export { SandboxDaemonClient, SandboxDaemonError, createSandboxDaemonClient } from "./client";
|
export { SandboxDaemonClient, SandboxDaemonError, createSandboxDaemonClient } from "./client.js";
|
||||||
export type {
|
export type {
|
||||||
AgentInfo,
|
AgentInfo,
|
||||||
AgentInstallRequest,
|
AgentInstallRequest,
|
||||||
|
|
@ -15,5 +15,5 @@ export type {
|
||||||
ProblemDetails,
|
ProblemDetails,
|
||||||
QuestionReplyRequest,
|
QuestionReplyRequest,
|
||||||
UniversalEvent,
|
UniversalEvent,
|
||||||
} from "./client";
|
} from "./client.js";
|
||||||
export type { components, paths } from "./generated/openapi";
|
export type { components, paths } from "./generated/openapi.js";
|
||||||
|
|
|
||||||
2
spec.md
2
spec.md
|
|
@ -89,7 +89,7 @@ POST /v1/sessions/{} (will install agent if not already installed)
|
||||||
agentSessionId?: string
|
agentSessionId?: string
|
||||||
}
|
}
|
||||||
- The client-provided session id is primary; `agentSessionId` is the underlying agent id (may be unknown until first prompt).
|
- The client-provided session id is primary; `agentSessionId` is the underlying agent id (may be unknown until first prompt).
|
||||||
- Auth uses the daemon-level token (`Authorization` / `x-sandbox-token`); per-session tokens are not supported.
|
- Auth uses the daemon-level token (`Authorization`); per-session tokens are not supported.
|
||||||
|
|
||||||
// agentMode vs permissionMode:
|
// agentMode vs permissionMode:
|
||||||
// - agentMode = what the agent DOES (behavior, system prompt)
|
// - agentMode = what the agent DOES (behavior, system prompt)
|
||||||
|
|
|
||||||
1
todo.md
1
todo.md
|
|
@ -75,6 +75,7 @@
|
||||||
- [x] Add instructions to run sandbox-agent (including CORS)
|
- [x] Add instructions to run sandbox-agent (including CORS)
|
||||||
- [x] Implement full agent UI covering all features
|
- [x] Implement full agent UI covering all features
|
||||||
- [x] Add HTTP request log with copyable curl command
|
- [x] Add HTTP request log with copyable curl command
|
||||||
|
- [x] Add Content-Type header to CORS callout command
|
||||||
|
|
||||||
## TypeScript SDK
|
## TypeScript SDK
|
||||||
- [x] Generate OpenAPI from utoipa and run `openapi-typescript`
|
- [x] Generate OpenAPI from utoipa and run `openapi-typescript`
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue