Files
Varsha 7139df8ca5 fix(exec): preserve output after stdin EOF and verify stream completion (#3359)
* fix(exec): preserve output after stdin EOF and verify stream completion

Signed-off-by: Varsha Prasad Narsing <varshaprasad96@gmail.com>

* test(exec): cover fair duplex progress and live SDK completion

Signed-off-by: Varsha Prasad Narsing <varshaprasad96@gmail.com>

* test(sdk): compare large exec buffers with native equality

Signed-off-by: Varsha Prasad Narsing <varshaprasad96@gmail.com>

* test(exec): use workspace-scoped sandbox name in EOF regression

Signed-off-by: Varsha Prasad Narsing <varshaprasad96@gmail.com>

---------

Signed-off-by: Varsha Prasad Narsing <varshaprasad96@gmail.com>
2026-09-22 14:11:06 +00:00

71 lines
2.7 KiB
Go

// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package v1
import (
"context"
"github.com/NVIDIA/OpenShell/sdk/go/openshell/v1/types"
)
// ExecResult holds the collected output of a completed command execution.
type ExecResult = types.ExecResult
// ExecChunk represents a single chunk of output from a streaming command execution.
type ExecChunk = types.ExecChunk
// ExecStream provides an iterator interface over streaming command output.
type ExecStream interface {
Next() (*ExecChunk, error)
ExitCode() (int, error)
Close() error
}
// InteractiveSession provides bidirectional I/O for interactive command execution.
type InteractiveSession interface {
Read(p []byte) (int, error)
Write(p []byte) (int, error)
Resize(cols, rows uint32) error
// ExitCode waits for final stream completion. An observed exit code is
// returned alongside any later transport error. Drain Read concurrently.
ExitCode() (int, error)
Close() error
}
// InteractiveSessionControl adds optional input closure and cancellation to
// InteractiveSession without requiring existing implementations to add methods.
// Sessions returned by this SDK implement both interfaces.
type InteractiveSessionControl interface {
InteractiveSession
// CloseWrite ends stdin and resize input without cancelling output.
CloseWrite() error
// Cancel aborts the RPC. Close retains the same full-close behavior.
Cancel() error
}
// CloseInteractiveInput ends input while preserving output when supported.
// Unsupported sessions return ErrorUnimplemented and are left open.
func CloseInteractiveInput(session InteractiveSession) error {
if closer, ok := session.(interface{ CloseWrite() error }); ok {
return closer.CloseWrite()
}
return &StatusError{Code: ErrorUnimplemented, Message: "interactive session does not support closing input independently"}
}
// CancelInteractive aborts a session, falling back to the original Close contract.
func CancelInteractive(session InteractiveSession) error {
if canceler, ok := session.(interface{ Cancel() error }); ok {
return canceler.Cancel()
}
return session.Close()
}
// ExecInterface defines command execution operations on sandboxes.
// Methods accept a sandbox name and resolve it to an ID internally.
type ExecInterface interface {
Run(ctx context.Context, workspace, sandboxName string, command []string, opts ...ExecOptions) (*ExecResult, error)
Stream(ctx context.Context, workspace, sandboxName string, command []string, opts ...ExecOptions) (ExecStream, error)
Interactive(ctx context.Context, workspace, sandboxName string, command []string, cols, rows uint32, opts ...ExecOptions) (InteractiveSession, error)
}