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 ¶
- func AsSummaries(defs []*ToolDefinition, tagsFilter []string) []*toolboxv0.ToolSummary
- func AsTools(defs []*ToolDefinition) []*toolboxv0.Tool
- func FindSpec(defs []*ToolDefinition, name string) *toolboxv0.ToolSpec
- type Base
- func (b *Base) CallTool(ctx context.Context, req *toolboxv0.CallToolRequest) (*toolboxv0.CallToolResponse, error)
- func (b *Base) DescribeTool(_ context.Context, req *toolboxv0.DescribeToolRequest) (*toolboxv0.DescribeToolResponse, error)
- func (b *Base) ListToolSummaries(_ context.Context, req *toolboxv0.ListToolSummariesRequest) (*toolboxv0.ListToolSummariesResponse, error)
- func (b *Base) ListTools(_ context.Context, _ *toolboxv0.ListToolsRequest) (*toolboxv0.ListToolsResponse, error)
- type ToolDefinition
- type Tooler
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.
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 (*Base) CallTool ¶
func (b *Base) CallTool(ctx context.Context, req *toolboxv0.CallToolRequest) (*toolboxv0.CallToolResponse, error)
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 ¶
func (b *Base) DescribeTool(_ context.Context, req *toolboxv0.DescribeToolRequest) (*toolboxv0.DescribeToolResponse, error)
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 ¶
func (b *Base) ListToolSummaries(_ context.Context, req *toolboxv0.ListToolSummariesRequest) (*toolboxv0.ListToolSummariesResponse, error)
ListToolSummaries (catalog) — lightweight, with optional tags filter. AND semantics: every tag in tags_filter must be present.
func (*Base) ListTools ¶
func (b *Base) ListTools(_ context.Context, _ *toolboxv0.ListToolsRequest) (*toolboxv0.ListToolsResponse, error)
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.