diff --git a/README.md b/README.md index 0b18527..5f841e2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # qmtacp CLI for a running QueryMT ACP WebSocket server (`qmtcode --acp-ws`). -Default endpoint is `ws://127.0.0.1:3030/ws`. +Default endpoint is `ws://127.0.0.1:3030/acp/ws`. Each invocation connects, initializes, does one job, and exits. Session ids are the only state. JSON goes to stdout; connection logs go to stderr. diff --git a/SKILL.md b/SKILL.md index 8a74a7d..32877c3 100644 --- a/SKILL.md +++ b/SKILL.md @@ -9,7 +9,7 @@ tags: ["querymt", "acp", "sessions", "automation", "orchestration", "qmtcode"] # qmtacp -Each invocation connects, does one job, and exits. Default URL: `ws://127.0.0.1:3030/ws`. +Each invocation connects, does one job, and exits. Default URL: `ws://127.0.0.1:3030/acp/ws`. The server owns session state. Keep the returned `sessionId`. - Do not invent session, profile, model, mode, effort, or URL values. Discover them (`caps`, `profiles`, `models`, `find`/`sessions`) or take them from JSON. @@ -45,7 +45,7 @@ All of these come *before* the subcommand: qmtacp [--url URL] [--allow-insecure] [--pretty] [--permission allow-once|reject-once|cancel] [--quiet] [--version] [--help] ``` -- `--url` / `-u`: `ws://`/`wss://` URL, or `host[:port][/path]`. Default `ws://127.0.0.1:3030/ws`. +- `--url` / `-u`: `ws://`/`wss://` URL, or `host[:port][/path]`. Default `ws://127.0.0.1:3030/acp/ws`. - `--allow-insecure`: required for plaintext `ws://` to non-loopback hosts. - `--pretty`: pretty JSON. Do not use on NDJSON streams. - `--quiet`: hide connection logs on stderr. diff --git a/src/main.rs b/src/main.rs index 7b9b54c..e3f60bb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,7 +25,7 @@ const VERSION: &str = concat!(env!("CARGO_PKG_VERSION"), " (", env!("QMTACP_GIT_ #[command(about = "JSON CLI for a running QueryMT ACP WebSocket server")] #[command(version = VERSION)] struct Cli { - /// ACP WebSocket URL or host[:port][/path]. Defaults to ws://127.0.0.1:3030/ws + /// ACP WebSocket URL or host[:port][/path]. Defaults to ws://127.0.0.1:3030/acp/ws #[arg(short, long, value_name = "url")] url: Option, diff --git a/src/url.rs b/src/url.rs index f605e5d..31933fb 100644 --- a/src/url.rs +++ b/src/url.rs @@ -3,7 +3,7 @@ use url::Url; pub const DEFAULT_HOST: &str = "127.0.0.1"; pub const DEFAULT_PORT: u16 = 3030; -pub const DEFAULT_PATH: &str = "/ws"; +pub const DEFAULT_PATH: &str = "/acp/ws"; pub fn normalize_acp_ws_url(value: &str, allow_insecure: bool) -> Result { let trimmed = value.trim(); @@ -122,16 +122,18 @@ mod tests { #[test] fn normalizes_websocket_urls_structurally() { let cases = [ - ("127.0.0.1", "ws://127.0.0.1:3030/ws"), - ("localhost", "ws://localhost:3030/ws"), - ("::1", "ws://[::1]:3030/ws"), - ("ws://[::1]", "ws://[::1]:3030/ws"), - ("ws://host:80", "ws://host:80/ws"), - ("wss://host:443", "wss://host:443/ws"), - ("ws://[::1]:80", "ws://[::1]:80/ws"), - ("ws://host:9000", "ws://host:9000/ws"), + ("127.0.0.1", "ws://127.0.0.1:3030/acp/ws"), + ("localhost", "ws://localhost:3030/acp/ws"), + ("::1", "ws://[::1]:3030/acp/ws"), + ("ws://[::1]", "ws://[::1]:3030/acp/ws"), + ("ws://host:80", "ws://host:80/acp/ws"), + ("wss://host:443", "wss://host:443/acp/ws"), + ("ws://[::1]:80", "ws://[::1]:80/acp/ws"), + ("ws://host:9000", "ws://host:9000/acp/ws"), ("host/custom", "ws://host:3030/custom"), - ("host?token=test", "ws://host:3030/ws?token=test"), + ("host?token=test", "ws://host:3030/acp/ws?token=test"), + ("ws://127.0.0.1:3030/acp/ws", "ws://127.0.0.1:3030/acp/ws"), + ("ws://127.0.0.1:3030/ws", "ws://127.0.0.1:3030/ws"), ( "wss://host:9443/custom?token=test", "wss://host:9443/custom?token=test", @@ -154,24 +156,24 @@ mod tests { assert!(normalize_acp_ws_url("ws://remote.example", false).is_err()); assert_eq!( normalize_acp_ws_url("wss://remote.example", false).unwrap(), - "wss://remote.example:3030/ws" + "wss://remote.example:3030/acp/ws" ); assert_eq!( normalize_acp_ws_url("localhost", false).unwrap(), - "ws://localhost:3030/ws" + "ws://localhost:3030/acp/ws" ); assert_eq!( normalize_acp_ws_url("::1", false).unwrap(), - "ws://[::1]:3030/ws" + "ws://[::1]:3030/acp/ws" ); } #[test] fn endpoint_label_redacts_credentials_query_and_fragment() { assert_eq!( - safe_endpoint_label("wss://user:secret@example.com:443/ws?token=secret#fragment") + safe_endpoint_label("wss://user:secret@example.com:443/acp/ws?token=secret#fragment") .unwrap(), - "wss://example.com:443/ws" + "wss://example.com:443/acp/ws" ); } }