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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
- run: pnpm test
- run: go mod tidy && git diff --exit-code -- go.mod go.sum
working-directory: packages/go-sdk
- run: make check-agent-instructions go-format-check go-vet go-coverage go-consumer-check
- run: make check-agent-instructions go-format-check go-doc-check go-vet go-coverage go-consumer-check

go-test:
runs-on: ubuntu-24.04
Expand Down
21 changes: 21 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,24 @@ jobs:
go mod init example.com/agentbox-release-smoke
GOPROXY=https://proxy.golang.org go get "github.com/abox-dev/sdk/packages/go-sdk@${GITHUB_REF_NAME}"
go test github.com/abox-dev/sdk/packages/go-sdk github.com/abox-dev/sdk/packages/go-sdk/codeinterpreter
- name: Wait for pkg.go.dev reference pages
env:
VERSION: ${{ github.ref_name }}
run: |
for package in \
"github.com/abox-dev/sdk/packages/go-sdk" \
"github.com/abox-dev/sdk/packages/go-sdk/codeinterpreter"
do
url="https://pkg.go.dev/${package}@${VERSION}"
available=false
for attempt in $(seq 1 30)
do
if curl --fail --silent --show-error --location --output /dev/null "$url"
then
available=true
break
fi
sleep 20
done
test "$available" = true
done
3 changes: 2 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ Use pnpm for JavaScript packages, uv for Python packages, and Go modules for Go
Use English exclusively in source code, comments, documentation, commit messages, and GitHub pull request titles and descriptions.
Keep the JavaScript, Python sync/async, and Go SDKs behaviorally aligned, including their Code Interpreter APIs.
Use only Go syntax and runtime dependencies compatible with the `go` directive in `packages/go-sdk/go.mod`.
Run format checks, lint, type checks, unit tests, deterministic generation, builds, package-install checks, and the Go race and coverage checks before committing. Handwritten Go code must keep at least 90% statement coverage; generated packages are excluded from the threshold.
Run format checks, lint, type checks, unit tests, deterministic generation, builds, package-install checks, the exported GoDoc gate, and the Go race and coverage checks before committing. Handwritten Go code must keep at least 90% statement coverage; generated packages are excluded from the threshold.
The API and envd snapshots under spec/ are generated from mono/infra. Do not edit them manually. Update them with `make sync-specs MONO_DIR=/path/to/mono`, then run `make generate`.
Generated clients must depend only on checked-in snapshots and never fetch network content during generation. Do not edit generated Go files under `packages/go-sdk/internal/gen` manually.
Generated SDK reference files under `reference/`, including `reference/sdk/go`, are owned by `make generate`; do not edit them manually. Keep `gomarkdoc` pinned as a build-only tool and do not emit source links to a floating branch.
Public APIs, package artifacts, examples, errors, environment variables, and headers must use AgentBox naming. Upstream names are allowed only in licenses, attribution, pinned build-only codegen tooling, and wire/protobuf namespaces that are required by the runtime protocol.
Default development credentials may be stored in `.env.local` or `~/.agentbox/config.json`; never print or commit them.

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

Open an issue or pull request at [abox-dev/sdk](https://github.com/abox-dev/sdk). Include tests for behavior changes and keep JavaScript, Python sync/async, and Go APIs aligned where applicable.

For Go changes, run `make go-check`. Generated clients under `packages/go-sdk/internal/gen` must be regenerated with `make generate` and must not be edited manually. `packages/go-sdk/go.mod` defines the minimum supported Go version; CI also tests every newer supported minor listed in `RELEASING.md`.
For Go changes, run `make go-check`. It includes the exported GoDoc gate. Generated clients under `packages/go-sdk/internal/gen` and Go reference pages under `reference/sdk/go` must be regenerated with `make generate` and must not be edited manually. `packages/go-sdk/go.mod` defines the minimum supported Go version; CI also tests every newer supported minor listed in `RELEASING.md`.

Use the development and generation commands documented in the root README. By contributing, you agree that your contribution is licensed under the license applicable to the package you modify.
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ CODEGEN_IMAGE ?= agentbox-sdk-codegen

.PHONY: generate generate-in-container generate-go codegen-image sync-specs \
go-format-check go-vet go-build go-test go-race go-coverage \
go-integration go-consumer-check go-check check-agent-instructions
go-doc-check go-integration go-consumer-check go-check check-agent-instructions

# Generate exclusively from the checked-in snapshots under spec/.
generate: codegen-image
Expand Down Expand Up @@ -33,6 +33,10 @@ check-agent-instructions:

go-format-check:
cd packages/go-sdk && ./scripts/check-go-format.sh
test -z "$$(gofmt -l scripts/check-go-docs.go)"

go-doc-check:
go run ./scripts/check-go-docs.go packages/go-sdk packages/go-sdk/codeinterpreter

go-vet:
cd packages/go-sdk && go vet ./...
Expand All @@ -55,7 +59,7 @@ go-integration:
go-consumer-check:
cd packages/go-sdk && ./scripts/test-go-consumer.sh

go-check: check-agent-instructions go-format-check go-vet go-build go-test go-race go-coverage go-consumer-check
go-check: check-agent-instructions go-format-check go-doc-check go-vet go-build go-test go-race go-coverage go-consumer-check

# Maintainer-only update from a local mono checkout.
sync-specs:
Expand Down
13 changes: 9 additions & 4 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ node scripts/check-release-versions.mjs vX.Y.Z
```

`release:version` updates the five workspace manifests, both Python
`pyproject.toml` files, and `packages/go-sdk/version.go`. Regenerate both Python lock files
rather than editing them by hand. Do not release any SDK packages at different
versions.
`pyproject.toml` files, `packages/go-sdk/version.go`, and the versioned
pkg.go.dev links in the Go README. Regenerate both Python lock files rather than
editing them by hand. Do not release any SDK packages at different versions.

## 3. Verify source and release artifacts

Expand Down Expand Up @@ -109,7 +109,8 @@ the tagged Go submodule. The `packages/go-sdk/vX.Y.Z` and `vX.Y.Z` tags must
point to the same commit. Go has no separate registry account or archive: the
immutable Git tag and Go checksum database are its published artifact. An
existing registry file is accepted only when its digest matches the newly built
artifact.
artifact. The release workflow also waits for the versioned core and Code
Interpreter pages to become available on pkg.go.dev.

## 6. Verify the published packages

Expand All @@ -122,6 +123,10 @@ packages into clean environments and repeat the KVM suite:

Also verify a clean Go consumer with
`GOPROXY=https://proxy.golang.org go get github.com/abox-dev/sdk/packages/go-sdk@vX.Y.Z`.
Confirm both versioned reference pages:

- `https://pkg.go.dev/github.com/abox-dev/sdk/packages/go-sdk@vX.Y.Z`;
- `https://pkg.go.dev/github.com/abox-dev/sdk/packages/go-sdk/codeinterpreter@vX.Y.Z`.

Supported Go CI versions are 1.24.x, 1.25.x, 1.26.x, and 1.27.x. Builds and
hermetic tests run on every row; race and coverage run on 1.27.x, while
Expand Down
3 changes: 2 additions & 1 deletion codegen.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ FROM golang:1.24.13 AS go-tools
RUN go install github.com/bufbuild/buf/cmd/buf@v1.50.1 && \
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.12 && \
go install connectrpc.com/connect/cmd/protoc-gen-connect-go@v1.19.1 && \
go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@v2.7.2
go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@v2.7.2 && \
go install github.com/princjef/gomarkdoc/cmd/gomarkdoc@v1.1.0


FROM python:3.10
Expand Down
3 changes: 3 additions & 0 deletions packages/go-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ func main() {
Code Interpreter is available from
`github.com/abox-dev/sdk/packages/go-sdk/codeinterpreter`.

API reference for this release: [core SDK on pkg.go.dev](https://pkg.go.dev/github.com/abox-dev/sdk/packages/go-sdk@v0.1.2) and
[Code Interpreter on pkg.go.dev](https://pkg.go.dev/github.com/abox-dev/sdk/packages/go-sdk/codeinterpreter@v0.1.2).

Documentation: [core SDK](https://docs.agentbox.ru/en/sdk/),
[sandboxes](https://docs.agentbox.ru/en/sdk/sandboxes/),
[templates](https://docs.agentbox.ru/en/sdk/templates/), and
Expand Down
22 changes: 20 additions & 2 deletions packages/go-sdk/codeinterpreter/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ import (
)

const (
DefaultTemplate = "code-interpreter"
// DefaultTemplate is the template used when Create receives no template.
DefaultTemplate = "code-interpreter"
// JupyterPort is the internal Code Interpreter service port.
JupyterPort = 49999
defaultExecutionTimeout = time.Minute
)

// Client wraps the core client with Code Interpreter creation helpers.
type Client struct{ Core *agentbox.Client }

// NewClient creates a Code Interpreter client using the core client options.
func NewClient(options ...agentbox.ClientOption) (*Client, error) {
client, err := agentbox.NewClient(options...)
if err != nil {
Expand All @@ -37,6 +40,7 @@ func NewClient(options ...agentbox.ClientOption) (*Client, error) {
// Sandbox is a core sandbox with notebook-kernel APIs.
type Sandbox struct{ *agentbox.Sandbox }

// Create creates a Code Interpreter sandbox.
func (client *Client) Create(ctx context.Context, options *agentbox.CreateSandboxOptions) (*Sandbox, error) {
if options == nil {
options = &agentbox.CreateSandboxOptions{}
Expand All @@ -53,6 +57,8 @@ func (client *Client) Create(ctx context.Context, options *agentbox.CreateSandbo
}
return &Sandbox{Sandbox: sandbox}, nil
}

// Connect attaches to an existing Code Interpreter sandbox.
func (client *Client) Connect(ctx context.Context, id string, options *agentbox.ConnectSandboxOptions) (*Sandbox, error) {
sandbox, err := client.Core.Sandboxes.Connect(ctx, id, options)
if err != nil {
Expand All @@ -65,8 +71,11 @@ func (client *Client) Connect(ctx context.Context, id string, options *agentbox.
type Language string

const (
Python Language = "python"
// Python selects a Python kernel.
Python Language = "python"
// JavaScript selects a JavaScript kernel.
JavaScript Language = "javascript"
// TypeScript selects a TypeScript kernel.
TypeScript Language = "typescript"
)

Expand All @@ -76,6 +85,8 @@ type Context struct {
Language string `json:"language"`
Cwd string `json:"cwd"`
}

// CreateContextOptions configures a persistent kernel context.
type CreateContextOptions struct {
Language Language `json:"language,omitempty"`
Cwd string `json:"cwd,omitempty"`
Expand Down Expand Up @@ -170,6 +181,7 @@ func (sandbox *Sandbox) RunCode(ctx context.Context, code string, options *RunCo
return execution, nil
}

// CreateContext creates a persistent kernel context.
func (sandbox *Sandbox) CreateContext(ctx context.Context, options *CreateContextOptions) (*Context, error) {
if options == nil {
options = &CreateContextOptions{}
Expand All @@ -180,19 +192,25 @@ func (sandbox *Sandbox) CreateContext(ctx context.Context, options *CreateContex
}
return &result, nil
}

// ListContexts returns all persistent kernel contexts in the sandbox.
func (sandbox *Sandbox) ListContexts(ctx context.Context) ([]Context, error) {
var result []Context
if err := sandbox.contextRequest(ctx, http.MethodGet, "/contexts", nil, 0, &result); err != nil {
return nil, err
}
return result, nil
}

// RemoveContext removes a persistent kernel context.
func (sandbox *Sandbox) RemoveContext(ctx context.Context, contextID string) error {
if strings.TrimSpace(contextID) == "" {
return &agentbox.InvalidArgumentError{Message: "context ID cannot be empty"}
}
return sandbox.contextRequest(ctx, http.MethodDelete, "/contexts/"+url.PathEscape(contextID), nil, 0, nil)
}

// RestartContext restarts a persistent kernel context.
func (sandbox *Sandbox) RestartContext(ctx context.Context, contextID string) error {
if strings.TrimSpace(contextID) == "" {
return &agentbox.InvalidArgumentError{Message: "context ID cannot be empty"}
Expand Down
54 changes: 41 additions & 13 deletions packages/go-sdk/codeinterpreter/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type OutputMessage struct {
Error bool
}

// String returns the output line.
func (message OutputMessage) String() string { return message.Line }

// ExecutionError is a kernel error and traceback.
Expand All @@ -23,19 +24,24 @@ type ExecutionError struct {
Traceback string `json:"traceback"`
}

// Error formats the kernel error name and value.
func (e ExecutionError) Error() string { return fmt.Sprintf("%s: %s", e.Name, e.Value) }

// Logs contains collected standard output and standard error lines.
type Logs struct {
Stdout []string `json:"stdout"`
Stderr []string `json:"stderr"`
}

// Execution contains the complete result of one code execution.
type Execution struct {
Results []Result `json:"results"`
Logs Logs `json:"logs"`
Error *ExecutionError `json:"error,omitempty"`
ExecutionCount int `json:"execution_count,omitempty"`
}

// Text returns the text representation of the main result, if present.
func (execution Execution) Text() string {
for _, result := range execution.Results {
if result.IsMainResult {
Expand All @@ -47,6 +53,8 @@ func (execution Execution) Text() string {

// RawData preserves every MIME representation returned by the kernel.
type RawData map[string]json.RawMessage

// Result contains the decoded and raw MIME representations of one result.
type Result struct {
Text, HTML, Markdown, SVG, PNG, JPEG, PDF, LaTeX, JSON, JavaScript string
Data map[string]any
Expand All @@ -56,6 +64,7 @@ type Result struct {
IsMainResult bool
}

// Formats returns the available raw MIME keys in sorted order.
func (result Result) Formats() []string {
formats := make([]string, 0, len(result.Raw))
for key := range result.Raw {
Expand All @@ -65,30 +74,48 @@ func (result Result) Formats() []string {
return formats
}

// ChartType identifies a supported chart representation.
type ChartType string

const (
ChartLine ChartType = "line"
ChartScatter ChartType = "scatter"
ChartBar ChartType = "bar"
ChartPie ChartType = "pie"
// ChartLine identifies a line chart.
ChartLine ChartType = "line"
// ChartScatter identifies a scatter chart.
ChartScatter ChartType = "scatter"
// ChartBar identifies a bar chart.
ChartBar ChartType = "bar"
// ChartPie identifies a pie chart.
ChartPie ChartType = "pie"
// ChartBoxAndWhisker identifies a box-and-whisker chart.
ChartBoxAndWhisker ChartType = "box_and_whisker"
ChartSuper ChartType = "superchart"
ChartUnknown ChartType = "unknown"
// ChartSuper identifies a composite chart.
ChartSuper ChartType = "superchart"
// ChartUnknown identifies a chart type unknown to this SDK version.
ChartUnknown ChartType = "unknown"
)

// ScaleType identifies a chart axis scale.
type ScaleType string

const (
ScaleLinear ScaleType = "linear"
ScaleDatetime ScaleType = "datetime"
// ScaleLinear identifies a linear scale.
ScaleLinear ScaleType = "linear"
// ScaleDatetime identifies a date and time scale.
ScaleDatetime ScaleType = "datetime"
// ScaleCategorical identifies a categorical scale.
ScaleCategorical ScaleType = "categorical"
ScaleLog ScaleType = "log"
ScaleSymlog ScaleType = "symlog"
ScaleLogit ScaleType = "logit"
ScaleFunction ScaleType = "function"
// ScaleLog identifies a logarithmic scale.
ScaleLog ScaleType = "log"
// ScaleSymlog identifies a symmetric logarithmic scale.
ScaleSymlog ScaleType = "symlog"
// ScaleLogit identifies a logit scale.
ScaleLogit ScaleType = "logit"
// ScaleFunction identifies a custom function scale.
ScaleFunction ScaleType = "function"
// ScaleFunctionLog identifies a logarithmic custom function scale.
ScaleFunctionLog ScaleType = "functionlog"
ScaleAsinh ScaleType = "asinh"
// ScaleAsinh identifies an inverse hyperbolic sine scale.
ScaleAsinh ScaleType = "asinh"
)

// Chart retains typed common chart properties and unknown fields in Extra.
Expand All @@ -105,6 +132,7 @@ type Chart struct {
Extra map[string]json.RawMessage `json:"-"`
}

// UnmarshalJSON decodes known chart fields and preserves unknown fields in Extra.
func (chart *Chart) UnmarshalJSON(data []byte) error {
type wire Chart
var value wire
Expand Down
1 change: 1 addition & 0 deletions packages/go-sdk/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type CommandExitError struct {
Message string
}

// Error describes the non-zero command exit code.
func (e *CommandExitError) Error() string {
if e.Message != "" {
return fmt.Sprintf("agentbox: command exited with code %d: %s", e.Result.ExitCode, e.Message)
Expand Down
Loading
Loading