sse-streaming
sse-streaming
Handle SSE streaming implementation, debugging, and reconnection for pplx-sdk.
When to use
Use this skill when implementing, debugging, or extending SSE streaming functionality for the Perplexity API.
Instructions
SSE Protocol Format
The Perplexity API uses standard SSE format:
event: query_progress
data: {"status": "searching", "progress": 0.5}
event: answer_chunk
data: {"text": "partial token", "backend_uuid": "uuid-here"}
event: final_response
data: {"text": "complete answer", "cursor": "cursor-value", "backend_uuid": "uuid-here"}
: [end]
Parsing Rules
- Read line-by-line from streaming response
- Skip lines starting with
:(comments) — except check for[end]marker - Parse
event: <type>lines → set current event type - Parse
data: <json>lines →json.loads()into payload - Empty line → emit event (type + accumulated data), reset buffers
- Stop on
[end]marker
Event Types
| Event | Purpose | Key Fields |
|---|---|---|
query_progress |
Search progress | status, progress |
search_results |
Source citations | sources[] |
answer_chunk |
Partial token | text |
final_response |
Complete answer | text, cursor, backend_uuid |
related_questions |
Follow-up suggestions | questions[] |
error |
Server error | message, code |
Stream Lifecycle
for chunk in transport.stream(query="...", context_uuid="..."):
if chunk.type == "answer_chunk":
print(chunk.text, end="", flush=True) # Incremental display
elif chunk.type == "final_response":
entry = Entry(...) # Build complete entry
break
Reconnection with Cursor
When a stream disconnects, resume using the cursor from the last final_response:
cursor = last_chunk.data.get("cursor")
backend_uuid = last_chunk.backend_uuid
payload["cursor"] = cursor
payload["resume_entry_uuids"] = [backend_uuid]
Retry with Exponential Backoff
from pplx_sdk.shared.retry import RetryConfig
config = RetryConfig(
max_retries=3,
initial_backoff_ms=1000, # 1s, 2s, 4s
max_backoff_ms=30000,
backoff_multiplier=2.0,
jitter=True, # ±25% randomization
)
Common Pitfalls
- Don't parse non-JSON data lines: Wrap
json.loads()in try/except - Handle empty streams: Raise
StreamingErrorif no events received - Buffer multi-line data: Some
data:fields span multiple lines; accumulate until empty line - Respect
[end]marker: Always check for[end]in comment lines to stop iteration
More from pv-udpv/pplx-sdk
code-analysis
Deep code analysis for pplx-sdk — parse Python AST, build dependency graphs, extract knowledge graphs, detect patterns, and generate actionable insights about code structure, complexity, and relationships. Use when analyzing code quality, mapping dependencies, or building understanding of the codebase.
19spa-reverse-engineer
Reverse engineer Single Page Applications built with React + Vite + Workbox — analyze SPA internals via Chrome DevTools Protocol (CDP), write browser extensions, intercept service workers, and extract runtime state for SDK integration.
19reverse-engineer
Reverse engineer Perplexity AI web APIs — intercept browser traffic, decode undocumented endpoints, map request/response schemas, extract auth flows, and translate discoveries into SDK code.
18api-design-principles
Master REST and GraphQL API design principles to build intuitive, scalable, and maintainable APIs that delight developers. Use when designing new APIs, reviewing API specifications, or establishing API design standards.
18test-fix
Diagnose and fix failing pytest tests in the pplx-sdk project, following existing test patterns and conventions.
17ast-grep
Guide for writing ast-grep rules to perform structural code search and analysis. Use when users need to search codebases using Abstract Syntax Tree (AST) patterns, find specific code structures, or perform complex code queries that go beyond simple text search. This skill should be used when users ask to search for code patterns, find specific language constructs, or locate code with particular structural characteristics.
17