plasmid

package module
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2026 License: MIT Imports: 35 Imported by: 0

README

plasmid

A CLI-free, in-process coding-agent harness for Go, built on Google ADK. Reads the skills and plugins your other agent tools already installed.

Plasmid supports Go hosts using Go 1.26.6 or newer and directly pins Google ADK v2.2.0, openai-go v3.49.0, and the first-party Model Context Protocol Go SDK v1.7.0. Both module directives retain ADK v2.2.0's Go 1.26.5 language floor. Go 1.26.5 is not a supported runtime because govulncheck reports reachable standard-library vulnerabilities fixed in Go 1.26.6. The direct Google ADK integration is the v1 runtime contract. There is no provider-neutral loop or adapter package.

Install the module with:

go get github.com/RandomCodeSpace/plasmid

OpenAI model construction

The openai sibling package constructs a native ADK model.LLM for either Responses or Chat Completions. Configuration is typed and closed: protocol, model, base URL, API key, caller-owned HTTP client, decompressed response limit, and retry count. There are no raw SDK options or header and middleware escape hatches.

The following complete host package constructs both protocols with a custom endpoint and caller-owned HTTP policy:

package host

import (
    "context"
    "net/http"
    "time"

    "github.com/RandomCodeSpace/plasmid/openai"
    "google.golang.org/adk/v2/model"
)

func models(ctx context.Context) (model.LLM, model.LLM, error) {
    client := &http.Client{Timeout: 30 * time.Second}

    responses, err := openai.New(ctx, openai.Config{
        Protocol:         openai.ProtocolResponses,
        Model:            "gpt-5.4",
        BaseURL:          "https://gateway.example.test/openai/v1",
        APIKey:           "",
        HTTPClient:       client,
        MaxResponseBytes: 8 << 20,
        MaxRetries:       0,
    })
    if err != nil {
        return nil, nil, err
    }

    chat, err := openai.New(ctx, openai.Config{
        Protocol:         openai.ProtocolChatCompletions,
        Model:            "gpt-5.4",
        BaseURL:          "https://gateway.example.test/openai/v1",
        APIKey:           "",
        HTTPClient:       client,
        MaxResponseBytes: 8 << 20,
        MaxRetries:       0,
        ChatTokenLimit:   openai.ChatTokenLimitMaxCompletionTokens,
    })
    if err != nil {
        return nil, nil, err
    }

    return responses, chat, nil
}

Protocol selection is fixed at construction. Plasmid never infers a protocol from the model or endpoint and never retries a processed request through another protocol. Use ChatTokenLimitMaxTokens for providers that require max_tokens.

Chat supports synchronous, non-streaming generation. It preserves ordered system, user, assistant, tool-call, and tool-result history and converts native ADK function declarations without reordering them. Missing call IDs and duplicate IDs after their first occurrence get deterministic unique replacements without reordering calls. Blank function arguments become an empty object. Direct Chat generation remains fail-closed: malformed, trailing, null, array, or scalar function arguments return ChatErrorMalformedArguments. Unsupported tool-call types, invalid choices, unsupported ADK parts, and streaming requests also return ChatError with a stable ChatErrorKind. A Chat length finish reason becomes native ADK MAX_TOKENS.

Native ADK function tools return map[string]any. For direct Chat conversion or a bounded one-shot run, a tool whose result is instead a JSON-compatible scalar, object, array, or null can return openai.RawChatToolResult(value) from its Run method. Chat sends the prevalidated JSON encoding as the next tool message's content; ordinary map results keep their existing encoding. Invalid values return ChatErrorInvalidToolResult without exposing the value. The marked result deliberately fails JSON serialization closed: it is unsupported with the Responses protocol and with durable Harness or session persistence.

An empty APIKey deliberately omits Authorization. Ambient OPENAI_* values cannot change the URL, credentials, headers, retry behavior, caller HTTP policy, response limit, protocol, or returned error text. The response limit counts bytes after gzip decompression and returns a typed ResponseTooLargeError on overflow.

One-shot execution

The oneshot sibling package runs one synchronous, non-streaming native ADK invocation. The caller supplies the model, literal instruction, prompt, and exact tool list. Each call creates an in-memory session and deletes it before returning, including after cancellation or a caller model or tool panic.

package host

import (
    "context"

    "github.com/RandomCodeSpace/plasmid/oneshot"
    "google.golang.org/adk/v2/model"
    "google.golang.org/adk/v2/tool"
)

func execute(
    ctx context.Context,
    llm model.LLM,
    hostTool tool.Tool,
) (oneshot.Result, error) {
    probe, err := oneshot.Probe(ctx, oneshot.ProbeRequest{
        Model:           llm,
        MaxOutputTokens: 256,
    })
    if err != nil {
        return probe, err
    }

    result, err := oneshot.Run(ctx, oneshot.Request{
        Model:                   llm,
        Instruction:             "Answer using only the supplied tool.",
        Prompt:                  "Look up the current value.",
        Tools:                   []tool.Tool{hostTool},
        MaxOutputTokens:         1024,
        MaxReturnedTextBytes:    64 << 10,
        MaxModelCalls:           4,
        MaxToolCallsPerResponse: 8,
        ToolExecution:           oneshot.ToolExecutionSequential,
    })
    if err != nil {
        return result, err
    }
    return result, nil
}

All four bounds are required and must be positive. MaxOutputTokens applies to each model request, while MaxModelCalls bounds the complete invocation. A model response that exceeds MaxToolCallsPerResponse is rejected before any tool from that response runs. Tool calls execute sequentially in response order by default. Set ToolExecution: oneshot.ToolExecutionParallel to opt into overlap.

When the supplied model is Plasmid's Chat adapter, oneshot.Run opts into call-level argument recovery. Malformed, trailing, null, array, and scalar arguments produce a model-visible invalid tool arguments result without invoking the target. Direct Chat use and the durable Harness retain the fail-closed behavior described above.

Result.Text contains bounded non-thought final or partial text. Result.ToolResults contains completed native tool responses in model response order, including when parallel execution is selected. Result.Metadata reports model calls, tool calls, and ADK token usage. A non-nil error may therefore accompany partial text and tool results. Empty final text is valid when a successful final event contains no non-thought text.

The package performs no discovery, persistence, configuration loading, or filesystem I/O. Supplied tools keep their native ADK behavior and own their side effects. Stable ErrorCode values distinguish invalid input, cancellation, caller panics, model-output truncation, returned-text truncation, model-call exhaustion, tool-call overflow, missing final output, execution failure, and session cleanup failure. Always inspect the returned Result before discarding it on error. CodeOf extracts the stable machine-readable code, while errors.Is matches the exported sentinel cause.

Probe, shown in the complete example above, checks a configured model without entering the runner. ProbeRequest.MaxOutputTokens must be positive and applies only to the probe's single model request. ProbeToolCalling(ctx, llm) remains the convenience form and uses a 64-token output budget.

The probe makes one direct, synchronous, non-streaming model.LLM request. It advertises only an inert plasmid_ping declaration with a fixed marker and succeeds only when the response contains exactly that valid call. It never creates a session or executes a tool. Result.Metadata reports one model call and zero tool calls for a completed request. Text answers and calls that reach the probe but do not exactly match the ping contract return CodeToolCallingUnsupported. Provider adapters may reject malformed or custom wire calls earlier as CodeExecutionFailed; neither outcome can report probe success. Cancellation, truncation, caller panics, and provider failures retain the same typed one-shot outcomes and redaction rules.

Choose one-shot or Harness

Use oneshot.Run when the host must expose exactly the tools in Request.Tools for one bounded, ephemeral invocation. It performs no extension or instruction discovery, configuration loading, persistent-session work, or filesystem I/O of its own.

Use plasmid.New for durable workspace coding. It discovers the configured coding environment, supplies its built-in coding tools, and persists sessions. plasmid.WithTools appends host-provided native ADK tools after Plasmid's coding tools; it is not a tool-exact replacement mechanism. Use one-shot execution when the tool surface must be exact.

Native Harness

plasmid.New constructs a native ADK llmagent and runner, six filesystem coding tools, optional bash when a shell is available, and a durable session service in process. A model is required. The working directory defaults to the resolved current directory, and sessions default to <workingDir>/.plasmid/sessions.

package host

import (
    "context"
    "errors"

    "github.com/RandomCodeSpace/plasmid"
    "google.golang.org/adk/v2/model"
)

func ask(
    ctx context.Context,
    llm model.LLM,
    workdir string,
    sessiondir string,
) (answer string, err error) {
    p, err := plasmid.New(ctx,
        plasmid.WithModel(llm),
        plasmid.WithWorkingDir(workdir),
        plasmid.WithSessionDir(sessiondir),
    )
    if err != nil {
        return "", err
    }
    defer func() {
        err = errors.Join(err, p.Close())
    }()

    sessionID, err := p.NewSession(ctx)
    if err != nil {
        return "", err
    }
    return p.Ask(ctx, sessionID, "Inspect the repository")
}

Run exposes native iter.Seq2[*session.Event, error] events. It permits one active run per session while allowing distinct sessions to run concurrently. Stopping iteration early cancels the run and releases its session lock. ResumeSession verifies an existing durable session and never creates a missing one. Ask returns text from the last final root-agent event.

Construction is transactional. Close is concurrent-safe and idempotent: it cancels active runs and waits up to ten seconds before teardown. Native ADK plugins close first in reverse registration order, followed by compiled plugins in reverse registration order, context and skill subscriptions, MCP sessions and transports, extension and context snapshots, LSP enforcement and manager state, and the durable session store. If a run resists cancellation, teardown proceeds after the wait and Close returns a coded error matching ErrCloseTimeout; concurrent and repeated calls observe the same completed teardown. Runtime failures use plasmid.Error with stable ErrorCode values; CodeOf extracts the code while errors.Is continues to match the exported sentinel cause.

Host tools use WithTools and append to the built-in coding tools. Native ADK plugins use WithADKPlugins; their callback mutation and short-circuit semantics remain authoritative. A compiled Plugin may register tools, toolsets, ADK callback bundles, named prompt fragments, and structured warnings during Init; registration seals before New returns. Built-in callbacks and instructions run before plugin additions. Callback panics become ordinary errors and secret-free structured warnings.

WithToolConfirmation(true) applies native ADK confirmation to non-streaming function tools; Plasmid provides no confirmation UI. Streaming tools do not support that native wrapper. Exposing one while global confirmation is enabled fails the run instead of silently bypassing confirmation.

Context and syntax runtime

Each session snapshots supported Codex, Claude Code, and GitHub Copilot instruction files. User and ancestor files assemble before repository-root files; nested AGENT.md, AGENTS.md, and CLAUDE.md files and path-scoped Claude and Copilot rules activate only after a native coding tool touches a matching path. Activation is session-local, and later model steps receive the updated least-specific-to-most-specific prompt.

Instruction discovery is cancellation-aware and bounded. Real-path and content-hash deduplication remove duplicate sources, Claude @path imports are confined to the workspace, the user home for user instructions, and configured import roots. The assembled byte budget evicts least-specific content first with a structured warning. Session, project-directory, and static effort variables come from Harness state; the process environment is not an implicit substitution source.

Instruction frontmatter can restrict native tool names and arguments with deny-wins nested policy intersection. Tool names exposed to the model are filtered through the active policy, and a native before-tool callback rechecks the complete argument before execution. Host names such as Read, Glob, and LS map deterministically to read, find, and ls. Turn scopes are released after normal completion, model or tool errors, cancellation, and early stream termination.

Inline ! commands and fenced command directives expand only through the same bounded shellexec executor used by bash. syntax.promptCommands is off, trusted, or on; the default trusted mode runs user instructions and repository instructions beneath an exact foreign.trustedRoots entry. Each command and document has independent time and output limits. Instruction discovery itself never runs commands.

sessionstore is the native durable Google ADK session.Service. Its per-session JSONL transcript is the commit record for complete non-partial ADK events and session-local state. App and user state use independent append-only journals with repairable derived snapshots. Temporary state is never persisted. The store serializes operations within one session while allowing different session transcripts to progress concurrently, and enables file and directory durability barriers by default. Its on-disk format is pre-v1 and carries no compatibility guarantee.

All loader degradation uses the framework-free warning.Warning shape and namespaced warning codes. The root Harness always collects construction and runtime warnings; Warnings returns a defensive snapshot. WithLogger additionally mirrors structured warnings to the supplied logger. Without that option, log output is discarded while warnings remain observable. Leaf packages accept a warning.Warner: warning.SlogSink emits structured records, warning.DiscardSink ignores them, and warning.SliceSink collects defensive copies. Warning.String renders as <path>:<line>: <code>: <message>; the structured fields, not the rendered line, are the machine-readable contract.

Versioned configuration

config.Load is the sole owner of Plasmid configuration. It accepts a context and honors cancellation during discovery, bounded reads, decoding, and path repair. It loads JSON version 1 from an explicit path when supplied; otherwise it checks <workingDir>/.plasmid.json, $XDG_CONFIG_HOME/plasmid/config.json, and ~/.config/plasmid/config.json in that order. The first existing file wins and files never merge. Built-in defaults are applied first, the file overlays them, and embedding overrides in config.Options apply last.

The file accepts these top-level keys:

{
  "version": 1,
  "appName": "plasmid",
  "lsp": {},
  "mcp": {},
  "skills": {},
  "foreign": {},
  "syntax": {},
  "context": {},
  "tools": {},
  "compaction": {}
}

Block keys are:

  • lsp: mode, settleTimeoutMs, initializeTimeoutMs, requestTimeoutMs, failureThreshold, maxDiagnosticsPerFile, and servers. Server entries use id, command, args, extensions, rootMarkers, and disabled; entries merge with the built-in gopls server by id.
  • mcp: inheritForeign, exact allowForeign names, and servers. A server is either stdio with id, command, optional args and env, or http with id, url, and optional headers.
  • skills: roots. foreign: enabled, claude, codex, copilot, and trustedRoots.
  • syntax: promptCommands, commandTimeoutMs, documentTimeoutMs, commandOutputBytes, and documentOutputBytes.
  • context: maxFileBytes, maxBytes, maxImportDepth, importRoots, and touchesPerToolCall.
  • tools: callOutputBytes, sessionOutputBytes, bashTimeoutMs, bashMaxTimeoutMs, and confirmation.
  • compaction: contextTokens, triggerFraction, targetFraction, keepRecentContents, minimumElisionTokens, preserveToolNames, and calibration. A zero context budget disables compaction.

Relative file paths are anchored to the selected config file and ~/ uses the resolved home directory. Unknown keys and invalid optional values produce stable structured warnings; invalid entries are repaired or dropped locally. Malformed JSON and versions newer than version 1 fail loading. Version zero is upgraded with a warning. Configuration loading performs bounded file I/O only: it does not start configured LSP or MCP processes.

Deterministic compaction

Setting compaction.contextTokens above zero installs one native ADK before-model callback and one after-model callback. The before-model callback estimates the assembled native request, reapplies durable sticky decisions, and compacts only when the calibrated estimate reaches the configured trigger. The after-model callback calibrates future estimates from reported prompt usage with EWMA alpha 0.3, clamped to 0.5 through 2.0. No provider-neutral request facade or summarizer is involved.

The raw estimator is fixture-pinned: canonical JSON uses sorted object keys, does not HTML-escape text, and charges one token per four UTF-8 bytes rounded up. It then adds 4 tokens per content, 1 per part, 8 per function call or response, 16 per binary payload, and 12 per function declaration. These are deterministic framing allowances, not claims about a provider tokenizer.

Compaction replaces the oldest eligible function or server-tool response body with [elided] while retaining its ID, name or type, and pair. Configured tool names are never body-elided, and turns containing them are never dropped. If elision cannot reach the target, Plasmid drops the oldest complete turn: a user prompt and its following model/tool traffic, ending immediately before the next user prompt. Content index zero, the active turn, the configured recent-content window, system instructions, and any turn whose removal would split a call/response pair remain intact.

Elided response identities and dropped-turn fingerprints, including repeated identical response and turn decisions, persist in the session's versioned compaction.v1 sidecar and reapply after restart. Sidecar load or save failure warns once and continues with in-memory state. A triggered compaction resets that session's cumulative tool-output budget. If protected content still exceeds the target, one exhaustion warning is recorded and the model call proceeds.

Foreign extension discovery

The foreign package discovers metadata already present for Claude Code, Codex, and GitHub Copilot. foreign.Scan returns a normalized skill view plus three independently ordered host source views; ScanClaude, ScanCodex, and ScanCopilot expose the host adapters separately. Shared portable skills merge their host provenance when their logical identity and real path or bytes match. Unrelated plugin-qualified records remain distinct. Records include source scope, plugin identity and version, enabled state, repository trust, and documented or compatibility classification. An unqualified skill name present in distinct records across hosts is reported as ambiguous rather than resolved through an invented host priority.

Only the Agent Skills SKILL.md core is shared. Each adapter owns its host's skill roots, legacy templates, plugin manifests, configuration, and precedence. Compatibility inputs are labeled, including Claude's version 2 installed-plugin index, $CODEX_HOME/skills, and legacy Codex prompts. Copilot IDE prompt files are preview input and remain disabled unless Options.EnableCopilotPreview is set. Repository records are listed with their trust state; trusted-project MCP configuration is read only when Options.ProjectTrusted is true.

Discovery is cancellation-aware, bounded file I/O. It never installs or runs skills, plugins, hooks, commands, MCP servers, or network clients. Foreign MCP records expose only inert identity and transport metadata; credentials, headers, environment values, and arguments are deliberately absent from normalized catalogs and warnings.

Extension activation

Each new or resumed session receives an immutable extension catalog snapshot. Configured and foreign skills with the same name and identical bytes deduplicate without dropping provenance. Different content stays ambiguous until selected by its canonical host:scope:name identity. Bodies load on first use and are checked against the discovery digest; resources are bounded UTF-8 regular files confined beneath the selected skill root. When identical skill bodies come from roots with different resources, resource loading requires a qualified name.

The native skills toolset exposes list_skills, load_skill, and load_skill_resource only when model-invocable skills exist. Loading expands arguments and Harness variables through the shared syntax runtime, then atomically intersects the active turn's tool policy. Explicit empty allow lists therefore deny every further tool. Repository content must be beneath an exact trusted root before it is model-invocable.

ListTemplates and GetTemplate provide deterministic API access; RunTemplate and AskTemplate use the normal serialized Harness run path. Template identity comes from the filename, with optional frontmatter for supported mode and policy fields.

Configured MCP servers are explicit consent. A foreign server activates only when its exact canonical name appears in mcp.allowForeign, or when mcp.inheritForeign is enabled, and its source is enabled and trusted. Server construction, config loading, discovery, and session creation perform no MCP I/O. The native MCP toolset connects allowed servers only when a model request needs tools, degrades failures per server, reconnects broken sessions, and suppresses repeated failures at the internal threshold. Harness close cancels active calls before closing SDK sessions, HTTP transports, and stdio child processes.

Output limiting

outputlimit provides deterministic UTF-8 and CRLF-safe output elision for embedded hosts. Policy.Apply applies byte, line, and line-body limits and uses the package's single Marker format. ApplyLines accepts logical lines and applies the same rendering policy. Writer retains bounded state when its policy has a positive byte cap; the zero-value policy is intentionally unlimited. Budget coordinates per-session rendered-byte reservations without exceeding its hard limit.

Shell execution

shellexec runs a fresh non-interactive shell for each request. Each initial working directory is resolved inside a workspace.Root, configured output limits bound capture, and timeout or cancellation terminates the Unix process group before escalating to a forced kill. A zero-value output policy is unlimited. Stdout and stderr can be captured separately or connected to one ordered stream with RunMerged. Shell execution is not an OS security boundary; hosts requiring isolation must confine the host process.

Coding tool contracts

codingtools.New returns the stable ordered set of native Google ADK function tools: read, write, edit, optional bash, grep, find, and ls. Set.Tools exposes native tool.Tool values directly. Each function tool has an explicit hand-authored JSON input schema, an object response schema, and a bounded model-facing description. Schema accessors return defensive copies. The optional bash tool is omitted with a structured warning when no shared shell executor is configured.

File paths are workspace-relative and file tools reject escapes. Bash accepts an optional workspace-relative initial directory, but commands retain host-process authority. Read results report the actual returned line window and total file line count, including when the requested window reaches EOF. The read tool accepts regular UTF-8 text files up to 5 MiB by default, records a full-file content hash, and returns numbered lines through the shared output policy and native ADK session identity. Existing files must be read before write or edit, and stale reads refuse mutation. Writes and edits are globally serialized, replace files through a synced same-directory temporary file and atomic rename, and preserve existing permissions. Writes create new files with mode 0644; edit accepts only existing regular files. Result shapes are JSON objects and reserve diagnostics and diagnostics_text for LSP decoration.

LSP enforcement

Automatic LSP mode subscribes to the shared workspace touch stream. The first successful write or edit of a matching file lazily detects and starts one server per resolved workspace root and server ID, sends full-text didOpen or monotonically versioned didChange, and waits within settleTimeoutMs for a diagnostic publication for that exact document generation. The native ADK after-tool callback then adds only diagnostics and diagnostics_text to that invocation's successful result. Stale publications are ignored; an explicit current empty publication clears diagnostics. Read tools, failed mutations, and unrelated invocations are never decorated.

The prompt reports LSP: none detected before a matching server starts and a sorted list of active server IDs afterward. mode: "off" omits the status, manager, subscription, and callback entirely. Plasmid v1 exposes no model-facing LSP query tools for diagnostics, symbols, or references. Diagnostics reach the model only through successful write and edit result decoration.

The immutable registry includes gopls and accepts validated per-ID overrides. Executable detection is lazy through exec.LookPath; Plasmid never downloads or installs a language server. Servers use bounded Content-Length JSON-RPC over stdio and degrade unavailable, failed, timed-out, or exited processes to a structured warning and no-op. Request deadlines interrupt blocked transport I/O, and cancellation or Harness close terminates the owned server process tree on Unix and Windows. Other targets fail server startup rather than leave descendants unmanaged.

The package also owns confined workspace-root selection, portable file URI conversion, UTF-8 and UTF-16 position conversion, deterministic bounded diagnostic normalization, full-text document versions, and fakeable transport and process-start seams. The root Harness alone owns native ADK injection and the LSP resource lifecycle.

Edit matching and diffs

codingtools applies edits deterministically: exact matches win first, then matches that differ only in trailing spaces or tabs, then matches with one uniform whitespace indentation delta. Ambiguous edits fail with every matching line unless replacement of all matches is requested. Edits preserve a file's UTF-8 BOM, dominant LF or CRLF line ending, and trailing-newline presence. Matched ranges use half-open byte offsets in normalized, BOM-free source text.

Unified diffs use a deterministic line-level Myers edit script with three lines of context by default. Path headers are emitted under a/ and b/, missing trailing newlines are marked in place, and excessive diff work falls back to a single whole-file replacement hunk.

Filtered directory walking

codingtools walks workspace descendants in deterministic lexical order and returns slash-separated paths relative to the workspace root. Filters support hidden and VCS directories, include and exclude globs, depth limits, bounded visits and results, nested .gitignore files, and .git/info/exclude. The supported ignore subset includes *, ?, **, character classes, anchoring, directory-only rules, comments, escapes, and last-match negation. Malformed ignore rules are skipped with a warning. Symlinks are reported from link metadata but are never descended, regardless of the compatibility FollowSymlinks setting.

Fixture conformance pack

testdata/conformance/manifest-v1.json and fixtures-v1.tar are the language-neutral fixture contract. The manifest records the ordered fixture areas and every archive entry's normalized slash-separated path, type, mode, size, and SHA-256 hash. The USTAR archive fixes directory modes to 0755, regular file modes to 0644, and timestamps and ownership to stable values, so identical fixture inputs produce identical bytes on every platform. Repository attributes preserve fixture sources byte-for-byte, including intentional CRLF and binary inputs, and pin the JSON manifest to LF checkouts.

From the repository root, go run ./internal/fixture/cmd/fixturepack verifies the committed artifacts without writing to them. Pass -update to regenerate both files after an intentional fixture change. CI verifies the committed pack and rejects regeneration that leaves a diff on Linux and Windows checkouts. Static fixture ownership checks also require exactly one direct fixture.AssertCoverage call from a runnable top-level test for every fixture area.

Engineering standards: AGENTS.md.

Documentation

Index

Constants

View Source
const (
	// LSPAuto enables lazy configured LSP detection.
	LSPAuto = config.LSPAuto
	// LSPOff disables LSP behavior.
	LSPOff = config.LSPOff
)

Variables

View Source
var (
	ErrInvalidArgument    = errors.New("plasmid: invalid argument")
	ErrConstructionFailed = errors.New("plasmid: construction failed")
	ErrUnknownSession     = errors.New("plasmid: unknown session")
	ErrSessionBusy        = errors.New("plasmid: session busy")
	ErrDuplicate          = errors.New("plasmid: duplicate registration")
	ErrClosed             = errors.New("plasmid: closed")
	ErrRegistrationSealed = errors.New("plasmid: registration sealed")
	ErrNoFinalResponse    = errors.New("plasmid: no final response")
	ErrRuntimeFailed      = errors.New("plasmid: runtime failed")
	ErrCloseTimeout       = errors.New("plasmid: close timeout")
	ErrCloseFailed        = errors.New("plasmid: close failed")
)

Functions

This section is empty.

Types

type Error

type Error struct {
	Code ErrorCode
	Op   string
	Err  error
}

Error carries a stable code while retaining the original cause.

func (*Error) Error

func (e *Error) Error() string

func (*Error) Unwrap

func (e *Error) Unwrap() error

type ErrorCode

type ErrorCode string

ErrorCode is a stable machine-readable Plasmid failure category.

const (
	CodeInvalidArgument    ErrorCode = "invalid_argument"
	CodeConstructionFailed ErrorCode = "construction_failed"
	CodeUnknownSession     ErrorCode = "unknown_session"
	CodeSessionBusy        ErrorCode = "session_busy"
	CodeDuplicate          ErrorCode = "duplicate"
	CodeClosed             ErrorCode = "closed"
	CodeRegistrationSealed ErrorCode = "registration_sealed"
	CodeNoFinalResponse    ErrorCode = "no_final_response"
	CodeRuntimeFailed      ErrorCode = "runtime_failed"
	CodeCloseFailed        ErrorCode = "close_failed"
)

func CodeOf

func CodeOf(err error) ErrorCode

CodeOf returns the first Plasmid error code in err's unwrap tree.

type ForeignResolution

type ForeignResolution = config.Foreign

ForeignResolution configures which installed foreign hosts are scanned.

type Harness

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

Harness is the in-process native Google ADK coding-agent runtime.

func New

func New(ctx context.Context, supplied ...Option) (*Harness, error)

New constructs a complete native ADK Harness transactionally.

func (*Harness) Ask

func (h *Harness) Ask(ctx context.Context, sessionID, prompt string) (string, error)

Ask runs one turn and returns text from the last final root-agent response.

func (*Harness) AskTemplate

func (h *Harness) AskTemplate(ctx context.Context, sessionID, name, arguments string) (string, error)

AskTemplate returns the last final root-agent text for one template run.

func (*Harness) Close

func (h *Harness) Close() error

Close cancels active runs and closes owned resources exactly once.

func (*Harness) Config

func (h *Harness) Config() config.Config

Config returns a defensive copy of the resolved configuration.

func (*Harness) Format

func (*Harness) Format(state fmt.State, _ rune)

Format prevents resolved credentials and owned transport state from appearing in diagnostic formatting.

func (*Harness) GetTemplate

func (h *Harness) GetTemplate(ctx context.Context, sessionID, name, arguments string) (string, error)

GetTemplate resolves and expands one user-invocable template without running it.

func (*Harness) ListTemplates

func (h *Harness) ListTemplates(ctx context.Context, sessionID string) ([]extensions.Template, error)

ListTemplates returns the stable template snapshot for one session.

func (*Harness) LogValue

func (*Harness) LogValue() slog.Value

LogValue prevents structured logging from reflecting Harness internals.

func (*Harness) Logger

func (h *Harness) Logger() *slog.Logger

Logger returns the configured logger or the default discard logger.

func (*Harness) NewSession

func (h *Harness) NewSession(ctx context.Context) (string, error)

NewSession creates a durable session with a store-generated canonical ID.

func (*Harness) RegisterADKPlugins

func (h *Harness) RegisterADKPlugins(values ...*adkplugin.Plugin) error

RegisterADKPlugins adds native ADK plugins during compiled-plugin Init.

func (*Harness) RegisterPromptFragments

func (h *Harness) RegisterPromptFragments(values ...PromptFragment) error

RegisterPromptFragments appends plugin instructions after Plasmid's built-in instructions. It is valid only during the calling plugin's Init.

func (*Harness) RegisterTools

func (h *Harness) RegisterTools(values ...adktool.Tool) error

RegisterTools adds static native ADK tools during compiled-plugin Init.

func (*Harness) RegisterToolsets

func (h *Harness) RegisterToolsets(values ...adktool.Toolset) error

RegisterToolsets adds native ADK toolsets during compiled-plugin Init.

func (*Harness) RegisterWarnings

func (h *Harness) RegisterWarnings(values ...warning.Warning) error

RegisterWarnings publishes stable warnings from the calling plugin's Init.

func (*Harness) ResumeSession

func (h *Harness) ResumeSession(ctx context.Context, sessionID string) error

ResumeSession verifies that a durable session already exists.

func (*Harness) Run

func (h *Harness) Run(ctx context.Context, sessionID, prompt string) iter.Seq2[*session.Event, error]

Run executes one native ADK turn and yields native session events.

func (*Harness) RunTemplate

func (h *Harness) RunTemplate(ctx context.Context, sessionID, name, arguments string) iter.Seq2[*session.Event, error]

RunTemplate expands a template and executes it through the normal run path.

func (*Harness) SessionDir

func (h *Harness) SessionDir() string

SessionDir returns the resolved durable session directory.

func (*Harness) Warnings

func (h *Harness) Warnings() []warning.Warning

Warnings returns a defensive snapshot of construction and runtime warnings.

func (*Harness) WorkingDir

func (h *Harness) WorkingDir() string

WorkingDir returns the resolved workspace root.

type LSPMode

type LSPMode = config.LSPMode

LSPMode selects automatic detection or complete LSP disablement.

type Option

type Option func(*options) error

Option configures a Harness before construction begins.

func WithADKPlugins

func WithADKPlugins(values ...*adkplugin.Plugin) Option

WithADKPlugins appends native ADK plugins after compiled-registered plugins.

func WithAppName

func WithAppName(name string) Option

WithAppName sets the ADK application name.

func WithConfig

func WithConfig(path string) Option

WithConfig selects one explicit versioned configuration file.

func WithForeignResolution

func WithForeignResolution(value ForeignResolution) Option

WithForeignResolution overrides foreign discovery settings.

func WithLSP

func WithLSP(mode LSPMode) Option

WithLSP overrides the configured LSP mode.

func WithLogger

func WithLogger(logger *slog.Logger) Option

WithLogger sets the structured logger. The default discards logs.

func WithModel

func WithModel(value model.LLM) Option

WithModel supplies the required native ADK model.

func WithPlugins

func WithPlugins(values ...Plugin) Option

WithPlugins appends host-compiled Plasmid plugins in initialization order.

func WithSessionDir

func WithSessionDir(path string) Option

WithSessionDir sets the durable session storage directory.

func WithToolConfirmation

func WithToolConfirmation(enabled bool) Option

WithToolConfirmation enables native ADK confirmation wrappers for tools.

func WithTools

func WithTools(values ...adktool.Tool) Option

WithTools appends host-provided native ADK tools after built-in tools.

func WithUserID

func WithUserID(id string) Option

WithUserID sets the durable session user identity.

func WithWorkingDir

func WithWorkingDir(path string) Option

WithWorkingDir sets the workspace root.

type Plugin

type Plugin interface {
	Name() string
	Init(*Harness) error
	Close() error
}

Plugin is a host-compiled extension initialized during Harness construction. Init may register native tools, toolsets, and ADK plugins on the supplied Harness. Registration is sealed before New returns.

type PromptFragment

type PromptFragment struct {
	Name    string
	Content string
}

PromptFragment is one named, static instruction fragment supplied by a host-compiled plugin during Init.

Directories

Path Synopsis
Package codingtools defines Plasmid's native ADK coding tools and their wire arguments and result objects.
Package codingtools defines Plasmid's native ADK coding tools and their wire arguments and result objects.
internal/walk
Package walk provides deterministic, filtered directory traversal.
Package walk provides deterministic, filtered directory traversal.
Package compaction provides deterministic native Google ADK request estimation and durable context compaction callbacks.
Package compaction provides deterministic native Google ADK request estimation and durable context compaction callbacks.
Package config owns Plasmid's versioned configuration, defaults, discovery, path normalization, validation, repair, and config warnings.
Package config owns Plasmid's versioned configuration, defaults, discovery, path normalization, validation, repair, and config warnings.
Package contextresolver discovers and assembles session-scoped coding-agent instructions without depending on an agent framework.
Package contextresolver discovers and assembles session-scoped coding-agent instructions without depending on an agent framework.
Package extensions owns immutable, framework-free extension catalog snapshots.
Package extensions owns immutable, framework-free extension catalog snapshots.
Package foreign discovers inert extension metadata installed for supported coding-agent hosts.
Package foreign discovers inert extension metadata installed for supported coding-agent hosts.
internal
foreignactivation
Package foreignactivation carries consent-gated MCP runtime descriptors between Plasmid packages without adding them to the public foreign catalog.
Package foreignactivation carries consent-gated MCP runtime descriptors between Plasmid packages without adding them to the public foreign catalog.
pathglob
Package pathglob provides deterministic matching for slash-separated paths.
Package pathglob provides deterministic matching for slash-separated paths.
processtree
Package processtree owns operating-system process descendant containment.
Package processtree owns operating-system process descendant containment.
syntax
Package syntax owns Plasmid's framework-free syntax document primitives.
Package syntax owns Plasmid's framework-free syntax document primitives.
toolcallrecovery
Package toolcallrecovery defines private metadata carried from provider decoding to a guarded tool execution boundary.
Package toolcallrecovery defines private metadata carried from provider decoding to a guarded tool execution boundary.
Package lsp provides framework-free language-server lifecycle leaves.
Package lsp provides framework-free language-server lifecycle leaves.
Package mcp owns lifecycle-aware native ADK toolsets over the first-party MCP SDK.
Package mcp owns lifecycle-aware native ADK toolsets over the first-party MCP SDK.
Package oneshot runs one bounded-lifetime Google ADK agent invocation.
Package oneshot runs one bounded-lifetime Google ADK agent invocation.
Package openai constructs native ADK models for OpenAI-compatible endpoints.
Package openai constructs native ADK models for OpenAI-compatible endpoints.
Package outputlimit renders bounded output without splitting UTF-8 or CRLF.
Package outputlimit renders bounded output without splitting UTF-8 or CRLF.
Package sessionstore persists native Google ADK sessions as JSONL files.
Package sessionstore persists native Google ADK sessions as JSONL files.
Package shellexec runs bounded shell commands with workspace-validated initial working directories and process-tree cleanup.
Package shellexec runs bounded shell commands with workspace-validated initial working directories and process-tree cleanup.
Package skills projects immutable extension catalogs into native ADK tools.
Package skills projects immutable extension catalogs into native ADK tools.
Package warning defines Plasmid's framework-free non-fatal warning contract.
Package warning defines Plasmid's framework-free non-fatal warning contract.
Package workspace provides framework-free workspace state and coordination.
Package workspace provides framework-free workspace state and coordination.

Jump to

Keyboard shortcuts

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