sdkadapter

package
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 30, 2026 License: AGPL-3.0 Imports: 22 Imported by: 0

Documentation

Overview

Package sdkadapter - shared approval types.

ApprovalResult and ApprovalStanding live in this package rather than internal/agent because internal/sdkadapter already imports nothing from internal/agent (the dependency direction is internal/agent -> internal/sdkadapter, and reversing it would create a cycle). The agent loop's Options.ApprovalGate / Options.ApprovalStanding fields reference these types directly.

The values produced by an Approver bridge flow from a real agent's internal/uiadapter port through this package's type, so the wire shape is the same for the legacy and SDK paths.

Package sdkadapter bridges CLI types and SDK types for the SDK convergence work tracked at internal/sdkadapter. Each bridge file in this package maps a pair of types that share an intent but differ in field shape: the CLI shapes here come from internal/{provider,tools,skills,hooks,contentref,reasoning, ledger}; the SDK shapes come from github.com/MiviaLabs/mivia-ai-sdk.

This package is the only seam between the CLI runtime and the SDK. It is permitted to import CLI packages and it is permitted to import SDK packages, but nothing else in the tree may import both: doing so would let a shape drift propagate. The .mivia/policy/import-layers.json row for internal/sdkadapter is the contract that pins this seam.

Each bridge file has a companion <name>_test.go whose table of tests is the round-trip surface: convert CLI -> SDK -> CLI (or write a struct, read its bridge output, and assert the key fields). New behaviour that gains its own test must NOT be added here unless it lives in the corresponding bridge file; the round-trip tests are the proof that the bridge is shape-faithful.

Package sdkadapter — MCP bridge.

The CLI's internal/mcp/ package is the full lifecycle host: per-server process management (executable_unix.go / executable_other.go), the in-memory manager (manager.go), the tool render and wrap pipeline (render.go, tool.go), the redaction and schema-byte-cap enforcement (sanitizeToolDescription / sanitizeToolSchema), the host-safe tool-name encoder (config.go: EncodeToolName), and the inbound reader that pipes stdio into the SDK's Transport. None of these move to the SDK; they are CLI product code.

This file re-exports the SDK's mcp.Client so future code that wants the canonical SDK shape (e.g. a codeintel analyzer driving an MCP server, or a future slash command that surfaces an SDK-shaped tool list) reaches it through the bridge without importing the SDK directly. The CLI's internal/mcp/ continues to wrap the SDK with the redaction, schema-byte-cap, and tool-name-encoding wrappers per the binding plan's B.2 #11 row; the bridge is the entry point, not a replacement.

Package sdkadapter - CLI-to-SDK tool-registry converter.

The CLI's internal/tools.Registry and the SDK's tools.Registry are distinct types in distinct modules. The SDK loop consumes only the SDK shape, so the bridge converts the CLI registry: every CLI tool wraps as an SDK tool plus tools.SchemaTool.

SchemaTool is required, not optional: the SDK's Definitions helper fails closed with ErrNoSchemas when a non-empty registry holds no schema-publishing tool. The schema is the json.Marshal of the CLI tool's Parameters() map - the same OpenAI-parameters object the CLI's OpenAITools() publishes today.

ConvertToolRegistryWithAdmission adds the legacy CLI's per-call staged/unadmitted predicates (see internal/agent/loop_tool_exec.go:13-27) on top of the standard wrapper: a predicate answering true returns a denial string wrapped in tools.Out, which the SDK renders as a RoleTool message so the model retries on the next iteration. Per-call evaluation keeps the UnadmittedHandler auto-stage side effect (see internal/agent/options.go:108-117) firing only when the model actually invokes the unadmitted tool.

The ref-only shim lives in the agent package (internal/agent/refonly_shim.go) and is applied after this converter. It cannot live here because *remainder.Spool already imports sdkadapter for sdkadapter.Mint; placing the shim in sdkadapter would create an import cycle. See docs/development/sdk-backend-field-mapping.md for the wider rationale.

Package sdkadapter — usage bridge.

Accumulator re-exports the SDK's per-session usage.Accumulator. The CLI reaches the bridge, never the SDK directly, so the SDK dependency stays inside internal/sdkadapter. The bridge is a type alias on purpose: local code that has *sdkusage.Accumulator via the SDK's own wiring (B.2 #8, when it lands) shares the same pointer the bridge returns, and methods dispatched through either name reach the same Record/Total/Reset implementation without a wrapper allocation.

Package sdkadapter — workspace bridge.

The CLI's internal/workspace/ package is the full lifecycle host: the mivia-specific namespacing helpers (AgentsPath, SkillsDir, SessionsDir, WorktreesDir, ContextStorePath, MemoryDBPath) in namespace.go, the os.Root-based sandbox primitives in root.go, and the longpath platform handling in longpath_unix.go / longpath_windows.go. None of these move to the SDK; they are CLI product code (the namespacing) or product-specific primitives (the longpath handling).

This file re-exports the SDK's workspace.Workspace, Options, and the four sentinels (ErrEscape, ErrInvalidLimit, ErrSecretPath, ErrTooLarge) so future code that wants the canonical SDK sandbox shape reaches it through the bridge without importing the SDK directly. The CLI's internal/workspace/ continues to be where the namespacing and platform handling live; the bridge is the entry point, not a replacement.

Index

Constants

View Source
const (
	KindOutput    = "output"
	KindError     = "error"
	KindMessage   = "message"
	KindToolCalls = "tool_calls"
	KindNote      = "note"
)

Reference kinds for content-addressed task results and agent messages. The bridge owns the CLI kind vocabulary: every package that needs to emit or recognise a "ref:<kind>:<digest>" string imports these constants from internal/sdkadapter instead of minting its own. Five kinds cover every content reference today: tool output, tool error, agent-to-agent message bodies, a subagent's recorded tool-call step trace (handed to the model by reference as tool_calls_ref on task result envelopes, pageable via ledger_read), and note. A note is model-authored content stored by the store_note tool; it is distinct from ref:output:, which a coordinator attests as a task's recorded output.

View Source
const DefaultMaxReadBytes = sdkws.DefaultMaxReadBytes

DefaultMaxReadBytes re-exports the SDK's DefaultMaxReadBytes (10 MiB) so CLI callers can reference the constant through the bridge without an extra SDK import.

View Source
const Unbounded = sdkws.Unbounded

Unbounded re-exports the SDK's Unbounded sentinel (-1) that signals "no read-size cap" to ReadFileLimit.

Variables

View Source
var (
	ErrBlankSessionID = sdkusage.ErrBlankSessionID
	ErrNilAccumulator = sdkusage.ErrNilAccumulator
	ErrNilCompleter   = sdkusage.ErrNilCompleter
)

Re-exported sentinels so CLI callers can errors.Is against sdkadapter.ErrBlankSessionID without an extra SDK import.

View Source
var (
	ErrEscape       = sdkws.ErrEscape
	ErrInvalidLimit = sdkws.ErrInvalidLimit
	ErrSecretPath   = sdkws.ErrSecretPath
	ErrTooLarge     = sdkws.ErrTooLarge
)

Re-exported sentinels so CLI callers can errors.Is against sdkadapter.ErrEscape etc. without an extra SDK import.

View Source
var ErrClosed = sdkmcp.ErrClosed

ErrClosed re-exports the SDK's ErrClosed sentinel so CLI callers can errors.Is against sdkadapter.ErrClosed without an extra SDK import.

View Source
var ErrMalformedReference = errors.New("sdkadapter: malformed content reference")

ErrMalformedReference is the bridge's fail-closed response when Parse sees a string that is neither a CLI reference nor an SDK reference.

View Source
var UsageCachedTokensUnsupportedErr = fmt.Errorf("sdkadapter: SDK Usage.CachedTokens has no CLI equivalent")

UsageCachedTokensUnsupportedErr is the error returned by SDKUsageToTokenUsage when the SDK side reports a non-zero CachedTokens value. The CLI's TokenUsage shape carries no cache token count: a bridge that silently dropped the value would under-report cache reuse, so the bridge refuses the conversion instead.

Functions

func BridgeCapableTool

func BridgeCapableTool(t tools.CapableTool) *capableToolBridge

BridgeCapableTool wraps a CLI tools.CapableTool so the SDK's ProfiledTool interface (and only that interface) can call its Capability method through the bridge. The wrapped value carries the class, resource key, and timeout through one Round-Trip call; tool execution is intentionally not bridged - the CLI runtime is what actually runs tools today, and exposing Run on the SDK side would hand a second execution path to a Tool that does not know about it.

func CLISkillToSDK

func CLISkillToSDK(d skills.Definition) sdkshape.Skill

CLISkillToSDK converts a CLI Definition into the SDK-shaped Skill. The reverse direction only carries the four fields the SDK can store; the 13 product-layer fields are dropped (see SDKSkillToCLI for the rationale).

Field mapping:

  • CLI Triggers -> SDK Triggers.
  • CLI Tools -> SDK RequiredTools.
  • CLI Name, Instructions -> SDK Name, Instructions verbatim.

func CapabilityToExecutionProfile

func CapabilityToExecutionProfile(c tools.Capability) sdkshape.ExecutionProfile

CapabilityToExecutionProfile maps the CLI's tools.Capability onto the SDK's tools.ExecutionProfile. Class, ResourceKey, and Timeout are preserved verbatim; MaxResultBytes is dropped because the SDK ExecutionProfile has no equivalent. The class conversion uses the three named classes by string identity; an out-of-enum CLI class (zero value or future expansion) maps to the SDK's ExecutionClassUnclassified so the bridge never invents a Class.

func ChatStream

func ChatStream(ctx context.Context, c provider.Completer, _ sdkshape.Request, w io.Writer) (string, error)

ChatStream proxies a ChatStream call from the SDK-shaped Request onto a CLI-shaped Completer and writes the assistant's text deltas into w. The returned string is the complete assistant content; the writer receives the same content in arrival order. The CLI Completer takes a Request plus an io.Writer; the SDK Completer takes a Request and returns a <-chan Chunk. This bridge lives entirely on the CLI side because the CLI runtime is what actually produces text today.

func ConvertToolRegistry

func ConvertToolRegistry(cliReg *tools.Registry, regOpts ...sdktools.Option) (*sdktools.Registry, error)

ConvertToolRegistry converts a CLI registry to an SDK registry. A nil input returns a nil output; the SDK's Options.Validate reports ErrNoTools for the nil registry, which names the real problem. Add errors (blank name, duplicate name) wrap with the offending tool's name so the operator can find the duplicate.

regOpts (for example sdktools.WithDefaultRunTimeout) are forwarded verbatim to the SDK's New. Without an explicit run-timeout option the SDK bounds every no-profile tool at its hardcoded DefaultRunTimeout (10 minutes); callers that arm their own per-call deadlines pass sdktools.WithDefaultRunTimeout(sdktools.TimeoutNone) to keep the SDK backstop from being tighter than their declared budgets.

func ConvertToolRegistryWithAdmission

func ConvertToolRegistryWithAdmission(cliReg *tools.Registry, pred AdmissionPredicates, regOpts ...sdktools.Option) (*sdktools.Registry, error)

ConvertToolRegistryWithAdmission converts a CLI registry to an SDK registry, wrapping each tool with the admission predicates. A nil pred produces the same result as ConvertToolRegistry. The check runs at call time so UnadmittedHandler's auto-stage side effect fires only when the model actually invokes the unadmitted tool.

When pred.ApprovalGate is non-nil, an approval layer is added OUTSIDE the admission layer: the admission checks (staged / unadmitted) run first; if those pass, the approval gate runs before the inner CLI tool. Layering order matters - a staged tool never reaches the approval gate. regOpts (for example sdktools.WithDefaultRunTimeout) are forwarded verbatim to the SDK's New, so the registry-wide run-timeout backstop is the caller's choice rather than the SDK's hardcoded default.

func ExecutionProfileToCapability

func ExecutionProfileToCapability(p sdkshape.ExecutionProfile) tools.Capability

ExecutionProfileToCapability maps the SDK's tools.ExecutionProfile onto the CLI's tools.Capability. Class, ResourceKey, and Timeout round-trip; MaxResultBytes is the zero value because the SDK ExecutionProfile has no equivalent.

The SDK ExecutionClassUnclassified ("") maps to the CLI zero class (i.e. ExecutionRead=0). A reverse bridge that mapped all SDK classes onto the highest-risk CLI class would silently over-classify unclassified tools; the zero-value mapping is the conservative default the runtime already relies on.

func IsAlwaysApproval

func IsAlwaysApproval(policy string) bool

IsAlwaysApproval reports whether the policy represents always-prompt.

func IsAutoApproval

func IsAutoApproval(policy string) bool

IsAutoApproval reports whether the policy represents auto-approval.

func IsDenyApproval

func IsDenyApproval(policy string) bool

IsDenyApproval reports whether the policy represents auto-deny: every gated tool call is rejected without a prompt (the "deny" settings-screen choice, config.ApprovalPolicyDeny).

func LevelToReasoningEffort

func LevelToReasoningEffort(l reasoning.Level) (sdkshape.ReasoningEffort, bool)

LevelToReasoningEffort maps the CLI's provider-neutral reasoning Level (eight values: off, minimal, low, medium, high, xhigh, max, auto) onto the SDK's ReasoningEffort (four values: none, low, medium, high). The empty Level maps to the empty SDK effort, which is the SDK's "send no reasoning field" reading.

Returns (effort, true) for the four levels the SDK has a constant for and for the empty Level; (empty, false) for levels that have no SDK analogue (minimal, xhigh, max, auto). The boolean lets the caller distinguish "the SDK has no surface for this" from "the user did not pick a level": a (false) result is a refused conversion, not a default.

The mapping is product-specific: it encodes CLI's decisions about which CLI configs survive the cutover to the SDK wire shape. It lives here (not in internal/reasoning) because internal/sdkadapter is the only package permitted to import both CLI and SDK shapes; placing the bridge in internal/reasoning would force the SDK dependency onto every caller of that package and would break internal/reasoning's deliberate stdlib-only contract (reasoning.go:5-7).

func Mint

func Mint(kind string, data []byte) string

Mint returns a content reference for data. The shape depends on kind: a non-empty kind produces the CLI "ref:<kind>:<hex>" shape by inlining the SDK digest and prefixing with "ref:<kind>:"; an empty kind produces the SDK "sha256:<hex>" shape.

The CLI shape is computed inline here rather than delegated to a second package, so this file is the one canonical minter for the CLI shape. The SDK shape is delegated to contextstate.Mint. The bridge never invents a hybrid; callers pick the shape they need by passing or omitting kind.

func Parse

func Parse(ref string) (kind, digest string, err error)

Parse splits a content reference into its (kind, digest) pair. The returned kind is the CLI kind (output, error, message) when the input is the CLI "ref:<kind>:<hex>" shape; it is empty when the input is the SDK "sha256:<hex>" shape, because the SDK shape carries no kind.

Both formats are accepted forever; see migrationWindow.

func PayloadFromAny

func PayloadFromAny(payload any) (hooks.Payload, error)

PayloadFromAny converts an SDK-supplied payload into the CLI's hooks.Payload shape. Two payload formats are accepted: a map[string]any (the natural shape from a SDK handler call site) and a JSON-encoded byte slice (the wire shape an SDK transport produces). Any other type is rejected with a descriptive error.

func SDKSkillToCLI

func SDKSkillToCLI(s sdkshape.Skill) skills.Definition

SDKSkillToCLI converts an SDK-shaped Skill into the CLI's skills.Definition. The SDK carries four fields the CLI cares about: Name, Instructions, Triggers, RequiredTools. RequiredTools maps onto the CLI's Tools field.

The CLI Definition carries 13 product-layer fields the SDK cannot represent (Version, Scope, Origin, Permission, Description, ShortDescription, ArgsHint, UserInvocable, Timeout, Budget, InputSchema, OutputSchema, Resources). They are deliberately not surfaced; populating them with defaults would invent behaviour the SDK did not opt into.

func SDKUsageToTokenUsage

func SDKUsageToTokenUsage(u sdkshape.Usage) (provider.TokenUsage, error)

SDKUsageToTokenUsage maps the SDK's Usage onto the CLI's TokenUsage. It refuses a non-zero CachedTokens via UsageCachedTokensUnsupportedErr so the caller can decide whether to surface the cache count somewhere else; the reverse direction is not symmetric because the CLI shape carries no cache token field. TotalTokens is dropped: the CLI does not store it.

func TokenUsageToSDKUsage

func TokenUsageToSDKUsage(t provider.TokenUsage) sdkshape.Usage

TokenUsageToSDKUsage maps the CLI's TokenUsage onto the SDK's Usage. A CLI-side Reported=false becomes the SDK's zero Usage, the only shape the SDK has for "no observation". TotalTokens is computed by the SDK side from prompt + completion and is not preserved across the reverse bridge.

func WrapCompleter

func WrapCompleter(sessionID string, a *Accumulator, c provider.Completer) (provider.Completer, error)

WrapCompleter returns a provider.Completer that records every completed Chat turn's usage under sessionID in a.

func WrapRegistryWithAdmission

func WrapRegistryWithAdmission(sdkReg *sdktools.Registry, cliReg *tools.Registry, pred AdmissionPredicates) error

WrapRegistryWithAdmission wraps each tool in sdkReg with the admission and approval predicates corresponding to cliReg.

func WrapToolWithAdmission

func WrapToolWithAdmission(inner sdktools.Tool, cliTool tools.Tool, pred AdmissionPredicates) sdktools.Tool

WrapToolWithAdmission wraps one already-converted SDK tool with approval and admission layers according to pred.

Types

type Accumulator

type Accumulator = sdkusage.Accumulator

Accumulator re-exports the SDK's per-session usage.Accumulator. See the package doc for why the bridge is a type alias.

func NewAccumulator

func NewAccumulator() *Accumulator

NewAccumulator returns an empty SDK Accumulator ready to record.

type AdmissionPredicates

type AdmissionPredicates struct {
	// StagedMessage answers whether name is a tool staged for
	// publication. The returned message becomes the RoleTool denial
	// content when true. nil disables the check.
	StagedMessage func(name string) (string, bool)
	// UnadmittedHandler answers whether name is a tool advertised but
	// not yet admitted for execution. The handler may auto-stage the
	// tool for publication at the next step boundary as a side
	// effect; the returned message becomes the RoleTool denial
	// content when true. nil disables the check.
	UnadmittedHandler func(ctx context.Context, name string) (string, bool)
	// ApprovalGate, when non-nil, is invoked before the tool runs for
	// any tool whose internal Capability.Class >= tools.ExecutionWrite.
	// Read-class tools skip the gate. The verdict drives the wrap
	// layer added below: Approved true delegates to the inner CLI
	// tool; Approved false returns the denial Err as the RoleTool
	// content (mirroring the staged/unadmitted denial shape).
	ApprovalGate func(ctx context.Context, name string, args json.RawMessage) ApprovalResult
	// ApprovalStanding is consulted BEFORE ApprovalGate to honor
	// "always" decisions. The same instance must be shared across
	// legacy and SDK paths within one session so a "always" decision
	// persists across backends.
	ApprovalStanding *ApprovalStanding
	// ApprovalPolicy controls tool execution approval policy ("write-only", "auto", "always").
	ApprovalPolicy string
	// EmitPending publishes a "tool pending approval" advisory from
	// inside the SDK wrapper, before invoking the gate. The fields
	// are the bridge primitives so the wrapper does not need to
	// import internal/agent (the agent package imports sdkadapter;
	// reversing that direction would create a cycle). The caller
	// reconstructs an agent.Event and routes it through the same
	// emit path the legacy loop uses (OnEvent + EventBus). nil
	// disables the surface (the bridge still runs; the wrapper
	// just does not publish the pending event).
	//
	// toolCallID is the in-flight call's id (toolcallctx.ToolCall.ID)
	// or "" when context did not carry one. The host MUST thread it
	// into the model-visible EventToolPending.ToolCallID: a drop
	// strands the UI's approval resolver, which keys on this id,
	// and the gate's blocking select never fires - the tool hangs
	// silently after the user approves.
	EmitPending func(toolCallID, name, detail, input string)
}

AdmissionPredicates carries the optional per-call admission checks the legacy CLI applies in loop_tool_exec.go. Either predicate may be nil; both nil produces the same result as ConvertToolRegistry without admission checks.

type ApprovalResult

type ApprovalResult struct {
	Approved         bool
	ApprovedForClass bool
	Err              string
}

ApprovalResult is the verdict returned by Options.ApprovalGate. If Approved is false, Err is rendered as the tool's failure message (the model sees it as a tool error and may retry or move on). ApprovedForClass persists the decision for the rest of the session - the user pressed "a always" or "D deny always" - and is consulted by the gate's lookup path before the function is invoked again.

type ApprovalStanding

type ApprovalStanding struct {
	// contains filtered or unexported fields
}

ApprovalStanding is the per-session "always" cache consulted by the approval gate before invoking Options.ApprovalGate. A nil pointer is safe: every call falls through to the gate. The same instance backs the legacy and SDK paths so a "always" decision persists across backends within one session. The zero value is an empty cache.

func NewApprovalStanding

func NewApprovalStanding() *ApprovalStanding

NewApprovalStanding returns an empty cache. Concurrent calls to its methods are safe.

func (*ApprovalStanding) Allow

func (s *ApprovalStanding) Allow(name string, class tools.ExecutionClass)

Allow records an "always approve" decision for name at class. The class tag is carried so a future audit can distinguish a per-class standing decision from a per-tool one.

func (*ApprovalStanding) Deny

func (s *ApprovalStanding) Deny(name string, class tools.ExecutionClass)

Deny records an "always deny" decision for name at class.

func (*ApprovalStanding) Lookup

func (s *ApprovalStanding) Lookup(name string) (approved bool, ok bool)

Lookup returns the standing verdict for name. The bool is true only when a verdict is recorded (allow OR deny); the verdict's direction is reported as approved=true (allow) or approved=false (deny).

type Client

type Client = sdkmcp.Client

Client re-exports the SDK's mcp.Client.

The CLI reaches the bridge, never the SDK directly, so the SDK dependency stays inside internal/sdkadapter. The bridge is a type alias on purpose: the local code that has *sdkmcp.Client via the SDK's own wiring (B.2 #8, when it lands) shares the same pointer the bridge returns, and methods dispatched through either name reach the same Connect/Close/ListTools/ CallTool implementation without a wrapper allocation.

func Connect

func Connect(ctx context.Context, t sdkmcp.Transport, opts ClientOptions) (*Client, error)

Connect re-exports the SDK's Connect (opens a Client over a Transport configured with opts.Info).

type ClientInfo

type ClientInfo = sdkmcp.ClientInfo

ClientInfo re-exports the SDK's ClientInfo (caller's name and version during the MCP initialize handshake).

type ClientOptions

type ClientOptions = sdkmcp.ClientOptions

ClientOptions re-exports the SDK's ClientOptions.

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler is one adapter entry the SDK's hooks.Registry.Fire can call. It accepts the SDK-side signature (ctx, any) and returns the SDK-side verdict (allow bool, error). Map the CLI Outcome onto that verdict at every invocation; see Handle for the rules.

func NewHandler

func NewHandler(runner HookRunner, groups []hooks.Group) *Handler

NewHandler builds a Handler for the supplied runner and CLI hook groups. The runner is the production hooks.Runner value (a struct, not a pointer) or a test fake; the bridge never mutates either.

func (*Handler) Handle

func (h *Handler) Handle(ctx context.Context, payload any) (bool, error)

Handle runs the CLI hook groups for one SDK-shaped call and returns the verdict the SDK's Registry.Fire expects.

Mapping rules:

  • Reactive events (PostToolUse, Stop) cannot block; always (true, nil).
  • PreToolUse with Denied==true and a Reason is a veto: return (false, nil) so the wrapping Registry.Fire raises ErrVetoed.
  • PreToolUse with Denied==true and no Reason is a defect: return an error wrapping the empty-Reason signal so a missing-reason denial reaches the wire as a real failure rather than as an unsourced veto.
  • Otherwise the call is allowed: return (true, nil). Warnings are operator-facing diagnostics and never reach the SDK veto path.

type HookRunner

type HookRunner interface {
	Run(ctx context.Context, groups []hooks.Group, payload hooks.Payload) hooks.Outcome
}

HookRunner is the surface the bridge uses from the CLI hooks package. It matches hooks.Runner.Run by shape; declaring it here lets tests pass a fake without spinning subprocesses. A production bridge calls hooks.Runner.Run verbatim.

type Options

type Options = sdkws.Options

Options re-exports the SDK's workspace.Options.

type Workspace

type Workspace = sdkws.Workspace

Workspace re-exports the SDK's workspace.Workspace. The CLI reaches the bridge, never the SDK directly, so the SDK dependency stays inside internal/sdkadapter. The bridge is a type alias on purpose: the local code that has *sdkws.Workspace via the SDK's own wiring (B.2 #8, when it lands) shares the same pointer the bridge returns, and methods dispatched through either name reach the same Open/ReadFile/WriteFile/List/Stat implementation without a wrapper allocation.

func Open

func Open(root string) (*Workspace, error)

Open re-exports the SDK's Open (opens a *Workspace rooted at root, with default options).

func OpenWith

func OpenWith(opts Options) (*Workspace, error)

OpenWith re-exports the SDK's OpenWith (opens a *Workspace with caller-supplied options including MaxReadBytes and Deny).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL