@pageops/sdk 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import type { ContextSession, ConversationMessage, ConversationThread, PageOpsMountOptions, SourceSnapshot } from './types';
1
+ import type { ContextSession, ConversationMessage, ConversationThread, PageOpsContext, PageOpsMountOptions, SourceSnapshot } from './types';
2
2
  export declare class PageOpsClient {
3
3
  private options;
4
4
  constructor(options: PageOpsMountOptions);
5
- createContext(): Promise<ContextSession>;
5
+ createContext(context?: PageOpsContext): Promise<ContextSession>;
6
6
  listConversations(): Promise<ConversationThread[]>;
7
7
  createConversation(contextSessionId: string, title?: string): Promise<ConversationThread>;
8
8
  listMessages(threadId: string): Promise<ConversationMessage[]>;
package/dist/index.d.ts CHANGED
@@ -6,6 +6,8 @@ declare class PageOpsSDKController {
6
6
  private root;
7
7
  private panel;
8
8
  private context;
9
+ private contextKey;
10
+ private selectedPageKey;
9
11
  private currentThread;
10
12
  private conversations;
11
13
  private messages;
@@ -22,6 +24,8 @@ declare class PageOpsSDKController {
22
24
  updateContext(options: Partial<PageOpsMountOptions>): void;
23
25
  private renderClosed;
24
26
  private ensureContext;
27
+ private getPageContext;
28
+ private getPageContextKey;
25
29
  private loadSources;
26
30
  private loadConversations;
27
31
  private newConversation;
@@ -1,13 +1,12 @@
1
- var w = Object.defineProperty;
2
- var x = (r, t, e) => t in r ? w(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
3
- var a = (r, t, e) => x(r, typeof t != "symbol" ? t + "" : t, e);
4
- class S {
1
+ var P = Object.defineProperty;
2
+ var w = (i, t, e) => t in i ? P(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e;
3
+ var c = (i, t, e) => w(i, typeof t != "symbol" ? t + "" : t, e);
4
+ class $ {
5
5
  constructor(t) {
6
6
  this.options = t;
7
7
  }
8
- async createContext() {
9
- var e, s, o, n, c;
10
- const t = (o = (s = (e = this.options).getPageContext) == null ? void 0 : s.call(e)) != null ? o : {};
8
+ async createContext(t = ((o) => (o = ((e) => ((s) => (s = (e = this.options).getPageContext) == null ? void 0 : s.call(e))())()) != null ? o : {})()) {
9
+ var n, r, l;
11
10
  return this.request("/context/session", {
12
11
  method: "POST",
13
12
  body: JSON.stringify({
@@ -15,7 +14,8 @@ class S {
15
14
  env: this.options.env,
16
15
  route: t.route,
17
16
  url: (n = t.url) != null ? n : location.href,
18
- title: (c = t.title) != null ? c : document.title,
17
+ title: (r = t.title) != null ? r : document.title,
18
+ menu_path: (l = t.menuPath) != null ? l : [],
19
19
  tenant_id: t.tenantId,
20
20
  user_role: t.userRole,
21
21
  build_version: t.buildVersion
@@ -23,16 +23,16 @@ class S {
23
23
  });
24
24
  }
25
25
  async listConversations() {
26
- return (await this.request("/conversations")).conversations;
26
+ return (await this.request(`/conversations?app_id=${encodeURIComponent(this.options.appId)}`)).conversations;
27
27
  }
28
28
  async createConversation(t, e) {
29
29
  return this.request("/conversations", {
30
30
  method: "POST",
31
- body: JSON.stringify({ context_session_id: t, title: e })
31
+ body: JSON.stringify({ app_id: this.options.appId, context_session_id: t, title: e })
32
32
  });
33
33
  }
34
34
  async listMessages(t) {
35
- return (await this.request(`/conversations/${encodeURIComponent(t)}/messages`)).messages;
35
+ return (await this.request(`/conversations/${encodeURIComponent(t)}/messages?app_id=${encodeURIComponent(this.options.appId)}`)).messages;
36
36
  }
37
37
  async listSources() {
38
38
  return (await this.request(`/sources?project_id=${encodeURIComponent(this.options.appId)}`)).sources;
@@ -45,13 +45,13 @@ class S {
45
45
  return fetch(`${this.base()}/question/stream`, {
46
46
  method: "POST",
47
47
  headers: { "content-type": "application/json" },
48
- body: JSON.stringify({ thread_id: t, question: e })
48
+ body: JSON.stringify({ app_id: this.options.appId, thread_id: t, question: e })
49
49
  });
50
50
  }
51
51
  async request(t, e) {
52
- var c, h;
53
- const s = (e == null ? void 0 : e.body) instanceof FormData ? e.headers : { "content-type": "application/json", ...(c = e == null ? void 0 : e.headers) != null ? c : {} }, o = await fetch(`${this.base()}${t}`, { ...e, headers: s }), n = await o.json();
54
- if (!o.ok) throw new Error((h = n.message) != null ? h : "PageOps 请求失败");
52
+ var r, l;
53
+ const s = (e == null ? void 0 : e.body) instanceof FormData ? e.headers : { "content-type": "application/json", ...(r = e == null ? void 0 : e.headers) != null ? r : {} }, o = await fetch(`${this.base()}${t}`, { ...e, headers: s }), n = await o.json();
54
+ if (!o.ok) throw new Error((l = n.message) != null ? l : "PageOps 请求失败");
55
55
  return n;
56
56
  }
57
57
  base() {
@@ -59,27 +59,27 @@ class S {
59
59
  return t.endsWith("/api") ? t : `${t}/api`;
60
60
  }
61
61
  }
62
- function E(r) {
63
- return r.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
62
+ function x(i) {
63
+ return i.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
64
64
  }
65
- function f(r) {
66
- return E(r).replace(/`([^`]+)`/g, "<code>$1</code>").replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>");
65
+ function f(i) {
66
+ return x(i).replace(/`([^`]+)`/g, "<code>$1</code>").replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>");
67
67
  }
68
- function P(r, t) {
69
- const e = r[t], s = r[t + 1];
68
+ function C(i, t) {
69
+ const e = i[t], s = i[t + 1];
70
70
  if (!(e != null && e.includes("|")) || !/^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)+\|?\s*$/.test(s != null ? s : "")) return null;
71
71
  const o = [];
72
72
  let n = t;
73
- for (; n < r.length && r[n].includes("|") && r[n].trim(); )
74
- o.push(r[n]), n += 1;
75
- const c = (d) => d.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map((m) => f(m.trim())), h = c(o[0]).map((d) => `<th>${d}</th>`).join(""), g = o.slice(2).map((d) => `<tr>${c(d).map((m) => `<td>${m}</td>`).join("")}</tr>`).join("");
76
- return { html: `<table><thead><tr>${h}</tr></thead><tbody>${g}</tbody></table>`, next: n };
73
+ for (; n < i.length && i[n].includes("|") && i[n].trim(); )
74
+ o.push(i[n]), n += 1;
75
+ const r = (d) => d.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map((g) => f(g.trim())), l = r(o[0]).map((d) => `<th>${d}</th>`).join(""), m = o.slice(2).map((d) => `<tr>${r(d).map((g) => `<td>${g}</td>`).join("")}</tr>`).join("");
76
+ return { html: `<table><thead><tr>${l}</tr></thead><tbody>${m}</tbody></table>`, next: n };
77
77
  }
78
- function b(r) {
79
- const t = r.split(`
78
+ function S(i) {
79
+ const t = i.split(`
80
80
  `), e = [];
81
81
  for (let s = 0; s < t.length; s += 1) {
82
- const o = P(t, s);
82
+ const o = C(t, s);
83
83
  if (o) {
84
84
  e.push(o.html), s = o.next - 1;
85
85
  continue;
@@ -89,48 +89,50 @@ function b(r) {
89
89
  }
90
90
  return e.join("");
91
91
  }
92
- async function T(r, t) {
93
- var n, c, h;
94
- const e = r.getReader(), s = new TextDecoder();
92
+ async function E(i, t) {
93
+ var n, r, l;
94
+ const e = i.getReader(), s = new TextDecoder();
95
95
  let o = "";
96
96
  for (; ; ) {
97
- const { done: g, value: d } = await e.read();
98
- if (g) break;
97
+ const { done: m, value: d } = await e.read();
98
+ if (m) break;
99
99
  o += s.decode(d, { stream: !0 });
100
- const m = o.split(`
100
+ const g = o.split(`
101
101
 
102
102
  `);
103
- o = (n = m.pop()) != null ? n : "";
104
- for (const v of m) {
105
- const l = (c = v.match(/^event: (.+)$/m)) == null ? void 0 : c[1], i = (h = v.match(/^data: (.+)$/m)) == null ? void 0 : h[1];
106
- l && i && t(l, JSON.parse(i));
103
+ o = (n = g.pop()) != null ? n : "";
104
+ for (const y of g) {
105
+ const h = (r = y.match(/^event: (.+)$/m)) == null ? void 0 : r[1], a = (l = y.match(/^data: (.+)$/m)) == null ? void 0 : l[1];
106
+ h && a && t(h, JSON.parse(a));
107
107
  }
108
108
  }
109
109
  }
110
- class U {
110
+ class T {
111
111
  constructor() {
112
- a(this, "client", null);
113
- a(this, "options", null);
114
- a(this, "root", null);
115
- a(this, "panel", null);
116
- a(this, "context", null);
117
- a(this, "currentThread", null);
118
- a(this, "conversations", []);
119
- a(this, "messages", []);
120
- a(this, "steps", []);
121
- a(this, "sourceSnapshots", []);
122
- a(this, "sourceUploadStatus", "");
123
- a(this, "sourceUploadError", "");
124
- a(this, "sourceUploading", !1);
125
- a(this, "streaming", "");
112
+ c(this, "client", null);
113
+ c(this, "options", null);
114
+ c(this, "root", null);
115
+ c(this, "panel", null);
116
+ c(this, "context", null);
117
+ c(this, "contextKey", "");
118
+ c(this, "selectedPageKey", "");
119
+ c(this, "currentThread", null);
120
+ c(this, "conversations", []);
121
+ c(this, "messages", []);
122
+ c(this, "steps", []);
123
+ c(this, "sourceSnapshots", []);
124
+ c(this, "sourceUploadStatus", "");
125
+ c(this, "sourceUploadError", "");
126
+ c(this, "sourceUploading", !1);
127
+ c(this, "streaming", "");
126
128
  }
127
129
  mount(t) {
128
130
  var e;
129
- this.unmount(), this.options = t, this.client = new S(t), this.root = document.createElement("div"), this.root.className = "pageops-sdk", ((e = t.container) != null ? e : document.body).appendChild(this.root), this.renderClosed();
131
+ this.unmount(), this.options = t, this.client = new $(t), this.root = document.createElement("div"), this.root.className = "pageops-sdk", ((e = t.container) != null ? e : document.body).appendChild(this.root), this.renderClosed();
130
132
  }
131
133
  unmount() {
132
134
  var t;
133
- (t = this.root) == null || t.remove(), this.root = null, this.panel = null, this.context = null, this.currentThread = null, this.conversations = [], this.messages = [], this.steps = [], this.sourceSnapshots = [], this.sourceUploadStatus = "", this.sourceUploadError = "", this.sourceUploading = !1, this.streaming = "";
135
+ (t = this.root) == null || t.remove(), this.root = null, this.panel = null, this.context = null, this.contextKey = "", this.selectedPageKey = "", this.currentThread = null, this.conversations = [], this.messages = [], this.steps = [], this.sourceSnapshots = [], this.sourceUploadStatus = "", this.sourceUploadError = "", this.sourceUploading = !1, this.streaming = "";
134
136
  }
135
137
  open() {
136
138
  this.root && (this.root.innerHTML = "", this.panel = document.createElement("div"), this.panel.className = "po-panel", this.root.appendChild(this.panel), this.loadSources(), this.loadConversations(), this.renderPanel());
@@ -139,16 +141,29 @@ class U {
139
141
  this.renderClosed();
140
142
  }
141
143
  updateContext(t) {
142
- this.options && (this.options = { ...this.options, ...t }, this.client = new S(this.options));
144
+ this.options && (this.options = { ...this.options, ...t }, this.client = new $(this.options), this.context = null, this.contextKey = "");
143
145
  }
144
146
  renderClosed() {
145
147
  var t;
146
148
  this.root && (this.root.innerHTML = '<button class="po-fab" type="button">多轮问答</button>', (t = this.root.querySelector("button")) == null || t.addEventListener("click", () => this.open()));
147
149
  }
148
150
  async ensureContext() {
149
- if (this.context) return this.context;
150
- if (!this.client) throw new Error("PageOps SDK 未初始化");
151
- return this.context = await this.client.createContext(), this.context;
151
+ if (!this.client || !this.options) throw new Error("PageOps SDK 未初始化");
152
+ const t = this.getPageContext(), e = this.getPageContextKey(t);
153
+ return this.context && this.contextKey === e ? this.context : (this.context = await this.client.createContext(t), this.contextKey = e, this.context);
154
+ }
155
+ getPageContext() {
156
+ var t, e, s;
157
+ return (s = (e = (t = this.options) == null ? void 0 : t.getPageContext) == null ? void 0 : e.call(t)) != null ? s : {};
158
+ }
159
+ getPageContextKey(t) {
160
+ var e, s, o, n;
161
+ return JSON.stringify([
162
+ (e = t.route) != null ? e : "",
163
+ (s = t.url) != null ? s : location.href,
164
+ (o = t.title) != null ? o : document.title,
165
+ (n = t.menuPath) != null ? n : []
166
+ ]);
152
167
  }
153
168
  async loadSources() {
154
169
  if (this.client) {
@@ -164,12 +179,13 @@ class U {
164
179
  this.client && (this.conversations = await this.client.listConversations(), this.renderPanel());
165
180
  }
166
181
  async newConversation() {
182
+ var s;
167
183
  if (!this.client) return;
168
- const t = await this.ensureContext();
169
- this.currentThread = await this.client.createConversation(t.id, t.route || document.title || "新的问答"), this.conversations = [this.currentThread, ...this.conversations], this.messages = [], this.steps = [], this.streaming = "", this.renderPanel();
184
+ const t = await this.ensureContext(), e = (s = t.menu_path) != null && s.length ? t.menu_path.join(" / ") : t.route || document.title || "新的问答";
185
+ this.currentThread = await this.client.createConversation(t.id, e), this.selectedPageKey = this.contextKey, this.conversations = [this.currentThread, ...this.conversations], this.messages = [], this.steps = [], this.streaming = "", this.renderPanel();
170
186
  }
171
187
  async selectThread(t) {
172
- this.client && (this.currentThread = t, this.messages = await this.client.listMessages(t.id), this.steps = [], this.streaming = "", this.renderPanel());
188
+ this.client && (this.currentThread = t, this.selectedPageKey = this.getPageContextKey(this.getPageContext()), this.messages = await this.client.listMessages(t.id), this.steps = [], this.streaming = "", this.renderPanel());
173
189
  }
174
190
  async uploadSource(t) {
175
191
  if (this.client) {
@@ -189,13 +205,14 @@ class U {
189
205
  this.sourceUploadError = "请先上传代码包后再提问。", this.renderPanel();
190
206
  return;
191
207
  }
192
- if (this.currentThread || await this.newConversation(), !this.currentThread) return;
208
+ const e = this.getPageContextKey(this.getPageContext());
209
+ if (this.currentThread && this.selectedPageKey && this.selectedPageKey !== e && (this.currentThread = null), this.currentThread || await this.newConversation(), !this.currentThread) return;
193
210
  this.messages.push({ id: `local-${Date.now()}`, role: "user", content: t, metadata_json: {} }), this.steps = [], this.streaming = "", this.renderPanel();
194
- const e = await this.client.streamQuestion(this.currentThread.id, t);
195
- if (!e.ok || !e.body) throw new Error("PageOps 流式问答失败");
196
- await T(e.body, (s, o) => {
197
- var n;
198
- s === "step" && this.upsertStep(o), s === "delta" && (this.streaming += String((n = o.content) != null ? n : "")), s === "done" && this.selectThread(this.currentThread), s === "error" && this.upsertStep({ id: "error", title: "执行失败", status: "failed", details: o }), this.renderPanel();
211
+ const s = await this.client.streamQuestion(this.currentThread.id, t);
212
+ if (!s.ok || !s.body) throw new Error("PageOps 流式问答失败");
213
+ await E(s.body, (o, n) => {
214
+ var r;
215
+ o === "step" && this.upsertStep(n), o === "delta" && (this.streaming += String((r = n.content) != null ? r : "")), o === "done" && this.selectThread(this.currentThread), o === "error" && this.upsertStep({ id: "error", title: "执行失败", status: "failed", details: n }), this.renderPanel();
199
216
  });
200
217
  }
201
218
  upsertStep(t) {
@@ -212,15 +229,15 @@ class U {
212
229
  var e;
213
230
  return `
214
231
  <button class="po-thread ${t.id === ((e = this.currentThread) == null ? void 0 : e.id) ? "active" : ""}" data-thread="${t.id}">
215
- <strong>${u(t.title)}</strong><span>${y(t.created_at)}</span>
232
+ <strong>${u(t.title)}</strong><span>${b(t.created_at)}</span>
216
233
  </button>`;
217
234
  }).join("")}</div>
218
235
  </aside>
219
236
  <main class="po-chat">
220
237
  <header><div><p>问数回答</p><h2>${this.currentThread ? u(this.currentThread.title) : "未选择问答"}</h2></div><span>Markdown · 流式输出</span></header>
221
238
  <section class="po-messages">
222
- ${this.messages.map((t) => `<article class="po-message ${t.role}"><b>${t.role === "user" ? "你" : "PageOps 分析"}</b><div>${t.role === "assistant" ? b(t.content) : u(t.content)}</div></article>`).join("")}
223
- ${this.streaming ? `<article class="po-message assistant streaming"><b>PageOps 分析</b><div>${b(this.streaming)}</div></article>` : ""}
239
+ ${this.messages.map((t) => `<article class="po-message ${t.role}"><b>${t.role === "user" ? "你" : "PageOps 分析"}</b><div>${t.role === "assistant" ? S(t.content) : u(t.content)}</div></article>`).join("")}
240
+ ${this.streaming ? `<article class="po-message assistant streaming"><b>PageOps 分析</b><div>${S(this.streaming)}</div></article>` : ""}
224
241
  </section>
225
242
  <form class="po-composer"><textarea ${this.sourceSnapshots.length ? "" : "disabled"} placeholder="${this.sourceSnapshots.length ? "请输入页面分析问题,Enter 发送,Shift + Enter 换行" : "请先上传代码包后再提问"}"></textarea><button type="submit" ${this.sourceSnapshots.length ? "" : "disabled"}>${this.sourceSnapshots.length ? "发送" : "请先上传代码包"}</button></form>
226
243
  </main>
@@ -243,7 +260,7 @@ class U {
243
260
  `;
244
261
  }
245
262
  renderSourceItem(t) {
246
- const e = t.filename || "未命名代码包", s = t.created_at ? y(t.created_at) : "刚刚上传", o = C(t.archive_bytes || t.total_bytes || 0);
263
+ const e = t.filename || "未命名代码包", s = t.created_at ? b(t.created_at) : "刚刚上传", o = U(t.archive_bytes || t.total_bytes || 0);
247
264
  return `<article class="po-source-item"><strong>${u(e)}</strong><span>${u(s)} · ${u(o)}</span></article>`;
248
265
  }
249
266
  renderSteps() {
@@ -253,43 +270,43 @@ class U {
253
270
  }).join("");
254
271
  }
255
272
  bindPanelEvents() {
256
- var t, e, s, o, n, c, h, g, d, m, v;
257
- (e = (t = this.panel) == null ? void 0 : t.querySelector('[data-action="new"]')) == null || e.addEventListener("click", () => void this.newConversation()), (o = (s = this.panel) == null ? void 0 : s.querySelector('[data-action="close"]')) == null || o.addEventListener("click", () => this.close()), (c = (n = this.panel) == null ? void 0 : n.querySelector('[data-action="upload-source"]')) == null || c.addEventListener("change", (l) => {
273
+ var t, e, s, o, n, r, l, m, d, g, y;
274
+ (e = (t = this.panel) == null ? void 0 : t.querySelector('[data-action="new"]')) == null || e.addEventListener("click", () => void this.newConversation()), (o = (s = this.panel) == null ? void 0 : s.querySelector('[data-action="close"]')) == null || o.addEventListener("click", () => this.close()), (r = (n = this.panel) == null ? void 0 : n.querySelector('[data-action="upload-source"]')) == null || r.addEventListener("change", (h) => {
258
275
  var p;
259
- const i = (p = l.target.files) == null ? void 0 : p[0];
260
- i && this.uploadSource(i);
261
- }), (h = this.panel) == null || h.querySelectorAll("[data-thread]").forEach((l) => {
262
- l.addEventListener("click", () => {
263
- const i = this.conversations.find((p) => p.id === l.dataset.thread);
264
- i && this.selectThread(i);
276
+ const a = (p = h.target.files) == null ? void 0 : p[0];
277
+ a && this.uploadSource(a);
278
+ }), (l = this.panel) == null || l.querySelectorAll("[data-thread]").forEach((h) => {
279
+ h.addEventListener("click", () => {
280
+ const a = this.conversations.find((p) => p.id === h.dataset.thread);
281
+ a && this.selectThread(a);
265
282
  });
266
- }), (d = (g = this.panel) == null ? void 0 : g.querySelector("form")) == null || d.addEventListener("submit", (l) => {
267
- var $;
268
- l.preventDefault();
269
- const i = ($ = this.panel) == null ? void 0 : $.querySelector("textarea"), p = i == null ? void 0 : i.value.trim();
270
- p && (i.value = "", this.ask(p));
271
- }), (v = (m = this.panel) == null ? void 0 : m.querySelector("textarea")) == null || v.addEventListener("keydown", (l) => {
272
- var p, $;
273
- const i = l;
274
- i.key === "Enter" && !i.shiftKey && (i.preventDefault(), ($ = (p = this.panel) == null ? void 0 : p.querySelector("form")) == null || $.requestSubmit());
283
+ }), (d = (m = this.panel) == null ? void 0 : m.querySelector("form")) == null || d.addEventListener("submit", (h) => {
284
+ var v;
285
+ h.preventDefault();
286
+ const a = (v = this.panel) == null ? void 0 : v.querySelector("textarea"), p = a == null ? void 0 : a.value.trim();
287
+ p && (a.value = "", this.ask(p));
288
+ }), (y = (g = this.panel) == null ? void 0 : g.querySelector("textarea")) == null || y.addEventListener("keydown", (h) => {
289
+ var p, v;
290
+ const a = h;
291
+ a.key === "Enter" && !a.shiftKey && (a.preventDefault(), (v = (p = this.panel) == null ? void 0 : p.querySelector("form")) == null || v.requestSubmit());
275
292
  });
276
293
  }
277
294
  }
278
- function u(r) {
279
- return r.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
295
+ function u(i) {
296
+ return i.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
280
297
  }
281
- function y(r) {
282
- return new Intl.DateTimeFormat("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" }).format(new Date(r));
298
+ function b(i) {
299
+ return new Intl.DateTimeFormat("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" }).format(new Date(i));
283
300
  }
284
- function C(r) {
285
- if (!r) return "0 B";
301
+ function U(i) {
302
+ if (!i) return "0 B";
286
303
  const t = ["B", "KB", "MB", "GB"];
287
- let e = r, s = 0;
304
+ let e = i, s = 0;
288
305
  for (; e >= 1024 && s < t.length - 1; )
289
306
  e /= 1024, s += 1;
290
307
  return `${e >= 10 || s === 0 ? e.toFixed(0) : e.toFixed(1)} ${t[s]}`;
291
308
  }
292
- const q = new U();
309
+ const _ = new T();
293
310
  export {
294
- q as PageOpsSDK
311
+ _ as PageOpsSDK
295
312
  };
@@ -1,21 +1,21 @@
1
- (function(h,c){typeof exports=="object"&&typeof module!="undefined"?c(exports):typeof define=="function"&&define.amd?define(["exports"],c):(h=typeof globalThis!="undefined"?globalThis:h||self,c(h.PageOpsSDK={}))})(this,(function(h){"use strict";var O=Object.defineProperty;var q=(h,c,v)=>c in h?O(h,c,{enumerable:!0,configurable:!0,writable:!0,value:v}):h[c]=v;var a=(h,c,v)=>q(h,typeof c!="symbol"?c+"":c,v);class c{constructor(t){this.options=t}async createContext(){var e,s,r,n,l;const t=(r=(s=(e=this.options).getPageContext)==null?void 0:s.call(e))!=null?r:{};return this.request("/context/session",{method:"POST",body:JSON.stringify({app_id:this.options.appId,env:this.options.env,route:t.route,url:(n=t.url)!=null?n:location.href,title:(l=t.title)!=null?l:document.title,tenant_id:t.tenantId,user_role:t.userRole,build_version:t.buildVersion})})}async listConversations(){return(await this.request("/conversations")).conversations}async createConversation(t,e){return this.request("/conversations",{method:"POST",body:JSON.stringify({context_session_id:t,title:e})})}async listMessages(t){return(await this.request(`/conversations/${encodeURIComponent(t)}/messages`)).messages}async listSources(){return(await this.request(`/sources?project_id=${encodeURIComponent(this.options.appId)}`)).sources}uploadSource(t){const e=new FormData;return e.append("file",t),this.request(`/sources/upload?project_id=${encodeURIComponent(this.options.appId)}`,{method:"POST",body:e,headers:{}})}streamQuestion(t,e){return fetch(`${this.base()}/question/stream`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({thread_id:t,question:e})})}async request(t,e){var l,u;const s=(e==null?void 0:e.body)instanceof FormData?e.headers:{"content-type":"application/json",...(l=e==null?void 0:e.headers)!=null?l:{}},r=await fetch(`${this.base()}${t}`,{...e,headers:s}),n=await r.json();if(!r.ok)throw new Error((u=n.message)!=null?u:"PageOps 请求失败");return n}base(){const t=this.options.apiBase.replace(/\/$/,"");return t.endsWith("/api")?t:`${t}/api`}}function v(o){return o.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function S(o){return v(o).replace(/`([^`]+)`/g,"<code>$1</code>").replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>")}function E(o,t){const e=o[t],s=o[t+1];if(!(e!=null&&e.includes("|"))||!/^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)+\|?\s*$/.test(s!=null?s:""))return null;const r=[];let n=t;for(;n<o.length&&o[n].includes("|")&&o[n].trim();)r.push(o[n]),n+=1;const l=m=>m.trim().replace(/^\|/,"").replace(/\|$/,"").split("|").map(g=>S(g.trim())),u=l(r[0]).map(m=>`<th>${m}</th>`).join(""),$=r.slice(2).map(m=>`<tr>${l(m).map(g=>`<td>${g}</td>`).join("")}</tr>`).join("");return{html:`<table><thead><tr>${u}</tr></thead><tbody>${$}</tbody></table>`,next:n}}function w(o){const t=o.split(`
2
- `),e=[];for(let s=0;s<t.length;s+=1){const r=E(t,s);if(r){e.push(r.html),s=r.next-1;continue}const n=t[s];n.startsWith("### ")?e.push(`<h4>${S(n.slice(4))}</h4>`):n.startsWith("## ")?e.push(`<h3>${S(n.slice(3))}</h3>`):n.startsWith("# ")?e.push(`<h2>${S(n.slice(2))}</h2>`):n.startsWith("- ")?e.push(`<li>${S(n.slice(2))}</li>`):n.trim()?e.push(`<p>${S(n)}</p>`):e.push("<br>")}return e.join("")}async function P(o,t){var n,l,u;const e=o.getReader(),s=new TextDecoder;let r="";for(;;){const{done:$,value:m}=await e.read();if($)break;r+=s.decode(m,{stream:!0});const g=r.split(`
1
+ (function(d,l){typeof exports=="object"&&typeof module!="undefined"?l(exports):typeof define=="function"&&define.amd?define(["exports"],l):(d=typeof globalThis!="undefined"?globalThis:d||self,l(d.PageOpsSDK={}))})(this,(function(d){"use strict";var K=Object.defineProperty;var O=(d,l,y)=>l in d?K(d,l,{enumerable:!0,configurable:!0,writable:!0,value:y}):d[l]=y;var c=(d,l,y)=>O(d,typeof l!="symbol"?l+"":l,y);class l{constructor(t){this.options=t}async createContext(t=(i=>(i=(e=>(s=>(s=(e=this.options).getPageContext)==null?void 0:s.call(e))())())!=null?i:{})()){var n,r,h;return this.request("/context/session",{method:"POST",body:JSON.stringify({app_id:this.options.appId,env:this.options.env,route:t.route,url:(n=t.url)!=null?n:location.href,title:(r=t.title)!=null?r:document.title,menu_path:(h=t.menuPath)!=null?h:[],tenant_id:t.tenantId,user_role:t.userRole,build_version:t.buildVersion})})}async listConversations(){return(await this.request(`/conversations?app_id=${encodeURIComponent(this.options.appId)}`)).conversations}async createConversation(t,e){return this.request("/conversations",{method:"POST",body:JSON.stringify({app_id:this.options.appId,context_session_id:t,title:e})})}async listMessages(t){return(await this.request(`/conversations/${encodeURIComponent(t)}/messages?app_id=${encodeURIComponent(this.options.appId)}`)).messages}async listSources(){return(await this.request(`/sources?project_id=${encodeURIComponent(this.options.appId)}`)).sources}uploadSource(t){const e=new FormData;return e.append("file",t),this.request(`/sources/upload?project_id=${encodeURIComponent(this.options.appId)}`,{method:"POST",body:e,headers:{}})}streamQuestion(t,e){return fetch(`${this.base()}/question/stream`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({app_id:this.options.appId,thread_id:t,question:e})})}async request(t,e){var r,h;const s=(e==null?void 0:e.body)instanceof FormData?e.headers:{"content-type":"application/json",...(r=e==null?void 0:e.headers)!=null?r:{}},i=await fetch(`${this.base()}${t}`,{...e,headers:s}),n=await i.json();if(!i.ok)throw new Error((h=n.message)!=null?h:"PageOps 请求失败");return n}base(){const t=this.options.apiBase.replace(/\/$/,"");return t.endsWith("/api")?t:`${t}/api`}}function y(o){return o.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function v(o){return y(o).replace(/`([^`]+)`/g,"<code>$1</code>").replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>")}function x(o,t){const e=o[t],s=o[t+1];if(!(e!=null&&e.includes("|"))||!/^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)+\|?\s*$/.test(s!=null?s:""))return null;const i=[];let n=t;for(;n<o.length&&o[n].includes("|")&&o[n].trim();)i.push(o[n]),n+=1;const r=g=>g.trim().replace(/^\|/,"").replace(/\|$/,"").split("|").map(f=>v(f.trim())),h=r(i[0]).map(g=>`<th>${g}</th>`).join(""),S=i.slice(2).map(g=>`<tr>${r(g).map(f=>`<td>${f}</td>`).join("")}</tr>`).join("");return{html:`<table><thead><tr>${h}</tr></thead><tbody>${S}</tbody></table>`,next:n}}function P(o){const t=o.split(`
2
+ `),e=[];for(let s=0;s<t.length;s+=1){const i=x(t,s);if(i){e.push(i.html),s=i.next-1;continue}const n=t[s];n.startsWith("### ")?e.push(`<h4>${v(n.slice(4))}</h4>`):n.startsWith("## ")?e.push(`<h3>${v(n.slice(3))}</h3>`):n.startsWith("# ")?e.push(`<h2>${v(n.slice(2))}</h2>`):n.startsWith("- ")?e.push(`<li>${v(n.slice(2))}</li>`):n.trim()?e.push(`<p>${v(n)}</p>`):e.push("<br>")}return e.join("")}async function C(o,t){var n,r,h;const e=o.getReader(),s=new TextDecoder;let i="";for(;;){const{done:S,value:g}=await e.read();if(S)break;i+=s.decode(g,{stream:!0});const f=i.split(`
3
3
 
4
- `);r=(n=g.pop())!=null?n:"";for(const y of g){const d=(l=y.match(/^event: (.+)$/m))==null?void 0:l[1],i=(u=y.match(/^data: (.+)$/m))==null?void 0:u[1];d&&i&&t(d,JSON.parse(i))}}}class T{constructor(){a(this,"client",null);a(this,"options",null);a(this,"root",null);a(this,"panel",null);a(this,"context",null);a(this,"currentThread",null);a(this,"conversations",[]);a(this,"messages",[]);a(this,"steps",[]);a(this,"sourceSnapshots",[]);a(this,"sourceUploadStatus","");a(this,"sourceUploadError","");a(this,"sourceUploading",!1);a(this,"streaming","")}mount(t){var e;this.unmount(),this.options=t,this.client=new c(t),this.root=document.createElement("div"),this.root.className="pageops-sdk",((e=t.container)!=null?e:document.body).appendChild(this.root),this.renderClosed()}unmount(){var t;(t=this.root)==null||t.remove(),this.root=null,this.panel=null,this.context=null,this.currentThread=null,this.conversations=[],this.messages=[],this.steps=[],this.sourceSnapshots=[],this.sourceUploadStatus="",this.sourceUploadError="",this.sourceUploading=!1,this.streaming=""}open(){this.root&&(this.root.innerHTML="",this.panel=document.createElement("div"),this.panel.className="po-panel",this.root.appendChild(this.panel),this.loadSources(),this.loadConversations(),this.renderPanel())}close(){this.renderClosed()}updateContext(t){this.options&&(this.options={...this.options,...t},this.client=new c(this.options))}renderClosed(){var t;this.root&&(this.root.innerHTML='<button class="po-fab" type="button">多轮问答</button>',(t=this.root.querySelector("button"))==null||t.addEventListener("click",()=>this.open()))}async ensureContext(){if(this.context)return this.context;if(!this.client)throw new Error("PageOps SDK 未初始化");return this.context=await this.client.createContext(),this.context}async loadSources(){if(this.client){try{this.sourceSnapshots=await this.client.listSources(),this.sourceUploadError=""}catch(t){this.sourceUploadError=t instanceof Error?t.message:"源码包状态加载失败"}this.renderPanel()}}async loadConversations(){this.client&&(this.conversations=await this.client.listConversations(),this.renderPanel())}async newConversation(){if(!this.client)return;const t=await this.ensureContext();this.currentThread=await this.client.createConversation(t.id,t.route||document.title||"新的问答"),this.conversations=[this.currentThread,...this.conversations],this.messages=[],this.steps=[],this.streaming="",this.renderPanel()}async selectThread(t){this.client&&(this.currentThread=t,this.messages=await this.client.listMessages(t.id),this.steps=[],this.streaming="",this.renderPanel())}async uploadSource(t){if(this.client){this.sourceUploading=!0,this.sourceUploadStatus="上传中...",this.sourceUploadError="",this.renderPanel();try{await this.client.uploadSource(t),this.sourceSnapshots=await this.client.listSources(),this.sourceUploadStatus="上传完成"}catch(e){this.sourceUploadError=e instanceof Error?e.message:"源码包上传失败",this.sourceUploadStatus=""}finally{this.sourceUploading=!1,this.renderPanel()}}}async ask(t){if(!this.client)return;if(!this.sourceSnapshots.length){this.sourceUploadError="请先上传代码包后再提问。",this.renderPanel();return}if(this.currentThread||await this.newConversation(),!this.currentThread)return;this.messages.push({id:`local-${Date.now()}`,role:"user",content:t,metadata_json:{}}),this.steps=[],this.streaming="",this.renderPanel();const e=await this.client.streamQuestion(this.currentThread.id,t);if(!e.ok||!e.body)throw new Error("PageOps 流式问答失败");await P(e.body,(s,r)=>{var n;s==="step"&&this.upsertStep(r),s==="delta"&&(this.streaming+=String((n=r.content)!=null?n:"")),s==="done"&&this.selectThread(this.currentThread),s==="error"&&this.upsertStep({id:"error",title:"执行失败",status:"failed",details:r}),this.renderPanel()})}upsertStep(t){const e=this.steps.findIndex(s=>s.id===t.id);this.steps=e===-1?[...this.steps,t]:this.steps.map(s=>s.id===t.id?{...s,...t}:s)}renderPanel(){this.panel&&(this.panel.innerHTML=`
4
+ `);i=(n=f.pop())!=null?n:"";for(const $ of f){const p=(r=$.match(/^event: (.+)$/m))==null?void 0:r[1],a=(h=$.match(/^data: (.+)$/m))==null?void 0:h[1];p&&a&&t(p,JSON.parse(a))}}}class T{constructor(){c(this,"client",null);c(this,"options",null);c(this,"root",null);c(this,"panel",null);c(this,"context",null);c(this,"contextKey","");c(this,"selectedPageKey","");c(this,"currentThread",null);c(this,"conversations",[]);c(this,"messages",[]);c(this,"steps",[]);c(this,"sourceSnapshots",[]);c(this,"sourceUploadStatus","");c(this,"sourceUploadError","");c(this,"sourceUploading",!1);c(this,"streaming","")}mount(t){var e;this.unmount(),this.options=t,this.client=new l(t),this.root=document.createElement("div"),this.root.className="pageops-sdk",((e=t.container)!=null?e:document.body).appendChild(this.root),this.renderClosed()}unmount(){var t;(t=this.root)==null||t.remove(),this.root=null,this.panel=null,this.context=null,this.contextKey="",this.selectedPageKey="",this.currentThread=null,this.conversations=[],this.messages=[],this.steps=[],this.sourceSnapshots=[],this.sourceUploadStatus="",this.sourceUploadError="",this.sourceUploading=!1,this.streaming=""}open(){this.root&&(this.root.innerHTML="",this.panel=document.createElement("div"),this.panel.className="po-panel",this.root.appendChild(this.panel),this.loadSources(),this.loadConversations(),this.renderPanel())}close(){this.renderClosed()}updateContext(t){this.options&&(this.options={...this.options,...t},this.client=new l(this.options),this.context=null,this.contextKey="")}renderClosed(){var t;this.root&&(this.root.innerHTML='<button class="po-fab" type="button">多轮问答</button>',(t=this.root.querySelector("button"))==null||t.addEventListener("click",()=>this.open()))}async ensureContext(){if(!this.client||!this.options)throw new Error("PageOps SDK 未初始化");const t=this.getPageContext(),e=this.getPageContextKey(t);return this.context&&this.contextKey===e?this.context:(this.context=await this.client.createContext(t),this.contextKey=e,this.context)}getPageContext(){var t,e,s;return(s=(e=(t=this.options)==null?void 0:t.getPageContext)==null?void 0:e.call(t))!=null?s:{}}getPageContextKey(t){var e,s,i,n;return JSON.stringify([(e=t.route)!=null?e:"",(s=t.url)!=null?s:location.href,(i=t.title)!=null?i:document.title,(n=t.menuPath)!=null?n:[]])}async loadSources(){if(this.client){try{this.sourceSnapshots=await this.client.listSources(),this.sourceUploadError=""}catch(t){this.sourceUploadError=t instanceof Error?t.message:"源码包状态加载失败"}this.renderPanel()}}async loadConversations(){this.client&&(this.conversations=await this.client.listConversations(),this.renderPanel())}async newConversation(){var s;if(!this.client)return;const t=await this.ensureContext(),e=(s=t.menu_path)!=null&&s.length?t.menu_path.join(" / "):t.route||document.title||"新的问答";this.currentThread=await this.client.createConversation(t.id,e),this.selectedPageKey=this.contextKey,this.conversations=[this.currentThread,...this.conversations],this.messages=[],this.steps=[],this.streaming="",this.renderPanel()}async selectThread(t){this.client&&(this.currentThread=t,this.selectedPageKey=this.getPageContextKey(this.getPageContext()),this.messages=await this.client.listMessages(t.id),this.steps=[],this.streaming="",this.renderPanel())}async uploadSource(t){if(this.client){this.sourceUploading=!0,this.sourceUploadStatus="上传中...",this.sourceUploadError="",this.renderPanel();try{await this.client.uploadSource(t),this.sourceSnapshots=await this.client.listSources(),this.sourceUploadStatus="上传完成"}catch(e){this.sourceUploadError=e instanceof Error?e.message:"源码包上传失败",this.sourceUploadStatus=""}finally{this.sourceUploading=!1,this.renderPanel()}}}async ask(t){if(!this.client)return;if(!this.sourceSnapshots.length){this.sourceUploadError="请先上传代码包后再提问。",this.renderPanel();return}const e=this.getPageContextKey(this.getPageContext());if(this.currentThread&&this.selectedPageKey&&this.selectedPageKey!==e&&(this.currentThread=null),this.currentThread||await this.newConversation(),!this.currentThread)return;this.messages.push({id:`local-${Date.now()}`,role:"user",content:t,metadata_json:{}}),this.steps=[],this.streaming="",this.renderPanel();const s=await this.client.streamQuestion(this.currentThread.id,t);if(!s.ok||!s.body)throw new Error("PageOps 流式问答失败");await C(s.body,(i,n)=>{var r;i==="step"&&this.upsertStep(n),i==="delta"&&(this.streaming+=String((r=n.content)!=null?r:"")),i==="done"&&this.selectThread(this.currentThread),i==="error"&&this.upsertStep({id:"error",title:"执行失败",status:"failed",details:n}),this.renderPanel()})}upsertStep(t){const e=this.steps.findIndex(s=>s.id===t.id);this.steps=e===-1?[...this.steps,t]:this.steps.map(s=>s.id===t.id?{...s,...t}:s)}renderPanel(){this.panel&&(this.panel.innerHTML=`
5
5
  <aside class="po-sidebar">
6
6
  <div class="po-brand"><div class="po-logo"></div><div><strong>PageOps 问答</strong><span>页面工程专家</span></div></div>
7
7
  <button class="po-new" data-action="new">+ 新建问答</button>
8
8
  <input class="po-search" placeholder="搜索问答" />
9
9
  <div class="po-thread-list">${this.conversations.map(t=>{var e;return`
10
10
  <button class="po-thread ${t.id===((e=this.currentThread)==null?void 0:e.id)?"active":""}" data-thread="${t.id}">
11
- <strong>${p(t.title)}</strong><span>${x(t.created_at)}</span>
11
+ <strong>${u(t.title)}</strong><span>${w(t.created_at)}</span>
12
12
  </button>`}).join("")}</div>
13
13
  </aside>
14
14
  <main class="po-chat">
15
- <header><div><p>问数回答</p><h2>${this.currentThread?p(this.currentThread.title):"未选择问答"}</h2></div><span>Markdown · 流式输出</span></header>
15
+ <header><div><p>问数回答</p><h2>${this.currentThread?u(this.currentThread.title):"未选择问答"}</h2></div><span>Markdown · 流式输出</span></header>
16
16
  <section class="po-messages">
17
- ${this.messages.map(t=>`<article class="po-message ${t.role}"><b>${t.role==="user"?"你":"PageOps 分析"}</b><div>${t.role==="assistant"?w(t.content):p(t.content)}</div></article>`).join("")}
18
- ${this.streaming?`<article class="po-message assistant streaming"><b>PageOps 分析</b><div>${w(this.streaming)}</div></article>`:""}
17
+ ${this.messages.map(t=>`<article class="po-message ${t.role}"><b>${t.role==="user"?"你":"PageOps 分析"}</b><div>${t.role==="assistant"?P(t.content):u(t.content)}</div></article>`).join("")}
18
+ ${this.streaming?`<article class="po-message assistant streaming"><b>PageOps 分析</b><div>${P(this.streaming)}</div></article>`:""}
19
19
  </section>
20
20
  <form class="po-composer"><textarea ${this.sourceSnapshots.length?"":"disabled"} placeholder="${this.sourceSnapshots.length?"请输入页面分析问题,Enter 发送,Shift + Enter 换行":"请先上传代码包后再提问"}"></textarea><button type="submit" ${this.sourceSnapshots.length?"":"disabled"}>${this.sourceSnapshots.length?"发送":"请先上传代码包"}</button></form>
21
21
  </main>
@@ -28,8 +28,8 @@
28
28
  <span>${this.sourceUploading?"上传中...":"选择代码包"}</span>
29
29
  <input type="file" accept=".zip,.tar,.gz,.tgz" data-action="upload-source" ${this.sourceUploading?"disabled":""} />
30
30
  </label>
31
- ${this.sourceUploadStatus?`<p class="po-upload-status">${p(this.sourceUploadStatus)}</p>`:""}
31
+ ${this.sourceUploadStatus?`<p class="po-upload-status">${u(this.sourceUploadStatus)}</p>`:""}
32
32
  ${this.sourceSnapshots.length?`<div class="po-source-list">${this.sourceSnapshots.map(t=>this.renderSourceItem(t)).join("")}</div>`:'<p class="po-upload-empty">当前系统暂无代码包,请先上传后再提问。</p>'}
33
- ${this.sourceUploadError?`<p class="po-upload-error">${p(this.sourceUploadError)}</p>`:""}
33
+ ${this.sourceUploadError?`<p class="po-upload-error">${u(this.sourceUploadError)}</p>`:""}
34
34
  </div>
35
- `}renderSourceItem(t){const e=t.filename||"未命名代码包",s=t.created_at?x(t.created_at):"刚刚上传",r=U(t.archive_bytes||t.total_bytes||0);return`<article class="po-source-item"><strong>${p(e)}</strong><span>${p(s)} · ${p(r)}</span></article>`}renderSteps(){return(this.steps.length?this.steps:[{id:"idle",title:"等待任务",status:"pending",details:{message:"发送消息后展示执行过程。"}}]).map(e=>{var s;return`<details class="po-step ${e.status}" ${e.status==="running"||e.status==="failed"?"open":""}><summary><strong>${p(e.title)}</strong><span>${e.status}</span></summary><pre>${p(JSON.stringify((s=e.details)!=null?s:{},null,2))}</pre></details>`}).join("")}bindPanelEvents(){var t,e,s,r,n,l,u,$,m,g,y;(e=(t=this.panel)==null?void 0:t.querySelector('[data-action="new"]'))==null||e.addEventListener("click",()=>void this.newConversation()),(r=(s=this.panel)==null?void 0:s.querySelector('[data-action="close"]'))==null||r.addEventListener("click",()=>this.close()),(l=(n=this.panel)==null?void 0:n.querySelector('[data-action="upload-source"]'))==null||l.addEventListener("change",d=>{var f;const i=(f=d.target.files)==null?void 0:f[0];i&&this.uploadSource(i)}),(u=this.panel)==null||u.querySelectorAll("[data-thread]").forEach(d=>{d.addEventListener("click",()=>{const i=this.conversations.find(f=>f.id===d.dataset.thread);i&&this.selectThread(i)})}),(m=($=this.panel)==null?void 0:$.querySelector("form"))==null||m.addEventListener("submit",d=>{var b;d.preventDefault();const i=(b=this.panel)==null?void 0:b.querySelector("textarea"),f=i==null?void 0:i.value.trim();f&&(i.value="",this.ask(f))}),(y=(g=this.panel)==null?void 0:g.querySelector("textarea"))==null||y.addEventListener("keydown",d=>{var f,b;const i=d;i.key==="Enter"&&!i.shiftKey&&(i.preventDefault(),(b=(f=this.panel)==null?void 0:f.querySelector("form"))==null||b.requestSubmit())})}}function p(o){return o.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function x(o){return new Intl.DateTimeFormat("zh-CN",{month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}).format(new Date(o))}function U(o){if(!o)return"0 B";const t=["B","KB","MB","GB"];let e=o,s=0;for(;e>=1024&&s<t.length-1;)e/=1024,s+=1;return`${e>=10||s===0?e.toFixed(0):e.toFixed(1)} ${t[s]}`}const C=new T;h.PageOpsSDK=C,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})}));
35
+ `}renderSourceItem(t){const e=t.filename||"未命名代码包",s=t.created_at?w(t.created_at):"刚刚上传",i=E(t.archive_bytes||t.total_bytes||0);return`<article class="po-source-item"><strong>${u(e)}</strong><span>${u(s)} · ${u(i)}</span></article>`}renderSteps(){return(this.steps.length?this.steps:[{id:"idle",title:"等待任务",status:"pending",details:{message:"发送消息后展示执行过程。"}}]).map(e=>{var s;return`<details class="po-step ${e.status}" ${e.status==="running"||e.status==="failed"?"open":""}><summary><strong>${u(e.title)}</strong><span>${e.status}</span></summary><pre>${u(JSON.stringify((s=e.details)!=null?s:{},null,2))}</pre></details>`}).join("")}bindPanelEvents(){var t,e,s,i,n,r,h,S,g,f,$;(e=(t=this.panel)==null?void 0:t.querySelector('[data-action="new"]'))==null||e.addEventListener("click",()=>void this.newConversation()),(i=(s=this.panel)==null?void 0:s.querySelector('[data-action="close"]'))==null||i.addEventListener("click",()=>this.close()),(r=(n=this.panel)==null?void 0:n.querySelector('[data-action="upload-source"]'))==null||r.addEventListener("change",p=>{var m;const a=(m=p.target.files)==null?void 0:m[0];a&&this.uploadSource(a)}),(h=this.panel)==null||h.querySelectorAll("[data-thread]").forEach(p=>{p.addEventListener("click",()=>{const a=this.conversations.find(m=>m.id===p.dataset.thread);a&&this.selectThread(a)})}),(g=(S=this.panel)==null?void 0:S.querySelector("form"))==null||g.addEventListener("submit",p=>{var b;p.preventDefault();const a=(b=this.panel)==null?void 0:b.querySelector("textarea"),m=a==null?void 0:a.value.trim();m&&(a.value="",this.ask(m))}),($=(f=this.panel)==null?void 0:f.querySelector("textarea"))==null||$.addEventListener("keydown",p=>{var m,b;const a=p;a.key==="Enter"&&!a.shiftKey&&(a.preventDefault(),(b=(m=this.panel)==null?void 0:m.querySelector("form"))==null||b.requestSubmit())})}}function u(o){return o.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function w(o){return new Intl.DateTimeFormat("zh-CN",{month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}).format(new Date(o))}function E(o){if(!o)return"0 B";const t=["B","KB","MB","GB"];let e=o,s=0;for(;e>=1024&&s<t.length-1;)e/=1024,s+=1;return`${e>=10||s===0?e.toFixed(0):e.toFixed(1)} ${t[s]}`}const U=new T;d.PageOpsSDK=U,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})}));
package/dist/types.d.ts CHANGED
@@ -2,6 +2,7 @@ export interface PageOpsContext {
2
2
  route?: string;
3
3
  url?: string;
4
4
  title?: string;
5
+ menuPath?: string[];
5
6
  tenantId?: string;
6
7
  userRole?: string;
7
8
  buildVersion?: string;
@@ -20,6 +21,7 @@ export interface ContextSession {
20
21
  route?: string;
21
22
  url?: string;
22
23
  title?: string;
24
+ menu_path?: string[];
23
25
  tenant_id?: string;
24
26
  user_role?: string;
25
27
  build_version?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pageops/sdk",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "PageOps embeddable frontend SDK",
5
5
  "type": "module",
6
6
  "main": "dist/pageops-sdk.umd.cjs",