Files
insomnia/packages/insomnia-data
Bingbing a7c5ca4799 feat(SSE): add stream summary extraction for SSE responses (#10455)
[INS-3702](https://konghq.atlassian.net/browse/INS-3702)

## Summary
- Extracts a JSONPath from each streaming SSE message and concatenates it into one readable transcript, shown in a new "Summary" tab next to Events — useful for debugging LLM streaming APIs (OpenAI, Anthropic, Gemini) without scrolling through raw chunks.
- Auto-infers the JSONPath from the request URL for known provider endpoints (OpenAI Chat Completions/legacy Completions/Responses, Anthropic Messages, Google Gemini streamGenerateContent), matched by pathname only (not full URL/host), so self-hosted or reverse-proxied endpoints that keep the same path shape still match. Falls back to a manually-editable path otherwise.
- Handles curl's SSE event log being chunk-granular rather than frame-granular (a JSON payload can span multiple raw network reads, or multiple SSE frames can land in one chunk) by reconstructing the raw wire text and re-parsing `data:` frames properly.
- Handles Gemini's default `streamGenerateContent` response (no `?alt=sse`), which is a single top-level JSON array with no `data:` frames and no blank lines between elements, by scanning the array's bracket/brace depth by hand and pulling out whichever elements have fully closed so far — including mid-stream, before the array's closing `]` (or even the last element's own closing `}`) has arrived — so the summary renders progressively instead of only after the full response finishes.
- Summary tab defaults to selected when the URL matches a known provider, otherwise Events stays default. Plain text/Markdown render toggle for the summary output.
- Scoped to `curl` (SSE) responses only — WebSocket, `socketIO`, and `mcp` responses are untouched.
2026-09-07 08:06:42 +00:00
..

insomnia-data

A runtime-agnostic data layer for Insomnia, based on interface + IoC.

Core idea

  • src/: runtime-agnostic contracts (IDatabase, Services, model metadata/types)
  • node-src/: Node/main concrete implementations (createNedbDatabase, servicesNodeImpl)
  • entry points wire once:
    • initDatabase(impl)
    • initServices(impl)

After wiring, business code always uses the same APIs: database, services, models.

Process flows

Database (main / renderer / inso)

flowchart LR
    subgraph Renderer
        R0[initDatabase] --> R1[clientDatabase implementation]
        R2[feature code] --> R3[database from insomnia-data]
        R3 --> R1
        R1 --> R4[window.database.invoke]
        R4 --> R5[ipcRenderer.invoke database.invoke]
    end

    subgraph Main
        M0[initDatabase] --> M1[mainDatabase implementation]
        M1 --> M2[createNedbDatabase impl]
        M2 --> M3[(NeDB)]
        M4[main feature code] --> M5[database from insomnia-data]
        M5 --> M1
        M6[ipcMain.handle database.invoke] --> M1
        M1 --> M7[webContents.send db.changes]
    end

    subgraph Inso
        I0[initDatabase] --> I1[inso database implementation]
        I1 --> I2[createNedbDatabase impl]
        I2 --> I3[(NeDB)]
        I4[inso feature code] --> I5[database from insomnia-data]
        I5 --> I1
    end

    R5 --> M6
    M7 -.notify.-> R2

Services (main / renderer / inso)

flowchart LR
    subgraph Renderer
        R0[initServices] --> R1[preload servicesProxy implementation]
        R2[feature code] --> R3[services from insomnia-data]
        R3 --> R1
        R1 --> R4[ipcRenderer.invoke services.invoke]
    end

    subgraph Main
        M0[initServices] --> M1[servicesNodeImpl]
        M2[feature code] --> M3[services from insomnia-data]
        M3 --> M1
        M1 --> M4[service logic]
        M4 --> M5[database]
        M5 --> M6[(NeDB)]
        M7[ipcMain.handle services.invoke] --> M1
    end

    subgraph Inso
        I0[initServices] --> I1[servicesNodeImpl]
        I2[feature code] --> I3[services from insomnia-data]
        I3 --> I1
        I1 --> I6[(NeDB)]
    end

    R4 --> M7

Renderer services path:

services.xxx -> preload proxy -> IPC -> main handler -> servicesNodeImpl -> database.

Why this design

  • Same API across runtimes: main, renderer, inso.
  • Feature code is decoupled from Electron/IPC/NeDB details.
  • Renderer has a safer boundary (bridge + IPC, no direct DB internals and node API access).
  • Easy to test or swap implementations by injecting at startup.

Minimal usage

Main

import { initDatabase, initServices } from 'insomnia-data';
import { mainDatabase } from '~/main/database.main';
import { servicesNodeImpl } from 'insomnia-data/node';

await initDatabase(mainDatabase);
initServices(servicesNodeImpl);

Renderer

import { initDatabase, initServices } from 'insomnia-data';
import { clientDatabase } from '~/ui/database.client';

await initDatabase(clientDatabase);
initServices(window._dataServices);

Inso / Node

import { initDatabase, initServices } from 'insomnia-data';
import { createNedbDatabase, servicesNodeImpl } from 'insomnia-data/node';

await initDatabase(createNedbDatabase());
initServices(servicesNodeImpl);

Consuming

import { services, models, type Request } from 'insomnia-data';

const mcpRequest = await services.mcpRequest.create({ url: 'http://localhost:3000' });
const all = await services.mcpRequest.all();

const request: Request = {};

const requestType = models.request.type;