@graineai/inapp-react-native 0.24.0 → 0.25.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/INTEGRATION.md +36 -1
- package/README.md +14 -1
- package/dist/client.d.ts +1 -0
- package/dist/client.js +7 -0
- package/dist/react-native/index.js +1 -1
- package/package.json +1 -1
package/INTEGRATION.md
CHANGED
|
@@ -809,6 +809,26 @@ useGraineEvents((e) => {
|
|
|
809
809
|
});
|
|
810
810
|
```
|
|
811
811
|
|
|
812
|
+
## Fast navigation: the agent always has the latest screen
|
|
813
|
+
|
|
814
|
+
A customer who taps through four screens and then asks "where am I?" gets the
|
|
815
|
+
fourth. The guarantees, so you do not have to think about them:
|
|
816
|
+
|
|
817
|
+
- **Immediate.** `useGraineScreen` reports a screen the moment it mounts, and
|
|
818
|
+
the voice launcher relays it to the runtime at once — the 400ms coalescing
|
|
819
|
+
applies only to the SDK's own text socket, never to a host's channel.
|
|
820
|
+
- **Ordered.** Every context frame carries a monotonic `seq`; the runtime keeps
|
|
821
|
+
the newest and drops anything that arrives late. The last screen always wins.
|
|
822
|
+
- **Cleanup-safe.** A screen's unmount clears the screen only if it is still
|
|
823
|
+
the one being described (`client.clearScreen(id)`), so a navigation library
|
|
824
|
+
unmounting the old screen after the new one mounted cannot erase it.
|
|
825
|
+
- **Reconnect-safe.** The newest context is replayed whenever the media or the
|
|
826
|
+
screen channel (re)connects.
|
|
827
|
+
|
|
828
|
+
If you drive the client yourself instead of using `useGraineScreen`, call
|
|
829
|
+
`client.setScreen(ctx)` on mount and `client.clearScreen(ctx.screen)` on
|
|
830
|
+
unmount — never `setScreen(null)` from a cleanup.
|
|
831
|
+
|
|
812
832
|
## What Call History shows for an in-app conversation
|
|
813
833
|
|
|
814
834
|
Every conversation lands in the dashboard's Call History with, beside the
|
|
@@ -880,7 +900,8 @@ told to ignore).
|
|
|
880
900
|
| `useGraineHighlight()` | let the agent point at an element on this screen |
|
|
881
901
|
| `useGraineWidget()` | the component the agent drew, and how to answer it |
|
|
882
902
|
| `useGraineTrack()` | product events that inform but do not interrupt |
|
|
883
|
-
| `useGraineEvents()` | conversation lifecycle |
|
|
903
|
+
| `useGraineEvents()` | conversation lifecycle, action outcomes, friction signals |
|
|
904
|
+
| `useGraineTap()` | wrap an `onPress` so the tap is tracked (and rage taps detected) |
|
|
884
905
|
| `useGraineVoice()` | only if you bring your own native audio instead of the WebView |
|
|
885
906
|
|
|
886
907
|
### `GraineProvider`
|
|
@@ -897,6 +918,20 @@ told to ignore).
|
|
|
897
918
|
| `autoConnect` | `boolean` | Default `true`. Set `false` when `GraineVoiceLauncher` owns the connection — see below. |
|
|
898
919
|
| `onProactive` | `(text) => void` | The agent spoke first; draw your own nudge. |
|
|
899
920
|
| `endOnBackground` | `boolean` | Default `true`. You want it on. |
|
|
921
|
+
| `appVersion` | `string` | Which build the conversation happened in. Lands on the call record. |
|
|
922
|
+
| `friction` | `FrictionConfig` | This app's friction rules, layered over the dashboard's. See *Friction detection*. |
|
|
923
|
+
|
|
924
|
+
### `GraineInAppClient`
|
|
925
|
+
|
|
926
|
+
| Method | For |
|
|
927
|
+
|---|---|
|
|
928
|
+
| `setScreen(ctx)` / `clearScreen(id)` | Report a screen; withdraw it only if it is still the current one. |
|
|
929
|
+
| `identify(user)` | Who the customer is. Masked on the way out. |
|
|
930
|
+
| `track(name, data)` / `reportEvent(event)` | Inform the agent / ask it to speak up. |
|
|
931
|
+
| `registerAction(name, handler)` / `executeAction(name, args)` | Implement and run in-app actions. |
|
|
932
|
+
| `configureFriction(rules)` / `friction` | Replace the app's friction layer / read the resolved rules. |
|
|
933
|
+
| `session()` | The dashboard config for this key: appearance, actions, friction. |
|
|
934
|
+
| `on(event, fn)` | `screen`, `action`, `action_result`, `friction`, `app_event`, `mic_denied`, … |
|
|
900
935
|
|
|
901
936
|
### `GraineVoiceLauncher`
|
|
902
937
|
|
package/README.md
CHANGED
|
@@ -219,11 +219,24 @@ requests a permission on your behalf.
|
|
|
219
219
|
| `useGraineScreen(context)` | Report what this screen shows. |
|
|
220
220
|
| `useGraineAction(name, handler)` | Implement one action the agent may call. |
|
|
221
221
|
| `useGraineVoice(adapter, opts)` | Microphone, playback and barge-in. |
|
|
222
|
+
| `useGraineEvents(fn)` | Conversation lifecycle, `action_completed`, `friction_detected`, `mic_denied`. |
|
|
223
|
+
| `useGraineTrack()` / `useGraineTap()` | Product events and taps the agent knows about but does not interrupt for. |
|
|
224
|
+
| `useGraineIdentify()` | Who the customer is — it reaches the greeting and the call record. |
|
|
225
|
+
| `useGraineHighlight()` / `useGraineWidget()` | Let the agent point at things and draw components. |
|
|
226
|
+
| `GraineVoiceLauncher` | The voice engine: WebView, microphone, WebRTC or WebSocket. |
|
|
222
227
|
| `GraineAgentBar` | Optional default UI. Mount at the root. Replace it with your own. |
|
|
223
228
|
| `addMaskRule(pattern, token)` | Mask an app-specific identifier format. |
|
|
224
229
|
|
|
230
|
+
**Friction detection** — the agent notices a stuck customer (idle, repeated
|
|
231
|
+
field errors, back-and-forth, rage taps, error banners) and speaks first. Rules
|
|
232
|
+
are JSON, per screen, configured in the dashboard; pass `friction` on the
|
|
233
|
+
provider only for the screens your app knows better. `DEFAULT_FRICTION`,
|
|
234
|
+
`resolveFriction` and `FrictionDetector` are exported for hosts that want the
|
|
235
|
+
engine on their own timers.
|
|
236
|
+
|
|
225
237
|
`GraineInAppClient` is exported for apps that want the transport without the
|
|
226
|
-
React layer
|
|
238
|
+
React layer: `setScreen`, `clearScreen`, `identify`, `track`, `reportEvent`,
|
|
239
|
+
`registerAction`, `executeAction`, `configureFriction`, `friction`, `session`.
|
|
227
240
|
|
|
228
241
|
## Support
|
|
229
242
|
|
package/dist/client.d.ts
CHANGED
|
@@ -91,6 +91,7 @@ export declare class GraineInAppClient {
|
|
|
91
91
|
highlight(name: string | null, ttlMs?: number): void;
|
|
92
92
|
registerAction(name: string, handler: ActionHandler): () => void;
|
|
93
93
|
get availableActions(): string[];
|
|
94
|
+
clearScreen(screenId: string | null | undefined): void;
|
|
94
95
|
setScreen(context: ScreenContext | null): void;
|
|
95
96
|
private dispatchFriction;
|
|
96
97
|
reportEvent(event: AppEvent): void;
|
package/dist/client.js
CHANGED
|
@@ -363,6 +363,13 @@ export class GraineInAppClient {
|
|
|
363
363
|
get availableActions() {
|
|
364
364
|
return [...this.actions.keys()];
|
|
365
365
|
}
|
|
366
|
+
clearScreen(screenId) {
|
|
367
|
+
if (!this.screen)
|
|
368
|
+
return;
|
|
369
|
+
if (screenId && this.screen.screen !== screenId)
|
|
370
|
+
return;
|
|
371
|
+
this.setScreen(null);
|
|
372
|
+
}
|
|
366
373
|
setScreen(context) {
|
|
367
374
|
const changedScreen = context?.screen !== this.screen?.screen;
|
|
368
375
|
this.screen = context;
|
|
@@ -332,7 +332,7 @@ export function useGraineScreen(context) {
|
|
|
332
332
|
const serialised = JSON.stringify(context ?? null);
|
|
333
333
|
useEffect(() => {
|
|
334
334
|
client.setScreen(context);
|
|
335
|
-
return () => client.
|
|
335
|
+
return () => client.clearScreen(context?.screen);
|
|
336
336
|
}, [client, serialised]);
|
|
337
337
|
}
|
|
338
338
|
export function useGraineHighlight(name) {
|
package/package.json
CHANGED