thebird 1.2.101 → 1.2.103
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.
- package/.gm/lastskill +1 -1
- package/CLAUDE.md +25 -8
- package/README.md +21 -233
- package/package.json +1 -1
package/.gm/lastskill
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
gm:
|
|
1
|
+
gm:update-docs
|
package/CLAUDE.md
CHANGED
|
@@ -2,9 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Architecture Overview
|
|
4
4
|
|
|
5
|
-
**thebird** is
|
|
5
|
+
**thebird** is the web OS shell — browser-native terminal, agentic chat, and file system. All Anthropic-format message translation, routing, streaming, and tool calling is owned by **[acptoapi](https://github.com/AnEntrypoint/acptoapi)** (`node_modules/acptoapi`). thebird depends on acptoapi as an npm package (`file:../acptoapi` locally, npm in CI).
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```
|
|
8
|
+
thebird (web OS)
|
|
9
|
+
├── docs/ — browser UI (chat, terminal, preview, shell)
|
|
10
|
+
├── serve.js — static file server for docs/
|
|
11
|
+
├── server.js — Anthropic-compat HTTP proxy (uses acptoapi)
|
|
12
|
+
├── index.js — re-exports acptoapi
|
|
13
|
+
└── node_modules/acptoapi/
|
|
14
|
+
├── lib/convert.js — Anthropic↔Gemini message translation
|
|
15
|
+
├── lib/providers/ — OpenAI-compat + ACP providers
|
|
16
|
+
├── lib/router-stream.js — multi-provider routing
|
|
17
|
+
└── index.js — streamGemini, generateGemini, createRouter, ...
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Message Translation (in acptoapi)
|
|
8
21
|
|
|
9
22
|
Anthropic format:
|
|
10
23
|
```js
|
|
@@ -18,14 +31,14 @@ Translates to provider-native format:
|
|
|
18
31
|
- **Gemini**: `parts: [{ text: '...' }, { inlineData: { mimeType: '...', data: '...' } }]`
|
|
19
32
|
- **OpenAI**: `content: [{ type: 'text', text: '...' }, { type: 'image_url', image_url: { url: '...' } }]`
|
|
20
33
|
|
|
21
|
-
### Tool Calling
|
|
34
|
+
### Tool Calling (in acptoapi)
|
|
22
35
|
|
|
23
36
|
Anthropic tool schema → provider native → normalized response back to Anthropic format.
|
|
24
37
|
|
|
25
38
|
Streaming events (all events are Anthropic-compatible):
|
|
26
39
|
- `text-delta`, `tool-use-start`, `tool-use-delta`, `message-start`, `message-stop`
|
|
27
40
|
|
|
28
|
-
### Routing (Multi-Provider)
|
|
41
|
+
### Routing (Multi-Provider, in acptoapi)
|
|
29
42
|
|
|
30
43
|
`createRouter()` picks provider+model per request based on:
|
|
31
44
|
1. `taskType` (e.g., 'think', 'background', 'longContext')
|
|
@@ -191,6 +204,14 @@ UI consumes via 3 channels: `onChunk(delta)` text streaming | `onEvent(ev)` badg
|
|
|
191
204
|
|
|
192
205
|
## Files
|
|
193
206
|
|
|
207
|
+
- `index.js`: Re-exports all of acptoapi
|
|
208
|
+
- `server.js`: Anthropic-compatible HTTP proxy using acptoapi (streamGemini/generateGemini)
|
|
209
|
+
- `serve.js`: Static file server for docs/ (COEP/COOP headers for WebContainer)
|
|
210
|
+
- `package.json`: depends on `acptoapi` (file:../acptoapi locally, npm in CI)
|
|
211
|
+
- `docs/shell-builtins.js`: FS/IO builtins (ls/cat/echo/cd/mkdir/rm/cp/mv/touch/head/tail/wc) — imports makeTextBuiltins
|
|
212
|
+
- `docs/shell-builtins-text.js`: Text-processing builtins (grep/sed/sort/uniq/tr) + env/export/clear/history/which/exit/true/false/printenv
|
|
213
|
+
|
|
214
|
+
**acptoapi** (owned by `c:/dev/acptoapi`, installed as npm dep):
|
|
194
215
|
- `lib/convert.js`: Message/tool translation logic
|
|
195
216
|
- `lib/client.js`: Provider client factory
|
|
196
217
|
- `lib/errors.js`: Typed error hierarchy (BridgeError, AuthError, RateLimitError, etc.), classifyError, redactKeys, withRetry
|
|
@@ -202,10 +223,6 @@ UI consumes via 3 channels: `onChunk(delta)` text streaming | `onEvent(ev)` badg
|
|
|
202
223
|
- `index.js`: Main entry point, Gemini streaming/generation, re-exports
|
|
203
224
|
- `index.d.ts`: TypeScript type definitions
|
|
204
225
|
- `examples/`: Working examples using Anthropic SDK format
|
|
205
|
-
- `wasi/cli.ts`: Deno streaming CLI — `deno run --allow-net --allow-env wasi/cli.ts [--model M] [--system S] <prompt>`
|
|
206
|
-
- `deno.json`: tasks `cli` (run) and `cli:compile` (→ `dist/thebird` binary)
|
|
207
|
-
- `docs/shell-builtins.js`: FS/IO builtins (ls/cat/echo/cd/mkdir/rm/cp/mv/touch/head/tail/wc) — imports makeTextBuiltins
|
|
208
|
-
- `docs/shell-builtins-text.js`: Text-processing builtins (grep/sed/sort/uniq/tr) + env/export/clear/history/which/exit/true/false/printenv
|
|
209
226
|
|
|
210
227
|
## WebContainer Terminal in docs/
|
|
211
228
|
|
package/README.md
CHANGED
|
@@ -1,255 +1,43 @@
|
|
|
1
1
|
# thebird
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Web OS — browser-native terminal, agentic chat, and file system powered by WebContainer and IndexedDB. Anthropic-format message routing is handled by [acptoapi](https://github.com/AnEntrypoint/acptoapi).
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Live Demo
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**[anentrypoint.github.io/thebird](https://anentrypoint.github.io/thebird/)**
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
This means you can use `@anthropic-ai/sdk` to build your messages and tool definitions, then pass them directly to thebird for execution against Gemini models.
|
|
15
|
-
|
|
16
|
-
## Install
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
npm install thebird @anthropic-ai/sdk
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Quick Start
|
|
23
|
-
|
|
24
|
-
**Anthropic SDK format → Gemini (streaming)**
|
|
25
|
-
|
|
26
|
-
```js
|
|
27
|
-
const Anthropic = require('@anthropic-ai/sdk');
|
|
28
|
-
const { streamGemini } = require('thebird');
|
|
29
|
-
|
|
30
|
-
// Build messages using Anthropic SDK format — same structure as client.messages.create()
|
|
31
|
-
const messages = [
|
|
32
|
-
{ role: 'user', content: 'Count from 1 to 5.' }
|
|
33
|
-
];
|
|
34
|
-
|
|
35
|
-
// Stream through Gemini — no server, no proxy
|
|
36
|
-
const { fullStream } = streamGemini({
|
|
37
|
-
model: 'gemini-3-flash-preview',
|
|
38
|
-
system: 'You are a helpful assistant.',
|
|
39
|
-
messages
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
for await (const event of fullStream) {
|
|
43
|
-
if (event.type === 'text-delta') process.stdout.write(event.textDelta);
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
**Anthropic SDK format → Gemini (non-streaming)**
|
|
48
|
-
|
|
49
|
-
```js
|
|
50
|
-
const { generateGemini } = require('thebird');
|
|
51
|
-
|
|
52
|
-
const { text } = await generateGemini({
|
|
53
|
-
model: 'gemini-3-flash-preview',
|
|
54
|
-
messages: [{ role: 'user', content: 'Hello!' }]
|
|
55
|
-
});
|
|
56
|
-
console.log(text);
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
**Multi-provider router**
|
|
60
|
-
|
|
61
|
-
```js
|
|
62
|
-
const { createRouter } = require('thebird');
|
|
63
|
-
|
|
64
|
-
const router = createRouter({
|
|
65
|
-
Providers: [
|
|
66
|
-
{ name: 'deepseek', api_base_url: 'https://api.deepseek.com/chat/completions', api_key: process.env.DEEPSEEK_API_KEY, models: ['deepseek-chat', 'deepseek-reasoner'], transformer: { use: ['deepseek'] } },
|
|
67
|
-
{ name: 'gemini', api_base_url: 'https://generativelanguage.googleapis.com/v1beta/models/', api_key: process.env.GEMINI_API_KEY, models: ['gemini-2.5-pro'] },
|
|
68
|
-
{ name: 'ollama', api_base_url: 'http://localhost:11434/v1/chat/completions', api_key: 'ollama', models: ['qwen2.5-coder:latest'] },
|
|
69
|
-
],
|
|
70
|
-
Router: {
|
|
71
|
-
default: 'deepseek,deepseek-chat',
|
|
72
|
-
background: 'ollama,qwen2.5-coder:latest',
|
|
73
|
-
think: 'deepseek,deepseek-reasoner',
|
|
74
|
-
longContext: 'gemini,gemini-2.5-pro',
|
|
75
|
-
longContextThreshold: 60000,
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// Stream — routes automatically based on taskType and token count
|
|
80
|
-
const { fullStream } = router.stream({ messages, taskType: 'think' });
|
|
81
|
-
for await (const event of fullStream) {
|
|
82
|
-
if (event.type === 'text-delta') process.stdout.write(event.textDelta);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Generate
|
|
86
|
-
const { text } = await router.generate({ messages });
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
**File-based config** — place config at `~/.thebird/config.json` (or set `THEBIRD_CONFIG` env) and use the auto-loading shorthand:
|
|
90
|
-
|
|
91
|
-
```js
|
|
92
|
-
const { streamRouter, generateRouter } = require('thebird');
|
|
93
|
-
const { fullStream } = streamRouter({ messages, taskType: 'background' });
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Routing
|
|
97
|
-
|
|
98
|
-
`createRouter` / `streamRouter` pick a provider+model per request:
|
|
99
|
-
|
|
100
|
-
| Route key | Trigger |
|
|
101
|
-
|---|---|
|
|
102
|
-
| `default` | Any request not matched by another rule |
|
|
103
|
-
| `background` | `taskType: 'background'` |
|
|
104
|
-
| `think` | `taskType: 'think'` |
|
|
105
|
-
| `webSearch` | `taskType: 'webSearch'` |
|
|
106
|
-
| `image` | `taskType: 'image'` |
|
|
107
|
-
| `longContext` | Estimated token count > `longContextThreshold` (default 60 000) |
|
|
108
|
-
| subagent tag | First user message starts with `<CCR-SUBAGENT-MODEL>provider,model</CCR-SUBAGENT-MODEL>` |
|
|
109
|
-
| custom function | `customRouter: async (params, cfg) => 'provider,model'` in config |
|
|
110
|
-
|
|
111
|
-
Route values are `"providerName,modelName"` strings matching a `Providers` entry.
|
|
112
|
-
|
|
113
|
-
## Transformers
|
|
114
|
-
|
|
115
|
-
Apply per-provider request/response transformations. Set on the provider's `transformer.use` array.
|
|
116
|
-
|
|
117
|
-
```json
|
|
118
|
-
{
|
|
119
|
-
"name": "deepseek",
|
|
120
|
-
"transformer": {
|
|
121
|
-
"use": ["deepseek"],
|
|
122
|
-
"deepseek-chat": { "use": [["maxtoken", { "max_tokens": 8192 }], "tooluse"] }
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Built-in transformers:
|
|
128
|
-
|
|
129
|
-
| Name | Effect |
|
|
130
|
-
|---|---|
|
|
131
|
-
| `deepseek` | Strips `cache_control`, normalises system to string |
|
|
132
|
-
| `openrouter` | Adds `HTTP-Referer` / `X-Title` headers; optional `provider` routing |
|
|
133
|
-
| `maxtoken` | Sets `max_tokens` to the given value |
|
|
134
|
-
| `tooluse` | Adds `tool_choice: {type:"required"}` when tools are present |
|
|
135
|
-
| `cleancache` | Strips all `cache_control` fields recursively |
|
|
136
|
-
| `reasoning` | Moves `reasoning_content` to `_reasoning` in response |
|
|
137
|
-
| `sampling` | Removes `top_k` / `repetition_penalty` |
|
|
138
|
-
| `groq` | Removes `top_k` |
|
|
139
|
-
|
|
140
|
-
Pass options as a nested array: `["maxtoken", { "max_tokens": 16384 }]`.
|
|
141
|
-
|
|
142
|
-
## Config File
|
|
143
|
-
|
|
144
|
-
`~/.thebird/config.json` (or `THEBIRD_CONFIG` env var) — same schema as the inline config object. Supports `$VAR` / `${VAR}` environment variable interpolation anywhere in the file.
|
|
145
|
-
|
|
146
|
-
```json
|
|
147
|
-
{
|
|
148
|
-
"Providers": [
|
|
149
|
-
{ "name": "openrouter", "api_base_url": "https://openrouter.ai/api/v1/chat/completions", "api_key": "$OPENROUTER_API_KEY", "models": ["google/gemini-2.5-pro-preview"], "transformer": { "use": ["openrouter"] } }
|
|
150
|
-
],
|
|
151
|
-
"Router": { "default": "openrouter,google/gemini-2.5-pro-preview" }
|
|
152
|
-
}
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
## Error Handling
|
|
156
|
-
|
|
157
|
-
thebird uses a typed error hierarchy. All errors extend `BridgeError`:
|
|
9
|
+
- **Chat tab** — Agentic chat via `acptoapi` running in-browser (`docs/vendor/thebird-browser.js`). Tools: `read_file`, `write_file`, `list_files` (IDB-backed), `run_command`, `read_terminal`, `send_to_terminal`. No proxy server required. API key stored in localStorage.
|
|
10
|
+
- **Terminal tab** — Browser-native POSIX shell (xstate v5 state machine, V8 eval) backed by IndexedDB filesystem. Built-in: `ls`, `cat`, `cd`, `pwd`, `mkdir`, `rm`, `cp`, `mv`, `echo`, `env`, `export`, `node`, `npm install`. Node REPL with persistent scope, `require()` from IDB node_modules, `http.createServer` polyfill.
|
|
11
|
+
- **Preview tab** — iframe served by a service worker reading files from IDB at `/preview/*`. Hot-reloads 5s after any file write.
|
|
158
12
|
|
|
159
|
-
|
|
160
|
-
|---|---|---|---|
|
|
161
|
-
| `AuthError` | 401, 403 | No | Invalid API key |
|
|
162
|
-
| `RateLimitError` | 429 | Yes | Quota exceeded |
|
|
163
|
-
| `TimeoutError` | 408 | Yes | Stream chunk timeout |
|
|
164
|
-
| `ContextWindowError` | 413 | No | Input too long |
|
|
165
|
-
| `ContentPolicyError` | 451 | No | Safety filter triggered |
|
|
166
|
-
| `ProviderError` | 5xx | Yes | Upstream server error |
|
|
13
|
+
All JS and CSS dependencies are vendored locally in `docs/vendor/` — no CDN required at runtime.
|
|
167
14
|
|
|
168
|
-
|
|
15
|
+
## Architecture
|
|
169
16
|
|
|
170
|
-
```js
|
|
171
|
-
const { classifyError, BridgeError } = require('thebird');
|
|
172
|
-
try { /* ... */ } catch (err) {
|
|
173
|
-
if (err instanceof BridgeError && err.retryable) { /* retry */ }
|
|
174
|
-
}
|
|
175
17
|
```
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
Pass `streamGuard` to protect against stalled or looping streams:
|
|
180
|
-
|
|
181
|
-
```js
|
|
182
|
-
streamGemini({
|
|
183
|
-
messages,
|
|
184
|
-
streamGuard: { chunkTimeoutMs: 30000, maxRepeats: 100 }
|
|
185
|
-
});
|
|
18
|
+
thebird (web OS shell)
|
|
19
|
+
└── acptoapi (npm) ← Anthropic format → Gemini / OpenAI-compat bridge
|
|
20
|
+
└── @google/genai ← Gemini native streaming
|
|
186
21
|
```
|
|
187
22
|
|
|
188
|
-
|
|
189
|
-
- **Repeat detection** — throws if the same chunk appears consecutively N times (default 100)
|
|
23
|
+
thebird is the web OS. `acptoapi` owns all Anthropic↔provider translation, streaming, routing, transformers, and TypeScript types. `server.js` exposes a local Anthropic-compatible proxy backed by acptoapi.
|
|
190
24
|
|
|
191
|
-
##
|
|
25
|
+
## Local Dev
|
|
192
26
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
Providers: [/* ... */],
|
|
198
|
-
circuitBreaker: { maxFailures: 5, cooldownMs: 60000 }
|
|
199
|
-
});
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
## Provider Capabilities
|
|
203
|
-
|
|
204
|
-
Declare what each provider supports. Unsupported features are stripped automatically with warnings:
|
|
205
|
-
|
|
206
|
-
```json
|
|
207
|
-
{
|
|
208
|
-
"name": "groq",
|
|
209
|
-
"api_base_url": "...",
|
|
210
|
-
"api_key": "$GROQ_API_KEY",
|
|
211
|
-
"capabilities": { "vision": false, "jsonMode": true }
|
|
212
|
-
}
|
|
27
|
+
```bash
|
|
28
|
+
npm install
|
|
29
|
+
node serve.js # serves docs/ at http://localhost:8080
|
|
30
|
+
node server.js # Anthropic-compat proxy at http://localhost:3456 (needs GEMINI_API_KEY)
|
|
213
31
|
```
|
|
214
32
|
|
|
215
|
-
|
|
33
|
+
## acptoapi
|
|
216
34
|
|
|
217
|
-
|
|
35
|
+
For the Anthropic-to-provider bridge (streaming, routing, tool calls, vision, retry logic, TypeScript types), see [acptoapi](https://github.com/AnEntrypoint/acptoapi).
|
|
218
36
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
## Message Format
|
|
222
|
-
|
|
223
|
-
Messages follow the Anthropic SDK format. All image block variants are supported:
|
|
224
|
-
|
|
225
|
-
```js
|
|
226
|
-
{ role: 'user', content: [
|
|
227
|
-
{ type: 'text', text: 'Describe this image.' },
|
|
228
|
-
{ type: 'image', source: { type: 'base64', media_type: 'image/png', data: '...' } }
|
|
229
|
-
]}
|
|
37
|
+
```bash
|
|
38
|
+
npm install acptoapi
|
|
230
39
|
```
|
|
231
40
|
|
|
232
|
-
## Streaming Events
|
|
233
|
-
|
|
234
|
-
| Event | Fields | Description |
|
|
235
|
-
|---|---|---|
|
|
236
|
-
| `start-step` | — | Beginning of a reasoning step |
|
|
237
|
-
| `text-delta` | `textDelta` | Streamed text chunk |
|
|
238
|
-
| `tool-call` | `toolCallId, toolName, args` | Model invoked a tool |
|
|
239
|
-
| `tool-result` | `toolCallId, toolName, args, result` | Tool execution result |
|
|
240
|
-
| `finish-step` | `finishReason` | Step completed |
|
|
241
|
-
| `error` | `error` | Error during step |
|
|
242
|
-
|
|
243
|
-
## Browser Demo
|
|
244
|
-
|
|
245
|
-
Live at **[anentrypoint.github.io/thebird](https://anentrypoint.github.io/thebird/)**
|
|
246
|
-
|
|
247
|
-
- **Chat tab** — Agentic chat powered by thebird `streamGemini` running in-browser (bundled in `docs/vendor/thebird-browser.js`). Tools: `read_file`, `write_file`, `list_files` (IDB-backed), `run_command`, `read_terminal`, `send_to_terminal`. No proxy server required. Gemini API key stored in localStorage.
|
|
248
|
-
- **Terminal tab** — Browser-native POSIX shell (xstate v5 state machine, V8 eval) backed by IndexedDB filesystem. Built-in commands: `ls`, `cat`, `cd`, `pwd`, `mkdir`, `rm`, `cp`, `mv`, `echo`, `env`, `export`, `node`, `npm install`. Node REPL mode with persistent scope, `require()` from IDB node_modules, `http.createServer` polyfill. No WebContainer or server required.
|
|
249
|
-
- **Preview tab** — iframe served by a service worker reading files from IDB at `/preview/*`. Hot-reloads 5s after any file write.
|
|
250
|
-
|
|
251
|
-
All JS and CSS dependencies are vendored locally in `docs/vendor/` — no CDN required at runtime.
|
|
252
|
-
|
|
253
41
|
## License
|
|
254
42
|
|
|
255
43
|
MIT
|
package/package.json
CHANGED