Build SDK

Stainless-Generated-From: 2a73acd2a4ffa080db5d98c9d41ff2b64b8f3f91
This commit is contained in:
stlc-bot
2026-07-27 20:40:34 +00:00
parent 479c2eba44
commit 4cf32888b3
9 changed files with 36 additions and 59 deletions
+4 -4
View File
@@ -8,7 +8,7 @@ import (
// Run executes a command and waits for completion.
func (s *Sandbox) Run(ctx context.Context, body SandboxBoxRunParams, opts ...option.RequestOption) (*SandboxExecutionResult, error) {
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.Status, s.DataplaneURL)
if err != nil {
return nil, err
}
@@ -17,7 +17,7 @@ func (s *Sandbox) Run(ctx context.Context, body SandboxBoxRunParams, opts ...opt
// StartCommand starts a streaming command in this sandbox.
func (s *Sandbox) StartCommand(ctx context.Context, body SandboxCommandStartParams, opts ...option.RequestOption) (*SandboxCommandHandle, error) {
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.Status, s.DataplaneURL)
if err != nil {
return nil, err
}
@@ -27,7 +27,7 @@ func (s *Sandbox) StartCommand(ctx context.Context, body SandboxCommandStartPara
// RunWithCallbacks starts a WebSocket command, invokes callbacks for output,
// and waits for completion.
func (s *Sandbox) RunWithCallbacks(ctx context.Context, body SandboxCommandStartParams, callbacks SandboxCommandCallbacks, opts ...option.RequestOption) (*SandboxExecutionResult, error) {
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.Status, s.DataplaneURL)
if err != nil {
return nil, err
}
@@ -36,7 +36,7 @@ func (s *Sandbox) RunWithCallbacks(ctx context.Context, body SandboxCommandStart
// ReconnectCommand reconnects to a command stream.
func (s *Sandbox) ReconnectCommand(ctx context.Context, commandID string, body SandboxCommandReconnectParams, opts ...option.RequestOption) (*SandboxCommandHandle, error) {
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.Status, s.DataplaneURL)
if err != nil {
return nil, err
}
+7 -37
View File
@@ -9,7 +9,6 @@ import (
"testing"
"github.com/langchain-ai/langsmith-go/option"
"github.com/stretchr/testify/require"
)
func TestSandboxCommandWrapperRunUsesCurrentDataplaneURL(t *testing.T) {
@@ -55,46 +54,17 @@ func TestSandboxCommandWrapperRunUsesCurrentDataplaneURL(t *testing.T) {
}
}
func TestSandboxCommandWrapperDoesNotGateOnStatus(t *testing.T) {
var called bool
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
called = true
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{
"stdout": "ok",
"stderr": "",
"exit_code": 0,
})
}))
defer srv.Close()
func TestSandboxCommandWrapperRejectsNotReadySandbox(t *testing.T) {
sandbox := &Sandbox{
Name: "box-a",
Status: "stopped",
DataplaneURL: srv.URL,
boxes: NewSandboxBoxService(
option.WithBaseURL("http://control-plane.test"),
option.WithAPIKey("test-api-key"),
option.WithMaxRetries(0),
),
}
result, err := sandbox.Run(context.Background(), SandboxBoxRunParams{Command: String("echo ok")})
require.NoError(t, err)
require.True(t, called, "expected the dataplane request to be issued for a stopped sandbox")
require.Equal(t, "ok", result.Stdout)
}
func TestSandboxCommandWrapperRejectsMissingDataplaneURL(t *testing.T) {
sandbox := &Sandbox{
Name: "box-a",
boxes: NewSandboxBoxService(),
Status: "starting",
DataplaneURL: "https://sandbox.example",
boxes: NewSandboxBoxService(),
}
_, err := sandbox.Run(context.Background(), SandboxBoxRunParams{Command: String("echo ok")})
var notConfigured *SandboxDataplaneNotConfiguredError
if !errors.As(err, &notConfigured) {
t.Fatalf("expected SandboxDataplaneNotConfiguredError, got %T: %v", err, err)
var notReady *SandboxNotReadyError
if !errors.As(err, &notReady) {
t.Fatalf("expected SandboxNotReadyError, got %T: %v", err, err)
}
}
+4 -4
View File
@@ -102,7 +102,7 @@ func (r *SandboxBoxService) Run(ctx context.Context, name string, body SandboxBo
if err != nil {
return nil, err
}
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.Status, box.DataplaneURL)
if err != nil {
return nil, err
}
@@ -135,7 +135,7 @@ func (r *SandboxBoxService) StartCommand(ctx context.Context, name string, body
if err != nil {
return nil, err
}
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.Status, box.DataplaneURL)
if err != nil {
return nil, err
}
@@ -175,7 +175,7 @@ func (r *SandboxBoxService) StartCommandWithCallbacks(ctx context.Context, name
if err != nil {
return nil, err
}
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.Status, box.DataplaneURL)
if err != nil {
return nil, err
}
@@ -237,7 +237,7 @@ func (r *SandboxBoxService) ReconnectCommand(ctx context.Context, name string, c
if err != nil {
return nil, err
}
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.Status, box.DataplaneURL)
if err != nil {
return nil, err
}
+4 -4
View File
@@ -18,7 +18,7 @@ func (r *SandboxBoxService) ReadFile(ctx context.Context, name string, path stri
if err != nil {
return nil, err
}
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.Status, box.DataplaneURL)
if err != nil {
return nil, err
}
@@ -51,7 +51,7 @@ func (r *SandboxBoxService) WriteFile(ctx context.Context, name string, path str
if err != nil {
return err
}
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.Status, box.DataplaneURL)
if err != nil {
return err
}
@@ -94,7 +94,7 @@ func (r *SandboxBoxService) WriteFileWithDataplaneURL(ctx context.Context, datap
// ReadFile reads a file from this sandbox.
func (s *Sandbox) ReadFile(ctx context.Context, path string, opts ...option.RequestOption) ([]byte, error) {
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.Status, s.DataplaneURL)
if err != nil {
return nil, err
}
@@ -103,7 +103,7 @@ func (s *Sandbox) ReadFile(ctx context.Context, path string, opts ...option.Requ
// WriteFile writes bytes to a file in this sandbox.
func (s *Sandbox) WriteFile(ctx context.Context, path string, content []byte, opts ...option.RequestOption) error {
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.Status, s.DataplaneURL)
if err != nil {
return err
}
+4 -2
View File
@@ -34,8 +34,10 @@ func sandboxFieldValue[T any](field param.Field[T], fallback T) T {
return fallback
}
// requireSandboxDataplaneURL ignores lifecycle status: the platform resumes a stopped sandbox when the dataplane request arrives, and the server rejects a genuinely not-ready box.
func requireSandboxDataplaneURL(name string, dataplaneURL string) (string, error) {
func requireSandboxDataplaneURL(name string, status string, dataplaneURL string) (string, error) {
if status != "" && status != "ready" {
return "", &SandboxNotReadyError{SandboxName: name, Status: status}
}
if dataplaneURL == "" {
return "", &SandboxDataplaneNotConfiguredError{SandboxName: name}
}
+7 -2
View File
@@ -61,7 +61,7 @@ func TestSandboxInternalURLHelpers(t *testing.T) {
}
func TestRequireSandboxDataplaneURL(t *testing.T) {
got, err := requireSandboxDataplaneURL("box-a", "https://sandbox.example")
got, err := requireSandboxDataplaneURL("box-a", "ready", "https://sandbox.example")
if err != nil {
t.Fatalf("requireSandboxDataplaneURL returned error: %v", err)
}
@@ -69,8 +69,13 @@ func TestRequireSandboxDataplaneURL(t *testing.T) {
t.Fatalf("unexpected dataplane URL: %q", got)
}
var notReady *SandboxNotReadyError
if _, err := requireSandboxDataplaneURL("box-a", "starting", "https://sandbox.example"); !errors.As(err, &notReady) {
t.Fatalf("expected SandboxNotReadyError, got %T: %v", err, err)
}
var notConfigured *SandboxDataplaneNotConfiguredError
if _, err := requireSandboxDataplaneURL("box-a", ""); !errors.As(err, &notConfigured) {
if _, err := requireSandboxDataplaneURL("box-a", "ready", ""); !errors.As(err, &notConfigured) {
t.Fatalf("expected SandboxDataplaneNotConfiguredError, got %T: %v", err, err)
}
}
+1 -1
View File
@@ -93,8 +93,8 @@ func (s *Sandbox) Stop(ctx context.Context, opts ...option.RequestOption) error
if err := s.boxes.Stop(ctx, s.Name, opts...); err != nil {
return err
}
// DataplaneURL stays set: it is stable across stop/start and a request on it resumes the sandbox.
s.Status = "stopped"
s.DataplaneURL = ""
return nil
}
+1 -1
View File
@@ -137,7 +137,7 @@ func TestSandboxRefreshUpdateAndStop(t *testing.T) {
if err := sandbox.Stop(context.Background()); err != nil {
t.Fatalf("Stop returned error: %v", err)
}
if !stopped || sandbox.Status != "stopped" || sandbox.DataplaneURL != "https://sandbox.example/updated" {
if !stopped || sandbox.Status != "stopped" || sandbox.DataplaneURL != "" {
t.Fatalf("unexpected stopped state: stopped=%v sandbox=%#v", stopped, sandbox)
}
}
+4 -4
View File
@@ -103,7 +103,7 @@ func (r *SandboxBoxService) Tunnel(ctx context.Context, name string, remotePort
if err != nil {
return nil, err
}
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.Status, box.DataplaneURL)
if err != nil {
return nil, err
}
@@ -117,7 +117,7 @@ func (r *SandboxBoxService) OpenTunnelStream(ctx context.Context, name string, r
if err != nil {
return nil, err
}
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(box.Name, box.Status, box.DataplaneURL)
if err != nil {
return nil, err
}
@@ -169,7 +169,7 @@ func (r *SandboxBoxService) TunnelWithDataplaneURL(ctx context.Context, dataplan
// OpenTunnelStream opens a single TCP stream to a port inside this sandbox.
func (s *Sandbox) OpenTunnelStream(ctx context.Context, remotePort int, opts ...option.RequestOption) (*SandboxTunnelStream, error) {
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.Status, s.DataplaneURL)
if err != nil {
return nil, err
}
@@ -178,7 +178,7 @@ func (s *Sandbox) OpenTunnelStream(ctx context.Context, remotePort int, opts ...
// Tunnel opens a TCP tunnel from localhost to a port inside this sandbox.
func (s *Sandbox) Tunnel(ctx context.Context, remotePort int, params SandboxTunnelParams, opts ...option.RequestOption) (*SandboxTunnel, error) {
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.DataplaneURL)
dataplaneURL, err := requireSandboxDataplaneURL(s.Name, s.Status, s.DataplaneURL)
if err != nil {
return nil, err
}