@neta-art/cohub 8.19.0 → 8.20.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/dist/chunks/environment.d.ts +53 -4
- package/dist/chunks/environment.js +4 -1
- package/dist/chunks/http.d.ts +73 -15
- package/dist/chunks/http.js +22 -9
- package/dist/chunks/websocket.d.ts +1 -1
- package/dist/chunks/websocket.js +1 -1
- package/dist/http.d.ts +2 -2
- package/dist/http.js +1 -1
- package/dist/index.d.ts +80 -3
- package/dist/index.js +829 -71
- package/docs/app-runtime-guide.md +49 -74
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Cohub App Runtime Guide
|
|
2
2
|
|
|
3
|
-
This guide explains the Cohub SDK in a published App iframe or
|
|
4
|
-
|
|
3
|
+
This guide explains the Cohub SDK in a published App iframe or a registered
|
|
4
|
+
standalone origin. New Apps should use `auth.authorize()`; see the
|
|
5
5
|
[authorization contract](../../../docs/app-authorization.md). Legacy APIs below
|
|
6
6
|
retain their original return types. Read this before building any
|
|
7
7
|
App that calls Cohub capabilities from browser-side JavaScript.
|
|
@@ -67,13 +67,13 @@ These runtime-only APIs form the foundation; everything else is standard SDK:
|
|
|
67
67
|
| API | What it does | Returns |
|
|
68
68
|
|---|---|---|
|
|
69
69
|
| `client.context()` | Asks the host for the App's identity | `{ app, space, viewer?, invocation?, shell?, permissions, capabilities?, mode? }` or `null` |
|
|
70
|
-
| `client.auth.authorize({ target, scopes, reason?, alwaysAsk?, fallback? })` | Requests consent for an account, a Space, or a viewer-picked Space;
|
|
70
|
+
| `client.auth.authorize({ target, scopes, reason?, alwaysAsk?, fallback? })` | Requests consent for an account, a Space, or a viewer-picked Space; also silently grants approved read-only scopes on the trusted Shell Space | `{ status: "granted", requestedTarget, target, resolution, grant }` \| `{ status: "cancelled" }` \| `{ status: "denied", code }` |
|
|
71
71
|
| `client.auth.request()` / `requestSpace()` / `requestCreateSpace()` | Legacy entry points, kept for older Apps | original shapes (`boolean`, `{ granted, space }`) |
|
|
72
72
|
| `client.context().permissions.viewerGrants` | Render the viewer's current per-space grants | `{ spaceId, scopes }[]` |
|
|
73
73
|
| `client.app.commerce.*` / `client.app.realtime.*` | Commerce and realtime, bound to the app's runtime identity | (see below) |
|
|
74
74
|
|
|
75
|
-
> **Runtime requirement.** Use a published App iframe or
|
|
76
|
-
>
|
|
75
|
+
> **Runtime requirement.** Use a published App iframe or a standalone origin
|
|
76
|
+
> registered with Cohub. The SDK discovers the transport automatically.
|
|
77
77
|
> Initialize `context()` before using APIs to discover Host capabilities.
|
|
78
78
|
|
|
79
79
|
`client.app.onContextChanged(listener)` pushes a fresh context whenever the
|
|
@@ -117,19 +117,18 @@ The App is accessed as a standalone page (`window.parent === window`), e.g.
|
|
|
117
117
|
a direct static-asset URL not wrapped in the Cohub iframe. The SDK opens a
|
|
118
118
|
**popup window** to a Cohub auth-broker page to obtain tokens.
|
|
119
119
|
|
|
120
|
-
- `client.context()` is **answered locally** by the SDK
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
- `client.auth.authorize()` opens
|
|
125
|
-
|
|
120
|
+
- `client.context()` is **answered locally** by the SDK after anonymously
|
|
121
|
+
resolving the page Origin. It has the same shape as bridge context, including
|
|
122
|
+
App identity, Home Space, capabilities and App scopes. `shell.surface` is
|
|
123
|
+
`"broker"`; there is no active shell Space, session or turn.
|
|
124
|
+
- `client.auth.authorize()` opens the environment's trusted Cohub broker.
|
|
125
|
+
- Broker tokens stay in memory and are never restored from or written to
|
|
126
|
+
`localStorage`.
|
|
126
127
|
|
|
127
|
-
> **
|
|
128
|
-
>
|
|
129
|
-
>
|
|
130
|
-
>
|
|
131
|
-
> has no parent to talk to, so `context()` returns `null`. See
|
|
132
|
-
> [Initialization recipe](#4-initialization-recipe).
|
|
128
|
+
> **No mode configuration is required.** `createCohubClient({ env })` uses
|
|
129
|
+
> bridge inside the Cohub shell and broker on a registered standalone Origin.
|
|
130
|
+
> Unregistered pages receive `null` from `context()`. Explicit `app` transport
|
|
131
|
+
> options remain available for legacy integrations and local debugging.
|
|
133
132
|
|
|
134
133
|
### Detecting the mode at runtime
|
|
135
134
|
|
|
@@ -242,9 +241,17 @@ requested Space.
|
|
|
242
241
|
|
|
243
242
|
### Requesting viewer grants
|
|
244
243
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
244
|
+
Normal consent must be requested **from a user gesture** (a button click).
|
|
245
|
+
A request whose explicit target is the trusted `ctx.shell.space.id` is also
|
|
246
|
+
silent for the read-only Shell scopes `space.view`, `file.view`,
|
|
247
|
+
`file.view.filtered`, `session.view`, `taskrun.view`, and `checkpoint.view`.
|
|
248
|
+
The Host decides this by comparing the request against the Space it is actually
|
|
249
|
+
showing, and the server still checks the viewer's current permission on that
|
|
250
|
+
Space. The API keeps its single `authorize` endpoint and is not told whether
|
|
251
|
+
consent was interactive, so there is no flag to trust or forge. Broker surfaces
|
|
252
|
+
keep the interactive flow. A Shell hosting an embedded App applies the same rule
|
|
253
|
+
on its behalf. Existing grants are read without extending their expiry. Any other target, mixed scope set, `pick-space`,
|
|
254
|
+
account data, writes, or actions keeps the interactive flow:
|
|
248
255
|
|
|
249
256
|
```js
|
|
250
257
|
// 1. Target a known Space. The result names the Space that was actually
|
|
@@ -432,54 +439,22 @@ const client = createCohubClient({
|
|
|
432
439
|
});
|
|
433
440
|
```
|
|
434
441
|
|
|
435
|
-
###
|
|
442
|
+
### Automatic standalone mode
|
|
436
443
|
|
|
437
|
-
|
|
438
|
-
|
|
444
|
+
Published public `file` and `directory` Apps may also be opened at a standalone
|
|
445
|
+
URL: the deployment's standalone host template with the App id substituted, for
|
|
446
|
+
example `https://<app-id>.apps.example.com`. Standalone origins are opt-in
|
|
447
|
+
against deployment configuration; without a template, Apps have no standalone
|
|
448
|
+
URL.
|
|
439
449
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
brokerOrigin: isDevApp ? "https://dev.cohub.live" : "https://cohub.live",
|
|
445
|
-
appId: "<your-published-app-id>",
|
|
446
|
-
},
|
|
447
|
-
});
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
When inside the Cohub iframe, the SDK auto-detects bridge mode and ignores
|
|
451
|
-
broker config. When standalone, it uses broker mode. **One codebase, both
|
|
452
|
-
deployments.**
|
|
453
|
-
|
|
454
|
-
#### Broker mode without a pre-known appId
|
|
455
|
-
|
|
456
|
-
The `appId` is only generated at publish time, so you often cannot hardcode
|
|
457
|
-
it while writing the App. In standalone deployments you can omit `appId` and
|
|
458
|
-
instead pass the App's public **slug triple**. The SDK resolves the appId at
|
|
459
|
-
runtime via the public `apps.getBySlug` API (anonymous, no auth required),
|
|
460
|
-
caches it, and starts broker mode with it.
|
|
461
|
-
|
|
462
|
-
All three values are known before publishing:
|
|
463
|
-
|
|
464
|
-
- `appSlug` — the slug you chose when creating the App.
|
|
465
|
-
- `ownerUsername` — the space owner's username (`cohub auth whoami`).
|
|
466
|
-
- `spaceSlug` — the space's slug (`cohub spaces get <spaceId>`).
|
|
467
|
-
|
|
468
|
-
```js
|
|
469
|
-
const client = createCohubClient({
|
|
470
|
-
env: isDevApp ? "dev" : "prod",
|
|
471
|
-
app: {
|
|
472
|
-
brokerOrigin: isDevApp ? "https://dev.cohub.live" : "https://cohub.live",
|
|
473
|
-
ownerUsername,
|
|
474
|
-
spaceSlug,
|
|
475
|
-
appSlug,
|
|
476
|
-
},
|
|
477
|
-
});
|
|
478
|
-
```
|
|
450
|
+
The same client initialization works in the Cohub iframe and at this direct
|
|
451
|
+
URL. The SDK first uses the parent bridge when embedded; at a top-level page it
|
|
452
|
+
anonymously resolves `window.location.origin` and selects the trusted broker.
|
|
453
|
+
The resolver returns identity only and never returns a token.
|
|
479
454
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
455
|
+
Explicit `app: { brokerOrigin, appId }` and slug-triple configuration remains
|
|
456
|
+
supported for older externally hosted Apps, but new Apps should not declare a
|
|
457
|
+
mode or hardcode their App id.
|
|
483
458
|
|
|
484
459
|
### Standard initialization sequence
|
|
485
460
|
|
|
@@ -487,8 +462,8 @@ the Cohub iframe both are ignored (bridge mode).
|
|
|
487
462
|
// 1. Create client (env is mandatory in the browser)
|
|
488
463
|
const client = createCohubClient({ env: isDevApp ? "dev" : "prod" });
|
|
489
464
|
|
|
490
|
-
// 2. Get runtime context (and keep it fresh). `app`
|
|
491
|
-
// broker mode;
|
|
465
|
+
// 2. Get runtime context (and keep it fresh). `app` and its Home Space are
|
|
466
|
+
// present in bridge and broker mode; shell location exists only when hosted.
|
|
492
467
|
const ctx = await client.context();
|
|
493
468
|
if (!ctx?.app?.id) {
|
|
494
469
|
throw new Error("Not running inside a published app.");
|
|
@@ -516,10 +491,11 @@ const activeSpace = client.space(consent.target.spaceId);
|
|
|
516
491
|
const result = await activeSpace.prompt({ content: [{ type: "text", text: "Hello" }] });
|
|
517
492
|
```
|
|
518
493
|
|
|
519
|
-
>
|
|
520
|
-
>
|
|
521
|
-
>
|
|
522
|
-
>
|
|
494
|
+
> **Normal interactive `auth.authorize()` calls must use a user gesture** (click
|
|
495
|
+
> handler). The approved Shell read-only path may run during initialization in
|
|
496
|
+
> bridge mode. Broker mode has no trusted Shell Space, so it keeps the normal
|
|
497
|
+
> popup and gesture requirements. `alwaysAsk: true` always returns to the
|
|
498
|
+
> interactive flow.
|
|
523
499
|
|
|
524
500
|
---
|
|
525
501
|
|
|
@@ -1286,9 +1262,8 @@ Before publishing your App, verify each item:
|
|
|
1286
1262
|
- [ ] **`subscribeGeneration` errors are not silently swallowed** — if the
|
|
1287
1263
|
stream fails, surface it; a silent fallback to polling will also 403 if
|
|
1288
1264
|
`session.view` is missing.
|
|
1289
|
-
- [ ] **Broker mode**:
|
|
1290
|
-
|
|
1291
|
-
API call (to avoid user-activation exhaustion).
|
|
1265
|
+
- [ ] **Broker mode**: initialize `context()` early so Origin discovery is warm,
|
|
1266
|
+
then call `auth.authorize()` from a user action before protected API calls.
|
|
1292
1267
|
- [ ] **Space has a slug and owner has a username** before publishing — the
|
|
1293
1268
|
API rejects Apps when either is missing.
|
|
1294
1269
|
- [ ] **Model ids are not hardcoded** — use `client.models.listMultimodal()`
|