@noodleseed/assistant 1.19.0 → 1.20.0
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 +68 -0
- package/dist/{chunk-S373FCAI.js → chunk-52XT7BLR.js} +9 -4
- package/dist/{chunk-S373FCAI.js.map → chunk-52XT7BLR.js.map} +1 -1
- package/dist/{chunk-RFETV5KQ.js → chunk-DLUINP4W.js} +9 -9
- package/dist/{chunk-RFETV5KQ.js.map → chunk-DLUINP4W.js.map} +1 -1
- package/dist/{client-BQ30Fq-c.d.cts → client-7o7n2nqw.d.cts} +6 -4
- package/dist/{client-B6pnBmF8.d.ts → client-CysBQBdd.d.ts} +6 -4
- package/dist/client.cjs +8 -3
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/embed.global.js +4 -4
- package/dist/index.cjs +15 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/react/client.cjs +8 -3
- package/dist/react/client.cjs.map +1 -1
- package/dist/react/client.d.cts +1 -1
- package/dist/react/client.d.ts +1 -1
- package/dist/react/client.js +1 -1
- package/dist/react.cjs +15 -10
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +2 -2
- package/dist/server.cjs +47 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +60 -7
- package/dist/server.d.ts +60 -7
- package/dist/server.js +45 -1
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -202,6 +202,74 @@ claims, or tool input. The endpoint key must match the authored name. Noodle val
|
|
|
202
202
|
only in private short-lived session state, and an omitted route leaves only dependent tools unavailable.
|
|
203
203
|
Mint a new session when the user's selected account or cluster changes.
|
|
204
204
|
|
|
205
|
+
#### Public website embeds
|
|
206
|
+
|
|
207
|
+
Everything above serves a signed-in user through your backend. A `publicWebsite(...)` surface serves the
|
|
208
|
+
same assistant to anonymous visitors — a marketing site, docs, or landing page — with a **required**
|
|
209
|
+
capability allowlist, per-surface daily budgets, and a kill switch. `noodle deploy` provisions a stable
|
|
210
|
+
embed id and prints a one-line snippet; the embed id is deliberately not a credential:
|
|
211
|
+
|
|
212
|
+
```html
|
|
213
|
+
<script src="https://cloud.noodleseed.dev/v1/assistant/embed.js"
|
|
214
|
+
data-embed-id="pub_7f2q4k9x" async></script>
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
In a bundled app, the same public surface mounts through the element or React wrapper with `embedId`
|
|
218
|
+
instead of `sessionEndpoint` — the two are mutually exclusive, and a public embed needs no backend route:
|
|
219
|
+
|
|
220
|
+
```tsx
|
|
221
|
+
<AssistantWidget embedId="pub_7f2q4k9x" serviceUrl="https://cloud.noodleseed.dev" />
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
A public embed opens its session on **first open**, never on mount — every mount would otherwise spend
|
|
225
|
+
one of the surface's daily admission budget. Add `signIn: true` to the surface and it becomes **mixed**:
|
|
226
|
+
anonymous visitors start immediately, and identity-dependent capabilities raise the sign-in flow below.
|
|
227
|
+
Before shipping, preflight the host with `noodle assistant embed --check --surface public` (or `mixed`) —
|
|
228
|
+
it verifies `script-src` too, the one CSP directive whose failure runs no widget code at all.
|
|
229
|
+
|
|
230
|
+
#### Mid-conversation sign-in (mixed surfaces)
|
|
231
|
+
|
|
232
|
+
On a `publicWebsite({ signIn: true })` surface, an anonymous visitor who reaches an identity-dependent
|
|
233
|
+
capability sees a "Sign in to continue" card, and the widget raises `assistant-sign-in-requested` with a
|
|
234
|
+
single-use `signInTicket` in its detail. The page signs the visitor in however it already does, then its
|
|
235
|
+
backend spends the ticket with the **same** helper and its own client credentials — same endpoint, same
|
|
236
|
+
`user` shape, plus the ticket:
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
const session = await createAssistantSession({
|
|
240
|
+
serviceUrl: process.env.NOODLE_SERVICE_URL!,
|
|
241
|
+
clientId: process.env.NOODLE_ASSISTANT_CLIENT_ID!,
|
|
242
|
+
clientSecret: process.env.NOODLE_ASSISTANT_CLIENT_SECRET!,
|
|
243
|
+
origin: process.env.PUBLIC_APP_ORIGIN!,
|
|
244
|
+
user: { id: user.id, email: user.email, roles: user.roles },
|
|
245
|
+
signInTicket, // from the widget's assistant-sign-in-requested event, via your page
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
The visitor keeps the same conversation with a new token; the anonymous token dies at that moment.
|
|
250
|
+
`signInTicket` and `context` are mutually exclusive — an elevation continues an existing session.
|
|
251
|
+
`routing` IS accepted here, and this is the moment to send it: elevation is the first authenticated
|
|
252
|
+
exchange, so it is the only chance a routed connector's session gets its backend-verified customer
|
|
253
|
+
routes. Possession of a ticket alone elevates nothing:
|
|
254
|
+
spending it also requires your client credentials, and the service checks your tenant owns that
|
|
255
|
+
conversation. (The ticket is deliberately **not** called a continuation: the server-held interaction
|
|
256
|
+
continuation described below must never reach browser code, while this value's whole job is to travel
|
|
257
|
+
through the page.)
|
|
258
|
+
|
|
259
|
+
A refused spend throws `AssistantSessionExchangeError`; branch on `error.elevationRefusal`:
|
|
260
|
+
|
|
261
|
+
| Code | What happened | What to do |
|
|
262
|
+
| :-- | :-- | :-- |
|
|
263
|
+
| `elevation_ticket_expired` | The visitor took too long (tickets live 10 minutes) | Re-prompt; the widget raises a fresh ticket when they retry the action |
|
|
264
|
+
| `elevation_ticket_invalid` | Stale, spent, or double-submitted ticket | Same recovery; log it — a burst is a replay signal |
|
|
265
|
+
| `elevation_tenant_mismatch` | Your credentials do not own that conversation | Alert someone; never retry |
|
|
266
|
+
| `elevation_already_signed_in` / `elevation_session_unavailable` | The conversation moved on | Ask the visitor to refresh |
|
|
267
|
+
|
|
268
|
+
`error.detail.serviceCode === "elevation_unavailable"` (a 503) means the deployment has no elevation
|
|
269
|
+
store configured — page the operator, not the visitor. Failures without a code (fresh-mint refusals,
|
|
270
|
+
proxy errors) carry `error.detail.status`, and `error.detail.retryable` is `true` only for
|
|
271
|
+
infrastructure 5xx responses.
|
|
272
|
+
|
|
205
273
|
Then add the framework-neutral element:
|
|
206
274
|
|
|
207
275
|
```ts
|
|
@@ -8383,11 +8383,16 @@ function toAssistantClientEvent(event) {
|
|
|
8383
8383
|
return event;
|
|
8384
8384
|
}
|
|
8385
8385
|
break;
|
|
8386
|
-
case "auth_requested":
|
|
8387
|
-
|
|
8388
|
-
|
|
8386
|
+
case "auth_requested": {
|
|
8387
|
+
const signInTicket = typeof value.signInTicket === "string" ? value.signInTicket : typeof value.continuation === "string" ? value.continuation : void 0;
|
|
8388
|
+
if (hasString(value, "id") && hasString(value, "tool") && signInTicket !== void 0 && hasString(value, "expiresAt") && hasOptionalTurnId(value)) {
|
|
8389
|
+
return {
|
|
8390
|
+
event: "auth_requested",
|
|
8391
|
+
data: { ...value, signInTicket }
|
|
8392
|
+
};
|
|
8389
8393
|
}
|
|
8390
8394
|
break;
|
|
8395
|
+
}
|
|
8391
8396
|
case "interaction_resolved":
|
|
8392
8397
|
if (hasString(value, "id") && (value.action === void 0 || isInteractionAction(value.action)) && hasOptionalTurnId(value)) {
|
|
8393
8398
|
return event;
|
|
@@ -9261,4 +9266,4 @@ export {
|
|
|
9261
9266
|
AssistantClientError,
|
|
9262
9267
|
createAssistantClient
|
|
9263
9268
|
};
|
|
9264
|
-
//# sourceMappingURL=chunk-
|
|
9269
|
+
//# sourceMappingURL=chunk-52XT7BLR.js.map
|