attachserve

package
v1.111.0 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package attachserve resolves a prompt's attached resources (#1013) into the form each serving surface needs: MCP content items appended to a prompts/get result, and a JSON summary carried by manage_prompt use.

It exists as its own package because it is the one place that needs both pkg/prompt (the attachment links) and pkg/resource (the material, its permissions, and its blobs), and both the MCP prompt layer and the REST attachment handler consume it. Putting it in either of those packages would point a dependency edge the wrong way.

The resolver never fails a prompt. A prompt whose attachment is unreadable, deleted, or unfetchable still serves: the material is reported as unavailable, missing, or unreadable, and the prompt text is unaffected. A procedure that has lost its template is still a procedure, and telling the agent the template is gone is strictly better than refusing to answer.

Index

Constants

View Source
const DefaultInlineLimit = 64 * 1024

DefaultInlineLimit caps how many bytes of a text attachment are embedded directly in a served prompt. Above it the attachment becomes a resource link the client can read on demand.

64 KiB is chosen to match the largest reference material that is still plausibly worth spending prompt context on unconditionally; a report template or checklist is far below it, a full data extract is far above.

Variables

This section is empty.

Functions

func Content

func Content(items []Resolved) []mcp.Content

Content renders resolved attachments as MCP prompt-message content: embedded resources carry the full text, linked resources carry a resource_link the client can read, and anything the caller cannot reach is summarized in a single trailing note.

The framing text is deliberately directive. An agent that receives a template alongside a procedure must fill that template rather than invent its own formatting, and the only place to say so is here, next to the material.

func ScopeOf

ScopeOf projects a resource onto the fields the scope rule needs.

func Summary

func Summary(items []Resolved) []map[string]any

Summary renders resolved attachments for the manage_prompt use provenance block, so an agent can state exactly what materials it received. Unavailable entries carry their reason and nothing else.

Types

type Availability

type Availability string

Availability describes whether a prompt's attached material reached the caller, and if not, why.

const (
	// AvailableEmbedded means the full contents are inline in the result.
	AvailableEmbedded Availability = "embedded"
	// AvailableLinked means the caller received a resource link and must read
	// the resource to get its contents (too large to inline, or binary).
	AvailableLinked Availability = "linked"
	// UnavailableForbidden means the attachment exists but this caller cannot
	// read it. Nothing identifying is disclosed alongside it, not even the
	// resource id: the caller has no repair action, and an id would be an
	// existence probe.
	UnavailableForbidden Availability = "unavailable"
	// UnavailableMissing means the resource was deleted after being attached.
	UnavailableMissing Availability = "missing"
	// UnavailableUnreadable means the resource could not be read. When its
	// metadata resolved and only the blob fetch failed, the link is served in
	// place of the contents; when the metadata read itself failed, nothing is
	// known about it and it is counted among the undelivered materials.
	UnavailableUnreadable Availability = "unreadable"
)

type BlobReader

type BlobReader interface {
	GetObject(ctx context.Context, bucket, key string) (body []byte, contentType string, err error)
}

BlobReader reads a resource's stored bytes. Satisfied by resource.S3Client.

type Deps

type Deps struct {
	Attachments prompt.AttachmentStore
	Resources   resource.Store
	Blobs       BlobReader
	Bucket      string

	// InlineLimit overrides DefaultInlineLimit when positive.
	InlineLimit int
}

Deps carries the collaborators the resolver needs. Attachments and Resources are required; a nil Blobs (or empty Bucket) degrades every text attachment to a link rather than failing, which is the correct behavior for a database-only deployment with no blob backend.

type Resolved

type Resolved struct {
	// ResourceID is always set, even when the resource is missing, because it
	// is what an author needs in order to repair a broken link.
	ResourceID string
	// Availability records the outcome. Every other field except ResourceID is
	// empty when it is UnavailableForbidden or UnavailableMissing: an
	// attachment the caller cannot read must not disclose its name, its
	// description, or its size.
	Availability Availability

	URI         string
	DisplayName string
	Description string
	MIMEType    string
	SizeBytes   int64

	// Text holds the contents when Availability is AvailableEmbedded.
	Text string
}

Resolved is one attachment after lookup, permission check, and (when the material is inlined) blob read.

type Resolver

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

Resolver resolves prompt attachments for a caller.

func New

func New(deps Deps) *Resolver

New builds a resolver. A nil result is a valid zero-attachment resolver, so callers need no nil checks at every serving site.

func (*Resolver) CheckPromotion

func (r *Resolver) CheckPromotion(ctx context.Context, promptID, targetScope string, targetPersonas []string) error

CheckPromotion reports whether a prompt's current attachments would still satisfy the scope rule at the target scope. It is the gate the promotion request and approval paths call, and it fails closed: a store error blocks the promotion rather than letting it through unchecked.

func (*Resolver) Resolve

func (r *Resolver) Resolve(ctx context.Context, promptID string, claims resource.Claims) []Resolved

Resolve returns a prompt's attachments in authored order, each evaluated for this caller. It returns nil for a prompt with no attachments, and nil rather than an error when the attachment store read fails: a store outage must not take down prompt serving.

func (*Resolver) Scopes

func (r *Resolver) Scopes(ctx context.Context, promptID string) ([]prompt.AttachmentScope, error)

Scopes returns the scope of every resource a prompt attaches, for the authoring-time rule in prompt.CheckAttachScope. It is deliberately caller-independent: the rule asks how widely a resource is visible, not whether one particular reader can see it.

A resource that no longer exists is skipped rather than reported: a broken link cannot violate a scope rule, and blocking a promotion on it would freeze the prompt against every edit until someone detached a link the portal already flags. Any other read failure does block, because an unknown scope is not a safe scope.

Jump to

Keyboard shortcuts

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