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

core

module
v0.13.2 Latest Latest
Warning

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

Go to latest
Published: Oct 16, 2026 License: Apache-2.0

README

looprig/core

github.com/looprig/core is the foundation module of the Looprig ecosystem. It holds the vocabulary every other module shares: conversation content (messages, content blocks, streaming chunks, token usage), a v4 UUID, a dependency-injected log/slog constructor, and version 1 of the transport-neutral session wire contract that Factory, Host, Harness and web clients speak to each other.

It is a tier-0 leaf: it depends on no other Looprig module and has no third-party runtime dependencies (the tool directives in go.mod are development tools only).

Install

go get github.com/looprig/core@latest

Packages

Package Purpose
content The sealed Block union (TextBlock, ThinkingBlock, ToolUseBlock, ToolResultBlock, ImageBlock, DocumentBlock, AudioBlock, ...), streaming Chunk types, messages (UserMessage, AIMessage, AgenticMessages), usage accounting, JSON codecs (MarshalBlock/UnmarshalBlock) and faithful copies (CloneBlock/CloneBlocks).
content/streamaccumulator Pure converters that fold streamed chunks into complete blocks (text, thinking, tool uses, refusals, images).
content/blocktest Test helper that builds fully populated block fixtures by reflection, so copy/encode/decode paths are checked field by field.
logging New(Config) builds a *slog.Logger for a composition root to inject; there is no package-level logger and slog.SetDefault is never called.
uuid Stdlib-only v4 UUID: New, strict Parse/MustParse, String, IsZero, text marshalling.
sessionwire/v1 Version 1 of the session wire contract: typed IDs, public session records (create/input/interrupt/restore/gate-response requests, command status, journal and gate pages, session status and summaries, publications, error envelopes), version negotiation, and the HostLink records and framing between Factory and Host.

content.Block is sealed: only the content package can add variants. Provider opaque reasoning state travels in ProviderState/ProviderStateFormat on the blocks that carry it; code that copies blocks should use content.CloneBlock rather than a hand-written struct literal, and can pin that with blocktest.

Usage

Adapted from examples/content/example_test.go:

request := &content.UserMessage{Message: content.Message{
	Role: content.RoleUser,
	Blocks: []content.Block{
		&content.TextBlock{Text: "Summarize the report."},
		&content.DocumentBlock{
			MediaType: content.MediaTypeDocumentText,
			Name:      "report.txt",
			Text:      "Revenue increased.",
		},
	},
}}

wire, err := content.MarshalBlock(request.Blocks[1])
if err != nil {
	return err
}
decoded, err := content.UnmarshalBlock(wire)
if err != nil {
	return err
}
document := decoded.(*content.DocumentBlock)

Further runnable examples live under examples/ (content, streaming, usage, logging, uuid) and run with go test ./examples/....

Session wire contract (sessionwire/v1)

Every record has a checked-in JSON Schema (draft 2020-12) under sessionwire/v1/schema/ and a golden fixture under sessionwire/v1/testdata/fixtures/; tests hold the Go types, schemas and fixtures together, and sessionwire/v1/testdata/exported_api.txt pins the exported API. Decoders are strict and refuse unknown fields, except the version-negotiation response, which is tolerant so that new optional members stay additive.

HostLink specifics a Factory or Host implementer needs:

  • Connect framing. The connect request and reply are the bare VersionNegotiationRequest/VersionNegotiationResponse; use EncodeHostLinkConnectRequest/DecodeHostLinkConnectRequest and EncodeHostLinkConnectReply/DecodeHostLinkConnectReply, which refuse a wrapped shape.
  • Method names and channels. The HostLinkMethod* constants name the RPC methods; command delivery is sent on HostLinkChannel(tenant, session) (prefix HostLinkChannelPrefix).
  • Capabilities. A Host lists the methods and capability tokens it supports in the negotiation reply's hostlink_methods; check them with VersionNegotiationResponse.Supports. Capability tokens are not methods: HostLinkCapabilityGateResponse (hostlink.command.gate_response) gates gate responses, and HostLinkCapabilityAttributionPrincipal (hostlink.attribution.principal) gates any command carrying principal or metadata, and HostLinkCapabilityPayloadReference (hostlink.payload.reference) gates placing a session whose pending command body is stored by reference (above SessionStore's 64 KiB inline bound). A Factory must not send a command a Host's reply does not support, and must not send hostlink.attach to a Host that does not advertise it.
  • Addressing. A Host advertises a bare base endpoint (ws/wss scheme and authority, no path). Each tenant's HostLink address is derived with HostLinkEndpoint(base, tenant) (base + HostLinkPathPrefix + escaped tenant); refusals are a typed HostLinkEndpointError. A Host behind a path-prefixed ingress must use host-based routing, a port per Host, or in-cluster Service DNS instead.
  • Command principal and metadata. Every command request may carry an optional principal (Principal{Tenant, Subject, Kind}, kind actor or service): the verified sender, stamped only by a Factory, never by a client. create and input may also carry optional metadata (MessageMetadata, string values only): at most 16 fields; keys ^[a-z][a-z0-9_]{0,63}$, never beginning looprig; values at most 1024 bytes; 4096 bytes encoded. Failures are a typed MetadataValidationError that also unwraps to RequestValidationError (invalid_field, metadata). When both are absent a request is byte-identical to earlier releases.
  • Command IDs. DeterministicCommandID(domain, fields...) derives a retry-stable command ID from framed fields.

The wire version is 1; changes within v1 are additive and existing fixtures stay byte-identical.

Where it sits

Tier 0 of the Looprig release graph, with no Looprig dependencies. Nearly every other module depends on it directly (inference, harness, flow, sessionstore, factory, host, tools, tui, wui and more), so a core release is published before any dependent names it.

Development

The module targets Go 1.26.9.

GOWORK=off go test ./...   # standalone, against the pinned go.mod
make test                  # go test -race ./...
make fmt                   # gofmt in place
make lint                  # fmt-check + vet + staticcheck + gosec
make secure                # lint + vuln (go mod verify + govulncheck)
make check                 # fmt-check, vet, staticcheck, gosec, govulncheck, tests, build
make fuzz                  # prints how to run the fuzz targets

Dependencies are pinned by go.mod/go.sum; the module is not vendored. See CONTRIBUTING.md for contribution guidelines.

License

Apache License 2.0. See LICENSE.

Directories

Path Synopsis
Package content defines the unified content vocabulary shared across all internal packages.
Package content defines the unified content vocabulary shared across all internal packages.
blocktest
Package blocktest builds fully populated content.Block fixtures by reflection so every copy, encode, and decode path in the workspace can be tested for FIELD-BY-FIELD completeness rather than for the handful of fields whose names a hand-written fixture happened to mention.
Package blocktest builds fully populated content.Block fixtures by reflection so every copy, encode, and decode path in the workspace can be tested for FIELD-BY-FIELD completeness rather than for the handful of fields whose names a hand-written fixture happened to mention.
streamaccumulator
Package streamaccumulator folds streaming content chunks into complete content blocks.
Package streamaccumulator folds streaming content chunks into complete content blocks.
Package logging builds the application's structured logger on top of the standard library's log/slog.
Package logging builds the application's structured logger on top of the standard library's log/slog.
sessionwire
v1
Package v1 defines version 1 of Looprig's transport-neutral session wire contract.
Package v1 defines version 1 of Looprig's transport-neutral session wire contract.
Package uuid is a stdlib-only v4 UUID: type UUID [16]byte, New (v4 via crypto/rand), strict Parse/MustParse (8-4-4-4-12, errors.Is-able sentinel), String, IsZero, and MarshalText/UnmarshalText.
Package uuid is a stdlib-only v4 UUID: type UUID [16]byte, New (v4 via crypto/rand), strict Parse/MustParse (8-4-4-4-12, errors.Is-able sentinel), String, IsZero, and MarshalText/UnmarshalText.

Jump to

Keyboard shortcuts

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