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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions changelog.d/cli-studio-opener.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
- `omnigraph studio --target NAME [--graph G] [--json]` opens OmniGraph Studio
on a configured server target through an `omnigraph-studio://open` link,
prints the link and exits; it sends no request and reads no credential.
Direct and managed targets refuse, and where nothing on the platform opens
Studio's links it prints the link and refuses with `studio_unavailable`
instead of opening a browser. `target inspect --json` now reports the `home`
and, for a server target, `binding` digests the link carries, and
`version --json` reports `protocols.studio: 1`. See [Open Studio][cli-studio].

[cli-studio]: ../docs/user/cli/studio.md
4 changes: 4 additions & 0 deletions crates/omnigraph-api-types/src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,10 @@ pub const CLI_ONLY_OPERATIONS: &[CliOnlyOperation] = &[
"mcp",
"Relays the MCP protocol to an existing server; --write opts into write tools. It is not a graph HTTP command.",
),
cli_only(
"studio",
"Opens OmniGraph Studio on an existing server target through a link; it sends no request to the server and is not a graph HTTP command.",
),
cli_only("skill export", LOCAL),
cli_only("skill show", LOCAL),
cli_only("version", LOCAL),
Expand Down
14 changes: 14 additions & 0 deletions crates/omnigraph-cli/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,20 @@ async fn run_bound(
)
.await;
}
Command::Studio(args) => {
return commands::studio::run(
args,
commands::studio::StudioScope {
operator: &operator,
target: required_target(),
graph: cli.graph.as_deref(),
},
commands::studio::Platform::current(),
&mut commands::studio::SystemRunner,
stdout,
stderr,
);
}
Command::Skill { command } => commands::local::run_skill(command, stdout)?,
Command::Version { json } => commands::local::run_version(json, stdout)?,
Command::Embed(args) => commands::local::run_embed(args, stdout).await?,
Expand Down
12 changes: 12 additions & 0 deletions crates/omnigraph-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub(crate) use crate::commands::cluster::{ClusterCommand, ClusterMembersCommand,
pub(crate) use crate::commands::control::{GraphsCommand, PolicyCommand, QueriesCommand};
pub(crate) use crate::commands::local::SkillCommand;
pub(crate) use crate::commands::mcp::McpArgs;
pub(crate) use crate::commands::studio::StudioArgs;
pub(crate) use crate::commands::targets::{AccessArgs, CredentialCommand, TargetCommand};
pub(crate) use crate::managed::args::{
OrganizationArgs, OrganizationCommand, OrganizationInvitationsCommand,
Expand Down Expand Up @@ -220,6 +221,17 @@ pub(crate) enum Command {
/// discovers or hosts a server. stdout carries only MCP messages and
/// diagnostics go to stderr.
Mcp(McpArgs),
/// Open OmniGraph Studio on an existing server target, print its link
/// and exit.
///
/// The `omnigraph-studio://open` link names the target, `--graph` when
/// given, and digests of the target's binding and of this operator home,
/// which Studio checks against its own resolution of the target. It
/// carries no secret and acquires no credential. Direct and managed
/// targets refuse. Without Studio, or anything on this platform that
/// handles its links, it prints the link and refuses with
/// `studio_unavailable`; it never opens a browser.
Studio(StudioArgs),
#[command(
about = "Validate operator configuration, rename bindings, or recover interrupted edits"
)]
Expand Down
1 change: 1 addition & 0 deletions crates/omnigraph-cli/src/command_outcome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ pub(crate) fn kind(cli: &Cli) -> Option<CommandKind> {
| Command::Config { .. }
| Command::Credential { .. }
| Command::Mcp(_)
| Command::Studio(_)
| Command::Skill { .. }
| Command::Version { .. } => None,
}
Expand Down
2 changes: 2 additions & 0 deletions crates/omnigraph-cli/src/commands/local/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub(crate) struct VersionOutput {

#[derive(Debug, Serialize)]
pub(crate) struct ProtocolVersionsOutput {
pub(crate) studio: u32,
pub(crate) target: u32,
pub(crate) credential: u32,
pub(crate) access: u32,
Expand Down Expand Up @@ -64,6 +65,7 @@ impl VersionOutput {
commit: omnigraph_api_types::build::SOURCE_COMMIT,
http_contract: omnigraph_api_types::HTTP_API_CONTRACT,
protocols: ProtocolVersionsOutput {
studio: crate::targets::STUDIO_PROTOCOL,
target: crate::targets::TARGET_PROTOCOL,
credential: crate::targets::CREDENTIAL_PROTOCOL,
access: crate::targets::ACCESS_PROTOCOL,
Expand Down
1 change: 1 addition & 0 deletions crates/omnigraph-cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub(crate) mod maintenance;
pub(crate) mod mcp;
pub(crate) mod query;
pub(crate) mod schema;
pub(crate) mod studio;
pub(crate) mod transfer;

pub(crate) mod targets;
9 changes: 9 additions & 0 deletions crates/omnigraph-cli/src/commands/studio/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use clap::Args;

#[derive(Debug, Args)]
pub(crate) struct StudioArgs {
/// Print the link and its digests as one JSON object; a refusal to open
/// Studio still carries the link.
#[arg(long)]
pub(crate) json: bool,
}
Loading
Loading