mirror of
https://github.com/patriceckhart/zot.git
synced 2026-06-26 21:36:31 +02:00
Single Go module, four top-level packages under packages/. Import
paths become github.com/patriceckhart/zot/packages/<name>; downstream
consumers can depend on individual packages without pulling the rest.
Layout:
packages/provider/ LLM clients + catalog
packages/provider/auth/ credential store + OAuth + login server
packages/core/ agent loop, sessions, cost
packages/tui/ terminal toolkit + chat view
packages/agent/ CLI wiring, system prompt
extensions/ extproto/ modes/ tools/ skills/ swarm/
sdk/ (was pkg/zotcore, package renamed zotcore -> sdk)
ext/ (was pkg/zotext, package renamed zotext -> ext)
internal/ and pkg/ removed. The internal/assets logo moved into
packages/provider/auth/assets.
Public Go SDK identifiers renamed:
pkg/zotcore (package zotcore) -> packages/agent/sdk (package sdk)
pkg/zotext (package zotext) -> packages/agent/ext (package ext)
This breaks Go-based extensions and embedders; the JSON wire protocol
for extensions and RPC is unchanged, so non-Go extensions, already-
built extension binaries, and zot rpc consumers are unaffected.
Docs, examples, and the built-in write-zot-extension skill updated
for the new paths and identifiers. Shadow-bug fixes in code samples
(ext := ext.New -> e := ext.New).
59 lines
1.1 KiB
Go
59 lines
1.1 KiB
Go
package provider
|
|
|
|
import (
|
|
"bufio"
|
|
"io"
|
|
"strings"
|
|
)
|
|
|
|
// sseEvent is one parsed event from a text/event-stream.
|
|
type sseEvent struct {
|
|
Event string // value of "event:" field (may be empty)
|
|
Data string // concatenated "data:" lines
|
|
}
|
|
|
|
// readSSE reads events from r and sends them on out. It closes out when r
|
|
// is exhausted or a read error occurs.
|
|
func readSSE(r io.Reader, out chan<- sseEvent) {
|
|
defer close(out)
|
|
sc := bufio.NewScanner(r)
|
|
sc.Buffer(make([]byte, 0, 64*1024), 10*1024*1024)
|
|
|
|
var ev sseEvent
|
|
flush := func() {
|
|
if ev.Data == "" && ev.Event == "" {
|
|
return
|
|
}
|
|
out <- ev
|
|
ev = sseEvent{}
|
|
}
|
|
|
|
for sc.Scan() {
|
|
line := sc.Text()
|
|
if line == "" {
|
|
flush()
|
|
continue
|
|
}
|
|
if strings.HasPrefix(line, ":") {
|
|
// comment / keep-alive
|
|
continue
|
|
}
|
|
field, value, ok := strings.Cut(line, ":")
|
|
if !ok {
|
|
field = line
|
|
value = ""
|
|
}
|
|
// optional single leading space after ':'
|
|
value = strings.TrimPrefix(value, " ")
|
|
switch field {
|
|
case "event":
|
|
ev.Event = value
|
|
case "data":
|
|
if ev.Data != "" {
|
|
ev.Data += "\n"
|
|
}
|
|
ev.Data += value
|
|
}
|
|
}
|
|
flush()
|
|
}
|