Bläck StudioPlugin SDK v1.0.0 · API 4
Contents

Start

Building

Beyond Bläck Studio

How it runs

Sharing

Look up

The network

A plugin reaches the internet only through this.app.net, and only the hosts its manifest names (network:api.example.com) that the writer allowed. Requests go over https; plain http is allowed only to this computer (localhost, 127.0.0.1), for trying a plugin against a server of your own. Redirects aren't followed.

app.net.fetch(url, init?) gets the whole answer, up to 20 MB, within 30 seconds:

const res = await this.app.net.fetch('https://api.example.com/words', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ text }),
})
if (res.ok) console.log(res.json())   // also res.text(), res.bytes(), res.status, res.headers

app.net.stream(url, init, onChunk) passes the answer on as it comes, each piece to onChunk as text: an AI's reply, word by word, say. It resolves, when the answer is done, with its status and headers. It runs up to ten minutes, and 200 MB.

const status = this.addStatusBarItem({ id: 'reply', text: '' })
let reply = ''
const res = await this.app.net.stream(
  'https://api.example.com/v1/chat',
  { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt, stream: true }) },
  (text) => {
    reply += text
    status.setText(reply.slice(-40))
  },
)
if (!res.ok) this.app.ui.notify(`The service answered ${res.status}`)

Each piece is text as it arrived, not a whole line or message. An event stream's data: lines can be split across pieces, so gather them before reading them.

There's one catch with a text/plain answer: without the header X-Content-Type-Options: nosniff it may arrive whole, up to its first 512 bytes, because Chromium reads that much to guess what kind of answer it is. Event streams (text/event-stream, what AI services send) and JSON arrive as they're sent.

Both work the same in a sandboxed plugin. A plugin can't open a WebSocket.