@noodleseed/assistant 1.1.0 → 1.2.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 +90 -7
- package/dist/chunk-J2YDKISA.js +1113 -0
- package/dist/chunk-J2YDKISA.js.map +1 -0
- package/dist/chunk-WUDHE5BD.js +636 -0
- package/dist/chunk-WUDHE5BD.js.map +1 -0
- package/dist/client-CwvdK4O6.d.cts +165 -0
- package/dist/client-DkAfqcSb.d.ts +165 -0
- package/dist/client.cjs +662 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +2 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +9 -0
- package/dist/client.js.map +1 -0
- package/dist/index.cjs +1273 -234
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -12
- package/dist/index.d.ts +14 -12
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +1273 -234
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -1
- package/dist/react.d.ts +2 -1
- package/dist/react.js +2 -1
- package/dist/react.js.map +1 -1
- package/dist/server.cjs +3 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +12 -0
- package/dist/server.d.ts +12 -0
- package/dist/server.js +3 -1
- package/dist/server.js.map +1 -1
- package/package.json +10 -1
- package/dist/chunk-OXFV6KZ2.js +0 -698
- package/dist/chunk-OXFV6KZ2.js.map +0 -1
package/README.md
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
Customer-branded embedded assistant surfaces for Noodle Seed deployments.
|
|
4
4
|
|
|
5
5
|
The package exports the canonical `<noodle-assistant>` Web Component, a React wrapper from
|
|
6
|
-
`@noodleseed/assistant/react`, and the backend-only
|
|
7
|
-
`@noodleseed/assistant/server`. Light, dark, and automatic themes work
|
|
8
|
-
inherits the deployed MCP server's brand kit while slots, methods,
|
|
9
|
-
SaaS developer integrate it without depending on internal DOM
|
|
6
|
+
`@noodleseed/assistant/react`, a DOM-free client from `@noodleseed/assistant/client`, and the backend-only
|
|
7
|
+
`createAssistantSession` helper from `@noodleseed/assistant/server`. Light, dark, and automatic themes work
|
|
8
|
+
without configuration; the component inherits the deployed MCP server's brand kit while slots, methods,
|
|
9
|
+
events, and semantic CSS variables let a SaaS developer integrate it without depending on internal DOM
|
|
10
|
+
selectors.
|
|
10
11
|
|
|
11
12
|
Never pass an embed client secret, model key, MCP token, or raw application session into the browser
|
|
12
13
|
component. Exchange the already-authenticated user from the customer backend and return only the short-lived
|
|
@@ -74,6 +75,7 @@ export async function POST(request: Request) {
|
|
|
74
75
|
origin: process.env.PUBLIC_APP_ORIGIN!,
|
|
75
76
|
user: { id: user.id, email: user.email, roles: user.roles },
|
|
76
77
|
context,
|
|
78
|
+
preferences: { locale: user.locale, timeZone: user.timeZone },
|
|
77
79
|
});
|
|
78
80
|
return Response.json(session);
|
|
79
81
|
}
|
|
@@ -97,6 +99,85 @@ import { NoodleAssistant } from '@noodleseed/assistant/react';
|
|
|
97
99
|
<NoodleAssistant sessionEndpoint="/api/assistant/session" theme="auto" />;
|
|
98
100
|
```
|
|
99
101
|
|
|
102
|
+
For a customer-owned renderer, subscribe to the same turn and interaction stream without registering a
|
|
103
|
+
custom element or touching browser storage:
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
import { createAssistantClient } from '@noodleseed/assistant/client';
|
|
107
|
+
|
|
108
|
+
const assistant = createAssistantClient({
|
|
109
|
+
sessionEndpoint: '/api/assistant/session',
|
|
110
|
+
clientContext: () => ({
|
|
111
|
+
locale: navigator.language,
|
|
112
|
+
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
113
|
+
}),
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
assistant.updateModelContext({
|
|
117
|
+
content: [{ type: 'text', text: 'The time-off form is mounted.' }],
|
|
118
|
+
structuredContent: { widget: { name: 'time-off', lifecycle: 'mounted' } },
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const unsubscribe = assistant.subscribe((event) => {
|
|
122
|
+
renderAssistantEvent(event);
|
|
123
|
+
if (event.event === 'view_available') {
|
|
124
|
+
renderRegisteredView(event.data.resourceUri, event.data.result);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
await assistant.sendMessage('Book next Thursday and Friday off');
|
|
128
|
+
await assistant.respond('interaction_123', { action: 'accept' });
|
|
129
|
+
// Resolve one interaction once; alternatives are { action: 'decline' } or { action: 'cancel' }.
|
|
130
|
+
|
|
131
|
+
unsubscribe();
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`clientContext` contains untrusted locale/timezone presentation hints and is evaluated for every turn.
|
|
135
|
+
The client resolves a turn or interaction only after exactly one valid terminal `done` event followed by
|
|
136
|
+
stream EOF. A truncated or malformed stream, duplicate `done`, or any frame after `done` is
|
|
137
|
+
`invalid_response`; it never emits `message_completed` or `interaction_completed` for that response.
|
|
138
|
+
`updateContext` remains the separate untrusted page-context channel used on the next session exchange.
|
|
139
|
+
`updateModelContext({ content, structuredContent })` replaces the complete renderer snapshot attached to each
|
|
140
|
+
later message turn without starting a turn itself; updates do not merge with prior fields. The same method is
|
|
141
|
+
available on `<noodle-assistant>` for cohesive surface snapshots such as mounted, submitted, cancelled, or
|
|
142
|
+
dismissed. Model context is untrusted, per-turn data: it is not conversation history or authorization input,
|
|
143
|
+
and credential-shaped or unbounded updates are rejected.
|
|
144
|
+
Backend `preferences` are the signed-in user's saved locale/time-zone choices and outrank those hints. Only
|
|
145
|
+
message turns retry once after an expired session; the client never auto-retries interaction decisions. A
|
|
146
|
+
`tool_proposed` event carries a complete schema-projected review of the tool input and collected answers. For
|
|
147
|
+
a connector-backed tool it also identifies the exact connector version, operation, and resolved arguments;
|
|
148
|
+
confirmable flows contain at most that one connector operation. Sensitive fields may be redacted, but any
|
|
149
|
+
other truncation or omission fails closed. Accept is bound to that server-held action and claims one
|
|
150
|
+
execution attempt; drift fails closed, while decline/cancel resolve without execution. Normal terminal
|
|
151
|
+
outcomes scrub private arguments and continuations immediately. Only an accepted action still in the
|
|
152
|
+
`executing` state retains them during its one-hour unknown-outcome recovery window; expiry records a bounded
|
|
153
|
+
`interaction_outcome_unknown` result and scrubs the payload. Without downstream idempotency this is not an
|
|
154
|
+
exactly-once business-effect guarantee. A caller may explicitly repeat the same id and decision to retrieve
|
|
155
|
+
the durable stored outcome without another execution attempt.
|
|
156
|
+
At the manifest/runtime boundary, only `confirm: true` enables this gate; omitted or `false` preserves direct
|
|
157
|
+
execution and standard annotations remain hints. TypeScript action helpers likewise require
|
|
158
|
+
`{ confirm: true }`; action/destructive/open-world hints alone never enforce approval. Capable bidirectional
|
|
159
|
+
MCP transports render the same gate as standard form elicitation and fail closed when that exchange is
|
|
160
|
+
unavailable.
|
|
161
|
+
An `input_requested` event carries the message and portable form schema recorded by `ctx.elicit`. After the
|
|
162
|
+
turn stream completes, a headless renderer answers it with
|
|
163
|
+
`respond(id, { action: 'accept', content })`, or stops it with decline/cancel. The Web Component renders the
|
|
164
|
+
same primitive as native controls. Accepted content is schema-validated before the runtime resumes, and the
|
|
165
|
+
server-held continuation is never exposed to browser code. Schema-invalid content returns `arg_invalid` and
|
|
166
|
+
leaves the same input interaction pending so the renderer can submit a corrected answer. Every interactive
|
|
167
|
+
flow collects all elicited input before its first connector operation.
|
|
168
|
+
|
|
169
|
+
A completed widget-linked tool emits typed `view_available` data with its call/interaction id, tool,
|
|
170
|
+
`ui://` resource identity, optional title, and bounded/redacted public result. This is an availability
|
|
171
|
+
signal, not proof of rendering. Map the identity to a component already trusted by your application; never
|
|
172
|
+
fetch the `ui://` URI or inject its resource HTML into your page. The standard element does not render it,
|
|
173
|
+
but forwards the same detail as a DOM event:
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
element.addEventListener('assistant-view-available', (event) => {
|
|
177
|
+
renderRegisteredView(event.detail.resourceUri, event.detail.result);
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
100
181
|
Assistant text renders as provider deltas arrive. If a turn finds an expired session, the component calls
|
|
101
182
|
the same authenticated session endpoint and retries that unprocessed message once. Confirmations never
|
|
102
183
|
replay across sessions. React applications may observe recovery and structured failures:
|
|
@@ -110,7 +191,7 @@ replay across sessions. React applications may observe recovery and structured f
|
|
|
110
191
|
```
|
|
111
192
|
|
|
112
193
|
`createAssistantSession` returns the opaque token, expiry, resolved non-secret configuration, and explicit
|
|
113
|
-
|
|
194
|
+
turn/interaction endpoint URLs. Forward that response unchanged to the component or headless client.
|
|
114
195
|
|
|
115
196
|
The MCP server's top-level `branding` block provides the shared identity and theme for widgets and the
|
|
116
197
|
assistant. Set semantic CSS variables only for application-level integration overrides:
|
|
@@ -128,5 +209,7 @@ radius, typography, and automatic theme. `embeddedAssistant(...)` controls float
|
|
|
128
209
|
position and dimensions, mobile and launcher/header/avatar/timestamp behavior, visible labels, suggested
|
|
129
210
|
prompts, privacy/terms links, locale, and text direction.
|
|
130
211
|
Named slots cover launcher/header/composer/footer extensions. Public methods include `open`, `close`,
|
|
131
|
-
`toggle`, `focusComposer`, `sendMessage`, `updateContext`, `confirmTool`, and `resetSession`;
|
|
132
|
-
message, tool-proposal,
|
|
212
|
+
`toggle`, `focusComposer`, `sendMessage`, `updateContext`, `updateModelContext`, `respond`, `confirmTool`, and `resetSession`;
|
|
213
|
+
lifecycle, message, tool-proposal, interaction-resolution, view-availability, context, and error events
|
|
214
|
+
support application integration. `confirmTool(id)` remains the compatibility shorthand for
|
|
215
|
+
`respond(id, { action: 'accept' })`.
|