Skip to content

feat(cli): add SageMaker streaming support - #142

Draft
GregHolmes wants to merge 1 commit into
mainfrom
gh/sagemaker-cli
Draft

GregHolmes wants to merge 1 commit into
mainfrom
gh/sagemaker-cli

Conversation

@GregHolmes

Copy link
Copy Markdown
Contributor

Summary

  • add optional SageMaker HTTP/2 streaming transport support
  • support SageMaker-backed Listen and Aura Speak commands using AWS credentials
  • validate transport limitations and cover SageMaker command behavior with unit tests

Testing

  • uv run pytest packages/deepctl-core/tests/unit/test_base.py packages/deepctl-cmd-listen/tests/unit/test_ws_and_routing.py packages/deepctl-cmd-speak/tests/unit/test_speak_command.py -k sagemaker
  • uv run ruff check packages/deepctl-core/src/deepctl_core/sagemaker.py packages/deepctl-core/src/deepctl_core/base_command.py packages/deepctl-cmd-listen/src/deepctl_cmd_listen/command.py packages/deepctl-cmd-speak/src/deepctl_cmd_speak/command.py

Further testing is ongoing before this PR is ready for review.

@GregHolmes

Copy link
Copy Markdown
Contributor Author

Further testing is ongoing before I ask for this PR to be reviewed.

dg-coreylweathers added a commit that referenced this pull request Nov 7, 2026
deepctl_core.transport.Transport owns where API requests go and what
they carry. The SDK facade builds its client through it. REST and
WebSocket base URLs come only from check_credential_host (http -> ws,
https -> wss), and Authorization is attached only after that check.

User-visible changes:
- One redirect refusal for REST and WebSocket: a 3xx is
  transport.RedirectRefused, the coded network_unavailable error
  (reason "unexpected redirect") with 0.4.1's text, which names both
  origins and says nothing was sent there (or no audio/text was sent,
  for a socket). for_status() maps every 3xx to it, so the client's own
  redirect check (_failed) and 0.4.1's separate ClickException go;
  deepctl_core.websocket re-exports the error and stays the only
  WebSocket open. Its message and exit_code read as before. Redirects
  were already refused; neither the key nor an upload body reaches
  another origin.
- A connection reset or closed after the request started (a read or
  write error, or the server disconnecting without a response) is
  network_unavailable with E-NETWORK-DROPPED ("dropped before the
  response was complete"). A reset while connecting, DNS and TLS
  failures keep E-NETWORK.
- DEEPGRAM_CLI_INSECURE now applies to the SDK's REST requests too, with
  0.4.1's rule: only 1 or true count, only localhost, 127.0.0.1 and
  [::1] skip certificate verification, every other host is verified
  (with one W-INSECURE-REMOTE warning), and AI agent sessions ignore it.
  The login client uses the same rule. WebSocket streaming, dg api and
  debug probe always verify.
- A WebSocket upgrade refused with an HTTP status maps through the same
  table as REST; DNS, connect and TLS failures map to
  network_unavailable, and an open that times out maps to timeout.
- The shared client keeps no cookies.

A backend seam (RestBackend by default) is where #142's SageMaker
backend plugs in. shared_client, map_exception and raise_for stay
module-level with unchanged signatures. dg whoami takes its default host
from hosts.DEFAULT_BASE_URL.

dg api takes its base URL from the Transport's host check and sends its
request on the process's client, so a dg api call opens one connection
like every other command. It still verifies TLS for every host, as in
0.4.1: when a person has DEEPGRAM_CLI_INSECURE set, dg api uses a
separate always-verified client, and a TLS failure on a loopback host
then says "DEEPGRAM_CLI_INSECURE doesn't apply to dg api, which always
verifies TLS certificates." It asks for no redirects, and keeps 0.4.1's
host scoping for the key.
GregHolmes pushed a commit that referenced this pull request Nov 12, 2026
deepctl_core.transport.Transport owns where API requests go and what
they carry. The SDK facade builds its client through it. REST and
WebSocket base URLs come only from check_credential_host (http -> ws,
https -> wss), and Authorization is attached only after that check.

User-visible changes:
- One redirect refusal for REST and WebSocket: a 3xx is
  transport.RedirectRefused, the coded network_unavailable error
  (reason "unexpected redirect") with 0.4.1's text, which names both
  origins and says nothing was sent there (or no audio/text was sent,
  for a socket). for_status() maps every 3xx to it, so the client's own
  redirect check (_failed) and 0.4.1's separate ClickException go;
  deepctl_core.websocket re-exports the error and stays the only
  WebSocket open. Its message and exit_code read as before. Redirects
  were already refused; neither the key nor an upload body reaches
  another origin.
- A connection reset or closed after the request started (a read or
  write error, or the server disconnecting without a response) is
  network_unavailable with E-NETWORK-DROPPED ("dropped before the
  response was complete"). A reset while connecting, DNS and TLS
  failures keep E-NETWORK.
- DEEPGRAM_CLI_INSECURE now applies to the SDK's REST requests too, with
  0.4.1's rule: only 1 or true count, only localhost, 127.0.0.1 and
  [::1] skip certificate verification, every other host is verified
  (with one W-INSECURE-REMOTE warning), and AI agent sessions ignore it.
  The login client uses the same rule. WebSocket streaming, dg api and
  debug probe always verify.
- A WebSocket upgrade refused with an HTTP status maps through the same
  table as REST; DNS, connect and TLS failures map to
  network_unavailable, and an open that times out maps to timeout.
- The shared client keeps no cookies.

A backend seam (RestBackend by default) is where #142's SageMaker
backend plugs in. shared_client, map_exception and raise_for stay
module-level with unchanged signatures. dg whoami takes its default host
from hosts.DEFAULT_BASE_URL.

dg api takes its base URL from the Transport's host check and sends its
request on the process's client, so a dg api call opens one connection
like every other command. It still verifies TLS for every host, as in
0.4.1: when a person has DEEPGRAM_CLI_INSECURE set, dg api uses a
separate always-verified client, and a TLS failure on a loopback host
then says "DEEPGRAM_CLI_INSECURE doesn't apply to dg api, which always
verifies TLS certificates." It asks for no redirects, and keeps 0.4.1's
host scoping for the key.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant