@neta-art/cohub 8.20.1 → 8.21.1

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/README.md CHANGED
@@ -231,122 +231,11 @@ An **App** (previously *Work*) is a published, shareable web page hosted by
231
231
  Cohub. When a viewer opens an App, it runs inside a Cohub-managed runtime that
232
232
  provides short-lived access tokens — no API keys required.
233
233
 
234
- These runtime-only APIs are available **exclusively inside a published App**:
235
-
236
- - `client.context()` — returns App identity, App home Space identity, the current
237
- viewer, permissions, optional invocation identifiers, and the current shell
238
- location (`context.shell`). A new chat background has `shell.surface:
239
- "background"` with the hosting Space in `shell.space` (`session` / `turn` are
240
- null); `invocation.spaceId` is the same Space for compatibility.
241
- Returns `null` outside an App runtime. `client.app.onContextChanged()` pushes
242
- fresh state.
243
- - `client.auth.authorize({ target, scopes, reason?, alwaysAsk?, fallback? })`
244
- — requests consent for an account, a specific Space, or a viewer-picked
245
- Space. Silent when a grant covers the scopes. Returns the actual target,
246
- how it was resolved, and the authoritative grant; see the
247
- [authorization contract](../../docs/app-authorization.md).
248
- `client.auth.request()` / `requestSpace()` / `requestCreateSpace()` remain
249
- available for older Apps.
250
- - `client.context().permissions.viewerGrants` — render the viewer's current
251
- per-space grants. Grant management uses an account-authenticated client or
252
- the CLI; an App session cannot manage its own grants.
253
- - `client.app.commerce.*` — entitlement checks, credit consumption,
254
- purchases.
255
- - `client.app.realtime.*` — temporary rooms, typed events, presence, and
256
- membership.
257
-
258
- ### Quick start (inside an App)
234
+ The App runtime APIs — `client.context()`, `client.auth.authorize()`, app
235
+ scopes and viewer grants, realtime rooms, callable surface, composer context,
236
+ commerce, and App Actions — are documented in one place:
259
237
 
260
- ```ts
261
- // Browsers don't inject ENV — pass it explicitly.
262
- const client = createCohubClient({ env: "prod" });
263
-
264
- const ctx = await client.context();
265
- if (!ctx?.app?.id) throw new Error("Not inside a published app.");
266
-
267
- const sourceSessionId = ctx.invocation?.sessionId ?? null;
268
- // `shell.space` is the current Cohub location. `app.homeSpace` is the App's
269
- // owning Space. A new chat background also has `invocation.spaceId`.
270
- const spaceId = ctx.shell?.space?.id ?? ctx.invocation?.spaceId ?? ctx.app.homeSpace?.id;
271
- const space = client.space(spaceId);
272
-
273
- // Request viewer grants from a user gesture (button click)
274
- const consent = await client.auth.authorize({
275
- target: { kind: "space", spaceId },
276
- scopes: ["session.prompt.fullaccess", "generation.create"],
277
- reason: "This app sends prompts and generates images.",
278
- });
279
- if (consent.status !== "granted") return;
280
- // Act on the granted target, which may differ from the request.
281
- const activeSpace = consent.target.kind === "space"
282
- ? client.space(consent.target.spaceId)
283
- : space;
284
- ```
285
-
286
- ### The permission model (critical)
287
-
288
- An app's effective permission for one Space is the union of **two grant
289
- sources** — either one is enough:
290
-
291
- - **App scopes** (no consent): eight bounded scopes — `space.view`,
292
- `session.view`, `file.view`, `file.edit`, `taskrun.view`,
293
- `session.prompt.readonly`, `session.prompt.fullaccess`, `command.execute` —
294
- granted at publish time via `appScopes`, applying only to the app's own
295
- Space.
296
- - **Viewer grants** (consent-required): any permission the viewer holds, on
297
- any Space they choose — one grant per Space, valid 14 days, re-validated
298
- against the viewer's live access on every request. Includes scopes beyond
299
- the eight app scopes, such as `generation.create` and the account-level
300
- `user.*` scopes.
301
-
302
- **They never substitute for each other's halves.** `session.prompt.fullaccess`
303
- lets you send a prompt but does NOT let you read the reply — that needs
304
- `session.view`. `generation.create` lets you create a generation task, but
305
- polling its result needs `taskrun.view`.
306
-
307
- Render grant state from `ctx.permissions.viewerGrants`; act through
308
- `auth.authorize()` (silent when covered). `allowedViewerScopes` is deprecated —
309
- viewer grants are no longer gated by the app configuration.
310
-
311
- ### Realtime rooms
312
-
313
- App runtime rooms are generic, temporary event channels. The SDK does not
314
- know the App's business events; define their names and payload types in the
315
- App itself.
316
-
317
- ```ts
318
- type Events = {
319
- "shared.state.updated": { value: number };
320
- "activity.submitted": { itemId: string };
321
- };
322
-
323
- const room = await client.app.realtime.createRoom<Events>({
324
- code: "TEAM-ALPHA", // optional; generated when omitted
325
- maxParticipants: 64,
326
- expiresInSeconds: 2 * 60 * 60,
327
- });
328
-
329
- const stop = room.subscribe("shared.state.updated", (event) => {
330
- console.log(event.sequence, event.data.value, event.self);
331
- });
332
-
333
- await room.publish("shared.state.updated", { value: 42 });
334
- await room.setPresence({ status: "active" });
335
- await room.leave();
336
- stop();
337
- ```
338
-
339
- `expiresInSeconds` is an absolute lifetime from server-side room creation. It
340
- never extends on publish, presence, or heartbeat. The maximum lifetime is
341
- 24 hours. Room events are live and ordered while connected, with publish ACKs
342
- and sequence-gap detection; events missed during a disconnect are not replayed.
343
-
344
- For high-frequency traffic such as input frames, `room.send(type, data)` skips
345
- the per-event ACK that would otherwise cap throughput at one round trip per
346
- event; failures surface through `room.onSendError`. Every connection is its own
347
- participant by default; create the room with `seatPerUser: true` to give each
348
- viewer a single seat instead.
238
+ **[App development](https://cohub.live/docs/developers/apps)**
349
239
 
350
- For the complete API-to-scope mapping, initialization recipe, capability
351
- recipes, a full working example, and a pitfalls checklist, see the
352
- **[App Runtime Guide](./docs/app-runtime-guide.md)**.
240
+ Runtime APIs only work inside a published App; local pages get `null` from
241
+ `context()`.