@pageops/sdk 0.1.37 → 0.1.39
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 +5 -0
- package/dist/client.d.ts +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/pageops-sdk.css +40 -0
- package/dist/pageops-sdk.es.js +58 -34
- package/dist/pageops-sdk.umd.cjs +58 -34
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,6 +12,11 @@ from the right-side `steps` contract. The middle timeline no longer re-renders
|
|
|
12
12
|
the execution cards; it receives only selected model decisions and evidence
|
|
13
13
|
activities shaped by the backend thought presenter.
|
|
14
14
|
|
|
15
|
+
Version `0.1.38` hides node progress in the right sidebar and keeps it only
|
|
16
|
+
inside chat answers, including live updates and historical Run selection. The
|
|
17
|
+
sidebar source-package controls remain available; backend step data is retained
|
|
18
|
+
for cancellation and history.
|
|
19
|
+
|
|
15
20
|
`src/index.js` is the readable ESM runtime baseline, `src/styles.css` preserves
|
|
16
21
|
the 0.1.34 styles, and `src/extensions.css` contains the new non-minified style
|
|
17
22
|
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;
|
|
@@ -89,11 +91,9 @@ declare class PageOpsSDKController {
|
|
|
89
91
|
private renderMessage;
|
|
90
92
|
private renderSourceUploader;
|
|
91
93
|
private renderSourceItem;
|
|
92
|
-
private renderSteps;
|
|
93
94
|
private renderThinkingProcess;
|
|
94
95
|
private renderThinkingSteps;
|
|
95
96
|
private renderThinkingTimeline;
|
|
96
|
-
private renderExecutionSteps;
|
|
97
97
|
private bindPanelEvents;
|
|
98
98
|
}
|
|
99
99
|
export declare const PageOpsSDK: PageOpsSDKController;
|
package/dist/pageops-sdk.css
CHANGED
|
@@ -140,3 +140,43 @@
|
|
|
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
|
+
}
|
package/dist/pageops-sdk.es.js
CHANGED
|
@@ -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", "");
|
|
@@ -233,7 +239,7 @@ class V {
|
|
|
233
239
|
}
|
|
234
240
|
unmount() {
|
|
235
241
|
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";
|
|
242
|
+
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.deletingSourceId = "", this.developerAccess = !1, this.activeQuestionStartedAt = "", this.answerAudience = "developer";
|
|
237
243
|
}
|
|
238
244
|
open() {
|
|
239
245
|
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());
|
|
@@ -437,6 +443,28 @@ class V {
|
|
|
437
443
|
}
|
|
438
444
|
}
|
|
439
445
|
}
|
|
446
|
+
async deleteSourceSnapshot(e) {
|
|
447
|
+
if (!this.client || this.asking || this.sourceUploading || this.deletingSourceId) return;
|
|
448
|
+
const id = this.sourceSnapshotValue(e);
|
|
449
|
+
const selected = this.selectedSourceSnapshot();
|
|
450
|
+
if (!id || e.in_use_reason || selected && this.sourceSnapshotValue(selected) === id) return;
|
|
451
|
+
const name = e.filename || `代码包 ${id}`;
|
|
452
|
+
if (!window.confirm(`确定删除历史代码包“${name}”吗?代码索引和存储文件将一并清理,此操作无法撤销。`)) return;
|
|
453
|
+
this.deletingSourceId = id;
|
|
454
|
+
this.sourceUploadError = "";
|
|
455
|
+
this.renderPanel();
|
|
456
|
+
try {
|
|
457
|
+
const result = await this.client.deleteSource(id);
|
|
458
|
+
this.sourceSnapshots = this.sourceSnapshots.filter((item) => this.sourceSnapshotValue(item) !== id);
|
|
459
|
+
this.sourceUploadError = result.warning || "";
|
|
460
|
+
await this.loadSources();
|
|
461
|
+
} catch (error) {
|
|
462
|
+
this.sourceUploadError = error instanceof Error ? error.message : "删除代码包失败";
|
|
463
|
+
} finally {
|
|
464
|
+
this.deletingSourceId = "";
|
|
465
|
+
this.renderPanel();
|
|
466
|
+
}
|
|
467
|
+
}
|
|
440
468
|
async ask(e) {
|
|
441
469
|
if (!this.client || this.asking) return;
|
|
442
470
|
const t = this.questionUnavailableReason();
|
|
@@ -479,10 +507,18 @@ class V {
|
|
|
479
507
|
this.typewriter.clear(), this.waitingForFirstContent = !1, (t = this.abortController) == null || t.abort(), this.abortController = null, e && this.renderPanel();
|
|
480
508
|
}
|
|
481
509
|
}
|
|
510
|
+
/**
|
|
511
|
+
* Consume an SSE event without duplicating node progress in the sidebar.
|
|
512
|
+
* Full steps remain available for cancellation; public thoughts update only
|
|
513
|
+
* the answer-local timeline. This method does not make remote requests.
|
|
514
|
+
* @param {string} e Backend event name.
|
|
515
|
+
* @param {object} t Event payload for steps, thoughts, content or completion.
|
|
516
|
+
* @returns {void}
|
|
517
|
+
*/
|
|
482
518
|
handleStreamEvent(e, t) {
|
|
483
519
|
var s, r;
|
|
484
520
|
if (e === "step") {
|
|
485
|
-
this.upsertStep(t)
|
|
521
|
+
this.upsertStep(t);
|
|
486
522
|
return;
|
|
487
523
|
}
|
|
488
524
|
if (e === "thought") {
|
|
@@ -587,7 +623,14 @@ class V {
|
|
|
587
623
|
stopSourceRefresh() {
|
|
588
624
|
this.sourceRefreshTimer && clearTimeout(this.sourceRefreshTimer), this.sourceRefreshTimer = null;
|
|
589
625
|
}
|
|
590
|
-
|
|
626
|
+
/**
|
|
627
|
+
* Recreate the chat shell and source controls while keeping progress in answers.
|
|
628
|
+
* Preserve chat scroll unless following the active answer; bind DOM listeners
|
|
629
|
+
* after replacement. The sidebar contains no node progress or auto-scroll.
|
|
630
|
+
* @param {boolean} e Whether to scroll the chat to its latest message.
|
|
631
|
+
* @returns {void} No-op when the SDK panel is closed; no remote requests.
|
|
632
|
+
*/
|
|
633
|
+
renderPanel(e = this.asking) {
|
|
591
634
|
var g;
|
|
592
635
|
if (!this.panel) return;
|
|
593
636
|
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) => `
|
|
@@ -618,7 +661,7 @@ class V {
|
|
|
618
661
|
</section>
|
|
619
662
|
<form class="po-composer"><textarea ${c ? "disabled" : ""} placeholder="${l(n)}"></textarea>${p}</form>
|
|
620
663
|
</main>
|
|
621
|
-
<aside class="po-trace"><header><h2>执行过程</h2><button data-action="close">×</button></header><section>${this.renderSourceUploader()}
|
|
664
|
+
<aside class="po-trace"><header><h2>执行过程</h2><button data-action="close">×</button></header><section>${this.renderSourceUploader()}</section></aside>
|
|
622
665
|
`, this.bindPanelEvents(), e) {
|
|
623
666
|
const o = this.panel.querySelector(".po-messages");
|
|
624
667
|
o && (o.scrollTop = o.scrollHeight);
|
|
@@ -626,10 +669,6 @@ class V {
|
|
|
626
669
|
const o = this.panel.querySelector(".po-messages");
|
|
627
670
|
o && (o.scrollTop = s);
|
|
628
671
|
}
|
|
629
|
-
if (t) {
|
|
630
|
-
const o = this.panel.querySelector(".po-trace > section");
|
|
631
|
-
o && (o.scrollTop = o.scrollHeight);
|
|
632
|
-
}
|
|
633
672
|
}
|
|
634
673
|
renderAnswerState() {
|
|
635
674
|
const n = messageTime(this.activeQuestionStartedAt), c = this.renderThinkingProcess(), e = this.asking && this.waitingForFirstContent ? `<article class="po-message assistant waiting" role="status" aria-live="polite">${n}<b>PageOps 分析</b><div class="po-ai-waiting"><span class="po-ai-spinner" aria-hidden="true"></span><span>正在理解问题并检索证据</span></div>${c}</article>` : "", t = this.streaming ? `<article class="po-message assistant streaming">${n}<b>PageOps 分析</b><div><span data-streaming-content>${R(this.streaming)}</span>${this.asking ? '<span class="po-typing-cursor" aria-hidden="true"></span>' : ""}</div>${c}</article>` : "", s = this.answerError ? `<article class="po-message assistant answer-error" role="alert">${n}<b>PageOps 分析</b><strong>本次回答失败</strong><div>${l(this.answerError)}</div></article>` : "", r = this.answerStopped ? '<div class="po-stream-stopped" role="status">已停止输出</div>' : "";
|
|
@@ -681,21 +720,11 @@ class V {
|
|
|
681
720
|
renderSourceItem(e) {
|
|
682
721
|
var w, b, S, $, E, A, T;
|
|
683
722
|
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 : "项目记忆状态未知";
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
const s = (c = t.metrics) != null && c.length ? `<div class="po-step-metrics">${t.metrics.map((g) => `<span>${l(g)}</span>`).join("")}</div>` : "", r = (p = t.details) != null && p.length ? `<div class="po-step-details">${t.details.map((g) => `<div><span>${l(g.label)}</span><p>${l(g.value)}</p></div>`).join("")}</div>` : "", n = !!(s || r);
|
|
690
|
-
return `<details class="po-step ${t.status}" ${t.status === "running" || t.status === "failed" ? "open" : ""} ${n ? "" : "data-static"}>
|
|
691
|
-
<summary>
|
|
692
|
-
<span class="po-step-dot" aria-hidden="true"></span>
|
|
693
|
-
<span class="po-step-copy"><strong>${l(t.title)}</strong><small>${l((m = t.summary) != null ? m : "")}</small>${s}</span>
|
|
694
|
-
<span class="po-step-status">${Z(t.status)}</span>
|
|
695
|
-
</summary>
|
|
696
|
-
${r}
|
|
697
|
-
</details>`;
|
|
698
|
-
}).join("");
|
|
723
|
+
const id = this.sourceSnapshotValue(e), selected = this.selectedSourceSnapshot(), current = selected && this.sourceSnapshotValue(selected) === id;
|
|
724
|
+
const reason = current ? "当前问答引用" : e.in_use_reason === "default" ? "默认问答引用" : e.in_use_reason === "conversation" ? "已有会话引用" : "";
|
|
725
|
+
const deleting = this.deletingSourceId === id;
|
|
726
|
+
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>`;
|
|
727
|
+
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>`;
|
|
699
728
|
}
|
|
700
729
|
renderThinkingProcess() {
|
|
701
730
|
if (!this.asking && !this.thoughts.length && !this.runLoading && !this.runLoadError) return "";
|
|
@@ -716,14 +745,6 @@ class V {
|
|
|
716
745
|
var e;
|
|
717
746
|
(e = this.panel) == null || e.querySelectorAll(".po-thinking-content").forEach((t) => t.innerHTML = this.renderThinkingSteps());
|
|
718
747
|
}
|
|
719
|
-
renderExecutionSteps(e = !1) {
|
|
720
|
-
var s, r;
|
|
721
|
-
const t = (s = this.panel) == null ? void 0 : s.querySelector(".po-steps");
|
|
722
|
-
if (t && (t.innerHTML = this.renderSteps(), e)) {
|
|
723
|
-
const n = (r = this.panel) == null ? void 0 : r.querySelector(".po-trace > section");
|
|
724
|
-
n && (n.scrollTop = n.scrollHeight);
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
748
|
bindPanelEvents() {
|
|
728
749
|
var e, t, s, r, n, c, p, m, g, o, y, w, b, S, $, E, A, T, h, d;
|
|
729
750
|
(t = (e = this.panel) == null ? void 0 : e.querySelector('[data-action="new"]')) == null || t.addEventListener("click", () => void this.newConversation()), (r = (s = this.panel) == null ? void 0 : s.querySelector('[data-action="close"]')) == null || r.addEventListener("click", () => this.close()), (c = (n = this.panel) == null ? void 0 : n.querySelector('[data-action="stop-answer"]')) == null || c.addEventListener("click", () => this.cancelActiveAnswer(!0)), (p = this.panel) == null || p.querySelectorAll("[data-audience]").forEach((h) => {
|
|
@@ -780,6 +801,12 @@ class V {
|
|
|
780
801
|
const d = h;
|
|
781
802
|
d.key === "Enter" && !d.shiftKey && (d.preventDefault(), (f = (u = this.panel) == null ? void 0 : u.querySelector("form")) == null || f.requestSubmit());
|
|
782
803
|
});
|
|
804
|
+
this.panel.querySelectorAll("[data-delete-source]").forEach((button) => {
|
|
805
|
+
button.addEventListener("click", () => {
|
|
806
|
+
const snapshot = this.sourceSnapshots.find((item) => this.sourceSnapshotValue(item) === button.dataset.deleteSource);
|
|
807
|
+
if (snapshot) this.deleteSourceSnapshot(snapshot);
|
|
808
|
+
});
|
|
809
|
+
});
|
|
783
810
|
}
|
|
784
811
|
}
|
|
785
812
|
function l(a) {
|
|
@@ -842,9 +869,6 @@ function G(a) {
|
|
|
842
869
|
t /= 1024, s += 1;
|
|
843
870
|
return `${t >= 10 || s === 0 ? t.toFixed(0) : t.toFixed(1)} ${e[s]}`;
|
|
844
871
|
}
|
|
845
|
-
function Z(a) {
|
|
846
|
-
return { pending: "等待中", running: "执行中", completed: "已完成", failed: "失败", cancelled: "已停止" }[a];
|
|
847
|
-
}
|
|
848
872
|
const Y = new V();
|
|
849
873
|
export {
|
|
850
874
|
Y as PageOpsSDK
|
package/dist/pageops-sdk.umd.cjs
CHANGED
|
@@ -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", "");
|
|
@@ -233,7 +239,7 @@ class V {
|
|
|
233
239
|
}
|
|
234
240
|
unmount() {
|
|
235
241
|
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";
|
|
242
|
+
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.deletingSourceId = "", this.developerAccess = !1, this.activeQuestionStartedAt = "", this.answerAudience = "developer";
|
|
237
243
|
}
|
|
238
244
|
open() {
|
|
239
245
|
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());
|
|
@@ -437,6 +443,28 @@ class V {
|
|
|
437
443
|
}
|
|
438
444
|
}
|
|
439
445
|
}
|
|
446
|
+
async deleteSourceSnapshot(e) {
|
|
447
|
+
if (!this.client || this.asking || this.sourceUploading || this.deletingSourceId) return;
|
|
448
|
+
const id = this.sourceSnapshotValue(e);
|
|
449
|
+
const selected = this.selectedSourceSnapshot();
|
|
450
|
+
if (!id || e.in_use_reason || selected && this.sourceSnapshotValue(selected) === id) return;
|
|
451
|
+
const name = e.filename || `代码包 ${id}`;
|
|
452
|
+
if (!window.confirm(`确定删除历史代码包“${name}”吗?代码索引和存储文件将一并清理,此操作无法撤销。`)) return;
|
|
453
|
+
this.deletingSourceId = id;
|
|
454
|
+
this.sourceUploadError = "";
|
|
455
|
+
this.renderPanel();
|
|
456
|
+
try {
|
|
457
|
+
const result = await this.client.deleteSource(id);
|
|
458
|
+
this.sourceSnapshots = this.sourceSnapshots.filter((item) => this.sourceSnapshotValue(item) !== id);
|
|
459
|
+
this.sourceUploadError = result.warning || "";
|
|
460
|
+
await this.loadSources();
|
|
461
|
+
} catch (error) {
|
|
462
|
+
this.sourceUploadError = error instanceof Error ? error.message : "删除代码包失败";
|
|
463
|
+
} finally {
|
|
464
|
+
this.deletingSourceId = "";
|
|
465
|
+
this.renderPanel();
|
|
466
|
+
}
|
|
467
|
+
}
|
|
440
468
|
async ask(e) {
|
|
441
469
|
if (!this.client || this.asking) return;
|
|
442
470
|
const t = this.questionUnavailableReason();
|
|
@@ -479,10 +507,18 @@ class V {
|
|
|
479
507
|
this.typewriter.clear(), this.waitingForFirstContent = !1, (t = this.abortController) == null || t.abort(), this.abortController = null, e && this.renderPanel();
|
|
480
508
|
}
|
|
481
509
|
}
|
|
510
|
+
/**
|
|
511
|
+
* Consume an SSE event without duplicating node progress in the sidebar.
|
|
512
|
+
* Full steps remain available for cancellation; public thoughts update only
|
|
513
|
+
* the answer-local timeline. This method does not make remote requests.
|
|
514
|
+
* @param {string} e Backend event name.
|
|
515
|
+
* @param {object} t Event payload for steps, thoughts, content or completion.
|
|
516
|
+
* @returns {void}
|
|
517
|
+
*/
|
|
482
518
|
handleStreamEvent(e, t) {
|
|
483
519
|
var s, r;
|
|
484
520
|
if (e === "step") {
|
|
485
|
-
this.upsertStep(t)
|
|
521
|
+
this.upsertStep(t);
|
|
486
522
|
return;
|
|
487
523
|
}
|
|
488
524
|
if (e === "thought") {
|
|
@@ -587,7 +623,14 @@ class V {
|
|
|
587
623
|
stopSourceRefresh() {
|
|
588
624
|
this.sourceRefreshTimer && clearTimeout(this.sourceRefreshTimer), this.sourceRefreshTimer = null;
|
|
589
625
|
}
|
|
590
|
-
|
|
626
|
+
/**
|
|
627
|
+
* Recreate the chat shell and source controls while keeping progress in answers.
|
|
628
|
+
* Preserve chat scroll unless following the active answer; bind DOM listeners
|
|
629
|
+
* after replacement. The sidebar contains no node progress or auto-scroll.
|
|
630
|
+
* @param {boolean} e Whether to scroll the chat to its latest message.
|
|
631
|
+
* @returns {void} No-op when the SDK panel is closed; no remote requests.
|
|
632
|
+
*/
|
|
633
|
+
renderPanel(e = this.asking) {
|
|
591
634
|
var g;
|
|
592
635
|
if (!this.panel) return;
|
|
593
636
|
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) => `
|
|
@@ -618,7 +661,7 @@ class V {
|
|
|
618
661
|
</section>
|
|
619
662
|
<form class="po-composer"><textarea ${c ? "disabled" : ""} placeholder="${l(n)}"></textarea>${p}</form>
|
|
620
663
|
</main>
|
|
621
|
-
<aside class="po-trace"><header><h2>执行过程</h2><button data-action="close">×</button></header><section>${this.renderSourceUploader()}
|
|
664
|
+
<aside class="po-trace"><header><h2>执行过程</h2><button data-action="close">×</button></header><section>${this.renderSourceUploader()}</section></aside>
|
|
622
665
|
`, this.bindPanelEvents(), e) {
|
|
623
666
|
const o = this.panel.querySelector(".po-messages");
|
|
624
667
|
o && (o.scrollTop = o.scrollHeight);
|
|
@@ -626,10 +669,6 @@ class V {
|
|
|
626
669
|
const o = this.panel.querySelector(".po-messages");
|
|
627
670
|
o && (o.scrollTop = s);
|
|
628
671
|
}
|
|
629
|
-
if (t) {
|
|
630
|
-
const o = this.panel.querySelector(".po-trace > section");
|
|
631
|
-
o && (o.scrollTop = o.scrollHeight);
|
|
632
|
-
}
|
|
633
672
|
}
|
|
634
673
|
renderAnswerState() {
|
|
635
674
|
const n = messageTime(this.activeQuestionStartedAt), c = this.renderThinkingProcess(), e = this.asking && this.waitingForFirstContent ? `<article class="po-message assistant waiting" role="status" aria-live="polite">${n}<b>PageOps 分析</b><div class="po-ai-waiting"><span class="po-ai-spinner" aria-hidden="true"></span><span>正在理解问题并检索证据</span></div>${c}</article>` : "", t = this.streaming ? `<article class="po-message assistant streaming">${n}<b>PageOps 分析</b><div><span data-streaming-content>${R(this.streaming)}</span>${this.asking ? '<span class="po-typing-cursor" aria-hidden="true"></span>' : ""}</div>${c}</article>` : "", s = this.answerError ? `<article class="po-message assistant answer-error" role="alert">${n}<b>PageOps 分析</b><strong>本次回答失败</strong><div>${l(this.answerError)}</div></article>` : "", r = this.answerStopped ? '<div class="po-stream-stopped" role="status">已停止输出</div>' : "";
|
|
@@ -681,21 +720,11 @@ class V {
|
|
|
681
720
|
renderSourceItem(e) {
|
|
682
721
|
var w, b, S, $, E, A, T;
|
|
683
722
|
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 : "项目记忆状态未知";
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
const s = (c = t.metrics) != null && c.length ? `<div class="po-step-metrics">${t.metrics.map((g) => `<span>${l(g)}</span>`).join("")}</div>` : "", r = (p = t.details) != null && p.length ? `<div class="po-step-details">${t.details.map((g) => `<div><span>${l(g.label)}</span><p>${l(g.value)}</p></div>`).join("")}</div>` : "", n = !!(s || r);
|
|
690
|
-
return `<details class="po-step ${t.status}" ${t.status === "running" || t.status === "failed" ? "open" : ""} ${n ? "" : "data-static"}>
|
|
691
|
-
<summary>
|
|
692
|
-
<span class="po-step-dot" aria-hidden="true"></span>
|
|
693
|
-
<span class="po-step-copy"><strong>${l(t.title)}</strong><small>${l((m = t.summary) != null ? m : "")}</small>${s}</span>
|
|
694
|
-
<span class="po-step-status">${Z(t.status)}</span>
|
|
695
|
-
</summary>
|
|
696
|
-
${r}
|
|
697
|
-
</details>`;
|
|
698
|
-
}).join("");
|
|
723
|
+
const id = this.sourceSnapshotValue(e), selected = this.selectedSourceSnapshot(), current = selected && this.sourceSnapshotValue(selected) === id;
|
|
724
|
+
const reason = current ? "当前问答引用" : e.in_use_reason === "default" ? "默认问答引用" : e.in_use_reason === "conversation" ? "已有会话引用" : "";
|
|
725
|
+
const deleting = this.deletingSourceId === id;
|
|
726
|
+
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>`;
|
|
727
|
+
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>`;
|
|
699
728
|
}
|
|
700
729
|
renderThinkingProcess() {
|
|
701
730
|
if (!this.asking && !this.thoughts.length && !this.runLoading && !this.runLoadError) return "";
|
|
@@ -716,14 +745,6 @@ class V {
|
|
|
716
745
|
var e;
|
|
717
746
|
(e = this.panel) == null || e.querySelectorAll(".po-thinking-content").forEach((t) => t.innerHTML = this.renderThinkingSteps());
|
|
718
747
|
}
|
|
719
|
-
renderExecutionSteps(e = !1) {
|
|
720
|
-
var s, r;
|
|
721
|
-
const t = (s = this.panel) == null ? void 0 : s.querySelector(".po-steps");
|
|
722
|
-
if (t && (t.innerHTML = this.renderSteps(), e)) {
|
|
723
|
-
const n = (r = this.panel) == null ? void 0 : r.querySelector(".po-trace > section");
|
|
724
|
-
n && (n.scrollTop = n.scrollHeight);
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
748
|
bindPanelEvents() {
|
|
728
749
|
var e, t, s, r, n, c, p, m, g, o, y, w, b, S, $, E, A, T, h, d;
|
|
729
750
|
(t = (e = this.panel) == null ? void 0 : e.querySelector('[data-action="new"]')) == null || t.addEventListener("click", () => void this.newConversation()), (r = (s = this.panel) == null ? void 0 : s.querySelector('[data-action="close"]')) == null || r.addEventListener("click", () => this.close()), (c = (n = this.panel) == null ? void 0 : n.querySelector('[data-action="stop-answer"]')) == null || c.addEventListener("click", () => this.cancelActiveAnswer(!0)), (p = this.panel) == null || p.querySelectorAll("[data-audience]").forEach((h) => {
|
|
@@ -780,6 +801,12 @@ class V {
|
|
|
780
801
|
const d = h;
|
|
781
802
|
d.key === "Enter" && !d.shiftKey && (d.preventDefault(), (f = (u = this.panel) == null ? void 0 : u.querySelector("form")) == null || f.requestSubmit());
|
|
782
803
|
});
|
|
804
|
+
this.panel.querySelectorAll("[data-delete-source]").forEach((button) => {
|
|
805
|
+
button.addEventListener("click", () => {
|
|
806
|
+
const snapshot = this.sourceSnapshots.find((item) => this.sourceSnapshotValue(item) === button.dataset.deleteSource);
|
|
807
|
+
if (snapshot) this.deleteSourceSnapshot(snapshot);
|
|
808
|
+
});
|
|
809
|
+
});
|
|
783
810
|
}
|
|
784
811
|
}
|
|
785
812
|
function l(a) {
|
|
@@ -842,8 +869,5 @@ function G(a) {
|
|
|
842
869
|
t /= 1024, s += 1;
|
|
843
870
|
return `${t >= 10 || s === 0 ? t.toFixed(0) : t.toFixed(1)} ${e[s]}`;
|
|
844
871
|
}
|
|
845
|
-
function Z(a) {
|
|
846
|
-
return { pending: "等待中", running: "执行中", completed: "已完成", failed: "失败", cancelled: "已停止" }[a];
|
|
847
|
-
}
|
|
848
872
|
const Y = new V();
|
|
849
873
|
exports.PageOpsSDK=Y;}));
|
package/dist/types.d.ts
CHANGED