@pageops/sdk 0.1.38 → 0.1.40

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 CHANGED
@@ -17,6 +17,10 @@ inside chat answers, including live updates and historical Run selection. The
17
17
  sidebar source-package controls remain available; backend step data is retained
18
18
  for cancellation and history.
19
19
 
20
+ Version `0.1.40` adds multi-selection and confirmed batch deletion to the
21
+ conversation sidebar. Each deletion uses the existing owner-scoped API; failed
22
+ items remain selected so they can be retried.
23
+
20
24
  `src/index.js` is the readable ESM runtime baseline, `src/styles.css` preserves
21
25
  the 0.1.34 styles, and `src/extensions.css` contains the new non-minified style
22
26
  rules. `npm run build` synchronizes ESM, UMD, and CSS under `dist/` without
package/dist/client.d.ts CHANGED
@@ -9,6 +9,7 @@ export declare class PageOpsClient {
9
9
  listMessages(threadId: string): Promise<ConversationMessage[]>;
10
10
  getAgentRun(runId: string): Promise<AgentRunHistory>;
11
11
  listSources(): Promise<SourceSnapshot[]>;
12
+ deleteSource(sourceSnapshotId: string): Promise<{ status: string; warning?: string | null }>;
12
13
  uploadSource(file: File, metadata: SourceUploadMetadata): Promise<SourceSnapshot>;
13
14
  streamQuestion(threadId: string, question: string, userRole: string, signal?: AbortSignal): Promise<Response>;
14
15
  private request;
package/dist/index.d.ts CHANGED
@@ -23,6 +23,7 @@ declare class PageOpsSDKController {
23
23
  private sourceUploadError;
24
24
  private sourceLoadError;
25
25
  private sourceUploading;
26
+ private deletingSourceId;
26
27
  private sourceRefreshTimer;
27
28
  private developerAccess;
28
29
  private streaming;
@@ -68,6 +69,7 @@ declare class PageOpsSDKController {
68
69
  private selectThread;
69
70
  private deleteConversation;
70
71
  private uploadSource;
72
+ private deleteSourceSnapshot;
71
73
  private ask;
72
74
  private cancelActiveAnswer;
73
75
  private handleStreamEvent;
@@ -140,3 +140,111 @@
140
140
  .po-message.user > div {
141
141
  margin-top: 1px;
142
142
  }
143
+
144
+ .po-source-item-head {
145
+ display: flex;
146
+ align-items: center;
147
+ justify-content: space-between;
148
+ gap: 8px;
149
+ min-width: 0;
150
+ }
151
+
152
+ .po-source-item-head strong {
153
+ min-width: 0;
154
+ }
155
+
156
+ .po-source-delete {
157
+ display: grid;
158
+ width: 28px;
159
+ height: 28px;
160
+ flex: 0 0 auto;
161
+ place-items: center;
162
+ border: 0;
163
+ border-radius: 6px;
164
+ background: transparent;
165
+ color: #64748b;
166
+ }
167
+
168
+ .po-source-delete:hover,
169
+ .po-source-delete:focus-visible {
170
+ background: #fee2e2;
171
+ color: #b91c1c;
172
+ }
173
+
174
+ .po-source-delete:focus-visible {
175
+ outline: 2px solid #b91c1c;
176
+ outline-offset: 1px;
177
+ }
178
+
179
+ .po-source-delete:disabled {
180
+ cursor: not-allowed;
181
+ opacity: .4;
182
+ }
183
+
184
+ .po-thread-actions {
185
+ display: flex;
186
+ align-items: center;
187
+ flex-wrap: wrap;
188
+ gap: 5px;
189
+ min-height: 28px;
190
+ }
191
+
192
+ .po-thread-actions button {
193
+ min-height: 28px;
194
+ border: 0;
195
+ border-radius: 6px;
196
+ background: transparent;
197
+ color: #475569;
198
+ padding: 3px 6px;
199
+ font-size: 12px;
200
+ font-weight: 650;
201
+ }
202
+
203
+ .po-thread-actions button:hover:not(:disabled) {
204
+ background: #dbeafe;
205
+ }
206
+
207
+ .po-thread-actions [data-action="delete-selected-threads"] {
208
+ margin-left: auto;
209
+ color: #b91c1c;
210
+ }
211
+
212
+ .po-thread-actions [data-action="delete-selected-threads"]:hover:not(:disabled) {
213
+ background: #fee2e2;
214
+ }
215
+
216
+ .po-thread-actions button:disabled {
217
+ cursor: not-allowed;
218
+ opacity: .45;
219
+ }
220
+
221
+ .po-thread-select-all {
222
+ display: inline-flex;
223
+ align-items: center;
224
+ gap: 5px;
225
+ color: #475569;
226
+ font-size: 12px;
227
+ font-weight: 650;
228
+ cursor: pointer;
229
+ }
230
+
231
+ .po-thread-select-all input,
232
+ .po-thread-checkbox {
233
+ width: 16px;
234
+ height: 16px;
235
+ accent-color: var(--po-primary);
236
+ cursor: pointer;
237
+ }
238
+
239
+ .po-thread-row.selecting {
240
+ grid-template-columns: 30px minmax(0, 1fr);
241
+ }
242
+
243
+ .po-thread-checkbox {
244
+ margin-left: 9px;
245
+ }
246
+
247
+ .po-thread-row.selecting .po-thread {
248
+ min-width: 0;
249
+ padding-left: 4px;
250
+ }
@@ -49,6 +49,11 @@ class K {
49
49
  async listSources() {
50
50
  return (await this.request(`/sources?project_id=${encodeURIComponent(this.options.appId)}`)).sources;
51
51
  }
52
+ async deleteSource(e) {
53
+ return this.request(`/sources/${encodeURIComponent(e)}?project_id=${encodeURIComponent(this.options.appId)}`, {
54
+ method: "DELETE"
55
+ });
56
+ }
52
57
  uploadSource(e, t) {
53
58
  if (e.size && e.size > UPLOAD_MAX_BYTES) throw new Error("源码包超过 500M,请压缩后重新上传。");
54
59
  const s = new FormData();
@@ -205,6 +210,7 @@ class V {
205
210
  i(this, "sourceUploadError", "");
206
211
  i(this, "sourceLoadError", "");
207
212
  i(this, "sourceUploading", !1);
213
+ i(this, "deletingSourceId", "");
208
214
  i(this, "sourceRefreshTimer", null);
209
215
  i(this, "developerAccess", !1);
210
216
  i(this, "streaming", "");
@@ -217,6 +223,9 @@ class V {
217
223
  i(this, "answerError", "");
218
224
  i(this, "conversationError", "");
219
225
  i(this, "deletingThreadId", "");
226
+ i(this, "selectingConversations", !1);
227
+ i(this, "selectedConversationIds", /* @__PURE__ */ new Set());
228
+ i(this, "bulkDeleting", !1);
220
229
  i(this, "streamFailure", "");
221
230
  i(this, "streamDone", null);
222
231
  i(this, "activeQuestionStartedAt", "");
@@ -233,7 +242,7 @@ class V {
233
242
  }
234
243
  unmount() {
235
244
  var e;
236
- this.cleanupFloatingLauncher(), this.stopSourceRefresh(), this.cancelActiveAnswer(!1), this.resetAnswerState(), (e = this.root) == null || e.remove(), this.root = null, this.panel = null, this.context = null, this.contextKey = "", this.selectedPageKey = "", this.currentThread = null, this.conversations = [], this.messages = [], this.steps = [], this.thoughts = [], this.selectedAgentRunId = "", this.runLoading = !1, this.runLoadError = "", this.clearCopyFeedback(), this.sourceSnapshots = [], this.selectedSourceSnapshotId = null, this.sourceUploadStatus = "", this.sourceUploadProgress = null, this.sourceUploadError = "", this.sourceLoadError = "", this.sourceUploading = !1, this.developerAccess = !1, this.activeQuestionStartedAt = "", this.answerAudience = "developer";
245
+ this.cleanupFloatingLauncher(), this.stopSourceRefresh(), this.cancelActiveAnswer(!1), this.resetAnswerState(), (e = this.root) == null || e.remove(), this.root = null, this.panel = null, this.context = null, this.contextKey = "", this.selectedPageKey = "", this.currentThread = null, this.conversations = [], this.selectingConversations = !1, this.selectedConversationIds.clear(), this.bulkDeleting = !1, this.messages = [], this.steps = [], this.thoughts = [], this.selectedAgentRunId = "", this.runLoading = !1, this.runLoadError = "", this.clearCopyFeedback(), this.sourceSnapshots = [], this.selectedSourceSnapshotId = null, this.sourceUploadStatus = "", this.sourceUploadProgress = null, this.sourceUploadError = "", this.sourceLoadError = "", this.sourceUploading = !1, this.deletingSourceId = "", this.developerAccess = !1, this.activeQuestionStartedAt = "", this.answerAudience = "developer";
237
246
  }
238
247
  open() {
239
248
  this.root && (this.cleanupFloatingLauncher(), this.root.innerHTML = "", this.panel = document.createElement("div"), this.panel.className = "po-panel", this.root.appendChild(this.panel), this.loadDeveloperAccess(), this.loadSources(), this.loadConversations(), this.renderPanel());
@@ -246,7 +255,7 @@ class V {
246
255
  const t = this.options.appId, s = String(this.options.ownerId || "").trim();
247
256
  this.options = { ...this.options, ...e }, this.client = new K(this.options);
248
257
  const r = String(this.options.ownerId || "").trim(), n = this.options.appId !== t;
249
- (n || r !== s) && (n && (this.answerAudience = this.loadAnswerAudience(this.options.appId), this.selectedSourceSnapshotId = null), this.currentThread = null, this.selectedPageKey = "", this.conversations = [], this.messages = [], this.steps = [], this.thoughts = [], this.selectedAgentRunId = "", this.runLoadError = ""), this.context = null, this.contextKey = "", r !== s && this.loadDeveloperAccess(), this.panel && this.loadConversations(), this.renderPanel();
258
+ (n || r !== s) && (n && (this.answerAudience = this.loadAnswerAudience(this.options.appId), this.selectedSourceSnapshotId = null), this.currentThread = null, this.selectedPageKey = "", this.conversations = [], this.selectingConversations = !1, this.selectedConversationIds.clear(), this.messages = [], this.steps = [], this.thoughts = [], this.selectedAgentRunId = "", this.runLoadError = ""), this.context = null, this.contextKey = "", r !== s && this.loadDeveloperAccess(), this.panel && this.loadConversations(), this.renderPanel();
250
259
  }
251
260
  renderClosed() {
252
261
  var e;
@@ -391,7 +400,7 @@ class V {
391
400
  }
392
401
  }
393
402
  async loadConversations() {
394
- this.client && (this.conversations = await this.client.listConversations(), this.renderPanel());
403
+ this.client && (this.conversations = await this.client.listConversations(), this.selectedConversationIds = new Set([...this.selectedConversationIds].filter((e) => this.conversations.some((t) => t.id === e))), this.renderPanel());
395
404
  }
396
405
  async newConversation(e = "") {
397
406
  var s;
@@ -407,7 +416,7 @@ class V {
407
416
  }
408
417
  async deleteConversation(e) {
409
418
  var t;
410
- if (!(!this.client || this.asking || this.deletingThreadId) && window.confirm(`确定删除会话“${e.title}”吗?此操作无法撤销。`)) {
419
+ if (!(!this.client || this.asking || this.deletingThreadId || this.bulkDeleting) && window.confirm(`确定删除会话“${e.title}”吗?此操作无法撤销。`)) {
411
420
  this.deletingThreadId = e.id, this.conversationError = "", this.renderPanel();
412
421
  try {
413
422
  if (await this.client.deleteConversation(e.id), this.conversations = this.conversations.filter((s) => s.id !== e.id), ((t = this.currentThread) == null ? void 0 : t.id) === e.id) {
@@ -422,6 +431,42 @@ class V {
422
431
  }
423
432
  }
424
433
  }
434
+ async deleteSelectedConversations() {
435
+ if (!this.client || this.asking || this.deletingThreadId || this.bulkDeleting) return;
436
+ const e = this.conversations.filter((t) => this.selectedConversationIds.has(t.id));
437
+ if (!e.length || !window.confirm(`确定删除选中的 ${e.length} 个会话吗?此操作无法撤销。`)) return;
438
+ const t = this.client, s = this.options.appId, r = this.client.ownerId(), n = [], c = [];
439
+ this.bulkDeleting = !0, this.conversationError = "", this.renderPanel();
440
+ try {
441
+ for (const p of e) {
442
+ try {
443
+ await t.deleteConversation(p.id), n.push(p.id);
444
+ } catch (m) {
445
+ c.push({ id: p.id, reason: m instanceof Error ? m.message : "请求失败" });
446
+ }
447
+ }
448
+ if (this.options.appId !== s || this.client.ownerId() !== r) return;
449
+ const p = new Set(n);
450
+ this.conversations = this.conversations.filter((m) => !p.has(m.id));
451
+ this.selectedConversationIds = new Set(c.map((m) => m.id));
452
+ let loadError = "";
453
+ if (this.currentThread && p.has(this.currentThread.id)) {
454
+ this.currentThread = null, this.selectedPageKey = "", this.messages = [], this.steps = [], this.thoughts = [], this.selectedAgentRunId = "", this.runLoadError = "", this.streaming = "", this.answerError = "", this.answerStopped = !1;
455
+ const m = this.conversations[0];
456
+ if (m) {
457
+ try {
458
+ await this.selectThread(m);
459
+ } catch (g) {
460
+ this.currentThread = null, loadError = g instanceof Error ? g.message : "加载会话失败";
461
+ }
462
+ }
463
+ }
464
+ this.selectingConversations = c.length > 0;
465
+ this.conversationError = [c.length ? `已删除 ${n.length} 个会话,${c.length} 个删除失败:${c[0].reason}` : "", loadError].filter(Boolean).join(";");
466
+ } finally {
467
+ this.bulkDeleting = !1, this.renderPanel();
468
+ }
469
+ }
425
470
  async uploadSource(e, t) {
426
471
  var s;
427
472
  if (this.client) {
@@ -437,6 +482,28 @@ class V {
437
482
  }
438
483
  }
439
484
  }
485
+ async deleteSourceSnapshot(e) {
486
+ if (!this.client || this.asking || this.sourceUploading || this.deletingSourceId) return;
487
+ const id = this.sourceSnapshotValue(e);
488
+ const selected = this.selectedSourceSnapshot();
489
+ if (!id || e.in_use_reason || selected && this.sourceSnapshotValue(selected) === id) return;
490
+ const name = e.filename || `代码包 ${id}`;
491
+ if (!window.confirm(`确定删除历史代码包“${name}”吗?代码索引和存储文件将一并清理,此操作无法撤销。`)) return;
492
+ this.deletingSourceId = id;
493
+ this.sourceUploadError = "";
494
+ this.renderPanel();
495
+ try {
496
+ const result = await this.client.deleteSource(id);
497
+ this.sourceSnapshots = this.sourceSnapshots.filter((item) => this.sourceSnapshotValue(item) !== id);
498
+ this.sourceUploadError = result.warning || "";
499
+ await this.loadSources();
500
+ } catch (error) {
501
+ this.sourceUploadError = error instanceof Error ? error.message : "删除代码包失败";
502
+ } finally {
503
+ this.deletingSourceId = "";
504
+ this.renderPanel();
505
+ }
506
+ }
440
507
  async ask(e) {
441
508
  if (!this.client || this.asking) return;
442
509
  const t = this.questionUnavailableReason();
@@ -605,23 +672,29 @@ class V {
605
672
  renderPanel(e = this.asking) {
606
673
  var g;
607
674
  if (!this.panel) return;
608
- const s = (g = this.panel.querySelector(".po-messages")) == null ? void 0 : g.scrollTop, r = this.questionUnavailableReason(), n = r || (this.asking ? "回答生成中,请稍候" : this.sourceSnapshots.length ? "请输入页面分析问题,Enter 发送,Shift + Enter 换行" : "可直接闲聊;业务问题需先上传代码包"), c = !!(r || this.asking), p = r ? '<button type="submit" disabled>暂不可提问</button>' : this.asking ? '<button class="po-stop" type="button" data-action="stop-answer" aria-label="停止输出" title="停止输出"><span aria-hidden="true"></span></button>' : '<button type="submit">发送</button>', m = C.map((o) => `
675
+ const listScroll = this.panel.querySelector(".po-thread-list")?.scrollTop;
676
+ const s = (g = this.panel.querySelector(".po-messages")) == null ? void 0 : g.scrollTop, r = this.questionUnavailableReason(), n = r || (this.asking ? "回答生成中,请稍候" : this.sourceSnapshots.length ? "请输入页面分析问题,Enter 发送,Shift + Enter 换行" : "可直接闲聊;业务问题需先上传代码包"), c = !!(r || this.asking || this.bulkDeleting), p = r ? '<button type="submit" disabled>暂不可提问</button>' : this.asking ? '<button class="po-stop" type="button" data-action="stop-answer" aria-label="停止输出" title="停止输出"><span aria-hidden="true"></span></button>' : `<button type="submit" ${this.bulkDeleting ? "disabled" : ""}>发送</button>`, m = C.map((o) => `
609
677
  <button type="button" data-audience="${o.value}" aria-pressed="${o.value === this.answerAudience}" ${this.asking ? "disabled" : ""}>${o.label}</button>
610
678
  `).join("");
611
679
  if (this.panel.innerHTML = `
612
680
  <aside class="po-sidebar">
613
681
  <div class="po-brand"><div class="po-logo"></div><div><strong>PageOps 问答</strong><span>页面工程专家</span></div></div>
614
- <button class="po-new" data-action="new" ${this.asking ? "disabled" : ""}>+ 新建问答</button>
682
+ <button class="po-new" data-action="new" ${this.asking || this.bulkDeleting ? "disabled" : ""}>+ 新建问答</button>
615
683
  <input class="po-search" placeholder="搜索问答" />
616
684
  ${this.conversationError ? `<p class="po-conversation-error" role="alert">${l(this.conversationError)}</p>` : ""}
685
+ ${this.conversations.length ? `<div class="po-thread-actions">${this.selectingConversations ? `
686
+ <label class="po-thread-select-all"><input type="checkbox" data-action="select-all-threads" ${this.selectedConversationIds.size === this.conversations.length ? "checked" : ""} ${this.bulkDeleting ? "disabled" : ""} />全选</label>
687
+ <button type="button" data-action="delete-selected-threads" ${!this.selectedConversationIds.size || this.bulkDeleting ? "disabled" : ""}>${this.bulkDeleting ? "删除中..." : `删除 (${this.selectedConversationIds.size})`}</button>
688
+ <button type="button" data-action="cancel-thread-selection" ${this.bulkDeleting ? "disabled" : ""}>取消</button>` : `<button type="button" data-action="select-threads" ${this.asking || this.deletingThreadId ? "disabled" : ""}>批量删除</button>`}</div>` : ""}
617
689
  <div class="po-thread-list">${this.conversations.map((o) => {
618
690
  var y;
619
691
  return `
620
- <div class="po-thread-row ${o.id === ((y = this.currentThread) == null ? void 0 : y.id) ? "active" : ""}">
621
- <button class="po-thread" data-thread="${l(o.id)}" ${this.asking ? "disabled" : ""}>
692
+ <div class="po-thread-row ${o.id === ((y = this.currentThread) == null ? void 0 : y.id) ? "active" : ""} ${this.selectingConversations ? "selecting" : ""}">
693
+ ${this.selectingConversations ? `<input class="po-thread-checkbox" type="checkbox" data-select-thread="${l(o.id)}" aria-label="选择会话:${l(o.title)}" ${this.selectedConversationIds.has(o.id) ? "checked" : ""} ${this.bulkDeleting ? "disabled" : ""} />` : ""}
694
+ <button class="po-thread" data-thread="${l(o.id)}" ${this.asking || this.bulkDeleting ? "disabled" : ""}>
622
695
  <strong>${l(o.title)}</strong><span>${O(o.created_at)}</span>
623
696
  </button>
624
- <button class="po-thread-delete" type="button" data-delete-thread="${l(o.id)}" aria-label="删除会话:${l(o.title)}" title="删除会话" ${this.asking || this.deletingThreadId === o.id ? "disabled" : ""}><span class="po-trash-icon" aria-hidden="true"></span></button>
697
+ ${this.selectingConversations ? "" : `<button class="po-thread-delete" type="button" data-delete-thread="${l(o.id)}" aria-label="删除会话:${l(o.title)}" title="删除会话" ${this.asking || this.deletingThreadId === o.id ? "disabled" : ""}><span class="po-trash-icon" aria-hidden="true"></span></button>`}
625
698
  </div>`;
626
699
  }).join("")}</div>
627
700
  </aside>
@@ -634,7 +707,7 @@ class V {
634
707
  <form class="po-composer"><textarea ${c ? "disabled" : ""} placeholder="${l(n)}"></textarea>${p}</form>
635
708
  </main>
636
709
  <aside class="po-trace"><header><h2>执行过程</h2><button data-action="close">×</button></header><section>${this.renderSourceUploader()}</section></aside>
637
- `, this.bindPanelEvents(), e) {
710
+ `, this.bindPanelEvents(), listScroll !== void 0 && (this.panel.querySelector(".po-thread-list").scrollTop = listScroll), e) {
638
711
  const o = this.panel.querySelector(".po-messages");
639
712
  o && (o.scrollTop = o.scrollHeight);
640
713
  } else if (s !== void 0) {
@@ -692,7 +765,11 @@ class V {
692
765
  renderSourceItem(e) {
693
766
  var w, b, S, $, E, A, T;
694
767
  const t = e.filename || "未命名代码包", s = e.created_at ? O(e.created_at) : "刚刚上传", r = G(e.archive_bytes || e.total_bytes || 0), n = String((b = (w = e.metadata) == null ? void 0 : w.analysis_status) != null ? b : "unknown"), c = typeof ((S = e.metadata) == null ? void 0 : S.tag) == "string" ? e.metadata.tag : "", p = typeof (($ = e.metadata) == null ? void 0 : $.branch) == "string" ? e.metadata.branch : "", m = c ? `Tag: ${c}` : p ? `Branch: ${p}` : "未记录代码引用", g = typeof ((E = e.metadata) == null ? void 0 : E.remark) == "string" && e.metadata.remark ? e.metadata.remark : "无备注", o = typeof ((A = e.metadata) == null ? void 0 : A.uploader) == "string" ? e.metadata.uploader : "未知用户", y = (T = { pending: "项目记忆等待更新", running: "项目记忆更新中", ready: "项目记忆已就绪", failed: "项目记忆更新失败" }[n]) != null ? T : "项目记忆状态未知";
695
- return `<article class="po-source-item ${this.selectedSourceSnapshotId != null && this.sourceSnapshotValue(e) === String(this.selectedSourceSnapshotId) || this.selectedSourceSnapshotId == null && e === this.sourceSnapshots[0] ? "selected" : ""}"><strong>${l(t)}</strong><span>${l(m)}</span><span>备注:${l(g)}</span><span>上传人:${l(o)} · ${l(s)} · ${l(r)}</span><span>${l(y)} · 当前问答${this.selectedSourceSnapshotId == null && e === this.sourceSnapshots[0] ? "默认" : ""}引用</span></article>`;
768
+ const id = this.sourceSnapshotValue(e), selected = this.selectedSourceSnapshot(), current = selected && this.sourceSnapshotValue(selected) === id;
769
+ const reason = current ? "当前问答引用" : e.in_use_reason === "default" ? "默认问答引用" : e.in_use_reason === "conversation" ? "已有会话引用" : "";
770
+ const deleting = this.deletingSourceId === id;
771
+ const action = reason ? "" : `<button class="po-source-delete" type="button" data-delete-source="${l(id)}" aria-label="删除代码包:${l(t)}" title="删除代码包" ${this.asking || this.sourceUploading || this.deletingSourceId ? "disabled" : ""}><span class="po-trash-icon" aria-hidden="true"></span></button>`;
772
+ return `<article class="po-source-item ${current ? "selected" : ""}"><div class="po-source-item-head"><strong title="${l(t)}">${l(t)}</strong>${action}</div><span>${l(m)}</span><span>备注:${l(g)}</span><span>上传人:${l(o)} · ${l(s)} · ${l(r)}</span><span>${l(y)}${reason ? ` · ${reason},不可删除` : deleting ? " · 正在删除" : ""}</span></article>`;
696
773
  }
697
774
  renderThinkingProcess() {
698
775
  if (!this.asking && !this.thoughts.length && !this.runLoading && !this.runLoadError) return "";
@@ -741,7 +818,23 @@ class V {
741
818
  }), (y = this.panel) == null || y.querySelectorAll("[data-thread]").forEach((h) => {
742
819
  h.addEventListener("click", () => {
743
820
  const d = this.conversations.find((u) => u.id === h.dataset.thread);
744
- d && this.selectThread(d);
821
+ if (!d) return;
822
+ if (this.selectingConversations) {
823
+ this.selectedConversationIds.has(d.id) ? this.selectedConversationIds.delete(d.id) : this.selectedConversationIds.add(d.id);
824
+ this.renderPanel(!1);
825
+ } else this.selectThread(d);
826
+ });
827
+ }), this.panel.querySelector('[data-action="select-threads"]')?.addEventListener("click", () => {
828
+ this.selectingConversations = !0, this.selectedConversationIds.clear(), this.conversationError = "", this.renderPanel(!1);
829
+ }), this.panel.querySelector('[data-action="cancel-thread-selection"]')?.addEventListener("click", () => {
830
+ this.selectingConversations = !1, this.selectedConversationIds.clear(), this.conversationError = "", this.renderPanel(!1);
831
+ }), this.panel.querySelector('[data-action="select-all-threads"]')?.addEventListener("change", (h) => {
832
+ this.selectedConversationIds = h.target.checked ? new Set(this.conversations.map((d) => d.id)) : /* @__PURE__ */ new Set();
833
+ this.renderPanel(!1);
834
+ }), this.panel.querySelector('[data-action="delete-selected-threads"]')?.addEventListener("click", () => void this.deleteSelectedConversations()), this.panel.querySelectorAll("[data-select-thread]").forEach((h) => {
835
+ h.addEventListener("change", () => {
836
+ h.checked ? this.selectedConversationIds.add(h.dataset.selectThread) : this.selectedConversationIds.delete(h.dataset.selectThread);
837
+ this.renderPanel(!1);
745
838
  });
746
839
  }), (w = this.panel) == null || w.querySelectorAll("[data-delete-thread]").forEach((h) => {
747
840
  h.addEventListener("click", (d) => {
@@ -769,6 +862,12 @@ class V {
769
862
  const d = h;
770
863
  d.key === "Enter" && !d.shiftKey && (d.preventDefault(), (f = (u = this.panel) == null ? void 0 : u.querySelector("form")) == null || f.requestSubmit());
771
864
  });
865
+ this.panel.querySelectorAll("[data-delete-source]").forEach((button) => {
866
+ button.addEventListener("click", () => {
867
+ const snapshot = this.sourceSnapshots.find((item) => this.sourceSnapshotValue(item) === button.dataset.deleteSource);
868
+ if (snapshot) this.deleteSourceSnapshot(snapshot);
869
+ });
870
+ });
772
871
  }
773
872
  }
774
873
  function l(a) {
@@ -49,6 +49,11 @@ class K {
49
49
  async listSources() {
50
50
  return (await this.request(`/sources?project_id=${encodeURIComponent(this.options.appId)}`)).sources;
51
51
  }
52
+ async deleteSource(e) {
53
+ return this.request(`/sources/${encodeURIComponent(e)}?project_id=${encodeURIComponent(this.options.appId)}`, {
54
+ method: "DELETE"
55
+ });
56
+ }
52
57
  uploadSource(e, t) {
53
58
  if (e.size && e.size > UPLOAD_MAX_BYTES) throw new Error("源码包超过 500M,请压缩后重新上传。");
54
59
  const s = new FormData();
@@ -205,6 +210,7 @@ class V {
205
210
  i(this, "sourceUploadError", "");
206
211
  i(this, "sourceLoadError", "");
207
212
  i(this, "sourceUploading", !1);
213
+ i(this, "deletingSourceId", "");
208
214
  i(this, "sourceRefreshTimer", null);
209
215
  i(this, "developerAccess", !1);
210
216
  i(this, "streaming", "");
@@ -217,6 +223,9 @@ class V {
217
223
  i(this, "answerError", "");
218
224
  i(this, "conversationError", "");
219
225
  i(this, "deletingThreadId", "");
226
+ i(this, "selectingConversations", !1);
227
+ i(this, "selectedConversationIds", /* @__PURE__ */ new Set());
228
+ i(this, "bulkDeleting", !1);
220
229
  i(this, "streamFailure", "");
221
230
  i(this, "streamDone", null);
222
231
  i(this, "activeQuestionStartedAt", "");
@@ -233,7 +242,7 @@ class V {
233
242
  }
234
243
  unmount() {
235
244
  var e;
236
- this.cleanupFloatingLauncher(), this.stopSourceRefresh(), this.cancelActiveAnswer(!1), this.resetAnswerState(), (e = this.root) == null || e.remove(), this.root = null, this.panel = null, this.context = null, this.contextKey = "", this.selectedPageKey = "", this.currentThread = null, this.conversations = [], this.messages = [], this.steps = [], this.thoughts = [], this.selectedAgentRunId = "", this.runLoading = !1, this.runLoadError = "", this.clearCopyFeedback(), this.sourceSnapshots = [], this.selectedSourceSnapshotId = null, this.sourceUploadStatus = "", this.sourceUploadProgress = null, this.sourceUploadError = "", this.sourceLoadError = "", this.sourceUploading = !1, this.developerAccess = !1, this.activeQuestionStartedAt = "", this.answerAudience = "developer";
245
+ this.cleanupFloatingLauncher(), this.stopSourceRefresh(), this.cancelActiveAnswer(!1), this.resetAnswerState(), (e = this.root) == null || e.remove(), this.root = null, this.panel = null, this.context = null, this.contextKey = "", this.selectedPageKey = "", this.currentThread = null, this.conversations = [], this.selectingConversations = !1, this.selectedConversationIds.clear(), this.bulkDeleting = !1, this.messages = [], this.steps = [], this.thoughts = [], this.selectedAgentRunId = "", this.runLoading = !1, this.runLoadError = "", this.clearCopyFeedback(), this.sourceSnapshots = [], this.selectedSourceSnapshotId = null, this.sourceUploadStatus = "", this.sourceUploadProgress = null, this.sourceUploadError = "", this.sourceLoadError = "", this.sourceUploading = !1, this.deletingSourceId = "", this.developerAccess = !1, this.activeQuestionStartedAt = "", this.answerAudience = "developer";
237
246
  }
238
247
  open() {
239
248
  this.root && (this.cleanupFloatingLauncher(), this.root.innerHTML = "", this.panel = document.createElement("div"), this.panel.className = "po-panel", this.root.appendChild(this.panel), this.loadDeveloperAccess(), this.loadSources(), this.loadConversations(), this.renderPanel());
@@ -246,7 +255,7 @@ class V {
246
255
  const t = this.options.appId, s = String(this.options.ownerId || "").trim();
247
256
  this.options = { ...this.options, ...e }, this.client = new K(this.options);
248
257
  const r = String(this.options.ownerId || "").trim(), n = this.options.appId !== t;
249
- (n || r !== s) && (n && (this.answerAudience = this.loadAnswerAudience(this.options.appId), this.selectedSourceSnapshotId = null), this.currentThread = null, this.selectedPageKey = "", this.conversations = [], this.messages = [], this.steps = [], this.thoughts = [], this.selectedAgentRunId = "", this.runLoadError = ""), this.context = null, this.contextKey = "", r !== s && this.loadDeveloperAccess(), this.panel && this.loadConversations(), this.renderPanel();
258
+ (n || r !== s) && (n && (this.answerAudience = this.loadAnswerAudience(this.options.appId), this.selectedSourceSnapshotId = null), this.currentThread = null, this.selectedPageKey = "", this.conversations = [], this.selectingConversations = !1, this.selectedConversationIds.clear(), this.messages = [], this.steps = [], this.thoughts = [], this.selectedAgentRunId = "", this.runLoadError = ""), this.context = null, this.contextKey = "", r !== s && this.loadDeveloperAccess(), this.panel && this.loadConversations(), this.renderPanel();
250
259
  }
251
260
  renderClosed() {
252
261
  var e;
@@ -391,7 +400,7 @@ class V {
391
400
  }
392
401
  }
393
402
  async loadConversations() {
394
- this.client && (this.conversations = await this.client.listConversations(), this.renderPanel());
403
+ this.client && (this.conversations = await this.client.listConversations(), this.selectedConversationIds = new Set([...this.selectedConversationIds].filter((e) => this.conversations.some((t) => t.id === e))), this.renderPanel());
395
404
  }
396
405
  async newConversation(e = "") {
397
406
  var s;
@@ -407,7 +416,7 @@ class V {
407
416
  }
408
417
  async deleteConversation(e) {
409
418
  var t;
410
- if (!(!this.client || this.asking || this.deletingThreadId) && window.confirm(`确定删除会话“${e.title}”吗?此操作无法撤销。`)) {
419
+ if (!(!this.client || this.asking || this.deletingThreadId || this.bulkDeleting) && window.confirm(`确定删除会话“${e.title}”吗?此操作无法撤销。`)) {
411
420
  this.deletingThreadId = e.id, this.conversationError = "", this.renderPanel();
412
421
  try {
413
422
  if (await this.client.deleteConversation(e.id), this.conversations = this.conversations.filter((s) => s.id !== e.id), ((t = this.currentThread) == null ? void 0 : t.id) === e.id) {
@@ -422,6 +431,42 @@ class V {
422
431
  }
423
432
  }
424
433
  }
434
+ async deleteSelectedConversations() {
435
+ if (!this.client || this.asking || this.deletingThreadId || this.bulkDeleting) return;
436
+ const e = this.conversations.filter((t) => this.selectedConversationIds.has(t.id));
437
+ if (!e.length || !window.confirm(`确定删除选中的 ${e.length} 个会话吗?此操作无法撤销。`)) return;
438
+ const t = this.client, s = this.options.appId, r = this.client.ownerId(), n = [], c = [];
439
+ this.bulkDeleting = !0, this.conversationError = "", this.renderPanel();
440
+ try {
441
+ for (const p of e) {
442
+ try {
443
+ await t.deleteConversation(p.id), n.push(p.id);
444
+ } catch (m) {
445
+ c.push({ id: p.id, reason: m instanceof Error ? m.message : "请求失败" });
446
+ }
447
+ }
448
+ if (this.options.appId !== s || this.client.ownerId() !== r) return;
449
+ const p = new Set(n);
450
+ this.conversations = this.conversations.filter((m) => !p.has(m.id));
451
+ this.selectedConversationIds = new Set(c.map((m) => m.id));
452
+ let loadError = "";
453
+ if (this.currentThread && p.has(this.currentThread.id)) {
454
+ this.currentThread = null, this.selectedPageKey = "", this.messages = [], this.steps = [], this.thoughts = [], this.selectedAgentRunId = "", this.runLoadError = "", this.streaming = "", this.answerError = "", this.answerStopped = !1;
455
+ const m = this.conversations[0];
456
+ if (m) {
457
+ try {
458
+ await this.selectThread(m);
459
+ } catch (g) {
460
+ this.currentThread = null, loadError = g instanceof Error ? g.message : "加载会话失败";
461
+ }
462
+ }
463
+ }
464
+ this.selectingConversations = c.length > 0;
465
+ this.conversationError = [c.length ? `已删除 ${n.length} 个会话,${c.length} 个删除失败:${c[0].reason}` : "", loadError].filter(Boolean).join(";");
466
+ } finally {
467
+ this.bulkDeleting = !1, this.renderPanel();
468
+ }
469
+ }
425
470
  async uploadSource(e, t) {
426
471
  var s;
427
472
  if (this.client) {
@@ -437,6 +482,28 @@ class V {
437
482
  }
438
483
  }
439
484
  }
485
+ async deleteSourceSnapshot(e) {
486
+ if (!this.client || this.asking || this.sourceUploading || this.deletingSourceId) return;
487
+ const id = this.sourceSnapshotValue(e);
488
+ const selected = this.selectedSourceSnapshot();
489
+ if (!id || e.in_use_reason || selected && this.sourceSnapshotValue(selected) === id) return;
490
+ const name = e.filename || `代码包 ${id}`;
491
+ if (!window.confirm(`确定删除历史代码包“${name}”吗?代码索引和存储文件将一并清理,此操作无法撤销。`)) return;
492
+ this.deletingSourceId = id;
493
+ this.sourceUploadError = "";
494
+ this.renderPanel();
495
+ try {
496
+ const result = await this.client.deleteSource(id);
497
+ this.sourceSnapshots = this.sourceSnapshots.filter((item) => this.sourceSnapshotValue(item) !== id);
498
+ this.sourceUploadError = result.warning || "";
499
+ await this.loadSources();
500
+ } catch (error) {
501
+ this.sourceUploadError = error instanceof Error ? error.message : "删除代码包失败";
502
+ } finally {
503
+ this.deletingSourceId = "";
504
+ this.renderPanel();
505
+ }
506
+ }
440
507
  async ask(e) {
441
508
  if (!this.client || this.asking) return;
442
509
  const t = this.questionUnavailableReason();
@@ -605,23 +672,29 @@ class V {
605
672
  renderPanel(e = this.asking) {
606
673
  var g;
607
674
  if (!this.panel) return;
608
- const s = (g = this.panel.querySelector(".po-messages")) == null ? void 0 : g.scrollTop, r = this.questionUnavailableReason(), n = r || (this.asking ? "回答生成中,请稍候" : this.sourceSnapshots.length ? "请输入页面分析问题,Enter 发送,Shift + Enter 换行" : "可直接闲聊;业务问题需先上传代码包"), c = !!(r || this.asking), p = r ? '<button type="submit" disabled>暂不可提问</button>' : this.asking ? '<button class="po-stop" type="button" data-action="stop-answer" aria-label="停止输出" title="停止输出"><span aria-hidden="true"></span></button>' : '<button type="submit">发送</button>', m = C.map((o) => `
675
+ const listScroll = this.panel.querySelector(".po-thread-list")?.scrollTop;
676
+ const s = (g = this.panel.querySelector(".po-messages")) == null ? void 0 : g.scrollTop, r = this.questionUnavailableReason(), n = r || (this.asking ? "回答生成中,请稍候" : this.sourceSnapshots.length ? "请输入页面分析问题,Enter 发送,Shift + Enter 换行" : "可直接闲聊;业务问题需先上传代码包"), c = !!(r || this.asking || this.bulkDeleting), p = r ? '<button type="submit" disabled>暂不可提问</button>' : this.asking ? '<button class="po-stop" type="button" data-action="stop-answer" aria-label="停止输出" title="停止输出"><span aria-hidden="true"></span></button>' : `<button type="submit" ${this.bulkDeleting ? "disabled" : ""}>发送</button>`, m = C.map((o) => `
609
677
  <button type="button" data-audience="${o.value}" aria-pressed="${o.value === this.answerAudience}" ${this.asking ? "disabled" : ""}>${o.label}</button>
610
678
  `).join("");
611
679
  if (this.panel.innerHTML = `
612
680
  <aside class="po-sidebar">
613
681
  <div class="po-brand"><div class="po-logo"></div><div><strong>PageOps 问答</strong><span>页面工程专家</span></div></div>
614
- <button class="po-new" data-action="new" ${this.asking ? "disabled" : ""}>+ 新建问答</button>
682
+ <button class="po-new" data-action="new" ${this.asking || this.bulkDeleting ? "disabled" : ""}>+ 新建问答</button>
615
683
  <input class="po-search" placeholder="搜索问答" />
616
684
  ${this.conversationError ? `<p class="po-conversation-error" role="alert">${l(this.conversationError)}</p>` : ""}
685
+ ${this.conversations.length ? `<div class="po-thread-actions">${this.selectingConversations ? `
686
+ <label class="po-thread-select-all"><input type="checkbox" data-action="select-all-threads" ${this.selectedConversationIds.size === this.conversations.length ? "checked" : ""} ${this.bulkDeleting ? "disabled" : ""} />全选</label>
687
+ <button type="button" data-action="delete-selected-threads" ${!this.selectedConversationIds.size || this.bulkDeleting ? "disabled" : ""}>${this.bulkDeleting ? "删除中..." : `删除 (${this.selectedConversationIds.size})`}</button>
688
+ <button type="button" data-action="cancel-thread-selection" ${this.bulkDeleting ? "disabled" : ""}>取消</button>` : `<button type="button" data-action="select-threads" ${this.asking || this.deletingThreadId ? "disabled" : ""}>批量删除</button>`}</div>` : ""}
617
689
  <div class="po-thread-list">${this.conversations.map((o) => {
618
690
  var y;
619
691
  return `
620
- <div class="po-thread-row ${o.id === ((y = this.currentThread) == null ? void 0 : y.id) ? "active" : ""}">
621
- <button class="po-thread" data-thread="${l(o.id)}" ${this.asking ? "disabled" : ""}>
692
+ <div class="po-thread-row ${o.id === ((y = this.currentThread) == null ? void 0 : y.id) ? "active" : ""} ${this.selectingConversations ? "selecting" : ""}">
693
+ ${this.selectingConversations ? `<input class="po-thread-checkbox" type="checkbox" data-select-thread="${l(o.id)}" aria-label="选择会话:${l(o.title)}" ${this.selectedConversationIds.has(o.id) ? "checked" : ""} ${this.bulkDeleting ? "disabled" : ""} />` : ""}
694
+ <button class="po-thread" data-thread="${l(o.id)}" ${this.asking || this.bulkDeleting ? "disabled" : ""}>
622
695
  <strong>${l(o.title)}</strong><span>${O(o.created_at)}</span>
623
696
  </button>
624
- <button class="po-thread-delete" type="button" data-delete-thread="${l(o.id)}" aria-label="删除会话:${l(o.title)}" title="删除会话" ${this.asking || this.deletingThreadId === o.id ? "disabled" : ""}><span class="po-trash-icon" aria-hidden="true"></span></button>
697
+ ${this.selectingConversations ? "" : `<button class="po-thread-delete" type="button" data-delete-thread="${l(o.id)}" aria-label="删除会话:${l(o.title)}" title="删除会话" ${this.asking || this.deletingThreadId === o.id ? "disabled" : ""}><span class="po-trash-icon" aria-hidden="true"></span></button>`}
625
698
  </div>`;
626
699
  }).join("")}</div>
627
700
  </aside>
@@ -634,7 +707,7 @@ class V {
634
707
  <form class="po-composer"><textarea ${c ? "disabled" : ""} placeholder="${l(n)}"></textarea>${p}</form>
635
708
  </main>
636
709
  <aside class="po-trace"><header><h2>执行过程</h2><button data-action="close">×</button></header><section>${this.renderSourceUploader()}</section></aside>
637
- `, this.bindPanelEvents(), e) {
710
+ `, this.bindPanelEvents(), listScroll !== void 0 && (this.panel.querySelector(".po-thread-list").scrollTop = listScroll), e) {
638
711
  const o = this.panel.querySelector(".po-messages");
639
712
  o && (o.scrollTop = o.scrollHeight);
640
713
  } else if (s !== void 0) {
@@ -692,7 +765,11 @@ class V {
692
765
  renderSourceItem(e) {
693
766
  var w, b, S, $, E, A, T;
694
767
  const t = e.filename || "未命名代码包", s = e.created_at ? O(e.created_at) : "刚刚上传", r = G(e.archive_bytes || e.total_bytes || 0), n = String((b = (w = e.metadata) == null ? void 0 : w.analysis_status) != null ? b : "unknown"), c = typeof ((S = e.metadata) == null ? void 0 : S.tag) == "string" ? e.metadata.tag : "", p = typeof (($ = e.metadata) == null ? void 0 : $.branch) == "string" ? e.metadata.branch : "", m = c ? `Tag: ${c}` : p ? `Branch: ${p}` : "未记录代码引用", g = typeof ((E = e.metadata) == null ? void 0 : E.remark) == "string" && e.metadata.remark ? e.metadata.remark : "无备注", o = typeof ((A = e.metadata) == null ? void 0 : A.uploader) == "string" ? e.metadata.uploader : "未知用户", y = (T = { pending: "项目记忆等待更新", running: "项目记忆更新中", ready: "项目记忆已就绪", failed: "项目记忆更新失败" }[n]) != null ? T : "项目记忆状态未知";
695
- return `<article class="po-source-item ${this.selectedSourceSnapshotId != null && this.sourceSnapshotValue(e) === String(this.selectedSourceSnapshotId) || this.selectedSourceSnapshotId == null && e === this.sourceSnapshots[0] ? "selected" : ""}"><strong>${l(t)}</strong><span>${l(m)}</span><span>备注:${l(g)}</span><span>上传人:${l(o)} · ${l(s)} · ${l(r)}</span><span>${l(y)} · 当前问答${this.selectedSourceSnapshotId == null && e === this.sourceSnapshots[0] ? "默认" : ""}引用</span></article>`;
768
+ const id = this.sourceSnapshotValue(e), selected = this.selectedSourceSnapshot(), current = selected && this.sourceSnapshotValue(selected) === id;
769
+ const reason = current ? "当前问答引用" : e.in_use_reason === "default" ? "默认问答引用" : e.in_use_reason === "conversation" ? "已有会话引用" : "";
770
+ const deleting = this.deletingSourceId === id;
771
+ const action = reason ? "" : `<button class="po-source-delete" type="button" data-delete-source="${l(id)}" aria-label="删除代码包:${l(t)}" title="删除代码包" ${this.asking || this.sourceUploading || this.deletingSourceId ? "disabled" : ""}><span class="po-trash-icon" aria-hidden="true"></span></button>`;
772
+ return `<article class="po-source-item ${current ? "selected" : ""}"><div class="po-source-item-head"><strong title="${l(t)}">${l(t)}</strong>${action}</div><span>${l(m)}</span><span>备注:${l(g)}</span><span>上传人:${l(o)} · ${l(s)} · ${l(r)}</span><span>${l(y)}${reason ? ` · ${reason},不可删除` : deleting ? " · 正在删除" : ""}</span></article>`;
696
773
  }
697
774
  renderThinkingProcess() {
698
775
  if (!this.asking && !this.thoughts.length && !this.runLoading && !this.runLoadError) return "";
@@ -741,7 +818,23 @@ class V {
741
818
  }), (y = this.panel) == null || y.querySelectorAll("[data-thread]").forEach((h) => {
742
819
  h.addEventListener("click", () => {
743
820
  const d = this.conversations.find((u) => u.id === h.dataset.thread);
744
- d && this.selectThread(d);
821
+ if (!d) return;
822
+ if (this.selectingConversations) {
823
+ this.selectedConversationIds.has(d.id) ? this.selectedConversationIds.delete(d.id) : this.selectedConversationIds.add(d.id);
824
+ this.renderPanel(!1);
825
+ } else this.selectThread(d);
826
+ });
827
+ }), this.panel.querySelector('[data-action="select-threads"]')?.addEventListener("click", () => {
828
+ this.selectingConversations = !0, this.selectedConversationIds.clear(), this.conversationError = "", this.renderPanel(!1);
829
+ }), this.panel.querySelector('[data-action="cancel-thread-selection"]')?.addEventListener("click", () => {
830
+ this.selectingConversations = !1, this.selectedConversationIds.clear(), this.conversationError = "", this.renderPanel(!1);
831
+ }), this.panel.querySelector('[data-action="select-all-threads"]')?.addEventListener("change", (h) => {
832
+ this.selectedConversationIds = h.target.checked ? new Set(this.conversations.map((d) => d.id)) : /* @__PURE__ */ new Set();
833
+ this.renderPanel(!1);
834
+ }), this.panel.querySelector('[data-action="delete-selected-threads"]')?.addEventListener("click", () => void this.deleteSelectedConversations()), this.panel.querySelectorAll("[data-select-thread]").forEach((h) => {
835
+ h.addEventListener("change", () => {
836
+ h.checked ? this.selectedConversationIds.add(h.dataset.selectThread) : this.selectedConversationIds.delete(h.dataset.selectThread);
837
+ this.renderPanel(!1);
745
838
  });
746
839
  }), (w = this.panel) == null || w.querySelectorAll("[data-delete-thread]").forEach((h) => {
747
840
  h.addEventListener("click", (d) => {
@@ -769,6 +862,12 @@ class V {
769
862
  const d = h;
770
863
  d.key === "Enter" && !d.shiftKey && (d.preventDefault(), (f = (u = this.panel) == null ? void 0 : u.querySelector("form")) == null || f.requestSubmit());
771
864
  });
865
+ this.panel.querySelectorAll("[data-delete-source]").forEach((button) => {
866
+ button.addEventListener("click", () => {
867
+ const snapshot = this.sourceSnapshots.find((item) => this.sourceSnapshotValue(item) === button.dataset.deleteSource);
868
+ if (snapshot) this.deleteSourceSnapshot(snapshot);
869
+ });
870
+ });
772
871
  }
773
872
  }
774
873
  function l(a) {
package/dist/types.d.ts CHANGED
@@ -90,6 +90,7 @@ export interface SourceSnapshot {
90
90
  filename?: string | null;
91
91
  archive_bytes?: number;
92
92
  status: string;
93
+ in_use_reason?: 'default' | 'conversation' | null;
93
94
  message?: string | null;
94
95
  file_count: number;
95
96
  total_bytes?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pageops/sdk",
3
- "version": "0.1.38",
3
+ "version": "0.1.40",
4
4
  "description": "PageOps embeddable frontend SDK",
5
5
  "type": "module",
6
6
  "main": "dist/pageops-sdk.umd.cjs",