Help us shape the future of Go! Take the 2026 Go Developer Survey

registry

package
v0.1.164 Latest Latest
Warning

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

Go to latest
Published: Jun 12, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package registry holds the shared "tool definition" type each codefly toolbox uses to declare its callable surface ONCE and project to whichever response shape the host requested:

  • Legacy *toolboxv0.Tool — heavy, returned by ListTools
  • *toolboxv0.ToolSummary — light, returned by ListToolSummaries
  • *toolboxv0.ToolSpec — heavy + examples, returned by DescribeTool

Toolboxes used to keep tool definitions inline in their ListTools method bodies and re-derive Tool messages on every call. With the two-phase contract in place we need the SAME tool data shaped three different ways. The registry keeps the source of truth in one place.

Go-SDK convenience for codefly toolbox plugin authors. The wire contract is the Toolbox gRPC service in proto/codefly/services/ toolbox/v0; this package is just the ergonomic Go shape on top. Plugin authors writing in other languages implement the proto directly. This package is NOT a stability promise to third-party Go plugins — treat it as semi-public, may evolve with the framework.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AsSummaries

func AsSummaries(defs []*ToolDefinition, tagsFilter []string) []*toolboxv0.ToolSummary

AsSummaries projects every definition into the lightweight catalog. Optionally pre-filters by tags — every tag in tagsFilter must be present on the definition's tags (AND semantics). Empty filter returns everything.

func AsTools

func AsTools(defs []*ToolDefinition) []*toolboxv0.Tool

AsTools projects every definition into the legacy envelope.

func FindSpec

func FindSpec(defs []*ToolDefinition, name string) *toolboxv0.ToolSpec

FindSpec returns the spec for the named tool, or nil when the name doesn't exist. Caller decides whether to surface as an error.

Types

type Base

type Base struct {
	toolboxv0.UnimplementedToolboxServer
	// contains filtered or unexported fields
}

Base is an embeddable that provides the boilerplate four RPCs of the Toolbox service. A plugin's Server type embeds *Base and implements Identity() + Tools() — the rest is handled here.

Usage:

type Server struct {
    *registry.Base
    // ... plugin-specific fields
}

func New() *Server {
    s := &Server{}
    s.Base = registry.NewBase(s)
    return s
}

func (s *Server) Tools() []*registry.ToolDefinition { ... }
func (s *Server) Identity(...) (*toolboxv0.IdentityResponse, error) { ... }

The two-step (NewBase + assign) is required because the Tooler pointer needs to point back at the embedding type, not at Base itself — Go embedding doesn't give us "self" automatically.

func NewBase

func NewBase(t Tooler) *Base

NewBase wires a Base to its owning Tooler.

func (*Base) CallTool

CallTool dispatches by name to the matching ToolDefinition.Handler. Unknown name → in-band error response. Tool with nil Handler → "unimplemented" error response (developer mistake; surface clearly rather than panic).

**Schema validation.** When a tool's InputSchema is set, the arguments are validated against it BEFORE the handler runs. The LLM-attack-surface is the args map: every plugin handler used to have to type-assert and nil-check by hand, with the failure mode being either a bad response or a runtime panic in the plugin process. Centralizing here means one validator for every plugin, fail-closed by default, with a clear in-band error so the model can repair its call.

Schemas with no InputSchema set are passed through unchecked — preserves backward compatibility with toolboxes that haven't declared one. Production toolboxes should always declare a schema.

func (*Base) DescribeTool

DescribeTool (full spec) — returns ToolSpec for the named tool, or an error string in the response when the name is unknown. We return the error in-band rather than as a gRPC error because the LLM caller benefits from a human-readable hint.

func (*Base) ListToolSummaries

ListToolSummaries (catalog) — lightweight, with optional tags filter. AND semantics: every tag in tags_filter must be present.

func (*Base) ListTools

ListTools (legacy) — returns the heavy envelope for every tool.

type ToolDefinition

type ToolDefinition struct {
	// Name is the dotted tool name (e.g. "git.status").
	Name string

	// SummaryDescription is the ONE-LINE description used in
	// ToolSummary — optimized for "should I pick this?".
	// Required; ~120 chars or fewer by convention.
	SummaryDescription string

	// LongDescription is the multi-paragraph description used in
	// ToolSpec — explain the contract, edge cases, when not to
	// use. Optional; if empty, falls back to SummaryDescription.
	LongDescription string

	// InputSchema is the JSON Schema for arguments. Encoded as a
	// structpb so we don't mirror JSON Schema's recursive shape
	// in proto.
	InputSchema *structpb.Struct

	// OutputSchema is optional — set when the toolbox wants to
	// constrain its output shape. Most tools leave this nil.
	OutputSchema *structpb.Struct

	// Destructive marks state-mutating tools. Hosts surface extra
	// confirmation UI for these.
	Destructive bool

	// Tags drive pre-filtering in routing (read-only, network,
	// filesystem, destructive, plus the toolbox name + free-form
	// domain tags). The toolbox name is auto-prepended by helpers
	// IF not present, so authors don't need to repeat it.
	Tags []string

	// Examples are worked invocations. AT LEAST ONE per tool by
	// convention — LLMs structure args dramatically better with
	// examples than with schemas alone. This is the load-bearing
	// addition of the two-phase design.
	Examples []*toolboxv0.ToolExample

	// Idempotency: "idempotent" | "side_effecting" | "" (unknown).
	Idempotency string

	// ErrorModes is free-text on what failure looks like and what
	// the caller should do. Helps the LLM diagnose without re-
	// running the call.
	ErrorModes string

	// Handler is the implementation invoked by Base.CallTool when
	// req.Name matches d.Name. Optional — if nil, Base.CallTool
	// returns an "unimplemented" error for that tool. Toolboxes that
	// dispatch via their own switch (legacy pattern) leave this nil.
	//
	// The handler is responsible for argument extraction, validation,
	// and response shaping. It must NOT panic; on internal error
	// return a CallToolResponse with the error string set.
	Handler func(ctx context.Context, req *toolboxv0.CallToolRequest) *toolboxv0.CallToolResponse
}

ToolDefinition is the single source of truth for one tool's metadata. Toolboxes hold a []ToolDefinition; helpers project to the three proto envelopes.

Field semantics mirror the proto messages — see proto/codefly/services/toolbox/v0/toolbox.proto for canonical docs. Brief notes here on the dual-description split:

func (*ToolDefinition) ToSpec

func (d *ToolDefinition) ToSpec() *toolboxv0.ToolSpec

ToSpec returns the full spec returned by DescribeTool.

func (*ToolDefinition) ToSummary

func (d *ToolDefinition) ToSummary() *toolboxv0.ToolSummary

ToSummary returns the lightweight catalog entry used by ListToolSummaries.

func (*ToolDefinition) ToTool

func (d *ToolDefinition) ToTool() *toolboxv0.Tool

ToTool returns the legacy heavy envelope used by ListTools.

type Tooler

type Tooler interface {
	Tools() []*ToolDefinition
}

Tooler exposes a toolbox's tool list. Base uses this virtual to project the four RPC envelopes — the embedding plugin defines Tools() once, gets ListTools/ListToolSummaries/DescribeTool/ CallTool for free.

Jump to

Keyboard shortcuts

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