@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.
@@ -0,0 +1,806 @@
1
+ function h(s) {
2
+ return {
3
+ key: s,
4
+ status: "not_requested",
5
+ data: null,
6
+ error: null,
7
+ requestId: 0,
8
+ updatedAt: null
9
+ };
10
+ }
11
+ class b {
12
+ constructor(t, e, i = (n, r) => r) {
13
+ this.loader = e, this.merge = i, this.state = h(t);
14
+ }
15
+ loader;
16
+ merge;
17
+ state;
18
+ listeners = /* @__PURE__ */ new Set();
19
+ inFlight = null;
20
+ trailingLoad = null;
21
+ getState() {
22
+ return this.state;
23
+ }
24
+ subscribe(t) {
25
+ return this.listeners.add(t), t(this.state), () => this.listeners.delete(t);
26
+ }
27
+ setKey(t) {
28
+ t !== this.state.key && (this.state = h(t), this.trailingLoad = null, this.publish());
29
+ }
30
+ reset() {
31
+ this.state = h(this.state.key), this.trailingLoad = null, this.publish();
32
+ }
33
+ invalidate() {
34
+ this.state = {
35
+ ...this.state,
36
+ status: this.state.data === null ? "not_requested" : "ready",
37
+ updatedAt: null
38
+ }, this.publish();
39
+ }
40
+ load(t = "replace", e = null) {
41
+ return this.trailingLoad = { mode: t, cursor: e }, this.inFlight ? this.inFlight : (this.inFlight = this.runLoads().finally(() => {
42
+ this.inFlight = null;
43
+ }), this.inFlight);
44
+ }
45
+ update(t) {
46
+ this.state = {
47
+ ...this.state,
48
+ data: t(this.state.data)
49
+ }, this.publish();
50
+ }
51
+ async runLoads() {
52
+ for (; this.trailingLoad; ) {
53
+ const t = this.trailingLoad;
54
+ this.trailingLoad = null;
55
+ const e = this.state.key, i = this.state.requestId + 1;
56
+ this.state = {
57
+ ...this.state,
58
+ status: t.mode === "append" ? "loading_more" : this.state.data === null ? "loading" : "refreshing",
59
+ error: null,
60
+ requestId: i
61
+ }, this.publish();
62
+ try {
63
+ const n = await this.loader({ key: e, cursor: t.cursor });
64
+ if (e !== this.state.key || i !== this.state.requestId) continue;
65
+ this.state = {
66
+ ...this.state,
67
+ status: "ready",
68
+ data: this.merge(this.state.data, n, t.mode),
69
+ error: null,
70
+ updatedAt: Date.now()
71
+ }, this.publish();
72
+ } catch (n) {
73
+ if (e !== this.state.key || i !== this.state.requestId) continue;
74
+ this.state = {
75
+ ...this.state,
76
+ status: "error",
77
+ error: n instanceof Error ? n.message : "The query failed."
78
+ }, this.publish();
79
+ }
80
+ }
81
+ }
82
+ publish() {
83
+ for (const t of this.listeners) t(this.state);
84
+ }
85
+ }
86
+ function p(s) {
87
+ const t = {}, e = [];
88
+ for (const i of s.entities)
89
+ t[i.id] || e.push(i.id), t[i.id] = i;
90
+ return {
91
+ entitiesById: t,
92
+ ids: e,
93
+ nextCursor: s.nextCursor
94
+ };
95
+ }
96
+ function P(s, t, e) {
97
+ if (e === "replace" || s === null) return t;
98
+ const i = { ...s.entitiesById, ...t.entitiesById }, n = [...s.ids];
99
+ for (const r of t.ids)
100
+ s.entitiesById[r] || n.push(r);
101
+ return { entitiesById: i, ids: n, nextCursor: t.nextCursor };
102
+ }
103
+ function A(s) {
104
+ return s ? s.ids.map((t) => s.entitiesById[t]).filter((t) => !!t) : [];
105
+ }
106
+ function _(s) {
107
+ return s.visible ? s.minimized ? { state: "minimized" } : { state: s.open ? "visible_open" : "visible_closed" } : { state: "hidden" };
108
+ }
109
+ function x(s, t) {
110
+ 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: [] };
111
+ }
112
+ function D(s) {
113
+ if (!s || typeof s != "object") return !1;
114
+ const t = s.paidCreditFallbackModel;
115
+ return typeof t == "string" && t.length > 0;
116
+ }
117
+ function C(s) {
118
+ 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 <= 0.2 ? { state: "low_credits" } : s.creditsUsed !== null ? { state: "usage" } : { state: "hidden" } : { state: "hidden" };
119
+ }
120
+ function R(s) {
121
+ const t = s.hasDraftMessage || s.hasPreSubmittedAttachment;
122
+ return s.hasRunningAssistantTurn && !t ? {
123
+ action: "stop",
124
+ disabled: !s.canStopRunningTurn
125
+ } : {
126
+ action: "send",
127
+ disabled: !t || !s.canSubmitMessage
128
+ };
129
+ }
130
+ class q {
131
+ constructor(t, e, i = 20) {
132
+ this.loadPage = e, this.limit = i, this.recentQuery = new b(
133
+ `${t}:recent`,
134
+ async ({ cursor: n }) => p(
135
+ await this.loadPage({ cursor: n, limit: this.limit, pinned: !1 }).then((r) => ({
136
+ entities: r.sessions,
137
+ nextCursor: r.nextCursor
138
+ }))
139
+ ),
140
+ P
141
+ ), this.pinnedQuery = new b(
142
+ `${t}:pinned`,
143
+ async () => p({
144
+ entities: await this.loadAllPinned(),
145
+ nextCursor: null
146
+ })
147
+ ), this.recentQuery.subscribe(() => this.publish()), this.pinnedQuery.subscribe(() => this.publish());
148
+ }
149
+ loadPage;
150
+ limit;
151
+ recentQuery;
152
+ pinnedQuery;
153
+ listeners = /* @__PURE__ */ new Set();
154
+ optimisticEntities = /* @__PURE__ */ new Map();
155
+ activityOverrides = /* @__PURE__ */ new Map();
156
+ pinnedOverrides = /* @__PURE__ */ new Map();
157
+ titleOverrides = /* @__PURE__ */ new Map();
158
+ refreshSequence = 0;
159
+ completedRefreshSequence = 0;
160
+ activityReconciliationScheduled = !1;
161
+ getState() {
162
+ const t = this.recentQuery.getState(), e = this.pinnedQuery.getState(), i = [
163
+ ...d(e.data),
164
+ ...d(t.data)
165
+ ], n = new Map(i.map((o) => [o.id, o])), r = Array.from(n.values()).map(
166
+ (o) => this.applyOverrides(o, this.completedRefreshSequence)
167
+ ), a = Array.from(this.optimisticEntities.values()).filter((o) => !n.has(o.id)).reverse(), l = t.data || e.data || a.length > 0 ? p({
168
+ entities: [...a, ...r],
169
+ nextCursor: t.data?.nextCursor ?? null
170
+ }) : null;
171
+ return {
172
+ key: t.key.slice(0, -7),
173
+ status: I(t, e),
174
+ data: l,
175
+ error: t.error ?? e.error,
176
+ requestId: Math.max(t.requestId, e.requestId),
177
+ updatedAt: Math.max(t.updatedAt ?? 0, e.updatedAt ?? 0) || null
178
+ };
179
+ }
180
+ subscribe(t) {
181
+ return this.listeners.add(t), t(this.getState()), () => this.listeners.delete(t);
182
+ }
183
+ getEntity(t) {
184
+ return this.getState().data?.entitiesById[t] ?? null;
185
+ }
186
+ setKey(t) {
187
+ 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`);
188
+ }
189
+ refresh() {
190
+ const t = ++this.refreshSequence, e = Promise.all([
191
+ this.recentQuery.load("replace"),
192
+ this.pinnedQuery.load("replace")
193
+ ]).then(() => {
194
+ this.completedRefreshSequence = Math.max(this.completedRefreshSequence, t), this.reconcileDurableEntities();
195
+ });
196
+ return e.then(() => {
197
+ !this.hasUnconfirmedActivityOverride() || this.activityReconciliationScheduled || (this.activityReconciliationScheduled = !0, this.refresh().finally(() => {
198
+ this.activityReconciliationScheduled = !1;
199
+ }));
200
+ }), e;
201
+ }
202
+ loadMore(t) {
203
+ return this.recentQuery.load("append", t);
204
+ }
205
+ addOptimistic(t) {
206
+ this.optimisticEntities.set(t.id, t), this.updateProjection();
207
+ }
208
+ removeOptimistic(t) {
209
+ this.optimisticEntities.delete(t) && this.updateProjection();
210
+ }
211
+ acknowledgeOptimistic(t, e) {
212
+ this.optimisticEntities.delete(t), this.optimisticEntities.set(e.id, e), this.updateProjection();
213
+ }
214
+ setActivity(t, e) {
215
+ this.activityOverrides.set(t, {
216
+ isActive: e,
217
+ confirmAfterRefresh: this.completedRefreshSequence + 1,
218
+ releaseAfterRefresh: this.completedRefreshSequence + 2
219
+ }), this.updateEntity(t, (i) => ({ ...i, isActive: e }));
220
+ }
221
+ setPinned(t, e) {
222
+ const i = { pinned: e, confirmAfterRefresh: Number.POSITIVE_INFINITY };
223
+ return this.pinnedOverrides.set(t, i), this.updateEntity(t, (n) => ({ ...n, isPinned: e })), i;
224
+ }
225
+ confirmPinned(t, e) {
226
+ this.pinnedOverrides.get(t) === e && (e.confirmAfterRefresh = this.completedRefreshSequence + 1);
227
+ }
228
+ rollbackPinned(t, e, i) {
229
+ this.pinnedOverrides.get(t) === e && (this.pinnedOverrides.delete(t), this.updateEntity(t, (n) => ({ ...n, isPinned: i })));
230
+ }
231
+ setTitle(t, e) {
232
+ this.titleOverrides.set(t, e), this.updateEntity(t, (i) => ({ ...i, customTitle: e }));
233
+ }
234
+ confirmTitle(t) {
235
+ this.titleOverrides.delete(t);
236
+ }
237
+ reconcileDurableEntities() {
238
+ const t = [
239
+ ...d(this.pinnedQuery.getState().data),
240
+ ...d(this.recentQuery.getState().data)
241
+ ], e = new Set(t.map((i) => i.id));
242
+ for (const i of this.optimisticEntities.keys())
243
+ e.has(i) && this.optimisticEntities.delete(i);
244
+ for (const i of t) this.applyOverrides(i, this.completedRefreshSequence);
245
+ this.publish();
246
+ }
247
+ async loadAllPinned() {
248
+ const t = [];
249
+ let e = null;
250
+ do {
251
+ const i = await this.loadPage({ cursor: e, limit: this.limit, pinned: !0 });
252
+ t.push(...i.sessions), e = i.nextCursor;
253
+ } while (e);
254
+ return t;
255
+ }
256
+ applyOverrides(t, e) {
257
+ let i = t;
258
+ const n = this.activityOverrides.get(t.id);
259
+ 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 });
260
+ const r = this.pinnedOverrides.get(t.id);
261
+ 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;
262
+ }
263
+ updateProjection() {
264
+ this.publish();
265
+ }
266
+ updateEntity(t, e) {
267
+ const i = this.optimisticEntities.get(t);
268
+ i && this.optimisticEntities.set(t, e(i)), this.publish();
269
+ }
270
+ hasUnconfirmedActivityOverride() {
271
+ return Array.from(this.activityOverrides.values()).some(
272
+ (t) => this.completedRefreshSequence < t.releaseAfterRefresh
273
+ );
274
+ }
275
+ publish() {
276
+ for (const t of this.listeners) t(this.getState());
277
+ }
278
+ }
279
+ function d(s) {
280
+ return s ? s.ids.map((t) => s.entitiesById[t]).filter((t) => !!t) : [];
281
+ }
282
+ function I(s, t) {
283
+ 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";
284
+ }
285
+ class L {
286
+ constructor(t, e = null) {
287
+ this.storage = t, e && (this.decisions = new Map(
288
+ e.filter(m).map((i) => [this.getDecisionKey(i), i])
289
+ ), this.initialized = !0);
290
+ }
291
+ storage;
292
+ decisions = /* @__PURE__ */ new Map();
293
+ scheduledEligibility = /* @__PURE__ */ new Map();
294
+ initialized = !1;
295
+ actionQueue = Promise.resolve();
296
+ async initialize() {
297
+ if (this.initialized) return;
298
+ const t = await this.storage.load();
299
+ this.decisions = new Map(
300
+ t.filter(m).map((e) => [this.getDecisionKey(e), e])
301
+ ), this.initialized = !0;
302
+ }
303
+ isEligible(t, e = Date.now()) {
304
+ const i = this.scheduledEligibility.get(this.getExactKey(t));
305
+ 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);
306
+ }
307
+ getDecision(t) {
308
+ return this.decisions.get(this.getExactKey(t)) ?? this.decisions.get(this.getCategoryKey(t)) ?? null;
309
+ }
310
+ getStatus(t, e = Date.now()) {
311
+ const i = this.scheduledEligibility.get(this.getExactKey(t));
312
+ if (i !== void 0 && i > e) return "scheduled";
313
+ const n = this.getDecision(t);
314
+ 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";
315
+ }
316
+ scheduleEligibility(t, e) {
317
+ const i = this.getExactKey(t), n = this.scheduledEligibility.get(i);
318
+ return n !== void 0 ? n : (this.scheduledEligibility.set(i, e), e);
319
+ }
320
+ getNextEligibilityAt(t = Date.now()) {
321
+ for (const [i, n] of this.scheduledEligibility)
322
+ n <= t && this.scheduledEligibility.delete(i);
323
+ const e = [
324
+ ...this.scheduledEligibility.values(),
325
+ ...Array.from(this.decisions.values()).map((i) => i.nextEligibleAt ? Date.parse(i.nextEligibleAt) : Number.NaN).filter((i) => Number.isFinite(i) && i > t)
326
+ ];
327
+ return e.length > 0 ? Math.min(...e) : null;
328
+ }
329
+ act(t, e, i = {}) {
330
+ const n = this.actionQueue.then(() => this.applyAction(t, e, i));
331
+ return this.actionQueue = n.then(() => {
332
+ }, () => {
333
+ }), n;
334
+ }
335
+ async applyAction(t, e, i) {
336
+ if (!t.allowedActions.includes(e))
337
+ throw new Error(`Interaction ${t.key} does not allow ${e}.`);
338
+ if (!w(e))
339
+ throw new Error(`Interaction action ${e} is not a persistence decision.`);
340
+ const n = i.now ?? /* @__PURE__ */ new Date(), r = {
341
+ promptKey: t.key,
342
+ category: t.category,
343
+ action: e,
344
+ scope: t.scope,
345
+ decidedAt: n.toISOString(),
346
+ nextEligibleAt: this.getNextEligibleAt(t, e, n, i.snoozeUntil)
347
+ }, a = e === "dont_show_again" ? this.getCategoryKey(t) : this.getExactKey(t), l = new Map(this.decisions);
348
+ return l.set(a, r), await this.storage.save([...l.values()]), this.decisions = l, r;
349
+ }
350
+ isDecisionEligible(t, e) {
351
+ return t ? t.action === "dismiss" || t.action === "never" || t.action === "dont_show_again" ? !1 : !t.nextEligibleAt || Date.parse(t.nextEligibleAt) <= e : !0;
352
+ }
353
+ getNextEligibleAt(t, e, i, n) {
354
+ if (e === "later")
355
+ return new Date(i.getTime() + (t.laterDelayMs ?? 3600 * 1e3)).toISOString();
356
+ if (e === "snooze") {
357
+ if (!n || n.getTime() <= i.getTime())
358
+ throw new Error("Snooze requires a future next-eligible time.");
359
+ return n.toISOString();
360
+ }
361
+ return null;
362
+ }
363
+ getDecisionKey(t) {
364
+ const e = f(t.scope);
365
+ return t.action === "dont_show_again" ? `${e}:category:${t.category}` : `${e}:interaction:${t.promptKey}`;
366
+ }
367
+ getExactKey(t) {
368
+ return `${f(t.scope)}:interaction:${t.key}`;
369
+ }
370
+ getCategoryKey(t) {
371
+ return `${f(t.scope)}:category:${t.category}`;
372
+ }
373
+ }
374
+ function Q(s, t) {
375
+ return {
376
+ load: async () => E(s, t),
377
+ save: async (e) => s.setItem(t, JSON.stringify(e))
378
+ };
379
+ }
380
+ function E(s, t) {
381
+ const e = s.getItem(t);
382
+ if (!e) return [];
383
+ const i = JSON.parse(e);
384
+ return Array.isArray(i) ? i.filter(m) : [];
385
+ }
386
+ function f(s) {
387
+ return `${s.level}:${s.key}`;
388
+ }
389
+ function w(s) {
390
+ return s === "dismiss" || s === "later" || s === "snooze" || s === "never" || s === "dont_show_again";
391
+ }
392
+ function m(s) {
393
+ if (!s || typeof s != "object") return !1;
394
+ const t = s;
395
+ return typeof t.promptKey == "string" && typeof t.category == "string" && typeof t.decidedAt == "string" && (t.nextEligibleAt === null || typeof t.nextEligibleAt == "string") && w(t.action) && !!(t.scope && typeof t.scope == "object" && typeof t.scope.level == "string" && typeof t.scope.key == "string");
396
+ }
397
+ const T = {
398
+ working: "⏳",
399
+ completed: "✅",
400
+ failed: "❗",
401
+ stopped: "⏹️"
402
+ }, M = /^(?:⌛|⏳|✅|❗|⏹️) Pluno(?:: )?/;
403
+ function O(s, t) {
404
+ if (!t) return g(s);
405
+ const e = g(s), i = `${T[t]} Pluno`;
406
+ return e ? `${i}: ${e}` : i;
407
+ }
408
+ class k {
409
+ constructor(t) {
410
+ this.titleDocument = t;
411
+ }
412
+ titleDocument;
413
+ status = null;
414
+ baseTitle = "";
415
+ lastAppliedTitle = null;
416
+ stopObserving = null;
417
+ liveStatusVersion = 0;
418
+ setStatus(t) {
419
+ this.liveStatusVersion += 1, this.applyStatus(t);
420
+ }
421
+ clear() {
422
+ this.liveStatusVersion += 1, this.applyClear();
423
+ }
424
+ async syncStatus(t) {
425
+ const e = this.liveStatusVersion, i = await t();
426
+ i === void 0 || e !== this.liveStatusVersion || (i ? this.applyStatus(i) : this.applyClear());
427
+ }
428
+ applyStatus(t) {
429
+ const e = this.titleDocument.getTitle();
430
+ e !== this.lastAppliedTitle && (this.baseTitle = g(e)), this.status = t, this.stopObserving || (this.stopObserving = this.titleDocument.observeTitle(() => this.handleTitleChanged())), this.applyTitle();
431
+ }
432
+ applyClear() {
433
+ const t = this.titleDocument.getTitle(), e = this.lastAppliedTitle !== null && t === this.lastAppliedTitle, i = this.lastAppliedTitle === null ? g(t) : t;
434
+ this.status = null, this.lastAppliedTitle = null, this.stopObserving?.(), this.stopObserving = null, e ? this.titleDocument.setTitle(this.baseTitle) : i !== t && this.titleDocument.setTitle(i);
435
+ }
436
+ handleTitleChanged() {
437
+ !this.status || this.titleDocument.getTitle() === this.lastAppliedTitle || this.applyTitle();
438
+ }
439
+ applyTitle() {
440
+ if (!this.status)
441
+ return;
442
+ const t = O(this.baseTitle, this.status);
443
+ this.lastAppliedTitle = t, this.titleDocument.getTitle() !== t && this.titleDocument.setTitle(t);
444
+ }
445
+ }
446
+ function $(s) {
447
+ return {
448
+ getTitle: () => s.title,
449
+ setTitle: (t) => {
450
+ s.title = t;
451
+ },
452
+ observeTitle: (t) => {
453
+ const e = new MutationObserver(t);
454
+ return e.observe(s.head, {
455
+ childList: !0,
456
+ subtree: !0,
457
+ characterData: !0
458
+ }), () => e.disconnect();
459
+ }
460
+ };
461
+ }
462
+ function g(s) {
463
+ return s.replace(M, "");
464
+ }
465
+ function K(s) {
466
+ if (!s || typeof s != "object" || !("type" in s)) return !1;
467
+ const t = s;
468
+ switch (t.type) {
469
+ case "runtime.connect":
470
+ case "session.new":
471
+ case "run.stop":
472
+ case "run.retry":
473
+ return !0;
474
+ case "runtime.warmup":
475
+ return t.reason === "panel_open" || t.reason === "extension_install" || t.reason === "composer_input";
476
+ case "runtime.widget_lifecycle":
477
+ return (t.action === "opened" || t.action === "closed" || t.action === "minimized") && typeof t.trigger == "string";
478
+ case "session.load":
479
+ return typeof t.sessionId == "string" && t.sessionId.length > 0;
480
+ case "session.list":
481
+ 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");
482
+ case "session.set_model":
483
+ return typeof t.model == "string";
484
+ case "session.pin":
485
+ return typeof t.sessionId == "string" && typeof t.pinned == "boolean";
486
+ case "session.rename":
487
+ return typeof t.sessionId == "string" && typeof t.title == "string";
488
+ case "interaction.act":
489
+ return typeof t.interactionId == "string" && typeof t.action == "string" && typeof t.expectedRevision == "number";
490
+ case "conversation.stage_proactive_suggestion":
491
+ return typeof t.question == "string" && typeof t.clientMessageId == "string";
492
+ case "conversation.stage":
493
+ return typeof t.content == "string" && typeof t.clientMessageId == "string" && (t.attachments === void 0 || Array.isArray(t.attachments));
494
+ case "conversation.fail_staged":
495
+ return typeof t.clientMessageId == "string" && typeof t.message == "string";
496
+ case "conversation.send":
497
+ return typeof t.content == "string" && typeof t.clientMessageId == "string" && (t.attachments === void 0 || Array.isArray(t.attachments));
498
+ default:
499
+ return !1;
500
+ }
501
+ }
502
+ class F {
503
+ constructor(t, e, i) {
504
+ this.adapter = e, this.state = y(t), this.model = i;
505
+ }
506
+ adapter;
507
+ listeners = {};
508
+ attachmentFiles = /* @__PURE__ */ new Map();
509
+ sessionHistoryListeners = /* @__PURE__ */ new Set();
510
+ interactionListeners = /* @__PURE__ */ new Set();
511
+ accountListeners = /* @__PURE__ */ new Set();
512
+ state;
513
+ sessionHistoryState = h("unavailable");
514
+ model;
515
+ interactions = [];
516
+ account = null;
517
+ stagedProactiveSuggestionClientMessageId = null;
518
+ operationQueue = Promise.resolve();
519
+ destroyed = !1;
520
+ on(t, e) {
521
+ const i = this.listeners[t] ?? /* @__PURE__ */ new Set();
522
+ return i.add(e), this.listeners[t] = i, () => i.delete(e);
523
+ }
524
+ getState() {
525
+ return y(this.state);
526
+ }
527
+ updateProjection(t, e, i, n, r) {
528
+ if (!this.destroyed) {
529
+ if (this.state = y(t), e !== void 0 && (this.model = e), i) {
530
+ this.sessionHistoryState = S(i);
531
+ for (const a of this.sessionHistoryListeners)
532
+ a(this.getSessionHistoryState());
533
+ }
534
+ if (n) {
535
+ this.interactions = n.map((a) => ({ ...a }));
536
+ for (const a of this.interactionListeners) a(this.getInteractions());
537
+ }
538
+ if (r !== void 0) {
539
+ this.account = r ? { ...r } : null;
540
+ for (const a of this.accountListeners) a(this.getAccount());
541
+ }
542
+ this.emit("state", this.getState());
543
+ }
544
+ }
545
+ async connect() {
546
+ await this.dispatch({ type: "runtime.connect" });
547
+ }
548
+ destroy() {
549
+ if (!this.destroyed) {
550
+ this.destroyed = !0, this.attachmentFiles.clear(), this.sessionHistoryListeners.clear(), this.interactionListeners.clear(), this.accountListeners.clear();
551
+ for (const t of Object.values(this.listeners)) t?.clear();
552
+ this.adapter.onDisconnect?.();
553
+ }
554
+ }
555
+ warmup(t = "panel_open") {
556
+ return this.dispatch({ type: "runtime.warmup", reason: t }).then(() => {
557
+ });
558
+ }
559
+ recordWidgetLifecycle(t, e) {
560
+ this.dispatch({ type: "runtime.widget_lifecycle", action: t, trigger: e });
561
+ }
562
+ sendMessage(t, e = {}) {
563
+ const i = t.trim(), n = e.attachments ?? [];
564
+ if (!i && n.length === 0) return Promise.resolve(null);
565
+ const r = e.clientMessageId ?? (e.proactiveSuggestionQuestion && this.stagedProactiveSuggestionClientMessageId ? this.stagedProactiveSuggestionClientMessageId : crypto.randomUUID()), a = this.state, l = {
566
+ id: `local-${r}`,
567
+ role: "user",
568
+ content: i,
569
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
570
+ ...n.length > 0 ? { attachments: n } : {},
571
+ clientMessageId: r
572
+ };
573
+ return this.state = {
574
+ ...this.state,
575
+ messages: [...this.state.messages, l],
576
+ pendingMessageStatus: "sending",
577
+ turnPhase: this.state.isThinking ? this.state.turnPhase : "sending",
578
+ taskStatus: "working",
579
+ isRetrying: !1,
580
+ lastError: null
581
+ }, this.emit("state", this.getState()), this.enqueueOperation(() => this.sendMessageNow(
582
+ i,
583
+ { ...e, clientMessageId: r },
584
+ a
585
+ ));
586
+ }
587
+ async sendMessageNow(t, e, i) {
588
+ const n = t, r = e.clientMessageId;
589
+ let a = e.attachments ?? [], l = !1;
590
+ try {
591
+ if (await this.adapter.dispatch({
592
+ type: "conversation.stage",
593
+ content: n,
594
+ clientMessageId: r,
595
+ proactiveSuggestionQuestion: e.proactiveSuggestionQuestion,
596
+ attachments: a.length > 0 ? a : void 0
597
+ }), l = !0, a.length > 0) {
598
+ if (!this.adapter.uploadAttachment)
599
+ throw new Error("The runtime does not support attachments.");
600
+ const c = [];
601
+ for (const u of a) {
602
+ if (u.sandboxPath || u.storageKey) {
603
+ c.push(u);
604
+ continue;
605
+ }
606
+ const v = u.id ? this.attachmentFiles.get(u.id) : void 0;
607
+ if (!v) throw new Error(`Attachment bytes are unavailable for ${u.name}`);
608
+ c.push(await this.adapter.uploadAttachment(v, u, { clientMessageId: r }));
609
+ }
610
+ a = c;
611
+ }
612
+ const o = await this.adapter.dispatch({
613
+ type: "conversation.send",
614
+ content: n,
615
+ clientMessageId: r,
616
+ initiatedBy: e.initiatedBy,
617
+ invocation: e.invocation,
618
+ proactiveSuggestionQuestion: e.proactiveSuggestionQuestion,
619
+ attachments: a.length > 0 ? a : void 0
620
+ });
621
+ for (const c of e.attachments ?? [])
622
+ c.id && this.attachmentFiles.delete(c.id);
623
+ return r === this.stagedProactiveSuggestionClientMessageId && (this.stagedProactiveSuggestionClientMessageId = null), o?.clientMessageId ?? r;
624
+ } catch (o) {
625
+ throw this.state = {
626
+ ...this.state,
627
+ messages: this.state.messages.filter(
628
+ (c) => c.id !== `local-${r}` && c.id !== `optimistic-user-message:${r}`
629
+ ),
630
+ pendingMessageStatus: i.pendingMessageStatus,
631
+ turnPhase: i.turnPhase,
632
+ isThinking: i.isThinking,
633
+ taskStatus: i.taskStatus
634
+ }, this.emit("state", this.getState()), l && await this.adapter.dispatch({
635
+ type: "conversation.fail_staged",
636
+ clientMessageId: r,
637
+ message: o instanceof Error ? o.message : String(o)
638
+ }), o;
639
+ }
640
+ }
641
+ getModel() {
642
+ return this.model;
643
+ }
644
+ setModel(t) {
645
+ return this.dispatch({ type: "session.set_model", model: t }).then(() => {
646
+ });
647
+ }
648
+ retryLastMessage() {
649
+ return this.dispatch({ type: "run.retry" }), !0;
650
+ }
651
+ createLocalAttachment(t) {
652
+ const e = crypto.randomUUID();
653
+ return this.attachmentFiles.set(e, t), {
654
+ id: e,
655
+ name: t.name || "attachment",
656
+ mimeType: t.type || "application/octet-stream",
657
+ sizeBytes: t.size
658
+ };
659
+ }
660
+ stop() {
661
+ return this.dispatch({ type: "run.stop" }).then(() => {
662
+ });
663
+ }
664
+ startNewSession(t = {}) {
665
+ return t.notifyTransport === !1 ? Promise.resolve() : this.dispatch({ type: "session.new" }).then(() => {
666
+ });
667
+ }
668
+ async listSessions(t = {}) {
669
+ await this.dispatch({ type: "session.list", ...t });
670
+ const e = this.sessionHistoryState.data;
671
+ return {
672
+ sessions: A(e),
673
+ nextCursor: e?.nextCursor ?? null
674
+ };
675
+ }
676
+ getSessionHistoryState() {
677
+ return S(this.sessionHistoryState);
678
+ }
679
+ subscribeSessionHistory(t) {
680
+ return this.sessionHistoryListeners.add(t), t(this.getSessionHistoryState()), () => this.sessionHistoryListeners.delete(t);
681
+ }
682
+ refreshSessionHistory() {
683
+ return this.dispatch({ type: "session.list", limit: 20 }).then(() => {
684
+ });
685
+ }
686
+ loadMoreSessionHistory() {
687
+ const t = this.sessionHistoryState.data?.nextCursor ?? null;
688
+ return t ? this.dispatch({ type: "session.list", cursor: t, limit: 20 }).then(() => {
689
+ }) : Promise.resolve();
690
+ }
691
+ setSessionPinned(t, e) {
692
+ return this.dispatch({ type: "session.pin", sessionId: t, pinned: e }).then(() => {
693
+ });
694
+ }
695
+ renameSession(t, e) {
696
+ return this.dispatch({ type: "session.rename", sessionId: t, title: e }).then(() => {
697
+ });
698
+ }
699
+ getInteractions() {
700
+ return this.interactions.map((t) => ({ ...t }));
701
+ }
702
+ subscribeInteractions(t) {
703
+ return this.interactionListeners.add(t), t(this.getInteractions()), () => this.interactionListeners.delete(t);
704
+ }
705
+ actOnInteraction(t, e, i, n = {}) {
706
+ return this.dispatch({
707
+ type: "interaction.act",
708
+ interactionId: t,
709
+ action: e,
710
+ expectedRevision: i,
711
+ ...n
712
+ }).then(() => {
713
+ });
714
+ }
715
+ getAccount() {
716
+ return this.account ? { ...this.account } : null;
717
+ }
718
+ subscribeAccount(t) {
719
+ return this.accountListeners.add(t), t(this.getAccount()), () => this.accountListeners.delete(t);
720
+ }
721
+ refreshAccount() {
722
+ return Promise.resolve();
723
+ }
724
+ loadSession(t) {
725
+ return this.dispatch({ type: "session.load", sessionId: t }).then(() => {
726
+ });
727
+ }
728
+ stageProactiveSuggestionQuestion(t) {
729
+ const e = t.trim();
730
+ if (!e) return Promise.resolve();
731
+ const i = this.stagedProactiveSuggestionClientMessageId ?? crypto.randomUUID();
732
+ return this.stagedProactiveSuggestionClientMessageId = i, this.dispatch({
733
+ type: "conversation.stage_proactive_suggestion",
734
+ question: e,
735
+ clientMessageId: i
736
+ }).then(() => {
737
+ });
738
+ }
739
+ dispatch(t) {
740
+ return this.enqueueOperation(() => this.adapter.dispatch(t));
741
+ }
742
+ enqueueOperation(t) {
743
+ const e = this.operationQueue.then(t);
744
+ return this.operationQueue = e.then(
745
+ () => {
746
+ },
747
+ () => {
748
+ }
749
+ ), e;
750
+ }
751
+ emit(t, e) {
752
+ const i = this.listeners[t];
753
+ for (const n of i ?? []) n(e);
754
+ }
755
+ }
756
+ function y(s) {
757
+ return {
758
+ ...s,
759
+ starterPrompts: [...s.starterPrompts],
760
+ appearance: s.appearance ? { ...s.appearance } : null,
761
+ messages: s.messages.map((t) => {
762
+ const e = {
763
+ ...t,
764
+ attachments: t.attachments?.map((r) => ({ ...r }))
765
+ }, i = t.assistantDraftItemId, n = t.clientMessageId;
766
+ return i && Object.defineProperty(e, "assistantDraftItemId", {
767
+ value: i,
768
+ enumerable: !1
769
+ }), n && Object.defineProperty(e, "clientMessageId", {
770
+ value: n,
771
+ enumerable: !1
772
+ }), e;
773
+ }),
774
+ activeScheduledFollowUps: s.activeScheduledFollowUps?.map((t) => ({ ...t })) ?? null
775
+ };
776
+ }
777
+ function S(s) {
778
+ return {
779
+ ...s,
780
+ data: s.data ? p({
781
+ entities: A(s.data).map((t) => ({ ...t })),
782
+ nextCursor: s.data.nextCursor
783
+ }) : null
784
+ };
785
+ }
786
+ export {
787
+ L as ProductAgentInteractionManager,
788
+ b as ProductAgentQueryController,
789
+ F as ProductAgentRemoteRuntimeClient,
790
+ q as ProductAgentSessionHistoryManager,
791
+ k as ProductAgentTaskPageTitleController,
792
+ Q as createLocalStorageInteractionDecisionStorage,
793
+ h as createProductAgentQueryState,
794
+ $ as createProductAgentTaskPageTitleDocument,
795
+ O as formatProductAgentTaskPageTitle,
796
+ D as hasProductAgentPaidCreditFallback,
797
+ K as isProductAgentRuntimeCommand,
798
+ P as mergeProductAgentEntityPages,
799
+ p as normalizeProductAgentEntityPage,
800
+ E as readLocalStorageInteractionDecisions,
801
+ x as reconcileProductAgentSubmissionGate,
802
+ C as resolveProductAgentBillingPresentation,
803
+ R as resolveProductAgentComposerAction,
804
+ _ as resolveProductAgentWidgetPresentation,
805
+ A as selectProductAgentQueryEntities
806
+ };