Documentation
¶
Overview ¶
Package textreplace implements the BUILD-phase "text-replace" plugin described in uiux-research/plugin-b-c-spec.md §7.1.
One plugin instance can serve BOTH directions: rules under "up" rewrite inbound request content before forwarding, rules under "down" rewrite outbound response content before it reaches the client. Either side may be empty — that side becomes a no-op while the other still runs.
Matching is literal substring (strings.ReplaceAll). Regex / case- insensitive variants are deferred per spec §7.1 "Out of scope for MVP."
Carve-out (spec §10.6) enforcement:
- BEFORE only touches Message ContentPart text payloads (Type=="text"). tool_use / tool_result / image / audio parts are left alone.
- AFTER streaming registers OnContentDelta only. tool_use input_json_delta events are routed to a distinct class by the W1 classifier and never reach the registered content transform — this plugin neither inspects nor mutates tool-call argument JSON.
Index ¶
Constants ¶
const Type = "text-replace"
Type is the operator-facing type name registered with v2.RegisterBuiltin. Stable wire string; do not change without a config migration.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// Routes is a list of path patterns the plugin applies to. Empty list
// means "all paths." Pattern semantics mirror pathfilter:
// - exact match: "/v1/messages"
// - trailing-"*" prefix: "/v1/*"
Routes []string `json:"routes"`
// Up is applied to request content before forwarding.
Up []Rule `json:"up"`
// Down is applied to response content before client send.
Down []Rule `json:"down"`
}
Config is the parsed instance config. The viewer Settings form (W4) reads ConfigSchema() to render this shape; YAML / runtime_overrides JSON encode into the same field names.
type Plugin ¶
type Plugin struct {
// contains filtered or unexported fields
}
Plugin implements both v2.BeforePlugin and v2.AfterPlugin. A single instance can mutate request content (Up), response content (Down), or both — empty rule slices make the corresponding direction a no-op.
func New ¶
New parses cfg, validates it, and returns a ready Plugin. Used by the builtin Ctor and directly by tests (tests bypass the global registry so the package-level init's RegisterBuiltin call does not get hit twice).
func (*Plugin) ConfigSchema ¶
ConfigSchema returns the form descriptor consumed by the viewer Settings UI (W4). The shape mirrors spec §8.6; W3 may canonicalize field-naming conventions across all plugins when the API surface lands, but the field set here is plugin-specific and stable.
func (*Plugin) OnAfter ¶
func (p *Plugin) OnAfter(_ context.Context, req *v2.ParsedRequest, ac *v2.AfterContext, _ map[string]any) v2.AfterResult
OnAfter has two branches:
Streaming (ac.Response == nil): register an OnContentDelta transform that applies each Down rule in declared order to the content delta text. Tool-use deltas are routed to a separate class by W1's classifier and never reach this transform — the §10.6 carve-out is enforced at the framework layer; no defensive guard is needed here.
Non-streaming (ac.Response != nil): walk the rules over ParsedResponse.Content. If anything changed return ActionMutate with a shallow clone (Content / Reasoning are strings; no slice aliasing is at risk).
Returns ActionContinue when the route does not match, Down is empty, or no text changed.
func (*Plugin) OnBefore ¶
func (p *Plugin) OnBefore(_ context.Context, req *v2.ParsedRequest, _ map[string]any) v2.BeforeResult
OnBefore applies p.cfg.Up rules to text-content parts of every Message. Returns ActionContinue (without rebuilding the request) when:
- the route does not match
- there are no Up rules
- no text payload changed after substitution
On match the returned ParsedRequest is a deep-enough clone that the caller's original is untouched (see spec §2.3 "treat ParsedRequest as logically read-only").
type Schema ¶
type Schema struct {
Fields []SchemaField `json:"fields"`
}
Schema and SchemaField are the per-plugin form descriptor used by the viewer Settings panel (spec §8.6). The canonical project-wide shape is owned by W3; this local pair is the minimum surface W4 needs while W3's API package is still in flight. Once W3 publishes the canonical type, plugins migrate to it.