mirror of
https://github.com/zap-proto/zip.git
synced 2026-10-19 15:38:57 +00:00
A typed op could only take one JSON value and answer one, so uploads, signed webhooks, form posts, YAML and merge-patch bodies, PDFs, SSE, WebSockets, OAuth redirects and upstream relays stayed untyped routes with no schema, tool, command or SDK method. Each is now a typed op and its REST wire is unchanged. Requests: a zip.Body field takes the body and Content-Type exactly as sent; an In implementing Parser decodes itself; form: fields and *zip.File parts bind url-encoded and multipart forms; cookie: binds a request cookie as an in: cookie parameter. Consumes names the media. Answers: zip.Body (bytes, filename, its own status and headers, a Reader streams chunked), Verbatim[T] (a relay documented as T), Sse[T] (events with keep-alive), Socket[M] (an upgrade after the contract runs; 426 without one, 501 over ZAP), Redirect, CookieCoder, Produces, and unions: a type whose OneOf method's results are the alternatives, with Or[A,B] as the stock one filing each under the status it states. Projections follow from the manifest: the document publishes binary media, form schemas, x-events, x-socket with 101, 3xx with Location and oneOf; MCP takes bytes as base64 and returns bytes, text or collected events as tool content, listing a socket op in _meta as no tool; the CLI reads --body @file|-, --field name=@file and --out, prints events as they arrive and bridges a socket to stdin and stdout. tools/list is ProjectMCP over the manifest, the projection MCPTools already was. Prose reaches promoted fields (filed under the declaring struct), a type defined over another struct, and the type arguments of zip's kinds and OneOf results; an instantiated generic is published under its name followed by its argument names instead of an illegal component key. The unused reflect-only document and tool builders go.
77 lines
1.9 KiB
Go
77 lines
1.9 KiB
Go
// Package kinds answers with zip's kinds: an event stream, a union, an
|
|
// either-or and a relay, each of whose wire shapes is a type argument or a
|
|
// OneOf result.
|
|
package kinds
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/zap-proto/zip"
|
|
)
|
|
|
|
// Chunk is one event of a completion.
|
|
type Chunk struct {
|
|
// Text is the next piece of the completion.
|
|
Text string `json:"text"`
|
|
}
|
|
|
|
// Done is a completion answered whole.
|
|
type Done struct {
|
|
// Answer is the whole completion.
|
|
Answer string `json:"answer"`
|
|
}
|
|
|
|
// Upstream is the upstream's answer.
|
|
type Upstream struct {
|
|
// Model is the model the upstream ran.
|
|
Model string `json:"model"`
|
|
}
|
|
|
|
// Event is one ingested event.
|
|
type Event struct {
|
|
// Kind names the event.
|
|
Kind string `json:"kind"`
|
|
}
|
|
|
|
// Batch is several events at once.
|
|
type Batch struct {
|
|
// Events are the events, oldest first.
|
|
Events []Event `json:"events"`
|
|
}
|
|
|
|
// Ingest is one event or a batch.
|
|
type Ingest struct{ one *Event }
|
|
|
|
// OneOf declares the alternatives.
|
|
func (Ingest) OneOf() (Event, Batch) { return Event{}, Batch{} }
|
|
|
|
// Prompt asks for a completion.
|
|
type Prompt struct {
|
|
// Stream asks for events rather than one answer.
|
|
Stream bool `json:"stream"`
|
|
}
|
|
|
|
// Stream streams a completion.
|
|
func Stream(ctx context.Context, in *Prompt) (*zip.Sse[Chunk], error) { return &zip.Sse[Chunk]{}, nil }
|
|
|
|
// Either answers whole or streams, as asked.
|
|
func Either(ctx context.Context, in *Prompt) (*zip.Or[Done, zip.Sse[Chunk]], error) {
|
|
return &zip.Or[Done, zip.Sse[Chunk]]{}, nil
|
|
}
|
|
|
|
// Relay passes the upstream's answer through as sent.
|
|
func Relay(ctx context.Context, in *Prompt) (*zip.Verbatim[Upstream], error) {
|
|
return &zip.Verbatim[Upstream]{}, nil
|
|
}
|
|
|
|
// Take ingests what was sent.
|
|
func Take(ctx context.Context, in *Ingest) (*struct{}, error) { return nil, nil }
|
|
|
|
// Register declares the ops.
|
|
func Register(app *zip.App) {
|
|
app.Post("/v1/stream", Stream)
|
|
app.Post("/v1/either", Either)
|
|
app.Post("/v1/relay", Relay)
|
|
app.Post("/v1/ingest", Take)
|
|
}
|