Skip to content
Closed
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/openshell-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,7 @@ enum CliProviderType {
Nvidia,
Gitlab,
Github,
Kode,
Outlook,
}

Expand Down Expand Up @@ -613,6 +614,7 @@ impl CliProviderType {
Self::Nvidia => "nvidia",
Self::Gitlab => "gitlab",
Self::Github => "github",
Self::Kode => "kode",
Self::Outlook => "outlook",
}
}
Expand Down
3 changes: 3 additions & 0 deletions crates/openshell-providers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ impl ProviderRegistry {
registry.register(providers::nvidia::NvidiaProvider);
registry.register(providers::gitlab::GitlabProvider);
registry.register(providers::github::GithubProvider);
registry.register(providers::kode::KodeProvider);
registry.register(providers::outlook::OutlookProvider);
registry
}
Expand Down Expand Up @@ -135,6 +136,7 @@ pub fn normalize_provider_type(input: &str) -> Option<&'static str> {
"nvidia" => Some("nvidia"),
"gitlab" | "glab" => Some("gitlab"),
"github" | "gh" => Some("github"),
"kode" => Some("kode"),
"outlook" => Some("outlook"),
_ => None,
}
Expand Down Expand Up @@ -164,6 +166,7 @@ mod tests {
assert_eq!(normalize_provider_type("openai"), Some("openai"));
assert_eq!(normalize_provider_type("anthropic"), Some("anthropic"));
assert_eq!(normalize_provider_type("nvidia"), Some("nvidia"));
assert_eq!(normalize_provider_type("kode"), Some("kode"));
assert_eq!(normalize_provider_type("unknown"), None);
}

Expand Down
58 changes: 58 additions & 0 deletions crates/openshell-providers/src/providers/kode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::{
ProviderDiscoverySpec, ProviderError, ProviderPlugin, RealDiscoveryContext, discover_with_spec,
};

pub struct KodeProvider;

pub const SPEC: ProviderDiscoverySpec = ProviderDiscoverySpec {
id: "kode",
credential_env_vars: &["ANTHROPIC_API_KEY", "OPENAI_API_KEY"],
};

impl ProviderPlugin for KodeProvider {
fn id(&self) -> &'static str {
SPEC.id
}

fn discover_existing(&self) -> Result<Option<crate::DiscoveredProvider>, ProviderError> {
discover_with_spec(&SPEC, &RealDiscoveryContext)
}

fn credential_env_vars(&self) -> &'static [&'static str] {
SPEC.credential_env_vars
}
}

#[cfg(test)]
mod tests {
use super::SPEC;
use crate::discover_with_spec;
use crate::test_helpers::MockDiscoveryContext;

#[test]
fn discovers_kode_anthropic_credentials() {
let ctx = MockDiscoveryContext::new().with_env("ANTHROPIC_API_KEY", "test-key");
let discovered = discover_with_spec(&SPEC, &ctx)
.expect("discovery")
.expect("provider");
assert_eq!(
discovered.credentials.get("ANTHROPIC_API_KEY"),
Some(&"test-key".to_string())
);
}

#[test]
fn discovers_kode_openai_credentials() {
let ctx = MockDiscoveryContext::new().with_env("OPENAI_API_KEY", "test-key");
let discovered = discover_with_spec(&SPEC, &ctx)
.expect("discovery")
.expect("provider");
assert_eq!(
discovered.credentials.get("OPENAI_API_KEY"),
Some(&"test-key".to_string())
);
}
}
1 change: 1 addition & 0 deletions crates/openshell-providers/src/providers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod claude;
pub mod codex;
pub mod generic;
pub mod github;
pub mod kode;
pub mod gitlab;
pub mod nvidia;
pub mod openai;
Expand Down
9 changes: 9 additions & 0 deletions crates/openshell-sandbox/testdata/sandbox-policy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ network_policies:
- { path: /usr/local/bin/claude }
- { path: /usr/bin/node }

kode_agent:
name: kode_agent
endpoints:
- { host: api.anthropic.com, port: 443 }
- { host: api.openai.com, port: 443 }
binaries:
- { path: /usr/local/bin/kode }
- { path: /usr/bin/node }

github_ssh_over_https:
name: github-ssh-over-https
endpoints:
Expand Down
1 change: 1 addition & 0 deletions docs/about/supported-agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ The following table summarizes the agents that run in OpenShell sandboxes. All a
| Agent | Source | Default Policy | Notes |
|---|---|---|---|
| [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | [`base`](https://github.com/NVIDIA/OpenShell-Community/tree/main/sandboxes/base) | Full coverage | Works out of the box. Requires `ANTHROPIC_API_KEY`. |
| [Kode](https://github.com/shareAI-lab/Kode-Agent) | [`base`](https://github.com/NVIDIA/OpenShell-Community/tree/main/sandboxes/base) | Full coverage | Multi-model AI coding agent. Requires `ANTHROPIC_API_KEY` and/or `OPENAI_API_KEY`. |
| [OpenCode](https://opencode.ai/) | [`base`](https://github.com/NVIDIA/OpenShell-Community/tree/main/sandboxes/base) | Partial coverage | Pre-installed. Add `opencode.ai` endpoint and OpenCode binary paths to the policy for full functionality. |
| [Codex](https://developers.openai.com/codex) | [`base`](https://github.com/NVIDIA/OpenShell-Community/tree/main/sandboxes/base) | No coverage | Pre-installed. Requires a custom policy with OpenAI endpoints and Codex binary paths. Requires `OPENAI_API_KEY`. |
| [OpenClaw](https://openclaw.ai/) | [`openclaw`](https://github.com/NVIDIA/OpenShell-Community/tree/main/sandboxes/openclaw) | Bundled | Agent orchestration layer. Launch with `openshell sandbox create --from openclaw`. |
Expand Down
1 change: 1 addition & 0 deletions docs/reference/default-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ The following table shows the coverage of the default policy for common agents.
| Agent | Coverage | Action Required |
|---|---|---|
| Claude Code | Full | None. Works out of the box. |
| Kode | Full | None. Works out of the box. |
| OpenCode | Partial | Add `opencode.ai` endpoint and OpenCode binary paths. |
| Codex | None | Provide a complete custom policy with OpenAI endpoints and Codex binary paths. |

Expand Down
Loading