diff --git a/README.md b/README.md index 0328dd0..20a42c0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # @neboai/app-sdk -SDK for building [Nebo](https://neboloop.com) apps. Mirrors native browser APIs (`fetch`, `WebSocket`, `localStorage`) while adding agent invocation, LLM completions, and real-time state management. +SDK for building [Nebo](https://neboai.com) apps. Mirrors native browser APIs (`fetch`, `WebSocket`, `localStorage`) while adding agent invocation, LLM completions, and real-time state management. ## Install @@ -8,12 +8,17 @@ SDK for building [Nebo](https://neboloop.com) apps. Mirrors native browser APIs pnpm add @neboai/app-sdk ``` -Or use the global build via CDN: +Or, for a page without a build step, load the copy Nebo serves to every app page: ```html - + + ``` +An unbundled page cannot `import` a bare package name; use the served global. + ## Quick Start ```typescript @@ -59,57 +64,70 @@ nebo.surfaces.on('state_snapshot', (e) => { ### `nebo.fetch(input, init?)` Auto-routed fetch. Relative URLs go to your sidecar. Absolute URLs go through Nebo's CORS-free proxy. -### `nebo.WebSocket(path?)` -Auto-reconnecting WebSocket with exponential backoff (1s–30s). +### `new nebo.WebSocket()` +Auto-reconnecting WebSocket to the app's own channel, with exponential backoff (1 s up to 30 s). It takes no path: any argument is ignored. To reach your own server (a game server, for example), open a plain `new WebSocket('wss://...')` from the page. ### `nebo.storage` Server-persisted async key-value store: `getItem`, `setItem`, `removeItem`, `clear`, `keys`. ### `nebo.agents` -- `invoke(message, options?)` — One-shot agent call, returns `{ text, tools? }` -- `stream(message, options?)` — Streaming agent call, yields `{ text, done }` +- `invoke(message, options?)`: one-shot agent call, returns `{ text, tools? }` +- `stream(message, options?)`: streaming agent call, yields `{ text, done }` ### `nebo.janus` -- `complete(options)` — Direct LLM completion -- `stream(options)` — Streaming LLM completion +- `complete(options)`: Direct LLM completion +- `stream(options)`: Streaming LLM completion ### `nebo.chat` -- `mount(element, options?)` — Embed chat UI -- `unmount()` — Remove chat UI -- `send(message)` — Programmatically send a message -- `onMessage(handler)` — Listen for chat events -- `setContext(context)` — Update app context for the agent -- `newThread()` — Start a new conversation +- `mount(element, options?)`: Embed chat UI +- `unmount()`: Remove chat UI +- `send(message)`: Programmatically send a message +- `onMessage(handler)`: Listen for chat events +- `setContext(context)`: Update app context for the agent +- `newThread()`: Start a new conversation ### `nebo.surfaces` Real-time agent-to-app event system with typed events: - `connect()` / `disconnect()` -- `on(type, handler)` — Subscribe to events (returns unsubscribe fn) -- `send(name, payload?)` — Send action to agent -- `requestState()` — Request full state snapshot +- `on(type, handler)`: Subscribe to events (returns unsubscribe fn) +- `send(name, payload?)`: Send action to agent +- `requestState()`: Request full state snapshot Events: `run_started`, `run_finished`, `run_error`, `text_start`, `text_content`, `text_end`, `tool_call_start`, `tool_call_end`, `state_snapshot`, `state_delta`, `surface_create`, `surface_update`, `surface_delete`, `data_update`, `custom`. ### `nebo.identity` -- `get()` — Returns agent metadata (id, name, skills, model, etc.) -- `invalidate()` — Clear cached identity +- `get()`: Returns agent metadata (id, name, skills, model, etc.) +- `invalidate()`: Clear cached identity ### `nebo.a2ui` A2UI v0.9 message bridge for agent-driven UI components. -- `init(processor)` — Initialize with `@a2ui/web_core` MessageProcessor -- `sendAction(surfaceId, action)` — Send UI action to agent -- `sendError(surfaceId, code, message)` — Report error to agent +- `init(processor)`: Initialize with `@a2ui/web_core` MessageProcessor +- `sendAction(surfaceId, action)`: Send UI action to agent +- `sendError(surfaceId, code, message)`: Report error to agent ### `nebo.configure(options)` Set `appId` and `baseUrl` manually (auto-detected by default). +## What the page gets from Nebo (no SDK call needed) + +Some app features come from the app's `manifest.json` and standard browser APIs rather than from the SDK: + +| Want | How | +|------|-----| +| Full screen, landscape | `"window": { "fullscreen": true, "orientation": "landscape" }` (`orientation`: `portrait` default, `landscape`, `any`). Pad with `env(safe-area-inset-*)` and `viewport-fit=cover`. | +| Tilt (gyroscope, accelerometer) | Add `"device:motion"` to `permissions`, then listen for `devicemotion` / `deviceorientation`. On iPhone call `DeviceMotionEvent.requestPermission()` from a tap. | +| Video and sound | Ship the files in `ui/`. They are served with their real content types and answer range requests, so `