ai newsFr., 16. Okt.
EilmeldungMCP vs LLM Function Calling: When Should You Adopt the Model Context Protocol?

I kept hitting jq: parse error on AI streams, so I built sjq

If you work with LLMs, you've done this: curl -N | jq . And you've seen this: jq: parse error: Invalid numeric literal at line 1, column 9 Column 9. That's where data: ends and the JSON begins. An SSE stream isn't JSON — it's a framing protocol: data: {...} lines separated by blank lines, [DONE] at

dev.toFreitag 02:44 · 16.10.2 Min. Lesezeit
Bild: dev.to

If you work with LLMs, you've done this: curl -N <streaming endpoint> | jq. And you've seen this:

jq: parse error: Invalid numeric literal at line 1, column 9 Enter fullscreen mode Exit fullscreen mode Column 9. That's where data: ends and the JSON begins. An SSE stream isn't JSON — it's a framing protocol: data: {...} lines separated by blank lines, [DONE] at the end. jq never stood a chance.

So I built sjq — jq, but for AI streaming. A small Rust CLI that parses OpenAI-compatible server-sent event streams ( /v1/chat/completions and /v1/responses ) and prints one short line per event, showing only what each event added.

sjq curl -s $BASE /v1/chat/completions \ -H "Authorization: Bearer $KEY " -H 'Content-Type: application/json' \ -d '{"model":"gemini-4-argon","stream":true,"messages":[{"role":"user","content":"hi"}]}' Enter fullscreen mode Exit fullscreen mode model: gemini -4 -argon role: assistant data: 'Hi' data: ' there' data: ' 👋' … time: ttft= 0.42 s total= 3.1 s tok/s= 258.2 Enter fullscreen mode Exit fullscreen mode Instead of 99% envelope JSON, you watch the actual content arrive — plus a timing line: TTFT, total, tokens/sec. Run through sjq curl and it also breaks out connect, TLS handshake, and TTFB, which is genuinely useful when you're debugging a slow provider.

It understands tool calls (name + arguments as they stream in), reasoning_content, refusals, logprobs, usage blocks, and multiple choices — each rendered as its own labeled line.

brew tap vivgrid/tap brew trust vivgrid/tap # Homebrew 6+ requires trusting third-party taps brew install sjq Enter fullscreen mode Exit fullscreen mode Or from source: cargo install --git https://github.com/vivgrid/sjq (one dependency: serde_json ).

You can — sed 's/^data: //' | jq — and plenty of people do. But then you're staring at full envelope objects per chunk: ids, timestamps, object: "chat.completion.chunk", finish_reason: null fifty times over. The signal (the tokens) drowns in the envelope. sjq inverts that: the delta is the output; the envelope gets summarized once.

MIT licensed, single binary. The repo ships 14 test fixtures covering the gnarly edges: multi-line data payloads, mid-stream errors, parallel tool calls, logprobs, CJK/emoji text.

Repo: https://github.com/vivgrid/sjq — feedback and weird streams welcome.

Quelle: dev.to (dev.to). Original öffnen