@pluno/product-agent-web 0.1.192 → 0.1.197
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/activityLoading.d.ts +4 -0
- package/dist/composerFocus.d.ts +15 -0
- package/dist/index.d.ts +73 -8
- package/dist/interactionManager.d.ts +38 -0
- package/dist/product-agent-runtime.cjs +1 -0
- package/dist/product-agent-runtime.js +806 -0
- package/dist/product-agent-sdk.js +3421 -2134
- package/dist/product-agent-widget.js +4863 -3915
- package/dist/runtime.d.ts +10 -0
- package/dist/runtimeClient.d.ts +189 -0
- package/dist/runtimeState.d.ts +174 -0
- package/dist/sessionActivityRecovery.d.ts +28 -0
- package/dist/sessionHistoryState.d.ts +57 -0
- package/dist/sessionRecoveryPolling.d.ts +25 -0
- package/dist/taskPageTitle.d.ts +1 -0
- package/dist/widget.d.ts +26 -53
- package/package.json +12 -5
package/dist/composerFocus.d.ts
CHANGED
|
@@ -2,3 +2,18 @@ export declare function isPassiveComposerFocusClick(target: EventTarget | null,
|
|
|
2
2
|
export declare function shouldFocusComposerFromSurfaceInteraction(clickCount: number, hasTextSelection: boolean, isInteractiveTarget: boolean): boolean;
|
|
3
3
|
export declare function isOutsideOverlayClick(target: EventTarget | null, overlay: Element | null, trigger: Element | null): boolean;
|
|
4
4
|
export declare function focusComposer(composer: HTMLTextAreaElement | null, isAvailable?: boolean): boolean;
|
|
5
|
+
type ComposerKeystrokeEvent = {
|
|
6
|
+
key: string;
|
|
7
|
+
defaultPrevented: boolean;
|
|
8
|
+
isComposing: boolean;
|
|
9
|
+
metaKey: boolean;
|
|
10
|
+
ctrlKey: boolean;
|
|
11
|
+
altKey: boolean;
|
|
12
|
+
getModifierState?: (keyArg: string) => boolean;
|
|
13
|
+
};
|
|
14
|
+
export declare function getComposerKeystroke(event: ComposerKeystrokeEvent, activeTarget: EventTarget | null): string | null;
|
|
15
|
+
export declare function insertComposerKeystroke(value: string, selectionStart: number | null, selectionEnd: number | null, keystroke: string): {
|
|
16
|
+
value: string;
|
|
17
|
+
caret: number;
|
|
18
|
+
};
|
|
19
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ProductAgentTaskStatus } from "./taskPageTitle";
|
|
2
|
+
import type { ProductAgentEntityQueryData, ProductAgentAccountProjection, ProductAgentInteraction, ProductAgentInteractionAction, ProductAgentQueryState } from "./runtimeState";
|
|
2
3
|
export type ProductAgentModel = "anthropic/claude-opus-5" | "anthropic/claude-sonnet-5" | "deepseek/deepseek-chat-v3.1" | "deepseek/deepseek-v4-flash" | "gpt-5.4-nano" | "gpt-5.4-mini" | "gpt-5.4" | "gpt-5.6-luna" | "gpt-5.6-terra" | "gpt-5.6-sol";
|
|
3
4
|
export type ProductAgentEntrySurface = "extension_sidepanel" | "extension_widget" | "main_web_chat" | "whatsapp" | "automation" | "mcp" | "embedded_widget" | "embedded_custom_ui";
|
|
4
5
|
export type ProductAgentProductVariant = "personal" | "customer_embedded";
|
|
@@ -32,13 +33,13 @@ export declare const PLUNO_PRODUCT_AGENT_WIDGET_HOST_SELECTOR = ".pluno-pa-widge
|
|
|
32
33
|
export declare const PLUNO_PRODUCT_AGENT_WIDGET_ROOT_SELECTOR = ".pluno-pa-widget[data-pluno-product-agent-ui-root=\"widget\"]";
|
|
33
34
|
export declare const PLUNO_PRODUCT_AGENT_WIDGET_PANEL_SELECTOR = ".pluno-pa-widget__panel";
|
|
34
35
|
export declare const PLUNO_PRODUCT_AGENT_WIDGET_TIMELINE_SELECTOR = ".pluno-pa-widget__timeline";
|
|
35
|
-
export declare const PLUNO_PRODUCT_AGENT_SDK_PREVIEW_HOST_SELECTOR = ".pluno-pa-widget-host[data-pluno-product-agent-ui=\"widget\"][data-pluno-sdk-preview-channel]";
|
|
36
36
|
export type ProductAgentMessage = {
|
|
37
37
|
id: string;
|
|
38
38
|
role: "user" | "assistant" | "tool" | "system";
|
|
39
39
|
phase?: "commentary" | "final_answer";
|
|
40
40
|
content: string;
|
|
41
41
|
createdAt: string;
|
|
42
|
+
displaySequence?: number;
|
|
42
43
|
causalSequence?: number;
|
|
43
44
|
respondsToUserMessageId?: string;
|
|
44
45
|
runId?: string;
|
|
@@ -142,6 +143,7 @@ export type ProductAgentState = {
|
|
|
142
143
|
assistantDraftPhase: "commentary" | "final_answer" | null;
|
|
143
144
|
assistantDraftRespondsToUserMessageId: string | null;
|
|
144
145
|
assistantDraftRunId: string | null;
|
|
146
|
+
activeResponseUserMessageId?: string | null;
|
|
145
147
|
pendingMessageStatus: "sending" | "reconnecting" | null;
|
|
146
148
|
turnPhase: ProductAgentTurnPhase | null;
|
|
147
149
|
isThinking: boolean;
|
|
@@ -171,6 +173,21 @@ export type ProductAgentInitOptions = {
|
|
|
171
173
|
automationRunId?: string;
|
|
172
174
|
keepRunsActiveOnSessionNavigation?: boolean;
|
|
173
175
|
capturePageContent?: boolean;
|
|
176
|
+
accountLoader?: () => Promise<ProductAgentAccountProjection | null>;
|
|
177
|
+
initialAccount?: ProductAgentAccountProjection | null;
|
|
178
|
+
runtimeAdapters?: ProductAgentRuntimeAdapters;
|
|
179
|
+
};
|
|
180
|
+
export type ProductAgentRuntimeAdapters = {
|
|
181
|
+
integrationAuthStatusLoader?: (request: ProductAgentIntegrationAuthRequest) => Promise<"pending" | "completed" | "cancelled" | "expired">;
|
|
182
|
+
integrationAuthHandler?: (request: ProductAgentIntegrationAuthRequest) => Promise<void>;
|
|
183
|
+
personalChannelConnectionHandler?: (request: ProductAgentPersonalChannelConnectionRequest) => Promise<void>;
|
|
184
|
+
tabGroups?: {
|
|
185
|
+
getState: () => Promise<{
|
|
186
|
+
permissionNeeded: boolean;
|
|
187
|
+
}>;
|
|
188
|
+
enable: () => Promise<void>;
|
|
189
|
+
dismiss: () => Promise<void>;
|
|
190
|
+
};
|
|
174
191
|
};
|
|
175
192
|
export type ProductAgentWebSocket = {
|
|
176
193
|
readyState: number;
|
|
@@ -223,7 +240,7 @@ type NetworkCaptureManager = {
|
|
|
223
240
|
};
|
|
224
241
|
export declare const PRODUCT_AGENT_PROVIDER_INPUT_ATTACHMENT_ACCEPT = ".pdf,.png,.jpg,.jpeg,.webp";
|
|
225
242
|
export declare function calculateReconnectDelay(attempt: number, random?: () => number): number;
|
|
226
|
-
export declare class
|
|
243
|
+
export declare class ProductAgentSessionEngine {
|
|
227
244
|
private readonly options;
|
|
228
245
|
private readonly listeners;
|
|
229
246
|
private socket;
|
|
@@ -249,6 +266,21 @@ export declare class PlunoProductAgent {
|
|
|
249
266
|
private activeComposerWarmupScope;
|
|
250
267
|
private pendingWarmupAckTimer;
|
|
251
268
|
private pendingSessionHistoryRequests;
|
|
269
|
+
private readonly sessionHistoryManager;
|
|
270
|
+
private readonly sessionRecoveryPoller;
|
|
271
|
+
private readonly sessionActivityRecovery;
|
|
272
|
+
private readonly sessionActivityRecoveryPoller;
|
|
273
|
+
private sessionRecoveryScope;
|
|
274
|
+
private account;
|
|
275
|
+
private usingPaidCreditFallback;
|
|
276
|
+
private readonly accountListeners;
|
|
277
|
+
private accountRefresh;
|
|
278
|
+
private runtimeInteractions;
|
|
279
|
+
private readonly interactionListeners;
|
|
280
|
+
private readonly interactionManager;
|
|
281
|
+
private integrationAuthStatusByRequestId;
|
|
282
|
+
private integrationAuthErrorByRequestId;
|
|
283
|
+
private tabGroupsPermissionNeeded;
|
|
252
284
|
private pendingSessionPinRequests;
|
|
253
285
|
private pendingSessionRenameRequests;
|
|
254
286
|
private sessionLoadRequestId;
|
|
@@ -259,7 +291,6 @@ export declare class PlunoProductAgent {
|
|
|
259
291
|
private readonly transportIdentity;
|
|
260
292
|
private retryAttemptsByClientMessageId;
|
|
261
293
|
private retryTimersByClientMessageId;
|
|
262
|
-
private recoveryExhaustionRequestedClientMessageIds;
|
|
263
294
|
private readonly reportedHealthSignalKeys;
|
|
264
295
|
private readonly clientMessageIdsByUserMessageItemId;
|
|
265
296
|
private readonly backgroundSessionIds;
|
|
@@ -303,7 +334,7 @@ export declare class PlunoProductAgent {
|
|
|
303
334
|
private lastStarterPromptPageUrl;
|
|
304
335
|
private state;
|
|
305
336
|
private constructor();
|
|
306
|
-
static init(options: ProductAgentInitOptions): Promise<
|
|
337
|
+
static init(options: ProductAgentInitOptions): Promise<ProductAgentSessionEngine>;
|
|
307
338
|
on<T extends EventName>(eventName: T, listener: Listener<T>): () => void;
|
|
308
339
|
getState(): ProductAgentState;
|
|
309
340
|
stageProactiveSuggestionQuestion(question: string): void;
|
|
@@ -337,14 +368,30 @@ export declare class PlunoProductAgent {
|
|
|
337
368
|
limit?: number;
|
|
338
369
|
pinned?: boolean;
|
|
339
370
|
}): Promise<ProductAgentSessionHistoryPage>;
|
|
371
|
+
getSessionHistoryState(): ProductAgentQueryState<ProductAgentEntityQueryData<ProductAgentSessionHistoryEntry>>;
|
|
372
|
+
subscribeSessionHistory(listener: (state: ProductAgentQueryState<ProductAgentEntityQueryData<ProductAgentSessionHistoryEntry>>) => void): () => void;
|
|
373
|
+
refreshSessionHistory(): Promise<void>;
|
|
374
|
+
loadMoreSessionHistory(): Promise<void>;
|
|
340
375
|
setSessionPinned(sessionId: string, pinned: boolean): Promise<void>;
|
|
341
376
|
renameSession(sessionId: string, title: string): Promise<void>;
|
|
377
|
+
getInteractions(): readonly ProductAgentInteraction[];
|
|
378
|
+
subscribeInteractions(listener: (interactions: readonly ProductAgentInteraction[]) => void): () => void;
|
|
379
|
+
actOnInteraction(interactionId: string, action: ProductAgentInteractionAction, expectedRevision: number, input?: {
|
|
380
|
+
feedback?: string;
|
|
381
|
+
snoozeUntil?: string;
|
|
382
|
+
}): Promise<void>;
|
|
383
|
+
private refreshRuntimeInteractions;
|
|
384
|
+
private rebuildRuntimeInteractions;
|
|
385
|
+
getAccount(): ProductAgentAccountProjection | null;
|
|
386
|
+
subscribeAccount(listener: (account: ProductAgentAccountProjection | null) => void): () => void;
|
|
387
|
+
refreshAccount(): Promise<void>;
|
|
342
388
|
loadSession(sessionId: string): void;
|
|
343
389
|
private canLoadSessionHistoryOverHttp;
|
|
344
390
|
private loadSessionHistoryOverHttp;
|
|
345
391
|
private subscribeToSessionBeforeHistory;
|
|
346
392
|
private autoLoadSessionActivity;
|
|
347
393
|
private fetchSessionHistoryPageUntilCurrent;
|
|
394
|
+
private fetchSessionHistoryPageOnce;
|
|
348
395
|
private failSessionHistoryRequest;
|
|
349
396
|
private send;
|
|
350
397
|
private getUploadToken;
|
|
@@ -367,15 +414,15 @@ export declare class PlunoProductAgent {
|
|
|
367
414
|
private shouldIgnoreStoppedTurnEvent;
|
|
368
415
|
private filterStoppedSnapshotItems;
|
|
369
416
|
private handleServerEvent;
|
|
417
|
+
private applyAccountSubmissionError;
|
|
370
418
|
private updatePersonalModelFromSession;
|
|
419
|
+
private updateAccountFallbackFromSession;
|
|
371
420
|
private shouldIgnoreBackgroundSessionEvent;
|
|
372
421
|
private shouldIgnoreDetachedSessionEvent;
|
|
373
422
|
private shouldDeferDetachedSessionEvent;
|
|
374
423
|
private rememberCurrentRunAsDetached;
|
|
375
424
|
private rememberCurrentRunAsBackground;
|
|
376
|
-
private
|
|
377
|
-
private retryAfterInterruptedRun;
|
|
378
|
-
private requestSessionRecoveryExhaustion;
|
|
425
|
+
private handleRetryableRecoveryError;
|
|
379
426
|
private clearRetryTimers;
|
|
380
427
|
private rememberUserMessageClientMessageIds;
|
|
381
428
|
private rejectPendingSessionHistoryRequests;
|
|
@@ -389,6 +436,7 @@ export declare class PlunoProductAgent {
|
|
|
389
436
|
private clearThinkingWatchdog;
|
|
390
437
|
private handleRunAck;
|
|
391
438
|
private promotePendingDelivery;
|
|
439
|
+
private shouldDeferPendingDeliveryPromotion;
|
|
392
440
|
private schedulePendingDeliveryAck;
|
|
393
441
|
private retryPendingDelivery;
|
|
394
442
|
private failPendingDelivery;
|
|
@@ -396,7 +444,6 @@ export declare class PlunoProductAgent {
|
|
|
396
444
|
private handleRunSteered;
|
|
397
445
|
private scheduleRunAckWatchdog;
|
|
398
446
|
private recoverMissedRunAck;
|
|
399
|
-
private scheduleRunAckResyncRetry;
|
|
400
447
|
private clearRunAckResyncRetryTimer;
|
|
401
448
|
private clearRunAckTimers;
|
|
402
449
|
private recoverStuckThinking;
|
|
@@ -421,6 +468,9 @@ export declare class PlunoProductAgent {
|
|
|
421
468
|
private replaceTimedOutSocket;
|
|
422
469
|
private setState;
|
|
423
470
|
private setReconnectingState;
|
|
471
|
+
private startSessionRecoveryPolling;
|
|
472
|
+
private stopSessionRecoveryPolling;
|
|
473
|
+
private applySessionRecoverySnapshot;
|
|
424
474
|
private emit;
|
|
425
475
|
}
|
|
426
476
|
declare global {
|
|
@@ -429,5 +479,20 @@ declare global {
|
|
|
429
479
|
}
|
|
430
480
|
}
|
|
431
481
|
export declare function getProductAgentOriginAccessErrorMessage(message: string, runtimeOrigin?: string): string | null;
|
|
482
|
+
export declare function normalizeProductAgentSessionItems(value: unknown, backendUrl?: string): ProductAgentMessage[];
|
|
432
483
|
export declare function validateProductAgentProviderInputFile(file: File): void;
|
|
484
|
+
export { createProductAgentQueryState, mergeProductAgentEntityPages, normalizeProductAgentEntityPage, ProductAgentQueryController, resolveProductAgentComposerAction, resolveProductAgentWidgetPresentation, selectProductAgentQueryEntities, } from "./runtimeState";
|
|
485
|
+
export { ProductAgentSessionHistoryManager } from "./sessionHistoryState";
|
|
486
|
+
export type { ProductAgentSessionHistoryEntity, ProductAgentSessionHistoryLoader, } from "./sessionHistoryState";
|
|
487
|
+
export { createLocalStorageInteractionDecisionStorage, ProductAgentInteractionManager, readLocalStorageInteractionDecisions, } from "./interactionManager";
|
|
488
|
+
export type { ProductAgentInteractionDecisionStorage, ProductAgentInteractionDefinition, } from "./interactionManager";
|
|
489
|
+
export type { ProductAgentAuthProjection, ProductAgentComposerAction, ProductAgentEntityQueryData, ProductAgentInteraction, ProductAgentInteractionAction, ProductAgentInteractionPresentation, ProductAgentInteractionScope, ProductAgentInteractionStatus, ProductAgentPromptAction, ProductAgentPromptDecision, ProductAgentPromptDecisionScope, ProductAgentQueryState, ProductAgentQueryStatus, ProductAgentSafeUser, ProductAgentSafeWorkspace, ProductAgentSubmissionGate, ProductAgentWidgetPresentation, } from "./runtimeState";
|
|
490
|
+
export { createProductAgentTaskPageTitleDocument, formatProductAgentTaskPageTitle, ProductAgentTaskPageTitleController, } from "./taskPageTitle";
|
|
491
|
+
export { isProductAgentRuntimeCommand, ProductAgentRemoteRuntimeClient } from "./runtimeClient";
|
|
492
|
+
export type { ProductAgentRuntimeClient, ProductAgentRuntimeClientAdapter, ProductAgentRuntimeCommand, ProductAgentRuntimeCommandResult, } from "./runtimeClient";
|
|
493
|
+
export type PlunoProductAgent = ProductAgentSessionEngine;
|
|
494
|
+
export declare const PlunoProductAgent: Readonly<{
|
|
495
|
+
init: (options: ProductAgentInitOptions) => Promise<ProductAgentSessionEngine>;
|
|
496
|
+
}>;
|
|
497
|
+
export declare function createProductAgentRuntime(options: ProductAgentInitOptions): Promise<ProductAgentSessionEngine>;
|
|
433
498
|
export default PlunoProductAgent;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ProductAgentInteractionAction, ProductAgentInteractionScope, ProductAgentPromptDecision } from "./runtimeState";
|
|
2
|
+
export type ProductAgentInteractionDefinition = {
|
|
3
|
+
key: string;
|
|
4
|
+
category: string;
|
|
5
|
+
scope: ProductAgentInteractionScope;
|
|
6
|
+
allowedActions: readonly ProductAgentInteractionAction[];
|
|
7
|
+
laterDelayMs?: number;
|
|
8
|
+
};
|
|
9
|
+
export type ProductAgentInteractionDecisionStorage = {
|
|
10
|
+
load: () => Promise<ProductAgentPromptDecision[]>;
|
|
11
|
+
save: (decisions: ProductAgentPromptDecision[]) => Promise<void>;
|
|
12
|
+
};
|
|
13
|
+
export declare class ProductAgentInteractionManager {
|
|
14
|
+
private readonly storage;
|
|
15
|
+
private decisions;
|
|
16
|
+
private scheduledEligibility;
|
|
17
|
+
private initialized;
|
|
18
|
+
private actionQueue;
|
|
19
|
+
constructor(storage: ProductAgentInteractionDecisionStorage, initialDecisions?: readonly ProductAgentPromptDecision[] | null);
|
|
20
|
+
initialize(): Promise<void>;
|
|
21
|
+
isEligible(interaction: ProductAgentInteractionDefinition, now?: number): boolean;
|
|
22
|
+
getDecision(interaction: ProductAgentInteractionDefinition): ProductAgentPromptDecision | null;
|
|
23
|
+
getStatus(interaction: ProductAgentInteractionDefinition, now?: number): "presentable" | "scheduled" | "snoozed" | "resolved" | "suppressed";
|
|
24
|
+
scheduleEligibility(interaction: ProductAgentInteractionDefinition, eligibleAt: number): number;
|
|
25
|
+
getNextEligibilityAt(now?: number): number | null;
|
|
26
|
+
act(interaction: ProductAgentInteractionDefinition, action: ProductAgentInteractionAction, options?: {
|
|
27
|
+
snoozeUntil?: Date;
|
|
28
|
+
now?: Date;
|
|
29
|
+
}): Promise<ProductAgentPromptDecision>;
|
|
30
|
+
private applyAction;
|
|
31
|
+
private isDecisionEligible;
|
|
32
|
+
private getNextEligibleAt;
|
|
33
|
+
private getDecisionKey;
|
|
34
|
+
private getExactKey;
|
|
35
|
+
private getCategoryKey;
|
|
36
|
+
}
|
|
37
|
+
export declare function createLocalStorageInteractionDecisionStorage(storage: Storage, storageKey: string): ProductAgentInteractionDecisionStorage;
|
|
38
|
+
export declare function readLocalStorageInteractionDecisions(storage: Storage, storageKey: string): ProductAgentPromptDecision[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function d(s){return{key:s,status:"not_requested",data:null,error:null,requestId:0,updatedAt:null}}class m{constructor(t,e,i=(n,r)=>r){this.loader=e,this.merge=i,this.state=d(t)}loader;merge;state;listeners=new Set;inFlight=null;trailingLoad=null;getState(){return this.state}subscribe(t){return this.listeners.add(t),t(this.state),()=>this.listeners.delete(t)}setKey(t){t!==this.state.key&&(this.state=d(t),this.trailingLoad=null,this.publish())}reset(){this.state=d(this.state.key),this.trailingLoad=null,this.publish()}invalidate(){this.state={...this.state,status:this.state.data===null?"not_requested":"ready",updatedAt:null},this.publish()}load(t="replace",e=null){return this.trailingLoad={mode:t,cursor:e},this.inFlight?this.inFlight:(this.inFlight=this.runLoads().finally(()=>{this.inFlight=null}),this.inFlight)}update(t){this.state={...this.state,data:t(this.state.data)},this.publish()}async runLoads(){for(;this.trailingLoad;){const t=this.trailingLoad;this.trailingLoad=null;const e=this.state.key,i=this.state.requestId+1;this.state={...this.state,status:t.mode==="append"?"loading_more":this.state.data===null?"loading":"refreshing",error:null,requestId:i},this.publish();try{const n=await this.loader({key:e,cursor:t.cursor});if(e!==this.state.key||i!==this.state.requestId)continue;this.state={...this.state,status:"ready",data:this.merge(this.state.data,n,t.mode),error:null,updatedAt:Date.now()},this.publish()}catch(n){if(e!==this.state.key||i!==this.state.requestId)continue;this.state={...this.state,status:"error",error:n instanceof Error?n.message:"The query failed."},this.publish()}}}publish(){for(const t of this.listeners)t(this.state)}}function h(s){const t={},e=[];for(const i of s.entities)t[i.id]||e.push(i.id),t[i.id]=i;return{entitiesById:t,ids:e,nextCursor:s.nextCursor}}function P(s,t,e){if(e==="replace"||s===null)return t;const i={...s.entitiesById,...t.entitiesById},n=[...s.ids];for(const r of t.ids)s.entitiesById[r]||n.push(r);return{entitiesById:i,ids:n,nextCursor:t.nextCursor}}function S(s){return s?s.ids.map(t=>s.entitiesById[t]).filter(t=>!!t):[]}function E(s){return s.visible?s.minimized?{state:"minimized"}:{state:s.open?"visible_open":"visible_closed"}:{state:"hidden"}}function M(s,t){return t==="limit_exceeded"?{allowed:!1,reason:"credits_exhausted",actions:["upgrade","earn_credits"]}:t==="subscription_required"||t==="subscription_inactive"||t==="payment_issue"||t==="subscription_invalid"||t==="payment_required"?{allowed:!1,reason:"payment_issue",actions:["upgrade"]}:s??{allowed:!0,reason:"allowed",actions:[]}}function O(s){if(!s||typeof s!="object")return!1;const t=s.paidCreditFallbackModel;return typeof t=="string"&&t.length>0}function _(s){return s?s.submissionGate?.allowed===!1?{state:"action_required",reason:s.submissionGate.reason}:s.usingPaidCreditFallback===!0?{state:"paid_credit_fallback"}:s.creditLimit!==null&&s.creditLimit>0&&s.creditsRemaining!==null&&s.creditsRemaining>0&&s.creditsRemaining/s.creditLimit<=.2?{state:"low_credits"}:s.creditsUsed!==null?{state:"usage"}:{state:"hidden"}:{state:"hidden"}}function D(s){const t=s.hasDraftMessage||s.hasPreSubmittedAttachment;return s.hasRunningAssistantTurn&&!t?{action:"stop",disabled:!s.canStopRunningTurn}:{action:"send",disabled:!t||!s.canSubmitMessage}}class x{constructor(t,e,i=20){this.loadPage=e,this.limit=i,this.recentQuery=new m(`${t}:recent`,async({cursor:n})=>h(await this.loadPage({cursor:n,limit:this.limit,pinned:!1}).then(r=>({entities:r.sessions,nextCursor:r.nextCursor}))),P),this.pinnedQuery=new m(`${t}:pinned`,async()=>h({entities:await this.loadAllPinned(),nextCursor:null})),this.recentQuery.subscribe(()=>this.publish()),this.pinnedQuery.subscribe(()=>this.publish())}loadPage;limit;recentQuery;pinnedQuery;listeners=new Set;optimisticEntities=new Map;activityOverrides=new Map;pinnedOverrides=new Map;titleOverrides=new Map;refreshSequence=0;completedRefreshSequence=0;activityReconciliationScheduled=!1;getState(){const t=this.recentQuery.getState(),e=this.pinnedQuery.getState(),i=[...g(e.data),...g(t.data)],n=new Map(i.map(o=>[o.id,o])),r=Array.from(n.values()).map(o=>this.applyOverrides(o,this.completedRefreshSequence)),a=Array.from(this.optimisticEntities.values()).filter(o=>!n.has(o.id)).reverse(),l=t.data||e.data||a.length>0?h({entities:[...a,...r],nextCursor:t.data?.nextCursor??null}):null;return{key:t.key.slice(0,-7),status:C(t,e),data:l,error:t.error??e.error,requestId:Math.max(t.requestId,e.requestId),updatedAt:Math.max(t.updatedAt??0,e.updatedAt??0)||null}}subscribe(t){return this.listeners.add(t),t(this.getState()),()=>this.listeners.delete(t)}getEntity(t){return this.getState().data?.entitiesById[t]??null}setKey(t){this.optimisticEntities.clear(),this.activityOverrides.clear(),this.pinnedOverrides.clear(),this.titleOverrides.clear(),this.refreshSequence=0,this.completedRefreshSequence=0,this.activityReconciliationScheduled=!1,this.recentQuery.setKey(`${t}:recent`),this.pinnedQuery.setKey(`${t}:pinned`)}refresh(){const t=++this.refreshSequence,e=Promise.all([this.recentQuery.load("replace"),this.pinnedQuery.load("replace")]).then(()=>{this.completedRefreshSequence=Math.max(this.completedRefreshSequence,t),this.reconcileDurableEntities()});return e.then(()=>{!this.hasUnconfirmedActivityOverride()||this.activityReconciliationScheduled||(this.activityReconciliationScheduled=!0,this.refresh().finally(()=>{this.activityReconciliationScheduled=!1}))}),e}loadMore(t){return this.recentQuery.load("append",t)}addOptimistic(t){this.optimisticEntities.set(t.id,t),this.updateProjection()}removeOptimistic(t){this.optimisticEntities.delete(t)&&this.updateProjection()}acknowledgeOptimistic(t,e){this.optimisticEntities.delete(t),this.optimisticEntities.set(e.id,e),this.updateProjection()}setActivity(t,e){this.activityOverrides.set(t,{isActive:e,confirmAfterRefresh:this.completedRefreshSequence+1,releaseAfterRefresh:this.completedRefreshSequence+2}),this.updateEntity(t,i=>({...i,isActive:e}))}setPinned(t,e){const i={pinned:e,confirmAfterRefresh:Number.POSITIVE_INFINITY};return this.pinnedOverrides.set(t,i),this.updateEntity(t,n=>({...n,isPinned:e})),i}confirmPinned(t,e){this.pinnedOverrides.get(t)===e&&(e.confirmAfterRefresh=this.completedRefreshSequence+1)}rollbackPinned(t,e,i){this.pinnedOverrides.get(t)===e&&(this.pinnedOverrides.delete(t),this.updateEntity(t,n=>({...n,isPinned:i})))}setTitle(t,e){this.titleOverrides.set(t,e),this.updateEntity(t,i=>({...i,customTitle:e}))}confirmTitle(t){this.titleOverrides.delete(t)}reconcileDurableEntities(){const t=[...g(this.pinnedQuery.getState().data),...g(this.recentQuery.getState().data)],e=new Set(t.map(i=>i.id));for(const i of this.optimisticEntities.keys())e.has(i)&&this.optimisticEntities.delete(i);for(const i of t)this.applyOverrides(i,this.completedRefreshSequence);this.publish()}async loadAllPinned(){const t=[];let e=null;do{const i=await this.loadPage({cursor:e,limit:this.limit,pinned:!0});t.push(...i.sessions),e=i.nextCursor}while(e);return t}applyOverrides(t,e){let i=t;const n=this.activityOverrides.get(t.id);n&&(e>=n.confirmAfterRefresh&&t.isActive===n.isActive?this.activityOverrides.delete(t.id):e>=n.releaseAfterRefresh?this.activityOverrides.delete(t.id):i={...i,isActive:n.isActive});const r=this.pinnedOverrides.get(t.id);return r&&(e>=r.confirmAfterRefresh&&t.isPinned===!0===r.pinned?this.pinnedOverrides.delete(t.id):i={...i,isPinned:r.pinned}),this.titleOverrides.has(t.id)&&(i={...i,customTitle:this.titleOverrides.get(t.id)??null}),i}updateProjection(){this.publish()}updateEntity(t,e){const i=this.optimisticEntities.get(t);i&&this.optimisticEntities.set(t,e(i)),this.publish()}hasUnconfirmedActivityOverride(){return Array.from(this.activityOverrides.values()).some(t=>this.completedRefreshSequence<t.releaseAfterRefresh)}publish(){for(const t of this.listeners)t(this.getState())}}function g(s){return s?s.ids.map(t=>s.entitiesById[t]).filter(t=>!!t):[]}function C(s,t){return s.status==="error"||t.status==="error"?"error":s.status==="loading"||t.status==="loading"?"loading":s.status==="refreshing"||t.status==="refreshing"?"refreshing":s.status==="loading_more"?"loading_more":s.status==="ready"||t.status==="ready"?"ready":"not_requested"}class R{constructor(t,e=null){this.storage=t,e&&(this.decisions=new Map(e.filter(v).map(i=>[this.getDecisionKey(i),i])),this.initialized=!0)}storage;decisions=new Map;scheduledEligibility=new Map;initialized=!1;actionQueue=Promise.resolve();async initialize(){if(this.initialized)return;const t=await this.storage.load();this.decisions=new Map(t.filter(v).map(e=>[this.getDecisionKey(e),e])),this.initialized=!0}isEligible(t,e=Date.now()){const i=this.scheduledEligibility.get(this.getExactKey(t));return i!==void 0&&i>e?!1:this.isDecisionEligible(this.decisions.get(this.getExactKey(t)),e)&&this.isDecisionEligible(this.decisions.get(this.getCategoryKey(t)),e)}getDecision(t){return this.decisions.get(this.getExactKey(t))??this.decisions.get(this.getCategoryKey(t))??null}getStatus(t,e=Date.now()){const i=this.scheduledEligibility.get(this.getExactKey(t));if(i!==void 0&&i>e)return"scheduled";const n=this.getDecision(t);return n?n.action==="never"||n.action==="dont_show_again"?"suppressed":n.action==="dismiss"?"resolved":n.nextEligibleAt&&Date.parse(n.nextEligibleAt)>e?"snoozed":"presentable":"presentable"}scheduleEligibility(t,e){const i=this.getExactKey(t),n=this.scheduledEligibility.get(i);return n!==void 0?n:(this.scheduledEligibility.set(i,e),e)}getNextEligibilityAt(t=Date.now()){for(const[i,n]of this.scheduledEligibility)n<=t&&this.scheduledEligibility.delete(i);const e=[...this.scheduledEligibility.values(),...Array.from(this.decisions.values()).map(i=>i.nextEligibleAt?Date.parse(i.nextEligibleAt):Number.NaN).filter(i=>Number.isFinite(i)&&i>t)];return e.length>0?Math.min(...e):null}act(t,e,i={}){const n=this.actionQueue.then(()=>this.applyAction(t,e,i));return this.actionQueue=n.then(()=>{},()=>{}),n}async applyAction(t,e,i){if(!t.allowedActions.includes(e))throw new Error(`Interaction ${t.key} does not allow ${e}.`);if(!I(e))throw new Error(`Interaction action ${e} is not a persistence decision.`);const n=i.now??new Date,r={promptKey:t.key,category:t.category,action:e,scope:t.scope,decidedAt:n.toISOString(),nextEligibleAt:this.getNextEligibleAt(t,e,n,i.snoozeUntil)},a=e==="dont_show_again"?this.getCategoryKey(t):this.getExactKey(t),l=new Map(this.decisions);return l.set(a,r),await this.storage.save([...l.values()]),this.decisions=l,r}isDecisionEligible(t,e){return t?t.action==="dismiss"||t.action==="never"||t.action==="dont_show_again"?!1:!t.nextEligibleAt||Date.parse(t.nextEligibleAt)<=e:!0}getNextEligibleAt(t,e,i,n){if(e==="later")return new Date(i.getTime()+(t.laterDelayMs??3600*1e3)).toISOString();if(e==="snooze"){if(!n||n.getTime()<=i.getTime())throw new Error("Snooze requires a future next-eligible time.");return n.toISOString()}return null}getDecisionKey(t){const e=f(t.scope);return t.action==="dont_show_again"?`${e}:category:${t.category}`:`${e}:interaction:${t.promptKey}`}getExactKey(t){return`${f(t.scope)}:interaction:${t.key}`}getCategoryKey(t){return`${f(t.scope)}:category:${t.category}`}}function L(s,t){return{load:async()=>w(s,t),save:async e=>s.setItem(t,JSON.stringify(e))}}function w(s,t){const e=s.getItem(t);if(!e)return[];const i=JSON.parse(e);return Array.isArray(i)?i.filter(v):[]}function f(s){return`${s.level}:${s.key}`}function I(s){return s==="dismiss"||s==="later"||s==="snooze"||s==="never"||s==="dont_show_again"}function v(s){if(!s||typeof s!="object")return!1;const t=s;return typeof t.promptKey=="string"&&typeof t.category=="string"&&typeof t.decidedAt=="string"&&(t.nextEligibleAt===null||typeof t.nextEligibleAt=="string")&&I(t.action)&&!!(t.scope&&typeof t.scope=="object"&&typeof t.scope.level=="string"&&typeof t.scope.key=="string")}const q={working:"⏳",completed:"✅",failed:"❗",stopped:"⏹️"},k=/^(?:⌛|⏳|✅|❗|⏹️) Pluno(?:: )?/;function T(s,t){if(!t)return p(s);const e=p(s),i=`${q[t]} Pluno`;return e?`${i}: ${e}`:i}class Q{constructor(t){this.titleDocument=t}titleDocument;status=null;baseTitle="";lastAppliedTitle=null;stopObserving=null;liveStatusVersion=0;setStatus(t){this.liveStatusVersion+=1,this.applyStatus(t)}clear(){this.liveStatusVersion+=1,this.applyClear()}async syncStatus(t){const e=this.liveStatusVersion,i=await t();i===void 0||e!==this.liveStatusVersion||(i?this.applyStatus(i):this.applyClear())}applyStatus(t){const e=this.titleDocument.getTitle();e!==this.lastAppliedTitle&&(this.baseTitle=p(e)),this.status=t,this.stopObserving||(this.stopObserving=this.titleDocument.observeTitle(()=>this.handleTitleChanged())),this.applyTitle()}applyClear(){const t=this.titleDocument.getTitle(),e=this.lastAppliedTitle!==null&&t===this.lastAppliedTitle,i=this.lastAppliedTitle===null?p(t):t;this.status=null,this.lastAppliedTitle=null,this.stopObserving?.(),this.stopObserving=null,e?this.titleDocument.setTitle(this.baseTitle):i!==t&&this.titleDocument.setTitle(i)}handleTitleChanged(){!this.status||this.titleDocument.getTitle()===this.lastAppliedTitle||this.applyTitle()}applyTitle(){if(!this.status)return;const t=T(this.baseTitle,this.status);this.lastAppliedTitle=t,this.titleDocument.getTitle()!==t&&this.titleDocument.setTitle(t)}}function $(s){return{getTitle:()=>s.title,setTitle:t=>{s.title=t},observeTitle:t=>{const e=new MutationObserver(t);return e.observe(s.head,{childList:!0,subtree:!0,characterData:!0}),()=>e.disconnect()}}}function p(s){return s.replace(k,"")}function K(s){if(!s||typeof s!="object"||!("type"in s))return!1;const t=s;switch(t.type){case"runtime.connect":case"session.new":case"run.stop":case"run.retry":return!0;case"runtime.warmup":return t.reason==="panel_open"||t.reason==="extension_install"||t.reason==="composer_input";case"runtime.widget_lifecycle":return(t.action==="opened"||t.action==="closed"||t.action==="minimized")&&typeof t.trigger=="string";case"session.load":return typeof t.sessionId=="string"&&t.sessionId.length>0;case"session.list":return(t.cursor===void 0||t.cursor===null||typeof t.cursor=="string")&&(t.limit===void 0||typeof t.limit=="number")&&(t.pinned===void 0||typeof t.pinned=="boolean");case"session.set_model":return typeof t.model=="string";case"session.pin":return typeof t.sessionId=="string"&&typeof t.pinned=="boolean";case"session.rename":return typeof t.sessionId=="string"&&typeof t.title=="string";case"interaction.act":return typeof t.interactionId=="string"&&typeof t.action=="string"&&typeof t.expectedRevision=="number";case"conversation.stage_proactive_suggestion":return typeof t.question=="string"&&typeof t.clientMessageId=="string";case"conversation.stage":return typeof t.content=="string"&&typeof t.clientMessageId=="string"&&(t.attachments===void 0||Array.isArray(t.attachments));case"conversation.fail_staged":return typeof t.clientMessageId=="string"&&typeof t.message=="string";case"conversation.send":return typeof t.content=="string"&&typeof t.clientMessageId=="string"&&(t.attachments===void 0||Array.isArray(t.attachments));default:return!1}}class F{constructor(t,e,i){this.adapter=e,this.state=y(t),this.model=i}adapter;listeners={};attachmentFiles=new Map;sessionHistoryListeners=new Set;interactionListeners=new Set;accountListeners=new Set;state;sessionHistoryState=d("unavailable");model;interactions=[];account=null;stagedProactiveSuggestionClientMessageId=null;operationQueue=Promise.resolve();destroyed=!1;on(t,e){const i=this.listeners[t]??new Set;return i.add(e),this.listeners[t]=i,()=>i.delete(e)}getState(){return y(this.state)}updateProjection(t,e,i,n,r){if(!this.destroyed){if(this.state=y(t),e!==void 0&&(this.model=e),i){this.sessionHistoryState=A(i);for(const a of this.sessionHistoryListeners)a(this.getSessionHistoryState())}if(n){this.interactions=n.map(a=>({...a}));for(const a of this.interactionListeners)a(this.getInteractions())}if(r!==void 0){this.account=r?{...r}:null;for(const a of this.accountListeners)a(this.getAccount())}this.emit("state",this.getState())}}async connect(){await this.dispatch({type:"runtime.connect"})}destroy(){if(!this.destroyed){this.destroyed=!0,this.attachmentFiles.clear(),this.sessionHistoryListeners.clear(),this.interactionListeners.clear(),this.accountListeners.clear();for(const t of Object.values(this.listeners))t?.clear();this.adapter.onDisconnect?.()}}warmup(t="panel_open"){return this.dispatch({type:"runtime.warmup",reason:t}).then(()=>{})}recordWidgetLifecycle(t,e){this.dispatch({type:"runtime.widget_lifecycle",action:t,trigger:e})}sendMessage(t,e={}){const i=t.trim(),n=e.attachments??[];if(!i&&n.length===0)return Promise.resolve(null);const r=e.clientMessageId??(e.proactiveSuggestionQuestion&&this.stagedProactiveSuggestionClientMessageId?this.stagedProactiveSuggestionClientMessageId:crypto.randomUUID()),a=this.state,l={id:`local-${r}`,role:"user",content:i,createdAt:new Date().toISOString(),...n.length>0?{attachments:n}:{},clientMessageId:r};return this.state={...this.state,messages:[...this.state.messages,l],pendingMessageStatus:"sending",turnPhase:this.state.isThinking?this.state.turnPhase:"sending",taskStatus:"working",isRetrying:!1,lastError:null},this.emit("state",this.getState()),this.enqueueOperation(()=>this.sendMessageNow(i,{...e,clientMessageId:r},a))}async sendMessageNow(t,e,i){const n=t,r=e.clientMessageId;let a=e.attachments??[],l=!1;try{if(await this.adapter.dispatch({type:"conversation.stage",content:n,clientMessageId:r,proactiveSuggestionQuestion:e.proactiveSuggestionQuestion,attachments:a.length>0?a:void 0}),l=!0,a.length>0){if(!this.adapter.uploadAttachment)throw new Error("The runtime does not support attachments.");const c=[];for(const u of a){if(u.sandboxPath||u.storageKey){c.push(u);continue}const b=u.id?this.attachmentFiles.get(u.id):void 0;if(!b)throw new Error(`Attachment bytes are unavailable for ${u.name}`);c.push(await this.adapter.uploadAttachment(b,u,{clientMessageId:r}))}a=c}const o=await this.adapter.dispatch({type:"conversation.send",content:n,clientMessageId:r,initiatedBy:e.initiatedBy,invocation:e.invocation,proactiveSuggestionQuestion:e.proactiveSuggestionQuestion,attachments:a.length>0?a:void 0});for(const c of e.attachments??[])c.id&&this.attachmentFiles.delete(c.id);return r===this.stagedProactiveSuggestionClientMessageId&&(this.stagedProactiveSuggestionClientMessageId=null),o?.clientMessageId??r}catch(o){throw this.state={...this.state,messages:this.state.messages.filter(c=>c.id!==`local-${r}`&&c.id!==`optimistic-user-message:${r}`),pendingMessageStatus:i.pendingMessageStatus,turnPhase:i.turnPhase,isThinking:i.isThinking,taskStatus:i.taskStatus},this.emit("state",this.getState()),l&&await this.adapter.dispatch({type:"conversation.fail_staged",clientMessageId:r,message:o instanceof Error?o.message:String(o)}),o}}getModel(){return this.model}setModel(t){return this.dispatch({type:"session.set_model",model:t}).then(()=>{})}retryLastMessage(){return this.dispatch({type:"run.retry"}),!0}createLocalAttachment(t){const e=crypto.randomUUID();return this.attachmentFiles.set(e,t),{id:e,name:t.name||"attachment",mimeType:t.type||"application/octet-stream",sizeBytes:t.size}}stop(){return this.dispatch({type:"run.stop"}).then(()=>{})}startNewSession(t={}){return t.notifyTransport===!1?Promise.resolve():this.dispatch({type:"session.new"}).then(()=>{})}async listSessions(t={}){await this.dispatch({type:"session.list",...t});const e=this.sessionHistoryState.data;return{sessions:S(e),nextCursor:e?.nextCursor??null}}getSessionHistoryState(){return A(this.sessionHistoryState)}subscribeSessionHistory(t){return this.sessionHistoryListeners.add(t),t(this.getSessionHistoryState()),()=>this.sessionHistoryListeners.delete(t)}refreshSessionHistory(){return this.dispatch({type:"session.list",limit:20}).then(()=>{})}loadMoreSessionHistory(){const t=this.sessionHistoryState.data?.nextCursor??null;return t?this.dispatch({type:"session.list",cursor:t,limit:20}).then(()=>{}):Promise.resolve()}setSessionPinned(t,e){return this.dispatch({type:"session.pin",sessionId:t,pinned:e}).then(()=>{})}renameSession(t,e){return this.dispatch({type:"session.rename",sessionId:t,title:e}).then(()=>{})}getInteractions(){return this.interactions.map(t=>({...t}))}subscribeInteractions(t){return this.interactionListeners.add(t),t(this.getInteractions()),()=>this.interactionListeners.delete(t)}actOnInteraction(t,e,i,n={}){return this.dispatch({type:"interaction.act",interactionId:t,action:e,expectedRevision:i,...n}).then(()=>{})}getAccount(){return this.account?{...this.account}:null}subscribeAccount(t){return this.accountListeners.add(t),t(this.getAccount()),()=>this.accountListeners.delete(t)}refreshAccount(){return Promise.resolve()}loadSession(t){return this.dispatch({type:"session.load",sessionId:t}).then(()=>{})}stageProactiveSuggestionQuestion(t){const e=t.trim();if(!e)return Promise.resolve();const i=this.stagedProactiveSuggestionClientMessageId??crypto.randomUUID();return this.stagedProactiveSuggestionClientMessageId=i,this.dispatch({type:"conversation.stage_proactive_suggestion",question:e,clientMessageId:i}).then(()=>{})}dispatch(t){return this.enqueueOperation(()=>this.adapter.dispatch(t))}enqueueOperation(t){const e=this.operationQueue.then(t);return this.operationQueue=e.then(()=>{},()=>{}),e}emit(t,e){const i=this.listeners[t];for(const n of i??[])n(e)}}function y(s){return{...s,starterPrompts:[...s.starterPrompts],appearance:s.appearance?{...s.appearance}:null,messages:s.messages.map(t=>{const e={...t,attachments:t.attachments?.map(r=>({...r}))},i=t.assistantDraftItemId,n=t.clientMessageId;return i&&Object.defineProperty(e,"assistantDraftItemId",{value:i,enumerable:!1}),n&&Object.defineProperty(e,"clientMessageId",{value:n,enumerable:!1}),e}),activeScheduledFollowUps:s.activeScheduledFollowUps?.map(t=>({...t}))??null}}function A(s){return{...s,data:s.data?h({entities:S(s.data).map(t=>({...t})),nextCursor:s.data.nextCursor}):null}}exports.ProductAgentInteractionManager=R;exports.ProductAgentQueryController=m;exports.ProductAgentRemoteRuntimeClient=F;exports.ProductAgentSessionHistoryManager=x;exports.ProductAgentTaskPageTitleController=Q;exports.createLocalStorageInteractionDecisionStorage=L;exports.createProductAgentQueryState=d;exports.createProductAgentTaskPageTitleDocument=$;exports.formatProductAgentTaskPageTitle=T;exports.hasProductAgentPaidCreditFallback=O;exports.isProductAgentRuntimeCommand=K;exports.mergeProductAgentEntityPages=P;exports.normalizeProductAgentEntityPage=h;exports.readLocalStorageInteractionDecisions=w;exports.reconcileProductAgentSubmissionGate=M;exports.resolveProductAgentBillingPresentation=_;exports.resolveProductAgentComposerAction=D;exports.resolveProductAgentWidgetPresentation=E;exports.selectProductAgentQueryEntities=S;
|