thebird 1.2.15 → 1.2.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/docs/app.js +14 -23
  2. package/package.json +1 -1
package/docs/app.js CHANGED
@@ -14,7 +14,7 @@ async function fetchModels(apiKey) {
14
14
  .map(m => ({ id: m.name.replace('models/', ''), label: m.displayName || m.name }));
15
15
  }
16
16
 
17
- async function* streamGenerate(apiKey, model, contents) {
17
+ async function streamGenerate(apiKey, model, contents, onChunk) {
18
18
  const res = await fetch(`${BASE}/models/${model}:streamGenerateContent?alt=sse&key=${apiKey}`, {
19
19
  method: 'POST',
20
20
  headers: { 'Content-Type': 'application/json' },
@@ -38,7 +38,7 @@ async function* streamGenerate(apiKey, model, contents) {
38
38
  const chunk = JSON.parse(json);
39
39
  for (const c of (chunk.candidates || []))
40
40
  for (const p of (c.content?.parts || []))
41
- if (p.text && !p.thought) yield p.text;
41
+ if (p.text && !p.thought) onChunk(p.text);
42
42
  } catch {}
43
43
  }
44
44
  }
@@ -84,14 +84,7 @@ class BirdChat extends HTMLElement {
84
84
  if (this.state.apiKey) this.loadModels(this.state.apiKey);
85
85
  }
86
86
 
87
- setState(patch) {
88
- Object.assign(this.state, patch);
89
- this.render();
90
- if (this.streamWrap && !this.querySelector('#msg-list')?.contains(this.streamWrap)) {
91
- const list = this.querySelector('#msg-list');
92
- if (list) list.appendChild(this.streamWrap);
93
- }
94
- }
87
+ setState(patch) { Object.assign(this.state, patch); this.render(); }
95
88
 
96
89
  async loadModels(apiKey) {
97
90
  this.setState({ modelsLoading: true, status: '' });
@@ -163,26 +156,24 @@ class BirdChat extends HTMLElement {
163
156
  this.setState({ messages, streaming: true, status: '', streamingText: '' });
164
157
  try {
165
158
  let full = '';
166
- this.streamEl = document.createElement('div');
167
- this.streamEl.className = 'msg-bubble card bg-base-200 text-base-content px-4 py-3 text-sm leading-relaxed';
159
+ const streamEl = document.createElement('div');
160
+ streamEl.className = 'msg-bubble card bg-base-200 text-base-content px-4 py-3 text-sm leading-relaxed';
168
161
  const cursor = document.createElement('span');
169
162
  cursor.className = 'animate-pulse ml-1';
170
163
  cursor.textContent = '▋';
171
- this.streamWrap = document.createElement('div');
172
- this.streamWrap.className = 'flex justify-start';
173
- this.streamWrap.appendChild(this.streamEl);
174
- this.streamWrap.appendChild(cursor);
164
+ const wrap = document.createElement('div');
165
+ wrap.className = 'flex justify-start';
166
+ wrap.appendChild(streamEl);
167
+ wrap.appendChild(cursor);
175
168
  const list = this.querySelector('#msg-list');
176
- if (list) list.appendChild(this.streamWrap);
177
- for await (const chunk of streamGenerate(apiKey, model, convertMessages(messages))) {
169
+ if (list) list.appendChild(wrap);
170
+ await streamGenerate(apiKey, model, convertMessages(messages), chunk => {
178
171
  full += chunk;
179
- this.streamEl.textContent = full;
172
+ streamEl.textContent = full;
180
173
  const l = this.querySelector('#msg-list');
181
174
  if (l) l.scrollTop = l.scrollHeight;
182
- }
183
- this.streamWrap.remove();
184
- this.streamEl = null;
185
- this.streamWrap = null;
175
+ });
176
+ wrap.remove();
186
177
  this.setState({ messages: [...messages, { role: 'assistant', content: full || '(empty)' }], streaming: false, streamingText: '' });
187
178
  const l2 = this.querySelector('#msg-list');
188
179
  if (l2) l2.scrollTop = l2.scrollHeight;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thebird",
3
- "version": "1.2.15",
3
+ "version": "1.2.16",
4
4
  "description": "Anthropic SDK to Gemini streaming bridge — drop-in proxy that translates Anthropic message format and tool calls to Google Gemini",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",