feat: add cog playground browser UI#3086
Conversation
- Render boolean inputs as a true/false select so optional booleans no longer show two checkboxes (the include toggle plus the value checkbox) - Start optional fields without a real default unchecked: treat a null/None default as "no default" so they are omitted rather than sending an explicit null - Add a tooltip clarifying the optional-field include checkbox
- Move run controls (mode, id, Run/Stop/Reset) into a sticky top action bar so they stay reachable without scrolling - Vendor Ace (buildless) and use it for all JSON: editable inputs (Form/JSON view and dict/object fields), read-only outputs and the Raw view, with code folding, light/dark theme binding, and a Copy button - Hide the metrics table in the Raw view (already part of the payload) - Use fixed-height editors with internal scroll so drag-selection autoscrolls, and keep normal full-page scrolling - Surface error responses in the Raw view
|
I'm Bonk, and I've done a quick review of your PR. This PR adds a I found two issues: 1. SSE newline injection in In _, _ = fmt.Fprintf(w, "data: %s\n\n", msg)The SSE spec requires each line of a Fix: split the payload by newlines and emit a for _, line := range strings.Split(string(msg), "\n") {
_, _ = fmt.Fprintf(w, "data: %s\n", line)
}
_, _ = fmt.Fprint(w, "\n")2. Missing
|
|
I'm Bonk, and I've done a quick review of your PR. This PR adds a I found two issues: 1. SSE newline injection in In _, _ = fmt.Fprintf(w, "data: %s\n\n", msg)The SSE spec requires each line of a Fix: split the payload by newlines and emit a for _, line := range strings.Split(string(msg), "\n") {
_, _ = fmt.Fprintf(w, "data: %s\n", line)
}
_, _ = fmt.Fprint(w, "\n")2. Missing
|
- handleEvents prefixes every line of a relayed webhook payload with 'data: ' so embedded newlines can't end the SSE event early or inject spoofed event:/data: fields; add a regression test - list playground.go and the playground/ asset dir in architecture/06-cli.md
There was a problem hiding this comment.
I'm Bonk, and I've done a quick review of your PR.
This PR adds a cog playground command with a browser-based UI, Go reverse proxy, webhook sink, and SSE relay for interacting with running Cog models.
I found three issues:
-
SSE newline injection in
pkg/cli/playground.go(HIGH)
Webhook payloads are written directly into SSE data lines without escaping newlines. A payload containing\n\nwould prematurely terminate the event, and lines starting withevent:ordata:could inject spoofed events. -
Missing test for SSE newline escaping (MEDIUM)
TestPlaygroundWebhookRelaytests the happy path but doesn't verify that webhook payloads containing newlines are properly escaped in the SSE stream. -
Missing
playground.goin architecture docs file tree (LOW)
architecture/06-cli.mdlists CLI source files but omitsplayground.goandplayground_test.go.
|
Posted a batch review on PR #3086 with three comments:
|
|
LGTM |
|
LGTM |
Vendor the Kumo UI semantic color tokens (vendor/kumo.css) and move the playground's inline CSS into styles.css built on those tokens. Light/dark now flips via the data-mode attribute Kumo keys off of (was data-theme). Also retheme the Ace JSON editors to match: register token-driven kumo-light/kumo-dark themes and drop the vendored chrome/tomorrow_night theme files. Extend the UI-serving test to assert both stylesheets ship.
|
LGTM |
Closes #649
Adds a
cog playgroundcommand: a local web server that serves a schema-driven, Postman-like browser UI and reverse-proxies to a running model API (e.g.cog serve). It reflects the model's OpenAPI schema and supports sync, streaming (SSE), and async (webhook) predictions, with form or raw-JSON input.The browser only talks to the playground's own origin, which proxies to the target chosen at runtime (via
X-Cog-Target) — sidestepping CORS and keeping SSE intact — and hosts a webhook sink that relays async events back over SSE.flowchart LR Browser["Browser UI"] subgraph Playground["cog playground (host)"] Static["Static UI assets<br/>(go:embed)"] Proxy["Reverse proxy<br/>/proxy/*"] Sink["Webhook sink + relay<br/>/webhook/{token} → /events"] end Model["Target model API<br/>(e.g. cog serve)"] Browser -->|"load UI"| Static Browser -->|"schema, predictions, SSE"| Proxy Proxy -->|"X-Cog-Target"| Model Model -->|"webhook (async)"| Sink Sink -->|"SSE events"| BrowserUsage: run
cog servein one terminal andcog playgroundin another.The UI is plain HTML/JS embedded via
go:embed(no build step; Ace vendored for JSON editing). Documented indocs/cli.mdandarchitecture/06-cli.md. Also bumps thestreaming-textexample to Python 3.13.