@pluno/product-agent-web 0.1.200 → 0.1.202

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 CHANGED
@@ -47,10 +47,11 @@ Pluno returns:
47
47
  import { PlunoProductAgent } from "@pluno/product-agent-web";
48
48
 
49
49
  const agent = await PlunoProductAgent.init({
50
- tokenProvider: async () => {
50
+ tokenProvider: async ({ signal } = {}) => {
51
51
  const response = await fetch("/api/pluno-product-agent-token", {
52
52
  method: "POST",
53
53
  credentials: "include",
54
+ signal,
54
55
  });
55
56
  return (await response.json()).token;
56
57
  },
@@ -101,10 +102,11 @@ const { mountPlunoProductAgentWidget } = await import(
101
102
  );
102
103
 
103
104
  const widget = await mountPlunoProductAgentWidget({
104
- tokenProvider: async () => {
105
+ tokenProvider: async ({ signal } = {}) => {
105
106
  const response = await fetch("/api/pluno-product-agent-token", {
106
107
  method: "POST",
107
108
  credentials: "include",
109
+ signal,
108
110
  headers: {
109
111
  Authorization: `Bearer ${customerAccessToken}`,
110
112
  "X-CSRF-Token": csrfToken,
package/README.md CHANGED
@@ -16,10 +16,11 @@ Keep your Product Agent `secret_key` on your server. Browser code should only re
16
16
  import { PlunoProductAgent } from "@pluno/product-agent-web";
17
17
 
18
18
  const agent = await PlunoProductAgent.init({
19
- tokenProvider: async () => {
19
+ tokenProvider: async ({ signal } = {}) => {
20
20
  const response = await fetch("/api/pluno-product-agent-token", {
21
21
  method: "POST",
22
22
  credentials: "include",
23
+ signal,
23
24
  });
24
25
  const payload = await response.json();
25
26
  return payload.token;
@@ -65,10 +66,11 @@ const { mountPlunoProductAgentWidget } = await import(
65
66
  );
66
67
 
67
68
  const widget = await mountPlunoProductAgentWidget({
68
- tokenProvider: async () => {
69
+ tokenProvider: async ({ signal } = {}) => {
69
70
  const response = await fetch("/api/pluno-product-agent-token", {
70
71
  method: "POST",
71
72
  credentials: "include",
73
+ signal,
72
74
  headers: {
73
75
  Authorization: `Bearer ${customerAccessToken}`,
74
76
  "X-CSRF-Token": csrfToken,
@@ -85,6 +87,12 @@ function removeProductAgentWidget() {
85
87
  }
86
88
  ```
87
89
 
90
+ The SDK keeps a valid JWT in memory, refreshes it shortly before expiry, and automatically retries transient provider
91
+ failures with capped backoff. Pass the supplied abort signal to your request so destroying the widget cancels it.
92
+ Generic provider failures are treated as transient; throw `ProductAgentTokenProviderError` with `retryable: false` for a
93
+ known permanent host-side validation or authorization failure, for example
94
+ `new ProductAgentTokenProviderError("Not authorized", false, 403)`.
95
+
88
96
  Importing the hosted module does not mount anything by itself. `mountPlunoProductAgentWidget` returns a handle containing
89
97
  the underlying `agent`, `openPanel()`, appearance/auth update methods, and `destroy()`.
90
98
 
package/dist/index.d.ts CHANGED
@@ -153,9 +153,19 @@ export type ProductAgentState = {
153
153
  lastErrorCode: string | null;
154
154
  lastErrorSecuritySettingsUrl: string | null;
155
155
  };
156
+ export type ProductAgentTokenProviderContext = {
157
+ signal: AbortSignal;
158
+ reason: "connect" | "upload" | "history";
159
+ };
160
+ export declare class ProductAgentTokenProviderError extends Error {
161
+ readonly retryable: boolean;
162
+ readonly status?: number | undefined;
163
+ readonly retryAfterMs?: number | undefined;
164
+ constructor(message: string, retryable: boolean, status?: number | undefined, retryAfterMs?: number | undefined);
165
+ }
156
166
  export type ProductAgentInitOptions = {
157
167
  token?: string;
158
- tokenProvider?: () => Promise<string>;
168
+ tokenProvider?: (context?: ProductAgentTokenProviderContext) => Promise<string>;
159
169
  backendUrl?: string;
160
170
  model?: ProductAgentModel;
161
171
  clientId?: string;
@@ -253,6 +263,9 @@ export declare class ProductAgentSessionEngine {
253
263
  private connectionAttemptId;
254
264
  private connectionInProgress;
255
265
  private token;
266
+ private tokenExpiresAtMs;
267
+ private tokenRequest;
268
+ private tokenAbortController;
256
269
  private authenticatedUserId;
257
270
  private authenticatedSocket;
258
271
  private networkCaptureCleanup;
@@ -339,6 +352,8 @@ export declare class ProductAgentSessionEngine {
339
352
  on<T extends EventName>(eventName: T, listener: Listener<T>): () => void;
340
353
  getState(): ProductAgentState;
341
354
  stageProactiveSuggestionQuestion(question: string): void;
355
+ private invalidateProviderToken;
356
+ private acquireToken;
342
357
  connect(): Promise<void>;
343
358
  disconnect(): void;
344
359
  destroy(): void;